source: golgotha/src/i4/lisp/li_dialog.cc @ 80

Last change on this file since 80 was 80, checked in by Sam Hocevar, 12 years ago
  • Adding the Golgotha source code. Not sure what's going to be interesting in there, but since it's all public domain, there's certainly stuff to pick up.
File size: 14.6 KB
Line 
1/********************************************************************** <BR>
2  This file is part of Crack dot Com's free source code release of
3  Golgotha. <a href="http://www.crack.com/golgotha_release"> <BR> for
4  information about compiling & licensing issues visit this URL</a>
5  <PRE> If that doesn't help, contact Jonathan Clark at
6  golgotha_source@usa.net (Subject should have "GOLG" in it)
7***********************************************************************/
8
9#include "gui/text_input.hh"
10#include "gui/text.hh"
11#include "lisp/li_types.hh"
12#include "lisp/li_class.hh"
13#include "lisp/li_dialog.hh"
14#include "file/ram_file.hh"
15#include "app/app.hh"
16#include "memory/array.hh"
17#include "gui/image_win.hh"
18#include "gui/button.hh"
19#include "gui/list_box.hh"
20#include "menu/textitem.hh"
21#include "window/wmanager.hh"
22
23
24static li_symbol_ref li_list_box("list_box");
25
26class li_generic_edit_class : public li_type_edit_class
27{
28public:
29  enum input_type { TEXT_INPUT,
30                    LIST_BOX };
31
32  input_type get_type(li_object *property_list, li_environment *env)
33  {
34    if (property_list && property_list->type()==LI_LIST &&
35        li_list_box.get()==li_car(property_list,env))
36      return LIST_BOX;
37    else
38      return TEXT_INPUT;
39  }
40 
41
42  virtual int create_edit_controls(const i4_const_str &name,
43                                   li_object *o,
44                                   li_object *property_list,
45                                   i4_window_class **windows,
46                                   int max_windows,
47                                   li_environment *env)
48  {
49    if (max_windows<2) return 0;
50   
51    char buf[200];
52    i4_ram_file_class rf(buf, 30);
53    li_get_type(o->type())->print(o, &rf);
54    buf[rf.tell()]=0;
55
56    i4_graphical_style_class *style=i4_current_app->get_style();
57
58    windows[0]=new i4_text_window_class(name, style);
59
60    if (get_type(property_list,env)==LIST_BOX)
61    {
62      property_list=li_cdr(property_list, env);
63   
64      i4_list_box_class *lb=new i4_list_box_class(200, style,
65                                                  i4_current_app->get_window_manager());
66
67      int on=0;
68      for (;property_list; property_list=li_cdr(property_list,env), on++)
69      {
70        char buf[100];
71        i4_ram_file_class rf(buf, 100);
72        li_object *v=li_car(property_list,env);
73
74
75        li_get_type(v->type())->print(v, &rf);
76        buf[rf.tell()]=0;
77
78        lb->add_item(new i4_text_item_class(buf, style));
79
80        if (v->type()==o->type() && li_get_type(v->type())->equal(o,v))
81          lb->set_current_item(on);
82       
83
84      }
85      windows[1]=lb;   
86    }   
87    else
88    {
89      if (o->type()==LI_STRING)
90      {
91        buf[strlen(buf)-1]=0;   // chop of end quote
92        windows[1]=new i4_text_input_class(style,buf+1, 200,200);
93      }
94      else
95        windows[1]=new i4_text_input_class(style,buf, 200,200);
96    }
97                                       
98    return 2;
99  }
100
101  virtual i4_bool can_apply_edit_controls(li_object *o,
102                                          li_object *property_list,
103                                          i4_window_class **windows)
104  {
105    return i4_T;   
106  }
107
108  virtual li_object *apply_edit_controls(li_object *o,
109                                         li_object *property_list,
110                                         i4_window_class **windows,
111                                         li_environment *env)
112  {
113    if (get_type(property_list, env)==LIST_BOX)
114    {
115      i4_list_box_class *ib=((i4_list_box_class *)windows[1]);
116      return li_nth(property_list, ib->get_current()+1, env);
117    }
118    else if (get_type(property_list, env)==TEXT_INPUT)
119    {
120      i4_text_input_class *w=((i4_text_input_class *)windows[1]);
121     
122      i4_const_str::iterator i=w->get_edit_string()->begin();
123      if (o->type()==LI_INT)
124        return new li_int(i.read_number());
125      else if (o->type()==LI_FLOAT)
126        return new li_float(i.read_float());
127      else if (o->type()==LI_SYMBOL)
128      {
129        char buf[300];
130        i4_os_string(*w->get_edit_string(), buf, 100);
131        return li_get_symbol(buf);
132      }
133      else if (o->type()==LI_STRING)
134        return new li_string(*w->get_edit_string());
135      else
136        return o;
137    }
138    else
139      return o;
140  }
141     
142
143} li_generic_edit_instance;
144
145
146class li_class_dialog_item : public li_dialog_item
147{
148public:
149  char *name() { return "li_class_item"; }
150
151  i4_array<li_dialog_item *> items;
152
153  li_class_dialog_item(li_class *c, li_object *_prop_list, li_environment *env)
154    : items(5,5)
155  {
156    prop_list=_prop_list;
157    o=c;
158
159    int t=li_class_total_members(c->type()), i, max_colums=0;
160    int colums[50];
161    memset(colums, 0, sizeof(colums));
162
163    for (i=0; i<t; i++)
164    {
165      li_symbol *sym=li_class_get_symbol(c->type(), i);
166      li_object *val=c->value(i);
167      li_object *prop_list=li_class_get_property_list(c->type(), sym);
168     
169      li_dialog_item *item=new li_dialog_item(sym->name()->value(), val, prop_list, env);
170       items.add(item);
171
172       int t_win=items[i]->t_windows;
173       if (t_win>max_colums)
174         max_colums=t_win;
175       for (int j=0; j<t_win; j++)
176         if (items[i]->windows[j] && items[i]->windows[j]->width()>colums[j])
177           colums[j]=items[i]->windows[j]->width();
178     }
179
180     int dy=0, maxw=0;
181     for (i=0; i<t; i++)
182     {
183       int dx=0, maxh=0;
184       add_child(dx,dy, items[i]);
185
186       for (int j=0; j<items[i]->t_windows; j++)
187       {
188         if (items[i]->windows[j])
189         {
190           int xoff=dx-(items[i]->windows[j]->x()-items[i]->x());
191           items[i]->windows[j]->move(xoff,0);
192
193           if (items[i]->windows[j]->height()>maxh)
194             maxh=items[i]->windows[j]->height();
195         }
196
197         dx+=colums[j]+3;
198         if (dx>maxw) maxw=dx;
199       }
200       items[i]->resize_to_fit_children();
201
202       dy+=maxh+1;       
203     }     
204
205     private_resize(maxw,dy);
206   }
207
208   i4_bool can_apply(li_environment *env)
209   {
210     for (int i=0; i<items.size(); i++)
211       if (!items[i]->can_apply(env))
212         return i4_F;
213     return i4_T;
214   }
215
216   li_object *apply(li_environment *env)
217   {
218     li_class *c=(li_class *)li_new(o.get()->type());
219
220     for (int i=0; i<items.size(); i++)
221       c->set_value(i, items[i]->apply(env));
222
223     return c;
224   }
225 };
226
227 class li_class_edit_class : public li_type_edit_class
228 {
229 public:
230   int create_edit_controls(const i4_const_str &name,
231                            li_object *object,
232                            li_object *property_list,
233                            i4_window_class **windows,
234                            int max_windows,
235                            li_environment *env)
236   {
237     if (max_windows)
238     {
239       windows[0]=new li_class_dialog_item(li_class::get(object,env), property_list, env);
240       return 1;
241     } else return 0;   
242   }
243
244   i4_bool can_apply_edit_controls(li_object *objectw,
245                                   li_object *property_list,
246                                   i4_window_class **windows,
247                                   li_environment *env)
248   {
249     return ((li_class_dialog_item *)windows[0])->can_apply(env);
250   }
251
252   li_object *apply_edit_controls(li_object *o,
253                                  li_object *property_list,
254                                  i4_window_class **windows,
255                                  li_environment *env)
256   {
257     return ((li_class_dialog_item *)windows[0])->apply(env);   
258   }
259
260 } li_class_edit_instance;
261
262
263 class li_generic_edit_initer : public i4_init_class
264 {
265 public:
266   int init_type() { return I4_INIT_TYPE_LISP_FUNCTIONS; }
267
268   void init()
269   {
270     li_get_type(LI_INT)->editor=&li_generic_edit_instance;
271     li_get_type(LI_FLOAT)->editor=&li_generic_edit_instance;
272     li_get_type(LI_SYMBOL)->editor=&li_generic_edit_instance;
273     li_get_type(LI_STRING)->editor=&li_generic_edit_instance;
274     li_set_class_editor(&li_class_edit_instance);
275   }
276
277 } li_generic_edit_initer_instance;
278
279
280 li_dialog_item::li_dialog_item()
281   : i4_color_window_class(0,0, i4_current_app->get_style()->color_hint->neutral(),
282                           i4_current_app->get_style())
283 {
284   windows=0;
285   t_windows=0;
286   o=0;
287   prop_list=0;
288 }
289
290
291 li_dialog_item::li_dialog_item(const i4_const_str &name,
292                                li_object *_o,
293                                li_object *prop_list,
294                                li_environment *env)
295
296   : i4_color_window_class(0,0, i4_current_app->get_style()->color_hint->neutral(),
297                           i4_current_app->get_style()),
298     prop_list(prop_list)
299 {
300   o=_o;
301   windows=0;
302   t_windows=0;
303
304   i4_window_class *w[10];
305
306   if (li_get_type(o->type())->editor)
307   {
308     if (prop_list!=li_get_symbol("no_edit"))
309     {
310       t_windows=li_get_type(o->type())->editor->create_edit_controls(name,
311                                                                      o.get(),
312                                                                      prop_list,
313                                                                      w, 10, env);
314       if (t_windows)
315       {       
316         windows=(i4_window_class **)i4_malloc(sizeof(i4_window_class *) * t_windows,"");
317         int x=0, i, maxh=0;
318         for (i=0; i<t_windows; i++)
319           if (w[i] && w[i]->height()>maxh)
320             maxh=w[i]->height();
321
322
323         for (i=0; i<t_windows; i++)
324         {
325           windows[i]=w[i];
326
327           add_child(x, maxh/2 - windows[i]->height()/2 , windows[i]);
328           x+=w[i]->width();
329         }
330         resize_to_fit_children();
331       }
332     }
333   }
334 }
335
336
337
338 i4_bool li_dialog_item::can_apply(li_environment *env)
339 {
340   if (!li_get_type(o->type())->editor)  return i4_T;
341
342   return li_get_type(o->type())->editor->can_apply_edit_controls(o.get(), prop_list, windows,env);
343 }
344
345
346 li_object *li_dialog_item::apply(li_environment *env)
347 {
348   if (li_get_type(o->type())->editor)
349     return li_get_type(o->type())->editor->apply_edit_controls(o.get(), prop_list, windows, env);
350   return o.get();
351 } 
352
353 li_dialog_item::~li_dialog_item()
354 {
355   if (windows)
356     i4_free(windows);
357 }
358
359
360 i4_graphical_style_class *li_dialog_window_class::style()
361 {
362   return i4_current_app->get_style();
363 }
364
365
366
367 li_dialog_window_class::~li_dialog_window_class()
368 {
369   if (called_on_close)
370   {
371     if (new_value.get())
372       called_on_close(li_make_list(new_value.get(), o.get(), 0),0);
373     called_on_close=0;
374   }
375 }
376
377 li_dialog_window_class::li_dialog_window_class(const i4_const_str &name,
378                                                li_object *_o,
379                                                li_object *_prop_list,
380                                                li_function_type called_on_close,
381                                                li_environment *env)
382   : i4_color_window_class(0,0, style()->color_hint->neutral(), style()),
383     called_on_close(called_on_close), enviroment(env)
384 {
385   o=_o;
386   prop_list=_prop_list;
387
388
389   mp_handle=0;
390   int t=li_get_type(o->type())->editor->create_edit_controls(name, o.get(),
391                                                             prop_list.get(), w, 10,
392                                                              env);
393  int x=0, maxh=0;
394  for (int i=0; i<t; i++)
395  {
396    add_child(x, 0, w[i]);
397    if (w[i]->height()>maxh)
398      maxh=w[i]->height();
399  }
400
401  i4_window_class *ok, *cancel;
402
403  if (style()->icon_hint->ok_icon && style()->icon_hint->cancel_icon)
404  {
405    ok=new i4_image_window_class(style()->icon_hint->ok_icon);
406    cancel=new i4_image_window_class(style()->icon_hint->cancel_icon);
407  }
408  else
409  {
410    ok=new i4_text_window_class(i4gets("ok"), style());
411    cancel=new i4_text_window_class(i4gets("cancel"), style());
412  }
413   
414  resize_to_fit_children();
415
416  i4_button_class *okb=new i4_button_class(0, ok, style(),
417                                           new i4_event_reaction_class(this, 1));
418  i4_button_class *cancelb=new i4_button_class(0, cancel, style(),
419                                               new i4_event_reaction_class(this, 1));
420  x=width()/2-okb->width()/2-cancelb->width()/2;
421  if (x<0) x=0;
422
423  add_child(x, maxh+1, okb);
424  add_child(x+okb->width(), maxh+1, cancelb);
425
426  resize_to_fit_children();
427
428}
429
430void li_dialog_window_class::receive_event(i4_event *ev)
431{
432  if (ev->type()==i4_event::USER_MESSAGE)
433  {
434    if (((i4_user_message_event_class *)ev)->sub_type==1)
435    {
436      if (!li_get_type(o->type())->editor->can_apply_edit_controls(o.get(), prop_list.get(), w, env()))
437        return;
438      else
439        new_value=li_get_type(o->type())->editor->apply_edit_controls(o.get(),
440                                                                      prop_list.get(), w, env());
441
442    }
443
444    if (mp_handle)
445      style()->close_mp_window(mp_handle);       
446
447    if (called_on_close)
448    {
449      if (new_value.get())
450        called_on_close(li_make_list( new_value.get(), o.get(),  0),0);
451      called_on_close=0;
452    }
453
454  }
455  else
456    i4_color_window_class::receive_event(ev);
457}
458 
459
460
461li_dialog_window_class *li_create_dialog(const i4_const_str &name,
462                                         li_object *o,
463                                         li_object *prop_list,
464                                         char *close_fun,
465                                         li_environment *env)
466{
467  li_function_type fun=0;
468  if (close_fun)
469    fun=li_function::get(li_get_fun(li_get_symbol(close_fun), env),env)->value();
470
471  li_dialog_window_class *d=new li_dialog_window_class(name, o,prop_list, fun, env);
472
473  i4_parent_window_class *mp;
474  mp=i4_current_app->get_style()->create_mp_window(-1,-1, d->width(), d->height(),
475                                                   name, 0);
476  d->mp_handle=mp;
477  mp->add_child(0,0,d);
478  return d;
479}
480
481
482
483
484li_dialog_window_class *li_create_dialog(const i4_const_str &name,
485                                         li_object *o,
486                                         li_object *prop_list,
487                                         li_function_type fun,
488                                         li_environment *env)
489{
490  li_dialog_window_class *d=new li_dialog_window_class(name, o,prop_list, fun, env);
491
492  i4_parent_window_class *mp;
493  mp=i4_current_app->get_style()->create_mp_window(-1,-1, d->width(), d->height(),
494                                                   name, 0);
495  d->mp_handle=mp;
496  mp->add_child(0,0,d);
497  return d;
498}
499
500
501
Note: See TracBrowser for help on using the repository browser.