/[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 2246 by persson, Fri Aug 19 10:55:41 2011 UTC revision 3226 by schoenebeck, Fri May 26 22:15:06 2017 UTC
# Line 1  Line 1 
1  /*  /*
2   * Copyright (C) 2006-2011 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 17  Line 17 
17   * 02110-1301 USA.   * 02110-1301 USA.
18   */   */
19    
20    #include "global.h"
21  #include "regionchooser.h"  #include "regionchooser.h"
22    
23  #include <algorithm>  #include <algorithm>
24  #include <sstream>  #include <assert.h>
25    
26  #include <cairomm/context.h>  #include <cairomm/context.h>
27  #include <gdkmm/general.h>  #include <gdkmm/general.h>
28  #include <gdkmm/cursor.h>  #include <gdkmm/cursor.h>
29  #include <gtkmm/stock.h>  #include <gtkmm/stock.h>
30    #include <gdkmm/pixbuf.h>
31  #include <gtkmm/spinbutton.h>  #include <gtkmm/spinbutton.h>
32  #include <gtkmm/dialog.h>  #include <gtkmm/dialog.h>
33    
34  #include "global.h"  #include "Settings.h"
35    #include "gfx/builtinpix.h"
36    
37  #define REGION_BLOCK_HEIGHT             20  #define REGION_BLOCK_HEIGHT             30
38  #define KEYBOARD_HEIGHT                 40  #define KEYBOARD_HEIGHT                 40
39    
40    struct RegionFeatures {
41        int sampleRefs;
42        int loops;
43    
44        RegionFeatures() {
45            sampleRefs = loops = 0;
46        }
47    };
48    
49    static RegionFeatures regionFeatures(gig::Region* rgn) {
50        RegionFeatures f;
51        for (int i = 0; i < rgn->DimensionRegions; ++i) {
52            gig::DimensionRegion* dr = rgn->pDimensionRegions[i];
53            if (dr->pSample) f.sampleRefs++;
54            // the user doesn't care about loop if there is no valid sample reference
55            if (dr->pSample && dr->SampleLoops) f.loops++;
56        }
57        return f;
58    }
59    
60  void SortedRegions::update(gig::Instrument* instrument) {  void SortedRegions::update(gig::Instrument* instrument) {
61      // Usually, the regions in a gig file are ordered after their key      // Usually, the regions in a gig file are ordered after their key
62      // range, but there are files where they are not. The      // range, but there are files where they are not. The
# Line 55  gig::Region* SortedRegions::first() { Line 78  gig::Region* SortedRegions::first() {
78  }  }
79    
80  gig::Region* SortedRegions::next() {  gig::Region* SortedRegions::next() {
81      region_iterator++;      ++region_iterator;
82      return region_iterator == regions.end() ? 0 : *region_iterator;      return region_iterator == regions.end() ? 0 : *region_iterator;
83  }  }
84    
# Line 63  gig::Region* SortedRegions::next() { Line 86  gig::Region* SortedRegions::next() {
86    
87  RegionChooser::RegionChooser() :  RegionChooser::RegionChooser() :
88      activeKeyColor("red"),      activeKeyColor("red"),
89      red("#8070ff"),      blue("#4796ff"),
90      grey1("grey69"),      grey1("grey69"),
91      white("white"),      white("white"),
92      black("black"),      black("black"),
93      m_VirtKeybModeChoice(_("Virtual Keyboard Mode")),      m_VirtKeybModeChoice(_("Virtual Keyboard Mode")),
94      currentActiveKey(-1)      currentActiveKey(-1),
95        modifyallregions(false)
96  {  {
97      set_size_request(500, KEYBOARD_HEIGHT + REGION_BLOCK_HEIGHT);      set_size_request(500, KEYBOARD_HEIGHT + REGION_BLOCK_HEIGHT);
98    
99        loadBuiltInPix();
100    
101        // create gray blue hatched pattern
102        {
103            const int width = grayBlueHatchedPattern->get_width();
104            const int height = grayBlueHatchedPattern->get_height();
105            const int stride = grayBlueHatchedPattern->get_rowstride();
106    
107            // manually convert from RGBA to ARGB
108            this->grayBlueHatchedPatternARGB = grayBlueHatchedPattern->copy();
109            const int pixelSize = stride / width;
110            const int totalPixels = width * height;
111            assert(pixelSize == 4);
112            unsigned char* ptr = this->grayBlueHatchedPatternARGB->get_pixels();
113            for (int iPixel = 0; iPixel < totalPixels; ++iPixel, ptr += pixelSize) {
114                const unsigned char r = ptr[0];
115                const unsigned char g = ptr[1];
116                const unsigned char b = ptr[2];
117                const unsigned char a = ptr[3];
118                ptr[0] = b;
119                ptr[1] = g;
120                ptr[2] = r;
121                ptr[3] = a;
122            }
123    
124            Cairo::RefPtr<Cairo::ImageSurface> imageSurface = Cairo::ImageSurface::create(
125                this->grayBlueHatchedPatternARGB->get_pixels(), Cairo::FORMAT_ARGB32, width, height, stride
126            );
127            this->grayBlueHatchedSurfacePattern = Cairo::SurfacePattern::create(imageSurface);
128            this->grayBlueHatchedSurfacePattern->set_extend(Cairo::EXTEND_REPEAT);
129        }
130    
131      instrument = 0;      instrument = 0;
132      region = 0;      region = 0;
133      resize.active = false;      resize.active = false;
# Line 155  RegionChooser::RegionChooser() : Line 211  RegionChooser::RegionChooser() :
211      keyboard_key_released_signal.connect(      keyboard_key_released_signal.connect(
212          sigc::mem_fun(*this, &RegionChooser::on_note_off_event)          sigc::mem_fun(*this, &RegionChooser::on_note_off_event)
213      );      );
214        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."));
215  }  }
216    
217  RegionChooser::~RegionChooser()  RegionChooser::~RegionChooser()
218  {  {
219  }  }
220    
221  template<class T> inline std::string ToString(T o) {  void RegionChooser::setModifyAllRegions(bool b) {
222      std::stringstream ss;      modifyallregions = b;
223      ss << o;      // redraw required parts
224      return ss.str();      queue_draw();
225  }  }
226    
227  void RegionChooser::invalidate_key(int key) {  void RegionChooser::invalidate_key(int key) {
# Line 219  bool RegionChooser::on_draw(const Cairo: Line 276  bool RegionChooser::on_draw(const Cairo:
276      Gdk::Cairo::set_source_rgba(cr, bg);      Gdk::Cairo::set_source_rgba(cr, bg);
277      cr->paint();      cr->paint();
278    
     const int w = get_width() - 1;  
   
279      if (clipy2 > h1) {      if (clipy2 > h1) {
280          draw_keyboard(cr, clipx1, clipx2);          draw_keyboard(cr, clipx1, clipx2);
281      }      }
# Line 319  void RegionChooser::draw_regions(const C Line 374  void RegionChooser::draw_regions(const C
374                  cr->line_to(x3, h1 - 0.5);                  cr->line_to(x3, h1 - 0.5);
375                  cr->stroke();                  cr->stroke();
376    
377                  Gdk::Cairo::set_source_rgba(cr, region == r ? red : white);                  if (region == r)
378                        Gdk::Cairo::set_source_rgba(cr, blue);
379                    else if (modifyallregions)
380                        cr->set_source(grayBlueHatchedSurfacePattern);
381                    else
382                        Gdk::Cairo::set_source_rgba(cr, white);
383    
384                  cr->rectangle(x3 + 1, 1, x2 - x3 - 1, h1 - 2);                  cr->rectangle(x3 + 1, 1, x2 - x3 - 1, h1 - 2);
385                  cr->fill();                  cr->fill();
386                  Gdk::Cairo::set_source_rgba(cr, black);                  Gdk::Cairo::set_source_rgba(cr, black);
# Line 330  void RegionChooser::draw_regions(const C Line 391  void RegionChooser::draw_regions(const C
391    
392      for (gig::Region* r = regions.first() ; r ; r = regions.next()) {      for (gig::Region* r = regions.first() ; r ; r = regions.next()) {
393          int x = key_to_x(r->KeyRange.low, w);          int x = key_to_x(r->KeyRange.low, w);
394            int x2 = key_to_x(r->KeyRange.high + 1, w);
395    
396            RegionFeatures features = regionFeatures(r);
397    
398            const bool bShowLoopSymbol = features.loops > 0;
399            const bool bShowSampleRefSymbol = features.sampleRefs < r->DimensionRegions;
400            if (bShowLoopSymbol || bShowSampleRefSymbol) {
401                const int margin = 2;
402                const int wRgn = x2 - x;
403                //printf("x=%d x2=%d wRgn=%d\n", x, x2, wRgn);
404    
405                cr->save();
406                cr->set_line_width(1);
407                cr->rectangle(x, 1, wRgn, h1 - 1);
408                cr->clip();
409                if (bShowSampleRefSymbol) {
410                    const int wPic = 8;
411                    const int hPic = 8;
412                    Gdk::Cairo::set_source_pixbuf(
413                        cr, (features.sampleRefs) ? yellowDot : redDot,
414                        x + (wRgn-wPic)/2.f,
415                        (bShowLoopSymbol) ? margin : (h1-hPic)/2.f
416                    );
417                    cr->paint();
418                }
419                if (bShowLoopSymbol) {
420                    const int wPic = 12;
421                    const int hPic = 14;
422                    Gdk::Cairo::set_source_pixbuf(
423                        cr, (features.loops == r->DimensionRegions) ? blackLoop : grayLoop,
424                        x + (wRgn-wPic)/2.f,
425                        (bShowSampleRefSymbol) ? h1 - hPic - margin : (h1-hPic)/2.f
426                    );
427                    cr->paint();
428                }
429                cr->restore();
430            }
431        }
432    
433        for (gig::Region* r = regions.first() ; r ; r = regions.next()) {
434            int x = key_to_x(r->KeyRange.low, w);
435    
436          if (x < clip_low) continue;          if (x < clip_low) continue;
437          if (x >= clip_high) break;          if (x >= clip_high) break;
# Line 338  void RegionChooser::draw_regions(const C Line 440  void RegionChooser::draw_regions(const C
440          cr->line_to(x + 0.5, h1 - 1);          cr->line_to(x + 0.5, h1 - 1);
441          cr->stroke();          cr->stroke();
442      }      }
443    
444        // if there is no region yet, show the user some hint text that he may
445        // right click on this area to create a new region
446        if (!regions.first()) {
447            Glib::RefPtr<Pango::Context> context = get_pango_context();
448            Glib::RefPtr<Pango::Layout> layout = Pango::Layout::create(context);
449            layout->set_alignment(Pango::ALIGN_CENTER);
450            layout->set_text(Glib::ustring("*** ") + _("Right click here to create a region.") + " ***");
451            layout->set_width(get_width() * Pango::SCALE);
452            //layout->set_height(get_height() * Pango::SCALE);
453            layout->set_spacing(10);
454            Gdk::Cairo::set_source_rgba(cr, blue);
455            // get the text dimensions
456            int text_width, text_height;
457            layout->get_pixel_size(text_width, text_height);
458            cr->move_to(0, (REGION_BLOCK_HEIGHT - text_height) / 2);
459    #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 16) || GTKMM_MAJOR_VERSION < 2
460            pango_cairo_show_layout(cr->cobj(), layout->gobj());
461    #else
462            layout->show_in_cairo_context(cr);
463    #endif
464        }
465  }  }
466    
467  bool RegionChooser::is_black_key(int key) {  bool RegionChooser::is_black_key(int key) {
# Line 500  void RegionChooser::update_after_resize( Line 624  void RegionChooser::update_after_resize(
624  void RegionChooser::update_after_move(int pos)  void RegionChooser::update_after_move(int pos)
625  {  {
626      instrument_struct_to_be_changed_signal.emit(instrument);      instrument_struct_to_be_changed_signal.emit(instrument);
627      region->SetKeyRange(pos, pos + region->KeyRange.high -      const int range = region->KeyRange.high - region->KeyRange.low;
628                          region->KeyRange.low);      const int diff  = pos - int(region->KeyRange.low);
629        region->SetKeyRange(pos, pos + range);
630        if (Settings::singleton()->moveRootNoteWithRegionMoved) {
631            for (int i = 0; i < 256; ++i) {
632                gig::DimensionRegion* dimrgn = region->pDimensionRegions[i];
633                if (!dimrgn || !dimrgn->pSample || !dimrgn->PitchTrack) continue;
634                dimrgn->UnityNote += diff;
635            }
636        }
637      regions.update(instrument);      regions.update(instrument);
638      instrument_changed.emit();      instrument_changed.emit();
639      instrument_struct_changed_signal.emit(instrument);      instrument_struct_changed_signal.emit(instrument);
# Line 523  bool RegionChooser::on_button_press_even Line 655  bool RegionChooser::on_button_press_even
655          }          }
656      }      }
657    
658        // left mouse button double click
659        if (event->type == GDK_2BUTTON_PRESS && event->button == 1) {
660            if (event->y < REGION_BLOCK_HEIGHT) {
661                // show dimension manager dialog for this region
662                manage_dimensions();
663            }
664        }
665    
666      if (event->y >= REGION_BLOCK_HEIGHT) return true;      if (event->y >= REGION_BLOCK_HEIGHT) return true;
667      if (event->type == GDK_BUTTON_PRESS && event->button == 3) {      if (event->type == GDK_BUTTON_PRESS && event->button == 3) {
668          gig::Region* r = get_region(k);          gig::Region* r = get_region(k);
# Line 598  gig::Region* RegionChooser::get_region(i Line 738  gig::Region* RegionChooser::get_region(i
738      return 0;      return 0;
739  }  }
740    
741    void RegionChooser::set_region(gig::Region* region) {
742        this->region = region;
743        queue_draw();
744        region_selected();
745        dimensionManager.set_region(region);
746    }
747    
748    void RegionChooser::select_next_region() {
749        if (!instrument) return;
750        if (!region) {
751            for (int i = 0; i < 128; ++i) {
752                ::gig::Region* rgn = instrument->GetRegion(i);
753                if (rgn) {
754                    set_region(rgn);
755                    return;
756                }
757            }
758        } else {
759            bool currentFound = false;
760            for (int i = 0; i < 128; ++i) {
761                ::gig::Region* rgn = instrument->GetRegion(i);
762                if (!rgn) continue;
763                if (currentFound) {
764                    if (rgn != region) {
765                        set_region(rgn);
766                        return;
767                    }
768                } else {
769                    if (rgn == region) currentFound = true;
770                }
771            }
772        }
773    }
774    
775    void RegionChooser::select_prev_region() {
776        if (!instrument) return;
777        if (!region) {
778            for (int i = 0; i < 128; ++i) {
779                ::gig::Region* rgn = instrument->GetRegion(i);
780                if (rgn) {
781                    set_region(rgn);
782                    return;
783                }
784            }
785        } else {
786            bool currentFound = false;
787            for (int i = 127; i >= 0; --i) {
788                ::gig::Region* rgn = instrument->GetRegion(i);
789                if (!rgn) continue;
790                if (currentFound) {
791                    if (rgn != region) {
792                        set_region(rgn);
793                        return;
794                    }
795                } else {
796                    if (rgn == region) currentFound = true;
797                }
798            }
799        }
800    }
801    
802  void RegionChooser::motion_resize_region(int x, int y)  void RegionChooser::motion_resize_region(int x, int y)
803  {  {
804      const int w = get_width() - 1;      const int w = get_width() - 1;
# Line 646  void RegionChooser::motion_resize_region Line 847  void RegionChooser::motion_resize_region
847    
848          update_after_resize();          update_after_resize();
849    
850          get_window()->invalidate_rect(rect, false);          //get_window()->invalidate_rect(rect, false);
851            get_window()->invalidate(false); // repaint entire region, otherwise it would create visual artifacts
852      }      }
853  }  }
854    
# Line 862  void RegionChooser::show_region_properti Line 1064  void RegionChooser::show_region_properti
1064      // add OK and CANCEL buttons to the dialog      // add OK and CANCEL buttons to the dialog
1065      dialog.add_button(Gtk::Stock::OK, 0);      dialog.add_button(Gtk::Stock::OK, 0);
1066      dialog.add_button(Gtk::Stock::CANCEL, 1);      dialog.add_button(Gtk::Stock::CANCEL, 1);
1067        dialog.set_position(Gtk::WIN_POS_MOUSE);
1068      dialog.show_all_children();      dialog.show_all_children();
1069      if (!dialog.run()) { // OK selected ...      if (!dialog.run()) { // OK selected ...
1070          region->KeyGroup =          region->KeyGroup =

Legend:
Removed from v.2246  
changed lines
  Added in v.3226

  ViewVC Help
Powered by ViewVC