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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2462 - (hide 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 schoenebeck 1225 /*
2 persson 2169 * Copyright (C) 2006-2011 Andreas Persson
3 schoenebeck 1225 *
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 persson 2151 #include <cairomm/context.h>
22 schoenebeck 1225 #include <gdkmm/cursor.h>
23 persson 2151 #include <gdkmm/general.h>
24 schoenebeck 1225
25 persson 1831 #include "global.h"
26    
27 persson 2169 DimRegionChooser::DimRegionChooser() :
28     red("#8070ff"),
29     black("black"),
30     white("white")
31 schoenebeck 1225 {
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 persson 2151 set_can_focus();
40 schoenebeck 1225 add_events(Gdk::BUTTON_PRESS_MASK | Gdk::POINTER_MOTION_MASK |
41     Gdk::POINTER_MOTION_HINT_MASK);
42    
43 persson 1303 for (int i = 0 ; i < 256 ; i++) dimvalue[i] = 0;
44 persson 2246 labels_changed = true;
45 schoenebeck 1225 }
46    
47     DimRegionChooser::~DimRegionChooser()
48     {
49     }
50    
51 persson 2169 #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
52     bool DimRegionChooser::on_expose_event(GdkEventExpose* e)
53 schoenebeck 1225 {
54 persson 2246 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 persson 2169 }
63     #endif
64 persson 2246 #else
65 persson 2169 bool DimRegionChooser::on_draw(const Cairo::RefPtr<Cairo::Context>& cr)
66     {
67 persson 2246 double clipx1, clipx2, clipy1, clipy2;
68     cr->get_clip_extents(clipx1, clipy1, clipx2, clipy2);
69     #endif
70    
71 schoenebeck 1225 if (!region) return true;
72    
73     // This is where we draw on the window
74 persson 1623 int w = get_width();
75 schoenebeck 1225 Glib::RefPtr<Pango::Context> context = get_pango_context();
76    
77     Glib::RefPtr<Pango::Layout> layout = Pango::Layout::create(context);
78 persson 2151 cr->set_line_width(1);
79 schoenebeck 1225
80     int y = 0;
81 persson 2246 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 schoenebeck 1225
144 persson 2246 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 persson 2169 #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
152 persson 2246 const Gdk::Color fg = get_style()->get_fg(get_state());
153 persson 2169 #else
154 persson 2246 const Gdk::RGBA fg =
155     get_style_context()->get_color(get_state_flags());
156 persson 2169 #endif
157 persson 2246 Gdk::Cairo::set_source_rgba(cr, fg);
158     cr->move_to(4, int(y + (h - text_h) / 2 + 0.5));
159 persson 2151 #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 16) || GTKMM_MAJOR_VERSION < 2
160 persson 2246 pango_cairo_show_layout(cr->cobj(), layout->gobj());
161 persson 2151 #else
162 persson 2246 layout->show_in_cairo_context(cr);
163 persson 2151 #endif
164 persson 2246 }
165     }
166     y += h;
167 schoenebeck 1225 }
168 persson 2246 label_width = int(maxwidth + 10);
169     labels_changed = false;
170 schoenebeck 1225 }
171 persson 2246 if (label_width >= clipx2) return true;
172 schoenebeck 1225
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 persson 2246 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 persson 2169 #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
184 persson 2246 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 persson 2169 #else
189 persson 2246 get_style_context()->render_focus(cr,
190     0, y, label_width, 20);
191 persson 2169 #endif
192 persson 2246 }
193 schoenebeck 1225
194 persson 2246 // 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 persson 2151
202 persson 2246 // 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 schoenebeck 1225
208 persson 2246 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 schoenebeck 1225 }
215 persson 2246 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 schoenebeck 1225
223 persson 2246 // draw dimension's zone borders
224     Gdk::Cairo::set_source_rgba(cr, black);
225 schoenebeck 1225 if (customsplits) {
226 persson 2246 cr->move_to(label_width + 0.5, y + 1);
227     cr->line_to(label_width + 0.5, y + h - 1);
228    
229 schoenebeck 1225 for (int j = 0 ; j < nbZones ; j++) {
230 persson 2246 gig::DimensionRegion* d =
231     region->pDimensionRegions[c + (j << bitpos)];
232 schoenebeck 1225 int upperLimit = d->DimensionUpperLimits[i];
233     if (!upperLimit) upperLimit = d->VelocityUpperLimit;
234     int v = upperLimit + 1;
235 persson 2246 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 schoenebeck 2462
260     int x1 = -1, x2 = -1;
261 persson 2246 if (customsplits) {
262 schoenebeck 2462 x1 = label_width;
263 persson 2246 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 schoenebeck 2462 x2 = int((w - label_width - 1) * v / 128.0 +
272     0.5) + label_width;
273 persson 2246 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 schoenebeck 2462 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 persson 2151 cr->rectangle(label_width + x1 + 1, y + 1,
288     (x2 - x1) - 1, h - 2);
289     cr->fill();
290 schoenebeck 1225 }
291     }
292 schoenebeck 2462
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 schoenebeck 1225 }
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 persson 1303 int z = std::min(dimvalue[region->pDimensionDefinitions[dim].dimension],
357     region->pDimensionDefinitions[dim].zones - 1);
358 schoenebeck 1225 dimregno |= (z << bitcount);
359     bitcount += region->pDimensionDefinitions[dim].bits;
360     }
361     dimreg = region->pDimensionRegions[dimregno];
362     } else {
363     dimreg = 0;
364     }
365 persson 1261 dimregion_selected();
366 persson 2169 set_size_request(800, region ? nbDimensions * 20 : 0);
367    
368 persson 2246 labels_changed = true;
369 schoenebeck 1225 queue_resize();
370     }
371    
372 persson 1533
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 persson 2246 void DimRegionChooser::update_after_resize()
396 schoenebeck 1225 {
397 persson 2246 if (region->pDimensionDefinitions[resize.dimension].dimension == gig::dimension_velocity) {
398 schoenebeck 1225
399 persson 2246 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 schoenebeck 1225
407 persson 2246 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 schoenebeck 1225 }
416 persson 2246 }
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 schoenebeck 1225
428 persson 2246 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 schoenebeck 1225 int nbZones = region->pDimensionDefinitions[resize.dimension].zones;
445 persson 2246
446 schoenebeck 1225 for (int j = 0 ; j < nbZones ; j++) {
447 persson 2246 gig::DimensionRegion* d = region->pDimensionRegions[i + (j << bitpos)];
448 schoenebeck 1225 d->DimensionUpperLimits[resize.dimension] = int(128.0 * (j + 1) / nbZones - 1);
449     }
450     }
451 persson 2246 gig::DimensionRegion* d = region->pDimensionRegions[i + resize.offset];
452 schoenebeck 1225 d->DimensionUpperLimits[resize.dimension] = resize.pos - 1;
453    
454 persson 2246 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 schoenebeck 1225 }
462 persson 2246 bitpos += region->pDimensionDefinitions[j].bits;
463 schoenebeck 1225 }
464 persson 2246 if (j == region->Dimensions) break;
465     i = (i & ~((1 << bitpos) - 1)) + (1 << bitpos);
466 schoenebeck 1225 }
467 persson 2246 }
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 persson 1261 region_changed();
481 schoenebeck 1225
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 persson 1623 int w = get_width();
493 schoenebeck 1225 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 persson 2169 #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
498 schoenebeck 1225 get_window()->pointer_grab(false,
499     Gdk::BUTTON_RELEASE_MASK |
500     Gdk::POINTER_MOTION_MASK |
501     Gdk::POINTER_MOTION_HINT_MASK,
502 persson 2169 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 schoenebeck 1225 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 persson 2246 gig::DimensionRegion* d = region->pDimensionRegions[c + (z << bitpos)];
547 schoenebeck 1225 if (val <= d->DimensionUpperLimits[i]) break;
548     }
549     } else {
550     for (z = 0 ; z < nbZones ; z++) {
551 persson 2246 gig::DimensionRegion* d = region->pDimensionRegions[c + (z << bitpos)];
552 schoenebeck 1225 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 persson 1303 dimvalue[region->pDimensionDefinitions[dim].dimension] = z;
565 schoenebeck 1225
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 persson 1261 dimregion_selected();
573 schoenebeck 1225 }
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 persson 1623 int w = get_width();
587 schoenebeck 1225 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 persson 2246 int x1, x2;
599     if (k > resize.pos) {
600     x1 = prevx;
601     x2 = x;
602 schoenebeck 1225 } else {
603 persson 2246 x1 = x;
604     x2 = prevx;
605 schoenebeck 1225 }
606 persson 2246 Gdk::Rectangle rect(x1, y + 1, x2 - x1 + 1, h - 2);
607 persson 2151
608 schoenebeck 1225 resize.pos = k;
609 persson 2246 update_after_resize();
610     get_window()->invalidate_rect(rect, false);
611 schoenebeck 1225 }
612     } else {
613     if (is_in_resize_zone(x, y)) {
614     if (!cursor_is_resize) {
615 persson 2169 #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 schoenebeck 1225 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 persson 1623 int w = get_width();
633 schoenebeck 1225 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 persson 2246 gig::DimensionRegion* d = region->pDimensionRegions[c + (iZone << bitpos)];
661 schoenebeck 1225 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 persson 2246 gig::DimensionRegion* d = region->pDimensionRegions[c + (iZone << bitpos)];
682 schoenebeck 1225
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 schoenebeck 1339 sigc::signal<void>& DimRegionChooser::signal_dimregion_selected()
701 schoenebeck 1225 {
702 persson 1261 return dimregion_selected;
703 schoenebeck 1225 }
704    
705 schoenebeck 1339 sigc::signal<void>& DimRegionChooser::signal_region_changed()
706 persson 1261 {
707     return region_changed;
708     }
709    
710 schoenebeck 1225 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