/[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 1322 - (show annotations) (download)
Tue Sep 4 11:04:56 2007 UTC (16 years, 7 months ago) by schoenebeck
File size: 25389 byte(s)
* as counterpart to latest LS commit: added experimental support to
  synchronize gigedit with LinuxSampler to avoid race conditions / crash
  while modifying data structures and playing the instrument with LS at
  the same time
* packaging fixes: don't use a hard coded path to install the LS plugin
  DLL, trying to substitute the given LS plugin directory by the
  '${libdir}' automake variable (mandatory i.e. for Gentoo ebuild) and
  include plugin/linuxsamplerplugin.h into the release tarball
  ('make dist')
* updated German translation (po/de.po)

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 resize.region->KeyRange.high = resize.pos - 1;
262 instrument_changed();
263 }
264 } else if (resize.mode == resize.moving_low_limit) {
265 if (resize.region->KeyRange.low != resize.pos) {
266 resize.region->KeyRange.low = resize.pos;
267 instrument_changed();
268 }
269 }
270
271 if (!is_in_resize_zone(event->x, event->y) && cursor_is_resize) {
272 get_window()->set_cursor();
273 cursor_is_resize = false;
274 }
275 } else if (move.active) {
276 get_window()->pointer_ungrab(event->time);
277 move.active = false;
278
279 if (move.pos) {
280 region->KeyRange.low += move.pos;
281 region->KeyRange.high += move.pos;
282
283 // find the r which is the first one to the right of region
284 // at its new position
285 gig::Region* r;
286 gig::Region* prev_region = 0;
287 for (r = instrument->GetFirstRegion() ; r ; r = instrument->GetNextRegion()) {
288 if (r->KeyRange.low > region->KeyRange.low) break;
289 prev_region = r;
290 }
291
292 // place region before r if it's not already there
293 if (prev_region != region) {
294 instrument_struct_to_be_changed_signal.emit(instrument);
295 instrument->MoveRegion(region, r);
296 instrument_struct_changed_signal.emit(instrument);
297 }
298 }
299
300 if (is_in_resize_zone(event->x, event->y)) {
301 get_window()->set_cursor(Gdk::Cursor(Gdk::SB_H_DOUBLE_ARROW));
302 cursor_is_resize = true;
303 }
304 }
305 return true;
306 }
307
308 bool RegionChooser::on_button_press_event(GdkEventButton* event)
309 {
310 if (!instrument) return true;
311
312 int k = int(event->x / (width - 1) * 128.0);
313
314 if (event->type == GDK_BUTTON_PRESS && event->button == 3) {
315 gig::Region* r = get_region(k);
316 if (r) {
317 region = r;
318 queue_draw();
319 region_selected();
320 popup_menu_inside_region->popup(event->button, event->time);
321 } else {
322 new_region_pos = k;
323 popup_menu_outside_region->popup(event->button, event->time);
324 }
325 } else {
326 if (is_in_resize_zone(event->x, event->y)) {
327 get_window()->pointer_grab(false,
328 Gdk::BUTTON_RELEASE_MASK |
329 Gdk::POINTER_MOTION_MASK |
330 Gdk::POINTER_MOTION_HINT_MASK,
331 Gdk::Cursor(Gdk::SB_H_DOUBLE_ARROW), event->time);
332 resize.active = true;
333 } else {
334 gig::Region* r = get_region(k);
335 if (r) {
336 region = r;
337 queue_draw();
338 region_selected();
339
340 get_window()->pointer_grab(false,
341 Gdk::BUTTON_RELEASE_MASK |
342 Gdk::POINTER_MOTION_MASK |
343 Gdk::POINTER_MOTION_HINT_MASK,
344 Gdk::Cursor(Gdk::FLEUR), event->time);
345 move.active = true;
346 move.from_x = event->x;
347 move.pos = 0;
348 }
349 }
350 }
351 return true;
352 }
353
354 gig::Region* RegionChooser::get_region(int key)
355 {
356 gig::Region* prev_region = 0;
357 gig::Region* next_region;
358 for (gig::Region *r = instrument->GetFirstRegion() ; r ;
359 r = next_region) {
360 next_region = instrument->GetNextRegion();
361
362 if (key < r->KeyRange.low) return 0;
363 if (key <= r->KeyRange.high) {
364 move.touch_left = prev_region && prev_region->KeyRange.high + 1 == r->KeyRange.low;
365 move.touch_right = next_region && r->KeyRange.high + 1 == next_region->KeyRange.low;
366 return r;
367 }
368 prev_region = r;
369 }
370 return 0;
371 }
372
373 void RegionChooser::motion_resize_region(int x, int y)
374 {
375 const int w = width - 1;
376 Glib::RefPtr<Gdk::Window> window = get_window();
377
378 int k = int(double(x) / w * 128.0 + 0.5);
379
380 if (k < resize.min) k = resize.min;
381 else if (k > resize.max) k = resize.max;
382
383 if (k != resize.pos) {
384 if (resize.mode == resize.undecided) {
385 if (k < resize.pos) {
386 // edit high limit of prev_region
387 resize.max = resize.region->KeyRange.low;
388 resize.region = resize.prev_region;
389 resize.mode = resize.moving_high_limit;
390 } else {
391 // edit low limit of region
392 resize.min = resize.prev_region->KeyRange.high + 1;
393 resize.mode = resize.moving_low_limit;
394 }
395 }
396 Glib::RefPtr<const Gdk::GC> black = get_style()->get_black_gc();
397 Glib::RefPtr<const Gdk::GC> white = get_style()->get_white_gc();
398 if (region == resize.region) {
399 gc->set_foreground(red);
400 white = gc;
401 }
402 Glib::RefPtr<const Gdk::GC> bg = get_style()->get_bg_gc(Gtk::STATE_NORMAL);
403 int prevx = int(w * resize.pos / 128.0 + 0.5);
404 x = int(w * k / 128.0 + 0.5);
405
406 if (resize.mode == resize.moving_high_limit) {
407 if (k > resize.pos) {
408 window->draw_rectangle(white, true, prevx, 1, x - prevx, h1 - 2);
409 window->draw_line(black, prevx, 0, x, 0);
410 window->draw_line(black, prevx, h1 - 1, x, h1 - 1);
411 } else {
412 int xx = ((resize.pos == resize.max && resize.max != 128) ? 1 : 0);
413 window->draw_rectangle(bg, true, x + 1, 0, prevx - x - xx, h1);
414 }
415 } else {
416 if (k < resize.pos) {
417 window->draw_rectangle(white, true, x + 1, 1, prevx - x, h1 - 2);
418 window->draw_line(black, x, 0, prevx, 0);
419 window->draw_line(black, x, h1 - 1, prevx, h1 - 1);
420 } else {
421 int xx = ((resize.pos == resize.min && resize.min != 0) ? 1 : 0);
422 window->draw_rectangle(bg, true, prevx + xx, 0, x - prevx - xx, h1);
423 }
424 }
425 window->draw_line(black, x, 1, x, h1 - 2);
426 resize.pos = k;
427 }
428 }
429
430 void RegionChooser::motion_move_region(int x, int y)
431 {
432 const int w = width - 1;
433 Glib::RefPtr<Gdk::Window> window = get_window();
434
435 int k = int(double(x - move.from_x) / w * 128.0 + 0.5);
436 if (k == move.pos) return;
437 int new_k;
438 bool new_touch_left;
439 bool new_touch_right;
440 int a = 0;
441 if (k > move.pos) {
442 for (gig::Region* r = instrument->GetFirstRegion() ; ;
443 r = instrument->GetNextRegion()) {
444 if (r != region) {
445 int b = r ? r->KeyRange.low : 128;
446
447 // gap: from a to b (not inclusive b)
448
449 if (region->KeyRange.high + move.pos >= b) {
450 // not found the current gap yet, just continue
451 } else {
452
453 if (a > region->KeyRange.low + k) {
454 // this gap is too far to the right, break
455 break;
456 }
457
458 int newhigh = std::min(region->KeyRange.high + k, b - 1);
459 int newlo = newhigh - (region->KeyRange.high - region->KeyRange.low);
460
461 if (newlo >= a) {
462 // yes it fits - it's a candidate
463 new_k = newlo - region->KeyRange.low;
464 new_touch_left = a > 0 && a == newlo;
465 new_touch_right = b < 128 && newhigh + 1 == b;
466 }
467 }
468 if (!r) break;
469 a = r->KeyRange.high + 1;
470 }
471 }
472 } else {
473 for (gig::Region* r = instrument->GetFirstRegion() ; ;
474 r = instrument->GetNextRegion()) {
475 if (r != region) {
476 int b = r ? r->KeyRange.low : 128;
477
478 // gap from a to b (not inclusive b)
479
480 if (region->KeyRange.high + k >= b) {
481 // not found the current gap yet, just continue
482 } else {
483
484 if (a > region->KeyRange.low + move.pos) {
485 // this gap is too far to the right, break
486 break;
487 }
488
489 int newlo = std::max(region->KeyRange.low + k, a);
490 int newhigh = newlo + (region->KeyRange.high - region->KeyRange.low);
491
492 if (newhigh < b) {
493 // yes it fits - break as the first one is the best
494 new_k = newlo - region->KeyRange.low;
495 new_touch_left = a > 0 && a == newlo;
496 new_touch_right = b < 128 && newhigh + 1 == b;
497 break;
498 }
499 }
500 if (!r) break;
501 a = r->KeyRange.high + 1;
502 }
503 }
504 }
505 k = new_k;
506 if (k == move.pos) return;
507
508 Glib::RefPtr<const Gdk::GC> bg = get_style()->get_bg_gc(Gtk::STATE_NORMAL);
509 int prevx = int(w * (move.pos + region->KeyRange.low) / 128.0 + 0.5);
510 x = int(w * (k + region->KeyRange.low) / 128.0 + 0.5);
511 int prevx2 = int(w * (move.pos + region->KeyRange.high + 1) / 128.0 + 0.5);
512 int x2 = int(w * (k + region->KeyRange.high + 1) / 128.0 + 0.5);
513 Glib::RefPtr<const Gdk::GC> black = get_style()->get_black_gc();
514 gc->set_foreground(red);
515
516 if (!new_touch_left) window->draw_line(black, x, 1, x, h1 - 2);
517 if (!new_touch_right) window->draw_line(black, x2, 1, x2, h1 - 2);
518
519 if (k > move.pos) {
520 window->draw_rectangle(bg, true, prevx + (move.touch_left ? 1 : 0), 0,
521 std::min(x, prevx2 + 1 - (move.touch_right ? 1 : 0)) -
522 (prevx + (move.touch_left ? 1 : 0)), h1);
523
524 window->draw_line(black, std::max(x, prevx2 + 1), 0, x2, 0);
525 window->draw_line(black, std::max(x, prevx2 + 1), h1 - 1, x2, h1 - 1);
526 window->draw_rectangle(gc, true, std::max(x + 1, prevx2), 1,
527 x2 - std::max(x + 1, prevx2), h1 - 2);
528 } else {
529 window->draw_rectangle(bg, true, std::max(x2 + 1, prevx + (move.touch_left ? 1 : 0)), 0,
530 prevx2 + 1 - (move.touch_right ? 1 : 0) -
531 std::max(x2 + 1, prevx + (move.touch_left ? 1 : 0)), h1);
532
533 window->draw_line(black, x, 0, std::min(x2, prevx - 1), 0);
534 window->draw_line(black, x, h1 - 1, std::min(x2, prevx - 1), h1 - 1);
535
536 window->draw_rectangle(gc, true, x + 1, 1, std::min(x2 - 1, prevx) - x, h1 - 2);
537 }
538
539 move.pos = k;
540 move.touch_left = new_touch_left;
541 move.touch_right = new_touch_right;
542 }
543
544
545 bool RegionChooser::on_motion_notify_event(GdkEventMotion* event)
546 {
547 Glib::RefPtr<Gdk::Window> window = get_window();
548 int x, y;
549 Gdk::ModifierType state = Gdk::ModifierType(0);
550 window->get_pointer(x, y, state);
551
552 if (resize.active) {
553 motion_resize_region(x, y);
554 } else if (move.active) {
555 motion_move_region(x, y);
556 } else {
557 if (is_in_resize_zone(x, y)) {
558 if (!cursor_is_resize) {
559 window->set_cursor(Gdk::Cursor(Gdk::SB_H_DOUBLE_ARROW));
560 cursor_is_resize = true;
561 }
562 } else if (cursor_is_resize) {
563 window->set_cursor();
564 cursor_is_resize = false;
565 }
566 }
567
568 return true;
569 }
570
571 bool RegionChooser::is_in_resize_zone(double x, double y) {
572 const int w = width - 1;
573
574 if (instrument && y >= 0 && y <= h1) {
575 gig::Region* prev_region = 0;
576 gig::Region* next_region;
577 for (gig::Region* r = instrument->GetFirstRegion() ; r ; r = next_region) {
578 next_region = instrument->GetNextRegion();
579
580 int lo = int(w * (r->KeyRange.low) / 128.0 + 0.5);
581 if (x <= lo - 2) break;
582 if (x < lo + 2) {
583 resize.region = r;
584 resize.pos = r->KeyRange.low;
585 resize.max = r->KeyRange.high;
586
587 if (prev_region && prev_region->KeyRange.high + 1 == r->KeyRange.low) {
588 // we don't know yet if it's the high limit of
589 // prev_region or the low limit of r that's going
590 // to be edited
591 resize.mode = resize.undecided;
592 resize.min = prev_region->KeyRange.low + 1;
593 resize.prev_region = prev_region;
594 return true;
595 }
596
597 // edit low limit
598 resize.mode = resize.moving_low_limit;
599 resize.min = prev_region ? prev_region->KeyRange.high + 1 : 0;
600 return true;
601 }
602 if (!next_region || r->KeyRange.high + 1 != next_region->KeyRange.low) {
603 int hi = int(w * (r->KeyRange.high + 1) / 128.0 + 0.5);
604 if (x <= hi - 2) break;
605 if (x < hi + 2) {
606 // edit high limit
607 resize.region = r;
608 resize.pos = r->KeyRange.high + 1;
609 resize.mode = resize.moving_high_limit;
610 resize.min = r->KeyRange.low + 1;
611 resize.max = next_region ? next_region->KeyRange.low : 128;
612 return true;
613 }
614 }
615 prev_region = r;
616 }
617 }
618 return false;
619 }
620
621 sigc::signal<void> RegionChooser::signal_region_selected()
622 {
623 return region_selected;
624 }
625
626 sigc::signal<void> RegionChooser::signal_instrument_changed()
627 {
628 return instrument_changed;
629 }
630
631 void RegionChooser::show_region_properties()
632 {
633 if (!region) return;
634 Gtk::Dialog dialog("Region Properties", true /*modal*/);
635 // add "Keygroup" checkbox
636 Gtk::CheckButton checkBoxKeygroup("Member of a Keygroup (Exclusive Group)");
637 checkBoxKeygroup.set_active(region->KeyGroup);
638 dialog.get_vbox()->pack_start(checkBoxKeygroup);
639 checkBoxKeygroup.show();
640 // add "Keygroup" spinbox
641 Gtk::Adjustment adjustment(1, 1, pow(2,32));
642 Gtk::SpinButton spinBox(adjustment);
643 if (region->KeyGroup) spinBox.set_value(region->KeyGroup);
644 dialog.get_vbox()->pack_start(spinBox);
645 spinBox.show();
646 // add OK and CANCEL buttons to the dialog
647 dialog.add_button(Gtk::Stock::OK, 0);
648 dialog.add_button(Gtk::Stock::CANCEL, 1);
649 dialog.show_all_children();
650 if (!dialog.run()) { // OK selected ...
651 region->KeyGroup =
652 (checkBoxKeygroup.get_active()) ? spinBox.get_value_as_int() : 0;
653 }
654 }
655
656 void RegionChooser::add_region()
657 {
658 gig::Region* r;
659 for (r = instrument->GetFirstRegion() ; r ; r = instrument->GetNextRegion()) {
660 if (r->KeyRange.low > new_region_pos) break;
661 }
662
663 instrument_struct_to_be_changed_signal.emit(instrument);
664
665 region = instrument->AddRegion();
666 region->KeyRange.low = region->KeyRange.high = new_region_pos;
667
668 instrument->MoveRegion(region, r);
669
670 instrument_struct_changed_signal.emit(instrument);
671
672 queue_draw();
673 region_selected();
674 instrument_changed();
675 }
676
677 void RegionChooser::delete_region()
678 {
679 instrument_struct_to_be_changed_signal.emit(instrument);
680 instrument->DeleteRegion(region);
681 instrument_struct_changed_signal.emit(instrument);
682
683 region = 0;
684 queue_draw();
685 region_selected();
686 instrument_changed();
687 }
688
689 void RegionChooser::manage_dimensions()
690 {
691 gig::Region* region = get_region();
692 if (!region) return;
693 dimensionManager.show(region);
694 }
695
696 void RegionChooser::on_dimension_manager_changed() {
697 region_selected();
698 instrument_changed();
699 }
700
701 sigc::signal<void, gig::Instrument*> RegionChooser::signal_instrument_struct_to_be_changed() {
702 return instrument_struct_to_be_changed_signal;
703 }
704
705 sigc::signal<void, gig::Instrument*> RegionChooser::signal_instrument_struct_changed() {
706 return instrument_struct_changed_signal;
707 }
708
709 sigc::signal<void, gig::Region*> RegionChooser::signal_region_to_be_changed() {
710 return region_to_be_changed_signal;
711 }
712
713 sigc::signal<void, gig::Region*> RegionChooser::signal_region_changed_signal() {
714 return region_changed_signal;
715 }

  ViewVC Help
Powered by ViewVC