mirror of https://github.com/buggins/dlangui.git
409 lines
13 KiB
D
409 lines
13 KiB
D
module dlangui.dialogs.settingsdialog;
|
|
|
|
import dlangui.core.events;
|
|
import dlangui.core.i18n;
|
|
import dlangui.core.stdaction;
|
|
import dlangui.core.files;
|
|
public import dlangui.core.settings;
|
|
import dlangui.widgets.controls;
|
|
import dlangui.widgets.lists;
|
|
import dlangui.widgets.layouts;
|
|
import dlangui.widgets.tree;
|
|
import dlangui.widgets.editors;
|
|
import dlangui.widgets.menu;
|
|
import dlangui.widgets.combobox;
|
|
import dlangui.widgets.styles;
|
|
import dlangui.platforms.common.platform;
|
|
import dlangui.dialogs.dialog;
|
|
|
|
private import std.algorithm;
|
|
private import std.file;
|
|
private import std.path;
|
|
private import std.utf;
|
|
private import std.conv : to;
|
|
private import std.array : split;
|
|
|
|
/// item on settings page
|
|
class SettingsItem {
|
|
protected string _id;
|
|
protected UIString _label;
|
|
protected SettingsPage _page;
|
|
this(string id, UIString label) {
|
|
_id = id;
|
|
_label = label;
|
|
}
|
|
/// setting path, e.g. "editor/tabSize"
|
|
@property string id() { return _id; }
|
|
@property ref UIString label() { return _label; }
|
|
/// create setting widget
|
|
Widget[] createWidgets(Setting settings) {
|
|
TextWidget res = new TextWidget(_id, _label);
|
|
return [res];
|
|
}
|
|
}
|
|
|
|
/// checkbox setting
|
|
class CheckboxItem : SettingsItem {
|
|
private bool _inverse;
|
|
this(string id, UIString label, bool inverse = false) {
|
|
super(id, label);
|
|
_inverse = inverse;
|
|
}
|
|
/// create setting widget
|
|
override Widget[] createWidgets(Setting settings) {
|
|
CheckBox res = new CheckBox(_id, _label);
|
|
Setting setting = settings.settingByPath(_id, SettingType.FALSE);
|
|
res.checked = setting.boolean ^ _inverse;
|
|
res.checkChange = delegate(Widget source, bool checked) {
|
|
setting.boolean = checked ^ _inverse;
|
|
return true;
|
|
};
|
|
return [res];
|
|
}
|
|
}
|
|
|
|
/// ComboBox based setting with string keys
|
|
class StringComboBoxItem : SettingsItem {
|
|
protected StringListValue[] _items;
|
|
this(string id, UIString label, StringListValue[] items) {
|
|
super(id, label);
|
|
_items = items;
|
|
}
|
|
/// create setting widget
|
|
override Widget[] createWidgets(Setting settings) {
|
|
TextWidget lbl = new TextWidget(_id ~ "-label", _label);
|
|
ComboBox cb = new ComboBox(_id, _items);
|
|
//cb.minWidth = 100;
|
|
Setting setting = settings.settingByPath(_id, SettingType.STRING);
|
|
string itemId = setting.str;
|
|
int index = -1;
|
|
for (int i = 0; i < _items.length; i++) {
|
|
if (_items[i].stringId.equal(itemId)) {
|
|
index = i;
|
|
break;
|
|
}
|
|
}
|
|
if (index >= 0)
|
|
cb.selectedItemIndex = index;
|
|
cb.itemClick = delegate(Widget source, int itemIndex) {
|
|
if (itemIndex >= 0 && itemIndex < _items.length)
|
|
setting.str = _items[itemIndex].stringId;
|
|
return true;
|
|
};
|
|
return [lbl, cb];
|
|
}
|
|
}
|
|
|
|
/// ComboBox based setting with int keys
|
|
class IntComboBoxItem : SettingsItem {
|
|
protected StringListValue[] _items;
|
|
this(string id, UIString label, StringListValue[] items) {
|
|
super(id, label);
|
|
_items = items;
|
|
}
|
|
/// create setting widget
|
|
override Widget[] createWidgets(Setting settings) {
|
|
TextWidget lbl = new TextWidget(_id ~ "-label", _label);
|
|
ComboBox cb = new ComboBox(_id, _items);
|
|
//cb.minWidth = 100;
|
|
Setting setting = settings.settingByPath(_id, SettingType.INTEGER);
|
|
long itemId = setting.integer;
|
|
int index = -1;
|
|
for (int i = 0; i < _items.length; i++) {
|
|
if (_items[i].intId == itemId) {
|
|
index = i;
|
|
break;
|
|
}
|
|
}
|
|
if (index >= 0)
|
|
cb.selectedItemIndex = index;
|
|
cb.itemClick = delegate(Widget source, int itemIndex) {
|
|
if (itemIndex >= 0 && itemIndex < _items.length)
|
|
setting.integer = _items[itemIndex].intId;
|
|
return true;
|
|
};
|
|
return [lbl, cb];
|
|
}
|
|
}
|
|
|
|
/// ComboBox based setting with floating point keys (actualy, fixed point digits after period is specidied by divider constructor parameter)
|
|
class FloatComboBoxItem : SettingsItem {
|
|
protected StringListValue[] _items;
|
|
protected long _divider;
|
|
this(string id, UIString label, StringListValue[] items, long divider = 1000) {
|
|
super(id, label);
|
|
_items = items;
|
|
_divider = divider;
|
|
}
|
|
/// create setting widget
|
|
override Widget[] createWidgets(Setting settings) {
|
|
TextWidget lbl = new TextWidget(_id ~ "-label", _label);
|
|
ComboBox cb = new ComboBox(_id, _items);
|
|
//cb.minWidth = 100;
|
|
Setting setting = settings.settingByPath(_id, SettingType.FLOAT);
|
|
long itemId = cast(long)(setting.floating * _divider);
|
|
int index = -1;
|
|
for (int i = 0; i < _items.length; i++) {
|
|
if (_items[i].intId == itemId) {
|
|
index = i;
|
|
break;
|
|
}
|
|
}
|
|
if (index >= 0)
|
|
cb.selectedItemIndex = index;
|
|
cb.itemClick = delegate(Widget source, int itemIndex) {
|
|
if (itemIndex >= 0 && itemIndex < _items.length)
|
|
setting.floating = _items[itemIndex].intId / cast(double)_divider;
|
|
return true;
|
|
};
|
|
return [lbl, cb];
|
|
}
|
|
}
|
|
|
|
class NumberEditItem : SettingsItem {
|
|
protected int _minValue;
|
|
protected int _maxValue;
|
|
protected int _defaultValue;
|
|
this(string id, UIString label, int minValue = int.max, int maxValue = int.max, int defaultValue = 0) {
|
|
super(id, label);
|
|
_minValue = minValue;
|
|
_maxValue = maxValue;
|
|
_defaultValue = defaultValue;
|
|
}
|
|
/// create setting widget
|
|
override Widget[] createWidgets(Setting settings) {
|
|
TextWidget lbl = new TextWidget(_id ~ "-label", _label);
|
|
EditLine ed = new EditLine(_id ~ "-edit", _label);
|
|
Setting setting = settings.settingByPath(_id, SettingType.INTEGER);
|
|
int n = cast(int)setting.integerDef(_defaultValue);
|
|
if (_minValue != int.max && n < _minValue)
|
|
n = _minValue;
|
|
if (_maxValue != int.max && n > _maxValue)
|
|
n = _maxValue;
|
|
setting.integer = cast(long)n;
|
|
ed.text = toUTF32(to!string(n));
|
|
ed.contentChange = delegate(EditableContent content) {
|
|
long v = parseLong(toUTF8(content.text), long.max);
|
|
if (v != long.max) {
|
|
if ((_minValue == int.max || v >= _minValue) && (_maxValue == int.max || v <= _maxValue)) {
|
|
setting.integer = v;
|
|
ed.textColor = 0x000000;
|
|
} else {
|
|
ed.textColor = 0xFF0000;
|
|
}
|
|
}
|
|
};
|
|
return [lbl, ed];
|
|
}
|
|
}
|
|
|
|
class StringEditItem : SettingsItem {
|
|
string _defaultValue;
|
|
this(string id, UIString label, string defaultValue) {
|
|
super(id, label);
|
|
_defaultValue = defaultValue;
|
|
}
|
|
/// create setting widget
|
|
override Widget[] createWidgets(Setting settings) {
|
|
TextWidget lbl = new TextWidget(_id ~ "-label", _label);
|
|
EditLine ed = new EditLine(_id ~ "-edit", _label);
|
|
Setting setting = settings.settingByPath(_id, SettingType.STRING);
|
|
string value = setting.strDef(_defaultValue);
|
|
setting.str = value;
|
|
ed.text = toUTF32(value);
|
|
ed.contentChange = delegate(EditableContent content) {
|
|
string value = toUTF8(content.text);
|
|
setting.str = value;
|
|
};
|
|
return [lbl, ed];
|
|
}
|
|
}
|
|
|
|
/// settings page - item of settings tree, can edit several settings
|
|
class SettingsPage {
|
|
protected SettingsPage _parent;
|
|
protected ObjectList!SettingsPage _children;
|
|
protected ObjectList!SettingsItem _items;
|
|
protected string _id;
|
|
protected UIString _label;
|
|
|
|
this(string id, UIString label) {
|
|
_id = id;
|
|
_label = label;
|
|
}
|
|
|
|
@property string id() { return _id; }
|
|
@property ref UIString label() { return _label; }
|
|
|
|
@property int childCount() {
|
|
return _children.count;
|
|
}
|
|
|
|
/// returns child page by index
|
|
SettingsPage child(int index) {
|
|
return _children[index];
|
|
}
|
|
|
|
SettingsPage addChild(SettingsPage item) {
|
|
_children.add(item);
|
|
item._parent = this;
|
|
return item;
|
|
}
|
|
|
|
SettingsPage addChild(string id, UIString label) {
|
|
return addChild(new SettingsPage(id, label));
|
|
}
|
|
|
|
@property int itemCount() {
|
|
return _items.count;
|
|
}
|
|
|
|
/// returns page item by index
|
|
SettingsItem item(int index) {
|
|
return _items[index];
|
|
}
|
|
|
|
SettingsItem addItem(SettingsItem item) {
|
|
_items.add(item);
|
|
item._page = this;
|
|
return item;
|
|
}
|
|
|
|
/// add checkbox (boolean value) for setting
|
|
CheckboxItem addCheckbox(string id, UIString label, bool inverse = false) {
|
|
CheckboxItem res = new CheckboxItem(id, label, inverse);
|
|
addItem(res);
|
|
return res;
|
|
}
|
|
|
|
/// add EditLine to edit number
|
|
NumberEditItem addNumberEdit(string id, UIString label, int minValue = int.max, int maxValue = int.max, int defaultValue = 0) {
|
|
NumberEditItem res = new NumberEditItem(id, label, minValue, maxValue, defaultValue);
|
|
addItem(res);
|
|
return res;
|
|
}
|
|
|
|
/// add EditLine to edit string
|
|
StringEditItem addStringEdit(string id, UIString label, string defaultValue = "") {
|
|
StringEditItem res = new StringEditItem(id, label, defaultValue);
|
|
addItem(res);
|
|
return res;
|
|
}
|
|
|
|
StringComboBoxItem addStringComboBox(string id, UIString label, StringListValue[] items) {
|
|
StringComboBoxItem res = new StringComboBoxItem(id, label, items);
|
|
addItem(res);
|
|
return res;
|
|
}
|
|
|
|
IntComboBoxItem addIntComboBox(string id, UIString label, StringListValue[] items) {
|
|
IntComboBoxItem res = new IntComboBoxItem(id, label, items);
|
|
addItem(res);
|
|
return res;
|
|
}
|
|
|
|
FloatComboBoxItem addFloatComboBox(string id, UIString label, StringListValue[] items, long divider = 1000) {
|
|
FloatComboBoxItem res = new FloatComboBoxItem(id, label, items, divider);
|
|
addItem(res);
|
|
return res;
|
|
}
|
|
|
|
/// create page widget (default implementation creates empty page)
|
|
Widget createWidget(Setting settings) {
|
|
VerticalLayout res = new VerticalLayout(_id);
|
|
res.minWidth(200).minHeight(200).layoutWidth(FILL_PARENT).layoutHeight(FILL_PARENT);
|
|
if (itemCount > 0) {
|
|
TextWidget caption = new TextWidget("prop-body-caption-" ~ _id, _label);
|
|
caption.styleId = STYLE_SETTINGS_PAGE_TITLE;
|
|
caption.layoutWidth(FILL_PARENT);
|
|
res.addChild(caption);
|
|
TableLayout tbl = null;
|
|
for (int i = 0; i < itemCount; i++) {
|
|
SettingsItem v = item(i);
|
|
Widget[] w = v.createWidgets(settings);
|
|
if (w.length == 1) {
|
|
tbl = null;
|
|
res.addChild(w[0]);
|
|
} else if (w.length == 2) {
|
|
if (!tbl) {
|
|
tbl = new TableLayout();
|
|
tbl.colCount = 2;
|
|
res.addChild(tbl);
|
|
}
|
|
tbl.addChild(w[0]);
|
|
tbl.addChild(w[1]);
|
|
}
|
|
|
|
}
|
|
}
|
|
return res;
|
|
}
|
|
|
|
/// returns true if this page is root page
|
|
@property bool isRoot() {
|
|
return !_parent;
|
|
}
|
|
|
|
TreeItem createTreeItem() {
|
|
return new TreeItem(_id, _label);
|
|
}
|
|
|
|
}
|
|
|
|
class SettingsDialog : Dialog {
|
|
protected TreeWidget _tree;
|
|
protected FrameLayout _frame;
|
|
protected Setting _settings;
|
|
protected SettingsPage _layout;
|
|
|
|
this(UIString caption, Window parent, Setting settings, SettingsPage layout) {
|
|
super(caption, parent, DialogFlag.Modal | DialogFlag.Resizable | DialogFlag.Popup);
|
|
_settings = settings;
|
|
_layout = layout;
|
|
}
|
|
|
|
void onTreeItemSelected(TreeItems source, TreeItem selectedItem, bool activated) {
|
|
if (!selectedItem)
|
|
return;
|
|
_frame.showChild(selectedItem.id);
|
|
}
|
|
|
|
void createControls(SettingsPage page, TreeItem base) {
|
|
TreeItem item = base;
|
|
if (!page.isRoot) {
|
|
item = page.createTreeItem();
|
|
base.addChild(item);
|
|
Widget widget = page.createWidget(_settings);
|
|
_frame.addChild(widget);
|
|
}
|
|
if (page.childCount > 0) {
|
|
for (int i = 0; i < page.childCount; i++) {
|
|
createControls(page.child(i), item);
|
|
}
|
|
}
|
|
}
|
|
|
|
/// override to implement creation of dialog controls
|
|
override void init() {
|
|
minWidth(600).minHeight(400);
|
|
_tree = new TreeWidget("prop_tree");
|
|
_tree.styleId = STYLE_SETTINGS_TREE;
|
|
_tree.layoutHeight(FILL_PARENT).layoutHeight(FILL_PARENT).minHeight(200).minWidth(100);
|
|
_tree.selectionChange = &onTreeItemSelected;
|
|
_tree.fontSize = 16;
|
|
_frame = new FrameLayout("prop_pages");
|
|
_frame.styleId = STYLE_SETTINGS_PAGES;
|
|
_frame.layoutHeight(FILL_PARENT).layoutHeight(FILL_PARENT).minHeight(200).minWidth(100);
|
|
createControls(_layout, _tree.items);
|
|
HorizontalLayout content = new HorizontalLayout("settings_dlg_content");
|
|
content.addChild(_tree);
|
|
content.addChild(_frame);
|
|
content.layoutHeight(FILL_PARENT).layoutHeight(FILL_PARENT);
|
|
addChild(content);
|
|
addChild(createButtonsPanel([ACTION_APPLY, ACTION_CANCEL], 0, 0));
|
|
if (_layout.childCount > 0)
|
|
_tree.selectItem(_layout.child(0).id);
|
|
}
|
|
|
|
}
|