├── docs ├── README.md ├── Menu-Items.rst ├── requirements.in ├── source │ ├── images │ │ ├── close_panel.gif │ │ ├── new_window.gif │ │ ├── floating_panel.gif │ │ ├── pinning_panel.gif │ │ ├── adjusting_split.gif │ │ ├── docking_handles.gif │ │ ├── docking_regions.gif │ │ ├── has_more_options.gif │ │ ├── new_topic_options.png │ │ ├── creating_tab_group.gif │ │ ├── completion_procedure.png │ │ ├── convert_table_to_xml.png │ │ ├── new_topic_options_dark.png │ │ ├── root_docking_handles.gif │ │ ├── completion_procedure_dark.png │ │ └── convert_table_to_xml_dark.png │ ├── Modern-Docking-API.rst │ ├── index.rst │ ├── Packaging.rst │ ├── Internal-Workings.rst │ ├── Persistence.rst │ ├── Listeners.rst │ ├── Menu-Items.rst │ ├── Events.rst │ ├── Modern-Docking-UI.rst │ ├── Customization-Points.rst │ ├── conf.py │ ├── Dockable-Properties.rst │ ├── Working-with-Layouts.rst │ └── Exceptions.rst ├── Makefile ├── make.bat ├── TODO.md └── requirements.txt ├── gradle_upgrade.bat ├── demo-multi-app ├── src │ ├── examples │ │ ├── Display.java │ │ ├── Maximize.java │ │ └── BringToFront.java │ ├── basic │ │ ├── MultipleInstances.java │ │ ├── AlwaysDisplayedPanel.java │ │ ├── BasePanel.java │ │ └── ToolPanel.java │ └── exception │ │ └── EdtViolationException.java ├── resources │ ├── icons │ │ ├── dark │ │ │ ├── close.png │ │ │ ├── pin.png │ │ │ ├── maximize.png │ │ │ └── minimize.png │ │ └── light │ │ │ ├── pin.png │ │ │ ├── close.png │ │ │ ├── maximize.png │ │ │ ├── minimize.png │ │ │ ├── icons8-vga-100.png │ │ │ ├── icons8-vga-16.png │ │ │ └── icons8-vga-50.png │ └── docking │ │ ├── FlatLightLaf.properties │ │ └── FlatDarkLaf.properties └── build.gradle ├── demo-single-app ├── src │ ├── examples │ │ ├── Display.java │ │ ├── Maximize.java │ │ ├── BringToFront.java │ │ ├── TopTabsMode.java │ │ ├── UpdateTabInfo.java │ │ └── NewWindow.java │ ├── exception │ │ └── EdtViolationException.java │ ├── basic │ │ ├── IncorrectDynamicDockable.java │ │ ├── ScrollingWithToolbarPanel.java │ │ ├── FixedSizePanel.java │ │ ├── Anchor.java │ │ ├── AlwaysDisplayedPanel.java │ │ ├── BasePanel.java │ │ ├── DialogWithDocking.java │ │ └── ToolPanel.java │ ├── packets │ │ ├── PacketBytesPanel.java │ │ ├── PacketListPanel.java │ │ └── PacketInfoPanel.java │ └── tests │ │ └── TranslucentTest.java ├── resources │ ├── icons │ │ ├── dark │ │ │ ├── pin.png │ │ │ ├── close.png │ │ │ ├── maximize.png │ │ │ └── minimize.png │ │ └── light │ │ │ ├── pin.png │ │ │ ├── close.png │ │ │ ├── maximize.png │ │ │ ├── minimize.png │ │ │ ├── icons8-vga-16.png │ │ │ ├── icons8-vga-50.png │ │ │ └── icons8-vga-100.png │ └── docking │ │ ├── FlatLightLaf.properties │ │ └── FlatDarkLaf.properties └── build.gradle ├── Writerside ├── images │ ├── new_window.gif │ ├── close_panel.gif │ ├── pinning_panel.gif │ ├── adjusting_split.gif │ ├── docking_handles.gif │ ├── docking_regions.gif │ ├── floating_panel.gif │ ├── creating_tab_group.gif │ ├── has_more_options.gif │ ├── new_topic_options.png │ ├── completion_procedure.png │ ├── convert_table_to_xml.png │ ├── root_docking_handles.gif │ ├── new_topic_options_dark.png │ ├── completion_procedure_dark.png │ └── convert_table_to_xml_dark.png ├── v.list ├── topics │ ├── Modern-Docking-API.md │ ├── starter-topic.md │ ├── Packaging.md │ ├── Events.md │ ├── Persistence.md │ ├── Menu-Items.md │ ├── Listeners.md │ ├── Internal-Workings.md │ ├── Customization-Points.md │ ├── Modern-Docking-UI.md │ ├── Dockable-Properties.md │ ├── Working-With-Layouts.md │ ├── Exceptions.md │ └── User-Facing-Features.md ├── c.list ├── project.ihp ├── cfg │ └── buildprofiles.xml ├── redirection-rules.xml └── m.tree ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── docking-api ├── resources │ └── api_icons │ │ ├── close.png │ │ ├── close-16.png │ │ └── settings.png ├── src │ ├── module-info.java │ └── io │ │ └── github │ │ └── andrewauclair │ │ └── moderndocking │ │ ├── event │ │ ├── DockingListener.java │ │ ├── DockingLayoutListener.java │ │ ├── MaximizeListener.java │ │ ├── NewFloatingFrameListener.java │ │ └── DockingLayoutEvent.java │ │ ├── ui │ │ ├── ToolbarLocation.java │ │ ├── DropdownUI.java │ │ └── DockingHeaderUI.java │ │ ├── DockingRegion.java │ │ ├── DockableStyle.java │ │ ├── DockableTabPreference.java │ │ ├── layouts │ │ ├── EmptyPanelNode.java │ │ └── DockingLayoutNode.java │ │ ├── exception │ │ ├── DockableNotFoundException.java │ │ ├── RootDockingPanelNotFoundException.java │ │ ├── DockableRegistrationFailureException.java │ │ ├── NotDockedException.java │ │ ├── RootDockingPanelRegistrationFailureException.java │ │ └── DockingLayoutException.java │ │ ├── DockingProperty.java │ │ ├── internal │ │ ├── util │ │ │ ├── CombinedIcon.java │ │ │ └── SlideBorder.java │ │ ├── FailedDockable.java │ │ └── AppStatePersister.java │ │ └── DynamicDockableParameters.java └── build.gradle ├── settings.gradle ├── docking-multi-app ├── src │ ├── module-info.java │ └── io │ │ └── github │ │ └── andrewauclair │ │ └── moderndocking │ │ └── app │ │ ├── DockingState.java │ │ ├── LayoutPersistence.java │ │ ├── WindowLayoutBuilder.java │ │ ├── Docking.java │ │ ├── RootDockingPanel.java │ │ ├── LayoutsMenu.java │ │ └── ApplicationLayoutMenuItem.java └── build.gradle ├── docking-ui ├── resources │ └── ui_ext_icons │ │ ├── settings.svg │ │ └── close.svg ├── src │ └── module-info.java └── build.gradle ├── docking-single-app ├── src │ ├── module-info.java │ └── io │ │ └── github │ │ └── andrewauclair │ │ └── moderndocking │ │ └── app │ │ ├── WindowLayoutBuilder.java │ │ ├── RootDockingPanel.java │ │ ├── LayoutsMenu.java │ │ ├── ApplicationLayoutMenuItem.java │ │ ├── LayoutPersistence.java │ │ └── DockingState.java └── build.gradle ├── publish.bat ├── .gitignore ├── .readthedocs.yaml ├── .github └── workflows │ ├── build.yml │ └── publish.yml ├── LICENSE ├── example_layout.xml ├── README.md └── gradlew.bat /docs/README.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/Menu-Items.rst: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /gradle_upgrade.bat: -------------------------------------------------------------------------------- 1 | gradlew wrapper --gradle-version=%1 -------------------------------------------------------------------------------- /docs/requirements.in: -------------------------------------------------------------------------------- 1 | sphinx==8.2.3 2 | sphinx_readable_theme==1.3.0 3 | sphinx-notfound-page==1.0.2 -------------------------------------------------------------------------------- /demo-multi-app/src/examples/Display.java: -------------------------------------------------------------------------------- 1 | package examples; 2 | 3 | public class Display { 4 | } 5 | -------------------------------------------------------------------------------- /demo-multi-app/src/examples/Maximize.java: -------------------------------------------------------------------------------- 1 | package examples; 2 | 3 | public class Maximize { 4 | } 5 | -------------------------------------------------------------------------------- /demo-single-app/src/examples/Display.java: -------------------------------------------------------------------------------- 1 | package examples; 2 | 3 | public class Display { 4 | } 5 | -------------------------------------------------------------------------------- /demo-single-app/src/examples/Maximize.java: -------------------------------------------------------------------------------- 1 | package examples; 2 | 3 | public class Maximize { 4 | } 5 | -------------------------------------------------------------------------------- /demo-multi-app/src/examples/BringToFront.java: -------------------------------------------------------------------------------- 1 | package examples; 2 | 3 | public class BringToFront { 4 | } 5 | -------------------------------------------------------------------------------- /demo-single-app/src/examples/BringToFront.java: -------------------------------------------------------------------------------- 1 | package examples; 2 | 3 | public class BringToFront { 4 | } 5 | -------------------------------------------------------------------------------- /demo-single-app/src/examples/TopTabsMode.java: -------------------------------------------------------------------------------- 1 | package examples; 2 | 3 | public class TopTabsMode { 4 | } 5 | -------------------------------------------------------------------------------- /demo-single-app/src/examples/UpdateTabInfo.java: -------------------------------------------------------------------------------- 1 | package examples; 2 | 3 | public class UpdateTabInfo { 4 | } 5 | -------------------------------------------------------------------------------- /Writerside/images/new_window.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewauclair/ModernDocking/HEAD/Writerside/images/new_window.gif -------------------------------------------------------------------------------- /Writerside/images/close_panel.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewauclair/ModernDocking/HEAD/Writerside/images/close_panel.gif -------------------------------------------------------------------------------- /Writerside/images/pinning_panel.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewauclair/ModernDocking/HEAD/Writerside/images/pinning_panel.gif -------------------------------------------------------------------------------- /docs/source/images/close_panel.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewauclair/ModernDocking/HEAD/docs/source/images/close_panel.gif -------------------------------------------------------------------------------- /docs/source/images/new_window.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewauclair/ModernDocking/HEAD/docs/source/images/new_window.gif -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewauclair/ModernDocking/HEAD/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /Writerside/images/adjusting_split.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewauclair/ModernDocking/HEAD/Writerside/images/adjusting_split.gif -------------------------------------------------------------------------------- /Writerside/images/docking_handles.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewauclair/ModernDocking/HEAD/Writerside/images/docking_handles.gif -------------------------------------------------------------------------------- /Writerside/images/docking_regions.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewauclair/ModernDocking/HEAD/Writerside/images/docking_regions.gif -------------------------------------------------------------------------------- /Writerside/images/floating_panel.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewauclair/ModernDocking/HEAD/Writerside/images/floating_panel.gif -------------------------------------------------------------------------------- /docs/source/images/floating_panel.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewauclair/ModernDocking/HEAD/docs/source/images/floating_panel.gif -------------------------------------------------------------------------------- /docs/source/images/pinning_panel.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewauclair/ModernDocking/HEAD/docs/source/images/pinning_panel.gif -------------------------------------------------------------------------------- /Writerside/images/creating_tab_group.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewauclair/ModernDocking/HEAD/Writerside/images/creating_tab_group.gif -------------------------------------------------------------------------------- /Writerside/images/has_more_options.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewauclair/ModernDocking/HEAD/Writerside/images/has_more_options.gif -------------------------------------------------------------------------------- /Writerside/images/new_topic_options.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewauclair/ModernDocking/HEAD/Writerside/images/new_topic_options.png -------------------------------------------------------------------------------- /docs/source/images/adjusting_split.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewauclair/ModernDocking/HEAD/docs/source/images/adjusting_split.gif -------------------------------------------------------------------------------- /docs/source/images/docking_handles.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewauclair/ModernDocking/HEAD/docs/source/images/docking_handles.gif -------------------------------------------------------------------------------- /docs/source/images/docking_regions.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewauclair/ModernDocking/HEAD/docs/source/images/docking_regions.gif -------------------------------------------------------------------------------- /docs/source/images/has_more_options.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewauclair/ModernDocking/HEAD/docs/source/images/has_more_options.gif -------------------------------------------------------------------------------- /docs/source/images/new_topic_options.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewauclair/ModernDocking/HEAD/docs/source/images/new_topic_options.png -------------------------------------------------------------------------------- /Writerside/images/completion_procedure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewauclair/ModernDocking/HEAD/Writerside/images/completion_procedure.png -------------------------------------------------------------------------------- /Writerside/images/convert_table_to_xml.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewauclair/ModernDocking/HEAD/Writerside/images/convert_table_to_xml.png -------------------------------------------------------------------------------- /Writerside/images/root_docking_handles.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewauclair/ModernDocking/HEAD/Writerside/images/root_docking_handles.gif -------------------------------------------------------------------------------- /docking-api/resources/api_icons/close.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewauclair/ModernDocking/HEAD/docking-api/resources/api_icons/close.png -------------------------------------------------------------------------------- /docs/source/images/creating_tab_group.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewauclair/ModernDocking/HEAD/docs/source/images/creating_tab_group.gif -------------------------------------------------------------------------------- /Writerside/images/new_topic_options_dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewauclair/ModernDocking/HEAD/Writerside/images/new_topic_options_dark.png -------------------------------------------------------------------------------- /demo-multi-app/resources/icons/dark/close.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewauclair/ModernDocking/HEAD/demo-multi-app/resources/icons/dark/close.png -------------------------------------------------------------------------------- /demo-multi-app/resources/icons/dark/pin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewauclair/ModernDocking/HEAD/demo-multi-app/resources/icons/dark/pin.png -------------------------------------------------------------------------------- /demo-multi-app/resources/icons/light/pin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewauclair/ModernDocking/HEAD/demo-multi-app/resources/icons/light/pin.png -------------------------------------------------------------------------------- /demo-single-app/resources/icons/dark/pin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewauclair/ModernDocking/HEAD/demo-single-app/resources/icons/dark/pin.png -------------------------------------------------------------------------------- /demo-single-app/resources/icons/light/pin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewauclair/ModernDocking/HEAD/demo-single-app/resources/icons/light/pin.png -------------------------------------------------------------------------------- /docking-api/resources/api_icons/close-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewauclair/ModernDocking/HEAD/docking-api/resources/api_icons/close-16.png -------------------------------------------------------------------------------- /docking-api/resources/api_icons/settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewauclair/ModernDocking/HEAD/docking-api/resources/api_icons/settings.png -------------------------------------------------------------------------------- /docs/source/images/completion_procedure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewauclair/ModernDocking/HEAD/docs/source/images/completion_procedure.png -------------------------------------------------------------------------------- /docs/source/images/convert_table_to_xml.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewauclair/ModernDocking/HEAD/docs/source/images/convert_table_to_xml.png -------------------------------------------------------------------------------- /docs/source/images/new_topic_options_dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewauclair/ModernDocking/HEAD/docs/source/images/new_topic_options_dark.png -------------------------------------------------------------------------------- /docs/source/images/root_docking_handles.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewauclair/ModernDocking/HEAD/docs/source/images/root_docking_handles.gif -------------------------------------------------------------------------------- /Writerside/images/completion_procedure_dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewauclair/ModernDocking/HEAD/Writerside/images/completion_procedure_dark.png -------------------------------------------------------------------------------- /Writerside/images/convert_table_to_xml_dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewauclair/ModernDocking/HEAD/Writerside/images/convert_table_to_xml_dark.png -------------------------------------------------------------------------------- /demo-multi-app/resources/icons/light/close.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewauclair/ModernDocking/HEAD/demo-multi-app/resources/icons/light/close.png -------------------------------------------------------------------------------- /demo-single-app/resources/icons/dark/close.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewauclair/ModernDocking/HEAD/demo-single-app/resources/icons/dark/close.png -------------------------------------------------------------------------------- /demo-single-app/resources/icons/light/close.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewauclair/ModernDocking/HEAD/demo-single-app/resources/icons/light/close.png -------------------------------------------------------------------------------- /demo-multi-app/resources/icons/dark/maximize.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewauclair/ModernDocking/HEAD/demo-multi-app/resources/icons/dark/maximize.png -------------------------------------------------------------------------------- /demo-multi-app/resources/icons/dark/minimize.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewauclair/ModernDocking/HEAD/demo-multi-app/resources/icons/dark/minimize.png -------------------------------------------------------------------------------- /demo-multi-app/resources/icons/light/maximize.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewauclair/ModernDocking/HEAD/demo-multi-app/resources/icons/light/maximize.png -------------------------------------------------------------------------------- /demo-multi-app/resources/icons/light/minimize.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewauclair/ModernDocking/HEAD/demo-multi-app/resources/icons/light/minimize.png -------------------------------------------------------------------------------- /demo-single-app/resources/icons/dark/maximize.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewauclair/ModernDocking/HEAD/demo-single-app/resources/icons/dark/maximize.png -------------------------------------------------------------------------------- /demo-single-app/resources/icons/dark/minimize.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewauclair/ModernDocking/HEAD/demo-single-app/resources/icons/dark/minimize.png -------------------------------------------------------------------------------- /demo-single-app/resources/icons/light/maximize.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewauclair/ModernDocking/HEAD/demo-single-app/resources/icons/light/maximize.png -------------------------------------------------------------------------------- /demo-single-app/resources/icons/light/minimize.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewauclair/ModernDocking/HEAD/demo-single-app/resources/icons/light/minimize.png -------------------------------------------------------------------------------- /docs/source/images/completion_procedure_dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewauclair/ModernDocking/HEAD/docs/source/images/completion_procedure_dark.png -------------------------------------------------------------------------------- /docs/source/images/convert_table_to_xml_dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewauclair/ModernDocking/HEAD/docs/source/images/convert_table_to_xml_dark.png -------------------------------------------------------------------------------- /demo-multi-app/resources/icons/light/icons8-vga-100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewauclair/ModernDocking/HEAD/demo-multi-app/resources/icons/light/icons8-vga-100.png -------------------------------------------------------------------------------- /demo-multi-app/resources/icons/light/icons8-vga-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewauclair/ModernDocking/HEAD/demo-multi-app/resources/icons/light/icons8-vga-16.png -------------------------------------------------------------------------------- /demo-multi-app/resources/icons/light/icons8-vga-50.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewauclair/ModernDocking/HEAD/demo-multi-app/resources/icons/light/icons8-vga-50.png -------------------------------------------------------------------------------- /demo-single-app/resources/icons/light/icons8-vga-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewauclair/ModernDocking/HEAD/demo-single-app/resources/icons/light/icons8-vga-16.png -------------------------------------------------------------------------------- /demo-single-app/resources/icons/light/icons8-vga-50.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewauclair/ModernDocking/HEAD/demo-single-app/resources/icons/light/icons8-vga-50.png -------------------------------------------------------------------------------- /demo-single-app/resources/icons/light/icons8-vga-100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewauclair/ModernDocking/HEAD/demo-single-app/resources/icons/light/icons8-vga-100.png -------------------------------------------------------------------------------- /Writerside/v.list: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'Modern Docking' 2 | 3 | include ':docking-api' 4 | include ':docking-ui' 5 | include ':docking-single-app' 6 | include ':docking-multi-app' 7 | include ':demo-single-app' 8 | include ':demo-multi-app' -------------------------------------------------------------------------------- /Writerside/topics/Modern-Docking-API.md: -------------------------------------------------------------------------------- 1 | # Modern Docking API 2 | 3 | This section of topics explains the Modern Docking API that can be used by an application. This API is used to create and maintain the dockables that users interact with. -------------------------------------------------------------------------------- /Writerside/c.list: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /docking-multi-app/src/module-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Module for the Modern Docking framework 3 | */ 4 | module modern_docking.multi_app { 5 | requires modern_docking.api; 6 | requires java.desktop; 7 | requires java.logging; 8 | 9 | exports io.github.andrewauclair.moderndocking.app; 10 | } -------------------------------------------------------------------------------- /docking-ui/resources/ui_ext_icons/settings.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docking-ui/src/module-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Module for the Modern Docking framework 3 | */ 4 | module modern_docking.ui_ext { 5 | requires modern_docking.api; 6 | requires java.desktop; 7 | requires com.formdev.flatlaf.extras; 8 | 9 | exports io.github.andrewauclair.moderndocking.ext.ui; 10 | } -------------------------------------------------------------------------------- /docking-single-app/src/module-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Module for the Modern Docking framework 3 | */ 4 | module modern_docking.single_app { 5 | requires modern_docking.api; 6 | requires java.desktop; 7 | requires java.logging; 8 | 9 | exports io.github.andrewauclair.moderndocking.app; 10 | } -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-9.0.0-bin.zip 4 | networkTimeout=10000 5 | validateDistributionUrl=true 6 | zipStoreBase=GRADLE_USER_HOME 7 | zipStorePath=wrapper/dists 8 | -------------------------------------------------------------------------------- /docking-ui/resources/ui_ext_icons/close.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Writerside/project.ihp: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Writerside/topics/starter-topic.md: -------------------------------------------------------------------------------- 1 | # Welcome to Modern Docking 2 | 3 | Welcome! This documentation explains the user facing features of Modern Docking, its API, and some of the internals. 4 | 5 | Modern Docking provides a rich set of features to enhance any Java Swing User Interface with a desire to provide user customizable layouts of UI components. Java 11 and newer are supported. 6 | -------------------------------------------------------------------------------- /publish.bat: -------------------------------------------------------------------------------- 1 | cd docking-api 2 | 3 | call gradlew publishToMavenLocal 4 | call gradlew publish 5 | 6 | 7 | cd ..\docking-ui 8 | 9 | call gradlew publishToMavenLocal 10 | call gradlew publish 11 | 12 | 13 | cd ..\docking-single-app 14 | 15 | call gradlew publishToMavenLocal 16 | call gradlew publish 17 | 18 | 19 | cd ..\docking-multi-app 20 | 21 | call gradlew publishToMavenLocal 22 | call gradlew publish 23 | 24 | cd .. 25 | -------------------------------------------------------------------------------- /Writerside/cfg/buildprofiles.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | true 9 | 10 | 11 | 14 | 15 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled class file 2 | *.class 3 | 4 | # Log file 5 | *.log 6 | 7 | # BlueJ files 8 | *.ctxt 9 | 10 | # Mobile Tools for Java (J2ME) 11 | .mtj.tmp/ 12 | 13 | # Package Files # 14 | *.jar 15 | *.war 16 | *.nar 17 | *.ear 18 | *.zip 19 | *.tar.gz 20 | *.rar 21 | 22 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 23 | hs_err_pid* 24 | 25 | # Gradle 26 | build 27 | .gradle 28 | 29 | # IntelliJ project files 30 | .idea 31 | *.iml 32 | out 33 | gen 34 | 35 | # the demos save layout files, we don't want to check them in 36 | demo/basic_demo_layout.xml -------------------------------------------------------------------------------- /docs/source/Modern-Docking-API.rst: -------------------------------------------------------------------------------- 1 | ##################### 2 | Modern Docking API 3 | ##################### 4 | 5 | This section of topics explains the Modern Docking API that can be used by an application. This API is used to create and maintain the dockables that users interact with. 6 | 7 | .. toctree:: 8 | :maxdepth: 2 9 | :caption: Contents: 10 | 11 | Hello-World 12 | Dockable-Properties 13 | Dockable-Interface 14 | Docking-Programmatically 15 | Menu-Items 16 | Customization-Points 17 | Exceptions 18 | Events 19 | Listeners 20 | Working-with-Layouts 21 | Persistence 22 | Look-and-Feel 23 | -------------------------------------------------------------------------------- /docs/source/index.rst: -------------------------------------------------------------------------------- 1 | ######################### 2 | Welcome to Modern Docking 3 | ######################### 4 | 5 | Welcome! This documentation explains the user facing features of Modern Docking, its API, and some of the internals. 6 | 7 | Modern Docking provides a rich set of features to enhance any Java Swing User Interface with a desire to provider user customizable layouts of UI components. 8 | 9 | Java 11 and newer are supported. 10 | 11 | .. toctree:: 12 | :maxdepth: 2 13 | :caption: Contents: 14 | 15 | User-Facing-Features 16 | Packaging 17 | Modern-Docking-API 18 | Modern-Docking-UI 19 | Internal-Workings -------------------------------------------------------------------------------- /Writerside/topics/Packaging.md: -------------------------------------------------------------------------------- 1 | # Packaging 2 | 3 | Modern Docking is provided on Maven Central as a collection of packages. 4 | 5 | Most applications will use `modern-docking-api` and `modern-docking-single-app`. There is an additional UI package ([Modern Docking UI](Modern-Docking-UI.md)) that adds special support for the [FlatLaf](https://www.formdev.com/flatlaf) look and feel library. 6 | 7 | In addition to the above packages, there is a package for applications that launch multiple instances in a single JVM, which is how IntelliJ IDEA works. This package is available as `modern-docking-multi-app` and replaces `modern-docking-single-app` for the multi-app in JVM use case. -------------------------------------------------------------------------------- /Writerside/topics/Events.md: -------------------------------------------------------------------------------- 1 | # Events 2 | 3 | 4 |

This event is fired when dockables are docked, undocked, shown, hidden, pinned or unpinned. Shown and hidden are used when a dockable is in a JTabbedPane and the active tab changes. Pinned and Unpinned are used when the dockable is added to a toolbar or removed from a toolbar. Shown and hidden will also be fired when a pinned dockable is shown and hidden.

5 |
6 | 7 |

Fired when layouts are added to or removed from DockingLayouts and when layouts are restored or persisted to a file

8 |
-------------------------------------------------------------------------------- /docs/source/Packaging.rst: -------------------------------------------------------------------------------- 1 | ############# 2 | Packaging 3 | ############# 4 | 5 | .. _FlatLaf: https://www.formdev.com/flatlaf 6 | 7 | Modern Docking is provided on Maven Central as a collection of packages. 8 | 9 | Most applications will use ``modern-docking-api`` and ``modern-docking-single-app``. There is an additional UI package (:doc:`Modern-Docking-UI`) that adds special support for the `FlatLaf`_ look and feel library. 10 | 11 | In addition to the above packages, there is a package for applications that launch multiple instances in a single JVM, which is how IntelliJ IDEA works. This package is available as ``modern-docking-multi-app`` and replaces ``modern-docking-single-app`` for the multi-app in JVM use case. -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 1 | # Minimal makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line, and also 5 | # from the environment for the first two. 6 | SPHINXOPTS ?= 7 | SPHINXBUILD ?= sphinx-build 8 | SOURCEDIR = source 9 | BUILDDIR = build 10 | 11 | # Put it first so that "make" without argument is like "make help". 12 | help: 13 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 14 | 15 | .PHONY: help Makefile 16 | 17 | # Catch-all target: route all unknown targets to Sphinx using the new 18 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). 19 | %: Makefile 20 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 21 | -------------------------------------------------------------------------------- /Writerside/topics/Persistence.md: -------------------------------------------------------------------------------- 1 | # Persistence 2 | 3 | Modern Docking will persist the current layout of the application to a file specified through the API. When auto persistence is enabled, this file is saved after a number of different UI actions listed below. A delay mechanism is employed to avoid unnecessarily saving the file, such as when the user is dragging splitters. 4 | 5 | The persistence feature defaults to off and can be enabled by calling the `setPersist`. The file that Modern Docking should use to persist the layout can be configured with `setPersistFile`. Finally, a default layout can be configured with `setDefaultApplicationLayout` for when persistence is disabled or Modern Docking fails to load the current auto persist file. 6 | -------------------------------------------------------------------------------- /Writerside/redirection-rules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 10 | Created after removal of "Dockable Customization" from ModernDocking 11 | Dockable-Customization.html 12 | 13 | 14 | Created after removal of "Using Docking Handles" from ModernDocking 15 | Using-Docking-Handles.html 16 | 17 | -------------------------------------------------------------------------------- /.readthedocs.yaml: -------------------------------------------------------------------------------- 1 | # Read the Docs configuration file 2 | # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details 3 | 4 | # Required 5 | version: 2 6 | 7 | # Set the OS, Python version, and other tools you might need 8 | build: 9 | os: ubuntu-24.04 10 | tools: 11 | python: "3.13" 12 | 13 | formats: 14 | - htmlzip 15 | - pdf 16 | 17 | # Build documentation in the "docs/" directory with Sphinx 18 | sphinx: 19 | configuration: docs/source/conf.py 20 | 21 | # Optionally, but recommended, 22 | # declare the Python requirements required to build your documentation 23 | # See https://docs.readthedocs.io/en/stable/guides/reproducible-builds.html 24 | python: 25 | install: 26 | - requirements: docs/requirements.txt -------------------------------------------------------------------------------- /docs/source/Internal-Workings.rst: -------------------------------------------------------------------------------- 1 | ################# 2 | Internal Workings 3 | ################# 4 | 5 | These topics cover internal functionality of the framework for anyone wanting to become more familiar with how Modern Docking works. This knowledge is not required for using Modern Docking. 6 | 7 | ActiveDockableHighlighter 8 | ------------------------- 9 | 10 | The ``ActiveDockableHighlighter`` is responsible for drawing a border around the dockable that the mouse is currently over. Using an AWT event listener on the AWT Toolkit lets us listen for all mouse events in the entire application. 11 | 12 | AppStatePersister 13 | ----------------- 14 | 15 | Used to call ``AppState.persist`` whenever a ``Window`` instance resizes, moves or changes state. 16 | -------------------------------------------------------------------------------- /docs/source/Persistence.rst: -------------------------------------------------------------------------------- 1 | ############# 2 | Persistence 3 | ############# 4 | 5 | Modern Docking will persist the current layout of the application to a file specified through the API. When auto persistence is enabled, this file is saved after a number of different UI actions listed below. A delay mechanism is employed to avoid unnecessarily saving the file, such as when the user is dragging splitters. 6 | 7 | The persistence feature defaults to off and can be enabled by calling the ``setPersist``. The file that Modern Docking should use to persist the layout can be configured with ``setPersistFile``. Finally, a default layout can be configured with ``setDefaultApplicationLayout`` for when persistence is disabled or Modern Docking fails to load the current auto persist file. 8 | -------------------------------------------------------------------------------- /docs/source/Listeners.rst: -------------------------------------------------------------------------------- 1 | ############# 2 | Listeners 3 | ############# 4 | 5 | DockingLayoutListener 6 | ----------------------- 7 | 8 | Listen for when layouts are added to or removed from ``DockingLayouts`` and when layouts are restored or saved to a file 9 | 10 | DockingListener 11 | ----------------------- 12 | 13 | Listen for any changes to active dockables. This includes docking, undocking, shown, hidden, auto hide 14 | 15 | MaximizeListener 16 | ----------------------- 17 | 18 | Listen for maximize events triggered by ``Docking.maximize`` 19 | 20 | NewFloatingFrameListener 21 | ----------------------- 22 | 23 | Listen for the creation of new floating frames. This allows the application to set icons, titles, menu bars, etc. on the new frame. 24 | -------------------------------------------------------------------------------- /docs/source/Menu-Items.rst: -------------------------------------------------------------------------------- 1 | ############# 2 | Menu Items 3 | ############# 4 | 5 | Modern Docking provides several specialized menu classes explained below 6 | 7 | LayoutsMenu 8 | ----------- 9 | 10 | Displays a list of all layouts that the layout manager knows about. These are automatically added and removed. When clicked the menu item will load that layout. 11 | 12 | ApplicationLayoutMenuItem 13 | ------------------------- 14 | 15 | Menu item specific to one layout. Simply displays the name and when clicked loads the layout with :java:`Docking.restore()` 16 | 17 | DockableMenuItem 18 | ---------------- 19 | 20 | Displays a single dockable. Shows a checkmark if the dockable is docked. If the dockable is not docked, docks it, if it is docked, it displays it. 21 | 22 | -------------------------------------------------------------------------------- /docking-api/src/module-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Module for the Modern Docking framework 3 | */ 4 | module modern_docking.api { 5 | requires java.desktop; 6 | requires java.logging; 7 | 8 | exports io.github.andrewauclair.moderndocking; 9 | exports io.github.andrewauclair.moderndocking.event; 10 | exports io.github.andrewauclair.moderndocking.exception; 11 | exports io.github.andrewauclair.moderndocking.layouts; 12 | exports io.github.andrewauclair.moderndocking.settings; 13 | exports io.github.andrewauclair.moderndocking.ui; 14 | exports io.github.andrewauclair.moderndocking.api; 15 | 16 | // export our internal package only to our other extension modules 17 | exports io.github.andrewauclair.moderndocking.internal to modern_docking.ui_ext, modern_docking.single_app, modern_docking.multi_app; 18 | } -------------------------------------------------------------------------------- /Writerside/topics/Menu-Items.md: -------------------------------------------------------------------------------- 1 | # Menu Items 2 | 3 | Modern Docking provides several specialized menu classes explained below 4 | 5 | 6 |

Displays a list of all layouts that the layout manager knows about. These are automatically added and removed. When clicked the menu item will load that layout.

7 |
8 | 9 |

Menu item specific to one layout. Simply displays the name and when clicked loads the layout with Docking.restore()

10 |
11 | 12 |

Displays a single dockable. Shows a checkmark if the dockable is docked. If the dockable is not docked, docks it, if it is docked, it displays it.

13 |
14 | -------------------------------------------------------------------------------- /Writerside/topics/Listeners.md: -------------------------------------------------------------------------------- 1 | # Listeners 2 | 3 | 4 |

Listen for when layouts are added to or removed from DockingLayouts and when layouts are restored or saved to a file

5 |
6 | 7 |

Listen for any changes to active dockables. This includes docking, undocking, shown, hidden, auto hide

8 |
9 | 10 |

Listen for maximize events triggered by Docking.maximize

11 |
12 | 13 |

Listen for the creation of new floating frames. This allows the application to set icons, titles, menu bars, etc. on the new frame.

14 |
-------------------------------------------------------------------------------- /Writerside/topics/Internal-Workings.md: -------------------------------------------------------------------------------- 1 | # Internal Workings 2 | 3 | These topics cover internal functionality of the framework for anyone wanting to become more familiar with how Modern Docking works. This knowledge is not required for using Modern Docking. 4 | 5 | 6 |

The ActiveDockableHighlighter is responsible for drawing a border around the dockable that the mouse is currently over. Using an AWT event listener on the AWT Toolkit lets us listen for all mouse events in the entire application.

7 |
8 | 9 | 10 |

Used to call AppState.persist whenever a Window instance resizes, moves or changes state.

11 |
12 | 13 | 14 |

15 |
-------------------------------------------------------------------------------- /docs/source/Events.rst: -------------------------------------------------------------------------------- 1 | ############# 2 | Events 3 | ############# 4 | 5 | DockingEvent 6 | ------------ 7 | 8 | This event is fired when dockables are docked, undocked, shown, hidden, pinned or unpinned. Shown and hidden are used when a dockable is in a ``JTabbedPane`` and the active tab changes. Pinned and Unpinned are used when the dockable is added to a toolbar or removed from a toolbar. Shown and hidden will also be fired when a pinned dockable is shown and hidden. 9 | 10 | Temporary events are fired when a user starts dragging a dockable. This allows any listeners to perform actions only based on permanent events (i.e. events that do not have the temporary flag set).JTabbedPane 11 | 12 | DockingLayoutEvent 13 | ------------------ 14 | 15 | Fired when layouts are added to or removed from ``DockingLayouts`` and when layouts are restored or persisted to a file 16 | -------------------------------------------------------------------------------- /docs/make.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | pushd %~dp0 4 | 5 | REM Command file for Sphinx documentation 6 | 7 | if "%SPHINXBUILD%" == "" ( 8 | set SPHINXBUILD=sphinx-build 9 | ) 10 | set SOURCEDIR=source 11 | set BUILDDIR=build 12 | 13 | %SPHINXBUILD% >NUL 2>NUL 14 | if errorlevel 9009 ( 15 | echo. 16 | echo.The 'sphinx-build' command was not found. Make sure you have Sphinx 17 | echo.installed, then set the SPHINXBUILD environment variable to point 18 | echo.to the full path of the 'sphinx-build' executable. Alternatively you 19 | echo.may add the Sphinx directory to PATH. 20 | echo. 21 | echo.If you don't have Sphinx installed, grab it from 22 | echo.https://www.sphinx-doc.org/ 23 | exit /b 1 24 | ) 25 | 26 | if "%1" == "" goto help 27 | 28 | %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% 29 | goto end 30 | 31 | :help 32 | %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% 33 | 34 | :end 35 | popd 36 | -------------------------------------------------------------------------------- /Writerside/topics/Customization-Points.md: -------------------------------------------------------------------------------- 1 | # Customization Points 2 | 3 | ## Tab Placement 4 | 5 | By default, Modern Docking places all tabs in `JTabbedPane`s at the bottom. This can be changed using `Settings.alwaysDisplayTabsMode` which will switch the tab placement to the top. 6 | 7 | 8 | ## Tab Layout Policy 9 | 10 | The tab layout policy of `JTabbedPane` can be customized with `Settings.setTabLayoutPolicy`. 11 | The default tab layout policy is `JTabbedPane.SCROLL_TAB_LAYOUT` and it can be set to either `JTabbedPane.SCROLL_TAB_LAYOUT` or `JTabbedPane.WRAP_TAB_LAYOUT`. 12 | 13 | ## Active Highlighter 14 | 15 | By default, Modern Docking will highlight the dockable that the house is currently over. This can be disabled before initializing the docking framework by using `Settings.setActiveHighlighterEnabled`. 16 | 17 | ## Custom Dockable Header 18 | 19 | Create your own implementation of the header UI and return it in Dockable. -------------------------------------------------------------------------------- /Writerside/topics/Modern-Docking-UI.md: -------------------------------------------------------------------------------- 1 | # Modern Docking UI 2 | 3 | Modern Docking UI is an extension to Modern Docking that changes png's to svg's for the Settings and Close icons using the FlatLaf library. 4 | 5 | ## Initializing Modern Docking UI 6 | 7 | Using our [Hello World](Hello-World.md) example, we can update it to initialize the Modern Docking UI like below, which is all that's required to use Modern Docking UI. 8 | 9 | ```java 10 | public static class MainFrame extends JFrame { 11 | public MainFrame() { 12 | setSize(400, 300); 13 | 14 | Docking.initialize(this); 15 | DockingUI.initialize(); 16 | 17 | RootDockingPanel root = new RootDockingPanel(this); 18 | add(root, BorderLayout.CENTER); 19 | 20 | DockingPanel helloWorld = new DockingPanel("Hello World"); 21 | 22 | Docking.dock(helloWorld, this); 23 | } 24 | } 25 | ``` 26 | 27 | ## FlatLaf 28 | 29 | 30 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | # This workflow uses actions that are not certified by GitHub. 2 | # They are provided by a third-party and are governed by 3 | # separate terms of service, privacy policy, and support 4 | # documentation. 5 | 6 | # GitHub recommends pinning actions to a commit SHA. 7 | # To get a newer version, you will need to update the SHA. 8 | # You can also reference a tag or branch, but the action may change without warning. 9 | 10 | name: Build 11 | on: push 12 | 13 | jobs: 14 | build: 15 | runs-on: ubuntu-latest 16 | steps: 17 | - uses: actions/checkout@v4 18 | - name: Set up Java 19 | uses: actions/setup-java@v4 20 | with: 21 | java-version: '21' 22 | distribution: 'temurin' 23 | - name: Validate Gradle wrapper 24 | uses: gradle/actions/wrapper-validation@v4 25 | - name: Setup Gradle 26 | uses: gradle/actions/setup-gradle@v3 27 | - name: Build 28 | run: ./gradlew build 29 | -------------------------------------------------------------------------------- /Writerside/topics/Dockable-Properties.md: -------------------------------------------------------------------------------- 1 | # Dockable Properties 2 | 3 | The `DockingProperty` attribute is used to dynamically add properties to dockable components and was inspired by the excellent Java command line parsing library [Picocli](https://picocli.info/). 4 | 5 | For example, say we have a simple `JCheckBox` on our Dockable component and wish to persist it together with the Docking layout. We could create a `boolean` member variable in our Dockable component class and tie it to a property. 6 | 7 | 8 | 9 | ```java 10 | public class Example implements Dockable { 11 | @DockingProperty(name = "enabled", defaultValue = "false") 12 | private boolean enabled; 13 | 14 | @Override 15 | public void updateProperties() { 16 | // enabled value is now usable 17 | } 18 | } 19 | ``` 20 | 21 | These dockable properties can be done for the following Java types: 22 | 23 | - byte 24 | - short 25 | - int 26 | - long 27 | - float 28 | - double 29 | - char 30 | - boolean 31 | - String -------------------------------------------------------------------------------- /docs/source/Modern-Docking-UI.rst: -------------------------------------------------------------------------------- 1 | ################# 2 | Modern Docking UI 3 | ################# 4 | 5 | Modern Docking UI is an extension to Modern Docking that changes png's to svg's for the Settings and Close icons using the FlatLaf library. 6 | 7 | Initializing 8 | ------------ 9 | 10 | Using our :doc:`Hello-World` example, we can update it to initialize the Modern Docking UI like below, which is all that's required to use Modern Docking UI. 11 | 12 | .. code-block:: java 13 | 14 | public static class MainFrame extends JFrame { 15 | public MainFrame() { 16 | setSize(400, 300); 17 | 18 | Docking.initialize(this); 19 | DockingUI.initialize(); 20 | 21 | RootDockingPanel root = new RootDockingPanel(this); 22 | add(root, BorderLayout.CENTER); 23 | 24 | DockingPanel helloWorld = new DockingPanel("Hello World"); 25 | 26 | Docking.dock(helloWorld, this); 27 | } 28 | 29 | public static void main(String[] args) { 30 | SwingUtilities.invokeLater(() -> new MainFrame().setVisible(true)); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Andrew Auclair 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /docs/source/Customization-Points.rst: -------------------------------------------------------------------------------- 1 | #################### 2 | Customization Points 3 | #################### 4 | 5 | ------------- 6 | Tab Placement 7 | ------------- 8 | 9 | By default, Modern Docking places all tabs in a ``JTabbedPane`` at the bottom. This can be changed using ``Settings.alwaysDisplayTabsMode`` which will switch the tab placement to the top. 10 | 11 | ----------------- 12 | Tab Layout Policy 13 | ----------------- 14 | 15 | The tab layout policy of ``JTabbedPane`` can be customized with ``Settings.setTabLayoutPolicy``. 16 | The default tab layout policy is ``JTabbedPane.SCROLL_TAB_LAYOUT`` and it can be set to either ``JTabbedPane.SCROLL_TAB_LAYOUT`` or ``JTabbedPane.WRAP_TAB_LAYOUT``. 17 | 18 | ------------------ 19 | Active Highlighter 20 | ------------------ 21 | 22 | By default, Modern Docking will highlight the dockable that the house is currently over. This can be disabled before initializing the docking framework by using ``Settings.setActiveHighlighterEnabled``. 23 | 24 | ---------------------- 25 | Custom Dockable Header 26 | ---------------------- 27 | 28 | Create your own implementation of the header UI and return it in Dockable. -------------------------------------------------------------------------------- /docs/source/conf.py: -------------------------------------------------------------------------------- 1 | # Configuration file for the Sphinx documentation builder. 2 | # 3 | # For the full list of built-in configuration values, see the documentation: 4 | # https://www.sphinx-doc.org/en/master/usage/configuration.html 5 | 6 | # -- Project information ----------------------------------------------------- 7 | # https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information 8 | 9 | project = 'Modern Docking' 10 | copyright = '2025, Andrew Auclair' 11 | author = 'Andrew Auclair' 12 | release = '1.3.1' 13 | 14 | # -- General configuration --------------------------------------------------- 15 | # https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration 16 | 17 | extensions = ['sphinx_readable_theme'] 18 | 19 | templates_path = ['_templates'] 20 | exclude_patterns = [] 21 | 22 | 23 | 24 | # -- Options for HTML output ------------------------------------------------- 25 | # https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output 26 | 27 | import sphinx_readable_theme 28 | html_theme = 'readable' 29 | html_static_path = ['_static'] 30 | html_theme_path = [sphinx_readable_theme.get_html_theme_path()] 31 | html_show_sourcelink = False -------------------------------------------------------------------------------- /demo-multi-app/resources/docking/FlatLightLaf.properties: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2020 FormDev Software GmbH 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # https://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | #Docking.handles.background = #F2F2F2 17 | #Docking.handles.background.border = #C2C2C2 18 | #Docking.handles.outline = #000000 19 | #Docking.handles.fill = #4E9DE7 20 | #Docking.overlay.color = #0063d4 21 | #Docking.overlay.border.color = #C2C2C2 22 | #Docking.overlay.alpha = 75 23 | 24 | #Docking.titlebar.default = #2675BF 25 | #Docking.titlebar.background = #ffffff 26 | #Docking.titlebar.border.enabled = true 27 | #Docking.titlebar.border.color = #666666 28 | #Docking.titlebar.border.size = 1 29 | #Docking.titlebar.button.color = #000000 -------------------------------------------------------------------------------- /demo-single-app/resources/docking/FlatLightLaf.properties: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2020 FormDev Software GmbH 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # https://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | #Docking.handles.background = #F2F2F2 17 | #Docking.handles.background.border = #C2C2C2 18 | #Docking.handles.outline = #000000 19 | #Docking.handles.fill = #4E9DE7 20 | #Docking.overlay.color = #0063d4 21 | #Docking.overlay.border.color = #C2C2C2 22 | #Docking.overlay.alpha = 75 23 | 24 | #Docking.titlebar.default = #2675BF 25 | #Docking.titlebar.background = #ffffff 26 | #Docking.titlebar.border.enabled = true 27 | #Docking.titlebar.border.color = #666666 28 | #Docking.titlebar.border.size = 1 29 | #Docking.titlebar.button.color = #000000 -------------------------------------------------------------------------------- /docs/source/Dockable-Properties.rst: -------------------------------------------------------------------------------- 1 | .. role:: java(code) 2 | :language: java 3 | 4 | ################### 5 | Dockable Properties 6 | ################### 7 | 8 | .. _Picocli: https://picocli.info/ 9 | 10 | The :java:`@DockingProperty` attribute is used to dynamically add properties to dockable components and was inspired by the excellent Java command line parsing library `Picocli`_. 11 | 12 | For example, say we have a simple :java:`JCheckBox` on our Dockable component and wish to persist it together with the Docking layout. We could create a :java:`boolean` member variable in our Dockable component class and tie it to a property. 13 | 14 | .. :: TODO make this example actually have a JCheckBox 15 | 16 | .. code-block:: java 17 | 18 | public class Example implements Dockable { 19 | @DockingProperty(name = "enabled", defaultValue = "false") 20 | private boolean enabled; 21 | 22 | @Override 23 | public void updateProperties() { 24 | // enabled value is now usable 25 | } 26 | } 27 | 28 | These dockable properties can be done for the following Java types: 29 | 30 | - byte 31 | - short 32 | - int 33 | - long 34 | - float 35 | - double 36 | - char 37 | - boolean 38 | - String -------------------------------------------------------------------------------- /demo-multi-app/src/basic/MultipleInstances.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2023 Andrew Auclair 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | SOFTWARE. 21 | */ 22 | package basic; 23 | 24 | public class MultipleInstances { 25 | 26 | } 27 | -------------------------------------------------------------------------------- /docs/TODO.md: -------------------------------------------------------------------------------- 1 | things that need documenting: 2 | 3 | modules: 4 | 5 | docking-api 6 | docking-ui 7 | docking-single-app 8 | docking-multi-app 9 | 10 | 11 | features: 12 | 13 | user facing features: 14 | 15 | docking handles 16 | Docking overlay 17 | Floating 18 | 19 | api features: 20 | 21 | Dockable 22 | DockableStyle 23 | DockingProperty 24 | ApplicationLayoutMenuItem 25 | AppState 26 | DockableMenuItem 27 | Docking 28 | DockingState 29 | LayoutPersistence 30 | LayoutsMenu 31 | RootDockingPanel 32 | WindowLayoutBuilder 33 | 34 | Docking events and listeners, docking, layout and maximize 35 | 36 | Exceptions (DockableNotFoundException, DockableRegistrationFailureException, DockingLayoutException, NotDockedException) 37 | 38 | Persistence states and AppState 39 | 40 | layouts 41 | 42 | Settings (UI color names and properties) 43 | 44 | Custom headers 45 | 46 | top tabs 47 | 48 | unpinned/pinned (renaming to auto hide soon) 49 | 50 | 51 | 52 | Docking single app: 53 | 54 | building an app that uses a single global instance of the docking framework 55 | 56 | 57 | Docking multi app: 58 | 59 | building an app that uses multiple instances of the docking framework to build apps that work like IntelliJ (multiple instances in the same JVM instance) 60 | 61 | -------------------------------------------------------------------------------- /demo-multi-app/resources/docking/FlatDarkLaf.properties: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2020 FormDev Software GmbH 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # https://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | 17 | #---- Demo.accent ---- 18 | 19 | #Docking.handles.background = #3C3F41 20 | #Docking.handles.background.border = #616365 21 | #Docking.handles.outline = #8C8C8C 22 | #Docking.handles.fill = #557394 23 | #Docking.overlay.color = #42c0ff 24 | #Docking.overlay.border.color = #111111 25 | #Docking.overlay.alpha = 85 26 | 27 | #Docking.titlebar.default = #4B6EAF 28 | #Docking.titlebar.background = #46494b 29 | #Docking.titlebar.border.enabled = true 30 | #Docking.titlebar.border.color = #666666 31 | #Docking.titlebar.border.size = 1 32 | #Docking.titlebar.button.color = #000000 -------------------------------------------------------------------------------- /demo-single-app/resources/docking/FlatDarkLaf.properties: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2020 FormDev Software GmbH 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # https://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | 17 | #---- Demo.accent ---- 18 | 19 | #Docking.handles.background = #3C3F41 20 | #Docking.handles.background.border = #616365 21 | #Docking.handles.outline = #8C8C8C 22 | #Docking.handles.fill = #557394 23 | #Docking.overlay.color = #42c0ff 24 | #Docking.overlay.border.color = #111111 25 | #Docking.overlay.alpha = 85 26 | 27 | #Docking.titlebar.default = #4B6EAF 28 | #Docking.titlebar.background = #46494b 29 | #Docking.titlebar.border.enabled = true 30 | #Docking.titlebar.border.color = #666666 31 | #Docking.titlebar.border.size = 1 32 | #Docking.titlebar.button.color = #000000 -------------------------------------------------------------------------------- /demo-multi-app/src/exception/EdtViolationException.java: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with 3 | the License. You may obtain a copy of the License at 4 | 5 | http://www.apache.org/licenses/LICENSE-2.0 6 | 7 | Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on 8 | an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the 9 | specific language governing permissions and limitations under the License. 10 | 11 | Copyright 2012-2015 the original author or authors. 12 | */ 13 | package exception; 14 | 15 | /** 16 | * Error thrown when an EDT violation is detected. For more details, please read the Swing's 18 | * Threading Policy. 19 | * 20 | * @author Alex Ruiz 21 | */ 22 | public class EdtViolationException extends RuntimeException { 23 | /** 24 | * Creates a new {@link EdtViolationException}. 25 | * 26 | * @param message the detail message. 27 | */ 28 | public EdtViolationException(String message) { 29 | super(message); 30 | } 31 | } -------------------------------------------------------------------------------- /demo-single-app/src/exception/EdtViolationException.java: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with 3 | the License. You may obtain a copy of the License at 4 | 5 | http://www.apache.org/licenses/LICENSE-2.0 6 | 7 | Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on 8 | an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the 9 | specific language governing permissions and limitations under the License. 10 | 11 | Copyright 2012-2015 the original author or authors. 12 | */ 13 | package exception; 14 | 15 | /** 16 | * Error thrown when an EDT violation is detected. For more details, please read the Swing's 18 | * Threading Policy. 19 | * 20 | * @author Alex Ruiz 21 | */ 22 | public class EdtViolationException extends RuntimeException { 23 | /** 24 | * Creates a new {@link EdtViolationException}. 25 | * 26 | * @param message the detail message. 27 | */ 28 | public EdtViolationException(String message) { 29 | super(message); 30 | } 31 | } -------------------------------------------------------------------------------- /Writerside/m.tree: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /example_layout.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /docs/requirements.txt: -------------------------------------------------------------------------------- 1 | # 2 | # This file is autogenerated by pip-compile with Python 3.13 3 | # by the following command: 4 | # 5 | # pip-compile 6 | # 7 | alabaster==0.7.16 8 | # via sphinx 9 | babel==2.17.0 10 | # via sphinx 11 | certifi==2025.8.3 12 | # via requests 13 | charset-normalizer==3.4.2 14 | # via requests 15 | colorama==0.4.6 16 | # via sphinx 17 | docutils==0.21.2 18 | # via sphinx 19 | idna==3.10 20 | # via requests 21 | imagesize==1.4.1 22 | # via sphinx 23 | jinja2==3.1.6 24 | # via sphinx 25 | markupsafe==3.0.2 26 | # via jinja2 27 | packaging==25.0 28 | # via sphinx 29 | pygments==2.19.2 30 | # via sphinx 31 | requests==2.32.4 32 | # via sphinx 33 | roman-numerals-py==3.1.0 34 | # via sphinx 35 | snowballstemmer==3.0.1 36 | # via sphinx 37 | sphinx==8.2.3 38 | # via 39 | # -r requirements.in 40 | # sphinx-notfound-page 41 | sphinx-notfound-page==1.0.2 42 | # via -r requirements.in 43 | sphinx-readable-theme==1.3.0 44 | # via -r requirements.in 45 | sphinxcontrib-applehelp==2.0.0 46 | # via sphinx 47 | sphinxcontrib-devhelp==2.0.0 48 | # via sphinx 49 | sphinxcontrib-htmlhelp==2.1.0 50 | # via sphinx 51 | sphinxcontrib-jsmath==1.0.1 52 | # via sphinx 53 | sphinxcontrib-qthelp==2.0.0 54 | # via sphinx 55 | sphinxcontrib-serializinghtml==2.0.0 56 | # via sphinx 57 | urllib3==2.5.0 58 | # via requests 59 | -------------------------------------------------------------------------------- /demo-single-app/src/basic/IncorrectDynamicDockable.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2024 Andrew Auclair 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | SOFTWARE. 21 | */ 22 | package basic; 23 | 24 | public class IncorrectDynamicDockable extends BasePanel { 25 | public IncorrectDynamicDockable() { 26 | super("Incorrect Dynamic Dockable", "Incorrect", "incorrect-dynamic-dockable"); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /demo-multi-app/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'java' 3 | id 'idea' 4 | id "com.github.ben-manes.versions" version "0.52.0" 5 | } 6 | 7 | java { 8 | sourceCompatibility = JavaVersion.VERSION_11 9 | targetCompatibility = JavaVersion.VERSION_11 10 | } 11 | 12 | sourceSets.main.java.srcDirs = ['src'] 13 | sourceSets.test.java.srcDirs = ['test'] 14 | sourceSets.main.resources.srcDirs = ['resources'] 15 | 16 | dependencies { 17 | if (project.hasProperty("useMavenVersion")) { 18 | implementation 'io.github.andrewauclair:modern-docking-ui:' + version 19 | implementation 'io.github.andrewauclair:modern-docking-multi-app:' + version 20 | } 21 | else { 22 | implementation project(':docking-ui') 23 | implementation project(':docking-multi-app') 24 | } 25 | 26 | implementation 'com.formdev:flatlaf:' + flatLafVersion 27 | implementation 'com.formdev:flatlaf-intellij-themes:' + flatLafVersion 28 | 29 | implementation 'com.ardikars.pcap:pcap-jdk7:1.5.3' 30 | 31 | implementation 'info.picocli:picocli:4.7.7' 32 | } 33 | 34 | jar { 35 | manifest { 36 | attributes "Main-Class": "basic.MainFrame" 37 | } 38 | 39 | from { 40 | configurations.compileClasspath.collect { it.isDirectory() ? it : zipTree(it) } 41 | } 42 | duplicatesStrategy = DuplicatesStrategy.EXCLUDE 43 | } 44 | 45 | tasks.withType(Javadoc).all { enabled = false } // don't generate javadocs for the demo projects 46 | -------------------------------------------------------------------------------- /docking-api/src/io/github/andrewauclair/moderndocking/event/DockingListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2022 Andrew Auclair 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | SOFTWARE. 21 | */ 22 | package io.github.andrewauclair.moderndocking.event; 23 | 24 | /** 25 | * Listener interface used to listen for docking events 26 | */ 27 | public interface DockingListener { 28 | /** 29 | * Called when docking events occur 30 | * 31 | * @param e The docking event 32 | */ 33 | void dockingChange(DockingEvent e); 34 | } 35 | -------------------------------------------------------------------------------- /docking-single-app/src/io/github/andrewauclair/moderndocking/app/WindowLayoutBuilder.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2023 Andrew Auclair 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | SOFTWARE. 21 | */ 22 | package io.github.andrewauclair.moderndocking.app; 23 | 24 | import io.github.andrewauclair.moderndocking.api.WindowLayoutBuilderAPI; 25 | 26 | public class WindowLayoutBuilder extends WindowLayoutBuilderAPI { 27 | public WindowLayoutBuilder(String firstID) { 28 | super(Docking.getSingleInstance(), firstID); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /demo-single-app/src/basic/ScrollingWithToolbarPanel.java: -------------------------------------------------------------------------------- 1 | package basic; 2 | 3 | import java.awt.GridBagConstraints; 4 | import java.awt.GridBagLayout; 5 | import javax.swing.JButton; 6 | import javax.swing.JLabel; 7 | import javax.swing.JPanel; 8 | import javax.swing.JScrollPane; 9 | import javax.swing.JToolBar; 10 | 11 | public class ScrollingWithToolbarPanel extends BasePanel { 12 | public ScrollingWithToolbarPanel() { 13 | super("scrolling", "Scrolling With Toolbar", "scroll-with-toolbar"); 14 | 15 | setLayout(new GridBagLayout()); 16 | 17 | JToolBar toolBar = new JToolBar(); 18 | toolBar.add(new JButton("Add")); 19 | toolBar.add(new JButton("Remove")); 20 | 21 | JPanel panel = new JPanel(); 22 | panel.setLayout(new GridBagLayout()); 23 | 24 | GridBagConstraints gbc = new GridBagConstraints(); 25 | gbc.gridx = 0; 26 | gbc.gridy = 0; 27 | gbc.weightx = 1; 28 | gbc.weighty = 0; 29 | gbc.fill = GridBagConstraints.HORIZONTAL; 30 | 31 | for (int i = 0; i < 30; i++) { 32 | panel.add(new JLabel("label " + i), gbc); 33 | gbc.gridy++; 34 | } 35 | 36 | gbc.gridy = 0; 37 | add(toolBar, gbc); 38 | 39 | gbc.gridy++; 40 | gbc.weightx = 1; 41 | gbc.weighty = 1; 42 | gbc.fill = GridBagConstraints.BOTH; 43 | 44 | add(new JScrollPane(panel), gbc); 45 | } 46 | 47 | @Override 48 | public boolean isWrappableInScrollpane() { 49 | return false; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /docking-multi-app/src/io/github/andrewauclair/moderndocking/app/DockingState.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2023 Andrew Auclair 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | SOFTWARE. 21 | */ 22 | package io.github.andrewauclair.moderndocking.app; 23 | 24 | import io.github.andrewauclair.moderndocking.api.DockingAPI; 25 | import io.github.andrewauclair.moderndocking.api.DockingStateAPI; 26 | 27 | public class DockingState extends DockingStateAPI { 28 | public DockingState(DockingAPI docking) { 29 | super(docking); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /docking-api/src/io/github/andrewauclair/moderndocking/event/DockingLayoutListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2023 Andrew Auclair 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | SOFTWARE. 21 | */ 22 | package io.github.andrewauclair.moderndocking.event; 23 | 24 | /** 25 | * Listen for changes to layouts 26 | */ 27 | public interface DockingLayoutListener { 28 | /** 29 | * A layout has changed 30 | * 31 | * @param e Information about the layout that has changed 32 | */ 33 | void layoutChange(DockingLayoutEvent e); 34 | } 35 | -------------------------------------------------------------------------------- /docking-multi-app/src/io/github/andrewauclair/moderndocking/app/LayoutPersistence.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2023 Andrew Auclair 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | SOFTWARE. 21 | */ 22 | package io.github.andrewauclair.moderndocking.app; 23 | 24 | import io.github.andrewauclair.moderndocking.api.DockingAPI; 25 | import io.github.andrewauclair.moderndocking.api.LayoutPersistenceAPI; 26 | 27 | public class LayoutPersistence extends LayoutPersistenceAPI { 28 | public LayoutPersistence(DockingAPI docking) { 29 | super(docking); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /demo-single-app/src/examples/NewWindow.java: -------------------------------------------------------------------------------- 1 | package examples; 2 | 3 | import io.github.andrewauclair.moderndocking.DockingRegion; 4 | import io.github.andrewauclair.moderndocking.app.Docking; 5 | import io.github.andrewauclair.moderndocking.app.RootDockingPanel; 6 | import io.github.andrewauclair.moderndocking.ext.ui.DockingUI; 7 | import io.github.andrewauclair.moderndocking.ui.DefaultDockingPanel; 8 | import java.awt.BorderLayout; 9 | import javax.swing.JButton; 10 | import javax.swing.JFrame; 11 | import javax.swing.SwingUtilities; 12 | 13 | public class NewWindow extends JFrame { 14 | public NewWindow() { 15 | setSize(300, 200); 16 | 17 | DockingUI.initialize(); 18 | 19 | RootDockingPanel root = new RootDockingPanel(this); 20 | add(root, BorderLayout.CENTER); 21 | 22 | DefaultDockingPanel one = new DefaultDockingPanel("one", "One"); 23 | DefaultDockingPanel two = new DefaultDockingPanel("two", "Two"); 24 | 25 | JButton openOneInNewWindow = new JButton("Open in new window"); 26 | openOneInNewWindow.addActionListener(e -> Docking.newWindow("one")); 27 | one.add(openOneInNewWindow); 28 | 29 | JButton openTwoInNewWindow = new JButton("Open in new window"); 30 | openTwoInNewWindow.addActionListener(e -> Docking.newWindow(two)); 31 | two.add(openTwoInNewWindow); 32 | 33 | Docking.dock(one, this); 34 | Docking.dock(two, one, DockingRegion.WEST); 35 | } 36 | 37 | public static void main(String[] args) { 38 | SwingUtilities.invokeLater(() -> new NewWindow().setVisible(true)); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /Writerside/topics/Working-With-Layouts.md: -------------------------------------------------------------------------------- 1 | # Working With Layouts 2 | 3 | Layouts can be created in memory from scratch with a builder, pulled from the current window or application layout and saved to files for long term storage. 4 | 5 | In memory layouts are created using the `WindowLayoutBuilder` class and are built using persistentIDs only, by calling similar `dock` functions to the ones provided in the `Docking` class. These persistentIDs do not need to be currently registered in the docking framework to be added to `WindowLayoutBuilder`. An error will be thrown if the persistentID already exists in the layout. When done building the layout, call `build()` to create a `WindowLayout` or `buildApplicationLayout()` to directly build an `ApplicationLayout`. If you're building a layout for multiple windows, you can manually create an `ApplicationLayout` and use `WindowLayoutBuilder` to create layouts and add them to `ApplicationLayout` with `addFrame`. 6 | 7 | The `WindowLayout` and `ApplicationLayout` can then be saved to XML, as well as loaded, with the `WindowLayoutXML` and `ApplicationLayoutXML` classes, respectively. 8 | 9 | The docking framework can store these layouts for you and provides special `JMenuItem`s that can restore named layouts on the application. 10 | 11 | Layouts can be restored by using the `restoreApplicationLayout` and `restoreWindowLayout` methods of the `DockingState` class. This undocks all dockables from the window (or entire application for an ApplicationLayout) and docks the dockables specified by the layout. 12 | 13 | Default layout management and restore is discussed in [Persistence](Persistence.md) -------------------------------------------------------------------------------- /docking-multi-app/src/io/github/andrewauclair/moderndocking/app/WindowLayoutBuilder.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2023 Andrew Auclair 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | SOFTWARE. 21 | */ 22 | package io.github.andrewauclair.moderndocking.app; 23 | 24 | import io.github.andrewauclair.moderndocking.api.DockingAPI; 25 | import io.github.andrewauclair.moderndocking.api.WindowLayoutBuilderAPI; 26 | 27 | public class WindowLayoutBuilder extends WindowLayoutBuilderAPI { 28 | public WindowLayoutBuilder(DockingAPI docking, String firstID) { 29 | super(docking, firstID); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /demo-single-app/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'java' 3 | id 'idea' 4 | id "com.github.ben-manes.versions" version "0.52.0" 5 | } 6 | 7 | java { 8 | sourceCompatibility = JavaVersion.VERSION_11 9 | targetCompatibility = JavaVersion.VERSION_11 10 | } 11 | 12 | sourceSets.main.java.srcDirs = ['src'] 13 | sourceSets.test.java.srcDirs = ['test'] 14 | sourceSets.main.resources.srcDirs = ['resources'] 15 | 16 | dependencies { 17 | if (project.hasProperty("useMavenVersion")) { 18 | implementation 'io.github.andrewauclair:modern-docking-ui:' + version 19 | implementation 'io.github.andrewauclair:modern-docking-single-app:' + version 20 | } 21 | else { 22 | implementation project(':docking-ui') 23 | implementation project(':docking-single-app') 24 | } 25 | 26 | implementation 'com.formdev:flatlaf:' + flatLafVersion 27 | implementation 'com.formdev:flatlaf-intellij-themes:' + flatLafVersion 28 | 29 | implementation 'com.ardikars.pcap:pcap-jdk7:1.5.3' 30 | 31 | implementation 'info.picocli:picocli:4.7.7' 32 | 33 | // uncomment this line to test Modern Docking persistence with a non-default XML parser 34 | // implementation 'com.fasterxml:aalto-xml:1.3.3' 35 | } 36 | 37 | jar { 38 | manifest { 39 | attributes "Main-Class": "basic.MainFrame" 40 | } 41 | 42 | from { 43 | configurations.compileClasspath.collect { it.isDirectory() ? it : zipTree(it) } 44 | } 45 | duplicatesStrategy = DuplicatesStrategy.EXCLUDE 46 | } 47 | 48 | tasks.withType(Javadoc).all { enabled = false } // don't generate javadocs for the demo projects 49 | -------------------------------------------------------------------------------- /docking-api/src/io/github/andrewauclair/moderndocking/event/MaximizeListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2022 Andrew Auclair 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | SOFTWARE. 21 | */ 22 | package io.github.andrewauclair.moderndocking.event; 23 | 24 | import io.github.andrewauclair.moderndocking.Dockable; 25 | 26 | /** 27 | * Interface for creating listeners for maximize events 28 | */ 29 | public interface MaximizeListener { 30 | /** 31 | * Maximized state of dockable has changed 32 | * 33 | * @param dockable Dockable that has changed 34 | * @param maximized New maximized state 35 | */ 36 | void maximized(Dockable dockable, boolean maximized); 37 | } 38 | -------------------------------------------------------------------------------- /docs/source/Working-with-Layouts.rst: -------------------------------------------------------------------------------- 1 | ##################### 2 | Working With Layouts 3 | ##################### 4 | 5 | Layouts can be created in memory from scratch with a builder, pulled from the current window or application layout and saved to files for long term storage. 6 | 7 | In memory layouts are created using the ``WindowLayoutBuilder`` class and are built using persistentIDs only, by calling similar ``dock`` functions to the ones provided in the ``Docking`` class. These persistentIDs do not need to be currently registered in the docking framework to be added to ``WindowLayoutBuilder``. An error will be thrown if the persistentID already exists in the layout. When done building the layout, call ``build()`` to create a ``WindowLayout`` or ``buildApplicationLayout()`` to directly build an ``ApplicationLayout``. If you're building a layout for multiple windows, you can manually create an ``ApplicationLayout`` and use ``WindowLayoutBuilder`` to create layouts and add them to ``ApplicationLayout`` with ``addFrame``. 8 | 9 | The ``WindowLayout`` and ``ApplicationLayout`` can then be saved to XML, as well as loaded, with the ``WindowLayoutXML`` and ``ApplicationLayoutXML`` classes, respectively. 10 | 11 | The docking framework can store these layouts for you and provides a special ``JMenuItem`` that can restore named layouts on the application. 12 | 13 | Layouts can be restored by using the ``restoreApplicationLayout`` and ``restoreWindowLayout`` methods of the ``DockingState`` class. This undocks all dockables from the window (or entire application for an ApplicationLayout) and docks the dockables specified by the layout. 14 | 15 | Default layout management and restore is discussed in :doc:`Persistence` -------------------------------------------------------------------------------- /docking-api/src/io/github/andrewauclair/moderndocking/ui/ToolbarLocation.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2023 Andrew Auclair 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | SOFTWARE. 21 | */ 22 | package io.github.andrewauclair.moderndocking.ui; 23 | 24 | /** 25 | * Location of the toolbar. Toolbars are supported to the West, South and East of a window 26 | */ 27 | public enum ToolbarLocation { 28 | /** 29 | * Toolbar is on the west of the root panel 30 | */ 31 | WEST, 32 | /** 33 | * Toolbar is on the south of the root panel 34 | */ 35 | SOUTH, 36 | /** 37 | * Toolbar is on the east of the root panel 38 | */ 39 | EAST 40 | } 41 | -------------------------------------------------------------------------------- /demo-single-app/src/basic/FixedSizePanel.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2024 Andrew Auclair 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | SOFTWARE. 21 | */ 22 | package basic; 23 | 24 | import io.github.andrewauclair.moderndocking.Dockable; 25 | import java.awt.Dimension; 26 | 27 | public class FixedSizePanel extends BasePanel implements Dockable { 28 | public FixedSizePanel() { 29 | super("Fixed Size", "Fixed Size", "fixed-size"); 30 | 31 | 32 | } 33 | 34 | @Override 35 | public Dimension getMinimumSize() { 36 | return new Dimension(300, 300); 37 | } 38 | 39 | @Override 40 | public boolean isWrappableInScrollpane() { 41 | return false; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /docking-api/src/io/github/andrewauclair/moderndocking/DockingRegion.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2022 Andrew Auclair 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | SOFTWARE. 21 | */ 22 | package io.github.andrewauclair.moderndocking; 23 | 24 | /** 25 | * Enum used to determine docking regions throughout the framework 26 | */ 27 | public enum DockingRegion { 28 | /** 29 | * Used to dock to the center of components 30 | */ 31 | CENTER, 32 | /** 33 | * North or top of windows 34 | */ 35 | NORTH, 36 | /** 37 | * East or right of windows 38 | */ 39 | EAST, 40 | /** 41 | * South or bottom of windows 42 | */ 43 | SOUTH, 44 | /** 45 | * West or left of windows 46 | */ 47 | WEST 48 | } 49 | -------------------------------------------------------------------------------- /docking-multi-app/src/io/github/andrewauclair/moderndocking/app/Docking.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2022-2023 Andrew Auclair 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | SOFTWARE. 21 | */ 22 | package io.github.andrewauclair.moderndocking.app; 23 | 24 | import io.github.andrewauclair.moderndocking.api.DockingAPI; 25 | import java.awt.Window; 26 | 27 | /** 28 | * Convenience class for apps that only need a single instance of the docking framework. Working with the static functions 29 | * is easier than passing an instance of the Docking class all over the app codebase. 30 | */ 31 | public class Docking extends DockingAPI { 32 | public Docking(Window mainWindow) { 33 | super(mainWindow); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /docking-api/src/io/github/andrewauclair/moderndocking/DockableStyle.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2022 Andrew Auclair 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | SOFTWARE. 21 | */ 22 | package io.github.andrewauclair.moderndocking; 23 | 24 | /** 25 | * The style used by a dockable. Used to lock dockables into specific orientations 26 | */ 27 | public enum DockableStyle { 28 | /** 29 | * Dockable is only allowed to be docked horizontally 30 | */ 31 | HORIZONTAL, 32 | /** 33 | * Dockable is only allowed to be docked vertically 34 | */ 35 | VERTICAL, 36 | /** 37 | * Dockable is allowed to be docked horizontally or vertically 38 | */ 39 | BOTH, 40 | /** 41 | * Dockable is only allowed to be docked to the center of other dockables 42 | */ 43 | CENTER_ONLY 44 | } 45 | -------------------------------------------------------------------------------- /demo-multi-app/src/basic/AlwaysDisplayedPanel.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2022 Andrew Auclair 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | SOFTWARE. 21 | */ 22 | package basic; 23 | 24 | import io.github.andrewauclair.moderndocking.api.DockingAPI; 25 | 26 | // Docking panel that is always displayed and cannot be closed 27 | public class AlwaysDisplayedPanel extends SimplePanel { 28 | // create a new basic.AlwaysDisplayedPanel with the given title and persistentID 29 | public AlwaysDisplayedPanel(DockingAPI docking, String title, String persistentID) { 30 | super(docking, title, persistentID); 31 | } 32 | 33 | @Override 34 | public boolean isClosable() { 35 | return false; 36 | } 37 | 38 | @Override 39 | public boolean isFloatingAllowed() { 40 | return false; 41 | } 42 | 43 | @Override 44 | public boolean isLimitedToWindow() { 45 | return true; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /docking-single-app/src/io/github/andrewauclair/moderndocking/app/RootDockingPanel.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2023 Andrew Auclair 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | SOFTWARE. 21 | */ 22 | package io.github.andrewauclair.moderndocking.app; 23 | 24 | import io.github.andrewauclair.moderndocking.api.RootDockingPanelAPI; 25 | import io.github.andrewauclair.moderndocking.ui.ToolbarLocation; 26 | import java.awt.Window; 27 | import java.util.EnumSet; 28 | 29 | public class RootDockingPanel extends RootDockingPanelAPI { 30 | public RootDockingPanel() { 31 | } 32 | 33 | public RootDockingPanel(Window window) { 34 | super(Docking.getSingleInstance(), window); 35 | } 36 | 37 | public RootDockingPanel(Window window, EnumSet supportedToolbars) { 38 | super(Docking.getSingleInstance(), window, supportedToolbars); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /docs/source/Exceptions.rst: -------------------------------------------------------------------------------- 1 | ############# 2 | Exceptions 3 | ############# 4 | 5 | DockableNotFoundException 6 | ------------------------- 7 | 8 | Thrown when a dockable is not found when restoring a DockingLayout 9 | 10 | .. note:: 11 | Thrown by ``DockingState.restoreState`` 12 | 13 | DockableRegistrationFailureException 14 | ------------------------------------ 15 | 16 | Thrown when a dockable with the ``persistentID`` has already been registered 17 | 18 | .. note:: 19 | Thrown by ``Docking.registerDockable`` 20 | 21 | DockingLayoutException 22 | ---------------------- 23 | 24 | This exception is thrown when there is an issue saving or loading a layout file. The exception provides the file that failed and the failure type 25 | 26 | .. note:: 27 | Thrown by ``AppState.restore``, ``LayoutPersistence.saveLayoutToFile`` and ``LayoutPersistence.loadApplicationLayoutFromFile`` 28 | 29 | NotDockedException 30 | ------------------ 31 | 32 | This exception is thrown when Modern Docking attempts to use a dockable that should be docked but isn't. Thrown when the target dockable when docking is not docked or when attempting to bring a dockable to front that isn't already docked 33 | 34 | .. note:: 35 | Thrown by ``Docking.dock`` and ``Docking.bringToFront`` 36 | 37 | RootDockingPanelNotFoundException 38 | --------------------------------- 39 | 40 | Thrown when the root for a window is not found 41 | 42 | .. note:: 43 | Thrown by ``Docking.configurePinning``, ``Docking.dock`` and ``DockingComponentUtils.rootForWindow`` 44 | 45 | RootDockingPanelRegistrationFailureException 46 | -------------------------------------------- 47 | 48 | Thrown when Modern Docking fails to register a ``RootDockingPanel`` because one is already registered for the window 49 | 50 | .. note:: 51 | Thrown by ``Docking.registerDockingPanel`` 52 | 53 | -------------------------------------------------------------------------------- /docking-multi-app/src/io/github/andrewauclair/moderndocking/app/RootDockingPanel.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2023 Andrew Auclair 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | SOFTWARE. 21 | */ 22 | package io.github.andrewauclair.moderndocking.app; 23 | 24 | import io.github.andrewauclair.moderndocking.api.DockingAPI; 25 | import io.github.andrewauclair.moderndocking.api.RootDockingPanelAPI; 26 | import io.github.andrewauclair.moderndocking.ui.ToolbarLocation; 27 | import java.awt.Window; 28 | import java.util.EnumSet; 29 | 30 | public class RootDockingPanel extends RootDockingPanelAPI { 31 | public RootDockingPanel(DockingAPI docking, Window window) { 32 | super(docking, window); 33 | } 34 | 35 | public RootDockingPanel(DockingAPI docking, Window window, EnumSet supportedToolbars) { 36 | super(docking, window, supportedToolbars); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /demo-single-app/src/packets/PacketBytesPanel.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2023 Andrew Auclair 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | SOFTWARE. 21 | */ 22 | package packets; 23 | 24 | import io.github.andrewauclair.moderndocking.Dockable; 25 | import io.github.andrewauclair.moderndocking.DockableStyle; 26 | import io.github.andrewauclair.moderndocking.app.Docking; 27 | import javax.swing.JPanel; 28 | 29 | public class PacketBytesPanel extends JPanel implements Dockable { 30 | public PacketBytesPanel() { 31 | Docking.registerDockable(this); 32 | } 33 | 34 | @Override 35 | public String getPersistentID() { 36 | return "packet-bytes"; 37 | } 38 | 39 | @Override 40 | public String getTabText() { 41 | return "Bytes"; 42 | } 43 | 44 | @Override 45 | public DockableStyle getStyle() { 46 | return null; 47 | } 48 | 49 | @Override 50 | public boolean isAutoHideAllowed() { 51 | return true; 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /docking-api/src/io/github/andrewauclair/moderndocking/ui/DropdownUI.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2022 Andrew Auclair 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | SOFTWARE. 21 | */ 22 | package io.github.andrewauclair.moderndocking.ui; 23 | 24 | import javax.swing.JButton; 25 | import javax.swing.plaf.basic.BasicComboBoxUI; 26 | 27 | // TODO This isn't used right now. I think I was trying to make a dropdown that could be used to swap panels instead of putting them in a tabbed pane. 28 | 29 | /** 30 | * An unused (yet) UI for custom dropdowns 31 | */ 32 | public class DropdownUI extends BasicComboBoxUI { 33 | /** 34 | * Unused 35 | */ 36 | public DropdownUI() { 37 | } 38 | 39 | /** 40 | * Unused 41 | * 42 | * @return Arrow button 43 | */ 44 | @Override 45 | protected JButton createArrowButton() { 46 | JButton button = super.createArrowButton(); 47 | button.setBackground(comboBox.getBackground()); 48 | return button; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /docking-api/src/io/github/andrewauclair/moderndocking/DockableTabPreference.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2024 Andrew Auclair 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | SOFTWARE. 21 | */ 22 | package io.github.andrewauclair.moderndocking; 23 | 24 | /** 25 | * Specify the tab preference of dockables and applications 26 | */ 27 | public enum DockableTabPreference { 28 | /** 29 | * Dockable has no tab preference 30 | */ 31 | NONE, 32 | /** 33 | * Dockable prefers tabs on the bottom 34 | */ 35 | BOTTOM, 36 | /** 37 | * Dockable prefers tabs on the top 38 | */ 39 | TOP, 40 | 41 | // use these options with Settings.setDefaultTabPreference to force tabs to always display, even with a single dockable 42 | /** 43 | * Application wants tabs always on the top 44 | */ 45 | BOTTOM_ALWAYS, 46 | /** 47 | * Application wants tabs always on the bottom 48 | */ 49 | TOP_ALWAYS 50 | } 51 | -------------------------------------------------------------------------------- /demo-single-app/src/basic/Anchor.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2025 Andrew Auclair 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | SOFTWARE. 21 | */ 22 | package basic; 23 | 24 | import io.github.andrewauclair.moderndocking.Dockable; 25 | import io.github.andrewauclair.moderndocking.DockableStyle; 26 | import java.awt.Color; 27 | import javax.swing.BorderFactory; 28 | import javax.swing.JLabel; 29 | import javax.swing.JPanel; 30 | 31 | public class Anchor extends JPanel implements Dockable { 32 | public Anchor() { 33 | setBorder(BorderFactory.createLineBorder(Color.RED)); 34 | 35 | add(new JLabel("This is an anchor")); 36 | } 37 | 38 | @Override 39 | public String getPersistentID() { 40 | return "anchor"; 41 | } 42 | 43 | @Override 44 | public String getTabText() { 45 | return ""; 46 | } 47 | 48 | @Override 49 | public DockableStyle getStyle() { 50 | return DockableStyle.CENTER_ONLY; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /demo-single-app/src/basic/AlwaysDisplayedPanel.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2022 Andrew Auclair 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | SOFTWARE. 21 | */ 22 | package basic; 23 | 24 | import io.github.andrewauclair.moderndocking.DockableTabPreference; 25 | 26 | // Docking panel that is always displayed and cannot be closed 27 | public class AlwaysDisplayedPanel extends SimplePanel { 28 | // create a new basic.AlwaysDisplayedPanel with the given title and persistentID 29 | public AlwaysDisplayedPanel(String title, String persistentID) { 30 | super(title, title, persistentID); 31 | } 32 | 33 | @Override 34 | public boolean isClosable() { 35 | return false; 36 | } 37 | 38 | @Override 39 | public boolean isFloatingAllowed() { 40 | return false; 41 | } 42 | 43 | @Override 44 | public boolean isLimitedToWindow() { 45 | return true; 46 | } 47 | 48 | @Override 49 | public DockableTabPreference getTabPreference() { 50 | return DockableTabPreference.TOP; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /demo-single-app/src/packets/PacketListPanel.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2023 Andrew Auclair 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | SOFTWARE. 21 | */ 22 | package packets; 23 | 24 | import io.github.andrewauclair.moderndocking.Dockable; 25 | import io.github.andrewauclair.moderndocking.app.Docking; 26 | import javax.swing.JPanel; 27 | 28 | public class PacketListPanel extends JPanel implements Dockable { 29 | private static int packetListCount = 0; 30 | 31 | public PacketListPanel() { 32 | Docking.registerDockable(this); 33 | } 34 | 35 | @Override 36 | public String getPersistentID() { 37 | return "packets"; 38 | } 39 | 40 | @Override 41 | public String getTabText() { 42 | return "Packets"; 43 | } 44 | 45 | @Override 46 | public boolean isFloatingAllowed() { 47 | return false; 48 | } 49 | 50 | @Override 51 | public boolean isLimitedToWindow() { 52 | return true; 53 | } 54 | 55 | @Override 56 | public boolean isClosable() { 57 | return packetListCount > 1; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /Writerside/topics/Exceptions.md: -------------------------------------------------------------------------------- 1 | # Exceptions 2 | 3 | 4 |

Thrown when a dockable is not found when restoring a DockingLayout

5 | Thrown by DockingState.restoreState 6 |
7 | 8 |

Thrown when a dockable with the persistentID has already been registered

9 | Thrown by Docking.registerDockable 10 |
11 | 12 |

This exception is thrown when there is an issue saving or loading a layout file. The exception provides the file that failed and the failure type

13 | Thrown by AppState.restore, LayoutPersistence.saveLayoutToFile and LayoutPersistence.loadApplicationLayoutFromFile 14 |
15 | 16 |

This exception is thrown when Modern Docking attempts to use a dockable that should be docked but isn't. Thrown when the target dockable when docking is not docked or when attempting to bring a dockable to front that isn't already docked

17 | Thrown by Docking.dock and Docking.bringToFront 18 |
19 | 20 |

Thrown when the root for a window is not found

21 | Thrown by Docking.configurePinning, Docking.dock and DockingComponentUtils.rootForWindow 22 |
23 | 24 |

Thrown when Modern Docking fails to register a RootDockingPanel because one is already registered for the window

25 | Thrown by Docing.registerDockingPanel 26 |
-------------------------------------------------------------------------------- /docking-api/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'java' 3 | id 'idea' 4 | id 'maven-publish' 5 | id 'signing' 6 | id "com.github.ben-manes.versions" version "0.52.0" 7 | } 8 | 9 | java { 10 | sourceCompatibility = JavaVersion.VERSION_11 11 | targetCompatibility = JavaVersion.VERSION_11 12 | } 13 | 14 | sourceSets.main.java.srcDirs = ['src'] 15 | sourceSets.main.resources.srcDirs = ['resources'] 16 | 17 | // NOTE: do not add new dependencies here, Modern Docking is a zero-dependency library 18 | dependencies { 19 | } 20 | 21 | java { 22 | withJavadocJar() 23 | withSourcesJar() 24 | } 25 | 26 | base { 27 | group = "io.github.andrewauclair" 28 | archivesName = "modern-docking-api" 29 | } 30 | 31 | publishing { 32 | publications { 33 | mavenJava(MavenPublication) { 34 | artifactId = 'modern-docking-api' 35 | from components.java 36 | versionMapping { 37 | usage('java-api') { 38 | fromResolutionOf('runtimeClasspath') 39 | } 40 | usage('java-runtime') { 41 | fromResolutionResult() 42 | } 43 | } 44 | pom { 45 | name = 'Java Modern Docking API' 46 | description = 'Modern docking library for Java Swing' 47 | url = 'https://github.com/andrewauclair/ModernDocking' 48 | licenses { 49 | license { 50 | name = 'The MIT License' 51 | url = 'https://opensource.org/licenses/MIT' 52 | } 53 | } 54 | developers { 55 | developer { 56 | id = 'andrewauclair' 57 | name = 'Andrew Auclair' 58 | email = 'mightymalakai33@gmail.com' 59 | } 60 | } 61 | scm { 62 | connection = 'scm:git:git//github.com/andrewauclair/ModernDocking.git' 63 | developerConnection = 'scm:git:ssh//github.com/andrewauclair/ModernDocking.git' 64 | url = 'https://github.com/andrewauclair/ModernDocking' 65 | } 66 | } 67 | } 68 | } 69 | } 70 | 71 | signing { 72 | required = { gradle.taskGraph.hasTask("publish") } 73 | sign publishing.publications.mavenJava 74 | } 75 | 76 | javadoc { 77 | if(JavaVersion.current().isJava9Compatible()) { 78 | options.addBooleanOption('html5', true) 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /docking-api/src/io/github/andrewauclair/moderndocking/ui/DockingHeaderUI.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2022 Andrew Auclair 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | SOFTWARE. 21 | */ 22 | package io.github.andrewauclair.moderndocking.ui; 23 | 24 | import java.awt.Color; 25 | import javax.swing.JButton; 26 | 27 | /** 28 | * Interface used for defining Docking header UIs that can be updated 29 | */ 30 | public interface DockingHeaderUI { 31 | /** 32 | * Update the UI 33 | */ 34 | void update(); 35 | 36 | /** 37 | * Display the settings menu 38 | * 39 | * @param settings Settings button to display menu at 40 | */ 41 | void displaySettingsMenu(JButton settings); 42 | 43 | /** 44 | * Set the background color override of the header UI 45 | * 46 | * @param color Background color. null to clear override 47 | */ 48 | void setBackgroundOverride(Color color); 49 | 50 | /** 51 | * Set the foreground color override of the header UI 52 | * 53 | * @param color Foreground color. null to clear override 54 | */ 55 | void setForegroundOverride(Color color); 56 | } 57 | -------------------------------------------------------------------------------- /docking-api/src/io/github/andrewauclair/moderndocking/layouts/EmptyPanelNode.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2022 Andrew Auclair 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | SOFTWARE. 21 | */ 22 | package io.github.andrewauclair.moderndocking.layouts; 23 | 24 | import io.github.andrewauclair.moderndocking.DockingRegion; 25 | 26 | /** 27 | * Used to avoid issues with null nodes when root layout nodes are empty 28 | */ 29 | public class EmptyPanelNode implements DockingLayoutNode { 30 | /** 31 | * Create new instance 32 | */ 33 | public EmptyPanelNode() { 34 | } 35 | 36 | @Override 37 | public DockingLayoutNode findNode(String persistentID) { 38 | return null; 39 | } 40 | 41 | @Override 42 | public void dock(String persistentID, DockingRegion region, double dividerProportion) { 43 | } 44 | 45 | @Override 46 | public void replaceChild(DockingLayoutNode child, DockingLayoutNode newChild) { 47 | } 48 | 49 | @Override 50 | public DockingLayoutNode getParent() { 51 | return null; 52 | } 53 | 54 | @Override 55 | public void setParent(DockingLayoutNode parent) { 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /demo-single-app/src/packets/PacketInfoPanel.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2023 Andrew Auclair 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | SOFTWARE. 21 | */ 22 | package packets; 23 | 24 | import io.github.andrewauclair.moderndocking.Dockable; 25 | import io.github.andrewauclair.moderndocking.DockableStyle; 26 | import io.github.andrewauclair.moderndocking.app.Docking; 27 | import javax.swing.JPanel; 28 | 29 | public class PacketInfoPanel extends JPanel implements Dockable { 30 | public PacketInfoPanel() { 31 | Docking.registerDockable(this); 32 | } 33 | 34 | @Override 35 | public String getPersistentID() { 36 | return "packet-info"; 37 | } 38 | 39 | @Override 40 | public String getTabText() { 41 | return "Info"; 42 | } 43 | 44 | @Override 45 | public boolean isFloatingAllowed() { 46 | return false; 47 | } 48 | 49 | @Override 50 | public boolean isLimitedToWindow() { 51 | return true; 52 | } 53 | 54 | @Override 55 | public DockableStyle getStyle() { 56 | return null; 57 | } 58 | 59 | @Override 60 | public boolean isAutoHideAllowed() { 61 | return true; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /demo-multi-app/src/basic/BasePanel.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2022 Andrew Auclair 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | SOFTWARE. 21 | */ 22 | package basic; 23 | 24 | import io.github.andrewauclair.moderndocking.Dockable; 25 | import io.github.andrewauclair.moderndocking.api.DockingAPI; 26 | import java.awt.BorderLayout; 27 | import javax.swing.JPanel; 28 | 29 | public abstract class BasePanel extends JPanel implements Dockable { 30 | private final String title; 31 | private final String persistentID; 32 | 33 | public BasePanel(DockingAPI docking, String title, String persistentID) { 34 | super(new BorderLayout()); 35 | 36 | this.title = title; 37 | this.persistentID = persistentID; 38 | 39 | JPanel panel = new JPanel(); 40 | 41 | add(panel, BorderLayout.CENTER); 42 | 43 | // the single call to register any docking panel extending this abstract class 44 | docking.registerDockable(this); 45 | } 46 | 47 | @Override 48 | public String getPersistentID() { 49 | return persistentID; 50 | } 51 | 52 | @Override 53 | public String getTabText() { 54 | return title; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /docking-api/src/io/github/andrewauclair/moderndocking/exception/DockableNotFoundException.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2022-2024 Andrew Auclair 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | SOFTWARE. 21 | */ 22 | package io.github.andrewauclair.moderndocking.exception; 23 | 24 | /** 25 | * This exception is thrown when the docking framework tries to lookup a dockable and fails 26 | */ 27 | public class DockableNotFoundException extends RuntimeException { 28 | /** 29 | * The persistent ID that we were unable to find a dockable registered with 30 | */ 31 | private final String persistentID; 32 | 33 | /** 34 | * Create a new DockableNotFoundException 35 | * 36 | * @param persistentID The persistentID of the non-existent dockable 37 | */ 38 | public DockableNotFoundException(String persistentID) { 39 | super("Dockable with persistent ID '" + persistentID + "' not found."); 40 | this.persistentID = persistentID; 41 | } 42 | 43 | /** 44 | * Retrieve the persistentID of the dockable that was not found 45 | * @return The persistentID of the non-existent dockable 46 | */ 47 | public String getPersistentID() { 48 | return persistentID; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /docking-api/src/io/github/andrewauclair/moderndocking/exception/RootDockingPanelNotFoundException.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2024 Andrew Auclair 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | SOFTWARE. 21 | */ 22 | package io.github.andrewauclair.moderndocking.exception; 23 | 24 | import java.awt.Window; 25 | 26 | /** 27 | * Exception thrown when a RootDockingPanel is not found for the given window 28 | */ 29 | public class RootDockingPanelNotFoundException extends RuntimeException { 30 | /** 31 | * The window that we wouldn't find a registered root docking panel for 32 | */ 33 | private final Window window; 34 | 35 | /** 36 | * Create a new instance of this exception 37 | * 38 | * @param window The window we didn't find a root for 39 | */ 40 | public RootDockingPanelNotFoundException(Window window) { 41 | super("No root panel for window has been registered."); 42 | this.window = window; 43 | } 44 | 45 | /** 46 | * Retrieve the window we didn't find a root for 47 | * 48 | * @return A Window, either a JFrame or JDialog 49 | */ 50 | public Window getWindow() { 51 | return window; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /docking-api/src/io/github/andrewauclair/moderndocking/exception/DockableRegistrationFailureException.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2022-2024 Andrew Auclair 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | SOFTWARE. 21 | */ 22 | package io.github.andrewauclair.moderndocking.exception; 23 | 24 | /** 25 | * This exception is thrown when the docking framework fails to register a dockable because one with the same persistentID already exists 26 | */ 27 | public class DockableRegistrationFailureException extends RuntimeException { 28 | /** 29 | * The persistent ID of the dockable that we failed to register 30 | */ 31 | private final String persistentID; 32 | 33 | /** 34 | * Create a new instance of this exception 35 | * 36 | * @param persistentID The persistentID of dockable that failed to register 37 | */ 38 | public DockableRegistrationFailureException(String persistentID) { 39 | super("Dockable with Persistent ID " + persistentID + " has not been registered."); 40 | this.persistentID = persistentID; 41 | } 42 | 43 | /** 44 | * Retrieve the persistent ID that already exists 45 | * 46 | * @return Persistent ID 47 | */ 48 | public String getPersistentID() { 49 | return persistentID; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /docking-api/src/io/github/andrewauclair/moderndocking/exception/NotDockedException.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2022-2024 Andrew Auclair 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | SOFTWARE. 21 | */ 22 | package io.github.andrewauclair.moderndocking.exception; 23 | 24 | import io.github.andrewauclair.moderndocking.Dockable; 25 | 26 | /** 27 | * Exception that is thrown when a dockable is not already docked 28 | */ 29 | public class NotDockedException extends RuntimeException { 30 | /** 31 | * The dockable that was not docked while attempting a docking operation 32 | */ 33 | private final Dockable dockable; 34 | 35 | /** 36 | * Create a new exception with the given dockable 37 | * 38 | * @param message Extra message information to display more detail about the problem 39 | * @param dockable Dockable that is not docked 40 | */ 41 | public NotDockedException(String message, Dockable dockable) { 42 | super(message + " because dockable with persistent ID '" + dockable.getPersistentID() + "' is not docked."); 43 | this.dockable = dockable; 44 | } 45 | 46 | /** 47 | * Retrieve the dockable 48 | * 49 | * @return The dockable that is not docked 50 | */ 51 | public Dockable getDockable() { 52 | return dockable; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /demo-single-app/src/basic/BasePanel.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2022 Andrew Auclair 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | SOFTWARE. 21 | */ 22 | package basic; 23 | 24 | import io.github.andrewauclair.moderndocking.Dockable; 25 | import io.github.andrewauclair.moderndocking.app.Docking; 26 | import java.awt.BorderLayout; 27 | import javax.swing.JPanel; 28 | 29 | public abstract class BasePanel extends JPanel implements Dockable { 30 | private final String tabText; 31 | private final String title; 32 | private final String persistentID; 33 | 34 | public BasePanel(String tabText, String title, String persistentID) { 35 | super(new BorderLayout()); 36 | 37 | this.tabText = tabText; 38 | this.title = title; 39 | this.persistentID = persistentID; 40 | 41 | JPanel panel = new JPanel(); 42 | 43 | add(panel, BorderLayout.CENTER); 44 | 45 | // the single call to register any docking panel extending this abstract class 46 | Docking.registerDockable(this); 47 | } 48 | 49 | @Override 50 | public String getPersistentID() { 51 | return persistentID; 52 | } 53 | 54 | @Override 55 | public String getTabText() { 56 | return tabText; 57 | } 58 | 59 | @Override 60 | public String getTitleText() { 61 | return title; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /docking-multi-app/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'java-library' 3 | id 'idea' 4 | id 'maven-publish' 5 | id 'signing' 6 | id "com.github.ben-manes.versions" version "0.52.0" 7 | } 8 | 9 | java { 10 | sourceCompatibility = JavaVersion.VERSION_11 11 | targetCompatibility = JavaVersion.VERSION_11 12 | } 13 | 14 | sourceSets.main.java.srcDirs = ['src'] 15 | sourceSets.main.resources.srcDirs = ['resources'] 16 | 17 | base { 18 | group = "io.github.andrewauclair" 19 | archivesName = "modern-docking-multi-app" 20 | } 21 | 22 | // NOTE: do not add new dependencies here, Modern Docking is a zero-dependency library 23 | dependencies { 24 | if (project.hasProperty("useMavenVersion")) { 25 | implementation 'io.github.andrewauclair:modern-docking-api:' + version 26 | } 27 | else { 28 | api project(':docking-api') 29 | } 30 | } 31 | 32 | java { 33 | withJavadocJar() 34 | withSourcesJar() 35 | } 36 | 37 | publishing { 38 | publications { 39 | mavenJava(MavenPublication) { 40 | artifactId = 'modern-docking-multi-app' 41 | from components.java 42 | versionMapping { 43 | usage('java-api') { 44 | fromResolutionOf('runtimeClasspath') 45 | } 46 | usage('java-runtime') { 47 | fromResolutionResult() 48 | } 49 | } 50 | pom { 51 | name = 'Java Modern Docking' 52 | description = 'Modern docking library for Java Swing' 53 | url = 'https://github.com/andrewauclair/ModernDocking' 54 | licenses { 55 | license { 56 | name = 'The MIT License' 57 | url = 'https://opensource.org/licenses/MIT' 58 | } 59 | } 60 | developers { 61 | developer { 62 | id = 'andrewauclair' 63 | name = 'Andrew Auclair' 64 | email = 'mightymalakai33@gmail.com' 65 | } 66 | } 67 | scm { 68 | connection = 'scm:git:git//github.com/andrewauclair/ModernDocking.git' 69 | developerConnection = 'scm:git:ssh//github.com/andrewauclair/ModernDocking.git' 70 | url = 'https://github.com/andrewauclair/ModernDocking' 71 | } 72 | } 73 | } 74 | } 75 | } 76 | 77 | signing { 78 | required = { gradle.taskGraph.hasTask("publish") } 79 | sign publishing.publications.mavenJava 80 | } 81 | 82 | javadoc { 83 | if(JavaVersion.current().isJava9Compatible()) { 84 | options.addBooleanOption('html5', true) 85 | } 86 | } -------------------------------------------------------------------------------- /docking-single-app/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'java-library' 3 | id 'idea' 4 | id 'maven-publish' 5 | id 'signing' 6 | id "com.github.ben-manes.versions" version "0.52.0" 7 | } 8 | 9 | java { 10 | sourceCompatibility = JavaVersion.VERSION_11 11 | targetCompatibility = JavaVersion.VERSION_11 12 | } 13 | 14 | sourceSets.main.java.srcDirs = ['src'] 15 | sourceSets.main.resources.srcDirs = ['resources'] 16 | 17 | base { 18 | group = "io.github.andrewauclair" 19 | archivesName = "modern-docking-single-app" 20 | } 21 | 22 | // NOTE: do not add new dependencies here, Modern Docking is a zero-dependency library 23 | dependencies { 24 | if (project.hasProperty("useMavenVersion")) { 25 | implementation 'io.github.andrewauclair:modern-docking-api:' + version 26 | } 27 | else { 28 | api project(':docking-api') 29 | } 30 | } 31 | 32 | java { 33 | withJavadocJar() 34 | withSourcesJar() 35 | } 36 | 37 | publishing { 38 | publications { 39 | mavenJava(MavenPublication) { 40 | artifactId = 'modern-docking-single-app' 41 | from components.java 42 | versionMapping { 43 | usage('java-api') { 44 | fromResolutionOf('runtimeClasspath') 45 | } 46 | usage('java-runtime') { 47 | fromResolutionResult() 48 | } 49 | } 50 | pom { 51 | name = 'Java Modern Docking' 52 | description = 'Modern docking library for Java Swing, single app instance' 53 | url = 'https://github.com/andrewauclair/ModernDocking' 54 | licenses { 55 | license { 56 | name = 'The MIT License' 57 | url = 'https://opensource.org/licenses/MIT' 58 | } 59 | } 60 | developers { 61 | developer { 62 | id = 'andrewauclair' 63 | name = 'Andrew Auclair' 64 | email = 'mightymalakai33@gmail.com' 65 | } 66 | } 67 | scm { 68 | connection = 'scm:git:git//github.com/andrewauclair/ModernDocking.git' 69 | developerConnection = 'scm:git:ssh//github.com/andrewauclair/ModernDocking.git' 70 | url = 'https://github.com/andrewauclair/ModernDocking' 71 | } 72 | } 73 | } 74 | } 75 | } 76 | 77 | signing { 78 | required = { gradle.taskGraph.hasTask("publish") } 79 | sign publishing.publications.mavenJava 80 | } 81 | 82 | javadoc { 83 | if(JavaVersion.current().isJava9Compatible()) { 84 | options.addBooleanOption('html5', true) 85 | } 86 | } -------------------------------------------------------------------------------- /docking-api/src/io/github/andrewauclair/moderndocking/DockingProperty.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2023 Andrew Auclair 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | SOFTWARE. 21 | */ 22 | package io.github.andrewauclair.moderndocking; 23 | 24 | import java.lang.annotation.ElementType; 25 | import java.lang.annotation.Retention; 26 | import java.lang.annotation.RetentionPolicy; 27 | import java.lang.annotation.Target; 28 | 29 | /** 30 | * Java annotation used to indicate a field is a docking property and should be saved and restored when saving and loading layout files 31 | */ 32 | @Retention(RetentionPolicy.RUNTIME) 33 | @Target({ElementType.FIELD}) 34 | public @interface DockingProperty { 35 | /** 36 | * The name of the property. Used for saving to layout files 37 | * 38 | * @return Name of the property 39 | */ 40 | String name(); 41 | 42 | /** 43 | * Indicate that this property is required to properly initialize a dockable 44 | * 45 | * NOTE: Currently unused 46 | * 47 | * @return Is this property required when initializing dockables 48 | */ 49 | boolean required() default false; 50 | 51 | /** 52 | * The default value of the property 53 | * 54 | * @return Default value 55 | */ 56 | String defaultValue() default "__no_default_value__"; 57 | } 58 | -------------------------------------------------------------------------------- /docking-single-app/src/io/github/andrewauclair/moderndocking/app/LayoutsMenu.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2022 Andrew Auclair 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | SOFTWARE. 21 | */ 22 | package io.github.andrewauclair.moderndocking.app; 23 | 24 | import io.github.andrewauclair.moderndocking.event.DockingLayoutEvent; 25 | import io.github.andrewauclair.moderndocking.event.DockingLayoutListener; 26 | import io.github.andrewauclair.moderndocking.layouts.DockingLayouts; 27 | import javax.swing.JMenu; 28 | import javax.swing.JMenuItem; 29 | 30 | /** 31 | * Custom JMenu that displays all the layouts in DockingLayouts as menu items 32 | */ 33 | public class LayoutsMenu extends JMenu implements DockingLayoutListener { 34 | /** 35 | * Create a new layouts menu. Add a listener for when layouts change. 36 | */ 37 | public LayoutsMenu() { 38 | super("Layouts"); 39 | 40 | DockingLayouts.addLayoutsListener(this); 41 | 42 | rebuildOptions(); 43 | } 44 | private void rebuildOptions() { 45 | removeAll(); 46 | 47 | for (String name : DockingLayouts.getLayoutNames()) { 48 | JMenuItem item = new JMenuItem(name); 49 | item.addActionListener(e -> DockingState.restoreApplicationLayout(DockingLayouts.getLayout(name))); 50 | 51 | add(item); 52 | } 53 | } 54 | 55 | @Override 56 | public void layoutChange(DockingLayoutEvent e) { 57 | rebuildOptions(); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /demo-single-app/src/tests/TranslucentTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2023 Andrew Auclair 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | SOFTWARE. 21 | */ 22 | package tests; 23 | 24 | import java.awt.GraphicsDevice; 25 | import java.awt.GraphicsEnvironment; 26 | import javax.swing.JFrame; 27 | import javax.swing.SwingUtilities; 28 | 29 | import static java.awt.GraphicsDevice.WindowTranslucency.PERPIXEL_TRANSLUCENT; 30 | import static java.awt.GraphicsDevice.WindowTranslucency.PERPIXEL_TRANSPARENT; 31 | import static java.awt.GraphicsDevice.WindowTranslucency.TRANSLUCENT; 32 | 33 | public class TranslucentTest extends JFrame { 34 | public TranslucentTest() { 35 | // Determine what the default GraphicsDevice can support. 36 | GraphicsEnvironment ge = 37 | GraphicsEnvironment.getLocalGraphicsEnvironment(); 38 | GraphicsDevice gd = ge.getDefaultScreenDevice(); 39 | 40 | System.out.println("Is uniform translucency supported: " + gd.isWindowTranslucencySupported(TRANSLUCENT)); 41 | System.out.println("Is per-pixel translucency supported: " + gd.isWindowTranslucencySupported(PERPIXEL_TRANSLUCENT)); 42 | System.out.println("Is shaped window supported: " + gd.isWindowTranslucencySupported(PERPIXEL_TRANSPARENT)); 43 | } 44 | 45 | public static void main(String[] args) { 46 | SwingUtilities.invokeLater(() -> new TranslucentTest().setVisible(true)); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /docking-multi-app/src/io/github/andrewauclair/moderndocking/app/LayoutsMenu.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2022 Andrew Auclair 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | SOFTWARE. 21 | */ 22 | package io.github.andrewauclair.moderndocking.app; 23 | 24 | import io.github.andrewauclair.moderndocking.api.DockingAPI; 25 | import io.github.andrewauclair.moderndocking.event.DockingLayoutEvent; 26 | import io.github.andrewauclair.moderndocking.event.DockingLayoutListener; 27 | import io.github.andrewauclair.moderndocking.layouts.DockingLayouts; 28 | import javax.swing.JMenu; 29 | import javax.swing.JMenuItem; 30 | 31 | /** 32 | * Custom JMenu that displays all the layouts in DockingLayouts as menu items 33 | */ 34 | public class LayoutsMenu extends JMenu implements DockingLayoutListener { 35 | private final DockingAPI docking; 36 | 37 | /** 38 | * Create a new layouts menu. Add a listener for when layouts change. 39 | */ 40 | public LayoutsMenu(DockingAPI docking) { 41 | super("Layouts"); 42 | this.docking = docking; 43 | 44 | DockingLayouts.addLayoutsListener(this); 45 | 46 | rebuildOptions(); 47 | } 48 | private void rebuildOptions() { 49 | removeAll(); 50 | 51 | for (String name : DockingLayouts.getLayoutNames()) { 52 | JMenuItem item = new JMenuItem(name); 53 | item.addActionListener(e -> docking.getDockingState().restoreApplicationLayout(DockingLayouts.getLayout(name))); 54 | 55 | add(item); 56 | } 57 | } 58 | 59 | @Override 60 | public void layoutChange(DockingLayoutEvent e) { 61 | rebuildOptions(); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /docking-api/src/io/github/andrewauclair/moderndocking/layouts/DockingLayoutNode.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2022 Andrew Auclair 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | SOFTWARE. 21 | */ 22 | package io.github.andrewauclair.moderndocking.layouts; 23 | 24 | import io.github.andrewauclair.moderndocking.DockingRegion; 25 | 26 | /** 27 | * Base interface for docking layout nodes, simple, split, tab and empty 28 | */ 29 | public interface DockingLayoutNode { 30 | /** 31 | * Find a node in the layout 32 | * 33 | * @param persistentID Persistent ID to search for 34 | * @return The layout node, if found. null if not found. 35 | */ 36 | DockingLayoutNode findNode(String persistentID); 37 | 38 | /** 39 | * Dock a new persistent ID into this node 40 | * 41 | * @param persistentID Persistent ID of dockable to add 42 | * @param region Region to dock into 43 | * @param dividerProportion Proportion to use if in a splitpane 44 | */ 45 | void dock(String persistentID, DockingRegion region, double dividerProportion); 46 | 47 | /** 48 | * Replace an existing layout node child 49 | * 50 | * @param child Child to replace 51 | * @param newChild Child to add 52 | */ 53 | void replaceChild(DockingLayoutNode child, DockingLayoutNode newChild); 54 | 55 | /** 56 | * Get the parent of this node 57 | * 58 | * @return Parent of node, null if root. 59 | */ 60 | DockingLayoutNode getParent(); 61 | 62 | /** 63 | * Set the parent of this node 64 | * 65 | * @param parent New parent 66 | */ 67 | void setParent(DockingLayoutNode parent); 68 | } 69 | -------------------------------------------------------------------------------- /.github/workflows/publish.yml: -------------------------------------------------------------------------------- 1 | # This workflow uses actions that are not certified by GitHub. 2 | # They are provided by a third-party and are governed by 3 | # separate terms of service, privacy policy, and support 4 | # documentation. 5 | 6 | # GitHub recommends pinning actions to a commit SHA. 7 | # To get a newer version, you will need to update the SHA. 8 | # You can also reference a tag or branch, but the action may change without warning. 9 | 10 | name: Publish package to the Maven Central Repository 11 | on: 12 | release: 13 | types: [created] 14 | jobs: 15 | publish: 16 | runs-on: ubuntu-latest 17 | steps: 18 | - uses: actions/checkout@v4 19 | - name: Set up Java 20 | uses: actions/setup-java@v4 21 | with: 22 | java-version: '21' 23 | distribution: 'temurin' 24 | server-id: ossrh # Value of the distributionManagement/repository/id field of the pom.xml 25 | server-username: MAVEN_USERNAME # env variable for username in deploy 26 | server-password: MAVEN_PASSWORD # env variable for token in deploy 27 | gpg-private-key: ${{ secrets.OSSRH_SECRET_KEY }} # Value of the GPG private key to import 28 | gpg-passphrase: MAVEN_GPG_PASSPHRASE # env variable for GPG private key passphrase 29 | - name: GPG Setup 30 | run: | 31 | # Install gpg secret key 32 | cat <(echo -e "${{ secrets.OSSRH_GPG_SECRET_KEY }}") | gpg --batch --import 33 | # Verify gpg secret key 34 | GPG_KEYID=$(gpg -K) 35 | gpg --list-secret-keys --keyid-format LONG 36 | gpg --pinentry-mode=loopback --yes --passphrase "${{ secrets.OSSRH_GPG_SECRET_KEY_PASSWORD }}" --keyring secring.gpg --export-secret-keys > /home/runner/.gnupg/secring.gpg 37 | - name: Validate Gradle wrapper 38 | uses: gradle/actions/wrapper-validation@v4 39 | - name: Setup Gradle 40 | uses: gradle/actions/setup-gradle@v3 41 | - name: Publish package 42 | run: ./gradlew publishToSonatype closeAndReleaseSonatypeStagingRepository -Psigning.secretKeyRingFile=/home/runner/.gnupg/secring.gpg -Psigning.password=${{ secrets.OSSRH_GPG_SECRET_KEY_PASSWORD }} -Psigning.keyId=${{ secrets.OSSRH_GPG_KEY_ID }} 43 | env: 44 | ORG_GRADLE_PROJECT_sonatypeUsername: ${{ secrets.OSSRH_USERNAME }} 45 | ORG_GRADLE_PROJECT_sonatypePassword: ${{ secrets.OSSRH_TOKEN }} 46 | MAVEN_USERNAME: ${{ secrets.OSSRH_USERNAME }} 47 | MAVEN_PASSWORD: ${{ secrets.OSSRH_TOKEN }} 48 | MAVEN_GPG_PASSPHRASE: ${{ secrets.OSSRH_GPG_SECRET_KEY_PASSWORD }} 49 | -------------------------------------------------------------------------------- /docking-api/src/io/github/andrewauclair/moderndocking/internal/util/CombinedIcon.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2023 Andrew Auclair 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | SOFTWARE. 21 | */ 22 | package io.github.andrewauclair.moderndocking.internal.util; 23 | 24 | import java.awt.Component; 25 | import java.awt.Graphics; 26 | import javax.swing.Icon; 27 | 28 | /** 29 | * Special Icon to combine multiple Icons. 30 | *

31 | * We use this to combine an image icon and rotated text icon on West/East docking toolbars 32 | */ 33 | public class CombinedIcon implements Icon { 34 | /** 35 | * The amount of padding to add between the two icons 36 | */ 37 | private static final int PADDING = 2; 38 | 39 | private final Icon top; 40 | private final Icon bottom; 41 | 42 | /** 43 | * Create a new CombinedIcon 44 | * 45 | * @param top The icon to display on the top 46 | * @param bottom The icon to display on the bottom 47 | */ 48 | public CombinedIcon(Icon top, Icon bottom) { 49 | this.top = top; 50 | this.bottom = bottom; 51 | } 52 | 53 | @Override 54 | public int getIconHeight() { 55 | return top.getIconHeight() + PADDING + bottom.getIconHeight(); 56 | } 57 | 58 | @Override 59 | public int getIconWidth() { 60 | return Math.max(top.getIconWidth(), bottom.getIconWidth()); 61 | } 62 | 63 | @Override 64 | public void paintIcon(Component c, Graphics g, int x, int y) { 65 | top.paintIcon(c, g, x, y); 66 | bottom.paintIcon(c, g, x, y + PADDING + top.getIconHeight()); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /docking-api/src/io/github/andrewauclair/moderndocking/DynamicDockableParameters.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2025 Andrew Auclair 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | SOFTWARE. 21 | */ 22 | package io.github.andrewauclair.moderndocking; 23 | 24 | /** 25 | * Parameters passed to the constructor of a dynamic dockable 26 | */ 27 | public class DynamicDockableParameters { 28 | private final String persistentID; 29 | private final String tabText; 30 | private final String titleText; 31 | 32 | /** 33 | * Create a new instance 34 | * 35 | * @param persistentID Persistent ID of the dynamic dockable 36 | * @param tabText Tab text of the dynamic dockable 37 | * @param titleText Title text of the dynamic dockable 38 | */ 39 | public DynamicDockableParameters(String persistentID, String tabText, String titleText) { 40 | this.persistentID = persistentID; 41 | this.tabText = tabText; 42 | this.titleText = titleText; 43 | } 44 | 45 | /** 46 | * The persistent ID of the dynamic dockable under construction 47 | * 48 | * @return Persistent ID 49 | */ 50 | public String getPersistentID() { 51 | return persistentID; 52 | } 53 | 54 | /** 55 | * Get the tab text of the dynamic dockable under construction 56 | * 57 | * @return Tab text 58 | */ 59 | public String getTabText() { 60 | return tabText; 61 | } 62 | 63 | /** 64 | * Get the title text of the dynamic dockable under construction 65 | * 66 | * @return Title text 67 | */ 68 | public String getTitleText() { 69 | return titleText; 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /docking-api/src/io/github/andrewauclair/moderndocking/internal/util/SlideBorder.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2022 Andrew Auclair 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | SOFTWARE. 21 | */ 22 | package io.github.andrewauclair.moderndocking.internal.util; 23 | 24 | import io.github.andrewauclair.moderndocking.ui.ToolbarLocation; 25 | import java.awt.Cursor; 26 | import java.awt.Dimension; 27 | import javax.swing.JPanel; 28 | 29 | /** 30 | * Panel that provides a slider for unpinned dockables when they are displayed 31 | */ 32 | public class SlideBorder extends JPanel { 33 | /** 34 | * The location of the toolbar that this slide border is for. Used to determine the correct orientation of the panel 35 | */ 36 | private final ToolbarLocation location; 37 | 38 | /** 39 | * Create a SlideBorder with the given toolbar location 40 | * 41 | * @param location Location of the toolbar 42 | */ 43 | public SlideBorder(ToolbarLocation location) { 44 | this.location = location; 45 | setCursor(location == ToolbarLocation.SOUTH ? Cursor.getPredefinedCursor(Cursor.N_RESIZE_CURSOR) : Cursor.getPredefinedCursor(Cursor.E_RESIZE_CURSOR)); 46 | } 47 | 48 | @Override 49 | public Dimension getMinimumSize() { 50 | Dimension size = super.getMinimumSize(); 51 | if (location == ToolbarLocation.SOUTH) { 52 | size.height = 6; 53 | } 54 | else { 55 | size.width = 6; 56 | } 57 | return size; 58 | } 59 | 60 | @Override 61 | public Dimension getPreferredSize() { 62 | Dimension size = super.getPreferredSize(); 63 | if (location == ToolbarLocation.SOUTH) { 64 | size.height = 6; 65 | } 66 | else { 67 | size.width = 6; 68 | } 69 | return size; 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /docking-api/src/io/github/andrewauclair/moderndocking/event/NewFloatingFrameListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2025 Andrew Auclair 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | SOFTWARE. 21 | */ 22 | package io.github.andrewauclair.moderndocking.event; 23 | 24 | import io.github.andrewauclair.moderndocking.Dockable; 25 | import io.github.andrewauclair.moderndocking.api.RootDockingPanelAPI; 26 | import javax.swing.JFrame; 27 | 28 | /** 29 | * Used to inform the application that a new floating frame has been created 30 | */ 31 | public interface NewFloatingFrameListener { 32 | /** 33 | * Called when a new floating frame is created when restoring a window layout or when dropping a tab group of dockables 34 | *

35 | * NOTE: Modern Docking will close and dispose of all FloatingFrames it creates 36 | * 37 | * @param frame The new floating frame created by Modern Docking 38 | * @param root The root panel of the frame. Provided in case the application wishes to rebuild the layout 39 | */ 40 | void newFrameCreated(JFrame frame, RootDockingPanelAPI root); 41 | 42 | /** 43 | * Called when a new floating frame is created by ModernDocking. The frame will already be visible 44 | * and the dockable will already be docked. 45 | *

46 | * NOTE: ModernDocking will close and dispose of all FloatingFrames it creates 47 | * 48 | * @param frame The new floating frame created by Modern Docking 49 | * @param root The root panel of the frame. Provided in case the application wishes to rebuild the layout 50 | * @param dockable The dockable that this floating frame was created for and that is currently docked in the frame 51 | */ 52 | void newFrameCreated(JFrame frame, RootDockingPanelAPI root, Dockable dockable); 53 | } 54 | -------------------------------------------------------------------------------- /demo-single-app/src/basic/DialogWithDocking.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2023 Andrew Auclair 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | SOFTWARE. 21 | */ 22 | package basic; 23 | 24 | import io.github.andrewauclair.moderndocking.DockableStyle; 25 | import io.github.andrewauclair.moderndocking.DockingRegion; 26 | import io.github.andrewauclair.moderndocking.api.RootDockingPanelAPI; 27 | import io.github.andrewauclair.moderndocking.app.Docking; 28 | import io.github.andrewauclair.moderndocking.app.RootDockingPanel; 29 | import javax.swing.JDialog; 30 | 31 | public class DialogWithDocking extends JDialog { 32 | 33 | private final RootDockingPanelAPI root; 34 | private final ToolPanel output; 35 | private final ToolPanel explorer; 36 | private final SimplePanel one; 37 | 38 | DialogWithDocking() { 39 | root = new RootDockingPanel(this); 40 | 41 | setModalityType(ModalityType.TOOLKIT_MODAL); 42 | 43 | add(root); 44 | 45 | output = new ToolPanel("output", "output-dialog", DockableStyle.HORIZONTAL); 46 | explorer = new ToolPanel("explorer", "explorer-dialog", DockableStyle.VERTICAL); 47 | 48 | one = new SimplePanel("The First Panel", "one", "one-dialog"); 49 | 50 | output.limitToWindow = true; 51 | explorer.limitToWindow = true; 52 | one.limitToWindow = true; 53 | 54 | Docking.dock(one, this); 55 | Docking.dock(explorer, one, DockingRegion.EAST); 56 | Docking.dock(output, this, DockingRegion.SOUTH); 57 | 58 | setSize(500, 500); 59 | pack(); 60 | 61 | setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE); 62 | } 63 | 64 | @Override 65 | public void removeNotify() { 66 | Docking.deregisterDockingPanel(this); 67 | 68 | Docking.deregisterDockable(output); 69 | Docking.deregisterDockable(explorer); 70 | Docking.deregisterDockable(one); 71 | 72 | super.removeNotify(); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /docking-api/src/io/github/andrewauclair/moderndocking/internal/FailedDockable.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2022 Andrew Auclair 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | SOFTWARE. 21 | */ 22 | package io.github.andrewauclair.moderndocking.internal; 23 | 24 | import io.github.andrewauclair.moderndocking.Dockable; 25 | import io.github.andrewauclair.moderndocking.api.DockingAPI; 26 | import javax.swing.JPanel; 27 | 28 | /** 29 | * Represents a dockable that has failed to load from a layout file. 30 | *

31 | * These are stripped out after restoring from the layout. 32 | */ 33 | public class FailedDockable extends JPanel implements Dockable { 34 | /** 35 | * The docking instance this failed dockable belongs to 36 | */ 37 | private final DockingAPI docking; 38 | /** 39 | * Persistent ID that no dockable has been registered for 40 | */ 41 | private final String persistentID; 42 | 43 | /** 44 | * Create a new FailedDockable 45 | * 46 | * @param docking The docking instance this failed dockable belongs to 47 | * @param persistentID Persistent ID that has failed to load 48 | */ 49 | public FailedDockable(DockingAPI docking, String persistentID) { 50 | this.docking = docking; 51 | this.persistentID = persistentID; 52 | 53 | docking.registerDockable(this); 54 | } 55 | 56 | /** 57 | * Deregister this dockable 58 | */ 59 | public void destroy() { 60 | docking.deregisterDockable(this); 61 | } 62 | 63 | @Override 64 | public String getPersistentID() { 65 | return persistentID; 66 | } 67 | 68 | @Override 69 | public int getType() { 70 | return 0; 71 | } 72 | 73 | @Override 74 | public String getTabText() { 75 | return "Failed"; 76 | } 77 | 78 | @Override 79 | public boolean isFloatingAllowed() { 80 | return false; 81 | } 82 | 83 | @Override 84 | public boolean isClosable() { 85 | return false; 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /docking-api/src/io/github/andrewauclair/moderndocking/exception/RootDockingPanelRegistrationFailureException.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2024 Andrew Auclair 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | SOFTWARE. 21 | */ 22 | package io.github.andrewauclair.moderndocking.exception; 23 | 24 | import io.github.andrewauclair.moderndocking.api.RootDockingPanelAPI; 25 | import java.awt.Window; 26 | 27 | /** 28 | * This exception is thrown when the docking framework fails to register a RootDockingPanel because one already exists for the window 29 | */ 30 | public class RootDockingPanelRegistrationFailureException extends RuntimeException { 31 | /** 32 | * The root docking panel that the application attempted to register 33 | */ 34 | private final RootDockingPanelAPI panel; 35 | /** 36 | * The window that already has a root docking panel registered for it 37 | */ 38 | private final Window window; 39 | 40 | /** 41 | * Create a new instance of this exception 42 | * 43 | * @param panel The RootDockingPanel being registered 44 | * @param window The window the root is being registered for 45 | */ 46 | public RootDockingPanelRegistrationFailureException(RootDockingPanelAPI panel, Window window) { 47 | super("RootDockingPanel already registered for frame: " + window); 48 | this.panel = panel; 49 | this.window = window; 50 | } 51 | 52 | /** 53 | * Retrieve the panel that failed to register 54 | * 55 | * @return The RootDockingPanel being registered 56 | */ 57 | public RootDockingPanelAPI getPanel() { 58 | return panel; 59 | } 60 | 61 | /** 62 | * Retrieve the window the root was being registered for 63 | * 64 | * @return The window the root is being registered for 65 | */ 66 | public Window getWindow() { 67 | return window; 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /docking-ui/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'java' 3 | id 'java-library' 4 | id 'idea' 5 | id 'maven-publish' 6 | id 'signing' 7 | id "com.github.ben-manes.versions" version "0.52.0" 8 | } 9 | 10 | java { 11 | sourceCompatibility = JavaVersion.VERSION_11 12 | targetCompatibility = JavaVersion.VERSION_11 13 | } 14 | 15 | sourceSets.main.java.srcDirs = ['src'] 16 | sourceSets.main.resources.srcDirs = ['resources'] 17 | 18 | base { 19 | group = "io.github.andrewauclair" 20 | archivesName = "modern-docking-ui" 21 | } 22 | 23 | dependencies { 24 | if (project.hasProperty("useMavenVersion")) { 25 | implementation 'io.github.andrewauclair:modern-docking-api:' + version 26 | } 27 | else { 28 | api project(':docking-api') 29 | } 30 | 31 | implementation 'com.formdev:flatlaf:' + flatLafVersion 32 | implementation 'com.formdev:flatlaf-extras:' + flatLafVersion 33 | } 34 | 35 | repositories { 36 | mavenCentral() 37 | } 38 | 39 | java { 40 | withJavadocJar() 41 | withSourcesJar() 42 | } 43 | 44 | publishing { 45 | publications { 46 | mavenJava(MavenPublication) { 47 | artifactId = 'modern-docking-ui' 48 | from components.java 49 | versionMapping { 50 | usage('java-api') { 51 | fromResolutionOf('runtimeClasspath') 52 | } 53 | usage('java-runtime') { 54 | fromResolutionResult() 55 | } 56 | } 57 | pom { 58 | name = 'Java Modern Docking UI' 59 | description = 'UI extension to Modern Docking' 60 | url = 'https://github.com/andrewauclair/ModernDocking' 61 | licenses { 62 | license { 63 | name = 'The MIT License' 64 | url = 'https://opensource.org/licenses/MIT' 65 | } 66 | } 67 | developers { 68 | developer { 69 | id = 'andrewauclair' 70 | name = 'Andrew Auclair' 71 | email = 'mightymalakai33@gmail.com' 72 | } 73 | } 74 | scm { 75 | connection = 'scm:git:git//github.com/andrewauclair/ModernDocking.git' 76 | developerConnection = 'scm:git:ssh//github.com/andrewauclair/ModernDocking.git' 77 | url = 'https://github.com/andrewauclair/ModernDocking' 78 | } 79 | } 80 | } 81 | } 82 | repositories { 83 | maven { 84 | credentials { 85 | username = System.getenv("MAVEN_USERNAME") 86 | password = System.getenv("MAVEN_PASSWORD") 87 | } 88 | 89 | url = version.endsWith('SNAPSHOT') ? 90 | 'https://central.sonatype.com/repository/maven-snapshots/' 91 | : 'https://ossrh-staging-api.central.sonatype.com/service/local/staging/deploy/maven2/' 92 | } 93 | } 94 | } 95 | 96 | signing { 97 | required = { gradle.taskGraph.hasTask("publish") } 98 | sign publishing.publications.mavenJava 99 | } 100 | 101 | javadoc { 102 | if(JavaVersion.current().isJava9Compatible()) { 103 | options.addBooleanOption('html5', true) 104 | } 105 | } -------------------------------------------------------------------------------- /docking-api/src/io/github/andrewauclair/moderndocking/exception/DockingLayoutException.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2023-2024 Andrew Auclair 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | SOFTWARE. 21 | */ 22 | package io.github.andrewauclair.moderndocking.exception; 23 | 24 | import java.io.File; 25 | 26 | /** 27 | * Exception wrapper for exceptions encountered while dealing loading or saving docking layouts 28 | */ 29 | public class DockingLayoutException extends Exception { 30 | /** 31 | * The type of failure for the exception 32 | */ 33 | public enum FailureType { 34 | /** 35 | * A docking layout has failed to load from a file 36 | */ 37 | LOAD, 38 | /** 39 | * A docking layout has failed to save to a file 40 | */ 41 | SAVE 42 | } 43 | 44 | /** 45 | * The file that we attempted to load or save 46 | */ 47 | private final File file; 48 | 49 | /** 50 | * The type of failure. load or save 51 | */ 52 | private final FailureType failureType; 53 | 54 | /** 55 | * Create a new instance 56 | * 57 | * @param file The layout file that was being saved or loaded 58 | * @param failureType The state we failed in, loading or saving 59 | * @param cause The root cause of the exception 60 | */ 61 | public DockingLayoutException(File file, FailureType failureType, Exception cause) { 62 | initCause(cause); 63 | 64 | this.file = file; 65 | this.failureType = failureType; 66 | } 67 | 68 | /** 69 | * Retrieve the file being loaded or saved 70 | * 71 | * @return File the framework attempted to load or save 72 | */ 73 | public File getFile() { 74 | return file; 75 | } 76 | 77 | /** 78 | * Retrieve the failure type 79 | * 80 | * @return Returns the failure type of this exception 81 | */ 82 | public FailureType getFailureType() { 83 | return failureType; 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /docking-api/src/io/github/andrewauclair/moderndocking/internal/AppStatePersister.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2022 Andrew Auclair 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | SOFTWARE. 21 | */ 22 | package io.github.andrewauclair.moderndocking.internal; 23 | 24 | import io.github.andrewauclair.moderndocking.api.DockingAPI; 25 | import java.awt.Window; 26 | import java.awt.event.ComponentAdapter; 27 | import java.awt.event.ComponentEvent; 28 | import java.awt.event.WindowEvent; 29 | import java.awt.event.WindowStateListener; 30 | 31 | /** 32 | * simple internal class that calls AppState.persist() whenever a frame resizes, moves or changes state 33 | */ 34 | public class AppStatePersister extends ComponentAdapter implements WindowStateListener { 35 | private final DockingAPI docking; 36 | 37 | /** 38 | * Create a new persister for the docking instance 39 | * 40 | * @param docking Docking instance 41 | */ 42 | public AppStatePersister(DockingAPI docking) { 43 | this.docking = docking; 44 | } 45 | /** 46 | * Add a window to this persister. The persister will listen for any changes to the window and trigger the 47 | * auto persistence. 48 | * 49 | * @param window The window to add 50 | */ 51 | public void addWindow(Window window) { 52 | window.addComponentListener(this); 53 | window.addWindowStateListener(this); 54 | } 55 | 56 | /** 57 | * Remove a window from this persister. This will stop the persister from listening to events. 58 | * 59 | * @param window The window to remove 60 | */ 61 | public void removeWindow(Window window) { 62 | window.removeComponentListener(this); 63 | window.removeWindowStateListener(this); 64 | } 65 | 66 | @Override 67 | public void componentResized(ComponentEvent e) { 68 | docking.getAppState().persist(); 69 | } 70 | 71 | @Override 72 | public void componentMoved(ComponentEvent e) { 73 | docking.getAppState().persist(); 74 | } 75 | 76 | @Override 77 | public void windowStateChanged(WindowEvent e) { 78 | docking.getAppState().persist(); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /demo-multi-app/src/basic/ToolPanel.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2022 Andrew Auclair 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | SOFTWARE. 21 | */ 22 | package basic; 23 | 24 | import io.github.andrewauclair.moderndocking.DockableStyle; 25 | import io.github.andrewauclair.moderndocking.api.DockingAPI; 26 | import javax.swing.Icon; 27 | import javax.swing.JMenuItem; 28 | import javax.swing.JPopupMenu; 29 | 30 | public class ToolPanel extends BasePanel { 31 | private final DockableStyle style; 32 | private final Icon icon; 33 | 34 | public boolean limitToWindow = false; 35 | 36 | public ToolPanel(DockingAPI docking, String title, String persistentID, DockableStyle style) { 37 | super(docking, title, persistentID); 38 | this.style = style; 39 | this.icon = null; 40 | } 41 | 42 | public ToolPanel(DockingAPI docking, String title, String persistentID, DockableStyle style, Icon icon) { 43 | super(docking, title, persistentID); 44 | this.style = style; 45 | this.icon = icon; 46 | 47 | 48 | } 49 | 50 | @Override 51 | public int getType() { 52 | return 0; 53 | } 54 | 55 | @Override 56 | public Icon getIcon() { 57 | return icon; 58 | } 59 | 60 | @Override 61 | public boolean isFloatingAllowed() { 62 | return false; 63 | } 64 | 65 | @Override 66 | public boolean isLimitedToWindow() { 67 | return limitToWindow; 68 | } 69 | 70 | @Override 71 | public DockableStyle getStyle() { 72 | return style; 73 | } 74 | 75 | @Override 76 | public boolean isClosable() { 77 | return true; 78 | } 79 | 80 | @Override 81 | public boolean isAutoHideAllowed() { 82 | return true; 83 | } 84 | 85 | @Override 86 | public boolean isMinMaxAllowed() { 87 | return false; 88 | } 89 | 90 | @Override 91 | public boolean hasMoreMenuOptions() { 92 | return true; 93 | } 94 | 95 | @Override 96 | public void addMoreOptions(JPopupMenu menu) { 97 | menu.add(new JMenuItem("Something")); 98 | menu.add(new JMenuItem("Else")); 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /docking-api/src/io/github/andrewauclair/moderndocking/event/DockingLayoutEvent.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2023 Andrew Auclair 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | SOFTWARE. 21 | */ 22 | package io.github.andrewauclair.moderndocking.event; 23 | 24 | import io.github.andrewauclair.moderndocking.layouts.ApplicationLayout; 25 | 26 | /** 27 | * Event used when the application layout has changed 28 | */ 29 | public class DockingLayoutEvent { 30 | /** 31 | * The ID of the layout event 32 | */ 33 | public enum ID { 34 | /** 35 | * Layout has been added 36 | */ 37 | ADDED, 38 | /** 39 | * Layout has been removed 40 | */ 41 | REMOVED, 42 | /** 43 | * Layout has been restored 44 | */ 45 | RESTORED, 46 | /** 47 | * Layout has been saved to a file 48 | */ 49 | PERSISTED 50 | } 51 | 52 | private final ID id; 53 | private final String layoutName; 54 | private final ApplicationLayout layout; 55 | 56 | /** 57 | * Create a new docking layout event 58 | * 59 | * @param id ID of event that has occurred 60 | * @param layoutName The name of the layout changed 61 | * @param layout The application layout that changed 62 | */ 63 | public DockingLayoutEvent(ID id, String layoutName, ApplicationLayout layout) { 64 | this.id = id; 65 | this.layoutName = layoutName; 66 | this.layout = layout; 67 | } 68 | 69 | /** 70 | * The ID of this event 71 | * 72 | * @return Event ID 73 | */ 74 | public ID getID() { 75 | return id; 76 | } 77 | 78 | /** 79 | * The name of the layout in this event 80 | * 81 | * @return Layout name 82 | */ 83 | public String getLayoutName() { 84 | return layoutName; 85 | } 86 | 87 | /** 88 | * The application layout in this event 89 | * 90 | * @return Application layout 91 | */ 92 | public ApplicationLayout getLayout() { 93 | return layout; 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /Writerside/topics/User-Facing-Features.md: -------------------------------------------------------------------------------- 1 | # User Facing Features 2 | 3 | Users of your application will interact with several UI components provided by Modern Docking. 4 | The framework is built around using Java Swing's `JTabbedPane` and `JSplitPane` to provide the docking layouts. 5 | The positioning of the applications dockable components within these `JTabbedPane`s and `JSplitPane`s is done by dragging the dockables. 6 | When the dockable is being dragged it will float above the window of the application and show Docking Handles and Docking Regions. 7 | Docking Handles allow the user to place the dockable precisely where they want it and Docking Regions provide extra visual feedback of this action. 8 | Docking Regions are also a quick way to "snap" dockables into place without needing to precisely drag to a Docking Handle. 9 | 10 | ## Using Docking Handles to Dock 11 | When dragging a dockable hovering over another dockable will display docking handles in the center of the dockable. 12 | These handles provide easy access to dock to the North, South, East and West regions. 13 | 14 | 15 | 16 | ![Docking Handles](docking_handles.gif) 17 | 18 | The dockable can also be docked to any of these regions by hovering over the region itself and dropping the dockable. 19 | 20 | 21 | ![Docking Regions](docking_regions.gif) 22 | 23 | The root also has North, South, East and West handles to dock the dockable directly to the root of the panel. 24 | 25 | 26 | ![Root Docking Handles](root_docking_handles.gif) 27 | 28 | ## Adjusting Split 29 | Splits can be adjusted and perform continuous layout. Double-clicking the split will return it to 50-50 split for the 2 sides. 30 | 31 | 32 | ![Adjusting Splits](adjusting_split.gif) 33 | 34 | ## Creating Tab Group 35 | Panels can be grouped into tabbed panes by dragging a dockable to the center region of another dockable. 36 | 37 | 38 | ![Creating Tab Group](creating_tab_group.gif) 39 | 40 | ## Closing Panels 41 | Panels can be closed using the X button on their headers. This option can be disabled in the source code. 42 | 43 | 44 | ![Closing Panels](close_panel.gif) 45 | 46 | ## Floating a Panel 47 | Panels can be floated as their own window by dragging them by their header and dropping them outside the frame. 48 | This creates a new JFrame with the dockable in it. More dockables can then be docked to this dockable. 49 | 50 | 51 | ![Floating Panels](floating_panel.gif) 52 | 53 | ## Auto Hide a Panel 54 | Panels can be set to Auto Hide with View Mode > Auto Hide from the settings button on the panel header. 55 | This option will display the panel on a side toolbar as a button which can be pressed to display the panel. 56 | Clicking the button again, or clicking off the panel, will return it to the toolbar. To return the panel to 57 | normal, select the View Mode > Auto Hide option again to deselect it. 58 | 59 | ![Auto Hide Panel](pinning_panel.gif) 60 | 61 | 62 | ## Option Panel in New Window 63 | Panels can be opened in their own window using View Mode > Window. 64 | 65 | ![New Window](new_window.gif) 66 | 67 | 68 | ## Additional Settings Options 69 | Display custom settings options on the settings menu. 70 | 71 | 72 | ![Additional Settings Options](has_more_options.gif) -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Modern Docking 2 | 3 | [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) 4 | 5 | [![Maven Central](https://img.shields.io/maven-central/v/io.github.andrewauclair/modern-docking-api?label=modern-docking-api)](https://mvnrepository.com/artifact/io.github.andrewauclair/modern-docking-api) 6 | 7 | [![Maven Central](https://img.shields.io/maven-central/v/io.github.andrewauclair/modern-docking-single-app?label=modern-docking-single-app)](https://mvnrepository.com/artifact/io.github.andrewauclair/modern-docking-single-app) 8 | [![Maven Central](https://img.shields.io/maven-central/v/io.github.andrewauclair/modern-docking-multi-app?label=modern-docking-multi-app)](https://mvnrepository.com/artifact/io.github.andrewauclair/modern-docking-multi-app) 9 | 10 | [![Maven Central](https://img.shields.io/maven-central/v/io.github.andrewauclair/modern-docking-ui?label=modern-docking-ui)](https://mvnrepository.com/artifact/io.github.andrewauclair/modern-docking-ui) 11 | 12 | 13 | Modern Docking is a simple framework designed for adding docking features to Java Swing applications. 14 | 15 | There are many existing Java Swing docking frameworks, but they are outdated and no longer maintained. The existing frameworks also suffer from complexity due to customization features. 16 | 17 | ### Snapshots 18 | 19 | Modern Docking snapshot binaries are available on 20 | [Sonatype Central Portal](https://central.sonatype.com/service/rest/repository/browse/maven-snapshots/io/github/andrewauclair/). 21 | To access the latest snapshot, change the Modern Docking version in your dependencies 22 | to `-SNAPSHOT` (e.g. `1.1-SNAPSHOT`) and add the repository 23 | `https://central.sonatype.com/repository/maven-snapshots/` to your build (see 24 | [Maven](https://maven.apache.org/guides/mini/guide-multiple-repositories.html) 25 | and 26 | [Gradle](https://docs.gradle.org/current/userguide/declaring_repositories.html#sec:declaring_custom_repository) 27 | docs). 28 | 29 | 30 | ## Features 31 | - Supports Java 11 and newer 32 | - Docking Component Interface 33 | - Docking Frames (Floating JFrame) 34 | - Docking Ports (One per frame) 35 | - Split Panels 36 | - Tabbed Panels 37 | - Visual Studio style drag floating and docking hints that show drop locations 38 | 39 | 40 | ## Modern Docking UI Extension 41 | - Requires FlatLaf L&F 42 | 43 | 44 | [![Maven Central](https://img.shields.io/maven-central/v/com.formdev/flatlaf)](https://mvnrepository.com/artifact/com.formdev/flatlaf) 45 | 46 | # Building 47 | 48 | Modern Docking uses Gradle and can be opened directly in IntelliJ IDEA or any other IDE that supports Gradle. It can also be built from the command line with `./gradlew build`. 49 | 50 | ## Examples 51 | See basic-demo for a simple example in Example.java and a more complicated example in MainFrame.java. 52 | 53 | ## Support 54 | Buy Me A Coffee 55 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | @rem SPDX-License-Identifier: Apache-2.0 17 | @rem 18 | 19 | @if "%DEBUG%"=="" @echo off 20 | @rem ########################################################################## 21 | @rem 22 | @rem Gradle startup script for Windows 23 | @rem 24 | @rem ########################################################################## 25 | 26 | @rem Set local scope for the variables with windows NT shell 27 | if "%OS%"=="Windows_NT" setlocal 28 | 29 | set DIRNAME=%~dp0 30 | if "%DIRNAME%"=="" set DIRNAME=. 31 | @rem This is normally unused 32 | set APP_BASE_NAME=%~n0 33 | set APP_HOME=%DIRNAME% 34 | 35 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 36 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 37 | 38 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 39 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 40 | 41 | @rem Find java.exe 42 | if defined JAVA_HOME goto findJavaFromJavaHome 43 | 44 | set JAVA_EXE=java.exe 45 | %JAVA_EXE% -version >NUL 2>&1 46 | if %ERRORLEVEL% equ 0 goto execute 47 | 48 | echo. 1>&2 49 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 50 | echo. 1>&2 51 | echo Please set the JAVA_HOME variable in your environment to match the 1>&2 52 | echo location of your Java installation. 1>&2 53 | 54 | goto fail 55 | 56 | :findJavaFromJavaHome 57 | set JAVA_HOME=%JAVA_HOME:"=% 58 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 59 | 60 | if exist "%JAVA_EXE%" goto execute 61 | 62 | echo. 1>&2 63 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 64 | echo. 1>&2 65 | echo Please set the JAVA_HOME variable in your environment to match the 1>&2 66 | echo location of your Java installation. 1>&2 67 | 68 | goto fail 69 | 70 | :execute 71 | @rem Setup the command line 72 | 73 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 74 | 75 | 76 | @rem Execute Gradle 77 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* 78 | 79 | :end 80 | @rem End local scope for the variables with windows NT shell 81 | if %ERRORLEVEL% equ 0 goto mainEnd 82 | 83 | :fail 84 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 85 | rem the _cmd.exe /c_ return code! 86 | set EXIT_CODE=%ERRORLEVEL% 87 | if %EXIT_CODE% equ 0 set EXIT_CODE=1 88 | if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% 89 | exit /b %EXIT_CODE% 90 | 91 | :mainEnd 92 | if "%OS%"=="Windows_NT" endlocal 93 | 94 | :omega 95 | -------------------------------------------------------------------------------- /docking-single-app/src/io/github/andrewauclair/moderndocking/app/ApplicationLayoutMenuItem.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2023 Andrew Auclair 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | SOFTWARE. 21 | */ 22 | package io.github.andrewauclair.moderndocking.app; 23 | 24 | import io.github.andrewauclair.moderndocking.layouts.ApplicationLayout; 25 | import io.github.andrewauclair.moderndocking.layouts.DockingLayouts; 26 | import java.awt.event.ActionEvent; 27 | import java.awt.event.ActionListener; 28 | import javax.swing.JMenuItem; 29 | import javax.swing.JOptionPane; 30 | 31 | /** 32 | * Special JMenuItem which will restore an ApplicationLayout when selected 33 | */ 34 | public class ApplicationLayoutMenuItem extends JMenuItem implements ActionListener { 35 | /** 36 | * The name of the ApplicationLayout, used to get the layout from DockingLayouts 37 | */ 38 | private final String layoutName; 39 | 40 | /** 41 | * Create a new ApplicationLayoutMenuItem for the specified layout. The layout name will be used as the display text. 42 | * 43 | * @param layoutName Name of the ApplicationLayout this ApplicationLayoutMenuItem will restore 44 | */ 45 | public ApplicationLayoutMenuItem(String layoutName) { 46 | super(layoutName); 47 | 48 | this.layoutName = layoutName; 49 | addActionListener(this); 50 | } 51 | 52 | /** 53 | * Create a new ApplicationLayoutMenuItem for the specified layout 54 | * 55 | * @param layoutName Name of the ApplicationLayout this ApplicationLayoutMenuItem will restore 56 | * @param text Display text of the JMenuItem 57 | */ 58 | public ApplicationLayoutMenuItem(String layoutName, String text) { 59 | super(text); 60 | 61 | this.layoutName = layoutName; 62 | addActionListener(this); 63 | } 64 | 65 | @Override 66 | public void actionPerformed(ActionEvent e) { 67 | ApplicationLayout layout = DockingLayouts.getLayout(layoutName); 68 | 69 | if (layout == null) { 70 | JOptionPane.showMessageDialog(this, "Layout " + layoutName + " does not exist."); 71 | } 72 | else { 73 | DockingState.restoreApplicationLayout(layout); 74 | } 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /demo-single-app/src/basic/ToolPanel.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2022 Andrew Auclair 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | SOFTWARE. 21 | */ 22 | package basic; 23 | 24 | import io.github.andrewauclair.moderndocking.DockableStyle; 25 | import javax.swing.Icon; 26 | import javax.swing.JMenuItem; 27 | import javax.swing.JOptionPane; 28 | import javax.swing.JPopupMenu; 29 | 30 | public class ToolPanel extends BasePanel { 31 | private final DockableStyle style; 32 | private final Icon icon; 33 | 34 | public boolean limitToWindow = false; 35 | 36 | public ToolPanel(String title, String persistentID, DockableStyle style) { 37 | super(title, title, persistentID); 38 | this.style = style; 39 | this.icon = null; 40 | } 41 | 42 | public ToolPanel(String title, String persistentID, DockableStyle style, Icon icon) { 43 | super(title, title, persistentID); 44 | this.style = style; 45 | this.icon = icon; 46 | 47 | 48 | } 49 | 50 | @Override 51 | public int getType() { 52 | return 0; 53 | } 54 | 55 | @Override 56 | public Icon getIcon() { 57 | return icon; 58 | } 59 | 60 | @Override 61 | public boolean isFloatingAllowed() { 62 | return false; 63 | } 64 | 65 | @Override 66 | public boolean isLimitedToWindow() { 67 | return limitToWindow; 68 | } 69 | 70 | @Override 71 | public DockableStyle getStyle() { 72 | return style; 73 | } 74 | 75 | @Override 76 | public DockableStyle getAutoHideStyle() { 77 | return style; 78 | } 79 | 80 | @Override 81 | public boolean isClosable() { 82 | return true; 83 | } 84 | 85 | @Override 86 | public boolean requestClose() { 87 | return JOptionPane.showConfirmDialog(null, "Are you sure you want to close this panel?", "Close Panel", JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION; 88 | } 89 | 90 | @Override 91 | public boolean isAutoHideAllowed() { 92 | return true; 93 | } 94 | 95 | @Override 96 | public boolean isMinMaxAllowed() { 97 | return false; 98 | } 99 | 100 | @Override 101 | public boolean hasMoreMenuOptions() { 102 | return true; 103 | } 104 | 105 | @Override 106 | public void addMoreOptions(JPopupMenu menu) { 107 | menu.add(new JMenuItem("Something")); 108 | menu.add(new JMenuItem("Else")); 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /docking-single-app/src/io/github/andrewauclair/moderndocking/app/LayoutPersistence.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2023 Andrew Auclair 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | SOFTWARE. 21 | */ 22 | package io.github.andrewauclair.moderndocking.app; 23 | 24 | import io.github.andrewauclair.moderndocking.api.LayoutPersistenceAPI; 25 | import io.github.andrewauclair.moderndocking.exception.DockingLayoutException; 26 | import io.github.andrewauclair.moderndocking.layouts.ApplicationLayout; 27 | import io.github.andrewauclair.moderndocking.layouts.WindowLayout; 28 | import java.io.File; 29 | 30 | /** 31 | * Persist and restore Application and Window layouts to/from files 32 | */ 33 | public class LayoutPersistence { 34 | private static final LayoutPersistenceAPI instance = new LayoutPersistenceAPI(Docking.getSingleInstance()){}; 35 | 36 | private LayoutPersistence() { 37 | } 38 | 39 | /** 40 | * saves a docking layout to the given file 41 | * 42 | * @param file File to save the docking layout into 43 | * @param layout The layout to save 44 | * @throws DockingLayoutException Thrown if we failed to save the layout to the file 45 | */ 46 | public static void saveLayoutToFile(File file, ApplicationLayout layout) throws DockingLayoutException { 47 | instance.saveLayoutToFile(file, layout); 48 | } 49 | 50 | /** 51 | * Load an ApplicationLayout from the specified file 52 | * 53 | * @param file File to load the ApplicationLayout from 54 | * @return ApplicationLayout loaded from the file 55 | * @throws DockingLayoutException Thrown if we failed to read from the file or something went wrong with loading the layout 56 | */ 57 | public static ApplicationLayout loadApplicationLayoutFromFile(File file) throws DockingLayoutException { 58 | return instance.loadApplicationLayoutFromFile(file); 59 | } 60 | 61 | public static boolean saveWindowLayoutToFile(File file, WindowLayout layout) { 62 | return instance.saveWindowLayoutToFile(file, layout); 63 | } 64 | 65 | /** 66 | * Load a WindowLayout from an XML file 67 | * 68 | * @param file File to load WindowLayout from 69 | * @return The loaded WindowLayout 70 | */ 71 | public static WindowLayout loadWindowLayoutFromFile(File file) { 72 | return instance.loadWindowLayoutFromFile(file); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /docking-multi-app/src/io/github/andrewauclair/moderndocking/app/ApplicationLayoutMenuItem.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2023 Andrew Auclair 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | SOFTWARE. 21 | */ 22 | package io.github.andrewauclair.moderndocking.app; 23 | 24 | import io.github.andrewauclair.moderndocking.api.DockingAPI; 25 | import io.github.andrewauclair.moderndocking.layouts.ApplicationLayout; 26 | import io.github.andrewauclair.moderndocking.layouts.DockingLayouts; 27 | import java.awt.event.ActionEvent; 28 | import java.awt.event.ActionListener; 29 | import javax.swing.JMenuItem; 30 | import javax.swing.JOptionPane; 31 | 32 | /** 33 | * Special JMenuItem which will restore an ApplicationLayout when selected 34 | */ 35 | public class ApplicationLayoutMenuItem extends JMenuItem implements ActionListener { 36 | private final DockingAPI docking; 37 | /** 38 | * The name of the ApplicationLayout, used to get the layout from DockingLayouts 39 | */ 40 | private final String layoutName; 41 | 42 | /** 43 | * Create a new ApplicationLayoutMenuItem for the specified layout. The layout name will be used as the display text. 44 | * 45 | * @param layoutName Name of the ApplicationLayout this ApplicationLayoutMenuItem will restore 46 | */ 47 | public ApplicationLayoutMenuItem(DockingAPI docking, String layoutName) { 48 | super(layoutName); 49 | this.docking = docking; 50 | 51 | this.layoutName = layoutName; 52 | addActionListener(this); 53 | } 54 | 55 | /** 56 | * Create a new ApplicationLayoutMenuItem for the specified layout 57 | * 58 | * @param layoutName Name of the ApplicationLayout this ApplicationLayoutMenuItem will restore 59 | * @param text Display text of the JMenuItem 60 | */ 61 | public ApplicationLayoutMenuItem(DockingAPI docking, String layoutName, String text) { 62 | super(text); 63 | this.docking = docking; 64 | 65 | this.layoutName = layoutName; 66 | addActionListener(this); 67 | } 68 | 69 | @Override 70 | public void actionPerformed(ActionEvent e) { 71 | ApplicationLayout layout = DockingLayouts.getLayout(layoutName); 72 | 73 | if (layout == null) { 74 | JOptionPane.showMessageDialog(this, "Layout " + layoutName + " does not exist."); 75 | } 76 | else { 77 | docking.getDockingState().restoreApplicationLayout(layout); 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /docking-single-app/src/io/github/andrewauclair/moderndocking/app/DockingState.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2023 Andrew Auclair 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | SOFTWARE. 21 | */ 22 | package io.github.andrewauclair.moderndocking.app; 23 | 24 | import io.github.andrewauclair.moderndocking.api.DockingStateAPI; 25 | import io.github.andrewauclair.moderndocking.layouts.ApplicationLayout; 26 | import io.github.andrewauclair.moderndocking.layouts.WindowLayout; 27 | import java.awt.Window; 28 | 29 | public class DockingState { 30 | private static final DockingStateAPI instance = new DockingStateAPI(Docking.getSingleInstance()){}; 31 | 32 | /** 33 | * This class should not be instantiated 34 | */ 35 | private DockingState() { 36 | } 37 | 38 | /** 39 | * Get the current window layout of a window 40 | * 41 | * @param window The window to get a layout for 42 | * 43 | * @return The window layout 44 | */ 45 | public static WindowLayout getWindowLayout(Window window) { 46 | return instance.getWindowLayout(window); 47 | } 48 | 49 | /** 50 | * Get the current application layout of the application 51 | * 52 | * @return Layout of the application 53 | */ 54 | public static ApplicationLayout getApplicationLayout() { 55 | return instance.getApplicationLayout(); 56 | } 57 | 58 | /** 59 | * Restore the application layout, creating any necessary windows 60 | * 61 | * @param layout Application layout to restore 62 | */ 63 | public static void restoreApplicationLayout(ApplicationLayout layout) { 64 | instance.restoreApplicationLayout(layout); 65 | } 66 | 67 | /** 68 | * Restore the layout of a single window 69 | * 70 | * @param window Window to restore the layout onto 71 | * @param layout The layout to restore 72 | */ 73 | public static void restoreWindowLayout(Window window, WindowLayout layout) { 74 | instance.restoreWindowLayout(window, layout); 75 | } 76 | 77 | /** 78 | * Restore the layout of a single window, preserving the current size and position of the window 79 | * 80 | * @param window Window to restore the layout onto 81 | * @param layout The layout to restore 82 | */ 83 | public static void restoreWindowLayout_PreserveSizeAndPos(Window window, WindowLayout layout) { 84 | instance.restoreWindowLayout_PreserveSizeAndPos(window, layout); 85 | } 86 | } 87 | --------------------------------------------------------------------------------