interp bilinear fix
[goodguy/history.git] / cinelerra-5.1 / 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 &&
277                 duration == top_level->get_resources()->tooltip_delay &&
278                 (status == BC_Toggle::TOGGLE_UPHI || status == BC_Toggle::TOGGLE_CHECKEDHI))
279         {
280                 show_tooltip();
281                 return 1;
282         }
283         return 0;
284 }
285
286 int BC_Toggle::cursor_enter_event()
287 {
288         if(top_level->event_win == win && enabled)
289         {
290                 if(top_level->button_down)
291                         status = BC_Toggle::TOGGLE_DOWN;
292                 else
293                         status = value ? BC_Toggle::TOGGLE_CHECKEDHI : BC_Toggle::TOGGLE_UPHI;
294                 draw_face(1, 1);
295         }
296         return 0;
297 }
298
299 int BC_Toggle::cursor_leave_event()
300 {
301         hide_tooltip();
302         if(!value && status == BC_Toggle::TOGGLE_UPHI)
303         {
304                 status = BC_Toggle::TOGGLE_UP;
305                 draw_face(1, 1);
306         }
307         else
308         if(status == BC_Toggle::TOGGLE_CHECKEDHI)
309         {
310                 status = BC_Toggle::TOGGLE_CHECKED;
311                 draw_face(1, 1);
312         }
313         return 0;
314 }
315
316 int BC_Toggle::button_press_event()
317 {
318         hide_tooltip();
319         if(top_level->event_win == win && get_buttonpress() == 1 && enabled)
320         {
321                 status = BC_Toggle::TOGGLE_DOWN;
322
323 // Change value now for select drag mode.
324 // Radial always goes to 1
325                 if(select_drag)
326                 {
327                         if(!is_radial)
328                                 value = !value;
329                         else
330                                 value = 1;
331                         top_level->toggle_drag = 1;
332                         top_level->toggle_value = value;
333                         handle_event();
334                 }
335
336                 draw_face(1, 1);
337                 return 1;
338         }
339         return 0;
340 }
341
342 int BC_Toggle::button_release_event()
343 {
344         int result = 0;
345         hide_tooltip();
346
347         if(top_level->event_win == win)
348         {
349 // Keep value regardless of status if drag mode.
350                 if(select_drag)
351                 {
352                         if(value)
353                                 status = BC_Toggle::TOGGLE_CHECKEDHI;
354                         else
355                                 status = BC_Toggle::TOGGLE_UPHI;
356                         top_level->toggle_drag = 0;
357                 }
358                 else
359 // Change value only if button down for default mode.
360                 if(status == BC_Toggle::TOGGLE_DOWN)
361                 {
362 // Radial always goes to 1.
363                         if(!value || is_radial)
364                         {
365                                 status = BC_Toggle::TOGGLE_CHECKEDHI;
366                                 value = 1;
367                         }
368                         else
369                         {
370                                 status = BC_Toggle::TOGGLE_UPHI;
371                                 value = 0;
372                         }
373                         result = handle_event();
374                 }
375                 draw_face(1, 1);
376                 return result;
377         }
378         return 0;
379 }
380
381 int BC_Toggle::cursor_motion_event()
382 {
383         if(top_level->button_down &&
384                 top_level->event_win == win &&
385                 !cursor_inside())
386         {
387                 if(status == BC_Toggle::TOGGLE_DOWN)
388                 {
389                         if(value)
390                                 status = BC_Toggle::TOGGLE_CHECKED;
391                         else
392                                 status = BC_Toggle::TOGGLE_UP;
393                         draw_face(1, 1);
394                 }
395                 else
396                 if(status == BC_Toggle::TOGGLE_UPHI)
397                 {
398                         status = BC_Toggle::TOGGLE_CHECKEDHI;
399                         draw_face(1, 1);
400                 }
401         }
402         return 0;
403 }
404
405 int BC_Toggle::get_value()
406 {
407         return value;
408 }
409
410 int BC_Toggle::set_value(int value, int draw)
411 {
412         if(value != this->value)
413         {
414                 this->value = value;
415                 if(value)
416                 {
417                         switch(status)
418                         {
419                                 case BC_Toggle::TOGGLE_UP:
420                                         status = BC_Toggle::TOGGLE_CHECKED;
421                                         break;
422                                 case BC_Toggle::TOGGLE_UPHI:
423                                         status = BC_Toggle::TOGGLE_CHECKEDHI;
424                                         break;
425                         }
426                 }
427                 else
428                 switch(status)
429                 {
430                         case BC_Toggle::TOGGLE_CHECKED:
431                                 status = BC_Toggle::TOGGLE_UP;
432                                 break;
433                         case BC_Toggle::TOGGLE_CHECKEDHI:
434                                 status = BC_Toggle::TOGGLE_UPHI;
435                                 break;
436                 }
437                 if(draw) draw_face(1, 1);
438         }
439         return 0;
440 }
441
442 int BC_Toggle::update(int value, int draw)
443 {
444         return set_value(value, draw);
445 }
446
447 void BC_Toggle::reposition_window(int x, int y)
448 {
449         BC_WindowBase::reposition_window(x, y);
450         draw_face(1, 0);
451 }
452
453
454 int BC_Toggle::has_caption()
455 {
456         return (caption != 0 && caption[0] != 0);
457 }
458
459 BC_Radial::BC_Radial(int x,
460         int y,
461         int value,
462         const char *caption,
463         int font,
464         int color)
465  : BC_Toggle(x,
466         y,
467         BC_WindowBase::get_resources()->radial_images,
468         value,
469         caption,
470         0,
471         font,
472         color)
473 {
474         is_radial = 1;
475 }
476
477 BC_CheckBox::BC_CheckBox(int x,
478         int y,
479         int value,
480         const char *caption,
481         int font,
482         int color)
483  : BC_Toggle(x,
484         y,
485         BC_WindowBase::get_resources()->checkbox_images,
486         value,
487         caption,
488         0,
489         font,
490         color)
491 {
492         this->value = 0;
493 }
494
495 BC_CheckBox::BC_CheckBox(int x,
496         int y,
497         int *value,
498         const char *caption,
499         int font,
500         int color)
501  : BC_Toggle(x,
502         y,
503         BC_WindowBase::get_resources()->checkbox_images,
504         *value,
505         caption,
506         1,
507         font,
508         color)
509 {
510         this->value = value;
511 }
512
513 void BC_CheckBox::calculate_extents(BC_WindowBase *gui, int *w, int *h,
514         const char *caption, int font)
515 {
516         int text_line, toggle_x, toggle_y;
517         int text_x, text_y, text_w, text_h;
518
519         BC_Toggle::calculate_extents(gui,
520                 BC_WindowBase::get_resources()->checkbox_images,
521                 1, &text_line, w, h, &toggle_x, &toggle_y,
522                 &text_x, &text_y, &text_w, &text_h, caption, font);
523 }
524
525 int BC_CheckBox::handle_event()
526 {
527         if( value )
528                 *value = get_value();
529         return 1;
530 }
531
532
533
534 BC_Label::BC_Label(int x,
535         int y,
536         int value,
537         int font,
538         int color)
539  : BC_Toggle(x,
540         y,
541         BC_WindowBase::get_resources()->label_images,
542         value,
543         "",
544         0,
545         font,
546         color)
547 {
548 }