/[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 3307 - (hide annotations) (download)
Tue Jul 11 23:06:38 2017 UTC (6 years, 10 months ago) by schoenebeck
File size: 39511 byte(s)
* Fixed loop and sample reference icons being displayed
  incorrectly sometimes, because unused dimension regions
  were not ignored.
* Bumped version (1.0.0.svn57).

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

  ViewVC Help
Powered by ViewVC