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

Legend:
Removed from v.1898  
changed lines
  Added in v.3148

  ViewVC Help
Powered by ViewVC