/*******************************************************************************
* Copyright (c) 2016 Weasis Team and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Nicolas Roduit - initial API and implementation
*******************************************************************************/
package org.weasis.core.ui.editor.image;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.InputEvent;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import javax.swing.AbstractButton;
import javax.swing.Box;
import javax.swing.ButtonGroup;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JMenu;
import javax.swing.JPopupMenu;
import javax.swing.JRadioButtonMenuItem;
import javax.swing.KeyStroke;
import javax.swing.UIManager;
import javax.swing.event.ListDataEvent;
import org.weasis.core.api.gui.util.ActionState;
import org.weasis.core.api.gui.util.ActionW;
import org.weasis.core.api.gui.util.ComboItemListener;
import org.weasis.core.api.gui.util.DropButtonIcon;
import org.weasis.core.api.gui.util.DropDownButton;
import org.weasis.core.api.gui.util.GroupPopup;
import org.weasis.core.api.gui.util.GroupRadioMenu;
import org.weasis.core.api.media.data.ImageElement;
import org.weasis.core.api.service.WProperties;
import org.weasis.core.ui.Messages;
import org.weasis.core.ui.util.WtoolBar;
public class ViewerToolBar<E extends ImageElement> extends WtoolBar implements ActionListener {
public static final List<ActionW> actionsButtons = Collections.synchronizedList(new ArrayList<>(Arrays
.asList(new ActionW[] { ActionW.PAN, ActionW.WINLEVEL, ActionW.SCROLL_SERIES, ActionW.ZOOM, ActionW.ROTATION,
ActionW.MEASURE, ActionW.DRAW, ActionW.CONTEXTMENU, ActionW.CROSSHAIR, ActionW.NO_ACTION })));
public static final ActionW[] actionsScroll =
{ ActionW.SCROLL_SERIES, ActionW.ZOOM, ActionW.ROTATION, ActionW.NO_ACTION };
public static final Icon MouseLeftIcon =
new ImageIcon(MouseActions.class.getResource("/icon/32x32/mouse-left.png")); //$NON-NLS-1$
public static final Icon MouseRightIcon =
new ImageIcon(MouseActions.class.getResource("/icon/32x32/mouse-right.png")); //$NON-NLS-1$
public static final Icon MouseMiddleIcon =
new ImageIcon(MouseActions.class.getResource("/icon/32x32/mouse-middle.png")); //$NON-NLS-1$
public static final Icon MouseWheelIcon =
new ImageIcon(MouseActions.class.getResource("/icon/32x32/mouse-wheel.png")); //$NON-NLS-1$
protected final ImageViewerEventManager<E> eventManager;
private final DropDownButton mouseLeft;
private final DropDownButton mouseMiddle;
private final DropDownButton mouseRight;
private final DropDownButton mouseWheel;
private final DropDownButton synchButton;
public ViewerToolBar(final ImageViewerEventManager<E> eventManager, int activeMouse, WProperties props, int index) {
super(Messages.getString("ViewerToolBar.title"), index); //$NON-NLS-1$
if (eventManager == null) {
throw new IllegalArgumentException("EventManager cannot be null"); //$NON-NLS-1$
}
this.eventManager = eventManager;
MouseActions actions = eventManager.getMouseActions();
if ((activeMouse & InputEvent.BUTTON1_DOWN_MASK) == InputEvent.BUTTON1_DOWN_MASK) {
mouseLeft = buildMouseButton(actions, MouseActions.LEFT);
mouseLeft.setToolTipText(
Messages.getString("ViewerToolBar.change") + " " + Messages.getString("ViewerToolBar.m_action")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
add(mouseLeft);
} else {
mouseLeft = null;
}
if ((activeMouse & InputEvent.BUTTON2_DOWN_MASK) == InputEvent.BUTTON2_DOWN_MASK) {
mouseMiddle = buildMouseButton(actions, MouseActions.MIDDLE);
add(mouseMiddle);
} else {
mouseMiddle = null;
}
if ((activeMouse & InputEvent.BUTTON3_DOWN_MASK) == InputEvent.BUTTON3_DOWN_MASK) {
mouseRight = buildMouseButton(actions, MouseActions.RIGHT);
add(mouseRight);
} else {
mouseRight = null;
}
if ((activeMouse & MouseActions.SCROLL_MASK) == MouseActions.SCROLL_MASK) {
mouseWheel = new DropDownButton(MouseActions.WHEEL,
buildMouseIcon(MouseActions.WHEEL, actions.getAction(MouseActions.WHEEL))) {
@Override
protected JPopupMenu getPopupMenu() {
return getPopupMenuScroll(this);
}
};
mouseWheel.setToolTipText(Messages.getString("ViewerToolBar.change")); //$NON-NLS-1$
add(mouseWheel);
} else {
mouseWheel = null;
}
if (activeMouse > 1) {
addSeparator(WtoolBar.SEPARATOR_2x24);
}
if (props.getBooleanProperty("weasis.toolbar.layoutbouton", true)) { //$NON-NLS-1$
final DropDownButton layout =
new DropDownButton("layout", new DropButtonIcon(new ImageIcon(MouseActions.class //$NON-NLS-1$
.getResource("/icon/32x32/layout.png")))) { //$NON-NLS-1$
@Override
protected JPopupMenu getPopupMenu() {
return getLayoutPopupMenuButton(this);
}
};
layout.setToolTipText(Messages.getString("ViewerToolBar.layout")); //$NON-NLS-1$
add(layout);
}
if (props.getBooleanProperty("weasis.toolbar.synchbouton", true)) { //$NON-NLS-1$
add(Box.createRigidArea(new Dimension(5, 0)));
synchButton = buildSynchButton();
add(synchButton);
} else {
synchButton = null;
}
if (props.getBooleanProperty("weasis.toolbar.reset", true)) { //$NON-NLS-1$
final JButton resetButton = new JButton();
resetButton.setToolTipText(Messages.getString("ViewerToolBar.disReset")); //$NON-NLS-1$
resetButton.setIcon(new ImageIcon(WtoolBar.class.getResource("/icon/32x32/reset.png"))); //$NON-NLS-1$
resetButton.addActionListener(e -> eventManager.resetDisplay());
ActionState layout = eventManager.getAction(ActionW.RESET);
if (layout != null) {
layout.registerActionState(resetButton);
}
add(resetButton);
}
}
private DropDownButton buildMouseButton(MouseActions actions, String actionLabel) {
String action = actions.getAction(actionLabel);
final DropDownButton button = new DropDownButton(actionLabel, buildMouseIcon(actionLabel, action)) {
@Override
protected JPopupMenu getPopupMenu() {
return getPopupMenuButton(this);
}
};
button.setActionCommand(action);
button.setToolTipText(Messages.getString("ViewerToolBar.change")); //$NON-NLS-1$
return button;
}
public DropDownButton getMouseLeft() {
return mouseLeft;
}
private JPopupMenu getLayoutPopupMenuButton(DropDownButton dropDownButton) {
ActionState layout = eventManager.getAction(ActionW.LAYOUT);
JPopupMenu popupMouseButtons = new JPopupMenu();
if (layout instanceof ComboItemListener) {
JMenu menu = ((ComboItemListener) layout).createUnregisteredRadioMenu("layout"); //$NON-NLS-1$
popupMouseButtons.setInvoker(dropDownButton);
Component[] cps = menu.getMenuComponents();
for (int i = 0; i < cps.length; i++) {
popupMouseButtons.add(cps[i]);
}
}
return popupMouseButtons;
}
public void removeMouseAction(ActionW action) {
if (action != null) {
actionsButtons.remove(action);
String cmd = action.cmd();
MouseActions actions = eventManager.getMouseActions();
if (cmd.equals(mouseLeft.getActionCommand())) {
ActionW last = actionsButtons.get(0);
actions.setAction(MouseActions.LEFT, last.cmd());
changeButtonState(MouseActions.LEFT, last.cmd());
}
}
}
private JPopupMenu getPopupMenuButton(DropDownButton dropButton) {
String type = dropButton.getType();
String action = eventManager.getMouseActions().getAction(type);
JPopupMenu popupMouseButtons = new JPopupMenu(type);
popupMouseButtons.setInvoker(dropButton);
ButtonGroup groupButtons = new ButtonGroup();
synchronized (actionsButtons) {
for (int i = 0; i < actionsButtons.size(); i++) {
ActionW b = actionsButtons.get(i);
if (eventManager.isActionRegistered(b)) {
JRadioButtonMenuItem radio =
new JRadioButtonMenuItem(b.getTitle(), b.getIcon(), b.cmd().equals(action));
radio.setActionCommand(b.cmd());
radio.addActionListener(this);
if (MouseActions.LEFT.equals(type)) {
radio.setAccelerator(KeyStroke.getKeyStroke(b.getKeyCode(), b.getModifier()));
}
popupMouseButtons.add(radio);
groupButtons.add(radio);
}
}
}
return popupMouseButtons;
}
private JPopupMenu getPopupMenuScroll(DropDownButton dropButton) {
String type = dropButton.getType();
String action = eventManager.getMouseActions().getAction(type);
JPopupMenu popupMouseScroll = new JPopupMenu(type);
popupMouseScroll.setInvoker(dropButton);
ButtonGroup groupButtons = new ButtonGroup();
for (int i = 0; i < actionsScroll.length; i++) {
if (eventManager.isActionRegistered(actionsScroll[i])) {
JRadioButtonMenuItem radio = new JRadioButtonMenuItem(actionsScroll[i].getTitle(),
actionsScroll[i].getIcon(), actionsScroll[i].cmd().equals(action));
radio.setActionCommand(actionsScroll[i].cmd());
radio.addActionListener(this);
popupMouseScroll.add(radio);
groupButtons.add(radio);
}
}
return popupMouseScroll;
}
@Override
public void actionPerformed(ActionEvent e) {
if (e.getSource() instanceof JRadioButtonMenuItem) {
JRadioButtonMenuItem item = (JRadioButtonMenuItem) e.getSource();
if (item.getParent() instanceof JPopupMenu) {
JPopupMenu pop = (JPopupMenu) item.getParent();
MouseActions mouseActions = eventManager.getMouseActions();
mouseActions.setAction(pop.getLabel(), item.getActionCommand());
ImageViewerPlugin<E> view = eventManager.getSelectedView2dContainer();
if (view != null) {
view.setMouseActions(mouseActions);
}
if (pop.getInvoker() instanceof DropDownButton) {
changeButtonState(pop.getLabel(), item.getActionCommand());
}
}
}
}
public boolean isCommandActive(String cmd) {
int active = eventManager.getMouseActions().getActiveButtons();
return cmd != null && checkButtonCommand(cmd, mouseLeft)
|| (((active & InputEvent.BUTTON2_DOWN_MASK) == InputEvent.BUTTON2_DOWN_MASK)
&& checkButtonCommand(cmd, mouseMiddle))
|| (((active & InputEvent.BUTTON3_DOWN_MASK) == InputEvent.BUTTON3_DOWN_MASK)
&& checkButtonCommand(cmd, mouseRight));
}
private static boolean checkButtonCommand(String cmd, JButton button) {
return (button == null) ? false : cmd.equals(button.getActionCommand());
}
public void changeButtonState(String type, String action) {
DropDownButton button = getDropDownButton(type);
if (button != null) {
Icon icon = buildMouseIcon(type, action);
button.setIcon(icon);
button.setActionCommand(action);
}
}
private Icon buildMouseIcon(String type, String action) {
final Icon mouseIcon = getMouseIcon(type);
ActionW actionW = getAction(actionsButtons, action);
final Icon smallIcon = actionW == null ? ActionW.NO_ACTION.getIcon() : actionW.getIcon();
return new DropButtonIcon(new Icon() {
@Override
public void paintIcon(Component c, Graphics g, int x, int y) {
if (c instanceof AbstractButton) {
AbstractButton model = (AbstractButton) c;
Icon icon = null;
if (!model.isEnabled()) {
icon = UIManager.getLookAndFeel().getDisabledIcon(model, mouseIcon);
}
if (icon == null) {
icon = mouseIcon;
}
icon.paintIcon(c, g, x, y);
if (smallIcon != null) {
Icon sIcon = null;
if (!model.isEnabled()) {
sIcon = UIManager.getLookAndFeel().getDisabledIcon(model, smallIcon);
}
if (sIcon == null) {
sIcon = smallIcon;
}
int sx = x + mouseIcon.getIconWidth() - sIcon.getIconWidth();
int sy = y + mouseIcon.getIconHeight() - sIcon.getIconHeight();
sIcon.paintIcon(c, g, sx, sy);
}
}
}
@Override
public int getIconWidth() {
return mouseIcon.getIconWidth();
}
@Override
public int getIconHeight() {
return mouseIcon.getIconHeight();
}
});
}
private DropDownButton buildSynchButton() {
GroupPopup menu = null;
ActionState synch = eventManager.getAction(ActionW.SYNCH);
SynchView synchView = SynchView.DEFAULT_STACK;
if (synch instanceof ComboItemListener) {
ComboItemListener m = (ComboItemListener) synch;
Object sel = m.getSelectedItem();
if (sel instanceof SynchView) {
synchView = (SynchView) sel;
}
menu = new SynchGroupMenu();
m.registerActionState(menu);
}
final DropDownButton button = new DropDownButton(ActionW.SYNCH.cmd(), buildSynchIcon(synchView), menu) {
@Override
protected JPopupMenu getPopupMenu() {
JPopupMenu menu = (getMenuModel() == null) ? new JPopupMenu() : getMenuModel().createJPopupMenu();
menu.setInvoker(this);
return menu;
}
};
button.setToolTipText(Messages.getString("ViewerToolBar.synch")); //$NON-NLS-1$
if (synch != null) {
synch.registerActionState(button);
}
return button;
}
private static Icon buildSynchIcon(SynchView synch) {
final Icon mouseIcon = new ImageIcon(MouseActions.class.getResource("/icon/32x32/synch.png")); //$NON-NLS-1$
final Icon smallIcon = synch.getIcon();
return new DropButtonIcon(new Icon() {
@Override
public void paintIcon(Component c, Graphics g, int x, int y) {
if (c instanceof AbstractButton) {
AbstractButton model = (AbstractButton) c;
Icon icon = null;
if (!model.isEnabled()) {
icon = UIManager.getLookAndFeel().getDisabledIcon(model, mouseIcon);
}
if (icon == null) {
icon = mouseIcon;
}
if (smallIcon != null) {
Icon sIcon = null;
if (!model.isEnabled()) {
sIcon = UIManager.getLookAndFeel().getDisabledIcon(model, smallIcon);
}
if (sIcon == null) {
sIcon = smallIcon;
}
int x2 = x + mouseIcon.getIconWidth() / 2 - sIcon.getIconWidth() / 2;
int y2 = y + mouseIcon.getIconHeight() / 2 - sIcon.getIconHeight() / 2;
sIcon.paintIcon(c, g, x2, y2);
}
icon.paintIcon(c, g, x, y);
}
}
@Override
public int getIconWidth() {
return mouseIcon.getIconWidth();
}
@Override
public int getIconHeight() {
return mouseIcon.getIconHeight();
}
});
}
public DropDownButton getDropDownButton(String type) {
if (MouseActions.LEFT.equals(type)) {
return mouseLeft;
} else if (MouseActions.RIGHT.equals(type)) {
return mouseRight;
} else if (MouseActions.MIDDLE.equals(type)) {
return mouseMiddle;
} else if (MouseActions.WHEEL.equals(type)) {
return mouseWheel;
}
return null;
}
public ActionW getAction(List<ActionW> buttons, String command) {
if (buttons != null) {
synchronized (buttons) {
for (ActionW a : buttons) {
if (a.cmd().equals(command)) {
return a;
}
}
}
}
return null;
}
private static Icon getMouseIcon(String type) {
if (MouseActions.LEFT.equals(type)) {
return MouseLeftIcon;
} else if (MouseActions.RIGHT.equals(type)) {
return MouseRightIcon;
} else if (MouseActions.MIDDLE.equals(type)) {
return MouseMiddleIcon;
} else if (MouseActions.WHEEL.equals(type)) {
return MouseWheelIcon;
}
return MouseLeftIcon;
}
public static final ActionW getNextCommand(List<ActionW> buttons, String command) {
if (buttons != null && !buttons.isEmpty()) {
int index = 0;
synchronized (buttons) {
for (int i = 0; i < buttons.size(); i++) {
ActionW b = buttons.get(i);
if (b.cmd().equals(command)) {
index = (i == buttons.size() - 1) ? 0 : i + 1;
break;
}
}
return buttons.get(index);
}
}
return null;
}
class SynchGroupMenu extends GroupRadioMenu<SynchView> {
@Override
public void contentsChanged(ListDataEvent e) {
super.contentsChanged(e);
changeButtonState();
}
public void changeButtonState() {
Object sel = dataModel.getSelectedItem();
if (sel instanceof SynchView && synchButton != null) {
Icon icon = buildSynchIcon((SynchView) sel);
synchButton.setIcon(icon);
synchButton.setActionCommand(sel.toString());
}
}
}
}