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

Diff of /gigedit/trunk/src/gigedit/regionchooser.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 3131 by schoenebeck, Thu Apr 27 17:28:01 2017 UTC
# Line 1  Line 1 
1  /*  /*
2   * Copyright (C) 2006-2010 Andreas Persson   * Copyright (C) 2006-2015 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 20  Line 20 
20  #include "regionchooser.h"  #include "regionchooser.h"
21    
22  #include <algorithm>  #include <algorithm>
 #include <cmath>  
 #include <sstream>  
23    
24  #include <cairomm/context.h>  #include <cairomm/context.h>
25  #include <gdkmm/general.h>  #include <gdkmm/general.h>
26  #include <gdkmm/cursor.h>  #include <gdkmm/cursor.h>
27  #include <gtkmm/stock.h>  #include <gdkmm/pixbuf.h>
28  #include <gtkmm/spinbutton.h>  #include <gtkmm/spinbutton.h>
29  #include <gtkmm/dialog.h>  #include <gtkmm/dialog.h>
30    
31  #include "global.h"  #include "global.h"
32    #include "Settings.h"
33    #include "gfx/builtinpix.h"
34    
35  #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 10) || GTKMM_MAJOR_VERSION < 2  #define REGION_BLOCK_HEIGHT             30
36    #define KEYBOARD_HEIGHT                 40
37    
38  #define create_cairo_context()                                          \  struct RegionFeatures {
39      gobj() ? Cairo::RefPtr<Cairo::Context>(                             \      int sampleRefs;
40          new Cairo::Context(gdk_cairo_create(get_window()->gobj()))) :   \      int loops;
41      Cairo::RefPtr<Cairo::Context>()  
42        RegionFeatures() {
43  namespace Gdk {          sampleRefs = loops = 0;
44      namespace Cairo {      }
45          void set_source_color(const ::Cairo::RefPtr< ::Cairo::Context >& cr,  };
46                                const Gdk::Color& color) {  
47              gdk_cairo_set_source_color(cr->cobj(),  static RegionFeatures regionFeatures(gig::Region* rgn) {
48                                         const_cast<GdkColor*>(color.gobj()));      RegionFeatures f;
49          }      for (int i = 0; i < rgn->DimensionRegions; ++i) {
50            gig::DimensionRegion* dr = rgn->pDimensionRegions[i];
51            if (dr->pSample) f.sampleRefs++;
52            // the user doesn't care about loop if there is no valid sample reference
53            if (dr->pSample && dr->SampleLoops) f.loops++;
54      }      }
55        return f;
56  }  }
 #endif  
   
 #define REGION_BLOCK_HEIGHT             20  
 #define KEYBOARD_HEIGHT                 40  
57    
58  void SortedRegions::update(gig::Instrument* instrument) {  void SortedRegions::update(gig::Instrument* instrument) {
59      // Usually, the regions in a gig file are ordered after their key      // Usually, the regions in a gig file are ordered after their key
# Line 74  gig::Region* SortedRegions::first() { Line 76  gig::Region* SortedRegions::first() {
76  }  }
77    
78  gig::Region* SortedRegions::next() {  gig::Region* SortedRegions::next() {
79      region_iterator++;      ++region_iterator;
80      return region_iterator == regions.end() ? 0 : *region_iterator;      return region_iterator == regions.end() ? 0 : *region_iterator;
81  }  }
82    
83    
84    
85  RegionChooser::RegionChooser() :  RegionChooser::RegionChooser() :
86        activeKeyColor("red"),
87        blue("#4796ff"),
88        grey1("grey69"),
89        white("white"),
90        black("black"),
91      m_VirtKeybModeChoice(_("Virtual Keyboard Mode")),      m_VirtKeybModeChoice(_("Virtual Keyboard Mode")),
92      currentActiveKey(-1)      currentActiveKey(-1)
93  {  {
94      red = Gdk::Color("#8070ff");      set_size_request(500, KEYBOARD_HEIGHT + REGION_BLOCK_HEIGHT);
95      grey1 = Gdk::Color("#b0b0b0");  
96      activeKeyColor = Gdk::Color("#ff0000");      loadBuiltInPix();
     white = Gdk::Color("#ffffff");  
     black = Gdk::Color("#000000");  
97    
98      instrument = 0;      instrument = 0;
99      region = 0;      region = 0;
# Line 99  RegionChooser::RegionChooser() : Line 104  RegionChooser::RegionChooser() :
104    
105      // properties of the virtual keyboard      // properties of the virtual keyboard
106      {      {
107          const char* choices[] = { _("normal"), _("chord"), NULL };          const char* choices[] = { _("normal"), _("chord"), 0 };
108          static const virt_keyboard_mode_t values[] = {          static const virt_keyboard_mode_t values[] = {
109              VIRT_KEYBOARD_MODE_NORMAL,              VIRT_KEYBOARD_MODE_NORMAL,
110              VIRT_KEYBOARD_MODE_CHORD              VIRT_KEYBOARD_MODE_CHORD
# Line 119  RegionChooser::RegionChooser() : Line 124  RegionChooser::RegionChooser() :
124      m_VirtKeybPropsBox.pack_start(m_VirtKeybOffVelocityLabel, Gtk::PACK_SHRINK);      m_VirtKeybPropsBox.pack_start(m_VirtKeybOffVelocityLabel, Gtk::PACK_SHRINK);
125      m_VirtKeybPropsBox.set_spacing(10);      m_VirtKeybPropsBox.set_spacing(10);
126      m_VirtKeybPropsBox.show();      m_VirtKeybPropsBox.show();
127        for (int i = 0 ; i < 128 ; i++) key_pressed[i] = false;
128    
129      actionGroup = Gtk::ActionGroup::create();      actionGroup = Gtk::ActionGroup::create();
130      actionGroup->add(Gtk::Action::create("Properties",      actionGroup->add(Gtk::Action::create("Properties", _("_Properties")),
                                          Gtk::Stock::PROPERTIES),  
131                       sigc::mem_fun(*this,                       sigc::mem_fun(*this,
132                                     &RegionChooser::show_region_properties));                                     &RegionChooser::show_region_properties));
133      actionGroup->add(Gtk::Action::create("Remove", Gtk::Stock::REMOVE),      actionGroup->add(Gtk::Action::create("Remove", _("_Remove")),
134                       sigc::mem_fun(*this, &RegionChooser::delete_region));                       sigc::mem_fun(*this, &RegionChooser::delete_region));
135      actionGroup->add(Gtk::Action::create("Add", Gtk::Stock::ADD),      actionGroup->add(Gtk::Action::create("Add", _("_Add")),
136                       sigc::mem_fun(*this, &RegionChooser::add_region));                       sigc::mem_fun(*this, &RegionChooser::add_region));
137      actionGroup->add(Gtk::Action::create("Dimensions", _("Dimensions...")),      actionGroup->add(Gtk::Action::create("Dimensions", _("Dimensions...")),
138                       sigc::mem_fun(*this, &RegionChooser::manage_dimensions));                       sigc::mem_fun(*this, &RegionChooser::manage_dimensions));
# Line 172  RegionChooser::RegionChooser() : Line 177  RegionChooser::RegionChooser() :
177      keyboard_key_released_signal.connect(      keyboard_key_released_signal.connect(
178          sigc::mem_fun(*this, &RegionChooser::on_note_off_event)          sigc::mem_fun(*this, &RegionChooser::on_note_off_event)
179      );      );
180        set_tooltip_text(_("Right click here for adding new region. Use mouse pointer for moving (dragging) or resizing existing regions (by pointing at region's boundary). Right click on an existing region for more actions."));
181  }  }
182    
183  RegionChooser::~RegionChooser()  RegionChooser::~RegionChooser()
184  {  {
185  }  }
186    
187  template<class T> inline std::string ToString(T o) {  void RegionChooser::invalidate_key(int key) {
188      std::stringstream ss;      const int h = KEYBOARD_HEIGHT;
189      ss << o;      const int w = get_width() - 1;
190      return ss.str();      int x1 = key_to_x(key - 0.5, w);
191        int x2 = key_to_x(key + 1.5, w);
192    
193        Gdk::Rectangle rect(x1 + 1, h1 + 1, x2 - x1 - 1, h - 2);
194        get_window()->invalidate_rect(rect, false);
195  }  }
196    
197  void RegionChooser::on_note_on_event(int key, int velocity) {  void RegionChooser::on_note_on_event(int key, int velocity) {
198      draw_key(key, activeKeyColor);      key_pressed[key] = true;
199        invalidate_key(key);
200      m_VirtKeybVelocityLabel.set_text(ToString(velocity));      m_VirtKeybVelocityLabel.set_text(ToString(velocity));
201  }  }
202    
203  void RegionChooser::on_note_off_event(int key, int velocity) {  void RegionChooser::on_note_off_event(int key, int velocity) {
204      if (is_black_key(key)) {      key_pressed[key] = false;
205          draw_key(key, black);      invalidate_key(key);
     } else {  
         draw_key(key, key >= 21 && key <= 108 ? white : grey1);  
     }  
206      m_VirtKeybOffVelocityLabel.set_text(ToString(velocity));      m_VirtKeybOffVelocityLabel.set_text(ToString(velocity));
207  }  }
208    
209    
210  bool RegionChooser::on_expose_event(GdkEventExpose* event)  #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
211  {  bool RegionChooser::on_expose_event(GdkEventExpose* e) {
212      Glib::RefPtr<Gdk::Window> window = get_window();      double clipx1 = e->area.x;
213      if (window) {      double clipx2 = e->area.x + e->area.width;
214          Cairo::RefPtr<Cairo::Context> cr = window->create_cairo_context();      double clipy1 = e->area.y;
215          if (event) {      double clipy2 = e->area.y + e->area.height;
216              cr->rectangle(event->area.x, event->area.y,  
217                            event->area.width, event->area.height);      const Cairo::RefPtr<Cairo::Context>& cr =
218              cr->clip();          get_window()->create_cairo_context();
219          }  #if 0
220          const int h = KEYBOARD_HEIGHT;  }
221          const int w = get_width() - 1;  #endif
222          const int bh = int(h * 0.55);  #else
223    bool RegionChooser::on_draw(const Cairo::RefPtr<Cairo::Context>& cr) {
224          cr->save();      double clipx1, clipx2, clipy1, clipy2;
225          cr->set_line_width(1);      cr->get_clip_extents(clipx1, clipy1, clipx2, clipy2);
226    #endif
         const Gdk::Color bg = get_style()->get_bg(Gtk::STATE_NORMAL);  
         Gdk::Cairo::set_source_color(cr, bg);  
         cr->paint();  
227    
228          Gdk::Cairo::set_source_color(cr, black);      cr->save();
229          cr->rectangle(0.5, h1 + 0.5, w, h - 1);      cr->set_line_width(1);
         cr->stroke();  
230    
231          int x1 = int(w * 20.5 / 128.0 + 0.5);  #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
232          int x2 = int(w * 109.5 / 128.0 + 0.5);      const Gdk::Color bg = get_style()->get_bg(Gtk::STATE_NORMAL);
233    #else
234        const Gdk::RGBA bg = get_style_context()->get_background_color();
235    #endif
236        Gdk::Cairo::set_source_rgba(cr, bg);
237        cr->paint();
238    
239          Gdk::Cairo::set_source_color(cr, grey1);      if (clipy2 > h1) {
240          cr->rectangle(1, h1 + 1, x1 - 1, h - 2);          draw_keyboard(cr, clipx1, clipx2);
241          cr->fill();      }
242    
243          Gdk::Cairo::set_source_color(cr, white);      if (clipy1 < h1 && instrument) {
244          cr->rectangle(x1 + 1, h1 + 1, x2 - x1 - 1, h - 2);          draw_regions(cr, clipx1, clipx2);
245          cr->fill();      }
246    
247          Gdk::Cairo::set_source_color(cr, grey1);      cr->restore();
         cr->rectangle(x2 + 1, h1 + 1, w - x2 - 1, h - 2);  
         cr->fill();  
248    
249          Gdk::Cairo::set_source_color(cr, black);      return true;
250          for (int i = 0 ; i < 128 ; i++) {  }
             int note = (i + 3) % 12;  
             int x = int(w * i / 128.0 + 0.5);  
   
             if (note == 1 || note == 4 || note == 6 ||  
                 note == 9 || note == 11) {  
                 int x2 = int(w * (i + 0.5) / 128.0 + 0.5);  
                 cr->move_to(x2 + 0.5, h1 + bh + 0.5);  
                 cr->line_to(x2 + 0.5, h1 + h - 1);  
                 cr->stroke();  
251    
252                  int x3 = int(w * (i + 1) / 128.0 + 0.5);  void RegionChooser::draw_keyboard(const Cairo::RefPtr<Cairo::Context>& cr,
253                  cr->rectangle(x, h1 + 1, x3 - x + 1, bh);                                    int clip_low, int clip_high) {
254                  cr->fill();      const int h = KEYBOARD_HEIGHT;
255              } else if (note == 3 || note == 8) {      const int w = get_width() - 1;
256                  cr->move_to(x + 0.5, h1 + 1);      const int bh = int(h * 0.55);
                 cr->line_to(x + 0.5, h1 + h - 1);  
                 cr->stroke();  
257    
258                  if (note == 3) draw_digit(i);      Gdk::Cairo::set_source_rgba(cr, black);
259              }      cr->rectangle(0.5, h1 + 0.5, w, h - 1);
260        cr->stroke();
261    
262        int x1 = key_to_x(20.5, w);
263        Gdk::Cairo::set_source_rgba(cr, grey1);
264        cr->rectangle(1, h1 + 1, x1 - 1, h - 2);
265        cr->fill();
266    
267        int x2 = key_to_x(109.5, w);
268        Gdk::Cairo::set_source_rgba(cr, white);
269        cr->rectangle(x1 + 1, h1 + 1, x2 - x1 - 1, h - 2);
270        cr->fill();
271    
272        Gdk::Cairo::set_source_rgba(cr, grey1);
273        cr->rectangle(x2 + 1, h1 + 1, w - x2 - 1, h - 2);
274        cr->fill();
275    
276        Gdk::Cairo::set_source_rgba(cr, black);
277    
278        int clipkey1 = std::max(0, x_to_key_right(clip_low - 1, w));
279        int clipkey2 = std::min(x_to_key_right(clip_high - 1, w) + 1, 128);
280    
281        for (int i = clipkey1 ; i < clipkey2 ; i++) {
282            int note = (i + 3) % 12;
283            int x = key_to_x(i, w);
284    
285            if (note == 1 || note == 4 || note == 6 ||
286                note == 9 || note == 11) {
287                // black key: short line in the middle, with a rectangle
288                // on top
289                int x2 = key_to_x(i + 0.5, w);
290                cr->move_to(x2 + 0.5, h1 + bh + 0.5);
291                cr->line_to(x2 + 0.5, h1 + h - 1);
292                cr->stroke();
293    
294                int x3 = key_to_x(i + 1, w);
295                cr->rectangle(x, h1 + 1, x3 - x + 1, bh);
296                cr->fill();
297            } else if (note == 3 || note == 8) {
298                // C or F: long line to the left
299                cr->move_to(x + 0.5, h1 + 1);
300                cr->line_to(x + 0.5, h1 + h - 1);
301                cr->stroke();
302          }          }
303    
304          if (instrument) {          if (key_pressed[i]) draw_key(cr, i);
             int i = 0;  
             gig::Region* next_region;  
             int x3 = -1;  
             for (gig::Region* r = regions.first() ; r ; r = next_region) {  
   
                 if (x3 < 0) x3 = int(w * (r->KeyRange.low) / 128.0 + 0.5);  
                 next_region = regions.next();  
                 if (!next_region ||  
                     r->KeyRange.high + 1 != next_region->KeyRange.low) {  
                     int x2 = int(w * (r->KeyRange.high + 1) / 128.0 + 0.5);  
                     cr->move_to(x3, 0.5);  
                     cr->line_to(x2 + 0.5, 0.5);  
                     cr->line_to(x2 + 0.5, h1 - 0.5);  
                     cr->line_to(x3, h1 - 0.5);  
                     cr->stroke();  
   
                     Gdk::Cairo::set_source_color(cr, white);  
                     cr->rectangle(x3 + 1, 1, x2 - x3 - 1, h1 - 2);  
                     cr->fill();  
                     Gdk::Cairo::set_source_color(cr, black);  
305    
306                      x3 = -1;          if (note == 3) draw_digit(cr, i);
307                  }      }
308                  i++;  }
             }  
309    
310              for (gig::Region* r = regions.first() ; r ; r = regions.next()) {  
311                  int x = int(w * (r->KeyRange.low) / 128.0 + 0.5);  void RegionChooser::draw_regions(const Cairo::RefPtr<Cairo::Context>& cr,
312                  cr->move_to(x + 0.5, 1);                                   int clip_low, int clip_high) {
313                  cr->line_to(x + 0.5, h1 - 1);      const int w = get_width() - 1;
314    
315        Gdk::Cairo::set_source_rgba(cr, black);
316        gig::Region* next_region;
317        int x3 = -1;
318        for (gig::Region* r = regions.first() ; r ; r = next_region) {
319            next_region = regions.next();
320    
321            if (x3 < 0) {
322                x3 = key_to_x(r->KeyRange.low, w);
323                if (x3 >= clip_high) break;
324            }
325            if (!next_region ||
326                r->KeyRange.high + 1 != next_region->KeyRange.low ||
327                r == region || next_region == region) {
328    
329                int x2 = key_to_x(r->KeyRange.high + 1, w);
330                if (x2 >= clip_low) {
331                    cr->move_to(x3, 0.5);
332                    cr->line_to(x2 + 0.5, 0.5);
333                    cr->line_to(x2 + 0.5, h1 - 0.5);
334                    cr->line_to(x3, h1 - 0.5);
335                  cr->stroke();                  cr->stroke();
             }  
336    
337              if (region) {                  Gdk::Cairo::set_source_rgba(cr, region == r ? blue : white);
338                  int x1 = int(w * (region->KeyRange.low) / 128.0 + 0.5);                  cr->rectangle(x3 + 1, 1, x2 - x3 - 1, h1 - 2);
                 int x2 = int(w * (region->KeyRange.high + 1) / 128.0 + 0.5);  
                 Gdk::Cairo::set_source_color(cr, red);  
                 cr->rectangle(x1 + 1, 1, x2 - x1 - 1, h1 - 2);  
339                  cr->fill();                  cr->fill();
340                    Gdk::Cairo::set_source_rgba(cr, black);
341              }              }
342                x3 = -1;
343          }          }
344        }
345    
346        for (gig::Region* r = regions.first() ; r ; r = regions.next()) {
347            int x = key_to_x(r->KeyRange.low, w);
348            int x2 = key_to_x(r->KeyRange.high + 1, w);
349    
350          cr->restore();          RegionFeatures features = regionFeatures(r);
351    
352            const bool bShowLoopSymbol = features.loops > 0;
353            const bool bShowSampleRefSymbol = features.sampleRefs < r->DimensionRegions;
354            if (bShowLoopSymbol || bShowSampleRefSymbol) {
355                const int margin = 2;
356                const int wRgn = x2 - x;
357                //printf("x=%d x2=%d wRgn=%d\n", x, x2, wRgn);
358    
359                cr->save();
360                cr->set_line_width(1);
361                cr->rectangle(x, 1, wRgn, h1 - 1);
362                cr->clip();
363                if (bShowSampleRefSymbol) {
364                    const int wPic = 8;
365                    const int hPic = 8;
366                    Gdk::Cairo::set_source_pixbuf(
367                        cr, (features.sampleRefs) ? yellowDot : redDot,
368                        x + (wRgn-wPic)/2.f,
369                        (bShowLoopSymbol) ? margin : (h1-hPic)/2.f
370                    );
371                    cr->paint();
372                }
373                if (bShowLoopSymbol) {
374                    const int wPic = 12;
375                    const int hPic = 14;
376                    Gdk::Cairo::set_source_pixbuf(
377                        cr, (features.loops == r->DimensionRegions) ? blackLoop : grayLoop,
378                        x + (wRgn-wPic)/2.f,
379                        (bShowSampleRefSymbol) ? h1 - hPic - margin : (h1-hPic)/2.f
380                    );
381                    cr->paint();
382                }
383                cr->restore();
384            }
385      }      }
386    
387      return true;      for (gig::Region* r = regions.first() ; r ; r = regions.next()) {
388  }          int x = key_to_x(r->KeyRange.low, w);
389    
390            if (x < clip_low) continue;
391            if (x >= clip_high) break;
392    
393  void RegionChooser::on_size_request(GtkRequisition* requisition)          cr->move_to(x + 0.5, 1);
394  {          cr->line_to(x + 0.5, h1 - 1);
395      *requisition = GtkRequisition();          cr->stroke();
396      requisition->height = KEYBOARD_HEIGHT + REGION_BLOCK_HEIGHT;      }
397      requisition->width = 500;  
398        // if there is no region yet, show the user some hint text that he may
399        // right click on this area to create a new region
400        if (!regions.first()) {
401            Glib::RefPtr<Pango::Context> context = get_pango_context();
402            Glib::RefPtr<Pango::Layout> layout = Pango::Layout::create(context);
403            layout->set_alignment(Pango::ALIGN_CENTER);
404            layout->set_text(Glib::ustring("*** ") + _("Right click here to create a region.") + " ***");
405            layout->set_width(get_width() * Pango::SCALE);
406            //layout->set_height(get_height() * Pango::SCALE);
407            layout->set_spacing(10);
408            Gdk::Cairo::set_source_rgba(cr, blue);
409            // get the text dimensions
410            int text_width, text_height;
411            layout->get_pixel_size(text_width, text_height);
412            cr->move_to(0, (REGION_BLOCK_HEIGHT - text_height) / 2);
413    #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 16) || GTKMM_MAJOR_VERSION < 2
414            pango_cairo_show_layout(cr->cobj(), layout->gobj());
415    #else
416            layout->show_in_cairo_context(cr);
417    #endif
418        }
419  }  }
420    
421  bool RegionChooser::is_black_key(int key) {  bool RegionChooser::is_black_key(int key) {
# Line 325  bool RegionChooser::is_black_key(int key Line 423  bool RegionChooser::is_black_key(int key
423      return note == 1 || note == 4 || note == 6 || note == 9 || note == 11;      return note == 1 || note == 4 || note == 6 || note == 9 || note == 11;
424  }  }
425    
426  void RegionChooser::draw_digit(int key) {  void RegionChooser::draw_digit(const Cairo::RefPtr<Cairo::Context>& cr,
427                                   int key) {
428      const int h = KEYBOARD_HEIGHT;      const int h = KEYBOARD_HEIGHT;
429      const int w = get_width() - 1;      const int w = get_width() - 1;
430      Glib::RefPtr<Pango::Layout> layout = Pango::Layout::create(get_pango_context());      Glib::RefPtr<Pango::Layout> layout =
431            Pango::Layout::create(get_pango_context());
432      char buf[30];      char buf[30];
433      sprintf(buf, "<span size=\"8000\">%d</span>", key / 12 - 1);      sprintf(buf, "<span size=\"8000\">%d</span>", key / 12 - 1);
434      layout->set_markup(buf);      layout->set_markup(buf);
# Line 336  void RegionChooser::draw_digit(int key) Line 436  void RegionChooser::draw_digit(int key)
436      double text_w = double(rectangle.get_width()) / Pango::SCALE;      double text_w = double(rectangle.get_width()) / Pango::SCALE;
437      double text_h = double(rectangle.get_height()) / Pango::SCALE;      double text_h = double(rectangle.get_height()) / Pango::SCALE;
438      double x = w * (key + 0.75) / 128.0;      double x = w * (key + 0.75) / 128.0;
439      Cairo::RefPtr<Cairo::Context> cr = get_window()->create_cairo_context();      Gdk::Cairo::set_source_rgba(cr, black);
     Gdk::Cairo::set_source_color(cr, black);  
440      cr->move_to(int(x - text_w / 2 + 1), int(h1 + h - text_h + 0.5));      cr->move_to(int(x - text_w / 2 + 1), int(h1 + h - text_h + 0.5));
441  #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
442      pango_cairo_show_layout(cr->cobj(), layout->gobj());      pango_cairo_show_layout(cr->cobj(), layout->gobj());
# Line 346  void RegionChooser::draw_digit(int key) Line 445  void RegionChooser::draw_digit(int key)
445  #endif  #endif
446  }  }
447    
448  void RegionChooser::draw_key(int key, const Gdk::Color& color)  void RegionChooser::draw_key(const Cairo::RefPtr<Cairo::Context>& cr,
449  {                               int key) {
450      const int h = KEYBOARD_HEIGHT;      const int h = KEYBOARD_HEIGHT;
451      const int w = get_width() - 1;      const int w = get_width() - 1;
452      const int bh = int(h * 0.55);      const int bh = int(h * 0.55);
453    
454      Cairo::RefPtr<Cairo::Context> cr = get_window()->create_cairo_context();      Gdk::Cairo::set_source_rgba(cr, activeKeyColor);
     Gdk::Cairo::set_source_color(cr, color);  
455    
456      int note = (key + 3) % 12;      int note = (key + 3) % 12;
457      int x = int(w * key / 128.0 + 0.5) + 1;      int x = key_to_x(key, w) + 1;
458      int x2 = int(w * (key + 1.5) / 128.0 + 0.5);      int x2 = key_to_x(key + 1.5, w);
459      int x3 = int(w * (key + 1) / 128.0 + 0.5);      int x3 = key_to_x(key + 1, w);
460      int x4 = int(w * (key - 0.5) / 128.0 + 0.5);      int x4 = key_to_x(key - 0.5, w);
461      int w1 = x3 - x;      int w1 = x3 - x;
462      switch (note) {      switch (note) {
463      case 0: case 5: case 10:      case 0: case 5: case 10:
# Line 379  void RegionChooser::draw_key(int key, co Line 477  void RegionChooser::draw_key(int key, co
477          cr->fill();          cr->fill();
478          cr->rectangle(x, h1 + bh + 1, x2 - x, h - bh - 2);          cr->rectangle(x, h1 + bh + 1, x2 - x, h - bh - 2);
479          cr->fill();          cr->fill();
         if (note == 3) draw_digit(key);  
480          break;          break;
481      default:      default:
482          cr->rectangle(x, h1 + 1, w1, bh - 1);          cr->rectangle(x, h1 + 1, w1, bh - 1);
483          cr->fill();          cr->fill();
484          break;          break;
485      }      }
486        Gdk::Cairo::set_source_rgba(cr, black);
487  }  }
488    
489  void RegionChooser::set_instrument(gig::Instrument* instrument)  void RegionChooser::set_instrument(gig::Instrument* instrument)
# Line 400  void RegionChooser::set_instrument(gig:: Line 498  void RegionChooser::set_instrument(gig::
498    
499  bool RegionChooser::on_button_release_event(GdkEventButton* event)  bool RegionChooser::on_button_release_event(GdkEventButton* event)
500  {  {
501      const int k = int(event->x / (get_width() - 1) * 128.0);      const int k = x_to_key(event->x, get_width() - 1);
502    
503      // handle-note off on virtual keyboard      // handle-note off on virtual keyboard
504      if (event->type == GDK_BUTTON_RELEASE) {      if (event->type == GDK_BUTTON_RELEASE) {
# Line 423  bool RegionChooser::on_button_release_ev Line 521  bool RegionChooser::on_button_release_ev
521      }      }
522    
523      if (resize.active) {      if (resize.active) {
524    #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
525          get_window()->pointer_ungrab(event->time);          get_window()->pointer_ungrab(event->time);
526    #else
527            Glib::wrap(event->device, true)->ungrab(event->time);
528    #endif
529          resize.active = false;          resize.active = false;
530    
         if (resize.mode == resize.moving_high_limit) {  
             if (resize.region->KeyRange.high != resize.pos - 1) {  
                 instrument_struct_to_be_changed_signal.emit(instrument);  
                 resize.region->SetKeyRange(  
                     resize.region->KeyRange.low, // low  
                     resize.pos - 1 // high  
                 );  
                 regions.update(instrument);  
                 instrument_changed.emit();  
                 instrument_struct_changed_signal.emit(instrument);  
             }  
         } else if (resize.mode == resize.moving_low_limit) {  
             if (resize.region->KeyRange.low != resize.pos) {  
                 instrument_struct_to_be_changed_signal.emit(instrument);  
                 resize.region->SetKeyRange(  
                     resize.pos, // low  
                     resize.region->KeyRange.high // high  
                 );  
                 regions.update(instrument);  
                 instrument_changed.emit();  
                 instrument_struct_changed_signal.emit(instrument);  
             }  
         }  
   
531          if (!is_in_resize_zone(event->x, event->y) && cursor_is_resize) {          if (!is_in_resize_zone(event->x, event->y) && cursor_is_resize) {
532              get_window()->set_cursor();              get_window()->set_cursor();
533              cursor_is_resize = false;              cursor_is_resize = false;
534          }          }
535      } else if (move.active) {      } else if (move.active) {
536    #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
537          get_window()->pointer_ungrab(event->time);          get_window()->pointer_ungrab(event->time);
538    #else
539            Glib::wrap(event->device, true)->ungrab(event->time);
540    #endif
541          move.active = false;          move.active = false;
542    
543          if (move.pos) {          if (is_in_resize_zone(event->x, event->y)) {
544    #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
545                get_window()->set_cursor(Gdk::Cursor(Gdk::SB_H_DOUBLE_ARROW));
546    #else
547                get_window()->set_cursor(Gdk::Cursor::create(Gdk::SB_H_DOUBLE_ARROW));
548    #endif
549                cursor_is_resize = true;
550            }
551        }
552        return true;
553    }
554    
555    void RegionChooser::update_after_resize()
556    {
557        if (resize.mode == resize.moving_high_limit) {
558            if (resize.region->KeyRange.high != resize.pos - 1) {
559              instrument_struct_to_be_changed_signal.emit(instrument);              instrument_struct_to_be_changed_signal.emit(instrument);
560              region->SetKeyRange(              resize.region->SetKeyRange(resize.region->KeyRange.low,
561                  region->KeyRange.low  + move.pos,                                         resize.pos - 1);
                 region->KeyRange.high + move.pos  
             );  
562              regions.update(instrument);              regions.update(instrument);
563              instrument_changed.emit();              instrument_changed.emit();
564              instrument_struct_changed_signal.emit(instrument);              instrument_struct_changed_signal.emit(instrument);
565          }          }
566        } else if (resize.mode == resize.moving_low_limit) {
567            if (resize.region->KeyRange.low != resize.pos) {
568                instrument_struct_to_be_changed_signal.emit(instrument);
569                resize.region->SetKeyRange(resize.pos,
570                                           resize.region->KeyRange.high);
571                regions.update(instrument);
572                instrument_changed.emit();
573                instrument_struct_changed_signal.emit(instrument);
574            }
575        }
576    }
577    
578          if (is_in_resize_zone(event->x, event->y)) {  void RegionChooser::update_after_move(int pos)
579              get_window()->set_cursor(Gdk::Cursor(Gdk::SB_H_DOUBLE_ARROW));  {
580              cursor_is_resize = true;      instrument_struct_to_be_changed_signal.emit(instrument);
581        const int range = region->KeyRange.high - region->KeyRange.low;
582        const int diff  = pos - int(region->KeyRange.low);
583        region->SetKeyRange(pos, pos + range);
584        if (Settings::singleton()->moveRootNoteWithRegionMoved) {
585            for (int i = 0; i < 256; ++i) {
586                gig::DimensionRegion* dimrgn = region->pDimensionRegions[i];
587                if (!dimrgn || !dimrgn->pSample || !dimrgn->PitchTrack) continue;
588                dimrgn->UnityNote += diff;
589          }          }
590      }      }
591      return true;      regions.update(instrument);
592        instrument_changed.emit();
593        instrument_struct_changed_signal.emit(instrument);
594  }  }
595    
596  bool RegionChooser::on_button_press_event(GdkEventButton* event)  bool RegionChooser::on_button_press_event(GdkEventButton* event)
597  {  {
598      if (!instrument) return true;      if (!instrument) return true;
599    
600      const int k = int(event->x / (get_width() - 1) * 128.0);      const int w = get_width() - 1;
601        const int k = x_to_key(event->x, w);
602    
603      if (event->type == GDK_BUTTON_PRESS) {      if (event->type == GDK_BUTTON_PRESS) {
604          if (event->y >= REGION_BLOCK_HEIGHT) {          if (event->y >= REGION_BLOCK_HEIGHT) {
# Line 492  bool RegionChooser::on_button_press_even Line 609  bool RegionChooser::on_button_press_even
609          }          }
610      }      }
611    
612        // left mouse button double click
613        if (event->type == GDK_2BUTTON_PRESS && event->button == 1) {
614            if (event->y < REGION_BLOCK_HEIGHT) {
615                // show dimension manager dialog for this region
616                manage_dimensions();
617            }
618        }
619    
620      if (event->y >= REGION_BLOCK_HEIGHT) return true;      if (event->y >= REGION_BLOCK_HEIGHT) return true;
621      if (event->type == GDK_BUTTON_PRESS && event->button == 3) {      if (event->type == GDK_BUTTON_PRESS && event->button == 3) {
622          gig::Region* r = get_region(k);          gig::Region* r = get_region(k);
# Line 507  bool RegionChooser::on_button_press_even Line 632  bool RegionChooser::on_button_press_even
632          }          }
633      } else {      } else {
634          if (is_in_resize_zone(event->x, event->y)) {          if (is_in_resize_zone(event->x, event->y)) {
635    #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
636              get_window()->pointer_grab(false,              get_window()->pointer_grab(false,
637                                         Gdk::BUTTON_RELEASE_MASK |                                         Gdk::BUTTON_RELEASE_MASK |
638                                         Gdk::POINTER_MOTION_MASK |                                         Gdk::POINTER_MOTION_MASK |
639                                         Gdk::POINTER_MOTION_HINT_MASK,                                         Gdk::POINTER_MOTION_HINT_MASK,
640                                         Gdk::Cursor(Gdk::SB_H_DOUBLE_ARROW), event->time);                                         Gdk::Cursor(Gdk::SB_H_DOUBLE_ARROW),
641                                           event->time);
642    #else
643                Glib::wrap(event->device, true)->grab(get_window(),
644                                                      Gdk::OWNERSHIP_NONE,
645                                                      false,
646                                                      Gdk::BUTTON_RELEASE_MASK |
647                                                      Gdk::POINTER_MOTION_MASK |
648                                                      Gdk::POINTER_MOTION_HINT_MASK,
649                                                      Gdk::Cursor::create(Gdk::SB_H_DOUBLE_ARROW),
650                                                      event->time);
651    #endif
652              resize.active = true;              resize.active = true;
653          } else {          } else {
654              gig::Region* r = get_region(k);              gig::Region* r = get_region(k);
# Line 521  bool RegionChooser::on_button_press_even Line 658  bool RegionChooser::on_button_press_even
658                  region_selected();                  region_selected();
659                  dimensionManager.set_region(region);                  dimensionManager.set_region(region);
660    
661    #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
662                  get_window()->pointer_grab(false,                  get_window()->pointer_grab(false,
663                                             Gdk::BUTTON_RELEASE_MASK |                                             Gdk::BUTTON_RELEASE_MASK |
664                                             Gdk::POINTER_MOTION_MASK |                                             Gdk::POINTER_MOTION_MASK |
665                                             Gdk::POINTER_MOTION_HINT_MASK,                                             Gdk::POINTER_MOTION_HINT_MASK,
666                                             Gdk::Cursor(Gdk::FLEUR), event->time);                                             Gdk::Cursor(Gdk::FLEUR),
667                                               event->time);
668    #else
669                    Glib::wrap(event->device, true)->grab(get_window(),
670                                                          Gdk::OWNERSHIP_NONE,
671                                                          false,
672                                                          Gdk::BUTTON_RELEASE_MASK |
673                                                          Gdk::POINTER_MOTION_MASK |
674                                                          Gdk::POINTER_MOTION_HINT_MASK,
675                                                          Gdk::Cursor::create(Gdk::FLEUR),
676                                                          event->time);
677    #endif
678                  move.active = true;                  move.active = true;
679                  move.from_x = event->x;                  move.offset = event->x - key_to_x(region->KeyRange.low, w);
                 move.pos = 0;  
680              }              }
681          }          }
682      }      }
# Line 537  bool RegionChooser::on_button_press_even Line 685  bool RegionChooser::on_button_press_even
685    
686  gig::Region* RegionChooser::get_region(int key)  gig::Region* RegionChooser::get_region(int key)
687  {  {
688      gig::Region* prev_region = 0;      for (gig::Region* r = regions.first() ; r ; r = regions.next()) {
     gig::Region* next_region;  
     for (gig::Region* r = regions.first() ; r ; r = next_region) {  
         next_region = regions.next();  
   
689          if (key < r->KeyRange.low) return 0;          if (key < r->KeyRange.low) return 0;
690          if (key <= r->KeyRange.high) {          if (key <= r->KeyRange.high) return r;
             move.touch_left = prev_region && prev_region->KeyRange.high + 1 == r->KeyRange.low;  
             move.touch_right = next_region && r->KeyRange.high + 1 == next_region->KeyRange.low;  
             return r;  
         }  
         prev_region = r;  
691      }      }
692      return 0;      return 0;
693  }  }
694    
695    void RegionChooser::set_region(gig::Region* region) {
696        this->region = region;
697        queue_draw();
698        region_selected();
699        dimensionManager.set_region(region);
700    }
701    
702    void RegionChooser::select_next_region() {
703        if (!instrument) return;
704        if (!region) {
705            for (int i = 0; i < 128; ++i) {
706                ::gig::Region* rgn = instrument->GetRegion(i);
707                if (rgn) {
708                    set_region(rgn);
709                    return;
710                }
711            }
712        } else {
713            bool currentFound = false;
714            for (int i = 0; i < 128; ++i) {
715                ::gig::Region* rgn = instrument->GetRegion(i);
716                if (!rgn) continue;
717                if (currentFound) {
718                    if (rgn != region) {
719                        set_region(rgn);
720                        return;
721                    }
722                } else {
723                    if (rgn == region) currentFound = true;
724                }
725            }
726        }
727    }
728    
729    void RegionChooser::select_prev_region() {
730        if (!instrument) return;
731        if (!region) {
732            for (int i = 0; i < 128; ++i) {
733                ::gig::Region* rgn = instrument->GetRegion(i);
734                if (rgn) {
735                    set_region(rgn);
736                    return;
737                }
738            }
739        } else {
740            bool currentFound = false;
741            for (int i = 127; i >= 0; --i) {
742                ::gig::Region* rgn = instrument->GetRegion(i);
743                if (!rgn) continue;
744                if (currentFound) {
745                    if (rgn != region) {
746                        set_region(rgn);
747                        return;
748                    }
749                } else {
750                    if (rgn == region) currentFound = true;
751                }
752            }
753        }
754    }
755    
756  void RegionChooser::motion_resize_region(int x, int y)  void RegionChooser::motion_resize_region(int x, int y)
757  {  {
758      const int w = get_width() - 1;      const int w = get_width() - 1;
# Line 563  void RegionChooser::motion_resize_region Line 763  void RegionChooser::motion_resize_region
763      else if (k > resize.max) k = resize.max;      else if (k > resize.max) k = resize.max;
764    
765      if (k != resize.pos) {      if (k != resize.pos) {
         Cairo::RefPtr<Cairo::Context> cr = get_window()->create_cairo_context();  
         cr->set_line_width(1);  
   
766          if (resize.mode == resize.undecided) {          if (resize.mode == resize.undecided) {
767              if (k < resize.pos) {              if (k < resize.pos) {
768                  // edit high limit of prev_region                  // edit high limit of prev_region
# Line 578  void RegionChooser::motion_resize_region Line 775  void RegionChooser::motion_resize_region
775                  resize.mode = resize.moving_low_limit;                  resize.mode = resize.moving_low_limit;
776              }              }
777          }          }
778          const Gdk::Color white =          resize.pos = k;
             region == resize.region ? red : get_style()->get_white();  
         const Gdk::Color bg = get_style()->get_bg(Gtk::STATE_NORMAL);  
   
         int prevx = int(w * resize.pos / 128.0 + 0.5);  
         x = int(w * k / 128.0 + 0.5);  
779    
780            int x1, x2;
781          if (resize.mode == resize.moving_high_limit) {          if (resize.mode == resize.moving_high_limit) {
782              if (k > resize.pos) {              if (resize.region->KeyRange.high < resize.pos - 1) {
783                  Gdk::Cairo::set_source_color(cr, white);                  x1 = resize.region->KeyRange.high;
784                  cr->rectangle(prevx, 1, x - prevx, h1 - 2);                  x2 = resize.pos - 1;
                 cr->fill();  
   
                 Gdk::Cairo::set_source_color(cr, black);  
                 cr->move_to(prevx, 0.5);  
                 cr->line_to(x + 1, 0.5);  
                 cr->move_to(prevx, h1 - 0.5);  
                 cr->line_to(x + 1, h1 - 0.5);  
                 cr->stroke();  
785              } else {              } else {
786                  int xx = (resize.pos == resize.max &&                  x1 = resize.pos - 1;
787                            resize.max != 128) ? 1 : 0;                  x2 = resize.region->KeyRange.high;
                 Gdk::Cairo::set_source_color(cr, bg);  
                 cr->rectangle(x + 1, 0, prevx - x - xx, h1);  
                 cr->fill();  
788              }              }
789          } else {          } else {
790              if (k < resize.pos) {              if (resize.region->KeyRange.low < resize.pos) {
791                  Gdk::Cairo::set_source_color(cr, white);                  x1 = resize.region->KeyRange.low;
792                  cr->rectangle(x + 1, 1, prevx - x, h1 - 2);                  x2 = resize.pos;
                 cr->fill();  
   
                 Gdk::Cairo::set_source_color(cr, black);  
                 cr->move_to(x, 0.5);  
                 cr->line_to(prevx, 0.5);  
                 cr->move_to(x, h1 - 0.5);  
                 cr->line_to(prevx, h1 - 0.5);  
                 cr->stroke();  
793              } else {              } else {
794                  int xx = (resize.pos == resize.min &&                  x1 = resize.pos;
795                            resize.min != 0) ? 1 : 0;                  x2 = resize.region->KeyRange.low;
                 Gdk::Cairo::set_source_color(cr, bg);  
                 cr->rectangle(prevx + xx, 0, x - prevx - xx, h1);  
                 cr->fill();  
796              }              }
797          }          }
798          Gdk::Cairo::set_source_color(cr, black);          x1 = key_to_x(x1, w);
799          cr->move_to(x + 0.5, 1);          x2 = key_to_x(x2 + 1, w) + 1;
800          cr->line_to(x + 0.5, h1 - 1);          Gdk::Rectangle rect(x1, 0, x2 - x1, h1);
801          cr->stroke();  
802          resize.pos = k;          update_after_resize();
803    
804            //get_window()->invalidate_rect(rect, false);
805            get_window()->invalidate(false); // repaint entire region, otherwise it would create visual artifacts
806      }      }
807  }  }
808    
809  void RegionChooser::motion_move_region(int x, int y)  void RegionChooser::motion_move_region(int x, int y)
810  {  {
811      const int w = get_width() - 1;      const int w = get_width() - 1;
     Cairo::RefPtr<Cairo::Context> cr = get_window()->create_cairo_context();  
     cr->set_line_width(1);  
812    
813      int k = int(double(x - move.from_x) / w * 128.0 + 0.5);      int l = int(double(x - move.offset) / w * 128.0 + 0.5);
814      if (k == move.pos) return;  
815      int new_k;      if (l == region->KeyRange.low) return;
816      bool new_touch_left;      int new_l;
817      bool new_touch_right;      int regionsize = region->KeyRange.high - region->KeyRange.low;
818      int a = 0;      int a = 0;
819      if (k > move.pos) {      if (l > region->KeyRange.low) {
820          for (gig::Region* r = regions.first() ; ; r = regions.next()) {          for (gig::Region* r = regions.first() ; ; r = regions.next()) {
821              if (r != region) {              if (r != region) {
822                  int b = r ? r->KeyRange.low : 128;                  int b = r ? r->KeyRange.low : 128;
823    
824                  // gap: from a to b (not inclusive b)                  // gap: from a to b (not inclusive b)
825    
826                  if (region->KeyRange.high + move.pos >= b) {                  if (region->KeyRange.high >= b) {
827                      // not found the current gap yet, just continue                      // not found the current gap yet, just continue
828                  } else {                  } else {
829    
830                      if (a > region->KeyRange.low + k) {                      if (a > l) {
831                          // this gap is too far to the right, break                          // this gap is too far to the right, break
832                          break;                          break;
833                      }                      }
834    
835                      int newhigh = std::min(region->KeyRange.high + k, b - 1);                      int newhigh = std::min(l + regionsize, b - 1);
836                      int newlo = newhigh - (region->KeyRange.high - region->KeyRange.low);                      int newlo = newhigh - regionsize;
837    
838                      if (newlo >= a) {                      if (newlo >= a) {
839                          // yes it fits - it's a candidate                          // yes it fits - it's a candidate
840                          new_k = newlo - region->KeyRange.low;                          new_l = newlo;
                         new_touch_left = a > 0 && a == newlo;  
                         new_touch_right = b < 128 && newhigh + 1 == b;  
841                      }                      }
842                  }                  }
843                  if (!r) break;                  if (!r) break;
# Line 681  void RegionChooser::motion_move_region(i Line 851  void RegionChooser::motion_move_region(i
851    
852                  // gap from a to b (not inclusive b)                  // gap from a to b (not inclusive b)
853    
854                  if (region->KeyRange.high + k >= b) {                  if (l + regionsize >= b) {
855                      // not found the current gap yet, just continue                      // not found the current gap yet, just continue
856                  } else {                  } else {
857    
858                      if (a > region->KeyRange.low + move.pos) {                      if (a > region->KeyRange.low) {
859                          // this gap is too far to the right, break                          // this gap is too far to the right, break
860                          break;                          break;
861                      }                      }
862    
863                      int newlo = std::max(region->KeyRange.low + k, a);                      int newlo = std::max(l, a);
864                      int newhigh = newlo + (region->KeyRange.high - region->KeyRange.low);                      int newhigh = newlo + regionsize;
865    
866                      if (newhigh < b) {                      if (newhigh < b) {
867                          // yes it fits - break as the first one is the best                          // yes it fits - break as the first one is the best
868                          new_k = newlo - region->KeyRange.low;                          new_l = newlo;
                         new_touch_left = a > 0 && a == newlo;  
                         new_touch_right = b < 128 && newhigh + 1 == b;  
869                          break;                          break;
870                      }                      }
871                  }                  }
# Line 706  void RegionChooser::motion_move_region(i Line 874  void RegionChooser::motion_move_region(i
874              }              }
875          }          }
876      }      }
877      k = new_k;      if (new_l == region->KeyRange.low) return;
     if (k == move.pos) return;  
878    
879      const Gdk::Color bg = get_style()->get_bg(Gtk::STATE_NORMAL);      int x1 = key_to_x(std::min(int(region->KeyRange.low), new_l), w);
880      int prevx = int(w * (move.pos + region->KeyRange.low) / 128.0 + 0.5);      int x2 = key_to_x(std::max(int(region->KeyRange.high),
881      x = int(w * (k + region->KeyRange.low) / 128.0 + 0.5);                                 new_l + regionsize) + 1, w) + 1;
     int prevx2 = int(w * (move.pos + region->KeyRange.high + 1) / 128.0 + 0.5);  
     int x2 = int(w * (k + region->KeyRange.high + 1) / 128.0 + 0.5);  
     const Gdk::Color black = get_style()->get_black();  
   
     if (!new_touch_left) {  
         Gdk::Cairo::set_source_color(cr, black);  
         cr->move_to(x + 0.5, 1);  
         cr->line_to(x + 0.5, h1 - 1);  
         cr->stroke();  
     }  
     if (!new_touch_right) {  
         Gdk::Cairo::set_source_color(cr, black);  
         cr->move_to(x2 + 0.5, 1);  
         cr->line_to(x2 + 0.5, h1 - 1);  
         cr->stroke();  
     }  
   
     if (k > move.pos) {  
         Gdk::Cairo::set_source_color(cr, bg);  
         cr->rectangle(prevx + (move.touch_left ? 1 : 0), 0,  
                       std::min(x, prevx2 + 1 - (move.touch_right ? 1 : 0)) -  
                       (prevx + (move.touch_left ? 1 : 0)), h1);  
         cr->fill();  
   
         Gdk::Cairo::set_source_color(cr, black);  
         cr->move_to(std::max(x, prevx2 + 1), 0.5);  
         cr->line_to(x2 + 1, 0.5);  
         cr->move_to(std::max(x, prevx2 + 1), h1 - 0.5);  
         cr->line_to(x2 + 1, h1 - 0.5);  
         cr->stroke();  
882    
883          Gdk::Cairo::set_source_color(cr, red);      Gdk::Rectangle rect(x1, 0, x2 - x1, h1);
884          cr->rectangle(std::max(x + 1, prevx2), 1,      update_after_move(new_l);
                       x2 - std::max(x + 1, prevx2), h1 - 2);  
         cr->fill();  
     } else {  
         Gdk::Cairo::set_source_color(cr, bg);  
         cr->rectangle(std::max(x2 + 1, prevx + (move.touch_left ? 1 : 0)), 0,  
                       prevx2 + 1 - (move.touch_right ? 1 : 0) -  
                       std::max(x2 + 1, prevx + (move.touch_left ? 1 : 0)), h1);  
         cr->fill();  
   
         Gdk::Cairo::set_source_color(cr, black);  
         cr->move_to(x, 0.5);  
         cr->line_to(std::min(x2, prevx - 1) + 1, 0.5);  
         cr->move_to(x, h1 - 0.5);  
         cr->line_to(std::min(x2, prevx - 1) + 1, h1 - 0.5);  
         cr->stroke();  
   
         Gdk::Cairo::set_source_color(cr, red);  
         cr->rectangle(x + 1, 1, std::min(x2 - 1, prevx) - x, h1 - 2);  
         cr->fill();  
     }  
885    
886      move.pos = k;      get_window()->invalidate_rect(rect, false);
     move.touch_left = new_touch_left;  
     move.touch_right = new_touch_right;  
887  }  }
888    
889    
# Line 785  bool RegionChooser::on_motion_notify_eve Line 900  bool RegionChooser::on_motion_notify_eve
900          event->y >= REGION_BLOCK_HEIGHT &&          event->y >= REGION_BLOCK_HEIGHT &&
901          event->y < REGION_BLOCK_HEIGHT + KEYBOARD_HEIGHT)          event->y < REGION_BLOCK_HEIGHT + KEYBOARD_HEIGHT)
902      {      {
903          const int k = int(event->x / (get_width() - 1) * 128.0);          const int k = x_to_key(event->x, get_width() - 1);
904          if (k != currentActiveKey) {          if (k != currentActiveKey) {
905              int velocity =              int velocity =
906                  (event->y >= REGION_BLOCK_HEIGHT + KEYBOARD_HEIGHT - 1) ? 127 :                  (event->y >= REGION_BLOCK_HEIGHT + KEYBOARD_HEIGHT - 1) ? 127 :
# Line 805  bool RegionChooser::on_motion_notify_eve Line 920  bool RegionChooser::on_motion_notify_eve
920      } else {      } else {
921          if (is_in_resize_zone(x, y)) {          if (is_in_resize_zone(x, y)) {
922              if (!cursor_is_resize) {              if (!cursor_is_resize) {
923    #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
924                  window->set_cursor(Gdk::Cursor(Gdk::SB_H_DOUBLE_ARROW));                  window->set_cursor(Gdk::Cursor(Gdk::SB_H_DOUBLE_ARROW));
925    #else
926                    window->set_cursor(Gdk::Cursor::create(Gdk::SB_H_DOUBLE_ARROW));
927    #endif
928                  cursor_is_resize = true;                  cursor_is_resize = true;
929              }              }
930          } else if (cursor_is_resize) {          } else if (cursor_is_resize) {
# Line 826  bool RegionChooser::is_in_resize_zone(do Line 945  bool RegionChooser::is_in_resize_zone(do
945          for (gig::Region* r = regions.first(); r ; r = next_region) {          for (gig::Region* r = regions.first(); r ; r = next_region) {
946              next_region = regions.next();              next_region = regions.next();
947    
948              int lo = int(w * (r->KeyRange.low) / 128.0 + 0.5);              int lo = key_to_x(r->KeyRange.low, w);
949              if (x <= lo - 2) break;              if (x <= lo - 2) break;
950              if (x < lo + 2) {              if (x < lo + 2) {
951                  resize.region = r;                  resize.region = r;
# Line 849  bool RegionChooser::is_in_resize_zone(do Line 968  bool RegionChooser::is_in_resize_zone(do
968                  return resize.min != resize.max;                  return resize.min != resize.max;
969              }              }
970              if (!next_region || r->KeyRange.high + 1 != next_region->KeyRange.low) {              if (!next_region || r->KeyRange.high + 1 != next_region->KeyRange.low) {
971                  int hi = int(w * (r->KeyRange.high + 1) / 128.0 + 0.5);                  int hi = key_to_x(r->KeyRange.high + 1, w);
972                  if (x <= hi - 2) break;                  if (x <= hi - 2) break;
973                  if (x < hi + 2) {                  if (x < hi + 2) {
974                      // edit high limit                      // edit high limit
# Line 887  void RegionChooser::show_region_properti Line 1006  void RegionChooser::show_region_properti
1006      dialog.get_vbox()->pack_start(checkBoxKeygroup);      dialog.get_vbox()->pack_start(checkBoxKeygroup);
1007      checkBoxKeygroup.show();      checkBoxKeygroup.show();
1008      // add "Keygroup" spinbox      // add "Keygroup" spinbox
1009      Gtk::Adjustment adjustment(1, 1, pow(2,32));  #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
1010        Gtk::Adjustment adjustment(1, 1, 999);
1011      Gtk::SpinButton spinBox(adjustment);      Gtk::SpinButton spinBox(adjustment);
1012    #else
1013        Gtk::SpinButton spinBox(Gtk::Adjustment::create(1, 1, 999));
1014    #endif
1015      if (region->KeyGroup) spinBox.set_value(region->KeyGroup);      if (region->KeyGroup) spinBox.set_value(region->KeyGroup);
1016      dialog.get_vbox()->pack_start(spinBox);      dialog.get_vbox()->pack_start(spinBox);
1017      spinBox.show();      spinBox.show();
1018      // add OK and CANCEL buttons to the dialog      // add OK and CANCEL buttons to the dialog
1019      dialog.add_button(Gtk::Stock::OK, 0);      dialog.add_button(_("_OK"), 0);
1020      dialog.add_button(Gtk::Stock::CANCEL, 1);      dialog.add_button(_("_Cancel"), 1);
1021      dialog.show_all_children();      dialog.show_all_children();
1022      if (!dialog.run()) { // OK selected ...      if (!dialog.run()) { // OK selected ...
1023          region->KeyGroup =          region->KeyGroup =

Legend:
Removed from v.2151  
changed lines
  Added in v.3131

  ViewVC Help
Powered by ViewVC