Creating A New Mode

Tags: #<Tag:0x00007f3637ca4b98> #<Tag:0x00007f3637ca4ad0>

Hi,
Following on from my first question here I am trying to create a new ‘Select’ mode but am having some difficulty in understanding how a new mode is registered.

According to the code comment in ‘ModeRegistry’ is I need to define ‘ACTION_NAME’ with a name that matches an Action defined in ‘resources.xml’. So basing my code on the ‘FreehandMode’ I created this basic class:

class SelectMode(gui.mode.BrushworkModeMixin, gui.mode.ScrollableModeMixin, gui.mode.InteractionMode):
ACTION_NAME = 'SelectMode'
permitted_switch_actions = set()

_OPTIONS_WIDGET = None

IS_LIVE_UPDATEABLE = True

MOTION_QUEUE_PRIORITY = GLib.PRIORITY_DEFAULT_IDLE

def __init__(self, ignore_modifiers=True, **args):
    super(SelectMode, self).__init__(**args)
    logger.info("Select initialised.")
    self.cursor_hidden_tdws = set()

pointer_behavior = gui.mode.Behavior.PAINT_LINE
scroll_behavior = gui.mode.Behavior.CHANGE_VIEW

@classmethod
def get_name(cls):
    return _(u"Select an Area")

def get_usage(self):
    return _(u"Select an area of the canvas")

def button_press_cb(self, tdw, event):
    logger.info("Button pressed.")
    super().button_press_cb(tdw, event)

def button_release_cb(self, tdw, event):
    logger.info("Button released.")
    super().button_release_cb(tdw, event)

I then added the following to ‘resources.xml’

<object class="GtkAction" id="SelectMode">
          <property name="label" translatable="yes" context="Menu→File (labels), Accel Editor (labels)">Select</property>
          <property name="short-label" translatable="yes" context="Toolbar (short labels)">Select</property>
          <property name="tooltip" translatable="yes" context="Toolbar (tooltips), Accel Editor (descriptions)">Select a rectangular area of canvas.</property>
          <signal name="activate" handler="mode_flip_action_activated_cb" />
        </object>

I also add a ‘menuitem’ to ‘menu.xml’ and that gets me a menu option under ‘Edit’ however my ‘SelectMode’ class never seems to get instantiated and the button callbacks are never called. I’ve confirmed this by adding a logging statement to L114 on ‘mode.py’ where new is defined and I never see ‘SelectMode’ logged. I have also tried to ‘break’ an existing mode by changing it’s ACTION_NAME, but I always see it being registered.

  1. Are there additional steps I need to do to register a mode?
  2. I note that there are ‘Flip’ and normal modes and I am not sure which I should register … possibly both? I am guessing the difference is something to do with one being related to a button on the tool bar and the other within the menus.

If your new class is defined in a new module, you will need to import that module in gui/application.py in order for the mode to be registered.

As for the flip versions of the actions, you need those to be defined in resources.xml as well. Take a look at how it’s done for e.g. FreeHand.

The flip action callback handler (which you currently use in your new action) has a comment explaining what flip actions are used for:

Thanks jpll,
I see my mode gets registered now once i have imported the module into gui/application.py - but out of curiosity and apologies if this is a pretty basic question, how are the other modes registered as I see no explicit imports for them in gui/application.py?

Not a basic question at all. Some of the modes are registered indirectly via imports in gui/document.py and maybe a couple of other places.

I’m not a huge fan of the registration magic myself. At some point we will probably have to move away from the use of GtkActions (which have been deprecated for a long time) and then it’s probably worth rethinking the overall structure.

Ok, as I am not too familiar with Python I did wonder if imports work differently than say Java which I am more familiar with. Thanks for the help.