initial commit
[goodguy/history.git] / cinelerra-5.0 / guicast / bctoggle.C
1
2 /*
3  * CINELERRA
4  * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  *
20  */
21
22 #include "bcpixmap.h"
23 #include "bcresources.h"
24 #include "bcsignals.h"
25 #include "bctoggle.h"
26 #include "clip.h"
27 #include "colors.h"
28 #include "cursors.h"
29 #include "fonts.h"
30 #include "vframe.h"
31
32 #include <string.h>
33
34 BC_Toggle::BC_Toggle(int x, int y,
35                 VFrame **data,
36                 int value,
37                 const char *caption,
38                 int bottom_justify,
39                 int font,
40                 int color)
41  : BC_SubWindow(x, y, 0, 0, -1)
42 {
43         this->data = data;
44         for(int i = 0; i < TOGGLE_IMAGES; i++)
45                 images[i] = 0;
46         bg_image = 0;
47         status = value ? BC_Toggle::TOGGLE_CHECKED : BC_Toggle::TOGGLE_UP;
48         this->value = value;
49         strcpy(this->caption, caption);
50         this->bottom_justify = bottom_justify;
51         this->font = font;
52         if(color >= 0)
53                 this->color = color;
54         else
55                 this->color = get_resources()->default_text_color;
56         select_drag = 0;
57         enabled = 1;
58         underline = -1;
59         is_radial = 0;
60 }
61
62
63 BC_Toggle::~BC_Toggle()
64 {
65         for(int i = 0; i < TOGGLE_IMAGES; i++) if(images[i]) delete images[i];
66         delete bg_image;
67 }
68
69
70 int BC_Toggle::initialize()
71 {
72 // Get the image
73         set_images(data);
74         calculate_extents(this,
75                 data,
76                 bottom_justify,
77                 &text_line,
78                 &w,
79                 &h,
80                 &toggle_x,
81                 &toggle_y,
82                 &text_x,
83                 &text_y,
84                 &text_w,
85                 &text_h,
86                 has_caption() ? caption : 0,
87                 font);
88
89 // Create the subwindow
90         BC_SubWindow::initialize();
91         set_cursor(UPRIGHT_ARROW_CURSOR, 0, 0);
92 // Display the bitmap
93         draw_face(1, 0);
94         show_window(0);
95         return 0;
96 }
97
98
99 void BC_Toggle::calculate_extents(BC_WindowBase *gui,
100         VFrame **images,
101         int bottom_justify,
102         int *text_line,
103         int *w,
104         int *h,
105         int *toggle_x,
106         int *toggle_y,
107         int *text_x,
108         int *text_y,
109         int *text_w,
110         int *text_h,
111         const char *caption,
112         int font)
113 {
114         BC_Resources *resources = get_resources();
115         VFrame *frame = images[0];
116         *w = frame->get_w();
117         *h = frame->get_h();
118         *toggle_x = 0;
119         *toggle_y = 0;
120         *text_x = *w + 5;
121         *text_y = 0;
122         *text_w = 0;
123         *text_h = 0;
124
125         if(caption)
126         {
127                 *text_w = gui->get_text_width(font, caption);
128                 *text_h = gui->get_text_height(font);
129
130                 if(resources->toggle_highlight_bg)
131                 {
132                         *text_w += resources->toggle_text_margin * 2;
133                         *text_h = MAX(*text_h, resources->toggle_highlight_bg->get_h());
134                 }
135
136                 if(*text_h > *h)
137                 {
138                         *toggle_y = (*text_h - *h) >> 1;
139                         *h = *text_h;
140                 }
141                 else
142                         *text_y = (*h - *text_h) >> 1;
143
144                 if(bottom_justify)
145                 {
146                         *text_y = *h - *text_h;
147                         *text_line = *h - gui->get_text_descent(font);
148                 }
149                 else
150                         *text_line = *text_y + gui->get_text_ascent(font);
151
152                 *w = *text_x + *text_w;
153         }
154
155
156 }
157
158 void BC_Toggle::set_radial(int value)
159 {
160         is_radial = value;
161 }
162
163 int BC_Toggle::set_images(VFrame **data)
164 {
165         delete bg_image;
166         bg_image = 0;
167         for(int i = 0; i < TOGGLE_IMAGES; i++)
168         {
169                 if(images[i]) delete images[i];
170                 images[i] = new BC_Pixmap(top_level, data[i], PIXMAP_ALPHA);
171         }
172         BC_Resources *resources = get_resources();
173         if(resources->toggle_highlight_bg)
174         {
175                 bg_image = new BC_Pixmap(top_level,
176                         resources->toggle_highlight_bg,
177                         PIXMAP_ALPHA);
178         }
179         return 0;
180 }
181
182 void BC_Toggle::set_underline(int number)
183 {
184         this->underline = number;
185 }
186
187
188 void BC_Toggle::set_select_drag(int value)
189 {
190         this->select_drag = value;
191 }
192
193 int BC_Toggle::draw_face(int flash, int flush)
194 {
195         BC_Resources *resources = get_resources();
196         draw_top_background(parent_window, 0, 0, get_w(), get_h());
197         if(has_caption())
198         {
199                 if(enabled &&
200                         (status == BC_Toggle::TOGGLE_UPHI ||
201                                 status == BC_Toggle::TOGGLE_DOWN ||
202                                 status == BC_Toggle::TOGGLE_CHECKEDHI))
203                 {
204 // Draw highlight image
205                         if(bg_image)
206                         {
207                                 int x = text_x;
208                                 int y = text_line - get_text_ascent(font) / 2 -
209                                                 bg_image->get_h() / 2;
210                                 y = MAX(y, 0);
211                                 int w = text_w;
212                                 draw_3segmenth(x,
213                                         y,
214                                         w,
215                                         bg_image);
216                         }
217                         else
218 // Draw a plain box
219                         {
220                                 set_color(LTGREY);
221                                 draw_box(text_x,
222                                         text_line - get_text_ascent(font),
223                                         get_w() - text_x,
224                                         get_text_height(font));
225                         }
226                 }
227
228                 set_opaque();
229                 if(enabled)
230                         set_color(color);
231                 else
232                         set_color(get_resources()->disabled_text_color);
233                 set_font(font);
234                 draw_text(text_x + resources->toggle_text_margin,
235                         text_line,
236                         caption);
237
238 // Draw underline
239                 if(underline >= 0)
240                 {
241                         int x = text_x + resources->toggle_text_margin;
242                         int y = text_line + 1;
243                         int x1 = get_text_width(current_font, caption, underline) + x;
244                         int x2 = get_text_width(current_font, caption, underline + 1) + x;
245                         draw_line(x1, y, x2, y);
246                         draw_line(x1, y + 1, (x2 + x1) / 2, y + 1);
247                 }
248         }
249
250         draw_pixmap(images[status]);
251         if(flash) this->flash(0);
252         if(flush) this->flush();
253         return 0;
254 }
255
256 void BC_Toggle::enable()
257 {
258         enabled = 1;
259         if(parent_window) draw_face(1, 1);
260 }
261
262 void BC_Toggle::disable()
263 {
264         enabled = 0;
265         if(parent_window) draw_face(1, 1);
266 }
267
268 void BC_Toggle::set_status(int value)
269 {
270         this->status = value;
271 }
272
273
274 int BC_Toggle::repeat_event(int64_t duration)
275 {
276         if(tooltip_text && tooltip_text[0] != 0 && !tooltip_done &&
277                 duration == top_level->get_resources()->tooltip_delay &&
278                 (status == BC_Toggle::TOGGLE_UPHI || status == BC_Toggle::TOGGLE_CHECKEDHI))
279         {
280                 show_tooltip();
281                 tooltip_done = 1;
282                 return 1;
283         }
284         return 0;
285 }
286
287 int BC_Toggle::cursor_enter_event()
288 {
289         if(top_level->event_win == win && enabled)
290         {
291                 tooltip_done = 0;
292                 if(top_level->button_down)
293                         status = BC_Toggle::TOGGLE_DOWN;
294                 else
295                         status = value ? BC_Toggle::TOGGLE_CHECKEDHI : BC_Toggle::TOGGLE_UPHI;
296                 draw_face(1, 1);
297         }
298         return 0;
299 }
300
301 int BC_Toggle::cursor_leave_event()
302 {
303         hide_tooltip();
304         if(!value && status == BC_Toggle::TOGGLE_UPHI)
305         {
306                 status = BC_Toggle::TOGGLE_UP;
307                 draw_face(1, 1);
308         }
309         else
310         if(status == BC_Toggle::TOGGLE_CHECKEDHI)
311         {
312                 status = BC_Toggle::TOGGLE_CHECKED;
313                 draw_face(1, 1);
314         }
315         return 0;
316 }
317
318 int BC_Toggle::button_press_event()
319 {
320         hide_tooltip();
321         if(top_level->event_win == win && get_buttonpress() == 1 && enabled)
322         {
323                 status = BC_Toggle::TOGGLE_DOWN;
324
325 // Change value now for select drag mode.
326 // Radial always goes to 1
327                 if(select_drag)
328                 {
329                         if(!is_radial)
330                                 value = !value;
331                         else
332                                 value = 1;
333                         top_level->toggle_drag = 1;
334                         top_level->toggle_value = value;
335                         handle_event();
336                 }
337
338                 draw_face(1, 1);
339                 return 1;
340         }
341         return 0;
342 }
343
344 int BC_Toggle::button_release_event()
345 {
346         int result = 0;
347         hide_tooltip();
348
349         if(top_level->event_win == win)
350         {
351 // Keep value regardless of status if drag mode.
352                 if(select_drag)
353                 {
354                         if(value)
355                                 status = BC_Toggle::TOGGLE_CHECKEDHI;
356                         else
357                                 status = BC_Toggle::TOGGLE_UPHI;
358                         top_level->toggle_drag = 0;
359                 }
360                 else
361 // Change value only if button down for default mode.
362                 if(status == BC_Toggle::TOGGLE_DOWN)
363                 {
364 // Radial always goes to 1.
365                         if(!value || is_radial)
366                         {
367                                 status = BC_Toggle::TOGGLE_CHECKEDHI;
368                                 value = 1;
369                         }
370                         else
371                         {
372                                 status = BC_Toggle::TOGGLE_UPHI;
373                                 value = 0;
374                         }
375                         result = handle_event();
376                 }
377                 draw_face(1, 1);
378                 return result;
379         }
380         return 0;
381 }
382
383 int BC_Toggle::cursor_motion_event()
384 {
385         if(top_level->button_down &&
386                 top_level->event_win == win &&
387                 !cursor_inside())
388         {
389                 if(status == BC_Toggle::TOGGLE_DOWN)
390                 {
391                         if(value)
392                                 status = BC_Toggle::TOGGLE_CHECKED;
393                         else
394                                 status = BC_Toggle::TOGGLE_UP;
395                         draw_face(1, 1);
396                 }
397                 else
398                 if(status == BC_Toggle::TOGGLE_UPHI)
399                 {
400                         status = BC_Toggle::TOGGLE_CHECKEDHI;
401                         draw_face(1, 1);
402                 }
403         }
404         return 0;
405 }
406
407 int BC_Toggle::get_value()
408 {
409         return value;
410 }
411
412 int BC_Toggle::set_value(int value, int draw)
413 {
414         if(value != this->value)
415         {
416                 this->value = value;
417                 if(value)
418                 {
419                         switch(status)
420                         {
421                                 case BC_Toggle::TOGGLE_UP:
422                                         status = BC_Toggle::TOGGLE_CHECKED;
423                                         break;
424                                 case BC_Toggle::TOGGLE_UPHI:
425                                         status = BC_Toggle::TOGGLE_CHECKEDHI;
426                                         break;
427                         }
428                 }
429                 else
430                 switch(status)
431                 {
432                         case BC_Toggle::TOGGLE_CHECKED:
433                                 status = BC_Toggle::TOGGLE_UP;
434                                 break;
435                         case BC_Toggle::TOGGLE_CHECKEDHI:
436                                 status = BC_Toggle::TOGGLE_UPHI;
437                                 break;
438                 }
439                 if(draw) draw_face(1, 1);
440         }
441         return 0;
442 }
443
444 int BC_Toggle::update(int value, int draw)
445 {
446         return set_value(value, draw);
447 }
448
449 void BC_Toggle::reposition_window(int x, int y)
450 {
451         BC_WindowBase::reposition_window(x, y);
452         draw_face(1, 0);
453 }
454
455
456 int BC_Toggle::has_caption()
457 {
458         return (caption != 0 && caption[0] != 0);
459 }
460
461 BC_Radial::BC_Radial(int x,
462         int y,
463         int value,
464         const char *caption,
465         int font,
466         int color)
467  : BC_Toggle(x,
468         y,
469         BC_WindowBase::get_resources()->radial_images,
470         value,
471         caption,
472         0,
473         font,
474         color)
475 {
476         is_radial = 1;
477 }
478
479 BC_CheckBox::BC_CheckBox(int x,
480         int y,
481         int value,
482         const char *caption,
483         int font,
484         int color)
485  : BC_Toggle(x,
486         y,
487         BC_WindowBase::get_resources()->checkbox_images,
488         value,
489         caption,
490         0,
491         font,
492         color)
493 {
494         this->value = 0;
495 }
496
497 BC_CheckBox::BC_CheckBox(int x,
498         int y,
499         int *value,
500         const char *caption,
501         int font,
502         int color)
503  : BC_Toggle(x,
504         y,
505         BC_WindowBase::get_resources()->checkbox_images,
506         *value,
507         caption,
508         1,
509         font,
510         color)
511 {
512         this->value = value;
513 }
514
515 void BC_CheckBox::calculate_extents(BC_WindowBase *gui, int *w, int *h,
516         const char *caption, int font)
517 {
518         int text_line, toggle_x, toggle_y;
519         int text_x, text_y, text_w, text_h;
520
521         BC_Toggle::calculate_extents(gui,
522                 BC_WindowBase::get_resources()->checkbox_images,
523                 1, &text_line, w, h, &toggle_x, &toggle_y,
524                 &text_x, &text_y, &text_w, &text_h, caption, font);
525 }
526
527 int BC_CheckBox::handle_event()
528 {
529         if( value )
530                 *value = get_value();
531         return 1;
532 }
533
534
535
536 BC_Label::BC_Label(int x,
537         int y,
538         int value,
539         int font,
540         int color)
541  : BC_Toggle(x,
542         y,
543         BC_WindowBase::get_resources()->label_images,
544         value,
545         "",
546         0,
547         font,
548         color)
549 {
550 }