home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 1998 October A / Pcwk10a98.iso / Inprise / TRIAL / JBUILDER / JSAMPLES.Z / Notepad.java < prev    next >
Text File  |  1998-05-08  |  17KB  |  656 lines

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