mirror of https://github.com/buggins/dlangui.git
ML parser, continue
This commit is contained in:
parent
e497b6bb36
commit
bec083326b
|
@ -426,6 +426,7 @@
|
|||
<File path="src\dlangui\widgets\layouts.d" />
|
||||
<File path="src\dlangui\widgets\lists.d" />
|
||||
<File path="src\dlangui\widgets\menu.d" />
|
||||
<File path="src\dlangui\widgets\metadata.d" />
|
||||
<File path="src\dlangui\widgets\popup.d" />
|
||||
<File path="src\dlangui\widgets\scroll.d" />
|
||||
<File path="src\dlangui\widgets\srcedit.d" />
|
||||
|
|
|
@ -445,6 +445,15 @@ extern (C) int UIAppMain(string[] args) {
|
|||
layout.addChild((new TextWidget(null, "Text widget3 with very long text"d)).textColor(0x004000));
|
||||
layout.addChild(new VSpacer()); // vertical spacer to fill extra space
|
||||
|
||||
/*
|
||||
import dlangui.core.parser;
|
||||
Widget w = parseML(q{
|
||||
TextWidget {
|
||||
}
|
||||
});
|
||||
Log.d("id=", w.id);
|
||||
*/
|
||||
|
||||
layout.childById("BTN1").onClickListener = (delegate (Widget w) { Log.d("onClick ", w.id); return true; });
|
||||
layout.childById("BTN2").onClickListener = (delegate (Widget w) { Log.d("onClick ", w.id); return true; });
|
||||
layout.childById("BTN3").onClickListener = (delegate (Widget w) { Log.d("onClick ", w.id); return true; });
|
||||
|
|
|
@ -2,6 +2,7 @@ module dlangui.core.parser;
|
|||
|
||||
import dlangui.core.linestream;
|
||||
import dlangui.widgets.widget;
|
||||
import dlangui.widgets.metadata;
|
||||
import std.conv : to;
|
||||
|
||||
class ParserException : Exception {
|
||||
|
@ -313,7 +314,7 @@ class Tokenizer {
|
|||
}
|
||||
|
||||
protected ref const(Token) parseOp(TokenType op) {
|
||||
_token.type = TokenType.error;
|
||||
_token.type = op;
|
||||
skipChar();
|
||||
return _token;
|
||||
}
|
||||
|
@ -380,26 +381,41 @@ class MLParser {
|
|||
|
||||
protected Token _token;
|
||||
|
||||
|
||||
protected void nextToken() {
|
||||
_token = _tokenizer.nextToken();
|
||||
Log.d("parsed token: ", _token.type, " ", _token.line, ":", _token.pos, " ", _token.text);
|
||||
}
|
||||
|
||||
protected void skipWhitespaceAndEols() {
|
||||
for (;;) {
|
||||
_token = _tokenizer.nextToken();
|
||||
if (_token.type != TokenType.eol && _token.type != TokenType.eof && _token.type != TokenType.whitespace && _token.type != TokenType.comment)
|
||||
nextToken();
|
||||
if (_token.type != TokenType.eol && _token.type != TokenType.whitespace && _token.type != TokenType.comment)
|
||||
break;
|
||||
}
|
||||
if (_token.type == TokenType.error)
|
||||
_tokenizer.emitError("error while parsing ML code");
|
||||
}
|
||||
|
||||
protected void skipWhitespace() {
|
||||
for (;;) {
|
||||
nextToken();
|
||||
if (_token.type != TokenType.whitespace && _token.type != TokenType.comment)
|
||||
break;
|
||||
}
|
||||
if (_token.type == TokenType.error)
|
||||
_tokenizer.emitError("error while parsing ML code");
|
||||
}
|
||||
|
||||
protected void error(string msg) {
|
||||
_tokenizer.emitError(msg);
|
||||
}
|
||||
|
||||
Widget createWidget(string name) {
|
||||
WidgetFactory factory = getWidgetFactory(name);
|
||||
if (!factory)
|
||||
error("Cannot create widget " ~ name ~ " : unknown class");
|
||||
return factory();
|
||||
auto metadata = findWidgetMetadata(name);
|
||||
if (!metadata)
|
||||
error("Cannot create widget " ~ name ~ " : unregistered widget class");
|
||||
return metadata.create();
|
||||
}
|
||||
|
||||
protected void createContext(string name) {
|
||||
|
@ -419,6 +435,11 @@ class MLParser {
|
|||
if (!_context)
|
||||
_tokenizer.emitError("No context widget is specified!");
|
||||
skipWhitespaceAndEols();
|
||||
if (_token.type != TokenType.curlyClose) // {
|
||||
_tokenizer.emitError("} is expected");
|
||||
skipWhitespaceAndEols();
|
||||
if (_token.type != TokenType.eof) // {
|
||||
_tokenizer.emitError("end of file expected");
|
||||
return _context;
|
||||
}
|
||||
|
||||
|
@ -427,10 +448,12 @@ class MLParser {
|
|||
_tokenizer = null;
|
||||
}
|
||||
|
||||
/// Parse DlangUI ML code
|
||||
static Widget parse(string code, string filename = "", Widget context = null) {
|
||||
MLParser parser = new MLParser(code, filename);
|
||||
scope(exit) destroy(parser);
|
||||
return parser.parse();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Parse DlangUI ML code
|
||||
public Widget parseML(string code, string filename = "", Widget context = null) {
|
||||
MLParser parser = new MLParser(code, filename);
|
||||
scope(exit) destroy(parser);
|
||||
return parser.parse();
|
||||
}
|
||||
|
|
|
@ -1029,3 +1029,5 @@ class CanvasWidget : Widget {
|
|||
}
|
||||
}
|
||||
|
||||
import dlangui.widgets.metadata;
|
||||
mixin(registerWidgets!(Widget, TextWidget, Button, ImageWidget, ImageButton, ImageTextButton, RadioButton, CheckBox, ScrollBar)());
|
||||
|
|
|
@ -840,3 +840,6 @@ class TableLayout : WidgetGroupDefaultDrawing {
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
import dlangui.widgets.metadata;
|
||||
mixin(registerWidgets!(VerticalLayout, HorizontalLayout, TableLayout, FrameLayout)());
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
module dlangui.widgets.metadata;
|
||||
|
||||
import dlangui.widgets.widget;
|
||||
|
||||
interface WidgetMetadataDef {
|
||||
Widget create();
|
||||
}
|
||||
|
||||
private __gshared WidgetMetadataDef[string] _registeredWidgets;
|
||||
|
||||
WidgetMetadataDef findWidgetMetadata(string name) {
|
||||
if (auto p = name in _registeredWidgets)
|
||||
return *p;
|
||||
return null;
|
||||
}
|
||||
|
||||
void registerWidgetMetadata(string name, WidgetMetadataDef metadata) {
|
||||
_registeredWidgets[name] = metadata;
|
||||
}
|
||||
|
||||
string generateMetadataClass(alias t)() {
|
||||
import std.traits;
|
||||
immutable string metadataClassName = t.stringof ~ "Metadata";
|
||||
return "class " ~ metadataClassName ~ " : WidgetMetadataDef { \n" ~
|
||||
" override Widget create() {\n" ~
|
||||
" return new " ~ moduleName!t ~ "." ~ t.stringof ~ "();\n" ~
|
||||
" }\n" ~
|
||||
"}\n";
|
||||
}
|
||||
|
||||
string generateRegisterMetadataClass(alias t)() {
|
||||
immutable string metadataClassName = t.stringof ~ "Metadata";
|
||||
return "registerWidgetMetadata(\"" ~ t.stringof ~ "\", new " ~ metadataClassName ~ "());\n";
|
||||
}
|
||||
|
||||
string registerWidgets(T...)() {
|
||||
string classDefs;
|
||||
string registerDefs;
|
||||
foreach(t; T) {
|
||||
//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;
|
||||
//registerWidgetMetadata(T.stringof, new Metadata());
|
||||
}
|
||||
return classDefs ~ "\n__gshared static this() {\n" ~ registerDefs ~ "}";
|
||||
}
|
|
@ -1439,6 +1439,73 @@ class Widget {
|
|||
// override
|
||||
}
|
||||
|
||||
/// set string property value, for ML loaders
|
||||
bool setProperty(string name, string value) {
|
||||
if (name.equal("text")) {
|
||||
text = UIString(value);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// set string property value, for ML loaders
|
||||
bool setProperty(string name, UIString value) {
|
||||
if (name.equal("text")) {
|
||||
text = value;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// set int property value, for ML loaders
|
||||
bool setProperty(string name, int value) {
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/** Widget list holder. */
|
||||
|
@ -1596,28 +1663,4 @@ mixin template ActionTooltipSupport() {
|
|||
}
|
||||
}
|
||||
|
||||
alias WidgetFactory = Widget function();
|
||||
|
||||
private __gshared WidgetFactory[string] _widgetFactories;
|
||||
|
||||
WidgetFactory getWidgetFactory(string name) {
|
||||
return _widgetFactories[name];
|
||||
}
|
||||
|
||||
void registerWidgetFactory(string name, WidgetFactory factory) {
|
||||
_widgetFactories[name] = factory;
|
||||
}
|
||||
|
||||
void registerWidgetFactories(T...)() {
|
||||
foreach(t; T) {
|
||||
//pragma(msg, t.stringof);
|
||||
immutable string code = "WidgetFactory f = function() { return new " ~ t.stringof ~ "(); };";
|
||||
//pragma(msg, code);
|
||||
mixin(code);
|
||||
registerWidgetFactory(T.stringof, f);
|
||||
}
|
||||
}
|
||||
|
||||
__gshared static this() {
|
||||
registerWidgetFactories!Widget;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue