From ed5640d8b587fbcfed7dd7967f3de04b37a76f26 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 11:06:44 +0200 Subject: Adding upstream version 4:7.4.7. Signed-off-by: Daniel Baumann --- .../com/sun/star/wizards/agenda/TopicsControl.py | 857 +++++++++++++++++++++ 1 file changed, 857 insertions(+) create mode 100644 wizards/com/sun/star/wizards/agenda/TopicsControl.py (limited to 'wizards/com/sun/star/wizards/agenda/TopicsControl.py') diff --git a/wizards/com/sun/star/wizards/agenda/TopicsControl.py b/wizards/com/sun/star/wizards/agenda/TopicsControl.py new file mode 100644 index 000000000..6e269f6bf --- /dev/null +++ b/wizards/com/sun/star/wizards/agenda/TopicsControl.py @@ -0,0 +1,857 @@ +# +# This file is part of the LibreOffice project. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# This file incorporates work covered by the following license notice: +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed +# with this work for additional information regarding copyright +# ownership. The ASF licenses this file to you under the Apache +# License, Version 2.0 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.apache.org/licenses/LICENSE-2.0 . +# +import uno +from ..ui.ControlScroller import ControlScroller, PropertyNames, traceback, \ + HelpIds +from .AgendaWizardDialogConst import HID +from ..common.Properties import Properties +from ..ui.event.CommonListener import FocusListenerProcAdapter, \ + KeyListenerProcAdapter + +from com.sun.star.awt.Key import DOWN, UP, TAB +from com.sun.star.awt.KeyModifier import SHIFT, MOD1 + +''' +This class implements the UI functionality of the topics scroller control. +
+During development, there has been a few changes which were not *fully* done +mainly in converting the topics and time boxes +from combobox and time box to normal textboxes, +so in the code they might be referenced as combobox or timebox. This should be +rather understood as topicstextbox and timetextbox.

+Important behaviour of this control is that there is always a +blank row at the end, in which the user can enter data.
+Once the row is not blank (thus, the user entered data...), +a new blank row is added.
+Once the user removes the last *unempty* row, binsertRowy deleting its data, it becomes +the *last empty row* and the one after is being automatically removed.

+The control shows 5 rows at a time.
+If, for example, only 2 rows exist (from which the 2ed one is empty...) +then the other three rows, which do not exist in the data model, are disabled. +
+The following other functionality is implemented: +
+0. synchronizing data between controls, data model and live preview. +1. Tab scrolling.
+2. Keyboard scrolling.
+3. Removing rows and adding new rows.
+4. Moving rows up and down.
+
+This control relays on the ControlScroller control which uses the following +Data model:
+1. It uses a vector, whose members are arrays of PropertyValue.
+2. Each array represents a row.
+(Note: the Name and Value members of the PropertyValue object are being used) +3. Each property Value represents a value +for a single control with the following rules:
+3. a. the Value of the property is used for as value +of the controls (usually text).
+3. b. the Name of the property is used to map values +to UI controls in the following manner:
+3. b. 1. only the Name of the first X Rows is regarded, +where X is the number of visible rows (in the ainsertRowgenda wizard this would be 5, +since 5 topic rows are visible on the dialog).
+3. b. 2. The Names of the first X (or 5...) rows are the names +of the UI Controls to hold values. When the control scroller scrolls, +it looks at the first 5 rows and uses the names specified there to map the +current values to the specified controls.
+This data model makes the following limitations on the implementation: +When moving rows, only the values should be moved. The Rows objects, +which contain also the Names of the controls should not be switched.
+also when deleting or inserting rows, attention should be paid that no rows +should be removed or inserted. Instead, only the Values should rotate.

+To save the topics in the registry a ConfigSet of objects of type CGTopic is +being used. +This one is not synchronized "live", since it is unnecessary... instead, it is +synchronized on call, before the settings should be saved. +''' + +class TopicsControl(ControlScroller): + + LABEL = "lblTopicCnt_" + TOPIC = "txtTopicTopic_" + RESP = "cbTopicResp_" + TIME = "txtTopicTime_" + LABEL_PROPS = (PropertyNames.PROPERTY_HEIGHT, PropertyNames.PROPERTY_LABEL, + PropertyNames.PROPERTY_POSITION_X, PropertyNames.PROPERTY_POSITION_Y, + PropertyNames.PROPERTY_STEP, PropertyNames.PROPERTY_TABINDEX, + PropertyNames.PROPERTY_WIDTH) + TEXT_PROPS = (PropertyNames.PROPERTY_HEIGHT, PropertyNames.PROPERTY_HELPURL, + PropertyNames.PROPERTY_POSITION_X, PropertyNames.PROPERTY_POSITION_Y, + PropertyNames.PROPERTY_STEP, PropertyNames.PROPERTY_TABINDEX, + PropertyNames.PROPERTY_WIDTH) + + def __init__(self, dialog, xmsf, agenda): + try: + super(TopicsControl, self).__init__( + dialog, xmsf, 5, 92, 38, 212, 5, 18, HID + 32) + self.dialog = dialog + #fill preview's table + self.initializeScrollFields(agenda) + #fill gui's table + self.fillupControls(True) + self.nscrollvalue = 0 + self.lastFocusRow = 0 + self.lastFocusControl = None + # set some focus listeners for TAB scroll down and up... + # prepare scroll down on tab press... + self.lastTime = \ + self.ControlGroupVector[self.nblockincrement - 1].timebox + + self.lastTime.addKeyListener(KeyListenerProcAdapter( + self.lastControlKeyPressed)) + #prepare scroll up on tab press... + self.firstTopic = self.ControlGroupVector[0].textbox + self.firstTopic.addKeyListener(KeyListenerProcAdapter( + self.firstControlKeyPressed)) + self.enableButtons() + except Exception: + traceback.print_exc() + + ''' + initializes the data of the control. + ''' + + def initializeScrollFields(self, agenda): + # create a row for each topic with the given values... + for index,item in enumerate(agenda.cp_Topics.childrenList): + row = self.newRow(index) + item.setDataToRow(row) + # a parent class method + self.registerControlGroup(row, index) + self.updateDocumentRow(index) + # inserts a blank row at the end... + self.insertRowAtEnd() + + ''' + Insert a blank (empty) row + as last row of the control. + The control has always a blank row at the + end, which enables the user to enter data... + ''' + + def insertRowAtEnd(self): + l = len(self.scrollfields) + self.registerControlGroup(self.newRow(l), l) + self.setTotalFieldCount(l + 1) + # if the new row is visible, it must have been disabled + # so it should be now enabled... + if l - self.nscrollvalue < self.nblockincrement: + self.ControlGroupVector[l - self.nscrollvalue].\ + setEnabled(True) + + def saveTopics(self, agenda): + # last row is always empty + agenda.cp_Topics.childrenList = self.scrollfields[:-1] + + ''' + remove the last row + ''' + + def removeLastRow(self): + l = len(self.scrollfields) + # if we should scroll up... + if (l - self.nscrollvalue) >= 1 \ + and (l - self.nscrollvalue) <= self.nblockincrement \ + and self.nscrollvalue > 0: + while (l - self.nscrollvalue >= 1) \ + and l - self.nscrollvalue <= self.nblockincrement \ + and self.nscrollvalue > 0: + self.setScrollValue(self.nscrollvalue - 1) + # if we should disable a row... + elif self.nscrollvalue == 0 and l - 1 < self.nblockincrement: + self.ControlGroupVector[l - 1].setEnabled(False) + + self.unregisterControlGroup(l - 1) + self.setTotalFieldCount(l - 1) + + ''' + in order to use the "move up", "down" "insert" and "remove" buttons, + we track the last control the gained focus, in order to know which + row should be handled. + @param fe + ''' + + def focusGained(self, fe): + xc = fe.Source + self.focusGained2(xc) + + ''' + Sometimes I set the focus programmatically to a control + (for example when moving a row up or down, the focus should move + with it). + In such cases, no VCL event is being triggered so it must + be called programmatically. + This is done by this method. + @param control + ''' + + def focusGained2(self, control): + try: + #calculate in which row we are... + name = control.Model.Name + num = name[name.index("_") + 1:] + self.lastFocusRow = int(num) + self.nscrollvalue + self.lastFocusControl = control + # enable/disable the buttons... + self.enableButtons() + except Exception: + traceback.print_exc() + + ''' + enable or disable the buttons according to the + current row we are in. + ''' + + def enableButtons(self): + self.CurUnoDialog.btnInsert.Model.Enabled = \ + self.lastFocusRow < len(self.scrollfields) + self.CurUnoDialog.btnRemove.Model.Enabled = \ + self.lastFocusRow < len(self.scrollfields) - 1 + if self.lastFocusControl is not None: + self.CurUnoDialog.btnUp.Model.Enabled = self.lastFocusRow > 0 + self.CurUnoDialog.btnDown.Model.Enabled = \ + self.lastFocusRow < len(self.scrollfields) - 1 + else: + self.CurUnoDialog.btnUp.Model.Enabled = False + self.CurUnoDialog.btnDown.Model.Enabled = False + + ''' + Removes the current row. + See general class documentation explanation about the + data model used and the limitations which explain the implementation here. + ''' + + def removeRow(self): + try: + for i in range(self.lastFocusRow, + len(self.scrollfields) - 1): + pv1 = self.scrollfields[i] + pv2 = self.scrollfields[i + 1] + pv1[1].Value = pv2[1].Value + pv1[2].Value = pv2[2].Value + pv1[3].Value = pv2[3].Value + self.updateDocumentRow(i) + if i - self.nscrollvalue < self.nblockincrement: + self.fillupControl(i - self.nscrollvalue) + + self.removeLastRow() + # update the live preview background document + self.reduceDocumentToTopics() + self.enableButtons() + if self.lastFocusControl is not None: + # the focus should return to the edit control + self.focus(self.lastFocusControl) + except Exception: + traceback.print_exc() + + ''' + Inserts a row before the current row. + See general class documentation explanation about the + data model used and the limitations which explain the implementation here. + ''' + + def insertRow(self): + try: + self.insertRowAtEnd() + for i in range(len(self.scrollfields) - 2, + self.lastFocusRow, -1): + pv1 = self.scrollfields[i] + pv2 = self.scrollfields[i - 1] + pv1[1].Value = pv2[1].Value + pv1[2].Value = pv2[2].Value + pv1[3].Value = pv2[3].Value + self.updateDocumentRow(i) + if i - self.nscrollvalue < self.nblockincrement: + self.fillupControl(i - self.nscrollvalue) + + # after rotating all the properties from this row on, + # we clear the row, so it is practically a new one... + pv1 = self.scrollfields[self.lastFocusRow] + pv1[1].Value = "" + pv1[2].Value = "" + pv1[3].Value = "" + # update the preview document. + self.updateDocumentRow(self.lastFocusRow) + self.fillupControl( + self.lastFocusRow - self.nscrollvalue) + self.enableButtons() + + if self.lastFocusControl is not None: + self.focus(self.lastFocusControl) + except Exception: + traceback.print_exc() + + ''' + create a new row with the given index. + The index is important because it is used in the + Name member of the PropertyValue objects. + To know why see general class documentation above (data model explanation) + @param i the index of the new row + @return + ''' + + def newRow(self, i): + pv = list(range(4)) + pv[0] = Properties.createProperty( + TopicsControl.LABEL + str(i), "" + str(i + 1) + ".") + pv[1] = Properties.createProperty(TopicsControl.TOPIC + str(i), "") + pv[2] = Properties.createProperty(TopicsControl.RESP + str(i), "") + pv[3] = Properties.createProperty(TopicsControl.TIME + str(i), "") + return pv + + ''' + Implementation of ControlScroller + This is a UI method which inserts a new row to the control. + It uses the child-class ControlRow. (see below). + ''' + + def insertControlGroup(self, _index, npos): + oControlRow = ControlRow( + self.CurUnoDialog, self.iCompPosX, npos, _index, + ControlRow.tabIndex, self) + self.ControlGroupVector.append(oControlRow) + ControlRow.tabIndex += 4 + + ''' + Checks if a row is empty. + This is used when the last row is changed. + If it is empty, the next row (which is always blank) is removed. + If it is not empty, a next row must exist. + @param row the index number of the row to check. + @return true if empty. false if not. + ''' + + def isRowEmpty(self, row): + data = self.getTopicData(row) + # now - is this row empty? + return not data[1].Value and not data[2].Value and not data[3].Value + + ''' + update the preview document and + remove/insert rows if needed. + @param guiRow + @param column + ''' + + def fieldChanged(self, guiRow, column): + try: + # First, I update the document + data = self.getTopicData(guiRow + self.nscrollvalue) + if data is None: + return + self.updateDocumentCell( + guiRow + self.nscrollvalue, column, data) + if self.isRowEmpty(guiRow + self.nscrollvalue): + ''' + if this is the row before the last one + (the last row is always empty) + delete the last row... + ''' + if (guiRow + self.nscrollvalue) \ + == len(self.scrollfields) - 2: + self.removeLastRow() + '''now consequently check the last two rows, + and remove the last one if they are both empty. + (actually I check always the "before last" row, + because the last one is always empty... + ''' + while len(self.scrollfields) > 1 \ + and self.isRowEmpty( + len(self.scrollfields) - 2): + self.removeLastRow() + cr = self.ControlGroupVector[ + len(self.scrollfields) - \ + self.nscrollvalue - 1] + # if a remove was performed, set focus + #to the last row with some data in it... + self.focus(self.getControlByIndex(cr, column)) + # update the preview document. + self.reduceDocumentToTopics() + else: + # row contains data + # is this the last row? + if (guiRow + self.nscrollvalue + 1) \ + == len(self.scrollfields): + self.insertRowAtEnd() + + except Exception: + traceback.print_exc() + + ''' + return the corresponding row data for the given index. + @param topic index of the topic to get. + @return a PropertyValue array with the data for the given topic. + ''' + + def getTopicData(self, topic): + if topic < len(self.scrollfields): + return self.scrollfields[topic] + else: + return None + + ''' + If the user presses tab on the last control, and + there *are* more rows in the model, scroll down. + @param event + ''' + + def lastControlKeyPressed(self, event): + # if tab without shift was pressed... + try: + if event.KeyCode == TAB and event.Modifiers == 0: + # if there is another row... + if (self.nblockincrement + self.nscrollvalue) \ + < len(self.scrollfields): + self.setScrollValue(self.nscrollvalue + 1) + self.focus(self.getControlByIndex(self.ControlGroupVector[4], 1)) + except Exception: + traceback.print_exc() + + ''' + If the user presses shift-tab on the first control, and + there *are* more rows in the model, scroll up. + @param event + ''' + + def firstControlKeyPressed(self, event): + # if tab with shift was pressed... + if (event.KeyCode == TAB) and \ + (event.Modifiers == SHIFT): + if self.nscrollvalue > 0: + self.setScrollValue(self.nscrollvalue - 1) + self.focus(self.lastTime) + + ''' + sets focus to the given control. + @param textControl + ''' + + def focus(self, textControl): + textControl.setFocus() + text = textControl.Text + textControl.Selection = uno.createUnoStruct( \ + 'com.sun.star.awt.Selection', 0, len(text)) + self.focusGained2(textControl) + + ''' + moves the given row one row down. + @param guiRow the gui index of the row to move. + @param control the control to gain focus after moving. + ''' + + def rowDown(self, guiRow=None, control=None): + try: + if guiRow is None: + guiRow = self.lastFocusRow - self.nscrollvalue + if control is None: + control = self.lastFocusControl + # only perform if this is not the last row. + actuallRow = guiRow + self.nscrollvalue + if actuallRow + 1 < len(self.scrollfields): + # get the current selection + selection = control.Selection + # the last row should scroll... + scroll = (guiRow == self.nblockincrement - 1) + if scroll: + self.setScrollValue(self.nscrollvalue + 1) + + scroll1 = self.nscrollvalue + if scroll: + aux = -1 + else: + aux = 1 + self.switchRows(guiRow, guiRow + aux) + if self.nscrollvalue != scroll1: + guiRow += (self.nscrollvalue - scroll1) + + self.setSelection(guiRow + (not scroll), control, selection) + except Exception: + traceback.print_exc() + + ''' + move the current row up + ''' + + def rowUp(self, guiRow=None, control=None): + try: + if guiRow is None: + guiRow = self.lastFocusRow - self.nscrollvalue + if control is None: + control = self.lastFocusControl + # only perform if this is not the first row + actuallRow = guiRow + self.nscrollvalue + if actuallRow > 0: + # get the current selection + selection = control.Selection + # the last row should scroll... + scroll = (guiRow == 0) + if scroll: + self.setScrollValue(self.nscrollvalue - 1) + if scroll: + aux = 1 + else: + aux = -1 + self.switchRows(guiRow, guiRow + aux) + self.setSelection(guiRow - (not scroll), control, selection) + except Exception: + traceback.print_exc() + + ''' + moves the cursor up. + @param guiRow + @param control + ''' + + def cursorUp(self, guiRow, control): + # is this the last full row ? + actuallRow = guiRow + self.nscrollvalue + #if this is the first row + if actuallRow == 0: + return + # the first row should scroll... + + scroll = (guiRow == 0) + if scroll: + self.setScrollValue(self.nscrollvalue - 1) + upperRow = self.ControlGroupVector[guiRow] + else: + upperRow = self.ControlGroupVector[guiRow - 1] + + self.focus(self.getControl(upperRow, control)) + + ''' + moves the cursor down + @param guiRow + @param control + ''' + + def cursorDown(self, guiRow, control): + # is this the last full row ? + actuallRow = guiRow + self.nscrollvalue + #if this is the last row, exit + if actuallRow == len(self.scrollfields) - 1: + return + # the first row should scroll... + + scroll = (guiRow == self.nblockincrement - 1) + if scroll: + self.setScrollValue(self.nscrollvalue + 1) + lowerRow = self.ControlGroupVector[guiRow] + else: + # if we scrolled we are done... + #otherwise... + lowerRow = self.ControlGroupVector[guiRow + 1] + + self.focus(self.getControl(lowerRow, control)) + + ''' + changes the values of the given rows with each other + @param row1 one can figure out what this parameter is... + @param row2 one can figure out what this parameter is... + ''' + + def switchRows(self, row1, row2): + o1 = self.scrollfields[row1 + self.nscrollvalue] + o2 = self.scrollfields[row2 + self.nscrollvalue] + temp = None + for i in range(1, len(o1)): + temp = o1[i].Value + o1[i].Value = o2[i].Value + o2[i].Value = temp + self.fillupControl(row1) + self.fillupControl(row2) + self.updateDocumentRow(row1 + self.nscrollvalue, o1) + self.updateDocumentRow(row2 + self.nscrollvalue, o2) + + ''' + if we changed the last row, add another one... + ''' + if (row1 + self.nscrollvalue + 1 == \ + len(self.scrollfields)) \ + or (row2 + self.nscrollvalue + 1 == \ + len(self.scrollfields)): + + self.insertRowAtEnd() + ''' + if we did not change the last row but + we did change the one before - check if we + have two empty rows at the end. + If so, delete the last one... + ''' + elif (row1 + self.nscrollvalue) + \ + (row2 + self.nscrollvalue) \ + == (len(self.scrollfields) * 2 - 5): + if self.isRowEmpty(len(self.scrollfields) - 2) \ + and self.isRowEmpty( + len(self.scrollfields) - 1): + self.removeLastRow() + self.reduceDocumentToTopics() + + ''' + sets a text selection to a given control. + This is used when one moves a row up or down. + After moving row X to X+/-1, the selection (or cursor position) of the + last focused control should be restored. + The control's row is the given guiRow. + The control's column is detected according to the given event. + This method is called as subsequent to different events, + thus it is comfortable to use the event here to detect the column, + rather than in the different event methods. + @param guiRow the row of the control to set the selection to. + @param eventSource helps to detect + the control's column to set the selection to. + @param s the selection object to set. + ''' + + def setSelection(self, guiRow, eventSource, s): + cr = self.ControlGroupVector[guiRow] + control = self.getControl(cr, eventSource) + control.setFocus() + control.setSelection(s) + + ''' + returns a control out of the given row, according to a column number. + @param cr control row object. + @param column the column number. + @return the control... + ''' + + def getControlByIndex(self, cr, column): + tmp_switch_var1 = column + if tmp_switch_var1 == 0: + return cr.label + elif tmp_switch_var1 == 1: + return cr.textbox + elif tmp_switch_var1 == 2: + return cr.combobox + elif tmp_switch_var1 == 3: + return cr.timebox + else: + raise Exception("No such column"); + + '''getControl + returns a control out of the given row, which is + in the same column as the given control. + @param cr control row object + @param control a control indicating a column. + @return + ''' + + def getControl(self, cr, control): + column = self.getColumn(control) + return self.getControlByIndex(cr, column) + + ''' + returns the column number of the given control. + @param control + @return + ''' + + def getColumn(self, control): + name = control.Model.Name + if name.startswith(TopicsControl.TOPIC): + return 1 + if name.startswith(TopicsControl.RESP): + return 2 + if name.startswith(TopicsControl.TIME): + return 3 + if name.startswith(TopicsControl.LABEL): + return 0 + return -1 + + ''' + update the given row in the preview document with the given data. + @param row + @param data + ''' + + def updateDocumentRow(self, row, data=None): + if data is None: + data = self.scrollfields[row] + try: + for i in range(len(data)): + self.CurUnoDialog.myAgendaDoc.topics.writeCell( + row, i, data) + except Exception: + traceback.print_exc() + + ''' + updates a single cell in the preview document. + Is called when a single value is changed, since we really + don't have to update the whole row for one small change... + @param row the data row to update (topic number). + @param column the column to update (a gui column, not a document column). + @param data the data of the entire row. + ''' + + def updateDocumentCell(self, row, column, data): + try: + self.CurUnoDialog.myAgendaDoc.topics.writeCell( + row, column, data) + except Exception: + traceback.print_exc() + + ''' + when removing rows, this method updates + the preview document to show the number of rows + according to the data model. + ''' + + def reduceDocumentToTopics(self): + try: + self.CurUnoDialog.myAgendaDoc.topics.reduceDocumentTo( + len(self.scrollfields) - 1) + except Exception: + traceback.print_exc() + +''' +A class represting a single GUI row. +Note that the instance methods of this class +are being called and handle controls of +a single row. +''' + +class ControlRow(object): + + tabIndex = 520 + ''' + constructor. Create the row in the given dialog given coordinates, + with the given offset (row number) and tabindex. + Note that since I use this specifically for the agenda wizard, + the step and all control coordinates inside the + row are constant (5). + ''' + + def __init__(self, dialog, x, y, i, tabindex, topicsControl): + self.offset = i + self.dialog = dialog + self.topicsControl = topicsControl + self.label = self.dialog.insertLabel( + self.topicsControl.LABEL + str(i), + self.topicsControl.LABEL_PROPS, + (8, "" + str(i + 1) + ".", + x + 4, y + 2, self.topicsControl.iStep, tabindex, 10)) + self.textbox = self.dialog.insertTextField( + self.topicsControl.TOPIC + str(i), "topicTextChanged", + self.topicsControl.TEXT_PROPS, + (12, HelpIds.getHelpIdString(self.topicsControl.curHelpIndex + i * 3 + 1), + x + 15, y, self.topicsControl.iStep, tabindex + 1, 84), self) + self.combobox = self.dialog.insertTextField( + self.topicsControl.RESP + str(i), "responsibleTextChanged", + self.topicsControl.TEXT_PROPS, + (12, HelpIds.getHelpIdString(self.topicsControl.curHelpIndex + i * 3 + 2), + x + 103, y, self.topicsControl.iStep, tabindex + 2, 68), self) + self.timebox = self.dialog.insertTextField( + self.topicsControl.TIME + str(i), "timeTextChanged", + self.topicsControl.TEXT_PROPS, + (12, HelpIds.getHelpIdString(self.topicsControl.curHelpIndex + i * 3 + 3), + x + 175, y, self.topicsControl.iStep, tabindex + 3, 20), self) + self.setEnabled(False) + self.textbox.addKeyListener(KeyListenerProcAdapter(self.keyPressed)) + self.combobox.addKeyListener(KeyListenerProcAdapter(self.keyPressed)) + self.timebox.addKeyListener(KeyListenerProcAdapter(self.keyPressed)) + self.textbox.addFocusListener(FocusListenerProcAdapter( + self.topicsControl.focusGained)) + self.combobox.addFocusListener(FocusListenerProcAdapter( + self.topicsControl.focusGained)) + self.timebox.addFocusListener(FocusListenerProcAdapter( + self.topicsControl.focusGained)) + + def topicTextChanged(self): + try: + # update the data model + self.topicsControl.fieldInfo(self.offset, 1) + # update the preview document + self.topicsControl.fieldChanged(self.offset, 1) + except Exception: + traceback.print_exc() + + ''' + called through an event listener when the + responsible text is changed by the user. + updates the data model and the preview document. + ''' + + def responsibleTextChanged(self): + try: + # update the data model + self.topicsControl.fieldInfo(self.offset, 2) + # update the preview document + self.topicsControl.fieldChanged(self.offset, 2) + except Exception: + traceback.print_exc() + + ''' + called through an event listener when the + time text is changed by the user. + updates the data model and the preview document. + ''' + + def timeTextChanged(self): + try: + # update the data model + self.topicsControl.fieldInfo(self.offset, 3) + # update the preview document + self.topicsControl.fieldChanged(self.offset, 3) + except Exception: + traceback.print_exc() + + ''' + enables/disables the row. + @param enabled true for enable, false for disable. + ''' + + def setEnabled(self, enabled): + self.label.Model.Enabled = enabled + self.textbox.Model.Enabled = enabled + self.combobox.Model.Enabled = enabled + self.timebox.Model.Enabled = enabled + + ''' + Implementation of XKeyListener. + Optionally performs the one of the following: + cursor up, or down, row up or down + ''' + + def keyPressed(self, event): + try: + if self.isMoveDown(event): + self.topicsControl.rowDown(self.offset, event.Source) + elif self.isMoveUp(event): + self.topicsControl.rowUp(self.offset, event.Source) + elif self.isDown(event): + self.topicsControl.cursorDown(self.offset, event.Source) + elif self.isUp(event): + self.topicsControl.cursorUp(self.offset, event.Source) + + self.topicsControl.enableButtons() + except Exception: + traceback.print_exc() + + def isMoveDown(self, e): + return (e.KeyCode == DOWN) and (e.Modifiers == MOD1) + + def isMoveUp(self, e): + return (e.KeyCode == UP) and (e.Modifiers == MOD1) + + def isDown(self, e): + return (e.KeyCode == DOWN) and (e.Modifiers == 0) + + def isUp(self, e): + return (e.KeyCode == UP) and (e.Modifiers == 0) -- cgit v1.2.3