source: branches/port5/AWT/awt_input_mask_internal.hxx

Last change on this file was 6100, checked in by westram, 15 years ago
  • fix warning "format not a string literal and no format arguments"
    • GB_export_error → GB_export_error/GB_export_errorf
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 22.7 KB
Line 
1// ============================================================ //
2//                                                              //
3//   File      : awt_input_mask_internal.hxx                    //
4//   Purpose   : input mask internal classes                    //
5//                                                              //
6//   Coded by Ralf Westram (coder@reallysoft.de) in June 2009   //
7//   Institute of Microbiology (Technical University Munich)    //
8//   www.arb-home.de                                            //
9//                                                              //
10// ============================================================ //
11
12#ifndef AWT_INPUT_MASK_INTERNAL_HXX
13#define AWT_INPUT_MASK_INTERNAL_HXX
14
15#ifndef AWT_INPUT_MASK_HXX
16#include <awt_input_mask.hxx>
17#endif
18
19#ifndef _CPP_MAP
20#include <map>
21#endif
22#ifndef _CPP_STRING
23#include <string>
24#endif
25#ifndef _CPP_LIST
26#include <list>
27#endif
28#ifndef _CPP_VECTOR
29#include <vector>
30#endif
31
32#ifndef SMARTPTR_H
33#include <smartptr.h>
34#endif
35#ifndef AWT_HOTKEYS_HXX
36#include <awt_hotkeys.hxx>
37#endif
38
39// ---------------------------
40//      forward references
41
42class awt_mask_item;
43class awt_linked_to_item;
44class awt_viewport;
45
46extern const char *awt_itemtype_names[]; // names of itemtypes
47
48// --------------------------------------
49//      class awt_input_mask_id_list
50
51class awt_input_mask_id_list {
52private:
53    // maps ids to corresponding input_handlers
54    std::map<std::string, awt_mask_item*> id;
55
56public:
57    awt_input_mask_id_list() {}
58    virtual ~awt_input_mask_id_list() {}
59
60    awt_mask_item *lookup(const std::string& name) const {
61        std::map<std::string, awt_mask_item*>::const_iterator found = id.find(name);
62        return (found == id.end()) ? 0 : found->second;
63    }
64    GB_ERROR add(const std::string& name, awt_mask_item *item);
65    GB_ERROR remove(const std::string& name);
66    bool empty() const { return id.empty(); }
67};
68
69//  ------------------------------------
70//      class awt_input_mask_global
71//     
72// data global to one input mask
73class awt_input_mask_global {
74private:
75    mutable AW_root *awr;
76    mutable GBDATA  *gb_main;
77    //     int              input_mask_id; // unique number of input mask
78    std::string      mask_name; // filename of mask-file
79    std::string      internal_mask_name; // filename of mask-file (prefixed by 0( = local) or 1( = global))
80    std::string      mask_id;   // key generated from mask_name
81    bool             local_mask; // true if mask was found in "~/.arb_prop/inputMasks"
82    awt_item_type    itemtype;  // what kind of item do we handle ?
83
84    bool test_edit_enabled; // true -> the global awar AWAR_INPUT_MASKS_EDIT_ENABLE should be tested before writing to database
85
86    const awt_item_type_selector *sel;
87
88    awt_hotkeys                   hotkeys;
89    awt_input_mask_id_list        ids; // local
90    static awt_input_mask_id_list global_ids;
91
92    static std::string generate_id(const std::string& mask_name_);
93
94
95public:
96    awt_input_mask_global(AW_root *awr_, GBDATA *gb_main_, const std::string& mask_name_, awt_item_type itemtype_, bool local, const awt_item_type_selector *sel_, bool test_edit_enabled_)
97        : awr(awr_)
98        , gb_main(gb_main_)
99        , mask_name(mask_name_)
100        , internal_mask_name(std::string(1, local ? '0' : '1')+mask_name_)
101        , mask_id(generate_id(mask_name_))
102        , local_mask(local)
103        , itemtype(itemtype_)
104        , test_edit_enabled(test_edit_enabled_)
105        , sel(sel_)
106    {
107        awt_assert(mask_name_[0] != '0' && mask_name_[0] != '1');
108    }
109    virtual ~awt_input_mask_global() {
110        awt_assert(ids.empty());
111    }
112
113    bool is_local_mask() const { return local_mask; }
114    AW_root *get_root() const { return awr; }
115    GBDATA *get_gb_main() const { return gb_main; }
116    const std::string& get_maskname() const { return mask_name; }
117    const std::string& get_internal_maskname() const { return internal_mask_name; }
118    std::string get_maskid() const { return mask_id; }
119    awt_item_type get_itemtype() const { return itemtype; }
120    const awt_item_type_selector *get_selector() const { awt_assert(sel); return sel; }
121    const char* hotkey(const std::string& label)  { return hotkeys.hotkey(label); }
122
123    bool has_local_id(const std::string& name) const { return ids.lookup(name); }
124    bool has_global_id(const std::string& name) const { return global_ids.lookup(name); }
125
126    GB_ERROR add_local_id(const std::string& name, awt_mask_item *handler) {
127        if (has_global_id(name)) return GB_export_errorf("ID '%s' already defined as GLOBAL", name.c_str());
128        return ids.add(name, handler);
129    }
130
131    GB_ERROR add_global_id(const std::string& name, awt_mask_item *handler) {
132        if (has_local_id(name)) return GB_export_errorf("ID '%s' already defined as LOCAL", name.c_str());
133        return global_ids.add(name, handler);
134    }
135
136    GB_ERROR remove_local_id(const std::string& name) { return ids.remove(name); }
137//     GB_ERROR remove_global_id(const string& name) { return global_ids.remove(name); }
138    GB_ERROR remove_id(const std::string& name) {
139        if (has_local_id(name)) return remove_local_id(name);
140        if (has_global_id(name)) return 0; // global ids are only created (never removed)
141        return GBS_global_string("ID '%s' not found - can't remove id", name.c_str());
142    }
143
144    awt_mask_item *get_identified_item(const std::string& name, GB_ERROR& error) const {
145        awt_mask_item *found = 0;
146        if (!error) {
147            found             = ids.lookup(name);
148            if (!found) found = global_ids.lookup(name);
149            if (!found) error = GB_export_errorf("No item '%s' declared", name.c_str());
150        }
151        return found;
152    }
153
154    void no_item_selected() const;
155    bool edit_allowed() const;
156};
157
158//  ----------------------------
159//      class awt_mask_item
160//
161// works as base class for all elements of a input-mask
162class awt_mask_item {
163private:
164
165    // basic item members
166    awt_input_mask_global *global; // reference
167    SmartPtr<std::string>       name; // name of this item (optional -- caused i.e. by script command 'ID')
168
169public:
170    awt_mask_item(awt_input_mask_global *global_); // awar_base has to be unique (in every mask)
171    virtual ~awt_mask_item();
172
173    const awt_input_mask_global *mask_global() const { return global; }
174    awt_input_mask_global *mask_global() { return global; }
175
176    bool has_name() const { return !name.Null(); }
177    const std::string& get_name() const { awt_assert(has_name()); return *name; }
178    GB_ERROR set_name(const std::string& name_, bool is_global);
179    GB_ERROR remove_name();
180
181    inline const awt_viewport *to_viewport(bool fail = true) const;
182    inline awt_viewport *to_viewport(bool fail = true);
183
184    inline const awt_linked_to_item *to_linked_item(bool fail = true) const;
185    inline awt_linked_to_item *to_linked_item(bool fail = true);
186//     inline const awt_input_handler *to_input_handler(bool fail = true) const;
187//     inline awt_input_handler *to_input_handler(bool fail = true);
188//
189//     inline const awt_script_viewport *to_script_viewport(bool fail = true) const;
190//     inline awt_script_viewport *to_script_viewport(bool fail = true);
191
192    bool is_viewport() const { return to_viewport(0) != 0; }
193    bool is_linked_item() const { return to_linked_item(0) != 0; }
194//     bool is_input_handler() const { return to_input_handler(0) != 0; }
195//     bool is_script_viewport() const { return to_script_viewport(0) != 0; }
196
197    virtual std::string get_value() const                    = 0; // reads the current value of the item
198    virtual GB_ERROR set_value(const std::string& new_value) = 0; // assigns a new value to the item
199};
200
201//  --------------------------------
202//      class awt_mask_awar_item
203//
204// holds an awar
205class awt_mask_awar_item :  public awt_mask_item {
206private:
207    // awar related members
208    std::string     awarName;        // name of the awar
209
210protected:
211
212    void add_awar_callbacks();
213    void remove_awar_callbacks();
214
215public:
216    awt_mask_awar_item(awt_input_mask_global *global_, const std::string& awar_base, const std::string& default_value, bool saved_with_properties);
217    virtual ~awt_mask_awar_item() { remove_awar_callbacks(); }
218
219    virtual void awar_changed() = 0; // called when awar changes
220
221    std::string awar_name() const  { return awarName; }
222    const AW_awar *awar() const { return mask_global()->get_root()->awar(awarName.c_str()); }
223    AW_awar *awar() { return mask_global()->get_root()->awar(awarName.c_str()); }
224
225    virtual std::string get_value() const {  // reads the current value of the item
226        return const_cast<AW_awar*>(awar())->read_string();
227    }
228    virtual GB_ERROR set_value(const std::string& new_value) { // assigns a new value to the item
229        awar()->write_string(new_value.c_str());
230        return 0; // an overloaded method may return an error
231    }
232};
233
234// ---------------------------
235//      class awt_viewport
236//
237// awar bound to a widget
238class awt_viewport : public awt_mask_awar_item {
239private:
240    std::string label;               // label of viewport
241
242public:
243    awt_viewport(awt_input_mask_global *global_, const std::string& awar_base, const std::string& default_value, bool saved_with_properties, const std::string& label_)
244        : awt_mask_awar_item(global_, awar_base, default_value, saved_with_properties)
245        , label(label_)
246    {}
247    awt_viewport(const awt_mask_awar_item& ref_item, const std::string& label_)
248        : awt_mask_awar_item(ref_item)
249        , label(label_)
250    {}
251    virtual ~awt_viewport() {}
252
253    const std::string& get_label() const { return label; }
254    virtual void build_widget(AW_window *aws) = 0; // builds the widget at the current position
255};
256
257// ---------------------------
258//      class awt_variable
259//
260// awar NOT bound to widget; is saved in properties
261class awt_variable : public awt_mask_awar_item {
262private:
263    bool is_global;
264
265    static std::string generate_baseName(const awt_input_mask_global *global_, const std::string& id, bool is_global_) {
266        // the generated name is NOT enumerated, because any reference to a variable should
267        // work on the same awar
268        return
269            is_global_
270            ? std::string("global_")+id
271            : std::string(GBS_global_string("local_%s_%s", global_->get_maskid().c_str(), id.c_str()));
272    }
273public:
274    awt_variable(awt_input_mask_global *global_, const std::string& id, bool is_global_, const std::string& default_value, GB_ERROR& error);
275    virtual ~awt_variable();
276    virtual void awar_changed() {
277#if defined(DEBUG)
278        printf("awt_variable was changed\n");
279#endif // DEBUG
280    }
281};
282
283
284//  ------------------------
285//      class awt_script
286//     
287class awt_script : public awt_mask_item {
288private:
289    std::string script;
290
291public:
292    awt_script(awt_input_mask_global *global_, const std::string& script_)
293        : awt_mask_item(global_)
294        , script(script_)
295    {}
296    virtual ~awt_script() {}
297
298    virtual std::string get_value() const; // reads the current value of the item
299    virtual GB_ERROR set_value(const std::string& /*new_value*/); // assigns a new value to the item
300};
301
302//  ---------------------------------
303//      class awt_linked_to_item
304//
305class awt_linked_to_item {
306private:
307    GBDATA                *gb_item; // item this handler is linked to
308    // if gb_item == 0 then no callbacks are installed
309
310protected:
311
312    virtual GB_ERROR add_db_callbacks();
313    virtual void     remove_db_callbacks();
314
315    void set_item(GBDATA *new_item) {
316#if defined(DEBUG)
317        printf("gb_item=%p new_item=%p\n", gb_item, new_item);
318#endif // DEBUG
319        gb_item = new_item;
320    }
321
322public:
323    awt_linked_to_item() : gb_item(0) {}
324    virtual ~awt_linked_to_item() {
325        /* unlink(); calling unlink does not work here, because it may cause a pure virtual call */
326        awt_assert(!gb_item); // you forgot to call awt_linked_to_item::unlink from where you destroy 'this'
327    }
328
329    GBDATA *item() { return gb_item; }
330    virtual GB_ERROR link_to(GBDATA *gb_new_item) = 0; // link to a new item
331
332    GB_ERROR unlink() { return link_to(0); }
333    virtual GB_ERROR relink() = 0; // used by callbacks to relink awt_input_handler
334
335    virtual void general_item_change() {} // called if item was changed (somehow)
336};
337
338
339//  ---------------------------------
340//      class awt_script_viewport
341//
342class awt_script_viewport : public awt_viewport, public awt_linked_to_item {
343private:
344    const awt_script *script;
345    int               field_width;
346
347    static std::string generate_baseName(const awt_input_mask_global *global_) {
348        static int awar_counter = 0;
349        return GBS_global_string("%s/scriptview_%i", global_->get_maskid().c_str(), awar_counter++);
350    }
351
352public:
353    awt_script_viewport(awt_input_mask_global *global_, const awt_script *script_, const std::string& label_, long field_width_);
354    virtual ~awt_script_viewport();
355
356    virtual GB_ERROR link_to(GBDATA *gb_new_item); // link to a new item
357    virtual GB_ERROR relink() { return link_to(mask_global()->get_selector()->current(mask_global()->get_root())); }
358
359    virtual void build_widget(AW_window *aws); // builds the widget at the current position
360    virtual void awar_changed();
361    virtual void db_changed();
362};
363
364
365//  --------------------------------
366//      class awt_input_handler
367//
368// an awt_input_handler is an awt_viewport bound to a database element
369class awt_input_handler : public awt_viewport, public awt_linked_to_item {
370private:
371    GBDATA   *gbd;              // link to database
372    std::string    child_path;       // path in database from item to handled child
373    GB_TYPES  db_type;          // type of database field
374    bool      in_destructor;
375
376    virtual GB_ERROR add_db_callbacks();
377    virtual void     remove_db_callbacks();
378
379    static std::string generate_baseName(const awt_input_mask_global *global_, const std::string& child_path) {
380        // the generated name is enumerated to allow different awt_input_handler's to be linked
381        // to the same child_path
382        static int awar_counter = 0;
383        return GBS_global_string("%s/handler_%s_%i", global_->get_maskid().c_str(), child_path.c_str(), awar_counter++);
384    }
385
386
387public:
388    awt_input_handler(awt_input_mask_global *global_, const std::string& child_path_, GB_TYPES type_, const std::string& label_);
389    virtual ~awt_input_handler();
390
391    virtual GB_ERROR link_to(GBDATA *gb_new_item); // link to a new item
392    virtual GB_ERROR relink() { return link_to(mask_global()->get_selector()->current(mask_global()->get_root())); }
393
394    GBDATA *data() { return gbd; }
395
396    GB_TYPES type() const { return db_type; }
397    void set_type(GB_TYPES typ) { db_type = typ; }
398
399    const std::string& get_child_path() const { return child_path; }
400
401    // callbacks are handled via the following virtual functions :
402    virtual void db_changed()   = 0;
403};
404
405typedef SmartPtr<awt_input_handler> awt_input_handler_ptr;
406typedef std::list<awt_input_handler_ptr> awt_input_handler_list;
407typedef SmartPtr<awt_mask_item>     awt_mask_item_ptr;
408typedef std::list<awt_mask_item_ptr>     awt_mask_item_list;
409
410//  --------------------------------
411//      class awt_string_handler
412//
413// this handler handles string fields
414class awt_string_handler : public awt_input_handler {
415private:
416    std::string  default_value;      // default value for awar if no data present
417
418public:
419    awt_string_handler(awt_input_mask_global *global_, const std::string& child_path_, const std::string& default_awar_value_, GB_TYPES default_type, const std::string& label_)
420        : awt_input_handler(global_, child_path_, default_type, label_)
421        , default_value(default_awar_value_)
422    {
423//         mask_global()->get_root()->awar_string(awar_name().c_str(), default_value.c_str()); // generate a string AWAR (now done by awt_mask_item)
424    }
425    virtual ~awt_string_handler() {}
426
427    virtual void awar_changed();
428    virtual void db_changed();
429
430    virtual std::string awar2db(const std::string& awar_content) const { return awar_content; }
431    virtual std::string db2awar(const std::string& db_content) const { return db_content; }
432
433    virtual void build_widget(AW_window *aws) = 0; // builds the widget at the current position
434};
435
436//  ------------------------------
437//      class awt_input_field
438//
439// awt_input_field holds a text field bound to a database string field
440class awt_input_field : public awt_string_handler {
441private:
442    int    field_width;
443
444public:
445    awt_input_field(awt_input_mask_global *global_, const std::string& child_path_, const std::string& label_, int field_width_, const std::string& default_value_, GB_TYPES default_type)
446        : awt_string_handler(global_, child_path_, default_value_, default_type, label_)
447        , field_width(field_width_)
448    { }
449    virtual ~awt_input_field() {}
450
451    virtual void build_widget(AW_window *aws);
452};
453
454//  -------------------------------
455//      class awt_text_viewport
456//
457class awt_text_viewport : public awt_viewport {
458private:
459    int    field_width;
460
461public:
462    awt_text_viewport(const awt_mask_awar_item *item, const std::string& label_, long field_width_)
463        : awt_viewport(*item, label_)
464        , field_width(field_width_)
465    {}
466    virtual ~awt_text_viewport() {}
467
468    virtual void awar_changed()  {
469#if defined(DEBUG)
470        printf("awt_text_viewport awar changed!\n");
471#endif // DEBUG
472    }
473    virtual void build_widget(AW_window *aws);
474};
475
476
477//  -------------------------------------
478//      class awt_numeric_input_field
479//
480class awt_numeric_input_field : public awt_input_field {
481private:
482    long min, max;
483
484public:
485    awt_numeric_input_field(awt_input_mask_global *global_, const std::string& child_path_, const std::string& label_, int field_width_, long default_value_, long min_, long max_)
486        : awt_input_field(global_, child_path_, label_, field_width_, GBS_global_string("%li", default_value_), GB_FLOAT)
487        , min(min_)
488        , max(max_)
489    {}
490    virtual ~awt_numeric_input_field() {}
491
492    virtual std::string awar2db(const std::string& awar_content) const;
493};
494
495
496//  ---------------------------
497//      class awt_check_box
498//
499class awt_check_box : public awt_string_handler {
500private:
501
502public:
503    awt_check_box(awt_input_mask_global *global_, const std::string& child_path_, const std::string& label_, bool default_checked)
504        : awt_string_handler(global_, child_path_, default_checked ? "yes" : "no", GB_BITS, label_)
505    {}
506    virtual ~awt_check_box() {}
507
508    virtual std::string awar2db(const std::string& awar_content) const;
509    virtual std::string db2awar(const std::string& db_content) const;
510
511    virtual void build_widget(AW_window *aws);
512};
513
514//  ------------------------------
515//      class awt_radio_button
516//
517class awt_radio_button : public awt_string_handler {
518private:
519    int            default_position;
520    bool           vertical;
521    std::vector<std::string> buttons; // the awar contains the names of the buttons
522    std::vector<std::string> values; // the database contains the names of the values
523
524public:
525    awt_radio_button(awt_input_mask_global *global_, const std::string& child_path_, const std::string& label_, int default_position_, bool vertical_, const std::vector<std::string>& buttons_, const std::vector<std::string>& values_)
526        : awt_string_handler(global_, child_path_, buttons_[default_position_], GB_STRING, label_)
527        , default_position(default_position_)
528        , vertical(vertical_)
529        , buttons(buttons_)
530        , values(values_)
531    {
532        awt_assert(buttons.size() == values.size());
533    }
534    virtual ~awt_radio_button() {}
535
536    virtual std::string awar2db(const std::string& awar_content) const;
537    virtual std::string db2awar(const std::string& db_content) const;
538
539    virtual void build_widget(AW_window *aws);
540
541    size_t no_of_toggles() const { return buttons.size(); }
542    size_t default_toggle() const { return default_position; }
543};
544
545
546//  -----------------------------
547//      class awt_input_mask
548//
549// awt_input_mask holds the description of an input mask.
550// an input mask is an i/o-interface to a database entry.
551
552class awt_input_mask {
553private:
554//     string                 mask_name;
555    awt_input_mask_global  global;
556    awt_mask_item_list     handlers;
557    AW_window_simple      *aws;
558    bool                   shall_reload_on_reinit;
559
560public:
561    awt_input_mask(AW_root *awr, GBDATA *gb_main, const std::string& mask_name_, awt_item_type itemtype_, bool local, const awt_item_type_selector *sel_, bool test_edit_enabled)
562        : global(awr, gb_main, mask_name_, itemtype_, local, sel_, test_edit_enabled)
563        , aws(0)
564        , shall_reload_on_reinit(false)
565    {}
566    // Initialisation is done in awt_create_input_mask
567    // see also :  AWT_initialize_input_mask
568
569    virtual ~awt_input_mask();
570
571    void show() { aws->activate(); }
572    void hide() { aws->hide(); }
573
574    void set_reload_on_reinit(bool dest) { shall_reload_on_reinit = dest; }
575    bool reload_on_reinit() { return shall_reload_on_reinit; }
576
577    AW_window_simple*& get_window() { return aws; }
578
579    const awt_input_mask_global *mask_global() const { return &global; }
580    awt_input_mask_global *mask_global() { return &global; }
581
582    void add_handler(awt_mask_item_ptr handler) { handlers.push_back(handler); }
583
584    void relink(bool unlink = false); // if unlink is true -> mask is unlinked from database
585};
586
587//  ----------------
588//      casts :
589
590inline const awt_linked_to_item *awt_mask_item::to_linked_item(bool fail) const { const awt_linked_to_item *linked = dynamic_cast<const awt_linked_to_item*>(this); AWUSE(fail); awt_assert(!fail || linked); return linked; }
591inline awt_linked_to_item *awt_mask_item::to_linked_item(bool fail) { awt_linked_to_item *linked = dynamic_cast< awt_linked_to_item*>(this); AWUSE(fail); awt_assert(!fail || linked); return linked; }
592
593inline const awt_viewport *awt_mask_item::to_viewport(bool fail) const { const awt_viewport *viewport = dynamic_cast<const awt_viewport*>(this); AWUSE(fail); awt_assert(!fail || viewport); return viewport; }
594inline awt_viewport *awt_mask_item::to_viewport(bool fail)  { awt_viewport *viewport = dynamic_cast<awt_viewport*>(this); AWUSE(fail); awt_assert(!fail || viewport); return viewport; }
595
596// inline const awt_input_handler *awt_mask_item::to_input_handler(bool fail) const { const awt_input_handler *handler = dynamic_cast<const awt_input_handler*>(this); awt_assert(!fail || handler); return handler; }
597// inline awt_input_handler *awt_mask_item::to_input_handler(bool fail)  { awt_input_handler *handler = dynamic_cast<awt_input_handler*>(this); awt_assert(!fail || handler); return handler; }
598//
599// inline const awt_script_viewport *awt_mask_item::to_script_viewport(bool fail) const { const awt_script_viewport *viewport = dynamic_cast<const awt_script_viewport*>(this); awt_assert(!fail || viewport); return viewport; }
600// inline awt_script_viewport *awt_mask_item::to_script_viewport(bool fail)  { awt_script_viewport *viewport = dynamic_cast<awt_script_viewport*>(this); awt_assert(!fail || viewport); return viewport; }
601
602#else
603#error awt_input_mask_internal.hxx included twice
604#endif // AWT_INPUT_MASK_INTERNAL_HXX
Note: See TracBrowser for help on using the repository browser.