mirror of https://github.com/buggins/dlangui.git
ComboBox implementation, continue
This commit is contained in:
parent
df8d271856
commit
0b67f637cc
|
@ -25,7 +25,7 @@ import std.utf;
|
|||
|
||||
mixin APP_ENTRY_POINT;
|
||||
|
||||
Widget createAboutWidget()
|
||||
Widget createAboutWidget()
|
||||
{
|
||||
LinearLayout res = new VerticalLayout();
|
||||
res.padding(Rect(10,10,10,10));
|
||||
|
@ -521,6 +521,12 @@ extern (C) int UIAppMain(string[] args) {
|
|||
// row 3
|
||||
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));
|
||||
|
||||
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);
|
||||
tabs.addTab(table, "TAB_TABLE_LAYOUT"c);
|
||||
|
||||
|
@ -692,7 +698,6 @@ extern (C) int UIAppMain(string[] args) {
|
|||
treeItemLabel.text = label;
|
||||
};
|
||||
|
||||
|
||||
tree.items.selectItem(tree.items.child(0));
|
||||
|
||||
tabs.addTab(treeLayout, "Tree"d);
|
||||
|
|
|
@ -60,5 +60,6 @@ public import dlangui.widgets.scroll;
|
|||
public import dlangui.widgets.editors;
|
||||
public import dlangui.widgets.grid;
|
||||
public import dlangui.widgets.tree;
|
||||
public import dlangui.widgets.combobox;
|
||||
public import dlangui.graphics.fonts;
|
||||
public import dlangui.core.i18n;
|
||||
|
|
|
@ -41,20 +41,21 @@ module dlangui.core.i18n;
|
|||
import dlangui.core.types;
|
||||
import dlangui.core.logger;
|
||||
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 {
|
||||
/// if not null, use it, otherwise lookup by id
|
||||
/** if not null, use it, otherwise lookup by id */
|
||||
private dstring _value;
|
||||
/// id to find value in translator
|
||||
/** id to find value in translator */
|
||||
private string _id;
|
||||
|
||||
/// create string with i18n resource id
|
||||
/** create string with i18n resource id */
|
||||
this(string id) {
|
||||
_id = id;
|
||||
}
|
||||
/// create string with raw value
|
||||
/** create string with raw value */
|
||||
this(dstring value) {
|
||||
_value = value;
|
||||
}
|
||||
|
@ -66,7 +67,7 @@ struct UIString {
|
|||
_id = ID;
|
||||
_value = null;
|
||||
}
|
||||
/// get value (either raw or translated by id)
|
||||
/** get value (either raw or translated by id) */
|
||||
@property dstring value() const {
|
||||
if (_value !is null)
|
||||
return _value;
|
||||
|
@ -75,27 +76,27 @@ struct UIString {
|
|||
// translate ID to dstring
|
||||
return i18n.get(_id);
|
||||
}
|
||||
/// set raw value
|
||||
/** set raw value */
|
||||
@property void value(dstring newValue) {
|
||||
_value = newValue;
|
||||
}
|
||||
/// assign raw value
|
||||
/** assign raw value */
|
||||
ref UIString opAssign(dstring rawValue) {
|
||||
_value = rawValue;
|
||||
_id = null;
|
||||
return this;
|
||||
}
|
||||
/// assign ID
|
||||
/** assign ID */
|
||||
ref UIString opAssign(string ID) {
|
||||
_id = ID;
|
||||
_value = null;
|
||||
return this;
|
||||
}
|
||||
/// default conversion to dstring
|
||||
/** default conversion to dstring */
|
||||
alias value this;
|
||||
}
|
||||
|
||||
/** UIString item collection */
|
||||
/** UIString item collection. */
|
||||
struct UIStringCollection {
|
||||
private UIString[] _items;
|
||||
private int _length;
|
||||
|
@ -201,13 +202,38 @@ struct UIStringCollection {
|
|||
_items[i] = _items[i + 1];
|
||||
_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 {
|
||||
|
||||
private UIStringList _main;
|
||||
private UIStringList _fallback;
|
||||
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 ...) {
|
||||
_resourceDirs.length = 0;
|
||||
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) {
|
||||
if (filename is null)
|
||||
return null;
|
||||
|
@ -242,7 +268,8 @@ synchronized class UIStringTranslator {
|
|||
_main = new shared UIStringList();
|
||||
_fallback = new shared UIStringList();
|
||||
}
|
||||
/// load translation file(s)
|
||||
|
||||
/** load translation file(s) */
|
||||
bool load(string mainFilename, string fallbackFilename = null) {
|
||||
_main.clear();
|
||||
_fallback.clear();
|
||||
|
@ -253,7 +280,7 @@ synchronized class UIStringTranslator {
|
|||
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) {
|
||||
if (id is null)
|
||||
return null;
|
||||
|
@ -267,7 +294,7 @@ synchronized class UIStringTranslator {
|
|||
}
|
||||
}
|
||||
|
||||
/// UI string translator
|
||||
/** UI string translator */
|
||||
private shared class UIStringList {
|
||||
private dstring[string] _map;
|
||||
/// remove all items
|
||||
|
@ -338,6 +365,7 @@ private shared class UIStringList {
|
|||
}
|
||||
}
|
||||
|
||||
/** Global translator object. */
|
||||
shared UIStringTranslator i18n;
|
||||
shared static this() {
|
||||
i18n = new shared UIStringTranslator();
|
||||
|
|
|
@ -6,6 +6,8 @@ import dlangui.widgets.editors;
|
|||
import dlangui.widgets.lists;
|
||||
import dlangui.widgets.controls;
|
||||
|
||||
private import std.algorithm;
|
||||
|
||||
class ComboBoxBase : HorizontalLayout, OnClickHandler {
|
||||
protected Widget _body;
|
||||
protected ImageButton _button;
|
||||
|
@ -26,13 +28,22 @@ class ComboBoxBase : HorizontalLayout, OnClickHandler {
|
|||
return res;
|
||||
}
|
||||
|
||||
/** Selected item index. */
|
||||
@property int selectedItemIndex() {
|
||||
return _selectedItemIndex;
|
||||
}
|
||||
|
||||
@property void selectedItemIndex(int index) {
|
||||
_selectedItemIndex = index;
|
||||
}
|
||||
|
||||
override bool onClick(Widget source) {
|
||||
// TODO
|
||||
return true;
|
||||
}
|
||||
|
||||
protected ImageButton createButton() {
|
||||
ImageButton res = new ImageButton("COMBOBOX_BUTTON");
|
||||
ImageButton res = new ImageButton("COMBOBOX_BUTTON", "scrollbar_btn_down");
|
||||
res.onClickListener = this;
|
||||
return res;
|
||||
}
|
||||
|
@ -49,10 +60,75 @@ class ComboBoxBase : HorizontalLayout, OnClickHandler {
|
|||
}
|
||||
|
||||
class ComboBox : ComboBoxBase {
|
||||
|
||||
protected StringListAdapter _adapter;
|
||||
protected EditLine _edit;
|
||||
|
||||
this(string ID) {
|
||||
super(ID, (_adapter = new StringListAdapter()), true);
|
||||
}
|
||||
|
||||
this(string ID, string[] items) {
|
||||
super(ID, new StringListAdapter(items), true);
|
||||
super(ID, (_adapter = new StringListAdapter(items)), true);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/** Selected item index. */
|
||||
@property int selectedItemIndex() {
|
||||
return _selectedItemIndex;
|
||||
}
|
||||
|
||||
@property void selectedItemIndex(int index) {
|
||||
selectItem(index);
|
||||
}
|
||||
|
||||
bool selectItem(int index) {
|
||||
debug Log.d("selectItem ", 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) {
|
||||
protected T[] _list;
|
||||
protected int _count;
|
||||
/// returns count of items
|
||||
/** returns count of items */
|
||||
@property int count() const { return _count; }
|
||||
/// get item by index
|
||||
/** get item by index */
|
||||
T get(int index) {
|
||||
assert(index >= 0 && index < _count, "child index out of range");
|
||||
return _list[index];
|
||||
}
|
||||
/// add item to list
|
||||
/** add item to list */
|
||||
T add(T item) {
|
||||
if (_list.length <= _count) // resize
|
||||
_list.length = _list.length < 4 ? 4 : _list.length * 2;
|
||||
_list[_count++] = item;
|
||||
return item;
|
||||
}
|
||||
/// add item to list
|
||||
/** add item to list */
|
||||
T insert(T item, int index = -1) {
|
||||
if (index > _count || index < 0)
|
||||
index = _count;
|
||||
|
@ -1260,14 +1260,14 @@ struct ObjectList(T) {
|
|||
_count++;
|
||||
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) {
|
||||
for (int i = 0; i < _count; i++)
|
||||
if (_list[i] == item)
|
||||
return i;
|
||||
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")) {
|
||||
int indexOf(string id) {
|
||||
for (int i = 0; i < _count; i++)
|
||||
|
@ -1276,7 +1276,7 @@ struct ObjectList(T) {
|
|||
return -1;
|
||||
}
|
||||
}
|
||||
/// remove item from list, return removed item
|
||||
/** remove item from list, return removed item */
|
||||
T remove(int index) {
|
||||
assert(index >= 0 && index < _count, "child index out of range");
|
||||
T item = _list[index];
|
||||
|
@ -1285,7 +1285,13 @@ struct ObjectList(T) {
|
|||
_count--;
|
||||
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() {
|
||||
for (int i = 0; i < _count; i++) {
|
||||
destroy(_list[i]);
|
||||
|
@ -1298,10 +1304,10 @@ struct ObjectList(T) {
|
|||
}
|
||||
}
|
||||
|
||||
/// widget list holder
|
||||
/** Widget list holder. */
|
||||
alias WidgetList = ObjectList!Widget;
|
||||
|
||||
/// base class for widgets which have children
|
||||
/** Base class for widgets which have children. */
|
||||
class WidgetGroup : Widget {
|
||||
|
||||
this(string ID = null) {
|
||||
|
|
Loading…
Reference in New Issue