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

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

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1420 by persson, Sun Oct 14 15:39:32 2007 UTC revision 2470 by persson, Sun Sep 15 13:31:04 2013 UTC
# Line 1  Line 1 
1  /*  /*
2   * Copyright (C) 2006, 2007 Andreas Persson   * Copyright (C) 2006-2011 Andreas Persson
3   *   *
4   * This program is free software; you can redistribute it and/or   * This program is free software; you can redistribute it and/or
5   * modify it under the terms of the GNU General Public License as   * modify it under the terms of the GNU General Public License as
# Line 18  Line 18 
18   */   */
19    
20  #include "dimregionchooser.h"  #include "dimregionchooser.h"
21    #include <cairomm/context.h>
22  #include <gdkmm/cursor.h>  #include <gdkmm/cursor.h>
23    #include <gdkmm/general.h>
24    #include <glibmm/stringutils.h>
25    
26  DimRegionChooser::DimRegionChooser()  #include "global.h"
27    
28    DimRegionChooser::DimRegionChooser() :
29        red("#8070ff"),
30        black("black"),
31        white("white")
32  {  {
     // get_window() would return 0 because the Gdk::Window has not yet been realized  
     // So we can only allocate the colors here - the rest will happen in on_realize().  
     Glib::RefPtr<Gdk::Colormap> colormap = get_default_colormap();  
   
     black = Gdk::Color("black");  
     white = Gdk::Color("white");  
     red = Gdk::Color("#8070ff");  
     blue = Gdk::Color("blue");  
     green = Gdk::Color("green");  
   
     colormap->alloc_color(black);  
     colormap->alloc_color(white);  
     colormap->alloc_color(red);  
     colormap->alloc_color(blue);  
     colormap->alloc_color(green);  
33      instrument = 0;      instrument = 0;
34      region = 0;      region = 0;
35      dimregno = -1;      dimregno = -1;
# Line 44  DimRegionChooser::DimRegionChooser() Line 37  DimRegionChooser::DimRegionChooser()
37      resize.active = false;      resize.active = false;
38      cursor_is_resize = false;      cursor_is_resize = false;
39      h = 20;      h = 20;
40      w = 800;      set_can_focus();
     set_flags(Gtk::CAN_FOCUS);  
41      add_events(Gdk::BUTTON_PRESS_MASK | Gdk::POINTER_MOTION_MASK |      add_events(Gdk::BUTTON_PRESS_MASK | Gdk::POINTER_MOTION_MASK |
42                 Gdk::POINTER_MOTION_HINT_MASK);                 Gdk::POINTER_MOTION_HINT_MASK);
43    
44      for (int i = 0 ; i < 256 ; i++) dimvalue[i] = 0;      for (int i = 0 ; i < 256 ; i++) dimvalue[i] = 0;
45        labels_changed = true;
46  }  }
47    
48  DimRegionChooser::~DimRegionChooser()  DimRegionChooser::~DimRegionChooser()
49  {  {
50  }  }
51    
52  void DimRegionChooser::on_realize()  #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
53    bool DimRegionChooser::on_expose_event(GdkEventExpose* e)
54  {  {
55      // We need to call the base on_realize()      double clipx1 = e->area.x;
56      Gtk::DrawingArea::on_realize();      double clipx2 = e->area.x + e->area.width;
57        double clipy1 = e->area.y;
58      // Now we can allocate any additional resources we need      double clipy2 = e->area.y + e->area.height;
59      Glib::RefPtr<Gdk::Window> window = get_window();  
60      gc = Gdk::GC::create(window);      const Cairo::RefPtr<Cairo::Context>& cr =
61            get_window()->create_cairo_context();
62    #if 0
63  }  }
64    #endif
65  bool DimRegionChooser::on_expose_event(GdkEventExpose* event)  #else
66    bool DimRegionChooser::on_draw(const Cairo::RefPtr<Cairo::Context>& cr)
67  {  {
68        double clipx1, clipx2, clipy1, clipy2;
69        cr->get_clip_extents(clipx1, clipy1, clipx2, clipy2);
70    #endif
71    
72      if (!region) return true;      if (!region) return true;
73    
74      // This is where we draw on the window      // This is where we draw on the window
75      Glib::RefPtr<Gdk::Window> window = get_window();      int w = get_width();
76      Glib::RefPtr<Pango::Context> context = get_pango_context();      Glib::RefPtr<Pango::Context> context = get_pango_context();
77    
78      Glib::RefPtr<Pango::Layout> layout = Pango::Layout::create(context);      Glib::RefPtr<Pango::Layout> layout = Pango::Layout::create(context);
79        cr->set_line_width(1);
80    
     window->clear();  
   
     // draw labels on the left (reflecting the dimension type)  
81      int y = 0;      int y = 0;
82      double maxwidth = 0;      if (labels_changed || label_width - 10 > clipx1) {
83      for (int i = 0 ; i < region->Dimensions ; i++) {          // draw labels on the left (reflecting the dimension type)
84          int nbZones = region->pDimensionDefinitions[i].zones;          double maxwidth = 0;
85          if (nbZones) {          for (int i = 0 ; i < region->Dimensions ; i++) {
86              const char* dstr;              int nbZones = region->pDimensionDefinitions[i].zones;
87              char dstrbuf[10];              if (nbZones) {
88              switch (region->pDimensionDefinitions[i].dimension) {                  const char* dstr;
89              case gig::dimension_none: dstr="none"; break;                  char dstrbuf[10];
90              case gig::dimension_samplechannel: dstr="samplechannel"; break;                  switch (region->pDimensionDefinitions[i].dimension) {
91              case gig::dimension_layer: dstr="layer"; break;                  case gig::dimension_none: dstr=_("none"); break;
92              case gig::dimension_velocity: dstr="velocity"; break;                  case gig::dimension_samplechannel: dstr=_("samplechannel");
93              case gig::dimension_channelaftertouch: dstr="channelaftertouch"; break;                      break;
94              case gig::dimension_releasetrigger: dstr="releasetrigger"; break;                  case gig::dimension_layer: dstr=_("layer"); break;
95              case gig::dimension_keyboard: dstr="keyboard"; break;                  case gig::dimension_velocity: dstr=_("velocity"); break;
96              case gig::dimension_roundrobin: dstr="roundrobin"; break;                  case gig::dimension_channelaftertouch:
97              case gig::dimension_random: dstr="random"; break;                      dstr=_("channelaftertouch"); break;
98              case gig::dimension_smartmidi: dstr="smartmidi"; break;                  case gig::dimension_releasetrigger:
99              case gig::dimension_roundrobinkeyboard: dstr="roundrobinkeyboard"; break;                      dstr=_("releasetrigger"); break;
100              case gig::dimension_modwheel: dstr="modwheel"; break;                  case gig::dimension_keyboard: dstr=_("keyswitching"); break;
101              case gig::dimension_breath: dstr="breath"; break;                  case gig::dimension_roundrobin: dstr=_("roundrobin"); break;
102              case gig::dimension_foot: dstr="foot"; break;                  case gig::dimension_random: dstr=_("random"); break;
103              case gig::dimension_portamentotime: dstr="portamentotime"; break;                  case gig::dimension_smartmidi: dstr=_("smartmidi"); break;
104              case gig::dimension_effect1: dstr="effect1"; break;                  case gig::dimension_roundrobinkeyboard:
105              case gig::dimension_effect2: dstr="effect2"; break;                      dstr=_("roundrobinkeyboard"); break;
106              case gig::dimension_genpurpose1: dstr="genpurpose1"; break;                  case gig::dimension_modwheel: dstr=_("modwheel"); break;
107              case gig::dimension_genpurpose2: dstr="genpurpose2"; break;                  case gig::dimension_breath: dstr=_("breath"); break;
108              case gig::dimension_genpurpose3: dstr="genpurpose3"; break;                  case gig::dimension_foot: dstr=_("foot"); break;
109              case gig::dimension_genpurpose4: dstr="genpurpose4"; break;                  case gig::dimension_portamentotime:
110              case gig::dimension_sustainpedal: dstr="sustainpedal"; break;                      dstr=_("portamentotime"); break;
111              case gig::dimension_portamento: dstr="portamento"; break;                  case gig::dimension_effect1: dstr=_("effect1"); break;
112              case gig::dimension_sostenutopedal: dstr="sostenutopedal"; break;                  case gig::dimension_effect2: dstr=_("effect2"); break;
113              case gig::dimension_softpedal: dstr="softpedal"; break;                  case gig::dimension_genpurpose1: dstr=_("genpurpose1"); break;
114              case gig::dimension_genpurpose5: dstr="genpurpose5"; break;                  case gig::dimension_genpurpose2: dstr=_("genpurpose2"); break;
115              case gig::dimension_genpurpose6: dstr="genpurpose6"; break;                  case gig::dimension_genpurpose3: dstr=_("genpurpose3"); break;
116              case gig::dimension_genpurpose7: dstr="genpurpose7"; break;                  case gig::dimension_genpurpose4: dstr=_("genpurpose4"); break;
117              case gig::dimension_genpurpose8: dstr="genpurpose8"; break;                  case gig::dimension_sustainpedal:
118              case gig::dimension_effect1depth: dstr="effect1depth"; break;                      dstr=_("sustainpedal"); break;
119              case gig::dimension_effect2depth: dstr="effect2depth"; break;                  case gig::dimension_portamento: dstr=_("portamento"); break;
120              case gig::dimension_effect3depth: dstr="effect3depth"; break;                  case gig::dimension_sostenutopedal:
121              case gig::dimension_effect4depth: dstr="effect4depth"; break;                      dstr=_("sostenutopedal"); break;
122              case gig::dimension_effect5depth: dstr="effect5depth"; break;                  case gig::dimension_softpedal: dstr=_("softpedal"); break;
123              default:                  case gig::dimension_genpurpose5: dstr=_("genpurpose5"); break;
124                  sprintf(dstrbuf, "%d",                  case gig::dimension_genpurpose6: dstr=_("genpurpose6"); break;
125                          region->pDimensionDefinitions[i].dimension);                  case gig::dimension_genpurpose7: dstr=_("genpurpose7"); break;
126                  dstr = dstrbuf;                  case gig::dimension_genpurpose8: dstr=_("genpurpose8"); break;
127                  break;                  case gig::dimension_effect1depth:
128              }                      dstr=_("effect1depth"); break;
129              layout->set_text(dstr);                  case gig::dimension_effect2depth:
130                        dstr=_("effect2depth"); break;
131              Pango::Rectangle rectangle = layout->get_logical_extents();                  case gig::dimension_effect3depth:
132              double text_w = double(rectangle.get_width()) / Pango::SCALE;                      dstr=_("effect3depth"); break;
133              if (text_w > maxwidth) maxwidth = text_w;                  case gig::dimension_effect4depth:
134              double text_h = double(rectangle.get_height()) / Pango::SCALE;                      dstr=_("effect4depth"); break;
135              Glib::RefPtr<const Gdk::GC> fg = get_style()->get_fg_gc(get_state());                  case gig::dimension_effect5depth:
136              window->draw_layout(fg, 4, int(y + (h - text_h) / 2 + 0.5), layout);                      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    
145                    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    #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
153                        const Gdk::Color fg = get_style()->get_fg(get_state());
154    #else
155                        const Gdk::RGBA fg =
156                            get_style_context()->get_color(get_state_flags());
157    #endif
158                        Gdk::Cairo::set_source_rgba(cr, fg);
159                        cr->move_to(4, int(y + (h - text_h) / 2 + 0.5));
160    #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 16) || GTKMM_MAJOR_VERSION < 2
161                        pango_cairo_show_layout(cr->cobj(), layout->gobj());
162    #else
163                        layout->show_in_cairo_context(cr);
164    #endif
165                    }
166                }
167                y += h;
168          }          }
169          y += h;          label_width = int(maxwidth + 10);
170            labels_changed = false;
171      }      }
172        if (label_width >= clipx2) return true;
173    
174      // draw dimensions' zones areas      // draw dimensions' zones areas
175      y = 0;      y = 0;
176      int bitpos = 0;      int bitpos = 0;
     label_width = int(maxwidth + 10);  
177      for (int i = 0 ; i < region->Dimensions ; i++) {      for (int i = 0 ; i < region->Dimensions ; i++) {
178          int nbZones = region->pDimensionDefinitions[i].zones;          int nbZones = region->pDimensionDefinitions[i].zones;
179          if (nbZones) {          if (nbZones) {
180              // draw focus rectangle around dimension's label and zones              if (y >= clipy2) break;
181              if (has_focus() && focus_line == i) {              if (y + h > clipy1) {
182                  Gdk::Rectangle farea(0, y, 150, 20);                  // draw focus rectangle around dimension's label and zones
183                  get_style()->paint_focus(window, get_state(), farea, *this, "",                  if (has_focus() && focus_line == i) {
184                                           0, y, label_width, 20);  #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
185              }                      Gdk::Rectangle farea(0, y, 150, 20);
186                        get_style()->paint_focus(get_window(), get_state(), farea,
187              Glib::RefPtr<const Gdk::GC> black = get_style()->get_black_gc();                                               *this, "",
188              // draw top and bottom lines of dimension's zones                                               0, y, label_width, 20);
189              window->draw_line(black, label_width, y, w - 1, y);  #else
190              window->draw_line(black, w - 1, y + h - 1, label_width, y + h - 1);                      get_style_context()->render_focus(cr,
191              // erase whole dimension's zones area                                                        0, y, label_width, 20);
192              window->draw_rectangle(get_style()->get_white_gc(), true,  #endif
193                                     label_width + 1, y + 1, (w - label_width - 2), h - 2);                  }
194    
195              int c = 0;                  // draw top and bottom lines of dimension's zones
196              if (dimregno >= 0) {                  Gdk::Cairo::set_source_rgba(cr, black);
197                  int mask = ~(((1 << region->pDimensionDefinitions[i].bits) - 1) << bitpos);                  cr->move_to(label_width, y + 0.5);
198                  c = dimregno & mask; // mask away this dimension                  cr->line_to(w, y + 0.5);
199              }                  cr->move_to(w, y + h - 0.5);
200              bool customsplits =                  cr->line_to(label_width, y + h - 0.5);
201                  ((region->pDimensionDefinitions[i].split_type == gig::split_type_normal &&                  cr->stroke();
202                   region->pDimensionRegions[c]->DimensionUpperLimits[i]) ||  
203                  (region->pDimensionDefinitions[i].dimension == gig::dimension_velocity &&                  // erase whole dimension's zones area
204                   region->pDimensionRegions[c]->VelocityUpperLimit));                  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    
209                    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                    }
216                    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    
224              // draw dimension's zone borders                  // draw dimension's zone borders
225              if (customsplits) {                  Gdk::Cairo::set_source_rgba(cr, black);
                 window->draw_line(black, label_width, y + 1, label_width, y + h - 2);  
                 for (int j = 0 ; j < nbZones ; j++) {  
                     gig::DimensionRegion *d = region->pDimensionRegions[c + (j << bitpos)];  
                     int upperLimit = d->DimensionUpperLimits[i];  
                     if (!upperLimit) upperLimit = d->VelocityUpperLimit;  
                     int v = upperLimit + 1;  
                     int x = int((w - label_width - 1) * v / 128.0 + 0.5);  
                     window->draw_line(black, label_width + x, y + 1, label_width + x, y + h - 2);  
                 }  
             } else {  
                 for (int j = 0 ; j <= nbZones ; j++) {  
                     int x = int((w - label_width - 1) * j / double(nbZones) + 0.5);  
                     window->draw_line(black, label_width + x, y + 1, label_width + x, y + h - 2);  
                 }  
             }  
   
             // draw fill for currently selected zone  
             if (dimregno >= 0) {  
                 gc->set_foreground(red);  
                 int dr = (dimregno >> bitpos) & ((1 << region->pDimensionDefinitions[i].bits) - 1);  
226                  if (customsplits) {                  if (customsplits) {
227                      int x1 = 0;                      cr->move_to(label_width + 0.5, y + 1);
228                        cr->line_to(label_width + 0.5, y + h - 1);
229    
230                      for (int j = 0 ; j < nbZones ; j++) {                      for (int j = 0 ; j < nbZones ; j++) {
231                          gig::DimensionRegion *d = region->pDimensionRegions[c + (j << bitpos)];                          gig::DimensionRegion* d =
232                                region->pDimensionRegions[c + (j << bitpos)];
233                          int upperLimit = d->DimensionUpperLimits[i];                          int upperLimit = d->DimensionUpperLimits[i];
234                          if (!upperLimit) upperLimit = d->VelocityUpperLimit;                          if (!upperLimit) upperLimit = d->VelocityUpperLimit;
235                          int v = upperLimit + 1;                          int v = upperLimit + 1;
236                          int x2 = int((w - label_width - 1) * v / 128.0 + 0.5);                          int x = int((w - label_width - 1) * v / 128.0 + 0.5) +
237                          if (j == dr && x1 < x2) {                              label_width;
238                              window->draw_rectangle(gc, true, label_width + x1 + 1, y + 1,                          if (x >= clipx2) break;
239                                                     (x2 - x1) - 1, h - 2);                          if (x < clipx1) continue;
240                              break;                          cr->move_to(x + 0.5, y + 1);
241                          }                          cr->line_to(x + 0.5, y + h - 1);
                         x1 = x2;  
242                      }                      }
243                  } else {                  } else {
244                      if (dr < nbZones) {                      for (int j = 0 ; j <= nbZones ; j++) {
245                          int x1 = int((w - label_width - 1) * dr / double(nbZones) + 0.5);                          int x = int((w - label_width - 1) * j /
246                          int x2 = int((w - label_width - 1) * (dr + 1) / double(nbZones) + 0.5);                                      double(nbZones) + 0.5) + label_width;
247                          window->draw_rectangle(gc, true, label_width + x1 + 1, y + 1,                          if (x >= clipx2) break;
248                                                 (x2 - x1) - 1, h - 2);                          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                        
261                        int x1 = -1, x2 = -1;
262                        if (customsplits) {
263                            x1 = label_width;
264                            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                                x2 = int((w - label_width - 1) * v / 128.0 +
273                                         0.5) + label_width;
274                                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                                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                                cr->rectangle(label_width + x1 + 1, y + 1,
289                                              (x2 - x1) - 1, h - 2);
290                                cr->fill();
291                            }
292                        }
293    
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                  }                  }
336              }              }
# Line 228  bool DimRegionChooser::on_expose_event(G Line 343  bool DimRegionChooser::on_expose_event(G
343      return true;      return true;
344  }  }
345    
 void DimRegionChooser::on_size_request(GtkRequisition* requisition)  
 {  
     *requisition = GtkRequisition();  
     requisition->height = region ? nbDimensions * 20 : 0;  
     requisition->width = 800;  
 }  
   
346  void DimRegionChooser::set_region(gig::Region* region)  void DimRegionChooser::set_region(gig::Region* region)
347  {  {
348      this->region = region;      this->region = region;
# Line 248  void DimRegionChooser::set_region(gig::R Line 356  void DimRegionChooser::set_region(gig::R
356    
357              int z = std::min(dimvalue[region->pDimensionDefinitions[dim].dimension],              int z = std::min(dimvalue[region->pDimensionDefinitions[dim].dimension],
358                               region->pDimensionDefinitions[dim].zones - 1);                               region->pDimensionDefinitions[dim].zones - 1);
             int mask =  
                 ~(((1 << region->pDimensionDefinitions[dim].bits) - 1) <<  
                   bitcount);  
             dimregno &= mask;  
359              dimregno |= (z << bitcount);              dimregno |= (z << bitcount);
360              bitcount += region->pDimensionDefinitions[dim].bits;              bitcount += region->pDimensionDefinitions[dim].bits;
361          }          }
# Line 260  void DimRegionChooser::set_region(gig::R Line 364  void DimRegionChooser::set_region(gig::R
364          dimreg = 0;          dimreg = 0;
365      }      }
366      dimregion_selected();      dimregion_selected();
367        set_size_request(800, region ? nbDimensions * 20 : 0);
368    
369        labels_changed = true;
370      queue_resize();      queue_resize();
371  }  }
372    
373  bool DimRegionChooser::on_button_release_event(GdkEventButton* event)  
374    void DimRegionChooser::get_dimregions(const gig::Region* region, bool stereo,
375                                          std::set<gig::DimensionRegion*>& dimregs) const
376  {  {
377      if (resize.active) {      int dimregno = 0;
378          get_window()->pointer_ungrab(event->time);      int bitcount = 0;
379          resize.active = false;      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          if (region->pDimensionDefinitions[resize.dimension].dimension == gig::dimension_velocity) {  void DimRegionChooser::update_after_resize()
397    {
398        if (region->pDimensionDefinitions[resize.dimension].dimension == gig::dimension_velocity) {
399    
400              int bitpos = 0;          int bitpos = 0;
401              for (int j = 0 ; j < resize.dimension ; j++) {          for (int j = 0 ; j < resize.dimension ; j++) {
402                  bitpos += region->pDimensionDefinitions[j].bits;              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    
408            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              }              }
417              int mask =          }
418                  ~(((1 << region->pDimensionDefinitions[resize.dimension].bits) - 1) << bitpos);          if (region->pDimensionRegions[c]->VelocityUpperLimit == 0) {
419              int c = dimregno & mask; // mask away this dimension              // 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    
429              if (region->pDimensionRegions[c]->DimensionUpperLimits[resize.dimension] == 0) {          gig::DimensionRegion* d = region->pDimensionRegions[c + resize.offset];
430                  // the velocity dimension didn't previously have          // update both v2 and v3 values
431                  // custom v3 splits, so we initialize all splits with          d->DimensionUpperLimits[resize.dimension] = resize.pos - 1;
432                  // default values          d->VelocityUpperLimit = resize.pos - 1;
433                  int nbZones = region->pDimensionDefinitions[resize.dimension].zones;  
434                  for (int j = 0 ; j < nbZones ; j++) {      } else {
435                      gig::DimensionRegion *d = region->pDimensionRegions[c + (j << bitpos)];          for (int i = 0 ; i < region->DimensionRegions ; ) {
436                      d->DimensionUpperLimits[resize.dimension] = int(128.0 * (j + 1) / nbZones - 1);  
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                  }                  }
             }  
             if (region->pDimensionRegions[c]->VelocityUpperLimit == 0) {  
                 // the velocity dimension didn't previously have  
                 // custom v2 splits, so we initialize all splits with  
                 // default values  
445                  int nbZones = region->pDimensionDefinitions[resize.dimension].zones;                  int nbZones = region->pDimensionDefinitions[resize.dimension].zones;
446    
447                  for (int j = 0 ; j < nbZones ; j++) {                  for (int j = 0 ; j < nbZones ; j++) {
448                      gig::DimensionRegion *d = region->pDimensionRegions[c + (j << bitpos)];                      gig::DimensionRegion* d = region->pDimensionRegions[i + (j << bitpos)];
449                      d->VelocityUpperLimit = int(128.0 * (j + 1) / nbZones - 1);                      d->DimensionUpperLimits[resize.dimension] = int(128.0 * (j + 1) / nbZones - 1);
450                  }                  }
451              }              }
452                gig::DimensionRegion* d = region->pDimensionRegions[i + resize.offset];
             gig::DimensionRegion *d = region->pDimensionRegions[c + resize.offset];  
             // update both v2 and v3 values  
453              d->DimensionUpperLimits[resize.dimension] = resize.pos - 1;              d->DimensionUpperLimits[resize.dimension] = resize.pos - 1;
             d->VelocityUpperLimit = resize.pos - 1;  
   
         } else {  
             for (int i = 0 ; i < region->DimensionRegions ; ) {  
   
                 if (region->pDimensionRegions[i]->DimensionUpperLimits[resize.dimension] == 0) {  
                     // the dimension didn't previously have custom  
                     // limits, so we have to set default limits for  
                     // all the dimension regions  
                     int bitpos = 0;  
                     for (int j = 0 ; j < resize.dimension ; j++) {  
                         bitpos += region->pDimensionDefinitions[j].bits;  
                     }  
                     int nbZones = region->pDimensionDefinitions[resize.dimension].zones;  
   
                     for (int j = 0 ; j < nbZones ; j++) {  
                         gig::DimensionRegion *d = region->pDimensionRegions[i + (j << bitpos)];  
                         d->DimensionUpperLimits[resize.dimension] = int(128.0 * (j + 1) / nbZones - 1);  
                     }  
                 }  
                 gig::DimensionRegion *d = region->pDimensionRegions[i + resize.offset];  
                 d->DimensionUpperLimits[resize.dimension] = resize.pos - 1;  
454    
455                  int bitpos = 0;              int bitpos = 0;
456                  int j;              int j;
457                  for (j = 0 ; j < region->Dimensions ; j++) {              for (j = 0 ; j < region->Dimensions ; j++) {
458                      if (j != resize.dimension) {                  if (j != resize.dimension) {
459                          int maxzones = 1 << region->pDimensionDefinitions[j].bits;                      int maxzones = 1 << region->pDimensionDefinitions[j].bits;
460                          int dimj = (i >> bitpos) & (maxzones - 1);                      int dimj = (i >> bitpos) & (maxzones - 1);
461                          if (dimj + 1 < region->pDimensionDefinitions[j].zones) break;                      if (dimj + 1 < region->pDimensionDefinitions[j].zones) break;
                     }  
                     bitpos += region->pDimensionDefinitions[j].bits;  
462                  }                  }
463                  if (j == region->Dimensions) break;                  bitpos += region->pDimensionDefinitions[j].bits;
                 i = (i & ~((1 << bitpos) - 1)) + (1 << bitpos);  
464              }              }
465                if (j == region->Dimensions) break;
466                i = (i & ~((1 << bitpos) - 1)) + (1 << bitpos);
467          }          }
468        }
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          region_changed();          region_changed();
482    
483          if (!is_in_resize_zone(event->x, event->y) && cursor_is_resize) {          if (!is_in_resize_zone(event->x, event->y) && cursor_is_resize) {
# Line 352  bool DimRegionChooser::on_button_release Line 490  bool DimRegionChooser::on_button_release
490    
491  bool DimRegionChooser::on_button_press_event(GdkEventButton* event)  bool DimRegionChooser::on_button_press_event(GdkEventButton* event)
492  {  {
493        int w = get_width();
494      if (region && event->y < nbDimensions * h &&      if (region && event->y < nbDimensions * h &&
495          event->x >= label_width && event->x < w) {          event->x >= label_width && event->x < w) {
496    
497          if (is_in_resize_zone(event->x, event->y)) {          if (is_in_resize_zone(event->x, event->y)) {
498              Gdk::Cursor double_arrow(Gdk::SB_H_DOUBLE_ARROW);  #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
499              get_window()->pointer_grab(false,              get_window()->pointer_grab(false,
500                                         Gdk::BUTTON_RELEASE_MASK |                                         Gdk::BUTTON_RELEASE_MASK |
501                                         Gdk::POINTER_MOTION_MASK |                                         Gdk::POINTER_MOTION_MASK |
502                                         Gdk::POINTER_MOTION_HINT_MASK,                                         Gdk::POINTER_MOTION_HINT_MASK,
503                                         double_arrow, event->time);                                         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              resize.active = true;              resize.active = true;
516          } else {          } else {
517              int ydim = int(event->y / h);              int ydim = int(event->y / h);
# Line 394  bool DimRegionChooser::on_button_press_e Line 544  bool DimRegionChooser::on_button_press_e
544    
545                  if (region->pDimensionRegions[c]->DimensionUpperLimits[i]) {                  if (region->pDimensionRegions[c]->DimensionUpperLimits[i]) {
546                      for (z = 0 ; z < nbZones ; z++) {                      for (z = 0 ; z < nbZones ; z++) {
547                          gig::DimensionRegion *d = region->pDimensionRegions[c + (z << bitpos)];                          gig::DimensionRegion* d = region->pDimensionRegions[c + (z << bitpos)];
548                          if (val <= d->DimensionUpperLimits[i]) break;                          if (val <= d->DimensionUpperLimits[i]) break;
549                      }                      }
550                  } else {                  } else {
551                      for (z = 0 ; z < nbZones ; z++) {                      for (z = 0 ; z < nbZones ; z++) {
552                          gig::DimensionRegion *d = region->pDimensionRegions[c + (z << bitpos)];                          gig::DimensionRegion* d = region->pDimensionRegions[c + (z << bitpos)];
553                          if (val <= d->VelocityUpperLimit) break;                          if (val <= d->VelocityUpperLimit) break;
554                      }                      }
555                  }                  }
# Line 434  bool DimRegionChooser::on_motion_notify_ Line 584  bool DimRegionChooser::on_motion_notify_
584      window->get_pointer(x, y, state);      window->get_pointer(x, y, state);
585    
586      if (resize.active) {      if (resize.active) {
587            int w = get_width();
588          int k = int((x - label_width) * 128.0 / (w - label_width - 1) + 0.5);          int k = int((x - label_width) * 128.0 / (w - label_width - 1) + 0.5);
589    
590          if (k < resize.min) k = resize.min;          if (k < resize.min) k = resize.min;
# Line 442  bool DimRegionChooser::on_motion_notify_ Line 593  bool DimRegionChooser::on_motion_notify_
593          if (k < 2) k = 2; // k is upper limit + 1, upper limit 0 is forbidden          if (k < 2) k = 2; // k is upper limit + 1, upper limit 0 is forbidden
594    
595          if (k != resize.pos) {          if (k != resize.pos) {
             Glib::RefPtr<const Gdk::GC> black = get_style()->get_black_gc();  
             Glib::RefPtr<const Gdk::GC> white = get_style()->get_white_gc();  
   
596              int prevx = int((w - label_width - 1) * resize.pos / 128.0 + 0.5) + label_width;              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;              int x = int((w - label_width - 1) * k / 128.0 + 0.5) + label_width;
598              int y = resize.dimension * h;              int y = resize.dimension * h;
599                int x1, x2;
600              if (resize.selected == resize.none) {              if (k > resize.pos) {
601                  if (resize.pos != resize.min && resize.pos != resize.max) {                  x1 = prevx;
602                      window->draw_line(white, prevx, y + 1, prevx, y + h - 2);                  x2 = x;
                 }  
603              } else {              } else {
604                  gc->set_foreground(red);                  x1 = x;
605                    x2 = prevx;
                 Glib::RefPtr<const Gdk::GC> left;  
                 Glib::RefPtr<const Gdk::GC> right;  
                 if (resize.selected == resize.left) {  
                     left = gc;  
                     right = white;  
                 } else {  
                     left = white;  
                     right = gc;  
                 }  
   
                 if (k > resize.pos) {  
                     int xx = resize.pos == resize.min ? 1 : 0;  
                     window->draw_rectangle(left, true,  
                                            prevx + xx, y + 1, x - prevx - xx, h - 2);  
                 } else {  
                     int xx = resize.pos == resize.max ? 0 : 1;  
                     window->draw_rectangle(right, true,  
                                            x, y + 1, prevx - x + xx, h - 2);  
                 }  
606              }              }
607              window->draw_line(black, x, y + 1, x, y + h - 2);              Gdk::Rectangle rect(x1, y + 1, x2 - x1 + 1, h - 2);
608    
609              resize.pos = k;              resize.pos = k;
610                update_after_resize();
611                get_window()->invalidate_rect(rect, false);
612          }          }
613      } else {      } else {
614          if (is_in_resize_zone(x, y)) {          if (is_in_resize_zone(x, y)) {
615              if (!cursor_is_resize) {              if (!cursor_is_resize) {
616                  Gdk::Cursor double_arrow(Gdk::SB_H_DOUBLE_ARROW);  #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
617                  window->set_cursor(double_arrow);                  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                  cursor_is_resize = true;                  cursor_is_resize = true;
622              }              }
623          } else if (cursor_is_resize) {          } else if (cursor_is_resize) {
# Line 496  bool DimRegionChooser::on_motion_notify_ Line 630  bool DimRegionChooser::on_motion_notify_
630    
631  bool DimRegionChooser::is_in_resize_zone(double x, double y)  bool DimRegionChooser::is_in_resize_zone(double x, double y)
632  {  {
633        int w = get_width();
634      if (region && y < nbDimensions * h && x >= label_width && x < w) {      if (region && y < nbDimensions * h && x >= label_width && x < w) {
635          int ydim = int(y / h);          int ydim = int(y / h);
636          int dim;          int dim;
# Line 523  bool DimRegionChooser::is_in_resize_zone Line 658  bool DimRegionChooser::is_in_resize_zone
658          if (region->pDimensionDefinitions[dim].split_type != gig::split_type_bit) {          if (region->pDimensionDefinitions[dim].split_type != gig::split_type_bit) {
659              int prev_limit = 0;              int prev_limit = 0;
660              for (int iZone = 0 ; iZone < nbZones - 1 ; iZone++) {              for (int iZone = 0 ; iZone < nbZones - 1 ; iZone++) {
661                  gig::DimensionRegion *d = region->pDimensionRegions[c + (iZone << bitpos)];                  gig::DimensionRegion* d = region->pDimensionRegions[c + (iZone << bitpos)];
662                  const int upperLimit =                  const int upperLimit =
663                      (customsplits) ?                      (customsplits) ?
664                          (d->DimensionUpperLimits[dim]) ?                          (d->DimensionUpperLimits[dim]) ?
# Line 544  bool DimRegionChooser::is_in_resize_zone Line 679  bool DimRegionChooser::is_in_resize_zone
679                          dr == iZone + 1 ? resize.right : resize.none;                          dr == iZone + 1 ? resize.right : resize.none;
680    
681                      iZone++;                      iZone++;
682                      gig::DimensionRegion *d = region->pDimensionRegions[c + (iZone << bitpos)];                      gig::DimensionRegion* d = region->pDimensionRegions[c + (iZone << bitpos)];
683    
684                      const int upperLimit =                      const int upperLimit =
685                          (customsplits) ?                          (customsplits) ?

Legend:
Removed from v.1420  
changed lines
  Added in v.2470

  ViewVC Help
Powered by ViewVC