ncurses 5.3
[ncurses.git] / c++ / demo.cc
1 /*
2  *   Silly demo program for the NCursesPanel class.
3  *
4  *   written by Anatoly Ivasyuk (anatoly@nick.csh.rit.edu)
5  *
6  *   Demo code for NCursesMenu and NCursesForm written by
7  *   Juergen Pfeifer
8  *   Contact: http://www.familiepfeifer.de/Contact.aspx?Lang=en
9  *
10  * $Id: demo.cc,v 1.22 2002/07/06 15:47:52 juergen Exp $
11  */
12
13 #include "cursesapp.h"
14 #include "cursesm.h"
15 #include "cursesf.h"
16
17 #if HAVE_LIBC_H
18 #  include <libc.h>
19 #endif
20
21 extern "C" unsigned int sleep(unsigned int);
22
23 #undef index // needed for NeXT
24
25 //
26 // -------------------------------------------------------------------------
27 //
28 class SillyDemo
29 {
30   public:
31   void run(int sleeptime) {
32
33     NCursesPanel *std = new NCursesPanel();
34
35     //  Make a few small demo panels
36
37     NCursesPanel *u = new NCursesPanel(8,20,12,4);
38     NCursesPanel *v = new NCursesPanel(8,20,10,6);
39     NCursesPanel *w = new NCursesPanel(8,20,8,8);
40     NCursesPanel *x = new NCursesPanel(8,20,6,10);
41     NCursesPanel *y = new NCursesPanel(8,20,4,12);
42     NCursesPanel *z = new NCursesPanel(8,30,2,14);
43
44     //  Draw something on the main screen, so we can see what happens
45     //  when panels get moved or deleted.
46
47     std->box();
48     std->move(std->height()/2,1);
49     std->hline(std->width()-2);
50     std->move(1,std->width()/2);
51     std->vline(std->height()-2);
52     std->addch(0,std->width()/2,ACS_TTEE);
53     std->addch(std->height()-1,std->width()/2,ACS_BTEE);
54     std->addch(std->height()/2,0,ACS_LTEE);
55     std->addch(std->height()/2,std->width()-1,ACS_RTEE);
56     std->addch(std->height()/2,std->width()/2,ACS_PLUS);
57
58     //  Draw frames with titles around panels so that we can see where
59     //  the panels are located.
60     u->boldframe("Win U");
61     v->frame("Win V");
62     w->boldframe("Win W");
63     x->frame("Win X");
64     y->boldframe("Win Y");
65     z->frame("Win Z");
66     if (NCursesApplication::getApplication()->useColors()) {
67       u->bkgd(' '|COLOR_PAIR(1));
68       w->bkgd(' '|COLOR_PAIR(1));
69       y->bkgd(' '|COLOR_PAIR(1));
70       v->bkgd(' '|COLOR_PAIR(2));
71       x->bkgd(' '|COLOR_PAIR(2));
72       z->bkgd(' '|COLOR_PAIR(2));
73     }
74
75     //  A refresh to any valid panel updates all panels and refreshes
76     //  the screen.  Using std is just convenient - We know it's always
77     //  valid until the end of the program.
78
79     std->refresh();
80     sleep(sleeptime);
81
82     //  Show what happens when panels are deleted and moved.
83
84     sleep(sleeptime);
85     delete u;
86     std->refresh();
87
88     sleep(sleeptime);
89     delete z;
90     std->refresh();
91
92     sleep(sleeptime);
93     delete v;
94     std->refresh();
95
96     // show how it looks when a panel moves
97     sleep(sleeptime);
98     y->mvwin(5,30);
99     std->refresh();
100
101     sleep(sleeptime);
102     delete y;
103     std->refresh();
104
105     // show how it looks when you raise a panel
106     sleep(sleeptime);
107     w->top();
108     std->refresh();
109
110     sleep(sleeptime);
111     delete w;
112     std->refresh();
113
114     sleep(sleeptime);
115     delete x;
116
117     std->clear();
118     std->refresh();
119
120     //  Don't forget to clean up the main screen.  Since this is the
121     //  last thing using NCursesWindow, this has the effect of
122     //  shutting down ncurses and restoring the terminal state.
123
124     sleep(sleeptime);
125     delete std;
126   }
127 };
128
129 class UserData
130 {
131 private:
132   int u;
133 public:
134   UserData(int x) : u(x) {}
135   int sleeptime() const { return u; }
136 };
137 //
138 // -------------------------------------------------------------------------
139 //
140 template<class T> class MyAction : public NCursesUserItem<T>
141 {
142 public:
143   MyAction (const char* p_name,
144             const T* p_UserData)
145     : NCursesUserItem<T>(p_name, (const char*)0, p_UserData)
146   {};
147
148   ~MyAction() {}
149
150   bool action() {
151     SillyDemo a;
152     a.run(NCursesUserItem<T>::UserData()->sleeptime());
153     return FALSE;
154   }
155 };
156
157 class QuitItem : public NCursesMenuItem
158 {
159 public:
160   QuitItem() : NCursesMenuItem("Quit") {
161   }
162
163   bool action() {
164     return TRUE;
165   }
166 };
167 //
168 // -------------------------------------------------------------------------
169 //
170 class Label : public NCursesFormField
171 {
172 public:
173   Label(const char* title,
174         int row, int col)
175     : NCursesFormField(1,(int)::strlen(title),row,col) {
176       set_value(title);
177       options_off(O_EDIT|O_ACTIVE);
178   }
179 };
180 //
181 // -------------------------------------------------------------------------
182 //
183 class MyFieldType : public UserDefinedFieldType {
184 private:
185   int chk;
186 protected:
187   bool field_check(NCursesFormField& f) {
188     return TRUE;
189   }
190   bool char_check(int c) {
191     return (c==chk?TRUE:FALSE);
192   }
193 public:
194   MyFieldType(int x) : chk(x) {
195   }
196 };
197 //
198 // -------------------------------------------------------------------------
199 //
200 class TestForm : public NCursesForm
201 {
202 private:
203   NCursesFormField** F;
204   MyFieldType* mft;
205   Integer_Field *ift;
206   Enumeration_Field *eft;
207
208   static char *weekdays[];
209
210 public:
211   TestForm() : NCursesForm(13,51,(lines()-15)/2,(cols()-53)/2) {
212
213     F     = new NCursesFormField*[10];
214     mft   = new MyFieldType('X');
215     ift   = new Integer_Field(0,1,10);
216     eft   = new Enumeration_Field(weekdays);
217
218     F[0]  = new Label("Demo Entry Form",0,16);
219     F[1]  = new Label("Weekday Enum",2,1);
220     F[2]  = new Label("Number(1-10)",2,21);
221     F[3]  = new Label("Only 'X'",2,35);
222     F[4]  = new Label("Multiline Field (Dynamic and Scrollable)",5,1);
223     F[5]  = new NCursesFormField(1,18,3,1);
224     F[6]  = new NCursesFormField(1,12,3,21);
225     F[7]  = new NCursesFormField(1,12,3,35);
226     F[8]  = new NCursesFormField(4,46,6,1,2);
227     F[9]  = new NCursesFormField();
228
229     InitForm(F,TRUE,TRUE);
230     boldframe();
231
232     F[5]->set_fieldtype(*eft);
233     F[6]->set_fieldtype(*ift);
234
235     F[7]->set_fieldtype(*mft);
236     F[7]->set_maximum_growth(20); // max. 20 characters
237     F[7]->options_off(O_STATIC);  // make field dynamic
238
239     F[8]->set_maximum_growth(10); // max. 10 lines
240     F[8]->options_off(O_STATIC);  // make field dynamic
241   }
242
243   ~TestForm() {
244     delete mft;
245     delete ift;
246     delete eft;
247   }
248 };
249
250 char* TestForm::weekdays[] = {
251     "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday",
252     "Friday", "Saturday", (char *)0 };
253 //
254 // -------------------------------------------------------------------------
255 //
256 class FormAction : public NCursesMenuItem
257 {
258 public:
259   FormAction(const char *s) : NCursesMenuItem(s) {
260   }
261
262   bool action() {
263     TestForm F;
264     Soft_Label_Key_Set* S = new Soft_Label_Key_Set;
265     for(int i=1; i <= S->labels(); i++) {
266       char buf[5];
267       ::sprintf(buf,"Frm%02d",i);
268       (*S)[i] = buf;                                      // Text
269       (*S)[i] = Soft_Label_Key_Set::Soft_Label_Key::Left; // Justification
270     }
271     NCursesApplication::getApplication()->push(*S);
272     F();
273     NCursesApplication::getApplication()->pop();
274     return FALSE;
275   }
276 };
277 //
278 // -------------------------------------------------------------------------
279 //
280 class PadAction : public NCursesMenuItem
281 {
282 public:
283   PadAction(const char* s) : NCursesMenuItem(s) {
284   }
285
286   bool action() {
287     const int GRIDSIZE = 3;
288     const int PADSIZE  = 200;
289     unsigned gridcount = 0;
290
291     NCursesPanel std;
292     NCursesPanel P(std.lines()-2,std.cols()-2,1,1);
293     NCursesFramedPad FP(P,PADSIZE,PADSIZE);
294
295     for (int i=0; i < PADSIZE; i++) {
296       for (int j=0; j < PADSIZE; j++) {
297         if (i % GRIDSIZE == 0 && j % GRIDSIZE == 0) {
298           if (i==0 || j==0)
299             FP.addch('+');
300           else
301             FP.addch((chtype)('A' + (gridcount++ % 26)));
302         }
303         else if (i % GRIDSIZE == 0)
304           FP.addch('-');
305         else if (j % GRIDSIZE == 0)
306           FP.addch('|');
307         else
308           FP.addch(' ');
309       }
310     }
311
312     P.label("Pad Demo",NULL);
313     FP();
314     P.clear();
315     return FALSE;
316   }
317 };
318
319 //
320 // -------------------------------------------------------------------------
321 //
322 class PassiveItem : public NCursesMenuItem {
323 public:
324   PassiveItem(const char* text) : NCursesMenuItem(text) {
325     options_off(O_SELECTABLE);
326   }
327 };
328
329 //
330 // -------------------------------------------------------------------------
331 //
332 class ScanAction : public NCursesMenuItem
333 {
334 public:
335   ScanAction(const char* s) : NCursesMenuItem(s) {
336   }
337
338   bool action() {
339     NCursesPanel *std = new NCursesPanel();
340
341     NCursesPanel *w = new NCursesPanel(std->lines() - 2, std->cols() - 2, 1, 1);
342     w->box();
343     w->refresh();
344
345     NCursesPanel *s = new NCursesPanel(w->lines() - 6, w->cols() - 6, 3, 3);
346     s->scrollok(TRUE);
347     ::echo();
348
349     s->printw("Enter decimal integers.  The running total will be shown\n");
350     int value = -1;
351     int result = 0;
352     while (value != 0) {
353       value = 0;
354       s->scanw("%d", &value);
355       if (value != 0) {
356         s->printw("%d: ", result += value);
357       }
358       s->refresh();
359     }
360     s->printw("\nPress any key to continue...");
361     s->getch();
362
363     delete s;
364     delete w;
365     delete std;
366     ::noecho();
367     return FALSE;
368   }
369 };
370
371 //
372 // -------------------------------------------------------------------------
373 //
374 class MyMenu : public NCursesMenu
375 {
376 private:
377   NCursesPanel* P;
378   NCursesMenuItem** I;
379   UserData *u;
380   #define n_items 7
381
382 public:
383   MyMenu ()
384     : NCursesMenu (n_items+2, 8, (lines()-10)/2, (cols()-10)/2)
385   {
386     u = new UserData(1);
387     I = new NCursesMenuItem*[1+n_items];
388     I[0] = new PassiveItem("One");
389     I[1] = new PassiveItem("Two");
390     I[2] = new MyAction<UserData> ("Silly", u);
391     I[3] = new FormAction("Form");
392     I[4] = new PadAction("Pad");
393     I[5] = new ScanAction("Scan");
394     I[6] = new QuitItem();
395     I[7] = new NCursesMenuItem(); // Terminating empty item
396
397     InitMenu(I,TRUE,TRUE);
398
399     P = new NCursesPanel(1,n_items,LINES-1,1);
400     boldframe("Demo","Silly");
401     P->show();
402   }
403
404   ~MyMenu()
405   {
406     P->hide();
407     delete P;
408     delete u;
409   }
410
411   virtual void On_Menu_Init()
412   {
413     NCursesWindow W(::stdscr);
414     P->move(0,0);
415     P->clrtoeol();
416     for(int i=1; i<=count(); i++)
417       P->addch('0' + i);
418     P->bkgd(W.getbkgd());
419     refresh();
420   }
421
422   virtual void On_Menu_Termination()
423   {
424     P->move(0,0);
425     P->clrtoeol();
426     refresh();
427   }
428
429   virtual void On_Item_Init(NCursesMenuItem& item)
430   {
431     P->move(0,item.index());
432     P->attron(A_REVERSE);
433     P->printw("%1d",1+item.index());
434     P->attroff(A_REVERSE);
435     refresh();
436   }
437
438   virtual void On_Item_Termination(NCursesMenuItem& item)
439   {
440     P->move(0,item.index());
441     P->attroff(A_REVERSE);
442     P->printw("%1d",1+item.index());
443     refresh();
444   }
445 };
446 //
447 // -------------------------------------------------------------------------
448 //
449 class TestApplication : public NCursesApplication {
450 protected:
451   int titlesize() const { return 1; }
452   void title();
453   Soft_Label_Key_Set::Label_Layout useSLKs() const {
454     return Soft_Label_Key_Set::PC_Style_With_Index;
455   }
456   void init_labels(Soft_Label_Key_Set& S) const;
457
458 public:
459   TestApplication() : NCursesApplication(TRUE) {
460   }
461
462   int run();
463 };
464
465 void TestApplication::init_labels(Soft_Label_Key_Set& S) const {
466   for(int i=1; i <= S.labels(); i++) {
467     char buf[5];
468     ::sprintf(buf,"Key%02d",i);
469     S[i] = buf;                                      // Text
470     S[i] = Soft_Label_Key_Set::Soft_Label_Key::Left; // Justification
471   }
472 }
473
474 void TestApplication::title() {
475   const char * const title = "Simple C++ Binding Demo";
476   const int len = ::strlen(title);
477
478   titleWindow->bkgd(screen_titles());
479   titleWindow->addstr(0,(titleWindow->cols()-len)/2,title);
480   titleWindow->noutrefresh();
481 }
482
483
484 int TestApplication::run() {
485   MyMenu M;
486   M();
487   return 0;
488 }
489
490 //
491 // -------------------------------------------------------------------------
492 //
493 static TestApplication Demo;