/[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 2507 by persson, Sun Jan 12 19:37:55 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             20
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 160  RegionChooser::~RegionChooser() Line 160  RegionChooser::~RegionChooser()
160  {  {
161  }  }
162    
163  template<class T> inline std::string ToString(T o) {  void RegionChooser::invalidate_key(int key) {
164      std::stringstream ss;      const int h = KEYBOARD_HEIGHT;
165      ss << o;      const int w = get_width() - 1;
166      return ss.str();      int x1 = key_to_x(key - 0.5, w);
167        int x2 = key_to_x(key + 1.5, w);
168    
169        Gdk::Rectangle rect(x1 + 1, h1 + 1, x2 - x1 - 1, h - 2);
170        get_window()->invalidate_rect(rect, false);
171  }  }
172    
173  void RegionChooser::on_note_on_event(int key, int velocity) {  void RegionChooser::on_note_on_event(int key, int velocity) {
174      draw_key(key, activeKeyColor);      key_pressed[key] = true;
175        invalidate_key(key);
176      m_VirtKeybVelocityLabel.set_text(ToString(velocity));      m_VirtKeybVelocityLabel.set_text(ToString(velocity));
177  }  }
178    
179  void RegionChooser::on_note_off_event(int key, int velocity) {  void RegionChooser::on_note_off_event(int key, int velocity) {
180      if (is_black_key(key)) {      key_pressed[key] = false;
181          draw_key(key, black);      invalidate_key(key);
     } else {  
         draw_key(key, key >= 21 && key <= 108 ? white : grey1);  
     }  
182      m_VirtKeybOffVelocityLabel.set_text(ToString(velocity));      m_VirtKeybOffVelocityLabel.set_text(ToString(velocity));
183  }  }
184    
185    
186  #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
187  bool RegionChooser::on_expose_event(GdkEventExpose* e)  bool RegionChooser::on_expose_event(GdkEventExpose* e) {
188  {      double clipx1 = e->area.x;
189      return on_draw(get_window()->create_cairo_context());      double clipx2 = e->area.x + e->area.width;
190        double clipy1 = e->area.y;
191        double clipy2 = e->area.y + e->area.height;
192    
193        const Cairo::RefPtr<Cairo::Context>& cr =
194            get_window()->create_cairo_context();
195    #if 0
196  }  }
197  #endif  #endif
198    #else
199  bool RegionChooser::on_draw(const Cairo::RefPtr<Cairo::Context>& cr)  bool RegionChooser::on_draw(const Cairo::RefPtr<Cairo::Context>& cr) {
200  {      double clipx1, clipx2, clipy1, clipy2;
201      const int h = KEYBOARD_HEIGHT;      cr->get_clip_extents(clipx1, clipy1, clipx2, clipy2);
202      const int w = get_width() - 1;  #endif
     const int bh = int(h * 0.55);  
203    
204      cr->save();      cr->save();
205      cr->set_line_width(1);      cr->set_line_width(1);
# Line 204  bool RegionChooser::on_draw(const Cairo: Line 212  bool RegionChooser::on_draw(const Cairo:
212      Gdk::Cairo::set_source_rgba(cr, bg);      Gdk::Cairo::set_source_rgba(cr, bg);
213      cr->paint();      cr->paint();
214    
215        if (clipy2 > h1) {
216            draw_keyboard(cr, clipx1, clipx2);
217        }
218    
219        if (clipy1 < h1 && instrument) {
220            draw_regions(cr, clipx1, clipx2);
221        }
222    
223        cr->restore();
224    
225        return true;
226    }
227    
228    void RegionChooser::draw_keyboard(const Cairo::RefPtr<Cairo::Context>& cr,
229                                      int clip_low, int clip_high) {
230        const int h = KEYBOARD_HEIGHT;
231        const int w = get_width() - 1;
232        const int bh = int(h * 0.55);
233    
234      Gdk::Cairo::set_source_rgba(cr, black);      Gdk::Cairo::set_source_rgba(cr, black);
235      cr->rectangle(0.5, h1 + 0.5, w, h - 1);      cr->rectangle(0.5, h1 + 0.5, w, h - 1);
236      cr->stroke();      cr->stroke();
237    
238      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);  
   
239      Gdk::Cairo::set_source_rgba(cr, grey1);      Gdk::Cairo::set_source_rgba(cr, grey1);
240      cr->rectangle(1, h1 + 1, x1 - 1, h - 2);      cr->rectangle(1, h1 + 1, x1 - 1, h - 2);
241      cr->fill();      cr->fill();
242    
243        int x2 = key_to_x(109.5, w);
244      Gdk::Cairo::set_source_rgba(cr, white);      Gdk::Cairo::set_source_rgba(cr, white);
245      cr->rectangle(x1 + 1, h1 + 1, x2 - x1 - 1, h - 2);      cr->rectangle(x1 + 1, h1 + 1, x2 - x1 - 1, h - 2);
246      cr->fill();      cr->fill();
# Line 224  bool RegionChooser::on_draw(const Cairo: Line 250  bool RegionChooser::on_draw(const Cairo:
250      cr->fill();      cr->fill();
251    
252      Gdk::Cairo::set_source_rgba(cr, black);      Gdk::Cairo::set_source_rgba(cr, black);
253      for (int i = 0 ; i < 128 ; i++) {  
254        int clipkey1 = std::max(0, x_to_key_right(clip_low - 1, w));
255        int clipkey2 = std::min(x_to_key_right(clip_high - 1, w) + 1, 128);
256    
257        for (int i = clipkey1 ; i < clipkey2 ; i++) {
258          int note = (i + 3) % 12;          int note = (i + 3) % 12;
259          int x = int(w * i / 128.0 + 0.5);          int x = key_to_x(i, w);
260    
261          if (note == 1 || note == 4 || note == 6 ||          if (note == 1 || note == 4 || note == 6 ||
262              note == 9 || note == 11) {              note == 9 || note == 11) {
263              int x2 = int(w * (i + 0.5) / 128.0 + 0.5);              // black key: short line in the middle, with a rectangle
264                // on top
265                int x2 = key_to_x(i + 0.5, w);
266              cr->move_to(x2 + 0.5, h1 + bh + 0.5);              cr->move_to(x2 + 0.5, h1 + bh + 0.5);
267              cr->line_to(x2 + 0.5, h1 + h - 1);              cr->line_to(x2 + 0.5, h1 + h - 1);
268              cr->stroke();              cr->stroke();
269    
270              int x3 = int(w * (i + 1) / 128.0 + 0.5);              int x3 = key_to_x(i + 1, w);
271              cr->rectangle(x, h1 + 1, x3 - x + 1, bh);              cr->rectangle(x, h1 + 1, x3 - x + 1, bh);
272              cr->fill();              cr->fill();
273          } else if (note == 3 || note == 8) {          } else if (note == 3 || note == 8) {
274                // C or F: long line to the left
275              cr->move_to(x + 0.5, h1 + 1);              cr->move_to(x + 0.5, h1 + 1);
276              cr->line_to(x + 0.5, h1 + h - 1);              cr->line_to(x + 0.5, h1 + h - 1);
277              cr->stroke();              cr->stroke();
   
             if (note == 3) draw_digit(i);  
278          }          }
279    
280            if (key_pressed[i]) draw_key(cr, i);
281    
282            if (note == 3) draw_digit(cr, i);
283      }      }
284    }
285    
     if (instrument) {  
         int i = 0;  
         gig::Region* next_region;  
         int x3 = -1;  
         for (gig::Region* r = regions.first() ; r ; r = next_region) {  
286    
287              if (x3 < 0) x3 = int(w * (r->KeyRange.low) / 128.0 + 0.5);  void RegionChooser::draw_regions(const Cairo::RefPtr<Cairo::Context>& cr,
288              next_region = regions.next();                                   int clip_low, int clip_high) {
289              if (!next_region ||      const int w = get_width() - 1;
290                  r->KeyRange.high + 1 != next_region->KeyRange.low) {  
291                  int x2 = int(w * (r->KeyRange.high + 1) / 128.0 + 0.5);      Gdk::Cairo::set_source_rgba(cr, black);
292        gig::Region* next_region;
293        int x3 = -1;
294        for (gig::Region* r = regions.first() ; r ; r = next_region) {
295            next_region = regions.next();
296    
297            if (x3 < 0) {
298                x3 = key_to_x(r->KeyRange.low, w);
299                if (x3 >= clip_high) break;
300            }
301            if (!next_region ||
302                r->KeyRange.high + 1 != next_region->KeyRange.low ||
303                r == region || next_region == region) {
304    
305                int x2 = key_to_x(r->KeyRange.high + 1, w);
306                if (x2 >= clip_low) {
307                  cr->move_to(x3, 0.5);                  cr->move_to(x3, 0.5);
308                  cr->line_to(x2 + 0.5, 0.5);                  cr->line_to(x2 + 0.5, 0.5);
309                  cr->line_to(x2 + 0.5, h1 - 0.5);                  cr->line_to(x2 + 0.5, h1 - 0.5);
310                  cr->line_to(x3, h1 - 0.5);                  cr->line_to(x3, h1 - 0.5);
311                  cr->stroke();                  cr->stroke();
312    
313                  Gdk::Cairo::set_source_rgba(cr, white);                  Gdk::Cairo::set_source_rgba(cr, region == r ? red : white);
314                  cr->rectangle(x3 + 1, 1, x2 - x3 - 1, h1 - 2);                  cr->rectangle(x3 + 1, 1, x2 - x3 - 1, h1 - 2);
315                  cr->fill();                  cr->fill();
316                  Gdk::Cairo::set_source_rgba(cr, black);                  Gdk::Cairo::set_source_rgba(cr, black);
   
                 x3 = -1;  
317              }              }
318              i++;              x3 = -1;
         }  
   
         for (gig::Region* r = regions.first() ; r ; r = regions.next()) {  
             int x = int(w * (r->KeyRange.low) / 128.0 + 0.5);  
             cr->move_to(x + 0.5, 1);  
             cr->line_to(x + 0.5, h1 - 1);  
             cr->stroke();  
         }  
   
         if (region) {  
             int x1 = int(w * (region->KeyRange.low) / 128.0 + 0.5);  
             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();  
319          }          }
320      }      }
321    
322      cr->restore();      for (gig::Region* r = regions.first() ; r ; r = regions.next()) {
323            int x = key_to_x(r->KeyRange.low, w);
324    
325      return true;          if (x < clip_low) continue;
326  }          if (x >= clip_high) break;
327    
328            cr->move_to(x + 0.5, 1);
329            cr->line_to(x + 0.5, h1 - 1);
330            cr->stroke();
331        }
332    }
333    
334  bool RegionChooser::is_black_key(int key) {  bool RegionChooser::is_black_key(int key) {
335      const int note = (key + 3) % 12;      const int note = (key + 3) % 12;
336      return note == 1 || note == 4 || note == 6 || note == 9 || note == 11;      return note == 1 || note == 4 || note == 6 || note == 9 || note == 11;
337  }  }
338    
339  void RegionChooser::draw_digit(int key) {  void RegionChooser::draw_digit(const Cairo::RefPtr<Cairo::Context>& cr,
340                                   int key) {
341      const int h = KEYBOARD_HEIGHT;      const int h = KEYBOARD_HEIGHT;
342      const int w = get_width() - 1;      const int w = get_width() - 1;
343      Glib::RefPtr<Pango::Layout> layout = Pango::Layout::create(get_pango_context());      Glib::RefPtr<Pango::Layout> layout =
344            Pango::Layout::create(get_pango_context());
345      char buf[30];      char buf[30];
346      sprintf(buf, "<span size=\"8000\">%d</span>", key / 12 - 1);      sprintf(buf, "<span size=\"8000\">%d</span>", key / 12 - 1);
347      layout->set_markup(buf);      layout->set_markup(buf);
# Line 312  void RegionChooser::draw_digit(int key) Line 349  void RegionChooser::draw_digit(int key)
349      double text_w = double(rectangle.get_width()) / Pango::SCALE;      double text_w = double(rectangle.get_width()) / Pango::SCALE;
350      double text_h = double(rectangle.get_height()) / Pango::SCALE;      double text_h = double(rectangle.get_height()) / Pango::SCALE;
351      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();  
352      Gdk::Cairo::set_source_rgba(cr, black);      Gdk::Cairo::set_source_rgba(cr, black);
353      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));
354  #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 358  void RegionChooser::draw_digit(int key)
358  #endif  #endif
359  }  }
360    
361  void RegionChooser::draw_key(int key, const Gdk::RGBA& color)  void RegionChooser::draw_key(const Cairo::RefPtr<Cairo::Context>& cr,
362  {                               int key) {
363      const int h = KEYBOARD_HEIGHT;      const int h = KEYBOARD_HEIGHT;
364      const int w = get_width() - 1;      const int w = get_width() - 1;
365      const int bh = int(h * 0.55);      const int bh = int(h * 0.55);
366    
367      Cairo::RefPtr<Cairo::Context> cr = get_window()->create_cairo_context();      Gdk::Cairo::set_source_rgba(cr, activeKeyColor);
     Gdk::Cairo::set_source_rgba(cr, color);  
368    
369      int note = (key + 3) % 12;      int note = (key + 3) % 12;
370      int x = int(w * key / 128.0 + 0.5) + 1;      int x = key_to_x(key, w) + 1;
371      int x2 = int(w * (key + 1.5) / 128.0 + 0.5);      int x2 = key_to_x(key + 1.5, w);
372      int x3 = int(w * (key + 1) / 128.0 + 0.5);      int x3 = key_to_x(key + 1, w);
373      int x4 = int(w * (key - 0.5) / 128.0 + 0.5);      int x4 = key_to_x(key - 0.5, w);
374      int w1 = x3 - x;      int w1 = x3 - x;
375      switch (note) {      switch (note) {
376      case 0: case 5: case 10:      case 0: case 5: case 10:
# Line 355  void RegionChooser::draw_key(int key, co Line 390  void RegionChooser::draw_key(int key, co
390          cr->fill();          cr->fill();
391          cr->rectangle(x, h1 + bh + 1, x2 - x, h - bh - 2);          cr->rectangle(x, h1 + bh + 1, x2 - x, h - bh - 2);
392          cr->fill();          cr->fill();
         if (note == 3) draw_digit(key);  
393          break;          break;
394      default:      default:
395          cr->rectangle(x, h1 + 1, w1, bh - 1);          cr->rectangle(x, h1 + 1, w1, bh - 1);
396          cr->fill();          cr->fill();
397          break;          break;
398      }      }
399        Gdk::Cairo::set_source_rgba(cr, black);
400  }  }
401    
402  void RegionChooser::set_instrument(gig::Instrument* instrument)  void RegionChooser::set_instrument(gig::Instrument* instrument)
# Line 376  void RegionChooser::set_instrument(gig:: Line 411  void RegionChooser::set_instrument(gig::
411    
412  bool RegionChooser::on_button_release_event(GdkEventButton* event)  bool RegionChooser::on_button_release_event(GdkEventButton* event)
413  {  {
414      const int k = int(event->x / (get_width() - 1) * 128.0);      const int k = x_to_key(event->x, get_width() - 1);
415    
416      // handle-note off on virtual keyboard      // handle-note off on virtual keyboard
417      if (event->type == GDK_BUTTON_RELEASE) {      if (event->type == GDK_BUTTON_RELEASE) {
# Line 406  bool RegionChooser::on_button_release_ev Line 441  bool RegionChooser::on_button_release_ev
441  #endif  #endif
442          resize.active = false;          resize.active = false;
443    
         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);  
             }  
         }  
   
444          if (!is_in_resize_zone(event->x, event->y) && cursor_is_resize) {          if (!is_in_resize_zone(event->x, event->y) && cursor_is_resize) {
445              get_window()->set_cursor();              get_window()->set_cursor();
446              cursor_is_resize = false;              cursor_is_resize = false;
# Line 442  bool RegionChooser::on_button_release_ev Line 453  bool RegionChooser::on_button_release_ev
453  #endif  #endif
454          move.active = false;          move.active = false;
455    
         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);  
         }  
   
456          if (is_in_resize_zone(event->x, event->y)) {          if (is_in_resize_zone(event->x, event->y)) {
457  #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2  #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
458              get_window()->set_cursor(Gdk::Cursor(Gdk::SB_H_DOUBLE_ARROW));              get_window()->set_cursor(Gdk::Cursor(Gdk::SB_H_DOUBLE_ARROW));
# Line 465  bool RegionChooser::on_button_release_ev Line 465  bool RegionChooser::on_button_release_ev
465      return true;      return true;
466  }  }
467    
468    void RegionChooser::update_after_resize()
469    {
470        if (resize.mode == resize.moving_high_limit) {
471            if (resize.region->KeyRange.high != resize.pos - 1) {
472                instrument_struct_to_be_changed_signal.emit(instrument);
473                resize.region->SetKeyRange(resize.region->KeyRange.low,
474                                           resize.pos - 1);
475                regions.update(instrument);
476                instrument_changed.emit();
477                instrument_struct_changed_signal.emit(instrument);
478            }
479        } else if (resize.mode == resize.moving_low_limit) {
480            if (resize.region->KeyRange.low != resize.pos) {
481                instrument_struct_to_be_changed_signal.emit(instrument);
482                resize.region->SetKeyRange(resize.pos,
483                                           resize.region->KeyRange.high);
484                regions.update(instrument);
485                instrument_changed.emit();
486                instrument_struct_changed_signal.emit(instrument);
487            }
488        }
489    }
490    
491    void RegionChooser::update_after_move(int pos)
492    {
493        instrument_struct_to_be_changed_signal.emit(instrument);
494        region->SetKeyRange(pos, pos + region->KeyRange.high -
495                            region->KeyRange.low);
496        regions.update(instrument);
497        instrument_changed.emit();
498        instrument_struct_changed_signal.emit(instrument);
499    }
500    
501  bool RegionChooser::on_button_press_event(GdkEventButton* event)  bool RegionChooser::on_button_press_event(GdkEventButton* event)
502  {  {
503      if (!instrument) return true;      if (!instrument) return true;
504    
505      const int k = int(event->x / (get_width() - 1) * 128.0);      const int w = get_width() - 1;
506        const int k = x_to_key(event->x, w);
507    
508      if (event->type == GDK_BUTTON_PRESS) {      if (event->type == GDK_BUTTON_PRESS) {
509          if (event->y >= REGION_BLOCK_HEIGHT) {          if (event->y >= REGION_BLOCK_HEIGHT) {
# Line 539  bool RegionChooser::on_button_press_even Line 573  bool RegionChooser::on_button_press_even
573                                                        event->time);                                                        event->time);
574  #endif  #endif
575                  move.active = true;                  move.active = true;
576                  move.from_x = event->x;                  move.offset = event->x - key_to_x(region->KeyRange.low, w);
                 move.pos = 0;  
577              }              }
578          }          }
579      }      }
# Line 549  bool RegionChooser::on_button_press_even Line 582  bool RegionChooser::on_button_press_even
582    
583  gig::Region* RegionChooser::get_region(int key)  gig::Region* RegionChooser::get_region(int key)
584  {  {
585      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();  
   
586          if (key < r->KeyRange.low) return 0;          if (key < r->KeyRange.low) return 0;
587          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;  
588      }      }
589      return 0;      return 0;
590  }  }
# Line 575  void RegionChooser::motion_resize_region Line 599  void RegionChooser::motion_resize_region
599      else if (k > resize.max) k = resize.max;      else if (k > resize.max) k = resize.max;
600    
601      if (k != resize.pos) {      if (k != resize.pos) {
         Cairo::RefPtr<Cairo::Context> cr = get_window()->create_cairo_context();  
         cr->set_line_width(1);  
   
602          if (resize.mode == resize.undecided) {          if (resize.mode == resize.undecided) {
603              if (k < resize.pos) {              if (k < resize.pos) {
604                  // edit high limit of prev_region                  // edit high limit of prev_region
# Line 590  void RegionChooser::motion_resize_region Line 611  void RegionChooser::motion_resize_region
611                  resize.mode = resize.moving_low_limit;                  resize.mode = resize.moving_low_limit;
612              }              }
613          }          }
614          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);  
615    
616            int x1, x2;
617          if (resize.mode == resize.moving_high_limit) {          if (resize.mode == resize.moving_high_limit) {
618              if (k > resize.pos) {              if (resize.region->KeyRange.high < resize.pos - 1) {
619                  Gdk::Cairo::set_source_rgba(cr, white);                  x1 = resize.region->KeyRange.high;
620                  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();  
621              } else {              } else {
622                  int xx = (resize.pos == resize.max &&                  x1 = resize.pos - 1;
623                            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();  
624              }              }
625          } else {          } else {
626              if (k < resize.pos) {              if (resize.region->KeyRange.low < resize.pos) {
627                  Gdk::Cairo::set_source_rgba(cr, white);                  x1 = resize.region->KeyRange.low;
628                  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();  
629              } else {              } else {
630                  int xx = (resize.pos == resize.min &&                  x1 = resize.pos;
631                            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();  
632              }              }
633          }          }
634          Gdk::Cairo::set_source_rgba(cr, black);          x1 = key_to_x(x1, w);
635          cr->move_to(x + 0.5, 1);          x2 = key_to_x(x2 + 1, w) + 1;
636          cr->line_to(x + 0.5, h1 - 1);          Gdk::Rectangle rect(x1, 0, x2 - x1, h1);
637          cr->stroke();  
638          resize.pos = k;          update_after_resize();
639    
640            get_window()->invalidate_rect(rect, false);
641      }      }
642  }  }
643    
644  void RegionChooser::motion_move_region(int x, int y)  void RegionChooser::motion_move_region(int x, int y)
645  {  {
646      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);  
647    
648      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);
649      if (k == move.pos) return;  
650      int new_k;      if (l == region->KeyRange.low) return;
651      bool new_touch_left;      int new_l;
652      bool new_touch_right;      int regionsize = region->KeyRange.high - region->KeyRange.low;
653      int a = 0;      int a = 0;
654      if (k > move.pos) {      if (l > region->KeyRange.low) {
655          for (gig::Region* r = regions.first() ; ; r = regions.next()) {          for (gig::Region* r = regions.first() ; ; r = regions.next()) {
656              if (r != region) {              if (r != region) {
657                  int b = r ? r->KeyRange.low : 128;                  int b = r ? r->KeyRange.low : 128;
658    
659                  // gap: from a to b (not inclusive b)                  // gap: from a to b (not inclusive b)
660    
661                  if (region->KeyRange.high + move.pos >= b) {                  if (region->KeyRange.high >= b) {
662                      // not found the current gap yet, just continue                      // not found the current gap yet, just continue
663                  } else {                  } else {
664    
665                      if (a > region->KeyRange.low + k) {                      if (a > l) {
666                          // this gap is too far to the right, break                          // this gap is too far to the right, break
667                          break;                          break;
668                      }                      }
669    
670                      int newhigh = std::min(region->KeyRange.high + k, b - 1);                      int newhigh = std::min(l + regionsize, b - 1);
671                      int newlo = newhigh - (region->KeyRange.high - region->KeyRange.low);                      int newlo = newhigh - regionsize;
672    
673                      if (newlo >= a) {                      if (newlo >= a) {
674                          // yes it fits - it's a candidate                          // yes it fits - it's a candidate
675                          new_k = newlo - region->KeyRange.low;                          new_l = newlo;
                         new_touch_left = a > 0 && a == newlo;  
                         new_touch_right = b < 128 && newhigh + 1 == b;  
676                      }                      }
677                  }                  }
678                  if (!r) break;                  if (!r) break;
# Line 696  void RegionChooser::motion_move_region(i Line 686  void RegionChooser::motion_move_region(i
686    
687                  // gap from a to b (not inclusive b)                  // gap from a to b (not inclusive b)
688    
689                  if (region->KeyRange.high + k >= b) {                  if (l + regionsize >= b) {
690                      // not found the current gap yet, just continue                      // not found the current gap yet, just continue
691                  } else {                  } else {
692    
693                      if (a > region->KeyRange.low + move.pos) {                      if (a > region->KeyRange.low) {
694                          // this gap is too far to the right, break                          // this gap is too far to the right, break
695                          break;                          break;
696                      }                      }
697    
698                      int newlo = std::max(region->KeyRange.low + k, a);                      int newlo = std::max(l, a);
699                      int newhigh = newlo + (region->KeyRange.high - region->KeyRange.low);                      int newhigh = newlo + regionsize;
700    
701                      if (newhigh < b) {                      if (newhigh < b) {
702                          // yes it fits - break as the first one is the best                          // yes it fits - break as the first one is the best
703                          new_k = newlo - region->KeyRange.low;                          new_l = newlo;
                         new_touch_left = a > 0 && a == newlo;  
                         new_touch_right = b < 128 && newhigh + 1 == b;  
704                          break;                          break;
705                      }                      }
706                  }                  }
# Line 721  void RegionChooser::motion_move_region(i Line 709  void RegionChooser::motion_move_region(i
709              }              }
710          }          }
711      }      }
712      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();  
713    
714          Gdk::Cairo::set_source_rgba(cr, black);      int x1 = key_to_x(std::min(int(region->KeyRange.low), new_l), w);
715          cr->move_to(std::max(x, prevx2 + 1), 0.5);      int x2 = key_to_x(std::max(int(region->KeyRange.high),
716          cr->line_to(x2 + 1, 0.5);                                 new_l + regionsize) + 1, w) + 1;
         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();  
717    
718          Gdk::Cairo::set_source_rgba(cr, black);      Gdk::Rectangle rect(x1, 0, x2 - x1, h1);
719          cr->move_to(x, 0.5);      update_after_move(new_l);
         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();  
     }  
720    
721      move.pos = k;      get_window()->invalidate_rect(rect, false);
     move.touch_left = new_touch_left;  
     move.touch_right = new_touch_right;  
722  }  }
723    
724    
# Line 804  bool RegionChooser::on_motion_notify_eve Line 735  bool RegionChooser::on_motion_notify_eve
735          event->y >= REGION_BLOCK_HEIGHT &&          event->y >= REGION_BLOCK_HEIGHT &&
736          event->y < REGION_BLOCK_HEIGHT + KEYBOARD_HEIGHT)          event->y < REGION_BLOCK_HEIGHT + KEYBOARD_HEIGHT)
737      {      {
738          const int k = int(event->x / (get_width() - 1) * 128.0);          const int k = x_to_key(event->x, get_width() - 1);
739          if (k != currentActiveKey) {          if (k != currentActiveKey) {
740              int velocity =              int velocity =
741                  (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 780  bool RegionChooser::is_in_resize_zone(do
780          for (gig::Region* r = regions.first(); r ; r = next_region) {          for (gig::Region* r = regions.first(); r ; r = next_region) {
781              next_region = regions.next();              next_region = regions.next();
782    
783              int lo = int(w * (r->KeyRange.low) / 128.0 + 0.5);              int lo = key_to_x(r->KeyRange.low, w);
784              if (x <= lo - 2) break;              if (x <= lo - 2) break;
785              if (x < lo + 2) {              if (x < lo + 2) {
786                  resize.region = r;                  resize.region = r;
# Line 872  bool RegionChooser::is_in_resize_zone(do Line 803  bool RegionChooser::is_in_resize_zone(do
803                  return resize.min != resize.max;                  return resize.min != resize.max;
804              }              }
805              if (!next_region || r->KeyRange.high + 1 != next_region->KeyRange.low) {              if (!next_region || r->KeyRange.high + 1 != next_region->KeyRange.low) {
806                  int hi = int(w * (r->KeyRange.high + 1) / 128.0 + 0.5);                  int hi = key_to_x(r->KeyRange.high + 1, w);
807                  if (x <= hi - 2) break;                  if (x <= hi - 2) break;
808                  if (x < hi + 2) {                  if (x < hi + 2) {
809                      // edit high limit                      // edit high limit

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

  ViewVC Help
Powered by ViewVC