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); } }