/[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 2627 by schoenebeck, Thu Jun 12 16:12:55 2014 UTC
# Line 1  Line 1 
1  /*  /*
2   * Copyright (C) 2006, 2007 Andreas Persson   * Copyright (C) 2006-2014 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    
33    #define REGION_BLOCK_HEIGHT             30
34    #define KEYBOARD_HEIGHT                 40
35    
36    void SortedRegions::update(gig::Instrument* instrument) {
37        // Usually, the regions in a gig file are ordered after their key
38        // range, but there are files where they are not. The
39        // RegionChooser code needs a sorted list of regions.
40        regions.clear();
41        if (instrument) {
42            for (gig::Region* r = instrument->GetFirstRegion() ;
43                 r ;
44                 r = instrument->GetNextRegion()) {
45                regions.push_back(r);
46            }
47            sort(regions.begin(), regions.end(), *this);
48        }
49    }
50    
51    gig::Region* SortedRegions::first() {
52        region_iterator = regions.begin();
53        return region_iterator == regions.end() ? 0 : *region_iterator;
54    }
55    
56    gig::Region* SortedRegions::next() {
57        region_iterator++;
58        return region_iterator == regions.end() ? 0 : *region_iterator;
59    }
60    
61    
 RegionChooser::RegionChooser()  
 {  
     Glib::RefPtr<Gdk::Colormap> colormap = get_default_colormap();  
62    
63      red = Gdk::Color("#8070ff");  RegionChooser::RegionChooser() :
64      grey1 = Gdk::Color("#b0b0b0");      activeKeyColor("red"),
65        red("#8070ff"),
66        grey1("grey69"),
67        white("white"),
68        black("black"),
69        m_VirtKeybModeChoice(_("Virtual Keyboard Mode")),
70        currentActiveKey(-1)
71    {
72        set_size_request(500, KEYBOARD_HEIGHT + REGION_BLOCK_HEIGHT);
73    
     colormap->alloc_color(red);  
     colormap->alloc_color(grey1);  
74      instrument = 0;      instrument = 0;
75      region = 0;      region = 0;
76      resize.active = false;      resize.active = false;
77        move.active = false;
78      cursor_is_resize = false;      cursor_is_resize = false;
79      h1 = 20;      h1 = REGION_BLOCK_HEIGHT;
80      width = 800;  
81        // properties of the virtual keyboard
82        {
83            const char* choices[] = { _("normal"), _("chord"), 0 };
84            static const virt_keyboard_mode_t values[] = {
85                VIRT_KEYBOARD_MODE_NORMAL,
86                VIRT_KEYBOARD_MODE_CHORD
87            };
88            m_VirtKeybModeChoice.set_choices(choices, values);
89            m_VirtKeybModeChoice.set_value(VIRT_KEYBOARD_MODE_NORMAL);
90        }
91        m_VirtKeybVelocityLabelDescr.set_text(_("Note-On Velocity:"));
92        m_VirtKeybVelocityLabel.set_text("-");
93        m_VirtKeybOffVelocityLabelDescr.set_text(_("Note-Off Velocity:"));
94        m_VirtKeybOffVelocityLabel.set_text("-");
95        m_VirtKeybPropsBox.pack_start(m_VirtKeybModeChoice.label, Gtk::PACK_SHRINK);
96        m_VirtKeybPropsBox.pack_start(m_VirtKeybModeChoice.widget, Gtk::PACK_SHRINK);
97        m_VirtKeybPropsBox.pack_start(m_VirtKeybVelocityLabelDescr, Gtk::PACK_SHRINK);
98        m_VirtKeybPropsBox.pack_start(m_VirtKeybVelocityLabel, Gtk::PACK_SHRINK);
99        m_VirtKeybPropsBox.pack_start(m_VirtKeybOffVelocityLabelDescr, Gtk::PACK_SHRINK);
100        m_VirtKeybPropsBox.pack_start(m_VirtKeybOffVelocityLabel, Gtk::PACK_SHRINK);
101        m_VirtKeybPropsBox.set_spacing(10);
102        m_VirtKeybPropsBox.show();
103        for (int i = 0 ; i < 128 ; i++) key_pressed[i] = false;
104    
105      actionGroup = Gtk::ActionGroup::create();      actionGroup = Gtk::ActionGroup::create();
106      actionGroup->add(Gtk::Action::create("Properties",      actionGroup->add(Gtk::Action::create("Properties",
# Line 78  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        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."));
158  }  }
159    
160  RegionChooser::~RegionChooser()  RegionChooser::~RegionChooser()
161  {  {
162  }  }
163    
164  void RegionChooser::on_realize()  void RegionChooser::invalidate_key(int key) {
165  {      const int h = KEYBOARD_HEIGHT;
166      // We need to call the base on_realize()      const int w = get_width() - 1;
167      Gtk::DrawingArea::on_realize();      int x1 = key_to_x(key - 0.5, w);
168        int x2 = key_to_x(key + 1.5, w);
169    
170      // Now we can allocate any additional resources we need      Gdk::Rectangle rect(x1 + 1, h1 + 1, x2 - x1 - 1, h - 2);
171      Glib::RefPtr<Gdk::Window> window = get_window();      get_window()->invalidate_rect(rect, false);
     gc = Gdk::GC::create(window);  
     window->clear();  
172  }  }
173    
174  bool RegionChooser::on_expose_event(GdkEventExpose* event)  void RegionChooser::on_note_on_event(int key, int velocity) {
175  {      key_pressed[key] = true;
176      Glib::RefPtr<Gdk::Window> window = get_window();      invalidate_key(key);
177      window->clear();      m_VirtKeybVelocityLabel.set_text(ToString(velocity));
178      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();  
179    
180      Glib::RefPtr<Pango::Context> context = get_pango_context();  void RegionChooser::on_note_off_event(int key, int velocity) {
181      Glib::RefPtr<Pango::Layout> layout = Pango::Layout::create(context);      key_pressed[key] = false;
182        invalidate_key(key);
183        m_VirtKeybOffVelocityLabel.set_text(ToString(velocity));
184    }
185    
     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);  
186    
187          if (note == 1 || note == 4 || note == 6 || note == 9 || note == 11) {  #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
188              int x2 = int(w * (i + 0.5) / 128.0 + 0.5);  bool RegionChooser::on_expose_event(GdkEventExpose* e) {
189              window->draw_line(black, x2, h1 + bh, x2, h1 + h);      double clipx1 = e->area.x;
190        double clipx2 = e->area.x + e->area.width;
191        double clipy1 = e->area.y;
192        double clipy2 = e->area.y + e->area.height;
193    
194              int x3 = int(w * (i + 1) / 128.0 + 0.5);      const Cairo::RefPtr<Cairo::Context>& cr =
195              window->draw_rectangle(black, true, x, h1 + 1, x3 - x + 1, bh);          get_window()->create_cairo_context();
196          } else if (note == 3 || note == 8) {  #if 0
197              window->draw_line(black, x, h1 + 1, x, h1 + h);  }
198          }  #endif
199          if (note == 3) {  #else
200              char buf[30];  bool RegionChooser::on_draw(const Cairo::RefPtr<Cairo::Context>& cr) {
201              sprintf(buf, "<span size=\"x-small\">%d</span>", octave);      double clipx1, clipx2, clipy1, clipy2;
202              layout->set_markup(buf);      cr->get_clip_extents(clipx1, clipy1, clipx2, clipy2);
203              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++;  
         }  
     }  
204    
205      if (instrument) {      cr->save();
206          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) {  
207    
208              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
209              next_region = instrument->GetNextRegion();      const Gdk::Color bg = get_style()->get_bg(Gtk::STATE_NORMAL);
210              if (!next_region || r->KeyRange.high + 1 != next_region->KeyRange.low) {  #else
211                  int x2 = int(w * (r->KeyRange.high + 1) / 128.0 + 0.5);      const Gdk::RGBA bg = get_style_context()->get_background_color();
212                  window->draw_line(black, x3, 0, x2, 0);  #endif
213                  window->draw_line(black, x3, h1 - 1, x2, h1 - 1);      Gdk::Cairo::set_source_rgba(cr, bg);
214                  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++;  
         }  
215    
216          for (gig::Region *r = instrument->GetFirstRegion() ;      if (clipy2 > h1) {
217               r ;          draw_keyboard(cr, clipx1, clipx2);
218               r = instrument->GetNextRegion()) {      }
             int x = int(w * (r->KeyRange.low) / 128.0 + 0.5);  
             window->draw_line(black, x, 1, x, h1 - 2);  
         }  
219    
220          if (region) {      if (clipy1 < h1 && instrument) {
221              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);  
         }  
222      }      }
223    
224        cr->restore();
225    
226      return true;      return true;
227  }  }
228    
229    void RegionChooser::draw_keyboard(const Cairo::RefPtr<Cairo::Context>& cr,
230                                      int clip_low, int clip_high) {
231        const int h = KEYBOARD_HEIGHT;
232        const int w = get_width() - 1;
233        const int bh = int(h * 0.55);
234    
235  void RegionChooser::on_size_request(GtkRequisition* requisition)      Gdk::Cairo::set_source_rgba(cr, black);
236  {      cr->rectangle(0.5, h1 + 0.5, w, h - 1);
237      *requisition = GtkRequisition();      cr->stroke();
238      requisition->height = 40 + 20;  
239      requisition->width = 500;      int x1 = key_to_x(20.5, w);
240        Gdk::Cairo::set_source_rgba(cr, grey1);
241        cr->rectangle(1, h1 + 1, x1 - 1, h - 2);
242        cr->fill();
243    
244        int x2 = key_to_x(109.5, w);
245        Gdk::Cairo::set_source_rgba(cr, white);
246        cr->rectangle(x1 + 1, h1 + 1, x2 - x1 - 1, h - 2);
247        cr->fill();
248    
249        Gdk::Cairo::set_source_rgba(cr, grey1);
250        cr->rectangle(x2 + 1, h1 + 1, w - x2 - 1, h - 2);
251        cr->fill();
252    
253        Gdk::Cairo::set_source_rgba(cr, black);
254    
255        int clipkey1 = std::max(0, x_to_key_right(clip_low - 1, w));
256        int clipkey2 = std::min(x_to_key_right(clip_high - 1, w) + 1, 128);
257    
258        for (int i = clipkey1 ; i < clipkey2 ; i++) {
259            int note = (i + 3) % 12;
260            int x = key_to_x(i, w);
261    
262            if (note == 1 || note == 4 || note == 6 ||
263                note == 9 || note == 11) {
264                // black key: short line in the middle, with a rectangle
265                // on top
266                int x2 = key_to_x(i + 0.5, w);
267                cr->move_to(x2 + 0.5, h1 + bh + 0.5);
268                cr->line_to(x2 + 0.5, h1 + h - 1);
269                cr->stroke();
270    
271                int x3 = key_to_x(i + 1, w);
272                cr->rectangle(x, h1 + 1, x3 - x + 1, bh);
273                cr->fill();
274            } else if (note == 3 || note == 8) {
275                // C or F: long line to the left
276                cr->move_to(x + 0.5, h1 + 1);
277                cr->line_to(x + 0.5, h1 + h - 1);
278                cr->stroke();
279            }
280    
281            if (key_pressed[i]) draw_key(cr, i);
282    
283            if (note == 3) draw_digit(cr, i);
284        }
285  }  }
286    
287    
288  // not used  void RegionChooser::draw_regions(const Cairo::RefPtr<Cairo::Context>& cr,
289  void RegionChooser::draw_region(int from, int to, const Gdk::Color& color)                                   int clip_low, int clip_high) {
290  {      const int w = get_width() - 1;
291      const int h = 40;  
292      const int w = width;      Gdk::Cairo::set_source_rgba(cr, black);
293        gig::Region* next_region;
294        int x3 = -1;
295        for (gig::Region* r = regions.first() ; r ; r = next_region) {
296            next_region = regions.next();
297    
298            if (x3 < 0) {
299                x3 = key_to_x(r->KeyRange.low, w);
300                if (x3 >= clip_high) break;
301            }
302            if (!next_region ||
303                r->KeyRange.high + 1 != next_region->KeyRange.low ||
304                r == region || next_region == region) {
305    
306                int x2 = key_to_x(r->KeyRange.high + 1, w);
307                if (x2 >= clip_low) {
308                    cr->move_to(x3, 0.5);
309                    cr->line_to(x2 + 0.5, 0.5);
310                    cr->line_to(x2 + 0.5, h1 - 0.5);
311                    cr->line_to(x3, h1 - 0.5);
312                    cr->stroke();
313    
314                    Gdk::Cairo::set_source_rgba(cr, region == r ? red : white);
315                    cr->rectangle(x3 + 1, 1, x2 - x3 - 1, h1 - 2);
316                    cr->fill();
317                    Gdk::Cairo::set_source_rgba(cr, black);
318                }
319                x3 = -1;
320            }
321        }
322    
323        for (gig::Region* r = regions.first() ; r ; r = regions.next()) {
324            int x = key_to_x(r->KeyRange.low, w);
325    
326            if (x < clip_low) continue;
327            if (x >= clip_high) break;
328    
329            cr->move_to(x + 0.5, 1);
330            cr->line_to(x + 0.5, h1 - 1);
331            cr->stroke();
332        }
333    
334        // if there is no region yet, show the user some hint text that he may
335        // right click on this area to create a new region
336        if (!regions.first()) {
337            Glib::RefPtr<Pango::Context> context = get_pango_context();
338            Glib::RefPtr<Pango::Layout> layout = Pango::Layout::create(context);
339            layout->set_alignment(Pango::ALIGN_CENTER);
340            layout->set_text(Glib::ustring("*** ") + _("Right click here to create a region.") + " ***");
341            layout->set_width(get_width() * Pango::SCALE);
342            //layout->set_height(get_height() * Pango::SCALE);
343            layout->set_spacing(10);
344            Gdk::Cairo::set_source_rgba(cr, red);        
345            // get the text dimensions
346            Pango::Rectangle rect = layout->get_logical_extents();
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        region->SetKeyRange(pos, pos + region->KeyRange.high -
519                            region->KeyRange.low);
520        regions.update(instrument);
521        instrument_changed.emit();
522        instrument_struct_changed_signal.emit(instrument);
523    }
524    
525  bool RegionChooser::on_button_press_event(GdkEventButton* event)  bool RegionChooser::on_button_press_event(GdkEventButton* event)
526  {  {
527      if (!instrument) return true;      if (!instrument) return true;
528    
529      int k = int(event->x / (width - 1) * 128.0);      const int w = get_width() - 1;
530        const int k = x_to_key(event->x, w);
531    
532        if (event->type == GDK_BUTTON_PRESS) {
533            if (event->y >= REGION_BLOCK_HEIGHT) {
534                int velocity = (event->y >= REGION_BLOCK_HEIGHT + KEYBOARD_HEIGHT - 1) ? 127 :
535                               int(float(event->y - REGION_BLOCK_HEIGHT) / float(KEYBOARD_HEIGHT) * 128.0f) + 1;
536                currentActiveKey = k;
537                keyboard_key_hit_signal.emit(k, velocity);
538            }
539        }
540    
541        if (event->y >= REGION_BLOCK_HEIGHT) return true;
542      if (event->type == GDK_BUTTON_PRESS && event->button == 3) {      if (event->type == GDK_BUTTON_PRESS && event->button == 3) {
543          gig::Region* r = get_region(k);          gig::Region* r = get_region(k);
544          if (r) {          if (r) {
545              region = r;              region = r;
546              queue_draw();              queue_draw();
547              region_selected();              region_selected();
548                dimensionManager.set_region(region);
549              popup_menu_inside_region->popup(event->button, event->time);              popup_menu_inside_region->popup(event->button, event->time);
550          } else {          } else {
551              new_region_pos = k;              new_region_pos = k;
# Line 313  bool RegionChooser::on_button_press_even Line 553  bool RegionChooser::on_button_press_even
553          }          }
554      } else {      } else {
555          if (is_in_resize_zone(event->x, event->y)) {          if (is_in_resize_zone(event->x, event->y)) {
556    #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
557              get_window()->pointer_grab(false,              get_window()->pointer_grab(false,
558                                         Gdk::BUTTON_RELEASE_MASK |                                         Gdk::BUTTON_RELEASE_MASK |
559                                         Gdk::POINTER_MOTION_MASK |                                         Gdk::POINTER_MOTION_MASK |
560                                         Gdk::POINTER_MOTION_HINT_MASK,                                         Gdk::POINTER_MOTION_HINT_MASK,
561                                         Gdk::Cursor(Gdk::SB_H_DOUBLE_ARROW), event->time);                                         Gdk::Cursor(Gdk::SB_H_DOUBLE_ARROW),
562                                           event->time);
563    #else
564                Glib::wrap(event->device, true)->grab(get_window(),
565                                                      Gdk::OWNERSHIP_NONE,
566                                                      false,
567                                                      Gdk::BUTTON_RELEASE_MASK |
568                                                      Gdk::POINTER_MOTION_MASK |
569                                                      Gdk::POINTER_MOTION_HINT_MASK,
570                                                      Gdk::Cursor::create(Gdk::SB_H_DOUBLE_ARROW),
571                                                      event->time);
572    #endif
573              resize.active = true;              resize.active = true;
574          } else {          } else {
575              gig::Region* r = get_region(k);              gig::Region* r = get_region(k);
# Line 325  bool RegionChooser::on_button_press_even Line 577  bool RegionChooser::on_button_press_even
577                  region = r;                  region = r;
578                  queue_draw();                  queue_draw();
579                  region_selected();                  region_selected();
580                    dimensionManager.set_region(region);
581    
582    #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
583                  get_window()->pointer_grab(false,                  get_window()->pointer_grab(false,
584                                             Gdk::BUTTON_RELEASE_MASK |                                             Gdk::BUTTON_RELEASE_MASK |
585                                             Gdk::POINTER_MOTION_MASK |                                             Gdk::POINTER_MOTION_MASK |
586                                             Gdk::POINTER_MOTION_HINT_MASK,                                             Gdk::POINTER_MOTION_HINT_MASK,
587                                             Gdk::Cursor(Gdk::FLEUR), event->time);                                             Gdk::Cursor(Gdk::FLEUR),
588                                               event->time);
589    #else
590                    Glib::wrap(event->device, true)->grab(get_window(),
591                                                          Gdk::OWNERSHIP_NONE,
592                                                          false,
593                                                          Gdk::BUTTON_RELEASE_MASK |
594                                                          Gdk::POINTER_MOTION_MASK |
595                                                          Gdk::POINTER_MOTION_HINT_MASK,
596                                                          Gdk::Cursor::create(Gdk::FLEUR),
597                                                          event->time);
598    #endif
599                  move.active = true;                  move.active = true;
600                  move.from_x = event->x;                  move.offset = event->x - key_to_x(region->KeyRange.low, w);
                 move.pos = 0;  
601              }              }
602          }          }
603      }      }
# Line 342  bool RegionChooser::on_button_press_even Line 606  bool RegionChooser::on_button_press_even
606    
607  gig::Region* RegionChooser::get_region(int key)  gig::Region* RegionChooser::get_region(int key)
608  {  {
609      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();  
   
610          if (key < r->KeyRange.low) return 0;          if (key < r->KeyRange.low) return 0;
611          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;  
612      }      }
613      return 0;      return 0;
614  }  }
615    
616  void RegionChooser::motion_resize_region(int x, int y)  void RegionChooser::motion_resize_region(int x, int y)
617  {  {
618      const int w = width - 1;      const int w = get_width() - 1;
     Glib::RefPtr<Gdk::Window> window = get_window();  
619    
620      int k = int(double(x) / w * 128.0 + 0.5);      int k = int(double(x) / w * 128.0 + 0.5);
621    
# Line 382  void RegionChooser::motion_resize_region Line 635  void RegionChooser::motion_resize_region
635                  resize.mode = resize.moving_low_limit;                  resize.mode = resize.moving_low_limit;
636              }              }
637          }          }
638          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);  
639    
640            int x1, x2;
641          if (resize.mode == resize.moving_high_limit) {          if (resize.mode == resize.moving_high_limit) {
642              if (k > resize.pos) {              if (resize.region->KeyRange.high < resize.pos - 1) {
643                  window->draw_rectangle(white, true, prevx, 1, x - prevx, h1 - 2);                  x1 = resize.region->KeyRange.high;
644                  window->draw_line(black, prevx, 0, x, 0);                  x2 = resize.pos - 1;
                 window->draw_line(black, prevx, h1 - 1, x, h1 - 1);  
645              } else {              } else {
646                  int xx = ((resize.pos == resize.max && resize.max != 128) ? 1 : 0);                  x1 = resize.pos - 1;
647                  window->draw_rectangle(bg, true, x + 1, 0, prevx - x - xx, h1);                  x2 = resize.region->KeyRange.high;
648              }              }
649          } else {          } else {
650              if (k < resize.pos) {              if (resize.region->KeyRange.low < resize.pos) {
651                  window->draw_rectangle(white, true, x + 1, 1, prevx - x, h1 - 2);                  x1 = resize.region->KeyRange.low;
652                  window->draw_line(black, x, 0, prevx, 0);                  x2 = resize.pos;
                 window->draw_line(black, x, h1 - 1, prevx, h1 - 1);  
653              } else {              } else {
654                  int xx = ((resize.pos == resize.min && resize.min != 0) ? 1 : 0);                  x1 = resize.pos;
655                  window->draw_rectangle(bg, true, prevx + xx, 0, x - prevx - xx, h1);                  x2 = resize.region->KeyRange.low;
656              }              }
657          }          }
658          window->draw_line(black, x, 1, x, h1 - 2);          x1 = key_to_x(x1, w);
659          resize.pos = k;          x2 = key_to_x(x2 + 1, w) + 1;
660            Gdk::Rectangle rect(x1, 0, x2 - x1, h1);
661    
662            update_after_resize();
663    
664            get_window()->invalidate_rect(rect, false);
665      }      }
666  }  }
667    
668  void RegionChooser::motion_move_region(int x, int y)  void RegionChooser::motion_move_region(int x, int y)
669  {  {
670      const int w = width - 1;      const int w = get_width() - 1;
671      Glib::RefPtr<Gdk::Window> window = get_window();  
672        int l = int(double(x - move.offset) / w * 128.0 + 0.5);
673    
674      int k = int(double(x - move.from_x) / w * 128.0 + 0.5);      if (l == region->KeyRange.low) return;
675      if (k == move.pos) return;      int new_l;
676      int new_k;      int regionsize = region->KeyRange.high - region->KeyRange.low;
     bool new_touch_left;  
     bool new_touch_right;  
677      int a = 0;      int a = 0;
678      if (k > move.pos) {      if (l > region->KeyRange.low) {
679          for (gig::Region* r = instrument->GetFirstRegion() ; ;          for (gig::Region* r = regions.first() ; ; r = regions.next()) {
              r = instrument->GetNextRegion()) {  
680              if (r != region) {              if (r != region) {
681                  int b = r ? r->KeyRange.low : 128;                  int b = r ? r->KeyRange.low : 128;
682    
683                  // gap: from a to b (not inclusive b)                  // gap: from a to b (not inclusive b)
684    
685                  if (region->KeyRange.high + move.pos >= b) {                  if (region->KeyRange.high >= b) {
686                      // not found the current gap yet, just continue                      // not found the current gap yet, just continue
687                  } else {                  } else {
688    
689                      if (a > region->KeyRange.low + k) {                      if (a > l) {
690                          // this gap is too far to the right, break                          // this gap is too far to the right, break
691                          break;                          break;
692                      }                      }
693    
694                      int newhigh = std::min(region->KeyRange.high + k, b - 1);                      int newhigh = std::min(l + regionsize, b - 1);
695                      int newlo = newhigh - (region->KeyRange.high - region->KeyRange.low);                      int newlo = newhigh - regionsize;
696    
697                      if (newlo >= a) {                      if (newlo >= a) {
698                          // yes it fits - it's a candidate                          // yes it fits - it's a candidate
699                          new_k = newlo - region->KeyRange.low;                          new_l = newlo;
                         new_touch_left = a > 0 && a == newlo;  
                         new_touch_right = b < 128 && newhigh + 1 == b;  
700                      }                      }
701                  }                  }
702                  if (!r) break;                  if (!r) break;
# Line 459  void RegionChooser::motion_move_region(i Line 704  void RegionChooser::motion_move_region(i
704              }              }
705          }          }
706      } else {      } else {
707          for (gig::Region* r = instrument->GetFirstRegion() ; ;          for (gig::Region* r = regions.first() ; ; r = regions.next()) {
              r = instrument->GetNextRegion()) {  
708              if (r != region) {              if (r != region) {
709                  int b = r ? r->KeyRange.low : 128;                  int b = r ? r->KeyRange.low : 128;
710    
711                  // gap from a to b (not inclusive b)                  // gap from a to b (not inclusive b)
712    
713                  if (region->KeyRange.high + k >= b) {                  if (l + regionsize >= b) {
714                      // not found the current gap yet, just continue                      // not found the current gap yet, just continue
715                  } else {                  } else {
716    
717                      if (a > region->KeyRange.low + move.pos) {                      if (a > region->KeyRange.low) {
718                          // this gap is too far to the right, break                          // this gap is too far to the right, break
719                          break;                          break;
720                      }                      }
721    
722                      int newlo = std::max(region->KeyRange.low + k, a);                      int newlo = std::max(l, a);
723                      int newhigh = newlo + (region->KeyRange.high - region->KeyRange.low);                      int newhigh = newlo + regionsize;
724    
725                      if (newhigh < b) {                      if (newhigh < b) {
726                          // yes it fits - break as the first one is the best                          // yes it fits - break as the first one is the best
727                          new_k = newlo - region->KeyRange.low;                          new_l = newlo;
                         new_touch_left = a > 0 && a == newlo;  
                         new_touch_right = b < 128 && newhigh + 1 == b;  
728                          break;                          break;
729                      }                      }
730                  }                  }
# Line 491  void RegionChooser::motion_move_region(i Line 733  void RegionChooser::motion_move_region(i
733              }              }
734          }          }
735      }      }
736      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);  
737    
738          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);
739          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),
740                                   new_l + regionsize) + 1, w) + 1;
741    
742          window->draw_rectangle(gc, true, x + 1, 1, std::min(x2 - 1, prevx) - x, h1 - 2);      Gdk::Rectangle rect(x1, 0, x2 - x1, h1);
743      }      update_after_move(new_l);
744    
745      move.pos = k;      get_window()->invalidate_rect(rect, false);
     move.touch_left = new_touch_left;  
     move.touch_right = new_touch_right;  
746  }  }
747    
748    
# Line 538  bool RegionChooser::on_motion_notify_eve Line 753  bool RegionChooser::on_motion_notify_eve
753      Gdk::ModifierType state = Gdk::ModifierType(0);      Gdk::ModifierType state = Gdk::ModifierType(0);
754      window->get_pointer(x, y, state);      window->get_pointer(x, y, state);
755    
756        // handle virtual MIDI keyboard
757        if (m_VirtKeybModeChoice.get_value() != VIRT_KEYBOARD_MODE_CHORD &&
758            currentActiveKey > 0 &&
759            event->y >= REGION_BLOCK_HEIGHT &&
760            event->y < REGION_BLOCK_HEIGHT + KEYBOARD_HEIGHT)
761        {
762            const int k = x_to_key(event->x, get_width() - 1);
763            if (k != currentActiveKey) {
764                int velocity =
765                    (event->y >= REGION_BLOCK_HEIGHT + KEYBOARD_HEIGHT - 1) ? 127 :
766                    int(float(event->y - REGION_BLOCK_HEIGHT) /
767                        float(KEYBOARD_HEIGHT) * 128.0f) + 1;
768                if (velocity <= 0) velocity = 1;
769                keyboard_key_released_signal.emit(currentActiveKey, velocity);
770                currentActiveKey = k;
771                keyboard_key_hit_signal.emit(k, velocity);
772            }
773        }
774    
775      if (resize.active) {      if (resize.active) {
776          motion_resize_region(x, y);          motion_resize_region(x, y);
777      } else if (move.active) {      } else if (move.active) {
# Line 545  bool RegionChooser::on_motion_notify_eve Line 779  bool RegionChooser::on_motion_notify_eve
779      } else {      } else {
780          if (is_in_resize_zone(x, y)) {          if (is_in_resize_zone(x, y)) {
781              if (!cursor_is_resize) {              if (!cursor_is_resize) {
782    #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
783                  window->set_cursor(Gdk::Cursor(Gdk::SB_H_DOUBLE_ARROW));                  window->set_cursor(Gdk::Cursor(Gdk::SB_H_DOUBLE_ARROW));
784    #else
785                    window->set_cursor(Gdk::Cursor::create(Gdk::SB_H_DOUBLE_ARROW));
786    #endif
787                  cursor_is_resize = true;                  cursor_is_resize = true;
788              }              }
789          } else if (cursor_is_resize) {          } else if (cursor_is_resize) {
# Line 558  bool RegionChooser::on_motion_notify_eve Line 796  bool RegionChooser::on_motion_notify_eve
796  }  }
797    
798  bool RegionChooser::is_in_resize_zone(double x, double y) {  bool RegionChooser::is_in_resize_zone(double x, double y) {
799      const int w = width - 1;      const int w = get_width() - 1;
800    
801      if (instrument && y >= 0 && y <= h1) {      if (instrument && y >= 0 && y <= h1) {
802          gig::Region* prev_region = 0;          gig::Region* prev_region = 0;
803          gig::Region* next_region;          gig::Region* next_region;
804          for (gig::Region* r = instrument->GetFirstRegion() ; r ; r = next_region) {          for (gig::Region* r = regions.first(); r ; r = next_region) {
805              next_region = instrument->GetNextRegion();              next_region = regions.next();
806    
807              int lo = int(w * (r->KeyRange.low) / 128.0 + 0.5);              int lo = key_to_x(r->KeyRange.low, w);
808              if (x <= lo - 2) break;              if (x <= lo - 2) break;
809              if (x < lo + 2) {              if (x < lo + 2) {
810                  resize.region = r;                  resize.region = r;
# Line 580  bool RegionChooser::is_in_resize_zone(do Line 818  bool RegionChooser::is_in_resize_zone(do
818                      resize.mode = resize.undecided;                      resize.mode = resize.undecided;
819                      resize.min = prev_region->KeyRange.low + 1;                      resize.min = prev_region->KeyRange.low + 1;
820                      resize.prev_region = prev_region;                      resize.prev_region = prev_region;
821                      return true;                      return resize.min != resize.max;
822                  }                  }
823    
824                  // edit low limit                  // edit low limit
825                  resize.mode = resize.moving_low_limit;                  resize.mode = resize.moving_low_limit;
826                  resize.min = prev_region ? prev_region->KeyRange.high + 1 : 0;                  resize.min = prev_region ? prev_region->KeyRange.high + 1 : 0;
827                  return true;                  return resize.min != resize.max;
828              }              }
829              if (!next_region || r->KeyRange.high + 1 != next_region->KeyRange.low) {              if (!next_region || r->KeyRange.high + 1 != next_region->KeyRange.low) {
830                  int hi = int(w * (r->KeyRange.high + 1) / 128.0 + 0.5);                  int hi = key_to_x(r->KeyRange.high + 1, w);
831                  if (x <= hi - 2) break;                  if (x <= hi - 2) break;
832                  if (x < hi + 2) {                  if (x < hi + 2) {
833                      // edit high limit                      // edit high limit
# Line 598  bool RegionChooser::is_in_resize_zone(do Line 836  bool RegionChooser::is_in_resize_zone(do
836                      resize.mode = resize.moving_high_limit;                      resize.mode = resize.moving_high_limit;
837                      resize.min = r->KeyRange.low + 1;                      resize.min = r->KeyRange.low + 1;
838                      resize.max = next_region ? next_region->KeyRange.low : 128;                      resize.max = next_region ? next_region->KeyRange.low : 128;
839                      return true;                      return resize.min != resize.max;
840                  }                  }
841              }              }
842              prev_region = r;              prev_region = r;
# Line 607  bool RegionChooser::is_in_resize_zone(do Line 845  bool RegionChooser::is_in_resize_zone(do
845      return false;      return false;
846  }  }
847    
848  sigc::signal<void> RegionChooser::signal_region_selected()  sigc::signal<void>& RegionChooser::signal_region_selected()
849  {  {
850      return region_selected;      return region_selected;
851  }  }
852    
853  sigc::signal<void> RegionChooser::signal_instrument_changed()  sigc::signal<void>& RegionChooser::signal_instrument_changed()
854  {  {
855      return instrument_changed;      return instrument_changed;
856  }  }
# Line 620  sigc::signal<void> RegionChooser::signal Line 858  sigc::signal<void> RegionChooser::signal
858  void RegionChooser::show_region_properties()  void RegionChooser::show_region_properties()
859  {  {
860      if (!region) return;      if (!region) return;
861      Gtk::Dialog dialog("Region Properties", true /*modal*/);      Gtk::Dialog dialog(_("Region Properties"), true /*modal*/);
862      // add "Keygroup" checkbox      // add "Keygroup" checkbox
863      Gtk::CheckButton checkBoxKeygroup("Member of a Keygroup (Exclusive Group)");      Gtk::CheckButton checkBoxKeygroup(_("Member of a Keygroup (Exclusive Group)"));
864      checkBoxKeygroup.set_active(region->KeyGroup);      checkBoxKeygroup.set_active(region->KeyGroup);
865      dialog.get_vbox()->pack_start(checkBoxKeygroup);      dialog.get_vbox()->pack_start(checkBoxKeygroup);
866      checkBoxKeygroup.show();      checkBoxKeygroup.show();
867      // add "Keygroup" spinbox      // add "Keygroup" spinbox
868      Gtk::Adjustment adjustment(1, 1, pow(2,32));  #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
869        Gtk::Adjustment adjustment(1, 1, 999);
870      Gtk::SpinButton spinBox(adjustment);      Gtk::SpinButton spinBox(adjustment);
871    #else
872        Gtk::SpinButton spinBox(Gtk::Adjustment::create(1, 1, 999));
873    #endif
874      if (region->KeyGroup) spinBox.set_value(region->KeyGroup);      if (region->KeyGroup) spinBox.set_value(region->KeyGroup);
875      dialog.get_vbox()->pack_start(spinBox);      dialog.get_vbox()->pack_start(spinBox);
876      spinBox.show();      spinBox.show();
# Line 644  void RegionChooser::show_region_properti Line 886  void RegionChooser::show_region_properti
886    
887  void RegionChooser::add_region()  void RegionChooser::add_region()
888  {  {
889      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;  
     }  
890    
891      region = instrument->AddRegion();      region = instrument->AddRegion();
892      region->KeyRange.low = region->KeyRange.high = new_region_pos;      region->SetKeyRange(new_region_pos, new_region_pos);
893    
894        instrument_struct_changed_signal.emit(instrument);
895        regions.update(instrument);
896    
     instrument->MoveRegion(region, r);  
897      queue_draw();      queue_draw();
898      region_selected();      region_selected();
899        dimensionManager.set_region(region);
900      instrument_changed();      instrument_changed();
901  }  }
902    
903  void RegionChooser::delete_region()  void RegionChooser::delete_region()
904  {  {
905        instrument_struct_to_be_changed_signal.emit(instrument);
906      instrument->DeleteRegion(region);      instrument->DeleteRegion(region);
907        instrument_struct_changed_signal.emit(instrument);
908        regions.update(instrument);
909    
910      region = 0;      region = 0;
911      queue_draw();      queue_draw();
912      region_selected();      region_selected();
913        dimensionManager.set_region(region);
914      instrument_changed();      instrument_changed();
915  }  }
916    
# Line 678  void RegionChooser::on_dimension_manager Line 925  void RegionChooser::on_dimension_manager
925      region_selected();      region_selected();
926      instrument_changed();      instrument_changed();
927  }  }
928    
929    sigc::signal<void, gig::Instrument*>& RegionChooser::signal_instrument_struct_to_be_changed() {
930        return instrument_struct_to_be_changed_signal;
931    }
932    
933    sigc::signal<void, gig::Instrument*>& RegionChooser::signal_instrument_struct_changed() {
934        return instrument_struct_changed_signal;
935    }
936    
937    sigc::signal<void, gig::Region*>& RegionChooser::signal_region_to_be_changed() {
938        return region_to_be_changed_signal;
939    }
940    
941    sigc::signal<void, gig::Region*>& RegionChooser::signal_region_changed_signal() {
942        return region_changed_signal;
943    }
944    
945    sigc::signal<void, int/*key*/, int/*velocity*/>& RegionChooser::signal_keyboard_key_hit() {
946        return keyboard_key_hit_signal;
947    }
948    
949    sigc::signal<void, int/*key*/, int/*velocity*/>& RegionChooser::signal_keyboard_key_released() {
950        return keyboard_key_released_signal;
951    }

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

  ViewVC Help
Powered by ViewVC