source: trunk/SL/DB_UI/info_window.h

Last change on this file was 18211, checked in by westram, 5 years ago
  • add new QUERY_ITEM_TYPE for organisms: QUERY_ITEM_ORGANISM
File size: 6.7 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 scanner->get_selector(); }
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         = NULp;
50            char *mapped_item = scanner->get_mapped_item_id();
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 scanner->get_gb_main(); }
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        return itemtype() == QUERY_ITEM_ORGANISM;
95    }
96    bool handlesSameItemtypeAs(const InfoWindow& other) const {
97        return itemtype() == other.itemtype();
98    }
99
100    GBDATA *get_selected_item() const {
101        GBDATA         *gb_main = get_gbmain();
102        GB_transaction  ta(gb_main);
103        return getSelector().get_selected_item(gb_main, get_root());
104    }
105
106    void map_item(GBDATA *gb_item) const {
107        scanner->Map(gb_item, getSelector().change_key_path);
108    }
109    void map_selected_item() const { map_item(get_selected_item()); }
110    void attach_selected_item() const {
111        map_selected_item();
112        update_window_title();
113    }
114    void reuse() const {
115        arb_assert(is_detached());
116        set_used(true);
117        aww->activate();
118        attach_selected_item();
119    }
120    void reactivate() const {
121        arb_assert(is_maininfo());
122        arb_assert(is_used());
123        aww->activate();     // popup existing window
124        map_selected_item(); // force item update (did not follow while it was popped-down)
125    }
126    void hide() const { aww->hide(); }
127
128    void bind_to_selected_item() const;
129    void add_detach_area(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 NULp if no such InfoWindow)
156        WinMap::iterator found = win.find(aww);
157        return found == win.end() ? NULp : &*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 NULp;
178    }
179    const InfoWindow *find_maininfo_of_same_type_as(const InfoWindow& other) {
180        for (WinMap::iterator i = win.begin(); i != win.end(); ++i) {
181            const InfoWindow::Ptr& info = i->second;
182            if (info->handlesSameItemtypeAs(other) && info->is_used() && info->is_maininfo()) return &*info;
183        }
184        return NULp;
185    }
186
187    static InfoWindowRegistry infowin;
188
189    static void reactivate(AW_window *aww)  {
190        const InfoWindow *iwin = infowin.find(aww);
191        arb_assert(iwin); // not called with an info-window
192        if (iwin) iwin->reactivate();
193    }
194
195    static const char *localize_scanner_id(const char *scanner_id, int detach_id) {
196        return detach_id == InfoWindow::MAIN_WINDOW
197            ? scanner_id
198            : GBS_global_string("%s_%i", scanner_id, detach_id);
199    }
200};
201
202#else
203#error info_window.h included twice
204#endif // INFO_WINDOW_H
Note: See TracBrowser for help on using the repository browser.