Fields Summary |
---|
protected Command[] | menuCmdsThe list of Commands to display in the menu. |
protected int | selIThe currently selected index in the menu. |
protected int | scrollIndexThe number of commands which have been scrolled off the
top of the menu, normally 0 unless there are more commands
than can fit on the menu. |
protected SoftButtonLayer | btnLayerThe SoftButtonLayer maintains the overall set of
commands and their associated listeners. |
protected CascadeMenuLayer | cascadeMenuA cascading menu which holds commands for a SubMenuCommand. |
protected boolean | cascadeMenuUpA flag indicating if a cascading menu is visible. |
private static final int | PRESS_OUT_OF_BOUNDSpointer pressed outside of the menuLayer's bounds |
private static final int | PRESS_ON_TITLEpointer pressed on the menuLayer's title area |
private int | itemIndexWhenPressedvariable used in pointerInput handling |
Methods Summary |
---|
protected void | alignMenu()Aligns the menu to the current screen.
bounds[W] = MenuSkin.WIDTH;
switch (MenuSkin.ALIGN_X) {
case Graphics.LEFT:
bounds[X] = 0;
break;
case Graphics.HCENTER:
bounds[X] = (ScreenSkin.WIDTH - bounds[W]) / 2;
break;
case Graphics.RIGHT:
default:
bounds[X] = ScreenSkin.WIDTH - bounds[W];
break;
}
switch (MenuSkin.ALIGN_Y) {
case Graphics.TOP:
bounds[Y] = 0;
break;
case Graphics.VCENTER:
bounds[Y] = (ScreenSkin.HEIGHT - SoftButtonSkin.HEIGHT -
bounds[H]) / 2;
break;
case Graphics.BOTTOM:
default:
bounds[Y] = ScreenSkin.HEIGHT - SoftButtonSkin.HEIGHT -
bounds[H];
break;
}
|
public void | dismiss()Cleans up the display when the cascaded menu is dismissed.
Removes the layer with the menu and requests the display to be
repainted.
dismissCascadeMenu();
selI = scrollIndex = 0;
|
public void | dismissCascadeMenu()Cleans up the display when the cascaded menu is dismissed.
Removes the layer with the menu and requests the display to be
repainted.
if (owner != null && cascadeMenuUp) {
cascadeMenuUp = false;
cascadeMenu.dismiss();
setScrollInd(ScrollIndLayer.getInstance(ScrollIndSkin.MODE));
owner.removeLayer(cascadeMenu);
requestRepaint();
}
|
public int | getIndex()Gets index of highlighted command.
return selI;
|
protected void | initialize()Initializes the menu parameters.
super.initialize();
bounds[X] = 0; // set in alignMenu()
bounds[Y] = 0; // set in alignMenu()
bounds[W] = MenuSkin.WIDTH;
bounds[H] = MenuSkin.HEIGHT;
|
private int | itemIndexAtPointerPosition(int x, int y)Helper function to determine the itemIndex at the x,y position
int ret;
if (!containsPoint(x + bounds[X], y + bounds[Y])) {
ret = PRESS_OUT_OF_BOUNDS;
} else if (y < MenuSkin.ITEM_TOPOFFSET) {
ret = PRESS_ON_TITLE;
} else {
ret = (y - MenuSkin.ITEM_TOPOFFSET) / MenuSkin.ITEM_HEIGHT;
}
return ret;
|
public boolean | keyInput(int type, int keyCode)Handles key input from a keypad. Parameters describe
the type of key event and the platform-specific
code for the key. (Codes are translated using the
lcdui.Canvas)
// The system menu will absorb all key presses except
// for the soft menu keys - that is, it will always
// return 'true' indicating it has handled the key
// event except for the soft button keys for which it
// returns 'false'
if (keyCode == EventConstants.SOFT_BUTTON1 ||
keyCode == EventConstants.SOFT_BUTTON2) {
return false;
}
if (type != EventConstants.PRESSED && type != EventConstants.REPEATED) {
return true;
}
if (keyCode == Constants.KEYCODE_UP) {
if (selI > 0) {
selI--;
if (selI < scrollIndex && scrollIndex > 0) {
scrollIndex--;
}
updateScrollIndicator();
requestRepaint();
}
} else if (keyCode == Constants.KEYCODE_DOWN) {
if (selI < (menuCmds.length - 1)) {
selI++;
if (selI >= scrollIndex + MenuSkin.MAX_ITEMS &&
scrollIndex < (menuCmds.length - MenuSkin.MAX_ITEMS)) {
scrollIndex++;
}
updateScrollIndicator();
requestRepaint();
}
} else if (keyCode == Constants.KEYCODE_LEFT) {
// IMPL_NOTE : Need to add support for a "right popping"
// sub menu if the system menu is placed on the left
// side of the screen instead of the right
if (btnLayer != null) {
showSubMenu(selI);
}
} else if (keyCode == Constants.KEYCODE_SELECT) {
if (btnLayer != null && !showSubMenu(selI)) {
btnLayer.commandSelected(menuCmds[selI]);
}
} else {
int max = 0;
switch (keyCode) {
case Canvas.KEY_NUM1:
max = 1;
break;
case Canvas.KEY_NUM2:
max = 2;
break;
case Canvas.KEY_NUM3:
max = 3;
break;
case Canvas.KEY_NUM4:
max = 4;
break;
case Canvas.KEY_NUM5:
max = 5;
break;
case Canvas.KEY_NUM6:
max = 6;
break;
case Canvas.KEY_NUM7:
max = 7;
break;
case Canvas.KEY_NUM8:
max = 8;
break;
case Canvas.KEY_NUM9:
max = 9;
break;
}
if (max > 0 && menuCmds.length >= max) {
if (btnLayer != null && !showSubMenu(max - 1)) {
btnLayer.commandSelected(menuCmds[max - 1]);
}
}
}
return true;
|
protected void | paintBody(Graphics g)Renders the body of the menu.
if (MenuSkin.TEXT_TITLE != null) {
// IMPL_NOTE enforce MenuSkin.TITLE_MAXWIDTH based on
// title value and font, add '...' to titles which
// are too long to show
g.setFont(MenuSkin.FONT_TITLE);
g.setColor(MenuSkin.COLOR_TITLE);
g.drawString(MenuSkin.TEXT_TITLE,
MenuSkin.TITLE_X,
MenuSkin.TITLE_Y,
Graphics.TOP | MenuSkin.TITLE_ALIGN);
}
if (menuCmds != null) {
int y = MenuSkin.ITEM_TOPOFFSET;
int x = 0;
Image arrow = null;
for (int cmdIndex = scrollIndex;
(cmdIndex < menuCmds.length)
&& (cmdIndex - scrollIndex < MenuSkin.MAX_ITEMS);
cmdIndex++)
{
if (menuCmds[cmdIndex] instanceof SubMenuCommand) {
arrow = MenuSkin.IMAGE_SUBMENU_ARROW;
if (cmdIndex == selI && !cascadeMenuUp) {
arrow = MenuSkin.IMAGE_SUBMENU_ARROW_HL;
}
if (arrow != null) {
x = arrow.getWidth() + 2;
}
}
if (cmdIndex == selI && !cascadeMenuUp) {
if (MenuSkin.IMAGE_ITEM_SEL_BG != null) {
// We want to draw the selected item background
CGraphicsUtil.draw3pcsBackground(g, 3,
((selI - scrollIndex) * MenuSkin.ITEM_HEIGHT) +
MenuSkin.IMAGE_BG[0].getHeight(),
bounds[W] - 3,
MenuSkin.IMAGE_ITEM_SEL_BG);
} else {
g.setColor(MenuSkin.COLOR_BG_SEL);
g.fillRoundRect(MenuSkin.ITEM_ANCHOR_X - 2,
((selI - scrollIndex) * MenuSkin.ITEM_HEIGHT) +
MenuSkin.ITEM_TOPOFFSET,
MenuSkin.FONT_ITEM_SEL.stringWidth(
menuCmds[cmdIndex].getLabel()) + 4 + x,
MenuSkin.ITEM_HEIGHT,
3, 3);
}
}
if (cmdIndex < 9) {
g.setFont((selI == cmdIndex) ?
MenuSkin.FONT_ITEM_SEL :
MenuSkin.FONT_ITEM);
g.setColor((selI == cmdIndex) ?
MenuSkin.COLOR_INDEX_SEL :
MenuSkin.COLOR_INDEX);
g.drawString("" + (cmdIndex + 1),
MenuSkin.ITEM_INDEX_ANCHOR_X,
y, Graphics.TOP | Graphics.LEFT);
}
g.setFont(MenuSkin.FONT_ITEM);
g.setColor((selI == cmdIndex) ? MenuSkin.COLOR_ITEM_SEL :
MenuSkin.COLOR_ITEM);
if (arrow != null) {
g.drawImage(arrow, MenuSkin.ITEM_ANCHOR_X, y + 2,
Graphics.TOP | Graphics.LEFT);
arrow = null;
}
g.drawString(menuCmds[cmdIndex].getLabel(),
MenuSkin.ITEM_ANCHOR_X + x,
y, Graphics.TOP | Graphics.LEFT);
x = 0;
y += MenuSkin.ITEM_HEIGHT;
}
}
|
public boolean | pointerInput(int type, int x, int y)Handle input from a pen tap. Parameters describe
the type of pen event and the x,y location in the
layer at which the event occurred. Important : the
x,y location of the pen tap will already be translated
into the coordinate space of the layer.
switch (type) {
case EventConstants.PRESSED:
itemIndexWhenPressed = itemIndexAtPointerPosition(x, y);
// dismiss the menu layer if the user pressed outside the menu
if (itemIndexWhenPressed == PRESS_OUT_OF_BOUNDS) {
if (btnLayer != null) {
btnLayer.dismissMenu();
}
} else if (itemIndexWhenPressed >= 0) { // press on valid menu item
selI = scrollIndex + itemIndexWhenPressed;
requestRepaint();
// if (btnLayer != null) btnLayer.serviceRepaints();
}
break;
case EventConstants.RELEASED:
int itemIndexWhenReleased = itemIndexAtPointerPosition(x, y);
if (itemIndexWhenReleased == itemIndexWhenPressed) {
if (itemIndexWhenPressed >= 0) {
if (btnLayer != null && !showSubMenu(selI)) {
if (selI >= 0 && selI < menuCmds.length) {
btnLayer.commandSelected(menuCmds[selI]);
}
}
}
}
// remember to reset the variables
itemIndexWhenPressed = PRESS_OUT_OF_BOUNDS;
break;
}
// return true always as menuLayer will capture all of the pointer inputs
return true;
|
public void | scrollContent(int scrollType, int thumbPosition)Scroll content inside of the Menu.
if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
Logging.report(Logging.INFORMATION,
LogChannels.LC_HIGHUI,
"MenuLayer.scrollContent scrollType=" + scrollType +
" thumbPosition=" + thumbPosition);
}
// keep old scrollIndex
int oldScrollIndex = scrollIndex;
switch (scrollType) {
case ScrollBarLayer.SCROLL_PAGEUP:
uScrollViewport(Canvas.UP);
break;
case ScrollBarLayer.SCROLL_PAGEDOWN:
uScrollViewport(Canvas.DOWN);
break;
case ScrollBarLayer.SCROLL_LINEUP:
uScrollByLine(Canvas.UP);
break;
case ScrollBarLayer.SCROLL_LINEDOWN:
uScrollByLine(Canvas.DOWN);
break;
case ScrollBarLayer.SCROLL_THUMBTRACK:
uScrollAt(thumbPosition);
break;
default:
break;
}
// only if scroll index has been changed do update
if (oldScrollIndex != scrollIndex && scrollIndex >= 0) {
// correct selI if required.
// The selected item always should be on the screen
if (selI < scrollIndex) {
selI = scrollIndex;
} else if (selI >= (scrollIndex + MenuSkin.MAX_ITEMS)) {
selI = scrollIndex + MenuSkin.MAX_ITEMS - 1;
}
updateScrollIndicator();
requestRepaint();
}
|
public void | setMenuCommands(Command[] cmdList, SoftButtonLayer btnLayer, int index)Called typically by the SoftButtonLayer to establish the
set of Commands to display on this system menu. This method will
create a new copy of the array of commands passed in.
if (cmdList.length == 1 && cmdList[0] instanceof SubMenuCommand) {
cmdList = ((SubMenuCommand)cmdList[0]).getSubCommands();
}
this.menuCmds = new Command[cmdList.length];
System.arraycopy(cmdList, 0, this.menuCmds, 0, cmdList.length);
// If we have fewer commands than fill up the menu,
// we shorten the menu's height
if (menuCmds.length < MenuSkin.MAX_ITEMS) {
bounds[H] = MenuSkin.HEIGHT -
((MenuSkin.MAX_ITEMS - menuCmds.length)
* MenuSkin.ITEM_HEIGHT);
} else {
bounds[H] = MenuSkin.HEIGHT;
}
alignMenu();
requestRepaint();
this.btnLayer = btnLayer;
selI = index < cmdList.length ? index : 0;
|
private boolean | showSubMenu(int index)Shows the sub menu.
boolean ret = false;
if (menuCmds[index] instanceof SubMenuCommand) {
SubMenuCommand subMenu = (SubMenuCommand)menuCmds[index];
cascadeMenu.setMenuCommands(subMenu.getSubCommands(), this);
cascadeMenu.setAnchorPoint(bounds[X],
bounds[Y] + MenuSkin.ITEM_TOPOFFSET +
((index - scrollIndex) *
MenuSkin.ITEM_HEIGHT));
cascadeMenuUp = true;
owner.addLayer(cascadeMenu);
setScrollInd(ScrollIndLayer.getInstance(ScrollIndSkin.MODE));
// IMPL_NOTE: fix layer inrteraction in removeLayer
btnLayer.requestRepaint();
selI = index;
addDirtyRegion();
ret = true;
}
return ret;
|
public void | subCommandSelected(Command cmd)Notifies listener that a command has been selected.
Dismisses the cascaded menu and the button layer.
Command c = menuCmds[selI];
if (c instanceof SubMenuCommand) {
btnLayer.dismissMenu();
((SubMenuCommand)c).notifyListener(cmd);
}
|
void | uScrollAt(int position)Perform a scrolling at the given position.
int viewableH = MenuSkin.ITEM_HEIGHT * menuCmds.length;
int viewportH = MenuSkin.ITEM_HEIGHT * MenuSkin.MAX_ITEMS;
int newY = (viewableH - viewportH) * position / 100;
if (newY < 0) {
newY = 0;
} else if (newY > viewableH - viewportH) {
newY = viewableH - viewportH;
}
scrollIndex = newY / MenuSkin.ITEM_HEIGHT;
|
private void | uScrollByLine(int dir)Perform a line scrolling in the given direction. This method will
attempt to scroll the view to show next/previous line.
switch(dir) {
case Canvas.UP:
if (scrollIndex > 0) {
scrollIndex--;
}
break;
case Canvas.DOWN:
if (scrollIndex < (menuCmds.length - MenuSkin.MAX_ITEMS)) {
scrollIndex++;
}
break;
}
|
private void | uScrollViewport(int dir)Perform a page flip in the given direction. This method will
attempt to scroll the view to show as much of the next page
as possible. It uses the locations and bounds of the items on
the page to best determine a new location - taking into account
items which may lie on page boundaries as well as items which
may span several pages.
switch (dir) {
case Canvas.UP:
scrollIndex -= MenuSkin.MAX_ITEMS - 1;
if (scrollIndex < 0) {
scrollIndex = 0;
}
break;
case Canvas.DOWN:
scrollIndex += MenuSkin.MAX_ITEMS - 1;
if (scrollIndex > menuCmds.length - MenuSkin.MAX_ITEMS) {
scrollIndex = menuCmds.length - MenuSkin.MAX_ITEMS;
}
break;
}
|
public void | update(CLayer[] layers)Update bounds of layer
alignMenu();
if (owner != null && cascadeMenuUp) {
cascadeMenu.update(layers);
if (btnLayer != null) {
showSubMenu(selI);
}
}
super.update(layers);
|
public void | updateScrollIndicator()Updates the scroll indicator.
if (scrollInd != null) {
if (menuCmds.length > MenuSkin.MAX_ITEMS) {
scrollInd.setVerticalScroll(
(scrollIndex * 100) / (menuCmds.length - MenuSkin.MAX_ITEMS),
(MenuSkin.MAX_ITEMS * 100) / menuCmds.length);
} else {
scrollInd.setVerticalScroll(0, 100);
}
super.updateScrollIndicator();
}
|