Code

Improve 'dirty' editor handling
[inkscape.git] / src / bind / java / org / inkscape / script / Editor.java
1 /**
2  * This is a simple mechanism to bind Inkscape to Java, and thence
3  * to all of the nice things that can be layered upon that.
4  *
5  * Authors:
6  *   Bob Jamison
7  *
8  * Copyright (C) 2007-2008 Bob Jamison
9  *
10  *  This library is free software; you can redistribute it and/or
11  *  modify it under the terms of the GNU Lesser General Public
12  *  License as published by the Free Software Foundation; either
13  *  version 3 of the License, or (at your option) any later version.
14  *
15  *  This library is distributed in the hope that it will be useful,
16  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  *  Lesser General Public License for more details.
19  *
20  *  You should have received a copy of the GNU Lesser General Public
21  *  License along with this library; if not, write to the Free Software
22  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
23  */
25 package org.inkscape.script;
28 import java.awt.BorderLayout;
29 import java.security.MessageDigest;
30 import java.security.NoSuchAlgorithmException;
31 import javax.swing.filechooser.FileNameExtensionFilter;
32 import javax.swing.JFileChooser;
33 import javax.swing.JOptionPane;
34 import javax.swing.JPanel;
35 import javax.swing.JTextPane;
37 import java.io.File;
38 import java.io.FileReader;
39 import java.io.FileWriter;
40 import java.io.IOException;
44 /**
45  * A simple script editor for quick fixes.
46  */
47 public class Editor extends JPanel
48 {
49 ScriptConsole parent;
50 JTextPane textPane;
52 //########################################################################
53 //# MESSSAGES
54 //########################################################################
55 void err(String fmt, Object... arguments)
56 {
57     parent.err("Editor err:" + fmt, arguments);
58 }
60 void msg(String fmt, Object... arguments)
61 {
62     parent.msg("Editor:" + fmt, arguments);
63 }
65 void trace(String fmt, Object... arguments)
66 {
67     parent.trace("Editor:" + fmt, arguments);
68 }
71 //########################################################################
72 //# U T I L I T Y
73 //########################################################################
75 private JFileChooser _chooser;
77 JFileChooser getChooser()
78 {
79     if (_chooser == null)
80         {
81         _chooser = new JFileChooser();
82         _chooser.setAcceptAllFileFilterUsed(false);
83         _chooser.setCurrentDirectory(new File("."));
84         FileNameExtensionFilter filter = new FileNameExtensionFilter(
85               "Script Files", "js", "py", "r");
86         _chooser.setFileFilter(filter);
87         }
88     return _chooser;
89 }
92 /**
93  * Returns the current text contained in this editor
94  */
95 public String getText()
96 {
97     return textPane.getText();
98 }
101 String lastHash = null;
103 /**
104  *  Sets the text of this editor
105  */
106 public void setText(String txt)
108     textPane.setText(txt);
109     lastHash = getHash(txt);
110     trace("hash:" + lastHash);
113 MessageDigest md = null;
115 final String hex = "0123456789abcdef";
117 String toHex(byte arr[])
119     StringBuffer buf = new StringBuffer();
120     for (byte b : arr)
121         {
122         buf.append(hex.charAt((b>>4) & 15));
123         buf.append(hex.charAt((b   ) & 15));
124                 }
125         return buf.toString();
128 String getHash(String text)
130     if (md == null)
131         {
132         try
133             {
134             md = MessageDigest.getInstance("MD5");
135                         }
136                 catch (NoSuchAlgorithmException e)
137                     {
138                     err("getHash: " + e);
139                         return "";
140                         }
141                 }
142     byte hash[] = md.digest(text.getBytes());
143     return toHex(hash);
147 //########################################################################
148 //# L O A D    /     S A V E
149 //########################################################################
150 String fileName = "";
152 /**
153  *  Gets the name of the current file in the editor
154  */
155 public String getFileName()
157     return fileName;
160 /**
161  *  Sets the name of the current file in the editor
162  */
163 public void setFileName(String val)
165     fileName = val;
168 /**
169  *  Selects and opens a file, loading into the editor
170  */
171 public boolean openFile()
173     JFileChooser chooser = getChooser();
174     int ret = chooser.showOpenDialog(this);
175     if (ret != JFileChooser.APPROVE_OPTION)
176         return false;
177     File f = chooser.getSelectedFile();
178     String fname = f.getName();
179     try
180             {
181                 FileReader in = new FileReader(fname);
182         StringBuffer buf = new StringBuffer();
183         while (true)
184             {
185             int ch = in.read();
186             if (ch < 0)
187                 break;
188             buf.append((char)ch);
189             }
190         in.close();
191         setText(buf.toString());
192         }
193     catch (IOException e)
194         {
195         err("save file:" + e);
196         return false;
197                 }
198     return true;
202 /**
203  *  Saves the file currently in the editor.  Uses the Save
204  *  selector if there is not current file name. 
205  */ 
206 public boolean saveFile()
208     if (!isDirty())
209         return true;
211     String fname = getFileName();
212     if (fname == null || fname.length()==0)
213         {
214         JFileChooser chooser = getChooser();
215         int ret = chooser.showSaveDialog(this);
216         if (ret != JFileChooser.APPROVE_OPTION)
217             return false;
218         File f = chooser.getSelectedFile();
219         fname = f.getName();
220         }
221     try
222             {
223                 FileWriter out = new FileWriter(fname);
224         out.write(getText());
225         out.close();
226         setFileName(fname);
227         resetDirty();
228         }
229     catch (IOException e)
230         {
231         err("save file:" + e);
232         return false;
233                 }
234     return true;
238 /**
239  *  Saves the file currently in the editor under a new name.
240  *  Get the new name from the chooser, and see if it already exists. 
241  */ 
242 public boolean saveAsFile()
244     JFileChooser chooser = getChooser();
245     int ret = chooser.showSaveDialog(this);
246     if (ret != JFileChooser.APPROVE_OPTION)
247         return false;
248     File f = chooser.getSelectedFile();
249     String fname = f.getName();
250     if (f.exists())
251         {
252         ret = JOptionPane.showConfirmDialog(this,
253                               "File '" + fname + "' already exists.  Overwrite?");
254                 if (ret != JOptionPane.YES_OPTION)
255                     return false;
256                 }
257     try
258             {
259                 FileWriter out = new FileWriter(fname);
260         out.write(getText());
261         out.close();
262         setFileName(fname);
263         resetDirty();
264         }
265     catch (IOException e)
266         {
267         err("saveAs file:" + e);
268         return false;
269                 }
270     return true;
274 /**
275  * State that the editor is now 'unedited'
276  */
277 public void resetDirty()
279     lastHash = getHash(getText());
282 /**
283  * Determines if the editor has been edited since the last open/save
284  */
285 public boolean isDirty()
287     String txt = getText();
288     String hash = getHash(txt);
289     if ( (lastHash == null && txt.length()>0) ||
290              (lastHash != null && !lastHash.equals(hash)) )
291         return true;
292     return false;
296 /**
297  * Creates the editor for the ScriptConsole
298  */
299 public Editor(ScriptConsole par)
301     super();
302     parent = par;
303     setLayout(new BorderLayout());
304     textPane = new JTextPane();
305     add(textPane, BorderLayout.CENTER);