From f5680f9fa6b48b2ffae0d16a123a3bd987cefab2 Mon Sep 17 00:00:00 2001 From: ketmar Date: Fri, 26 Nov 2021 07:43:06 +0000 Subject: [PATCH] egra: better selectors (they can be customised with return type now, and has proper default return types) FossilOrigin-Name: b190acc22820376806e7daf866669ae16c7f1aeadd3cefbe277c7ddd1bff89be --- egra/gui/dialogs.d | 14 ++++++++++---- egra/gui/style.d | 22 +++++++++++++--------- egra/gui/subwindows.d | 3 +++ egra/gui/widgets.d | 3 +++ egra/test.d | 6 +++--- 5 files changed, 32 insertions(+), 16 deletions(-) diff --git a/egra/gui/dialogs.d b/egra/gui/dialogs.d index f8b042f..fe27f9e 100644 --- a/egra/gui/dialogs.d +++ b/egra/gui/dialogs.d @@ -83,7 +83,6 @@ public dynstring[] buildAutoCompletion (ConString prefix) { // ////////////////////////////////////////////////////////////////////////// // public class SelectCompletionWindow : SubWindow { - SimpleListBoxWidget lb; dynstring[] list; void delegate (dynstring str) onSelected; @@ -93,7 +92,9 @@ public class SelectCompletionWindow : SubWindow { int xhgt = 0; int xwdt = 0; bool idxset = false; - lb = new SimpleListBoxWidget(rootWidget); + + SimpleListBoxWidget lb = new SimpleListBoxWidget(rootWidget); + lb.id = "main-listbox"; foreach (dynstring s; clist) { if (aspath && s.length) { usize lspos = s.length; @@ -133,8 +134,13 @@ public class SelectCompletionWindow : SubWindow { override bool onKeyBubble (KeyEvent event) { if (event.pressed) { - if (event == "Escape" /*|| event == "C-Q"*/) { close(); return true; } - if (event == "Enter") { lb.onAction(lb); return true; } + if (event == "Escape") { close(); return true; } + if (event == "Enter") { + if (auto lb = querySelector!Widget("#main-listbox")) { + lb.doAction(); + return true; + } + } } return super.onKeyBubble(event); } diff --git a/egra/gui/style.d b/egra/gui/style.d index 68b2b7d..17707ed 100644 --- a/egra/gui/style.d +++ b/egra/gui/style.d @@ -1119,26 +1119,28 @@ public: } } - final EgraStyledClass querySelector (const(char)[] sel) { + final T querySelectorInternal(T:EgraStyledClass) (const(char)[] sel) { import std.traits; for (EgraStyledClass w = getFirstChild(); w !is null; w = w.getNextSibling()) { - if (EgraStyledClass res = w.querySelector(sel)) return res; + if (EgraStyledClass res = w.querySelector!T(sel)) return cast(T)res; } bool modhit; if (isMySelector(sel, &modhit)) { - if (modhit) return this; + if (modhit) return cast(T)this; } return null; } - static template isGoodIteratorDelegate(DG) { + final T querySelector(T:EgraStyledClass=EgraStyledClass) (const(char)[] sel) { pragma(inline, true); return querySelectorInternal!T(sel); } + + static template isGoodIteratorDelegate(DG, T) { import std.traits; enum isGoodIteratorDelegate = (is(ReturnType!DG == int)) && - is(typeof((inout int=0) { DG dg = void; EgraStyledClass w; int res = dg(w); })); + is(typeof((inout int=0) { DG dg = void; /*EgraStyledClass*/T w; int res = dg(w); })); } - static struct Iter { + static struct Iter(T) { EgraStyledClass c; dynstring sel; @@ -1148,18 +1150,20 @@ public: if (asel.length) { c = cc; sel = asel; } } - int opApply(DG) (scope DG dg) if (isGoodIteratorDelegate!DG) { + int opApply(DG) (scope DG dg) if (isGoodIteratorDelegate!(DG, T)) { int res = 0; if (c is null || dg is null) return 0; c.forEachSelector(sel.getData, (EgraStyledClass w) { - res = dg(w); + if (auto cw = cast(T)w) { + res = dg(cw); + } return (res != 0); }); return res; } } - final Iter querySelectorAll (const(char)[] sel) nothrow @safe @nogc { pragma(inline, true); return Iter(this, sel); } + final auto querySelectorAll(T:EgraStyledClass=EgraStyledClass) (const(char)[] sel) nothrow @safe @nogc { pragma(inline, true); return Iter!T(this, sel); } public: static string classShortName (in TypeInfo_Class ct) pure nothrow @trusted @nogc { diff --git a/egra/gui/subwindows.d b/egra/gui/subwindows.d index 68a894a..124635f 100644 --- a/egra/gui/subwindows.d +++ b/egra/gui/subwindows.d @@ -604,6 +604,9 @@ public: return false; } + final T querySelector(T:EgraStyledClass=Widget) (const(char)[] sel) { pragma(inline, true); return querySelectorInternal!T(sel); } + final auto querySelectorAll(T:EgraStyledClass=Widget) (const(char)[] sel) nothrow @safe @nogc { pragma(inline, true); return Iter!T(this, sel); } + protected: void createRoot () { if (mRoot is null) setRoot(new RootWidget(this)); else fixRoot(); diff --git a/egra/gui/widgets.d b/egra/gui/widgets.d index b1baeaa..e3f7f78 100644 --- a/egra/gui/widgets.d +++ b/egra/gui/widgets.d @@ -187,6 +187,9 @@ public: win.widgetChanged(); } + final T querySelector(T:EgraStyledClass=Widget) (const(char)[] sel) { pragma(inline, true); return querySelectorInternal!T(sel); } + final auto querySelectorAll(T:EgraStyledClass=Widget) (const(char)[] sel) nothrow @safe @nogc { pragma(inline, true); return Iter!T(this, sel); } + public: dynstring getHotkey () { return mHotkey; } void setHotkey (const(char)[] v) { mHotkey = v; } diff --git a/egra/test.d b/egra/test.d index 87630b1..0dd4b75 100644 --- a/egra/test.d +++ b/egra/test.d @@ -250,13 +250,13 @@ public class TagOptionsWindow : SubWindow { //return false; }); - foreach (EgraStyledClass c; querySelectorAll("SubWindow > RootWidget HotLabelWidget")) { + foreach (HotLabelWidget c; querySelectorAll!HotLabelWidget("SubWindow > RootWidget HotLabelWidget")) { import iv.vfs.io; - writeln("LBL: <", (cast(HotLabelWidget)c).text.getData, ">"); + writeln("LBL: <", c.text.getData, ">"); } { import iv.vfs.io; - auto qf = querySelector(":focused"); + Widget qf = querySelector(":focused"); if (qf !is null) writeln("QFOCUSED=", typeid(qf).name); else writeln("FUCK!"); } } -- 2.11.4.GIT