/[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 2556 by schoenebeck, Fri May 16 23:19:23 2014 UTC
# Line 1  Line 1 
1  /*  /*
2   * Copyright (C) 2006, 2007 Andreas Persson   * Copyright (C) 2006-2014 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  DimRegionChooser::DimRegionChooser()  #include <glibmm/stringutils.h>
25    #include <gtkmm/stock.h>
26    #include <glibmm/ustring.h>
27    #include <gtkmm/messagedialog.h>
28    
29    #include "global.h"
30    
31    DimRegionChooser::DimRegionChooser() :
32        red("#8070ff"),
33        black("black"),
34        white("white")
35  {  {
     // 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);  
36      instrument = 0;      instrument = 0;
37      region = 0;      region = 0;
38      dimregno = -1;      dimregno = -1;
# Line 44  DimRegionChooser::DimRegionChooser() Line 40  DimRegionChooser::DimRegionChooser()
40      resize.active = false;      resize.active = false;
41      cursor_is_resize = false;      cursor_is_resize = false;
42      h = 20;      h = 20;
43      w = 800;      set_can_focus();
44      set_flags(Gtk::CAN_FOCUS);  
45        actionGroup = Gtk::ActionGroup::create();
46        actionGroup->add(
47            Gtk::Action::create("SplitDimZone", _("Split Dimensions Zone")),
48            sigc::mem_fun(*this, &DimRegionChooser::split_dimension_zone)
49        );
50        actionGroup->add(
51            Gtk::Action::create("DeleteDimZone", _("Delete Dimension Zone")),
52            sigc::mem_fun(*this, &DimRegionChooser::delete_dimension_zone)
53        );
54    
55        uiManager = Gtk::UIManager::create();
56        uiManager->insert_action_group(actionGroup);
57        Glib::ustring ui_info =
58            "<ui>"
59            "  <popup name='PopupMenuInsideDimRegion'>"
60            "    <menuitem action='SplitDimZone'/>"
61            "    <menuitem action='DeleteDimZone'/>"
62            "  </popup>"
63    //         "  <popup name='PopupMenuOutsideDimRegion'>"
64    //         "    <menuitem action='Add'/>"
65    //         "  </popup>"
66            "</ui>";
67        uiManager->add_ui_from_string(ui_info);
68    
69        popup_menu_inside_dimregion = dynamic_cast<Gtk::Menu*>(
70            uiManager->get_widget("/PopupMenuInsideDimRegion"));
71    //     popup_menu_outside_dimregion = dynamic_cast<Gtk::Menu*>(
72    //         uiManager->get_widget("/PopupMenuOutsideDimRegion"));
73    
74      add_events(Gdk::BUTTON_PRESS_MASK | Gdk::POINTER_MOTION_MASK |      add_events(Gdk::BUTTON_PRESS_MASK | Gdk::POINTER_MOTION_MASK |
75                 Gdk::POINTER_MOTION_HINT_MASK);                 Gdk::POINTER_MOTION_HINT_MASK);
76    
77      for (int i = 0 ; i < 256 ; i++) dimvalue[i] = 0;      for (int i = 0 ; i < 256 ; i++) dimvalue[i] = 0;
78        labels_changed = true;
79    
80        set_tooltip_text(_("Right click here for options on altering dimension zones."));
81  }  }
82    
83  DimRegionChooser::~DimRegionChooser()  DimRegionChooser::~DimRegionChooser()
84  {  {
85  }  }
86    
87  void DimRegionChooser::on_realize()  #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
88    bool DimRegionChooser::on_expose_event(GdkEventExpose* e)
89  {  {
90      // We need to call the base on_realize()      double clipx1 = e->area.x;
91      Gtk::DrawingArea::on_realize();      double clipx2 = e->area.x + e->area.width;
92        double clipy1 = e->area.y;
93        double clipy2 = e->area.y + e->area.height;
94    
95        const Cairo::RefPtr<Cairo::Context>& cr =
96            get_window()->create_cairo_context();
97    #if 0
98    }
99    #endif
100    #else
101    bool DimRegionChooser::on_draw(const Cairo::RefPtr<Cairo::Context>& cr)
102    {
103        double clipx1, clipx2, clipy1, clipy2;
104        cr->get_clip_extents(clipx1, clipy1, clipx2, clipy2);
105    #endif
106    
     // Now we can allocate any additional resources we need  
     Glib::RefPtr<Gdk::Window> window = get_window();  
     gc = Gdk::GC::create(window);  
 }  
   
 bool DimRegionChooser::on_expose_event(GdkEventExpose* event)  
 {  
107      if (!region) return true;      if (!region) return true;
108    
109      // This is where we draw on the window      // This is where we draw on the window
110      Glib::RefPtr<Gdk::Window> window = get_window();      int w = get_width();
111      Glib::RefPtr<Pango::Context> context = get_pango_context();      Glib::RefPtr<Pango::Context> context = get_pango_context();
112    
113      Glib::RefPtr<Pango::Layout> layout = Pango::Layout::create(context);      Glib::RefPtr<Pango::Layout> layout = Pango::Layout::create(context);
114        cr->set_line_width(1);
115    
     window->clear();  
   
     // draw labels on the left (reflecting the dimension type)  
116      int y = 0;      int y = 0;
117      double maxwidth = 0;      if (labels_changed || label_width - 10 > clipx1) {
118      for (int i = 0 ; i < region->Dimensions ; i++) {          // draw labels on the left (reflecting the dimension type)
119          int nbZones = region->pDimensionDefinitions[i].zones;          double maxwidth = 0;
120          if (nbZones) {          for (int i = 0 ; i < region->Dimensions ; i++) {
121              const char* dstr;              int nbZones = region->pDimensionDefinitions[i].zones;
122              char dstrbuf[10];              if (nbZones) {
123              switch (region->pDimensionDefinitions[i].dimension) {                  const char* dstr;
124              case gig::dimension_none: dstr="none"; break;                  char dstrbuf[10];
125              case gig::dimension_samplechannel: dstr="samplechannel"; break;                  switch (region->pDimensionDefinitions[i].dimension) {
126              case gig::dimension_layer: dstr="layer"; break;                  case gig::dimension_none: dstr=_("none"); break;
127              case gig::dimension_velocity: dstr="velocity"; break;                  case gig::dimension_samplechannel: dstr=_("samplechannel");
128              case gig::dimension_channelaftertouch: dstr="channelaftertouch"; break;                      break;
129              case gig::dimension_releasetrigger: dstr="releasetrigger"; break;                  case gig::dimension_layer: dstr=_("layer"); break;
130              case gig::dimension_keyboard: dstr="keyboard"; break;                  case gig::dimension_velocity: dstr=_("velocity"); break;
131              case gig::dimension_roundrobin: dstr="roundrobin"; break;                  case gig::dimension_channelaftertouch:
132              case gig::dimension_random: dstr="random"; break;                      dstr=_("channelaftertouch"); break;
133              case gig::dimension_smartmidi: dstr="smartmidi"; break;                  case gig::dimension_releasetrigger:
134              case gig::dimension_roundrobinkeyboard: dstr="roundrobinkeyboard"; break;                      dstr=_("releasetrigger"); break;
135              case gig::dimension_modwheel: dstr="modwheel"; break;                  case gig::dimension_keyboard: dstr=_("keyswitching"); break;
136              case gig::dimension_breath: dstr="breath"; break;                  case gig::dimension_roundrobin: dstr=_("roundrobin"); break;
137              case gig::dimension_foot: dstr="foot"; break;                  case gig::dimension_random: dstr=_("random"); break;
138              case gig::dimension_portamentotime: dstr="portamentotime"; break;                  case gig::dimension_smartmidi: dstr=_("smartmidi"); break;
139              case gig::dimension_effect1: dstr="effect1"; break;                  case gig::dimension_roundrobinkeyboard:
140              case gig::dimension_effect2: dstr="effect2"; break;                      dstr=_("roundrobinkeyboard"); break;
141              case gig::dimension_genpurpose1: dstr="genpurpose1"; break;                  case gig::dimension_modwheel: dstr=_("modwheel"); break;
142              case gig::dimension_genpurpose2: dstr="genpurpose2"; break;                  case gig::dimension_breath: dstr=_("breath"); break;
143              case gig::dimension_genpurpose3: dstr="genpurpose3"; break;                  case gig::dimension_foot: dstr=_("foot"); break;
144              case gig::dimension_genpurpose4: dstr="genpurpose4"; break;                  case gig::dimension_portamentotime:
145              case gig::dimension_sustainpedal: dstr="sustainpedal"; break;                      dstr=_("portamentotime"); break;
146              case gig::dimension_portamento: dstr="portamento"; break;                  case gig::dimension_effect1: dstr=_("effect1"); break;
147              case gig::dimension_sostenutopedal: dstr="sostenutopedal"; break;                  case gig::dimension_effect2: dstr=_("effect2"); break;
148              case gig::dimension_softpedal: dstr="softpedal"; break;                  case gig::dimension_genpurpose1: dstr=_("genpurpose1"); break;
149              case gig::dimension_genpurpose5: dstr="genpurpose5"; break;                  case gig::dimension_genpurpose2: dstr=_("genpurpose2"); break;
150              case gig::dimension_genpurpose6: dstr="genpurpose6"; break;                  case gig::dimension_genpurpose3: dstr=_("genpurpose3"); break;
151              case gig::dimension_genpurpose7: dstr="genpurpose7"; break;                  case gig::dimension_genpurpose4: dstr=_("genpurpose4"); break;
152              case gig::dimension_genpurpose8: dstr="genpurpose8"; break;                  case gig::dimension_sustainpedal:
153              case gig::dimension_effect1depth: dstr="effect1depth"; break;                      dstr=_("sustainpedal"); break;
154              case gig::dimension_effect2depth: dstr="effect2depth"; break;                  case gig::dimension_portamento: dstr=_("portamento"); break;
155              case gig::dimension_effect3depth: dstr="effect3depth"; break;                  case gig::dimension_sostenutopedal:
156              case gig::dimension_effect4depth: dstr="effect4depth"; break;                      dstr=_("sostenutopedal"); break;
157              case gig::dimension_effect5depth: dstr="effect5depth"; break;                  case gig::dimension_softpedal: dstr=_("softpedal"); break;
158              default:                  case gig::dimension_genpurpose5: dstr=_("genpurpose5"); break;
159                  sprintf(dstrbuf, "%d",                  case gig::dimension_genpurpose6: dstr=_("genpurpose6"); break;
160                          region->pDimensionDefinitions[i].dimension);                  case gig::dimension_genpurpose7: dstr=_("genpurpose7"); break;
161                  dstr = dstrbuf;                  case gig::dimension_genpurpose8: dstr=_("genpurpose8"); break;
162                  break;                  case gig::dimension_effect1depth:
163              }                      dstr=_("effect1depth"); break;
164              layout->set_text(dstr);                  case gig::dimension_effect2depth:
165                        dstr=_("effect2depth"); break;
166              Pango::Rectangle rectangle = layout->get_logical_extents();                  case gig::dimension_effect3depth:
167              double text_w = double(rectangle.get_width()) / Pango::SCALE;                      dstr=_("effect3depth"); break;
168              if (text_w > maxwidth) maxwidth = text_w;                  case gig::dimension_effect4depth:
169              double text_h = double(rectangle.get_height()) / Pango::SCALE;                      dstr=_("effect4depth"); break;
170              Glib::RefPtr<const Gdk::GC> fg = get_style()->get_fg_gc(get_state());                  case gig::dimension_effect5depth:
171              window->draw_layout(fg, 4, int(y + (h - text_h) / 2 + 0.5), layout);                      dstr=_("effect5depth"); break;
172                    default:
173                        sprintf(dstrbuf, "%d",
174                                region->pDimensionDefinitions[i].dimension);
175                        dstr = dstrbuf;
176                        break;
177                    }
178                    layout->set_text(dstr);
179    
180                    Pango::Rectangle rectangle = layout->get_logical_extents();
181                    double text_w = double(rectangle.get_width()) / Pango::SCALE;
182                    if (text_w > maxwidth) maxwidth = text_w;
183    
184                    if (y + h > clipy1 && y < clipy2 && text_w >= clipx1) {
185                        double text_h = double(rectangle.get_height()) /
186                            Pango::SCALE;
187    #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
188                        const Gdk::Color fg = get_style()->get_fg(get_state());
189    #else
190                        const Gdk::RGBA fg =
191                            get_style_context()->get_color(get_state_flags());
192    #endif
193                        Gdk::Cairo::set_source_rgba(cr, fg);
194                        cr->move_to(4, int(y + (h - text_h) / 2 + 0.5));
195    #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 16) || GTKMM_MAJOR_VERSION < 2
196                        pango_cairo_show_layout(cr->cobj(), layout->gobj());
197    #else
198                        layout->show_in_cairo_context(cr);
199    #endif
200                    }
201                }
202                y += h;
203          }          }
204          y += h;          label_width = int(maxwidth + 10);
205            labels_changed = false;
206      }      }
207        if (label_width >= clipx2) return true;
208    
209      // draw dimensions' zones areas      // draw dimensions' zones areas
210      y = 0;      y = 0;
211      int bitpos = 0;      int bitpos = 0;
     label_width = int(maxwidth + 10);  
212      for (int i = 0 ; i < region->Dimensions ; i++) {      for (int i = 0 ; i < region->Dimensions ; i++) {
213          int nbZones = region->pDimensionDefinitions[i].zones;          int nbZones = region->pDimensionDefinitions[i].zones;
214          if (nbZones) {          if (nbZones) {
215              // draw focus rectangle around dimension's label and zones              if (y >= clipy2) break;
216              if (has_focus() && focus_line == i) {              if (y + h > clipy1) {
217                  Gdk::Rectangle farea(0, y, 150, 20);                  // draw focus rectangle around dimension's label and zones
218                  get_style()->paint_focus(window, get_state(), farea, *this, "",                  if (has_focus() && focus_line == i) {
219                                           0, y, label_width, 20);  #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
220              }                      Gdk::Rectangle farea(0, y, 150, 20);
221                        get_style()->paint_focus(get_window(), get_state(), farea,
222              Glib::RefPtr<const Gdk::GC> black = get_style()->get_black_gc();                                               *this, "",
223              // draw top and bottom lines of dimension's zones                                               0, y, label_width, 20);
224              window->draw_line(black, label_width, y, w - 1, y);  #else
225              window->draw_line(black, w - 1, y + h - 1, label_width, y + h - 1);                      get_style_context()->render_focus(cr,
226              // erase whole dimension's zones area                                                        0, y, label_width, 20);
227              window->draw_rectangle(get_style()->get_white_gc(), true,  #endif
228                                     label_width + 1, y + 1, (w - label_width - 2), h - 2);                  }
229    
230              int c = 0;                  // draw top and bottom lines of dimension's zones
231              if (dimregno >= 0) {                  Gdk::Cairo::set_source_rgba(cr, black);
232                  int mask = ~(((1 << region->pDimensionDefinitions[i].bits) - 1) << bitpos);                  cr->move_to(label_width, y + 0.5);
233                  c = dimregno & mask; // mask away this dimension                  cr->line_to(w, y + 0.5);
234              }                  cr->move_to(w, y + h - 0.5);
235              bool customsplits =                  cr->line_to(label_width, y + h - 0.5);
236                  ((region->pDimensionDefinitions[i].split_type == gig::split_type_normal &&                  cr->stroke();
237                   region->pDimensionRegions[c]->DimensionUpperLimits[i]) ||  
238                  (region->pDimensionDefinitions[i].dimension == gig::dimension_velocity &&                  // erase whole dimension's zones area
239                   region->pDimensionRegions[c]->VelocityUpperLimit));                  Gdk::Cairo::set_source_rgba(cr, white);
240                    cr->rectangle(label_width + 1, y + 1,
241              // draw dimension's zone borders                                (w - label_width - 2), h - 2);
242              if (customsplits) {                  cr->fill();
243                  window->draw_line(black, label_width, y + 1, label_width, y + h - 2);  
244                  for (int j = 0 ; j < nbZones ; j++) {                  int c = 0;
245                      gig::DimensionRegion *d = region->pDimensionRegions[c + (j << bitpos)];                  if (dimregno >= 0) {
246                      int upperLimit = d->DimensionUpperLimits[i];                      int mask =
247                      if (!upperLimit) upperLimit = d->VelocityUpperLimit;                          ~(((1 << region->pDimensionDefinitions[i].bits) - 1) <<
248                      int v = upperLimit + 1;                            bitpos);
249                      int x = int((w - label_width - 1) * v / 128.0 + 0.5);                      c = dimregno & mask; // mask away this dimension
250                      window->draw_line(black, label_width + x, y + 1, label_width + x, y + h - 2);                  }
251                  }                  bool customsplits =
252              } else {                      ((region->pDimensionDefinitions[i].split_type ==
253                  for (int j = 0 ; j <= nbZones ; j++) {                        gig::split_type_normal &&
254                      int x = int((w - label_width - 1) * j / double(nbZones) + 0.5);                        region->pDimensionRegions[c]->DimensionUpperLimits[i]) ||
255                      window->draw_line(black, label_width + x, y + 1, label_width + x, y + h - 2);                       (region->pDimensionDefinitions[i].dimension ==
256                  }                        gig::dimension_velocity &&
257              }                        region->pDimensionRegions[c]->VelocityUpperLimit));
258    
259              // draw fill for currently selected zone                  // draw dimension's zone borders
260              if (dimregno >= 0) {                  Gdk::Cairo::set_source_rgba(cr, black);
                 gc->set_foreground(red);  
                 int dr = (dimregno >> bitpos) & ((1 << region->pDimensionDefinitions[i].bits) - 1);  
261                  if (customsplits) {                  if (customsplits) {
262                      int x1 = 0;                      cr->move_to(label_width + 0.5, y + 1);
263                        cr->line_to(label_width + 0.5, y + h - 1);
264    
265                      for (int j = 0 ; j < nbZones ; j++) {                      for (int j = 0 ; j < nbZones ; j++) {
266                          gig::DimensionRegion *d = region->pDimensionRegions[c + (j << bitpos)];                          gig::DimensionRegion* d =
267                                region->pDimensionRegions[c + (j << bitpos)];
268                          int upperLimit = d->DimensionUpperLimits[i];                          int upperLimit = d->DimensionUpperLimits[i];
269                          if (!upperLimit) upperLimit = d->VelocityUpperLimit;                          if (!upperLimit) upperLimit = d->VelocityUpperLimit;
270                          int v = upperLimit + 1;                          int v = upperLimit + 1;
271                          int x2 = int((w - label_width - 1) * v / 128.0 + 0.5);                          int x = int((w - label_width - 1) * v / 128.0 + 0.5) +
272                          if (j == dr && x1 < x2) {                              label_width;
273                              window->draw_rectangle(gc, true, label_width + x1 + 1, y + 1,                          if (x >= clipx2) break;
274                                                     (x2 - x1) - 1, h - 2);                          if (x < clipx1) continue;
275                              break;                          cr->move_to(x + 0.5, y + 1);
276                          }                          cr->line_to(x + 0.5, y + h - 1);
                         x1 = x2;  
277                      }                      }
278                  } else {                  } else {
279                      if (dr < nbZones) {                      for (int j = 0 ; j <= nbZones ; j++) {
280                          int x1 = int((w - label_width - 1) * dr / double(nbZones) + 0.5);                          int x = int((w - label_width - 1) * j /
281                          int x2 = int((w - label_width - 1) * (dr + 1) / double(nbZones) + 0.5);                                      double(nbZones) + 0.5) + label_width;
282                          window->draw_rectangle(gc, true, label_width + x1 + 1, y + 1,                          if (x >= clipx2) break;
283                                                 (x2 - x1) - 1, h - 2);                          if (x < clipx1) continue;
284                            cr->move_to(x + 0.5, y + 1);
285                            cr->line_to(x + 0.5, y + h - 1);
286                        }
287                    }
288                    cr->stroke();
289    
290                    // draw fill for currently selected zone
291                    if (dimregno >= 0) {
292                        Gdk::Cairo::set_source_rgba(cr, red);
293                        int dr = (dimregno >> bitpos) &
294                            ((1 << region->pDimensionDefinitions[i].bits) - 1);
295                        
296                        int x1 = -1, x2 = -1;
297                        if (customsplits) {
298                            x1 = label_width;
299                            for (int j = 0 ; j < nbZones && x1 + 1 < clipx2 ; j++) {
300                                gig::DimensionRegion* d =
301                                    region->pDimensionRegions[c + (j << bitpos)];
302                                int upperLimit = d->DimensionUpperLimits[i];
303                                if (!upperLimit) {
304                                    upperLimit = d->VelocityUpperLimit;
305                                }
306                                int v = upperLimit + 1;
307                                x2 = int((w - label_width - 1) * v / 128.0 +
308                                         0.5) + label_width;
309                                if (j == dr && x1 < x2) {
310                                    cr->rectangle(x1 + 1, y + 1,
311                                                  (x2 - x1) - 1, h - 2);
312                                    cr->fill();
313                                    break;
314                                }
315                                x1 = x2;
316                            }
317                        } else {
318                            if (dr < nbZones) {
319                                x1 = int((w - label_width - 1) * dr /
320                                         double(nbZones) + 0.5);
321                                x2 = int((w - label_width - 1) * (dr + 1) /
322                                         double(nbZones) + 0.5);
323                                cr->rectangle(label_width + x1 + 1, y + 1,
324                                              (x2 - x1) - 1, h - 2);
325                                cr->fill();
326                            }
327                        }
328    
329                        // draw text showing the beginning of the dimension zone
330                        // as numeric value to the user
331                        if (x1 >= 0) {
332                            Glib::RefPtr<Pango::Layout> layout = Pango::Layout::create(context);
333                            int v = roundf(float(x1 - label_width) / float(w - label_width) * 127.f);
334                            if (dr > 0) v++;
335                            layout->set_text(Glib::Ascii::dtostr(v));
336                            Gdk::Cairo::set_source_rgba(cr, black);
337                            Pango::Rectangle rect = layout->get_logical_extents();
338                            
339                            int text_width, text_height;
340                            // get the text dimensions
341                            layout->get_pixel_size(text_width, text_height);
342                            // move text to the right end of the dimension zone
343                            cr->move_to(x1 + 1, y + 1);
344    #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 16) || GTKMM_MAJOR_VERSION < 2
345                            pango_cairo_show_layout(cr->cobj(), layout->gobj());
346    #else
347                            layout->show_in_cairo_context(cr);
348    #endif
349                        }
350                        // draw text showing the end of the dimension zone
351                        // as numeric value to the user
352                        if (x2 >= 0) {
353                            Glib::RefPtr<Pango::Layout> layout = Pango::Layout::create(context);
354                            const int v = roundf(float(x2 - label_width) / float(w - label_width) * 127.f);
355                            layout->set_text(Glib::Ascii::dtostr(v));
356                            Gdk::Cairo::set_source_rgba(cr, black);
357                            Pango::Rectangle rect = layout->get_logical_extents();
358                            
359                            int text_width, text_height;
360                            // get the text dimensions
361                            layout->get_pixel_size(text_width, text_height);
362                            // move text to the right end of the dimension zone
363                            cr->move_to(x2 - text_width - 1, y + 1);
364    #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 16) || GTKMM_MAJOR_VERSION < 2
365                            pango_cairo_show_layout(cr->cobj(), layout->gobj());
366    #else
367                            layout->show_in_cairo_context(cr);
368    #endif
369                      }                      }
370                  }                  }
371              }              }
# Line 228  bool DimRegionChooser::on_expose_event(G Line 378  bool DimRegionChooser::on_expose_event(G
378      return true;      return true;
379  }  }
380    
 void DimRegionChooser::on_size_request(GtkRequisition* requisition)  
 {  
     *requisition = GtkRequisition();  
     requisition->height = region ? nbDimensions * 20 : 0;  
     requisition->width = 800;  
 }  
   
381  void DimRegionChooser::set_region(gig::Region* region)  void DimRegionChooser::set_region(gig::Region* region)
382  {  {
383      this->region = region;      this->region = region;
# Line 248  void DimRegionChooser::set_region(gig::R Line 391  void DimRegionChooser::set_region(gig::R
391    
392              int z = std::min(dimvalue[region->pDimensionDefinitions[dim].dimension],              int z = std::min(dimvalue[region->pDimensionDefinitions[dim].dimension],
393                               region->pDimensionDefinitions[dim].zones - 1);                               region->pDimensionDefinitions[dim].zones - 1);
             int mask =  
                 ~(((1 << region->pDimensionDefinitions[dim].bits) - 1) <<  
                   bitcount);  
             dimregno &= mask;  
394              dimregno |= (z << bitcount);              dimregno |= (z << bitcount);
395              bitcount += region->pDimensionDefinitions[dim].bits;              bitcount += region->pDimensionDefinitions[dim].bits;
396          }          }
# Line 260  void DimRegionChooser::set_region(gig::R Line 399  void DimRegionChooser::set_region(gig::R
399          dimreg = 0;          dimreg = 0;
400      }      }
401      dimregion_selected();      dimregion_selected();
402        set_size_request(800, region ? nbDimensions * 20 : 0);
403    
404        labels_changed = true;
405      queue_resize();      queue_resize();
406  }  }
407    
408  bool DimRegionChooser::on_button_release_event(GdkEventButton* event)  void DimRegionChooser::refresh_all() {
409        set_region(region);
410    }
411    
412    void DimRegionChooser::get_dimregions(const gig::Region* region, bool stereo,
413                                          std::set<gig::DimensionRegion*>& dimregs) const
414  {  {
415      if (resize.active) {      int dimregno = 0;
416          get_window()->pointer_ungrab(event->time);      int bitcount = 0;
417          resize.active = false;      int stereo_bit = 0;
418        for (int dim = 0 ; dim < region->Dimensions ; dim++) {
419            if (region->pDimensionDefinitions[dim].bits == 0) continue;
420            if (stereo &&
421                region->pDimensionDefinitions[dim].dimension == gig::dimension_samplechannel) {
422                stereo_bit = (1 << bitcount);
423            } else {
424                int z = std::min(dimvalue[region->pDimensionDefinitions[dim].dimension],
425                                 region->pDimensionDefinitions[dim].zones - 1);
426                dimregno |= (z << bitcount);
427            }
428            bitcount += region->pDimensionDefinitions[dim].bits;
429        }
430        dimregs.insert(region->pDimensionRegions[dimregno]);
431        if (stereo_bit) dimregs.insert(region->pDimensionRegions[dimregno | stereo_bit]);
432    }
433    
434          if (region->pDimensionDefinitions[resize.dimension].dimension == gig::dimension_velocity) {  void DimRegionChooser::update_after_resize()
435    {
436        if (region->pDimensionDefinitions[resize.dimension].dimension == gig::dimension_velocity) {
437    
438              int bitpos = 0;          int bitpos = 0;
439              for (int j = 0 ; j < resize.dimension ; j++) {          for (int j = 0 ; j < resize.dimension ; j++) {
440                  bitpos += region->pDimensionDefinitions[j].bits;              bitpos += region->pDimensionDefinitions[j].bits;
441            }
442            int mask =
443                ~(((1 << region->pDimensionDefinitions[resize.dimension].bits) - 1) << bitpos);
444            int c = dimregno & mask; // mask away this dimension
445    
446            if (region->pDimensionRegions[c]->DimensionUpperLimits[resize.dimension] == 0) {
447                // the velocity dimension didn't previously have
448                // custom v3 splits, so we initialize all splits with
449                // default values
450                int nbZones = region->pDimensionDefinitions[resize.dimension].zones;
451                for (int j = 0 ; j < nbZones ; j++) {
452                    gig::DimensionRegion* d = region->pDimensionRegions[c + (j << bitpos)];
453                    d->DimensionUpperLimits[resize.dimension] = int(128.0 * (j + 1) / nbZones - 1);
454                }
455            }
456            if (region->pDimensionRegions[c]->VelocityUpperLimit == 0) {
457                // the velocity dimension didn't previously have
458                // custom v2 splits, so we initialize all splits with
459                // default values
460                int nbZones = region->pDimensionDefinitions[resize.dimension].zones;
461                for (int j = 0 ; j < nbZones ; j++) {
462                    gig::DimensionRegion* d = region->pDimensionRegions[c + (j << bitpos)];
463                    d->VelocityUpperLimit = int(128.0 * (j + 1) / nbZones - 1);
464              }              }
465              int mask =          }
                 ~(((1 << region->pDimensionDefinitions[resize.dimension].bits) - 1) << bitpos);  
             int c = dimregno & mask; // mask away this dimension  
466    
467              if (region->pDimensionRegions[c]->DimensionUpperLimits[resize.dimension] == 0) {          gig::DimensionRegion* d = region->pDimensionRegions[c + resize.offset];
468                  // the velocity dimension didn't previously have          // update both v2 and v3 values
469                  // custom v3 splits, so we initialize all splits with          d->DimensionUpperLimits[resize.dimension] = resize.pos - 1;
470                  // default values          d->VelocityUpperLimit = resize.pos - 1;
471                  int nbZones = region->pDimensionDefinitions[resize.dimension].zones;  
472                  for (int j = 0 ; j < nbZones ; j++) {      } else {
473                      gig::DimensionRegion *d = region->pDimensionRegions[c + (j << bitpos)];          for (int i = 0 ; i < region->DimensionRegions ; ) {
474                      d->DimensionUpperLimits[resize.dimension] = int(128.0 * (j + 1) / nbZones - 1);  
475                if (region->pDimensionRegions[i]->DimensionUpperLimits[resize.dimension] == 0) {
476                    // the dimension didn't previously have custom
477                    // limits, so we have to set default limits for
478                    // all the dimension regions
479                    int bitpos = 0;
480                    for (int j = 0 ; j < resize.dimension ; j++) {
481                        bitpos += region->pDimensionDefinitions[j].bits;
482                  }                  }
             }  
             if (region->pDimensionRegions[c]->VelocityUpperLimit == 0) {  
                 // the velocity dimension didn't previously have  
                 // custom v2 splits, so we initialize all splits with  
                 // default values  
483                  int nbZones = region->pDimensionDefinitions[resize.dimension].zones;                  int nbZones = region->pDimensionDefinitions[resize.dimension].zones;
484    
485                  for (int j = 0 ; j < nbZones ; j++) {                  for (int j = 0 ; j < nbZones ; j++) {
486                      gig::DimensionRegion *d = region->pDimensionRegions[c + (j << bitpos)];                      gig::DimensionRegion* d = region->pDimensionRegions[i + (j << bitpos)];
487                      d->VelocityUpperLimit = int(128.0 * (j + 1) / nbZones - 1);                      d->DimensionUpperLimits[resize.dimension] = int(128.0 * (j + 1) / nbZones - 1);
488                  }                  }
489              }              }
490                gig::DimensionRegion* d = region->pDimensionRegions[i + resize.offset];
             gig::DimensionRegion *d = region->pDimensionRegions[c + resize.offset];  
             // update both v2 and v3 values  
491              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;  
492    
493                  int bitpos = 0;              int bitpos = 0;
494                  int j;              int j;
495                  for (j = 0 ; j < region->Dimensions ; j++) {              for (j = 0 ; j < region->Dimensions ; j++) {
496                      if (j != resize.dimension) {                  if (j != resize.dimension) {
497                          int maxzones = 1 << region->pDimensionDefinitions[j].bits;                      int maxzones = 1 << region->pDimensionDefinitions[j].bits;
498                          int dimj = (i >> bitpos) & (maxzones - 1);                      int dimj = (i >> bitpos) & (maxzones - 1);
499                          if (dimj + 1 < region->pDimensionDefinitions[j].zones) break;                      if (dimj + 1 < region->pDimensionDefinitions[j].zones) break;
                     }  
                     bitpos += region->pDimensionDefinitions[j].bits;  
500                  }                  }
501                  if (j == region->Dimensions) break;                  bitpos += region->pDimensionDefinitions[j].bits;
                 i = (i & ~((1 << bitpos) - 1)) + (1 << bitpos);  
502              }              }
503                if (j == region->Dimensions) break;
504                i = (i & ~((1 << bitpos) - 1)) + (1 << bitpos);
505          }          }
506        }
507    }
508    
509    bool DimRegionChooser::on_button_release_event(GdkEventButton* event)
510    {
511        if (resize.active) {
512    #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
513            get_window()->pointer_ungrab(event->time);
514    #else
515            Glib::wrap(event->device, true)->ungrab(event->time);
516    #endif
517            resize.active = false;
518    
519          region_changed();          region_changed();
520    
521          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 528  bool DimRegionChooser::on_button_release
528    
529  bool DimRegionChooser::on_button_press_event(GdkEventButton* event)  bool DimRegionChooser::on_button_press_event(GdkEventButton* event)
530  {  {
531        int w = get_width();
532      if (region && event->y < nbDimensions * h &&      if (region && event->y < nbDimensions * h &&
533          event->x >= label_width && event->x < w) {          event->x >= label_width && event->x < w) {
534    
535          if (is_in_resize_zone(event->x, event->y)) {          if (is_in_resize_zone(event->x, event->y)) {
536              Gdk::Cursor double_arrow(Gdk::SB_H_DOUBLE_ARROW);  #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
537              get_window()->pointer_grab(false,              get_window()->pointer_grab(false,
538                                         Gdk::BUTTON_RELEASE_MASK |                                         Gdk::BUTTON_RELEASE_MASK |
539                                         Gdk::POINTER_MOTION_MASK |                                         Gdk::POINTER_MOTION_MASK |
540                                         Gdk::POINTER_MOTION_HINT_MASK,                                         Gdk::POINTER_MOTION_HINT_MASK,
541                                         double_arrow, event->time);                                         Gdk::Cursor(Gdk::SB_H_DOUBLE_ARROW),
542                                           event->time);
543    #else
544                Glib::wrap(event->device, true)->grab(get_window(),
545                                                      Gdk::OWNERSHIP_NONE,
546                                                      false,
547                                                      Gdk::BUTTON_RELEASE_MASK |
548                                                      Gdk::POINTER_MOTION_MASK |
549                                                      Gdk::POINTER_MOTION_HINT_MASK,
550                                                      Gdk::Cursor::create(Gdk::SB_H_DOUBLE_ARROW),
551                                                      event->time);
552    #endif
553              resize.active = true;              resize.active = true;
554          } else {          } else {
555              int ydim = int(event->y / h);              int ydim = int(event->y / h);
# Line 394  bool DimRegionChooser::on_button_press_e Line 582  bool DimRegionChooser::on_button_press_e
582    
583                  if (region->pDimensionRegions[c]->DimensionUpperLimits[i]) {                  if (region->pDimensionRegions[c]->DimensionUpperLimits[i]) {
584                      for (z = 0 ; z < nbZones ; z++) {                      for (z = 0 ; z < nbZones ; z++) {
585                          gig::DimensionRegion *d = region->pDimensionRegions[c + (z << bitpos)];                          gig::DimensionRegion* d = region->pDimensionRegions[c + (z << bitpos)];
586                          if (val <= d->DimensionUpperLimits[i]) break;                          if (val <= d->DimensionUpperLimits[i]) break;
587                      }                      }
588                  } else {                  } else {
589                      for (z = 0 ; z < nbZones ; z++) {                      for (z = 0 ; z < nbZones ; z++) {
590                          gig::DimensionRegion *d = region->pDimensionRegions[c + (z << bitpos)];                          gig::DimensionRegion* d = region->pDimensionRegions[c + (z << bitpos)];
591                          if (val <= d->VelocityUpperLimit) break;                          if (val <= d->VelocityUpperLimit) break;
592                      }                      }
593                  }                  }
# Line 416  bool DimRegionChooser::on_button_press_e Line 604  bool DimRegionChooser::on_button_press_e
604    
605              dimregno = c | (z << bitpos);              dimregno = c | (z << bitpos);
606    
607                this->dimtype = dim;
608                this->dimzone = z;
609    
610              focus_line = dim;              focus_line = dim;
611              if (has_focus()) queue_draw();              if (has_focus()) queue_draw();
612              else grab_focus();              else grab_focus();
613              dimreg = region->pDimensionRegions[dimregno];              dimreg = region->pDimensionRegions[dimregno];
614              dimregion_selected();              dimregion_selected();
615    
616                if (event->button == 3) {
617                    printf("dimregion right click\n");
618                    popup_menu_inside_dimregion->popup(event->button, event->time);
619                }
620          }          }
621      }      }
622      return true;      return true;
# Line 434  bool DimRegionChooser::on_motion_notify_ Line 630  bool DimRegionChooser::on_motion_notify_
630      window->get_pointer(x, y, state);      window->get_pointer(x, y, state);
631    
632      if (resize.active) {      if (resize.active) {
633            int w = get_width();
634          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);
635    
636          if (k < resize.min) k = resize.min;          if (k < resize.min) k = resize.min;
# Line 442  bool DimRegionChooser::on_motion_notify_ Line 639  bool DimRegionChooser::on_motion_notify_
639          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
640    
641          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();  
   
642              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;
643              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;
644              int y = resize.dimension * h;              int y = resize.dimension * h;
645                int x1, x2;
646              if (resize.selected == resize.none) {              if (k > resize.pos) {
647                  if (resize.pos != resize.min && resize.pos != resize.max) {                  x1 = prevx;
648                      window->draw_line(white, prevx, y + 1, prevx, y + h - 2);                  x2 = x;
                 }  
649              } else {              } else {
650                  gc->set_foreground(red);                  x1 = x;
651                    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);  
                 }  
652              }              }
653              window->draw_line(black, x, y + 1, x, y + h - 2);              Gdk::Rectangle rect(x1, y + 1, x2 - x1 + 1, h - 2);
654    
655              resize.pos = k;              resize.pos = k;
656                update_after_resize();
657                get_window()->invalidate_rect(rect, false);
658          }          }
659      } else {      } else {
660          if (is_in_resize_zone(x, y)) {          if (is_in_resize_zone(x, y)) {
661              if (!cursor_is_resize) {              if (!cursor_is_resize) {
662                  Gdk::Cursor double_arrow(Gdk::SB_H_DOUBLE_ARROW);  #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
663                  window->set_cursor(double_arrow);                  window->set_cursor(Gdk::Cursor(Gdk::SB_H_DOUBLE_ARROW));
664    #else
665                    window->set_cursor(Gdk::Cursor::create(Gdk::SB_H_DOUBLE_ARROW));
666    #endif
667                  cursor_is_resize = true;                  cursor_is_resize = true;
668              }              }
669          } else if (cursor_is_resize) {          } else if (cursor_is_resize) {
# Line 496  bool DimRegionChooser::on_motion_notify_ Line 676  bool DimRegionChooser::on_motion_notify_
676    
677  bool DimRegionChooser::is_in_resize_zone(double x, double y)  bool DimRegionChooser::is_in_resize_zone(double x, double y)
678  {  {
679        int w = get_width();
680      if (region && y < nbDimensions * h && x >= label_width && x < w) {      if (region && y < nbDimensions * h && x >= label_width && x < w) {
681          int ydim = int(y / h);          int ydim = int(y / h);
682          int dim;          int dim;
# Line 523  bool DimRegionChooser::is_in_resize_zone Line 704  bool DimRegionChooser::is_in_resize_zone
704          if (region->pDimensionDefinitions[dim].split_type != gig::split_type_bit) {          if (region->pDimensionDefinitions[dim].split_type != gig::split_type_bit) {
705              int prev_limit = 0;              int prev_limit = 0;
706              for (int iZone = 0 ; iZone < nbZones - 1 ; iZone++) {              for (int iZone = 0 ; iZone < nbZones - 1 ; iZone++) {
707                  gig::DimensionRegion *d = region->pDimensionRegions[c + (iZone << bitpos)];                  gig::DimensionRegion* d = region->pDimensionRegions[c + (iZone << bitpos)];
708                  const int upperLimit =                  const int upperLimit =
709                      (customsplits) ?                      (customsplits) ?
710                          (d->DimensionUpperLimits[dim]) ?                          (d->DimensionUpperLimits[dim]) ?
# Line 544  bool DimRegionChooser::is_in_resize_zone Line 725  bool DimRegionChooser::is_in_resize_zone
725                          dr == iZone + 1 ? resize.right : resize.none;                          dr == iZone + 1 ? resize.right : resize.none;
726    
727                      iZone++;                      iZone++;
728                      gig::DimensionRegion *d = region->pDimensionRegions[c + (iZone << bitpos)];                      gig::DimensionRegion* d = region->pDimensionRegions[c + (iZone << bitpos)];
729    
730                      const int upperLimit =                      const int upperLimit =
731                          (customsplits) ?                          (customsplits) ?
# Line 615  bool DimRegionChooser::on_focus(Gtk::Dir Line 796  bool DimRegionChooser::on_focus(Gtk::Dir
796          // TODO: öka eller minska värde!          // TODO: öka eller minska värde!
797      }      }
798  }  }
799    
800    void DimRegionChooser::split_dimension_zone() {
801        printf("split_dimension_zone() type=%d, zone=%d\n", dimtype, dimzone);
802        try {
803            region->SplitDimensionZone(
804                region->pDimensionDefinitions[dimtype].dimension,
805                dimzone
806            );
807        } catch (RIFF::Exception e) {
808            Gtk::MessageDialog msg(e.Message, false, Gtk::MESSAGE_ERROR);
809            msg.run();
810        } catch (...) {
811            Glib::ustring txt = _("An unknown exception occurred!");
812            Gtk::MessageDialog msg(txt, false, Gtk::MESSAGE_ERROR);
813            msg.run();
814        }
815        refresh_all();
816    }
817    
818    void DimRegionChooser::delete_dimension_zone() {
819        printf("delete_dimension_zone() type=%d, zone=%d\n", dimtype, dimzone);
820        try {
821            region->DeleteDimensionZone(
822                region->pDimensionDefinitions[dimtype].dimension,
823                dimzone
824            );
825        } catch (RIFF::Exception e) {
826            Gtk::MessageDialog msg(e.Message, false, Gtk::MESSAGE_ERROR);
827            msg.run();
828        } catch (...) {
829            Glib::ustring txt = _("An unknown exception occurred!");
830            Gtk::MessageDialog msg(txt, false, Gtk::MESSAGE_ERROR);
831            msg.run();
832        }
833        refresh_all();
834    }

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

  ViewVC Help
Powered by ViewVC