46 |
import java.awt.Point; |
import java.awt.Point; |
47 |
import java.awt.Rectangle; |
import java.awt.Rectangle; |
48 |
import java.awt.Shape; |
import java.awt.Shape; |
49 |
|
import java.beans.PropertyChangeEvent; |
50 |
|
import java.beans.PropertyChangeListener; |
51 |
|
|
52 |
|
import javax.swing.Action; |
53 |
|
import javax.swing.ActionMap; |
54 |
|
import javax.swing.InputMap; |
55 |
import javax.swing.JComponent; |
import javax.swing.JComponent; |
56 |
|
import javax.swing.SwingUtilities; |
57 |
|
import javax.swing.UIDefaults; |
58 |
|
import javax.swing.UIManager; |
59 |
import javax.swing.plaf.ComponentUI; |
import javax.swing.plaf.ComponentUI; |
60 |
import javax.swing.plaf.TextUI; |
import javax.swing.plaf.TextUI; |
61 |
import javax.swing.plaf.UIResource; |
import javax.swing.plaf.UIResource; |
69 |
import javax.swing.text.Element; |
import javax.swing.text.Element; |
70 |
import javax.swing.text.Highlighter; |
import javax.swing.text.Highlighter; |
71 |
import javax.swing.text.JTextComponent; |
import javax.swing.text.JTextComponent; |
72 |
|
import javax.swing.text.Keymap; |
73 |
import javax.swing.text.PlainDocument; |
import javax.swing.text.PlainDocument; |
74 |
|
import javax.swing.text.PlainView; |
75 |
import javax.swing.text.Position; |
import javax.swing.text.Position; |
76 |
import javax.swing.text.View; |
import javax.swing.text.View; |
77 |
import javax.swing.text.ViewFactory; |
import javax.swing.text.ViewFactory; |
98 |
|
|
99 |
private class RootView extends View |
private class RootView extends View |
100 |
{ |
{ |
|
private JTextComponent textComponent; |
|
101 |
private View view; |
private View view; |
102 |
|
|
103 |
public RootView(JTextComponent parent) |
public RootView() |
104 |
{ |
{ |
105 |
super(null); |
super(null); |
106 |
textComponent = parent; |
} |
107 |
|
|
108 |
|
public ViewFactory getViewFactory() |
109 |
|
{ |
110 |
|
// FIXME: Handle EditorKit somehow. |
111 |
|
return BasicTextUI.this; |
112 |
} |
} |
113 |
|
|
114 |
public void setView(View v) |
public void setView(View v) |
137 |
|
|
138 |
public void paint(Graphics g, Shape s) |
public void paint(Graphics g, Shape s) |
139 |
{ |
{ |
|
System.out.println("Michael: BasicTextUI.RootView.paint"); |
|
|
|
|
140 |
if (view != null) |
if (view != null) |
141 |
view.paint(g, s); |
view.paint(g, s); |
142 |
} |
} |
143 |
|
|
144 |
|
protected Rectangle modelToView(int position, Shape a, Position.Bias bias) |
145 |
|
throws BadLocationException |
146 |
|
{ |
147 |
|
return ((PlainView) view).modelToView(position, a, bias).getBounds(); |
148 |
|
} |
149 |
} |
} |
150 |
|
|
151 |
RootView rootView; |
class UpdateHandler implements PropertyChangeListener |
152 |
|
{ |
153 |
|
public void propertyChange(PropertyChangeEvent event) |
154 |
|
{ |
155 |
|
if (event.getPropertyName().equals("document")) |
156 |
|
{ |
157 |
|
// Document changed. |
158 |
|
modelChanged(); |
159 |
|
} |
160 |
|
} |
161 |
|
} |
162 |
|
|
163 |
|
static EditorKit kit = new DefaultEditorKit(); |
164 |
|
|
165 |
|
RootView rootView = new RootView(); |
166 |
JTextComponent textComponent; |
JTextComponent textComponent; |
167 |
int gap = 3; |
UpdateHandler updateHandler = new UpdateHandler(); |
|
EditorKit kit = new DefaultEditorKit(); |
|
168 |
|
|
169 |
public BasicTextUI() |
public BasicTextUI() |
170 |
{ |
{ |
195 |
Document doc = textComponent.getDocument(); |
Document doc = textComponent.getDocument(); |
196 |
if (doc == null) |
if (doc == null) |
197 |
{ |
{ |
198 |
doc = new PlainDocument(); |
doc = getEditorKit(textComponent).createDefaultDocument(); |
199 |
textComponent.setDocument(doc); |
textComponent.setDocument(doc); |
200 |
} |
} |
201 |
|
|
202 |
rootView = new RootView(textComponent); |
textComponent.addPropertyChangeListener(updateHandler); |
203 |
setView(create(doc.getDefaultRootElement())); |
modelChanged(); |
204 |
|
|
205 |
installDefaults(); |
installDefaults(); |
206 |
installListeners(); |
installListeners(); |
209 |
|
|
210 |
protected void installDefaults() |
protected void installDefaults() |
211 |
{ |
{ |
212 |
|
Caret caret = textComponent.getCaret(); |
213 |
|
if (caret == null) |
214 |
|
{ |
215 |
|
caret = createCaret(); |
216 |
|
textComponent.setCaret(caret); |
217 |
|
} |
218 |
|
|
219 |
|
Highlighter highlighter = textComponent.getHighlighter(); |
220 |
|
if (highlighter == null) |
221 |
|
textComponent.setHighlighter(createHighlighter()); |
222 |
|
|
223 |
|
String prefix = getPropertyPrefix(); |
224 |
|
UIDefaults defaults = UIManager.getLookAndFeelDefaults(); |
225 |
|
textComponent.setBackground(defaults.getColor(prefix + ".background")); |
226 |
|
textComponent.setForeground(defaults.getColor(prefix + ".foreground")); |
227 |
|
textComponent.setMargin(defaults.getInsets(prefix + ".margin")); |
228 |
|
textComponent.setBorder(defaults.getBorder(prefix + ".border")); |
229 |
|
textComponent.setFont(defaults.getFont(prefix + ".font")); |
230 |
|
|
231 |
|
caret.setBlinkRate(defaults.getInt(prefix + ".caretBlinkRate")); |
232 |
} |
} |
233 |
|
|
234 |
protected void installListeners() |
protected void installListeners() |
235 |
{ |
{ |
236 |
|
// Do nothing here. |
237 |
|
} |
238 |
|
|
239 |
|
protected String getKeymapName() |
240 |
|
{ |
241 |
|
return "BasicTextUI"; |
242 |
|
} |
243 |
|
|
244 |
|
protected Keymap createKeymap() |
245 |
|
{ |
246 |
|
String prefix = getPropertyPrefix(); |
247 |
|
UIDefaults defaults = UIManager.getLookAndFeelDefaults(); |
248 |
|
JTextComponent.KeyBinding[] bindings = |
249 |
|
(JTextComponent.KeyBinding[]) defaults.get(prefix + ".keyBindings"); |
250 |
|
Keymap km = JTextComponent.addKeymap(getKeymapName(), |
251 |
|
JTextComponent.getKeymap(JTextComponent.DEFAULT_KEYMAP)); |
252 |
|
JTextComponent.loadKeymap(km, bindings, textComponent.getActions()); |
253 |
|
return km; |
254 |
} |
} |
255 |
|
|
256 |
protected void installKeyboardActions() |
protected void installKeyboardActions() |
257 |
{ |
{ |
258 |
|
// load any bindings for the older Keymap interface |
259 |
|
Keymap km = JTextComponent.getKeymap(getKeymapName()); |
260 |
|
if (km == null) |
261 |
|
km = createKeymap(); |
262 |
|
textComponent.setKeymap(km); |
263 |
|
|
264 |
|
// load any bindings for the newer InputMap / ActionMap interface |
265 |
|
SwingUtilities.replaceUIInputMap(textComponent, |
266 |
|
JComponent.WHEN_FOCUSED, |
267 |
|
getInputMap(JComponent.WHEN_FOCUSED)); |
268 |
|
SwingUtilities.replaceUIActionMap(textComponent, getActionMap()); |
269 |
|
} |
270 |
|
|
271 |
|
InputMap getInputMap(int condition) |
272 |
|
{ |
273 |
|
String prefix = getPropertyPrefix(); |
274 |
|
UIDefaults defaults = UIManager.getLookAndFeelDefaults(); |
275 |
|
switch (condition) |
276 |
|
{ |
277 |
|
case JComponent.WHEN_IN_FOCUSED_WINDOW: |
278 |
|
// FIXME: is this the right string? nobody seems to use it. |
279 |
|
return (InputMap) defaults.get(prefix + ".windowInputMap"); |
280 |
|
case JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT: |
281 |
|
return (InputMap) defaults.get(prefix + ".ancestorInputMap"); |
282 |
|
default: |
283 |
|
case JComponent.WHEN_FOCUSED: |
284 |
|
return (InputMap) defaults.get(prefix + ".focusInputMap"); |
285 |
|
} |
286 |
|
} |
287 |
|
|
288 |
|
ActionMap getActionMap() |
289 |
|
{ |
290 |
|
String prefix = getPropertyPrefix(); |
291 |
|
UIDefaults defaults = UIManager.getLookAndFeelDefaults(); |
292 |
|
ActionMap am = (ActionMap) defaults.get(prefix + ".actionMap"); |
293 |
|
if (am == null) |
294 |
|
{ |
295 |
|
am = createActionMap(); |
296 |
|
defaults.put(prefix + ".actionMap", am); |
297 |
|
} |
298 |
|
return am; |
299 |
|
} |
300 |
|
|
301 |
|
ActionMap createActionMap() |
302 |
|
{ |
303 |
|
Action[] actions = textComponent.getActions(); |
304 |
|
ActionMap am = new ActionMap(); |
305 |
|
for (int i = 0; i < actions.length; ++i) |
306 |
|
{ |
307 |
|
String name = (String) actions[i].getValue(Action.NAME); |
308 |
|
if (name != null) |
309 |
|
am.put(name, actions[i]); |
310 |
|
} |
311 |
|
return am; |
312 |
} |
} |
313 |
|
|
314 |
public void uninstallUI(final JComponent c) |
public void uninstallUI(final JComponent component) |
315 |
{ |
{ |
316 |
super.uninstallUI(c); |
super.uninstallUI(component); |
317 |
rootView = null; |
rootView.setView(null); |
318 |
|
|
319 |
|
textComponent.removePropertyChangeListener(updateHandler); |
320 |
|
textComponent = null; |
321 |
|
|
322 |
uninstallDefaults(); |
uninstallDefaults(); |
323 |
uninstallListeners(); |
uninstallListeners(); |
326 |
|
|
327 |
protected void uninstallDefaults() |
protected void uninstallDefaults() |
328 |
{ |
{ |
329 |
|
// Do nothing here. |
330 |
} |
} |
331 |
|
|
332 |
protected void uninstallListeners() |
protected void uninstallListeners() |
333 |
{ |
{ |
334 |
|
// Do nothing here. |
335 |
} |
} |
336 |
|
|
337 |
protected void uninstallKeyboardActions() |
protected void uninstallKeyboardActions() |
338 |
{ |
{ |
339 |
|
// Do nothing here. |
340 |
} |
} |
341 |
|
|
342 |
protected abstract String getPropertyPrefix(); |
protected abstract String getPropertyPrefix(); |
364 |
if (textComponent.isOpaque()) |
if (textComponent.isOpaque()) |
365 |
paintBackground(g); |
paintBackground(g); |
366 |
|
|
367 |
rootView.paint(g, getVisibleEditorRect()); |
if (highlighter != null |
368 |
|
&& textComponent.getSelectionStart() != textComponent.getSelectionEnd()) |
|
if (highlighter != null) |
|
369 |
highlighter.paint(g); |
highlighter.paint(g); |
370 |
|
|
371 |
|
rootView.paint(g, getVisibleEditorRect()); |
372 |
|
|
373 |
if (caret != null) |
if (caret != null) |
374 |
caret.paint(g); |
caret.paint(g); |
375 |
} |
} |
376 |
|
|
377 |
protected void paintBackground(Graphics g) |
protected void paintBackground(Graphics g) |
378 |
{ |
{ |
379 |
g.setColor(Color.WHITE); // FIXME: set background color |
g.setColor(textComponent.getBackground()); |
380 |
g.fillRect(0, 0, textComponent.getWidth(), textComponent.getHeight()); |
g.fillRect(0, 0, textComponent.getWidth(), textComponent.getHeight()); |
381 |
} |
} |
382 |
|
|
411 |
public Rectangle modelToView(JTextComponent t, int pos) |
public Rectangle modelToView(JTextComponent t, int pos) |
412 |
throws BadLocationException |
throws BadLocationException |
413 |
{ |
{ |
414 |
return modelToView(t, pos, null); |
return modelToView(t, pos, Position.Bias.Forward); |
415 |
} |
} |
416 |
|
|
417 |
public Rectangle modelToView(JTextComponent t, int pos, Position.Bias bias) |
public Rectangle modelToView(JTextComponent t, int pos, Position.Bias bias) |
418 |
throws BadLocationException |
throws BadLocationException |
419 |
{ |
{ |
420 |
return null; |
return rootView.modelToView(pos, getVisibleEditorRect(), bias).getBounds(); |
421 |
} |
} |
422 |
|
|
423 |
public int viewToModel(JTextComponent t, Point pt) |
public int viewToModel(JTextComponent t, Point pt) |
461 |
rootView.setView(view); |
rootView.setView(view); |
462 |
view.setParent(rootView); |
view.setParent(rootView); |
463 |
} |
} |
464 |
|
|
465 |
|
protected void modelChanged() |
466 |
|
{ |
467 |
|
ViewFactory factory = rootView.getViewFactory(); |
468 |
|
Element elem = textComponent.getDocument().getDefaultRootElement(); |
469 |
|
setView(factory.create(elem)); |
470 |
|
} |
471 |
} |
} |