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