View Javadoc
1   /*
2    * Copyright (c) 2011, 2013, 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.Insets;
29  import java.util.*;
30  
31  import javax.swing.*;
32  import javax.swing.border.Border;
33  
34  import apple.laf.JRSUIConstants.*;
35  
36  import com.apple.laf.AquaUtilControlSize.*;
37  import com.apple.laf.AquaUtils.RecyclableSingleton;
38  
39  /**
40   * All the "magic numbers" in this class should go away once
41   * <rdar://problem/4613866> "default font" and sizes for controls in Java Aqua Look and Feel
42   * has been addressed, and we can cull widget metrics from the native system.
43   */
44  public class AquaButtonExtendedTypes {
45      protected static Border getBorderForPosition(final AbstractButton c, final Object type, final Object logicalPosition) {
46          final String name = (logicalPosition == null ? (String)type : type + "-" + getRealPositionForLogicalPosition((String)logicalPosition, c.getComponentOrientation().isLeftToRight()));
47          final TypeSpecifier specifier = getSpecifierByName(name);
48          if (specifier == null) return null;
49  
50          final Border border = specifier.getBorder();
51          if (!(border instanceof AquaBorder)) return border;
52  
53          return ((AquaBorder)border).deriveBorderForSize(AquaUtilControlSize.getUserSizeFrom(c));
54      }
55  
56      protected static String getRealPositionForLogicalPosition(String logicalPosition, boolean leftToRight) {
57          if (!leftToRight) {
58              if ("first".equalsIgnoreCase(logicalPosition)) return "last";
59              if ("last".equalsIgnoreCase(logicalPosition)) return "first";
60          }
61          return logicalPosition;
62      }
63  
64      static abstract class TypeSpecifier {
65          final String name;
66          final boolean setIconFont;
67  
68          TypeSpecifier(final String name, final boolean setIconFont) {
69              this.name = name; this.setIconFont = setIconFont;
70          }
71  
72          abstract Border getBorder();
73      }
74  
75      static class BorderDefinedTypeSpecifier extends TypeSpecifier {
76          final AquaBorder border;
77  
78          BorderDefinedTypeSpecifier(final String name, final Widget widget, final SizeVariant variant) {
79              this(name, widget, variant, 0, 0, 0, 0);
80          }
81  
82          BorderDefinedTypeSpecifier(final String name, final Widget widget, final SizeVariant variant, final int smallW, final int smallH, final int miniW, final int miniH) {
83              super(name, false);
84              border = initBorder(widget, new SizeDescriptor(variant) {
85                  public SizeVariant deriveSmall(final SizeVariant v) {
86                      v.alterMinSize(smallW, smallH);
87                      return super.deriveSmall(v);
88                  }
89                  public SizeVariant deriveMini(final SizeVariant v) {
90                      v.alterMinSize(miniW, miniH);
91                      return super.deriveMini(v);
92                  }
93              });
94              patchUp(border.sizeDescriptor);
95          }
96  
97          Border getBorder() { return border; }
98          void patchUp(final SizeDescriptor descriptor) {}
99  
100         AquaBorder initBorder(final Widget widget, final SizeDescriptor desc) {
101             return new AquaButtonBorder.Named(widget, desc);
102         }
103     }
104 
105     static class SegmentedBorderDefinedTypeSpecifier extends BorderDefinedTypeSpecifier {
106         public SegmentedBorderDefinedTypeSpecifier(final String name, final Widget widget, final SegmentPosition position, final SizeVariant variant) {
107             this(name, widget, position, variant, 0, 0, 0, 0);
108         }
109 
110         public SegmentedBorderDefinedTypeSpecifier(final String name, final Widget widget, final SegmentPosition position, final SizeVariant variant, final int smallW, final int smallH, final int miniW, final int miniH) {
111             super(name, widget, variant, smallW, smallH, miniW, miniH);
112             border.painter.state.set(SegmentTrailingSeparator.YES);
113             border.painter.state.set(position);
114         }
115 
116         AquaBorder initBorder(final Widget widget, final SizeDescriptor desc) {
117             return new SegmentedNamedBorder(widget, desc);
118         }
119     }
120 
121     public static class SegmentedNamedBorder extends AquaButtonBorder.Named {
122         public SegmentedNamedBorder(final SegmentedNamedBorder sizeDescriptor) {
123             super(sizeDescriptor);
124         }
125 
126         public SegmentedNamedBorder(final Widget widget, final SizeDescriptor sizeDescriptor) {
127             super(widget, sizeDescriptor);
128         }
129 
130         protected boolean isSelectionPressing() {
131             return false;
132         }
133     }
134 
135     protected static TypeSpecifier getSpecifierByName(final String name) {
136         return typeDefinitions.get().get(name);
137     }
138 
139     protected final static RecyclableSingleton<Map<String, TypeSpecifier>> typeDefinitions = new RecyclableSingleton<Map<String, TypeSpecifier>>() {
140         protected Map<String, TypeSpecifier> getInstance() {
141             return getAllTypes();
142         }
143     };
144 
145     protected static Map<String, TypeSpecifier> getAllTypes() {
146         final Map<String, TypeSpecifier> specifiersByName = new HashMap<String, TypeSpecifier>();
147 
148         final Insets focusInsets = new Insets(4, 4, 4, 4);
149 
150         final TypeSpecifier[] specifiers = {
151             new TypeSpecifier("toolbar", true) {
152                 Border getBorder() { return AquaButtonBorder.getToolBarButtonBorder(); }
153             },
154             new TypeSpecifier("icon", true) {
155                 Border getBorder() { return AquaButtonBorder.getToggleButtonBorder(); }
156             },
157             new TypeSpecifier("text", false) {
158                 Border getBorder() { return UIManager.getBorder("Button.border"); }
159             },
160             new TypeSpecifier("toggle", false) {
161                 Border getBorder() { return AquaButtonBorder.getToggleButtonBorder(); }
162             },
163             new BorderDefinedTypeSpecifier("combobox", Widget.BUTTON_POP_DOWN, new SizeVariant().alterMargins(7, 10, 6, 30).alterInsets(1, 2, 0, 2).alterMinSize(0, 29), 0, -3, 0, -6) {
164                 void patchUp(final SizeDescriptor descriptor) { descriptor.small.alterMargins(0, 0, 0, -4); descriptor.mini.alterMargins(0, 0, 0, -6); }
165             },
166             new BorderDefinedTypeSpecifier("comboboxInternal", Widget.BUTTON_POP_DOWN, new SizeVariant().alterInsets(1, 2, 0, 2).alterMinSize(0, 29), 0, -3, 0, -6),
167             new BorderDefinedTypeSpecifier("comboboxEndCap", Widget.BUTTON_COMBO_BOX, new SizeVariant().alterMargins(5, 10, 6, 10).alterInsets(1, 2, 0, 2).alterMinSize(0, 29), 0, -3, 0, -6){
168                 void patchUp(final SizeDescriptor descriptor) { border.painter.state.set(IndicatorOnly.YES); }
169             },
170 
171             new BorderDefinedTypeSpecifier("square", Widget.BUTTON_BEVEL, new SizeVariant(16, 16).alterMargins(5, 7, 5, 7).replaceInsets(focusInsets)),
172             new BorderDefinedTypeSpecifier("gradient", Widget.BUTTON_BEVEL_INSET, new SizeVariant(18, 18).alterMargins(8, 9, 8, 9).replaceInsets(focusInsets)) {
173                 void patchUp(SizeDescriptor descriptor) { descriptor.small.alterMargins(0, 0, 0, 0); }
174             },
175             new BorderDefinedTypeSpecifier("bevel", Widget.BUTTON_BEVEL_ROUND, new SizeVariant(22, 22).alterMargins(7, 8, 9, 8).alterInsets(0, 0, 0, 0)),
176 
177             new BorderDefinedTypeSpecifier("textured", Widget.BUTTON_PUSH_TEXTURED, new SizeVariant(28, 28).alterMargins(5, 10, 6, 10).alterInsets(1, 2, 0, 2)),
178             new BorderDefinedTypeSpecifier("roundRect", Widget.BUTTON_PUSH_INSET, new SizeVariant(28, 28).alterMargins(4, 14, 4, 14).replaceInsets(focusInsets)),
179             new BorderDefinedTypeSpecifier("recessed", Widget.BUTTON_PUSH_SCOPE, new SizeVariant(28, 28).alterMargins(4, 14, 4, 14).replaceInsets(focusInsets)),
180 
181             new BorderDefinedTypeSpecifier("well", Widget.FRAME_WELL, new SizeVariant(32, 32)),
182 
183             new BorderDefinedTypeSpecifier("help", Widget.BUTTON_ROUND_HELP, new SizeVariant().alterInsets(2, 0, 0, 0).alterMinSize(28, 28), -3, -3, -3, -3),
184             new BorderDefinedTypeSpecifier("round", Widget.BUTTON_ROUND, new SizeVariant().alterInsets(2, 0, 0, 0).alterMinSize(28, 28), -3, -3, -3, -3),
185             new BorderDefinedTypeSpecifier("texturedRound", Widget.BUTTON_ROUND_INSET, new SizeVariant().alterInsets(0, 0, 0, 0).alterMinSize(26, 26), -2, -2, 0, 0),
186 
187             new SegmentedBorderDefinedTypeSpecifier("segmented-first", Widget.BUTTON_SEGMENTED, SegmentPosition.FIRST, new SizeVariant().alterMargins(6, 16, 6, 10).alterInsets(2, 3, 2, 0).alterMinSize(0, 28), 0, -3, 0, -3),
188             new SegmentedBorderDefinedTypeSpecifier("segmented-middle", Widget.BUTTON_SEGMENTED, SegmentPosition.MIDDLE, new SizeVariant().alterMargins(6, 9, 6, 10).alterInsets(2, 0, 2, 0).alterMinSize(0, 28), 0, -3, 0, -3),
189             new SegmentedBorderDefinedTypeSpecifier("segmented-last", Widget.BUTTON_SEGMENTED, SegmentPosition.LAST, new SizeVariant().alterMargins(6, 9, 6, 16).alterInsets(2, 0, 2, 3).alterMinSize(0, 28), 0, -3, 0, -3),
190             new SegmentedBorderDefinedTypeSpecifier("segmented-only", Widget.BUTTON_SEGMENTED, SegmentPosition.ONLY, new SizeVariant().alterMargins(6, 16, 6, 16).alterInsets(2, 3, 2, 3).alterMinSize(34, 28), 0, -3, 0, -3),
191 
192             new SegmentedBorderDefinedTypeSpecifier("segmentedRoundRect-first", Widget.BUTTON_SEGMENTED_INSET, SegmentPosition.FIRST, new SizeVariant().alterMargins(6, 12, 6, 8).alterInsets(2, 2, 2, 0).alterMinSize(0, 28), 0, -3, 0, -3),
193             new SegmentedBorderDefinedTypeSpecifier("segmentedRoundRect-middle", Widget.BUTTON_SEGMENTED_INSET, SegmentPosition.MIDDLE, new SizeVariant().alterMargins(6, 8, 6, 8).alterInsets(2, 0, 2, 0).alterMinSize(0, 28), 0, -3, 0, -3),
194             new SegmentedBorderDefinedTypeSpecifier("segmentedRoundRect-last", Widget.BUTTON_SEGMENTED_INSET, SegmentPosition.LAST, new SizeVariant().alterMargins(6, 8, 6, 12).alterInsets(2, 0, 2, 2).alterMinSize(0, 28), 0, -3, 0, -3),
195             new SegmentedBorderDefinedTypeSpecifier("segmentedRoundRect-only", Widget.BUTTON_SEGMENTED_INSET, SegmentPosition.ONLY, new SizeVariant().alterMargins(6, 12, 6, 12).alterInsets(2, 2, 2, 2).alterMinSize(0, 28), 0, -3, 0, -3),
196 
197             new SegmentedBorderDefinedTypeSpecifier("segmentedTexturedRounded-first", Widget.BUTTON_SEGMENTED_SCURVE, SegmentPosition.FIRST, new SizeVariant().alterMargins(6, 12, 6, 8).alterInsets(2, 2, 2, 0).alterMinSize(0, 28), 0, -3, 0, -3),
198             new SegmentedBorderDefinedTypeSpecifier("segmentedTexturedRounded-middle", Widget.BUTTON_SEGMENTED_SCURVE, SegmentPosition.MIDDLE, new SizeVariant().alterMargins(6, 8, 6, 8).alterInsets(2, 0, 2, 0).alterMinSize(0, 28), 0, -3, 0, -3),
199             new SegmentedBorderDefinedTypeSpecifier("segmentedTexturedRounded-last", Widget.BUTTON_SEGMENTED_SCURVE, SegmentPosition.LAST, new SizeVariant().alterMargins(6, 8, 6, 12).alterInsets(2, 0, 2, 2).alterMinSize(0, 28), 0, -3, 0, -3),
200             new SegmentedBorderDefinedTypeSpecifier("segmentedTexturedRounded-only", Widget.BUTTON_SEGMENTED_SCURVE, SegmentPosition.ONLY, new SizeVariant().alterMargins(6, 12, 6, 12).alterInsets(2, 2, 2, 2).alterMinSize(0, 28), 0, -3, 0, -3),
201 
202             new SegmentedBorderDefinedTypeSpecifier("segmentedTextured-first", Widget.BUTTON_SEGMENTED_TEXTURED, SegmentPosition.FIRST, new SizeVariant().alterMargins(6, 12, 6, 8).alterInsets(2, 3, 2, 0).alterMinSize(0, 28), 0, -3, 0, -3),
203             new SegmentedBorderDefinedTypeSpecifier("segmentedTextured-middle", Widget.BUTTON_SEGMENTED_TEXTURED, SegmentPosition.MIDDLE, new SizeVariant().alterMargins(6, 8, 6, 8).alterInsets(2, 0, 2, 0).alterMinSize(0, 28), 0, -3, 0, -3),
204             new SegmentedBorderDefinedTypeSpecifier("segmentedTextured-last", Widget.BUTTON_SEGMENTED_TEXTURED, SegmentPosition.LAST, new SizeVariant().alterMargins(6, 8, 6, 12).alterInsets(2, 0, 2, 3).alterMinSize(0, 28), 0, -3, 0, -3),
205             new SegmentedBorderDefinedTypeSpecifier("segmentedTextured-only", Widget.BUTTON_SEGMENTED_TEXTURED, SegmentPosition.ONLY, new SizeVariant().alterMargins(6, 12, 6, 12).alterInsets(2, 3, 2, 3).alterMinSize(0, 28), 0, -3, 0, -3),
206 
207             new SegmentedBorderDefinedTypeSpecifier("segmentedCapsule-first", Widget.BUTTON_SEGMENTED_TOOLBAR, SegmentPosition.FIRST, new SizeVariant().alterMargins(6, 12, 6, 8).alterInsets(2, 2, 2, 0).alterMinSize(0, 28), 0, 0, 0, 0),
208             new SegmentedBorderDefinedTypeSpecifier("segmentedCapsule-middle", Widget.BUTTON_SEGMENTED_TOOLBAR, SegmentPosition.MIDDLE, new SizeVariant().alterMargins(6, 8, 6, 8).alterInsets(2, 0, 2, 0).alterMinSize(0, 28), 0, 0, 0, 0),
209             new SegmentedBorderDefinedTypeSpecifier("segmentedCapsule-last", Widget.BUTTON_SEGMENTED_TOOLBAR, SegmentPosition.LAST, new SizeVariant().alterMargins(6, 8, 6, 12).alterInsets(2, 0, 2, 2).alterMinSize(0, 28), 0, 0, 0, 0),
210             new SegmentedBorderDefinedTypeSpecifier("segmentedCapsule-only", Widget.BUTTON_SEGMENTED_TOOLBAR, SegmentPosition.ONLY, new SizeVariant().alterMargins(6, 12, 6, 12).alterInsets(2, 2, 2, 2).alterMinSize(34, 28), 0, 0, 0, 0),
211 
212             new BorderDefinedTypeSpecifier("segmentedGradient-first", Widget.BUTTON_BEVEL_INSET, new SizeVariant(18, 18).alterMargins(4, 5, 4, 5).replaceInsets(new Insets(-2,-0,-2,-0))),
213             new BorderDefinedTypeSpecifier("segmentedGradient-middle", Widget.BUTTON_BEVEL_INSET, new SizeVariant(18, 18).alterMargins(4, 5, 4, 5).replaceInsets(new Insets(-2,-1,-2,-0))),
214             new BorderDefinedTypeSpecifier("segmentedGradient-last", Widget.BUTTON_BEVEL_INSET, new SizeVariant(18, 18).alterMargins(4, 5, 4, 5).replaceInsets(new Insets(-2,-1,-2,-0))),
215             new BorderDefinedTypeSpecifier("segmentedGradient-only", Widget.BUTTON_BEVEL_INSET, new SizeVariant(18, 18).alterMargins(4, 5, 4, 5).replaceInsets(new Insets(-2,-1,-2,-1))),
216 
217             new BorderDefinedTypeSpecifier("disclosure", Widget.BUTTON_DISCLOSURE, new SizeVariant().alterMargins(10, 10, 10, 10).replaceInsets(focusInsets).alterMinSize(27, 27), -1, -1, -1, -1),
218 
219             //new BorderDefinedTypeSpecifier("disclosureTriangle", false, Widget.DISCLOSURE_TRIANGLE, new SizeVariant()),
220             new BorderDefinedTypeSpecifier("scrollColumnSizer", Widget.SCROLL_COLUMN_SIZER, new SizeVariant(14, 14)),
221         };
222 
223         for (final TypeSpecifier specifier : specifiers) {
224             specifiersByName.put(specifier.name, specifier);
225         }
226 
227         return specifiersByName;
228     }
229 }