/* * Select.java * * Created on 22 Июнь 2007 г., 15:00 * * To change this template, choose Tools | Template Manager * and open the template in the editor. */ package jimmui.view.menu; import jimm.Jimm; import jimmui.view.base.touch.*; import jimmui.view.form.Menu; import jimmui.view.icons.*; import javax.microedition.lcdui.*; import jimmui.view.base.*; import java.util.Vector; /** * @author vladimir */ public final class Select extends CanvasEx implements Menu { private static final int ICON_INTERVAL = 2; private static final int WIDTH_SPACE = 6; private static final int SLEEP_BEFORE = 2000 / NativeCanvas.UIUPDATE_TIME; private static final int SLEEP_AFTER = 1000 / NativeCanvas.UIUPDATE_TIME; private static final int STEP = 10; private static final int EMPTY_WIDTH = 5 * STEP; private MenuModel items; private int topItem; private int selectedItemIndex; private int selectedItemPosX; private int sleep; private int left; private int top; private int width; private int itemPerPage; private int itemHeight; private int itemWidth; private int iconWidth; public MySoftBar softBar = new MySoftBar(); private int getHeadSpace() { return Math.max(3, itemHeight / 4); } protected final int[] getScroll() { // scroll bar int[] scroll = MyScrollBar.makeVertScroll( left + itemWidth - scrollerWidth, top, scrollerWidth + 1, (itemPerPage) * itemHeight + 1 + 2 * getHeadSpace(), itemPerPage, items.count()); if (null != scroll) { scroll[MyScrollBar.SCROLL_TOP_VALUE] = topItem; } return scroll; } // #sijapp cond.if modules_TOUCH is "true"# private int getItemStartY() { return topItem * itemHeight + getHeadSpace(); } private int getItemByCoord(int relativeY) { relativeY -= getHeadSpace(); final int size = items.count(); for (int i = topItem; i < size; ++i) { if (relativeY < itemHeight) { return i; } relativeY -= itemHeight; } return -1; } private boolean checkRegion(int fromX, int fromY) { int relativeX = fromX - left; int relativeY = fromY - top - getHeadSpace(); int curHeight = itemPerPage * itemHeight; int curWidth = itemWidth; return (relativeX >= 0) && (relativeX < curWidth) && (relativeY >= 0) && (relativeY < curHeight); } private boolean isItemsRegion(int absoluteX) { return (absoluteX - left) < itemWidth; } protected void stylusPressed(TouchState state) { if (getHeight() < state.y) { state.region = softBar; return; } if (!checkRegion(state.x, state.y)) { return; } touchPressed = true; touchUsed = true; int posY = state.y - top; if (isItemsRegion(state.x)) { // menu items state.prevTopY = getItemStartY(); int cur = getItemByCoord(posY); if (-1 != cur) { selectedItemIndex = -1; setSelectedItemIndex(cur); } } } private void setTop(int pos) { int newTop = Math.max(0, Math.min(pos, items.count() - itemPerPage)); boolean update = (newTop != topItem); topItem = newTop; if (update) { invalidate(); } } protected void setScrollTop(int top) { setTop(top); } protected int getScrollTop() { return topItem; } protected void stylusGeneralYMoved(TouchState state) { if (checkRegion(state.fromX, state.fromY) && isItemsRegion(state.fromX)) { setTop((state.prevTopY - state.y + state.fromY + getHeadSpace()) / itemHeight); } } protected void stylusTap(TouchState state) { if (checkRegion(state.x, state.y)) { if (isItemsRegion(state.x)) { int posY = state.y - this.top; int cur = getItemByCoord(posY); if (-1 != cur) { setSelectedItemIndex(getIndex(cur, 0)); go(items.itemAt(cur).code); } } } else { back(); } } // #sijapp cond.end# public Select(MenuModel menu) { setModel(menu); softBar.setSoftBarLabels("select", "select", "back", false); } private void calcMetrix(int screenWidth) { Font menuFont = GraphicsEx.menuFont; itemHeight = menuFont.getHeight(); int textWidth = 0; iconWidth = 0; final int size = items.count(); for (int i = 0; i < size; ++i) { MenuItem item = items.itemAt(i); if (null == item.text) continue; Icon icon = item.icon; if (null != icon) { itemHeight = Math.max(itemHeight, icon.getHeight()); iconWidth = Math.max(iconWidth, icon.getWidth()); } textWidth = Math.max(textWidth, menuFont.stringWidth(item.text)); } textWidth = Math.max(screenWidth * 2 / 5, textWidth); itemHeight = Math.max(itemHeight, CanvasEx.minItemHeight); int emptySpaceWidth = Math.max(scrollerWidth, CanvasEx.minItemHeight / 3); if (0 < iconWidth) { iconWidth = Math.max(iconWidth, itemHeight); } else { iconWidth = emptySpaceWidth - ICON_INTERVAL; } int _itemWidth = textWidth + iconWidth + ICON_INTERVAL + emptySpaceWidth; int maxItemWidth = screenWidth - (WIDTH_SPACE + emptySpaceWidth); _itemWidth = between(_itemWidth, CanvasEx.minItemWidth, maxItemWidth); final int prevWidth = prevMenuWidth(); if (prevWidth == _itemWidth) { _itemWidth += emptySpaceWidth - ICON_INTERVAL; _itemWidth = between(_itemWidth, CanvasEx.minItemWidth, maxItemWidth); if (prevWidth == _itemWidth) { _itemWidth -= emptySpaceWidth - ICON_INTERVAL; _itemWidth = between(_itemWidth, CanvasEx.minItemWidth, maxItemWidth); } } itemWidth = _itemWidth; } private int prevMenuWidth() { Object last = jimm.Jimm.getJimm().getDisplay().getCurrentDisplay(); if (this == last) { Vector v = jimm.Jimm.getJimm().getDisplay().getStack(); last = (0 < v.size()) ? v.elementAt(v.size() - 1) : null; } if (last instanceof Select) { return ((Select)last).itemWidth; } return 0; } protected void showing() { selectedItemIndex = items.getDefaultItemIndex(); selectedItemPosX = 0; sleep = 0; } private int between(int x, int min, int max) { return Math.max(min, Math.min(x, max)); } protected void restoring() { selectedItemPosX = 0; sleep = 0; int screenHeight = getScreenHeight(); int screenWidth = getScreenWidth(); calcMetrix(screenWidth); itemPerPage = Math.min(screenHeight / itemHeight - 1, items.count()); width = between(itemWidth, screenWidth / 3, screenWidth - 10); left = (screenWidth - width) / 2; int height = itemHeight * itemPerPage + 2 * getHeadSpace(); top = (screenHeight - height) / 3; setSelectedItemIndex(selectedItemIndex); relocateTop(); } public void update() { restoring(); invalidate(); } public final void setModel(MenuModel model) { items = model; } public int getSelectedItemCode() { return items.getItemCodeByIndex(selectedItemIndex); } protected void paint(GraphicsEx g) { final int size = items.count(); final boolean hasScroll = (size > itemPerPage); // get top item final int curWidth = this.width; final int curHeight = itemHeight * itemPerPage + 2 * getHeadSpace(); final int currentIndex = selectedItemIndex; int y = this.top; int x = this.left; g.setStrokeStyle(Graphics.SOLID); // #sijapp cond.if modules_ANDROID is "true" # g.setClip(x, y, curWidth, curHeight); g.setThemeColor(THEME_MENU_BACK); g.getGraphics().fillRoundRect(x, y, curWidth, curHeight, getHeadSpace(), getHeadSpace()); g.setThemeColor(THEME_MENU_BORDER); g.getGraphics().drawRoundRect(x, y, curWidth, curHeight, getHeadSpace(), getHeadSpace()); // #sijapp cond.else # g.fillRect(x, y, curWidth, curHeight, THEME_MENU_BACK); g.drawDoubleBorder(x, y, curWidth, curHeight, THEME_MENU_BORDER); // #sijapp cond.end # g.setClip(x, y, curWidth + 1, curHeight + 1); y += getHeadSpace(); paintItems(g, x, y, itemPerPage, currentIndex); y -= getHeadSpace(); g.setClip(x, y, curWidth + 1, curHeight + 1); if (hasScroll) { MyScrollBar.paint(g, this, THEME_MENU_BORDER); } if (isSoftBarShown()) { softBar.paint(g, this, getHeight()); } } private void paintItems(GraphicsEx g, int baseX, int baseY, int count, int currentIndex) { Font menuFont = GraphicsEx.menuFont; int iconX = baseX + iconWidth / 2; int iconY = baseY + itemHeight / 2; int promtX = baseX + iconWidth + ICON_INTERVAL; int promtY = baseY + itemHeight / 2 - menuFont.getHeight() / 2; g.setFont(menuFont); // #sijapp cond.if modules_TOUCH is "true"# if (touchUsed && !touchPressed) currentIndex = -1; // #sijapp cond.end# for (int i = topItem; count > 0; ++i, --count) { g.setClip(baseX, baseY, itemWidth + 1, itemHeight + 1); if (currentIndex == i) { g.setThemeColor(THEME_MENU_SEL_BACK); int capBkColor = g.getThemeColor(THEME_MENU_SEL_BACK); g.fillGradRect(capBkColor, g.transformColorLight(capBkColor, -32), baseX, baseY, itemWidth, itemHeight); } MenuItem item = items.itemAt(i); g.drawInCenter(item.icon, iconX, iconY); g.setClip(baseX, baseY - 1, itemWidth, itemHeight + 2); if (null == item.text) { int posY = baseY + itemHeight / 2; g.setThemeColor(THEME_MENU_BORDER); g.drawLine(baseX, posY, baseX + itemWidth, posY); g.drawLine(baseX, posY + 1, baseX + itemWidth, posY + 1); } else if (currentIndex == i) { g.setThemeColor(THEME_MENU_SEL_TEXT); g.drawString(item.text, promtX - selectedItemPosX, promtY, Graphics.TOP | Graphics.LEFT); } else { g.setThemeColor(THEME_MENU_TEXT); g.drawString(item.text, promtX, promtY, Graphics.TOP | Graphics.LEFT); } baseY += itemHeight; iconY += itemHeight; promtY += itemHeight; } } private int getIndex(int currentIndex, int moveTo) { return Math.max(Math.min(currentIndex + moveTo, items.count() - 1), 0); } private void setSelectedItemIndex(int index) { index = getIndex(index, 0); if (index != selectedItemIndex) { selectedItemIndex = index; selectedItemPosX = 0; sleep = 0; invalidate(); } } private void relocateTop() { final int size = items.count(); final boolean hasScroll = (size > itemPerPage); int oldTop = topItem; if (hasScroll) { int newTop = topItem; newTop = Math.max(newTop, getIndex(selectedItemIndex, 1 + 1 - itemPerPage)); newTop = Math.min(newTop, getIndex(size, -itemPerPage)); newTop = Math.min(newTop, getIndex(selectedItemIndex, -1)); topItem = newTop; } else { topItem = 0; } if (oldTop != topItem) { invalidate(); } } private void nextPrevItem(boolean next) { final int size = items.count(); setSelectedItemIndex((selectedItemIndex + (next ? 1 : size - 1)) % size); relocateTop(); } protected void doJimmAction(int keyCode) { switch (keyCode) { case NativeCanvas.JIMM_SELECT: // #sijapp cond.if modules_ANDROID is "true" # back(); // #sijapp cond.else # go(getSelectedItemCode()); // #sijapp cond.end # break; case NativeCanvas.JIMM_BACK: back(); break; } } protected boolean hasMenu() { return false; } protected void doKeyReaction(int keyCode, int gameAct, int type) { if (KEY_RELEASED == type) { return; } // #sijapp cond.if modules_TOUCH is "true"# touchUsed = false; // #sijapp cond.end# switch (gameAct) { case NativeCanvas.NAVIKEY_DOWN: case NativeCanvas.NAVIKEY_UP: nextPrevItem(NativeCanvas.NAVIKEY_DOWN == gameAct); return; } if (KEY_PRESSED != type) { return; } switch (keyCode) { case NativeCanvas.CLEAR_KEY: execJimmAction(NativeCanvas.JIMM_BACK); return; case NativeCanvas.KEY_NUM1: setSelectedItemIndex(0); relocateTop(); return; case NativeCanvas.KEY_NUM7: setSelectedItemIndex(items.count() - 1); relocateTop(); return; case NativeCanvas.KEY_NUM3: case NativeCanvas.KEY_NUM9: int count = itemPerPage; if (NativeCanvas.KEY_NUM3 == keyCode) { count = -count; } setSelectedItemIndex(selectedItemIndex + count); relocateTop(); return; } switch (gameAct) { case NativeCanvas.NAVIKEY_RIGHT: // ???? case NativeCanvas.NAVIKEY_FIRE: execJimmAction(NativeCanvas.JIMM_SELECT); break; case NativeCanvas.NAVIKEY_LEFT: execJimmAction(NativeCanvas.JIMM_BACK); break; } } protected void updateTask(long microTime) { sleep++; if ((0 == selectedItemPosX) && (sleep < SLEEP_BEFORE)) return; Font menuFont = GraphicsEx.menuFont; int fullWidth = menuFont.stringWidth(items.itemAt(selectedItemIndex).text); int visWidth = itemWidth - (iconWidth + ICON_INTERVAL); if (fullWidth <= visWidth) return; if (selectedItemPosX + visWidth > (fullWidth + EMPTY_WIDTH)) { if (sleep < SLEEP_AFTER) return; selectedItemPosX = 0; } else { selectedItemPosX += STEP; } sleep = 0; invalidate(); } private void go(int code) { items.exec(this, code); } public final int getScreenWidth() { return Jimm.getJimm().getDisplay().getScreenWidth(); } public final int getScreenHeight() { if (isSoftBarShown()) { return Jimm.getJimm().getDisplay().getScreenHeight() - softBar.getHeight(); } return Jimm.getJimm().getDisplay().getScreenHeight(); } }