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