commit-gnue
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[gnue] r10270 - in trunk/gnue-forms: . src/uidrivers/wx/widgets


From: reinhard
Subject: [gnue] r10270 - in trunk/gnue-forms: . src/uidrivers/wx/widgets
Date: Sun, 12 Dec 2010 15:50:36 -0600 (CST)

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 can
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üller <address@hidden>
properties: 
        branch-nick: forms

   + timestamp: 2010-12-11 17:52:20.673000097 +0100
committer: Reinhard Müller <address@hidden>
properties: 
        branch-nick: forms

Name: bzr:file-ids
   - src/GFObjects/GFBlock.py   
address@hidden:trunk%2Fgnue-forms:src%2FGFObjects%2FGFBlock.py

   + src/uidrivers/wx/widgets/entry.py  
address@hidden:trunk%2Fgnue-forms:src%2Fuidrivers%2Fwx%2Fwidgets%2Fentry.py

Name: bzr:revision-id:v4
   - 3116 address@hidden
3117 address@hidden
3118 address@hidden
3119 address@hidden
3120 address@hidden
3121 address@hidden
3122 address@hidden
3123 address@hidden
3124 address@hidden
3125 address@hidden
3126 address@hidden
3127 address@hidden
3128 address@hidden
3129 address@hidden
3130 address@hidden
3131 address@hidden
3132 address@hidden
3133 address@hidden
3134 address@hidden
3135 address@hidden
3136 address@hidden
3137 address@hidden
3138 address@hidden
3139 address@hidden
3140 address@hidden
3141 address@hidden
3142 address@hidden
3143 address@hidden
3144 address@hidden
3145 address@hidden
3146 address@hidden
3147 address@hidden
3148 address@hidden
3149 address@hidden
3150 address@hidden
3151 address@hidden
3152 address@hidden
3153 address@hidden
3154 address@hidden
3155 address@hidden
3156 address@hidden
3157 address@hidden
3158 address@hidden
3159 address@hidden
3160 address@hidden
3161 address@hidden
3162 address@hidden
3163 address@hidden
3164 address@hidden
3165 address@hidden
3166 address@hidden
3167 address@hidden
3168 address@hidden
3169 address@hidden
3170 address@hidden
3171 address@hidden
3172 address@hidden
3173 address@hidden
3174 address@hidden
3175 address@hidden

   + 3116 address@hidden
3117 address@hidden
3118 address@hidden
3119 address@hidden
3120 address@hidden
3121 address@hidden
3122 address@hidden
3123 address@hidden
3124 address@hidden
3125 address@hidden
3126 address@hidden
3127 address@hidden
3128 address@hidden
3129 address@hidden
3130 address@hidden
3131 address@hidden
3132 address@hidden
3133 address@hidden
3134 address@hidden
3135 address@hidden
3136 address@hidden
3137 address@hidden
3138 address@hidden
3139 address@hidden
3140 address@hidden
3141 address@hidden
3142 address@hidden
3143 address@hidden
3144 address@hidden
3145 address@hidden
3146 address@hidden
3147 address@hidden
3148 address@hidden
3149 address@hidden
3150 address@hidden
3151 address@hidden
3152 address@hidden
3153 address@hidden
3154 address@hidden
3155 address@hidden
3156 address@hidden
3157 address@hidden
3158 address@hidden
3159 address@hidden
3160 address@hidden
3161 address@hidden
3162 address@hidden
3163 address@hidden
3164 address@hidden
3165 address@hidden
3166 address@hidden
3167 address@hidden
3168 address@hidden
3169 address@hidden
3170 address@hidden
3171 address@hidden
3172 address@hidden
3173 address@hidden
3174 address@hidden
3175 address@hidden
3176 address@hidden

Name: bzr:text-parents
   - src/GFObjects/GFBlock.py   address@hidden

   + src/uidrivers/wx/widgets/entry.py  address@hidden


Modified: trunk/gnue-forms/src/uidrivers/wx/widgets/entry.py
===================================================================
--- trunk/gnue-forms/src/uidrivers/wx/widgets/entry.py  2010-12-12 21:50:33 UTC 
(rev 10269)
+++ trunk/gnue-forms/src/uidrivers/wx/widgets/entry.py  2010-12-12 21:50:36 UTC 
(rev 10270)
@@ -24,8 +24,10 @@
 Implementation of the <entry> tag
 """
 
+import locale
 import os
 import wx
+import wx.combo
 
 from gnue.forms.uidrivers.wx.widgets import _base
 from gnue.forms.input import GFKeyMapper
@@ -85,28 +87,34 @@
 
     def __build_default(self, parent, password=False, multiline=False):
 
-        xFlags = wx.TE_PROCESS_TAB
+        if multiline and not self.managed:
+            self.__border = self._uiDriver.control_border('default')
 
-        if password:
-            xFlags |= wx.TE_PASSWORD
-
-        if multiline:
-            xFlags |= wx.TE_MULTILINE
-        else:
-            xFlags |= wx.TE_PROCESS_ENTER
-
-        # Right-align numeric fields.  This does work on wxMSW and wxGTK only.
         if self._gfObject._field.datatype == 'number':
-            xFlags |= wx.TE_RIGHT
+            style = wx.CB_DROPDOWN
+            ctrl = NumberEntryCtrl(parent, style=style)
 
-        if multiline and not self.managed:
-            self.__border = self._uiDriver.control_border('default')
+        elif self._gfObject._field.datatype == 'date':
+            style = wx.DP_DROPDOWN | wx.DP_ALLOWNONE
+            ctrl = DatePickerCtrl(parent, style=style)
 
-        ctrl = wx.TextCtrl(parent, -1, style=xFlags)
+        else:
+            style = wx.TE_PROCESS_TAB
+            if password:
+                style |= wx.TE_PASSWORD
+            if multiline:
+                style |= wx.TE_MULTILINE
+            else:
+                style |= wx.TE_PROCESS_ENTER
+            ctrl = wx.TextCtrl(parent, style=style)
 
         self.__set_size(ctrl)
 
-        ctrl.Bind(wx.EVT_TEXT, self.__on_text_changed)
+        if isinstance(ctrl, DatePickerCtrl):
+            ctrl.Bind(wx.EVT_DATE_CHANGED, self.__on_datepicker_date_changed)
+            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)
 
+        event.Skip()                
+
     # -------------------------------------------------------------------------
 
     def __on_mac_choice_clicked(self, event):
@@ -345,6 +355,23 @@
 
     # -------------------------------------------------------------------------
 
+    def __on_datepicker_date_changed(self, event):
+
+        widget = event.GetEventObject()
+
+        self._request('REPLACEVALUE', text=widget.GetText())
+
+    # -------------------------------------------------------------------------
+
+    def __on_datepicker_text(self, event):
+
+        widget = event.GetEventObject()
+
+        self._request('REPLACEVALUE', text=widget.GetValue(),
+                position=widget.GetInsertionPoint())
+
+    # -------------------------------------------------------------------------
+
     def __on_gtk_text_changed(self, event):
 
         # FIXME: workaround for issue-144.  Setting a selection within an
@@ -406,6 +433,12 @@
                 event.Skip()
                 return
 
+        # Let Windows' date picker handle up/down.
+        if 'wxMSW' in wx.PlatformInfo and isinstance(control, DatePickerCtrl):
+            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 == 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)
 
@@ -602,6 +637,10 @@
             # Take care: SetSelection in a ListBox sets the selected item!
             pass
 
+        elif isinstance(widget, DatePickerCtrl) and 'wxMSW' in wx.PlatformInfo:
+            # Windows' native DatePickerCtrl doesn't have a selection.
+            pass
+        
         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 how to
             # determine the real border width in wx.
-            if self._gfObject.style.lower() == 'dropdown':
+            if isinstance (control, wx.ComboBox) \
+                    or isinstance (control, NumberEntryCtrl) \
+                    or isinstance (control, DatePickerCtrl):
                 min_w += 4
                 if max_w:
                     max_w += 4
@@ -826,6 +867,271 @@
 
 
 # =============================================================================
+# Number Entry Control
+# =============================================================================
+
+class NumberEntryCtrl(wx.combo.ComboCtrl):
+
+    def __init__(self, *args, **kwargs):
+
+        wx.combo.ComboCtrl.__init__(self, *args, **kwargs)
+
+        popup = NumberEntryPopup()
+        popup.TextCtrl = self.GetTextCtrl()
+        self.SetPopupControl(popup)
+
+        # In wxWidgets 2.8, wxComboCtrl receives the EVT_SET_FOCUS events 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 require
+        # higher versions of wxWidgets.
+        self.GetTextCtrl().Bind(wx.EVT_KILL_FOCUS, self.OnKillFocus)
+
+    # -------------------------------------------------------------------------
+
+    def OnKillFocus(self, event):
+
+        e = 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)
+
+# =============================================================================
+
+class NumberEntryPopup(wx.combo.ComboPopup):
+
+    def Create(self, parent, *args, **kwargs):
+
+        wx.combo.ComboPopup.Create(self, parent, *args, **kwargs)
+
+        self.panel = wx.Panel(parent, style=wx.BORDER_SIMPLE)
+
+        radixc = u" " + locale.localeconv()['decimal_point'] + u" "
+
+        self.b1 = wx.Button(self.panel, label=u" 1 ", style=wx.BU_EXACTFIT)
+        self.b2 = wx.Button(self.panel, label=u" 2 ", style=wx.BU_EXACTFIT)
+        self.b3 = wx.Button(self.panel, label=u" 3 ", style=wx.BU_EXACTFIT)
+        self.b4 = wx.Button(self.panel, label=u" 4 ", style=wx.BU_EXACTFIT)
+        self.b5 = wx.Button(self.panel, label=u" 5 ", style=wx.BU_EXACTFIT)
+        self.b6 = wx.Button(self.panel, label=u" 6 ", style=wx.BU_EXACTFIT)
+        self.b7 = wx.Button(self.panel, label=u" 7 ", style=wx.BU_EXACTFIT)
+        self.b8 = wx.Button(self.panel, label=u" 8 ", style=wx.BU_EXACTFIT)
+        self.b9 = wx.Button(self.panel, label=u" 9 ", style=wx.BU_EXACTFIT)
+        self.b0 = wx.Button(self.panel, label=u" 0 ", style=wx.BU_EXACTFIT)
+        self.br = wx.Button(self.panel, label=radixc, style=wx.BU_EXACTFIT)
+        self.bx = wx.Button(self.panel, label=u" x ", style=wx.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 = wx.GridSizer(rows=4, cols=3)
+        box.Add(self.b1, flag=wx.EXPAND)
+        box.Add(self.b2, flag=wx.EXPAND)
+        box.Add(self.b3, flag=wx.EXPAND)
+        box.Add(self.b4, flag=wx.EXPAND)
+        box.Add(self.b5, flag=wx.EXPAND)
+        box.Add(self.b6, flag=wx.EXPAND)
+        box.Add(self.b7, flag=wx.EXPAND)
+        box.Add(self.b8, flag=wx.EXPAND)
+        box.Add(self.b9, flag=wx.EXPAND)
+        box.Add(self.b0, flag=wx.EXPAND)
+        box.Add(self.br, flag=wx.EXPAND)
+        box.Add(self.bx, flag=wx.EXPAND)
+        self.panel.SetSizerAndFit(box)
+
+    # -------------------------------------------------------------------------
+
+    def OnClick(self, event):
+
+        char = event.GetEventObject().GetLabel()[1:2]
+        if char == "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()
+
+
+# =============================================================================
+# Date Picker Control
+# =============================================================================
+
+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 breakage
+        # we try to fix here, so we just do nothing.
+        if 'wxMSW' in wx.PlatformInfo:
+            return
+        
+        self.combo = None
+
+        for child in self.GetChildren():
+            if isinstance (child, wx.combo.ComboCtrl):
+                self.combo = 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 = False
+
+    # -------------------------------------------------------------------------
+
+    def OnEvent(self, event):
+
+        self.propagating_event = True
+        try:
+            e = event.Clone()
+            e.SetEventObject(self)
+            self.GetEventHandler().ProcessEvent(e)
+        finally:
+            self.propagating_event = 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 endless
+        # 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_CHANGED
+        # events around.  We avoid this here.
+
+        pass
+
+    # -------------------------------------------------------------------------
+
+    def GetText(self):
+
+        if 'wxMSW' in wx.PlatformInfo:
+            date = 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, since this
+        # function messes with the cursor position and the selection, and under
+        # Windows, we have no way to restore the cursor.
+        if text != self.GetText():
+            if 'wxMSW' in wx.PlatformInfo:
+                date = 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):
+
+        
+        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, **kwargs)
+
+    # -------------------------------------------------------------------------
+
+    def SetInsertionPoint(self, *args, **kwargs):
+
+        if not 'wxMSW' in wx.PlatformInfo:
+            return self.combo.GetTextCtrl().SetInsertionPoint(*args, **kwargs)
+
+# =============================================================================
 # Configuration
 # =============================================================================
 


Property changes on: trunk/gnue-forms/src/uidrivers/wx/widgets/entry.py
___________________________________________________________________
Name: svn:executable
   + *




reply via email to

[Prev in Thread] Current Thread [Next in Thread]