├── .gitignore ├── Java8Support └── src │ └── org │ └── violetlib │ └── aqua │ ├── Aqua8MappedMultiResolutionImage.java │ ├── Aqua8MultiResolutionImage.java │ ├── Aqua8MultiResolutionImage2.java │ ├── Aqua8PopupFactory.java │ └── Java8Support.java ├── Java9Support ├── build.sh └── src │ └── org │ └── violetlib │ └── aqua │ ├── Aqua9MappedMultiResolutionImage.java │ ├── Aqua9MultiResolutionImage.java │ ├── Aqua9MultiResolutionImage2.java │ ├── Aqua9PopupFactory.java │ └── Java9Support.java ├── README.md ├── libkeywindowpatch ├── AquaWrappedWindowDelegate.h ├── AquaWrappedWindowDelegate.m ├── CMenuBarCategory.h ├── CMenuBarCategory.m ├── CMenuItemCategory.h ├── CMenuItemCategory.m ├── KeyWindowPatch.h └── KeyWindowPatch.m ├── libvaqua ├── AquaNativeSupport.h ├── AquaNativeSupport.m ├── AquaSidebarBackground.h ├── AquaSidebarBackground.m ├── AquaVisualEffectView.h ├── AquaVisualEffectView.m ├── AquaWrappedAWTView.h ├── AquaWrappedAWTView.m ├── JavaWindowAccess.h ├── JavaWindowAccess.m ├── jnix.h ├── jnu.h └── jnu_support.m ├── libwindowstylepatch └── WindowStylePatch.m ├── license ├── LICENSE ├── Quaqua License.html └── TreeTable Introduction Post.pdf ├── release └── build.xml ├── resources └── org │ └── violetlib │ └── aqua │ ├── Labels.properties │ ├── Labels_de.properties │ ├── Labels_en.properties │ ├── Labels_fr.properties │ ├── Labels_it.properties │ ├── Labels_sv.properties │ └── fc │ ├── ExpandArrowTemplate.png │ └── ExpandArrowTemplate@2x.png └── src └── org └── violetlib ├── aqua ├── AnimationController.java ├── AppearanceColorsBuilder.java ├── AppearanceContext.java ├── AppearanceManager.java ├── AquaAppearance.java ├── AquaAppearances.java ├── AquaBackgroundBorder.java ├── AquaBasicPopupMenuWrapper.java ├── AquaBorder.java ├── AquaBoxPainter.java ├── AquaButtonBorder.java ├── AquaButtonCheckBoxUI.java ├── AquaButtonExtendedTypes.java ├── AquaButtonIcon.java ├── AquaButtonLabeledUI.java ├── AquaButtonRadioUI.java ├── AquaButtonSupport.java ├── AquaButtonToggleUI.java ├── AquaButtonUI.java ├── AquaCaret.java ├── AquaCellBorder.java ├── AquaCellEditorPolicy.java ├── AquaCheckBoxButtonBorder.java ├── AquaColorChooserDialog.java ├── AquaColors.java ├── AquaComboBoxButton.java ├── AquaComboBoxPopup.java ├── AquaComboBoxPopupMenuUI.java ├── AquaComboBoxRenderer.java ├── AquaComboBoxType.java ├── AquaComboBoxUI.java ├── AquaComponentUI.java ├── AquaContextualColorImpl.java ├── AquaContextualPopup.java ├── AquaCustomStyledWindow.java ├── AquaDefaultFocusRingProvider.java ├── AquaDisclosureButtonBorder.java ├── AquaDisclosureTriangleButtonBorder.java ├── AquaDragRecognitionSupport.java ├── AquaEditorPaneUI.java ├── AquaEditorPaneUIDelegate.java ├── AquaExtendedPopup.java ├── AquaFieldView.java ├── AquaFocusHandler.java ├── AquaFocusRingManager.java ├── AquaFocusRingPainter.java ├── AquaFonts.java ├── AquaGroupBorder.java ├── AquaIcon.java ├── AquaIconToggleButtonBorder.java ├── AquaImageFactory.java ├── AquaInternalFrameBorder.java ├── AquaInternalFrameDockIconUI.java ├── AquaInternalFrameManager.java ├── AquaInternalFramePaneUI.java ├── AquaInternalFrameUI.java ├── AquaKeyBindings.java ├── AquaLabelUI.java ├── AquaLabeledButtonBorder.java ├── AquaLineBorder.java ├── AquaListMouseBehavior.java ├── AquaListUI.java ├── AquaLookAndFeel.java ├── AquaMarginView.java ├── AquaMenuBarBorder.java ├── AquaMenuBarUI.java ├── AquaMenuItemBorder.java ├── AquaMenuItemUI.java ├── AquaMenuSupport.java ├── AquaMenuUI.java ├── AquaMnemonicHandler.java ├── AquaMultiResolutionImage.java ├── AquaNamedButtonBorder.java ├── AquaNativeColorChooser.java ├── AquaNativeSupport.java ├── AquaOptionPaneUI.java ├── AquaOverlayScrollPaneController.java ├── AquaOverlayScrollPaneLayout.java ├── AquaPainting.java ├── AquaPanelUI.java ├── AquaPopup.java ├── AquaPopupFactory.java ├── AquaPopupMenuSeparatorUI.java ├── AquaPopupMenuUI.java ├── AquaProgressBarUI.java ├── AquaPushButtonBorder.java ├── AquaRadioButtonBorder.java ├── AquaRootPaneUI.java ├── AquaScrollBar.java ├── AquaScrollBarUI.java ├── AquaScrollPaneUI.java ├── AquaScrollingPopupMenuWrapper.java ├── AquaSegmentedButtonBorder.java ├── AquaSeparatorUI.java ├── AquaSharedColorChooser.java ├── AquaSheetSupport.java ├── AquaSliderUI.java ├── AquaSpinnerUI.java ├── AquaSplitPaneDivider.java ├── AquaSplitPaneUI.java ├── AquaTabbedPaneCopyFromBasicUI.java ├── AquaTabbedPaneTabState.java ├── AquaTabbedPaneUI.java ├── AquaTableHeaderBorder.java ├── AquaTableHeaderCellRenderer.java ├── AquaTableHeaderUI.java ├── AquaTableScrollPaneCorner.java ├── AquaTableUI.java ├── AquaTextAreaUI.java ├── AquaTextAreaUIDelegate.java ├── AquaTextComponentBorder.java ├── AquaTextComponentDelegatedUIBase.java ├── AquaTextComponentSupport.java ├── AquaTextComponentUIBase.java ├── AquaTextComponentUIDelegate.java ├── AquaTextFieldFormattedUI.java ├── AquaTextFieldSearch.java ├── AquaTextFieldUI.java ├── AquaTextFieldUIDelegate.java ├── AquaTextPaneUI.java ├── AquaTextPaneUIBase.java ├── AquaTextPaneUIDelegate.java ├── AquaTextPasswordFieldUI.java ├── AquaTitleBar.java ├── AquaToggleButtonBorder.java ├── AquaToolBarSeparatorUI.java ├── AquaToolBarUI.java ├── AquaToolTipUI.java ├── AquaTreeBorder.java ├── AquaTreeCellEditor.java ├── AquaTreeEditorBorder.java ├── AquaTreeMouseBehavior.java ├── AquaTreeTableUI.java ├── AquaTreeUI.java ├── AquaUtilControlSize.java ├── AquaUtils.java ├── AquaVibrantSupport.java ├── AquaViewStyleContainerUI.java ├── AquaViewportUI.java ├── BackgroundPainter.java ├── BasicAquaAppearance.java ├── BasicColors.java ├── BasicColorsBuilder.java ├── BasicContextualColors.java ├── BasicContextualColorsImpl.java ├── BasicTableUIPainter.java ├── Border2D.java ├── ClientPropertyApplicator.java ├── Colors.java ├── ColorsBuilder.java ├── ColorsInstrumentation.java ├── ComponentTracker.java ├── ComponentVibrantEffects.java ├── ContainerContextualColors.java ├── ContextualColor.java ├── DelegatedContainerContextualColors.java ├── DynamicIcon.java ├── EffectName.java ├── EmptyIcon.java ├── ExtendedVariableHeightLayoutCache.java ├── FocusRingOutlineProvider.java ├── FocusRingPainter.java ├── GenericList.java ├── GradientColor.java ├── ImageIconUIResource.java ├── Images.java ├── JListModel.java ├── JTableModel.java ├── JavaSupport.java ├── KeyWindowPatch.java ├── LazyActionMap.java ├── ListSelectionBoundsTracker.java ├── Logger.java ├── MenuSelectionBoundsTracker.java ├── MenuVibrantEffects.java ├── NativeOverlayView.java ├── OSXSystemProperties.java ├── OutlineFocusRingPainter.java ├── OverlayPainterComponent.java ├── OverlayScrollPaneHack.java ├── ProcessedImageCache.java ├── SegmentedControlModel.java ├── SelectionBoundsDescription.java ├── SelectionBoundsTracker.java ├── SelectionRegion.java ├── SelectionRepaintable.java ├── SharedColorChooserOwner.java ├── StripedContainerContextualColors.java ├── SystemColors.java ├── SystemPropertyChangeManager.java ├── TintedEraser.java ├── ToolbarSensitiveUI.java ├── TreeSelectionBoundsTracker.java ├── TreeTableModel.java ├── UIAction.java ├── UniformContainerContextualColors.java ├── Utils.java ├── VAquaRenderingAccess.java ├── VImageCache.java ├── VisibleBounds.java ├── VisualEffectView.java ├── VisualEffectViewPeer.java ├── WindowDraggingMouseListener.java ├── WindowStylePatch.java ├── fc │ ├── AbstractFileChooserBrowserListUI.java │ ├── AquaFileChooserBrowser.java │ ├── AquaFileChooserBrowserListUI.java │ ├── AquaFileChooserListMouseBehavior.java │ ├── AquaFileChooserTreeTableUI.java │ ├── AquaFileChooserUI.java │ ├── AquaFileIcon.java │ ├── AquaFileIcons.java │ ├── AquaFileSystemView.java │ ├── AquaFileView.java │ ├── ArrayUtil.java │ ├── BasicBrowserUI.java │ ├── BasicOSXFileSystemView.java │ ├── BrowserCellRenderer.java │ ├── BrowserPreviewRenderer.java │ ├── BrowserUI.java │ ├── CatalinaFileIconServiceImpl.java │ ├── ColumnView.java │ ├── ColumnViewImpl.java │ ├── CompositeTransferable.java │ ├── ConcurrentDispatcher.java │ ├── DefaultColumnCellRenderer.java │ ├── DefaultTransferable.java │ ├── DelegatedFileSystemViewBase.java │ ├── EventLoop.java │ ├── FileAttributes.java │ ├── FileChooserView.java │ ├── FileIconService.java │ ├── FileIconServiceImplBase.java │ ├── FileInfo.java │ ├── FilePreview.java │ ├── FilePreviewView.java │ ├── FileRenderer.java │ ├── FileSystemTreeModel.java │ ├── FileTransferHandler.java │ ├── FilenameDocument.java │ ├── GenericCellRenderer.java │ ├── HybridFileIconServiceImpl.java │ ├── IteratorEnumeration.java │ ├── JBrowser.java │ ├── ListView.java │ ├── ListViewImpl.java │ ├── NameView.java │ ├── OSXCollator.java │ ├── OSXFile.java │ ├── OSXFileSystemView.java │ ├── OverlayContainer.java │ ├── SavedSearchFileSystemTreeModel.java │ ├── SequentialDispatcher.java │ ├── SidebarTreeModel.java │ ├── SidebarTreeNode.java │ ├── SubtreeFileChooserUI.java │ ├── SubtreeTreeModel.java │ ├── ViewModeControl.java │ ├── ViewModeControlImpl.java │ └── Worker.java └── resources │ ├── aqua.properties │ ├── aqua_de.properties │ ├── aqua_es.properties │ ├── aqua_fr.properties │ ├── aqua_it.properties │ ├── aqua_ja.properties │ ├── aqua_ko.properties │ ├── aqua_pt_BR.properties │ ├── aqua_sv.properties │ ├── aqua_zh_CN.properties │ └── aqua_zh_TW.properties └── treetable ├── AbstractTreeColumnModel.java ├── AbstractTreeModel.java ├── CellEditorContainer.java ├── DefaultTreeColumnModel.java ├── DefaultTreeTableCellEditor.java ├── DefaultTreeTableCellRenderer.java ├── DefaultTreeTableNode.java ├── DefaultTreeTableSorter.java ├── IconMap.java ├── MutableTreeTableNode.java ├── ToolTipMap.java ├── TreeColumnModel.java ├── TreeTable.java ├── TreeTableCellEditor.java ├── TreeTableCellRenderer.java ├── TreeTableModel.java ├── TreeTableNode.java ├── TreeTableSorter.java ├── event ├── TreeColumnModelEvent.java ├── TreeColumnModelListener.java ├── TreeTableMouseEvent.java ├── TreeTableMouseListener.java ├── TreeTableMouseMotionListener.java ├── TreeTableSorterEvent.java └── TreeTableSorterListener.java └── ui ├── BasicTreeTableUI.java ├── InternalTableWithMargins.java ├── TableInterface.java ├── TreeInterface.java └── TreeTableUI.java /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | /archive 3 | /properties.txt 4 | /dist 5 | /out 6 | /release/out 7 | /release/dist 8 | /resources/libvaqua.dylib 9 | /deploy 10 | /VAqua.iml 11 | Java8Support.iml 12 | Java9Support.iml 13 | /lib 14 | /build.xml 15 | -------------------------------------------------------------------------------- /Java8Support/src/org/violetlib/aqua/Aqua8MultiResolutionImage2.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015-2016 Alan Snyder. 3 | * All rights reserved. 4 | * 5 | * You may not use, copy or modify this file, except in compliance with the license agreement. For details see 6 | * accompanying license terms. 7 | */ 8 | 9 | package org.violetlib.aqua; 10 | 11 | import java.awt.*; 12 | import java.awt.image.BufferedImage; 13 | import java.util.ArrayList; 14 | import java.util.List; 15 | import java.util.function.Function; 16 | 17 | import sun.awt.image.MultiResolutionImage; 18 | 19 | /** 20 | * A multi-resolution image with a 1x and a 2x representation. This class is designed for Java 8. 21 | */ 22 | public class Aqua8MultiResolutionImage2 extends AquaMultiResolutionImage implements MultiResolutionImage { 23 | private final BufferedImage im1; 24 | private final BufferedImage im2; 25 | 26 | public Aqua8MultiResolutionImage2(BufferedImage im1, BufferedImage im2) { 27 | super(im1); 28 | this.im1 = im1; 29 | this.im2 = im2; 30 | } 31 | 32 | @Override 33 | public Image getResolutionVariant(int width, int height) { 34 | return width > baseImageWidth || height > baseImageHeight ? im2 : im1; 35 | } 36 | 37 | @Override 38 | public List getResolutionVariants() { 39 | List result = new ArrayList<>(); 40 | result.add(im1); 41 | result.add(im2); 42 | return result; 43 | } 44 | 45 | @Override 46 | public AquaMultiResolutionImage map(Mapper mapper) { 47 | BufferedImage m1 = mapper.map(im1, 1); 48 | BufferedImage m2 = im2 != null ? mapper.map(im2, 2) : null; 49 | return new Aqua8MultiResolutionImage2(m1, m2); 50 | } 51 | 52 | @Override 53 | public AquaMultiResolutionImage map(Function mapper) { 54 | BufferedImage m1 = Images.toBufferedImage(mapper.apply(im1)); 55 | BufferedImage m2 = Images.toBufferedImage(mapper.apply(im2)); 56 | return new Aqua8MultiResolutionImage2(m1, m2); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /Java8Support/src/org/violetlib/aqua/Aqua8PopupFactory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015-2018 Alan Snyder. 3 | * All rights reserved. 4 | * 5 | * You may not use, copy or modify this file, except in compliance with the license agreement. For details see 6 | * accompanying license terms. 7 | */ 8 | 9 | package org.violetlib.aqua; 10 | 11 | import java.awt.*; 12 | import java.lang.reflect.Method; 13 | import javax.swing.*; 14 | 15 | /** 16 | * A Java 8 specific popup factory. 17 | */ 18 | 19 | public class Aqua8PopupFactory extends AquaPopupFactory { 20 | 21 | @Override 22 | protected Popup getHeavyweightPopup(Component owner, Component contents, int x, int y) { 23 | // Heavy weight popups are required to support vibrant backgrounds and rounded corners. 24 | // If we cannot configure this factory to create heavy weight popups, we will create a new popup directly. 25 | try { 26 | Method m = PopupFactory.class.getDeclaredMethod("setPopupType", Integer.TYPE); 27 | m.setAccessible(true); 28 | m.invoke(this, 2); 29 | } catch (Throwable e) { 30 | Utils.logError("Unable to setPopupType", e); 31 | return new AquaPopup(owner, contents, x, y); 32 | } 33 | 34 | Popup p = getDefaultPopup(owner, contents, x, y); 35 | 36 | // Reusing popups is not working reliably. Not sure if there is a general timing problem or a change in 37 | // behavior in El Capitan. The problem is that the stale contents are briefly displayed. 38 | // See bug JDK-8040630. 39 | 40 | try { 41 | Method m = p.getClass().getDeclaredMethod("setCacheEnabled", Boolean.TYPE); 42 | m.setAccessible(true); 43 | m.invoke(p, false); 44 | } catch (Exception ex) { 45 | Utils.logError("Unable to prevent popup from being reused", ex); 46 | } 47 | 48 | return p; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /Java9Support/build.sh: -------------------------------------------------------------------------------- 1 | JAVACMD=/build/jdk/java9.jdk/Contents/Home/bin/java ant 2 | -------------------------------------------------------------------------------- /Java9Support/src/org/violetlib/aqua/Aqua9MultiResolutionImage2.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Alan Snyder. 3 | * All rights reserved. 4 | * 5 | * You may not use, copy or modify this file, except in compliance with the license agreement. For details see 6 | * accompanying license terms. 7 | */ 8 | 9 | package org.violetlib.aqua; 10 | 11 | import java.awt.*; 12 | import java.awt.image.BufferedImage; 13 | import java.awt.image.MultiResolutionImage; 14 | import java.util.List; 15 | import java.util.ArrayList; 16 | import java.util.function.Function; 17 | 18 | /** 19 | * A multi-resolution image with a 1x and a 2x representation. This class is designed for Java 9. 20 | */ 21 | 22 | public class Aqua9MultiResolutionImage2 extends AquaMultiResolutionImage implements MultiResolutionImage { 23 | 24 | private final BufferedImage im1; 25 | private final BufferedImage im2; 26 | 27 | public Aqua9MultiResolutionImage2(BufferedImage im1, BufferedImage im2) { 28 | super(im1); 29 | this.im1 = im1; 30 | this.im2 = im2; 31 | } 32 | 33 | @Override 34 | public Image getResolutionVariant(double width, double height) { 35 | return width > baseImageWidth || height > baseImageHeight ? im2 : im1; 36 | } 37 | 38 | @Override 39 | public List getResolutionVariants() { 40 | List result = new ArrayList<>(); 41 | result.add(im1); 42 | result.add(im2); 43 | return result; 44 | } 45 | 46 | @Override 47 | public AquaMultiResolutionImage map(Mapper mapper) { 48 | BufferedImage m1 = mapper.map(im1, 1); 49 | BufferedImage m2 = im2 != null ? mapper.map(im2, 2) : null; 50 | return new Aqua9MultiResolutionImage2(m1, m2); 51 | } 52 | 53 | @Override 54 | public AquaMultiResolutionImage map(Function mapper) { 55 | BufferedImage m1 = Images.toBufferedImage(mapper.apply(im1)); 56 | BufferedImage m2 = Images.toBufferedImage(mapper.apply(im2)); 57 | return new Aqua9MultiResolutionImage2(m1, m2); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /Java9Support/src/org/violetlib/aqua/Aqua9PopupFactory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015-2018 Alan Snyder. 3 | * All rights reserved. 4 | * 5 | * You may not use, copy or modify this file, except in compliance with the license agreement. For details see 6 | * accompanying license terms. 7 | */ 8 | 9 | package org.violetlib.aqua; 10 | 11 | import java.awt.*; 12 | import javax.swing.*; 13 | 14 | /** 15 | * A popup factory for Java 9 and later. 16 | */ 17 | 18 | public class Aqua9PopupFactory extends AquaPopupFactory { 19 | 20 | @Override 21 | protected Popup getHeavyweightPopup(Component owner, Component contents, int x, int y) { 22 | // Heavy weight popups are required to support vibrant backgrounds and rounded corners. 23 | Popup p = super.getPopup(owner, contents, x, y, true); 24 | 25 | // Reusing popups is not working reliably. Not sure if there is a general timing problem or a change in 26 | // behavior in El Capitan. The problem is that the stale contents are briefly displayed. 27 | // See bug JDK-8040630. 28 | 29 | try { 30 | AquaUtils.disablePopupCache(p); 31 | } catch (Throwable th) { 32 | Utils.logError("Unable to prevent popup from being reused", th); 33 | } 34 | 35 | return p; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # VAqua 2 | 3 | An improved native Swing look and feel for macOS. 4 | 5 | [![Maven Central](https://maven-badges.herokuapp.com/maven-central/org.violetlib/vaqua/badge.svg)](https://search.maven.org/artifact/org.violetlib/vaqua) 6 | 7 | See [website](https://violetlib.org/vaqua/overview.html) for details and releases. 8 | -------------------------------------------------------------------------------- /libkeywindowpatch/AquaWrappedWindowDelegate.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Alan Snyder. 3 | * All rights reserved. 4 | * 5 | * You may not use, copy or modify this file, except in compliance with the license agreement. For details see 6 | * accompanying license terms. 7 | */ 8 | 9 | #import 10 | 11 | @interface AquaWrappedWindowDelegate : NSProxy 12 | - (instancetype)initWithObject:(id)object; 13 | @end 14 | -------------------------------------------------------------------------------- /libkeywindowpatch/CMenuBarCategory.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018-2023 Alan Snyder. 3 | * All rights reserved. 4 | * 5 | * You may not use, copy or modify this file, except in compliance with the license agreement. For details see 6 | * accompanying license terms. 7 | */ 8 | 9 | #import 10 | 11 | @interface CMenu : NSObject { } 12 | @end 13 | 14 | @interface CMenuBar : NSObject { 15 | @public 16 | NSMutableArray *fMenuList; 17 | BOOL fModallyDisabled; 18 | CMenu *fHelpMenu; 19 | } 20 | @end 21 | 22 | @interface CMenuBar (CMenuBarCategory) 23 | + (BOOL) isActiveMenuBar:(CMenuBar *)inMenuBar; 24 | + (void) activate:(CMenuBar *)menubar modallyDisabled:(BOOL)modallyDisabled; 25 | - (void) deactivate; 26 | - (void) javaAddMenu: (CMenu *)theMenu; 27 | - (void) javaAddMenu: (CMenu *)theMenu atIndex:(jint)index; 28 | - (void) javaDeleteMenu: (jint)index; 29 | @end 30 | -------------------------------------------------------------------------------- /libkeywindowpatch/CMenuItemCategory.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Alan Snyder. 3 | * All rights reserved. 4 | * 5 | * You may not use, copy or modify this file, except in compliance with the license agreement. For details see 6 | * accompanying license terms. 7 | */ 8 | 9 | #import 10 | 11 | // The following are minimal definitions to allow our altered methods to access the instance variables it needs. 12 | 13 | @interface CMenuComponent : NSObject { 14 | @public 15 | jobject fPeer; 16 | } 17 | @end 18 | 19 | @interface CMenuItem : CMenuComponent 20 | { 21 | BOOL fIsCheckbox; 22 | } 23 | @end 24 | 25 | @interface CMenuItem (CMenuItemCategory) 26 | - (void)handleAction:(NSMenuItem *)sender; 27 | @end 28 | 29 | @interface ApplicationDelegate { } 30 | @end 31 | -------------------------------------------------------------------------------- /libkeywindowpatch/KeyWindowPatch.h: -------------------------------------------------------------------------------- 1 | //#define DEBUG_PATCH 2 | -------------------------------------------------------------------------------- /libkeywindowpatch/KeyWindowPatch.m: -------------------------------------------------------------------------------- 1 | /* 2 | * @(#)KeyWindowPatch.m 3 | * 4 | * Copyright (c) 2018-2023 Alan Snyder. 5 | * All rights reserved. 6 | * 7 | * You may not use, copy or modify this file, except in compliance with the license agreement. For details see 8 | * accompanying license terms. 9 | */ 10 | 11 | #import 12 | 13 | #include "jnix.h" 14 | #import "KeyWindowPatch.h" 15 | #import "AquaWrappedWindowDelegate.h" 16 | #import "CMenuItemCategory.h" 17 | #import "CMenuBarCategory.h" 18 | 19 | void ensureWindowDelegateWrapper(NSWindow *w); 20 | 21 | /* 22 | * Class: org_violetlib_aqua_KeyWindowPatch 23 | * Method: nativeEnsureWindowDelegateInstalled 24 | * Signature: (J)I 25 | */ 26 | JNIEXPORT jint JNICALL Java_org_violetlib_aqua_KeyWindowPatch_nativeEnsureWindowDelegateInstalled 27 | (JNIEnv *env, jclass cl, jlong wptr) 28 | { 29 | COCOA_ENTER(); 30 | 31 | void (^block)() = ^(){ 32 | NSWindow *w = (NSWindow *) wptr; 33 | ensureWindowDelegateWrapper(w); 34 | }; 35 | 36 | // avoid deadlock if invoked on a thread other than the main thread by not waiting 37 | APPKIT_EXEC_NOW_OR_LATER(block); 38 | 39 | COCOA_EXIT(); 40 | } 41 | 42 | // Ensure that our wrapper window delegate is installed. 43 | 44 | void ensureWindowDelegateWrapper(NSWindow *w) 45 | { 46 | id delegate = [w delegate]; 47 | if (![delegate isKindOfClass: [AquaWrappedWindowDelegate class]]) { 48 | #ifdef DEBUG_PATCH 49 | NSLog(@"Installing window delegate: %@ %@", [w title], delegate); 50 | #endif 51 | delegate = [[AquaWrappedWindowDelegate alloc] initWithObject: delegate]; 52 | [w setDelegate: delegate]; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /libvaqua/AquaNativeSupport.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018-2021 Alan Snyder. 3 | * All rights reserved. 4 | * 5 | * You may not use, copy or modify this file, except in compliance with the license agreement. For details see 6 | * accompanying license terms. 7 | */ 8 | 9 | #ifndef __AQUA_NATIVE_SUPPORT__ 10 | #define __AQUA_NATIVE_SUPPORT__ 11 | 12 | void deliverWindowChangedAppearance(NSWindow *window, NSAppearance *appearance); 13 | void runOnMainThread(void (^block)()); 14 | long getJavaVersion(); 15 | 16 | #endif /* __AQUA_NATIVE_SUPPORT__ */ 17 | -------------------------------------------------------------------------------- /libvaqua/AquaSidebarBackground.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015-2021 Alan Snyder. 3 | * All rights reserved. 4 | * 5 | * You may not use, copy or modify this file, except in compliance with the license agreement. For details see 6 | * accompanying license terms. 7 | */ 8 | 9 | #import 10 | #import "AquaVisualEffectView.h" 11 | 12 | @interface AquaSidebarBackground : AquaVisualEffectView 13 | - (AquaSidebarBackground *) initWithFrame: (NSRect) frameRect style: (UInt16) style forceActive: (BOOL) forceActive; 14 | - (void) updateSelectionViews: (int*) data; 15 | @end 16 | -------------------------------------------------------------------------------- /libvaqua/AquaVisualEffectView.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018-2021 Alan Snyder. 3 | * All rights reserved. 4 | * 5 | * You may not use, copy or modify this file, except in compliance with the license agreement. For details see 6 | * accompanying license terms. 7 | */ 8 | 9 | #ifndef __VISUAL_EFFECT_VIEW__ 10 | #define __VISUAL_EFFECT_VIEW__ 11 | 12 | #import 13 | 14 | /* 15 | * A visual effect view that remembers the style specified by Java so that it can reconfigure itself when the 16 | * window appearance changes. 17 | * 18 | */ 19 | 20 | @interface AquaVisualEffectView : NSVisualEffectView 21 | @property UInt16 style; 22 | - (void) configureWithAppearance: (NSAppearance *) appearance; 23 | @end 24 | 25 | // Java constants for vibrant styles 26 | 27 | #define LIGHT_STYLE 0 28 | #define DARK_STYLE 1 29 | #define SIDEBAR_STYLE 2 30 | #define TITLE_BAR_STYLE 3 31 | #define MENU_STYLE 4 32 | #define POPOVER_STYLE 5 33 | #define MEDIUM_LIGHT_STYLE 6 34 | #define ULTRA_DARK_STYLE 7 35 | #define SHEET_STYLE 8 36 | #define SELECTION_STYLE 9 37 | #define HEADER_STYLE 10 38 | #define WINDOW_BACKGROUND_STYLE 11 39 | #define HUD_WINDOW_STYLE 12 40 | #define FULL_SCREEN_MODAL_STYLE 13 41 | #define TOOL_TIP_STYLE 14 42 | #define CONTENT_BACKGROUND_STYLE 15 43 | #define UNDER_WINDOW_BACKGROUND_STYLE 16 44 | #define UNDER_PAGE_BACKGROUND_STYLE 17 45 | 46 | #define EMPHASIZED_MATERIAL_MASK 0x1000 47 | 48 | #endif /* __VISUAL_EFFECT_VIEW__ */ 49 | -------------------------------------------------------------------------------- /libvaqua/AquaWrappedAWTView.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015-2018 Alan Snyder. 3 | * All rights reserved. 4 | * 5 | * You may not use, copy or modify this file, except in compliance with the license agreement. For details see 6 | * accompanying license terms. 7 | */ 8 | 9 | #ifndef __AQUA_WRAPPED_AWT_VIEW__ 10 | #define __AQUA_WRAPPED_AWT_VIEW__ 11 | 12 | #import 13 | #import "AquaVisualEffectView.h" 14 | 15 | @interface AquaWrappedAWTView : NSView 16 | - (instancetype) initWithAWTView: (NSView *) awtView; 17 | - (NSView *) awtView; 18 | - (int) configureAsPopup: (CGFloat) cornerRadius; 19 | - (AquaVisualEffectView *) addFullWindowVisualEffectView; 20 | - (void) addSiblingView: (NSView *) view; 21 | - (void) removeFullWindowVisualEffectView; 22 | - (void) deliverJavaMouseEvent: (NSEvent *) event; 23 | - (BOOL) mouseIsOver; 24 | @end 25 | 26 | #endif /* __AQUA_WRAPPED_AWT_VIEW__ */ 27 | -------------------------------------------------------------------------------- /libvaqua/JavaWindowAccess.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018-2020 Alan Snyder. 3 | * All rights reserved. 4 | * 5 | * You may not use, copy or modify this file, except in compliance with the license agreement. For details see 6 | * accompanying license terms. 7 | */ 8 | 9 | // Support for mapping a native window to a Java window or a Java platform window (CPlatformWindow). 10 | 11 | #import 12 | #import 13 | 14 | jobject getJavaWindow(JNIEnv *env, NSWindow *w); 15 | jobject getJavaPlatformWindow(JNIEnv *env, NSWindow *w); 16 | -------------------------------------------------------------------------------- /libvaqua/JavaWindowAccess.m: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018-2023 Alan Snyder. 3 | * All rights reserved. 4 | * 5 | * You may not use, copy or modify this file, except in compliance with the license agreement. For details see 6 | * accompanying license terms. 7 | */ 8 | 9 | // Support for mapping a native window to a Java window. 10 | 11 | #include "jnix.h" 12 | #import "JavaWindowAccess.h" 13 | #import "AquaNativeSupport.h" 14 | 15 | static jclass jc_CPlatformWindow; 16 | static jfieldID jf_target; 17 | 18 | // Map a native window to its Java window, if possible. 19 | jobject getJavaWindow(JNIEnv *env, NSWindow *w) 20 | { 21 | jobject jPlatformWindow = getJavaPlatformWindow(env, w); 22 | if (jPlatformWindow) { 23 | GET_CLASS_RETURN(jc_CPlatformWindow, "sun/lwawt/macosx/CPlatformWindow", NULL); 24 | GET_FIELD_RETURN(jf_target, jc_CPlatformWindow, "target", "Ljava/awt/Window;", NULL); 25 | jobject result = (*env)->GetObjectField(env, jPlatformWindow, jf_target); 26 | CHECK_EXCEPTION(); 27 | return result; 28 | } 29 | return NULL; 30 | } 31 | 32 | // Map a native window to its Java platform window, if possible. 33 | jobject getJavaPlatformWindow(JNIEnv *env, NSWindow *w) 34 | { 35 | NSObject *delegate = [w delegate]; 36 | 37 | if ([delegate respondsToSelector: @selector(javaPlatformWindow)]) { 38 | long javaVersion = getJavaVersion(); 39 | if (javaVersion >= 1700000 40 | || (javaVersion >= 1500004 && javaVersion < 1600000) 41 | || (javaVersion >= 1300008 && javaVersion < 1400000) 42 | || (javaVersion >= 1100012 && javaVersion < 1300000) 43 | ) { 44 | return (*env)->NewLocalRef(env, [delegate javaPlatformWindow]); 45 | } else { 46 | /* JNFWeakJObjectWrapper */ NSObject *jPlatformWindowWrapper = [delegate javaPlatformWindow]; 47 | if (jPlatformWindowWrapper) { 48 | return [jPlatformWindowWrapper jObjectWithEnv:env]; 49 | } 50 | } 51 | } 52 | 53 | return NULL; 54 | } 55 | -------------------------------------------------------------------------------- /libvaqua/jnix.h: -------------------------------------------------------------------------------- 1 | #define _JNU_PREFIX vaqua 2 | 3 | #import 4 | #import 5 | -------------------------------------------------------------------------------- /license/TreeTable Introduction Post.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/violetlib/vaqua/ebd9609c4acd132b7625589a97dd3ca997759e6a/license/TreeTable Introduction Post.pdf -------------------------------------------------------------------------------- /resources/org/violetlib/aqua/fc/ExpandArrowTemplate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/violetlib/vaqua/ebd9609c4acd132b7625589a97dd3ca997759e6a/resources/org/violetlib/aqua/fc/ExpandArrowTemplate.png -------------------------------------------------------------------------------- /resources/org/violetlib/aqua/fc/ExpandArrowTemplate@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/violetlib/vaqua/ebd9609c4acd132b7625589a97dd3ca997759e6a/resources/org/violetlib/aqua/fc/ExpandArrowTemplate@2x.png -------------------------------------------------------------------------------- /src/org/violetlib/aqua/AppearanceContext.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Alan Snyder. 3 | * All rights reserved. 4 | * 5 | * You may not use, copy or modify this file, except in compliance with the license agreement. For details see 6 | * accompanying license terms. 7 | */ 8 | 9 | package org.violetlib.aqua; 10 | 11 | import org.jetbrains.annotations.NotNull; 12 | import org.violetlib.jnr.aqua.AquaUIPainter; 13 | 14 | /** 15 | * 16 | */ 17 | 18 | public class AppearanceContext { 19 | 20 | private final @NotNull AquaAppearance appearance; 21 | private final @NotNull AquaUIPainter.State state; 22 | private final boolean isSelected; 23 | private final boolean isIcon; 24 | 25 | /** 26 | * Create an appearance context 27 | * @param appearance The appearance to use. 28 | * @param state The component state. The {@code ACTIVE_DEFAULT} state is used for active components that own the 29 | * keyboard focus. 30 | * @param isSelected If true, use a color appropriate for a selected item, if one is defined. 31 | * @param isIcon If true, use a color appropriate for an icon label, if one is defined. 32 | */ 33 | 34 | public AppearanceContext(@NotNull AquaAppearance appearance, 35 | @NotNull AquaUIPainter.State state, 36 | boolean isSelected, 37 | boolean isIcon) { 38 | this.appearance = appearance; 39 | this.state = state; 40 | this.isSelected = isSelected; 41 | this.isIcon = isIcon; 42 | } 43 | 44 | public @NotNull AquaAppearance getAppearance() { 45 | return appearance; 46 | } 47 | 48 | public @NotNull AquaUIPainter.State getState() { 49 | return state; 50 | } 51 | 52 | public boolean isSelected() { 53 | return isSelected; 54 | } 55 | 56 | public boolean isIcon() { 57 | return isIcon; 58 | } 59 | 60 | public @NotNull AppearanceContext withSelected(boolean b) { 61 | return b == isSelected ? this : new AppearanceContext(appearance, state, b, isIcon); 62 | } 63 | 64 | public @NotNull AppearanceContext withState(@NotNull AquaUIPainter.State state) { 65 | return state == this.state ? this : new AppearanceContext(appearance, state, isSelected, isIcon); 66 | } 67 | 68 | @Override 69 | public @NotNull String toString() { 70 | String s = "[" + appearance.getName() + " " + state; 71 | if (isSelected) { 72 | s += " Selected"; 73 | } 74 | if (isIcon) { 75 | s += " Icon"; 76 | } 77 | return s + "]"; 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/org/violetlib/aqua/AquaBackgroundBorder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 Alan Snyder. 3 | * All rights reserved. 4 | * 5 | * You may not use, copy or modify this file, except in compliance with the license agreement. For details see 6 | * accompanying license terms. 7 | */ 8 | 9 | package org.violetlib.aqua; 10 | 11 | import java.awt.*; 12 | 13 | import javax.swing.border.Border; 14 | 15 | import org.jetbrains.annotations.NotNull; 16 | import org.jetbrains.annotations.Nullable; 17 | 18 | /** 19 | * A "border" that actually paints a background. Used by AquaTextComponentUI. 20 | */ 21 | public interface AquaBackgroundBorder extends Border { 22 | 23 | void paintBackground(@NotNull Component c, Graphics g, @Nullable Color background); 24 | } 25 | -------------------------------------------------------------------------------- /src/org/violetlib/aqua/AquaBasicPopupMenuWrapper.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015-2018 Alan Snyder. 3 | * All rights reserved. 4 | * 5 | * You may not use, copy or modify this file, except in compliance with the license agreement. For details see 6 | * accompanying license terms. 7 | */ 8 | 9 | package org.violetlib.aqua; 10 | 11 | import java.awt.*; 12 | import javax.swing.*; 13 | import javax.swing.border.Border; 14 | 15 | /** 16 | * The container that wraps a component to support rounded corners. Used for contextual menus, pop up and pull down 17 | * menus, but not for editable combo box menus. 18 | */ 19 | public class AquaBasicPopupMenuWrapper extends JPanel { 20 | 21 | public AquaBasicPopupMenuWrapper(JComponent c, Border border) { 22 | super(null); 23 | 24 | setLayout(new BorderLayout()); 25 | add(c); 26 | setBorder(border); 27 | setOpaque(false); 28 | } 29 | 30 | @Override 31 | public void paintComponent(Graphics g) { 32 | 33 | // The following code supports pop up menus with rounded corners. The key requirement is that the popup must 34 | // not paint near the corners. 35 | 36 | Border border = getBorder(); 37 | if (border instanceof BackgroundPainter) { 38 | BackgroundPainter p = (BackgroundPainter) border; 39 | Rectangle bounds = getBounds(); 40 | p.paintBackground(this, g, bounds.x, bounds.y, bounds.width, bounds.height); 41 | } 42 | 43 | super.paintComponent(g); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/org/violetlib/aqua/AquaButtonCheckBoxUI.java: -------------------------------------------------------------------------------- 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 org.violetlib.aqua; 27 | 28 | import javax.swing.*; 29 | import javax.swing.plaf.ComponentUI; 30 | 31 | import org.violetlib.aqua.AquaUtils.RecyclableSingleton; 32 | import org.violetlib.aqua.AquaUtils.RecyclableSingletonFromDefaultConstructor; 33 | 34 | public class AquaButtonCheckBoxUI extends AquaButtonLabeledUI { 35 | protected static final RecyclableSingleton instance = new RecyclableSingletonFromDefaultConstructor(AquaButtonCheckBoxUI.class); 36 | 37 | public static ComponentUI createUI(final JComponent b) { 38 | return instance.get(); 39 | } 40 | 41 | public AquaButtonCheckBoxUI() { 42 | super(new AquaCheckBoxButtonBorder()); 43 | } 44 | 45 | public String getPropertyPrefix() { 46 | return "CheckBox" + "."; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/org/violetlib/aqua/AquaButtonLabeledUI.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Changes copyright (c) 2015-2020 Alan Snyder. 3 | * All rights reserved. 4 | * 5 | * You may not use, copy or modify this file, except in compliance with the license agreement. For details see 6 | * accompanying license terms. 7 | */ 8 | 9 | /* 10 | * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. 11 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 12 | * 13 | * This code is free software; you can redistribute it and/or modify it 14 | * under the terms of the GNU General Public License version 2 only, as 15 | * published by the Free Software Foundation. Oracle designates this 16 | * particular file as subject to the "Classpath" exception as provided 17 | * by Oracle in the LICENSE file that accompanied this code. 18 | * 19 | * This code is distributed in the hope that it will be useful, but WITHOUT 20 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 21 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 22 | * version 2 for more details (a copy is included in the LICENSE file that 23 | * accompanied this code). 24 | * 25 | * You should have received a copy of the GNU General Public License version 26 | * 2 along with this work; if not, write to the Free Software Foundation, 27 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 28 | * 29 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 30 | * or visit www.oracle.com if you need additional information or have any 31 | * questions. 32 | */ 33 | 34 | package org.violetlib.aqua; 35 | 36 | import java.awt.*; 37 | import javax.swing.*; 38 | import javax.swing.border.Border; 39 | 40 | import org.jetbrains.annotations.NotNull; 41 | 42 | /** 43 | * The base class for check box and radio button UIs. These UIs are shared. 44 | */ 45 | public abstract class AquaButtonLabeledUI extends AquaButtonUI { 46 | 47 | protected final @NotNull AquaLabeledButtonBorder widgetBorder; 48 | 49 | public AquaButtonLabeledUI(@NotNull AquaLabeledButtonBorder border) { 50 | widgetBorder = border; 51 | } 52 | 53 | @Override 54 | protected @NotNull Border getDefaultBorder(@NotNull AbstractButton b, boolean isToolbar) { 55 | return widgetBorder; 56 | } 57 | 58 | @Override 59 | protected void paint(@NotNull Graphics2D g, @NotNull AbstractButton b) { 60 | Rectangle viewRect = new Rectangle(b.getWidth(), b.getHeight()); 61 | widgetBorder.paintButton(g, b, null, viewRect); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/org/violetlib/aqua/AquaButtonToggleUI.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Changes copyright (c) 2018 Alan Snyder. 3 | * All rights reserved. 4 | * 5 | * You may not use, copy or modify this file, except in compliance with the license agreement. For details see 6 | * accompanying license terms. 7 | */ 8 | 9 | /* 10 | * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. 11 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 12 | * 13 | * This code is free software; you can redistribute it and/or modify it 14 | * under the terms of the GNU General Public License version 2 only, as 15 | * published by the Free Software Foundation. Oracle designates this 16 | * particular file as subject to the "Classpath" exception as provided 17 | * by Oracle in the LICENSE file that accompanied this code. 18 | * 19 | * This code is distributed in the hope that it will be useful, but WITHOUT 20 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 21 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 22 | * version 2 for more details (a copy is included in the LICENSE file that 23 | * accompanied this code). 24 | * 25 | * You should have received a copy of the GNU General Public License version 26 | * 2 along with this work; if not, write to the Free Software Foundation, 27 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 28 | * 29 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 30 | * or visit www.oracle.com if you need additional information or have any 31 | * questions. 32 | */ 33 | 34 | package org.violetlib.aqua; 35 | 36 | import javax.swing.*; 37 | import javax.swing.plaf.ComponentUI; 38 | 39 | import org.violetlib.aqua.AquaUtils.RecyclableSingleton; 40 | import org.violetlib.aqua.AquaUtils.RecyclableSingletonFromDefaultConstructor; 41 | 42 | public class AquaButtonToggleUI extends AquaButtonUI { 43 | 44 | static final RecyclableSingleton aquaToggleButtonUI = new RecyclableSingletonFromDefaultConstructor(AquaButtonToggleUI.class); 45 | 46 | public static ComponentUI createUI(JComponent b) { 47 | return aquaToggleButtonUI.get(); 48 | } 49 | 50 | protected String getPropertyPrefix() { 51 | return "ToggleButton" + "."; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/org/violetlib/aqua/AquaCellBorder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020-2021 Alan Snyder. 3 | * All rights reserved. 4 | * 5 | * You may not use, copy or modify this file, except in compliance with the license agreement. For details see 6 | * accompanying license terms. 7 | */ 8 | 9 | package org.violetlib.aqua; 10 | 11 | import java.awt.*; 12 | import javax.swing.*; 13 | import javax.swing.border.AbstractBorder; 14 | import javax.swing.plaf.UIResource; 15 | 16 | import org.jetbrains.annotations.NotNull; 17 | 18 | /** 19 | * A context dependent border for list cells. 20 | */ 21 | @SuppressWarnings("serial") 22 | public class AquaCellBorder extends AbstractBorder implements UIResource { 23 | 24 | public static final @NotNull String RENDERER_CONTAINER_KEY = "JComponent.rendererContainer"; 25 | 26 | public Insets getBorderInsets(@NotNull Component c, @NotNull Insets insets) { 27 | boolean isInset = computeIsInset((JComponent)c); 28 | int top = isInset ? 5 : 1; 29 | int side = isInset ? 20 : 1; 30 | insets.top = insets.bottom = top; 31 | insets.left = insets.right = side; 32 | return insets; 33 | } 34 | 35 | private boolean computeIsInset(@NotNull JComponent c) { 36 | Container parent = c.getParent(); 37 | if (parent instanceof CellRendererPane) { 38 | parent = parent.getParent(); 39 | } 40 | 41 | if (parent != null) { 42 | AquaViewStyleContainerUI ui = AquaUtils.getUI((JComponent) parent, AquaViewStyleContainerUI.class); 43 | if (ui != null) { 44 | return ui.isInset(); 45 | } 46 | } 47 | 48 | Object o = c.getClientProperty(RENDERER_CONTAINER_KEY); 49 | if (o instanceof JComponent) { 50 | AquaViewStyleContainerUI ui = AquaUtils.getUI((JComponent) o, AquaViewStyleContainerUI.class); 51 | if (ui != null) { 52 | return ui.isInset(); 53 | } 54 | } 55 | 56 | return false; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/org/violetlib/aqua/AquaCheckBoxButtonBorder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 Alan Snyder. 3 | * All rights reserved. 4 | * 5 | * You may not use, copy or modify this file, except in compliance with the license agreement. For details see 6 | * accompanying license terms. 7 | */ 8 | 9 | package org.violetlib.aqua; 10 | 11 | import org.violetlib.jnr.aqua.AquaUIPainter.ButtonWidget; 12 | 13 | /** 14 | * A border for a checkbox. 15 | */ 16 | public class AquaCheckBoxButtonBorder extends AquaLabeledButtonBorder { 17 | public AquaCheckBoxButtonBorder() { 18 | super(ButtonWidget.BUTTON_CHECK_BOX, AquaButtonExtendedTypes.getWidgetInfo(ButtonWidget.BUTTON_CHECK_BOX)); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/org/violetlib/aqua/AquaComboBoxPopupMenuUI.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015-2021 Alan Snyder. 3 | * All rights reserved. 4 | * 5 | * You may not use, copy or modify this file, except in compliance with the license agreement. For details see 6 | * accompanying license terms. 7 | */ 8 | 9 | package org.violetlib.aqua; 10 | 11 | import java.awt.*; 12 | import javax.swing.*; 13 | import javax.swing.plaf.ComponentUI; 14 | 15 | import org.jetbrains.annotations.NotNull; 16 | import org.jetbrains.annotations.Nullable; 17 | 18 | /** 19 | * The UI for a combo box popup menu. It installs the intended menu border. Needed because a JPopupMenu uninstalls and 20 | * reinstalls the UI when the popup menu is shown. 21 | */ 22 | public class AquaComboBoxPopupMenuUI extends AquaPopupMenuUI { 23 | 24 | public static ComponentUI createUI(JComponent x) { 25 | return new AquaComboBoxPopupMenuUI(); 26 | } 27 | 28 | protected @Nullable ContainerContextualColors colorsForList; 29 | 30 | public AquaComboBoxPopupMenuUI() { 31 | } 32 | 33 | @Override 34 | public void installUI(JComponent c) { 35 | super.installUI(c); 36 | // When a pop up is shown, the UI is uninstalled and then reinstalled, which removes our border. 37 | if (c instanceof AquaComboBoxPopup) { 38 | AquaComboBoxPopup p = (AquaComboBoxPopup) c; 39 | p.updateContents(false); 40 | } 41 | } 42 | 43 | @Override 44 | protected @NotNull BasicContextualColors getMenuColors(Component c) { 45 | if (c instanceof JComboBox) { 46 | JComboBox cb = (JComboBox) c; 47 | if (cb.isEditable()) { 48 | return AquaColors.getComboBoxMenuColors(); 49 | } 50 | } 51 | return super.getMenuColors(c); 52 | } 53 | 54 | @Override 55 | protected boolean isVibrantSelectionSupportNeeded(Component owner) { 56 | return false; 57 | } 58 | 59 | @Override 60 | protected int getContextualMenuStyle(Component owner) { 61 | if (owner instanceof JComboBox) { 62 | JComboBox cb = (JComboBox) owner; 63 | if (cb.isEditable()) { 64 | return OSXSystemProperties.OSVersion >= 1014 ? SIMPLE_CONTEXTUAL_MENU_STYLE : ORDINARY_CONTEXTUAL_MENU_STYLE; 65 | } 66 | } 67 | return super.getContextualMenuStyle(owner); 68 | } 69 | 70 | public void configure(@NotNull JComboBox cb, @NotNull JList list) { 71 | if (colorsForList == null) { 72 | colorsForList = new DelegatedContainerContextualColors(getMenuColors(cb)); 73 | } 74 | AquaListUI ui = AquaUtils.getUI(list, AquaListUI.class); 75 | if (ui != null) { 76 | ui.configureAsMenu(!cb.isEditable()); 77 | ui.setColors(colorsForList); 78 | list.putClientProperty(AquaListUI.LIST_VIEW_STYLE_KEY, "inset"); 79 | } 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/org/violetlib/aqua/AquaComboBoxType.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 Alan Snyder. 3 | * All rights reserved. 4 | * 5 | * You may not use, copy or modify this file, except in compliance with the license agreement. For details see 6 | * accompanying license terms. 7 | */ 8 | 9 | package org.violetlib.aqua; 10 | 11 | /** 12 | * This enum distinguishes different types of controls that are represented in Swing using JComboBox. 13 | */ 14 | public enum AquaComboBoxType { 15 | EDITABLE_COMBO_BOX, // the standard combo box, with an editable text field 16 | POP_UP_MENU_BUTTON, // a button that brings up a pop up menu (custom for Aqua) 17 | PULL_DOWN_MENU_BUTTON // a button that brings up a pull down menu (custom for Aqua) 18 | } 19 | -------------------------------------------------------------------------------- /src/org/violetlib/aqua/AquaComponentUI.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Alan Snyder. 3 | * All rights reserved. 4 | * 5 | * You may not use, copy or modify this file, except in compliance with the license agreement. For details see 6 | * accompanying license terms. 7 | */ 8 | 9 | package org.violetlib.aqua; 10 | 11 | import javax.swing.*; 12 | 13 | import org.jetbrains.annotations.NotNull; 14 | 15 | /** 16 | 17 | */ 18 | 19 | public interface AquaComponentUI { 20 | 21 | void appearanceChanged(@NotNull JComponent c, @NotNull AquaAppearance appearance); 22 | 23 | void activeStateChanged(@NotNull JComponent c, boolean isActive); 24 | } 25 | -------------------------------------------------------------------------------- /src/org/violetlib/aqua/AquaDefaultFocusRingProvider.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015-2020 Alan Snyder. 3 | * All rights reserved. 4 | * 5 | * You may not use, copy or modify this file, except in compliance with the license agreement. For details see 6 | * accompanying license terms. 7 | */ 8 | 9 | package org.violetlib.aqua; 10 | 11 | import javax.swing.*; 12 | import java.awt.*; 13 | import java.awt.geom.Rectangle2D; 14 | 15 | import org.jetbrains.annotations.NotNull; 16 | 17 | /** 18 | * The default focus ring provider uses the bounds rectangle of the component. 19 | */ 20 | public class AquaDefaultFocusRingProvider implements FocusRingOutlineProvider { 21 | 22 | public static final float OUTLINE_OFFSET = 0; 23 | 24 | @Override 25 | public @NotNull Shape getFocusRingOutline(@NotNull JComponent c) { 26 | int width = c.getWidth(); 27 | int height = c.getHeight(); 28 | return new Rectangle2D.Double(OUTLINE_OFFSET, OUTLINE_OFFSET, width-2*OUTLINE_OFFSET, height-2*OUTLINE_OFFSET); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/org/violetlib/aqua/AquaDisclosureButtonBorder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015-2020 Alan Snyder. 3 | * All rights reserved. 4 | * 5 | * You may not use, copy or modify this file, except in compliance with the license agreement. For details see 6 | * accompanying license terms. 7 | */ 8 | 9 | package org.violetlib.aqua; 10 | 11 | import javax.swing.*; 12 | 13 | import org.jetbrains.annotations.NotNull; 14 | import org.violetlib.jnr.aqua.AquaUIPainter.ButtonState; 15 | import org.violetlib.jnr.aqua.AquaUIPainter.ButtonWidget; 16 | 17 | import static org.violetlib.jnr.aqua.AquaUIPainter.ButtonState.OFF; 18 | import static org.violetlib.jnr.aqua.AquaUIPainter.ButtonState.ON; 19 | 20 | /** 21 | * A border for a disclosure button. 22 | */ 23 | public class AquaDisclosureButtonBorder extends AquaButtonBorder implements FocusRingOutlineProvider { 24 | 25 | public AquaDisclosureButtonBorder() { 26 | } 27 | 28 | @Override 29 | public @NotNull ButtonWidget getButtonWidget(@NotNull AbstractButton b) { 30 | return ButtonWidget.BUTTON_DISCLOSURE; 31 | } 32 | 33 | @Override 34 | protected @NotNull ButtonState getButtonState(@NotNull AbstractButton b) { 35 | return b.getModel().isSelected() ? ON : OFF; 36 | } 37 | 38 | @Override 39 | public boolean allowsContent() { 40 | return false; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/org/violetlib/aqua/AquaDisclosureTriangleButtonBorder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015-2020 Alan Snyder. 3 | * All rights reserved. 4 | * 5 | * You may not use, copy or modify this file, except in compliance with the license agreement. For details see 6 | * accompanying license terms. 7 | */ 8 | 9 | package org.violetlib.aqua; 10 | 11 | import javax.swing.*; 12 | 13 | import org.jetbrains.annotations.NotNull; 14 | import org.violetlib.jnr.aqua.AquaUIPainter.ButtonState; 15 | import org.violetlib.jnr.aqua.AquaUIPainter.ButtonWidget; 16 | 17 | import static org.violetlib.jnr.aqua.AquaUIPainter.ButtonState.OFF; 18 | import static org.violetlib.jnr.aqua.AquaUIPainter.ButtonState.ON; 19 | 20 | /** 21 | * A border for a disclosure triangle button. 22 | */ 23 | public class AquaDisclosureTriangleButtonBorder extends AquaButtonBorder implements FocusRingOutlineProvider { 24 | 25 | public AquaDisclosureTriangleButtonBorder() { 26 | } 27 | 28 | @Override 29 | public @NotNull ButtonWidget getButtonWidget(@NotNull AbstractButton b) { 30 | return ButtonWidget.BUTTON_DISCLOSURE_TRIANGLE; 31 | } 32 | 33 | @Override 34 | protected @NotNull ButtonState getButtonState(AbstractButton b) { 35 | return b.getModel().isSelected() ? ON : OFF; 36 | } 37 | 38 | @Override 39 | public boolean allowsContent() { 40 | return false; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/org/violetlib/aqua/AquaEditorPaneUI.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Alan Snyder. 3 | * All rights reserved. 4 | * 5 | * You may not use, copy or modify this file, except in compliance with the license agreement. For details see 6 | * accompanying license terms. 7 | */ 8 | 9 | package org.violetlib.aqua; 10 | 11 | import javax.swing.*; 12 | import javax.swing.plaf.ComponentUI; 13 | 14 | /** 15 | * The UI for JEditorPane. 16 | */ 17 | public class AquaEditorPaneUI extends AquaTextPaneUIBase { 18 | 19 | public static ComponentUI createUI(JComponent c) { 20 | return new AquaEditorPaneUI(); 21 | } 22 | 23 | public AquaEditorPaneUI() { 24 | super(new AquaEditorPaneUIDelegate()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/org/violetlib/aqua/AquaExtendedPopup.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 Alan Snyder. 3 | * All rights reserved. 4 | * 5 | * You may not use, copy or modify this file, except in compliance with the license agreement. For details see 6 | * accompanying license terms. 7 | */ 8 | 9 | package org.violetlib.aqua; 10 | 11 | import java.awt.event.MouseEvent; 12 | 13 | /** 14 | * Optional methods that may be supported by a popup. 15 | */ 16 | public interface AquaExtendedPopup { 17 | 18 | /** 19 | * Enter arrow scrolling mode. 20 | */ 21 | void startArrowScroll(); 22 | 23 | /** 24 | * Exit arrow scrolling mode. 25 | */ 26 | void stopArrowScroll(); 27 | 28 | /** 29 | * Update the selection display as appropriate for a change in the mouse position. 30 | */ 31 | void updateSelection(MouseEvent e); 32 | } 33 | -------------------------------------------------------------------------------- /src/org/violetlib/aqua/AquaIconToggleButtonBorder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015-2020 Alan Snyder. 3 | * All rights reserved. 4 | * 5 | * You may not use, copy or modify this file, except in compliance with the license agreement. For details see 6 | * accompanying license terms. 7 | */ 8 | 9 | package org.violetlib.aqua; 10 | 11 | import java.awt.*; 12 | import javax.swing.*; 13 | 14 | import org.jetbrains.annotations.NotNull; 15 | import org.violetlib.jnr.aqua.AquaUIPainter.Size; 16 | 17 | /** 18 | * The border used for the icon button style. 19 | */ 20 | public class AquaIconToggleButtonBorder extends AquaToggleButtonBorder { 21 | 22 | @Override 23 | public @NotNull Font getCustomDefaultFont(@NotNull AbstractButton b, @NotNull Size size, @NotNull Font df) { 24 | float fontSize = AquaFonts.getControlTextSmallFont().getSize2D(); 25 | return df.deriveFont(fontSize); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/org/violetlib/aqua/AquaLineBorder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Changes copyright (c) 2018 Alan Snyder. 3 | * All rights reserved. 4 | * 5 | * You may not use, copy or modify this file, except in compliance with the license agreement. For details see 6 | * accompanying license terms. 7 | */ 8 | 9 | /* 10 | * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. 11 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 12 | * 13 | * This code is free software; you can redistribute it and/or modify it 14 | * under the terms of the GNU General Public License version 2 only, as 15 | * published by the Free Software Foundation. Oracle designates this 16 | * particular file as subject to the "Classpath" exception as provided 17 | * by Oracle in the LICENSE file that accompanied this code. 18 | * 19 | * This code is distributed in the hope that it will be useful, but WITHOUT 20 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 21 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 22 | * version 2 for more details (a copy is included in the LICENSE file that 23 | * accompanied this code). 24 | * 25 | * You should have received a copy of the GNU General Public License version 26 | * 2 along with this work; if not, write to the Free Software Foundation, 27 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 28 | * 29 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 30 | * or visit www.oracle.com if you need additional information or have any 31 | * questions. 32 | */ 33 | 34 | package org.violetlib.aqua; 35 | 36 | import java.awt.*; 37 | import javax.swing.border.Border; 38 | 39 | import org.jetbrains.annotations.NotNull; 40 | import org.jetbrains.annotations.Nullable; 41 | 42 | /** 43 | * The class renders a line border using an appearance based color. 44 | */ 45 | public class AquaLineBorder implements Border { 46 | 47 | private static final Insets borderInsets = new Insets(1, 1, 1, 1); 48 | 49 | private final String colorName; 50 | 51 | public AquaLineBorder(@NotNull String colorName) { 52 | this.colorName = colorName; 53 | } 54 | 55 | @Override 56 | public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) { 57 | Color color = getColor(c); 58 | if (color == null) { 59 | color = Color.gray; 60 | } 61 | 62 | g.setColor(color); 63 | g.fillRect(x, y, width, 1); 64 | g.fillRect(x, y+1, 1, height-2); 65 | g.fillRect(x, y + height - 1, width, 1); 66 | g.fillRect(x + width - 1, y+1, 1, height-2); 67 | } 68 | 69 | protected @Nullable Color getColor(@NotNull Component c) { 70 | AquaAppearance appearance = AppearanceManager.getAppearance(c); 71 | return appearance.getColor(colorName); 72 | } 73 | 74 | @Override 75 | public @NotNull Insets getBorderInsets(Component c) { 76 | return borderInsets; 77 | } 78 | 79 | @Override 80 | public boolean isBorderOpaque() { 81 | return false; 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/org/violetlib/aqua/AquaMenuBarBorder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Changes copyright (c) 2018 Alan Snyder. 3 | * All rights reserved. 4 | * 5 | * You may not use, copy or modify this file, except in compliance with the license agreement. For details see 6 | * accompanying license terms. 7 | */ 8 | 9 | /* 10 | * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. 11 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 12 | * 13 | * This code is free software; you can redistribute it and/or modify it 14 | * under the terms of the GNU General Public License version 2 only, as 15 | * published by the Free Software Foundation. Oracle designates this 16 | * particular file as subject to the "Classpath" exception as provided 17 | * by Oracle in the LICENSE file that accompanied this code. 18 | * 19 | * This code is distributed in the hope that it will be useful, but WITHOUT 20 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 21 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 22 | * version 2 for more details (a copy is included in the LICENSE file that 23 | * accompanied this code). 24 | * 25 | * You should have received a copy of the GNU General Public License version 26 | * 2 along with this work; if not, write to the Free Software Foundation, 27 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 28 | * 29 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 30 | * or visit www.oracle.com if you need additional information or have any 31 | * questions. 32 | */ 33 | 34 | package org.violetlib.aqua; 35 | 36 | import java.awt.Color; 37 | import java.awt.Component; 38 | import java.awt.Graphics; 39 | import java.awt.Insets; 40 | 41 | import javax.swing.border.Border; 42 | 43 | /** 44 | * The class represents the border of a {@code JMenuBar}. 45 | */ 46 | public class AquaMenuBarBorder implements Border { 47 | 48 | @Override 49 | public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) { 50 | g.setColor(Color.gray); 51 | AquaUtils.drawHLine(g, x, x + width - 1, y + height - 1); 52 | } 53 | 54 | @Override 55 | public Insets getBorderInsets(Component c) { 56 | return new Insets(0, 0, 1, 0); 57 | } 58 | 59 | @Override 60 | public boolean isBorderOpaque() { 61 | return false; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/org/violetlib/aqua/AquaMenuBarUI.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018-2021 Alan Snyder. 3 | * All rights reserved. 4 | * 5 | * You may not use, copy or modify this file, except in compliance with the license agreement. For details see 6 | * accompanying license terms. 7 | */ 8 | 9 | package org.violetlib.aqua; 10 | 11 | import java.awt.*; 12 | import javax.swing.*; 13 | import javax.swing.plaf.ComponentUI; 14 | import javax.swing.plaf.basic.BasicMenuBarUI; 15 | 16 | import org.jetbrains.annotations.NotNull; 17 | import org.jetbrains.annotations.Nullable; 18 | import org.violetlib.jnr.aqua.AquaUIPainter; 19 | 20 | /** 21 | * Support for menu bars that are not using the screen menu bar. 22 | */ 23 | public class AquaMenuBarUI extends BasicMenuBarUI implements AquaComponentUI { 24 | 25 | public static ComponentUI createUI(JComponent c) { 26 | return new AquaMenuBarUI(); 27 | } 28 | 29 | protected @NotNull BasicContextualColors colors; 30 | protected @Nullable AppearanceContext appearanceContext; 31 | 32 | public AquaMenuBarUI() { 33 | colors = AquaColors.CONTROL_COLORS; 34 | } 35 | 36 | protected void installDefaults() { 37 | super.installDefaults(); 38 | configureAppearanceContext(null); 39 | } 40 | 41 | @Override 42 | protected void installListeners() { 43 | super.installListeners(); 44 | AppearanceManager.installListeners(menuBar); 45 | } 46 | 47 | @Override 48 | protected void uninstallListeners() { 49 | AppearanceManager.uninstallListeners(menuBar); 50 | super.uninstallListeners(); 51 | } 52 | 53 | @Override 54 | public void appearanceChanged(@NotNull JComponent c, @NotNull AquaAppearance appearance) { 55 | configureAppearanceContext(appearance); 56 | } 57 | 58 | @Override 59 | public void activeStateChanged(@NotNull JComponent c, boolean isActive) { 60 | configureAppearanceContext(null); 61 | } 62 | 63 | protected void configureAppearanceContext(@Nullable AquaAppearance appearance) { 64 | if (appearance == null) { 65 | appearance = AppearanceManager.ensureAppearance(menuBar); 66 | } 67 | AquaUIPainter.State state = AquaUIPainter.State.ACTIVE; 68 | appearanceContext = new AppearanceContext(appearance, state, false, false); 69 | AquaColors.installColors(menuBar, appearanceContext, colors); 70 | menuBar.repaint(); 71 | } 72 | 73 | @Override 74 | public void update(Graphics g, JComponent c) { 75 | AppearanceManager.registerCurrentAppearance(c); 76 | super.update(g, c); 77 | } 78 | 79 | @Override 80 | public void paint(Graphics g, JComponent c) { 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/org/violetlib/aqua/AquaMenuItemBorder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 Alan Snyder. 3 | * All rights reserved. 4 | * 5 | * You may not use, copy or modify this file, except in compliance with the license agreement. For details see 6 | * accompanying license terms. 7 | */ 8 | 9 | package org.violetlib.aqua; 10 | 11 | import java.awt.*; 12 | 13 | /** 14 | * A border for a menu item. 15 | */ 16 | public class AquaMenuItemBorder extends AquaBorder { 17 | @Override 18 | public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) { 19 | } 20 | 21 | @Override 22 | public Insets getBorderInsets(Component c) { 23 | return new Insets(1, 5, 1, 5); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/org/violetlib/aqua/AquaNamedButtonBorder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015-2020 Alan Snyder. 3 | * All rights reserved. 4 | * 5 | * You may not use, copy or modify this file, except in compliance with the license agreement. For details see 6 | * accompanying license terms. 7 | */ 8 | 9 | package org.violetlib.aqua; 10 | 11 | import javax.swing.*; 12 | 13 | import org.jetbrains.annotations.NotNull; 14 | import org.violetlib.jnr.Insetter; 15 | import org.violetlib.jnr.aqua.AquaUIPainter; 16 | import org.violetlib.jnr.aqua.AquaUIPainter.ButtonWidget; 17 | import org.violetlib.jnr.aqua.AquaUIPainter.Size; 18 | import org.violetlib.jnr.aqua.ButtonLayoutConfiguration; 19 | 20 | /** 21 | * A border for a button with a client specified button style. 22 | */ 23 | public class AquaNamedButtonBorder extends AquaButtonBorder { 24 | 25 | protected final @NotNull ButtonWidget widget; 26 | private final @NotNull AquaButtonExtendedTypes.WidgetInfo info; 27 | private final boolean allowsContent; 28 | 29 | public AquaNamedButtonBorder(@NotNull ButtonWidget w, @NotNull AquaButtonExtendedTypes.WidgetInfo info) { 30 | this.widget = w; 31 | this.info = info; 32 | this.allowsContent = determineAllowsContent(w); 33 | } 34 | 35 | private boolean determineAllowsContent(@NotNull ButtonWidget w) { 36 | // Certain widgets do not allow content. For example, a help button. 37 | // We can figure this out, but note the assumption that the answer does not 38 | // depend upon the size variant. 39 | 40 | ButtonLayoutConfiguration g = new ButtonLayoutConfiguration(w, Size.REGULAR, AquaUIPainter.UILayoutDirection.LEFT_TO_RIGHT); 41 | Insetter s = painter.getLayoutInfo().getButtonLabelInsets(g); 42 | return s != null; 43 | } 44 | 45 | @Override 46 | public @NotNull ButtonWidget getButtonWidget(@NotNull AbstractButton b) { 47 | return widget; 48 | } 49 | 50 | @Override 51 | protected @NotNull AquaButtonExtendedTypes.WidgetInfo getWidgetInfo(@NotNull AbstractButton b) { 52 | return info; 53 | } 54 | 55 | @Override 56 | public boolean allowsContent() { 57 | return allowsContent; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/org/violetlib/aqua/AquaNativeColorChooser.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015-2017 Alan Snyder. 3 | * All rights reserved. 4 | * 5 | * You may not use, copy or modify this file, except in compliance with the license agreement. For details see 6 | * accompanying license terms. 7 | */ 8 | 9 | package org.violetlib.aqua; 10 | 11 | import java.awt.*; 12 | 13 | /** 14 | * Provide access to the shared NSColorPanel. 15 | */ 16 | public class AquaNativeColorChooser { 17 | 18 | private static boolean isInitialized; 19 | private static boolean isCreated; 20 | private static SharedColorChooserOwner currentOwner; 21 | 22 | private static SharedColorChooserOwner myOwner; 23 | 24 | public static boolean display(SharedColorChooserOwner owner, Color initialColor, boolean enableTranslucentColors) { 25 | if (!isInitialized) { 26 | isInitialized = true; 27 | 28 | if (!AquaNativeSupport.load()) { 29 | return false; 30 | } 31 | 32 | myOwner = new SharedColorChooserOwner() { 33 | @Override 34 | public void applyColor(Color c) { 35 | if (currentOwner != null) { 36 | currentOwner.applyColor(c); 37 | } 38 | } 39 | 40 | @Override 41 | public void disconnected() { 42 | if (currentOwner != null) { 43 | SharedColorChooserOwner o = currentOwner; 44 | currentOwner = null; 45 | o.disconnected(); 46 | } 47 | } 48 | }; 49 | isCreated = create(myOwner); 50 | } 51 | 52 | if (isCreated) { 53 | currentOwner = owner; 54 | float[] cs = initialColor.getRGBComponents(null); 55 | float alpha = enableTranslucentColors ? cs[3] : 0; 56 | show(cs[0], cs[1], cs[2], alpha, enableTranslucentColors); 57 | return true; 58 | } 59 | 60 | return false; 61 | } 62 | 63 | public static void disconnect() { 64 | currentOwner = null; 65 | hide(); 66 | } 67 | 68 | private static native boolean create(SharedColorChooserOwner owner); 69 | private static native void show(float r, float g, float b, float a, boolean isAlpha); 70 | private static native void hide(); 71 | } 72 | -------------------------------------------------------------------------------- /src/org/violetlib/aqua/AquaPainting.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015-2018 Alan Snyder. 3 | * All rights reserved. 4 | * 5 | * You may not use, copy or modify this file, except in compliance with the license agreement. For details see 6 | * accompanying license terms. 7 | */ 8 | 9 | package org.violetlib.aqua; 10 | 11 | import org.jetbrains.annotations.NotNull; 12 | import org.violetlib.jnr.aqua.AquaNativeRendering; 13 | import org.violetlib.jnr.aqua.AquaUIPainter; 14 | 15 | /** 16 | * Provides access to the native painter. 17 | */ 18 | public class AquaPainting { 19 | 20 | public static @NotNull AquaUIPainter create() { 21 | return AquaNativeRendering.createPainter(); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/org/violetlib/aqua/AquaPopup.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 Alan Snyder. 3 | * All rights reserved. 4 | * 5 | * You may not use, copy or modify this file, except in compliance with the license agreement. For details see 6 | * accompanying license terms. 7 | */ 8 | 9 | package org.violetlib.aqua; 10 | 11 | import java.awt.*; 12 | import javax.swing.*; 13 | 14 | /** 15 | * A heavy weight popup. Used only when unable to configure the standard popup factory. 16 | */ 17 | public class AquaPopup extends Popup { 18 | 19 | public AquaPopup(Component owner, Component contents, int x, int y) { 20 | super(owner, contents, x, y); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/org/violetlib/aqua/AquaPopupFactory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015-2023 Alan Snyder. 3 | * All rights reserved. 4 | * 5 | * You may not use, copy or modify this file, except in compliance with the license agreement. For details see 6 | * accompanying license terms. 7 | */ 8 | 9 | package org.violetlib.aqua; 10 | 11 | import java.awt.*; 12 | import javax.swing.*; 13 | 14 | /** 15 | * A custom popup factory that creates heavyweight popups and reconfigures reused popups. Custom behavior is disabled 16 | * when this look and feel is uninstalled. Custom behavior is implemented by platform-dependent subclasses. 17 | */ 18 | public abstract class AquaPopupFactory extends PopupFactory { 19 | protected boolean isActive; 20 | 21 | public boolean isActive() { 22 | return isActive; 23 | } 24 | 25 | public void setActive(boolean active) { 26 | isActive = active; 27 | } 28 | 29 | @Override 30 | public Popup getPopup(Component owner, Component contents, int x, int y) 31 | throws IllegalArgumentException { 32 | if (isActive) { 33 | Popup p = getHeavyweightPopup(owner, contents, x, y); 34 | return configure(owner, p, contents); 35 | } else { 36 | return super.getPopup(owner, contents, x, y); 37 | } 38 | } 39 | 40 | protected abstract Popup getHeavyweightPopup(Component owner, Component contents, int x, int y); 41 | 42 | // for use by subclasses 43 | protected Popup getDefaultPopup(Component owner, Component contents, int x, int y) 44 | { 45 | return super.getPopup(owner, contents, x, y); 46 | } 47 | 48 | private Popup configure(Component owner, Popup p, Component contents) { 49 | // If the popup is a reused popup, then we need to reconfigure it. 50 | // A new popup will have zero size because pack() is not called if the window is not visible (and why would 51 | // it be?) A reused popup will probably have the wrong size, for the same reason. 52 | 53 | Window w = SwingUtilities.getWindowAncestor(contents); 54 | AquaRootPaneUI ui = null; 55 | JRootPane rp = AquaUtils.getRootPane(w); 56 | if (rp != null) { 57 | ui = AquaUtils.getUI(rp, AquaRootPaneUI.class); 58 | if (ui == null) { 59 | rp.updateUI(); 60 | ui = AquaUtils.getUI(rp, AquaRootPaneUI.class); 61 | } 62 | } 63 | 64 | if (w.isDisplayable() && w.getWidth() > 0) { 65 | // The popup is reused. It will have the old size. 66 | w.setSize(w.getPreferredSize()); 67 | w.invalidate(); 68 | w.validate(); 69 | } 70 | 71 | if (ui != null) { 72 | String appearanceName = AppearanceManager.getSpecifiedAppearanceName(owner); 73 | AppearanceManager.setSpecifiedAppearanceName(rp, appearanceName); 74 | } 75 | 76 | // Workaround for JDK bug when popup owner is an embedded component 77 | AquaUtils.nativeFixPopupWindow((Window) w.getParent(), p); 78 | 79 | return p; 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/org/violetlib/aqua/AquaPushButtonBorder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015-2020 Alan Snyder. 3 | * All rights reserved. 4 | * 5 | * You may not use, copy or modify this file, except in compliance with the license agreement. For details see 6 | * accompanying license terms. 7 | */ 8 | 9 | package org.violetlib.aqua; 10 | 11 | import javax.swing.*; 12 | 13 | import org.jetbrains.annotations.NotNull; 14 | import org.violetlib.jnr.aqua.AquaUIPainter.ButtonWidget; 15 | 16 | /** 17 | * A border for a push button with no client specified button style. A generic button border must adapt to any size 18 | * text. It can use a fixed height style only if the text fits using that height. Otherwise, an alternate style must be 19 | * used. 20 | * 21 | * @see AquaToggleButtonBorder 22 | */ 23 | public class AquaPushButtonBorder extends AquaButtonBorder { 24 | 25 | @Override 26 | public @NotNull ButtonWidget getButtonWidget(@NotNull AbstractButton b) { 27 | boolean isOnToolbar = AquaUtils.isOnToolbar(b); 28 | 29 | ButtonWidget preferredWidget = isOnToolbar 30 | ? ButtonWidget.BUTTON_TEXTURED_TOOLBAR 31 | : ButtonWidget.BUTTON_PUSH; 32 | if (isProposedButtonWidgetUsable(b, preferredWidget)) { 33 | return preferredWidget; 34 | } 35 | 36 | if (b.getIcon() != null) { 37 | return isOnToolbar ? ButtonWidget.BUTTON_TOOLBAR_ITEM : ButtonWidget.BUTTON_GRADIENT; 38 | } 39 | 40 | return ButtonWidget.BUTTON_BEVEL_ROUND; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/org/violetlib/aqua/AquaRadioButtonBorder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 Alan Snyder. 3 | * All rights reserved. 4 | * 5 | * You may not use, copy or modify this file, except in compliance with the license agreement. For details see 6 | * accompanying license terms. 7 | */ 8 | 9 | package org.violetlib.aqua; 10 | 11 | import org.violetlib.jnr.aqua.AquaUIPainter.ButtonWidget; 12 | 13 | /** 14 | * A border for a radio button. 15 | */ 16 | public class AquaRadioButtonBorder extends AquaLabeledButtonBorder { 17 | public AquaRadioButtonBorder() { 18 | super(ButtonWidget.BUTTON_RADIO, AquaButtonExtendedTypes.getWidgetInfo(ButtonWidget.BUTTON_RADIO)); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/org/violetlib/aqua/AquaTableScrollPaneCorner.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015-2018 Alan Snyder. 3 | * All rights reserved. 4 | * 5 | * You may not use, copy or modify this file, except in compliance with the license agreement. For details see 6 | * accompanying license terms. 7 | */ 8 | 9 | package org.violetlib.aqua; 10 | 11 | import java.awt.*; 12 | import javax.swing.*; 13 | import javax.swing.plaf.UIResource; 14 | import javax.swing.table.JTableHeader; 15 | 16 | import org.jetbrains.annotations.NotNull; 17 | import org.jetbrains.annotations.Nullable; 18 | 19 | /** 20 | * Fills out the table header when a legacy vertical scroll bar is used. 21 | */ 22 | public class AquaTableScrollPaneCorner extends JComponent implements UIResource { 23 | 24 | @Override 25 | protected void paintComponent(@NotNull Graphics g) { 26 | int width = getWidth(); 27 | int height = getHeight(); 28 | 29 | JTableHeader header = getHeader(); 30 | if (header != null) { 31 | Color bc = header.getBackground(); 32 | if (bc != null) { 33 | g.setColor(bc); 34 | g.fillRect(0, 0, width, height); 35 | } 36 | AquaTableHeaderUI ui = AquaUtils.getUI(header, AquaTableHeaderUI.class); 37 | if (ui != null) { 38 | Color borderColor = ui.getSeparatorColor(); 39 | if (borderColor != null) { 40 | int borderHeight = ui.getBorderHeight(); 41 | if (borderHeight > 0) { 42 | g.setColor(borderColor); 43 | g.fillRect(0, height - borderHeight, width, borderHeight); 44 | } 45 | } 46 | } 47 | } 48 | } 49 | 50 | protected @Nullable JTableHeader getHeader() { 51 | Object parent = getParent(); 52 | if (parent instanceof JScrollPane) { 53 | JScrollPane sp = (JScrollPane) parent; 54 | JViewport vp = sp.getColumnHeader(); 55 | if (vp != null) { 56 | Component c = vp.getView(); 57 | if (c instanceof JTableHeader) { 58 | return (JTableHeader) c; 59 | } 60 | } 61 | } 62 | return null; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/org/violetlib/aqua/AquaTextAreaUI.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Alan Snyder. 3 | * All rights reserved. 4 | * 5 | * You may not use, copy or modify this file, except in compliance with the license agreement. For details see 6 | * accompanying license terms. 7 | */ 8 | 9 | package org.violetlib.aqua; 10 | 11 | import javax.swing.*; 12 | import javax.swing.plaf.ComponentUI; 13 | 14 | import org.jetbrains.annotations.NotNull; 15 | 16 | /** 17 | * The UI for JTextArea. 18 | */ 19 | public class AquaTextAreaUI extends AquaTextPaneUIBase { 20 | 21 | public static @NotNull ComponentUI createUI(@NotNull JComponent c) { 22 | return new AquaTextAreaUI(); 23 | } 24 | 25 | public AquaTextAreaUI() { 26 | super(new AquaTextAreaUIDelegate()); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/org/violetlib/aqua/AquaTextComponentUIDelegate.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Alan Snyder. 3 | * All rights reserved. 4 | * 5 | * You may not use, copy or modify this file, except in compliance with the license agreement. For details see 6 | * accompanying license terms. 7 | */ 8 | 9 | package org.violetlib.aqua; 10 | 11 | import java.awt.*; 12 | import java.beans.PropertyChangeEvent; 13 | import javax.swing.*; 14 | import javax.swing.text.EditorKit; 15 | import javax.swing.text.Element; 16 | import javax.swing.text.JTextComponent; 17 | import javax.swing.text.View; 18 | 19 | import org.jetbrains.annotations.NotNull; 20 | import org.jetbrains.annotations.Nullable; 21 | 22 | /** 23 | * The interface supported by a text component UI delegate. The UI delegate supports the custom behaviors for a 24 | * specific type of text component. 25 | */ 26 | public interface AquaTextComponentUIDelegate { 27 | 28 | @NotNull String getPropertyPrefix(); 29 | 30 | void install(@NotNull JTextComponent c); 31 | 32 | void uninstall(@NotNull JTextComponent c); 33 | 34 | /** 35 | * Respond to a property change on the text component. 36 | * @return true if the model should be updated. 37 | */ 38 | boolean propertyChange(@NotNull PropertyChangeEvent ev); 39 | 40 | @Nullable EditorKit getEditorKit(@NotNull JTextComponent c); 41 | 42 | @Nullable View create(@NotNull JTextComponent c, Element elem); 43 | 44 | int getBaseline(@NotNull JTextComponent c, int width, int height); 45 | 46 | @NotNull Component.BaselineResizeBehavior getBaselineResizeBehavior(JTextComponent c); 47 | 48 | @Nullable ActionMap getActionMap(@NotNull JTextComponent c); 49 | } 50 | -------------------------------------------------------------------------------- /src/org/violetlib/aqua/AquaTextFieldFormattedUI.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Changes copyright (c) 2018 Alan Snyder. 3 | * All rights reserved. 4 | * 5 | * You may not use, copy or modify this file, except in compliance with the license agreement. For details see 6 | * accompanying license terms. 7 | */ 8 | 9 | /* 10 | * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. 11 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 12 | * 13 | * This code is free software; you can redistribute it and/or modify it 14 | * under the terms of the GNU General Public License version 2 only, as 15 | * published by the Free Software Foundation. Oracle designates this 16 | * particular file as subject to the "Classpath" exception as provided 17 | * by Oracle in the LICENSE file that accompanied this code. 18 | * 19 | * This code is distributed in the hope that it will be useful, but WITHOUT 20 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 21 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 22 | * version 2 for more details (a copy is included in the LICENSE file that 23 | * accompanied this code). 24 | * 25 | * You should have received a copy of the GNU General Public License version 26 | * 2 along with this work; if not, write to the Free Software Foundation, 27 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 28 | * 29 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 30 | * or visit www.oracle.com if you need additional information or have any 31 | * questions. 32 | */ 33 | 34 | package org.violetlib.aqua; 35 | 36 | import java.awt.event.*; 37 | 38 | import javax.swing.JComponent; 39 | import javax.swing.plaf.ComponentUI; 40 | import javax.swing.text.JTextComponent; 41 | 42 | /** 43 | * This class exists only as a hack to work around a Sun bug which parks the 44 | * insertion caret at the beginning of a text field when it gets clicked on. 45 | */ 46 | public class AquaTextFieldFormattedUI extends AquaTextFieldUI implements MouseListener { 47 | 48 | public static ComponentUI createUI(JComponent c) { 49 | return new AquaTextFieldFormattedUI(); 50 | } 51 | 52 | @Override 53 | protected String getPropertyPrefix() { 54 | return "FormattedTextField"; 55 | } 56 | 57 | protected void installListeners() { 58 | super.installListeners(); 59 | getComponent().addMouseListener(this); 60 | } 61 | 62 | protected void uninstallListeners() { 63 | getComponent().removeMouseListener(this); 64 | super.uninstallListeners(); 65 | } 66 | 67 | public void mouseClicked(MouseEvent e) { 68 | if (e.getClickCount() != 1) return; 69 | 70 | JTextComponent c = getComponent(); 71 | // apparently, focus has already been granted by the time this mouse listener fires 72 | // if (c.hasFocus()) return; 73 | 74 | c.setCaretPosition(viewToModel(c, e.getPoint())); 75 | } 76 | 77 | public void mouseEntered(MouseEvent e) { } 78 | public void mouseExited(MouseEvent e) { } 79 | public void mousePressed(MouseEvent e) { } 80 | public void mouseReleased(MouseEvent e) { } 81 | } 82 | -------------------------------------------------------------------------------- /src/org/violetlib/aqua/AquaTextPaneUI.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Alan Snyder. 3 | * All rights reserved. 4 | * 5 | * You may not use, copy or modify this file, except in compliance with the license agreement. For details see 6 | * accompanying license terms. 7 | */ 8 | 9 | package org.violetlib.aqua; 10 | 11 | import javax.swing.*; 12 | import javax.swing.plaf.ComponentUI; 13 | 14 | import org.jetbrains.annotations.NotNull; 15 | 16 | /** 17 | * The UI for JTextPane. 18 | */ 19 | public class AquaTextPaneUI extends AquaTextPaneUIBase { 20 | 21 | public static @NotNull ComponentUI createUI(@NotNull JComponent c) { 22 | return new AquaTextPaneUI(); 23 | } 24 | 25 | public AquaTextPaneUI() { 26 | super(new AquaTextPaneUIDelegate()); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/org/violetlib/aqua/AquaTextPaneUIDelegate.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Alan Snyder. 3 | * All rights reserved. 4 | * 5 | * You may not use, copy or modify this file, except in compliance with the license agreement. For details see 6 | * accompanying license terms. 7 | */ 8 | 9 | package org.violetlib.aqua; 10 | 11 | import org.jetbrains.annotations.NotNull; 12 | 13 | /** 14 | * Supports UI behavior specific to JTextPane. 15 | */ 16 | 17 | public class AquaTextPaneUIDelegate extends AquaEditorPaneUIDelegate { 18 | 19 | @Override 20 | public @NotNull String getPropertyPrefix() { 21 | return "TextPane"; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/org/violetlib/aqua/AquaToggleButtonBorder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2020 Alan Snyder. 3 | * All rights reserved. 4 | * 5 | * You may not use, copy or modify this file, except in compliance with the license agreement. For details see 6 | * accompanying license terms. 7 | */ 8 | 9 | package org.violetlib.aqua; 10 | 11 | import javax.swing.*; 12 | 13 | import org.jetbrains.annotations.NotNull; 14 | import org.jetbrains.annotations.Nullable; 15 | import org.violetlib.jnr.aqua.*; 16 | import org.violetlib.jnr.aqua.AquaUIPainter.ButtonWidget; 17 | import org.violetlib.jnr.aqua.AquaUIPainter.GenericButtonWidget; 18 | import org.violetlib.jnr.aqua.AquaUIPainter.SegmentedButtonWidget; 19 | 20 | /** 21 | * A border for a toggle button with no client specified button style. A generic button border must adapt to any size 22 | * text. It can use a fixed height style only if the text fits using that height. Otherwise, an alternate style must be 23 | * used. 24 | * 25 | * @see AquaPushButtonBorder 26 | */ 27 | public class AquaToggleButtonBorder extends AquaButtonBorder implements FocusRingOutlineProvider { 28 | 29 | @Override 30 | public final @NotNull GenericButtonWidget getButtonWidget(@NotNull AbstractButton b) { 31 | boolean isOnToolbar = AquaUtils.isOnToolbar(b); 32 | 33 | GenericButtonWidget preferredWidget = isOnToolbar 34 | ? ButtonWidget.BUTTON_TEXTURED_TOOLBAR 35 | : SegmentedButtonWidget.BUTTON_SEGMENTED; 36 | if (isProposedButtonWidgetUsable(b, preferredWidget)) { 37 | return preferredWidget; 38 | } 39 | 40 | if (b.getIcon() != null) { 41 | return isOnToolbar ? ButtonWidget.BUTTON_TOOLBAR_ITEM : ButtonWidget.BUTTON_GRADIENT; 42 | } 43 | 44 | return ButtonWidget.BUTTON_BEVEL_ROUND; 45 | } 46 | 47 | @Override 48 | public @Nullable GenericButtonConfiguration getConfiguration(@NotNull AbstractButton b, int width, int height) { 49 | 50 | LayoutConfiguration g = getLayoutConfiguration(b); 51 | 52 | if (g instanceof SegmentedButtonLayoutConfiguration) { 53 | AquaUIPainter.State state = getState(b); 54 | boolean isFocused = computeIsFocused(state, b); 55 | boolean isSelected = b.getModel().isSelected(); 56 | AquaUIPainter.Direction d = AquaUIPainter.Direction.NONE; 57 | return new SegmentedButtonConfiguration((SegmentedButtonLayoutConfiguration) g, state, isSelected, 58 | isFocused, d, SegmentedButtonConfiguration.DividerState.NONE, SegmentedButtonConfiguration.DividerState.NONE); 59 | } 60 | 61 | return super.getConfiguration(b, width, height); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/org/violetlib/aqua/AquaToolTipUI.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018-2021 Alan Snyder. 3 | * All rights reserved. 4 | * 5 | * You may not use, copy or modify this file, except in compliance with the license agreement. For details see 6 | * accompanying license terms. 7 | */ 8 | 9 | /* 10 | * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. 11 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 12 | * 13 | * This code is free software; you can redistribute it and/or modify it 14 | * under the terms of the GNU General Public License version 2 only, as 15 | * published by the Free Software Foundation. Oracle designates this 16 | * particular file as subject to the "Classpath" exception as provided 17 | * by Oracle in the LICENSE file that accompanied this code. 18 | * 19 | * This code is distributed in the hope that it will be useful, but WITHOUT 20 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 21 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 22 | * version 2 for more details (a copy is included in the LICENSE file that 23 | * accompanied this code). 24 | * 25 | * You should have received a copy of the GNU General Public License version 26 | * 2 along with this work; if not, write to the Free Software Foundation, 27 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 28 | * 29 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 30 | * or visit www.oracle.com if you need additional information or have any 31 | * questions. 32 | */ 33 | 34 | package org.violetlib.aqua; 35 | 36 | import java.awt.*; 37 | import javax.swing.*; 38 | import javax.swing.plaf.ComponentUI; 39 | import javax.swing.plaf.basic.BasicToolTipUI; 40 | 41 | import org.jetbrains.annotations.NotNull; 42 | import org.violetlib.aqua.AquaUtils.RecyclableSingletonFromDefaultConstructor; 43 | import org.violetlib.jnr.aqua.AquaUIPainter; 44 | 45 | public class AquaToolTipUI extends BasicToolTipUI implements AquaComponentUI { 46 | 47 | static final RecyclableSingletonFromDefaultConstructor sharedAquaInstance = new RecyclableSingletonFromDefaultConstructor(AquaToolTipUI.class); 48 | 49 | public static ComponentUI createUI(JComponent c) { 50 | return sharedAquaInstance.get(); 51 | } 52 | 53 | protected @NotNull BasicContextualColors colors; 54 | 55 | public AquaToolTipUI() { 56 | colors = AquaColors.TOOL_TIP_COLORS; 57 | } 58 | 59 | @Override 60 | public void appearanceChanged(@NotNull JComponent c, @NotNull AquaAppearance appearance) { 61 | } 62 | 63 | @Override 64 | public void activeStateChanged(@NotNull JComponent c, boolean isActive) { 65 | } 66 | 67 | @Override 68 | public void update(Graphics g, JComponent c) { 69 | AquaAppearance appearance = AppearanceManager.registerCurrentAppearance(c); 70 | AquaUIPainter.State state = AquaUIPainter.State.ACTIVE; 71 | AppearanceContext context = new AppearanceContext(appearance, state, false, false); 72 | AquaColors.installColors(c, context, colors); 73 | super.update(g, c); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/org/violetlib/aqua/AquaTreeBorder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020-2021 Alan Snyder. 3 | * All rights reserved. 4 | * 5 | * You may not use, copy or modify this file, except in compliance with the license agreement. For details see 6 | * accompanying license terms. 7 | */ 8 | 9 | package org.violetlib.aqua; 10 | 11 | import java.awt.*; 12 | import javax.swing.*; 13 | import javax.swing.border.AbstractBorder; 14 | import javax.swing.plaf.UIResource; 15 | 16 | import org.jetbrains.annotations.NotNull; 17 | 18 | /** 19 | * A context dependent border for trees that supports side margins when the inset view style is in use. 20 | */ 21 | @SuppressWarnings("serial") 22 | public class AquaTreeBorder extends AbstractBorder implements UIResource { 23 | 24 | public Insets getBorderInsets(@NotNull Component c, @NotNull Insets insets) { 25 | AquaTreeUI ui = AquaUtils.getUI((JComponent) c, AquaTreeUI.class); 26 | if (ui != null) { 27 | return ui.getInsets(); 28 | } 29 | insets.top = 0; 30 | insets.bottom = 0; 31 | insets.left = 1; 32 | insets.right = 1; 33 | return insets; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/org/violetlib/aqua/AquaTreeEditorBorder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 Alan Snyder. 3 | * All rights reserved. 4 | * 5 | * You may not use, copy or modify this file, except in compliance with the license agreement. For details see 6 | * accompanying license terms. 7 | */ 8 | 9 | package org.violetlib.aqua; 10 | 11 | import java.awt.*; 12 | import javax.swing.*; 13 | import javax.swing.plaf.UIResource; 14 | 15 | import org.jetbrains.annotations.NotNull; 16 | import org.jetbrains.annotations.Nullable; 17 | 18 | /** 19 | * The default border for a tree cell editor. 20 | */ 21 | public class AquaTreeEditorBorder implements AquaBackgroundBorder, UIResource { 22 | 23 | public AquaTreeEditorBorder() { 24 | } 25 | 26 | @Override 27 | public void paintBackground(@NotNull Component c, Graphics g, @Nullable Color background) { 28 | Color bc = getBackground(c); 29 | if (bc != null) { 30 | int width = c.getWidth(); 31 | int height = c.getHeight(); 32 | g.setColor(bc); 33 | g.fillRect(0, 0, width, height); 34 | } 35 | } 36 | 37 | private @Nullable Color getBackground(@NotNull Component c) { 38 | JTree tree = getTree(c); 39 | if (tree != null) { 40 | AquaTreeUI ui = AquaUtils.getUI(tree, AquaTreeUI.class); 41 | if (ui != null) { 42 | AquaAppearance a = AppearanceManager.getAppearance(tree); 43 | if (a.isDark()) { 44 | Color b = AquaColors.getCellEditorBackground(tree); 45 | if (b != null) { 46 | return b; 47 | } 48 | } 49 | } 50 | } 51 | return c.getBackground(); 52 | } 53 | 54 | private @Nullable JTree getTree(@NotNull Component c) { 55 | Container parent = c.getParent(); 56 | if (parent instanceof JTree) { 57 | return (JTree) parent; 58 | } 59 | if (parent == null) { 60 | return null; 61 | } 62 | parent = parent.getParent(); 63 | return parent instanceof JTree ? (JTree) parent : null; 64 | } 65 | 66 | @Override 67 | public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) { 68 | // Not used 69 | } 70 | 71 | @Override 72 | public Insets getBorderInsets(Component c) { 73 | return new Insets(0, 0, 0, 0); 74 | } 75 | 76 | @Override 77 | public boolean isBorderOpaque() { 78 | return true; 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/org/violetlib/aqua/AquaViewStyleContainerUI.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 Alan Snyder. 3 | * All rights reserved. 4 | * 5 | * You may not use, copy or modify this file, except in compliance with the license agreement. For details see 6 | * accompanying license terms. 7 | */ 8 | 9 | package org.violetlib.aqua; 10 | 11 | import javax.swing.*; 12 | 13 | import org.jetbrains.annotations.Nullable; 14 | 15 | /** 16 | * Methods supported by containers that support the inset view style (lists and tables). 17 | */ 18 | public interface AquaViewStyleContainerUI { 19 | 20 | boolean isInset(); 21 | 22 | void scrollPaneAncestorChanged(@Nullable JScrollPane sp); 23 | } 24 | -------------------------------------------------------------------------------- /src/org/violetlib/aqua/AquaViewportUI.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015-2021 Alan Snyder. 3 | * All rights reserved. 4 | * 5 | * You may not use, copy or modify this file, except in compliance with the license agreement. For details see 6 | * accompanying license terms. 7 | */ 8 | 9 | package org.violetlib.aqua; 10 | 11 | import java.awt.*; 12 | import javax.swing.*; 13 | import javax.swing.plaf.ComponentUI; 14 | import javax.swing.plaf.ViewportUI; 15 | 16 | import org.jetbrains.annotations.NotNull; 17 | import org.jetbrains.annotations.Nullable; 18 | import org.violetlib.jnr.aqua.AquaUIPainter; 19 | 20 | /** 21 | * The viewport UI supports vibrant backgrounds and appearances. 22 | */ 23 | public class AquaViewportUI extends ViewportUI implements AquaComponentUI { 24 | 25 | public static ComponentUI createUI(JComponent c) { 26 | return new AquaViewportUI(); 27 | } 28 | 29 | protected @Nullable JViewport viewport; 30 | protected final @NotNull BasicContextualColors colors; 31 | protected @Nullable AppearanceContext appearanceContext; 32 | 33 | public AquaViewportUI() { 34 | colors = AquaColors.CONTROL_COLORS; 35 | } 36 | 37 | @Override 38 | public void installUI(JComponent c) { 39 | super.installUI(c); 40 | viewport = (JViewport) c; 41 | AquaVibrantSupport.installVibrantStyle(c); 42 | AppearanceManager.installListeners(c); 43 | configureAppearanceContext(null); 44 | } 45 | 46 | @Override 47 | public void uninstallUI(JComponent c) { 48 | AppearanceManager.uninstallListeners(c); 49 | AquaVibrantSupport.uninstallVibrantStyle(c); 50 | viewport = null; 51 | super.uninstallUI(c); 52 | } 53 | 54 | @Override 55 | public void appearanceChanged(@NotNull JComponent c, @NotNull AquaAppearance appearance) { 56 | configureAppearanceContext(appearance); 57 | } 58 | 59 | @Override 60 | public void activeStateChanged(@NotNull JComponent c, boolean isActive) { 61 | configureAppearanceContext(null); 62 | } 63 | 64 | protected void configureAppearanceContext(@Nullable AquaAppearance appearance) { 65 | assert viewport != null; 66 | if (appearance == null) { 67 | appearance = AppearanceManager.ensureAppearance(viewport); 68 | } 69 | AquaUIPainter.State state = getState(); 70 | appearanceContext = new AppearanceContext(appearance, state, false, false); 71 | AquaColors.installColors(viewport, appearanceContext, colors); 72 | viewport.repaint(); 73 | } 74 | 75 | protected AquaUIPainter.State getState() { 76 | return AquaFocusHandler.isActive(viewport) ? AquaUIPainter.State.ACTIVE : AquaUIPainter.State.INACTIVE; 77 | } 78 | 79 | @Override 80 | public final void update(@NotNull Graphics g, @NotNull JComponent c) { 81 | AppearanceManager.registerCurrentAppearance(c); 82 | if (c.isOpaque() || AquaVibrantSupport.isVibrant(c)) { 83 | AquaUtils.fillRect(g, c, AquaUtils.ERASE_IF_VIBRANT); 84 | } 85 | paint(g, c); 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /src/org/violetlib/aqua/BackgroundPainter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2015 Alan Snyder. 3 | * All rights reserved. 4 | * 5 | * You may not use, copy or modify this file, except in compliance with the license agreement. For details see 6 | * accompanying license terms. 7 | */ 8 | 9 | package org.violetlib.aqua; 10 | 11 | import java.awt.*; 12 | import javax.swing.*; 13 | 14 | /** 15 | * The interface for an object that paints the background of a component. 16 | */ 17 | public interface BackgroundPainter { 18 | void paintBackground(JComponent c, Graphics g, int x, int y, int width, int height); 19 | } 20 | -------------------------------------------------------------------------------- /src/org/violetlib/aqua/BasicAquaAppearance.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018-2020 Alan Snyder. 3 | * All rights reserved. 4 | * 5 | * You may not use, copy or modify this file, except in compliance with the license agreement. For details see 6 | * accompanying license terms. 7 | */ 8 | 9 | package org.violetlib.aqua; 10 | 11 | import java.awt.*; 12 | import java.util.Map; 13 | 14 | import org.jetbrains.annotations.NotNull; 15 | import org.jetbrains.annotations.Nullable; 16 | import org.violetlib.vappearances.VAppearance; 17 | 18 | /** 19 | * An object representing a specific appearance, including the current accent and highlight colors. 20 | */ 21 | 22 | public class BasicAquaAppearance implements VAppearance { 23 | 24 | private final @NotNull VAppearance appearance; 25 | private final @NotNull Colors colors; 26 | private final @NotNull Logger log; 27 | 28 | public BasicAquaAppearance(@NotNull VAppearance appearance, 29 | @NotNull Colors colors, 30 | @NotNull Logger log) { 31 | this.appearance = appearance; 32 | this.colors = colors; 33 | this.log = log; 34 | } 35 | 36 | @Override 37 | public @NotNull String getName() { 38 | return appearance.getName(); 39 | } 40 | 41 | @Override 42 | public boolean isDark() { 43 | return appearance.isDark(); 44 | } 45 | 46 | @Override 47 | public boolean isHighContrast() { 48 | return appearance.isHighContrast(); 49 | } 50 | 51 | @Override 52 | public @NotNull Map getColors() { 53 | return appearance.getColors(); 54 | } 55 | 56 | /** 57 | * Return the color with the specified name. 58 | * @param colorName The color name. 59 | * @return the color, as a ColorUIResource, or null if the color name not defined in this appearance. 60 | */ 61 | 62 | public @Nullable Color getColor(@NotNull String colorName) { 63 | return colors.get(colorName); 64 | } 65 | 66 | public boolean isBasedOn(@NotNull VAppearance va) { 67 | return va == appearance; 68 | } 69 | 70 | @Override 71 | public @NotNull String toString() { 72 | return super.toString() + "[" + appearance.getName() + "]"; 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/org/violetlib/aqua/BasicColors.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 Alan Snyder. 3 | * All rights reserved. 4 | * 5 | * You may not use, copy or modify this file, except in compliance with the license agreement. For details see 6 | * accompanying license terms. 7 | */ 8 | 9 | package org.violetlib.aqua; 10 | 11 | import java.awt.*; 12 | import java.util.Map; 13 | 14 | import org.jetbrains.annotations.NotNull; 15 | 16 | /** 17 | * A collection of color definitions. Color names are defined in terms of specific colors or as synonyms. 18 | */ 19 | 20 | public class BasicColors { 21 | public final @NotNull Map colors; 22 | public final @NotNull Map synonyms; 23 | 24 | public BasicColors(@NotNull Map colors, @NotNull Map synonyms) { 25 | this.colors = colors; 26 | this.synonyms = synonyms; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/org/violetlib/aqua/BasicContextualColors.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Alan Snyder. 3 | * All rights reserved. 4 | * 5 | * You may not use, copy or modify this file, except in compliance with the license agreement. For details see 6 | * accompanying license terms. 7 | */ 8 | 9 | package org.violetlib.aqua; 10 | 11 | import java.awt.*; 12 | 13 | import org.jetbrains.annotations.NotNull; 14 | 15 | /** 16 | * Identify contextually determined foreground and background colors. 17 | */ 18 | 19 | public interface BasicContextualColors { 20 | 21 | @NotNull Color getBackground(@NotNull AppearanceContext context); 22 | 23 | @NotNull Color getForeground(@NotNull AppearanceContext context); 24 | } 25 | -------------------------------------------------------------------------------- /src/org/violetlib/aqua/BasicContextualColorsImpl.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Alan Snyder. 3 | * All rights reserved. 4 | * 5 | * You may not use, copy or modify this file, except in compliance with the license agreement. For details see 6 | * accompanying license terms. 7 | */ 8 | 9 | package org.violetlib.aqua; 10 | 11 | import java.awt.*; 12 | 13 | import org.jetbrains.annotations.NotNull; 14 | 15 | /** 16 | * Identify contextually determined foreground and background colors. 17 | */ 18 | 19 | public class BasicContextualColorsImpl implements BasicContextualColors { 20 | 21 | protected @NotNull ContextualColor background; 22 | protected @NotNull ContextualColor foreground; 23 | 24 | public BasicContextualColorsImpl(@NotNull ContextualColor background, 25 | @NotNull ContextualColor foreground) { 26 | this.background = background; 27 | this.foreground = foreground; 28 | } 29 | 30 | @Override 31 | public @NotNull Color getBackground(@NotNull AppearanceContext context) { 32 | AquaColors.setupDebugging(this); 33 | Color color = background.get(context); 34 | AquaColors.clearDebugging(); 35 | return color; 36 | } 37 | 38 | @Override 39 | public @NotNull Color getForeground(@NotNull AppearanceContext context) { 40 | AquaColors.setupDebugging(this); 41 | Color color = foreground.get(context); 42 | AquaColors.clearDebugging(); 43 | return color; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/org/violetlib/aqua/Border2D.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2018 Alan Snyder. 3 | * All rights reserved. 4 | * 5 | * You may not use, copy or modify this file, except in compliance with the license agreement. For details see 6 | * accompanying license terms. 7 | */ 8 | 9 | package org.violetlib.aqua; 10 | 11 | import java.awt.*; 12 | 13 | import org.jetbrains.annotations.NotNull; 14 | import org.violetlib.jnr.Insets2D; 15 | 16 | /** 17 | * Interface for a border that has floating point insets. 18 | */ 19 | public interface Border2D { 20 | @NotNull Insets2D getBorderInsets2D(@NotNull Component c); 21 | } 22 | -------------------------------------------------------------------------------- /src/org/violetlib/aqua/Colors.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 Alan Snyder. 3 | * All rights reserved. 4 | * 5 | * You may not use, copy or modify this file, except in compliance with the license agreement. For details see 6 | * accompanying license terms. 7 | */ 8 | 9 | package org.violetlib.aqua; 10 | 11 | import java.awt.*; 12 | import java.util.Map; 13 | import java.util.Set; 14 | 15 | import org.jetbrains.annotations.NotNull; 16 | import org.jetbrains.annotations.Nullable; 17 | 18 | /** 19 | * A collection of color definitions. 20 | */ 21 | 22 | public class Colors { 23 | private final @NotNull Map colors; 24 | 25 | public Colors(@NotNull Map colors) { 26 | this.colors = colors; 27 | } 28 | 29 | public @Nullable Color get(@NotNull String name) { 30 | return colors.get(name); 31 | } 32 | 33 | public @NotNull Set getColorNames() { 34 | return colors.keySet(); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/org/violetlib/aqua/ColorsInstrumentation.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 Alan Snyder. 3 | * All rights reserved. 4 | * 5 | * You may not use, copy or modify this file, except in compliance with the license agreement. For details see 6 | * accompanying license terms. 7 | */ 8 | 9 | package org.violetlib.aqua; 10 | 11 | import java.awt.*; 12 | 13 | import org.jetbrains.annotations.NotNull; 14 | import org.jetbrains.annotations.Nullable; 15 | 16 | /** 17 | * 18 | */ 19 | 20 | public interface ColorsInstrumentation { 21 | 22 | interface Access { 23 | @NotNull String[] getColorNames(); 24 | @Nullable Color getColor(@NotNull String name); 25 | @Nullable String getSynonym(@NotNull String name); 26 | } 27 | 28 | void addingColor(@NotNull String context, @NotNull String name, @NotNull Color color, @NotNull Access access); 29 | 30 | void addingSynonym(@NotNull String context, @NotNull String name, @NotNull String synonym, @NotNull Access access); 31 | 32 | void removingColor(@NotNull String context, @NotNull String name, @NotNull Access access); 33 | 34 | void applyingSynonym(@NotNull String context, @NotNull String name, @Nullable Color color, @NotNull Access access); 35 | 36 | void colorsReady(@NotNull Access access); 37 | } 38 | -------------------------------------------------------------------------------- /src/org/violetlib/aqua/ComponentVibrantEffects.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 Alan Snyder. 3 | * All rights reserved. 4 | * 5 | * You may not use, copy or modify this file, except in compliance with the license agreement. For details see 6 | * accompanying license terms. 7 | */ 8 | 9 | package org.violetlib.aqua; 10 | 11 | import java.awt.*; 12 | import javax.swing.*; 13 | 14 | /** 15 | * A generic component for supporting vibrant backgrounds on a component. 16 | */ 17 | public class ComponentVibrantEffects extends VisualEffectView { 18 | 19 | protected SelectionBoundsTracker boundsTracker; 20 | 21 | /** 22 | * Create an object to support vibrant backgrounds on a component. 23 | * @param c The component. 24 | * @param style The vibrant background style. See constants in {@link AquaVibrantSupport}. 25 | * @param bt An optional selection bounds tracker, if the component has selected item regions that should display 26 | * using a vibrant style. A consumer will be installed in the tracker. 27 | */ 28 | public ComponentVibrantEffects(JComponent c, int style, SelectionBoundsTracker bt) { 29 | super(c, style, bt != null); 30 | this.boundsTracker = bt; 31 | 32 | if (bt != null) { 33 | bt.setConsumer(sd -> ComponentVibrantEffects.this.updateSelectionBackgrounds(sd)); 34 | } 35 | } 36 | 37 | /** 38 | * Recompute the selection bounds (if a selection bounds tracker was provided). 39 | */ 40 | public void update() { 41 | if (boundsTracker != null) { 42 | boundsTracker.update(); 43 | } 44 | } 45 | 46 | @Override 47 | public void dispose() { 48 | super.dispose(); 49 | if (boundsTracker != null) { 50 | boundsTracker.dispose(); 51 | boundsTracker = null; 52 | } 53 | } 54 | 55 | @Override 56 | protected void windowChanged(Window newWindow) { 57 | super.windowChanged(newWindow); 58 | if (boundsTracker != null) { 59 | boundsTracker.reset(); 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/org/violetlib/aqua/ContainerContextualColors.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Alan Snyder. 3 | * All rights reserved. 4 | * 5 | * You may not use, copy or modify this file, except in compliance with the license agreement. For details see 6 | * accompanying license terms. 7 | */ 8 | 9 | package org.violetlib.aqua; 10 | 11 | import java.awt.*; 12 | 13 | import org.jetbrains.annotations.NotNull; 14 | 15 | /** 16 | * Container contextual colors support row specific values. These objects are stateful. They must be configured before 17 | * use. 18 | */ 19 | 20 | public interface ContainerContextualColors extends BasicContextualColors { 21 | 22 | void configureForContainer(); 23 | 24 | void configureForRow(int rowIndex, boolean isRowSelected); 25 | 26 | void configureForRow(boolean isRowSelected); 27 | 28 | boolean isStriped(); 29 | 30 | @NotNull Color getBackground(@NotNull AppearanceContext context); 31 | 32 | @NotNull Color getForeground(@NotNull AppearanceContext context); 33 | 34 | @NotNull Color getGrid(@NotNull AppearanceContext context); 35 | } 36 | -------------------------------------------------------------------------------- /src/org/violetlib/aqua/ContextualColor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Alan Snyder. 3 | * All rights reserved. 4 | * 5 | * You may not use, copy or modify this file, except in compliance with the license agreement. For details see 6 | * accompanying license terms. 7 | */ 8 | 9 | package org.violetlib.aqua; 10 | 11 | import java.awt.*; 12 | 13 | import org.jetbrains.annotations.NotNull; 14 | 15 | /** 16 | * A contextual color is a source of colors based on context. 17 | */ 18 | 19 | public interface ContextualColor { 20 | 21 | /** 22 | * Return the name of this contextual color (for debugging). 23 | */ 24 | 25 | @NotNull String getColorName(); 26 | 27 | /** 28 | * Return the color to use in a specified context. 29 | * @param context The context. 30 | * @return the color. 31 | * @throws UnsupportedOperationException if no color is defined. 32 | */ 33 | 34 | @NotNull Color get(@NotNull AppearanceContext context); 35 | } 36 | -------------------------------------------------------------------------------- /src/org/violetlib/aqua/DelegatedContainerContextualColors.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Alan Snyder. 3 | * All rights reserved. 4 | * 5 | * You may not use, copy or modify this file, except in compliance with the license agreement. For details see 6 | * accompanying license terms. 7 | */ 8 | 9 | package org.violetlib.aqua; 10 | 11 | import java.awt.*; 12 | 13 | import javax.swing.plaf.ColorUIResource; 14 | 15 | import org.jetbrains.annotations.NotNull; 16 | import org.jetbrains.annotations.Nullable; 17 | 18 | /** 19 | 20 | */ 21 | 22 | public class DelegatedContainerContextualColors implements ContainerContextualColors { 23 | 24 | protected @NotNull BasicContextualColors source; 25 | protected @Nullable ContextualColor grid; 26 | protected boolean isRowSelected; 27 | 28 | /** 29 | * Create colors for a uniform (not striped) container. 30 | */ 31 | 32 | public DelegatedContainerContextualColors(@NotNull BasicContextualColors source) { 33 | this.source = source; 34 | this.grid = null; 35 | } 36 | 37 | /** 38 | * Create colors for a uniform (not striped) container. 39 | */ 40 | 41 | public DelegatedContainerContextualColors(@NotNull BasicContextualColors source, 42 | @NotNull ContextualColor grid) { 43 | this.source = source; 44 | this.grid = grid; 45 | } 46 | 47 | public void configureForContainer() { 48 | isRowSelected = false; 49 | } 50 | 51 | public void configureForRow(int rowIndex, boolean isRowSelected) { 52 | this.isRowSelected = isRowSelected; 53 | } 54 | 55 | public void configureForRow(boolean isRowSelected) { 56 | this.isRowSelected = isRowSelected; 57 | } 58 | 59 | public boolean isStriped() { 60 | return false; 61 | } 62 | 63 | @Override 64 | public @NotNull Color getBackground(@NotNull AppearanceContext context) { 65 | context = context.withSelected(isRowSelected || context.isSelected()); 66 | return source.getBackground(context); 67 | } 68 | 69 | @Override 70 | public @NotNull Color getForeground(@NotNull AppearanceContext context) { 71 | context = context.withSelected(isRowSelected || context.isSelected()); 72 | return source.getForeground(context); 73 | } 74 | 75 | public @NotNull Color getGrid(@NotNull AppearanceContext context) { 76 | if (grid != null) { 77 | context = context.withSelected(isRowSelected || context.isSelected()); 78 | return grid.get(context); 79 | } else { 80 | throw new UnsupportedOperationException("No grid color has been defined"); 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/org/violetlib/aqua/EffectName.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Alan Snyder. 3 | * All rights reserved. 4 | * 5 | * You may not use, copy or modify this file, except in compliance with the license agreement. For details see 6 | * accompanying license terms. 7 | */ 8 | 9 | package org.violetlib.aqua; 10 | 11 | import org.jetbrains.annotations.NotNull; 12 | 13 | /** 14 | 15 | */ 16 | 17 | public class EffectName { 18 | private final @NotNull String name; 19 | 20 | public static final @NotNull EffectName EFFECT_NONE = new EffectName("none"); 21 | public static final @NotNull EffectName EFFECT_PRESSED = new EffectName("pressed"); 22 | public static final @NotNull EffectName EFFECT_DEEP_PRESSED = new EffectName("deepPressed"); 23 | public static final @NotNull EffectName EFFECT_DISABLED = new EffectName("disabled"); 24 | public static final @NotNull EffectName EFFECT_ROLLOVER = new EffectName("rollover"); 25 | 26 | private EffectName(@NotNull String name) { 27 | this.name = name; 28 | } 29 | 30 | public @NotNull String getName() { 31 | return name; 32 | } 33 | 34 | @Override 35 | public @NotNull String toString() { 36 | return name; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/org/violetlib/aqua/EmptyIcon.java: -------------------------------------------------------------------------------- 1 | /* 2 | * @(#)EmptyIcon.java 3 | * 4 | * Copyright 2010 Werner Randelshofer, Switzerland. 5 | * All rights reserved. 6 | * 7 | * You may not use, copy or modify this file, except in compliance with the 8 | * license agreement you entered into with Werner Randelshofer. 9 | * For details see accompanying license terms. 10 | */ 11 | 12 | package org.violetlib.aqua; 13 | 14 | import java.awt.*; 15 | import java.io.Serializable; 16 | import javax.swing.*; 17 | 18 | /** 19 | * {@code EmptyIcon}. 20 | * 21 | * @author Werner Randelshofer 22 | * @version $Id$ 23 | */ 24 | public class EmptyIcon implements Icon, Serializable { 25 | private int width; 26 | private int height; 27 | 28 | public EmptyIcon(int width, int height) { 29 | this.width = width; 30 | this.height = height; 31 | } 32 | 33 | public void paintIcon(Component c, Graphics g, int x, int y) { 34 | // empty 35 | } 36 | 37 | public int getIconWidth() { 38 | return width; 39 | } 40 | 41 | public int getIconHeight() { 42 | return height; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/org/violetlib/aqua/FocusRingOutlineProvider.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2020 Alan Snyder. 3 | * All rights reserved. 4 | * 5 | * You may not use, copy or modify this file, except in compliance with the license agreement. For details see 6 | * accompanying license terms. 7 | */ 8 | 9 | package org.violetlib.aqua; 10 | 11 | import javax.swing.*; 12 | import java.awt.*; 13 | 14 | import org.jetbrains.annotations.NotNull; 15 | import org.jetbrains.annotations.Nullable; 16 | 17 | /** 18 | * An interface to allow a component UI to return a focus ring outline for a component. 19 | */ 20 | public interface FocusRingOutlineProvider { 21 | 22 | /** 23 | * Return the focus ring outline to use for the specified component. The actual focus ring shape will be determined 24 | * by the focus ring painter based on this outline. In most cases, the outline should correspond to the visual 25 | * outline of the component, excluding shadows. 26 | * 27 | * Most focus ring outlines depend only upon the component location and size. There are some components, such as 28 | * JSlider, where the focus ring outline also depends upon the state of the component. Providers for these 29 | * components must notify the focus ring manager when the outline may have changed, by calling 30 | * AquaFocusRingManager#focusRingOutlineChanged. This method only needs to be called when the focus ring is being 31 | * displayed. 32 | * 33 | * @param c The component. 34 | * @return the focus ring outline, relative to the component bounds, or null if the component should not display a 35 | * focus ring. 36 | */ 37 | @Nullable Shape getFocusRingOutline(@NotNull JComponent c); 38 | } 39 | -------------------------------------------------------------------------------- /src/org/violetlib/aqua/FocusRingPainter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2015 Alan Snyder. 3 | * All rights reserved. 4 | * 5 | * You may not use, copy or modify this file, except in compliance with the license agreement. For details see 6 | * accompanying license terms. 7 | */ 8 | 9 | package org.violetlib.aqua; 10 | 11 | import java.awt.*; 12 | 13 | /** 14 | * Interface for a focus ring painter. 15 | */ 16 | public interface FocusRingPainter { 17 | 18 | /** 19 | * Paint a focus ring using the specified color. 20 | */ 21 | void paint(Graphics2D g, Color c); 22 | } 23 | -------------------------------------------------------------------------------- /src/org/violetlib/aqua/GenericList.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2015 Alan Snyder. 3 | * All rights reserved. 4 | * 5 | * You may not use, copy or modify this file, except in compliance with the license agreement. For details see 6 | * accompanying license terms. 7 | */ 8 | 9 | package org.violetlib.aqua; 10 | 11 | import javax.swing.*; 12 | import java.awt.*; 13 | 14 | /** 15 | * A generic interface for a component that has list-like behavior (e.g. JList, JTable, TreeTable). 16 | */ 17 | public interface GenericList { 18 | 19 | JComponent getComponent(); 20 | 21 | boolean isEnabled(); 22 | 23 | void requestFocus(); 24 | 25 | int getRowCount(); 26 | 27 | Object getRow(int index); 28 | 29 | boolean isMultipleSelection(); 30 | 31 | boolean isRowSelected(int index); 32 | 33 | boolean isSelectionEmpty(); 34 | 35 | void clearSelection(); 36 | 37 | void setSelectionInterval(int index1, int index2); 38 | 39 | void addSelectionInterval(int index1, int index2); 40 | 41 | void removeSelectionInterval(int index1, int index2); 42 | 43 | int getAnchorSelectionIndex(); 44 | 45 | void setAnchorSelectionIndex(int index); 46 | 47 | int getMinSelectionIndex(); 48 | 49 | int getMaxSelectionIndex(); 50 | 51 | boolean isValueAdjusting(); 52 | 53 | void setValueIsAdjusting(boolean b); 54 | 55 | int identifyRowAtLocation(Point loc); 56 | 57 | void scrollToViewRows(int index1, int index2); 58 | 59 | boolean isDragEnabled(); 60 | 61 | TransferHandler getTransferHandler(); 62 | } 63 | -------------------------------------------------------------------------------- /src/org/violetlib/aqua/GradientColor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018-2020 Alan Snyder. 3 | * All rights reserved. 4 | * 5 | * You may not use, copy or modify this file, except in compliance with the license agreement. For details see 6 | * accompanying license terms. 7 | */ 8 | 9 | package org.violetlib.aqua; 10 | 11 | import java.awt.*; 12 | import javax.swing.plaf.ColorUIResource; 13 | 14 | import org.jetbrains.annotations.NotNull; 15 | 16 | /** 17 | * A synthetic color that paints a gradient. 18 | */ 19 | 20 | public class GradientColor extends ColorUIResource { 21 | private final @NotNull Color finish; 22 | private final boolean useMagicEraser; 23 | private final @NotNull Logger log; 24 | 25 | public GradientColor(@NotNull Color start, @NotNull Color finish, @NotNull Logger log) { 26 | super(start); 27 | this.finish = finish; 28 | this.useMagicEraser = false; 29 | this.log = log; 30 | } 31 | 32 | public GradientColor(@NotNull Color start, @NotNull Color finish, boolean useMagicEraser, @NotNull Logger log) { 33 | super(start); 34 | this.finish = finish; 35 | this.useMagicEraser = useMagicEraser; 36 | this.log = log; 37 | 38 | if (useMagicEraser && (start.getAlpha() == 255 && finish.getAlpha() == 255)) { 39 | log.log("Magic eraser not needed with opaque gradient"); 40 | } 41 | } 42 | 43 | public @NotNull Color getStart() { 44 | return this; 45 | } 46 | 47 | public @NotNull Color getFinish() { 48 | return finish; 49 | } 50 | 51 | public boolean useMagicEraser() { 52 | return useMagicEraser; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/org/violetlib/aqua/ImageIconUIResource.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2004, 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 org.violetlib.aqua; 27 | 28 | import javax.swing.ImageIcon; 29 | import javax.swing.plaf.UIResource; 30 | import java.awt.Image; 31 | 32 | /** 33 | * A subclass of ImageIcon that implements UIResource. 34 | * 35 | * @author Shannon Hickey 36 | * 37 | */ 38 | @SuppressWarnings("serial") // JDK-implementation class 39 | public class ImageIconUIResource extends ImageIcon implements UIResource { 40 | 41 | /** 42 | * Calls the superclass constructor with the same parameter. 43 | * 44 | * @param imageData an array of pixels 45 | * @see javax.swing.ImageIcon#ImageIcon(byte[]) 46 | */ 47 | public ImageIconUIResource(byte[] imageData) { 48 | super(imageData); 49 | } 50 | 51 | /** 52 | * Calls the superclass constructor with the same parameter. 53 | * 54 | * @param image an image 55 | * @see javax.swing.ImageIcon#ImageIcon(Image) 56 | */ 57 | public ImageIconUIResource(Image image) { 58 | super(image); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/org/violetlib/aqua/KeyWindowPatch.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018-2021 Alan Snyder. 3 | * All rights reserved. 4 | * 5 | * You may not use, copy or modify this file, except in compliance with the license agreement. For details see 6 | * accompanying license terms. 7 | */ 8 | 9 | package org.violetlib.aqua; 10 | 11 | import java.awt.*; 12 | import java.security.AccessControlException; 13 | 14 | /** 15 | * A very hairy patch to support coexistence with native key-only windows, such as the NSColorPanel. 16 | * This problem is fixed in Java 11. 17 | */ 18 | 19 | public class KeyWindowPatch 20 | { 21 | private static Boolean isInstalled; // false if install failed, true if install succeeded, null if not tried 22 | private static Boolean isNeeded; // false if not needed, true if needed, null if not known 23 | 24 | public static void installIfNeeded() { 25 | if (isInstalled == null && isNeeded()) { 26 | loadNativeSupport(); 27 | } 28 | } 29 | 30 | public static void applyPatchIfNeeded(Window w) { 31 | if (isNeededAndIsInstalled()) { 32 | AquaUtils.ensureWindowPeer(w); 33 | AquaUtils.execute(w, ptr -> ensureWindowDelegateInstalled(w, ptr)); 34 | } 35 | } 36 | 37 | private static boolean isNeeded() { 38 | if (isNeeded == null) { 39 | isNeeded = computeIfNeeded(); 40 | } 41 | return Boolean.TRUE.equals(isNeeded); 42 | } 43 | 44 | private static boolean isNeededAndIsInstalled() { 45 | if (isNeeded()) { 46 | if (isInstalled == null) { 47 | loadNativeSupport(); 48 | } 49 | return Boolean.TRUE.equals(isInstalled); 50 | } 51 | return false; 52 | } 53 | 54 | private static Boolean computeIfNeeded() { 55 | int version = Utils.getJavaVersion(); 56 | return version < 1100000; 57 | } 58 | 59 | private static void loadNativeSupport() { 60 | isInstalled = false; 61 | try { 62 | String fn = AquaNativeSupport.findNativeLibrary(AquaNativeSupport.class, "keywindowpatch"); 63 | if (fn == null) { 64 | reportError("Library not found"); 65 | return; 66 | } 67 | 68 | System.load(fn); 69 | isInstalled = true; 70 | Utils.logDebug("VAqua: installed patch for main/key window support"); 71 | } catch (UnsatisfiedLinkError e) { 72 | reportError(e.getMessage()); 73 | } catch (AccessControlException e) { 74 | reportError("permission denied: " + e.getMessage()); 75 | } catch (Throwable e) { 76 | reportError(e.toString()); 77 | e.printStackTrace(); 78 | } 79 | } 80 | 81 | private static void reportError(String msg) { 82 | String s = "KeyWindowPatch: Unable to load library: " + msg; 83 | Utils.logError(s); 84 | } 85 | 86 | private static long ensureWindowDelegateInstalled(Window w, long wptr) 87 | { 88 | return nativeEnsureWindowDelegateInstalled(wptr); 89 | } 90 | 91 | private static native int nativeEnsureWindowDelegateInstalled(long w); 92 | } 93 | -------------------------------------------------------------------------------- /src/org/violetlib/aqua/Logger.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 Alan Snyder. 3 | * All rights reserved. 4 | * 5 | * You may not use, copy or modify this file, except in compliance with the license agreement. For details see 6 | * accompanying license terms. 7 | */ 8 | 9 | package org.violetlib.aqua; 10 | 11 | import org.jetbrains.annotations.NotNull; 12 | 13 | /** 14 | * An interface for debug logging 15 | */ 16 | 17 | public interface Logger { 18 | void log(@NotNull String message); 19 | } 20 | -------------------------------------------------------------------------------- /src/org/violetlib/aqua/MenuVibrantEffects.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 Alan Snyder. 3 | * All rights reserved. 4 | * 5 | * You may not use, copy or modify this file, except in compliance with the license agreement. For details see 6 | * accompanying license terms. 7 | */ 8 | 9 | package org.violetlib.aqua; 10 | 11 | import java.awt.*; 12 | import javax.swing.*; 13 | 14 | import org.jetbrains.annotations.NotNull; 15 | import org.jetbrains.annotations.Nullable; 16 | 17 | /** 18 | * Support for vibrant effects. An NSVisualEffectView is created for the menu background and for the selected menu item 19 | * background region. 20 | */ 21 | 22 | public class MenuVibrantEffects extends VisualEffectView { 23 | protected @Nullable MenuSelectionBoundsTracker bt; 24 | protected final int style; 25 | 26 | public MenuVibrantEffects(@NotNull JComponent top, @NotNull JPopupMenu menu, int style) { 27 | super(top, style, true); 28 | 29 | this.style = style; 30 | bt = new MenuSelectionBoundsTracker(menu, this::updateSelectionBackgrounds) { 31 | @Override 32 | protected int convertRowYCoordinateToSelectionDescription(int y) { 33 | if (top != menu) { 34 | Point p = SwingUtilities.convertPoint(menu, 0, y, top); 35 | return p.y; 36 | } else { 37 | return y; 38 | } 39 | } 40 | }; 41 | menu.putClientProperty(AquaPopupMenuUI.POP_UP_TRACKER, bt); 42 | 43 | //menu.getSelectionModel().addChangeListener(e -> update()); 44 | } 45 | 46 | public void update() { 47 | if (bt != null) { 48 | bt.update(); 49 | } 50 | } 51 | 52 | public void dispose() { 53 | super.dispose(); 54 | if (bt != null) { 55 | bt.dispose(); 56 | bt = null; 57 | } 58 | } 59 | 60 | @Override 61 | protected void windowChanged(Window newWindow) { 62 | super.windowChanged(newWindow); 63 | if (bt != null) { 64 | bt.reset(); 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/org/violetlib/aqua/OutlineFocusRingPainter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2015 Alan Snyder. 3 | * All rights reserved. 4 | * 5 | * You may not use, copy or modify this file, except in compliance with the license agreement. For details see 6 | * accompanying license terms. 7 | */ 8 | 9 | package org.violetlib.aqua; 10 | 11 | import java.awt.*; 12 | import java.awt.geom.Area; 13 | 14 | /** 15 | * Paint a focus ring based on an inner and outer shape. 16 | */ 17 | public class OutlineFocusRingPainter implements FocusRingPainter { 18 | 19 | protected final Shape ringShape; 20 | 21 | /** 22 | * Create a focus ring painter based on an inner and outer shape. 23 | * @param innerShape The inner shape. 24 | * @param outerShape The outer shape. 25 | */ 26 | public OutlineFocusRingPainter(Shape innerShape, Shape outerShape) { 27 | Area outerArea = new Area(outerShape); 28 | Area innerArea = new Area(innerShape); 29 | outerArea.subtract(innerArea); 30 | ringShape = outerArea; 31 | } 32 | 33 | public void paint(Graphics2D gg, Color c) { 34 | Graphics2D g = (Graphics2D) gg.create(); 35 | g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); 36 | g.setColor(c); 37 | g.fill(ringShape); 38 | g.dispose(); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/org/violetlib/aqua/SelectionBoundsTracker.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 Alan Snyder. 3 | * All rights reserved. 4 | * 5 | * You may not use, copy or modify this file, except in compliance with the license agreement. For details see 6 | * accompanying license terms. 7 | */ 8 | 9 | package org.violetlib.aqua; 10 | 11 | import java.util.function.Consumer; 12 | 13 | /** 14 | * An interface for an object that determines the bounds of the regions of a component that correspond to selected items 15 | * and tracks changes in those bounds. 16 | */ 17 | public interface SelectionBoundsTracker { 18 | 19 | /** 20 | * Install the consumer to receive the initial selection bounds as well as any subsequent changes. 21 | * A null value is produced when there are no selected regions. 22 | */ 23 | void setConsumer(Consumer consumer); 24 | 25 | /** 26 | * Call this method to recompute the selection bounds. 27 | */ 28 | void update(); 29 | 30 | /** 31 | * Call this method to discard the current selection bounds. 32 | */ 33 | void reset(); 34 | 35 | /** 36 | * Call this method when selection bounds tracking is no longer needed. 37 | */ 38 | void dispose(); 39 | } 40 | -------------------------------------------------------------------------------- /src/org/violetlib/aqua/SelectionRegion.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 Alan Snyder. 3 | * All rights reserved. 4 | * 5 | * You may not use, copy or modify this file, except in compliance with the license agreement. For details see 6 | * accompanying license terms. 7 | */ 8 | 9 | package org.violetlib.aqua; 10 | 11 | import org.jetbrains.annotations.NotNull; 12 | 13 | /** 14 | * A description of a full-width region corresponding to a selection. 15 | */ 16 | 17 | public class SelectionRegion { 18 | public final int y; 19 | public final int height; 20 | 21 | public SelectionRegion(int y, int height) { 22 | this.y = y; 23 | this.height = height; 24 | } 25 | 26 | public boolean matches(@NotNull SelectionRegion r) { 27 | return y == r.y && height == r.height; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/org/violetlib/aqua/SelectionRepaintable.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2015 Alan Snyder. 3 | * All rights reserved. 4 | * 5 | * You may not use, copy or modify this file, except in compliance with the license agreement. For details see 6 | * accompanying license terms. 7 | */ 8 | 9 | package org.violetlib.aqua; 10 | 11 | /** 12 | * Additional methods supported by tree and table UIs, used by TreeTableUI. 13 | */ 14 | public interface SelectionRepaintable { 15 | void repaintSelection(); 16 | } 17 | -------------------------------------------------------------------------------- /src/org/violetlib/aqua/SharedColorChooserOwner.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 Alan Snyder. 3 | * All rights reserved. 4 | * 5 | * You may not use, copy or modify this file, except in compliance with the license agreement. For details see 6 | * accompanying license terms. 7 | */ 8 | 9 | package org.violetlib.aqua; 10 | 11 | import java.awt.*; 12 | 13 | /** 14 | * The interface that supports a connection to the object that wants a color to be specified using a shared color 15 | * chooser. 16 | */ 17 | public interface SharedColorChooserOwner { 18 | /** 19 | * This method is called to apply a color selection. This method may be called multiple times while connected. 20 | * @param c 21 | */ 22 | void applyColor(Color c); 23 | /** 24 | * This method is called when the connection is broken except by the explicit request of this owner. 25 | */ 26 | void disconnected(); 27 | } 28 | -------------------------------------------------------------------------------- /src/org/violetlib/aqua/StripedContainerContextualColors.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Alan Snyder. 3 | * All rights reserved. 4 | * 5 | * You may not use, copy or modify this file, except in compliance with the license agreement. For details see 6 | * accompanying license terms. 7 | */ 8 | 9 | package org.violetlib.aqua; 10 | 11 | import java.awt.*; 12 | 13 | import org.jetbrains.annotations.NotNull; 14 | 15 | /** 16 | 17 | */ 18 | 19 | public class StripedContainerContextualColors implements ContainerContextualColors { 20 | 21 | protected @NotNull ContextualColor containerBackground; 22 | protected @NotNull ContextualColor evenRowBackground; 23 | protected @NotNull ContextualColor oddRowBackground; 24 | protected @NotNull ContextualColor grid; 25 | protected boolean isRowSelected; 26 | protected @NotNull ContextualColor background; 27 | protected @NotNull ContextualColor foreground; 28 | 29 | /** 30 | * Create colors for a striped container. 31 | */ 32 | public StripedContainerContextualColors(@NotNull ContextualColor containerBackground, 33 | @NotNull ContextualColor evenRowBackground, 34 | @NotNull ContextualColor oddRowBackground, 35 | @NotNull ContextualColor foreground, 36 | @NotNull ContextualColor grid) { 37 | this.containerBackground = containerBackground; 38 | this.evenRowBackground = evenRowBackground; 39 | this.oddRowBackground = oddRowBackground; 40 | this.grid = grid; 41 | this.background = containerBackground; 42 | this.foreground = foreground; 43 | } 44 | 45 | public void configureForContainer() { 46 | isRowSelected = false; 47 | this.background = containerBackground; 48 | } 49 | 50 | public void configureForRow(int rowIndex, boolean isRowSelected) { 51 | this.isRowSelected = isRowSelected; 52 | this.background = rowIndex % 2 == 0 ? evenRowBackground : oddRowBackground; 53 | } 54 | 55 | public void configureForRow(boolean isRowSelected) { 56 | this.isRowSelected = isRowSelected; 57 | this.background = containerBackground; 58 | } 59 | 60 | public boolean isStriped() { 61 | return true; 62 | } 63 | 64 | @Override 65 | public @NotNull Color getBackground(@NotNull AppearanceContext context) { 66 | context = context.withSelected(isRowSelected || context.isSelected()); 67 | return background.get(context); 68 | } 69 | 70 | @Override 71 | public @NotNull Color getForeground(@NotNull AppearanceContext context) { 72 | context = context.withSelected(isRowSelected || context.isSelected()); 73 | return foreground.get(context); 74 | } 75 | 76 | public @NotNull Color getGrid(@NotNull AppearanceContext context) { 77 | context = context.withSelected(isRowSelected || context.isSelected()); 78 | return grid.get(context); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/org/violetlib/aqua/SystemPropertyChangeManager.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023 Alan Snyder. 3 | * All rights reserved. 4 | * 5 | * You may not use, copy or modify this file, except in compliance with the license agreement. For details see 6 | * accompanying license terms. 7 | */ 8 | 9 | package org.violetlib.aqua; 10 | 11 | import java.util.ArrayList; 12 | import java.util.Collection; 13 | import java.util.List; 14 | import java.util.WeakHashMap; 15 | import javax.swing.*; 16 | import javax.swing.plaf.ComponentUI; 17 | 18 | /** 19 | * Manage components whose UIs want to be notified when certain system properties change. 20 | * This design avoids holding a strong reference to the component. 21 | */ 22 | 23 | public class SystemPropertyChangeManager { 24 | 25 | public interface SystemPropertyChangeListener { 26 | void systemPropertyChanged(JComponent c, Object type); 27 | } 28 | 29 | private static final WeakHashMap components = new WeakHashMap<>(); 30 | 31 | public static void register(JComponent c) { 32 | components.put(c, null); 33 | } 34 | 35 | public static void unregister(JComponent c) { 36 | components.remove(c); 37 | } 38 | 39 | public static void notifyChange(Object type) { 40 | Collection cs = components.keySet(); 41 | if (!cs.isEmpty()) { 42 | List componentList = new ArrayList<>(cs); 43 | for (JComponent jc : componentList) { 44 | SystemPropertyChangeListener l = AquaUtils.getUI(jc, SystemPropertyChangeListener.class); 45 | if (l != null) { 46 | l.systemPropertyChanged(jc, type); 47 | } else { 48 | components.remove(jc); 49 | } 50 | } 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/org/violetlib/aqua/TintedEraser.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 Alan Snyder. 3 | * All rights reserved. 4 | * 5 | * You may not use, copy or modify this file, except in compliance with the license agreement. For details see 6 | * accompanying license terms. 7 | */ 8 | 9 | package org.violetlib.aqua; 10 | 11 | import java.awt.*; 12 | import javax.swing.plaf.ColorUIResource; 13 | 14 | /** 15 | * A synthetic color that erases, then applies a tint. 16 | */ 17 | 18 | public class TintedEraser extends ColorUIResource { 19 | public TintedEraser(int intensity, int alpha) { 20 | super(new Color(intensity, intensity, intensity, alpha)); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/org/violetlib/aqua/ToolbarSensitiveUI.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Alan Snyder. 3 | * All rights reserved. 4 | * 5 | * You may not use, copy or modify this file, except in compliance with the license agreement. For details see 6 | * accompanying license terms. 7 | */ 8 | 9 | package org.violetlib.aqua; 10 | 11 | import javax.swing.*; 12 | 13 | import org.jetbrains.annotations.NotNull; 14 | 15 | /** 16 | 17 | */ 18 | 19 | public interface ToolbarSensitiveUI { 20 | 21 | /** 22 | * This method is called when the toolbar status of the component may have changed. 23 | * See {@link AquaUtils#installToolbarSensitivity(JComponent)}. 24 | */ 25 | void toolbarStatusChanged(@NotNull JComponent c); 26 | } 27 | -------------------------------------------------------------------------------- /src/org/violetlib/aqua/UniformContainerContextualColors.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Alan Snyder. 3 | * All rights reserved. 4 | * 5 | * You may not use, copy or modify this file, except in compliance with the license agreement. For details see 6 | * accompanying license terms. 7 | */ 8 | 9 | package org.violetlib.aqua; 10 | 11 | import java.awt.*; 12 | 13 | import org.jetbrains.annotations.NotNull; 14 | 15 | /** 16 | 17 | */ 18 | 19 | public class UniformContainerContextualColors implements ContainerContextualColors { 20 | 21 | protected @NotNull ContextualColor background; 22 | protected @NotNull ContextualColor foreground; 23 | protected @NotNull ContextualColor grid; 24 | protected boolean isRowSelected; 25 | 26 | /** 27 | * Create colors for a uniform (not striped) container. 28 | */ 29 | 30 | public UniformContainerContextualColors(@NotNull ContextualColor background, 31 | @NotNull ContextualColor foreground, 32 | @NotNull ContextualColor grid) { 33 | this.background = background; 34 | this.foreground = foreground; 35 | this.grid = grid; 36 | } 37 | 38 | public void configureForContainer() { 39 | isRowSelected = false; 40 | } 41 | 42 | public void configureForRow(int rowIndex, boolean isRowSelected) { 43 | this.isRowSelected = isRowSelected; 44 | } 45 | 46 | public void configureForRow(boolean isRowSelected) { 47 | this.isRowSelected = isRowSelected; 48 | } 49 | 50 | public boolean isStriped() { 51 | return false; 52 | } 53 | 54 | @Override 55 | public @NotNull Color getBackground(@NotNull AppearanceContext context) { 56 | context = context.withSelected(isRowSelected || context.isSelected()); 57 | return background.get(context); 58 | } 59 | 60 | @Override 61 | public @NotNull Color getForeground(@NotNull AppearanceContext context) { 62 | context = context.withSelected(isRowSelected || context.isSelected()); 63 | return foreground.get(context); 64 | } 65 | 66 | public @NotNull Color getGrid(@NotNull AppearanceContext context) { 67 | context = context.withSelected(isRowSelected || context.isSelected()); 68 | return grid.get(context); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/org/violetlib/aqua/Utils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015-2021 Alan Snyder. 3 | * All rights reserved. 4 | * 5 | * You may not use, copy or modify this file, except in compliance with the license agreement. For details see 6 | * accompanying license terms. 7 | */ 8 | 9 | package org.violetlib.aqua; 10 | 11 | import java.util.StringTokenizer; 12 | 13 | import org.jetbrains.annotations.NotNull; 14 | 15 | /** 16 | * Basic utilities that do not involve native code. 17 | */ 18 | 19 | public class Utils { 20 | 21 | private static final int javaVersion = obtainJavaVersion(); 22 | 23 | private Utils() { 24 | } 25 | 26 | public static void logError(@NotNull String message) { 27 | System.err.println(message); 28 | } 29 | 30 | public static void logError(@NotNull String message, @NotNull Throwable th) { 31 | System.err.println(message + ": " + th); 32 | } 33 | 34 | public static void logDebug(@NotNull String message) { 35 | System.err.println(message); 36 | } 37 | 38 | public static int getJavaVersion() { 39 | return javaVersion; 40 | } 41 | 42 | private static int obtainJavaVersion() 43 | { 44 | String s = System.getProperty("java.version"); 45 | if (s.startsWith("1.")) { 46 | s = s.substring(2); 47 | } 48 | int version = 0; 49 | int tokenCount = 0; 50 | StringTokenizer st = new StringTokenizer(s, "._"); 51 | try { 52 | while (st.hasMoreTokens()) { 53 | String token = st.nextToken(); 54 | int pos = token.indexOf("-"); 55 | if (pos > 0) { 56 | token = token.substring(0, pos); 57 | } 58 | int n = Integer.parseInt(token); 59 | ++tokenCount; 60 | int limit = tokenCount < 3 ? 100 : 1000; 61 | if (n < 0 || n >= limit) { 62 | return 0; 63 | } 64 | version = version * limit + n; 65 | if (tokenCount == 3) { 66 | return version; 67 | } 68 | } 69 | } catch (NumberFormatException ex) { 70 | return 0; 71 | } 72 | 73 | while (tokenCount < 3) { 74 | ++tokenCount; 75 | int limit = tokenCount < 3 ? 100 : 1000; 76 | version = version * limit; 77 | } 78 | return version; 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/org/violetlib/aqua/VisibleBounds.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 Alan Snyder. 3 | * All rights reserved. 4 | * 5 | * You may not use, copy or modify this file, except in compliance with the license agreement. For details see 6 | * accompanying license terms. 7 | */ 8 | 9 | package org.violetlib.aqua; 10 | 11 | import java.awt.*; 12 | import java.util.Objects; 13 | 14 | import org.jetbrains.annotations.NotNull; 15 | import org.jetbrains.annotations.Nullable; 16 | 17 | /** 18 | * A description of the location and visibility of a native view with respect to the native content view. This 19 | * description supports rectangular clipping that can be imposed by scroll pane viewports. It does not support arbitrary 20 | * clipping that might result from occlusion by components painted over the native view. 21 | */ 22 | 23 | public final class VisibleBounds { 24 | 25 | /** 26 | * The region of the content view where the view appears. 27 | */ 28 | public final @NotNull Rectangle visibleBounds; 29 | 30 | /** 31 | * The origin and size of the full view. For a fully visible view, the frame will match the visible bounds. 32 | */ 33 | public final @NotNull Rectangle frame; 34 | 35 | public VisibleBounds(@NotNull Rectangle visibleBounds, @NotNull Rectangle frame) { 36 | this.visibleBounds = visibleBounds; 37 | this.frame = frame; 38 | } 39 | 40 | public boolean isClipped() { 41 | return !visibleBounds.equals(frame); 42 | } 43 | 44 | @Override 45 | public boolean equals(@Nullable Object o) { 46 | if (this == o) { 47 | return true; 48 | } 49 | if (o == null || getClass() != o.getClass()) { 50 | return false; 51 | } 52 | VisibleBounds that = (VisibleBounds) o; 53 | return visibleBounds.equals(that.visibleBounds) && frame.equals(that.frame); 54 | } 55 | 56 | @Override 57 | public int hashCode() { 58 | return Objects.hash(visibleBounds, frame); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/org/violetlib/aqua/VisualEffectViewPeer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 Alan Snyder. 3 | * All rights reserved. 4 | * 5 | * You may not use, copy or modify this file, except in compliance with the license agreement. For details see 6 | * accompanying license terms. 7 | */ 8 | 9 | package org.violetlib.aqua; 10 | 11 | /** 12 | * Provide access to the native support for visual effect views. 13 | */ 14 | public interface VisualEffectViewPeer { 15 | void setFrame(int x, int y, int width, int height); 16 | void updateSelectionBackgrounds(SelectionBoundsDescription sd); 17 | void dispose(); 18 | } 19 | -------------------------------------------------------------------------------- /src/org/violetlib/aqua/WindowDraggingMouseListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015-2016 Alan Snyder. 3 | * All rights reserved. 4 | * 5 | * You may not use, copy or modify this file, except in compliance with the license agreement. For details see 6 | * accompanying license terms. 7 | */ 8 | 9 | package org.violetlib.aqua; 10 | 11 | import java.awt.*; 12 | import java.awt.event.MouseEvent; 13 | import javax.swing.*; 14 | import javax.swing.event.MouseInputAdapter; 15 | 16 | /** 17 | * Support window dragging. 18 | */ 19 | public class WindowDraggingMouseListener extends MouseInputAdapter { 20 | private Window w; 21 | private JComponent c; 22 | private int topExclude; 23 | private int xOffset; 24 | private int yOffset; 25 | 26 | public WindowDraggingMouseListener(int topExclude) { 27 | this.topExclude = topExclude; 28 | } 29 | 30 | public void attach(JComponent c) { 31 | if (c != null) { 32 | this.c = c; 33 | c.addMouseListener(this); 34 | c.addMouseMotionListener(this); 35 | } 36 | } 37 | 38 | public void detach() { 39 | if (c != null) { 40 | c.removeMouseListener(this); 41 | c.removeMouseMotionListener(this); 42 | } 43 | } 44 | 45 | @Override 46 | public void mousePressed(MouseEvent e) { 47 | Component c = e.getComponent(); 48 | Window ancestor = SwingUtilities.getWindowAncestor(c); 49 | if (ancestor != null) { 50 | Point p = e.getPoint(); 51 | if (p.y >= topExclude && isDragArea(c, p) 52 | && !AquaSheetSupport.isSheet(ancestor) && !AquaUtils.isFullScreenWindow(ancestor)) { 53 | w = ancestor; 54 | xOffset = e.getX(); 55 | yOffset = e.getY(); 56 | e.consume(); 57 | } 58 | } 59 | } 60 | 61 | @Override 62 | public void mouseReleased(MouseEvent e) { 63 | if (w != null) { 64 | w = null; 65 | e.consume(); 66 | } 67 | } 68 | 69 | @Override 70 | public void mouseDragged(MouseEvent e) { 71 | if (w != null) { 72 | Point p = MouseInfo.getPointerInfo().getLocation(); 73 | int x = p.x - xOffset; 74 | int y = p.y - yOffset; 75 | w.setLocation(x, y); 76 | e.consume(); 77 | } 78 | } 79 | 80 | protected boolean isDragArea(Component c, Point p) { 81 | return true; 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/org/violetlib/aqua/WindowStylePatch.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018-2021 Alan Snyder. 3 | * All rights reserved. 4 | * 5 | * You may not use, copy or modify this file, except in compliance with the license agreement. For details see 6 | * accompanying license terms. 7 | */ 8 | 9 | package org.violetlib.aqua; 10 | 11 | import java.security.AccessControlException; 12 | 13 | /** 14 | * A patch to prevent AWT from writing over window style bits set by VAqua. 15 | * This patch does not work in JDK 12+ (and is not used there). 16 | */ 17 | 18 | public class WindowStylePatch 19 | { 20 | private static Boolean isInstalled; // false if install failed, true if install succeeded, null if not tried 21 | private static Boolean isNeeded; // false if not needed, true if needed, null if not known 22 | 23 | public static void installIfNeeded() { 24 | if (isInstalled == null && isNeeded()) { 25 | loadNativeSupport(); 26 | } 27 | } 28 | 29 | public static boolean isNeeded() { 30 | if (isNeeded == null) { 31 | isNeeded = computeIfNeeded(); 32 | } 33 | return Boolean.TRUE.equals(isNeeded); 34 | } 35 | 36 | private static Boolean computeIfNeeded() { 37 | int version = Utils.getJavaVersion(); 38 | return version < 1200000; 39 | } 40 | 41 | private static void loadNativeSupport() { 42 | isInstalled = false; 43 | try { 44 | String fn = AquaNativeSupport.findNativeLibrary(AquaNativeSupport.class, "windowstylepatch"); 45 | if (fn == null) { 46 | reportError("Library not found"); 47 | return; 48 | } 49 | 50 | System.load(fn); 51 | isInstalled = true; 52 | Utils.logDebug("VAqua: installed patch for preserving window style bits"); 53 | } catch (UnsatisfiedLinkError e) { 54 | reportError(e.getMessage()); 55 | } catch (AccessControlException e) { 56 | reportError("permission denied: " + e.getMessage()); 57 | } catch (Throwable e) { 58 | reportError(e.toString()); 59 | e.printStackTrace(); 60 | } 61 | } 62 | 63 | private static void reportError(String msg) { 64 | String s = "WindowStylePatch: Unable to load library: " + msg; 65 | Utils.logError(s); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/org/violetlib/aqua/fc/AbstractFileChooserBrowserListUI.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2015 Alan Snyder. 3 | * All rights reserved. 4 | * 5 | * You may not use, copy or modify this file, except in compliance with the license agreement. For details see 6 | * accompanying license terms. 7 | */ 8 | 9 | package org.violetlib.aqua.fc; 10 | 11 | /** 12 | * An abstract base class for a file chooser browser list UI. 13 | */ 14 | public interface AbstractFileChooserBrowserListUI { 15 | void setFileSelectionHandler(AquaFileChooserListMouseBehavior.FileSelectionHandler h); 16 | } 17 | -------------------------------------------------------------------------------- /src/org/violetlib/aqua/fc/AquaFileChooserBrowser.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2018 Alan Snyder. 3 | * All rights reserved. 4 | * 5 | * You may not use, copy or modify this file, except in compliance with the license agreement. For details see 6 | * accompanying license terms. 7 | */ 8 | 9 | package org.violetlib.aqua.fc; 10 | 11 | import javax.swing.*; 12 | import javax.swing.plaf.ListUI; 13 | import java.awt.*; 14 | import java.awt.event.MouseWheelEvent; 15 | import java.awt.event.MouseWheelListener; 16 | import java.io.File; 17 | 18 | import org.jetbrains.annotations.Nullable; 19 | 20 | /** 21 | * The browser in a file chooser. Implements special behavior for clicking on an ordinary file in a Save panel. 22 | */ 23 | public class AquaFileChooserBrowser extends JBrowser { 24 | protected final JFileChooser fc; 25 | protected final ColumnScrollPaneMouseWheelListener columnScrollPaneMouseWheelListener; 26 | 27 | public AquaFileChooserBrowser(JFileChooser fc) { 28 | this.fc = fc; 29 | columnScrollPaneMouseWheelListener = new ColumnScrollPaneMouseWheelListener(); 30 | } 31 | 32 | @Override 33 | protected ListUI getColumnListUI(ListUI basicUI) { 34 | 35 | AbstractFileChooserBrowserListUI ui = new AquaFileChooserBrowserListUI(fc); 36 | 37 | ui.setFileSelectionHandler(new AquaFileChooserListMouseBehavior.FileSelectionHandler() { 38 | @Override 39 | public void fileSelected(File f) { 40 | AquaFileChooserBrowser.this.fileSelectedInSavePanel(f); 41 | } 42 | }); 43 | 44 | return (ListUI) ui; 45 | } 46 | 47 | @Override 48 | protected JScrollPane createScrollPane(@Nullable JComponent c) { 49 | JScrollPane sp = super.createScrollPane(c); 50 | sp.addMouseWheelListener(columnScrollPaneMouseWheelListener); 51 | return sp; 52 | } 53 | 54 | protected void fileSelectedInSavePanel(File f) { 55 | } 56 | 57 | /** 58 | * Support horizontal mouse wheel scrolling of the entire browser when the mouse is over a column scroll pane. 59 | */ 60 | protected class ColumnScrollPaneMouseWheelListener implements MouseWheelListener { 61 | @Override 62 | public void mouseWheelMoved(MouseWheelEvent e) { 63 | if (e.isShiftDown()) { 64 | JScrollPane browserScrollPane = getBrowserScrollPane(e.getComponent()); 65 | if (browserScrollPane != null) { 66 | MouseWheelEvent ce = (MouseWheelEvent) SwingUtilities.convertMouseEvent(e.getComponent(), e, browserScrollPane); 67 | browserScrollPane.dispatchEvent(ce); 68 | } 69 | } 70 | } 71 | 72 | protected JScrollPane getBrowserScrollPane(Component c) { 73 | for (;;) { 74 | Container p = c.getParent(); 75 | if (p == null || p instanceof JFileChooser) { 76 | return null; 77 | } 78 | if (p instanceof JScrollPane) { 79 | return (JScrollPane) p; 80 | } 81 | c = p; 82 | } 83 | } 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /src/org/violetlib/aqua/fc/AquaFileChooserBrowserListUI.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2015 Alan Snyder. 3 | * All rights reserved. 4 | * 5 | * You may not use, copy or modify this file, except in compliance with the license agreement. For details see 6 | * accompanying license terms. 7 | */ 8 | 9 | package org.violetlib.aqua.fc; 10 | 11 | import org.violetlib.aqua.AquaListUI; 12 | import org.violetlib.aqua.JListModel; 13 | 14 | import javax.swing.*; 15 | import javax.swing.event.MouseInputListener; 16 | 17 | /** 18 | * A UI for the lists in a file chooser browser. 19 | */ 20 | public class AquaFileChooserBrowserListUI extends AquaListUI implements AbstractFileChooserBrowserListUI { 21 | 22 | private JFileChooser fc; 23 | private AquaFileChooserListMouseBehavior.FileSelectionHandler fileSelectionHandler; 24 | private AquaFileChooserListMouseBehavior mouseBehavior; 25 | 26 | public AquaFileChooserBrowserListUI(JFileChooser fc) { 27 | this.fc = fc; 28 | } 29 | 30 | public void setFileSelectionHandler(AquaFileChooserListMouseBehavior.FileSelectionHandler h) { 31 | fileSelectionHandler = h; 32 | if (mouseBehavior != null) { 33 | mouseBehavior.setFileSelectionHandler(h); 34 | } 35 | } 36 | 37 | @Override 38 | protected void installKeyboardActions() { 39 | super.installKeyboardActions(); 40 | 41 | // Avoid conflict with Cmd-Shift-A in the file chooser 42 | InputMap map = list.getInputMap(JComponent.WHEN_FOCUSED).getParent(); 43 | KeyStroke ks = KeyStroke.getKeyStroke("shift meta A"); 44 | Object v = map.get(ks); 45 | if (v != null && v.equals("clearSelection")) { 46 | InputMap newMap = new InputMap(); 47 | newMap.setParent(map); 48 | newMap.put(ks, "selectApplicationsFolder"); // dummy name for now 49 | SwingUtilities.replaceUIInputMap(list, JComponent.WHEN_FOCUSED, newMap); 50 | } 51 | } 52 | 53 | @Override 54 | protected MouseInputListener createMouseInputListener() { 55 | if (mouseBehavior == null) { 56 | mouseBehavior = new AquaFileChooserListMouseBehavior(fc, new JListModel(list)); 57 | mouseBehavior.setFileSelectionHandler(fileSelectionHandler); 58 | } 59 | return mouseBehavior; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/org/violetlib/aqua/fc/AquaFileIcon.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 Alan Snyder. 3 | * All rights reserved. 4 | * 5 | * You may not use, copy or modify this file, except in compliance with the license agreement. For details see 6 | * accompanying license terms. 7 | */ 8 | 9 | package org.violetlib.aqua.fc; 10 | 11 | import org.violetlib.aqua.DynamicIcon; 12 | 13 | /** 14 | * An object that represents the possibly evolving state of an icon for a file. 15 | */ 16 | public class AquaFileIcon extends DynamicIcon { 17 | 18 | public AquaFileIcon(int width, int height) { 19 | super(width, height); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/org/violetlib/aqua/fc/AquaFileIcons.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 Alan Snyder. 3 | * All rights reserved. 4 | * 5 | * You may not use, copy or modify this file, except in compliance with the license agreement. For details see 6 | * accompanying license terms. 7 | */ 8 | 9 | package org.violetlib.aqua.fc; 10 | 11 | import java.io.File; 12 | 13 | import org.jetbrains.annotations.NotNull; 14 | 15 | /** 16 | * Support for file icons used in the file chooser. 17 | */ 18 | public class AquaFileIcons { 19 | 20 | private static final @NotNull FileIconService fis = 21 | CatalinaFileIconServiceImpl.isAvailable() 22 | ? new CatalinaFileIconServiceImpl() 23 | : new HybridFileIconServiceImpl(); 24 | 25 | /** 26 | * Return a thumbnail icon for a file. The icon is dynamic. An image is installed into the icon when available. 27 | * Additional images may be installed if they have higher priority than the current image. 28 | */ 29 | public static @NotNull AquaFileIcon getThumbnail(@NotNull File f) 30 | { 31 | AquaFileIcon result = new AquaFileIcon(16, 16); 32 | fis.requestIcon(f, 28, 2, (icon, quality) -> result.installIcon(icon)); 33 | return result; 34 | } 35 | 36 | public static @NotNull AquaFileIcon getPreview(@NotNull File f) 37 | { 38 | AquaFileIcon result = new AquaFileIcon(1600, 1600); 39 | fis.requestIcon(f, 1600, 2, (icon, quality) -> result.installIcon(icon)); 40 | return result; 41 | } 42 | 43 | /** 44 | * Obtain the icon or QuickLook image for a file. 45 | * 46 | * @param path the path to the file. 47 | * @param isQuickLook True to get the QuickLook image, false to get the file icon. 48 | * @param useIconMode True to use Icon mode when using Quick Look, false otherwise. 49 | * @param buffers 1x and 2x rasters stored are here (2x is optional) 50 | * @param w The width of the image. 51 | * @param h The height of the image. 52 | * @return true if successful, false otherwise. 53 | */ 54 | public static native boolean nativeRenderFileImage(@NotNull String path, boolean isQuickLook, 55 | boolean useIconMode, int[][] buffers, int w, int h); 56 | } 57 | -------------------------------------------------------------------------------- /src/org/violetlib/aqua/fc/AquaFileSystemView.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2005-2013 Werner Randelshofer, Switzerland. 3 | * Copyright (c) 2018 Alan Snyder. 4 | * All rights reserved. 5 | * 6 | * The copyright of this software is owned by Werner Randelshofer. 7 | * You may not use, copy or modify this software, except in 8 | * accordance with the license agreement you entered into with 9 | * Werner Randelshofer. For details see accompanying license terms. 10 | */ 11 | 12 | package org.violetlib.aqua.fc; 13 | 14 | import java.io.File; 15 | import javax.swing.*; 16 | import javax.swing.filechooser.FileView; 17 | 18 | import org.jetbrains.annotations.NotNull; 19 | 20 | /** 21 | * An enhanced FileSystemView, which provides additional information about a file system required for Aqua file 22 | * choosers. This class acts as a wrapper on platform specific file system views. The resulting view is an Aqua-style 23 | * view on the file system. 24 | */ 25 | public abstract class AquaFileSystemView extends DelegatedFileSystemViewBase { 26 | 27 | /** 28 | * Creates a new instance. 29 | */ 30 | public AquaFileSystemView() { 31 | } 32 | 33 | /** 34 | * Convert a file (path) to canonical form. 35 | */ 36 | public File canonicalize(File f) { 37 | return f; 38 | } 39 | 40 | /** 41 | * Returns the file that represents this computer node. 42 | */ 43 | public abstract File getComputer(); 44 | 45 | /** 46 | * Returns the file that represents the system (boot) volume of this 47 | * computer. 48 | */ 49 | public abstract File getSystemVolume(); 50 | 51 | /** 52 | * Creates a system specific file view for the specified JFileChooser. 53 | */ 54 | public @NotNull FileView createFileView(JFileChooser chooser) { 55 | return new AquaFileView(this); 56 | } 57 | 58 | private static AquaFileSystemView fileSystemView; 59 | 60 | /** 61 | * Returns a FileSystemView that can be cast into AquaFileSystemView. 62 | */ 63 | public static @NotNull AquaFileSystemView getAquaFileSystemView() { 64 | if (fileSystemView == null) { 65 | fileSystemView = new OSXFileSystemView(); 66 | } 67 | return fileSystemView; 68 | } 69 | 70 | /** 71 | * Indicate whether a file (directory) can be visited. 72 | * @param f The file. 73 | * @param isPackageTraversable True if packages should be traversable. 74 | * @param isApplicationTraversable True if bundled applications should be traversable. 75 | * @return true if and only if the file can be visited. 76 | */ 77 | public @NotNull Boolean isTraversable(File f, boolean isPackageTraversable, boolean isApplicationTraversable) { 78 | return target.isTraversable(f); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/org/violetlib/aqua/fc/AquaFileView.java: -------------------------------------------------------------------------------- 1 | /* 2 | * @(#)AquaFileView.java 3 | * 4 | * Copyright (c) 2005-2013 Werner Randelshofer, Switzerland. 5 | * Copyright (c) 2014-2015 Alan Snyder. 6 | * You may not use, copy or modify this file, except in compliance with the 7 | * accompanying license terms. 8 | */ 9 | 10 | package org.violetlib.aqua.fc; 11 | 12 | import javax.swing.*; 13 | import javax.swing.filechooser.FileView; 14 | import java.io.File; 15 | 16 | /** 17 | * A FileView for OS X. It supports the file chooser options for traversing packages and applications. The trick is 18 | * that JFileChooser calls isTraversable() on a file view without knowing about the traversal options. We cache the 19 | * options here. 20 | * 21 | * @author Werner Randelshofer 22 | * @version $Id$ 23 | */ 24 | public class AquaFileView extends FileView { 25 | private AquaFileSystemView fsv; 26 | private boolean isPackageTraversable; 27 | private boolean isApplicationTraversable; 28 | 29 | public AquaFileView(AquaFileSystemView fsv) { 30 | this.fsv = fsv; 31 | } 32 | 33 | public boolean isPackageTraversable() { 34 | return isPackageTraversable; 35 | } 36 | 37 | public void setPackageTraversable(boolean b) { 38 | isPackageTraversable = b; 39 | } 40 | 41 | public boolean isApplicationTraversable() { 42 | return isApplicationTraversable; 43 | } 44 | 45 | public void setApplicationTraversable(boolean b) { 46 | isApplicationTraversable = b; 47 | } 48 | 49 | @Override 50 | public String getName(File f) { 51 | return fsv.getSystemDisplayName(f); 52 | } 53 | 54 | @Override 55 | public String getDescription(File f) { 56 | // This method is not used by the Aqua file chooser UI. 57 | return ""; 58 | } 59 | 60 | @Override 61 | public String getTypeDescription(File f) { 62 | return fsv.getSystemTypeDescription(f); 63 | } 64 | 65 | @Override 66 | public Icon getIcon(File f) { 67 | return fsv.getSystemIcon(f); 68 | } 69 | 70 | @Override 71 | public Boolean isTraversable(File f) { 72 | return fsv.isTraversable(f, isPackageTraversable, isApplicationTraversable); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/org/violetlib/aqua/fc/ArrayUtil.java: -------------------------------------------------------------------------------- 1 | /* 2 | * @(#)ArrayUtil.java 3 | * 4 | * Copyright (c) 2003-2010 Werner Randelshofer, Switzerland 5 | * All rights reserved. 6 | * 7 | * You may not use, copy or modify this file, except in compliance with the 8 | * license agreement you entered into with Werner Randelshofer. 9 | * For details see accompanying license terms. 10 | */ 11 | 12 | package org.violetlib.aqua.fc; 13 | 14 | import java.util.ArrayList; 15 | 16 | /** 17 | * ArrayUtil. 18 | * 19 | * @author Werner Randelshofer 20 | * @version $Id$ 21 | */ 22 | public class ArrayUtil { 23 | 24 | /** Prevent instance creation. */ 25 | private ArrayUtil() { 26 | } 27 | 28 | public static ArrayList asList(int[] a) { 29 | ArrayList list = new ArrayList(a.length); 30 | for (int i=0; i < a.length; i++) { 31 | list.add(a[i]); 32 | } 33 | return list; 34 | } 35 | 36 | private final static char[] hexChars = { 37 | '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' 38 | }; 39 | 40 | public static int[] truncate(int[] a, int off, int len) { 41 | int[] b = new int[len]; 42 | System.arraycopy(a, off, b, 0, len); 43 | return b; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/org/violetlib/aqua/fc/BrowserCellRenderer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * @(#)BrowserCellRenderer.java 3 | * 4 | * Copyright (c) 2008-2013 Werner Randelshofer, Switzerland. 5 | * You may not use, copy or modify this file, except in compliance with the 6 | * accompanying license terms. 7 | */ 8 | 9 | package org.violetlib.aqua.fc; 10 | 11 | import java.awt.*; 12 | 13 | /** 14 | * Defines the requirements for an object that displays a tree node in a JBrowser. 15 | * 16 | * @author Werner Randelshofer 17 | * @version $Id$ 18 | */ 19 | public interface BrowserCellRenderer { 20 | 21 | /** 22 | * Sets the value of the current tree cell to {@code value}. 23 | * If {@code selected} is true, the cell will be drawn as if 24 | * selected. If {@code expanded} is true the node is currently 25 | * expanded and if {@code leaf} is true the node represents a 26 | * leaf and if {@code hasFocus} is true the node currently has 27 | * focus. {@code tree} is the {@code JTree} the receiver is being 28 | * configured for. Returns the {@code Component} that the renderer 29 | * uses to draw the value. 30 | * 31 | * @param browser target 32 | * @param value value to be rendered 33 | * @param selected whether the cell is selected 34 | * @param expanded whether the cell is expanded 35 | * @param leaf whether the cell is a leaf 36 | * @param row row index 37 | * @param hasFocus whether the cell has focus 38 | * @return the {@code Component} that the renderer uses to draw the value 39 | */ 40 | Component getBrowserCellRendererComponent(JBrowser browser, Object value, 41 | boolean selected, boolean expanded, 42 | boolean leaf, int row, boolean hasFocus); 43 | } 44 | -------------------------------------------------------------------------------- /src/org/violetlib/aqua/fc/BrowserPreviewRenderer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * @(#)BrowserPreviewRenderer.java 3 | * 4 | * Copyright (c) 2005-2013 Werner Randelshofer, Switzerland. 5 | * You may not use, copy or modify this file, except in compliance with the 6 | * accompanying license terms. 7 | */ 8 | 9 | package org.violetlib.aqua.fc; 10 | 11 | import javax.swing.tree.TreePath; 12 | import java.awt.*; 13 | 14 | /** 15 | * Identifies components that can be used to paint the preview column in a 16 | * JBrowser. Unlike other renderers, this one is not just used for a rubber stamp. 17 | * The renderer is added to the preview column of the JBrowser. 18 | *

19 | * For example, to use a JLabel as a BrowserPreviewRenderer, you 20 | * would write something like this: 21 | *

22 |  * class MyPreviewRenderer extends JLabel implements BrowserPreviewRenderer {
23 |  *     public MyPreviewRenderer() {
24 |  *         setOpaque(true);
25 |  *     }
26 |  *     public Component getPreviewRendererRendererComponent(
27 |  *         JBrowser browser,
28 |  *         TreePath[] paths
29 |  *         )
30 |  *     {
31 |  *         setText((paths.length == 1)
32 |  *            ? values[0].getLastPathComponent().toString()
33 |  *            : values.length+" items");
34 |  *         return this;
35 |  *     }
36 |  * }
37 |  * 
38 | * 39 | * @author Werner Randelshofer 40 | * @version $Id$ 41 | */ 42 | public interface BrowserPreviewRenderer { 43 | /** 44 | * Return a component that has been configured to display the specified 45 | * value. That component is then added to the preview column of the JBrowser. 46 | * 47 | * @param browser The JBrowser we're painting. 48 | * @param paths The paths returned by browser.getSelectionPaths(). This 49 | * is granted to be a non-null array containing at least one element. 50 | * @return The component. 51 | * 52 | */ 53 | Component getPreviewRendererComponent( 54 | JBrowser browser, 55 | TreePath[] paths 56 | ); 57 | } 58 | -------------------------------------------------------------------------------- /src/org/violetlib/aqua/fc/BrowserUI.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2005-2013 Werner Randelshofer, Switzerland. 3 | * Copyright (c) 2018 Alan Snyder 4 | * You may not use, copy or modify this file, except in compliance with the 5 | * accompanying license terms. 6 | */ 7 | 8 | package org.violetlib.aqua.fc; 9 | 10 | import javax.swing.plaf.ComponentUI; 11 | 12 | public class BrowserUI extends ComponentUI { 13 | } 14 | -------------------------------------------------------------------------------- /src/org/violetlib/aqua/fc/ColumnView.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2015 Alan Snyder. 3 | * All rights reserved. 4 | * 5 | * You may not use, copy or modify this file, except in compliance with the license agreement. For details see 6 | * accompanying license terms. 7 | */ 8 | 9 | package org.violetlib.aqua.fc; 10 | 11 | import javax.swing.*; 12 | import javax.swing.event.ChangeEvent; 13 | import javax.swing.event.ChangeListener; 14 | import javax.swing.tree.TreePath; 15 | import java.util.List; 16 | 17 | /** 18 | * The file chooser column view. 19 | */ 20 | public abstract class ColumnView extends JPanel implements FileChooserView { 21 | 22 | private ChangeListener changeListener; 23 | private ChangeEvent changeEvent = new ChangeEvent(this); 24 | private SelectListener selectListener; 25 | 26 | public static ColumnView create(JFileChooser fc) { 27 | return new ColumnViewImpl(fc); 28 | } 29 | 30 | @Override 31 | public final void addSelectionChangeListener(ChangeListener l) { 32 | changeListener = l; 33 | } 34 | 35 | @Override 36 | public final void addSelectListener(SelectListener l) { 37 | selectListener = l; 38 | } 39 | 40 | protected final void selectionChanged() { 41 | if (changeListener != null) { 42 | changeListener.stateChanged(changeEvent); 43 | } 44 | } 45 | 46 | protected final void select(TreePath path) { 47 | if (selectListener != null) { 48 | selectListener.select(path); 49 | } 50 | } 51 | 52 | @Override 53 | public void ensureSelectionIsVisible() { 54 | List paths = getSelection(); 55 | if (!paths.isEmpty()) { 56 | ensurePathIsVisible(paths.get(0)); 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/org/violetlib/aqua/fc/CompositeTransferable.java: -------------------------------------------------------------------------------- 1 | /* 2 | * @(#)CompositeTransferable.java 3 | * 4 | * Copyright (c) 2001-2013 Werner Randelshofer, Switzerland. 5 | * Copyright (c) 2015 Alan Snyder. 6 | * You may not use, copy or modify this file, except in compliance with the 7 | * accompanying license terms. 8 | */ 9 | 10 | package org.violetlib.aqua.fc; 11 | 12 | import java.awt.datatransfer.DataFlavor; 13 | import java.awt.datatransfer.Transferable; 14 | import java.awt.datatransfer.UnsupportedFlavorException; 15 | import java.io.IOException; 16 | import java.util.HashMap; 17 | import java.util.LinkedList; 18 | import java.util.Map; 19 | 20 | /** 21 | * CompositeTransferable. 22 | * 23 | * @author Werner Randelshofer 24 | * @version $Id$ 25 | */ 26 | public class CompositeTransferable implements java.awt.datatransfer.Transferable { 27 | private Map transferables = new HashMap<>(); 28 | private LinkedList flavors = new LinkedList<>(); 29 | 30 | /** Creates a new instance of CompositeTransferable */ 31 | public CompositeTransferable() { 32 | } 33 | 34 | public void add(Transferable t) { 35 | DataFlavor[] fs = t.getTransferDataFlavors(); 36 | for (DataFlavor f : fs) { 37 | if (!transferables.containsKey(f)) { 38 | flavors.add(f); 39 | } 40 | transferables.put(f, t); 41 | } 42 | } 43 | 44 | /** 45 | * Returns an object which represents the data to be transferred. The class 46 | * of the object returned is defined by the representation class of the flavor. 47 | * 48 | * @param flavor the requested flavor for the data 49 | * @see DataFlavor#getRepresentationClass 50 | * @exception IOException if the data is no longer available 51 | * in the requested flavor. 52 | * @exception UnsupportedFlavorException if the requested data flavor is 53 | * not supported. 54 | */ 55 | public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException { 56 | Transferable t = transferables.get(flavor); 57 | if (t == null) { 58 | throw new UnsupportedFlavorException(flavor); 59 | } 60 | return t.getTransferData(flavor); 61 | } 62 | 63 | /** 64 | * Returns an array of DataFlavor objects indicating the flavors the data 65 | * can be provided in. The array should be ordered according to preference 66 | * for providing the data (from most richly descriptive to least descriptive). 67 | * @return an array of data flavors in which this data can be transferred 68 | */ 69 | public DataFlavor[] getTransferDataFlavors() { 70 | return flavors.toArray(new DataFlavor[transferables.size()]); 71 | } 72 | 73 | /** 74 | * Returns whether or not the specified data flavor is supported for 75 | * this object. 76 | * @param flavor the requested flavor for the data 77 | * @return boolean indicating whether or not the data flavor is supported 78 | */ 79 | public boolean isDataFlavorSupported(DataFlavor flavor) { 80 | return transferables.containsKey(flavor); 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/org/violetlib/aqua/fc/FileChooserView.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2015 Alan Snyder. 3 | * All rights reserved. 4 | * 5 | * You may not use, copy or modify this file, except in compliance with the license agreement. For details see 6 | * accompanying license terms. 7 | */ 8 | 9 | package org.violetlib.aqua.fc; 10 | 11 | import javax.swing.event.ChangeListener; 12 | import javax.swing.tree.TreePath; 13 | import java.util.List; 14 | 15 | /** 16 | * The common methods of the file chooser views (list and browser). 17 | */ 18 | public interface FileChooserView { 19 | 20 | void setActive(boolean b); 21 | 22 | void setModel(SubtreeTreeModel m); 23 | 24 | void setFileRenderer(GenericCellRenderer r); 25 | 26 | void setMultipleSelection(boolean b); 27 | 28 | void setSelection(TreePath path); 29 | 30 | void setSelection(List paths); 31 | 32 | List getSelection(); 33 | 34 | void ensurePathIsVisible(TreePath path); 35 | 36 | void ensureSelectionIsVisible(); 37 | 38 | /** 39 | * Add a listener to be called when the selection changes. 40 | */ 41 | void addSelectionChangeListener(ChangeListener l); 42 | 43 | /** 44 | * Add a listener to be called when the user selects a file or directory in a way 45 | * that has an effect beyond the view. 46 | */ 47 | void addSelectListener(SelectListener l); 48 | 49 | interface SelectListener { 50 | void select(TreePath path); 51 | } 52 | 53 | /** 54 | * Update the view in response to a change in the file chooser configuration. 55 | */ 56 | void reconfigure(); 57 | 58 | boolean requestFocusInWindow(); 59 | } 60 | -------------------------------------------------------------------------------- /src/org/violetlib/aqua/fc/FileIconService.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 Alan Snyder. 3 | * All rights reserved. 4 | * 5 | * You may not use, copy or modify this file, except in compliance with the license agreement. For details see 6 | * accompanying license terms. 7 | */ 8 | 9 | package org.violetlib.aqua.fc; 10 | 11 | import java.io.File; 12 | import javax.swing.*; 13 | 14 | import org.jetbrains.annotations.NotNull; 15 | 16 | /** 17 | * Platform support for obtaining file icons for use in the file chooser. 18 | */ 19 | 20 | public interface FileIconService { 21 | 22 | // Icon quality levels 23 | 24 | int ICON_GENERIC = 0; // a generic icon for any file 25 | int ICON_TYPE = 10; // an icon for a specific file type 26 | int ICON_CUSTOM_LOW = 20; // a low-quality icon that may be custom for a specific file 27 | int ICON_CUSTOM = 30; // the best quality icon for a specific file 28 | 29 | boolean debugFlag = false; 30 | 31 | /** 32 | * Request an icon for a file. Icons are delivered to the specified handler on an unspecified thread. 33 | * This method may return before any icons are delivered. Icons may also be delivered on this thread before this 34 | * method returns. 35 | * Multiple icons may be delivered, in order of increasing quality and specificity. 36 | * No guarantee is made on the number of icons that will be delivered. In an unlikely failure situation, the number 37 | * may be zero. 38 | * 39 | * @param f The file whose icon is requested. The file need not exist, if a generic icon can be delivered or the 40 | * file type can be deduced from the file name. 41 | * @param size The requested icon size (in points). The delivered icons may be larger or smaller than this size. 42 | * @param scale The display scale of the display where the icon will be rendered. 43 | * @param handler The handler that will receive the icons. 44 | * @return an object that can be used to cancel the request. 45 | */ 46 | @NotNull Request requestIcon(@NotNull File f, int size, float scale, @NotNull Handler handler); 47 | 48 | interface Handler { 49 | /** 50 | * Deliver a requested icon. 51 | * @param icon The icon. 52 | * @param quality The quality level of the icon. 53 | */ 54 | void provideIcon(@NotNull ImageIcon icon, int quality); 55 | } 56 | 57 | interface Request { 58 | /** 59 | * Cancel the request, if possible. 60 | */ 61 | void cancel(); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/org/violetlib/aqua/fc/FileInfo.java: -------------------------------------------------------------------------------- 1 | /* 2 | * @(#)FileInfo.java 3 | * 4 | * Copyright (c) 2005-2013 Werner Randelshofer, Switzerland. 5 | * Copyright (c) 2019 Alan Snyder. 6 | * You may not use, copy or modify this file, except in compliance with the 7 | * accompanying license terms. 8 | */ 9 | 10 | package org.violetlib.aqua.fc; 11 | 12 | import java.io.File; 13 | import javax.swing.*; 14 | 15 | import org.jetbrains.annotations.NotNull; 16 | 17 | /** 18 | * Provides information about a File object. FileInfo uses a worker thread for 19 | * validating the information that it provides. The quality of the information 20 | * returned increases over time. 21 | */ 22 | public interface FileInfo { 23 | 24 | /** 25 | * Returns the unresolved file object. 26 | */ 27 | File getFile(); 28 | 29 | /** 30 | * Returns the resolved file object. 31 | */ 32 | File getResolvedFile(); 33 | 34 | /** 35 | * Lazyily returns the resolved file object. 36 | * Returns null, if the file object has not been resolved yet. 37 | */ 38 | File lazyGetResolvedFile(); 39 | 40 | /** 41 | * Returns true, if the file object is traversable. 42 | */ 43 | boolean isTraversable(); 44 | 45 | /** 46 | * Returns true, if the file object is hidden. 47 | */ 48 | boolean isHidden(); 49 | 50 | /** 51 | * Returns true, if the file object is acceptable, i.e. selectable in the JFileChooser. 52 | */ 53 | boolean isAcceptable(); 54 | 55 | /** 56 | * Returns the (color) label of the file. 57 | * Returns -1 if the label has not (yet) been determined. 58 | */ 59 | int getFileLabel(); 60 | 61 | /** 62 | * Returns the user name of the file. 63 | */ 64 | String getUserName(); 65 | 66 | /** 67 | * Returns the icon of the file. 68 | * Returns a proxy icon if the real icon has not yet been fetched from the file system. 69 | */ 70 | Icon getIcon(); 71 | 72 | /** 73 | * Returns the length of the file. 74 | * Returns -1 if the length has not (yet) been determined. 75 | */ 76 | long getFileLength(); 77 | 78 | /** 79 | * Return true if the file is an alias or symbolic link. 80 | */ 81 | boolean isAlias(); 82 | 83 | /** 84 | * Returns the kind of the file. 85 | */ 86 | @NotNull String getFileKind(); 87 | } 88 | -------------------------------------------------------------------------------- /src/org/violetlib/aqua/fc/FilePreviewView.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 Alan Snyder. 3 | * All rights reserved. 4 | * 5 | * You may not use, copy or modify this file, except in compliance with the license agreement. For details see 6 | * accompanying license terms. 7 | */ 8 | 9 | package org.violetlib.aqua.fc; 10 | 11 | import java.awt.*; 12 | import java.io.File; 13 | 14 | import org.jetbrains.annotations.NotNull; 15 | import org.jetbrains.annotations.Nullable; 16 | import org.violetlib.aqua.NativeOverlayView; 17 | 18 | /** 19 | * Provides access to a native quick look preview view. 20 | */ 21 | 22 | public class FilePreviewView { 23 | 24 | private long vptr; 25 | private @Nullable NativeOverlayView overlayView; 26 | 27 | public FilePreviewView() 28 | throws UnsupportedOperationException { 29 | vptr = nativeCreatePreviewView(); 30 | if (vptr == 0) { 31 | throw new UnsupportedOperationException("Unable to create file preview view"); 32 | } 33 | } 34 | 35 | public void track(@NotNull Component trackingComponent) { 36 | if (vptr != 0) { 37 | if (overlayView != null) { 38 | overlayView.dispose(); 39 | overlayView = null; 40 | } 41 | overlayView = new NativeOverlayView(trackingComponent, vptr); 42 | } 43 | } 44 | 45 | public void clear() { 46 | if (vptr != 0) { 47 | nativeConfigurePreview(vptr, null); 48 | } 49 | } 50 | 51 | public void configure(@NotNull File f) { 52 | if (vptr != 0) { 53 | nativeConfigurePreview(vptr, f.getAbsolutePath()); 54 | } 55 | } 56 | 57 | public void dispose() { 58 | if (vptr != 0) { 59 | if (overlayView != null) { 60 | overlayView.dispose(); 61 | overlayView = null; 62 | } 63 | nativeDisposePreviewView(vptr); 64 | vptr = 0; 65 | } 66 | } 67 | 68 | private static native long nativeCreatePreviewView(); 69 | private static native void nativeConfigurePreview(long vptr, @Nullable String path); 70 | private static native void nativeDisposePreviewView(long vptr); 71 | } 72 | -------------------------------------------------------------------------------- /src/org/violetlib/aqua/fc/FilenameDocument.java: -------------------------------------------------------------------------------- 1 | /* 2 | * @(#)FilenameDocument.java 3 | * 4 | * Copyright (c) 2010 Werner Randelshofer, Switzerland. 5 | * All rights reserved. 6 | * 7 | * You may not use, copy or modify this file, except in compliance with the 8 | * license agreement you entered into with Werner Randelshofer. 9 | * For details see accompanying license terms. 10 | */ 11 | 12 | package org.violetlib.aqua.fc; 13 | 14 | import javax.swing.text.AttributeSet; 15 | import javax.swing.text.BadLocationException; 16 | import javax.swing.text.PlainDocument; 17 | import java.util.HashSet; 18 | 19 | /** 20 | * A document model which silently converts forbidden filename characters into dashes. 21 | *

22 | * On Mac OS X, only the colon character is forbidden: {@code : }. 23 | * 24 | * @author Werner Randelshofer 25 | * @version $Id$ 26 | */ 27 | public class FilenameDocument extends PlainDocument { 28 | 29 | private HashSet forbidden; 30 | 31 | public FilenameDocument() { 32 | forbidden = new HashSet(); 33 | forbidden.add(':'); 34 | } 35 | 36 | @Override 37 | public void insertString(int offs, String str, AttributeSet a) 38 | throws BadLocationException { 39 | char[] chars = str.toCharArray(); 40 | for (int i = 0; i < chars.length; i++) { 41 | if (forbidden.contains(chars[i])) { 42 | chars[i] = '-'; 43 | } 44 | } 45 | 46 | super.insertString(offs, new String(chars), a); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/org/violetlib/aqua/fc/GenericCellRenderer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015-2018 Alan Snyder. 3 | * All rights reserved. 4 | * 5 | * You may not use, copy or modify this file, except in compliance with the license agreement. For details see 6 | * accompanying license terms. 7 | */ 8 | 9 | package org.violetlib.aqua.fc; 10 | 11 | import java.awt.*; 12 | import javax.swing.*; 13 | 14 | import org.jetbrains.annotations.NotNull; 15 | import org.jetbrains.annotations.Nullable; 16 | import org.violetlib.aqua.AquaAppearance; 17 | import org.violetlib.aqua.ContainerContextualColors; 18 | 19 | /** 20 | * A cell renderer that does not care what kind of container it is used in. 21 | */ 22 | public interface GenericCellRenderer { 23 | Component getCellRendererComponent(JComponent container, 24 | @NotNull AquaAppearance appearance, 25 | @NotNull ContainerContextualColors colors, 26 | Object value, 27 | boolean isSelected, 28 | boolean cellHasFocus); 29 | } 30 | -------------------------------------------------------------------------------- /src/org/violetlib/aqua/fc/IteratorEnumeration.java: -------------------------------------------------------------------------------- 1 | /* 2 | * @(#)IteratorEnumeration.java 3 | * 4 | * Copyright (c) 2004-2013 Werner Randelshofer, Switzerland. 5 | * All rights reserved. 6 | * 7 | * The copyright of this software is owned by Werner Randelshofer. 8 | * You may not use, copy or modify this software, except in 9 | * accordance with the license agreement you entered into with 10 | * Werner Randelshofer. For details see accompanying license terms. 11 | */ 12 | 13 | package org.violetlib.aqua.fc; 14 | 15 | import java.util.Enumeration; 16 | import java.util.Iterator; 17 | 18 | /** 19 | * This Enumeration is a wrapper over an Iterator. 20 | * 21 | * @author Werner Randelshofer 22 | * @version $Id$ 23 | */ 24 | public class IteratorEnumeration implements Enumeration { 25 | private Iterator iterator; 26 | 27 | public IteratorEnumeration(Iterator iterator) { 28 | this.iterator = iterator; 29 | } 30 | 31 | public boolean hasMoreElements() { 32 | return iterator.hasNext(); 33 | } 34 | 35 | public Object nextElement() { 36 | return iterator.next(); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/org/violetlib/aqua/fc/ListView.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2015 Alan Snyder. 3 | * All rights reserved. 4 | * 5 | * You may not use, copy or modify this file, except in compliance with the license agreement. For details see 6 | * accompanying license terms. 7 | */ 8 | 9 | package org.violetlib.aqua.fc; 10 | 11 | import javax.swing.*; 12 | import javax.swing.event.ChangeEvent; 13 | import javax.swing.event.ChangeListener; 14 | import javax.swing.tree.TreePath; 15 | import java.util.List; 16 | 17 | /** 18 | * The file chooser list view. 19 | */ 20 | public abstract class ListView extends JPanel implements FileChooserView { 21 | 22 | protected SubtreeTreeModel model; 23 | 24 | private ChangeListener changeListener; 25 | private ChangeEvent changeEvent = new ChangeEvent(this); 26 | private SelectListener selectListener; 27 | 28 | public static ListView create(JFileChooser fc) { 29 | return new ListViewImpl(fc); 30 | } 31 | 32 | @Override 33 | public void setModel(SubtreeTreeModel m) { 34 | if (m != model) { 35 | model = m; 36 | updateForNewModel(); 37 | } 38 | } 39 | 40 | @Override 41 | public void addSelectionChangeListener(ChangeListener l) { 42 | changeListener = l; 43 | } 44 | 45 | @Override 46 | public void addSelectListener(SelectListener l) { 47 | selectListener = l; 48 | } 49 | 50 | protected void selectionChanged() { 51 | if (changeListener != null) { 52 | changeListener.stateChanged(changeEvent); 53 | } 54 | } 55 | 56 | protected abstract void updateForNewModel(); 57 | 58 | protected final void select(TreePath path) { 59 | if (selectListener != null) { 60 | selectListener.select(path); 61 | } 62 | } 63 | 64 | @Override 65 | public void ensureSelectionIsVisible() { 66 | List paths = getSelection(); 67 | if (!paths.isEmpty()) { 68 | ensurePathIsVisible(paths.get(0)); 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/org/violetlib/aqua/fc/OSXFileSystemView.java: -------------------------------------------------------------------------------- 1 | /* 2 | * @(#)OSXFileSystemView.java 3 | * 4 | * Copyright (c) 2009-2013 Werner Randelshofer, Switzerland. 5 | * You may not use, copy or modify this file, except in compliance with the 6 | * accompanying license terms. 7 | */ 8 | 9 | package org.violetlib.aqua.fc; 10 | 11 | import java.io.File; 12 | import java.util.Arrays; 13 | 14 | /** 15 | * A file system view for the OS X file system. This view was created for 10.7 but has been updated for later releases. 16 | * 17 | * @author Werner Randelshofer 18 | * @version $Id$ 19 | */ 20 | public class OSXFileSystemView extends BasicOSXFileSystemView { 21 | 22 | public OSXFileSystemView() { 23 | 24 | String[] names = { 25 | "AppleShare PDS", 26 | "automount", 27 | "bin", 28 | "Cleanup At Startup", 29 | "cores", 30 | "Desktop DB", 31 | "Desktop DF", 32 | "dev", 33 | "etc", 34 | "home", 35 | "mach", 36 | "mach_kernel", 37 | "mach_kernel.ctfsys", 38 | "mach.sym", 39 | "net", 40 | "Network", 41 | "opt", 42 | "private", 43 | "sbin", 44 | "Temporary Items", 45 | "TheVolumeSettingsFolder", 46 | "TheFindByContentFolder", 47 | "tmp", 48 | "Trash", 49 | "usr", 50 | "var", 51 | "Volumes", 52 | "\u0003\u0002\u0001Move&Rename", 53 | }; 54 | 55 | hiddenTopLevelNames.addAll(Arrays.asList(names)); 56 | 57 | names = new String[] { 58 | "$RECYCLE.BIN", 59 | "Thumbs.db", 60 | "desktop.ini", 61 | }; 62 | 63 | hiddenDirectoryNames.addAll(Arrays.asList(names)); 64 | 65 | File[] files={ 66 | new File(System.getProperty("user.home"), "Library") 67 | }; 68 | hiddenFiles.addAll(Arrays.asList(files)); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/org/violetlib/aqua/fc/OverlayContainer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 Alan Snyder. 3 | * All rights reserved. 4 | * 5 | * You may not use, copy or modify this file, except in compliance with the license agreement. For details see 6 | * accompanying license terms. 7 | */ 8 | 9 | package org.violetlib.aqua.fc; 10 | 11 | import java.awt.*; 12 | import javax.swing.*; 13 | 14 | public class OverlayContainer extends JComponent { 15 | 16 | public OverlayContainer() { 17 | setLayout(new MyLayoutManager()); 18 | setOpaque(false); 19 | } 20 | 21 | @Override 22 | public boolean isOptimizedDrawingEnabled() { 23 | return false; 24 | } 25 | 26 | private class MyLayoutManager implements LayoutManager { 27 | @Override 28 | public void addLayoutComponent(String name, Component comp) { 29 | } 30 | 31 | @Override 32 | public void removeLayoutComponent(Component comp) { 33 | } 34 | 35 | @Override 36 | public Dimension preferredLayoutSize(Container parent) { 37 | return null; 38 | } 39 | 40 | @Override 41 | public Dimension minimumLayoutSize(Container parent) { 42 | return null; 43 | } 44 | 45 | @Override 46 | public void layoutContainer(Container parent) { 47 | int width = parent.getWidth(); 48 | int height = parent.getHeight(); 49 | int count = parent.getComponentCount(); 50 | for (int i = 0; i < count; i++) { 51 | Component c = parent.getComponent(i); 52 | c.setBounds(0, 0, width, height); 53 | } 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/org/violetlib/aqua/fc/SequentialDispatcher.java: -------------------------------------------------------------------------------- 1 | /* 2 | * @(#)SequentialDispatcher.java 1.0 2002-05-18 3 | * 4 | * Copyright (c) 2001-2013 Werner Randelshofer, Switzerland. 5 | * All rights reserved. 6 | * 7 | * This software is the confidential and proprietary information of 8 | * Werner Randelshofer. ("Confidential Information"). You shall not 9 | * disclose such Confidential Information and shall use it only in 10 | * accordance with the terms of the license agreement you entered into 11 | * with Werner Randelshofer. 12 | */ 13 | 14 | package org.violetlib.aqua.fc; 15 | 16 | /** 17 | * Processes Runnable objects sequentially on a processor thread. 18 | * The order in which the runnable objects are processed is 19 | * the same in which they were added to the dispatcher. 20 | *

21 | * Design pattern used: Acceptor 22 | * Role in design pattern: EventCollector and EventProcessor 23 | * 24 | * @author Werner Randelshofef 25 | * @version 1.0 2002-05-18 Created 26 | */ 27 | public class SequentialDispatcher extends EventLoop { 28 | /** 29 | * Creates new SequentialDispatcher which processes Runnable objects 30 | * at java.lang.Thread.NORM_PRIORITY. 31 | */ 32 | public SequentialDispatcher() { 33 | } 34 | /** 35 | * Creates a new SequentialDispatcher which processes Runnable Objects 36 | * at the desired thread priority. 37 | * 38 | * @param priority The Thread priority of the event processor. 39 | */ 40 | public SequentialDispatcher(int priority) { 41 | super(priority); 42 | } 43 | 44 | /** 45 | * This method processes an event on the event processor thread. 46 | * 47 | * @param event An event from the queue. 48 | */ 49 | protected void processEvent(Object event) { 50 | Runnable r = (Runnable) event; 51 | r.run(); 52 | } 53 | 54 | /** 55 | * Queues the Runnable object for later execution on the 56 | * processor thread. 57 | */ 58 | public void dispatch(Runnable r) { 59 | collectEvent(r); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/org/violetlib/aqua/fc/SubtreeFileChooserUI.java: -------------------------------------------------------------------------------- 1 | /* 2 | * @(#)SubtreeFileChooserUI.java 1.0 2010-08-20 3 | * 4 | * Copyright (c) 2010 Werner Randelshofer, Switzerland. 5 | * All rights reserved. 6 | * 7 | * You may not use, copy or modify this file, except in compliance with the 8 | * license agreement you entered into with Werner Randelshofer. 9 | * For details see accompanying license terms. 10 | */ 11 | 12 | package org.violetlib.aqua.fc; 13 | 14 | import java.io.File; 15 | 16 | /** 17 | * SubtreeFileChooserUI for filechoosers which can change their filesystem root or select a directory within that 18 | * subtree. 19 | * 20 | * @author Werner Randelshofer 21 | * @version 1.0 2010-08-20 Created. 22 | */ 23 | public interface SubtreeFileChooserUI { 24 | /** Sets the root directory of the subtree. */ 25 | void setRootDirectory(File file); 26 | 27 | /** 28 | * Set the current directory. If possible, the subtree root is not changed. Otherwise, the specified directory 29 | * becomes the new subtree root. 30 | */ 31 | void selectDirectory(File file); 32 | } 33 | -------------------------------------------------------------------------------- /src/org/violetlib/aqua/fc/ViewModeControl.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014 Alan Snyder. 3 | * All rights reserved. 4 | * 5 | * You may not use, copy or modify this file, except in compliance with the license agreement. For details see 6 | * accompanying license terms. 7 | */ 8 | 9 | package org.violetlib.aqua.fc; 10 | 11 | import javax.swing.*; 12 | import javax.swing.event.ChangeEvent; 13 | import javax.swing.event.ChangeListener; 14 | 15 | /** 16 | * A control that allows the user to select a view mode for the file chooser. 17 | */ 18 | public abstract class ViewModeControl extends JPanel { 19 | 20 | public final static int ICON_VIEW = 0; 21 | public final static int LIST_VIEW = 1; 22 | public final static int COLUMN_VIEW = 2; 23 | public final static int FLOW_VIEW = 3; 24 | 25 | private ChangeListener changeListener; 26 | private ChangeEvent changeEvent = new ChangeEvent(this); 27 | 28 | public static ViewModeControl create() { 29 | return new ViewModeControlImpl(); 30 | } 31 | 32 | public abstract void setSelectedViewMode(int mode); 33 | 34 | public abstract int getSelectedViewMode(); 35 | 36 | public void addChangeListener(ChangeListener l) { 37 | changeListener = l; 38 | } 39 | 40 | protected void selectedViewModeChanged() { 41 | if (changeListener != null) { 42 | changeListener.stateChanged(changeEvent); 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/org/violetlib/treetable/DefaultTreeTableCellEditor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This program is free software: you can redistribute it and/or modify 3 | * it under the terms of the GNU Lesser General Public License as published 4 | * by the Free Software Foundation, either version 3 of the License, or 5 | * (at your option) any later version. 6 | * 7 | * This program is distributed in the hope that it will be useful, 8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 | * GNU Lesser General Public License for more details. 11 | * 12 | * You should have received a copy of the GNU Lesser General Public License 13 | * along with this program. If not, see . 14 | */ 15 | package org.violetlib.treetable; 16 | 17 | import java.awt.Component; 18 | 19 | import javax.swing.DefaultCellEditor; 20 | import javax.swing.JCheckBox; 21 | import javax.swing.JComboBox; 22 | import javax.swing.JTable; 23 | import javax.swing.JTextField; 24 | import javax.swing.JTree; 25 | 26 | public class DefaultTreeTableCellEditor extends DefaultCellEditor 27 | implements TreeTableCellEditor { 28 | 29 | public DefaultTreeTableCellEditor(JCheckBox checkBox) { 30 | super(checkBox); 31 | // TODO Auto-generated constructor stub 32 | } 33 | 34 | public DefaultTreeTableCellEditor(JComboBox comboBox) { 35 | super(comboBox); 36 | // TODO Auto-generated constructor stub 37 | } 38 | 39 | public DefaultTreeTableCellEditor(JTextField textField) { 40 | super(textField); 41 | // TODO Auto-generated constructor stub 42 | } 43 | 44 | @Override 45 | public Component getTreeTableCellEditorComponent(TreeTable treeTable, 46 | Object value, boolean selected, int row, int column) { 47 | treeTable.getUI().configureCellEditor(this, 48 | treeTable, value, selected, row, column); 49 | return getComponent(); 50 | } 51 | 52 | @Override 53 | public Component getTreeTableCellEditorComponent(TreeTable treeTable, 54 | Object value, boolean selected, int row, int column, 55 | boolean expanded, boolean leaf) { 56 | treeTable.getUI().configureCellEditor(this, 57 | treeTable, value, selected, row, column, expanded, leaf); 58 | return getComponent(); 59 | } 60 | 61 | @Override 62 | public /* final */ Component getTableCellEditorComponent(JTable table, 63 | Object value, boolean selected, int row, int column) { 64 | return super.getTableCellEditorComponent( 65 | table, value, selected, row, column); 66 | } 67 | 68 | @Override 69 | public /* final */ Component getTreeCellEditorComponent(JTree tree, 70 | Object value, boolean selected, boolean expanded, boolean leaf, int row) { 71 | return super.getTreeCellEditorComponent( 72 | tree, value, selected, expanded, leaf, row); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/org/violetlib/treetable/DefaultTreeTableNode.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This program is free software: you can redistribute it and/or modify 3 | * it under the terms of the GNU Lesser General Public License as published 4 | * by the Free Software Foundation, either version 3 of the License, or 5 | * (at your option) any later version. 6 | * 7 | * This program is distributed in the hope that it will be useful, 8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 | * GNU Lesser General Public License for more details. 11 | * 12 | * You should have received a copy of the GNU Lesser General Public License 13 | * along with this program. If not, see . 14 | */ 15 | package org.violetlib.treetable; 16 | 17 | import javax.swing.tree.DefaultMutableTreeNode; 18 | 19 | public class DefaultTreeTableNode extends DefaultMutableTreeNode implements MutableTreeTableNode { 20 | 21 | public DefaultTreeTableNode() { 22 | this(""); 23 | } 24 | 25 | public DefaultTreeTableNode(Object ... rowData) { 26 | if (rowData == null) 27 | throw new NullPointerException(); 28 | this.rowData = rowData; 29 | } 30 | 31 | private Object[] rowData; 32 | 33 | @Override 34 | public Object getValueAt(int column) { 35 | return rowData[column]; 36 | } 37 | 38 | @Override 39 | public void setValueAt(Object value, int column) { 40 | rowData[column] = value; 41 | } 42 | 43 | @Override 44 | public int getColumnCount() { 45 | return rowData.length; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/org/violetlib/treetable/IconMap.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This program is free software: you can redistribute it and/or modify 3 | * it under the terms of the GNU Lesser General Public License as published 4 | * by the Free Software Foundation, either version 3 of the License, or 5 | * (at your option) any later version. 6 | * 7 | * This program is distributed in the hope that it will be useful, 8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 | * GNU Lesser General Public License for more details. 11 | * 12 | * You should have received a copy of the GNU Lesser General Public License 13 | * along with this program. If not, see . 14 | */ 15 | package org.violetlib.treetable; 16 | 17 | import javax.swing.Icon; 18 | 19 | public interface IconMap { 20 | Icon getIcon(TreeTable treeTable, Object node, boolean expanded, boolean leaf); 21 | } 22 | -------------------------------------------------------------------------------- /src/org/violetlib/treetable/MutableTreeTableNode.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This program is free software: you can redistribute it and/or modify 3 | * it under the terms of the GNU Lesser General Public License as published 4 | * by the Free Software Foundation, either version 3 of the License, or 5 | * (at your option) any later version. 6 | * 7 | * This program is distributed in the hope that it will be useful, 8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 | * GNU Lesser General Public License for more details. 11 | * 12 | * You should have received a copy of the GNU Lesser General Public License 13 | * along with this program. If not, see . 14 | */ 15 | package org.violetlib.treetable; 16 | 17 | import javax.swing.tree.MutableTreeNode; 18 | 19 | public interface MutableTreeTableNode extends TreeTableNode, MutableTreeNode { 20 | void setValueAt(Object value, int column); 21 | } 22 | -------------------------------------------------------------------------------- /src/org/violetlib/treetable/ToolTipMap.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This program is free software: you can redistribute it and/or modify 3 | * it under the terms of the GNU Lesser General Public License as published 4 | * by the Free Software Foundation, either version 3 of the License, or 5 | * (at your option) any later version. 6 | * 7 | * This program is distributed in the hope that it will be useful, 8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 | * GNU Lesser General Public License for more details. 11 | * 12 | * You should have received a copy of the GNU Lesser General Public License 13 | * along with this program. If not, see . 14 | */ 15 | package org.violetlib.treetable; 16 | 17 | import java.awt.event.MouseEvent; 18 | 19 | import javax.swing.JComponent; 20 | 21 | public interface ToolTipMap { 22 | String getToolTipText(C c, MouseEvent e); 23 | } 24 | -------------------------------------------------------------------------------- /src/org/violetlib/treetable/TreeColumnModel.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This program is free software: you can redistribute it and/or modify 3 | * it under the terms of the GNU Lesser General Public License as published 4 | * by the Free Software Foundation, either version 3 of the License, or 5 | * (at your option) any later version. 6 | * 7 | * This program is distributed in the hope that it will be useful, 8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 | * GNU Lesser General Public License for more details. 11 | * 12 | * You should have received a copy of the GNU Lesser General Public License 13 | * along with this program. If not, see . 14 | */ 15 | package org.violetlib.treetable; 16 | 17 | import org.violetlib.treetable.event.TreeColumnModelListener; 18 | 19 | public interface TreeColumnModel { 20 | 21 | String getColumnName(int column); 22 | 23 | Class getColumnClass(int column); 24 | 25 | int getColumnCount(); 26 | 27 | Object getValueAt(Object node, int column); 28 | 29 | void setValueAt(Object value, Object node, int column); 30 | 31 | boolean isCellEditable(Object node, int column); 32 | 33 | int getHierarchicalColumn(); 34 | 35 | void addTreeColumnModelListener(TreeColumnModelListener l); 36 | 37 | void removeTreeColumnModelListener(TreeColumnModelListener l); 38 | } 39 | -------------------------------------------------------------------------------- /src/org/violetlib/treetable/TreeTableCellEditor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This program is free software: you can redistribute it and/or modify 3 | * it under the terms of the GNU Lesser General Public License as published 4 | * by the Free Software Foundation, either version 3 of the License, or 5 | * (at your option) any later version. 6 | * 7 | * This program is distributed in the hope that it will be useful, 8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 | * GNU Lesser General Public License for more details. 11 | * 12 | * You should have received a copy of the GNU Lesser General Public License 13 | * along with this program. If not, see . 14 | */ 15 | package org.violetlib.treetable; 16 | 17 | import java.awt.Component; 18 | 19 | import javax.swing.CellEditor; 20 | 21 | public interface TreeTableCellEditor extends CellEditor { 22 | 23 | Component getTreeTableCellEditorComponent(TreeTable treeTable, 24 | Object value, boolean isSelected, int row, int column); 25 | 26 | Component getTreeTableCellEditorComponent(TreeTable treeTable, 27 | Object value, boolean isSelected, int row, int column, 28 | boolean expanded, boolean leaf); 29 | } 30 | -------------------------------------------------------------------------------- /src/org/violetlib/treetable/TreeTableCellRenderer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This program is free software: you can redistribute it and/or modify 3 | * it under the terms of the GNU Lesser General Public License as published 4 | * by the Free Software Foundation, either version 3 of the License, or 5 | * (at your option) any later version. 6 | * 7 | * This program is distributed in the hope that it will be useful, 8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 | * GNU Lesser General Public License for more details. 11 | * 12 | * You should have received a copy of the GNU Lesser General Public License 13 | * along with this program. If not, see . 14 | */ 15 | package org.violetlib.treetable; 16 | 17 | import java.awt.Component; 18 | 19 | public interface TreeTableCellRenderer { 20 | 21 | Component getTreeTableCellRendererComponent(TreeTable treeTable, 22 | Object value, boolean selected, boolean hasFocus, 23 | int row, int column); 24 | 25 | Component getTreeTableCellRendererComponent(TreeTable treeTable, 26 | Object value, boolean selected, boolean hasFocus, 27 | int row, int column, boolean expanded, boolean leaf); 28 | } 29 | -------------------------------------------------------------------------------- /src/org/violetlib/treetable/TreeTableModel.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This program is free software: you can redistribute it and/or modify 3 | * it under the terms of the GNU Lesser General Public License as published 4 | * by the Free Software Foundation, either version 3 of the License, or 5 | * (at your option) any later version. 6 | * 7 | * This program is distributed in the hope that it will be useful, 8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 | * GNU Lesser General Public License for more details. 11 | * 12 | * You should have received a copy of the GNU Lesser General Public License 13 | * along with this program. If not, see . 14 | */ 15 | package org.violetlib.treetable; 16 | 17 | import javax.swing.table.TableModel; 18 | import javax.swing.tree.TreeModel; 19 | 20 | public interface TreeTableModel extends TreeModel, TableModel { 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/org/violetlib/treetable/TreeTableNode.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This program is free software: you can redistribute it and/or modify 3 | * it under the terms of the GNU Lesser General Public License as published 4 | * by the Free Software Foundation, either version 3 of the License, or 5 | * (at your option) any later version. 6 | * 7 | * This program is distributed in the hope that it will be useful, 8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 | * GNU Lesser General Public License for more details. 11 | * 12 | * You should have received a copy of the GNU Lesser General Public License 13 | * along with this program. If not, see . 14 | */ 15 | package org.violetlib.treetable; 16 | 17 | import javax.swing.tree.TreeNode; 18 | 19 | public interface TreeTableNode extends TreeNode { 20 | 21 | Object getValueAt(int column); 22 | 23 | int getColumnCount(); 24 | } 25 | -------------------------------------------------------------------------------- /src/org/violetlib/treetable/TreeTableSorter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This program is free software: you can redistribute it and/or modify 3 | * it under the terms of the GNU Lesser General Public License as published 4 | * by the Free Software Foundation, either version 3 of the License, or 5 | * (at your option) any later version. 6 | * 7 | * This program is distributed in the hope that it will be useful, 8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 | * GNU Lesser General Public License for more details. 11 | * 12 | * You should have received a copy of the GNU Lesser General Public License 13 | * along with this program. If not, see . 14 | */ 15 | package org.violetlib.treetable; 16 | 17 | import java.util.List; 18 | 19 | import javax.swing.RowSorter; 20 | import javax.swing.SortOrder; 21 | import javax.swing.RowSorter.SortKey; 22 | import javax.swing.tree.TreeModel; 23 | import javax.swing.tree.TreePath; 24 | 25 | import org.violetlib.treetable.event.TreeTableSorterListener; 26 | 27 | public interface TreeTableSorter { 28 | 29 | List getSortKeys(); 30 | 31 | void setSortKeys(List keys); 32 | 33 | void toggleSortOrder(int column); 34 | 35 | /** 36 | * Retrieves the RowSorter for the specified path, 37 | * creates it if necessary. 38 | * 39 | * @see #getRowSorter(Object) 40 | */ 41 | RowSorter getRowSorter(TreePath path); 42 | 43 | /** 44 | * Differs from the TreePath variety as it won't 45 | * (lacks the necessary information) create 46 | * the row sorter if it doesn't exist. 47 | * 48 | * @see #getRowSorter(TreePath) 49 | */ 50 | RowSorter getRowSorter(Object node); 51 | 52 | void addTreeTableSorterListener(TreeTableSorterListener l); 53 | 54 | void removeTreeTableSorterListener(TreeTableSorterListener l); 55 | 56 | void setVisible(TreePath path, List subPaths, boolean visible); 57 | 58 | void structureChanged(TreePath path, boolean newRoot); 59 | 60 | void nodesRemoved(TreePath path, Object[] childNodes); 61 | 62 | interface SortCycle { 63 | 64 | void setSortCycle(List cycle); 65 | 66 | List getSortCycle(); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/org/violetlib/treetable/event/TreeColumnModelEvent.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This program is free software: you can redistribute it and/or modify 3 | * it under the terms of the GNU Lesser General Public License as published 4 | * by the Free Software Foundation, either version 3 of the License, or 5 | * (at your option) any later version. 6 | * 7 | * This program is distributed in the hope that it will be useful, 8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 | * GNU Lesser General Public License for more details. 11 | * 12 | * You should have received a copy of the GNU Lesser General Public License 13 | * along with this program. If not, see . 14 | */ 15 | package org.violetlib.treetable.event; 16 | 17 | import java.util.EventObject; 18 | 19 | import javax.swing.event.TableModelEvent; 20 | import javax.swing.tree.TreePath; 21 | 22 | import org.violetlib.treetable.TreeColumnModel; 23 | 24 | public class TreeColumnModelEvent extends EventObject { 25 | 26 | public static final int ALL_COLUMNS = TableModelEvent.ALL_COLUMNS; 27 | 28 | public TreeColumnModelEvent(TreeColumnModel source, TreePath path, int column) { 29 | super(source); 30 | this.path = path; 31 | this.column = column; 32 | } 33 | 34 | private TreePath path; 35 | 36 | private int column; 37 | 38 | public TreePath getTreePath() { 39 | return path; 40 | } 41 | 42 | public int getColumn() { 43 | return column; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/org/violetlib/treetable/event/TreeColumnModelListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This program is free software: you can redistribute it and/or modify 3 | * it under the terms of the GNU Lesser General Public License as published 4 | * by the Free Software Foundation, either version 3 of the License, or 5 | * (at your option) any later version. 6 | * 7 | * This program is distributed in the hope that it will be useful, 8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 | * GNU Lesser General Public License for more details. 11 | * 12 | * You should have received a copy of the GNU Lesser General Public License 13 | * along with this program. If not, see . 14 | */ 15 | package org.violetlib.treetable.event; 16 | 17 | import java.util.EventListener; 18 | 19 | public interface TreeColumnModelListener extends EventListener { 20 | 21 | void treeColumnChanged(TreeColumnModelEvent e); 22 | } 23 | -------------------------------------------------------------------------------- /src/org/violetlib/treetable/event/TreeTableMouseListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This program is free software: you can redistribute it and/or modify 3 | * it under the terms of the GNU Lesser General Public License as published 4 | * by the Free Software Foundation, either version 3 of the License, or 5 | * (at your option) any later version. 6 | * 7 | * This program is distributed in the hope that it will be useful, 8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 | * GNU Lesser General Public License for more details. 11 | * 12 | * You should have received a copy of the GNU Lesser General Public License 13 | * along with this program. If not, see . 14 | */ 15 | package org.violetlib.treetable.event; 16 | 17 | import java.util.EventListener; 18 | 19 | public interface TreeTableMouseListener extends EventListener { 20 | 21 | void mouseClicked(TreeTableMouseEvent e); 22 | 23 | void mousePressed(TreeTableMouseEvent e); 24 | 25 | void mouseReleased(TreeTableMouseEvent e); 26 | } 27 | -------------------------------------------------------------------------------- /src/org/violetlib/treetable/event/TreeTableMouseMotionListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This program is free software: you can redistribute it and/or modify 3 | * it under the terms of the GNU Lesser General Public License as published 4 | * by the Free Software Foundation, either version 3 of the License, or 5 | * (at your option) any later version. 6 | * 7 | * This program is distributed in the hope that it will be useful, 8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 | * GNU Lesser General Public License for more details. 11 | * 12 | * You should have received a copy of the GNU Lesser General Public License 13 | * along with this program. If not, see . 14 | */ 15 | package org.violetlib.treetable.event; 16 | 17 | import java.util.EventListener; 18 | 19 | public interface TreeTableMouseMotionListener extends EventListener { 20 | 21 | void mouseMoved(TreeTableMouseEvent e); 22 | 23 | void mouseDragged(TreeTableMouseEvent e); 24 | } 25 | -------------------------------------------------------------------------------- /src/org/violetlib/treetable/event/TreeTableSorterEvent.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This program is free software: you can redistribute it and/or modify 3 | * it under the terms of the GNU Lesser General Public License as published 4 | * by the Free Software Foundation, either version 3 of the License, or 5 | * (at your option) any later version. 6 | * 7 | * This program is distributed in the hope that it will be useful, 8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 | * GNU Lesser General Public License for more details. 11 | * 12 | * You should have received a copy of the GNU Lesser General Public License 13 | * along with this program. If not, see . 14 | */ 15 | package org.violetlib.treetable.event; 16 | 17 | import java.util.EventObject; 18 | import javax.swing.tree.TreePath; 19 | import org.violetlib.treetable.TreeTableSorter; 20 | 21 | public class TreeTableSorterEvent extends EventObject { 22 | 23 | public enum Type { 24 | SORT_ORDER_CHANGED, SORTED, NODE_SORTED 25 | } 26 | 27 | public TreeTableSorterEvent(TreeTableSorter source) { 28 | super(source); 29 | type = Type.SORT_ORDER_CHANGED; 30 | } 31 | 32 | public TreeTableSorterEvent(TreeTableSorter source, TreePath path) { 33 | super(source); 34 | type = path == null ? Type.SORTED : Type.NODE_SORTED; 35 | this.path = path; 36 | } 37 | 38 | private Type type; 39 | 40 | private TreePath path; 41 | 42 | public Type getType() { 43 | return type; 44 | } 45 | 46 | public TreePath getTreePath() { 47 | return path; 48 | } 49 | 50 | public TreeTableSorter getSource() { 51 | return (TreeTableSorter)super.getSource(); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/org/violetlib/treetable/event/TreeTableSorterListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This program is free software: you can redistribute it and/or modify 3 | * it under the terms of the GNU Lesser General Public License as published 4 | * by the Free Software Foundation, either version 3 of the License, or 5 | * (at your option) any later version. 6 | * 7 | * This program is distributed in the hope that it will be useful, 8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 | * GNU Lesser General Public License for more details. 11 | * 12 | * You should have received a copy of the GNU Lesser General Public License 13 | * along with this program. If not, see . 14 | */ 15 | package org.violetlib.treetable.event; 16 | 17 | import java.util.EventListener; 18 | 19 | public interface TreeTableSorterListener extends EventListener { 20 | 21 | void sorterChanged(TreeTableSorterEvent e); 22 | } 23 | -------------------------------------------------------------------------------- /src/org/violetlib/treetable/ui/TreeTableUI.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This program is free software: you can redistribute it and/or modify 3 | * it under the terms of the GNU Lesser General Public License as published 4 | * by the Free Software Foundation, either version 3 of the License, or 5 | * (at your option) any later version. 6 | * 7 | * This program is distributed in the hope that it will be useful, 8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 | * GNU Lesser General Public License for more details. 11 | * 12 | * You should have received a copy of the GNU Lesser General Public License 13 | * along with this program. If not, see . 14 | */ 15 | package org.violetlib.treetable.ui; 16 | 17 | import java.awt.Rectangle; 18 | 19 | import javax.swing.plaf.ComponentUI; 20 | import javax.swing.tree.TreePath; 21 | 22 | import org.violetlib.treetable.TreeTable; 23 | import org.violetlib.treetable.DefaultTreeTableCellEditor; 24 | import org.violetlib.treetable.DefaultTreeTableCellRenderer; 25 | import org.violetlib.treetable.TreeTableCellEditor; 26 | import org.violetlib.treetable.TreeTableCellRenderer; 27 | 28 | public abstract class TreeTableUI extends ComponentUI { 29 | 30 | public abstract TreeInterface getTreeInterface(TreeTable treeTable); 31 | 32 | public abstract TableInterface getTableInterface(TreeTable treeTable); 33 | 34 | public abstract void configureCellRenderer( 35 | DefaultTreeTableCellRenderer renderer, TreeTable treeTable, 36 | Object value, boolean selected, boolean hasFocus, 37 | int row, int column); 38 | 39 | public abstract void configureCellRenderer( 40 | DefaultTreeTableCellRenderer renderer, TreeTable treeTable, 41 | Object value, boolean selected, boolean hasFocus, 42 | int row, int column, boolean expanded, boolean leaf); 43 | 44 | public abstract void configureCellEditor(DefaultTreeTableCellEditor editor, 45 | TreeTable treeTable, Object value, boolean selected, int row, int column); 46 | 47 | public abstract void configureCellEditor(DefaultTreeTableCellEditor editor, 48 | TreeTable treeTable, Object value, boolean selected, 49 | int row, int column, boolean expanded, boolean leaf); 50 | 51 | public abstract TreeTableCellRenderer getDefaultRenderer(TreeTable treeTable, Class columnClass); 52 | 53 | public abstract TreeTableCellEditor getDefaultEditor(TreeTable treeTable, Class columnClass, int column); 54 | 55 | public abstract Rectangle getPathBounds(TreeTable treeTable, TreePath path); 56 | 57 | public abstract TreePath getPathForLocation(TreeTable treeTable, int x, int y); 58 | 59 | public abstract TreePath getClosestPathForLocation(TreeTable treeTable, int x, int y); 60 | 61 | public abstract int getDistanceToTreeHandle(TreeTable treeTable, TreePath path, int x); 62 | } 63 | --------------------------------------------------------------------------------