📄 dialog.java
字号:
package org.j4me.ui;
import java.util.*;
import javax.microedition.lcdui.*;
import org.j4me.ui.components.*;
import org.j4me.util.*;
/**
* The <code>Dialog</code> class is a base class for any screen that accepts user input
* using standard components like the text box. It is similar to the MIDP <code>Form</code> class
* except that it uses the J4ME control flow and has an OK and Cancel button built in.
* <p>
* Form classes can only have component objects, like the text box or label, placed on them.
* The class handles layout, painting, and management of the components.
* If you need direct control over the appearance of the screen use the <code>DeviceScreen</code>
* class.
*
* @see javax.microedition.lcdui.Form
*/
public abstract class Dialog
extends DeviceScreen
{
/**
* The collection of all components on this form. Components are displayed
* as ordered from top to bottom.
*/
private Vector components = new Vector();
/**
* The index of <code>component</code> the user currently has highlighted.
* If this is not an index of <code>component</code> nothing is highlighted.
*/
private int highlightedComponent = -1;
/**
* The number of pixels between the left and right of the screen and the
* components. This also pads the top and bottom of the form; however,
* scrolling can make the text appear at the very top and bottom of the
* screen.
*/
private int margin = 5;
/**
* The number of pixels above and below components.
*/
private int spacing = margin;
/**
* The offset into the form that has been scrolled down. 0 indicates
* the very top of the form is shown at the top of the screen. 100
* would indicate that the current top of the screen (i.e. y == 0)
* shows the 100th pixel down in the form. If the first component
* were 80 pixels tall and the second 40, 100 would mean the bottom
* half of the second component would be at the top of the screen.
*/
private int topOfScreen = 0;
/**
* The number of pixels wide each component is.
* <p>
* When the form is painted for the first time this number will be
* calculated. If the components on the form are changed, this will be
* reset back to <code>null</code>.
* <p>
* The last element in this array is a dummy element.
*/
private int[] componentWidths = null;
/**
* The number of pixels high the entire form is with all the components
* on it. If this number is greater than the height of the screen, a
* vertical scrollbar will be added to the side.
* <p>
* When the form is painted for the first time this number will be
* calculated. If the components on the form are changed, this will be
* reset back to <code>null</code>.
* <p>
* The last element in this array is a dummy element. Its value helps
* determine the bottom of the last component.
*/
private int[] absoluteHeights = null;
/**
* Implicitly called by derived classes to setup a new J4ME form.
*/
public Dialog ()
{
super();
// Set the default menu options.
Theme theme = UIManager.getTheme();
String cancel = theme.getMenuTextForCancel();
String ok = theme.getMenuTextForOK();
setMenuText( cancel, ok );
}
/**
* Called immediately before this screen is replaced by another screen.
* <p>
* Notifies all the components they are hidden. Classes that override
* this method should be sure to call <code>super.onDeselection</code>.
*
* @see DeviceScreen#hideNotify()
*/
public void hideNotify ()
{
// Hide all the components on the screen.
Enumeration e = components.elements();
while ( e.hasMoreElements() )
{
Component c = (Component)e.nextElement();
c.show( false );
}
// Continue deselection.
super.hideNotify();
}
/**
* Adds the <code>component</code> to the end of this form.
*
* @param component is the UI component to add to the bottom of the form.
*/
public void append (Component component)
{
clearLayout();
components.addElement( component );
}
/**
* Inserts the <code>component</code> in this form at the specified <code>index</code>.
* Each component on this form with an index greater or equal to the
* specified <code>index</code> is shifted upward to have an index one greater
* than the value it had previously.
*
* @param component is the UI component to insert.
* @param index is where to insert <code>component</code> on the form. It must
* greater than or equal to 0 and less than or equal to the number of
* components already on the form.
* @throws ArrayIndexOutOfBoundsException if the index was invalid.
*/
public void insert (Component component, int index)
{
clearLayout();
components.insertElementAt( component, index );
}
/**
* Sets the <code>component</code> in this form at the specified <code>index</code>.
* The previous component at that position is discarded.
*
* @param component is the UI component to set to.
* @param index is where to set <code>component</code> on the form. It must
* greater than or equal to 0 and less than the number of
* components already on the form.
* @throws ArrayIndexOutOfBoundsException if the index was invalid.
*/
public void set (Component component, int index)
{
clearLayout();
components.setElementAt( component, index );
}
/**
* Removes the first occurrence of the <code>component</code> from this form.
* If <code>component</code> is found on this form, each component on the form
* with an index greater or equal to the <code>component</code>'s index is
* shifted downward to have an index one smaller than the value it had
* previously.
*
* @param component is the UI component to remove.
*/
public void delete (Component component)
{
clearLayout();
components.removeElement( component );
}
/**
* Deletes the <code>component</code> at the specified <code>index</code>. Each
* component in this vector with an index greater or equal to the
* specified index is shifted downward to have an index one smaller
* than the value it had previously.
*
* @param index is the index of the component to remove. It must be
* a value greater than or equal to 0 and less than the current
* number of components on the form.
* @throws ArrayIndexOutOfBoundsException if the index was invalid.
*/
public void delete (int index)
{
clearLayout();
components.removeElementAt( index );
}
/**
* Removes all of the components from this form.
*/
public void deleteAll ()
{
clearLayout();
components.removeAllElements();
}
/**
* Returns an enumeration of the components on this form.
*
* @return An enumeration of the components on this form.
*/
public Enumeration components ()
{
clearLayout();
return components.elements();
}
/**
* Returns the number of components on this form.
*
* @return The number of components on this form.
*/
public int size ()
{
return components.size();
}
/**
* Returns the component at the specified index.
*
* @param index is the value into the component list to get.
* @return The component at <code>index</code> or <code>null</code> if the
* index is invalid.
*/
public Component get (int index)
{
Component c = null;
if ( (index >= 0) && (index < components.size()) )
{
c = (Component)components.elementAt( index );
}
return c;
}
/**
* Returns the index of the currently selected component. It is
* the one the user can currently enter data into.
*
* @return The index of the component on the form that is currently
* selected.
*/
public int getSelected ()
{
if ( highlightedComponent < 0 )
{
return 0;
}
else
{
return highlightedComponent;
}
}
/**
* Returns the index of the component that contains the given pixel.
* If no component is at that location, for example it is in the
* spacing between components, then <code>-1</code> is returned.
* <p>
* This method assumes that the click is relative to the form
* area. It may not address the title bar, menu bar, or a
* scroll bar.
*
* @param x is the X-coordinate of the pixel on the form.
* @param y is the Y-coordinate of the pixel on the form.
* @return The index of the component containing the pixel
* (<code>x</code>, <code>y</code>) or <code>-1</code> if no component contains it.
*/
private int getAt (int x, int y)
{
int matched = -1;
// Get the absolute position of y on the form.
int absY = topOfScreen + y;
// Walk the list of component positions until absY is found.
for ( int i = 0; i < absoluteHeights.length - 1; i++ )
{
// Get the dimensions of this component.
int top = absoluteHeights[i];
int topOfNext = absoluteHeights[i + 1];
int bottom = topOfNext - spacing;
int left = margin;
int right = left + componentWidths[i];
// Does the point fall within this component?
if ( (absY >= top) && (absY < bottom) &&
(x >= left) && (x < right) )
{
// This is the component that (x, y) falls within.
matched = i;
}
// Stop processing if point is above the top of the component.
if ( absY < topOfNext )
{
break;
}
}
return matched;
}
/**
* Sets the selected component. It is the one the user can input
* data into and that the screen is scrolled to.
*
* @param index is the new selected component.
*/
public void setSelected (int index)
{
if ( (index < 0) || (index >= components.size()) )
{
throw new IndexOutOfBoundsException( String.valueOf(index) );
}
highlightedComponent = index;
// Scroll screen to this component.
if ( absoluteHeights == null )
{
calculateLayout( UIManager.getTheme(), getWidth(), getHeight() );
}
// Set the top of the screen.
if ( index == 0 )
{
// The top of the screen will be the very start.
topOfScreen = 0;
}
else
{
// The top of the screen will be the top of the component.
topOfScreen = absoluteHeights[index] - spacing;
}
// Adjust the top of the screen for scrolling.
int maxScroll = absoluteHeights[absoluteHeights.length - 1] - getHeight();
if ( maxScroll <= 0 )
{
// All the components fit on one form.
topOfScreen = 0;
}
else if ( topOfScreen > maxScroll )
{
// Scroll all the way to the bottom. The highlighted
// component will be visible, but not at the top of the page.
topOfScreen = maxScroll;
}
}
/**
* Sets the selected component. It is the one the user can input
* data into and that the screen is scrolled to.
*
* @param component is the new selected component. If it is not
* on the form this has no effect.
*/
public void setSelected (Component component)
{
int index = 0;
// Walk the list of components until we find it.
Enumeration e = components.elements();
while ( e.hasMoreElements() )
{
Component c = (Component)e.nextElement();
if ( c == component )
{
// This is the component.
break;
}
index++;
}
// Set the component as the selected one.
if ( index < size() )
{
setSelected( index );
}
}
/**
* Paints the form and its components. The layout is calculated from the
* components and their order.
*
* @param g is the <code>Graphics</code> object to paint with.
*/
protected synchronized void paint (Graphics g)
{
// Have we determined the layout?
Theme theme = UIManager.getTheme();
int height = getHeight();
// Add a vertical scrollbar?
if ( hasVerticalScrollbar() )
{
// Paint the scrollbar.
int width = super.getWidth(); // Exclude the margins and scrollbar
int heightOfAllComponents = absoluteHeights[absoluteHeights.length - 1];
paintVerticalScrollbar( g, 0, 0, width, height, topOfScreen, heightOfAllComponents );
}
// Walk the list of components and paint them.
int formWidth = getWidth();
int bottomOfScreen = topOfScreen + height;
Enumeration list = components.elements();
for ( int i = 0; i < absoluteHeights.length - 1; i++ )
{
Component c = (Component)list.nextElement();
int componentTop = absoluteHeights[i];
int componentBottom = absoluteHeights[i + 1] - spacing;
// Is the component visible on the screen?
if ( componentTop >= bottomOfScreen )
{
// Skip drawing components below the screen.
c.show( false );
}
else if ( componentBottom <= topOfScreen )
{
// Skip drawing components above the screen.
c.show( false );
}
else // visible
{
c.show( true );
// Calculate the position of the component.
int componentX = margin;
int componentY = componentTop - topOfScreen;
int componentWidth = formWidth;
int componentHeight = componentBottom - componentTop;
// Paint this component.
if ( intersects(g, componentX, componentY, componentWidth, componentHeight) )
{
boolean selected = (i == highlightedComponent);
c.paint( g, theme, this,
componentX, componentY,
componentWidth, componentHeight,
selected );
}
}
}
}
/**
* Returns the margin for the left and right of the screen. This
* also pads the top and bottom of the form; however, scrolling can
* make the text appear at the very top and bottom of the screen.
*
* @return The number of pixels between components and the edges
* of the screen.
*/
public int getMargin ()
{
return margin;
}
/**
* Sets the margin for the left and right of the screen. This
* also pads the top and bottom of the form; however, scrolling can
* make the text appear at the very top and bottom of the screen.
*
* @param margin is the number of pixels between components and
* the edges of the screen. Values less than 0 are ignored.
*/
public void setMargin (int margin)
{
if ( (margin >= 0) && (this.margin != margin) )
{
this.margin = margin;
// Recalculate the layout with the new margins later.
clearLayout();
}
}
/**
* Returns the vertical spacing between components.
*
* @return The number of pixels that vertically separate components.
*/
public int getSpacing ()
{
return spacing;
}
/**
* Sets the vertical spacing between components.
*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -