menu.lzx

<library>
    <include href="button.lzx"/>
    <include href="base/basescrollbar.lzx"/>
    <include href="lz/list.lzx"/>
    <include href="lz/textlistitem.lzx"/>
    <include href="lz/floatinglist.lzx"/>

    <!-- resources for menuarrow class -->
    <resource name="menuarrow_rsrc">
        <frame src="resources/menu/menu_arrow_rt.swf"/>
        <frame src="resources/menu/menu_arrow_lft.swf"/>
    </resource>

    <!-- LPP-3399 -->
    <class name="menutrackgroup" extends="basetrackgroup">
      <!--- @access private -->
      <method name="addSubview" args="sv">
        if( !(sv instanceof lz.menu) ){
          super.addSubview( sv );
        }
      </method>
    </class>

    <!-- class: menubar -->
    <class name="menubar" extends="basecomponent" focusable="false">
        <!--- @access private -->
        <attribute name="defaultplacement" value="mbarcontent" type="string"/>
        <!--- @access private -->
        <attribute name="height" value="20"/>
        <!--- in a window, the menubar's width  needs to extend one more pixel 
             past its container ( which has the same width as the content ) so
             it's default width is immediateparent.width + 1
             @access private -->
        <attribute name="width" value="${immediateparent.width + 1}"/>
        <!--- @access private -->
        <attribute name="_clickcounter" value="0"/>
        <!--- @access private -->
        <attribute name="_openedmenu" value="0"/>


        <!-- background views  -->
            <view name="_outerbezel" resource="lzbutton_bezel_outer_rsc" stretches="both" width="${parent.width-1}" height="${parent.height-1}"/>
            <view name="_innerbezel" resource="lzbutton_bezel_inner_rsc" stretches="both" x="1" y="1" width="${parent.width-3}" height="${parent.height-3}"/>
            <view name="_face" resource="lzbutton_face_rsc" stretches="both" x="2" y="2" width="${parent.width-4}" height="${parent.height-4}"/>

        <!-- a basetracker to hold and track the menuButtons when the mouse is 
             down -->
        <menutrackgroup name="mbarcontent" layout="axis:x; spacing:-2" deactivateevents="[]" height="100%"/>


        <!--- opens ( or closes ) requested menu and closes any other menus that are currently opened
              @param Menu menuref: the menu to be opened or closed
              @param Boolean openit: true to open menu, false to close it -->
        <method name="openMenu" args="menuref,openit"> 
            if ( menuref == this._openedmenu ){
                if ( openit ) return; // don't reopen menu if already opened
                else {
                    this._openedmenu._menubutton.showUp();
                    this._openedmenu.setOpen( false );
                    this._openedmenu = 0;

                    // deactiavte basetracker
                    this.mbarcontent.deactivateTrackgroup(null);

                    // set clickcounter back to zero
                    this._clickcounter = 0;
                    this._openedmenu = 0;
                }
            } else {
                // about to open/close a different menu so ...
                // close the previously opened menu
                if ( this._openedmenu ) {
                    this._openedmenu._menubutton.showUp();
                    this._openedmenu.close();
                }

                // now open/close requested menu
                if ( menuref != null) {
                    menuref.setOpen( openit );
                    if ( openit ) this._openedmenu = menuref
                } else this._openedmenu = 0

            }
        </method>

        <!--- @keywords private -->
        <method name="_applystyle" args="s">
            if (this.style != null) {
                setTint( _outerbezel, s.basecolor);
                setTint( _innerbezel, s.basecolor);
                setTint( _face, s.basecolor);
            }
        </method>

        <doc>
            <tag name="shortdesc">
                <text>A menubar that contains menus.</text>
            </tag>
            <text>
                <p>
                    The <tagname>menubar</tagname> tag creates a menubar that can be
                    placed within any view, but is most commonly found within a window.
                    By default, a menubar adjusts to the width of its parent unless
                    otherwise directed. Within a window a menubar has its own
                    <code>placement="menubar"</code> so that it lives above the contents
                    of the window.
                </p>
                <example>
                    
<canvas debug="true" height="250">
  <debug y="120"/>
  <menubar width="200" >
    <menu text="Menu 1" width="100">
      <menuitem text="Item 1" onselect="canvas.whichOne(this);"/>
      <menuitem text="Item 2" onselect="canvas.whichOne(this);"/>
      <menuitem text="Item 3" onselect="canvas.whichOne(this);"/>
      <menuseparator/>
      <menuitem text="Item 4" onselect="canvas.whichOne(this);"/>
    </menu>
    <menu text="Menu 2" width="100">
      <menuitem text="More items..." onselect="canvas.whichOne(this);"/>
    </menu>
  </menubar>

  <method name="whichOne" args="vThis">
    Debug.debug("%w - %w", vThis.parent.owner.text, vThis.text);
  </method>
</canvas>
                    
                </example>
            <p><b>See Also:</b></p>

              <ul>
                  <li>
                      <sgmltag class="element" role="lzCommand"><command></sgmltag>, <sgmltag class="element" role="lz.menu"><menu></sgmltag>, 
                      <sgmltag class="element" role="lz.menuitem"><menuitem></sgmltag> and <sgmltag class="element" role="lz.simplelayout"><menuseparator></sgmltag>
                  </li>
              </ul>
            </text>
        </doc>

    </class> <!-- end menubar -->

    <!-- An instance of this class automatically created when a menuitem has a submenu.-->
    <class name="menuarrow" resource="menuarrow_rsrc" x="${parent.width - width - 5}" y="5"/>

    <!-- An instance of this class automatically created when a menu is a subview
        of a menubar -->
    <class name="menubutton" extends="button" respondtomouseout="false" text="${this._menuref.text}" height="${parent.height}" doesenter="false" focusable="false">

        <!--- Reference to menu that created this button.
              @keywords private -->
        <attribute name="_menuref" value="null"/>

        <!--- this method is called to override the default event handling inherited
             from button @keywords private -->
        <method name="registerEventHandlers"> 
            // ignore the default event handling from the button class.
            // new event handling is defined in methods below.
         </method>

        <!--- @keywords private -->
        <handler name="onmousedown">
            // a menu button only exists within a menubar so
            // toggle menubar's clickcounter between 0 and 1
            this.parent._clickcounter += 1; // this.parent is a menubar
            if ( this.parent._clickcounter > 1 ) this.parent._clickcounter = 0;
            this.showDown();
        </handler>

        <!--- override the button's showDown method to also display the associated menu
              @keywords private -->
        <method name="showDown" args="sd=null">
            super.showDown();
            if ( this._menuref )
                parent.openMenu(this._menuref,true);
        </method>

        <!--- @keywords private -->
        <handler name="onmousetrackup">
            // on first click keep the button down
            // on second click treat it like a onmouseupinside for the button
            if ( this.parent._clickcounter == 0) {
                this.showOver();
                // close the menu associated with this menuitem
                if ( this._menuref )
                    parent.openMenu( this._menuref, false );
            }
        </handler>

        <!--- the showOver method is blocked because it responds to onclick. 
             this method effectively replaces that method  @keywords private-->
        <handler name="onmouseover">
            // if the clickcounter == 1 then a rollover action is like a
            // mousedown, otherwise do a normal rollover.
            if ( this.parent._clickcounter ) {
                this.showDown();
            } else {
                this.showOver();
            }
        </handler>

        <!--- @keywords private -->
        <handler name="onmouseout" method="showout"/>
        <method name="showout" args="ignore">
            if ( !this.parent._clickcounter ) {
                this.showUp();
            }
        </method>


        <!--- @keywords private -->
        <handler name="onmousetrackover">
            this.showDown();
        </handler>

        <!--- @keywords private -->
       <handler name="onmousetrackout">
            //this.myshowup();
        </handler>

        <!--- @keywords private -->
        <method name="toString">
           return "MENU BUTTON title =" + this.text;
       </method>

    </class> <!-- END menubutton -->

    <!-- A beveled line used to visually separate menu items -->
    <class name="menuseparator" width="100%" opacity="1" height="6" extends="basecomponent" focusable="false">

        <!--- the number of pixels to inset the menuseparartor from the sides of the menu -->
        <attribute name="xinset" value="3" type="number"/>

        <view x="${parent.xinset}" width="${parent.width - 2*parent.xinset}" bgcolor="black" height="1" y="3" opacity=".5"/>

        <view x="${parent.xinset}" width="${parent.width - 2*parent.xinset}" bgcolor="white" height="1" y="4"/>

        <!--- @keywords private -->
        <method name="_applystyle" args="s">
            if (this.style != null) {
                //parent.setAttribute('bgcolor',s.menuitembgcolor);
                this.setAttribute('bgcolor', s.textfieldcolor);
            }
        </method>

        <doc>
            <tag name="shortdesc"><text>
                A horizontal separator for pull-down menus.
            </text></tag>
            <text>
                <p>
                    The <classname>menuseparator</classname> tag provides a 
                    horizontal separator for pull-down menus. This tag must 
                    reside within a <xref linkend="lz.menu"/> tag.
                </p>
                <p>
                    For an example, see <xref linkend="lz.menu"/>.
                </p>
            <p><b>See Also:</b></p>

              <ul>
                  <li>
                     <sgmltag class="element" role="lz.menubar"><menubar></sgmltag>, <sgmltag class="element" role="lz.menu"><menu></sgmltag>
                     and <sgmltag class="element" role="lz.menuitem"><menuitem></sgmltag>
                  </li>
              </ul>

            </text>
        </doc>

    </class>


    <class name="menuitem" extends="textlistitem" focusable="false">

        <!--- @keywords private-->
        <attribute name="delaytime" value="300"/>

        <!--- the command object assigned to be executed when this menuitem is selected -->
        <attribute name="command" value="null" type="expression" setter="this.setCommand( command )" when="once"/>

        <!--- this event is sent to the menuitem when it is selected -->
        <event name="onselect"/>

        <!---  @keywords private -->
        <attribute name="_doshowsubmenu" value="false"/>

        <!---  @keywords private -->
        <attribute name="_submenu" value="null"/>

        <!---  @keywords private -->
        <attribute name="showsubmenu_del" value="null"/>

        <!---  @keywords private -->
        <attribute name="hidesubmenu_del" value="null"/>

        <state name="commandstate" applied="false">
            <text name="cmdkeys" x="${parent.width - 90}" y="${classroot.text_y}" width="90"/>
        </state>

        <!---  @keywords private -->
        <method name="init">
            super.init();
            // now that the menuitem is inited make sure the floatinglist
            // constraints are updated by resetting the attachtarget
            if ( this._submenu ) this._submenu.flist.setAttribute('attachtarget',this);
        </method>

         <!---  @keywords private -->
        <handler name="onmouseover">
            // listitem ( that menuitem extends) is resposible for the visual
            // changes when a menuitem is hilited.
            // If a menuitem also has a submenu then that is displayed by calling...
            if ( _submenu ) this._opensubmenu( true );
        </handler>

        <!--- @keywords private -->
        <handler name="onmouseout">
            
            // hide the submenu if exiting item
            // except when moving into the submenu
            // x can be variable based on performance of system
            // and speed of mouse movement, hence a small buffer
            if (this.getMouse('x') < (parent.width-6)) {
                if ( _submenu ) this._opensubmenu( false );
            }
            
        </handler>

         <!---  @keywords private -->
        <handler name="onmousetrackover">
            // listitem ( that menuitem extends) is resposible for the visual
            // changes when a menuitem is hilited.
            // If a menuitem also has a submenu then that is displayed by calling...
            if ( _submenu ) this._opensubmenu( true );
        </handler>

         <!---  @keywords private -->
         <handler name="onmousetrackout">
            // don't need to unhilite listitem, parent view
            // will do this when another listitem is hilited
            // this is needed for menus
            //_ipclassroot.setHilite( null );
        </handler>

         <!---  @keywords private -->
         <handler name="onmousetrackup">
        
            if ( !_submenu && this.enabled ) {
                // no submenu so execute the menu command
                // and close this menuitem's menu and all of its hierarchy
                parent.owner.open( false );
                if ( command ) command.onselect.sendEvent();
                if ( this.onselect  ) this.onselect.sendEvent();
            }
            // else do nothing because hiliting this menuitem
            // has already opened the submenu if there is one
        
        </handler>

         <!---  Called automatically by the menu. The default action uses the colors
                defined in a styles object to change the colors of the background and text. 
                @param Boolean ishilite: true shows the hilite and false restores it back-->
         <method name="setHilite" args="ishilite">
            super.setHilite( ishilite );
            if ( !_initcomplete ) return;
            if (ishilite){
                if ( _submenu ) this._menuarrow.setAttribute('fgcolor',this.style.texthilitecolor);
            } else {
                if ( _submenu ) {
                    this._menuarrow.setAttribute('fgcolor',0x000000);
                    this._opensubmenu( false );
                }
            }
        </method>

        <!--- if a menuitem is hilited and has a submenu then this method is 
             called by a delegate after a period of time specified by delaytime 
             @keywords private -->
        <method name="showSubmenu" args="ignore">
            // this method is called by a delegate which was activated by a timer.
            // First, make sure we still want to show the submenu by checking
            // the _doshowsubmenu flag.
            if ( _doshowsubmenu ) this._submenu.setOpen(true);
        </method>

        <!--- if a menuitem is unhilited and has a submenu then this method is 
             called by a delegate after a period of time specified by delaytime
             @keywords private -->
        <method name="hideSubmenu" args="ignore">
            if ( !_doshowsubmenu ) this._submenu.setOpen(false);
        </method>

        <!--- @keywords private -->
        <method name="_opensubmenu" args="doopen">
            if ( doopen ) {
                this._doshowsubmenu = true;
                if (!this.showsubmenu_del) this.showsubmenu_del = new LzDelegate(this,'showSubmenu');
                lz.Timer.addTimer( this.showsubmenu_del, delaytime );
            } else  {
                this._doshowsubmenu = false;
                if (!this.hidesubmenu_del) this.hidesubmenu_del = new LzDelegate(this,'hideSubmenu');
                lz.Timer.addTimer( this.hidesubmenu_del, delaytime );
            }
        </method>

        <!--- @keywords private -->
        <method name="setSelected" args="isSelected">
            // menus don't keep a selection in this version
            // so override this method to block the list's
            // selection manager.
            // super.setSelected( isSelected );
        </method>

        <!--- call this method to set the command associated with a menuitem 
             @param LzCommand cmd: the command object to be executed when this menuitem is selected 
             -->
       <method name="setCommand" args="cmd">
            this.command = cmd;
            if ( this.command ) {
                // force the appplication of this state
                // because order of execution demands it.
                this.commandstate.apply();
                var t = command.keysToString();
                this.cmdkeys.setAttribute('text', t);
            }
        </method>

        <!--- @keywords private -->
        <method name="toString">
            return "menuitem text =" + this.text;
        </method>

        <!--- @keywords private -->
        <method name="_showEnabled"> 
             if (_initcomplete) {
                _applystyle(this.style);
            }
        
        </method>

        <!--- @keywords private -->
        <method name="_applystyle" args="s">
            if (this.style != null) {
                super._applystyle(s);
                if (command) {
                    if (_enabled) {
                         if (hilited) {
                             this.cmdkeys.setAttribute('fgcolor', style.texthilitecolor);
                         }
                         else if (selected) {
                             this.cmdkeys.setAttribute('fgcolor', style.textselectedcolor);
                         } else {
                             this.cmdkeys.setAttribute('fgcolor', style.textcolor);
                         }
                    } else {
                        this.cmdkeys.setAttribute( "fgcolor", style.textdisabledcolor );
                    }
                }
            }
        </method>

   </class> <!-- menuitem -->

   <!--- @access private -->
   <class name="menufloatinglist" extends="floatinglist" bgcolor="0x445566" autoscrollbar="false" visible="false" focusable="false">

        <!--- @keywords private -->
        <attribute name="issubmenu" value="false"/>

        <!--- @keywords:  private -->
        <attribute name="_updateifsubmenu" value="true"/>

        <!--- setHilite is called by the list class, and it overridden here to support 
              heirarchical menus -->
        <method name="setHilite" args="v">
            super.setHilite( v );
            if ( v )  {
                if ( issubmenu ) {
                    // because this floatinglist belongs to a menu that is actually a submenu
                    // we need to rehilite the menuitem that owns this submenu.
                    // owner.parent = the menuitem that owns this submenu
                    // owner.parent.parent = floating list that contains that menuitem.

                    // however, we only want to do this once, not everytime we hilite
                    // a mnenuitem within the submenu, so frist check to see if we
                    // need to update those objects that own and manage this usbmenu.
                    if ( _updateifsubmenu ) {
                        owner.parent._doshowsubmenu = true;
                        owner.parent.parent.setHilite( owner.parent );
                        // we did it so now don't do again until this menu
                        // is closed and reopened.
                        this._updateifsubmenu = false;
                    }
                }
            } else { // need to clear hilite
                if ( _hiliteview )  {
                    this._hiliteview.setHilite( false );
                    this._hiliteview= null;
                }
            }
        </method>

        <!--- @keywords private -->
        <handler name="onmousetrackout" reference="this.interior">
            this.setHilite(null);
        </handler>
    </class>


    <!-- class: menu -->
    <class name="menu" width="150" extends="basecomponent" focusable="false">
        <!--- the test that appears in the menu button if the menu is a subview of a menubar -->
        <attribute name="text" value="menutitle" type="html"/>

        <!--- a boolean indicating whether or not the menu is in opened -->
        <attribute name="opened" value="false" setter="this.setOpen( opened )" type="boolean"/>

        <!--- @keywords private -->
        <event name="onopened"/>

        <!--- @keywords private
              @deprecated the attribute is deprecated -->
        <attribute name="menu_ref" value="false"/>

        <!--- @keywords private -->
        <attribute name="flist" value="null"/>

        <!--- a string to indicate how the floating part of the menu attaches to 
              the menubutton or menuitem. Possible values are: 'top', 'bottom', 'left', and 'right' -->
        <attribute name="attach" value="bottom" type="string"/>

        <!--- @keywords private -->
        <handler name="onattach">
            if (this.flist != null)
                this.flist.setAttribute("attach", this.attach);
        </handler>

        <!--- @keywords private -->
        <attribute name="_menuitems" value="null"/>

        <!--- @keywords private -->
        <setter name="width" args="w">
            super.setAttribute("width", w);
            if (this.flist != null) {
                this.flist.setAttribute("width", w);
            }
        </setter>

        <!--- @keywords private -->
        <method name="init">
            // create a floating list. Though the parent for this floating
            // list is this menu, the floating list will be created on the
            // canvas and its owner attribute will point to this menu.
            var w = width;
            if ( (this.parent) instanceof lz.menubar) {
                // menu's parent is a menubar so create a floating list
                // with the following parameters...
                // create a floating list that will attach to the bottom
                // of the menubutton by default ( the floating list is
                // canvas-aware and will try to display itself below the menubutton ).
                // if this does not work, then it will try above it.
                this.flist = new lz.menufloatinglist(this,
                             { attach:'bottom',
                               attachoffset:-2,
                               width:w,
                               shadowcrn:1 }, this._menuitems);
                               // border_top:0, border_bottom:0,
            } else if ( (this.parent) instanceof  lz.menuitem ) {
                // menu's parent is a menuitem so attach the floatinglist to
                // the right ( again canvas-aware will try right but display left
                // if necessary )
                this.flist = new lz.menufloatinglist(this,
                             { attach:'right',
                               width:w,
                               issubmenu:true,
                               shadowcrn:2 }, this._menuitems);
            } else {
                // menu's parent is some other type of view so attach the
                // floatinglist to the value of 'attach' attribute
                var atch = this.attach;
                this.flist = new lz.menufloatinglist(this,
                             { attach:atch,
                               width:w,
                               shadowcrn:1 }, this._menuitems);
            }

            // By default the floating list's target will be constrained to the
            // menu's parent. This  private variable wil be change if necessary
            this._flisttarget = this.parent;

            if ( parent instanceof lz.menubar ) {
                // Since the parent is a menubar ...

                // Create a menubutton and have the menu keep a reference to it.
                // Likewise, have the menubutton keep a reference to this menu
                this._menubutton = new lz.menubutton(parent, {_menuref:this}, null, false);

                // Have the floating list constrain to the menubutton and not
                // the parent of the menu ( which would have been menubar in
                // this case )
                this._flisttarget = this._menubutton;
            } else if ( parent instanceof  lz.menuitem ) {
                // insert an arrow into the target
                new lz.menuarrow( this._flisttarget, { name:'_menuarrow' } );

                // have the menuitem keep a reference to its submenu
                this.parent._submenu = this;
            }

            // need to wait until here when the width and heights of the target
            // set before I activate the constraints
            super.init();
            this.flist.setAttachTarget(this._flisttarget);
        </method>

        <!--- this method is called autmatically.
              @param array childrenarray: an array of nodes to be created
              @access private -->
        <method name="createChildren" args="childrenarray">
            this._menuitems = childrenarray;
            super.createChildren( [] );
        </method>

        <!--- @keywords private -->
        <method name="childOfMenuHierarchy" args="v">
            var result = v.childOf( this ) || v.childOf( flist );
            if ( result ) return true; //don't need to check any further

            // Now check to make sure that mousedown has not occurred in another
            // part of the menu hierarchy

            if ( v instanceof  lz.menuitem ) {
                var aMenuRef = v.parent.owner;
                while ( aMenuRef instanceof lz.menu) {
                    result = ( this == aMenuRef );
                    if (result) break;
                    if (aMenuRef.parent.parent['owner'] == null) break;
                    aMenuRef = aMenuRef.parent.parent.owner;
                }
            }
            return result;
        </method>

        <!--- @keywords private -->
        <method name="passModeEvent" args="event,view"> 
            // Once a view has been made modal, this method
            // gets called by the system ONLY when a user clicks on
            // a view 'outside' the contents of this view.
            if ( event == 'onmousedown' ) {
                if ( view != null ) { // view is a clickable view
                    // view is not LITERALLY part of the class hierarchy but
                    // it maybe part of the floatingview of this menu, or part
                    // of the parent view that contains this menu

                    var inMenu = this.childOfMenuHierarchy( view ) ||
                                 view.childOf( parent );
                    if ( !inMenu ) {
                        // view is REALLY outside of the menu so close the menu
                        this.open(false);
                    }
                } else { // view is not a clickable view so close the menu
                    this.open(false);
                }
            }
            // since a menu is not strictly modal ( 'fragile' ), always return
            // true to pass the event to the object that was clicked on
            return true;
         </method>

        <!--- Finds the top most menu in the heirarchy associated with this menu
              @return Object: top most menu
        -->
        <method name="getTopMenu">
            // this is called by a menu so start with this
            var mc = this;
            // iterate up the parent chain starting with this menu's parent
            var mcp = mc;
            while ( mcp !== canvas ){
                if ( mcp instanceof lz.menu ){
                    mc = mcp;
                }
                // in case view is contained within a floating list
                if ( mcp['owner'] ) mcp = mcp.owner;
                else mcp = mcp.parent;
            }
            // return this or another menu that own's this one
            return mc;
        </method>

        <!--- The general method to open/close a menu starting with itself
              and then moving 'up' the hierarchy to open/close the other
              menus in the hierarchy.
              @param Boolean openit: true opens menu, false closes it-->
        <method name="open" args="openit"> 
            // this is called by a menu so start with this
            var mc = this;
            // iterate up the parent chain starting with this menu's parent
            // and as we iterate open/close as we go
            var mcp = mc;
            while ( mcp != canvas ){
                if ( mcp instanceof lz.menu ){
                    mc = mcp;
                    mc.setOpen( openit );
                } else if ( mcp instanceof lz.menubar){
                    mcp.openMenu( mc, openit )
                }
                // in case view is contained within a floating list
                if ( mcp['owner'] ) mcp = mcp.owner;
                else mcp = mcp.parent;
            }
        </method>


        <!--- The general method to close a menu starting with itself
              and then moving 'down' the hierarchy to close all the other
              menus in the hierarchy. -->
        <method name="close"> 
            var mi;
            for (var k=0; k < this.flist.interior.content.subviews.length ; k++) {
                mi = this.flist.interior.content.subviews[k];
                if ( mi instanceof lz.menuitem){
                    if ( mi._submenu ) mi._submenu.close();
                }
            }
            this.setOpen(false);
        </method>


        <!--- Only Hides and shows the floating list associated with the menu.
              It does not effect any other part of the menu's heirarchy.
              To open a menu within a heirarchy use open() instead of setOpen()
              @param Boolean isopened: true opens menu, false closes it-->
        <method name="setOpen" args="isopened">
            if ( _initcomplete ){
                if ( this.opened == isopened ) return;
                this.opened = isopened;
                if ( isopened ){
                    lz.ModeManager.makeModal( this );

                    this.flist.bringToFront();
                    this.flist.setHilite(null);
                    this.flist.setAttribute('tracking',true);
                    this.flist._updateifsubmenu = true;
                    this.flist.setAttribute('visible', true);
                } else {
                    lz.ModeManager.release( this );
                    this.flist.setHilite(null);
                    this.flist.setAttribute('tracking',false);
                    this.flist.setAttribute('visible', false);
                }
                if ( onopened ) this.onopened.sendEvent( this.opened );
            } else this.opened = isopened;
        </method>

        <!--- open and closes the menu 
              @keywords private -->
        <method name="toggle">
            this.setOpen(!this.opened);
        </method>

         <doc>
           <tag name="shortdesc"><text>
               A pull-down menu that can be used within a menubar, a menuitem or any other view.
           </text></tag>
           <text>
             <p>The <tagname>menu</tagname> tag creates a menu that floats above
               all other views when activated.  If a menu is a subview of a
               <tagname>menubar</tagname>, then it will create a
               "menubutton" in the menubar with the its
               <attribute>text</attribute> attribute equal to that of the menu's. This "menubutton"
               inherits its properties from <tagname>button</tagname>.
             </p>

             <p>
               typical use of a menu is shown below, with its children of <tagname link="true">menuitem</tagname>s and <tagname link="true">menuseparator</tagname>s. Note, however, that the parent
               of a menuitem is not the menu itself, but rather a <tagname link="true">floatinglist</tagname> that is implicity part of the menu.
               To access the menu from a menuitem (or any other subview) use the
               reference "<code>parent.owner</code>".
             </p>

             <example title="using the menubar">
               <canvas debug="true" height="230">
               <debug y="100"/>
               <menubar width="200" >
               <menu text="Menu 1" width="100">
               <menuitem text="Item 1" onselect="canvas.whichOne(this);"/>
               <menuitem text="Item 2" onselect="canvas.whichOne(this);"/>
               <menuitem text="Item 3" onselect="canvas.whichOne(this);"/>
               <menuseparator/>
               <menuitem text="Item 4" onselect="canvas.whichOne(this);"/>
               </menu>
               <menu text="Menu 2" width="100">
               <menuitem text="More items..." onselect="canvas.whichOne(this);"/>
               </menu>
               </menubar>

               <method name="whichOne" args="vThis">
               Debug.debug("%w - %w", vThis.parent.owner.text, vThis.text);
               </method>
               </canvas>
             </example>

             <example title="simple menu">
               <canvas debug="true" height="235">
               <debug y="105"/>
               <button text="openMenu below">
               <menu name="topmenu" attach="bottom">
               <menuitem text="item 1"/>
               <menuitem text="item 2">
               <menu name="submenu">
               <menuitem text="subitem 1"/>
               <menuitem text="subitem 2"/>
               </menu>
               </menuitem>
               </menu>

               <handler name="onmousedown">
               this.topmenu.setOpen(true);
               </handler>
               </button>
               </canvas>
             </example>

             <seealso>
               <tags>command menuitem menubar menuseparator floatinglist</tags>
               <component-design id="menus" title="Menus"/>
             </seealso>
          </text>
        </doc>

    </class> <!-- end menu -->

</library>
<!-- * X_LZ_COPYRIGHT_BEGIN ***************************************************
* Copyright 2001-2010 Laszlo Systems, Inc.  All Rights Reserved.              *
* Use is subject to license terms.                                            *
* X_LZ_COPYRIGHT_END ****************************************************** -->
<!-- @LZX_VERSION@                                                         -->

Cross References

Includes

Resources

Name Source Image
menuarrow_rsrc resources/menu/menu_arrow_rt.swf
resources/menu/menu_arrow_lft.swf

Classes

Named Instances