KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > prefuse > demos > FisheyeMenu


1 /**
2  * Copyright (c) 2004-2006 Regents of the University of California.
3  * See "license-prefuse.txt" for licensing terms.
4  */

5 package prefuse.demos;
6
7 import java.awt.Insets JavaDoc;
8 import java.awt.event.ActionEvent JavaDoc;
9 import java.awt.event.ActionListener JavaDoc;
10 import java.awt.event.MouseEvent JavaDoc;
11 import java.awt.geom.Rectangle2D JavaDoc;
12 import java.util.Iterator JavaDoc;
13 import java.util.logging.Level JavaDoc;
14 import java.util.logging.Logger JavaDoc;
15
16 import javax.swing.AbstractAction JavaDoc;
17 import javax.swing.BorderFactory JavaDoc;
18 import javax.swing.JFrame JavaDoc;
19
20 import prefuse.Constants;
21 import prefuse.Display;
22 import prefuse.Visualization;
23 import prefuse.action.ActionList;
24 import prefuse.action.RepaintAction;
25 import prefuse.action.assignment.ColorAction;
26 import prefuse.action.distortion.Distortion;
27 import prefuse.action.distortion.FisheyeDistortion;
28 import prefuse.action.layout.Layout;
29 import prefuse.controls.AnchorUpdateControl;
30 import prefuse.controls.ControlAdapter;
31 import prefuse.data.Schema;
32 import prefuse.data.Table;
33 import prefuse.render.DefaultRendererFactory;
34 import prefuse.render.LabelRenderer;
35 import prefuse.util.ColorLib;
36 import prefuse.visual.VisualItem;
37
38 /**
39  * <p>A prefuse-based implementation of Fisheye Menus, showcasing the use of
40  * visual distortion to provide access to a large number of data items
41  * without scrolling.</p>
42  *
43  * <p>This implementation is inspired by the Fisheye Menu research conducted
44  * by Ben Bederson at the University of Maryland. See the
45  * <a HREF="http://www.cs.umd.edu/hcil/fisheyemenu/">Fisheye Menu project
46  * web site</a> for more details.</p>
47  *
48  * @author <a HREF="http://jheer.org">jeffrey heer</a>
49  */

50 public class FisheyeMenu extends Display {
51
52     /** The data group name of menu items. */
53     public static final String JavaDoc ITEMS = "items";
54     /** The label data field for menu items. */
55     public static final String JavaDoc LABEL = "label";
56     /** The action data field for menu items. */
57     public static final String JavaDoc ACTION = "action";
58     
59     /**
60      * This schema holds the data representation for internal storage of
61      * menu items.
62      */

63     protected static final Schema ITEM_SCHEMA = new Schema();
64     static {
65         ITEM_SCHEMA.addColumn(LABEL, String JavaDoc.class);
66         ITEM_SCHEMA.addColumn(ACTION, ActionListener JavaDoc.class);
67     }
68     
69     private Table m_items = ITEM_SCHEMA.instantiate(); // table of menu items
70

71     private double m_maxHeight = 500; // maximum menu height in pixels
72
private double m_scale = 7; // scale parameter for fisheye distortion
73

74     /**
75      * Create a new, empty FisheyeMenu.
76      * @see #addMenuItem(String, javax.swing.Action)
77      */

78     public FisheyeMenu() {
79         super(new Visualization());
80         m_vis.addTable(ITEMS, m_items);
81         
82         // set up the renderer to use
83
LabelRenderer renderer = new LabelRenderer(LABEL);
84         renderer.setHorizontalPadding(0);
85         renderer.setVerticalPadding(1);
86         renderer.setHorizontalAlignment(Constants.LEFT);
87         m_vis.setRendererFactory(new DefaultRendererFactory(renderer));
88         
89         // set up this display
90
setSize(100,470);
91         setHighQuality(true);
92         setBorder(BorderFactory.createEmptyBorder(10,10,10,5));
93         addControlListener(new ControlAdapter() {
94             // dispatch an action event to the menu item
95
public void itemClicked(VisualItem item, MouseEvent JavaDoc e) {
96                 ActionListener JavaDoc al = (ActionListener JavaDoc)item.get(ACTION);
97                 al.actionPerformed(new ActionEvent JavaDoc(item, e.getID(),
98                     "click", e.getWhen(), e.getModifiers()));
99             }
100         });
101         
102         // text color function
103
// items with the mouse over printed in red, otherwise black
104
ColorAction colors = new ColorAction(ITEMS, VisualItem.TEXTCOLOR);
105         colors.setDefaultColor(ColorLib.gray(0));
106         colors.add("hover()", ColorLib.rgb(255,0,0));
107         
108         // initial layout and coloring
109
ActionList init = new ActionList();
110         init.add(new VerticalLineLayout(m_maxHeight));
111         init.add(colors);
112         init.add(new RepaintAction());
113         m_vis.putAction("init", init);
114
115         // fisheye distortion based on the current anchor location
116
ActionList distort = new ActionList();
117         Distortion feye = new FisheyeDistortion(0,m_scale);
118         distort.add(feye);
119         distort.add(colors);
120         distort.add(new RepaintAction());
121         m_vis.putAction("distort", distort);
122         
123         // update the distortion anchor position to be the current
124
// location of the mouse pointer
125
addControlListener(new AnchorUpdateControl(feye, "distort"));
126     }
127     
128     /**
129      * Adds a menu item to the fisheye menu.
130      * @param name the menu label to use
131      * @param action the ActionListener to notify when the item is clicked
132      * The prefuse VisualItem corresponding to this menu item will
133      * be returned by the ActionEvent's getSource() method.
134      */

135     public void addMenuItem(String JavaDoc name, ActionListener JavaDoc listener) {
136         int row = m_items.addRow();
137         m_items.set(row, LABEL, name);
138         m_items.set(row, ACTION, listener);
139     }
140     
141     /**
142      * Run a demonstration of the FisheyeMenu
143      */

144     public static final void main(String JavaDoc[] argv) {
145         // only log warnings
146
Logger.getLogger("prefuse").setLevel(Level.WARNING);
147
148         FisheyeMenu fm = demo();
149         
150         // create and display application window
151
JFrame JavaDoc f = new JFrame JavaDoc("p r e f u s e | f i s h e y e");
152         f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
153         f.getContentPane().add(fm);
154         f.pack();
155         f.setVisible(true);
156     }
157     
158     public static FisheyeMenu demo() {
159         // create a new fisheye menu and populate it
160
FisheyeMenu fm = new FisheyeMenu();
161         for ( int i=1; i<=72; ++i ) {
162             // add menu items that simply print their label when clicked
163
fm.addMenuItem(String.valueOf(i), new AbstractAction JavaDoc() {
164                 public void actionPerformed(ActionEvent JavaDoc e) {
165                     System.out.println("clicked item: "+
166                         ((VisualItem)e.getSource()).get(LABEL));
167                     System.out.flush();
168                 }
169             });
170         }
171         fm.getVisualization().run("init");
172         return fm;
173     }
174     
175     /**
176      * Lines up all VisualItems vertically. Also scales the size such that
177      * all items fit within the maximum layout size, and updates the
178      * Display to the final computed size.
179      */

180     public class VerticalLineLayout extends Layout {
181         private double m_maxHeight = 600;
182         
183         public VerticalLineLayout(double maxHeight) {
184             m_maxHeight = maxHeight;
185         }
186         
187         public void run(double frac) {
188             // first pass
189
double w = 0, h = 0;
190             Iterator JavaDoc iter = m_vis.items();
191             while ( iter.hasNext() ) {
192                 VisualItem item = (VisualItem)iter.next();
193                 item.setSize(1.0);
194                 h += item.getBounds().getHeight();
195             }
196             double scale = h > m_maxHeight ? m_maxHeight/h : 1.0;
197             
198             Display d = m_vis.getDisplay(0);
199             Insets JavaDoc ins = d.getInsets();
200             
201             // second pass
202
h = ins.top;
203             double ih, y=0, x=ins.left;
204             iter = m_vis.items();
205             while ( iter.hasNext() ) {
206                 VisualItem item = (VisualItem)iter.next();
207                 item.setSize(scale); item.setEndSize(scale);
208                 Rectangle2D JavaDoc b = item.getBounds();
209                 
210                 w = Math.max(w, b.getWidth());
211                 ih = b.getHeight();
212                 y = h+(ih/2);
213                 setX(item, null, x);
214                 setY(item, null, y);
215                 h += ih;
216             }
217             
218             // set the display size to fit text
219
d.setSize((int)Math.round(2*m_scale*w + ins.left + ins.right),
220                       (int)Math.round(h + ins.bottom));
221         }
222     } // end of inner class VerticalLineLayout
223

224 } // end of class FisheyeMenu
225
Popular Tags