no longer need ffmpeg patch0 which was for Termux
[goodguy/cinelerra.git] / cinelerra-5.1 / cinelerra / vpatchgui.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 "autoconf.h"
23 #include "automation.h"
24 #include "edl.h"
25 #include "edlsession.h"
26 #include "floatauto.h"
27 #include "floatautos.h"
28 #include "gwindowgui.h"
29 #include "intauto.h"
30 #include "intautos.h"
31 #include "keys.h"
32 #include "language.h"
33 #include "localsession.h"
34 #include "mainsession.h"
35 #include "mainundo.h"
36 #include "mwindow.h"
37 #include "mwindowgui.h"
38 #include "overlayframe.inc"
39 #include "patchbay.h"
40 #include "theme.h"
41 #include "trackcanvas.h"
42 #include "vpatchgui.h"
43 #include "vtrack.h"
44 #include "vwindow.h"
45
46 #include <string.h>
47
48
49 VPatchGUI::VPatchGUI(MWindow *mwindow, PatchBay *patchbay, VTrack *track, int x, int y)
50  : PatchGUI(mwindow, patchbay, track, x, y)
51 {
52         data_type = TRACK_VIDEO;
53         this->vtrack = track;
54         mode = 0;
55         fade = 0;
56 }
57
58 VPatchGUI::~VPatchGUI()
59 {
60         if( fade ) delete fade;
61         if( mode ) delete mode;
62 }
63
64 void VPatchGUI::create_objects()
65 {
66         update(x, y);
67 }
68
69 int VPatchGUI::reposition(int x, int y)
70 {
71         //int x1 = 0;
72         int y1 = PatchGUI::reposition(x, y);
73
74         if( fade )
75                 fade->reposition_window(fade->get_x(), y1+y);
76         y1 += mwindow->theme->fade_h;
77         if( mix )
78                 mix->reposition_window(mix->get_x(), y1+y);
79         if( mode )
80                 mode->reposition_window(mode->get_x(), y1+y);
81         if( nudge )
82                 nudge->reposition_window(nudge->get_x(), y1+y);
83         y1 += mwindow->theme->mode_h;
84         return y1;
85 }
86
87 int VPatchGUI::update(int x, int y)
88 {
89         int h = track->vertical_span(mwindow->theme);
90         int x1 = 0;
91         int y1 = PatchGUI::update(x, y);
92
93         int y2 = y1 + mwindow->theme->fade_h;
94         if( fade ) {
95                 if( h < y2 ) {
96                         delete fade;  fade = 0;
97                 }
98                 else {
99                         FloatAuto *previous = 0, *next = 0;
100                         double unit_position = mwindow->edl->local_session->get_selectionstart(1);
101                         int64_t unit_pos = vtrack->to_units(unit_position, 0);
102                         FloatAutos *ptr = (FloatAutos*)track->automation->autos[AUTOMATION_FADE];
103                         float value = ptr->get_value(unit_pos, PLAY_FORWARD, previous, next);
104                         fade->update(fade->get_w(), value,
105                                      mwindow->edl->local_session->automation_mins[AUTOGROUPTYPE_VIDEO_FADE],
106                                      mwindow->edl->local_session->automation_maxs[AUTOGROUPTYPE_VIDEO_FADE]);
107                 }
108         }
109         else if( h >= y2 ) {
110                 int64_t v = mwindow->get_float_auto(this, AUTOMATION_FADE)->get_value();
111                 patchbay->add_subwindow(fade = new VFadePatch(this, x1+x, y1+y,
112                         patchbay->get_w() - xS(10), v));
113         }
114         y1 = y2;
115
116         y2 = y1 + mwindow->theme->mode_h;
117         if( mode ) {
118                 if( h < y2 ) {
119                         delete mix;    mix = 0;
120                         delete mode;   mode = 0;
121                         delete nudge;  nudge = 0;
122                 }
123                 else {
124                         if( mwindow->session->selected_zwindow >= 0 ) {
125                                 int v = mwindow->mixer_track_active(track);
126                                 mix->update(v);
127                         }
128                         mode->update(mwindow->get_int_auto(this, AUTOMATION_MODE)->value);
129                         nudge->update();
130                 }
131         }
132         else if( h >= y2 ) {
133                 patchbay->add_subwindow(mix = new VMixPatch(mwindow, this, x1+x, y1+y+yS(5)));
134                 x1 += mix->get_w();
135                 patchbay->add_subwindow(mode = new VModePatch(mwindow, this, x1+x, y1+y));
136                 mode->create_objects();
137                 x1 += mode->get_w();
138                 patchbay->add_subwindow(nudge = new NudgePatch(mwindow, this, x1+x, y1+y,
139                         patchbay->get_w() - x1-x - xS(10)));
140         }
141         y1 = y2;
142
143         return y1;
144 }
145
146 VFadePatch::VFadePatch(VPatchGUI *patch, int x, int y, int w, int64_t v)
147  : BC_ISlider(x, y, 0, w, w,
148                 patch->mwindow->edl->local_session->automation_mins[AUTOGROUPTYPE_VIDEO_FADE],
149                 patch->mwindow->edl->local_session->automation_maxs[AUTOGROUPTYPE_VIDEO_FADE],
150                 v)
151 {
152         this->patch = patch;
153 }
154
155 void VPatchGUI::update_faders(float v)
156 {
157         if( fade )
158                 fade->update(v);
159
160         change_source = 1;
161         double position = mwindow->edl->local_session->get_selectionstart(1);
162         Autos *fade_autos = vtrack->automation->autos[AUTOMATION_FADE];
163         int need_undo = !fade_autos->auto_exists_for_editing(position);
164         mwindow->undo->update_undo_before(_("fade"), need_undo ? 0 : this);
165         FloatAuto *current = (FloatAuto*)fade_autos->get_auto_for_editing(position);
166         float change = v - current->get_value(edge);
167         current->bump_value(v, edge, span);
168         if( track->is_ganged() && track->is_armed() )
169                 patchbay->synchronize_faders(change, TRACK_VIDEO, track, edge, span);
170         mwindow->undo->update_undo_after(_("fade"), LOAD_AUTOMATION);
171         change_source = 0;
172
173         mwindow->sync_parameters(CHANGE_PARAMS);
174
175         if( mwindow->edl->session->auto_conf->autos[AUTOMATION_FADE] ) {
176                 mwindow->gui->draw_overlays(1);
177         }
178 }
179
180 int VFadePatch::handle_event()
181 {
182         if( shift_down() ) {
183                 update(100);
184                 set_tooltip(get_caption());
185         }
186         patch->update_faders(get_value());
187         return 1;
188 }
189
190 VKeyFadePatch::VKeyFadePatch(MWindow *mwindow, VPatchGUI *gui,
191                         int bump, int x, int y)
192  : BC_SubWindow(x,y, xS(200),yS(bump ? 50 : 24),
193                 GWindowGUI::auto_colors[AUTOMATION_FADE])
194 {
195         this->mwindow = mwindow;
196         this->gui = gui;
197 }
198 VKeyFadePatch::~VKeyFadePatch()
199 {
200 }
201
202 void VKeyFadePatch::create_objects()
203 {
204         int x = 0, x1 = x, y = 0, dy = 0;
205         FloatAuto *fade_auto = mwindow->get_float_auto(gui, AUTOMATION_FADE);
206         int64_t v = fade_auto->get_value(gui->edge);
207         add_subwindow(vkey_fade_text = new VKeyFadeText(this, x, y, xS(64), v));
208         x += vkey_fade_text->get_w();
209         dy = bmax(dy, vkey_fade_text->get_h());
210         VFrame **lok_images = mwindow->theme->get_image_set("lok");
211         int w1 = get_w() - x - lok_images[0]->get_w();
212         add_subwindow(vkey_fade_slider = new VKeyFadeSlider(this, x, y, w1, v));
213         x += vkey_fade_slider->get_w();
214         dy = bmax(dy, vkey_fade_slider->get_h());
215         add_subwindow(vkey_fade_ok = new VKeyFadeOK(this, x, y, lok_images));
216         dy = bmax(dy, vkey_fade_ok->get_h());
217         if( fade_auto->is_bump() ) {
218                 y += dy;
219                 set_color(get_resources()->get_bg_color());
220                 draw_box(0,y, get_w(),get_h());
221                 add_subwindow(auto_edge = new VKeyPatchAutoEdge(mwindow, this, x1, y));
222                 x1 += auto_edge->get_w() + xS(15);
223                 add_subwindow(auto_span = new VKeyPatchAutoSpan(mwindow, this, x1, y));
224         }
225         draw_3d_border(0,0, get_w(), get_h(), 0);
226         activate();
227         show_window();
228 }
229
230 void VKeyFadePatch::set_edge(int edge)
231 {
232         gui->edge = edge;
233         FloatAuto *fade_auto = mwindow->get_float_auto(gui, AUTOMATION_FADE);
234         int64_t v = fade_auto->get_value(edge);
235         update(v);
236 }
237
238 void VKeyFadePatch::set_span(int span)
239 {
240         gui->span = span;
241 }
242
243 void VKeyFadePatch::update(int64_t v)
244 {
245         vkey_fade_text->update(v);
246         vkey_fade_slider->update(v);
247         gui->update_faders(v);
248 }
249
250 VKeyFadeOK::VKeyFadeOK(VKeyFadePatch *vkey_fade_patch, int x, int y, VFrame **images)
251  : BC_Button(x, y, images)
252 {
253         this->vkey_fade_patch = vkey_fade_patch;
254 }
255
256 int VKeyFadeOK::handle_event()
257 {
258         MWindow *mwindow = vkey_fade_patch->mwindow;
259         mwindow->gui->close_keyvalue_popup();
260         return 1;
261 }
262
263 VKeyFadeText::VKeyFadeText(VKeyFadePatch *vkey_fade_patch, int x, int y, int w, int64_t v)
264  : BC_TextBox(x, y, w, 1, v, 1, MEDIUMFONT)
265 {
266         this->vkey_fade_patch = vkey_fade_patch;
267 }
268
269 int VKeyFadeText::handle_event()
270 {
271         int64_t v = atoi(get_text());
272         vkey_fade_patch->update(v);
273         return get_keypress() != RETURN ? 1 :
274                 vkey_fade_patch->vkey_fade_ok->handle_event();
275 }
276
277 VKeyFadeSlider::VKeyFadeSlider(VKeyFadePatch *vkey_fade_patch,
278         int x, int y, int w, int64_t v)
279  : VFadePatch(vkey_fade_patch->gui, x,y, w, v)
280 {
281         this->vkey_fade_patch = vkey_fade_patch;
282 }
283
284 int VKeyFadeSlider::handle_event()
285 {
286         int64_t v = get_value();
287         vkey_fade_patch->update(v);
288         return 1;
289 }
290
291
292 VModePatch::VModePatch(MWindow *mwindow, VPatchGUI *patch, int x, int y)
293  : BC_PopupMenu(x, y, patch->patchbay->mode_icons[0]->get_w() + xS(20),
294         "", 1, mwindow->theme->get_image_set("mode_popup", 0), 0)
295 {
296         this->mwindow = mwindow;
297         this->patch = patch;
298         this->mode = mwindow->get_int_auto(patch, AUTOMATION_MODE)->value;
299         set_icon(patch->patchbay->mode_to_icon(this->mode));
300         set_tooltip(_("Overlay mode"));
301 // *** CONTEXT_HELP ***
302         context_help_set_keyword("Overlays");
303 }
304
305 VModePatch::VModePatch(MWindow *mwindow, VPatchGUI *patch)
306  : BC_PopupMenu(0, 0, 0, "", 0)
307 {
308         this->mwindow = mwindow;
309         this->patch = patch;
310         this->mode = mwindow->get_int_auto(patch, AUTOMATION_MODE)->value;
311 }
312
313
314 int VModePatch::handle_event()
315 {
316 // Set menu items
317 //      for( int i = 0; i < total_items(); i++ )
318 //      {
319 //              VModePatchItem *item = (VModePatchItem*)get_item(i);
320 //              if( item->mode == mode )
321 //                      item->set_checked(1);
322 //              else
323 //                      item->set_checked(0);
324 //      }
325         update(mode);
326
327 // Set keyframe
328         IntAuto *current;
329         double position = mwindow->edl->local_session->get_selectionstart(1);
330         Autos *mode_autos = patch->vtrack->automation->autos[AUTOMATION_MODE];
331         int need_undo = !mode_autos->auto_exists_for_editing(position);
332         mwindow->undo->update_undo_before(_("mode"), need_undo ? 0 : this);
333         current = (IntAuto*)mode_autos->get_auto_for_editing(position);
334         current->value = mode;
335         mwindow->undo->update_undo_after(_("mode"), LOAD_AUTOMATION);
336         mwindow->sync_parameters(CHANGE_PARAMS);
337
338         if( mwindow->edl->session->auto_conf->autos[AUTOMATION_MODE] ) {
339                 mwindow->gui->draw_overlays(1);
340         }
341         mwindow->session->changes_made = 1;
342         return 1;
343 }
344
345 void VModePatch::create_objects()
346 {
347         VModePatchItem *mode_item;
348         VModePatchSubMenu *submenu;
349         add_item(mode_item = new VModePatchItem(this, mode_to_text(TRANSFER_NORMAL),  TRANSFER_NORMAL));
350         add_item(mode_item = new VModePatchItem(this, _("Arithmetic..."), -1));
351         mode_item->add_submenu(submenu = new VModePatchSubMenu(mode_item));
352         submenu->add_submenuitem(new VModeSubMenuItem(submenu, mode_to_text(TRANSFER_ADDITION), TRANSFER_ADDITION));
353         submenu->add_submenuitem(new VModeSubMenuItem(submenu, mode_to_text(TRANSFER_SUBTRACT), TRANSFER_SUBTRACT));
354         submenu->add_submenuitem(new VModeSubMenuItem(submenu, mode_to_text(TRANSFER_DIVIDE),   TRANSFER_DIVIDE));
355         submenu->add_submenuitem(new VModeSubMenuItem(submenu, mode_to_text(TRANSFER_MULTIPLY), TRANSFER_MULTIPLY));
356         submenu->add_submenuitem(new VModeSubMenuItem(submenu, mode_to_text(TRANSFER_REPLACE),  TRANSFER_REPLACE));
357         add_item(mode_item = new VModePatchItem(this, _("PorterDuff..."), -1));
358         mode_item->add_submenu(submenu = new VModePatchSubMenu(mode_item));
359         submenu->add_submenuitem(new VModeSubMenuItem(submenu, mode_to_text(TRANSFER_DST),      TRANSFER_DST));
360         submenu->add_submenuitem(new VModeSubMenuItem(submenu, mode_to_text(TRANSFER_DST_ATOP), TRANSFER_DST_ATOP));
361         submenu->add_submenuitem(new VModeSubMenuItem(submenu, mode_to_text(TRANSFER_DST_IN),   TRANSFER_DST_IN));
362         submenu->add_submenuitem(new VModeSubMenuItem(submenu, mode_to_text(TRANSFER_DST_OUT),  TRANSFER_DST_OUT));
363         submenu->add_submenuitem(new VModeSubMenuItem(submenu, mode_to_text(TRANSFER_DST_OVER), TRANSFER_DST_OVER));
364         submenu->add_submenuitem(new VModeSubMenuItem(submenu, mode_to_text(TRANSFER_SRC),      TRANSFER_SRC));
365         submenu->add_submenuitem(new VModeSubMenuItem(submenu, mode_to_text(TRANSFER_SRC_ATOP), TRANSFER_SRC_ATOP));
366         submenu->add_submenuitem(new VModeSubMenuItem(submenu, mode_to_text(TRANSFER_SRC_IN),   TRANSFER_SRC_IN));
367         submenu->add_submenuitem(new VModeSubMenuItem(submenu, mode_to_text(TRANSFER_SRC_OUT),  TRANSFER_SRC_OUT));
368         submenu->add_submenuitem(new VModeSubMenuItem(submenu, mode_to_text(TRANSFER_SRC_OVER), TRANSFER_SRC_OVER));
369         add_item(mode_item = new VModePatchItem(this, _("Logical..."), -1));
370         mode_item->add_submenu(submenu = new VModePatchSubMenu(mode_item));
371         submenu->add_submenuitem(new VModeSubMenuItem(submenu, mode_to_text(TRANSFER_MIN),      TRANSFER_MIN));
372         submenu->add_submenuitem(new VModeSubMenuItem(submenu, mode_to_text(TRANSFER_MAX),      TRANSFER_MAX));
373         submenu->add_submenuitem(new VModeSubMenuItem(submenu, mode_to_text(TRANSFER_DARKEN),   TRANSFER_DARKEN));
374         submenu->add_submenuitem(new VModeSubMenuItem(submenu, mode_to_text(TRANSFER_LIGHTEN),  TRANSFER_LIGHTEN));
375         submenu->add_submenuitem(new VModeSubMenuItem(submenu, mode_to_text(TRANSFER_AND),      TRANSFER_AND));
376         submenu->add_submenuitem(new VModeSubMenuItem(submenu, mode_to_text(TRANSFER_OR),       TRANSFER_OR));
377         submenu->add_submenuitem(new VModeSubMenuItem(submenu, mode_to_text(TRANSFER_XOR),      TRANSFER_XOR));
378         add_item(mode_item = new VModePatchItem(this, _("Graphic Art..."), -1));
379         mode_item->add_submenu(submenu = new VModePatchSubMenu(mode_item));
380         submenu->add_submenuitem(new VModeSubMenuItem(submenu, mode_to_text(TRANSFER_OVERLAY),  TRANSFER_OVERLAY));
381         submenu->add_submenuitem(new VModeSubMenuItem(submenu, mode_to_text(TRANSFER_SCREEN),   TRANSFER_SCREEN));
382         submenu->add_submenuitem(new VModeSubMenuItem(submenu, mode_to_text(TRANSFER_BURN),     TRANSFER_BURN));
383         submenu->add_submenuitem(new VModeSubMenuItem(submenu, mode_to_text(TRANSFER_DODGE),    TRANSFER_DODGE));
384         submenu->add_submenuitem(new VModeSubMenuItem(submenu, mode_to_text(TRANSFER_DIFFERENCE),TRANSFER_DIFFERENCE));
385         submenu->add_submenuitem(new VModeSubMenuItem(submenu, mode_to_text(TRANSFER_HARDLIGHT),TRANSFER_HARDLIGHT));
386         submenu->add_submenuitem(new VModeSubMenuItem(submenu, mode_to_text(TRANSFER_SOFTLIGHT),TRANSFER_SOFTLIGHT));
387 }
388
389 void VModePatch::update(int mode)
390 {
391         set_icon(patch->patchbay->mode_to_icon(mode));
392         for( int i = 0; i < total_items(); i++ ) {
393                 VModePatchItem *item = (VModePatchItem*)get_item(i);
394                 item->set_checked(item->mode == mode);
395                 VModePatchSubMenu *submenu = (VModePatchSubMenu *)item->get_submenu();
396                 if( !submenu ) continue;
397                 int n = submenu->total_items();
398                 for( int j=0; j<n; ++j ) {
399                         VModePatchItem *subitem = (VModePatchItem*)submenu->get_item(j);
400                         subitem->set_checked(subitem->mode == mode);
401                 }
402         }
403 }
404
405
406 const char* VModePatch::mode_to_text(int mode)
407 {
408         switch( mode ) {
409         case TRANSFER_NORMAL:           return _("Normal");
410         case TRANSFER_ADDITION:         return _("Addition");
411         case TRANSFER_SUBTRACT:         return _("Subtract");
412         case TRANSFER_MULTIPLY:         return _("Multiply");
413         case TRANSFER_DIVIDE:           return _("Divide");
414         case TRANSFER_REPLACE:          return _("Replace");
415         case TRANSFER_MAX:              return _("Max");
416         case TRANSFER_MIN:              return _("Min");
417         case TRANSFER_DARKEN:           return _("Darken");
418         case TRANSFER_LIGHTEN:          return _("Lighten");
419         case TRANSFER_DST:              return _("Dst");
420         case TRANSFER_DST_ATOP:         return _("DstAtop");
421         case TRANSFER_DST_IN:           return _("DstIn");
422         case TRANSFER_DST_OUT:          return _("DstOut");
423         case TRANSFER_DST_OVER:         return _("DstOver");
424         case TRANSFER_SRC:              return _("Src");
425         case TRANSFER_SRC_ATOP:         return _("SrcAtop");
426         case TRANSFER_SRC_IN:           return _("SrcIn");
427         case TRANSFER_SRC_OUT:          return _("SrcOut");
428         case TRANSFER_SRC_OVER:         return _("SrcOver");
429         case TRANSFER_AND:              return _("AND");
430         case TRANSFER_OR:               return _("OR");
431         case TRANSFER_XOR:              return _("XOR");
432         case TRANSFER_OVERLAY:          return _("Overlay");
433         case TRANSFER_SCREEN:           return _("Screen");
434         case TRANSFER_BURN:             return _("Burn");
435         case TRANSFER_DODGE:            return _("Dodge");
436         case TRANSFER_HARDLIGHT:        return _("Hardlight");
437         case TRANSFER_SOFTLIGHT:        return _("Softlight");
438         case TRANSFER_DIFFERENCE:       return _("Difference");
439         }
440         return _("Normal");
441 }
442
443
444
445 VModePatchItem::VModePatchItem(VModePatch *popup, const char *text, int mode)
446  : BC_MenuItem(text)
447 {
448         this->popup = popup;
449         this->mode = mode;
450         if( this->mode == popup->mode ) set_checked(1);
451 }
452
453 int VModePatchItem::handle_event()
454 {
455         if( mode >= 0 ) {
456                 popup->mode = mode;
457 //              popup->set_icon(popup->patch->patchbay->mode_to_icon(mode));
458                 popup->handle_event();
459         }
460         return 1;
461 }
462
463 VModePatchSubMenu::VModePatchSubMenu(VModePatchItem *mode_item)
464 {
465         this->mode_item = mode_item;
466 }
467 VModePatchSubMenu::~VModePatchSubMenu()
468 {
469 }
470
471 VModeSubMenuItem::VModeSubMenuItem(VModePatchSubMenu *submenu, const char *text, int mode)
472  : BC_MenuItem(text)
473 {
474         this->submenu = submenu;
475         this->mode = mode;
476         VModePatch *popup = submenu->mode_item->popup;
477         if( this->mode == popup->mode ) set_checked(1);
478 }
479 VModeSubMenuItem::~VModeSubMenuItem()
480 {
481 }
482
483 int VModeSubMenuItem::handle_event()
484 {
485         VModePatch *popup = submenu->mode_item->popup;
486         popup->mode = mode;
487 //      popup->set_icon(popup->patch->patchbay->mode_to_icon(mode));
488         popup->handle_event();
489         return 1;
490 }
491
492
493 VKeyModePatch::VKeyModePatch(MWindow *mwindow, VPatchGUI *patch)
494  : VModePatch(mwindow, patch)
495 {
496 }
497
498 int VKeyModePatch::handle_event()
499 {
500         int ret = VModePatch::handle_event();
501         VModePatch *mode = patch->mode;
502         if( mode )
503                 mode->update(this->mode);
504         return ret;
505 }
506
507
508 VMixPatch::VMixPatch(MWindow *mwindow, VPatchGUI *patch, int x, int y)
509  : MixPatch(mwindow, patch, x, y)
510 {
511         set_tooltip(_("Mixer"));
512 // *** CONTEXT_HELP ***
513         context_help_set_keyword("Recover Mixer Windows");
514 }
515
516 VMixPatch::~VMixPatch()
517 {
518 }
519
520 VKeyPatchAutoEdge::VKeyPatchAutoEdge(MWindow *mwindow,
521                 VKeyFadePatch *patch, int x, int y)
522  : BC_Toggle(x, y, mwindow->theme->get_image_set("bump_edge"),
523                 patch->gui->edge,_("Edge"))
524 {
525         this->mwindow = mwindow;
526         this->patch = patch;
527         set_tooltip(_("Bump uses left edge"));
528 }
529
530 int VKeyPatchAutoEdge::handle_event()
531 {
532         patch->set_edge(get_value());
533         return 1;
534 }
535
536 VKeyPatchAutoSpan::VKeyPatchAutoSpan(MWindow *mwindow,
537                 VKeyFadePatch *patch, int x, int y)
538  : BC_Toggle(x, y, mwindow->theme->get_image_set("bump_span"),
539                 patch->gui->span,_("Span"))
540 {
541         this->mwindow = mwindow;
542         this->patch = patch;
543         set_tooltip(_("Bump spans to next"));
544 }
545
546 int VKeyPatchAutoSpan::handle_event()
547 {
548         patch->set_span(get_value());
549         return 1;
550 }
551