/[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 1396 by schoenebeck, Wed Oct 10 15:48:54 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 <math.h>  
32    
33  #include "global.h"  #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    
82    
83    RegionChooser::RegionChooser() :
84        m_VirtKeybModeChoice(_("Virtual Keyboard Mode")),
85        currentActiveKey(-1)
86    {
87      red = Gdk::Color("#8070ff");      red = Gdk::Color("#8070ff");
88      grey1 = Gdk::Color("#b0b0b0");      grey1 = Gdk::Color("#b0b0b0");
89        activeKeyColor = Gdk::Color("#ff0000");
90        white = Gdk::Color("#ffffff");
91        black = Gdk::Color("#000000");
92    
     colormap->alloc_color(red);  
     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;      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 89  RegionChooser::RegionChooser() Line 166  RegionChooser::RegionChooser()
166              sigc::mem_fun(*this, &RegionChooser::on_dimension_manager_changed)              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    
177  RegionChooser::~RegionChooser()  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));
190      window->clear();  }
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      Glib::RefPtr<Pango::Context> context = get_pango_context();          const int w = get_width() - 1;
214      Glib::RefPtr<Pango::Layout> layout = Pango::Layout::create(context);          const int bh = int(h * 0.55);
215    
216      window->draw_rectangle(black, false, 0, h1, w, h - 1);          cr->save();
217      gc->set_foreground(grey1);          cr->set_line_width(1);
218      int x1 = int(w * 20.5 / 128.0 + 0.5);  
219      int x2 = int(w * 109.5 / 128.0 + 0.5);          const Gdk::Color bg = get_style()->get_bg(Gtk::STATE_NORMAL);
220      window->draw_rectangle(gc, true, 1, h1 + 1,          Gdk::Cairo::set_source_color(cr, bg);
221                             x1 - 1, h - 2);          cr->paint();
222      window->draw_rectangle(white, true, x1 + 1, h1 + 1, x2 - x1 - 1, h - 2);  
223      window->draw_rectangle(gc, true, x2 + 1, h1 + 1,          Gdk::Cairo::set_source_color(cr, black);
224                             w - x2 - 1, h - 2);          cr->rectangle(0.5, h1 + 0.5, w, h - 1);
225      int octave = -1;          cr->stroke();
226      for (int i = 0 ; i < 128 ; i++) {  
227          int note = (i + 3) % 12;          int x1 = int(w * 20.5 / 128.0 + 0.5);
228          int x = int(w * i / 128.0 + 0.5);          int x2 = int(w * 109.5 / 128.0 + 0.5);
229    
230          if (note == 1 || note == 4 || note == 6 || note == 9 || note == 11) {          Gdk::Cairo::set_source_color(cr, grey1);
231              int x2 = int(w * (i + 0.5) / 128.0 + 0.5);          cr->rectangle(1, h1 + 1, x1 - 1, h - 2);
232              window->draw_line(black, x2, h1 + bh, x2, h1 + h);          cr->fill();
233    
234              int x3 = int(w * (i + 1) / 128.0 + 0.5);          Gdk::Cairo::set_source_color(cr, white);
235              window->draw_rectangle(black, true, x, h1 + 1, x3 - x + 1, bh);          cr->rectangle(x1 + 1, h1 + 1, x2 - x1 - 1, h - 2);
236          } else if (note == 3 || note == 8) {          cr->fill();
237              window->draw_line(black, x, h1 + 1, x, h1 + h);  
238          }          Gdk::Cairo::set_source_color(cr, grey1);
239          if (note == 3) {          cr->rectangle(x2 + 1, h1 + 1, w - x2 - 1, h - 2);
240              char buf[30];          cr->fill();
241              sprintf(buf, "<span size=\"x-small\">%d</span>", octave);  
242              layout->set_markup(buf);          Gdk::Cairo::set_source_color(cr, black);
243              Pango::Rectangle rectangle = layout->get_logical_extents();          for (int i = 0 ; i < 128 ; i++) {
244              double text_w = double(rectangle.get_width()) / Pango::SCALE;              int note = (i + 3) % 12;
245              double text_h = double(rectangle.get_height()) / Pango::SCALE;              int x = int(w * i / 128.0 + 0.5);
246              double x2 = w * (i + 0.75) / 128.0;  
247              window->draw_layout(black, int(x2 - text_w / 2 + 1),              if (note == 1 || note == 4 || note == 6 ||
248                                  int(h1 + h - text_h + 0.5), layout);                  note == 9 || note == 11) {
249              octave++;                  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                    if (note == 3) draw_digit(i);
263                }
264            }
265    
266            if (instrument) {
267                int i = 0;
268                gig::Region* next_region;
269                int x3 = -1;
270                for (gig::Region* r = regions.first() ; r ; r = next_region) {
271    
272                    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 (instrument) {                      x3 = -1;
289          int i = 0;                  }
290          gig::Region *next_region;                  i++;
291          int x3 = -1;              }
         for (gig::Region *r = instrument->GetFirstRegion() ;  
              r ;  
              r = next_region) {  
292    
293              if (x3 < 0) x3 = int(w * (r->KeyRange.low) / 128.0 + 0.5);              for (gig::Region* r = regions.first() ; r ; r = regions.next()) {
294              next_region = instrument->GetNextRegion();                  int x = int(w * (r->KeyRange.low) / 128.0 + 0.5);
295              if (!next_region || r->KeyRange.high + 1 != next_region->KeyRange.low) {                  cr->move_to(x + 0.5, 1);
296                  int x2 = int(w * (r->KeyRange.high + 1) / 128.0 + 0.5);                  cr->line_to(x + 0.5, h1 - 1);
297                  window->draw_line(black, x3, 0, x2, 0);                  cr->stroke();
                 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;  
298              }              }
             i++;  
         }  
299    
300          for (gig::Region *r = instrument->GetFirstRegion() ;              if (region) {
301               r ;                  int x1 = int(w * (region->KeyRange.low) / 128.0 + 0.5);
302               r = instrument->GetNextRegion()) {                  int x2 = int(w * (region->KeyRange.high + 1) / 128.0 + 0.5);
303              int x = int(w * (r->KeyRange.low) / 128.0 + 0.5);                  Gdk::Cairo::set_source_color(cr, red);
304              window->draw_line(black, x, 1, x, h1 - 2);                  cr->rectangle(x1 + 1, 1, x2 - x1 - 1, h1 - 2);
305                    cr->fill();
306                }
307          }          }
308    
309          if (region) {          cr->restore();
             int x1 = int(w * (region->KeyRange.low) / 128.0 + 0.5);  
             int x2 = int(w * (region->KeyRange.high + 1) / 128.0 + 0.5);  
             gc->set_foreground(red);  
             window->draw_rectangle(gc, true, x1 + 1, 1, x2 - x1 - 1, h1 - 2);  
         }  
310      }      }
311    
312      return true;      return true;
313  }  }
314    
# Line 199  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;
# Line 262  bool RegionChooser::on_button_release_ev Line 433  bool RegionChooser::on_button_release_ev
433                      resize.region->KeyRange.low, // low                      resize.region->KeyRange.low, // low
434                      resize.pos - 1 // high                      resize.pos - 1 // high
435                  );                  );
436                    regions.update(instrument);
437                  instrument_changed.emit();                  instrument_changed.emit();
438                  instrument_struct_changed_signal.emit(instrument);                  instrument_struct_changed_signal.emit(instrument);
439              }              }
# Line 272  bool RegionChooser::on_button_release_ev Line 444  bool RegionChooser::on_button_release_ev
444                      resize.pos, // low                      resize.pos, // low
445                      resize.region->KeyRange.high // high                      resize.region->KeyRange.high // high
446                  );                  );
447                    regions.update(instrument);
448                  instrument_changed.emit();                  instrument_changed.emit();
449                  instrument_struct_changed_signal.emit(instrument);                  instrument_struct_changed_signal.emit(instrument);
450              }              }
# Line 291  bool RegionChooser::on_button_release_ev Line 464  bool RegionChooser::on_button_release_ev
464                  region->KeyRange.low  + move.pos,                  region->KeyRange.low  + move.pos,
465                  region->KeyRange.high + move.pos                  region->KeyRange.high + move.pos
466              );              );
467                regions.update(instrument);
468                instrument_changed.emit();
469              instrument_struct_changed_signal.emit(instrument);              instrument_struct_changed_signal.emit(instrument);
470          }          }
471    
# Line 306  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 333  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,                  get_window()->pointer_grab(false,
525                                             Gdk::BUTTON_RELEASE_MASK |                                             Gdk::BUTTON_RELEASE_MASK |
# Line 352  gig::Region* RegionChooser::get_region(i Line 539  gig::Region* RegionChooser::get_region(i
539  {  {
540      gig::Region* prev_region = 0;      gig::Region* prev_region = 0;
541      gig::Region* next_region;      gig::Region* next_region;
542      for (gig::Region *r = instrument->GetFirstRegion() ; r ;      for (gig::Region* r = regions.first() ; r ; r = next_region) {
543           r = next_region) {          next_region = regions.next();
         next_region = instrument->GetNextRegion();  
544    
545          if (key < r->KeyRange.low) return 0;          if (key < r->KeyRange.low) return 0;
546          if (key <= r->KeyRange.high) {          if (key <= r->KeyRange.high) {
# Line 369  gig::Region* RegionChooser::get_region(i Line 555  gig::Region* RegionChooser::get_region(i
555    
556  void RegionChooser::motion_resize_region(int x, int y)  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();  
559    
560      int k = int(double(x) / w * 128.0 + 0.5);      int k = int(double(x) / w * 128.0 + 0.5);
561    
# Line 378  void RegionChooser::motion_resize_region Line 563  void RegionChooser::motion_resize_region
563      else if (k > resize.max) k = resize.max;      else if (k > resize.max) k = resize.max;
564    
565      if (k != resize.pos) {      if (k != resize.pos) {
566            Cairo::RefPtr<Cairo::Context> cr = get_window()->create_cairo_context();
567            cr->set_line_width(1);
568    
569          if (resize.mode == resize.undecided) {          if (resize.mode == resize.undecided) {
570              if (k < resize.pos) {              if (k < resize.pos) {
571                  // edit high limit of prev_region                  // edit high limit of prev_region
# Line 390  void RegionChooser::motion_resize_region Line 578  void RegionChooser::motion_resize_region
578                  resize.mode = resize.moving_low_limit;                  resize.mode = resize.moving_low_limit;
579              }              }
580          }          }
581          Glib::RefPtr<const Gdk::GC> black = get_style()->get_black_gc();          const Gdk::Color white =
582          Glib::RefPtr<const Gdk::GC> white = get_style()->get_white_gc();              region == resize.region ? red : get_style()->get_white();
583          if (region == resize.region) {          const Gdk::Color bg = get_style()->get_bg(Gtk::STATE_NORMAL);
584              gc->set_foreground(red);  
             white = gc;  
         }  
         Glib::RefPtr<const Gdk::GC> bg = get_style()->get_bg_gc(Gtk::STATE_NORMAL);  
585          int prevx = int(w * resize.pos / 128.0 + 0.5);          int prevx = int(w * resize.pos / 128.0 + 0.5);
586          x = int(w * k / 128.0 + 0.5);          x = int(w * k / 128.0 + 0.5);
587    
588          if (resize.mode == resize.moving_high_limit) {          if (resize.mode == resize.moving_high_limit) {
589              if (k > resize.pos) {              if (k > resize.pos) {
590                  window->draw_rectangle(white, true, prevx, 1, x - prevx, h1 - 2);                  Gdk::Cairo::set_source_color(cr, white);
591                  window->draw_line(black, prevx, 0, x, 0);                  cr->rectangle(prevx, 1, x - prevx, h1 - 2);
592                  window->draw_line(black, prevx, h1 - 1, x, h1 - 1);                  cr->fill();
593    
594                    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 {              } else {
601                  int xx = ((resize.pos == resize.max && resize.max != 128) ? 1 : 0);                  int xx = (resize.pos == resize.max &&
602                  window->draw_rectangle(bg, true, x + 1, 0, prevx - x - xx, h1);                            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 {          } else {
608              if (k < resize.pos) {              if (k < resize.pos) {
609                  window->draw_rectangle(white, true, x + 1, 1, prevx - x, h1 - 2);                  Gdk::Cairo::set_source_color(cr, white);
610                  window->draw_line(black, x, 0, prevx, 0);                  cr->rectangle(x + 1, 1, prevx - x, h1 - 2);
611                  window->draw_line(black, x, h1 - 1, prevx, h1 - 1);                  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 {              } else {
620                  int xx = ((resize.pos == resize.min && resize.min != 0) ? 1 : 0);                  int xx = (resize.pos == resize.min &&
621                  window->draw_rectangle(bg, true, prevx + xx, 0, x - prevx - xx, h1);                            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          window->draw_line(black, x, 1, x, h1 - 2);          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;          resize.pos = k;
632      }      }
633  }  }
634    
635  void RegionChooser::motion_move_region(int x, int y)  void RegionChooser::motion_move_region(int x, int y)
636  {  {
637      const int w = width - 1;      const int w = get_width() - 1;
638      Glib::RefPtr<Gdk::Window> window = get_window();      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);      int k = int(double(x - move.from_x) / w * 128.0 + 0.5);
642      if (k == move.pos) return;      if (k == move.pos) return;
# Line 436  void RegionChooser::motion_move_region(i Line 645  void RegionChooser::motion_move_region(i
645      bool new_touch_right;      bool new_touch_right;
646      int a = 0;      int a = 0;
647      if (k > move.pos) {      if (k > move.pos) {
648          for (gig::Region* r = instrument->GetFirstRegion() ; ;          for (gig::Region* r = regions.first() ; ; r = regions.next()) {
              r = instrument->GetNextRegion()) {  
649              if (r != region) {              if (r != region) {
650                  int b = r ? r->KeyRange.low : 128;                  int b = r ? r->KeyRange.low : 128;
651    
# Line 467  void RegionChooser::motion_move_region(i Line 675  void RegionChooser::motion_move_region(i
675              }              }
676          }          }
677      } else {      } else {
678          for (gig::Region* r = instrument->GetFirstRegion() ; ;          for (gig::Region* r = regions.first() ; ; r = regions.next()) {
              r = instrument->GetNextRegion()) {  
679              if (r != region) {              if (r != region) {
680                  int b = r ? r->KeyRange.low : 128;                  int b = r ? r->KeyRange.low : 128;
681    
# Line 502  void RegionChooser::motion_move_region(i Line 709  void RegionChooser::motion_move_region(i
709      k = new_k;      k = new_k;
710      if (k == move.pos) return;      if (k == move.pos) return;
711    
712      Glib::RefPtr<const Gdk::GC> bg = get_style()->get_bg_gc(Gtk::STATE_NORMAL);      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);      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);      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);      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);      int x2 = int(w * (k + region->KeyRange.high + 1) / 128.0 + 0.5);
717      Glib::RefPtr<const Gdk::GC> black = get_style()->get_black_gc();      const Gdk::Color black = get_style()->get_black();
     gc->set_foreground(red);  
718    
719      if (!new_touch_left) window->draw_line(black, x, 1, x, h1 - 2);      if (!new_touch_left) {
720      if (!new_touch_right) window->draw_line(black, x2, 1, x2, h1 - 2);          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) {      if (k > move.pos) {
733          window->draw_rectangle(bg, true, prevx + (move.touch_left ? 1 : 0), 0,          Gdk::Cairo::set_source_color(cr, bg);
734                                 std::min(x, prevx2 + 1 - (move.touch_right ? 1 : 0)) -          cr->rectangle(prevx + (move.touch_left ? 1 : 0), 0,
735                                 (prevx + (move.touch_left ? 1 : 0)), h1);                        std::min(x, prevx2 + 1 - (move.touch_right ? 1 : 0)) -
736                          (prevx + (move.touch_left ? 1 : 0)), h1);
737          window->draw_line(black, std::max(x, prevx2 + 1), 0, x2, 0);          cr->fill();
738          window->draw_line(black, std::max(x, prevx2 + 1), h1 - 1, x2, h1 - 1);  
739          window->draw_rectangle(gc, true, std::max(x + 1, prevx2), 1,          Gdk::Cairo::set_source_color(cr, black);
740                                 x2 - std::max(x + 1, prevx2), h1 - 2);          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 {      } else {
751          window->draw_rectangle(bg, true, std::max(x2 + 1, prevx + (move.touch_left ? 1 : 0)), 0,          Gdk::Cairo::set_source_color(cr, bg);
752                                 prevx2 + 1 - (move.touch_right ? 1 : 0) -          cr->rectangle(std::max(x2 + 1, prevx + (move.touch_left ? 1 : 0)), 0,
753                                 std::max(x2 + 1, prevx + (move.touch_left ? 1 : 0)), h1);                        prevx2 + 1 - (move.touch_right ? 1 : 0) -
754                          std::max(x2 + 1, prevx + (move.touch_left ? 1 : 0)), h1);
755          window->draw_line(black, x, 0, std::min(x2, prevx - 1), 0);          cr->fill();
756          window->draw_line(black, x, h1 - 1, std::min(x2, prevx - 1), h1 - 1);  
757            Gdk::Cairo::set_source_color(cr, black);
758          window->draw_rectangle(gc, true, x + 1, 1, std::min(x2 - 1, prevx) - x, h1 - 2);          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;      move.pos = k;
# Line 546  bool RegionChooser::on_motion_notify_eve Line 779  bool RegionChooser::on_motion_notify_eve
779      Gdk::ModifierType state = Gdk::ModifierType(0);      Gdk::ModifierType state = Gdk::ModifierType(0);
780      window->get_pointer(x, y, state);      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) {      if (resize.active) {
802          motion_resize_region(x, y);          motion_resize_region(x, y);
803      } else if (move.active) {      } else if (move.active) {
# Line 566  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 588  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 606  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 628  sigc::signal<void>& RegionChooser::signa Line 880  sigc::signal<void>& RegionChooser::signa
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 658  void RegionChooser::add_region() Line 910  void RegionChooser::add_region()
910      region->SetKeyRange(new_region_pos, new_region_pos);      region->SetKeyRange(new_region_pos, new_region_pos);
911    
912      instrument_struct_changed_signal.emit(instrument);      instrument_struct_changed_signal.emit(instrument);
913        regions.update(instrument);
914    
915      queue_draw();      queue_draw();
916      region_selected();      region_selected();
917        dimensionManager.set_region(region);
918      instrument_changed();      instrument_changed();
919  }  }
920    
# Line 669  void RegionChooser::delete_region() Line 923  void RegionChooser::delete_region()
923      instrument_struct_to_be_changed_signal.emit(instrument);      instrument_struct_to_be_changed_signal.emit(instrument);
924      instrument->DeleteRegion(region);      instrument->DeleteRegion(region);
925      instrument_struct_changed_signal.emit(instrument);      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 703  sigc::signal<void, gig::Region*>& Region Line 959  sigc::signal<void, gig::Region*>& Region
959  sigc::signal<void, gig::Region*>& RegionChooser::signal_region_changed_signal() {  sigc::signal<void, gig::Region*>& RegionChooser::signal_region_changed_signal() {
960      return region_changed_signal;      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.1396  
changed lines
  Added in v.2151

  ViewVC Help
Powered by ViewVC