Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve API for Tab Preference Selection #235

Merged
merged 1 commit into from
Jul 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions demo-single-app/src/basic/AlwaysDisplayedPanel.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ of this software and associated documentation files (the "Software"), to deal
*/
package basic;

import ModernDocking.DockableTabPreference;

import javax.swing.*;

// Docking panel that is always displayed and cannot be closed
Expand All @@ -46,7 +48,7 @@ public boolean isLimitedToRoot() {
}

@Override
public int getTabPosition() {
return SwingConstants.TOP;
public DockableTabPreference getTabPreference() {
return DockableTabPreference.TOP;
}
}
17 changes: 15 additions & 2 deletions demo-single-app/src/basic/MainFrame.java
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,9 @@ public class MainFrame extends JFrame implements Callable<Integer> {
@CommandLine.Option(names = "--always-use-tabs", defaultValue = "false", description = "always use tabs, even when there is only 1 dockable in the tab group")
boolean alwaysUseTabs;

@CommandLine.Option(names = "--tab-location", defaultValue = "NONE", description = "Location to display tabs. values: ${COMPLETION-CANDIDATES}")
DockableTabPreference tabLocation;

@CommandLine.Option(names = "--create-docking-instance", defaultValue = "false", description = "create a separate instance of the framework for this MainFrame")
boolean createDockingInstance;

Expand All @@ -86,11 +89,21 @@ public void setVisible(boolean visible) {

setTitle("Modern Docking Basic Demo");

if (alwaysUseTabs) {
if (tabLocation == DockableTabPreference.TOP) {
Settings.setDefaultTabPreference(DockableTabPreference.TOP_ALWAYS);
}
else {
Settings.setDefaultTabPreference(DockableTabPreference.BOTTOM_ALWAYS);
}
}
else {
Settings.setDefaultTabPreference(tabLocation);
}

Docking.initialize(this);
DockingUI.initialize();

Settings.setAlwaysDisplayTabMode(alwaysUseTabs);

JMenuBar menuBar = new JMenuBar();
setJMenuBar(menuBar);

Expand Down
8 changes: 8 additions & 0 deletions docking-api/src/ModernDocking/Dockable.java
Original file line number Diff line number Diff line change
Expand Up @@ -191,10 +191,18 @@ default boolean getHasMoreOptions() {
return false;
}

/**
* @deprecated Replaced with getTabPreference. Will be removed in future release.
*/
@Deprecated(since = "0.12.0", forRemoval = true)
default int getTabPosition() {
return SwingConstants.BOTTOM;
}

default DockableTabPreference getTabPreference() {
return DockableTabPreference.NONE;
}

/**
* add the more options to the popup menu. defaults to an empty block to handle the case of hasMoreOptions() = false
*
Expand Down
32 changes: 32 additions & 0 deletions docking-api/src/ModernDocking/DockableTabPreference.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
Copyright (c) 2024 Andrew Auclair

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
package ModernDocking;

public enum DockableTabPreference {
NONE,
BOTTOM,
TOP,

// use these options with Settings.setDefaultTabPreference to force tabs to always display, even with a single dockable
BOTTOM_ALWAYS,
TOP_ALWAYS
}
3 changes: 2 additions & 1 deletion docking-api/src/ModernDocking/api/RootDockingPanelAPI.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ of this software and associated documentation files (the "Software"), to deal
package ModernDocking.api;

import ModernDocking.Dockable;
import ModernDocking.DockableTabPreference;
import ModernDocking.DockingRegion;
import ModernDocking.internal.*;
import ModernDocking.settings.Settings;
Expand Down Expand Up @@ -296,7 +297,7 @@ public void dock(Dockable dockable, DockingRegion region, double dividerProporti
if (panel != null) {
panel.dock(dockable, region, dividerProportion);
}
else if (Settings.alwaysDisplayTabsMode(dockable)) {
else if (Settings.alwaysDisplayTabsMode()) {
setPanel(new DockedTabbedPanel(docking, wrapper));
wrapper.setWindow(window);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ protected void undock() {

@Override
protected JFrame createFloatingFrame() {
if (Settings.alwaysDisplayTabsMode(panel.getWrapper().getDockable())) {
if (Settings.alwaysDisplayTabsMode()) {
return new TempFloatingFrame(Collections.singletonList(panel.getWrapper()), 0, panel, panel.getSize());
}
return new TempFloatingFrame(panel.getWrapper(), panel, panel.getSize());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ public TempFloatingFrame(List<DockableWrapper> dockables, int selectedIndex, JCo
// we only support tabs on top if we have FlatLaf because we can add a trailing component for our menu
boolean usingFlatLaf = tabs.getUI().getClass().getPackageName().startsWith("com.formdev.flatlaf");

if (Settings.alwaysDisplayTabsMode(dockables.get(0).getDockable()) && usingFlatLaf) {
if (Settings.alwaysDisplayTabsMode() && usingFlatLaf) {
tabs.setTabPlacement(JTabbedPane.TOP);
}
else {
Expand Down
2 changes: 1 addition & 1 deletion docking-api/src/ModernDocking/internal/DisplayPanel.java
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ private void buildUI() {
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.weightx = 1.0;

if (!Settings.alwaysDisplayTabsMode(wrapper.getDockable()) || wrapper.isHidden()) {
if (!Settings.alwaysDisplayTabsMode() || wrapper.isHidden()) {
if (!(wrapper.getParent() instanceof DockedTabbedPanel) || ((DockedTabbedPanel) wrapper.getParent()).isUsingBottomTabs()) {
add((Component) wrapper.getHeaderUI(), gbc);
gbc.gridy++;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ else if (region == DockingRegion.CENTER) {

DockingPanel newPanel;

if (Settings.alwaysDisplayTabsMode(wrapper.getDockable())) {
if (Settings.alwaysDisplayTabsMode()) {
newPanel = new DockedTabbedPanel(docking, wrapper);
}
else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -283,7 +283,7 @@ public void dock(Dockable dockable, DockingRegion region, double dividerProporti

DockingPanel newPanel;

if (Settings.alwaysDisplayTabsMode(wrapper.getDockable())) {
if (Settings.alwaysDisplayTabsMode()) {
newPanel = new DockedTabbedPanel(docking, wrapper);
}
else {
Expand Down
33 changes: 26 additions & 7 deletions docking-api/src/ModernDocking/internal/DockedTabbedPanel.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ of this software and associated documentation files (the "Software"), to deal
package ModernDocking.internal;

import ModernDocking.Dockable;
import ModernDocking.DockableTabPreference;
import ModernDocking.DockingRegion;
import ModernDocking.api.DockingAPI;
import ModernDocking.floating.DockedTabbedPanelFloatListener;
Expand Down Expand Up @@ -85,7 +86,7 @@ public DockedTabbedPanel(DockingAPI docking, DockableWrapper dockable) {
// we only support tabs on top if we have FlatLaf because we can add a trailing component for our menu
boolean usingFlatLaf = tabs.getUI().getClass().getPackageName().startsWith("com.formdev.flatlaf");

if (Settings.alwaysDisplayTabsMode(dockable.getDockable()) && usingFlatLaf) {
if (Settings.alwaysDisplayTabsMode() && usingFlatLaf) {
tabs.setTabPlacement(JTabbedPane.TOP);
}
else {
Expand All @@ -94,7 +95,7 @@ public DockedTabbedPanel(DockingAPI docking, DockableWrapper dockable) {

tabs.setTabLayoutPolicy(Settings.getTabLayoutPolicy());

if (Settings.alwaysDisplayTabsMode(dockable.getDockable())) {
if (Settings.alwaysDisplayTabsMode()) {
configureTrailingComponent();
}

Expand Down Expand Up @@ -203,17 +204,35 @@ public void addPanel(DockableWrapper dockable) {

dockable.getFloatListener().addAlternateDragSource(tabs, draggingFromTabPanel);

// if any of the dockables use top tab position, switch this tabbedpanel to top tabs
if (tabs.getTabPlacement() != SwingConstants.TOP && dockable.getDockable().getTabPosition() == SwingConstants.TOP) {
DockableTabPreference tabPreference = Settings.defaultTabPreference();

// we only support tabs on top if we have FlatLaf because we can add a trailing component for our menu
boolean usingFlatLaf = tabs.getUI().getClass().getPackageName().startsWith("com.formdev.flatlaf");

if (tabPreference == DockableTabPreference.TOP_ALWAYS && usingFlatLaf) {
tabs.setTabPlacement(SwingConstants.TOP);
}
else if (tabPreference == DockableTabPreference.BOTTOM_ALWAYS) {
tabs.setTabPlacement(SwingConstants.BOTTOM);
}
else if (tabPreference == DockableTabPreference.TOP && usingFlatLaf) {
// in the normal top preference case, only switch if we add a dockable that prefers the top tab position
if (dockable.getDockable().getTabPreference() == DockableTabPreference.TOP) {
tabs.setTabPlacement(SwingConstants.TOP);
}
}

// if any of the dockables use top tab position, switch this tabbedpanel to top tabs
// if (tabs.getTabPlacement() != SwingConstants.TOP && dockable.getDockable().getTabPosition() == SwingConstants.TOP) {
// tabs.setTabPlacement(SwingConstants.TOP);
// }

tabs.setToolTipTextAt(tabs.getTabCount() - 1, dockable.getDockable().getTabTooltip());
tabs.setIconAt(tabs.getTabCount() - 1, dockable.getDockable().getIcon());
tabs.setSelectedIndex(tabs.getTabCount() - 1);
selectedTab = tabs.getSelectedIndex();

if (Settings.alwaysDisplayTabsMode(dockable.getDockable()) && dockable.getDockable().isClosable()) {
if (Settings.alwaysDisplayTabsMode() && dockable.getDockable().isClosable()) {
dockable.getDisplayPanel().putClientProperty("JTabbedPane.tabClosable", true);
}

Expand Down Expand Up @@ -267,7 +286,7 @@ public void dock(Dockable dockable, DockingRegion region, double dividerProporti

DockingPanel newPanel;

if (Settings.alwaysDisplayTabsMode(wrapper.getDockable())) {
if (Settings.alwaysDisplayTabsMode()) {
newPanel = new DockedTabbedPanel(docking, wrapper);
}
else {
Expand Down Expand Up @@ -322,7 +341,7 @@ public void dockAtIndex(Dockable dockable, int index) {
public void undock(Dockable dockable) {
removePanel(DockingInternal.get(docking).getWrapper(dockable));

if (!Floating.isFloatingTabbedPane() && !Settings.alwaysDisplayTabsMode(dockable) && panels.size() == 1 && parent != null && panels.get(0).getDockable().getTabPosition() != SwingConstants.TOP) {
if (!Floating.isFloatingTabbedPane() && !Settings.alwaysDisplayTabsMode() && panels.size() == 1 && parent != null && panels.get(0).getDockable().getTabPosition() != SwingConstants.TOP) {
parent.replaceChild(this, new DockedSimplePanel(docking, panels.get(0)));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ public void dock(String persistentID, DockingRegion region, double dividerPropor
if (node != null) {
node.dock(persistentID, region, dividerProportion);
}
else if (Settings.alwaysDisplayTabsMode(DockingInternal.get(docking).getDockable(persistentID))) {
else if (Settings.alwaysDisplayTabsMode()) {
node = new DockingTabPanelNode(docking, persistentID);
node.setParent(this);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ else if (region == DockingRegion.CENTER) {
DockingLayoutNode left;
DockingLayoutNode right;

if (Settings.alwaysDisplayTabsMode(DockingInternal.get(docking).getDockable(persistentID))) {
if (Settings.alwaysDisplayTabsMode()) {
if (orientation == JSplitPane.HORIZONTAL_SPLIT) {
left = region == DockingRegion.EAST ? this : new DockingTabPanelNode(docking, persistentID);
right = region == DockingRegion.EAST ? new DockingTabPanelNode(docking, persistentID) : this;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ public void dock(String persistentID, DockingRegion region, double dividerPropor
DockingLayoutNode left;
DockingLayoutNode right;

if (Settings.alwaysDisplayTabsMode(DockingInternal.get(docking).getDockable(persistentID))) {
if (Settings.alwaysDisplayTabsMode()) {
left = region == DockingRegion.NORTH || region == DockingRegion.WEST ? new DockingTabPanelNode(docking, persistentID) : this;
right = region == DockingRegion.NORTH || region == DockingRegion.WEST ? this : new DockingTabPanelNode(docking, persistentID);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ public void dock(String persistentID, DockingRegion region, double dividerPropor
DockingLayoutNode left;
DockingLayoutNode right;

if (Settings.alwaysDisplayTabsMode(DockingInternal.get(docking).getDockable(persistentID))) {
if (Settings.alwaysDisplayTabsMode()) {
left = region == DockingRegion.NORTH || region == DockingRegion.WEST ? new DockingTabPanelNode(docking, persistentID) : this;
right = region == DockingRegion.NORTH || region == DockingRegion.WEST ? this : new DockingTabPanelNode(docking, persistentID);
}
Expand Down
30 changes: 26 additions & 4 deletions docking-api/src/ModernDocking/settings/Settings.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,26 +22,48 @@ of this software and associated documentation files (the "Software"), to deal
package ModernDocking.settings;

import ModernDocking.Dockable;
import ModernDocking.DockableTabPreference;

import javax.swing.*;

public class Settings {
private static boolean alwaysDisplayTabsMode = false;
private static DockableTabPreference defaultTabPreference = DockableTabPreference.BOTTOM;

private static int tabLayoutPolicy = JTabbedPane.SCROLL_TAB_LAYOUT;

private static boolean enableActiveHighlighter = true;

public static boolean alwaysDisplayTabsMode() {
return alwaysDisplayTabsMode;
return defaultTabPreference == DockableTabPreference.TOP_ALWAYS || defaultTabPreference == DockableTabPreference.BOTTOM_ALWAYS;
}

/**
* @deprecated Replaced with defaultTabPreference. Will be removed in future release.
*/
@Deprecated(since = "0.12.0", forRemoval = true)
public static boolean alwaysDisplayTabsMode(Dockable dockable) {
return alwaysDisplayTabsMode || dockable.getTabPosition() == SwingConstants.TOP;
return defaultTabPreference == DockableTabPreference.TOP || dockable.getTabPosition() == SwingConstants.TOP;
}

/**
* @deprecated Replaced with setDefaultTabPreference. Will be removed in future release.
*/
@Deprecated(since = "0.12.0", forRemoval = true)
public static void setAlwaysDisplayTabMode(boolean alwaysDisplayTabsMode) {
Settings.alwaysDisplayTabsMode = alwaysDisplayTabsMode;
defaultTabPreference = alwaysDisplayTabsMode ? DockableTabPreference.TOP : DockableTabPreference.BOTTOM;
}

public static DockableTabPreference defaultTabPreference() {
return defaultTabPreference;
}

/**
* Set the applications preference for default tab location when adding dockables to tab groups.
*
* @param tabPreference The new default tab location preference
*/
public static void setDefaultTabPreference(DockableTabPreference tabPreference) {
defaultTabPreference = tabPreference;
}

public static int getTabLayoutPolicy() {
Expand Down
Loading