/[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 1262 by persson, Sun Jul 22 15:07:08 2007 UTC revision 2841 by persson, Sun Aug 30 10:00:49 2015 UTC
# Line 1  Line 1 
1  /*  /*
2   * Copyright (C) 2006, 2007 Andreas Persson   * Copyright (C) 2006-2015 Andreas Persson
3   *   *
4   * This program is free software; you can redistribute it and/or   * This program is free software; you can redistribute it and/or
5   * modify it under the terms of the GNU General Public License as   * modify it under the terms of the GNU General Public License as
# Line 18  Line 18 
18   */   */
19    
20  #include "regionchooser.h"  #include "regionchooser.h"
21    
22    #include <algorithm>
23    
24    #include <cairomm/context.h>
25    #include <gdkmm/general.h>
26  #include <gdkmm/cursor.h>  #include <gdkmm/cursor.h>
27  #include <gtkmm/stock.h>  #include <gtkmm/stock.h>
28  #include <gtkmm/spinbutton.h>  #include <gtkmm/spinbutton.h>
29  #include <gtkmm/dialog.h>  #include <gtkmm/dialog.h>
 #include <libintl.h>  
 #include <math.h>  
30    
31  #define _(String) gettext(String)  #include "global.h"
32    #include "Settings.h"
33    
34  RegionChooser::RegionChooser()  #define REGION_BLOCK_HEIGHT             30
35  {  #define KEYBOARD_HEIGHT                 40
     Glib::RefPtr<Gdk::Colormap> colormap = get_default_colormap();  
36    
37      red = Gdk::Color("#8070ff");  void SortedRegions::update(gig::Instrument* instrument) {
38      grey1 = Gdk::Color("#b0b0b0");      // Usually, the regions in a gig file are ordered after their key
39        // range, but there are files where they are not. The
40        // RegionChooser code needs a sorted list of regions.
41        regions.clear();
42        if (instrument) {
43            for (gig::Region* r = instrument->GetFirstRegion() ;
44                 r ;
45                 r = instrument->GetNextRegion()) {
46                regions.push_back(r);
47            }
48            sort(regions.begin(), regions.end(), *this);
49        }
50    }
51    
52    gig::Region* SortedRegions::first() {
53        region_iterator = regions.begin();
54        return region_iterator == regions.end() ? 0 : *region_iterator;
55    }
56    
57    gig::Region* SortedRegions::next() {
58        ++region_iterator;
59        return region_iterator == regions.end() ? 0 : *region_iterator;
60    }
61    
62    
63    
64    RegionChooser::RegionChooser() :
65        activeKeyColor("red"),
66        red("#8070ff"),
67        grey1("grey69"),
68        white("white"),
69        black("black"),
70        m_VirtKeybModeChoice(_("Virtual Keyboard Mode")),
71        currentActiveKey(-1)
72    {
73        set_size_request(500, KEYBOARD_HEIGHT + REGION_BLOCK_HEIGHT);
74    
     colormap->alloc_color(red);  
     colormap->alloc_color(grey1);  
75      instrument = 0;      instrument = 0;
76      region = 0;      region = 0;
77      resize.active = false;      resize.active = false;
78        move.active = false;
79      cursor_is_resize = false;      cursor_is_resize = false;
80      h1 = 20;      h1 = REGION_BLOCK_HEIGHT;
81      width = 800;  
82        // properties of the virtual keyboard
83        {
84            const char* choices[] = { _("normal"), _("chord"), 0 };
85            static const virt_keyboard_mode_t values[] = {
86                VIRT_KEYBOARD_MODE_NORMAL,
87                VIRT_KEYBOARD_MODE_CHORD
88            };
89            m_VirtKeybModeChoice.set_choices(choices, values);
90            m_VirtKeybModeChoice.set_value(VIRT_KEYBOARD_MODE_NORMAL);
91        }
92        m_VirtKeybVelocityLabelDescr.set_text(_("Note-On Velocity:"));
93        m_VirtKeybVelocityLabel.set_text("-");
94        m_VirtKeybOffVelocityLabelDescr.set_text(_("Note-Off Velocity:"));
95        m_VirtKeybOffVelocityLabel.set_text("-");
96        m_VirtKeybPropsBox.pack_start(m_VirtKeybModeChoice.label, Gtk::PACK_SHRINK);
97        m_VirtKeybPropsBox.pack_start(m_VirtKeybModeChoice.widget, Gtk::PACK_SHRINK);
98        m_VirtKeybPropsBox.pack_start(m_VirtKeybVelocityLabelDescr, Gtk::PACK_SHRINK);
99        m_VirtKeybPropsBox.pack_start(m_VirtKeybVelocityLabel, Gtk::PACK_SHRINK);
100        m_VirtKeybPropsBox.pack_start(m_VirtKeybOffVelocityLabelDescr, Gtk::PACK_SHRINK);
101        m_VirtKeybPropsBox.pack_start(m_VirtKeybOffVelocityLabel, Gtk::PACK_SHRINK);
102        m_VirtKeybPropsBox.set_spacing(10);
103        m_VirtKeybPropsBox.show();
104        for (int i = 0 ; i < 128 ; i++) key_pressed[i] = false;
105    
106      actionGroup = Gtk::ActionGroup::create();      actionGroup = Gtk::ActionGroup::create();
107      actionGroup->add(Gtk::Action::create("Properties",      actionGroup->add(Gtk::Action::create("Properties",
# Line 78  RegionChooser::RegionChooser() Line 138  RegionChooser::RegionChooser()
138      add_events(Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK |      add_events(Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK |
139                 Gdk::POINTER_MOTION_MASK | Gdk::POINTER_MOTION_HINT_MASK);                 Gdk::POINTER_MOTION_MASK | Gdk::POINTER_MOTION_HINT_MASK);
140    
141      dimensionManager.articulation_changed_signal.connect(      dimensionManager.region_to_be_changed_signal.connect(
142          sigc::mem_fun(*this, &RegionChooser::on_dimension_manager_changed)          region_to_be_changed_signal.make_slot()
143        );
144        dimensionManager.region_changed_signal.connect(
145            region_changed_signal.make_slot()
146        );
147        dimensionManager.region_changed_signal.connect(
148            sigc::hide(
149                sigc::mem_fun(*this, &RegionChooser::on_dimension_manager_changed)
150            )
151        );
152        keyboard_key_hit_signal.connect(
153            sigc::mem_fun(*this, &RegionChooser::on_note_on_event)
154      );      );
155        keyboard_key_released_signal.connect(
156            sigc::mem_fun(*this, &RegionChooser::on_note_off_event)
157        );
158        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."));
159  }  }
160    
161  RegionChooser::~RegionChooser()  RegionChooser::~RegionChooser()
162  {  {
163  }  }
164    
165  void RegionChooser::on_realize()  void RegionChooser::invalidate_key(int key) {
166  {      const int h = KEYBOARD_HEIGHT;
167      // We need to call the base on_realize()      const int w = get_width() - 1;
168      Gtk::DrawingArea::on_realize();      int x1 = key_to_x(key - 0.5, w);
169        int x2 = key_to_x(key + 1.5, w);
170    
171      // Now we can allocate any additional resources we need      Gdk::Rectangle rect(x1 + 1, h1 + 1, x2 - x1 - 1, h - 2);
172      Glib::RefPtr<Gdk::Window> window = get_window();      get_window()->invalidate_rect(rect, false);
     gc = Gdk::GC::create(window);  
     window->clear();  
173  }  }
174    
175  bool RegionChooser::on_expose_event(GdkEventExpose* event)  void RegionChooser::on_note_on_event(int key, int velocity) {
176  {      key_pressed[key] = true;
177      Glib::RefPtr<Gdk::Window> window = get_window();      invalidate_key(key);
178      window->clear();      m_VirtKeybVelocityLabel.set_text(ToString(velocity));
179      const int h = 40;  }
     const int w = width - 1;  
     const int bh = int(h * 0.55);  
   
     Glib::RefPtr<const Gdk::GC> black = get_style()->get_black_gc();  
     Glib::RefPtr<const Gdk::GC> white = get_style()->get_white_gc();  
180    
181      Glib::RefPtr<Pango::Context> context = get_pango_context();  void RegionChooser::on_note_off_event(int key, int velocity) {
182      Glib::RefPtr<Pango::Layout> layout = Pango::Layout::create(context);      key_pressed[key] = false;
183        invalidate_key(key);
184        m_VirtKeybOffVelocityLabel.set_text(ToString(velocity));
185    }
186    
     window->draw_rectangle(black, false, 0, h1, w, h - 1);  
     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);  
     int octave = -1;  
     for (int i = 0 ; i < 128 ; i++) {  
         int note = (i + 3) % 12;  
         int x = int(w * i / 128.0 + 0.5);  
187    
188          if (note == 1 || note == 4 || note == 6 || note == 9 || note == 11) {  #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
189              int x2 = int(w * (i + 0.5) / 128.0 + 0.5);  bool RegionChooser::on_expose_event(GdkEventExpose* e) {
190              window->draw_line(black, x2, h1 + bh, x2, h1 + h);      double clipx1 = e->area.x;
191        double clipx2 = e->area.x + e->area.width;
192        double clipy1 = e->area.y;
193        double clipy2 = e->area.y + e->area.height;
194    
195              int x3 = int(w * (i + 1) / 128.0 + 0.5);      const Cairo::RefPtr<Cairo::Context>& cr =
196              window->draw_rectangle(black, true, x, h1 + 1, x3 - x + 1, bh);          get_window()->create_cairo_context();
197          } else if (note == 3 || note == 8) {  #if 0
198              window->draw_line(black, x, h1 + 1, x, h1 + h);  }
199          }  #endif
200          if (note == 3) {  #else
201              char buf[30];  bool RegionChooser::on_draw(const Cairo::RefPtr<Cairo::Context>& cr) {
202              sprintf(buf, "<span size=\"x-small\">%d</span>", octave);      double clipx1, clipx2, clipy1, clipy2;
203              layout->set_markup(buf);      cr->get_clip_extents(clipx1, clipy1, clipx2, clipy2);
204              Pango::Rectangle rectangle = layout->get_logical_extents();  #endif
             double text_w = double(rectangle.get_width()) / Pango::SCALE;  
             double text_h = double(rectangle.get_height()) / Pango::SCALE;  
             double x2 = w * (i + 0.75) / 128.0;  
             window->draw_layout(black, int(x2 - text_w / 2 + 1),  
                                 int(h1 + h - text_h + 0.5), layout);  
             octave++;  
         }  
     }  
205    
206      if (instrument) {      cr->save();
207          int i = 0;      cr->set_line_width(1);
         gig::Region *next_region;  
         int x3 = -1;  
         for (gig::Region *r = instrument->GetFirstRegion() ;  
              r ;  
              r = next_region) {  
208    
209              if (x3 < 0) x3 = int(w * (r->KeyRange.low) / 128.0 + 0.5);  #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
210              next_region = instrument->GetNextRegion();      const Gdk::Color bg = get_style()->get_bg(Gtk::STATE_NORMAL);
211              if (!next_region || r->KeyRange.high + 1 != next_region->KeyRange.low) {  #else
212                  int x2 = int(w * (r->KeyRange.high + 1) / 128.0 + 0.5);      const Gdk::RGBA bg = get_style_context()->get_background_color();
213                  window->draw_line(black, x3, 0, x2, 0);  #endif
214                  window->draw_line(black, x3, h1 - 1, x2, h1 - 1);      Gdk::Cairo::set_source_rgba(cr, bg);
215                  window->draw_line(black, x2, 1, x2, h1 - 2);      cr->paint();
                 window->draw_rectangle(white, true, x3 + 1, 1, x2 - x3 - 1, h1 - 2);  
                 x3 = -1;  
             }  
             i++;  
         }  
216    
217          for (gig::Region *r = instrument->GetFirstRegion() ;      if (clipy2 > h1) {
218               r ;          draw_keyboard(cr, clipx1, clipx2);
219               r = instrument->GetNextRegion()) {      }
             int x = int(w * (r->KeyRange.low) / 128.0 + 0.5);  
             window->draw_line(black, x, 1, x, h1 - 2);  
         }  
220    
221          if (region) {      if (clipy1 < h1 && instrument) {
222              int x1 = int(w * (region->KeyRange.low) / 128.0 + 0.5);          draw_regions(cr, clipx1, clipx2);
             int x2 = int(w * (region->KeyRange.high + 1) / 128.0 + 0.5);  
             gc->set_foreground(red);  
             window->draw_rectangle(gc, true, x1 + 1, 1, x2 - x1 - 1, h1 - 2);  
         }  
223      }      }
224    
225        cr->restore();
226    
227      return true;      return true;
228  }  }
229    
230    void RegionChooser::draw_keyboard(const Cairo::RefPtr<Cairo::Context>& cr,
231                                      int clip_low, int clip_high) {
232        const int h = KEYBOARD_HEIGHT;
233        const int w = get_width() - 1;
234        const int bh = int(h * 0.55);
235    
236  void RegionChooser::on_size_request(GtkRequisition* requisition)      Gdk::Cairo::set_source_rgba(cr, black);
237  {      cr->rectangle(0.5, h1 + 0.5, w, h - 1);
238      *requisition = GtkRequisition();      cr->stroke();
239      requisition->height = 40 + 20;  
240      requisition->width = 500;      int x1 = key_to_x(20.5, w);
241        Gdk::Cairo::set_source_rgba(cr, grey1);
242        cr->rectangle(1, h1 + 1, x1 - 1, h - 2);
243        cr->fill();
244    
245        int x2 = key_to_x(109.5, w);
246        Gdk::Cairo::set_source_rgba(cr, white);
247        cr->rectangle(x1 + 1, h1 + 1, x2 - x1 - 1, h - 2);
248        cr->fill();
249    
250        Gdk::Cairo::set_source_rgba(cr, grey1);
251        cr->rectangle(x2 + 1, h1 + 1, w - x2 - 1, h - 2);
252        cr->fill();
253    
254        Gdk::Cairo::set_source_rgba(cr, black);
255    
256        int clipkey1 = std::max(0, x_to_key_right(clip_low - 1, w));
257        int clipkey2 = std::min(x_to_key_right(clip_high - 1, w) + 1, 128);
258    
259        for (int i = clipkey1 ; i < clipkey2 ; i++) {
260            int note = (i + 3) % 12;
261            int x = key_to_x(i, w);
262    
263            if (note == 1 || note == 4 || note == 6 ||
264                note == 9 || note == 11) {
265                // black key: short line in the middle, with a rectangle
266                // on top
267                int x2 = key_to_x(i + 0.5, w);
268                cr->move_to(x2 + 0.5, h1 + bh + 0.5);
269                cr->line_to(x2 + 0.5, h1 + h - 1);
270                cr->stroke();
271    
272                int x3 = key_to_x(i + 1, w);
273                cr->rectangle(x, h1 + 1, x3 - x + 1, bh);
274                cr->fill();
275            } else if (note == 3 || note == 8) {
276                // C or F: long line to the left
277                cr->move_to(x + 0.5, h1 + 1);
278                cr->line_to(x + 0.5, h1 + h - 1);
279                cr->stroke();
280            }
281    
282            if (key_pressed[i]) draw_key(cr, i);
283    
284            if (note == 3) draw_digit(cr, i);
285        }
286  }  }
287    
288    
289  // not used  void RegionChooser::draw_regions(const Cairo::RefPtr<Cairo::Context>& cr,
290  void RegionChooser::draw_region(int from, int to, const Gdk::Color& color)                                   int clip_low, int clip_high) {
291  {      const int w = get_width() - 1;
292      const int h = 40;  
293      const int w = width;      Gdk::Cairo::set_source_rgba(cr, black);
294        gig::Region* next_region;
295        int x3 = -1;
296        for (gig::Region* r = regions.first() ; r ; r = next_region) {
297            next_region = regions.next();
298    
299            if (x3 < 0) {
300                x3 = key_to_x(r->KeyRange.low, w);
301                if (x3 >= clip_high) break;
302            }
303            if (!next_region ||
304                r->KeyRange.high + 1 != next_region->KeyRange.low ||
305                r == region || next_region == region) {
306    
307                int x2 = key_to_x(r->KeyRange.high + 1, w);
308                if (x2 >= clip_low) {
309                    cr->move_to(x3, 0.5);
310                    cr->line_to(x2 + 0.5, 0.5);
311                    cr->line_to(x2 + 0.5, h1 - 0.5);
312                    cr->line_to(x3, h1 - 0.5);
313                    cr->stroke();
314    
315                    Gdk::Cairo::set_source_rgba(cr, region == r ? red : white);
316                    cr->rectangle(x3 + 1, 1, x2 - x3 - 1, h1 - 2);
317                    cr->fill();
318                    Gdk::Cairo::set_source_rgba(cr, black);
319                }
320                x3 = -1;
321            }
322        }
323    
324        for (gig::Region* r = regions.first() ; r ; r = regions.next()) {
325            int x = key_to_x(r->KeyRange.low, w);
326    
327            if (x < clip_low) continue;
328            if (x >= clip_high) break;
329    
330            cr->move_to(x + 0.5, 1);
331            cr->line_to(x + 0.5, h1 - 1);
332            cr->stroke();
333        }
334    
335        // if there is no region yet, show the user some hint text that he may
336        // right click on this area to create a new region
337        if (!regions.first()) {
338            Glib::RefPtr<Pango::Context> context = get_pango_context();
339            Glib::RefPtr<Pango::Layout> layout = Pango::Layout::create(context);
340            layout->set_alignment(Pango::ALIGN_CENTER);
341            layout->set_text(Glib::ustring("*** ") + _("Right click here to create a region.") + " ***");
342            layout->set_width(get_width() * Pango::SCALE);
343            //layout->set_height(get_height() * Pango::SCALE);
344            layout->set_spacing(10);
345            Gdk::Cairo::set_source_rgba(cr, red);        
346            // get the text dimensions
347            int text_width, text_height;
348            layout->get_pixel_size(text_width, text_height);
349            cr->move_to(0, (REGION_BLOCK_HEIGHT - text_height) / 2);
350    #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 16) || GTKMM_MAJOR_VERSION < 2
351            pango_cairo_show_layout(cr->cobj(), layout->gobj());
352    #else
353            layout->show_in_cairo_context(cr);
354    #endif
355        }
356    }
357    
358    bool RegionChooser::is_black_key(int key) {
359        const int note = (key + 3) % 12;
360        return note == 1 || note == 4 || note == 6 || note == 9 || note == 11;
361    }
362    
363    void RegionChooser::draw_digit(const Cairo::RefPtr<Cairo::Context>& cr,
364                                   int key) {
365        const int h = KEYBOARD_HEIGHT;
366        const int w = get_width() - 1;
367        Glib::RefPtr<Pango::Layout> layout =
368            Pango::Layout::create(get_pango_context());
369        char buf[30];
370        sprintf(buf, "<span size=\"8000\">%d</span>", key / 12 - 1);
371        layout->set_markup(buf);
372        Pango::Rectangle rectangle = layout->get_logical_extents();
373        double text_w = double(rectangle.get_width()) / Pango::SCALE;
374        double text_h = double(rectangle.get_height()) / Pango::SCALE;
375        double x = w * (key + 0.75) / 128.0;
376        Gdk::Cairo::set_source_rgba(cr, black);
377        cr->move_to(int(x - text_w / 2 + 1), int(h1 + h - text_h + 0.5));
378    #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 16) || GTKMM_MAJOR_VERSION < 2
379        pango_cairo_show_layout(cr->cobj(), layout->gobj());
380    #else
381        layout->show_in_cairo_context(cr);
382    #endif
383    }
384    
385    void RegionChooser::draw_key(const Cairo::RefPtr<Cairo::Context>& cr,
386                                 int key) {
387        const int h = KEYBOARD_HEIGHT;
388        const int w = get_width() - 1;
389      const int bh = int(h * 0.55);      const int bh = int(h * 0.55);
390    
391      Glib::RefPtr<Gdk::Window> window = get_window();      Gdk::Cairo::set_source_rgba(cr, activeKeyColor);
     gc->set_foreground(color);  
392    
393      for (int i = from ; i < to ; i++) {      int note = (key + 3) % 12;
394          int note = (i + 3) % 12;      int x = key_to_x(key, w) + 1;
395          int x = int(w * i / 128.0 + 0.5) + 1;      int x2 = key_to_x(key + 1.5, w);
396          int x2 = int(w * (i + 1.5) / 128.0 + 0.5);      int x3 = key_to_x(key + 1, w);
397          int x3 = int(w * (i + 1) / 128.0 + 0.5);      int x4 = key_to_x(key - 0.5, w);
398          int x4 = int(w * (i - 0.5) / 128 + 0.5) + 1;      int w1 = x3 - x;
399          int w1 = x3 - x;      switch (note) {
400          switch (note) {      case 0: case 5: case 10:
401          case 0: case 5: case 10:          cr->rectangle(x, h1 + 1, w1, bh);
402              window->draw_rectangle(gc, true, x, h1 + 1, w1, bh);          cr->fill();
403              window->draw_rectangle(gc, true, x4, h1 + bh + 1, x2 - x4, h - bh - 2);          cr->rectangle(x4 + 1, h1 + bh + 1, x2 - x4 - 1, h - bh - 2);
404              break;          cr->fill();
405          case 2: case 7:          break;
406              window->draw_rectangle(gc, true, x, h1 + 1, w1, bh);      case 2: case 7:
407              window->draw_rectangle(gc, true, x4, h1 + bh + 1, x3 - x4, h - bh - 2);          cr->rectangle(x, h1 + 1, w1, bh);
408              break;          cr->fill();
409          case 3: case 8:          cr->rectangle(x4 + 1, h1 + bh + 1, x3 - x4 - 1, h - bh - 2);
410              window->draw_rectangle(gc, true, x, h1 + 1, w1, bh);          cr->fill();
411              window->draw_rectangle(gc, true, x, h1 + bh + 1, x2 - x, h - bh - 2);          break;
412              break;      case 3: case 8:
413          default:          cr->rectangle(x, h1 + 1, w1, bh);
414              window->draw_rectangle(gc, true, x, h1 + 1, w1, bh - 1);          cr->fill();
415              break;          cr->rectangle(x, h1 + bh + 1, x2 - x, h - bh - 2);
416          }          cr->fill();
417            break;
418        default:
419            cr->rectangle(x, h1 + 1, w1, bh - 1);
420            cr->fill();
421            break;
422      }      }
423        Gdk::Cairo::set_source_rgba(cr, black);
424  }  }
425    
426  void RegionChooser::set_instrument(gig::Instrument* instrument)  void RegionChooser::set_instrument(gig::Instrument* instrument)
427  {  {
428      this->instrument = instrument;      this->instrument = instrument;
429      region = instrument ? instrument->GetFirstRegion() : 0;      regions.update(instrument);
430        region = regions.first();
431      queue_draw();      queue_draw();
432      region_selected();      region_selected();
433        dimensionManager.set_region(region);
434  }  }
435    
436  bool RegionChooser::on_button_release_event(GdkEventButton* event)  bool RegionChooser::on_button_release_event(GdkEventButton* event)
437  {  {
438        const int k = x_to_key(event->x, get_width() - 1);
439    
440        // handle-note off on virtual keyboard
441        if (event->type == GDK_BUTTON_RELEASE) {
442            int velocity = (event->y >= REGION_BLOCK_HEIGHT + KEYBOARD_HEIGHT - 1) ? 127 :
443                           int(float(event->y - REGION_BLOCK_HEIGHT) / float(KEYBOARD_HEIGHT) * 128.0f) + 1;
444            if (velocity <= 0) velocity = 1;
445            switch (m_VirtKeybModeChoice.get_value()) {
446                case VIRT_KEYBOARD_MODE_CHORD:
447                    if (event->y >= REGION_BLOCK_HEIGHT)
448                        keyboard_key_released_signal.emit(k, velocity);
449                    break;
450                case VIRT_KEYBOARD_MODE_NORMAL:
451                default:
452                    if (currentActiveKey >= 0 && currentActiveKey <= 127) {
453                        keyboard_key_released_signal.emit(currentActiveKey, velocity);
454                        currentActiveKey = -1;
455                    }
456                    break;
457            }
458        }
459    
460      if (resize.active) {      if (resize.active) {
461    #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
462          get_window()->pointer_ungrab(event->time);          get_window()->pointer_ungrab(event->time);
463    #else
464            Glib::wrap(event->device, true)->ungrab(event->time);
465    #endif
466          resize.active = false;          resize.active = false;
467    
         if (resize.mode == resize.moving_high_limit) {  
             if (resize.region->KeyRange.high != resize.pos - 1) {  
                 resize.region->KeyRange.high = resize.pos - 1;  
                 instrument_changed();  
             }  
         } else if (resize.mode == resize.moving_low_limit) {  
             if (resize.region->KeyRange.low != resize.pos) {  
                 resize.region->KeyRange.low = resize.pos;  
                 instrument_changed();  
             }  
         }  
   
468          if (!is_in_resize_zone(event->x, event->y) && cursor_is_resize) {          if (!is_in_resize_zone(event->x, event->y) && cursor_is_resize) {
469              get_window()->set_cursor();              get_window()->set_cursor();
470              cursor_is_resize = false;              cursor_is_resize = false;
471          }          }
472      } else if (move.active) {      } else if (move.active) {
473    #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
474          get_window()->pointer_ungrab(event->time);          get_window()->pointer_ungrab(event->time);
475    #else
476            Glib::wrap(event->device, true)->ungrab(event->time);
477    #endif
478          move.active = false;          move.active = false;
479    
         if (move.pos) {  
             region->KeyRange.low += move.pos;  
             region->KeyRange.high += move.pos;  
   
             // find the r which is the first one to the right of region  
             // at its new position  
             gig::Region* r;  
             gig::Region* prev_region = 0;  
             for (r = instrument->GetFirstRegion() ; r ; r = instrument->GetNextRegion()) {  
                 if (r->KeyRange.low > region->KeyRange.low) break;  
                 prev_region = r;  
             }  
   
             // place region before r if it's not already there  
             if (prev_region != region) {  
                 instrument->MoveRegion(region, r);  
             }  
         }  
   
480          if (is_in_resize_zone(event->x, event->y)) {          if (is_in_resize_zone(event->x, event->y)) {
481    #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
482              get_window()->set_cursor(Gdk::Cursor(Gdk::SB_H_DOUBLE_ARROW));              get_window()->set_cursor(Gdk::Cursor(Gdk::SB_H_DOUBLE_ARROW));
483    #else
484                get_window()->set_cursor(Gdk::Cursor::create(Gdk::SB_H_DOUBLE_ARROW));
485    #endif
486              cursor_is_resize = true;              cursor_is_resize = true;
487          }          }
488      }      }
489      return true;      return true;
490  }  }
491    
492    void RegionChooser::update_after_resize()
493    {
494        if (resize.mode == resize.moving_high_limit) {
495            if (resize.region->KeyRange.high != resize.pos - 1) {
496                instrument_struct_to_be_changed_signal.emit(instrument);
497                resize.region->SetKeyRange(resize.region->KeyRange.low,
498                                           resize.pos - 1);
499                regions.update(instrument);
500                instrument_changed.emit();
501                instrument_struct_changed_signal.emit(instrument);
502            }
503        } else if (resize.mode == resize.moving_low_limit) {
504            if (resize.region->KeyRange.low != resize.pos) {
505                instrument_struct_to_be_changed_signal.emit(instrument);
506                resize.region->SetKeyRange(resize.pos,
507                                           resize.region->KeyRange.high);
508                regions.update(instrument);
509                instrument_changed.emit();
510                instrument_struct_changed_signal.emit(instrument);
511            }
512        }
513    }
514    
515    void RegionChooser::update_after_move(int pos)
516    {
517        instrument_struct_to_be_changed_signal.emit(instrument);
518        const int range = region->KeyRange.high - region->KeyRange.low;
519        const int diff  = pos - int(region->KeyRange.low);
520        region->SetKeyRange(pos, pos + range);
521        if (Settings::singleton()->moveRootNoteWithRegionMoved) {
522            for (int i = 0; i < 256; ++i) {
523                gig::DimensionRegion* dimrgn = region->pDimensionRegions[i];
524                if (!dimrgn || !dimrgn->pSample || !dimrgn->PitchTrack) continue;
525                dimrgn->UnityNote += diff;
526            }
527        }
528        regions.update(instrument);
529        instrument_changed.emit();
530        instrument_struct_changed_signal.emit(instrument);
531    }
532    
533  bool RegionChooser::on_button_press_event(GdkEventButton* event)  bool RegionChooser::on_button_press_event(GdkEventButton* event)
534  {  {
535      if (!instrument) return true;      if (!instrument) return true;
536    
537      int k = int(event->x / (width - 1) * 128.0);      const int w = get_width() - 1;
538        const int k = x_to_key(event->x, w);
539    
540        if (event->type == GDK_BUTTON_PRESS) {
541            if (event->y >= REGION_BLOCK_HEIGHT) {
542                int velocity = (event->y >= REGION_BLOCK_HEIGHT + KEYBOARD_HEIGHT - 1) ? 127 :
543                               int(float(event->y - REGION_BLOCK_HEIGHT) / float(KEYBOARD_HEIGHT) * 128.0f) + 1;
544                currentActiveKey = k;
545                keyboard_key_hit_signal.emit(k, velocity);
546            }
547        }
548    
549        // left mouse button double click
550        if (event->type == GDK_2BUTTON_PRESS && event->button == 1) {
551            if (event->y < REGION_BLOCK_HEIGHT) {
552                // show dimension manager dialog for this region
553                manage_dimensions();
554            }
555        }
556    
557        if (event->y >= REGION_BLOCK_HEIGHT) return true;
558      if (event->type == GDK_BUTTON_PRESS && event->button == 3) {      if (event->type == GDK_BUTTON_PRESS && event->button == 3) {
559          gig::Region* r = get_region(k);          gig::Region* r = get_region(k);
560          if (r) {          if (r) {
561              region = r;              region = r;
562              queue_draw();              queue_draw();
563              region_selected();              region_selected();
564                dimensionManager.set_region(region);
565              popup_menu_inside_region->popup(event->button, event->time);              popup_menu_inside_region->popup(event->button, event->time);
566          } else {          } else {
567              new_region_pos = k;              new_region_pos = k;
# Line 313  bool RegionChooser::on_button_press_even Line 569  bool RegionChooser::on_button_press_even
569          }          }
570      } else {      } else {
571          if (is_in_resize_zone(event->x, event->y)) {          if (is_in_resize_zone(event->x, event->y)) {
572    #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
573              get_window()->pointer_grab(false,              get_window()->pointer_grab(false,
574                                         Gdk::BUTTON_RELEASE_MASK |                                         Gdk::BUTTON_RELEASE_MASK |
575                                         Gdk::POINTER_MOTION_MASK |                                         Gdk::POINTER_MOTION_MASK |
576                                         Gdk::POINTER_MOTION_HINT_MASK,                                         Gdk::POINTER_MOTION_HINT_MASK,
577                                         Gdk::Cursor(Gdk::SB_H_DOUBLE_ARROW), event->time);                                         Gdk::Cursor(Gdk::SB_H_DOUBLE_ARROW),
578                                           event->time);
579    #else
580                Glib::wrap(event->device, true)->grab(get_window(),
581                                                      Gdk::OWNERSHIP_NONE,
582                                                      false,
583                                                      Gdk::BUTTON_RELEASE_MASK |
584                                                      Gdk::POINTER_MOTION_MASK |
585                                                      Gdk::POINTER_MOTION_HINT_MASK,
586                                                      Gdk::Cursor::create(Gdk::SB_H_DOUBLE_ARROW),
587                                                      event->time);
588    #endif
589              resize.active = true;              resize.active = true;
590          } else {          } else {
591              gig::Region* r = get_region(k);              gig::Region* r = get_region(k);
# Line 325  bool RegionChooser::on_button_press_even Line 593  bool RegionChooser::on_button_press_even
593                  region = r;                  region = r;
594                  queue_draw();                  queue_draw();
595                  region_selected();                  region_selected();
596                    dimensionManager.set_region(region);
597    
598    #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
599                  get_window()->pointer_grab(false,                  get_window()->pointer_grab(false,
600                                             Gdk::BUTTON_RELEASE_MASK |                                             Gdk::BUTTON_RELEASE_MASK |
601                                             Gdk::POINTER_MOTION_MASK |                                             Gdk::POINTER_MOTION_MASK |
602                                             Gdk::POINTER_MOTION_HINT_MASK,                                             Gdk::POINTER_MOTION_HINT_MASK,
603                                             Gdk::Cursor(Gdk::FLEUR), event->time);                                             Gdk::Cursor(Gdk::FLEUR),
604                                               event->time);
605    #else
606                    Glib::wrap(event->device, true)->grab(get_window(),
607                                                          Gdk::OWNERSHIP_NONE,
608                                                          false,
609                                                          Gdk::BUTTON_RELEASE_MASK |
610                                                          Gdk::POINTER_MOTION_MASK |
611                                                          Gdk::POINTER_MOTION_HINT_MASK,
612                                                          Gdk::Cursor::create(Gdk::FLEUR),
613                                                          event->time);
614    #endif
615                  move.active = true;                  move.active = true;
616                  move.from_x = event->x;                  move.offset = event->x - key_to_x(region->KeyRange.low, w);
                 move.pos = 0;  
617              }              }
618          }          }
619      }      }
# Line 342  bool RegionChooser::on_button_press_even Line 622  bool RegionChooser::on_button_press_even
622    
623  gig::Region* RegionChooser::get_region(int key)  gig::Region* RegionChooser::get_region(int key)
624  {  {
625      gig::Region* prev_region = 0;      for (gig::Region* r = regions.first() ; r ; r = regions.next()) {
     gig::Region* next_region;  
     for (gig::Region *r = instrument->GetFirstRegion() ; r ;  
          r = next_region) {  
         next_region = instrument->GetNextRegion();  
   
626          if (key < r->KeyRange.low) return 0;          if (key < r->KeyRange.low) return 0;
627          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;  
628      }      }
629      return 0;      return 0;
630  }  }
631    
632    void RegionChooser::set_region(gig::Region* region) {
633        this->region = region;
634        queue_draw();
635        region_selected();
636        dimensionManager.set_region(region);
637    }
638    
639  void RegionChooser::motion_resize_region(int x, int y)  void RegionChooser::motion_resize_region(int x, int y)
640  {  {
641      const int w = width - 1;      const int w = get_width() - 1;
     Glib::RefPtr<Gdk::Window> window = get_window();  
642    
643      int k = int(double(x) / w * 128.0 + 0.5);      int k = int(double(x) / w * 128.0 + 0.5);
644    
# Line 382  void RegionChooser::motion_resize_region Line 658  void RegionChooser::motion_resize_region
658                  resize.mode = resize.moving_low_limit;                  resize.mode = resize.moving_low_limit;
659              }              }
660          }          }
661          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);  
662    
663            int x1, x2;
664          if (resize.mode == resize.moving_high_limit) {          if (resize.mode == resize.moving_high_limit) {
665              if (k > resize.pos) {              if (resize.region->KeyRange.high < resize.pos - 1) {
666                  window->draw_rectangle(white, true, prevx, 1, x - prevx, h1 - 2);                  x1 = resize.region->KeyRange.high;
667                  window->draw_line(black, prevx, 0, x, 0);                  x2 = resize.pos - 1;
                 window->draw_line(black, prevx, h1 - 1, x, h1 - 1);  
668              } else {              } else {
669                  int xx = ((resize.pos == resize.max && resize.max != 128) ? 1 : 0);                  x1 = resize.pos - 1;
670                  window->draw_rectangle(bg, true, x + 1, 0, prevx - x - xx, h1);                  x2 = resize.region->KeyRange.high;
671              }              }
672          } else {          } else {
673              if (k < resize.pos) {              if (resize.region->KeyRange.low < resize.pos) {
674                  window->draw_rectangle(white, true, x + 1, 1, prevx - x, h1 - 2);                  x1 = resize.region->KeyRange.low;
675                  window->draw_line(black, x, 0, prevx, 0);                  x2 = resize.pos;
                 window->draw_line(black, x, h1 - 1, prevx, h1 - 1);  
676              } else {              } else {
677                  int xx = ((resize.pos == resize.min && resize.min != 0) ? 1 : 0);                  x1 = resize.pos;
678                  window->draw_rectangle(bg, true, prevx + xx, 0, x - prevx - xx, h1);                  x2 = resize.region->KeyRange.low;
679              }              }
680          }          }
681          window->draw_line(black, x, 1, x, h1 - 2);          x1 = key_to_x(x1, w);
682          resize.pos = k;          x2 = key_to_x(x2 + 1, w) + 1;
683            Gdk::Rectangle rect(x1, 0, x2 - x1, h1);
684    
685            update_after_resize();
686    
687            get_window()->invalidate_rect(rect, false);
688      }      }
689  }  }
690    
691  void RegionChooser::motion_move_region(int x, int y)  void RegionChooser::motion_move_region(int x, int y)
692  {  {
693      const int w = width - 1;      const int w = get_width() - 1;
     Glib::RefPtr<Gdk::Window> window = get_window();  
694    
695      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);
696      if (k == move.pos) return;  
697      int new_k;      if (l == region->KeyRange.low) return;
698      bool new_touch_left;      int new_l;
699      bool new_touch_right;      int regionsize = region->KeyRange.high - region->KeyRange.low;
700      int a = 0;      int a = 0;
701      if (k > move.pos) {      if (l > region->KeyRange.low) {
702          for (gig::Region* r = instrument->GetFirstRegion() ; ;          for (gig::Region* r = regions.first() ; ; r = regions.next()) {
              r = instrument->GetNextRegion()) {  
703              if (r != region) {              if (r != region) {
704                  int b = r ? r->KeyRange.low : 128;                  int b = r ? r->KeyRange.low : 128;
705    
706                  // gap: from a to b (not inclusive b)                  // gap: from a to b (not inclusive b)
707    
708                  if (region->KeyRange.high + move.pos >= b) {                  if (region->KeyRange.high >= b) {
709                      // not found the current gap yet, just continue                      // not found the current gap yet, just continue
710                  } else {                  } else {
711    
712                      if (a > region->KeyRange.low + k) {                      if (a > l) {
713                          // this gap is too far to the right, break                          // this gap is too far to the right, break
714                          break;                          break;
715                      }                      }
716    
717                      int newhigh = std::min(region->KeyRange.high + k, b - 1);                      int newhigh = std::min(l + regionsize, b - 1);
718                      int newlo = newhigh - (region->KeyRange.high - region->KeyRange.low);                      int newlo = newhigh - regionsize;
719    
720                      if (newlo >= a) {                      if (newlo >= a) {
721                          // yes it fits - it's a candidate                          // yes it fits - it's a candidate
722                          new_k = newlo - region->KeyRange.low;                          new_l = newlo;
                         new_touch_left = a > 0 && a == newlo;  
                         new_touch_right = b < 128 && newhigh + 1 == b;  
723                      }                      }
724                  }                  }
725                  if (!r) break;                  if (!r) break;
# Line 459  void RegionChooser::motion_move_region(i Line 727  void RegionChooser::motion_move_region(i
727              }              }
728          }          }
729      } else {      } else {
730          for (gig::Region* r = instrument->GetFirstRegion() ; ;          for (gig::Region* r = regions.first() ; ; r = regions.next()) {
              r = instrument->GetNextRegion()) {  
731              if (r != region) {              if (r != region) {
732                  int b = r ? r->KeyRange.low : 128;                  int b = r ? r->KeyRange.low : 128;
733    
734                  // gap from a to b (not inclusive b)                  // gap from a to b (not inclusive b)
735    
736                  if (region->KeyRange.high + k >= b) {                  if (l + regionsize >= b) {
737                      // not found the current gap yet, just continue                      // not found the current gap yet, just continue
738                  } else {                  } else {
739    
740                      if (a > region->KeyRange.low + move.pos) {                      if (a > region->KeyRange.low) {
741                          // this gap is too far to the right, break                          // this gap is too far to the right, break
742                          break;                          break;
743                      }                      }
744    
745                      int newlo = std::max(region->KeyRange.low + k, a);                      int newlo = std::max(l, a);
746                      int newhigh = newlo + (region->KeyRange.high - region->KeyRange.low);                      int newhigh = newlo + regionsize;
747    
748                      if (newhigh < b) {                      if (newhigh < b) {
749                          // yes it fits - break as the first one is the best                          // yes it fits - break as the first one is the best
750                          new_k = newlo - region->KeyRange.low;                          new_l = newlo;
                         new_touch_left = a > 0 && a == newlo;  
                         new_touch_right = b < 128 && newhigh + 1 == b;  
751                          break;                          break;
752                      }                      }
753                  }                  }
# Line 491  void RegionChooser::motion_move_region(i Line 756  void RegionChooser::motion_move_region(i
756              }              }
757          }          }
758      }      }
759      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);  
760    
761          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);
762          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),
763                                   new_l + regionsize) + 1, w) + 1;
764    
765          window->draw_rectangle(gc, true, x + 1, 1, std::min(x2 - 1, prevx) - x, h1 - 2);      Gdk::Rectangle rect(x1, 0, x2 - x1, h1);
766      }      update_after_move(new_l);
767    
768      move.pos = k;      get_window()->invalidate_rect(rect, false);
     move.touch_left = new_touch_left;  
     move.touch_right = new_touch_right;  
769  }  }
770    
771    
# Line 538  bool RegionChooser::on_motion_notify_eve Line 776  bool RegionChooser::on_motion_notify_eve
776      Gdk::ModifierType state = Gdk::ModifierType(0);      Gdk::ModifierType state = Gdk::ModifierType(0);
777      window->get_pointer(x, y, state);      window->get_pointer(x, y, state);
778    
779        // handle virtual MIDI keyboard
780        if (m_VirtKeybModeChoice.get_value() != VIRT_KEYBOARD_MODE_CHORD &&
781            currentActiveKey > 0 &&
782            event->y >= REGION_BLOCK_HEIGHT &&
783            event->y < REGION_BLOCK_HEIGHT + KEYBOARD_HEIGHT)
784        {
785            const int k = x_to_key(event->x, get_width() - 1);
786            if (k != currentActiveKey) {
787                int velocity =
788                    (event->y >= REGION_BLOCK_HEIGHT + KEYBOARD_HEIGHT - 1) ? 127 :
789                    int(float(event->y - REGION_BLOCK_HEIGHT) /
790                        float(KEYBOARD_HEIGHT) * 128.0f) + 1;
791                if (velocity <= 0) velocity = 1;
792                keyboard_key_released_signal.emit(currentActiveKey, velocity);
793                currentActiveKey = k;
794                keyboard_key_hit_signal.emit(k, velocity);
795            }
796        }
797    
798      if (resize.active) {      if (resize.active) {
799          motion_resize_region(x, y);          motion_resize_region(x, y);
800      } else if (move.active) {      } else if (move.active) {
# Line 545  bool RegionChooser::on_motion_notify_eve Line 802  bool RegionChooser::on_motion_notify_eve
802      } else {      } else {
803          if (is_in_resize_zone(x, y)) {          if (is_in_resize_zone(x, y)) {
804              if (!cursor_is_resize) {              if (!cursor_is_resize) {
805    #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
806                  window->set_cursor(Gdk::Cursor(Gdk::SB_H_DOUBLE_ARROW));                  window->set_cursor(Gdk::Cursor(Gdk::SB_H_DOUBLE_ARROW));
807    #else
808                    window->set_cursor(Gdk::Cursor::create(Gdk::SB_H_DOUBLE_ARROW));
809    #endif
810                  cursor_is_resize = true;                  cursor_is_resize = true;
811              }              }
812          } else if (cursor_is_resize) {          } else if (cursor_is_resize) {
# Line 558  bool RegionChooser::on_motion_notify_eve Line 819  bool RegionChooser::on_motion_notify_eve
819  }  }
820    
821  bool RegionChooser::is_in_resize_zone(double x, double y) {  bool RegionChooser::is_in_resize_zone(double x, double y) {
822      const int w = width - 1;      const int w = get_width() - 1;
823    
824      if (instrument && y >= 0 && y <= h1) {      if (instrument && y >= 0 && y <= h1) {
825          gig::Region* prev_region = 0;          gig::Region* prev_region = 0;
826          gig::Region* next_region;          gig::Region* next_region;
827          for (gig::Region* r = instrument->GetFirstRegion() ; r ; r = next_region) {          for (gig::Region* r = regions.first(); r ; r = next_region) {
828              next_region = instrument->GetNextRegion();              next_region = regions.next();
829    
830              int lo = int(w * (r->KeyRange.low) / 128.0 + 0.5);              int lo = key_to_x(r->KeyRange.low, w);
831              if (x <= lo - 2) break;              if (x <= lo - 2) break;
832              if (x < lo + 2) {              if (x < lo + 2) {
833                  resize.region = r;                  resize.region = r;
# Line 580  bool RegionChooser::is_in_resize_zone(do Line 841  bool RegionChooser::is_in_resize_zone(do
841                      resize.mode = resize.undecided;                      resize.mode = resize.undecided;
842                      resize.min = prev_region->KeyRange.low + 1;                      resize.min = prev_region->KeyRange.low + 1;
843                      resize.prev_region = prev_region;                      resize.prev_region = prev_region;
844                      return true;                      return resize.min != resize.max;
845                  }                  }
846    
847                  // edit low limit                  // edit low limit
848                  resize.mode = resize.moving_low_limit;                  resize.mode = resize.moving_low_limit;
849                  resize.min = prev_region ? prev_region->KeyRange.high + 1 : 0;                  resize.min = prev_region ? prev_region->KeyRange.high + 1 : 0;
850                  return true;                  return resize.min != resize.max;
851              }              }
852              if (!next_region || r->KeyRange.high + 1 != next_region->KeyRange.low) {              if (!next_region || r->KeyRange.high + 1 != next_region->KeyRange.low) {
853                  int hi = int(w * (r->KeyRange.high + 1) / 128.0 + 0.5);                  int hi = key_to_x(r->KeyRange.high + 1, w);
854                  if (x <= hi - 2) break;                  if (x <= hi - 2) break;
855                  if (x < hi + 2) {                  if (x < hi + 2) {
856                      // edit high limit                      // edit high limit
# Line 598  bool RegionChooser::is_in_resize_zone(do Line 859  bool RegionChooser::is_in_resize_zone(do
859                      resize.mode = resize.moving_high_limit;                      resize.mode = resize.moving_high_limit;
860                      resize.min = r->KeyRange.low + 1;                      resize.min = r->KeyRange.low + 1;
861                      resize.max = next_region ? next_region->KeyRange.low : 128;                      resize.max = next_region ? next_region->KeyRange.low : 128;
862                      return true;                      return resize.min != resize.max;
863                  }                  }
864              }              }
865              prev_region = r;              prev_region = r;
# Line 607  bool RegionChooser::is_in_resize_zone(do Line 868  bool RegionChooser::is_in_resize_zone(do
868      return false;      return false;
869  }  }
870    
871  sigc::signal<void> RegionChooser::signal_region_selected()  sigc::signal<void>& RegionChooser::signal_region_selected()
872  {  {
873      return region_selected;      return region_selected;
874  }  }
875    
876  sigc::signal<void> RegionChooser::signal_instrument_changed()  sigc::signal<void>& RegionChooser::signal_instrument_changed()
877  {  {
878      return instrument_changed;      return instrument_changed;
879  }  }
# Line 620  sigc::signal<void> RegionChooser::signal Line 881  sigc::signal<void> RegionChooser::signal
881  void RegionChooser::show_region_properties()  void RegionChooser::show_region_properties()
882  {  {
883      if (!region) return;      if (!region) return;
884      Gtk::Dialog dialog("Region Properties", true /*modal*/);      Gtk::Dialog dialog(_("Region Properties"), true /*modal*/);
885      // add "Keygroup" checkbox      // add "Keygroup" checkbox
886      Gtk::CheckButton checkBoxKeygroup("Member of a Keygroup (Exclusive Group)");      Gtk::CheckButton checkBoxKeygroup(_("Member of a Keygroup (Exclusive Group)"));
887      checkBoxKeygroup.set_active(region->KeyGroup);      checkBoxKeygroup.set_active(region->KeyGroup);
888      dialog.get_vbox()->pack_start(checkBoxKeygroup);      dialog.get_vbox()->pack_start(checkBoxKeygroup);
889      checkBoxKeygroup.show();      checkBoxKeygroup.show();
890      // add "Keygroup" spinbox      // add "Keygroup" spinbox
891      Gtk::Adjustment adjustment(1, 1, pow(2,32));  #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
892        Gtk::Adjustment adjustment(1, 1, 999);
893      Gtk::SpinButton spinBox(adjustment);      Gtk::SpinButton spinBox(adjustment);
894    #else
895        Gtk::SpinButton spinBox(Gtk::Adjustment::create(1, 1, 999));
896    #endif
897      if (region->KeyGroup) spinBox.set_value(region->KeyGroup);      if (region->KeyGroup) spinBox.set_value(region->KeyGroup);
898      dialog.get_vbox()->pack_start(spinBox);      dialog.get_vbox()->pack_start(spinBox);
899      spinBox.show();      spinBox.show();
# Line 644  void RegionChooser::show_region_properti Line 909  void RegionChooser::show_region_properti
909    
910  void RegionChooser::add_region()  void RegionChooser::add_region()
911  {  {
912      gig::Region* r;      instrument_struct_to_be_changed_signal.emit(instrument);
     for (r = instrument->GetFirstRegion() ; r ; r = instrument->GetNextRegion()) {  
         if (r->KeyRange.low > new_region_pos) break;  
     }  
913    
914      region = instrument->AddRegion();      region = instrument->AddRegion();
915      region->KeyRange.low = region->KeyRange.high = new_region_pos;      region->SetKeyRange(new_region_pos, new_region_pos);
916    
917        instrument_struct_changed_signal.emit(instrument);
918        regions.update(instrument);
919    
     instrument->MoveRegion(region, r);  
920      queue_draw();      queue_draw();
921      region_selected();      region_selected();
922        dimensionManager.set_region(region);
923      instrument_changed();      instrument_changed();
924  }  }
925    
926  void RegionChooser::delete_region()  void RegionChooser::delete_region()
927  {  {
928        instrument_struct_to_be_changed_signal.emit(instrument);
929      instrument->DeleteRegion(region);      instrument->DeleteRegion(region);
930        instrument_struct_changed_signal.emit(instrument);
931        regions.update(instrument);
932    
933      region = 0;      region = 0;
934      queue_draw();      queue_draw();
935      region_selected();      region_selected();
936        dimensionManager.set_region(region);
937      instrument_changed();      instrument_changed();
938  }  }
939    
# Line 678  void RegionChooser::on_dimension_manager Line 948  void RegionChooser::on_dimension_manager
948      region_selected();      region_selected();
949      instrument_changed();      instrument_changed();
950  }  }
951    
952    sigc::signal<void, gig::Instrument*>& RegionChooser::signal_instrument_struct_to_be_changed() {
953        return instrument_struct_to_be_changed_signal;
954    }
955    
956    sigc::signal<void, gig::Instrument*>& RegionChooser::signal_instrument_struct_changed() {
957        return instrument_struct_changed_signal;
958    }
959    
960    sigc::signal<void, gig::Region*>& RegionChooser::signal_region_to_be_changed() {
961        return region_to_be_changed_signal;
962    }
963    
964    sigc::signal<void, gig::Region*>& RegionChooser::signal_region_changed_signal() {
965        return region_changed_signal;
966    }
967    
968    sigc::signal<void, int/*key*/, int/*velocity*/>& RegionChooser::signal_keyboard_key_hit() {
969        return keyboard_key_hit_signal;
970    }
971    
972    sigc::signal<void, int/*key*/, int/*velocity*/>& RegionChooser::signal_keyboard_key_released() {
973        return keyboard_key_released_signal;
974    }

Legend:
Removed from v.1262  
changed lines
  Added in v.2841

  ViewVC Help
Powered by ViewVC