1 /* 2 * Copyright (c) 1997, 2002, 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.sun.java.swing.plaf.motif; 27 28 import java.awt.*; 29 import java.awt.event.*; 30 import javax.swing.*; 31 import javax.swing.event.*; 32 import javax.swing.plaf.*; 33 import javax.swing.plaf.basic.BasicTabbedPaneUI; 34 import java.io.Serializable; 35 36 /** 37 * A Motif L&F implementation of TabbedPaneUI. 38 * <p> 39 * <strong>Warning:</strong> 40 * Serialized objects of this class will not be compatible with 41 * future Swing releases. The current serialization support is appropriate 42 * for short term storage or RMI between applications running the same 43 * version of Swing. A future release of Swing will provide support for 44 * long term persistence. 45 * 46 * @author Amy Fowler 47 * @author Philip Milne 48 */ 49 public class MotifTabbedPaneUI extends BasicTabbedPaneUI 50 { 51 52 // Instance variables initialized at installation 53 54 protected Color unselectedTabBackground; 55 protected Color unselectedTabForeground; 56 protected Color unselectedTabShadow; 57 protected Color unselectedTabHighlight; 58 59 60 // UI creation 61 62 public static ComponentUI createUI(JComponent tabbedPane) { 63 return new MotifTabbedPaneUI(); 64 } 65 66 67 // UI Installation/De-installation 68 69 70 protected void installDefaults() { 71 super.installDefaults(); 72 73 unselectedTabBackground = UIManager.getColor("TabbedPane.unselectedTabBackground"); 74 unselectedTabForeground = UIManager.getColor("TabbedPane.unselectedTabForeground"); 75 unselectedTabShadow = UIManager.getColor("TabbedPane.unselectedTabShadow"); 76 unselectedTabHighlight = UIManager.getColor("TabbedPane.unselectedTabHighlight"); 77 } 78 79 protected void uninstallDefaults() { 80 super.uninstallDefaults(); 81 82 unselectedTabBackground = null; 83 unselectedTabForeground = null; 84 unselectedTabShadow = null; 85 unselectedTabHighlight = null; 86 } 87 88 // UI Rendering 89 90 protected void paintContentBorderTopEdge(Graphics g, int tabPlacement, 91 int selectedIndex, 92 int x, int y, int w, int h) { 93 Rectangle selRect = selectedIndex < 0? null : 94 getTabBounds(selectedIndex, calcRect); 95 g.setColor(lightHighlight); 96 97 // Draw unbroken line if tabs are not on TOP, OR 98 // selected tab is not visible (SCROLL_TAB_LAYOUT) 99 // 100 if (tabPlacement != TOP || selectedIndex < 0 || 101 (selRect.x < x || selRect.x > x + w)) { 102 g.drawLine(x, y, x+w-2, y); 103 } else { 104 // Break line to show visual connection to selected tab 105 g.drawLine(x, y, selRect.x - 1, y); 106 if (selRect.x + selRect.width < x + w - 2) { 107 g.drawLine(selRect.x + selRect.width, y, 108 x+w-2, y); 109 } 110 } 111 } 112 113 protected void paintContentBorderBottomEdge(Graphics g, int tabPlacement, 114 int selectedIndex, 115 int x, int y, int w, int h) { 116 Rectangle selRect = selectedIndex < 0? null : 117 getTabBounds(selectedIndex, calcRect); 118 g.setColor(shadow); 119 120 // Draw unbroken line if tabs are not on BOTTOM, OR 121 // selected tab is not visible (SCROLL_TAB_LAYOUT) 122 // 123 if (tabPlacement != BOTTOM || selectedIndex < 0 || 124 (selRect.x < x || selRect.x > x + w)) { 125 g.drawLine(x+1, y+h-1, x+w-1, y+h-1); 126 } else { 127 // Break line to show visual connection to selected tab 128 g.drawLine(x+1, y+h-1, selRect.x - 1, y+h-1); 129 if (selRect.x + selRect.width < x + w - 2) { 130 g.drawLine(selRect.x + selRect.width, y+h-1, x+w-2, y+h-1); 131 } 132 } 133 } 134 135 protected void paintContentBorderRightEdge(Graphics g, int tabPlacement, 136 int selectedIndex, 137 int x, int y, int w, int h) { 138 Rectangle selRect = selectedIndex < 0? null : 139 getTabBounds(selectedIndex, calcRect); 140 g.setColor(shadow); 141 // Draw unbroken line if tabs are not on RIGHT, OR 142 // selected tab is not visible (SCROLL_TAB_LAYOUT) 143 // 144 if (tabPlacement != RIGHT || selectedIndex < 0 || 145 (selRect.y < y || selRect.y > y + h)) { 146 g.drawLine(x+w-1, y+1, x+w-1, y+h-1); 147 } else { 148 // Break line to show visual connection to selected tab 149 g.drawLine(x+w-1, y+1, x+w-1, selRect.y - 1); 150 if (selRect.y + selRect.height < y + h - 2 ) { 151 g.drawLine(x+w-1, selRect.y + selRect.height, 152 x+w-1, y+h-2); 153 } 154 } 155 } 156 157 protected void paintTabBackground(Graphics g, 158 int tabPlacement, int tabIndex, 159 int x, int y, int w, int h, 160 boolean isSelected ) { 161 g.setColor(isSelected? tabPane.getBackgroundAt(tabIndex) : unselectedTabBackground); 162 switch(tabPlacement) { 163 case LEFT: 164 g.fillRect(x+1, y+1, w-1, h-2); 165 break; 166 case RIGHT: 167 g.fillRect(x, y+1, w-1, h-2); 168 break; 169 case BOTTOM: 170 g.fillRect(x+1, y, w-2, h-3); 171 g.drawLine(x+2, y+h-3, x+w-3, y+h-3); 172 g.drawLine(x+3, y+h-2, x+w-4, y+h-2); 173 break; 174 case TOP: 175 default: 176 g.fillRect(x+1, y+3, w-2, h-3); 177 g.drawLine(x+2, y+2, x+w-3, y+2); 178 g.drawLine(x+3, y+1, x+w-4, y+1); 179 } 180 181 } 182 183 protected void paintTabBorder(Graphics g, 184 int tabPlacement, int tabIndex, 185 int x, int y, int w, int h, 186 boolean isSelected) { 187 g.setColor(isSelected? lightHighlight : unselectedTabHighlight); 188 189 switch(tabPlacement) { 190 case LEFT: 191 g.drawLine(x, y+2, x, y+h-3); 192 g.drawLine(x+1, y+1, x+1, y+2); 193 g.drawLine(x+2, y, x+2, y+1); 194 g.drawLine(x+3, y, x+w-1, y); 195 g.setColor(isSelected? shadow : unselectedTabShadow); 196 g.drawLine(x+1, y+h-3, x+1, y+h-2); 197 g.drawLine(x+2, y+h-2, x+2, y+h-1); 198 g.drawLine(x+3, y+h-1, x+w-1, y+h-1); 199 break; 200 case RIGHT: 201 g.drawLine(x, y, x+w-3, y); 202 g.setColor(isSelected? shadow : unselectedTabShadow); 203 g.drawLine(x+w-3, y, x+w-3, y+1); 204 g.drawLine(x+w-2, y+1, x+w-2, y+2); 205 g.drawLine(x+w-1, y+2, x+w-1, y+h-3); 206 g.drawLine(x+w-2, y+h-3, x+w-2, y+h-2); 207 g.drawLine(x+w-3, y+h-2, x+w-3, y+h-1); 208 g.drawLine(x, y+h-1, x+w-3, y+h-1); 209 break; 210 case BOTTOM: 211 g.drawLine(x, y, x, y+h-3); 212 g.drawLine(x+1, y+h-3, x+1, y+h-2); 213 g.drawLine(x+2, y+h-2, x+2, y+h-1); 214 g.setColor(isSelected? shadow : unselectedTabShadow); 215 g.drawLine(x+3, y+h-1, x+w-4, y+h-1); 216 g.drawLine(x+w-3, y+h-2, x+w-3, y+h-1); 217 g.drawLine(x+w-2, y+h-3, x+w-2, y+h-2); 218 g.drawLine(x+w-1, y, x+w-1, y+h-3); 219 break; 220 case TOP: 221 default: 222 g.drawLine(x, y+2, x, y+h-1); 223 g.drawLine(x+1, y+1, x+1, y+2); 224 g.drawLine(x+2, y, x+2, y+1); 225 g.drawLine(x+3, y, x+w-4, y); 226 g.setColor(isSelected? shadow : unselectedTabShadow); 227 g.drawLine(x+w-3, y, x+w-3, y+1); 228 g.drawLine(x+w-2, y+1, x+w-2, y+2); 229 g.drawLine(x+w-1, y+2, x+w-1, y+h-1); 230 } 231 232 } 233 234 protected void paintFocusIndicator(Graphics g, int tabPlacement, 235 Rectangle[] rects, int tabIndex, 236 Rectangle iconRect, Rectangle textRect, 237 boolean isSelected) { 238 Rectangle tabRect = rects[tabIndex]; 239 if (tabPane.hasFocus() && isSelected) { 240 int x, y, w, h; 241 g.setColor(focus); 242 switch(tabPlacement) { 243 case LEFT: 244 x = tabRect.x + 3; 245 y = tabRect.y + 3; 246 w = tabRect.width - 6; 247 h = tabRect.height - 7; 248 break; 249 case RIGHT: 250 x = tabRect.x + 2; 251 y = tabRect.y + 3; 252 w = tabRect.width - 6; 253 h = tabRect.height - 7; 254 break; 255 case BOTTOM: 256 x = tabRect.x + 3; 257 y = tabRect.y + 2; 258 w = tabRect.width - 7; 259 h = tabRect.height - 6; 260 break; 261 case TOP: 262 default: 263 x = tabRect.x + 3; 264 y = tabRect.y + 3; 265 w = tabRect.width - 7; 266 h = tabRect.height - 6; 267 } 268 g.drawRect(x, y, w, h); 269 } 270 } 271 272 protected int getTabRunIndent(int tabPlacement, int run) { 273 return run*3; 274 } 275 276 protected int getTabRunOverlay(int tabPlacement) { 277 tabRunOverlay = (tabPlacement == LEFT || tabPlacement == RIGHT)? 278 (int)Math.round((float)maxTabWidth * .10) : 279 (int)Math.round((float)maxTabHeight * .22); 280 281 // Ensure that runover lay is not more than insets 282 // 2 pixel offset is set from insets to each run 283 switch(tabPlacement) { 284 case LEFT: 285 if( tabRunOverlay > tabInsets.right - 2 ) 286 tabRunOverlay = tabInsets.right - 2 ; 287 break; 288 case RIGHT: 289 if( tabRunOverlay > tabInsets.left - 2 ) 290 tabRunOverlay = tabInsets.left - 2 ; 291 break; 292 case TOP: 293 if( tabRunOverlay > tabInsets.bottom - 2 ) 294 tabRunOverlay = tabInsets.bottom - 2 ; 295 break; 296 case BOTTOM: 297 if( tabRunOverlay > tabInsets.top - 2 ) 298 tabRunOverlay = tabInsets.top - 2 ; 299 break; 300 301 } 302 303 return tabRunOverlay; 304 } 305 306 }