diff --git a/app/src/processing/app/tools/MenuScroller.java b/app/src/processing/app/tools/MenuScroller.java index cb7495650..e5ac193ae 100644 --- a/app/src/processing/app/tools/MenuScroller.java +++ b/app/src/processing/app/tools/MenuScroller.java @@ -3,43 +3,31 @@ */ package processing.app.tools; -import java.awt.Color; -import java.awt.Component; -import java.awt.Dimension; -import java.awt.Graphics; +import javax.swing.*; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import javax.swing.event.PopupMenuEvent; +import javax.swing.event.PopupMenuListener; +import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseWheelEvent; import java.awt.event.MouseWheelListener; -import javax.swing.Icon; -import javax.swing.JComponent; -import javax.swing.JMenu; -import javax.swing.JMenuItem; -import javax.swing.JPopupMenu; -import javax.swing.MenuSelectionManager; -import javax.swing.Timer; -import javax.swing.event.ChangeEvent; -import javax.swing.event.ChangeListener; -import javax.swing.event.PopupMenuEvent; -import javax.swing.event.PopupMenuListener; -import javax.swing.plaf.ButtonUI; - /** * A class that provides scrolling capabilities to a long menu dropdown or * popup menu. A number of items can optionally be frozen at the top and/or * bottom of the menu. - *
+ *
* Implementation note: The default number of items to display * at a time is 15, and the default scrolling interval is 125 milliseconds. - *+ *
* - * @version 1.5.0 04/05/12 * @author Darryl + * @version 1.5.0 04/05/12 */ public class MenuScroller { - //private JMenu menu; private JPopupMenu menu; private Component[] menuItems; private MenuScrollItem upItem; @@ -53,32 +41,13 @@ public class MenuScroller { private int firstIndex = 0; private int keepVisibleIndex = -1; - private static int getMaximumItems(JPopupMenu menu) { - JMenuItem test = new JMenuItem("test"); - ButtonUI ui = test.getUI(); - Dimension d = ui.getPreferredSize(test); - double item_height = d.getHeight(); - //System.out.println("JMenuItem Height " + item_height); - JMenuItem up = new JMenuItem(MenuIcon.UP); - ui = up.getUI(); - d = ui.getPreferredSize(up); - double icon_height = d.getHeight(); - //System.out.println("icon item height " + icon_height); - double menu_border_height = 8.0; // kludge - how to detect this? - double screen_height = java.awt.Toolkit.getDefaultToolkit().getScreenSize().getHeight(); - //System.out.println("screen height " + screen_height); - int n = (int)((screen_height - icon_height * 2 - menu_border_height) / item_height); - //System.out.println("max items " + n); - return n; - } - /** * Registers a menu to be scrolled with the default number of items to * display at a time and the default scrolling interval. - * + * * @param menu the menu * @return the MenuScroller - */ + */ public static MenuScroller setScrollerFor(JMenu menu) { return new MenuScroller(menu); } @@ -86,7 +55,7 @@ public class MenuScroller { /** * Registers a popup menu to be scrolled with the default number of items to * display at a time and the default scrolling interval. - * + * * @param menu the popup menu * @return the MenuScroller */ @@ -97,8 +66,8 @@ public class MenuScroller { /** * Registers a menu to be scrolled with the default number of items to * display at a time and the specified scrolling interval. - * - * @param menu the menu + * + * @param menu the menu * @param scrollCount the number of items to display at a time * @return the MenuScroller * @throws IllegalArgumentException if scrollCount is 0 or negative @@ -110,8 +79,8 @@ public class MenuScroller { /** * Registers a popup menu to be scrolled with the default number of items to * display at a time and the specified scrolling interval. - * - * @param menu the popup menu + * + * @param menu the popup menu * @param scrollCount the number of items to display at a time * @return the MenuScroller * @throws IllegalArgumentException if scrollCount is 0 or negative @@ -123,10 +92,10 @@ public class MenuScroller { /** * Registers a menu to be scrolled, with the specified number of items to * display at a time and the specified scrolling interval. - * - * @param menu the menu + * + * @param menu the menu * @param scrollCount the number of items to be displayed at a time - * @param interval the scroll interval, in milliseconds + * @param interval the scroll interval, in milliseconds * @return the MenuScroller * @throws IllegalArgumentException if scrollCount or interval is 0 or negative */ @@ -137,10 +106,10 @@ public class MenuScroller { /** * Registers a popup menu to be scrolled, with the specified number of items to * display at a time and the specified scrolling interval. - * - * @param menu the popup menu + * + * @param menu the popup menu * @param scrollCount the number of items to be displayed at a time - * @param interval the scroll interval, in milliseconds + * @param interval the scroll interval, in milliseconds * @return the MenuScroller * @throws IllegalArgumentException if scrollCount or interval is 0 or negative */ @@ -153,20 +122,20 @@ public class MenuScroller { * to display in the scrolling region, the specified scrolling interval, * and the specified numbers of items fixed at the top and bottom of the * menu. - * - * @param menu the menu - * @param scrollCount the number of items to display in the scrolling portion - * @param interval the scroll interval, in milliseconds - * @param topFixedCount the number of items to fix at the top. May be 0. + * + * @param menu the menu + * @param scrollCount the number of items to display in the scrolling portion + * @param interval the scroll interval, in milliseconds + * @param topFixedCount the number of items to fix at the top. May be 0. * @param bottomFixedCount the number of items to fix at the bottom. May be 0 - * @throws IllegalArgumentException if scrollCount or interval is 0 or - * negative or if topFixedCount or bottomFixedCount is negative * @return the MenuScroller + * @throws IllegalArgumentException if scrollCount or interval is 0 or + * negative or if topFixedCount or bottomFixedCount is negative */ public static MenuScroller setScrollerFor(JMenu menu, int scrollCount, int interval, - int topFixedCount, int bottomFixedCount) { + int topFixedCount, int bottomFixedCount) { return new MenuScroller(menu, scrollCount, interval, - topFixedCount, bottomFixedCount); + topFixedCount, bottomFixedCount); } /** @@ -174,50 +143,50 @@ public class MenuScroller { * to display in the scrolling region, the specified scrolling interval, * and the specified numbers of items fixed at the top and bottom of the * popup menu. - * - * @param menu the popup menu - * @param scrollCount the number of items to display in the scrolling portion - * @param interval the scroll interval, in milliseconds - * @param topFixedCount the number of items to fix at the top. May be 0 + * + * @param menu the popup menu + * @param scrollCount the number of items to display in the scrolling portion + * @param interval the scroll interval, in milliseconds + * @param topFixedCount the number of items to fix at the top. May be 0 * @param bottomFixedCount the number of items to fix at the bottom. May be 0 - * @throws IllegalArgumentException if scrollCount or interval is 0 or - * negative or if topFixedCount or bottomFixedCount is negative * @return the MenuScroller + * @throws IllegalArgumentException if scrollCount or interval is 0 or + * negative or if topFixedCount or bottomFixedCount is negative */ public static MenuScroller setScrollerFor(JPopupMenu menu, int scrollCount, int interval, - int topFixedCount, int bottomFixedCount) { + int topFixedCount, int bottomFixedCount) { return new MenuScroller(menu, scrollCount, interval, - topFixedCount, bottomFixedCount); + topFixedCount, bottomFixedCount); } /** * Constructs aMenuScroller
that scrolls a menu with the
* default number of items to display at a time, and default scrolling
* interval.
- *
+ *
* @param menu the menu
*/
public MenuScroller(JMenu menu) {
- this(menu, -1);
+ this(menu, 15);
}
/**
* Constructs a MenuScroller
that scrolls a popup menu with the
* default number of items to display at a time, and default scrolling
* interval.
- *
+ *
* @param menu the popup menu
*/
public MenuScroller(JPopupMenu menu) {
- this(menu, -1);
+ this(menu, 15);
}
/**
* Constructs a MenuScroller
that scrolls a menu with the
* specified number of items to display at a time, and default scrolling
* interval.
- *
- * @param menu the menu
+ *
+ * @param menu the menu
* @param scrollCount the number of items to display at a time
* @throws IllegalArgumentException if scrollCount is 0 or negative
*/
@@ -229,8 +198,8 @@ public class MenuScroller {
* Constructs a MenuScroller
that scrolls a popup menu with the
* specified number of items to display at a time, and default scrolling
* interval.
- *
- * @param menu the popup menu
+ *
+ * @param menu the popup menu
* @param scrollCount the number of items to display at a time
* @throws IllegalArgumentException if scrollCount is 0 or negative
*/
@@ -242,10 +211,10 @@ public class MenuScroller {
* Constructs a MenuScroller
that scrolls a menu with the
* specified number of items to display at a time, and specified scrolling
* interval.
- *
- * @param menu the menu
+ *
+ * @param menu the menu
* @param scrollCount the number of items to display at a time
- * @param interval the scroll interval, in milliseconds
+ * @param interval the scroll interval, in milliseconds
* @throws IllegalArgumentException if scrollCount or interval is 0 or negative
*/
public MenuScroller(JMenu menu, int scrollCount, int interval) {
@@ -256,10 +225,10 @@ public class MenuScroller {
* Constructs a MenuScroller
that scrolls a popup menu with the
* specified number of items to display at a time, and specified scrolling
* interval.
- *
- * @param menu the popup menu
+ *
+ * @param menu the popup menu
* @param scrollCount the number of items to display at a time
- * @param interval the scroll interval, in milliseconds
+ * @param interval the scroll interval, in milliseconds
* @throws IllegalArgumentException if scrollCount or interval is 0 or negative
*/
public MenuScroller(JPopupMenu menu, int scrollCount, int interval) {
@@ -271,17 +240,17 @@ public class MenuScroller {
* specified number of items to display in the scrolling region, the
* specified scrolling interval, and the specified numbers of items fixed at
* the top and bottom of the menu.
- *
- * @param menu the menu
- * @param scrollCount the number of items to display in the scrolling portion
- * @param interval the scroll interval, in milliseconds
- * @param topFixedCount the number of items to fix at the top. May be 0
+ *
+ * @param menu the menu
+ * @param scrollCount the number of items to display in the scrolling portion
+ * @param interval the scroll interval, in milliseconds
+ * @param topFixedCount the number of items to fix at the top. May be 0
* @param bottomFixedCount the number of items to fix at the bottom. May be 0
* @throws IllegalArgumentException if scrollCount or interval is 0 or
- * negative or if topFixedCount or bottomFixedCount is negative
+ * negative or if topFixedCount or bottomFixedCount is negative
*/
public MenuScroller(JMenu menu, int scrollCount, int interval,
- int topFixedCount, int bottomFixedCount) {
+ int topFixedCount, int bottomFixedCount) {
this(menu.getPopupMenu(), scrollCount, interval, topFixedCount, bottomFixedCount);
}
@@ -290,24 +259,23 @@ public class MenuScroller {
* specified number of items to display in the scrolling region, the
* specified scrolling interval, and the specified numbers of items fixed at
* the top and bottom of the popup menu.
- *
- * @param menu the popup menu
- * @param scrollCount the number of items to display in the scrolling portion
- * @param interval the scroll interval, in milliseconds
- * @param topFixedCount the number of items to fix at the top. May be 0
+ *
+ * @param menu the popup menu
+ * @param scrollCount the number of items to display in the scrolling portion
+ * @param interval the scroll interval, in milliseconds
+ * @param topFixedCount the number of items to fix at the top. May be 0
* @param bottomFixedCount the number of items to fix at the bottom. May be 0
* @throws IllegalArgumentException if scrollCount or interval is 0 or
- * negative or if topFixedCount or bottomFixedCount is negative
+ * negative or if topFixedCount or bottomFixedCount is negative
*/
public MenuScroller(JPopupMenu menu, int scrollCount, int interval,
- int topFixedCount, int bottomFixedCount) {
-
- if(scrollCount == -1)
- scrollCount = getMaximumItems(menu)-topFixedCount-bottomFixedCount; // Autosize
-
- if(interval == -1)
- interval = 150; // Default value
-
+ int topFixedCount, int bottomFixedCount) {
+
+ int autoSizeScrollCount = getMaximumDrawableMenuItems();
+ if (autoSizeScrollCount > scrollCount) {
+ scrollCount = autoSizeScrollCount;
+ }
+
if (scrollCount <= 0 || interval <= 0) {
throw new IllegalArgumentException("scrollCount and interval must be greater than 0");
}
@@ -329,7 +297,7 @@ public class MenuScroller {
/**
* Returns the scroll interval in milliseconds
- *
+ *
* @return the scroll interval in milliseconds
*/
public int getInterval() {
@@ -338,7 +306,7 @@ public class MenuScroller {
/**
* Sets the scroll interval in milliseconds
- *
+ *
* @param interval the scroll interval in milliseconds
* @throws IllegalArgumentException if interval is 0 or negative
*/
@@ -362,7 +330,7 @@ public class MenuScroller {
/**
* Sets the number of items in the scrolling portion of the menu.
- *
+ *
* @param scrollCount the number of items to display at a time
* @throws IllegalArgumentException if scrollCount is 0 or negative
*/
@@ -376,7 +344,7 @@ public class MenuScroller {
/**
* Returns the number of items fixed at the top of the menu or popup menu.
- *
+ *
* @return the number of items
*/
public int getTopFixedCount() {
@@ -385,7 +353,7 @@ public class MenuScroller {
/**
* Sets the number of items to fix at the top of the menu or popup menu.
- *
+ *
* @param topFixedCount the number of items
*/
public void setTopFixedCount(int topFixedCount) {
@@ -399,7 +367,7 @@ public class MenuScroller {
/**
* Returns the number of items fixed at the bottom of the menu or popup menu.
- *
+ *
* @return the number of items
*/
public int getBottomFixedCount() {
@@ -408,7 +376,7 @@ public class MenuScroller {
/**
* Sets the number of items to fix at the bottom of the menu or popup menu.
- *
+ *
* @param bottomFixedCount the number of items
*/
public void setBottomFixedCount(int bottomFixedCount) {
@@ -427,8 +395,7 @@ public class MenuScroller {
if (item == null) {
keepVisibleIndex = -1;
} else {
- int index = menu.getComponentIndex(item);
- keepVisibleIndex = index;
+ keepVisibleIndex = menu.getComponentIndex(item);
}
}
@@ -459,56 +426,64 @@ public class MenuScroller {
/**
* Ensures that the dispose
method of this MenuScroller is
* called when there are no more refrences to it.
- *
- * @exception Throwable if an error occurs.
+ *
+ * @throws Throwable if an error occurs.
* @see MenuScroller#dispose()
*/
@Override
public void finalize() throws Throwable {
+ super.finalize();
dispose();
}
private void refreshMenu() {
- if (menuItems == null || menuItems.length == 0) {
- return;
- }
+ if (menuItems != null && menuItems.length > 0) {
+ firstIndex = Math.max(topFixedCount, firstIndex);
+ firstIndex = Math.min(menuItems.length - bottomFixedCount - scrollCount, firstIndex);
- int newFirstIndex = Math.max(topFixedCount, firstIndex);
- newFirstIndex = Math.min(menuItems.length - bottomFixedCount - scrollCount, newFirstIndex);
+ upItem.setEnabled(firstIndex > topFixedCount);
+ downItem.setEnabled(firstIndex + scrollCount < menuItems.length - bottomFixedCount);
- if (newFirstIndex < 0) {
- return;
- }
-
- firstIndex = newFirstIndex;
-
- upItem.setEnabled(firstIndex > topFixedCount);
- downItem.setEnabled(firstIndex + scrollCount < menuItems.length - bottomFixedCount);
-
- menu.removeAll();
- for (int i = 0; i < topFixedCount; i++) {
- menu.add(menuItems[i]);
- }
- /*if (topFixedCount > 0) {
+ menu.removeAll();
+ for (int i = 0; i < topFixedCount; i++) {
+ menu.add(menuItems[i]);
+ }
+ if (topFixedCount > 0) {
menu.addSeparator();
- }*/
+ }
- menu.add(upItem);
- for (int i = firstIndex; i < scrollCount + firstIndex; i++) {
- menu.add(menuItems[i]);
- }
- menu.add(downItem);
+ menu.add(upItem);
+ for (int i = firstIndex; i < scrollCount + firstIndex; i++) {
+ menu.add(menuItems[i]);
+ }
+ menu.add(downItem);
- /*if (bottomFixedCount > 0) {
+ if (bottomFixedCount > 0) {
menu.addSeparator();
- }*/
- for (int i = menuItems.length - bottomFixedCount; i < menuItems.length; i++) {
- menu.add(menuItems[i]);
- }
+ }
+ for (int i = menuItems.length - bottomFixedCount; i < menuItems.length; i++) {
+ menu.add(menuItems[i]);
+ }
- JComponent parent = (JComponent) upItem.getParent();
- parent.revalidate();
- parent.repaint();
+ JComponent parent = (JComponent) upItem.getParent();
+ parent.revalidate();
+ parent.repaint();
+ }
+ }
+
+ private int getMaximumDrawableMenuItems() {
+ JMenuItem test = new JMenuItem("test");
+ double itemHeight = test.getUI().getPreferredSize(test).getHeight();
+
+ JMenuItem arrowMenuItem = new JMenuItem(MenuIcon.UP);
+ double arrowMenuItemHeight = arrowMenuItem.getUI().getPreferredSize(arrowMenuItem).getHeight();
+
+ double menuBorderHeight = 8.0; // kludge - how to detect this?
+ double screenHeight = java.awt.Toolkit.getDefaultToolkit().getScreenSize().getHeight();
+
+ int maxItems = (int) ((screenHeight - arrowMenuItemHeight * 2 - menuBorderHeight) / itemHeight);
+ maxItems -= maxItems / 3;
+ return maxItems;
}
private class MouseScrollListener implements MouseWheelListener {
@@ -518,7 +493,7 @@ public class MenuScroller {
mwe.consume();
}
}
-
+
private class MenuScrollListener implements PopupMenuListener {
@Override
@@ -538,29 +513,10 @@ public class MenuScroller {
private void setMenuItems() {
menuItems = menu.getComponents();
-
- // Hack for auto detect the topFixed total
- /*int topFixedCountPrev = topFixedCount;
- for(int i=menuItems.length-1;i>0;i--)
- {
- if(menuItems[i].getClass().getName().endsWith("Separator"))
- {
- System.out.println(i);
- setTopFixedCount(i+1);
-
- if(topFixedCount!=topFixedCountPrev)
- {
- scrollCount = getMaximumItems()-topFixedCount;
- System.out.println(getMaximumItems()-topFixedCount);
- }
- break;
- }
- }*/
-
if (keepVisibleIndex >= topFixedCount
- && keepVisibleIndex <= menuItems.length - bottomFixedCount
- && (keepVisibleIndex > firstIndex + scrollCount
- || keepVisibleIndex < firstIndex)) {
+ && keepVisibleIndex <= menuItems.length - bottomFixedCount
+ && (keepVisibleIndex > firstIndex + scrollCount
+ || keepVisibleIndex < firstIndex)) {
firstIndex = Math.min(firstIndex, keepVisibleIndex);
firstIndex = Math.max(firstIndex, keepVisibleIndex - scrollCount + 1);
}
@@ -577,7 +533,6 @@ public class MenuScroller {
}
}
- @SuppressWarnings("serial")
private class MenuScrollTimer extends Timer {
public MenuScrollTimer(final int increment, int interval) {
@@ -592,11 +547,10 @@ public class MenuScroller {
}
}
- @SuppressWarnings("serial")
private class MenuScrollItem extends JMenuItem
- implements ChangeListener {
+ implements ChangeListener {
- private MenuScrollTimer timer;
+ private final MenuScrollTimer timer;
public MenuScrollItem(MenuIcon icon, int increment) {
setIcon(icon);
@@ -620,7 +574,7 @@ public class MenuScroller {
}
}
- private static enum MenuIcon implements Icon {
+ private enum MenuIcon implements Icon {
UP(9, 1, 9),
DOWN(1, 9, 1);