source: branches/stable/GENOM/GEN_graphic.cxx

Last change on this file was 17944, checked in by westram, 5 years ago
  • FIXES crash in RELEASE version (when invalid color group occurs in database).
  • add assertions against
    • invalid color_groups and
    • invalid unshaded GCs.
  • ARBDB color-group interface:
    • define number of allowed color groups in ARBDB
    • fix interface types (long→int)
    • report error when color_group passed to GBT_set_color_group is out-of-range.
    • GBT_get_color_group does range check. returns 0 if out-of-range.
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 16.0 KB
Line 
1// =============================================================== //
2//                                                                 //
3//   File      : GEN_graphic.cxx                                   //
4//   Purpose   :                                                   //
5//                                                                 //
6//   Coded by Ralf Westram (coder@reallysoft.de) in 2001           //
7//   Institute of Microbiology (Technical University Munich)       //
8//   http://www.arb-home.de/                                       //
9//                                                                 //
10// =============================================================== //
11
12#include "GEN_local.hxx"
13#include "GEN_gene.hxx"
14#include "GEN_graphic.hxx"
15
16#include <arbdbt.h>
17
18#include <aw_awar.hxx>
19#include <aw_preset.hxx>
20#include <aw_msg.hxx>
21#include <aw_root.hxx>
22
23#include <climits>
24
25using namespace std;
26using namespace AW;
27
28// ---------------------
29//      GEN_graphic
30
31GEN_graphic::GEN_graphic(AW_root *aw_root_, GBDATA *gb_main_, GEN_graphic_cb_installer callback_installer_, int window_nr_)
32    : aw_root(aw_root_),
33      gb_main(gb_main_),
34      callback_installer(callback_installer_),
35      window_nr(window_nr_),
36      gen_root(NULp),
37      disp_device(NULp)
38{
39    exports.set_standard_default_padding();
40
41    LocallyModify<int> allow_flag_modify(exports.get_modifying_flag_ref(), -1); // delays zoom-reset triggered by set_display_style
42    set_display_style(GEN_DisplayStyle(aw_root->awar(AWAR_GENMAP_DISPLAY_TYPE(window_nr))->read_int()));
43}
44
45GEN_graphic::~GEN_graphic() {}
46
47AW_gc_manager *GEN_graphic::init_devices(AW_window *aww, AW_device *device, AWT_canvas *scr) {
48    disp_device = device;
49
50    AW_gc_manager *gc_manager =
51        AW_manage_GC(aww,
52                     scr->get_gc_base_name(),
53                     device,
54                     GEN_GC_MAX, AW_GCM_DATA_AREA,
55                     makeGcChangedCallback(AWT_GC_changed_cb, scr),
56                     "#55C0AA",
57                     "Default$#5555ff",
58                     "Gene$#000000",
59                     "Marked$#ffff00",
60                     "Cursor$#ff0000",
61
62                     "&color_groups", // use color groups
63
64                     NULp);
65
66    return gc_manager;
67}
68
69void GEN_graphic::show(AW_device *device) {
70    if (gen_root) {
71#if defined(DEBUG) && 0
72        fprintf(stderr, "GEN_graphic::show\n");
73#endif // DEBUG
74
75        gen_root->paint(device);
76    }
77    else {
78        device->line(GEN_GC_DEFAULT, -100, -100, 100, 100);
79        device->line(GEN_GC_DEFAULT, -100, 100, 100, -100);
80    }
81}
82
83void GEN_graphic::check_for_DB_update(GBDATA *) {
84}
85
86void GEN_graphic::handle_command(AW_device *, AWT_graphic_event& event) {
87    if (event.type() == AW_Mouse_Press) {
88        switch (event.cmd()) {
89            case AWT_MODE_ZOOM: {
90                break;
91            }
92            case AWT_MODE_SELECT:
93            case AWT_MODE_INFO: {
94                if (event.button()==AW_BUTTON_LEFT) {
95                    const AW_clicked_element *clicked = event.best_click();
96                    if (clicked) {
97                        GEN_gene *gene = (GEN_gene*)clicked->cd1();
98                        if (gene) {
99                            GB_transaction ta(gb_main);
100                            aw_root->awar(AWAR_LOCAL_GENE_NAME(window_nr))->write_string(gene->Name().c_str());
101
102                            if (event.cmd() == AWT_MODE_INFO) {
103                                GEN_popup_gene_infowindow(aw_root, gb_main);
104                            }
105                        }
106                    }
107                }
108                break;
109            }
110            default: {
111                gen_assert(0);
112                break;
113            }
114        }
115    }
116}
117
118inline int GEN_root::smart_text(AW_device *device, int gc, const char *str, AW_pos x, AW_pos y) {
119    SizedCstr cstr(str);
120    int       res = device->text(gc, cstr, x, y);
121    if (gc == GEN_GC_CURSOR) {
122        int                   xsize = device->get_string_size(gc, cstr);
123        const AW_font_limits& lim   = device->get_font_limits(gc, 0);
124
125        Position  stext = device->transform(Position(x, y));
126        Rectangle srect(stext.xpos(), stext.ypos()-lim.ascent, stext.xpos()+xsize, stext.ypos()+lim.descent);
127        Rectangle wrect = device->rtransform(srect);
128        increase_selected_range(wrect);
129    }
130    return res;
131}
132
133inline int GEN_root::smart_line(AW_device *device, int gc, AW_pos x0, AW_pos y0, AW_pos x1, AW_pos y1) {
134    int res = device->line(gc, x0, y0, x1, y1);
135    if (gc == GEN_GC_CURSOR) increase_selected_range(Rectangle(x0, y0, x1, y1));
136    return res;
137}
138
139enum PaintWhat {
140    PAINT_MIN,
141
142    PAINT_NORMAL = PAINT_MIN,
143    PAINT_COLORED,
144    PAINT_MARKED,
145    PAINT_SELECTED,
146
147    PAINT_MAX = PAINT_SELECTED,
148    PAINT_COUNT, // has to be last (do NOT remove)
149};
150
151inline bool getDrawGcs(GEN_iterator& gene, PaintWhat what, const string& curr_gene_name, int& draw_gc, int& text_gc) {
152    bool draw = false;
153    if (curr_gene_name == gene->Name()) { // current gene
154        draw_gc = text_gc = GEN_GC_CURSOR;
155        draw    = (what == PAINT_SELECTED);
156    }
157    else {
158        GBDATA *gb_gene = (GBDATA*)gene->GbGene();
159
160        if (GB_read_flag(gb_gene)) { // marked genes
161            draw_gc = text_gc = GEN_GC_MARKED;
162            draw    = (what == PAINT_MARKED);
163        }
164        else {
165            int color_group = AW_color_groups_active() ? GBT_get_color_group(gb_gene) : 0;
166            if (color_group) {
167                draw_gc = text_gc = GEN_GC_FIRST_COLOR_GROUP+color_group-1;
168                draw    = (what == PAINT_COLORED);
169            }
170            else {
171                draw_gc = GEN_GC_GENE;
172                text_gc = GEN_GC_DEFAULT; // see show_all_nds in GEN_root::paint if you change this!!!
173                draw    = (what == PAINT_NORMAL);
174            }
175        }
176    }
177    return draw;
178}
179
180void GEN_root::paint(AW_device *device) {
181    if (error_reason.length()) {
182        device->text(GEN_GC_DEFAULT, error_reason.c_str(), 0, 0);
183        return;
184    }
185
186    clear_selected_range();
187
188    AW_root *aw_root      = gen_graphic->get_aw_root();
189    int      arrow_size   = aw_root->awar(AWAR_GENMAP_ARROW_SIZE)->read_int();
190    int      show_all_nds = aw_root->awar(AWAR_GENMAP_SHOW_ALL_NDS)->read_int();
191
192    for (PaintWhat paint_what = PAINT_MIN; paint_what <= PAINT_MAX; paint_what = PaintWhat((int(paint_what)+1))) {
193        switch (gen_graphic->get_display_style()) {
194            case GEN_DISPLAY_STYLE_RADIAL: {
195                double w0      = 2.0*M_PI/double(length);
196                double mp2     = M_PI/2;
197                double inside  = aw_root->awar(AWAR_GENMAP_RADIAL_INSIDE)->read_float()*1000;
198                double outside = aw_root->awar(AWAR_GENMAP_RADIAL_OUTSIDE)->read_float();
199
200                GEN_iterator curr = gene_set.begin();
201                GEN_iterator end  = gene_set.end();
202
203                while (curr != end) {
204                    int draw_gc, text_gc;
205                    if (getDrawGcs(curr, paint_what, gene_name, draw_gc, text_gc)) {
206                        double w    = w0*curr->StartPos()-mp2;
207                        double sinw = sin(w);
208                        double cosw = cos(w);
209                        int    len  = curr->Length();
210
211                        int xi = int(cosw*inside+0.5);
212                        int yi = int(sinw*inside+0.5);
213                        int xo = xi+int(cosw*outside*len+0.5);
214                        int yo = yi+int(sinw*outside*len+0.5);
215
216                        AW_click_cd cd(device, (AW_CL)&*curr);
217                        if (show_all_nds || text_gc != GEN_GC_DEFAULT) {
218                            smart_text(device, text_gc, curr->NodeInfo().c_str(), xo+20, yo);
219                        }
220                        smart_line(device, draw_gc, xi, yi, xo, yo);
221
222                        int sa = int(sinw*arrow_size+0.5);
223                        int ca = int(cosw*arrow_size+0.5);
224
225                        if (curr->Complement()) {
226                            int xa = xi-sa+ca;
227                            int ya = yi+ca+sa;
228                            smart_line(device, draw_gc, xi, yi, xa, ya);
229                        }
230                        else {
231                            int xa = xo+sa-ca;
232                            int ya = yo-ca-sa;
233                            smart_line(device, draw_gc, xo, yo, xa, ya);
234                        }
235                    }
236                    ++curr;
237                }
238                break;
239            }
240            case GEN_DISPLAY_STYLE_VERTICAL: {
241                float factor_x = aw_root->awar(AWAR_GENMAP_VERTICAL_FACTOR_X)->read_float();
242                float factor_y = aw_root->awar(AWAR_GENMAP_VERTICAL_FACTOR_Y)->read_float();
243                int   arrow_x  = int(factor_x*arrow_size);
244                int   arrow_y  = int(factor_y*arrow_size);
245
246                GEN_iterator curr = gene_set.begin();
247                GEN_iterator end  = gene_set.end();
248
249                while (curr != end) {
250                    int draw_gc, text_gc;
251                    if (getDrawGcs(curr, paint_what, gene_name, draw_gc, text_gc)) {
252                        int y         = int(curr->StartPos()*factor_y+0.5);
253                        int x2        = int(curr->Length()*factor_x+0.5);
254
255                        AW_click_cd cd(device, (AW_CL)&*curr);
256                        if (show_all_nds || text_gc != GEN_GC_DEFAULT) {
257                            smart_text(device, text_gc, curr->NodeInfo().c_str(), x2+20, y);
258                        }
259                        smart_line(device, draw_gc, 0, y, x2, y);
260                        if (curr->Complement()) {
261                            smart_line(device, draw_gc, 0, y, arrow_x, y-arrow_y);
262                        }
263                        else {
264                            smart_line(device, draw_gc, x2, y, x2-arrow_x, y-arrow_y);
265                        }
266                    }
267                    ++curr;
268                }
269                break;
270            }
271            case GEN_DISPLAY_STYLE_BOOK: {
272                int   display_width  = aw_root->awar(AWAR_GENMAP_BOOK_BASES_PER_LINE)->read_int();
273                float width_factor   = aw_root->awar(AWAR_GENMAP_BOOK_WIDTH_FACTOR)->read_float();
274                int   line_height    = aw_root->awar(AWAR_GENMAP_BOOK_LINE_HEIGHT)->read_int();
275                int   line_space     = aw_root->awar(AWAR_GENMAP_BOOK_LINE_SPACE)->read_int();
276                int   height_of_line = line_height+line_space;
277                int   xLeft          = 0;
278                int   xRight         = int(display_width*width_factor+0.5);
279                int   arrowMid       = line_height/2;
280
281                GEN_iterator curr = gene_set.begin();
282                GEN_iterator end  = gene_set.end();
283
284                while (curr != end) {
285                    int draw_gc, text_gc;
286                    if (getDrawGcs(curr, paint_what, gene_name, draw_gc, text_gc)) {
287                        int line1 = curr->StartPos()/display_width;
288                        int line2 = curr->EndPos()  / display_width;
289                        int x1    = int((curr->StartPos()-line1*display_width)*width_factor+0.5);
290                        int x2    = int((curr->EndPos()  -line2*display_width)*width_factor+0.5);
291                        int y1    = line1*height_of_line;
292                        int y1o   = y1-line_height;
293
294                        AW_click_cd cd(device, (AW_CL)&*curr);
295                        if (line1 == line2) { // whole gene in one book-line
296                            smart_line(device, draw_gc, x1, y1,  x1, y1o);
297                            smart_line(device, draw_gc, x2, y1,  x2, y1o);
298                            smart_line(device, draw_gc, x1, y1,  x2, y1);
299                            smart_line(device, draw_gc, x1, y1o, x2, y1o);
300                            if (show_all_nds || text_gc != GEN_GC_DEFAULT) smart_text(device, text_gc, curr->NodeInfo().c_str(), x1+2, y1-2);
301
302                            if (curr->Complement()) {
303                                smart_line(device, draw_gc, x2, y1o, x2-arrowMid, y1o+arrowMid);
304                                smart_line(device, draw_gc, x2, y1,  x2-arrowMid, y1o+arrowMid);
305                            }
306                            else {
307                                smart_line(device, draw_gc, x1, y1o,  x1+arrowMid, y1o+arrowMid);
308                                smart_line(device, draw_gc, x1, y1,   x1+arrowMid, y1o+arrowMid);
309                            }
310                        }
311                        else {
312                            int y2  = line2*height_of_line;
313                            int y2o = y2-line_height;
314
315                            // upper line (don't draw right border)
316                            smart_line(device, draw_gc, x1, y1,  x1,     y1o);
317                            smart_line(device, draw_gc, x1, y1,  xRight, y1);
318                            smart_line(device, draw_gc, x1, y1o, xRight, y1o);
319                            if (show_all_nds || text_gc != GEN_GC_DEFAULT) smart_text(device, text_gc, curr->NodeInfo().c_str(), x1+2, y1-2);
320
321                            // lower line (don't draw left border)
322                            smart_line(device, draw_gc, x2,    y2,  x2, y2o);
323                            smart_line(device, draw_gc, xLeft, y2,  x2, y2);
324                            smart_line(device, draw_gc, xLeft, y2o, x2, y2o);
325                            if (show_all_nds || text_gc != GEN_GC_DEFAULT) smart_text(device, text_gc, curr->NodeInfo().c_str(), xLeft+2, y2-2);
326
327                            if (curr->Complement()) {
328                                smart_line(device, draw_gc, x2, y2o, x2-arrowMid, y2o+arrowMid);
329                                smart_line(device, draw_gc, x2, y2,  x2-arrowMid, y2o+arrowMid);
330                            }
331                            else {
332                                smart_line(device, draw_gc, x1, y1o, x1+arrowMid, y1o+arrowMid);
333                                smart_line(device, draw_gc, x1, y1,  x1+arrowMid, y1o+arrowMid);
334                            }
335                        }
336                    }
337                    ++curr;
338                }
339                break;
340            }
341        }
342    }
343}
344
345void GEN_graphic::delete_gen_root(AWT_canvas *scr, bool just_forget_callbacks) {
346    callback_installer(just_forget_callbacks ? FORGET_CBS : REMOVE_CBS, scr, this);
347    delete gen_root;
348    gen_root = NULp;
349}
350
351void GEN_graphic::reinit_gen_root(AWT_canvas *scr, bool force_reinit) {
352    char *organism_name = aw_root->awar(AWAR_LOCAL_ORGANISM_NAME(window_nr))->read_string();
353    char *gene_name     = aw_root->awar(AWAR_LOCAL_GENE_NAME(window_nr))->read_string();
354
355    gen_assert(exports.flags_writeable());
356
357    if (gen_root) {
358        if (force_reinit || (gen_root->OrganismName() != string(organism_name))) {
359            bool just_forget_callbacks = false;
360            if (gen_root->OrganismName().length() == 0) {
361                exports.request_zoom_reset(); // no organism was displayed before
362            }
363            else {
364                GB_transaction ta(gb_main);
365                if (!GEN_find_organism(gb_main, gen_root->OrganismName().c_str())) {
366                    just_forget_callbacks = true; // genome already deleted -> just clean up callback table
367                    exports.request_zoom_reset(); // invalid (=none) organism was displayed before
368                }
369            }
370            delete_gen_root(scr, just_forget_callbacks);
371        }
372        if (gen_root && gen_root->GeneName() != string(gene_name)) {
373            gen_root->set_GeneName(gene_name);
374        }
375    }
376
377    if (!gen_root) {
378        gen_root = new GEN_root(organism_name, gene_name, gb_main, aw_root, this);
379        callback_installer(INSTALL_CBS, scr, this);
380    }
381
382    free(organism_name);
383    free(gene_name);
384}
385
386void GEN_graphic::set_display_style(GEN_DisplayStyle type) {
387    style = type;
388
389    switch (style) {
390        case GEN_DISPLAY_STYLE_RADIAL:
391            exports.fit_mode = AWT_FIT_LARGER;
392            break;
393
394        case GEN_DISPLAY_STYLE_VERTICAL:
395        case GEN_DISPLAY_STYLE_BOOK:
396            exports.fit_mode = AWT_FIT_SMALLER;
397            break;
398    }
399
400    exports.zoom_mode = AWT_ZOOM_BOTH;
401    exports.request_zoom_reset();
402}
403
404
Note: See TracBrowser for help on using the repository browser.