home *** CD-ROM | disk | FTP | other *** search
/ Programming Languages Suite / ProgramD2.iso / J A V A / Java Development Kit V1.2 / jdk12-win32(1).exe / data1.cab / demos / demo / jfc / Notepad / Notepad.java < prev    next >
Encoding:
Java Source  |  1998-12-01  |  18.0 KB  |  702 lines

  1. /*
  2.  * @(#)Notepad.java    1.13 98/08/28
  3.  *
  4.  * Copyright 1997, 1998 by Sun Microsystems, Inc.,
  5.  * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
  6.  * All rights reserved.
  7.  *
  8.  * This software is the confidential and proprietary information
  9.  * of Sun Microsystems, Inc. ("Confidential Information").  You
  10.  * shall not disclose such Confidential Information and shall use
  11.  * it only in accordance with the terms of the license agreement
  12.  * you entered into with Sun.
  13.  */
  14.  
  15. import java.awt.*;
  16. import java.awt.event.*;
  17. import java.beans.*;
  18. import java.io.*;
  19. import java.net.URL;
  20. import java.util.*;
  21.  
  22. import javax.swing.text.*;
  23. import javax.swing.undo.*;
  24. import javax.swing.event.*;
  25. import javax.swing.*;
  26.  
  27. /**
  28.  * Sample application using the simple text editor component that
  29.  * supports only one font.
  30.  *
  31.  * @author  Timothy Prinzing
  32.  * @version 1.13 08/28/98
  33.  */
  34. class Notepad extends JPanel {
  35.  
  36.     private static ResourceBundle resources;
  37.  
  38.     static {
  39.         try {
  40.             resources = ResourceBundle.getBundle("resources.Notepad", 
  41.                                                  Locale.getDefault());
  42.         } catch (MissingResourceException mre) {
  43.             System.err.println("resources/Notepad.properties not found");
  44.             System.exit(1);
  45.         }
  46.     }
  47.  
  48.     Notepad() {
  49.     super(true);
  50.  
  51.     // Force SwingSet to come up in the Cross Platform L&F
  52.     try {
  53.         UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName());
  54.         // If you want the System L&F instead, comment out the above line and
  55.         // uncomment the following:
  56.         // UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
  57.     } catch (Exception exc) {
  58.         System.err.println("Error loading L&F: " + exc);
  59.     }
  60.  
  61.     setBorder(BorderFactory.createEtchedBorder());
  62.     setLayout(new BorderLayout());
  63.  
  64.     // create the embedded JTextComponent
  65.     editor = createEditor();
  66.     editor.setFont(new Font("monospaced", Font.PLAIN, 12));
  67.     // Add this as a listener for undoable edits.
  68.     editor.getDocument().addUndoableEditListener(undoHandler);
  69.  
  70.     // install the command table
  71.     commands = new Hashtable();
  72.     Action[] actions = getActions();
  73.     for (int i = 0; i < actions.length; i++) {
  74.         Action a = actions[i];
  75.         //commands.put(a.getText(Action.NAME), a);
  76.         commands.put(a.getValue(Action.NAME), a);
  77.     }
  78.     
  79.     JScrollPane scroller = new JScrollPane();
  80.     JViewport port = scroller.getViewport();
  81.     port.add(editor);
  82.     try {
  83.         String vpFlag = resources.getString("ViewportBackingStore");
  84.         Boolean bs = new Boolean(vpFlag);
  85.         port.setBackingStoreEnabled(bs.booleanValue());
  86.     } catch (MissingResourceException mre) {
  87.         // just use the viewport default
  88.     }
  89.  
  90.     menuItems = new Hashtable();
  91.     menubar = createMenubar();
  92.     add("North", menubar);
  93.     JPanel panel = new JPanel();
  94.     panel.setLayout(new BorderLayout());    
  95.     panel.add("North",createToolbar());
  96.     panel.add("Center", scroller);
  97.     add("Center", panel);
  98.     add("South", createStatusbar());
  99.     }
  100.  
  101.     public static void main(String[] args) {
  102.         try {
  103.         String vers = System.getProperty("java.version");
  104.         if (vers.compareTo("1.1.2") < 0) {
  105.             System.out.println("!!!WARNING: Swing must be run with a " +
  106.                                "1.1.2 or higher version VM!!!");
  107.         }
  108.         JFrame frame = new JFrame();
  109.         frame.setTitle(resources.getString("Title"));
  110.     frame.setBackground(Color.lightGray);
  111.     frame.getContentPane().setLayout(new BorderLayout());
  112.     frame.getContentPane().add("Center", new Notepad());
  113.     frame.addWindowListener(new AppCloser());
  114.     frame.pack();
  115.     frame.setSize(500, 600);
  116.         frame.show();
  117.         } catch (Throwable t) {
  118.             System.out.println("uncaught exception: " + t);
  119.             t.printStackTrace();
  120.         }
  121.     }
  122.  
  123.     /**
  124.      * Fetch the list of actions supported by this
  125.      * editor.  It is implemented to return the list
  126.      * of actions supported by the embedded JTextComponent
  127.      * augmented with the actions defined locally.
  128.      */
  129.     public Action[] getActions() {
  130.     return TextAction.augmentList(editor.getActions(), defaultActions);
  131.     }
  132.  
  133.     /**
  134.      * Create an editor to represent the given document.  
  135.      */
  136.     protected JTextComponent createEditor() {
  137.     return new JTextArea();
  138.     }
  139.  
  140.     /** 
  141.      * Fetch the editor contained in this panel
  142.      */
  143.     protected JTextComponent getEditor() {
  144.     return editor;
  145.     }
  146.  
  147.     /**
  148.      * To shutdown when run as an application.  This is a
  149.      * fairly lame implementation.   A more self-respecting
  150.      * implementation would at least check to see if a save
  151.      * was needed.
  152.      */
  153.     protected static final class AppCloser extends WindowAdapter {
  154.         public void windowClosing(WindowEvent e) {
  155.         System.exit(0);
  156.     }
  157.     }
  158.  
  159.     /**
  160.      * Find the hosting frame, for the file-chooser dialog.
  161.      */
  162.     protected Frame getFrame() {
  163.     for (Container p = getParent(); p != null; p = p.getParent()) {
  164.         if (p instanceof Frame) {
  165.         return (Frame) p;
  166.         }
  167.     }
  168.     return null;
  169.     }
  170.  
  171.     /**
  172.      * This is the hook through which all menu items are
  173.      * created.  It registers the result with the menuitem
  174.      * hashtable so that it can be fetched with getMenuItem().
  175.      * @see #getMenuItem
  176.      */
  177.     protected JMenuItem createMenuItem(String cmd) {
  178.     JMenuItem mi = new JMenuItem(getResourceString(cmd + labelSuffix));
  179.         URL url = getResource(cmd + imageSuffix);
  180.     if (url != null) {
  181.         mi.setHorizontalTextPosition(JButton.RIGHT);
  182.         mi.setIcon(new ImageIcon(url));
  183.     }
  184.     String astr = getResourceString(cmd + actionSuffix);
  185.     if (astr == null) {
  186.         astr = cmd;
  187.     }
  188.     mi.setActionCommand(astr);
  189.     Action a = getAction(astr);
  190.     if (a != null) {
  191.         mi.addActionListener(a);
  192.         a.addPropertyChangeListener(createActionChangeListener(mi));
  193.         mi.setEnabled(a.isEnabled());
  194.     } else {
  195.         mi.setEnabled(false);
  196.     }
  197.     menuItems.put(cmd, mi);
  198.     return mi;
  199.     }
  200.  
  201.     /**
  202.      * Fetch the menu item that was created for the given
  203.      * command.
  204.      * @param cmd  Name of the action.
  205.      * @returns item created for the given command or null
  206.      *  if one wasn't created.
  207.      */
  208.     protected JMenuItem getMenuItem(String cmd) {
  209.     return (JMenuItem) menuItems.get(cmd);
  210.     }
  211.  
  212.     protected Action getAction(String cmd) {
  213.     return (Action) commands.get(cmd);
  214.     }
  215.  
  216.     protected String getResourceString(String nm) {
  217.     String str;
  218.     try {
  219.         str = resources.getString(nm);
  220.     } catch (MissingResourceException mre) {
  221.         str = null;
  222.     }
  223.     return str;
  224.     }
  225.  
  226.     protected URL getResource(String key) {
  227.     String name = getResourceString(key);
  228.     if (name != null) {
  229.         URL url = this.getClass().getResource(name);
  230.         return url;
  231.     }
  232.     return null;
  233.     }
  234.  
  235.     protected Container getToolbar() {
  236.     return toolbar;
  237.     }
  238.  
  239.     protected JMenuBar getMenubar() {
  240.     return menubar;
  241.     }
  242.  
  243.     /**
  244.      * Create a status bar
  245.      */
  246.     protected Component createStatusbar() {
  247.     // need to do something reasonable here
  248.     status = new StatusBar();
  249.     return status;
  250.     }
  251.  
  252.     /**
  253.      * Create the toolbar.  By default this reads the 
  254.      * resource file for the definition of the toolbar.
  255.      */
  256.     private Component createToolbar() {
  257.     toolbar = new JToolBar();
  258.     String[] toolKeys = tokenize(getResourceString("toolbar"));
  259.     for (int i = 0; i < toolKeys.length; i++) {
  260.         if (toolKeys[i].equals("-")) {
  261.         toolbar.add(Box.createHorizontalStrut(5));
  262.         } else {
  263.         toolbar.add(createTool(toolKeys[i]));
  264.         }
  265.     }
  266.     toolbar.add(Box.createHorizontalGlue());
  267.     return toolbar;
  268.     }
  269.  
  270.     /**
  271.      * Hook through which every toolbar item is created.
  272.      */
  273.     protected Component createTool(String key) {
  274.     return createToolbarButton(key);
  275.     }
  276.  
  277.     /**
  278.      * Create a button to go inside of the toolbar.  By default this
  279.      * will load an image resource.  The image filename is relative to
  280.      * the classpath (including the '.' directory if its a part of the
  281.      * classpath), and may either be in a JAR file or a separate file.
  282.      * 
  283.      * @param key The key in the resource file to serve as the basis
  284.      *  of lookups.
  285.      */
  286.     protected JButton createToolbarButton(String key) {
  287.     URL url = getResource(key + imageSuffix);
  288.         JButton b = new JButton(new ImageIcon(url)) {
  289.             public float getAlignmentY() { return 0.5f; }
  290.     };
  291.         b.setRequestFocusEnabled(false);
  292.         b.setMargin(new Insets(1,1,1,1));
  293.  
  294.     String astr = getResourceString(key + actionSuffix);
  295.     if (astr == null) {
  296.         astr = key;
  297.     }
  298.     Action a = getAction(astr);
  299.     if (a != null) {
  300.         b.setActionCommand(astr);
  301.         b.addActionListener(a);
  302.     } else {
  303.         b.setEnabled(false);
  304.     }
  305.  
  306.     String tip = getResourceString(key + tipSuffix);
  307.     if (tip != null) {
  308.         b.setToolTipText(tip);
  309.     }
  310.  
  311.         return b;
  312.     }
  313.  
  314.     /**
  315.      * Take the given string and chop it up into a series
  316.      * of strings on whitespace boundries.  This is useful
  317.      * for trying to get an array of strings out of the
  318.      * resource file.
  319.      */
  320.     protected String[] tokenize(String input) {
  321.     Vector v = new Vector();
  322.     StringTokenizer t = new StringTokenizer(input);
  323.     String cmd[];
  324.  
  325.     while (t.hasMoreTokens())
  326.         v.addElement(t.nextToken());
  327.     cmd = new String[v.size()];
  328.     for (int i = 0; i < cmd.length; i++)
  329.         cmd[i] = (String) v.elementAt(i);
  330.  
  331.     return cmd;
  332.     }
  333.  
  334.     /**
  335.      * Create the menubar for the app.  By default this pulls the
  336.      * definition of the menu from the associated resource file. 
  337.      */
  338.     protected JMenuBar createMenubar() {
  339.     JMenuItem mi;
  340.     JMenuBar mb = new JMenuBar();
  341.  
  342.     String[] menuKeys = tokenize(getResourceString("menubar"));
  343.     for (int i = 0; i < menuKeys.length; i++) {
  344.         JMenu m = createMenu(menuKeys[i]);
  345.         if (m != null) {
  346.         mb.add(m);
  347.         }
  348.     }
  349.     return mb;
  350.     }
  351.  
  352.     /**
  353.      * Create a menu for the app.  By default this pulls the
  354.      * definition of the menu from the associated resource file.
  355.      */
  356.     protected JMenu createMenu(String key) {
  357.     String[] itemKeys = tokenize(getResourceString(key));
  358.     JMenu menu = new JMenu(getResourceString(key + "Label"));
  359.     for (int i = 0; i < itemKeys.length; i++) {
  360.         if (itemKeys[i].equals("-")) {
  361.         menu.addSeparator();
  362.         } else {
  363.         JMenuItem mi = createMenuItem(itemKeys[i]);
  364.         menu.add(mi);
  365.         }
  366.     }
  367.     return menu;
  368.     }
  369.  
  370.     // Yarked from JMenu, ideally this would be public.
  371.     protected PropertyChangeListener createActionChangeListener(JMenuItem b) {
  372.     return new ActionChangedListener(b);
  373.     }
  374.  
  375.     // Yarked from JMenu, ideally this would be public.
  376.     private class ActionChangedListener implements PropertyChangeListener {
  377.         JMenuItem menuItem;
  378.         
  379.         ActionChangedListener(JMenuItem mi) {
  380.             super();
  381.             this.menuItem = mi;
  382.         }
  383.         public void propertyChange(PropertyChangeEvent e) {
  384.             String propertyName = e.getPropertyName();
  385.             if (e.getPropertyName().equals(Action.NAME)) {
  386.                 String text = (String) e.getNewValue();
  387.                 menuItem.setText(text);
  388.             } else if (propertyName.equals("enabled")) {
  389.                 Boolean enabledState = (Boolean) e.getNewValue();
  390.                 menuItem.setEnabled(enabledState.booleanValue());
  391.             }
  392.         }
  393.     }
  394.  
  395.     private JTextComponent editor;
  396.     private Hashtable commands;
  397.     private Hashtable menuItems;
  398.     private JMenuBar menubar;
  399.     private JToolBar toolbar;
  400.     private JComponent status;
  401.     private JFrame elementTreeFrame;
  402.  
  403.     protected FileDialog fileDialog;
  404.  
  405.     /**
  406.      * Listener for the edits on the current document.
  407.      */
  408.     protected UndoableEditListener undoHandler = new UndoHandler();
  409.  
  410.     /** UndoManager that we add edits to. */
  411.     protected UndoManager undo = new UndoManager();
  412.  
  413.     /**
  414.      * Suffix applied to the key used in resource file
  415.      * lookups for an image.
  416.      */
  417.     public static final String imageSuffix = "Image";
  418.  
  419.     /**
  420.      * Suffix applied to the key used in resource file
  421.      * lookups for a label.
  422.      */
  423.     public static final String labelSuffix = "Label";
  424.  
  425.     /**
  426.      * Suffix applied to the key used in resource file
  427.      * lookups for an action.
  428.      */
  429.     public static final String actionSuffix = "Action";
  430.  
  431.     /**
  432.      * Suffix applied to the key used in resource file
  433.      * lookups for tooltip text.
  434.      */
  435.     public static final String tipSuffix = "Tooltip";
  436.  
  437.     public static final String openAction = "open";
  438.     public static final String newAction  = "new";
  439.     public static final String saveAction = "save";
  440.     public static final String exitAction = "exit";
  441.     public static final String showElementTreeAction = "showElementTree";
  442.  
  443.     class UndoHandler implements UndoableEditListener {
  444.  
  445.     /**
  446.      * Messaged when the Document has created an edit, the edit is
  447.      * added to <code>undo</code>, an instance of UndoManager.
  448.      */
  449.         public void undoableEditHappened(UndoableEditEvent e) {
  450.         undo.addEdit(e.getEdit());
  451.         undoAction.update();
  452.         redoAction.update();
  453.     }
  454.     }
  455.  
  456.     /**
  457.      * FIXME - I'm not very useful yet
  458.      */
  459.     class StatusBar extends JComponent {
  460.  
  461.         public StatusBar() {
  462.         super();
  463.         setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
  464.     }
  465.  
  466.         public void paint(Graphics g) {
  467.         super.paint(g);
  468.     }
  469.  
  470.     }
  471.  
  472.     // --- action implementations -----------------------------------
  473.  
  474.     private UndoAction undoAction = new UndoAction();
  475.     private RedoAction redoAction = new RedoAction();
  476.  
  477.     /**
  478.      * Actions defined by the Notepad class
  479.      */
  480.     private Action[] defaultActions = {
  481.     new NewAction(),
  482.     new OpenAction(),
  483.     new ExitAction(),
  484.     new ShowElementTreeAction(),
  485.         undoAction,
  486.         redoAction
  487.     };
  488.  
  489.     class UndoAction extends AbstractAction {
  490.     public UndoAction() {
  491.         super("Undo");
  492.         setEnabled(false);
  493.     }
  494.  
  495.     public void actionPerformed(ActionEvent e) {
  496.         try {
  497.         undo.undo();
  498.         } catch (CannotUndoException ex) {
  499.         System.out.println("Unable to undo: " + ex);
  500.         ex.printStackTrace();
  501.         }
  502.         update();
  503.         redoAction.update();
  504.     }
  505.  
  506.     protected void update() {
  507.         if(undo.canUndo()) {
  508.         setEnabled(true);
  509.         putValue(Action.NAME, undo.getUndoPresentationName());
  510.         }
  511.         else {
  512.         setEnabled(false);
  513.         putValue(Action.NAME, "Undo");
  514.         }
  515.     }
  516.     }
  517.  
  518.     class RedoAction extends AbstractAction {
  519.     public RedoAction() {
  520.         super("Redo");
  521.         setEnabled(false);
  522.     }
  523.  
  524.     public void actionPerformed(ActionEvent e) {
  525.         try {
  526.         undo.redo();
  527.         } catch (CannotRedoException ex) {
  528.         System.out.println("Unable to redo: " + ex);
  529.         ex.printStackTrace();
  530.         }
  531.         update();
  532.         undoAction.update();
  533.     }
  534.  
  535.     protected void update() {
  536.         if(undo.canRedo()) {
  537.         setEnabled(true);
  538.         putValue(Action.NAME, undo.getRedoPresentationName());
  539.         }
  540.         else {
  541.         setEnabled(false);
  542.         putValue(Action.NAME, "Redo");
  543.         }
  544.     }
  545.     }
  546.  
  547.     class OpenAction extends NewAction {
  548.  
  549.     OpenAction() {
  550.         super(openAction);
  551.     }
  552.  
  553.         public void actionPerformed(ActionEvent e) {
  554.         Frame frame = getFrame();
  555.         if (fileDialog == null) {
  556.         fileDialog = new FileDialog(frame);
  557.         }
  558.         fileDialog.setMode(FileDialog.LOAD);
  559.         fileDialog.show();
  560.  
  561.         String file = fileDialog.getFile();
  562.         if (file == null) {
  563.         return;
  564.         }
  565.         String directory = fileDialog.getDirectory();
  566.         File f = new File(directory, file);
  567.         if (f.exists()) {
  568.         Document oldDoc = getEditor().getDocument();
  569.         if(oldDoc != null)
  570.             oldDoc.removeUndoableEditListener(undoHandler);
  571.         getEditor().setDocument(new PlainDocument());
  572.         frame.setTitle(file);
  573.         Thread loader = new FileLoader(f, editor.getDocument());
  574.         loader.start();
  575.         }
  576.     }
  577.     }
  578.     
  579.     class NewAction extends AbstractAction {
  580.  
  581.     NewAction() {
  582.         super(newAction);
  583.     }
  584.  
  585.     NewAction(String nm) {
  586.         super(nm);
  587.     }
  588.  
  589.         public void actionPerformed(ActionEvent e) {
  590.         Document oldDoc = getEditor().getDocument();
  591.         if(oldDoc != null)
  592.         oldDoc.removeUndoableEditListener(undoHandler);
  593.         getEditor().setDocument(new PlainDocument());
  594.         getEditor().getDocument().addUndoableEditListener(undoHandler);
  595.         revalidate();
  596.     }
  597.     }
  598.  
  599.     /**
  600.      * Really lame implementation of an exit command
  601.      */
  602.     class ExitAction extends AbstractAction {
  603.  
  604.     ExitAction() {
  605.         super(exitAction);
  606.     }
  607.  
  608.         public void actionPerformed(ActionEvent e) {
  609.         System.exit(0);
  610.     }
  611.     }
  612.  
  613.     /**
  614.      * Action that brings up a JFrame with a JTree showing the structure
  615.      * of the document.
  616.      */
  617.     class ShowElementTreeAction extends AbstractAction {
  618.  
  619.     ShowElementTreeAction() {
  620.         super(showElementTreeAction);
  621.     }
  622.  
  623.     ShowElementTreeAction(String nm) {
  624.         super(nm);
  625.     }
  626.  
  627.         public void actionPerformed(ActionEvent e) {
  628.         if(elementTreeFrame == null) {
  629.         // Create a frame containing an instance of 
  630.         // ElementTreePanel.
  631.         try {
  632.             String    title = resources.getString
  633.                             ("ElementTreeFrameTitle");
  634.             elementTreeFrame = new JFrame(title);
  635.         } catch (MissingResourceException mre) {
  636.             elementTreeFrame = new JFrame();
  637.         }
  638.  
  639.         elementTreeFrame.addWindowListener(new WindowAdapter() {
  640.             public void windowClosing(WindowEvent weeee) {
  641.             elementTreeFrame.setVisible(false);
  642.             }
  643.         });
  644.         Container fContentPane = elementTreeFrame.getContentPane();
  645.  
  646.         fContentPane.setLayout(new BorderLayout());
  647.         fContentPane.add(new ElementTreePanel(getEditor()));
  648.         elementTreeFrame.pack();
  649.         }
  650.         elementTreeFrame.show();
  651.     }
  652.     }
  653.  
  654.     /**
  655.      * Thread to load a file into the text storage model
  656.      */
  657.     class FileLoader extends Thread {
  658.  
  659.     FileLoader(File f, Document doc) {
  660.         setPriority(4);
  661.         this.f = f;
  662.         this.doc = doc;
  663.     }
  664.  
  665.         public void run() {
  666.         try {
  667.         // initialize the statusbar
  668.         status.removeAll();
  669.         JProgressBar progress = new JProgressBar();
  670.         progress.setMinimum(0);
  671.         progress.setMaximum((int) f.length());
  672.         status.add(progress);
  673.         status.revalidate();
  674.  
  675.         // try to start reading
  676.         Reader in = new FileReader(f);
  677.         char[] buff = new char[4096];
  678.         int nch;
  679.         while ((nch = in.read(buff, 0, buff.length)) != -1) {
  680.             doc.insertString(doc.getLength(), new String(buff, 0, nch), null);
  681.             progress.setValue(progress.getValue() + nch);
  682.         }
  683.  
  684.         // we are done... get rid of progressbar
  685.         doc.addUndoableEditListener(undoHandler);
  686.         status.removeAll();
  687.         status.revalidate();
  688.         }
  689.         catch (IOException e) {
  690.         System.err.println(e.toString());
  691.         }
  692.         catch (BadLocationException e) {
  693.         System.err.println(e.getMessage());
  694.         }
  695.     }
  696.  
  697.     Document doc;
  698.     File f;
  699.     }
  700.  
  701. }
  702.