/[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 3226 by schoenebeck, Fri May 26 22:15:06 2017 UTC
# Line 1  Line 1 
1  /*  /*
2   * Copyright (C) 2006-2010 Andreas Persson   * Copyright (C) 2006-2017 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 17  Line 17 
17   * 02110-1301 USA.   * 02110-1301 USA.
18   */   */
19    
20    #include "global.h"
21  #include "regionchooser.h"  #include "regionchooser.h"
22    
23  #include <algorithm>  #include <algorithm>
24  #include <cmath>  #include <assert.h>
 #include <sstream>  
25    
26  #include <cairomm/context.h>  #include <cairomm/context.h>
27  #include <gdkmm/general.h>  #include <gdkmm/general.h>
28  #include <gdkmm/cursor.h>  #include <gdkmm/cursor.h>
29  #include <gtkmm/stock.h>  #include <gtkmm/stock.h>
30    #include <gdkmm/pixbuf.h>
31  #include <gtkmm/spinbutton.h>  #include <gtkmm/spinbutton.h>
32  #include <gtkmm/dialog.h>  #include <gtkmm/dialog.h>
33    
34  #include "global.h"  #include "Settings.h"
35    #include "gfx/builtinpix.h"
36    
37  #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 10) || GTKMM_MAJOR_VERSION < 2  #define REGION_BLOCK_HEIGHT             30
38    #define KEYBOARD_HEIGHT                 40
39    
40  #define create_cairo_context()                                          \  struct RegionFeatures {
41      gobj() ? Cairo::RefPtr<Cairo::Context>(                             \      int sampleRefs;
42          new Cairo::Context(gdk_cairo_create(get_window()->gobj()))) :   \      int loops;
     Cairo::RefPtr<Cairo::Context>()  
43    
44  namespace Gdk {      RegionFeatures() {
45      namespace Cairo {          sampleRefs = loops = 0;
         void set_source_color(const ::Cairo::RefPtr< ::Cairo::Context >& cr,  
                               const Gdk::Color& color) {  
             gdk_cairo_set_source_color(cr->cobj(),  
                                        const_cast<GdkColor*>(color.gobj()));  
         }  
46      }      }
47  }  };
 #endif  
48    
49  #define REGION_BLOCK_HEIGHT             20  static RegionFeatures regionFeatures(gig::Region* rgn) {
50  #define KEYBOARD_HEIGHT                 40      RegionFeatures f;
51        for (int i = 0; i < rgn->DimensionRegions; ++i) {
52            gig::DimensionRegion* dr = rgn->pDimensionRegions[i];
53            if (dr->pSample) f.sampleRefs++;
54            // the user doesn't care about loop if there is no valid sample reference
55            if (dr->pSample && dr->SampleLoops) f.loops++;
56        }
57        return f;
58    }
59    
60  void SortedRegions::update(gig::Instrument* instrument) {  void SortedRegions::update(gig::Instrument* instrument) {
61      // 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 78  gig::Region* SortedRegions::first() {
78  }  }
79    
80  gig::Region* SortedRegions::next() {  gig::Region* SortedRegions::next() {
81      region_iterator++;      ++region_iterator;
82      return region_iterator == regions.end() ? 0 : *region_iterator;      return region_iterator == regions.end() ? 0 : *region_iterator;
83  }  }
84    
85    
86    
87  RegionChooser::RegionChooser() :  RegionChooser::RegionChooser() :
88        activeKeyColor("red"),
89        blue("#4796ff"),
90        grey1("grey69"),
91        white("white"),
92        black("black"),
93      m_VirtKeybModeChoice(_("Virtual Keyboard Mode")),      m_VirtKeybModeChoice(_("Virtual Keyboard Mode")),
94      currentActiveKey(-1)      currentActiveKey(-1),
95        modifyallregions(false)
96  {  {
97      red = Gdk::Color("#8070ff");      set_size_request(500, KEYBOARD_HEIGHT + REGION_BLOCK_HEIGHT);
98      grey1 = Gdk::Color("#b0b0b0");  
99      activeKeyColor = Gdk::Color("#ff0000");      loadBuiltInPix();
100      white = Gdk::Color("#ffffff");  
101      black = Gdk::Color("#000000");      // create gray blue hatched pattern
102        {
103            const int width = grayBlueHatchedPattern->get_width();
104            const int height = grayBlueHatchedPattern->get_height();
105            const int stride = grayBlueHatchedPattern->get_rowstride();
106    
107            // manually convert from RGBA to ARGB
108            this->grayBlueHatchedPatternARGB = grayBlueHatchedPattern->copy();
109            const int pixelSize = stride / width;
110            const int totalPixels = width * height;
111            assert(pixelSize == 4);
112            unsigned char* ptr = this->grayBlueHatchedPatternARGB->get_pixels();
113            for (int iPixel = 0; iPixel < totalPixels; ++iPixel, ptr += pixelSize) {
114                const unsigned char r = ptr[0];
115                const unsigned char g = ptr[1];
116                const unsigned char b = ptr[2];
117                const unsigned char a = ptr[3];
118                ptr[0] = b;
119                ptr[1] = g;
120                ptr[2] = r;
121                ptr[3] = a;
122            }
123    
124            Cairo::RefPtr<Cairo::ImageSurface> imageSurface = Cairo::ImageSurface::create(
125                this->grayBlueHatchedPatternARGB->get_pixels(), Cairo::FORMAT_ARGB32, width, height, stride
126            );
127            this->grayBlueHatchedSurfacePattern = Cairo::SurfacePattern::create(imageSurface);
128            this->grayBlueHatchedSurfacePattern->set_extend(Cairo::EXTEND_REPEAT);
129        }
130    
131      instrument = 0;      instrument = 0;
132      region = 0;      region = 0;
# Line 99  RegionChooser::RegionChooser() : Line 137  RegionChooser::RegionChooser() :
137    
138      // properties of the virtual keyboard      // properties of the virtual keyboard
139      {      {
140          const char* choices[] = { _("normal"), _("chord"), NULL };          const char* choices[] = { _("normal"), _("chord"), 0 };
141          static const virt_keyboard_mode_t values[] = {          static const virt_keyboard_mode_t values[] = {
142              VIRT_KEYBOARD_MODE_NORMAL,              VIRT_KEYBOARD_MODE_NORMAL,
143              VIRT_KEYBOARD_MODE_CHORD              VIRT_KEYBOARD_MODE_CHORD
# Line 119  RegionChooser::RegionChooser() : Line 157  RegionChooser::RegionChooser() :
157      m_VirtKeybPropsBox.pack_start(m_VirtKeybOffVelocityLabel, Gtk::PACK_SHRINK);      m_VirtKeybPropsBox.pack_start(m_VirtKeybOffVelocityLabel, Gtk::PACK_SHRINK);
158      m_VirtKeybPropsBox.set_spacing(10);      m_VirtKeybPropsBox.set_spacing(10);
159      m_VirtKeybPropsBox.show();      m_VirtKeybPropsBox.show();
160        for (int i = 0 ; i < 128 ; i++) key_pressed[i] = false;
161    
162      actionGroup = Gtk::ActionGroup::create();      actionGroup = Gtk::ActionGroup::create();
163      actionGroup->add(Gtk::Action::create("Properties",      actionGroup->add(Gtk::Action::create("Properties",
# Line 172  RegionChooser::RegionChooser() : Line 211  RegionChooser::RegionChooser() :
211      keyboard_key_released_signal.connect(      keyboard_key_released_signal.connect(
212          sigc::mem_fun(*this, &RegionChooser::on_note_off_event)          sigc::mem_fun(*this, &RegionChooser::on_note_off_event)
213      );      );
214        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."));
215  }  }
216    
217  RegionChooser::~RegionChooser()  RegionChooser::~RegionChooser()
218  {  {
219  }  }
220    
221  template<class T> inline std::string ToString(T o) {  void RegionChooser::setModifyAllRegions(bool b) {
222      std::stringstream ss;      modifyallregions = b;
223      ss << o;      // redraw required parts
224      return ss.str();      queue_draw();
225    }
226    
227    void RegionChooser::invalidate_key(int key) {
228        const int h = KEYBOARD_HEIGHT;
229        const int w = get_width() - 1;
230        int x1 = key_to_x(key - 0.5, w);
231        int x2 = key_to_x(key + 1.5, w);
232    
233        Gdk::Rectangle rect(x1 + 1, h1 + 1, x2 - x1 - 1, h - 2);
234        get_window()->invalidate_rect(rect, false);
235  }  }
236    
237  void RegionChooser::on_note_on_event(int key, int velocity) {  void RegionChooser::on_note_on_event(int key, int velocity) {
238      draw_key(key, activeKeyColor);      key_pressed[key] = true;
239        invalidate_key(key);
240      m_VirtKeybVelocityLabel.set_text(ToString(velocity));      m_VirtKeybVelocityLabel.set_text(ToString(velocity));
241  }  }
242    
243  void RegionChooser::on_note_off_event(int key, int velocity) {  void RegionChooser::on_note_off_event(int key, int velocity) {
244      if (is_black_key(key)) {      key_pressed[key] = false;
245          draw_key(key, black);      invalidate_key(key);
     } else {  
         draw_key(key, key >= 21 && key <= 108 ? white : grey1);  
     }  
246      m_VirtKeybOffVelocityLabel.set_text(ToString(velocity));      m_VirtKeybOffVelocityLabel.set_text(ToString(velocity));
247  }  }
248    
249    
250  bool RegionChooser::on_expose_event(GdkEventExpose* event)  #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
251  {  bool RegionChooser::on_expose_event(GdkEventExpose* e) {
252      Glib::RefPtr<Gdk::Window> window = get_window();      double clipx1 = e->area.x;
253      if (window) {      double clipx2 = e->area.x + e->area.width;
254          Cairo::RefPtr<Cairo::Context> cr = window->create_cairo_context();      double clipy1 = e->area.y;
255          if (event) {      double clipy2 = e->area.y + e->area.height;
256              cr->rectangle(event->area.x, event->area.y,  
257                            event->area.width, event->area.height);      const Cairo::RefPtr<Cairo::Context>& cr =
258              cr->clip();          get_window()->create_cairo_context();
259          }  #if 0
260          const int h = KEYBOARD_HEIGHT;  }
261          const int w = get_width() - 1;  #endif
262          const int bh = int(h * 0.55);  #else
263    bool RegionChooser::on_draw(const Cairo::RefPtr<Cairo::Context>& cr) {
264          cr->save();      double clipx1, clipx2, clipy1, clipy2;
265          cr->set_line_width(1);      cr->get_clip_extents(clipx1, clipy1, clipx2, clipy2);
266    #endif
         const Gdk::Color bg = get_style()->get_bg(Gtk::STATE_NORMAL);  
         Gdk::Cairo::set_source_color(cr, bg);  
         cr->paint();  
267    
268          Gdk::Cairo::set_source_color(cr, black);      cr->save();
269          cr->rectangle(0.5, h1 + 0.5, w, h - 1);      cr->set_line_width(1);
         cr->stroke();  
270    
271          int x1 = int(w * 20.5 / 128.0 + 0.5);  #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
272          int x2 = int(w * 109.5 / 128.0 + 0.5);      const Gdk::Color bg = get_style()->get_bg(Gtk::STATE_NORMAL);
273    #else
274        const Gdk::RGBA bg = get_style_context()->get_background_color();
275    #endif
276        Gdk::Cairo::set_source_rgba(cr, bg);
277        cr->paint();
278    
279          Gdk::Cairo::set_source_color(cr, grey1);      if (clipy2 > h1) {
280          cr->rectangle(1, h1 + 1, x1 - 1, h - 2);          draw_keyboard(cr, clipx1, clipx2);
281          cr->fill();      }
282    
283          Gdk::Cairo::set_source_color(cr, white);      if (clipy1 < h1 && instrument) {
284          cr->rectangle(x1 + 1, h1 + 1, x2 - x1 - 1, h - 2);          draw_regions(cr, clipx1, clipx2);
285          cr->fill();      }
286    
287          Gdk::Cairo::set_source_color(cr, grey1);      cr->restore();
         cr->rectangle(x2 + 1, h1 + 1, w - x2 - 1, h - 2);  
         cr->fill();  
288    
289          Gdk::Cairo::set_source_color(cr, black);      return true;
290          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();  
291    
292                  int x3 = int(w * (i + 1) / 128.0 + 0.5);  void RegionChooser::draw_keyboard(const Cairo::RefPtr<Cairo::Context>& cr,
293                  cr->rectangle(x, h1 + 1, x3 - x + 1, bh);                                    int clip_low, int clip_high) {
294                  cr->fill();      const int h = KEYBOARD_HEIGHT;
295              } else if (note == 3 || note == 8) {      const int w = get_width() - 1;
296                  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();  
297    
298                  if (note == 3) draw_digit(i);      Gdk::Cairo::set_source_rgba(cr, black);
299              }      cr->rectangle(0.5, h1 + 0.5, w, h - 1);
300        cr->stroke();
301    
302        int x1 = key_to_x(20.5, w);
303        Gdk::Cairo::set_source_rgba(cr, grey1);
304        cr->rectangle(1, h1 + 1, x1 - 1, h - 2);
305        cr->fill();
306    
307        int x2 = key_to_x(109.5, w);
308        Gdk::Cairo::set_source_rgba(cr, white);
309        cr->rectangle(x1 + 1, h1 + 1, x2 - x1 - 1, h - 2);
310        cr->fill();
311    
312        Gdk::Cairo::set_source_rgba(cr, grey1);
313        cr->rectangle(x2 + 1, h1 + 1, w - x2 - 1, h - 2);
314        cr->fill();
315    
316        Gdk::Cairo::set_source_rgba(cr, black);
317    
318        int clipkey1 = std::max(0, x_to_key_right(clip_low - 1, w));
319        int clipkey2 = std::min(x_to_key_right(clip_high - 1, w) + 1, 128);
320    
321        for (int i = clipkey1 ; i < clipkey2 ; i++) {
322            int note = (i + 3) % 12;
323            int x = key_to_x(i, w);
324    
325            if (note == 1 || note == 4 || note == 6 ||
326                note == 9 || note == 11) {
327                // black key: short line in the middle, with a rectangle
328                // on top
329                int x2 = key_to_x(i + 0.5, w);
330                cr->move_to(x2 + 0.5, h1 + bh + 0.5);
331                cr->line_to(x2 + 0.5, h1 + h - 1);
332                cr->stroke();
333    
334                int x3 = key_to_x(i + 1, w);
335                cr->rectangle(x, h1 + 1, x3 - x + 1, bh);
336                cr->fill();
337            } else if (note == 3 || note == 8) {
338                // C or F: long line to the left
339                cr->move_to(x + 0.5, h1 + 1);
340                cr->line_to(x + 0.5, h1 + h - 1);
341                cr->stroke();
342          }          }
343    
344          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);  
345    
346                      x3 = -1;          if (note == 3) draw_digit(cr, i);
347                  }      }
348                  i++;  }
349              }  
350    
351    void RegionChooser::draw_regions(const Cairo::RefPtr<Cairo::Context>& cr,
352                                     int clip_low, int clip_high) {
353        const int w = get_width() - 1;
354    
355              for (gig::Region* r = regions.first() ; r ; r = regions.next()) {      Gdk::Cairo::set_source_rgba(cr, black);
356                  int x = int(w * (r->KeyRange.low) / 128.0 + 0.5);      gig::Region* next_region;
357                  cr->move_to(x + 0.5, 1);      int x3 = -1;
358                  cr->line_to(x + 0.5, h1 - 1);      for (gig::Region* r = regions.first() ; r ; r = next_region) {
359            next_region = regions.next();
360    
361            if (x3 < 0) {
362                x3 = key_to_x(r->KeyRange.low, w);
363                if (x3 >= clip_high) break;
364            }
365            if (!next_region ||
366                r->KeyRange.high + 1 != next_region->KeyRange.low ||
367                r == region || next_region == region) {
368    
369                int x2 = key_to_x(r->KeyRange.high + 1, w);
370                if (x2 >= clip_low) {
371                    cr->move_to(x3, 0.5);
372                    cr->line_to(x2 + 0.5, 0.5);
373                    cr->line_to(x2 + 0.5, h1 - 0.5);
374                    cr->line_to(x3, h1 - 0.5);
375                  cr->stroke();                  cr->stroke();
             }  
376    
377              if (region) {                  if (region == r)
378                  int x1 = int(w * (region->KeyRange.low) / 128.0 + 0.5);                      Gdk::Cairo::set_source_rgba(cr, blue);
379                  int x2 = int(w * (region->KeyRange.high + 1) / 128.0 + 0.5);                  else if (modifyallregions)
380                  Gdk::Cairo::set_source_color(cr, red);                      cr->set_source(grayBlueHatchedSurfacePattern);
381                  cr->rectangle(x1 + 1, 1, x2 - x1 - 1, h1 - 2);                  else
382                        Gdk::Cairo::set_source_rgba(cr, white);
383    
384                    cr->rectangle(x3 + 1, 1, x2 - x3 - 1, h1 - 2);
385                  cr->fill();                  cr->fill();
386                    Gdk::Cairo::set_source_rgba(cr, black);
387              }              }
388                x3 = -1;
389          }          }
390        }
391    
392          cr->restore();      for (gig::Region* r = regions.first() ; r ; r = regions.next()) {
393            int x = key_to_x(r->KeyRange.low, w);
394            int x2 = key_to_x(r->KeyRange.high + 1, w);
395    
396            RegionFeatures features = regionFeatures(r);
397    
398            const bool bShowLoopSymbol = features.loops > 0;
399            const bool bShowSampleRefSymbol = features.sampleRefs < r->DimensionRegions;
400            if (bShowLoopSymbol || bShowSampleRefSymbol) {
401                const int margin = 2;
402                const int wRgn = x2 - x;
403                //printf("x=%d x2=%d wRgn=%d\n", x, x2, wRgn);
404    
405                cr->save();
406                cr->set_line_width(1);
407                cr->rectangle(x, 1, wRgn, h1 - 1);
408                cr->clip();
409                if (bShowSampleRefSymbol) {
410                    const int wPic = 8;
411                    const int hPic = 8;
412                    Gdk::Cairo::set_source_pixbuf(
413                        cr, (features.sampleRefs) ? yellowDot : redDot,
414                        x + (wRgn-wPic)/2.f,
415                        (bShowLoopSymbol) ? margin : (h1-hPic)/2.f
416                    );
417                    cr->paint();
418                }
419                if (bShowLoopSymbol) {
420                    const int wPic = 12;
421                    const int hPic = 14;
422                    Gdk::Cairo::set_source_pixbuf(
423                        cr, (features.loops == r->DimensionRegions) ? blackLoop : grayLoop,
424                        x + (wRgn-wPic)/2.f,
425                        (bShowSampleRefSymbol) ? h1 - hPic - margin : (h1-hPic)/2.f
426                    );
427                    cr->paint();
428                }
429                cr->restore();
430            }
431      }      }
432    
433      return true;      for (gig::Region* r = regions.first() ; r ; r = regions.next()) {
434  }          int x = key_to_x(r->KeyRange.low, w);
435    
436            if (x < clip_low) continue;
437            if (x >= clip_high) break;
438    
439  void RegionChooser::on_size_request(GtkRequisition* requisition)          cr->move_to(x + 0.5, 1);
440  {          cr->line_to(x + 0.5, h1 - 1);
441      *requisition = GtkRequisition();          cr->stroke();
442      requisition->height = KEYBOARD_HEIGHT + REGION_BLOCK_HEIGHT;      }
443      requisition->width = 500;  
444        // if there is no region yet, show the user some hint text that he may
445        // right click on this area to create a new region
446        if (!regions.first()) {
447            Glib::RefPtr<Pango::Context> context = get_pango_context();
448            Glib::RefPtr<Pango::Layout> layout = Pango::Layout::create(context);
449            layout->set_alignment(Pango::ALIGN_CENTER);
450            layout->set_text(Glib::ustring("*** ") + _("Right click here to create a region.") + " ***");
451            layout->set_width(get_width() * Pango::SCALE);
452            //layout->set_height(get_height() * Pango::SCALE);
453            layout->set_spacing(10);
454            Gdk::Cairo::set_source_rgba(cr, blue);
455            // get the text dimensions
456            int text_width, text_height;
457            layout->get_pixel_size(text_width, text_height);
458            cr->move_to(0, (REGION_BLOCK_HEIGHT - text_height) / 2);
459    #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 16) || GTKMM_MAJOR_VERSION < 2
460            pango_cairo_show_layout(cr->cobj(), layout->gobj());
461    #else
462            layout->show_in_cairo_context(cr);
463    #endif
464        }
465  }  }
466    
467  bool RegionChooser::is_black_key(int key) {  bool RegionChooser::is_black_key(int key) {
# Line 325  bool RegionChooser::is_black_key(int key Line 469  bool RegionChooser::is_black_key(int key
469      return note == 1 || note == 4 || note == 6 || note == 9 || note == 11;      return note == 1 || note == 4 || note == 6 || note == 9 || note == 11;
470  }  }
471    
472  void RegionChooser::draw_digit(int key) {  void RegionChooser::draw_digit(const Cairo::RefPtr<Cairo::Context>& cr,
473                                   int key) {
474      const int h = KEYBOARD_HEIGHT;      const int h = KEYBOARD_HEIGHT;
475      const int w = get_width() - 1;      const int w = get_width() - 1;
476      Glib::RefPtr<Pango::Layout> layout = Pango::Layout::create(get_pango_context());      Glib::RefPtr<Pango::Layout> layout =
477            Pango::Layout::create(get_pango_context());
478      char buf[30];      char buf[30];
479      sprintf(buf, "<span size=\"8000\">%d</span>", key / 12 - 1);      sprintf(buf, "<span size=\"8000\">%d</span>", key / 12 - 1);
480      layout->set_markup(buf);      layout->set_markup(buf);
# Line 336  void RegionChooser::draw_digit(int key) Line 482  void RegionChooser::draw_digit(int key)
482      double text_w = double(rectangle.get_width()) / Pango::SCALE;      double text_w = double(rectangle.get_width()) / Pango::SCALE;
483      double text_h = double(rectangle.get_height()) / Pango::SCALE;      double text_h = double(rectangle.get_height()) / Pango::SCALE;
484      double x = w * (key + 0.75) / 128.0;      double x = w * (key + 0.75) / 128.0;
485      Cairo::RefPtr<Cairo::Context> cr = get_window()->create_cairo_context();      Gdk::Cairo::set_source_rgba(cr, black);
     Gdk::Cairo::set_source_color(cr, black);  
486      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));
487  #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
488      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 491  void RegionChooser::draw_digit(int key)
491  #endif  #endif
492  }  }
493    
494  void RegionChooser::draw_key(int key, const Gdk::Color& color)  void RegionChooser::draw_key(const Cairo::RefPtr<Cairo::Context>& cr,
495  {                               int key) {
496      const int h = KEYBOARD_HEIGHT;      const int h = KEYBOARD_HEIGHT;
497      const int w = get_width() - 1;      const int w = get_width() - 1;
498      const int bh = int(h * 0.55);      const int bh = int(h * 0.55);
499    
500      Cairo::RefPtr<Cairo::Context> cr = get_window()->create_cairo_context();      Gdk::Cairo::set_source_rgba(cr, activeKeyColor);
     Gdk::Cairo::set_source_color(cr, color);  
501    
502      int note = (key + 3) % 12;      int note = (key + 3) % 12;
503      int x = int(w * key / 128.0 + 0.5) + 1;      int x = key_to_x(key, w) + 1;
504      int x2 = int(w * (key + 1.5) / 128.0 + 0.5);      int x2 = key_to_x(key + 1.5, w);
505      int x3 = int(w * (key + 1) / 128.0 + 0.5);      int x3 = key_to_x(key + 1, w);
506      int x4 = int(w * (key - 0.5) / 128.0 + 0.5);      int x4 = key_to_x(key - 0.5, w);
507      int w1 = x3 - x;      int w1 = x3 - x;
508      switch (note) {      switch (note) {
509      case 0: case 5: case 10:      case 0: case 5: case 10:
# Line 379  void RegionChooser::draw_key(int key, co Line 523  void RegionChooser::draw_key(int key, co
523          cr->fill();          cr->fill();
524          cr->rectangle(x, h1 + bh + 1, x2 - x, h - bh - 2);          cr->rectangle(x, h1 + bh + 1, x2 - x, h - bh - 2);
525          cr->fill();          cr->fill();
         if (note == 3) draw_digit(key);  
526          break;          break;
527      default:      default:
528          cr->rectangle(x, h1 + 1, w1, bh - 1);          cr->rectangle(x, h1 + 1, w1, bh - 1);
529          cr->fill();          cr->fill();
530          break;          break;
531      }      }
532        Gdk::Cairo::set_source_rgba(cr, black);
533  }  }
534    
535  void RegionChooser::set_instrument(gig::Instrument* instrument)  void RegionChooser::set_instrument(gig::Instrument* instrument)
# Line 400  void RegionChooser::set_instrument(gig:: Line 544  void RegionChooser::set_instrument(gig::
544    
545  bool RegionChooser::on_button_release_event(GdkEventButton* event)  bool RegionChooser::on_button_release_event(GdkEventButton* event)
546  {  {
547      const int k = int(event->x / (get_width() - 1) * 128.0);      const int k = x_to_key(event->x, get_width() - 1);
548    
549      // handle-note off on virtual keyboard      // handle-note off on virtual keyboard
550      if (event->type == GDK_BUTTON_RELEASE) {      if (event->type == GDK_BUTTON_RELEASE) {
# Line 423  bool RegionChooser::on_button_release_ev Line 567  bool RegionChooser::on_button_release_ev
567      }      }
568    
569      if (resize.active) {      if (resize.active) {
570    #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
571          get_window()->pointer_ungrab(event->time);          get_window()->pointer_ungrab(event->time);
572    #else
573            Glib::wrap(event->device, true)->ungrab(event->time);
574    #endif
575          resize.active = false;          resize.active = false;
576    
         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);  
             }  
         }  
   
577          if (!is_in_resize_zone(event->x, event->y) && cursor_is_resize) {          if (!is_in_resize_zone(event->x, event->y) && cursor_is_resize) {
578              get_window()->set_cursor();              get_window()->set_cursor();
579              cursor_is_resize = false;              cursor_is_resize = false;
580          }          }
581      } else if (move.active) {      } else if (move.active) {
582    #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
583          get_window()->pointer_ungrab(event->time);          get_window()->pointer_ungrab(event->time);
584    #else
585            Glib::wrap(event->device, true)->ungrab(event->time);
586    #endif
587          move.active = false;          move.active = false;
588    
589          if (move.pos) {          if (is_in_resize_zone(event->x, event->y)) {
590    #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
591                get_window()->set_cursor(Gdk::Cursor(Gdk::SB_H_DOUBLE_ARROW));
592    #else
593                get_window()->set_cursor(Gdk::Cursor::create(Gdk::SB_H_DOUBLE_ARROW));
594    #endif
595                cursor_is_resize = true;
596            }
597        }
598        return true;
599    }
600    
601    void RegionChooser::update_after_resize()
602    {
603        if (resize.mode == resize.moving_high_limit) {
604            if (resize.region->KeyRange.high != resize.pos - 1) {
605                instrument_struct_to_be_changed_signal.emit(instrument);
606                resize.region->SetKeyRange(resize.region->KeyRange.low,
607                                           resize.pos - 1);
608                regions.update(instrument);
609                instrument_changed.emit();
610                instrument_struct_changed_signal.emit(instrument);
611            }
612        } else if (resize.mode == resize.moving_low_limit) {
613            if (resize.region->KeyRange.low != resize.pos) {
614              instrument_struct_to_be_changed_signal.emit(instrument);              instrument_struct_to_be_changed_signal.emit(instrument);
615              region->SetKeyRange(              resize.region->SetKeyRange(resize.pos,
616                  region->KeyRange.low  + move.pos,                                         resize.region->KeyRange.high);
                 region->KeyRange.high + move.pos  
             );  
617              regions.update(instrument);              regions.update(instrument);
618              instrument_changed.emit();              instrument_changed.emit();
619              instrument_struct_changed_signal.emit(instrument);              instrument_struct_changed_signal.emit(instrument);
620          }          }
621        }
622    }
623    
624          if (is_in_resize_zone(event->x, event->y)) {  void RegionChooser::update_after_move(int pos)
625              get_window()->set_cursor(Gdk::Cursor(Gdk::SB_H_DOUBLE_ARROW));  {
626              cursor_is_resize = true;      instrument_struct_to_be_changed_signal.emit(instrument);
627        const int range = region->KeyRange.high - region->KeyRange.low;
628        const int diff  = pos - int(region->KeyRange.low);
629        region->SetKeyRange(pos, pos + range);
630        if (Settings::singleton()->moveRootNoteWithRegionMoved) {
631            for (int i = 0; i < 256; ++i) {
632                gig::DimensionRegion* dimrgn = region->pDimensionRegions[i];
633                if (!dimrgn || !dimrgn->pSample || !dimrgn->PitchTrack) continue;
634                dimrgn->UnityNote += diff;
635          }          }
636      }      }
637      return true;      regions.update(instrument);
638        instrument_changed.emit();
639        instrument_struct_changed_signal.emit(instrument);
640  }  }
641    
642  bool RegionChooser::on_button_press_event(GdkEventButton* event)  bool RegionChooser::on_button_press_event(GdkEventButton* event)
643  {  {
644      if (!instrument) return true;      if (!instrument) return true;
645    
646      const int k = int(event->x / (get_width() - 1) * 128.0);      const int w = get_width() - 1;
647        const int k = x_to_key(event->x, w);
648    
649      if (event->type == GDK_BUTTON_PRESS) {      if (event->type == GDK_BUTTON_PRESS) {
650          if (event->y >= REGION_BLOCK_HEIGHT) {          if (event->y >= REGION_BLOCK_HEIGHT) {
# Line 492  bool RegionChooser::on_button_press_even Line 655  bool RegionChooser::on_button_press_even
655          }          }
656      }      }
657    
658        // left mouse button double click
659        if (event->type == GDK_2BUTTON_PRESS && event->button == 1) {
660            if (event->y < REGION_BLOCK_HEIGHT) {
661                // show dimension manager dialog for this region
662                manage_dimensions();
663            }
664        }
665    
666      if (event->y >= REGION_BLOCK_HEIGHT) return true;      if (event->y >= REGION_BLOCK_HEIGHT) return true;
667      if (event->type == GDK_BUTTON_PRESS && event->button == 3) {      if (event->type == GDK_BUTTON_PRESS && event->button == 3) {
668          gig::Region* r = get_region(k);          gig::Region* r = get_region(k);
# Line 507  bool RegionChooser::on_button_press_even Line 678  bool RegionChooser::on_button_press_even
678          }          }
679      } else {      } else {
680          if (is_in_resize_zone(event->x, event->y)) {          if (is_in_resize_zone(event->x, event->y)) {
681    #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
682              get_window()->pointer_grab(false,              get_window()->pointer_grab(false,
683                                         Gdk::BUTTON_RELEASE_MASK |                                         Gdk::BUTTON_RELEASE_MASK |
684                                         Gdk::POINTER_MOTION_MASK |                                         Gdk::POINTER_MOTION_MASK |
685                                         Gdk::POINTER_MOTION_HINT_MASK,                                         Gdk::POINTER_MOTION_HINT_MASK,
686                                         Gdk::Cursor(Gdk::SB_H_DOUBLE_ARROW), event->time);                                         Gdk::Cursor(Gdk::SB_H_DOUBLE_ARROW),
687                                           event->time);
688    #else
689                Glib::wrap(event->device, true)->grab(get_window(),
690                                                      Gdk::OWNERSHIP_NONE,
691                                                      false,
692                                                      Gdk::BUTTON_RELEASE_MASK |
693                                                      Gdk::POINTER_MOTION_MASK |
694                                                      Gdk::POINTER_MOTION_HINT_MASK,
695                                                      Gdk::Cursor::create(Gdk::SB_H_DOUBLE_ARROW),
696                                                      event->time);
697    #endif
698              resize.active = true;              resize.active = true;
699          } else {          } else {
700              gig::Region* r = get_region(k);              gig::Region* r = get_region(k);
# Line 521  bool RegionChooser::on_button_press_even Line 704  bool RegionChooser::on_button_press_even
704                  region_selected();                  region_selected();
705                  dimensionManager.set_region(region);                  dimensionManager.set_region(region);
706    
707    #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
708                  get_window()->pointer_grab(false,                  get_window()->pointer_grab(false,
709                                             Gdk::BUTTON_RELEASE_MASK |                                             Gdk::BUTTON_RELEASE_MASK |
710                                             Gdk::POINTER_MOTION_MASK |                                             Gdk::POINTER_MOTION_MASK |
711                                             Gdk::POINTER_MOTION_HINT_MASK,                                             Gdk::POINTER_MOTION_HINT_MASK,
712                                             Gdk::Cursor(Gdk::FLEUR), event->time);                                             Gdk::Cursor(Gdk::FLEUR),
713                                               event->time);
714    #else
715                    Glib::wrap(event->device, true)->grab(get_window(),
716                                                          Gdk::OWNERSHIP_NONE,
717                                                          false,
718                                                          Gdk::BUTTON_RELEASE_MASK |
719                                                          Gdk::POINTER_MOTION_MASK |
720                                                          Gdk::POINTER_MOTION_HINT_MASK,
721                                                          Gdk::Cursor::create(Gdk::FLEUR),
722                                                          event->time);
723    #endif
724                  move.active = true;                  move.active = true;
725                  move.from_x = event->x;                  move.offset = event->x - key_to_x(region->KeyRange.low, w);
                 move.pos = 0;  
726              }              }
727          }          }
728      }      }
# Line 537  bool RegionChooser::on_button_press_even Line 731  bool RegionChooser::on_button_press_even
731    
732  gig::Region* RegionChooser::get_region(int key)  gig::Region* RegionChooser::get_region(int key)
733  {  {
734      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();  
   
735          if (key < r->KeyRange.low) return 0;          if (key < r->KeyRange.low) return 0;
736          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;  
737      }      }
738      return 0;      return 0;
739  }  }
740    
741    void RegionChooser::set_region(gig::Region* region) {
742        this->region = region;
743        queue_draw();
744        region_selected();
745        dimensionManager.set_region(region);
746    }
747    
748    void RegionChooser::select_next_region() {
749        if (!instrument) return;
750        if (!region) {
751            for (int i = 0; i < 128; ++i) {
752                ::gig::Region* rgn = instrument->GetRegion(i);
753                if (rgn) {
754                    set_region(rgn);
755                    return;
756                }
757            }
758        } else {
759            bool currentFound = false;
760            for (int i = 0; i < 128; ++i) {
761                ::gig::Region* rgn = instrument->GetRegion(i);
762                if (!rgn) continue;
763                if (currentFound) {
764                    if (rgn != region) {
765                        set_region(rgn);
766                        return;
767                    }
768                } else {
769                    if (rgn == region) currentFound = true;
770                }
771            }
772        }
773    }
774    
775    void RegionChooser::select_prev_region() {
776        if (!instrument) return;
777        if (!region) {
778            for (int i = 0; i < 128; ++i) {
779                ::gig::Region* rgn = instrument->GetRegion(i);
780                if (rgn) {
781                    set_region(rgn);
782                    return;
783                }
784            }
785        } else {
786            bool currentFound = false;
787            for (int i = 127; i >= 0; --i) {
788                ::gig::Region* rgn = instrument->GetRegion(i);
789                if (!rgn) continue;
790                if (currentFound) {
791                    if (rgn != region) {
792                        set_region(rgn);
793                        return;
794                    }
795                } else {
796                    if (rgn == region) currentFound = true;
797                }
798            }
799        }
800    }
801    
802  void RegionChooser::motion_resize_region(int x, int y)  void RegionChooser::motion_resize_region(int x, int y)
803  {  {
804      const int w = get_width() - 1;      const int w = get_width() - 1;
# Line 563  void RegionChooser::motion_resize_region Line 809  void RegionChooser::motion_resize_region
809      else if (k > resize.max) k = resize.max;      else if (k > resize.max) k = resize.max;
810    
811      if (k != resize.pos) {      if (k != resize.pos) {
         Cairo::RefPtr<Cairo::Context> cr = get_window()->create_cairo_context();  
         cr->set_line_width(1);  
   
812          if (resize.mode == resize.undecided) {          if (resize.mode == resize.undecided) {
813              if (k < resize.pos) {              if (k < resize.pos) {
814                  // edit high limit of prev_region                  // edit high limit of prev_region
# Line 578  void RegionChooser::motion_resize_region Line 821  void RegionChooser::motion_resize_region
821                  resize.mode = resize.moving_low_limit;                  resize.mode = resize.moving_low_limit;
822              }              }
823          }          }
824          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);  
825    
826            int x1, x2;
827          if (resize.mode == resize.moving_high_limit) {          if (resize.mode == resize.moving_high_limit) {
828              if (k > resize.pos) {              if (resize.region->KeyRange.high < resize.pos - 1) {
829                  Gdk::Cairo::set_source_color(cr, white);                  x1 = resize.region->KeyRange.high;
830                  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();  
831              } else {              } else {
832                  int xx = (resize.pos == resize.max &&                  x1 = resize.pos - 1;
833                            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();  
834              }              }
835          } else {          } else {
836              if (k < resize.pos) {              if (resize.region->KeyRange.low < resize.pos) {
837                  Gdk::Cairo::set_source_color(cr, white);                  x1 = resize.region->KeyRange.low;
838                  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();  
839              } else {              } else {
840                  int xx = (resize.pos == resize.min &&                  x1 = resize.pos;
841                            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();  
842              }              }
843          }          }
844          Gdk::Cairo::set_source_color(cr, black);          x1 = key_to_x(x1, w);
845          cr->move_to(x + 0.5, 1);          x2 = key_to_x(x2 + 1, w) + 1;
846          cr->line_to(x + 0.5, h1 - 1);          Gdk::Rectangle rect(x1, 0, x2 - x1, h1);
847          cr->stroke();  
848          resize.pos = k;          update_after_resize();
849    
850            //get_window()->invalidate_rect(rect, false);
851            get_window()->invalidate(false); // repaint entire region, otherwise it would create visual artifacts
852      }      }
853  }  }
854    
855  void RegionChooser::motion_move_region(int x, int y)  void RegionChooser::motion_move_region(int x, int y)
856  {  {
857      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);  
858    
859      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);
860      if (k == move.pos) return;  
861      int new_k;      if (l == region->KeyRange.low) return;
862      bool new_touch_left;      int new_l;
863      bool new_touch_right;      int regionsize = region->KeyRange.high - region->KeyRange.low;
864      int a = 0;      int a = 0;
865      if (k > move.pos) {      if (l > region->KeyRange.low) {
866          for (gig::Region* r = regions.first() ; ; r = regions.next()) {          for (gig::Region* r = regions.first() ; ; r = regions.next()) {
867              if (r != region) {              if (r != region) {
868                  int b = r ? r->KeyRange.low : 128;                  int b = r ? r->KeyRange.low : 128;
869    
870                  // gap: from a to b (not inclusive b)                  // gap: from a to b (not inclusive b)
871    
872                  if (region->KeyRange.high + move.pos >= b) {                  if (region->KeyRange.high >= b) {
873                      // not found the current gap yet, just continue                      // not found the current gap yet, just continue
874                  } else {                  } else {
875    
876                      if (a > region->KeyRange.low + k) {                      if (a > l) {
877                          // this gap is too far to the right, break                          // this gap is too far to the right, break
878                          break;                          break;
879                      }                      }
880    
881                      int newhigh = std::min(region->KeyRange.high + k, b - 1);                      int newhigh = std::min(l + regionsize, b - 1);
882                      int newlo = newhigh - (region->KeyRange.high - region->KeyRange.low);                      int newlo = newhigh - regionsize;
883    
884                      if (newlo >= a) {                      if (newlo >= a) {
885                          // yes it fits - it's a candidate                          // yes it fits - it's a candidate
886                          new_k = newlo - region->KeyRange.low;                          new_l = newlo;
                         new_touch_left = a > 0 && a == newlo;  
                         new_touch_right = b < 128 && newhigh + 1 == b;  
887                      }                      }
888                  }                  }
889                  if (!r) break;                  if (!r) break;
# Line 681  void RegionChooser::motion_move_region(i Line 897  void RegionChooser::motion_move_region(i
897    
898                  // gap from a to b (not inclusive b)                  // gap from a to b (not inclusive b)
899    
900                  if (region->KeyRange.high + k >= b) {                  if (l + regionsize >= b) {
901                      // not found the current gap yet, just continue                      // not found the current gap yet, just continue
902                  } else {                  } else {
903    
904                      if (a > region->KeyRange.low + move.pos) {                      if (a > region->KeyRange.low) {
905                          // this gap is too far to the right, break                          // this gap is too far to the right, break
906                          break;                          break;
907                      }                      }
908    
909                      int newlo = std::max(region->KeyRange.low + k, a);                      int newlo = std::max(l, a);
910                      int newhigh = newlo + (region->KeyRange.high - region->KeyRange.low);                      int newhigh = newlo + regionsize;
911    
912                      if (newhigh < b) {                      if (newhigh < b) {
913                          // yes it fits - break as the first one is the best                          // yes it fits - break as the first one is the best
914                          new_k = newlo - region->KeyRange.low;                          new_l = newlo;
                         new_touch_left = a > 0 && a == newlo;  
                         new_touch_right = b < 128 && newhigh + 1 == b;  
915                          break;                          break;
916                      }                      }
917                  }                  }
# Line 706  void RegionChooser::motion_move_region(i Line 920  void RegionChooser::motion_move_region(i
920              }              }
921          }          }
922      }      }
923      k = new_k;      if (new_l == region->KeyRange.low) return;
     if (k == move.pos) return;  
924    
925      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);
926      int prevx = int(w * (move.pos + region->KeyRange.low) / 128.0 + 0.5);      int x2 = key_to_x(std::max(int(region->KeyRange.high),
927      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();  
928    
929          Gdk::Cairo::set_source_color(cr, red);      Gdk::Rectangle rect(x1, 0, x2 - x1, h1);
930          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();  
     }  
931    
932      move.pos = k;      get_window()->invalidate_rect(rect, false);
     move.touch_left = new_touch_left;  
     move.touch_right = new_touch_right;  
933  }  }
934    
935    
# Line 785  bool RegionChooser::on_motion_notify_eve Line 946  bool RegionChooser::on_motion_notify_eve
946          event->y >= REGION_BLOCK_HEIGHT &&          event->y >= REGION_BLOCK_HEIGHT &&
947          event->y < REGION_BLOCK_HEIGHT + KEYBOARD_HEIGHT)          event->y < REGION_BLOCK_HEIGHT + KEYBOARD_HEIGHT)
948      {      {
949          const int k = int(event->x / (get_width() - 1) * 128.0);          const int k = x_to_key(event->x, get_width() - 1);
950          if (k != currentActiveKey) {          if (k != currentActiveKey) {
951              int velocity =              int velocity =
952                  (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 966  bool RegionChooser::on_motion_notify_eve
966      } else {      } else {
967          if (is_in_resize_zone(x, y)) {          if (is_in_resize_zone(x, y)) {
968              if (!cursor_is_resize) {              if (!cursor_is_resize) {
969    #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
970                  window->set_cursor(Gdk::Cursor(Gdk::SB_H_DOUBLE_ARROW));                  window->set_cursor(Gdk::Cursor(Gdk::SB_H_DOUBLE_ARROW));
971    #else
972                    window->set_cursor(Gdk::Cursor::create(Gdk::SB_H_DOUBLE_ARROW));
973    #endif
974                  cursor_is_resize = true;                  cursor_is_resize = true;
975              }              }
976          } else if (cursor_is_resize) {          } else if (cursor_is_resize) {
# Line 826  bool RegionChooser::is_in_resize_zone(do Line 991  bool RegionChooser::is_in_resize_zone(do
991          for (gig::Region* r = regions.first(); r ; r = next_region) {          for (gig::Region* r = regions.first(); r ; r = next_region) {
992              next_region = regions.next();              next_region = regions.next();
993    
994              int lo = int(w * (r->KeyRange.low) / 128.0 + 0.5);              int lo = key_to_x(r->KeyRange.low, w);
995              if (x <= lo - 2) break;              if (x <= lo - 2) break;
996              if (x < lo + 2) {              if (x < lo + 2) {
997                  resize.region = r;                  resize.region = r;
# Line 849  bool RegionChooser::is_in_resize_zone(do Line 1014  bool RegionChooser::is_in_resize_zone(do
1014                  return resize.min != resize.max;                  return resize.min != resize.max;
1015              }              }
1016              if (!next_region || r->KeyRange.high + 1 != next_region->KeyRange.low) {              if (!next_region || r->KeyRange.high + 1 != next_region->KeyRange.low) {
1017                  int hi = int(w * (r->KeyRange.high + 1) / 128.0 + 0.5);                  int hi = key_to_x(r->KeyRange.high + 1, w);
1018                  if (x <= hi - 2) break;                  if (x <= hi - 2) break;
1019                  if (x < hi + 2) {                  if (x < hi + 2) {
1020                      // edit high limit                      // edit high limit
# Line 887  void RegionChooser::show_region_properti Line 1052  void RegionChooser::show_region_properti
1052      dialog.get_vbox()->pack_start(checkBoxKeygroup);      dialog.get_vbox()->pack_start(checkBoxKeygroup);
1053      checkBoxKeygroup.show();      checkBoxKeygroup.show();
1054      // add "Keygroup" spinbox      // add "Keygroup" spinbox
1055      Gtk::Adjustment adjustment(1, 1, pow(2,32));  #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
1056        Gtk::Adjustment adjustment(1, 1, 999);
1057      Gtk::SpinButton spinBox(adjustment);      Gtk::SpinButton spinBox(adjustment);
1058    #else
1059        Gtk::SpinButton spinBox(Gtk::Adjustment::create(1, 1, 999));
1060    #endif
1061      if (region->KeyGroup) spinBox.set_value(region->KeyGroup);      if (region->KeyGroup) spinBox.set_value(region->KeyGroup);
1062      dialog.get_vbox()->pack_start(spinBox);      dialog.get_vbox()->pack_start(spinBox);
1063      spinBox.show();      spinBox.show();
1064      // add OK and CANCEL buttons to the dialog      // add OK and CANCEL buttons to the dialog
1065      dialog.add_button(Gtk::Stock::OK, 0);      dialog.add_button(Gtk::Stock::OK, 0);
1066      dialog.add_button(Gtk::Stock::CANCEL, 1);      dialog.add_button(Gtk::Stock::CANCEL, 1);
1067        dialog.set_position(Gtk::WIN_POS_MOUSE);
1068      dialog.show_all_children();      dialog.show_all_children();
1069      if (!dialog.run()) { // OK selected ...      if (!dialog.run()) { // OK selected ...
1070          region->KeyGroup =          region->KeyGroup =

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

  ViewVC Help
Powered by ViewVC