/[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 2442 by persson, Sun Apr 14 07:29:59 2013 UTC revision 3131 by schoenebeck, Thu Apr 27 17:28:01 2017 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 24  Line 24 
24  #include <cairomm/context.h>  #include <cairomm/context.h>
25  #include <gdkmm/general.h>  #include <gdkmm/general.h>
26  #include <gdkmm/cursor.h>  #include <gdkmm/cursor.h>
27  #include <gtkmm/stock.h>  #include <gdkmm/pixbuf.h>
28  #include <gtkmm/spinbutton.h>  #include <gtkmm/spinbutton.h>
29  #include <gtkmm/dialog.h>  #include <gtkmm/dialog.h>
30    
31  #include "global.h"  #include "global.h"
32    #include "Settings.h"
33    #include "gfx/builtinpix.h"
34    
35  #define REGION_BLOCK_HEIGHT             20  #define REGION_BLOCK_HEIGHT             30
36  #define KEYBOARD_HEIGHT                 40  #define KEYBOARD_HEIGHT                 40
37    
38    struct RegionFeatures {
39        int sampleRefs;
40        int loops;
41    
42        RegionFeatures() {
43            sampleRefs = loops = 0;
44        }
45    };
46    
47    static RegionFeatures regionFeatures(gig::Region* rgn) {
48        RegionFeatures f;
49        for (int i = 0; i < rgn->DimensionRegions; ++i) {
50            gig::DimensionRegion* dr = rgn->pDimensionRegions[i];
51            if (dr->pSample) f.sampleRefs++;
52            // the user doesn't care about loop if there is no valid sample reference
53            if (dr->pSample && dr->SampleLoops) f.loops++;
54        }
55        return f;
56    }
57    
58  void SortedRegions::update(gig::Instrument* instrument) {  void SortedRegions::update(gig::Instrument* instrument) {
59      // Usually, the regions in a gig file are ordered after their key      // Usually, the regions in a gig file are ordered after their key
60      // range, but there are files where they are not. The      // range, but there are files where they are not. The
# Line 54  gig::Region* SortedRegions::first() { Line 76  gig::Region* SortedRegions::first() {
76  }  }
77    
78  gig::Region* SortedRegions::next() {  gig::Region* SortedRegions::next() {
79      region_iterator++;      ++region_iterator;
80      return region_iterator == regions.end() ? 0 : *region_iterator;      return region_iterator == regions.end() ? 0 : *region_iterator;
81  }  }
82    
# Line 62  gig::Region* SortedRegions::next() { Line 84  gig::Region* SortedRegions::next() {
84    
85  RegionChooser::RegionChooser() :  RegionChooser::RegionChooser() :
86      activeKeyColor("red"),      activeKeyColor("red"),
87      red("#8070ff"),      blue("#4796ff"),
88      grey1("grey69"),      grey1("grey69"),
89      white("white"),      white("white"),
90      black("black"),      black("black"),
# Line 71  RegionChooser::RegionChooser() : Line 93  RegionChooser::RegionChooser() :
93  {  {
94      set_size_request(500, KEYBOARD_HEIGHT + REGION_BLOCK_HEIGHT);      set_size_request(500, KEYBOARD_HEIGHT + REGION_BLOCK_HEIGHT);
95    
96        loadBuiltInPix();
97    
98      instrument = 0;      instrument = 0;
99      region = 0;      region = 0;
100      resize.active = false;      resize.active = false;
# Line 103  RegionChooser::RegionChooser() : Line 127  RegionChooser::RegionChooser() :
127      for (int i = 0 ; i < 128 ; i++) key_pressed[i] = false;      for (int i = 0 ; i < 128 ; i++) key_pressed[i] = false;
128    
129      actionGroup = Gtk::ActionGroup::create();      actionGroup = Gtk::ActionGroup::create();
130      actionGroup->add(Gtk::Action::create("Properties",      actionGroup->add(Gtk::Action::create("Properties", _("_Properties")),
                                          Gtk::Stock::PROPERTIES),  
131                       sigc::mem_fun(*this,                       sigc::mem_fun(*this,
132                                     &RegionChooser::show_region_properties));                                     &RegionChooser::show_region_properties));
133      actionGroup->add(Gtk::Action::create("Remove", Gtk::Stock::REMOVE),      actionGroup->add(Gtk::Action::create("Remove", _("_Remove")),
134                       sigc::mem_fun(*this, &RegionChooser::delete_region));                       sigc::mem_fun(*this, &RegionChooser::delete_region));
135      actionGroup->add(Gtk::Action::create("Add", Gtk::Stock::ADD),      actionGroup->add(Gtk::Action::create("Add", _("_Add")),
136                       sigc::mem_fun(*this, &RegionChooser::add_region));                       sigc::mem_fun(*this, &RegionChooser::add_region));
137      actionGroup->add(Gtk::Action::create("Dimensions", _("Dimensions...")),      actionGroup->add(Gtk::Action::create("Dimensions", _("Dimensions...")),
138                       sigc::mem_fun(*this, &RegionChooser::manage_dimensions));                       sigc::mem_fun(*this, &RegionChooser::manage_dimensions));
# Line 154  RegionChooser::RegionChooser() : Line 177  RegionChooser::RegionChooser() :
177      keyboard_key_released_signal.connect(      keyboard_key_released_signal.connect(
178          sigc::mem_fun(*this, &RegionChooser::on_note_off_event)          sigc::mem_fun(*this, &RegionChooser::on_note_off_event)
179      );      );
180        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."));
181  }  }
182    
183  RegionChooser::~RegionChooser()  RegionChooser::~RegionChooser()
# Line 212  bool RegionChooser::on_draw(const Cairo: Line 236  bool RegionChooser::on_draw(const Cairo:
236      Gdk::Cairo::set_source_rgba(cr, bg);      Gdk::Cairo::set_source_rgba(cr, bg);
237      cr->paint();      cr->paint();
238    
     const int w = get_width() - 1;  
   
239      if (clipy2 > h1) {      if (clipy2 > h1) {
240          draw_keyboard(cr, clipx1, clipx2);          draw_keyboard(cr, clipx1, clipx2);
241      }      }
# Line 312  void RegionChooser::draw_regions(const C Line 334  void RegionChooser::draw_regions(const C
334                  cr->line_to(x3, h1 - 0.5);                  cr->line_to(x3, h1 - 0.5);
335                  cr->stroke();                  cr->stroke();
336    
337                  Gdk::Cairo::set_source_rgba(cr, region == r ? red : white);                  Gdk::Cairo::set_source_rgba(cr, region == r ? blue : white);
338                  cr->rectangle(x3 + 1, 1, x2 - x3 - 1, h1 - 2);                  cr->rectangle(x3 + 1, 1, x2 - x3 - 1, h1 - 2);
339                  cr->fill();                  cr->fill();
340                  Gdk::Cairo::set_source_rgba(cr, black);                  Gdk::Cairo::set_source_rgba(cr, black);
# Line 323  void RegionChooser::draw_regions(const C Line 345  void RegionChooser::draw_regions(const C
345    
346      for (gig::Region* r = regions.first() ; r ; r = regions.next()) {      for (gig::Region* r = regions.first() ; r ; r = regions.next()) {
347          int x = key_to_x(r->KeyRange.low, w);          int x = key_to_x(r->KeyRange.low, w);
348            int x2 = key_to_x(r->KeyRange.high + 1, w);
349    
350            RegionFeatures features = regionFeatures(r);
351    
352            const bool bShowLoopSymbol = features.loops > 0;
353            const bool bShowSampleRefSymbol = features.sampleRefs < r->DimensionRegions;
354            if (bShowLoopSymbol || bShowSampleRefSymbol) {
355                const int margin = 2;
356                const int wRgn = x2 - x;
357                //printf("x=%d x2=%d wRgn=%d\n", x, x2, wRgn);
358    
359                cr->save();
360                cr->set_line_width(1);
361                cr->rectangle(x, 1, wRgn, h1 - 1);
362                cr->clip();
363                if (bShowSampleRefSymbol) {
364                    const int wPic = 8;
365                    const int hPic = 8;
366                    Gdk::Cairo::set_source_pixbuf(
367                        cr, (features.sampleRefs) ? yellowDot : redDot,
368                        x + (wRgn-wPic)/2.f,
369                        (bShowLoopSymbol) ? margin : (h1-hPic)/2.f
370                    );
371                    cr->paint();
372                }
373                if (bShowLoopSymbol) {
374                    const int wPic = 12;
375                    const int hPic = 14;
376                    Gdk::Cairo::set_source_pixbuf(
377                        cr, (features.loops == r->DimensionRegions) ? blackLoop : grayLoop,
378                        x + (wRgn-wPic)/2.f,
379                        (bShowSampleRefSymbol) ? h1 - hPic - margin : (h1-hPic)/2.f
380                    );
381                    cr->paint();
382                }
383                cr->restore();
384            }
385        }
386    
387        for (gig::Region* r = regions.first() ; r ; r = regions.next()) {
388            int x = key_to_x(r->KeyRange.low, w);
389    
390          if (x < clip_low) continue;          if (x < clip_low) continue;
391          if (x >= clip_high) break;          if (x >= clip_high) break;
# Line 331  void RegionChooser::draw_regions(const C Line 394  void RegionChooser::draw_regions(const C
394          cr->line_to(x + 0.5, h1 - 1);          cr->line_to(x + 0.5, h1 - 1);
395          cr->stroke();          cr->stroke();
396      }      }
397    
398        // if there is no region yet, show the user some hint text that he may
399        // right click on this area to create a new region
400        if (!regions.first()) {
401            Glib::RefPtr<Pango::Context> context = get_pango_context();
402            Glib::RefPtr<Pango::Layout> layout = Pango::Layout::create(context);
403            layout->set_alignment(Pango::ALIGN_CENTER);
404            layout->set_text(Glib::ustring("*** ") + _("Right click here to create a region.") + " ***");
405            layout->set_width(get_width() * Pango::SCALE);
406            //layout->set_height(get_height() * Pango::SCALE);
407            layout->set_spacing(10);
408            Gdk::Cairo::set_source_rgba(cr, blue);
409            // get the text dimensions
410            int text_width, text_height;
411            layout->get_pixel_size(text_width, text_height);
412            cr->move_to(0, (REGION_BLOCK_HEIGHT - text_height) / 2);
413    #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 16) || GTKMM_MAJOR_VERSION < 2
414            pango_cairo_show_layout(cr->cobj(), layout->gobj());
415    #else
416            layout->show_in_cairo_context(cr);
417    #endif
418        }
419  }  }
420    
421  bool RegionChooser::is_black_key(int key) {  bool RegionChooser::is_black_key(int key) {
# Line 493  void RegionChooser::update_after_resize( Line 578  void RegionChooser::update_after_resize(
578  void RegionChooser::update_after_move(int pos)  void RegionChooser::update_after_move(int pos)
579  {  {
580      instrument_struct_to_be_changed_signal.emit(instrument);      instrument_struct_to_be_changed_signal.emit(instrument);
581      region->SetKeyRange(pos, pos + region->KeyRange.high -      const int range = region->KeyRange.high - region->KeyRange.low;
582                          region->KeyRange.low);      const int diff  = pos - int(region->KeyRange.low);
583        region->SetKeyRange(pos, pos + range);
584        if (Settings::singleton()->moveRootNoteWithRegionMoved) {
585            for (int i = 0; i < 256; ++i) {
586                gig::DimensionRegion* dimrgn = region->pDimensionRegions[i];
587                if (!dimrgn || !dimrgn->pSample || !dimrgn->PitchTrack) continue;
588                dimrgn->UnityNote += diff;
589            }
590        }
591      regions.update(instrument);      regions.update(instrument);
592      instrument_changed.emit();      instrument_changed.emit();
593      instrument_struct_changed_signal.emit(instrument);      instrument_struct_changed_signal.emit(instrument);
# Line 516  bool RegionChooser::on_button_press_even Line 609  bool RegionChooser::on_button_press_even
609          }          }
610      }      }
611    
612        // left mouse button double click
613        if (event->type == GDK_2BUTTON_PRESS && event->button == 1) {
614            if (event->y < REGION_BLOCK_HEIGHT) {
615                // show dimension manager dialog for this region
616                manage_dimensions();
617            }
618        }
619    
620      if (event->y >= REGION_BLOCK_HEIGHT) return true;      if (event->y >= REGION_BLOCK_HEIGHT) return true;
621      if (event->type == GDK_BUTTON_PRESS && event->button == 3) {      if (event->type == GDK_BUTTON_PRESS && event->button == 3) {
622          gig::Region* r = get_region(k);          gig::Region* r = get_region(k);
# Line 591  gig::Region* RegionChooser::get_region(i Line 692  gig::Region* RegionChooser::get_region(i
692      return 0;      return 0;
693  }  }
694    
695    void RegionChooser::set_region(gig::Region* region) {
696        this->region = region;
697        queue_draw();
698        region_selected();
699        dimensionManager.set_region(region);
700    }
701    
702    void RegionChooser::select_next_region() {
703        if (!instrument) return;
704        if (!region) {
705            for (int i = 0; i < 128; ++i) {
706                ::gig::Region* rgn = instrument->GetRegion(i);
707                if (rgn) {
708                    set_region(rgn);
709                    return;
710                }
711            }
712        } else {
713            bool currentFound = false;
714            for (int i = 0; i < 128; ++i) {
715                ::gig::Region* rgn = instrument->GetRegion(i);
716                if (!rgn) continue;
717                if (currentFound) {
718                    if (rgn != region) {
719                        set_region(rgn);
720                        return;
721                    }
722                } else {
723                    if (rgn == region) currentFound = true;
724                }
725            }
726        }
727    }
728    
729    void RegionChooser::select_prev_region() {
730        if (!instrument) return;
731        if (!region) {
732            for (int i = 0; i < 128; ++i) {
733                ::gig::Region* rgn = instrument->GetRegion(i);
734                if (rgn) {
735                    set_region(rgn);
736                    return;
737                }
738            }
739        } else {
740            bool currentFound = false;
741            for (int i = 127; i >= 0; --i) {
742                ::gig::Region* rgn = instrument->GetRegion(i);
743                if (!rgn) continue;
744                if (currentFound) {
745                    if (rgn != region) {
746                        set_region(rgn);
747                        return;
748                    }
749                } else {
750                    if (rgn == region) currentFound = true;
751                }
752            }
753        }
754    }
755    
756  void RegionChooser::motion_resize_region(int x, int y)  void RegionChooser::motion_resize_region(int x, int y)
757  {  {
758      const int w = get_width() - 1;      const int w = get_width() - 1;
# Line 639  void RegionChooser::motion_resize_region Line 801  void RegionChooser::motion_resize_region
801    
802          update_after_resize();          update_after_resize();
803    
804          get_window()->invalidate_rect(rect, false);          //get_window()->invalidate_rect(rect, false);
805            get_window()->invalidate(false); // repaint entire region, otherwise it would create visual artifacts
806      }      }
807  }  }
808    
# Line 853  void RegionChooser::show_region_properti Line 1016  void RegionChooser::show_region_properti
1016      dialog.get_vbox()->pack_start(spinBox);      dialog.get_vbox()->pack_start(spinBox);
1017      spinBox.show();      spinBox.show();
1018      // add OK and CANCEL buttons to the dialog      // add OK and CANCEL buttons to the dialog
1019      dialog.add_button(Gtk::Stock::OK, 0);      dialog.add_button(_("_OK"), 0);
1020      dialog.add_button(Gtk::Stock::CANCEL, 1);      dialog.add_button(_("_Cancel"), 1);
1021      dialog.show_all_children();      dialog.show_all_children();
1022      if (!dialog.run()) { // OK selected ...      if (!dialog.run()) { // OK selected ...
1023          region->KeyGroup =          region->KeyGroup =

Legend:
Removed from v.2442  
changed lines
  Added in v.3131

  ViewVC Help
Powered by ViewVC