source: tags/ms_r17q2/WINDOW/AW_at.cxx

Last change on this file was 15822, checked in by westram, 7 years ago
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 15.4 KB
Line 
1// =============================================================== //
2//                                                                 //
3//   File      : AW_at.cxx                                         //
4//   Purpose   :                                                   //
5//                                                                 //
6//   Institute of Microbiology (Technical University Munich)       //
7//   http://www.arb-home.de/                                       //
8//                                                                 //
9// =============================================================== //
10
11#include "aw_at.hxx"
12#include "aw_window.hxx"
13#include "aw_xfig.hxx"
14#include "aw_root.hxx"
15
16#include <arbdbt.h>
17
18AW_at::AW_at() {
19    memset((char*)this, 0, sizeof(AW_at));
20
21    length_of_buttons = 10;
22    height_of_buttons = 0;
23    shadow_thickness  = 2;
24    widget_mask       = AWM_ALL;
25}
26
27void AW_window::at(const char *at_id) {
28    char to_position[100];
29    memset(to_position, 0, sizeof(to_position));
30
31    _at->attach_y   = _at->attach_x = false;
32    _at->attach_ly  = _at->attach_lx = false;
33    _at->attach_any = false;
34
35    if (!xfig_data) GBK_terminatef("no xfig-data loaded, can't position at(\"%s\")", at_id);
36
37    AW_xfig     *xfig = (AW_xfig *)xfig_data;
38    AW_xfig_pos *pos;
39
40    pos = (AW_xfig_pos*)GBS_read_hash(xfig->at_pos_hash, at_id);
41
42    if (!pos) {
43        sprintf(to_position, "X:%s", at_id);
44        pos = (AW_xfig_pos*)GBS_read_hash(xfig->at_pos_hash, to_position);
45        if (pos) _at->attach_any = _at->attach_lx = true;
46    }
47    if (!pos) {
48        sprintf(to_position, "Y:%s", at_id);
49        pos = (AW_xfig_pos*)GBS_read_hash(xfig->at_pos_hash, to_position);
50        if (pos) _at->attach_any = _at->attach_ly = true;
51    }
52    if (!pos) {
53        sprintf(to_position, "XY:%s", at_id);
54        pos = (AW_xfig_pos*)GBS_read_hash(xfig->at_pos_hash, to_position);
55        if (pos) _at->attach_any = _at->attach_lx = _at->attach_ly = true;
56    }
57
58    if (!pos) GBK_terminatef("ID '%s' does not exist in xfig file", at_id);
59
60    at((pos->x - xfig->minx), (pos->y - xfig->miny - this->get_root()->font_height - 9));
61    _at->correct_for_at_center = pos->center;
62
63    sprintf(to_position, "to:%s", at_id);
64    pos = (AW_xfig_pos*)GBS_read_hash(xfig->at_pos_hash, to_position);
65
66    if (!pos) {
67        sprintf(to_position, "to:X:%s", at_id);
68        pos = (AW_xfig_pos*)GBS_read_hash(xfig->at_pos_hash, to_position);
69        if (pos) _at->attach_any = _at->attach_x = true;
70    }
71    if (!pos) {
72        sprintf(to_position, "to:Y:%s", at_id);
73        pos = (AW_xfig_pos*)GBS_read_hash(xfig->at_pos_hash, to_position);
74        if (pos) _at->attach_any = _at->attach_y = true;
75    }
76    if (!pos) {
77        sprintf(to_position, "to:XY:%s", at_id);
78        pos = (AW_xfig_pos*)GBS_read_hash(xfig->at_pos_hash, to_position);
79        if (pos) _at->attach_any = _at->attach_x = _at->attach_y = true;
80    }
81
82    if (pos) {
83        _at->to_position_exists = true;
84        _at->to_position_x = (pos->x - xfig->minx);
85        _at->to_position_y = (pos->y - xfig->miny);
86        _at->correct_for_at_center = 0; // always justify left when a to-position exists
87    }
88    else {
89        _at->to_position_exists = false;
90    }
91}
92
93void AW_window::at(int x, int y) {
94    at_x(x);
95    at_y(y);
96}
97
98void AW_window::at_x(int x) {
99    if (_at->x_for_next_button > _at->max_x_size) _at->max_x_size = _at->x_for_next_button;
100    _at->x_for_next_button = x;
101    if (_at->x_for_next_button > _at->max_x_size) _at->max_x_size = _at->x_for_next_button;
102}
103
104void AW_window::at_y(int y) {
105    if (_at->y_for_next_button + _at->biggest_height_of_buttons > _at->max_y_size)
106        _at->max_y_size = _at->y_for_next_button + _at->biggest_height_of_buttons;
107    _at->biggest_height_of_buttons = _at->biggest_height_of_buttons + _at->y_for_next_button - y;
108    if (_at->biggest_height_of_buttons<0) {
109        _at->biggest_height_of_buttons = 0;
110        if (_at->max_y_size < y)    _at->max_y_size = y;
111    }
112    _at->y_for_next_button = y;
113}
114
115void AW_window::at_shift(int x, int y) {
116    at(x+_at->x_for_next_button, y+_at->y_for_next_button);
117}
118
119void AW_window::at_newline() {
120    if (_at->do_auto_increment) {
121        at_y(_at->auto_increment_y + _at->y_for_next_button);
122    }
123    else {
124        if (_at->do_auto_space) {
125            at_y(_at->y_for_next_button + _at->auto_space_y + _at->biggest_height_of_buttons);
126        }
127        else {
128            GBK_terminate("neither auto_space nor auto_increment activated while using at_newline");
129        }
130    }
131    at_x(_at->x_for_newline);
132}
133
134bool AW_window::at_ifdef(const  char *at_id_) {
135    AW_xfig *xfig = (AW_xfig *)xfig_data;
136    if (!xfig) return false;
137
138    char buffer[100];
139
140#if defined(DEBUG)
141    int printed =
142#endif // DEBUG
143        sprintf(buffer, "XY:%s", at_id_);
144#if defined(DEBUG)
145    aw_assert(printed<100);
146#endif // DEBUG
147
148    if (GBS_read_hash(xfig->at_pos_hash, buffer+3)) return true; // "tag"
149    if (GBS_read_hash(xfig->at_pos_hash, buffer+1)) return true; // "Y:tag"
150    if (GBS_read_hash(xfig->at_pos_hash, buffer)) return true; // "XY:tag"
151    buffer[1] = 'X';
152    if (GBS_read_hash(xfig->at_pos_hash, buffer+1)) return true; // "X:tag"
153
154    return false;
155}
156
157void AW_window::at_attach(int x, int y) {
158    // similar to using "$XY:noId" in xfig, but works w/o defined 'noId' (ie. w/o having xfig)
159    //
160    // meaning of x/y:
161    // - positive values = absolute position like at(x, y) does
162    // - negative values = relative position to right/lower border.
163    //                     Position will get attached to that border.
164    //                     For 'x' position widget will also become right-aligned.
165    // - zero = keep current at-position
166    //
167    // Note: window should have already reached its minimum size when using an at_attach..-function!
168
169    bool attach_x = x<0;
170    bool attach_y = y<0;
171
172    _at->attach_any = attach_x || attach_y;
173
174    aw_assert(_at->attach_any); // call has no effect (use at(x, y) to set an absolute position!)
175
176    _at->attach_lx = attach_x;
177    _at->attach_ly = attach_y;
178    _at->correct_for_at_center = attach_x ? 2 : 0;
179
180    int width, height;
181    get_window_size(width, height);
182
183    if (x) at_x(attach_x ? width+x : x);
184    if (y) at_y(attach_y ? height+y : y);
185}
186
187void AW_window::at_attach_to(bool attach_x, bool attach_y, int xoff, int yoff) {
188    // similar to using "$to:XY:noId" in xfig, but works w/o defined 'noId'
189    //
190    // negative offsets define the to-position of the widget relative to right/lower border (of the window)
191    // positive offsets define the size of the widget (from current at-position)
192    //
193    // Note: window should have already reached its minimum size when using an at_attach..-function!
194
195    _at->attach_any = _at->attach_any || attach_x || attach_y;
196    _at->attach_x   = attach_x;
197    _at->attach_y   = attach_y;
198
199    _at->to_position_exists = true;
200    _at->to_position_x      = xoff >= 0 ? _at->x_for_next_button + xoff : _at->max_x_size+xoff;
201    _at->to_position_y      = yoff >= 0 ? _at->y_for_next_button + yoff : _at->max_y_size+yoff;
202
203    aw_assert(_at->to_position_x > _at->x_for_next_button);
204    aw_assert(_at->to_position_y > _at->y_for_next_button); // invalid (would calculate ultra-large button-size in create_button)
205
206    if (_at->to_position_x > _at->max_x_size) _at->max_x_size = _at->to_position_x;
207    if (_at->to_position_y > _at->max_y_size) _at->max_y_size = _at->to_position_y;
208
209    _at->correct_for_at_center = 0;
210}
211void AW_window::at_unattach() {
212    _at->attach_any    =
213        _at->attach_x  = _at->attach_y  =
214        _at->attach_lx = _at->attach_ly  = false;
215
216    _at->to_position_exists    = false;
217    _at->correct_for_at_center = 0;
218}
219
220void AW_window::unset_at_commands() {
221    _callback   = NULL;
222    _d_callback = NULL;
223
224    _at->correct_for_at_center = 0;
225    _at->to_position_exists    = false;
226    _at->highlight             = false;
227
228    freenull(_at->helptext_for_next_button);
229    freenull(_at->label_for_inputfield);
230
231    _at->background_color = 0;
232}
233
234void AW_window::increment_at_commands(int width, int height) {
235
236    at_shift(width, 0);
237    at_shift(-width, 0);        // set bounding box
238
239    if (_at->do_auto_increment) {
240        at_shift(_at->auto_increment_x, 0);
241    }
242    if (_at->do_auto_space) {
243        at_shift(_at->auto_space_x + width, 0);
244    }
245
246    if (_at->biggest_height_of_buttons < height) {
247        _at->biggest_height_of_buttons = height;
248    }
249
250    if (_at->max_y_size < (_at->y_for_next_button + _at->biggest_height_of_buttons + 3.0)) {
251        _at->max_y_size = _at->y_for_next_button + _at->biggest_height_of_buttons + 3;
252    }
253
254    if (_at->max_x_size < (_at->x_for_next_button + this->get_root()->font_width)) {
255        _at->max_x_size = _at->x_for_next_button + this->get_root()->font_width;
256    }
257}
258
259void AW_window::auto_space(int x, int y) {
260    _at->do_auto_space = true;
261    _at->auto_space_x  = x;
262    _at->auto_space_y  = y;
263
264    _at->do_auto_increment = false;
265
266    _at->x_for_newline             = _at->x_for_next_button;
267    _at->biggest_height_of_buttons = 0;
268}
269
270// -------------------------------------------------------------------------
271//      force-diff-sync 9126478246 (remove after merging back to trunk)
272
273void AW_window::auto_increment(int x, int y) {
274    _at->do_auto_increment         = true;
275    _at->auto_increment_x          = x;
276    _at->auto_increment_y          = y;
277    _at->x_for_newline             = _at->x_for_next_button;
278    _at->do_auto_space             = false;
279    _at->biggest_height_of_buttons = 0;
280}
281
282void AW_window::label_length(int length) {
283    _at->length_of_label_for_inputfield = length;
284}
285
286void AW_window::button_length(int length) {
287    _at->length_of_buttons = length;
288}
289
290int  AW_window::get_button_length() const {
291    return _at->length_of_buttons;
292}
293
294void AW_window::get_at_position(int *x, int *y) const {
295    *x = _at->x_for_next_button;
296    *y = _at->y_for_next_button;
297}
298
299int AW_window::get_at_xposition() const {
300    return _at->x_for_next_button;
301}
302
303int AW_window::get_at_yposition() const {
304    return _at->y_for_next_button;
305}
306
307// -------------------
308//      AW_at_size
309
310class AW_at_size : public AW_at_storage {
311    int  to_offset_x;                               // here we use offsets (not positions like in AW_at)
312    int  to_offset_y;
313    bool to_position_exists;
314
315    bool attach_x;           // attach right side to right form
316    bool attach_y;
317    bool attach_lx;          // attach left side to right form
318    bool attach_ly;
319    bool attach_any;
320
321public:
322    AW_at_size()
323        : to_offset_x(0),
324          to_offset_y(0),
325          to_position_exists(false),
326          attach_x(false),
327          attach_y(false),
328          attach_lx(false),
329          attach_ly(false),
330          attach_any(false)
331    {}
332
333    void store(const AW_at& at) OVERRIDE;
334    void restore(AW_at& at) const OVERRIDE;
335};
336
337void AW_at_size::store(const AW_at& at) {
338    to_position_exists = at.to_position_exists;
339    if (to_position_exists) {
340        to_offset_x = at.to_position_x - at.x_for_next_button;
341        to_offset_y = at.to_position_y - at.y_for_next_button;
342    }
343    attach_x   = at.attach_x;
344    attach_y   = at.attach_y;
345    attach_lx  = at.attach_lx;
346    attach_ly  = at.attach_ly;
347    attach_any = at.attach_any;
348}
349
350void AW_at_size::restore(AW_at& at) const {
351    at.to_position_exists = to_position_exists;
352    if (to_position_exists) {
353        at.to_position_x = at.x_for_next_button + to_offset_x;
354        at.to_position_y = at.y_for_next_button + to_offset_y;
355    }
356    at.attach_x   = attach_x;
357    at.attach_y   = attach_y;
358    at.attach_lx  = attach_lx;
359    at.attach_ly  = attach_ly;
360    at.attach_any = attach_any;
361}
362
363// -------------------
364//      AW_at_maxsize
365
366class AW_at_maxsize : public AW_at_storage {
367    int maxx;
368    int maxy;
369
370public:
371    AW_at_maxsize()
372        : maxx(0),
373          maxy(0)
374    {}
375
376    void store(const AW_at &at) OVERRIDE;
377    void restore(AW_at &at) const OVERRIDE;
378};
379
380void AW_at_maxsize::store(const AW_at &at) {
381    maxx = at.max_x_size;
382    maxy = at.max_y_size;
383}
384
385void AW_at_maxsize::restore(AW_at &at) const {
386    at.max_x_size = maxx;
387    at.max_y_size = maxy;
388}
389
390// -------------------
391//      AW_at_auto
392
393class AW_at_auto : public AW_at_storage {
394    enum { INC, SPACE, OFF } type;
395    int x, y;
396    int xfn, xfnb, yfnb, bhob;
397public:
398    AW_at_auto() : type(OFF), x(0), y(0), xfn(0), xfnb(0), yfnb(0), bhob(0) {}
399
400    void store(const AW_at &at) OVERRIDE;
401    void restore(AW_at &at) const OVERRIDE;
402};
403
404void AW_at_auto::store(const AW_at &at) {
405    if (at.do_auto_increment) {
406        type = INC;
407        x    = at.auto_increment_x;
408        y    = at.auto_increment_y;
409    }
410    else if (at.do_auto_space)  {
411        type = SPACE;
412        x    = at.auto_space_x;
413        y    = at.auto_space_y;
414    }
415    else {
416        type = OFF;
417    }
418
419    xfn  = at.x_for_newline;
420    xfnb = at.x_for_next_button;
421    yfnb = at.y_for_next_button;
422    bhob = at.biggest_height_of_buttons;
423}
424
425void AW_at_auto::restore(AW_at &at) const {
426    at.do_auto_space     = (type == SPACE);
427    at.do_auto_increment = (type == INC);
428
429    if (at.do_auto_space) {
430        at.auto_space_x = x;
431        at.auto_space_y = y;
432    }
433    else if (at.do_auto_increment) {
434        at.auto_increment_x = x;
435        at.auto_increment_y = y;
436    }
437
438    at.x_for_newline             = xfn;
439    at.x_for_next_button         = xfnb;
440    at.y_for_next_button         = yfnb;
441    at.biggest_height_of_buttons = bhob;
442}
443
444// -------------------------------
445//      AW_at_storage factory
446
447AW_at_storage *AW_at_storage::make(AW_window *aww, AW_at_storage_type type) {
448    AW_at_storage *s = NULL;
449    switch (type) {
450        case AW_AT_SIZE_AND_ATTACH: s = new AW_at_size(); break;
451        case AW_AT_AUTO:            s = new AW_at_auto(); break;
452        case AW_AT_MAXSIZE:         s = new AW_at_maxsize(); break;
453    }
454    aww->store_at_to(*s);
455    return s;
456}
457
458// -------------------------------------------------------------------------
459//      force-diff-sync 6423462367 (remove after merging back to trunk)
460
461int AW_window::calculate_string_width(int columns) const {
462    if (xfig_data) {
463        AW_xfig *xfig = (AW_xfig *)xfig_data;
464        return (int)(columns * xfig->font_scale * XFIG_DEFAULT_FONT_WIDTH);   // stdfont 8x13
465    }
466    else {
467        return columns * XFIG_DEFAULT_FONT_WIDTH; // stdfont 8x13
468    }
469}
470
471int AW_window::calculate_string_height(int rows, int offset) const {
472    if (xfig_data) {
473        AW_xfig *xfig = (AW_xfig *)xfig_data;
474        return (int)((rows * XFIG_DEFAULT_FONT_HEIGHT + offset) * xfig->font_scale); // stdfont 8x13
475    }
476    else {
477        return (rows * XFIG_DEFAULT_FONT_HEIGHT + offset);    // stdfont 8x13
478    }
479}
480
481char *AW_window::align_string(const char *label_text, int columns) {
482    // shortens or expands 'label_text' to 'columns' columns
483    // if label_text contains '\n', each "line" is handled separately
484
485    const char *lf     = strchr(label_text, '\n');
486    char       *result = 0;
487
488    if (!lf) {
489        ARB_alloc(result, columns+1);
490
491        int len              = strlen(label_text);
492        if (len>columns) len = columns;
493
494        memcpy(result, label_text, len);
495        if (len<columns) memset(result+len, ' ', columns-len);
496        result[columns] = 0;
497    }
498    else {
499        char *part1    = ARB_strpartdup(label_text, lf-1);
500        char *aligned1 = align_string(part1, columns);
501        char *aligned2 = align_string(lf+1, columns);
502
503        result = GBS_global_string_copy("%s\n%s", aligned1, aligned2);
504
505        free(aligned2);
506        free(aligned1);
507        free(part1);
508    }
509    return result;
510}
511
Note: See TracBrowser for help on using the repository browser.