/[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 2536 by schoenebeck, Mon Apr 21 17:49:17 2014 UTC revision 3148 by schoenebeck, Thu May 4 11:47:45 2017 UTC
# Line 1  Line 1 
1  /*  /*
2   * Copyright (C) 2006-2014 Andreas Persson   * Copyright (C) 2006-2017 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>
23    #include <assert.h>
24    
25  #include <cairomm/context.h>  #include <cairomm/context.h>
26  #include <gdkmm/general.h>  #include <gdkmm/general.h>
27  #include <gdkmm/cursor.h>  #include <gdkmm/cursor.h>
28  #include <gtkmm/stock.h>  #include <gdkmm/pixbuf.h>
29  #include <gtkmm/spinbutton.h>  #include <gtkmm/spinbutton.h>
30  #include <gtkmm/dialog.h>  #include <gtkmm/dialog.h>
31    
32  #include "global.h"  #include "global.h"
33    #include "Settings.h"
34    #include "gfx/builtinpix.h"
35    
36  #define REGION_BLOCK_HEIGHT             20  #define REGION_BLOCK_HEIGHT             30
37  #define KEYBOARD_HEIGHT                 40  #define KEYBOARD_HEIGHT                 40
38    
39    struct RegionFeatures {
40        int sampleRefs;
41        int loops;
42    
43        RegionFeatures() {
44            sampleRefs = loops = 0;
45        }
46    };
47    
48    static RegionFeatures regionFeatures(gig::Region* rgn) {
49        RegionFeatures f;
50        for (int i = 0; i < rgn->DimensionRegions; ++i) {
51            gig::DimensionRegion* dr = rgn->pDimensionRegions[i];
52            if (dr->pSample) f.sampleRefs++;
53            // the user doesn't care about loop if there is no valid sample reference
54            if (dr->pSample && dr->SampleLoops) f.loops++;
55        }
56        return f;
57    }
58    
59  void SortedRegions::update(gig::Instrument* instrument) {  void SortedRegions::update(gig::Instrument* instrument) {
60      // Usually, the regions in a gig file are ordered after their key      // Usually, the regions in a gig file are ordered after their key
61      // 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 77  gig::Region* SortedRegions::first() {
77  }  }
78    
79  gig::Region* SortedRegions::next() {  gig::Region* SortedRegions::next() {
80      region_iterator++;      ++region_iterator;
81      return region_iterator == regions.end() ? 0 : *region_iterator;      return region_iterator == regions.end() ? 0 : *region_iterator;
82  }  }
83    
# Line 62  gig::Region* SortedRegions::next() { Line 85  gig::Region* SortedRegions::next() {
85    
86  RegionChooser::RegionChooser() :  RegionChooser::RegionChooser() :
87      activeKeyColor("red"),      activeKeyColor("red"),
88      red("#8070ff"),      blue("#4796ff"),
89      grey1("grey69"),      grey1("grey69"),
90      white("white"),      white("white"),
91      black("black"),      black("black"),
92      m_VirtKeybModeChoice(_("Virtual Keyboard Mode")),      m_VirtKeybModeChoice(_("Virtual Keyboard Mode")),
93      currentActiveKey(-1)      currentActiveKey(-1),
94        modifyallregions(false)
95  {  {
96      set_size_request(500, KEYBOARD_HEIGHT + REGION_BLOCK_HEIGHT);      set_size_request(500, KEYBOARD_HEIGHT + REGION_BLOCK_HEIGHT);
97    
98        loadBuiltInPix();
99    
100        // create gray blue hatched pattern
101        {
102            const int width = grayBlueHatchedPattern->get_width();
103            const int height = grayBlueHatchedPattern->get_height();
104            const int stride = grayBlueHatchedPattern->get_rowstride();
105    
106            // manually convert from RGBA to ARGB
107            this->grayBlueHatchedPatternARGB = grayBlueHatchedPattern->copy();
108            const int pixelSize = stride / width;
109            const int totalPixels = width * height;
110            assert(pixelSize == 4);
111            unsigned char* ptr = this->grayBlueHatchedPatternARGB->get_pixels();
112            for (int iPixel = 0; iPixel < totalPixels; ++iPixel, ptr += pixelSize) {
113                const unsigned char r = ptr[0];
114                const unsigned char g = ptr[1];
115                const unsigned char b = ptr[2];
116                const unsigned char a = ptr[3];
117                ptr[0] = b;
118                ptr[1] = g;
119                ptr[2] = r;
120                ptr[3] = a;
121            }
122    
123            Cairo::RefPtr<Cairo::ImageSurface> imageSurface = Cairo::ImageSurface::create(
124                this->grayBlueHatchedPatternARGB->get_pixels(), Cairo::FORMAT_ARGB32, width, height, stride
125            );
126            this->grayBlueHatchedSurfacePattern = Cairo::SurfacePattern::create(imageSurface);
127            this->grayBlueHatchedSurfacePattern->set_extend(Cairo::EXTEND_REPEAT);
128        }
129    
130      instrument = 0;      instrument = 0;
131      region = 0;      region = 0;
132      resize.active = false;      resize.active = false;
# Line 103  RegionChooser::RegionChooser() : Line 159  RegionChooser::RegionChooser() :
159      for (int i = 0 ; i < 128 ; i++) key_pressed[i] = false;      for (int i = 0 ; i < 128 ; i++) key_pressed[i] = false;
160    
161      actionGroup = Gtk::ActionGroup::create();      actionGroup = Gtk::ActionGroup::create();
162      actionGroup->add(Gtk::Action::create("Properties",      actionGroup->add(Gtk::Action::create("Properties", _("_Properties")),
                                          Gtk::Stock::PROPERTIES),  
163                       sigc::mem_fun(*this,                       sigc::mem_fun(*this,
164                                     &RegionChooser::show_region_properties));                                     &RegionChooser::show_region_properties));
165      actionGroup->add(Gtk::Action::create("Remove", Gtk::Stock::REMOVE),      actionGroup->add(Gtk::Action::create("Remove", _("_Remove")),
166                       sigc::mem_fun(*this, &RegionChooser::delete_region));                       sigc::mem_fun(*this, &RegionChooser::delete_region));
167      actionGroup->add(Gtk::Action::create("Add", Gtk::Stock::ADD),      actionGroup->add(Gtk::Action::create("Add", _("_Add")),
168                       sigc::mem_fun(*this, &RegionChooser::add_region));                       sigc::mem_fun(*this, &RegionChooser::add_region));
169      actionGroup->add(Gtk::Action::create("Dimensions", _("Dimensions...")),      actionGroup->add(Gtk::Action::create("Dimensions", _("Dimensions...")),
170                       sigc::mem_fun(*this, &RegionChooser::manage_dimensions));                       sigc::mem_fun(*this, &RegionChooser::manage_dimensions));
# Line 161  RegionChooser::~RegionChooser() Line 216  RegionChooser::~RegionChooser()
216  {  {
217  }  }
218    
219    void RegionChooser::setModifyAllRegions(bool b) {
220        modifyallregions = b;
221        // redraw required parts
222        queue_draw();
223    }
224    
225  void RegionChooser::invalidate_key(int key) {  void RegionChooser::invalidate_key(int key) {
226      const int h = KEYBOARD_HEIGHT;      const int h = KEYBOARD_HEIGHT;
227      const int w = get_width() - 1;      const int w = get_width() - 1;
# Line 311  void RegionChooser::draw_regions(const C Line 372  void RegionChooser::draw_regions(const C
372                  cr->line_to(x3, h1 - 0.5);                  cr->line_to(x3, h1 - 0.5);
373                  cr->stroke();                  cr->stroke();
374    
375                  Gdk::Cairo::set_source_rgba(cr, region == r ? red : white);                  if (region == r)
376                        Gdk::Cairo::set_source_rgba(cr, blue);
377                    else if (modifyallregions)
378                        cr->set_source(grayBlueHatchedSurfacePattern);
379                    else
380                        Gdk::Cairo::set_source_rgba(cr, white);
381    
382                  cr->rectangle(x3 + 1, 1, x2 - x3 - 1, h1 - 2);                  cr->rectangle(x3 + 1, 1, x2 - x3 - 1, h1 - 2);
383                  cr->fill();                  cr->fill();
384                  Gdk::Cairo::set_source_rgba(cr, black);                  Gdk::Cairo::set_source_rgba(cr, black);
# Line 322  void RegionChooser::draw_regions(const C Line 389  void RegionChooser::draw_regions(const C
389    
390      for (gig::Region* r = regions.first() ; r ; r = regions.next()) {      for (gig::Region* r = regions.first() ; r ; r = regions.next()) {
391          int x = key_to_x(r->KeyRange.low, w);          int x = key_to_x(r->KeyRange.low, w);
392            int x2 = key_to_x(r->KeyRange.high + 1, w);
393    
394            RegionFeatures features = regionFeatures(r);
395    
396            const bool bShowLoopSymbol = features.loops > 0;
397            const bool bShowSampleRefSymbol = features.sampleRefs < r->DimensionRegions;
398            if (bShowLoopSymbol || bShowSampleRefSymbol) {
399                const int margin = 2;
400                const int wRgn = x2 - x;
401                //printf("x=%d x2=%d wRgn=%d\n", x, x2, wRgn);
402    
403                cr->save();
404                cr->set_line_width(1);
405                cr->rectangle(x, 1, wRgn, h1 - 1);
406                cr->clip();
407                if (bShowSampleRefSymbol) {
408                    const int wPic = 8;
409                    const int hPic = 8;
410                    Gdk::Cairo::set_source_pixbuf(
411                        cr, (features.sampleRefs) ? yellowDot : redDot,
412                        x + (wRgn-wPic)/2.f,
413                        (bShowLoopSymbol) ? margin : (h1-hPic)/2.f
414                    );
415                    cr->paint();
416                }
417                if (bShowLoopSymbol) {
418                    const int wPic = 12;
419                    const int hPic = 14;
420                    Gdk::Cairo::set_source_pixbuf(
421                        cr, (features.loops == r->DimensionRegions) ? blackLoop : grayLoop,
422                        x + (wRgn-wPic)/2.f,
423                        (bShowSampleRefSymbol) ? h1 - hPic - margin : (h1-hPic)/2.f
424                    );
425                    cr->paint();
426                }
427                cr->restore();
428            }
429        }
430    
431        for (gig::Region* r = regions.first() ; r ; r = regions.next()) {
432            int x = key_to_x(r->KeyRange.low, w);
433    
434          if (x < clip_low) continue;          if (x < clip_low) continue;
435          if (x >= clip_high) break;          if (x >= clip_high) break;
# Line 339  void RegionChooser::draw_regions(const C Line 447  void RegionChooser::draw_regions(const C
447          layout->set_alignment(Pango::ALIGN_CENTER);          layout->set_alignment(Pango::ALIGN_CENTER);
448          layout->set_text(Glib::ustring("*** ") + _("Right click here to create a region.") + " ***");          layout->set_text(Glib::ustring("*** ") + _("Right click here to create a region.") + " ***");
449          layout->set_width(get_width() * Pango::SCALE);          layout->set_width(get_width() * Pango::SCALE);
450          Gdk::Cairo::set_source_rgba(cr, red);          //layout->set_height(get_height() * Pango::SCALE);
451            layout->set_spacing(10);
452            Gdk::Cairo::set_source_rgba(cr, blue);
453            // get the text dimensions
454            int text_width, text_height;
455            layout->get_pixel_size(text_width, text_height);
456            cr->move_to(0, (REGION_BLOCK_HEIGHT - text_height) / 2);
457  #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
458          pango_cairo_show_layout(cr->cobj(), layout->gobj());          pango_cairo_show_layout(cr->cobj(), layout->gobj());
459  #else  #else
# Line 508  void RegionChooser::update_after_resize( Line 622  void RegionChooser::update_after_resize(
622  void RegionChooser::update_after_move(int pos)  void RegionChooser::update_after_move(int pos)
623  {  {
624      instrument_struct_to_be_changed_signal.emit(instrument);      instrument_struct_to_be_changed_signal.emit(instrument);
625      region->SetKeyRange(pos, pos + region->KeyRange.high -      const int range = region->KeyRange.high - region->KeyRange.low;
626                          region->KeyRange.low);      const int diff  = pos - int(region->KeyRange.low);
627        region->SetKeyRange(pos, pos + range);
628        if (Settings::singleton()->moveRootNoteWithRegionMoved) {
629            for (int i = 0; i < 256; ++i) {
630                gig::DimensionRegion* dimrgn = region->pDimensionRegions[i];
631                if (!dimrgn || !dimrgn->pSample || !dimrgn->PitchTrack) continue;
632                dimrgn->UnityNote += diff;
633            }
634        }
635      regions.update(instrument);      regions.update(instrument);
636      instrument_changed.emit();      instrument_changed.emit();
637      instrument_struct_changed_signal.emit(instrument);      instrument_struct_changed_signal.emit(instrument);
# Line 531  bool RegionChooser::on_button_press_even Line 653  bool RegionChooser::on_button_press_even
653          }          }
654      }      }
655    
656        // left mouse button double click
657        if (event->type == GDK_2BUTTON_PRESS && event->button == 1) {
658            if (event->y < REGION_BLOCK_HEIGHT) {
659                // show dimension manager dialog for this region
660                manage_dimensions();
661            }
662        }
663    
664      if (event->y >= REGION_BLOCK_HEIGHT) return true;      if (event->y >= REGION_BLOCK_HEIGHT) return true;
665      if (event->type == GDK_BUTTON_PRESS && event->button == 3) {      if (event->type == GDK_BUTTON_PRESS && event->button == 3) {
666          gig::Region* r = get_region(k);          gig::Region* r = get_region(k);
# Line 606  gig::Region* RegionChooser::get_region(i Line 736  gig::Region* RegionChooser::get_region(i
736      return 0;      return 0;
737  }  }
738    
739    void RegionChooser::set_region(gig::Region* region) {
740        this->region = region;
741        queue_draw();
742        region_selected();
743        dimensionManager.set_region(region);
744    }
745    
746    void RegionChooser::select_next_region() {
747        if (!instrument) return;
748        if (!region) {
749            for (int i = 0; i < 128; ++i) {
750                ::gig::Region* rgn = instrument->GetRegion(i);
751                if (rgn) {
752                    set_region(rgn);
753                    return;
754                }
755            }
756        } else {
757            bool currentFound = false;
758            for (int i = 0; i < 128; ++i) {
759                ::gig::Region* rgn = instrument->GetRegion(i);
760                if (!rgn) continue;
761                if (currentFound) {
762                    if (rgn != region) {
763                        set_region(rgn);
764                        return;
765                    }
766                } else {
767                    if (rgn == region) currentFound = true;
768                }
769            }
770        }
771    }
772    
773    void RegionChooser::select_prev_region() {
774        if (!instrument) return;
775        if (!region) {
776            for (int i = 0; i < 128; ++i) {
777                ::gig::Region* rgn = instrument->GetRegion(i);
778                if (rgn) {
779                    set_region(rgn);
780                    return;
781                }
782            }
783        } else {
784            bool currentFound = false;
785            for (int i = 127; i >= 0; --i) {
786                ::gig::Region* rgn = instrument->GetRegion(i);
787                if (!rgn) continue;
788                if (currentFound) {
789                    if (rgn != region) {
790                        set_region(rgn);
791                        return;
792                    }
793                } else {
794                    if (rgn == region) currentFound = true;
795                }
796            }
797        }
798    }
799    
800  void RegionChooser::motion_resize_region(int x, int y)  void RegionChooser::motion_resize_region(int x, int y)
801  {  {
802      const int w = get_width() - 1;      const int w = get_width() - 1;
# Line 654  void RegionChooser::motion_resize_region Line 845  void RegionChooser::motion_resize_region
845    
846          update_after_resize();          update_after_resize();
847    
848          get_window()->invalidate_rect(rect, false);          //get_window()->invalidate_rect(rect, false);
849            get_window()->invalidate(false); // repaint entire region, otherwise it would create visual artifacts
850      }      }
851  }  }
852    
# Line 868  void RegionChooser::show_region_properti Line 1060  void RegionChooser::show_region_properti
1060      dialog.get_vbox()->pack_start(spinBox);      dialog.get_vbox()->pack_start(spinBox);
1061      spinBox.show();      spinBox.show();
1062      // add OK and CANCEL buttons to the dialog      // add OK and CANCEL buttons to the dialog
1063      dialog.add_button(Gtk::Stock::OK, 0);      dialog.add_button(_("_OK"), 0);
1064      dialog.add_button(Gtk::Stock::CANCEL, 1);      dialog.add_button(_("_Cancel"), 1);
1065      dialog.show_all_children();      dialog.show_all_children();
1066      if (!dialog.run()) { // OK selected ...      if (!dialog.run()) { // OK selected ...
1067          region->KeyGroup =          region->KeyGroup =

Legend:
Removed from v.2536  
changed lines
  Added in v.3148

  ViewVC Help
Powered by ViewVC