/[svn]/gigedit/trunk/src/gigedit/regionchooser.cpp
ViewVC logotype

Contents of /gigedit/trunk/src/gigedit/regionchooser.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1339 - (show annotations) (download)
Mon Sep 10 19:56:26 2007 UTC (16 years, 6 months ago) by schoenebeck
File size: 25165 byte(s)
* bugfix: signals triggered before and after sensible modifications didn't
  ever make it to the outer world (i.e. to LinuxSampler)

1 /*
2 * Copyright (C) 2006, 2007 Andreas Persson
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2, or (at
7 * your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with program; see the file COPYING. If not, write to the Free
16 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
17 * 02110-1301 USA.
18 */
19
20 #include "regionchooser.h"
21 #include <gdkmm/cursor.h>
22 #include <gtkmm/stock.h>
23 #include <gtkmm/spinbutton.h>
24 #include <gtkmm/dialog.h>
25 #include <libintl.h>
26 #include <math.h>
27
28 #define _(String) gettext(String)
29
30 RegionChooser::RegionChooser()
31 {
32 Glib::RefPtr<Gdk::Colormap> colormap = get_default_colormap();
33
34 red = Gdk::Color("#8070ff");
35 grey1 = Gdk::Color("#b0b0b0");
36
37 colormap->alloc_color(red);
38 colormap->alloc_color(grey1);
39 instrument = 0;
40 region = 0;
41 resize.active = false;
42 move.active = false;
43 cursor_is_resize = false;
44 h1 = 20;
45 width = 800;
46
47 actionGroup = Gtk::ActionGroup::create();
48 actionGroup->add(Gtk::Action::create("Properties",
49 Gtk::Stock::PROPERTIES),
50 sigc::mem_fun(*this,
51 &RegionChooser::show_region_properties));
52 actionGroup->add(Gtk::Action::create("Remove", Gtk::Stock::REMOVE),
53 sigc::mem_fun(*this, &RegionChooser::delete_region));
54 actionGroup->add(Gtk::Action::create("Add", Gtk::Stock::ADD),
55 sigc::mem_fun(*this, &RegionChooser::add_region));
56 actionGroup->add(Gtk::Action::create("Dimensions", _("Dimensions...")),
57 sigc::mem_fun(*this, &RegionChooser::manage_dimensions));
58
59 uiManager = Gtk::UIManager::create();
60 uiManager->insert_action_group(actionGroup);
61 Glib::ustring ui_info =
62 "<ui>"
63 " <popup name='PopupMenuInsideRegion'>"
64 " <menuitem action='Properties'/>"
65 " <menuitem action='Dimensions'/>"
66 " <menuitem action='Remove'/>"
67 " </popup>"
68 " <popup name='PopupMenuOutsideRegion'>"
69 " <menuitem action='Add'/>"
70 " </popup>"
71 "</ui>";
72 uiManager->add_ui_from_string(ui_info);
73
74 popup_menu_inside_region = dynamic_cast<Gtk::Menu*>(
75 uiManager->get_widget("/PopupMenuInsideRegion"));
76 popup_menu_outside_region = dynamic_cast<Gtk::Menu*>(
77 uiManager->get_widget("/PopupMenuOutsideRegion"));
78
79 add_events(Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK |
80 Gdk::POINTER_MOTION_MASK | Gdk::POINTER_MOTION_HINT_MASK);
81
82 dimensionManager.region_to_be_changed_signal.connect(
83 region_to_be_changed_signal.make_slot()
84 );
85 dimensionManager.region_changed_signal.connect(
86 region_changed_signal.make_slot()
87 );
88 dimensionManager.region_changed_signal.connect(
89 sigc::hide(
90 sigc::mem_fun(*this, &RegionChooser::on_dimension_manager_changed)
91 )
92 );
93 }
94
95 RegionChooser::~RegionChooser()
96 {
97 }
98
99 void RegionChooser::on_realize()
100 {
101 // We need to call the base on_realize()
102 Gtk::DrawingArea::on_realize();
103
104 // Now we can allocate any additional resources we need
105 Glib::RefPtr<Gdk::Window> window = get_window();
106 gc = Gdk::GC::create(window);
107 window->clear();
108 }
109
110 bool RegionChooser::on_expose_event(GdkEventExpose* event)
111 {
112 Glib::RefPtr<Gdk::Window> window = get_window();
113 window->clear();
114 const int h = 40;
115 const int w = width - 1;
116 const int bh = int(h * 0.55);
117
118 Glib::RefPtr<const Gdk::GC> black = get_style()->get_black_gc();
119 Glib::RefPtr<const Gdk::GC> white = get_style()->get_white_gc();
120
121 Glib::RefPtr<Pango::Context> context = get_pango_context();
122 Glib::RefPtr<Pango::Layout> layout = Pango::Layout::create(context);
123
124 window->draw_rectangle(black, false, 0, h1, w, h - 1);
125 gc->set_foreground(grey1);
126 int x1 = int(w * 20.5 / 128.0 + 0.5);
127 int x2 = int(w * 109.5 / 128.0 + 0.5);
128 window->draw_rectangle(gc, true, 1, h1 + 1,
129 x1 - 1, h - 2);
130 window->draw_rectangle(white, true, x1 + 1, h1 + 1, x2 - x1 - 1, h - 2);
131 window->draw_rectangle(gc, true, x2 + 1, h1 + 1,
132 w - x2 - 1, h - 2);
133 int octave = -1;
134 for (int i = 0 ; i < 128 ; i++) {
135 int note = (i + 3) % 12;
136 int x = int(w * i / 128.0 + 0.5);
137
138 if (note == 1 || note == 4 || note == 6 || note == 9 || note == 11) {
139 int x2 = int(w * (i + 0.5) / 128.0 + 0.5);
140 window->draw_line(black, x2, h1 + bh, x2, h1 + h);
141
142 int x3 = int(w * (i + 1) / 128.0 + 0.5);
143 window->draw_rectangle(black, true, x, h1 + 1, x3 - x + 1, bh);
144 } else if (note == 3 || note == 8) {
145 window->draw_line(black, x, h1 + 1, x, h1 + h);
146 }
147 if (note == 3) {
148 char buf[30];
149 sprintf(buf, "<span size=\"x-small\">%d</span>", octave);
150 layout->set_markup(buf);
151 Pango::Rectangle rectangle = layout->get_logical_extents();
152 double text_w = double(rectangle.get_width()) / Pango::SCALE;
153 double text_h = double(rectangle.get_height()) / Pango::SCALE;
154 double x2 = w * (i + 0.75) / 128.0;
155 window->draw_layout(black, int(x2 - text_w / 2 + 1),
156 int(h1 + h - text_h + 0.5), layout);
157 octave++;
158 }
159 }
160
161 if (instrument) {
162 int i = 0;
163 gig::Region *next_region;
164 int x3 = -1;
165 for (gig::Region *r = instrument->GetFirstRegion() ;
166 r ;
167 r = next_region) {
168
169 if (x3 < 0) x3 = int(w * (r->KeyRange.low) / 128.0 + 0.5);
170 next_region = instrument->GetNextRegion();
171 if (!next_region || r->KeyRange.high + 1 != next_region->KeyRange.low) {
172 int x2 = int(w * (r->KeyRange.high + 1) / 128.0 + 0.5);
173 window->draw_line(black, x3, 0, x2, 0);
174 window->draw_line(black, x3, h1 - 1, x2, h1 - 1);
175 window->draw_line(black, x2, 1, x2, h1 - 2);
176 window->draw_rectangle(white, true, x3 + 1, 1, x2 - x3 - 1, h1 - 2);
177 x3 = -1;
178 }
179 i++;
180 }
181
182 for (gig::Region *r = instrument->GetFirstRegion() ;
183 r ;
184 r = instrument->GetNextRegion()) {
185 int x = int(w * (r->KeyRange.low) / 128.0 + 0.5);
186 window->draw_line(black, x, 1, x, h1 - 2);
187 }
188
189 if (region) {
190 int x1 = int(w * (region->KeyRange.low) / 128.0 + 0.5);
191 int x2 = int(w * (region->KeyRange.high + 1) / 128.0 + 0.5);
192 gc->set_foreground(red);
193 window->draw_rectangle(gc, true, x1 + 1, 1, x2 - x1 - 1, h1 - 2);
194 }
195 }
196 return true;
197 }
198
199
200 void RegionChooser::on_size_request(GtkRequisition* requisition)
201 {
202 *requisition = GtkRequisition();
203 requisition->height = 40 + 20;
204 requisition->width = 500;
205 }
206
207
208 // not used
209 void RegionChooser::draw_region(int from, int to, const Gdk::Color& color)
210 {
211 const int h = 40;
212 const int w = width;
213 const int bh = int(h * 0.55);
214
215 Glib::RefPtr<Gdk::Window> window = get_window();
216 gc->set_foreground(color);
217
218 for (int i = from ; i < to ; i++) {
219 int note = (i + 3) % 12;
220 int x = int(w * i / 128.0 + 0.5) + 1;
221 int x2 = int(w * (i + 1.5) / 128.0 + 0.5);
222 int x3 = int(w * (i + 1) / 128.0 + 0.5);
223 int x4 = int(w * (i - 0.5) / 128 + 0.5) + 1;
224 int w1 = x3 - x;
225 switch (note) {
226 case 0: case 5: case 10:
227 window->draw_rectangle(gc, true, x, h1 + 1, w1, bh);
228 window->draw_rectangle(gc, true, x4, h1 + bh + 1, x2 - x4, h - bh - 2);
229 break;
230 case 2: case 7:
231 window->draw_rectangle(gc, true, x, h1 + 1, w1, bh);
232 window->draw_rectangle(gc, true, x4, h1 + bh + 1, x3 - x4, h - bh - 2);
233 break;
234 case 3: case 8:
235 window->draw_rectangle(gc, true, x, h1 + 1, w1, bh);
236 window->draw_rectangle(gc, true, x, h1 + bh + 1, x2 - x, h - bh - 2);
237 break;
238 default:
239 window->draw_rectangle(gc, true, x, h1 + 1, w1, bh - 1);
240 break;
241 }
242 }
243 }
244
245 void RegionChooser::set_instrument(gig::Instrument* instrument)
246 {
247 this->instrument = instrument;
248 region = instrument ? instrument->GetFirstRegion() : 0;
249 queue_draw();
250 region_selected();
251 }
252
253 bool RegionChooser::on_button_release_event(GdkEventButton* event)
254 {
255 if (resize.active) {
256 get_window()->pointer_ungrab(event->time);
257 resize.active = false;
258
259 if (resize.mode == resize.moving_high_limit) {
260 if (resize.region->KeyRange.high != resize.pos - 1) {
261 instrument_struct_to_be_changed_signal.emit(instrument);
262 resize.region->SetKeyRange(
263 resize.region->KeyRange.low, // low
264 resize.pos - 1 // high
265 );
266 instrument_changed.emit();
267 instrument_struct_changed_signal.emit(instrument);
268 }
269 } else if (resize.mode == resize.moving_low_limit) {
270 if (resize.region->KeyRange.low != resize.pos) {
271 instrument_struct_to_be_changed_signal.emit(instrument);
272 resize.region->SetKeyRange(
273 resize.pos, // low
274 resize.region->KeyRange.high // high
275 );
276 instrument_changed.emit();
277 instrument_struct_changed_signal.emit(instrument);
278 }
279 }
280
281 if (!is_in_resize_zone(event->x, event->y) && cursor_is_resize) {
282 get_window()->set_cursor();
283 cursor_is_resize = false;
284 }
285 } else if (move.active) {
286 get_window()->pointer_ungrab(event->time);
287 move.active = false;
288
289 if (move.pos) {
290 instrument_struct_to_be_changed_signal.emit(instrument);
291 region->SetKeyRange(
292 region->KeyRange.low + move.pos,
293 region->KeyRange.high + move.pos
294 );
295 instrument_struct_changed_signal.emit(instrument);
296 }
297
298 if (is_in_resize_zone(event->x, event->y)) {
299 get_window()->set_cursor(Gdk::Cursor(Gdk::SB_H_DOUBLE_ARROW));
300 cursor_is_resize = true;
301 }
302 }
303 return true;
304 }
305
306 bool RegionChooser::on_button_press_event(GdkEventButton* event)
307 {
308 if (!instrument) return true;
309
310 int k = int(event->x / (width - 1) * 128.0);
311
312 if (event->type == GDK_BUTTON_PRESS && event->button == 3) {
313 gig::Region* r = get_region(k);
314 if (r) {
315 region = r;
316 queue_draw();
317 region_selected();
318 popup_menu_inside_region->popup(event->button, event->time);
319 } else {
320 new_region_pos = k;
321 popup_menu_outside_region->popup(event->button, event->time);
322 }
323 } else {
324 if (is_in_resize_zone(event->x, event->y)) {
325 get_window()->pointer_grab(false,
326 Gdk::BUTTON_RELEASE_MASK |
327 Gdk::POINTER_MOTION_MASK |
328 Gdk::POINTER_MOTION_HINT_MASK,
329 Gdk::Cursor(Gdk::SB_H_DOUBLE_ARROW), event->time);
330 resize.active = true;
331 } else {
332 gig::Region* r = get_region(k);
333 if (r) {
334 region = r;
335 queue_draw();
336 region_selected();
337
338 get_window()->pointer_grab(false,
339 Gdk::BUTTON_RELEASE_MASK |
340 Gdk::POINTER_MOTION_MASK |
341 Gdk::POINTER_MOTION_HINT_MASK,
342 Gdk::Cursor(Gdk::FLEUR), event->time);
343 move.active = true;
344 move.from_x = event->x;
345 move.pos = 0;
346 }
347 }
348 }
349 return true;
350 }
351
352 gig::Region* RegionChooser::get_region(int key)
353 {
354 gig::Region* prev_region = 0;
355 gig::Region* next_region;
356 for (gig::Region *r = instrument->GetFirstRegion() ; r ;
357 r = next_region) {
358 next_region = instrument->GetNextRegion();
359
360 if (key < r->KeyRange.low) return 0;
361 if (key <= r->KeyRange.high) {
362 move.touch_left = prev_region && prev_region->KeyRange.high + 1 == r->KeyRange.low;
363 move.touch_right = next_region && r->KeyRange.high + 1 == next_region->KeyRange.low;
364 return r;
365 }
366 prev_region = r;
367 }
368 return 0;
369 }
370
371 void RegionChooser::motion_resize_region(int x, int y)
372 {
373 const int w = width - 1;
374 Glib::RefPtr<Gdk::Window> window = get_window();
375
376 int k = int(double(x) / w * 128.0 + 0.5);
377
378 if (k < resize.min) k = resize.min;
379 else if (k > resize.max) k = resize.max;
380
381 if (k != resize.pos) {
382 if (resize.mode == resize.undecided) {
383 if (k < resize.pos) {
384 // edit high limit of prev_region
385 resize.max = resize.region->KeyRange.low;
386 resize.region = resize.prev_region;
387 resize.mode = resize.moving_high_limit;
388 } else {
389 // edit low limit of region
390 resize.min = resize.prev_region->KeyRange.high + 1;
391 resize.mode = resize.moving_low_limit;
392 }
393 }
394 Glib::RefPtr<const Gdk::GC> black = get_style()->get_black_gc();
395 Glib::RefPtr<const Gdk::GC> white = get_style()->get_white_gc();
396 if (region == resize.region) {
397 gc->set_foreground(red);
398 white = gc;
399 }
400 Glib::RefPtr<const Gdk::GC> bg = get_style()->get_bg_gc(Gtk::STATE_NORMAL);
401 int prevx = int(w * resize.pos / 128.0 + 0.5);
402 x = int(w * k / 128.0 + 0.5);
403
404 if (resize.mode == resize.moving_high_limit) {
405 if (k > resize.pos) {
406 window->draw_rectangle(white, true, prevx, 1, x - prevx, h1 - 2);
407 window->draw_line(black, prevx, 0, x, 0);
408 window->draw_line(black, prevx, h1 - 1, x, h1 - 1);
409 } else {
410 int xx = ((resize.pos == resize.max && resize.max != 128) ? 1 : 0);
411 window->draw_rectangle(bg, true, x + 1, 0, prevx - x - xx, h1);
412 }
413 } else {
414 if (k < resize.pos) {
415 window->draw_rectangle(white, true, x + 1, 1, prevx - x, h1 - 2);
416 window->draw_line(black, x, 0, prevx, 0);
417 window->draw_line(black, x, h1 - 1, prevx, h1 - 1);
418 } else {
419 int xx = ((resize.pos == resize.min && resize.min != 0) ? 1 : 0);
420 window->draw_rectangle(bg, true, prevx + xx, 0, x - prevx - xx, h1);
421 }
422 }
423 window->draw_line(black, x, 1, x, h1 - 2);
424 resize.pos = k;
425 }
426 }
427
428 void RegionChooser::motion_move_region(int x, int y)
429 {
430 const int w = width - 1;
431 Glib::RefPtr<Gdk::Window> window = get_window();
432
433 int k = int(double(x - move.from_x) / w * 128.0 + 0.5);
434 if (k == move.pos) return;
435 int new_k;
436 bool new_touch_left;
437 bool new_touch_right;
438 int a = 0;
439 if (k > move.pos) {
440 for (gig::Region* r = instrument->GetFirstRegion() ; ;
441 r = instrument->GetNextRegion()) {
442 if (r != region) {
443 int b = r ? r->KeyRange.low : 128;
444
445 // gap: from a to b (not inclusive b)
446
447 if (region->KeyRange.high + move.pos >= b) {
448 // not found the current gap yet, just continue
449 } else {
450
451 if (a > region->KeyRange.low + k) {
452 // this gap is too far to the right, break
453 break;
454 }
455
456 int newhigh = std::min(region->KeyRange.high + k, b - 1);
457 int newlo = newhigh - (region->KeyRange.high - region->KeyRange.low);
458
459 if (newlo >= a) {
460 // yes it fits - it's a candidate
461 new_k = newlo - region->KeyRange.low;
462 new_touch_left = a > 0 && a == newlo;
463 new_touch_right = b < 128 && newhigh + 1 == b;
464 }
465 }
466 if (!r) break;
467 a = r->KeyRange.high + 1;
468 }
469 }
470 } else {
471 for (gig::Region* r = instrument->GetFirstRegion() ; ;
472 r = instrument->GetNextRegion()) {
473 if (r != region) {
474 int b = r ? r->KeyRange.low : 128;
475
476 // gap from a to b (not inclusive b)
477
478 if (region->KeyRange.high + k >= b) {
479 // not found the current gap yet, just continue
480 } else {
481
482 if (a > region->KeyRange.low + move.pos) {
483 // this gap is too far to the right, break
484 break;
485 }
486
487 int newlo = std::max(region->KeyRange.low + k, a);
488 int newhigh = newlo + (region->KeyRange.high - region->KeyRange.low);
489
490 if (newhigh < b) {
491 // yes it fits - break as the first one is the best
492 new_k = newlo - region->KeyRange.low;
493 new_touch_left = a > 0 && a == newlo;
494 new_touch_right = b < 128 && newhigh + 1 == b;
495 break;
496 }
497 }
498 if (!r) break;
499 a = r->KeyRange.high + 1;
500 }
501 }
502 }
503 k = new_k;
504 if (k == move.pos) return;
505
506 Glib::RefPtr<const Gdk::GC> bg = get_style()->get_bg_gc(Gtk::STATE_NORMAL);
507 int prevx = int(w * (move.pos + region->KeyRange.low) / 128.0 + 0.5);
508 x = int(w * (k + region->KeyRange.low) / 128.0 + 0.5);
509 int prevx2 = int(w * (move.pos + region->KeyRange.high + 1) / 128.0 + 0.5);
510 int x2 = int(w * (k + region->KeyRange.high + 1) / 128.0 + 0.5);
511 Glib::RefPtr<const Gdk::GC> black = get_style()->get_black_gc();
512 gc->set_foreground(red);
513
514 if (!new_touch_left) window->draw_line(black, x, 1, x, h1 - 2);
515 if (!new_touch_right) window->draw_line(black, x2, 1, x2, h1 - 2);
516
517 if (k > move.pos) {
518 window->draw_rectangle(bg, true, prevx + (move.touch_left ? 1 : 0), 0,
519 std::min(x, prevx2 + 1 - (move.touch_right ? 1 : 0)) -
520 (prevx + (move.touch_left ? 1 : 0)), h1);
521
522 window->draw_line(black, std::max(x, prevx2 + 1), 0, x2, 0);
523 window->draw_line(black, std::max(x, prevx2 + 1), h1 - 1, x2, h1 - 1);
524 window->draw_rectangle(gc, true, std::max(x + 1, prevx2), 1,
525 x2 - std::max(x + 1, prevx2), h1 - 2);
526 } else {
527 window->draw_rectangle(bg, true, std::max(x2 + 1, prevx + (move.touch_left ? 1 : 0)), 0,
528 prevx2 + 1 - (move.touch_right ? 1 : 0) -
529 std::max(x2 + 1, prevx + (move.touch_left ? 1 : 0)), h1);
530
531 window->draw_line(black, x, 0, std::min(x2, prevx - 1), 0);
532 window->draw_line(black, x, h1 - 1, std::min(x2, prevx - 1), h1 - 1);
533
534 window->draw_rectangle(gc, true, x + 1, 1, std::min(x2 - 1, prevx) - x, h1 - 2);
535 }
536
537 move.pos = k;
538 move.touch_left = new_touch_left;
539 move.touch_right = new_touch_right;
540 }
541
542
543 bool RegionChooser::on_motion_notify_event(GdkEventMotion* event)
544 {
545 Glib::RefPtr<Gdk::Window> window = get_window();
546 int x, y;
547 Gdk::ModifierType state = Gdk::ModifierType(0);
548 window->get_pointer(x, y, state);
549
550 if (resize.active) {
551 motion_resize_region(x, y);
552 } else if (move.active) {
553 motion_move_region(x, y);
554 } else {
555 if (is_in_resize_zone(x, y)) {
556 if (!cursor_is_resize) {
557 window->set_cursor(Gdk::Cursor(Gdk::SB_H_DOUBLE_ARROW));
558 cursor_is_resize = true;
559 }
560 } else if (cursor_is_resize) {
561 window->set_cursor();
562 cursor_is_resize = false;
563 }
564 }
565
566 return true;
567 }
568
569 bool RegionChooser::is_in_resize_zone(double x, double y) {
570 const int w = width - 1;
571
572 if (instrument && y >= 0 && y <= h1) {
573 gig::Region* prev_region = 0;
574 gig::Region* next_region;
575 for (gig::Region* r = instrument->GetFirstRegion() ; r ; r = next_region) {
576 next_region = instrument->GetNextRegion();
577
578 int lo = int(w * (r->KeyRange.low) / 128.0 + 0.5);
579 if (x <= lo - 2) break;
580 if (x < lo + 2) {
581 resize.region = r;
582 resize.pos = r->KeyRange.low;
583 resize.max = r->KeyRange.high;
584
585 if (prev_region && prev_region->KeyRange.high + 1 == r->KeyRange.low) {
586 // we don't know yet if it's the high limit of
587 // prev_region or the low limit of r that's going
588 // to be edited
589 resize.mode = resize.undecided;
590 resize.min = prev_region->KeyRange.low + 1;
591 resize.prev_region = prev_region;
592 return true;
593 }
594
595 // edit low limit
596 resize.mode = resize.moving_low_limit;
597 resize.min = prev_region ? prev_region->KeyRange.high + 1 : 0;
598 return true;
599 }
600 if (!next_region || r->KeyRange.high + 1 != next_region->KeyRange.low) {
601 int hi = int(w * (r->KeyRange.high + 1) / 128.0 + 0.5);
602 if (x <= hi - 2) break;
603 if (x < hi + 2) {
604 // edit high limit
605 resize.region = r;
606 resize.pos = r->KeyRange.high + 1;
607 resize.mode = resize.moving_high_limit;
608 resize.min = r->KeyRange.low + 1;
609 resize.max = next_region ? next_region->KeyRange.low : 128;
610 return true;
611 }
612 }
613 prev_region = r;
614 }
615 }
616 return false;
617 }
618
619 sigc::signal<void>& RegionChooser::signal_region_selected()
620 {
621 return region_selected;
622 }
623
624 sigc::signal<void>& RegionChooser::signal_instrument_changed()
625 {
626 return instrument_changed;
627 }
628
629 void RegionChooser::show_region_properties()
630 {
631 if (!region) return;
632 Gtk::Dialog dialog("Region Properties", true /*modal*/);
633 // add "Keygroup" checkbox
634 Gtk::CheckButton checkBoxKeygroup("Member of a Keygroup (Exclusive Group)");
635 checkBoxKeygroup.set_active(region->KeyGroup);
636 dialog.get_vbox()->pack_start(checkBoxKeygroup);
637 checkBoxKeygroup.show();
638 // add "Keygroup" spinbox
639 Gtk::Adjustment adjustment(1, 1, pow(2,32));
640 Gtk::SpinButton spinBox(adjustment);
641 if (region->KeyGroup) spinBox.set_value(region->KeyGroup);
642 dialog.get_vbox()->pack_start(spinBox);
643 spinBox.show();
644 // add OK and CANCEL buttons to the dialog
645 dialog.add_button(Gtk::Stock::OK, 0);
646 dialog.add_button(Gtk::Stock::CANCEL, 1);
647 dialog.show_all_children();
648 if (!dialog.run()) { // OK selected ...
649 region->KeyGroup =
650 (checkBoxKeygroup.get_active()) ? spinBox.get_value_as_int() : 0;
651 }
652 }
653
654 void RegionChooser::add_region()
655 {
656 instrument_struct_to_be_changed_signal.emit(instrument);
657
658 region = instrument->AddRegion();
659 region->SetKeyRange(new_region_pos, new_region_pos);
660
661 instrument_struct_changed_signal.emit(instrument);
662
663 queue_draw();
664 region_selected();
665 instrument_changed();
666 }
667
668 void RegionChooser::delete_region()
669 {
670 instrument_struct_to_be_changed_signal.emit(instrument);
671 instrument->DeleteRegion(region);
672 instrument_struct_changed_signal.emit(instrument);
673
674 region = 0;
675 queue_draw();
676 region_selected();
677 instrument_changed();
678 }
679
680 void RegionChooser::manage_dimensions()
681 {
682 gig::Region* region = get_region();
683 if (!region) return;
684 dimensionManager.show(region);
685 }
686
687 void RegionChooser::on_dimension_manager_changed() {
688 region_selected();
689 instrument_changed();
690 }
691
692 sigc::signal<void, gig::Instrument*>& RegionChooser::signal_instrument_struct_to_be_changed() {
693 return instrument_struct_to_be_changed_signal;
694 }
695
696 sigc::signal<void, gig::Instrument*>& RegionChooser::signal_instrument_struct_changed() {
697 return instrument_struct_changed_signal;
698 }
699
700 sigc::signal<void, gig::Region*>& RegionChooser::signal_region_to_be_changed() {
701 return region_to_be_changed_signal;
702 }
703
704 sigc::signal<void, gig::Region*>& RegionChooser::signal_region_changed_signal() {
705 return region_changed_signal;
706 }

  ViewVC Help
Powered by ViewVC