/** * @(#)ActionDemo2.java 1.7 03/02/10 * * Copyright 2003 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or * without modification, are permitted provided that the following * conditions are met: * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials * provided with the distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY * DAMAGES OR LIABILITIES SUFFERED BY LICENSEE AS A RESULT OF OR * RELATING TO USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE OR * ITS DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE * FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, * SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER * CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF * THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS * BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed, licensed or * intended for use in the design, construction, operation or * maintenance of any nuclear facility. * */ package demo; import java.awt.BorderLayout; import java.awt.Component; import java.awt.Dimension; import java.awt.FontMetrics; import java.awt.FlowLayout; import java.awt.event.ItemEvent; import java.awt.event.MouseEvent; import java.awt.event.MouseAdapter; import java.io.File; import java.io.IOException; import java.net.*; import javax.swing.*; import javax.swing.event.*; import javax.swing.text.Document; import javax.swing.text.DefaultStyledDocument; import com.sun.jaf.ui.ActionManager; import com.sun.jaf.ui.UIFactory; /** * This class demonstrates how to create an application that uses the * XML Actions architecture. */ public class ActionDemo2 extends JFrame { // Pane for editing text. private JEditorPane editor; // Status bar which reports mouseover action messages private StatusBar status; // Popup which mirrors the toolbar private JPopupMenu popup; // The Application action manager; private ActionManager manager; // Document name fields private static String UNTITLED = "[untitled]"; private String documentName = UNTITLED; /** * @param url The url of a file to load. */ public ActionDemo2(URL url) { setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); initActions(); initUI(); initDocument(url); status.setMessage("Right mouse click in text area for popup"); pack(); } private void initActions() { URL actionURL = ActionDemo.class.getResource("resources/actions-demo.xml"); manager = ActionManager.getInstance(); try { manager.loadActions(actionURL); } catch (IOException ioe) { System.out.println("ERROR parsing: " + ioe); } // Set the initial state of the actions manager.setSelected("history-command", true); // Register the callback methods on the actions. // For each action id ActionController controller = new ActionController(); manager.registerCallback("exit-command", controller, "handleExit"); manager.registerCallback("new-command", controller, "handleNew"); manager.registerCallback("open-command", controller, "handleOpen"); manager.registerCallback("save-command", controller, "handleSave"); manager.registerCallback("cut-command", controller, "handleCut"); manager.registerCallback("copy-command", controller, "handleCopy"); manager.registerCallback("paste-command", controller, "handlePaste"); manager.registerCallback("history-command", controller, "handleViewStatus"); manager.registerCallback("about-command", controller, "handleAbout"); } /** * This class is the binding class that performs the actual action. * It would probably need to understand the state of the application, etc.... * * Perhaps a beter way of doing this is to enforce a naming pattern * and dynamically register all the actions in in the action-set. * * Callback methods for simple actionPerformed Actions should * not have any arguments. * * Callback methods for toggle Actions should take an boolean * as an argument which indicates if the item is selected. */ public class ActionController { private JFileChooser chooser; public void handleExit() { System.exit(0); } public void handleNew() { initDocument(null); } public void handleOpen() { JFileChooser chooser = getFileChooser(); if (chooser.showOpenDialog(ActionDemo2.this) == JFileChooser.APPROVE_OPTION) { File file = chooser.getSelectedFile(); if (file.exists()) { try { initDocument(file.toURL()); } catch (MalformedURLException ex) { System.err.println(ex.getMessage()); } } } } public void handleSave() { JFileChooser chooser = getFileChooser(); if (chooser.showSaveDialog(ActionDemo2.this) == JFileChooser.APPROVE_OPTION) { File selectedFile = chooser.getSelectedFile(); documentName = selectedFile.getAbsolutePath(); } else { return; } // Save to the filename. System.err.println("Save not implemented"); setTitle(documentName); } // This hides and shows the status bar. public void handleViewStatus(boolean selected) { status.setVisible(selected); } public void handleAbout() { String message = "Actions/UI Framework Demo\n"; message += System.getProperty("java.vm.vendor"); message += "\nJava VM Version: " + System.getProperty("java.vm.version"); JOptionPane.showMessageDialog(ActionDemo2.this, message); } public void handleCut() { editor.cut(); } public void handleCopy() { editor.copy(); } public void handlePaste() { editor.paste(); } /** * Gets the file chooser for saving/loading documents. * This is the file chooser for Open and Save Actions. */ private JFileChooser getFileChooser() { if (chooser == null) { // Open to the current dir chooser = new JFileChooser(System.getProperty("user.dir")); } return chooser; } } // end class ActionController /** * Constructs a user interface based on a action-layout document */ private void initUI() { UIFactory factory = UIFactory.getInstance(); JMenuBar menubar = factory.createMenuBar("main-menu"); if (menubar != null) { setJMenuBar(menubar); } JToolBar toolbar = factory.createToolBar("main-toolbar"); if (toolbar != null) { getContentPane().add(toolbar, BorderLayout.NORTH); } editor = new JEditorPane(); editor.addMouseListener(new MouseAdapter() { public void mousePressed(MouseEvent e) { if (e.isPopupTrigger()) { if (popup != null) { popup.show((Component)e.getSource(), e.getX(), e.getY()); } } } public void mouseReleased(MouseEvent e) { if (e.isPopupTrigger()) { if (popup != null) { popup.show((Component)e.getSource(), e.getX(), e.getY()); } } } }); JScrollPane scrollPane = new JScrollPane(editor); scrollPane.setPreferredSize(new Dimension(400,300)); getContentPane().add(scrollPane, BorderLayout.CENTER); // Show a popup. It's using the toolbar action-list // to demonstrate that the action-lists are reusable. popup = factory.createPopup("main-toolbar"); status = new StatusBar(); // iterate over all the children in the menuBar, toolbar and popup // and add the StatusBar as a MouseListener. status.registerListener(menubar.getSubElements()); status.registerListener(popup.getSubElements()); status.registerListener(toolbar.getComponents()); status.setBorder(BorderFactory.createEtchedBorder()); getContentPane().add(status, BorderLayout.SOUTH); } /** * A status bar which is a mouse listener that can report on mouse over * messages on action based components. */ private class StatusBar extends JPanel { private JLabel label; private Dimension preferredSize; private MouseHandler handler; public StatusBar() { this.setLayout(new FlowLayout(FlowLayout.LEFT)); this.setBorder(BorderFactory.createEtchedBorder()); // Set a large blank label to set the preferred size. label = new JLabel(" "); preferredSize = new Dimension(getWidth(label.getText()), 2 * getFontHeight()); this.add(label); } /** * Returns the string width * @param s the string * @return the string width */ protected int getWidth(String s) { FontMetrics fm = this.getFontMetrics(this.getFont()); if (fm == null) { return 0; } return fm.stringWidth(s); } /** * Returns the height of a line of text * @return the height of a line of text */ protected int getFontHeight() { FontMetrics fm = this.getFontMetrics(this.getFont()); if (fm == null) { return 0; } return fm.getHeight(); } /** * Returns the perferred size * @return the preferred size */ public Dimension getPreferredSize() { return preferredSize; } /** * Sets non-transient status bar message * @param message the message to display on the status bar */ public void setMessage(String message) { label.setText(message); } /** * Custom mouse handler which will listen to mouse * events on action based components and send the * value of the LONG_DESCRIPTION to the status bar. */ private class MouseHandler extends MouseAdapter { public void mouseExited(MouseEvent evt) { setMessage(""); } /** * Takes the LONG_DESCRIPTION of the Action based components * and sends them to the Status bar */ public void mouseEntered(MouseEvent evt) { if (evt.getSource() instanceof AbstractButton) { AbstractButton button = (AbstractButton)evt.getSource(); Action action = button.getAction(); if (action != null) { String message = (String)action.getValue(Action.LONG_DESCRIPTION); setMessage(message); } } } } /** * Helper method to recursively register all MenuElements with * a mouse listener. */ public void registerListener(MenuElement[] elements) { if (handler == null) { handler = new MouseHandler(); } for (int i = 0; i < elements.length; i++) { if (elements[i] instanceof JMenuItem) { ((JMenuItem)elements[i]).addMouseListener(handler); } registerListener(elements[i].getSubElements()); } } /** * Helper method to register all components with a mouse listener. */ public void registerListener(Component[] components) { if (handler == null) { handler = new MouseHandler(); } for (int i = 0; i < components.length; i++) { if (components[i] instanceof AbstractButton) { ((AbstractButton)components[i]).addMouseListener(handler); } } } } // end class StatusBar /** * Creates a new document */ private void initDocument(URL url) { if (url != null) { documentName = url.getFile(); try { editor.setPage(url); } catch (IOException ex) { // Some sort of exception with the URL, re-init System.err.println(ex.getMessage()); } } else { documentName = UNTITLED; editor.setDocument(editor.getEditorKit().createDefaultDocument()); } setTitle(documentName); } /** * Entry point of the demo. Passing a file name as the argument will * load the file into the editor. */ public static void main(String[] args) { URL url = null; if (args.length > 0) { try { url = ActionDemo2.class.getResource(args[0]); if (url == null) { url = new File(args[0]).toURL(); } } catch (MalformedURLException mfe) { System.out.println("ERROR: " + mfe.getMessage()); System.out.println("Using default action-set"); } } ActionDemo2 demo = new ActionDemo2(url); demo.setVisible(true); } }