ARB
aw_device_click.hxx
Go to the documentation of this file.
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 
20  AW_CL client_data1;
21  AW_CL client_data2;
22 
23  bool exists; // true if a drawn element was clicked, else false
24  int distance; // distance in pixel to nearest line/text
25  AW_pos nearest_rel_pos; // 0 = at left(upper) small-side, 1 = at right(lower) small-side of textArea or line (does not make sense for box or polygon)
26 
27  void copy_cds(const AW_click_cd *click_cd) {
28  if (click_cd) {
29  client_data1 = click_cd->get_cd1();
30  client_data2 = click_cd->get_cd2();
31  }
32  else {
33  client_data1 = 0;
34  client_data2 = 0;
35  }
36  }
37  void set_rel_pos(double rel) { aw_assert(rel >= 0.0 && rel <= 1.0); nearest_rel_pos = rel; }
38 
39 protected:
40 
42  : client_data1(0),
43  client_data2(0),
44  exists(false),
45  distance(-1),
46  nearest_rel_pos(0)
47  {}
48 
49  void assign(int distance_, const AW_pos& nearest_rel_pos_, const AW_click_cd *click_cd_) {
50  distance = distance_;
51  set_rel_pos(nearest_rel_pos_);
52  copy_cds(click_cd_);
53  exists = true;
54  }
55 
56 public:
57  virtual ~AW_clicked_element() {}
58 
59  AW_CL cd1() const { return client_data1; }
60  AW_CL cd2() const { return client_data2; }
61 
62  virtual AW::Position get_attach_point() const = 0;
63  virtual AW::Rectangle get_bounding_box() const = 0;
64  virtual AW_clicked_element *clone() const = 0;
65 
66  bool does_exist() const { return exists; }
67 
68  inline bool is_text() const;
69  inline bool is_line() const;
70  inline bool is_box() const;
71  inline bool is_polygon() const;
72 
73  double get_rel_pos() const { return nearest_rel_pos; }
74  int get_distance() const { return distance; }
78  }
79 
80  virtual bool operator==(const AW_clicked_element& other) const = 0;
81  virtual int indicate_selected(AW_device *d, int gc) const = 0;
82 };
83 
85  AW::LineVector line; // world coordinates of clicked line
86 public:
87  void assign(const AW::LineVector& line_, int distance_, const AW_pos& nearest_rel_pos_, const AW_click_cd *click_cd_) {
88  AW_clicked_element::assign(distance_, nearest_rel_pos_, click_cd_);
89  line = line_;
90  }
91 
92  bool operator == (const AW_clicked_element& other) const OVERRIDE {
93  const AW_clicked_line *otherLine = dynamic_cast<const AW_clicked_line*>(&other);
94  return otherLine ? nearlyEqual(get_line(), otherLine->get_line()) : false;
95  }
96 
98  double nrp = get_rel_pos();
99  return line.start() + nrp*line.line_vector();
100  }
102  const AW::LineVector& get_line() const { return line; }
103 
104  int indicate_selected(AW_device *d, int gc) const OVERRIDE;
105  AW_clicked_element *clone() const OVERRIDE { return new AW_clicked_line(*this); }
106 };
107 
109  AW::Rectangle textArea; // world coordinates of clicked text
110 public:
111  void assign(AW::Rectangle textArea_, int distance_, const AW_pos& nearest_rel_pos_, const AW_click_cd *click_cd_) {
112  AW_clicked_element::assign(distance_, nearest_rel_pos_, click_cd_);
113  textArea = textArea_;
114  }
115 
116  bool operator == (const AW_clicked_element& other) const OVERRIDE {
117  const AW_clicked_text *otherText = dynamic_cast<const AW_clicked_text*>(&other);
118  return otherText ? nearlyEqual(textArea, otherText->textArea) : false;
119  }
120 
121  AW::Position get_attach_point() const OVERRIDE { return textArea.centroid(); }
122  AW::Rectangle get_bounding_box() const OVERRIDE { return textArea; }
123 
124  int indicate_selected(AW_device *d, int gc) const OVERRIDE;
125  AW_clicked_element *clone() const OVERRIDE { return new AW_clicked_text(*this); }
126 };
127 
129  AW::Rectangle box; // world coordinates of clicked box
130 public:
131  void assign(AW::Rectangle box_, int distance_, const AW_pos& nearest_rel_pos_, const AW_click_cd *click_cd_) {
132  AW_clicked_element::assign(distance_, nearest_rel_pos_, click_cd_);
133  box = box_;
134  }
135 
136  bool operator == (const AW_clicked_element& other) const OVERRIDE {
137  const AW_clicked_box *otherBox = dynamic_cast<const AW_clicked_box*>(&other);
138  return otherBox ? nearlyEqual(box, otherBox->box) : false;
139  }
140 
141  AW::Position get_attach_point() const OVERRIDE { return box.centroid(); }
142  AW::Rectangle get_bounding_box() const OVERRIDE { return box; }
143  int indicate_selected(AW_device *d, int gc) const OVERRIDE;
144  AW_clicked_element *clone() const OVERRIDE { return new AW_clicked_box(*this); }
145 };
146 
147 class AW_clicked_polygon FINAL_TYPE : public AW_clicked_element {
148  int npos; // number of corners
149  AW::Position *pos; // world coordinates of clicked polygon
150 
151 public:
153  npos(0),
154  pos(NULp)
155  {}
156  AW_clicked_polygon(const AW_clicked_polygon& other) :
157  AW_clicked_element(other),
158  npos(other.npos)
159  {
160  if (other.pos) {
161  pos = new AW::Position[npos];
162  for (int i = 0; i<npos; ++i) pos[i] = other.pos[i];
163  }
164  else {
165  pos = NULp;
166  }
167  }
168  DECLARE_ASSIGNMENT_OPERATOR(AW_clicked_polygon);
170  delete [] pos;
171  }
172 
173  void assign(int npos_, const AW::Position *pos_, int distance_, const AW_pos& nearest_rel_pos_, const AW_click_cd *click_cd_) {
174  if (pos) delete [] pos;
175 
176  AW_clicked_element::assign(distance_, nearest_rel_pos_, click_cd_);
177 
178  npos = npos_;
179  pos = new AW::Position[npos];
180  for (int i = 0; i<npos; ++i) pos[i] = pos_[i];
181  }
182 
183  bool operator == (const AW_clicked_element& other) const OVERRIDE {
184  const AW_clicked_polygon *otherPoly = dynamic_cast<const AW_clicked_polygon*>(&other);
185  if (otherPoly) {
186  if (npos == otherPoly->npos) {
187  for (int i = 0; i<npos; ++i) {
188  if (!nearlyEqual(pos[i], otherPoly->pos[i])) {
189  return false;
190  }
191  }
192  return true;
193  }
194  }
195  return false;
196  }
197 
199  AW::Position c = pos[0];
200  for (int i = 1; i<npos; ++i) {
201  c += AW::Vector(pos[i]);
202  }
203  return AW::Position(c.xpos()/npos, c.ypos()/npos);
204  }
206  int indicate_selected(AW_device *d, int gc) const OVERRIDE;
207  AW_clicked_element *clone() const OVERRIDE {
208  return new AW_clicked_polygon(*this);
209  }
210 
211  const AW::Position *get_polygon(int& posCount) const {
213  posCount = npos;
214  return pos;
215  }
216 };
217 
218 
219 // ---------------------
220 // type checks
221 
222 inline bool AW_clicked_element::is_text() const { return dynamic_cast<const AW_clicked_text*>(this); }
223 inline bool AW_clicked_element::is_line() const { return dynamic_cast<const AW_clicked_line*>(this); }
224 inline bool AW_clicked_element::is_box() const { return dynamic_cast<const AW_clicked_box*>(this); }
225 inline bool AW_clicked_element::is_polygon() const { return dynamic_cast<const AW_clicked_polygon*>(this); }
226 
227 #define AWT_CATCH 30 // max-pixel distance to graphical element (to accept a click or command)
228 #define AWT_NO_CATCH -1
229 
230 class AW_device_click FINAL_TYPE : public AW_simple_device {
231  AW::Position mouse;
232 
233  int max_distance_line;
234  int max_distance_text;
235 
236  AW_clicked_line opt_line;
237  AW_clicked_text opt_text;
238  AW_clicked_box opt_box;
239  AW_clicked_polygon opt_polygon;
240 
241  bool line_impl(int gc, const AW::LineVector& Line, AW_bitset filteri) OVERRIDE;
242  bool text_impl(int gc, const SizedCstr& cstr, const AW::Position& pos, AW_pos alignment, AW_bitset filteri) OVERRIDE;
243  bool box_impl(int gc, AW::FillStyle filled, const AW::Rectangle& rect, AW_bitset filteri) OVERRIDE;
244  bool polygon_impl(int gc, AW::FillStyle filled, int npos, const AW::Position *pos, AW_bitset filteri) OVERRIDE;
245 
246  // completely ignore clicks to circles and arcs
247  bool circle_impl(int, AW::FillStyle, const AW::Position&, const AW::Vector&, AW_bitset) OVERRIDE { return false; }
248  bool arc_impl(int, AW::FillStyle, const AW::Position&, const AW::Vector&, int, int, AW_bitset) OVERRIDE { return false; }
249 
250  bool invisible_impl(const AW::Position& pos, AW_bitset filteri) OVERRIDE { return generic_invisible(pos, filteri); }
251  void specific_reset() OVERRIDE {}
252 
253 public:
254  AW_device_click(AW_common *common_);
255 
257 
258  void init_click(const AW::Position& click, int max_distance, AW_bitset filteri);
259 
260  enum ClickPreference { PREFER_NEARER, PREFER_LINE, PREFER_TEXT };
261  const AW_clicked_element *best_click(ClickPreference prefer = PREFER_NEARER);
262 };
263 
264 #else
265 #error aw_device_click.hxx included twice
266 #endif // AW_DEVICE_CLICK_HXX
bool does_exist() const
void assign(int distance_, const AW_pos &nearest_rel_pos_, const AW_click_cd *click_cd_)
long AW_bitset
Definition: aw_base.hxx:44
Position centroid() const
bool nearlyEqual(const double &val1, const double &val2)
Definition: aw_position.hxx:75
AW::Rectangle get_bounding_box() const OVERRIDE
void assign(AW::Rectangle box_, int distance_, const AW_pos &nearest_rel_pos_, const AW_click_cd *click_cd_)
bool operator==(const AW_clicked_element &other) const OVERRIDE
virtual AW_clicked_element * clone() const =0
AW_clicked_polygon(const AW_clicked_polygon &other)
virtual AW::Rectangle get_bounding_box() const =0
AW_clicked_element * clone() const OVERRIDE
AW::Rectangle get_bounding_box() const OVERRIDE
const AW::Position * get_polygon(int &posCount) const
virtual ~AW_clicked_element()
bool operator==(const AW_clicked_element &other) const OVERRIDE
const Position & start() const
double AW_pos
Definition: aw_base.hxx:29
bool operator==(const AW_clicked_element &other) const OVERRIDE
const double & ypos() const
#define DECLARE_ASSIGNMENT_OPERATOR(T)
Definition: arbtools.h:61
#define aw_assert(bed)
Definition: aw_position.hxx:29
AW_CL cd1() const
#define false
Definition: ureadseq.h:13
AW_CL get_cd1() const
Definition: aw_device.hxx:347
AW::Position get_attach_point() const OVERRIDE
AW_CL get_cd2() const
Definition: aw_device.hxx:348
int indicate_selected(AW_device *d, int gc) const OVERRIDE
AW::Position get_attach_point() const OVERRIDE
virtual AW_DEVICE_TYPE type()=0
virtual int indicate_selected(AW_device *d, int gc) const =0
bool is_polygon() const
bool generic_invisible(const AW::Position &pos, AW_bitset filteri)
Definition: AW_device.cxx:294
const AW::LineVector & get_line() const
const Vector & line_vector() const
virtual bool operator==(const AW_clicked_element &other) const =0
AW::Rectangle get_bounding_box() const OVERRIDE
AW_CL cd2() const
xml element
long AW_CL
Definition: cb.h:21
double get_rel_pos() const
#define OVERRIDE
Definition: cxxforward.h:93
AW::Position get_attach_point() const OVERRIDE
void assign(AW::Rectangle textArea_, int distance_, const AW_pos &nearest_rel_pos_, const AW_click_cd *click_cd_)
void assign(int npos_, const AW::Position *pos_, int distance_, const AW_pos &nearest_rel_pos_, const AW_click_cd *click_cd_)
AW::LineVector get_connecting_line(const AW_clicked_element &other) const
AW::Position get_attach_point() const OVERRIDE
AW_clicked_element * clone() const OVERRIDE
AW_clicked_element * clone() const OVERRIDE
virtual AW::Position get_attach_point() const =0
const double & xpos() const
#define NULp
Definition: cxxforward.h:97
const char * cstr
Definition: defines.h:21
AW_DEVICE_TYPE
Definition: aw_device.hxx:48
void assign(const AW::LineVector &line_, int distance_, const AW_pos &nearest_rel_pos_, const AW_click_cd *click_cd_)
int get_distance() const
int indicate_selected(AW_device *d, int gc) const OVERRIDE
int indicate_selected(AW_device *d, int gc) const OVERRIDE