/[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 2151 - (show annotations) (download)
Sun Nov 21 12:38:41 2010 UTC (13 years, 4 months ago) by persson
File size: 27867 byte(s)
* use Cairo instead of deprecated gdk drawing primitives
* avoid deprecated gtk methods when using newer gtk versions
* raised minimum supported gtkmm version to 2.8

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

  ViewVC Help
Powered by ViewVC