KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > swing > scrollbars > impl > MetalMarkedScrollBarUI


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20
21 /*
22  * MarkedScrollbarUI.java
23  *
24  * Created on March 5, 2003, 4:32 PM
25  */

26 package org.netbeans.swing.scrollbars.impl;
27
28 import org.netbeans.swing.scrollbars.spi.Mark;
29 import org.netbeans.swing.scrollbars.spi.MarkingModel;
30
31 import javax.swing.*;
32 import javax.swing.event.ChangeListener JavaDoc;
33 import javax.swing.plaf.metal.MetalScrollBarUI JavaDoc;
34 import java.awt.*;
35 import java.awt.event.ComponentEvent JavaDoc;
36 import java.awt.event.ComponentListener JavaDoc;
37 import java.awt.event.MouseEvent JavaDoc;
38 import java.beans.PropertyChangeEvent JavaDoc;
39 import java.beans.PropertyChangeListener JavaDoc;
40 import java.util.Enumeration JavaDoc;
41 import java.util.HashMap JavaDoc;
42 import java.util.Iterator JavaDoc;
43 import java.util.Map JavaDoc;
44
45 /** Scrollbar UI that can take a MarkingModel and visually render
46  * rectangles for and respond to the marks alongside the scrollbar.
47  *
48  * @version 1.1
49  * @author Tim Boudreau
50  */

51 public class MetalMarkedScrollBarUI extends MetalScrollBarUI JavaDoc implements PropertyChangeListener JavaDoc, ChangeListener JavaDoc {
52     private static final int minsize = 4;
53     
54     private int gutterSize=8;
55     private MarkingModel model;
56
57     /** Creates a new instance of MarkedScrollbarUI
58      * @param model An instance of MarkingModel which will provide marks for it to render alongside
59      * the scrollbar.
60      */

61     public MetalMarkedScrollBarUI(MarkingModel model) {
62         this.model = model;
63         model.addChangeListener(this);
64         updateUI();
65     }
66
67     public void updateUI () {
68         if ((scrollbar != null) && scrollbar.isVisible()) {
69             if (scrollbar.getOrientation() == JScrollBar.VERTICAL) {
70                 layoutVScrollbar (scrollbar);
71             } else {
72                 layoutHScrollbar (scrollbar);
73             }
74         }
75     }
76     
77     public Dimension getPreferredSize(JComponent c) {
78         Dimension result = super.getPreferredSize(c);
79         if (scrollbar.getOrientation() == JScrollBar.VERTICAL) {
80             result.width += gutterSize - (gutterSize / 3);
81         } else {
82             result.height += gutterSize - (gutterSize / 3);
83         }
84         return result;
85     }
86     
87     public void installUI(JComponent c) {
88         updateUI();
89         super.installUI(c);
90         UIManager.addPropertyChangeListener(this);
91         c.addComponentListener ((ComponentListener JavaDoc) trackListener);
92     }
93     
94     public void uninstallUI(JComponent c) {
95         super.uninstallUI(c);
96         UIManager.removePropertyChangeListener(this);
97         c.removeComponentListener ((ComponentListener JavaDoc) trackListener);
98     }
99
100     /** Listens to the UIManager for changes, so the PLAF can be changed
101      * on the fly. Will call <code>updateUI()</code> in the case of a change. */

102     public final void propertyChange (PropertyChangeEvent JavaDoc pce) {
103         updateUI();
104     }
105     
106     protected void layoutVScrollbar(JScrollBar sb) {
107         super.layoutVScrollbar (sb);
108         trackRect.width -=gutterSize;
109         thumbRect.width -=gutterSize;
110         invalidateMarks();
111     }
112     
113     protected void layoutHScrollbar(JScrollBar sb) {
114         super.layoutVScrollbar (sb);
115         trackRect.height -=gutterSize;
116         thumbRect.height -=gutterSize;
117         invalidateMarks();
118     }
119     
120     public void paint(Graphics g, JComponent c) {
121         paintTrack(g, c, getTrackBounds());
122         paintThumb(g, c, getThumbBounds());
123         paintMarks(g);
124         if (scrollbar.getOrientation() == JScrollBar.VERTICAL) {
125             g.setColor(UIManager.getColor("controlDkShadow")); //NOI18N
126
g.drawLine(c.getWidth()-2, trackRect.y, c.getWidth()-2, trackRect.y+trackRect.height);
127             g.setColor(UIManager.getColor("controlHighlight")); //NOI18N
128
g.drawLine(c.getWidth()-1, trackRect.y, c.getWidth()-1, trackRect.y+trackRect.height);
129         } else {
130             g.setColor(UIManager.getColor("controlDkShadow")); //NOI18N
131
g.drawLine(trackRect.x, 2, trackRect.x+trackRect.width, 2);
132             g.setColor(UIManager.getColor("controlHighlight")); //NOI18N
133
g.drawLine(trackRect.x, 1, trackRect.x+trackRect.width, 1);
134         }
135     }
136
137     private void paintMarks (Graphics g) {
138         Map JavaDoc map = getRectsToMarks();
139         for (Iterator JavaDoc i = map.keySet().iterator(); i.hasNext();) {
140             Rectangle mrect = (Rectangle) i.next();
141             Mark mark = (Mark) map.get(mrect);
142             paintMark (mark, g, mrect);
143         }
144     }
145
146     private boolean invalid = true;
147     private void invalidateMarks() {
148         invalid = true;
149         scrollbar.repaint();
150     }
151
152     private Map JavaDoc getRectsToMarks() {
153         if (invalid) {
154             buildRects();
155         }
156         return rectsToMarks;
157     }
158
159     private void buildRects() {
160         rectsToMarks.clear();
161         if (model.size() == 0) {
162             return;
163         }
164         boolean vertical = scrollbar.getOrientation() == JScrollBar.VERTICAL;
165         int markRange = model.getMaxMarkLocation();
166
167         Rectangle r = getMarksRect();
168         for (Enumeration JavaDoc e = model.getMarks(); e.hasMoreElements();) {
169             Mark mark = (Mark) e.nextElement();
170             Rectangle curr = new Rectangle();
171             if (vertical) {
172                 r.y = translate (mark.getStart(), markRange);
173                 r.height = Math.max(minsize, translate (mark.getLength(), markRange));
174                 r.width = gutterSize;
175                 curr.setBounds(r.x, r.y, r.width, r.height);
176                 rectsToMarks.put (curr, mark);
177             } else {
178                 r.x = translate (mark.getStart(), markRange);
179                 r.width = Math.max(minsize, translate (mark.getLength(), markRange));
180                 r.height = gutterSize;
181                 curr.setBounds(r.x, r.y, r.width, r.height);
182                 rectsToMarks.put (curr, mark);
183             }
184         }
185         invalid = false;
186     }
187
188     private HashMap JavaDoc rectsToMarks = new HashMap JavaDoc();
189
190     /** Find the mark at a given point in the component's coordinate space
191      * @return The Mark object at that point, or null
192      * @param p A point in the scrollbar's coordinate space
193      */

194     public Mark markAtPoint (Point p) {
195         Rectangle rect = getMarksRect();
196         if (!(rect.contains(p))) return null;
197         java.util.Iterator JavaDoc i = rectsToMarks.keySet().iterator();
198         while (i.hasNext()) {
199             Rectangle r = (Rectangle) i.next();
200             if (r.contains(p)) return (Mark) rectsToMarks.get(r);
201         }
202         return null;
203     }
204     
205     /** Translate a location as given by a call to <code>someMark.getStart()</code>
206      * into the coordinate space of the scrollbar.
207      * @param loc The location given by the Mark object
208      * @param max The maximum, given by the model
209      * @return The coordinate in the space of the scrollbar, as a position along the
210      * scrollbar's resizable axis.
211      */

212     protected final int translate (int loc, int max) {
213         int range = getVisibleRange();
214         double factor = range / max;
215         double pos = factor * loc;
216         return Math.round(Math.round(pos));
217     }
218     
219     /** Get the total number of possible thumb positions on the resizable axis of the
220      * scrollbar - the track height or width, depending on the scrollbar's
221      * orientation
222      * @return The total
223      */

224     protected final int getVisibleRange () {
225         Rectangle mrect = getMarksRect();
226         return (scrollbar.getOrientation() == JScrollBar.VERTICAL) ?
227             mrect.height : mrect.width;
228     }
229     
230     /** Get the rectangle within which marks can be displayed.
231      * @return The rectangle
232      */

233     protected final Rectangle getMarksRect () {
234         Rectangle result;
235         if (scrollbar.getOrientation() == JScrollBar.VERTICAL) {
236             result = new Rectangle (trackRect.x + trackRect.width + 1, trackRect.y,
237                                     trackRect.width +gutterSize, trackRect.height);
238         } else {
239             result = new Rectangle (trackRect.x, trackRect.y + trackRect.height + 1,
240                                     trackRect.width, trackRect.height +gutterSize);
241         }
242         return result;
243     }
244     
245     protected TrackListener createTrackListener() {
246         return new MarkAndTrackListener ();
247     }
248     
249     private int translateToScrollbarModel (int i) {
250         BoundedRangeModel mod = scrollbar.getModel();
251         int min = mod.getMinimum();
252         int max = mod.getMaximum();
253         int mrange = max - min;
254         
255         double factor = mrange / model.getMaxMarkLocation();
256         double pos = (i * factor) + min;
257         return Math.round(Math.round(pos));
258     }
259     
260     private void goToMark (Mark m) {
261         Rectangle r = getMarksRect();
262         int loc = translate (m.getStart(), r.height);
263         scrollbar.setValue(translateToScrollbarModel (loc));
264         m.select();
265     }
266     
267     public void stateChanged(javax.swing.event.ChangeEvent JavaDoc e) {
268         invalidateMarks();
269     }
270     
271     protected class MarkAndTrackListener extends TrackListener implements ComponentListener JavaDoc {
272         public void mousePressed (MouseEvent JavaDoc e)
273         {
274             if (scrollbar.getValueIsAdjusting ()) {
275                 super.mousePressed (e);
276                 return;
277             }
278             if (SwingUtilities.isRightMouseButton(e) ||
279                 SwingUtilities.isMiddleMouseButton(e) || !scrollbar.isEnabled()) {
280                 return;
281             }
282
283             Point p = e.getPoint();
284             Rectangle r = getMarksRect();
285             
286             if (r.contains (p)) {
287                 Mark m = markAtPoint (p);
288                 if (m != null) {
289                     goToMark (m);
290                 }
291             } else {
292                 super.mousePressed(e);
293             }
294         }
295         
296         private boolean notInMarksRect (MouseEvent JavaDoc e) {
297             Point p = e.getPoint();
298             Rectangle r = getMarksRect();
299             return !(r.contains (p));
300         }
301         
302         public void mouseReleased (MouseEvent JavaDoc e) {
303             if (scrollbar.getValueIsAdjusting () || notInMarksRect (e)) {
304                 super.mouseReleased (e);
305             }
306         }
307
308         public void mouseDragged (MouseEvent JavaDoc e) {
309             if (scrollbar.getValueIsAdjusting () || notInMarksRect (e)) {
310                 super.mouseDragged (e);
311             }
312         }
313         String JavaDoc oldtext;
314         public void mouseMoved (MouseEvent JavaDoc e) {
315             if (scrollbar.getValueIsAdjusting () || notInMarksRect (e)) {
316                 super.mouseMoved (e);
317             } else {
318                 Point p = e.getPoint();
319                 Rectangle r = getMarksRect();
320
321                 if (r.contains (p)) {
322                     Mark m = markAtPoint (p);
323                     if (m != null) {
324                         scrollbar.setToolTipText (m.getText());
325                     } else {
326                         scrollbar.setToolTipText (null);
327                     }
328                 }
329             }
330         }
331
332         /**
333          * Invoked when the component's size changes.
334          */

335         public void componentResized(ComponentEvent JavaDoc e) {
336             invalidateMarks();
337         }
338
339         /**
340          * Invoked when the component's position changes.
341          */

342         public void componentMoved(ComponentEvent JavaDoc e) {
343
344         }
345
346         /**
347          * Invoked when the component has been made visible.
348          */

349         public void componentShown(ComponentEvent JavaDoc e) {
350             invalidateMarks();
351         }
352
353         /**
354          * Invoked when the component has been made invisible.
355          */

356         public void componentHidden(ComponentEvent JavaDoc e) {
357             rectsToMarks.clear();
358             invalid = true;
359         }
360     }
361
362     public void paintMarkMetal(Mark mark, Graphics g, Rectangle r) {
363          Color c = (Color) mark.get ("color"); //NOI18N
364
if (c == null) {
365              c = UIManager.getColor("windowText"); //NOI18N
366
}
367          g.setColor (c);
368          g.fillRect (r.x-1, r.y, r.width-1, r.height);
369          g.setColor (c.darker());
370          g.drawRect (r.x-1, r.y, r.width-2, r.height);
371     }
372
373
374
375     public void paintMark(Mark mark, Graphics g, Rectangle r) {
376         if (getClass() == MetalMarkedScrollBarUI.class) {
377             paintMarkMetal (mark, g, r);
378         } else {
379             paintMarkWindows (mark, g, r);
380         }
381     }
382         
383     private static final int overhang =5;
384     public void paintMarkWindows (Mark mark, Graphics graphics, Rectangle rect) {
385         Color c = (Color) mark.get ("color"); //NOI18N
386
if (c == null) {
387             c = UIManager.getColor("windowText"); //NOI18N
388
}
389         Paint p = new GradientPaint(rect.x+rect.width-1, rect.y+3, c,
390             rect.x-overhang, rect.y+3, UIManager.getColor("control"));
391         ((Graphics2D)graphics).setPaint(p);
392
393         graphics.fillRect (rect.x-overhang, rect.y, rect.width+4, rect.height);
394
395         graphics.setColor(c.darker());
396         graphics.drawLine(rect.x+rect.width, rect.y, rect.x+rect.width, rect.y+rect.height-1);
397         graphics.drawLine(rect.x+rect.width-1, rect.y, rect.x+rect.width-1, rect.y+rect.height-1);
398         graphics.drawLine(rect.x+rect.width-2, rect.y, rect.x+rect.width-2, rect.y+rect.height-1);
399         graphics.drawLine(rect.x+rect.width-3, rect.y, rect.x+rect.width-3, rect.y+rect.height-1);
400
401
402         graphics.setColor(UIManager.getColor("controlLtHighlight"));
403         graphics.drawLine(rect.x-overhang, rect.y,
404             rect.x+rect.width+overhang, rect.y);
405
406         p = new GradientPaint(rect.x+rect.width-1, rect.y+3, c.darker(),
407             rect.x-overhang, rect.y+3, UIManager.getColor("controlShadow"));
408         ((Graphics2D)graphics).setPaint(p);
409
410         graphics.drawLine(rect.x-overhang, rect.y+rect.height,
411             rect.x+rect.width+overhang, rect.y+rect.height);
412     }
413 }
414
Popular Tags