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 {
  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 
  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     static abstract class TypeSpecifier {
  67         final String name;
  68         final boolean setIconFont;
  69 
  70         TypeSpecifier(final String name, final boolean setIconFont) {
  71             this.name = name; this.setIconFont = setIconFont;
  72         }
  73 
  74         abstract Border getBorder();
  75     }
  76 
  77     static class BorderDefinedTypeSpecifier extends TypeSpecifier {
  78         final AquaBorder border;
  79 
  80         BorderDefinedTypeSpecifier(final String name, final Widget widget, final SizeVariant variant) {
  81             this(name, widget, variant, 0, 0, 0, 0);
  82         }
  83 
  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 
  99         Border getBorder() { return border; }
 100         void patchUp(final SizeDescriptor descriptor) {}
 101 
 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 {
 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 
 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 
 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 {
 124         public SegmentedNamedBorder(final SegmentedNamedBorder sizeDescriptor) {
 125             super(sizeDescriptor);
 126         }
 127 
 128         public SegmentedNamedBorder(final Widget widget, final SizeDescriptor sizeDescriptor) {
 129             super(widget, sizeDescriptor);
 130         }
 131 
 132         protected boolean isSelectionPressing() {
 133             return false;
 134         }
 135     }
 136 
 137     protected static TypeSpecifier getSpecifierByName(final String name) {
 138         return typeDefinitions.get().get(name);
 139     }
 140 
 141     protected final static RecyclableSingleton<Map<String, TypeSpecifier>> typeDefinitions = new RecyclableSingleton<Map<String, TypeSpecifier>>() {
 142         protected Map<String, TypeSpecifier> getInstance() {
 143             return getAllTypes();
 144         }
 145     };
 146 
 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 }