r1022: Restructure overlay and label code for efficiency; change the graphic display...
[cinelerra_cv.git] / guicast / bctoggle.C
blobd35392e8f929e4e96d4a0a36b48705372380d1c8
1 #include "bcpixmap.h"
2 #include "bcresources.h"
3 #include "bcsignals.h"
4 #include "bctoggle.h"
5 #include "clip.h"
6 #include "colors.h"
7 #include "cursors.h"
8 #include "fonts.h"
9 #include "vframe.h"
11 #include <string.h>
13 BC_Toggle::BC_Toggle(int x, int y, 
14                 VFrame **data, 
15                 int value, 
16                 char *caption,
17                 int bottom_justify, 
18                 int font,
19                 int color)
20  : BC_SubWindow(x, y, 0, 0, -1)
22         this->data = data;
23         for(int i = 0; i < 5; i++)
24                 images[i] = 0;
25         bg_image = 0;
26         status = value ? BC_Toggle::TOGGLE_CHECKED : BC_Toggle::TOGGLE_UP;
27         this->value = value;
28         strcpy(this->caption, caption);
29         this->bottom_justify = bottom_justify;
30         this->font = font;
31         if(color >= 0)
32                 this->color = color;
33         else
34                 this->color = get_resources()->default_text_color;
35         select_drag = 0;
36         enabled = 1;
37         underline = -1;
38         is_radial = 0;
42 BC_Toggle::~BC_Toggle()
44         for(int i = 0; i < 5; i++) if(images[i]) delete images[i];
45         delete bg_image;
49 int BC_Toggle::initialize()
51 // Get the image
52         set_images(data);
53         calculate_extents(this,
54                 data,
55                 bottom_justify,
56                 &text_line,
57                 &w,
58                 &h,
59                 &toggle_x,
60                 &toggle_y,
61                 &text_x, 
62                 &text_y,
63                 &text_w,
64                 &text_h, 
65                 has_caption() ? caption : 0);
67 // Create the subwindow
68         BC_SubWindow::initialize();
69         set_cursor(UPRIGHT_ARROW_CURSOR);
70 // Display the bitmap
71         draw_face();
72         return 0;
76 void BC_Toggle::calculate_extents(BC_WindowBase *gui, 
77         VFrame **images,
78         int bottom_justify,
79         int *text_line,
80         int *w,
81         int *h,
82         int *toggle_x,
83         int *toggle_y,
84         int *text_x,
85         int *text_y, 
86         int *text_w,
87         int *text_h, 
88         char *caption)
90         BC_Resources *resources = get_resources();
91         VFrame *frame = images[0];
92         *w = frame->get_w();
93         *h = frame->get_h();
94         *toggle_x = 0;
95         *toggle_y = 0;
96         *text_x = *w + 5;
97         *text_y = 0;
98         *text_w = 0;
99         *text_h = 0;
101         if(caption)
102         {
103                 *text_w = gui->get_text_width(MEDIUMFONT, caption);
104                 *text_h = gui->get_text_height(MEDIUMFONT);
106                 if(resources->toggle_highlight_bg)
107                 {
108                         *text_w += resources->toggle_text_margin * 2;
109                         *text_h = MAX(*text_h, resources->toggle_highlight_bg->get_h());
110                 }
112                 if(*text_h > *h)
113                 {
114                         *toggle_y = (*text_h - *h) >> 1;
115                         *h = *text_h;
116                 }
117                 else
118                         *text_y = (*h - *text_h) >> 1;
120                 if(bottom_justify)
121                 {
122                         *text_y = *h - *text_h;
123                         *text_line = *h - gui->get_text_descent(MEDIUMFONT);
124                 }
125                 else
126                         *text_line = *text_y + gui->get_text_ascent(MEDIUMFONT);
128                 *w = *text_x + *text_w;
129         }
135 int BC_Toggle::set_images(VFrame **data)
137         delete bg_image;
138         bg_image = 0;
139         for(int i = 0; i < 5; i++)
140         {
141                 if(images[i]) delete images[i];
142                 images[i] = new BC_Pixmap(top_level, data[i], PIXMAP_ALPHA);
143         }
144         BC_Resources *resources = get_resources();
145         if(resources->toggle_highlight_bg)
146         {
147                 bg_image = new BC_Pixmap(top_level, 
148                         resources->toggle_highlight_bg, 
149                         PIXMAP_ALPHA);
150         }
151         return 0;
154 void BC_Toggle::set_underline(int number)
156         this->underline = number;
160 void BC_Toggle::set_select_drag(int value)
162         this->select_drag = value;
165 int BC_Toggle::draw_face()
167         BC_Resources *resources = get_resources();
168         draw_top_background(parent_window, 0, 0, get_w(), get_h());
169         if(has_caption())
170         {
171                 if(enabled &&
172                         (status == BC_Toggle::TOGGLE_UPHI || 
173                                 status == BC_Toggle::TOGGLE_DOWN || 
174                                 status == BC_Toggle::TOGGLE_CHECKEDHI))
175                 {
176 // Draw highlight image
177                         if(bg_image)
178                         {
179                                 int x = text_x;
180                                 int y = text_line - get_text_ascent(MEDIUMFONT) / 2 - 
181                                                 bg_image->get_h() / 2;
182                                 int w = text_w;
183                                 draw_3segmenth(x, 
184                                         y, 
185                                         w,
186                                         bg_image);
187                         }
188                         else
189 // Draw a plain box
190                         {
191                                 set_color(LTGREY);
192                                 draw_box(text_x, 
193                                         text_line - get_text_ascent(MEDIUMFONT), 
194                                         get_w() - text_x, 
195                                         get_text_height(MEDIUMFONT));
196                         }
197                 }
199                 set_opaque();
200                 if(enabled)
201                         set_color(color);
202                 else
203                         set_color(MEGREY);
204                 set_font(font);
205                 draw_text(text_x + resources->toggle_text_margin, 
206                         text_line, 
207                         caption);
209 // Draw underline
210                 if(underline >= 0)
211                 {
212                         int x = text_x + resources->toggle_text_margin;
213                         int y = text_line + 1;
214                         int x1 = get_text_width(current_font, caption, underline) + x;
215                         int x2 = get_text_width(current_font, caption, underline + 1) + x;
216                         draw_line(x1, y, x2, y);
217                         draw_line(x1, y + 1, (x2 + x1) / 2, y + 1);
218                 }
219         }
221         draw_pixmap(images[status]);
222         flash();
223         return 0;
226 void BC_Toggle::enable()
228         enabled = 1;
229         if(parent_window) draw_face();
232 void BC_Toggle::disable()
234         enabled = 0;
235         if(parent_window) draw_face();
238 void BC_Toggle::set_status(int value)
240         this->status = value;
244 int BC_Toggle::repeat_event(int64_t duration)
246         if(duration == top_level->get_resources()->tooltip_delay &&
247                 tooltip_text[0] != 0 &&
248                 (status == BC_Toggle::TOGGLE_UPHI || status == BC_Toggle::TOGGLE_CHECKEDHI) &&
249                 !tooltip_done)
250         {
251                 show_tooltip();
252                 tooltip_done = 1;
253                 return 1;
254         }
255         return 0;
258 int BC_Toggle::cursor_enter_event()
260         if(top_level->event_win == win && enabled)
261         {
262                 tooltip_done = 0;
263                 if(top_level->button_down)
264                         status = BC_Toggle::TOGGLE_DOWN;
265                 else
266                         status = value ? BC_Toggle::TOGGLE_CHECKEDHI : BC_Toggle::TOGGLE_UPHI;
267                 draw_face();
268         }
269         return 0;
272 int BC_Toggle::cursor_leave_event()
274         hide_tooltip();
275         if(!value && status == BC_Toggle::TOGGLE_UPHI)
276         {
277                 status = BC_Toggle::TOGGLE_UP;
278                 draw_face();
279         }
280         else
281         if(status == BC_Toggle::TOGGLE_CHECKEDHI)
282         {
283                 status = BC_Toggle::TOGGLE_CHECKED;
284                 draw_face();
285         }
286         return 0;
289 int BC_Toggle::button_press_event()
291         hide_tooltip();
292         if(top_level->event_win == win && get_buttonpress() == 1 && enabled)
293         {
294                 status = BC_Toggle::TOGGLE_DOWN;
296 // Change value now for select drag mode.
297 // Radial always goes to 1
298                 if(select_drag)
299                 {
300                         if(!is_radial)
301                                 value = !value;
302                         else
303                                 value = 1;
304                         top_level->toggle_drag = 1;
305                         top_level->toggle_value = value;
306                         handle_event();
307                 }
309                 draw_face();
310                 return 1;
311         }
312         return 0;
315 int BC_Toggle::button_release_event()
317         int result = 0;
318         hide_tooltip();
320         if(top_level->event_win == win)
321         {
322 // Keep value regardless of status if drag mode.
323                 if(select_drag)
324                 {
325                         if(value)
326                                 status = BC_Toggle::TOGGLE_CHECKEDHI;
327                         else
328                                 status = BC_Toggle::TOGGLE_UPHI;
329                         top_level->toggle_drag = 0;
330                 }
331                 else
332 // Change value only if button down for default mode.
333                 if(status == BC_Toggle::TOGGLE_DOWN)
334                 {
335 // Radial always goes to 1.
336                         if(!value || is_radial)
337                         {
338                                 status = BC_Toggle::TOGGLE_CHECKEDHI;
339                                 value = 1;
340                         }
341                         else
342                         {
343                                 status = BC_Toggle::TOGGLE_UPHI;
344                                 value = 0;
345                         }
346                         result = handle_event();
347                 }
348                 draw_face();
349                 return result;
350         }
351         return 0;
354 int BC_Toggle::cursor_motion_event()
356         if(top_level->button_down && 
357                 top_level->event_win == win && 
358                 !cursor_inside())
359         {
360                 if(status == BC_Toggle::TOGGLE_DOWN)
361                 {
362                         if(value)
363                                 status = BC_Toggle::TOGGLE_CHECKED;
364                         else
365                                 status = BC_Toggle::TOGGLE_UP;
366                         draw_face();
367                 }
368                 else
369                 if(status == BC_Toggle::TOGGLE_UPHI)
370                 {
371                         status = BC_Toggle::TOGGLE_CHECKEDHI;
372                         draw_face();
373                 }
374         }
375         return 0;
378 int BC_Toggle::get_value()
380         return value;
383 int BC_Toggle::set_value(int value, int draw)
385         if(value != this->value)
386         {
387                 this->value = value;
388                 if(value) 
389                 {
390                         switch(status)
391                         {
392                                 case BC_Toggle::TOGGLE_UP:
393                                         status = BC_Toggle::TOGGLE_CHECKED;
394                                         break;
395                                 case BC_Toggle::TOGGLE_UPHI:
396                                         status = BC_Toggle::TOGGLE_CHECKEDHI;
397                                         break;
398                         }
399                 }
400                 else
401                 switch(status)
402                 {
403                         case BC_Toggle::TOGGLE_CHECKED:
404                                 status = BC_Toggle::TOGGLE_UP;
405                                 break;
406                         case BC_Toggle::TOGGLE_CHECKEDHI:
407                                 status = BC_Toggle::TOGGLE_UPHI;
408                                 break;
409                 }
410                 if(draw) draw_face();
411         }
412         return 0;
415 int BC_Toggle::update(int value, int draw)
417         return set_value(value, draw);
420 void BC_Toggle::reposition_window(int x, int y)
422         BC_WindowBase::reposition_window(x, y);
423         draw_face();
427 int BC_Toggle::has_caption()
429         return (caption != 0 && caption[0] != 0);
432 BC_Radial::BC_Radial(int x, 
433         int y, 
434         int value, 
435         char *caption, 
436         int font,
437         int color)
438  : BC_Toggle(x, 
439         y, 
440         BC_WindowBase::get_resources()->radial_images, 
441         value, 
442         caption, 
443         0, 
444         font,
445         color)
447         is_radial = 1;
450 BC_CheckBox::BC_CheckBox(int x, 
451         int y, 
452         int value, 
453         char *caption, 
454         int font,
455         int color)
456  : BC_Toggle(x, 
457         y, 
458         BC_WindowBase::get_resources()->checkbox_images, 
459         value, 
460         caption, 
461         0, 
462         font,
463         color)
465         this->value = 0;
468 BC_CheckBox::BC_CheckBox(int x, 
469         int y, 
470         int *value, 
471         char *caption, 
472         int font,
473         int color)
474  : BC_Toggle(x, 
475         y, 
476         BC_WindowBase::get_resources()->checkbox_images, 
477         *value, 
478         caption, 
479         1, 
480         font,
481         color)
483         this->value = value;
486 int BC_CheckBox::handle_event()
488         *value = get_value();
489         return 1;
494 BC_Label::BC_Label(int x, 
495         int y, 
496         int value, 
497         int font,
498         int color)
499  : BC_Toggle(x, 
500         y, 
501         BC_WindowBase::get_resources()->label_images, 
502         value, 
503         "", 
504         0, 
505         font,
506         color)