Skip to the content.

Layout tag: context

Create a context menu, a popup menu.

A context menu is a menu that will pop up, usually in response to a right click (hence the name), though context menus can be more generic than that. They can be used for pop-up menus (appear when the user presses a button, for instance).

<context id=right>
  ...
</context>

Usage

Like dialogs, context menus are generated dynamically in response to a control. It is, however, necessary to register them in the window layout, even though they don’t “appear” on the screen before they’re actually popped up.

Register a context menu

To register a context menu, use the <context> tag as a direct child of a window.

<window title="Show context menu usage">
  <!-- A menu bar perhaps here -->
  <context id=right>
    <item>Cut</item>
    <item>Copy</item>
    <item>Paste</item>
    <menu name="Paste Special">
      <item>Mix...</item>
      <item>Merge...</item>
    </menu>
    <item>Property...</item>
  </context>

  <!-- The window grid... -->
</window>

To register a context menu, we place a <context> tag as a direct child of the window tag. We give it a mandatory identifier (ID). Inside of the context tag, we use items to represent choices and menus to represent sub-menus.

Defining a context menu in layout will not pop anything on the screen. This is just a way to register the menu, but you’ll have to pop it.

Pop it up

After a menu has been registered and assigned an ID, you can easily pop it in response to a user action, in control methods:

class TestContextMenu(Window):

    layout = mark("""
       # Insert the layout in the previous section...
   """)

    def on_right_click(self):
        """The user has right clicked anywhere on the window."""
        # We use the context menu's identifier ("right")
        self.pop_menu("right")

And that’s it. The call to pop_menu will block until the user selects a choice. When that’s done, a control is fired and the menu closes.

How to intercept controls in this situation?

You will have defined control methods to intercept these choices. The following section offers a complete example:

Control methods and context menus

We take the same example as previously and intercept the user clicking on “Cut” and “Copy”.

class TestContextMenu(Window):

    layout = mark("""
        <window title="Show context menu usage">
          <!-- A menu bar perhaps here -->
          <context id=right>
            <item>Cut</item>
            <item id=ctx_copy>Copy</item>
            <item>Paste</item>
            <menu name="Paste Special">
              <item>Mix...</item>
              <item>Merge...</item>
            </menu>
            <item>Property...</item>
          </context>

          <!-- The window grid... -->
          <text x=2 y=2 width=3 id=result read-only>Result</text>
        </window>
    """)

    def on_right_click(self):
        """The user has right clicked anywhere on the window."""
        self.pop_menu("right")

    def on_cut(self):
        """The user has chosen "cut" in the context menu."""
        self["result"].value = "The user chose to Cut!"

    def on_ctx_copy(self):
        """The user has clicked on the "copy" menu item.
        (Note that this menu has a specific ID).
        """
        self["result"].value = "The user chose to Copy!"

It works because the context menu was registered beforehand and control methods were successfully connected to menu items. Notice that the note about identifiers in items also applies to items inside context menus: you might need to give them explicit IDs (like we did for the “Copy” item in the previous example) and adapt your control methods accordingly.

Attributes

Name Required Description Example
id Yes The context menu identifier (ID). Contrary to other widgets, an identifier is absolutely required, otherwise you won’t be able to pop this context menu in a control method. <context id=right>

id is the only mandatory attribute.

Data

This tag will be turned into a Context widget.

Attribute Meaning and type Example
id The ID (str). This attribute cannot be changed. cid = self.id

Controls

This widget has no control. Use the controls on menu items instead.