1 /*
   2  * Copyright (c) 2011, 2012, 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 com.apple.laf;
  27 
  28 import java.awt.*;
  29 
  30 import javax.swing.*;
  31 import javax.swing.plaf.ComponentUI;
  32 import javax.swing.plaf.basic.BasicOptionPaneUI;
  33 
  34 public class AquaOptionPaneUI extends BasicOptionPaneUI {
  35     private static final int kOKCancelButtonWidth = 79;
  36     private static final int kButtonHeight = 23;
  37 
  38     private static final int kDialogSmallPadding = 4;
  39     private static final int kDialogLargePadding = 23;
  40 
  41     /**
  42      * Creates a new BasicOptionPaneUI instance.
  43      */
  44     public static ComponentUI createUI(final JComponent x) {
  45         return new AquaOptionPaneUI();
  46     }
  47 
  48     /**
  49      * Creates and returns a Container containin the buttons. The buttons
  50      * are created by calling <code>getButtons</code>.
  51      */
  52     protected Container createButtonArea() {
  53         final Container bottom = super.createButtonArea();
  54         // Now replace the Layout
  55         bottom.setLayout(new AquaButtonAreaLayout(true, kDialogSmallPadding));
  56         return bottom;
  57     }
  58 
  59     /**
  60      * Messaged from installComponents to create a Container containing the
  61      * body of the message.
  62      * The icon and body should be aligned on their top edges
  63      */
  64     protected Container createMessageArea() {
  65         final JPanel top = new JPanel();
  66         top.setBorder(UIManager.getBorder("OptionPane.messageAreaBorder"));
  67         top.setLayout(new BoxLayout(top, BoxLayout.X_AXIS));
  68 
  69         /* Fill the body. */
  70         final Container body = new JPanel();
  71 
  72         final Icon sideIcon = getIcon();
  73 
  74         if (sideIcon != null) {
  75             final JLabel iconLabel = new JLabel(sideIcon);
  76             iconLabel.setVerticalAlignment(SwingConstants.TOP);
  77 
  78             final JPanel iconPanel = new JPanel();
  79             iconPanel.add(iconLabel);
  80             top.add(iconPanel);
  81             top.add(Box.createHorizontalStrut(kDialogLargePadding));
  82         }
  83 
  84         body.setLayout(new GridBagLayout());
  85         final GridBagConstraints cons = new GridBagConstraints();
  86         cons.gridx = cons.gridy = 0;
  87         cons.gridwidth = GridBagConstraints.REMAINDER;
  88         cons.gridheight = 1;
  89         cons.anchor = GridBagConstraints.WEST;
  90         cons.insets = new Insets(0, 0, 3, 0);
  91 
  92         addMessageComponents(body, cons, getMessage(), getMaxCharactersPerLineCount(), false);
  93         top.add(body);
  94 
  95         return top;
  96     }
  97 
  98     /**
  99      * AquaButtonAreaLayout lays out all
 100      *   components according to the HI Guidelines:
 101      * The most important button is always on the far right
 102      * The group of buttons is on the right for left-to-right,
 103      *         left for right-to-left
 104      * The widths of each component will be set to the largest preferred size width.
 105      *
 106      *
 107      * This inner class is marked &quot;public&quot; due to a compiler bug.
 108      * This class should be treated as a &quot;protected&quot; inner class.
 109      * Instantiate it only within subclasses of BasicOptionPaneUI.
 110      *
 111      * BasicOptionPaneUI expects that its buttons are layed out with
 112      * a subclass of ButtonAreaLayout
 113      */
 114     public static class AquaButtonAreaLayout extends ButtonAreaLayout {
 115         public AquaButtonAreaLayout(final boolean syncAllWidths, final int padding) {
 116             super(true, padding);
 117         }
 118 
 119         public void layoutContainer(final Container container) {
 120             final Component[] children = container.getComponents();
 121             if (children == null || 0 >= children.length) return;
 122 
 123             final int numChildren = children.length;
 124             final int yLocation = container.getInsets().top;
 125 
 126             // Always syncAllWidths - and heights!
 127             final Dimension maxSize = new Dimension(kOKCancelButtonWidth, kButtonHeight);
 128             for (int i = 0; i < numChildren; i++) {
 129                 final Dimension sizes = children[i].getPreferredSize();
 130                 maxSize.width = Math.max(maxSize.width, sizes.width);
 131                 maxSize.height = Math.max(maxSize.height, sizes.height);
 132             }
 133 
 134             // ignore getCentersChildren, because we don't
 135             int xLocation = container.getSize().width - (maxSize.width * numChildren + (numChildren - 1) * padding);
 136             final int xOffset = maxSize.width + padding;
 137 
 138             // most important button (button zero) on far right
 139             for (int i = numChildren - 1; i >= 0; i--) {
 140                 children[i].setBounds(xLocation, yLocation, maxSize.width, maxSize.height);
 141                 xLocation += xOffset;
 142             }
 143         }
 144     }
 145 }