/[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 2151 by persson, Sun Nov 21 12:38:41 2010 UTC revision 2556 by schoenebeck, Fri May 16 23:19:23 2014 UTC
# Line 1  Line 1 
1  /*  /*
2   * Copyright (C) 2006-2010 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 21  Line 21 
21  #include <cairomm/context.h>  #include <cairomm/context.h>
22  #include <gdkmm/cursor.h>  #include <gdkmm/cursor.h>
23  #include <gdkmm/general.h>  #include <gdkmm/general.h>
24    #include <glibmm/stringutils.h>
25    #include <gtkmm/stock.h>
26    #include <glibmm/ustring.h>
27    #include <gtkmm/messagedialog.h>
28    
29  #include "global.h"  #include "global.h"
30    
31  #include "global.h"  DimRegionChooser::DimRegionChooser() :
32        red("#8070ff"),
33  #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 10) || GTKMM_MAJOR_VERSION < 2      black("black"),
34        white("white")
 #define create_cairo_context()                                          \  
     gobj() ? Cairo::RefPtr<Cairo::Context>(                             \  
         new Cairo::Context(gdk_cairo_create(get_window()->gobj()))) :   \  
     Cairo::RefPtr<Cairo::Context>()  
   
 namespace Gdk {  
     namespace Cairo {  
         void set_source_color(const ::Cairo::RefPtr< ::Cairo::Context >& cr,  
                               const Gdk::Color& color);  
     }  
 }  
 #endif  
   
 DimRegionChooser::DimRegionChooser()  
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 65  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;
 #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 18) || GTKMM_MAJOR_VERSION < 2  
     set_flags(Gtk::CAN_FOCUS);  
 #else  
43      set_can_focus();      set_can_focus();
44  #endif  
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  bool DimRegionChooser::on_expose_event(GdkEventExpose* event)  #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
88    bool DimRegionChooser::on_expose_event(GdkEventExpose* e)
89    {
90        double clipx1 = e->area.x;
91        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    
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      int w = get_width();      int w = get_width();
     Glib::RefPtr<Gdk::Window> window = get_window();  
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);
     Cairo::RefPtr<Cairo::Context> cr = get_window()->create_cairo_context();  
114      cr->set_line_width(1);      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=_("keyswitching"); 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              const Gdk::Color fg = get_style()->get_fg(get_state());                  case gig::dimension_effect5depth:
171              Gdk::Cairo::set_source_color(cr, fg);                      dstr=_("effect5depth"); break;
172              cr->move_to(4, int(y + (h - text_h) / 2 + 0.5));                  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  #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 16) || GTKMM_MAJOR_VERSION < 2
196              pango_cairo_show_layout(cr->cobj(), layout->gobj());                      pango_cairo_show_layout(cr->cobj(), layout->gobj());
197  #else  #else
198              layout->show_in_cairo_context(cr);                      layout->show_in_cairo_context(cr);
199  #endif  #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              // draw top and bottom lines of dimension's zones                                               *this, "",
223              Gdk::Cairo::set_source_color(cr, black);                                               0, y, label_width, 20);
224              cr->move_to(label_width, y + 0.5);  #else
225              cr->line_to(w, y + 0.5);                      get_style_context()->render_focus(cr,
226              cr->move_to(w, y + h - 0.5);                                                        0, y, label_width, 20);
227              cr->line_to(label_width, y + h - 0.5);  #endif
228              cr->stroke();                  }
   
             // erase whole dimension's zones area  
             Gdk::Cairo::set_source_color(cr, white);  
             cr->rectangle(label_width + 1, y + 1, (w - label_width - 2), h - 2);  
             cr->fill();  
   
             int c = 0;  
             if (dimregno >= 0) {  
                 int mask = ~(((1 << region->pDimensionDefinitions[i].bits) - 1) << bitpos);  
                 c = dimregno & mask; // mask away this dimension  
             }  
             bool customsplits =  
                 ((region->pDimensionDefinitions[i].split_type == gig::split_type_normal &&  
                  region->pDimensionRegions[c]->DimensionUpperLimits[i]) ||  
                 (region->pDimensionDefinitions[i].dimension == gig::dimension_velocity &&  
                  region->pDimensionRegions[c]->VelocityUpperLimit));  
229    
230              // draw dimension's zone borders                  // draw top and bottom lines of dimension's zones
231              Gdk::Cairo::set_source_color(cr, black);                  Gdk::Cairo::set_source_rgba(cr, black);
232              if (customsplits) {                  cr->move_to(label_width, y + 0.5);
233                  cr->move_to(label_width + 0.5, y + 1);                  cr->line_to(w, y + 0.5);
234                  cr->line_to(label_width + 0.5, y + h - 1);                  cr->move_to(w, y + h - 0.5);
235                    cr->line_to(label_width, y + h - 0.5);
236                    cr->stroke();
237    
238                    // erase whole dimension's zones area
239                    Gdk::Cairo::set_source_rgba(cr, white);
240                    cr->rectangle(label_width + 1, y + 1,
241                                  (w - label_width - 2), h - 2);
242                    cr->fill();
243    
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                      cr->move_to(label_width + x + 0.5, y + 1);                  }
251                      cr->line_to(label_width + x + 0.5, y + h - 1);                  bool customsplits =
252                  }                      ((region->pDimensionDefinitions[i].split_type ==
253              } else {                        gig::split_type_normal &&
254                  for (int j = 0 ; j <= nbZones ; j++) {                        region->pDimensionRegions[c]->DimensionUpperLimits[i]) ||
255                      int x = int((w - label_width - 1) * j / double(nbZones) + 0.5);                       (region->pDimensionDefinitions[i].dimension ==
256                      cr->move_to(label_width + x + 0.5, y + 1);                        gig::dimension_velocity &&
257                      cr->line_to(label_width + x + 0.5, y + h - 1);                        region->pDimensionRegions[c]->VelocityUpperLimit));
258                  }  
259              }                  // draw dimension's zone borders
260              cr->stroke();                  Gdk::Cairo::set_source_rgba(cr, black);
   
             // draw fill for currently selected zone  
             if (dimregno >= 0) {  
                 Gdk::Cairo::set_source_color(cr, 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                            if (x >= clipx2) break;
274                            if (x < clipx1) continue;
275                            cr->move_to(x + 0.5, y + 1);
276                            cr->line_to(x + 0.5, y + h - 1);
277                        }
278                    } else {
279                        for (int j = 0 ; j <= nbZones ; j++) {
280                            int x = int((w - label_width - 1) * j /
281                                        double(nbZones) + 0.5) + label_width;
282                            if (x >= clipx2) break;
283                            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,                              cr->rectangle(label_width + x1 + 1, y + 1,
324                                            (x2 - x1) - 1, h - 2);                                            (x2 - x1) - 1, h - 2);
325                              cr->fill();                              cr->fill();
                             break;  
326                          }                          }
                         x1 = x2;  
327                      }                      }
328                  } else {  
329                      if (dr < nbZones) {                      // draw text showing the beginning of the dimension zone
330                          int x1 = int((w - label_width - 1) * dr / double(nbZones) + 0.5);                      // as numeric value to the user
331                          int x2 = int((w - label_width - 1) * (dr + 1) / double(nbZones) + 0.5);                      if (x1 >= 0) {
332                          cr->rectangle(label_width + x1 + 1, y + 1,                          Glib::RefPtr<Pango::Layout> layout = Pango::Layout::create(context);
333                                        (x2 - x1) - 1, h - 2);                          int v = roundf(float(x1 - label_width) / float(w - label_width) * 127.f);
334                          cr->fill();                          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 263  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 291  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    void DimRegionChooser::refresh_all() {
409        set_region(region);
410    }
411    
412  void DimRegionChooser::get_dimregions(const gig::Region* region, bool stereo,  void DimRegionChooser::get_dimregions(const gig::Region* region, bool stereo,
413                                        std::set<gig::DimensionRegion*>& dimregs) const                                        std::set<gig::DimensionRegion*>& dimregs) const
# Line 317  void DimRegionChooser::get_dimregions(co Line 431  void DimRegionChooser::get_dimregions(co
431      if (stereo_bit) dimregs.insert(region->pDimensionRegions[dimregno | stereo_bit]);      if (stereo_bit) dimregs.insert(region->pDimensionRegions[dimregno | stereo_bit]);
432  }  }
433    
434    void DimRegionChooser::update_after_resize()
 bool DimRegionChooser::on_button_release_event(GdkEventButton* event)  
435  {  {
436      if (resize.active) {      if (region->pDimensionDefinitions[resize.dimension].dimension == gig::dimension_velocity) {
         get_window()->pointer_ungrab(event->time);  
         resize.active = false;  
   
         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;  
492    
493          } else {              int bitpos = 0;
494              for (int i = 0 ; i < region->DimensionRegions ; ) {              int j;
495                for (j = 0 ; j < region->Dimensions ; j++) {
496                  if (region->pDimensionRegions[i]->DimensionUpperLimits[resize.dimension] == 0) {                  if (j != resize.dimension) {
497                      // the dimension didn't previously have custom                      int maxzones = 1 << region->pDimensionDefinitions[j].bits;
498                      // limits, so we have to set default limits for                      int dimj = (i >> bitpos) & (maxzones - 1);
499                      // all the dimension regions                      if (dimj + 1 < region->pDimensionDefinitions[j].zones) break;
                     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;  
   
                 int bitpos = 0;  
                 int j;  
                 for (j = 0 ; j < region->Dimensions ; j++) {  
                     if (j != resize.dimension) {  
                         int maxzones = 1 << region->pDimensionDefinitions[j].bits;  
                         int dimj = (i >> bitpos) & (maxzones - 1);  
                         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 412  bool DimRegionChooser::on_button_press_e Line 533  bool DimRegionChooser::on_button_press_e
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 450  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 472  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 499  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) {
             Cairo::RefPtr<Cairo::Context> cr = get_window()->create_cairo_context();  
             cr->set_line_width(1);  
   
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                      Gdk::Cairo::set_source_color(cr, white);                  x2 = x;
                     cr->move_to(prevx + 0.5, y + 1);  
                     cr->line_to(prevx + 0.5, y + h - 1);  
                     cr->stroke();  
                 }  
649              } else {              } else {
650                  Gdk::Color left;                  x1 = x;
651                  Gdk::Color right;                  x2 = prevx;
                 if (resize.selected == resize.left) {  
                     left = red;  
                     right = white;  
                 } else {  
                     left = white;  
                     right = red;  
                 }  
   
                 if (k > resize.pos) {  
                     int xx = resize.pos == resize.min ? 1 : 0;  
                     Gdk::Cairo::set_source_color(cr, left);  
                     cr->rectangle(prevx + xx, y + 1, x - prevx - xx, h - 2);  
                 } else {  
                     int xx = resize.pos == resize.max ? 0 : 1;  
                     Gdk::Cairo::set_source_color(cr, right);  
                     cr->rectangle(x, y + 1, prevx - x + xx, h - 2);  
                 }  
                 cr->fill();  
652              }              }
653              Gdk::Cairo::set_source_color(cr, black);              Gdk::Rectangle rect(x1, y + 1, x2 - x1 + 1, h - 2);
             cr->move_to(x + 0.5, y + 1);  
             cr->line_to(x + 0.5, y + h - 1);  
             cr->stroke();  
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 587  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 608  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 679  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.2151  
changed lines
  Added in v.2556

  ViewVC Help
Powered by ViewVC