1
0
Fork 0
fgdata/Nasal/canvas/gui/widgets/TabWidget.nas
2023-01-03 12:39:51 +00:00

162 lines
3.7 KiB
Text

# TabWidget.nas - widget with a tabs bar and a content area which always displays
# exactly one of its tabs
# SPDX-FileCopyrightText: (C) 2022 Frederic Croix <thefgfseagle@gmail.com>
# SPDX-License-Identifier: GPL-2.0-or-later
gui.widgets.TabWidgetTabButton = {
new: func(parent, style, cfg) {
var cfg = Config.new(cfg);
var m = gui.Widget.new(gui.widgets.TabWidgetTabButton);
m._focus_policy = m.StrongFocus;
m._selected = 0;
m._setView(style.createWidget(parent, "tab-widget-tab-button", cfg));
return m;
},
setText: func(text) {
me._view.setText(me, text);
return me;
},
setSelected: func(selected = 1) {
if (me._selected == selected) {
return me;
}
me._selected = selected;
me._trigger("toggled", {selected: selected});
me._onStateChange();
me._view.update(me);
return me;
},
_setView: func(view) {
call(gui.Widget._setView, [view], me);
var el = view._root;
#el.addEventListener("mousedown", func me.dragStart());
#el.addEventListener("mouseup", func me.dragStop());
el.addEventListener("click", func me.setSelected());
el.addEventListener("drag", func(e) { e.stopPropagation() });
#el.addEventListener("drag", me.drag);
}
};
gui.widgets.TabWidget = {
new: func(parent, style, cfg) {
var m = gui.Widget.new(gui.widgets.TabWidget);
m._cfg = Config.new(cfg);
m._focus_policy = m.NoFocus;
m._setView(style.createWidget(parent, "tab-widget", m._cfg));
m._layout = VBoxLayout.new();
m._layout.setCanvas(m._view._root.getCanvas());
m._tabBar = HBoxLayout.new();
m._layout.addItem(m._tabBar);
m._currentTab = nil;
m._currentTabId = nil;
m._tabs = {};
m._tabButtons = {};
m.setLayoutMinimumSize([50, 30]);
m.setLayoutSizeHint([100, 30]);
return m;
},
hasTab: func(id) {
return me._tabs[id] != nil;
},
getTab: func(id) {
if (!me.hasTab(id)) {
die("tab with id '" ~ id ~ "' does not exist");
}
return me._tabs[id];
},
addTab: func(id, label, widget) {
if (me.hasTab(id)) {
die("cannot add multiple tabs with the same id: " ~ id);
}
me._tabButtons[id] = gui.widgets.TabWidgetTabButton.new(me._view._root, canvas.style, {})
.setText(label)
.listen("toggled", func (e) {
if (e.detail.selected and id != me._currentTabId) {
me.setCurrentTab(id);
}
});
me._tabBar.addItem(me._tabButtons[id]);
me._tabs[id] = widget;
me._layout.addItem(widget);
me.setCurrentTab(keys(me._tabs)[0]);
return me;
},
removeTab: func(id) {
if (!me.hasTab(id)) {
die("tab with id '" ~ id ~ "' does not exist");
}
me._tabs[id].setVisible(0);
me._layout.removeItem(me._tabs[id]);
delete(me._tabs, id);
me._tabBar.removeItem(me._tabButtons[id]);
delete(me._tabButtons, id);
if (size(keys(me._tabs)) > 0) {
me.setCurrentTab(keys(me._tabs)[-1]);
}
return me;
},
setCurrentTab: func(id) {
if (!me.hasTab(id)) {
die("tab with id '" ~ id ~ "' does not exist");
}
if (me._currentTabId) {
me._tabButtons[me._currentTabId].setSelected(0);
}
me._tabButtons[id].setSelected();
foreach (var tabid; keys(me._tabs)) {
me._tabs[tabid].setVisible(0);
}
me._tabs[id].setVisible(1);
me._currentTabId = id;
me._currentTab = me._tabs[id];
return me.update();
},
setSize: func {
if (size(arg) == 1) {
var arg = arg[0];
}
var (x, y) = arg;
me._size = [x, y];
return me.update();
},
# Needs to be called when the size of the content changes.
update: func() {
if(me._layout.getParent() == nil) {
me._layout.setParent(me);
}
me._tabBar.setGeometry([0, 0, me._size[0], me._view.tabBarHeight]);
if (me._currentTab) {
me._currentTab.setGeometry([0, me._view.tabBarHeight, me._size[0], me._size[1] - me._view.tabBarHeight]);
}
me._view.update(me);
return me;
},
};