Menu

ViewMenu Spec

SourceForge Editorial Staff

Functional and Design Specification


Glossary

brick layout - layout used by the native Android options menu. If there are an odd number of menu items, then the items have two different sizes and are layed out in a brick pattern.

menu button - on an Android device, a physical button that brings up the options menu

view menu - a menu that is used to present actions to a user

Summary and Background

The ViewMenu component is a non-hierarchical container of ViewMenuItems. ViewMenuItems are buttons that display a label and possibly an icon. They also dispatch a click event when the item has been pressed or committed via the keyboard or 5-way input.

ViewMenu subclasses SkinnableContainer and has a custom layout.

The ViewMenu appears when a user presses the device's menu button. Typically, the menu items will vary depending on the current application and screen.

Hierarchical menus will be addressed at a later time and are not within the scope of this feature.

Usage Scenarios

Jimi is creating a mobile application for his music review website called PitchSpoon. He creates two Views, one is a list of album reviews (AlbumListView) and the second is the actual album review (AlbumView). Jimi wants to promote the reviews. When the user presses the menu button in the AlbumView, he gets presented with a choice to email or tweet about the articles. Jimi adds email and tweet menu items to his View and then adds click handlers to each item. When the user selects the email item, it brings up an email form. When the user selects the tweet item, it brings up a form to submit the tweet.

Detailed Description

ViewMenu

The ViewMenu is a SkinnableContainer with customized layout and keyboard interaction. It replaces the mxmlContent property with an viewMenuItems property which is a Vector of ViewMenuItems.

This component appears when the user presses the menu button. ViewMenus typically expose a set of action to perform in the application and in the current View.

Each View has an optional ViewMenuItems property which contains the list of items to use in that View's ViewMenu. When the user presses the menu button, the MobileApplication creates an ViewMenu, populates it with the activeView's menu items and then pops it up using the PopUpManager. When the user selects an item, that ViewMenuItem dispatches a click event and the MobileApplication closes the ViewMenu. The user can dismiss the ViewMenu without selecting an item by pressing the menu button, the back button, or outside of the menu .

The ViewMenu is generated from the MobileApplication's viewMenu dynamic skin part. This value defaults to a factory that generates an ViewMenu.

A user can choose an item using the keyboard or 5-way input. The ViewMenu displays a caret when navigating to the different items using the keyboard.

ViewMenuItem

ViewMenuItem subclasses ButtonBase. It uses the label property and icon style. It adds a showCaret property and showsCaret skin state. The enabled property controls the menu item's appearance (if disabled, it will be greyed out) and its user interaction (users can not select a disabled item). ViewMenuItem dispatches a click event if the item has been pressed or keyboard selected or selected using the 5-way input.

ViewMenuItemSkin

ViewMenuItemSkin subclasses ButtonSkin. It draws a background using the backgroundColor and backgroundAlpha styles. It also handles the showsCaret and down states.

ViewMenuLayout

ViewMenuLayout subclasses LayoutBase. It limits the number of columns to three in portrait mode and six in landscape mode. In each row, it makes each item the same size and stretches the items' widths across the layout.

MobileApplication and View integration

MobileApplicationBase has an viewMenu optional skin part which is of type IFactory. Each time the menu button is pressed, the MobileApplication will generate a new ViewMenu instance from this factory and populate it with the View's viewMenuItems. View exposes an viewMenuItems property, which is a Vector of ViewMenuItems. If the property is empty for a particular View, then nothing happens when the user presses the menu button while in that View.

MobileApplicationBase exposes a viewMenuOpen property to control the view menu.

API Description

\

package spark.components
{

<a href="DefaultProperty%28%26quot%3Bitems%26quot%3B%29">DefaultProperty("items")</a>

<a href="SkinState%28%26quot%3BnormalAndLandscape%26quot%3B%29">SkinState("normalAndLandscape")</a>
<a href="SkinState%28%26quot%3BdisabledAndLandscape%26quot%3B%29">SkinState("disabledAndLandscape")</a>

/**
 *  The ViewMenu class display a set of ViewMenuItems. MobileApplication 
 *  will automatically create and display an ViewMenu when the user has 
 *  pressed the device's Menu button. 
 * 
 *  ViewMenu's default layout is ViewMenuLayout
 * 
 *  Set the items property to a Vector of ViewMenuItems.
 */ 
public class ViewMenu extends SkinnableContainer implements IFocusManagerComponent
{
    /**
     *  Constructor 
     */ 
    public function ViewMenu()
    {
    }

    /**
     *  The item that is currently in the caret state
     */   
    public function get caretIndex():int;    
    public function set caretIndex(value:int):void;

    /**
     *  The Vector of ViewMenuItems to display in the ViewMenu
     */    
    public function get items():Vector.<ViewMenuItem>;
    public function set items(value:Vector.<ViewMenuItem>):void;
}
}

\

package spark.components
{    
/**
 *  Caret State of the Button
 */
<a href="SkinState%28%26quot%3BshowsCaret%26quot%3B%29">SkinState("showsCaret")</a>

/**
 *  Displays a label and icon inside of an ViewMenu. Typically, you should 
 *  listen for the itemClick event to perform some operation based on clicking
 *  this item. 
 */ 
public class ViewMenuItem extends ButtonBase
{
    /**
     *  Constructor 
     */ 
    public function ViewMenuItem()
    {
        super();
    }

    /**
     *  Contains <code>true</code> if the item renderer 
     *  can show itself as focused. 
     *
     *  @default false  
     */    
    public function get showsCaret():Boolean;
    public function set showsCaret(value:Boolean):void;

}
}

\

package spark.skins.mobile
{

/**
 *  Default skin for ViewMenuItem. Supports a label, icon and iconPlacement and draws a background.   
 */ 
public class ViewMenuItemSkin extends ButtonSkin
{
    public function ViewMenuItemSkin()
    {
        super();
    }
}
}

\

package spark.layouts
{
/**
 *  ViewMenuLayout is a specialized TileLayout for ViewMenu. 
 */ 
public class ViewMenuLayout extends LayoutBase
{
    public function ViewMenuLayout()
    {
    }

    /**
     *  The horizontal space between columns, in pixels.
     *
     *  @default 2
     */
    public function get horizontalGap():Number;    
    public function set horizontalGap(value:Number):void;

    /**
     *  The vertical space between rows, in pixels.
     *
     *  @default 2
     */
    public function get verticalGap():Number;    
    public function set verticalGap(value:Number):void;

    /**
     *  The maximum number of columns to display in a row. 
     *
     *  @default 3
     */
    public function get requestedMaxColumnCount():int;
    public function set requestedMaxColumnCount(value:int):void;

}
}

\

package spark.components
{
public class MobileApplicationBase
{
    public function MobileApplicationBase()
    {
    }

    <a href="SkinPart%28required%3D%26quot%3Bfalse%26quot%3B%29">SkinPart(required="false")</a>
    /**
     *  Dynamic skin part that defines the ViewMenu used to display the
     *  view menu when the menu button is pressed. The default skin uses 
     *  a factory that generates an ViewMenu instance. 
     */ 
    public var viewMenu:IFactory;

    /**
     *  Opens the view menu if set to true and closes it if set to false. 
     * 
     *  @default false
     */
    public function get viewMenuOpen():Boolean;
    public function set viewMenuOpen(value:Boolean):void;

    /**
     *  Called when the menu button is pressed
     */ 
    protected function menuKeyHandler(event:KeyboardEvent):void;
}
}

\

package spark.skins.mobile
{
public class MobileApplicationSkin
{
    public function MobileApplicationSkin()
    {
    }

    /**
     *  Factory that generates an instance of the view menu when the
     *  menu button is pressed 
     * 
     *  @default class factory generating ViewMenu
     */ 
    public var viewMenu:IFactory;

}
}

\

package spark.components
{
public class View
{
    public function View()
    {
    }

    /**
     *  The Vector of ViewMenuItems that are passed to the ViewMenu when
     *  this View is the active view. 
     */   
    public function get viewMenuItems():Vector.<ViewMenuItem>;
    public function set viewMenuItems(value:Vector.<ViewMenuItem>):void;
}
}

\

B Features

None

Examples and Usage

Example showing how to add an view menu to a View:

<?xml version="1.0" encoding="utf-8"?>
<s:View xmlns:fx="http://ns.adobe.com/mxml/2009" 
        xmlns:s="library://ns.adobe.com/flex/spark" title="ViewMenuViewIntegration">
    <s:viewMenuItems>
        <s:ViewMenuItem label="Add" icon="@Embed('menuIcons/addIcon.png')" click="trace('Add Stuff')"/>
        <s:ViewMenuItem label="Cancel" icon="@Embed('menuIcons/cancelIcon.png')" click="trace('Cancel Stuff')"/>
        <s:ViewMenuItem label="Delete" icon="@Embed('menuIcons/deleteIcon.png')" click="trace('Delete Stuff')"/>
        <s:ViewMenuItem label="Edit" icon="@Embed('menuIcons/editIcon.png')" click="trace('Edit Stuff')"/>
        <s:ViewMenuItem label="Search" icon="@Embed('menuIcons/searchIcon.png')" click="trace('Search Stuff')"/>
    </s:viewMenuItems>

    <s:VGroup>
        <s:Label text="Some Random View"/>
    </s:VGroup>
</s:View>

\

Additional Implementation Details

Compiler Work

None

Backwards Compatibility

None

Accessibility

Not supported yet

Performance

The ViewMenu item renderer needs to be performant. This means they need to be written as Actionscript classes.

Globalization

Localization

Framework Features

List the RTE message strings that will require localization. (They must all come from .properties files.)

List all UI text that will require localization, such as the month and day names in a DateChooser. (All such text must all come from .properties files.)

List all UI images, skins, sounds, etc. that will require localization.

Discuss any locale-specific formatting requirements for numbers, dates, currency, etc.

Discuss any locale-specific sorting requirements.

Cross-Platform Considerations

Not all platforms will have a menu button. We should make the ViewMenu integration with View and MobileApplication platform independant, where possible.

Issues and Recommendations

Resolved Issues

Should MobileApplicationBase expose functions to control the ViewMenu lifecycle? Is there a use case for programmatically opening and closing the ViewMenu?

Property added to MobileApplicationBase

When the device goes into landscape mode, what happens? How does the ViewMenu and ViewMenuLayout get notified of the change. How do they implement the change? Will ViewMenu listen for a deviceOrientation change?

The ViewMenu will change width and layout.

Should ViewMenuItem's itemClick event be named click instead?

The click event would be dispatched on mouseClick and on keyboard input (space key or 5-way button press), similar to how Button's click event works.

Should ViewMenu subclass List or SkinnableContainer?

ViewMenu doesn't need many of the properties defined on List and its ancestor classes. Nor does it expose the notion of selection or the change events. Using List provides some caret support. However, the keyboard interaction would need to be overridden.

Should ViewMenuItem subclass MobileItemRenderer or a simpler class?

ViewMenuItem doesn't need the IItemRenderer API. ButtonBase provides a label property and icon style.

Where does the ViewMenu appear? Does it appear at the bottom of the View, ViewNavigator or MobileApplication?

It should appear at the bottom of the MobileApplication

What events should we dispatch?

ViewMenu itself should not dispatch any events. ViewMenuItem will dispatch an itemClick event when it has been selected via mouse, keyboard or 5-way.

Rather than having an Array or IList of ViewMenuItemData objects, could we have a MenuData object that encapsulates that? Along the same lines, I don't really like calling it "ViewMenuDataProvider" on the View since I don't really see it as a dataProvider. What about "ViewMenuItems" (and typing it as a simple Array or this new MenuData object and call it "ViewMenuData" in that case).

The argument for this is to strongly type the list of menu items. If we use a generic dataProvider, then it is not clear what data type to use for each item.

The argument against this is that this adds an extra property to ViewMenu and MenuList and deprecates dataProvider. DataProvider is a common pattern for all of the list-based flex components. Do we really want to add a new pattern?

The actual implementation will probably pass the MenuItemData list to the dataProvider.

Can we put click events on the MenuItemData object. Something similar to: http://frishy.blogspot.com/2007/12/making-flex-menus-easier.html . I think this would be really useful for people, and I think it supports the mental model I have for Menus a lot better than the List dataProvider model.

This would allow developers to add click handlers inline to their menu item data tags. The argument is that each menu item is typically associated with a unique action which is performed when the item is clicked. In a List, selecting an item usually just means populating some property with the selectedItem's data, so a generic change handler is sufficient.

It is unlikely that MenuItemData is shared amongst multiple menus. If they are, then you probably want them to perform the same action. If you don't, then they shouldn't be shared across menus.

Should we be dispatching a click event or some sort of selection event? Is "click" a high level event that is triggered from mouse, touch, or keyboard interactions?

MenuItemData should probably also dispatch toggled events.

The argument against this is that it breaks the existing model for all list-based components. There isn't another example of a data class dispatching interaction events. Does this break MVC?

Does the View or MobileApplication handle creating and positioning the ViewMenu?

Having MobileApplication handle this makes it easier to incorporate into View transitions and provides a consistent position for the menu across all Veiws. It is unlikely that a developer wants to customize the creation and position of the ViewMenu on a per View basis.

Who dispatches the click/change event?

This event can be dispatched from either the MenuItemData, the View or the MobileApplication.

Handling this event on the MobileApplication makes the least sense since the actions depend upon the View. We will probably need a new event which contains a reference to the MenuItemData. The IndexChangeEvent isn't ideal since the index is in the View's context. The developer would have to pass the index to the application's active view's data to get the selected item.

Putting it on the MenuItemData seems to break the data/controller boundaries.

We could bubble this event or dispatch it from the data and the View and/or the application

Should MobileApplication have a menu items array which is cumulative with the View's menu items array?

This seems like a convenience that isn't needed. Menu items will most likely be hard coded. They aren't going to be dynamically changing on a per View or application basis. Secondly, some menu items on the application might have different behaviors based on the current view, so there would be no benefit to putting the handlers on the application. The contract between a the MobileApplication and View's menu items array is an implied one. The relationship between the MobileApplication and View is a bit indirect.

We decided MobileApplication does not have a menu items array

Glenn suggests that we change View.ViewMenuFactory into a dynamic skin part on MobileApplication.

How would the developer know to look at MobileApplication's skin in order to customize the ViewMenu?

The ActionBar skins are on MobileApplication skin as well, so this shouldn't be too hard to discover.


Related

Wiki: Flex 4.5
Wiki: ViewNavigatorApplication

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.