Path: blob/master/src/demo/share/jfc/Stylepad/Stylepad.java
41152 views
/*1*2* Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.3*4* Redistribution and use in source and binary forms, with or without5* modification, are permitted provided that the following conditions6* are met:7*8* - Redistributions of source code must retain the above copyright9* notice, this list of conditions and the following disclaimer.10*11* - Redistributions in binary form must reproduce the above copyright12* notice, this list of conditions and the following disclaimer in the13* documentation and/or other materials provided with the distribution.14*15* - Neither the name of Oracle nor the names of its16* contributors may be used to endorse or promote products derived17* from this software without specific prior written permission.18*19* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS20* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,21* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR22* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR23* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,24* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,25* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR26* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF27* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING28* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS29* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.30*/313233import java.awt.BorderLayout;34import java.awt.Color;35import java.awt.Component;36import java.awt.FileDialog;37import java.awt.Frame;38import java.awt.Graphics;39import java.awt.GraphicsEnvironment;40import java.awt.event.ActionEvent;41import java.awt.event.ActionListener;42import java.io.File;43import java.io.FileInputStream;44import java.io.FileOutputStream;45import java.io.IOException;46import java.io.ObjectInputStream;47import java.io.ObjectOutput;48import java.io.ObjectOutputStream;49import java.lang.reflect.InvocationTargetException;50import java.util.MissingResourceException;51import java.util.ResourceBundle;52import java.util.logging.Level;53import java.util.logging.Logger;54import javax.swing.AbstractAction;55import javax.swing.Action;56import javax.swing.Icon;57import javax.swing.JButton;58import javax.swing.JComboBox;59import javax.swing.JFrame;60import javax.swing.JMenu;61import javax.swing.JMenuItem;62import javax.swing.JTextPane;63import javax.swing.SwingUtilities;64import javax.swing.text.DefaultStyledDocument;65import javax.swing.text.Document;66import javax.swing.text.JTextComponent;67import javax.swing.text.StyleContext;68import javax.swing.text.StyledEditorKit;69import javax.swing.text.TextAction;707172/**73* Sample application using JTextPane.74*75* @author Timothy Prinzing76*/77@SuppressWarnings("serial")78public class Stylepad extends Notepad {7980private static ResourceBundle resources;81private FileDialog fileDialog;8283private static final String[] MENUBAR_KEYS = {"file", "edit", "color",84"font", "debug"};85private static final String[] FONT_KEYS = {"family1", "family2", "family3",86"family4", "-", "size1", "size2", "size3", "size4", "size5", "-",87"bold", "italic", "underline"};88private static final String[] TOOLBAR_KEYS = {"new", "open", "save", "-",89"cut", "copy", "paste", "-", "bold", "italic", "underline", "-",90"left", "center", "right"};919293static {94try {95properties.load(Stylepad.class.getResourceAsStream(96"resources/StylepadSystem.properties"));97resources = ResourceBundle.getBundle("resources.Stylepad");98} catch (MissingResourceException | IOException mre) {99System.err.println("Stylepad.properties or StylepadSystem.properties not found");100System.exit(0);101}102}103104public Stylepad() {105super();106}107108public static void main(String[] args) {109try {110SwingUtilities.invokeAndWait(new Runnable() {111112public void run() {113JFrame frame = new JFrame();114frame.setTitle(resources.getString("Title"));115frame.setBackground(Color.lightGray);116frame.getContentPane().117setLayout(new BorderLayout());118Stylepad stylepad = new Stylepad();119frame.getContentPane().add("Center", stylepad);120frame.setJMenuBar(stylepad.createMenubar());121frame.addWindowListener(new AppCloser());122frame.pack();123frame.setSize(600, 480);124frame.setVisible(true);125}126});127} catch (InterruptedException ex) {128Logger.getLogger(Stylepad.class.getName()).log(Level.SEVERE, null,129ex);130} catch (InvocationTargetException ex) {131Logger.getLogger(Stylepad.class.getName()).log(Level.SEVERE, null,132ex);133}134}135136/**137* Fetch the list of actions supported by this138* editor. It is implemented to return the list139* of actions supported by the superclass140* augmented with the actions defined locally.141*/142@Override143public Action[] getActions() {144Action[] defaultActions = {145new NewAction(),146new OpenAction(),147new SaveAction(),148new StyledEditorKit.FontFamilyAction("font-family-SansSerif",149"SansSerif"), };150Action[] a = TextAction.augmentList(super.getActions(), defaultActions);151return a;152}153154/**155* Try and resolve the resource name in the local156* resource file, and if not found fall back to157* the superclass resource file.158*/159@Override160protected String getResourceString(String nm) {161String str;162try {163str = Stylepad.resources.getString(nm);164} catch (MissingResourceException mre) {165str = super.getResourceString(nm);166}167return str;168}169170/**171* Create an editor to represent the given document.172*/173@Override174protected JTextComponent createEditor() {175StyleContext sc = new StyleContext();176DefaultStyledDocument doc = new DefaultStyledDocument(sc);177initDocument(doc, sc);178JTextPane p = new JTextPane(doc);179p.setDragEnabled(true);180181//p.getCaret().setBlinkRate(0);182183return p;184}185186/**187* Create a menu for the app. This is redefined to trap188* a couple of special entries for now.189*/190@Override191protected JMenu createMenu(String key) {192if (key.equals("color")) {193return createColorMenu();194}195return super.createMenu(key);196}197198@Override199protected String[] getItemKeys(String key) {200switch (key) {201case "font":202return FONT_KEYS;203default:204return super.getItemKeys(key);205}206}207208@Override209protected String[] getMenuBarKeys() {210return MENUBAR_KEYS;211}212213@Override214protected String[] getToolBarKeys() {215return TOOLBAR_KEYS;216}217218// this will soon be replaced219JMenu createColorMenu() {220ActionListener a;221JMenuItem mi;222JMenu menu = new JMenu(getResourceString("color" + labelSuffix));223mi = new JMenuItem(resources.getString("Red"));224mi.setHorizontalTextPosition(JButton.RIGHT);225mi.setIcon(new ColoredSquare(Color.red));226a =227new StyledEditorKit.ForegroundAction("set-foreground-red",228Color.red);229//a = new ColorAction(se, Color.red);230mi.addActionListener(a);231menu.add(mi);232mi = new JMenuItem(resources.getString("Green"));233mi.setHorizontalTextPosition(JButton.RIGHT);234mi.setIcon(new ColoredSquare(Color.green));235a = new StyledEditorKit.ForegroundAction("set-foreground-green",236Color.green);237//a = new ColorAction(se, Color.green);238mi.addActionListener(a);239menu.add(mi);240mi = new JMenuItem(resources.getString("Blue"));241mi.setHorizontalTextPosition(JButton.RIGHT);242mi.setIcon(new ColoredSquare(Color.blue));243a = new StyledEditorKit.ForegroundAction("set-foreground-blue",244Color.blue);245//a = new ColorAction(se, Color.blue);246mi.addActionListener(a);247menu.add(mi);248249return menu;250}251252void initDocument(DefaultStyledDocument doc, StyleContext sc) {253Wonderland w = new Wonderland(doc, sc);254w.loadDocument();255}256257JComboBox<String> createFamilyChoices() {258JComboBox<String> b = new JComboBox<>();259String[] fontNames = GraphicsEnvironment.getLocalGraphicsEnvironment().260getAvailableFontFamilyNames();261for (String fontName : fontNames) {262b.addItem(fontName);263}264return b;265}266267268/**269* Trys to read a file which is assumed to be a270* serialization of a document.271*/272class OpenAction extends AbstractAction {273274OpenAction() {275super(openAction);276}277278@Override279public void actionPerformed(ActionEvent e) {280Frame frame = getFrame();281if (fileDialog == null) {282fileDialog = new FileDialog(frame);283}284fileDialog.setMode(FileDialog.LOAD);285fileDialog.setVisible(true);286287String file = fileDialog.getFile();288if (file == null) {289return;290}291String directory = fileDialog.getDirectory();292File f = new File(directory, file);293if (f.exists()) {294try {295FileInputStream fin = new FileInputStream(f);296ObjectInputStream istrm = new ObjectInputStream(fin);297Document doc = (Document) istrm.readObject();298if (getEditor().getDocument() != null) {299getEditor().getDocument().removeUndoableEditListener(300undoHandler);301}302getEditor().setDocument(doc);303doc.addUndoableEditListener(undoHandler);304resetUndoManager();305frame.setTitle(file);306validate();307} catch (IOException io) {308// should put in status panel309System.err.println("IOException: " + io.getMessage());310} catch (ClassNotFoundException cnf) {311// should put in status panel312System.err.println("Class not found: " + cnf.getMessage());313}314} else {315// should put in status panel316System.err.println("No such file: " + f);317}318}319}320321322/**323* Trys to write the document as a serialization.324*/325class SaveAction extends AbstractAction {326327SaveAction() {328super(saveAction);329}330331@Override332public void actionPerformed(ActionEvent e) {333Frame frame = getFrame();334if (fileDialog == null) {335fileDialog = new FileDialog(frame);336}337fileDialog.setMode(FileDialog.SAVE);338fileDialog.setVisible(true);339String file = fileDialog.getFile();340if (file == null) {341return;342}343String directory = fileDialog.getDirectory();344File f = new File(directory, file);345try {346FileOutputStream fstrm = new FileOutputStream(f);347ObjectOutput ostrm = new ObjectOutputStream(fstrm);348ostrm.writeObject(getEditor().getDocument());349ostrm.flush();350frame.setTitle(f.getName());351} catch (IOException io) {352// should put in status panel353System.err.println("IOException: " + io.getMessage());354}355}356}357358359/**360* Creates an empty document.361*/362class NewAction extends AbstractAction {363364NewAction() {365super(newAction);366}367368@Override369public void actionPerformed(ActionEvent e) {370if (getEditor().getDocument() != null) {371getEditor().getDocument().removeUndoableEditListener(undoHandler);372}373getEditor().setDocument(new DefaultStyledDocument());374getEditor().getDocument().addUndoableEditListener(undoHandler);375resetUndoManager();376getFrame().setTitle(resources.getString("Title"));377validate();378}379}380381382class ColoredSquare implements Icon {383384Color color;385386public ColoredSquare(Color c) {387this.color = c;388}389390@Override391public void paintIcon(Component c, Graphics g, int x, int y) {392Color oldColor = g.getColor();393g.setColor(color);394g.fill3DRect(x, y, getIconWidth(), getIconHeight(), true);395g.setColor(oldColor);396}397398@Override399public int getIconWidth() {400return 12;401}402403@Override404public int getIconHeight() {405return 12;406}407}408}409410411