add view thumbnail size pref, rework vicon view popup, add view popup zoom scale
[goodguy/cinelerra.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 "bccolors.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, VFrame **data, int value,
35                 const char *caption, int bottom_justify, int font, int color)
36  : BC_SubWindow(x, y, 0, 0, -1)
37 {
38         this->data = data;
39         for( int i=0; i<TOGGLE_IMAGES; ++i ) images[i] = 0;
40         bg_image = 0;
41         status = value ? BC_Toggle::TOGGLE_CHECKED : BC_Toggle::TOGGLE_UP;
42         this->value = value;
43         strcpy(this->caption, caption);
44         this->bottom_justify = bottom_justify;
45         this->font = font;
46         this->color = color >= 0 ? color : get_resources()->default_text_color;
47         select_drag = 0;
48         enabled = 1;
49         underline = -1;
50         is_radial = 0;
51 }
52
53
54 BC_Toggle::~BC_Toggle()
55 {
56         for( int i=0; i<TOGGLE_IMAGES; ++i ) delete images[i];
57         delete bg_image;
58 }
59
60
61 int BC_Toggle::initialize()
62 {
63 // Get the image
64         set_images(data);
65         calculate_extents(this, data, bottom_justify,
66                 &text_line, &w, &h, &toggle_x, &toggle_y,
67                 &text_x, &text_y, &text_w, &text_h,
68                 has_caption() ? caption : 0,
69                 font);
70
71 // Create the subwindow
72         BC_SubWindow::initialize();
73         set_cursor(UPRIGHT_ARROW_CURSOR, 0, 0);
74 // Display the bitmap
75         draw_face(1, 0);
76         show_window(0);
77         return 0;
78 }
79
80
81 void BC_Toggle::calculate_extents(BC_WindowBase *gui,
82         VFrame **images, int bottom_justify,
83         int *text_line, int *w, int *h, int *toggle_x, int *toggle_y,
84         int *text_x, int *text_y, int *text_w, int *text_h,
85         const char *caption, int font)
86 {
87         BC_Resources *resources = get_resources();
88         VFrame *frame = images[0];
89         *w = frame->get_w();
90         *h = frame->get_h();
91         *toggle_x = 0;
92         *toggle_y = 0;
93         *text_x = *w + 5;
94         *text_y = 0;
95         *text_w = 0;
96         *text_h = 0;
97
98         if( caption ) {
99                 *text_w = gui->get_text_width(font, caption);
100                 *text_h = gui->get_text_height(font);
101
102                 if( resources->toggle_highlight_bg ) {
103                         *text_w += resources->toggle_text_margin * 2;
104                         *text_h = MAX(*text_h, resources->toggle_highlight_bg->get_h());
105                 }
106
107                 if( *text_h > *h ) {
108                         *toggle_y = (*text_h - *h) >> 1;
109                         *h = *text_h;
110                 }
111                 else
112                         *text_y = (*h - *text_h) >> 1;
113
114                 if( bottom_justify ) {
115                         *text_y = *h - *text_h;
116                         *text_line = *h - gui->get_text_descent(font);
117                 }
118                 else
119                         *text_line = *text_y + gui->get_text_ascent(font);
120
121                 *w = *text_x + *text_w;
122         }
123
124
125 }
126
127 void BC_Toggle::set_radial(int value)
128 {
129         is_radial = value;
130 }
131
132 int BC_Toggle::set_images(VFrame **data)
133 {
134         delete bg_image;
135         bg_image = 0;
136         for( int i=0; i<TOGGLE_IMAGES; ++i ) {
137                 delete images[i];
138                 images[i] = new BC_Pixmap(top_level, data[i], PIXMAP_ALPHA);
139         }
140         BC_Resources *resources = get_resources();
141         if( resources->toggle_highlight_bg ) {
142                 bg_image = new BC_Pixmap(top_level,
143                         resources->toggle_highlight_bg,
144                         PIXMAP_ALPHA);
145         }
146         return 0;
147 }
148
149 void BC_Toggle::set_underline(int number)
150 {
151         this->underline = number;
152 }
153
154
155 void BC_Toggle::set_select_drag(int value)
156 {
157         this->select_drag = value;
158 }
159
160 int BC_Toggle::draw_face(int flash, int flush)
161 {
162         BC_Resources *resources = get_resources();
163         draw_top_background(parent_window, 0, 0, get_w(), get_h());
164         if( has_caption() ) {
165                 if( enabled &&
166                         (status == BC_Toggle::TOGGLE_UPHI ||
167                                 status == BC_Toggle::TOGGLE_DOWN ||
168                                 status == BC_Toggle::TOGGLE_CHECKEDHI) ) {
169 // Draw highlight image
170                         if( bg_image ) {
171                                 int x = text_x;
172                                 int y = text_line - get_text_ascent(font) / 2 -
173                                                 bg_image->get_h() / 2;
174                                 y = MAX(y, 0);
175                                 int w = text_w;
176                                 draw_3segmenth(x,
177                                         y,
178                                         w,
179                                         bg_image);
180                         }
181                         else
182 // Draw a plain box
183                         {
184                                 set_color(LTGREY);
185                                 draw_box(text_x,
186                                         text_line - get_text_ascent(font),
187                                         get_w() - text_x,
188                                         get_text_height(font));
189                         }
190                 }
191
192                 set_opaque();
193                 if( enabled )
194                         set_color(color);
195                 else
196                         set_color(get_resources()->disabled_text_color);
197                 set_font(font);
198                 draw_text(text_x + resources->toggle_text_margin,
199                         text_line,
200                         caption);
201
202 // Draw underline
203                 if( underline >= 0 ) {
204                         int x = text_x + resources->toggle_text_margin;
205                         int y = text_line + 1;
206                         int x1 = get_text_width(current_font, caption, underline) + x;
207                         int x2 = get_text_width(current_font, caption, underline + 1) + x;
208                         draw_line(x1, y, x2, y);
209                         draw_line(x1, y + 1, (x2 + x1) / 2, y + 1);
210                 }
211         }
212
213         draw_pixmap(images[status]);
214         if( flash ) this->flash(0);
215         if( flush ) this->flush();
216         return 0;
217 }
218
219 void BC_Toggle::enable()
220 {
221         enabled = 1;
222         if( parent_window ) draw_face(1, 1);
223 }
224
225 void BC_Toggle::disable()
226 {
227         enabled = 0;
228         if( parent_window ) draw_face(1, 1);
229 }
230
231 void BC_Toggle::set_status(int value)
232 {
233         this->status = value;
234 }
235
236
237 int BC_Toggle::repeat_event(int64_t duration)
238 {
239         if( tooltip_text && tooltip_text[0] != 0 &&
240                 duration == top_level->get_resources()->tooltip_delay &&
241                 (status == BC_Toggle::TOGGLE_UPHI || status == BC_Toggle::TOGGLE_CHECKEDHI) ) {
242                 show_tooltip();
243                 return 1;
244         }
245         return 0;
246 }
247
248 int BC_Toggle::cursor_enter_event()
249 {
250         if( top_level->event_win == win && enabled ) {
251                 if( top_level->button_down )
252                         status = BC_Toggle::TOGGLE_DOWN;
253                 else
254                         status = value ? BC_Toggle::TOGGLE_CHECKEDHI : BC_Toggle::TOGGLE_UPHI;
255                 draw_face(1, 1);
256         }
257         return 0;
258 }
259
260 int BC_Toggle::cursor_leave_event()
261 {
262         hide_tooltip();
263         if( !value && status == BC_Toggle::TOGGLE_UPHI ) {
264                 status = BC_Toggle::TOGGLE_UP;
265                 draw_face(1, 1);
266         }
267         else
268         if( status == BC_Toggle::TOGGLE_CHECKEDHI ) {
269                 status = BC_Toggle::TOGGLE_CHECKED;
270                 draw_face(1, 1);
271         }
272         return 0;
273 }
274
275 int BC_Toggle::button_press_event()
276 {
277         hide_tooltip();
278         if( top_level->event_win == win && get_buttonpress() == 1 && enabled ) {
279                 status = BC_Toggle::TOGGLE_DOWN;
280
281 // Change value now for select drag mode.
282 // Radial always goes to 1
283                 if( select_drag ) {
284                         if( !is_radial )
285                                 value = !value;
286                         else
287                                 value = 1;
288                         top_level->toggle_drag = 1;
289                         top_level->toggle_value = value;
290                         handle_event();
291                 }
292
293                 draw_face(1, 1);
294                 return 1;
295         }
296         return 0;
297 }
298
299 int BC_Toggle::button_release_event()
300 {
301         int result = 0;
302         hide_tooltip();
303
304         if( top_level->event_win == win ) {
305 // Keep value regardless of status if drag mode.
306                 if( select_drag ) {
307                         if( value )
308                                 status = BC_Toggle::TOGGLE_CHECKEDHI;
309                         else
310                                 status = BC_Toggle::TOGGLE_UPHI;
311                         top_level->toggle_drag = 0;
312                 }
313                 else
314 // Change value only if button down for default mode.
315                 if( status == BC_Toggle::TOGGLE_DOWN ) {
316 // Radial always goes to 1.
317                         if( !value || is_radial ) {
318                                 status = BC_Toggle::TOGGLE_CHECKEDHI;
319                                 value = 1;
320                         }
321                         else {
322                                 status = BC_Toggle::TOGGLE_UPHI;
323                                 value = 0;
324                         }
325                         result = handle_event();
326                 }
327                 draw_face(1, 1);
328                 return result;
329         }
330         return 0;
331 }
332
333 int BC_Toggle::cursor_motion_event()
334 {
335         if( top_level->button_down &&
336                 top_level->event_win == win &&
337                 !cursor_inside() ) {
338                 if( status == BC_Toggle::TOGGLE_DOWN ) {
339                         if( value )
340                                 status = BC_Toggle::TOGGLE_CHECKED;
341                         else
342                                 status = BC_Toggle::TOGGLE_UP;
343                         draw_face(1, 1);
344                 }
345                 else
346                 if( status == BC_Toggle::TOGGLE_UPHI ) {
347                         status = BC_Toggle::TOGGLE_CHECKEDHI;
348                         draw_face(1, 1);
349                 }
350         }
351         return 0;
352 }
353
354 int BC_Toggle::get_value()
355 {
356         return value;
357 }
358
359 int BC_Toggle::set_value(int value, int draw)
360 {
361         if( value != this->value ) {
362                 this->value = value;
363                 if( value ) {
364                         switch( status ) {
365                         case BC_Toggle::TOGGLE_UP:
366                                 status = BC_Toggle::TOGGLE_CHECKED;
367                                 break;
368                         case BC_Toggle::TOGGLE_UPHI:
369                                 status = BC_Toggle::TOGGLE_CHECKEDHI;
370                                 break;
371                         }
372                 }
373                 else {
374                         switch( status ) {
375                         case BC_Toggle::TOGGLE_CHECKED:
376                                 status = BC_Toggle::TOGGLE_UP;
377                                 break;
378                         case BC_Toggle::TOGGLE_CHECKEDHI:
379                                 status = BC_Toggle::TOGGLE_UPHI;
380                                 break;
381                         }
382                 }
383                 if( draw ) draw_face(1, 1);
384         }
385         return 0;
386 }
387
388 int BC_Toggle::update(int value, int draw)
389 {
390         return set_value(value, draw);
391 }
392
393 void BC_Toggle::reposition_window(int x, int y)
394 {
395         BC_WindowBase::reposition_window(x, y);
396         draw_face(1, 0);
397 }
398
399
400 int BC_Toggle::has_caption()
401 {
402         return (caption != 0 && caption[0] != 0);
403 }
404
405 BC_Radial::BC_Radial(int x, int y, int value,
406         const char *caption, int font, int color)
407  : BC_Toggle(x, y,
408         BC_WindowBase::get_resources()->radial_images,
409         value, caption, 0, font, color)
410 {
411         is_radial = 1;
412 }
413
414 BC_CheckBox::BC_CheckBox(int x, int y, int value,
415         const char *caption, int font, int color)
416  : BC_Toggle(x, y,
417         BC_WindowBase::get_resources()->checkbox_images,
418         value, caption, 0, font, color)
419 {
420         this->value = 0;
421 }
422
423 BC_CheckBox::BC_CheckBox(int x, int y, int *value,
424         const char *caption, int font, int color)
425  : BC_Toggle(x, y,
426         BC_WindowBase::get_resources()->checkbox_images,
427         *value, caption, 1, font, color)
428 {
429         this->value = value;
430 }
431
432 void BC_CheckBox::calculate_extents(BC_WindowBase *gui, int *w, int *h,
433         const char *caption, int font)
434 {
435         int text_line, toggle_x, toggle_y;
436         int text_x, text_y, text_w, text_h;
437
438         BC_Toggle::calculate_extents(gui,
439                 BC_WindowBase::get_resources()->checkbox_images,
440                 1, &text_line, w, h, &toggle_x, &toggle_y,
441                 &text_x, &text_y, &text_w, &text_h, caption, font);
442 }
443
444 int BC_CheckBox::handle_event()
445 {
446         if( value )
447                 *value = get_value();
448         return 1;
449 }
450
451 int BC_CheckBox::calculate_h(BC_WindowBase *gui, int font)
452 {
453         int w, h;
454         calculate_extents(gui, &w, &h, "X", font);
455         return h;
456 }
457
458
459 BC_Label::BC_Label(int x, int y, int value, int font, int color)
460  : BC_Toggle(x, y,
461         BC_WindowBase::get_resources()->label_images, value,
462         "", 0, font, color)
463 {
464 }