1 /*
   2  * Copyright (c) 2008, 2014, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package javax.swing.colorchooser;
  27 
  28 import java.awt.Color;
  29 import java.awt.Component;
  30 import java.awt.Container;
  31 import java.awt.GridBagConstraints;
  32 import java.awt.GridBagLayout;
  33 import java.beans.PropertyChangeEvent;
  34 import java.beans.PropertyChangeListener;
  35 import javax.swing.Icon;
  36 import javax.swing.JComponent;
  37 import javax.swing.JFormattedTextField;
  38 import javax.swing.JLabel;
  39 import javax.swing.SwingConstants;
  40 
  41 @SuppressWarnings("serial") // Superclass is not serializable across versions
  42 final class ColorChooserPanel extends AbstractColorChooserPanel implements PropertyChangeListener {
  43     private static final int MASK = 0xFF000000;
  44     private final ColorModel model;
  45     private final ColorPanel panel;
  46     private final DiagramComponent slider;
  47     private final DiagramComponent diagram;
  48     private final JFormattedTextField text;
  49     private final JLabel label;
  50 
  51     ColorChooserPanel(ColorModel model) {
  52         this.model = model;
  53         this.panel = new ColorPanel(this.model);
  54         this.slider = new DiagramComponent(this.panel, false);
  55         this.diagram = new DiagramComponent(this.panel, true);
  56         this.text = new JFormattedTextField();
  57         this.label = new JLabel(null, null, SwingConstants.RIGHT);
  58         ValueFormatter.init(6, true, this.text);
  59     }
  60 
  61     @Override
  62     public void setEnabled(boolean enabled) {
  63         super.setEnabled(enabled);
  64         setEnabled(this, enabled);
  65     }
  66 
  67     private static void setEnabled(Container container, boolean enabled) {
  68         for (Component component : container.getComponents()) {
  69             component.setEnabled(enabled);
  70             if (component instanceof Container) {
  71                 setEnabled((Container) component, enabled);
  72             }
  73         }
  74     }
  75 
  76     @Override
  77     public void updateChooser() {
  78         Color color = getColorFromModel();
  79         if (color != null) {
  80             this.panel.setColor(color);
  81             this.text.setValue(Integer.valueOf(color.getRGB()));
  82             this.slider.repaint();
  83             this.diagram.repaint();
  84         }
  85     }
  86 
  87     @Override
  88     protected void buildChooser() {
  89         if (0 == getComponentCount()) {
  90             setLayout(new GridBagLayout());
  91 
  92             GridBagConstraints gbc = new GridBagConstraints();
  93 
  94             gbc.gridx = 3;
  95             gbc.gridwidth = 2;
  96             gbc.weighty = 1.0;
  97             gbc.anchor = GridBagConstraints.NORTH;
  98             gbc.fill = GridBagConstraints.HORIZONTAL;
  99             gbc.insets.top = 10;
 100             gbc.insets.right = 10;
 101             add(this.panel, gbc);
 102 
 103             gbc.gridwidth = 1;
 104             gbc.weightx = 1.0;
 105             gbc.weighty = 0.0;
 106             gbc.anchor = GridBagConstraints.CENTER;
 107             gbc.insets.right = 5;
 108             gbc.insets.bottom = 10;
 109             add(this.label, gbc);
 110 
 111             gbc.gridx = 4;
 112             gbc.weightx = 0.0;
 113             gbc.insets.right = 10;
 114             add(this.text, gbc);
 115 
 116             gbc.gridx = 2;
 117             gbc.gridheight = 2;
 118             gbc.anchor = GridBagConstraints.NORTH;
 119             gbc.ipadx = this.text.getPreferredSize().height;
 120             gbc.ipady = getPreferredSize().height;
 121             add(this.slider, gbc);
 122 
 123             gbc.gridx = 1;
 124             gbc.insets.left = 10;
 125             gbc.ipadx = gbc.ipady;
 126             add(this.diagram, gbc);
 127 
 128             this.label.setLabelFor(this.text);
 129             this.text.addPropertyChangeListener("value", this); // NON-NLS: the property name
 130             this.slider.setBorder(this.text.getBorder());
 131             this.diagram.setBorder(this.text.getBorder());
 132 
 133             setInheritsPopupMenu(this, true); // CR:4966112
 134         }
 135         String label = this.model.getText(this, "HexCode"); // NON-NLS: suffix
 136         boolean visible = label != null;
 137         this.text.setVisible(visible);
 138         this.text.getAccessibleContext().setAccessibleDescription(label);
 139         this.label.setVisible(visible);
 140         if (visible) {
 141             this.label.setText(label);
 142             int mnemonic = this.model.getInteger(this, "HexCodeMnemonic"); // NON-NLS: suffix
 143             if (mnemonic > 0) {
 144                 this.label.setDisplayedMnemonic(mnemonic);
 145                 mnemonic = this.model.getInteger(this, "HexCodeMnemonicIndex"); // NON-NLS: suffix
 146                 if (mnemonic >= 0) {
 147                     this.label.setDisplayedMnemonicIndex(mnemonic);
 148                 }
 149             }
 150         }
 151         this.panel.buildPanel();
 152     }
 153 
 154     @Override
 155     public String getDisplayName() {
 156         return this.model.getText(this, "Name"); // NON-NLS: suffix
 157     }
 158 
 159     @Override
 160     public int getMnemonic() {
 161         return this.model.getInteger(this, "Mnemonic"); // NON-NLS: suffix
 162     }
 163 
 164     @Override
 165     public int getDisplayedMnemonicIndex() {
 166         return this.model.getInteger(this, "DisplayedMnemonicIndex"); // NON-NLS: suffix
 167     }
 168 
 169     @Override
 170     public Icon getSmallDisplayIcon() {
 171         return null;
 172     }
 173 
 174     @Override
 175     public Icon getLargeDisplayIcon() {
 176         return null;
 177     }
 178 
 179     public void propertyChange(PropertyChangeEvent event) {
 180         ColorSelectionModel model = getColorSelectionModel();
 181         if (model != null) {
 182             Object object = event.getNewValue();
 183             if (object instanceof Integer) {
 184                 int value = MASK & model.getSelectedColor().getRGB() | (Integer) object;
 185                 model.setSelectedColor(new Color(value, true));
 186             }
 187         }
 188         this.text.selectAll();
 189     }
 190 
 191     /**
 192      * Allows to show context popup for all components recursively.
 193      *
 194      * @param component  the root component of the tree
 195      * @param value      whether or not the popup menu is inherited
 196      */
 197     private static void setInheritsPopupMenu(JComponent component, boolean value) {
 198         component.setInheritsPopupMenu(value);
 199         for (Object object : component.getComponents()) {
 200             if (object instanceof JComponent) {
 201                 setInheritsPopupMenu((JComponent) object, value);
 202             }
 203         }
 204     }
 205 }