KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > xml > wsdl > ui > view > grapheditor > ZoomManager


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-2007 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20 package org.netbeans.modules.xml.wsdl.ui.view.grapheditor;
21
22 import java.awt.Dimension JavaDoc;
23 import java.awt.Image JavaDoc;
24 import java.awt.Point JavaDoc;
25 import java.awt.Rectangle JavaDoc;
26 import java.awt.event.ActionEvent JavaDoc;
27 import java.awt.event.ActionListener JavaDoc;
28 import java.util.EventListener JavaDoc;
29 import java.util.EventObject JavaDoc;
30 import javax.swing.AbstractAction JavaDoc;
31 import javax.swing.Action JavaDoc;
32 import javax.swing.DefaultComboBoxModel JavaDoc;
33 import javax.swing.ImageIcon JavaDoc;
34 import javax.swing.JComboBox JavaDoc;
35 import javax.swing.JComponent JavaDoc;
36 import javax.swing.JScrollPane JavaDoc;
37 import javax.swing.JToolBar JavaDoc;
38 import javax.swing.JViewport JavaDoc;
39 import javax.swing.SwingUtilities JavaDoc;
40 import javax.swing.event.EventListenerList JavaDoc;
41 import org.netbeans.api.visual.widget.Scene;
42 import org.openide.util.NbBundle;
43 import org.openide.util.Utilities;
44
45 /**
46  * Manages the zoom level for a particular Scene instance.
47  *
48  * @author Nathan Fiedler
49  */

50 public class ZoomManager {
51     /** The default zoom percent value. */
52     public static final int DEFAULT_ZOOM_PERCENT = 100;
53     /** The minimum zoom percent value. */
54     public static final int MIN_ZOOM_PERCENT = 33;
55     /** The maximum zoom percent value. */
56     public static final int MAX_ZOOM_PERCENT = 200;
57     /** Point at which the zoom increments/decrements more or less
58      * (less below the threshold, more above the threshold). */

59     private static final int ZOOM_STEP_THRESHOLD = DEFAULT_ZOOM_PERCENT;
60     /** Small zoom increment, when below the threshold. */
61     private static final int ZOOM_STEP_SMALL = 5;
62     /** Large zoom increment, when above the threshold. */
63     private static final int ZOOM_STEP_LARGE = 25;
64     /** The scene to zoom in/out. */
65     private Scene scene;
66     /** The zoom factor in the form of a percentage (e.g. 75%). */
67     private int zoomPercentage = DEFAULT_ZOOM_PERCENT;
68     /** List of zoom listeners. */
69     private EventListenerList JavaDoc listeners;
70
71     /**
72      * Creates a new instance of ZoomManager.
73      *
74      * @param scene the scene to be managed.
75      */

76     public ZoomManager(Scene scene) {
77         this.scene = scene;
78         listeners = new EventListenerList JavaDoc();
79     }
80
81     /**
82      * Adds the given listener to this manager instance. It will be notified
83      * when the zoom value is changed.
84      *
85      * @param listener listener to be added.
86      */

87     public void addZoomListener(ZoomListener listener) {
88         listeners.add(ZoomListener.class, listener);
89     }
90
91     /**
92      * Adds zoom actions to the given toolbar (no separators are added).
93      *
94      * @param toolbar to which the actions are added.
95      */

96     public void addToolbarActions(JToolBar JavaDoc toolbar) {
97         toolbar.add(new FitDiagramAction(this));
98         toolbar.add(new FitWidthAction(this));
99         toolbar.add(new ZoomDefaultAction(this));
100         toolbar.add(new ZoomComboBox(this));
101         ZoomInAction inAction = new ZoomInAction(this);
102         addZoomListener(inAction);
103         toolbar.add(inAction);
104         ZoomOutAction outAction = new ZoomOutAction(this);
105         addZoomListener(outAction);
106         toolbar.add(outAction);
107     }
108
109     /**
110      * Determine the zoom percentage if the user is zooming in
111      * (e.g. from 75 to 80, 100 to 125, etc.).
112      *
113      * @param percent the current percent value.
114      * @return the decreased percent value.
115      */

116     public static int calculateZoomInValue(int percent) {
117         int newZoomValue;
118         if (percent >= ZOOM_STEP_THRESHOLD) {
119             newZoomValue = ((percent + ZOOM_STEP_LARGE) / ZOOM_STEP_LARGE)
120             * ZOOM_STEP_LARGE;
121         } else {
122             newZoomValue = ((percent + ZOOM_STEP_SMALL) / ZOOM_STEP_SMALL)
123             * ZOOM_STEP_SMALL;
124         }
125         return newZoomValue;
126     }
127
128     /**
129      * Determine the zoom percentage if the user is zooming out
130      * (e.g. from 75 to 70, 150 to 125, etc.).
131      *
132      * @param percent the current percent value.
133      * @return the increased percent value.
134      */

135     public static int calculateZoomOutValue(int percent) {
136         int newZoomValue;
137         if (percent > ZOOM_STEP_THRESHOLD) {
138             newZoomValue = ((percent - 1) / ZOOM_STEP_LARGE) * ZOOM_STEP_LARGE;
139         } else {
140             newZoomValue = ((percent - 1) / ZOOM_STEP_SMALL) * ZOOM_STEP_SMALL;
141         }
142         return newZoomValue;
143     }
144
145     /**
146      * Fires zoom events to the registered listeners, if any.
147      *
148      * @param percent the new percent value.
149      */

150     private void fireZoomEvent(int percent) {
151         Object JavaDoc[] list = listeners.getListenerList();
152         ZoomEvent event = null;
153         for (int ii = list.length - 2; ii >= 0; ii -= 2) {
154             if (list[ii] == ZoomListener.class) {
155                 if (event == null) {
156                     event = new ZoomEvent(this, percent);
157                 }
158                 ((ZoomListener) list[ii + 1]).zoomChanged(event);
159             }
160         }
161     }
162
163     /**
164      * Return the Scene for which this manager is controlling the zoom.
165      *
166      * @return Scene managed by this manager.
167      */

168     public Scene getScene() {
169         return scene;
170     }
171
172     /**
173      * Return the zoom factor for the Scene mananged by this ZoomManager
174      * instance. The value represents a percentage (e.g. 100%) and
175      * is always a positive number.
176      *
177      * @return current zoom percentage.
178      */

179     public int getZoom() {
180         return zoomPercentage;
181     }
182
183     /**
184      * Removes the given listener from this manager instance, such that it
185      * will no longer receive zoom events.
186      *
187      * @param listener listener to be removed.
188      */

189     public void removeZoomListener(ZoomListener listener) {
190         listeners.remove(ZoomListener.class, listener);
191     }
192
193     /**
194      * Set the zoom factor for the Scene mananged by this ZoomManager
195      * instance. The value represents a percentage (e.g. 100%) and
196      * must be a positive number. Any value outside of the defined
197      * range (<tt>MIN_ZOOM_PERCENT</tt> and <tt>MAX_ZOOM_PERCENT</tt>)
198      * will be forced into that range.
199      *
200      * @param percent the percent value (e.g. 50 for half-size,
201      * 200 for double-size).
202      */

203     public void setZoom(int percent) {
204         JScrollPane JavaDoc pane = (JScrollPane JavaDoc) SwingUtilities.getAncestorOfClass(
205                 JScrollPane JavaDoc.class, scene.getView());
206         assert pane != null : "Scene view component not in a JScrollPane?!?";
207         if (pane == null) {
208             return;
209         }
210         JViewport JavaDoc viewport = pane.getViewport();
211         Rectangle JavaDoc visRect = viewport.getViewRect();
212         Point JavaDoc center = new Point JavaDoc(visRect.x + visRect.width / 2,
213                 visRect.y + visRect.height / 2);
214         setZoom(percent, center);
215     }
216
217     /**
218      * Set the zoom factor for the Scene mananged by this ZoomManager
219      * instance. The value represents a percentage (e.g. 100%) and
220      * must be a positive number. Any value outside of the defined
221      * range (<tt>MIN_ZOOM_PERCENT</tt> and <tt>MAX_ZOOM_PERCENT</tt>)
222      * will be forced into that range.
223      *
224      * @param percent the percent value (e.g. 50 for half-size,
225      * 200 for double-size).
226      * @param center the point at which to zoom in and keep centered.
227      */

228     public void setZoom(int percent, Point JavaDoc center) {
229         if (percent < MIN_ZOOM_PERCENT) {
230             percent = MIN_ZOOM_PERCENT;
231         } else if (percent > MAX_ZOOM_PERCENT) {
232             percent = MAX_ZOOM_PERCENT;
233         }
234
235         // Find the current center point prior to zooming.
236
Point JavaDoc sceneCenter = scene.convertViewToScene(center);
237         zoomPercentage = percent;
238         // Convert the percent value to the zoom factor Scene is expecting
239
// (a double that acts as the multiplier to the component sizes and
240
// locations, such that 0.5 is 50%, 1.0 is 100%, and 2.0 is 200%.
241
double factor = ((double) percent) / 100.0d;
242         scene.setZoomFactor(factor);
243         // Setting the zoom factor alone is not enough, must force
244
// validation and repainting of the scene for it to work.
245
scene.validate();
246         scene.repaint();
247
248         // Find the new center point and scroll the view after zooming.
249
Point JavaDoc newViewCenter = scene.convertSceneToView(sceneCenter);
250         JComponent JavaDoc view = scene.getView();
251         Rectangle JavaDoc visRect = view.getVisibleRect();
252         visRect.x = newViewCenter.x - (center.x - visRect.x);
253         visRect.y = newViewCenter.y - (center.y - visRect.y);
254         Dimension JavaDoc viewSize = view.getSize();
255         if (visRect.x + visRect.width > viewSize.width) {
256             visRect.x = viewSize.width - visRect.width;
257         }
258         if (visRect.y + visRect.height > viewSize.height) {
259             visRect.y = viewSize.height - visRect.height;
260         }
261         if (visRect.x < 0) {
262             visRect.x = 0;
263         }
264         if (visRect.y < 0) {
265             visRect.y = 0;
266         }
267         view.scrollRectToVisible(visRect);
268         view.revalidate();
269         view.repaint();
270
271         // Notify registered listeners so they may update their state.
272
fireZoomEvent(percent);
273     }
274
275     /**
276      * Manages the combobox for setting the zoom level.
277      */

278     private static class ZoomComboBox extends JComboBox JavaDoc {
279         /** The associated zoom manager. */
280         private ZoomManager manager;
281
282         /**
283          * Creates a new instance of ZoomComboBox.
284          *
285          * @param manager the zoom manager.
286          */

287         public ZoomComboBox(ZoomManager manager) {
288             super(new Model JavaDoc());
289             this.manager = manager;
290             // The combo will expand to fill all available space, so
291
// instead, give it a prototype value and then ask for the
292
// preferred size, making that the maximum size
293
// (make it wide enough to accomodate the '%').
294
setPrototypeDisplayValue(new Integer JavaDoc(10000));
295             setMaximumSize(getPreferredSize());
296             setEditable(true);
297             Listener JavaDoc l = new Listener JavaDoc(manager);
298             // We can't listen to ourselves, so use a delegate.
299
addActionListener(l);
300             manager.addZoomListener(l);
301         }
302
303         /**
304          * Combobox model, provides default zoom values.
305          */

306         private static class Model extends DefaultComboBoxModel JavaDoc {
307
308             /**
309              * Creates a new instance of Model.
310              */

311             public Model() {
312                 addElement(new Value(33));
313                 addElement(new Value(50));
314                 addElement(new Value(75));
315                 // We are assuming the default is between 75 and 150...
316
Value def = new Value(DEFAULT_ZOOM_PERCENT);
317                 addElement(def);
318                 addElement(new Value(150));
319                 addElement(new Value(200));
320                 setSelectedItem(def);
321             }
322         }
323
324         /**
325          * Class Value represents a combobox element.
326          */

327         private static class Value {
328             /** The value of the combobox element. */
329             private int value;
330             /** The String to represent this value. */
331             private String JavaDoc str;
332
333             /**
334              * Creates a new instance of Value.
335              *
336              * @param value the zoom value (e.g. 75, 100, 150).
337              */

338             public Value(int value) {
339                 this.value = value;
340                 str = value + "%";
341             }
342
343             public boolean equals(Object JavaDoc o) {
344                 if (o instanceof Value) {
345                     return value == ((Value) o).getValue();
346                 }
347                 return false;
348             }
349
350             public int hashCode() {
351                 return value;
352             }
353
354             /**
355              * Returns the integer value of this instance.
356              *
357              * @return integer value.
358              */

359             public int getValue() {
360                 return value;
361             }
362
363             public String JavaDoc toString() {
364                 return str;
365             }
366         }
367
368         /**
369          * Listener to the combobox and zoom manager.
370          */

371         private class Listener implements ActionListener JavaDoc, ZoomListener {
372             /** The associated zoom manager. */
373             private ZoomManager manager;
374
375             /**
376              * Creates a new instance of Listener.
377              *
378              * @param manager the zoom manager.
379              */

380             public Listener(ZoomManager manager) {
381                 this.manager = manager;
382             }
383
384             public void actionPerformed(ActionEvent JavaDoc event) {
385                 Object JavaDoc src = event.getSource();
386                 String JavaDoc cmd = event.getActionCommand();
387                 if (src == ZoomComboBox.this &&
388                         cmd.equals(ZoomComboBox.this.getActionCommand())) {
389                     // Ignore the "edited" action, since the "changed" action
390
// is sent on both accounts (selection or edit).
391
Object JavaDoc item = ZoomComboBox.this.getSelectedItem();
392                     Value value = null;
393                     if (item instanceof String JavaDoc) {
394                         String JavaDoc str = (String JavaDoc) item;
395                         if (str.endsWith("%")) {
396                             str = str.substring(0, str.length() - 1);
397                         }
398                         try {
399                             int i = Integer.parseInt(str);
400                             value = new Value(i);
401                         } catch (NumberFormatException JavaDoc nfe) {
402                             // ignore and fall through
403
}
404                     } else if (item instanceof Value) {
405                         value = (Value) item;
406                     }
407                     if (value == null) {
408                         value = new Value(ZoomComboBox.this.manager.getZoom());
409                     }
410                     manager.setZoom(value.getValue());
411                 }
412             }
413
414             public void zoomChanged(ZoomEvent event) {
415                 // Set the selected combobox value.
416
ZoomComboBox.this.removeActionListener(this);
417                 ZoomComboBox.this.setSelectedItem(new Value(event.getPercent()));
418                 ZoomComboBox.this.addActionListener(this);
419             }
420         }
421     }
422
423     /**
424      * Event object representing a change in the zoom level of a ZoomManager.
425      */

426     private static class ZoomEvent extends EventObject JavaDoc {
427         /** Percent value of the zoom manager at the time of the event. */
428         private int percent;
429
430         /**
431          * Creates a new instance of ZoomEvent.
432          *
433          * @param src the source of the event.
434          * @param percent the new zoom percent value.
435          */

436         public ZoomEvent(Object JavaDoc src, int percent) {
437             super(src);
438             this.percent = percent;
439         }
440
441         /**
442          * Returns the percent value of the zoom manager at the time of
443          * the event.
444          *
445          * @return percent value.
446          */

447         public int getPercent() {
448             return percent;
449         }
450     }
451
452     /**
453      * The listener interface for receiving zoom events.
454      */

455     private static interface ZoomListener extends EventListener JavaDoc {
456
457         /**
458          * The zoom level of the ZoomManager has changed.
459          *
460          * @param event the zoom event.
461          */

462         void zoomChanged(ZoomEvent event);
463     }
464
465     /**
466      * Implements the fit-diagram feature, such that it sets the zoom to
467      * show the Scene contents at the largest percentage while still
468      * fitting within the available scroll area.
469      */

470     private static class FitDiagramAction extends AbstractAction JavaDoc {
471         /** The associated ZoomManager. */
472         private ZoomManager manager;
473
474         /**
475          * Creates a new instance of FitDiagramAction.
476          *
477          * @param manager the zoom manager.
478          */

479         public FitDiagramAction(ZoomManager manager) {
480             this.manager = manager;
481             String JavaDoc path = NbBundle.getMessage(FitDiagramAction.class,
482                     "IMG_FitDiagramAction");
483             Image JavaDoc img = Utilities.loadImage(path);
484             if (img != null) {
485                 putValue(Action.SMALL_ICON, new ImageIcon JavaDoc(img));
486             }
487             String JavaDoc desc = NbBundle.getMessage(FitDiagramAction.class,
488                     "LBL_FitDiagramAction");
489             putValue(Action.NAME, desc); // for accessibility
490
putValue(Action.SHORT_DESCRIPTION, desc);
491         }
492
493         public void actionPerformed(ActionEvent JavaDoc e) {
494             Scene scene = manager.getScene();
495             JScrollPane JavaDoc pane = (JScrollPane JavaDoc) SwingUtilities.getAncestorOfClass(
496                     JScrollPane JavaDoc.class, scene.getView());
497             if (pane == null) {
498                 // Unlikely, but we cannot assume it exists.
499
return;
500             }
501             JViewport JavaDoc viewport = pane.getViewport();
502             Rectangle JavaDoc visRect = viewport.getViewRect();
503             Rectangle JavaDoc compRect = scene.getPreferredBounds();
504             int zoomX = visRect.width * 100 / compRect.width;
505             int zoomY = visRect.height * 100 / compRect.height;
506             int zoom = Math.min(zoomX, zoomY);
507             manager.setZoom(zoom);
508         }
509     }
510
511     /**
512      * Implements the fit-width feature, such that it sets the zoom to
513      * show the Scene contents at the largest percentage while still
514      * fitting within the width of the available scroll area.
515      */

516     private static class FitWidthAction extends AbstractAction JavaDoc {
517         /** The associated ZoomManager. */
518         private ZoomManager manager;
519
520         /**
521          * Creates a new instance of FitWidthAction.
522          *
523          * @param manager the zoom manager.
524          */

525         public FitWidthAction(ZoomManager manager) {
526             this.manager = manager;
527             String JavaDoc path = NbBundle.getMessage(FitWidthAction.class,
528                     "IMG_FitWidthAction");
529             Image JavaDoc img = Utilities.loadImage(path);
530             if (img != null) {
531                 putValue(Action.SMALL_ICON, new ImageIcon JavaDoc(img));
532             }
533             String JavaDoc desc = NbBundle.getMessage(FitWidthAction.class,
534                     "LBL_FitWidthAction");
535             putValue(Action.NAME, desc); // for accessibility
536
putValue(Action.SHORT_DESCRIPTION, desc);
537         }
538
539         public void actionPerformed(ActionEvent JavaDoc e) {
540             Scene scene = manager.getScene();
541             JScrollPane JavaDoc pane = (JScrollPane JavaDoc) SwingUtilities.getAncestorOfClass(
542                     JScrollPane JavaDoc.class, scene.getView());
543             if (pane == null) {
544                 // Unlikely, but we cannot assume it exists.
545
return;
546             }
547             JViewport JavaDoc viewport = pane.getViewport();
548             Rectangle JavaDoc visRect = viewport.getViewRect();
549             Rectangle JavaDoc compRect = scene.getPreferredBounds();
550             int zoom = visRect.width * 100 / compRect.width;
551             manager.setZoom(zoom);
552         }
553     }
554
555     /**
556      * Implements the 100% zoom feature, such that it sets the zoom percent
557      * to the fixed value of 100 (the default zoom level).
558      */

559     private static class ZoomDefaultAction extends AbstractAction JavaDoc {
560         /** The associated ZoomManager. */
561         private ZoomManager manager;
562
563         /**
564          * Creates a new instance of ZoomDefaultAction.
565          *
566          * @param manager the zoom manager.
567          */

568         public ZoomDefaultAction(ZoomManager manager) {
569             this.manager = manager;
570             String JavaDoc path = NbBundle.getMessage(ZoomDefaultAction.class,
571                     "IMG_ZoomDefaultAction");
572             Image JavaDoc img = Utilities.loadImage(path);
573             if (img != null) {
574                 putValue(Action.SMALL_ICON, new ImageIcon JavaDoc(img));
575             }
576             String JavaDoc desc = NbBundle.getMessage(ZoomDefaultAction.class,
577                     "LBL_ZoomDefaultAction");
578             putValue(Action.NAME, desc); // for accessibility
579
putValue(Action.SHORT_DESCRIPTION, desc);
580         }
581
582         public void actionPerformed(ActionEvent JavaDoc e) {
583             manager.setZoom(ZoomManager.DEFAULT_ZOOM_PERCENT);
584         }
585     }
586
587     /**
588      * Implements the zoom-in feature, such that it sets the zoom percent
589      * to a decreased amount for the scene.
590      */

591     private static class ZoomInAction extends AbstractAction JavaDoc implements ZoomListener {
592         /** The associated ZoomManager. */
593         private ZoomManager manager;
594
595         /**
596          * Creates a new instance of ZoomInAction.
597          *
598          * @param manager the zoom manager.
599          */

600         public ZoomInAction(ZoomManager manager) {
601             this.manager = manager;
602             String JavaDoc path = NbBundle.getMessage(ZoomInAction.class,
603                     "IMG_ZoomInAction");
604             Image JavaDoc img = Utilities.loadImage(path);
605             if (img != null) {
606                 putValue(Action.SMALL_ICON, new ImageIcon JavaDoc(img));
607             }
608             String JavaDoc desc = NbBundle.getMessage(ZoomInAction.class,
609                     "LBL_ZoomInAction");
610             putValue(Action.NAME, desc); // for accessibility
611
putValue(Action.SHORT_DESCRIPTION, desc);
612         }
613
614         public void actionPerformed(ActionEvent JavaDoc e) {
615             int percent = manager.getZoom();
616             percent = ZoomManager.calculateZoomInValue(percent);
617             manager.setZoom(percent);
618         }
619
620         public void zoomChanged(ZoomEvent event) {
621             boolean enable = event.getPercent() < MAX_ZOOM_PERCENT;
622             setEnabled(enable);
623         }
624     }
625
626     /**
627      * Implements the zoom-out feature, such that it sets the zoom percent
628      * to an increased amount for the scene.
629      */

630     private static class ZoomOutAction extends AbstractAction JavaDoc implements ZoomListener {
631         /** The associated ZoomManager. */
632         private ZoomManager manager;
633
634         /**
635          * Creates a new instance of ZoomOutAction.
636          *
637          * @param manager the zoom manager.
638          */

639         public ZoomOutAction(ZoomManager manager) {
640             this.manager = manager;
641             String JavaDoc path = NbBundle.getMessage(ZoomOutAction.class,
642                     "IMG_ZoomOutAction");
643             Image JavaDoc img = Utilities.loadImage(path);
644             if (img != null) {
645                 putValue(Action.SMALL_ICON, new ImageIcon JavaDoc(img));
646             }
647             String JavaDoc desc = NbBundle.getMessage(ZoomOutAction.class,
648                     "LBL_ZoomOutAction");
649             putValue(Action.NAME, desc); // for accessibility
650
putValue(Action.SHORT_DESCRIPTION, desc);
651         }
652
653         public void actionPerformed(ActionEvent JavaDoc e) {
654             int percent = manager.getZoom();
655             percent = ZoomManager.calculateZoomOutValue(percent);
656             manager.setZoom(percent);
657         }
658
659         public void zoomChanged(ZoomEvent event) {
660             boolean enable = event.getPercent() > MIN_ZOOM_PERCENT;
661             setEnabled(enable);
662         }
663     }
664 }
665
Popular Tags