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
CheckBox { id: cb1; text: "checkbox 1" }
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 {

View File

@ -192,20 +192,42 @@ struct UIStringCollection {
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);
}
/** 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 */
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);
}
}
@ -226,6 +248,10 @@ struct UIStringCollection {
s = item;
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 */
void add(UIString item, int index = -1) {
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 */
class UIStringTranslator {

View File

@ -181,6 +181,18 @@ class MLParser {
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) {
if (!_currentWidget.setRectProperty(propName, value))
error("unknown Rect property " ~ propName);
@ -300,6 +312,66 @@ class MLParser {
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() {
if (_token.type != TokenType.ident)
error("identifier expected");
@ -323,6 +395,8 @@ class MLParser {
error("number expected after + and -");
} else if (_token.type == TokenType.floating)
setFloatProperty(propName, _token.floatvalue);
else if (_token.type == TokenType.squareOpen)
parseArrayProperty(propName);
else if (_token.type == TokenType.str)
setStringProperty(propName, _token.text);
else if (_token.type == TokenType.ident) {

View File

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

View File

@ -119,6 +119,8 @@ class ComboBoxBase : HorizontalLayout, OnClickHandler {
}
protected void showPopup() {
if (!_adapter || !_adapter.itemCount)
return; // don't show empty popup
_popupList = createPopup();
_popup = window.showPopup(_popupList, this, PopupAlign.Below | PopupAlign.FitAnchorSize);
_popup.flags = PopupFlags.CloseOnClickOutside;
@ -233,13 +235,25 @@ class ComboBox : ComboBoxBase {
}
@property void items(StringListValue[] items) {
setAdapter(new StringListAdapter(items));
if (auto a = cast(StringListAdapter)_adapter)
a.items = items;
else
setAdapter(new StringListAdapter(items));
if(items.length > 0) {
selectedItemIndex = 0;
}
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
@property dstring selectedItem() {
if (_selectedItemIndex < 0 || _selectedItemIndex >= _adapter.itemCount)
@ -348,7 +362,10 @@ class IconTextComboBox : ComboBoxBase {
}
@property void items(StringListValue[] items) {
setAdapter(new IconStringListAdapter(items));
if (auto a = cast(IconStringListAdapter)_adapter)
a.items = items;
else
setAdapter(new IconStringListAdapter(items));
if(items.length > 0) {
selectedItemIndex = 0;
}
@ -451,18 +468,42 @@ class ComboEdit : ComboBox {
/// empty parameter list constructor - for usage by factory
this() {
this(null);
postInit();
}
/// create with ID parameter
this(string ID) {
super(ID);
postInit();
}
this(string ID, string[] items) {
super(ID, items);
postInit();
}
this(string ID, dstring[] 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() {
@ -484,6 +525,8 @@ class ComboEdit : ComboBox {
res.layoutHeight = WRAP_CONTENT;
res.readOnly = false;
_edit = res;
postInit();
//_edit.focusable = true;
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. */
class StringListAdapterBase : ListAdapterBase {
protected UIStringCollection _items;
@ -340,6 +303,40 @@ class StringListAdapterBase : ListAdapterBase {
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
@property override int itemCount() const {
return _items.length;
@ -1355,6 +1352,15 @@ class StringListWidget : ListWidget {
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
@property dstring selectedItem() {
if (_selectedItemIndex < 0 || _selectedItemIndex >= _adapter.itemCount)

View File

@ -1570,6 +1570,16 @@ public:
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
bool setBoolProperty(string name, bool value) {
mixin(generatePropertySetters("enabled", "clickable", "checkable", "focusable", "checked", "fontItalic"));
@ -1809,3 +1819,4 @@ string generatePropertySettersMethodOverride(string methodName, string typeName,
return res;
}