KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > core > windows > view > ui > toolbars > ToolbarConstraints


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 package org.netbeans.core.windows.view.ui.toolbars;
21
22 import org.openide.awt.Toolbar;
23
24 import java.awt.*;
25 import java.beans.PropertyChangeListener JavaDoc;
26 import java.beans.PropertyChangeSupport JavaDoc;
27 import java.util.Iterator JavaDoc;
28 import java.util.Vector JavaDoc;
29
30 /** An object that encapsulates position and (optionally) size for
31  * Absolute positioning of components.
32  *
33  * Each toolbar constraints (TC) is component of toolbar row(s) and configuration.
34  * Every TC has cached the nearest neighbournhood, so there is a list of rows for TC is part,
35  * list of previous and next toolbars.
36  * So when there is some motion all of those cached attributes are recomputed.
37  *
38  * @author Libor Kramolis
39  */

40 public class ToolbarConstraints {
41     static final long serialVersionUID =3065774641403311880L;
42
43     /** Toolbar anchor status. */
44     static final int LEFT_ANCHOR = -1;
45     static final int NO_ANCHOR = 0;
46     
47     public static final String JavaDoc PREFERRED_SIZE = "preferredSize";
48
49     /** Toolbar name */
50     private String JavaDoc name;
51     /** Toolbar horizontal position */
52     private int position;
53     /** Which anchor toolbar use. */
54     private int anchor; // LEFT_ANCHOR | NO_ANCHOR
55
/** Is toolbar visible. */
56     private boolean visible;
57     /** Toolbar is part of those rows. */
58     private Vector JavaDoc<ToolbarRow> ownRows;
59     /** List of previous toolbars. */
60     private Vector JavaDoc<ToolbarConstraints> prevBars;
61     /** List of next toolbars. */
62     private Vector JavaDoc<ToolbarConstraints> nextBars;
63     /** The nearest end of previous toolbars. */
64     private int prevEnd; // nejblizsi konec predchozich toolbaru
65
/** The nearest begin of next toolbars. */
66     private int nextBeg; // nejblizsi zacatek nasledujicich toolbaru
67
/** The nearest begin of previous toolbars. */
68     private int prevBeg; // nejblizsi zacatek predchozich toolbaru
69
/** The nearest end of next toolbars. */
70     private int nextEnd; // nejblizsi konec nasledujicich toolbaru
71

72     /** Preferred size. */
73     private Dimension prefSize;
74     /** Toolbar bounds. */
75     private Rectangle bounds;
76     /** Toolbar constraints is part of ToolbarConfiguration. */
77     private ToolbarConfiguration toolbarConfig;
78     /** Number of rows. */
79     private int rowCount;
80     /** Width of last toolbar. */
81     private int prefLastWidth;
82     /** Last row index. */
83     private int lastRowIndex;
84     /** The toolbar index as defined by the order of declarations in layers.
85         Value -1 means that absolute pixel positioning will be used instead. */

86     private int initialIndexInRow;
87     
88     private PropertyChangeSupport JavaDoc propSupport;
89
90     ToolbarConstraints (ToolbarConfiguration conf, String JavaDoc nam, Integer JavaDoc pos, Boolean JavaDoc vis) {
91         this( conf, nam, pos, vis, -1 );
92     }
93     
94     /** Create new ToolbarConstraints
95      * @param conf own ToolbarConfiguration
96      * @param nam name of toolbar
97      * @param pos wanted position of toolbar
98      * @param vis visibility of toolbar
99      */

100     ToolbarConstraints (ToolbarConfiguration conf, String JavaDoc nam, Integer JavaDoc pos, Boolean JavaDoc vis, int initialIndexInRow) {
101         toolbarConfig = conf;
102         name = nam;
103         if (pos == null) {
104             position = 0;
105             anchor = LEFT_ANCHOR;
106             this.initialIndexInRow = initialIndexInRow;
107         } else {
108             position = pos.intValue();
109             anchor = NO_ANCHOR;
110             //the absolute positioning takes precedence over the order of
111
//declarations in layers
112
this.initialIndexInRow = -1;
113         }
114         visible = vis.booleanValue();
115
116         prefSize = new Dimension ();
117         rowCount = 0;
118         prefLastWidth = 0;
119         bounds = new Rectangle ();
120
121         initValues();
122     }
123
124     /** Init neighbourhood values. */
125     void initValues () {
126         ownRows = new Vector JavaDoc<ToolbarRow>();
127         prevBars = new Vector JavaDoc<ToolbarConstraints>();
128         nextBars = new Vector JavaDoc<ToolbarConstraints>();
129
130         resetPrev();
131         resetNext();
132     }
133
134     /** Checks position and visibility of multirow toolbar.
135      * @param position maybe new position
136      * @param visible maybe new visibility
137      */

138     void checkNextPosition (Integer JavaDoc position, Boolean JavaDoc visible) {
139         if (position == null) {
140             this.position = 0;
141             this.anchor = LEFT_ANCHOR;
142         } else {
143             if (anchor == NO_ANCHOR)
144                 this.position = (this.position + position.intValue()) / 2;
145             else
146                 this.position = position.intValue();
147             this.anchor = NO_ANCHOR;
148         }
149         this.visible = this.visible || visible.booleanValue();
150     }
151
152     /** @return name of toolbar. */
153     String JavaDoc getName () {
154         return name;
155     }
156
157     /** @return anchor of toolbar. */
158     int getAnchor () {
159         return anchor;
160     }
161
162     /** Set anchor of toolbar.
163      * @param anch new toolbar anchor.
164      */

165     void setAnchor (int anch) {
166         anchor = anch;
167     }
168
169     /** @return toolbar visibility. */
170     boolean isVisible () {
171         return visible;
172     }
173
174     /** Set new toolbar visibility.
175      * @param v new toolbar visibility
176      */

177     void setVisible (boolean v) {
178         visible = v;
179     }
180
181     /** @return horizontal toolbar position. */
182     int getPosition () {
183         return position;
184     }
185
186     /** Set new toolbar position.
187      * @param pos new toolbar position
188      */

189     void setPosition (int pos) {
190         position = pos;
191     }
192
193     /** @return toolbar width. */
194     int getWidth () {
195         return prefSize.width;
196     }
197
198     /** @return number toolbar rows. */
199     int getRowCount () {
200         return rowCount;
201     }
202     
203     int checkInitialIndexInRow() {
204         int retValue = initialIndexInRow;
205         initialIndexInRow = -1;
206         return retValue;
207     }
208     
209     /** @return toolbar bounds. */
210     Rectangle getBounds () {
211         return new Rectangle (bounds);
212     }
213
214     /** Destroy toolbar and it's neighbourhood (row context).
215      * @return true if after destroy stay some empty row.
216      */

217     boolean destroy () {
218         lastRowIndex = rowIndex();
219         rowCount = ownRows.size();
220
221         boolean emptyRow = false;
222         for (ToolbarRow row: ownRows) {
223             row.removeToolbar (this);
224             emptyRow = emptyRow || row.isEmpty();
225         }
226         initValues();
227         return emptyRow;
228     }
229
230     /** Add row to owned rows.
231      * @param row new owned row.
232      */

233     void addOwnRow (ToolbarRow row) {
234         ownRows.add (row);
235     }
236
237     /** Add toolbar to list of previous toolbars.
238      * @param prev new previous toolbar
239      */

240     void addPrevBar (ToolbarConstraints prev) {
241         if (prev == null)
242             return;
243         prevBars.add (prev);
244     }
245
246     /** Add toolbar to list of next toolbars.
247      * @param next new next toolbar
248      */

249     void addNextBar (ToolbarConstraints next) {
250         if (next == null)
251             return;
252         nextBars.add (next);
253     }
254
255     /** Remove toolbar from previous toolbars.
256      * @param prev toolbar for remove.
257      */

258     void removePrevBar (ToolbarConstraints prev) {
259         if (prev == null)
260             return;
261         prevBars.remove (prev);
262     }
263
264     /** Remove toolbar from next toolbars.
265      * @param next toolbar for remove.
266      */

267     void removeNextBar (ToolbarConstraints next) {
268         if (next == null)
269             return;
270         nextBars.remove (next);
271     }
272
273     /** Set preferred size of toolbar. There is important recompute toolbar neighbourhood.
274      * @param size preferred size
275      */

276     void setPreferredSize (Dimension size) {
277         Dimension oldSize = prefSize;
278         prefSize = size;
279         rowCount = Toolbar.rowCount (prefSize.height);
280
281         if (ownRows.isEmpty())
282             return;
283
284         ToolbarRow row;
285
286         if (visible) {
287             boolean emptyRow = false;
288             while (rowCount < ownRows.size()) {
289                 row = ownRows.lastElement();
290                 row.removeToolbar (this);
291                 ownRows.remove (row);
292                 emptyRow = emptyRow || row.isEmpty();
293             }
294             if (emptyRow)
295                 toolbarConfig.checkToolbarRows();
296             while (rowCount > ownRows.size()) {
297                 row = ownRows.lastElement();
298                 ToolbarRow nR = row.getNextRow();
299                 if (nR == null)
300                     nR = toolbarConfig.createLastRow();
301                 nR.addToolbar (this, position);
302             }
303         }
304         updatePosition();
305         propSupport.firePropertyChange(PREFERRED_SIZE, oldSize, prefSize);
306     }
307
308     /** @return index of first toolbar row. */
309     int rowIndex () {
310         if (!visible)
311             return toolbarConfig.getRowCount();
312         if (ownRows.isEmpty())
313             return lastRowIndex;
314         return toolbarConfig.rowIndex (ownRows.firstElement());
315     }
316
317     /** @return true if toolbar is alone at row(s). */
318     boolean isAlone () {
319         for (ToolbarRow row: ownRows) {
320             if (row.toolbarCount() != 1)
321                 return false;
322         }
323         return true;
324     }
325
326     /** Update preferred size of toolbar.
327      * @param size new preferred size
328      */

329     void updatePreferredSize (Dimension size) {
330         if (!prefSize.equals (size)) {
331             setPreferredSize (size);
332         }
333     }
334
335     /** Update toolbar bounds. */
336     void updateBounds () {
337         if (ownRows.size() > 0) {
338             Iterator JavaDoc<ToolbarRow> iter = ownRows.iterator();
339             ToolbarRow firstRow = iter.next();
340             int toolbarHeight = firstRow.getPreferredHeight();
341             while (iter.hasNext()) {
342                 toolbarHeight += iter.next().getPreferredHeight() + ToolbarLayout.VGAP;
343             }
344             bounds = new Rectangle (position, toolbarConfig.getRowVertLocation(firstRow),
345                                     nextBeg - position - ToolbarLayout.HGAP, toolbarHeight);
346         }
347         else {
348             bounds = new Rectangle(position, 0, 0, 0);
349         }
350     }
351
352     /** Update toolbar position and it's neighbourhood. */
353     void updatePosition () {
354         updatePrev();
355         if (anchor == NO_ANCHOR) {
356             if (position < (prevEnd + ToolbarLayout.HGAP)) {
357                 position = prevEnd + ToolbarLayout.HGAP;
358                 anchor = LEFT_ANCHOR;
359             }
360         } else {
361             position = prevEnd + ToolbarLayout.HGAP;
362         }
363         updatePrevBars();
364         updateNextBars();
365         updateBounds();
366         updatePrefWidth();
367     }
368
369     /** Update positions of previous toolbars. */
370     void updatePrevPosition () {
371         Iterator JavaDoc it = prevBars.iterator();
372         ToolbarConstraints tc;
373         while (it.hasNext()) {
374             tc = (ToolbarConstraints)it.next();
375             tc.updatePosition();
376         }
377     }
378
379     /** Update next position of previous toolbars. */
380     void updatePrevBars () {
381         for (ToolbarConstraints tc: prevBars) {
382             tc.updateNext();
383         }
384     }
385
386     /** Update previous position of next toolbars. */
387     void updateNextBars () {
388         Iterator JavaDoc<ToolbarConstraints> it = nextBars.iterator();
389         ToolbarConstraints tc;
390         if (!it.hasNext()) {
391             resetNext();
392             updatePrefWidth();
393         }
394         while (it.hasNext()) {
395             tc = it.next();
396             //hotfix for issue 31822, ToolbarConstraint endless loop. Core
397
//problem is that somehow nextBars ends up containing this
398
//constraint
399
if (tc != this) tc.updatePosition();
400         }
401     }
402
403     /** Update width of prevoius toolbars. */
404     void updatePrefWidth () {
405         if (nextBars.size() == 0) {
406             prefLastWidth = getPosition() + getWidth() + ToolbarLayout.HGAP;
407             toolbarConfig.updatePrefWidth();
408         }
409     }
410
411     /** @return preferred toolbar width. */
412     int getPrefWidth () {
413         return prefLastWidth;
414     }
415     
416     int getPrefHeight () {
417         return prefSize.height;
418     }
419
420     /** Update values about next toolbars. */
421     void updateNext () {
422         resetNext();
423         Iterator JavaDoc it = nextBars.iterator();
424         ToolbarConstraints tc;
425         int nextPos;
426         while (it.hasNext()) {
427             tc = (ToolbarConstraints)it.next();
428             nextBeg = Math.min (nextBeg, nextPos = tc.getPosition());
429             nextEnd = Math.min (nextEnd, nextPos + tc.getWidth());
430         }
431         updateBounds();
432     }
433
434     /** Update values about previous toolbars. */
435     void updatePrev () {
436         resetPrev();
437         Iterator JavaDoc it = prevBars.iterator();
438         ToolbarConstraints tc;
439         int prevPos;
440         while (it.hasNext()) {
441             tc = (ToolbarConstraints)it.next();
442             prevBeg = Math.max (prevBeg, prevPos = tc.getPosition());
443             prevEnd = Math.max (prevEnd, prevPos + tc.getWidth());
444         }
445     }
446
447     /** Reset values about previous toolbars. */
448     void resetPrev () {
449         prevBeg = 0;
450         prevEnd = 0;
451     }
452
453     /** Reset values about next toolbars. */
454     void resetNext () {
455         nextBeg = Integer.MAX_VALUE;
456         nextEnd = Integer.MAX_VALUE;
457     }
458
459     /** Move toolbar left if it's possible.
460      * @param dx horizontal distance
461      */

462     void moveLeft (int dx) {
463         int wantX = position - dx;
464
465         position = wantX;
466         anchor = NO_ANCHOR;
467         if (wantX > prevEnd) { // no problem to move left
468
setAnchorTo (NO_ANCHOR, nextBars);
469         } else {
470             if (canSwitchLeft (getPosition(), getWidth(), prevBeg, prevEnd - prevBeg)) { // can switch left ?
471
switchToolbarLeft ();
472             }
473         }
474     }
475
476     /** Move toolbar right if it's possible.
477      * @param dx horizontal distance
478      */

479     void moveRight (int dx) {
480         int wantX = position + dx;
481         int wantXpWidth = wantX + getWidth(); // wantX plus width
482

483         if (wantXpWidth < nextBeg) { // no problem to move right
484
anchor = NO_ANCHOR;
485             position = wantX;
486         } else {
487             if (canSwitchRight (wantX, getWidth(), nextBeg, nextEnd - nextBeg)) { // can switch right ?
488
position = wantX;
489                 anchor = NO_ANCHOR;
490                 switchToolbarRight ();
491             } else {
492                 position = nextBeg - getWidth() - ToolbarLayout.HGAP;
493                 anchor = NO_ANCHOR;
494             }
495         }
496
497         updatePrevPosition();
498     }
499
500     /** Move toolbar left with all followers. */
501     void moveLeft2End (int dx) {
502         int wantX = position - dx;
503
504         anchor = NO_ANCHOR;
505         if (wantX < (prevEnd + ToolbarLayout.HGAP)) {
506             wantX = prevEnd + ToolbarLayout.HGAP;
507         }
508         move2End (wantX - position);
509     }
510
511     /** Move toolbar right with all followers. */
512     void moveRight2End (int dx) {
513         move2End (dx);
514     }
515
516     /** Move toolbar horizontal with all followers. */
517     void move2End (int dx) {
518         position += dx;
519         Iterator JavaDoc it = nextBars.iterator();
520         ToolbarConstraints tc;
521         int nextPos;
522         while (it.hasNext()) {
523             tc = (ToolbarConstraints)it.next();
524             tc.move2End (dx);
525         }
526     }
527
528     /** Set anchor to list of toolbars.
529      * @param anch type of anchor
530      * @param bars list of toolbars
531      */

532     void setAnchorTo (int anch, Vector JavaDoc bars) {
533         Iterator JavaDoc it = bars.iterator();
534         ToolbarConstraints tc;
535         while (it.hasNext()) {
536             tc = (ToolbarConstraints)it.next();
537             tc.setAnchor (anch);
538         }
539     }
540
541     /** Switch toolbar left if it's possible. */
542     void switchToolbarLeft () {
543         Iterator JavaDoc it = ownRows.iterator();
544         ToolbarRow row;
545         while (it.hasNext()) {
546             row = (ToolbarRow)it.next();
547             row.trySwitchLeft (this);
548         }
549     }
550
551     /** Switch toolbar right if it's possible. */
552     void switchToolbarRight () {
553         Iterator JavaDoc it = ownRows.iterator();
554         ToolbarRow row;
555         while (it.hasNext()) {
556             row = (ToolbarRow)it.next();
557             row.trySwitchRight (this);
558         }
559     }
560     
561     public void addPropertyChangeListener (PropertyChangeListener JavaDoc l) {
562         if (propSupport == null) {
563             propSupport = new PropertyChangeSupport JavaDoc(this);
564         }
565         propSupport.addPropertyChangeListener(l);
566     }
567     
568     public void removePropertyChangeListener (PropertyChangeListener JavaDoc l) {
569         if (propSupport != null) {
570             propSupport.removePropertyChangeListener(l);
571         }
572     }
573
574     /** Can switch toolbar left?
575      * @param p1 toolbar1 position
576      * @param w1 toolbar1 width
577      * @param p2 toolbar2 position
578      * @param w2 toolbar2 width
579      * @return true if possible switch toolbar left.
580      */

581     static boolean canSwitchLeft (int p1, int w1, int p2, int w2) {
582         return (p1 < (p2));
583     }
584
585     /** Can switch toolbar right?
586      * @param p1 toolbar1 position
587      * @param w1 toolbar1 width
588      * @param p2 toolbar2 position
589      * @param w2 toolbar2 width
590      * @return true if possible switch toolbar right.
591      */

592     static boolean canSwitchRight (int p1, int w1, int p2, int w2) {
593         return (p1 > (p2));
594     }
595
596
597     /** Class to store toolbar in xml format. */
598     static class WritableToolbar {
599         /** name of toolbar */
600         String JavaDoc name;
601         /** position of toolbar */
602         int position;
603         /** anchor of toolbar */
604         int anchor;
605         /** toolbar visibility */
606         boolean visible;
607
608         /** Create new WritableToolbar.
609          * @param tc ToolbarConstraints
610          */

611         public WritableToolbar (ToolbarConstraints tc) {
612             name = tc.getName();
613             position = tc.getPosition();
614             anchor = tc.getAnchor();
615             visible = tc.isVisible();
616         }
617
618         /** @return ToolbarConstraints int xml format. */
619         public String JavaDoc toString () {
620             StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
621             String JavaDoc quotedName = name;
622             try {
623                 quotedName = org.openide.xml.XMLUtil.toAttributeValue(name);
624             }
625             catch (java.io.IOException JavaDoc ignore) {}
626             
627             sb.append (" <").append (ToolbarConfiguration.TAG_TOOLBAR); // NOI18N
628
sb.append (" ").append (ToolbarConfiguration.ATT_TOOLBAR_NAME).append ("=\""). // NOI18N
629
append (quotedName).append ("\""); // NOI18N
630
if ((anchor == ToolbarConstraints.NO_ANCHOR) || !visible)
631                 sb.append (" ").append (ToolbarConfiguration.ATT_TOOLBAR_POSITION).append ("=\""). // NOI18N
632
append (position).append ("\""); // NOI18N
633
if (!visible)
634                 sb.append (" ").append (ToolbarConfiguration.ATT_TOOLBAR_VISIBLE).append ("=\""). // NOI18N
635
append (visible).append ("\""); // NOI18N
636
sb.append (" />\n"); // NOI18N
637

638             return sb.toString();
639         }
640     } // end of inner class WritableToolbar
641
} // end of class ToolbarConstraints
642

643
Popular Tags