1 /* 2 * Copyright (c) 2011, 2015, 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.border.Border; 32 import javax.swing.plaf.UIResource; 33 import javax.swing.text.JTextComponent; 34 35 import apple.laf.*; 36 import apple.laf.JRSUIConstants.*; 37 38 import com.apple.laf.AquaUtilControlSize.*; 39 40 public abstract class AquaBorder implements Border, UIResource { 41 protected final AquaPainter<? extends JRSUIState> painter; 42 protected final SizeDescriptor sizeDescriptor; 43 protected SizeVariant sizeVariant; 44 45 protected AquaBorder(final SizeDescriptor sizeDescriptor) { 46 this.sizeDescriptor = sizeDescriptor; 47 this.sizeVariant = sizeDescriptor.get(Size.REGULAR); 48 this.painter = createPainter(); 49 } 50 51 protected AquaPainter<? extends JRSUIState> createPainter() { 52 final AquaPainter<JRSUIState> painter = AquaPainter.create(JRSUIState.getInstance()); 53 painter.state.set(AlignmentVertical.CENTER); 54 painter.state.set(AlignmentHorizontal.CENTER); 55 return painter; 56 } 57 58 protected AquaBorder(final AquaBorder other) { 59 this.sizeDescriptor = other.sizeDescriptor; 60 this.sizeVariant = other.sizeVariant; 61 this.painter = AquaPainter.create(other.painter.state.derive()); 62 painter.state.set(AlignmentVertical.CENTER); 63 painter.state.set(AlignmentHorizontal.CENTER); 64 } 65 66 protected void setSize(final Size size) { 67 sizeVariant = sizeDescriptor.get(size); 68 painter.state.set(size); 69 } 70 71 @Override 72 public Insets getBorderInsets(final Component c) { 73 return (Insets) sizeVariant.margins.clone(); 74 } 75 76 protected AquaBorder deriveBorderForSize(final Size size) { 77 try { 78 final Class<? extends AquaBorder> clazz = getClass(); 79 @SuppressWarnings("deprecation") 80 final AquaBorder border = clazz.getConstructor(new Class<?>[] { clazz }).newInstance(new Object[] { this }); 81 border.setSize(size); 82 return border; 83 } catch (final Throwable e) { 84 return null; 85 } 86 } 87 88 public static void repaintBorder(final JComponent c) { 89 JComponent borderedComponent = c; 90 Border border = c.getBorder(); 91 if (border == null) { 92 // See if it's inside a JScrollpane or something 93 final Container p = c.getParent(); 94 if (p instanceof JViewport) { 95 borderedComponent = (JComponent)p.getParent(); 96 if (borderedComponent != null) border = borderedComponent.getBorder(); 97 } 98 } 99 100 // If we really don't have a border, then bail 101 // It might be a compound border with a ThemeBorder inside 102 // The check for that case is tricky, so we just go ahead and repaint any border 103 if (border == null || borderedComponent == null) return; 104 105 final int width = borderedComponent.getWidth(); 106 final int height = borderedComponent.getHeight(); 107 final Insets i = borderedComponent.getInsets(); 108 109 borderedComponent.repaint(0, 0, width, i.top); // Top edge 110 borderedComponent.repaint(0, 0, i.left, height); // Left edge 111 borderedComponent.repaint(0, height - i.bottom, width, i.bottom); // Bottom edge 112 borderedComponent.repaint(width - i.right, 0, i.right, height); // Right edge 113 } 114 115 // The JScrollPane doesn't let us know if its viewport view has focus 116 protected boolean isFocused(final Component c) { 117 // Being really paranoid in case this Component isn't a Swing component 118 Component focusable = c; 119 120 if (c instanceof JScrollPane) { 121 final JViewport vp = ((JScrollPane)c).getViewport(); 122 if (vp != null) { 123 focusable = vp.getView(); 124 // Lists, Tables & Trees get focus rings, TextAreas don't (JBuilder puts TextField border on TextAreas) 125 if (focusable instanceof JTextComponent) return false; 126 } 127 } else if (focusable instanceof JTextComponent) { 128 // non-editable text areas don't draw the focus ring 129 if (!((javax.swing.text.JTextComponent)focusable).isEditable()) return false; 130 } 131 132 return (focusable != null && focusable instanceof JComponent && ((JComponent)focusable).hasFocus()); 133 } 134 135 @Override 136 public boolean isBorderOpaque() { return false; } 137 138 @Override 139 public void paintBorder(final Component c, final Graphics g, final int x, final int y, final int w, final int h) { 140 painter.paint(g, c, x, y, w, h); 141 } 142 143 static class Default extends AquaBorder { 144 Default() { super(new SizeDescriptor(new SizeVariant())); } 145 } 146 }