Source code: com/virtuosotechnologies/asaph/standardgui/StringUpdater.java
1 /*
2 ================================================================================
3
4 FILE: StringUpdater.java
5
6 PROJECT:
7
8 Asaph
9
10 CONTENTS:
11
12 Something that keeps a SimpleString and a text field synched.
13
14 PROGRAMMERS:
15
16 Daniel Azuma (DA) <dazuma@kagi.com>
17
18 COPYRIGHT:
19
20 Copyright (C) 2003 Daniel Azuma (dazuma@kagi.com)
21
22 This program is free software; you can redistribute it and/or
23 modify it under the terms of the GNU General Public License as
24 published by the Free Software Foundation; either version 2
25 of the License, or (at your option) any later version.
26
27 This program is distributed in the hope that it will be useful,
28 but WITHOUT ANY WARRANTY; without even the implied warranty of
29 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30 GNU General Public License for more details.
31
32 You should have received a copy of the GNU General Public
33 License along with this program; if not, write to
34 Free Software Foundation, Inc.
35 59 Temple Place, Suite 330
36 Boston, MA 02111-1307 USA
37
38 ================================================================================
39 */
40
41
42 package com.virtuosotechnologies.asaph.standardgui;
43
44
45 import java.awt.event.FocusListener;
46 import java.awt.event.FocusEvent;
47 import java.awt.event.ActionListener;
48 import java.awt.event.ActionEvent;
49 import javax.swing.JTextField;
50 import javax.swing.undo.UndoableEdit;
51 import javax.swing.undo.AbstractUndoableEdit;
52 import javax.swing.undo.CannotUndoException;
53 import javax.swing.undo.CannotRedoException;
54 import javax.swing.event.UndoableEditListener;
55 import javax.swing.event.UndoableEditEvent;
56 import javax.swing.event.CaretListener;
57 import javax.swing.event.CaretEvent;
58 import javax.swing.text.JTextComponent;
59
60 import com.virtuosotechnologies.asaph.model.SimpleString;
61 import com.virtuosotechnologies.asaph.model.StringList;
62 import com.virtuosotechnologies.asaph.modelutils.SongUtils;
63
64
65 /**
66 * Something that keeps a SimpleString and a text field synched.
67 */
68 /*package*/ class StringUpdater
69 implements
70 FocusListener,
71 ActionListener,
72 UndoableEditListener,
73 CaretListener
74 {
75 private static StringUpdater currentUpdater_ = null;
76
77 private JTextComponent field_;
78 private SimpleString model_;
79 private StringList listModel_;
80 private SongUtils songUtils_;
81 private SongEditor editor_;
82 private UndoableEditListener undoListener_;
83 private InternalListener internalListener_;
84 private boolean fieldDirty_;
85
86
87 /*package*/ static void install(
88 JTextComponent field,
89 SimpleString model,
90 SongEditor editor,
91 UndoableEditListener listener)
92 {
93 StringUpdater updater = new StringUpdater(field, model, editor, listener);
94 field.addFocusListener(updater);
95 if (field instanceof JTextField)
96 {
97 ((JTextField)field).addActionListener(updater);
98 }
99 field.getDocument().addUndoableEditListener(updater);
100 }
101
102
103 /*package*/ static void install(
104 JTextComponent field,
105 StringList model,
106 SongUtils songUtils,
107 SongEditor editor,
108 UndoableEditListener listener)
109 {
110 StringUpdater updater = new StringUpdater(field, model, songUtils, editor, listener);
111 field.addFocusListener(updater);
112 if (field instanceof JTextField)
113 {
114 ((JTextField)field).addActionListener(updater);
115 }
116 field.getDocument().addUndoableEditListener(updater);
117 }
118
119
120 private StringUpdater(
121 JTextComponent field,
122 SimpleString model,
123 SongEditor editor,
124 UndoableEditListener listener)
125 {
126 field_ = field;
127 model_ = model;
128 editor_ = editor;
129 undoListener_ = listener;
130 internalListener_ = new InternalListener();
131 fieldDirty_ = false;
132 }
133
134
135 private StringUpdater(
136 JTextComponent field,
137 StringList model,
138 SongUtils songUtils,
139 SongEditor editor,
140 UndoableEditListener listener)
141 {
142 field_ = field;
143 listModel_ = model;
144 songUtils_ = songUtils;
145 editor_ = editor;
146 undoListener_ = listener;
147 internalListener_ = new InternalListener();
148 fieldDirty_ = false;
149 }
150
151
152 public void actionPerformed(
153 ActionEvent ev)
154 {
155 field_.transferFocus();
156 }
157
158
159 public void undoableEditHappened(
160 UndoableEditEvent ev)
161 {
162 editor_.markDirty();
163 fieldDirty_ = true;
164 }
165
166
167 public void focusGained(
168 FocusEvent ev)
169 {
170 if (!ev.isTemporary() && currentUpdater_ != this)
171 {
172 currentUpdater_ = this;
173 field_.addCaretListener(this);
174 if (field_.getSelectionStart() == field_.getSelectionEnd())
175 {
176 editor_.updateFieldClipboardMenus(1);
177 }
178 else
179 {
180 editor_.updateFieldClipboardMenus(2);
181 }
182 }
183 }
184
185
186 public void focusLost(
187 FocusEvent ev)
188 {
189 commit();
190 if (!ev.isTemporary() && currentUpdater_ == this)
191 {
192 currentUpdater_ = null;
193 field_.removeCaretListener(this);
194 editor_.updateFieldClipboardMenus(0);
195 }
196 }
197
198
199 public void caretUpdate(
200 CaretEvent ev)
201 {
202 if (currentUpdater_ == this)
203 {
204 if (field_.getSelectionStart() == field_.getSelectionEnd())
205 {
206 editor_.updateFieldClipboardMenus(1);
207 }
208 else
209 {
210 editor_.updateFieldClipboardMenus(2);
211 }
212 }
213 }
214
215
216 private void commit()
217 {
218 if (fieldDirty_)
219 {
220 if (model_ != null)
221 {
222 model_.setString(field_.getText(), internalListener_);
223 }
224 else
225 {
226 songUtils_.setMultiLineString(listModel_, field_.getText(),
227 internalListener_);
228 }
229 fieldDirty_ = false;
230 }
231 }
232
233
234 /*package*/ static void commitCurrent()
235 {
236 if (currentUpdater_ != null)
237 {
238 currentUpdater_.commit();
239 }
240 }
241
242
243 /*package*/ static void cutCurrent()
244 {
245 if (currentUpdater_ != null)
246 {
247 currentUpdater_.field_.cut();
248 }
249 }
250
251
252 /*package*/ static void copyCurrent()
253 {
254 if (currentUpdater_ != null)
255 {
256 currentUpdater_.field_.copy();
257 }
258 }
259
260
261 /*package*/ static void pasteCurrent()
262 {
263 if (currentUpdater_ != null)
264 {
265 currentUpdater_.field_.paste();
266 }
267 }
268
269
270 /*package*/ static void deleteCurrent()
271 {
272 if (currentUpdater_ != null)
273 {
274 currentUpdater_.field_.replaceSelection("");
275 }
276 }
277
278
279 private class InternalListener
280 implements UndoableEditListener
281 {
282 public void undoableEditHappened(
283 UndoableEditEvent ev)
284 {
285 final UndoableEdit delegate = ev.getEdit();
286
287 undoListener_.undoableEditHappened(new UndoableEditEvent(
288 ev.getSource(),
289 new AbstractUndoableEdit()
290 {
291 public void undo()
292 throws CannotUndoException
293 {
294 super.undo();
295 delegate.undo();
296 if (model_ != null)
297 {
298 field_.setText(model_.getString());
299 }
300 else
301 {
302 field_.setText(songUtils_.getMultiLineString(listModel_));
303 }
304 fieldDirty_ = false;
305 }
306
307 public void redo()
308 throws CannotRedoException
309 {
310 super.redo();
311 delegate.redo();
312 if (model_ != null)
313 {
314 field_.setText(model_.getString());
315 }
316 else
317 {
318 field_.setText(songUtils_.getMultiLineString(listModel_));
319 }
320 fieldDirty_ = false;
321 }
322 }));
323 }
324 }
325 }