Mega Code Archive

 
Categories / Java / Swing Components
 

Yes No Panel

/*  * Copyright (c) 2004 David Flanagan.  All rights reserved.  * This code is from the book Java Examples in a Nutshell, 3nd Edition.  * It is provided AS-IS, WITHOUT ANY WARRANTY either expressed or implied.  * You may study, use, and modify it for any non-commercial purpose,  * including teaching and use in open-source projects.  * You may distribute it non-commercially as long as you retain this notice.  * For a commercial use license, or to purchase the book,   * please visit http://www.davidflanagan.com/javaexamples3.  */ import java.awt.BorderLayout; import java.awt.Color; import java.awt.Dimension; import java.awt.FlowLayout; import java.awt.Font; import java.awt.FontMetrics; import java.awt.Graphics; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.ArrayList; import java.util.List; import java.util.StringTokenizer; import javax.swing.JButton; import javax.swing.JComponent; import javax.swing.JFrame; import javax.swing.JPanel; class Alignment {   /** This private constructor prevents anyone from instantiating us */   private Alignment() {   };   // The following three constants are the only instances of this class   public static final Alignment LEFT = new Alignment();   public static final Alignment CENTER = new Alignment();   public static final Alignment RIGHT = new Alignment(); } /**  * A custom component that displays multiple lines of text with specified  * margins and alignment.  */ class MultiLineLabel extends JComponent {   // User-specified properties   protected String label; // The label, not broken into lines   protected int margin_width; // Left and right margins   protected int margin_height; // Top and bottom margins   protected Alignment alignment; // The alignment of the text.   // Computed state values   protected int num_lines; // The number of lines   protected String[] lines; // The label, broken into lines   protected int[] line_widths; // How wide each line is   protected int max_width; // The width of the widest line   protected int line_height; // Total height of the font   protected int line_ascent; // Font height above baseline   protected boolean measured = false; // Have the lines been measured?   // Here are five versions of the constructor.   public MultiLineLabel(String label, int margin_width, int margin_height, Alignment alignment) {     this.label = label; // Remember all the properties.     this.margin_width = margin_width;     this.margin_height = margin_height;     this.alignment = alignment;     newLabel(); // Break the label up into lines.   }   public MultiLineLabel(String label, int margin_width, int margin_height) {     this(label, margin_width, margin_height, Alignment.LEFT);   }   public MultiLineLabel(String label, Alignment alignment) {     this(label, 10, 10, alignment);   }   public MultiLineLabel(String label) {     this(label, 10, 10, Alignment.LEFT);   }   public MultiLineLabel() {     this("");   }   // Methods to set and query the various attributes of the component.   // Note that some query methods are inherited from the superclass.   public void setLabel(String label) {     this.label = label;     newLabel(); // Break the label into lines.     repaint(); // Request a redraw.     measured = false; // Note that we need to measure lines.     invalidate(); // Tell our containers about this   }   public void setAlignment(Alignment a) {     alignment = a;     repaint();   }   public void setMarginWidth(int mw) {     margin_width = mw;     repaint();   }   public void setMarginHeight(int mh) {     margin_height = mh;     repaint();   }   // Override this property setter method because we need to remeasure   public void setFont(Font f) {     super.setFont(f); // Tell our superclass about the new font.     repaint(); // Request a redraw.     measured = false; // Note that we need to remeasure lines.     invalidate(); // Tell our containers about new size   }   // Property getter methods.   public String getLabel() {     return label;   }   public Alignment getAlignment() {     return alignment;   }   public int getMarginWidth() {     return margin_width;   }   public int getMarginHeight() {     return margin_height;   }   /**    * This method is called by a layout manager when it wants to know how big    * we'd like to be.    */   public Dimension getPreferredSize() {     if (!measured)       measure();     return new Dimension(max_width + 2 * margin_width, num_lines * line_height + 2 * margin_height);   }   /**    * This method is called when the layout manager wants to know the bare    * minimum amount of space we need to get by.    */   public Dimension getMinimumSize() {     return getPreferredSize();   }   /**    * This method draws the component. Note that it handles the margins and the    * alignment, but that it doesn't have to worry about the color or font--the    * superclass takes care of setting those in the Graphics object we're passed.    */   public void paintComponent(Graphics g) {     int x, y;     Dimension size = this.getSize();     if (!measured)       measure();     y = line_ascent + (size.height - num_lines * line_height) / 2;     for (int i = 0; i < num_lines; i++, y += line_height) {       if (alignment == Alignment.LEFT)         x = margin_width;       else if (alignment == Alignment.CENTER)         x = (size.width - line_widths[i]) / 2;       else         x = size.width - margin_width - line_widths[i];       g.drawString(lines[i], x, y);     }   }   /**    * This internal method breaks a specified label up into an array of lines. It    * uses the StringTokenizer utility class.    */   protected synchronized void newLabel() {     StringTokenizer t = new StringTokenizer(label, "\n");     num_lines = t.countTokens();     lines = new String[num_lines];     line_widths = new int[num_lines];     for (int i = 0; i < num_lines; i++)       lines[i] = t.nextToken();   }   /**    * This internal method figures out how the font is, and how wide each line of    * the label is, and how wide the widest line is.    */   protected synchronized void measure() {     FontMetrics fm = this.getFontMetrics(this.getFont());     line_height = fm.getHeight();     line_ascent = fm.getAscent();     max_width = 0;     for (int i = 0; i < num_lines; i++) {       line_widths[i] = fm.stringWidth(lines[i]);       if (line_widths[i] > max_width)         max_width = line_widths[i];     }     measured = true;   } } class AnswerEvent extends java.util.EventObject {   public static final int YES = 0, NO = 1, CANCEL = 2; // Button constants   protected int id; // Which button was pressed?   public AnswerEvent(Object source, int id) {     super(source);     this.id = id;   }   public int getID() {     return id;   } // Return the button } interface AnswerListener extends java.util.EventListener {   public void yes(AnswerEvent e);   public void no(AnswerEvent e);   public void cancel(AnswerEvent e); } /**  * This JavaBean displays a multi-line message and up to three buttons. It fires  * an AnswerEvent when the user clicks on one of the buttons  */ public class YesNoPanel extends JPanel {   // Properties of the bean.   protected String messageText; // The message to display   protected Alignment alignment; // The alignment of the message   protected String yesLabel; // Text for the yes, no, & cancel buttons   protected String noLabel;   protected String cancelLabel;   // Internal components of the panel   protected MultiLineLabel message;   protected JPanel buttonbox;   protected JButton yes, no, cancel;   /** The no-argument bean constructor, with default property values */   public YesNoPanel() {     this("Your\nMessage\nHere");   }   public YesNoPanel(String messageText) {     this(messageText, Alignment.LEFT, "Yes", "No", "Cancel");   }   /** A constructor for programmers using this class "by hand" */   public YesNoPanel(String messageText, Alignment alignment, String yesLabel, String noLabel,       String cancelLabel) {     // Create the components for this panel     setLayout(new BorderLayout(15, 15));     // Put the message label in the middle of the window.     message = new MultiLineLabel(messageText, 20, 20, alignment);     message.setOpaque(false); // allow background color to show through     add(message, BorderLayout.CENTER);     // Create a panel for the Panel buttons and put it at the bottom     // of the Panel. Specify a FlowLayout layout manager for it.     buttonbox = new JPanel();     buttonbox.setLayout(new FlowLayout(FlowLayout.CENTER, 25, 15));     buttonbox.setOpaque(false); // allow background color to show through     add(buttonbox, BorderLayout.SOUTH);     // Create each specified button, specifying the action listener     // and action command for each, and adding them to the buttonbox     yes = new JButton(); // Create buttons     no = new JButton();     cancel = new JButton();     // Add the buttons to the button box     buttonbox.add(yes);     buttonbox.add(no);     buttonbox.add(cancel);     // Register listeners for each button     yes.addActionListener(new ActionListener() {       public void actionPerformed(ActionEvent e) {         fireEvent(new AnswerEvent(YesNoPanel.this, AnswerEvent.YES));       }     });     no.addActionListener(new ActionListener() {       public void actionPerformed(ActionEvent e) {         fireEvent(new AnswerEvent(YesNoPanel.this, AnswerEvent.NO));       }     });     cancel.addActionListener(new ActionListener() {       public void actionPerformed(ActionEvent e) {         fireEvent(new AnswerEvent(YesNoPanel.this, AnswerEvent.CANCEL));       }     });     // Now call property setter methods to set the message and button     // components to contain the right text     setMessageText(messageText);     setAlignment(alignment);     setYesLabel(yesLabel);     setNoLabel(noLabel);     setCancelLabel(cancelLabel);   }   // Methods to query all of the bean properties.   public String getMessageText() {     return messageText;   }   public Alignment getAlignment() {     return alignment;   }   public String getYesLabel() {     return yesLabel;   }   public String getNoLabel() {     return noLabel;   }   public String getCancelLabel() {     return cancelLabel;   }   public Font getMessageFont() {     return message.getFont();   }   public Color getMessageColor() {     return message.getForeground();   }   public Font getButtonFont() {     return yes.getFont();   }   // Methods to set all of the bean properties.   public void setMessageText(String messageText) {     this.messageText = messageText;     message.setLabel(messageText);   }   public void setAlignment(Alignment alignment) {     this.alignment = alignment;     message.setAlignment(alignment);   }   public void setYesLabel(String l) {     yesLabel = l;     yes.setText(l);     yes.setVisible((l != null) && (l.length() > 0));   }   public void setNoLabel(String l) {     noLabel = l;     no.setText(l);     no.setVisible((l != null) && (l.length() > 0));   }   public void setCancelLabel(String l) {     cancelLabel = l;     cancel.setText(l);     cancel.setVisible((l != null) && (l.length() > 0));   }   public void setMessageFont(Font f) {     message.setFont(f);   }   public void setMessageColor(Color c) {     message.setForeground(c);   }   public void setButtonFont(Font f) {     yes.setFont(f);     no.setFont(f);     cancel.setFont(f);   }   /** This field holds a list of registered ActionListeners. */   protected List listeners = new ArrayList();   /** Register an action listener to be notified when a button is pressed */   public void addAnswerListener(AnswerListener l) {     listeners.add(l);   }   /** Remove an Answer listener from our list of interested listeners */   public void removeAnswerListener(AnswerListener l) {     listeners.remove(l);   }   /** Send an event to all registered listeners */   public void fireEvent(AnswerEvent e) {     // Make a copy of the list and fire the events using that copy.     // This means that listeners can be added or removed from the original     // list in response to this event.     Object[] copy = listeners.toArray();     for (int i = 0; i < copy.length; i++) {       AnswerListener listener = (AnswerListener) copy[i];       switch (e.getID()) {       case AnswerEvent.YES:         listener.yes(e);         break;       case AnswerEvent.NO:         listener.no(e);         break;       case AnswerEvent.CANCEL:         listener.cancel(e);         break;       }     }   }   /** A main method that demonstrates the class */   public static void main(String[] args) {     // Create an instance of YesNoPanel, with title and message specified:     YesNoPanel p = new YesNoPanel("Do you really want to quit?");     // Register an action listener for the Panel. This one just prints     // the results out to the console.     p.addAnswerListener(new AnswerListener() {       public void yes(AnswerEvent e) {         System.exit(0);       }       public void no(AnswerEvent e) {         System.out.println("No");       }       public void cancel(AnswerEvent e) {         System.out.println("Cancel");       }     });     JFrame f = new JFrame();     f.getContentPane().add(p);     f.pack();     f.setVisible(true);   } }