/[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 1303 by persson, Sun Aug 26 09:29:52 2007 UTC revision 2169 by persson, Sun Mar 6 07:51:04 2011 UTC
# Line 1  Line 1 
1  /*  /*
2   * Copyright (C) 2006, 2007 Andreas Persson   * Copyright (C) 2006-2011 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    #include <sstream>
24    
25    #include <cairomm/context.h>
26    #include <gdkmm/general.h>
27  #include <gdkmm/cursor.h>  #include <gdkmm/cursor.h>
28  #include <gtkmm/stock.h>  #include <gtkmm/stock.h>
29  #include <gtkmm/spinbutton.h>  #include <gtkmm/spinbutton.h>
30  #include <gtkmm/dialog.h>  #include <gtkmm/dialog.h>
 #include <libintl.h>  
 #include <math.h>  
31    
32  #define _(String) gettext(String)  #include "global.h"
33    
34  RegionChooser::RegionChooser()  #define REGION_BLOCK_HEIGHT             20
35  {  #define KEYBOARD_HEIGHT                 40
36      Glib::RefPtr<Gdk::Colormap> colormap = get_default_colormap();  
37    void SortedRegions::update(gig::Instrument* instrument) {
38        // 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      red = Gdk::Color("#8070ff");  gig::Region* SortedRegions::first() {
53      grey1 = Gdk::Color("#b0b0b0");      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;      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"), NULL };
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    
105      actionGroup = Gtk::ActionGroup::create();      actionGroup = Gtk::ActionGroup::create();
106      actionGroup->add(Gtk::Action::create("Properties",      actionGroup->add(Gtk::Action::create("Properties",
# Line 79  RegionChooser::RegionChooser() Line 137  RegionChooser::RegionChooser()
137      add_events(Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK |      add_events(Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK |
138                 Gdk::POINTER_MOTION_MASK | Gdk::POINTER_MOTION_HINT_MASK);                 Gdk::POINTER_MOTION_MASK | Gdk::POINTER_MOTION_HINT_MASK);
139    
140      dimensionManager.articulation_changed_signal.connect(      dimensionManager.region_to_be_changed_signal.connect(
141          sigc::mem_fun(*this, &RegionChooser::on_dimension_manager_changed)          region_to_be_changed_signal.make_slot()
142        );
143        dimensionManager.region_changed_signal.connect(
144            region_changed_signal.make_slot()
145        );
146        dimensionManager.region_changed_signal.connect(
147            sigc::hide(
148                sigc::mem_fun(*this, &RegionChooser::on_dimension_manager_changed)
149            )
150        );
151        keyboard_key_hit_signal.connect(
152            sigc::mem_fun(*this, &RegionChooser::on_note_on_event)
153        );
154        keyboard_key_released_signal.connect(
155            sigc::mem_fun(*this, &RegionChooser::on_note_off_event)
156      );      );
157  }  }
158    
# Line 88  RegionChooser::~RegionChooser() Line 160  RegionChooser::~RegionChooser()
160  {  {
161  }  }
162    
163  void RegionChooser::on_realize()  template<class T> inline std::string ToString(T o) {
164  {      std::stringstream ss;
165      // We need to call the base on_realize()      ss << o;
166      Gtk::DrawingArea::on_realize();      return ss.str();
167    }
168    
169      // Now we can allocate any additional resources we need  void RegionChooser::on_note_on_event(int key, int velocity) {
170      Glib::RefPtr<Gdk::Window> window = get_window();      draw_key(key, activeKeyColor);
171      gc = Gdk::GC::create(window);      m_VirtKeybVelocityLabel.set_text(ToString(velocity));
172      window->clear();  }
173    
174    void RegionChooser::on_note_off_event(int key, int velocity) {
175        if (is_black_key(key)) {
176            draw_key(key, black);
177        } else {
178            draw_key(key, key >= 21 && key <= 108 ? white : grey1);
179        }
180        m_VirtKeybOffVelocityLabel.set_text(ToString(velocity));
181  }  }
182    
183  bool RegionChooser::on_expose_event(GdkEventExpose* event)  #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
184    bool RegionChooser::on_expose_event(GdkEventExpose* e)
185  {  {
186      Glib::RefPtr<Gdk::Window> window = get_window();      return on_draw(get_window()->create_cairo_context());
187      window->clear();  }
188      const int h = 40;  #endif
189      const int w = width - 1;  
190    bool RegionChooser::on_draw(const Cairo::RefPtr<Cairo::Context>& cr)
191    {
192        const int h = KEYBOARD_HEIGHT;
193        const int w = get_width() - 1;
194      const int bh = int(h * 0.55);      const int bh = int(h * 0.55);
195    
196      Glib::RefPtr<const Gdk::GC> black = get_style()->get_black_gc();      cr->save();
197      Glib::RefPtr<const Gdk::GC> white = get_style()->get_white_gc();      cr->set_line_width(1);
198    
199      Glib::RefPtr<Pango::Context> context = get_pango_context();  #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
200      Glib::RefPtr<Pango::Layout> layout = Pango::Layout::create(context);      const Gdk::Color bg = get_style()->get_bg(Gtk::STATE_NORMAL);
201    #else
202        const Gdk::RGBA bg = get_style_context()->get_background_color();
203    #endif
204        Gdk::Cairo::set_source_rgba(cr, bg);
205        cr->paint();
206    
207        Gdk::Cairo::set_source_rgba(cr, black);
208        cr->rectangle(0.5, h1 + 0.5, w, h - 1);
209        cr->stroke();
210    
     window->draw_rectangle(black, false, 0, h1, w, h - 1);  
     gc->set_foreground(grey1);  
211      int x1 = int(w * 20.5 / 128.0 + 0.5);      int x1 = int(w * 20.5 / 128.0 + 0.5);
212      int x2 = int(w * 109.5 / 128.0 + 0.5);      int x2 = int(w * 109.5 / 128.0 + 0.5);
213      window->draw_rectangle(gc, true, 1, h1 + 1,  
214                             x1 - 1, h - 2);      Gdk::Cairo::set_source_rgba(cr, grey1);
215      window->draw_rectangle(white, true, x1 + 1, h1 + 1, x2 - x1 - 1, h - 2);      cr->rectangle(1, h1 + 1, x1 - 1, h - 2);
216      window->draw_rectangle(gc, true, x2 + 1, h1 + 1,      cr->fill();
217                             w - x2 - 1, h - 2);  
218      int octave = -1;      Gdk::Cairo::set_source_rgba(cr, white);
219        cr->rectangle(x1 + 1, h1 + 1, x2 - x1 - 1, h - 2);
220        cr->fill();
221    
222        Gdk::Cairo::set_source_rgba(cr, grey1);
223        cr->rectangle(x2 + 1, h1 + 1, w - x2 - 1, h - 2);
224        cr->fill();
225    
226        Gdk::Cairo::set_source_rgba(cr, black);
227      for (int i = 0 ; i < 128 ; i++) {      for (int i = 0 ; i < 128 ; i++) {
228          int note = (i + 3) % 12;          int note = (i + 3) % 12;
229          int x = int(w * i / 128.0 + 0.5);          int x = int(w * i / 128.0 + 0.5);
230    
231          if (note == 1 || note == 4 || note == 6 || note == 9 || note == 11) {          if (note == 1 || note == 4 || note == 6 ||
232                note == 9 || note == 11) {
233              int x2 = int(w * (i + 0.5) / 128.0 + 0.5);              int x2 = int(w * (i + 0.5) / 128.0 + 0.5);
234              window->draw_line(black, x2, h1 + bh, x2, h1 + h);              cr->move_to(x2 + 0.5, h1 + bh + 0.5);
235                cr->line_to(x2 + 0.5, h1 + h - 1);
236                cr->stroke();
237    
238              int x3 = int(w * (i + 1) / 128.0 + 0.5);              int x3 = int(w * (i + 1) / 128.0 + 0.5);
239              window->draw_rectangle(black, true, x, h1 + 1, x3 - x + 1, bh);              cr->rectangle(x, h1 + 1, x3 - x + 1, bh);
240                cr->fill();
241          } else if (note == 3 || note == 8) {          } else if (note == 3 || note == 8) {
242              window->draw_line(black, x, h1 + 1, x, h1 + h);              cr->move_to(x + 0.5, h1 + 1);
243          }              cr->line_to(x + 0.5, h1 + h - 1);
244          if (note == 3) {              cr->stroke();
245              char buf[30];  
246              sprintf(buf, "<span size=\"x-small\">%d</span>", octave);              if (note == 3) draw_digit(i);
             layout->set_markup(buf);  
             Pango::Rectangle rectangle = layout->get_logical_extents();  
             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++;  
247          }          }
248      }      }
249    
250      if (instrument) {      if (instrument) {
251          int i = 0;          int i = 0;
252          gig::Region *next_region;          gig::Region* next_region;
253          int x3 = -1;          int x3 = -1;
254          for (gig::Region *r = instrument->GetFirstRegion() ;          for (gig::Region* r = regions.first() ; r ; r = next_region) {
              r ;  
              r = next_region) {  
255    
256              if (x3 < 0) x3 = int(w * (r->KeyRange.low) / 128.0 + 0.5);              if (x3 < 0) x3 = int(w * (r->KeyRange.low) / 128.0 + 0.5);
257              next_region = instrument->GetNextRegion();              next_region = regions.next();
258              if (!next_region || r->KeyRange.high + 1 != next_region->KeyRange.low) {              if (!next_region ||
259                    r->KeyRange.high + 1 != next_region->KeyRange.low) {
260                  int x2 = int(w * (r->KeyRange.high + 1) / 128.0 + 0.5);                  int x2 = int(w * (r->KeyRange.high + 1) / 128.0 + 0.5);
261                  window->draw_line(black, x3, 0, x2, 0);                  cr->move_to(x3, 0.5);
262                  window->draw_line(black, x3, h1 - 1, x2, h1 - 1);                  cr->line_to(x2 + 0.5, 0.5);
263                  window->draw_line(black, x2, 1, x2, h1 - 2);                  cr->line_to(x2 + 0.5, h1 - 0.5);
264                  window->draw_rectangle(white, true, x3 + 1, 1, x2 - x3 - 1, h1 - 2);                  cr->line_to(x3, h1 - 0.5);
265                    cr->stroke();
266    
267                    Gdk::Cairo::set_source_rgba(cr, white);
268                    cr->rectangle(x3 + 1, 1, x2 - x3 - 1, h1 - 2);
269                    cr->fill();
270                    Gdk::Cairo::set_source_rgba(cr, black);
271    
272                  x3 = -1;                  x3 = -1;
273              }              }
274              i++;              i++;
275          }          }
276    
277          for (gig::Region *r = instrument->GetFirstRegion() ;          for (gig::Region* r = regions.first() ; r ; r = regions.next()) {
              r ;  
              r = instrument->GetNextRegion()) {  
278              int x = int(w * (r->KeyRange.low) / 128.0 + 0.5);              int x = int(w * (r->KeyRange.low) / 128.0 + 0.5);
279              window->draw_line(black, x, 1, x, h1 - 2);              cr->move_to(x + 0.5, 1);
280                cr->line_to(x + 0.5, h1 - 1);
281                cr->stroke();
282          }          }
283    
284          if (region) {          if (region) {
285              int x1 = int(w * (region->KeyRange.low) / 128.0 + 0.5);              int x1 = int(w * (region->KeyRange.low) / 128.0 + 0.5);
286              int x2 = int(w * (region->KeyRange.high + 1) / 128.0 + 0.5);              int x2 = int(w * (region->KeyRange.high + 1) / 128.0 + 0.5);
287              gc->set_foreground(red);              Gdk::Cairo::set_source_rgba(cr, red);
288              window->draw_rectangle(gc, true, x1 + 1, 1, x2 - x1 - 1, h1 - 2);              cr->rectangle(x1 + 1, 1, x2 - x1 - 1, h1 - 2);
289                cr->fill();
290          }          }
291      }      }
292    
293        cr->restore();
294    
295      return true;      return true;
296  }  }
297    
298    
299  void RegionChooser::on_size_request(GtkRequisition* requisition)  bool RegionChooser::is_black_key(int key) {
300  {      const int note = (key + 3) % 12;
301      *requisition = GtkRequisition();      return note == 1 || note == 4 || note == 6 || note == 9 || note == 11;
302      requisition->height = 40 + 20;  }
303      requisition->width = 500;  
304    void RegionChooser::draw_digit(int key) {
305        const int h = KEYBOARD_HEIGHT;
306        const int w = get_width() - 1;
307        Glib::RefPtr<Pango::Layout> layout = Pango::Layout::create(get_pango_context());
308        char buf[30];
309        sprintf(buf, "<span size=\"8000\">%d</span>", key / 12 - 1);
310        layout->set_markup(buf);
311        Pango::Rectangle rectangle = layout->get_logical_extents();
312        double text_w = double(rectangle.get_width()) / Pango::SCALE;
313        double text_h = double(rectangle.get_height()) / Pango::SCALE;
314        double x = w * (key + 0.75) / 128.0;
315        Cairo::RefPtr<Cairo::Context> cr = get_window()->create_cairo_context();
316        Gdk::Cairo::set_source_rgba(cr, black);
317        cr->move_to(int(x - text_w / 2 + 1), int(h1 + h - text_h + 0.5));
318    #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 16) || GTKMM_MAJOR_VERSION < 2
319        pango_cairo_show_layout(cr->cobj(), layout->gobj());
320    #else
321        layout->show_in_cairo_context(cr);
322    #endif
323  }  }
324    
325    void RegionChooser::draw_key(int key, const Gdk::RGBA& color)
 // not used  
 void RegionChooser::draw_region(int from, int to, const Gdk::Color& color)  
326  {  {
327      const int h = 40;      const int h = KEYBOARD_HEIGHT;
328      const int w = width;      const int w = get_width() - 1;
329      const int bh = int(h * 0.55);      const int bh = int(h * 0.55);
330    
331      Glib::RefPtr<Gdk::Window> window = get_window();      Cairo::RefPtr<Cairo::Context> cr = get_window()->create_cairo_context();
332      gc->set_foreground(color);      Gdk::Cairo::set_source_rgba(cr, color);
333    
334      for (int i = from ; i < to ; i++) {      int note = (key + 3) % 12;
335          int note = (i + 3) % 12;      int x = int(w * key / 128.0 + 0.5) + 1;
336          int x = int(w * i / 128.0 + 0.5) + 1;      int x2 = int(w * (key + 1.5) / 128.0 + 0.5);
337          int x2 = int(w * (i + 1.5) / 128.0 + 0.5);      int x3 = int(w * (key + 1) / 128.0 + 0.5);
338          int x3 = int(w * (i + 1) / 128.0 + 0.5);      int x4 = int(w * (key - 0.5) / 128.0 + 0.5);
339          int x4 = int(w * (i - 0.5) / 128 + 0.5) + 1;      int w1 = x3 - x;
340          int w1 = x3 - x;      switch (note) {
341          switch (note) {      case 0: case 5: case 10:
342          case 0: case 5: case 10:          cr->rectangle(x, h1 + 1, w1, bh);
343              window->draw_rectangle(gc, true, x, h1 + 1, w1, bh);          cr->fill();
344              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);
345              break;          cr->fill();
346          case 2: case 7:          break;
347              window->draw_rectangle(gc, true, x, h1 + 1, w1, bh);      case 2: case 7:
348              window->draw_rectangle(gc, true, x4, h1 + bh + 1, x3 - x4, h - bh - 2);          cr->rectangle(x, h1 + 1, w1, bh);
349              break;          cr->fill();
350          case 3: case 8:          cr->rectangle(x4 + 1, h1 + bh + 1, x3 - x4 - 1, h - bh - 2);
351              window->draw_rectangle(gc, true, x, h1 + 1, w1, bh);          cr->fill();
352              window->draw_rectangle(gc, true, x, h1 + bh + 1, x2 - x, h - bh - 2);          break;
353              break;      case 3: case 8:
354          default:          cr->rectangle(x, h1 + 1, w1, bh);
355              window->draw_rectangle(gc, true, x, h1 + 1, w1, bh - 1);          cr->fill();
356              break;          cr->rectangle(x, h1 + bh + 1, x2 - x, h - bh - 2);
357          }          cr->fill();
358            if (note == 3) draw_digit(key);
359            break;
360        default:
361            cr->rectangle(x, h1 + 1, w1, bh - 1);
362            cr->fill();
363            break;
364      }      }
365  }  }
366    
367  void RegionChooser::set_instrument(gig::Instrument* instrument)  void RegionChooser::set_instrument(gig::Instrument* instrument)
368  {  {
369      this->instrument = instrument;      this->instrument = instrument;
370      region = instrument ? instrument->GetFirstRegion() : 0;      regions.update(instrument);
371        region = regions.first();
372      queue_draw();      queue_draw();
373      region_selected();      region_selected();
374        dimensionManager.set_region(region);
375  }  }
376    
377  bool RegionChooser::on_button_release_event(GdkEventButton* event)  bool RegionChooser::on_button_release_event(GdkEventButton* event)
378  {  {
379        const int k = int(event->x / (get_width() - 1) * 128.0);
380    
381        // handle-note off on virtual keyboard
382        if (event->type == GDK_BUTTON_RELEASE) {
383            int velocity = (event->y >= REGION_BLOCK_HEIGHT + KEYBOARD_HEIGHT - 1) ? 127 :
384                           int(float(event->y - REGION_BLOCK_HEIGHT) / float(KEYBOARD_HEIGHT) * 128.0f) + 1;
385            if (velocity <= 0) velocity = 1;
386            switch (m_VirtKeybModeChoice.get_value()) {
387                case VIRT_KEYBOARD_MODE_CHORD:
388                    if (event->y >= REGION_BLOCK_HEIGHT)
389                        keyboard_key_released_signal.emit(k, velocity);
390                    break;
391                case VIRT_KEYBOARD_MODE_NORMAL:
392                default:
393                    if (currentActiveKey >= 0 && currentActiveKey <= 127) {
394                        keyboard_key_released_signal.emit(currentActiveKey, velocity);
395                        currentActiveKey = -1;
396                    }
397                    break;
398            }
399        }
400    
401      if (resize.active) {      if (resize.active) {
402    #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
403          get_window()->pointer_ungrab(event->time);          get_window()->pointer_ungrab(event->time);
404    #else
405            Glib::wrap(event->device, true)->ungrab(event->time);
406    #endif
407          resize.active = false;          resize.active = false;
408    
409          if (resize.mode == resize.moving_high_limit) {          if (resize.mode == resize.moving_high_limit) {
410              if (resize.region->KeyRange.high != resize.pos - 1) {              if (resize.region->KeyRange.high != resize.pos - 1) {
411                  resize.region->KeyRange.high = resize.pos - 1;                  instrument_struct_to_be_changed_signal.emit(instrument);
412                  instrument_changed();                  resize.region->SetKeyRange(
413                        resize.region->KeyRange.low, // low
414                        resize.pos - 1 // high
415                    );
416                    regions.update(instrument);
417                    instrument_changed.emit();
418                    instrument_struct_changed_signal.emit(instrument);
419              }              }
420          } else if (resize.mode == resize.moving_low_limit) {          } else if (resize.mode == resize.moving_low_limit) {
421              if (resize.region->KeyRange.low != resize.pos) {              if (resize.region->KeyRange.low != resize.pos) {
422                  resize.region->KeyRange.low = resize.pos;                  instrument_struct_to_be_changed_signal.emit(instrument);
423                  instrument_changed();                  resize.region->SetKeyRange(
424                        resize.pos, // low
425                        resize.region->KeyRange.high // high
426                    );
427                    regions.update(instrument);
428                    instrument_changed.emit();
429                    instrument_struct_changed_signal.emit(instrument);
430              }              }
431          }          }
432    
# Line 265  bool RegionChooser::on_button_release_ev Line 435  bool RegionChooser::on_button_release_ev
435              cursor_is_resize = false;              cursor_is_resize = false;
436          }          }
437      } else if (move.active) {      } else if (move.active) {
438    #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
439          get_window()->pointer_ungrab(event->time);          get_window()->pointer_ungrab(event->time);
440    #else
441            Glib::wrap(event->device, true)->ungrab(event->time);
442    #endif
443          move.active = false;          move.active = false;
444    
445          if (move.pos) {          if (move.pos) {
446              region->KeyRange.low += move.pos;              instrument_struct_to_be_changed_signal.emit(instrument);
447              region->KeyRange.high += move.pos;              region->SetKeyRange(
448                    region->KeyRange.low  + move.pos,
449              // find the r which is the first one to the right of region                  region->KeyRange.high + move.pos
450              // at its new position              );
451              gig::Region* r;              regions.update(instrument);
452              gig::Region* prev_region = 0;              instrument_changed.emit();
453              for (r = instrument->GetFirstRegion() ; r ; r = instrument->GetNextRegion()) {              instrument_struct_changed_signal.emit(instrument);
                 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);  
             }  
454          }          }
455    
456          if (is_in_resize_zone(event->x, event->y)) {          if (is_in_resize_zone(event->x, event->y)) {
457    #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
458              get_window()->set_cursor(Gdk::Cursor(Gdk::SB_H_DOUBLE_ARROW));              get_window()->set_cursor(Gdk::Cursor(Gdk::SB_H_DOUBLE_ARROW));
459    #else
460                get_window()->set_cursor(Gdk::Cursor::create(Gdk::SB_H_DOUBLE_ARROW));
461    #endif
462              cursor_is_resize = true;              cursor_is_resize = true;
463          }          }
464      }      }
# Line 299  bool RegionChooser::on_button_press_even Line 469  bool RegionChooser::on_button_press_even
469  {  {
470      if (!instrument) return true;      if (!instrument) return true;
471    
472      int k = int(event->x / (width - 1) * 128.0);      const int k = int(event->x / (get_width() - 1) * 128.0);
473    
474        if (event->type == GDK_BUTTON_PRESS) {
475            if (event->y >= REGION_BLOCK_HEIGHT) {
476                int velocity = (event->y >= REGION_BLOCK_HEIGHT + KEYBOARD_HEIGHT - 1) ? 127 :
477                               int(float(event->y - REGION_BLOCK_HEIGHT) / float(KEYBOARD_HEIGHT) * 128.0f) + 1;
478                currentActiveKey = k;
479                keyboard_key_hit_signal.emit(k, velocity);
480            }
481        }
482    
483        if (event->y >= REGION_BLOCK_HEIGHT) return true;
484      if (event->type == GDK_BUTTON_PRESS && event->button == 3) {      if (event->type == GDK_BUTTON_PRESS && event->button == 3) {
485          gig::Region* r = get_region(k);          gig::Region* r = get_region(k);
486          if (r) {          if (r) {
487              region = r;              region = r;
488              queue_draw();              queue_draw();
489              region_selected();              region_selected();
490                dimensionManager.set_region(region);
491              popup_menu_inside_region->popup(event->button, event->time);              popup_menu_inside_region->popup(event->button, event->time);
492          } else {          } else {
493              new_region_pos = k;              new_region_pos = k;
# Line 314  bool RegionChooser::on_button_press_even Line 495  bool RegionChooser::on_button_press_even
495          }          }
496      } else {      } else {
497          if (is_in_resize_zone(event->x, event->y)) {          if (is_in_resize_zone(event->x, event->y)) {
498    #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
499              get_window()->pointer_grab(false,              get_window()->pointer_grab(false,
500                                         Gdk::BUTTON_RELEASE_MASK |                                         Gdk::BUTTON_RELEASE_MASK |
501                                         Gdk::POINTER_MOTION_MASK |                                         Gdk::POINTER_MOTION_MASK |
502                                         Gdk::POINTER_MOTION_HINT_MASK,                                         Gdk::POINTER_MOTION_HINT_MASK,
503                                         Gdk::Cursor(Gdk::SB_H_DOUBLE_ARROW), event->time);                                         Gdk::Cursor(Gdk::SB_H_DOUBLE_ARROW),
504                                           event->time);
505    #else
506                Glib::wrap(event->device, true)->grab(get_window(),
507                                                      Gdk::OWNERSHIP_NONE,
508                                                      false,
509                                                      Gdk::BUTTON_RELEASE_MASK |
510                                                      Gdk::POINTER_MOTION_MASK |
511                                                      Gdk::POINTER_MOTION_HINT_MASK,
512                                                      Gdk::Cursor::create(Gdk::SB_H_DOUBLE_ARROW),
513                                                      event->time);
514    #endif
515              resize.active = true;              resize.active = true;
516          } else {          } else {
517              gig::Region* r = get_region(k);              gig::Region* r = get_region(k);
# Line 326  bool RegionChooser::on_button_press_even Line 519  bool RegionChooser::on_button_press_even
519                  region = r;                  region = r;
520                  queue_draw();                  queue_draw();
521                  region_selected();                  region_selected();
522                    dimensionManager.set_region(region);
523    
524    #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
525                  get_window()->pointer_grab(false,                  get_window()->pointer_grab(false,
526                                             Gdk::BUTTON_RELEASE_MASK |                                             Gdk::BUTTON_RELEASE_MASK |
527                                             Gdk::POINTER_MOTION_MASK |                                             Gdk::POINTER_MOTION_MASK |
528                                             Gdk::POINTER_MOTION_HINT_MASK,                                             Gdk::POINTER_MOTION_HINT_MASK,
529                                             Gdk::Cursor(Gdk::FLEUR), event->time);                                             Gdk::Cursor(Gdk::FLEUR),
530                                               event->time);
531    #else
532                    Glib::wrap(event->device, true)->grab(get_window(),
533                                                          Gdk::OWNERSHIP_NONE,
534                                                          false,
535                                                          Gdk::BUTTON_RELEASE_MASK |
536                                                          Gdk::POINTER_MOTION_MASK |
537                                                          Gdk::POINTER_MOTION_HINT_MASK,
538                                                          Gdk::Cursor::create(Gdk::FLEUR),
539                                                          event->time);
540    #endif
541                  move.active = true;                  move.active = true;
542                  move.from_x = event->x;                  move.from_x = event->x;
543                  move.pos = 0;                  move.pos = 0;
# Line 345  gig::Region* RegionChooser::get_region(i Line 551  gig::Region* RegionChooser::get_region(i
551  {  {
552      gig::Region* prev_region = 0;      gig::Region* prev_region = 0;
553      gig::Region* next_region;      gig::Region* next_region;
554      for (gig::Region *r = instrument->GetFirstRegion() ; r ;      for (gig::Region* r = regions.first() ; r ; r = next_region) {
555           r = next_region) {          next_region = regions.next();
         next_region = instrument->GetNextRegion();  
556    
557          if (key < r->KeyRange.low) return 0;          if (key < r->KeyRange.low) return 0;
558          if (key <= r->KeyRange.high) {          if (key <= r->KeyRange.high) {
# Line 362  gig::Region* RegionChooser::get_region(i Line 567  gig::Region* RegionChooser::get_region(i
567    
568  void RegionChooser::motion_resize_region(int x, int y)  void RegionChooser::motion_resize_region(int x, int y)
569  {  {
570      const int w = width - 1;      const int w = get_width() - 1;
     Glib::RefPtr<Gdk::Window> window = get_window();  
571    
572      int k = int(double(x) / w * 128.0 + 0.5);      int k = int(double(x) / w * 128.0 + 0.5);
573    
# Line 371  void RegionChooser::motion_resize_region Line 575  void RegionChooser::motion_resize_region
575      else if (k > resize.max) k = resize.max;      else if (k > resize.max) k = resize.max;
576    
577      if (k != resize.pos) {      if (k != resize.pos) {
578            Cairo::RefPtr<Cairo::Context> cr = get_window()->create_cairo_context();
579            cr->set_line_width(1);
580    
581          if (resize.mode == resize.undecided) {          if (resize.mode == resize.undecided) {
582              if (k < resize.pos) {              if (k < resize.pos) {
583                  // edit high limit of prev_region                  // edit high limit of prev_region
# Line 383  void RegionChooser::motion_resize_region Line 590  void RegionChooser::motion_resize_region
590                  resize.mode = resize.moving_low_limit;                  resize.mode = resize.moving_low_limit;
591              }              }
592          }          }
593          Glib::RefPtr<const Gdk::GC> black = get_style()->get_black_gc();          const Gdk::RGBA white = region == resize.region ? red : this->white;
594          Glib::RefPtr<const Gdk::GC> white = get_style()->get_white_gc();  #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
595          if (region == resize.region) {          const Gdk::Color bg = get_style()->get_bg(Gtk::STATE_NORMAL);
596              gc->set_foreground(red);  #else
597              white = gc;          const Gdk::RGBA bg = get_style_context()->get_background_color();
598          }  #endif
599          Glib::RefPtr<const Gdk::GC> bg = get_style()->get_bg_gc(Gtk::STATE_NORMAL);  
600          int prevx = int(w * resize.pos / 128.0 + 0.5);          int prevx = int(w * resize.pos / 128.0 + 0.5);
601          x = int(w * k / 128.0 + 0.5);          x = int(w * k / 128.0 + 0.5);
602    
603          if (resize.mode == resize.moving_high_limit) {          if (resize.mode == resize.moving_high_limit) {
604              if (k > resize.pos) {              if (k > resize.pos) {
605                  window->draw_rectangle(white, true, prevx, 1, x - prevx, h1 - 2);                  Gdk::Cairo::set_source_rgba(cr, white);
606                  window->draw_line(black, prevx, 0, x, 0);                  cr->rectangle(prevx, 1, x - prevx, h1 - 2);
607                  window->draw_line(black, prevx, h1 - 1, x, h1 - 1);                  cr->fill();
608    
609                    Gdk::Cairo::set_source_rgba(cr, black);
610                    cr->move_to(prevx, 0.5);
611                    cr->line_to(x + 1, 0.5);
612                    cr->move_to(prevx, h1 - 0.5);
613                    cr->line_to(x + 1, h1 - 0.5);
614                    cr->stroke();
615              } else {              } else {
616                  int xx = ((resize.pos == resize.max && resize.max != 128) ? 1 : 0);                  int xx = (resize.pos == resize.max &&
617                  window->draw_rectangle(bg, true, x + 1, 0, prevx - x - xx, h1);                            resize.max != 128) ? 1 : 0;
618                    Gdk::Cairo::set_source_rgba(cr, bg);
619                    cr->rectangle(x + 1, 0, prevx - x - xx, h1);
620                    cr->fill();
621              }              }
622          } else {          } else {
623              if (k < resize.pos) {              if (k < resize.pos) {
624                  window->draw_rectangle(white, true, x + 1, 1, prevx - x, h1 - 2);                  Gdk::Cairo::set_source_rgba(cr, white);
625                  window->draw_line(black, x, 0, prevx, 0);                  cr->rectangle(x + 1, 1, prevx - x, h1 - 2);
626                  window->draw_line(black, x, h1 - 1, prevx, h1 - 1);                  cr->fill();
627    
628                    Gdk::Cairo::set_source_rgba(cr, black);
629                    cr->move_to(x, 0.5);
630                    cr->line_to(prevx, 0.5);
631                    cr->move_to(x, h1 - 0.5);
632                    cr->line_to(prevx, h1 - 0.5);
633                    cr->stroke();
634              } else {              } else {
635                  int xx = ((resize.pos == resize.min && resize.min != 0) ? 1 : 0);                  int xx = (resize.pos == resize.min &&
636                  window->draw_rectangle(bg, true, prevx + xx, 0, x - prevx - xx, h1);                            resize.min != 0) ? 1 : 0;
637                    Gdk::Cairo::set_source_rgba(cr, bg);
638                    cr->rectangle(prevx + xx, 0, x - prevx - xx, h1);
639                    cr->fill();
640              }              }
641          }          }
642          window->draw_line(black, x, 1, x, h1 - 2);          Gdk::Cairo::set_source_rgba(cr, black);
643            cr->move_to(x + 0.5, 1);
644            cr->line_to(x + 0.5, h1 - 1);
645            cr->stroke();
646          resize.pos = k;          resize.pos = k;
647      }      }
648  }  }
649    
650  void RegionChooser::motion_move_region(int x, int y)  void RegionChooser::motion_move_region(int x, int y)
651  {  {
652      const int w = width - 1;      const int w = get_width() - 1;
653      Glib::RefPtr<Gdk::Window> window = get_window();      Cairo::RefPtr<Cairo::Context> cr = get_window()->create_cairo_context();
654        cr->set_line_width(1);
655    
656      int k = int(double(x - move.from_x) / w * 128.0 + 0.5);      int k = int(double(x - move.from_x) / w * 128.0 + 0.5);
657      if (k == move.pos) return;      if (k == move.pos) return;
# Line 429  void RegionChooser::motion_move_region(i Line 660  void RegionChooser::motion_move_region(i
660      bool new_touch_right;      bool new_touch_right;
661      int a = 0;      int a = 0;
662      if (k > move.pos) {      if (k > move.pos) {
663          for (gig::Region* r = instrument->GetFirstRegion() ; ;          for (gig::Region* r = regions.first() ; ; r = regions.next()) {
              r = instrument->GetNextRegion()) {  
664              if (r != region) {              if (r != region) {
665                  int b = r ? r->KeyRange.low : 128;                  int b = r ? r->KeyRange.low : 128;
666    
# Line 460  void RegionChooser::motion_move_region(i Line 690  void RegionChooser::motion_move_region(i
690              }              }
691          }          }
692      } else {      } else {
693          for (gig::Region* r = instrument->GetFirstRegion() ; ;          for (gig::Region* r = regions.first() ; ; r = regions.next()) {
              r = instrument->GetNextRegion()) {  
694              if (r != region) {              if (r != region) {
695                  int b = r ? r->KeyRange.low : 128;                  int b = r ? r->KeyRange.low : 128;
696    
# Line 495  void RegionChooser::motion_move_region(i Line 724  void RegionChooser::motion_move_region(i
724      k = new_k;      k = new_k;
725      if (k == move.pos) return;      if (k == move.pos) return;
726    
727      Glib::RefPtr<const Gdk::GC> bg = get_style()->get_bg_gc(Gtk::STATE_NORMAL);  #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
728        const Gdk::Color bg = get_style()->get_bg(Gtk::STATE_NORMAL);
729    #else
730        const Gdk::RGBA bg = get_style_context()->get_background_color();
731    #endif
732    
733      int prevx = int(w * (move.pos + region->KeyRange.low) / 128.0 + 0.5);      int prevx = int(w * (move.pos + region->KeyRange.low) / 128.0 + 0.5);
734      x = int(w * (k + region->KeyRange.low) / 128.0 + 0.5);      x = int(w * (k + region->KeyRange.low) / 128.0 + 0.5);
735      int prevx2 = int(w * (move.pos + region->KeyRange.high + 1) / 128.0 + 0.5);      int prevx2 = int(w * (move.pos + region->KeyRange.high + 1) / 128.0 + 0.5);
736      int x2 = int(w * (k + 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);  
737    
738      if (!new_touch_left) window->draw_line(black, x, 1, x, h1 - 2);      if (!new_touch_left) {
739      if (!new_touch_right) window->draw_line(black, x2, 1, x2, h1 - 2);          Gdk::Cairo::set_source_rgba(cr, black);
740            cr->move_to(x + 0.5, 1);
741            cr->line_to(x + 0.5, h1 - 1);
742            cr->stroke();
743        }
744        if (!new_touch_right) {
745            Gdk::Cairo::set_source_rgba(cr, black);
746            cr->move_to(x2 + 0.5, 1);
747            cr->line_to(x2 + 0.5, h1 - 1);
748            cr->stroke();
749        }
750    
751      if (k > move.pos) {      if (k > move.pos) {
752          window->draw_rectangle(bg, true, prevx + (move.touch_left ? 1 : 0), 0,          Gdk::Cairo::set_source_rgba(cr, bg);
753                                 std::min(x, prevx2 + 1 - (move.touch_right ? 1 : 0)) -          cr->rectangle(prevx + (move.touch_left ? 1 : 0), 0,
754                                 (prevx + (move.touch_left ? 1 : 0)), h1);                        std::min(x, prevx2 + 1 - (move.touch_right ? 1 : 0)) -
755                          (prevx + (move.touch_left ? 1 : 0)), h1);
756          window->draw_line(black, std::max(x, prevx2 + 1), 0, x2, 0);          cr->fill();
757          window->draw_line(black, std::max(x, prevx2 + 1), h1 - 1, x2, h1 - 1);  
758          window->draw_rectangle(gc, true, std::max(x + 1, prevx2), 1,          Gdk::Cairo::set_source_rgba(cr, black);
759                                 x2 - std::max(x + 1, prevx2), h1 - 2);          cr->move_to(std::max(x, prevx2 + 1), 0.5);
760            cr->line_to(x2 + 1, 0.5);
761            cr->move_to(std::max(x, prevx2 + 1), h1 - 0.5);
762            cr->line_to(x2 + 1, h1 - 0.5);
763            cr->stroke();
764    
765            Gdk::Cairo::set_source_rgba(cr, red);
766            cr->rectangle(std::max(x + 1, prevx2), 1,
767                          x2 - std::max(x + 1, prevx2), h1 - 2);
768            cr->fill();
769      } else {      } else {
770          window->draw_rectangle(bg, true, std::max(x2 + 1, prevx + (move.touch_left ? 1 : 0)), 0,          Gdk::Cairo::set_source_rgba(cr, bg);
771                                 prevx2 + 1 - (move.touch_right ? 1 : 0) -          cr->rectangle(std::max(x2 + 1, prevx + (move.touch_left ? 1 : 0)), 0,
772                                 std::max(x2 + 1, prevx + (move.touch_left ? 1 : 0)), h1);                        prevx2 + 1 - (move.touch_right ? 1 : 0) -
773                          std::max(x2 + 1, prevx + (move.touch_left ? 1 : 0)), h1);
774          window->draw_line(black, x, 0, std::min(x2, prevx - 1), 0);          cr->fill();
775          window->draw_line(black, x, h1 - 1, std::min(x2, prevx - 1), h1 - 1);  
776            Gdk::Cairo::set_source_rgba(cr, black);
777          window->draw_rectangle(gc, true, x + 1, 1, std::min(x2 - 1, prevx) - x, h1 - 2);          cr->move_to(x, 0.5);
778            cr->line_to(std::min(x2, prevx - 1) + 1, 0.5);
779            cr->move_to(x, h1 - 0.5);
780            cr->line_to(std::min(x2, prevx - 1) + 1, h1 - 0.5);
781            cr->stroke();
782    
783            Gdk::Cairo::set_source_rgba(cr, red);
784            cr->rectangle(x + 1, 1, std::min(x2 - 1, prevx) - x, h1 - 2);
785            cr->fill();
786      }      }
787    
788      move.pos = k;      move.pos = k;
# Line 539  bool RegionChooser::on_motion_notify_eve Line 798  bool RegionChooser::on_motion_notify_eve
798      Gdk::ModifierType state = Gdk::ModifierType(0);      Gdk::ModifierType state = Gdk::ModifierType(0);
799      window->get_pointer(x, y, state);      window->get_pointer(x, y, state);
800    
801        // handle virtual MIDI keyboard
802        if (m_VirtKeybModeChoice.get_value() != VIRT_KEYBOARD_MODE_CHORD &&
803            currentActiveKey > 0 &&
804            event->y >= REGION_BLOCK_HEIGHT &&
805            event->y < REGION_BLOCK_HEIGHT + KEYBOARD_HEIGHT)
806        {
807            const int k = int(event->x / (get_width() - 1) * 128.0);
808            if (k != currentActiveKey) {
809                int velocity =
810                    (event->y >= REGION_BLOCK_HEIGHT + KEYBOARD_HEIGHT - 1) ? 127 :
811                    int(float(event->y - REGION_BLOCK_HEIGHT) /
812                        float(KEYBOARD_HEIGHT) * 128.0f) + 1;
813                if (velocity <= 0) velocity = 1;
814                keyboard_key_released_signal.emit(currentActiveKey, velocity);
815                currentActiveKey = k;
816                keyboard_key_hit_signal.emit(k, velocity);
817            }
818        }
819    
820      if (resize.active) {      if (resize.active) {
821          motion_resize_region(x, y);          motion_resize_region(x, y);
822      } else if (move.active) {      } else if (move.active) {
# Line 546  bool RegionChooser::on_motion_notify_eve Line 824  bool RegionChooser::on_motion_notify_eve
824      } else {      } else {
825          if (is_in_resize_zone(x, y)) {          if (is_in_resize_zone(x, y)) {
826              if (!cursor_is_resize) {              if (!cursor_is_resize) {
827    #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
828                  window->set_cursor(Gdk::Cursor(Gdk::SB_H_DOUBLE_ARROW));                  window->set_cursor(Gdk::Cursor(Gdk::SB_H_DOUBLE_ARROW));
829    #else
830                    window->set_cursor(Gdk::Cursor::create(Gdk::SB_H_DOUBLE_ARROW));
831    #endif
832                  cursor_is_resize = true;                  cursor_is_resize = true;
833              }              }
834          } else if (cursor_is_resize) {          } else if (cursor_is_resize) {
# Line 559  bool RegionChooser::on_motion_notify_eve Line 841  bool RegionChooser::on_motion_notify_eve
841  }  }
842    
843  bool RegionChooser::is_in_resize_zone(double x, double y) {  bool RegionChooser::is_in_resize_zone(double x, double y) {
844      const int w = width - 1;      const int w = get_width() - 1;
845    
846      if (instrument && y >= 0 && y <= h1) {      if (instrument && y >= 0 && y <= h1) {
847          gig::Region* prev_region = 0;          gig::Region* prev_region = 0;
848          gig::Region* next_region;          gig::Region* next_region;
849          for (gig::Region* r = instrument->GetFirstRegion() ; r ; r = next_region) {          for (gig::Region* r = regions.first(); r ; r = next_region) {
850              next_region = instrument->GetNextRegion();              next_region = regions.next();
851    
852              int lo = int(w * (r->KeyRange.low) / 128.0 + 0.5);              int lo = int(w * (r->KeyRange.low) / 128.0 + 0.5);
853              if (x <= lo - 2) break;              if (x <= lo - 2) break;
# Line 581  bool RegionChooser::is_in_resize_zone(do Line 863  bool RegionChooser::is_in_resize_zone(do
863                      resize.mode = resize.undecided;                      resize.mode = resize.undecided;
864                      resize.min = prev_region->KeyRange.low + 1;                      resize.min = prev_region->KeyRange.low + 1;
865                      resize.prev_region = prev_region;                      resize.prev_region = prev_region;
866                      return true;                      return resize.min != resize.max;
867                  }                  }
868    
869                  // edit low limit                  // edit low limit
870                  resize.mode = resize.moving_low_limit;                  resize.mode = resize.moving_low_limit;
871                  resize.min = prev_region ? prev_region->KeyRange.high + 1 : 0;                  resize.min = prev_region ? prev_region->KeyRange.high + 1 : 0;
872                  return true;                  return resize.min != resize.max;
873              }              }
874              if (!next_region || r->KeyRange.high + 1 != next_region->KeyRange.low) {              if (!next_region || r->KeyRange.high + 1 != next_region->KeyRange.low) {
875                  int hi = int(w * (r->KeyRange.high + 1) / 128.0 + 0.5);                  int hi = int(w * (r->KeyRange.high + 1) / 128.0 + 0.5);
# Line 599  bool RegionChooser::is_in_resize_zone(do Line 881  bool RegionChooser::is_in_resize_zone(do
881                      resize.mode = resize.moving_high_limit;                      resize.mode = resize.moving_high_limit;
882                      resize.min = r->KeyRange.low + 1;                      resize.min = r->KeyRange.low + 1;
883                      resize.max = next_region ? next_region->KeyRange.low : 128;                      resize.max = next_region ? next_region->KeyRange.low : 128;
884                      return true;                      return resize.min != resize.max;
885                  }                  }
886              }              }
887              prev_region = r;              prev_region = r;
# Line 608  bool RegionChooser::is_in_resize_zone(do Line 890  bool RegionChooser::is_in_resize_zone(do
890      return false;      return false;
891  }  }
892    
893  sigc::signal<void> RegionChooser::signal_region_selected()  sigc::signal<void>& RegionChooser::signal_region_selected()
894  {  {
895      return region_selected;      return region_selected;
896  }  }
897    
898  sigc::signal<void> RegionChooser::signal_instrument_changed()  sigc::signal<void>& RegionChooser::signal_instrument_changed()
899  {  {
900      return instrument_changed;      return instrument_changed;
901  }  }
# Line 621  sigc::signal<void> RegionChooser::signal Line 903  sigc::signal<void> RegionChooser::signal
903  void RegionChooser::show_region_properties()  void RegionChooser::show_region_properties()
904  {  {
905      if (!region) return;      if (!region) return;
906      Gtk::Dialog dialog("Region Properties", true /*modal*/);      Gtk::Dialog dialog(_("Region Properties"), true /*modal*/);
907      // add "Keygroup" checkbox      // add "Keygroup" checkbox
908      Gtk::CheckButton checkBoxKeygroup("Member of a Keygroup (Exclusive Group)");      Gtk::CheckButton checkBoxKeygroup(_("Member of a Keygroup (Exclusive Group)"));
909      checkBoxKeygroup.set_active(region->KeyGroup);      checkBoxKeygroup.set_active(region->KeyGroup);
910      dialog.get_vbox()->pack_start(checkBoxKeygroup);      dialog.get_vbox()->pack_start(checkBoxKeygroup);
911      checkBoxKeygroup.show();      checkBoxKeygroup.show();
912      // add "Keygroup" spinbox      // add "Keygroup" spinbox
913      Gtk::Adjustment adjustment(1, 1, pow(2,32));  #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
914        Gtk::Adjustment adjustment(1, 1, 999);
915      Gtk::SpinButton spinBox(adjustment);      Gtk::SpinButton spinBox(adjustment);
916    #else
917        Gtk::SpinButton spinBox(Gtk::Adjustment::create(1, 1, 999));
918    #endif
919      if (region->KeyGroup) spinBox.set_value(region->KeyGroup);      if (region->KeyGroup) spinBox.set_value(region->KeyGroup);
920      dialog.get_vbox()->pack_start(spinBox);      dialog.get_vbox()->pack_start(spinBox);
921      spinBox.show();      spinBox.show();
# Line 645  void RegionChooser::show_region_properti Line 931  void RegionChooser::show_region_properti
931    
932  void RegionChooser::add_region()  void RegionChooser::add_region()
933  {  {
934      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;  
     }  
935    
936      region = instrument->AddRegion();      region = instrument->AddRegion();
937      region->KeyRange.low = region->KeyRange.high = new_region_pos;      region->SetKeyRange(new_region_pos, new_region_pos);
938    
939        instrument_struct_changed_signal.emit(instrument);
940        regions.update(instrument);
941    
     instrument->MoveRegion(region, r);  
942      queue_draw();      queue_draw();
943      region_selected();      region_selected();
944        dimensionManager.set_region(region);
945      instrument_changed();      instrument_changed();
946  }  }
947    
948  void RegionChooser::delete_region()  void RegionChooser::delete_region()
949  {  {
950        instrument_struct_to_be_changed_signal.emit(instrument);
951      instrument->DeleteRegion(region);      instrument->DeleteRegion(region);
952        instrument_struct_changed_signal.emit(instrument);
953        regions.update(instrument);
954    
955      region = 0;      region = 0;
956      queue_draw();      queue_draw();
957      region_selected();      region_selected();
958        dimensionManager.set_region(region);
959      instrument_changed();      instrument_changed();
960  }  }
961    
# Line 679  void RegionChooser::on_dimension_manager Line 970  void RegionChooser::on_dimension_manager
970      region_selected();      region_selected();
971      instrument_changed();      instrument_changed();
972  }  }
973    
974    sigc::signal<void, gig::Instrument*>& RegionChooser::signal_instrument_struct_to_be_changed() {
975        return instrument_struct_to_be_changed_signal;
976    }
977    
978    sigc::signal<void, gig::Instrument*>& RegionChooser::signal_instrument_struct_changed() {
979        return instrument_struct_changed_signal;
980    }
981    
982    sigc::signal<void, gig::Region*>& RegionChooser::signal_region_to_be_changed() {
983        return region_to_be_changed_signal;
984    }
985    
986    sigc::signal<void, gig::Region*>& RegionChooser::signal_region_changed_signal() {
987        return region_changed_signal;
988    }
989    
990    sigc::signal<void, int/*key*/, int/*velocity*/>& RegionChooser::signal_keyboard_key_hit() {
991        return keyboard_key_hit_signal;
992    }
993    
994    sigc::signal<void, int/*key*/, int/*velocity*/>& RegionChooser::signal_keyboard_key_released() {
995        return keyboard_key_released_signal;
996    }

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

  ViewVC Help
Powered by ViewVC