/[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 2169 by persson, Sun Mar 6 07:51:04 2011 UTC revision 3307 by schoenebeck, Tue Jul 11 23:06:38 2017 UTC
# Line 1  Line 1 
1  /*  /*
2   * Copyright (C) 2006-2011 Andreas Persson   * Copyright (C) 2006-2017 Andreas Persson
3   *   *
4   * This program is free software; you can redistribute it and/or   * This program is free software; you can redistribute it and/or
5   * modify it under the terms of the GNU General Public License as   * modify it under the terms of the GNU General Public License as
# Line 17  Line 17 
17   * 02110-1301 USA.   * 02110-1301 USA.
18   */   */
19    
20    #include "global.h"
21  #include "regionchooser.h"  #include "regionchooser.h"
22    
23  #include <algorithm>  #include <algorithm>
24  #include <sstream>  #include <assert.h>
25    
26  #include <cairomm/context.h>  #include <cairomm/context.h>
27  #include <gdkmm/general.h>  #include <gdkmm/general.h>
28  #include <gdkmm/cursor.h>  #include <gdkmm/cursor.h>
29  #include <gtkmm/stock.h>  #include <gtkmm/stock.h>
30    #include <gdkmm/pixbuf.h>
31  #include <gtkmm/spinbutton.h>  #include <gtkmm/spinbutton.h>
32  #include <gtkmm/dialog.h>  #include <gtkmm/dialog.h>
33    
34  #include "global.h"  #include "Settings.h"
35    #include "gfx/builtinpix.h"
36    
37  #define REGION_BLOCK_HEIGHT             20  #define REGION_BLOCK_HEIGHT             30
38  #define KEYBOARD_HEIGHT                 40  #define KEYBOARD_HEIGHT                 40
39    
40    struct RegionFeatures {
41        int sampleRefs;
42        int loops;
43        int validDimRegs;
44    
45        RegionFeatures() {
46            sampleRefs = loops = validDimRegs = 0;
47        }
48    };
49    
50    static RegionFeatures regionFeatures(gig::Region* rgn) {
51        RegionFeatures f;
52        for (int i = 0; i < rgn->DimensionRegions; ++i) {
53            gig::DimensionRegion* dr = rgn->pDimensionRegions[i];
54            DimensionCase c = dimensionCaseOf(dr);
55            if (!isUsedCase(c, rgn)) continue;
56            f.validDimRegs++;
57            if (dr->pSample) f.sampleRefs++;
58            // the user doesn't care about loop if there is no valid sample reference
59            if (dr->pSample && dr->SampleLoops) f.loops++;
60        }
61        return f;
62    }
63    
64  void SortedRegions::update(gig::Instrument* instrument) {  void SortedRegions::update(gig::Instrument* instrument) {
65      // 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 55  gig::Region* SortedRegions::first() { Line 82  gig::Region* SortedRegions::first() {
82  }  }
83    
84  gig::Region* SortedRegions::next() {  gig::Region* SortedRegions::next() {
85      region_iterator++;      ++region_iterator;
86      return region_iterator == regions.end() ? 0 : *region_iterator;      return region_iterator == regions.end() ? 0 : *region_iterator;
87  }  }
88    
# Line 63  gig::Region* SortedRegions::next() { Line 90  gig::Region* SortedRegions::next() {
90    
91  RegionChooser::RegionChooser() :  RegionChooser::RegionChooser() :
92      activeKeyColor("red"),      activeKeyColor("red"),
93      red("#8070ff"),      blue("#4796ff"),
94      grey1("grey69"),      grey1("grey69"),
95      white("white"),      white("white"),
96      black("black"),      black("black"),
97      m_VirtKeybModeChoice(_("Virtual Keyboard Mode")),      m_VirtKeybModeChoice(_("Virtual Keyboard Mode")),
98      currentActiveKey(-1)      currentActiveKey(-1),
99        modifyallregions(false)
100  {  {
101      set_size_request(500, KEYBOARD_HEIGHT + REGION_BLOCK_HEIGHT);      set_size_request(500, KEYBOARD_HEIGHT + REGION_BLOCK_HEIGHT);
102    
103        loadBuiltInPix();
104    
105        // create blue hatched pattern
106        {
107            const int width = blueHatchedPattern->get_width();
108            const int height = blueHatchedPattern->get_height();
109            const int stride = blueHatchedPattern->get_rowstride();
110    
111            // manually convert from RGBA to ARGB
112            this->blueHatchedPatternARGB = blueHatchedPattern->copy();
113            const int pixelSize = stride / width;
114            const int totalPixels = width * height;
115            assert(pixelSize == 4);
116            unsigned char* ptr = this->blueHatchedPatternARGB->get_pixels();
117            for (int iPixel = 0; iPixel < totalPixels; ++iPixel, ptr += pixelSize) {
118                const unsigned char r = ptr[0];
119                const unsigned char g = ptr[1];
120                const unsigned char b = ptr[2];
121                const unsigned char a = ptr[3];
122                ptr[0] = b;
123                ptr[1] = g;
124                ptr[2] = r;
125                ptr[3] = a;
126            }
127    
128            Cairo::RefPtr<Cairo::ImageSurface> imageSurface = Cairo::ImageSurface::create(
129                this->blueHatchedPatternARGB->get_pixels(), Cairo::FORMAT_ARGB32, width, height, stride
130            );
131            this->blueHatchedSurfacePattern = Cairo::SurfacePattern::create(imageSurface);
132            this->blueHatchedSurfacePattern->set_extend(Cairo::EXTEND_REPEAT);
133        }
134    
135      instrument = 0;      instrument = 0;
136      region = 0;      region = 0;
137      resize.active = false;      resize.active = false;
# Line 81  RegionChooser::RegionChooser() : Line 141  RegionChooser::RegionChooser() :
141    
142      // properties of the virtual keyboard      // properties of the virtual keyboard
143      {      {
144          const char* choices[] = { _("normal"), _("chord"), NULL };          const char* choices[] = { _("normal"), _("chord"), 0 };
145          static const virt_keyboard_mode_t values[] = {          static const virt_keyboard_mode_t values[] = {
146              VIRT_KEYBOARD_MODE_NORMAL,              VIRT_KEYBOARD_MODE_NORMAL,
147              VIRT_KEYBOARD_MODE_CHORD              VIRT_KEYBOARD_MODE_CHORD
# Line 101  RegionChooser::RegionChooser() : Line 161  RegionChooser::RegionChooser() :
161      m_VirtKeybPropsBox.pack_start(m_VirtKeybOffVelocityLabel, Gtk::PACK_SHRINK);      m_VirtKeybPropsBox.pack_start(m_VirtKeybOffVelocityLabel, Gtk::PACK_SHRINK);
162      m_VirtKeybPropsBox.set_spacing(10);      m_VirtKeybPropsBox.set_spacing(10);
163      m_VirtKeybPropsBox.show();      m_VirtKeybPropsBox.show();
164        for (int i = 0 ; i < 128 ; i++) key_pressed[i] = false;
165    
166      actionGroup = Gtk::ActionGroup::create();      actionGroup = Gtk::ActionGroup::create();
167      actionGroup->add(Gtk::Action::create("Properties",      actionGroup->add(Gtk::Action::create("Properties",
# Line 154  RegionChooser::RegionChooser() : Line 215  RegionChooser::RegionChooser() :
215      keyboard_key_released_signal.connect(      keyboard_key_released_signal.connect(
216          sigc::mem_fun(*this, &RegionChooser::on_note_off_event)          sigc::mem_fun(*this, &RegionChooser::on_note_off_event)
217      );      );
218        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."));
219  }  }
220    
221  RegionChooser::~RegionChooser()  RegionChooser::~RegionChooser()
222  {  {
223  }  }
224    
225  template<class T> inline std::string ToString(T o) {  void RegionChooser::setModifyAllRegions(bool b) {
226      std::stringstream ss;      modifyallregions = b;
227      ss << o;      // redraw required parts
228      return ss.str();      queue_draw();
229    }
230    
231    void RegionChooser::invalidate_key(int key) {
232        const int h = KEYBOARD_HEIGHT;
233        const int w = get_width() - 1;
234        int x1 = key_to_x(key - 0.5, w);
235        int x2 = key_to_x(key + 1.5, w);
236    
237        Gdk::Rectangle rect(x1 + 1, h1 + 1, x2 - x1 - 1, h - 2);
238        get_window()->invalidate_rect(rect, false);
239  }  }
240    
241  void RegionChooser::on_note_on_event(int key, int velocity) {  void RegionChooser::on_note_on_event(int key, int velocity) {
242      draw_key(key, activeKeyColor);      key_pressed[key] = true;
243        invalidate_key(key);
244      m_VirtKeybVelocityLabel.set_text(ToString(velocity));      m_VirtKeybVelocityLabel.set_text(ToString(velocity));
245  }  }
246    
247  void RegionChooser::on_note_off_event(int key, int velocity) {  void RegionChooser::on_note_off_event(int key, int velocity) {
248      if (is_black_key(key)) {      key_pressed[key] = false;
249          draw_key(key, black);      invalidate_key(key);
     } else {  
         draw_key(key, key >= 21 && key <= 108 ? white : grey1);  
     }  
250      m_VirtKeybOffVelocityLabel.set_text(ToString(velocity));      m_VirtKeybOffVelocityLabel.set_text(ToString(velocity));
251  }  }
252    
253    
254  #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2  #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
255  bool RegionChooser::on_expose_event(GdkEventExpose* e)  bool RegionChooser::on_expose_event(GdkEventExpose* e) {
256  {      double clipx1 = e->area.x;
257      return on_draw(get_window()->create_cairo_context());      double clipx2 = e->area.x + e->area.width;
258        double clipy1 = e->area.y;
259        double clipy2 = e->area.y + e->area.height;
260    
261        const Cairo::RefPtr<Cairo::Context>& cr =
262            get_window()->create_cairo_context();
263    #if 0
264  }  }
265  #endif  #endif
266    #else
267  bool RegionChooser::on_draw(const Cairo::RefPtr<Cairo::Context>& cr)  bool RegionChooser::on_draw(const Cairo::RefPtr<Cairo::Context>& cr) {
268  {      double clipx1, clipx2, clipy1, clipy2;
269      const int h = KEYBOARD_HEIGHT;      cr->get_clip_extents(clipx1, clipy1, clipx2, clipy2);
270      const int w = get_width() - 1;  #endif
     const int bh = int(h * 0.55);  
271    
272      cr->save();      cr->save();
273      cr->set_line_width(1);      cr->set_line_width(1);
# Line 204  bool RegionChooser::on_draw(const Cairo: Line 280  bool RegionChooser::on_draw(const Cairo:
280      Gdk::Cairo::set_source_rgba(cr, bg);      Gdk::Cairo::set_source_rgba(cr, bg);
281      cr->paint();      cr->paint();
282    
283        if (clipy2 > h1) {
284            draw_keyboard(cr, clipx1, clipx2);
285        }
286    
287        if (clipy1 < h1 && instrument) {
288            draw_regions(cr, clipx1, clipx2);
289        }
290    
291        cr->restore();
292    
293        return true;
294    }
295    
296    void RegionChooser::draw_keyboard(const Cairo::RefPtr<Cairo::Context>& cr,
297                                      int clip_low, int clip_high) {
298        const int h = KEYBOARD_HEIGHT;
299        const int w = get_width() - 1;
300        const int bh = int(h * 0.55);
301    
302      Gdk::Cairo::set_source_rgba(cr, black);      Gdk::Cairo::set_source_rgba(cr, black);
303      cr->rectangle(0.5, h1 + 0.5, w, h - 1);      cr->rectangle(0.5, h1 + 0.5, w, h - 1);
304      cr->stroke();      cr->stroke();
305    
306      int x1 = int(w * 20.5 / 128.0 + 0.5);      int x1 = key_to_x(20.5, w);
     int x2 = int(w * 109.5 / 128.0 + 0.5);  
   
307      Gdk::Cairo::set_source_rgba(cr, grey1);      Gdk::Cairo::set_source_rgba(cr, grey1);
308      cr->rectangle(1, h1 + 1, x1 - 1, h - 2);      cr->rectangle(1, h1 + 1, x1 - 1, h - 2);
309      cr->fill();      cr->fill();
310    
311        int x2 = key_to_x(109.5, w);
312      Gdk::Cairo::set_source_rgba(cr, white);      Gdk::Cairo::set_source_rgba(cr, white);
313      cr->rectangle(x1 + 1, h1 + 1, x2 - x1 - 1, h - 2);      cr->rectangle(x1 + 1, h1 + 1, x2 - x1 - 1, h - 2);
314      cr->fill();      cr->fill();
# Line 224  bool RegionChooser::on_draw(const Cairo: Line 318  bool RegionChooser::on_draw(const Cairo:
318      cr->fill();      cr->fill();
319    
320      Gdk::Cairo::set_source_rgba(cr, black);      Gdk::Cairo::set_source_rgba(cr, black);
321      for (int i = 0 ; i < 128 ; i++) {  
322        int clipkey1 = std::max(0, x_to_key_right(clip_low - 1, w));
323        int clipkey2 = std::min(x_to_key_right(clip_high - 1, w) + 1, 128);
324    
325        for (int i = clipkey1 ; i < clipkey2 ; i++) {
326          int note = (i + 3) % 12;          int note = (i + 3) % 12;
327          int x = int(w * i / 128.0 + 0.5);          int x = key_to_x(i, w);
328    
329          if (note == 1 || note == 4 || note == 6 ||          if (note == 1 || note == 4 || note == 6 ||
330              note == 9 || note == 11) {              note == 9 || note == 11) {
331              int x2 = int(w * (i + 0.5) / 128.0 + 0.5);              // black key: short line in the middle, with a rectangle
332                // on top
333                int x2 = key_to_x(i + 0.5, w);
334              cr->move_to(x2 + 0.5, h1 + bh + 0.5);              cr->move_to(x2 + 0.5, h1 + bh + 0.5);
335              cr->line_to(x2 + 0.5, h1 + h - 1);              cr->line_to(x2 + 0.5, h1 + h - 1);
336              cr->stroke();              cr->stroke();
337    
338              int x3 = int(w * (i + 1) / 128.0 + 0.5);              int x3 = key_to_x(i + 1, w);
339              cr->rectangle(x, h1 + 1, x3 - x + 1, bh);              cr->rectangle(x, h1 + 1, x3 - x + 1, bh);
340              cr->fill();              cr->fill();
341          } else if (note == 3 || note == 8) {          } else if (note == 3 || note == 8) {
342                // C or F: long line to the left
343              cr->move_to(x + 0.5, h1 + 1);              cr->move_to(x + 0.5, h1 + 1);
344              cr->line_to(x + 0.5, h1 + h - 1);              cr->line_to(x + 0.5, h1 + h - 1);
345              cr->stroke();              cr->stroke();
   
             if (note == 3) draw_digit(i);  
346          }          }
347    
348            if (key_pressed[i]) draw_key(cr, i);
349    
350            if (note == 3) draw_digit(cr, i);
351      }      }
352    }
353    
     if (instrument) {  
         int i = 0;  
         gig::Region* next_region;  
         int x3 = -1;  
         for (gig::Region* r = regions.first() ; r ; r = next_region) {  
354    
355              if (x3 < 0) x3 = int(w * (r->KeyRange.low) / 128.0 + 0.5);  void RegionChooser::draw_regions(const Cairo::RefPtr<Cairo::Context>& cr,
356              next_region = regions.next();                                   int clip_low, int clip_high) {
357              if (!next_region ||      const int w = get_width() - 1;
358                  r->KeyRange.high + 1 != next_region->KeyRange.low) {  
359                  int x2 = int(w * (r->KeyRange.high + 1) / 128.0 + 0.5);      Gdk::Cairo::set_source_rgba(cr, black);
360        gig::Region* next_region;
361        int x3 = -1;
362        for (gig::Region* r = regions.first() ; r ; r = next_region) {
363            next_region = regions.next();
364    
365            if (x3 < 0) {
366                x3 = key_to_x(r->KeyRange.low, w);
367                if (x3 >= clip_high) break;
368            }
369            if (!next_region ||
370                r->KeyRange.high + 1 != next_region->KeyRange.low ||
371                r == region || next_region == region) {
372    
373                int x2 = key_to_x(r->KeyRange.high + 1, w);
374                if (x2 >= clip_low) {
375                  cr->move_to(x3, 0.5);                  cr->move_to(x3, 0.5);
376                  cr->line_to(x2 + 0.5, 0.5);                  cr->line_to(x2 + 0.5, 0.5);
377                  cr->line_to(x2 + 0.5, h1 - 0.5);                  cr->line_to(x2 + 0.5, h1 - 0.5);
378                  cr->line_to(x3, h1 - 0.5);                  cr->line_to(x3, h1 - 0.5);
379                  cr->stroke();                  cr->stroke();
380    
381                  Gdk::Cairo::set_source_rgba(cr, white);                  if (region == r)
382                        Gdk::Cairo::set_source_rgba(cr, blue);
383                    else if (modifyallregions)
384                        cr->set_source(blueHatchedSurfacePattern);
385                    else
386                        Gdk::Cairo::set_source_rgba(cr, white);
387    
388                  cr->rectangle(x3 + 1, 1, x2 - x3 - 1, h1 - 2);                  cr->rectangle(x3 + 1, 1, x2 - x3 - 1, h1 - 2);
389                  cr->fill();                  cr->fill();
390                  Gdk::Cairo::set_source_rgba(cr, black);                  Gdk::Cairo::set_source_rgba(cr, black);
   
                 x3 = -1;  
391              }              }
392              i++;              x3 = -1;
         }  
   
         for (gig::Region* r = regions.first() ; r ; r = regions.next()) {  
             int x = int(w * (r->KeyRange.low) / 128.0 + 0.5);  
             cr->move_to(x + 0.5, 1);  
             cr->line_to(x + 0.5, h1 - 1);  
             cr->stroke();  
393          }          }
394        }
395    
396          if (region) {      for (gig::Region* r = regions.first() ; r ; r = regions.next()) {
397              int x1 = int(w * (region->KeyRange.low) / 128.0 + 0.5);          int x = key_to_x(r->KeyRange.low, w);
398              int x2 = int(w * (region->KeyRange.high + 1) / 128.0 + 0.5);          int x2 = key_to_x(r->KeyRange.high + 1, w);
399              Gdk::Cairo::set_source_rgba(cr, red);  
400              cr->rectangle(x1 + 1, 1, x2 - x1 - 1, h1 - 2);          RegionFeatures features = regionFeatures(r);
401              cr->fill();  
402            const bool bShowLoopSymbol = features.loops > 0;
403            const bool bShowSampleRefSymbol = features.sampleRefs < features.validDimRegs;
404            if (bShowLoopSymbol || bShowSampleRefSymbol) {
405                const int margin = 2;
406                const int wRgn = x2 - x;
407                //printf("x=%d x2=%d wRgn=%d\n", x, x2, wRgn);
408    
409                cr->save();
410                cr->set_line_width(1);
411                cr->rectangle(x, 1, wRgn, h1 - 1);
412                cr->clip();
413                if (bShowSampleRefSymbol) {
414                    const int wPic = 8;
415                    const int hPic = 8;
416                    Gdk::Cairo::set_source_pixbuf(
417                        cr, (features.sampleRefs) ? yellowDot : redDot,
418                        x + (wRgn-wPic)/2.f,
419                        (bShowLoopSymbol) ? margin : (h1-hPic)/2.f
420                    );
421                    cr->paint();
422                }
423                if (bShowLoopSymbol) {
424                    const int wPic = 12;
425                    const int hPic = 14;
426                    Gdk::Cairo::set_source_pixbuf(
427                        cr, (features.loops == features.validDimRegs) ? blackLoop : grayLoop,
428                        x + (wRgn-wPic)/2.f,
429                        (bShowSampleRefSymbol) ? h1 - hPic - margin : (h1-hPic)/2.f
430                    );
431                    cr->paint();
432                }
433                cr->restore();
434          }          }
435      }      }
436    
437      cr->restore();      for (gig::Region* r = regions.first() ; r ; r = regions.next()) {
438            int x = key_to_x(r->KeyRange.low, w);
439    
440      return true;          if (x < clip_low) continue;
441  }          if (x >= clip_high) break;
442    
443            cr->move_to(x + 0.5, 1);
444            cr->line_to(x + 0.5, h1 - 1);
445            cr->stroke();
446        }
447    
448        // if there is no region yet, show the user some hint text that he may
449        // right click on this area to create a new region
450        if (!regions.first()) {
451            Glib::RefPtr<Pango::Context> context = get_pango_context();
452            Glib::RefPtr<Pango::Layout> layout = Pango::Layout::create(context);
453            layout->set_alignment(Pango::ALIGN_CENTER);
454            layout->set_text(Glib::ustring("*** ") + _("Right click here to create a region.") + " ***");
455            layout->set_width(get_width() * Pango::SCALE);
456            //layout->set_height(get_height() * Pango::SCALE);
457            layout->set_spacing(10);
458            Gdk::Cairo::set_source_rgba(cr, blue);
459            // get the text dimensions
460            int text_width, text_height;
461            layout->get_pixel_size(text_width, text_height);
462            cr->move_to(0, (REGION_BLOCK_HEIGHT - text_height) / 2);
463    #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 16) || GTKMM_MAJOR_VERSION < 2
464            pango_cairo_show_layout(cr->cobj(), layout->gobj());
465    #else
466            layout->show_in_cairo_context(cr);
467    #endif
468        }
469    }
470    
471  bool RegionChooser::is_black_key(int key) {  bool RegionChooser::is_black_key(int key) {
472      const int note = (key + 3) % 12;      const int note = (key + 3) % 12;
473      return note == 1 || note == 4 || note == 6 || note == 9 || note == 11;      return note == 1 || note == 4 || note == 6 || note == 9 || note == 11;
474  }  }
475    
476  void RegionChooser::draw_digit(int key) {  void RegionChooser::draw_digit(const Cairo::RefPtr<Cairo::Context>& cr,
477                                   int key) {
478      const int h = KEYBOARD_HEIGHT;      const int h = KEYBOARD_HEIGHT;
479      const int w = get_width() - 1;      const int w = get_width() - 1;
480      Glib::RefPtr<Pango::Layout> layout = Pango::Layout::create(get_pango_context());      Glib::RefPtr<Pango::Layout> layout =
481            Pango::Layout::create(get_pango_context());
482      char buf[30];      char buf[30];
483      sprintf(buf, "<span size=\"8000\">%d</span>", key / 12 - 1);      sprintf(buf, "<span size=\"8000\">%d</span>", key / 12 - 1);
484      layout->set_markup(buf);      layout->set_markup(buf);
# Line 312  void RegionChooser::draw_digit(int key) Line 486  void RegionChooser::draw_digit(int key)
486      double text_w = double(rectangle.get_width()) / Pango::SCALE;      double text_w = double(rectangle.get_width()) / Pango::SCALE;
487      double text_h = double(rectangle.get_height()) / Pango::SCALE;      double text_h = double(rectangle.get_height()) / Pango::SCALE;
488      double x = w * (key + 0.75) / 128.0;      double x = w * (key + 0.75) / 128.0;
     Cairo::RefPtr<Cairo::Context> cr = get_window()->create_cairo_context();  
489      Gdk::Cairo::set_source_rgba(cr, black);      Gdk::Cairo::set_source_rgba(cr, black);
490      cr->move_to(int(x - text_w / 2 + 1), int(h1 + h - text_h + 0.5));      cr->move_to(int(x - text_w / 2 + 1), int(h1 + h - text_h + 0.5));
491  #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 16) || GTKMM_MAJOR_VERSION < 2  #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 16) || GTKMM_MAJOR_VERSION < 2
# Line 322  void RegionChooser::draw_digit(int key) Line 495  void RegionChooser::draw_digit(int key)
495  #endif  #endif
496  }  }
497    
498  void RegionChooser::draw_key(int key, const Gdk::RGBA& color)  void RegionChooser::draw_key(const Cairo::RefPtr<Cairo::Context>& cr,
499  {                               int key) {
500      const int h = KEYBOARD_HEIGHT;      const int h = KEYBOARD_HEIGHT;
501      const int w = get_width() - 1;      const int w = get_width() - 1;
502      const int bh = int(h * 0.55);      const int bh = int(h * 0.55);
503    
504      Cairo::RefPtr<Cairo::Context> cr = get_window()->create_cairo_context();      Gdk::Cairo::set_source_rgba(cr, activeKeyColor);
     Gdk::Cairo::set_source_rgba(cr, color);  
505    
506      int note = (key + 3) % 12;      int note = (key + 3) % 12;
507      int x = int(w * key / 128.0 + 0.5) + 1;      int x = key_to_x(key, w) + 1;
508      int x2 = int(w * (key + 1.5) / 128.0 + 0.5);      int x2 = key_to_x(key + 1.5, w);
509      int x3 = int(w * (key + 1) / 128.0 + 0.5);      int x3 = key_to_x(key + 1, w);
510      int x4 = int(w * (key - 0.5) / 128.0 + 0.5);      int x4 = key_to_x(key - 0.5, w);
511      int w1 = x3 - x;      int w1 = x3 - x;
512      switch (note) {      switch (note) {
513      case 0: case 5: case 10:      case 0: case 5: case 10:
# Line 355  void RegionChooser::draw_key(int key, co Line 527  void RegionChooser::draw_key(int key, co
527          cr->fill();          cr->fill();
528          cr->rectangle(x, h1 + bh + 1, x2 - x, h - bh - 2);          cr->rectangle(x, h1 + bh + 1, x2 - x, h - bh - 2);
529          cr->fill();          cr->fill();
         if (note == 3) draw_digit(key);  
530          break;          break;
531      default:      default:
532          cr->rectangle(x, h1 + 1, w1, bh - 1);          cr->rectangle(x, h1 + 1, w1, bh - 1);
533          cr->fill();          cr->fill();
534          break;          break;
535      }      }
536        Gdk::Cairo::set_source_rgba(cr, black);
537  }  }
538    
539  void RegionChooser::set_instrument(gig::Instrument* instrument)  void RegionChooser::set_instrument(gig::Instrument* instrument)
# Line 376  void RegionChooser::set_instrument(gig:: Line 548  void RegionChooser::set_instrument(gig::
548    
549  bool RegionChooser::on_button_release_event(GdkEventButton* event)  bool RegionChooser::on_button_release_event(GdkEventButton* event)
550  {  {
551      const int k = int(event->x / (get_width() - 1) * 128.0);      const int k = x_to_key(event->x, get_width() - 1);
552    
553      // handle-note off on virtual keyboard      // handle-note off on virtual keyboard
554      if (event->type == GDK_BUTTON_RELEASE) {      if (event->type == GDK_BUTTON_RELEASE) {
# Line 406  bool RegionChooser::on_button_release_ev Line 578  bool RegionChooser::on_button_release_ev
578  #endif  #endif
579          resize.active = false;          resize.active = false;
580    
         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);  
             }  
         }  
   
581          if (!is_in_resize_zone(event->x, event->y) && cursor_is_resize) {          if (!is_in_resize_zone(event->x, event->y) && cursor_is_resize) {
582              get_window()->set_cursor();              get_window()->set_cursor();
583              cursor_is_resize = false;              cursor_is_resize = false;
# Line 442  bool RegionChooser::on_button_release_ev Line 590  bool RegionChooser::on_button_release_ev
590  #endif  #endif
591          move.active = false;          move.active = false;
592    
         if (move.pos) {  
             instrument_struct_to_be_changed_signal.emit(instrument);  
             region->SetKeyRange(  
                 region->KeyRange.low  + move.pos,  
                 region->KeyRange.high + move.pos  
             );  
             regions.update(instrument);  
             instrument_changed.emit();  
             instrument_struct_changed_signal.emit(instrument);  
         }  
   
593          if (is_in_resize_zone(event->x, event->y)) {          if (is_in_resize_zone(event->x, event->y)) {
594  #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2  #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
595              get_window()->set_cursor(Gdk::Cursor(Gdk::SB_H_DOUBLE_ARROW));              get_window()->set_cursor(Gdk::Cursor(Gdk::SB_H_DOUBLE_ARROW));
# Line 465  bool RegionChooser::on_button_release_ev Line 602  bool RegionChooser::on_button_release_ev
602      return true;      return true;
603  }  }
604    
605    void RegionChooser::update_after_resize()
606    {
607        if (resize.mode == resize.moving_high_limit) {
608            if (resize.region->KeyRange.high != resize.pos - 1) {
609                instrument_struct_to_be_changed_signal.emit(instrument);
610                resize.region->SetKeyRange(resize.region->KeyRange.low,
611                                           resize.pos - 1);
612                regions.update(instrument);
613                instrument_changed.emit();
614                instrument_struct_changed_signal.emit(instrument);
615            }
616        } else if (resize.mode == resize.moving_low_limit) {
617            if (resize.region->KeyRange.low != resize.pos) {
618                instrument_struct_to_be_changed_signal.emit(instrument);
619                resize.region->SetKeyRange(resize.pos,
620                                           resize.region->KeyRange.high);
621                regions.update(instrument);
622                instrument_changed.emit();
623                instrument_struct_changed_signal.emit(instrument);
624            }
625        }
626    }
627    
628    void RegionChooser::update_after_move(int pos)
629    {
630        instrument_struct_to_be_changed_signal.emit(instrument);
631        const int range = region->KeyRange.high - region->KeyRange.low;
632        const int diff  = pos - int(region->KeyRange.low);
633        region->SetKeyRange(pos, pos + range);
634        if (Settings::singleton()->moveRootNoteWithRegionMoved) {
635            for (int i = 0; i < 256; ++i) {
636                gig::DimensionRegion* dimrgn = region->pDimensionRegions[i];
637                if (!dimrgn || !dimrgn->pSample || !dimrgn->PitchTrack) continue;
638                dimrgn->UnityNote += diff;
639            }
640        }
641        regions.update(instrument);
642        instrument_changed.emit();
643        instrument_struct_changed_signal.emit(instrument);
644    }
645    
646  bool RegionChooser::on_button_press_event(GdkEventButton* event)  bool RegionChooser::on_button_press_event(GdkEventButton* event)
647  {  {
648      if (!instrument) return true;      if (!instrument) return true;
649    
650      const int k = int(event->x / (get_width() - 1) * 128.0);      const int w = get_width() - 1;
651        const int k = x_to_key(event->x, w);
652    
653      if (event->type == GDK_BUTTON_PRESS) {      if (event->type == GDK_BUTTON_PRESS) {
654          if (event->y >= REGION_BLOCK_HEIGHT) {          if (event->y >= REGION_BLOCK_HEIGHT) {
# Line 480  bool RegionChooser::on_button_press_even Line 659  bool RegionChooser::on_button_press_even
659          }          }
660      }      }
661    
662        // left mouse button double click
663        if (event->type == GDK_2BUTTON_PRESS && event->button == 1) {
664            if (event->y < REGION_BLOCK_HEIGHT) {
665                // show dimension manager dialog for this region
666                manage_dimensions();
667            }
668        }
669    
670      if (event->y >= REGION_BLOCK_HEIGHT) return true;      if (event->y >= REGION_BLOCK_HEIGHT) return true;
671      if (event->type == GDK_BUTTON_PRESS && event->button == 3) {      if (event->type == GDK_BUTTON_PRESS && event->button == 3) {
672          gig::Region* r = get_region(k);          gig::Region* r = get_region(k);
# Line 539  bool RegionChooser::on_button_press_even Line 726  bool RegionChooser::on_button_press_even
726                                                        event->time);                                                        event->time);
727  #endif  #endif
728                  move.active = true;                  move.active = true;
729                  move.from_x = event->x;                  move.offset = event->x - key_to_x(region->KeyRange.low, w);
                 move.pos = 0;  
730              }              }
731          }          }
732      }      }
# Line 549  bool RegionChooser::on_button_press_even Line 735  bool RegionChooser::on_button_press_even
735    
736  gig::Region* RegionChooser::get_region(int key)  gig::Region* RegionChooser::get_region(int key)
737  {  {
738      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();  
   
739          if (key < r->KeyRange.low) return 0;          if (key < r->KeyRange.low) return 0;
740          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;  
741      }      }
742      return 0;      return 0;
743  }  }
744    
745    void RegionChooser::set_region(gig::Region* region) {
746        this->region = region;
747        queue_draw();
748        region_selected();
749        dimensionManager.set_region(region);
750    }
751    
752    void RegionChooser::select_next_region() {
753        if (!instrument) return;
754        if (!region) {
755            for (int i = 0; i < 128; ++i) {
756                ::gig::Region* rgn = instrument->GetRegion(i);
757                if (rgn) {
758                    set_region(rgn);
759                    return;
760                }
761            }
762        } else {
763            bool currentFound = false;
764            for (int i = 0; i < 128; ++i) {
765                ::gig::Region* rgn = instrument->GetRegion(i);
766                if (!rgn) continue;
767                if (currentFound) {
768                    if (rgn != region) {
769                        set_region(rgn);
770                        return;
771                    }
772                } else {
773                    if (rgn == region) currentFound = true;
774                }
775            }
776        }
777    }
778    
779    void RegionChooser::select_prev_region() {
780        if (!instrument) return;
781        if (!region) {
782            for (int i = 0; i < 128; ++i) {
783                ::gig::Region* rgn = instrument->GetRegion(i);
784                if (rgn) {
785                    set_region(rgn);
786                    return;
787                }
788            }
789        } else {
790            bool currentFound = false;
791            for (int i = 127; i >= 0; --i) {
792                ::gig::Region* rgn = instrument->GetRegion(i);
793                if (!rgn) continue;
794                if (currentFound) {
795                    if (rgn != region) {
796                        set_region(rgn);
797                        return;
798                    }
799                } else {
800                    if (rgn == region) currentFound = true;
801                }
802            }
803        }
804    }
805    
806  void RegionChooser::motion_resize_region(int x, int y)  void RegionChooser::motion_resize_region(int x, int y)
807  {  {
808      const int w = get_width() - 1;      const int w = get_width() - 1;
# Line 575  void RegionChooser::motion_resize_region Line 813  void RegionChooser::motion_resize_region
813      else if (k > resize.max) k = resize.max;      else if (k > resize.max) k = resize.max;
814    
815      if (k != resize.pos) {      if (k != resize.pos) {
         Cairo::RefPtr<Cairo::Context> cr = get_window()->create_cairo_context();  
         cr->set_line_width(1);  
   
816          if (resize.mode == resize.undecided) {          if (resize.mode == resize.undecided) {
817              if (k < resize.pos) {              if (k < resize.pos) {
818                  // edit high limit of prev_region                  // edit high limit of prev_region
# Line 590  void RegionChooser::motion_resize_region Line 825  void RegionChooser::motion_resize_region
825                  resize.mode = resize.moving_low_limit;                  resize.mode = resize.moving_low_limit;
826              }              }
827          }          }
828          const Gdk::RGBA white = region == resize.region ? red : this->white;          resize.pos = k;
 #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2  
         const Gdk::Color bg = get_style()->get_bg(Gtk::STATE_NORMAL);  
 #else  
         const Gdk::RGBA bg = get_style_context()->get_background_color();  
 #endif  
   
         int prevx = int(w * resize.pos / 128.0 + 0.5);  
         x = int(w * k / 128.0 + 0.5);  
829    
830            int x1, x2;
831          if (resize.mode == resize.moving_high_limit) {          if (resize.mode == resize.moving_high_limit) {
832              if (k > resize.pos) {              if (resize.region->KeyRange.high < resize.pos - 1) {
833                  Gdk::Cairo::set_source_rgba(cr, white);                  x1 = resize.region->KeyRange.high;
834                  cr->rectangle(prevx, 1, x - prevx, h1 - 2);                  x2 = resize.pos - 1;
                 cr->fill();  
   
                 Gdk::Cairo::set_source_rgba(cr, black);  
                 cr->move_to(prevx, 0.5);  
                 cr->line_to(x + 1, 0.5);  
                 cr->move_to(prevx, h1 - 0.5);  
                 cr->line_to(x + 1, h1 - 0.5);  
                 cr->stroke();  
835              } else {              } else {
836                  int xx = (resize.pos == resize.max &&                  x1 = resize.pos - 1;
837                            resize.max != 128) ? 1 : 0;                  x2 = resize.region->KeyRange.high;
                 Gdk::Cairo::set_source_rgba(cr, bg);  
                 cr->rectangle(x + 1, 0, prevx - x - xx, h1);  
                 cr->fill();  
838              }              }
839          } else {          } else {
840              if (k < resize.pos) {              if (resize.region->KeyRange.low < resize.pos) {
841                  Gdk::Cairo::set_source_rgba(cr, white);                  x1 = resize.region->KeyRange.low;
842                  cr->rectangle(x + 1, 1, prevx - x, h1 - 2);                  x2 = resize.pos;
                 cr->fill();  
   
                 Gdk::Cairo::set_source_rgba(cr, black);  
                 cr->move_to(x, 0.5);  
                 cr->line_to(prevx, 0.5);  
                 cr->move_to(x, h1 - 0.5);  
                 cr->line_to(prevx, h1 - 0.5);  
                 cr->stroke();  
843              } else {              } else {
844                  int xx = (resize.pos == resize.min &&                  x1 = resize.pos;
845                            resize.min != 0) ? 1 : 0;                  x2 = resize.region->KeyRange.low;
                 Gdk::Cairo::set_source_rgba(cr, bg);  
                 cr->rectangle(prevx + xx, 0, x - prevx - xx, h1);  
                 cr->fill();  
846              }              }
847          }          }
848          Gdk::Cairo::set_source_rgba(cr, black);          x1 = key_to_x(x1, w);
849          cr->move_to(x + 0.5, 1);          x2 = key_to_x(x2 + 1, w) + 1;
850          cr->line_to(x + 0.5, h1 - 1);          Gdk::Rectangle rect(x1, 0, x2 - x1, h1);
851          cr->stroke();  
852          resize.pos = k;          update_after_resize();
853    
854            //get_window()->invalidate_rect(rect, false);
855            get_window()->invalidate(false); // repaint entire region, otherwise it would create visual artifacts
856      }      }
857  }  }
858    
859  void RegionChooser::motion_move_region(int x, int y)  void RegionChooser::motion_move_region(int x, int y)
860  {  {
861      const int w = get_width() - 1;      const int w = get_width() - 1;
     Cairo::RefPtr<Cairo::Context> cr = get_window()->create_cairo_context();  
     cr->set_line_width(1);  
862    
863      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);
864      if (k == move.pos) return;  
865      int new_k;      if (l == region->KeyRange.low) return;
866      bool new_touch_left;      int new_l;
867      bool new_touch_right;      int regionsize = region->KeyRange.high - region->KeyRange.low;
868      int a = 0;      int a = 0;
869      if (k > move.pos) {      if (l > region->KeyRange.low) {
870          for (gig::Region* r = regions.first() ; ; r = regions.next()) {          for (gig::Region* r = regions.first() ; ; r = regions.next()) {
871              if (r != region) {              if (r != region) {
872                  int b = r ? r->KeyRange.low : 128;                  int b = r ? r->KeyRange.low : 128;
873    
874                  // gap: from a to b (not inclusive b)                  // gap: from a to b (not inclusive b)
875    
876                  if (region->KeyRange.high + move.pos >= b) {                  if (region->KeyRange.high >= b) {
877                      // not found the current gap yet, just continue                      // not found the current gap yet, just continue
878                  } else {                  } else {
879    
880                      if (a > region->KeyRange.low + k) {                      if (a > l) {
881                          // this gap is too far to the right, break                          // this gap is too far to the right, break
882                          break;                          break;
883                      }                      }
884    
885                      int newhigh = std::min(region->KeyRange.high + k, b - 1);                      int newhigh = std::min(l + regionsize, b - 1);
886                      int newlo = newhigh - (region->KeyRange.high - region->KeyRange.low);                      int newlo = newhigh - regionsize;
887    
888                      if (newlo >= a) {                      if (newlo >= a) {
889                          // yes it fits - it's a candidate                          // yes it fits - it's a candidate
890                          new_k = newlo - region->KeyRange.low;                          new_l = newlo;
                         new_touch_left = a > 0 && a == newlo;  
                         new_touch_right = b < 128 && newhigh + 1 == b;  
891                      }                      }
892                  }                  }
893                  if (!r) break;                  if (!r) break;
# Line 696  void RegionChooser::motion_move_region(i Line 901  void RegionChooser::motion_move_region(i
901    
902                  // gap from a to b (not inclusive b)                  // gap from a to b (not inclusive b)
903    
904                  if (region->KeyRange.high + k >= b) {                  if (l + regionsize >= b) {
905                      // not found the current gap yet, just continue                      // not found the current gap yet, just continue
906                  } else {                  } else {
907    
908                      if (a > region->KeyRange.low + move.pos) {                      if (a > region->KeyRange.low) {
909                          // this gap is too far to the right, break                          // this gap is too far to the right, break
910                          break;                          break;
911                      }                      }
912    
913                      int newlo = std::max(region->KeyRange.low + k, a);                      int newlo = std::max(l, a);
914                      int newhigh = newlo + (region->KeyRange.high - region->KeyRange.low);                      int newhigh = newlo + regionsize;
915    
916                      if (newhigh < b) {                      if (newhigh < b) {
917                          // yes it fits - break as the first one is the best                          // yes it fits - break as the first one is the best
918                          new_k = newlo - region->KeyRange.low;                          new_l = newlo;
                         new_touch_left = a > 0 && a == newlo;  
                         new_touch_right = b < 128 && newhigh + 1 == b;  
919                          break;                          break;
920                      }                      }
921                  }                  }
# Line 721  void RegionChooser::motion_move_region(i Line 924  void RegionChooser::motion_move_region(i
924              }              }
925          }          }
926      }      }
927      k = new_k;      if (new_l == region->KeyRange.low) return;
     if (k == move.pos) return;  
928    
929  #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2      int x1 = key_to_x(std::min(int(region->KeyRange.low), new_l), w);
930      const Gdk::Color bg = get_style()->get_bg(Gtk::STATE_NORMAL);      int x2 = key_to_x(std::max(int(region->KeyRange.high),
931  #else                                 new_l + regionsize) + 1, w) + 1;
     const Gdk::RGBA bg = get_style_context()->get_background_color();  
 #endif  
   
     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);  
   
     if (!new_touch_left) {  
         Gdk::Cairo::set_source_rgba(cr, black);  
         cr->move_to(x + 0.5, 1);  
         cr->line_to(x + 0.5, h1 - 1);  
         cr->stroke();  
     }  
     if (!new_touch_right) {  
         Gdk::Cairo::set_source_rgba(cr, black);  
         cr->move_to(x2 + 0.5, 1);  
         cr->line_to(x2 + 0.5, h1 - 1);  
         cr->stroke();  
     }  
932    
933      if (k > move.pos) {      Gdk::Rectangle rect(x1, 0, x2 - x1, h1);
934          Gdk::Cairo::set_source_rgba(cr, bg);      update_after_move(new_l);
         cr->rectangle(prevx + (move.touch_left ? 1 : 0), 0,  
                       std::min(x, prevx2 + 1 - (move.touch_right ? 1 : 0)) -  
                       (prevx + (move.touch_left ? 1 : 0)), h1);  
         cr->fill();  
   
         Gdk::Cairo::set_source_rgba(cr, black);  
         cr->move_to(std::max(x, prevx2 + 1), 0.5);  
         cr->line_to(x2 + 1, 0.5);  
         cr->move_to(std::max(x, prevx2 + 1), h1 - 0.5);  
         cr->line_to(x2 + 1, h1 - 0.5);  
         cr->stroke();  
   
         Gdk::Cairo::set_source_rgba(cr, red);  
         cr->rectangle(std::max(x + 1, prevx2), 1,  
                       x2 - std::max(x + 1, prevx2), h1 - 2);  
         cr->fill();  
     } else {  
         Gdk::Cairo::set_source_rgba(cr, bg);  
         cr->rectangle(std::max(x2 + 1, prevx + (move.touch_left ? 1 : 0)), 0,  
                       prevx2 + 1 - (move.touch_right ? 1 : 0) -  
                       std::max(x2 + 1, prevx + (move.touch_left ? 1 : 0)), h1);  
         cr->fill();  
   
         Gdk::Cairo::set_source_rgba(cr, black);  
         cr->move_to(x, 0.5);  
         cr->line_to(std::min(x2, prevx - 1) + 1, 0.5);  
         cr->move_to(x, h1 - 0.5);  
         cr->line_to(std::min(x2, prevx - 1) + 1, h1 - 0.5);  
         cr->stroke();  
   
         Gdk::Cairo::set_source_rgba(cr, red);  
         cr->rectangle(x + 1, 1, std::min(x2 - 1, prevx) - x, h1 - 2);  
         cr->fill();  
     }  
935    
936      move.pos = k;      get_window()->invalidate_rect(rect, false);
     move.touch_left = new_touch_left;  
     move.touch_right = new_touch_right;  
937  }  }
938    
939    
# Line 804  bool RegionChooser::on_motion_notify_eve Line 950  bool RegionChooser::on_motion_notify_eve
950          event->y >= REGION_BLOCK_HEIGHT &&          event->y >= REGION_BLOCK_HEIGHT &&
951          event->y < REGION_BLOCK_HEIGHT + KEYBOARD_HEIGHT)          event->y < REGION_BLOCK_HEIGHT + KEYBOARD_HEIGHT)
952      {      {
953          const int k = int(event->x / (get_width() - 1) * 128.0);          const int k = x_to_key(event->x, get_width() - 1);
954          if (k != currentActiveKey) {          if (k != currentActiveKey) {
955              int velocity =              int velocity =
956                  (event->y >= REGION_BLOCK_HEIGHT + KEYBOARD_HEIGHT - 1) ? 127 :                  (event->y >= REGION_BLOCK_HEIGHT + KEYBOARD_HEIGHT - 1) ? 127 :
# Line 849  bool RegionChooser::is_in_resize_zone(do Line 995  bool RegionChooser::is_in_resize_zone(do
995          for (gig::Region* r = regions.first(); r ; r = next_region) {          for (gig::Region* r = regions.first(); r ; r = next_region) {
996              next_region = regions.next();              next_region = regions.next();
997    
998              int lo = int(w * (r->KeyRange.low) / 128.0 + 0.5);              int lo = key_to_x(r->KeyRange.low, w);
999              if (x <= lo - 2) break;              if (x <= lo - 2) break;
1000              if (x < lo + 2) {              if (x < lo + 2) {
1001                  resize.region = r;                  resize.region = r;
# Line 872  bool RegionChooser::is_in_resize_zone(do Line 1018  bool RegionChooser::is_in_resize_zone(do
1018                  return resize.min != resize.max;                  return resize.min != resize.max;
1019              }              }
1020              if (!next_region || r->KeyRange.high + 1 != next_region->KeyRange.low) {              if (!next_region || r->KeyRange.high + 1 != next_region->KeyRange.low) {
1021                  int hi = int(w * (r->KeyRange.high + 1) / 128.0 + 0.5);                  int hi = key_to_x(r->KeyRange.high + 1, w);
1022                  if (x <= hi - 2) break;                  if (x <= hi - 2) break;
1023                  if (x < hi + 2) {                  if (x < hi + 2) {
1024                      // edit high limit                      // edit high limit
# Line 922  void RegionChooser::show_region_properti Line 1068  void RegionChooser::show_region_properti
1068      // add OK and CANCEL buttons to the dialog      // add OK and CANCEL buttons to the dialog
1069      dialog.add_button(Gtk::Stock::OK, 0);      dialog.add_button(Gtk::Stock::OK, 0);
1070      dialog.add_button(Gtk::Stock::CANCEL, 1);      dialog.add_button(Gtk::Stock::CANCEL, 1);
1071        dialog.set_position(Gtk::WIN_POS_MOUSE);
1072      dialog.show_all_children();      dialog.show_all_children();
1073      if (!dialog.run()) { // OK selected ...      if (!dialog.run()) { // OK selected ...
1074          region->KeyGroup =          region->KeyGroup =

Legend:
Removed from v.2169  
changed lines
  Added in v.3307

  ViewVC Help
Powered by ViewVC