Phil Wallach

I follow where my mind leads …

Phil Wallach header image 2

OpenLaszlo: a way to propagate context menus

July 27th, 2007 · 2 Comments · OpenLaszlo

In OpenLaszlo context menus are attached to a single view. If an object on the screen is composed from multiple views the context menu must be attach to each of these views. This was a problem for me because I had screen objects composed from over 20 views each, and assigning a context menu to each of those views was going to make my code both ugly and bug prone.

My solution was to create classes that automatically inherit their context menu from their parent. These classes are shown below.

I used a timer because

  • views are initialised from the bottom up, so children are inited before their parents
  • I use ‘initstage=”defer”‘ extensively so I need to wait until something happens.
  • For views …

      <class name="view_cm">
        <handler name="oninit">
          this.focusDelegate = new LzDelegate(this,
              
    "cm_callback");
          LzTimer.addTimer(this.focusDelegate, 100);
        </handler>
        <method name="cm_callback">
          if (parent.isinited)
          {
            var cm = parent.getContextMenu();
            if (cm != null)
            {
              this.setContextMenu(parent.getContextMenu());
              return;
            }
          }
          this.focusDelegate = new LzDelegate(this,
              "cm_callback");
          LzTimer.addTimer(this.focusDelegate, 100);
        </method>
      </class>
    

    For text …

      <class name="text_cm" extends="text">
        <handler name="oninit">
          this.focusDelegate = new LzDelegate(this,
              "cm_callback");
          LzTimer.addTimer(this.focusDelegate, 100);
        </handler>
        <method name="cm_callback">
          if (parent.isinited)
          {
            var cm = parent.getContextMenu();
            if (cm != null)
            {
              this.setContextMenu(parent.getContextMenu());
              return;
            }
          }
          this.focusDelegate = new LzDelegate(this,
              
    "cm_callback");
          LzTimer.addTimer(this.focusDelegate, 100);
        </method>
      </class>

    The last class is used for views containing images. If you try and attach a context menu to a view with no background or movieclip, a warning is issued. I like my code warning free, so this class waits for the onload event before trying to set the context menu.

      <class name="view_cm_load">
        <handler name="onload">
          this.focusDelegate = new LzDelegate(this,
              "cm_callback");
          LzTimer.addTimer(this.focusDelegate, 100);
        </handler>
        <method name="cm_callback">
            if (parent.isinited &&
                this.getAttribute('resource') != null)
            {
              var cm = parent.getContextMenu();
              if (cm != null)
              {
                this.setContextMenu(parent.getContextMenu());
                return;
              }
            }
            this.focusDelegate = new LzDelegate(this,
                "cm_callback");
            LzTimer.addTimer(this.focusDelegate, 100);
          </method>
      </class>
    

    Using these classes is as simple a changing view, class (extends) and text declarations as required e.g. from “<view … />” to “<view_cm … />”. The rest of the code is untouched.

    The above classes are something I dreamed up to solve a particular problem I had. I would be interested in any improvements or alternative approaches.

    RESOURCES

    OpenLaszlo: building context menus

    Tags:

    2 Comments so far ↓

    • kin lam

      thanks Phil. I was wondering how to add a context menu to a list of inputtext and have stumbled upon your example. It probably save me couple days to trials and errors

    • chuckgom

      looks great, thanks Phil !

    Leave a Comment