blob: 9c1b120e66779e77793ca936ff05e1615e9c6e18 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package java.awt;
import java.awt.event.FocusListener;
import java.awt.event.MouseEvent;
import java.awt.peer.MenuComponentPeer;
import java.io.Serializable;
import java.util.Locale; //import javax.accessibility.Accessible;
//import javax.accessibility.AccessibleComponent;
//import javax.accessibility.AccessibleContext;
//import javax.accessibility.AccessibleRole;
//import javax.accessibility.AccessibleSelection;
//import javax.accessibility.AccessibleStateSet;
import org.apache.harmony.awt.gl.MultiRectArea;
import org.apache.harmony.awt.state.MenuItemState;
import org.apache.harmony.awt.state.MenuState;
import org.apache.harmony.luni.util.NotImplementedException;
/**
* The MenuComponent abstract class is the superclass for menu components. Menu
* components receive and process AWT events.
*
* @since Android 1.0
*/
public abstract class MenuComponent implements Serializable {
/**
* The Constant serialVersionUID.
*/
private static final long serialVersionUID = -4536902356223894379L;
/**
* The name.
*/
private String name;
/**
* The font.
*/
private Font font;
/**
* The parent.
*/
MenuContainer parent;
/**
* The deprecated event handler.
*/
boolean deprecatedEventHandler = true;
/**
* The selected item index.
*/
private int selectedItemIndex;
// ???AWT: private AccessibleContext accessibleContext;
/**
* The toolkit.
*/
final Toolkit toolkit = Toolkit.getDefaultToolkit();
// ???AWT
/*
* protected abstract class AccessibleAWTMenuComponent extends
* AccessibleContext implements Serializable, AccessibleComponent,
* AccessibleSelection { private static final long serialVersionUID =
* -4269533416223798698L; public void addFocusListener(FocusListener
* listener) { } public boolean contains(Point pt) { return false; } public
* Accessible getAccessibleAt(Point pt) { return null; } public Color
* getBackground() { return null; } public Rectangle getBounds() { return
* null; } public Cursor getCursor() { return null; } public Font getFont()
* { return MenuComponent.this.getFont(); } public FontMetrics
* getFontMetrics(Font font) { return null; } public Color getForeground() {
* return null; } public Point getLocation() { return null; } public Point
* getLocationOnScreen() { return null; } public Dimension getSize() {
* return null; } public boolean isEnabled() { return true; // always
* enabled } public boolean isFocusTraversable() { return true; // always
* focus traversable } public boolean isShowing() { return true;// always
* showing } public boolean isVisible() { return true; // always visible }
* public void removeFocusListener(FocusListener listener) { } public void
* requestFocus() { } public void setBackground(Color color) { } public void
* setBounds(Rectangle rect) { } public void setCursor(Cursor cursor) { }
* public void setEnabled(boolean enabled) { } public void setFont(Font
* font) { MenuComponent.this.setFont(font); } public void
* setForeground(Color color) { } public void setLocation(Point pt) { }
* public void setSize(Dimension pt) { } public void setVisible(boolean
* visible) { } public void addAccessibleSelection(int index) { } public
* void clearAccessibleSelection() { } public Accessible
* getAccessibleSelection(int index) { return null; } public int
* getAccessibleSelectionCount() { return 0; } public boolean
* isAccessibleChildSelected(int index) { return false; } public void
* removeAccessibleSelection(int index) { } public void
* selectAllAccessibleSelection() { }
* @Override public Accessible getAccessibleChild(int index) { return null;
* }
* @Override public int getAccessibleChildrenCount() { return 0; }
* @Override public AccessibleComponent getAccessibleComponent() { return
* this; }
* @Override public String getAccessibleDescription() { return
* super.getAccessibleDescription(); }
* @Override public int getAccessibleIndexInParent() { toolkit.lockAWT();
* try { Accessible aParent = getAccessibleParent(); int aIndex = -1; if
* (aParent instanceof MenuComponent) { MenuComponent parent =
* (MenuComponent) aParent; int count = parent.getItemCount(); for (int i =
* 0; i < count; i++) { MenuComponent comp = parent.getItem(i); if (comp
* instanceof Accessible) { aIndex++; if (comp == MenuComponent.this) {
* return aIndex; } } } } return -1; } finally { toolkit.unlockAWT(); } }
* @Override public String getAccessibleName() { return
* super.getAccessibleName(); }
* @Override public Accessible getAccessibleParent() { toolkit.lockAWT();
* try { Accessible aParent = super.getAccessibleParent(); if (aParent !=
* null) { return aParent; } MenuContainer parent = getParent(); if (parent
* instanceof Accessible) { aParent = (Accessible) parent; } return aParent;
* } finally { toolkit.unlockAWT(); } }
* @Override public AccessibleRole getAccessibleRole() { return
* AccessibleRole.AWT_COMPONENT; }
* @Override public AccessibleSelection getAccessibleSelection() { return
* this; }
* @Override public AccessibleStateSet getAccessibleStateSet() { return new
* AccessibleStateSet(); }
* @Override public Locale getLocale() { return Locale.getDefault(); } }
*/
/**
* The accessor to MenuComponent internal state, utilized by the visual
* theme.
*
* @throws HeadlessException
* the headless exception.
*/
// ???AWT
/*
* class State implements MenuState { Dimension size; Dimension getSize() {
* if (size == null) { calculate(); } return size; } public int getWidth() {
* return getSize().width; } public int getHeight() { return
* getSize().height; } public Font getFont() { return
* MenuComponent.this.getFont(); } public int getItemCount() { return
* MenuComponent.this.getItemCount(); } public int getSelectedItemIndex() {
* return MenuComponent.this.getSelectedItemIndex(); } public boolean
* isFontSet() { return MenuComponent.this.isFontSet(); }
* @SuppressWarnings("deprecation") public FontMetrics getFontMetrics(Font
* f) { return MenuComponent.this.toolkit.getFontMetrics(f); } public Point
* getLocation() { return MenuComponent.this.getLocation(); } public
* MenuItemState getItem(int index) { MenuItem item =
* MenuComponent.this.getItem(index); return item.itemState; } public void
* setSize(int w, int h) { this.size = new Dimension(w, h); } void
* calculate() { size = new Dimension();
* size.setSize(toolkit.theme.calculateMenuSize(this)); } void reset() { for
* (int i = 0; i < getItemCount(); i++) { ((MenuItem.State)
* getItem(i)).reset(); } } }
*/
/**
* Pop-up box for menu. It transfers the paint events, keyboard and mouse
* events to the menu component itself.
*/
// ???AWT
/*
* class MenuPopupBox extends PopupBox { private final Point lastMousePos =
* new Point();
* @Override boolean isMenu() { return true; }
* @Override void paint(Graphics gr) { MenuComponent.this.paint(gr); }
* @Override void onKeyEvent(int eventId, int vKey, long when, int
* modifiers) { MenuComponent.this.onKeyEvent(eventId, vKey, when,
* modifiers); }
* @Override void onMouseEvent(int eventId, Point where, int mouseButton,
* long when, int modifiers, int wheelRotation) { // prevent conflict of
* mouse and keyboard // when sub-menu drops down due to keyboard navigation
* if (lastMousePos.equals(where) && (eventId == MouseEvent.MOUSE_MOVED ||
* eventId == MouseEvent.MOUSE_ENTERED)) { return; }
* lastMousePos.setLocation(where); MenuComponent.this.onMouseEvent(eventId,
* where, mouseButton, when, modifiers); } }
*/
/**
* Instantiates a new MenuComponent object.
*
* @throws HeadlessException
* if the graphical interface environment can't support
* MenuComponents.
*/
public MenuComponent() throws HeadlessException {
toolkit.lockAWT();
try {
Toolkit.checkHeadless();
name = autoName();
selectedItemIndex = -1;
} finally {
toolkit.unlockAWT();
}
}
/**
* Gets the name of the MenuComponent object.
*
* @return the name of the MenuComponent object.
*/
public String getName() {
toolkit.lockAWT();
try {
return name;
} finally {
toolkit.unlockAWT();
}
}
/**
* Returns a String representation of the MenuComponent object.
*
* @return a String representation of the MenuComponent object.
*/
@Override
public String toString() {
toolkit.lockAWT();
try {
return getClass().getName() + "[" + paramString() + "]"; //$NON-NLS-1$ //$NON-NLS-2$
} finally {
toolkit.unlockAWT();
}
}
/**
* Gets the parent menu container.
*
* @return the parent.
*/
public MenuContainer getParent() {
toolkit.lockAWT();
try {
return parent;
} finally {
toolkit.unlockAWT();
}
}
/**
* Sets the name of the MenuComponent to the specified string.
*
* @param name
* the new name of the MenuComponent object.
*/
public void setName(String name) {
toolkit.lockAWT();
try {
this.name = name;
} finally {
toolkit.unlockAWT();
}
}
/**
* Dispatches AWT event.
*
* @param event
* the AWTEvent.
*/
public final void dispatchEvent(AWTEvent event) {
toolkit.lockAWT();
try {
processEvent(event);
if (deprecatedEventHandler) {
postDeprecatedEvent(event);
}
} finally {
toolkit.unlockAWT();
}
}
/**
* Post deprecated event.
*
* @param event
* the event.
*/
void postDeprecatedEvent(AWTEvent event) {
Event evt = event.getEvent();
if (evt != null) {
postEvent(evt);
}
}
/**
* Gets the peer of the MenuComponent; an application must not use this
* method directly.
*
* @return the MenuComponentPeer object.
* @throws NotImplementedException
* if this method is not implemented by a subclass.
* @deprecated an application must not use this method directly.
*/
@Deprecated
public MenuComponentPeer getPeer() throws org.apache.harmony.luni.util.NotImplementedException {
toolkit.lockAWT();
try {
} finally {
toolkit.unlockAWT();
}
if (true) {
throw new RuntimeException("Method is not implemented"); //TODO: implement //$NON-NLS-1$
}
return null;
}
/**
* Gets the locking object of this MenuComponent.
*
* @return the locking object of this MenuComponent.
*/
protected final Object getTreeLock() {
return toolkit.awtTreeLock;
}
/**
* Posts the Event to the MenuComponent.
*
* @param e
* the Event.
* @return true, if the event is posted successfully, false otherwise.
* @deprecated Replaced dispatchEvent method.
*/
@SuppressWarnings("deprecation")
@Deprecated
public boolean postEvent(Event e) {
toolkit.lockAWT();
try {
if (parent != null) {
return parent.postEvent(e);
}
return false;
} finally {
toolkit.unlockAWT();
}
}
/**
* Returns the string representation of the MenuComponent state.
*
* @return returns the string representation of the MenuComponent state.
*/
protected String paramString() {
toolkit.lockAWT();
try {
return getName();
} finally {
toolkit.unlockAWT();
}
}
// ???AWT
/*
* public AccessibleContext getAccessibleContext() { toolkit.lockAWT(); try
* { if (accessibleContext == null) { accessibleContext =
* createAccessibleContext(); } return accessibleContext; } finally {
* toolkit.unlockAWT(); } }
*/
/**
* Gets the font of the MenuComponent object.
*
* @return the Font of the MenuComponent object.
*/
public Font getFont() {
toolkit.lockAWT();
try {
if (font == null && hasDefaultFont()) {
return toolkit.getDefaultFont();
}
if (font == null && parent != null) {
return parent.getFont();
}
return font;
} finally {
toolkit.unlockAWT();
}
}
/**
* Checks if is font set.
*
* @return true, if is font set
*/
boolean isFontSet() {
return font != null
|| ((parent instanceof MenuComponent) && ((MenuComponent)parent).isFontSet());
}
/**
* Checks for default font.
*
* @return true, if successful.
*/
boolean hasDefaultFont() {
return false;
}
/**
* Processes an AWTEevent on this menu component.
*
* @param event
* the AWTEvent.
*/
protected void processEvent(AWTEvent event) {
toolkit.lockAWT();
try {
// do nothing
} finally {
toolkit.unlockAWT();
}
}
/**
* Removes the peer of the MenuComponent.
*/
public void removeNotify() {
toolkit.lockAWT();
try {
} finally {
toolkit.unlockAWT();
}
}
/**
* Sets the Font for this MenuComponent object.
*
* @param font
* the new Font to be used for this MenuComponent.
*/
public void setFont(Font font) {
toolkit.lockAWT();
try {
this.font = font;
} finally {
toolkit.unlockAWT();
}
}
/**
* Sets the parent.
*
* @param parent
* the new parent.
*/
void setParent(MenuContainer parent) {
this.parent = parent;
}
/**
* Gets the location.
*
* @return the location.
*/
Point getLocation() {
// to be overridden
return new Point(0, 0);
}
/**
* Gets the width.
*
* @return the width.
*/
int getWidth() {
// to be overridden
return 1;
}
/**
* Gets the height.
*
* @return the height.
*/
int getHeight() {
// to be overridden
return 1;
}
/**
* Recursively find the menu item for a menu shortcut.
*
* @param gr
* the gr.
* @return the menu item; or null if the item is not available for this
* shortcut.
*/
// ???AWT
/*
* MenuItem getShortcutMenuItemImpl(MenuShortcut ms) { if (ms == null) {
* return null; } for (int i = 0; i < getItemCount(); i++) { MenuItem mi =
* getItem(i); if (mi instanceof Menu) { mi = ((Menu)
* mi).getShortcutMenuItemImpl(ms); if (mi != null) { return mi; } } else if
* (ms.equals(mi.getShortcut())) { return mi; } } return null; }
*/
void paint(Graphics gr) {
gr.setColor(Color.LIGHT_GRAY);
gr.fillRect(0, 0, getWidth(), getHeight());
gr.setColor(Color.BLACK);
}
/**
* Mouse events handler.
*
* @param eventId
* one of the MouseEvent.MOUSE_* constants.
* @param where
* mouse location.
* @param mouseButton
* mouse button that was pressed or released.
* @param when
* event time.
* @param modifiers
* input event modifiers.
*/
void onMouseEvent(int eventId, Point where, int mouseButton, long when, int modifiers) {
// to be overridden
}
/**
* Keyboard event handler.
*
* @param eventId
* one of the KeyEvent.KEY_* constants.
* @param vKey
* the key code.
* @param when
* event time.
* @param modifiers
* input event modifiers.
*/
void onKeyEvent(int eventId, int vKey, long when, int modifiers) {
// to be overridden
}
/**
* Post the ActionEvent or ItemEvent, depending on type of the menu item.
*
* @param index
* the index.
* @return the item rect.
*/
// ???AWT
/*
* void fireItemAction(int item, long when, int modifiers) { MenuItem mi =
* getItem(item); mi.itemSelected(when, modifiers); } MenuItem getItem(int
* index) { // to be overridden return null; } int getItemCount() { return
* 0; }
*/
/**
* @return The sub-menu of currently selecetd item, or null if such a
* sub-menu is not available.
*/
// ???AWT
/*
* Menu getSelectedSubmenu() { if (selectedItemIndex < 0) { return null; }
* MenuItem item = getItem(selectedItemIndex); return (item instanceof Menu)
* ? (Menu) item : null; }
*/
/**
* Convenience method for selectItem(index, true).
*/
// ???AWT
/*
* void selectItem(int index) { selectItem(index, true); }
*/
/**
* Change the selection in the menu.
*
* @param index
* new selecetd item's index.
* @param showSubMenu
* if new selected item has a sub-menu, should that sub-menu be
* displayed.
*/
// ???AWT
/*
* void selectItem(int index, boolean showSubMenu) { if (selectedItemIndex
* == index) { return; } if (selectedItemIndex >= 0 &&
* getItem(selectedItemIndex) instanceof Menu) { ((Menu)
* getItem(selectedItemIndex)).hide(); } MultiRectArea clip =
* getUpdateClip(index, selectedItemIndex); selectedItemIndex = index;
* Graphics gr = getGraphics(clip); if (gr != null) { paint(gr); } if
* (showSubMenu) { showSubMenu(selectedItemIndex); } }
*/
/**
* Change the selected item to the next one in the requested direction
* moving cyclically, skipping separators
*
* @param forward
* the direction to move the selection.
* @param showSubMenu
* if new selected item has a sub-menu, should that sub-menu be
* displayed.
*/
// ???AWT
/*
* void selectNextItem(boolean forward, boolean showSubMenu) { int selected
* = getSelectedItemIndex(); int count = getItemCount(); if (count == 0) {
* return; } if (selected < 0) { selected = (forward ? count - 1 : 0); } int
* i = selected; do { i = (forward ? (i + 1) : (i + count - 1)) % count; i
* %= count; MenuItem item = getItem(i); if (!"-".equals(item.getLabel())) {
* //$NON-NLS-1$ selectItem(i, showSubMenu); return; } } while (i !=
* selected); } void showSubMenu(int index) { if ((index < 0) ||
* !isActive()) { return; } MenuItem item = getItem(index); if (item
* instanceof Menu) { Menu menu = ((Menu) getItem(index)); if
* (menu.getItemCount() == 0) { return; } Point location =
* getSubmenuLocation(index); menu.show(location.x, location.y, false); } }
*/
/**
* @return the menu bar which is the root of current menu's hierarchy; or
* null if the hierarchy root is not a menu bar.
*/
// ???AWT
/*
* MenuBar getMenuBar() { if (parent instanceof MenuBar) { return (MenuBar)
* parent; } if (parent instanceof MenuComponent) { return ((MenuComponent)
* parent).getMenuBar(); } return null; } PopupBox getPopupBox() { return
* null; }
*/
Rectangle getItemRect(int index) {
// to be overridden
return null;
}
/**
* Determine the clip region when menu selection is changed from index1 to
* index2.
*
* @param index1
* old selected item.
* @param index2
* new selected item.
* @return the region to repaint.
*/
final MultiRectArea getUpdateClip(int index1, int index2) {
MultiRectArea clip = new MultiRectArea();
if (index1 >= 0) {
clip.add(getItemRect(index1));
}
if (index2 >= 0) {
clip.add(getItemRect(index2));
}
return clip;
}
/**
* Gets the submenu location.
*
* @param index
* the index.
* @return the submenu location.
*/
Point getSubmenuLocation(int index) {
// to be overridden
return new Point(0, 0);
}
/**
* Gets the selected item index.
*
* @return the selected item index.
*/
int getSelectedItemIndex() {
return selectedItemIndex;
}
/**
* Hide.
*/
void hide() {
selectedItemIndex = -1;
if (parent instanceof MenuComponent) {
((MenuComponent)parent).itemHidden(this);
}
}
/**
* Item hidden.
*
* @param mc
* the mc.
*/
void itemHidden(MenuComponent mc) {
// to be overridden
}
/**
* Checks if is visible.
*
* @return true, if is visible.
*/
boolean isVisible() {
return true;
}
/**
* Checks if is active.
*
* @return true, if is active.
*/
boolean isActive() {
return true;
}
/**
* Hide all menu hierarchy.
*/
void endMenu() {
// ???AWT: toolkit.dispatcher.popupDispatcher.deactivateAll();
}
/**
* Handle the mouse click or Enter key event on a menu's item.
*
* @param when
* the event time.
* @param modifiers
* input event modifiers.
*/
void itemSelected(long when, int modifiers) {
endMenu();
}
/**
* Auto name.
*
* @return the string.
*/
String autoName() {
String name = getClass().getName();
if (name.indexOf("$") != -1) { //$NON-NLS-1$
return null;
}
// ???AWT: int number = toolkit.autoNumber.nextMenuComponent++;
int number = 0;
name = name.substring(name.lastIndexOf(".") + 1) + Integer.toString(number); //$NON-NLS-1$
return name;
}
/**
* Creates the Graphics object for the pop-up box of this menu component.
*
* @param clip
* the clip to set on this Graphics.
* @return the created Graphics object, or null if such object is not
* available.
*/
Graphics getGraphics(MultiRectArea clip) {
// to be overridden
return null;
}
/**
* @return accessible context specific for particular menu component.
*/
// ???AWT
/*
* AccessibleContext createAccessibleContext() { return null; }
*/
}