// (c) 2003 Allen I Holub. All rights reserved. // package com.holub.ui; import javax.swing.*; import javax.swing.border.*; import java.awt.*; import java.awt.event.*; import java.awt.image.BufferedImage; import java.awt.geom.Line2D; import java.net.URL; // Test this class by instantiating DateSelector // TODO: Draw the close box in a paint() override using lines so that // the dependancy on the image file goes away and so that // it can change colors to match the foreground color. /*** A PopupDialog is a clean, lightweight, "modal" window intended for * simple pop-up user-interface widgets. The frame, as shown at right, * <img src="../../../images/PopupDialog.gif" align=right> * is a single-pixel-wide * line; the title bar holds only * the title text and a small "close-window" icon. * The dialog * box can be dragged around on the screen by grabbing the title * bar (and closed by clicking on the icon), but the user can't * resize it, minimize it, etc. (Your program can do so, of course). * <p> * The "close" icon in the current implementation is an image * loaded as a "resource" from the CLASSPATH. The file must be * located at * <blockquote> * $CLASSPATH/images/8px.red.X.gif * </blockquote> * where <em>$CLASSPATH</em> is any directory on your CLASSPATH. * If the class can't find the image file, it uses the character * "X" instead. * The main problem with this approach is that you can't change * the color of the close icon to math the title-bar colors. * Future versions of this class will fix the problem by rendering * the image internally. * * <!-- ====================== distribution terms ===================== --> * <p><blockquote * style="border-style: solid; border-width:thin; padding: 1em 1em 1em 1em;"> * <center> * Copyright © 2003, Allen I. Holub. All rights reserved. * </center> * <br> * <br> * This code is distributed under the terms of the * <a href="http://www.gnu.org/licenses/gpl.html" * >GNU Public License</a> (GPL) * with the following ammendment to section 2.c: * <p> * As a requirement for distributing this code, your splash screen, * about box, or equivalent must include an my name, copyright, * <em>and URL</em>. An acceptable message would be: * <center> * This program contains Allen Holub's <em>XXX</em> utility.<br> * (c) 2003 Allen I. Holub. All Rights Reserved.<br> * http://www.holub.com<br> * </center> * If your progam does not run interactively, then the foregoing * notice must appear in your documentation. * </blockquote> * <!-- =============================================================== --> * @author Allen I. Holub */ public class PopupDialog extends JDialog { private Color TITLE_BAR_COLOR = com.holub.ui.Colors.LIGHT_YELLOW; private Color CLOSE_BOX_COLOR = com.holub.ui.Colors.DARK_RED; private JLabel title = new JLabel("xxxxxxxxxxxxxx"); { title.setHorizontalAlignment(SwingConstants.CENTER); title.setOpaque( false ); title.setFont( title.getFont().deriveFont(Font.BOLD) ); } private JPanel header = new JPanel(); { header.setBackground( TITLE_BAR_COLOR ); header.setLayout( new BorderLayout() ); header.setBorder( BorderFactory.createEmptyBorder(2,2,2,2) ); header.add( title , BorderLayout.CENTER ); header.add( createCloseButton() , BorderLayout.EAST ); } private JPanel contentPane = new JPanel(); { contentPane.setLayout( new BorderLayout() ); } public PopupDialog( Frame owner ){ super(owner); setModal(true); } public PopupDialog( Dialog owner){ super(owner); setModal(true); } /* code common to all constructors */ { initDragable(); setUndecorated( true ); JPanel contents = new JPanel(); contents.setBorder( BorderFactory.createLineBorder(Color.BLACK,1) ); contents.setLayout(new BorderLayout()); contents.add(header, BorderLayout.NORTH); contents.add(contentPane, BorderLayout.CENTER); contents.setBackground( Color.WHITE ); setContentPane( contents ); // , BorderLayout.CENTER ); setLocation(100,100); } private JButton createCloseButton() { URL image = getClass().getClassLoader().getResource( "images/8px.red.X.gif"); JButton b = (image!=null) ? new JButton( new ImageIcon(image) ) : new JButton( " X " ) ; Border outer = BorderFactory.createLineBorder(CLOSE_BOX_COLOR,1); Border inner = BorderFactory.createEmptyBorder(2,2,2,2); b.setBorder( BorderFactory.createCompoundBorder(outer,inner) ); b.setOpaque( false ); b.addActionListener ( new ActionListener() { public void actionPerformed(ActionEvent e) { PopupDialog.this.setVisible(false); PopupDialog.this.dispose(); } } ); b.setFocusable( false ); return b; } /** Set the dialog title to the indicated text */ public void setTitle( String text ){ title.setText( text ); } //---------------------------------------------------------------------- // Drag support. {=PopupDialog.drag.support} // private Point referencePosition = new Point(0,0); private MouseMotionListener movementHandler; private MouseListener clickHandler; private void initDragable() { clickHandler = new MouseAdapter() { public void mousePressed( MouseEvent e ) { referencePosition = e.getPoint(); // start of the drag } }; movementHandler = new MouseMotionAdapter() { public void mouseDragged( MouseEvent e ) { // The reference posistion is the (window relative) // cursor postion when the click occured. The // currentMouse-position is mouse position // now, and the deltas represent the disance // moved. Point currentMousePosition = e.getPoint(); Point currentWindowLocation = getLocation(); int deltaX=currentMousePosition.x - referencePosition.x; int deltaY=currentMousePosition.y - referencePosition.y; // Move the window over by the computed delta. This move // effectivly shifts the window-relative current-mouse // position back to the original reference position. currentWindowLocation.translate(deltaX, deltaY); setLocation(currentWindowLocation); } }; setDragable(true); } /** Turn dragability on or off. */ public void setDragable( boolean on ) { if( on ) { title.addMouseMotionListener ( movementHandler ); title.addMouseListener ( clickHandler ); } else { title.removeMouseMotionListener ( movementHandler ); title.removeMouseListener ( clickHandler ); } } /** Add your widgets to the window returned by this method, in * a manner similar to a JFrame. Do not modify the PoupDialog * itself. The returned container is a {@link JPanel JPanel} * with a preinstalled {@link BorderLayout}. * By default, it's colored colored dialog-box gray. * @return the content pane. */ public Container getContentPane(){ return contentPane; } /** Change the color of the text and background in the title bar. * The "close" icon is always * {@linkplain com.holub.ui.Colors#DARK_RED dark red} * so it will be hard to see if the background color is also * a dark red). * @param foreground the text color * @param background the background color */ public void changeTitlebarColors( Color foreground, Color background ) { title.setForeground ( foreground ); header.setBackground( background ); } //---------------------------------------------------------------------- private static class Test { public static void main( String[] args ) { final JFrame main = new JFrame("Hello"); final JDialog dialog= new PopupDialog( main ); final JButton b = new JButton("close"); b.addActionListener ( new ActionListener() { public void actionPerformed(ActionEvent e) { dialog.setVisible(false); dialog.dispose(); } } ); main.getContentPane().add(new JLabel("Main window")); main.pack(); main.show(); System.out.println("Creating dialog"); dialog.getContentPane().add( b ); dialog.pack(); System.out.println("Displaying dialog"); dialog.show(); System.out.println("Dialog shut down"); System.out.println("Display nondragable in different colors"); PopupDialog d = (PopupDialog)dialog; d.changeTitlebarColors( Color.WHITE, Color.BLACK ); d.setDragable( false ); dialog.show(); System.exit(0); } } }