/[svn]/gigedit/trunk/src/gigedit/dimregionchooser.cpp
ViewVC logotype

Contents of /gigedit/trunk/src/gigedit/dimregionchooser.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2470 - (show annotations) (download)
Sun Sep 15 13:31:04 2013 UTC (10 years, 7 months ago) by persson
File size: 31373 byte(s)
* fixed compilation error with newer glibmm
* minor update of Swedish and German translations
* Mac OS X: initialize gtk and gettext with files from base directory
  of the libgigedit library
* Mac OS X: fixed "recently used" in file dialogs
* Mac OS X: avoid crash when starting gigedit as an application bundle

1 /*
2 * Copyright (C) 2006-2011 Andreas Persson
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2, or (at
7 * your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with program; see the file COPYING. If not, write to the Free
16 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
17 * 02110-1301 USA.
18 */
19
20 #include "dimregionchooser.h"
21 #include <cairomm/context.h>
22 #include <gdkmm/cursor.h>
23 #include <gdkmm/general.h>
24 #include <glibmm/stringutils.h>
25
26 #include "global.h"
27
28 DimRegionChooser::DimRegionChooser() :
29 red("#8070ff"),
30 black("black"),
31 white("white")
32 {
33 instrument = 0;
34 region = 0;
35 dimregno = -1;
36 focus_line = 0;
37 resize.active = false;
38 cursor_is_resize = false;
39 h = 20;
40 set_can_focus();
41 add_events(Gdk::BUTTON_PRESS_MASK | Gdk::POINTER_MOTION_MASK |
42 Gdk::POINTER_MOTION_HINT_MASK);
43
44 for (int i = 0 ; i < 256 ; i++) dimvalue[i] = 0;
45 labels_changed = true;
46 }
47
48 DimRegionChooser::~DimRegionChooser()
49 {
50 }
51
52 #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
53 bool DimRegionChooser::on_expose_event(GdkEventExpose* e)
54 {
55 double clipx1 = e->area.x;
56 double clipx2 = e->area.x + e->area.width;
57 double clipy1 = e->area.y;
58 double clipy2 = e->area.y + e->area.height;
59
60 const Cairo::RefPtr<Cairo::Context>& cr =
61 get_window()->create_cairo_context();
62 #if 0
63 }
64 #endif
65 #else
66 bool DimRegionChooser::on_draw(const Cairo::RefPtr<Cairo::Context>& cr)
67 {
68 double clipx1, clipx2, clipy1, clipy2;
69 cr->get_clip_extents(clipx1, clipy1, clipx2, clipy2);
70 #endif
71
72 if (!region) return true;
73
74 // This is where we draw on the window
75 int w = get_width();
76 Glib::RefPtr<Pango::Context> context = get_pango_context();
77
78 Glib::RefPtr<Pango::Layout> layout = Pango::Layout::create(context);
79 cr->set_line_width(1);
80
81 int y = 0;
82 if (labels_changed || label_width - 10 > clipx1) {
83 // draw labels on the left (reflecting the dimension type)
84 double maxwidth = 0;
85 for (int i = 0 ; i < region->Dimensions ; i++) {
86 int nbZones = region->pDimensionDefinitions[i].zones;
87 if (nbZones) {
88 const char* dstr;
89 char dstrbuf[10];
90 switch (region->pDimensionDefinitions[i].dimension) {
91 case gig::dimension_none: dstr=_("none"); break;
92 case gig::dimension_samplechannel: dstr=_("samplechannel");
93 break;
94 case gig::dimension_layer: dstr=_("layer"); break;
95 case gig::dimension_velocity: dstr=_("velocity"); break;
96 case gig::dimension_channelaftertouch:
97 dstr=_("channelaftertouch"); break;
98 case gig::dimension_releasetrigger:
99 dstr=_("releasetrigger"); break;
100 case gig::dimension_keyboard: dstr=_("keyswitching"); break;
101 case gig::dimension_roundrobin: dstr=_("roundrobin"); break;
102 case gig::dimension_random: dstr=_("random"); break;
103 case gig::dimension_smartmidi: dstr=_("smartmidi"); break;
104 case gig::dimension_roundrobinkeyboard:
105 dstr=_("roundrobinkeyboard"); break;
106 case gig::dimension_modwheel: dstr=_("modwheel"); break;
107 case gig::dimension_breath: dstr=_("breath"); break;
108 case gig::dimension_foot: dstr=_("foot"); break;
109 case gig::dimension_portamentotime:
110 dstr=_("portamentotime"); break;
111 case gig::dimension_effect1: dstr=_("effect1"); break;
112 case gig::dimension_effect2: dstr=_("effect2"); break;
113 case gig::dimension_genpurpose1: dstr=_("genpurpose1"); break;
114 case gig::dimension_genpurpose2: dstr=_("genpurpose2"); break;
115 case gig::dimension_genpurpose3: dstr=_("genpurpose3"); break;
116 case gig::dimension_genpurpose4: dstr=_("genpurpose4"); break;
117 case gig::dimension_sustainpedal:
118 dstr=_("sustainpedal"); break;
119 case gig::dimension_portamento: dstr=_("portamento"); break;
120 case gig::dimension_sostenutopedal:
121 dstr=_("sostenutopedal"); break;
122 case gig::dimension_softpedal: dstr=_("softpedal"); break;
123 case gig::dimension_genpurpose5: dstr=_("genpurpose5"); break;
124 case gig::dimension_genpurpose6: dstr=_("genpurpose6"); break;
125 case gig::dimension_genpurpose7: dstr=_("genpurpose7"); break;
126 case gig::dimension_genpurpose8: dstr=_("genpurpose8"); break;
127 case gig::dimension_effect1depth:
128 dstr=_("effect1depth"); break;
129 case gig::dimension_effect2depth:
130 dstr=_("effect2depth"); break;
131 case gig::dimension_effect3depth:
132 dstr=_("effect3depth"); break;
133 case gig::dimension_effect4depth:
134 dstr=_("effect4depth"); break;
135 case gig::dimension_effect5depth:
136 dstr=_("effect5depth"); break;
137 default:
138 sprintf(dstrbuf, "%d",
139 region->pDimensionDefinitions[i].dimension);
140 dstr = dstrbuf;
141 break;
142 }
143 layout->set_text(dstr);
144
145 Pango::Rectangle rectangle = layout->get_logical_extents();
146 double text_w = double(rectangle.get_width()) / Pango::SCALE;
147 if (text_w > maxwidth) maxwidth = text_w;
148
149 if (y + h > clipy1 && y < clipy2 && text_w >= clipx1) {
150 double text_h = double(rectangle.get_height()) /
151 Pango::SCALE;
152 #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
153 const Gdk::Color fg = get_style()->get_fg(get_state());
154 #else
155 const Gdk::RGBA fg =
156 get_style_context()->get_color(get_state_flags());
157 #endif
158 Gdk::Cairo::set_source_rgba(cr, fg);
159 cr->move_to(4, int(y + (h - text_h) / 2 + 0.5));
160 #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 16) || GTKMM_MAJOR_VERSION < 2
161 pango_cairo_show_layout(cr->cobj(), layout->gobj());
162 #else
163 layout->show_in_cairo_context(cr);
164 #endif
165 }
166 }
167 y += h;
168 }
169 label_width = int(maxwidth + 10);
170 labels_changed = false;
171 }
172 if (label_width >= clipx2) return true;
173
174 // draw dimensions' zones areas
175 y = 0;
176 int bitpos = 0;
177 for (int i = 0 ; i < region->Dimensions ; i++) {
178 int nbZones = region->pDimensionDefinitions[i].zones;
179 if (nbZones) {
180 if (y >= clipy2) break;
181 if (y + h > clipy1) {
182 // draw focus rectangle around dimension's label and zones
183 if (has_focus() && focus_line == i) {
184 #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
185 Gdk::Rectangle farea(0, y, 150, 20);
186 get_style()->paint_focus(get_window(), get_state(), farea,
187 *this, "",
188 0, y, label_width, 20);
189 #else
190 get_style_context()->render_focus(cr,
191 0, y, label_width, 20);
192 #endif
193 }
194
195 // draw top and bottom lines of dimension's zones
196 Gdk::Cairo::set_source_rgba(cr, black);
197 cr->move_to(label_width, y + 0.5);
198 cr->line_to(w, y + 0.5);
199 cr->move_to(w, y + h - 0.5);
200 cr->line_to(label_width, y + h - 0.5);
201 cr->stroke();
202
203 // erase whole dimension's zones area
204 Gdk::Cairo::set_source_rgba(cr, white);
205 cr->rectangle(label_width + 1, y + 1,
206 (w - label_width - 2), h - 2);
207 cr->fill();
208
209 int c = 0;
210 if (dimregno >= 0) {
211 int mask =
212 ~(((1 << region->pDimensionDefinitions[i].bits) - 1) <<
213 bitpos);
214 c = dimregno & mask; // mask away this dimension
215 }
216 bool customsplits =
217 ((region->pDimensionDefinitions[i].split_type ==
218 gig::split_type_normal &&
219 region->pDimensionRegions[c]->DimensionUpperLimits[i]) ||
220 (region->pDimensionDefinitions[i].dimension ==
221 gig::dimension_velocity &&
222 region->pDimensionRegions[c]->VelocityUpperLimit));
223
224 // draw dimension's zone borders
225 Gdk::Cairo::set_source_rgba(cr, black);
226 if (customsplits) {
227 cr->move_to(label_width + 0.5, y + 1);
228 cr->line_to(label_width + 0.5, y + h - 1);
229
230 for (int j = 0 ; j < nbZones ; j++) {
231 gig::DimensionRegion* d =
232 region->pDimensionRegions[c + (j << bitpos)];
233 int upperLimit = d->DimensionUpperLimits[i];
234 if (!upperLimit) upperLimit = d->VelocityUpperLimit;
235 int v = upperLimit + 1;
236 int x = int((w - label_width - 1) * v / 128.0 + 0.5) +
237 label_width;
238 if (x >= clipx2) break;
239 if (x < clipx1) continue;
240 cr->move_to(x + 0.5, y + 1);
241 cr->line_to(x + 0.5, y + h - 1);
242 }
243 } else {
244 for (int j = 0 ; j <= nbZones ; j++) {
245 int x = int((w - label_width - 1) * j /
246 double(nbZones) + 0.5) + label_width;
247 if (x >= clipx2) break;
248 if (x < clipx1) continue;
249 cr->move_to(x + 0.5, y + 1);
250 cr->line_to(x + 0.5, y + h - 1);
251 }
252 }
253 cr->stroke();
254
255 // draw fill for currently selected zone
256 if (dimregno >= 0) {
257 Gdk::Cairo::set_source_rgba(cr, red);
258 int dr = (dimregno >> bitpos) &
259 ((1 << region->pDimensionDefinitions[i].bits) - 1);
260
261 int x1 = -1, x2 = -1;
262 if (customsplits) {
263 x1 = label_width;
264 for (int j = 0 ; j < nbZones && x1 + 1 < clipx2 ; j++) {
265 gig::DimensionRegion* d =
266 region->pDimensionRegions[c + (j << bitpos)];
267 int upperLimit = d->DimensionUpperLimits[i];
268 if (!upperLimit) {
269 upperLimit = d->VelocityUpperLimit;
270 }
271 int v = upperLimit + 1;
272 x2 = int((w - label_width - 1) * v / 128.0 +
273 0.5) + label_width;
274 if (j == dr && x1 < x2) {
275 cr->rectangle(x1 + 1, y + 1,
276 (x2 - x1) - 1, h - 2);
277 cr->fill();
278 break;
279 }
280 x1 = x2;
281 }
282 } else {
283 if (dr < nbZones) {
284 x1 = int((w - label_width - 1) * dr /
285 double(nbZones) + 0.5);
286 x2 = int((w - label_width - 1) * (dr + 1) /
287 double(nbZones) + 0.5);
288 cr->rectangle(label_width + x1 + 1, y + 1,
289 (x2 - x1) - 1, h - 2);
290 cr->fill();
291 }
292 }
293
294 // draw text showing the beginning of the dimension zone
295 // as numeric value to the user
296 if (x1 >= 0) {
297 Glib::RefPtr<Pango::Layout> layout = Pango::Layout::create(context);
298 int v = roundf(float(x1 - label_width) / float(w - label_width) * 127.f);
299 if (dr > 0) v++;
300 layout->set_text(Glib::Ascii::dtostr(v));
301 Gdk::Cairo::set_source_rgba(cr, black);
302 Pango::Rectangle rect = layout->get_logical_extents();
303
304 int text_width, text_height;
305 // get the text dimensions
306 layout->get_pixel_size(text_width, text_height);
307 // move text to the right end of the dimension zone
308 cr->move_to(x1 + 1, y + 1);
309 #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 16) || GTKMM_MAJOR_VERSION < 2
310 pango_cairo_show_layout(cr->cobj(), layout->gobj());
311 #else
312 layout->show_in_cairo_context(cr);
313 #endif
314 }
315 // draw text showing the end of the dimension zone
316 // as numeric value to the user
317 if (x2 >= 0) {
318 Glib::RefPtr<Pango::Layout> layout = Pango::Layout::create(context);
319 const int v = roundf(float(x2 - label_width) / float(w - label_width) * 127.f);
320 layout->set_text(Glib::Ascii::dtostr(v));
321 Gdk::Cairo::set_source_rgba(cr, black);
322 Pango::Rectangle rect = layout->get_logical_extents();
323
324 int text_width, text_height;
325 // get the text dimensions
326 layout->get_pixel_size(text_width, text_height);
327 // move text to the right end of the dimension zone
328 cr->move_to(x2 - text_width - 1, y + 1);
329 #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 16) || GTKMM_MAJOR_VERSION < 2
330 pango_cairo_show_layout(cr->cobj(), layout->gobj());
331 #else
332 layout->show_in_cairo_context(cr);
333 #endif
334 }
335 }
336 }
337
338 y += h;
339 }
340 bitpos += region->pDimensionDefinitions[i].bits;
341 }
342
343 return true;
344 }
345
346 void DimRegionChooser::set_region(gig::Region* region)
347 {
348 this->region = region;
349 dimregno = 0;
350 nbDimensions = 0;
351 if (region) {
352 int bitcount = 0;
353 for (int dim = 0 ; dim < region->Dimensions ; dim++) {
354 if (region->pDimensionDefinitions[dim].bits == 0) continue;
355 nbDimensions++;
356
357 int z = std::min(dimvalue[region->pDimensionDefinitions[dim].dimension],
358 region->pDimensionDefinitions[dim].zones - 1);
359 dimregno |= (z << bitcount);
360 bitcount += region->pDimensionDefinitions[dim].bits;
361 }
362 dimreg = region->pDimensionRegions[dimregno];
363 } else {
364 dimreg = 0;
365 }
366 dimregion_selected();
367 set_size_request(800, region ? nbDimensions * 20 : 0);
368
369 labels_changed = true;
370 queue_resize();
371 }
372
373
374 void DimRegionChooser::get_dimregions(const gig::Region* region, bool stereo,
375 std::set<gig::DimensionRegion*>& dimregs) const
376 {
377 int dimregno = 0;
378 int bitcount = 0;
379 int stereo_bit = 0;
380 for (int dim = 0 ; dim < region->Dimensions ; dim++) {
381 if (region->pDimensionDefinitions[dim].bits == 0) continue;
382 if (stereo &&
383 region->pDimensionDefinitions[dim].dimension == gig::dimension_samplechannel) {
384 stereo_bit = (1 << bitcount);
385 } else {
386 int z = std::min(dimvalue[region->pDimensionDefinitions[dim].dimension],
387 region->pDimensionDefinitions[dim].zones - 1);
388 dimregno |= (z << bitcount);
389 }
390 bitcount += region->pDimensionDefinitions[dim].bits;
391 }
392 dimregs.insert(region->pDimensionRegions[dimregno]);
393 if (stereo_bit) dimregs.insert(region->pDimensionRegions[dimregno | stereo_bit]);
394 }
395
396 void DimRegionChooser::update_after_resize()
397 {
398 if (region->pDimensionDefinitions[resize.dimension].dimension == gig::dimension_velocity) {
399
400 int bitpos = 0;
401 for (int j = 0 ; j < resize.dimension ; j++) {
402 bitpos += region->pDimensionDefinitions[j].bits;
403 }
404 int mask =
405 ~(((1 << region->pDimensionDefinitions[resize.dimension].bits) - 1) << bitpos);
406 int c = dimregno & mask; // mask away this dimension
407
408 if (region->pDimensionRegions[c]->DimensionUpperLimits[resize.dimension] == 0) {
409 // the velocity dimension didn't previously have
410 // custom v3 splits, so we initialize all splits with
411 // default values
412 int nbZones = region->pDimensionDefinitions[resize.dimension].zones;
413 for (int j = 0 ; j < nbZones ; j++) {
414 gig::DimensionRegion* d = region->pDimensionRegions[c + (j << bitpos)];
415 d->DimensionUpperLimits[resize.dimension] = int(128.0 * (j + 1) / nbZones - 1);
416 }
417 }
418 if (region->pDimensionRegions[c]->VelocityUpperLimit == 0) {
419 // the velocity dimension didn't previously have
420 // custom v2 splits, so we initialize all splits with
421 // default values
422 int nbZones = region->pDimensionDefinitions[resize.dimension].zones;
423 for (int j = 0 ; j < nbZones ; j++) {
424 gig::DimensionRegion* d = region->pDimensionRegions[c + (j << bitpos)];
425 d->VelocityUpperLimit = int(128.0 * (j + 1) / nbZones - 1);
426 }
427 }
428
429 gig::DimensionRegion* d = region->pDimensionRegions[c + resize.offset];
430 // update both v2 and v3 values
431 d->DimensionUpperLimits[resize.dimension] = resize.pos - 1;
432 d->VelocityUpperLimit = resize.pos - 1;
433
434 } else {
435 for (int i = 0 ; i < region->DimensionRegions ; ) {
436
437 if (region->pDimensionRegions[i]->DimensionUpperLimits[resize.dimension] == 0) {
438 // the dimension didn't previously have custom
439 // limits, so we have to set default limits for
440 // all the dimension regions
441 int bitpos = 0;
442 for (int j = 0 ; j < resize.dimension ; j++) {
443 bitpos += region->pDimensionDefinitions[j].bits;
444 }
445 int nbZones = region->pDimensionDefinitions[resize.dimension].zones;
446
447 for (int j = 0 ; j < nbZones ; j++) {
448 gig::DimensionRegion* d = region->pDimensionRegions[i + (j << bitpos)];
449 d->DimensionUpperLimits[resize.dimension] = int(128.0 * (j + 1) / nbZones - 1);
450 }
451 }
452 gig::DimensionRegion* d = region->pDimensionRegions[i + resize.offset];
453 d->DimensionUpperLimits[resize.dimension] = resize.pos - 1;
454
455 int bitpos = 0;
456 int j;
457 for (j = 0 ; j < region->Dimensions ; j++) {
458 if (j != resize.dimension) {
459 int maxzones = 1 << region->pDimensionDefinitions[j].bits;
460 int dimj = (i >> bitpos) & (maxzones - 1);
461 if (dimj + 1 < region->pDimensionDefinitions[j].zones) break;
462 }
463 bitpos += region->pDimensionDefinitions[j].bits;
464 }
465 if (j == region->Dimensions) break;
466 i = (i & ~((1 << bitpos) - 1)) + (1 << bitpos);
467 }
468 }
469 }
470
471 bool DimRegionChooser::on_button_release_event(GdkEventButton* event)
472 {
473 if (resize.active) {
474 #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
475 get_window()->pointer_ungrab(event->time);
476 #else
477 Glib::wrap(event->device, true)->ungrab(event->time);
478 #endif
479 resize.active = false;
480
481 region_changed();
482
483 if (!is_in_resize_zone(event->x, event->y) && cursor_is_resize) {
484 get_window()->set_cursor();
485 cursor_is_resize = false;
486 }
487 }
488 return true;
489 }
490
491 bool DimRegionChooser::on_button_press_event(GdkEventButton* event)
492 {
493 int w = get_width();
494 if (region && event->y < nbDimensions * h &&
495 event->x >= label_width && event->x < w) {
496
497 if (is_in_resize_zone(event->x, event->y)) {
498 #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
499 get_window()->pointer_grab(false,
500 Gdk::BUTTON_RELEASE_MASK |
501 Gdk::POINTER_MOTION_MASK |
502 Gdk::POINTER_MOTION_HINT_MASK,
503 Gdk::Cursor(Gdk::SB_H_DOUBLE_ARROW),
504 event->time);
505 #else
506 Glib::wrap(event->device, true)->grab(get_window(),
507 Gdk::OWNERSHIP_NONE,
508 false,
509 Gdk::BUTTON_RELEASE_MASK |
510 Gdk::POINTER_MOTION_MASK |
511 Gdk::POINTER_MOTION_HINT_MASK,
512 Gdk::Cursor::create(Gdk::SB_H_DOUBLE_ARROW),
513 event->time);
514 #endif
515 resize.active = true;
516 } else {
517 int ydim = int(event->y / h);
518 int dim;
519 for (dim = 0 ; dim < region->Dimensions ; dim++) {
520 if (region->pDimensionDefinitions[dim].bits == 0) continue;
521 if (ydim == 0) break;
522 ydim--;
523 }
524 int nbZones = region->pDimensionDefinitions[dim].zones;
525
526 int z = -1;
527 int bitpos = 0;
528 for (int i = 0 ; i < dim ; i++) {
529 bitpos += region->pDimensionDefinitions[i].bits;
530 }
531
532 int i = dim;
533 if (dimregno < 0) dimregno = 0;
534 int mask = ~(((1 << region->pDimensionDefinitions[i].bits) - 1) << bitpos);
535 int c = dimregno & mask; // mask away this dimension
536
537 bool customsplits =
538 ((region->pDimensionDefinitions[i].split_type == gig::split_type_normal &&
539 region->pDimensionRegions[c]->DimensionUpperLimits[i]) ||
540 (region->pDimensionDefinitions[i].dimension == gig::dimension_velocity &&
541 region->pDimensionRegions[c]->VelocityUpperLimit));
542 if (customsplits) {
543 int val = int((event->x - label_width) * 128 / (w - label_width - 1));
544
545 if (region->pDimensionRegions[c]->DimensionUpperLimits[i]) {
546 for (z = 0 ; z < nbZones ; z++) {
547 gig::DimensionRegion* d = region->pDimensionRegions[c + (z << bitpos)];
548 if (val <= d->DimensionUpperLimits[i]) break;
549 }
550 } else {
551 for (z = 0 ; z < nbZones ; z++) {
552 gig::DimensionRegion* d = region->pDimensionRegions[c + (z << bitpos)];
553 if (val <= d->VelocityUpperLimit) break;
554 }
555 }
556 } else {
557 z = int((event->x - label_width) * nbZones / (w - label_width - 1));
558 }
559
560 printf("dim=%d z=%d dimensionsource=%d split_type=%d zones=%d zone_size=%f\n", dim, z,
561 region->pDimensionDefinitions[dim].dimension,
562 region->pDimensionDefinitions[dim].split_type,
563 region->pDimensionDefinitions[dim].zones,
564 region->pDimensionDefinitions[dim].zone_size);
565 dimvalue[region->pDimensionDefinitions[dim].dimension] = z;
566
567 dimregno = c | (z << bitpos);
568
569 focus_line = dim;
570 if (has_focus()) queue_draw();
571 else grab_focus();
572 dimreg = region->pDimensionRegions[dimregno];
573 dimregion_selected();
574 }
575 }
576 return true;
577 }
578
579 bool DimRegionChooser::on_motion_notify_event(GdkEventMotion* event)
580 {
581 Glib::RefPtr<Gdk::Window> window = get_window();
582 int x, y;
583 Gdk::ModifierType state = Gdk::ModifierType(0);
584 window->get_pointer(x, y, state);
585
586 if (resize.active) {
587 int w = get_width();
588 int k = int((x - label_width) * 128.0 / (w - label_width - 1) + 0.5);
589
590 if (k < resize.min) k = resize.min;
591 else if (k > resize.max) k = resize.max;
592
593 if (k < 2) k = 2; // k is upper limit + 1, upper limit 0 is forbidden
594
595 if (k != resize.pos) {
596 int prevx = int((w - label_width - 1) * resize.pos / 128.0 + 0.5) + label_width;
597 int x = int((w - label_width - 1) * k / 128.0 + 0.5) + label_width;
598 int y = resize.dimension * h;
599 int x1, x2;
600 if (k > resize.pos) {
601 x1 = prevx;
602 x2 = x;
603 } else {
604 x1 = x;
605 x2 = prevx;
606 }
607 Gdk::Rectangle rect(x1, y + 1, x2 - x1 + 1, h - 2);
608
609 resize.pos = k;
610 update_after_resize();
611 get_window()->invalidate_rect(rect, false);
612 }
613 } else {
614 if (is_in_resize_zone(x, y)) {
615 if (!cursor_is_resize) {
616 #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
617 window->set_cursor(Gdk::Cursor(Gdk::SB_H_DOUBLE_ARROW));
618 #else
619 window->set_cursor(Gdk::Cursor::create(Gdk::SB_H_DOUBLE_ARROW));
620 #endif
621 cursor_is_resize = true;
622 }
623 } else if (cursor_is_resize) {
624 window->set_cursor();
625 cursor_is_resize = false;
626 }
627 }
628 return true;
629 }
630
631 bool DimRegionChooser::is_in_resize_zone(double x, double y)
632 {
633 int w = get_width();
634 if (region && y < nbDimensions * h && x >= label_width && x < w) {
635 int ydim = int(y / h);
636 int dim;
637 int bitpos = 0;
638 for (dim = 0 ; dim < region->Dimensions ; dim++) {
639 if (region->pDimensionDefinitions[dim].bits == 0) continue;
640 if (ydim == 0) break;
641 ydim--;
642 bitpos += region->pDimensionDefinitions[dim].bits;
643 }
644 int nbZones = region->pDimensionDefinitions[dim].zones;
645
646 int c = 0;
647 if (dimregno >= 0) {
648 int mask = ~(((1 << region->pDimensionDefinitions[dim].bits) - 1) << bitpos);
649 c = dimregno & mask; // mask away this dimension
650 }
651 const bool customsplits =
652 ((region->pDimensionDefinitions[dim].split_type == gig::split_type_normal &&
653 region->pDimensionRegions[c]->DimensionUpperLimits[dim]) ||
654 (region->pDimensionDefinitions[dim].dimension == gig::dimension_velocity &&
655 region->pDimensionRegions[c]->VelocityUpperLimit));
656
657 // dimensions of split_type_bit cannot be resized
658 if (region->pDimensionDefinitions[dim].split_type != gig::split_type_bit) {
659 int prev_limit = 0;
660 for (int iZone = 0 ; iZone < nbZones - 1 ; iZone++) {
661 gig::DimensionRegion* d = region->pDimensionRegions[c + (iZone << bitpos)];
662 const int upperLimit =
663 (customsplits) ?
664 (d->DimensionUpperLimits[dim]) ?
665 d->DimensionUpperLimits[dim] : d->VelocityUpperLimit
666 : (iZone+1) * (int)region->pDimensionDefinitions[dim].zone_size - 1;
667 int limit = upperLimit + 1;
668 int limitx = int((w - label_width - 1) * limit / 128.0 + 0.5) + label_width;
669 if (x <= limitx - 2) break;
670 if (x <= limitx + 2) {
671 resize.dimension = dim;
672 resize.offset = iZone << bitpos;
673 resize.pos = limit;
674 resize.min = prev_limit;
675
676 int dr = (dimregno >> bitpos) &
677 ((1 << region->pDimensionDefinitions[dim].bits) - 1);
678 resize.selected = dr == iZone ? resize.left :
679 dr == iZone + 1 ? resize.right : resize.none;
680
681 iZone++;
682 gig::DimensionRegion* d = region->pDimensionRegions[c + (iZone << bitpos)];
683
684 const int upperLimit =
685 (customsplits) ?
686 (d->DimensionUpperLimits[dim]) ?
687 d->DimensionUpperLimits[dim] : d->VelocityUpperLimit
688 : (iZone+1) * (int)region->pDimensionDefinitions[dim].zone_size - 1;
689
690 int limit = upperLimit + 1;
691 resize.max = limit;
692 return true;
693 }
694 prev_limit = limit;
695 }
696 }
697 }
698 return false;
699 }
700
701 sigc::signal<void>& DimRegionChooser::signal_dimregion_selected()
702 {
703 return dimregion_selected;
704 }
705
706 sigc::signal<void>& DimRegionChooser::signal_region_changed()
707 {
708 return region_changed;
709 }
710
711 bool DimRegionChooser::on_focus(Gtk::DirectionType direction)
712 {
713 // TODO: kolla att region finns osv, dvs att det g�r att s�tta
714 // fokus.
715 if (direction == Gtk::DIR_TAB_FORWARD ||
716 direction == Gtk::DIR_DOWN) {
717 if (!has_focus()) {
718 focus_line = 0;
719 grab_focus();
720 return true;
721 } else {
722 if (focus_line + 1 < region->Dimensions) {
723 focus_line++;
724 queue_draw();
725 return true;
726 } else {
727 return false;
728 }
729 }
730 } else if (direction == Gtk::DIR_TAB_BACKWARD ||
731 direction == Gtk::DIR_UP) {
732 if (!has_focus()) {
733 focus_line = region->Dimensions - 1;
734 grab_focus();
735 return true;
736 } else {
737 if (focus_line > 0) {
738 focus_line--;
739 queue_draw();
740 return true;
741 } else {
742 return false;
743 }
744 }
745 } else if (!has_focus()) {
746 // TODO: kolla att focus_line finns!
747 grab_focus();
748 return true;
749 } else {
750 // TODO: �ka eller minska v�rde!
751 }
752 }

  ViewVC Help
Powered by ViewVC