mirror of https://github.com/buggins/dlangui.git
Added basic property metadata generation, and extended dmledit example to demonstrate it.
This commit is contained in:
parent
075708fae3
commit
c99b3976f2
|
@ -4,6 +4,7 @@ import dlangui;
|
|||
import dlangui.dialogs.filedlg;
|
||||
import dlangui.dialogs.dialog;
|
||||
import dlangui.dml.dmlhighlight;
|
||||
import dlangui.widgets.metadata;
|
||||
import std.array : replaceFirst;
|
||||
|
||||
mixin APP_ENTRY_POINT;
|
||||
|
@ -91,6 +92,8 @@ q{VerticalLayout {
|
|||
}
|
||||
};
|
||||
|
||||
// used to generate property lists once, then simply swap
|
||||
StringListAdapter[string] propListsAdapters;
|
||||
|
||||
class EditFrame : AppFrame {
|
||||
|
||||
|
@ -181,15 +184,15 @@ class EditFrame : AppFrame {
|
|||
window.close();
|
||||
return true;
|
||||
case IDEActions.HelpAbout:
|
||||
window.showMessageBox(UIString("About DlangUI ML Editor"d),
|
||||
UIString("DLangIDE\n(C) Vadim Lopatin, 2015\nhttp://github.com/buggins/dlangui\nSimple editor for DML code"d));
|
||||
window.showMessageBox(UIString.fromRaw("About DlangUI ML Editor"d),
|
||||
UIString.fromRaw("DLangIDE\n(C) Vadim Lopatin, 2015\nhttp://github.com/buggins/dlangui\nSimple editor for DML code"d));
|
||||
return true;
|
||||
case IDEActions.FileNew:
|
||||
UIString caption;
|
||||
caption = "Create new DML file"d;
|
||||
FileDialog dlg = createFileDialog(caption, false);
|
||||
dlg.addFilter(FileFilterEntry(UIString("DML files"d), "*.dml"));
|
||||
dlg.addFilter(FileFilterEntry(UIString("All files"d), "*.*"));
|
||||
dlg.addFilter(FileFilterEntry(UIString.fromRaw("DML files"d), "*.dml"));
|
||||
dlg.addFilter(FileFilterEntry(UIString.fromRaw("All files"d), "*.*"));
|
||||
dlg.dialogResult = delegate(Dialog dlg, const Action result) {
|
||||
if (result.id == ACTION_OPEN.id) {
|
||||
string filename = result.stringParam;
|
||||
|
@ -207,8 +210,8 @@ class EditFrame : AppFrame {
|
|||
UIString caption;
|
||||
caption = "Save DML File as"d;
|
||||
FileDialog dlg = createFileDialog(caption, false);
|
||||
dlg.addFilter(FileFilterEntry(UIString("DML files"d), "*.dml"));
|
||||
dlg.addFilter(FileFilterEntry(UIString("All files"d), "*.*"));
|
||||
dlg.addFilter(FileFilterEntry(UIString.fromRaw("DML files"d), "*.dml"));
|
||||
dlg.addFilter(FileFilterEntry(UIString.fromRaw("All files"d), "*.*"));
|
||||
dlg.dialogResult = delegate(Dialog dlg, const Action result) {
|
||||
if (result.id == ACTION_OPEN.id) {
|
||||
string filename = result.stringParam;
|
||||
|
@ -221,8 +224,8 @@ class EditFrame : AppFrame {
|
|||
UIString caption;
|
||||
caption = "Open DML File"d;
|
||||
FileDialog dlg = createFileDialog(caption);
|
||||
dlg.addFilter(FileFilterEntry(UIString("DML files"d), "*.dml"));
|
||||
dlg.addFilter(FileFilterEntry(UIString("All files"d), "*.*"));
|
||||
dlg.addFilter(FileFilterEntry(UIString.fromRaw("DML files"d), "*.dml"));
|
||||
dlg.addFilter(FileFilterEntry(UIString.fromRaw("All files"d), "*.*"));
|
||||
dlg.dialogResult = delegate(Dialog dlg, const Action result) {
|
||||
if (result.id == ACTION_OPEN.id) {
|
||||
string filename = result.stringParam;
|
||||
|
@ -302,6 +305,29 @@ class EditFrame : AppFrame {
|
|||
HorizontalLayout hlayout = new HorizontalLayout();
|
||||
hlayout.layoutWidth = FILL_PARENT;
|
||||
hlayout.layoutHeight = FILL_PARENT;
|
||||
WidgetsList widgetsList = new WidgetsList();
|
||||
StringListWidget propList = new StringListWidget();
|
||||
auto sla = new StringListAdapter();
|
||||
foreach(const ref widget; getRegisteredWidgetsList())
|
||||
{
|
||||
auto propertyListAdapter = new StringListAdapter();
|
||||
if ( auto meta = findWidgetMetadata(widget) )
|
||||
{
|
||||
foreach(prop; meta.properties)
|
||||
{
|
||||
propertyListAdapter.add(UIString.fromRaw(prop.name ~ " [" ~ to!string(prop.type) ~ "]" ));
|
||||
propListsAdapters[widget] = propertyListAdapter;
|
||||
}
|
||||
}
|
||||
sla.add(UIString.fromRaw(widget));
|
||||
}
|
||||
widgetsList.adapter = sla;
|
||||
auto leftPanel = new VerticalLayout();
|
||||
leftPanel.addChild(new TextWidget().text("Widgets").backgroundColor(0x7F7F7F) );
|
||||
leftPanel.addChild(widgetsList);
|
||||
leftPanel.addChild(new TextWidget().text("Widget properties").backgroundColor(0x7F7F7F));
|
||||
leftPanel.addChild(propList);
|
||||
hlayout.addChild(leftPanel);
|
||||
_editor = new DMLSourceEdit();
|
||||
hlayout.addChild(_editor);
|
||||
_editor.text = SAMPLE_SOURCE_CODE;
|
||||
|
@ -327,6 +353,17 @@ class EditFrame : AppFrame {
|
|||
updatePreview();
|
||||
return true;
|
||||
};
|
||||
widgetsList.itemClick = delegate (Widget source, int itemIndex){
|
||||
propList.adapter = propListsAdapters[to!string(widgetsList.selectedItem)];
|
||||
return true;
|
||||
};
|
||||
widgetsList.onItemDoubleClick = delegate (Widget source, int itemIndex) {
|
||||
auto caret = _editor.caretPos;
|
||||
auto widgetClassName = widgetsList.selectedItem;
|
||||
EditOperation op = new EditOperation(EditAction.Replace, caret, widgetClassName);
|
||||
_editor.content.performOperation(op, this);
|
||||
};
|
||||
|
||||
previewControls.addChild(cbFillHorizontal);
|
||||
previewControls.addChild(cbFillVertical);
|
||||
previewControls.addChild(cbHighlightBackground);
|
||||
|
@ -344,6 +381,22 @@ class EditFrame : AppFrame {
|
|||
|
||||
}
|
||||
|
||||
alias onItemDoubleClickHandler = void delegate (Widget source, int itemIndex);
|
||||
|
||||
class WidgetsList : StringListWidget
|
||||
{
|
||||
onItemDoubleClickHandler onItemDoubleClick;
|
||||
|
||||
override bool onMouseEvent(MouseEvent event) {
|
||||
bool result = super.onMouseEvent(event);
|
||||
if (event.doubleClick) {
|
||||
if (onItemDoubleClick !is null)
|
||||
onItemDoubleClick(this, selectedItemIndex);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/// entry point for dlangui based application
|
||||
extern (C) int UIAppMain(string[] args) {
|
||||
|
||||
|
|
|
@ -10,6 +10,8 @@ interface WidgetMetadataDef {
|
|||
string moduleName();
|
||||
/// full class name, e.g. "dlangui.widgets.editors.EditLine"
|
||||
string fullName();
|
||||
/// property list, e.g. "backgroundColor"
|
||||
WidgetPropertyMetadata[] properties();
|
||||
}
|
||||
|
||||
struct WidgetSignalMetadata {
|
||||
|
@ -20,8 +22,22 @@ struct WidgetSignalMetadata {
|
|||
TypeInfo paramsType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores information about property
|
||||
*
|
||||
*/
|
||||
struct WidgetPropertyMetadata {
|
||||
TypeInfo type;
|
||||
string name;
|
||||
}
|
||||
|
||||
private __gshared WidgetMetadataDef[string] _registeredWidgets;
|
||||
|
||||
string[] getRegisteredWidgetsList()
|
||||
{
|
||||
return _registeredWidgets.keys;
|
||||
}
|
||||
|
||||
WidgetMetadataDef findWidgetMetadata(string name) {
|
||||
if (auto p = name in _registeredWidgets)
|
||||
return *p;
|
||||
|
@ -51,10 +67,60 @@ WidgetSignalMetadata[] getSignalList(alias T)() {
|
|||
return res;
|
||||
}
|
||||
|
||||
template isMarkupType(T)
|
||||
{
|
||||
enum isMarkupType = is(T==int) ||
|
||||
is(T==float) ||
|
||||
is(T==double) ||
|
||||
is(T==bool) ||
|
||||
is(T==Rect) ||
|
||||
is(T==string) ||
|
||||
is(T==dstring) ||
|
||||
is(T==UIString) ||
|
||||
is(T==UIString[]) ||
|
||||
is(T==StringListValue[]);
|
||||
}
|
||||
|
||||
string generatePropertiesMetadata(alias T)() {
|
||||
import std.algorithm.searching;
|
||||
import std.traits;
|
||||
import std.meta;
|
||||
string str = "[";
|
||||
WidgetPropertyMetadata[] res;
|
||||
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
|
||||
static if ([__traits(getFunctionAttributes, __traits(getMember, T, m))[]].canFind("@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 ~ " ), ";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
str ~= "]";
|
||||
return str;
|
||||
}
|
||||
|
||||
string generateMetadataClass(alias t)() {
|
||||
//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" ~
|
||||
" override Widget create() {\n" ~
|
||||
|
@ -69,6 +135,9 @@ string generateMetadataClass(alias t)() {
|
|||
" override string fullName() {\n" ~
|
||||
" return \"" ~ moduleName!t ~ "." ~ t.stringof ~ "\";\n" ~
|
||||
" }\n" ~
|
||||
" override WidgetPropertyMetadata[] properties() {" ~
|
||||
" return " ~ generatePropertiesMetadata!t ~ ";\n" ~
|
||||
" }\n" ~
|
||||
"}\n";
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue