/[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 2462 - (show annotations) (download)
Wed Sep 4 20:23:05 2013 UTC (10 years, 7 months ago) by schoenebeck
File size: 31341 byte(s)
* show dimension zone start and end as numeric text labels

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
260 int x1 = -1, x2 = -1;
261 if (customsplits) {
262 x1 = label_width;
263 for (int j = 0 ; j < nbZones && x1 + 1 < clipx2 ; j++) {
264 gig::DimensionRegion* d =
265 region->pDimensionRegions[c + (j << bitpos)];
266 int upperLimit = d->DimensionUpperLimits[i];
267 if (!upperLimit) {
268 upperLimit = d->VelocityUpperLimit;
269 }
270 int v = upperLimit + 1;
271 x2 = int((w - label_width - 1) * v / 128.0 +
272 0.5) + label_width;
273 if (j == dr && x1 < x2) {
274 cr->rectangle(x1 + 1, y + 1,
275 (x2 - x1) - 1, h - 2);
276 cr->fill();
277 break;
278 }
279 x1 = x2;
280 }
281 } else {
282 if (dr < nbZones) {
283 x1 = int((w - label_width - 1) * dr /
284 double(nbZones) + 0.5);
285 x2 = int((w - label_width - 1) * (dr + 1) /
286 double(nbZones) + 0.5);
287 cr->rectangle(label_width + x1 + 1, y + 1,
288 (x2 - x1) - 1, h - 2);
289 cr->fill();
290 }
291 }
292
293 // draw text showing the beginning of the dimension zone
294 // as numeric value to the user
295 if (x1 >= 0) {
296 Glib::RefPtr<Pango::Layout> layout = Pango::Layout::create(context);
297 int v = roundf(float(x1 - label_width) / float(w - label_width) * 127.f);
298 if (dr > 0) v++;
299 layout->set_text(Glib::Ascii::dtostr(v));
300 Gdk::Cairo::set_source_rgba(cr, black);
301 Pango::Rectangle rect = layout->get_logical_extents();
302
303 int text_width, text_height;
304 // get the text dimensions
305 layout->get_pixel_size(text_width, text_height);
306 // move text to the right end of the dimension zone
307 cr->move_to(x1 + 1, y + 1);
308 #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 16) || GTKMM_MAJOR_VERSION < 2
309 pango_cairo_show_layout(cr->cobj(), layout->gobj());
310 #else
311 layout->show_in_cairo_context(cr);
312 #endif
313 }
314 // draw text showing the end of the dimension zone
315 // as numeric value to the user
316 if (x2 >= 0) {
317 Glib::RefPtr<Pango::Layout> layout = Pango::Layout::create(context);
318 const int v = roundf(float(x2 - label_width) / float(w - label_width) * 127.f);
319 layout->set_text(Glib::Ascii::dtostr(v));
320 Gdk::Cairo::set_source_rgba(cr, black);
321 Pango::Rectangle rect = layout->get_logical_extents();
322
323 int text_width, text_height;
324 // get the text dimensions
325 layout->get_pixel_size(text_width, text_height);
326 // move text to the right end of the dimension zone
327 cr->move_to(x2 - text_width - 1, y + 1);
328 #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 16) || GTKMM_MAJOR_VERSION < 2
329 pango_cairo_show_layout(cr->cobj(), layout->gobj());
330 #else
331 layout->show_in_cairo_context(cr);
332 #endif
333 }
334 }
335 }
336
337 y += h;
338 }
339 bitpos += region->pDimensionDefinitions[i].bits;
340 }
341
342 return true;
343 }
344
345 void DimRegionChooser::set_region(gig::Region* region)
346 {
347 this->region = region;
348 dimregno = 0;
349 nbDimensions = 0;
350 if (region) {
351 int bitcount = 0;
352 for (int dim = 0 ; dim < region->Dimensions ; dim++) {
353 if (region->pDimensionDefinitions[dim].bits == 0) continue;
354 nbDimensions++;
355
356 int z = std::min(dimvalue[region->pDimensionDefinitions[dim].dimension],
357 region->pDimensionDefinitions[dim].zones - 1);
358 dimregno |= (z << bitcount);
359 bitcount += region->pDimensionDefinitions[dim].bits;
360 }
361 dimreg = region->pDimensionRegions[dimregno];
362 } else {
363 dimreg = 0;
364 }
365 dimregion_selected();
366 set_size_request(800, region ? nbDimensions * 20 : 0);
367
368 labels_changed = true;
369 queue_resize();
370 }
371
372
373 void DimRegionChooser::get_dimregions(const gig::Region* region, bool stereo,
374 std::set<gig::DimensionRegion*>& dimregs) const
375 {
376 int dimregno = 0;
377 int bitcount = 0;
378 int stereo_bit = 0;
379 for (int dim = 0 ; dim < region->Dimensions ; dim++) {
380 if (region->pDimensionDefinitions[dim].bits == 0) continue;
381 if (stereo &&
382 region->pDimensionDefinitions[dim].dimension == gig::dimension_samplechannel) {
383 stereo_bit = (1 << bitcount);
384 } else {
385 int z = std::min(dimvalue[region->pDimensionDefinitions[dim].dimension],
386 region->pDimensionDefinitions[dim].zones - 1);
387 dimregno |= (z << bitcount);
388 }
389 bitcount += region->pDimensionDefinitions[dim].bits;
390 }
391 dimregs.insert(region->pDimensionRegions[dimregno]);
392 if (stereo_bit) dimregs.insert(region->pDimensionRegions[dimregno | stereo_bit]);
393 }
394
395 void DimRegionChooser::update_after_resize()
396 {
397 if (region->pDimensionDefinitions[resize.dimension].dimension == gig::dimension_velocity) {
398
399 int bitpos = 0;
400 for (int j = 0 ; j < resize.dimension ; j++) {
401 bitpos += region->pDimensionDefinitions[j].bits;
402 }
403 int mask =
404 ~(((1 << region->pDimensionDefinitions[resize.dimension].bits) - 1) << bitpos);
405 int c = dimregno & mask; // mask away this dimension
406
407 if (region->pDimensionRegions[c]->DimensionUpperLimits[resize.dimension] == 0) {
408 // the velocity dimension didn't previously have
409 // custom v3 splits, so we initialize all splits with
410 // default values
411 int nbZones = region->pDimensionDefinitions[resize.dimension].zones;
412 for (int j = 0 ; j < nbZones ; j++) {
413 gig::DimensionRegion* d = region->pDimensionRegions[c + (j << bitpos)];
414 d->DimensionUpperLimits[resize.dimension] = int(128.0 * (j + 1) / nbZones - 1);
415 }
416 }
417 if (region->pDimensionRegions[c]->VelocityUpperLimit == 0) {
418 // the velocity dimension didn't previously have
419 // custom v2 splits, so we initialize all splits with
420 // default values
421 int nbZones = region->pDimensionDefinitions[resize.dimension].zones;
422 for (int j = 0 ; j < nbZones ; j++) {
423 gig::DimensionRegion* d = region->pDimensionRegions[c + (j << bitpos)];
424 d->VelocityUpperLimit = int(128.0 * (j + 1) / nbZones - 1);
425 }
426 }
427
428 gig::DimensionRegion* d = region->pDimensionRegions[c + resize.offset];
429 // update both v2 and v3 values
430 d->DimensionUpperLimits[resize.dimension] = resize.pos - 1;
431 d->VelocityUpperLimit = resize.pos - 1;
432
433 } else {
434 for (int i = 0 ; i < region->DimensionRegions ; ) {
435
436 if (region->pDimensionRegions[i]->DimensionUpperLimits[resize.dimension] == 0) {
437 // the dimension didn't previously have custom
438 // limits, so we have to set default limits for
439 // all the dimension regions
440 int bitpos = 0;
441 for (int j = 0 ; j < resize.dimension ; j++) {
442 bitpos += region->pDimensionDefinitions[j].bits;
443 }
444 int nbZones = region->pDimensionDefinitions[resize.dimension].zones;
445
446 for (int j = 0 ; j < nbZones ; j++) {
447 gig::DimensionRegion* d = region->pDimensionRegions[i + (j << bitpos)];
448 d->DimensionUpperLimits[resize.dimension] = int(128.0 * (j + 1) / nbZones - 1);
449 }
450 }
451 gig::DimensionRegion* d = region->pDimensionRegions[i + resize.offset];
452 d->DimensionUpperLimits[resize.dimension] = resize.pos - 1;
453
454 int bitpos = 0;
455 int j;
456 for (j = 0 ; j < region->Dimensions ; j++) {
457 if (j != resize.dimension) {
458 int maxzones = 1 << region->pDimensionDefinitions[j].bits;
459 int dimj = (i >> bitpos) & (maxzones - 1);
460 if (dimj + 1 < region->pDimensionDefinitions[j].zones) break;
461 }
462 bitpos += region->pDimensionDefinitions[j].bits;
463 }
464 if (j == region->Dimensions) break;
465 i = (i & ~((1 << bitpos) - 1)) + (1 << bitpos);
466 }
467 }
468 }
469
470 bool DimRegionChooser::on_button_release_event(GdkEventButton* event)
471 {
472 if (resize.active) {
473 #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
474 get_window()->pointer_ungrab(event->time);
475 #else
476 Glib::wrap(event->device, true)->ungrab(event->time);
477 #endif
478 resize.active = false;
479
480 region_changed();
481
482 if (!is_in_resize_zone(event->x, event->y) && cursor_is_resize) {
483 get_window()->set_cursor();
484 cursor_is_resize = false;
485 }
486 }
487 return true;
488 }
489
490 bool DimRegionChooser::on_button_press_event(GdkEventButton* event)
491 {
492 int w = get_width();
493 if (region && event->y < nbDimensions * h &&
494 event->x >= label_width && event->x < w) {
495
496 if (is_in_resize_zone(event->x, event->y)) {
497 #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
498 get_window()->pointer_grab(false,
499 Gdk::BUTTON_RELEASE_MASK |
500 Gdk::POINTER_MOTION_MASK |
501 Gdk::POINTER_MOTION_HINT_MASK,
502 Gdk::Cursor(Gdk::SB_H_DOUBLE_ARROW),
503 event->time);
504 #else
505 Glib::wrap(event->device, true)->grab(get_window(),
506 Gdk::OWNERSHIP_NONE,
507 false,
508 Gdk::BUTTON_RELEASE_MASK |
509 Gdk::POINTER_MOTION_MASK |
510 Gdk::POINTER_MOTION_HINT_MASK,
511 Gdk::Cursor::create(Gdk::SB_H_DOUBLE_ARROW),
512 event->time);
513 #endif
514 resize.active = true;
515 } else {
516 int ydim = int(event->y / h);
517 int dim;
518 for (dim = 0 ; dim < region->Dimensions ; dim++) {
519 if (region->pDimensionDefinitions[dim].bits == 0) continue;
520 if (ydim == 0) break;
521 ydim--;
522 }
523 int nbZones = region->pDimensionDefinitions[dim].zones;
524
525 int z = -1;
526 int bitpos = 0;
527 for (int i = 0 ; i < dim ; i++) {
528 bitpos += region->pDimensionDefinitions[i].bits;
529 }
530
531 int i = dim;
532 if (dimregno < 0) dimregno = 0;
533 int mask = ~(((1 << region->pDimensionDefinitions[i].bits) - 1) << bitpos);
534 int c = dimregno & mask; // mask away this dimension
535
536 bool customsplits =
537 ((region->pDimensionDefinitions[i].split_type == gig::split_type_normal &&
538 region->pDimensionRegions[c]->DimensionUpperLimits[i]) ||
539 (region->pDimensionDefinitions[i].dimension == gig::dimension_velocity &&
540 region->pDimensionRegions[c]->VelocityUpperLimit));
541 if (customsplits) {
542 int val = int((event->x - label_width) * 128 / (w - label_width - 1));
543
544 if (region->pDimensionRegions[c]->DimensionUpperLimits[i]) {
545 for (z = 0 ; z < nbZones ; z++) {
546 gig::DimensionRegion* d = region->pDimensionRegions[c + (z << bitpos)];
547 if (val <= d->DimensionUpperLimits[i]) break;
548 }
549 } else {
550 for (z = 0 ; z < nbZones ; z++) {
551 gig::DimensionRegion* d = region->pDimensionRegions[c + (z << bitpos)];
552 if (val <= d->VelocityUpperLimit) break;
553 }
554 }
555 } else {
556 z = int((event->x - label_width) * nbZones / (w - label_width - 1));
557 }
558
559 printf("dim=%d z=%d dimensionsource=%d split_type=%d zones=%d zone_size=%f\n", dim, z,
560 region->pDimensionDefinitions[dim].dimension,
561 region->pDimensionDefinitions[dim].split_type,
562 region->pDimensionDefinitions[dim].zones,
563 region->pDimensionDefinitions[dim].zone_size);
564 dimvalue[region->pDimensionDefinitions[dim].dimension] = z;
565
566 dimregno = c | (z << bitpos);
567
568 focus_line = dim;
569 if (has_focus()) queue_draw();
570 else grab_focus();
571 dimreg = region->pDimensionRegions[dimregno];
572 dimregion_selected();
573 }
574 }
575 return true;
576 }
577
578 bool DimRegionChooser::on_motion_notify_event(GdkEventMotion* event)
579 {
580 Glib::RefPtr<Gdk::Window> window = get_window();
581 int x, y;
582 Gdk::ModifierType state = Gdk::ModifierType(0);
583 window->get_pointer(x, y, state);
584
585 if (resize.active) {
586 int w = get_width();
587 int k = int((x - label_width) * 128.0 / (w - label_width - 1) + 0.5);
588
589 if (k < resize.min) k = resize.min;
590 else if (k > resize.max) k = resize.max;
591
592 if (k < 2) k = 2; // k is upper limit + 1, upper limit 0 is forbidden
593
594 if (k != resize.pos) {
595 int prevx = int((w - label_width - 1) * resize.pos / 128.0 + 0.5) + label_width;
596 int x = int((w - label_width - 1) * k / 128.0 + 0.5) + label_width;
597 int y = resize.dimension * h;
598 int x1, x2;
599 if (k > resize.pos) {
600 x1 = prevx;
601 x2 = x;
602 } else {
603 x1 = x;
604 x2 = prevx;
605 }
606 Gdk::Rectangle rect(x1, y + 1, x2 - x1 + 1, h - 2);
607
608 resize.pos = k;
609 update_after_resize();
610 get_window()->invalidate_rect(rect, false);
611 }
612 } else {
613 if (is_in_resize_zone(x, y)) {
614 if (!cursor_is_resize) {
615 #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
616 window->set_cursor(Gdk::Cursor(Gdk::SB_H_DOUBLE_ARROW));
617 #else
618 window->set_cursor(Gdk::Cursor::create(Gdk::SB_H_DOUBLE_ARROW));
619 #endif
620 cursor_is_resize = true;
621 }
622 } else if (cursor_is_resize) {
623 window->set_cursor();
624 cursor_is_resize = false;
625 }
626 }
627 return true;
628 }
629
630 bool DimRegionChooser::is_in_resize_zone(double x, double y)
631 {
632 int w = get_width();
633 if (region && y < nbDimensions * h && x >= label_width && x < w) {
634 int ydim = int(y / h);
635 int dim;
636 int bitpos = 0;
637 for (dim = 0 ; dim < region->Dimensions ; dim++) {
638 if (region->pDimensionDefinitions[dim].bits == 0) continue;
639 if (ydim == 0) break;
640 ydim--;
641 bitpos += region->pDimensionDefinitions[dim].bits;
642 }
643 int nbZones = region->pDimensionDefinitions[dim].zones;
644
645 int c = 0;
646 if (dimregno >= 0) {
647 int mask = ~(((1 << region->pDimensionDefinitions[dim].bits) - 1) << bitpos);
648 c = dimregno & mask; // mask away this dimension
649 }
650 const bool customsplits =
651 ((region->pDimensionDefinitions[dim].split_type == gig::split_type_normal &&
652 region->pDimensionRegions[c]->DimensionUpperLimits[dim]) ||
653 (region->pDimensionDefinitions[dim].dimension == gig::dimension_velocity &&
654 region->pDimensionRegions[c]->VelocityUpperLimit));
655
656 // dimensions of split_type_bit cannot be resized
657 if (region->pDimensionDefinitions[dim].split_type != gig::split_type_bit) {
658 int prev_limit = 0;
659 for (int iZone = 0 ; iZone < nbZones - 1 ; iZone++) {
660 gig::DimensionRegion* d = region->pDimensionRegions[c + (iZone << bitpos)];
661 const int upperLimit =
662 (customsplits) ?
663 (d->DimensionUpperLimits[dim]) ?
664 d->DimensionUpperLimits[dim] : d->VelocityUpperLimit
665 : (iZone+1) * (int)region->pDimensionDefinitions[dim].zone_size - 1;
666 int limit = upperLimit + 1;
667 int limitx = int((w - label_width - 1) * limit / 128.0 + 0.5) + label_width;
668 if (x <= limitx - 2) break;
669 if (x <= limitx + 2) {
670 resize.dimension = dim;
671 resize.offset = iZone << bitpos;
672 resize.pos = limit;
673 resize.min = prev_limit;
674
675 int dr = (dimregno >> bitpos) &
676 ((1 << region->pDimensionDefinitions[dim].bits) - 1);
677 resize.selected = dr == iZone ? resize.left :
678 dr == iZone + 1 ? resize.right : resize.none;
679
680 iZone++;
681 gig::DimensionRegion* d = region->pDimensionRegions[c + (iZone << bitpos)];
682
683 const int upperLimit =
684 (customsplits) ?
685 (d->DimensionUpperLimits[dim]) ?
686 d->DimensionUpperLimits[dim] : d->VelocityUpperLimit
687 : (iZone+1) * (int)region->pDimensionDefinitions[dim].zone_size - 1;
688
689 int limit = upperLimit + 1;
690 resize.max = limit;
691 return true;
692 }
693 prev_limit = limit;
694 }
695 }
696 }
697 return false;
698 }
699
700 sigc::signal<void>& DimRegionChooser::signal_dimregion_selected()
701 {
702 return dimregion_selected;
703 }
704
705 sigc::signal<void>& DimRegionChooser::signal_region_changed()
706 {
707 return region_changed;
708 }
709
710 bool DimRegionChooser::on_focus(Gtk::DirectionType direction)
711 {
712 // TODO: kolla att region finns osv, dvs att det g�r att s�tta
713 // fokus.
714 if (direction == Gtk::DIR_TAB_FORWARD ||
715 direction == Gtk::DIR_DOWN) {
716 if (!has_focus()) {
717 focus_line = 0;
718 grab_focus();
719 return true;
720 } else {
721 if (focus_line + 1 < region->Dimensions) {
722 focus_line++;
723 queue_draw();
724 return true;
725 } else {
726 return false;
727 }
728 }
729 } else if (direction == Gtk::DIR_TAB_BACKWARD ||
730 direction == Gtk::DIR_UP) {
731 if (!has_focus()) {
732 focus_line = region->Dimensions - 1;
733 grab_focus();
734 return true;
735 } else {
736 if (focus_line > 0) {
737 focus_line--;
738 queue_draw();
739 return true;
740 } else {
741 return false;
742 }
743 }
744 } else if (!has_focus()) {
745 // TODO: kolla att focus_line finns!
746 grab_focus();
747 return true;
748 } else {
749 // TODO: �ka eller minska v�rde!
750 }
751 }

  ViewVC Help
Powered by ViewVC