Move key press extraction logic into actions module.
authorJosh Blum <josh@joshknows.com>
Sun, 13 Sep 2009 07:04:58 +0000 (00:04 -0700)
committerJosh Blum <josh@joshknows.com>
Sun, 13 Sep 2009 07:04:58 +0000 (00:04 -0700)
Replaced xml encode with gtk escape text.
Added templates for category and docs tool tips.
Other various code tweaks in gui modules.

grc/gui/ActionHandler.py
grc/gui/Actions.py
grc/gui/BlockTreeWindow.py
grc/gui/Utils.py

index 0d39ea5fd375c9e68aaab5c730767d5821012aa4..901619e69cb06f0867162f2a3ff668dcadea33e5 100644 (file)
@@ -79,16 +79,11 @@ class ActionHandler:
                When not in focus, gtk and the accelerators handle the the key press.
                @return false to let gtk handle the key action
                """
-               keyval, egroup, level, consumed = \
-                       gtk.gdk.keymap_get_default().translate_keyboard_state(
-                       event.hardware_keycode, event.state, event.group)
-               #extract action name from this key press
-               action_name = Actions.get_action_name_from_key_press(keyval, event.state & ~consumed)
-               #handle the action if flow graph is in focus
-               if action_name and self.get_focus_flag():
-                       self.handle_states(action_name)
-                       return True #handled by this method
-               return False #let gtk handle the key press
+               try: assert self.get_focus_flag()
+               except AssertionError: return False
+               try: self.handle_states(Actions.get_action_name_from_key_press(event))
+               except KeyError: return False
+               return True #handled by this method
 
        def _quit(self, window, event):
                """
@@ -100,13 +95,14 @@ class ActionHandler:
                self.handle_states(Actions.APPLICATION_QUIT)
                return True
 
-       def _handle_actions(self, event):
+       def _handle_actions(self, action):
                """
                Handle all of the activate signals from the gtk actions.
                The action signals derive from clicking on a toolbar or menu bar button.
                Forward the action to the state handler.
                """
-               self.handle_states(event.get_name())
+               self.handle_states(action.get_name())
+               return True
 
        def handle_states(self, state=''):
                """
index cacee22ce120d7529b85a9c836e0b8a0d9ab1673..531888ac1aa14e1b6a206b33701f91387cbf5772 100644 (file)
@@ -97,20 +97,23 @@ _actions_key_list = (
        (PORT_CONTROLLER_DEC,       gtk.keysyms.KP_Subtract, NO_MODS_MASK),
 )
 
-_actions_key_dict = dict(((key_val, mod_mask), action_name) for action_name, key_val, mod_mask in _actions_key_list)
-_used_mods_mask = reduce(lambda x, y: x | y, [mod_mask for action_name, key_val, mod_mask in _actions_key_list], NO_MODS_MASK)
-def get_action_name_from_key_press(key_val, mod_mask=NO_MODS_MASK):
+_actions_key_dict = dict(((keyval, mod_mask), action_name) for action_name, keyval, mod_mask in _actions_key_list)
+_used_mods_mask = reduce(lambda x, y: x | y, [mod_mask for action_name, keyval, mod_mask in _actions_key_list], NO_MODS_MASK)
+_keymap = gtk.gdk.keymap_get_default()
+def get_action_name_from_key_press(event):
        """
-       Get the action name associated with the key value and mask.
-       Both the key value and the mask have to match.
-       @param key_val the value of the key
-       @param mod_mask the key press mask (shift, ctrl) 0 for none
+       Get the action name associated with the key press event.
+       Both the key value and the mask must have a match.
+       @param event a gtk key press event
        @return the action name or blank string
        """
-       mod_mask &= _used_mods_mask #ignore irrelevant modifiers
-       key_val_mod_mask = (key_val, mod_mask)
-       try: return _actions_key_dict[key_val_mod_mask]
-       except KeyError: return ''
+       #extract the key value and the consumed modifiers
+       keyval, egroup, level, consumed = _keymap.translate_keyboard_state(
+               event.hardware_keycode, event.state, event.group)
+       #get the modifier mask and ignore irrelevant modifiers
+       mod_mask = event.state & ~consumed & _used_mods_mask
+       try: return _actions_key_dict[(keyval, mod_mask)]
+       except KeyError: raise KeyError, 'Keypress: "%s, %s" does not have an associated action'%(gtk.gdk.keyval_name(keyval), mod_mask)
 
 ######################################################################################################
 # Actions
@@ -143,7 +146,7 @@ _actions_list = (
 )
 def get_all_actions(): return _actions_list
 
-_actions_dict = dict((action.get_name(), action) for action in _actions_list)
+_actions_dict = dict((action.get_name(), action) for action in get_all_actions())
 def get_action_from_name(action_name):
        """
        Retrieve the action from the action list.
@@ -152,8 +155,8 @@ def get_action_from_name(action_name):
        @throw KeyError bad action name
        @return a gtk action object
        """
-       if action_name in _actions_dict: return _actions_dict[action_name]
-       raise KeyError('Action Name: "%s" does not exist'%action_name)
+       try: return _actions_dict[action_name]
+       except KeyError: raise KeyError, 'Action Name: "%s" does not exist'%action_name
 
 ######################################################################################################
 # Accelerators
@@ -163,10 +166,10 @@ def get_accel_group(): return _accel_group
 
 #set the accelerator group, and accelerator path
 #register the key name and mod mask with the accelerator path
-for action_name, key_val, mod_mask in _actions_key_list:
+for action_name, keyval, mod_mask in _actions_key_list:
        try:
                accel_path = '<main>/'+action_name
                get_action_from_name(action_name).set_accel_group(get_accel_group())
                get_action_from_name(action_name).set_accel_path(accel_path)
-               gtk.accel_map_add_entry(accel_path, key_val, mod_mask)
+               gtk.accel_map_add_entry(accel_path, keyval, mod_mask)
        except KeyError: pass #no action was created for this action name
index 379c4a6a25e04b0d2ca6db6431efa250cb1e4fab..5c5d21b640b13b4eacc38396c603c21c8c313ac1 100644 (file)
@@ -28,6 +28,15 @@ NAME_INDEX = 0
 KEY_INDEX = 1
 DOC_INDEX = 2
 
+DOC_MARKUP_TMPL="""\
+#if $doc
+$encode($doc)#slurp
+#else
+undocumented#slurp
+#end if"""
+
+CAT_MARKUP_TMPL="""Category: $cat"""
+
 class BlockTreeWindow(gtk.VBox):
        """The block selection panel."""
 
@@ -97,14 +106,14 @@ class BlockTreeWindow(gtk.VBox):
                                iter = self.treestore.insert_before(self._categories[sub_category[:-1]], None)
                                self.treestore.set_value(iter, NAME_INDEX, '[ %s ]'%cat_name)
                                self.treestore.set_value(iter, KEY_INDEX, '')
-                               self.treestore.set_value(iter, DOC_INDEX, Utils.xml_encode('Category: %s'%cat_name))
+                               self.treestore.set_value(iter, DOC_INDEX, Utils.parse_template(CAT_MARKUP_TMPL, cat=cat_name))
                                self._categories[sub_category] = iter
                #add block
                if block is None: return
                iter = self.treestore.insert_before(self._categories[category], None)
                self.treestore.set_value(iter, NAME_INDEX, block.get_name())
                self.treestore.set_value(iter, KEY_INDEX, block.get_key())
-               self.treestore.set_value(iter, DOC_INDEX, Utils.xml_encode(block.get_doc() or 'undocumented'))
+               self.treestore.set_value(iter, DOC_INDEX, Utils.parse_template(DOC_MARKUP_TMPL, doc=block.get_doc()))
 
        ############################################################
        ## Helper Methods
index ee6dc6cdc4aa2a62cddc7bc5d6a1ecce71bba496..83036a4b858c0c4eb5460738be7eb2f3e4002e6d 100644 (file)
@@ -19,6 +19,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 
 from Constants import POSSIBLE_ROTATIONS
 from Cheetah.Template import Template
+import gobject
 
 def get_rotated_coordinate(coor, rotation):
        """
@@ -54,23 +55,6 @@ def get_angle_from_coordinates((x1,y1), (x2,y2)):
                if y2 > y1: return 270
                else: return 90
 
-def xml_encode(string):
-       """
-       Encode a string into an xml safe string by replacing special characters.
-       Needed for gtk pango markup in labels.
-       @param string the input string
-       @return output string with safe characters
-       """
-       string = str(string)
-       for char, safe in (
-                       ('&', '&amp;'),
-                       ('<', '&lt;'),
-                       ('>', '&gt;'),
-                       ('"', '&quot;'),
-                       ("'", '&apos;'),
-       ): string = string.replace(char, safe)
-       return string
-
 def parse_template(tmpl_str, **kwargs):
        """
        Parse the template string with the given args.
@@ -78,5 +62,5 @@ def parse_template(tmpl_str, **kwargs):
        @param tmpl_str the template as a string
        @return a string of the parsed template
        """
-       kwargs['encode'] = xml_encode
+       kwargs['encode'] = gobject.markup_escape_text
        return str(Template(tmpl_str, kwargs))