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