source: trunk/SL/MASKS/input_mask_internal.hxx

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