/[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 2246 - (show annotations) (download)
Fri Aug 19 10:55:41 2011 UTC (12 years, 7 months ago) by persson
File size: 28949 byte(s)
* gtkmm 3 fix: rewrote the custom widgets (regionchooser and
  dimregionchooser) so they only draw pixels in the on_draw
  method. This should make them work again in newer gtkmm 3
  environments.

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

  ViewVC Help
Powered by ViewVC