source: tags/svn.1.5.4/WINDOW/AW_preset.cxx

Last change on this file was 8359, checked in by westram, 13 years ago
  • added 'Never ask again' switch to most modal question dialogs. This is a workaround to make it possible to work with macros where modal questions are used. See also #179
    • added unique IDs to all calls to aw_question / AW_repeated_question::get_answer
    • replaced most calls to aw_popup_ok with aw_message (most of them only worked-around the non-standard way of EDIT4 to show aw_message)
  • added 'Reactivate questions' to all properties menus
  • hardcoded unused default-params from aw_ask_sure, aw_popup_ok + aw_popup_exit
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 38.2 KB
Line 
1// ================================================================ //
2//                                                                  //
3//   File      : AW_preset.cxx                                      //
4//   Purpose   :                                                    //
5//                                                                  //
6//   Institute of Microbiology (Technical University Munich)        //
7//   http://www.arb-home.de/                                        //
8//                                                                  //
9// ================================================================ //
10
11#ifndef IN_ARB_WINDOW
12#error MODULE_... is not known
13#endif
14
15#include <aw_color_groups.hxx>
16#include <aw_def.hxx>
17#include <aw_preset.hxx>
18#include <aw_advice.hxx>
19#include <aw_awar.hxx>
20#include <aw_msg.hxx>
21#include "aw_device.hxx"
22#include "aw_root.hxx"
23#include "aw_question.hxx"
24
25#include <arbdbt.h>
26
27#include <cstdarg>
28
29void AW_save_specific_properties(AW_window *aw, const char *filename) {  // special version for EDIT4
30    GB_ERROR error = aw->get_root()->save_properties(filename);
31    if (error) aw_message(error);
32}
33void AW_save_properties(AW_window *aw) {
34    AW_save_specific_properties(aw, NULL);
35}
36
37
38static void aw_message_reload(AW_root *) {
39    aw_message("Sorry, to activate new colors:\n"
40                "   save properties\n"
41                "   and restart application");
42}
43static char *aw_glob_font_awar_name = 0;
44
45static void aw_set_color(AW_window *aww, AW_CL cl_color_name) {
46    const char *color_name = (const char *)cl_color_name;
47    aww->get_root()->awar(aw_glob_font_awar_name)->write_string(color_name);
48}
49
50static int hex2dez(char c) {
51    if (c>='0' && c<='9') return c-'0';
52    if (c>='A' && c<='F') return c-'A'+10;
53    if (c>='a' && c<='f') return c-'a'+10;
54    return -1;
55}
56
57static void aw_incdec_color(AW_window *aww, const char *action) {
58    // action is sth like "r+" "b-" "g++" "r--"
59    AW_awar *awar  = aww->get_root()->awar(aw_glob_font_awar_name);
60    char    *color = awar->read_string();
61    bool     err   = true;
62
63    fprintf(stderr, "current color is '%s'\n", color);
64
65    if (color[0]=='#') {
66        int len = strlen(color);
67        if (len==4 || len==7) {
68            len = (len-1)/3; // len of one color channel (1 or 2)
69            aw_assert(len==1 || len==2);
70
71            int diff = action[2]==action[1] ? 7 : 1;
72
73            int channel[3];
74            for (int c=0; c<3; ++c) {
75                if (len==2) channel[c] = hex2dez(color[c*len+1])*16+hex2dez(color[c*len+2]);
76                else        channel[c] = hex2dez(color[c*len+1])*16;
77            }
78
79            int rgb;
80            for (rgb=0; rgb<3; ++rgb) {
81                if (action[0]=="rgb"[rgb] || action[0]=='a') {
82                    if (action[1]=='+') { channel[rgb] += diff; if (channel[rgb]>255) channel[rgb]=255; }
83                    else                { channel[rgb] -= diff; if (channel[rgb]<0)   channel[rgb]=0; }
84                }
85            }
86
87            sprintf(color, "#%2.2X%2.2X%2.2X", channel[0], channel[1], channel[2]);
88
89            err = false;
90            awar->write_string(color);
91        }
92    }
93
94    if (err) {
95        aw_message("Only color values in #rgb- or #rrggbb-style \n"
96                   "can be modified by these buttons. \n"
97                   "Choose a color below and try again.");
98    }
99}
100
101#define AWAR_GLOBAL_COLOR_NAME "tmp/aw/color_label"
102
103static void aw_create_color_chooser_window(AW_window *aww, const char *awar_name, const char *label_name) {
104    AW_root *awr = aww->get_root();
105    static AW_window_simple *aws = 0;
106    if (!aws) {
107        int x1, y1, x2, y2;
108
109        awr->awar_string(AWAR_GLOBAL_COLOR_NAME);
110        aws = new AW_window_simple;
111        aws->init(awr, "COLORS", "COLORS");
112        aws->at(10, 10);
113        aws->auto_space(3, 3);
114        aws->callback     (AW_POPDOWN);
115        aws->create_button("CLOSE", "CLOSE", "C");
116        aws->get_at_position(&x1, &y1);
117        aws->at_newline();
118
119        aws->button_length(20);
120        aws->create_button("LABEL", AWAR_GLOBAL_COLOR_NAME, "A");
121        aws->get_at_position(&x2, &y2);
122        aws->at_newline();
123
124        x1 = x1>x2 ? x1 : x2;
125
126        int red, green, blue, grey;
127
128        for (int minus = 0; minus<=1; ++minus) {
129            aws->at(x1, minus==0 ? y1 : y2);
130            for (int rgb=0; rgb<4; ++rgb) {
131                for (int big=0; big<=1; ++big) {
132                    aws->button_length(2+big);
133
134                    char action[4] = "xxx";
135                    action[0] = "rgba"[rgb];
136                    action[1] = "+-"[minus];
137                    action[2] = big ? action[1] : 0;
138
139                    char color_name[10];
140                    sprintf(color_name, "#%2.2X%2.2X%2.2X", rgb==0 ? 0xff : 0x55, rgb==1 ? 0xff : 0x55, rgb==2 ? 0xff : 0x55);
141                    aws->callback((AW_CB1)aw_incdec_color, (AW_CL)strdup(action));
142                    aws->create_button(action, action+1, 0, color_name);
143                }
144            }
145        }
146
147        aws->button_length(2);
148        aws->at_newline();
149
150        for (red = 0; red <= 255; red += 255/3) {
151            for (green = 0; green <= 255; green += 255/3) {
152                for (blue = 0; blue <= 255; blue += 255/3) {
153                    char color_name[256];
154                    sprintf(color_name, "#%2.2X%2.2X%2.2X", red, green, blue);
155                    aws->callback((AW_CB1)aw_set_color, (AW_CL)strdup(color_name));
156                    aws->create_button(color_name, "=", 0, color_name);
157                }
158            }
159            aws->at_newline();
160        }
161        for (grey = 256/32; grey < 256; grey += 256/16) { // grey buttons (skip black/white - already present above)
162            char color_name[256];
163            sprintf(color_name, "#%2.2X%2.2X%2.2X", grey, grey, grey);
164            aws->callback(aw_set_color, (AW_CL)strdup(color_name));
165            aws->create_button(color_name, "=", 0, color_name);
166        }
167        aws->at_newline();
168
169        aws->window_fit();
170    }
171    awr->awar(AWAR_GLOBAL_COLOR_NAME)->write_string(label_name);
172    freedup(aw_glob_font_awar_name, awar_name);
173    aws->activate();
174}
175
176static void AW_preset_create_color_chooser(AW_window *aws, const char *awar_name, const char *label, bool message_reload, bool show_label)
177{
178    if (message_reload) aws->get_root()->awar(awar_name)->add_callback(aw_message_reload);
179    if (show_label) {
180        aw_assert(label);
181        aws->label(label);
182    }
183    aws->callback((AW_CB)aw_create_color_chooser_window, (AW_CL)strdup(awar_name), (AW_CL)strdup(label));
184    char *color     = aws->get_root()->awar(awar_name)->read_string();
185    char *button_id = GBS_global_string_copy("sel_color[%s]", awar_name);
186    aws->create_button(button_id, " ", 0, color);
187    free(button_id);
188    free(color);
189}
190
191static void AW_preset_create_font_chooser(AW_window *aws, const char *awar, const char *label, bool message_reload)
192{
193    if (message_reload) {
194        aws->get_root()->awar(awar)->add_callback(aw_message_reload);
195    }
196
197    aws->create_option_menu(awar, label);
198    aws->insert_option        ("5x8",   "5", "5x8");
199    aws->insert_option        ("6x10",   "6", "6x10");
200    aws->insert_option        ("7x13",   "7", "7x13");
201    aws->insert_option        ("7x13bold",   "7", "7x13bold");
202    aws->insert_option        ("8x13",   "8", "8x13");
203    aws->insert_option        ("8x13bold",   "8", "8x13bold");
204    aws->insert_option        ("9x15",   "9", "9x15");
205    aws->insert_option        ("9x15bold",   "9", "9x15bold");
206    aws->insert_option        ("helvetica-12",   "9", "helvetica-12");
207    aws->insert_option        ("helvetica-bold-12",   "9", "helvetica-bold-12");
208    aws->insert_option        ("helvetica-13",   "9", "helvetica-13");
209    aws->insert_option        ("helvetica-bold-13",   "9", "helvetica-bold-13");
210    aws->insert_default_option("other", "o", "");
211    aws->update_option_menu();
212}
213
214struct AW_MGC_awar_cb_struct;
215
216class aw_gc_manager {
217    const char            *field;
218    const char            *default_value;
219    AW_option_menu_struct *font_size_handle; // the option menu to define the font size of the GC
220    AW_MGC_awar_cb_struct *font_change_cb_parameter;
221    aw_gc_manager         *next;
222
223public:
224    aw_gc_manager(const char *field_, const char *default_value_)
225        : field(field_)
226        , default_value(default_value_)
227        , font_size_handle(0)
228        , next(0)
229    {}
230
231    void enqueue(aw_gc_manager *next_) {
232        aw_assert(!next);
233        next = next_;
234    }
235
236    const char *get_field() const { return field; }
237    const char *get_default_value() const { return default_value; }
238    const aw_gc_manager *get_next() const { return next; }
239    aw_gc_manager *get_next() { return next; }
240
241    void set_font_size_handle(AW_option_menu_struct *oms) { font_size_handle = oms; }
242    AW_option_menu_struct *get_font_size_handle() const { return font_size_handle; }
243
244    void set_font_change_parameter(AW_MGC_awar_cb_struct *cb_data) { font_change_cb_parameter = cb_data; }
245    AW_MGC_awar_cb_struct *get_font_change_parameter() const { return font_change_cb_parameter; }
246};
247
248struct AW_MGC_cb_struct {   // one for each window
249    AW_MGC_cb_struct(AW_window *awi, void (*g)(AW_window*, AW_CL, AW_CL), AW_CL cd1i, AW_CL cd2i);
250
251    AW_window *aw;
252    void (*f)(AW_window*, AW_CL, AW_CL);
253    AW_CL      cd1;
254    AW_CL      cd2;
255    char      *window_awar_name;
256    AW_device *device;
257
258    struct AW_MGC_awar_cb_struct *next_drag;
259};
260
261AW_MGC_cb_struct::AW_MGC_cb_struct(AW_window *awi, void (*g)(AW_window*, AW_CL, AW_CL), AW_CL cd1i, AW_CL cd2i) {
262    memset((char*)this, 0, sizeof(AW_MGC_cb_struct));
263    aw  = awi;
264    f   = g;
265    cd1 = cd1i;
266    cd2 = cd2i;
267
268    window_awar_name = strdup(awi->get_window_id());
269}
270
271struct AW_MGC_awar_cb_struct {  // one for each awar
272    struct AW_MGC_cb_struct      *cbs;
273    const char                   *fontbasename;
274    const char                   *colorbasename;
275    short                         gc;
276    short                         gc_drag;
277    short                         colorindex;
278    aw_gc_manager                *gcmgr;
279    AW_window                    *gc_def_window;
280    struct AW_MGC_awar_cb_struct *next;
281};
282
283static void add_font_sizes_to_option_menu(AW_window *aww, int count, int *available_sizes) {
284    char ssize[20];
285    bool default_size_set = false;
286
287    for (int idx = 0; idx < count; ++idx) {
288        int size = available_sizes[idx];
289        if (!default_size_set && size > DEF_FONTSIZE) { // insert default size if missing
290            sprintf(ssize, "%i", DEF_FONTSIZE);
291            aww->insert_default_option(ssize, 0, (int) DEF_FONTSIZE);
292            default_size_set = true;
293        }
294        sprintf(ssize, "%i", size);
295        if (size == DEF_FONTSIZE) {
296            aww->insert_default_option(ssize, 0, (int) size);
297            default_size_set = true;
298        }
299        else {
300            aww->insert_option(ssize, 0, (int) size);
301        }
302    }
303
304    if (!default_size_set) {
305        sprintf(ssize, "%i", DEF_FONTSIZE);
306        aww->insert_default_option(ssize, 0, (int) DEF_FONTSIZE);
307    }
308
309    aww->update_option_menu();
310}
311
312static void aw_init_font_sizes(AW_root *awr, AW_MGC_awar_cb_struct *cbs, bool firstCall) {
313    AW_option_menu_struct *oms = cbs->gcmgr->get_font_size_handle();
314    aw_assert(oms);
315
316    if (oms) {                  // has font size definition
317        int  available_sizes[MAX_FONTSIZE-MIN_FONTSIZE+1];
318        char awar_name[256];
319        sprintf(awar_name, AWP_FONTNAME_TEMPLATE, cbs->cbs->window_awar_name, cbs->fontbasename);
320
321        int        font_nr     = awr->awar(awar_name)->read_int();
322        int        found_sizes = cbs->cbs->device->get_available_fontsizes(cbs->gc, font_nr, available_sizes);
323        AW_window *aww         = cbs->gc_def_window;
324        aw_assert(aww);
325
326        if (!firstCall) aww->clear_option_menu(oms);
327        add_font_sizes_to_option_menu(aww, found_sizes, available_sizes);
328    }
329}
330
331static void aw_font_changed_cb(AW_root *awr, AW_CL cl_cbs) {
332    AW_MGC_awar_cb_struct *cbs = (AW_MGC_awar_cb_struct*)cl_cbs;
333    aw_init_font_sizes(awr, cbs, false);
334}
335
336static void aw_gc_changed_cb(AW_root *awr, AW_MGC_awar_cb_struct *cbs, long mode)
337{
338    static int dont_recurse = 0;
339
340    if (dont_recurse == 0) {
341        ++dont_recurse;
342        // mode == -1 -> no callback
343        char awar_name[256];
344        int  font;
345        int  size;
346
347        sprintf(awar_name, AWP_FONTNAME_TEMPLATE, cbs->cbs->window_awar_name, cbs->fontbasename);
348        font = awr->awar(awar_name)->read_int();
349
350        sprintf(awar_name, AWP_FONTSIZE_TEMPLATE, cbs->cbs->window_awar_name, cbs->fontbasename);
351        AW_awar *awar_font_size = awr->awar(awar_name);
352        size                    = awar_font_size->read_int();
353
354        int found_font_size;
355        cbs->cbs->device->set_font(cbs->gc, font, size, &found_font_size);
356        cbs->cbs->device->set_font(cbs->gc_drag, font, size, 0);
357        if (found_font_size != -1 && found_font_size != size) {
358            // correct awar value if exact fontsize wasn't found
359            awar_font_size->write_int(found_font_size);
360        }
361
362        if (mode != -1) {
363            cbs->cbs->f(cbs->cbs->aw, cbs->cbs->cd1, cbs->cbs->cd2);
364        }
365        --dont_recurse;
366    }
367}
368
369static void aw_gc_color_changed_cb(AW_root *root, AW_MGC_awar_cb_struct *cbs, long mode)
370{
371    char awar_name[256];
372    char *colorname;
373
374    sprintf(awar_name, AWP_COLORNAME_TEMPLATE, cbs->cbs->window_awar_name, cbs->colorbasename);
375    colorname = root->awar(awar_name)->read_string();
376    AW_color_idx color = (AW_color_idx)cbs->colorindex;
377    cbs->cbs->aw->alloc_named_data_color(color, colorname);
378    if (color != AW_DATA_BG) {
379        cbs->cbs->device->set_foreground_color(cbs->gc, color);
380        cbs->cbs->device->set_foreground_color(cbs->gc_drag, color);
381    }
382    else {
383        struct AW_MGC_awar_cb_struct *acbs;
384        for (acbs = cbs->cbs->next_drag; acbs; acbs=acbs->next) {
385            cbs->cbs->device->set_foreground_color(acbs->gc_drag, (AW_color_idx)acbs->colorindex);
386        }
387    }
388    if (mode != -1) {
389        cbs->cbs->f(cbs->cbs->aw, cbs->cbs->cd1, cbs->cbs->cd2);
390    }
391    free(colorname);
392}
393
394static bool color_groups_initialized = false;
395static bool use_color_groups = false;
396
397static const char *AW_get_color_group_name_awarname(int color_group) {
398    if (color_group>0 && color_group <= AW_COLOR_GROUPS) {
399        static char buf[sizeof(AWAR_COLOR_GROUPS_PREFIX)+1+4+2+1];
400        sprintf(buf, AWAR_COLOR_GROUPS_PREFIX "/name%i", color_group);
401        return buf;
402    }
403    return 0;
404}
405
406char *AW_get_color_group_name(AW_root *awr, int color_group) {
407    aw_assert(color_groups_initialized);
408    aw_assert(color_group>0 && color_group <= AW_COLOR_GROUPS);
409    return awr->awar(AW_get_color_group_name_awarname(color_group))->read_string();
410}
411
412static void AW_color_group_name_changed_cb(AW_root *) {
413    AW_advice("To activate the new names for color groups you have to\n"
414              "save properties and restart the program.",
415              AW_ADVICE_TOGGLE, "Color group name has been changed", 0);
416}
417static void AW_color_group_usage_changed_cb(AW_root *awr, AW_CL /* cl_ntw */) {
418    use_color_groups       = awr->awar(AWAR_COLOR_GROUPS_USE)->read_int();
419    //     AWT_canvas *ntw = (AWT_canvas*)cl_ntw;
420    //     ntw->refresh();
421    // @@@ FIXME: a working refresh is missing
422}
423
424static void AW_init_color_groups(AW_root *awr, AW_default def) {
425    if (!color_groups_initialized) {
426        AW_awar *useAwar = awr->awar_int(AWAR_COLOR_GROUPS_USE, 1, def);
427        use_color_groups = useAwar->read_int();
428        useAwar->add_callback(AW_color_group_usage_changed_cb, (AW_CL)0);
429
430        char name_buf[AW_COLOR_GROUP_NAME_LEN+1];
431        for (int i = 1; i <= AW_COLOR_GROUPS; ++i) {
432            sprintf(name_buf, "color_group_%i", i);
433            awr->awar_string(AW_get_color_group_name_awarname(i), name_buf, def)->add_callback(AW_color_group_name_changed_cb);
434        }
435        color_groups_initialized = true;
436    }
437}
438
439#if defined(UNIT_TESTS)
440void fake_AW_init_color_groups() {
441    if (!color_groups_initialized) {
442        use_color_groups = true;
443    }
444    color_groups_initialized = true;
445}
446#endif
447
448
449// values optimized for ARB_NTREE :
450static const char *ARB_NTREE_color_group[AW_COLOR_GROUPS+1] = {
451    "+-" AW_COLOR_GROUP_PREFIX  "1$#D50000", "-" AW_COLOR_GROUP_PREFIX  "2$#00ffff",
452    "+-" AW_COLOR_GROUP_PREFIX  "3$#00FF77", "-" AW_COLOR_GROUP_PREFIX  "4$#c700c7",
453    "+-" AW_COLOR_GROUP_PREFIX  "5$#0000ff", "-" AW_COLOR_GROUP_PREFIX  "6$#FFCE5B",
454
455    "+-" AW_COLOR_GROUP_PREFIX  "7$#AB2323", "-" AW_COLOR_GROUP_PREFIX  "8$#008888",
456    "+-" AW_COLOR_GROUP_PREFIX  "9$#008800", "-" AW_COLOR_GROUP_PREFIX "10$#880088",
457    "+-" AW_COLOR_GROUP_PREFIX "11$#000088", "-" AW_COLOR_GROUP_PREFIX "12$#888800",
458
459    0
460};
461
462// values optimized for ARB_EDIT4 :
463static const char *ARB_EDIT4_color_group[AW_COLOR_GROUPS+1] = {
464    "+-" AW_COLOR_GROUP_PREFIX  "1$#FFAFAF", "-" AW_COLOR_GROUP_PREFIX  "2$#A1FFFF",
465    "+-" AW_COLOR_GROUP_PREFIX  "3$#AAFFAA", "-" AW_COLOR_GROUP_PREFIX  "4$#c700c7",
466    "+-" AW_COLOR_GROUP_PREFIX  "5$#C5C5FF", "-" AW_COLOR_GROUP_PREFIX  "6$#FFE370",
467
468    "+-" AW_COLOR_GROUP_PREFIX  "7$#F87070", "-" AW_COLOR_GROUP_PREFIX  "8$#DAFFFF",
469    "+-" AW_COLOR_GROUP_PREFIX  "9$#8DE28D", "-" AW_COLOR_GROUP_PREFIX "10$#880088",
470    "+-" AW_COLOR_GROUP_PREFIX "11$#000088", "-" AW_COLOR_GROUP_PREFIX "12$#F1F169",
471
472    0
473};
474
475static const char **color_group_gc_defaults = 0;
476
477void AW_init_color_group_defaults(const char *for_program) {
478    // if for_program == NULL defaults of arb_ntree are silently used
479    // if for_program is unknown a warning is shown
480
481    aw_assert(color_group_gc_defaults == 0); // oops - called twice
482
483    if (for_program) {
484        if (strcmp(for_program, "arb_ntree")      == 0) color_group_gc_defaults = ARB_NTREE_color_group;
485        else if (strcmp(for_program, "arb_edit4") == 0) color_group_gc_defaults = ARB_EDIT4_color_group;
486    }
487
488    if (!color_group_gc_defaults) {
489        if (for_program) { // unknown program ?
490#if defined(DEBUG)
491            fprintf(stderr, "No specific defaults for color groups defined (using those from ARB_NTREE)\n");
492#endif // DEBUG
493        }
494        color_group_gc_defaults = ARB_NTREE_color_group;
495    }
496
497    aw_assert(color_group_gc_defaults);
498}
499
500
501long AW_find_color_group(GBDATA *gbd, bool ignore_usage_flag) {
502    /* species/genes etc. may have a color group entry ('ARB_color')
503     * call with ignore_usage_flag == true to read color group regardless of global usage flag (AWAR_COLOR_GROUPS_USE)
504     */
505    aw_assert(color_groups_initialized);
506    if (!use_color_groups && !ignore_usage_flag) return 0;
507
508    GBDATA *gb_group = GB_entry(gbd, AW_COLOR_GROUP_ENTRY);
509    if (gb_group) return GB_read_int(gb_group);
510    return 0;                   // no color group
511}
512
513GB_ERROR AW_set_color_group(GBDATA *gbd, long color_group) {
514    return GBT_write_int(gbd, AW_COLOR_GROUP_ENTRY, color_group);
515}
516
517struct gc_props {
518    bool hidden; 
519    bool select_font;
520    bool select_color;
521
522    bool fixed_fonts_only;
523    bool append_same_line;
524
525    gc_props()
526        : hidden(false),
527          select_font(true), 
528          select_color(true),
529          fixed_fonts_only(false),
530          append_same_line(false)
531    {}
532
533private:
534    bool parse_char(char c) {
535        switch (c) {
536            case '#': fixed_fonts_only = true; break;
537            case '+': append_same_line = true; break;
538
539            case '=': select_color = false; break;
540            case '-': {
541                if (select_font) select_font = false;
542                else hidden                  = true; // two '-' means 'hidden'
543                break;
544            }
545
546            default : return false;
547        }
548        return true;
549    }
550
551    void correct() {
552        if (!select_font && !select_color) hidden             = true;
553        if (append_same_line && select_font) append_same_line = false;
554    }
555public:
556
557    int parse_decl(const char *decl) {
558        // returns number of (interpreted) prefix characters
559        int offset = 0;
560        while (decl[offset]) {
561            if (!parse_char(decl[offset])) break;
562            offset++;
563        }
564        correct();
565        return offset;
566    }
567};
568
569AW_gc_manager AW_manage_GC(AW_window   *aww,
570                           AW_device   *device,
571                           int          base_gc,
572                           int          base_drag,
573                           AW_GCM_AREA  area,
574                           void (*changecb)(AW_window*, AW_CL, AW_CL),
575                           AW_CL        cd1,
576                           AW_CL        cd2,
577                           bool         define_color_groups,
578                           const char  *default_background_color,
579                           ...)
580{
581    /*  Parameter:
582     *          aww:                    base window
583     *          device:                 screen device
584     *          base_gc:                first gc number
585     *          base_drag:              one after last gc
586     *          area:                   middle,top ...
587     *          changecb:               cb if changed
588     *          cd1,cd2:                free Parameters to changecb
589     *          define_color_groups:    true -> add colors for color groups
590     *
591     *          ...:        NULL terminated list of \0 terminated strings:
592     *
593     *          first GC is fixed: '-background'
594     *
595     *          optionsSTRING   name of GC and AWAR
596     *          options:        #   fixed fonts only
597     *                          -   no fonts
598     *                          --  completely hide GC
599     *                          =   no color selector
600     *                          +   append next in same line
601     *
602     *                          $color at end of string = > define default color value
603     *                          ${GCname} at end of string = > use default of previously defined color
604     */
605
606    AW_root    *aw_root = aww->get_root();
607    AW_default  aw_def  = AW_ROOT_DEFAULT;
608
609    AW_init_color_groups(aw_root, aw_def);
610
611    const char           *id;
612    va_list               parg;
613    va_start(parg, default_background_color);
614    AW_font               def_font;
615    struct aw_gc_manager *gcmgrlast = 0, *gcmgr2=0, *gcmgrfirst=0;
616
617    AW_MGC_cb_struct *mcbs = new AW_MGC_cb_struct(aww, changecb, cd1, cd2);
618    mcbs->device = device;
619
620    int col = AW_WINDOW_BG;
621    if (area == AW_GCM_DATA_AREA) {
622        col = AW_DATA_BG;
623    }
624    bool first = true;
625
626    aww->main_drag_gc = base_drag;
627    gcmgrfirst = gcmgrlast = new aw_gc_manager(mcbs->window_awar_name, 0);
628
629    const char *last_font_base_name = "default";
630
631    char background[50];
632    aw_assert(default_background_color[0]);
633
634    sprintf(background, "-background$%s", default_background_color);
635
636    for (int loop = 1; loop <= 2; ++loop) {
637        int color_group_counter = 0;
638
639        if (loop == 1) { // set default colors
640            id = background;
641        }
642        else { // set color_group colors
643            id = 0;
644            if (define_color_groups) {
645                aw_assert(color_group_gc_defaults); // forgot to call AW_init_color_group_defaults ?
646                id = color_group_gc_defaults[color_group_counter++];
647            }
648        }
649
650        while (id) {
651            gc_props gcp;
652            AW_MGC_awar_cb_struct *acbs = 0;
653            {
654                char       *id_copy       = strdup(id);
655                const char *default_color = 0;
656
657                {
658                    char *color = strchr(id_copy, '$'); // search color def
659
660                    if (color) {
661                        *color++ = 0;
662
663                        if (color[0] == '{') {
664                            char *close = strchr(color+1, '}');
665                            aw_assert(close); // format is '${KNOWN_GC}'
666                            aw_assert(close[1] == 0); // unexpected chars behind
667                            if (close) {
668                                close[0] = 0;
669                                color++;
670
671                                aw_gc_manager *known = gcmgrfirst;
672                                aw_assert(known);
673                                while (known) {
674                                    if (strcmp(known->get_field(), color) == 0) { // found referred gc
675                                        default_color = known->get_default_value(); // use it's default color
676                                        break;
677                                    }
678                                    known = known->get_next();
679                                }
680                                aw_assert(known); // referred to unknown {GC}
681                            }
682                        }
683                        else {
684                            default_color = color;
685                        }
686                    }
687                }
688
689                if (!default_color) default_color = first ? "white" : "black";
690
691                gcmgr2 = new aw_gc_manager(strdup(id_copy), strdup(default_color));
692
693                gcmgrlast->enqueue(gcmgr2);
694                gcmgrlast = gcmgr2;
695
696                acbs                = new AW_MGC_awar_cb_struct;
697                acbs->cbs           = mcbs;
698                acbs->colorbasename = GBS_string_2_key(id_copy);
699                acbs->gc            = base_gc;
700                acbs->gc_drag       = base_drag;
701                acbs->gcmgr         = gcmgr2;
702                acbs->gc_def_window = 0;
703
704                if (!first) {
705                    acbs->next = mcbs->next_drag;
706                    mcbs->next_drag = acbs;
707                }
708
709                gcp.parse_decl(id_copy);
710                freenull(id_copy);
711            }
712
713            def_font = gcp.fixed_fonts_only ? AW_DEFAULT_FIXED_FONT : AW_DEFAULT_NORMAL_FONT;
714
715            if ((area != AW_GCM_DATA_AREA) || !first) {
716                device->new_gc(base_gc);
717                device->set_line_attributes(base_gc, 1, AW_SOLID);
718                device->set_function(base_gc, AW_COPY);
719
720                device->new_gc(base_drag);
721                device->set_line_attributes(base_drag, 1, AW_SOLID);
722                device->set_function(base_drag, AW_XOR);
723                device->establish_default(base_drag);
724            }
725
726            char awar_name[256]; memset(awar_name, 0, 256);
727            sprintf(awar_name, AWP_COLORNAME_TEMPLATE, mcbs->window_awar_name, acbs->colorbasename);
728            acbs->colorindex = col;
729
730            aw_root->awar_string(awar_name, gcmgr2->get_default_value(), aw_def);
731            aw_root->awar(awar_name)->add_callback((AW_RCB)aw_gc_color_changed_cb, (AW_CL)acbs, (AW_CL)0);
732
733            aw_gc_color_changed_cb(aw_root, acbs, -1);
734
735            acbs->fontbasename  = gcp.select_font ? acbs->colorbasename : last_font_base_name;
736            last_font_base_name = acbs->fontbasename;
737
738            {
739                sprintf(awar_name, AWP_FONTNAME_TEMPLATE, mcbs->window_awar_name, acbs->fontbasename);
740                AW_awar *font_awar = aw_root->awar_int(awar_name, def_font, aw_def);
741                sprintf(awar_name, AWP_FONTSIZE_TEMPLATE,  mcbs->window_awar_name, acbs->fontbasename);
742                AW_awar *font_size_awar = aw_root->awar_int(awar_name, DEF_FONTSIZE, aw_def);
743
744                if (gcp.select_font) {
745                    font_awar->add_callback(aw_font_changed_cb, (AW_CL)acbs);
746                    gcmgr2->set_font_change_parameter(acbs);
747                }
748
749                font_awar->add_callback((AW_RCB)aw_gc_changed_cb, (AW_CL)acbs, (AW_CL)0);
750                font_size_awar->add_callback((AW_RCB)aw_gc_changed_cb, (AW_CL)acbs, (AW_CL)0);
751            }
752
753            if (!first) {
754                aw_gc_changed_cb(aw_root, acbs, -1);
755                base_gc++;
756                base_drag++;
757            }
758            col++;
759            first = false;
760
761            // switch to next default:
762
763            if (loop == 1) id = va_arg(parg, char*);
764            else {
765                aw_assert(color_group_gc_defaults); // forgot to call AW_init_color_group_defaults ?
766                id = color_group_gc_defaults[color_group_counter++];
767            }
768        }
769    }
770
771    va_end(parg);
772
773    return (AW_gc_manager)gcmgrfirst;
774}
775
776void AW_copy_GCs(AW_root *aw_root, const char *source_window, const char *dest_window, bool has_font_info, const char *id0, ...) {
777    // read the values of the specified GCs from 'source_window'
778    // and write the values into same-named GCs of 'dest_window'
779    //
780    // 'id0' is the first of a list of color ids
781    // a NULL pointer has to be given behind the last color!
782
783    va_list parg;
784    va_start(parg, id0);
785
786    const char *id = id0;
787    while (id) {
788        char *value = aw_root->awar(GBS_global_string(AWP_COLORNAME_TEMPLATE, source_window, id))->read_string();
789        aw_root->awar(GBS_global_string(AWP_COLORNAME_TEMPLATE, dest_window, id))->write_string(value);
790        free(value);
791
792        if (has_font_info) {
793            int ivalue = aw_root->awar(GBS_global_string(AWP_FONTNAME_TEMPLATE, source_window, id))->read_int();
794            aw_root->awar(GBS_global_string(AWP_FONTNAME_TEMPLATE, dest_window, id))->write_int(ivalue);
795            ivalue     = aw_root->awar(GBS_global_string(AWP_FONTSIZE_TEMPLATE, source_window, id))->read_int();
796            aw_root->awar(GBS_global_string(AWP_FONTSIZE_TEMPLATE, dest_window, id))->write_int(ivalue);
797        }
798
799        id = va_arg(parg, const char*); // another argument ?
800    }
801
802    va_end(parg);
803}
804
805static bool aw_insert_gcs(AW_root *aw_root, AW_window_simple *aws, aw_gc_manager *gcmgr, bool insert_color_groups) {
806    // returns true if GCs starting with COLOR_GROUP_PREFIX were found
807
808    bool        has_color_groups = false;
809    const char *window_awar_name = gcmgr->get_field();
810
811    for (gcmgr = gcmgr->get_next(); gcmgr; gcmgr = gcmgr->get_next()) {
812        const char *id = gcmgr->get_field();
813        gc_props    gcp;
814
815        id += gcp.parse_decl(id);
816
817        char *fontbasename   = GBS_string_2_key(id);
818        char  awar_name[256];
819        bool  is_color_group = strncmp(id, AW_COLOR_GROUP_PREFIX, AW_COLOR_GROUP_PREFIX_LEN) == 0;
820        int   color_group    = -1;
821
822        if (is_color_group) {
823            has_color_groups = true;
824            color_group      = atoi(id+AW_COLOR_GROUP_PREFIX_LEN);
825            if (!insert_color_groups) continue;
826        }
827        else { // is no color group
828            if (insert_color_groups) continue;
829        }
830
831        if (!gcp.hidden) {
832            sprintf(awar_name, AWP_COLORNAME_TEMPLATE, window_awar_name, fontbasename);
833            aws->label_length(15);
834
835            if (is_color_group) {
836                aw_assert(color_group > 0);
837                char *color_group_name = AW_get_color_group_name(aw_root, color_group);
838                aws->label(color_group_name);
839                free(color_group_name);
840            }
841            else {
842                aws->label(id);
843            }
844
845            if (gcp.select_color) {
846                aws->button_length(5);
847                AW_preset_create_color_chooser(aws, awar_name, id, false, false);
848            }
849            aws->create_input_field(awar_name, 7);
850
851            if (gcp.select_font) {
852                sprintf(awar_name, AWP_FONTNAME_TEMPLATE, window_awar_name, fontbasename);
853
854                aws->label_length(5);
855                aws->create_option_menu(awar_name, "Font", 0);
856                {
857                    int font_nr;
858                    const char *font_string;
859
860                    for (font_nr = 0; ; font_nr++) {
861                        font_string = AW_font_2_ascii((AW_font) font_nr);
862                        if (!font_string) break;
863                        if (gcp.fixed_fonts_only && AW_font_2_xfig((AW_font) font_nr) >= 0) continue;
864                        aws->insert_option(font_string, 0, (int) font_nr);
865                    }
866                    aws->update_option_menu();
867                }
868
869                sprintf(awar_name, AWP_FONTSIZE_TEMPLATE, window_awar_name, fontbasename);
870                aws->label_length(5);
871
872                AW_option_menu_struct *oms = aws->create_option_menu(awar_name, "size", 0);
873                gcmgr->set_font_size_handle(oms);
874
875                AW_MGC_awar_cb_struct *acs = gcmgr->get_font_change_parameter();
876                acs->gc_def_window         = aws;
877
878                aw_init_font_sizes(aw_root, acs, true); // does update_option_menu
879            }
880            if (!gcp.append_same_line)  aws->at_newline();
881        }
882        free(fontbasename);
883    }
884
885    return has_color_groups;
886}
887
888struct attached_window {
889    AW_window_simple       *aws;
890    AW_CL                   attached_to;
891    struct attached_window *next;
892};
893
894static void AW_create_gc_color_groups_name_window(AW_window * /* aww */, AW_CL cl_aw_root, AW_CL cl_gcmgr) {
895    AW_root *aw_root = (AW_root*)cl_aw_root;
896    static struct attached_window *head = 0;
897
898    // search for attached window:
899
900    struct attached_window *look = head;
901    while (look) {
902        if (look->attached_to == cl_gcmgr) break;
903        look = look->next;
904    }
905
906    AW_window_simple *aws = 0;
907
908    if (look) {
909        aws = look->aws;
910    }
911    else {
912        look = new struct attached_window;
913
914        look->aws         = new AW_window_simple;
915        look->attached_to = cl_gcmgr;
916        look->next        = head;
917        head              = look;
918
919        aws = look->aws;
920
921        aws->init(aw_root, "NAME_COLOR_GROUPS", "COLORS GROUP NAMES");
922
923        aws->at(10, 10);
924        aws->auto_space(5, 5);
925
926        aws->callback((AW_CB0) AW_POPDOWN);
927        aws->create_button("CLOSE", "CLOSE", "C");
928
929        for (int i = 1; i <= AW_COLOR_GROUPS; ++i) {
930            aws->at_newline();
931
932            aws->label(GBS_global_string("Name for color group #%i%s", i, (i >= 10) ? "" : " "));
933            aws->create_input_field(AW_get_color_group_name_awarname(i), AW_COLOR_GROUP_NAME_LEN);
934        }
935
936        aws->window_fit();
937    }
938
939    aws->activate();
940}
941
942static void AW_create_gc_color_groups_window(AW_window * /* aww */, AW_CL cl_aw_root, AW_CL cl_gcmgr) {
943    aw_assert(color_groups_initialized);
944
945    AW_root       *aw_root = (AW_root*)cl_aw_root;
946    aw_gc_manager *gcmgr   = (aw_gc_manager*)cl_gcmgr;
947
948    static struct attached_window *head = 0;
949
950    // search for attached window:
951
952    struct attached_window *look = head;
953    while (look) {
954        if (look->attached_to == cl_gcmgr) break;
955        look = look->next;
956    }
957
958    AW_window_simple *aws = 0;
959
960    if (look) {
961        aws = look->aws;
962    }
963    else {
964        look = new struct attached_window;
965
966        look->aws         = new AW_window_simple;
967        look->attached_to = cl_gcmgr;
968        look->next        = head;
969        head              = look;
970
971        aws = look->aws;
972
973        aws->init(aw_root, "PROPS_COLOR_GROUPS", "COLORS GROUPS");
974
975        aws->at(10, 10);
976        aws->auto_space(5, 5);
977
978        aws->callback((AW_CB0) AW_POPDOWN);
979        aws->create_button("CLOSE", "CLOSE", "C");
980
981        aws->callback(AW_POPUP_HELP, (AW_CL)"color_props_groups.hlp");
982        aws->create_button("HELP", "HELP", "H");
983
984        aws->at_newline();
985
986        aw_insert_gcs(aw_root, aws, gcmgr, true);
987
988        aws->at_newline();
989
990        aws->label_length(16);
991        aws->label("Use color groups");
992        aws->create_toggle(AWAR_COLOR_GROUPS_USE);
993
994        aws->callback((AW_CB)AW_create_gc_color_groups_name_window, (AW_CL)aw_root, cl_gcmgr);
995        aws->create_autosize_button("DEF_NAMES", "Define names", "D");
996
997        aws->window_fit();
998    }
999
1000    aws->activate();
1001}
1002
1003AW_window *AW_create_gc_window_named(AW_root * aw_root, AW_gc_manager id_par, const char *wid, const char *windowname) {
1004    AW_window_simple * aws = new AW_window_simple;
1005
1006    aws->init(aw_root, wid, windowname);
1007
1008    aw_gc_manager *gcmgr = (aw_gc_manager *)id_par;
1009
1010    aws->at(10, 10);
1011    aws->auto_space(5, 5);
1012
1013    aws->callback((AW_CB0) AW_POPDOWN);
1014    aws->create_button("CLOSE", "CLOSE", "C");
1015
1016    aws->callback(AW_POPUP_HELP, (AW_CL)"color_props.hlp");
1017    aws->create_button("HELP", "HELP", "H");
1018
1019    aws->at_newline();
1020
1021    bool has_color_groups = aw_insert_gcs(aw_root, aws, gcmgr, false);
1022
1023    if (has_color_groups) {
1024        aws->callback((AW_CB)AW_create_gc_color_groups_window, (AW_CL)aw_root, (AW_CL)id_par);
1025        aws->create_autosize_button("EDIT_COLOR_GROUP", "Edit color groups", "E");
1026        aws->at_newline();
1027    }
1028
1029    aws->window_fit();
1030    return (AW_window *) aws;
1031
1032}
1033AW_window *AW_create_gc_window(AW_root * aw_root, AW_gc_manager id_par)
1034{
1035    return AW_create_gc_window_named(aw_root, id_par, "PROPS_GC", "Colors and Fonts");
1036}
1037
1038AW_window *AW_preset_window(AW_root *root) {
1039    AW_window_simple *aws = new AW_window_simple;
1040    const int   tabstop = 400;
1041    aws->init(root, "PROPS_FRAME", "WINDOW_PROPERTIES");
1042
1043    aws->label_length(25);
1044    aws->button_length(20);
1045
1046    aws->at           (10, 10);
1047    aws->auto_space(10, 10);
1048
1049    aws->callback     (AW_POPDOWN);
1050    aws->create_button("CLOSE", "CLOSE", "C");
1051
1052    aws->callback(AW_POPUP_HELP, (AW_CL)"props_frame.hlp");
1053    aws->create_button("HELP", "HELP", "H");
1054
1055    aws->at_newline();
1056
1057    AW_preset_create_font_chooser(aws, "window/font", "Main Menu Font", 1);
1058    aws->at_x(tabstop);
1059    aws->create_input_field("window/font", 12);
1060
1061    aws->at_newline();
1062
1063    aws->button_length(10);
1064    AW_preset_create_color_chooser(aws, "window/background", "Application Background", true, true);
1065    aws->at_x(tabstop);
1066    aws->create_input_field("window/background", 12);
1067
1068    aws->at_newline();
1069
1070    AW_preset_create_color_chooser(aws, "window/foreground", "Application Foreground", true, true);
1071    aws->at_x(tabstop);
1072    aws->create_input_field("window/foreground", 12);
1073
1074    aws->at_newline();
1075
1076    AW_preset_create_color_chooser(aws, "window/color_1", "Color 1", true, true);
1077    aws->at_x(tabstop);
1078    aws->create_input_field("window/color_1", 12);
1079
1080    aws->at_newline();
1081
1082    AW_preset_create_color_chooser(aws, "window/color_2", "Color 2", true, true);
1083    aws->at_x(tabstop);
1084    aws->create_input_field("window/color_2", 12);
1085
1086    aws->at_newline();
1087
1088    AW_preset_create_color_chooser(aws, "window/color_3", "Color 3", true, true);
1089    aws->at_x(tabstop);
1090    aws->create_input_field("window/color_3", 12);
1091   
1092    aws->at_newline();
1093
1094    aws->window_fit();
1095    return (AW_window *)aws;
1096
1097}
1098
1099static void add_common_property_menu_entries(AW_window *aw) {
1100    aw->insert_menu_topic("enable_advices",   "Reactivate advices",   "R", "advice.hlp",    AWM_ALL, (AW_CB)AW_reactivate_all_advices,   0, 0);
1101    aw->insert_menu_topic("enable_questions", "Reactivate questions", "q", "questions.hlp", AWM_ALL, (AW_CB)AW_reactivate_all_questions, 0, 0);
1102}
1103void AW_insert_common_property_menu_entries(AW_window_menu_modes *awmm) { add_common_property_menu_entries(awmm); }
1104void AW_insert_common_property_menu_entries(AW_window_simple_menu *awsm) { add_common_property_menu_entries(awsm); }
Note: See TracBrowser for help on using the repository browser.