/[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 3158 - (hide annotations) (download)
Mon May 8 18:05:35 2017 UTC (6 years, 11 months ago) by schoenebeck
File size: 39354 byte(s)
* Reverted major parts of r2845 concerning deprected Gtk StockIDs
  (StockIDs still available with Gtk 3, no replacement API available,
  and these changes caused useful icons to vanish with Gtk 2).
* Bumped version (1.0.0.svn39).

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

  ViewVC Help
Powered by ViewVC