source: tags/ms_r16q3/SL/DB_UI/info_window.h

Last change on this file was 11018, checked in by westram, 10 years ago
  • added compatibility wrapper for unordered_map (arb_unordered_map)
  • use arb_unordered_map somewhere
File size: 5.9 KB
Line 
1// ============================================================ //
2//                                                              //
3//   File      : info_window.h                                  //
4//   Purpose   :                                                //
5//                                                              //
6//   Coded by Ralf Westram (coder@reallysoft.de) in July 2013   //
7//   Institute of Microbiology (Technical University Munich)    //
8//   http://www.arb-home.de/                                    //
9//                                                              //
10// ============================================================ //
11
12#ifndef INFO_WINDOW_H
13#define INFO_WINDOW_H
14
15#ifndef AW_WINDOW_HXX
16#include <aw_window.hxx>
17#endif
18#ifndef DB_SCANNER_HXX
19#include <db_scanner.hxx>
20#endif
21#ifndef ARB_MSG_H
22#include <arb_msg.h>
23#endif
24#ifndef ARBDBT_H
25#include <arbdbt.h>
26#endif
27#ifndef ARB_UNORDERED_MAP_H
28#include <arb_unordered_map.h>
29#endif
30
31// --------------------
32//      InfoWindow
33
34class InfoWindow : virtual Noncopyable {
35    AW_window *aww;
36    DbScanner *scanner;
37    int        detach_id;
38
39    mutable bool used; // window in use (i.e. not yet popped down)
40
41    const ItemSelector& getSelector() const { return get_itemSelector_of(scanner); }
42    QUERY_ITEM_TYPE itemtype() const { return getSelector().type; }
43    const char *itemname() const { return getSelector().item_name; }
44
45    AW_root *get_root() const { return aww->get_root(); }
46
47    void update_window_title() const {
48        if (is_detached()) { // only change window titles of detached windows
49            char *title         = NULL;
50            char *mapped_item = get_id_of_item_mapped_in(scanner);
51            if (mapped_item) {
52                title = GBS_global_string_copy("%s information (%s)", mapped_item, itemname());
53                free(mapped_item);
54            }
55            else {
56                title = GBS_global_string_copy("Press 'Update' to attach selected %s", itemname());
57            }
58
59            arb_assert(title);
60            aww->set_window_title(title);
61            free(title);
62        }
63    }
64
65public:
66
67    static const int MAIN_WINDOW = 0;
68    typedef SmartPtr<InfoWindow> Ptr;
69    typedef void (*detached_uppopper)(AW_window*, const InfoWindow*);
70
71    InfoWindow(AW_window *aww_, DbScanner *scanner_, int detach_id_)
72        : aww(aww_),
73          scanner(scanner_),
74          detach_id(detach_id_),
75          used(true)
76    {}
77    ~InfoWindow() {
78        // @@@ should free 'scanner'
79    }
80
81    bool is_detached() const { return detach_id>MAIN_WINDOW; }
82    bool is_maininfo() const { return detach_id == MAIN_WINDOW; }
83    int getDetachID() const { return detach_id; }
84
85    GBDATA *get_gbmain() const { return get_db_scanner_main(scanner); }
86
87    bool is_used() const { return used; }
88    void set_used(bool used_) const {
89        arb_assert(!is_maininfo()); // cannot change for maininfo window (it is never reused!)
90        used = used_;
91    }
92
93    bool mapsOrganism() const {
94        const ItemSelector& sel = getSelector();
95
96        return
97            (sel.type == QUERY_ITEM_SPECIES) &&
98            (strcmp(sel.item_name, "organism") == 0);
99    }
100    bool handlesSameItemtypeAs(const InfoWindow& other) const {
101        QUERY_ITEM_TYPE type = itemtype();
102        if (type == other.itemtype()) {
103            return type != QUERY_ITEM_SPECIES || mapsOrganism() == other.mapsOrganism();
104        }
105        return false;
106    }
107
108    GBDATA *get_selected_item() const {
109        GBDATA         *gb_main = get_gbmain();
110        GB_transaction  ta(gb_main);
111        return getSelector().get_selected_item(gb_main, get_root());
112    }
113
114    void map_item(GBDATA *gb_item) const {
115        map_db_scanner(scanner, gb_item, getSelector().change_key_path);
116    }
117    void map_selected_item() const { map_item(get_selected_item()); }
118    void attach_selected_item() const {
119        map_selected_item();
120        update_window_title();
121    }
122    void reuse() const {
123        set_used(true);
124        aww->activate();
125        attach_selected_item();
126    }
127
128    void bind_to_selected_item() const;
129    void add_detachOrGet_button(detached_uppopper popup_detached_cb) const;
130
131    void display_selected_item() const;
132    void detach_selected_item(detached_uppopper popup_detached_cb) const;
133};
134
135class InfoWindowRegistry {
136    typedef arb_unordered_map<AW_window*, InfoWindow::Ptr> WinMap;
137    WinMap win;
138
139    InfoWindowRegistry(){} // InfoWindowRegistry is a singleton and always exists
140
141public:
142    const InfoWindow& registerInfoWindow(AW_window *aww, DbScanner *scanner, int detach_id) {
143        // registers a new instance of an InfoWindow
144        // returned reference is persistent
145        arb_assert(aww && scanner);
146        arb_assert(detach_id >= InfoWindow::MAIN_WINDOW);
147
148        arb_assert(!find(aww));
149
150        win[aww] = new InfoWindow(aww, scanner, detach_id);
151        return *win[aww];
152    }
153
154    const InfoWindow* find(AW_window *aww) {
155        // returns InfoWindow for 'aww' (or NULL if no such InfoWindow)
156        WinMap::iterator found = win.find(aww);
157        return found == win.end() ? NULL : &*found->second;
158    }
159
160    int allocate_detach_id(const InfoWindow& other) {
161        arb_assert(other.is_maininfo());
162
163        int maxUsedID = InfoWindow::MAIN_WINDOW;
164        for (WinMap::iterator i = win.begin(); i != win.end(); ++i) {
165            const InfoWindow::Ptr& info = i->second;
166            if (info->handlesSameItemtypeAs(other)) {
167                maxUsedID = std::max(maxUsedID, info->getDetachID());
168            }
169        }
170        return maxUsedID+1;
171    }
172    const InfoWindow *find_reusable_of_same_type_as(const InfoWindow& other) {
173        for (WinMap::iterator i = win.begin(); i != win.end(); ++i) {
174            const InfoWindow::Ptr& info = i->second;
175            if (info->handlesSameItemtypeAs(other) && !info->is_used()) return &*info;
176        }
177        return NULL;
178    }
179
180    static InfoWindowRegistry infowin;
181};
182
183#else
184#error info_window.h included twice
185#endif // INFO_WINDOW_H
Note: See TracBrowser for help on using the repository browser.