/[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 2169 by persson, Sun Mar 6 07:51:04 2011 UTC revision 2663 by schoenebeck, Wed Jul 2 23:53:21 2014 UTC
# Line 1  Line 1 
1  /*  /*
2   * Copyright (C) 2006-2011 Andreas Persson   * Copyright (C) 2006-2014 Andreas Persson
3   *   *
4   * This program is free software; you can redistribute it and/or   * This program is free software; you can redistribute it and/or
5   * modify it under the terms of the GNU General Public License as   * modify it under the terms of the GNU General Public License as
# Line 20  Line 20 
20  #include "regionchooser.h"  #include "regionchooser.h"
21    
22  #include <algorithm>  #include <algorithm>
 #include <sstream>  
23    
24  #include <cairomm/context.h>  #include <cairomm/context.h>
25  #include <gdkmm/general.h>  #include <gdkmm/general.h>
# Line 31  Line 30 
30    
31  #include "global.h"  #include "global.h"
32    
33  #define REGION_BLOCK_HEIGHT             20  #define REGION_BLOCK_HEIGHT             30
34  #define KEYBOARD_HEIGHT                 40  #define KEYBOARD_HEIGHT                 40
35    
36  void SortedRegions::update(gig::Instrument* instrument) {  void SortedRegions::update(gig::Instrument* instrument) {
37      // Usually, the regions in a gig file are ordered after their key      // Usually, the regions in a gig file are ordered after their key
# Line 81  RegionChooser::RegionChooser() : Line 80  RegionChooser::RegionChooser() :
80    
81      // properties of the virtual keyboard      // properties of the virtual keyboard
82      {      {
83          const char* choices[] = { _("normal"), _("chord"), NULL };          const char* choices[] = { _("normal"), _("chord"), 0 };
84          static const virt_keyboard_mode_t values[] = {          static const virt_keyboard_mode_t values[] = {
85              VIRT_KEYBOARD_MODE_NORMAL,              VIRT_KEYBOARD_MODE_NORMAL,
86              VIRT_KEYBOARD_MODE_CHORD              VIRT_KEYBOARD_MODE_CHORD
# Line 101  RegionChooser::RegionChooser() : Line 100  RegionChooser::RegionChooser() :
100      m_VirtKeybPropsBox.pack_start(m_VirtKeybOffVelocityLabel, Gtk::PACK_SHRINK);      m_VirtKeybPropsBox.pack_start(m_VirtKeybOffVelocityLabel, Gtk::PACK_SHRINK);
101      m_VirtKeybPropsBox.set_spacing(10);      m_VirtKeybPropsBox.set_spacing(10);
102      m_VirtKeybPropsBox.show();      m_VirtKeybPropsBox.show();
103        for (int i = 0 ; i < 128 ; i++) key_pressed[i] = false;
104    
105      actionGroup = Gtk::ActionGroup::create();      actionGroup = Gtk::ActionGroup::create();
106      actionGroup->add(Gtk::Action::create("Properties",      actionGroup->add(Gtk::Action::create("Properties",
# Line 154  RegionChooser::RegionChooser() : Line 154  RegionChooser::RegionChooser() :
154      keyboard_key_released_signal.connect(      keyboard_key_released_signal.connect(
155          sigc::mem_fun(*this, &RegionChooser::on_note_off_event)          sigc::mem_fun(*this, &RegionChooser::on_note_off_event)
156      );      );
157        set_tooltip_text(_("Right click here for adding new region. Use mouse pointer for moving (dragging) or resizing existing regions (by pointing at region's boundary). Right click on an existing region for more actions."));
158  }  }
159    
160  RegionChooser::~RegionChooser()  RegionChooser::~RegionChooser()
161  {  {
162  }  }
163    
164  template<class T> inline std::string ToString(T o) {  void RegionChooser::invalidate_key(int key) {
165      std::stringstream ss;      const int h = KEYBOARD_HEIGHT;
166      ss << o;      const int w = get_width() - 1;
167      return ss.str();      int x1 = key_to_x(key - 0.5, w);
168        int x2 = key_to_x(key + 1.5, w);
169    
170        Gdk::Rectangle rect(x1 + 1, h1 + 1, x2 - x1 - 1, h - 2);
171        get_window()->invalidate_rect(rect, false);
172  }  }
173    
174  void RegionChooser::on_note_on_event(int key, int velocity) {  void RegionChooser::on_note_on_event(int key, int velocity) {
175      draw_key(key, activeKeyColor);      key_pressed[key] = true;
176        invalidate_key(key);
177      m_VirtKeybVelocityLabel.set_text(ToString(velocity));      m_VirtKeybVelocityLabel.set_text(ToString(velocity));
178  }  }
179    
180  void RegionChooser::on_note_off_event(int key, int velocity) {  void RegionChooser::on_note_off_event(int key, int velocity) {
181      if (is_black_key(key)) {      key_pressed[key] = false;
182          draw_key(key, black);      invalidate_key(key);
     } else {  
         draw_key(key, key >= 21 && key <= 108 ? white : grey1);  
     }  
183      m_VirtKeybOffVelocityLabel.set_text(ToString(velocity));      m_VirtKeybOffVelocityLabel.set_text(ToString(velocity));
184  }  }
185    
186    
187  #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2  #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
188  bool RegionChooser::on_expose_event(GdkEventExpose* e)  bool RegionChooser::on_expose_event(GdkEventExpose* e) {
189  {      double clipx1 = e->area.x;
190      return on_draw(get_window()->create_cairo_context());      double clipx2 = e->area.x + e->area.width;
191        double clipy1 = e->area.y;
192        double clipy2 = e->area.y + e->area.height;
193    
194        const Cairo::RefPtr<Cairo::Context>& cr =
195            get_window()->create_cairo_context();
196    #if 0
197  }  }
198  #endif  #endif
199    #else
200  bool RegionChooser::on_draw(const Cairo::RefPtr<Cairo::Context>& cr)  bool RegionChooser::on_draw(const Cairo::RefPtr<Cairo::Context>& cr) {
201  {      double clipx1, clipx2, clipy1, clipy2;
202      const int h = KEYBOARD_HEIGHT;      cr->get_clip_extents(clipx1, clipy1, clipx2, clipy2);
203      const int w = get_width() - 1;  #endif
     const int bh = int(h * 0.55);  
204    
205      cr->save();      cr->save();
206      cr->set_line_width(1);      cr->set_line_width(1);
# Line 204  bool RegionChooser::on_draw(const Cairo: Line 213  bool RegionChooser::on_draw(const Cairo:
213      Gdk::Cairo::set_source_rgba(cr, bg);      Gdk::Cairo::set_source_rgba(cr, bg);
214      cr->paint();      cr->paint();
215    
216        if (clipy2 > h1) {
217            draw_keyboard(cr, clipx1, clipx2);
218        }
219    
220        if (clipy1 < h1 && instrument) {
221            draw_regions(cr, clipx1, clipx2);
222        }
223    
224        cr->restore();
225    
226        return true;
227    }
228    
229    void RegionChooser::draw_keyboard(const Cairo::RefPtr<Cairo::Context>& cr,
230                                      int clip_low, int clip_high) {
231        const int h = KEYBOARD_HEIGHT;
232        const int w = get_width() - 1;
233        const int bh = int(h * 0.55);
234    
235      Gdk::Cairo::set_source_rgba(cr, black);      Gdk::Cairo::set_source_rgba(cr, black);
236      cr->rectangle(0.5, h1 + 0.5, w, h - 1);      cr->rectangle(0.5, h1 + 0.5, w, h - 1);
237      cr->stroke();      cr->stroke();
238    
239      int x1 = int(w * 20.5 / 128.0 + 0.5);      int x1 = key_to_x(20.5, w);
     int x2 = int(w * 109.5 / 128.0 + 0.5);  
   
240      Gdk::Cairo::set_source_rgba(cr, grey1);      Gdk::Cairo::set_source_rgba(cr, grey1);
241      cr->rectangle(1, h1 + 1, x1 - 1, h - 2);      cr->rectangle(1, h1 + 1, x1 - 1, h - 2);
242      cr->fill();      cr->fill();
243    
244        int x2 = key_to_x(109.5, w);
245      Gdk::Cairo::set_source_rgba(cr, white);      Gdk::Cairo::set_source_rgba(cr, white);
246      cr->rectangle(x1 + 1, h1 + 1, x2 - x1 - 1, h - 2);      cr->rectangle(x1 + 1, h1 + 1, x2 - x1 - 1, h - 2);
247      cr->fill();      cr->fill();
# Line 224  bool RegionChooser::on_draw(const Cairo: Line 251  bool RegionChooser::on_draw(const Cairo:
251      cr->fill();      cr->fill();
252    
253      Gdk::Cairo::set_source_rgba(cr, black);      Gdk::Cairo::set_source_rgba(cr, black);
254      for (int i = 0 ; i < 128 ; i++) {  
255        int clipkey1 = std::max(0, x_to_key_right(clip_low - 1, w));
256        int clipkey2 = std::min(x_to_key_right(clip_high - 1, w) + 1, 128);
257    
258        for (int i = clipkey1 ; i < clipkey2 ; i++) {
259          int note = (i + 3) % 12;          int note = (i + 3) % 12;
260          int x = int(w * i / 128.0 + 0.5);          int x = key_to_x(i, w);
261    
262          if (note == 1 || note == 4 || note == 6 ||          if (note == 1 || note == 4 || note == 6 ||
263              note == 9 || note == 11) {              note == 9 || note == 11) {
264              int x2 = int(w * (i + 0.5) / 128.0 + 0.5);              // black key: short line in the middle, with a rectangle
265                // on top
266                int x2 = key_to_x(i + 0.5, w);
267              cr->move_to(x2 + 0.5, h1 + bh + 0.5);              cr->move_to(x2 + 0.5, h1 + bh + 0.5);
268              cr->line_to(x2 + 0.5, h1 + h - 1);              cr->line_to(x2 + 0.5, h1 + h - 1);
269              cr->stroke();              cr->stroke();
270    
271              int x3 = int(w * (i + 1) / 128.0 + 0.5);              int x3 = key_to_x(i + 1, w);
272              cr->rectangle(x, h1 + 1, x3 - x + 1, bh);              cr->rectangle(x, h1 + 1, x3 - x + 1, bh);
273              cr->fill();              cr->fill();
274          } else if (note == 3 || note == 8) {          } else if (note == 3 || note == 8) {
275                // C or F: long line to the left
276              cr->move_to(x + 0.5, h1 + 1);              cr->move_to(x + 0.5, h1 + 1);
277              cr->line_to(x + 0.5, h1 + h - 1);              cr->line_to(x + 0.5, h1 + h - 1);
278              cr->stroke();              cr->stroke();
   
             if (note == 3) draw_digit(i);  
279          }          }
280    
281            if (key_pressed[i]) draw_key(cr, i);
282    
283            if (note == 3) draw_digit(cr, i);
284      }      }
285    }
286    
     if (instrument) {  
         int i = 0;  
         gig::Region* next_region;  
         int x3 = -1;  
         for (gig::Region* r = regions.first() ; r ; r = next_region) {  
287    
288              if (x3 < 0) x3 = int(w * (r->KeyRange.low) / 128.0 + 0.5);  void RegionChooser::draw_regions(const Cairo::RefPtr<Cairo::Context>& cr,
289              next_region = regions.next();                                   int clip_low, int clip_high) {
290              if (!next_region ||      const int w = get_width() - 1;
291                  r->KeyRange.high + 1 != next_region->KeyRange.low) {  
292                  int x2 = int(w * (r->KeyRange.high + 1) / 128.0 + 0.5);      Gdk::Cairo::set_source_rgba(cr, black);
293        gig::Region* next_region;
294        int x3 = -1;
295        for (gig::Region* r = regions.first() ; r ; r = next_region) {
296            next_region = regions.next();
297    
298            if (x3 < 0) {
299                x3 = key_to_x(r->KeyRange.low, w);
300                if (x3 >= clip_high) break;
301            }
302            if (!next_region ||
303                r->KeyRange.high + 1 != next_region->KeyRange.low ||
304                r == region || next_region == region) {
305    
306                int x2 = key_to_x(r->KeyRange.high + 1, w);
307                if (x2 >= clip_low) {
308                  cr->move_to(x3, 0.5);                  cr->move_to(x3, 0.5);
309                  cr->line_to(x2 + 0.5, 0.5);                  cr->line_to(x2 + 0.5, 0.5);
310                  cr->line_to(x2 + 0.5, h1 - 0.5);                  cr->line_to(x2 + 0.5, h1 - 0.5);
311                  cr->line_to(x3, h1 - 0.5);                  cr->line_to(x3, h1 - 0.5);
312                  cr->stroke();                  cr->stroke();
313    
314                  Gdk::Cairo::set_source_rgba(cr, white);                  Gdk::Cairo::set_source_rgba(cr, region == r ? red : white);
315                  cr->rectangle(x3 + 1, 1, x2 - x3 - 1, h1 - 2);                  cr->rectangle(x3 + 1, 1, x2 - x3 - 1, h1 - 2);
316                  cr->fill();                  cr->fill();
317                  Gdk::Cairo::set_source_rgba(cr, black);                  Gdk::Cairo::set_source_rgba(cr, black);
   
                 x3 = -1;  
318              }              }
319              i++;              x3 = -1;
320          }          }
321        }
322    
323          for (gig::Region* r = regions.first() ; r ; r = regions.next()) {      for (gig::Region* r = regions.first() ; r ; r = regions.next()) {
324              int x = int(w * (r->KeyRange.low) / 128.0 + 0.5);          int x = key_to_x(r->KeyRange.low, w);
             cr->move_to(x + 0.5, 1);  
             cr->line_to(x + 0.5, h1 - 1);  
             cr->stroke();  
         }  
325    
326          if (region) {          if (x < clip_low) continue;
327              int x1 = int(w * (region->KeyRange.low) / 128.0 + 0.5);          if (x >= clip_high) break;
             int x2 = int(w * (region->KeyRange.high + 1) / 128.0 + 0.5);  
             Gdk::Cairo::set_source_rgba(cr, red);  
             cr->rectangle(x1 + 1, 1, x2 - x1 - 1, h1 - 2);  
             cr->fill();  
         }  
     }  
328    
329      cr->restore();          cr->move_to(x + 0.5, 1);
330            cr->line_to(x + 0.5, h1 - 1);
331            cr->stroke();
332        }
333    
334      return true;      // if there is no region yet, show the user some hint text that he may
335        // right click on this area to create a new region
336        if (!regions.first()) {
337            Glib::RefPtr<Pango::Context> context = get_pango_context();
338            Glib::RefPtr<Pango::Layout> layout = Pango::Layout::create(context);
339            layout->set_alignment(Pango::ALIGN_CENTER);
340            layout->set_text(Glib::ustring("*** ") + _("Right click here to create a region.") + " ***");
341            layout->set_width(get_width() * Pango::SCALE);
342            //layout->set_height(get_height() * Pango::SCALE);
343            layout->set_spacing(10);
344            Gdk::Cairo::set_source_rgba(cr, red);        
345            // get the text dimensions
346            Pango::Rectangle rect = layout->get_logical_extents();
347            int text_width, text_height;
348            layout->get_pixel_size(text_width, text_height);
349            cr->move_to(0, (REGION_BLOCK_HEIGHT - text_height) / 2);
350    #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 16) || GTKMM_MAJOR_VERSION < 2
351            pango_cairo_show_layout(cr->cobj(), layout->gobj());
352    #else
353            layout->show_in_cairo_context(cr);
354    #endif
355        }
356  }  }
357    
   
358  bool RegionChooser::is_black_key(int key) {  bool RegionChooser::is_black_key(int key) {
359      const int note = (key + 3) % 12;      const int note = (key + 3) % 12;
360      return note == 1 || note == 4 || note == 6 || note == 9 || note == 11;      return note == 1 || note == 4 || note == 6 || note == 9 || note == 11;
361  }  }
362    
363  void RegionChooser::draw_digit(int key) {  void RegionChooser::draw_digit(const Cairo::RefPtr<Cairo::Context>& cr,
364                                   int key) {
365      const int h = KEYBOARD_HEIGHT;      const int h = KEYBOARD_HEIGHT;
366      const int w = get_width() - 1;      const int w = get_width() - 1;
367      Glib::RefPtr<Pango::Layout> layout = Pango::Layout::create(get_pango_context());      Glib::RefPtr<Pango::Layout> layout =
368            Pango::Layout::create(get_pango_context());
369      char buf[30];      char buf[30];
370      sprintf(buf, "<span size=\"8000\">%d</span>", key / 12 - 1);      sprintf(buf, "<span size=\"8000\">%d</span>", key / 12 - 1);
371      layout->set_markup(buf);      layout->set_markup(buf);
# Line 312  void RegionChooser::draw_digit(int key) Line 373  void RegionChooser::draw_digit(int key)
373      double text_w = double(rectangle.get_width()) / Pango::SCALE;      double text_w = double(rectangle.get_width()) / Pango::SCALE;
374      double text_h = double(rectangle.get_height()) / Pango::SCALE;      double text_h = double(rectangle.get_height()) / Pango::SCALE;
375      double x = w * (key + 0.75) / 128.0;      double x = w * (key + 0.75) / 128.0;
     Cairo::RefPtr<Cairo::Context> cr = get_window()->create_cairo_context();  
376      Gdk::Cairo::set_source_rgba(cr, black);      Gdk::Cairo::set_source_rgba(cr, black);
377      cr->move_to(int(x - text_w / 2 + 1), int(h1 + h - text_h + 0.5));      cr->move_to(int(x - text_w / 2 + 1), int(h1 + h - text_h + 0.5));
378  #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 16) || GTKMM_MAJOR_VERSION < 2  #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 16) || GTKMM_MAJOR_VERSION < 2
# Line 322  void RegionChooser::draw_digit(int key) Line 382  void RegionChooser::draw_digit(int key)
382  #endif  #endif
383  }  }
384    
385  void RegionChooser::draw_key(int key, const Gdk::RGBA& color)  void RegionChooser::draw_key(const Cairo::RefPtr<Cairo::Context>& cr,
386  {                               int key) {
387      const int h = KEYBOARD_HEIGHT;      const int h = KEYBOARD_HEIGHT;
388      const int w = get_width() - 1;      const int w = get_width() - 1;
389      const int bh = int(h * 0.55);      const int bh = int(h * 0.55);
390    
391      Cairo::RefPtr<Cairo::Context> cr = get_window()->create_cairo_context();      Gdk::Cairo::set_source_rgba(cr, activeKeyColor);
     Gdk::Cairo::set_source_rgba(cr, color);  
392    
393      int note = (key + 3) % 12;      int note = (key + 3) % 12;
394      int x = int(w * key / 128.0 + 0.5) + 1;      int x = key_to_x(key, w) + 1;
395      int x2 = int(w * (key + 1.5) / 128.0 + 0.5);      int x2 = key_to_x(key + 1.5, w);
396      int x3 = int(w * (key + 1) / 128.0 + 0.5);      int x3 = key_to_x(key + 1, w);
397      int x4 = int(w * (key - 0.5) / 128.0 + 0.5);      int x4 = key_to_x(key - 0.5, w);
398      int w1 = x3 - x;      int w1 = x3 - x;
399      switch (note) {      switch (note) {
400      case 0: case 5: case 10:      case 0: case 5: case 10:
# Line 355  void RegionChooser::draw_key(int key, co Line 414  void RegionChooser::draw_key(int key, co
414          cr->fill();          cr->fill();
415          cr->rectangle(x, h1 + bh + 1, x2 - x, h - bh - 2);          cr->rectangle(x, h1 + bh + 1, x2 - x, h - bh - 2);
416          cr->fill();          cr->fill();
         if (note == 3) draw_digit(key);  
417          break;          break;
418      default:      default:
419          cr->rectangle(x, h1 + 1, w1, bh - 1);          cr->rectangle(x, h1 + 1, w1, bh - 1);
420          cr->fill();          cr->fill();
421          break;          break;
422      }      }
423        Gdk::Cairo::set_source_rgba(cr, black);
424  }  }
425    
426  void RegionChooser::set_instrument(gig::Instrument* instrument)  void RegionChooser::set_instrument(gig::Instrument* instrument)
# Line 376  void RegionChooser::set_instrument(gig:: Line 435  void RegionChooser::set_instrument(gig::
435    
436  bool RegionChooser::on_button_release_event(GdkEventButton* event)  bool RegionChooser::on_button_release_event(GdkEventButton* event)
437  {  {
438      const int k = int(event->x / (get_width() - 1) * 128.0);      const int k = x_to_key(event->x, get_width() - 1);
439    
440      // handle-note off on virtual keyboard      // handle-note off on virtual keyboard
441      if (event->type == GDK_BUTTON_RELEASE) {      if (event->type == GDK_BUTTON_RELEASE) {
# Line 406  bool RegionChooser::on_button_release_ev Line 465  bool RegionChooser::on_button_release_ev
465  #endif  #endif
466          resize.active = false;          resize.active = false;
467    
         if (resize.mode == resize.moving_high_limit) {  
             if (resize.region->KeyRange.high != resize.pos - 1) {  
                 instrument_struct_to_be_changed_signal.emit(instrument);  
                 resize.region->SetKeyRange(  
                     resize.region->KeyRange.low, // low  
                     resize.pos - 1 // high  
                 );  
                 regions.update(instrument);  
                 instrument_changed.emit();  
                 instrument_struct_changed_signal.emit(instrument);  
             }  
         } else if (resize.mode == resize.moving_low_limit) {  
             if (resize.region->KeyRange.low != resize.pos) {  
                 instrument_struct_to_be_changed_signal.emit(instrument);  
                 resize.region->SetKeyRange(  
                     resize.pos, // low  
                     resize.region->KeyRange.high // high  
                 );  
                 regions.update(instrument);  
                 instrument_changed.emit();  
                 instrument_struct_changed_signal.emit(instrument);  
             }  
         }  
   
468          if (!is_in_resize_zone(event->x, event->y) && cursor_is_resize) {          if (!is_in_resize_zone(event->x, event->y) && cursor_is_resize) {
469              get_window()->set_cursor();              get_window()->set_cursor();
470              cursor_is_resize = false;              cursor_is_resize = false;
# Line 442  bool RegionChooser::on_button_release_ev Line 477  bool RegionChooser::on_button_release_ev
477  #endif  #endif
478          move.active = false;          move.active = false;
479    
         if (move.pos) {  
             instrument_struct_to_be_changed_signal.emit(instrument);  
             region->SetKeyRange(  
                 region->KeyRange.low  + move.pos,  
                 region->KeyRange.high + move.pos  
             );  
             regions.update(instrument);  
             instrument_changed.emit();  
             instrument_struct_changed_signal.emit(instrument);  
         }  
   
480          if (is_in_resize_zone(event->x, event->y)) {          if (is_in_resize_zone(event->x, event->y)) {
481  #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2  #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
482              get_window()->set_cursor(Gdk::Cursor(Gdk::SB_H_DOUBLE_ARROW));              get_window()->set_cursor(Gdk::Cursor(Gdk::SB_H_DOUBLE_ARROW));
# Line 465  bool RegionChooser::on_button_release_ev Line 489  bool RegionChooser::on_button_release_ev
489      return true;      return true;
490  }  }
491    
492    void RegionChooser::update_after_resize()
493    {
494        if (resize.mode == resize.moving_high_limit) {
495            if (resize.region->KeyRange.high != resize.pos - 1) {
496                instrument_struct_to_be_changed_signal.emit(instrument);
497                resize.region->SetKeyRange(resize.region->KeyRange.low,
498                                           resize.pos - 1);
499                regions.update(instrument);
500                instrument_changed.emit();
501                instrument_struct_changed_signal.emit(instrument);
502            }
503        } else if (resize.mode == resize.moving_low_limit) {
504            if (resize.region->KeyRange.low != resize.pos) {
505                instrument_struct_to_be_changed_signal.emit(instrument);
506                resize.region->SetKeyRange(resize.pos,
507                                           resize.region->KeyRange.high);
508                regions.update(instrument);
509                instrument_changed.emit();
510                instrument_struct_changed_signal.emit(instrument);
511            }
512        }
513    }
514    
515    void RegionChooser::update_after_move(int pos)
516    {
517        instrument_struct_to_be_changed_signal.emit(instrument);
518        region->SetKeyRange(pos, pos + region->KeyRange.high -
519                            region->KeyRange.low);
520        regions.update(instrument);
521        instrument_changed.emit();
522        instrument_struct_changed_signal.emit(instrument);
523    }
524    
525  bool RegionChooser::on_button_press_event(GdkEventButton* event)  bool RegionChooser::on_button_press_event(GdkEventButton* event)
526  {  {
527      if (!instrument) return true;      if (!instrument) return true;
528    
529      const int k = int(event->x / (get_width() - 1) * 128.0);      const int w = get_width() - 1;
530        const int k = x_to_key(event->x, w);
531    
532      if (event->type == GDK_BUTTON_PRESS) {      if (event->type == GDK_BUTTON_PRESS) {
533          if (event->y >= REGION_BLOCK_HEIGHT) {          if (event->y >= REGION_BLOCK_HEIGHT) {
# Line 480  bool RegionChooser::on_button_press_even Line 538  bool RegionChooser::on_button_press_even
538          }          }
539      }      }
540    
541        // left mouse button double click
542        if (event->type == GDK_2BUTTON_PRESS && event->button == 1) {
543            if (event->y < REGION_BLOCK_HEIGHT) {
544                // show dimension manager dialog for this region
545                manage_dimensions();
546            }
547        }
548    
549      if (event->y >= REGION_BLOCK_HEIGHT) return true;      if (event->y >= REGION_BLOCK_HEIGHT) return true;
550      if (event->type == GDK_BUTTON_PRESS && event->button == 3) {      if (event->type == GDK_BUTTON_PRESS && event->button == 3) {
551          gig::Region* r = get_region(k);          gig::Region* r = get_region(k);
# Line 539  bool RegionChooser::on_button_press_even Line 605  bool RegionChooser::on_button_press_even
605                                                        event->time);                                                        event->time);
606  #endif  #endif
607                  move.active = true;                  move.active = true;
608                  move.from_x = event->x;                  move.offset = event->x - key_to_x(region->KeyRange.low, w);
                 move.pos = 0;  
609              }              }
610          }          }
611      }      }
# Line 549  bool RegionChooser::on_button_press_even Line 614  bool RegionChooser::on_button_press_even
614    
615  gig::Region* RegionChooser::get_region(int key)  gig::Region* RegionChooser::get_region(int key)
616  {  {
617      gig::Region* prev_region = 0;      for (gig::Region* r = regions.first() ; r ; r = regions.next()) {
     gig::Region* next_region;  
     for (gig::Region* r = regions.first() ; r ; r = next_region) {  
         next_region = regions.next();  
   
618          if (key < r->KeyRange.low) return 0;          if (key < r->KeyRange.low) return 0;
619          if (key <= r->KeyRange.high) {          if (key <= r->KeyRange.high) return r;
             move.touch_left = prev_region && prev_region->KeyRange.high + 1 == r->KeyRange.low;  
             move.touch_right = next_region && r->KeyRange.high + 1 == next_region->KeyRange.low;  
             return r;  
         }  
         prev_region = r;  
620      }      }
621      return 0;      return 0;
622  }  }
# Line 575  void RegionChooser::motion_resize_region Line 631  void RegionChooser::motion_resize_region
631      else if (k > resize.max) k = resize.max;      else if (k > resize.max) k = resize.max;
632    
633      if (k != resize.pos) {      if (k != resize.pos) {
         Cairo::RefPtr<Cairo::Context> cr = get_window()->create_cairo_context();  
         cr->set_line_width(1);  
   
634          if (resize.mode == resize.undecided) {          if (resize.mode == resize.undecided) {
635              if (k < resize.pos) {              if (k < resize.pos) {
636                  // edit high limit of prev_region                  // edit high limit of prev_region
# Line 590  void RegionChooser::motion_resize_region Line 643  void RegionChooser::motion_resize_region
643                  resize.mode = resize.moving_low_limit;                  resize.mode = resize.moving_low_limit;
644              }              }
645          }          }
646          const Gdk::RGBA white = region == resize.region ? red : this->white;          resize.pos = k;
 #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2  
         const Gdk::Color bg = get_style()->get_bg(Gtk::STATE_NORMAL);  
 #else  
         const Gdk::RGBA bg = get_style_context()->get_background_color();  
 #endif  
   
         int prevx = int(w * resize.pos / 128.0 + 0.5);  
         x = int(w * k / 128.0 + 0.5);  
647    
648            int x1, x2;
649          if (resize.mode == resize.moving_high_limit) {          if (resize.mode == resize.moving_high_limit) {
650              if (k > resize.pos) {              if (resize.region->KeyRange.high < resize.pos - 1) {
651                  Gdk::Cairo::set_source_rgba(cr, white);                  x1 = resize.region->KeyRange.high;
652                  cr->rectangle(prevx, 1, x - prevx, h1 - 2);                  x2 = resize.pos - 1;
                 cr->fill();  
   
                 Gdk::Cairo::set_source_rgba(cr, black);  
                 cr->move_to(prevx, 0.5);  
                 cr->line_to(x + 1, 0.5);  
                 cr->move_to(prevx, h1 - 0.5);  
                 cr->line_to(x + 1, h1 - 0.5);  
                 cr->stroke();  
653              } else {              } else {
654                  int xx = (resize.pos == resize.max &&                  x1 = resize.pos - 1;
655                            resize.max != 128) ? 1 : 0;                  x2 = resize.region->KeyRange.high;
                 Gdk::Cairo::set_source_rgba(cr, bg);  
                 cr->rectangle(x + 1, 0, prevx - x - xx, h1);  
                 cr->fill();  
656              }              }
657          } else {          } else {
658              if (k < resize.pos) {              if (resize.region->KeyRange.low < resize.pos) {
659                  Gdk::Cairo::set_source_rgba(cr, white);                  x1 = resize.region->KeyRange.low;
660                  cr->rectangle(x + 1, 1, prevx - x, h1 - 2);                  x2 = resize.pos;
                 cr->fill();  
   
                 Gdk::Cairo::set_source_rgba(cr, black);  
                 cr->move_to(x, 0.5);  
                 cr->line_to(prevx, 0.5);  
                 cr->move_to(x, h1 - 0.5);  
                 cr->line_to(prevx, h1 - 0.5);  
                 cr->stroke();  
661              } else {              } else {
662                  int xx = (resize.pos == resize.min &&                  x1 = resize.pos;
663                            resize.min != 0) ? 1 : 0;                  x2 = resize.region->KeyRange.low;
                 Gdk::Cairo::set_source_rgba(cr, bg);  
                 cr->rectangle(prevx + xx, 0, x - prevx - xx, h1);  
                 cr->fill();  
664              }              }
665          }          }
666          Gdk::Cairo::set_source_rgba(cr, black);          x1 = key_to_x(x1, w);
667          cr->move_to(x + 0.5, 1);          x2 = key_to_x(x2 + 1, w) + 1;
668          cr->line_to(x + 0.5, h1 - 1);          Gdk::Rectangle rect(x1, 0, x2 - x1, h1);
669          cr->stroke();  
670          resize.pos = k;          update_after_resize();
671    
672            get_window()->invalidate_rect(rect, false);
673      }      }
674  }  }
675    
676  void RegionChooser::motion_move_region(int x, int y)  void RegionChooser::motion_move_region(int x, int y)
677  {  {
678      const int w = get_width() - 1;      const int w = get_width() - 1;
     Cairo::RefPtr<Cairo::Context> cr = get_window()->create_cairo_context();  
     cr->set_line_width(1);  
679    
680      int k = int(double(x - move.from_x) / w * 128.0 + 0.5);      int l = int(double(x - move.offset) / w * 128.0 + 0.5);
681      if (k == move.pos) return;  
682      int new_k;      if (l == region->KeyRange.low) return;
683      bool new_touch_left;      int new_l;
684      bool new_touch_right;      int regionsize = region->KeyRange.high - region->KeyRange.low;
685      int a = 0;      int a = 0;
686      if (k > move.pos) {      if (l > region->KeyRange.low) {
687          for (gig::Region* r = regions.first() ; ; r = regions.next()) {          for (gig::Region* r = regions.first() ; ; r = regions.next()) {
688              if (r != region) {              if (r != region) {
689                  int b = r ? r->KeyRange.low : 128;                  int b = r ? r->KeyRange.low : 128;
690    
691                  // gap: from a to b (not inclusive b)                  // gap: from a to b (not inclusive b)
692    
693                  if (region->KeyRange.high + move.pos >= b) {                  if (region->KeyRange.high >= b) {
694                      // not found the current gap yet, just continue                      // not found the current gap yet, just continue
695                  } else {                  } else {
696    
697                      if (a > region->KeyRange.low + k) {                      if (a > l) {
698                          // this gap is too far to the right, break                          // this gap is too far to the right, break
699                          break;                          break;
700                      }                      }
701    
702                      int newhigh = std::min(region->KeyRange.high + k, b - 1);                      int newhigh = std::min(l + regionsize, b - 1);
703                      int newlo = newhigh - (region->KeyRange.high - region->KeyRange.low);                      int newlo = newhigh - regionsize;
704    
705                      if (newlo >= a) {                      if (newlo >= a) {
706                          // yes it fits - it's a candidate                          // yes it fits - it's a candidate
707                          new_k = newlo - region->KeyRange.low;                          new_l = newlo;
                         new_touch_left = a > 0 && a == newlo;  
                         new_touch_right = b < 128 && newhigh + 1 == b;  
708                      }                      }
709                  }                  }
710                  if (!r) break;                  if (!r) break;
# Line 696  void RegionChooser::motion_move_region(i Line 718  void RegionChooser::motion_move_region(i
718    
719                  // gap from a to b (not inclusive b)                  // gap from a to b (not inclusive b)
720    
721                  if (region->KeyRange.high + k >= b) {                  if (l + regionsize >= b) {
722                      // not found the current gap yet, just continue                      // not found the current gap yet, just continue
723                  } else {                  } else {
724    
725                      if (a > region->KeyRange.low + move.pos) {                      if (a > region->KeyRange.low) {
726                          // this gap is too far to the right, break                          // this gap is too far to the right, break
727                          break;                          break;
728                      }                      }
729    
730                      int newlo = std::max(region->KeyRange.low + k, a);                      int newlo = std::max(l, a);
731                      int newhigh = newlo + (region->KeyRange.high - region->KeyRange.low);                      int newhigh = newlo + regionsize;
732    
733                      if (newhigh < b) {                      if (newhigh < b) {
734                          // yes it fits - break as the first one is the best                          // yes it fits - break as the first one is the best
735                          new_k = newlo - region->KeyRange.low;                          new_l = newlo;
                         new_touch_left = a > 0 && a == newlo;  
                         new_touch_right = b < 128 && newhigh + 1 == b;  
736                          break;                          break;
737                      }                      }
738                  }                  }
# Line 721  void RegionChooser::motion_move_region(i Line 741  void RegionChooser::motion_move_region(i
741              }              }
742          }          }
743      }      }
744      k = new_k;      if (new_l == region->KeyRange.low) return;
     if (k == move.pos) return;  
   
 #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2  
     const Gdk::Color bg = get_style()->get_bg(Gtk::STATE_NORMAL);  
 #else  
     const Gdk::RGBA bg = get_style_context()->get_background_color();  
 #endif  
   
     int prevx = int(w * (move.pos + region->KeyRange.low) / 128.0 + 0.5);  
     x = int(w * (k + region->KeyRange.low) / 128.0 + 0.5);  
     int prevx2 = int(w * (move.pos + region->KeyRange.high + 1) / 128.0 + 0.5);  
     int x2 = int(w * (k + region->KeyRange.high + 1) / 128.0 + 0.5);  
   
     if (!new_touch_left) {  
         Gdk::Cairo::set_source_rgba(cr, black);  
         cr->move_to(x + 0.5, 1);  
         cr->line_to(x + 0.5, h1 - 1);  
         cr->stroke();  
     }  
     if (!new_touch_right) {  
         Gdk::Cairo::set_source_rgba(cr, black);  
         cr->move_to(x2 + 0.5, 1);  
         cr->line_to(x2 + 0.5, h1 - 1);  
         cr->stroke();  
     }  
745    
746      if (k > move.pos) {      int x1 = key_to_x(std::min(int(region->KeyRange.low), new_l), w);
747          Gdk::Cairo::set_source_rgba(cr, bg);      int x2 = key_to_x(std::max(int(region->KeyRange.high),
748          cr->rectangle(prevx + (move.touch_left ? 1 : 0), 0,                                 new_l + regionsize) + 1, w) + 1;
                       std::min(x, prevx2 + 1 - (move.touch_right ? 1 : 0)) -  
                       (prevx + (move.touch_left ? 1 : 0)), h1);  
         cr->fill();  
749    
750          Gdk::Cairo::set_source_rgba(cr, black);      Gdk::Rectangle rect(x1, 0, x2 - x1, h1);
751          cr->move_to(std::max(x, prevx2 + 1), 0.5);      update_after_move(new_l);
         cr->line_to(x2 + 1, 0.5);  
         cr->move_to(std::max(x, prevx2 + 1), h1 - 0.5);  
         cr->line_to(x2 + 1, h1 - 0.5);  
         cr->stroke();  
   
         Gdk::Cairo::set_source_rgba(cr, red);  
         cr->rectangle(std::max(x + 1, prevx2), 1,  
                       x2 - std::max(x + 1, prevx2), h1 - 2);  
         cr->fill();  
     } else {  
         Gdk::Cairo::set_source_rgba(cr, bg);  
         cr->rectangle(std::max(x2 + 1, prevx + (move.touch_left ? 1 : 0)), 0,  
                       prevx2 + 1 - (move.touch_right ? 1 : 0) -  
                       std::max(x2 + 1, prevx + (move.touch_left ? 1 : 0)), h1);  
         cr->fill();  
   
         Gdk::Cairo::set_source_rgba(cr, black);  
         cr->move_to(x, 0.5);  
         cr->line_to(std::min(x2, prevx - 1) + 1, 0.5);  
         cr->move_to(x, h1 - 0.5);  
         cr->line_to(std::min(x2, prevx - 1) + 1, h1 - 0.5);  
         cr->stroke();  
   
         Gdk::Cairo::set_source_rgba(cr, red);  
         cr->rectangle(x + 1, 1, std::min(x2 - 1, prevx) - x, h1 - 2);  
         cr->fill();  
     }  
752    
753      move.pos = k;      get_window()->invalidate_rect(rect, false);
     move.touch_left = new_touch_left;  
     move.touch_right = new_touch_right;  
754  }  }
755    
756    
# Line 804  bool RegionChooser::on_motion_notify_eve Line 767  bool RegionChooser::on_motion_notify_eve
767          event->y >= REGION_BLOCK_HEIGHT &&          event->y >= REGION_BLOCK_HEIGHT &&
768          event->y < REGION_BLOCK_HEIGHT + KEYBOARD_HEIGHT)          event->y < REGION_BLOCK_HEIGHT + KEYBOARD_HEIGHT)
769      {      {
770          const int k = int(event->x / (get_width() - 1) * 128.0);          const int k = x_to_key(event->x, get_width() - 1);
771          if (k != currentActiveKey) {          if (k != currentActiveKey) {
772              int velocity =              int velocity =
773                  (event->y >= REGION_BLOCK_HEIGHT + KEYBOARD_HEIGHT - 1) ? 127 :                  (event->y >= REGION_BLOCK_HEIGHT + KEYBOARD_HEIGHT - 1) ? 127 :
# Line 849  bool RegionChooser::is_in_resize_zone(do Line 812  bool RegionChooser::is_in_resize_zone(do
812          for (gig::Region* r = regions.first(); r ; r = next_region) {          for (gig::Region* r = regions.first(); r ; r = next_region) {
813              next_region = regions.next();              next_region = regions.next();
814    
815              int lo = int(w * (r->KeyRange.low) / 128.0 + 0.5);              int lo = key_to_x(r->KeyRange.low, w);
816              if (x <= lo - 2) break;              if (x <= lo - 2) break;
817              if (x < lo + 2) {              if (x < lo + 2) {
818                  resize.region = r;                  resize.region = r;
# Line 872  bool RegionChooser::is_in_resize_zone(do Line 835  bool RegionChooser::is_in_resize_zone(do
835                  return resize.min != resize.max;                  return resize.min != resize.max;
836              }              }
837              if (!next_region || r->KeyRange.high + 1 != next_region->KeyRange.low) {              if (!next_region || r->KeyRange.high + 1 != next_region->KeyRange.low) {
838                  int hi = int(w * (r->KeyRange.high + 1) / 128.0 + 0.5);                  int hi = key_to_x(r->KeyRange.high + 1, w);
839                  if (x <= hi - 2) break;                  if (x <= hi - 2) break;
840                  if (x < hi + 2) {                  if (x < hi + 2) {
841                      // edit high limit                      // edit high limit

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

  ViewVC Help
Powered by ViewVC