ComboEdit enhancements - issue #224

This commit is contained in:
Vadim Lopatin 2016-04-22 11:31:28 +03:00
parent c1a48eea18
commit 53e13ff706
7 changed files with 246 additions and 49 deletions

View File

@ -46,7 +46,7 @@ extern (C) int UIAppMain(string[] args) {
layoutWidth: fill layoutWidth: fill
CheckBox { id: cb1; text: "checkbox 1" } CheckBox { id: cb1; text: "checkbox 1" }
CheckBox { id: cb2; text: "checkbox 2" } CheckBox { id: cb2; text: "checkbox 2" }
ComboEdit { id: ce1; text: "some text"; } ComboEdit { id: ce1; text: "some text"; minWidth: 100; items: ["Item 1", "Item 2", "Additional item"] }
} }
} }
HorizontalLayout { HorizontalLayout {

View File

@ -192,20 +192,42 @@ struct UIStringCollection {
clear(); clear();
addAll(items); addAll(items);
} }
/** Append array of string resource IDs */
void addAll(string[] items) {
foreach (string item; items) {
add(item);
}
}
/** Assign array of unicode strings */ /** Assign array of unicode strings */
void opAssign(dstring[] items) { void opAssign(dstring[] items) {
clear(); clear();
addAll(items); addAll(items);
} }
/** Assign array of UIString */
void opAssign(UIString[] items) {
clear();
addAll(items);
}
/** Assign array of StringListValue */
void opAssign(StringListValue[] items) {
clear();
addAll(items);
}
/** Append array of unicode strings */ /** Append array of unicode strings */
void addAll(dstring[] items) { void addAll(dstring[] items) {
foreach (dstring item; items) { foreach (item; items) {
add(item);
}
}
/** Append array of unicode strings */
void addAll(string[] items) {
foreach (item; items) {
add(item);
}
}
/** Append array of unicode strings */
void addAll(UIString[] items) {
foreach (item; items) {
add(item);
}
}
/** Append array of unicode strings */
void addAll(StringListValue[] items) {
foreach (item; items) {
add(item); add(item);
} }
} }
@ -226,6 +248,10 @@ struct UIStringCollection {
s = item; s = item;
add(s, index); add(s, index);
} }
/** Insert StringListValue.label item into specified position */
void add(StringListValue item, int index = -1) {
add(item.label, index);
}
/** Insert UIString item into specified position */ /** Insert UIString item into specified position */
void add(UIString item, int index = -1) { void add(UIString item, int index = -1) {
if (index < 0 || index > _length) if (index < 0 || index > _length)
@ -274,6 +300,43 @@ struct UIStringCollection {
} }
} }
/// string values string list adapter - each item can have optional string or integer id, and optional icon resource id
struct StringListValue {
/// integer id for item
int intId;
/// string id for item
string stringId;
/// icon resource id
string iconId;
/// label to show for item
UIString label;
this(string id, dstring name, string iconId = null) {
this.stringId = id;
this.label = name;
this.iconId = iconId;
}
this(string id, string nameResourceId, string iconId = null) {
this.stringId = id;
this.label = nameResourceId;
this.iconId = iconId;
}
this(int id, dstring name, string iconId = null) {
this.intId = id;
this.label = name;
this.iconId = iconId;
}
this(int id, string nameResourceId, string iconId = null) {
this.intId = id;
this.label = nameResourceId;
this.iconId = iconId;
}
this(dstring name, string iconId = null) {
this.label = name;
this.iconId = iconId;
}
}
/** UI Strings internationalization translator */ /** UI Strings internationalization translator */
class UIStringTranslator { class UIStringTranslator {

View File

@ -181,6 +181,18 @@ class MLParser {
error("unknown double property " ~ propName); error("unknown double property " ~ propName);
} }
protected void setStringListValueProperty(string propName, StringListValue[] values) {
if (!_currentWidget.setStringListValueListProperty(propName, values)) {
UIString[] strings;
foreach(value; values)
strings ~= value.label;
if (!_currentWidget.setUIStringListProperty(propName, strings)) {
error("unknown string list property " ~ propName);
}
}
}
protected void setRectProperty(string propName, Rect value) { protected void setRectProperty(string propName, Rect value) {
if (!_currentWidget.setRectProperty(propName, value)) if (!_currentWidget.setRectProperty(propName, value))
error("unknown Rect property " ~ propName); error("unknown Rect property " ~ propName);
@ -300,6 +312,66 @@ class MLParser {
setRectProperty(propName, Rect(values[0], values[1], values[2], values[3])); setRectProperty(propName, Rect(values[0], values[1], values[2], values[3]));
} }
// something in []
protected void parseArrayProperty(string propName) {
// current token is Rect
nextToken();
skipWhitespaceAndEolsNoEof();
StringListValue[] values;
for (;;) {
if (_token.type == TokenType.squareClose)
break;
if (_token.type == TokenType.integer) {
if (_token.text.length)
error("Integer literal suffixes not allowed for [] items");
StringListValue value;
value.intId = _token.intvalue;
value.label = UIString(to!dstring(_token.intvalue));
values ~= value;
nextToken();
skipWhitespaceAndEolsNoEof();
if (_token.type == TokenType.comma || _token.type == TokenType.semicolon) {
nextToken();
skipWhitespaceAndEolsNoEof();
}
} else if (_token.type == TokenType.ident) {
string name = _token.text;
StringListValue value;
value.stringId = name;
value.label = UIString(name);
values ~= value;
nextToken();
skipWhitespaceAndEolsNoEof();
if (_token.type == TokenType.comma || _token.type == TokenType.semicolon) {
nextToken();
skipWhitespaceAndEolsNoEof();
}
} else if (_token.type == TokenType.str) {
string name = _token.text;
StringListValue value;
value.stringId = name;
value.label = UIString(name.toUTF32);
values ~= value;
nextToken();
skipWhitespaceAndEolsNoEof();
if (_token.type == TokenType.comma || _token.type == TokenType.semicolon) {
nextToken();
skipWhitespaceAndEolsNoEof();
}
} else {
error("invalid [] item");
}
}
setStringListValueProperty(propName, values);
}
protected void parseProperty() { protected void parseProperty() {
if (_token.type != TokenType.ident) if (_token.type != TokenType.ident)
error("identifier expected"); error("identifier expected");
@ -323,6 +395,8 @@ class MLParser {
error("number expected after + and -"); error("number expected after + and -");
} else if (_token.type == TokenType.floating) } else if (_token.type == TokenType.floating)
setFloatProperty(propName, _token.floatvalue); setFloatProperty(propName, _token.floatvalue);
else if (_token.type == TokenType.squareOpen)
parseArrayProperty(propName);
else if (_token.type == TokenType.str) else if (_token.type == TokenType.str)
setStringProperty(propName, _token.text); setStringProperty(propName, _token.text);
else if (_token.type == TokenType.ident) { else if (_token.type == TokenType.ident) {

View File

@ -41,9 +41,9 @@ enum TokenType : ushort {
minus, minus,
/// + operator /// + operator
plus, plus,
/// [ /// {
curlyOpen, curlyOpen,
/// ] /// }
curlyClose, curlyClose,
/// ( /// (
open, open,

View File

@ -119,6 +119,8 @@ class ComboBoxBase : HorizontalLayout, OnClickHandler {
} }
protected void showPopup() { protected void showPopup() {
if (!_adapter || !_adapter.itemCount)
return; // don't show empty popup
_popupList = createPopup(); _popupList = createPopup();
_popup = window.showPopup(_popupList, this, PopupAlign.Below | PopupAlign.FitAnchorSize); _popup = window.showPopup(_popupList, this, PopupAlign.Below | PopupAlign.FitAnchorSize);
_popup.flags = PopupFlags.CloseOnClickOutside; _popup.flags = PopupFlags.CloseOnClickOutside;
@ -233,6 +235,9 @@ class ComboBox : ComboBoxBase {
} }
@property void items(StringListValue[] items) { @property void items(StringListValue[] items) {
if (auto a = cast(StringListAdapter)_adapter)
a.items = items;
else
setAdapter(new StringListAdapter(items)); setAdapter(new StringListAdapter(items));
if(items.length > 0) { if(items.length > 0) {
selectedItemIndex = 0; selectedItemIndex = 0;
@ -240,6 +245,15 @@ class ComboBox : ComboBoxBase {
requestLayout(); requestLayout();
} }
/// StringListValue list values
override bool setStringListValueListProperty(string propName, StringListValue[] values) {
if (propName == "items") {
items = values;
return true;
}
return false;
}
/// get selected item as text /// get selected item as text
@property dstring selectedItem() { @property dstring selectedItem() {
if (_selectedItemIndex < 0 || _selectedItemIndex >= _adapter.itemCount) if (_selectedItemIndex < 0 || _selectedItemIndex >= _adapter.itemCount)
@ -348,6 +362,9 @@ class IconTextComboBox : ComboBoxBase {
} }
@property void items(StringListValue[] items) { @property void items(StringListValue[] items) {
if (auto a = cast(IconStringListAdapter)_adapter)
a.items = items;
else
setAdapter(new IconStringListAdapter(items)); setAdapter(new IconStringListAdapter(items));
if(items.length > 0) { if(items.length > 0) {
selectedItemIndex = 0; selectedItemIndex = 0;
@ -451,18 +468,42 @@ class ComboEdit : ComboBox {
/// empty parameter list constructor - for usage by factory /// empty parameter list constructor - for usage by factory
this() { this() {
this(null); this(null);
postInit();
} }
/// create with ID parameter /// create with ID parameter
this(string ID) { this(string ID) {
super(ID); super(ID);
postInit();
} }
this(string ID, string[] items) { this(string ID, string[] items) {
super(ID, items); super(ID, items);
postInit();
} }
this(string ID, dstring[] items) { this(string ID, dstring[] items) {
super(ID, items); super(ID, items);
postInit();
}
protected void postInit() {
focusable = false;
clickable = false;
_edit.focusable = true;
keyEvent = delegate(Widget source, KeyEvent event) {
if (event.keyCode == KeyCode.DOWN) {
if (event.action == KeyAction.KeyDown) {
showPopup();
}
}
return _edit.onKeyEvent(event);
};
}
// called to process click and notify listeners
override protected bool handleClick() {
_edit.setFocus();
return true;
} }
@property bool readOnly() { @property bool readOnly() {
@ -484,6 +525,8 @@ class ComboEdit : ComboBox {
res.layoutHeight = WRAP_CONTENT; res.layoutHeight = WRAP_CONTENT;
res.readOnly = false; res.readOnly = false;
_edit = res; _edit = res;
postInit();
//_edit.focusable = true;
return res; return res;
} }

View File

@ -177,43 +177,6 @@ class WidgetListAdapter : ListAdapterBase {
} }
} }
/// string values string list adapter - each item can have optional string or integer id, and optional icon resource id
struct StringListValue {
/// integer id for item
int intId;
/// string id for item
string stringId;
/// icon resource id
string iconId;
/// label to show for item
UIString label;
this(string id, dstring name, string iconId = null) {
this.stringId = id;
this.label = name;
this.iconId = iconId;
}
this(string id, string nameResourceId, string iconId = null) {
this.stringId = id;
this.label = nameResourceId;
this.iconId = iconId;
}
this(int id, dstring name, string iconId = null) {
this.intId = id;
this.label = name;
this.iconId = iconId;
}
this(int id, string nameResourceId, string iconId = null) {
this.intId = id;
this.label = nameResourceId;
this.iconId = iconId;
}
this(dstring name, string iconId = null) {
this.label = name;
this.iconId = iconId;
}
}
/** List adapter providing strings only. */ /** List adapter providing strings only. */
class StringListAdapterBase : ListAdapterBase { class StringListAdapterBase : ListAdapterBase {
protected UIStringCollection _items; protected UIStringCollection _items;
@ -340,6 +303,40 @@ class StringListAdapterBase : ListAdapterBase {
return this; return this;
} }
/** Replace items collection. */
@property StringListAdapterBase items(UIString[] values) {
_items = values;
_intIds.length = items.length;
_states.length = _items.length;
_stringIds.length = items.length;
_iconIds.length = items.length;
for (int i = 0; i < _items.length; i++) {
_intIds[i] = 0;
_stringIds[i] = null;
_iconIds[i] = null;
_states[i] = State.Enabled;
}
updateViews();
return this;
}
/** Replace items collection. */
@property StringListAdapterBase items(StringListValue[] values) {
_items = values;
_intIds.length = items.length;
_states.length = _items.length;
_stringIds.length = items.length;
_iconIds.length = items.length;
for (int i = 0; i < _items.length; i++) {
_intIds[i] = values[i].intId;
_stringIds[i] = values[i].stringId;
_iconIds[i] = values[i].iconId;
_states[i] = State.Enabled;
}
updateViews();
return this;
}
/// returns number of widgets in list /// returns number of widgets in list
@property override int itemCount() const { @property override int itemCount() const {
return _items.length; return _items.length;
@ -1355,6 +1352,15 @@ class StringListWidget : ListWidget {
requestLayout(); requestLayout();
} }
/// StringListValue list values
override bool setStringListValueListProperty(string propName, StringListValue[] values) {
if (propName == "items") {
items = values;
return true;
}
return false;
}
/// get selected item as text /// get selected item as text
@property dstring selectedItem() { @property dstring selectedItem() {
if (_selectedItemIndex < 0 || _selectedItemIndex >= _adapter.itemCount) if (_selectedItemIndex < 0 || _selectedItemIndex >= _adapter.itemCount)

View File

@ -1570,6 +1570,16 @@ public:
return false; return false;
} }
/// StringListValue list values
bool setStringListValueListProperty(string propName, StringListValue[] values) {
return false;
}
/// UIString list values
bool setUIStringListProperty(string propName, UIString[] values) {
return false;
}
/// set string property value, for ML loaders /// set string property value, for ML loaders
bool setBoolProperty(string name, bool value) { bool setBoolProperty(string name, bool value) {
mixin(generatePropertySetters("enabled", "clickable", "checkable", "focusable", "checked", "fontItalic")); mixin(generatePropertySetters("enabled", "clickable", "checkable", "focusable", "checked", "fontItalic"));
@ -1809,3 +1819,4 @@ string generatePropertySettersMethodOverride(string methodName, string typeName,
return res; return res;
} }