[gnue] r10270 - in trunk/gnue-forms: . src/uidrivers/wx/widgets
[email protected] Sun, 12 Dec 2010 15:50:36 -0600 (CST)
| Newsgroups | gmane.comp.cms.gnue.cvs |
|---|---|
| Message-ID | <[email protected]> |
Author: reinhard Date: 2010-12-12 15:50:36 -0600 (Sun, 12 Dec 2010) New Revision: 10270 Modified: trunk/gnue-forms/ trunk/gnue-forms/src/uidrivers/wx/widgets/entry.py Log: Introduced "picker" controls for numeric and date input. Now the user ca= n input numerical and date fields with the mouse. Helpful for applications= used with a touch pen. Property changes on: trunk/gnue-forms ___________________________________________________________________ Name: bzr:revision-info - timestamp: 2010-12-08 01:03:04.076999903 +0100 committer: Reinhard M=C3=BCller <[email protected]> properties:=20 branch-nick: forms + timestamp: 2010-12-11 17:52:20.673000097 +0100 committer: Reinhard M=C3=BCller <[email protected]> properties:=20 branch-nick: forms Name: bzr:file-ids - src/GFObjects/GFBlock.py 1459@3a364389-8fce-0310-8f11-cc363fde16c7:t= runk%2Fgnue-forms:src%2FGFObjects%2FGFBlock.py + src/uidrivers/wx/widgets/entry.py 10053@3a364389-8fce-0310-8f11-cc36= 3fde16c7:trunk%2Fgnue-forms:src%2Fuidrivers%2Fwx%2Fwidgets%2Fentry.py Name: bzr:revision-id:v4 - 3116 [email protected] 3117 [email protected] 3118 [email protected] 3119 [email protected] 3120 [email protected] 3121 [email protected] 3122 [email protected] 3123 [email protected] 3124 [email protected] 3125 [email protected] 3126 [email protected] 3127 [email protected] 3128 [email protected] 3129 [email protected] 3130 [email protected] 3131 [email protected] 3132 [email protected] 3133 [email protected] 3134 [email protected] 3135 [email protected] 3136 [email protected] 3137 [email protected] 3138 [email protected] 3139 [email protected] 3140 [email protected] 3141 [email protected] 3142 [email protected] 3143 [email protected] 3144 [email protected] 3145 [email protected] 3146 [email protected] 3147 [email protected] 3148 [email protected] 3149 [email protected] 3150 [email protected] 3151 [email protected] 3152 [email protected] 3153 [email protected] 3154 [email protected] 3155 [email protected] 3156 [email protected] 3157 [email protected] 3158 [email protected] 3159 [email protected] 3160 [email protected] 3161 [email protected] 3162 [email protected] 3163 [email protected] 3164 [email protected] 3165 [email protected] 3166 [email protected] 3167 [email protected] 3168 [email protected] 3169 [email protected] 3170 [email protected] 3171 [email protected] 3172 [email protected] 3173 [email protected] 3174 [email protected] 3175 [email protected] + 3116 [email protected] 3117 [email protected] 3118 [email protected] 3119 [email protected] 3120 [email protected] 3121 [email protected] 3122 [email protected] 3123 [email protected] 3124 [email protected] 3125 [email protected] 3126 [email protected] 3127 [email protected] 3128 [email protected] 3129 [email protected] 3130 [email protected] 3131 [email protected] 3132 [email protected] 3133 [email protected] 3134 [email protected] 3135 [email protected] 3136 [email protected] 3137 [email protected] 3138 [email protected] 3139 [email protected] 3140 [email protected] 3141 [email protected] 3142 [email protected] 3143 [email protected] 3144 [email protected] 3145 [email protected] 3146 [email protected] 3147 [email protected] 3148 [email protected] 3149 [email protected] 3150 [email protected] 3151 [email protected] 3152 [email protected] 3153 [email protected] 3154 [email protected] 3155 [email protected] 3156 [email protected] 3157 [email protected] 3158 [email protected] 3159 [email protected] 3160 [email protected] 3161 [email protected] 3162 [email protected] 3163 [email protected] 3164 [email protected] 3165 [email protected] 3166 [email protected] 3167 [email protected] 3168 [email protected] 3169 [email protected] 3170 [email protected] 3171 [email protected] 3172 [email protected] 3173 [email protected] 3174 [email protected] 3175 [email protected] 3176 [email protected] Name: bzr:text-parents - src/GFObjects/GFBlock.py [email protected]= -rw7t0y2fxoqksceo + src/uidrivers/wx/widgets/entry.py [email protected]= 203112140-2fva9rrj0j87abw4 Modified: trunk/gnue-forms/src/uidrivers/wx/widgets/entry.py =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- trunk/gnue-forms/src/uidrivers/wx/widgets/entry.py 2010-12-12 21:50:3= 3 UTC (rev 10269) +++ trunk/gnue-forms/src/uidrivers/wx/widgets/entry.py 2010-12-12 21:50:3= 6 UTC (rev 10270) @@ -24,8 +24,10 @@ Implementation of the <entry> tag """ =20 +import locale import os import wx +import wx.combo =20 from gnue.forms.uidrivers.wx.widgets import _base from gnue.forms.input import GFKeyMapper @@ -85,28 +87,34 @@ =20 def __build_default(self, parent, password=3DFalse, multiline=3DFals= e): =20 - xFlags =3D wx.TE_PROCESS_TAB + if multiline and not self.managed: + self.__border =3D self._uiDriver.control_border('default') =20 - if password: - xFlags |=3D wx.TE_PASSWORD - - if multiline: - xFlags |=3D wx.TE_MULTILINE - else: - xFlags |=3D wx.TE_PROCESS_ENTER - - # Right-align numeric fields. This does work on wxMSW and wxGTK= only. if self._gfObject._field.datatype =3D=3D 'number': - xFlags |=3D wx.TE_RIGHT + style =3D wx.CB_DROPDOWN + ctrl =3D NumberEntryCtrl(parent, style=3Dstyle) =20 - if multiline and not self.managed: - self.__border =3D self._uiDriver.control_border('default') + elif self._gfObject._field.datatype =3D=3D 'date': + style =3D wx.DP_DROPDOWN | wx.DP_ALLOWNONE + ctrl =3D DatePickerCtrl(parent, style=3Dstyle) =20 - ctrl =3D wx.TextCtrl(parent, -1, style=3DxFlags) + else: + style =3D wx.TE_PROCESS_TAB + if password: + style |=3D wx.TE_PASSWORD + if multiline: + style |=3D wx.TE_MULTILINE + else: + style |=3D wx.TE_PROCESS_ENTER + ctrl =3D wx.TextCtrl(parent, style=3Dstyle) =20 self.__set_size(ctrl) =20 - ctrl.Bind(wx.EVT_TEXT, self.__on_text_changed) + if isinstance(ctrl, DatePickerCtrl): + ctrl.Bind(wx.EVT_DATE_CHANGED, self.__on_datepicker_date_cha= nged) + ctrl.Bind(wx.EVT_TEXT, self.__on_datepicker_text) + else: + ctrl.Bind(wx.EVT_TEXT, self.__on_text_changed) ctrl.Bind(wx.EVT_CHAR, self.__on_keypress) ctrl.Bind(wx.EVT_KEY_DOWN, self.__on_key_down) ctrl.Bind(wx.EVT_SET_FOCUS, self.__on_set_focus) @@ -311,6 +319,8 @@ if self.__old_background is not None: widget.SetBackgroundColour(self.__old_background) =20 + event.Skip() =20 + # ------------------------------------------------------------------= ------- =20 def __on_mac_choice_clicked(self, event): @@ -345,6 +355,23 @@ =20 # ------------------------------------------------------------------= ------- =20 + def __on_datepicker_date_changed(self, event): + + widget =3D event.GetEventObject() + + self._request('REPLACEVALUE', text=3Dwidget.GetText()) + + # ------------------------------------------------------------------= ------- + + def __on_datepicker_text(self, event): + + widget =3D event.GetEventObject() + + self._request('REPLACEVALUE', text=3Dwidget.GetValue(), + position=3Dwidget.GetInsertionPoint()) + + # ------------------------------------------------------------------= ------- + def __on_gtk_text_changed(self, event): =20 # FIXME: workaround for issue-144. Setting a selection within a= n @@ -406,6 +433,12 @@ event.Skip() return =20 + # Let Windows' date picker handle up/down. + if 'wxMSW' in wx.PlatformInfo and isinstance(control, DatePicker= Ctrl): + if keycode in (wx.WXK_UP, wx.WXK_DOWN): + event.Skip() + return + # Handle cursor up/down and page up/down. if not (event.ShiftDown() or event.CmdDown() or event.AltDown())= : if keycode =3D=3D wx.WXK_UP: @@ -541,6 +574,8 @@ # with the string value (e.g. in Choice-Controls on OS X= ) if not widget.SetStringSelection(value): widget.SetValue(value) + elif isinstance(widget, DatePickerCtrl): + widget.SetText(value) else: widget.SetValue(value) =20 @@ -602,6 +637,10 @@ # Take care: SetSelection in a ListBox sets the selected ite= m! pass =20 + elif isinstance(widget, DatePickerCtrl) and 'wxMSW' in wx.Platfo= rmInfo: + # Windows' native DatePickerCtrl doesn't have a selection. + pass + =20 elif hasattr(widget, 'SetSelection'): if 'wxGTK' in wx.PlatformInfo: wx.CallAfter(widget.SetSelection, selection1, selection2= ) @@ -743,7 +782,9 @@ # Add border width. # FIXME: This is only an estimate, but I haven't found out h= ow to # determine the real border width in wx. - if self._gfObject.style.lower() =3D=3D 'dropdown': + if isinstance (control, wx.ComboBox) \ + or isinstance (control, NumberEntryCtrl) \ + or isinstance (control, DatePickerCtrl): min_w +=3D 4 if max_w: max_w +=3D 4 @@ -826,6 +867,271 @@ =20 =20 # =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D +# Number Entry Control +# =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D + +class NumberEntryCtrl(wx.combo.ComboCtrl): + + def __init__(self, *args, **kwargs): + + wx.combo.ComboCtrl.__init__(self, *args, **kwargs) + + popup =3D NumberEntryPopup() + popup.TextCtrl =3D self.GetTextCtrl() + self.SetPopupControl(popup) + + # In wxWidgets 2.8, wxComboCtrl receives the EVT_SET_FOCUS event= s from + # the TextCtrl, but not EVT_KILL_FOCUS events. This seems to be = fixed + # in wxWidgets 2.9, so this workaround can be removed when we re= quire + # higher versions of wxWidgets. + self.GetTextCtrl().Bind(wx.EVT_KILL_FOCUS, self.OnKillFocus) + + # ------------------------------------------------------------------= ------- + + def OnKillFocus(self, event): + + e =3D event.Clone() + e.SetEventObject(self) + self.GetEventHandler().ProcessEvent(e) + + event.Skip() + + # ------------------------------------------------------------------= ------- + + def GetBackgroundColour(self, *args, **kwargs): + + return self.GetTextCtrl().GetBackgroundColour(*args, **kwargs) + + # ------------------------------------------------------------------= ------- + + def SetBackgroundColour(self, *args, **kwargs): + + return self.GetTextCtrl().SetBackgroundColour(*args, **kwargs) + + # ------------------------------------------------------------------= ------- + + def SetSelection(self, *args, **kwargs): + + return self.GetTextCtrl().SetSelection(*args, **kwargs) + + # ------------------------------------------------------------------= ------- + + def SetInsertionPoint(self, *args, **kwargs): + + return self.GetTextCtrl().SetInsertionPoint(*args, **kwargs) + +# =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D + +class NumberEntryPopup(wx.combo.ComboPopup): + + def Create(self, parent, *args, **kwargs): + + wx.combo.ComboPopup.Create(self, parent, *args, **kwargs) + + self.panel =3D wx.Panel(parent, style=3Dwx.BORDER_SIMPLE) + + radixc =3D u" " + locale.localeconv()['decimal_point'] + u" " + + self.b1 =3D wx.Button(self.panel, label=3Du" 1 ", style=3Dwx.BU_= EXACTFIT) + self.b2 =3D wx.Button(self.panel, label=3Du" 2 ", style=3Dwx.BU_= EXACTFIT) + self.b3 =3D wx.Button(self.panel, label=3Du" 3 ", style=3Dwx.BU_= EXACTFIT) + self.b4 =3D wx.Button(self.panel, label=3Du" 4 ", style=3Dwx.BU_= EXACTFIT) + self.b5 =3D wx.Button(self.panel, label=3Du" 5 ", style=3Dwx.BU_= EXACTFIT) + self.b6 =3D wx.Button(self.panel, label=3Du" 6 ", style=3Dwx.BU_= EXACTFIT) + self.b7 =3D wx.Button(self.panel, label=3Du" 7 ", style=3Dwx.BU_= EXACTFIT) + self.b8 =3D wx.Button(self.panel, label=3Du" 8 ", style=3Dwx.BU_= EXACTFIT) + self.b9 =3D wx.Button(self.panel, label=3Du" 9 ", style=3Dwx.BU_= EXACTFIT) + self.b0 =3D wx.Button(self.panel, label=3Du" 0 ", style=3Dwx.BU_= EXACTFIT) + self.br =3D wx.Button(self.panel, label=3Dradixc, style=3Dwx.BU_= EXACTFIT) + self.bx =3D wx.Button(self.panel, label=3Du" x ", style=3Dwx.BU_= EXACTFIT) + self.b1.Bind(wx.EVT_BUTTON, self.OnClick) + self.b2.Bind(wx.EVT_BUTTON, self.OnClick) + self.b3.Bind(wx.EVT_BUTTON, self.OnClick) + self.b4.Bind(wx.EVT_BUTTON, self.OnClick) + self.b5.Bind(wx.EVT_BUTTON, self.OnClick) + self.b6.Bind(wx.EVT_BUTTON, self.OnClick) + self.b7.Bind(wx.EVT_BUTTON, self.OnClick) + self.b8.Bind(wx.EVT_BUTTON, self.OnClick) + self.b9.Bind(wx.EVT_BUTTON, self.OnClick) + self.b0.Bind(wx.EVT_BUTTON, self.OnClick) + self.br.Bind(wx.EVT_BUTTON, self.OnClick) + self.bx.Bind(wx.EVT_BUTTON, self.OnClick) + + box =3D wx.GridSizer(rows=3D4, cols=3D3) + box.Add(self.b1, flag=3Dwx.EXPAND) + box.Add(self.b2, flag=3Dwx.EXPAND) + box.Add(self.b3, flag=3Dwx.EXPAND) + box.Add(self.b4, flag=3Dwx.EXPAND) + box.Add(self.b5, flag=3Dwx.EXPAND) + box.Add(self.b6, flag=3Dwx.EXPAND) + box.Add(self.b7, flag=3Dwx.EXPAND) + box.Add(self.b8, flag=3Dwx.EXPAND) + box.Add(self.b9, flag=3Dwx.EXPAND) + box.Add(self.b0, flag=3Dwx.EXPAND) + box.Add(self.br, flag=3Dwx.EXPAND) + box.Add(self.bx, flag=3Dwx.EXPAND) + self.panel.SetSizerAndFit(box) + + # ------------------------------------------------------------------= ------- + + def OnClick(self, event): + + char =3D event.GetEventObject().GetLabel()[1:2] + if char =3D=3D "x": + self.TextCtrl.ChangeValue(self.TextCtrl.GetValue()[:-1]) + self.TextCtrl.SetInsertionPointEnd() + else: + self.TextCtrl.WriteText(char) + + # ------------------------------------------------------------------= ------- + + def GetControl(self, *args, **kwds): + + return self.panel + + # ------------------------------------------------------------------= ------- + + def GetAdjustedSize(self, *args, **kwds): + + return self.panel.GetMinSize() + + +# =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D +# Date Picker Control +# =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D + +class DatePickerCtrl(wx.DatePickerCtrl): + + def __init__(self, *args, **kwargs): + + wx.DatePickerCtrl.__init__(self, *args, **kwargs) + + # The native control available in Windows doesn't have all the b= reakage + # we try to fix here, so we just do nothing. + if 'wxMSW' in wx.PlatformInfo: + return + =20 + self.combo =3D None + + for child in self.GetChildren(): + if isinstance (child, wx.combo.ComboCtrl): + self.combo =3D child + + # Make sure we receive the interesting events from the TextCtrl. + self.combo.GetTextCtrl().Bind(wx.EVT_KEY_DOWN, self.OnEvent) + self.combo.GetTextCtrl().Bind(wx.EVT_CHAR, self.OnEvent) + self.combo.GetTextCtrl().Bind(wx.EVT_SET_FOCUS, self.OnEvent) + self.combo.GetTextCtrl().Bind(wx.EVT_KILL_FOCUS, self.OnEvent) + + self.Bind(wx.EVT_SET_FOCUS, self.OnSetFocus) + self.Bind(wx.EVT_TEXT, self.OnText) + + self.propagating_event =3D False + + # ------------------------------------------------------------------= ------- + + def OnEvent(self, event): + + self.propagating_event =3D True + try: + e =3D event.Clone() + e.SetEventObject(self) + self.GetEventHandler().ProcessEvent(e) + finally: + self.propagating_event =3D False + + event.Skip() + + # ------------------------------------------------------------------= ------- + + def OnSetFocus(self, event): + + # wxDatePickerCtrl's EVT_SET_FOCUS handler unconditionally sets = the + # focus on the ComboCtrl element, and the combo element sets the= focus + # on its TextCtrl element. Since we propagate the TextCtrl's + # EVT_SET_FOCUS up to the DatePickerCtrl, this would create an e= ndless + # recursion. We avoid this here. + + if not self.propagating_event: + event.Skip() + + # ------------------------------------------------------------------= ------- + + def OnText(self, event): + + # wxDatePickerCtrl's EVT_TEXT handler sends bogus EVT_DATE_CHANG= ED + # events around. We avoid this here. + + pass + + # ------------------------------------------------------------------= ------- + + def GetText(self): + + if 'wxMSW' in wx.PlatformInfo: + date =3D self.GetValue() + if date.IsOk(): + return date.FormatDate() + else: + return u"" + else: + return self.combo.GetValue() + + # ------------------------------------------------------------------= ------- + + def SetText(self, text): + + # Don't call SetValue() if the value hasn't really changed, sinc= e this + # function messes with the cursor position and the selection, an= d under + # Windows, we have no way to restore the cursor. + if text !=3D self.GetText(): + if 'wxMSW' in wx.PlatformInfo: + date =3D wx.DateTime() + date.ParseFormat(text, '%x') + self.SetValue(date) + else: + self.combo.SetValue(text) + + # ------------------------------------------------------------------= ------- + + def GetBackgroundColour(self, *args, **kwargs): + + if 'wxMSW' in wx.PlatformInfo: + return wx.DatePickerCtrl.GetBackgroundColour(self, *args, **= kwargs) + else: + return self.combo.GetTextCtrl().GetBackgroundColour(*args, *= *kwargs) + + # ------------------------------------------------------------------= ------- + + def SetBackgroundColour(self, *args, **kwargs): + + =20 + if 'wxMSW' in wx.PlatformInfo: + return wx.DatePickerCtrl.SetBackgroundColour(self, *args, **= kwargs) + else: + return self.combo.GetTextCtrl().SetBackgroundColour(*args, *= *kwargs) + + # ------------------------------------------------------------------= ------- + + def SetSelection(self, *args, **kwargs): + + if not 'wxMSW' in wx.PlatformInfo: + return self.combo.GetTextCtrl().SetSelection(*args, **kwargs= ) + + # ------------------------------------------------------------------= ------- + + def GetInsertionPoint(self, *args, **kwargs): + + return self.combo.GetTextCtrl().GetInsertionPoint(*args, **kwarg= s) + + # ------------------------------------------------------------------= ------- + + def SetInsertionPoint(self, *args, **kwargs): + + if not 'wxMSW' in wx.PlatformInfo: + return self.combo.GetTextCtrl().SetInsertionPoint(*args, **k= wargs) + +# =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D # Configuration # =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D =20 Property changes on: trunk/gnue-forms/src/uidrivers/wx/widgets/entry.py ___________________________________________________________________ Name: svn:executable + *