1 //----------------------------------------------------------------------------
2 // Anti-Grain Geometry (AGG) - Version 2.5
3 // A high quality rendering engine for C++
4 // Copyright (C) 2002-2006 Maxim Shemanarev
5 // Contact: mcseem@antigrain.com
6 //          mcseemagg@yahoo.com
7 //          http://antigrain.com
8 //
9 // AGG is free software; you can redistribute it and/or
10 // modify it under the terms of the GNU General Public License
11 // as published by the Free Software Foundation; either version 2
12 // of the License, or (at your option) any later version.
13 //
14 // AGG is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 // GNU General Public License for more details.
18 //
19 // You should have received a copy of the GNU General Public License
20 // along with AGG; if not, write to the Free Software
21 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
22 // MA 02110-1301, USA.
23 //----------------------------------------------------------------------------
24 
25 #include <string.h>
26 #include "ctrl/agg_rbox_ctrl.h"
27 
28 namespace agg
29 {
30 
31     //------------------------------------------------------------------------
rbox_ctrl_impl(double x1,double y1,double x2,double y2,bool flip_y)32     rbox_ctrl_impl::rbox_ctrl_impl(double x1, double y1,
33                                    double x2, double y2, bool flip_y) :
34         ctrl(x1, y1, x2, y2, flip_y),
35         m_border_width(1.0),
36         m_border_extra(0.0),
37         m_text_thickness(1.5),
38         m_text_height(9.0),
39         m_text_width(0.0),
40         m_num_items(0),
41         m_cur_item(-1),
42         m_ellipse_poly(m_ellipse),
43         m_text_poly(m_text),
44         m_idx(0),
45         m_vertex(0)
46     {
47         calc_rbox();
48     }
49 
50 
51     //------------------------------------------------------------------------
calc_rbox()52     void rbox_ctrl_impl::calc_rbox()
53     {
54         m_xs1 = m_x1 + m_border_width;
55         m_ys1 = m_y1 + m_border_width;
56         m_xs2 = m_x2 - m_border_width;
57         m_ys2 = m_y2 - m_border_width;
58     }
59 
60 
61     //------------------------------------------------------------------------
add_item(const char * text)62     void rbox_ctrl_impl::add_item(const char* text)
63     {
64         if(m_num_items < 32)
65         {
66             m_items[m_num_items].resize(strlen(text) + 1);
67             strcpy(&m_items[m_num_items][0], text);
68             m_num_items++;
69         }
70     }
71 
72 
73     //------------------------------------------------------------------------
border_width(double t,double extra)74     void rbox_ctrl_impl::border_width(double t, double extra)
75     {
76         m_border_width = t;
77         m_border_extra = extra;
78         calc_rbox();
79     }
80 
81 
82     //------------------------------------------------------------------------
text_size(double h,double w)83     void rbox_ctrl_impl::text_size(double h, double w)
84     {
85         m_text_width = w;
86         m_text_height = h;
87     }
88 
89 
90 
91     //------------------------------------------------------------------------
rewind(unsigned idx)92     void rbox_ctrl_impl::rewind(unsigned idx)
93     {
94         m_idx = idx;
95         m_dy = m_text_height * 2.0;
96         m_draw_item = 0;
97 
98         switch(idx)
99         {
100         default:
101 
102         case 0:                 // Background
103             m_vertex = 0;
104             m_vx[0] = m_x1 - m_border_extra;
105             m_vy[0] = m_y1 - m_border_extra;
106             m_vx[1] = m_x2 + m_border_extra;
107             m_vy[1] = m_y1 - m_border_extra;
108             m_vx[2] = m_x2 + m_border_extra;
109             m_vy[2] = m_y2 + m_border_extra;
110             m_vx[3] = m_x1 - m_border_extra;
111             m_vy[3] = m_y2 + m_border_extra;
112             break;
113 
114         case 1:                 // Border
115             m_vertex = 0;
116             m_vx[0] = m_x1;
117             m_vy[0] = m_y1;
118             m_vx[1] = m_x2;
119             m_vy[1] = m_y1;
120             m_vx[2] = m_x2;
121             m_vy[2] = m_y2;
122             m_vx[3] = m_x1;
123             m_vy[3] = m_y2;
124             m_vx[4] = m_x1 + m_border_width;
125             m_vy[4] = m_y1 + m_border_width;
126             m_vx[5] = m_x1 + m_border_width;
127             m_vy[5] = m_y2 - m_border_width;
128             m_vx[6] = m_x2 - m_border_width;
129             m_vy[6] = m_y2 - m_border_width;
130             m_vx[7] = m_x2 - m_border_width;
131             m_vy[7] = m_y1 + m_border_width;
132             break;
133 
134         case 2:                 // Text
135             m_text.text(&m_items[0][0]);
136             m_text.start_point(m_xs1 + m_dy * 1.5, m_ys1 + m_dy / 2.0);
137             m_text.size(m_text_height, m_text_width);
138             m_text_poly.width(m_text_thickness);
139             m_text_poly.line_join(round_join);
140             m_text_poly.line_cap(round_cap);
141             m_text_poly.rewind(0);
142             break;
143 
144         case 3:                 // Inactive items
145             m_ellipse.init(m_xs1 + m_dy / 1.3,
146                            m_ys1 + m_dy / 1.3,
147                            m_text_height / 1.5,
148                            m_text_height / 1.5, 32);
149             m_ellipse_poly.width(m_text_thickness);
150             m_ellipse_poly.rewind(0);
151             break;
152 
153 
154         case 4:                 // Active Item
155             if(m_cur_item >= 0)
156             {
157                 m_ellipse.init(m_xs1 + m_dy / 1.3,
158                                m_ys1 + m_dy * m_cur_item + m_dy / 1.3,
159                                m_text_height / 2.0,
160                                m_text_height / 2.0, 32);
161                 m_ellipse.rewind(0);
162             }
163             break;
164 
165         }
166     }
167 
168 
169     //------------------------------------------------------------------------
vertex(double * x,double * y)170     unsigned rbox_ctrl_impl::vertex(double* x, double* y)
171     {
172         unsigned cmd = path_cmd_line_to;
173         switch(m_idx)
174         {
175         case 0:
176             if(m_vertex == 0) cmd = path_cmd_move_to;
177             if(m_vertex >= 4) cmd = path_cmd_stop;
178             *x = m_vx[m_vertex];
179             *y = m_vy[m_vertex];
180             m_vertex++;
181             break;
182 
183         case 1:
184             if(m_vertex == 0 || m_vertex == 4) cmd = path_cmd_move_to;
185             if(m_vertex >= 8) cmd = path_cmd_stop;
186             *x = m_vx[m_vertex];
187             *y = m_vy[m_vertex];
188             m_vertex++;
189             break;
190 
191         case 2:
192             cmd = m_text_poly.vertex(x, y);
193             if(is_stop(cmd))
194             {
195                 m_draw_item++;
196                 if(m_draw_item >= m_num_items)
197                 {
198                     break;
199                 }
200                 else
201                 {
202                     m_text.text(&m_items[m_draw_item][0]);
203                     m_text.start_point(m_xs1 + m_dy * 1.5,
204                                        m_ys1 + m_dy * (m_draw_item + 1) - m_dy / 2.0);
205 
206                     m_text_poly.rewind(0);
207                     cmd = m_text_poly.vertex(x, y);
208                 }
209             }
210             break;
211 
212         case 3:
213             cmd = m_ellipse_poly.vertex(x, y);
214             if(is_stop(cmd))
215             {
216                 m_draw_item++;
217                 if(m_draw_item >= m_num_items)
218                 {
219                     break;
220                 }
221                 else
222                 {
223                     m_ellipse.init(m_xs1 + m_dy / 1.3,
224                                    m_ys1 + m_dy * m_draw_item + m_dy / 1.3,
225                                    m_text_height / 1.5,
226                                    m_text_height / 1.5, 32);
227                     m_ellipse_poly.rewind(0);
228                     cmd = m_ellipse_poly.vertex(x, y);
229                 }
230             }
231             break;
232 
233 
234         case 4:
235             if(m_cur_item >= 0)
236             {
237                 cmd = m_ellipse.vertex(x, y);
238             }
239             else
240             {
241                 cmd = path_cmd_stop;
242             }
243             break;
244 
245         default:
246             cmd = path_cmd_stop;
247             break;
248         }
249 
250         if(!is_stop(cmd))
251         {
252             transform_xy(x, y);
253         }
254 
255         return cmd;
256     }
257 
258 
259     //------------------------------------------------------------------------
in_rect(double x,double y) const260     bool rbox_ctrl_impl::in_rect(double x, double y) const
261     {
262         inverse_transform_xy(&x, &y);
263         return x >= m_x1 && x <= m_x2 && y >= m_y1 && y <= m_y2;
264     }
265 
266 
267 
268     //------------------------------------------------------------------------
on_mouse_button_down(double x,double y)269     bool rbox_ctrl_impl::on_mouse_button_down(double x, double y)
270     {
271         inverse_transform_xy(&x, &y);
272         unsigned i;
273         for(i = 0; i < m_num_items; i++)
274         {
275             double xp = m_xs1 + m_dy / 1.3;
276             double yp = m_ys1 + m_dy * i + m_dy / 1.3;
277             if(calc_distance(x, y, xp, yp) <= m_text_height / 1.5)
278             {
279                 m_cur_item = int(i);
280                 return true;
281             }
282         }
283         return false;
284     }
285 
286 
287     //------------------------------------------------------------------------
on_mouse_move(double,double,bool)288     bool rbox_ctrl_impl::on_mouse_move(double, double, bool)
289     {
290         return false;
291     }
292 
293     //------------------------------------------------------------------------
on_mouse_button_up(double,double)294     bool rbox_ctrl_impl::on_mouse_button_up(double, double)
295     {
296         return false;
297     }
298 
299     //------------------------------------------------------------------------
on_arrow_keys(bool left,bool right,bool down,bool up)300     bool rbox_ctrl_impl::on_arrow_keys(bool left, bool right, bool down, bool up)
301     {
302         if(m_cur_item >= 0)
303         {
304             if(up || right)
305             {
306                 m_cur_item++;
307                 if(m_cur_item >= int(m_num_items))
308                 {
309                     m_cur_item = 0;
310                 }
311                 return true;
312             }
313 
314             if(down || left)
315             {
316                 m_cur_item--;
317                 if(m_cur_item < 0)
318                 {
319                     m_cur_item = m_num_items - 1;
320                 }
321                 return true;
322             }
323         }
324         return false;
325     }
326 
327 
328 }
329 
330 
331