/[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 2470 - (hide annotations) (download)
Sun Sep 15 13:31:04 2013 UTC (10 years, 7 months ago) by persson
File size: 31373 byte(s)
* fixed compilation error with newer glibmm
* minor update of Swedish and German translations
* Mac OS X: initialize gtk and gettext with files from base directory
  of the libgigedit library
* Mac OS X: fixed "recently used" in file dialogs
* Mac OS X: avoid crash when starting gigedit as an application bundle

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

  ViewVC Help
Powered by ViewVC