/[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 2151 - (hide annotations) (download)
Sun Nov 21 12:38:41 2010 UTC (13 years, 5 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 schoenebeck 1225 /*
2 persson 2151 * Copyright (C) 2006-2010 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 2151 #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 schoenebeck 1225 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 persson 2151 #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 18) || GTKMM_MAJOR_VERSION < 2
69 schoenebeck 1225 set_flags(Gtk::CAN_FOCUS);
70 persson 2151 #else
71     set_can_focus();
72     #endif
73 schoenebeck 1225 add_events(Gdk::BUTTON_PRESS_MASK | Gdk::POINTER_MOTION_MASK |
74     Gdk::POINTER_MOTION_HINT_MASK);
75    
76 persson 1303 for (int i = 0 ; i < 256 ; i++) dimvalue[i] = 0;
77 schoenebeck 1225 }
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 persson 1623 int w = get_width();
89 schoenebeck 1225 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 persson 2151 Cairo::RefPtr<Cairo::Context> cr = get_window()->create_cairo_context();
94     cr->set_line_width(1);
95 schoenebeck 1225
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 persson 1831 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 schoenebeck 1225 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 persson 2151 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 schoenebeck 1225 }
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 persson 2151 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 schoenebeck 1225 // erase whole dimension's zones area
188 persson 2151 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 schoenebeck 1225
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 persson 2151 Gdk::Cairo::set_source_color(cr, black);
205 schoenebeck 1225 if (customsplits) {
206 persson 2151 cr->move_to(label_width + 0.5, y + 1);
207     cr->line_to(label_width + 0.5, y + h - 1);
208    
209 schoenebeck 1225 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 persson 2151 cr->move_to(label_width + x + 0.5, y + 1);
216     cr->line_to(label_width + x + 0.5, y + h - 1);
217 schoenebeck 1225 }
218     } else {
219     for (int j = 0 ; j <= nbZones ; j++) {
220     int x = int((w - label_width - 1) * j / double(nbZones) + 0.5);
221 persson 2151 cr->move_to(label_width + x + 0.5, y + 1);
222     cr->line_to(label_width + x + 0.5, y + h - 1);
223 schoenebeck 1225 }
224     }
225 persson 2151 cr->stroke();
226 schoenebeck 1225
227     // draw fill for currently selected zone
228     if (dimregno >= 0) {
229 persson 2151 Gdk::Cairo::set_source_color(cr, red);
230 schoenebeck 1225 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 persson 2151 cr->rectangle(label_width + x1 + 1, y + 1,
241     (x2 - x1) - 1, h - 2);
242     cr->fill();
243 schoenebeck 1225 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 persson 2151 cr->rectangle(label_width + x1 + 1, y + 1,
252     (x2 - x1) - 1, h - 2);
253     cr->fill();
254 schoenebeck 1225 }
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 persson 1303 int z = std::min(dimvalue[region->pDimensionDefinitions[dim].dimension],
285     region->pDimensionDefinitions[dim].zones - 1);
286 schoenebeck 1225 dimregno |= (z << bitcount);
287     bitcount += region->pDimensionDefinitions[dim].bits;
288     }
289     dimreg = region->pDimensionRegions[dimregno];
290     } else {
291     dimreg = 0;
292     }
293 persson 1261 dimregion_selected();
294 schoenebeck 1225 queue_resize();
295     }
296    
297 persson 1533
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 schoenebeck 1225 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 persson 1261 region_changed();
399 schoenebeck 1225
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 persson 1623 int w = get_width();
411 schoenebeck 1225 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 persson 1303 dimvalue[region->pDimensionDefinitions[dim].dimension] = z;
472 schoenebeck 1225
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 persson 1261 dimregion_selected();
480 schoenebeck 1225 }
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 persson 1623 int w = get_width();
494 schoenebeck 1225 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 persson 2151 Cairo::RefPtr<Cairo::Context> cr = get_window()->create_cairo_context();
503     cr->set_line_width(1);
504 schoenebeck 1225
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 persson 2151 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 schoenebeck 1225 }
516     } else {
517 persson 2151 Gdk::Color left;
518     Gdk::Color right;
519 schoenebeck 1225 if (resize.selected == resize.left) {
520 persson 2151 left = red;
521 schoenebeck 1225 right = white;
522     } else {
523     left = white;
524 persson 2151 right = red;
525 schoenebeck 1225 }
526    
527     if (k > resize.pos) {
528     int xx = resize.pos == resize.min ? 1 : 0;
529 persson 2151 Gdk::Cairo::set_source_color(cr, left);
530     cr->rectangle(prevx + xx, y + 1, x - prevx - xx, h - 2);
531 schoenebeck 1225 } else {
532     int xx = resize.pos == resize.max ? 0 : 1;
533 persson 2151 Gdk::Cairo::set_source_color(cr, right);
534     cr->rectangle(x, y + 1, prevx - x + xx, h - 2);
535 schoenebeck 1225 }
536 persson 2151 cr->fill();
537 schoenebeck 1225 }
538 persson 2151 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 schoenebeck 1225 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 persson 1623 int w = get_width();
563 schoenebeck 1225 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 schoenebeck 1339 sigc::signal<void>& DimRegionChooser::signal_dimregion_selected()
631 schoenebeck 1225 {
632 persson 1261 return dimregion_selected;
633 schoenebeck 1225 }
634    
635 schoenebeck 1339 sigc::signal<void>& DimRegionChooser::signal_region_changed()
636 persson 1261 {
637     return region_changed;
638     }
639    
640 schoenebeck 1225 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