/[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 2246 - (hide annotations) (download)
Fri Aug 19 10:55:41 2011 UTC (12 years, 8 months ago) by persson
File size: 28949 byte(s)
* gtkmm 3 fix: rewrote the custom widgets (regionchooser and
  dimregionchooser) so they only draw pixels in the on_draw
  method. This should make them work again in newer gtkmm 3
  environments.

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     if (customsplits) {
260     int x1 = label_width;
261     for (int j = 0 ; j < nbZones && x1 + 1 < clipx2 ; j++) {
262     gig::DimensionRegion* d =
263     region->pDimensionRegions[c + (j << bitpos)];
264     int upperLimit = d->DimensionUpperLimits[i];
265     if (!upperLimit) {
266     upperLimit = d->VelocityUpperLimit;
267     }
268     int v = upperLimit + 1;
269     int x2 = int((w - label_width - 1) * v / 128.0 +
270     0.5) + label_width;
271     if (j == dr && x1 < x2) {
272     cr->rectangle(x1 + 1, y + 1,
273     (x2 - x1) - 1, h - 2);
274     cr->fill();
275     break;
276     }
277     x1 = x2;
278     }
279     } else {
280     if (dr < nbZones) {
281     int x1 = int((w - label_width - 1) * dr /
282     double(nbZones) + 0.5);
283     int x2 = int((w - label_width - 1) * (dr + 1) /
284     double(nbZones) + 0.5);
285 persson 2151 cr->rectangle(label_width + x1 + 1, y + 1,
286     (x2 - x1) - 1, h - 2);
287     cr->fill();
288 schoenebeck 1225 }
289     }
290     }
291     }
292    
293     y += h;
294     }
295     bitpos += region->pDimensionDefinitions[i].bits;
296     }
297    
298     return true;
299     }
300    
301     void DimRegionChooser::set_region(gig::Region* region)
302     {
303     this->region = region;
304     dimregno = 0;
305     nbDimensions = 0;
306     if (region) {
307     int bitcount = 0;
308     for (int dim = 0 ; dim < region->Dimensions ; dim++) {
309     if (region->pDimensionDefinitions[dim].bits == 0) continue;
310     nbDimensions++;
311    
312 persson 1303 int z = std::min(dimvalue[region->pDimensionDefinitions[dim].dimension],
313     region->pDimensionDefinitions[dim].zones - 1);
314 schoenebeck 1225 dimregno |= (z << bitcount);
315     bitcount += region->pDimensionDefinitions[dim].bits;
316     }
317     dimreg = region->pDimensionRegions[dimregno];
318     } else {
319     dimreg = 0;
320     }
321 persson 1261 dimregion_selected();
322 persson 2169 set_size_request(800, region ? nbDimensions * 20 : 0);
323    
324 persson 2246 labels_changed = true;
325 schoenebeck 1225 queue_resize();
326     }
327    
328 persson 1533
329     void DimRegionChooser::get_dimregions(const gig::Region* region, bool stereo,
330     std::set<gig::DimensionRegion*>& dimregs) const
331     {
332     int dimregno = 0;
333     int bitcount = 0;
334     int stereo_bit = 0;
335     for (int dim = 0 ; dim < region->Dimensions ; dim++) {
336     if (region->pDimensionDefinitions[dim].bits == 0) continue;
337     if (stereo &&
338     region->pDimensionDefinitions[dim].dimension == gig::dimension_samplechannel) {
339     stereo_bit = (1 << bitcount);
340     } else {
341     int z = std::min(dimvalue[region->pDimensionDefinitions[dim].dimension],
342     region->pDimensionDefinitions[dim].zones - 1);
343     dimregno |= (z << bitcount);
344     }
345     bitcount += region->pDimensionDefinitions[dim].bits;
346     }
347     dimregs.insert(region->pDimensionRegions[dimregno]);
348     if (stereo_bit) dimregs.insert(region->pDimensionRegions[dimregno | stereo_bit]);
349     }
350    
351 persson 2246 void DimRegionChooser::update_after_resize()
352 schoenebeck 1225 {
353 persson 2246 if (region->pDimensionDefinitions[resize.dimension].dimension == gig::dimension_velocity) {
354 schoenebeck 1225
355 persson 2246 int bitpos = 0;
356     for (int j = 0 ; j < resize.dimension ; j++) {
357     bitpos += region->pDimensionDefinitions[j].bits;
358     }
359     int mask =
360     ~(((1 << region->pDimensionDefinitions[resize.dimension].bits) - 1) << bitpos);
361     int c = dimregno & mask; // mask away this dimension
362 schoenebeck 1225
363 persson 2246 if (region->pDimensionRegions[c]->DimensionUpperLimits[resize.dimension] == 0) {
364     // the velocity dimension didn't previously have
365     // custom v3 splits, so we initialize all splits with
366     // default values
367     int nbZones = region->pDimensionDefinitions[resize.dimension].zones;
368     for (int j = 0 ; j < nbZones ; j++) {
369     gig::DimensionRegion* d = region->pDimensionRegions[c + (j << bitpos)];
370     d->DimensionUpperLimits[resize.dimension] = int(128.0 * (j + 1) / nbZones - 1);
371 schoenebeck 1225 }
372 persson 2246 }
373     if (region->pDimensionRegions[c]->VelocityUpperLimit == 0) {
374     // the velocity dimension didn't previously have
375     // custom v2 splits, so we initialize all splits with
376     // default values
377     int nbZones = region->pDimensionDefinitions[resize.dimension].zones;
378     for (int j = 0 ; j < nbZones ; j++) {
379     gig::DimensionRegion* d = region->pDimensionRegions[c + (j << bitpos)];
380     d->VelocityUpperLimit = int(128.0 * (j + 1) / nbZones - 1);
381     }
382     }
383 schoenebeck 1225
384 persson 2246 gig::DimensionRegion* d = region->pDimensionRegions[c + resize.offset];
385     // update both v2 and v3 values
386     d->DimensionUpperLimits[resize.dimension] = resize.pos - 1;
387     d->VelocityUpperLimit = resize.pos - 1;
388    
389     } else {
390     for (int i = 0 ; i < region->DimensionRegions ; ) {
391    
392     if (region->pDimensionRegions[i]->DimensionUpperLimits[resize.dimension] == 0) {
393     // the dimension didn't previously have custom
394     // limits, so we have to set default limits for
395     // all the dimension regions
396     int bitpos = 0;
397     for (int j = 0 ; j < resize.dimension ; j++) {
398     bitpos += region->pDimensionDefinitions[j].bits;
399     }
400 schoenebeck 1225 int nbZones = region->pDimensionDefinitions[resize.dimension].zones;
401 persson 2246
402 schoenebeck 1225 for (int j = 0 ; j < nbZones ; j++) {
403 persson 2246 gig::DimensionRegion* d = region->pDimensionRegions[i + (j << bitpos)];
404 schoenebeck 1225 d->DimensionUpperLimits[resize.dimension] = int(128.0 * (j + 1) / nbZones - 1);
405     }
406     }
407 persson 2246 gig::DimensionRegion* d = region->pDimensionRegions[i + resize.offset];
408 schoenebeck 1225 d->DimensionUpperLimits[resize.dimension] = resize.pos - 1;
409    
410 persson 2246 int bitpos = 0;
411     int j;
412     for (j = 0 ; j < region->Dimensions ; j++) {
413     if (j != resize.dimension) {
414     int maxzones = 1 << region->pDimensionDefinitions[j].bits;
415     int dimj = (i >> bitpos) & (maxzones - 1);
416     if (dimj + 1 < region->pDimensionDefinitions[j].zones) break;
417 schoenebeck 1225 }
418 persson 2246 bitpos += region->pDimensionDefinitions[j].bits;
419 schoenebeck 1225 }
420 persson 2246 if (j == region->Dimensions) break;
421     i = (i & ~((1 << bitpos) - 1)) + (1 << bitpos);
422 schoenebeck 1225 }
423 persson 2246 }
424     }
425    
426     bool DimRegionChooser::on_button_release_event(GdkEventButton* event)
427     {
428     if (resize.active) {
429     #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
430     get_window()->pointer_ungrab(event->time);
431     #else
432     Glib::wrap(event->device, true)->ungrab(event->time);
433     #endif
434     resize.active = false;
435    
436 persson 1261 region_changed();
437 schoenebeck 1225
438     if (!is_in_resize_zone(event->x, event->y) && cursor_is_resize) {
439     get_window()->set_cursor();
440     cursor_is_resize = false;
441     }
442     }
443     return true;
444     }
445    
446     bool DimRegionChooser::on_button_press_event(GdkEventButton* event)
447     {
448 persson 1623 int w = get_width();
449 schoenebeck 1225 if (region && event->y < nbDimensions * h &&
450     event->x >= label_width && event->x < w) {
451    
452     if (is_in_resize_zone(event->x, event->y)) {
453 persson 2169 #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
454 schoenebeck 1225 get_window()->pointer_grab(false,
455     Gdk::BUTTON_RELEASE_MASK |
456     Gdk::POINTER_MOTION_MASK |
457     Gdk::POINTER_MOTION_HINT_MASK,
458 persson 2169 Gdk::Cursor(Gdk::SB_H_DOUBLE_ARROW),
459     event->time);
460     #else
461     Glib::wrap(event->device, true)->grab(get_window(),
462     Gdk::OWNERSHIP_NONE,
463     false,
464     Gdk::BUTTON_RELEASE_MASK |
465     Gdk::POINTER_MOTION_MASK |
466     Gdk::POINTER_MOTION_HINT_MASK,
467     Gdk::Cursor::create(Gdk::SB_H_DOUBLE_ARROW),
468     event->time);
469     #endif
470 schoenebeck 1225 resize.active = true;
471     } else {
472     int ydim = int(event->y / h);
473     int dim;
474     for (dim = 0 ; dim < region->Dimensions ; dim++) {
475     if (region->pDimensionDefinitions[dim].bits == 0) continue;
476     if (ydim == 0) break;
477     ydim--;
478     }
479     int nbZones = region->pDimensionDefinitions[dim].zones;
480    
481     int z = -1;
482     int bitpos = 0;
483     for (int i = 0 ; i < dim ; i++) {
484     bitpos += region->pDimensionDefinitions[i].bits;
485     }
486    
487     int i = dim;
488     if (dimregno < 0) dimregno = 0;
489     int mask = ~(((1 << region->pDimensionDefinitions[i].bits) - 1) << bitpos);
490     int c = dimregno & mask; // mask away this dimension
491    
492     bool customsplits =
493     ((region->pDimensionDefinitions[i].split_type == gig::split_type_normal &&
494     region->pDimensionRegions[c]->DimensionUpperLimits[i]) ||
495     (region->pDimensionDefinitions[i].dimension == gig::dimension_velocity &&
496     region->pDimensionRegions[c]->VelocityUpperLimit));
497     if (customsplits) {
498     int val = int((event->x - label_width) * 128 / (w - label_width - 1));
499    
500     if (region->pDimensionRegions[c]->DimensionUpperLimits[i]) {
501     for (z = 0 ; z < nbZones ; z++) {
502 persson 2246 gig::DimensionRegion* d = region->pDimensionRegions[c + (z << bitpos)];
503 schoenebeck 1225 if (val <= d->DimensionUpperLimits[i]) break;
504     }
505     } else {
506     for (z = 0 ; z < nbZones ; z++) {
507 persson 2246 gig::DimensionRegion* d = region->pDimensionRegions[c + (z << bitpos)];
508 schoenebeck 1225 if (val <= d->VelocityUpperLimit) break;
509     }
510     }
511     } else {
512     z = int((event->x - label_width) * nbZones / (w - label_width - 1));
513     }
514    
515     printf("dim=%d z=%d dimensionsource=%d split_type=%d zones=%d zone_size=%f\n", dim, z,
516     region->pDimensionDefinitions[dim].dimension,
517     region->pDimensionDefinitions[dim].split_type,
518     region->pDimensionDefinitions[dim].zones,
519     region->pDimensionDefinitions[dim].zone_size);
520 persson 1303 dimvalue[region->pDimensionDefinitions[dim].dimension] = z;
521 schoenebeck 1225
522     dimregno = c | (z << bitpos);
523    
524     focus_line = dim;
525     if (has_focus()) queue_draw();
526     else grab_focus();
527     dimreg = region->pDimensionRegions[dimregno];
528 persson 1261 dimregion_selected();
529 schoenebeck 1225 }
530     }
531     return true;
532     }
533    
534     bool DimRegionChooser::on_motion_notify_event(GdkEventMotion* event)
535     {
536     Glib::RefPtr<Gdk::Window> window = get_window();
537     int x, y;
538     Gdk::ModifierType state = Gdk::ModifierType(0);
539     window->get_pointer(x, y, state);
540    
541     if (resize.active) {
542 persson 1623 int w = get_width();
543 schoenebeck 1225 int k = int((x - label_width) * 128.0 / (w - label_width - 1) + 0.5);
544    
545     if (k < resize.min) k = resize.min;
546     else if (k > resize.max) k = resize.max;
547    
548     if (k < 2) k = 2; // k is upper limit + 1, upper limit 0 is forbidden
549    
550     if (k != resize.pos) {
551     int prevx = int((w - label_width - 1) * resize.pos / 128.0 + 0.5) + label_width;
552     int x = int((w - label_width - 1) * k / 128.0 + 0.5) + label_width;
553     int y = resize.dimension * h;
554 persson 2246 int x1, x2;
555     if (k > resize.pos) {
556     x1 = prevx;
557     x2 = x;
558 schoenebeck 1225 } else {
559 persson 2246 x1 = x;
560     x2 = prevx;
561 schoenebeck 1225 }
562 persson 2246 Gdk::Rectangle rect(x1, y + 1, x2 - x1 + 1, h - 2);
563 persson 2151
564 schoenebeck 1225 resize.pos = k;
565 persson 2246 update_after_resize();
566     get_window()->invalidate_rect(rect, false);
567 schoenebeck 1225 }
568     } else {
569     if (is_in_resize_zone(x, y)) {
570     if (!cursor_is_resize) {
571 persson 2169 #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
572     window->set_cursor(Gdk::Cursor(Gdk::SB_H_DOUBLE_ARROW));
573     #else
574     window->set_cursor(Gdk::Cursor::create(Gdk::SB_H_DOUBLE_ARROW));
575     #endif
576 schoenebeck 1225 cursor_is_resize = true;
577     }
578     } else if (cursor_is_resize) {
579     window->set_cursor();
580     cursor_is_resize = false;
581     }
582     }
583     return true;
584     }
585    
586     bool DimRegionChooser::is_in_resize_zone(double x, double y)
587     {
588 persson 1623 int w = get_width();
589 schoenebeck 1225 if (region && y < nbDimensions * h && x >= label_width && x < w) {
590     int ydim = int(y / h);
591     int dim;
592     int bitpos = 0;
593     for (dim = 0 ; dim < region->Dimensions ; dim++) {
594     if (region->pDimensionDefinitions[dim].bits == 0) continue;
595     if (ydim == 0) break;
596     ydim--;
597     bitpos += region->pDimensionDefinitions[dim].bits;
598     }
599     int nbZones = region->pDimensionDefinitions[dim].zones;
600    
601     int c = 0;
602     if (dimregno >= 0) {
603     int mask = ~(((1 << region->pDimensionDefinitions[dim].bits) - 1) << bitpos);
604     c = dimregno & mask; // mask away this dimension
605     }
606     const bool customsplits =
607     ((region->pDimensionDefinitions[dim].split_type == gig::split_type_normal &&
608     region->pDimensionRegions[c]->DimensionUpperLimits[dim]) ||
609     (region->pDimensionDefinitions[dim].dimension == gig::dimension_velocity &&
610     region->pDimensionRegions[c]->VelocityUpperLimit));
611    
612     // dimensions of split_type_bit cannot be resized
613     if (region->pDimensionDefinitions[dim].split_type != gig::split_type_bit) {
614     int prev_limit = 0;
615     for (int iZone = 0 ; iZone < nbZones - 1 ; iZone++) {
616 persson 2246 gig::DimensionRegion* d = region->pDimensionRegions[c + (iZone << bitpos)];
617 schoenebeck 1225 const int upperLimit =
618     (customsplits) ?
619     (d->DimensionUpperLimits[dim]) ?
620     d->DimensionUpperLimits[dim] : d->VelocityUpperLimit
621     : (iZone+1) * (int)region->pDimensionDefinitions[dim].zone_size - 1;
622     int limit = upperLimit + 1;
623     int limitx = int((w - label_width - 1) * limit / 128.0 + 0.5) + label_width;
624     if (x <= limitx - 2) break;
625     if (x <= limitx + 2) {
626     resize.dimension = dim;
627     resize.offset = iZone << bitpos;
628     resize.pos = limit;
629     resize.min = prev_limit;
630    
631     int dr = (dimregno >> bitpos) &
632     ((1 << region->pDimensionDefinitions[dim].bits) - 1);
633     resize.selected = dr == iZone ? resize.left :
634     dr == iZone + 1 ? resize.right : resize.none;
635    
636     iZone++;
637 persson 2246 gig::DimensionRegion* d = region->pDimensionRegions[c + (iZone << bitpos)];
638 schoenebeck 1225
639     const int upperLimit =
640     (customsplits) ?
641     (d->DimensionUpperLimits[dim]) ?
642     d->DimensionUpperLimits[dim] : d->VelocityUpperLimit
643     : (iZone+1) * (int)region->pDimensionDefinitions[dim].zone_size - 1;
644    
645     int limit = upperLimit + 1;
646     resize.max = limit;
647     return true;
648     }
649     prev_limit = limit;
650     }
651     }
652     }
653     return false;
654     }
655    
656 schoenebeck 1339 sigc::signal<void>& DimRegionChooser::signal_dimregion_selected()
657 schoenebeck 1225 {
658 persson 1261 return dimregion_selected;
659 schoenebeck 1225 }
660    
661 schoenebeck 1339 sigc::signal<void>& DimRegionChooser::signal_region_changed()
662 persson 1261 {
663     return region_changed;
664     }
665    
666 schoenebeck 1225 bool DimRegionChooser::on_focus(Gtk::DirectionType direction)
667     {
668     // TODO: kolla att region finns osv, dvs att det g�r att s�tta
669     // fokus.
670     if (direction == Gtk::DIR_TAB_FORWARD ||
671     direction == Gtk::DIR_DOWN) {
672     if (!has_focus()) {
673     focus_line = 0;
674     grab_focus();
675     return true;
676     } else {
677     if (focus_line + 1 < region->Dimensions) {
678     focus_line++;
679     queue_draw();
680     return true;
681     } else {
682     return false;
683     }
684     }
685     } else if (direction == Gtk::DIR_TAB_BACKWARD ||
686     direction == Gtk::DIR_UP) {
687     if (!has_focus()) {
688     focus_line = region->Dimensions - 1;
689     grab_focus();
690     return true;
691     } else {
692     if (focus_line > 0) {
693     focus_line--;
694     queue_draw();
695     return true;
696     } else {
697     return false;
698     }
699     }
700     } else if (!has_focus()) {
701     // TODO: kolla att focus_line finns!
702     grab_focus();
703     return true;
704     } else {
705     // TODO: �ka eller minska v�rde!
706     }
707     }

  ViewVC Help
Powered by ViewVC