⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 menuoption.java

📁 关于J4ME J2ME实例
💻 JAVA
字号:
package org.j4me.ui.components;

import javax.microedition.lcdui.*;
import org.j4me.ui.*;

/**
 * The <code>Menu</code> screen uses one of these <code>MenuOption</code> components
 * for each menu choice.
 * <p>
 * The default implementation shows the choice number on the left, then
 * the text for the choice, and an arrow on the right if it is a submenu.
 * The text is clipped if it runs over a single line.  This keeps all
 * menu items the same height.
 * 
 * @see Menu
 */
public class MenuOption
	extends Component
{
	/**
	 * The number of pixels that separates the text and submenu
	 * indicator from the left and right edges of the component.
	 * Increasing this number reduces the width of usuable space
	 * to write the menu choice's text.
	 */
	private static final int HORIZONTAL_MARGIN = 3;
	
	/**
	 * The number of pixels that separate the text from the top
	 * and bottom of the menu indicator.  Increasing this value
	 * also increases the spacing between menu items by a factor
	 * of two (i.e. the bottom of this one plus top of the next).
	 */
	private static final int VERTICAL_MARGIN = HORIZONTAL_MARGIN;
	
	/**
	 * The <code>MenuItem</code> encapsulated by this component.  If this
	 * component is for a <code>DeviceScreen</code> option, this will be
	 * <code>null</code>.
	 */
	private final MenuItem menuItem;
	
	/**
	 * The <code>DeviceScreen</code> encapsulated by this component.  If this
	 * component is for a <code>MenuItem</code> option, this will be
	 * <code>null</code>.
	 */
	private final DeviceScreen screen;

	/**
	 * The menu text to use if explicitly set.  This can be <code>null</code>
	 * in which case <code>menuItem.getText()</code> or <code>screen.getTitle()</code>
	 * should be used.
	 */
	private String screenText;
	
	/**
	 * This is the menu text for this choice.  It comes from the
	 * <code>MenuItem</code> or <code>DeviceScreen</code> this choice represents.
	 */
	private final Label text = new Label();
	
	/**
	 * When <code>true</code> it indicates this option is for a submenu of
	 * the current menu.  Submenus have an arrow that appears to the
	 * right of the option text.  There is nothing else special about
	 * them.
	 */
	private boolean submenu = false;
	
	/**
	 * Creates a new <code>MenuOption</code> component that encapsulates a
	 * <code>MenuItem</code>.
	 * 
	 * @param choice is the command that is represented by this component.
	 */
	public MenuOption (MenuItem choice)
	{
		if ( choice == null )
		{
			throw new IllegalArgumentException("choice cannot be null");
		}
		
		if ( choice.getText() == null )
		{
			throw new IllegalArgumentException("choice text cannot be null");
		}
		
		this.menuItem = choice;
		this.screen = null;
	}
	
	/**
	 * Creates a new <code>MenuOption</code> component that encapsulates a
	 * <code>DeviceScreen</code>.
	 * 
	 * @param choice is the command that is represented by this component.
	 */
	public MenuOption (DeviceScreen choice)
	{
		if ( choice == null )
		{
			throw new IllegalArgumentException("choice cannot be null");
		}
		
		this.menuItem = null;
		this.screen = choice;
	}

	/**
	 * Creates a new <code>MenuOption</code> component that encapsulates a
	 * <code>DeviceScreen</code>.
	 * 
	 * @param text is string that appears in the menu option.
	 * @param choice is the command that is represented by this component.
	 */
	public MenuOption (String text, DeviceScreen choice)
	{
		if ( choice == null )
		{
			throw new IllegalArgumentException("choice cannot be null");
		}
		
		this.menuItem = null;
		this.screen = choice;
		this.screenText = text;
	}

	/**
	 * Creates a new <code>MenuOption</code> component that encapsulates a
	 * <code>Menu</code>.
	 * 
	 * @param choice is the command that is represented by this component.
	 * @param submenu when <code>true</code> indicates this is a submenu of the
	 *  current menu.
	 */
	public MenuOption (Menu choice, boolean submenu)
	{
		this( choice );
		this.submenu = submenu;
	}

	/**
	 * @return <code>true</code> if this choice represents a submenu;
	 *  <code>false</code> otherwise.
	 */
	public boolean isSubmenu ()
	{
		return submenu;
	}

	/**
	 * Explicitly sets the text shown in this menu option.  This
	 * overrides any value set by the <code>MenuItem</code> or the title
	 * of the <code>DeviceScreen</code>.  To clear explicitly set text pass
	 * in <code>null</code>.
	 *
	 * @param label is the text that will appear for this menu item.
	 *  If <code>null</code> the <code>MenuItem.getText()</code> or
	 *  <code>DeviceScreen.getTitle()</code> will be used.
	 */
	public void setLabel (String label)
	{
		screenText = label;
	}
	
	/**
	 * @return The text displayed for this menu item.  It is never
	 *  <code>null</code>.
	 */
	public String getLabel ()
	{
		// Always use explicitly set text.
		if ( screenText != null )
		{
			return screenText;
		}
		
		// Otherwise use implied text.
		String label;
		
		if ( menuItem != null )
		{
			label = menuItem.getText();
		}
		else  // ( screen != null )
		{
			label = screen.getTitle();
		}
		
		if ( label == null )
		{
			label = "";
		}
		
		return label;
	}

	/**
	 * Activates the command represented by this choice.  The <code>Menu</code>
	 * class will call this method when the user selects this choice.
	 */
	public void select ()
	{
		if ( menuItem != null )
		{
			menuItem.onSelection();
		}
		else  // screen != null
		{
			screen.show();
		}
	}
	
	/**
	 * An event raised whenever the component is made visible on the screen.
	 * This is called before the <code>paintComponent</code> method.
	 */
	protected void showNotify ()
	{
		// Pass the event to contained components.
		text.show( true );
		
		// Continue processing the event.
		super.showNotify();
	}

	/**
	 * An event raised whenever the component is removed from the screen.
	 */
	protected void hideNotify ()
	{
		// Pass the event to contained components.
		text.show( false );
		
		// Continue processing the event.
		super.hideNotify();
	}
	
	/**
	 * Paints a <code>MenuOption</code>.  On the left is the choice number in
	 * a box.  The middle has the text for the choice.  If it is a submenu
	 * the right has an arrow.
	 * 
	 * @param g is the <code>Graphics</code> object to paint with.
	 * @param theme is the application's theme used to paint the menu item.
	 * @param width is the width of the menu item area in pixels.
	 * @param height is the height of the menu item area in pixels.
	 * @param selected is <code>true</code> if this is the currently highlighted
	 *  menu choice.
	 *  
	 * @see org.j4me.ui.components.Component#paintComponent(javax.microedition.lcdui.Graphics, org.j4me.ui.Theme, int, int, boolean)
	 */
	protected void paintComponent (Graphics g, Theme theme, int width, int height, boolean selected)
	{
		// Paint the background for the menu item.
		int backgroundColor = selected ?
				theme.getHighlightColor() :
				theme.getBackgroundColor();
		g.setColor( backgroundColor );
		
		g.fillRect( 0, 0, width, height );

		// Calculate the dimensions of the text and submenu arrow.
		int[] submenuDimensions = getSubmenuIndicatorSize( theme, width, height );
		int textWidth = width - 3 * HORIZONTAL_MARGIN - submenuDimensions[0];

		int[] textDimensions = getPreferredTextSize( theme, textWidth, height );
		int textHeight = textDimensions[1];
		int textTop = (height - textHeight) / 2;
		int textLeft = HORIZONTAL_MARGIN;

		// Paint the menu text.
		paintText( g, theme, textLeft, textTop, textWidth, textHeight, selected );

		// If this is a submenu, paint an arrow next to it.
		if ( submenu )
		{
			// Get the dimensions of the arrow.
			int arrowHeight = submenuDimensions[1];
			
			if ( arrowHeight % 2 == 0 )
			{
				// The arrow height must odd to make a good looking triangle.
				arrowHeight--;
			}
			
			int arrowWidth = submenuDimensions[0];
			int arrowX = width - HORIZONTAL_MARGIN - arrowWidth;
			int arrowY = (height - arrowHeight) / 2;

			// Set the color of the arrow.
			int arrowColor = selected ?
					theme.getMenuFontColor() :
					theme.getFontColor();
			g.setColor( arrowColor );
			
			// Draw the arrow as a triangle.
			g.fillTriangle(
					arrowX, arrowY,
					arrowX, arrowY + arrowHeight,
					arrowX + arrowWidth, arrowY + arrowHeight / 2 + 1 );
		}
	}

	/**
	 * Paints a the text within the menu option component.
	 * 
	 * @param g is the <code>Graphics</code> object to paint with.
	 * @param theme is the application's theme used to paint the menu item.
	 * @param x is the left of the text area.
	 * @param y is the top of the text area.
	 * @param width is the width of the menu item area in pixels.
	 * @param height is the height of the menu item area in pixels.
	 * @param selected is <code>true</code> if this is the currently highlighted
	 *  menu choice.
	 *  
	 * @see #paintComponent(Graphics, Theme, int, int, boolean)
	 */
	protected void paintText (Graphics g, Theme theme, int x, int y, int width, int height, boolean selected)
	{
		// Set the font color.
		int fontColor = selected ?
				theme.getBackgroundColor() :
				theme.getFontColor();
		text.setFontColor( fontColor );
		
		// Paint the text.
		text.paint( g, theme, getScreen(),
				x, y, width, height,
				selected );
	}
	
	/**
	 * Returns the size of the menu choice.  It will be one line of text
	 * high and as wide as the screen.
	 * 
	 * @see org.j4me.ui.components.Component#getPreferredComponentSize(org.j4me.ui.Theme, int, int)
	 */
	protected int[] getPreferredComponentSize (Theme theme, int viewportWidth, int viewportHeight)
	{
		// Calculate the dimensions of the non-text parts.
		int[] submenuDimensions = getSubmenuIndicatorSize( theme, viewportWidth, viewportHeight );
		
		// Calculate the width of the area the text can appear in.
		int textWidth = viewportWidth - 3 * HORIZONTAL_MARGIN - submenuDimensions[0];

		// Calculate the dimensions of the text.
		int[] textDimensions = getPreferredTextSize( theme, textWidth, viewportHeight );
		
		// The height is the greater of them.
		int height = Math.max( textDimensions[1], submenuDimensions[1] );
		height += 2 * VERTICAL_MARGIN;
		
		return new int[] { viewportWidth, height };
	}

	/**
	 * Returns the size of the menu text.
	 * 
	 * @param theme is the application's <code>Theme</code>.
	 * @param viewportWidth is the width of the screen in pixels.
	 * @param viewportHeight is the height of the screen in pixels.
	 * @return An array with two elements where the first is the width
	 *  in pixels and the second is the height.
	 */
	protected int[] getPreferredTextSize (Theme theme, int viewportWidth, int viewportHeight)
	{
		text.setLabel( getLabel() );
		return text.getPreferredSize( theme, viewportWidth, viewportHeight );
	}
	
	/**
	 * Returns the size of the submenu indicator.  It appears at the right
	 * of this component.
	 * 
	 * @param theme is the application's <code>Theme</code>.
	 * @param viewportWidth is the width of the screen in pixels.
	 * @param viewportHeight is the height of the screen in pixels.
	 * @return An array with two elements where the first is the width
	 *  in pixels and the second is the height.
	 */
	protected int[] getSubmenuIndicatorSize (Theme theme, int viewportWidth, int viewportHeight)
	{
		// Get the dimensions of the arrow.
		Font textFont = theme.getFont();
		int arrowHeight = textFont.getHeight() * 4 / 5;  // 80%
		
		if ( arrowHeight % 2 == 0 )
		{
			// The arrow height must odd to make a good looking triangle.
			arrowHeight--;
		}
		
		int arrowWidth = arrowHeight / 2;

		return new int[] { arrowWidth, arrowHeight };
	}
	
	/**
	 * @return <code>true</code> because this component accepts user input.
	 */
	public boolean acceptsInput ()
	{
		return true;
	}
	
	/**
	 * Called when the user presses any key.
	 * 
	 * @param key is code of the key that was pressed.
	 * 
	 * @see Component#keyPressed(int)
	 */
	public void keyPressed (int key)
	{
		// The joystick's fire button means to select this item.
		if ( key == DeviceScreen.FIRE )
		{
			select();
		}
		
		// Continue processing the key event.
		super.keyPressed( key );
	}
	
	/**
	 * Called when the pointer is pressed.
	 * 
	 * @param x is the horizontal location where the pointer was pressed
	 *  relative to the top-left corner of the component.
	 * @param y is the vertical location where the pointer was pressed
	 *  relative to the top-left corner of the component.
	 */
	public void pointerPressed (int x, int y)
	{
		// If anywhere on the menu item is pressed it has been selected.
		select();
		
		// Continue processing the pointer event.
		super.pointerPressed( x, y );
	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -