/[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 2841 by persson, Sun Aug 30 10:00:49 2015 UTC
# Line 1  Line 1 
1  /*  /*
2   * Copyright (C) 2006-2011 Andreas Persson   * Copyright (C) 2006-2015 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 30  Line 29 
29  #include <gtkmm/dialog.h>  #include <gtkmm/dialog.h>
30    
31  #include "global.h"  #include "global.h"
32    #include "Settings.h"
33    
34  #define REGION_BLOCK_HEIGHT             20  #define REGION_BLOCK_HEIGHT             30
35  #define KEYBOARD_HEIGHT                 40  #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
# Line 55  gig::Region* SortedRegions::first() { Line 55  gig::Region* SortedRegions::first() {
55  }  }
56    
57  gig::Region* SortedRegions::next() {  gig::Region* SortedRegions::next() {
58      region_iterator++;      ++region_iterator;
59      return region_iterator == regions.end() ? 0 : *region_iterator;      return region_iterator == regions.end() ? 0 : *region_iterator;
60  }  }
61    
# Line 81  RegionChooser::RegionChooser() : Line 81  RegionChooser::RegionChooser() :
81    
82      // properties of the virtual keyboard      // properties of the virtual keyboard
83      {      {
84          const char* choices[] = { _("normal"), _("chord"), NULL };          const char* choices[] = { _("normal"), _("chord"), 0 };
85          static const virt_keyboard_mode_t values[] = {          static const virt_keyboard_mode_t values[] = {
86              VIRT_KEYBOARD_MODE_NORMAL,              VIRT_KEYBOARD_MODE_NORMAL,
87              VIRT_KEYBOARD_MODE_CHORD              VIRT_KEYBOARD_MODE_CHORD
# Line 101  RegionChooser::RegionChooser() : Line 101  RegionChooser::RegionChooser() :
101      m_VirtKeybPropsBox.pack_start(m_VirtKeybOffVelocityLabel, Gtk::PACK_SHRINK);      m_VirtKeybPropsBox.pack_start(m_VirtKeybOffVelocityLabel, Gtk::PACK_SHRINK);
102      m_VirtKeybPropsBox.set_spacing(10);      m_VirtKeybPropsBox.set_spacing(10);
103      m_VirtKeybPropsBox.show();      m_VirtKeybPropsBox.show();
104        for (int i = 0 ; i < 128 ; i++) key_pressed[i] = false;
105    
106      actionGroup = Gtk::ActionGroup::create();      actionGroup = Gtk::ActionGroup::create();
107      actionGroup->add(Gtk::Action::create("Properties",      actionGroup->add(Gtk::Action::create("Properties",
# Line 154  RegionChooser::RegionChooser() : Line 155  RegionChooser::RegionChooser() :
155      keyboard_key_released_signal.connect(      keyboard_key_released_signal.connect(
156          sigc::mem_fun(*this, &RegionChooser::on_note_off_event)          sigc::mem_fun(*this, &RegionChooser::on_note_off_event)
157      );      );
158        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."));
159  }  }
160    
161  RegionChooser::~RegionChooser()  RegionChooser::~RegionChooser()
162  {  {
163  }  }
164    
165  template<class T> inline std::string ToString(T o) {  void RegionChooser::invalidate_key(int key) {
166      std::stringstream ss;      const int h = KEYBOARD_HEIGHT;
167      ss << o;      const int w = get_width() - 1;
168      return ss.str();      int x1 = key_to_x(key - 0.5, w);
169        int x2 = key_to_x(key + 1.5, w);
170    
171        Gdk::Rectangle rect(x1 + 1, h1 + 1, x2 - x1 - 1, h - 2);
172        get_window()->invalidate_rect(rect, false);
173  }  }
174    
175  void RegionChooser::on_note_on_event(int key, int velocity) {  void RegionChooser::on_note_on_event(int key, int velocity) {
176      draw_key(key, activeKeyColor);      key_pressed[key] = true;
177        invalidate_key(key);
178      m_VirtKeybVelocityLabel.set_text(ToString(velocity));      m_VirtKeybVelocityLabel.set_text(ToString(velocity));
179  }  }
180    
181  void RegionChooser::on_note_off_event(int key, int velocity) {  void RegionChooser::on_note_off_event(int key, int velocity) {
182      if (is_black_key(key)) {      key_pressed[key] = false;
183          draw_key(key, black);      invalidate_key(key);
     } else {  
         draw_key(key, key >= 21 && key <= 108 ? white : grey1);  
     }  
184      m_VirtKeybOffVelocityLabel.set_text(ToString(velocity));      m_VirtKeybOffVelocityLabel.set_text(ToString(velocity));
185  }  }
186    
187    
188  #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
189  bool RegionChooser::on_expose_event(GdkEventExpose* e)  bool RegionChooser::on_expose_event(GdkEventExpose* e) {
190  {      double clipx1 = e->area.x;
191      return on_draw(get_window()->create_cairo_context());      double clipx2 = e->area.x + e->area.width;
192        double clipy1 = e->area.y;
193        double clipy2 = e->area.y + e->area.height;
194    
195        const Cairo::RefPtr<Cairo::Context>& cr =
196            get_window()->create_cairo_context();
197    #if 0
198  }  }
199  #endif  #endif
200    #else
201  bool RegionChooser::on_draw(const Cairo::RefPtr<Cairo::Context>& cr)  bool RegionChooser::on_draw(const Cairo::RefPtr<Cairo::Context>& cr) {
202  {      double clipx1, clipx2, clipy1, clipy2;
203      const int h = KEYBOARD_HEIGHT;      cr->get_clip_extents(clipx1, clipy1, clipx2, clipy2);
204      const int w = get_width() - 1;  #endif
     const int bh = int(h * 0.55);  
205    
206      cr->save();      cr->save();
207      cr->set_line_width(1);      cr->set_line_width(1);
# Line 204  bool RegionChooser::on_draw(const Cairo: Line 214  bool RegionChooser::on_draw(const Cairo:
214      Gdk::Cairo::set_source_rgba(cr, bg);      Gdk::Cairo::set_source_rgba(cr, bg);
215      cr->paint();      cr->paint();
216    
217        if (clipy2 > h1) {
218            draw_keyboard(cr, clipx1, clipx2);
219        }
220    
221        if (clipy1 < h1 && instrument) {
222            draw_regions(cr, clipx1, clipx2);
223        }
224    
225        cr->restore();
226    
227        return true;
228    }
229    
230    void RegionChooser::draw_keyboard(const Cairo::RefPtr<Cairo::Context>& cr,
231                                      int clip_low, int clip_high) {
232        const int h = KEYBOARD_HEIGHT;
233        const int w = get_width() - 1;
234        const int bh = int(h * 0.55);
235    
236      Gdk::Cairo::set_source_rgba(cr, black);      Gdk::Cairo::set_source_rgba(cr, black);
237      cr->rectangle(0.5, h1 + 0.5, w, h - 1);      cr->rectangle(0.5, h1 + 0.5, w, h - 1);
238      cr->stroke();      cr->stroke();
239    
240      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);  
   
241      Gdk::Cairo::set_source_rgba(cr, grey1);      Gdk::Cairo::set_source_rgba(cr, grey1);
242      cr->rectangle(1, h1 + 1, x1 - 1, h - 2);      cr->rectangle(1, h1 + 1, x1 - 1, h - 2);
243      cr->fill();      cr->fill();
244    
245        int x2 = key_to_x(109.5, w);
246      Gdk::Cairo::set_source_rgba(cr, white);      Gdk::Cairo::set_source_rgba(cr, white);
247      cr->rectangle(x1 + 1, h1 + 1, x2 - x1 - 1, h - 2);      cr->rectangle(x1 + 1, h1 + 1, x2 - x1 - 1, h - 2);
248      cr->fill();      cr->fill();
# Line 224  bool RegionChooser::on_draw(const Cairo: Line 252  bool RegionChooser::on_draw(const Cairo:
252      cr->fill();      cr->fill();
253    
254      Gdk::Cairo::set_source_rgba(cr, black);      Gdk::Cairo::set_source_rgba(cr, black);
255      for (int i = 0 ; i < 128 ; i++) {  
256        int clipkey1 = std::max(0, x_to_key_right(clip_low - 1, w));
257        int clipkey2 = std::min(x_to_key_right(clip_high - 1, w) + 1, 128);
258    
259        for (int i = clipkey1 ; i < clipkey2 ; i++) {
260          int note = (i + 3) % 12;          int note = (i + 3) % 12;
261          int x = int(w * i / 128.0 + 0.5);          int x = key_to_x(i, w);
262    
263          if (note == 1 || note == 4 || note == 6 ||          if (note == 1 || note == 4 || note == 6 ||
264              note == 9 || note == 11) {              note == 9 || note == 11) {
265              int x2 = int(w * (i + 0.5) / 128.0 + 0.5);              // black key: short line in the middle, with a rectangle
266                // on top
267                int x2 = key_to_x(i + 0.5, w);
268              cr->move_to(x2 + 0.5, h1 + bh + 0.5);              cr->move_to(x2 + 0.5, h1 + bh + 0.5);
269              cr->line_to(x2 + 0.5, h1 + h - 1);              cr->line_to(x2 + 0.5, h1 + h - 1);
270              cr->stroke();              cr->stroke();
271    
272              int x3 = int(w * (i + 1) / 128.0 + 0.5);              int x3 = key_to_x(i + 1, w);
273              cr->rectangle(x, h1 + 1, x3 - x + 1, bh);              cr->rectangle(x, h1 + 1, x3 - x + 1, bh);
274              cr->fill();              cr->fill();
275          } else if (note == 3 || note == 8) {          } else if (note == 3 || note == 8) {
276                // C or F: long line to the left
277              cr->move_to(x + 0.5, h1 + 1);              cr->move_to(x + 0.5, h1 + 1);
278              cr->line_to(x + 0.5, h1 + h - 1);              cr->line_to(x + 0.5, h1 + h - 1);
279              cr->stroke();              cr->stroke();
   
             if (note == 3) draw_digit(i);  
280          }          }
281    
282            if (key_pressed[i]) draw_key(cr, i);
283    
284            if (note == 3) draw_digit(cr, i);
285      }      }
286    }
287    
     if (instrument) {  
         int i = 0;  
         gig::Region* next_region;  
         int x3 = -1;  
         for (gig::Region* r = regions.first() ; r ; r = next_region) {  
288    
289              if (x3 < 0) x3 = int(w * (r->KeyRange.low) / 128.0 + 0.5);  void RegionChooser::draw_regions(const Cairo::RefPtr<Cairo::Context>& cr,
290              next_region = regions.next();                                   int clip_low, int clip_high) {
291              if (!next_region ||      const int w = get_width() - 1;
292                  r->KeyRange.high + 1 != next_region->KeyRange.low) {  
293                  int x2 = int(w * (r->KeyRange.high + 1) / 128.0 + 0.5);      Gdk::Cairo::set_source_rgba(cr, black);
294        gig::Region* next_region;
295        int x3 = -1;
296        for (gig::Region* r = regions.first() ; r ; r = next_region) {
297            next_region = regions.next();
298    
299            if (x3 < 0) {
300                x3 = key_to_x(r->KeyRange.low, w);
301                if (x3 >= clip_high) break;
302            }
303            if (!next_region ||
304                r->KeyRange.high + 1 != next_region->KeyRange.low ||
305                r == region || next_region == region) {
306    
307                int x2 = key_to_x(r->KeyRange.high + 1, w);
308                if (x2 >= clip_low) {
309                  cr->move_to(x3, 0.5);                  cr->move_to(x3, 0.5);
310                  cr->line_to(x2 + 0.5, 0.5);                  cr->line_to(x2 + 0.5, 0.5);
311                  cr->line_to(x2 + 0.5, h1 - 0.5);                  cr->line_to(x2 + 0.5, h1 - 0.5);
312                  cr->line_to(x3, h1 - 0.5);                  cr->line_to(x3, h1 - 0.5);
313                  cr->stroke();                  cr->stroke();
314    
315                  Gdk::Cairo::set_source_rgba(cr, white);                  Gdk::Cairo::set_source_rgba(cr, region == r ? red : white);
316                  cr->rectangle(x3 + 1, 1, x2 - x3 - 1, h1 - 2);                  cr->rectangle(x3 + 1, 1, x2 - x3 - 1, h1 - 2);
317                  cr->fill();                  cr->fill();
318                  Gdk::Cairo::set_source_rgba(cr, black);                  Gdk::Cairo::set_source_rgba(cr, black);
   
                 x3 = -1;  
319              }              }
320              i++;              x3 = -1;
321          }          }
322        }
323    
324          for (gig::Region* r = regions.first() ; r ; r = regions.next()) {      for (gig::Region* r = regions.first() ; r ; r = regions.next()) {
325              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();  
         }  
326    
327          if (region) {          if (x < clip_low) continue;
328              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();  
         }  
     }  
329    
330      cr->restore();          cr->move_to(x + 0.5, 1);
331            cr->line_to(x + 0.5, h1 - 1);
332            cr->stroke();
333        }
334    
335      return true;      // if there is no region yet, show the user some hint text that he may
336        // right click on this area to create a new region
337        if (!regions.first()) {
338            Glib::RefPtr<Pango::Context> context = get_pango_context();
339            Glib::RefPtr<Pango::Layout> layout = Pango::Layout::create(context);
340            layout->set_alignment(Pango::ALIGN_CENTER);
341            layout->set_text(Glib::ustring("*** ") + _("Right click here to create a region.") + " ***");
342            layout->set_width(get_width() * Pango::SCALE);
343            //layout->set_height(get_height() * Pango::SCALE);
344            layout->set_spacing(10);
345            Gdk::Cairo::set_source_rgba(cr, red);        
346            // get the text dimensions
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        const int range = region->KeyRange.high - region->KeyRange.low;
519        const int diff  = pos - int(region->KeyRange.low);
520        region->SetKeyRange(pos, pos + range);
521        if (Settings::singleton()->moveRootNoteWithRegionMoved) {
522            for (int i = 0; i < 256; ++i) {
523                gig::DimensionRegion* dimrgn = region->pDimensionRegions[i];
524                if (!dimrgn || !dimrgn->pSample || !dimrgn->PitchTrack) continue;
525                dimrgn->UnityNote += diff;
526            }
527        }
528        regions.update(instrument);
529        instrument_changed.emit();
530        instrument_struct_changed_signal.emit(instrument);
531    }
532    
533  bool RegionChooser::on_button_press_event(GdkEventButton* event)  bool RegionChooser::on_button_press_event(GdkEventButton* event)
534  {  {
535      if (!instrument) return true;      if (!instrument) return true;
536    
537      const int k = int(event->x / (get_width() - 1) * 128.0);      const int w = get_width() - 1;
538        const int k = x_to_key(event->x, w);
539    
540      if (event->type == GDK_BUTTON_PRESS) {      if (event->type == GDK_BUTTON_PRESS) {
541          if (event->y >= REGION_BLOCK_HEIGHT) {          if (event->y >= REGION_BLOCK_HEIGHT) {
# Line 480  bool RegionChooser::on_button_press_even Line 546  bool RegionChooser::on_button_press_even
546          }          }
547      }      }
548    
549        // left mouse button double click
550        if (event->type == GDK_2BUTTON_PRESS && event->button == 1) {
551            if (event->y < REGION_BLOCK_HEIGHT) {
552                // show dimension manager dialog for this region
553                manage_dimensions();
554            }
555        }
556    
557      if (event->y >= REGION_BLOCK_HEIGHT) return true;      if (event->y >= REGION_BLOCK_HEIGHT) return true;
558      if (event->type == GDK_BUTTON_PRESS && event->button == 3) {      if (event->type == GDK_BUTTON_PRESS && event->button == 3) {
559          gig::Region* r = get_region(k);          gig::Region* r = get_region(k);
# Line 539  bool RegionChooser::on_button_press_even Line 613  bool RegionChooser::on_button_press_even
613                                                        event->time);                                                        event->time);
614  #endif  #endif
615                  move.active = true;                  move.active = true;
616                  move.from_x = event->x;                  move.offset = event->x - key_to_x(region->KeyRange.low, w);
                 move.pos = 0;  
617              }              }
618          }          }
619      }      }
# Line 549  bool RegionChooser::on_button_press_even Line 622  bool RegionChooser::on_button_press_even
622    
623  gig::Region* RegionChooser::get_region(int key)  gig::Region* RegionChooser::get_region(int key)
624  {  {
625      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();  
   
626          if (key < r->KeyRange.low) return 0;          if (key < r->KeyRange.low) return 0;
627          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;  
628      }      }
629      return 0;      return 0;
630  }  }
631    
632    void RegionChooser::set_region(gig::Region* region) {
633        this->region = region;
634        queue_draw();
635        region_selected();
636        dimensionManager.set_region(region);
637    }
638    
639  void RegionChooser::motion_resize_region(int x, int y)  void RegionChooser::motion_resize_region(int x, int y)
640  {  {
641      const int w = get_width() - 1;      const int w = get_width() - 1;
# Line 575  void RegionChooser::motion_resize_region Line 646  void RegionChooser::motion_resize_region
646      else if (k > resize.max) k = resize.max;      else if (k > resize.max) k = resize.max;
647    
648      if (k != resize.pos) {      if (k != resize.pos) {
         Cairo::RefPtr<Cairo::Context> cr = get_window()->create_cairo_context();  
         cr->set_line_width(1);  
   
649          if (resize.mode == resize.undecided) {          if (resize.mode == resize.undecided) {
650              if (k < resize.pos) {              if (k < resize.pos) {
651                  // edit high limit of prev_region                  // edit high limit of prev_region
# Line 590  void RegionChooser::motion_resize_region Line 658  void RegionChooser::motion_resize_region
658                  resize.mode = resize.moving_low_limit;                  resize.mode = resize.moving_low_limit;
659              }              }
660          }          }
661          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);  
662    
663            int x1, x2;
664          if (resize.mode == resize.moving_high_limit) {          if (resize.mode == resize.moving_high_limit) {
665              if (k > resize.pos) {              if (resize.region->KeyRange.high < resize.pos - 1) {
666                  Gdk::Cairo::set_source_rgba(cr, white);                  x1 = resize.region->KeyRange.high;
667                  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();  
668              } else {              } else {
669                  int xx = (resize.pos == resize.max &&                  x1 = resize.pos - 1;
670                            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();  
671              }              }
672          } else {          } else {
673              if (k < resize.pos) {              if (resize.region->KeyRange.low < resize.pos) {
674                  Gdk::Cairo::set_source_rgba(cr, white);                  x1 = resize.region->KeyRange.low;
675                  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();  
676              } else {              } else {
677                  int xx = (resize.pos == resize.min &&                  x1 = resize.pos;
678                            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();  
679              }              }
680          }          }
681          Gdk::Cairo::set_source_rgba(cr, black);          x1 = key_to_x(x1, w);
682          cr->move_to(x + 0.5, 1);          x2 = key_to_x(x2 + 1, w) + 1;
683          cr->line_to(x + 0.5, h1 - 1);          Gdk::Rectangle rect(x1, 0, x2 - x1, h1);
684          cr->stroke();  
685          resize.pos = k;          update_after_resize();
686    
687            get_window()->invalidate_rect(rect, false);
688      }      }
689  }  }
690    
691  void RegionChooser::motion_move_region(int x, int y)  void RegionChooser::motion_move_region(int x, int y)
692  {  {
693      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);  
694    
695      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);
696      if (k == move.pos) return;  
697      int new_k;      if (l == region->KeyRange.low) return;
698      bool new_touch_left;      int new_l;
699      bool new_touch_right;      int regionsize = region->KeyRange.high - region->KeyRange.low;
700      int a = 0;      int a = 0;
701      if (k > move.pos) {      if (l > region->KeyRange.low) {
702          for (gig::Region* r = regions.first() ; ; r = regions.next()) {          for (gig::Region* r = regions.first() ; ; r = regions.next()) {
703              if (r != region) {              if (r != region) {
704                  int b = r ? r->KeyRange.low : 128;                  int b = r ? r->KeyRange.low : 128;
705    
706                  // gap: from a to b (not inclusive b)                  // gap: from a to b (not inclusive b)
707    
708                  if (region->KeyRange.high + move.pos >= b) {                  if (region->KeyRange.high >= b) {
709                      // not found the current gap yet, just continue                      // not found the current gap yet, just continue
710                  } else {                  } else {
711    
712                      if (a > region->KeyRange.low + k) {                      if (a > l) {
713                          // this gap is too far to the right, break                          // this gap is too far to the right, break
714                          break;                          break;
715                      }                      }
716    
717                      int newhigh = std::min(region->KeyRange.high + k, b - 1);                      int newhigh = std::min(l + regionsize, b - 1);
718                      int newlo = newhigh - (region->KeyRange.high - region->KeyRange.low);                      int newlo = newhigh - regionsize;
719    
720                      if (newlo >= a) {                      if (newlo >= a) {
721                          // yes it fits - it's a candidate                          // yes it fits - it's a candidate
722                          new_k = newlo - region->KeyRange.low;                          new_l = newlo;
                         new_touch_left = a > 0 && a == newlo;  
                         new_touch_right = b < 128 && newhigh + 1 == b;  
723                      }                      }
724                  }                  }
725                  if (!r) break;                  if (!r) break;
# Line 696  void RegionChooser::motion_move_region(i Line 733  void RegionChooser::motion_move_region(i
733    
734                  // gap from a to b (not inclusive b)                  // gap from a to b (not inclusive b)
735    
736                  if (region->KeyRange.high + k >= b) {                  if (l + regionsize >= b) {
737                      // not found the current gap yet, just continue                      // not found the current gap yet, just continue
738                  } else {                  } else {
739    
740                      if (a > region->KeyRange.low + move.pos) {                      if (a > region->KeyRange.low) {
741                          // this gap is too far to the right, break                          // this gap is too far to the right, break
742                          break;                          break;
743                      }                      }
744    
745                      int newlo = std::max(region->KeyRange.low + k, a);                      int newlo = std::max(l, a);
746                      int newhigh = newlo + (region->KeyRange.high - region->KeyRange.low);                      int newhigh = newlo + regionsize;
747    
748                      if (newhigh < b) {                      if (newhigh < b) {
749                          // yes it fits - break as the first one is the best                          // yes it fits - break as the first one is the best
750                          new_k = newlo - region->KeyRange.low;                          new_l = newlo;
                         new_touch_left = a > 0 && a == newlo;  
                         new_touch_right = b < 128 && newhigh + 1 == b;  
751                          break;                          break;
752                      }                      }
753                  }                  }
# Line 721  void RegionChooser::motion_move_region(i Line 756  void RegionChooser::motion_move_region(i
756              }              }
757          }          }
758      }      }
759      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();  
     }  
   
     if (k > move.pos) {  
         Gdk::Cairo::set_source_rgba(cr, bg);  
         cr->rectangle(prevx + (move.touch_left ? 1 : 0), 0,  
                       std::min(x, prevx2 + 1 - (move.touch_right ? 1 : 0)) -  
                       (prevx + (move.touch_left ? 1 : 0)), h1);  
         cr->fill();  
   
         Gdk::Cairo::set_source_rgba(cr, black);  
         cr->move_to(std::max(x, prevx2 + 1), 0.5);  
         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();  
760    
761          Gdk::Cairo::set_source_rgba(cr, black);      int x1 = key_to_x(std::min(int(region->KeyRange.low), new_l), w);
762          cr->move_to(x, 0.5);      int x2 = key_to_x(std::max(int(region->KeyRange.high),
763          cr->line_to(std::min(x2, prevx - 1) + 1, 0.5);                                 new_l + regionsize) + 1, w) + 1;
         cr->move_to(x, h1 - 0.5);  
         cr->line_to(std::min(x2, prevx - 1) + 1, h1 - 0.5);  
         cr->stroke();  
764    
765          Gdk::Cairo::set_source_rgba(cr, red);      Gdk::Rectangle rect(x1, 0, x2 - x1, h1);
766          cr->rectangle(x + 1, 1, std::min(x2 - 1, prevx) - x, h1 - 2);      update_after_move(new_l);
         cr->fill();  
     }  
767    
768      move.pos = k;      get_window()->invalidate_rect(rect, false);
     move.touch_left = new_touch_left;  
     move.touch_right = new_touch_right;  
769  }  }
770    
771    
# Line 804  bool RegionChooser::on_motion_notify_eve Line 782  bool RegionChooser::on_motion_notify_eve
782          event->y >= REGION_BLOCK_HEIGHT &&          event->y >= REGION_BLOCK_HEIGHT &&
783          event->y < REGION_BLOCK_HEIGHT + KEYBOARD_HEIGHT)          event->y < REGION_BLOCK_HEIGHT + KEYBOARD_HEIGHT)
784      {      {
785          const int k = int(event->x / (get_width() - 1) * 128.0);          const int k = x_to_key(event->x, get_width() - 1);
786          if (k != currentActiveKey) {          if (k != currentActiveKey) {
787              int velocity =              int velocity =
788                  (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 827  bool RegionChooser::is_in_resize_zone(do
827          for (gig::Region* r = regions.first(); r ; r = next_region) {          for (gig::Region* r = regions.first(); r ; r = next_region) {
828              next_region = regions.next();              next_region = regions.next();
829    
830              int lo = int(w * (r->KeyRange.low) / 128.0 + 0.5);              int lo = key_to_x(r->KeyRange.low, w);
831              if (x <= lo - 2) break;              if (x <= lo - 2) break;
832              if (x < lo + 2) {              if (x < lo + 2) {
833                  resize.region = r;                  resize.region = r;
# Line 872  bool RegionChooser::is_in_resize_zone(do Line 850  bool RegionChooser::is_in_resize_zone(do
850                  return resize.min != resize.max;                  return resize.min != resize.max;
851              }              }
852              if (!next_region || r->KeyRange.high + 1 != next_region->KeyRange.low) {              if (!next_region || r->KeyRange.high + 1 != next_region->KeyRange.low) {
853                  int hi = int(w * (r->KeyRange.high + 1) / 128.0 + 0.5);                  int hi = key_to_x(r->KeyRange.high + 1, w);
854                  if (x <= hi - 2) break;                  if (x <= hi - 2) break;
855                  if (x < hi + 2) {                  if (x < hi + 2) {
856                      // edit high limit                      // edit high limit

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

  ViewVC Help
Powered by ViewVC