Skip to content

Commit

Permalink
feat: UITabPane supports automatic disposing view
Browse files Browse the repository at this point in the history
  • Loading branch information
teletha committed Feb 12, 2024
1 parent e04dc7f commit a63a716
Show file tree
Hide file tree
Showing 4 changed files with 155 additions and 120 deletions.
50 changes: 39 additions & 11 deletions src/main/java/viewtify/ui/UITab.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

import kiss.I;
import kiss.Signal;
import kiss.Variable;
import kiss.WiseFunction;
import viewtify.Viewtify;
import viewtify.ui.helper.ContextMenuHelper;
Expand All @@ -30,6 +31,24 @@

public class UITab extends Tab implements StyleHelper<UITab, Tab>, LabelHelper<UITab>, ContextMenuHelper<UITab>, DisableHelper<UITab> {

/** The translatable text. */
private static final Variable<String> CloseThisTab = I.translate("Close this tab");

/** The translatable text. */
private static final Variable<String> CloseMultipleTabs = I.translate("Close multiple tabs");

/** The translatable text. */
private static final Variable<String> CloseRightTabs = I.translate("Close tabs to the right");

/** The translatable text. */
private static final Variable<String> CloseLeftTabs = I.translate("Close tabs to the left");

/** The translatable text. */
private static final Variable<String> CloseOtherTabs = I.translate("Close all other tabs");

/** The translatable text. */
private static final Variable<String> CloseAllTabs = I.translate("Close all tabs");

/** Cache to find tab node. */
private static final WiseFunction<Node, Object> findTab;

Expand All @@ -54,7 +73,7 @@ public class UITab extends Tab implements StyleHelper<UITab, Tab>, LabelHelper<U
private final AtomicBoolean loaded = new AtomicBoolean();

/** The actual contents. */
private View contents;
View contents;

/** The cached reference for the styleable node . */
private WeakReference<Node> styleable;
Expand All @@ -68,16 +87,25 @@ public UITab(View parent) {
selectedProperty().addListener(change -> load());
tabPaneProperty().addListener(invalidaed -> styleable = null);

addEventHandler(CLOSED_EVENT, e -> {
System.out.println("CLOSE");
if (contents != null) {
System.out.println("Dispose tab");
contents.dispose();
contents = null;
}
});
addEventHandler(TAB_CLOSE_REQUEST_EVENT, e -> {
System.out.println("REQUEST");
context(menus -> {
menus.menu().text(CloseThisTab).action(this::close);
menus.menu(CloseMultipleTabs, sub -> {
sub.menu(CloseRightTabs).action(() -> {
ObservableList<Tab> tabs = getTabPane().getTabs();
I.signal(tabs).skip(tabs.indexOf(this) + 1).buffer().flatIterable(x -> x).to(x -> tabs.remove(x));
});
sub.menu(CloseLeftTabs).action(() -> {
ObservableList<Tab> tabs = getTabPane().getTabs();
I.signal(tabs).take(tabs.indexOf(this)).buffer().flatIterable(x -> x).to(x -> tabs.remove(x));
});
sub.menu(CloseOtherTabs).action(() -> {
ObservableList<Tab> tabs = getTabPane().getTabs();
I.signal(tabs).skip(this).buffer().flatIterable(x -> x).to(x -> tabs.remove(x));
});
sub.menu(CloseAllTabs).action(() -> {
getTabPane().getTabs().clear();
});
});
});
}

Expand Down
17 changes: 14 additions & 3 deletions src/main/java/viewtify/ui/UITabPane.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,17 @@
import java.util.function.Consumer;

import javafx.beans.property.Property;
import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList;
import javafx.geometry.Insets;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
import javafx.scene.control.TabPane.TabClosingPolicy;
import javafx.scene.control.TabPane.TabDragPolicy;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Pane;
import javafx.scene.layout.StackPane;

import kiss.Disposable;
import kiss.WiseConsumer;
import stylist.Style;
import stylist.StyleDSL;
Expand All @@ -36,8 +37,7 @@
public class UITabPane extends UserInterface<UITabPane, TabPane>
implements ContextMenuHelper<UITabPane>, SelectableHelper<UITabPane, UITab>, CollectableHelper<UITabPane, UITab> {

/** The model disposer. */
private Disposable disposable = Disposable.empty();
public static final String AvoidAutomaticDisposingTabClass = "undisposable";

/**
* Enchanced view.
Expand All @@ -49,6 +49,17 @@ public UITabPane(View view) {

// FUNCTIONALITY : wheel scroll will change selection.
when(User.Scroll).take(Actions.inside(() -> ui.lookup(".tab-header-background"))).to(Actions.traverse(ui.getSelectionModel()));

// dispose view automatically
ui.getTabs().addListener((ListChangeListener<Tab>) change -> {
while (change.next()) {
for (Tab removed : change.getRemoved()) {
if (removed instanceof UITab tab && tab.contents != null && !tab.getStyleClass().contains(AvoidAutomaticDisposingTabClass)) {
tab.contents.dispose();
}
}
}
});
}

/**
Expand Down
100 changes: 47 additions & 53 deletions src/main/java/viewtify/ui/dock/DockSystem.java
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@
import viewtify.ui.UILabel;
import viewtify.ui.UIPane;
import viewtify.ui.UITab;
import viewtify.ui.UITabPane;
import viewtify.ui.UserInterfaceProvider;

/**
Expand All @@ -73,24 +74,6 @@
*/
public final class DockSystem {

/** The translatable text. */
private static final Variable<String> CloseThisTab = I.translate("Close this tab");

/** The translatable text. */
private static final Variable<String> CloseMultipleTabs = I.translate("Close multiple tabs");

/** The translatable text. */
private static final Variable<String> CloseRightTabs = I.translate("Close tabs to the right");

/** The translatable text. */
private static final Variable<String> CloseLeftTabs = I.translate("Close tabs to the left");

/** The translatable text. */
private static final Variable<String> CloseOtherTabs = I.translate("Close all other tabs");

/** The translatable text. */
private static final Variable<String> CloseAllTabs = I.translate("Close all tabs");

/** The root user interface for the docking system. */
public static final UserInterfaceProvider<Parent> UI = () -> layout().findRoot().node.ui;

Expand Down Expand Up @@ -133,6 +116,9 @@ public final class DockSystem {
/** The user configuration. */
static TabClosingPolicy tabPolicy = TabClosingPolicy.ALL_TABS;

/** The initialization state. */
static boolean whileInitialization;

/** Avoid multiplex requesting. */
private static boolean requesting;

Expand Down Expand Up @@ -251,34 +237,36 @@ public static UITab register(String id, UnaryOperator<DockRecommendedLocation> o

UITab tab = new UITab(null);
tab.setId(id);
tab.context(menus -> {
menus.menu().text(CloseThisTab).action(() -> {
TabArea area = (TabArea) tab.getProperties().get("tabarea");
area.remove(tab, true);
});
menus.menu(CloseMultipleTabs, sub -> {
sub.menu(CloseRightTabs).action(() -> {
TabArea area = (TabArea) tab.getProperties().get("tabarea");
ObservableList<Tab> tabs = tab.getTabPane().getTabs();
I.signal(tabs).skip(tabs.indexOf(tab) + 1).buffer().flatIterable(x -> x).to(x -> area.remove(x, true));
});
sub.menu(CloseLeftTabs).action(() -> {
TabArea area = (TabArea) tab.getProperties().get("tabarea");
ObservableList<Tab> tabs = tab.getTabPane().getTabs();
I.signal(tabs).take(tabs.indexOf(tab)).buffer().flatIterable(x -> x).to(x -> area.remove(x, true));
});
sub.menu(CloseOtherTabs).action(() -> {
TabArea area = (TabArea) tab.getProperties().get("tabarea");
ObservableList<Tab> tabs = tab.getTabPane().getTabs();
I.signal(tabs).skip(tab).buffer().flatIterable(x -> x).to(x -> area.remove(x, true));
});
sub.menu(CloseAllTabs).action(() -> {
TabArea area = (TabArea) tab.getProperties().get("tabarea");
ObservableList<Tab> tabs = tab.getTabPane().getTabs();
I.signal(tabs).buffer().flatIterable(x -> x).to(x -> area.remove(x, true));
});
});
});
// tab.context(menus -> {
// menus.menu().text(CloseThisTab).action(() -> {
// TabArea area = (TabArea) tab.getProperties().get("tabarea");
// area.remove(tab);
// });
// menus.menu(CloseMultipleTabs, sub -> {
// sub.menu(CloseRightTabs).action(() -> {
// TabArea area = (TabArea) tab.getProperties().get("tabarea");
// ObservableList<Tab> tabs = tab.getTabPane().getTabs();
// I.signal(tabs).skip(tabs.indexOf(tab) + 1).buffer().flatIterable(x -> x).to(x ->
// area.remove(x));
// });
// sub.menu(CloseLeftTabs).action(() -> {
// TabArea area = (TabArea) tab.getProperties().get("tabarea");
// ObservableList<Tab> tabs = tab.getTabPane().getTabs();
// I.signal(tabs).take(tabs.indexOf(tab)).buffer().flatIterable(x -> x).to(x ->
// area.remove(x));
// });
// sub.menu(CloseOtherTabs).action(() -> {
// TabArea area = (TabArea) tab.getProperties().get("tabarea");
// ObservableList<Tab> tabs = tab.getTabPane().getTabs();
// I.signal(tabs).skip(tab).buffer().flatIterable(x -> x).to(x -> area.remove(x));
// });
// sub.menu(CloseAllTabs).action(() -> {
// TabArea area = (TabArea) tab.getProperties().get("tabarea");
// ObservableList<Tab> tabs = tab.getTabPane().getTabs();
// I.signal(tabs).buffer().flatIterable(x -> x).to(x -> area.remove(x));
// });
// });
// });

DockRecommendedLocation o = option.apply(new DockRecommendedLocation());
DockLayout layout = layout();
Expand Down Expand Up @@ -378,6 +366,8 @@ public static void initialize() {
* Initialize dock system with your menu builder.
*/
public static void initialize(WiseConsumer<UILabel> menuBuilder) {
whileInitialization = true;

DockLayout layout = layout();
if (Locator.file(layout.locate()).isAbsent()) {
for (DockProvider provider : I.find(DockProvider.class)) {
Expand Down Expand Up @@ -415,6 +405,8 @@ public static void initialize(WiseConsumer<UILabel> menuBuilder) {
});
}
}

whileInitialization = false;
}

/**
Expand Down Expand Up @@ -547,6 +539,7 @@ static void onDragDetected(MouseEvent event, TabArea area, UITab tab) {
event.consume(); // stop event propagation

dragedTab = tab;
dragedTab.getStyleClass().add(UITabPane.AvoidAutomaticDisposingTabClass);
dragedTabArea = area;
dragedDoppelganger.setText(tab.getText());

Expand All @@ -571,6 +564,7 @@ static void onDragDone(DragEvent event, TabArea area) {

if (event.getTransferMode() == TransferMode.MOVE && event.getDragboard().hasContent(DnD)) {
area.handleEmpty();
dragedTab.getStyleClass().remove(UITabPane.AvoidAutomaticDisposingTabClass);
dragedTab = null;
dragedTabArea = null;

Expand Down Expand Up @@ -640,16 +634,16 @@ static void onDragDropped(DragEvent event, TabArea area) {
int position = detectPosition(event, area.node.ui);
if (canDrop(position, area)) {
if (area.node.isHeaderShown() || position != PositionCenter) {
dragedTabArea.remove(dragedTab, false);
dragedTabArea.remove(dragedTab);
area.add(dragedTab, position);
} else {
// switch operation
UITab tab = area.node.first().v;
int dragedIndex = dragedTabArea.node.indexOf(dragedTab);

// remove each tab
area.remove(tab, false);
dragedTabArea.remove(dragedTab, false);
area.remove(tab);
dragedTabArea.remove(dragedTab);

// add each tab
area.add(dragedTab, PositionCenter);
Expand Down Expand Up @@ -705,7 +699,7 @@ static void onDragDroppedNewStage(DragEvent event) {
.getWidth(), contentsBound.getHeight() + titleBarHeight);

openNewWindow(area, bounds, e -> {
dragedTabArea.remove(dragedTab, false);
dragedTabArea.remove(dragedTab);
area.add(dragedTab, PositionCenter);
layout().roots.add(area);
});
Expand Down Expand Up @@ -872,7 +866,7 @@ static void onHeaderDragDropped(DragEvent event, TabArea area) {

int[] values = calculate(area, event);

dragedTabArea.remove(dragedTab, false);
dragedTabArea.remove(dragedTab);
area.add(dragedTab, values[1]);
area.node.ui.getSelectionModel().select(values[1]);

Expand Down Expand Up @@ -905,7 +899,7 @@ private static int[] calculate(TabArea area, DragEvent event) {
* @param area
*/
private static void revert(TabArea area) {
area.remove(dragedDoppelganger, false);
area.remove(dragedDoppelganger);

for (Tab tab : area.node.ui.getTabs()) {
Node node = tab.getStyleableNode();
Expand Down Expand Up @@ -1014,7 +1008,7 @@ static void onSplitterDragDropped(DragEvent event, SplitArea area) {
// cannot be calculated.
// Therefore, it is necessary to calculate it first.
int position = detectPosition(event, area.node.ui);
dragedTabArea.remove(dragedTab, false);
dragedTabArea.remove(dragedTab);
area.add(dragedTab, position);

onSplitterDragExited();
Expand Down
Loading

0 comments on commit a63a716

Please sign in to comment.