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 > 24) |
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() |
295 |
sigc::mem_fun(*this, &RegionChooser::on_note_off_event) |
sigc::mem_fun(*this, &RegionChooser::on_note_off_event) |
296 |
); |
); |
297 |
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.")); |
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.")); |
298 |
|
|
299 |
|
Settings::singleton()->showTooltips.get_proxy().signal_changed().connect( |
300 |
|
sigc::mem_fun(*this, &RegionChooser::on_show_tooltips_changed) |
301 |
|
); |
302 |
|
|
303 |
|
on_show_tooltips_changed(); |
304 |
} |
} |
305 |
|
|
306 |
RegionChooser::~RegionChooser() |
RegionChooser::~RegionChooser() |
307 |
{ |
{ |
308 |
} |
} |
309 |
|
|
310 |
|
void RegionChooser::on_show_tooltips_changed() { |
311 |
|
const bool b = Settings::singleton()->showTooltips; |
312 |
|
|
313 |
|
set_has_tooltip(b); |
314 |
|
} |
315 |
|
|
316 |
|
void RegionChooser::setModifyAllRegions(bool b) { |
317 |
|
modifyallregions = b; |
318 |
|
// redraw required parts |
319 |
|
queue_draw(); |
320 |
|
} |
321 |
|
|
322 |
void RegionChooser::invalidate_key(int key) { |
void RegionChooser::invalidate_key(int key) { |
323 |
const int h = KEYBOARD_HEIGHT; |
const int h = KEYBOARD_HEIGHT; |
324 |
const int w = get_width() - 1; |
const int w = get_width() - 1; |
366 |
#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 |
367 |
const Gdk::Color bg = get_style()->get_bg(Gtk::STATE_NORMAL); |
const Gdk::Color bg = get_style()->get_bg(Gtk::STATE_NORMAL); |
368 |
#else |
#else |
369 |
|
#if GTKMM_MAJOR_VERSION > 3 || (GTKMM_MAJOR_VERSION == 3 && GTKMM_MINOR_VERSION > 24) |
370 |
|
GdkRGBA gdkBgRGBA; |
371 |
|
gtk_style_context_get_background_color(get_style_context()->gobj(), &gdkBgRGBA); |
372 |
|
const Gdk::RGBA bg = Glib::wrap(&gdkBgRGBA, true); |
373 |
|
# else |
374 |
const Gdk::RGBA bg = get_style_context()->get_background_color(); |
const Gdk::RGBA bg = get_style_context()->get_background_color(); |
375 |
|
# endif |
376 |
#endif |
#endif |
377 |
Gdk::Cairo::set_source_rgba(cr, bg); |
Gdk::Cairo::set_source_rgba(cr, bg); |
378 |
cr->paint(); |
cr->paint(); |
475 |
cr->line_to(x3, h1 - 0.5); |
cr->line_to(x3, h1 - 0.5); |
476 |
cr->stroke(); |
cr->stroke(); |
477 |
|
|
478 |
Gdk::Cairo::set_source_rgba(cr, region == r ? red : white); |
if (region == r) |
479 |
|
Gdk::Cairo::set_source_rgba(cr, blue); |
480 |
|
else if (modifyallregions) |
481 |
|
cr->set_source(blueHatchedSurfacePattern); |
482 |
|
else |
483 |
|
Gdk::Cairo::set_source_rgba(cr, white); |
484 |
|
|
485 |
cr->rectangle(x3 + 1, 1, x2 - x3 - 1, h1 - 2); |
cr->rectangle(x3 + 1, 1, x2 - x3 - 1, h1 - 2); |
486 |
cr->fill(); |
cr->fill(); |
487 |
Gdk::Cairo::set_source_rgba(cr, black); |
Gdk::Cairo::set_source_rgba(cr, black); |
492 |
|
|
493 |
for (gig::Region* r = regions.first() ; r ; r = regions.next()) { |
for (gig::Region* r = regions.first() ; r ; r = regions.next()) { |
494 |
int x = key_to_x(r->KeyRange.low, w); |
int x = key_to_x(r->KeyRange.low, w); |
495 |
|
int x2 = key_to_x(r->KeyRange.high + 1, w); |
496 |
|
|
497 |
|
RegionFeatures features = regionFeatures(r); |
498 |
|
|
499 |
|
const bool bShowLoopSymbol = features.loops > 0; |
500 |
|
const bool bShowSampleRefSymbol = features.sampleRefs < features.validDimRegs; |
501 |
|
if (bShowLoopSymbol || bShowSampleRefSymbol) { |
502 |
|
const int margin = 2; |
503 |
|
const int wRgn = x2 - x; |
504 |
|
//printf("x=%d x2=%d wRgn=%d\n", x, x2, wRgn); |
505 |
|
|
506 |
|
cr->save(); |
507 |
|
cr->set_line_width(1); |
508 |
|
cr->rectangle(x, 1, wRgn, h1 - 1); |
509 |
|
cr->clip(); |
510 |
|
if (bShowSampleRefSymbol) { |
511 |
|
const int wPic = 8; |
512 |
|
const int hPic = 8; |
513 |
|
Gdk::Cairo::set_source_pixbuf( |
514 |
|
cr, (features.sampleRefs) ? yellowDot : redDot, |
515 |
|
x + (wRgn-wPic)/2.f, |
516 |
|
(bShowLoopSymbol) ? margin : (h1-hPic)/2.f |
517 |
|
); |
518 |
|
cr->paint(); |
519 |
|
} |
520 |
|
if (bShowLoopSymbol) { |
521 |
|
const int wPic = 12; |
522 |
|
const int hPic = 14; |
523 |
|
Gdk::Cairo::set_source_pixbuf( |
524 |
|
cr, (features.loops == features.validDimRegs) ? blackLoop : grayLoop, |
525 |
|
x + (wRgn-wPic)/2.f, |
526 |
|
(bShowSampleRefSymbol) ? h1 - hPic - margin : (h1-hPic)/2.f |
527 |
|
); |
528 |
|
cr->paint(); |
529 |
|
} |
530 |
|
cr->restore(); |
531 |
|
} |
532 |
|
} |
533 |
|
|
534 |
|
for (gig::Region* r = regions.first() ; r ; r = regions.next()) { |
535 |
|
int x = key_to_x(r->KeyRange.low, w); |
536 |
|
|
537 |
if (x < clip_low) continue; |
if (x < clip_low) continue; |
538 |
if (x >= clip_high) break; |
if (x >= clip_high) break; |
550 |
layout->set_alignment(Pango::ALIGN_CENTER); |
layout->set_alignment(Pango::ALIGN_CENTER); |
551 |
layout->set_text(Glib::ustring("*** ") + _("Right click here to create a region.") + " ***"); |
layout->set_text(Glib::ustring("*** ") + _("Right click here to create a region.") + " ***"); |
552 |
layout->set_width(get_width() * Pango::SCALE); |
layout->set_width(get_width() * Pango::SCALE); |
553 |
Gdk::Cairo::set_source_rgba(cr, red); |
//layout->set_height(get_height() * Pango::SCALE); |
554 |
|
layout->set_spacing(10); |
555 |
|
Gdk::Cairo::set_source_rgba(cr, blue); |
556 |
|
// get the text dimensions |
557 |
|
int text_width, text_height; |
558 |
|
layout->get_pixel_size(text_width, text_height); |
559 |
|
cr->move_to(0, (REGION_BLOCK_HEIGHT - text_height) / 2); |
560 |
#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 |
561 |
pango_cairo_show_layout(cr->cobj(), layout->gobj()); |
pango_cairo_show_layout(cr->cobj(), layout->gobj()); |
562 |
#else |
#else |
671 |
#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 |
672 |
get_window()->pointer_ungrab(event->time); |
get_window()->pointer_ungrab(event->time); |
673 |
#else |
#else |
674 |
|
# if GTKMM_MAJOR_VERSION < 3 || (GTKMM_MAJOR_VERSION == 3 && GTKMM_MINOR_VERSION < 20) |
675 |
Glib::wrap(event->device, true)->ungrab(event->time); |
Glib::wrap(event->device, true)->ungrab(event->time); |
676 |
|
# else |
677 |
|
gdk_device_ungrab(Glib::wrap(event->device, true)->gobj(), event->time); |
678 |
|
# endif |
679 |
#endif |
#endif |
680 |
resize.active = false; |
resize.active = false; |
681 |
|
|
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()->pointer_ungrab(event->time); |
get_window()->pointer_ungrab(event->time); |
689 |
#else |
#else |
690 |
|
# if GTKMM_MAJOR_VERSION < 3 || (GTKMM_MAJOR_VERSION == 3 && GTKMM_MINOR_VERSION < 20) |
691 |
Glib::wrap(event->device, true)->ungrab(event->time); |
Glib::wrap(event->device, true)->ungrab(event->time); |
692 |
|
# else |
693 |
|
gdk_device_ungrab(Glib::wrap(event->device, true)->gobj(), event->time); |
694 |
|
# endif |
695 |
#endif |
#endif |
696 |
move.active = false; |
move.active = false; |
697 |
|
|
699 |
#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 |
700 |
get_window()->set_cursor(Gdk::Cursor(Gdk::SB_H_DOUBLE_ARROW)); |
get_window()->set_cursor(Gdk::Cursor(Gdk::SB_H_DOUBLE_ARROW)); |
701 |
#else |
#else |
702 |
get_window()->set_cursor(Gdk::Cursor::create(Gdk::SB_H_DOUBLE_ARROW)); |
get_window()->set_cursor( |
703 |
|
# if GTKMM_MAJOR_VERSION < 3 || (GTKMM_MAJOR_VERSION == 3 && GTKMM_MINOR_VERSION < 20) |
704 |
|
Gdk::Cursor::create(Gdk::SB_H_DOUBLE_ARROW) |
705 |
|
# else |
706 |
|
Gdk::Cursor::create( |
707 |
|
Glib::wrap(event->device, true)->get_seat()->get_display(), |
708 |
|
Gdk::SB_H_DOUBLE_ARROW |
709 |
|
) |
710 |
|
# endif |
711 |
|
); |
712 |
#endif |
#endif |
713 |
cursor_is_resize = true; |
cursor_is_resize = true; |
714 |
} |
} |
742 |
void RegionChooser::update_after_move(int pos) |
void RegionChooser::update_after_move(int pos) |
743 |
{ |
{ |
744 |
instrument_struct_to_be_changed_signal.emit(instrument); |
instrument_struct_to_be_changed_signal.emit(instrument); |
745 |
region->SetKeyRange(pos, pos + region->KeyRange.high - |
const int range = region->KeyRange.high - region->KeyRange.low; |
746 |
region->KeyRange.low); |
const int diff = pos - int(region->KeyRange.low); |
747 |
|
region->SetKeyRange(pos, pos + range); |
748 |
|
if (Settings::singleton()->moveRootNoteWithRegionMoved) { |
749 |
|
for (int i = 0; i < 256; ++i) { |
750 |
|
gig::DimensionRegion* dimrgn = region->pDimensionRegions[i]; |
751 |
|
if (!dimrgn || !dimrgn->pSample || !dimrgn->PitchTrack) continue; |
752 |
|
dimrgn->UnityNote += diff; |
753 |
|
} |
754 |
|
} |
755 |
regions.update(instrument); |
regions.update(instrument); |
756 |
instrument_changed.emit(); |
instrument_changed.emit(); |
757 |
instrument_struct_changed_signal.emit(instrument); |
instrument_struct_changed_signal.emit(instrument); |
773 |
} |
} |
774 |
} |
} |
775 |
|
|
776 |
|
// left mouse button double click |
777 |
|
if (event->type == GDK_2BUTTON_PRESS && event->button == 1) { |
778 |
|
if (event->y < REGION_BLOCK_HEIGHT) { |
779 |
|
// show dimension manager dialog for this region |
780 |
|
manage_dimensions(); |
781 |
|
} |
782 |
|
} |
783 |
|
|
784 |
if (event->y >= REGION_BLOCK_HEIGHT) return true; |
if (event->y >= REGION_BLOCK_HEIGHT) return true; |
785 |
if (event->type == GDK_BUTTON_PRESS && event->button == 3) { |
if (event->type == GDK_BUTTON_PRESS && event->button == 3) { |
786 |
gig::Region* r = get_region(k); |
gig::Region* r = get_region(k); |
804 |
Gdk::Cursor(Gdk::SB_H_DOUBLE_ARROW), |
Gdk::Cursor(Gdk::SB_H_DOUBLE_ARROW), |
805 |
event->time); |
event->time); |
806 |
#else |
#else |
807 |
|
# if GTKMM_MAJOR_VERSION < 3 || (GTKMM_MAJOR_VERSION == 3 && GTKMM_MINOR_VERSION < 20) |
808 |
Glib::wrap(event->device, true)->grab(get_window(), |
Glib::wrap(event->device, true)->grab(get_window(), |
809 |
Gdk::OWNERSHIP_NONE, |
Gdk::OWNERSHIP_NONE, |
810 |
false, |
false, |
813 |
Gdk::POINTER_MOTION_HINT_MASK, |
Gdk::POINTER_MOTION_HINT_MASK, |
814 |
Gdk::Cursor::create(Gdk::SB_H_DOUBLE_ARROW), |
Gdk::Cursor::create(Gdk::SB_H_DOUBLE_ARROW), |
815 |
event->time); |
event->time); |
816 |
|
# else |
817 |
|
gdk_device_grab( |
818 |
|
Glib::wrap(event->device, true)->gobj(), |
819 |
|
get_window()->gobj(), |
820 |
|
GDK_OWNERSHIP_NONE, |
821 |
|
false, |
822 |
|
GdkEventMask(GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK | |
823 |
|
GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON1_MOTION_MASK), |
824 |
|
Gdk::Cursor::create( |
825 |
|
Glib::wrap(event->device, true)->get_seat()->get_display(), |
826 |
|
Gdk::SB_H_DOUBLE_ARROW |
827 |
|
)->gobj(), |
828 |
|
event->time |
829 |
|
); |
830 |
|
# endif |
831 |
#endif |
#endif |
832 |
resize.active = true; |
resize.active = true; |
833 |
} else { |
} else { |
846 |
Gdk::Cursor(Gdk::FLEUR), |
Gdk::Cursor(Gdk::FLEUR), |
847 |
event->time); |
event->time); |
848 |
#else |
#else |
849 |
Glib::wrap(event->device, true)->grab(get_window(), |
# if GTKMM_MAJOR_VERSION < 3 || (GTKMM_MAJOR_VERSION == 3 && GTKMM_MINOR_VERSION < 20) |
850 |
Gdk::OWNERSHIP_NONE, |
Glib::wrap(event->device, true)->grab(get_window(), |
851 |
false, |
Gdk::OWNERSHIP_NONE, |
852 |
Gdk::BUTTON_RELEASE_MASK | |
false, |
853 |
Gdk::POINTER_MOTION_MASK | |
Gdk::BUTTON_RELEASE_MASK | |
854 |
Gdk::POINTER_MOTION_HINT_MASK, |
Gdk::POINTER_MOTION_MASK | |
855 |
Gdk::Cursor::create(Gdk::FLEUR), |
Gdk::POINTER_MOTION_HINT_MASK, |
856 |
event->time); |
Gdk::Cursor::create(Gdk::FLEUR), |
857 |
|
event->time); |
858 |
|
# else |
859 |
|
gdk_device_grab( |
860 |
|
Glib::wrap(event->device, true)->gobj(), |
861 |
|
get_window()->gobj(), |
862 |
|
GDK_OWNERSHIP_NONE, |
863 |
|
false, |
864 |
|
GdkEventMask(GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK | |
865 |
|
GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON1_MOTION_MASK), |
866 |
|
Gdk::Cursor::create( |
867 |
|
Glib::wrap(event->device, true)->get_seat()->get_display(), |
868 |
|
Gdk::FLEUR |
869 |
|
)->gobj(), |
870 |
|
event->time |
871 |
|
); |
872 |
|
# endif |
873 |
#endif |
#endif |
874 |
move.active = true; |
move.active = true; |
875 |
move.offset = event->x - key_to_x(region->KeyRange.low, w); |
move.offset = event->x - key_to_x(region->KeyRange.low, w); |
888 |
return 0; |
return 0; |
889 |
} |
} |
890 |
|
|
891 |
|
void RegionChooser::set_region(gig::Region* region) { |
892 |
|
this->region = region; |
893 |
|
queue_draw(); |
894 |
|
region_selected(); |
895 |
|
dimensionManager.set_region(region); |
896 |
|
} |
897 |
|
|
898 |
|
void RegionChooser::select_next_region() { |
899 |
|
if (!instrument) return; |
900 |
|
if (!region) { |
901 |
|
for (int i = 0; i < 128; ++i) { |
902 |
|
::gig::Region* rgn = instrument->GetRegion(i); |
903 |
|
if (rgn) { |
904 |
|
set_region(rgn); |
905 |
|
return; |
906 |
|
} |
907 |
|
} |
908 |
|
} else { |
909 |
|
bool currentFound = false; |
910 |
|
for (int i = 0; i < 128; ++i) { |
911 |
|
::gig::Region* rgn = instrument->GetRegion(i); |
912 |
|
if (!rgn) continue; |
913 |
|
if (currentFound) { |
914 |
|
if (rgn != region) { |
915 |
|
set_region(rgn); |
916 |
|
return; |
917 |
|
} |
918 |
|
} else { |
919 |
|
if (rgn == region) currentFound = true; |
920 |
|
} |
921 |
|
} |
922 |
|
} |
923 |
|
} |
924 |
|
|
925 |
|
void RegionChooser::select_prev_region() { |
926 |
|
if (!instrument) return; |
927 |
|
if (!region) { |
928 |
|
for (int i = 0; i < 128; ++i) { |
929 |
|
::gig::Region* rgn = instrument->GetRegion(i); |
930 |
|
if (rgn) { |
931 |
|
set_region(rgn); |
932 |
|
return; |
933 |
|
} |
934 |
|
} |
935 |
|
} else { |
936 |
|
bool currentFound = false; |
937 |
|
for (int i = 127; i >= 0; --i) { |
938 |
|
::gig::Region* rgn = instrument->GetRegion(i); |
939 |
|
if (!rgn) continue; |
940 |
|
if (currentFound) { |
941 |
|
if (rgn != region) { |
942 |
|
set_region(rgn); |
943 |
|
return; |
944 |
|
} |
945 |
|
} else { |
946 |
|
if (rgn == region) currentFound = true; |
947 |
|
} |
948 |
|
} |
949 |
|
} |
950 |
|
} |
951 |
|
|
952 |
void RegionChooser::motion_resize_region(int x, int y) |
void RegionChooser::motion_resize_region(int x, int y) |
953 |
{ |
{ |
954 |
const int w = get_width() - 1; |
const int w = get_width() - 1; |
997 |
|
|
998 |
update_after_resize(); |
update_after_resize(); |
999 |
|
|
1000 |
get_window()->invalidate_rect(rect, false); |
//get_window()->invalidate_rect(rect, false); |
1001 |
|
get_window()->invalidate(false); // repaint entire region, otherwise it would create visual artifacts |
1002 |
} |
} |
1003 |
} |
} |
1004 |
|
|
1087 |
{ |
{ |
1088 |
Glib::RefPtr<Gdk::Window> window = get_window(); |
Glib::RefPtr<Gdk::Window> window = get_window(); |
1089 |
int x, y; |
int x, y; |
1090 |
|
#if HAS_GDKMM_SEAT |
1091 |
|
x = event->x; |
1092 |
|
y = event->y; |
1093 |
|
Gdk::ModifierType state = Gdk::ModifierType(event->state); |
1094 |
|
#else |
1095 |
Gdk::ModifierType state = Gdk::ModifierType(0); |
Gdk::ModifierType state = Gdk::ModifierType(0); |
1096 |
window->get_pointer(x, y, state); |
window->get_pointer(x, y, state); |
1097 |
|
#endif |
1098 |
|
|
1099 |
// handle virtual MIDI keyboard |
// handle virtual MIDI keyboard |
1100 |
if (m_VirtKeybModeChoice.get_value() != VIRT_KEYBOARD_MODE_CHORD && |
if (m_VirtKeybModeChoice.get_value() != VIRT_KEYBOARD_MODE_CHORD && |
1125 |
#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 |
1126 |
window->set_cursor(Gdk::Cursor(Gdk::SB_H_DOUBLE_ARROW)); |
window->set_cursor(Gdk::Cursor(Gdk::SB_H_DOUBLE_ARROW)); |
1127 |
#else |
#else |
1128 |
window->set_cursor(Gdk::Cursor::create(Gdk::SB_H_DOUBLE_ARROW)); |
window->set_cursor( |
1129 |
|
# if GTKMM_MAJOR_VERSION < 3 || (GTKMM_MAJOR_VERSION == 3 && GTKMM_MINOR_VERSION < 20) |
1130 |
|
Gdk::Cursor::create(Gdk::SB_H_DOUBLE_ARROW) |
1131 |
|
# else |
1132 |
|
Gdk::Cursor::create( |
1133 |
|
Glib::wrap(event->device, true)->get_seat()->get_display(), |
1134 |
|
Gdk::SB_H_DOUBLE_ARROW |
1135 |
|
) |
1136 |
|
# endif |
1137 |
|
); |
1138 |
#endif |
#endif |
1139 |
cursor_is_resize = true; |
cursor_is_resize = true; |
1140 |
} |
} |
1214 |
// add "Keygroup" checkbox |
// add "Keygroup" checkbox |
1215 |
Gtk::CheckButton checkBoxKeygroup(_("Member of a Keygroup (Exclusive Group)")); |
Gtk::CheckButton checkBoxKeygroup(_("Member of a Keygroup (Exclusive Group)")); |
1216 |
checkBoxKeygroup.set_active(region->KeyGroup); |
checkBoxKeygroup.set_active(region->KeyGroup); |
1217 |
|
#if USE_GTKMM_BOX |
1218 |
|
dialog.get_content_area()->pack_start(checkBoxKeygroup); |
1219 |
|
#else |
1220 |
dialog.get_vbox()->pack_start(checkBoxKeygroup); |
dialog.get_vbox()->pack_start(checkBoxKeygroup); |
1221 |
|
#endif |
1222 |
checkBoxKeygroup.show(); |
checkBoxKeygroup.show(); |
1223 |
// add "Keygroup" spinbox |
// add "Keygroup" spinbox |
1224 |
#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 |
1228 |
Gtk::SpinButton spinBox(Gtk::Adjustment::create(1, 1, 999)); |
Gtk::SpinButton spinBox(Gtk::Adjustment::create(1, 1, 999)); |
1229 |
#endif |
#endif |
1230 |
if (region->KeyGroup) spinBox.set_value(region->KeyGroup); |
if (region->KeyGroup) spinBox.set_value(region->KeyGroup); |
1231 |
|
#if USE_GTKMM_BOX |
1232 |
|
dialog.get_content_area()->pack_start(spinBox); |
1233 |
|
#else |
1234 |
dialog.get_vbox()->pack_start(spinBox); |
dialog.get_vbox()->pack_start(spinBox); |
1235 |
|
#endif |
1236 |
spinBox.show(); |
spinBox.show(); |
1237 |
// add OK and CANCEL buttons to the dialog |
// add OK and CANCEL buttons to the dialog |
1238 |
|
#if HAS_GTKMM_STOCK |
1239 |
dialog.add_button(Gtk::Stock::OK, 0); |
dialog.add_button(Gtk::Stock::OK, 0); |
1240 |
dialog.add_button(Gtk::Stock::CANCEL, 1); |
dialog.add_button(Gtk::Stock::CANCEL, 1); |
1241 |
|
#else |
1242 |
|
dialog.add_button(_("_OK"), 0); |
1243 |
|
dialog.add_button(_("_Cancel"), 1); |
1244 |
|
#endif |
1245 |
|
dialog.set_position(Gtk::WIN_POS_MOUSE); |
1246 |
|
#if HAS_GTKMM_SHOW_ALL_CHILDREN |
1247 |
dialog.show_all_children(); |
dialog.show_all_children(); |
1248 |
|
#endif |
1249 |
if (!dialog.run()) { // OK selected ... |
if (!dialog.run()) { // OK selected ... |
1250 |
region->KeyGroup = |
region->KeyGroup = |
1251 |
(checkBoxKeygroup.get_active()) ? spinBox.get_value_as_int() : 0; |
(checkBoxKeygroup.get_active()) ? spinBox.get_value_as_int() : 0; |