|
Developing GUI Components
An Introduction with Examples in Java |
|
Prof. David Bernstein |
| Computer Science Department |
| bernstdh@jmu.edu |
Widget Classpackage widget;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Panel;
/**
* The parent class of all GUI components/widgets
*
* @author Prof. David Bernstein, James Madison University
* @version 1.0
*/
public abstract class Widget extends Panel
implements FocusListener
{
protected boolean doubleBuffered = true;
protected boolean hasFocus = false;
protected Graphics bufferedGraphics;
protected Image bufferedImage;
/**
* Default Constructor
*/
public Widget()
{
super();
}
/**
* Process a focusGained event
*
* @param evt The FocusEvent
*/
public void focusGained(FocusEvent evt)
{
if (!evt.isTemporary()) setHasFocus(true);
}
/**
* Process a focusLost event
*
* @param evt The FocusEvent
*/
public void focusLost(FocusEvent evt)
{
if (!evt.isTemporary()) setHasFocus(false);
}
/**
* Get a color for this widget/Component
*
* @param part The part of the component (e.g., BORDER)
* @param state The state (e.g., DISABLED)
* @return The Color
*/
public Color getColor(int part, int state)
{
return getView().getColor(part, state);
}
/**
* Get the model associated with this component/Widget
*
* @return The model
*/
public abstract WidgetModel getModel();
/**
* Get the view associated with this component/Widget
*
* @return The view
*/
public abstract WidgetView getView();
/**
* Get the minimum amount of size required by this
* component/Widget
*
* @return The minimum required size
*/
public Dimension getMinimumSize()
{
return getView().getMinimumSize();
}
/**
* Get the preferred size for this component/Widget
*
* @return The minimum required size
*/
public Dimension getPreferredSize()
{
return getMinimumSize();
}
/**
* Does this component/Widget have the focus?
*
* @return true if the component has the focus
*/
public boolean hasFocus()
{
return hasFocus;
}
/**
* Is the component/Widget capable of having the focus?
*
* @return true if the component can/should get the focus
*/
public boolean isFocusTraversable()
{
return true;
}
/**
* Paint this component/Widget
*
* @param g The Graphics context to use
*/
public void paint(Graphics g)
{
if (doubleBuffered)
{
if ( (bufferedImage == null) ||
(getSize().width != bufferedImage.getWidth(null)) ||
(getSize().height != bufferedImage.getHeight(null)) )
{
bufferedImage = createImage(getSize().width,
getSize().height);
bufferedGraphics = bufferedImage.getGraphics();
}
bufferedGraphics.setFont(g.getFont());
getView().paint(bufferedGraphics);
g.drawImage(bufferedImage, 0, 0, null);
}
else
{
getView().paint(g);
}
}
/**
* Pause (i.e., sleep) for the specified amount of time
*
* @param millis The number of millseconds to pause
*/
public void pause(int millis)
{
try
{
Thread.sleep(millis);
}
catch (InterruptedException ie)
{
// Ignore
}
}
/**
* Set a color for this widget/Component
*
* @param part The part of the component (e.g., BORDER_COLOR)
* @param state The state (e.g., DISABLED_COLOR)
* @param color The Color
*/
public void setColor(int part, int state, Color color)
{
getView().setColor(part, state, color);
}
/**
* Set whether this component has the focus
*
* @param hasFocus true if it has the focus, false otherwise
*/
public void setHasFocus(boolean hasFocus)
{
this.hasFocus = hasFocus;
repaint();
}
/**
* Set the height of this component/Widget
*
* @param height The height (in pixels)
*/
public void setHeight(int height)
{
getView().setHeight(height);
}
/**
* Setup the event handlers for this Widget
*/
public void setupEventHandlers()
{
addFocusListener(this);
requestFocus();
}
/**
* Update this component
*
* @param g The Graphics context
*/
public void update(Graphics g)
{
paint(g);
}
}
WidgetModel Classpackage widget;
/**
* The parent class of a GUI component's/widget's model
*
* @author Prof. David Bernstein, James Madison University
* @version 1.0
*/
public class WidgetModel
{
}
WidgetView Classpackage widget;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Insets;
/**
* The parent class of a GUI component's/widget's view
*
* @author Prof. David Bernstein, James Madison University
* @version 1.0
*/
public abstract class WidgetView
{
protected Color[][] colors;
protected Dimension minimumSize = new Dimension();
protected Insets insets = new Insets(0,0,0,0);
public static final int DISABLED = 0;
public static final int FOCUSED = 1;
public static final int UNFOCUSED = 2;
public static final int BACKGROUND = 0;
public static final int BORDER = 1;
public static final int FOREGROUND = 2;
/**
* Get a color for this widget/Component
*
* @param part The part of the component (e.g., BORDER)
* @param state The state (e.g., DISABLED)
* @return The Color
*/
public Color getColor(int part, int state)
{
Color color;
color = null;
if ( (part >= BACKGROUND) && (part <= FOREGROUND) &&
(state >= DISABLED) && (part <= UNFOCUSED) )
{
color = colors[part][state];
}
return color;
}
/**
* Get the minimum amount of size required by this
* component
*
* @return The minimum required size
*/
public Dimension getMinimumSize()
{
return minimumSize;
}
/**
* Get the preferred size for this component
*
* @return The minimum required size
*/
public Dimension getPreferredSize()
{
return getMinimumSize();
}
/**
* Get the component/Widget being controlled
*
* @return The Widget
*/
public abstract Widget getWidget();
/**
* Get the Insets associated with this component/Widget
*
* @return The Insets
*/
public Insets getInsets()
{
return insets;
}
/**
* Paint this component
*
* @param g The Graphics context to use
*/
public abstract void paint(Graphics g);
/**
* Set a color for this widget/Component
*
* @param part The part of the component (e.g., BORDER)
* @param state The state (e.g., DISABLED)
* @param color The Color
*/
public void setColor(int part, int state, Color color)
{
if ( (part >= BACKGROUND) && (part <= FOREGROUND) &&
(state >= DISABLED) && (part <= UNFOCUSED) )
{
colors[part][state] = color;
}
}
/**
* Set the colors
*
* @param colors The matrix of Color objects
*/
protected void setColors(Color[][] colors)
{
this.colors = colors;
}
/**
* Set the height of this component/Widget
*
* @param height The height (in pixels)
*/
public void setHeight(int height)
{
Dimension size;
Widget widget;
widget = getWidget();
size = widget.getSize();
widget.setSize(size.width, height);
}
/**
* Set the Insets associated with this component/Widget
*
* @param insets The Insets
*/
public void setInsets(Insets insets)
{
this.insets = insets;
}
/**
* Set the minimum size of this component/Widget
*
* @param width The width (in pixels)
* @param height The height (in pixels)
*/
public void setMinimumSize(int width, int height)
{
minimumSize.width = width;
minimumSize.height = height;
}
/**
* Set the width (in pixels) of the component
*
* @param width The width
*/
public void setWidth(int width)
{
Dimension size;
Widget widget;
widget = getWidget();
size = widget.getSize();
widget.setSize(size.height, width);
}
}
SizeScheme Classpackage widget;
/**
* A SizeScheme is a collection of sizes used by a Widget set
*
* @author Prof. David Bernstein, James Madison University
* @version 1.0
*/
public class SizeScheme
{
public static int WIDTH = 640;
public static int HEIGHT = 480;
public static int BUTTON_HEIGHT = 35;
public static int BUTTON_WIDTH = 95;
public static int HALF_BUTTON_WIDTH = 45;
}
ColorScheme Classpackage widget;
import java.awt.Color;
/**
* A ColorScheme is a collection of colors used by a Widget set
*
* @author Prof. David Bernstein, James Madison University
* @version 1.0
*/
public class ColorScheme
{
public static final int DISABLED = WidgetView.DISABLED;
public static final int FOCUSED = WidgetView.FOCUSED;
public static final int UNFOCUSED = WidgetView.UNFOCUSED;
public static final int BACKGROUND = WidgetView.BACKGROUND;
public static final int BORDER = WidgetView.BORDER;
public static final int FOREGROUND = WidgetView.FOREGROUND;
public static final Color blue = new Color(4, 130, 132);
public static final Color brown = new Color(212, 206, 188);
public static final Color tan = new Color(236, 230, 220);
public static final Color FRAME = brown;
public static Color[][] getButtonColors()
{
Color[][] colors;
colors = new Color[3][3];
colors[DISABLED][BACKGROUND] = brown;
colors[DISABLED][BORDER] = brown;
colors[DISABLED][FOREGROUND] = Color.gray;
colors[FOCUSED][BACKGROUND] = tan;
colors[FOCUSED][BORDER] = tan;
colors[FOCUSED][FOREGROUND] = Color.black;
colors[UNFOCUSED][BACKGROUND] = brown;
colors[UNFOCUSED][BORDER] = brown;
colors[UNFOCUSED][FOREGROUND] = Color.white;
return colors;
}
}
AbstractButton Classpackage widget;
import java.awt.AWTEventMulticaster;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.KeyListener;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.PaintEvent;
import java.awt.Canvas;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Image;
/**
* The abstract parent for simple Button objects
*
* @author Prof. David Bernstein, James Madison University
* @version 1.0
*/
public abstract class AbstractButton extends Widget
implements KeyListener,
MouseListener
{
protected ActionListener actionListener;
protected int buttonType;
public static final int RECTANGLE = 0;
public static final int ROUNDED_RECTANGLE = 1;
public static final int LEFT = 0;
public static final int CENTER = 1;
public static final int RIGHT = 2;
public static final int TOP = 0;
// CENTER = 1;
public static final int BOTTOM = 2;
public static final int NORMAL = 0;
public static final int TOGGLE = 1;
/**
* Default constructor
*/
public AbstractButton()
{
super();
actionListener = null;
}
/**
* Add an ActionListener
*
* @param listener The ActionListener to add
*/
public void addActionListener(ActionListener listener)
{
// Add the listener to the existing multicast listener
actionListener = AWTEventMulticaster.add(actionListener, listener);
}
/**
* Get the action command associated with this Button
*
* @return The action command
*/
public String getActionCommand()
{
AbstractButtonModel model;
model = (AbstractButtonModel)(getModel());
return model.getActionCommand();
}
/**
* Get the button type
*
* @return The button type
*/
public int getButtonType()
{
return buttonType;
}
/**
* Get the default icon Image associated with the button
*
* @return The Image
*/
public Image getIcon()
{
AbstractButtonView view;
view = (AbstractButtonView)(getView());
return view.getIcon();
}
/**
* Get the text on this Button
*
* @return The text
*/
public String getText()
{
AbstractButtonView view;
view = (AbstractButtonView)(getView());
return view.getText();
}
/**
* Get the shape of this Button
*
* @return The shape
*/
public int getShape()
{
AbstractButtonView view;
view = (AbstractButtonView)(getView());
return view.getShape();
}
/**
* Handle keyPressed events (required by KeyListener)
*
* @param evt The KeyEvent
*/
public void keyPressed(KeyEvent evt)
{
AbstractButtonView view;
Rectangle r;
int keyCode;
view = (AbstractButtonView)(getView());
keyCode = evt.getKeyCode();
if ( (keyCode == KeyEvent.VK_SPACE) ||
(keyCode == KeyEvent.VK_ENTER) )
{
dispatchEvent(new MouseEvent(this,
MouseEvent.MOUSE_PRESSED,
0, 0, 0, 0, 1, false));
r = getBounds();
r.x = 0;
r.y = 0;
dispatchEvent(new PaintEvent(this,
PaintEvent.PAINT,
r
));
notifyActionListeners();
pause(50);
dispatchEvent(new MouseEvent(this,
MouseEvent.MOUSE_RELEASED,
0, 0, 0, 0, 1, false));
}
}
/**
* Handle keyReleased events (required by KeyListener)
*
* @param evt The KeyEvent
*/
public void keyReleased(KeyEvent evt)
{
// Ignore
}
/**
* Handle keyTyped events (required by KeyListener)
*
* @param evt The KeyEvent
*/
public void keyTyped(KeyEvent evt)
{
// Ignore
}
/**
* Handle mouseClicked events (required by MouseListener)
*
* @param evt The event
*/
public void mouseClicked(MouseEvent evt)
{
// Everything is handled by the mousePressed and
// mouseReleased handlers
}
/**
* Handle mouseEntered events (required by MouseListener)
*
* @param evt The event
*/
public void mouseEntered(MouseEvent evt)
{
// Handled by children that care
}
/**
* Handle mouseExited events (required by MouseListener)
*
* @param evt The event
*/
public void mouseExited(MouseEvent evt)
{
// Handled by children that care
}
/**
* Handle mousePressed events (required by MouseListener)
*
* @param evt The event
*/
public void mousePressed(MouseEvent evt)
{
AbstractButtonModel model;
AbstractButtonView view;
model = (AbstractButtonModel)(getModel());
view = (AbstractButtonView)(getView());
if (isEnabled())
{
requestFocus();
if (buttonType == TOGGLE)
{
if (model.isSelected())
{
model.setSelected(false);
}
else
{
model.setSelected(true);
view.setViewState(AbstractButtonView.DOWN);
}
}
else
{
view.setViewState(AbstractButtonView.DOWN);
}
}
}
/**
* Handle mouseReleased events (required by MouseListener)
*
* @param evt The event
*/
public void mouseReleased(MouseEvent evt)
{
AbstractButtonModel model;
AbstractButtonView view;
model = (AbstractButtonModel)(getModel());
view = (AbstractButtonView)(getView());
if (isEnabled())
{
notifyActionListeners();
if (buttonType == TOGGLE)
{
// Ignore
}
else
{
view.setViewState(AbstractButtonView.UP);
}
}
}
/**
* Notify all ActionListener objects of an ActionEvent
*/
public void notifyActionListeners()
{
AbstractButtonModel model;
ActionEvent ae;
model = (AbstractButtonModel)(getModel());
ae = new ActionEvent(this,
ActionEvent.ACTION_PERFORMED,
model.getActionCommand());
if (actionListener != null)
{
actionListener.actionPerformed(ae);
}
}
/**
* Remove an ActionListener
*
* @param listener The ActionListener to remove
*/
public void removeActionListener(ActionListener listener)
{
// Remove the listener from the existing multicast listener
actionListener = AWTEventMulticaster.remove(actionListener, listener);
}
/**
* Set the action command associated with this Button
*
* @param ac The action command
*/
public void setActionCommand(String ac)
{
AbstractButtonModel model;
model = (AbstractButtonModel)(getModel());
model.setActionCommand(ac);
}
/**
* Set the button type (NORMAL or TOGGLE)
*
* @param type The type
*/
public void setButtonType(int type)
{
if ((type == NORMAL) || (type == TOGGLE)) buttonType = type;
}
/**
* Set the Font
*
* @param font The Font
*/
public void setFont(Font font)
{
AbstractButtonView view;
view = (AbstractButtonView)(getView());
super.setFont(font);
if (view != null) view.setTextSize(null);
}
/**
* Set the horizontal position of the text
*
* @param hpos The horizontal position (LEFT, CENTER, RIGHT)
*/
public void setHorizontalTextPosition(int hpos)
{
AbstractButtonView view;
view = (AbstractButtonView)(getView());
if ((hpos >= LEFT) && (hpos <= CENTER))
{
view.setHorizontalTextPosition(hpos);
}
}
/**
* Set the default icon Image associated with the button
*
* @param image The Image
*/
public void setIcon(Image image)
{
AbstractButtonView view;
view = (AbstractButtonView)(getView());
view.setIcon(image);
}
/**
* Set the model associated with this component/Widget
*
* @param model The model
*/
public void setModel(AbstractButtonModel model)
{
// Nothing to do
}
/**
* Set the shape of this Button
*
* @param shape The shape (RECTANGLE, ROUNDED_RECTANGLE)
*/
public void setShape(int shape)
{
AbstractButtonView view;
view = (AbstractButtonView)(getView());
if ((shape >= RECTANGLE) && (shape <= ROUNDED_RECTANGLE))
{
view.setShape(shape);
}
}
/**
* Set the text on this Button
*
* @param text The text
*/
public void setText(String text)
{
AbstractButtonView view;
view = (AbstractButtonView)(getView());
view.setText(text);
view.setTextSize(null);
}
/**
* Setup the event handlers for this Widget
*/
public void setupEventHandlers()
{
super.setupEventHandlers();
addKeyListener(this);
addMouseListener(this);
}
/**
* Set the vertical position of the text
*
* @param vpos The vertical position (TOP, CENTER, BOTTOM)
*/
public void setVerticalTextPosition(int vpos)
{
AbstractButtonView view;
view = (AbstractButtonView)(getView());
if ((vpos >= TOP) && (vpos <= BOTTOM))
{
view.setVerticalTextPosition(vpos);
}
}
/**
* Set the View for this component/Widget
*
* @param view The view
*/
public void setView(AbstractButtonView view)
{
// Nothing to do
}
/**
* Set the view state (e.g., UP, DOWN)
*
* @param The viewState
*/
public void setViewState(int viewState)
{
AbstractButtonView view;
view = (AbstractButtonView)(getView());
view.setViewState(viewState);
}
}
AbstractButtonModel Classpackage widget;
/**
* The Model (from the Model-View-Controller pattern)
* for an AbstractButton.
*
* @author Prof. David Bernstein, James Madison University
* @version 1.0
*/
public abstract class AbstractButtonModel extends WidgetModel
{
private boolean selected;
protected String actionCommand;
/**
* Constructor
*
* @param button The button this controller belongs to
* @param ac The action command associated with this button
*/
public AbstractButtonModel(String ac)
{
this.actionCommand = ac;
selected = false;
}
/**
* Get the action command associated with this Button
*
* @return The action command
*/
public String getActionCommand()
{
return actionCommand;
}
/**
* Is this ToggleButton selected?
*
* @return true if selected, false otherwise
*/
public boolean isSelected()
{
return selected;
}
/**
* Set the action command associated with this Button
*
* @param ac The action command
*/
public void setActionCommand(String ac)
{
actionCommand = ac;
}
/**
* Set whether this ToggleButton is selected
*
* @param selected true to selected, false to de-select
*/
public void setSelected(boolean selected)
{
this.selected = selected;
}
}
AbstractButtonView Classpackage widget;
import java.awt.Dimension;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Image;
/**
* The View (from the Model-View-Controller pattern)
* for a Button.
*
* @author Prof. David Bernstein, James Madison University
* @version 1.0
*/
public abstract class AbstractButtonView extends WidgetView
{
protected Dimension textSize;
protected FontMetrics fm;
protected Image disabledIcon, enabledIcon;
protected int arcHeight, arcWidth, horizontalTextPosition;
protected int mouseState, shape, verticalTextPosition;
protected int viewState;
protected String text;
public static final int DOWN = 0;
public static final int UP = 1;
/**
* Default constructor
*/
public AbstractButtonView()
{
this(0, 0);
}
/**
* Constructor
*
* @param width The width of the button (in pixels)
* @param height The height of the button (in pixels)
*/
public AbstractButtonView(int width, int height)
{
setMinimumSize(width, height);
viewState = UP;
shape = AbstractButton.RECTANGLE;
arcHeight = 20;
arcWidth = 20;
disabledIcon = null;
enabledIcon = null;
horizontalTextPosition = AbstractButton.CENTER;
verticalTextPosition = AbstractButton.CENTER;
}
/**
* Get the default icon Image associated with the button
*
* @return The Image
*/
public Image getIcon()
{
return enabledIcon;
}
/**
* Get the shape of this Button
*
* @return The shape
*/
public int getShape()
{
return shape;
}
/**
* Get the text on this Button
*
* @return The text
*/
public String getText()
{
return text;
}
/**
* Get the view state (e.g., UP, DOWN)
*
* @return The view state
*/
public int getViewState()
{
return viewState;
}
/**
* Paint this component
*
* @param g The Graphics context to use
*/
public abstract void paint(Graphics g);
/**
* Set the horizontal position of the text
*
* @param hpos The horizontal position (LEFT, CENTER, RIGHT)
*/
public void setHorizontalTextPosition(int hpos)
{
horizontalTextPosition = hpos;
}
/**
* Set the default icon Image associated with the button
*
* @param icon The Image
*/
public void setIcon(Image icon)
{
enabledIcon = icon;
}
/**
* Set the state of the mouse
*
* @param state The new state
*/
/*
public void setMouseState(int state)
{
AbstractButton button;
button = (Button)(getWidget());
if ((state >= MOUSE_OUT) && (state <= MOUSE_UP)) {
mouseState = state;
} else {
mouseState = MOUSE_OUT;
}
button.repaint();
}
*/
/**
* Set the shape of this Button
*
* @param shape The shape (RECTANGLE, ROUNDED_RECTANGLE)
*/
public void setShape(int shape)
{
this.shape = shape;
}
/**
* Set the text on this Button
*
* @param text The text
*/
public void setText(String text)
{
this.text = text;
}
/**
* Set the size of the text on this Button
*
* @param size The size of the text
*/
public void setTextSize(Dimension size)
{
this.textSize = size;
}
/**
* Set the vertical position of the text
*
* @param vpos The vertical position (TOP, CENTER, BOTTOM)
*/
public void setVerticalTextPosition(int vpos)
{
verticalTextPosition = vpos;
}
/**
* Set the view state (e.g., UP, DOWN)
*
* @param The viewState
*/
public void setViewState(int viewState)
{
AbstractButton button;
button = (Button)(getWidget());
if ((viewState >= DOWN) && (viewState <=UP))
{
this.viewState = viewState;
button.repaint();
}
}
}
Button Classpackage widget;
/**
* An encapsulation of a "normal" Button
*
* @author Prof. David Bernstein, James Madison University
* @version 1.0
*/
public class Button extends AbstractButton
{
protected ButtonModel model;
protected ButtonView view;
/**
* Default constructor
*/
public Button()
{
this("DefaultButtonActionCommand", 10, 10);
}
/**
* Constructor
*
* @param ac The action command associated with this button
* @param text The text on the Button
* @param width The width of the Button (in pixels)
* @param height The height of the Button (in pixels)
*/
public Button(String ac, int width, int height)
{
super();
setModel(new ButtonModel(this, ac));
setView(new ButtonView(this, width, height));
setupEventHandlers();
buttonType = NORMAL;
}
/**
* Get the model associated with this component/Widget
*
* @return The model
*/
public WidgetModel getModel()
{
return model;
}
/**
* Get the view associated with this component/Widget
*
* @return The view
*/
public WidgetView getView()
{
return view;
}
/**
* Set the model associated with this component/Widget
*
* @param model The model
*/
public void setModel(ButtonModel model)
{
super.setModel(model);
this.model = model;
}
/**
* Set the View for this component/Widget
*
* @param view The view
*/
public void setView(ButtonView view)
{
super.setView(view);
this.view = view;
}
}
ButtonView Classpackage widget;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Image;
/**
* The View (from the Model-View-Controller pattern)
* for a Button.
*
* @version 1.0
* @author Prof. David Bernstein, James Madison University
*/
public class ButtonView extends AbstractButtonView
{
protected Button button;
protected Color downColor, upColor;
/**
* Constructor
*
* @param button The button this view belongs to
* @param width The width of the button (in pixels)
* @param height The height of the button (in pixels)
*/
public ButtonView(Button button, int width, int height)
{
super(width, height);
this.button = button;
getWidget().setSize(width, height);
button.setSize(new Dimension(width, height));
button.setFont(new Font("Sans Serif", Font.PLAIN, 20));
button.setBackground(ColorScheme.FRAME);
setColors(ColorScheme.getButtonColors());
downColor = Color.red;
upColor = Color.gray;
}
/**
* Get the Button associated with this view
*
* @return The Button
*/
public Widget getWidget()
{
return button;
}
/**
* Paint this component
*
* @param g The Graphics context to use
*/
public void paint(Graphics g)
{
paintBackground(g);
paintText(g);
paintBorder(g);
}
/**
* Paint the background
*
* @param g The Graphics context to use
*/
protected void paintBackground(Graphics g)
{
Color bgColor;
Dimension size;
int buttonType, h, w, x, y;
size = button.getSize();
// Fill the background
bgColor = button.getBackground();
g.setColor(bgColor);
g.fillRect(0,0,size.width,size.height);
// Fill the button
if (button.hasFocus()) g.setColor(colors[FOCUSED][BACKGROUND]);
else g.setColor(colors[UNFOCUSED][BACKGROUND]);
if (shape == button.RECTANGLE)
{
g.fillRect(0,0,size.width,size.height);
}
else if (shape == button.ROUNDED_RECTANGLE)
{
g.fillRoundRect(0,0,size.width,size.height,
arcWidth,arcHeight);
}
// Render the icon (if one exists)
//
if (enabledIcon != null)
{
h = enabledIcon.getHeight(null);
w = enabledIcon.getWidth(null);
x = (size.width - w)/2;
y = (size.height - h)/2;
// Modify the icon location based on whether
// the button is UP or DOWN
if (viewState == DOWN)
{
x += 2;
y += 2;
}
g.drawImage(enabledIcon, x, y, null);
}
// Render the state indicator (if it's a toggle button)
buttonType = button.getButtonType();
if (buttonType == Button.TOGGLE)
{
x = size.width - 25;
y = 5;
if (viewState == UP)
{
g.setColor(upColor);
}
else if (viewState == DOWN)
{
g.setColor(downColor);
x += 2;
y += 2;
}
g.fillRect(x, y, 20, 5);
}
}
/**
* Paint the border
*
* @param g The Graphics context to use
*/
protected void paintBorder(Graphics g)
{
Dimension size;
size = button.getSize();
g.setColor(colors[FOCUSED][BORDER]);
if (shape == button.RECTANGLE)
{
g.drawRect(0,0,size.width-1,size.height-1);
}
else if (shape == button.ROUNDED_RECTANGLE)
{
g.drawRoundRect(0,0,size.width-1,size.height-1,
arcWidth,arcHeight);
}
}
/**
* Paint the text
*
* @param g The Graphics context to use
*/
protected void paintText(Graphics g)
{
Dimension size;
int h, w, x, y;
size = button.getSize();
// Short circuit if no text
if ((text == null) || (text.equals(""))) return;
// Determine the size of the text
if (textSize == null)
{
fm = g.getFontMetrics();
h = fm.getMaxAscent();
w = fm.stringWidth(text);
setTextSize(new Dimension(w, h));
}
// Determine the horizontal location
if (horizontalTextPosition == button.LEFT)
{
x = 0;
}
else if (horizontalTextPosition==button.RIGHT)
{
x = size.width - textSize.width;
}
else
{
x = (size.width - textSize.width)/2;
}
// Determine the vertical location
if (verticalTextPosition == button.TOP)
{
y = textSize.height;
}
else if (verticalTextPosition==button.BOTTOM)
{
y=size.height - fm.getMaxDescent();
}
else
{
y = (size.height + textSize.height)/2;
}
// Modify the text location based on whether the button is UP or DOWN
if (viewState == DOWN)
{
x += 1;
y -= 1;
}
// Render the text
g.setFont(button.getFont());
if (!button.isEnabled())
{
g.setColor(colors[DISABLED][FOREGROUND]);
}
else if (button.hasFocus())
{
g.setColor(colors[FOCUSED][FOREGROUND]);
}
else
{
g.setColor(colors[UNFOCUSED][FOREGROUND]);
}
g.drawString(text, x, y);
}
/**
* Set the color used for different view states
*
* @param state The view state (DOWN or UP)
* @param color The Color
*/
public void setViewStateColor(int state, Color color)
{
if (state == DOWN) downColor = color;
else if (state == UP) upColor = color;
}
}
ButtonModel Classpackage widget;
/**
* The Model (from the Model-View-Controller pattern)
* for an AbstractButton.
*
* @author Prof. David Bernstein, James Madison University
* @version 1.0
*/
public class ButtonModel extends AbstractButtonModel
{
private Button button;
/**
* Constructor
*
* @param button The button this controller belongs to
* @param ac The action command associated with this button
*/
public ButtonModel(Button button, String ac)
{
super(ac);
this.button = button;
}
/**
* Get the Button associated with this model
*
* @return The Button
*/
public Widget getWidget()
{
return button;
}
}
package widget;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Image;
/**
* A "flat" View (from the Model-View-Controller pattern)
* for a Button.
*
* @author Prof. David Bernstein, James Madison University
* @version 1.0
*/
public class ButtonView extends AbstractButtonView
{
protected Button button;
protected Color downColor, upColor;
/**
* Constructor
*
* @param button The button this view belongs to
* @param width The width of the button (in pixels)
* @param height The height of the button (in pixels)
*/
public ButtonView(Button button, int width, int height)
{
super(width, height);
this.button = button;
getWidget().setSize(width, height);
button.setSize(new Dimension(width, height));
button.setFont(new Font("Sans Serif", Font.PLAIN, 20));
button.setBackground(ColorScheme.FRAME);
setColors(ColorScheme.getButtonColors());
downColor = Color.red;
upColor = Color.gray;
}
/**
* Get the Button associated with this view
*
* @return The Button
*/
public Widget getWidget()
{
return button;
}
/**
* Paint this component
*
* @param g The Graphics context to use
*/
public void paint(Graphics g)
{
paintBackground(g);
paintText(g);
paintBorder(g);
}
/**
* Paint the background
*
* @param g The Graphics context to use
*/
protected void paintBackground(Graphics g)
{
Color bgColor;
Dimension size;
int buttonType, h, w, x, y;
size = button.getSize();
// Fill the background
bgColor = button.getBackground();
g.setColor(bgColor);
g.fillRect(0,0,size.width,size.height);
// Fill the button
if (button.hasFocus()) g.setColor(colors[FOCUSED][BACKGROUND]);
else g.setColor(colors[UNFOCUSED][BACKGROUND]);
if (shape == button.RECTANGLE)
{
g.fillRect(0,0,size.width,size.height);
}
else if (shape == button.ROUNDED_RECTANGLE)
{
g.fillRoundRect(0,0,size.width,size.height,
arcWidth,arcHeight);
}
// Render the icon (if one exists)
//
if (enabledIcon != null)
{
h = enabledIcon.getHeight(null);
w = enabledIcon.getWidth(null);
x = (size.width - w)/2;
y = (size.height - h)/2;
// Modify the icon location based on whether
// the button is UP or DOWN
if (viewState == DOWN)
{
x += 2;
y += 2;
}
g.drawImage(enabledIcon, x, y, null);
}
// Render the state indicator (if it's a toggle button)
buttonType = button.getButtonType();
if (buttonType == Button.TOGGLE)
{
x = size.width - 25;
y = 5;
if (viewState == UP)
{
g.setColor(upColor);
}
else if (viewState == DOWN)
{
g.setColor(downColor);
x += 2;
y += 2;
}
g.fillRect(x, y, 20, 5);
}
}
/**
* Paint the border
*
* @param g The Graphics context to use
*/
protected void paintBorder(Graphics g)
{
Dimension size;
size = button.getSize();
g.setColor(colors[FOCUSED][BORDER]);
if (shape == button.RECTANGLE)
{
g.drawRect(0,0,size.width-1,size.height-1);
}
else if (shape == button.ROUNDED_RECTANGLE)
{
g.drawRoundRect(0,0,size.width-1,size.height-1,
arcWidth,arcHeight);
}
}
/**
* Paint the text
*
* @param g The Graphics context to use
*/
protected void paintText(Graphics g)
{
Dimension size;
int h, w, x, y;
size = button.getSize();
// Short circuit if no text
if ((text == null) || (text.equals(""))) return;
// Determine the size of the text
if (textSize == null)
{
fm = g.getFontMetrics();
h = fm.getMaxAscent();
w = fm.stringWidth(text);
setTextSize(new Dimension(w, h));
}
// Determine the horizontal location
if (horizontalTextPosition == button.LEFT)
{
x = 0;
}
else if (horizontalTextPosition==button.RIGHT)
{
x = size.width - textSize.width;
}
else
{
x = (size.width - textSize.width)/2;
}
// Determine the vertical location
if (verticalTextPosition == button.TOP)
{
y = textSize.height;
}
else if (verticalTextPosition==button.BOTTOM)
{
y=size.height - fm.getMaxDescent();
}
else
{
y = (size.height + textSize.height)/2;
}
// Modify the text location based on whether the button is UP or DOWN
if (viewState == DOWN)
{
x += 1;
y -= 1;
}
// Render the text
g.setFont(button.getFont());
if (!button.isEnabled())
{
g.setColor(colors[DISABLED][FOREGROUND]);
}
else if (button.hasFocus())
{
g.setColor(colors[FOCUSED][FOREGROUND]);
}
else
{
g.setColor(colors[UNFOCUSED][FOREGROUND]);
}
g.drawString(text, x, y);
}
/**
* Set the color used for different view states
*
* @param state The view state (DOWN or UP)
* @param color The Color
*/
public void setViewStateColor(int state, Color color)
{
if (state == DOWN) downColor = color;
else if (state == UP) upColor = color;
}
}
package widget;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Image;
/**
* A 3-D View (from the Model-View-Controller pattern)
* for a Button.
*
* @author Prof. David Bernstein, James Madison University
* @version 1.0
*/
public class ButtonView extends AbstractButtonView
{
protected Button button;
protected Color darkColor, lightColor;
/**
* Constructor
*
* @param button The button this view belongs to
* @param width The width of the button (in pixels)
* @param height The height of the button (in pixels)
*/
public ButtonView(Button button, int width, int height)
{
this(width, height);
this.button = button;
setMinimumSize(width, height);
button.setSize(width, height);
colors = ColorScheme.getButtonColors();
button.setBackground(ColorScheme.FRAME);
lightColor = colors[UNFOCUSED][BACKGROUND].brighter();
darkColor = colors[UNFOCUSED][BACKGROUND].darker();
}
/**
* Constructor
*
* @param width The width of the button (in pixels)
* @param height The height of the button (in pixels)
*/
public ButtonView(int width, int height)
{
super(width, height);
}
/**
* Get the Button associated with this view
*
* @return The Button
*/
public Widget getWidget()
{
return button;
}
/**
* Paint this component
*
* @param g The Graphics context to use
*/
public void paint(Graphics g)
{
paintBackground(g);
paintText(g);
paintBorder(g);
}
/**
* Paint the background
*
* @param g The Graphics context to use
*/
protected void paintBackground(Graphics g)
{
Color bgColor;
Dimension size;
int h, w, x, y;
size = button.getSize();
// Fill the background
g.setColor(button.getBackground());
g.fillRect(0,0,size.width,size.height);
// Fill the button
if (button.hasFocus()) g.setColor(colors[FOCUSED][BACKGROUND]);
else g.setColor(colors[UNFOCUSED][BACKGROUND]);
if (shape == button.RECTANGLE)
{
g.fillRect(0,0,size.width,size.height);
}
else if (shape == button.ROUNDED_RECTANGLE)
{
g.fillRoundRect(0,0,size.width,size.height,
arcWidth,arcHeight);
}
// Render the icon (if one exists)
//
if (enabledIcon != null)
{
h = enabledIcon.getHeight(null);
w = enabledIcon.getWidth(null);
x = (size.width - w)/2;
y = (size.height - h)/2;
// Modify the icon location based on whether
// the button is UP or DOWN
if (viewState == DOWN)
{
x += 2;
y += 2;
}
g.drawImage(enabledIcon, x, y, null);
}
}
/**
* Paint the border
*
* @param g The Graphics context to use
*/
protected void paintBorder(Graphics g)
{
Color brColor, ulColor;
Dimension size;
size = button.getSize();
brColor = darkColor;
ulColor = darkColor;
// Determine the border colors
if (viewState == UP)
{
brColor = darkColor;
ulColor = lightColor;
}
else if (viewState == DOWN)
{
brColor = lightColor;
ulColor = darkColor;
}
// Draw the border
if (shape == button.RECTANGLE)
{
g.setColor(ulColor);
g.drawLine(0,0,size.width-1,0);
g.drawLine(0,0,0,size.height-1);
g.setColor(brColor);
g.drawLine(0,size.height-1,size.width-1,size.height-1);
g.drawLine(size.width-1,0,size.width-1,size.height-1);
}
else if (shape == button.ROUNDED_RECTANGLE)
{
g.setColor(ulColor);
g.drawLine(arcWidth/2,0,size.width-1-arcWidth/2,0);
g.drawLine(0,arcHeight/2,0,size.height-1-arcHeight/2);
// Upper left
g.drawArc(0,0,arcWidth,arcHeight,90,90);
// Upper right
g.drawArc(size.width-1-arcWidth,0,arcWidth,arcHeight,45,45);
// Lower left
g.drawArc(0,size.height-1-arcHeight,arcWidth,arcHeight,180,45);
g.setColor(brColor);
g.drawLine(arcWidth/2,size.height-1,
size.width-1-arcWidth/2,size.height-1);
g.drawLine(size.width-1,arcHeight/2,
size.width-1,size.height-1-arcHeight/2);
//Upper right
g.drawArc(size.width-1-arcWidth,0,
arcWidth,arcHeight,0,45);
// Lower left
g.drawArc(0,size.height-1-arcHeight,
arcWidth,arcHeight,225,45);
// Lower right
g.drawArc(size.width-1-arcWidth,size.height-1-arcHeight,
arcWidth,arcHeight,270,90);
}
}
/**
* Paint the text
*
* @param g The Graphics context to use
*/
protected void paintText(Graphics g)
{
Dimension size;
int h, w, x, y;
size = button.getSize();
// Short circuit if no text
if ((text == null) || (text.equals(""))) return;
// Determine the size of the text
if (textSize == null)
{
fm = g.getFontMetrics();
h = fm.getMaxAscent();
w = fm.stringWidth(text);
setTextSize(new Dimension(w, h));
}
// Determine the horizontal location
if (horizontalTextPosition == button.LEFT)
{
x = 0;
}
else if (horizontalTextPosition==button.RIGHT)
{
x = size.width - textSize.width;
}
else
{
x = (size.width - textSize.width)/2;
}
// Determine the vertical location
if (verticalTextPosition == button.TOP)
{
y = textSize.height;
}
else if (verticalTextPosition==button.BOTTOM)
{
y=size.height - fm.getMaxDescent();
}
else
{
y = (size.height + textSize.height)/2;
}
// Modify the text location based on whether the button is UP or DOWN
if (viewState == DOWN)
{
x += 2;
y += 2;
}
// Render the text
g.setFont(button.getFont());
g.setColor(colors[FOCUSED][FOREGROUND]);
g.drawString(text, x, y);
}
}