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

Legend:
Removed from v.1261  
changed lines
  Added in v.2151

  ViewVC Help
Powered by ViewVC