001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041:
042: package org.netbeans.modules.gsfret.navigation.base;
043:
044: import javax.swing.*;
045: import java.awt.*;
046: import java.awt.event.*;
047: import java.lang.ref.*;
048:
049: /**
050: * This file is originally from Retouche, the Java Support
051: * infrastructure in NetBeans. I have modified the file as little
052: * as possible to make merging Retouche fixes back as simple as
053: * possible.
054: * <p>
055: * Panel that can collapse to a small size and be reexpanded.
056: *
057: * @author Tim Boudreau
058: */
059: public final class TapPanel extends javax.swing.JPanel {
060: public static final int UP = 0;
061: public static final int DOWN = 2;
062:
063: public static final String PROP_ORIENTATION = "orientation"; //NOI18N
064: private int orientation = UP;
065: private boolean armed = false;
066: private boolean expanded = true;
067: private int minimumHeight = 8;
068:
069: /**
070: * Creates a new instance of TapPanel
071: */
072: public TapPanel() {
073: setLayout(new TrivialLayout());
074: }
075:
076: private static WeakReference<Adap> adapRef = null;
077:
078: static class Adap extends MouseAdapter implements
079: MouseMotionListener {
080: MouseListener other = null;
081:
082: public void mouseEntered(MouseEvent e) {
083: ((TapPanel) e.getSource()).setArmed(true);
084: }
085:
086: public void mouseExited(MouseEvent e) {
087: ((TapPanel) e.getSource()).setArmed(false);
088: }
089:
090: public void mouseMoved(MouseEvent e) {
091: ((TapPanel) e.getSource()).setArmed(((TapPanel) e
092: .getSource()).isArmPoint(e.getPoint()));
093: }
094:
095: public void mousePressed(MouseEvent e) {
096: if (((TapPanel) e.getSource()).isArmPoint(e.getPoint())) {
097: ((TapPanel) e.getSource()).setExpanded(!((TapPanel) e
098: .getSource()).isExpanded());
099: e.consume();
100: } else if (other != null) {
101: other.mousePressed(e);
102: }
103: }
104:
105: public void mouseDragged(MouseEvent e) {
106: //do nothing
107: }
108: }
109:
110: private static Adap getAdapter() {
111: Adap result = null;
112: if (adapRef != null) {
113: result = (Adap) adapRef.get();
114: }
115: if (result == null) {
116: result = new Adap();
117: adapRef = new WeakReference<Adap>(result);
118: }
119: return result;
120: }
121:
122: /**
123: * Allows mouse clicks *not* in the expansion bar to cause the navigator component to become activated, but the user
124: * can click to expand/collapse without activating the component.
125: */
126: void setSecondaryMouseHandler(MouseListener lis) {
127: getAdapter().other = lis;
128: }
129:
130: public void addNotify() {
131: addMouseMotionListener(getAdapter());
132: addMouseListener(getAdapter());
133: super .addNotify();
134: }
135:
136: public void removeNotify() {
137: super .removeNotify();
138: removeMouseMotionListener(getAdapter());
139: removeMouseListener(getAdapter());
140: }
141:
142: public int getOrientation() {
143: return orientation;
144: }
145:
146: public void setOrientation(int i) {
147: if (i != orientation) {
148: int oldOr = i;
149: orientation = i;
150: firePropertyChange(PROP_ORIENTATION, oldOr, i);
151: }
152: }
153:
154: private void setArmed(boolean val) {
155: if (val != armed) {
156: armed = val;
157: repaint();
158: }
159: }
160:
161: public boolean isExpanded() {
162: return expanded;
163: }
164:
165: public Dimension getPreferredSize() {
166: return getLayout().preferredLayoutSize(this );
167: }
168:
169: public Dimension getMinimumSize() {
170: Dimension d = getPreferredSize();
171: d.width = 20;
172: return d;
173: }
174:
175: public Dimension getMaximumSize() {
176: return getPreferredSize();
177: }
178:
179: public void setExpanded(boolean b) {
180: if (expanded != b) {
181: Dimension d = getPreferredSize();
182: expanded = b;
183: Dimension d1 = getPreferredSize();
184: if (isDisplayable()) {
185: revalidate();
186: }
187: }
188: }
189:
190: private boolean isArmPoint(Point p) {
191: if (!expanded) {
192: return p.y > 0 && p.y < getHeight();
193: } else {
194: if (orientation == UP) {
195: return p.y > getHeight() - minimumHeight;
196: } else {
197: return p.y < minimumHeight;
198: }
199: }
200: }
201:
202: public void updateBorder() {
203: if (orientation == UP) {
204: super .setBorder(BorderFactory.createEmptyBorder(0, 0,
205: minimumHeight, 0));
206: } else {
207: super .setBorder(BorderFactory.createEmptyBorder(
208: minimumHeight, 0, 0, 0));
209: }
210: }
211:
212: public int getMinimumHeight() {
213: return minimumHeight;
214: }
215:
216: public void setBorder() {
217: //do nothing
218: }
219:
220: public void paintBorder(Graphics g) {
221: Color c = armed ? UIManager
222: .getColor("List.selectionBackground") : getBackground(); //NOI18N
223: int x = 0;
224: int y = orientation == UP ? 1 + (getHeight() - minimumHeight)
225: : 0;
226: int w = getWidth();
227: int h = minimumHeight - 1;
228: g.setColor(c);
229: g.fillRect(x, y, w, h);
230:
231: int pos = orientation == UP ? getHeight() - 1 : 0;
232: int dir = orientation == UP ? -1 : 1;
233: g.setColor(armed ? c.darker() : UIManager
234: .getColor("controlShadow")); //NOI18N
235: g.drawLine(0, pos, w, pos);
236: pos += dir;
237:
238: if ((orientation == UP) == expanded) {
239: up.paintIcon(this , g, (getWidth() / 2)
240: - (up.getIconWidth() / 2), getHeight()
241: - (minimumHeight + (expanded ? 0 : -1)));
242: } else {
243: down.paintIcon(this , g, (getWidth() / 2)
244: - (up.getIconWidth() / 2), expanded ? 2 : 1);
245: }
246: }
247:
248: public void paintChildren(Graphics g) {
249: if (!expanded)
250: return;
251: super .paintChildren(g);
252: }
253:
254: private Icon up = new UpIcon();
255: private Icon down = new DownIcon();
256:
257: private int ICON_SIZE = 8;
258:
259: private class UpIcon implements Icon {
260: public int getIconHeight() {
261: return ICON_SIZE - 2;
262: }
263:
264: public int getIconWidth() {
265: return ICON_SIZE + 2;
266: }
267:
268: public void paintIcon(java.awt.Component c, Graphics g, int x,
269: int y) {
270:
271: g.setColor(armed ? UIManager
272: .getColor("List.selectionForeground") : //NOI18N
273: UIManager.getColor("controlShadow")); //NOI18N
274: /* int[] xPoints = new int[] {x+getIconWidth()/2, x+getIconWidth(), x};
275: int[] yPoints = new int[] {y, y+getIconHeight()-1, y+getIconHeight()-1};
276: */
277:
278: int[] xPoints = new int[] { x, x + 8, x + 4 };
279: int[] yPoints = new int[] { y + 5, y + 5, y };
280:
281: g.fillPolygon(xPoints, yPoints, 3);
282: }
283: }
284:
285: private class DownIcon implements Icon {
286:
287: public int getIconHeight() {
288: return ICON_SIZE - 3;
289: }
290:
291: public int getIconWidth() {
292: return ICON_SIZE + 2;
293: }
294:
295: public void paintIcon(java.awt.Component c, Graphics g, int x,
296: int y) {
297: x++;
298: g.setColor(armed ? UIManager
299: .getColor("List.selectionForeground") : //NOI18N
300: UIManager.getColor("controlShadow")); //NOI18N
301: /*
302: int[] xPoints = new int[] {(x+getIconWidth()/2), x+getIconWidth()-1, x};
303: int[] yPoints = new int[] {y+getIconHeight()-2, y, y};
304: */
305: int[] xPoints = new int[] { x, x + 8, x + 4 };
306: int[] yPoints = new int[] { y, y, y + 4 };
307:
308: g.fillPolygon(xPoints, yPoints, 3);
309: }
310:
311: }
312:
313: }
|