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 final AquaBorder border = clazz.getConstructor(new Class<?>[] { clazz }).newInstance(new Object[] { this }); 80 border.setSize(size); 81 return border; 82 } catch (final Throwable e) { 83 return null; 84 } 85 } 86 87 public static void repaintBorder(final JComponent c) { 88 JComponent borderedComponent = c; 89 Border border = c.getBorder(); 90 if (border == null) { 91 // See if it's inside a JScrollpane or something 92 final Container p = c.getParent(); 93 if (p instanceof JViewport) { 94 borderedComponent = (JComponent)p.getParent(); 95 if (borderedComponent != null) border = borderedComponent.getBorder(); 96 } 97 } 98 99 // If we really don't have a border, then bail 100 // It might be a compound border with a ThemeBorder inside 101 // The check for that case is tricky, so we just go ahead and repaint any border 102 if (border == null || borderedComponent == null) return; 103 104 final int width = borderedComponent.getWidth(); 105 final int height = borderedComponent.getHeight(); 106 final Insets i = borderedComponent.getInsets(); 107 108 borderedComponent.repaint(0, 0, width, i.top); // Top edge 109 borderedComponent.repaint(0, 0, i.left, height); // Left edge 110 borderedComponent.repaint(0, height - i.bottom, width, i.bottom); // Bottom edge 111 borderedComponent.repaint(width - i.right, 0, i.right, height); // Right edge 112 } 113 114 // The JScrollPane doesn't let us know if its viewport view has focus 115 protected boolean isFocused(final Component c) { 116 // Being really paranoid in case this Component isn't a Swing component 117 Component focusable = c; 118 119 if (c instanceof JScrollPane) { 120 final JViewport vp = ((JScrollPane)c).getViewport(); 121 if (vp != null) { 122 focusable = vp.getView(); 123 // Lists, Tables & Trees get focus rings, TextAreas don't (JBuilder puts TextField border on TextAreas) 124 if (focusable instanceof JTextComponent) return false; 125 } 126 } else if (focusable instanceof JTextComponent) { 127 // non-editable text areas don't draw the focus ring 128 if (!((javax.swing.text.JTextComponent)focusable).isEditable()) return false; 129 } 130 131 return (focusable != null && focusable instanceof JComponent && ((JComponent)focusable).hasFocus()); 132 } 133 134 @Override 135 public boolean isBorderOpaque() { return false; } 136 137 @Override 138 public void paintBorder(final Component c, final Graphics g, final int x, final int y, final int w, final int h) { 139 painter.paint(g, c, x, y, w, h); 140 } 141 142 static class Default extends AquaBorder { 143 Default() { super(new SizeDescriptor(new SizeVariant())); } 144 } 145 }