088dc2fbc86dc810e6deeadeab303cf15a7e5b74
[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 <juergen.pfeifer@gmx.net>
8  *
9  * $Id: demo.cc,v 1.18 1999/09/11 18:57:54 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 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 char* TestForm::weekdays[] = {
250     "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday",
251     "Friday", "Saturday", (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 class MyMenu : public NCursesMenu
331 {
332 private:
333   NCursesPanel* P;
334   NCursesMenuItem** I;
335   UserData *u;
336   #define n_items 7
337
338 public:
339   MyMenu ()
340     : NCursesMenu (n_items+2, 8, (lines()-10)/2, (cols()-10)/2)
341   {
342     u = new UserData(1);
343     I = new NCursesMenuItem*[1+n_items];
344     I[0] = new PassiveItem("One");
345     I[1] = new PassiveItem("Two");
346     I[2] = new MyAction<UserData> ("Silly", u);
347     I[3] = new FormAction("Form");
348     I[4] = new PadAction("Pad");
349     I[5] = new PassiveItem("Six");
350     I[6] = new QuitItem();
351     I[7] = new NCursesMenuItem(); // Terminating empty item
352
353     InitMenu(I,TRUE,TRUE);
354
355     P = new NCursesPanel(1,n_items,LINES-1,1);
356     boldframe("Demo","Silly");
357     P->show();
358   }
359
360   ~MyMenu()
361   {
362     P->hide();
363     delete P;
364     delete u;
365   }
366
367   virtual void On_Menu_Init()
368   {
369     NCursesWindow W(::stdscr);
370     P->move(0,0);
371     P->clrtoeol();
372     for(int i=1; i<=count(); i++)
373       P->addch('0' + i);
374     P->bkgd(W.getbkgd());
375     refresh();
376   }
377
378   virtual void On_Menu_Termination()
379   {
380     P->move(0,0);
381     P->clrtoeol();
382     refresh();
383   }
384
385   virtual void On_Item_Init(NCursesMenuItem& item)
386   {
387     P->move(0,item.index());
388     P->attron(A_REVERSE);
389     P->printw("%1d",1+item.index());
390     P->attroff(A_REVERSE);
391     refresh();
392   }
393
394   virtual void On_Item_Termination(NCursesMenuItem& item)
395   {
396     P->move(0,item.index());
397     P->attroff(A_REVERSE);
398     P->printw("%1d",1+item.index());
399     refresh();
400   }
401 };
402 //
403 // -------------------------------------------------------------------------
404 //
405 class TestApplication : public NCursesApplication {
406 protected:
407   int titlesize() const { return 1; }
408   void title();
409   Soft_Label_Key_Set::Label_Layout useSLKs() const {
410     return Soft_Label_Key_Set::PC_Style_With_Index;
411   }
412   void init_labels(Soft_Label_Key_Set& S) const;
413
414 public:
415   TestApplication() : NCursesApplication(TRUE) {
416   }
417
418   int run();
419 };
420
421 void TestApplication::init_labels(Soft_Label_Key_Set& S) const {
422   for(int i=1; i <= S.labels(); i++) {
423     char buf[5];
424     ::sprintf(buf,"Key%02d",i);
425     S[i] = buf;                                      // Text
426     S[i] = Soft_Label_Key_Set::Soft_Label_Key::Left; // Justification
427   }
428 }
429
430 void TestApplication::title() {
431   const char * const title = "Simple C++ Binding Demo";
432   const int len = ::strlen(title);
433
434   titleWindow->bkgd(screen_titles());
435   titleWindow->addstr(0,(titleWindow->cols()-len)/2,title);
436   titleWindow->noutrefresh();
437 }
438
439
440 int TestApplication::run() {
441   MyMenu M;
442   M();
443   return 0;
444 }
445
446 //
447 // -------------------------------------------------------------------------
448 //
449 static TestApplication Demo;