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

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 schoenebeck 1225 }
45    
46     DimRegionChooser::~DimRegionChooser()
47     {
48     }
49    
50 persson 2169 #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
51     bool DimRegionChooser::on_expose_event(GdkEventExpose* e)
52 schoenebeck 1225 {
53 persson 2169 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 schoenebeck 1225 if (!region) return true;
60    
61     // This is where we draw on the window
62 persson 1623 int w = get_width();
63 schoenebeck 1225 Glib::RefPtr<Pango::Context> context = get_pango_context();
64    
65     Glib::RefPtr<Pango::Layout> layout = Pango::Layout::create(context);
66 persson 2151 cr->set_line_width(1);
67 schoenebeck 1225
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 persson 1831 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 schoenebeck 1225 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 persson 2169 #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
124 persson 2151 const Gdk::Color fg = get_style()->get_fg(get_state());
125 persson 2169 #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 persson 2151 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 schoenebeck 1225 }
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 persson 2169 #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
149 schoenebeck 1225 Gdk::Rectangle farea(0, y, 150, 20);
150 persson 2169 get_style()->paint_focus(get_window(), get_state(), farea, *this, "",
151 schoenebeck 1225 0, y, label_width, 20);
152 persson 2169 #else
153     get_style_context()->render_focus(cr, 0, y, label_width, 20);
154     #endif
155 schoenebeck 1225 }
156    
157     // draw top and bottom lines of dimension's zones
158 persson 2169 Gdk::Cairo::set_source_rgba(cr, black);
159 persson 2151 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 schoenebeck 1225 // erase whole dimension's zones area
166 persson 2169 Gdk::Cairo::set_source_rgba(cr, white);
167 persson 2151 cr->rectangle(label_width + 1, y + 1, (w - label_width - 2), h - 2);
168     cr->fill();
169 schoenebeck 1225
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 persson 2169 Gdk::Cairo::set_source_rgba(cr, black);
183 schoenebeck 1225 if (customsplits) {
184 persson 2151 cr->move_to(label_width + 0.5, y + 1);
185     cr->line_to(label_width + 0.5, y + h - 1);
186    
187 schoenebeck 1225 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 persson 2151 cr->move_to(label_width + x + 0.5, y + 1);
194     cr->line_to(label_width + x + 0.5, y + h - 1);
195 schoenebeck 1225 }
196     } else {
197     for (int j = 0 ; j <= nbZones ; j++) {
198     int x = int((w - label_width - 1) * j / double(nbZones) + 0.5);
199 persson 2151 cr->move_to(label_width + x + 0.5, y + 1);
200     cr->line_to(label_width + x + 0.5, y + h - 1);
201 schoenebeck 1225 }
202     }
203 persson 2151 cr->stroke();
204 schoenebeck 1225
205     // draw fill for currently selected zone
206     if (dimregno >= 0) {
207 persson 2169 Gdk::Cairo::set_source_rgba(cr, red);
208 schoenebeck 1225 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 persson 2151 cr->rectangle(label_width + x1 + 1, y + 1,
219     (x2 - x1) - 1, h - 2);
220     cr->fill();
221 schoenebeck 1225 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 persson 2151 cr->rectangle(label_width + x1 + 1, y + 1,
230     (x2 - x1) - 1, h - 2);
231     cr->fill();
232 schoenebeck 1225 }
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 persson 1303 int z = std::min(dimvalue[region->pDimensionDefinitions[dim].dimension],
256     region->pDimensionDefinitions[dim].zones - 1);
257 schoenebeck 1225 dimregno |= (z << bitcount);
258     bitcount += region->pDimensionDefinitions[dim].bits;
259     }
260     dimreg = region->pDimensionRegions[dimregno];
261     } else {
262     dimreg = 0;
263     }
264 persson 1261 dimregion_selected();
265 persson 2169 set_size_request(800, region ? nbDimensions * 20 : 0);
266    
267 schoenebeck 1225 queue_resize();
268     }
269    
270 persson 1533
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 schoenebeck 1225 bool DimRegionChooser::on_button_release_event(GdkEventButton* event)
295     {
296     if (resize.active) {
297 persson 2169 #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
298 schoenebeck 1225 get_window()->pointer_ungrab(event->time);
299 persson 2169 #else
300     Glib::wrap(event->device, true)->ungrab(event->time);
301     #endif
302 schoenebeck 1225 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 persson 1261 region_changed();
376 schoenebeck 1225
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 persson 1623 int w = get_width();
388 schoenebeck 1225 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 persson 2169 #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
393 schoenebeck 1225 get_window()->pointer_grab(false,
394     Gdk::BUTTON_RELEASE_MASK |
395     Gdk::POINTER_MOTION_MASK |
396     Gdk::POINTER_MOTION_HINT_MASK,
397 persson 2169 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 schoenebeck 1225 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 persson 1303 dimvalue[region->pDimensionDefinitions[dim].dimension] = z;
460 schoenebeck 1225
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 persson 1261 dimregion_selected();
468 schoenebeck 1225 }
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 persson 1623 int w = get_width();
482 schoenebeck 1225 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 persson 2151 Cairo::RefPtr<Cairo::Context> cr = get_window()->create_cairo_context();
491     cr->set_line_width(1);
492 schoenebeck 1225
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 persson 2169 Gdk::Cairo::set_source_rgba(cr, white);
500 persson 2151 cr->move_to(prevx + 0.5, y + 1);
501     cr->line_to(prevx + 0.5, y + h - 1);
502     cr->stroke();
503 schoenebeck 1225 }
504     } else {
505 persson 2169 Gdk::RGBA left;
506     Gdk::RGBA right;
507 schoenebeck 1225 if (resize.selected == resize.left) {
508 persson 2151 left = red;
509 schoenebeck 1225 right = white;
510     } else {
511     left = white;
512 persson 2151 right = red;
513 schoenebeck 1225 }
514    
515     if (k > resize.pos) {
516     int xx = resize.pos == resize.min ? 1 : 0;
517 persson 2169 Gdk::Cairo::set_source_rgba(cr, left);
518 persson 2151 cr->rectangle(prevx + xx, y + 1, x - prevx - xx, h - 2);
519 schoenebeck 1225 } else {
520     int xx = resize.pos == resize.max ? 0 : 1;
521 persson 2169 Gdk::Cairo::set_source_rgba(cr, right);
522 persson 2151 cr->rectangle(x, y + 1, prevx - x + xx, h - 2);
523 schoenebeck 1225 }
524 persson 2151 cr->fill();
525 schoenebeck 1225 }
526 persson 2169 Gdk::Cairo::set_source_rgba(cr, black);
527 persson 2151 cr->move_to(x + 0.5, y + 1);
528     cr->line_to(x + 0.5, y + h - 1);
529     cr->stroke();
530    
531 schoenebeck 1225 resize.pos = k;
532     }
533     } else {
534     if (is_in_resize_zone(x, y)) {
535     if (!cursor_is_resize) {
536 persson 2169 #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 schoenebeck 1225 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 persson 1623 int w = get_width();
554 schoenebeck 1225 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 schoenebeck 1339 sigc::signal<void>& DimRegionChooser::signal_dimregion_selected()
622 schoenebeck 1225 {
623 persson 1261 return dimregion_selected;
624 schoenebeck 1225 }
625    
626 schoenebeck 1339 sigc::signal<void>& DimRegionChooser::signal_region_changed()
627 persson 1261 {
628     return region_changed;
629     }
630    
631 schoenebeck 1225 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