~ubuntu-branches/ubuntu/trusty/libswingx-java/trusty

« back to all changes in this revision

Viewing changes to swingx-core/src/main/java/org/jdesktop/swingx/plaf/PromptTextUI.java

  • Committer: Bazaar Package Importer
  • Author(s): Damien Raude-Morvan
  • Date: 2011-03-06 00:28:45 UTC
  • mfrom: (4.1.5 sid)
  • Revision ID: james.westby@ubuntu.com-20110306002845-escned3cbqp5qx0t
Tags: 1:1.6.2-1
* New upstream release.
* Switch to maven as build system:
  - d/control: drop ant, add maven-debian-helper
  - d/rules: use maven.mk
* d/patches/pom.diff: drop, uneeded since upstream fixed its dependencies.
* d/watch: update to use java.net directly.
* d/rules: force debian version for JARs (Closes: #603495).
* d/copyright: Update to lastest DEP-5 r166.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
package org.jdesktop.swingx.plaf;
 
2
 
 
3
import static javax.swing.BorderFactory.createEmptyBorder;
 
4
 
 
5
import java.awt.Dimension;
 
6
import java.awt.Graphics;
 
7
import java.awt.Graphics2D;
 
8
import java.awt.Insets;
 
9
import java.awt.Point;
 
10
import java.awt.Rectangle;
 
11
import java.awt.TextComponent;
 
12
import java.awt.Component.BaselineResizeBehavior;
 
13
import java.awt.event.FocusAdapter;
 
14
import java.awt.event.FocusEvent;
 
15
import java.lang.reflect.Method;
 
16
 
 
17
import javax.accessibility.Accessible;
 
18
import javax.swing.JComponent;
 
19
import javax.swing.border.Border;
 
20
import javax.swing.plaf.ComponentUI;
 
21
import javax.swing.plaf.TextUI;
 
22
import javax.swing.text.BadLocationException;
 
23
import javax.swing.text.Caret;
 
24
import javax.swing.text.EditorKit;
 
25
import javax.swing.text.Highlighter;
 
26
import javax.swing.text.JTextComponent;
 
27
import javax.swing.text.Position;
 
28
import javax.swing.text.View;
 
29
import javax.swing.text.DefaultHighlighter.DefaultHighlightPainter;
 
30
import javax.swing.text.Position.Bias;
 
31
 
 
32
import org.jdesktop.swingx.painter.Painter;
 
33
import org.jdesktop.swingx.prompt.PromptSupport;
 
34
import org.jdesktop.swingx.prompt.PromptSupport.FocusBehavior;
 
35
 
 
36
/**
 
37
 * <p>
 
38
 * Abstract {@link TextUI} class that delegates most work to another
 
39
 * {@link TextUI} and additionally renders a prompt text as specified in the
 
40
 * {@link JTextComponent}s client properties by {@link PromptSupport}.
 
41
 * <p>
 
42
 * Subclasses of this class must provide a prompt component used for rendering
 
43
 * the prompt text.
 
44
 * </p>
 
45
 * 
 
46
 * @author Peter Weishapl <petw@gmx.net>
 
47
 * 
 
48
 */
 
49
public abstract class PromptTextUI extends TextUI {
 
50
    protected class PainterHighlighter implements Highlighter {
 
51
        private final Painter painter;
 
52
 
 
53
        private JTextComponent c;
 
54
 
 
55
        public PainterHighlighter(Painter painter) {
 
56
            this.painter = painter;
 
57
        }
 
58
 
 
59
        /**
 
60
         * {@inheritDoc}
 
61
         */
 
62
        public Object addHighlight(int p0, int p1, HighlightPainter p)
 
63
                throws BadLocationException {
 
64
            return new Object();
 
65
        }
 
66
 
 
67
        /**
 
68
         * {@inheritDoc}
 
69
         */
 
70
        public void changeHighlight(Object tag, int p0, int p1)
 
71
                throws BadLocationException {
 
72
 
 
73
        }
 
74
 
 
75
        /**
 
76
         * {@inheritDoc}
 
77
         */
 
78
        public void deinstall(JTextComponent c) {
 
79
            c = null;
 
80
        }
 
81
 
 
82
        /**
 
83
         * {@inheritDoc}
 
84
         */
 
85
        public Highlight[] getHighlights() {
 
86
            return null;
 
87
        }
 
88
 
 
89
        /**
 
90
         * {@inheritDoc}
 
91
         */
 
92
        public void install(JTextComponent c) {
 
93
            this.c = c;
 
94
        }
 
95
 
 
96
        /**
 
97
         * {@inheritDoc}
 
98
         */
 
99
        public void paint(Graphics g) {
 
100
            Graphics2D g2d = (Graphics2D) g.create();
 
101
 
 
102
            try {
 
103
                painter.paint(g2d, c, c.getWidth(), c.getHeight());
 
104
            } finally {
 
105
                g2d.dispose();
 
106
            }
 
107
        }
 
108
 
 
109
        /**
 
110
         * {@inheritDoc}
 
111
         */
 
112
        public void removeAllHighlights() {
 
113
            // TODO Auto-generated method stub
 
114
 
 
115
        }
 
116
 
 
117
        /**
 
118
         * {@inheritDoc}
 
119
         */
 
120
        public void removeHighlight(Object tag) {
 
121
            // TODO Auto-generated method stub
 
122
 
 
123
        }
 
124
    }
 
125
 
 
126
    static final FocusHandler focusHandler = new FocusHandler();
 
127
 
 
128
    /**
 
129
     * Delegate the hard work to this object.
 
130
     */
 
131
    protected final TextUI delegate;
 
132
 
 
133
    /**
 
134
     * This component ist painted when rendering the prompt text.
 
135
     */
 
136
    protected JTextComponent promptComponent;
 
137
 
 
138
    /**
 
139
     * Creates a new {@link PromptTextUI} which delegates most work to another
 
140
     * {@link TextUI}.
 
141
     * 
 
142
     * @param delegate
 
143
     */
 
144
    public PromptTextUI(TextUI delegate) {
 
145
        this.delegate = delegate;
 
146
    }
 
147
 
 
148
    /**
 
149
     * Creates a component which should be used to render the prompt text.
 
150
     * 
 
151
     * @return
 
152
     */
 
153
    protected abstract JTextComponent createPromptComponent();
 
154
 
 
155
    /**
 
156
     * Calls TextUI#installUI(JComponent) on the delegate and installs a focus
 
157
     * listener on <code>c</code> which repaints the component when it gains or
 
158
     * loses the focus.
 
159
     */
 
160
    @Override
 
161
    public void installUI(JComponent c) {
 
162
        delegate.installUI(c);
 
163
 
 
164
        JTextComponent txt = (JTextComponent) c;
 
165
 
 
166
        // repaint to correctly highlight text if FocusBehavior is
 
167
        // HIGHLIGHT_LABEL in Metal and Windows LnF
 
168
        txt.addFocusListener(focusHandler);
 
169
    }
 
170
 
 
171
    /**
 
172
     * Delegates, then uninstalls the focus listener.
 
173
     */
 
174
    @Override
 
175
    public void uninstallUI(JComponent c) {
 
176
        delegate.uninstallUI(c);
 
177
        c.removeFocusListener(focusHandler);
 
178
        promptComponent = null;
 
179
    }
 
180
 
 
181
    /**
 
182
     * Creates a label component, if none has already been created. Sets the
 
183
     * prompt components properties to reflect the given {@link JTextComponent}s
 
184
     * properties and returns it.
 
185
     * 
 
186
     * @param txt
 
187
     * @return the adjusted prompt component
 
188
     */
 
189
    public JTextComponent getPromptComponent(JTextComponent txt) {
 
190
        if (promptComponent == null) {
 
191
            promptComponent = createPromptComponent();
 
192
        }
 
193
        if (txt.isFocusOwner()
 
194
                && PromptSupport.getFocusBehavior(txt) == FocusBehavior.HIDE_PROMPT) {
 
195
            promptComponent.setText(null);
 
196
        } else {
 
197
            promptComponent.setText(PromptSupport.getPrompt(txt));
 
198
        }
 
199
 
 
200
        promptComponent.getHighlighter().removeAllHighlights();
 
201
        if (txt.isFocusOwner()
 
202
                && PromptSupport.getFocusBehavior(txt) == FocusBehavior.HIGHLIGHT_PROMPT) {
 
203
            promptComponent.setForeground(txt.getSelectedTextColor());
 
204
            try {
 
205
                promptComponent.getHighlighter().addHighlight(0,
 
206
                        promptComponent.getText().length(),
 
207
                        new DefaultHighlightPainter(txt.getSelectionColor()));
 
208
            } catch (BadLocationException e) {
 
209
                e.printStackTrace();
 
210
            }
 
211
        } else {
 
212
            promptComponent.setForeground(PromptSupport.getForeground(txt));
 
213
        }
 
214
 
 
215
        if (PromptSupport.getFontStyle(txt) == null) {
 
216
            promptComponent.setFont(txt.getFont());
 
217
        } else {
 
218
            promptComponent.setFont(txt.getFont().deriveFont(
 
219
                    PromptSupport.getFontStyle(txt)));
 
220
        }
 
221
 
 
222
        promptComponent.setBackground(PromptSupport.getBackground(txt));
 
223
        promptComponent.setHighlighter(new PainterHighlighter(PromptSupport
 
224
                .getBackgroundPainter(txt)));
 
225
        promptComponent.setEnabled(txt.isEnabled());
 
226
        promptComponent.setOpaque(txt.isOpaque());
 
227
        promptComponent.setBounds(txt.getBounds());
 
228
        Border b = txt.getBorder();
 
229
        
 
230
        if (b == null) {
 
231
            promptComponent.setBorder(txt.getBorder());
 
232
        } else {
 
233
            Insets insets = b.getBorderInsets(txt);
 
234
            promptComponent.setBorder(
 
235
                    createEmptyBorder(insets.top, insets.left, insets.bottom, insets.right));
 
236
        }
 
237
        
 
238
        promptComponent.setSelectedTextColor(txt.getSelectedTextColor());
 
239
        promptComponent.setSelectionColor(txt.getSelectionColor());
 
240
        promptComponent.setEditable(txt.isEditable());
 
241
        promptComponent.setMargin(txt.getMargin());
 
242
 
 
243
        return promptComponent;
 
244
    }
 
245
 
 
246
    /**
 
247
     * When {@link #shouldPaintPrompt(JTextComponent)} returns true, the prompt
 
248
     * component is retrieved by calling
 
249
     * {@link #getPromptComponent(JTextComponent)} and it's preferred size is
 
250
     * returned. Otherwise super{@link #getPreferredSize(JComponent)} is called.
 
251
     */
 
252
    @Override
 
253
    public Dimension getPreferredSize(JComponent c) {
 
254
        JTextComponent txt = (JTextComponent) c;
 
255
        if (shouldPaintPrompt(txt)) {
 
256
            return getPromptComponent(txt).getPreferredSize();
 
257
        }
 
258
        return delegate.getPreferredSize(c);
 
259
    }
 
260
 
 
261
    /**
 
262
     * Delegates painting when {@link #shouldPaintPrompt(JTextComponent)}
 
263
     * returns false. Otherwise the prompt component is retrieved by calling
 
264
     * {@link #getPromptComponent(JTextComponent)} and painted. Then the caret
 
265
     * of the given text component is painted.
 
266
     */
 
267
    @Override
 
268
    public void paint(Graphics g, final JComponent c) {
 
269
        JTextComponent txt = (JTextComponent) c;
 
270
 
 
271
        if (shouldPaintPrompt(txt)) {
 
272
            paintPromptComponent(g, txt);
 
273
        } else {
 
274
            delegate.paint(g, c);
 
275
        }
 
276
    }
 
277
 
 
278
    protected void paintPromptComponent(Graphics g, JTextComponent txt) {
 
279
        JTextComponent lbl = getPromptComponent(txt);
 
280
        lbl.paint(g);
 
281
 
 
282
        if (txt.getCaret() != null) {
 
283
            txt.getCaret().paint(g);
 
284
        }
 
285
    }
 
286
 
 
287
    /**
 
288
     * Returns if the prompt or the text field should be painted, depending on
 
289
     * the state of <code>txt</code>.
 
290
     * 
 
291
     * @param txt
 
292
     * @return true when <code>txt</code> contains not text, otherwise false
 
293
     */
 
294
    public boolean shouldPaintPrompt(JTextComponent txt) {
 
295
        return txt.getText() == null || txt.getText().length() == 0;
 
296
    }
 
297
 
 
298
    /**
 
299
     * Calls super.{@link #update(Graphics, JComponent)}, which in turn calls
 
300
     * the paint method of this object.
 
301
     */
 
302
    @Override
 
303
    public void update(Graphics g, JComponent c) {
 
304
        super.update(g, c);
 
305
    }
 
306
 
 
307
    /**
 
308
     * Delegate when {@link #shouldPaintPrompt(JTextComponent)} returns false.
 
309
     * Otherwise get the prompt component's UI and delegate to it. This ensures
 
310
     * that the {@link Caret} is painted on the correct position (this is
 
311
     * important when the text is centered, so that the caret will not be
 
312
     * painted inside the label text)
 
313
     */
 
314
    @Override
 
315
    public Rectangle modelToView(JTextComponent t, int pos, Bias bias)
 
316
            throws BadLocationException {
 
317
        if (shouldPaintPrompt(t)) {
 
318
            return getPromptComponent(t).getUI().modelToView(t, pos, bias);
 
319
        } else {
 
320
            return delegate.modelToView(t, pos, bias);
 
321
        }
 
322
    }
 
323
 
 
324
    /**
 
325
     * Calls {@link #modelToView(JTextComponent, int, Bias)} with
 
326
     * {@link Bias#Forward}.
 
327
     */
 
328
    @Override
 
329
    public Rectangle modelToView(JTextComponent t, int pos)
 
330
            throws BadLocationException {
 
331
        return modelToView(t, pos, Position.Bias.Forward);
 
332
    }
 
333
 
 
334
    // ********************* Delegate methods *************************///
 
335
    // ****************************************************************///
 
336
 
 
337
    @Override
 
338
    public boolean contains(JComponent c, int x, int y) {
 
339
        return delegate.contains(c, x, y);
 
340
    }
 
341
 
 
342
    @Override
 
343
    public void damageRange(JTextComponent t, int p0, int p1, Bias firstBias,
 
344
            Bias secondBias) {
 
345
        delegate.damageRange(t, p0, p1, firstBias, secondBias);
 
346
    }
 
347
 
 
348
    @Override
 
349
    public void damageRange(JTextComponent t, int p0, int p1) {
 
350
        delegate.damageRange(t, p0, p1);
 
351
    }
 
352
 
 
353
    @Override
 
354
    public boolean equals(Object obj) {
 
355
        return delegate.equals(obj);
 
356
    }
 
357
 
 
358
    @Override
 
359
    public Accessible getAccessibleChild(JComponent c, int i) {
 
360
        return delegate.getAccessibleChild(c, i);
 
361
    }
 
362
 
 
363
    @Override
 
364
    public int getAccessibleChildrenCount(JComponent c) {
 
365
        return delegate.getAccessibleChildrenCount(c);
 
366
    }
 
367
 
 
368
    @Override
 
369
    public EditorKit getEditorKit(JTextComponent t) {
 
370
        return delegate.getEditorKit(t);
 
371
    }
 
372
 
 
373
    @Override
 
374
    public Dimension getMaximumSize(JComponent c) {
 
375
        return delegate.getMaximumSize(c);
 
376
    }
 
377
 
 
378
    @Override
 
379
    public Dimension getMinimumSize(JComponent c) {
 
380
        return delegate.getMinimumSize(c);
 
381
    }
 
382
 
 
383
    @Override
 
384
    public int getNextVisualPositionFrom(JTextComponent t, int pos, Bias b,
 
385
            int direction, Bias[] biasRet) throws BadLocationException {
 
386
        return delegate
 
387
                .getNextVisualPositionFrom(t, pos, b, direction, biasRet);
 
388
    }
 
389
 
 
390
    @Override
 
391
    public View getRootView(JTextComponent t) {
 
392
        return delegate.getRootView(t);
 
393
    }
 
394
 
 
395
    @Override
 
396
    public String getToolTipText(JTextComponent t, Point pt) {
 
397
        return delegate.getToolTipText(t, pt);
 
398
    }
 
399
 
 
400
    @Override
 
401
    public int hashCode() {
 
402
        return delegate.hashCode();
 
403
    }
 
404
 
 
405
    @Override
 
406
    public String toString() {
 
407
        return String.format("%s (%s)", getClass().getName(), delegate
 
408
                .toString());
 
409
    }
 
410
 
 
411
    @Override
 
412
    public int viewToModel(JTextComponent t, Point pt, Bias[] biasReturn) {
 
413
        return delegate.viewToModel(t, pt, biasReturn);
 
414
    }
 
415
 
 
416
    @Override
 
417
    public int viewToModel(JTextComponent t, Point pt) {
 
418
        return delegate.viewToModel(t, pt);
 
419
    }
 
420
 
 
421
    /**
 
422
     * Tries to call {@link ComponentUI#getBaseline(int, int)} on the delegate
 
423
     * via Reflection. Workaround to maintain compatibility with Java 5. Ideally
 
424
     * we should also override {@link #getBaselineResizeBehavior(JComponent)},
 
425
     * but that's impossible since the {@link BaselineResizeBehavior} class,
 
426
     * which does not exist in Java 5, is involved.
 
427
     * 
 
428
     * @return the baseline, or -2 if <code>getBaseline</code> could not be
 
429
     *         invoked on the delegate.
 
430
     */
 
431
    @Override
 
432
    public int getBaseline(JComponent c, int width, int height) {
 
433
        try {
 
434
            Method m = delegate.getClass().getMethod("getBaseline",
 
435
                    JComponent.class, int.class, int.class);
 
436
            Object o = m.invoke(delegate, new Object[] { c, width, height });
 
437
            return (Integer) o;
 
438
        } catch (Exception ex) {
 
439
            // ignore
 
440
            return -2;
 
441
        }
 
442
    }
 
443
 
 
444
    /**
 
445
     * Repaint the {@link TextComponent} when it loses or gains the focus.
 
446
     */
 
447
    private static final class FocusHandler extends FocusAdapter {
 
448
        @Override
 
449
        public void focusGained(FocusEvent e) {
 
450
            e.getComponent().repaint();
 
451
        }
 
452
 
 
453
        @Override
 
454
        public void focusLost(FocusEvent e) {
 
455
            e.getComponent().repaint();
 
456
        }
 
457
    }
 
458
}
 
 
b'\\ No newline at end of file'