1 /*
2  * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.  Oracle designates this
8  * particular file as subject to the "Classpath" exception as provided
9  * by Oracle in the LICENSE file that accompanied this code.
10  *
11  * This code is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14  * version 2 for more details (a copy is included in the LICENSE file that
15  * accompanied this code).
16  *
17  * You should have received a copy of the GNU General Public License version
18  * 2 along with this work; if not, write to the Free Software Foundation,
19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20  *
21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22  * or visit www.oracle.com if you need additional information or have any
23  * questions.
24  */
25 
26 package jdk.editpad;
27 
28 import java.awt.BorderLayout;
29 import java.awt.FlowLayout;
30 import java.awt.Font;
31 import java.awt.event.ActionListener;
32 import java.awt.event.KeyEvent;
33 import java.awt.event.WindowAdapter;
34 import java.awt.event.WindowEvent;
35 import java.util.MissingResourceException;
36 import java.util.ResourceBundle;
37 import java.util.function.Consumer;
38 import javax.swing.JButton;
39 import javax.swing.JFrame;
40 import javax.swing.JPanel;
41 import javax.swing.JScrollPane;
42 import javax.swing.JTextArea;
43 
44 /**
45  * A minimal Swing editor as a fallback when the user does not specify an
46  * external editor.
47  */
48 class EditPad implements Runnable {
49 
50     private static final String L10N_RB_NAME  = "jdk.editpad.resources.l10n";
51     private ResourceBundle rb  = null;
52     private final String windowLabel;
53     private final Consumer<String> errorHandler;
54     private final String initialText;
55     private final Runnable closeMark;
56     private final Consumer<String> saveHandler;
57 
58     /**
59      * Create an Edit Pad minimal editor.
60      *
61      * @param windowLabel the label string for the Edit Pad window
62      * @param errorHandler a handler for unexpected errors
63      * @param initialText the source to load in the Edit Pad
64      * @param closeMark a Runnable that is run when Edit Pad closes
65      * @param saveHandler a handler for changed source (sent the full source)
66      */
EditPad(String windowLabel, Consumer<String> errorHandler, String initialText, Runnable closeMark, Consumer<String> saveHandler)67     EditPad(String windowLabel, Consumer<String> errorHandler, String initialText,
68             Runnable closeMark, Consumer<String> saveHandler) {
69         this.windowLabel = windowLabel;
70         this.errorHandler = errorHandler;
71         this.initialText = initialText;
72         this.closeMark = closeMark;
73         this.saveHandler = saveHandler;
74     }
75 
76     @Override
run()77     public void run() {
78         JFrame jframe = new JFrame(windowLabel == null
79                 ? getResourceString("editpad.name")
80                 : windowLabel);
81         Runnable closer = () -> {
82             jframe.setVisible(false);
83             jframe.dispose();
84             closeMark.run();
85         };
86         jframe.addWindowListener(new WindowAdapter() {
87             @Override
88             public void windowClosing(WindowEvent e) {
89                 closer.run();
90             }
91         });
92         jframe.setLocationRelativeTo(null);
93         jframe.setLayout(new BorderLayout());
94         JTextArea textArea = new JTextArea(initialText);
95         textArea.setFont(new Font("monospaced", Font.PLAIN, 13));
96         jframe.add(new JScrollPane(textArea), BorderLayout.CENTER);
97         jframe.add(buttons(closer, textArea), BorderLayout.SOUTH);
98 
99         jframe.setSize(800, 600);
100         jframe.setVisible(true);
101     }
102 
buttons(Runnable closer, JTextArea textArea)103     private JPanel buttons(Runnable closer, JTextArea textArea) {
104         FlowLayout flow = new FlowLayout();
105         flow.setHgap(35);
106         JPanel buttons = new JPanel(flow);
107         addButton(buttons, "editpad.cancel", KeyEvent.VK_C, e -> {
108             closer.run();
109         });
110         addButton(buttons, "editpad.accept", KeyEvent.VK_A, e -> {
111             saveHandler.accept(textArea.getText());
112         });
113         addButton(buttons, "editpad.exit",   KeyEvent.VK_X, e -> {
114             saveHandler.accept(textArea.getText());
115             closer.run();
116         });
117         return buttons;
118     }
119 
addButton(JPanel buttons, String rkey, int mnemonic, ActionListener action)120     private void addButton(JPanel buttons, String rkey, int mnemonic, ActionListener action) {
121         JButton but = new JButton(getResourceString(rkey));
122         but.setMnemonic(mnemonic);
123         buttons.add(but);
124         but.addActionListener(action);
125     }
126 
getResourceString(String key)127     private String getResourceString(String key) {
128         if (rb == null) {
129             try {
130                 rb = ResourceBundle.getBundle(L10N_RB_NAME);
131             } catch (MissingResourceException mre) {
132                 error("Cannot find ResourceBundle: %s", L10N_RB_NAME);
133                 return "";
134             }
135         }
136         String s;
137         try {
138             s = rb.getString(key);
139         } catch (MissingResourceException mre) {
140             error("Missing resource: %s in %s", key, L10N_RB_NAME);
141             return "";
142         }
143         return s;
144     }
145 
error(String fmt, Object... args)146     private void error(String fmt, Object... args) {
147         errorHandler.accept(String.format(fmt, args));
148     }
149 }
150