diff --git a/dlangui-msvc.visualdproj b/dlangui-msvc.visualdproj
index 6fc6c1e8..b8eed368 100644
--- a/dlangui-msvc.visualdproj
+++ b/dlangui-msvc.visualdproj
@@ -8,7 +8,7 @@
0
0
0
- 0
+ 1
0
0
0
@@ -317,7 +317,7 @@
0
0
0
- 0
+ 1
0
0
0
@@ -1276,6 +1276,7 @@
+
diff --git a/src/dlangui/core/types.d b/src/dlangui/core/types.d
index 260f38cb..21187060 100644
--- a/src/dlangui/core/types.d
+++ b/src/dlangui/core/types.d
@@ -50,12 +50,18 @@ struct Point {
int x;
int y;
- Point opBinary(string op)(Point v) if (op == "+") {
+ Point opBinary(string op)(Point v) const if (op == "+") {
return Point(x + v.x, y + v.y);
}
- Point opBinary(string op)(Point v) if (op == "-") {
+ Point opBinary(string op)(int n) const if (op == "*") {
+ return Point(x * n, y * n);
+ }
+ Point opBinary(string op)(Point v) const if (op == "-") {
return Point(x - v.x, y - v.y);
}
+ Point opUnary(string op)() const if (op == "-") {
+ return Point(-x, -y);
+ }
int opCmp(ref const Point b) const {
if (x == b.x) return y - b.y;
return x - b.x;
diff --git a/src/dlangui/platforms/common/startup.d b/src/dlangui/platforms/common/startup.d
index ba145a56..70190234 100644
--- a/src/dlangui/platforms/common/startup.d
+++ b/src/dlangui/platforms/common/startup.d
@@ -416,41 +416,7 @@ extern (C) void initResourceManagers() {
Log.d("initResourceManagers() -- finished");
}
-/// register standard widgets to use in DML
-void registerStandardWidgets() {
- Log.d("Registering standard widgets for DML");
- import dlangui.widgets.metadata;
- import dlangui.widgets.widget;
- import dlangui.widgets.layouts;
- import dlangui.widgets.controls;
- import dlangui.widgets.scrollbar;
- import dlangui.widgets.lists;
- import dlangui.widgets.combobox;
- import dlangui.widgets.editors;
- import dlangui.widgets.grid;
- import dlangui.widgets.groupbox;
- import dlangui.widgets.progressbar;
- import dlangui.dialogs.filedlg;
- import dlangui.widgets.menu;
- import dlangui.widgets.tree;
- import dlangui.widgets.tabs;
- mixin(registerWidgets!(FileNameEditLine, DirEditLine, //dlangui.dialogs.filedlg
- ComboBox, ComboEdit, //dlangui.widgets.combobox
- Widget, TextWidget, MultilineTextWidget, Button, ImageWidget, ImageButton, ImageCheckButton, ImageTextButton,
- SwitchButton, RadioButton, CheckBox, HSpacer, VSpacer, CanvasWidget, // dlangui.widgets.controls
- ScrollBar, SliderWidget, // dlangui.widgets.scrollbar
- EditLine, EditBox, LogWidget,//dlangui.widgets.editors
- GroupBox, // dlangui.widgets.groupbox
- ProgressBarWidget, // dlangui.widgets.progressbar
- StringGridWidget, //dlangui.widgets.grid
- VerticalLayout, HorizontalLayout, TableLayout, FrameLayout, // dlangui.widgets.layouts
- ListWidget, StringListWidget,//dlangui.widgets.lists
- MainMenu, //dlangui.widgets.menu
- TreeWidget, // dlangui.widgets.tree
- TabWidget, // dlangui.widgets.tabs
- )("void registerWidgets"));
- registerWidgets();
-}
+
/// call this from shared static this()
extern (C) void initSharedResourceManagers() {
@@ -466,6 +432,9 @@ shared static this() {
//initSharedResourceManagers();
}
+/// register standard widgets to use in DML
+extern(C) void registerStandardWidgets();
+
/// call this when all resources are supposed to be freed to report counts of non-freed resources by type
extern (C) void releaseResourcesOnAppExit() {
diff --git a/src/dlangui/widgets/dmlwidgets.d b/src/dlangui/widgets/dmlwidgets.d
new file mode 100644
index 00000000..edff07ac
--- /dev/null
+++ b/src/dlangui/widgets/dmlwidgets.d
@@ -0,0 +1,117 @@
+module dlangui.widgets.dmlwidgets;
+
+/// register standard widgets to use in DML
+extern(C) void registerStandardWidgets() {
+ import dlangui.core.config;
+ import dlangui.core.logger;
+
+ Log.d("Registering standard widgets for DML");
+
+ import dlangui.widgets.metadata;
+ import dlangui.widgets.widget;
+
+ mixin(registerWidgetMetadataClass!Widget);
+
+ import dlangui.widgets.layouts;
+ mixin(registerWidgetMetadataClass!VerticalLayout);
+ mixin(registerWidgetMetadataClass!HorizontalLayout);
+ mixin(registerWidgetMetadataClass!TableLayout);
+ mixin(registerWidgetMetadataClass!FrameLayout); // dlangui.widgets.layouts
+
+ import dlangui.widgets.controls;
+
+ mixin(registerWidgetMetadataClass!TextWidget);
+ mixin(registerWidgetMetadataClass!MultilineTextWidget);
+ mixin(registerWidgetMetadataClass!Button);
+ mixin(registerWidgetMetadataClass!ImageWidget);
+ mixin(registerWidgetMetadataClass!ImageButton);
+ mixin(registerWidgetMetadataClass!ImageCheckButton);
+ mixin(registerWidgetMetadataClass!ImageTextButton);
+ mixin(registerWidgetMetadataClass!SwitchButton);
+ mixin(registerWidgetMetadataClass!RadioButton);
+ mixin(registerWidgetMetadataClass!CheckBox);
+ mixin(registerWidgetMetadataClass!HSpacer);
+ mixin(registerWidgetMetadataClass!VSpacer);
+ mixin(registerWidgetMetadataClass!CanvasWidget); // dlangui.widgets.controls
+
+ import dlangui.widgets.scrollbar;
+
+ mixin(registerWidgetMetadataClass!ScrollBar);
+ mixin(registerWidgetMetadataClass!SliderWidget); // dlangui.widgets.scrollbar
+
+ import dlangui.widgets.lists;
+
+ mixin(registerWidgetMetadataClass!ListWidget);
+ mixin(registerWidgetMetadataClass!StringListWidget);//dlangui.widgets.lists
+
+
+ import dlangui.widgets.editors;
+
+ mixin(registerWidgetMetadataClass!EditLine);
+ mixin(registerWidgetMetadataClass!EditBox);
+ mixin(registerWidgetMetadataClass!LogWidget);//dlangui.widgets.editors
+
+ import dlangui.widgets.combobox;
+ mixin(registerWidgetMetadataClass!ComboBox);
+ mixin(registerWidgetMetadataClass!ComboEdit); //dlangui.widgets.combobox
+
+ import dlangui.widgets.grid;
+
+ mixin(registerWidgetMetadataClass!StringGridWidget); //dlangui.widgets.grid
+
+ import dlangui.widgets.groupbox;
+
+ mixin(registerWidgetMetadataClass!GroupBox); // dlangui.widgets.groupbox
+
+ import dlangui.widgets.progressbar;
+
+ mixin(registerWidgetMetadataClass!ProgressBarWidget); // dlangui.widgets.progressbar
+
+ import dlangui.widgets.menu;
+
+ mixin(registerWidgetMetadataClass!MainMenu); //dlangui.widgets.menu
+
+ import dlangui.widgets.tree;
+
+ mixin(registerWidgetMetadataClass!TreeWidget); // dlangui.widgets.tree
+
+ import dlangui.widgets.tabs;
+
+ mixin(registerWidgetMetadataClass!TabWidget); // dlangui.widgets.tabs
+
+ import dlangui.dialogs.filedlg;
+
+ mixin(registerWidgetMetadataClass!FileNameEditLine);
+ mixin(registerWidgetMetadataClass!DirEditLine);
+
+ /*
+ mixin (registerWidgets!("void registerWidgets1",
+ FileNameEditLine, DirEditLine, //dlangui.dialogs.filedlg
+ ComboBox, ComboEdit, //dlangui.widgets.combobox
+ // )());
+ //mixin(registerWidgets!("void registerWidgets2",
+ Widget, TextWidget, MultilineTextWidget, Button, ImageWidget, ImageButton, ImageCheckButton, ImageTextButton,
+ ));
+ mixin(registerWidgets!("void registerWidgets3",
+ SwitchButton, RadioButton, CheckBox, HSpacer, VSpacer, CanvasWidget, // dlangui.widgets.controls
+ ScrollBar, SliderWidget, // dlangui.widgets.scrollbar
+ EditLine, EditBox, LogWidget,//dlangui.widgets.editors
+ ));
+ mixin(registerWidgets!("void registerWidgets4",
+ GroupBox, // dlangui.widgets.groupbox
+ ProgressBarWidget, // dlangui.widgets.progressbar
+ StringGridWidget, //dlangui.widgets.grid
+ VerticalLayout, HorizontalLayout, TableLayout, FrameLayout, // dlangui.widgets.layouts
+ MainMenu, //dlangui.widgets.menu
+ TreeWidget, // dlangui.widgets.tree
+ TabWidget, // dlangui.widgets.tabs
+ ));
+
+
+ registerWidgets1();
+ //registerWidgets2();
+ registerWidgets3();
+ registerWidgets4();
+ */
+}
+
diff --git a/src/dlangui/widgets/lists.d b/src/dlangui/widgets/lists.d
index e46ae548..e102a76f 100644
--- a/src/dlangui/widgets/lists.d
+++ b/src/dlangui/widgets/lists.d
@@ -1402,7 +1402,8 @@ class ListWidget : WidgetGroup, OnScrollHandler, OnAdapterChangeHandler {
class StringListWidget : ListWidget {
import std.conv : to;
- import std.datetime : dto = to, StopWatch;
+ import std.datetime.stopwatch : StopWatch;
+ import core.time : dur;
private dstring _searchString;
private StopWatch _stopWatch;
@@ -1479,9 +1480,10 @@ class StringListWidget : ListWidget {
if (event.action == KeyAction.Text) {
if ( !_stopWatch.running) { _stopWatch.start; }
- auto timePassed = _stopWatch.peek.dto!("seconds", float)(); // dtop is std.datetime.to
+ auto timePassed = _stopWatch.peek; //.to!("seconds", float)(); // dtop is std.datetime.to
- if (timePassed > 0.5) _searchString = ""d;
+ if (timePassed > dur!"msecs"(500))
+ _searchString = ""d;
_searchString ~= to!dchar(event.text.toUTF8);
_stopWatch.reset;
diff --git a/src/dlangui/widgets/metadata.d b/src/dlangui/widgets/metadata.d
index 86c630e8..793bd49e 100644
--- a/src/dlangui/widgets/metadata.d
+++ b/src/dlangui/widgets/metadata.d
@@ -83,53 +83,136 @@ template isMarkupType(T)
is(T==StringListValue[]);
}
-string generatePropertiesMetadata(alias T)() {
- version (GENERATE_PROPERTY_METADATA) {
- import std.algorithm.searching;
+private bool hasPropertyAnnotation(alias ti)() {
+ bool res = false;
+ foreach ( attr; __traits(getFunctionAttributes, ti)) {
+ static if (attr == "@property") {
+ res = true;
+ }
+ }
+ return res;
+}
+/*
+string markupPropertyGetterType(alias overload)() {
+ static if (__traits(getProtection, overload) == "public") {
import std.traits;
- import std.meta;
- char[] str;
- str ~= "[";
- foreach(m; __traits(allMembers, T)) {
- static if (__traits(compiles, (typeof(__traits(getMember, T, m))))){
- // skip non-public members, only functions that takes 0 or 1 arguments, add only types that parseable in markup
- static if (__traits(getProtection, __traits(getMember, T, m)) == "public") {
- static if (isFunction!(__traits(getMember, T, m))) {
- immutable int fnArity = arity!(__traits(getMember, T, m));
- static if (fnArity == 0 || fnArity == 1) {
- // TODO: filter out templates, signals and such
- // iterates class members and process @property functions (note: foreach {if})
- foreach ( attr; __traits(getFunctionAttributes, __traits(getMember, T, m))) if (attr == "@property") {
- alias ret = ReturnType!(__traits(getMember, T, m));
- alias params = Parameters!(__traits(getMember, T, m));
- string typestring;
- static if (fnArity == 0 && !__traits(isTemplate,ret) && isMarkupType!ret)
- typestring = ret.stringof;
- else static if (fnArity == 1 && !__traits(isTemplate,params[0]) && isMarkupType!(params[0]))
- typestring = params[0].stringof;
- if (typestring is null)
- continue;
- str ~= "WidgetPropertyMetadata( typeid(" ~ typestring ~ "), " ~ m.stringof ~ " ), ";
- }
+ static if (is(typeof(overload) == function) && hasPropertyAnnotation!overload) {
+ alias ret = ReturnType!overload;
+ //alias params = Parameters!overload;
+ alias params = ParameterTypeTuple!overload;
+ static if (params.length == 0 && isMarkupType!ret && !isTemplate!ret) {
+ return ret.stringof;
+ } else {
+ return null;
+ }
+ } else {
+ return null;
+ }
+ }
+}
+
+string markupPropertySetterType(alias overload)() {
+ static if (__traits(getProtection, overload) == "public") {
+ import std.traits;
+ static if (is(typeof(overload) == function) && hasPropertyAnnotation!overload) {
+ //alias params = Parameters!overload;
+ alias params = ParameterTypeTuple!overload;
+ static if (params.length == 1 && isMarkupType!(params[0]) && !isTemplate!(params[0])) {
+ return params[0].stringof;
+ } else {
+ return null;
+ }
+ } else {
+ return null;
+ }
+ }
+}
+*/
+
+private template isPublicPropertyFunction(alias overload) {
+ static if (__traits(getProtection, overload) == "public") {
+ static if (hasPropertyAnnotation!overload) {
+ enum isPublicPropertyFunction = true;
+ } else {
+ enum isPublicPropertyFunction = false;
+ }
+ } else {
+ enum isPublicPropertyFunction = false;
+ }
+ //pragma(msg, is(typeof(overload) == function).stringof);
+ //enum isPublicPropertyFunction = (__traits(getProtection, overload) == "public") && is(typeof(overload) == function);// && hasPropertyAnnotation!overload;
+}
+
+private template markupPropertyType(alias overload) {
+ import std.traits : ReturnType, ParameterTypeTuple;
+ alias ret = ReturnType!overload;
+ alias params = ParameterTypeTuple!overload;
+ static if (params.length == 0 && isMarkupType!ret /* && !isTemplate!ret*/) {
+ enum string markupPropertyType = ret.stringof;
+ } else static if (params.length == 1 && isMarkupType!(params[0]) /* && !isTemplate!(params[0])*/) {
+ enum string markupPropertyType = params[0].stringof;
+ } else {
+ enum string markupPropertyType = null;
+ }
+}
+
+private string[] generatePropertyTypeList(alias T)() {
+ import std.meta;
+ string[] properties;
+ properties ~= "[";
+ foreach(m; __traits(allMembers, T)) {
+ static if (__traits(compiles, (typeof(__traits(getMember, T, m))))){
+ //static if (is (typeof(__traits(getMember, T, m)) == function)) {
+ static if (__traits(isVirtualFunction, __traits(getMember, T, m))) {//
+ import std.traits : MemberFunctionsTuple;
+ alias overloads = typeof(__traits(getVirtualFunctions, T, m));
+ static if (overloads.length == 2) {
+ static if (isPublicPropertyFunction!(__traits(getVirtualFunctions, T, m)[0]) && isPublicPropertyFunction!(__traits(getVirtualFunctions, T, m)[1])) {
+ //pragma(msg, m ~ " isPublicPropertyFunction0=" ~ isPublicPropertyFunction!(__traits(getVirtualFunctions, T, m)[0]).stringof);
+ //pragma(msg, m ~ " isPublicPropertyFunction1=" ~ isPublicPropertyFunction!(__traits(getVirtualFunctions, T, m)[1]).stringof);
+ immutable getterType = markupPropertyType!(__traits(getVirtualFunctions, T, m)[0]);
+ immutable setterType = markupPropertyType!(__traits(getVirtualFunctions, T, m)[1]);
+ static if (getterType && setterType && getterType == setterType) {
+ //pragma(msg, "markup property found: " ~ getterType ~ " " ~ m.stringof);
+ properties ~= "WidgetPropertyMetadata( typeid(" ~ getterType ~ "), " ~ m.stringof ~ " ), ";
}
}
}
}
}
- str ~= "]";
- return cast(string)str;
+ }
+ properties ~= "]";
+ return properties;
+}
+
+string joinStrings(string[] lines) {
+ if (lines.length == 0)
+ return "";
+ if (lines.length == 1)
+ return lines[0];
+ else
+ return joinStrings(lines[0 .. $/2]) ~ joinStrings(lines[$/2 .. $]);
+}
+
+private string generatePropertiesMetadata(alias T)() if (is(T : Widget)) {
+ version (GENERATE_PROPERTY_METADATA) {
+ //import std.algorithm.searching;
+ //import std.traits : MemberFunctionsTuple;
+ //import std.meta;
+ auto properties = generatePropertyTypeList!T;
+ return joinStrings(properties);
} else {
return "[]";
}
}
-string generateMetadataClass(alias t)() {
+string generateMetadataClass(alias t)() if (is(t : Widget)) {
//pragma(msg, moduleName!t);
import std.traits;
//pragma(msg, getSignalList!t);
//pragma(msg, generatePropertiesMetadata!t);
immutable string metadataClassName = t.stringof ~ "Metadata";
- return "class " ~ metadataClassName ~ " : WidgetMetadataDef { \n" ~
+ return "static class " ~ metadataClassName ~ " : WidgetMetadataDef { \n" ~
" override Widget create() {\n" ~
" return new " ~ moduleName!t ~ "." ~ t.stringof ~ "();\n" ~
" }\n" ~
@@ -142,33 +225,73 @@ string generateMetadataClass(alias t)() {
" override string fullName() {\n" ~
" return \"" ~ moduleName!t ~ "." ~ t.stringof ~ "\";\n" ~
" }\n" ~
- " override WidgetPropertyMetadata[] properties() {" ~
+ " override WidgetPropertyMetadata[] properties() {\n" ~
" return " ~ generatePropertiesMetadata!t ~ ";\n" ~
" }\n" ~
"}\n";
}
-string generateRegisterMetadataClass(alias t)() {
+string generateRegisterMetadataClass(alias t)() if (is(t : Widget)) {
immutable string metadataClassName = t.stringof ~ "Metadata";
- return "registerWidgetMetadata(\"" ~ t.stringof ~ "\", new " ~ metadataClassName ~ "());\n";
+ //pragma(msg, metadataClassName);
+ return "registerWidgetMetadata(\"" ~ t.stringof ~ "\", new " ~ t.stringof ~ "Metadata" ~ "());\n";
}
-string registerWidgets(T...)(string registerFunctionName = "__gshared static this") {
- string classDefs;
- string registerDefs;
+template registerWidgetMetadataClass(alias t) if (is(t : Widget)) {
+ //pragma(msg, t.stringof);
+ //pragma(msg, generateMetadataClass!t);
+ immutable string classDef = generateMetadataClass!t;
+ immutable string registerDef = "registerWidgetMetadata(\"" ~ t.stringof ~ "\", new " ~ t.stringof ~ "Metadata" ~ "());\n";
+ enum registerWidgetMetadataClass = classDef ~ registerDef;
+ //mixin(classDef);
+
+ //pragma(msg, "registerWidgetMetadata(\"" ~ t.stringof ~ "\", new " ~ t.stringof ~ "Metadata" ~ "());\n");
+ //mixin("registerWidgetMetadata(\"" ~ t.stringof ~ "\", new " ~ t.stringof ~ "Metadata" ~ "());\n");
+}
+
+string registerWidgetsFunction(string registerFunctionName = "__gshared static this", T...)() {
+ pragma(msg, registerFunctionName);
+ pragma(msg, T);
+ string[] registerDefs;
foreach(t; T) {
- //pragma(msg, t.stringof);
+ pragma(msg, t.stringof);
//pragma(msg, moduleName!t);
//
- immutable string classdef = generateMetadataClass!t;
- //pragma(msg, classdef);
- immutable string registerdef = generateRegisterMetadataClass!t;
- //pragma(msg, registerdef);
- classDefs ~= classdef;
- registerDefs ~= registerdef;
+ static if (is(t : Widget)) {
+ //pragma(msg, classdef);
+ immutable string registerdef = generateRegisterMetadataClass!t;
+ pragma(msg, registerdef);
+ registerDefs ~= registerdef;
+ } else {
+ pragma(msg, "Skipping non-widget class: " ~ t.stringof);
+ }
//registerWidgetMetadata(T.stringof, new Metadata());
}
- return classDefs ~ "\n" ~ registerFunctionName ~ "() {\n" ~ registerDefs ~ "}";
+ return registerFunctionName ~ "() {\n" ~ joinStrings(registerDefs) ~ "}\n";
+}
+
+string registerWidgets(string registerFunctionName = "__gshared static this", T...)() {
+ pragma(msg, registerFunctionName);
+ pragma(msg, T);
+ string[] classDefs;
+ string[] registerDefs;
+ foreach(t; T) {
+ pragma(msg, t.stringof);
+ //pragma(msg, moduleName!t);
+ //
+ static if (is(t : Widget)) {
+ immutable string classdef = generateMetadataClass!t;
+ //pragma(msg, classdef);
+ immutable string registerdef = generateRegisterMetadataClass!t;
+ pragma(msg, registerdef);
+ classDefs ~= classdef;
+ registerDefs ~= registerdef;
+ } else {
+ pragma(msg, "Skipping non-widget class: " ~ t.stringof);
+ }
+ //registerWidgetMetadata(T.stringof, new Metadata());
+ }
+ return joinStrings(classDefs) ~ "\n" ~ registerFunctionName ~ "() {\n" ~ joinStrings(registerDefs) ~ "}\n";
}
/// returns true if passed name is identifier of registered widget class
diff --git a/src/dlangui/widgets/widget.d b/src/dlangui/widgets/widget.d
index e769f82a..3ac0e600 100644
--- a/src/dlangui/widgets/widget.d
+++ b/src/dlangui/widgets/widget.d
@@ -637,6 +637,13 @@ public:
/// sets layout weight (while resizing to fill parent, widget will be resized proportionally to this value)
@property Widget layoutWeight(int value) { ownStyle.layoutWeight = value; return this; }
+ /// sets layoutWidth=FILL_PARENT and layoutHeight=FILL_PARENT
+ Widget fillParent() { return layoutWidth(FILL_PARENT).layoutHeight(FILL_PARENT); }
+ /// sets layoutWidth=FILL_PARENT
+ Widget fillHorizontal() { return layoutWidth(FILL_PARENT); }
+ /// sets layoutHeight=FILL_PARENT
+ Widget fillVertical() { return layoutHeight(FILL_PARENT); }
+
/// returns widget visibility (Visible, Invisible, Gone)
@property Visibility visibility() { return _visibility; }
/// sets widget visibility (Visible, Invisible, Gone)