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

« back to all changes in this revision

Viewing changes to src/java/org/jdesktop/swingx/plaf/basic/BasicHeaderUI.java

  • Committer: Bazaar Package Importer
  • Author(s): Torsten Werner
  • Date: 2008-03-08 16:18:24 UTC
  • Revision ID: james.westby@ubuntu.com-20080308161824-wsahvl9pwzjcea3g
Tags: upstream-0.9.2
ImportĀ upstreamĀ versionĀ 0.9.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * $Id: BasicHeaderUI.java,v 1.24 2008/02/29 08:35:12 rah003 Exp $
 
3
 *
 
4
 * Copyright 2004 Sun Microsystems, Inc., 4150 Network Circle,
 
5
 * Santa Clara, California 95054, U.S.A. All rights reserved.
 
6
 *
 
7
 * This library is free software; you can redistribute it and/or
 
8
 * modify it under the terms of the GNU Lesser General Public
 
9
 * License as published by the Free Software Foundation; either
 
10
 * version 2.1 of the License, or (at your option) any later version.
 
11
 *
 
12
 * This library is distributed in the hope that it will be useful,
 
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
15
 * Lesser General Public License for more details.
 
16
 *
 
17
 * You should have received a copy of the GNU Lesser General Public
 
18
 * License along with this library; if not, write to the Free Software
 
19
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
20
 */
 
21
 
 
22
package org.jdesktop.swingx.plaf.basic;
 
23
 
 
24
import org.jdesktop.swingx.JXHeader;
 
25
import org.jdesktop.swingx.JXLabel;
 
26
import org.jdesktop.swingx.JXHeader.IconPosition;
 
27
import org.jdesktop.swingx.painter.MattePainter;
 
28
import org.jdesktop.swingx.painter.Painter;
 
29
import org.jdesktop.swingx.plaf.HeaderUI;
 
30
import org.jdesktop.swingx.plaf.PainterUIResource;
 
31
 
 
32
import javax.swing.*;
 
33
import javax.swing.plaf.ColorUIResource;
 
34
import javax.swing.plaf.ComponentUI;
 
35
import javax.swing.plaf.FontUIResource;
 
36
import javax.swing.plaf.basic.BasicHTML;
 
37
import javax.swing.text.View;
 
38
 
 
39
import java.awt.*;
 
40
import java.awt.event.HierarchyBoundsAdapter;
 
41
import java.awt.event.HierarchyBoundsListener;
 
42
import java.awt.event.HierarchyEvent;
 
43
import java.beans.PropertyChangeEvent;
 
44
import java.beans.PropertyChangeListener;
 
45
 
 
46
/**
 
47
 *
 
48
 * @author rbair
 
49
 * @author rah003
 
50
 */
 
51
public class BasicHeaderUI extends HeaderUI {
 
52
        // Implementation detail. Neeeded to expose getMultiLineSupport() method to allow restoring view
 
53
        // lost after LAF switch 
 
54
    protected class DescriptionPane extends JXLabel {
 
55
            @Override
 
56
            public void paint(Graphics g) {
 
57
                // switch off jxlabel default antialiasing
 
58
                ((Graphics2D)g).setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
 
59
                        RenderingHints.VALUE_TEXT_ANTIALIAS_OFF);
 
60
                super.paint(g);
 
61
            }
 
62
            
 
63
            public MultiLineSupport getMultiLineSupport() {
 
64
                return super.getMultiLineSupport();
 
65
            }
 
66
        }
 
67
 
 
68
        protected JLabel titleLabel;
 
69
    protected DescriptionPane descriptionPane;
 
70
    protected JLabel imagePanel;
 
71
    private PropertyChangeListener propListener;
 
72
    private HierarchyBoundsListener boundsListener;
 
73
    private Color gradientLightColor;
 
74
    private Color gradientDarkColor;
 
75
 
 
76
    /** Creates a new instance of BasicHeaderUI */
 
77
    public BasicHeaderUI() {
 
78
    }
 
79
 
 
80
    /**
 
81
     * Returns an instance of the UI delegate for the specified component.
 
82
     * Each subclass must provide its own static <code>createUI</code>
 
83
     * method that returns an instance of that UI delegate subclass.
 
84
     * If the UI delegate subclass is stateless, it may return an instance
 
85
     * that is shared by multiple components.  If the UI delegate is
 
86
     * stateful, then it should return a new instance per component.
 
87
     * The default implementation of this method throws an error, as it
 
88
     * should never be invoked.
 
89
     */
 
90
    public static ComponentUI createUI(JComponent c) {
 
91
        return new BasicHeaderUI();
 
92
    }
 
93
 
 
94
    /**
 
95
     * Configures the specified component appropriate for the look and feel.
 
96
     * This method is invoked when the <code>ComponentUI</code> instance is being installed
 
97
     * as the UI delegate on the specified component.  This method should
 
98
     * completely configure the component for the look and feel,
 
99
     * including the following:
 
100
     * <ol>
 
101
     * <li>Install any default property values for color, fonts, borders,
 
102
     *     icons, opacity, etc. on the component.  Whenever possible,
 
103
     *     property values initialized by the client program should <i>not</i>
 
104
     *     be overridden.
 
105
     * <li>Install a <code>LayoutManager</code> on the component if necessary.
 
106
     * <li>Create/add any required sub-components to the component.
 
107
     * <li>Create/install event listeners on the component.
 
108
     * <li>Create/install a <code>PropertyChangeListener</code> on the component in order
 
109
     *     to detect and respond to component property changes appropriately.
 
110
     * <li>Install keyboard UI (mnemonics, traversal, etc.) on the component.
 
111
     * <li>Initialize any appropriate instance data.
 
112
     * </ol>
 
113
     * @param c the component where this UI delegate is being installed
 
114
     *
 
115
     * @see #uninstallUI
 
116
     * @see javax.swing.JComponent#setUI
 
117
     * @see javax.swing.JComponent#updateUI
 
118
     */
 
119
    @Override
 
120
    public void installUI(JComponent c) {
 
121
        super.installUI(c);
 
122
        assert c instanceof JXHeader;
 
123
        JXHeader header = (JXHeader)c;
 
124
 
 
125
        titleLabel = new JLabel();
 
126
        descriptionPane = new DescriptionPane();
 
127
        descriptionPane.setLineWrap(true);
 
128
        descriptionPane.setOpaque(false);
 
129
 
 
130
        installDefaults(header);
 
131
 
 
132
        imagePanel = new JLabel();
 
133
        imagePanel.setIcon(header.getIcon() == null ? UIManager.getIcon("Header.defaultIcon") : header.getIcon());
 
134
        
 
135
        installComponents(header);
 
136
        installListeners(header);
 
137
    }
 
138
 
 
139
    /**
 
140
     * Reverses configuration which was done on the specified component during
 
141
     * <code>installUI</code>.  This method is invoked when this
 
142
     * <code>UIComponent</code> instance is being removed as the UI delegate
 
143
     * for the specified component.  This method should undo the
 
144
     * configuration performed in <code>installUI</code>, being careful to
 
145
     * leave the <code>JComponent</code> instance in a clean state (no
 
146
     * extraneous listeners, look-and-feel-specific property objects, etc.).
 
147
     * This should include the following:
 
148
     * <ol>
 
149
     * <li>Remove any UI-set borders from the component.
 
150
     * <li>Remove any UI-set layout managers on the component.
 
151
     * <li>Remove any UI-added sub-components from the component.
 
152
     * <li>Remove any UI-added event/property listeners from the component.
 
153
     * <li>Remove any UI-installed keyboard UI from the component.
 
154
     * <li>Nullify any allocated instance data objects to allow for GC.
 
155
     * </ol>
 
156
     * @param c the component from which this UI delegate is being removed;
 
157
     *          this argument is often ignored,
 
158
     *          but might be used if the UI object is stateless
 
159
     *          and shared by multiple components
 
160
     *
 
161
     * @see #installUI
 
162
     * @see javax.swing.JComponent#updateUI
 
163
     */
 
164
    @Override
 
165
    public void uninstallUI(JComponent c) {
 
166
        assert c instanceof JXHeader;
 
167
        JXHeader header = (JXHeader)c;
 
168
 
 
169
        uninstallDefaults(header);
 
170
        uninstallListeners(header);
 
171
        uninstallComponents(header);
 
172
 
 
173
        titleLabel = null;
 
174
        descriptionPane = null;
 
175
        imagePanel = null;
 
176
    }
 
177
 
 
178
    protected void installDefaults(JXHeader h) {
 
179
        gradientLightColor = UIManager.getColor("JXHeader.startBackground");
 
180
        if (gradientLightColor == null) {
 
181
                // fallback to white
 
182
                gradientLightColor = Color.WHITE;
 
183
        }
 
184
        gradientDarkColor = UIManager.getColor("JXHeader.background");
 
185
        //for backwards compatibility (mostly for substance and synthetica,
 
186
        //I suspect) I'll fall back on the "control" color if JXHeader.background
 
187
        //isn't specified.
 
188
        if (gradientDarkColor == null) {
 
189
            gradientDarkColor = UIManager.getColor("control"); 
 
190
        }
 
191
        
 
192
        Painter p = h.getBackgroundPainter();
 
193
        if (p == null || p instanceof PainterUIResource) {
 
194
            h.setBackgroundPainter(createBackgroundPainter());
 
195
        }
 
196
 
 
197
        // title properties
 
198
        Font titleFont = h.getTitleFont();
 
199
        if (titleFont == null || titleFont instanceof FontUIResource) {
 
200
                titleFont = UIManager.getFont("JXHeader.titleFont");
 
201
                // fallback to label font
 
202
                titleLabel.setFont(titleFont != null ? titleFont : UIManager.getFont("Label.font"));
 
203
        }
 
204
        
 
205
        Color titleForeground = h.getTitleForeground();
 
206
        if (titleForeground == null || titleForeground instanceof ColorUIResource) {
 
207
                titleForeground = UIManager.getColor("JXHeader.titleForeground");
 
208
                // fallback to label foreground
 
209
                titleLabel.setForeground(titleForeground != null ? titleForeground : UIManager.getColor("Label.foreground"));
 
210
        }
 
211
 
 
212
        titleLabel.setText(h.getTitle());
 
213
        
 
214
        // description properties
 
215
        Font descFont = h.getDescriptionFont();
 
216
        if (descFont == null || descFont instanceof FontUIResource) {
 
217
                descFont = UIManager.getFont("JXHeader.descriptionFont");
 
218
                // fallback to label font
 
219
                descriptionPane.setFont(descFont != null ? descFont : UIManager.getFont("Label.font"));
 
220
        }
 
221
            
 
222
        Color descForeground = h.getDescriptionForeground();
 
223
        if (descForeground == null || descForeground instanceof ColorUIResource) {
 
224
                descForeground = UIManager.getColor("JXHeader.descriptionForeground");
 
225
                // fallback to label foreground
 
226
                descriptionPane.setForeground(descForeground != null ? descForeground : UIManager.getColor("Label.foreground"));
 
227
        }
 
228
        
 
229
        descriptionPane.setText(h.getDescription());
 
230
    }
 
231
 
 
232
    protected void uninstallDefaults(JXHeader h) {
 
233
    }
 
234
 
 
235
    protected void installListeners(final JXHeader header) {
 
236
        propListener = new PropertyChangeListener() {
 
237
            public void propertyChange(PropertyChangeEvent evt) {
 
238
                onPropertyChange(header, evt.getPropertyName(), evt.getOldValue(), evt.getNewValue());
 
239
            }
 
240
        };
 
241
        boundsListener = new HierarchyBoundsAdapter() {
 
242
            public void ancestorResized(HierarchyEvent e) {
 
243
                if (header == e.getComponent()) {
 
244
                    View v = (View) descriptionPane.getClientProperty(BasicHTML.propertyKey);
 
245
                    // view might get lost on LAF change ...
 
246
                    if (v == null) {
 
247
                        descriptionPane.putClientProperty(BasicHTML.propertyKey, descriptionPane.getMultiLineSupport().createView(descriptionPane));
 
248
                        v = (View) descriptionPane.getClientProperty(BasicHTML.propertyKey);
 
249
                    }
 
250
                    if (v != null) {
 
251
                        int h = Math.max(descriptionPane.getHeight(), header.getTopLevelAncestor().getHeight());
 
252
                        int w = Math.min(header.getTopLevelAncestor().getWidth(), header.getParent().getWidth());
 
253
                        // 35 = description pane insets, TODO: obtain dynamically
 
254
                        w -= 35 + header.getInsets().left + header.getInsets().right + descriptionPane.getInsets().left + descriptionPane.getInsets().right + imagePanel.getInsets().left + imagePanel.getInsets().right + imagePanel.getWidth() + descriptionPane.getBounds().x;
 
255
                        v.setSize(w, h);
 
256
                        descriptionPane.setSize(w, (int) Math.ceil(v.getPreferredSpan(View.Y_AXIS)));
 
257
                    }
 
258
                }
 
259
            }};
 
260
        header.addPropertyChangeListener(propListener);
 
261
        header.addHierarchyBoundsListener(boundsListener);
 
262
    }
 
263
 
 
264
    protected void uninstallListeners(JXHeader h) {
 
265
        h.removePropertyChangeListener(propListener);
 
266
        h.removeHierarchyBoundsListener(boundsListener);
 
267
    }
 
268
 
 
269
    protected void onPropertyChange(JXHeader h, String propertyName, Object oldValue, final Object newValue) {
 
270
        if ("title".equals(propertyName)) {
 
271
            titleLabel.setText(h.getTitle());
 
272
        } else if ("description".equals(propertyName)) {
 
273
            descriptionPane.setText(h.getDescription());
 
274
        } else if ("icon".equals(propertyName)) {
 
275
            imagePanel.setIcon(h.getIcon());
 
276
        } else if ("enabled".equals(propertyName)) {
 
277
            boolean enabled = h.isEnabled();
 
278
            titleLabel.setEnabled(enabled);
 
279
            descriptionPane.setEnabled(enabled);
 
280
            imagePanel.setEnabled(enabled);
 
281
        } else if ("titleFont".equals(propertyName)) {
 
282
            titleLabel.setFont((Font)newValue);
 
283
        } else if ("descriptionFont".equals(propertyName)) {
 
284
            descriptionPane.setFont((Font)newValue);
 
285
        } else if ("titleForeground".equals(propertyName)) {
 
286
            titleLabel.setForeground((Color)newValue);
 
287
        } else if ("descriptionForeground".equals(propertyName)) {
 
288
            descriptionPane.setForeground((Color)newValue);
 
289
        } else if ("iconPosition".equals(propertyName)) {
 
290
            resetLayout(h);
 
291
        }
 
292
    }
 
293
 
 
294
    protected void installComponents(JXHeader h) {
 
295
        h.setLayout(new GridBagLayout());
 
296
        resetLayout(h);
 
297
    }
 
298
 
 
299
    private void resetLayout(JXHeader h) {
 
300
        h.remove(titleLabel);
 
301
        h.remove(descriptionPane);
 
302
        h.remove(imagePanel);
 
303
        if (h.getIconPosition() == null || h.getIconPosition() == IconPosition.RIGHT) {
 
304
                h.add(titleLabel, new GridBagConstraints(0, 0, 1, 1, 1.0, 0.0, GridBagConstraints.LINE_START, GridBagConstraints.HORIZONTAL, new Insets(12, 12, 0, 11), 0, 0));
 
305
                h.add(descriptionPane, new GridBagConstraints(0, 1, 1, 1, 1.0, 1.0, GridBagConstraints.FIRST_LINE_START, GridBagConstraints.BOTH, new Insets(0, 24, 12, 11), 0, 0));
 
306
                h.add(imagePanel, new GridBagConstraints(1, 0, 1, 2, 0.0, 1.0, GridBagConstraints.FIRST_LINE_END, GridBagConstraints.NONE, new Insets(12, 0, 11, 11), 0, 0));
 
307
        } else {
 
308
                h.add(titleLabel, new GridBagConstraints(1, 0, 1, 1, 1.0, 0.0, GridBagConstraints.LINE_START, GridBagConstraints.HORIZONTAL, new Insets(12, 12, 0, 11), 0, 0));
 
309
                h.add(descriptionPane, new GridBagConstraints(1, 1, 1, 1, 1.0, 1.0, GridBagConstraints.FIRST_LINE_START, GridBagConstraints.BOTH, new Insets(0, 24, 12, 11), 0, 0));
 
310
                h.add(imagePanel, new GridBagConstraints(0, 0, 1, 2, 0.0, 1.0, GridBagConstraints.FIRST_LINE_END, GridBagConstraints.NONE, new Insets(12, 11, 0, 11), 0, 0));
 
311
        }
 
312
        }
 
313
 
 
314
        protected void uninstallComponents(JXHeader h) {
 
315
        h.remove(titleLabel);
 
316
        h.remove(descriptionPane);
 
317
        h.remove(imagePanel);
 
318
    }
 
319
 
 
320
    protected Painter createBackgroundPainter() {
 
321
        MattePainter p = new MattePainter(new GradientPaint(0, 0, gradientLightColor, 1, 0, gradientDarkColor));
 
322
        p.setPaintStretched(true);
 
323
        return new PainterUIResource(p);
 
324
    }
 
325
}