Skip to content

Commit

Permalink
feat: open dock on the manipulated menu area
Browse files Browse the repository at this point in the history
  • Loading branch information
teletha committed Feb 12, 2024
1 parent 407616e commit e04dc7f
Show file tree
Hide file tree
Showing 5 changed files with 144 additions and 23 deletions.
18 changes: 12 additions & 6 deletions src/main/java/viewtify/ui/UITab.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import javafx.scene.Node;
import javafx.scene.control.Tab;
import javafx.scene.layout.StackPane;

import kiss.I;
import kiss.Signal;
import kiss.WiseFunction;
Expand Down Expand Up @@ -78,12 +79,6 @@ public UITab(View parent) {
addEventHandler(TAB_CLOSE_REQUEST_EVENT, e -> {
System.out.println("REQUEST");
});

context(menus -> {
menus.menu().text(I.translate("Close this tab")).action(() -> {
getTabPane().getTabs().remove(this);
});
});
}

/**
Expand Down Expand Up @@ -150,6 +145,17 @@ public final UITab closable(boolean enable) {
return this;
}

/**
* Close this tab.
*
* @return
*/
public final UITab close() {
getTabPane().getTabs().remove(this);

return this;
}

/**
* Test if this tab has been already loaded.
*
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/viewtify/ui/UITabPane.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import javafx.scene.layout.HBox;
import javafx.scene.layout.Pane;
import javafx.scene.layout.StackPane;

import kiss.Disposable;
import kiss.WiseConsumer;
import stylist.Style;
Expand Down Expand Up @@ -180,7 +181,6 @@ public final UITabPane registerIcon(WiseConsumer<UILabel> builder) {
UILabel icon = new UILabel(null).style(style.icon);
builder.accept(icon);
menus.getChildren().add(icon.ui());

}
return this;
}
Expand Down
81 changes: 70 additions & 11 deletions src/main/java/viewtify/ui/dock/DockSystem.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@
import java.util.concurrent.TimeUnit;
import java.util.function.UnaryOperator;

import org.controlsfx.glyphfont.FontAwesome;

import javafx.application.Platform;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
Expand Down Expand Up @@ -51,6 +49,9 @@
import javafx.stage.Stage;
import javafx.stage.StageStyle;
import javafx.stage.WindowEvent;

import org.controlsfx.glyphfont.FontAwesome;

import kiss.I;
import kiss.Managed;
import kiss.Signal;
Expand All @@ -72,6 +73,24 @@
*/
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 @@ -109,7 +128,7 @@ public final class DockSystem {
static final Variable<Tab> selected = Variable.empty();

/** The dock system event. */
static final ObservableSet<String> opened = FXCollections.observableSet();
static final ObservableSet<String> openedTabs = FXCollections.observableSet();

/** The user configuration. */
static TabClosingPolicy tabPolicy = TabClosingPolicy.ALL_TABS;
Expand Down Expand Up @@ -191,7 +210,7 @@ public static boolean has(String id) {
* @return
*/
public static Signal<Boolean> isOpened(String id) {
return Viewtify.observing(opened).map(x -> x.contains(id));
return Viewtify.observing(openedTabs).map(x -> x.contains(id));
}

public static Tab selected() {
Expand Down Expand Up @@ -232,16 +251,53 @@ 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));
});
});
});

DockRecommendedLocation o = option.apply(new DockRecommendedLocation());
DockLayout layout = layout();

// First, if there is an area where the specified view's ID is registered,
// First, if the registration is activated on the tab mene,
// add the view there.
Variable<TabArea> area = Variable.of(latestMenuActivatedTabArea);
if (area.isPresent()) {
area.v.add(tab, PositionCenter);
openedTabs.add(id);
return tab;
}

// Next, if there is an area where the specified view's ID is registered,
// add the view there.
Variable<TabArea> area = layout.find(TabArea.class).take(x -> x.hasView(id)).first().to();
area = layout.find(TabArea.class).take(x -> x.hasView(id)).first().to();
if (area.isPresent()) {
area.v.add(tab, PositionRestore);
opened.add(id);
openedTabs.add(id);
return tab;
}

Expand All @@ -250,7 +306,7 @@ public static UITab register(String id, UnaryOperator<DockRecommendedLocation> o
area = layout.find(TabArea.class).take(v -> v.location == o.recommendedArea).first().to();
if (area.isPresent()) {
area.v.add(tab, PositionCenter);
opened.add(id);
openedTabs.add(id);
return tab;
}

Expand All @@ -261,7 +317,7 @@ public static UITab register(String id, UnaryOperator<DockRecommendedLocation> o
created.location = o.recommendedArea;
created.setViewportRatio(o.recommendedArea == PositionRight || o.recommendedArea == PositionBottom ? 1 - o.recommendedRatio
: o.recommendedRatio);
opened.add(id);
openedTabs.add(id);
return tab;
}

Expand Down Expand Up @@ -292,6 +348,9 @@ private static void openNewWindow(RootArea area, Bounds bounds, EventHandler<Win
/** The registered menu builders. */
static final List<WiseConsumer<UILabel>> menuBuilders = new ArrayList();

/** The latest activate menu tabarea. */
static TabArea latestMenuActivatedTabArea;

/**
* Initialize dock system with default menu.
*/
Expand Down Expand Up @@ -351,8 +410,8 @@ public static void initialize(WiseConsumer<UILabel> menuBuilder) {
menuBuilders.add(menuBuilder);

for (RootArea area : layout().roots) {
area.findAll(TabArea.class).to(x -> {
x.node.registerIcon(menuBuilder);
area.findAll(TabArea.class).to(tabs -> {
tabs.registerMenu(menuBuilder);
});
}
}
Expand Down
44 changes: 40 additions & 4 deletions src/main/java/viewtify/ui/dock/TabArea.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,14 @@
import java.util.List;
import java.util.Objects;

import javafx.beans.InvalidationListener;
import javafx.collections.ObservableList;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
import javafx.scene.control.skin.TabPaneSkin;
import javafx.scene.input.DragEvent;
import javafx.scene.layout.StackPane;
import javafx.stage.WindowEvent;

import kiss.I;
import kiss.WiseConsumer;
import viewtify.Viewtify;
Expand Down Expand Up @@ -77,7 +78,8 @@ class TabArea extends ViewArea<UITabPane> {
});
});

node.ui.getTabs().addListener((InvalidationListener) c -> DockSystem.requestSavingLayout());
// node.ui.getTabs().addListener((InvalidationListener) c ->
// DockSystem.requestSavingLayout());

// Since TabPane implementation delays the initialization of Skin and internal nodes
// are not generated. So we should create Skin eagerly.
Expand Down Expand Up @@ -210,11 +212,27 @@ private void saveSelectedTab() {
*/
void remove(Tab tab, boolean checkEmpty) {
node.ui.getTabs().remove(tab);
if (checkEmpty) {

handleTabManipulation(tab.getId(), false, checkEmpty);
}

/**
* Handle tab removing.
*
* @param id
* @param checkEmpty
*/
private void handleTabManipulation(String id, boolean add, boolean checkEmpty) {
if (!add && checkEmpty) {
handleEmpty();
}

updatePosition();
DockSystem.opened.remove(tab.getId());
if (add) {
DockSystem.openedTabs.add(id);
} else {
DockSystem.openedTabs.remove(id);
}
}

/**
Expand Down Expand Up @@ -265,6 +283,9 @@ public TabArea add(UITab tab, int position) {

selectInitialTabOnlyOnce(tab);
if (!restore) updatePosition();

tab.getProperties().put("tabarea", this);
// handleTabManipulation(tab.getId(), true, false);
return this;
}
}
Expand Down Expand Up @@ -347,4 +368,19 @@ private void updatePosition() {

DockSystem.requestSavingLayout();
}

/**
* @param menuBuilder
*/
void registerMenu(WiseConsumer<UILabel> menuBuilder) {
node.registerIcon(label -> {
menuBuilder.accept(label);

label.when(WindowEvent.WINDOW_SHOWING, () -> {
DockSystem.latestMenuActivatedTabArea = this;
}).when(WindowEvent.WINDOW_HIDDEN, () -> {
DockSystem.latestMenuActivatedTabArea = null;
});
});
}
}
22 changes: 21 additions & 1 deletion src/main/java/viewtify/ui/helper/ContextMenuHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import javafx.event.Event;
import javafx.event.EventHandler;
import javafx.event.EventTarget;
import javafx.event.EventType;
import javafx.geometry.Side;
import javafx.scene.Node;
import javafx.scene.control.ContextMenu;
Expand All @@ -30,7 +31,10 @@
import javafx.scene.input.ContextMenuEvent;
import javafx.scene.input.MouseButton;
import javafx.scene.input.MouseEvent;
import javafx.stage.WindowEvent;

import kiss.Variable;
import kiss.WiseRunnable;
import viewtify.ui.UIContextMenu;
import viewtify.ui.UserInterfaceProvider;

Expand Down Expand Up @@ -73,7 +77,7 @@ default Self context(Consumer<UIContextMenu> builder) {
* @return A chainable API for further configuration.
*/
default Self context(Object id, Consumer<UIContextMenu> builder) {
return context(true, this, builder);
return context(true, id, builder);
}

/**
Expand Down Expand Up @@ -362,4 +366,20 @@ private Variable<EventTarget> target(Object o) {
}
return Variable.empty();
}

/**
* Register window event.
*
* @param type
* @param action
* @return
*/
default Self when(EventType<WindowEvent> type, WiseRunnable action) {
if (action != null) {
context().addEventHandler(type, e -> {
action.run();
});
}
return (Self) this;
}
}

0 comments on commit e04dc7f

Please sign in to comment.