/* * org.openmicroscopy.shoola.util.ui.colourpicker.TabbedPaneUI * *------------------------------------------------------------------------------ * Copyright (C) 2006-2014 University of Dundee. All rights reserved. * * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * *------------------------------------------------------------------------------ */ package org.openmicroscopy.shoola.util.ui.colourpicker; //Java imports import java.awt.BorderLayout; import java.awt.CardLayout; import java.awt.Dimension; import java.awt.FlowLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.AbstractAction; import javax.swing.Box; import javax.swing.BoxLayout; import javax.swing.JButton; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JSeparator; import javax.swing.JTextField; import javax.swing.JToggleButton; import javax.swing.JToolBar; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; import info.clearthought.layout.TableLayout; //Third-party libraries //Application-internal dependencies import org.openmicroscopy.shoola.util.ui.IconManager; import org.openmicroscopy.shoola.util.ui.UIUtilities; /** * The TabbedPaneUI controls the allows the switching between the different * views in the colour picker. * * @author Jean-Marie Burel      * <a href="mailto:j.burel@dundee.ac.uk">j.burel@dundee.ac.uk</a> * @author Donald MacDonald      * <a href="mailto:donald@lifesci.dundee.ac.uk">donald@lifesci.dundee.ac.uk</a> * @version 3.0 * <small> * (<b>Internal version:</b> $Revision: $ $Date: $) * </small> * @since OME2.2 */ class TabbedPaneUI extends JPanel implements ActionListener, ChangeListener, DocumentListener { /** The number of column of the label displaying the alpha value. */ static final int TEXTBOX_COLUMN = 2; /** Used by card layout to select colour wheel panel. */ private static final String COLOURWHEELPANE = "Color Wheel Pane"; /** Used by card layout to select RGB Slider panel. */ private static final String RGBSLIDERPANE = "RGB Slider Pane"; /** Used by card layout to select swatch panel. */ private static final String SWATCHPANE = "Swatch Pane"; /** Action id to preview the color changes.*/ private static final int PREVIEW = 0; /** Action id to cancel and close the dialog.*/ private static final int CANCEL = 1; /** Action id to accept the color changes.*/ private static final int ACCEPT = 2; /** Action id to revert the color changes.*/ private static final int REVERT = 3; /** * Toolbar contains the buttons to select the HSVWheelUI, RGB Selector * or Colour Swatch. */ private JToolBar toolbar; /** * Actionbar contains the buttons to accept, cancel or revert to the * original colour selection. */ private JPanel userActionPanel; /** Button to choose HSVColourWheelPanel. */ private JToggleButton colourWheelButton; /** Button to choose RGB Sliders panel. */ private JToggleButton RGBSlidersButton; /** Button to choose colour swatch panel. */ private JToggleButton colourSwatchButton; /** Accept the current colour choice. */ private JButton acceptButton; /** Accept the current colour choice. */ private JButton previewButton; /** Revert to the original colour chosen by the user. */ private JButton revertButton; /** Cancel the colour panel. */ private JButton cancelButton; /** The deescrption of the color. */ private JTextField fieldDescription; /** ColourWheel panel, containing the HSVPickerUI. */ private HSVColourWheelUI colourWheelPane; /** RGBPanel containing the ColourSlider UI. */ private RGBSliderUI RGBSliderPane; /** Containing the Swatch UI. */ private ColourSwatchUI swatchPane; /** Layout manager for the colourwheel, slider and swatch panels. */ private CardLayout tabPaneLayout; /** * Container for the layout manager above. Containers colourwheel, slider * and swatch panels. */ private JPanel tabPanel; /** * Paintpot pane will be displayed at the top of the window, above selected * pane and below toolbar. */ private PaintPotUI paintPotPane; /** Model which will be changed when user adjusts sliders/textfield. */ private RGBControl control; /** The owner of this component. */ private ColourPicker parent; /** The original description of the color. */ private String originalDescription; /** Flag indicating that the preview button was clicked.*/ private boolean preview; /** * The toolbar controls which panel is active, the user has the choice * of HSV Colour wheel, RGB Sliders and colour swatches. * Create the toolbar and its buttons, add actions to the buttons and load * the button icons, attach the buttons to the tool bar. */ private void createToolbar() { toolbar = new JToolBar(); IconManager icons = IconManager.getInstance(); colourWheelButton = new JToggleButton( icons.getIcon(IconManager.COLOUR_WHEEL_24)); UIUtilities.unifiedButtonLookAndFeel(colourWheelButton); colourWheelButton.setBorderPainted(true); colourWheelButton.setToolTipText("Show HSV Color Wheel."); AbstractAction action = new AbstractAction("HSV Wheel Color Button") { public void actionPerformed(ActionEvent evt) { clearToggleButtons(); pickWheelPane(); } }; colourWheelButton.addActionListener(action); RGBSlidersButton = new JToggleButton( icons.getIcon(IconManager.COLOUR_SLIDER_24)); UIUtilities.unifiedButtonLookAndFeel(RGBSlidersButton); RGBSlidersButton.setBorderPainted(true); RGBSlidersButton.setToolTipText("Show RGB Color Sliders."); action = new AbstractAction("RGB Slider Button") { public void actionPerformed(ActionEvent evt) { clearToggleButtons(); pickRGBSliderPane(); } }; RGBSlidersButton.addActionListener(action); colourSwatchButton = new JToggleButton( icons.getIcon(IconManager.COLOUR_SWATCH_24)); colourSwatchButton.setToolTipText("Show Color List."); UIUtilities.unifiedButtonLookAndFeel(colourSwatchButton); colourSwatchButton.setBorderPainted(true); action = new AbstractAction("Color Swatch Button") { public void actionPerformed(ActionEvent evt) { clearToggleButtons(); pickSwatchPane(); } }; colourSwatchButton.addActionListener(action); toolbar.setFloatable(false); toolbar.setRollover(true); toolbar.add(colourWheelButton); toolbar.add(RGBSlidersButton); toolbar.add(colourSwatchButton); } /** * The action bar controls if the user wishes to as accept current colour * choice, close the colour picker window or revert to the original colour * selected when the colour picker was loaded. * * Creates action bar, its buttons and load icons. Attach action events * to buttons and buttons to bar. */ private void createActionbar() { userActionPanel = new JPanel(); userActionPanel.setLayout(new FlowLayout()); //accept acceptButton = new JButton("Accept"); acceptButton.setToolTipText("Accept the selected color."); acceptButton.setActionCommand(""+ACCEPT); acceptButton.addActionListener(this); //revert revertButton = new JButton("Revert"); revertButton.setToolTipText("Revert to the original color."); revertButton.setActionCommand(""+REVERT); revertButton.addActionListener(this); //cancel cancelButton = new JButton("Cancel"); cancelButton.setToolTipText("Close the Color Picker."); cancelButton.setActionCommand(""+CANCEL); cancelButton.addActionListener(this); //preview previewButton = new JButton("Preview"); previewButton.setToolTipText("Preview the color change."); previewButton.setActionCommand(""+PREVIEW); previewButton.addActionListener(this); previewButton.setVisible(false); userActionPanel.add(previewButton); userActionPanel.add(acceptButton); userActionPanel.add(revertButton); userActionPanel.add(cancelButton); setButtonsEnabled(false); parent.getRootPane().setDefaultButton(cancelButton); } /** * Creates PaintPotUI, RGB slider panel and HSVWheel panel and Colour * Swatch panel. */ private void createPanels() { colourWheelPane = new HSVColourWheelUI(control); paintPotPane = new PaintPotUI(control.getColour(), control); RGBSliderPane = new RGBSliderUI(control); swatchPane = new ColourSwatchUI(control); } /** * Creates all the UI elements and displays the HSVWheel as active. * * @param field Pass <code>true</code> to add a field, * <code>false</code> otherwise. */ private void createUI(boolean field) { createToolbar(); createActionbar(); createPanels(); JPanel container = new JPanel(); container.setLayout(new BorderLayout()); container.add(toolbar, BorderLayout.WEST); this.setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); add(container); paintPotPane.setPreferredSize(new Dimension(260, 24)); add(Box.createVerticalStrut(5)); add(paintPotPane); add(Box.createVerticalStrut(5)); tabPanel = new JPanel(); tabPaneLayout = new CardLayout(); tabPanel.setLayout(tabPaneLayout); tabPanel.add(colourWheelPane, COLOURWHEELPANE); tabPanel.add(RGBSliderPane, RGBSLIDERPANE); tabPanel.add(swatchPane, SWATCHPANE); add(tabPanel); if (field) { add(new JSeparator()); JLabel label = UIUtilities.setTextFont("Description: "); JPanel p = new JPanel(); double[][] size = {{TableLayout.PREFERRED, TableLayout.FILL}, {TableLayout.PREFERRED}}; p.setLayout(new TableLayout(size)); p.add(label, "0, 0"); fieldDescription = new JTextField(); p.add(fieldDescription, "1, 0"); add(p); } add(userActionPanel); pickSwatchPane(); } /** Clears all buttons. */ private void clearToggleButtons() { colourWheelButton.setSelected(false); RGBSlidersButton.setSelected(false); colourSwatchButton.setSelected(false); } /** Sets Wheelbutton as picked and makes it visible. */ private void pickWheelPane() { colourWheelButton.setSelected(true); colourWheelPane.setActive(true); tabPaneLayout.show(tabPanel,COLOURWHEELPANE); RGBSliderPane.setActive(false); swatchPane.setActive(false); colourWheelPane.findPuck(); colourWheelPane.refresh(); colourWheelPane.repaint(); } /** Sets swatch as picked and makes it visible. */ private void pickSwatchPane() { tabPaneLayout.show(tabPanel,SWATCHPANE); colourSwatchButton.setSelected(true); swatchPane.setActive(true); RGBSliderPane.setActive(false); colourWheelPane.setActive(false); this.doLayout(); swatchPane.refresh(); } /** Sets RGBSlider as picked and makes it visible. */ private void pickRGBSliderPane() { tabPaneLayout.show(tabPanel,RGBSLIDERPANE); RGBSlidersButton.setSelected(true); RGBSliderPane.setActive(true); colourWheelPane.setActive(false); swatchPane.setActive(false); this.doLayout(); RGBSliderPane.refresh(); } /** * Instantiates the tabbed pane, creates the UI and sets the control. * * @param parent The parent of this component. Mustn't be <code>null</code>. * @param control Reference to the control. Mustn't be <code>null</code>. * @param field Pass <code>true</code> to add a field, * <code>false</code> otherwise. */ TabbedPaneUI(ColourPicker parent, RGBControl control, boolean field) { if (parent == null) throw new NullPointerException("No parent."); if (control == null) throw new NullPointerException("No control."); this.parent = parent; this.control = control; createUI(field); this.control.addListener(this); } /** * Sets the enabled flag of the {@link #acceptButton} and * {@link #revertButton}. * * @param enabled The value to set. */ void setButtonsEnabled(boolean enabled) { acceptButton.setEnabled(enabled); revertButton.setEnabled(enabled); previewButton.setEnabled(enabled); if (enabled) parent.getRootPane().setDefaultButton(acceptButton); else parent.getRootPane().setDefaultButton(cancelButton); } /** * Reverts current colour to the original colour choice passed to * Colourpicker. */ void revertAction() { control.revert(); swatchPane.revert(); //Check if preview was if (preview) { preview = false; parent.reset(); } } /** * Returns the description entered if any. * * @return See above. */ String getDescription() { if (fieldDescription == null) return null; String text = fieldDescription.getText(); if (text == null) return null; return text.trim(); } /** * Sets the description associated to the color. * * @param description The value to set. */ void setColorDescription(String description) { if (fieldDescription == null || description == null) return; originalDescription = description; fieldDescription.setText(description); fieldDescription.getDocument().addDocumentListener(this); } /** * Shows or hides the preview button. * * @param visible Pass <code>true</code> to show the preview button, * <code>false</code> otherwise. */ void setPreviewVisible(boolean visible) { previewButton.setVisible(visible); } /** * Listens to ChangeEvent. * @see ChangeListener#stateChanged(ChangeEvent) */ public void stateChanged(ChangeEvent evt) { if (RGBSliderPane != null && RGBSliderPane.isVisible()) RGBSliderPane.refresh(); if (colourWheelPane != null && colourWheelPane.isVisible()) colourWheelPane.refresh(); if (swatchPane != null && swatchPane.isVisible()) swatchPane.refresh(); if (fieldDescription == null) setButtonsEnabled(!control.isOriginalColour()); else { String text = fieldDescription.getText(); setButtonsEnabled(!text.equals(originalDescription) || !control.isOriginalColour()); } } /** * Implemented as specified by {@link DocumentListener} I/F. * @see DocumentListener#insertUpdate(DocumentEvent) */ public void insertUpdate(DocumentEvent e) { if (fieldDescription == null) return; String text = fieldDescription.getText(); setButtonsEnabled(!text.equals(originalDescription) || !control.isOriginalColour()); } /** * Implemented as specified by {@link DocumentListener} I/F. * @see DocumentListener#removeUpdate(DocumentEvent) */ public void removeUpdate(DocumentEvent e) { if (fieldDescription == null) return; String text = fieldDescription.getText(); setButtonsEnabled(!text.equals(originalDescription) || !control.isOriginalColour()); } /** * Reacts to button clicks. * @see ActionListener#actionPerformed(ActionEvent) */ public void actionPerformed(ActionEvent e) { int v = Integer.parseInt(e.getActionCommand()); switch (v) { case CANCEL: parent.cancel(); break; case REVERT: revertAction(); break; case ACCEPT: parent.accept(); break; case PREVIEW: preview = true; parent.preview(); } } /** * Required by the {@link DocumentListener} I/F but no-operation * implementation in our case. * @see DocumentListener#changedUpdate(DocumentEvent) */ public void changedUpdate(DocumentEvent e) {} }