From df8d2718561ab0a6f60b1fe82d7fdc5a73d998b1 Mon Sep 17 00:00:00 2001 From: Vadim Lopatin Date: Mon, 15 Dec 2014 12:16:56 +0300 Subject: [PATCH] StringListAdapter implemented --- dlanguilib.visualdproj | 4 +- examples/example1/example1.visualdproj | 2 +- examples/example1/src/main.d | 31 ++++++- src/dlangui/core/i18n.d | 115 ++++++++++++++++++++++++- src/dlangui/widgets/combobox.d | 58 +++++++++++++ src/dlangui/widgets/lists.d | 90 +++++++++++++++++++ travis.yml | 0 7 files changed, 291 insertions(+), 9 deletions(-) create mode 100644 src/dlangui/widgets/combobox.d create mode 100644 travis.yml diff --git a/dlanguilib.visualdproj b/dlanguilib.visualdproj index 199dfc2d1..1c67d6876 100644 --- a/dlanguilib.visualdproj +++ b/dlanguilib.visualdproj @@ -66,7 +66,7 @@ 0 0 - + USE_SDL USE_OPENGL 0 0 1 @@ -160,6 +160,7 @@ 0 0 + 0 0 0 @@ -327,6 +328,7 @@ + diff --git a/examples/example1/example1.visualdproj b/examples/example1/example1.visualdproj index 7bdbb952c..f03b868b0 100644 --- a/examples/example1/example1.visualdproj +++ b/examples/example1/example1.visualdproj @@ -66,7 +66,7 @@ 0 0 - + USE_SDL USE_OPENGL 0 3 0 diff --git a/examples/example1/src/main.d b/examples/example1/src/main.d index 3563e733f..c5537cda5 100644 --- a/examples/example1/src/main.d +++ b/examples/example1/src/main.d @@ -375,10 +375,24 @@ extern (C) int UIAppMain(string[] args) { tabs.addTab(layout, "Tab 1"d); static if (true) { - ListWidget list = new ListWidget("tab2", Orientation.Vertical); + // two long lists + // left one is list with widgets as items + // right one is list with string list adapter + HorizontalLayout longLists = new HorizontalLayout("tab2"); + longLists.layoutWidth(FILL_PARENT).layoutHeight(FILL_PARENT); + + ListWidget list = new ListWidget("list1", Orientation.Vertical); + list.layoutWidth(FILL_PARENT).layoutHeight(FILL_PARENT); + + StringListAdapter stringList = new StringListAdapter(); WidgetListAdapter listAdapter = new WidgetListAdapter(); - for (int i = 0; i < 1000; i++) - listAdapter.widgets.add((new TextWidget()).text("List item "d ~ to!dstring(i)).styleId("LIST_ITEM")); + listAdapter.widgets.add((new TextWidget()).text("This is a list of widgets"d).styleId("LIST_ITEM")); + stringList.items.add("This is a list of strings from StringListAdapter"d); + for (int i = 1; i < 1000; i++) { + dstring label = "List item "d ~ to!dstring(i); + listAdapter.widgets.add((new TextWidget()).text("Widget list - "d ~ label).styleId("LIST_ITEM")); + stringList.items.add("Simple string - "d ~ label); + } list.ownAdapter = listAdapter; listAdapter.resetItemState(0, State.Enabled); listAdapter.resetItemState(5, State.Enabled); @@ -388,7 +402,16 @@ extern (C) int UIAppMain(string[] args) { assert(list.itemEnabled(6) == true); list.layoutWidth(FILL_PARENT).layoutHeight(FILL_PARENT); list.selectItem(0); - tabs.addTab(list, "TAB_LONG_LIST"c); + + longLists.addChild(list); + + ListWidget list2 = new ListWidget("list2"); + list2.ownAdapter = stringList; + list2.layoutWidth(FILL_PARENT).layoutHeight(FILL_PARENT); + list2.selectItem(0); + longLists.addChild(list2); + + tabs.addTab(longLists, "TAB_LONG_LIST"c); } { diff --git a/src/dlangui/core/i18n.d b/src/dlangui/core/i18n.d index 5821da54f..fffecc7b7 100644 --- a/src/dlangui/core/i18n.d +++ b/src/dlangui/core/i18n.d @@ -95,9 +95,112 @@ struct UIString { alias value this; } -shared UIStringTranslator i18n; -shared static this() { - i18n = new shared UIStringTranslator(); +/** UIString item collection */ +struct UIStringCollection { + private UIString[] _items; + private int _length; + + /** returns number of items */ + @property int length() { return _length; } + /** slice */ + UIString[] opIndex() { + return _items[0 .. _length]; + } + /** slice */ + UIString[] opSlice() { + return _items[0 .. _length]; + } + /** slice */ + UIString[] opSlice(size_t start, size_t end) { + return _items[start .. end]; + } + /** read item by index */ + UIString opIndex(size_t index) { + return _items[index]; + } + /** modify item by index */ + UIString opIndexAssign(UIString value, size_t index) { + _items[index] = value; + return _items[index]; + } + /** return unicode string for item by index */ + dstring get(size_t index) { + return _items[index].value; + } + /** Assign UIStringCollection */ + void opAssign(ref UIStringCollection items) { + clear(); + addAll(items); + } + /** Append UIStringCollection */ + void addAll(ref UIStringCollection items) { + foreach (UIString item; items) { + add(item); + } + } + /** Assign array of string resource IDs */ + void opAssign(string[] items) { + clear(); + addAll(items); + } + /** Append array of string resource IDs */ + void addAll(string[] items) { + foreach (string item; items) { + add(item); + } + } + /** Assign array of unicode strings */ + void opAssign(dstring[] items) { + clear(); + addAll(items); + } + /** Append array of unicode strings */ + void addAll(dstring[] items) { + foreach (dstring item; items) { + add(item); + } + } + /** remove all items */ + void clear() { + _items.length = 0; + _length = 0; + } + /** Insert resource id item into specified position */ + void add(string item, int index = -1) { + UIString s; + s = item; + add(s, index); + } + /** Insert unicode string item into specified position */ + void add(dstring item, int index = -1) { + UIString s; + s = item; + add(s, index); + } + /** Insert UIString item into specified position */ + void add(UIString item, int index = -1) { + if (index < 0 || index > _length) + index = _length; + if (_items.length < _length + 1) { + if (_items.length < 8) + _items.length = 8; + else + _items.length = _items.length * 2; + } + for (size_t i = _length; i > index; i--) { + _items[i] = _items[i + 1]; + } + _items[index] = item; + _length++; + } + /** Remove item with specified index */ + void remove(int index) { + if (index < 0 || index >= _length) + return; + for (size_t i = index; i < _length - 1; i++) + _items[i] = _items[i + 1]; + _length--; + } } synchronized class UIStringTranslator { @@ -149,6 +252,7 @@ synchronized class UIStringTranslator { } return res; } + /// translate string ID to string (returns "UNTRANSLATED: id" for missing values) dstring get(string id) { if (id is null) @@ -233,3 +337,8 @@ private shared class UIStringList { return res; } } + +shared UIStringTranslator i18n; +shared static this() { + i18n = new shared UIStringTranslator(); +} diff --git a/src/dlangui/widgets/combobox.d b/src/dlangui/widgets/combobox.d new file mode 100644 index 000000000..24fbea556 --- /dev/null +++ b/src/dlangui/widgets/combobox.d @@ -0,0 +1,58 @@ +module dlangui.widgets.combobox; + +import dlangui.widgets.widget; +import dlangui.widgets.layouts; +import dlangui.widgets.editors; +import dlangui.widgets.lists; +import dlangui.widgets.controls; + +class ComboBoxBase : HorizontalLayout, OnClickHandler { + protected Widget _body; + protected ImageButton _button; + protected ListAdapter _adapter; + protected bool _ownAdapter; + protected int _selectedItemIndex; + + protected Widget createSelectedItemWidget() { + Widget res; + if (_adapter && _selectedItemIndex < _adapter.itemCount) { + res = _adapter.itemWidget(_selectedItemIndex); + res.id = "COMBOBOX_BODY"; + } else { + res = new Widget("COMBOBOX_BODY"); + } + res.layoutWidth = FILL_PARENT; + res.layoutHeight = WRAP_CONTENT; + return res; + } + + override bool onClick(Widget source) { + // TODO + return true; + } + + protected ImageButton createButton() { + ImageButton res = new ImageButton("COMBOBOX_BUTTON"); + res.onClickListener = this; + return res; + } + + this(string ID, ListAdapter adapter, bool ownAdapter = true) { + super(ID); + _adapter = adapter; + _ownAdapter = ownAdapter; + _body = createSelectedItemWidget(); + _button = createButton(); + addChild(_body); + addChild(_button); + } +} + +class ComboBox : ComboBoxBase { + this(string ID, string[] items) { + super(ID, new StringListAdapter(items), true); + } + this(string ID, dstring[] items) { + super(ID, new StringListAdapter(items), true); + } +} diff --git a/src/dlangui/widgets/lists.d b/src/dlangui/widgets/lists.d index f7c2d0714..578f1e37a 100644 --- a/src/dlangui/widgets/lists.d +++ b/src/dlangui/widgets/lists.d @@ -65,6 +65,96 @@ class WidgetListAdapter : ListAdapter { } } +/** List adapter providing strings only. */ +class StringListAdapter : ListAdapter { + protected UIStringCollection _items; + protected uint[] _states; + protected TextWidget _widget; + protected int _lastItemIndex; + + /** create empty string list adapter. */ + this() { + _lastItemIndex = -1; + } + + /** Init with array of string resource IDs. */ + this(string[] items) { + _items.addAll(items); + _lastItemIndex = -1; + updateStatesLength(); + } + + /** Init with array of unicode strings. */ + this(dstring[] items) { + _items.addAll(items); + _lastItemIndex = -1; + updateStatesLength(); + } + + /** Access to items collection. */ + @property ref UIStringCollection items() { return _items; } + + /// returns number of widgets in list + @property override int itemCount() { + return _items.length; + } + + protected void updateStatesLength() { + if (_states.length < _items.length) { + int oldlen = _states.length; + _states.length = _items.length; + for (int i = oldlen; i < _items.length; i++) + _states[i] = State.Enabled; + } + } + + /// return list item widget by item index + override Widget itemWidget(int index) { + updateStatesLength(); + if (_widget is null) { + _widget = new TextWidget("LIST_ITEM"); + _widget.styleId = "LIST_ITEM"; + } else { + if (index == _lastItemIndex) + return _widget; + } + // update widget + _widget.text = _items.get(index); + _widget.state = _states[index]; + _lastItemIndex = index; + return _widget; + } + + /// return list item's state flags + override uint itemState(int index) { + updateStatesLength(); + return _states[index]; + } + + /// set one or more list item's state flags, returns updated state + override uint setItemState(int index, uint flags) { + updateStatesLength(); + _states[index] |= flags; + if (_widget !is null && _lastItemIndex == index) + _widget.state = _states[index]; + return _states[index]; + } + /// reset one or more list item's state flags, returns updated state + override uint resetItemState(int index, uint flags) { + updateStatesLength(); + _states[index] &= ~flags; + if (_widget !is null && _lastItemIndex == index) + _widget.state = _states[index]; + return _states[index]; + } + + ~this() { + //Log.d("Destroying StringListAdapter"); + if (_widget) + destroy(_widget); + } +} + /// List class ListWidget : WidgetGroup, OnScrollHandler { protected Orientation _orientation = Orientation.Vertical; diff --git a/travis.yml b/travis.yml new file mode 100644 index 000000000..e69de29bb