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.
Fired when layouts are added to or removed from DockingLayouts and when layouts are restored or persisted to a file
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 |Menu item specific to one layout. Simply displays the name and when clicked loads the layout with Docking.restore()
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 |Listen for when layouts are added to or removed from DockingLayouts and when layouts are restored or saved to a file
Listen for any changes to active dockables. This includes docking, undocking, shown, hidden, auto hide
8 |Listen for maximize events triggered by Docking.maximize
Listen for the creation of new floating frames. This allows the application to set icons, titles, menu bars, etc. on the new frame.
14 |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.
Used to call AppState.persist whenever a Window instance resizes, moves or changes state.
Thrown when a dockable is not found when restoring a DockingLayout
5 |DockingState.restoreStateThrown when a dockable with the persistentID has already been registered
Docking.registerDockableThis 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 |AppState.restore, LayoutPersistence.saveLayoutToFile and LayoutPersistence.loadApplicationLayoutFromFileThis 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 |Docking.dock and Docking.bringToFrontThrown when the root for a window is not found
21 |Docking.configurePinning, Docking.dock and DockingComponentUtils.rootForWindowThrown when Modern Docking fails to register a RootDockingPanel because one is already registered for the window
Docing.registerDockingPanel31 | * 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 | 
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 | 
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 | 
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 | 
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 | 
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 | 
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 | 
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 | 
60 |
61 |
62 | ## Option Panel in New Window
63 | Panels can be opened in their own window using View Mode > Window.
64 |
65 | 
66 |
67 |
68 | ## Additional Settings Options
69 | Display custom settings options on the settings menu.
70 |
71 |
72 | 
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Modern Docking
2 |
3 | [](https://opensource.org/licenses/MIT)
4 |
5 | [](https://mvnrepository.com/artifact/io.github.andrewauclair/modern-docking-api)
6 |
7 | [](https://mvnrepository.com/artifact/io.github.andrewauclair/modern-docking-single-app)
8 | [](https://mvnrepository.com/artifact/io.github.andrewauclair/modern-docking-multi-app)
9 |
10 | [](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 `
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 |
--------------------------------------------------------------------------------