Add more browser tab actions

This commit is contained in:
crschnick 2024-07-21 00:16:02 +00:00
parent 1061d407e5
commit 031ff66387
16 changed files with 163 additions and 19 deletions

View file

@ -4,13 +4,16 @@ import atlantafx.base.controls.RingProgressIndicator;
import atlantafx.base.theme.Styles; import atlantafx.base.theme.Styles;
import io.xpipe.app.browser.BrowserWelcomeComp; import io.xpipe.app.browser.BrowserWelcomeComp;
import io.xpipe.app.comp.base.MultiContentComp; import io.xpipe.app.comp.base.MultiContentComp;
import io.xpipe.app.core.AppI18n;
import io.xpipe.app.fxcomps.Comp; import io.xpipe.app.fxcomps.Comp;
import io.xpipe.app.fxcomps.SimpleComp; import io.xpipe.app.fxcomps.SimpleComp;
import io.xpipe.app.fxcomps.impl.PrettyImageHelper; import io.xpipe.app.fxcomps.impl.PrettyImageHelper;
import io.xpipe.app.fxcomps.impl.TooltipAugment; import io.xpipe.app.fxcomps.impl.TooltipAugment;
import io.xpipe.app.fxcomps.util.LabelGraphic;
import io.xpipe.app.fxcomps.util.PlatformThread; import io.xpipe.app.fxcomps.util.PlatformThread;
import io.xpipe.app.storage.DataStorage; import io.xpipe.app.storage.DataStorage;
import io.xpipe.app.util.BooleanScope; import io.xpipe.app.util.BooleanScope;
import io.xpipe.app.util.ContextMenuHelper;
import io.xpipe.app.util.InputHelper; import io.xpipe.app.util.InputHelper;
import javafx.application.Platform; import javafx.application.Platform;
import javafx.beans.binding.Bindings; import javafx.beans.binding.Bindings;
@ -21,9 +24,7 @@ import javafx.beans.value.ObservableValue;
import javafx.collections.ListChangeListener; import javafx.collections.ListChangeListener;
import javafx.geometry.Insets; import javafx.geometry.Insets;
import javafx.geometry.Pos; import javafx.geometry.Pos;
import javafx.scene.control.Label; import javafx.scene.control.*;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
import javafx.scene.input.DragEvent; import javafx.scene.input.DragEvent;
import javafx.scene.input.KeyCode; import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyCodeCombination; import javafx.scene.input.KeyCodeCombination;
@ -31,10 +32,7 @@ import javafx.scene.input.KeyCombination;
import javafx.scene.layout.Region; import javafx.scene.layout.Region;
import javafx.scene.layout.StackPane; import javafx.scene.layout.StackPane;
import java.util.HashMap; import java.util.*;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.UUID;
import static atlantafx.base.theme.Styles.DENSE; import static atlantafx.base.theme.Styles.DENSE;
import static atlantafx.base.theme.Styles.toggleStyleClass; import static atlantafx.base.theme.Styles.toggleStyleClass;
@ -247,8 +245,65 @@ public class BrowserSessionTabsComp extends SimpleComp {
return tabs; return tabs;
} }
private ContextMenu createContextMenu(TabPane tabs, Tab tab) {
var cm = ContextMenuHelper.create();
var select = ContextMenuHelper.item(LabelGraphic.none(), AppI18n.get("selectTab"));
select.acceleratorProperty().bind(Bindings.createObjectBinding(() -> {
var start = KeyCode.F1.getCode();
var index = tabs.getTabs().indexOf(tab);
var keyCode = Arrays.stream(KeyCode.values()).filter(code -> code.getCode() == start + index).findAny().orElse(null);
return keyCode != null ? new KeyCodeCombination(keyCode) : null;
}, tabs.getTabs()));
cm.getItems().add(select);
cm.getItems().add(new SeparatorMenuItem());
var close = ContextMenuHelper.item(LabelGraphic.none(), AppI18n.get("closeTab" ));
close.setAccelerator(new KeyCodeCombination(KeyCode.W, KeyCombination.SHORTCUT_DOWN));
close.setOnAction(event -> {
tabs.getTabs().remove(tab);
event.consume();
});
cm.getItems().add(close);
var closeOthers = ContextMenuHelper.item(LabelGraphic.none(), AppI18n.get("closeOtherTabs"));
closeOthers.setOnAction(event -> {
tabs.getTabs().removeAll(tabs.getTabs().stream().filter(t -> t != tab).toList());
event.consume();
});
cm.getItems().add(closeOthers);
var closeLeft = ContextMenuHelper.item(LabelGraphic.none(), AppI18n.get("closeLeftTabs"));
closeLeft.setOnAction(event -> {
var index = tabs.getTabs().indexOf(tab);
tabs.getTabs().removeAll(tabs.getTabs().stream().filter(t -> tabs.getTabs().indexOf(t) < index).toList());
event.consume();
});
cm.getItems().add(closeLeft);
var closeRight = ContextMenuHelper.item(LabelGraphic.none(), AppI18n.get("closeRightTabs"));
closeRight.setOnAction(event -> {
var index = tabs.getTabs().indexOf(tab);
tabs.getTabs().removeAll(tabs.getTabs().stream().filter(t -> tabs.getTabs().indexOf(t) > index).toList());
event.consume();
});
cm.getItems().add(closeRight);
var closeAll = ContextMenuHelper.item(LabelGraphic.none(), AppI18n.get("closeAllTabs"));
closeAll.setAccelerator(new KeyCodeCombination(KeyCode.W, KeyCombination.SHORTCUT_DOWN, KeyCombination.SHIFT_DOWN));
closeAll.setOnAction(event -> {
tabs.getTabs().clear();
event.consume();
});
cm.getItems().add(closeAll);
return cm;
}
private Tab createTab(TabPane tabs, BrowserSessionTab<?> model) { private Tab createTab(TabPane tabs, BrowserSessionTab<?> model) {
var tab = new Tab(); var tab = new Tab();
tab.setContextMenu(createContextMenu(tabs, tab));
var ring = new RingProgressIndicator(0, false); var ring = new RingProgressIndicator(0, false);
ring.setMinSize(16, 16); ring.setMinSize(16, 16);

View file

@ -4,6 +4,7 @@ import io.xpipe.app.fxcomps.Comp;
import io.xpipe.app.fxcomps.CompStructure; import io.xpipe.app.fxcomps.CompStructure;
import io.xpipe.app.fxcomps.impl.IconButtonComp; import io.xpipe.app.fxcomps.impl.IconButtonComp;
import io.xpipe.app.fxcomps.impl.PrettyImageHelper; import io.xpipe.app.fxcomps.impl.PrettyImageHelper;
import io.xpipe.app.fxcomps.util.LabelGraphic;
import io.xpipe.app.util.ContextMenuHelper; import io.xpipe.app.util.ContextMenuHelper;
import javafx.geometry.Side; import javafx.geometry.Side;
@ -44,7 +45,7 @@ public class StoreQuickAccessButtonComp extends Comp<CompStructure<Button>> {
w.getEntry().getProvider().getDisplayIconFileName(w.getEntry().getStore()); w.getEntry().getProvider().getDisplayIconFileName(w.getEntry().getStore());
if (c.getList().isEmpty()) { if (c.getList().isEmpty()) {
var item = ContextMenuHelper.item( var item = ContextMenuHelper.item(
PrettyImageHelper.ofFixedSizeSquare(graphic, 16), new LabelGraphic.ImageGraphic(graphic, 16),
w.getName().getValue()); w.getName().getValue());
item.setOnAction(event -> { item.setOnAction(event -> {
action.accept(w); action.accept(w);

View file

@ -1,19 +1,22 @@
package io.xpipe.app.fxcomps.util; package io.xpipe.app.fxcomps.util;
import io.xpipe.app.fxcomps.Comp; import io.xpipe.app.fxcomps.Comp;
import io.xpipe.app.fxcomps.impl.PrettyImageHelper;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.value.ObservableValue;
import javafx.scene.Node; import javafx.scene.Node;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import lombok.Value; import lombok.Value;
import org.kordamp.ikonli.javafx.FontIcon; import org.kordamp.ikonli.javafx.FontIcon;
public abstract class LabelGraphic { public abstract class LabelGraphic {
public static ObservableValue<LabelGraphic> fixedIcon(String icon) { public static LabelGraphic none() {
return new SimpleObjectProperty<>(new IconGraphic(icon)); return new LabelGraphic() {
@Override
public Node createGraphicNode() {
return null;
}
};
} }
public abstract Node createGraphicNode(); public abstract Node createGraphicNode();
@ -30,6 +33,20 @@ public abstract class LabelGraphic {
} }
} }
@Value
@EqualsAndHashCode(callSuper = true)
public static class ImageGraphic extends LabelGraphic {
String file;
int size;
@Override
public Node createGraphicNode() {
return PrettyImageHelper.ofFixedSizeSquare(file, size).createRegion();
}
}
@Value @Value
@EqualsAndHashCode(callSuper = true) @EqualsAndHashCode(callSuper = true)
public static class CompGraphic extends LabelGraphic { public static class CompGraphic extends LabelGraphic {

View file

@ -1,7 +1,6 @@
package io.xpipe.app.util; package io.xpipe.app.util;
import io.xpipe.app.fxcomps.Comp; import io.xpipe.app.fxcomps.util.LabelGraphic;
import javafx.application.Platform; import javafx.application.Platform;
import javafx.geometry.Side; import javafx.geometry.Side;
import javafx.scene.Node; import javafx.scene.Node;
@ -36,14 +35,14 @@ public class ContextMenuHelper {
return contextMenu; return contextMenu;
} }
public static MenuItem item(Comp<?> graphic, String name) { public static MenuItem item(LabelGraphic graphic, String name) {
var i = new MenuItem(name, graphic.createRegion()); var i = new MenuItem(name, graphic.createGraphicNode());
return i; return i;
} }
public static void toggleShow(ContextMenu contextMenu, Node ref, Side side) { public static void toggleShow(ContextMenu contextMenu, Node ref, Side side) {
if (!contextMenu.isShowing()) { if (!contextMenu.isShowing()) {
contextMenu.show(ref, Side.RIGHT, 0, 0); contextMenu.show(ref, side, 0, 0);
} else { } else {
contextMenu.hide(); contextMenu.hide();
} }

View file

@ -481,3 +481,9 @@ copyId=Kopi ID
requireDoubleClickForConnections=Kræver dobbeltklik for forbindelser requireDoubleClickForConnections=Kræver dobbeltklik for forbindelser
requireDoubleClickForConnectionsDescription=Hvis den er aktiveret, skal du dobbeltklikke på forbindelser for at starte dem. Det er nyttigt, hvis man er vant til at dobbeltklikke på ting. requireDoubleClickForConnectionsDescription=Hvis den er aktiveret, skal du dobbeltklikke på forbindelser for at starte dem. Det er nyttigt, hvis man er vant til at dobbeltklikke på ting.
clearTransferDescription=Ryd valg clearTransferDescription=Ryd valg
selectTab=Vælg fane
closeTab=Luk fanen
closeOtherTabs=Luk andre faner
closeAllTabs=Luk alle faner
closeLeftTabs=Luk faner til venstre
closeRightTabs=Luk faner til højre

View file

@ -475,3 +475,9 @@ copyId=ID kopieren
requireDoubleClickForConnections=Doppelklick für Verbindungen erforderlich requireDoubleClickForConnections=Doppelklick für Verbindungen erforderlich
requireDoubleClickForConnectionsDescription=Wenn diese Funktion aktiviert ist, musst du auf die Verbindungen doppelklicken, um sie zu starten. Das ist nützlich, wenn du es gewohnt bist, auf Dinge doppelt zu klicken. requireDoubleClickForConnectionsDescription=Wenn diese Funktion aktiviert ist, musst du auf die Verbindungen doppelklicken, um sie zu starten. Das ist nützlich, wenn du es gewohnt bist, auf Dinge doppelt zu klicken.
clearTransferDescription=Auswahl löschen clearTransferDescription=Auswahl löschen
selectTab=Registerkarte auswählen
closeTab=Registerkarte schließen
closeOtherTabs=Andere Tabs schließen
closeAllTabs=Alle Registerkarten schließen
closeLeftTabs=Tabs nach links schließen
closeRightTabs=Tabs nach rechts schließen

View file

@ -480,3 +480,9 @@ copyId=Copy ID
requireDoubleClickForConnections=Require double click for connections requireDoubleClickForConnections=Require double click for connections
requireDoubleClickForConnectionsDescription=If enabled, you have to double-click connections to launch them. This is useful if you're used to double-clicking things. requireDoubleClickForConnectionsDescription=If enabled, you have to double-click connections to launch them. This is useful if you're used to double-clicking things.
clearTransferDescription=Clear selection clearTransferDescription=Clear selection
selectTab=Select tab
closeTab=Close tab
closeOtherTabs=Close other tabs
closeAllTabs=Close all tabs
closeLeftTabs=Close tabs to the left
closeRightTabs=Close tabs to the right

View file

@ -462,3 +462,9 @@ copyId=ID de copia
requireDoubleClickForConnections=Requiere doble clic para las conexiones requireDoubleClickForConnections=Requiere doble clic para las conexiones
requireDoubleClickForConnectionsDescription=Si está activado, tienes que hacer doble clic en las conexiones para iniciarlas. Esto es útil si estás acostumbrado a hacer doble clic en las cosas. requireDoubleClickForConnectionsDescription=Si está activado, tienes que hacer doble clic en las conexiones para iniciarlas. Esto es útil si estás acostumbrado a hacer doble clic en las cosas.
clearTransferDescription=Borrar selección clearTransferDescription=Borrar selección
selectTab=Seleccionar pestaña
closeTab=Cerrar pestaña
closeOtherTabs=Cerrar otras pestañas
closeAllTabs=Cerrar todas las pestañas
closeLeftTabs=Cerrar pestañas a la izquierda
closeRightTabs=Cerrar pestañas a la derecha

View file

@ -462,3 +462,9 @@ copyId=ID de copie
requireDoubleClickForConnections=Nécessite un double clic pour les connexions requireDoubleClickForConnections=Nécessite un double clic pour les connexions
requireDoubleClickForConnectionsDescription=Si cette option est activée, tu dois double-cliquer sur les connexions pour les lancer. C'est utile si tu as l'habitude de double-cliquer sur les choses. requireDoubleClickForConnectionsDescription=Si cette option est activée, tu dois double-cliquer sur les connexions pour les lancer. C'est utile si tu as l'habitude de double-cliquer sur les choses.
clearTransferDescription=Effacer la sélection clearTransferDescription=Effacer la sélection
selectTab=Onglet de sélection
closeTab=Fermer l'onglet
closeOtherTabs=Fermer d'autres onglets
closeAllTabs=Fermer tous les onglets
closeLeftTabs=Ferme les onglets à gauche
closeRightTabs=Ferme les onglets à droite

View file

@ -462,3 +462,9 @@ copyId=Copia ID
requireDoubleClickForConnections=Richiede un doppio clic per le connessioni requireDoubleClickForConnections=Richiede un doppio clic per le connessioni
requireDoubleClickForConnectionsDescription=Se abilitato, devi fare doppio clic sulle connessioni per avviarle. Questo è utile se sei abituato a fare doppio clic. requireDoubleClickForConnectionsDescription=Se abilitato, devi fare doppio clic sulle connessioni per avviarle. Questo è utile se sei abituato a fare doppio clic.
clearTransferDescription=Cancella la selezione clearTransferDescription=Cancella la selezione
selectTab=Seleziona scheda
closeTab=Chiudi scheda
closeOtherTabs=Chiudere altre schede
closeAllTabs=Chiudi tutte le schede
closeLeftTabs=Chiudere le schede a sinistra
closeRightTabs=Chiudere le schede a destra

View file

@ -462,3 +462,9 @@ copyId=コピーID
requireDoubleClickForConnections=接続にはダブルクリックが必要 requireDoubleClickForConnections=接続にはダブルクリックが必要
requireDoubleClickForConnectionsDescription=有効にすると、接続をダブルクリックしないと起動しなくなる。ダブルクリックに慣れている人には便利な機能だ。 requireDoubleClickForConnectionsDescription=有効にすると、接続をダブルクリックしないと起動しなくなる。ダブルクリックに慣れている人には便利な機能だ。
clearTransferDescription=選択範囲をクリアする clearTransferDescription=選択範囲をクリアする
selectTab=タブを選択する
closeTab=閉じるタブ
closeOtherTabs=他のタブを閉じる
closeAllTabs=すべてのタブを閉じる
closeLeftTabs=タブを左に閉じる
closeRightTabs=タブを右に閉じる

View file

@ -462,3 +462,9 @@ copyId=ID kopiëren
requireDoubleClickForConnections=Dubbelklikken vereist voor verbindingen requireDoubleClickForConnections=Dubbelklikken vereist voor verbindingen
requireDoubleClickForConnectionsDescription=Als dit is ingeschakeld, moet je dubbelklikken op verbindingen om ze te starten. Dit is handig als je gewend bent om op dingen te dubbelklikken. requireDoubleClickForConnectionsDescription=Als dit is ingeschakeld, moet je dubbelklikken op verbindingen om ze te starten. Dit is handig als je gewend bent om op dingen te dubbelklikken.
clearTransferDescription=Selectie wissen clearTransferDescription=Selectie wissen
selectTab=Tabblad selecteren
closeTab=Tabblad sluiten
closeOtherTabs=Andere tabbladen sluiten
closeAllTabs=Alle tabbladen sluiten
closeLeftTabs=Tabbladen naar links sluiten
closeRightTabs=Tabbladen naar rechts sluiten

View file

@ -462,3 +462,9 @@ copyId=ID de cópia
requireDoubleClickForConnections=Exige duplo clique para ligações requireDoubleClickForConnections=Exige duplo clique para ligações
requireDoubleClickForConnectionsDescription=Se estiver ativado, tens de fazer duplo clique nas ligações para as iniciar. Isto é útil se estiveres habituado a fazer duplo clique em coisas. requireDoubleClickForConnectionsDescription=Se estiver ativado, tens de fazer duplo clique nas ligações para as iniciar. Isto é útil se estiveres habituado a fazer duplo clique em coisas.
clearTransferDescription=Limpar seleção clearTransferDescription=Limpar seleção
selectTab=Selecionar separador
closeTab=Fecha o separador
closeOtherTabs=Fecha outros separadores
closeAllTabs=Fecha todos os separadores
closeLeftTabs=Fecha os separadores à esquerda
closeRightTabs=Fecha os separadores à direita

View file

@ -462,3 +462,9 @@ copyId=Идентификатор копии
requireDoubleClickForConnections=Требуется двойной щелчок для подключения requireDoubleClickForConnections=Требуется двойной щелчок для подключения
requireDoubleClickForConnectionsDescription=Если эта опция включена, тебе придется дважды щелкнуть по соединениям, чтобы запустить их. Это полезно, если ты привык все запускать двойным щелчком. requireDoubleClickForConnectionsDescription=Если эта опция включена, тебе придется дважды щелкнуть по соединениям, чтобы запустить их. Это полезно, если ты привык все запускать двойным щелчком.
clearTransferDescription=Четкий выбор clearTransferDescription=Четкий выбор
selectTab=Выберите вкладку
closeTab=Закройте вкладку
closeOtherTabs=Закрыть другие вкладки
closeAllTabs=Закрыть все вкладки
closeLeftTabs=Закрыть вкладки слева
closeRightTabs=Закрывать вкладки справа

View file

@ -463,3 +463,9 @@ copyId=Kopya Kimliği
requireDoubleClickForConnections=Bağlantılar için çift tıklama gerektir requireDoubleClickForConnections=Bağlantılar için çift tıklama gerektir
requireDoubleClickForConnectionsDescription=Etkinleştirilirse, bağlantıları başlatmak için çift tıklamanız gerekir. Bu, bir şeyleri çift tıklamaya alışkınsanız kullanışlıdır. requireDoubleClickForConnectionsDescription=Etkinleştirilirse, bağlantıları başlatmak için çift tıklamanız gerekir. Bu, bir şeyleri çift tıklamaya alışkınsanız kullanışlıdır.
clearTransferDescription=Seçimi temizle clearTransferDescription=Seçimi temizle
selectTab=Sekme seçin
closeTab=Sekmeyi kapat
closeOtherTabs=Diğer sekmeleri kapatın
closeAllTabs=Tüm sekmeleri kapat
closeLeftTabs=Sekmeleri sola doğru kapatın
closeRightTabs=Sekmeleri sağa doğru kapatın

View file

@ -462,3 +462,9 @@ copyId=复制 ID
requireDoubleClickForConnections=要求双击连接 requireDoubleClickForConnections=要求双击连接
requireDoubleClickForConnectionsDescription=如果启用,则必须双击连接才能启动。如果您习惯双击事物,这将非常有用。 requireDoubleClickForConnectionsDescription=如果启用,则必须双击连接才能启动。如果您习惯双击事物,这将非常有用。
clearTransferDescription=清除选择 clearTransferDescription=清除选择
selectTab=选择选项卡
closeTab=关闭选项卡
closeOtherTabs=关闭其他标签页
closeAllTabs=关闭所有标签页
closeLeftTabs=向左关闭标签
closeRightTabs=向右关闭标签页