2 * coded by Ketmar // Invisible Vector <ketmar@ketmar.no-ip.org>
3 * Understanding is not required. Only obedience.
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, version 3 of the License ONLY.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 module test /*is aliced*/;
19 import arsd
.simpledisplay
;
31 // ////////////////////////////////////////////////////////////////////////// //
32 static immutable string TestStyle
= `
34 grouplist-divline: white;
37 threadlist-divline: white;
38 threadlist-back: #222;
53 // ////////////////////////////////////////////////////////////////////////// //
54 //__gshared int lastWinWidth, lastWinHeight;
57 // ////////////////////////////////////////////////////////////////////////// //
58 public class TitlerWindow
: SubWindow
{
60 LineEditWidget edtTitle
;
61 LineEditWidget fromName
;
62 LineEditWidget fromMail
;
70 bool delegate (dynstring name
, dynstring mail
, dynstring folder
, dynstring title
) onSelected
;
72 override void createWidgets () {
76 fromName
= new LineEditWidget("Name:");
80 fromMail
= new LineEditWidget("Mail:");
84 edtTitle
= new LineEditWidget("Title:");
87 (new HBoxWidget
).enter{
88 with (new HotLabelWidget("&Name:", LabelWidget
.HAlign
.Right
)) { width
= width
+2; hsizeId
= "editors"; }
90 fromName
= new LineEditWidget();
95 (new HBoxWidget
).enter{
96 with (new HotLabelWidget("&Mail:", LabelWidget
.HAlign
.Right
)) { width
= width
+2; hsizeId
= "editors"; }
98 fromMail
= new LineEditWidget();
103 (new HBoxWidget
).enter{
104 with (new HotLabelWidget("&Title:", LabelWidget
.HAlign
.Right
)) { width
= width
+2; hsizeId
= "editors"; }
106 edtTitle
= new LineEditWidget();
112 (new HBoxWidget
).enter{
115 with (new ButtonWidget(" O&k ")) {
116 hsizeId
= "okcancel";
117 deftype
= Default
.Accept
;
118 onAction
= delegate (self
) {
119 if (onSelected
!is null) {
120 if (!onSelected(fromName
.str, fromMail
.str, folder
, edtTitle
.str)) return;
126 with (new ButtonWidget(" Cancel ")) {
127 hsizeId
= "okcancel";
128 deftype
= Default
.Cancel
;
129 onAction
= delegate (self
) {
134 with (new ButtonWidget(" ... ")) {
135 hsizeId
= "okcancel";
146 edtTitle
.str = title
;
154 this (const(char)[] aname
, const(char)[] amail
, const(char)[] afolder
, const(char)[] atitle
) {
155 dynstring caption
= "Title for "~aname
~" <"~amail
~">";
165 // ////////////////////////////////////////////////////////////////////////// //
166 public class TagOptionsWindow
: SubWindow
{
169 void delegate (const(char)[] tagname
) onUpdated
;
171 this (const(char)[] atagname
) {
173 dynstring caption
= "options for '"~atagname
~"'";
177 override void createWidgets () {
178 LabelWidget optPath
= new LabelWidget("", LabelWidget
.HAlign
.Center
);
181 LineEditWidget optMonthes
;
182 (new HBoxWidget
).enter{
183 with (new HotLabelWidget("&Monthes:", LabelWidget
.HAlign
.Right
)) { width
= width
+2; /*hsizeId = "editors";*/ }
185 optMonthes
= new LineEditWidget();
186 //optMonthes.flex = 1;
187 optMonthes
.width
= gxTextWidthUtf("96669");
188 conwriteln("ISMYSEL: ", optMonthes
.isMySelector(" Widget#. "));
189 conwriteln("ISMYSEL: ", optMonthes
.isMySelector(" HBoxWidget LineEditWidget#. "));
190 conwriteln("ISMYSEL: ", optMonthes
.isMySelector(" HBoxWidget> #. "));
191 conwriteln("ISMYSEL: ", optMonthes
.isMySelector(" SubWindow HBoxWidget LineEditWidget#. "));
192 //new SpringWidget(1);
195 CheckboxWidget optThreaded
= new CheckboxWidget("&Threaded");
196 optThreaded
.flex
= 1;
198 CheckboxWidget optAttaches
= new CheckboxWidget("&Attaches");
199 optAttaches
.flex
= 1;
201 with (new RadioWidget("Radio &1")) {
207 with (new RadioWidget("Radio &2")) {
215 (new HBoxWidget
).enter{
218 with (new ButtonWidget(" O&k ")) {
219 hsizeId
= "okcancel";
220 deftype
= Default
.Accept
;
221 onAction
= delegate (self
) {
222 if (onUpdated
!is null) onUpdated(tagname
);
224 auto rw
= self
.getSelectedRadio("rg1");
225 if (rw
!is null) conwriteln("SELECTED RADIO: <", rw
.id
, ">");
229 with (new ButtonWidget(" Cancel ")) {
230 hsizeId
= "okcancel";
231 deftype
= Default
.Cancel
;
232 onAction
= delegate (self
) {
237 with (new ButtonWidget(" ... ")) {
238 hsizeId
= "okcancel";
240 onAction
= delegate (self
) {
241 (new SelectCompletionWindow("", buildAutoCompletion("/home/ketmar/"), aspath
:true)).onSelected
= (str) {
242 conwriteln("SELECTED: <", str.getData
, ">");
255 optPath
.text
= "booPath";
256 optMonthes
.str = "666";
258 optThreaded
.enabled
= false;
259 optAttaches
.enabled
= true;
261 optMonthes
.killTextOnChar
= true;
265 //add(); // for "focused"
267 forEachSelector("SubWindow > RootWidget CheckboxWidget", (EgraStyledClass w
) {
268 import iv
.vfs
.io
; writeln("LEW=", typeid(w
).name
, "; text=", (cast(CheckboxWidget
)w
).title
.getData
);
272 forEachSelector("SubWindow > RootWidget :focused", (EgraStyledClass w
) {
273 import iv
.vfs
.io
; writeln("FOCUSED=", typeid(w
).name
);
277 foreach (HotLabelWidget c
; querySelectorAll
!HotLabelWidget("SubWindow > RootWidget HotLabelWidget")) {
279 writeln("LBL: <", c
.text
.getData
, ">");
283 Widget qf
= querySelector(":focused");
284 if (qf
!is null) writeln("QFOCUSED=", typeid(qf
).name
); else writeln("FUCK!");
289 // ////////////////////////////////////////////////////////////////////////// //
290 void initConsole () {
291 // //////////////////////////////////////////////////////////////////// //
293 import core
.memory
: GC
;
294 conwriteln("starting GC collection...");
297 conwriteln("GC collection complete.");
298 })("gc_collect", "force GC collection cycle");
301 // //////////////////////////////////////////////////////////////////// //
303 auto qww
= new YesNoWindow("Quit?", "Do you really want to quit?", true);
304 qww
.onYes
= () { concmd("quit"); };
306 })("quit_prompt", "quit with prompt");
309 new TitlerWindow("name", "mail", "folder", "title");
310 })("window_titler", "titler window test");
313 new TagOptionsWindow("xtag");
314 })("window_tagoptions", "tag options window test");
318 // ////////////////////////////////////////////////////////////////////////// //
319 __gshared MainPaneWindow mainPane
;
322 final class MainPaneWindow
: SubWindow
{
323 ProgressBarWidget pbar
;
325 AGGTesselation deftess
;
327 int lastMX
= -10000, lastMY
= -10000;
330 super(null, GxPoint(0, 0), GxSize(screenWidth
, screenHeight
));
331 mType
= Type
.OnBottom
;
333 pbar
= new ProgressBarWidget(rootWidget
, "progress bar");
334 pbar
.setMinMax(0, 100);
335 pbar
.width
= clientWidth
-64;
337 pbar
.posy
= clientHeight
-pbar
.height
-8;
338 pbar
.posx
= (clientWidth
-pbar
.width
)/2;
340 deftess
= gxagg
.tesselator
;
345 // //////////////////////////////////////////////////////////////////// //
346 override void onPaint () {
349 enum guiGroupListWidth
= 128;
350 enum guiThreadListHeight
= 520;
352 gxFillRect(0, 0, guiGroupListWidth
, screenHeight
, getColor("grouplist-back"));
353 gxVLine(guiGroupListWidth
, 0, screenHeight
, getColor("grouplist-divline"));
355 gxFillRect(guiGroupListWidth
+1, 0, screenWidth
, guiThreadListHeight
, getColor("threadlist-back"));
356 gxHLine(guiGroupListWidth
+1, guiThreadListHeight
, screenWidth
, getColor("threadlist-divline"));
359 import core
.stdc
.math
: roundf
;
362 if (tessType
> AGGTesselation
.max
) tessType
= AGGTesselation
.max
;
363 gxagg
.tesselator
= cast(AGGTesselation
)tessType
;
365 gxagg
.tesselator
= deftess
;
369 gxagg
.params
.width
= 1.4f;
370 //gxagg.width = 1.0f;
372 float baphx
= roundf((screenWidth
-gxagg
.BaphometDims
)*0.5f)+0.5f;
373 float baphy
= roundf((screenHeight
-gxagg
.BaphometDims
)*0.5f)+0.5f;
381 foreach (; 0..1000) {
383 immutable tstt
= clockMicro();
384 gxagg
.renderBaphomet(baphx
, baphy
);
385 estt
+= (clockMicro()-tstt
);
389 gxagg
.renderBaphomet(baphx
, baphy
);
391 immutable tstt
= clockMicro();
392 gxagg
.renderBaphomet(baphx
, baphy
);
393 estt
= clockMicro()-tstt
;
398 .moveTo(baphx
-1, baphy
-1)
399 .lineTo(baphx
+gxagg
.BaphometDims
, baphy
-1)
400 .lineTo(baphx
+gxagg
.BaphometDims
, baphy
+gxagg
.BaphometDims
)
401 .lineTo(baphx
-1, baphy
+gxagg
.BaphometDims
)
402 .lineTo(baphx
-1, baphy
-1);
405 gxagg
.roundedRect(baphx
-1, baphy
-1, gxagg
.BaphometDims
+1, gxagg
.BaphometDims
+1, 16.0f);
420 hit
= gxagg
.hitTest(lastMX
, lastMY
);
421 gxagg
.endFrame(gxrgba(255, 0, 0, (tessType
>= 0 ?
255 : 66)));
424 import std
.format
: format
;
425 string s
= "tess: %s level: %d; mcsecs: %s".format(gxagg
.tesselator
, gxagg
.bezierLimit
, estt
);
426 gxDrawTextUtf(200, 20, s
, GxColors
.k8orange
);
428 s
= "hit: %3s".format(hit
);
429 gxDrawTextUtf(200, 40, s
, GxColors
.k8orange
);
439 .rotate(deg2rad(35.0f))
441 assert(!tmt
.isIdentity
);
445 .translate(0.5f, 0.5f)
448 gxagg
.withTransform(tmt
, {
449 gxagg
.moveTo(50, 50);
450 gxagg
.lineTo(60, 60);
451 gxagg
.moveTo(100, 100);
452 gxagg
.lineTo(140, 120);
454 // CW (because logical coords are upwards)
455 gxagg
.moveTo(200, 200);
456 gxagg
.lineTo(200, 100);
457 gxagg
.lineTo(100, 100);
458 gxagg
.lineTo(100, 200);
459 gxagg
.lineTo(200, 200);
461 // CCW (because logical coords are upwards)
462 gxagg
.moveTo(100, 100);
463 gxagg
.lineTo(200, 100);
464 gxagg
.lineTo(200, 200);
465 gxagg
.lineTo(100, 200);
468 //gxagg.flipOrientation = true;
469 //gxagg.dumpVertices();
474 gxagg
.render(gxrgba(0, 127, 0, 127));
477 //gxagg.dumpVertices();
479 gxagg
.render(gxrgba(127, 0, 0, 255));
487 //gxagg.dashContour();
488 gxagg
.render(gxrgba(255, 255, 0, 255));
492 gxagg
.paramsContour
.width
= 6;
494 gxagg
.render(gxrgba(255, 255, 255, 255));
498 gxagg
.flipOrientation
= true;
500 gxagg
.render(gxrgba(0, 255, 0, 255));
501 gxagg
.flipOrientation
= false;
504 //gxagg.render(gxrgba(0, 127, 0, 127));
509 .roundedRect(400.5f, 600.5f, 96, 28, 8)
511 //.render(gxRGB!(192, 192, 192));
512 .renderVGradient(gxRGB
!(127, 127, 127), gxRGB
!(142, 142, 142), 0.2f, gxRGB
!(196, 196, 196));
518 if (gxFontCharPathBounds(dch
, bounds
[])) {
519 conwriteln("bounds: (", bounds
[0], ",", bounds
[1], ")-(", bounds
[2], ",", bounds
[3], ")");
521 immutable float gwdt
= bounds
[2]-bounds
[0];
522 immutable float ghgt
= bounds
[3]-bounds
[1];
523 float scale
= desthgt
/ghgt
;
527 .translate(-bounds
[0]*scale
+100.5f, -bounds
[1]*scale
+100.5f);
528 gxagg
.withTransform(tmx
, {
532 if (gxFontCharToPath(dch
)) {
536 //.render(GxColors.k8orange);
537 .renderVGradient(gxRGB
!(200, 73, 0), gxRGB
!(255, 128, 0));
539 int emb
= cast(int)(4/scale
);
543 if (gxFontCharPathEmboldenBounds(dch
, emb
, ebounds
[])) {
544 immutable float ewdt
= ebounds
[2]-ebounds
[0];
545 immutable float ehgt
= ebounds
[3]-ebounds
[1];
546 gxagg
.transform
.translate(-(ewdt
-gwdt
)*0.5f*scale
, (ehgt
-ghgt
)*0.5f*scale
);
547 if (gxFontCharToPathEmbolden(dch
, emb
)) {
550 .render(GxColors
.green
);
560 version(test_round_rect
) {
562 gxFillRoundedRect(lastMouseX
-16, lastMouseY
-16, 128, 96, rrad
, /*gxSolidWhite*/gxRGBA
!(0, 255, 0, 127));
563 //gxDrawRoundedRect(lastMouseX-16, lastMouseY-16, 128, 96, rrad, gxRGBA!(0, 255, 0, 127));
569 version(test_round_rect
) {
573 override bool onKeyBubble (KeyEvent event
) {
575 version(test_round_rect
) {
576 if (event
== "Plus") { ++rrad
; return true; }
577 if (event
== "Minus") { --rrad
; return true; }
579 if (event
== "C-Q") { concmd("quit_prompt"); return true; }
580 if (event
== "1") { concmd("window_titler"); return true; }
581 if (event
== "2") { concmd("window_tagoptions"); return true; }
582 if (event
== "Minus") { pbar
.current
= pbar
.current
-1; return true; }
583 if (event
== "Plus") { pbar
.current
= pbar
.current
+1; return true; }
585 if (event
== "Q") { if (gxagg
.bezierLimit
> 1) { --gxagg
.bezierLimit
; widgetChanged(); } return true; }
586 if (event
== "W") { if (gxagg
.bezierLimit
< 1000) { ++gxagg
.bezierLimit
; widgetChanged(); } return true; }
588 if (event
== "Z") { --tessType
; if (tessType
< -1) tessType
= -1; widgetChanged(); return true; }
589 if (event
== "X") { ++tessType
; widgetChanged(); return true; }
591 if (event
== "T") { timetest
= true; widgetChanged(); return true; }
592 //if (dbg_dump_keynames) conwriteln("key: ", event.toStr, ": ", event.modifierState&ModifierState.windows);
593 //foreach (const ref kv; mainAppKeyBindings.byKeyValue) if (event == kv.key) concmd(kv.value);
598 // returning `false` to avoid screen rebuilding by dispatcher
599 override bool onMouseBubble (MouseEvent event
) {
600 if (event
.type
== MouseEventType
.buttonPressed || event
.type
== MouseEventType
.buttonReleased
) {
601 if (lastMX
!= event
.x || lastMY
!= event
.y
) {
607 } else if (event
.modifierState
) {
608 // for OpenGL, this rebuilds the whole screen anyway
618 // ////////////////////////////////////////////////////////////////////////// //
619 void main (string
[] args
) {
620 defaultColorStyle
.parseStyle(TestStyle
);
621 //egraDefaultFontSize = 48;
623 glconAllowOpenGLRender
= false;
625 sdpyWindowClass
= "EGRATest";
626 //glconShowKey = "M-Grave";
631 conProcessArgs
!true(args
);
633 egraCreateSystemWindow("EGRA Test", allowResize
:false);
635 vbwin
.addEventListener((QuitEvent evt
) {
636 if (vbwin
.closed
) return;
637 if (isQuitRequested
) { vbwin
.close(); return; }
641 static if (is(typeof(&vbwin
.closeQuery
))) {
642 vbwin
.closeQuery
= delegate () { concmd("quit"); egraPostDoConCommands(); };
645 mainPane
= new MainPaneWindow();
646 //egraSkipScreenClear = true; // main pane is fullscreen
651 vbwin
.eventLoop(1000*10,
653 egraProcessConsole();
655 delegate (KeyEvent event
) {
656 if (egraOnKey(event
)) return;
658 delegate (MouseEvent event
) {
659 if (egraOnMouse(event
)) return;
661 delegate (dchar ch
) {
662 if (egraOnChar(ch
)) return;
667 conProcessQueue(int.max
/4);