diff --git a/examples/example1/src/example1.d b/examples/example1/src/example1.d index a6140f3c..691a0b19 100644 --- a/examples/example1/src/example1.d +++ b/examples/example1/src/example1.d @@ -458,14 +458,20 @@ extern (C) int UIAppMain(string[] args) { */ id: myLabel1 text: "Some text"; padding: 5 + enabled: false } TextWidget { id: myLabel2 text: SOME_TEXT_RESOURCE_ID; margins: 5 + enabled: true } } }); - Log.d("id=", w.id, " text=", w.text, " padding=", w.padding, " margins=", w.margins, " lbl1=", w.childById!TextWidget("myLabel1").text, " lbl2=", w.childById!TextWidget("myLabel2").text); + Log.d("id=", w.id, " text=", w.text, " padding=", w.padding, " margins=", w.margins, + " lbl1.text=", w.childById!TextWidget("myLabel1").text, + " lbl1.enabled=", w.childById!TextWidget("myLabel1").enabled, + " lbl2.text=", w.childById!TextWidget("myLabel2").text + ); destroy(w); layout.childById("BTN1").onClickListener = (delegate (Widget w) { Log.d("onClick ", w.id); return true; }); diff --git a/src/dlangui/core/parser.d b/src/dlangui/core/parser.d index a23b51d4..862071f1 100644 --- a/src/dlangui/core/parser.d +++ b/src/dlangui/core/parser.d @@ -511,44 +511,53 @@ class MLParser { protected void setIntProperty(string propName, int value, string suffix = null) { value = applySuffix(value, suffix); - if (!_currentWidget.setProperty(propName, value)) + if (!_currentWidget.setIntProperty(propName, value)) + error("unknown int property " ~ propName); + } + + protected void setBoolProperty(string propName, bool value) { + if (!_currentWidget.setBoolProperty(propName, value)) error("unknown int property " ~ propName); } protected void setFloatProperty(string propName, double value) { - if (!_currentWidget.setProperty(propName, value)) + if (!_currentWidget.setDoubleProperty(propName, value)) error("unknown double property " ~ propName); } protected void setRectProperty(string propName, Rect value) { - if (!_currentWidget.setProperty(propName, value)) + if (!_currentWidget.setRectProperty(propName, value)) error("unknown Rect property " ~ propName); } protected void setStringProperty(string propName, string value) { if (propName.equal("id")) { - if (!_currentWidget.setProperty(propName, value)) + if (!_currentWidget.setStringProperty(propName, value)) error("cannot set id property for widget"); return; } dstring v = toUTF32(value); - if (!_currentWidget.setProperty(propName, v)) + if (!_currentWidget.setDstringProperty(propName, v)) error("unknown string property " ~ propName); } protected void setIdentProperty(string propName, string value) { if (propName.equal("id")) { - if (!_currentWidget.setProperty(propName, value)) + if (!_currentWidget.setStringProperty(propName, value)) error("cannot set id property for widget"); return; } - if (value.equal("FILL") || value.equal("FILL_PARENT")) + if (value.equal("true")) + setBoolProperty(propName, true); + else if (value.equal("false")) + setBoolProperty(propName, false); + else if (value.equal("FILL") || value.equal("FILL_PARENT")) setIntProperty(propName, FILL_PARENT); else if (value.equal("WRAP") || value.equal("WRAP_CONTENT")) setIntProperty(propName, WRAP_CONTENT); - else if (!_currentWidget.setProperty(propName, value)) + else if (!_currentWidget.setStringProperty(propName, value)) error("unknown ident property " ~ propName); } diff --git a/src/dlangui/widgets/controls.d b/src/dlangui/widgets/controls.d index 49de599c..2b69275a 100644 --- a/src/dlangui/widgets/controls.d +++ b/src/dlangui/widgets/controls.d @@ -207,6 +207,10 @@ class ImageWidget : Widget { return this; } + /// set string property value, for ML loaders + mixin(generatePropertySettersMethodOverride("setStringProperty", "string", + "drawableId")); + /// handle theme change: e.g. reload some themed resources override void onThemeChanged() { if (_drawableId !is null) @@ -244,7 +248,6 @@ class ImageWidget : Widget { } } - /// button with image only class ImageButton : ImageWidget { /// constructor by id and icon resource id @@ -534,6 +537,11 @@ class AbstractSlider : WidgetGroup { } return this; } + + /// set int property value, for ML loaders + mixin(generatePropertySettersMethodOverride("setIntProperty", "int", + "minValue", "maxValue", "pageSize", "position")); + /// set new range (min and max values for slider) AbstractSlider setRange(int min, int max) { if (_minValue != min || _maxValue != max) { @@ -748,6 +756,18 @@ class ScrollBar : AbstractSlider, OnClickHandler { return this; } + /// set string property value, for ML loaders + override bool setStringProperty(string name, string value) { + if (name.equal("orientation")) { + if (value.equal("Vertical") || value.equal("vertical")) + orientation = Orientation.Vertical; + else + orientation = Orientation.Horizontal; + return true; + } + return super.setStringProperty(name, value); + } + /// empty parameter list constructor - for usage by factory this() { diff --git a/src/dlangui/widgets/editors.d b/src/dlangui/widgets/editors.d index a783400e..025aa163 100644 --- a/src/dlangui/widgets/editors.d +++ b/src/dlangui/widgets/editors.d @@ -473,7 +473,14 @@ class EditWidgetBase : ScrollWidgetBase, EditableContentListener, MenuItemAction override uint getCursorType(int x, int y) { return x < _pos.left + _leftPaneWidth ? CursorType.Arrow : CursorType.IBeam; } - + + /// set bool property value, for ML loaders + mixin(generatePropertySettersMethodOverride("setBoolProperty", "bool", + "wantTabs", "showIcons", "showFolding", "showModificationMarks", "showLineNumbers", "readOnly", "replaceMode", "useSpacesForTabs")); + + /// set int property value, for ML loaders + mixin(generatePropertySettersMethodOverride("setIntProperty", "int", + "tabSize")); /// when true, Tab / Shift+Tab presses are processed internally in widget (e.g. insert tab character) instead of focus change navigation. @property bool wantTabs() { @@ -2366,6 +2373,10 @@ class LogWidget : EditBox { /// when true, automatically scrolls down when new lines are appended (usually being reset by scrollbar interaction) @property void scrollLock(bool flg) { _scrollLock = flg; } + this() { + this(null); + } + this(string ID) { super(ID); _scrollLock = true; @@ -2425,3 +2436,6 @@ class LogWidget : EditBox { } } + +import dlangui.widgets.metadata; +mixin(registerWidgets!(EditLine, EditBox, LogWidget)()); diff --git a/src/dlangui/widgets/grid.d b/src/dlangui/widgets/grid.d index 16f9e7b6..ac18bfe8 100644 --- a/src/dlangui/widgets/grid.d +++ b/src/dlangui/widgets/grid.d @@ -56,6 +56,7 @@ import dlangui.widgets.widget; import dlangui.widgets.controls; import dlangui.widgets.scroll; import std.conv; +import std.algorithm : equal; /** * Data provider for GridWidget. @@ -346,10 +347,19 @@ class GridWidgetBase : ScrollWidgetBase { return this; } + /// set bool property value, for ML loaders + mixin(generatePropertySettersMethodOverride("setBoolProperty", "bool", + "showColHeaders", "showColHeaders", "rowSelect")); + + /// set int property value, for ML loaders + mixin(generatePropertySettersMethodOverride("setIntProperty", "int", + "headerCols", "headerRows", "fixedCols", "fixedRows", "cols", "rows", "defColumnWidth", "defRowHeight")); + /// flag to enable column headers @property bool showColHeaders() { return _showColHeaders; } + @property GridWidgetBase showColHeaders(bool show) { if (_showColHeaders != show) { _showColHeaders = show; @@ -1353,3 +1363,5 @@ class StringGridWidget : StringGridWidgetBase { } +import dlangui.widgets.metadata; +mixin(registerWidgets!(StringGridWidget)()); diff --git a/src/dlangui/widgets/layouts.d b/src/dlangui/widgets/layouts.d index 9640882d..d78469a1 100644 --- a/src/dlangui/widgets/layouts.d +++ b/src/dlangui/widgets/layouts.d @@ -810,6 +810,10 @@ class TableLayout : WidgetGroupDefaultDrawing { return (childCount + (_colCount - 1)) / _colCount * _colCount; } + /// set int property value, for ML loaders + mixin(generatePropertySettersMethodOverride("setIntProperty", "int", + "colCount")); + /// Measure widget according to desired width and height constraints. (Step 1 of two phase layout). override void measure(int parentWidth, int parentHeight) { Rect m = margins; diff --git a/src/dlangui/widgets/widget.d b/src/dlangui/widgets/widget.d index d6deade5..c922cfff 100644 --- a/src/dlangui/widgets/widget.d +++ b/src/dlangui/widgets/widget.d @@ -1474,11 +1474,8 @@ class Widget { } /// set string property value, for ML loaders - bool setProperty(string name, string value) { - if (name.equal("id")) { - id = value; - return true; - } + bool setStringProperty(string name, string value) { + mixin(generatePropertySetters("id")); if (name.equal("text")) { text = UIString(value); return true; @@ -1487,7 +1484,7 @@ class Widget { } /// set string property value, for ML loaders - bool setProperty(string name, dstring value) { + bool setDstringProperty(string name, dstring value) { if (name.equal("text")) { text = UIString(value); return true; @@ -1496,7 +1493,7 @@ class Widget { } /// set string property value, for ML loaders - bool setProperty(string name, UIString value) { + bool setUistringProperty(string name, UIString value) { if (name.equal("text")) { text = value; return true; @@ -1505,37 +1502,22 @@ class Widget { } /// set string property value, for ML loaders - bool setProperty(string name, bool value) { - if (name.equal("enabled")) { - enabled = value; - return true; - } - if (name.equal("clickable")) { - clickable = value; - return true; - } - if (name.equal("checkable")) { - checkable = value; - return true; - } - if (name.equal("checked")) { - checked = value; - return true; - } + bool setBoolProperty(string name, bool value) { + mixin(generatePropertySetters("enabled", "clickable", "checkable", "focusable", "checked")); return false; } /// set double property value, for ML loaders - bool setProperty(string name, double value) { + bool setDoubleProperty(string name, double value) { if (name.equal("alpha")) { int n = cast(int)(value * 255); - setProperty(name, n); + setIntProperty(name, n); } return false; } /// set int property value, for ML loaders - bool setProperty(string name, int value) { + bool setIntProperty(string name, int value) { if (name.equal("alpha")) { if (value < 0) value = 0; @@ -1544,38 +1526,7 @@ class Widget { alpha = cast(ushort)value; return true; } - if (name.equal("minWidth")) { - minWidth = value; - return true; - } - if (name.equal("maxWidth")) { - maxWidth = value; - return true; - } - if (name.equal("minHeight")) { - minHeight = value; - return true; - } - if (name.equal("maxHeight")) { - maxHeight = value; - return true; - } - if (name.equal("layoutWidth")) { - layoutWidth = value; - return true; - } - if (name.equal("layoutHeight")) { - layoutHeight = value; - return true; - } - if (name.equal("textColor")) { - textColor = cast(uint)value; - return true; - } - if (name.equal("backgroundColor")) { - backgroundColor = cast(uint)value; - return true; - } + mixin(generatePropertySetters("minWidth", "maxWidth", "minHeight", "maxHeight", "layoutWidth", "layoutHeight", "textColor", "backgroundColor")); if (name.equal("margins")) { // use same value for all sides margins = Rect(value, value, value, value); return true; @@ -1587,16 +1538,9 @@ class Widget { return false; } - /// set int property value, for ML loaders - bool setProperty(string name, Rect value) { - if (name.equal("margins")) { - margins = value; - return true; - } - if (name.equal("padding")) { - padding = value; - return true; - } + /// set Rect property value, for ML loaders + bool setRectProperty(string name, Rect value) { + mixin(generatePropertySetters("margins", "padding")); return false; } } @@ -1756,4 +1700,30 @@ mixin template ActionTooltipSupport() { } } +/// use in mixin to set this object property with name propName with value of variable value if variable name matches propName +string generatePropertySetter(string propName) { + return " if (name.equal(\"" ~ propName ~ "\")) { \n" ~ + " " ~ propName ~ " = value;\n" ~ + " return true;\n" ~ + " }\n"; +} + +/// use in mixin to set this object properties with names from parameter list with value of variable value if variable name matches propName +string generatePropertySetters(string[] propNames...) { + string res; + foreach(propName; propNames) + res ~= generatePropertySetter(propName); + return res; +} + +/// use in mixin for method override to set this object properties with names from parameter list with value of variable value if variable name matches propName +string generatePropertySettersMethodOverride(string methodName, string typeName, string[] propNames...) { + return " override bool " ~ methodName ~ "(string name, " ~ typeName ~ " value) {\n" ~ + " return super." ~ methodName ~ "(name, value);\n" ~ + " }\n"; + string res; + foreach(propName; propNames) + res ~= generatePropertySetter(propName); + return res; +}