1 /*
   2  * Copyright (c) 2002, 2010, 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.plaf.synth;
  27 
  28 import java.awt.*;
  29 import java.beans.*;
  30 import javax.swing.*;
  31 import javax.swing.plaf.*;
  32 import javax.swing.plaf.basic.*;
  33 import sun.swing.DefaultLookup;
  34 
  35 /**
  36  * Provides the Synth L&F UI delegate for
  37  * {@link javax.swing.JOptionPane}.
  38  *
  39  * @author James Gosling
  40  * @author Scott Violet
  41  * @author Amy Fowler
  42  * @since 1.7
  43  */
  44 public class SynthOptionPaneUI extends BasicOptionPaneUI implements
  45                                 PropertyChangeListener, SynthUI {
  46     private SynthStyle style;
  47 
  48     /**
  49      * Creates a new UI object for the given component.
  50      *
  51      * @param x component to create UI object for
  52      * @return the UI object
  53      */
  54     public static ComponentUI createUI(JComponent x) {
  55         return new SynthOptionPaneUI();
  56     }
  57 
  58     /**
  59      * @inheritDoc
  60      */
  61     @Override
  62     protected void installDefaults() {
  63         updateStyle(optionPane);
  64     }
  65 
  66     /**
  67      * @inheritDoc
  68      */
  69     @Override
  70     protected void installListeners() {
  71         super.installListeners();
  72         optionPane.addPropertyChangeListener(this);
  73     }
  74 
  75     private void updateStyle(JComponent c) {
  76         SynthContext context = getContext(c, ENABLED);
  77         SynthStyle oldStyle = style;
  78 
  79         style = SynthLookAndFeel.updateStyle(context, this);
  80         if (style != oldStyle) {
  81             minimumSize = (Dimension)style.get(context,
  82                                                "OptionPane.minimumSize");
  83             if (minimumSize == null) {
  84                 minimumSize = new Dimension(262, 90);
  85             }
  86             if (oldStyle != null) {
  87                 uninstallKeyboardActions();
  88                 installKeyboardActions();
  89             }
  90         }
  91         context.dispose();
  92     }
  93 
  94     /**
  95      * @inheritDoc
  96      */
  97     @Override
  98     protected void uninstallDefaults() {
  99         SynthContext context = getContext(optionPane, ENABLED);
 100 
 101         style.uninstallDefaults(context);
 102         context.dispose();
 103         style = null;
 104     }
 105 
 106     /**
 107      * @inheritDoc
 108      */
 109     @Override
 110     protected void uninstallListeners() {
 111         super.uninstallListeners();
 112         optionPane.removePropertyChangeListener(this);
 113     }
 114 
 115     /**
 116      * @inheritDoc
 117      */
 118     @Override
 119     protected void installComponents() {
 120         optionPane.add(createMessageArea());
 121 
 122         Container separator = createSeparator();
 123         if (separator != null) {
 124             optionPane.add(separator);
 125             SynthContext context = getContext(optionPane, ENABLED);
 126             optionPane.add(Box.createVerticalStrut(context.getStyle().
 127                        getInt(context, "OptionPane.separatorPadding", 6)));
 128             context.dispose();
 129         }
 130         optionPane.add(createButtonArea());
 131         optionPane.applyComponentOrientation(optionPane.getComponentOrientation());
 132     }
 133 
 134     /**
 135      * @inheritDoc
 136      */
 137     @Override
 138     public SynthContext getContext(JComponent c) {
 139         return getContext(c, getComponentState(c));
 140     }
 141 
 142     private SynthContext getContext(JComponent c, int state) {
 143         return SynthContext.getContext(SynthContext.class, c,
 144                     SynthLookAndFeel.getRegion(c), style, state);
 145     }
 146 
 147     private int getComponentState(JComponent c) {
 148         return SynthLookAndFeel.getComponentState(c);
 149     }
 150 
 151     /**
 152      * Notifies this UI delegate to repaint the specified component.
 153      * This method paints the component background, then calls
 154      * the {@link #paint(SynthContext,Graphics)} method.
 155      *
 156      * <p>In general, this method does not need to be overridden by subclasses.
 157      * All Look and Feel rendering code should reside in the {@code paint} method.
 158      *
 159      * @param g the {@code Graphics} object used for painting
 160      * @param c the component being painted
 161      * @see #paint(SynthContext,Graphics)
 162      */
 163     @Override
 164     public void update(Graphics g, JComponent c) {
 165         SynthContext context = getContext(c);
 166 
 167         SynthLookAndFeel.update(context, g);
 168         context.getPainter().paintOptionPaneBackground(context,
 169                           g, 0, 0, c.getWidth(), c.getHeight());
 170         paint(context, g);
 171         context.dispose();
 172     }
 173 
 174     /**
 175      * Paints the specified component according to the Look and Feel.
 176      * <p>This method is not used by Synth Look and Feel.
 177      * Painting is handled by the {@link #paint(SynthContext,Graphics)} method.
 178      *
 179      * @param g the {@code Graphics} object used for painting
 180      * @param c the component being painted
 181      * @see #paint(SynthContext,Graphics)
 182      */
 183     @Override
 184     public void paint(Graphics g, JComponent c) {
 185         SynthContext context = getContext(c);
 186 
 187         paint(context, g);
 188         context.dispose();
 189     }
 190 
 191     /**
 192      * Paints the specified component. This implementation does nothing.
 193      *
 194      * @param context context for the component being painted
 195      * @param g the {@code Graphics} object used for painting
 196      * @see #update(Graphics,JComponent)
 197      */
 198     protected void paint(SynthContext context, Graphics g) {
 199     }
 200 
 201     /**
 202      * @inheritDoc
 203      */
 204     @Override
 205     public void paintBorder(SynthContext context, Graphics g, int x,
 206                             int y, int w, int h) {
 207         context.getPainter().paintOptionPaneBorder(context, g, x, y, w, h);
 208     }
 209 
 210     /**
 211      * @inheritDoc
 212      */
 213     @Override
 214     public void propertyChange(PropertyChangeEvent e) {
 215         if (SynthLookAndFeel.shouldUpdateStyle(e)) {
 216             updateStyle((JOptionPane)e.getSource());
 217         }
 218     }
 219 
 220     /**
 221      * @inheritDoc
 222      */
 223     @Override
 224     protected boolean getSizeButtonsToSameWidth() {
 225         return DefaultLookup.getBoolean(optionPane, this,
 226                                         "OptionPane.sameSizeButtons", true);
 227     }
 228 
 229     /**
 230      * Called from {@link #installComponents} to create a {@code Container}
 231      * containing the body of the message. The icon is the created by calling
 232      * {@link #addIcon}.
 233      */
 234     @Override
 235     protected Container createMessageArea() {
 236         JPanel top = new JPanel();
 237         top.setName("OptionPane.messageArea");
 238         top.setLayout(new BorderLayout());
 239 
 240         /* Fill the body. */
 241         Container          body = new JPanel(new GridBagLayout());
 242         Container          realBody = new JPanel(new BorderLayout());
 243 
 244         body.setName("OptionPane.body");
 245         realBody.setName("OptionPane.realBody");
 246 
 247         if (getIcon() != null) {
 248             JPanel sep = new JPanel();
 249             sep.setName("OptionPane.separator");
 250             sep.setPreferredSize(new Dimension(15, 1));
 251             realBody.add(sep, BorderLayout.BEFORE_LINE_BEGINS);
 252         }
 253         realBody.add(body, BorderLayout.CENTER);
 254 
 255         GridBagConstraints cons = new GridBagConstraints();
 256         cons.gridx = cons.gridy = 0;
 257         cons.gridwidth = GridBagConstraints.REMAINDER;
 258         cons.gridheight = 1;
 259 
 260         SynthContext context = getContext(optionPane, ENABLED);
 261         cons.anchor = context.getStyle().getInt(context,
 262                       "OptionPane.messageAnchor", GridBagConstraints.CENTER);
 263         context.dispose();
 264 
 265         cons.insets = new Insets(0,0,3,0);
 266 
 267         addMessageComponents(body, cons, getMessage(),
 268                           getMaxCharactersPerLineCount(), false);
 269         top.add(realBody, BorderLayout.CENTER);
 270 
 271         addIcon(top);
 272         return top;
 273     }
 274 
 275     /**
 276      * @inheritDoc
 277      */
 278     @Override
 279     protected Container createSeparator() {
 280         JSeparator separator = new JSeparator(SwingConstants.HORIZONTAL);
 281 
 282         separator.setName("OptionPane.separator");
 283         return separator;
 284     }
 285 }