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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3148 - (hide annotations) (download)
Thu May 4 11:47:45 2017 UTC (6 years, 11 months ago) by schoenebeck
File size: 39258 byte(s)
* Region Chooser: Mark all regions which are auto selected by check box
  "All Regions" with gray hatched pattern.
* Bumped version (1.0.0.svn34).

1 schoenebeck 1225 /*
2 schoenebeck 3148 * Copyright (C) 2006-2017 Andreas Persson
3 schoenebeck 1225 *
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 persson 2151
22 persson 1623 #include <algorithm>
23 schoenebeck 3148 #include <assert.h>
24 persson 2151
25     #include <cairomm/context.h>
26     #include <gdkmm/general.h>
27 schoenebeck 1225 #include <gdkmm/cursor.h>
28 schoenebeck 3106 #include <gdkmm/pixbuf.h>
29 schoenebeck 1225 #include <gtkmm/spinbutton.h>
30     #include <gtkmm/dialog.h>
31    
32 schoenebeck 1396 #include "global.h"
33 schoenebeck 2773 #include "Settings.h"
34 schoenebeck 3106 #include "gfx/builtinpix.h"
35 schoenebeck 1225
36 schoenebeck 2627 #define REGION_BLOCK_HEIGHT 30
37 persson 2246 #define KEYBOARD_HEIGHT 40
38 schoenebeck 1660
39 schoenebeck 3106 struct RegionFeatures {
40     int sampleRefs;
41     int loops;
42    
43     RegionFeatures() {
44     sampleRefs = loops = 0;
45     }
46     };
47    
48     static RegionFeatures regionFeatures(gig::Region* rgn) {
49     RegionFeatures f;
50     for (int i = 0; i < rgn->DimensionRegions; ++i) {
51     gig::DimensionRegion* dr = rgn->pDimensionRegions[i];
52     if (dr->pSample) f.sampleRefs++;
53     // the user doesn't care about loop if there is no valid sample reference
54     if (dr->pSample && dr->SampleLoops) f.loops++;
55     }
56     return f;
57     }
58    
59 persson 1623 void SortedRegions::update(gig::Instrument* instrument) {
60     // Usually, the regions in a gig file are ordered after their key
61     // range, but there are files where they are not. The
62     // RegionChooser code needs a sorted list of regions.
63     regions.clear();
64     if (instrument) {
65 persson 2151 for (gig::Region* r = instrument->GetFirstRegion() ;
66 persson 1623 r ;
67     r = instrument->GetNextRegion()) {
68     regions.push_back(r);
69     }
70     sort(regions.begin(), regions.end(), *this);
71     }
72     }
73    
74     gig::Region* SortedRegions::first() {
75     region_iterator = regions.begin();
76     return region_iterator == regions.end() ? 0 : *region_iterator;
77     }
78    
79     gig::Region* SortedRegions::next() {
80 persson 2841 ++region_iterator;
81 persson 1623 return region_iterator == regions.end() ? 0 : *region_iterator;
82     }
83    
84    
85    
86 schoenebeck 1661 RegionChooser::RegionChooser() :
87 persson 2169 activeKeyColor("red"),
88 schoenebeck 3131 blue("#4796ff"),
89 persson 2169 grey1("grey69"),
90     white("white"),
91     black("black"),
92 schoenebeck 1661 m_VirtKeybModeChoice(_("Virtual Keyboard Mode")),
93 schoenebeck 3148 currentActiveKey(-1),
94     modifyallregions(false)
95 schoenebeck 1225 {
96 persson 2169 set_size_request(500, KEYBOARD_HEIGHT + REGION_BLOCK_HEIGHT);
97 schoenebeck 1225
98 schoenebeck 3106 loadBuiltInPix();
99    
100 schoenebeck 3148 // create gray blue hatched pattern
101     {
102     const int width = grayBlueHatchedPattern->get_width();
103     const int height = grayBlueHatchedPattern->get_height();
104     const int stride = grayBlueHatchedPattern->get_rowstride();
105    
106     // manually convert from RGBA to ARGB
107     this->grayBlueHatchedPatternARGB = grayBlueHatchedPattern->copy();
108     const int pixelSize = stride / width;
109     const int totalPixels = width * height;
110     assert(pixelSize == 4);
111     unsigned char* ptr = this->grayBlueHatchedPatternARGB->get_pixels();
112     for (int iPixel = 0; iPixel < totalPixels; ++iPixel, ptr += pixelSize) {
113     const unsigned char r = ptr[0];
114     const unsigned char g = ptr[1];
115     const unsigned char b = ptr[2];
116     const unsigned char a = ptr[3];
117     ptr[0] = b;
118     ptr[1] = g;
119     ptr[2] = r;
120     ptr[3] = a;
121     }
122    
123     Cairo::RefPtr<Cairo::ImageSurface> imageSurface = Cairo::ImageSurface::create(
124     this->grayBlueHatchedPatternARGB->get_pixels(), Cairo::FORMAT_ARGB32, width, height, stride
125     );
126     this->grayBlueHatchedSurfacePattern = Cairo::SurfacePattern::create(imageSurface);
127     this->grayBlueHatchedSurfacePattern->set_extend(Cairo::EXTEND_REPEAT);
128     }
129    
130 schoenebeck 1225 instrument = 0;
131     region = 0;
132     resize.active = false;
133 persson 1303 move.active = false;
134 schoenebeck 1225 cursor_is_resize = false;
135 schoenebeck 1660 h1 = REGION_BLOCK_HEIGHT;
136 schoenebeck 1225
137 persson 1831 // properties of the virtual keyboard
138 schoenebeck 1661 {
139 persson 2246 const char* choices[] = { _("normal"), _("chord"), 0 };
140 schoenebeck 1661 static const virt_keyboard_mode_t values[] = {
141     VIRT_KEYBOARD_MODE_NORMAL,
142     VIRT_KEYBOARD_MODE_CHORD
143     };
144     m_VirtKeybModeChoice.set_choices(choices, values);
145     m_VirtKeybModeChoice.set_value(VIRT_KEYBOARD_MODE_NORMAL);
146     }
147     m_VirtKeybVelocityLabelDescr.set_text(_("Note-On Velocity:"));
148     m_VirtKeybVelocityLabel.set_text("-");
149     m_VirtKeybOffVelocityLabelDescr.set_text(_("Note-Off Velocity:"));
150     m_VirtKeybOffVelocityLabel.set_text("-");
151     m_VirtKeybPropsBox.pack_start(m_VirtKeybModeChoice.label, Gtk::PACK_SHRINK);
152     m_VirtKeybPropsBox.pack_start(m_VirtKeybModeChoice.widget, Gtk::PACK_SHRINK);
153     m_VirtKeybPropsBox.pack_start(m_VirtKeybVelocityLabelDescr, Gtk::PACK_SHRINK);
154     m_VirtKeybPropsBox.pack_start(m_VirtKeybVelocityLabel, Gtk::PACK_SHRINK);
155     m_VirtKeybPropsBox.pack_start(m_VirtKeybOffVelocityLabelDescr, Gtk::PACK_SHRINK);
156     m_VirtKeybPropsBox.pack_start(m_VirtKeybOffVelocityLabel, Gtk::PACK_SHRINK);
157     m_VirtKeybPropsBox.set_spacing(10);
158     m_VirtKeybPropsBox.show();
159 persson 2246 for (int i = 0 ; i < 128 ; i++) key_pressed[i] = false;
160 schoenebeck 1661
161 schoenebeck 1225 actionGroup = Gtk::ActionGroup::create();
162 persson 2845 actionGroup->add(Gtk::Action::create("Properties", _("_Properties")),
163 schoenebeck 1225 sigc::mem_fun(*this,
164     &RegionChooser::show_region_properties));
165 persson 2845 actionGroup->add(Gtk::Action::create("Remove", _("_Remove")),
166 schoenebeck 1225 sigc::mem_fun(*this, &RegionChooser::delete_region));
167 persson 2845 actionGroup->add(Gtk::Action::create("Add", _("_Add")),
168 schoenebeck 1225 sigc::mem_fun(*this, &RegionChooser::add_region));
169     actionGroup->add(Gtk::Action::create("Dimensions", _("Dimensions...")),
170     sigc::mem_fun(*this, &RegionChooser::manage_dimensions));
171    
172     uiManager = Gtk::UIManager::create();
173     uiManager->insert_action_group(actionGroup);
174     Glib::ustring ui_info =
175     "<ui>"
176     " <popup name='PopupMenuInsideRegion'>"
177     " <menuitem action='Properties'/>"
178     " <menuitem action='Dimensions'/>"
179     " <menuitem action='Remove'/>"
180     " </popup>"
181     " <popup name='PopupMenuOutsideRegion'>"
182     " <menuitem action='Add'/>"
183     " </popup>"
184     "</ui>";
185     uiManager->add_ui_from_string(ui_info);
186    
187     popup_menu_inside_region = dynamic_cast<Gtk::Menu*>(
188     uiManager->get_widget("/PopupMenuInsideRegion"));
189     popup_menu_outside_region = dynamic_cast<Gtk::Menu*>(
190     uiManager->get_widget("/PopupMenuOutsideRegion"));
191    
192     add_events(Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK |
193     Gdk::POINTER_MOTION_MASK | Gdk::POINTER_MOTION_HINT_MASK);
194    
195 schoenebeck 1322 dimensionManager.region_to_be_changed_signal.connect(
196     region_to_be_changed_signal.make_slot()
197 schoenebeck 1225 );
198 schoenebeck 1322 dimensionManager.region_changed_signal.connect(
199     region_changed_signal.make_slot()
200     );
201     dimensionManager.region_changed_signal.connect(
202     sigc::hide(
203     sigc::mem_fun(*this, &RegionChooser::on_dimension_manager_changed)
204     )
205     );
206 schoenebeck 1660 keyboard_key_hit_signal.connect(
207     sigc::mem_fun(*this, &RegionChooser::on_note_on_event)
208     );
209     keyboard_key_released_signal.connect(
210     sigc::mem_fun(*this, &RegionChooser::on_note_off_event)
211     );
212 schoenebeck 2536 set_tooltip_text(_("Right click here for adding new region. Use mouse pointer for moving (dragging) or resizing existing regions (by pointing at region's boundary). Right click on an existing region for more actions."));
213 schoenebeck 1225 }
214    
215     RegionChooser::~RegionChooser()
216     {
217     }
218    
219 schoenebeck 3148 void RegionChooser::setModifyAllRegions(bool b) {
220     modifyallregions = b;
221     // redraw required parts
222     queue_draw();
223     }
224    
225 persson 2246 void RegionChooser::invalidate_key(int key) {
226     const int h = KEYBOARD_HEIGHT;
227     const int w = get_width() - 1;
228     int x1 = key_to_x(key - 0.5, w);
229     int x2 = key_to_x(key + 1.5, w);
230    
231     Gdk::Rectangle rect(x1 + 1, h1 + 1, x2 - x1 - 1, h - 2);
232     get_window()->invalidate_rect(rect, false);
233     }
234    
235 schoenebeck 1654 void RegionChooser::on_note_on_event(int key, int velocity) {
236 persson 2246 key_pressed[key] = true;
237     invalidate_key(key);
238 schoenebeck 1661 m_VirtKeybVelocityLabel.set_text(ToString(velocity));
239 schoenebeck 1654 }
240    
241     void RegionChooser::on_note_off_event(int key, int velocity) {
242 persson 2246 key_pressed[key] = false;
243     invalidate_key(key);
244 schoenebeck 1661 m_VirtKeybOffVelocityLabel.set_text(ToString(velocity));
245 schoenebeck 1654 }
246    
247 persson 2246
248 persson 2169 #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
249 persson 2246 bool RegionChooser::on_expose_event(GdkEventExpose* e) {
250     double clipx1 = e->area.x;
251     double clipx2 = e->area.x + e->area.width;
252     double clipy1 = e->area.y;
253     double clipy2 = e->area.y + e->area.height;
254    
255     const Cairo::RefPtr<Cairo::Context>& cr =
256     get_window()->create_cairo_context();
257     #if 0
258 persson 2169 }
259     #endif
260 persson 2246 #else
261     bool RegionChooser::on_draw(const Cairo::RefPtr<Cairo::Context>& cr) {
262     double clipx1, clipx2, clipy1, clipy2;
263     cr->get_clip_extents(clipx1, clipy1, clipx2, clipy2);
264     #endif
265 schoenebeck 1225
266 persson 2169 cr->save();
267     cr->set_line_width(1);
268 schoenebeck 1225
269 persson 2169 #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
270     const Gdk::Color bg = get_style()->get_bg(Gtk::STATE_NORMAL);
271     #else
272     const Gdk::RGBA bg = get_style_context()->get_background_color();
273     #endif
274     Gdk::Cairo::set_source_rgba(cr, bg);
275     cr->paint();
276 schoenebeck 1225
277 persson 2246 if (clipy2 > h1) {
278     draw_keyboard(cr, clipx1, clipx2);
279     }
280    
281     if (clipy1 < h1 && instrument) {
282     draw_regions(cr, clipx1, clipx2);
283     }
284    
285     cr->restore();
286    
287     return true;
288     }
289    
290     void RegionChooser::draw_keyboard(const Cairo::RefPtr<Cairo::Context>& cr,
291     int clip_low, int clip_high) {
292     const int h = KEYBOARD_HEIGHT;
293     const int w = get_width() - 1;
294     const int bh = int(h * 0.55);
295    
296 persson 2169 Gdk::Cairo::set_source_rgba(cr, black);
297     cr->rectangle(0.5, h1 + 0.5, w, h - 1);
298     cr->stroke();
299 schoenebeck 1225
300 persson 2246 int x1 = key_to_x(20.5, w);
301 persson 2169 Gdk::Cairo::set_source_rgba(cr, grey1);
302     cr->rectangle(1, h1 + 1, x1 - 1, h - 2);
303     cr->fill();
304 schoenebeck 1225
305 persson 2246 int x2 = key_to_x(109.5, w);
306 persson 2169 Gdk::Cairo::set_source_rgba(cr, white);
307     cr->rectangle(x1 + 1, h1 + 1, x2 - x1 - 1, h - 2);
308     cr->fill();
309 persson 2151
310 persson 2169 Gdk::Cairo::set_source_rgba(cr, grey1);
311     cr->rectangle(x2 + 1, h1 + 1, w - x2 - 1, h - 2);
312     cr->fill();
313 persson 2151
314 persson 2169 Gdk::Cairo::set_source_rgba(cr, black);
315 persson 2246
316     int clipkey1 = std::max(0, x_to_key_right(clip_low - 1, w));
317     int clipkey2 = std::min(x_to_key_right(clip_high - 1, w) + 1, 128);
318    
319     for (int i = clipkey1 ; i < clipkey2 ; i++) {
320 persson 2169 int note = (i + 3) % 12;
321 persson 2246 int x = key_to_x(i, w);
322 persson 2151
323 persson 2169 if (note == 1 || note == 4 || note == 6 ||
324     note == 9 || note == 11) {
325 persson 2246 // black key: short line in the middle, with a rectangle
326     // on top
327     int x2 = key_to_x(i + 0.5, w);
328 persson 2169 cr->move_to(x2 + 0.5, h1 + bh + 0.5);
329     cr->line_to(x2 + 0.5, h1 + h - 1);
330     cr->stroke();
331 persson 2151
332 persson 2246 int x3 = key_to_x(i + 1, w);
333 persson 2169 cr->rectangle(x, h1 + 1, x3 - x + 1, bh);
334     cr->fill();
335     } else if (note == 3 || note == 8) {
336 persson 2246 // C or F: long line to the left
337 persson 2169 cr->move_to(x + 0.5, h1 + 1);
338     cr->line_to(x + 0.5, h1 + h - 1);
339     cr->stroke();
340 persson 2246 }
341 persson 2151
342 persson 2246 if (key_pressed[i]) draw_key(cr, i);
343    
344     if (note == 3) draw_digit(cr, i);
345 persson 2169 }
346 persson 2246 }
347 schoenebeck 1225
348 persson 2151
349 persson 2246 void RegionChooser::draw_regions(const Cairo::RefPtr<Cairo::Context>& cr,
350     int clip_low, int clip_high) {
351     const int w = get_width() - 1;
352    
353     Gdk::Cairo::set_source_rgba(cr, black);
354     gig::Region* next_region;
355     int x3 = -1;
356     for (gig::Region* r = regions.first() ; r ; r = next_region) {
357     next_region = regions.next();
358    
359     if (x3 < 0) {
360     x3 = key_to_x(r->KeyRange.low, w);
361     if (x3 >= clip_high) break;
362     }
363     if (!next_region ||
364     r->KeyRange.high + 1 != next_region->KeyRange.low ||
365     r == region || next_region == region) {
366    
367     int x2 = key_to_x(r->KeyRange.high + 1, w);
368     if (x2 >= clip_low) {
369 persson 2169 cr->move_to(x3, 0.5);
370     cr->line_to(x2 + 0.5, 0.5);
371     cr->line_to(x2 + 0.5, h1 - 0.5);
372     cr->line_to(x3, h1 - 0.5);
373     cr->stroke();
374 persson 2151
375 schoenebeck 3148 if (region == r)
376     Gdk::Cairo::set_source_rgba(cr, blue);
377     else if (modifyallregions)
378     cr->set_source(grayBlueHatchedSurfacePattern);
379     else
380     Gdk::Cairo::set_source_rgba(cr, white);
381    
382 persson 2169 cr->rectangle(x3 + 1, 1, x2 - x3 - 1, h1 - 2);
383     cr->fill();
384     Gdk::Cairo::set_source_rgba(cr, black);
385 persson 2151 }
386 persson 2246 x3 = -1;
387 persson 2169 }
388 persson 2246 }
389 persson 2151
390 persson 2246 for (gig::Region* r = regions.first() ; r ; r = regions.next()) {
391     int x = key_to_x(r->KeyRange.low, w);
392 schoenebeck 3106 int x2 = key_to_x(r->KeyRange.high + 1, w);
393 persson 2151
394 schoenebeck 3106 RegionFeatures features = regionFeatures(r);
395    
396     const bool bShowLoopSymbol = features.loops > 0;
397     const bool bShowSampleRefSymbol = features.sampleRefs < r->DimensionRegions;
398     if (bShowLoopSymbol || bShowSampleRefSymbol) {
399     const int margin = 2;
400     const int wRgn = x2 - x;
401     //printf("x=%d x2=%d wRgn=%d\n", x, x2, wRgn);
402    
403     cr->save();
404     cr->set_line_width(1);
405     cr->rectangle(x, 1, wRgn, h1 - 1);
406     cr->clip();
407     if (bShowSampleRefSymbol) {
408     const int wPic = 8;
409     const int hPic = 8;
410     Gdk::Cairo::set_source_pixbuf(
411     cr, (features.sampleRefs) ? yellowDot : redDot,
412     x + (wRgn-wPic)/2.f,
413     (bShowLoopSymbol) ? margin : (h1-hPic)/2.f
414     );
415     cr->paint();
416     }
417     if (bShowLoopSymbol) {
418     const int wPic = 12;
419     const int hPic = 14;
420     Gdk::Cairo::set_source_pixbuf(
421     cr, (features.loops == r->DimensionRegions) ? blackLoop : grayLoop,
422     x + (wRgn-wPic)/2.f,
423     (bShowSampleRefSymbol) ? h1 - hPic - margin : (h1-hPic)/2.f
424     );
425     cr->paint();
426     }
427     cr->restore();
428     }
429     }
430    
431     for (gig::Region* r = regions.first() ; r ; r = regions.next()) {
432     int x = key_to_x(r->KeyRange.low, w);
433    
434 persson 2246 if (x < clip_low) continue;
435     if (x >= clip_high) break;
436    
437     cr->move_to(x + 0.5, 1);
438     cr->line_to(x + 0.5, h1 - 1);
439     cr->stroke();
440 schoenebeck 1225 }
441 schoenebeck 2536
442     // if there is no region yet, show the user some hint text that he may
443     // right click on this area to create a new region
444     if (!regions.first()) {
445     Glib::RefPtr<Pango::Context> context = get_pango_context();
446     Glib::RefPtr<Pango::Layout> layout = Pango::Layout::create(context);
447     layout->set_alignment(Pango::ALIGN_CENTER);
448     layout->set_text(Glib::ustring("*** ") + _("Right click here to create a region.") + " ***");
449     layout->set_width(get_width() * Pango::SCALE);
450 schoenebeck 2627 //layout->set_height(get_height() * Pango::SCALE);
451     layout->set_spacing(10);
452 schoenebeck 3131 Gdk::Cairo::set_source_rgba(cr, blue);
453 schoenebeck 2627 // get the text dimensions
454     int text_width, text_height;
455     layout->get_pixel_size(text_width, text_height);
456     cr->move_to(0, (REGION_BLOCK_HEIGHT - text_height) / 2);
457 schoenebeck 2536 #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 16) || GTKMM_MAJOR_VERSION < 2
458     pango_cairo_show_layout(cr->cobj(), layout->gobj());
459     #else
460     layout->show_in_cairo_context(cr);
461     #endif
462     }
463 schoenebeck 1225 }
464    
465 schoenebeck 1654 bool RegionChooser::is_black_key(int key) {
466     const int note = (key + 3) % 12;
467     return note == 1 || note == 4 || note == 6 || note == 9 || note == 11;
468     }
469 schoenebeck 1225
470 persson 2246 void RegionChooser::draw_digit(const Cairo::RefPtr<Cairo::Context>& cr,
471     int key) {
472 schoenebeck 1660 const int h = KEYBOARD_HEIGHT;
473 persson 1658 const int w = get_width() - 1;
474 persson 2246 Glib::RefPtr<Pango::Layout> layout =
475     Pango::Layout::create(get_pango_context());
476 persson 1658 char buf[30];
477     sprintf(buf, "<span size=\"8000\">%d</span>", key / 12 - 1);
478     layout->set_markup(buf);
479     Pango::Rectangle rectangle = layout->get_logical_extents();
480     double text_w = double(rectangle.get_width()) / Pango::SCALE;
481     double text_h = double(rectangle.get_height()) / Pango::SCALE;
482     double x = w * (key + 0.75) / 128.0;
483 persson 2169 Gdk::Cairo::set_source_rgba(cr, black);
484 persson 2151 cr->move_to(int(x - text_w / 2 + 1), int(h1 + h - text_h + 0.5));
485     #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 16) || GTKMM_MAJOR_VERSION < 2
486     pango_cairo_show_layout(cr->cobj(), layout->gobj());
487     #else
488     layout->show_in_cairo_context(cr);
489     #endif
490 persson 1658 }
491    
492 persson 2246 void RegionChooser::draw_key(const Cairo::RefPtr<Cairo::Context>& cr,
493     int key) {
494 schoenebeck 1660 const int h = KEYBOARD_HEIGHT;
495 persson 1658 const int w = get_width() - 1;
496 schoenebeck 1225 const int bh = int(h * 0.55);
497    
498 persson 2246 Gdk::Cairo::set_source_rgba(cr, activeKeyColor);
499 schoenebeck 1225
500 persson 2151 int note = (key + 3) % 12;
501 persson 2246 int x = key_to_x(key, w) + 1;
502     int x2 = key_to_x(key + 1.5, w);
503     int x3 = key_to_x(key + 1, w);
504     int x4 = key_to_x(key - 0.5, w);
505 persson 2151 int w1 = x3 - x;
506     switch (note) {
507     case 0: case 5: case 10:
508     cr->rectangle(x, h1 + 1, w1, bh);
509     cr->fill();
510     cr->rectangle(x4 + 1, h1 + bh + 1, x2 - x4 - 1, h - bh - 2);
511     cr->fill();
512     break;
513     case 2: case 7:
514     cr->rectangle(x, h1 + 1, w1, bh);
515     cr->fill();
516     cr->rectangle(x4 + 1, h1 + bh + 1, x3 - x4 - 1, h - bh - 2);
517     cr->fill();
518     break;
519     case 3: case 8:
520     cr->rectangle(x, h1 + 1, w1, bh);
521     cr->fill();
522     cr->rectangle(x, h1 + bh + 1, x2 - x, h - bh - 2);
523     cr->fill();
524     break;
525     default:
526     cr->rectangle(x, h1 + 1, w1, bh - 1);
527     cr->fill();
528     break;
529 schoenebeck 1225 }
530 persson 2246 Gdk::Cairo::set_source_rgba(cr, black);
531 schoenebeck 1225 }
532    
533     void RegionChooser::set_instrument(gig::Instrument* instrument)
534     {
535     this->instrument = instrument;
536 persson 1623 regions.update(instrument);
537     region = regions.first();
538 schoenebeck 1225 queue_draw();
539 persson 1261 region_selected();
540 persson 1677 dimensionManager.set_region(region);
541 schoenebeck 1225 }
542    
543     bool RegionChooser::on_button_release_event(GdkEventButton* event)
544     {
545 persson 2246 const int k = x_to_key(event->x, get_width() - 1);
546 schoenebeck 1660
547 schoenebeck 1661 // handle-note off on virtual keyboard
548 schoenebeck 1660 if (event->type == GDK_BUTTON_RELEASE) {
549 schoenebeck 1661 int velocity = (event->y >= REGION_BLOCK_HEIGHT + KEYBOARD_HEIGHT - 1) ? 127 :
550     int(float(event->y - REGION_BLOCK_HEIGHT) / float(KEYBOARD_HEIGHT) * 128.0f) + 1;
551     if (velocity <= 0) velocity = 1;
552     switch (m_VirtKeybModeChoice.get_value()) {
553     case VIRT_KEYBOARD_MODE_CHORD:
554     if (event->y >= REGION_BLOCK_HEIGHT)
555     keyboard_key_released_signal.emit(k, velocity);
556     break;
557     case VIRT_KEYBOARD_MODE_NORMAL:
558     default:
559     if (currentActiveKey >= 0 && currentActiveKey <= 127) {
560     keyboard_key_released_signal.emit(currentActiveKey, velocity);
561     currentActiveKey = -1;
562     }
563     break;
564 schoenebeck 1660 }
565     }
566    
567 schoenebeck 1225 if (resize.active) {
568 persson 2169 #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
569 schoenebeck 1225 get_window()->pointer_ungrab(event->time);
570 persson 2169 #else
571     Glib::wrap(event->device, true)->ungrab(event->time);
572     #endif
573 schoenebeck 1225 resize.active = false;
574    
575     if (!is_in_resize_zone(event->x, event->y) && cursor_is_resize) {
576     get_window()->set_cursor();
577     cursor_is_resize = false;
578     }
579 persson 1262 } else if (move.active) {
580 persson 2169 #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
581 persson 1262 get_window()->pointer_ungrab(event->time);
582 persson 2169 #else
583     Glib::wrap(event->device, true)->ungrab(event->time);
584     #endif
585 persson 1262 move.active = false;
586    
587     if (is_in_resize_zone(event->x, event->y)) {
588 persson 2169 #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
589 persson 1262 get_window()->set_cursor(Gdk::Cursor(Gdk::SB_H_DOUBLE_ARROW));
590 persson 2169 #else
591     get_window()->set_cursor(Gdk::Cursor::create(Gdk::SB_H_DOUBLE_ARROW));
592     #endif
593 persson 1262 cursor_is_resize = true;
594     }
595 schoenebeck 1225 }
596     return true;
597     }
598    
599 persson 2246 void RegionChooser::update_after_resize()
600     {
601     if (resize.mode == resize.moving_high_limit) {
602     if (resize.region->KeyRange.high != resize.pos - 1) {
603     instrument_struct_to_be_changed_signal.emit(instrument);
604     resize.region->SetKeyRange(resize.region->KeyRange.low,
605     resize.pos - 1);
606     regions.update(instrument);
607     instrument_changed.emit();
608     instrument_struct_changed_signal.emit(instrument);
609     }
610     } else if (resize.mode == resize.moving_low_limit) {
611     if (resize.region->KeyRange.low != resize.pos) {
612     instrument_struct_to_be_changed_signal.emit(instrument);
613     resize.region->SetKeyRange(resize.pos,
614     resize.region->KeyRange.high);
615     regions.update(instrument);
616     instrument_changed.emit();
617     instrument_struct_changed_signal.emit(instrument);
618     }
619     }
620     }
621    
622     void RegionChooser::update_after_move(int pos)
623     {
624     instrument_struct_to_be_changed_signal.emit(instrument);
625 schoenebeck 2773 const int range = region->KeyRange.high - region->KeyRange.low;
626     const int diff = pos - int(region->KeyRange.low);
627     region->SetKeyRange(pos, pos + range);
628     if (Settings::singleton()->moveRootNoteWithRegionMoved) {
629     for (int i = 0; i < 256; ++i) {
630     gig::DimensionRegion* dimrgn = region->pDimensionRegions[i];
631     if (!dimrgn || !dimrgn->pSample || !dimrgn->PitchTrack) continue;
632     dimrgn->UnityNote += diff;
633     }
634     }
635 persson 2246 regions.update(instrument);
636     instrument_changed.emit();
637     instrument_struct_changed_signal.emit(instrument);
638     }
639    
640 schoenebeck 1225 bool RegionChooser::on_button_press_event(GdkEventButton* event)
641     {
642     if (!instrument) return true;
643    
644 persson 2246 const int w = get_width() - 1;
645     const int k = x_to_key(event->x, w);
646 schoenebeck 1225
647 schoenebeck 1660 if (event->type == GDK_BUTTON_PRESS) {
648     if (event->y >= REGION_BLOCK_HEIGHT) {
649     int velocity = (event->y >= REGION_BLOCK_HEIGHT + KEYBOARD_HEIGHT - 1) ? 127 :
650     int(float(event->y - REGION_BLOCK_HEIGHT) / float(KEYBOARD_HEIGHT) * 128.0f) + 1;
651 schoenebeck 1661 currentActiveKey = k;
652 schoenebeck 1660 keyboard_key_hit_signal.emit(k, velocity);
653     }
654     }
655    
656 schoenebeck 2641 // left mouse button double click
657     if (event->type == GDK_2BUTTON_PRESS && event->button == 1) {
658 schoenebeck 2663 if (event->y < REGION_BLOCK_HEIGHT) {
659     // show dimension manager dialog for this region
660     manage_dimensions();
661     }
662 schoenebeck 2641 }
663    
664 schoenebeck 1660 if (event->y >= REGION_BLOCK_HEIGHT) return true;
665 schoenebeck 1225 if (event->type == GDK_BUTTON_PRESS && event->button == 3) {
666     gig::Region* r = get_region(k);
667     if (r) {
668     region = r;
669     queue_draw();
670 persson 1261 region_selected();
671 persson 1677 dimensionManager.set_region(region);
672 schoenebeck 1225 popup_menu_inside_region->popup(event->button, event->time);
673     } else {
674     new_region_pos = k;
675     popup_menu_outside_region->popup(event->button, event->time);
676     }
677     } else {
678     if (is_in_resize_zone(event->x, event->y)) {
679 persson 2169 #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
680 schoenebeck 1225 get_window()->pointer_grab(false,
681     Gdk::BUTTON_RELEASE_MASK |
682     Gdk::POINTER_MOTION_MASK |
683     Gdk::POINTER_MOTION_HINT_MASK,
684 persson 2169 Gdk::Cursor(Gdk::SB_H_DOUBLE_ARROW),
685     event->time);
686     #else
687     Glib::wrap(event->device, true)->grab(get_window(),
688     Gdk::OWNERSHIP_NONE,
689     false,
690     Gdk::BUTTON_RELEASE_MASK |
691     Gdk::POINTER_MOTION_MASK |
692     Gdk::POINTER_MOTION_HINT_MASK,
693     Gdk::Cursor::create(Gdk::SB_H_DOUBLE_ARROW),
694     event->time);
695     #endif
696 schoenebeck 1225 resize.active = true;
697     } else {
698     gig::Region* r = get_region(k);
699     if (r) {
700     region = r;
701     queue_draw();
702 persson 1261 region_selected();
703 persson 1677 dimensionManager.set_region(region);
704 persson 1262
705 persson 2169 #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
706 persson 1262 get_window()->pointer_grab(false,
707     Gdk::BUTTON_RELEASE_MASK |
708     Gdk::POINTER_MOTION_MASK |
709     Gdk::POINTER_MOTION_HINT_MASK,
710 persson 2169 Gdk::Cursor(Gdk::FLEUR),
711     event->time);
712     #else
713     Glib::wrap(event->device, true)->grab(get_window(),
714     Gdk::OWNERSHIP_NONE,
715     false,
716     Gdk::BUTTON_RELEASE_MASK |
717     Gdk::POINTER_MOTION_MASK |
718     Gdk::POINTER_MOTION_HINT_MASK,
719     Gdk::Cursor::create(Gdk::FLEUR),
720     event->time);
721     #endif
722 persson 1262 move.active = true;
723 persson 2246 move.offset = event->x - key_to_x(region->KeyRange.low, w);
724 schoenebeck 1225 }
725     }
726     }
727     return true;
728     }
729    
730     gig::Region* RegionChooser::get_region(int key)
731     {
732 persson 2246 for (gig::Region* r = regions.first() ; r ; r = regions.next()) {
733 schoenebeck 1225 if (key < r->KeyRange.low) return 0;
734 persson 2246 if (key <= r->KeyRange.high) return r;
735 schoenebeck 1225 }
736     return 0;
737     }
738    
739 schoenebeck 2695 void RegionChooser::set_region(gig::Region* region) {
740     this->region = region;
741     queue_draw();
742     region_selected();
743     dimensionManager.set_region(region);
744     }
745    
746 schoenebeck 3123 void RegionChooser::select_next_region() {
747     if (!instrument) return;
748     if (!region) {
749     for (int i = 0; i < 128; ++i) {
750     ::gig::Region* rgn = instrument->GetRegion(i);
751     if (rgn) {
752     set_region(rgn);
753     return;
754     }
755     }
756     } else {
757     bool currentFound = false;
758     for (int i = 0; i < 128; ++i) {
759     ::gig::Region* rgn = instrument->GetRegion(i);
760     if (!rgn) continue;
761     if (currentFound) {
762     if (rgn != region) {
763     set_region(rgn);
764     return;
765     }
766     } else {
767     if (rgn == region) currentFound = true;
768     }
769     }
770     }
771     }
772    
773     void RegionChooser::select_prev_region() {
774     if (!instrument) return;
775     if (!region) {
776     for (int i = 0; i < 128; ++i) {
777     ::gig::Region* rgn = instrument->GetRegion(i);
778     if (rgn) {
779     set_region(rgn);
780     return;
781     }
782     }
783     } else {
784     bool currentFound = false;
785     for (int i = 127; i >= 0; --i) {
786     ::gig::Region* rgn = instrument->GetRegion(i);
787     if (!rgn) continue;
788     if (currentFound) {
789     if (rgn != region) {
790     set_region(rgn);
791     return;
792     }
793     } else {
794     if (rgn == region) currentFound = true;
795     }
796     }
797     }
798     }
799    
800 persson 1262 void RegionChooser::motion_resize_region(int x, int y)
801 schoenebeck 1225 {
802 persson 1623 const int w = get_width() - 1;
803 schoenebeck 1225
804 persson 1262 int k = int(double(x) / w * 128.0 + 0.5);
805 schoenebeck 1225
806 persson 1262 if (k < resize.min) k = resize.min;
807     else if (k > resize.max) k = resize.max;
808    
809     if (k != resize.pos) {
810     if (resize.mode == resize.undecided) {
811     if (k < resize.pos) {
812     // edit high limit of prev_region
813     resize.max = resize.region->KeyRange.low;
814     resize.region = resize.prev_region;
815     resize.mode = resize.moving_high_limit;
816     } else {
817     // edit low limit of region
818     resize.min = resize.prev_region->KeyRange.high + 1;
819     resize.mode = resize.moving_low_limit;
820 schoenebeck 1225 }
821 persson 1262 }
822 persson 2246 resize.pos = k;
823 persson 2151
824 persson 2246 int x1, x2;
825 persson 1262 if (resize.mode == resize.moving_high_limit) {
826 persson 2246 if (resize.region->KeyRange.high < resize.pos - 1) {
827     x1 = resize.region->KeyRange.high;
828     x2 = resize.pos - 1;
829 persson 1262 } else {
830 persson 2246 x1 = resize.pos - 1;
831     x2 = resize.region->KeyRange.high;
832 schoenebeck 1225 }
833 persson 1262 } else {
834 persson 2246 if (resize.region->KeyRange.low < resize.pos) {
835     x1 = resize.region->KeyRange.low;
836     x2 = resize.pos;
837 persson 1262 } else {
838 persson 2246 x1 = resize.pos;
839     x2 = resize.region->KeyRange.low;
840 persson 1262 }
841     }
842 persson 2246 x1 = key_to_x(x1, w);
843     x2 = key_to_x(x2 + 1, w) + 1;
844     Gdk::Rectangle rect(x1, 0, x2 - x1, h1);
845    
846     update_after_resize();
847    
848 schoenebeck 3106 //get_window()->invalidate_rect(rect, false);
849     get_window()->invalidate(false); // repaint entire region, otherwise it would create visual artifacts
850 persson 1262 }
851     }
852 schoenebeck 1225
853 persson 1262 void RegionChooser::motion_move_region(int x, int y)
854     {
855 persson 1623 const int w = get_width() - 1;
856 persson 1262
857 persson 2246 int l = int(double(x - move.offset) / w * 128.0 + 0.5);
858    
859     if (l == region->KeyRange.low) return;
860     int new_l;
861     int regionsize = region->KeyRange.high - region->KeyRange.low;
862 persson 1262 int a = 0;
863 persson 2246 if (l > region->KeyRange.low) {
864 persson 1623 for (gig::Region* r = regions.first() ; ; r = regions.next()) {
865 persson 1262 if (r != region) {
866     int b = r ? r->KeyRange.low : 128;
867    
868     // gap: from a to b (not inclusive b)
869    
870 persson 2246 if (region->KeyRange.high >= b) {
871 persson 1262 // not found the current gap yet, just continue
872 schoenebeck 1225 } else {
873 persson 1262
874 persson 2246 if (a > l) {
875 persson 1262 // this gap is too far to the right, break
876     break;
877     }
878    
879 persson 2246 int newhigh = std::min(l + regionsize, b - 1);
880     int newlo = newhigh - regionsize;
881 persson 1262
882     if (newlo >= a) {
883     // yes it fits - it's a candidate
884 persson 2246 new_l = newlo;
885 persson 1262 }
886 schoenebeck 1225 }
887 persson 1262 if (!r) break;
888     a = r->KeyRange.high + 1;
889     }
890     }
891     } else {
892 persson 1623 for (gig::Region* r = regions.first() ; ; r = regions.next()) {
893 persson 1262 if (r != region) {
894     int b = r ? r->KeyRange.low : 128;
895    
896     // gap from a to b (not inclusive b)
897    
898 persson 2246 if (l + regionsize >= b) {
899 persson 1262 // not found the current gap yet, just continue
900 schoenebeck 1225 } else {
901 persson 1262
902 persson 2246 if (a > region->KeyRange.low) {
903 persson 1262 // this gap is too far to the right, break
904     break;
905     }
906    
907 persson 2246 int newlo = std::max(l, a);
908     int newhigh = newlo + regionsize;
909 persson 1262
910     if (newhigh < b) {
911     // yes it fits - break as the first one is the best
912 persson 2246 new_l = newlo;
913 persson 1262 break;
914     }
915 schoenebeck 1225 }
916 persson 1262 if (!r) break;
917     a = r->KeyRange.high + 1;
918 schoenebeck 1225 }
919     }
920 persson 1262 }
921 persson 2246 if (new_l == region->KeyRange.low) return;
922 persson 1262
923 persson 2246 int x1 = key_to_x(std::min(int(region->KeyRange.low), new_l), w);
924     int x2 = key_to_x(std::max(int(region->KeyRange.high),
925     new_l + regionsize) + 1, w) + 1;
926 persson 2169
927 persson 2246 Gdk::Rectangle rect(x1, 0, x2 - x1, h1);
928     update_after_move(new_l);
929 persson 1262
930 persson 2246 get_window()->invalidate_rect(rect, false);
931 persson 1262 }
932    
933    
934     bool RegionChooser::on_motion_notify_event(GdkEventMotion* event)
935     {
936     Glib::RefPtr<Gdk::Window> window = get_window();
937     int x, y;
938     Gdk::ModifierType state = Gdk::ModifierType(0);
939     window->get_pointer(x, y, state);
940    
941 schoenebeck 1661 // handle virtual MIDI keyboard
942     if (m_VirtKeybModeChoice.get_value() != VIRT_KEYBOARD_MODE_CHORD &&
943     currentActiveKey > 0 &&
944     event->y >= REGION_BLOCK_HEIGHT &&
945     event->y < REGION_BLOCK_HEIGHT + KEYBOARD_HEIGHT)
946     {
947 persson 2246 const int k = x_to_key(event->x, get_width() - 1);
948 persson 1898 if (k != currentActiveKey) {
949     int velocity =
950     (event->y >= REGION_BLOCK_HEIGHT + KEYBOARD_HEIGHT - 1) ? 127 :
951     int(float(event->y - REGION_BLOCK_HEIGHT) /
952     float(KEYBOARD_HEIGHT) * 128.0f) + 1;
953     if (velocity <= 0) velocity = 1;
954     keyboard_key_released_signal.emit(currentActiveKey, velocity);
955     currentActiveKey = k;
956     keyboard_key_hit_signal.emit(k, velocity);
957     }
958 schoenebeck 1661 }
959    
960 persson 1262 if (resize.active) {
961     motion_resize_region(x, y);
962     } else if (move.active) {
963     motion_move_region(x, y);
964     } else {
965 schoenebeck 1225 if (is_in_resize_zone(x, y)) {
966     if (!cursor_is_resize) {
967 persson 2169 #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
968 persson 1262 window->set_cursor(Gdk::Cursor(Gdk::SB_H_DOUBLE_ARROW));
969 persson 2169 #else
970     window->set_cursor(Gdk::Cursor::create(Gdk::SB_H_DOUBLE_ARROW));
971     #endif
972 schoenebeck 1225 cursor_is_resize = true;
973     }
974     } else if (cursor_is_resize) {
975     window->set_cursor();
976     cursor_is_resize = false;
977     }
978     }
979    
980     return true;
981     }
982    
983     bool RegionChooser::is_in_resize_zone(double x, double y) {
984 persson 1623 const int w = get_width() - 1;
985 schoenebeck 1225
986     if (instrument && y >= 0 && y <= h1) {
987     gig::Region* prev_region = 0;
988     gig::Region* next_region;
989 persson 1623 for (gig::Region* r = regions.first(); r ; r = next_region) {
990     next_region = regions.next();
991 schoenebeck 1225
992 persson 2246 int lo = key_to_x(r->KeyRange.low, w);
993 schoenebeck 1225 if (x <= lo - 2) break;
994     if (x < lo + 2) {
995     resize.region = r;
996     resize.pos = r->KeyRange.low;
997     resize.max = r->KeyRange.high;
998    
999     if (prev_region && prev_region->KeyRange.high + 1 == r->KeyRange.low) {
1000     // we don't know yet if it's the high limit of
1001     // prev_region or the low limit of r that's going
1002     // to be edited
1003     resize.mode = resize.undecided;
1004     resize.min = prev_region->KeyRange.low + 1;
1005     resize.prev_region = prev_region;
1006 persson 1623 return resize.min != resize.max;
1007 schoenebeck 1225 }
1008    
1009     // edit low limit
1010     resize.mode = resize.moving_low_limit;
1011     resize.min = prev_region ? prev_region->KeyRange.high + 1 : 0;
1012 persson 1623 return resize.min != resize.max;
1013 schoenebeck 1225 }
1014     if (!next_region || r->KeyRange.high + 1 != next_region->KeyRange.low) {
1015 persson 2246 int hi = key_to_x(r->KeyRange.high + 1, w);
1016 schoenebeck 1225 if (x <= hi - 2) break;
1017     if (x < hi + 2) {
1018     // edit high limit
1019     resize.region = r;
1020     resize.pos = r->KeyRange.high + 1;
1021     resize.mode = resize.moving_high_limit;
1022     resize.min = r->KeyRange.low + 1;
1023     resize.max = next_region ? next_region->KeyRange.low : 128;
1024 persson 1623 return resize.min != resize.max;
1025 schoenebeck 1225 }
1026     }
1027     prev_region = r;
1028     }
1029     }
1030     return false;
1031     }
1032    
1033 schoenebeck 1339 sigc::signal<void>& RegionChooser::signal_region_selected()
1034 schoenebeck 1225 {
1035 persson 1261 return region_selected;
1036 schoenebeck 1225 }
1037    
1038 schoenebeck 1339 sigc::signal<void>& RegionChooser::signal_instrument_changed()
1039 persson 1261 {
1040     return instrument_changed;
1041     }
1042    
1043 schoenebeck 1225 void RegionChooser::show_region_properties()
1044     {
1045     if (!region) return;
1046 persson 1831 Gtk::Dialog dialog(_("Region Properties"), true /*modal*/);
1047 schoenebeck 1225 // add "Keygroup" checkbox
1048 persson 1831 Gtk::CheckButton checkBoxKeygroup(_("Member of a Keygroup (Exclusive Group)"));
1049 schoenebeck 1225 checkBoxKeygroup.set_active(region->KeyGroup);
1050     dialog.get_vbox()->pack_start(checkBoxKeygroup);
1051     checkBoxKeygroup.show();
1052     // add "Keygroup" spinbox
1053 persson 2169 #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
1054     Gtk::Adjustment adjustment(1, 1, 999);
1055 schoenebeck 1225 Gtk::SpinButton spinBox(adjustment);
1056 persson 2169 #else
1057     Gtk::SpinButton spinBox(Gtk::Adjustment::create(1, 1, 999));
1058     #endif
1059 schoenebeck 1225 if (region->KeyGroup) spinBox.set_value(region->KeyGroup);
1060     dialog.get_vbox()->pack_start(spinBox);
1061     spinBox.show();
1062     // add OK and CANCEL buttons to the dialog
1063 persson 2845 dialog.add_button(_("_OK"), 0);
1064     dialog.add_button(_("_Cancel"), 1);
1065 schoenebeck 1225 dialog.show_all_children();
1066     if (!dialog.run()) { // OK selected ...
1067     region->KeyGroup =
1068     (checkBoxKeygroup.get_active()) ? spinBox.get_value_as_int() : 0;
1069     }
1070     }
1071    
1072     void RegionChooser::add_region()
1073     {
1074 schoenebeck 1322 instrument_struct_to_be_changed_signal.emit(instrument);
1075    
1076 schoenebeck 1225 region = instrument->AddRegion();
1077 schoenebeck 1336 region->SetKeyRange(new_region_pos, new_region_pos);
1078 schoenebeck 1225
1079 schoenebeck 1322 instrument_struct_changed_signal.emit(instrument);
1080 persson 1623 regions.update(instrument);
1081 schoenebeck 1322
1082 schoenebeck 1225 queue_draw();
1083 persson 1261 region_selected();
1084 persson 1677 dimensionManager.set_region(region);
1085 persson 1261 instrument_changed();
1086 schoenebeck 1225 }
1087    
1088     void RegionChooser::delete_region()
1089     {
1090 schoenebeck 1322 instrument_struct_to_be_changed_signal.emit(instrument);
1091 schoenebeck 1225 instrument->DeleteRegion(region);
1092 schoenebeck 1322 instrument_struct_changed_signal.emit(instrument);
1093 persson 1623 regions.update(instrument);
1094 schoenebeck 1322
1095 schoenebeck 1225 region = 0;
1096     queue_draw();
1097 persson 1261 region_selected();
1098 persson 1677 dimensionManager.set_region(region);
1099 persson 1261 instrument_changed();
1100 schoenebeck 1225 }
1101    
1102     void RegionChooser::manage_dimensions()
1103     {
1104     gig::Region* region = get_region();
1105     if (!region) return;
1106     dimensionManager.show(region);
1107     }
1108    
1109     void RegionChooser::on_dimension_manager_changed() {
1110 persson 1261 region_selected();
1111     instrument_changed();
1112 schoenebeck 1225 }
1113 schoenebeck 1322
1114 schoenebeck 1339 sigc::signal<void, gig::Instrument*>& RegionChooser::signal_instrument_struct_to_be_changed() {
1115 schoenebeck 1322 return instrument_struct_to_be_changed_signal;
1116     }
1117    
1118 schoenebeck 1339 sigc::signal<void, gig::Instrument*>& RegionChooser::signal_instrument_struct_changed() {
1119 schoenebeck 1322 return instrument_struct_changed_signal;
1120     }
1121    
1122 schoenebeck 1339 sigc::signal<void, gig::Region*>& RegionChooser::signal_region_to_be_changed() {
1123 schoenebeck 1322 return region_to_be_changed_signal;
1124     }
1125    
1126 schoenebeck 1339 sigc::signal<void, gig::Region*>& RegionChooser::signal_region_changed_signal() {
1127 schoenebeck 1322 return region_changed_signal;
1128     }
1129 schoenebeck 1660
1130     sigc::signal<void, int/*key*/, int/*velocity*/>& RegionChooser::signal_keyboard_key_hit() {
1131     return keyboard_key_hit_signal;
1132     }
1133    
1134     sigc::signal<void, int/*key*/, int/*velocity*/>& RegionChooser::signal_keyboard_key_released() {
1135     return keyboard_key_released_signal;
1136     }

  ViewVC Help
Powered by ViewVC