1 /* Invisible Vector Library
2 * simple FlexBox-based TUI engine
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, version 3 of the License ONLY.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 module iv
.egtui
.dialogs
/*is aliced*/;
25 import iv
.egtui
.parser
;
28 // ///////////////////////////////////////////////////////////////////////// //
29 void dialogMessage(string type
, A
...) (const(char)[] title
, const(char)[] fmt
, A args
) {
30 static assert(type
== "error" || type
== "info" || type
== "debug", "invalid message dialog type");
36 label
: { align: expand caption
: "$msg" }
42 button
: { id
: "btclose" caption
: "&Close" }
47 import std
.format
: format
;
48 string msg
= fmt
.format(args
);
50 auto ctx
= FuiContext
.create();
51 static if (type
== "error") {
52 ctx
.dialogPalette(TuiPaletteError
/*TuiPaletteNormal*/);
54 ctx
.parse
!(title
, msg
)(laydesc
);
60 // ///////////////////////////////////////////////////////////////////////// //
61 int dialogTanOna (const(char)[] title
, const(char)[] text
, bool def
) {
77 button
: { id
: "bttan" caption
: "&tan" }
78 //spacer: { width: 1 } // this hack just inserts space
79 button
: { id
: "btona" caption
: "o&na" }
84 auto ctx
= FuiContext
.create();
85 //ctx.maxDimensions = FuiSize(ttyw, ttyh);
86 ctx
.parse
!(title
, text
)(laydesc
);
88 ctx
.focused
= ctx
[def ?
"bttan" : "btona"];
89 auto res
= ctx
.modalDialog
;
90 if (res
>= 0) return (ctx
.itemId(res
) == "bttan" ?
1 : 0);
95 // ///////////////////////////////////////////////////////////////////////// //
96 // result.ptr is null: calcelled
97 string
dialogInputLine(string editorid
="") (const(char)[] msg
, const(char)[] def
=null, FuiHistoryManager dghisman
=null) {
98 static if (editorid
.length
> 0) string editid
= editorid
; else string editid
= "ed";
100 caption
: "Input query"
117 button
: { id
: "btok" caption
: " O&K " default }
118 button
: { id
: "btcancel" caption
: "&Cancel" }
123 auto ctx
= FuiContext
.create();
125 ctx
.parse
!(msg
, def
, editid
)(laydesc
);
126 static if (editorid
.length
> 0) {
127 if (dghisman
!is null) ctx
.dialogHistoryManager
= dghisman
;
130 if (ctx
.layprops(0).position
.w
< ttyw
/3*2) {
131 ctx
.layprops(0).minSize
.w
= ttyw
/3*2;
134 auto res
= ctx
.modalDialog
;
136 if (auto edl
= ctx
.firstItemOfType
!"editline") {
140 if (rng
.length
== 0) return ""; // so it won't be null
141 rs
.reserve(rng
.length
);
142 foreach (char ch
; rng
) rs
~= ch
;
143 static if (editorid
.length
> 0) {
144 if (auto hisman
= ctx
.dialogHistoryManager
) hisman
.add(editid
, rs
);
146 return cast(string
)rs
; // it is safe to cast it here
153 // ///////////////////////////////////////////////////////////////////////// //
154 void dialogTextView (const(char)[] title
, const(char)[] text
) {
168 flex
: 1 // eat all possible vertical space
176 button
: { id
: "btclose" caption
: "&Close" }
188 auto ctx
= FuiContext
.create();
189 ctx
.parse
!(title
, text
, mw
, mh
, winmw
, winmh
)(laydesc
);
191 int th
= ctx
.textviewHeight(ctx
["text"]);
193 // fix size and relayout
194 auto lpr
= ctx
.layprops(0);
195 lpr
.minSize
.h
= lpr
.maxSize
.h
= lpr
.position
.h
-(mh
-th
);
196 lpr
.position
.y
= 0; // make sure that `modalDialog()` will center it
203 // ///////////////////////////////////////////////////////////////////////// //
204 // return -1 on escape or index
205 int dialogHistory (FuiHistoryManager hisman
, const(char)[] hid
, int winx
, int winy
, int startidx
=-1) {
206 if (hisman
is null ||
!hisman
.has(hid
)) return -1;
208 int hcount
= hisman
.count(hid
);
209 if (hcount
< 1) return -1; // just in case
212 if (maxhgt
< 3) maxhgt
= 3;
215 if (maxwdt
< 3) maxwdt
= 3;
219 foreach (int idx
; 0..hcount
) {
220 auto s
= hisman
.item(hid
, idx
);
221 if (s
.length
> maxlen
) maxlen
= cast(int)s
.length
;
223 if (maxlen
> ttyw
-4) maxlen
= ttyw
-4;
226 if (pgsize
> maxhgt
-2) pgsize
= maxhgt
-2;
229 winx
= (ttyw
-(maxlen
+4))/2;
230 if (winx
< 0) winx
= 0;
233 winy
= (ttyh
-(pgsize
+2))/2;
234 if (winy
< 0) winy
= 0;
239 // no room to show it at the bottom?
240 if (y0
+pgsize
+1 > ttyh
) {
242 // no room to show it at the top? center it then
243 if (y0
< 0 || y0
>= ttyh
) y0
= (ttyh
-(pgsize
+2))/2;
245 if (x0
+maxlen
+4 > ttyw
) x0
= ttyw
-maxlen
-4;
249 int winhgt
= pgsize
+2;
250 int winwdt
= maxlen
+4;
252 if (winwdt
> maxwdt
) winwdt
= maxwdt
;
269 auto ctx
= FuiContext
.create();
270 ctx
.parse
!(winhgt
, winwdt
, maxwdt
, maxhgt
)(laydesc
);
273 auto lbi
= ctx
["lbhistory"];
275 foreach (int idx
; 0..hcount
) {
276 auto s
= hisman
.item(hid
, idx
);
277 ctx
.listboxItemAdd(lbi
, s
);
279 if (startidx
< 0 || startidx
>= hcount
) {
280 ctx
.listboxItemSetCurrent(lbi
, hcount
-1);
282 ctx
.listboxItemSetCurrent(lbi
, startidx
);
286 ctx
.layprops(0).position
.x
= x0
;
287 ctx
.layprops(0).position
.y
= y0
;
288 auto res
= ctx
.modalDialog
!false; // don't center
289 if (res
< 0) return -1;
290 return ctx
.listboxItemCurrent(lbi
);