1 #include "dialogs.h"
2 
3 
4 Font* dialogs::FontResource;
5 SDL_Color dialogs::BackgroundColor;
6 SDL_Color dialogs::TextBoxColor;
7 stack<yesnoData> dialogs::yesnoCurrent;
8 stack<inputDialog> dialogs::inputCurrent;
onDialogClickDoNothing(bool yesclicked)9 void onDialogClickDoNothing(bool yesclicked) {};
10 
11 class yesnoButtonData: public buttondata
12 {
13  public:
14     onDialogEnd func;
15     window* target;
16 
yesnoButtonData(onDialogEnd afunc,window * atarget)17     yesnoButtonData(onDialogEnd afunc,window* atarget)
18     {
19         func=afunc;
20         target=atarget;
21     }
22 };
23 
yesButtonClick(const buttondata * data)24 void dialogs::yesButtonClick(const buttondata* data)
25 {
26     const yesnoButtonData* dt=static_cast<const yesnoButtonData*>(data);
27     onDialogEnd func=dt->func;
28     dt->target->endSub();
29     dialogs::yesnoCurrent.pop();
30     func(true);
31 }
32 
33 
noButtonClick(const buttondata * data)34 void dialogs::noButtonClick(const buttondata* data)
35 {
36     const yesnoButtonData* dt=static_cast<const yesnoButtonData*>(data);
37     onDialogEnd func=dt->func;
38     dt->target->endSub();
39     dialogs::yesnoCurrent.pop();
40     func(false);
41 }
42 
yesnoOnKeyDown(SDLKey keysym,Uint16 unicode)43 void dialogs::yesnoOnKeyDown(SDLKey keysym, Uint16 unicode)
44 {
45     yesnoData dt= dialogs::yesnoCurrent.top();
46 
47     switch(keysym)
48     {
49         case SDLK_RETURN :
50             dialogs::yesnoCurrent.pop();
51             dt.enterdown=true;
52             dialogs::yesnoCurrent.push(dt);
53             break;
54         case (SDLK_ESCAPE):
55             dialogs::yesnoCurrent.pop();
56             dt.escdown=true;
57             dialogs::yesnoCurrent.push(dt);
58             break;
59     }
60 }
61 
yesnoOnKeyUp(SDLKey keysym,Uint16 unicode)62 void dialogs::yesnoOnKeyUp(SDLKey keysym, Uint16 unicode)
63 {
64     yesnoData dt= dialogs::yesnoCurrent.top();
65 
66     switch(keysym)
67     {
68         case SDLK_RETURN :
69             if(!dt.enterdown) return;
70             dialogs::yesnoCurrent.pop();
71             dt.target->endSub();
72             dt.func(true);
73             break;
74         case (SDLK_ESCAPE):
75 
76             if(!dt.escdown) return;
77             dialogs::yesnoCurrent.pop();
78             dt.target->endSub();
79             dt.func(false);
80 
81             break;
82     }
83 }
84 //================================================================================
85 class inputtextblock: public control
86 {
87  public:
88     int lines;
89     int tic;
90     string oldtext;
91     inputDialog* diag;
92     inputtextblock(int sx, int sy, int sw, int slines);
93 
94     vector<string> textsplit;
95 
96     void draw(SDL_Surface* target);
loop()97     void loop() {}
onMouseMove(int px,int py)98     inline void onMouseMove(int px,int py){}
onMouseOut()99     inline void onMouseOut() {}
onMouseDown(int px,int py)100     inline void onMouseDown(int px,int py) {}
onMouseUp(int px,int py)101     inline void onMouseUp(int px,int py) {}
onMouseRightUp(int px,int py)102     inline void onMouseRightUp(int px,int py) {}
103 };
104 
inputtextblock(int sx,int sy,int sw,int slines)105 inputtextblock::inputtextblock(int sx, int sy, int sw, int slines)
106 {
107     lines=slines;
108     oldtext="";
109     textsplit=vector<string>(1,"");
110     x=sx;y=sy;w=sw;h=lines*dialogs::FontResource->Height();
111     depth=0;
112     tic=0;
113 }
114 
draw(SDL_Surface * target)115 void inputtextblock::draw(SDL_Surface* target)
116 {
117     tic++;
118     string text=dialogs::getCurrentInputText();
119 
120     if(text!=oldtext)
121     {
122         textsplit=dialogs::FontResource->splitByLines(text,w);
123         if(textsplit.size()==0) textsplit.push_back("");
124         oldtext=text;
125     }
126 
127 
128 
129 
130     int begi=0,endi=lines;
131     if(lines<textsplit.size())
132     {
133         begi=textsplit.size()-lines;
134         endi=textsplit.size();
135     }
136 
137     if (lines>textsplit.size())
138     {
139         endi=textsplit.size();
140     }
141 
142     int fh=dialogs::FontResource->Height();
143     int th=0;
144     for (int i=begi;i<endi;i++)
145     {
146 
147         if((i==endi-1) && (tic%8<4) )
148             dialogs::FontResource->Write(target, x, y+th, textsplit[i]+"|");
149         else
150             dialogs::FontResource->Write(target, x, y+th, textsplit[i]);
151         th+=fh;
152     }
153 }
154 
155 
156 
157 //================================================================================
158 
getCurrentInputText()159 string dialogs::getCurrentInputText()
160 {
161     if(inputCurrent.empty()) return "NULL";
162     else return inputCurrent.top().text;
163 }
makeButtonDialog(window * target,string prompt,string yescaption,bool showno,string nocaption,onDialogEnd func)164 void dialogs::makeButtonDialog(window* target, string prompt, string yescaption, bool showno, string nocaption, onDialogEnd func)
165 {
166 
167 
168     Sint16 pw = target->Width/2;
169     Sint16 ph = max(target->Height/3, min<int>(target->Height, FontResource->WrappedTextHeight(prompt, pw-2*button::Size) + button::Size*4) );
170     Sint16 px = target->Width/4;
171     Sint16 py = (target->Height - ph)/2;
172 
173 
174 
175     yesnoData dt;
176     dt.target=target;
177     dt.func=func;
178     dt.enterdown=false;
179     dt.escdown=false;
180     dialogs::yesnoCurrent.push(dt);
181     target->beginSub();
182 
183     control* tmcntrl;
184 
185     tmcntrl = new rectangle(px-1,py-1,pw+2,ph+2, 0,0,0 );
186     tmcntrl->depth=1;
187     target->addControl(tmcntrl);
188 
189     tmcntrl = new rectangle(px+3,py+3,pw,ph, 0,0,0 );
190     tmcntrl->depth=1;
191     target->addControl(tmcntrl);
192 
193 
194     tmcntrl=new rectangle(px,py,pw,ph, BackgroundColor );
195     tmcntrl->depth=2;
196     target->addControl(tmcntrl);
197 
198     target->onKeyUp=yesnoOnKeyUp;
199     target->onKeyDown=yesnoOnKeyDown;
200 
201 
202     textblock* tx = new textblock(px+button::Size, py+button::Size, pw-2*button::Size, ph - 4*button::Size, dialogs::FontResource);
203     tx->text= prompt;
204     tx->depth=19;
205     target->addControl(tx);
206 
207     int ybuttonw = FontResource->TextWidth(yescaption)+button::Size;
208     if (ybuttonw<button::Size*4) ybuttonw=button::Size*4;
209 
210     int buttonw = FontResource->TextWidth(nocaption)+button::Size;
211     if (buttonw<ybuttonw) buttonw=ybuttonw;
212     int buttonx;
213 
214     if(showno) buttonx=px+pw/2-buttonw-button::Size/2;
215     else buttonx=px+(pw-buttonw)/2;
216 
217 
218     int buttony=py+ph-2*button::Size+button::Size/2;
219     button* tmbut= new button(buttonx,buttony,buttonw,button::Size);
220     tmbut->text=yescaption;
221     tmbut->depth=20;
222     tmbut->onClick=yesButtonClick;
223     tmbut->data=new yesnoButtonData(func,target);
224 
225     target->addControl(tmbut);
226 
227 
228 
229     if(showno)
230     {
231         buttonx=px+pw/2+button::Size/2;
232         tmbut= new button(buttonx,buttony,buttonw,button::Size);
233         tmbut->text=nocaption;
234         tmbut->depth=20;
235         tmbut->onClick=noButtonClick;
236         tmbut->data=new yesnoButtonData(func,target);
237         target->addControl(tmbut);
238     }
239 }
240 
makeYesNoDialog(window * target,string prompt,string yescaption,string nocaption,onDialogEnd func)241 void dialogs::makeYesNoDialog(window* target, string prompt, string yescaption, string nocaption, onDialogEnd func)
242 {
243     makeButtonDialog(target,prompt, yescaption, true, nocaption, func);
244 }
makeMessageDialog(window * target,string prompt,string buttoncaption,onDialogEnd func)245 void dialogs::makeMessageDialog(window* target, string prompt, string buttoncaption, onDialogEnd func)
246 {
247     makeButtonDialog(target,prompt, buttoncaption, false, "", func);
248 }
249 
250 
251 //==================================
textDialogClickClear(const buttondata * data)252 void dialogs::textDialogClickClear(const buttondata* data)
253 {
254     inputDialog& d= inputCurrent.top();
255     d.text = "";
256 }
257 
textDialogClick(bool ok)258 void dialogs::textDialogClick(bool ok)
259 {
260     inputDialog d= inputCurrent.top();
261     inputCurrent.pop();
262 
263     d.target->endSub();
264     d.func(ok,d.text,d.data);
265 }
266 
inputOnKeyDown(SDLKey keysym,Uint16 unicode)267 void dialogs::inputOnKeyDown(SDLKey keysym,Uint16 unicode)
268 {
269     inputDialog d= inputCurrent.top();
270     if( unicode < 0x80)
271     {
272         char c = (char)(unicode);
273         if(c>=' ')
274         {
275             d.text+=c;
276             inputCurrent.pop();
277             inputCurrent.push(d);
278         }
279     }
280 
281     switch(keysym)
282     {
283         case SDLK_RETURN: textDialogClick(true); break;
284         case SDLK_ESCAPE: textDialogClick(false); break;
285 
286         case SDLK_BACKSPACE:
287             d.text=d.text.substr(0,d.text.length()-1);
288             inputCurrent.pop();
289             inputCurrent.push(d);
290             break;
291     }
292 }
293 
inputOnKeyUp(SDLKey keysym,Uint16 unicode)294 void dialogs::inputOnKeyUp(SDLKey keysym,Uint16 unicode)
295 {
296 
297 }
298 
299 
makeTextInputDialog(window * target,string prompt,string defaulttext,int lines,string okcaption,string cancelcaption,onTextDialogEnd func,inputDialogData * data)300 void dialogs::makeTextInputDialog(window* target,  string prompt, string defaulttext, int lines, string okcaption, string cancelcaption, onTextDialogEnd func, inputDialogData* data)
301 {
302 
303     SDL_EnableUNICODE(1);
304     Sint16 pw = target->Width/2;
305     Sint16 ph = max(target->Height/3, min<int>(target->Height, FontResource->WrappedTextHeight(prompt, pw-2*button::Size) + button::Size*5) );
306     Sint16 px = target->Width/4;
307     Sint16 py = (target->Height - ph)/2;
308 
309 
310     Sint16 ith = lines*FontResource->Height();
311     Sint16 textblockheight=ph - 4*button::Size - 2 - ith;
312     Sint16 itw = pw-2*button::Size;
313     Sint16 itx = px+button::Size, ity=py+button::Size+textblockheight+1;
314 
315 
316     inputDialog cur;
317     cur.data=data;
318     cur.text=defaulttext;
319     cur.lines=lines;
320     cur.target=target;
321     cur.func=func;
322 
323     inputCurrent.push(cur);
324 
325 
326     target->beginSub();
327     target->onKeyUp=inputOnKeyUp;
328     target->onKeyDown=inputOnKeyDown;
329 
330     control * tmcntrl;
331     tmcntrl = new rectangle(px-1,py-1,pw+2,ph+2, 0,0,0 );
332     tmcntrl->depth=1;
333     target->addControl(tmcntrl);
334 
335     tmcntrl = new rectangle(px+3,py+3,pw,ph, 0,0,0 );
336     tmcntrl->depth=1;
337     target->addControl(tmcntrl);
338 
339 
340 
341     tmcntrl=new rectangle(px,py,pw,ph, BackgroundColor );
342     tmcntrl->depth=2;
343     target->addControl(tmcntrl);
344 
345     tmcntrl=new rectangle(itx-1,ity-1,itw+2,ith+2, 0,0,0);
346     tmcntrl->depth=3;
347     target->addControl(tmcntrl);
348 
349     tmcntrl=new rectangle(itx,ity,itw,ith, dialogs::TextBoxColor);
350     tmcntrl->depth=4;
351     target->addControl(tmcntrl);
352 
353 
354 
355     textblock* tx = new textblock(px+button::Size, py+button::Size, pw-2*button::Size, textblockheight, dialogs::FontResource);
356     tx->text= prompt;
357     tx->depth=19;
358     target->addControl(tx);
359 
360     inputtextblock* input = new inputtextblock(itx+2, ity, itw-4,lines);
361     input->depth=19;
362     target->addControl(input);
363 
364 
365     int ybuttonw = FontResource->TextWidth(okcaption)+button::Size;
366     if (ybuttonw<button::Size*4) ybuttonw=button::Size*4;
367 
368     int buttonw = FontResource->TextWidth(cancelcaption)+button::Size;
369     if (buttonw<ybuttonw) buttonw=ybuttonw;
370 
371 
372     int buttonx=px + button::Size  /*+pw/2-buttonw-button::Size/2*/;
373 
374     int buttony=py+ph-2*button::Size+button::Size/2;
375     button* tmbut= new button(buttonx,buttony,buttonw,button::Size);
376     tmbut->text=okcaption;
377     tmbut->depth=20;
378     tmbut->onClick=textDialogClickOk;
379     tmbut->data=NULL;
380     target->addControl(tmbut);
381 
382     buttonx=/*px+pw/2+button::Size/2*/ px + pw/2 - buttonw/2;
383     tmbut= new button(buttonx,buttony,buttonw,button::Size);
384     tmbut->text="Clear";
385     tmbut->depth=20;
386     tmbut->onClick=textDialogClickClear;
387     tmbut->data=NULL;
388     target->addControl(tmbut);
389 
390 
391 
392     buttonx=/*px+pw/2+button::Size/2*/ px + pw - buttonw - button::Size;
393     tmbut= new button(buttonx,buttony,buttonw,button::Size);
394     tmbut->text=cancelcaption;
395     tmbut->depth=20;
396     tmbut->onClick=textDialogClickCancel;
397     tmbut->data=NULL;
398     target->addControl(tmbut);
399 
400 
401 
402 
403 }
404