/[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 1261 by persson, Thu Jul 5 17:12:20 2007 UTC revision 1322 by schoenebeck, Tue Sep 4 11:04:56 2007 UTC
# Line 31  RegionChooser::RegionChooser() Line 31  RegionChooser::RegionChooser()
31  {  {
32      Glib::RefPtr<Gdk::Colormap> colormap = get_default_colormap();      Glib::RefPtr<Gdk::Colormap> colormap = get_default_colormap();
33    
     black = Gdk::Color("black");  
     white = Gdk::Color("white");  
34      red = Gdk::Color("#8070ff");      red = Gdk::Color("#8070ff");
35      blue = Gdk::Color("#c098ff");      grey1 = Gdk::Color("#b0b0b0");
     green = Gdk::Color("#a088ff");  
     grey1 = Gdk::Color("red");  
36    
     colormap->alloc_color(black);  
     colormap->alloc_color(white);  
37      colormap->alloc_color(red);      colormap->alloc_color(red);
     colormap->alloc_color(blue);  
     colormap->alloc_color(green);  
38      colormap->alloc_color(grey1);      colormap->alloc_color(grey1);
39      instrument = 0;      instrument = 0;
40      region = 0;      region = 0;
41      resize.active = false;      resize.active = false;
42        move.active = false;
43      cursor_is_resize = false;      cursor_is_resize = false;
44      h1 = 20;      h1 = 20;
45      width = 800;      width = 800;
# Line 86  RegionChooser::RegionChooser() Line 79  RegionChooser::RegionChooser()
79      add_events(Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK |      add_events(Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK |
80                 Gdk::POINTER_MOTION_MASK | Gdk::POINTER_MOTION_HINT_MASK);                 Gdk::POINTER_MOTION_MASK | Gdk::POINTER_MOTION_HINT_MASK);
81    
82      dimensionManager.articulation_changed_signal.connect(      dimensionManager.region_to_be_changed_signal.connect(
83          sigc::mem_fun(*this, &RegionChooser::on_dimension_manager_changed)          region_to_be_changed_signal.make_slot()
84        );
85        dimensionManager.region_changed_signal.connect(
86            region_changed_signal.make_slot()
87        );
88        dimensionManager.region_changed_signal.connect(
89            sigc::hide(
90                sigc::mem_fun(*this, &RegionChooser::on_dimension_manager_changed)
91            )
92      );      );
93  }  }
94    
# Line 117  bool RegionChooser::on_expose_event(GdkE Line 118  bool RegionChooser::on_expose_event(GdkE
118      Glib::RefPtr<const Gdk::GC> black = get_style()->get_black_gc();      Glib::RefPtr<const Gdk::GC> black = get_style()->get_black_gc();
119      Glib::RefPtr<const Gdk::GC> white = get_style()->get_white_gc();      Glib::RefPtr<const Gdk::GC> white = get_style()->get_white_gc();
120    
121        Glib::RefPtr<Pango::Context> context = get_pango_context();
122        Glib::RefPtr<Pango::Layout> layout = Pango::Layout::create(context);
123    
124      window->draw_rectangle(black, false, 0, h1, w, h - 1);      window->draw_rectangle(black, false, 0, h1, w, h - 1);
125      window->draw_rectangle(white, true, 1, h1 + 1, w - 1, h - 2);      gc->set_foreground(grey1);
126        int x1 = int(w * 20.5 / 128.0 + 0.5);
127        int x2 = int(w * 109.5 / 128.0 + 0.5);
128        window->draw_rectangle(gc, true, 1, h1 + 1,
129                               x1 - 1, h - 2);
130        window->draw_rectangle(white, true, x1 + 1, h1 + 1, x2 - x1 - 1, h - 2);
131        window->draw_rectangle(gc, true, x2 + 1, h1 + 1,
132                               w - x2 - 1, h - 2);
133        int octave = -1;
134      for (int i = 0 ; i < 128 ; i++) {      for (int i = 0 ; i < 128 ; i++) {
135          int note = (i + 3) % 12;          int note = (i + 3) % 12;
136          int x = int(w * i / 128.0 + 0.5);          int x = int(w * i / 128.0 + 0.5);
# Line 132  bool RegionChooser::on_expose_event(GdkE Line 144  bool RegionChooser::on_expose_event(GdkE
144          } else if (note == 3 || note == 8) {          } else if (note == 3 || note == 8) {
145              window->draw_line(black, x, h1 + 1, x, h1 + h);              window->draw_line(black, x, h1 + 1, x, h1 + h);
146          }          }
147            if (note == 3) {
148                char buf[30];
149                sprintf(buf, "<span size=\"x-small\">%d</span>", octave);
150                layout->set_markup(buf);
151                Pango::Rectangle rectangle = layout->get_logical_extents();
152                double text_w = double(rectangle.get_width()) / Pango::SCALE;
153                double text_h = double(rectangle.get_height()) / Pango::SCALE;
154                double x2 = w * (i + 0.75) / 128.0;
155                window->draw_layout(black, int(x2 - text_w / 2 + 1),
156                                    int(h1 + h - text_h + 0.5), layout);
157                octave++;
158            }
159      }      }
160    
161      if (instrument) {      if (instrument) {
162          int i = 0;          int i = 0;
163          gig::Region *nextRegion;          gig::Region *next_region;
164          int x3 = -1;          int x3 = -1;
165          for (gig::Region *r = instrument->GetFirstRegion() ;          for (gig::Region *r = instrument->GetFirstRegion() ;
166               r ;               r ;
167               r = nextRegion) {               r = next_region) {
168    
169              if (x3 < 0) x3 = int(w * (r->KeyRange.low) / 128.0 + 0.5);              if (x3 < 0) x3 = int(w * (r->KeyRange.low) / 128.0 + 0.5);
170              nextRegion = instrument->GetNextRegion();              next_region = instrument->GetNextRegion();
171              if (!nextRegion || r->KeyRange.high + 1 != nextRegion->KeyRange.low) {              if (!next_region || r->KeyRange.high + 1 != next_region->KeyRange.low) {
172                  int x2 = int(w * (r->KeyRange.high + 1) / 128.0 + 0.5);                  int x2 = int(w * (r->KeyRange.high + 1) / 128.0 + 0.5);
173                  window->draw_line(black, x3, 0, x2, 0);                  window->draw_line(black, x3, 0, x2, 0);
174                  window->draw_line(black, x3, h1 - 1, x2, h1 - 1);                  window->draw_line(black, x3, h1 - 1, x2, h1 - 1);
# Line 248  bool RegionChooser::on_button_release_ev Line 272  bool RegionChooser::on_button_release_ev
272              get_window()->set_cursor();              get_window()->set_cursor();
273              cursor_is_resize = false;              cursor_is_resize = false;
274          }          }
275        } else if (move.active) {
276            get_window()->pointer_ungrab(event->time);
277            move.active = false;
278    
279            if (move.pos) {
280                region->KeyRange.low += move.pos;
281                region->KeyRange.high += move.pos;
282    
283                // find the r which is the first one to the right of region
284                // at its new position
285                gig::Region* r;
286                gig::Region* prev_region = 0;
287                for (r = instrument->GetFirstRegion() ; r ; r = instrument->GetNextRegion()) {
288                    if (r->KeyRange.low > region->KeyRange.low) break;
289                    prev_region = r;
290                }
291    
292                // place region before r if it's not already there
293                if (prev_region != region) {
294                    instrument_struct_to_be_changed_signal.emit(instrument);
295                    instrument->MoveRegion(region, r);
296                    instrument_struct_changed_signal.emit(instrument);
297                }
298            }
299    
300            if (is_in_resize_zone(event->x, event->y)) {
301                get_window()->set_cursor(Gdk::Cursor(Gdk::SB_H_DOUBLE_ARROW));
302                cursor_is_resize = true;
303            }
304      }      }
305      return true;      return true;
306  }  }
# Line 271  bool RegionChooser::on_button_press_even Line 324  bool RegionChooser::on_button_press_even
324          }          }
325      } else {      } else {
326          if (is_in_resize_zone(event->x, event->y)) {          if (is_in_resize_zone(event->x, event->y)) {
             Gdk::Cursor double_arrow(Gdk::SB_H_DOUBLE_ARROW);  
327              get_window()->pointer_grab(false,              get_window()->pointer_grab(false,
328                                         Gdk::BUTTON_RELEASE_MASK |                                         Gdk::BUTTON_RELEASE_MASK |
329                                         Gdk::POINTER_MOTION_MASK |                                         Gdk::POINTER_MOTION_MASK |
330                                         Gdk::POINTER_MOTION_HINT_MASK,                                         Gdk::POINTER_MOTION_HINT_MASK,
331                                         double_arrow, event->time);                                         Gdk::Cursor(Gdk::SB_H_DOUBLE_ARROW), event->time);
332              resize.active = true;              resize.active = true;
333          } else {          } else {
334              gig::Region* r = get_region(k);              gig::Region* r = get_region(k);
# Line 284  bool RegionChooser::on_button_press_even Line 336  bool RegionChooser::on_button_press_even
336                  region = r;                  region = r;
337                  queue_draw();                  queue_draw();
338                  region_selected();                  region_selected();
339    
340                    get_window()->pointer_grab(false,
341                                               Gdk::BUTTON_RELEASE_MASK |
342                                               Gdk::POINTER_MOTION_MASK |
343                                               Gdk::POINTER_MOTION_HINT_MASK,
344                                               Gdk::Cursor(Gdk::FLEUR), event->time);
345                    move.active = true;
346                    move.from_x = event->x;
347                    move.pos = 0;
348              }              }
349          }          }
350      }      }
# Line 292  bool RegionChooser::on_button_press_even Line 353  bool RegionChooser::on_button_press_even
353    
354  gig::Region* RegionChooser::get_region(int key)  gig::Region* RegionChooser::get_region(int key)
355  {  {
356        gig::Region* prev_region = 0;
357        gig::Region* next_region;
358      for (gig::Region *r = instrument->GetFirstRegion() ; r ;      for (gig::Region *r = instrument->GetFirstRegion() ; r ;
359           r = instrument->GetNextRegion()) {           r = next_region) {
360            next_region = instrument->GetNextRegion();
361    
362          if (key < r->KeyRange.low) return 0;          if (key < r->KeyRange.low) return 0;
363          if (key <= r->KeyRange.high) return r;          if (key <= r->KeyRange.high) {
364                move.touch_left = prev_region && prev_region->KeyRange.high + 1 == r->KeyRange.low;
365                move.touch_right = next_region && r->KeyRange.high + 1 == next_region->KeyRange.low;
366                return r;
367            }
368            prev_region = r;
369      }      }
370      return 0;      return 0;
371  }  }
372    
373  bool RegionChooser::on_motion_notify_event(GdkEventMotion* event)  void RegionChooser::motion_resize_region(int x, int y)
374  {  {
375      const int w = width - 1;      const int w = width - 1;
376      Glib::RefPtr<Gdk::Window> window = get_window();      Glib::RefPtr<Gdk::Window> window = get_window();
     int x, y;  
     Gdk::ModifierType state = Gdk::ModifierType(0);  
     window->get_pointer(x, y, state);  
     if (resize.active) {  
         int k = int(double(x) / w * 128.0 + 0.5);  
377    
378          if (k < resize.min) k = resize.min;      int k = int(double(x) / w * 128.0 + 0.5);
         else if (k > resize.max) k = resize.max;  
379    
380          if (k != resize.pos) {      if (k < resize.min) k = resize.min;
381              if (resize.mode == resize.undecided) {      else if (k > resize.max) k = resize.max;
382                  if (k < resize.pos) {  
383                      // edit high limit of prev_region      if (k != resize.pos) {
384                      resize.max = resize.region->KeyRange.low;          if (resize.mode == resize.undecided) {
385                      resize.region = resize.prev_region;              if (k < resize.pos) {
386                      resize.mode = resize.moving_high_limit;                  // edit high limit of prev_region
387                  } else {                  resize.max = resize.region->KeyRange.low;
388                      // edit low limit of region                  resize.region = resize.prev_region;
389                      resize.min = resize.prev_region->KeyRange.high + 1;                  resize.mode = resize.moving_high_limit;
390                      resize.mode = resize.moving_low_limit;              } else {
391                  }                  // edit low limit of region
392                    resize.min = resize.prev_region->KeyRange.high + 1;
393                    resize.mode = resize.moving_low_limit;
394                }
395            }
396            Glib::RefPtr<const Gdk::GC> black = get_style()->get_black_gc();
397            Glib::RefPtr<const Gdk::GC> white = get_style()->get_white_gc();
398            if (region == resize.region) {
399                gc->set_foreground(red);
400                white = gc;
401            }
402            Glib::RefPtr<const Gdk::GC> bg = get_style()->get_bg_gc(Gtk::STATE_NORMAL);
403            int prevx = int(w * resize.pos / 128.0 + 0.5);
404            x = int(w * k / 128.0 + 0.5);
405    
406            if (resize.mode == resize.moving_high_limit) {
407                if (k > resize.pos) {
408                    window->draw_rectangle(white, true, prevx, 1, x - prevx, h1 - 2);
409                    window->draw_line(black, prevx, 0, x, 0);
410                    window->draw_line(black, prevx, h1 - 1, x, h1 - 1);
411                } else {
412                    int xx = ((resize.pos == resize.max && resize.max != 128) ? 1 : 0);
413                    window->draw_rectangle(bg, true, x + 1, 0, prevx - x - xx, h1);
414              }              }
415              Glib::RefPtr<const Gdk::GC> black = get_style()->get_black_gc();          } else {
416              Glib::RefPtr<const Gdk::GC> white = get_style()->get_white_gc();              if (k < resize.pos) {
417              if (region == resize.region) {                  window->draw_rectangle(white, true, x + 1, 1, prevx - x, h1 - 2);
418                  gc->set_foreground(red);                  window->draw_line(black, x, 0, prevx, 0);
419                  white = gc;                  window->draw_line(black, x, h1 - 1, prevx, h1 - 1);
420              }              } else {
421              Glib::RefPtr<const Gdk::GC> bg = get_style()->get_bg_gc(Gtk::STATE_NORMAL);                  int xx = ((resize.pos == resize.min && resize.min != 0) ? 1 : 0);
422              int prevx = int(w * resize.pos / 128.0 + 0.5);                  window->draw_rectangle(bg, true, prevx + xx, 0, x - prevx - xx, h1);
423              x = int(w * k / 128.0 + 0.5);              }
424            }
425              if (resize.mode == resize.moving_high_limit) {          window->draw_line(black, x, 1, x, h1 - 2);
426                  if (k > resize.pos) {          resize.pos = k;
427                      window->draw_rectangle(white, true, prevx, 1, x - prevx, h1 - 2);      }
428                      window->draw_line(black, prevx, 0, x, 0);  }
429                      window->draw_line(black, prevx, h1 - 1, x, h1 - 1);  
430    void RegionChooser::motion_move_region(int x, int y)
431    {
432        const int w = width - 1;
433        Glib::RefPtr<Gdk::Window> window = get_window();
434    
435        int k = int(double(x - move.from_x) / w * 128.0 + 0.5);
436        if (k == move.pos) return;
437        int new_k;
438        bool new_touch_left;
439        bool new_touch_right;
440        int a = 0;
441        if (k > move.pos) {
442            for (gig::Region* r = instrument->GetFirstRegion() ; ;
443                 r = instrument->GetNextRegion()) {
444                if (r != region) {
445                    int b = r ? r->KeyRange.low : 128;
446    
447                    // gap: from a to b (not inclusive b)
448    
449                    if (region->KeyRange.high + move.pos >= b) {
450                        // not found the current gap yet, just continue
451                  } else {                  } else {
452                      int xx = ((resize.pos == resize.max && resize.max != 128) ? 1 : 0);  
453                      window->draw_rectangle(bg, true, x + 1, 0, prevx - x - xx, h1);                      if (a > region->KeyRange.low + k) {
454                            // this gap is too far to the right, break
455                            break;
456                        }
457    
458                        int newhigh = std::min(region->KeyRange.high + k, b - 1);
459                        int newlo = newhigh - (region->KeyRange.high - region->KeyRange.low);
460    
461                        if (newlo >= a) {
462                            // yes it fits - it's a candidate
463                            new_k = newlo - region->KeyRange.low;
464                            new_touch_left = a > 0 && a == newlo;
465                            new_touch_right = b < 128 && newhigh + 1 == b;
466                        }
467                  }                  }
468              } else {                  if (!r) break;
469                  if (k < resize.pos) {                  a = r->KeyRange.high + 1;
470                      window->draw_rectangle(white, true, x + 1, 1, prevx - x, h1 - 2);              }
471                      window->draw_line(black, x, 0, prevx, 0);          }
472                      window->draw_line(black, x, h1 - 1, prevx, h1 - 1);      } else {
473            for (gig::Region* r = instrument->GetFirstRegion() ; ;
474                 r = instrument->GetNextRegion()) {
475                if (r != region) {
476                    int b = r ? r->KeyRange.low : 128;
477    
478                    // gap from a to b (not inclusive b)
479    
480                    if (region->KeyRange.high + k >= b) {
481                        // not found the current gap yet, just continue
482                  } else {                  } else {
483                      int xx = ((resize.pos == resize.min && resize.min != 0) ? 1 : 0);  
484                      window->draw_rectangle(bg, true, prevx + xx, 0, x - prevx - xx, h1);                      if (a > region->KeyRange.low + move.pos) {
485                            // this gap is too far to the right, break
486                            break;
487                        }
488    
489                        int newlo = std::max(region->KeyRange.low + k, a);
490                        int newhigh = newlo + (region->KeyRange.high - region->KeyRange.low);
491    
492                        if (newhigh < b) {
493                            // yes it fits - break as the first one is the best
494                            new_k = newlo - region->KeyRange.low;
495                            new_touch_left = a > 0 && a == newlo;
496                            new_touch_right = b < 128 && newhigh + 1 == b;
497                            break;
498                        }
499                  }                  }
500                    if (!r) break;
501                    a = r->KeyRange.high + 1;
502              }              }
             window->draw_line(black, x, 1, x, h1 - 2);  
             resize.pos = k;  
503          }          }
504        }
505        k = new_k;
506        if (k == move.pos) return;
507    
508        Glib::RefPtr<const Gdk::GC> bg = get_style()->get_bg_gc(Gtk::STATE_NORMAL);
509        int prevx = int(w * (move.pos + region->KeyRange.low) / 128.0 + 0.5);
510        x = int(w * (k + region->KeyRange.low) / 128.0 + 0.5);
511        int prevx2 = int(w * (move.pos + region->KeyRange.high + 1) / 128.0 + 0.5);
512        int x2 = int(w * (k + region->KeyRange.high + 1) / 128.0 + 0.5);
513        Glib::RefPtr<const Gdk::GC> black = get_style()->get_black_gc();
514        gc->set_foreground(red);
515    
516        if (!new_touch_left) window->draw_line(black, x, 1, x, h1 - 2);
517        if (!new_touch_right) window->draw_line(black, x2, 1, x2, h1 - 2);
518    
519        if (k > move.pos) {
520            window->draw_rectangle(bg, true, prevx + (move.touch_left ? 1 : 0), 0,
521                                   std::min(x, prevx2 + 1 - (move.touch_right ? 1 : 0)) -
522                                   (prevx + (move.touch_left ? 1 : 0)), h1);
523    
524            window->draw_line(black, std::max(x, prevx2 + 1), 0, x2, 0);
525            window->draw_line(black, std::max(x, prevx2 + 1), h1 - 1, x2, h1 - 1);
526            window->draw_rectangle(gc, true, std::max(x + 1, prevx2), 1,
527                                   x2 - std::max(x + 1, prevx2), h1 - 2);
528        } else {
529            window->draw_rectangle(bg, true, std::max(x2 + 1, prevx + (move.touch_left ? 1 : 0)), 0,
530                                   prevx2 + 1 - (move.touch_right ? 1 : 0) -
531                                   std::max(x2 + 1, prevx + (move.touch_left ? 1 : 0)), h1);
532    
533            window->draw_line(black, x, 0, std::min(x2, prevx - 1), 0);
534            window->draw_line(black, x, h1 - 1, std::min(x2, prevx - 1), h1 - 1);
535    
536            window->draw_rectangle(gc, true, x + 1, 1, std::min(x2 - 1, prevx) - x, h1 - 2);
537        }
538    
539        move.pos = k;
540        move.touch_left = new_touch_left;
541        move.touch_right = new_touch_right;
542    }
543    
544    
545    bool RegionChooser::on_motion_notify_event(GdkEventMotion* event)
546    {
547        Glib::RefPtr<Gdk::Window> window = get_window();
548        int x, y;
549        Gdk::ModifierType state = Gdk::ModifierType(0);
550        window->get_pointer(x, y, state);
551    
552        if (resize.active) {
553            motion_resize_region(x, y);
554        } else if (move.active) {
555            motion_move_region(x, y);
556      } else {      } else {
557          if (is_in_resize_zone(x, y)) {          if (is_in_resize_zone(x, y)) {
558              if (!cursor_is_resize) {              if (!cursor_is_resize) {
559                  Gdk::Cursor double_arrow(Gdk::SB_H_DOUBLE_ARROW);                  window->set_cursor(Gdk::Cursor(Gdk::SB_H_DOUBLE_ARROW));
                 window->set_cursor(double_arrow);  
560                  cursor_is_resize = true;                  cursor_is_resize = true;
561              }              }
562          } else if (cursor_is_resize) {          } else if (cursor_is_resize) {
# Line 466  void RegionChooser::add_region() Line 660  void RegionChooser::add_region()
660          if (r->KeyRange.low > new_region_pos) break;          if (r->KeyRange.low > new_region_pos) break;
661      }      }
662    
663        instrument_struct_to_be_changed_signal.emit(instrument);
664    
665      region = instrument->AddRegion();      region = instrument->AddRegion();
666      region->KeyRange.low = region->KeyRange.high = new_region_pos;      region->KeyRange.low = region->KeyRange.high = new_region_pos;
667    
668      instrument->MoveRegion(region, r);      instrument->MoveRegion(region, r);
669    
670        instrument_struct_changed_signal.emit(instrument);
671    
672      queue_draw();      queue_draw();
673      region_selected();      region_selected();
674      instrument_changed();      instrument_changed();
# Line 477  void RegionChooser::add_region() Line 676  void RegionChooser::add_region()
676    
677  void RegionChooser::delete_region()  void RegionChooser::delete_region()
678  {  {
679        instrument_struct_to_be_changed_signal.emit(instrument);
680      instrument->DeleteRegion(region);      instrument->DeleteRegion(region);
681        instrument_struct_changed_signal.emit(instrument);
682    
683      region = 0;      region = 0;
684      queue_draw();      queue_draw();
685      region_selected();      region_selected();
# Line 495  void RegionChooser::on_dimension_manager Line 697  void RegionChooser::on_dimension_manager
697      region_selected();      region_selected();
698      instrument_changed();      instrument_changed();
699  }  }
700    
701    sigc::signal<void, gig::Instrument*> RegionChooser::signal_instrument_struct_to_be_changed() {
702        return instrument_struct_to_be_changed_signal;
703    }
704    
705    sigc::signal<void, gig::Instrument*> RegionChooser::signal_instrument_struct_changed() {
706        return instrument_struct_changed_signal;
707    }
708    
709    sigc::signal<void, gig::Region*> RegionChooser::signal_region_to_be_changed() {
710        return region_to_be_changed_signal;
711    }
712    
713    sigc::signal<void, gig::Region*> RegionChooser::signal_region_changed_signal() {
714        return region_changed_signal;
715    }

Legend:
Removed from v.1261  
changed lines
  Added in v.1322

  ViewVC Help
Powered by ViewVC