001: /*
002: * Copyright 2001-2006 C:1 Financial Services GmbH
003: *
004: * This software is free software; you can redistribute it and/or
005: * modify it under the terms of the GNU Lesser General Public
006: * License Version 2.1, as published by the Free Software Foundation.
007: *
008: * This software is distributed in the hope that it will be useful,
009: * but WITHOUT ANY WARRANTY; without even the implied warranty of
010: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
011: * Lesser General Public License for more details.
012: *
013: * You should have received a copy of the GNU Lesser General Public
014: * License along with this library; if not, write to the Free Software
015: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
016: */
017:
018: package de.finix.contelligent.client.gui;
019:
020: import java.io.BufferedReader;
021: import java.io.File;
022: import java.io.FileReader;
023: import java.io.FileWriter;
024: import java.io.IOException;
025: import java.util.ArrayList;
026: import java.util.List;
027: import java.util.StringTokenizer;
028: import java.util.prefs.Preferences;
029:
030: import javax.swing.JOptionPane;
031:
032: import de.finix.contelligent.client.base.ContelligentConstants;
033: import de.finix.contelligent.client.event.ContelligentEvent;
034: import de.finix.contelligent.client.i18n.Resources;
035: import de.finix.contelligent.client.modules.preferences.PreferencesModule;
036: import de.finix.contelligent.client.util.ExceptionDialog;
037:
038: public abstract class AbstractComponentEditorWithExternal extends
039: AbstractComponentResourceEditor implements ComponentEditor {
040:
041: private LaunchEditor launchEditor = null;
042:
043: protected abstract String getType();
044:
045: protected abstract void notifyEditingFinished(String text,
046: boolean successful);
047:
048: protected abstract String decodeTextFromExternalEditing(String text);
049:
050: protected abstract String encodeTextForExternalEditing(String text);
051:
052: private class LaunchEditor implements Runnable {
053:
054: File tmpfile = null;
055:
056: Process process = null;
057:
058: String text;
059:
060: boolean editInProgress = false;
061:
062: boolean editSuccessful = false;
063:
064: public LaunchEditor(String text) {
065: setText(text);
066: }
067:
068: public String getText() {
069: return text;
070: }
071:
072: public void setText(String text) {
073: this .text = encodeTextForExternalEditing(text);
074: }
075:
076: public void run() {
077: editInProgress = true;
078: editSuccessful = false;
079:
080: try {
081: saveTmpFile();
082: execExternalEditor();
083: loadTmpFile();
084: deleteFile();
085: editSuccessful = true;
086: } catch (IOException e) {
087: ExceptionDialog.show(e);
088: } catch (InterruptedException e) {
089: ExceptionDialog.show(e);
090: } finally {
091: editInProgress = false;
092: // setEditable(true);
093: notifyEditingFinished(text, editSuccessful);
094: }
095: }
096:
097: public void saveTmpFile() throws IOException {
098: tmpfile = File.createTempFile(
099: ContelligentConstants.TMP_FILE_PREFIX,
100: ContelligentConstants.TMP_FILE_SUFFIX);
101: FileWriter fileWriter = new FileWriter(tmpfile);
102: fileWriter.write(text);
103: fileWriter.close();
104: }
105:
106: public void loadTmpFile() throws IOException {
107: BufferedReader in = new BufferedReader(new FileReader(
108: tmpfile));
109: StringBuffer buffer = new StringBuffer(4096);
110: String line;
111: while ((line = in.readLine()) != null) {
112: buffer.append(line).append("\n");
113: }
114: in.close();
115: text = decodeTextFromExternalEditing(buffer.toString());
116: }
117:
118: public void execExternalEditor() throws IOException,
119: InterruptedException {
120: Preferences applicationPreferences = PreferencesModule
121: .getApplicationPreferences();
122: String editor = applicationPreferences.get(getType(), null);
123:
124: // we need tokenizer due to parameters
125: StringTokenizer tokenizer = new StringTokenizer(editor);
126: List<String> command = new ArrayList<String>();
127: while (tokenizer.hasMoreTokens()) {
128: command.add(tokenizer.nextToken());
129: }
130: command.add(tmpfile.getCanonicalPath());
131:
132: process = Runtime.getRuntime().exec(
133: (String[]) command.toArray(new String[0]));
134: process.waitFor();
135: }
136:
137: // XXX: does not do anything to make external editing possible
138: // even when blocking wait for process does not (with Windows)
139: public void deleteFile() {
140: /*
141: * try { tmpfile.delete(); } catch (Exception ignored) { }
142: */
143: }
144:
145: public void destroy() {
146: if (process != null) {
147: process.destroy();
148: }
149: }
150: }
151:
152: protected void cancelExternalEdit() {
153: if (launchEditor != null) {
154: launchEditor.destroy();
155: launchEditor.deleteFile();
156: launchEditor = null;
157: }
158: }
159:
160: protected void updateFromExternalEdit() {
161: if (launchEditor != null) {
162: try {
163: launchEditor.loadTmpFile();
164: } catch (IOException e) {
165: ExceptionDialog.show(e);
166: } finally {
167: notifyEditingFinished(launchEditor.text, true);
168: }
169: }
170: }
171:
172: protected void forceCommitExternalEdit() {
173: if (launchEditor != null) {
174: try {
175: launchEditor.loadTmpFile();
176: launchEditor.editSuccessful = true;
177: launchEditor.destroy();
178: } catch (IOException e) {
179: ExceptionDialog.show(e);
180: } finally {
181: // setEditable(true);
182: notifyEditingFinished(launchEditor.text,
183: launchEditor.editSuccessful);
184: launchEditor = null;
185: }
186: }
187: }
188:
189: protected void startExternalEdit(String text) {
190: // setEditable(false);
191: cancelExternalEdit();
192: launchEditor = new LaunchEditor(text);
193: new Thread(launchEditor).start();
194: }
195:
196: // overloads method in AbstractComponentRenderer
197: protected void componentChanged(ContelligentEvent event) {
198: if (launchEditor != null && launchEditor.editInProgress) {
199: if (JOptionPane
200: .showConfirmDialog(
201: null,
202: Resources
203: .getLocalString("close_external_editor_component_changed"),
204: Resources
205: .getLocalString("external_edit_in_progress_component_changed"),
206: JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION) {
207: cancelExternalEdit();
208: update();
209: }
210: } else {
211: update();
212: }
213: }
214:
215: public void rollback() {
216: /*
217: * if (launchEditor != null && launchEditor.editInProgress) { if
218: * (JOptionPane.showConfirmDialog(null,
219: * Resources.getLocalString("close_external_editor_rollback"),
220: * Resources.getLocalString("external_edit_in_progress"),
221: * JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION) {
222: * cancelExternalEdit(); super.rollback(); } } else {
223: */
224: cancelExternalEdit();
225: super .rollback();
226: // }
227: }
228:
229: public void commit() {
230: /*
231: * // wait until user will close the editor if (launchEditor != null &&
232: * launchEditor.editInProgress) { if
233: * (JOptionPane.showConfirmDialog(null,
234: * Resources.getLocalString("close_external_editor"),
235: * Resources.getLocalString("external_edit_in_progress"),
236: * JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION) {
237: * super.commit(); cancelExternalEdit(); } } else {
238: */
239: forceCommitExternalEdit();
240: super .commit();
241: // }
242: }
243:
244: }
|