Implemented canvas radio button
This commit is contained in:
parent
f569a5ac29
commit
7dd431cbbd
6 changed files with 237 additions and 69 deletions
|
@ -46,6 +46,7 @@ loadWidget("MenuBar");
|
|||
loadWidget("PropertyTree");
|
||||
loadWidget("PropertyWidgets");
|
||||
loadWidget("ScrollArea");
|
||||
loadWidget("RadioButton");
|
||||
loadWidget("Rule");
|
||||
loadWidget("Slider");
|
||||
loadWidget("TabWidget");
|
||||
|
|
|
@ -11,7 +11,6 @@ var WidgetsFactoryDialog = {
|
|||
.set("background", style.getColor("bg_color"))
|
||||
.createGroup();
|
||||
m.vbox = VBoxLayout.new();
|
||||
#m.vbox.setContentsMargin(10);
|
||||
m.window.setLayout(m.vbox);
|
||||
|
||||
m.menubar = canvas.gui.widgets.MenuBar.new(m.root, canvas.style, {});
|
||||
|
@ -22,12 +21,18 @@ var WidgetsFactoryDialog = {
|
|||
tabsMenu.createItem(text: "Select first tab", cb: func m.tabs.setCurrentTab("tab-1"));
|
||||
tabsMenu.createItem(text: "Select second tab", cb: func m.tabs.setCurrentTab("tab-2"));
|
||||
|
||||
m.menubar.createMenu("Widgets")
|
||||
.createItem(text: "Benchmark label", cb: func {
|
||||
m.benchmark_widget(canvas.gui.widgets.Label, func(w, i) {
|
||||
w.setText("Label " ~ i);
|
||||
});
|
||||
});
|
||||
var widgetsMenu = m.menubar.createMenu("Widgets");
|
||||
widgetsMenu.createItem(text: "Benchmark label", cb: func {
|
||||
m.benchmark_widget(canvas.gui.widgets.Label, func(w, i) {
|
||||
w.setText("Label " ~ i);
|
||||
});
|
||||
});
|
||||
|
||||
widgetsMenu.createItem(text: "Benchmark radio button", cb: func {
|
||||
m.benchmark_radio_button(func(w, i) {
|
||||
w.setText("Radio button " ~ i);
|
||||
});
|
||||
});
|
||||
m.vbox.addItem(m.menubar);
|
||||
|
||||
m.tabs = gui.widgets.TabWidget.new(m.root, style, {});
|
||||
|
@ -45,11 +50,11 @@ var WidgetsFactoryDialog = {
|
|||
r.setText("Checkboxes!");
|
||||
m.tab_1.addItem(r);
|
||||
|
||||
m.checkbox_left = gui.widgets.CheckBox.new(m.tabsContent, style, {"label-position": "right"})
|
||||
m.checkbox_left = gui.widgets.CheckBox.new(m.tabsContent, style, {})
|
||||
.setText("Wanna check something ?");
|
||||
m.tab_1.addItem(m.checkbox_left);
|
||||
m.checkbox_right = gui.widgets.CheckBox.new(m.tabsContent, style, {"label-position": "right"})
|
||||
.setText("Checkbox with text on the right side");
|
||||
m.checkbox_right = gui.widgets.CheckBox.new(m.tabsContent, style, {"label-position": "left"})
|
||||
.setText("Checkbox with text on the left side");
|
||||
m.tab_1.addItem(m.checkbox_right);
|
||||
m.property_checkbox = gui.widgets.PropertyCheckBox.new(props.globals.getNode("/controls/lighting/nav-lights"), m.tabsContent, style, {})
|
||||
.setText("Nav lights");
|
||||
|
@ -57,6 +62,19 @@ var WidgetsFactoryDialog = {
|
|||
|
||||
var r2 = gui.widgets.HorizontalRule.new(m.tabsContent, style, {});
|
||||
m.tab_1.addItem(r2);
|
||||
|
||||
m.radio1 = gui.widgets.RadioButton.new(m.tabsContent)
|
||||
.setText("Radio button 1");
|
||||
m.tab_1.addItem(m.radio1);
|
||||
m.radio2 = gui.widgets.RadioButton.new(parent: m.tabsContent, cfg: {parentRadio: m.radio1})
|
||||
.setText("Radio button 2");
|
||||
m.tab_1.addItem(m.radio2);
|
||||
m.radio3 = gui.widgets.RadioButton.new(parent: m.tabsContent, cfg: {parentRadio: m.radio1})
|
||||
.setText("Radio button 3");
|
||||
m.tab_1.addItem(m.radio3);
|
||||
m.radio4 = gui.widgets.RadioButton.new(parent: m.tabsContent, cfg: {parentRadio: m.radio1})
|
||||
.setText("Radio button 4");
|
||||
m.tab_1.addItem(m.radio4);
|
||||
|
||||
m.tab_2 = HBoxLayout.new();
|
||||
m.tabs.addTab("tab-2", "Tab 2", m.tab_2);
|
||||
|
@ -145,6 +163,7 @@ var WidgetsFactoryDialog = {
|
|||
m.benchmark_tab_scroll = canvas.gui.widgets.ScrollArea.new(m.tabsContent, canvas.style, {});
|
||||
m.benchmark_tab_scroll.setSizeHint([m.list._MAX_SIZE, m.list._MAX_SIZE]);
|
||||
m.benchmark_tab_scroll_layout = VBoxLayout.new();
|
||||
m.benchmark_tab_scroll_layout.setSpacing(0);
|
||||
m.benchmark_tab_scroll.setLayout(m.benchmark_tab_scroll_layout);
|
||||
m.benchmark_tab.addItem(m.benchmark_tab_scroll);
|
||||
m.benchmark_statistics = canvas.gui.widgets.Label.new(m.tabsContent, canvas.style, {});
|
||||
|
@ -185,6 +204,21 @@ var WidgetsFactoryDialog = {
|
|||
me.benchmark_statistics.setText("Took " ~ time ~ " seconds to add " ~ amount ~ " widgets.");
|
||||
},
|
||||
|
||||
benchmark_radio_button: func(proc_func=nil, amount=50) {
|
||||
var start = systime();
|
||||
me.benchmark_tab_scroll_layout.clear();
|
||||
var r = canvas.gui.widgets.RadioButton.new(me.benchmark_tab_scroll.getContent());
|
||||
for (var i = 1; i < amount; i += 1) {
|
||||
var w = canvas.gui.widgets.RadioButton.new(me.benchmark_tab_scroll.getContent(), canvas.style, {parentRadio: r});
|
||||
if (proc_func != nil) {
|
||||
proc_func(w, i);
|
||||
}
|
||||
me.benchmark_tab_scroll_layout.addItem(w);
|
||||
}
|
||||
var time = systime() - start;
|
||||
me.benchmark_statistics.setText("Took " ~ time ~ " seconds to add " ~ amount ~ " widgets.");
|
||||
},
|
||||
|
||||
del: func {
|
||||
me.property_checkbox.del();
|
||||
me.window.del();
|
||||
|
|
|
@ -176,6 +176,73 @@ DefaultStyle.widgets.checkbox = {
|
|||
}
|
||||
};
|
||||
|
||||
# A checkbox
|
||||
DefaultStyle.widgets["radio-button"] = {
|
||||
new: func(parent, cfg) {
|
||||
me._root = parent.createChild("group", "radio-button");
|
||||
me._bg = me._root.createChild("path");
|
||||
me._icon = me._root.createChild("group", "radio-button-icon");
|
||||
me._icon_background = me._icon.createChild("path", "radio-button-icon-border")
|
||||
.circle(8.5, 9, 9);
|
||||
me._icon_selected_indicator = me._icon.createChild("path", "radio-button-icon-selected-indicator")
|
||||
.circle(6, 9, 9)
|
||||
.set("stroke-width", 5);
|
||||
me._icon_border = me._icon.createChild("path", "radio-button-icon-border")
|
||||
.circle(8, 9, 9)
|
||||
.set("stroke-width", 1);
|
||||
me._label = me._root.createChild("text")
|
||||
.set("font", "LiberationFonts/LiberationSans-Regular.ttf")
|
||||
.set("character-size", 14)
|
||||
.set("alignment", "left-center");
|
||||
},
|
||||
setSize: func(model, w, h) {
|
||||
me._bg.reset().rect(0, 0, w, h);
|
||||
me._icon.setTranslation(3, int((h - 18) / 2));
|
||||
me._label.setTranslation(24, int(h / 2) + 1);
|
||||
|
||||
return me;
|
||||
},
|
||||
setText: func(model, text) {
|
||||
me._label.setText(text);
|
||||
|
||||
var min_width = me._label.maxWidth() + 3 + 24;
|
||||
model.setLayoutMinimumSize([min_width, 24]);
|
||||
model.setLayoutSizeHint([min_width, 24]);
|
||||
|
||||
return me;
|
||||
},
|
||||
update: func(model) {
|
||||
var backdrop = !model._windowFocus();
|
||||
|
||||
me._bg.set("fill", me._style.getColor("radio_button_bg_color" ~ (model._hover ? "_hovered" : "")));
|
||||
|
||||
me._icon_border.set("stroke", me._style.getColor("radio_button_selected_indicator_border_color"));
|
||||
if (backdrop) {
|
||||
me._label.set("fill", me._style.getColor("backdrop_fg_color"));
|
||||
} else {
|
||||
me._label.set("fill", me._style.getColor("fg_color"));
|
||||
}
|
||||
|
||||
if (model._checked) {
|
||||
me._icon_selected_indicator.show();
|
||||
} else {
|
||||
me._icon_selected_indicator.hide();
|
||||
}
|
||||
|
||||
if (model._enabled) {
|
||||
if (model._hover) {
|
||||
me._icon_background.set("fill", me._style.getColor("radio_button_selected_indicator_bg_color_hovered"));
|
||||
} else {
|
||||
me._icon_background.set("fill", me._style.getColor("radio_button_selected_indicator_bg_color"));
|
||||
}
|
||||
me._icon_selected_indicator.set("stroke", me._style.getColor("radio_button_selected_indicator_color"));
|
||||
} else {
|
||||
me._icon_background.set("fill", me._style.getColor("radio_button_selected_indicator_bg_color_disabled"));
|
||||
me._icon_selected_indicator.set("stroke", me._style.getColor("radio_button_selected_indicator_color_disabled"));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
# A label
|
||||
DefaultStyle.widgets.label = {
|
||||
new: func(parent, cfg)
|
||||
|
|
|
@ -5,17 +5,17 @@
|
|||
gui.widgets.Button = {
|
||||
new: func(parent, style, cfg)
|
||||
{
|
||||
var cfg = Config.new(cfg);
|
||||
var m = gui.Widget.new(gui.widgets.Button);
|
||||
m._cfg = Config.new(cfg);
|
||||
m._focus_policy = m.StrongFocus;
|
||||
m._down = 0;
|
||||
m._checkable = 0;
|
||||
m._flat = cfg.get("flat", 0);
|
||||
m._isDefault = cfg.get("default", 0);
|
||||
m._destructive = cfg.get("destructive", 0);
|
||||
m._flat = m._cfg.get("flat", 0);
|
||||
m._isDefault = m._cfg.get("default", 0);
|
||||
m._destructive = m._cfg.get("destructive", 0);
|
||||
|
||||
if( style != nil and !m._flat )
|
||||
m._setView( style.createWidget(parent, cfg.get("type", "button"), cfg) );
|
||||
m._setView( style.createWidget(parent, m._cfg.get("type", "button"), m._cfg) );
|
||||
|
||||
return m;
|
||||
},
|
||||
|
|
|
@ -1,95 +1,113 @@
|
|||
# RadioButton.nas : radio button, and group helper
|
||||
# to manage updating checked state conherently
|
||||
# SPDX-FileCopyrightText: (C) 2022 James Turner <james@flightgear.org>
|
||||
# SPDX-FileCopyrightText: (C) 2022 James Turner <james@flightgear.org>, Frederic Croix <thefgfseagle@gmail.com>
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
gui.widgets.RadioButton = {
|
||||
new: func(parent, style, cfg)
|
||||
{
|
||||
cfg["type"] = "radio";
|
||||
var m = gui.widgets.Button.new(parent, style, cfg);
|
||||
m._checkable = 1;
|
||||
new: func(parent, style = nil, cfg = nil) {
|
||||
var m = gui.Widget.new(gui.widgets.RadioButton);
|
||||
style = style or canvas.style;
|
||||
m._cfg = Config.new(cfg or {});
|
||||
m._focus_policy = m.StrongFocus;
|
||||
m._checked = 0;
|
||||
m.radioGroup = nil;
|
||||
|
||||
append(m.parents, gui.widgets.RadioButton);
|
||||
m._setView( style.createWidget(parent, m._cfg.get("type", "radio-button"), m._cfg) );
|
||||
|
||||
if (contains(pr, "radioGroup") {
|
||||
pr.radioGroup.addRadio(m);
|
||||
var parentRadio = m._cfg.get("parentRadio", nil);
|
||||
if (parentRadio != nil) {
|
||||
m.radioGroup = parentRadio.radioGroup;
|
||||
} else {
|
||||
m.radioGroup = gui.widgets.RadioButtonsGroup.new();
|
||||
}
|
||||
m.radioGroup.addRadio(m);
|
||||
|
||||
return m;
|
||||
},
|
||||
|
||||
del: func()
|
||||
{
|
||||
var pr = getParent();
|
||||
if (contains(pr, "radioGroup") {
|
||||
pr.radioGroup.removeRadio(me);
|
||||
}
|
||||
setText: func(text) {
|
||||
me._view.setText(me, text);
|
||||
return me;
|
||||
},
|
||||
|
||||
setCheckable: nil,
|
||||
setChecked: func(checked = 1)
|
||||
{
|
||||
# call our base version
|
||||
me.parents[0].setChecked(checked);
|
||||
if (checked) {
|
||||
me._setRadioGroupSiblingsUnchecked();
|
||||
setChecked: func(checked = 1) {
|
||||
if (me._checked == checked) {
|
||||
return me;
|
||||
}
|
||||
|
||||
me._setRadioGroupSiblingsUnchecked();
|
||||
me._trigger("toggled", {checked: checked});
|
||||
me._checked = checked;
|
||||
me._onStateChange();
|
||||
return me;
|
||||
},
|
||||
|
||||
_setRadioGroupSiblingsUnchecked: func {
|
||||
me.radioGroup._updateChecked(me);
|
||||
},
|
||||
|
||||
toggle: func {
|
||||
me.setChecked(!me._checked);
|
||||
return me;
|
||||
},
|
||||
|
||||
_setView: func(view) {
|
||||
call(gui.Widget._setView, [view], me);
|
||||
|
||||
var el = view._root;
|
||||
el.addEventListener("click", func {
|
||||
if (me._enabled) {
|
||||
me.setChecked()
|
||||
}
|
||||
});
|
||||
|
||||
el.addEventListener("drag", func(e) e.stopPropagation());
|
||||
},
|
||||
# protected members
|
||||
_setRadioGroupSiblingsUnchecked: func
|
||||
{
|
||||
var pr = getParent();
|
||||
if (contains(pr, "radioGroup") {
|
||||
pr.radioGroup._updateChecked(me);
|
||||
} else {
|
||||
# todo, remove me, it's okay to manually manage RadioButtons
|
||||
logprint(LOG_DEV, "No radio group defined");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
# auto manage radio-button checked state
|
||||
gui.widgets.RadioGroup = {
|
||||
new: func(nm = 'unnamed')
|
||||
gui.widgets.RadioButtonsGroup = {
|
||||
new: func(name = "unnamed")
|
||||
{
|
||||
var m = {parents:[gui.widgets.RadioGroup, name:nm, radios:[]]};
|
||||
var m = {
|
||||
parents: [gui.widgets.RadioButtonsGroup],
|
||||
name: name,
|
||||
radios: [],
|
||||
};
|
||||
return m;
|
||||
},
|
||||
|
||||
addRadio: func(r)
|
||||
{
|
||||
if (r.parents[0] != RadioButton) {
|
||||
logprint(LOG_ALERT, "Adding non-RadioButton to RadioGroup")
|
||||
return;
|
||||
}
|
||||
r.listen("toggled", func(e) {
|
||||
me._updateChecked(r);
|
||||
});
|
||||
append(me.radios, r);
|
||||
},
|
||||
|
||||
removeRadio: func(r)
|
||||
{
|
||||
if (r.parents[0] != RadioButton) {
|
||||
logprint(LOG_ALERT, "Remove non-RadioButton from RadioGroup")
|
||||
return;
|
||||
# XXX should we update some other item to be checked ?
|
||||
if (contains(me.radios, r)) {
|
||||
var index = find(r, me.radios);
|
||||
me.radios = subvec(me.radios, 0, index) ~ subvec(me.radios, index + 1);
|
||||
}
|
||||
|
||||
# should we update some other item to be checked?
|
||||
me.radios.remove(r);
|
||||
},
|
||||
|
||||
setEnabled: func(doEnable = 1)
|
||||
setEnabled: func(enabled = 1)
|
||||
{
|
||||
foreach (var r : me.radios) {
|
||||
r.setEnabled(doEnable);
|
||||
foreach (var r; me.radios) {
|
||||
r.setEnabled(enabled);
|
||||
}
|
||||
},
|
||||
|
||||
# protected methods
|
||||
# update check state of all radios in the group
|
||||
_updateChecked: func(active)
|
||||
{
|
||||
foreach (var r : me.radios) {
|
||||
r.setChecked(r == active);
|
||||
foreach (var r; me.radios) {
|
||||
if (r != active) {
|
||||
r.setChecked(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
},
|
||||
};
|
||||
|
|
|
@ -209,5 +209,53 @@
|
|||
<green type="float">0.15</green>
|
||||
<blue type="float">1</blue>
|
||||
</list_item_bg_selected>
|
||||
|
||||
<radio_button_bg_color>
|
||||
<red type="float">0.949</red>
|
||||
<green type="float">0.945</green>
|
||||
<blue type="float">0.941</blue>
|
||||
</radio_button_bg_color>
|
||||
|
||||
<radio_button_bg_color_hovered>
|
||||
<red type="float">0.989</red>
|
||||
<green type="float">0.985</green>
|
||||
<blue type="float">0.981</blue>
|
||||
</radio_button_bg_color_hovered>
|
||||
|
||||
<radio_button_selected_indicator_bg_color>
|
||||
<red type="float">1</red>
|
||||
<green type="float">1</green>
|
||||
<blue type="float">1</blue>
|
||||
</radio_button_selected_indicator_bg_color>
|
||||
|
||||
<radio_button_selected_indicator_bg_color_hovered>
|
||||
<red type="float">0.95</red>
|
||||
<green type="float">0.95</green>
|
||||
<blue type="float">0.95</blue>
|
||||
</radio_button_selected_indicator_bg_color_hovered>
|
||||
|
||||
<radio_button_selected_indicator_bg_color_disabled>
|
||||
<red type="float">0.9</red>
|
||||
<green type="float">0.9</green>
|
||||
<blue type="float">0.9</blue>
|
||||
</radio_button_selected_indicator_bg_color_disabled>
|
||||
|
||||
<radio_button_selected_indicator_border_color>
|
||||
<red type="float">0.5</red>
|
||||
<green type="float">0.5</green>
|
||||
<blue type="float">0.5</blue>
|
||||
</radio_button_selected_indicator_border_color>
|
||||
|
||||
<radio_button_selected_indicator_color>
|
||||
<red type="float">0.25</red>
|
||||
<green type="float">0.25</green>
|
||||
<blue type="float">1</blue>
|
||||
</radio_button_selected_indicator_color>
|
||||
|
||||
<radio_button_selected_indicator_color_disabled>
|
||||
<red type="float">0.5</red>
|
||||
<green type="float">0.5</green>
|
||||
<blue type="float">1</blue>
|
||||
</radio_button_selected_indicator_color_disabled>
|
||||
</colors>
|
||||
</PropertyList>
|
||||
|
|
Loading…
Reference in a new issue