mirror of https://github.com/buggins/dlangui.git
ComboEdit enhancements - issue #224
This commit is contained in:
parent
c1a48eea18
commit
53e13ff706
|
@ -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 {
|
||||
|
|
|
@ -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 {
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -41,9 +41,9 @@ enum TokenType : ushort {
|
|||
minus,
|
||||
/// + operator
|
||||
plus,
|
||||
/// [
|
||||
/// {
|
||||
curlyOpen,
|
||||
/// ]
|
||||
/// }
|
||||
curlyClose,
|
||||
/// (
|
||||
open,
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue