--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/javauis/lcdui_qt/src/javax/microedition/lcdui/Item.java Mon May 03 12:27:20 2010 +0300
@@ -0,0 +1,770 @@
+/*
+* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:
+*
+*/
+package javax.microedition.lcdui;
+
+import java.util.Vector;
+
+import javax.microedition.lcdui.EventDispatcher.LCDUIEvent;
+
+import org.eclipse.swt.graphics.Point;
+
+/**
+ * Abstract class representing an item.<br>
+ */
+public abstract class Item {
+
+ /**
+ * A layout directive.
+ */
+ public static final int LAYOUT_DEFAULT = 0;
+
+ /**
+ * A layout directive.
+ */
+ public static final int LAYOUT_LEFT = 1;
+
+ /**
+ * A layout directive.
+ */
+ public static final int LAYOUT_RIGHT = 2;
+
+ /**
+ * A layout directive.
+ */
+ public static final int LAYOUT_CENTER = 3;
+
+ /**
+ * A layout directive.
+ */
+ public static final int LAYOUT_TOP = 16;
+
+ /**
+ * A layout directive.
+ */
+ public static final int LAYOUT_BOTTOM = 32;
+
+ /**
+ * A layout directive.
+ */
+ public static final int LAYOUT_VCENTER = 48;
+
+ /**
+ * A layout directive.
+ */
+ public static final int LAYOUT_NEWLINE_BEFORE = 256;
+
+ /**
+ * A layout directive.
+ */
+ public static final int LAYOUT_NEWLINE_AFTER = 512;
+
+ /**
+ * A layout directive.
+ */
+ public static final int LAYOUT_SHRINK = 1024;
+
+ /**
+ * A layout directive.
+ */
+ public static final int LAYOUT_EXPAND = 2048;
+
+ /**
+ * A layout directive.
+ */
+ public static final int LAYOUT_VSHRINK = 4096;
+
+ /**
+ * A layout directive.
+ */
+ public static final int LAYOUT_VEXPAND = 8192;
+
+ /**
+ * A layout directive indicating that MIDP 2 layout rules are used.
+ */
+ public static final int LAYOUT_2 = 16384;
+
+ /**
+ * An appearance mode value.
+ */
+ public static final int PLAIN = 0;
+
+ /**
+ * An appearance mode value.
+ */
+ public static final int HYPERLINK = 1;
+
+ /**
+ * An appearance mode value.
+ */
+ public static final int BUTTON = 2;
+
+ /**
+ * Combination of all possible layout directives.
+ */
+ private static final int LAYOUT_BITMASK =
+ LAYOUT_DEFAULT
+ | LAYOUT_LEFT
+ | LAYOUT_RIGHT
+ | LAYOUT_CENTER
+ | LAYOUT_TOP
+ | LAYOUT_BOTTOM
+ | LAYOUT_VCENTER
+ | LAYOUT_NEWLINE_BEFORE
+ | LAYOUT_NEWLINE_AFTER
+ | LAYOUT_SHRINK
+ | LAYOUT_EXPAND
+ | LAYOUT_VSHRINK
+ | LAYOUT_VEXPAND
+ | LAYOUT_2;
+
+ static final int LAYOUT_HORIZONTAL_MASK = LAYOUT_CENTER; // 15;
+
+ static final int LAYOUT_VERTICAL_MASK = LAYOUT_VCENTER; // 48;
+
+
+ static final int UPDATE_NONE = 0;
+
+ static final int UPDATE_ADDCOMMAND = 1;
+
+ static final int UPDATE_REMOVECOMMAND = 2;
+
+ /**
+ * Item content has changed. Re-layouting not needed.
+ */
+ static final int UPDATE_CONTENT = 3; // general update value
+
+ static final int UPDATE_REASON_MASK = 255;
+
+ /**
+ * Item height has changed. Re-layouting not needed.
+ */
+ static final int UPDATE_HEIGHT_CHANGED = 256;
+
+ /**
+ * Item width is changed. Re-layouting asap.
+ */
+ static final int UPDATE_WIDTH_CHANGED = 512;
+
+ /**
+ * Item width and height changed. Re-layouting asap.
+ */
+ static final int UPDATE_SIZE_CHANGED =
+ UPDATE_HEIGHT_CHANGED | UPDATE_WIDTH_CHANGED;
+
+ private String label;
+
+ /**
+ * Vector of commands added to this item that have eSWT Command associated
+ * with them.
+ */
+ private Vector commands = new Vector();
+ private ItemCommandListener itemCommandListener;
+
+ private Command defaultCommand;
+ private Screen parent;
+
+ private int layout;
+ private int lockedPrefWidth = -1;
+ private int lockedPrefHeight = -1;
+
+ private Point calculatedMinSize;
+ private Point calculatedPrefSize;
+
+ private boolean focused;
+ private boolean visible;
+
+ /**
+ * Sets the parent of this Item.
+ * @param parent new Parent. If null, current parent is removed.
+ */
+ void setParent(Screen parent) {
+ this.parent = parent;
+ }
+
+ /**
+ * Gets the Item's parent.
+ *
+ * @return the Item's parent or null if it has none.
+ */
+ Screen getParent() {
+ return parent;
+ }
+
+ /**
+ * Sets the label of the item.
+ *
+ * @param newLabel New label to be set.
+ * @throws IllegalStateException If this item is contained within an alert.
+ */
+ public void setLabel(String newLabel) {
+ if (isContainedInAlert()) {
+ throw new IllegalStateException(
+ MsgRepository.ITEM_EXCEPTION_OWNED_BY_ALERT);
+ }
+ label = newLabel;
+ updateParent(UPDATE_SIZE_CHANGED);
+ }
+
+ /**
+ * Gets the label of the item.
+ *
+ * @return The label of the item.
+ */
+ public String getLabel() {
+ return label;
+ }
+
+ /**
+ * Returns if this item has a valid label, not null and not empty.
+ */
+ boolean hasLabel() {
+ return ((label != null) && (!label.equals("")));
+ }
+
+ /**
+ * Gets item's current layout.
+ *
+ * @return A combination of layout directives currently in use.
+ */
+ public int getLayout() {
+ return layout;
+ }
+
+ /**
+ * Sets the layout of the item.
+ *
+ * @param newLayout a Combination of layout directives to be used.
+ * @throws IllegalArgumentException if newLayout is not valid bitwise OR
+ * combination of layout directives spesified in this class.
+ * @throws IllegalStateException If this Item is contained within an Alert.
+ */
+ public void setLayout(int newLayout) {
+ if (isContainedInAlert()) {
+ throw new IllegalStateException(
+ MsgRepository.ITEM_EXCEPTION_OWNED_BY_ALERT);
+ }
+
+ if (!isValidLayout(newLayout)) {
+ throw new IllegalArgumentException(
+ MsgRepository.ITEM_EXCEPTION_INVALID_LAYOUT);
+ }
+ layout = newLayout;
+ Logger.method(this, "setLayout", String.valueOf(layout));
+ updateParent(UPDATE_SIZE_CHANGED);
+ }
+
+ /**
+ * Adds command to this item. If same command is already added to this item,
+ * nothing happens.
+ *
+ * @param command A command to be added.
+ * @throws NullPointerException if cmd is null.
+ * @throws IllegalStateException If this Item is contained within an Alert.
+ */
+ public void addCommand(Command command) {
+ if (isContainedInAlert()) {
+ throw new IllegalStateException(
+ MsgRepository.ITEM_EXCEPTION_OWNED_BY_ALERT);
+ }
+ if (command == null) {
+ throw new NullPointerException(
+ MsgRepository.ITEM_EXCEPTION_NULL_COMMAND_ADDED);
+ }
+ if (!commands.contains(command)) {
+ commands.addElement(command);
+
+ int reason = UPDATE_ADDCOMMAND;
+
+ if (this instanceof StringItem && commands.size() == 1) {
+ reason |= UPDATE_SIZE_CHANGED;
+ }
+ if (this instanceof ImageItem && commands.size() == 1) {
+ reason |= UPDATE_SIZE_CHANGED;
+ }
+
+ updateParent(reason, command);
+ }
+ }
+
+ /**
+ * Removes command from the item. If command doesn't exists in this item,
+ * nothing happens.
+ *
+ * @param command The command to be removed.
+ */
+ public void removeCommand(Command command) {
+ // It is not specified what should happen when this method is
+ // called with null-parameter !
+ if (command != null && commands.contains(command)) {
+ // Remove command from commands-vector
+ commands.removeElement(command);
+
+ int reason = UPDATE_REMOVECOMMAND;
+
+ if (this instanceof StringItem && commands.size() == 0) {
+ reason |= UPDATE_SIZE_CHANGED;
+ }
+ if (this instanceof ImageItem && commands.size() == 0) {
+ reason |= UPDATE_SIZE_CHANGED;
+ }
+
+ updateParent(reason, command);
+ }
+ }
+
+
+ /**
+ * Sets Listener which will receive command events associated with this
+ * item.
+ *
+ * @param newItemCmdListener A new listener. If null, already existing
+ * listener is removed.
+ * @throws IllegalStateException If this Item is contained within an Alert.
+ */
+ public void setItemCommandListener(ItemCommandListener newItemCmdListener) {
+ if (isContainedInAlert()) {
+ throw new IllegalStateException(
+ MsgRepository.ITEM_EXCEPTION_OWNED_BY_ALERT);
+ }
+ itemCommandListener = newItemCmdListener;
+ }
+
+ /**
+ * Gets the minimum width of this item.
+ *
+ * @return Minimum width.
+ */
+ public int getMinimumWidth() {
+ return getCalculatedMinimumSize().x;
+ }
+
+ /**
+ * Gets the minimum height of this item.
+ *
+ * @return Minimum height.
+ */
+ public int getMinimumHeight() {
+ return getCalculatedMinimumSize().y;
+ }
+
+ private Point getCalculatedMinimumSize() {
+ if (calculatedMinSize == null) {
+ calculatedMinSize = calculateMinimumSize();
+ // Logger.method(this, "calculateMinimumSize", calculatedMinSize);
+ }
+ return calculatedMinSize;
+ }
+
+ /**
+ * Calculates minimum size of this item.
+ *
+ * @return Minimum size.
+ */
+ abstract Point calculateMinimumSize();
+
+ /**
+ * Gets the preferred width of this item.
+ *
+ * @return Preferred width.
+ */
+ public int getPreferredWidth() {
+ if (lockedPrefWidth >= 0) {
+ if (calculatedMinSize == null) {
+ checkLockedSizes();
+ }
+ return lockedPrefWidth;
+ }
+ else {
+ return getCalculatedPreferredSize().x;
+ }
+ }
+
+ /**
+ * Gets the preferred height of this item.
+ *
+ * @return Preferred height.
+ */
+ public int getPreferredHeight() {
+ if (lockedPrefHeight >= 0) {
+ if (calculatedMinSize == null) {
+ checkLockedSizes();
+ }
+ return lockedPrefHeight;
+ }
+ else {
+ return getCalculatedPreferredSize().y;
+ }
+ }
+
+ private Point getCalculatedPreferredSize() {
+ if (calculatedPrefSize == null) {
+ calculatedPrefSize = calculatePreferredSize();
+ // Logger.method(this, "calculatePreferredSize", calculatedPrefSize);
+ }
+ return calculatedPrefSize;
+ }
+
+ void checkLockedSizes() {
+ if (lockedPrefWidth >= 0) {
+ lockedPrefWidth = Math.min(
+ Math.max(lockedPrefWidth, getMinimumWidth()),
+ ItemLayouter.getMaximumItemWidth(null));
+ }
+ if (lockedPrefHeight >= 0) {
+ lockedPrefHeight = Math.max(lockedPrefHeight, getMinimumHeight());
+ }
+ }
+
+ /**
+ * Invalidates this Item's calculated preferred size. Forces the
+ * implementation to calculate it again.
+ */
+ void invalidateCachedSizes() {
+ calculatedMinSize = null;
+ calculatedPrefSize = null;
+ }
+
+ /**
+ * Calculates preferred size of this item.
+ *
+ * @return Preferred size.
+ */
+ abstract Point calculatePreferredSize();
+
+ /**
+ * Sets the preferred size of this item. If new value is larger than -1 and
+ * less than minimum value, the minimum value is used instead. If value is
+ * larger than minimum value, the dimension is locked to provided value. It
+ * is possible to unlock dimension by setting value to -1.
+ *
+ * @param w New preferred width.
+ * @param h New preferred height.
+ * @throws IllegalArgumentException if w or h is less than -1.
+ * @throws IllegalStateException If this Item is contained within an Alert.
+ */
+ public synchronized void setPreferredSize(int w, int h) {
+ if (isContainedInAlert()) {
+ throw new IllegalStateException(
+ MsgRepository.ITEM_EXCEPTION_OWNED_BY_ALERT);
+ }
+ if ((w < -1) || (h < -1)) {
+ throw new IllegalArgumentException(
+ MsgRepository.ITEM_EXCEPTION_INVALID_DIMENSION);
+ }
+
+ lockedPrefWidth = w;
+ lockedPrefHeight = h;
+ checkLockedSizes();
+ Logger.method(this, "setPrefSize",
+ String.valueOf(lockedPrefWidth),
+ String.valueOf(lockedPrefHeight));
+ updateParent(UPDATE_SIZE_CHANGED);
+ }
+
+ /**
+ * Sets the default command of this item. This method doesn't remove
+ * commands from the item, it just tells which command is the default one.
+ *
+ * @param cmd New default command. If cmd doesn't exists in this item yet it
+ * is added to it. Null means that this item wont have default
+ * command at all after this call.
+ * @throws IllegalStateException If this Item is contained within an Alert.
+ */
+ public void setDefaultCommand(Command cmd) {
+ if (isContainedInAlert()) {
+ throw new IllegalStateException(
+ MsgRepository.ITEM_EXCEPTION_OWNED_BY_ALERT);
+ }
+ defaultCommand = cmd;
+ if (cmd != null) {
+ // It is safe to call addCommand() even if command already exists
+ // because the addCommand() wont create duplicates:
+ addCommand(cmd);
+ }
+
+ // Form need to be updated if this item is focused:
+ updateParent(UPDATE_SIZE_CHANGED);
+ }
+
+ /**
+ * Makes this item's containing form to notify item's ItemStateListener.
+ * This method must be called only when item's state has actually changed
+ * and when that change has occured because of user.
+ *
+ * If ItemStateListener is not set to the Form where this Item belongs,
+ * nothing happens.
+ *
+ * @throws IllegalStateException If the item is not owned by a form.
+ */
+ public void notifyStateChanged() {
+ if (!isContainedInForm()) {
+ throw new IllegalStateException(
+ MsgRepository.ITEM_EXCEPTION_NOT_OWNED_BY_FORM);
+ }
+ // Notify item state listener
+ ((Form) parent).notifyItemStateChanged(this);
+ }
+
+ /**
+ * Is this item's size locked.
+ */
+ boolean isSizeLocked() {
+ return (lockedPrefWidth >= 0) || (lockedPrefHeight >= 0);
+ }
+
+ /**
+ * Gets locked preferred width of this item.
+ *
+ * @return Locked preferred width. If width is not locked, returns -1.
+ */
+ int getLockedPreferredWidth() {
+ return lockedPrefWidth;
+ }
+
+ /**
+ * Gets locked preferred height of this item.
+ *
+ * @return Locked preferred height. If height is not locked, returns -1.
+ */
+ int getLockedPreferredHeight() {
+ return lockedPrefHeight;
+ }
+
+ /**
+ * Gets LAYOUT_2 width of this item.
+ */
+ int getLayoutWidth() {
+ if (hasLayout(LAYOUT_SHRINK)) {
+ return getMinimumWidth();
+ }
+ return getPreferredWidth();
+ }
+
+ /**
+ * Gets LAYOUT_2 height of this item.
+ */
+ int getLayoutHeight() {
+ if (hasLayout(LAYOUT_VSHRINK)) {
+ return getMinimumHeight();
+ }
+ return getPreferredHeight();
+ }
+
+ /**
+ * If the item is owned by an Alert.
+ */
+ boolean isContainedInAlert() {
+ return (parent != null && parent instanceof Alert);
+ }
+
+ /**
+ * If the item is owned by an Form.
+ */
+ boolean isContainedInForm() {
+ return (parent != null && parent instanceof Form);
+ }
+
+ /**
+ * Return internal layout with optional custom flags.
+ *
+ * @return layout directive
+ */
+ int internalGetLayout() {
+ return getLayout();
+ }
+
+ /**
+ * Updates the parent if it's a Form.
+ */
+ void updateParent(int updateReason) {
+ updateParent(updateReason, null);
+ }
+
+ /**
+ * Updates the parent if it's a Form.
+ *
+ * @param param additional parameter
+ */
+ void updateParent(int updateReason, Object param) {
+ if ((updateReason & UPDATE_SIZE_CHANGED) != 0) {
+ invalidateCachedSizes();
+ }
+ if (isContainedInForm()) {
+ ((Form) parent).updateItemState(this, updateReason, param);
+ }
+ }
+
+ boolean hasLayout(int aLayout) {
+ return (getLayout() & aLayout) != 0;
+ }
+
+ /**
+ * Check that new layout is bitwise OR combination of layout
+ * directives:
+ *
+ * @param layout Layout combination to be check.
+ * @return true If provided layout is valid.
+ */
+ static boolean isValidLayout(int layout) {
+ if ((layout & (0xffffffff ^ LAYOUT_BITMASK)) != 0) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Get Item horizontal layout directive: LAYOUT_LEFT, LAYOUT_RIGHT,
+ * LAYOUT_CENTER, DEFAULT_LAYOUT .
+ *
+ * @param layout item Layout.
+ * @return horizontal layout of an Item.
+ */
+ static int getHorizontalLayout(int layout) {
+ return layout & Item.LAYOUT_HORIZONTAL_MASK;
+ }
+
+ /**
+ * Get Item vertical Layout directive: LAYOUT_TOP, LAYOUT_BOTTOM,
+ * LAYOUT_VCENTER.
+ *
+ * @param layout item Layout.
+ * @return vertical layout of an Item.
+ */
+ static int getVerticalLayout(int layout) {
+ return layout & Item.LAYOUT_VERTICAL_MASK;
+ }
+
+ /**
+ * Is item focusable.
+ */
+ boolean isFocusable() {
+ return false;
+ }
+
+ /**
+ * Sets current item as focused
+ */
+ void internalSetFocused(boolean isFocused) {
+ if (isFocusable()) {
+ focused = isFocused;
+ }
+ }
+
+ /**
+ * Check that item has current focus on it.
+ *
+ * @return true if item has focus.
+ */
+ boolean isFocused() {
+ return focused;
+ }
+
+ /**
+ * Sets current item visibility
+ */
+ void internalSetVisible(boolean isVisible) {
+ this.visible = isVisible;
+ }
+
+ /**
+ * Check that item is visible.
+ *
+ * @return true if item is visible
+ */
+ boolean isVisible() {
+ return visible;
+ }
+
+ /**
+ * Returns the number of commands.
+ *
+ * @return number of commands.
+ */
+ int getNumCommands() {
+ return commands.size();
+ }
+
+ /**
+ * Gets default command of this item.
+ *
+ * @return Default command or null if no default set.
+ */
+ Command getDefaultCommand() {
+ return defaultCommand;
+ }
+
+ /**
+ * Returns the Default Command or if not set, then the first Command.
+ */
+ Command getMSKCommand() {
+ Command ret = null;
+ if (defaultCommand != null) {
+ ret = defaultCommand;
+ }
+ else if (commands.elementAt(0) != null) {
+ ret = (Command) commands.elementAt(0);
+ }
+ return ret;
+ }
+
+ /**
+ * Calls the command action on the owning Items command listener.
+ *
+ * @param command the Command
+ */
+ void callCommandAction(Command command) {
+ if (itemCommandListener != null && command != null) {
+ EventDispatcher eventDispatcher = EventDispatcher.instance();
+ LCDUIEvent event = eventDispatcher.newEvent(
+ LCDUIEvent.ITEM_COMMANDACTION,
+ this);
+ event.command = command;
+ event.itemCommandListener = itemCommandListener;
+ eventDispatcher.postEvent(event);
+ }
+ }
+
+ /**
+ * Gets commands of this item.
+ *
+ * @return Vector of commands added to this item.
+ * Vector may be empty but not null.
+ */
+ Vector getCommands() {
+ return commands;
+ }
+
+ /**
+ * Gets ItemCommandListener.
+ * @return Current ItemCommandListener or null if
+ * no listener set.
+ */
+ ItemCommandListener getItemCommandListener() {
+ return itemCommandListener;
+ }
+
+ /*
+ * Dispatcher thread calls.
+ */
+ void doCallback(LCDUIEvent event) {
+ switch(event.type) {
+ case LCDUIEvent.ITEM_COMMANDACTION:
+ event.itemCommandListener.commandAction(event.command, this);
+ break;
+ }
+ }
+}