/[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 1654 by schoenebeck, Wed Jan 30 02:20:48 2008 UTC revision 2169 by persson, Sun Mar 6 07:51:04 2011 UTC
# Line 1  Line 1 
1  /*  /*
2   * Copyright (C) 2006-2008 Andreas Persson   * Copyright (C) 2006-2011 Andreas Persson
3   *   *
4   * This program is free software; you can redistribute it and/or   * This program is free software; you can redistribute it and/or
5   * modify it under the terms of the GNU General Public License as   * modify it under the terms of the GNU General Public License as
# Line 18  Line 18 
18   */   */
19    
20  #include "regionchooser.h"  #include "regionchooser.h"
21    
22  #include <algorithm>  #include <algorithm>
23    #include <sstream>
24    
25    #include <cairomm/context.h>
26    #include <gdkmm/general.h>
27  #include <gdkmm/cursor.h>  #include <gdkmm/cursor.h>
28  #include <gtkmm/stock.h>  #include <gtkmm/stock.h>
29  #include <gtkmm/spinbutton.h>  #include <gtkmm/spinbutton.h>
30  #include <gtkmm/dialog.h>  #include <gtkmm/dialog.h>
 #include <math.h>  
31    
32  #include "global.h"  #include "global.h"
33    
34    #define REGION_BLOCK_HEIGHT             20
35    #define KEYBOARD_HEIGHT                 40
36    
37  void SortedRegions::update(gig::Instrument* instrument) {  void SortedRegions::update(gig::Instrument* instrument) {
38      // Usually, the regions in a gig file are ordered after their key      // Usually, the regions in a gig file are ordered after their key
39      // range, but there are files where they are not. The      // range, but there are files where they are not. The
40      // RegionChooser code needs a sorted list of regions.      // RegionChooser code needs a sorted list of regions.
41      regions.clear();      regions.clear();
42      if (instrument) {      if (instrument) {
43          for (gig::Region *r = instrument->GetFirstRegion() ;          for (gig::Region* r = instrument->GetFirstRegion() ;
44               r ;               r ;
45               r = instrument->GetNextRegion()) {               r = instrument->GetNextRegion()) {
46              regions.push_back(r);              regions.push_back(r);
# Line 54  gig::Region* SortedRegions::next() { Line 61  gig::Region* SortedRegions::next() {
61    
62    
63    
64  RegionChooser::RegionChooser()  RegionChooser::RegionChooser() :
65        activeKeyColor("red"),
66        red("#8070ff"),
67        grey1("grey69"),
68        white("white"),
69        black("black"),
70        m_VirtKeybModeChoice(_("Virtual Keyboard Mode")),
71        currentActiveKey(-1)
72  {  {
73      Glib::RefPtr<Gdk::Colormap> colormap = get_default_colormap();      set_size_request(500, KEYBOARD_HEIGHT + REGION_BLOCK_HEIGHT);
74    
     red = Gdk::Color("#8070ff");  
     grey1 = Gdk::Color("#b0b0b0");  
     activeKeyColor = Gdk::Color("#ff0000");  
     white = Gdk::Color("#ffffff");  
     black = Gdk::Color("#000000");  
   
     colormap->alloc_color(red);  
     colormap->alloc_color(grey1);  
     colormap->alloc_color(activeKeyColor);  
     colormap->alloc_color(white);  
     colormap->alloc_color(black);  
75      instrument = 0;      instrument = 0;
76      region = 0;      region = 0;
77      resize.active = false;      resize.active = false;
78      move.active = false;      move.active = false;
79      cursor_is_resize = false;      cursor_is_resize = false;
80      h1 = 20;      h1 = REGION_BLOCK_HEIGHT;
81    
82        // properties of the virtual keyboard
83        {
84            const char* choices[] = { _("normal"), _("chord"), NULL };
85            static const virt_keyboard_mode_t values[] = {
86                VIRT_KEYBOARD_MODE_NORMAL,
87                VIRT_KEYBOARD_MODE_CHORD
88            };
89            m_VirtKeybModeChoice.set_choices(choices, values);
90            m_VirtKeybModeChoice.set_value(VIRT_KEYBOARD_MODE_NORMAL);
91        }
92        m_VirtKeybVelocityLabelDescr.set_text(_("Note-On Velocity:"));
93        m_VirtKeybVelocityLabel.set_text("-");
94        m_VirtKeybOffVelocityLabelDescr.set_text(_("Note-Off Velocity:"));
95        m_VirtKeybOffVelocityLabel.set_text("-");
96        m_VirtKeybPropsBox.pack_start(m_VirtKeybModeChoice.label, Gtk::PACK_SHRINK);
97        m_VirtKeybPropsBox.pack_start(m_VirtKeybModeChoice.widget, Gtk::PACK_SHRINK);
98        m_VirtKeybPropsBox.pack_start(m_VirtKeybVelocityLabelDescr, Gtk::PACK_SHRINK);
99        m_VirtKeybPropsBox.pack_start(m_VirtKeybVelocityLabel, Gtk::PACK_SHRINK);
100        m_VirtKeybPropsBox.pack_start(m_VirtKeybOffVelocityLabelDescr, Gtk::PACK_SHRINK);
101        m_VirtKeybPropsBox.pack_start(m_VirtKeybOffVelocityLabel, Gtk::PACK_SHRINK);
102        m_VirtKeybPropsBox.set_spacing(10);
103        m_VirtKeybPropsBox.show();
104    
105      actionGroup = Gtk::ActionGroup::create();      actionGroup = Gtk::ActionGroup::create();
106      actionGroup->add(Gtk::Action::create("Properties",      actionGroup->add(Gtk::Action::create("Properties",
# Line 122  RegionChooser::RegionChooser() Line 148  RegionChooser::RegionChooser()
148              sigc::mem_fun(*this, &RegionChooser::on_dimension_manager_changed)              sigc::mem_fun(*this, &RegionChooser::on_dimension_manager_changed)
149          )          )
150      );      );
151        keyboard_key_hit_signal.connect(
152            sigc::mem_fun(*this, &RegionChooser::on_note_on_event)
153        );
154        keyboard_key_released_signal.connect(
155            sigc::mem_fun(*this, &RegionChooser::on_note_off_event)
156        );
157  }  }
158    
159  RegionChooser::~RegionChooser()  RegionChooser::~RegionChooser()
160  {  {
161  }  }
162    
163    template<class T> inline std::string ToString(T o) {
164        std::stringstream ss;
165        ss << o;
166        return ss.str();
167    }
168    
169  void RegionChooser::on_note_on_event(int key, int velocity) {  void RegionChooser::on_note_on_event(int key, int velocity) {
170      draw_region(key, key+1, activeKeyColor);      draw_key(key, activeKeyColor);
171        m_VirtKeybVelocityLabel.set_text(ToString(velocity));
172  }  }
173    
174  void RegionChooser::on_note_off_event(int key, int velocity) {  void RegionChooser::on_note_off_event(int key, int velocity) {
175      if (is_black_key(key))      if (is_black_key(key)) {
176          draw_region(key, key+1, black);          draw_key(key, black);
177      else      } else {
178          draw_region(key, key+1, white);          draw_key(key, key >= 21 && key <= 108 ? white : grey1);
179        }
180        m_VirtKeybOffVelocityLabel.set_text(ToString(velocity));
181  }  }
182    
183  void RegionChooser::on_realize()  #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
184    bool RegionChooser::on_expose_event(GdkEventExpose* e)
185  {  {
186      // We need to call the base on_realize()      return on_draw(get_window()->create_cairo_context());
     Gtk::DrawingArea::on_realize();  
   
     // Now we can allocate any additional resources we need  
     Glib::RefPtr<Gdk::Window> window = get_window();  
     gc = Gdk::GC::create(window);  
     window->clear();  
187  }  }
188    #endif
189    
190  bool RegionChooser::on_expose_event(GdkEventExpose* event)  bool RegionChooser::on_draw(const Cairo::RefPtr<Cairo::Context>& cr)
191  {  {
192      Glib::RefPtr<Gdk::Window> window = get_window();      const int h = KEYBOARD_HEIGHT;
     window->clear();  
     const int h = 40;  
193      const int w = get_width() - 1;      const int w = get_width() - 1;
194      const int bh = int(h * 0.55);      const int bh = int(h * 0.55);
195    
196      Glib::RefPtr<const Gdk::GC> black = get_style()->get_black_gc();      cr->save();
197      Glib::RefPtr<const Gdk::GC> white = get_style()->get_white_gc();      cr->set_line_width(1);
198    
199      Glib::RefPtr<Pango::Context> context = get_pango_context();  #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
200      Glib::RefPtr<Pango::Layout> layout = Pango::Layout::create(context);      const Gdk::Color bg = get_style()->get_bg(Gtk::STATE_NORMAL);
201    #else
202        const Gdk::RGBA bg = get_style_context()->get_background_color();
203    #endif
204        Gdk::Cairo::set_source_rgba(cr, bg);
205        cr->paint();
206    
207        Gdk::Cairo::set_source_rgba(cr, black);
208        cr->rectangle(0.5, h1 + 0.5, w, h - 1);
209        cr->stroke();
210    
     window->draw_rectangle(black, false, 0, h1, w, h - 1);  
     gc->set_foreground(grey1);  
211      int x1 = int(w * 20.5 / 128.0 + 0.5);      int x1 = int(w * 20.5 / 128.0 + 0.5);
212      int x2 = int(w * 109.5 / 128.0 + 0.5);      int x2 = int(w * 109.5 / 128.0 + 0.5);
213      window->draw_rectangle(gc, true, 1, h1 + 1,  
214                             x1 - 1, h - 2);      Gdk::Cairo::set_source_rgba(cr, grey1);
215      window->draw_rectangle(white, true, x1 + 1, h1 + 1, x2 - x1 - 1, h - 2);      cr->rectangle(1, h1 + 1, x1 - 1, h - 2);
216      window->draw_rectangle(gc, true, x2 + 1, h1 + 1,      cr->fill();
217                             w - x2 - 1, h - 2);  
218      int octave = -1;      Gdk::Cairo::set_source_rgba(cr, white);
219        cr->rectangle(x1 + 1, h1 + 1, x2 - x1 - 1, h - 2);
220        cr->fill();
221    
222        Gdk::Cairo::set_source_rgba(cr, grey1);
223        cr->rectangle(x2 + 1, h1 + 1, w - x2 - 1, h - 2);
224        cr->fill();
225    
226        Gdk::Cairo::set_source_rgba(cr, black);
227      for (int i = 0 ; i < 128 ; i++) {      for (int i = 0 ; i < 128 ; i++) {
228          int note = (i + 3) % 12;          int note = (i + 3) % 12;
229          int x = int(w * i / 128.0 + 0.5);          int x = int(w * i / 128.0 + 0.5);
230    
231          if (note == 1 || note == 4 || note == 6 || note == 9 || note == 11) {          if (note == 1 || note == 4 || note == 6 ||
232                note == 9 || note == 11) {
233              int x2 = int(w * (i + 0.5) / 128.0 + 0.5);              int x2 = int(w * (i + 0.5) / 128.0 + 0.5);
234              window->draw_line(black, x2, h1 + bh, x2, h1 + h);              cr->move_to(x2 + 0.5, h1 + bh + 0.5);
235                cr->line_to(x2 + 0.5, h1 + h - 1);
236                cr->stroke();
237    
238              int x3 = int(w * (i + 1) / 128.0 + 0.5);              int x3 = int(w * (i + 1) / 128.0 + 0.5);
239              window->draw_rectangle(black, true, x, h1 + 1, x3 - x + 1, bh);              cr->rectangle(x, h1 + 1, x3 - x + 1, bh);
240                cr->fill();
241          } else if (note == 3 || note == 8) {          } else if (note == 3 || note == 8) {
242              window->draw_line(black, x, h1 + 1, x, h1 + h);              cr->move_to(x + 0.5, h1 + 1);
243          }              cr->line_to(x + 0.5, h1 + h - 1);
244          if (note == 3) {              cr->stroke();
245              char buf[30];  
246              sprintf(buf, "<span size=\"8000\">%d</span>", octave);              if (note == 3) draw_digit(i);
             layout->set_markup(buf);  
             Pango::Rectangle rectangle = layout->get_logical_extents();  
             double text_w = double(rectangle.get_width()) / Pango::SCALE;  
             double text_h = double(rectangle.get_height()) / Pango::SCALE;  
             double x2 = w * (i + 0.75) / 128.0;  
             window->draw_layout(black, int(x2 - text_w / 2 + 1),  
                                 int(h1 + h - text_h + 0.5), layout);  
             octave++;  
247          }          }
248      }      }
249    
250      if (instrument) {      if (instrument) {
251          int i = 0;          int i = 0;
252          gig::Region *next_region;          gig::Region* next_region;
253          int x3 = -1;          int x3 = -1;
254          for (gig::Region *r = regions.first() ; r ; r = next_region) {          for (gig::Region* r = regions.first() ; r ; r = next_region) {
255    
256              if (x3 < 0) x3 = int(w * (r->KeyRange.low) / 128.0 + 0.5);              if (x3 < 0) x3 = int(w * (r->KeyRange.low) / 128.0 + 0.5);
257              next_region = regions.next();              next_region = regions.next();
258              if (!next_region || r->KeyRange.high + 1 != next_region->KeyRange.low) {              if (!next_region ||
259                    r->KeyRange.high + 1 != next_region->KeyRange.low) {
260                  int x2 = int(w * (r->KeyRange.high + 1) / 128.0 + 0.5);                  int x2 = int(w * (r->KeyRange.high + 1) / 128.0 + 0.5);
261                  window->draw_line(black, x3, 0, x2, 0);                  cr->move_to(x3, 0.5);
262                  window->draw_line(black, x3, h1 - 1, x2, h1 - 1);                  cr->line_to(x2 + 0.5, 0.5);
263                  window->draw_line(black, x2, 1, x2, h1 - 2);                  cr->line_to(x2 + 0.5, h1 - 0.5);
264                  window->draw_rectangle(white, true, x3 + 1, 1, x2 - x3 - 1, h1 - 2);                  cr->line_to(x3, h1 - 0.5);
265                    cr->stroke();
266    
267                    Gdk::Cairo::set_source_rgba(cr, white);
268                    cr->rectangle(x3 + 1, 1, x2 - x3 - 1, h1 - 2);
269                    cr->fill();
270                    Gdk::Cairo::set_source_rgba(cr, black);
271    
272                  x3 = -1;                  x3 = -1;
273              }              }
274              i++;              i++;
275          }          }
276    
277          for (gig::Region *r = regions.first() ; r ; r = regions.next()) {          for (gig::Region* r = regions.first() ; r ; r = regions.next()) {
278              int x = int(w * (r->KeyRange.low) / 128.0 + 0.5);              int x = int(w * (r->KeyRange.low) / 128.0 + 0.5);
279              window->draw_line(black, x, 1, x, h1 - 2);              cr->move_to(x + 0.5, 1);
280                cr->line_to(x + 0.5, h1 - 1);
281                cr->stroke();
282          }          }
283    
284          if (region) {          if (region) {
285              int x1 = int(w * (region->KeyRange.low) / 128.0 + 0.5);              int x1 = int(w * (region->KeyRange.low) / 128.0 + 0.5);
286              int x2 = int(w * (region->KeyRange.high + 1) / 128.0 + 0.5);              int x2 = int(w * (region->KeyRange.high + 1) / 128.0 + 0.5);
287              gc->set_foreground(red);              Gdk::Cairo::set_source_rgba(cr, red);
288              window->draw_rectangle(gc, true, x1 + 1, 1, x2 - x1 - 1, h1 - 2);              cr->rectangle(x1 + 1, 1, x2 - x1 - 1, h1 - 2);
289                cr->fill();
290          }          }
291      }      }
     return true;  
 }  
292    
293        cr->restore();
294    
295  void RegionChooser::on_size_request(GtkRequisition* requisition)      return true;
 {  
     *requisition = GtkRequisition();  
     requisition->height = 40 + 20;  
     requisition->width = 500;  
296  }  }
297    
298    
299  bool RegionChooser::is_black_key(int key) {  bool RegionChooser::is_black_key(int key) {
300      const int note = (key + 3) % 12;      const int note = (key + 3) % 12;
301      return note == 1 || note == 4 || note == 6 || note == 9 || note == 11;      return note == 1 || note == 4 || note == 6 || note == 9 || note == 11;
302  }  }
303    
304  void RegionChooser::draw_region(int from, int to, const Gdk::Color& color)  void RegionChooser::draw_digit(int key) {
305        const int h = KEYBOARD_HEIGHT;
306        const int w = get_width() - 1;
307        Glib::RefPtr<Pango::Layout> layout = Pango::Layout::create(get_pango_context());
308        char buf[30];
309        sprintf(buf, "<span size=\"8000\">%d</span>", key / 12 - 1);
310        layout->set_markup(buf);
311        Pango::Rectangle rectangle = layout->get_logical_extents();
312        double text_w = double(rectangle.get_width()) / Pango::SCALE;
313        double text_h = double(rectangle.get_height()) / Pango::SCALE;
314        double x = w * (key + 0.75) / 128.0;
315        Cairo::RefPtr<Cairo::Context> cr = get_window()->create_cairo_context();
316        Gdk::Cairo::set_source_rgba(cr, black);
317        cr->move_to(int(x - text_w / 2 + 1), int(h1 + h - text_h + 0.5));
318    #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 16) || GTKMM_MAJOR_VERSION < 2
319        pango_cairo_show_layout(cr->cobj(), layout->gobj());
320    #else
321        layout->show_in_cairo_context(cr);
322    #endif
323    }
324    
325    void RegionChooser::draw_key(int key, const Gdk::RGBA& color)
326  {  {
327      const int h = 40;      const int h = KEYBOARD_HEIGHT;
328      const int w = get_width();      const int w = get_width() - 1;
329      const int bh = int(h * 0.55);      const int bh = int(h * 0.55);
330    
331      Glib::RefPtr<Gdk::Window> window = get_window();      Cairo::RefPtr<Cairo::Context> cr = get_window()->create_cairo_context();
332      gc->set_foreground(color);      Gdk::Cairo::set_source_rgba(cr, color);
333    
334      for (int i = from ; i < to ; i++) {      int note = (key + 3) % 12;
335          int note = (i + 3) % 12;      int x = int(w * key / 128.0 + 0.5) + 1;
336          int x = int(w * i / 128.0 + 0.5) + 1;      int x2 = int(w * (key + 1.5) / 128.0 + 0.5);
337          int x2 = int(w * (i + 1.5) / 128.0 + 0.5);      int x3 = int(w * (key + 1) / 128.0 + 0.5);
338          int x3 = int(w * (i + 1) / 128.0 + 0.5);      int x4 = int(w * (key - 0.5) / 128.0 + 0.5);
339          int x4 = int(w * (i - 0.5) / 128 + 0.5) + 1;      int w1 = x3 - x;
340          int w1 = x3 - x;      switch (note) {
341          switch (note) {      case 0: case 5: case 10:
342          case 0: case 5: case 10:          cr->rectangle(x, h1 + 1, w1, bh);
343              window->draw_rectangle(gc, true, x - 1, h1 + 1, w1, bh);          cr->fill();
344              window->draw_rectangle(gc, true, x4, h1 + bh + 1, x2 - x4 - 1, h - bh - 2);          cr->rectangle(x4 + 1, h1 + bh + 1, x2 - x4 - 1, h - bh - 2);
345              break;          cr->fill();
346          case 2: case 7:          break;
347              window->draw_rectangle(gc, true, x, h1 + 1, w1, bh);      case 2: case 7:
348              window->draw_rectangle(gc, true, x4 - 1, h1 + bh + 1, x3 - x4 + 1, h - bh - 2);          cr->rectangle(x, h1 + 1, w1, bh);
349              break;          cr->fill();
350          case 3: case 8:          cr->rectangle(x4 + 1, h1 + bh + 1, x3 - x4 - 1, h - bh - 2);
351              window->draw_rectangle(gc, true, x, h1 + 1, w1, bh);          cr->fill();
352              window->draw_rectangle(gc, true, x, h1 + bh + 1, x2 - x, h - bh - 2);          break;
353              break;      case 3: case 8:
354          default:          cr->rectangle(x, h1 + 1, w1, bh);
355              window->draw_rectangle(gc, true, x, h1 + 1, w1 - 1, bh - 1);          cr->fill();
356              break;          cr->rectangle(x, h1 + bh + 1, x2 - x, h - bh - 2);
357          }          cr->fill();
358            if (note == 3) draw_digit(key);
359            break;
360        default:
361            cr->rectangle(x, h1 + 1, w1, bh - 1);
362            cr->fill();
363            break;
364      }      }
365  }  }
366    
# Line 291  void RegionChooser::set_instrument(gig:: Line 371  void RegionChooser::set_instrument(gig::
371      region = regions.first();      region = regions.first();
372      queue_draw();      queue_draw();
373      region_selected();      region_selected();
374        dimensionManager.set_region(region);
375  }  }
376    
377  bool RegionChooser::on_button_release_event(GdkEventButton* event)  bool RegionChooser::on_button_release_event(GdkEventButton* event)
378  {  {
379        const int k = int(event->x / (get_width() - 1) * 128.0);
380    
381        // handle-note off on virtual keyboard
382        if (event->type == GDK_BUTTON_RELEASE) {
383            int velocity = (event->y >= REGION_BLOCK_HEIGHT + KEYBOARD_HEIGHT - 1) ? 127 :
384                           int(float(event->y - REGION_BLOCK_HEIGHT) / float(KEYBOARD_HEIGHT) * 128.0f) + 1;
385            if (velocity <= 0) velocity = 1;
386            switch (m_VirtKeybModeChoice.get_value()) {
387                case VIRT_KEYBOARD_MODE_CHORD:
388                    if (event->y >= REGION_BLOCK_HEIGHT)
389                        keyboard_key_released_signal.emit(k, velocity);
390                    break;
391                case VIRT_KEYBOARD_MODE_NORMAL:
392                default:
393                    if (currentActiveKey >= 0 && currentActiveKey <= 127) {
394                        keyboard_key_released_signal.emit(currentActiveKey, velocity);
395                        currentActiveKey = -1;
396                    }
397                    break;
398            }
399        }
400    
401      if (resize.active) {      if (resize.active) {
402    #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
403          get_window()->pointer_ungrab(event->time);          get_window()->pointer_ungrab(event->time);
404    #else
405            Glib::wrap(event->device, true)->ungrab(event->time);
406    #endif
407          resize.active = false;          resize.active = false;
408    
409          if (resize.mode == resize.moving_high_limit) {          if (resize.mode == resize.moving_high_limit) {
# Line 328  bool RegionChooser::on_button_release_ev Line 435  bool RegionChooser::on_button_release_ev
435              cursor_is_resize = false;              cursor_is_resize = false;
436          }          }
437      } else if (move.active) {      } else if (move.active) {
438    #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
439          get_window()->pointer_ungrab(event->time);          get_window()->pointer_ungrab(event->time);
440    #else
441            Glib::wrap(event->device, true)->ungrab(event->time);
442    #endif
443          move.active = false;          move.active = false;
444    
445          if (move.pos) {          if (move.pos) {
# Line 343  bool RegionChooser::on_button_release_ev Line 454  bool RegionChooser::on_button_release_ev
454          }          }
455    
456          if (is_in_resize_zone(event->x, event->y)) {          if (is_in_resize_zone(event->x, event->y)) {
457    #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
458              get_window()->set_cursor(Gdk::Cursor(Gdk::SB_H_DOUBLE_ARROW));              get_window()->set_cursor(Gdk::Cursor(Gdk::SB_H_DOUBLE_ARROW));
459    #else
460                get_window()->set_cursor(Gdk::Cursor::create(Gdk::SB_H_DOUBLE_ARROW));
461    #endif
462              cursor_is_resize = true;              cursor_is_resize = true;
463          }          }
464      }      }
# Line 354  bool RegionChooser::on_button_press_even Line 469  bool RegionChooser::on_button_press_even
469  {  {
470      if (!instrument) return true;      if (!instrument) return true;
471    
472      int k = int(event->x / (get_width() - 1) * 128.0);      const int k = int(event->x / (get_width() - 1) * 128.0);
473    
474        if (event->type == GDK_BUTTON_PRESS) {
475            if (event->y >= REGION_BLOCK_HEIGHT) {
476                int velocity = (event->y >= REGION_BLOCK_HEIGHT + KEYBOARD_HEIGHT - 1) ? 127 :
477                               int(float(event->y - REGION_BLOCK_HEIGHT) / float(KEYBOARD_HEIGHT) * 128.0f) + 1;
478                currentActiveKey = k;
479                keyboard_key_hit_signal.emit(k, velocity);
480            }
481        }
482    
483        if (event->y >= REGION_BLOCK_HEIGHT) return true;
484      if (event->type == GDK_BUTTON_PRESS && event->button == 3) {      if (event->type == GDK_BUTTON_PRESS && event->button == 3) {
485          gig::Region* r = get_region(k);          gig::Region* r = get_region(k);
486          if (r) {          if (r) {
487              region = r;              region = r;
488              queue_draw();              queue_draw();
489              region_selected();              region_selected();
490                dimensionManager.set_region(region);
491              popup_menu_inside_region->popup(event->button, event->time);              popup_menu_inside_region->popup(event->button, event->time);
492          } else {          } else {
493              new_region_pos = k;              new_region_pos = k;
# Line 369  bool RegionChooser::on_button_press_even Line 495  bool RegionChooser::on_button_press_even
495          }          }
496      } else {      } else {
497          if (is_in_resize_zone(event->x, event->y)) {          if (is_in_resize_zone(event->x, event->y)) {
498    #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
499              get_window()->pointer_grab(false,              get_window()->pointer_grab(false,
500                                         Gdk::BUTTON_RELEASE_MASK |                                         Gdk::BUTTON_RELEASE_MASK |
501                                         Gdk::POINTER_MOTION_MASK |                                         Gdk::POINTER_MOTION_MASK |
502                                         Gdk::POINTER_MOTION_HINT_MASK,                                         Gdk::POINTER_MOTION_HINT_MASK,
503                                         Gdk::Cursor(Gdk::SB_H_DOUBLE_ARROW), event->time);                                         Gdk::Cursor(Gdk::SB_H_DOUBLE_ARROW),
504                                           event->time);
505    #else
506                Glib::wrap(event->device, true)->grab(get_window(),
507                                                      Gdk::OWNERSHIP_NONE,
508                                                      false,
509                                                      Gdk::BUTTON_RELEASE_MASK |
510                                                      Gdk::POINTER_MOTION_MASK |
511                                                      Gdk::POINTER_MOTION_HINT_MASK,
512                                                      Gdk::Cursor::create(Gdk::SB_H_DOUBLE_ARROW),
513                                                      event->time);
514    #endif
515              resize.active = true;              resize.active = true;
516          } else {          } else {
517              gig::Region* r = get_region(k);              gig::Region* r = get_region(k);
# Line 381  bool RegionChooser::on_button_press_even Line 519  bool RegionChooser::on_button_press_even
519                  region = r;                  region = r;
520                  queue_draw();                  queue_draw();
521                  region_selected();                  region_selected();
522                    dimensionManager.set_region(region);
523    
524    #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
525                  get_window()->pointer_grab(false,                  get_window()->pointer_grab(false,
526                                             Gdk::BUTTON_RELEASE_MASK |                                             Gdk::BUTTON_RELEASE_MASK |
527                                             Gdk::POINTER_MOTION_MASK |                                             Gdk::POINTER_MOTION_MASK |
528                                             Gdk::POINTER_MOTION_HINT_MASK,                                             Gdk::POINTER_MOTION_HINT_MASK,
529                                             Gdk::Cursor(Gdk::FLEUR), event->time);                                             Gdk::Cursor(Gdk::FLEUR),
530                                               event->time);
531    #else
532                    Glib::wrap(event->device, true)->grab(get_window(),
533                                                          Gdk::OWNERSHIP_NONE,
534                                                          false,
535                                                          Gdk::BUTTON_RELEASE_MASK |
536                                                          Gdk::POINTER_MOTION_MASK |
537                                                          Gdk::POINTER_MOTION_HINT_MASK,
538                                                          Gdk::Cursor::create(Gdk::FLEUR),
539                                                          event->time);
540    #endif
541                  move.active = true;                  move.active = true;
542                  move.from_x = event->x;                  move.from_x = event->x;
543                  move.pos = 0;                  move.pos = 0;
# Line 400  gig::Region* RegionChooser::get_region(i Line 551  gig::Region* RegionChooser::get_region(i
551  {  {
552      gig::Region* prev_region = 0;      gig::Region* prev_region = 0;
553      gig::Region* next_region;      gig::Region* next_region;
554      for (gig::Region *r = regions.first() ; r ; r = next_region) {      for (gig::Region* r = regions.first() ; r ; r = next_region) {
555          next_region = regions.next();          next_region = regions.next();
556    
557          if (key < r->KeyRange.low) return 0;          if (key < r->KeyRange.low) return 0;
# Line 417  gig::Region* RegionChooser::get_region(i Line 568  gig::Region* RegionChooser::get_region(i
568  void RegionChooser::motion_resize_region(int x, int y)  void RegionChooser::motion_resize_region(int x, int y)
569  {  {
570      const int w = get_width() - 1;      const int w = get_width() - 1;
     Glib::RefPtr<Gdk::Window> window = get_window();  
571    
572      int k = int(double(x) / w * 128.0 + 0.5);      int k = int(double(x) / w * 128.0 + 0.5);
573    
# Line 425  void RegionChooser::motion_resize_region Line 575  void RegionChooser::motion_resize_region
575      else if (k > resize.max) k = resize.max;      else if (k > resize.max) k = resize.max;
576    
577      if (k != resize.pos) {      if (k != resize.pos) {
578            Cairo::RefPtr<Cairo::Context> cr = get_window()->create_cairo_context();
579            cr->set_line_width(1);
580    
581          if (resize.mode == resize.undecided) {          if (resize.mode == resize.undecided) {
582              if (k < resize.pos) {              if (k < resize.pos) {
583                  // edit high limit of prev_region                  // edit high limit of prev_region
# Line 437  void RegionChooser::motion_resize_region Line 590  void RegionChooser::motion_resize_region
590                  resize.mode = resize.moving_low_limit;                  resize.mode = resize.moving_low_limit;
591              }              }
592          }          }
593          Glib::RefPtr<const Gdk::GC> black = get_style()->get_black_gc();          const Gdk::RGBA white = region == resize.region ? red : this->white;
594          Glib::RefPtr<const Gdk::GC> white = get_style()->get_white_gc();  #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
595          if (region == resize.region) {          const Gdk::Color bg = get_style()->get_bg(Gtk::STATE_NORMAL);
596              gc->set_foreground(red);  #else
597              white = gc;          const Gdk::RGBA bg = get_style_context()->get_background_color();
598          }  #endif
599          Glib::RefPtr<const Gdk::GC> bg = get_style()->get_bg_gc(Gtk::STATE_NORMAL);  
600          int prevx = int(w * resize.pos / 128.0 + 0.5);          int prevx = int(w * resize.pos / 128.0 + 0.5);
601          x = int(w * k / 128.0 + 0.5);          x = int(w * k / 128.0 + 0.5);
602    
603          if (resize.mode == resize.moving_high_limit) {          if (resize.mode == resize.moving_high_limit) {
604              if (k > resize.pos) {              if (k > resize.pos) {
605                  window->draw_rectangle(white, true, prevx, 1, x - prevx, h1 - 2);                  Gdk::Cairo::set_source_rgba(cr, white);
606                  window->draw_line(black, prevx, 0, x, 0);                  cr->rectangle(prevx, 1, x - prevx, h1 - 2);
607                  window->draw_line(black, prevx, h1 - 1, x, h1 - 1);                  cr->fill();
608    
609                    Gdk::Cairo::set_source_rgba(cr, black);
610                    cr->move_to(prevx, 0.5);
611                    cr->line_to(x + 1, 0.5);
612                    cr->move_to(prevx, h1 - 0.5);
613                    cr->line_to(x + 1, h1 - 0.5);
614                    cr->stroke();
615              } else {              } else {
616                  int xx = ((resize.pos == resize.max && resize.max != 128) ? 1 : 0);                  int xx = (resize.pos == resize.max &&
617                  window->draw_rectangle(bg, true, x + 1, 0, prevx - x - xx, h1);                            resize.max != 128) ? 1 : 0;
618                    Gdk::Cairo::set_source_rgba(cr, bg);
619                    cr->rectangle(x + 1, 0, prevx - x - xx, h1);
620                    cr->fill();
621              }              }
622          } else {          } else {
623              if (k < resize.pos) {              if (k < resize.pos) {
624                  window->draw_rectangle(white, true, x + 1, 1, prevx - x, h1 - 2);                  Gdk::Cairo::set_source_rgba(cr, white);
625                  window->draw_line(black, x, 0, prevx, 0);                  cr->rectangle(x + 1, 1, prevx - x, h1 - 2);
626                  window->draw_line(black, x, h1 - 1, prevx, h1 - 1);                  cr->fill();
627    
628                    Gdk::Cairo::set_source_rgba(cr, black);
629                    cr->move_to(x, 0.5);
630                    cr->line_to(prevx, 0.5);
631                    cr->move_to(x, h1 - 0.5);
632                    cr->line_to(prevx, h1 - 0.5);
633                    cr->stroke();
634              } else {              } else {
635                  int xx = ((resize.pos == resize.min && resize.min != 0) ? 1 : 0);                  int xx = (resize.pos == resize.min &&
636                  window->draw_rectangle(bg, true, prevx + xx, 0, x - prevx - xx, h1);                            resize.min != 0) ? 1 : 0;
637                    Gdk::Cairo::set_source_rgba(cr, bg);
638                    cr->rectangle(prevx + xx, 0, x - prevx - xx, h1);
639                    cr->fill();
640              }              }
641          }          }
642          window->draw_line(black, x, 1, x, h1 - 2);          Gdk::Cairo::set_source_rgba(cr, black);
643            cr->move_to(x + 0.5, 1);
644            cr->line_to(x + 0.5, h1 - 1);
645            cr->stroke();
646          resize.pos = k;          resize.pos = k;
647      }      }
648  }  }
# Line 474  void RegionChooser::motion_resize_region Line 650  void RegionChooser::motion_resize_region
650  void RegionChooser::motion_move_region(int x, int y)  void RegionChooser::motion_move_region(int x, int y)
651  {  {
652      const int w = get_width() - 1;      const int w = get_width() - 1;
653      Glib::RefPtr<Gdk::Window> window = get_window();      Cairo::RefPtr<Cairo::Context> cr = get_window()->create_cairo_context();
654        cr->set_line_width(1);
655    
656      int k = int(double(x - move.from_x) / w * 128.0 + 0.5);      int k = int(double(x - move.from_x) / w * 128.0 + 0.5);
657      if (k == move.pos) return;      if (k == move.pos) return;
# Line 547  void RegionChooser::motion_move_region(i Line 724  void RegionChooser::motion_move_region(i
724      k = new_k;      k = new_k;
725      if (k == move.pos) return;      if (k == move.pos) return;
726    
727      Glib::RefPtr<const Gdk::GC> bg = get_style()->get_bg_gc(Gtk::STATE_NORMAL);  #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
728        const Gdk::Color bg = get_style()->get_bg(Gtk::STATE_NORMAL);
729    #else
730        const Gdk::RGBA bg = get_style_context()->get_background_color();
731    #endif
732    
733      int prevx = int(w * (move.pos + region->KeyRange.low) / 128.0 + 0.5);      int prevx = int(w * (move.pos + region->KeyRange.low) / 128.0 + 0.5);
734      x = int(w * (k + region->KeyRange.low) / 128.0 + 0.5);      x = int(w * (k + region->KeyRange.low) / 128.0 + 0.5);
735      int prevx2 = int(w * (move.pos + region->KeyRange.high + 1) / 128.0 + 0.5);      int prevx2 = int(w * (move.pos + region->KeyRange.high + 1) / 128.0 + 0.5);
736      int x2 = int(w * (k + region->KeyRange.high + 1) / 128.0 + 0.5);      int x2 = int(w * (k + region->KeyRange.high + 1) / 128.0 + 0.5);
     Glib::RefPtr<const Gdk::GC> black = get_style()->get_black_gc();  
     gc->set_foreground(red);  
737    
738      if (!new_touch_left) window->draw_line(black, x, 1, x, h1 - 2);      if (!new_touch_left) {
739      if (!new_touch_right) window->draw_line(black, x2, 1, x2, h1 - 2);          Gdk::Cairo::set_source_rgba(cr, black);
740            cr->move_to(x + 0.5, 1);
741            cr->line_to(x + 0.5, h1 - 1);
742            cr->stroke();
743        }
744        if (!new_touch_right) {
745            Gdk::Cairo::set_source_rgba(cr, black);
746            cr->move_to(x2 + 0.5, 1);
747            cr->line_to(x2 + 0.5, h1 - 1);
748            cr->stroke();
749        }
750    
751      if (k > move.pos) {      if (k > move.pos) {
752          window->draw_rectangle(bg, true, prevx + (move.touch_left ? 1 : 0), 0,          Gdk::Cairo::set_source_rgba(cr, bg);
753                                 std::min(x, prevx2 + 1 - (move.touch_right ? 1 : 0)) -          cr->rectangle(prevx + (move.touch_left ? 1 : 0), 0,
754                                 (prevx + (move.touch_left ? 1 : 0)), h1);                        std::min(x, prevx2 + 1 - (move.touch_right ? 1 : 0)) -
755                          (prevx + (move.touch_left ? 1 : 0)), h1);
756          window->draw_line(black, std::max(x, prevx2 + 1), 0, x2, 0);          cr->fill();
757          window->draw_line(black, std::max(x, prevx2 + 1), h1 - 1, x2, h1 - 1);  
758          window->draw_rectangle(gc, true, std::max(x + 1, prevx2), 1,          Gdk::Cairo::set_source_rgba(cr, black);
759                                 x2 - std::max(x + 1, prevx2), h1 - 2);          cr->move_to(std::max(x, prevx2 + 1), 0.5);
760            cr->line_to(x2 + 1, 0.5);
761            cr->move_to(std::max(x, prevx2 + 1), h1 - 0.5);
762            cr->line_to(x2 + 1, h1 - 0.5);
763            cr->stroke();
764    
765            Gdk::Cairo::set_source_rgba(cr, red);
766            cr->rectangle(std::max(x + 1, prevx2), 1,
767                          x2 - std::max(x + 1, prevx2), h1 - 2);
768            cr->fill();
769      } else {      } else {
770          window->draw_rectangle(bg, true, std::max(x2 + 1, prevx + (move.touch_left ? 1 : 0)), 0,          Gdk::Cairo::set_source_rgba(cr, bg);
771                                 prevx2 + 1 - (move.touch_right ? 1 : 0) -          cr->rectangle(std::max(x2 + 1, prevx + (move.touch_left ? 1 : 0)), 0,
772                                 std::max(x2 + 1, prevx + (move.touch_left ? 1 : 0)), h1);                        prevx2 + 1 - (move.touch_right ? 1 : 0) -
773                          std::max(x2 + 1, prevx + (move.touch_left ? 1 : 0)), h1);
774          window->draw_line(black, x, 0, std::min(x2, prevx - 1), 0);          cr->fill();
775          window->draw_line(black, x, h1 - 1, std::min(x2, prevx - 1), h1 - 1);  
776            Gdk::Cairo::set_source_rgba(cr, black);
777          window->draw_rectangle(gc, true, x + 1, 1, std::min(x2 - 1, prevx) - x, h1 - 2);          cr->move_to(x, 0.5);
778            cr->line_to(std::min(x2, prevx - 1) + 1, 0.5);
779            cr->move_to(x, h1 - 0.5);
780            cr->line_to(std::min(x2, prevx - 1) + 1, h1 - 0.5);
781            cr->stroke();
782    
783            Gdk::Cairo::set_source_rgba(cr, red);
784            cr->rectangle(x + 1, 1, std::min(x2 - 1, prevx) - x, h1 - 2);
785            cr->fill();
786      }      }
787    
788      move.pos = k;      move.pos = k;
# Line 591  bool RegionChooser::on_motion_notify_eve Line 798  bool RegionChooser::on_motion_notify_eve
798      Gdk::ModifierType state = Gdk::ModifierType(0);      Gdk::ModifierType state = Gdk::ModifierType(0);
799      window->get_pointer(x, y, state);      window->get_pointer(x, y, state);
800    
801        // handle virtual MIDI keyboard
802        if (m_VirtKeybModeChoice.get_value() != VIRT_KEYBOARD_MODE_CHORD &&
803            currentActiveKey > 0 &&
804            event->y >= REGION_BLOCK_HEIGHT &&
805            event->y < REGION_BLOCK_HEIGHT + KEYBOARD_HEIGHT)
806        {
807            const int k = int(event->x / (get_width() - 1) * 128.0);
808            if (k != currentActiveKey) {
809                int velocity =
810                    (event->y >= REGION_BLOCK_HEIGHT + KEYBOARD_HEIGHT - 1) ? 127 :
811                    int(float(event->y - REGION_BLOCK_HEIGHT) /
812                        float(KEYBOARD_HEIGHT) * 128.0f) + 1;
813                if (velocity <= 0) velocity = 1;
814                keyboard_key_released_signal.emit(currentActiveKey, velocity);
815                currentActiveKey = k;
816                keyboard_key_hit_signal.emit(k, velocity);
817            }
818        }
819    
820      if (resize.active) {      if (resize.active) {
821          motion_resize_region(x, y);          motion_resize_region(x, y);
822      } else if (move.active) {      } else if (move.active) {
# Line 598  bool RegionChooser::on_motion_notify_eve Line 824  bool RegionChooser::on_motion_notify_eve
824      } else {      } else {
825          if (is_in_resize_zone(x, y)) {          if (is_in_resize_zone(x, y)) {
826              if (!cursor_is_resize) {              if (!cursor_is_resize) {
827    #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
828                  window->set_cursor(Gdk::Cursor(Gdk::SB_H_DOUBLE_ARROW));                  window->set_cursor(Gdk::Cursor(Gdk::SB_H_DOUBLE_ARROW));
829    #else
830                    window->set_cursor(Gdk::Cursor::create(Gdk::SB_H_DOUBLE_ARROW));
831    #endif
832                  cursor_is_resize = true;                  cursor_is_resize = true;
833              }              }
834          } else if (cursor_is_resize) {          } else if (cursor_is_resize) {
# Line 673  sigc::signal<void>& RegionChooser::signa Line 903  sigc::signal<void>& RegionChooser::signa
903  void RegionChooser::show_region_properties()  void RegionChooser::show_region_properties()
904  {  {
905      if (!region) return;      if (!region) return;
906      Gtk::Dialog dialog("Region Properties", true /*modal*/);      Gtk::Dialog dialog(_("Region Properties"), true /*modal*/);
907      // add "Keygroup" checkbox      // add "Keygroup" checkbox
908      Gtk::CheckButton checkBoxKeygroup("Member of a Keygroup (Exclusive Group)");      Gtk::CheckButton checkBoxKeygroup(_("Member of a Keygroup (Exclusive Group)"));
909      checkBoxKeygroup.set_active(region->KeyGroup);      checkBoxKeygroup.set_active(region->KeyGroup);
910      dialog.get_vbox()->pack_start(checkBoxKeygroup);      dialog.get_vbox()->pack_start(checkBoxKeygroup);
911      checkBoxKeygroup.show();      checkBoxKeygroup.show();
912      // add "Keygroup" spinbox      // add "Keygroup" spinbox
913      Gtk::Adjustment adjustment(1, 1, pow(2,32));  #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
914        Gtk::Adjustment adjustment(1, 1, 999);
915      Gtk::SpinButton spinBox(adjustment);      Gtk::SpinButton spinBox(adjustment);
916    #else
917        Gtk::SpinButton spinBox(Gtk::Adjustment::create(1, 1, 999));
918    #endif
919      if (region->KeyGroup) spinBox.set_value(region->KeyGroup);      if (region->KeyGroup) spinBox.set_value(region->KeyGroup);
920      dialog.get_vbox()->pack_start(spinBox);      dialog.get_vbox()->pack_start(spinBox);
921      spinBox.show();      spinBox.show();
# Line 707  void RegionChooser::add_region() Line 941  void RegionChooser::add_region()
941    
942      queue_draw();      queue_draw();
943      region_selected();      region_selected();
944        dimensionManager.set_region(region);
945      instrument_changed();      instrument_changed();
946  }  }
947    
# Line 720  void RegionChooser::delete_region() Line 955  void RegionChooser::delete_region()
955      region = 0;      region = 0;
956      queue_draw();      queue_draw();
957      region_selected();      region_selected();
958        dimensionManager.set_region(region);
959      instrument_changed();      instrument_changed();
960  }  }
961    
# Line 750  sigc::signal<void, gig::Region*>& Region Line 986  sigc::signal<void, gig::Region*>& Region
986  sigc::signal<void, gig::Region*>& RegionChooser::signal_region_changed_signal() {  sigc::signal<void, gig::Region*>& RegionChooser::signal_region_changed_signal() {
987      return region_changed_signal;      return region_changed_signal;
988  }  }
989    
990    sigc::signal<void, int/*key*/, int/*velocity*/>& RegionChooser::signal_keyboard_key_hit() {
991        return keyboard_key_hit_signal;
992    }
993    
994    sigc::signal<void, int/*key*/, int/*velocity*/>& RegionChooser::signal_keyboard_key_released() {
995        return keyboard_key_released_signal;
996    }

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

  ViewVC Help
Powered by ViewVC