1 |
/* |
/* |
2 |
* Copyright (C) 2006-2014 Andreas Persson |
* Copyright (C) 2006-2017 Andreas Persson |
3 |
* |
* |
4 |
* This program is free software; you can redistribute it and/or |
* This program is free software; you can redistribute it and/or |
5 |
* modify it under the terms of the GNU General Public License as |
* modify it under the terms of the GNU General Public License as |
17 |
* 02110-1301 USA. |
* 02110-1301 USA. |
18 |
*/ |
*/ |
19 |
|
|
20 |
|
#include "compat.h" |
21 |
|
#include "global.h" |
22 |
#include "regionchooser.h" |
#include "regionchooser.h" |
23 |
|
|
24 |
#include <algorithm> |
#include <algorithm> |
25 |
|
#include <assert.h> |
26 |
|
|
27 |
#include <cairomm/context.h> |
#include <cairomm/context.h> |
28 |
#include <gdkmm/general.h> |
#include <gdkmm/general.h> |
29 |
|
#if HAS_GDKMM_SEAT |
30 |
|
# include <gdkmm/seat.h> |
31 |
|
#endif |
32 |
#include <gdkmm/cursor.h> |
#include <gdkmm/cursor.h> |
33 |
#include <gtkmm/stock.h> |
#if HAS_GTKMM_STOCK |
34 |
|
# include <gtkmm/stock.h> |
35 |
|
#endif |
36 |
|
#include <gdkmm/pixbuf.h> |
37 |
#include <gtkmm/spinbutton.h> |
#include <gtkmm/spinbutton.h> |
38 |
#include <gtkmm/dialog.h> |
#include <gtkmm/dialog.h> |
39 |
|
|
40 |
#include "global.h" |
#include "Settings.h" |
41 |
|
#include "gfx/builtinpix.h" |
42 |
|
|
43 |
#define REGION_BLOCK_HEIGHT 20 |
#define REGION_BLOCK_HEIGHT 30 |
44 |
#define KEYBOARD_HEIGHT 40 |
#define KEYBOARD_HEIGHT 40 |
45 |
|
|
46 |
|
struct RegionFeatures { |
47 |
|
int sampleRefs; |
48 |
|
int loops; |
49 |
|
int validDimRegs; |
50 |
|
|
51 |
|
RegionFeatures() { |
52 |
|
sampleRefs = loops = validDimRegs = 0; |
53 |
|
} |
54 |
|
}; |
55 |
|
|
56 |
|
static RegionFeatures regionFeatures(gig::Region* rgn) { |
57 |
|
RegionFeatures f; |
58 |
|
for (int i = 0; i < rgn->DimensionRegions; ++i) { |
59 |
|
gig::DimensionRegion* dr = rgn->pDimensionRegions[i]; |
60 |
|
DimensionCase c = dimensionCaseOf(dr); |
61 |
|
if (!isUsedCase(c, rgn)) continue; |
62 |
|
f.validDimRegs++; |
63 |
|
if (dr->pSample) f.sampleRefs++; |
64 |
|
// the user doesn't care about loop if there is no valid sample reference |
65 |
|
if (dr->pSample && dr->SampleLoops) f.loops++; |
66 |
|
} |
67 |
|
return f; |
68 |
|
} |
69 |
|
|
70 |
void SortedRegions::update(gig::Instrument* instrument) { |
void SortedRegions::update(gig::Instrument* instrument) { |
71 |
// Usually, the regions in a gig file are ordered after their key |
// Usually, the regions in a gig file are ordered after their key |
72 |
// range, but there are files where they are not. The |
// range, but there are files where they are not. The |
88 |
} |
} |
89 |
|
|
90 |
gig::Region* SortedRegions::next() { |
gig::Region* SortedRegions::next() { |
91 |
region_iterator++; |
++region_iterator; |
92 |
return region_iterator == regions.end() ? 0 : *region_iterator; |
return region_iterator == regions.end() ? 0 : *region_iterator; |
93 |
} |
} |
94 |
|
|
96 |
|
|
97 |
RegionChooser::RegionChooser() : |
RegionChooser::RegionChooser() : |
98 |
activeKeyColor("red"), |
activeKeyColor("red"), |
99 |
red("#8070ff"), |
blue("#4796ff"), |
100 |
grey1("grey69"), |
grey1("grey69"), |
101 |
white("white"), |
white("white"), |
102 |
black("black"), |
black("black"), |
103 |
m_VirtKeybModeChoice(_("Virtual Keyboard Mode")), |
m_VirtKeybModeChoice(_("Virtual Keyboard Mode")), |
104 |
currentActiveKey(-1) |
currentActiveKey(-1), |
105 |
|
modifyallregions(false) |
106 |
{ |
{ |
107 |
set_size_request(500, KEYBOARD_HEIGHT + REGION_BLOCK_HEIGHT); |
set_size_request(500, KEYBOARD_HEIGHT + REGION_BLOCK_HEIGHT); |
108 |
|
|
109 |
|
loadBuiltInPix(); |
110 |
|
|
111 |
|
// create blue hatched pattern |
112 |
|
{ |
113 |
|
const int width = blueHatchedPattern->get_width(); |
114 |
|
const int height = blueHatchedPattern->get_height(); |
115 |
|
const int stride = blueHatchedPattern->get_rowstride(); |
116 |
|
|
117 |
|
// manually convert from RGBA to ARGB |
118 |
|
this->blueHatchedPatternARGB = blueHatchedPattern->copy(); |
119 |
|
const int pixelSize = stride / width; |
120 |
|
const int totalPixels = width * height; |
121 |
|
assert(pixelSize == 4); |
122 |
|
unsigned char* ptr = this->blueHatchedPatternARGB->get_pixels(); |
123 |
|
for (int iPixel = 0; iPixel < totalPixels; ++iPixel, ptr += pixelSize) { |
124 |
|
const unsigned char r = ptr[0]; |
125 |
|
const unsigned char g = ptr[1]; |
126 |
|
const unsigned char b = ptr[2]; |
127 |
|
const unsigned char a = ptr[3]; |
128 |
|
ptr[0] = b; |
129 |
|
ptr[1] = g; |
130 |
|
ptr[2] = r; |
131 |
|
ptr[3] = a; |
132 |
|
} |
133 |
|
|
134 |
|
Cairo::RefPtr<Cairo::ImageSurface> imageSurface = Cairo::ImageSurface::create( |
135 |
|
#if HAS_CAIROMM_CPP11_ENUMS |
136 |
|
this->blueHatchedPatternARGB->get_pixels(), Cairo::Surface::Format::ARGB32, width, height, stride |
137 |
|
#else |
138 |
|
this->blueHatchedPatternARGB->get_pixels(), Cairo::FORMAT_ARGB32, width, height, stride |
139 |
|
#endif |
140 |
|
); |
141 |
|
this->blueHatchedSurfacePattern = Cairo::SurfacePattern::create(imageSurface); |
142 |
|
#if HAS_CAIROMM_CPP11_ENUMS |
143 |
|
this->blueHatchedSurfacePattern->set_extend(Cairo::Pattern::Extend::REPEAT); |
144 |
|
#else |
145 |
|
this->blueHatchedSurfacePattern->set_extend(Cairo::EXTEND_REPEAT); |
146 |
|
#endif |
147 |
|
} |
148 |
|
|
149 |
instrument = 0; |
instrument = 0; |
150 |
region = 0; |
region = 0; |
151 |
resize.active = false; |
resize.active = false; |
177 |
m_VirtKeybPropsBox.show(); |
m_VirtKeybPropsBox.show(); |
178 |
for (int i = 0 ; i < 128 ; i++) key_pressed[i] = false; |
for (int i = 0 ; i < 128 ; i++) key_pressed[i] = false; |
179 |
|
|
180 |
actionGroup = Gtk::ActionGroup::create(); |
actionGroup = ActionGroup::create(); |
181 |
|
#if USE_GLIB_ACTION |
182 |
|
actionGroup->add_action( |
183 |
|
"Properties", sigc::mem_fun(*this, &RegionChooser::show_region_properties) |
184 |
|
); |
185 |
|
actionGroup->add_action( |
186 |
|
"Remove", sigc::mem_fun(*this, &RegionChooser::delete_region) |
187 |
|
); |
188 |
|
actionGroup->add_action( |
189 |
|
"Add", sigc::mem_fun(*this, &RegionChooser::add_region) |
190 |
|
); |
191 |
|
actionGroup->add_action( |
192 |
|
"Dimensions", sigc::mem_fun(*this, &RegionChooser::manage_dimensions) |
193 |
|
); |
194 |
|
insert_action_group("PopupMenuInsideRegion", actionGroup); |
195 |
|
#else |
196 |
actionGroup->add(Gtk::Action::create("Properties", |
actionGroup->add(Gtk::Action::create("Properties", |
197 |
Gtk::Stock::PROPERTIES), |
Gtk::Stock::PROPERTIES), |
198 |
sigc::mem_fun(*this, |
sigc::mem_fun(*this, |
203 |
sigc::mem_fun(*this, &RegionChooser::add_region)); |
sigc::mem_fun(*this, &RegionChooser::add_region)); |
204 |
actionGroup->add(Gtk::Action::create("Dimensions", _("Dimensions...")), |
actionGroup->add(Gtk::Action::create("Dimensions", _("Dimensions...")), |
205 |
sigc::mem_fun(*this, &RegionChooser::manage_dimensions)); |
sigc::mem_fun(*this, &RegionChooser::manage_dimensions)); |
206 |
|
#endif |
207 |
|
|
208 |
|
#if USE_GTKMM_BUILDER |
209 |
|
uiManager = Gtk::Builder::create(); |
210 |
|
Glib::ustring ui_info = |
211 |
|
"<interface>" |
212 |
|
" <menu id='menu-PopupMenuInsideRegion'>" |
213 |
|
" <section>" |
214 |
|
" <item>" |
215 |
|
" <attribute name='label' translatable='yes'>Properties</attribute>" |
216 |
|
" <attribute name='action'>PopupMenuInsideRegion.Properties</attribute>" |
217 |
|
" </item>" |
218 |
|
" <item>" |
219 |
|
" <attribute name='label' translatable='yes'>Dimensions</attribute>" |
220 |
|
" <attribute name='action'>PopupMenuInsideRegion.Dimensions</attribute>" |
221 |
|
" </item>" |
222 |
|
" <item>" |
223 |
|
" <attribute name='label' translatable='yes'>Remove</attribute>" |
224 |
|
" <attribute name='action'>PopupMenuInsideRegion.Remove</attribute>" |
225 |
|
" </item>" |
226 |
|
" </section>" |
227 |
|
" </menu>" |
228 |
|
" <menu id='menu-PopupMenuOutsideRegion'>" |
229 |
|
" <section>" |
230 |
|
" <item>" |
231 |
|
" <attribute name='label' translatable='yes'>Add</attribute>" |
232 |
|
" <attribute name='action'>PopupMenuInsideRegion.Add</attribute>" |
233 |
|
" </item>" |
234 |
|
" </section>" |
235 |
|
" </menu>" |
236 |
|
"</interface>"; |
237 |
|
uiManager->add_from_string(ui_info); |
238 |
|
|
239 |
|
popup_menu_inside_region = new Gtk::Menu( |
240 |
|
Glib::RefPtr<Gio::Menu>::cast_dynamic( |
241 |
|
uiManager->get_object("menu-PopupMenuInsideRegion") |
242 |
|
) |
243 |
|
); |
244 |
|
popup_menu_outside_region = new Gtk::Menu( |
245 |
|
Glib::RefPtr<Gio::Menu>::cast_dynamic( |
246 |
|
uiManager->get_object("menu-PopupMenuOutsideRegion") |
247 |
|
) |
248 |
|
); |
249 |
|
#else |
250 |
uiManager = Gtk::UIManager::create(); |
uiManager = Gtk::UIManager::create(); |
251 |
uiManager->insert_action_group(actionGroup); |
uiManager->insert_action_group(actionGroup); |
252 |
Glib::ustring ui_info = |
Glib::ustring ui_info = |
267 |
popup_menu_outside_region = dynamic_cast<Gtk::Menu*>( |
popup_menu_outside_region = dynamic_cast<Gtk::Menu*>( |
268 |
uiManager->get_widget("/PopupMenuOutsideRegion")); |
uiManager->get_widget("/PopupMenuOutsideRegion")); |
269 |
|
|
270 |
|
#endif // USE_GTKMM_BUILDER |
271 |
|
|
272 |
|
#if GTKMM_MAJOR_VERSION > 3 || (GTKMM_MAJOR_VERSION == 3 && GTKMM_MINOR_VERSION > 22) |
273 |
|
# warning GTKMM4 event registration code missing for regionchooser! |
274 |
|
//add_events(Gdk::EventMask::BUTTON_PRESS_MASK); |
275 |
|
#else |
276 |
add_events(Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK | |
add_events(Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK | |
277 |
Gdk::POINTER_MOTION_MASK | Gdk::POINTER_MOTION_HINT_MASK); |
Gdk::POINTER_MOTION_MASK | Gdk::POINTER_MOTION_HINT_MASK); |
278 |
|
#endif |
279 |
|
|
280 |
dimensionManager.region_to_be_changed_signal.connect( |
dimensionManager.region_to_be_changed_signal.connect( |
281 |
region_to_be_changed_signal.make_slot() |
region_to_be_changed_signal.make_slot() |
301 |
{ |
{ |
302 |
} |
} |
303 |
|
|
304 |
|
void RegionChooser::setModifyAllRegions(bool b) { |
305 |
|
modifyallregions = b; |
306 |
|
// redraw required parts |
307 |
|
queue_draw(); |
308 |
|
} |
309 |
|
|
310 |
void RegionChooser::invalidate_key(int key) { |
void RegionChooser::invalidate_key(int key) { |
311 |
const int h = KEYBOARD_HEIGHT; |
const int h = KEYBOARD_HEIGHT; |
312 |
const int w = get_width() - 1; |
const int w = get_width() - 1; |
354 |
#if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2 |
#if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2 |
355 |
const Gdk::Color bg = get_style()->get_bg(Gtk::STATE_NORMAL); |
const Gdk::Color bg = get_style()->get_bg(Gtk::STATE_NORMAL); |
356 |
#else |
#else |
357 |
|
#if GTKMM_MAJOR_VERSION > 3 || (GTKMM_MAJOR_VERSION == 3 && GTKMM_MINOR_VERSION > 22) |
358 |
|
GdkRGBA gdkBgRGBA; |
359 |
|
gtk_style_context_get_background_color(get_style_context()->gobj(), &gdkBgRGBA); |
360 |
|
const Gdk::RGBA bg = Glib::wrap(&gdkBgRGBA, true); |
361 |
|
# else |
362 |
const Gdk::RGBA bg = get_style_context()->get_background_color(); |
const Gdk::RGBA bg = get_style_context()->get_background_color(); |
363 |
|
# endif |
364 |
#endif |
#endif |
365 |
Gdk::Cairo::set_source_rgba(cr, bg); |
Gdk::Cairo::set_source_rgba(cr, bg); |
366 |
cr->paint(); |
cr->paint(); |
463 |
cr->line_to(x3, h1 - 0.5); |
cr->line_to(x3, h1 - 0.5); |
464 |
cr->stroke(); |
cr->stroke(); |
465 |
|
|
466 |
Gdk::Cairo::set_source_rgba(cr, region == r ? red : white); |
if (region == r) |
467 |
|
Gdk::Cairo::set_source_rgba(cr, blue); |
468 |
|
else if (modifyallregions) |
469 |
|
cr->set_source(blueHatchedSurfacePattern); |
470 |
|
else |
471 |
|
Gdk::Cairo::set_source_rgba(cr, white); |
472 |
|
|
473 |
cr->rectangle(x3 + 1, 1, x2 - x3 - 1, h1 - 2); |
cr->rectangle(x3 + 1, 1, x2 - x3 - 1, h1 - 2); |
474 |
cr->fill(); |
cr->fill(); |
475 |
Gdk::Cairo::set_source_rgba(cr, black); |
Gdk::Cairo::set_source_rgba(cr, black); |
480 |
|
|
481 |
for (gig::Region* r = regions.first() ; r ; r = regions.next()) { |
for (gig::Region* r = regions.first() ; r ; r = regions.next()) { |
482 |
int x = key_to_x(r->KeyRange.low, w); |
int x = key_to_x(r->KeyRange.low, w); |
483 |
|
int x2 = key_to_x(r->KeyRange.high + 1, w); |
484 |
|
|
485 |
|
RegionFeatures features = regionFeatures(r); |
486 |
|
|
487 |
|
const bool bShowLoopSymbol = features.loops > 0; |
488 |
|
const bool bShowSampleRefSymbol = features.sampleRefs < features.validDimRegs; |
489 |
|
if (bShowLoopSymbol || bShowSampleRefSymbol) { |
490 |
|
const int margin = 2; |
491 |
|
const int wRgn = x2 - x; |
492 |
|
//printf("x=%d x2=%d wRgn=%d\n", x, x2, wRgn); |
493 |
|
|
494 |
|
cr->save(); |
495 |
|
cr->set_line_width(1); |
496 |
|
cr->rectangle(x, 1, wRgn, h1 - 1); |
497 |
|
cr->clip(); |
498 |
|
if (bShowSampleRefSymbol) { |
499 |
|
const int wPic = 8; |
500 |
|
const int hPic = 8; |
501 |
|
Gdk::Cairo::set_source_pixbuf( |
502 |
|
cr, (features.sampleRefs) ? yellowDot : redDot, |
503 |
|
x + (wRgn-wPic)/2.f, |
504 |
|
(bShowLoopSymbol) ? margin : (h1-hPic)/2.f |
505 |
|
); |
506 |
|
cr->paint(); |
507 |
|
} |
508 |
|
if (bShowLoopSymbol) { |
509 |
|
const int wPic = 12; |
510 |
|
const int hPic = 14; |
511 |
|
Gdk::Cairo::set_source_pixbuf( |
512 |
|
cr, (features.loops == features.validDimRegs) ? blackLoop : grayLoop, |
513 |
|
x + (wRgn-wPic)/2.f, |
514 |
|
(bShowSampleRefSymbol) ? h1 - hPic - margin : (h1-hPic)/2.f |
515 |
|
); |
516 |
|
cr->paint(); |
517 |
|
} |
518 |
|
cr->restore(); |
519 |
|
} |
520 |
|
} |
521 |
|
|
522 |
|
for (gig::Region* r = regions.first() ; r ; r = regions.next()) { |
523 |
|
int x = key_to_x(r->KeyRange.low, w); |
524 |
|
|
525 |
if (x < clip_low) continue; |
if (x < clip_low) continue; |
526 |
if (x >= clip_high) break; |
if (x >= clip_high) break; |
538 |
layout->set_alignment(Pango::ALIGN_CENTER); |
layout->set_alignment(Pango::ALIGN_CENTER); |
539 |
layout->set_text(Glib::ustring("*** ") + _("Right click here to create a region.") + " ***"); |
layout->set_text(Glib::ustring("*** ") + _("Right click here to create a region.") + " ***"); |
540 |
layout->set_width(get_width() * Pango::SCALE); |
layout->set_width(get_width() * Pango::SCALE); |
541 |
Gdk::Cairo::set_source_rgba(cr, red); |
//layout->set_height(get_height() * Pango::SCALE); |
542 |
|
layout->set_spacing(10); |
543 |
|
Gdk::Cairo::set_source_rgba(cr, blue); |
544 |
|
// get the text dimensions |
545 |
|
int text_width, text_height; |
546 |
|
layout->get_pixel_size(text_width, text_height); |
547 |
|
cr->move_to(0, (REGION_BLOCK_HEIGHT - text_height) / 2); |
548 |
#if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 16) || GTKMM_MAJOR_VERSION < 2 |
#if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 16) || GTKMM_MAJOR_VERSION < 2 |
549 |
pango_cairo_show_layout(cr->cobj(), layout->gobj()); |
pango_cairo_show_layout(cr->cobj(), layout->gobj()); |
550 |
#else |
#else |
659 |
#if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2 |
#if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2 |
660 |
get_window()->pointer_ungrab(event->time); |
get_window()->pointer_ungrab(event->time); |
661 |
#else |
#else |
662 |
|
# if GTKMM_MAJOR_VERSION < 3 || (GTKMM_MAJOR_VERSION == 3 && GTKMM_MINOR_VERSION < 20) |
663 |
Glib::wrap(event->device, true)->ungrab(event->time); |
Glib::wrap(event->device, true)->ungrab(event->time); |
664 |
|
# else |
665 |
|
gdk_device_ungrab(Glib::wrap(event->device, true)->gobj(), event->time); |
666 |
|
# endif |
667 |
#endif |
#endif |
668 |
resize.active = false; |
resize.active = false; |
669 |
|
|
675 |
#if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2 |
#if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2 |
676 |
get_window()->pointer_ungrab(event->time); |
get_window()->pointer_ungrab(event->time); |
677 |
#else |
#else |
678 |
|
# if GTKMM_MAJOR_VERSION < 3 || (GTKMM_MAJOR_VERSION == 3 && GTKMM_MINOR_VERSION < 20) |
679 |
Glib::wrap(event->device, true)->ungrab(event->time); |
Glib::wrap(event->device, true)->ungrab(event->time); |
680 |
|
# else |
681 |
|
gdk_device_ungrab(Glib::wrap(event->device, true)->gobj(), event->time); |
682 |
|
# endif |
683 |
#endif |
#endif |
684 |
move.active = false; |
move.active = false; |
685 |
|
|
687 |
#if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2 |
#if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2 |
688 |
get_window()->set_cursor(Gdk::Cursor(Gdk::SB_H_DOUBLE_ARROW)); |
get_window()->set_cursor(Gdk::Cursor(Gdk::SB_H_DOUBLE_ARROW)); |
689 |
#else |
#else |
690 |
get_window()->set_cursor(Gdk::Cursor::create(Gdk::SB_H_DOUBLE_ARROW)); |
get_window()->set_cursor( |
691 |
|
# if GTKMM_MAJOR_VERSION < 3 || (GTKMM_MAJOR_VERSION == 3 && GTKMM_MINOR_VERSION < 20) |
692 |
|
Gdk::Cursor::create(Gdk::SB_H_DOUBLE_ARROW) |
693 |
|
# else |
694 |
|
Gdk::Cursor::create( |
695 |
|
Glib::wrap(event->device, true)->get_seat()->get_display(), |
696 |
|
Gdk::SB_H_DOUBLE_ARROW |
697 |
|
) |
698 |
|
# endif |
699 |
|
); |
700 |
#endif |
#endif |
701 |
cursor_is_resize = true; |
cursor_is_resize = true; |
702 |
} |
} |
730 |
void RegionChooser::update_after_move(int pos) |
void RegionChooser::update_after_move(int pos) |
731 |
{ |
{ |
732 |
instrument_struct_to_be_changed_signal.emit(instrument); |
instrument_struct_to_be_changed_signal.emit(instrument); |
733 |
region->SetKeyRange(pos, pos + region->KeyRange.high - |
const int range = region->KeyRange.high - region->KeyRange.low; |
734 |
region->KeyRange.low); |
const int diff = pos - int(region->KeyRange.low); |
735 |
|
region->SetKeyRange(pos, pos + range); |
736 |
|
if (Settings::singleton()->moveRootNoteWithRegionMoved) { |
737 |
|
for (int i = 0; i < 256; ++i) { |
738 |
|
gig::DimensionRegion* dimrgn = region->pDimensionRegions[i]; |
739 |
|
if (!dimrgn || !dimrgn->pSample || !dimrgn->PitchTrack) continue; |
740 |
|
dimrgn->UnityNote += diff; |
741 |
|
} |
742 |
|
} |
743 |
regions.update(instrument); |
regions.update(instrument); |
744 |
instrument_changed.emit(); |
instrument_changed.emit(); |
745 |
instrument_struct_changed_signal.emit(instrument); |
instrument_struct_changed_signal.emit(instrument); |
761 |
} |
} |
762 |
} |
} |
763 |
|
|
764 |
|
// left mouse button double click |
765 |
|
if (event->type == GDK_2BUTTON_PRESS && event->button == 1) { |
766 |
|
if (event->y < REGION_BLOCK_HEIGHT) { |
767 |
|
// show dimension manager dialog for this region |
768 |
|
manage_dimensions(); |
769 |
|
} |
770 |
|
} |
771 |
|
|
772 |
if (event->y >= REGION_BLOCK_HEIGHT) return true; |
if (event->y >= REGION_BLOCK_HEIGHT) return true; |
773 |
if (event->type == GDK_BUTTON_PRESS && event->button == 3) { |
if (event->type == GDK_BUTTON_PRESS && event->button == 3) { |
774 |
gig::Region* r = get_region(k); |
gig::Region* r = get_region(k); |
792 |
Gdk::Cursor(Gdk::SB_H_DOUBLE_ARROW), |
Gdk::Cursor(Gdk::SB_H_DOUBLE_ARROW), |
793 |
event->time); |
event->time); |
794 |
#else |
#else |
795 |
|
# if GTKMM_MAJOR_VERSION < 3 || (GTKMM_MAJOR_VERSION == 3 && GTKMM_MINOR_VERSION < 20) |
796 |
Glib::wrap(event->device, true)->grab(get_window(), |
Glib::wrap(event->device, true)->grab(get_window(), |
797 |
Gdk::OWNERSHIP_NONE, |
Gdk::OWNERSHIP_NONE, |
798 |
false, |
false, |
801 |
Gdk::POINTER_MOTION_HINT_MASK, |
Gdk::POINTER_MOTION_HINT_MASK, |
802 |
Gdk::Cursor::create(Gdk::SB_H_DOUBLE_ARROW), |
Gdk::Cursor::create(Gdk::SB_H_DOUBLE_ARROW), |
803 |
event->time); |
event->time); |
804 |
|
# else |
805 |
|
gdk_device_grab( |
806 |
|
Glib::wrap(event->device, true)->gobj(), |
807 |
|
get_window()->gobj(), |
808 |
|
GDK_OWNERSHIP_NONE, |
809 |
|
false, |
810 |
|
GdkEventMask(GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK | |
811 |
|
GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON1_MOTION_MASK), |
812 |
|
Gdk::Cursor::create( |
813 |
|
Glib::wrap(event->device, true)->get_seat()->get_display(), |
814 |
|
Gdk::SB_H_DOUBLE_ARROW |
815 |
|
)->gobj(), |
816 |
|
event->time |
817 |
|
); |
818 |
|
# endif |
819 |
#endif |
#endif |
820 |
resize.active = true; |
resize.active = true; |
821 |
} else { |
} else { |
834 |
Gdk::Cursor(Gdk::FLEUR), |
Gdk::Cursor(Gdk::FLEUR), |
835 |
event->time); |
event->time); |
836 |
#else |
#else |
837 |
Glib::wrap(event->device, true)->grab(get_window(), |
# if GTKMM_MAJOR_VERSION < 3 || (GTKMM_MAJOR_VERSION == 3 && GTKMM_MINOR_VERSION < 20) |
838 |
Gdk::OWNERSHIP_NONE, |
Glib::wrap(event->device, true)->grab(get_window(), |
839 |
false, |
Gdk::OWNERSHIP_NONE, |
840 |
Gdk::BUTTON_RELEASE_MASK | |
false, |
841 |
Gdk::POINTER_MOTION_MASK | |
Gdk::BUTTON_RELEASE_MASK | |
842 |
Gdk::POINTER_MOTION_HINT_MASK, |
Gdk::POINTER_MOTION_MASK | |
843 |
Gdk::Cursor::create(Gdk::FLEUR), |
Gdk::POINTER_MOTION_HINT_MASK, |
844 |
event->time); |
Gdk::Cursor::create(Gdk::FLEUR), |
845 |
|
event->time); |
846 |
|
# else |
847 |
|
gdk_device_grab( |
848 |
|
Glib::wrap(event->device, true)->gobj(), |
849 |
|
get_window()->gobj(), |
850 |
|
GDK_OWNERSHIP_NONE, |
851 |
|
false, |
852 |
|
GdkEventMask(GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK | |
853 |
|
GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON1_MOTION_MASK), |
854 |
|
Gdk::Cursor::create( |
855 |
|
Glib::wrap(event->device, true)->get_seat()->get_display(), |
856 |
|
Gdk::FLEUR |
857 |
|
)->gobj(), |
858 |
|
event->time |
859 |
|
); |
860 |
|
# endif |
861 |
#endif |
#endif |
862 |
move.active = true; |
move.active = true; |
863 |
move.offset = event->x - key_to_x(region->KeyRange.low, w); |
move.offset = event->x - key_to_x(region->KeyRange.low, w); |
876 |
return 0; |
return 0; |
877 |
} |
} |
878 |
|
|
879 |
|
void RegionChooser::set_region(gig::Region* region) { |
880 |
|
this->region = region; |
881 |
|
queue_draw(); |
882 |
|
region_selected(); |
883 |
|
dimensionManager.set_region(region); |
884 |
|
} |
885 |
|
|
886 |
|
void RegionChooser::select_next_region() { |
887 |
|
if (!instrument) return; |
888 |
|
if (!region) { |
889 |
|
for (int i = 0; i < 128; ++i) { |
890 |
|
::gig::Region* rgn = instrument->GetRegion(i); |
891 |
|
if (rgn) { |
892 |
|
set_region(rgn); |
893 |
|
return; |
894 |
|
} |
895 |
|
} |
896 |
|
} else { |
897 |
|
bool currentFound = false; |
898 |
|
for (int i = 0; i < 128; ++i) { |
899 |
|
::gig::Region* rgn = instrument->GetRegion(i); |
900 |
|
if (!rgn) continue; |
901 |
|
if (currentFound) { |
902 |
|
if (rgn != region) { |
903 |
|
set_region(rgn); |
904 |
|
return; |
905 |
|
} |
906 |
|
} else { |
907 |
|
if (rgn == region) currentFound = true; |
908 |
|
} |
909 |
|
} |
910 |
|
} |
911 |
|
} |
912 |
|
|
913 |
|
void RegionChooser::select_prev_region() { |
914 |
|
if (!instrument) return; |
915 |
|
if (!region) { |
916 |
|
for (int i = 0; i < 128; ++i) { |
917 |
|
::gig::Region* rgn = instrument->GetRegion(i); |
918 |
|
if (rgn) { |
919 |
|
set_region(rgn); |
920 |
|
return; |
921 |
|
} |
922 |
|
} |
923 |
|
} else { |
924 |
|
bool currentFound = false; |
925 |
|
for (int i = 127; i >= 0; --i) { |
926 |
|
::gig::Region* rgn = instrument->GetRegion(i); |
927 |
|
if (!rgn) continue; |
928 |
|
if (currentFound) { |
929 |
|
if (rgn != region) { |
930 |
|
set_region(rgn); |
931 |
|
return; |
932 |
|
} |
933 |
|
} else { |
934 |
|
if (rgn == region) currentFound = true; |
935 |
|
} |
936 |
|
} |
937 |
|
} |
938 |
|
} |
939 |
|
|
940 |
void RegionChooser::motion_resize_region(int x, int y) |
void RegionChooser::motion_resize_region(int x, int y) |
941 |
{ |
{ |
942 |
const int w = get_width() - 1; |
const int w = get_width() - 1; |
985 |
|
|
986 |
update_after_resize(); |
update_after_resize(); |
987 |
|
|
988 |
get_window()->invalidate_rect(rect, false); |
//get_window()->invalidate_rect(rect, false); |
989 |
|
get_window()->invalidate(false); // repaint entire region, otherwise it would create visual artifacts |
990 |
} |
} |
991 |
} |
} |
992 |
|
|
1075 |
{ |
{ |
1076 |
Glib::RefPtr<Gdk::Window> window = get_window(); |
Glib::RefPtr<Gdk::Window> window = get_window(); |
1077 |
int x, y; |
int x, y; |
1078 |
|
#if HAS_GDKMM_SEAT |
1079 |
|
x = event->x; |
1080 |
|
y = event->y; |
1081 |
|
Gdk::ModifierType state = Gdk::ModifierType(event->state); |
1082 |
|
#else |
1083 |
Gdk::ModifierType state = Gdk::ModifierType(0); |
Gdk::ModifierType state = Gdk::ModifierType(0); |
1084 |
window->get_pointer(x, y, state); |
window->get_pointer(x, y, state); |
1085 |
|
#endif |
1086 |
|
|
1087 |
// handle virtual MIDI keyboard |
// handle virtual MIDI keyboard |
1088 |
if (m_VirtKeybModeChoice.get_value() != VIRT_KEYBOARD_MODE_CHORD && |
if (m_VirtKeybModeChoice.get_value() != VIRT_KEYBOARD_MODE_CHORD && |
1113 |
#if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2 |
#if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2 |
1114 |
window->set_cursor(Gdk::Cursor(Gdk::SB_H_DOUBLE_ARROW)); |
window->set_cursor(Gdk::Cursor(Gdk::SB_H_DOUBLE_ARROW)); |
1115 |
#else |
#else |
1116 |
window->set_cursor(Gdk::Cursor::create(Gdk::SB_H_DOUBLE_ARROW)); |
window->set_cursor( |
1117 |
|
# if GTKMM_MAJOR_VERSION < 3 || (GTKMM_MAJOR_VERSION == 3 && GTKMM_MINOR_VERSION < 20) |
1118 |
|
Gdk::Cursor::create(Gdk::SB_H_DOUBLE_ARROW) |
1119 |
|
# else |
1120 |
|
Gdk::Cursor::create( |
1121 |
|
Glib::wrap(event->device, true)->get_seat()->get_display(), |
1122 |
|
Gdk::SB_H_DOUBLE_ARROW |
1123 |
|
) |
1124 |
|
# endif |
1125 |
|
); |
1126 |
#endif |
#endif |
1127 |
cursor_is_resize = true; |
cursor_is_resize = true; |
1128 |
} |
} |
1202 |
// add "Keygroup" checkbox |
// add "Keygroup" checkbox |
1203 |
Gtk::CheckButton checkBoxKeygroup(_("Member of a Keygroup (Exclusive Group)")); |
Gtk::CheckButton checkBoxKeygroup(_("Member of a Keygroup (Exclusive Group)")); |
1204 |
checkBoxKeygroup.set_active(region->KeyGroup); |
checkBoxKeygroup.set_active(region->KeyGroup); |
1205 |
|
#if USE_GTKMM_BOX |
1206 |
|
dialog.get_content_area()->pack_start(checkBoxKeygroup); |
1207 |
|
#else |
1208 |
dialog.get_vbox()->pack_start(checkBoxKeygroup); |
dialog.get_vbox()->pack_start(checkBoxKeygroup); |
1209 |
|
#endif |
1210 |
checkBoxKeygroup.show(); |
checkBoxKeygroup.show(); |
1211 |
// add "Keygroup" spinbox |
// add "Keygroup" spinbox |
1212 |
#if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2 |
#if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2 |
1216 |
Gtk::SpinButton spinBox(Gtk::Adjustment::create(1, 1, 999)); |
Gtk::SpinButton spinBox(Gtk::Adjustment::create(1, 1, 999)); |
1217 |
#endif |
#endif |
1218 |
if (region->KeyGroup) spinBox.set_value(region->KeyGroup); |
if (region->KeyGroup) spinBox.set_value(region->KeyGroup); |
1219 |
|
#if USE_GTKMM_BOX |
1220 |
|
dialog.get_content_area()->pack_start(spinBox); |
1221 |
|
#else |
1222 |
dialog.get_vbox()->pack_start(spinBox); |
dialog.get_vbox()->pack_start(spinBox); |
1223 |
|
#endif |
1224 |
spinBox.show(); |
spinBox.show(); |
1225 |
// add OK and CANCEL buttons to the dialog |
// add OK and CANCEL buttons to the dialog |
1226 |
|
#if HAS_GTKMM_STOCK |
1227 |
dialog.add_button(Gtk::Stock::OK, 0); |
dialog.add_button(Gtk::Stock::OK, 0); |
1228 |
dialog.add_button(Gtk::Stock::CANCEL, 1); |
dialog.add_button(Gtk::Stock::CANCEL, 1); |
1229 |
|
#else |
1230 |
|
dialog.add_button(_("_OK"), 0); |
1231 |
|
dialog.add_button(_("_Cancel"), 1); |
1232 |
|
#endif |
1233 |
|
dialog.set_position(Gtk::WIN_POS_MOUSE); |
1234 |
|
#if HAS_GTKMM_SHOW_ALL_CHILDREN |
1235 |
dialog.show_all_children(); |
dialog.show_all_children(); |
1236 |
|
#endif |
1237 |
if (!dialog.run()) { // OK selected ... |
if (!dialog.run()) { // OK selected ... |
1238 |
region->KeyGroup = |
region->KeyGroup = |
1239 |
(checkBoxKeygroup.get_active()) ? spinBox.get_value_as_int() : 0; |
(checkBoxKeygroup.get_active()) ? spinBox.get_value_as_int() : 0; |