2
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
4
* Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
6
* The contents of this file are subject to the terms of either the GNU
7
* General Public License Version 2 only ("GPL") or the Common
8
* Development and Distribution License("CDDL") (collectively, the
9
* "License"). You may not use this file except in compliance with the
10
* License. You can obtain a copy of the License at
11
* http://www.netbeans.org/cddl-gplv2.html
12
* or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
* specific language governing permissions and limitations under the
14
* License. When distributing the software, include this License Header
15
* Notice in each file and include the License file at
16
* nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
17
* particular file as subject to the "Classpath" exception as provided
18
* by Sun in the GPL Version 2 section of the License file that
19
* accompanied this code. If applicable, add the following below the
20
* License Header, with the fields enclosed by brackets [] replaced by
21
* your own identifying information:
22
* "Portions Copyrighted [year] [name of copyright owner]"
26
* The Original Software is NetBeans. The Initial Developer of the Original
27
* Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
28
* Microsystems, Inc. All Rights Reserved.
30
* If you wish your version of this file to be governed by only the CDDL
31
* or only the GPL Version 2, indicate your decision by adding
32
* "[Contributor] elects to include this software in this distribution
33
* under the [CDDL or GPL Version 2] license." If you do not indicate a
34
* single choice of license, a recipient has the option to distribute
35
* your version of this file under either the CDDL, the GPL Version 2 or
36
* to extend the choice of license to its licensees as provided above.
37
* However, if you add GPL Version 2 code and therefore, elected the GPL
38
* Version 2 license, then the option applies only if the new code is
39
* made subject to such option by the copyright holder.
41
package org.openide.explorer.propertysheet;
43
import java.awt.Color;
44
import java.awt.Component;
45
import java.awt.Dimension;
47
import java.awt.FontMetrics;
48
import java.awt.Graphics;
49
import java.awt.Insets;
50
import java.awt.Rectangle;
51
import java.awt.event.ComponentEvent;
52
import java.awt.event.ComponentListener;
53
import java.awt.event.ContainerEvent;
54
import java.awt.event.ContainerListener;
56
import javax.swing.JComponent;
57
import javax.swing.JViewport;
58
import javax.swing.UIManager;
59
import javax.swing.plaf.ComponentUI;
60
import javax.swing.plaf.ViewportUI;
61
import javax.swing.plaf.basic.BasicViewportUI;
64
/** Viewport UI which will paint a margin if the contained
65
* SheetTable is showing one, so the margin appears to continue
66
* down to the bottom of the component.
68
* @author Tim Boudreau
70
class MarginViewportUI extends ViewportUI implements ComponentListener, ContainerListener {
71
private JViewport viewport;
72
private int lastHeight = -1;
73
private int stringWidth = -1;
74
private int stringHeight = -1;
75
private int ascent = -1;
76
Rectangle scratch = new Rectangle();
77
private String emptyString = "THIS IS A BUG"; //NOI18N
78
Color marginColor = UIManager.getColor("controlShadow"); //NOI18N
79
private int marginWidth = PropUtils.getMarginWidth();
80
private boolean marginPainted = false;
81
Dimension lastKnownSize = new Dimension();
83
/** Creates a new instance of MarginViewportUI */
84
private MarginViewportUI(JViewport jv) {
88
/** Uses a single shared instance, as does BasicViewportUI */
89
public static ComponentUI createUI(JComponent c) {
90
return new MarginViewportUI((JViewport) c);
93
public void installUI(JComponent c) {
96
//Fetch the "no properties" string - it's not going to change
97
//for the life of the session
98
// noPropsString = NbBundle.getMessage(MarginViewportUI.class,
99
// "CTL_NoProperties"); //NOI18N
100
//Set an appropriate font and color. Only really relevant on OS-X to
101
//keep the font consistent with other NB fonts
102
Color fg = UIManager.getColor("controlShadow"); //NOI18N
105
fg = Color.LIGHT_GRAY;
110
Color bg = UIManager.getColor("window"); //NOI18N
118
Font f = UIManager.getFont("Tree.font"); //NOI18N
121
f = UIManager.getFont("controlFont"); //NOI18N
128
c.addContainerListener(this);
130
Component[] kids = c.getComponents();
132
for (int i = 0; i < kids.length; i++) {
133
//Should almost always be empty anyway, if not only one component,
134
//but for completeness...
135
kids[i].addComponentListener(this);
139
public void uninstallUI(JComponent vp) {
140
JViewport jv = (JViewport) vp;
141
Component[] c = jv.getComponents();
143
for (int i = 0; i < c.length; i++) {
144
c[i].removeComponentListener(this);
147
jv.removeContainerListener(this);
150
public void setEmptyString(String s) {
156
public void setMarginColor(Color c) {
160
public void setMarginWidth(int margin) {
161
this.marginWidth = margin;
164
public void setMarginPainted(boolean val) {
165
if (marginPainted != val) {
171
/** Overridden to draw "no properties" if necessary */
172
public void paint(Graphics g, JComponent c) {
173
Component view = ((JViewport) c).getView();
176
lastKnownSize = view.getSize();
179
if (stringWidth == -1) {
180
calcStringSizes(c.getFont(), g);
183
//Update will have set paintNoProps to the correct value
184
if (shouldPaintEmptyMessage()) {
185
//We need to paint centered "<No Properties>" text
186
g.setFont(c.getFont());
187
g.setColor(c.getForeground());
189
Rectangle r = getEmptyMessageBounds();
191
//See if we really need to do any painting
192
if (g.hitClip(r.x, r.y, r.width, r.height)) {
194
g.drawString(emptyString, r.x, r.y + ascent);
199
private void calcStringSizes(Font f, Graphics g) {
200
FontMetrics fm = g.getFontMetrics(f);
201
stringWidth = fm.stringWidth(emptyString);
202
stringHeight = fm.getHeight();
203
ascent = fm.getMaxAscent();
206
private Rectangle getEmptyMessageBounds() {
207
Insets ins = viewport.getInsets();
209
scratch.x = ins.left + (((viewport.getWidth() - (ins.left + ins.right)) / 2) - (stringWidth / 2));
211
scratch.y = ins.top + (((viewport.getHeight() - (ins.top + ins.bottom)) / 2) - (stringHeight / 2));
213
scratch.width = stringWidth;
214
scratch.height = stringHeight;
219
public void update(Graphics g, JComponent c) {
220
g.setColor(c.getBackground());
222
boolean margin = shouldPaintMargin();
224
int leftEdge = margin ? marginWidth : 0;
225
g.fillRect(leftEdge, 0, c.getWidth() - leftEdge, c.getHeight());
228
g.setColor(marginColor);
229
g.fillRect(0, 0, marginWidth, c.getHeight());
235
private void scheduleRepaint(Dimension nuSize) {
236
if (!marginPainted && ((nuSize.height > 10) == (lastKnownSize.height > 10))) {
240
int heightDif = Math.abs(nuSize.height - lastKnownSize.height);
242
if (heightDif == 0) {
246
// if (heightDif != 0) {
247
Insets ins = viewport.getInsets();
251
int top = nuSize.height + ins.top;
252
int width = marginWidth;
253
int height = lastKnownSize.height - nuSize.height;
255
viewport.repaint (left, top, width, height);
257
viewport.repaint(ins.left, ins.top, marginWidth, viewport.getHeight() - (ins.top + ins.bottom));
260
// if (nuSize.height < 10) {
261
Rectangle r = getEmptyMessageBounds();
262
viewport.repaint(r.x, r.y, r.width, r.height);
267
private boolean shouldPaintEmptyMessage() {
268
Dimension d = viewport.getView().getSize();
270
return d.height < 10;
273
private boolean shouldPaintMargin() {
274
return marginPainted & !shouldPaintEmptyMessage();
277
public void componentAdded(ContainerEvent e) {
278
e.getChild().addComponentListener(this);
281
public void componentHidden(ComponentEvent e) {
284
public void componentMoved(ComponentEvent e) {
287
public void componentRemoved(ContainerEvent e) {
288
e.getChild().removeComponentListener(this);
291
public void componentResized(ComponentEvent e) {
292
scheduleRepaint(((Component) e.getSource()).getSize());
295
public void componentShown(ComponentEvent e) {
296
scheduleRepaint(((Component) e.getSource()).getSize());