[Schmitzm-commits] r2421 - in trunk/schmitzm-core/src/main/java/de/schmitzm/swing: . event
scm-commit at wald.intevation.org
scm-commit at wald.intevation.org
Thu Jun 23 17:50:57 CEST 2016
Author: mojays
Date: 2016-06-23 17:50:57 +0200 (Thu, 23 Jun 2016)
New Revision: 2421
Modified:
trunk/schmitzm-core/src/main/java/de/schmitzm/swing/SwingUtil.java
trunk/schmitzm-core/src/main/java/de/schmitzm/swing/event/PopupMenuListener.java
Log:
PopupMenuListener: handle popup sources different than Component (esp. TrayIcon)
SwingUtil: handle application in system tray; simple transform from JPopupMenu to PopupMenu
Modified: trunk/schmitzm-core/src/main/java/de/schmitzm/swing/SwingUtil.java
===================================================================
--- trunk/schmitzm-core/src/main/java/de/schmitzm/swing/SwingUtil.java 2016-02-15 16:40:50 UTC (rev 2420)
+++ trunk/schmitzm-core/src/main/java/de/schmitzm/swing/SwingUtil.java 2016-06-23 15:50:57 UTC (rev 2421)
@@ -35,6 +35,7 @@
import java.awt.Container;
import java.awt.Cursor;
import java.awt.Desktop;
+import java.awt.Dialog;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Font;
@@ -44,9 +45,13 @@
import java.awt.GraphicsEnvironment;
import java.awt.GridBagConstraints;
import java.awt.Image;
+import java.awt.MenuItem;
import java.awt.Point;
+import java.awt.PopupMenu;
import java.awt.Rectangle;
+import java.awt.SystemTray;
import java.awt.Toolkit;
+import java.awt.TrayIcon;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
@@ -58,6 +63,8 @@
import java.awt.event.MouseWheelListener;
import java.awt.font.TextAttribute;
import java.awt.image.BufferedImage;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
@@ -105,9 +112,11 @@
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
+import javax.swing.JPopupMenu;
import javax.swing.JProgressBar;
import javax.swing.JRadioButtonMenuItem;
import javax.swing.JScrollPane;
+import javax.swing.JSeparator;
import javax.swing.JSpinner;
import javax.swing.JSplitPane;
import javax.swing.JTabbedPane;
@@ -119,6 +128,7 @@
import javax.swing.JToolBar;
import javax.swing.JTree;
import javax.swing.JViewport;
+import javax.swing.KeyStroke;
import javax.swing.RootPaneContainer;
import javax.swing.SpinnerNumberModel;
import javax.swing.SwingUtilities;
@@ -151,6 +161,7 @@
import de.schmitzm.lang.ApplicationProps;
import de.schmitzm.lang.LangUtil;
import de.schmitzm.lang.ResourceProvider;
+import de.schmitzm.swing.event.PopupMenuListener;
import de.schmitzm.swing.event.SmoothProgressBarUpdater;
import de.schmitzm.swing.input.BooleanInputOption;
import de.schmitzm.swing.input.InputOption;
@@ -305,6 +316,8 @@
public static final Cursor SELECTION_REMOVE_CURSOR = createCursorFromResourcePath(
"resource/cursor/selection_remove.png", 10, 10, null);
+ /** Default java application icon (coffee cup) */
+ public static final ImageIcon ICON_JAVA_DEFAULT = SwingUtil.createImageIconFromResourcePath(SwingUtil.class, "resource/icons/small/java_coffee_cup.png", null);
/** Icon of default checkbox with state enabled and checked */
public static final ImageIcon ICON_CHECKBOX_CHECKED = SwingUtil.createImageIconFromResourcePath(SwingUtil.class, "resource/icons/checkbox/checked.png", null);
/** Icon of default checkbox with state enabled and unchecked */
@@ -3211,5 +3224,167 @@
downloadWorker.terminate();
return (File)downloadWorker.getWorkResult();
}
+
+ /**
+ * Configures the current application for use as tray icon. Frame title is used as tray icon tooltip.
+ * @param icon icon used in tray (if {@code null} the frame icon is used if available)
+ * @param menu popup menu for tray icon (can be {@code null})
+ * @param defaultAction action performed on click on tray icon (if {@code null} show frame action is used)
+ * @return {@code null} if tray is not supported or could not be installed
+ */
+ public static TrayIcon configureApplicationInTray(final Frame frame, Image icon, final JPopupMenu menu, ActionListener defaultAction) {
+ // Default Action: show/hide frame
+ if ( defaultAction == null ) {
+ defaultAction = new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ // execute default action of the application
+ boolean visible = true; // !frame.isVisible();
+ frame.setVisible( visible );
+ frame.toFront();
+ }
+ };
+ }
+ // Default Icon: frame icon
+ if ( icon == null )
+ icon = frame.getIconImage();
+ // Title = Dialog title
+ String tooltipTitle = frame.getTitle();
+ return configureApplicationInTray(icon, tooltipTitle, menu, defaultAction);
+
+ }
+
+ /**
+ * Configures the current application for use as tray icon. Dialog title is used as tray icon tooltip.
+ * @param icon icon used in tray (if {@code null} the dialog icon is used if available)
+ * @param menu popup menu for tray icon (can be {@code null})
+ * @param defaultAction action performed on click on tray icon (if {@code null} show dialog action is used)
+ * @return {@code null} if tray is not supported or could not be installed
+ */
+ public static TrayIcon configureApplicationInTray(final Dialog dialog, Image icon, final JPopupMenu menu, ActionListener defaultAction) {
+ // Default Action: show/hide frame
+ if ( defaultAction == null ) {
+ defaultAction = new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ boolean visible = true; // !dialog.isVisible();
+ dialog.setVisible( visible );
+ dialog.toFront();
+ }
+ };
+ }
+ // Default Icon: frame icon
+ if ( icon == null && !dialog.getIconImages().isEmpty() )
+ icon = dialog.getIconImages().get(0);
+ // Title = Dialog title
+ String tooltipTitle = dialog.getTitle();
+ return configureApplicationInTray(icon, tooltipTitle, menu, defaultAction);
+ }
+
+ /**
+ * Configures the current application for use as tray icon. Either {@code menu} or
+ * {@code defaultAction} should be set to handle some action on tray icon.
+ * @param icon icon used in tray (if {@code null} the icon {@link #ICON_JAVA_DEFAULT} is used)
+ * @param tooltipTitle tool tip text to show when mouse moves over tray icon
+ * @param menu popup menu for tray icon (can be {@code null})
+ * @param defaultAction action performed on click on tray icon (can be {@code null})
+ * @return {@code null} if tray is not supported or could not be installed
+ */
+ public static TrayIcon configureApplicationInTray(Image icon, String tooltipTitle, final JPopupMenu menu, final ActionListener defaultAction) {
+ if (!SystemTray.isSupported())
+ return( null );
+
+ if ( icon == null )
+ icon = SwingUtil.ICON_JAVA_DEFAULT.getImage();
+ // get the SystemTray instance
+ SystemTray tray = SystemTray.getSystemTray();
+
+ // construct a TrayIcon
+ TrayIcon trayIcon = new TrayIcon(icon, tooltipTitle);
+ trayIcon.setImageAutoSize(true);
+ if ( menu != null ) {
+// trayIcon.addMouseListener( new PopupMenuListener(menu) ); // does not handle ESC key well!
+ trayIcon.setPopupMenu( transformJMenu(menu) ); // transform JPopupMenu to PopupMenu
+ }
+ // set the TrayIcon properties
+ if ( defaultAction != null )
+ if ( defaultAction instanceof Action )
+ // If listerner is instance of Action pipe event
+ // to provide action's command ID in event
+ trayIcon.addActionListener( new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ e = new ActionEvent(e.getSource(), e.getID(), (String)((Action)defaultAction).getValue(Action.ACTION_COMMAND_KEY));
+ defaultAction.actionPerformed(e);
+ }
+ });
+ else
+ trayIcon.addActionListener( defaultAction );
+
+ // add the tray image
+ try {
+ tray.add(trayIcon);
+ } catch (Exception e) {
+ System.err.println(e);
+ return( null );
+ }
+
+ return( trayIcon );
+ }
+
+ /**
+ * Transforms a {@link JPopupMenu} to a {@link PopupMenu} in a simple way,
+ * by copying all items and separators. The {@link Action} of each new {@link MenuItem} is
+ * piped to the corresponding {@link JMenuItem} action.<br>
+ * <b>Note:</b> As the only property change the enabled/disabled property is piped
+ * from {@link JMenuItem} to corresponding {@link MenuItem}. All other belated property
+ * changes on {@link JMenu} are ignored!
+ */
+ public static PopupMenu transformJMenu(JPopupMenu jMenu) {
+ PopupMenu menu = new PopupMenu( jMenu.getLabel() );
+
+ for (Component c : jMenu.getComponents()) {
+ if ( c instanceof JMenuItem ) {
+ // Create MenuItem from JMenuItem
+ final JMenuItem jMenuItem = (JMenuItem)c;
+ final MenuItem menuItem = new MenuItem();
+ menuItem.setActionCommand((String)jMenuItem.getAction().getValue(Action.ACTION_COMMAND_KEY));
+ menuItem.setEnabled(jMenuItem.isEnabled());
+ menuItem.setFont(jMenuItem.getFont());
+ menuItem.setLabel(jMenuItem.getText());
+ menuItem.setName((String)jMenuItem.getAction().getValue(Action.SHORT_DESCRIPTION));
+ // listener to pipe action from MenuItem to corresponding JMenuItem
+ menuItem.addActionListener( new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ jMenuItem.getAction().actionPerformed( new ActionEvent(
+ jMenuItem,
+ e.getID(),
+ e.getActionCommand()
+ )
+ );
+ }
+ });
+ // Listener to pipe proerty changes from JMenuItem to
+ // corresponding MenuItem
+ jMenuItem.addPropertyChangeListener(new PropertyChangeListener() {
+ @Override
+ public void propertyChange(PropertyChangeEvent evt) {
+// System.out.println( "JMenuItem."+evt.getPropertyName()+ ": "+evt.getOldValue()+" --> "+evt.getNewValue());
+ if ( "enabled".equalsIgnoreCase(evt.getPropertyName()) )
+ menuItem.setEnabled( !menuItem.isEnabled() );
+ }
+ });
+ // Add item to menue
+ menu.add(menuItem);
+ }
+ if ( c instanceof JSeparator )
+ menu.addSeparator();
+ }
+
+ return( menu );
+ }
}
+
+
+
+
Modified: trunk/schmitzm-core/src/main/java/de/schmitzm/swing/event/PopupMenuListener.java
===================================================================
--- trunk/schmitzm-core/src/main/java/de/schmitzm/swing/event/PopupMenuListener.java 2016-02-15 16:40:50 UTC (rev 2420)
+++ trunk/schmitzm-core/src/main/java/de/schmitzm/swing/event/PopupMenuListener.java 2016-06-23 15:50:57 UTC (rev 2421)
@@ -29,7 +29,7 @@
******************************************************************************/
package de.schmitzm.swing.event;
-import java.awt.Component;
+import java.awt.TrayIcon;
import java.awt.event.MouseEvent;
import javax.swing.JPopupMenu;
@@ -61,7 +61,16 @@
*/
protected void checkPopupSignal(MouseEvent e) {
if ( e.isPopupTrigger() ) {
- menu.show( (Component)e.getSource(), e.getX(), e.getY() );
+ if ( e.getSource() instanceof TrayIcon ) {
+ // show(.) method does not work properly on tray icon (e.g.
+ // highlighting of menu items on mouseover works only with
+ // following command sequence)
+ menu.setLocation(e.getX(), e.getY());
+ menu.setInvoker(menu);
+ menu.setVisible(true);
+ } else {
+ menu.show( e.getComponent(), e.getX(), e.getY() );
+ }
e.consume();
}
}
More information about the Schmitzm-commits
mailing list