/[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 2169 - (show annotations) (download)
Sun Mar 6 07:51:04 2011 UTC (13 years ago) by persson
File size: 27945 byte(s)
* ported to gtkmm 3, keeping compatibility with gtkmm 2

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

  ViewVC Help
Powered by ViewVC