/******************************************************************************* * 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 *******************************************************************************/ // Placed in public domain by Dmitry Olshansky, 2006 package org.weasis.core.ui.editor.image; import java.awt.BorderLayout; import java.awt.Component; import java.util.List; import java.util.UUID; import javax.swing.Icon; import javax.swing.JPanel; import org.weasis.core.api.explorer.ObservableEvent; import org.weasis.core.api.gui.Insertable; import org.weasis.core.api.gui.util.GuiExecutor; import org.weasis.core.api.media.data.MediaElement; import org.weasis.core.api.media.data.MediaSeriesGroup; import org.weasis.core.ui.Messages; import org.weasis.core.ui.docking.UIManager; import org.weasis.core.ui.editor.SeriesViewer; import org.weasis.core.ui.editor.ViewerPluginBuilder; import org.weasis.core.ui.util.Toolbar; import bibliothek.gui.DockStation; import bibliothek.gui.Dockable; import bibliothek.gui.dock.action.view.ActionViewConverter; import bibliothek.gui.dock.action.view.ViewTarget; import bibliothek.gui.dock.common.CLocation; import bibliothek.gui.dock.common.DefaultSingleCDockable; import bibliothek.gui.dock.common.action.CAction; import bibliothek.gui.dock.common.action.CButton; import bibliothek.gui.dock.common.action.core.CommonSimpleButtonAction; import bibliothek.gui.dock.common.action.predefined.CCloseAction; import bibliothek.gui.dock.common.intern.AbstractCDockable; import bibliothek.gui.dock.common.intern.CDockable; import bibliothek.gui.dock.common.intern.CommonDockable; import bibliothek.gui.dock.common.intern.DefaultCommonDockable; import bibliothek.gui.dock.common.mode.ExtendedMode; import bibliothek.gui.dock.control.focus.DefaultFocusRequest; public abstract class ViewerPlugin<E extends MediaElement> extends JPanel implements SeriesViewer<E> { private final String dockableUID; private MediaSeriesGroup groupID; private String pluginName; private final Icon icon; private final String tooltips; private final DefaultSingleCDockable dockable; public ViewerPlugin(String pluginName) { this(null, pluginName, null, null); } public ViewerPlugin(String uid, String pluginName, Icon icon, String tooltips) { setLayout(new BorderLayout()); setName(pluginName); this.pluginName = pluginName; this.icon = icon; this.tooltips = tooltips; this.dockableUID = uid == null ? UUID.randomUUID().toString() : uid; this.dockable = new DefaultSingleCDockable(dockableUID, icon, pluginName); this.dockable.setTitleText(pluginName); this.dockable.setTitleToolTip(tooltips); this.dockable.setTitleIcon(icon); this.dockable.setFocusComponent(this); this.dockable.setStackable(true); this.dockable.setSingleTabShown(true); this.dockable.putAction(CDockable.ACTION_KEY_CLOSE, new CCloseAction(UIManager.DOCKING_CONTROL) { @Override public void close(CDockable dockable) { super.close(dockable); if (dockable.getFocusComponent() instanceof SeriesViewer) { ((SeriesViewer) dockable.getFocusComponent()).close(); } Dockable prevDockable = UIManager.DOCKING_CONTROL.getController().getFocusHistory() .getNewestOn(dockable.getWorkingArea().getStation()); if (prevDockable == null) { handleFocusAfterClosing(); } else { if (prevDockable instanceof DefaultCommonDockable) { CDockable ld = ((DefaultCommonDockable) prevDockable).getDockable(); if (ld instanceof AbstractCDockable) { ((AbstractCDockable) ld).toFront(); } } } } }); this.dockable.setCloseable(true); this.dockable.setMinimizable(false); this.dockable.setExternalizable(false); this.dockable.addAction(new CloseOthersAction(dockable, false)); this.dockable.addAction(new CloseOthersAction(dockable, true)); } @Override public MediaSeriesGroup getGroupID() { return groupID; } public void setGroupID(MediaSeriesGroup groupID) { this.groupID = groupID; } @Override public String getPluginName() { return pluginName; } public Icon getIcon() { return icon; } public String getTooltips() { return tooltips; } @Override public String getDockableUID() { return dockableUID; } public void setPluginName(String pluginName) { this.pluginName = pluginName; this.dockable.setTitleText(pluginName); } public void setSelectedAndGetFocus() { UIManager.DOCKING_CONTROL.getController() .setFocusedDockable(new DefaultFocusRequest(dockable.intern(), this, false, true, false)); } public void handleFocusAfterClosing() { int size = UIManager.VIEWER_PLUGINS.size(); if (size > 0) { ViewerPlugin<?> lp = UIManager.VIEWER_PLUGINS.get(size - 1); if (lp != null) { lp.dockable.toFront(); } } else { ViewerPluginBuilder.DefaultDataModel.firePropertyChange(new ObservableEvent( ObservableEvent.BasicAction.NULL_SELECTION, ViewerPlugin.this, null, null)); } } @Override public void close() { GuiExecutor.instance().execute(() -> { UIManager.VIEWER_PLUGINS.remove(ViewerPlugin.this); UIManager.DOCKING_CONTROL.removeDockable(dockable); }); } public Component getComponent() { return this; } public final DefaultSingleCDockable getDockable() { return dockable; } public void showDockable() { GuiExecutor.instance().execute(() -> { if (!dockable.isVisible()) { if (!UIManager.VIEWER_PLUGINS.contains(ViewerPlugin.this)) { UIManager.VIEWER_PLUGINS.add(ViewerPlugin.this); } dockable.add(getComponent()); dockable.setFocusComponent(ViewerPlugin.this); UIManager.MAIN_AREA.add(getDockable()); dockable.setDefaultLocation(ExtendedMode.NORMALIZED, CLocation.working(UIManager.MAIN_AREA).stack()); dockable.setVisible(true); } }); } public ViewerToolBar getViewerToolBar() { List<Toolbar> bars = getToolBar(); if (bars != null) { synchronized (bars) { for (Insertable t : bars) { if (t instanceof ViewerToolBar) { return (ViewerToolBar) t; } } } } return null; } private static class CloseOthersAction extends CButton { private CDockable dockable; private boolean closeAll; public CloseOthersAction(CDockable dockable, boolean closeAll) { // prevent standard initialization of the action by calling the protected constructor super(null); // initialize with a modified action init(new MenuOnlySimpleAction(this)); this.dockable = dockable; this.closeAll = closeAll; setText(closeAll ? Messages.getString("ViewerPlugin.close_all") //$NON-NLS-1$ : Messages.getString("ViewerPlugin.close_other")); //$NON-NLS-1$ } @Override protected void action() { super.action(); // We need to access the Core API to find out which other Dockables exist. DockStation parent = dockable.intern().getDockParent(); // Because closing a Dockable may remove the parent DockStation, we first collect all the // Dockables we may later close Dockable[] children = new Dockable[parent.getDockableCount()]; for (int i = 0; i < children.length; i++) { children[i] = parent.getDockable(i); } for (Dockable child : children) { // we are not interested in things like entire stacks, or our own Dockable. So let's do // some checks before closing a Dockable if (child instanceof CommonDockable) { CDockable cChild = ((CommonDockable) child).getDockable(); if (cChild.isCloseable() && (closeAll || cChild != dockable)) { if (cChild.getFocusComponent() instanceof SeriesViewer) { ((SeriesViewer) cChild.getFocusComponent()).close(); } else { cChild.setVisible(false); } } } } } } private static class MenuOnlySimpleAction extends CommonSimpleButtonAction { public MenuOnlySimpleAction(CAction action) { super(action); } @Override public <V> V createView(ViewTarget<V> target, ActionViewConverter converter, Dockable dockable) { // This method creates the view (e.g. a JMenuItem) for this DockAction. Since we do not want // to show it up everywhere, we just ignore some places (targets). if (ViewTarget.TITLE == target) { return null; } return super.createView(target, converter, dockable); } } }