| /* |
| * |
| * Copyright (c) 2007, 2011, Oracle and/or its affiliates. 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. |
| * |
| * - Redistributions 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 Oracle nor the names of its |
| * contributors may be used to endorse or promote products derived |
| * from this software without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS |
| * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, |
| * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
| * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR |
| * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
| * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
| * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
| * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
| * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
| * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
| * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| |
| import java.awt.BorderLayout; |
| import java.awt.Color; |
| import java.awt.Component; |
| import java.awt.FileDialog; |
| import java.awt.Frame; |
| import java.awt.Graphics; |
| import java.awt.GraphicsEnvironment; |
| import java.awt.event.ActionEvent; |
| import java.awt.event.ActionListener; |
| import java.io.File; |
| import java.io.FileInputStream; |
| import java.io.FileOutputStream; |
| import java.io.IOException; |
| import java.io.ObjectInputStream; |
| import java.io.ObjectOutput; |
| import java.io.ObjectOutputStream; |
| import java.lang.reflect.InvocationTargetException; |
| import java.util.MissingResourceException; |
| import java.util.ResourceBundle; |
| import java.util.logging.Level; |
| import java.util.logging.Logger; |
| import javax.swing.AbstractAction; |
| import javax.swing.Action; |
| import javax.swing.Icon; |
| import javax.swing.JButton; |
| import javax.swing.JComboBox; |
| import javax.swing.JFrame; |
| import javax.swing.JMenu; |
| import javax.swing.JMenuItem; |
| import javax.swing.JTextPane; |
| import javax.swing.SwingUtilities; |
| import javax.swing.text.DefaultStyledDocument; |
| import javax.swing.text.Document; |
| import javax.swing.text.JTextComponent; |
| import javax.swing.text.StyleContext; |
| import javax.swing.text.StyledEditorKit; |
| import javax.swing.text.TextAction; |
| |
| |
| /** |
| * Sample application using JTextPane. |
| * |
| * @author Timothy Prinzing |
| */ |
| @SuppressWarnings("serial") |
| public class Stylepad extends Notepad { |
| |
| private static ResourceBundle resources; |
| private FileDialog fileDialog; |
| |
| private static final String[] MENUBAR_KEYS = {"file", "edit", "color", |
| "font", "debug"}; |
| private static final String[] FONT_KEYS = {"family1", "family2", "family3", |
| "family4", "-", "size1", "size2", "size3", "size4", "size5", "-", |
| "bold", "italic", "underline"}; |
| private static final String[] TOOLBAR_KEYS = {"new", "open", "save", "-", |
| "cut", "copy", "paste", "-", "bold", "italic", "underline", "-", |
| "left", "center", "right"}; |
| |
| |
| static { |
| try { |
| properties.load(Stylepad.class.getResourceAsStream( |
| "resources/StylepadSystem.properties")); |
| resources = ResourceBundle.getBundle("resources.Stylepad"); |
| } catch (MissingResourceException | IOException mre) { |
| System.err.println("Stylepad.properties or StylepadSystem.properties not found"); |
| System.exit(0); |
| } |
| } |
| |
| public Stylepad() { |
| super(); |
| } |
| |
| public static void main(String[] args) { |
| try { |
| SwingUtilities.invokeAndWait(new Runnable() { |
| |
| public void run() { |
| JFrame frame = new JFrame(); |
| frame.setTitle(resources.getString("Title")); |
| frame.setBackground(Color.lightGray); |
| frame.getContentPane(). |
| setLayout(new BorderLayout()); |
| Stylepad stylepad = new Stylepad(); |
| frame.getContentPane().add("Center", stylepad); |
| frame.setJMenuBar(stylepad.createMenubar()); |
| frame.addWindowListener(new AppCloser()); |
| frame.pack(); |
| frame.setSize(600, 480); |
| frame.setVisible(true); |
| } |
| }); |
| } catch (InterruptedException ex) { |
| Logger.getLogger(Stylepad.class.getName()).log(Level.SEVERE, null, |
| ex); |
| } catch (InvocationTargetException ex) { |
| Logger.getLogger(Stylepad.class.getName()).log(Level.SEVERE, null, |
| ex); |
| } |
| } |
| |
| /** |
| * Fetch the list of actions supported by this |
| * editor. It is implemented to return the list |
| * of actions supported by the superclass |
| * augmented with the actions defined locally. |
| */ |
| @Override |
| public Action[] getActions() { |
| Action[] defaultActions = { |
| new NewAction(), |
| new OpenAction(), |
| new SaveAction(), |
| new StyledEditorKit.FontFamilyAction("font-family-SansSerif", |
| "SansSerif"), }; |
| Action[] a = TextAction.augmentList(super.getActions(), defaultActions); |
| return a; |
| } |
| |
| /** |
| * Try and resolve the resource name in the local |
| * resource file, and if not found fall back to |
| * the superclass resource file. |
| */ |
| @Override |
| protected String getResourceString(String nm) { |
| String str; |
| try { |
| str = Stylepad.resources.getString(nm); |
| } catch (MissingResourceException mre) { |
| str = super.getResourceString(nm); |
| } |
| return str; |
| } |
| |
| /** |
| * Create an editor to represent the given document. |
| */ |
| @Override |
| protected JTextComponent createEditor() { |
| StyleContext sc = new StyleContext(); |
| DefaultStyledDocument doc = new DefaultStyledDocument(sc); |
| initDocument(doc, sc); |
| JTextPane p = new JTextPane(doc); |
| p.setDragEnabled(true); |
| |
| //p.getCaret().setBlinkRate(0); |
| |
| return p; |
| } |
| |
| /** |
| * Create a menu for the app. This is redefined to trap |
| * a couple of special entries for now. |
| */ |
| @Override |
| protected JMenu createMenu(String key) { |
| if (key.equals("color")) { |
| return createColorMenu(); |
| } |
| return super.createMenu(key); |
| } |
| |
| @Override |
| protected String[] getItemKeys(String key) { |
| switch (key) { |
| case "font": |
| return FONT_KEYS; |
| default: |
| return super.getItemKeys(key); |
| } |
| } |
| |
| @Override |
| protected String[] getMenuBarKeys() { |
| return MENUBAR_KEYS; |
| } |
| |
| @Override |
| protected String[] getToolBarKeys() { |
| return TOOLBAR_KEYS; |
| } |
| |
| // this will soon be replaced |
| JMenu createColorMenu() { |
| ActionListener a; |
| JMenuItem mi; |
| JMenu menu = new JMenu(getResourceString("color" + labelSuffix)); |
| mi = new JMenuItem(resources.getString("Red")); |
| mi.setHorizontalTextPosition(JButton.RIGHT); |
| mi.setIcon(new ColoredSquare(Color.red)); |
| a = |
| new StyledEditorKit.ForegroundAction("set-foreground-red", |
| Color.red); |
| //a = new ColorAction(se, Color.red); |
| mi.addActionListener(a); |
| menu.add(mi); |
| mi = new JMenuItem(resources.getString("Green")); |
| mi.setHorizontalTextPosition(JButton.RIGHT); |
| mi.setIcon(new ColoredSquare(Color.green)); |
| a = new StyledEditorKit.ForegroundAction("set-foreground-green", |
| Color.green); |
| //a = new ColorAction(se, Color.green); |
| mi.addActionListener(a); |
| menu.add(mi); |
| mi = new JMenuItem(resources.getString("Blue")); |
| mi.setHorizontalTextPosition(JButton.RIGHT); |
| mi.setIcon(new ColoredSquare(Color.blue)); |
| a = new StyledEditorKit.ForegroundAction("set-foreground-blue", |
| Color.blue); |
| //a = new ColorAction(se, Color.blue); |
| mi.addActionListener(a); |
| menu.add(mi); |
| |
| return menu; |
| } |
| |
| void initDocument(DefaultStyledDocument doc, StyleContext sc) { |
| Wonderland w = new Wonderland(doc, sc); |
| w.loadDocument(); |
| } |
| |
| JComboBox createFamilyChoices() { |
| JComboBox b = new JComboBox(); |
| String[] fontNames = GraphicsEnvironment.getLocalGraphicsEnvironment(). |
| getAvailableFontFamilyNames(); |
| for (String fontName : fontNames) { |
| b.addItem(fontName); |
| } |
| return b; |
| } |
| |
| |
| /** |
| * Trys to read a file which is assumed to be a |
| * serialization of a document. |
| */ |
| class OpenAction extends AbstractAction { |
| |
| OpenAction() { |
| super(openAction); |
| } |
| |
| @Override |
| public void actionPerformed(ActionEvent e) { |
| Frame frame = getFrame(); |
| if (fileDialog == null) { |
| fileDialog = new FileDialog(frame); |
| } |
| fileDialog.setMode(FileDialog.LOAD); |
| fileDialog.setVisible(true); |
| |
| String file = fileDialog.getFile(); |
| if (file == null) { |
| return; |
| } |
| String directory = fileDialog.getDirectory(); |
| File f = new File(directory, file); |
| if (f.exists()) { |
| try { |
| FileInputStream fin = new FileInputStream(f); |
| ObjectInputStream istrm = new ObjectInputStream(fin); |
| Document doc = (Document) istrm.readObject(); |
| if (getEditor().getDocument() != null) { |
| getEditor().getDocument().removeUndoableEditListener( |
| undoHandler); |
| } |
| getEditor().setDocument(doc); |
| doc.addUndoableEditListener(undoHandler); |
| resetUndoManager(); |
| frame.setTitle(file); |
| validate(); |
| } catch (IOException io) { |
| // should put in status panel |
| System.err.println("IOException: " + io.getMessage()); |
| } catch (ClassNotFoundException cnf) { |
| // should put in status panel |
| System.err.println("Class not found: " + cnf.getMessage()); |
| } |
| } else { |
| // should put in status panel |
| System.err.println("No such file: " + f); |
| } |
| } |
| } |
| |
| |
| /** |
| * Trys to write the document as a serialization. |
| */ |
| class SaveAction extends AbstractAction { |
| |
| SaveAction() { |
| super(saveAction); |
| } |
| |
| @Override |
| public void actionPerformed(ActionEvent e) { |
| Frame frame = getFrame(); |
| if (fileDialog == null) { |
| fileDialog = new FileDialog(frame); |
| } |
| fileDialog.setMode(FileDialog.SAVE); |
| fileDialog.setVisible(true); |
| String file = fileDialog.getFile(); |
| if (file == null) { |
| return; |
| } |
| String directory = fileDialog.getDirectory(); |
| File f = new File(directory, file); |
| try { |
| FileOutputStream fstrm = new FileOutputStream(f); |
| ObjectOutput ostrm = new ObjectOutputStream(fstrm); |
| ostrm.writeObject(getEditor().getDocument()); |
| ostrm.flush(); |
| frame.setTitle(f.getName()); |
| } catch (IOException io) { |
| // should put in status panel |
| System.err.println("IOException: " + io.getMessage()); |
| } |
| } |
| } |
| |
| |
| /** |
| * Creates an empty document. |
| */ |
| class NewAction extends AbstractAction { |
| |
| NewAction() { |
| super(newAction); |
| } |
| |
| @Override |
| public void actionPerformed(ActionEvent e) { |
| if (getEditor().getDocument() != null) { |
| getEditor().getDocument().removeUndoableEditListener(undoHandler); |
| } |
| getEditor().setDocument(new DefaultStyledDocument()); |
| getEditor().getDocument().addUndoableEditListener(undoHandler); |
| resetUndoManager(); |
| getFrame().setTitle(resources.getString("Title")); |
| validate(); |
| } |
| } |
| |
| |
| class ColoredSquare implements Icon { |
| |
| Color color; |
| |
| public ColoredSquare(Color c) { |
| this.color = c; |
| } |
| |
| @Override |
| public void paintIcon(Component c, Graphics g, int x, int y) { |
| Color oldColor = g.getColor(); |
| g.setColor(color); |
| g.fill3DRect(x, y, getIconWidth(), getIconHeight(), true); |
| g.setColor(oldColor); |
| } |
| |
| @Override |
| public int getIconWidth() { |
| return 12; |
| } |
| |
| @Override |
| public int getIconHeight() { |
| return 12; |
| } |
| } |
| } |