Merge CV, ver=5.1; ops/methods from HV, and interface from CV where possible
[goodguy/history.git] / cinelerra-5.1 / plugins / titler / titlewindow.C
1
2 /*
3  * CINELERRA
4  * Copyright (C) 1997-2014 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 "bcdisplayinfo.h"
23 #include "bcsignals.h"
24 #include "cstrdup.h"
25 #include "language.h"
26 #include "theme.h"
27 #include "titlewindow.h"
28 #include "bcfontentry.h"
29
30 #include <wchar.h>
31
32 static const int timeunit_formats[] =
33 {
34         TIME_HMS,
35         TIME_SECONDS,
36         TIME_HMSF,
37         TIME_SAMPLES,
38         TIME_SAMPLES_HEX,
39         TIME_FRAMES,
40         TIME_FEET_FRAMES
41 };
42
43 TitleWindow::TitleWindow(TitleMain *client)
44  : PluginClientWindow(client,
45         client->config.window_w,
46         client->config.window_h,
47         100,
48         100,
49         1)
50 {
51 //printf("TitleWindow::TitleWindow %d %d %d\n", __LINE__, client->config.window_w, client->config.window_h);
52         this->client = client;
53         font_tumbler = 0;
54         justify_title = 0;
55         style_title = 0;
56         size_title = 0;
57         title_y = 0;
58         bottom = 0;
59         size = 0;
60         loop = 0;
61         title_x = 0;
62         dropshadow = 0;
63         motion = 0;
64         dropshadow_title = 0;
65         text = 0;
66         timecode = 0;
67         fade_in = 0;
68         encoding_title = 0;
69         x_title = 0;
70         bold = 0;
71         color_y = 0;
72         speed = 0;
73         center = 0;
74         italic = 0;
75         text_title = 0;
76         motion_title = 0;
77         fadeout_title = 0;
78         font_title = 0;
79         fadein_title = 0;
80         fade_out = 0;
81         color_button = 0;
82         left = 0;
83         speed_title = 0;
84         top = 0;
85         font = 0;
86         right = 0;
87         color_x = 0;
88         color_y = 0;
89         y_title = 0;
90         color_thread = 0;
91         mid = 0;
92         encoding_title = 0;
93         encoding = 0;
94 }
95
96 TitleWindow::~TitleWindow()
97 {
98         for(int j = 0; j < fonts.size(); j++)
99         {
100 // delete the pixmaps but not the vframes since they're static
101                 delete fonts.get(j)->get_icon();
102         }
103
104         sizes.remove_all_objects();
105         delete timecode_format;
106         delete color_thread;
107 #ifdef USE_OUTLINE
108         delete color_stroke_thread;
109 #endif
110         delete title_x;
111         delete title_y;
112 }
113
114 void TitleWindow::create_objects()
115 {
116         int x = 10, y = 10;
117         int margin = client->get_theme()->widget_border;
118         char string[BCTEXTLEN];
119
120 #define COLOR_W 50
121 #define COLOR_H 30
122         client->build_previews(this);
123
124         encodings.append(new BC_ListBoxItem("ISO8859-1"));
125         encodings.append(new BC_ListBoxItem("ISO8859-2"));
126         encodings.append(new BC_ListBoxItem("ISO8859-3"));
127         encodings.append(new BC_ListBoxItem("ISO8859-4"));
128         encodings.append(new BC_ListBoxItem("ISO8859-5"));
129         encodings.append(new BC_ListBoxItem("ISO8859-6"));
130         encodings.append(new BC_ListBoxItem("ISO8859-7"));
131         encodings.append(new BC_ListBoxItem("ISO8859-8"));
132         encodings.append(new BC_ListBoxItem("ISO8859-9"));
133         encodings.append(new BC_ListBoxItem("ISO8859-10"));
134         encodings.append(new BC_ListBoxItem("ISO8859-11"));
135         encodings.append(new BC_ListBoxItem("ISO8859-12"));
136         encodings.append(new BC_ListBoxItem("ISO8859-13"));
137         encodings.append(new BC_ListBoxItem("ISO8859-14"));
138         encodings.append(new BC_ListBoxItem("ISO8859-15"));
139         encodings.append(new BC_ListBoxItem("KOI8"));
140         encodings.append(new BC_ListBoxItem("UTF-8"));
141
142
143         sizes.append(new BC_ListBoxItem("8"));
144         sizes.append(new BC_ListBoxItem("9"));
145         sizes.append(new BC_ListBoxItem("10"));
146         sizes.append(new BC_ListBoxItem("11"));
147         sizes.append(new BC_ListBoxItem("12"));
148         sizes.append(new BC_ListBoxItem("13"));
149         sizes.append(new BC_ListBoxItem("14"));
150         sizes.append(new BC_ListBoxItem("16"));
151         sizes.append(new BC_ListBoxItem("18"));
152         sizes.append(new BC_ListBoxItem("20"));
153         sizes.append(new BC_ListBoxItem("22"));
154         sizes.append(new BC_ListBoxItem("24"));
155         sizes.append(new BC_ListBoxItem("26"));
156         sizes.append(new BC_ListBoxItem("28"));
157         sizes.append(new BC_ListBoxItem("32"));
158         sizes.append(new BC_ListBoxItem("36"));
159         sizes.append(new BC_ListBoxItem("40"));
160         sizes.append(new BC_ListBoxItem("48"));
161         sizes.append(new BC_ListBoxItem("56"));
162         sizes.append(new BC_ListBoxItem("64"));
163         sizes.append(new BC_ListBoxItem("72"));
164         sizes.append(new BC_ListBoxItem("100"));
165         sizes.append(new BC_ListBoxItem("128"));
166         sizes.append(new BC_ListBoxItem("256"));
167         sizes.append(new BC_ListBoxItem("512"));
168         sizes.append(new BC_ListBoxItem("1024"));
169
170         paths.append(new BC_ListBoxItem(TitleMain::motion_to_text(NO_MOTION)));
171         paths.append(new BC_ListBoxItem(TitleMain::motion_to_text(BOTTOM_TO_TOP)));
172         paths.append(new BC_ListBoxItem(TitleMain::motion_to_text(TOP_TO_BOTTOM)));
173         paths.append(new BC_ListBoxItem(TitleMain::motion_to_text(RIGHT_TO_LEFT)));
174         paths.append(new BC_ListBoxItem(TitleMain::motion_to_text(LEFT_TO_RIGHT)));
175
176
177
178 // Construct font list
179         ArrayList<BC_FontEntry*> *fontlist = get_resources()->fontlist;
180
181         for(int i = 0; i < fontlist->size(); i++) {
182                 int exists = 0;
183                 for(int j = 0; j < fonts.size(); j++) {
184                         if(!strcasecmp(fonts.get(j)->get_text(),
185                                 fontlist->get(i)->displayname)) {
186                                 exists = 1;
187                                 break;
188                         }
189                 }
190
191                 BC_ListBoxItem *item = 0;
192                 if(!exists) {
193                         fonts.append(item = new
194                                 BC_ListBoxItem(fontlist->get(i)->displayname));
195                         if(!strcmp(client->config.font, item->get_text()))
196                                 item->set_selected(1);
197                         if(fontlist->values[i]->image)
198                         {
199                                 VFrame *vframe = fontlist->get(i)->image;
200                                 BC_Pixmap *icon = new BC_Pixmap(this, vframe, PIXMAP_ALPHA);
201                                 item->set_icon(icon);
202                                 item->set_icon_vframe(vframe);
203                         }
204                 }
205         }
206
207 // Sort font list
208         int done = 0;
209         while(!done) {
210                 done = 1;
211                 for(int i = 0; i < fonts.size() - 1; i++) {
212                         if(strcmp(fonts.values[i]->get_text(),
213                                 fonts.values[i + 1]->get_text()) > 0) {
214                                 BC_ListBoxItem *temp = fonts.values[i + 1];
215                                 fonts.values[i + 1] = fonts.values[i];
216                                 fonts.values[i] = temp;
217                                 done = 0;
218                         }
219                 }
220         }
221
222         add_tool(font_title = new BC_Title(x, y, _("Font:")));
223         font = new TitleFont(client, this, x, y + font_title->get_h());
224         font->create_objects();
225         x += font->get_w();
226         add_subwindow(font_tumbler = new TitleFontTumble(client, this, x, y+10));
227         x += font_tumbler->get_w() + margin;
228
229         int x1 = x, y1 = y;
230         add_tool(size_title = new BC_Title(x1, y1+10, _("Size:")));
231         sprintf(string, "%d", client->config.size);
232         x1 += size_title->get_w() + margin;
233         size = new TitleSize(client, this, x1, y1+10, string);
234         size->create_objects();
235         int x2 = x1 + size->get_w(), y2 = y1 + size->get_h() + margin;
236         add_subwindow(size_tumbler = new TitleSizeTumble(client, this, x2, y1+10));
237
238         add_tool(pitch_title = new BC_Title(x-5, y2+10, _("Pitch:")));
239         pitch = new TitlePitch(client, this, x1, y2+10, &client->config.line_pitch);
240         pitch->create_objects();
241         x = x2 + size_tumbler->get_w() + margin;
242
243         add_tool(style_title = new BC_Title(x, y, _("Style:")));
244         add_tool(italic = new TitleItalic(client, this, x, y + 20));
245         int w1 = italic->get_w();
246         add_tool(bold = new TitleBold(client, this, x, y + 50));
247         if( bold->get_w() > w1 ) w1 = bold->get_w();  
248 #ifdef USE_OUTLINE
249         add_tool(stroke = new TitleStroke(client, this, x, y + 80));
250         if( stroke->get_w() > w1 ) w1 = stroke->get_w();  
251 #endif
252         x += w1 + 10;
253         add_tool(justify_title = new BC_Title(x, y, _("Justify:")));
254         add_tool(left = new TitleLeft(client, this, x, y + 20));
255         w1 = left->get_w();
256         add_tool(center = new TitleCenter(client, this, x, y + 50));
257         if( center->get_w() > w1 ) w1 = center->get_w();  
258         add_tool(right = new TitleRight(client, this, x, y + 80));
259         if( right->get_w() > w1 ) w1 = right->get_w();  
260
261         x += w1 + 10;
262         add_tool(top = new TitleTop(client, this, x, y + 20));
263         add_tool(mid = new TitleMid(client, this, x, y + 50));
264         add_tool(bottom= new TitleBottom(client, this, x, y + 80));
265
266         y += 50;
267         x = 10;
268
269         add_tool(x_title = new BC_Title(x, y, _("X:")));
270         title_x = new TitleX(client, this, x, y + 20);
271         title_x->create_objects();
272         x += 90;
273
274         add_tool(y_title = new BC_Title(x, y, _("Y:")));
275         title_y = new TitleY(client, this, x, y + 20);
276         title_y->create_objects();
277         x += 90;
278
279         add_tool(motion_title = new BC_Title(x, y, _("Motion type:")));
280
281         motion = new TitleMotion(client, this, x, y + 20);
282         motion->create_objects();
283         x += 150;
284
285         add_tool(loop = new TitleLoop(client, x, y + 20));
286
287         x = 10;
288         y += 50;
289
290         add_tool(dropshadow_title = new BC_Title(x, y, _("Drop shadow:")));
291         w1 = dropshadow_title->get_w();
292         dropshadow = new TitleDropShadow(client, this, x, y + 20);
293         dropshadow->create_objects();
294         if( dropshadow->get_w() > w1 ) w1 = dropshadow->get_w();
295         x += w1 + 10;
296
297         add_tool(fadein_title = new BC_Title(x, y, _("Fade in (sec):")));
298         w1 = fadein_title->get_w();
299         add_tool(fade_in = new TitleFade(client, this, &client->config.fade_in, x, y + 20));
300         if( fade_in->get_w() > w1 ) w1 = fade_in->get_w();
301         x += w1 + 10;
302
303         add_tool(fadeout_title = new BC_Title(x, y, _("Fade out (sec):")));
304         w1 = fadeout_title->get_w();
305         add_tool(fade_out = new TitleFade(client, this, &client->config.fade_out, x, y + 20));
306         if( fade_out->get_w() > w1 ) w1 = fade_out->get_w();
307         x += w1 + 10;
308
309         add_tool(speed_title = new BC_Title(x, y, _("Speed:")));
310         w1 = speed_title->get_w();
311         speed = new TitleSpeed(client, this, x, y + 20);
312         speed->create_objects();
313         if( speed->get_w() > w1 ) w1 = speed->get_w();
314         x += w1 + 10;
315
316         color_x = x;
317         color_y = y + 16;
318         x += COLOR_W + 5;
319         add_tool(color_button = new TitleColorButton(client, this, x, y + 16, 0));
320         x += color_button->get_w() + 5;
321         color_thread = new TitleColorThread(client, this, 0);
322
323         x = color_x;
324         y += 50;
325
326         outline_color_x = x;
327         outline_color_y = y + 20;
328         x += COLOR_W + 5;
329         add_tool(outline_color_button = new TitleColorButton(client, this, x, y + 20, 1));
330         x += outline_color_button->get_w();
331         outline_color_thread = new TitleColorThread(client, this, 1);
332
333         x = 10;
334 //      y += 50;
335
336         add_tool(outline_title = new BC_Title(x, y, _("Outline:")));
337         outline = new TitleOutline(client, this, x, y + outline_title->get_h() + margin);
338         outline->create_objects();
339         x += outline->get_w() + margin;
340
341 #ifndef X_HAVE_UTF8_STRING
342         add_tool(encoding_title = new BC_Title(x, y + 3, _("Encoding:")));
343         encoding = new TitleEncoding(client, this, x, y + encoding_title->get_h() + margin);
344         encoding->create_objects();
345         x += 100;
346 #endif
347
348         y += outline_title->get_h() + margin;
349         add_tool(timecode = new TitleTimecode(client, x, y));
350         x += timecode->get_w() + margin;
351
352         add_tool(timecode_format = new TitleTimecodeFormat(client, x, y,
353                 Units::print_time_format(client->config.timecode_format, string)));
354         timecode_format->create_objects();
355         x = 10;
356         y += timecode_format->get_h() + margin;
357
358         add_tool(text_title = new BC_Title(x, y + 3, _("Text:")));
359         y += text_title->get_h() + margin;
360         text = new TitleText(client, this, x, y, get_w() - x - 10, get_h() - y - 50);
361         text->create_objects();
362         update();
363
364         show_window(1);
365 }
366
367 int TitleWindow::resize_event(int w, int h)
368 {
369         client->config.window_w = w;
370         client->config.window_h = h;
371
372         clear_box(0, 0, w, h);
373         font_title->reposition_window(font_title->get_x(), font_title->get_y());
374         font->reposition_window(font->get_x(), font->get_y());
375         font_tumbler->reposition_window(font_tumbler->get_x(), font_tumbler->get_y());
376         x_title->reposition_window(x_title->get_x(), x_title->get_y());
377         title_x->reposition_window(title_x->get_x(), title_x->get_y());
378         y_title->reposition_window(y_title->get_x(), y_title->get_y());
379         title_y->reposition_window(title_y->get_x(), title_y->get_y());
380         style_title->reposition_window(style_title->get_x(), style_title->get_y());
381         italic->reposition_window(italic->get_x(), italic->get_y());
382         bold->reposition_window(bold->get_x(), bold->get_y());
383 #ifdef USE_OUTLINE
384         stroke->reposition_window(stroke->get_x(), stroke->get_y());
385 #endif
386         size_title->reposition_window(size_title->get_x(), size_title->get_y());
387         size->reposition_window(size->get_x(), size->get_y());
388         size_tumbler->reposition_window(size_title->get_x(), size_title->get_y());
389         pitch_title->reposition_window(pitch_title->get_x(), pitch_title->get_y());
390         pitch->reposition_window(size->get_x(), size->get_y());
391
392 #ifndef X_HAVE_UTF8_STRING
393         encoding->reposition_window(encoding->get_x(), encoding->get_y());
394 #endif
395
396         color_button->reposition_window(color_button->get_x(), color_button->get_y());
397 #ifdef USE_OUTLINE
398         color_stroke_button->reposition_window(color_stroke_button->get_x(), color_stroke_button->get_y());
399 #endif
400         outline_color_button->reposition_window(outline_color_button->get_x(), outline_color_button->get_y());
401         motion_title->reposition_window(motion_title->get_x(), motion_title->get_y());
402         motion->reposition_window(motion->get_x(), motion->get_y());
403         loop->reposition_window(loop->get_x(), loop->get_y());
404         dropshadow_title->reposition_window(dropshadow_title->get_x(), dropshadow_title->get_y());
405         dropshadow->reposition_window(dropshadow->get_x(), dropshadow->get_y());
406         fadein_title->reposition_window(fadein_title->get_x(), fadein_title->get_y());
407         fade_in->reposition_window(fade_in->get_x(), fade_in->get_y());
408         fadeout_title->reposition_window(fadeout_title->get_x(), fadeout_title->get_y());
409         fade_out->reposition_window(fade_out->get_x(), fade_out->get_y());
410         text_title->reposition_window(text_title->get_x(), text_title->get_y());
411 #ifdef USE_OUTLINE
412         stroke_width->reposition_window(stroke_width->get_x(), stroke_width->get_y());
413         strokewidth_title->reposition_window(strokewidth_title->get_x(), strokewidth_title->get_y());
414 #endif
415         timecode->reposition_window(timecode->get_x(), timecode->get_y());
416
417         text->reposition_window(text->get_x(),
418                 text->get_y(),
419                 w - text->get_x() - 10,
420                 BC_TextBox::pixels_to_rows(this, MEDIUMFONT, h - text->get_y() - 10));
421
422
423
424         justify_title->reposition_window(justify_title->get_x(), justify_title->get_y());
425         left->reposition_window(left->get_x(), left->get_y());
426         center->reposition_window(center->get_x(), center->get_y());
427         right->reposition_window(right->get_x(), right->get_y());
428         top->reposition_window(top->get_x(), top->get_y());
429         mid->reposition_window(mid->get_x(), mid->get_y());
430         bottom->reposition_window(bottom->get_x(), bottom->get_y());
431         speed_title->reposition_window(speed_title->get_x(), speed_title->get_y());
432         speed->reposition_window(speed->get_x(), speed->get_y());
433         update_color();
434         flash();
435
436         return 1;
437 }
438
439
440 void TitleWindow::previous_font()
441 {
442         int current_font = font->get_number();
443         current_font--;
444         if(current_font < 0) current_font = fonts.total - 1;
445
446         if(current_font < 0 || current_font >= fonts.total) return;
447
448         for(int i = 0; i < fonts.total; i++)
449         {
450                 fonts.values[i]->set_selected(i == current_font);
451         }
452
453         font->update(fonts.values[current_font]->get_text());
454         strcpy(client->config.font, fonts.values[current_font]->get_text());
455         client->send_configure_change();
456 }
457
458 void  TitleWindow::next_font()
459 {
460         int current_font = font->get_number();
461         current_font++;
462         if(current_font >= fonts.total) current_font = 0;
463
464         if(current_font < 0 || current_font >= fonts.total) return;
465
466         for(int i = 0; i < fonts.total; i++)
467         {
468                 fonts.values[i]->set_selected(i == current_font);
469         }
470
471         font->update(fonts.values[current_font]->get_text());
472         strcpy(client->config.font, fonts.values[current_font]->get_text());
473         client->send_configure_change();
474 }
475
476
477
478 void TitleWindow::update_color()
479 {
480 //printf("TitleWindow::update_color %x\n", client->config.color);
481         set_color(client->config.color);
482         draw_box(color_x, color_y, COLOR_W, COLOR_H);
483         flash(color_x, color_y, COLOR_W, COLOR_H);
484         set_color(client->config.outline_color);
485         draw_box(outline_color_x, outline_color_y, COLOR_W, COLOR_H);
486         set_color(BLACK);
487         draw_rectangle(color_x, color_y, COLOR_W, COLOR_H);
488         draw_rectangle(outline_color_x, outline_color_y, COLOR_W, COLOR_H);
489         flash(outline_color_x, outline_color_y, COLOR_W, COLOR_H);
490 }
491
492 void TitleWindow::update_justification()
493 {
494         left->update(client->config.hjustification == JUSTIFY_LEFT);
495         center->update(client->config.hjustification == JUSTIFY_CENTER);
496         right->update(client->config.hjustification == JUSTIFY_RIGHT);
497         top->update(client->config.vjustification == JUSTIFY_TOP);
498         mid->update(client->config.vjustification == JUSTIFY_MID);
499         bottom->update(client->config.vjustification == JUSTIFY_BOTTOM);
500 }
501
502 void TitleWindow::update()
503 {
504         title_x->update((int64_t)client->config.x);
505         title_y->update((int64_t)client->config.y);
506         italic->update(client->config.style & BC_FONT_ITALIC);
507         bold->update(client->config.style & BC_FONT_BOLD);
508 #ifdef USE_OUTLINE
509         stroke->update(client->config.style & BC_FONT_OUTLINE);
510 #endif
511         size->update(client->config.size);
512 #ifndef X_HAVE_UTF8_STRING
513         encoding->update(client->config.encoding);
514 #endif
515         motion->update(TitleMain::motion_to_text(client->config.motion_strategy));
516         loop->update(client->config.loop);
517         dropshadow->update((float)client->config.dropshadow);
518         fade_in->update((float)client->config.fade_in);
519         fade_out->update((float)client->config.fade_out);
520 #ifdef USE_OUTLINE
521         stroke_width->update((float)client->config.stroke_width);
522 #endif
523         font->update(client->config.font);
524         text->update(&client->config.wtext[0]);
525         speed->update(client->config.pixels_per_second);
526         outline->update((int64_t)client->config.outline_size);
527         timecode->update(client->config.timecode);
528         timecode_format->update(client->config.timecode_format);
529
530         char string[BCTEXTLEN];
531         for(int i = 0; i < lengthof(timeunit_formats); i++) {
532                 if(timeunit_formats[i] == client->config.timecode_format)
533                 {
534                         timecode_format->set_text(
535                                 Units::print_time_format(timeunit_formats[i], string));
536                         break;
537                 }
538         }
539         update_justification();
540         update_color();
541 }
542
543
544 TitleFontTumble::TitleFontTumble(TitleMain *client, TitleWindow *window, int x, int y)
545  : BC_Tumbler(x, y)
546 {
547         this->client = client;
548         this->window = window;
549 }
550 int TitleFontTumble::handle_up_event()
551 {
552         window->previous_font();
553         return 1;
554 }
555
556 int TitleFontTumble::handle_down_event()
557 {
558         window->next_font();
559         return 1;
560 }
561
562
563
564 TitleSizeTumble::TitleSizeTumble(TitleMain *client, TitleWindow *window, int x, int y)
565  : BC_Tumbler(x, y)
566 {
567         this->client = client;
568         this->window = window;
569 }
570
571 int TitleSizeTumble::handle_up_event()
572 {
573         int current_index = -1;
574         int current_difference = -1;
575         for(int i = 0; i < window->sizes.size(); i++)
576         {
577                 int size = atoi(window->sizes.get(i)->get_text());
578                 if(current_index < 0 ||
579                         abs(size - client->config.size) < current_difference)
580                 {
581                         current_index = i;
582                         current_difference = abs(size - client->config.size);
583                 }
584         }
585
586         current_index++;
587         if(current_index >= window->sizes.size()) current_index = 0;
588
589
590         client->config.size = atoi(window->sizes.get(current_index)->get_text());
591         window->size->update(client->config.size);
592         client->send_configure_change();
593         return 1;
594 }
595
596 int TitleSizeTumble::handle_down_event()
597 {
598         int current_index = -1;
599         int current_difference = -1;
600         for(int i = 0; i < window->sizes.size(); i++)
601         {
602                 int size = atoi(window->sizes.get(i)->get_text());
603                 if(current_index < 0 ||
604                         abs(size - client->config.size) < current_difference)
605                 {
606                         current_index = i;
607                         current_difference = abs(size - client->config.size);
608                 }
609         }
610
611         current_index--;
612         if(current_index < 0) current_index = window->sizes.size() - 1;
613
614
615         client->config.size = atoi(window->sizes.get(current_index)->get_text());
616         window->size->update(client->config.size);
617         client->send_configure_change();
618         return 1;
619 }
620
621 TitleBold::TitleBold(TitleMain *client, TitleWindow *window, int x, int y)
622  : BC_CheckBox(x, y, client->config.style & BC_FONT_BOLD, _("Bold"))
623 {
624         this->client = client;
625         this->window = window;
626 }
627
628 int TitleBold::handle_event()
629 {
630         client->config.style =
631                 (client->config.style & ~BC_FONT_BOLD) |
632                         (get_value() ? BC_FONT_BOLD : 0);
633         client->send_configure_change();
634         return 1;
635 }
636
637 TitleItalic::TitleItalic(TitleMain *client, TitleWindow *window, int x, int y)
638  : BC_CheckBox(x, y, client->config.style & BC_FONT_ITALIC, _("Italic"))
639 {
640         this->client = client;
641         this->window = window;
642 }
643 int TitleItalic::handle_event()
644 {
645         client->config.style =
646                 (client->config.style & ~BC_FONT_ITALIC) |
647                         (get_value() ? BC_FONT_ITALIC : 0);
648         client->send_configure_change();
649         return 1;
650 }
651
652
653
654 TitleSize::TitleSize(TitleMain *client, TitleWindow *window, int x, int y, char *text)
655  : BC_PopupTextBox(window,
656                 &window->sizes,
657                 text,
658                 x,
659                 y,
660                 64,
661                 300)
662 {
663         this->client = client;
664         this->window = window;
665 }
666 TitleSize::~TitleSize()
667 {
668 }
669 int TitleSize::handle_event()
670 {
671         client->config.size = atol(get_text());
672 //printf("TitleSize::handle_event 1 %s\n", get_text());
673         client->send_configure_change();
674         return 1;
675 }
676 void TitleSize::update(int size)
677 {
678         char string[BCTEXTLEN];
679         sprintf(string, "%d", size);
680         BC_PopupTextBox::update(string);
681 }
682
683 TitlePitch::
684 TitlePitch(TitleMain *client, TitleWindow *window, int x, int y, int *value)
685  : BC_TumbleTextBox(window, *value, 0, INT_MAX, x, y, 64)
686
687 {
688         this->client = client;
689         this->window = window;
690         this->value = value;
691 }
692
693 TitlePitch::
694 ~TitlePitch()
695 {
696 }
697
698 int TitlePitch::handle_event()
699 {
700         *value = atof(get_text());
701         client->send_configure_change();
702         return 1;
703 }
704
705 TitleColorButton::TitleColorButton(TitleMain *client,
706         TitleWindow *window,
707         int x,
708         int y,
709         int is_outline)
710  : BC_GenericButton(x, y, is_outline ? _("Outline color...") : _("Color..."))
711 {
712         this->client = client;
713         this->window = window;
714         this->is_outline = is_outline;
715 }
716 int TitleColorButton::handle_event()
717 {
718         if(is_outline)
719                 window->outline_color_thread->start_window(client->config.outline_color,
720                         client->config.outline_alpha);
721         else
722                 window->color_thread->start_window(client->config.color,
723                         client->config.alpha);
724         return 1;
725 }
726
727 TitleMotion::TitleMotion(TitleMain *client, TitleWindow *window, int x, int y)
728  : BC_PopupTextBox(window,
729                 &window->paths,
730                 client->motion_to_text(client->config.motion_strategy),
731                 x,
732                 y,
733                 120,
734                 100)
735 {
736         this->client = client;
737         this->window = window;
738 }
739 int TitleMotion::handle_event()
740 {
741         client->config.motion_strategy = client->text_to_motion(get_text());
742         client->send_configure_change();
743         return 1;
744 }
745
746 TitleLoop::TitleLoop(TitleMain *client, int x, int y)
747  : BC_CheckBox(x, y, client->config.loop, _("Loop"))
748 {
749         this->client = client;
750 }
751 int TitleLoop::handle_event()
752 {
753         client->config.loop = get_value();
754         client->send_configure_change();
755         return 1;
756 }
757 TitleTimecode::TitleTimecode(TitleMain *client, int x, int y)
758  : BC_CheckBox(x, y, client->config.timecode, _("Stamp timecode"))
759 {
760         this->client = client;
761 }
762 int TitleTimecode::handle_event()
763 {
764         client->config.timecode = get_value();
765         client->send_configure_change();
766         return 1;
767 }
768
769 TitleTimecodeFormat::TitleTimecodeFormat(TitleMain *client, int x, int y, const char *text)
770  : BC_PopupMenu(x, y, 100, text, 1)
771 {
772         this->client = client;
773 }
774
775 int TitleTimecodeFormat::handle_event()
776 {
777         client->config.timecode_format = Units::text_to_format(get_text());
778         client->send_configure_change();
779         return 1;
780 }
781
782 void TitleTimecodeFormat::create_objects()
783 {
784         char string[BCTEXTLEN];
785         for(int i = 0; i < lengthof(timeunit_formats); i++) {
786                 add_item(new BC_MenuItem(
787                         Units::print_time_format(timeunit_formats[i], string)));
788         }
789 }
790
791
792 int TitleTimecodeFormat::update(int timecode_format)
793 {
794         char string[BCTEXTLEN];
795         for(int i = 0; i < lengthof(timeunit_formats); i++) {
796                 if(timeunit_formats[i] == timecode_format)
797                 {
798                         set_text(Units::print_time_format(timeunit_formats[i], string));
799                         break;
800                 }
801         }
802         return 0;
803 }
804
805 TitleFade::TitleFade(TitleMain *client,
806         TitleWindow *window,
807         double *value,
808         int x,
809         int y)
810  : BC_TextBox(x, y, 90, 1, (float)*value)
811 {
812         this->client = client;
813         this->window = window;
814         this->value = value;
815 }
816
817 int TitleFade::handle_event()
818 {
819         *value = atof(get_text());
820         client->send_configure_change();
821         return 1;
822 }
823
824 TitleFont::TitleFont(TitleMain *client, TitleWindow *window, int x, int y)
825  : BC_PopupTextBox(window,
826                 &window->fonts,
827                 client->config.font,
828                 x,
829                 y,
830                 200,
831                 500,
832                 LISTBOX_ICON_LIST)
833 {
834         this->client = client;
835         this->window = window;
836 }
837 int TitleFont::handle_event()
838 {
839         strcpy(client->config.font, get_text());
840         client->send_configure_change();
841         return 1;
842 }
843
844 TitleText::TitleText(TitleMain *client,
845         TitleWindow *window, int x, int y, int w, int h)
846  : BC_ScrollTextBox(window, x, y, w,
847                 BC_TextBox::pixels_to_rows(window, MEDIUMFONT, h),
848                 client->config.wtext, 8192)
849 {
850         this->client = client;
851         this->window = window;
852 //printf("TitleText::TitleText %s\n", client->config.text);
853 }
854
855 int TitleText::handle_event()
856 {
857         int len =  sizeof(client->config.wtext) / sizeof(wchar_t);
858         wcsncpy(client->config.wtext, get_wtext(), len);
859         client->config.wtext[len-1] = 0;
860         client->config.wlen = wcslen(client->config.wtext);
861         client->send_configure_change();
862         return 1;
863 }
864
865
866 TitleDropShadow::TitleDropShadow(TitleMain *client, TitleWindow *window, int x, int y)
867  : BC_TumbleTextBox(window,
868         (int64_t)client->config.dropshadow,
869         (int64_t)-1000,
870         (int64_t)1000,
871         x,
872         y,
873         70)
874 {
875         this->client = client;
876         this->window = window;
877 }
878 int TitleDropShadow::handle_event()
879 {
880         client->config.dropshadow = atol(get_text());
881         client->send_configure_change();
882         return 1;
883 }
884
885
886 TitleOutline::TitleOutline(TitleMain *client, TitleWindow *window, int x, int y)
887  : BC_TumbleTextBox(window,
888         (int64_t)client->config.outline_size,
889         (int64_t)0,
890         (int64_t)1000,
891         x,
892         y,
893         70)
894 {
895         this->client = client;
896         this->window = window;
897 }
898 int TitleOutline::handle_event()
899 {
900         client->config.outline_size = atol(get_text());
901         client->send_configure_change();
902         return 1;
903 }
904
905
906 TitleX::TitleX(TitleMain *client, TitleWindow *window, int x, int y)
907  : BC_TumbleTextBox(window,
908         (int64_t)client->config.x,
909         (int64_t)-2048,
910         (int64_t)2048,
911         x,
912         y,
913         60)
914 {
915         this->client = client;
916         this->window = window;
917 }
918 int TitleX::handle_event()
919 {
920         client->config.x = atol(get_text());
921         client->send_configure_change();
922         return 1;
923 }
924
925 TitleY::TitleY(TitleMain *client, TitleWindow *window, int x, int y)
926  : BC_TumbleTextBox(window,
927         (int64_t)client->config.y,
928         (int64_t)-2048,
929         (int64_t)2048,
930         x,
931         y,
932         60)
933 {
934         this->client = client;
935         this->window = window;
936 }
937 int TitleY::handle_event()
938 {
939         client->config.y = atol(get_text());
940         client->send_configure_change();
941         return 1;
942 }
943
944 TitleStrokeW::TitleStrokeW(TitleMain *client,
945         TitleWindow *window,
946         int x,
947         int y)
948  : BC_TumbleTextBox(window,
949         (float)client->config.stroke_width,
950         (float)-2048,
951         (float)2048,
952         x,
953         y,
954         60)
955 {
956         this->client = client;
957         this->window = window;
958 }
959 int TitleStrokeW::handle_event()
960 {
961         client->config.stroke_width = atof(get_text());
962         client->send_configure_change();
963         return 1;
964 }
965
966
967 TitleSpeed::TitleSpeed(TitleMain *client, TitleWindow *window, int x, int y)
968  : BC_TumbleTextBox(window,
969         (float)client->config.pixels_per_second,
970         (float)0,
971         (float)1000,
972         x,
973         y,
974         70)
975 {
976         this->client = client;
977 }
978
979
980 int TitleSpeed::handle_event()
981 {
982         client->config.pixels_per_second = atof(get_text());
983         client->send_configure_change();
984         return 1;
985 }
986
987
988
989
990
991
992
993 TitleLeft::TitleLeft(TitleMain *client, TitleWindow *window, int x, int y)
994  : BC_Radial(x, y, client->config.hjustification == JUSTIFY_LEFT, _("Left"))
995 {
996         this->client = client;
997         this->window = window;
998 }
999 int TitleLeft::handle_event()
1000 {
1001         client->config.hjustification = JUSTIFY_LEFT;
1002         window->update_justification();
1003         client->send_configure_change();
1004         return 1;
1005 }
1006
1007 TitleCenter::TitleCenter(TitleMain *client, TitleWindow *window, int x, int y)
1008  : BC_Radial(x, y, client->config.hjustification == JUSTIFY_CENTER, _("Center"))
1009 {
1010         this->client = client;
1011         this->window = window;
1012 }
1013 int TitleCenter::handle_event()
1014 {
1015         client->config.hjustification = JUSTIFY_CENTER;
1016         window->update_justification();
1017         client->send_configure_change();
1018         return 1;
1019 }
1020
1021 TitleRight::TitleRight(TitleMain *client, TitleWindow *window, int x, int y)
1022  : BC_Radial(x, y, client->config.hjustification == JUSTIFY_RIGHT, _("Right"))
1023 {
1024         this->client = client;
1025         this->window = window;
1026 }
1027 int TitleRight::handle_event()
1028 {
1029         client->config.hjustification = JUSTIFY_RIGHT;
1030         window->update_justification();
1031         client->send_configure_change();
1032         return 1;
1033 }
1034
1035
1036
1037 TitleTop::TitleTop(TitleMain *client, TitleWindow *window, int x, int y)
1038  : BC_Radial(x, y, client->config.vjustification == JUSTIFY_TOP, _("Top"))
1039 {
1040         this->client = client;
1041         this->window = window;
1042 }
1043 int TitleTop::handle_event()
1044 {
1045         client->config.vjustification = JUSTIFY_TOP;
1046         window->update_justification();
1047         client->send_configure_change();
1048         return 1;
1049 }
1050
1051 TitleMid::TitleMid(TitleMain *client, TitleWindow *window, int x, int y)
1052  : BC_Radial(x, y, client->config.vjustification == JUSTIFY_MID, _("Mid"))
1053 {
1054         this->client = client;
1055         this->window = window;
1056 }
1057 int TitleMid::handle_event()
1058 {
1059         client->config.vjustification = JUSTIFY_MID;
1060         window->update_justification();
1061         client->send_configure_change();
1062         return 1;
1063 }
1064
1065 TitleBottom::TitleBottom(TitleMain *client, TitleWindow *window, int x, int y)
1066  : BC_Radial(x, y, client->config.vjustification == JUSTIFY_BOTTOM, _("Bottom"))
1067 {
1068         this->client = client;
1069         this->window = window;
1070 }
1071 int TitleBottom::handle_event()
1072 {
1073         client->config.vjustification = JUSTIFY_BOTTOM;
1074         window->update_justification();
1075         client->send_configure_change();
1076         return 1;
1077 }
1078
1079
1080
1081 TitleColorThread::TitleColorThread(TitleMain *client, TitleWindow *window, int is_outline)
1082  : ColorThread(1)
1083 {
1084         this->client = client;
1085         this->window = window;
1086         this->is_outline = is_outline;
1087 }
1088
1089 int TitleColorThread::handle_new_color(int output, int alpha)
1090 {
1091         if(is_outline)
1092         {
1093                 client->config.outline_color = output;
1094                 client->config.outline_alpha = alpha;
1095         }
1096         else
1097         {
1098                 client->config.color = output;
1099                 client->config.alpha = alpha;
1100         }
1101
1102         window->lock_window("TitleColorThread::handle_new_color");
1103         window->update_color();
1104         window->flush();
1105         window->unlock_window();
1106
1107         client->send_configure_change();
1108
1109
1110         return 1;
1111 }
1112 TitleColorStrokeThread::TitleColorStrokeThread(TitleMain *client, TitleWindow *window)
1113  : ColorThread()
1114 {
1115         this->client = client;
1116         this->window = window;
1117 }
1118
1119 int TitleColorStrokeThread::handle_event(int output)
1120 {
1121         client->config.color_stroke = output;
1122         window->update_color();
1123         window->flush();
1124         client->send_configure_change();
1125         return 1;
1126 }