mirror of https://github.com/buggins/dlangui.git
ComboBox implementation, continue
This commit is contained in:
parent
df8d271856
commit
0b67f637cc
|
@ -521,6 +521,12 @@ extern (C) int UIAppMain(string[] args) {
|
||||||
// row 3
|
// row 3
|
||||||
table.addChild((new TextWidget(null, "Param 3"d)).alignment(Align.Right | Align.VCenter));
|
table.addChild((new TextWidget(null, "Param 3"d)).alignment(Align.Right | Align.VCenter));
|
||||||
table.addChild((new EditLine("edit3", "Parameter 3 value"d)).layoutWidth(FILL_PARENT));
|
table.addChild((new EditLine("edit3", "Parameter 3 value"d)).layoutWidth(FILL_PARENT));
|
||||||
|
|
||||||
|
ComboBox combo1 = new ComboBox("combo1", ["item value 1"d, "item value 2"d, "item value 3"d, "item value 4"d, "item value 5"d, "item value 6"d]);
|
||||||
|
table.addChild((new TextWidget(null, "Combo box param"d)).alignment(Align.Right | Align.VCenter));
|
||||||
|
combo1.selectedItemIndex(3);
|
||||||
|
table.addChild(combo1).layoutWidth(FILL_PARENT);
|
||||||
|
|
||||||
table.margins(Rect(10,10,10,10)).layoutWidth(FILL_PARENT);
|
table.margins(Rect(10,10,10,10)).layoutWidth(FILL_PARENT);
|
||||||
tabs.addTab(table, "TAB_TABLE_LAYOUT"c);
|
tabs.addTab(table, "TAB_TABLE_LAYOUT"c);
|
||||||
|
|
||||||
|
@ -692,7 +698,6 @@ extern (C) int UIAppMain(string[] args) {
|
||||||
treeItemLabel.text = label;
|
treeItemLabel.text = label;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
tree.items.selectItem(tree.items.child(0));
|
tree.items.selectItem(tree.items.child(0));
|
||||||
|
|
||||||
tabs.addTab(treeLayout, "Tree"d);
|
tabs.addTab(treeLayout, "Tree"d);
|
||||||
|
|
|
@ -60,5 +60,6 @@ public import dlangui.widgets.scroll;
|
||||||
public import dlangui.widgets.editors;
|
public import dlangui.widgets.editors;
|
||||||
public import dlangui.widgets.grid;
|
public import dlangui.widgets.grid;
|
||||||
public import dlangui.widgets.tree;
|
public import dlangui.widgets.tree;
|
||||||
|
public import dlangui.widgets.combobox;
|
||||||
public import dlangui.graphics.fonts;
|
public import dlangui.graphics.fonts;
|
||||||
public import dlangui.core.i18n;
|
public import dlangui.core.i18n;
|
||||||
|
|
|
@ -41,20 +41,21 @@ module dlangui.core.i18n;
|
||||||
import dlangui.core.types;
|
import dlangui.core.types;
|
||||||
import dlangui.core.logger;
|
import dlangui.core.logger;
|
||||||
private import dlangui.core.linestream;
|
private import dlangui.core.linestream;
|
||||||
import std.utf;
|
private import std.utf;
|
||||||
|
private import std.algorithm;
|
||||||
|
|
||||||
/// container for UI string - either raw value or string resource ID
|
/** container for UI string - either raw value or string resource ID */
|
||||||
struct UIString {
|
struct UIString {
|
||||||
/// if not null, use it, otherwise lookup by id
|
/** if not null, use it, otherwise lookup by id */
|
||||||
private dstring _value;
|
private dstring _value;
|
||||||
/// id to find value in translator
|
/** id to find value in translator */
|
||||||
private string _id;
|
private string _id;
|
||||||
|
|
||||||
/// create string with i18n resource id
|
/** create string with i18n resource id */
|
||||||
this(string id) {
|
this(string id) {
|
||||||
_id = id;
|
_id = id;
|
||||||
}
|
}
|
||||||
/// create string with raw value
|
/** create string with raw value */
|
||||||
this(dstring value) {
|
this(dstring value) {
|
||||||
_value = value;
|
_value = value;
|
||||||
}
|
}
|
||||||
|
@ -66,7 +67,7 @@ struct UIString {
|
||||||
_id = ID;
|
_id = ID;
|
||||||
_value = null;
|
_value = null;
|
||||||
}
|
}
|
||||||
/// get value (either raw or translated by id)
|
/** get value (either raw or translated by id) */
|
||||||
@property dstring value() const {
|
@property dstring value() const {
|
||||||
if (_value !is null)
|
if (_value !is null)
|
||||||
return _value;
|
return _value;
|
||||||
|
@ -75,27 +76,27 @@ struct UIString {
|
||||||
// translate ID to dstring
|
// translate ID to dstring
|
||||||
return i18n.get(_id);
|
return i18n.get(_id);
|
||||||
}
|
}
|
||||||
/// set raw value
|
/** set raw value */
|
||||||
@property void value(dstring newValue) {
|
@property void value(dstring newValue) {
|
||||||
_value = newValue;
|
_value = newValue;
|
||||||
}
|
}
|
||||||
/// assign raw value
|
/** assign raw value */
|
||||||
ref UIString opAssign(dstring rawValue) {
|
ref UIString opAssign(dstring rawValue) {
|
||||||
_value = rawValue;
|
_value = rawValue;
|
||||||
_id = null;
|
_id = null;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
/// assign ID
|
/** assign ID */
|
||||||
ref UIString opAssign(string ID) {
|
ref UIString opAssign(string ID) {
|
||||||
_id = ID;
|
_id = ID;
|
||||||
_value = null;
|
_value = null;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
/// default conversion to dstring
|
/** default conversion to dstring */
|
||||||
alias value this;
|
alias value this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** UIString item collection */
|
/** UIString item collection. */
|
||||||
struct UIStringCollection {
|
struct UIStringCollection {
|
||||||
private UIString[] _items;
|
private UIString[] _items;
|
||||||
private int _length;
|
private int _length;
|
||||||
|
@ -201,13 +202,38 @@ struct UIStringCollection {
|
||||||
_items[i] = _items[i + 1];
|
_items[i] = _items[i + 1];
|
||||||
_length--;
|
_length--;
|
||||||
}
|
}
|
||||||
|
/** Return index of first item with specified text or -1 if not found. */
|
||||||
|
int indexOf(dstring str) {
|
||||||
|
for (int i = 0; i < _length; i++) {
|
||||||
|
if (_items[i].value.equal(str))
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
/** Return index of first item with specified string resource id or -1 if not found. */
|
||||||
|
int indexOf(string strId) {
|
||||||
|
for (int i = 0; i < _length; i++) {
|
||||||
|
if (_items[i].id.equal(strId))
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
/** Return index of first item with specified string or -1 if not found. */
|
||||||
|
int indexOf(UIString str) {
|
||||||
|
if (str.id !is null)
|
||||||
|
return indexOf(str.id);
|
||||||
|
return indexOf(str.value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** UI Strings internationalization translator. */
|
||||||
synchronized class UIStringTranslator {
|
synchronized class UIStringTranslator {
|
||||||
|
|
||||||
private UIStringList _main;
|
private UIStringList _main;
|
||||||
private UIStringList _fallback;
|
private UIStringList _fallback;
|
||||||
private string[] _resourceDirs;
|
private string[] _resourceDirs;
|
||||||
/// looks for i18n directory inside one of passed dirs, and uses first found as directory to read i18n files from
|
|
||||||
|
/** looks for i18n directory inside one of passed dirs, and uses first found as directory to read i18n files from */
|
||||||
void findTranslationsDir(string[] dirs ...) {
|
void findTranslationsDir(string[] dirs ...) {
|
||||||
_resourceDirs.length = 0;
|
_resourceDirs.length = 0;
|
||||||
import std.file;
|
import std.file;
|
||||||
|
@ -220,7 +246,7 @@ synchronized class UIStringTranslator {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// convert resource path - append resource dir if necessary
|
/** convert resource path - append resource dir if necessary */
|
||||||
string[] convertResourcePaths(string filename) {
|
string[] convertResourcePaths(string filename) {
|
||||||
if (filename is null)
|
if (filename is null)
|
||||||
return null;
|
return null;
|
||||||
|
@ -242,7 +268,8 @@ synchronized class UIStringTranslator {
|
||||||
_main = new shared UIStringList();
|
_main = new shared UIStringList();
|
||||||
_fallback = new shared UIStringList();
|
_fallback = new shared UIStringList();
|
||||||
}
|
}
|
||||||
/// load translation file(s)
|
|
||||||
|
/** load translation file(s) */
|
||||||
bool load(string mainFilename, string fallbackFilename = null) {
|
bool load(string mainFilename, string fallbackFilename = null) {
|
||||||
_main.clear();
|
_main.clear();
|
||||||
_fallback.clear();
|
_fallback.clear();
|
||||||
|
@ -253,7 +280,7 @@ synchronized class UIStringTranslator {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// translate string ID to string (returns "UNTRANSLATED: id" for missing values)
|
/** translate string ID to string (returns "UNTRANSLATED: id" for missing values) */
|
||||||
dstring get(string id) {
|
dstring get(string id) {
|
||||||
if (id is null)
|
if (id is null)
|
||||||
return null;
|
return null;
|
||||||
|
@ -267,7 +294,7 @@ synchronized class UIStringTranslator {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// UI string translator
|
/** UI string translator */
|
||||||
private shared class UIStringList {
|
private shared class UIStringList {
|
||||||
private dstring[string] _map;
|
private dstring[string] _map;
|
||||||
/// remove all items
|
/// remove all items
|
||||||
|
@ -338,6 +365,7 @@ private shared class UIStringList {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Global translator object. */
|
||||||
shared UIStringTranslator i18n;
|
shared UIStringTranslator i18n;
|
||||||
shared static this() {
|
shared static this() {
|
||||||
i18n = new shared UIStringTranslator();
|
i18n = new shared UIStringTranslator();
|
||||||
|
|
|
@ -6,6 +6,8 @@ import dlangui.widgets.editors;
|
||||||
import dlangui.widgets.lists;
|
import dlangui.widgets.lists;
|
||||||
import dlangui.widgets.controls;
|
import dlangui.widgets.controls;
|
||||||
|
|
||||||
|
private import std.algorithm;
|
||||||
|
|
||||||
class ComboBoxBase : HorizontalLayout, OnClickHandler {
|
class ComboBoxBase : HorizontalLayout, OnClickHandler {
|
||||||
protected Widget _body;
|
protected Widget _body;
|
||||||
protected ImageButton _button;
|
protected ImageButton _button;
|
||||||
|
@ -26,13 +28,22 @@ class ComboBoxBase : HorizontalLayout, OnClickHandler {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Selected item index. */
|
||||||
|
@property int selectedItemIndex() {
|
||||||
|
return _selectedItemIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
@property void selectedItemIndex(int index) {
|
||||||
|
_selectedItemIndex = index;
|
||||||
|
}
|
||||||
|
|
||||||
override bool onClick(Widget source) {
|
override bool onClick(Widget source) {
|
||||||
// TODO
|
// TODO
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected ImageButton createButton() {
|
protected ImageButton createButton() {
|
||||||
ImageButton res = new ImageButton("COMBOBOX_BUTTON");
|
ImageButton res = new ImageButton("COMBOBOX_BUTTON", "scrollbar_btn_down");
|
||||||
res.onClickListener = this;
|
res.onClickListener = this;
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
@ -49,10 +60,75 @@ class ComboBoxBase : HorizontalLayout, OnClickHandler {
|
||||||
}
|
}
|
||||||
|
|
||||||
class ComboBox : ComboBoxBase {
|
class ComboBox : ComboBoxBase {
|
||||||
|
|
||||||
|
protected StringListAdapter _adapter;
|
||||||
|
protected EditLine _edit;
|
||||||
|
|
||||||
|
this(string ID) {
|
||||||
|
super(ID, (_adapter = new StringListAdapter()), true);
|
||||||
|
}
|
||||||
|
|
||||||
this(string ID, string[] items) {
|
this(string ID, string[] items) {
|
||||||
super(ID, new StringListAdapter(items), true);
|
super(ID, (_adapter = new StringListAdapter(items)), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
this(string ID, dstring[] items) {
|
this(string ID, dstring[] items) {
|
||||||
super(ID, new StringListAdapter(items), true);
|
super(ID, (_adapter = new StringListAdapter(items)), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@property bool readOnly() {
|
||||||
|
return _edit.readOnly;
|
||||||
|
}
|
||||||
|
|
||||||
|
@property ComboBox readOnly(bool ro) {
|
||||||
|
_edit.readOnly = ro;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@property override dstring text() {
|
||||||
|
return _edit.text;
|
||||||
|
}
|
||||||
|
|
||||||
|
@property override Widget text(dstring txt) {
|
||||||
|
int idx = _adapter.items.indexOf(txt);
|
||||||
|
if (idx >= 0) {
|
||||||
|
selectedItemIndex = idx;
|
||||||
|
} else {
|
||||||
|
if (!readOnly) {
|
||||||
|
// not found
|
||||||
|
_selectedItemIndex = -1;
|
||||||
|
_edit.text = txt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@property override Widget text(UIString txt) {
|
||||||
|
int idx = _adapter.items.indexOf(txt);
|
||||||
|
if (idx >= 0) {
|
||||||
|
selectedItemIndex = idx;
|
||||||
|
} else {
|
||||||
|
if (!readOnly) {
|
||||||
|
// not found
|
||||||
|
_selectedItemIndex = -1;
|
||||||
|
_edit.text = txt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
override @property void selectedItemIndex(int index) {
|
||||||
|
_selectedItemIndex = index;
|
||||||
|
_edit.text = _adapter.items[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
override protected Widget createSelectedItemWidget() {
|
||||||
|
EditLine res = new EditLine("COMBOBOX_BODY");
|
||||||
|
res.layoutWidth = FILL_PARENT;
|
||||||
|
res.layoutHeight = WRAP_CONTENT;
|
||||||
|
res.readOnly = true;
|
||||||
|
_edit = res;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -420,6 +420,15 @@ class ListWidget : WidgetGroup, OnScrollHandler {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Selected item index. */
|
||||||
|
@property int selectedItemIndex() {
|
||||||
|
return _selectedItemIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
@property void selectedItemIndex(int index) {
|
||||||
|
selectItem(index);
|
||||||
|
}
|
||||||
|
|
||||||
bool selectItem(int index) {
|
bool selectItem(int index) {
|
||||||
debug Log.d("selectItem ", index);
|
debug Log.d("selectItem ", index);
|
||||||
if (_selectedItemIndex == index) {
|
if (_selectedItemIndex == index) {
|
||||||
|
|
|
@ -1230,25 +1230,25 @@ class Widget {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// object list holder, owning its objects - on destroy of holder, all own objects will be destroyed
|
/** object list holder, owning its objects - on destroy of holder, all own objects will be destroyed */
|
||||||
struct ObjectList(T) {
|
struct ObjectList(T) {
|
||||||
protected T[] _list;
|
protected T[] _list;
|
||||||
protected int _count;
|
protected int _count;
|
||||||
/// returns count of items
|
/** returns count of items */
|
||||||
@property int count() const { return _count; }
|
@property int count() const { return _count; }
|
||||||
/// get item by index
|
/** get item by index */
|
||||||
T get(int index) {
|
T get(int index) {
|
||||||
assert(index >= 0 && index < _count, "child index out of range");
|
assert(index >= 0 && index < _count, "child index out of range");
|
||||||
return _list[index];
|
return _list[index];
|
||||||
}
|
}
|
||||||
/// add item to list
|
/** add item to list */
|
||||||
T add(T item) {
|
T add(T item) {
|
||||||
if (_list.length <= _count) // resize
|
if (_list.length <= _count) // resize
|
||||||
_list.length = _list.length < 4 ? 4 : _list.length * 2;
|
_list.length = _list.length < 4 ? 4 : _list.length * 2;
|
||||||
_list[_count++] = item;
|
_list[_count++] = item;
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
/// add item to list
|
/** add item to list */
|
||||||
T insert(T item, int index = -1) {
|
T insert(T item, int index = -1) {
|
||||||
if (index > _count || index < 0)
|
if (index > _count || index < 0)
|
||||||
index = _count;
|
index = _count;
|
||||||
|
@ -1260,14 +1260,14 @@ struct ObjectList(T) {
|
||||||
_count++;
|
_count++;
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
/// find child index for item, return -1 if not found
|
/** find child index for item, return -1 if not found */
|
||||||
int indexOf(T item) {
|
int indexOf(T item) {
|
||||||
for (int i = 0; i < _count; i++)
|
for (int i = 0; i < _count; i++)
|
||||||
if (_list[i] == item)
|
if (_list[i] == item)
|
||||||
return i;
|
return i;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
/// find child index for item by id, return -1 if not found
|
/** find child index for item by id, return -1 if not found */
|
||||||
static if (__traits(hasMember, T, "compareId")) {
|
static if (__traits(hasMember, T, "compareId")) {
|
||||||
int indexOf(string id) {
|
int indexOf(string id) {
|
||||||
for (int i = 0; i < _count; i++)
|
for (int i = 0; i < _count; i++)
|
||||||
|
@ -1276,7 +1276,7 @@ struct ObjectList(T) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/// remove item from list, return removed item
|
/** remove item from list, return removed item */
|
||||||
T remove(int index) {
|
T remove(int index) {
|
||||||
assert(index >= 0 && index < _count, "child index out of range");
|
assert(index >= 0 && index < _count, "child index out of range");
|
||||||
T item = _list[index];
|
T item = _list[index];
|
||||||
|
@ -1285,7 +1285,13 @@ struct ObjectList(T) {
|
||||||
_count--;
|
_count--;
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
/// remove and destroy all items
|
/** Replace item with another value, destroy old value. */
|
||||||
|
void replace(T item, int index) {
|
||||||
|
T old = _list[index];
|
||||||
|
_list[index] = item;
|
||||||
|
destroy(old);
|
||||||
|
}
|
||||||
|
/** remove and destroy all items */
|
||||||
void clear() {
|
void clear() {
|
||||||
for (int i = 0; i < _count; i++) {
|
for (int i = 0; i < _count; i++) {
|
||||||
destroy(_list[i]);
|
destroy(_list[i]);
|
||||||
|
@ -1298,10 +1304,10 @@ struct ObjectList(T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// widget list holder
|
/** Widget list holder. */
|
||||||
alias WidgetList = ObjectList!Widget;
|
alias WidgetList = ObjectList!Widget;
|
||||||
|
|
||||||
/// base class for widgets which have children
|
/** Base class for widgets which have children. */
|
||||||
class WidgetGroup : Widget {
|
class WidgetGroup : Widget {
|
||||||
|
|
||||||
this(string ID = null) {
|
this(string ID = null) {
|
||||||
|
|
Loading…
Reference in New Issue