1 | // ================================================================ // |
---|
2 | // // |
---|
3 | // File : aw_device_click.hxx // |
---|
4 | // Purpose : Detect which graphical element is "nearby" // |
---|
5 | // a given mouse position // |
---|
6 | // // |
---|
7 | // Institute of Microbiology (Technical University Munich) // |
---|
8 | // http://www.arb-home.de/ // |
---|
9 | // // |
---|
10 | // ================================================================ // |
---|
11 | |
---|
12 | #ifndef AW_DEVICE_CLICK_HXX |
---|
13 | #define AW_DEVICE_CLICK_HXX |
---|
14 | |
---|
15 | #ifndef AW_DEVICE_HXX |
---|
16 | #include "aw_device.hxx" |
---|
17 | #endif |
---|
18 | |
---|
19 | // @@@ TODO: elements of the following classes should go private! |
---|
20 | |
---|
21 | class AW_clicked_element { |
---|
22 | AW_CL client_data1; |
---|
23 | AW_CL client_data2; |
---|
24 | |
---|
25 | public: // @@@ make private |
---|
26 | |
---|
27 | bool exists; // true if a drawn element was clicked, else false |
---|
28 | int distance; // distance in pixel to nearest line/text |
---|
29 | |
---|
30 | AW_pos nearest_rel_pos; // 0 = at left(upper) small-side, 1 = at right(lower) small-side of textArea |
---|
31 | |
---|
32 | protected: |
---|
33 | |
---|
34 | void init() { |
---|
35 | client_data1 = 0; |
---|
36 | client_data2 = 0; |
---|
37 | exists = false; |
---|
38 | distance = -1; |
---|
39 | nearest_rel_pos = 0; |
---|
40 | } |
---|
41 | |
---|
42 | AW_clicked_element() { init(); } |
---|
43 | virtual ~AW_clicked_element() {} |
---|
44 | |
---|
45 | virtual void clear() = 0; |
---|
46 | |
---|
47 | public: |
---|
48 | |
---|
49 | AW_CL cd1() const { return client_data1; } |
---|
50 | AW_CL cd2() const { return client_data2; } |
---|
51 | |
---|
52 | void copy_cds(const AW_click_cd *click_cd) { |
---|
53 | if (click_cd) { |
---|
54 | client_data1 = click_cd->get_cd1(); |
---|
55 | client_data2 = click_cd->get_cd2(); |
---|
56 | } |
---|
57 | else { |
---|
58 | client_data1 = 0; |
---|
59 | client_data2 = 0; |
---|
60 | } |
---|
61 | } |
---|
62 | |
---|
63 | virtual AW::Position get_attach_point() const = 0; |
---|
64 | virtual bool is_text() const = 0; |
---|
65 | |
---|
66 | bool is_line() const { return !is_text(); } |
---|
67 | |
---|
68 | double get_rel_pos() const { return nearest_rel_pos; } |
---|
69 | void set_rel_pos(double rel) { aw_assert(rel >= 0.0 && rel <= 1.0); nearest_rel_pos = rel; } |
---|
70 | |
---|
71 | AW::LineVector get_connecting_line(const AW_clicked_element& other) const { |
---|
72 | //! determine LineVector between two clicked elements (e.g. for drag&drop) |
---|
73 | return AW::LineVector(get_attach_point(), other.get_attach_point()); |
---|
74 | } |
---|
75 | |
---|
76 | virtual int indicate_selected(AW_device *d, int gc) const = 0; |
---|
77 | }; |
---|
78 | |
---|
79 | class AW_clicked_line : public AW_clicked_element { |
---|
80 | public: |
---|
81 | AW_pos x0, y0, x1, y1; // @@@ make this a LineVector and private! |
---|
82 | private: |
---|
83 | void init() { |
---|
84 | x0 = 0; y0 = 0; |
---|
85 | x1 = 0; y1 = 0; |
---|
86 | } |
---|
87 | public: |
---|
88 | |
---|
89 | AW_clicked_line() { init(); } |
---|
90 | void clear() OVERRIDE { AW_clicked_element::init(); init(); } |
---|
91 | |
---|
92 | bool is_text() const OVERRIDE { return false; } |
---|
93 | bool operator == (const AW_clicked_line& other) const { return nearlyEqual(get_line(), other.get_line()); } |
---|
94 | |
---|
95 | AW::Position get_attach_point() const OVERRIDE { |
---|
96 | double nrp = get_rel_pos(); |
---|
97 | return AW::Position(x0*(1-nrp)+x1*nrp, |
---|
98 | y0*(1-nrp)+y1*nrp); |
---|
99 | } |
---|
100 | |
---|
101 | AW::LineVector get_line() const { return AW::LineVector(x0, y0, x1, y1); } |
---|
102 | int indicate_selected(AW_device *d, int gc) const OVERRIDE; |
---|
103 | }; |
---|
104 | |
---|
105 | class AW_clicked_text : public AW_clicked_element { |
---|
106 | public: // @@@ make members private |
---|
107 | AW::Rectangle textArea; // world coordinates of text |
---|
108 | int cursor; // which letter was selected, from 0 to strlen-1 [or -1 if not 'exactHit'] |
---|
109 | bool exactHit; // true -> real click inside text bounding-box (not only near text) (@@@ redundant: exactHit == (distance == 0)) |
---|
110 | private: |
---|
111 | void init() { |
---|
112 | textArea = AW::Rectangle(); |
---|
113 | cursor = -1; |
---|
114 | exactHit = false; |
---|
115 | } |
---|
116 | public: |
---|
117 | |
---|
118 | AW_clicked_text() { init(); } |
---|
119 | void clear() OVERRIDE { AW_clicked_element::init(); init(); } |
---|
120 | |
---|
121 | bool is_text() const OVERRIDE { return true; } |
---|
122 | bool operator == (const AW_clicked_text& other) const { return nearlyEqual(textArea, other.textArea); } |
---|
123 | |
---|
124 | AW::Position get_attach_point() const OVERRIDE { |
---|
125 | return textArea.centroid(); // @@@ uses center atm - should attach to bounding box |
---|
126 | } |
---|
127 | int indicate_selected(AW_device *d, int gc) const OVERRIDE; |
---|
128 | }; |
---|
129 | |
---|
130 | #define AWT_CATCH 30 // max-pixel distance to graphical element (to accept a click or command) |
---|
131 | #define AWT_NO_CATCH -1 |
---|
132 | |
---|
133 | class AW_device_click : public AW_simple_device { |
---|
134 | AW_pos mouse_x, mouse_y; // @@@ use 'int' instead |
---|
135 | int max_distance_line; |
---|
136 | int max_distance_text; |
---|
137 | |
---|
138 | bool line_impl(int gc, const AW::LineVector& Line, AW_bitset filteri) OVERRIDE; |
---|
139 | bool text_impl(int gc, const char *str, const AW::Position& pos, AW_pos alignment, AW_bitset filteri, long opt_strlen) OVERRIDE; |
---|
140 | bool invisible_impl(const AW::Position& pos, AW_bitset filteri) OVERRIDE { return generic_invisible(pos, filteri); } |
---|
141 | |
---|
142 | void specific_reset() OVERRIDE {} |
---|
143 | |
---|
144 | public: |
---|
145 | AW_clicked_line opt_line; // @@@ make private |
---|
146 | AW_clicked_text opt_text; |
---|
147 | |
---|
148 | AW_device_click(AW_common *common_); |
---|
149 | |
---|
150 | AW_DEVICE_TYPE type() OVERRIDE; |
---|
151 | |
---|
152 | void init_click(AW_pos mousex, AW_pos mousey, int max_distance, AW_bitset filteri); |
---|
153 | |
---|
154 | void get_clicked_line(class AW_clicked_line *ptr) const; // @@@ make real accessors returning const& |
---|
155 | void get_clicked_text(class AW_clicked_text *ptr) const; |
---|
156 | }; |
---|
157 | |
---|
158 | #else |
---|
159 | #error aw_device_click.hxx included twice |
---|
160 | #endif // AW_DEVICE_CLICK_HXX |
---|