source: tags/old_import_filter/WINDOW/AW_click.cxx

Last change on this file was 7669, checked in by westram, 13 years ago
  • merge from dev [7638] [7639] [7646] [7645] [7647] [7648] [7649] [7650] [7651] [7652]
    • compatibility with cppcheck 1.49 (assert + ASSERT_RESULT)
    • fixed (AWT and WINDOW)
      • missing const attributes
      • uninitialized/unused/wrong-scoped/useless variables
      • alloc/free/delete mismatches
      • use assertions instead of null-pointer-assignments
    • removed
      • AW_device_Xm fast/slow/fastflag
    • new class AW_scalar
      • can hold any AW_awar-value
        • uses int32_t (AW_awar is based on GB_INT which is 32 bit)
      • knows its type
      • use in
        • AW_option_struct / AW_toggle_struct (both classes were identical → replaced them by new class AW_widget_value_pair)
        • in AW_variable_update_struct (now VarUpdateInfo)
        • in AW_select_table_struct (now AW_selection_list_entry)
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 7.3 KB
Line 
1// =============================================================== //
2//                                                                 //
3//   File      : AW_click.cxx                                      //
4//   Purpose   :                                                   //
5//                                                                 //
6//   Institute of Microbiology (Technical University Munich)       //
7//   http://www.arb-home.de/                                       //
8//                                                                 //
9// =============================================================== //
10
11#include "aw_common.hxx"
12
13using namespace AW;
14
15// ------------------------
16//      AW_device_click
17
18void AW_device_click::init(AW_pos mousex, AW_pos mousey, AW_pos max_distance_linei, AW_pos max_distance_texti, AW_pos /*radi*/, AW_bitset filteri) {
19    mouse_x           = mousex;
20    mouse_y           = mousey;
21    filter            = filteri;
22    max_distance_line = max_distance_linei*max_distance_linei;
23    max_distance_text = max_distance_texti;
24    memset((char *)&opt_line, 0, sizeof(opt_line));
25    memset((char *)&opt_text, 0, sizeof(opt_text));
26    opt_line.exists   = false;
27    opt_text.exists   = false;
28}
29
30
31AW_DEVICE_TYPE AW_device_click::type() {
32    return AW_DEVICE_CLICK;
33}
34
35
36bool AW_device_click::line_impl(int /*gc*/, const LineVector& Line, AW_bitset filteri) {
37    if (!(filteri & filter)) return false;
38
39    LineVector transLine = transform(Line);
40    LineVector clippedLine;
41    bool       drawflag  = clip(transLine, clippedLine);
42
43    if (drawflag) {
44        Position mouse(mouse_x, mouse_y);
45        double   nearest_rel_pos;
46        Position nearest  = nearest_linepoint(mouse, clippedLine, nearest_rel_pos);
47        double   distance = Distance(mouse, nearest);
48
49        if (distance < max_distance_line) {
50            max_distance_line = distance;
51           
52            opt_line.x0 = Line.xpos();
53            opt_line.y0 = Line.ypos();
54            opt_line.x1 = Line.head().xpos();
55            opt_line.y1 = Line.head().ypos();
56
57            opt_line.distance        = distance;
58            opt_line.nearest_rel_pos = nearest_rel_pos;
59
60            if (click_cd) {
61                opt_line.client_data1 = click_cd->get_cd1();
62                opt_line.client_data2 = click_cd->get_cd2();
63            }
64            else {
65                opt_line.client_data1 = 0;
66                opt_line.client_data2 = 0;
67            }
68            opt_line.exists = true;
69        }
70    }
71    return drawflag;
72}
73
74
75bool AW_device_click::text_impl(int gc, const char *str, const AW::Position& pos, AW_pos alignment, AW_bitset filteri, long opt_strlen) {
76    bool drawflag = false;
77    if (filteri & filter) {
78        AW_pos X0, Y0;          // Transformed pos
79        this->transform(pos.xpos(), pos.ypos(), X0, Y0);
80
81        const AW_GC           *gcm         = get_common()->map_gc(gc);
82        const AW_font_limits&  font_limits = gcm->get_font_limits();
83
84        AW_pos Y1 = Y0+font_limits.descent;
85        Y0        = Y0-font_limits.ascent;
86
87        // Fast check text against top/bottom clip
88        const AW_screen_area& clipRect = get_cliprect();
89        if (clipRect.t == 0) {
90            if (Y1 < clipRect.t) return false;
91        }
92        else {
93            if (Y0 < clipRect.t) return false;
94        }
95
96        if (clipRect.b == get_common()->get_screen().b) {
97            if (Y0 > clipRect.b) return false;
98        }
99        else {
100            if (Y1 > clipRect.b) return false;
101        }
102
103        // vertical check mouse against textsurrounding
104        bool   exact     = true;
105        double best_dist = 0;
106
107        // @@@ the following section produces wrong result
108        if (mouse_y > Y1) {     // outside text
109            if (mouse_y > Y1+max_distance_text) return false; // too far above
110            exact = false;
111            best_dist = mouse_y - Y1;
112        }
113        else if (mouse_y < Y0) {
114            if (mouse_y < Y0-max_distance_text) return false; // too far below
115            exact = false;
116            best_dist = Y0 - mouse_y;
117        }
118
119        // align text
120        int len        = opt_strlen ? opt_strlen : strlen(str);
121        int text_width = (int)get_string_size(gc, str, len);
122
123        X0        = x_alignment(X0, text_width, alignment);
124        AW_pos X1 = X0+text_width;
125
126        // check against left right clipping areas
127        if (X1 < clipRect.l) return false;
128        if (X0 > clipRect.r) return false;
129
130        if (mouse_x < X0) return false; // left of text
131        if (mouse_x > X1) return false; // right of text
132
133        max_distance_text = best_dist; // exact hit -> distance = 0;
134
135        int position;
136        if (font_limits.is_monospaced()) {
137            short letter_width = font_limits.width;
138            position = (int)((mouse_x-X0)/letter_width);
139            if (position<0) position = 0;
140            if (position>(len-1)) position = len-1;
141        }
142        else { // proportional font
143            position   = 0;
144            int tmp_offset = 0;
145            while (position<=len) {
146                tmp_offset += gcm->get_width_of_char(str[position]);
147                if (mouse_x <= X0+tmp_offset) break;
148                position++;
149            }
150        }
151
152        AW_pos dist2center = Distance(Position(mouse_x, mouse_y),
153                                      LineVector(X0, Y0, X0+text_width, Y1).centroid());
154
155        if (!opt_text.exists || // first candidate
156            (!opt_text.exactHit && exact) || // previous candidate was no exact hit
157            (dist2center<opt_text.dist2center)) // distance to text-center is smaller
158        {
159            opt_text.textArea     = Rectangle(rtransform(LineVector(X0, Y0, X1, Y1)));
160            opt_text.alignment    = alignment;
161            opt_text.rotation     = 0;
162            opt_text.distance     = max_distance_text;
163            opt_text.dist2center  = dist2center;
164            opt_text.cursor       = position;
165            if (click_cd) {
166                opt_text.client_data1 = click_cd->get_cd1();
167                opt_text.client_data2 = click_cd->get_cd2();
168            }
169            else {
170                opt_text.client_data1 = 0;
171                opt_text.client_data2 = 0;
172            }
173            // opt_text.client_data1 = clientdata1;
174            // opt_text.client_data2 = clientdata2;
175            opt_text.exists       = true;
176            opt_text.exactHit     = exact;
177        }
178        drawflag = true;
179    }
180    return drawflag;
181}
182
183
184void AW_device_click::get_clicked_line(class AW_clicked_line *ptr) const {
185    *ptr = opt_line;
186}
187
188
189void AW_device_click::get_clicked_text(class AW_clicked_text *ptr) const {
190    *ptr = opt_text;
191}
192
193bool AW_getBestClick(AW_clicked_line *cl, AW_clicked_text *ct, AW_CL *cd1, AW_CL *cd2) {
194    // detect the nearest item next to 'click'
195    // and return that items callback params.
196    // returns false, if nothing has been clicked
197
198    AW_clicked_element *bestClick = 0;
199
200    if (cl->exists) {
201        if (ct->exists) {
202            if (cl->distance < ct->distance) {
203                bestClick = cl;
204            }
205            else {
206                bestClick = ct;
207            }
208        }
209        else {
210            bestClick = cl;
211        }
212    }
213    else if (ct->exists) {
214        bestClick = ct;
215    }
216
217    if (bestClick) {
218        *cd1 = bestClick->client_data1;
219        *cd2 = bestClick->client_data2;
220    }
221    else {
222        *cd1 = 0;
223        *cd2 = 0;
224    }
225
226    return bestClick;
227}
228
Note: See TracBrowser for help on using the repository browser.