source: tags/arb-6.0/WINDOW/AW_preset.cxx

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