package com.vistatec.ocelot.tm.gui; import java.awt.Component; import java.awt.Dimension; import java.awt.SystemColor; import java.awt.Toolkit; import java.awt.Window; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JTabbedPane; import javax.swing.SwingUtilities; import com.vistatec.ocelot.Ocelot; import com.vistatec.ocelot.tm.gui.constants.TmIconsConst; import com.vistatec.ocelot.tm.gui.match.TmGuiMatchController; /** * Detachable panel displayed on top of Ocelot frame. It provides methods for * getting either the attached or the detached panel. A pin button is displayed * in the panel, triggering the attach/detach actions. When the detached panel * is visible (in a separated window), the panel returns to the attached mode by * either pressing the pin button or closing the window. */ public abstract class AbstractDetachableTmPanel implements DetachableComponent, ActionListener { /** The TM panel. */ protected Component panel; /** The window where the panel is displayed when in detached state. */ protected Window window; /** The original panel container. In case of TM panel, it is a Split Pane. */ protected Component panelContainer; protected TmGuiMatchController controller; /** The pin button. This is the button firing the attach/detach events. */ private JButton btnPin; /** * Constructor. * * @param controller * the tm match controller */ public AbstractDetachableTmPanel(final TmGuiMatchController controller) { this.controller = controller; } /** * Manages the pin button pressed event. * * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent) */ @Override public void actionPerformed(ActionEvent e) { if (e.getSource().equals(btnPin)) { attachDetachEvent(); } } /** * Manages the attach/detach event. If the window is currently * <code>null</code>, then it is a "detach" request; otherwise it is an * "attach" event. */ private void attachDetachEvent() { if (window == null) { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { detach(); } }); } else { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { attach(); } }); } } /** * Gets the pin component. * * @return the pin component, firing the attach/detach events. */ protected Component getPinComponent() { if (btnPin == null) { Toolkit kit = Toolkit.getDefaultToolkit(); ImageIcon icon = new ImageIcon(kit.createImage(Ocelot.class .getResource(TmIconsConst.PIN_ICO))); btnPin = new JButton(icon); btnPin.addActionListener(this); btnPin.setToolTipText("Detach"); final Dimension dim = new Dimension(16, 16); btnPin.setPreferredSize(dim); btnPin.setMaximumSize(dim); btnPin.setMinimumSize(dim); btnPin.setOpaque(false); btnPin.setBorder(null); btnPin.setBackground(SystemColor.control); } return btnPin; } /** * Detaches the component: creates a window and displays the component * inside the new window. The original container does no longer contain the * component. */ private void detach() { window = getDetachedComponent(); window.setVisible(true); panelContainer.repaint(); } /** * Attaches the component: the component window is closed. The component is * added to the original container. */ private void attach() { ((JTabbedPane) panelContainer).add(panel); window.setVisible(false); window.dispose(); window = null; panelContainer.repaint(); } /** * Builds the panel being the attachable/detachable component. */ protected abstract void makePanel(); /** * Builds the window displaying the detached component. */ protected abstract void makeWindow(); /* * (non-Javadoc) * * @see * com.vistatec.ocelot.tm.gui.DetachableComponent#getAttachedComponent() */ @Override public Component getAttachedComponent() { if (panel == null) { makePanel(); } return panel; } /* * (non-Javadoc) * * @see * com.vistatec.ocelot.tm.gui.DetachableComponent#getDetachedComponent() */ @Override public Window getDetachedComponent() { if (window == null) { makeWindow(); window.addWindowListener(new WindowAdapter() { @Override public void windowClosing(WindowEvent e) { attach(); } }); Window mainFrame = SwingUtilities.getWindowAncestor(panel); window.setIconImages(mainFrame.getIconImages()); panelContainer = panel.getParent(); window.add(panel); window.setLocationRelativeTo(mainFrame); window.pack(); } return window; } }