1 /* 2 * Copyright (c) 2011, 2012, 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 import java.awt.image.BufferedImage; 30 import java.security.PrivilegedAction; 31 32 import javax.swing.*; 33 import javax.swing.plaf.*; 34 35 import sun.lwawt.macosx.LWCToolkit; 36 import apple.laf.JRSUIConstants.AlignmentHorizontal; 37 import apple.laf.JRSUIConstants.AlignmentVertical; 38 import apple.laf.JRSUIConstants.Direction; 39 import apple.laf.JRSUIConstants.State; 40 import apple.laf.JRSUIConstants.Widget; 41 import apple.laf.*; 42 43 import com.apple.eio.FileManager; 44 import com.apple.laf.AquaIcon.InvertableIcon; 45 import com.apple.laf.AquaIcon.JRSUIControlSpec; 46 import com.apple.laf.AquaIcon.SystemIcon; 47 import com.apple.laf.AquaUtils.RecyclableObject; 48 import com.apple.laf.AquaUtils.RecyclableSingleton; 49 import sun.awt.image.MultiResolutionImage; 50 import sun.awt.image.MultiResolutionCachedImage; 51 52 public class AquaImageFactory { getConfirmImageIcon()53 public static IconUIResource getConfirmImageIcon() { 54 // public, because UIDefaults.ProxyLazyValue uses reflection to get this value 55 56 return new IconUIResource(new AquaIcon.CachingScalingIcon(kAlertIconSize, kAlertIconSize) { 57 Image createImage() { 58 return getGenericJavaIcon(); 59 } 60 }); 61 } 62 63 public static IconUIResource getCautionImageIcon() { 64 // public, because UIDefaults.ProxyLazyValue uses reflection to get this value 65 return getAppIconCompositedOn(AquaIcon.SystemIcon.getCautionIcon()); 66 } 67 68 public static IconUIResource getStopImageIcon() { 69 // public, because UIDefaults.ProxyLazyValue uses reflection to get this value 70 return getAppIconCompositedOn(AquaIcon.SystemIcon.getStopIcon()); 71 } 72 73 public static IconUIResource getLockImageIcon() { 74 // public, because UIDefaults.ProxyLazyValue uses reflection to get this value 75 if (JRSUIUtils.Images.shouldUseLegacySecurityUIPath()) { 76 final Image lockIcon = AquaUtils.getCImageCreator().createImageFromFile("/System/Library/CoreServices/SecurityAgent.app/Contents/Resources/Security.icns", kAlertIconSize, kAlertIconSize); 77 return getAppIconCompositedOn(lockIcon); 78 } 79 80 final Image lockIcon = Toolkit.getDefaultToolkit().getImage("NSImage://NSSecurity"); 81 return getAppIconCompositedOn(lockIcon); 82 } 83 84 static Image getGenericJavaIcon() { 85 return java.security.AccessController.doPrivileged(new PrivilegedAction<Image>() { 86 public Image run() { 87 return com.apple.eawt.Application.getApplication().getDockIconImage(); 88 } 89 }); 90 } 91 92 static String getPathToThisApplication() { 93 return java.security.AccessController.doPrivileged(new PrivilegedAction<String>() { 94 public String run() { 95 return FileManager.getPathToApplicationBundle(); 96 } 97 }); 98 } 99 100 static IconUIResource getAppIconCompositedOn(final SystemIcon systemIcon) { 101 systemIcon.setSize(kAlertIconSize, kAlertIconSize); 102 return getAppIconCompositedOn(systemIcon.createImage()); 103 } 104 105 private static final int kAlertIconSize = 64; 106 static IconUIResource getAppIconCompositedOn(final Image background) { 107 108 if (background instanceof MultiResolutionCachedImage) { 109 int width = background.getWidth(null); 110 Image mrIconImage = ((MultiResolutionCachedImage) background).map( 111 rv -> getAppIconImageCompositedOn(rv, rv.getWidth(null) / width)); 112 return new IconUIResource(new ImageIcon(mrIconImage)); 113 } 114 115 BufferedImage iconImage = getAppIconImageCompositedOn(background, 1); 116 return new IconUIResource(new ImageIcon(iconImage)); 117 } 118 119 static BufferedImage getAppIconImageCompositedOn(final Image background, int scaleFactor) { 120 121 final int scaledAlertIconSize = kAlertIconSize * scaleFactor; 122 final int kAlertSubIconSize = (int) (scaledAlertIconSize * 0.5); 123 final int kAlertSubIconInset = scaledAlertIconSize - kAlertSubIconSize; 124 final Icon smallAppIconScaled = new AquaIcon.CachingScalingIcon( 125 kAlertSubIconSize, kAlertSubIconSize) { 126 Image createImage() { 127 return getGenericJavaIcon(); 128 } 129 }; 130 131 final BufferedImage image = new BufferedImage(scaledAlertIconSize, 132 scaledAlertIconSize, BufferedImage.TYPE_INT_ARGB_PRE); 133 final Graphics g = image.getGraphics(); 134 g.drawImage(background, 0, 0, 135 scaledAlertIconSize, scaledAlertIconSize, null); 136 if (g instanceof Graphics2D) { 137 // improves icon rendering quality in Quartz 138 ((Graphics2D) g).setRenderingHint(RenderingHints.KEY_RENDERING, 139 RenderingHints.VALUE_RENDER_QUALITY); 140 } 141 142 smallAppIconScaled.paintIcon(null, g, 143 kAlertSubIconInset, kAlertSubIconInset); 144 g.dispose(); 145 146 return image; 147 } 148 149 public static IconUIResource getTreeFolderIcon() { 150 // public, because UIDefaults.ProxyLazyValue uses reflection to get this value 151 return AquaIcon.SystemIcon.getFolderIconUIResource(); 152 } 153 154 public static IconUIResource getTreeOpenFolderIcon() { 155 // public, because UIDefaults.ProxyLazyValue uses reflection to get this value 156 return AquaIcon.SystemIcon.getOpenFolderIconUIResource(); 157 } 158 159 public static IconUIResource getTreeDocumentIcon() { 160 // public, because UIDefaults.ProxyLazyValue uses reflection to get this value 161 return AquaIcon.SystemIcon.getDocumentIconUIResource(); 162 } 163 164 public static UIResource getTreeExpandedIcon() { 165 // public, because UIDefaults.ProxyLazyValue uses reflection to get this value 166 return AquaIcon.getIconFor(new JRSUIControlSpec() { 167 public void initIconPainter(final AquaPainter<? extends JRSUIState> painter) { 168 painter.state.set(Widget.DISCLOSURE_TRIANGLE); 169 painter.state.set(State.ACTIVE); 170 painter.state.set(Direction.DOWN); 171 painter.state.set(AlignmentHorizontal.CENTER); 172 painter.state.set(AlignmentVertical.CENTER); 173 } 174 }, 20, 20); 175 } 176 177 public static UIResource getTreeCollapsedIcon() { 178 // public, because UIDefaults.ProxyLazyValue uses reflection to get this value 179 return AquaIcon.getIconFor(new JRSUIControlSpec() { 180 public void initIconPainter(final AquaPainter<? extends JRSUIState> painter) { 181 painter.state.set(Widget.DISCLOSURE_TRIANGLE); 182 painter.state.set(State.ACTIVE); 183 painter.state.set(Direction.RIGHT); 184 painter.state.set(AlignmentHorizontal.CENTER); 185 painter.state.set(AlignmentVertical.CENTER); 186 } 187 }, 20, 20); 188 } 189 190 public static UIResource getTreeRightToLeftCollapsedIcon() { 191 // public, because UIDefaults.ProxyLazyValue uses reflection to get this value 192 return AquaIcon.getIconFor(new JRSUIControlSpec() { 193 public void initIconPainter(final AquaPainter<? extends JRSUIState> painter) { 194 painter.state.set(Widget.DISCLOSURE_TRIANGLE); 195 painter.state.set(State.ACTIVE); 196 painter.state.set(Direction.LEFT); 197 painter.state.set(AlignmentHorizontal.CENTER); 198 painter.state.set(AlignmentVertical.CENTER); 199 } 200 }, 20, 20); 201 } 202 203 static class NamedImageSingleton extends RecyclableSingleton<Image> { 204 final String namedImage; 205 206 NamedImageSingleton(final String namedImage) { 207 this.namedImage = namedImage; 208 } 209 210 @Override 211 protected Image getInstance() { 212 return getNSIcon(namedImage); 213 } 214 } 215 216 static class IconUIResourceSingleton extends RecyclableSingleton<IconUIResource> { 217 final NamedImageSingleton holder; 218 219 public IconUIResourceSingleton(final NamedImageSingleton holder) { 220 this.holder = holder; 221 } 222 223 @Override 224 protected IconUIResource getInstance() { 225 return new IconUIResource(new ImageIcon(holder.get())); 226 } 227 } 228 229 static class InvertableImageIcon extends ImageIcon implements InvertableIcon, UIResource { 230 Icon invertedImage; 231 public InvertableImageIcon(final Image image) { 232 super(image); 233 } 234 235 @Override 236 public Icon getInvertedIcon() { 237 if (invertedImage != null) return invertedImage; 238 return invertedImage = new IconUIResource(new ImageIcon(AquaUtils.generateLightenedImage(getImage(), 100))); 239 } 240 } 241 242 protected static final NamedImageSingleton northArrow = new NamedImageSingleton("NSMenuScrollUp"); 243 protected static final IconUIResourceSingleton northArrowIcon = new IconUIResourceSingleton(northArrow); 244 protected static final NamedImageSingleton southArrow = new NamedImageSingleton("NSMenuScrollDown"); 245 protected static final IconUIResourceSingleton southArrowIcon = new IconUIResourceSingleton(southArrow); 246 protected static final NamedImageSingleton westArrow = new NamedImageSingleton("NSMenuSubmenuLeft"); 247 protected static final IconUIResourceSingleton westArrowIcon = new IconUIResourceSingleton(westArrow); 248 protected static final NamedImageSingleton eastArrow = new NamedImageSingleton("NSMenuSubmenu"); 249 protected static final IconUIResourceSingleton eastArrowIcon = new IconUIResourceSingleton(eastArrow); 250 251 static Image getArrowImageForDirection(final int direction) { 252 switch(direction) { 253 case SwingConstants.NORTH: return northArrow.get(); 254 case SwingConstants.SOUTH: return southArrow.get(); 255 case SwingConstants.EAST: return eastArrow.get(); 256 case SwingConstants.WEST: return westArrow.get(); 257 } 258 return null; 259 } 260 261 static Icon getArrowIconForDirection(int direction) { 262 switch(direction) { 263 case SwingConstants.NORTH: return northArrowIcon.get(); 264 case SwingConstants.SOUTH: return southArrowIcon.get(); 265 case SwingConstants.EAST: return eastArrowIcon.get(); 266 case SwingConstants.WEST: return westArrowIcon.get(); 267 } 268 return null; 269 } 270 271 public static Icon getMenuArrowIcon() { 272 return new InvertableImageIcon(AquaUtils.generateLightenedImage(eastArrow.get(), 25)); 273 } 274 275 public static Icon getMenuItemCheckIcon() { 276 return new InvertableImageIcon(AquaUtils.generateLightenedImage( 277 getNSIcon("NSMenuItemSelection"), 25)); 278 } 279 280 public static Icon getMenuItemDashIcon() { 281 return new InvertableImageIcon(AquaUtils.generateLightenedImage( 282 getNSIcon("NSMenuMixedState"), 25)); 283 } 284 285 private static Image getNSIcon(String imageName) { 286 Image icon = Toolkit.getDefaultToolkit() 287 .getImage("NSImage://" + imageName); 288 return icon; 289 } 290 291 public static class NineSliceMetrics { 292 public final int wCut, eCut, nCut, sCut; 293 public final int minW, minH; 294 public final boolean showMiddle, stretchH, stretchV; 295 296 public NineSliceMetrics(final int minWidth, final int minHeight, final int westCut, final int eastCut, final int northCut, final int southCut) { 297 this(minWidth, minHeight, westCut, eastCut, northCut, southCut, true); 298 } 299 300 public NineSliceMetrics(final int minWidth, final int minHeight, final int westCut, final int eastCut, final int northCut, final int southCut, final boolean showMiddle) { 301 this(minWidth, minHeight, westCut, eastCut, northCut, southCut, showMiddle, true, true); 302 } 303 304 public NineSliceMetrics(final int minWidth, final int minHeight, final int westCut, final int eastCut, final int northCut, final int southCut, final boolean showMiddle, final boolean stretchHorizontally, final boolean stretchVertically) { 305 this.wCut = westCut; this.eCut = eastCut; this.nCut = northCut; this.sCut = southCut; 306 this.minW = minWidth; this.minH = minHeight; 307 this.showMiddle = showMiddle; this.stretchH = stretchHorizontally; this.stretchV = stretchVertically; 308 } 309 } 310 311 /* 312 * A "paintable" which holds nine images, which represent a sliced up initial 313 * image that can be streched from its middles. 314 */ 315 public static class SlicedImageControl { 316 final BufferedImage NW, N, NE; 317 final BufferedImage W, C, E; 318 final BufferedImage SW, S, SE; 319 320 final NineSliceMetrics metrics; 321 322 final int totalWidth, totalHeight; 323 final int centerColWidth, centerRowHeight; 324 325 public SlicedImageControl(final Image img, final int westCut, final int eastCut, final int northCut, final int southCut) { 326 this(img, westCut, eastCut, northCut, southCut, true); 327 } 328 329 public SlicedImageControl(final Image img, final int westCut, final int eastCut, final int northCut, final int southCut, final boolean useMiddle) { 330 this(img, westCut, eastCut, northCut, southCut, useMiddle, true, true); 331 } 332 333 public SlicedImageControl(final Image img, final int westCut, final int eastCut, final int northCut, final int southCut, final boolean useMiddle, final boolean stretchHorizontally, final boolean stretchVertically) { 334 this(img, new NineSliceMetrics(img.getWidth(null), img.getHeight(null), westCut, eastCut, northCut, southCut, useMiddle, stretchHorizontally, stretchVertically)); 335 } 336 337 public SlicedImageControl(final Image img, final NineSliceMetrics metrics) { 338 this.metrics = metrics; 339 340 if (img.getWidth(null) != metrics.minW || img.getHeight(null) != metrics.minH) { 341 throw new IllegalArgumentException("SlicedImageControl: template image and NineSliceMetrics don't agree on minimum dimensions"); 342 } 343 344 totalWidth = metrics.minW; 345 totalHeight = metrics.minH; 346 centerColWidth = totalWidth - metrics.wCut - metrics.eCut; 347 centerRowHeight = totalHeight - metrics.nCut - metrics.sCut; 348 349 NW = createSlice(img, 0, 0, metrics.wCut, metrics.nCut); 350 N = createSlice(img, metrics.wCut, 0, centerColWidth, metrics.nCut); 351 NE = createSlice(img, totalWidth - metrics.eCut, 0, metrics.eCut, metrics.nCut); 352 W = createSlice(img, 0, metrics.nCut, metrics.wCut, centerRowHeight); 353 C = metrics.showMiddle ? createSlice(img, metrics.wCut, metrics.nCut, centerColWidth, centerRowHeight) : null; 354 E = createSlice(img, totalWidth - metrics.eCut, metrics.nCut, metrics.eCut, centerRowHeight); 355 SW = createSlice(img, 0, totalHeight - metrics.sCut, metrics.wCut, metrics.sCut); 356 S = createSlice(img, metrics.wCut, totalHeight - metrics.sCut, centerColWidth, metrics.sCut); 357 SE = createSlice(img, totalWidth - metrics.eCut, totalHeight - metrics.sCut, metrics.eCut, metrics.sCut); 358 } 359 360 static BufferedImage createSlice(final Image img, final int x, final int y, final int w, final int h) { 361 if (w == 0 || h == 0) return null; 362 363 final BufferedImage slice = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB_PRE); 364 final Graphics2D g2d = slice.createGraphics(); 365 g2d.drawImage(img, 0, 0, w, h, x, y, x + w, y + h, null); 366 g2d.dispose(); 367 368 return slice; 369 } 370 371 public void paint(final Graphics g, final int x, final int y, final int w, final int h) { 372 g.translate(x, y); 373 374 if (w < totalWidth || h < totalHeight) { 375 paintCompressed(g, w, h); 376 } else { 377 paintStretchedMiddles(g, w, h); 378 } 379 380 g.translate(-x, -y); 381 } 382 383 void paintStretchedMiddles(final Graphics g, final int w, final int h) { 384 int baseX = metrics.stretchH ? 0 : ((w / 2) - (totalWidth / 2)); 385 int baseY = metrics.stretchV ? 0 : ((h / 2) - (totalHeight / 2)); 386 int adjustedWidth = metrics.stretchH ? w : totalWidth; 387 int adjustedHeight = metrics.stretchV ? h : totalHeight; 388 389 if (NW != null) g.drawImage(NW, baseX, baseY, null); 390 if (N != null) g.drawImage(N, baseX + metrics.wCut, baseY, adjustedWidth - metrics.eCut - metrics.wCut, metrics.nCut, null); 391 if (NE != null) g.drawImage(NE, baseX + adjustedWidth - metrics.eCut, baseY, null); 392 if (W != null) g.drawImage(W, baseX, baseY + metrics.nCut, metrics.wCut, adjustedHeight - metrics.nCut - metrics.sCut, null); 393 if (C != null) g.drawImage(C, baseX + metrics.wCut, baseY + metrics.nCut, adjustedWidth - metrics.eCut - metrics.wCut, adjustedHeight - metrics.nCut - metrics.sCut, null); 394 if (E != null) g.drawImage(E, baseX + adjustedWidth - metrics.eCut, baseY + metrics.nCut, metrics.eCut, adjustedHeight - metrics.nCut - metrics.sCut, null); 395 if (SW != null) g.drawImage(SW, baseX, baseY + adjustedHeight - metrics.sCut, null); 396 if (S != null) g.drawImage(S, baseX + metrics.wCut, baseY + adjustedHeight - metrics.sCut, adjustedWidth - metrics.eCut - metrics.wCut, metrics.sCut, null); 397 if (SE != null) g.drawImage(SE, baseX + adjustedWidth - metrics.eCut, baseY + adjustedHeight - metrics.sCut, null); 398 399 /* 400 if (NW != null) {g.setColor(Color.GREEN); g.fillRect(baseX, baseY, NW.getWidth(), NW.getHeight());} 401 if (N != null) {g.setColor(Color.RED); g.fillRect(baseX + metrics.wCut, baseY, adjustedWidth - metrics.eCut - metrics.wCut, metrics.nCut);} 402 if (NE != null) {g.setColor(Color.BLUE); g.fillRect(baseX + adjustedWidth - metrics.eCut, baseY, NE.getWidth(), NE.getHeight());} 403 if (W != null) {g.setColor(Color.PINK); g.fillRect(baseX, baseY + metrics.nCut, metrics.wCut, adjustedHeight - metrics.nCut - metrics.sCut);} 404 if (C != null) {g.setColor(Color.ORANGE); g.fillRect(baseX + metrics.wCut, baseY + metrics.nCut, adjustedWidth - metrics.eCut - metrics.wCut, adjustedHeight - metrics.nCut - metrics.sCut);} 405 if (E != null) {g.setColor(Color.CYAN); g.fillRect(baseX + adjustedWidth - metrics.eCut, baseY + metrics.nCut, metrics.eCut, adjustedHeight - metrics.nCut - metrics.sCut);} 406 if (SW != null) {g.setColor(Color.MAGENTA); g.fillRect(baseX, baseY + adjustedHeight - metrics.sCut, SW.getWidth(), SW.getHeight());} 407 if (S != null) {g.setColor(Color.DARK_GRAY); g.fillRect(baseX + metrics.wCut, baseY + adjustedHeight - metrics.sCut, adjustedWidth - metrics.eCut - metrics.wCut, metrics.sCut);} 408 if (SE != null) {g.setColor(Color.YELLOW); g.fillRect(baseX + adjustedWidth - metrics.eCut, baseY + adjustedHeight - metrics.sCut, SE.getWidth(), SE.getHeight());} 409 */ 410 } 411 412 void paintCompressed(final Graphics g, final int w, final int h) { 413 final double heightRatio = h > totalHeight ? 1.0 : (double)h / (double)totalHeight; 414 final double widthRatio = w > totalWidth ? 1.0 : (double)w / (double)totalWidth; 415 416 final int northHeight = (int)(metrics.nCut * heightRatio); 417 final int southHeight = (int)(metrics.sCut * heightRatio); 418 final int centerHeight = h - northHeight - southHeight; 419 420 final int westWidth = (int)(metrics.wCut * widthRatio); 421 final int eastWidth = (int)(metrics.eCut * widthRatio); 422 final int centerWidth = w - westWidth - eastWidth; 423 424 if (NW != null) g.drawImage(NW, 0, 0, westWidth, northHeight, null); 425 if (N != null) g.drawImage(N, westWidth, 0, centerWidth, northHeight, null); 426 if (NE != null) g.drawImage(NE, w - eastWidth, 0, eastWidth, northHeight, null); 427 if (W != null) g.drawImage(W, 0, northHeight, westWidth, centerHeight, null); 428 if (C != null) g.drawImage(C, westWidth, northHeight, centerWidth, centerHeight, null); 429 if (E != null) g.drawImage(E, w - eastWidth, northHeight, eastWidth, centerHeight, null); 430 if (SW != null) g.drawImage(SW, 0, h - southHeight, westWidth, southHeight, null); 431 if (S != null) g.drawImage(S, westWidth, h - southHeight, centerWidth, southHeight, null); 432 if (SE != null) g.drawImage(SE, w - eastWidth, h - southHeight, eastWidth, southHeight, null); 433 } 434 } 435 436 public abstract static class RecyclableSlicedImageControl extends RecyclableObject<SlicedImageControl> { 437 final NineSliceMetrics metrics; 438 439 public RecyclableSlicedImageControl(final NineSliceMetrics metrics) { 440 this.metrics = metrics; 441 } 442 443 @Override 444 protected SlicedImageControl create() { 445 return new SlicedImageControl(createTemplateImage(metrics.minW, metrics.minH), metrics); 446 } 447 448 protected abstract Image createTemplateImage(final int width, final int height); 449 } 450 451 // when we use SystemColors, we need to proxy the color with something that implements UIResource, 452 // so that it will be uninstalled when the look and feel is changed. 453 private static class SystemColorProxy extends Color implements UIResource { 454 final Color color; 455 public SystemColorProxy(final Color color) { 456 super(color.getRGB()); 457 this.color = color; 458 } 459 460 public int getRGB() { 461 return color.getRGB(); 462 } 463 } 464 465 public static Color getWindowBackgroundColorUIResource() { 466 //return AquaNativeResources.getWindowBackgroundColorUIResource(); 467 return new SystemColorProxy(SystemColor.window); 468 } 469 470 public static Color getTextSelectionBackgroundColorUIResource() { 471 return new SystemColorProxy(SystemColor.textHighlight); 472 } 473 474 public static Color getTextSelectionForegroundColorUIResource() { 475 return new SystemColorProxy(SystemColor.textHighlightText); 476 } 477 478 public static Color getSelectionBackgroundColorUIResource() { 479 return new SystemColorProxy(SystemColor.controlHighlight); 480 } 481 482 public static Color getSelectionForegroundColorUIResource() { 483 return new SystemColorProxy(SystemColor.controlLtHighlight); 484 } 485 486 public static Color getFocusRingColorUIResource() { 487 return new SystemColorProxy(LWCToolkit.getAppleColor(LWCToolkit.KEYBOARD_FOCUS_COLOR)); 488 } 489 490 public static Color getSelectionInactiveBackgroundColorUIResource() { 491 return new SystemColorProxy(LWCToolkit.getAppleColor(LWCToolkit.INACTIVE_SELECTION_BACKGROUND_COLOR)); 492 } 493 494 public static Color getSelectionInactiveForegroundColorUIResource() { 495 return new SystemColorProxy(LWCToolkit.getAppleColor(LWCToolkit.INACTIVE_SELECTION_FOREGROUND_COLOR)); 496 } 497 } 498