Added BoolProperty and StringProperty
authorW. Trevor King <wking@drexel.edu>
Thu, 29 Jul 2010 16:08:23 +0000 (12:08 -0400)
committerW. Trevor King <wking@drexel.edu>
Thu, 29 Jul 2010 16:08:23 +0000 (12:08 -0400)
A grep through hooke/plugins/ shows what we need to implement.
I've checked the completed properties with '+'.

  $ grep 'type=' hooke/plugin/*.py | sed -n "s/.* type='\([^']*\)'.*/\1/p" | sort | uniq -c
 +    8 bool
      2 curve
      3 dict
      1 driver
      5 file
      7 float
      1 function
      1 glob
 +   22 int
      3 object
      2 path
      1 playlist
      1 point
 +    6 string

hooke/ui/gui/panel/propertyeditor2.py

index f361a371de931b20002dab006b8b90e06d271b06..90eb32ad313a96ba448de660610a2d13b62172be 100644 (file)
@@ -36,21 +36,77 @@ class Property (object):
         self.help = help\r
 \r
     def get_editor(self):\r
-        """Return a wx.Window instance containing a suitable editor.\r
-\r
-        Retains a reference to the returned editory as `._editor`.\r
+        """Return a suitable grid editor.\r
         """\r
         raise NotImplementedError()\r
 \r
-    def value_string(self, value):\r
+    def get_renderer(self):\r
+        """Return a suitable grid renderer.\r
+\r
+        Returns `None` if no special renderer is required.\r
+        """\r
+        return None\r
+\r
+    def string_for_value(self, value):\r
         """Return a string representation of `value` for loading the table.\r
         """\r
         return str(value)\r
 \r
-    def get_value(self):\r
-        """Return the value of `._editor`.\r
+    def value_for_string(self, string):\r
+        """Return the value represented by `string`.\r
         """\r
-        raise NotImplementedError()\r
+        return string\r
+\r
+\r
+class StringProperty (Property):\r
+    def __init__(self, **kwargs):\r
+        assert 'type' not in kwargs, kwargs\r
+        if 'default' not in kwargs:\r
+            kwargs['default'] = 0\r
+        super(StringProperty, self).__init__(type='string', **kwargs)\r
+\r
+    def get_editor(self):\r
+        return wx.grid.GridCellTextEditor()\r
+\r
+    def get_renderer(self):\r
+        return wx.grid.GridCellStringRenderer()\r
+\r
+\r
+class BoolProperty (Property):\r
+    """A boolean property.\r
+\r
+    Notes\r
+    -----\r
+    Unfortunately, changing a boolean property takes two clicks:\r
+\r
+    1) create the editor\r
+    2) change the value\r
+\r
+    There are `ways around this`_, but it's not pretty.\r
+\r
+    .. _ways around this:\r
+      http://wiki.wxpython.org/Change%20wxGrid%20CheckBox%20with%20one%20click\r
+    """\r
+    def __init__(self, **kwargs):\r
+        assert 'type' not in kwargs, kwargs\r
+        if 'default' not in kwargs:\r
+            kwargs['default'] = True\r
+        super(BoolProperty, self).__init__(type='bool', **kwargs)\r
+\r
+    def get_editor(self):\r
+        return wx.grid.GridCellBoolEditor()\r
+        #return wx.grid.GridCellChoiceEditor(choices=['true', 'false'])\r
+\r
+    def get_renderer(self):\r
+        return wx.grid.GridCellBoolRenderer()\r
+\r
+    def string_for_value(self, value):\r
+        if value == True:\r
+            return '1'\r
+        return ''\r
+\r
+    def value_for_string(self, string):\r
+        return string == '1'\r
 \r
 \r
 class IntProperty (Property):\r
@@ -61,11 +117,13 @@ class IntProperty (Property):
         super(IntProperty, self).__init__(type='int', **kwargs)\r
 \r
     def get_editor(self):\r
-        self._editor = wx.grid.GridCellNumberEditor()\r
-        return self._editor\r
+        return wx.grid.GridCellNumberEditor()\r
 \r
-    def get_value(self):\r
-        raise int(self._editor.GetValue())\r
+    def get_renderer(self):\r
+        return wx.grid.GridCellNumberRenderer()\r
+\r
+    def value_for_string(self, string):\r
+        return int(string)\r
 \r
 \r
 #class PyFilesProperty(wxpg.PyArrayStringProperty):\r
@@ -323,6 +381,17 @@ class PropertyPanel(Panel, wx.grid.Grid):
         self._last_tooltip = None\r
         self.GetGridWindow().Bind(wx.EVT_MOTION, self._on_mouse_over)\r
 \r
+        # add example properties for testing\r
+        self.append_property(StringProperty(\r
+                label='my string',\r
+                default='hithere',\r
+                help='help for my string',\r
+                ))\r
+        self.append_property(BoolProperty(\r
+                label='my bool',\r
+                default=True,\r
+                help='help for my bool',\r
+                ))\r
         self.append_property(IntProperty(\r
                 label='my int',\r
                 default=5,\r
@@ -352,123 +421,42 @@ class PropertyPanel(Panel, wx.grid.Grid):
         if msg != self._last_tooltip:\r
             self._last_tooltip = msg\r
             event.GetEventObject().SetToolTipString(msg)\r
+            self._get_values()  # for testing\r
 \r
     def append_property(self, property):\r
-        if len([p for p in self._properties if p.label == label]) > 0:\r
+        if len([p for p in self._properties if p.label == property.label]) > 0:\r
             raise ValueError(property)  # property.label collision\r
         self._properties.append(property)\r
         row = len(self._properties) - 1\r
         self.AppendRows(numRows=1)\r
         self.SetRowLabelValue(row, property.label)\r
         self.SetCellEditor(row=row, col=0, editor=property.get_editor())\r
+        r = property.get_renderer()\r
+        if r != None:\r
+            self.SetCellRenderer(row=row, col=0, renderer=r)\r
         self.set_property(property.label, property.default)\r
 \r
     def set_property(self, label, value):\r
+        row,property = self._property_by_label(label)\r
+        self.SetCellValue(row=row, col=0, s=property.string_for_value(value))\r
+\r
+    def get_property(self, label):\r
+        row,property = self._property_by_label(label)\r
+        string = self.GetCellValue(row=row, col=0)\r
+        return property.value_for_string(string)\r
+\r
+    def remove_property(self, label):\r
+        row,property = self._property_by_label(label)\r
+        raise NotImplementedError()\r
+\r
+    def _property_by_label(self, label):\r
         props = [(i,p) for i,p in enumerate(self._properties)\r
                  if p.label == label]\r
         assert len(props) == 1, props\r
         row,property = props[0]\r
-        self.SetCellValue(row=row, col=0, s=property.value_string(value))\r
+        return (row, property)\r
 \r
-    def remove_property(self, property):\r
-        pass\r
-\r
-    def GetPropertyValues(self):\r
-        raise NotImplementedError()\r
-        return self.pg.GetPropertyValues()\r
-\r
-    def Initialize(self, properties):\r
-        raise NotImplementedError()\r
-        pg = self.pg\r
-        pg.Clear()\r
-\r
-        if properties:\r
-            for element in properties:\r
-                if element[1]['type'] == 'arraystring':\r
-                    elements = element[1]['elements']\r
-                    if 'value' in element[1]:\r
-                        property_value = element[1]['value']\r
-                    else: \r
-                       property_value = element[1]['default']\r
-                    #retrieve individual strings\r
-                    property_value = split(property_value, ' ')\r
-                    #remove " delimiters\r
-                    values = [value.strip('"') for value in property_value]\r
-                    pg.Append(wxpg.ArrayStringProperty(element[0], value=values))\r
-\r
-                if element[1]['type'] == 'boolean':\r
-                    if 'value' in element[1]:\r
-                        property_value = element[1].as_bool('value')\r
-                    else:\r
-                        property_value = element[1].as_bool('default')\r
-                    property_control = wxpg.BoolProperty(element[0], value=property_value)\r
-                    pg.Append(property_control)\r
-                    pg.SetPropertyAttribute(element[0], 'UseCheckbox', True)\r
-\r
-                #if element[0] == 'category':\r
-                    #pg.Append(wxpg.PropertyCategory(element[1]))\r
-\r
-                if element[1]['type'] == 'color':\r
-                    if 'value' in element[1]:\r
-                        property_value = element[1]['value']\r
-                    else:\r
-                        property_value = element[1]['default']\r
-                    property_value = eval(property_value)\r
-                    pg.Append(wxpg.ColourProperty(element[0], value=property_value))\r
-\r
-                if element[1]['type'] == 'enum':\r
-                    elements = element[1]['elements']\r
-                    if 'value' in element[1]:\r
-                        property_value = element[1]['value']\r
-                    else:\r
-                        property_value = element[1]['default']\r
-                    pg.Append(wxpg.EnumProperty(element[0], element[0], elements, [], elements.index(property_value)))\r
-\r
-                if element[1]['type'] == 'filename':\r
-                    if 'value' in element[1]:\r
-                        property_value = element[1]['value']\r
-                    else:\r
-                        property_value = element[1]['default']\r
-                    pg.Append(wxpg.FileProperty(element[0], value=property_value))\r
-\r
-                if element[1]['type'] == 'float':\r
-                    if 'value' in element[1]:\r
-                        property_value = element[1].as_float('value')\r
-                    else:\r
-                        property_value = element[1].as_float('default')\r
-                    property_control = wxpg.FloatProperty(element[0], value=property_value)\r
-                    pg.Append(property_control)\r
-\r
-                if element[1]['type'] == 'folder':\r
-                    if 'value' in element[1]:\r
-                        property_value = element[1]['value']\r
-                    else:\r
-                        property_value = element[1]['default']\r
-                    pg.Append(wxpg.DirProperty(element[0], value=property_value))\r
-\r
-                if element[1]['type'] == 'integer':\r
-                    if 'value' in element[1]:\r
-                        property_value = element[1].as_int('value')\r
-                    else:\r
-                        property_value = element[1].as_int('default')\r
-                    property_control = wxpg.IntProperty(element[0], value=property_value)\r
-                    if 'maximum' in element[1]:\r
-                        property_control.SetAttribute('Max', element[1].as_int('maximum'))\r
-                    if 'minimum' in element[1]:\r
-                        property_control.SetAttribute('Min', element[1].as_int('minimum'))\r
-                    property_control.SetAttribute('Wrap', True)\r
-                    pg.Append(property_control)\r
-                    pg.SetPropertyEditor(element[0], 'SpinCtrl')\r
-\r
-                if element[1]['type'] == 'string':\r
-                    if 'value' in element[1]:\r
-                        property_value = element[1]['value']\r
-                    else:\r
-                        property_value = element[1]['default']\r
-                    pg.Append(wxpg.StringProperty(element[0], value=property_value))\r
-\r
-        pg.Refresh()\r
-\r
-    def OnReserved(self, event):\r
-        raise NotImplementedError()\r
-        pass\r
+    def _get_values(self):  # for testing\r
+        for property in self._properties:\r
+            v = self.get_property(property.label)\r
+            print property.label, property.type, type(v), v\r