/[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 1898 by persson, Sun May 10 09:35:56 2009 UTC revision 3131 by schoenebeck, Thu Apr 27 17:28:01 2017 UTC
# Line 1  Line 1 
1  /*  /*
2   * Copyright (C) 2006-2009 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 18  Line 18 
18   */   */
19    
20  #include "regionchooser.h"  #include "regionchooser.h"
21    
22  #include <algorithm>  #include <algorithm>
23    
24    #include <cairomm/context.h>
25    #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>
 #include <math.h>  
 #include <sstream>  
30    
31  #include "global.h"  #include "global.h"
32    #include "Settings.h"
33    #include "gfx/builtinpix.h"
34    
35  #define REGION_BLOCK_HEIGHT             20  #define REGION_BLOCK_HEIGHT             30
36  #define KEYBOARD_HEIGHT                 40  #define KEYBOARD_HEIGHT                 40
37    
38    struct RegionFeatures {
39        int sampleRefs;
40        int loops;
41    
42        RegionFeatures() {
43            sampleRefs = loops = 0;
44        }
45    };
46    
47    static RegionFeatures regionFeatures(gig::Region* rgn) {
48        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    }
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 37  void SortedRegions::update(gig::Instrume Line 61  void SortedRegions::update(gig::Instrume
61      // RegionChooser code needs a sorted list of regions.      // RegionChooser code needs a sorted list of regions.
62      regions.clear();      regions.clear();
63      if (instrument) {      if (instrument) {
64          for (gig::Region *r = instrument->GetFirstRegion() ;          for (gig::Region* r = instrument->GetFirstRegion() ;
65               r ;               r ;
66               r = instrument->GetNextRegion()) {               r = instrument->GetNextRegion()) {
67              regions.push_back(r);              regions.push_back(r);
# Line 52  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      Glib::RefPtr<Gdk::Colormap> colormap = get_default_colormap();      set_size_request(500, KEYBOARD_HEIGHT + REGION_BLOCK_HEIGHT);
95    
96        loadBuiltInPix();
97    
     red = Gdk::Color("#8070ff");  
     grey1 = Gdk::Color("#b0b0b0");  
     activeKeyColor = Gdk::Color("#ff0000");  
     white = Gdk::Color("#ffffff");  
     black = Gdk::Color("#000000");  
   
     colormap->alloc_color(red);  
     colormap->alloc_color(grey1);  
     colormap->alloc_color(activeKeyColor);  
     colormap->alloc_color(white);  
     colormap->alloc_color(black);  
98      instrument = 0;      instrument = 0;
99      region = 0;      region = 0;
100      resize.active = false;      resize.active = false;
# Line 84  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 104  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 157  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_region(key, key+1, 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_region(key, key+1, black);      invalidate_key(key);
     } else {  
         draw_region(key, key+1, key >= 21 && key <= 108 ? white : grey1);  
     }  
206      m_VirtKeybOffVelocityLabel.set_text(ToString(velocity));      m_VirtKeybOffVelocityLabel.set_text(ToString(velocity));
207  }  }
208    
 void RegionChooser::on_realize()  
 {  
     // We need to call the base on_realize()  
     Gtk::DrawingArea::on_realize();  
209    
210      // Now we can allocate any additional resources we need  #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
211      Glib::RefPtr<Gdk::Window> window = get_window();  bool RegionChooser::on_expose_event(GdkEventExpose* e) {
212      gc = Gdk::GC::create(window);      double clipx1 = e->area.x;
213      window->clear();      double clipx2 = e->area.x + e->area.width;
214        double clipy1 = e->area.y;
215        double clipy2 = e->area.y + e->area.height;
216    
217        const Cairo::RefPtr<Cairo::Context>& cr =
218            get_window()->create_cairo_context();
219    #if 0
220    }
221    #endif
222    #else
223    bool RegionChooser::on_draw(const Cairo::RefPtr<Cairo::Context>& cr) {
224        double clipx1, clipx2, clipy1, clipy2;
225        cr->get_clip_extents(clipx1, clipy1, clipx2, clipy2);
226    #endif
227    
228        cr->save();
229        cr->set_line_width(1);
230    
231    #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
232        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        if (clipy2 > h1) {
240            draw_keyboard(cr, clipx1, clipx2);
241        }
242    
243        if (clipy1 < h1 && instrument) {
244            draw_regions(cr, clipx1, clipx2);
245        }
246    
247        cr->restore();
248    
249        return true;
250  }  }
251    
252  bool RegionChooser::on_expose_event(GdkEventExpose* event)  void RegionChooser::draw_keyboard(const Cairo::RefPtr<Cairo::Context>& cr,
253  {                                    int clip_low, int clip_high) {
     Glib::RefPtr<Gdk::Window> window = get_window();  
     window->clear();  
254      const int h = KEYBOARD_HEIGHT;      const int h = KEYBOARD_HEIGHT;
255      const int w = get_width() - 1;      const int w = get_width() - 1;
256      const int bh = int(h * 0.55);      const int bh = int(h * 0.55);
257    
258      Glib::RefPtr<const Gdk::GC> black = get_style()->get_black_gc();      Gdk::Cairo::set_source_rgba(cr, black);
259      Glib::RefPtr<const Gdk::GC> white = get_style()->get_white_gc();      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      window->draw_rectangle(black, false, 0, h1, w, h - 1);      Gdk::Cairo::set_source_rgba(cr, black);
     gc->set_foreground(grey1);  
     int x1 = int(w * 20.5 / 128.0 + 0.5);  
     int x2 = int(w * 109.5 / 128.0 + 0.5);  
     window->draw_rectangle(gc, true, 1, h1 + 1,  
                            x1 - 1, h - 2);  
     window->draw_rectangle(white, true, x1 + 1, h1 + 1, x2 - x1 - 1, h - 2);  
     window->draw_rectangle(gc, true, x2 + 1, h1 + 1,  
                            w - x2 - 1, h - 2);  
     for (int i = 0 ; i < 128 ; i++) {  
         int note = (i + 3) % 12;  
         int x = int(w * i / 128.0 + 0.5);  
277    
278          if (note == 1 || note == 4 || note == 6 || note == 9 || note == 11) {      int clipkey1 = std::max(0, x_to_key_right(clip_low - 1, w));
279              int x2 = int(w * (i + 0.5) / 128.0 + 0.5);      int clipkey2 = std::min(x_to_key_right(clip_high - 1, w) + 1, 128);
280              window->draw_line(black, x2, h1 + bh, x2, h1 + h);  
281        for (int i = clipkey1 ; i < clipkey2 ; i++) {
282            int note = (i + 3) % 12;
283            int x = key_to_x(i, w);
284    
285              int x3 = int(w * (i + 1) / 128.0 + 0.5);          if (note == 1 || note == 4 || note == 6 ||
286              window->draw_rectangle(black, true, x, h1 + 1, x3 - x + 1, bh);              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) {          } else if (note == 3 || note == 8) {
298              window->draw_line(black, x, h1 + 1, x, h1 + h);              // 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          if (note == 3) draw_digit(i);  
304            if (key_pressed[i]) draw_key(cr, i);
305    
306            if (note == 3) draw_digit(cr, i);
307      }      }
308    }
309    
     if (instrument) {  
         int i = 0;  
         gig::Region *next_region;  
         int x3 = -1;  
         for (gig::Region *r = regions.first() ; r ; r = next_region) {  
310    
311              if (x3 < 0) x3 = int(w * (r->KeyRange.low) / 128.0 + 0.5);  void RegionChooser::draw_regions(const Cairo::RefPtr<Cairo::Context>& cr,
312              next_region = regions.next();                                   int clip_low, int clip_high) {
313              if (!next_region || r->KeyRange.high + 1 != next_region->KeyRange.low) {      const int w = get_width() - 1;
314                  int x2 = int(w * (r->KeyRange.high + 1) / 128.0 + 0.5);  
315                  window->draw_line(black, x3, 0, x2, 0);      Gdk::Cairo::set_source_rgba(cr, black);
316                  window->draw_line(black, x3, h1 - 1, x2, h1 - 1);      gig::Region* next_region;
317                  window->draw_line(black, x2, 1, x2, h1 - 2);      int x3 = -1;
318                  window->draw_rectangle(white, true, x3 + 1, 1, x2 - x3 - 1, h1 - 2);      for (gig::Region* r = regions.first() ; r ; r = next_region) {
319                  x3 = -1;          next_region = regions.next();
320              }  
321              i++;          if (x3 < 0) {
322          }              x3 = key_to_x(r->KeyRange.low, w);
323                if (x3 >= clip_high) break;
324          for (gig::Region *r = regions.first() ; r ; r = regions.next()) {          }
325              int x = int(w * (r->KeyRange.low) / 128.0 + 0.5);          if (!next_region ||
326              window->draw_line(black, x, 1, x, h1 - 2);              r->KeyRange.high + 1 != next_region->KeyRange.low ||
327          }              r == region || next_region == region) {
328    
329          if (region) {              int x2 = key_to_x(r->KeyRange.high + 1, w);
330              int x1 = int(w * (region->KeyRange.low) / 128.0 + 0.5);              if (x2 >= clip_low) {
331              int x2 = int(w * (region->KeyRange.high + 1) / 128.0 + 0.5);                  cr->move_to(x3, 0.5);
332              gc->set_foreground(red);                  cr->line_to(x2 + 0.5, 0.5);
333              window->draw_rectangle(gc, true, x1 + 1, 1, x2 - x1 - 1, h1 - 2);                  cr->line_to(x2 + 0.5, h1 - 0.5);
334                    cr->line_to(x3, h1 - 0.5);
335                    cr->stroke();
336    
337                    Gdk::Cairo::set_source_rgba(cr, region == r ? blue : white);
338                    cr->rectangle(x3 + 1, 1, x2 - x3 - 1, h1 - 2);
339                    cr->fill();
340                    Gdk::Cairo::set_source_rgba(cr, black);
341                }
342                x3 = -1;
343          }          }
344      }      }
     return true;  
 }  
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            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  void RegionChooser::on_size_request(GtkRequisition* requisition)      for (gig::Region* r = regions.first() ; r ; r = regions.next()) {
388  {          int x = key_to_x(r->KeyRange.low, w);
389      *requisition = GtkRequisition();  
390      requisition->height = KEYBOARD_HEIGHT + REGION_BLOCK_HEIGHT;          if (x < clip_low) continue;
391      requisition->width = 500;          if (x >= clip_high) break;
392    
393            cr->move_to(x + 0.5, 1);
394            cr->line_to(x + 0.5, h1 - 1);
395            cr->stroke();
396        }
397    
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 277  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 288  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      get_window()->draw_layout(get_style()->get_black_gc(), int(x - text_w / 2 + 1),      Gdk::Cairo::set_source_rgba(cr, black);
440                                int(h1 + h - text_h + 0.5), layout);      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
442        pango_cairo_show_layout(cr->cobj(), layout->gobj());
443    #else
444        layout->show_in_cairo_context(cr);
445    #endif
446  }  }
447    
448  void RegionChooser::draw_region(int from, int to, 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      Glib::RefPtr<Gdk::Window> window = get_window();      Gdk::Cairo::set_source_rgba(cr, activeKeyColor);
     gc->set_foreground(color);  
455    
456      for (int i = from ; i < to ; i++) {      int note = (key + 3) % 12;
457          int note = (i + 3) % 12;      int x = key_to_x(key, w) + 1;
458          int x = int(w * i / 128.0 + 0.5) + 1;      int x2 = key_to_x(key + 1.5, w);
459          int x2 = int(w * (i + 1.5) / 128.0 + 0.5);      int x3 = key_to_x(key + 1, w);
460          int x3 = int(w * (i + 1) / 128.0 + 0.5);      int x4 = key_to_x(key - 0.5, w);
461          int x4 = int(w * (i - 0.5) / 128.0 + 0.5);      int w1 = x3 - x;
462          int w1 = x3 - x;      switch (note) {
463          switch (note) {      case 0: case 5: case 10:
464          case 0: case 5: case 10:          cr->rectangle(x, h1 + 1, w1, bh);
465              window->draw_rectangle(gc, true, x, h1 + 1, w1, bh);          cr->fill();
466              window->draw_rectangle(gc, true, x4 + 1, h1 + bh + 1, x2 - x4 - 1, h - bh - 2);          cr->rectangle(x4 + 1, h1 + bh + 1, x2 - x4 - 1, h - bh - 2);
467              break;          cr->fill();
468          case 2: case 7:          break;
469              window->draw_rectangle(gc, true, x, h1 + 1, w1, bh);      case 2: case 7:
470              window->draw_rectangle(gc, true, x4 + 1, h1 + bh + 1, x3 - x4 - 1, h - bh - 2);          cr->rectangle(x, h1 + 1, w1, bh);
471              break;          cr->fill();
472          case 3: case 8:          cr->rectangle(x4 + 1, h1 + bh + 1, x3 - x4 - 1, h - bh - 2);
473              window->draw_rectangle(gc, true, x, h1 + 1, w1, bh);          cr->fill();
474              window->draw_rectangle(gc, true, x, h1 + bh + 1, x2 - x, h - bh - 2);          break;
475              if (note == 3) draw_digit(i);      case 3: case 8:
476              break;          cr->rectangle(x, h1 + 1, w1, bh);
477          default:          cr->fill();
478              window->draw_rectangle(gc, true, x, h1 + 1, w1, bh - 1);          cr->rectangle(x, h1 + bh + 1, x2 - x, h - bh - 2);
479              break;          cr->fill();
480          }          break;
481        default:
482            cr->rectangle(x, h1 + 1, w1, bh - 1);
483            cr->fill();
484            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 341  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 364  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);
560                resize.region->SetKeyRange(resize.region->KeyRange.low,
561                                           resize.pos - 1);
562                regions.update(instrument);
563                instrument_changed.emit();
564                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);              instrument_struct_to_be_changed_signal.emit(instrument);
569              region->SetKeyRange(              resize.region->SetKeyRange(resize.pos,
570                  region->KeyRange.low  + move.pos,                                         resize.region->KeyRange.high);
                 region->KeyRange.high + move.pos  
             );  
571              regions.update(instrument);              regions.update(instrument);
572              instrument_changed.emit();              instrument_changed.emit();
573              instrument_struct_changed_signal.emit(instrument);              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 433  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 448  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 462  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 478  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;
     Glib::RefPtr<Gdk::Window> window = get_window();  
759    
760      int k = int(double(x) / w * 128.0 + 0.5);      int k = int(double(x) / w * 128.0 + 0.5);
761    
# Line 517  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          Glib::RefPtr<const Gdk::GC> black = get_style()->get_black_gc();          resize.pos = k;
         Glib::RefPtr<const Gdk::GC> white = get_style()->get_white_gc();  
         if (region == resize.region) {  
             gc->set_foreground(red);  
             white = gc;  
         }  
         Glib::RefPtr<const Gdk::GC> bg = get_style()->get_bg_gc(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                  window->draw_rectangle(white, true, prevx, 1, x - prevx, h1 - 2);                  x1 = resize.region->KeyRange.high;
784                  window->draw_line(black, prevx, 0, x, 0);                  x2 = resize.pos - 1;
                 window->draw_line(black, prevx, h1 - 1, x, h1 - 1);  
785              } else {              } else {
786                  int xx = ((resize.pos == resize.max && resize.max != 128) ? 1 : 0);                  x1 = resize.pos - 1;
787                  window->draw_rectangle(bg, true, x + 1, 0, prevx - x - xx, h1);                  x2 = resize.region->KeyRange.high;
788              }              }
789          } else {          } else {
790              if (k < resize.pos) {              if (resize.region->KeyRange.low < resize.pos) {
791                  window->draw_rectangle(white, true, x + 1, 1, prevx - x, h1 - 2);                  x1 = resize.region->KeyRange.low;
792                  window->draw_line(black, x, 0, prevx, 0);                  x2 = resize.pos;
                 window->draw_line(black, x, h1 - 1, prevx, h1 - 1);  
793              } else {              } else {
794                  int xx = ((resize.pos == resize.min && resize.min != 0) ? 1 : 0);                  x1 = resize.pos;
795                  window->draw_rectangle(bg, true, prevx + xx, 0, x - prevx - xx, h1);                  x2 = resize.region->KeyRange.low;
796              }              }
797          }          }
798          window->draw_line(black, x, 1, x, h1 - 2);          x1 = key_to_x(x1, w);
799          resize.pos = k;          x2 = key_to_x(x2 + 1, w) + 1;
800            Gdk::Rectangle rect(x1, 0, x2 - x1, h1);
801    
802            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;
     Glib::RefPtr<Gdk::Window> window = get_window();  
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 599  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 624  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      Glib::RefPtr<const Gdk::GC> bg = get_style()->get_bg_gc(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);  
     Glib::RefPtr<const Gdk::GC> black = get_style()->get_black_gc();  
     gc->set_foreground(red);  
   
     if (!new_touch_left) window->draw_line(black, x, 1, x, h1 - 2);  
     if (!new_touch_right) window->draw_line(black, x2, 1, x2, h1 - 2);  
   
     if (k > move.pos) {  
         window->draw_rectangle(bg, true, prevx + (move.touch_left ? 1 : 0), 0,  
                                std::min(x, prevx2 + 1 - (move.touch_right ? 1 : 0)) -  
                                (prevx + (move.touch_left ? 1 : 0)), h1);  
   
         window->draw_line(black, std::max(x, prevx2 + 1), 0, x2, 0);  
         window->draw_line(black, std::max(x, prevx2 + 1), h1 - 1, x2, h1 - 1);  
         window->draw_rectangle(gc, true, std::max(x + 1, prevx2), 1,  
                                x2 - std::max(x + 1, prevx2), h1 - 2);  
     } else {  
         window->draw_rectangle(bg, true, 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);  
   
         window->draw_line(black, x, 0, std::min(x2, prevx - 1), 0);  
         window->draw_line(black, x, h1 - 1, std::min(x2, prevx - 1), h1 - 1);  
882    
883          window->draw_rectangle(gc, true, x + 1, 1, std::min(x2 - 1, prevx) - x, h1 - 2);      Gdk::Rectangle rect(x1, 0, x2 - x1, h1);
884      }      update_after_move(new_l);
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 677  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 697  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 718  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 741  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 779  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.1898  
changed lines
  Added in v.3131

  ViewVC Help
Powered by ViewVC