fixed "article_mark_spam"
[chiroptera.git] / egui / dialogs.d
blob849c8ad677a60a75a337326f263a37912631339f
1 /* E-Mail Client
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 egui.dialogs /*is aliced*/;
18 private:
20 import core.time;
22 import arsd.simpledisplay;
24 import iv.alice;
25 import iv.cmdcon;
26 import iv.strex;
27 import iv.utfutil;
28 import iv.vfs;
30 import egfx;
31 import egui.subwindows;
32 import egui.widgets;
35 // ////////////////////////////////////////////////////////////////////////// //
36 public string[] buildAutoCompletion (ConString prefix) {
37 import std.file : DirEntry, SpanMode, dirEntries;
39 if (prefix.length == 0) return null;
41 ConString path, namepfx;
43 if (prefix[$-1] == '/') {
44 path = prefix;
45 namepfx = null;
46 } else {
47 auto lspos = prefix.lastIndexOf('/');
48 if (lspos < 0) {
49 path = null;
50 namepfx = prefix;
51 } else {
52 path = prefix[0..lspos+1];
53 namepfx = prefix[lspos+1..$];
57 //conwriteln("path=[", path, "]; namepfx=[", namepfx, "]");
59 string[] res;
60 foreach (DirEntry de; dirEntries(path.idup, SpanMode.shallow)) {
61 if (namepfx.length != 0) {
62 import std.path : baseName;
63 //conwriteln(" [", de.baseName, "]");
64 if (!de.baseName.startsWith(namepfx)) continue;
66 try {
67 if (de.isDir) res ~= de.name~"/"; else res ~= de.name;
68 } catch (Exception e) {}
71 if (res.length > 1) {
72 import std.algorithm : sort;
73 sort(res);
76 return res;
80 // ////////////////////////////////////////////////////////////////////////// //
81 public class SelectCompletionWindow : SubWindow {
82 SimpleListBoxWidget lb;
83 string[] list;
85 void delegate (string str) onSelected;
87 this (const(char)[] prefix, string[] clist, bool aspath) {
88 int xhgt = 0;
89 int xwdt = 0;
90 bool idxset = false;
91 lb = new SimpleListBoxWidget(this);
92 foreach (string s; clist) {
93 if (aspath && s.length) {
94 usize lspos = s.length;
95 if (s[$-1] == '/') --lspos;
96 while (lspos > 0 && s.ptr[lspos-1] != '/') --lspos;
97 s = s[lspos..$];
99 lb.appendItem(s);
100 if (s == prefix) { idxset = true; lb.curidx = lb.length-1; }
101 if (!idxset && s.startsWith(prefix)) { idxset = true; lb.curidx = lb.length-1; }
102 int w = gxTextWidthUtf(s)+2;
103 if (xwdt < w) xwdt = w;
104 xhgt += gxTextHeightUtf;
107 if (xhgt == 0) { super(); return; }
108 if (xhgt > VBufHeight) xhgt = VBufHeight-decorationSizeY;
110 if (xwdt > VBufWidth-decorationSizeX) xwdt = VBufWidth-decorationSizeX;
112 super("Select Completion", xwdt+decorationSizeX, xhgt+decorationSizeY);
113 lb.ww = clientWidth;
114 lb.wh = clientHeight;
115 list = clist;
117 lb.onAction = delegate (self) {
118 if (onSelected !is null && lb.curidx >= 0 && lb.curidx < list.length) {
119 close();
120 onSelected(list[lb.curidx]);
121 return;
123 vbwin.beep();
126 addModal();
129 override bool onKey (KeyEvent event) {
130 if (event.pressed) {
131 if (event == "Escape" || event == "C-Q") { close(); return true; }
132 if (event == "Enter") { lb.onAction(lb); return true; }
134 return super.onKey(event);
139 // ////////////////////////////////////////////////////////////////////////// //
140 public class YesNoWindow : SubWindow {
141 ButtonWidget yes, no;
142 CenteredLabelWidget message;
144 void delegate () onYes;
145 void delegate () onNo;
147 this (string atitle, string amessage, bool defaction=true) {
148 import std.algorithm : max;
150 clrWinFrame = gxRGB!(0x40, 0x70, 0xcf);
151 clrWinTitleBack = gxRGB!(0x73, 0x96, 0xdc);
152 clrWinTitle = gxRGB!(0xff, 0xff, 0xff);
153 clrWinBack = gxRGB!(0xbf, 0xcf, 0xef);
154 clrWinText = gxRGB!(0x16, 0x2d, 0x59);
156 int xwdt = gxTextWidthUtf(amessage)+6;
157 int xhgt = gxTextHeightUtf+4;
159 message = new CenteredLabelWidget(this, amessage);
161 yes = new ButtonExWidget(this, "&Yes", "M-Y");
162 no = new ButtonExWidget(this, "&No", "M-N");
163 yes.width = max(yes.width, no.width);
164 no.width = max(yes.width, no.width);
166 int bwdt = yes.width+6+no.width;
167 int bhgt = yes.height;
169 if (xwdt < bwdt) xwdt = bwdt;
170 xhgt += bhgt+4;
172 super(atitle, xwdt+decorationSizeX, xhgt+decorationSizeY);
174 message.wx = 0;
175 message.wy = 2;
176 message.ww = clientWidth;
178 yes.wy = message.wy+message.wh+4;
179 no.wy = yes.wy;
181 yes.wx = (clientWidth-bwdt)/2;
182 no.wx = yes.wx+yes.ww+1+3;
184 if (defaction) activeWidget = yes; else activeWidget = no;
186 yes.onAction = delegate (self) {
187 close();
188 if (onYes !is null) onYes();
191 no.onAction = delegate (self) {
192 close();
193 if (onNo !is null) onNo();
196 addModal();
199 override bool onKey (KeyEvent event) {
200 if (event.pressed) {
201 if (event == "Escape" || event == "C-Q") { no.onAction(no); return true; }
203 return super.onKey(event);