View Javadoc

1   package com.eviware.soapui.support.propertyexpansion.scrollmenu;
2   
3   import java.awt.Component;
4   import java.awt.Dimension;
5   import java.awt.event.ActionEvent;
6   import java.awt.event.ActionListener;
7   import java.awt.event.MouseAdapter;
8   import java.awt.event.MouseEvent;
9   import java.awt.event.MouseListener;
10  import java.util.Vector;
11  
12  import javax.swing.Action;
13  import javax.swing.JButton;
14  import javax.swing.JComponent;
15  import javax.swing.JMenuItem;
16  import javax.swing.JPopupMenu;
17  import javax.swing.JSeparator;
18  import javax.swing.Timer;
19  
20  import com.eviware.soapui.support.UISupport;
21  
22  /***
23   * JMenu with the scrolling feature.
24   */
25  public class ScrollablePopup extends JPopupMenu implements ScrollableMenuContainer
26  {
27  	/*** How fast the scrolling will happen. */
28  	private int scrollSpeed = 20;
29  	/*** Handles the scrolling upwards. */
30  	private Timer timerUp;
31  	/*** Handles the scrolling downwards. */
32  	private Timer timerDown;
33  	/*** How many items are visible. */
34  	private int visibleItems;
35  	/***
36  	 * Menuitem's index which is used to control if up and downbutton are visible
37  	 * or not.
38  	 */
39  	private int indexVisible = 0;
40  	/*** Button to scroll menu upwards. */
41  	private JButton upButton;
42  	/*** Button to scroll menu downwards. */
43  	private JButton downButton;
44  	/*** Container to hold submenus. */
45  	private Vector<JMenuItem> subMenus = new Vector<JMenuItem>();
46  	/*** Height of the screen. */
47  	private double screenHeight;
48  	/*** Height of the menu. */
49  	private double menuHeight;
50  	private int headerCount;
51  	private int footerCount;
52  
53  	/***
54  	 * Creates a new ScrollableMenu object with a given name.
55  	 * <p>
56  	 * This also instantiates the timers and buttons. After the buttons are
57  	 * created they are set invisible.
58  	 * 
59  	 * @param name
60  	 *           name to be displayed on the JMenu
61  	 */
62  	public ScrollablePopup( String name )
63  	{
64  		super( name );
65  
66  		timerUp = new Timer( scrollSpeed, new ActionListener()
67  		{
68  			public void actionPerformed( ActionEvent evt )
69  			{
70  				scrollUp();
71  			}
72  		} );
73  		timerDown = new Timer( scrollSpeed, new ActionListener()
74  		{
75  			public void actionPerformed( ActionEvent evt )
76  			{
77  				scrollDown();
78  			}
79  		} );
80  
81  		screenHeight = 400;
82  		createButtons();
83  		hideButtons();
84  	}
85  
86  	/***
87  	 * JMenu's add-method is override to keep track of the added items. If there
88  	 * are more items that JMenu can display, then the added menuitems will be
89  	 * invisible. After that downscrolling button will be visible.
90  	 * 
91  	 * @param menuItem
92  	 *           to be added
93  	 * 
94  	 * @return added menuitem
95  	 */
96  	public JMenuItem add( JMenuItem menuItem )
97  	{
98  		add( menuItem, subMenus.size() + headerCount + 1 + ( headerCount == 0 ? 0 : 1 ) );
99  		subMenus.add( menuItem );
100 
101 		menuHeight += menuItem.getPreferredSize().getHeight();
102 
103 		if( menuHeight > screenHeight )
104 		{
105 			menuItem.setVisible( false );
106 			downButton.setVisible( true );
107 		}
108 		else
109 		{
110 			visibleItems++ ;
111 		}
112 
113 		return menuItem;
114 	}
115 
116 	public Component add( Component comp )
117 	{
118 		if( comp instanceof JMenuItem )
119 			return add( ( JMenuItem )comp );
120 		else
121 			return super.add( comp );
122 	}
123 
124 	public void removeAll()
125 	{
126 		super.removeAll();
127 
128 		headerCount = 0;
129 		footerCount = 0;
130 		menuHeight = 0;
131 		indexVisible = 0;
132 		visibleItems = 0;
133 
134 		subMenus.clear();
135 
136 		add( upButton );
137 		add( downButton );
138 	}
139 
140 	/***
141 	 * When timerUp is started it calls constantly this method to make the JMenu
142 	 * scroll upwards. When the top of menu is reached then upButton is set
143 	 * invisible. When scrollUp starts downButton is setVisible.
144 	 */
145 	private void scrollUp()
146 	{
147 		// closeOpenedSubMenus();
148 
149 		if( indexVisible == 0 )
150 		{
151 			upButton.setVisible( false );
152 
153 			return;
154 		}
155 		else
156 		{
157 			indexVisible-- ;
158 			( ( JComponent )subMenus.get( indexVisible + visibleItems ) ).setVisible( false );
159 			( ( JComponent )subMenus.get( indexVisible ) ).setVisible( true );
160 			downButton.setVisible( true );
161 			if( indexVisible == 0 )
162 			{
163 				upButton.setVisible( false );
164 			}
165 		}
166 	}
167 
168 	/***
169 	 * When timerDown is started it calls constantly this method to make the
170 	 * JMenu scroll downwards. When the bottom of menu is reached then downButton
171 	 * is set invisible. When scrolldown starts upButton is setVisible.
172 	 */
173 	private void scrollDown()
174 	{
175 		// closeOpenedSubMenus();
176 
177 		if( ( indexVisible + visibleItems ) == subMenus.size() )
178 		{
179 			downButton.setVisible( false );
180 
181 			return;
182 		}
183 		else if( ( indexVisible + visibleItems ) > subMenus.size() )
184 		{
185 			return;
186 		}
187 		else
188 		{
189 			try
190 			{
191 				( ( JComponent )subMenus.get( indexVisible ) ).setVisible( false );
192 				( ( JComponent )subMenus.get( indexVisible + visibleItems ) ).setVisible( true );
193 				upButton.setVisible( true );
194 				indexVisible++ ;
195 				if( ( indexVisible + visibleItems ) == subMenus.size() )
196 				{
197 					downButton.setVisible( false );
198 				}
199 			}
200 			catch( Exception eks )
201 			{
202 				eks.printStackTrace();
203 			}
204 		}
205 	}
206 
207 	/***
208 	 * Creates two button: upButton and downButton.
209 	 */
210 	private void createButtons()
211 	{
212 		upButton = new JButton( UISupport.createImageIcon( "/up_arrow.gif" ) );
213 
214 		Dimension d = new Dimension( 100, 20 );
215 		upButton.setPreferredSize( d );
216 		upButton.setBorderPainted( false );
217 		upButton.setFocusPainted( false );
218 		upButton.setRolloverEnabled( true );
219 
220 		class Up extends MouseAdapter
221 		{
222 			/***
223 			 * When mouse enters over the upbutton, timerUp starts the scrolling
224 			 * upwards.
225 			 * 
226 			 * @param e
227 			 *           MouseEvent
228 			 */
229 			public void mouseEntered( MouseEvent e )
230 			{
231 				try
232 				{
233 					timerUp.start();
234 				}
235 				catch( Exception ekas )
236 				{
237 				}
238 			}
239 
240 			/***
241 			 * When mouse exites the upbutton, timerUp stops.
242 			 * 
243 			 * @param e
244 			 *           MouseEvent
245 			 */
246 			public void mouseExited( MouseEvent e )
247 			{
248 				try
249 				{
250 					timerUp.stop();
251 				}
252 				catch( Exception ekas )
253 				{
254 				}
255 			}
256 		}
257 
258 		MouseListener scrollUpListener = new Up();
259 		upButton.addMouseListener( scrollUpListener );
260 
261 		add( upButton );
262 		downButton = new JButton( UISupport.createImageIcon( "/down_arrow.gif" ) );
263 		downButton.setPreferredSize( d );
264 		downButton.setBorderPainted( false );
265 		downButton.setFocusPainted( false );
266 
267 		class Down extends MouseAdapter
268 		{
269 			/***
270 			 * When mouse enters over the downbutton, timerDown starts the
271 			 * scrolling downwards.
272 			 * 
273 			 * @param e
274 			 *           MouseEvent
275 			 */
276 			public void mouseEntered( MouseEvent e )
277 			{
278 				try
279 				{
280 					timerDown.start();
281 				}
282 				catch( Exception ekas )
283 				{
284 				}
285 			}
286 
287 			/***
288 			 * When mouse exites the downbutton, timerDown stops.
289 			 * 
290 			 * @param e
291 			 *           MouseEvent
292 			 */
293 			public void mouseExited( MouseEvent e )
294 			{
295 				try
296 				{
297 					timerDown.stop();
298 				}
299 				catch( Exception ekas )
300 				{
301 				}
302 			}
303 		}
304 
305 		MouseListener scrollDownListener = new Down();
306 		downButton.addMouseListener( scrollDownListener );
307 		add( downButton, 1 + subMenus.size() );
308 	}
309 
310 	/***
311 	 * Hides the scrollButtons.
312 	 */
313 	public void hideButtons()
314 	{
315 		upButton.setVisible( false );
316 		downButton.setVisible( false );
317 	}
318 
319 	public JMenuItem addHeader( JMenuItem header )
320 	{
321 		add( header, headerCount );
322 
323 		if( ++headerCount == 1 )
324 			add( new JSeparator(), 1 );
325 
326 		return header;
327 	}
328 
329 	public JMenuItem addHeader( Action action )
330 	{
331 		return addHeader( new JMenuItem( action ) );
332 	}
333 
334 	public JMenuItem addFooter( JMenuItem footer )
335 	{
336 		if( footerCount == 0 )
337 			add( new JSeparator(), subMenus.size() + headerCount + 2 + ( headerCount == 0 ? 0 : 1 ) );
338 
339 		add( footer, subMenus.size() + headerCount + footerCount + 3 + ( headerCount == 0 ? 0 : 1 ) );
340 		footerCount++ ;
341 
342 		return footer;
343 	}
344 
345 	public JMenuItem addFooter( Action action )
346 	{
347 		return addFooter( new JMenuItem( action ) );
348 	}
349 }