123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857 |
- #
- # 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.
- <br/>
- 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.<br/><br/>
- Important behaviour of this control is that there is always a
- blank row at the end, in which the user can enter data.<br/>
- Once the row is not blank (thus, the user entered data...),
- a new blank row is added.<br/>
- 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.<br/><br/>
- The control shows 5 rows at a time.<br/>
- 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.
- <br/>
- The following other functionality is implemented:
- <br/>
- 0. synchronizing data between controls, data model and live preview.
- 1. Tab scrolling.<br/>
- 2. Keyboard scrolling.<br/>
- 3. Removing rows and adding new rows.<br/>
- 4. Moving rows up and down. <br/>
- <br/>
- This control relays on the ControlScroller control which uses the following
- Data model:<br/>
- 1. It uses a vector, whose members are arrays of PropertyValue.<br/>
- 2. Each array represents a row.<br/>
- (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:<br/>
- 3. a. the Value of the property is used for as value
- of the controls (usually text).<br/>
- 3. b. the Name of the property is used to map values
- to UI controls in the following manner:<br/>
- 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).<br/>
- 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. <br/>
- 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. <br/>
- also when deleting or inserting rows, attention should be paid that no rows
- should be removed or inserted. Instead, only the Values should rotate. <br/><br/>
- 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)
|