1 |
/* |
/* |
2 |
* Copyright (C) 2006-2011 Andreas Persson |
* Copyright (C) 2006-2019 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 <sstream> |
#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 30 |
44 |
|
#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 |
#define REGION_BLOCK_HEIGHT 20 |
static RegionFeatures regionFeatures(gig::Region* rgn) { |
57 |
#define KEYBOARD_HEIGHT 40 |
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 |
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; |
155 |
|
|
156 |
// properties of the virtual keyboard |
// properties of the virtual keyboard |
157 |
{ |
{ |
158 |
const char* choices[] = { _("normal"), _("chord"), NULL }; |
const char* choices[] = { _("normal"), _("chord"), 0 }; |
159 |
static const virt_keyboard_mode_t values[] = { |
static const virt_keyboard_mode_t values[] = { |
160 |
VIRT_KEYBOARD_MODE_NORMAL, |
VIRT_KEYBOARD_MODE_NORMAL, |
161 |
VIRT_KEYBOARD_MODE_CHORD |
VIRT_KEYBOARD_MODE_CHORD |
175 |
m_VirtKeybPropsBox.pack_start(m_VirtKeybOffVelocityLabel, Gtk::PACK_SHRINK); |
m_VirtKeybPropsBox.pack_start(m_VirtKeybOffVelocityLabel, Gtk::PACK_SHRINK); |
176 |
m_VirtKeybPropsBox.set_spacing(10); |
m_VirtKeybPropsBox.set_spacing(10); |
177 |
m_VirtKeybPropsBox.show(); |
m_VirtKeybPropsBox.show(); |
178 |
|
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() |
294 |
keyboard_key_released_signal.connect( |
keyboard_key_released_signal.connect( |
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.")); |
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 |
template<class T> inline std::string ToString(T o) { |
void RegionChooser::on_show_tooltips_changed() { |
311 |
std::stringstream ss; |
const bool b = Settings::singleton()->showTooltips; |
312 |
ss << o; |
|
313 |
return ss.str(); |
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) { |
323 |
|
const int h = KEYBOARD_HEIGHT; |
324 |
|
const int w = get_width() - 1; |
325 |
|
int x1 = key_to_x(key - 0.5, w); |
326 |
|
int x2 = key_to_x(key + 1.5, w); |
327 |
|
|
328 |
|
Gdk::Rectangle rect(x1 + 1, h1 + 1, x2 - x1 - 1, h - 2); |
329 |
|
get_window()->invalidate_rect(rect, false); |
330 |
} |
} |
331 |
|
|
332 |
void RegionChooser::on_note_on_event(int key, int velocity) { |
void RegionChooser::on_note_on_event(int key, int velocity) { |
333 |
draw_key(key, activeKeyColor); |
key_pressed[key] = true; |
334 |
|
invalidate_key(key); |
335 |
m_VirtKeybVelocityLabel.set_text(ToString(velocity)); |
m_VirtKeybVelocityLabel.set_text(ToString(velocity)); |
336 |
} |
} |
337 |
|
|
338 |
void RegionChooser::on_note_off_event(int key, int velocity) { |
void RegionChooser::on_note_off_event(int key, int velocity) { |
339 |
if (is_black_key(key)) { |
key_pressed[key] = false; |
340 |
draw_key(key, black); |
invalidate_key(key); |
|
} else { |
|
|
draw_key(key, key >= 21 && key <= 108 ? white : grey1); |
|
|
} |
|
341 |
m_VirtKeybOffVelocityLabel.set_text(ToString(velocity)); |
m_VirtKeybOffVelocityLabel.set_text(ToString(velocity)); |
342 |
} |
} |
343 |
|
|
344 |
|
|
345 |
#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 |
346 |
bool RegionChooser::on_expose_event(GdkEventExpose* e) |
bool RegionChooser::on_expose_event(GdkEventExpose* e) { |
347 |
{ |
double clipx1 = e->area.x; |
348 |
return on_draw(get_window()->create_cairo_context()); |
double clipx2 = e->area.x + e->area.width; |
349 |
|
double clipy1 = e->area.y; |
350 |
|
double clipy2 = e->area.y + e->area.height; |
351 |
|
|
352 |
|
const Cairo::RefPtr<Cairo::Context>& cr = |
353 |
|
get_window()->create_cairo_context(); |
354 |
|
#if 0 |
355 |
} |
} |
356 |
#endif |
#endif |
357 |
|
#else |
358 |
bool RegionChooser::on_draw(const Cairo::RefPtr<Cairo::Context>& cr) |
bool RegionChooser::on_draw(const Cairo::RefPtr<Cairo::Context>& cr) { |
359 |
{ |
double clipx1, clipx2, clipy1, clipy2; |
360 |
const int h = KEYBOARD_HEIGHT; |
cr->get_clip_extents(clipx1, clipy1, clipx2, clipy2); |
361 |
const int w = get_width() - 1; |
#endif |
|
const int bh = int(h * 0.55); |
|
362 |
|
|
363 |
cr->save(); |
cr->save(); |
364 |
cr->set_line_width(1); |
cr->set_line_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(); |
379 |
|
|
380 |
|
if (clipy2 > h1) { |
381 |
|
draw_keyboard(cr, clipx1, clipx2); |
382 |
|
} |
383 |
|
|
384 |
|
if (clipy1 < h1 && instrument) { |
385 |
|
draw_regions(cr, clipx1, clipx2); |
386 |
|
} |
387 |
|
|
388 |
|
cr->restore(); |
389 |
|
|
390 |
|
return true; |
391 |
|
} |
392 |
|
|
393 |
|
void RegionChooser::draw_keyboard(const Cairo::RefPtr<Cairo::Context>& cr, |
394 |
|
int clip_low, int clip_high) { |
395 |
|
const int h = KEYBOARD_HEIGHT; |
396 |
|
const int w = get_width() - 1; |
397 |
|
const int bh = int(h * 0.55); |
398 |
|
|
399 |
Gdk::Cairo::set_source_rgba(cr, black); |
Gdk::Cairo::set_source_rgba(cr, black); |
400 |
cr->rectangle(0.5, h1 + 0.5, w, h - 1); |
cr->rectangle(0.5, h1 + 0.5, w, h - 1); |
401 |
cr->stroke(); |
cr->stroke(); |
402 |
|
|
403 |
int x1 = int(w * 20.5 / 128.0 + 0.5); |
int x1 = key_to_x(20.5, w); |
|
int x2 = int(w * 109.5 / 128.0 + 0.5); |
|
|
|
|
404 |
Gdk::Cairo::set_source_rgba(cr, grey1); |
Gdk::Cairo::set_source_rgba(cr, grey1); |
405 |
cr->rectangle(1, h1 + 1, x1 - 1, h - 2); |
cr->rectangle(1, h1 + 1, x1 - 1, h - 2); |
406 |
cr->fill(); |
cr->fill(); |
407 |
|
|
408 |
|
int x2 = key_to_x(109.5, w); |
409 |
Gdk::Cairo::set_source_rgba(cr, white); |
Gdk::Cairo::set_source_rgba(cr, white); |
410 |
cr->rectangle(x1 + 1, h1 + 1, x2 - x1 - 1, h - 2); |
cr->rectangle(x1 + 1, h1 + 1, x2 - x1 - 1, h - 2); |
411 |
cr->fill(); |
cr->fill(); |
415 |
cr->fill(); |
cr->fill(); |
416 |
|
|
417 |
Gdk::Cairo::set_source_rgba(cr, black); |
Gdk::Cairo::set_source_rgba(cr, black); |
418 |
for (int i = 0 ; i < 128 ; i++) { |
|
419 |
|
int clipkey1 = std::max(0, x_to_key_right(clip_low - 1, w)); |
420 |
|
int clipkey2 = std::min(x_to_key_right(clip_high - 1, w) + 1, 128); |
421 |
|
|
422 |
|
for (int i = clipkey1 ; i < clipkey2 ; i++) { |
423 |
int note = (i + 3) % 12; |
int note = (i + 3) % 12; |
424 |
int x = int(w * i / 128.0 + 0.5); |
int x = key_to_x(i, w); |
425 |
|
|
426 |
if (note == 1 || note == 4 || note == 6 || |
if (note == 1 || note == 4 || note == 6 || |
427 |
note == 9 || note == 11) { |
note == 9 || note == 11) { |
428 |
int x2 = int(w * (i + 0.5) / 128.0 + 0.5); |
// black key: short line in the middle, with a rectangle |
429 |
|
// on top |
430 |
|
int x2 = key_to_x(i + 0.5, w); |
431 |
cr->move_to(x2 + 0.5, h1 + bh + 0.5); |
cr->move_to(x2 + 0.5, h1 + bh + 0.5); |
432 |
cr->line_to(x2 + 0.5, h1 + h - 1); |
cr->line_to(x2 + 0.5, h1 + h - 1); |
433 |
cr->stroke(); |
cr->stroke(); |
434 |
|
|
435 |
int x3 = int(w * (i + 1) / 128.0 + 0.5); |
int x3 = key_to_x(i + 1, w); |
436 |
cr->rectangle(x, h1 + 1, x3 - x + 1, bh); |
cr->rectangle(x, h1 + 1, x3 - x + 1, bh); |
437 |
cr->fill(); |
cr->fill(); |
438 |
} else if (note == 3 || note == 8) { |
} else if (note == 3 || note == 8) { |
439 |
|
// C or F: long line to the left |
440 |
cr->move_to(x + 0.5, h1 + 1); |
cr->move_to(x + 0.5, h1 + 1); |
441 |
cr->line_to(x + 0.5, h1 + h - 1); |
cr->line_to(x + 0.5, h1 + h - 1); |
442 |
cr->stroke(); |
cr->stroke(); |
|
|
|
|
if (note == 3) draw_digit(i); |
|
443 |
} |
} |
444 |
|
|
445 |
|
if (key_pressed[i]) draw_key(cr, i); |
446 |
|
|
447 |
|
if (note == 3) draw_digit(cr, i); |
448 |
} |
} |
449 |
|
} |
450 |
|
|
|
if (instrument) { |
|
|
int i = 0; |
|
|
gig::Region* next_region; |
|
|
int x3 = -1; |
|
|
for (gig::Region* r = regions.first() ; r ; r = next_region) { |
|
451 |
|
|
452 |
if (x3 < 0) x3 = int(w * (r->KeyRange.low) / 128.0 + 0.5); |
void RegionChooser::draw_regions(const Cairo::RefPtr<Cairo::Context>& cr, |
453 |
next_region = regions.next(); |
int clip_low, int clip_high) { |
454 |
if (!next_region || |
const int w = get_width() - 1; |
455 |
r->KeyRange.high + 1 != next_region->KeyRange.low) { |
|
456 |
int x2 = int(w * (r->KeyRange.high + 1) / 128.0 + 0.5); |
Gdk::Cairo::set_source_rgba(cr, black); |
457 |
|
gig::Region* next_region; |
458 |
|
int x3 = -1; |
459 |
|
for (gig::Region* r = regions.first() ; r ; r = next_region) { |
460 |
|
next_region = regions.next(); |
461 |
|
|
462 |
|
if (x3 < 0) { |
463 |
|
x3 = key_to_x(r->KeyRange.low, w); |
464 |
|
if (x3 >= clip_high) break; |
465 |
|
} |
466 |
|
if (!next_region || |
467 |
|
r->KeyRange.high + 1 != next_region->KeyRange.low || |
468 |
|
r == region || next_region == region) { |
469 |
|
|
470 |
|
int x2 = key_to_x(r->KeyRange.high + 1, w); |
471 |
|
if (x2 >= clip_low) { |
472 |
cr->move_to(x3, 0.5); |
cr->move_to(x3, 0.5); |
473 |
cr->line_to(x2 + 0.5, 0.5); |
cr->line_to(x2 + 0.5, 0.5); |
474 |
cr->line_to(x2 + 0.5, h1 - 0.5); |
cr->line_to(x2 + 0.5, h1 - 0.5); |
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, 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); |
|
|
|
|
x3 = -1; |
|
488 |
} |
} |
489 |
i++; |
x3 = -1; |
|
} |
|
|
|
|
|
for (gig::Region* r = regions.first() ; r ; r = regions.next()) { |
|
|
int x = int(w * (r->KeyRange.low) / 128.0 + 0.5); |
|
|
cr->move_to(x + 0.5, 1); |
|
|
cr->line_to(x + 0.5, h1 - 1); |
|
|
cr->stroke(); |
|
490 |
} |
} |
491 |
|
} |
492 |
|
|
493 |
if (region) { |
for (gig::Region* r = regions.first() ; r ; r = regions.next()) { |
494 |
int x1 = int(w * (region->KeyRange.low) / 128.0 + 0.5); |
int x = key_to_x(r->KeyRange.low, w); |
495 |
int x2 = int(w * (region->KeyRange.high + 1) / 128.0 + 0.5); |
int x2 = key_to_x(r->KeyRange.high + 1, w); |
496 |
Gdk::Cairo::set_source_rgba(cr, red); |
|
497 |
cr->rectangle(x1 + 1, 1, x2 - x1 - 1, h1 - 2); |
RegionFeatures features = regionFeatures(r); |
498 |
cr->fill(); |
|
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 |
cr->restore(); |
for (gig::Region* r = regions.first() ; r ; r = regions.next()) { |
535 |
|
int x = key_to_x(r->KeyRange.low, w); |
536 |
|
|
537 |
return true; |
if (x < clip_low) continue; |
538 |
} |
if (x >= clip_high) break; |
539 |
|
|
540 |
|
cr->move_to(x + 0.5, 1); |
541 |
|
cr->line_to(x + 0.5, h1 - 1); |
542 |
|
cr->stroke(); |
543 |
|
} |
544 |
|
|
545 |
|
// if there is no region yet, show the user some hint text that he may |
546 |
|
// right click on this area to create a new region |
547 |
|
if (!regions.first()) { |
548 |
|
Glib::RefPtr<Pango::Context> context = get_pango_context(); |
549 |
|
Glib::RefPtr<Pango::Layout> layout = Pango::Layout::create(context); |
550 |
|
layout->set_alignment(Pango::ALIGN_CENTER); |
551 |
|
layout->set_text(Glib::ustring("*** ") + _("Right click here to create a region.") + " ***"); |
552 |
|
layout->set_width(get_width() * Pango::SCALE); |
553 |
|
//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 |
561 |
|
pango_cairo_show_layout(cr->cobj(), layout->gobj()); |
562 |
|
#else |
563 |
|
layout->show_in_cairo_context(cr); |
564 |
|
#endif |
565 |
|
} |
566 |
|
} |
567 |
|
|
568 |
bool RegionChooser::is_black_key(int key) { |
bool RegionChooser::is_black_key(int key) { |
569 |
const int note = (key + 3) % 12; |
const int note = (key + 3) % 12; |
570 |
return note == 1 || note == 4 || note == 6 || note == 9 || note == 11; |
return note == 1 || note == 4 || note == 6 || note == 9 || note == 11; |
571 |
} |
} |
572 |
|
|
573 |
void RegionChooser::draw_digit(int key) { |
void RegionChooser::draw_digit(const Cairo::RefPtr<Cairo::Context>& cr, |
574 |
|
int key) { |
575 |
const int h = KEYBOARD_HEIGHT; |
const int h = KEYBOARD_HEIGHT; |
576 |
const int w = get_width() - 1; |
const int w = get_width() - 1; |
577 |
Glib::RefPtr<Pango::Layout> layout = Pango::Layout::create(get_pango_context()); |
Glib::RefPtr<Pango::Layout> layout = |
578 |
|
Pango::Layout::create(get_pango_context()); |
579 |
char buf[30]; |
char buf[30]; |
580 |
sprintf(buf, "<span size=\"8000\">%d</span>", key / 12 - 1); |
sprintf(buf, "<span size=\"8000\">%d</span>", key / 12 - 1); |
581 |
layout->set_markup(buf); |
layout->set_markup(buf); |
583 |
double text_w = double(rectangle.get_width()) / Pango::SCALE; |
double text_w = double(rectangle.get_width()) / Pango::SCALE; |
584 |
double text_h = double(rectangle.get_height()) / Pango::SCALE; |
double text_h = double(rectangle.get_height()) / Pango::SCALE; |
585 |
double x = w * (key + 0.75) / 128.0; |
double x = w * (key + 0.75) / 128.0; |
|
Cairo::RefPtr<Cairo::Context> cr = get_window()->create_cairo_context(); |
|
586 |
Gdk::Cairo::set_source_rgba(cr, black); |
Gdk::Cairo::set_source_rgba(cr, black); |
587 |
cr->move_to(int(x - text_w / 2 + 1), int(h1 + h - text_h + 0.5)); |
cr->move_to(int(x - text_w / 2 + 1), int(h1 + h - text_h + 0.5)); |
588 |
#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 |
592 |
#endif |
#endif |
593 |
} |
} |
594 |
|
|
595 |
void RegionChooser::draw_key(int key, const Gdk::RGBA& color) |
void RegionChooser::draw_key(const Cairo::RefPtr<Cairo::Context>& cr, |
596 |
{ |
int key) { |
597 |
const int h = KEYBOARD_HEIGHT; |
const int h = KEYBOARD_HEIGHT; |
598 |
const int w = get_width() - 1; |
const int w = get_width() - 1; |
599 |
const int bh = int(h * 0.55); |
const int bh = int(h * 0.55); |
600 |
|
|
601 |
Cairo::RefPtr<Cairo::Context> cr = get_window()->create_cairo_context(); |
Gdk::Cairo::set_source_rgba(cr, activeKeyColor); |
|
Gdk::Cairo::set_source_rgba(cr, color); |
|
602 |
|
|
603 |
int note = (key + 3) % 12; |
int note = (key + 3) % 12; |
604 |
int x = int(w * key / 128.0 + 0.5) + 1; |
int x = key_to_x(key, w) + 1; |
605 |
int x2 = int(w * (key + 1.5) / 128.0 + 0.5); |
int x2 = key_to_x(key + 1.5, w); |
606 |
int x3 = int(w * (key + 1) / 128.0 + 0.5); |
int x3 = key_to_x(key + 1, w); |
607 |
int x4 = int(w * (key - 0.5) / 128.0 + 0.5); |
int x4 = key_to_x(key - 0.5, w); |
608 |
int w1 = x3 - x; |
int w1 = x3 - x; |
609 |
switch (note) { |
switch (note) { |
610 |
case 0: case 5: case 10: |
case 0: case 5: case 10: |
624 |
cr->fill(); |
cr->fill(); |
625 |
cr->rectangle(x, h1 + bh + 1, x2 - x, h - bh - 2); |
cr->rectangle(x, h1 + bh + 1, x2 - x, h - bh - 2); |
626 |
cr->fill(); |
cr->fill(); |
|
if (note == 3) draw_digit(key); |
|
627 |
break; |
break; |
628 |
default: |
default: |
629 |
cr->rectangle(x, h1 + 1, w1, bh - 1); |
cr->rectangle(x, h1 + 1, w1, bh - 1); |
630 |
cr->fill(); |
cr->fill(); |
631 |
break; |
break; |
632 |
} |
} |
633 |
|
Gdk::Cairo::set_source_rgba(cr, black); |
634 |
} |
} |
635 |
|
|
636 |
void RegionChooser::set_instrument(gig::Instrument* instrument) |
void RegionChooser::set_instrument(gig::Instrument* instrument) |
645 |
|
|
646 |
bool RegionChooser::on_button_release_event(GdkEventButton* event) |
bool RegionChooser::on_button_release_event(GdkEventButton* event) |
647 |
{ |
{ |
648 |
const int k = int(event->x / (get_width() - 1) * 128.0); |
const int k = x_to_key(event->x, get_width() - 1); |
649 |
|
|
650 |
// handle-note off on virtual keyboard |
// handle-note off on virtual keyboard |
651 |
if (event->type == GDK_BUTTON_RELEASE) { |
if (event->type == GDK_BUTTON_RELEASE) { |
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 |
|
Glib::wrap(event->device, true)->get_seat()->ungrab(); |
678 |
|
# endif |
679 |
#endif |
#endif |
680 |
resize.active = false; |
resize.active = false; |
681 |
|
|
|
if (resize.mode == resize.moving_high_limit) { |
|
|
if (resize.region->KeyRange.high != resize.pos - 1) { |
|
|
instrument_struct_to_be_changed_signal.emit(instrument); |
|
|
resize.region->SetKeyRange( |
|
|
resize.region->KeyRange.low, // low |
|
|
resize.pos - 1 // high |
|
|
); |
|
|
regions.update(instrument); |
|
|
instrument_changed.emit(); |
|
|
instrument_struct_changed_signal.emit(instrument); |
|
|
} |
|
|
} else if (resize.mode == resize.moving_low_limit) { |
|
|
if (resize.region->KeyRange.low != resize.pos) { |
|
|
instrument_struct_to_be_changed_signal.emit(instrument); |
|
|
resize.region->SetKeyRange( |
|
|
resize.pos, // low |
|
|
resize.region->KeyRange.high // high |
|
|
); |
|
|
regions.update(instrument); |
|
|
instrument_changed.emit(); |
|
|
instrument_struct_changed_signal.emit(instrument); |
|
|
} |
|
|
} |
|
|
|
|
682 |
if (!is_in_resize_zone(event->x, event->y) && cursor_is_resize) { |
if (!is_in_resize_zone(event->x, event->y) && cursor_is_resize) { |
683 |
get_window()->set_cursor(); |
get_window()->set_cursor(); |
684 |
cursor_is_resize = false; |
cursor_is_resize = false; |
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 |
|
Glib::wrap(event->device, true)->get_seat()->ungrab(); |
694 |
|
# endif |
695 |
#endif |
#endif |
696 |
move.active = false; |
move.active = false; |
697 |
|
|
|
if (move.pos) { |
|
|
instrument_struct_to_be_changed_signal.emit(instrument); |
|
|
region->SetKeyRange( |
|
|
region->KeyRange.low + move.pos, |
|
|
region->KeyRange.high + move.pos |
|
|
); |
|
|
regions.update(instrument); |
|
|
instrument_changed.emit(); |
|
|
instrument_struct_changed_signal.emit(instrument); |
|
|
} |
|
|
|
|
698 |
if (is_in_resize_zone(event->x, event->y)) { |
if (is_in_resize_zone(event->x, event->y)) { |
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 |
} |
} |
716 |
return true; |
return true; |
717 |
} |
} |
718 |
|
|
719 |
|
void RegionChooser::update_after_resize() |
720 |
|
{ |
721 |
|
if (resize.mode == resize.moving_high_limit) { |
722 |
|
if (resize.region->KeyRange.high != resize.pos - 1) { |
723 |
|
instrument_struct_to_be_changed_signal.emit(instrument); |
724 |
|
resize.region->SetKeyRange(resize.region->KeyRange.low, |
725 |
|
resize.pos - 1); |
726 |
|
regions.update(instrument); |
727 |
|
instrument_changed.emit(); |
728 |
|
instrument_struct_changed_signal.emit(instrument); |
729 |
|
} |
730 |
|
} else if (resize.mode == resize.moving_low_limit) { |
731 |
|
if (resize.region->KeyRange.low != resize.pos) { |
732 |
|
instrument_struct_to_be_changed_signal.emit(instrument); |
733 |
|
resize.region->SetKeyRange(resize.pos, |
734 |
|
resize.region->KeyRange.high); |
735 |
|
regions.update(instrument); |
736 |
|
instrument_changed.emit(); |
737 |
|
instrument_struct_changed_signal.emit(instrument); |
738 |
|
} |
739 |
|
} |
740 |
|
} |
741 |
|
|
742 |
|
void RegionChooser::update_after_move(int pos) |
743 |
|
{ |
744 |
|
instrument_struct_to_be_changed_signal.emit(instrument); |
745 |
|
const int range = region->KeyRange.high - region->KeyRange.low; |
746 |
|
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); |
756 |
|
instrument_changed.emit(); |
757 |
|
instrument_struct_changed_signal.emit(instrument); |
758 |
|
} |
759 |
|
|
760 |
bool RegionChooser::on_button_press_event(GdkEventButton* event) |
bool RegionChooser::on_button_press_event(GdkEventButton* event) |
761 |
{ |
{ |
762 |
if (!instrument) return true; |
if (!instrument) return true; |
763 |
|
|
764 |
const int k = int(event->x / (get_width() - 1) * 128.0); |
const int w = get_width() - 1; |
765 |
|
const int k = x_to_key(event->x, w); |
766 |
|
|
767 |
if (event->type == GDK_BUTTON_PRESS) { |
if (event->type == GDK_BUTTON_PRESS) { |
768 |
if (event->y >= REGION_BLOCK_HEIGHT) { |
if (event->y >= REGION_BLOCK_HEIGHT) { |
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 |
|
Glib::wrap(event->device, true)->get_seat()->grab( |
818 |
|
get_window(), |
819 |
|
Gdk::SeatCapabilities::SEAT_CAPABILITY_ALL_POINTING, |
820 |
|
false, |
821 |
|
Gdk::Cursor::create( |
822 |
|
Glib::wrap(event->device, true)->get_seat()->get_display(), |
823 |
|
Gdk::SB_H_DOUBLE_ARROW |
824 |
|
), |
825 |
|
reinterpret_cast<GdkEvent*>(event) |
826 |
|
); |
827 |
|
# endif |
828 |
#endif |
#endif |
829 |
resize.active = true; |
resize.active = true; |
830 |
} else { |
} else { |
843 |
Gdk::Cursor(Gdk::FLEUR), |
Gdk::Cursor(Gdk::FLEUR), |
844 |
event->time); |
event->time); |
845 |
#else |
#else |
846 |
Glib::wrap(event->device, true)->grab(get_window(), |
# if GTKMM_MAJOR_VERSION < 3 || (GTKMM_MAJOR_VERSION == 3 && GTKMM_MINOR_VERSION < 20) |
847 |
Gdk::OWNERSHIP_NONE, |
Glib::wrap(event->device, true)->grab(get_window(), |
848 |
false, |
Gdk::OWNERSHIP_NONE, |
849 |
Gdk::BUTTON_RELEASE_MASK | |
false, |
850 |
Gdk::POINTER_MOTION_MASK | |
Gdk::BUTTON_RELEASE_MASK | |
851 |
Gdk::POINTER_MOTION_HINT_MASK, |
Gdk::POINTER_MOTION_MASK | |
852 |
Gdk::Cursor::create(Gdk::FLEUR), |
Gdk::POINTER_MOTION_HINT_MASK, |
853 |
event->time); |
Gdk::Cursor::create(Gdk::FLEUR), |
854 |
|
event->time); |
855 |
|
# else |
856 |
|
Glib::wrap(event->device, true)->get_seat()->grab( |
857 |
|
get_window(), |
858 |
|
Gdk::SeatCapabilities::SEAT_CAPABILITY_ALL_POINTING, |
859 |
|
false, |
860 |
|
Gdk::Cursor::create( |
861 |
|
Glib::wrap(event->device, true)->get_seat()->get_display(), |
862 |
|
Gdk::FLEUR |
863 |
|
), |
864 |
|
reinterpret_cast<GdkEvent*>(event) |
865 |
|
); |
866 |
|
# endif |
867 |
#endif |
#endif |
868 |
move.active = true; |
move.active = true; |
869 |
move.from_x = event->x; |
move.offset = event->x - key_to_x(region->KeyRange.low, w); |
|
move.pos = 0; |
|
870 |
} |
} |
871 |
} |
} |
872 |
} |
} |
875 |
|
|
876 |
gig::Region* RegionChooser::get_region(int key) |
gig::Region* RegionChooser::get_region(int key) |
877 |
{ |
{ |
878 |
gig::Region* prev_region = 0; |
for (gig::Region* r = regions.first() ; r ; r = regions.next()) { |
|
gig::Region* next_region; |
|
|
for (gig::Region* r = regions.first() ; r ; r = next_region) { |
|
|
next_region = regions.next(); |
|
|
|
|
879 |
if (key < r->KeyRange.low) return 0; |
if (key < r->KeyRange.low) return 0; |
880 |
if (key <= r->KeyRange.high) { |
if (key <= r->KeyRange.high) return r; |
|
move.touch_left = prev_region && prev_region->KeyRange.high + 1 == r->KeyRange.low; |
|
|
move.touch_right = next_region && r->KeyRange.high + 1 == next_region->KeyRange.low; |
|
|
return r; |
|
|
} |
|
|
prev_region = r; |
|
881 |
} |
} |
882 |
return 0; |
return 0; |
883 |
} |
} |
884 |
|
|
885 |
|
void RegionChooser::set_region(gig::Region* region) { |
886 |
|
this->region = region; |
887 |
|
queue_draw(); |
888 |
|
region_selected(); |
889 |
|
dimensionManager.set_region(region); |
890 |
|
} |
891 |
|
|
892 |
|
void RegionChooser::select_next_region() { |
893 |
|
if (!instrument) return; |
894 |
|
if (!region) { |
895 |
|
for (int i = 0; i < 128; ++i) { |
896 |
|
::gig::Region* rgn = instrument->GetRegion(i); |
897 |
|
if (rgn) { |
898 |
|
set_region(rgn); |
899 |
|
return; |
900 |
|
} |
901 |
|
} |
902 |
|
} else { |
903 |
|
bool currentFound = false; |
904 |
|
for (int i = 0; i < 128; ++i) { |
905 |
|
::gig::Region* rgn = instrument->GetRegion(i); |
906 |
|
if (!rgn) continue; |
907 |
|
if (currentFound) { |
908 |
|
if (rgn != region) { |
909 |
|
set_region(rgn); |
910 |
|
return; |
911 |
|
} |
912 |
|
} else { |
913 |
|
if (rgn == region) currentFound = true; |
914 |
|
} |
915 |
|
} |
916 |
|
} |
917 |
|
} |
918 |
|
|
919 |
|
void RegionChooser::select_prev_region() { |
920 |
|
if (!instrument) return; |
921 |
|
if (!region) { |
922 |
|
for (int i = 0; i < 128; ++i) { |
923 |
|
::gig::Region* rgn = instrument->GetRegion(i); |
924 |
|
if (rgn) { |
925 |
|
set_region(rgn); |
926 |
|
return; |
927 |
|
} |
928 |
|
} |
929 |
|
} else { |
930 |
|
bool currentFound = false; |
931 |
|
for (int i = 127; i >= 0; --i) { |
932 |
|
::gig::Region* rgn = instrument->GetRegion(i); |
933 |
|
if (!rgn) continue; |
934 |
|
if (currentFound) { |
935 |
|
if (rgn != region) { |
936 |
|
set_region(rgn); |
937 |
|
return; |
938 |
|
} |
939 |
|
} else { |
940 |
|
if (rgn == region) currentFound = true; |
941 |
|
} |
942 |
|
} |
943 |
|
} |
944 |
|
} |
945 |
|
|
946 |
void RegionChooser::motion_resize_region(int x, int y) |
void RegionChooser::motion_resize_region(int x, int y) |
947 |
{ |
{ |
948 |
const int w = get_width() - 1; |
const int w = get_width() - 1; |
953 |
else if (k > resize.max) k = resize.max; |
else if (k > resize.max) k = resize.max; |
954 |
|
|
955 |
if (k != resize.pos) { |
if (k != resize.pos) { |
|
Cairo::RefPtr<Cairo::Context> cr = get_window()->create_cairo_context(); |
|
|
cr->set_line_width(1); |
|
|
|
|
956 |
if (resize.mode == resize.undecided) { |
if (resize.mode == resize.undecided) { |
957 |
if (k < resize.pos) { |
if (k < resize.pos) { |
958 |
// edit high limit of prev_region |
// edit high limit of prev_region |
965 |
resize.mode = resize.moving_low_limit; |
resize.mode = resize.moving_low_limit; |
966 |
} |
} |
967 |
} |
} |
968 |
const Gdk::RGBA white = region == resize.region ? red : this->white; |
resize.pos = k; |
|
#if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2 |
|
|
const Gdk::Color bg = get_style()->get_bg(Gtk::STATE_NORMAL); |
|
|
#else |
|
|
const Gdk::RGBA bg = get_style_context()->get_background_color(); |
|
|
#endif |
|
|
|
|
|
int prevx = int(w * resize.pos / 128.0 + 0.5); |
|
|
x = int(w * k / 128.0 + 0.5); |
|
969 |
|
|
970 |
|
int x1, x2; |
971 |
if (resize.mode == resize.moving_high_limit) { |
if (resize.mode == resize.moving_high_limit) { |
972 |
if (k > resize.pos) { |
if (resize.region->KeyRange.high < resize.pos - 1) { |
973 |
Gdk::Cairo::set_source_rgba(cr, white); |
x1 = resize.region->KeyRange.high; |
974 |
cr->rectangle(prevx, 1, x - prevx, h1 - 2); |
x2 = resize.pos - 1; |
|
cr->fill(); |
|
|
|
|
|
Gdk::Cairo::set_source_rgba(cr, black); |
|
|
cr->move_to(prevx, 0.5); |
|
|
cr->line_to(x + 1, 0.5); |
|
|
cr->move_to(prevx, h1 - 0.5); |
|
|
cr->line_to(x + 1, h1 - 0.5); |
|
|
cr->stroke(); |
|
975 |
} else { |
} else { |
976 |
int xx = (resize.pos == resize.max && |
x1 = resize.pos - 1; |
977 |
resize.max != 128) ? 1 : 0; |
x2 = resize.region->KeyRange.high; |
|
Gdk::Cairo::set_source_rgba(cr, bg); |
|
|
cr->rectangle(x + 1, 0, prevx - x - xx, h1); |
|
|
cr->fill(); |
|
978 |
} |
} |
979 |
} else { |
} else { |
980 |
if (k < resize.pos) { |
if (resize.region->KeyRange.low < resize.pos) { |
981 |
Gdk::Cairo::set_source_rgba(cr, white); |
x1 = resize.region->KeyRange.low; |
982 |
cr->rectangle(x + 1, 1, prevx - x, h1 - 2); |
x2 = resize.pos; |
|
cr->fill(); |
|
|
|
|
|
Gdk::Cairo::set_source_rgba(cr, black); |
|
|
cr->move_to(x, 0.5); |
|
|
cr->line_to(prevx, 0.5); |
|
|
cr->move_to(x, h1 - 0.5); |
|
|
cr->line_to(prevx, h1 - 0.5); |
|
|
cr->stroke(); |
|
983 |
} else { |
} else { |
984 |
int xx = (resize.pos == resize.min && |
x1 = resize.pos; |
985 |
resize.min != 0) ? 1 : 0; |
x2 = resize.region->KeyRange.low; |
|
Gdk::Cairo::set_source_rgba(cr, bg); |
|
|
cr->rectangle(prevx + xx, 0, x - prevx - xx, h1); |
|
|
cr->fill(); |
|
986 |
} |
} |
987 |
} |
} |
988 |
Gdk::Cairo::set_source_rgba(cr, black); |
x1 = key_to_x(x1, w); |
989 |
cr->move_to(x + 0.5, 1); |
x2 = key_to_x(x2 + 1, w) + 1; |
990 |
cr->line_to(x + 0.5, h1 - 1); |
Gdk::Rectangle rect(x1, 0, x2 - x1, h1); |
991 |
cr->stroke(); |
|
992 |
resize.pos = k; |
update_after_resize(); |
993 |
|
|
994 |
|
//get_window()->invalidate_rect(rect, false); |
995 |
|
get_window()->invalidate(false); // repaint entire region, otherwise it would create visual artifacts |
996 |
} |
} |
997 |
} |
} |
998 |
|
|
999 |
void RegionChooser::motion_move_region(int x, int y) |
void RegionChooser::motion_move_region(int x, int y) |
1000 |
{ |
{ |
1001 |
const int w = get_width() - 1; |
const int w = get_width() - 1; |
|
Cairo::RefPtr<Cairo::Context> cr = get_window()->create_cairo_context(); |
|
|
cr->set_line_width(1); |
|
1002 |
|
|
1003 |
int k = int(double(x - move.from_x) / w * 128.0 + 0.5); |
int l = int(double(x - move.offset) / w * 128.0 + 0.5); |
1004 |
if (k == move.pos) return; |
|
1005 |
int new_k; |
if (l == region->KeyRange.low) return; |
1006 |
bool new_touch_left; |
int new_l; |
1007 |
bool new_touch_right; |
int regionsize = region->KeyRange.high - region->KeyRange.low; |
1008 |
int a = 0; |
int a = 0; |
1009 |
if (k > move.pos) { |
if (l > region->KeyRange.low) { |
1010 |
for (gig::Region* r = regions.first() ; ; r = regions.next()) { |
for (gig::Region* r = regions.first() ; ; r = regions.next()) { |
1011 |
if (r != region) { |
if (r != region) { |
1012 |
int b = r ? r->KeyRange.low : 128; |
int b = r ? r->KeyRange.low : 128; |
1013 |
|
|
1014 |
// gap: from a to b (not inclusive b) |
// gap: from a to b (not inclusive b) |
1015 |
|
|
1016 |
if (region->KeyRange.high + move.pos >= b) { |
if (region->KeyRange.high >= b) { |
1017 |
// not found the current gap yet, just continue |
// not found the current gap yet, just continue |
1018 |
} else { |
} else { |
1019 |
|
|
1020 |
if (a > region->KeyRange.low + k) { |
if (a > l) { |
1021 |
// this gap is too far to the right, break |
// this gap is too far to the right, break |
1022 |
break; |
break; |
1023 |
} |
} |
1024 |
|
|
1025 |
int newhigh = std::min(region->KeyRange.high + k, b - 1); |
int newhigh = std::min(l + regionsize, b - 1); |
1026 |
int newlo = newhigh - (region->KeyRange.high - region->KeyRange.low); |
int newlo = newhigh - regionsize; |
1027 |
|
|
1028 |
if (newlo >= a) { |
if (newlo >= a) { |
1029 |
// yes it fits - it's a candidate |
// yes it fits - it's a candidate |
1030 |
new_k = newlo - region->KeyRange.low; |
new_l = newlo; |
|
new_touch_left = a > 0 && a == newlo; |
|
|
new_touch_right = b < 128 && newhigh + 1 == b; |
|
1031 |
} |
} |
1032 |
} |
} |
1033 |
if (!r) break; |
if (!r) break; |
1041 |
|
|
1042 |
// gap from a to b (not inclusive b) |
// gap from a to b (not inclusive b) |
1043 |
|
|
1044 |
if (region->KeyRange.high + k >= b) { |
if (l + regionsize >= b) { |
1045 |
// not found the current gap yet, just continue |
// not found the current gap yet, just continue |
1046 |
} else { |
} else { |
1047 |
|
|
1048 |
if (a > region->KeyRange.low + move.pos) { |
if (a > region->KeyRange.low) { |
1049 |
// this gap is too far to the right, break |
// this gap is too far to the right, break |
1050 |
break; |
break; |
1051 |
} |
} |
1052 |
|
|
1053 |
int newlo = std::max(region->KeyRange.low + k, a); |
int newlo = std::max(l, a); |
1054 |
int newhigh = newlo + (region->KeyRange.high - region->KeyRange.low); |
int newhigh = newlo + regionsize; |
1055 |
|
|
1056 |
if (newhigh < b) { |
if (newhigh < b) { |
1057 |
// yes it fits - break as the first one is the best |
// yes it fits - break as the first one is the best |
1058 |
new_k = newlo - region->KeyRange.low; |
new_l = newlo; |
|
new_touch_left = a > 0 && a == newlo; |
|
|
new_touch_right = b < 128 && newhigh + 1 == b; |
|
1059 |
break; |
break; |
1060 |
} |
} |
1061 |
} |
} |
1064 |
} |
} |
1065 |
} |
} |
1066 |
} |
} |
1067 |
k = new_k; |
if (new_l == region->KeyRange.low) return; |
|
if (k == move.pos) return; |
|
|
|
|
|
#if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2 |
|
|
const Gdk::Color bg = get_style()->get_bg(Gtk::STATE_NORMAL); |
|
|
#else |
|
|
const Gdk::RGBA bg = get_style_context()->get_background_color(); |
|
|
#endif |
|
|
|
|
|
int prevx = int(w * (move.pos + region->KeyRange.low) / 128.0 + 0.5); |
|
|
x = int(w * (k + region->KeyRange.low) / 128.0 + 0.5); |
|
|
int prevx2 = int(w * (move.pos + region->KeyRange.high + 1) / 128.0 + 0.5); |
|
|
int x2 = int(w * (k + region->KeyRange.high + 1) / 128.0 + 0.5); |
|
|
|
|
|
if (!new_touch_left) { |
|
|
Gdk::Cairo::set_source_rgba(cr, black); |
|
|
cr->move_to(x + 0.5, 1); |
|
|
cr->line_to(x + 0.5, h1 - 1); |
|
|
cr->stroke(); |
|
|
} |
|
|
if (!new_touch_right) { |
|
|
Gdk::Cairo::set_source_rgba(cr, black); |
|
|
cr->move_to(x2 + 0.5, 1); |
|
|
cr->line_to(x2 + 0.5, h1 - 1); |
|
|
cr->stroke(); |
|
|
} |
|
|
|
|
|
if (k > move.pos) { |
|
|
Gdk::Cairo::set_source_rgba(cr, bg); |
|
|
cr->rectangle(prevx + (move.touch_left ? 1 : 0), 0, |
|
|
std::min(x, prevx2 + 1 - (move.touch_right ? 1 : 0)) - |
|
|
(prevx + (move.touch_left ? 1 : 0)), h1); |
|
|
cr->fill(); |
|
1068 |
|
|
1069 |
Gdk::Cairo::set_source_rgba(cr, black); |
int x1 = key_to_x(std::min(int(region->KeyRange.low), new_l), w); |
1070 |
cr->move_to(std::max(x, prevx2 + 1), 0.5); |
int x2 = key_to_x(std::max(int(region->KeyRange.high), |
1071 |
cr->line_to(x2 + 1, 0.5); |
new_l + regionsize) + 1, w) + 1; |
|
cr->move_to(std::max(x, prevx2 + 1), h1 - 0.5); |
|
|
cr->line_to(x2 + 1, h1 - 0.5); |
|
|
cr->stroke(); |
|
1072 |
|
|
1073 |
Gdk::Cairo::set_source_rgba(cr, red); |
Gdk::Rectangle rect(x1, 0, x2 - x1, h1); |
1074 |
cr->rectangle(std::max(x + 1, prevx2), 1, |
update_after_move(new_l); |
|
x2 - std::max(x + 1, prevx2), h1 - 2); |
|
|
cr->fill(); |
|
|
} else { |
|
|
Gdk::Cairo::set_source_rgba(cr, bg); |
|
|
cr->rectangle(std::max(x2 + 1, prevx + (move.touch_left ? 1 : 0)), 0, |
|
|
prevx2 + 1 - (move.touch_right ? 1 : 0) - |
|
|
std::max(x2 + 1, prevx + (move.touch_left ? 1 : 0)), h1); |
|
|
cr->fill(); |
|
1075 |
|
|
1076 |
Gdk::Cairo::set_source_rgba(cr, black); |
get_window()->invalidate_rect(rect, false); |
|
cr->move_to(x, 0.5); |
|
|
cr->line_to(std::min(x2, prevx - 1) + 1, 0.5); |
|
|
cr->move_to(x, h1 - 0.5); |
|
|
cr->line_to(std::min(x2, prevx - 1) + 1, h1 - 0.5); |
|
|
cr->stroke(); |
|
|
|
|
|
Gdk::Cairo::set_source_rgba(cr, red); |
|
|
cr->rectangle(x + 1, 1, std::min(x2 - 1, prevx) - x, h1 - 2); |
|
|
cr->fill(); |
|
|
} |
|
|
|
|
|
move.pos = k; |
|
|
move.touch_left = new_touch_left; |
|
|
move.touch_right = new_touch_right; |
|
1077 |
} |
} |
1078 |
|
|
1079 |
|
|
1081 |
{ |
{ |
1082 |
Glib::RefPtr<Gdk::Window> window = get_window(); |
Glib::RefPtr<Gdk::Window> window = get_window(); |
1083 |
int x, y; |
int x, y; |
1084 |
|
#if HAS_GDKMM_SEAT |
1085 |
|
x = event->x; |
1086 |
|
y = event->y; |
1087 |
|
Gdk::ModifierType state = Gdk::ModifierType(event->state); |
1088 |
|
#else |
1089 |
Gdk::ModifierType state = Gdk::ModifierType(0); |
Gdk::ModifierType state = Gdk::ModifierType(0); |
1090 |
window->get_pointer(x, y, state); |
window->get_pointer(x, y, state); |
1091 |
|
#endif |
1092 |
|
|
1093 |
// handle virtual MIDI keyboard |
// handle virtual MIDI keyboard |
1094 |
if (m_VirtKeybModeChoice.get_value() != VIRT_KEYBOARD_MODE_CHORD && |
if (m_VirtKeybModeChoice.get_value() != VIRT_KEYBOARD_MODE_CHORD && |
1096 |
event->y >= REGION_BLOCK_HEIGHT && |
event->y >= REGION_BLOCK_HEIGHT && |
1097 |
event->y < REGION_BLOCK_HEIGHT + KEYBOARD_HEIGHT) |
event->y < REGION_BLOCK_HEIGHT + KEYBOARD_HEIGHT) |
1098 |
{ |
{ |
1099 |
const int k = int(event->x / (get_width() - 1) * 128.0); |
const int k = x_to_key(event->x, get_width() - 1); |
1100 |
if (k != currentActiveKey) { |
if (k != currentActiveKey) { |
1101 |
int velocity = |
int velocity = |
1102 |
(event->y >= REGION_BLOCK_HEIGHT + KEYBOARD_HEIGHT - 1) ? 127 : |
(event->y >= REGION_BLOCK_HEIGHT + KEYBOARD_HEIGHT - 1) ? 127 : |
1119 |
#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 |
1120 |
window->set_cursor(Gdk::Cursor(Gdk::SB_H_DOUBLE_ARROW)); |
window->set_cursor(Gdk::Cursor(Gdk::SB_H_DOUBLE_ARROW)); |
1121 |
#else |
#else |
1122 |
window->set_cursor(Gdk::Cursor::create(Gdk::SB_H_DOUBLE_ARROW)); |
window->set_cursor( |
1123 |
|
# if GTKMM_MAJOR_VERSION < 3 || (GTKMM_MAJOR_VERSION == 3 && GTKMM_MINOR_VERSION < 20) |
1124 |
|
Gdk::Cursor::create(Gdk::SB_H_DOUBLE_ARROW) |
1125 |
|
# else |
1126 |
|
Gdk::Cursor::create( |
1127 |
|
Glib::wrap(event->device, true)->get_seat()->get_display(), |
1128 |
|
Gdk::SB_H_DOUBLE_ARROW |
1129 |
|
) |
1130 |
|
# endif |
1131 |
|
); |
1132 |
#endif |
#endif |
1133 |
cursor_is_resize = true; |
cursor_is_resize = true; |
1134 |
} |
} |
1150 |
for (gig::Region* r = regions.first(); r ; r = next_region) { |
for (gig::Region* r = regions.first(); r ; r = next_region) { |
1151 |
next_region = regions.next(); |
next_region = regions.next(); |
1152 |
|
|
1153 |
int lo = int(w * (r->KeyRange.low) / 128.0 + 0.5); |
int lo = key_to_x(r->KeyRange.low, w); |
1154 |
if (x <= lo - 2) break; |
if (x <= lo - 2) break; |
1155 |
if (x < lo + 2) { |
if (x < lo + 2) { |
1156 |
resize.region = r; |
resize.region = r; |
1173 |
return resize.min != resize.max; |
return resize.min != resize.max; |
1174 |
} |
} |
1175 |
if (!next_region || r->KeyRange.high + 1 != next_region->KeyRange.low) { |
if (!next_region || r->KeyRange.high + 1 != next_region->KeyRange.low) { |
1176 |
int hi = int(w * (r->KeyRange.high + 1) / 128.0 + 0.5); |
int hi = key_to_x(r->KeyRange.high + 1, w); |
1177 |
if (x <= hi - 2) break; |
if (x <= hi - 2) break; |
1178 |
if (x < hi + 2) { |
if (x < hi + 2) { |
1179 |
// edit high limit |
// edit high limit |
1208 |
// add "Keygroup" checkbox |
// add "Keygroup" checkbox |
1209 |
Gtk::CheckButton checkBoxKeygroup(_("Member of a Keygroup (Exclusive Group)")); |
Gtk::CheckButton checkBoxKeygroup(_("Member of a Keygroup (Exclusive Group)")); |
1210 |
checkBoxKeygroup.set_active(region->KeyGroup); |
checkBoxKeygroup.set_active(region->KeyGroup); |
1211 |
|
#if USE_GTKMM_BOX |
1212 |
|
dialog.get_content_area()->pack_start(checkBoxKeygroup); |
1213 |
|
#else |
1214 |
dialog.get_vbox()->pack_start(checkBoxKeygroup); |
dialog.get_vbox()->pack_start(checkBoxKeygroup); |
1215 |
|
#endif |
1216 |
checkBoxKeygroup.show(); |
checkBoxKeygroup.show(); |
1217 |
// add "Keygroup" spinbox |
// add "Keygroup" spinbox |
1218 |
#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 |
1222 |
Gtk::SpinButton spinBox(Gtk::Adjustment::create(1, 1, 999)); |
Gtk::SpinButton spinBox(Gtk::Adjustment::create(1, 1, 999)); |
1223 |
#endif |
#endif |
1224 |
if (region->KeyGroup) spinBox.set_value(region->KeyGroup); |
if (region->KeyGroup) spinBox.set_value(region->KeyGroup); |
1225 |
|
#if USE_GTKMM_BOX |
1226 |
|
dialog.get_content_area()->pack_start(spinBox); |
1227 |
|
#else |
1228 |
dialog.get_vbox()->pack_start(spinBox); |
dialog.get_vbox()->pack_start(spinBox); |
1229 |
|
#endif |
1230 |
spinBox.show(); |
spinBox.show(); |
1231 |
// add OK and CANCEL buttons to the dialog |
// add OK and CANCEL buttons to the dialog |
1232 |
|
#if HAS_GTKMM_STOCK |
1233 |
dialog.add_button(Gtk::Stock::OK, 0); |
dialog.add_button(Gtk::Stock::OK, 0); |
1234 |
dialog.add_button(Gtk::Stock::CANCEL, 1); |
dialog.add_button(Gtk::Stock::CANCEL, 1); |
1235 |
|
#else |
1236 |
|
dialog.add_button(_("_OK"), 0); |
1237 |
|
dialog.add_button(_("_Cancel"), 1); |
1238 |
|
#endif |
1239 |
|
dialog.set_position(Gtk::WIN_POS_MOUSE); |
1240 |
|
#if HAS_GTKMM_SHOW_ALL_CHILDREN |
1241 |
dialog.show_all_children(); |
dialog.show_all_children(); |
1242 |
|
#endif |
1243 |
if (!dialog.run()) { // OK selected ... |
if (!dialog.run()) { // OK selected ... |
1244 |
region->KeyGroup = |
region->KeyGroup = |
1245 |
(checkBoxKeygroup.get_active()) ? spinBox.get_value_as_int() : 0; |
(checkBoxKeygroup.get_active()) ? spinBox.get_value_as_int() : 0; |