Changeset 5972
- Timestamp:
- 09/01/2010 05:15:43 AM (1 year ago)
- Files:
-
- trunk/dabo/ui/uiwx/dDialog.py (modified) (20 diffs)
- trunk/dabo/ui/uiwx/dForm.py (modified) (46 diffs)
- trunk/dabo/ui/uiwx/dFormMain.py (modified) (3 diffs)
- trunk/dabo/ui/uiwx/dFormMixin.py (modified) (56 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/dabo/ui/uiwx/dDialog.py
r5968 r5972 37 37 38 38 preClass = wx.PreDialog 39 fm.dFormMixin.__init__(self, preClass, parent, properties=properties, 39 fm.dFormMixin.__init__(self, preClass, parent, properties=properties, 40 40 *args, **kwargs) 41 41 … … 76 76 def showModal(self): 77 77 """Show the dialog modally.""" 78 ## pkm: We had to override this, because the default in dPemMixin doesn't 78 ## pkm: We had to override this, because the default in dPemMixin doesn't 79 79 ## actually result in a modal dialog. 80 80 self.Modal = True … … 97 97 def show(self): 98 98 # Call _afterShow() once immediately, and then once after the dialog is visible, which 99 # will correct minor mistakes such as the height of wordwrapped labels not being 99 # will correct minor mistakes such as the height of wordwrapped labels not being 100 100 # accounted for. If we only called it after the dialog was already shown, then we 101 101 # risk the dialog being too jumpy. … … 106 106 return {wx.ID_OK: kons.DLG_OK, wx.ID_CANCEL: kons.DLG_CANCEL}.get(ret, ret) 107 107 return self.Show(True) 108 108 109 109 110 110 111 111 def _addControls(self): 112 """Any controls that need to be added to the dialog 112 """Any controls that need to be added to the dialog 113 113 can be added in this method in framework classes, or 114 114 in addControls() in instances. … … 190 190 def _setModal(self, val): 191 191 self._modal = val 192 192 193 193 194 194 def _getShowStat(self): … … 202 202 203 203 Borderless = property(_getBorderless, _setBorderless, None, 204 _("""Must be passed at construction time. When set to True, the dialog displays 204 _("""Must be passed at construction time. When set to True, the dialog displays 205 205 without a title bar or borders (bool)""")) 206 206 … … 213 213 Modal = property(_getModal, _setModal, None, 214 214 _("Determines if the dialog is shown modal (default) or modeless. (bool)")) 215 215 216 216 217 217 DynamicAutoSize = makeDynamicProperty(AutoSize) … … 222 222 223 223 class dStandardButtonDialog(dDialog): 224 """Creates a dialog with standard buttons and associated functionality. You can 225 choose the buttons that display by passing True for any of the following 224 """Creates a dialog with standard buttons and associated functionality. You can 225 choose the buttons that display by passing True for any of the following 226 226 properties: 227 227 228 228 OK 229 229 Cancel … … 235 235 you must specify them all; in other words, OK is only assumed if nothing is specified. 236 236 Then add your custom controls in the addControls() hook method, and respond to 237 the pressing of the standard buttons in the run*() handlers, where * is the name of the 238 associated property (e.g., runOK(), runOo(), etc.). You can query the Accepted property 239 to find out if the user pressed "OK" or "Yes"; if neither of these was pressed, 237 the pressing of the standard buttons in the run*() handlers, where * is the name of the 238 associated property (e.g., runOK(), runOo(), etc.). You can query the Accepted property 239 to find out if the user pressed "OK" or "Yes"; if neither of these was pressed, 240 240 Accepted will be False. 241 241 """ … … 271 271 no = self._no 272 272 help = self._help 273 if (ok is None and cancel is None and yes is None and 273 if (ok is None and cancel is None and yes is None and 274 274 no is None and help is None): 275 275 ok = True 276 276 277 277 flags = 0 278 278 if ok: … … 333 333 # Force the escape button to be set appropriately: 334 334 self.CancelOnEscape = self.CancelOnEscape 335 335 336 336 # Wx rearranges the order of the buttons per platform conventions, but 337 337 # doesn't rearrange the tab order for us. So, we do it manually: … … 376 376 377 377 ################################################ 378 # Handlers for the standard buttons. 378 # Handlers for the standard buttons. 379 379 ################################################ 380 # Note that onOK() and 381 # onCancel() are the names of the old event handlers, and 380 # Note that onOK() and 381 # onCancel() are the names of the old event handlers, and 382 382 # code has been written to use these. So as not to break this 383 383 # older code, we issue a deprecation warning and call the … … 388 388 self.onOK() 389 389 except TypeError: 390 warnings.warn(_("The onOK() handler is deprecated. Use the runOK() method instead"), 390 warnings.warn(_("The onOK() handler is deprecated. Use the runOK() method instead"), 391 391 Warning) 392 392 self.onOK(None) … … 402 402 self.onCancel() 403 403 except TypeError: 404 warnings.warn(_("The onCancel() handler is deprecated. Use the runCancel() method instead"), 404 warnings.warn(_("The onCancel() handler is deprecated. Use the runCancel() method instead"), 405 405 Warning) 406 406 self.onCancel(None) … … 408 408 # New code should not have onCancel 409 409 pass 410 410 411 411 if self.runCancel() is not False: 412 412 self.EndModal(kons.DLG_CANCEL) … … 436 436 ################################################ 437 437 438 438 439 439 def addControls(self): 440 """Use this method to add controls to the dialog. The standard buttons will be added 440 """Use this method to add controls to the dialog. The standard buttons will be added 441 441 after this method runs, so that they appear at the bottom of the dialog. 442 442 """ 443 443 pass 444 445 444 445 446 446 def addControlSequence(self, seq): 447 """This takes a sequence of 3-tuples or 3-lists, and adds controls 447 """This takes a sequence of 3-tuples or 3-lists, and adds controls 448 448 to the dialog as a grid of labels and data controls. The first element of 449 449 the list/tuple is the prompt, the second is the data type, and the third … … 470 470 self.Sizer.insert(self.LastPositionInSizer, gs, "x") 471 471 self.layout() 472 473 472 473 474 474 def _getAccepted(self): 475 return self._accepted 475 return self._accepted 476 476 477 477 def _setAccepted(self, val): 478 478 self._accepted = val 479 480 479 480 481 481 def _getButtonSizer(self): 482 482 return getattr(self, "stdButtonSizer", None) … … 509 509 def _getHelpButton(self): 510 510 return self.btnHelp 511 511 512 512 513 513 def _getOKButton(self): 514 514 return self.btnOK 515 515 516 516 517 517 def _getNoButton(self): 518 518 return self.btnNo 519 519 520 520 521 521 def _getYesButton(self): 522 522 return self.btnYes 523 523 524 524 525 525 Accepted = property(_getAccepted, _setAccepted, None, … … 534 534 CancelButton = property(_getCancelButton, None, None, 535 535 _("Reference to the Cancel button on the form, if present (dButton or None).")) 536 536 537 537 CancelOnEscape = property(_getCancelOnEscape, _setCancelOnEscape, None, 538 _("""When True (default), pressing the Escape key will perform the same action 539 as clicking the Cancel button. If no Cancel button is present but there is a No button, 540 the No behavior will be executed. If neither button is present, the default button's 538 _("""When True (default), pressing the Escape key will perform the same action 539 as clicking the Cancel button. If no Cancel button is present but there is a No button, 540 the No behavior will be executed. If neither button is present, the default button's 541 541 action will be executed (bool)""")) 542 542 543 543 HelpButton = property(_getHelpButton, None, None, 544 544 _("Reference to the Help button on the form, if present (dButton or None).")) 545 545 546 546 NoButton = property(_getNoButton, None, None, 547 547 _("Reference to the No button on the form, if present (dButton or None).")) 548 548 549 549 OKButton = property(_getOKButton, None, None, 550 550 _("Reference to the OK button on the form, if present (dButton or None).")) 551 551 552 552 YesButton = property(_getYesButton, None, None, 553 553 _("Reference to the Yes button on the form, if present (dButton or None).")) 554 555 554 555 556 556 557 557 class dOkCancelDialog(dStandardButtonDialog): … … 606 606 self.Bottom = min(self.Bottom, maxH-5) 607 607 super(_FloatDialog, self).show() 608 608 609 609 610 610 def _getAbove(self): trunk/dabo/ui/uiwx/dForm.py
r5971 r5972 18 18 """Creates a bizobj-aware form. 19 19 20 dForm knows how to handle one or more dBizobjs, providing proxy methods 20 dForm knows how to handle one or more dBizobjs, providing proxy methods 21 21 like next(), last(), save(), and requery(). 22 22 """ … … 24 24 self.bizobjs = {} 25 25 self._primaryBizobj = None 26 26 27 27 # If this is True, a panel will be automatically added to the 28 28 # form and sized to fill the form. … … 33 33 # else: 34 34 # self.mkPanel = self._extractKey((kwargs, properties), "panel", False) 35 35 36 36 # Use this for timing queries and other long- 37 37 # running events … … 42 42 # or a requery is about to happen. 43 43 self._checkForChanges = True 44 44 45 45 fm.dFormMixin.__init__(self, preClass, parent, properties, attProperties, *args, **kwargs) 46 46 … … 49 49 # # applied at that point. 50 50 # self.mainPanel.BackColor = self.BackColor 51 51 52 52 # Used to override some cases where the status 53 53 # text should be displayed despite other processes … … 61 61 if "UseSizers" in props and not hasattr(self, "UseSizers"): 62 62 del props["UseSizers"] 63 64 63 64 65 65 def _afterInit(self): 66 66 self.Sizer = dabo.ui.dSizer("vertical") … … 73 73 if self.RequeryOnLoad: 74 74 dabo.ui.callAfter(self.requery) 75 76 75 76 77 77 def _beforeClose(self, evt=None): 78 78 """ See if there are any pending changes in the form, if the 79 form is set for checking for this. If everything's OK, call the 79 form is set for checking for this. If everything's OK, call the 80 80 hook method. 81 81 """ … … 87 87 ret = super(BaseForm, self)._beforeClose(evt) 88 88 return ret 89 90 89 90 91 91 def notifyUser(self, msg, title=None, severe=False, exception=None): 92 92 """ Displays an alert messagebox for the user. You can customize … … 105 105 106 106 def update(self, interval=None): 107 """Updates the contained controls with current values from the source. 107 """Updates the contained controls with current values from the source. 108 108 109 109 This method is called repeatedly from many different places during … … 112 112 can change that to suit your app needs by passing a different interval 113 113 in milliseconds. 114 115 Sometimes, though, you want to force immediate execution of the 114 115 Sometimes, though, you want to force immediate execution of the 116 116 update. In these cases, pass an interval of 0 to this method, which 117 117 means don't wait; execute now. … … 125 125 def __update(self): 126 126 super(BaseForm, self).update() 127 128 127 128 129 129 def confirmChanges(self, bizobjs=None): 130 130 """Ask the user if they want to save changes, discard changes, or cancel. … … 132 132 The user will be queried if the form's CheckForChanges property is True, and 133 133 if there are any pending changes on the form's bizobjs as specified in either 134 the 'bizobjs' parameter, or, if no parameter is sent, the return value of 134 the 'bizobjs' parameter, or, if no parameter is sent, the return value of 135 135 getBizobjsToCheck(). 136 136 137 137 If all the above are True, the dialog will be presented. "Yes" will cause 138 all changes to be saved. "No" will discard any changes before proceeding 138 all changes to be saved. "No" will discard any changes before proceeding 139 139 with the operation that caused confirmChanges() to be called in the first 140 140 place (e.g. a requery() or the form being closed). "Cancel" will not save 141 141 any changes, but also cancel the requery or form close. 142 142 143 143 See also: getBizobjsToCheck() method, CheckForChanges property. 144 144 """ … … 153 153 bizList = bizobjs 154 154 changedBizList = [] 155 155 156 156 for biz in bizList: 157 157 if biz and biz.isAnyChanged(): 158 158 changedBizList.append(biz) 159 159 160 160 if changedBizList: 161 161 queryMessage = self.getConfirmChangesQueryMessage(changedBizList) … … 172 172 self.cancel(dataSource=biz.DataSource) 173 173 return True 174 174 175 175 176 176 def getConfirmChangesQueryMessage(self, changedBizList): … … 178 178 179 179 The default is to return "Do you wish to save your changes?". Subclasses 180 can override with whatever message they want, possibly iterating the 180 can override with whatever message they want, possibly iterating the 181 181 changed bizobj list to introspect the exact changes made to construct the 182 182 message. … … 188 188 """Return the list of bizobj's to check for changes during confirmChanges(). 189 189 190 The default behavior is to simply check the primary bizobj, however there 191 may be cases in subclasses where a different bizobj may be checked, or even 192 several. In those cases, override this method and return a list of the 190 The default behavior is to simply check the primary bizobj, however there 191 may be cases in subclasses where a different bizobj may be checked, or even 192 several. In those cases, override this method and return a list of the 193 193 required bizobjs. 194 194 """ 195 195 return (self.PrimaryBizobj, ) 196 197 196 197 198 198 def addBizobj(self, bizobj): 199 199 """ Add a bizobj to this form. 200 200 201 Make the bizobj the form's primary bizobj if it is the first bizobj to 201 Make the bizobj the form's primary bizobj if it is the first bizobj to 202 202 be added. For convenience, return the bizobj to the caller 203 203 """ … … 224 224 # Running in preview or some other non-live mode 225 225 return 226 return self._moveRecordPointer(bizobj.moveToRowNumber, dataSource=bizobj, 226 return self._moveRecordPointer(bizobj.moveToRowNumber, dataSource=bizobj, 227 227 rowNumber=rowNumber) 228 228 … … 261 261 if biz.RowNumber != oldRowNum: 262 262 # Notify listeners that the row number changed: 263 dabo.ui.callAfter(self.raiseEvent, dEvents.RowNumChanged, 263 dabo.ui.callAfter(self.raiseEvent, dEvents.RowNumChanged, 264 264 newRowNumber=biz.RowNumber, oldRowNumber=oldRowNum, 265 265 bizobj=biz) … … 328 328 self._moveRecordPointer(bizobj.next, dataSource) 329 329 self.afterNext() 330 330 331 331 332 332 def filter(self, dataSource=None, fld=None, expr=None, op="="): … … 356 356 return 357 357 self._moveRecordPointer(bizobj.removeFilter, dataSource) 358 358 359 359 360 360 def removeFilters(self, dataSource=None): … … 366 366 return 367 367 self._moveRecordPointer(bizobj.removeFilters, dataSource) 368 368 369 369 370 370 def save(self, dataSource=None): … … 386 386 else: 387 387 bizobj.save() 388 388 389 389 self.setStatusText(_("Changes to %s saved.") % ( 390 390 self.SaveAllRows and "all records" or "current record",)) 391 391 392 392 except dException.ConnectionLostException, e: 393 393 msg = self._connectionLostMsg(ustr(e)) … … 399 399 self.setStatusText(_("Nothing to save!")) 400 400 return True 401 401 402 402 except (dException.BusinessRuleViolation, dException.DBQueryException), e: 403 403 self.setStatusText(_("Save failed.")) … … 410 410 self.refresh() 411 411 return True 412 413 412 413 414 414 def cancel(self, dataSource=None, ignoreNoRecords=None): 415 415 """ Ask the bizobj to cancel its changes. … … 482 482 self.stopWatch.Pause() 483 483 elapsed = round(self.stopWatch.Time()/1000.0, 3) 484 484 485 485 self.update() 486 486 # del busy … … 525 525 self.refresh() 526 526 return ret 527 527 528 528 529 529 def delete(self, dataSource=None, message=None, prompt=True): … … 541 541 542 542 self.activeControlValid() 543 543 544 544 if not bizobj.RowCount > 0: 545 545 # Nothing to delete! 546 546 self.setStatusText(_("Nothing to delete!")) 547 547 return 548 548 549 549 err = self.beforeDelete() 550 550 if err: … … 604 604 self.update() 605 605 self.refresh() 606 606 607 607 608 608 def new(self, dataSource=None): … … 614 614 return 615 615 self.activeControlValid() 616 616 617 617 err = self.beforeNew() 618 618 if err: 619 619 self.notifyUser(err) 620 return 620 return 621 621 622 622 try: 623 623 bizobj.new() 624 624 except dException.dException, e: 625 self.notifyUser(_("Add new record failed with response:\n\n%s") % e, 625 self.notifyUser(_("Add new record failed with response:\n\n%s") % e, 626 626 severe=True, exception=e) 627 627 … … 635 635 self.update() 636 636 self.refresh() 637 637 638 638 639 639 def afterNew(self): pass … … 648 648 """ Set the SQL for the bizobj.""" 649 649 self.getBizobj(dataSource).setSQL(sql) 650 650 651 651 652 652 def _connectionLostMsg(self, err): … … 658 658 659 659 def getBizobj(self, dataSource=None, parentBizobj=None): 660 """ Return the bizobj with the passed dataSource. If no 660 """ Return the bizobj with the passed dataSource. If no 661 661 dataSource is passed, getBizobj() will return the primary bizobj. 662 662 """ 663 663 if not parentBizobj and not dataSource: 664 664 return self.PrimaryBizobj 665 665 666 666 if not parentBizobj and self.bizobjs.has_key(dataSource): 667 667 return self.bizobjs[dataSource] 668 668 669 669 if isinstance(dataSource, dabo.biz.dBizobj): 670 670 return dataSource … … 675 675 # controls 676 676 return self 677 677 678 678 # See if it is the RegID of a registered control 679 679 reg = self.getObjectByRegID(dataSource) … … 702 702 # if we got here, none were found 703 703 return None 704 704 705 705 706 706 def onFirst(self, evt): self.first() … … 770 770 771 771 def validateField(self, ctrl): 772 """Call the bizobj for the control's DataSource. If the control's 773 value is rejected for field validation reasons, a 772 """Call the bizobj for the control's DataSource. If the control's 773 value is rejected for field validation reasons, a 774 774 BusinessRuleViolation exception will be raised, and the form 775 775 can then respond to this. … … 808 808 def onFieldValidationFailed(self, ctrl, ds, df, val, err): 809 809 """Basic handling of field-level validation failure. You should 810 override it with your own code to handle this failure 810 override it with your own code to handle this failure 811 811 appropriately for your application. 812 812 """ … … 814 814 dabo.ui.callAfter(ctrl.setFocus) 815 815 self._fieldValidationControl = ctrl 816 817 816 817 818 818 def onFieldValidationPassed(self, ctrl, ds, df, val): 819 """Basic handling when field-level validation succeeds. 820 You should override it with your own code to handle this event 819 """Basic handling when field-level validation succeeds. 820 You should override it with your own code to handle this event 821 821 appropriately for your application. 822 822 """ 823 823 pass 824 825 824 825 826 826 # Property get/set/del functions follow. 827 827 def _getCheckForChanges(self): 828 828 return self._checkForChanges 829 829 830 830 def _setCheckForChanges(self, value): 831 831 self._checkForChanges = bool(value) 832 832 833 833 834 834 def _getPrimaryBizobj(self): … … 847 847 self._primaryBizobj = bo 848 848 return bo 849 849 850 850 def _setPrimaryBizobj(self, bizOrDataSource): 851 851 if isinstance(bizOrDataSource, dabo.biz.dBizobj): … … 878 878 except AttributeError: 879 879 return True 880 880 881 881 def _setSaveAllRows(self, value): 882 882 self._SaveAllRows = bool(value) … … 884 884 885 885 # Property definitions: 886 CheckForChanges = property(_getCheckForChanges, _setCheckForChanges, None, 886 CheckForChanges = property(_getCheckForChanges, _setCheckForChanges, None, 887 887 _("""Specifies whether the user is prompted to save or discard changes. (bool) 888 888 889 889 If True (the default), when operations such as requery() or the closing 890 890 of the form are about to occur, the user will be presented with a dialog 891 box asking whether to save changes, discard changes, or cancel the 891 box asking whether to save changes, discard changes, or cancel the 892 892 operation that led to the dialog being presented.""") ) 893 893 894 PrimaryBizobj = property(_getPrimaryBizobj, _setPrimaryBizobj, None, 894 PrimaryBizobj = property(_getPrimaryBizobj, _setPrimaryBizobj, None, 895 895 _("Reference to the primary bizobj for this form (dBizobj)") ) 896 896 897 897 RequeryOnLoad = property(_getRequeryOnLoad, _setRequeryOnLoad, None, 898 _("""Specifies whether an automatic requery happens when the 898 _("""Specifies whether an automatic requery happens when the 899 899 form is loaded. (bool)""")) 900 900 901 SaveAllRows = property(_getSaveAllRows, _setSaveAllRows, None, 901 SaveAllRows = property(_getSaveAllRows, _setSaveAllRows, None, 902 902 _("Specifies whether dataset is row- or table-buffered. (bool)") ) 903 903 … … 955 955 def _getVisible(self): 956 956 return self.IsShown() 957 957 958 958 def _setVisible(self, val): 959 959 if self._constructed(): … … 984 984 _("Specifies whether the form is shown or hidden. (bool)") ) 985 985 986 986 987 987 988 988 class dToolForm(BaseForm, wx.MiniFrame): … … 993 993 style = kwargs.get("style", 0) 994 994 kwargs["style"] = style | wx.RESIZE_BORDER | wx.CAPTION | wx.MINIMIZE_BOX | \ 995 wx.MAXIMIZE_BOX | wx.CLOSE_BOX 995 wx.MAXIMIZE_BOX | wx.CLOSE_BOX 996 996 kwargs["TinyTitleBar"] = True 997 997 kwargs["ShowStatusBar"] = False … … 1015 1015 preClass = wx.PreFrame 1016 1016 BaseForm.__init__(self, preClass, parent, properties, attProperties, *args, **kwargs) 1017 1017 1018 1018 def Show(self, show=True, *args, **kwargs): 1019 1019 self._gtk_show_fix(show) … … 1028 1028 def onDeactivate(self, evt): 1029 1029 print _("Deactivate") 1030 1030 1031 1031 class _dBorderlessForm_test(dBorderlessForm): 1032 1032 def afterInit(self): … … 1036 1036 self.btn.bindEvent(dEvents.Hit, self.close) 1037 1037 dabo.ui.callAfter(self.setSize) 1038 1038 1039 1039 def setSize(self): 1040 1040 self.Width, self.Height = self.btn.Width+60, self.btn.Height+60 1041 1041 self.layout() 1042 1042 self.Centered = True 1043 1044 1045 1043 1044 1045 1046 1046 if __name__ == "__main__": 1047 1047 import test trunk/dabo/ui/uiwx/dFormMain.py
r5050 r5972 13 13 def __init__(self, preClass, parent=None, properties=None, *args, **kwargs): 14 14 fm.dFormMixin.__init__(self, preClass, parent, properties, *args, **kwargs) 15 15 16 16 17 17 def _beforeClose(self, evt=None): … … 21 21 frm = forms2close[0] 22 22 # This will allow forms to veto closing (i.e., user doesn't 23 # want to save pending changes). 23 # want to save pending changes). 24 24 if frm.close() == False: 25 25 # The form stopped the closing process. The user 26 # must deal with this form (save changes, etc.) 26 # must deal with this form (save changes, etc.) 27 27 # before the app can exit. 28 28 frm.bringToFront() … … 31 31 forms2close.remove(frm) 32 32 33 33 34 34 35 35 trunk/dabo/ui/uiwx/dFormMixin.py
r5970 r5972 17 17 18 18 class dFormMixin(pm.dPemMixin): 19 def __init__(self, preClass, parent=None, properties=None, attProperties=None, 19 def __init__(self, preClass, parent=None, properties=None, attProperties=None, 20 20 src=None, *args, **kwargs): 21 21 self._cxnName = "" … … 27 27 self._drawSizerChildren = False 28 28 self._statusBarClass = dabo.ui.dStatusBar 29 29 30 30 # Extract the menu definition file, if any 31 self._menuBarFile = self._extractKey((properties, attProperties, kwargs), 31 self._menuBarFile = self._extractKey((properties, attProperties, kwargs), 32 32 "MenuBarFile", "") 33 33 if self._menuBarFile: 34 34 self._menuBarClass = self._menuBarFile 35 35 36 36 if False and parent: 37 37 ## pkm 3/10/05: I like it better now without the float on parent option … … 58 58 # When in designer mode, we need to turn off various behaviors. 59 59 self._designerMode = False 60 # Default behavior used to be for the form to set the status bar text with the 60 # Default behavior used to be for the form to set the status bar text with the 61 61 # current record position. Now we only turn it on for data apps. 62 62 self._autoUpdateStatusText = False … … 72 72 self._fieldValidationControl = None 73 73 74 super(dFormMixin, self).__init__(preClass, parent, properties, 74 super(dFormMixin, self).__init__(preClass, parent, properties, 75 75 attProperties, *args, **kwargs) 76 76 77 77 dabo.ui.callAfter(self._createStatusBar) 78 self._createToolBar() 79 if not self._designerMode: 78 self._createToolBar() 79 if not self._designerMode: 80 80 self.restoreSizeAndPosition() 81 81 82 82 83 83 def _getInitPropertiesList(self): 84 additional = ["BorderResizable", "FloatOnParent", "ShowCloseButton", "ShowInTaskBar", 84 additional = ["BorderResizable", "FloatOnParent", "ShowCloseButton", "ShowInTaskBar", 85 85 "ShowMaxButton", "ShowMinButton", "ShowSystemMenu", "StayOnTop", "TinyTitleBar"] 86 86 original = list(super(dFormMixin, self)._getInitPropertiesList()) 87 87 return tuple(original + additional) 88 88 89 89 90 90 def _afterInit(self): … … 109 109 if app is not None: 110 110 app.uiForms.add(self) 111 111 112 112 # Centering information 113 113 self._normLeft = self.Left … … 126 126 # If there are custom menu hotkey bindings, re-set them 127 127 wx.CallAfter(self._restoreMenuPrefs) 128 128 129 129 super(dFormMixin, self)._afterInit() 130 130 131 131 ## pkm 2010-08-03: The below results in smoother, nicer forms (no menu flickering or 132 ## other weird artifacts like page tabs partially disappearing), 133 ## however there are reports of python.exe maxing out the CPU and the 134 ## process needing to be killed by the user. My testing was with 132 ## other weird artifacts like page tabs partially disappearing), 133 ## however there are reports of python.exe maxing out the CPU and the 134 ## process needing to be killed by the user. My testing was with 135 135 ## Python 2.5.4 / wx 2.8.11.0 / Windows Vista. Perhaps we just need to 136 136 ## play around with where we make this call, or set double buffered off 137 137 ## every now and then with a timer or something... 138 138 ##self.SetDoubleBuffered(True) 139 140 139 140 141 141 def _initEvents(self): 142 142 super(dFormMixin, self)._initEvents() … … 147 147 self.bindEvent(dEvents.Paint, self.__onPaint) 148 148 self.bindEvent(dEvents.Idle, self.__onIdle) 149 150 149 150 151 151 def __onWxClose(self, evt): 152 152 self.raiseEvent(dEvents.Close, evt) 153 153 if evt.CanVeto(): 154 154 evt.Veto() 155 156 155 156 157 157 def __onWxActivate(self, evt): 158 158 """ Raise the Dabo Activate or Deactivate appropriately.""" … … 172 172 # Clear it 173 173 self._fieldValidationControl = None 174 175 174 175 176 176 def Maximize(self, maximize=True, *args, **kwargs): 177 177 # On Mac MDI Child Frames, Maximize(False) erroneously maximizes. Not sure … … 186 186 def SetPosition(self, val): 187 187 # On Windows MDI Child frames when the main form has a toolbar, setting the 188 # top position results in a position too low by the height of the toolbar. 188 # top position results in a position too low by the height of the toolbar. 189 189 left, top = val 190 190 tb = None … … 194 194 and self.MDI \ 195 195 and tb: 196 top -= tb.Height 196 top -= tb.Height 197 197 super(dFormMixin, self).SetPosition((left, top)) 198 198 … … 209 209 def _createStatusBar(self): 210 210 modal = getattr(self, "Modal", False) 211 if (self and self.ShowStatusBar 211 if (self and self.ShowStatusBar 212 212 and self.StatusBar is None 213 213 and not isinstance (self, wx.Dialog) … … 222 222 self.Application.clearActiveForm(self) 223 223 224 224 225 225 def __onPaint(self, evt): 226 226 if self.Application: … … 228 228 else: 229 229 self.__needOutlineRedraw = False 230 231 230 231 232 232 def __onIdle(self, evt): 233 233 if self.__needOutlineRedraw or self._alwaysDrawSizerOutlines: … … 235 235 sz.drawOutline(self, recurse=self._recurseOutlinedSizers, 236 236 drawChildren=self._drawSizerChildren) 237 238 237 238 239 239 def __onClose(self, evt): 240 240 app = self.Application 241 241 242 if not self._designerMode: 242 if not self._designerMode: 243 243 self.saveSizeAndPosition() 244 244 … … 250 250 # Run the cleanup code. 251 251 self.closing() 252 252 253 253 self._isClosed = True 254 254 if self._isModal: … … 256 256 257 257 # On the Mac, this next line prevents Bus Errors when closing a form. 258 self.Visible = False 258 self.Visible = False 259 259 260 260 if app is not None: … … 265 265 """ Force the control-with-focus to fire its KillFocus code. 266 266 267 The bizobj will only get its field updated during the control's 267 The bizobj will only get its field updated during the control's 268 268 KillFocus code. This function effectively commands that update to 269 269 happen before it would have otherwise occurred. … … 284 284 can change that to suit your app needs by passing a different interval 285 285 in milliseconds. 286 287 Sometimes, though, you want to force immediate execution of the 286 287 Sometimes, though, you want to force immediate execution of the 288 288 refresh. In these cases, pass an interval of 0 to this method, which 289 289 means don't wait; execute now. … … 349 349 for pth in relPath.split("."): 350 350 try: 351 menuItem = [ch for ch in menuItem.Children 351 menuItem = [ch for ch in menuItem.Children 352 352 if hasattr(ch, "Caption") 353 353 and cleanMenuCaption(ch.Caption) == pth][0] … … 360 360 menuItem.HotKey = hk 361 361 362 362 363 363 def _gtk_show_fix(self, show=True): 364 364 # On Gtk, in wxPython 2.8.1.1 at least, the form will get re-shown at its … … 378 378 """Shows the form in a modal fashion. Other forms can still be 379 379 activated, but all controls are disabled. 380 NOTE: wxPython does not currently support this. DO NOT USE 380 NOTE: wxPython does not currently support this. DO NOT USE 381 381 this method. 382 382 """ 383 383 raise dException.FeatureNotSupportedException( 384 384 _("The underlying UI toolkit does not support modal forms. Use a dDialog instead.")) 385 386 385 386 387 387 def release(self): 388 388 """ Instead of just destroying the object, make sure that … … 396 396 the beforeClose methods will be called, and these will have 397 397 an opportunity to conditionally block the form from closing. 398 If force=True, the form is closed without any chance of 398 If force=True, the form is closed without any chance of 399 399 preventing it. 400 400 """ … … 416 416 if self: 417 417 self.Destroy() 418 418 419 419 420 420 def _beforeClose(self, evt=None): 421 421 """ See if there are any pending changes in the form, if the 422 form is set for checking for this. If everything's OK, call the 422 form is set for checking for this. If everything's OK, call the 423 423 hook method. 424 424 """ … … 427 427 ret = self.beforeClose(evt) 428 428 return ret 429 430 429 430 431 431 def beforeClose(self, evt): 432 """ Hook method. Returning False will prevent the form from 432 """ Hook method. Returning False will prevent the form from 433 433 closing. Gives you a chance to determine the status of the form 434 434 to see if changes need to be saved, etc. 435 435 """ 436 436 return True 437 438 437 438 439 439 def closing(self): 440 440 """ Stub method to be customized in subclasses. At this point, 441 441 the form is going to close. If you need to do something that might 442 prevent the form from closing, code it in the beforeClose() 442 prevent the form from closing, code it in the beforeClose() 443 443 method instead. 444 444 """ 445 445 pass 446 446 447 447 448 448 def afterSetMenuBar(self): … … 455 455 456 456 Every form maintains an internal menu of actions appropriate to itself. 457 For instance, a dForm with a primary bizobj will maintain a menu with 458 'requery', 'save', 'next', etc. choices. 459 460 This function sets up the internal menu, which can optionally be 457 For instance, a dForm with a primary bizobj will maintain a menu with 458 'requery', 'save', 'next', etc. choices. 459 460 This function sets up the internal menu, which can optionally be 461 461 inserted into the mainForm's menu bar during SetFocus. 462 462 """ 463 463 menu = dMenu.dMenu() 464 464 return menu 465 466 465 466 467 467 def onEditUndo(self, evt): 468 468 """If you want your form to respond to the Undo menu item in 469 the Edit menu that is installed in the Dabo base menu, override 469 the Edit menu that is installed in the Dabo base menu, override 470 470 this method, and either return nothing, or return something other 471 471 than False. 472 472 """ 473 473 return False 474 475 474 475 476 476 def onEditRedo(self, evt): 477 477 """If you want your form to respond to the Redo menu item in 478 the Edit menu that is installed in the Dabo base menu, override 478 the Edit menu that is installed in the Dabo base menu, override 479 479 this method, and either return nothing, or return something other 480 480 than False. 481 481 """ 482 482 return False 483 484 483 484 485 485 def restoreSizeAndPosition(self): 486 486 """ Restore the saved window geometry for this form. 487 487 488 Ask dApp for the last saved setting of height, width, left, and top, 488 Ask dApp for the last saved setting of height, width, left, and top, 489 489 and set those properties on this form. 490 490 """ … … 506 506 if state not in ("Minimized", "Maximized", "Normal", "FullScreen"): 507 507 state = self.WindowState 508 508 509 509 if state == "Minimized": 510 510 state = "Normal" … … 550 550 app.setUserSetting("%s.width" % name, width) 551 551 app.setUserSetting("%s.height" % name, height) 552 552 553 553 554 554 def setStatusText(self, *args): 555 555 """Moved functionality to the StatusText property setter.""" 556 556 self._setStatusText(*args) 557 558 557 558 559 559 def layout(self): 560 560 """ Wrap the wx sizer layout call. """ … … 567 567 if self.Application.Platform == "Win": 568 568 self.refresh() 569 570 569 570 571 571 def registerObject(self, obj): 572 572 """Stores a reference to the passed object using the RegID key 573 property of the object for later retrieval. You may reference the 573 property of the object for later retrieval. You may reference the 574 574 object as if it were a child object of this form; i.e., by using simple 575 dot notation, with the RegID as the 'name' of the object. 575 dot notation, with the RegID as the 'name' of the object. 576 576 """ 577 577 if hasattr(obj, "RegID"): … … 587 587 else: 588 588 self.__dict__[id] = obj 589 590 589 590 591 591 def getObjectByRegID(self, id): 592 """Given a RegID value, this will return a reference to the 592 """Given a RegID value, this will return a reference to the 593 593 associated object, if any. If not, returns None. 594 594 """ … … 597 597 else: 598 598 return None 599 600 599 600 601 601 def _appendToMenu(self, menu, caption, function, bitmap=wx.NullBitmap, menuId=-1): 602 602 return menu.append(caption, OnHit=function, bmp=bitmap) 603 603 604 604 605 def appendToolBarButton(self, name, pic, toggle=False, tip="", help="", 605 def appendToolBarButton(self, name, pic, toggle=False, tip="", help="", 606 606 *args, **kwargs): 607 return self.ToolBar.appendButton(name, pic, toggle=toggle, tip=tip, 607 return self.ToolBar.appendButton(name, pic, toggle=toggle, tip=tip, 608 608 help=help, *args, **kwargs) 609 609 … … 611 611 def fillPreferenceDialog(self, dlg): 612 612 """This method is called with a reference to the pref dialog. It can be overridden 613 in subclasses to add application-specific content to the pref dialog. To add a 613 in subclasses to add application-specific content to the pref dialog. To add a 614 614 new page to the dialog, call the dialog's addCategory() method, passing the caption 615 for that page. It will return a reference to the newly-created page, to which you 615 for that page. It will return a reference to the newly-created page, to which you 616 616 then add your controls. 617 617 """ … … 620 620 621 621 def _setAbsoluteFontZoom(self, amt): 622 """Let the default behavior run, but then save the font zoom level to 623 the user preferences file. The loading of the saved pref happens in 624 the individual control (dPemMixinBase) so that the restoration of the 625 control's font zoom isn't dependent on the control being created at 622 """Let the default behavior run, but then save the font zoom level to 623 the user preferences file. The loading of the saved pref happens in 624 the individual control (dPemMixinBase) so that the restoration of the 625 control's font zoom isn't dependent on the control being created at 626 626 form load time. 627 627 """ 628 628 self.super(amt) 629 629 if self.Application and self.SaveRestorePosition: 630 self.Application.setUserSetting("%s.fontzoom" 630 self.Application.setUserSetting("%s.fontzoom" 631 631 % self.getAbsoluteName(), self._currFontZoom) 632 632 633 633 def _restoreFontZoom(self): 634 634 if self.Application: 635 self._currFontZoom = self.Application.getUserSetting("%s.fontzoom" 635 self._currFontZoom = self.Application.getUserSetting("%s.fontzoom" 636 636 % self.getAbsoluteName(), 0) 637 637 … … 663 663 # whether or not it is a member of this form. 664 664 return getattr(self, "_activeControl", None) 665 665 666 666 def _setActiveControl(self, val): 667 667 val.setFocus() 668 668 669 669 670 670 def _getAutoUpdateStatusText(self): 671 671 return self._autoUpdateStatusText … … 677 677 def _getBorderResizable(self): 678 678 return (self.MDI or self._hasWindowStyleFlag(wx.RESIZE_BORDER)) 679 679 680 680 def _setBorderResizable(self, value): 681 681 self._delWindowStyleFlag(wx.RESIZE_BORDER) … … 690 690 v = self._centered = False 691 691 return v 692 692 693 693 def _setCentered(self, val): 694 694 if self._constructed(): … … 809 809 else: 810 810 self._properties["MenuBar"] = val 811 811 812 812 813 813 def _getMenuBarClass(self): … … 820 820 def _setMenuBarClass(self, val): 821 821 self._menuBarClass = val 822 822 823 823 824 824 def _getMenuBarFile(self): … … 838 838 val = self._saveRestorePosition = not isinstance(self, dabo.ui.dDialog) 839 839 return val 840 840 841 841 def _setSaveRestorePosition(self, val): 842 842 self._saveRestorePosition = val … … 845 845 def _getShowCaption(self): 846 846 return self._hasWindowStyleFlag(wx.CAPTION) 847 847 848 848 def _setShowCaption(self, value): 849 849 self._delWindowStyleFlag(wx.CAPTION) … … 854 854 def _getShowCloseButton(self): 855 855 return self._hasWindowStyleFlag(wx.CLOSE_BOX) 856 856 857 857 def _setShowCloseButton(self, value): 858 858 self._delWindowStyleFlag(wx.CLOSE_BOX) … … 872 872 def _getShowMaxButton(self): 873 873 return self._hasWindowStyleFlag(wx.MAXIMIZE_BOX) 874 874 875 875 def _setShowMaxButton(self, value): 876 876 self._delWindowStyleFlag(wx.MAXIMIZE_BOX) 877 877 if value: 878 878 self._addWindowStyleFlag(wx.MAXIMIZE_BOX) 879 879 880 880 881 881 def _getShowMenuBar(self): … … 892 892 def _getShowMinButton(self): 893 893 return self._hasWindowStyleFlag(wx.MINIMIZE_BOX) 894 894 895 895 def _setShowMinButton(self, value): 896 896 self._delWindowStyleFlag(wx.MINIMIZE_BOX) … … 904 904 except AttributeError: 905 905 ret = self._showStatusBar = True 906 return ret 907 906 return ret 907 908 908 def _setShowStatusBar(self, val): 909 909 self._showStatusBar = bool(val) 910 911 910 911 912 912 def _getShowSystemMenu(self): 913 913 return self._hasWindowStyleFlag(wx.SYSTEM_MENU) 914 914 915 915 def _setShowSystemMenu(self, value): 916 916 self._delWindowStyleFlag(wx.SYSTEM_MENU) 917 917 if value: 918 918 self._addWindowStyleFlag(wx.SYSTEM_MENU) 919 920 919 920 921 921 def _getShowToolBar(self): 922 922 try: … … 926 926 ret = self._showToolBar = False 927 927 return ret 928 928 929 929 def _setShowToolBar(self, val): 930 self._showToolBar = bool(val) 930 self._showToolBar = bool(val) 931 931 932 932 … … 985 985 986 986 def _setStatusText(self, val, _callAfter=True): 987 """ Set the text of the status bar. Dabo will decide whether to 987 """ Set the text of the status bar. Dabo will decide whether to 988 988 send the text to the main frame or this frame. This matters with MDI 989 989 versus non-MDI forms. … … 1002 1002 statusBar = None 1003 1003 1004 if statusBar: 1004 if statusBar: 1005 1005 sb = controllingFrame.GetStatusBar() 1006 1006 sb.SetStatusText(val) 1007 1007 statusBar.Update() 1008 1008 1009 1009 1010 1010 def _getStayOnTop(self): … … 1029 1029 def _getTinyTitleBar(self): 1030 1030 return self._hasWindowStyleFlag(wx.FRAME_TOOL_WINDOW) 1031 1031 1032 1032 def _setTinyTitleBar(self, value): 1033 1033 self._delWindowStyleFlag(wx.FRAME_TOOL_WINDOW) 1034 1034 if value: 1035 1035 self._addWindowStyleFlag(wx.FRAME_TOOL_WINDOW) 1036 1036 1037 1037 1038 1038 def _getToolBar(self): … … 1042 1042 # We are probably a dialog or some other form that doesn't support ToolBars. 1043 1043 return None 1044 1044 1045 1045 def _setToolBar(self, val): 1046 1046 self.SetToolBar(val) 1047 1047 1048 1048 def _getWindowState(self): 1049 1049 try: … … 1087 1087 1088 1088 # property definitions follow: 1089 ActiveControl = property(_getActiveControl, _setActiveControl, None, 1089 ActiveControl = property(_getActiveControl, _setActiveControl, None, 1090 1090 _("Contains a reference to the active control on the form, or None.")) 1091 1091 1092 1092 AutoUpdateStatusText = property(_getAutoUpdateStatusText, _setAutoUpdateStatusText, None, 1093 1093 _("Does this form update the status text with the current record position? (bool)")) … … 1098 1098 The default is True for dForm and False for dDialog.""")) 1099 1099 1100 Centered = property(_getCentered, _setCentered, None, 1100 Centered = property(_getCentered, _setCentered, None, 1101 1101 _("Centers the form on the screen when set to True. (bool)")) 1102 1102 … … 1106 1106 CxnName = property(_getCxnName, _setCxnName, None, 1107 1107 _("Name of the connection used for data access (str)")) 1108 1108 1109 1109 FloatingPanel = property(_getFloatingPanel, None, None, 1110 _("""Small modal dialog that is designed to be used for temporary displays, 1111 similar to context menus, but which can contain any controls. 1110 _("""Small modal dialog that is designed to be used for temporary displays, 1111 similar to context menus, but which can contain any controls. 1112 1112 (read-only) (dDialog)""")) 1113 1113 1114 1114 FloatOnParent = property(_getFloatOnParent, _setFloatOnParent, None, 1115 1115 _("Specifies whether the form stays on top of the parent or not.")) 1116 1117 Icon = property(_getIcon, _setIcon, None, 1116 1117 Icon = property(_getIcon, _setIcon, None, 1118 1118 _("""Specifies the icon for the form. 1119 1119 … … 1126 1126 MDI = property(_getMDI, None, None, 1127 1127 _("""Returns True if this is a MDI (Multiple Document Interface) form. (bool) 1128 1128 1129 1129 Otherwise, returns False if this is a SDI (Single Document Interface) form. 1130 1130 Users on Microsoft Windows seem to expect MDI, while on other platforms SDI is 1131 1131 preferred. 1132 1132 1133 1133 See also: the dabo.MDI global setting. (bool)""")) 1134 1134 … … 1142 1142 _("Path to the .mnxml file that defines this form's menu bar (str)")) 1143 1143 1144 SaveRestorePosition = property(_getSaveRestorePosition, 1144 SaveRestorePosition = property(_getSaveRestorePosition, 1145 1145 _setSaveRestorePosition, None, 1146 1146 _("""Specifies whether the form's position and size as set by the user 1147 1147 will get saved and restored in the next session. Default is True for 1148 1148 forms and False for dialogs.""")) 1149 1149 1150 1150 ShowCaption = property(_getShowCaption, _setShowCaption, None, 1151 1151 _("Specifies whether the caption is displayed in the title bar. (bool).")) … … 1176 1176 1177 1177 SizersToOutline = property(_getSizersToOutline, _setSizersToOutline, None, 1178 _("""When drawing the outline of sizers, the sizer(s) to draw. 1178 _("""When drawing the outline of sizers, the sizer(s) to draw. 1179 1179 Default=self.Sizer (dSizer)""")) 1180 1180 … … 1194 1194 _("""Used to indicate that this is a temporary form, and that its settings 1195 1195 should not be persisted. Default=False (bool)""")) 1196 1196 1197 1197 TinyTitleBar = property(_getTinyTitleBar, _setTinyTitleBar, None, 1198 1198 _("Specifies whether the title bar is small, like a tool window. (bool).")) … … 1200 1200 ToolBar = property(_getToolBar, _setToolBar, None, 1201 1201 _("Tool bar for this form. (dToolBar)")) 1202 1202 1203 1203 WindowState = property(_getWindowState, _setWindowState, None, 1204 1204 _("""Specifies the current state of the form. (int) 1205 1205 1206 1206 Normal 1207 1207 Minimized
