Optimize automation-event process splitting
[ardour.git] / gtk2_ardour / midi_scroomer.cc
1 /*
2     Copyright (C) 2008 Paul Davis
3
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17 */
18
19 #include <iostream>
20 #include <cairomm/context.h>
21
22 #include "midi_scroomer.h"
23 #include "ui_config.h"
24
25 using namespace Gtk;
26 using namespace std;
27
28 //std::map<int, Glib::RefPtr<Gdk::Pixmap> > MidiScroomer::piano_pixmaps;
29
30 MidiScroomer::MidiScroomer(Adjustment& adj)
31         : ArdourWidgets::Scroomer(adj)
32 {
33
34         adj.set_lower(0);
35         adj.set_upper(127);
36
37         /* set minimum view range to one octave */
38         set_min_page_size(12);
39 }
40
41 MidiScroomer::~MidiScroomer()
42 {
43 }
44
45 bool
46 MidiScroomer::on_expose_event(GdkEventExpose* ev)
47 {
48         Cairo::RefPtr<Cairo::Context> cc = get_window()->create_cairo_context();
49         GdkRectangle comp_rect, clip_rect;
50         Component first_comp = point_in(ev->area.y);
51         Component last_comp = point_in(ev->area.y + ev->area.height);
52         int height = get_height();
53         int lnote, hnote;
54         double y2note = (double) 127 / height;
55         double note2y = (double) height / 127;
56         double note_width = 0.8 * get_width();
57         double note_height = 1.4 * note2y;
58         double black_shift = 0.1 * note2y;
59         double colors[6] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f};
60
61         //cerr << ev->area.y << " " << ev->area.height << endl;
62
63         comp_rect.x = 0;
64         comp_rect.width = get_width();
65
66         for (int i = first_comp; i <= last_comp; ++i) {
67                 Component comp = (Component) i;
68                 set_comp_rect(comp_rect, comp);
69
70                 if (gdk_rectangle_intersect(&comp_rect, &ev->area, &clip_rect)) {
71                         get_colors(colors, comp);
72
73                         cc->rectangle(clip_rect.x, clip_rect.y, clip_rect.width, clip_rect.height);
74                         cc->set_source_rgb (colors[3], colors[4], colors[5]);
75                         cc->fill_preserve();
76                         cc->clip();
77
78                         cc->set_source_rgb(colors[0], colors[1], colors[2]);
79                         cc->set_line_width(note_height);
80
81                         lnote = 127 - (int) floor((double) (clip_rect.y + clip_rect.height) * y2note) - 1;
82                         hnote = 127 - (int) floor((double) clip_rect.y * y2note) + 1;
83
84                         for (int note = lnote; note < hnote + 1; ++note) {
85                                 double y = height - note * note2y;
86                                 bool draw = false;
87
88                                 switch (note % 12) {
89                                 case 1:
90                                 case 6:
91                                         y -= black_shift;
92                                         draw = true;
93                                         break;
94                                 case 3:
95                                 case 10:
96                                         y += black_shift;
97                                         draw = true;
98                                         break;
99                                 case 8:
100                                         draw = true;
101                                         break;
102                                 default:
103                                         break;
104                                 }
105
106                                 if(draw) {
107                                         cc->set_line_width(1.4 * note2y);
108                                         cc->move_to(0, y);
109                                         cc->line_to(note_width, y);
110                                         cc->stroke();
111                                 }
112                         }
113
114                         if (i == Handle1 || i == Handle2) {
115                                 cc->rectangle(comp_rect.x + 0.5f, comp_rect.y + 0.5f, comp_rect.width - 1.0f, comp_rect.height - 1.0f);
116                                 cc->set_line_width(1.0f);
117                                 cc->set_source_rgb (1.0f, 1.0f, 1.0f);
118                                 cc->stroke();
119                         }
120
121                         cc->reset_clip();
122                 }
123         }
124
125         return true;
126 }
127
128 void
129 MidiScroomer::get_colors(double color[], Component comp)
130 {
131         switch (comp) {
132         case TopBase:
133         case BottomBase:
134                 color[0] = 0.24f;
135                 color[1] = 0.24f;
136                 color[2] = 0.24f;
137                 color[3] = 0.33f;
138                 color[4] = 0.33f;
139                 color[5] = 0.33f;
140                 break;
141         case Handle1:
142         case Handle2:
143                 color[0] = 0.91f;
144                 color[1] = 0.91f;
145                 color[2] = 0.91f;
146                 color[3] = 0.0f;
147                 color[4] = 0.0f;
148                 color[5] = 0.0f;
149                 break;
150         case Slider:
151                 color[0] = 0.38f;
152                 color[1] = 0.38f;
153                 color[2] = 0.38f;
154                 color[3] = 0.77f;
155                 color[4] = 0.77f;
156                 color[5] = 0.77f;
157                 break;
158         default:
159                 break;
160         }
161 }
162
163 void
164 MidiScroomer::on_size_request(Gtk::Requisition* r)
165 {
166         r->width = std::max (12.f, rintf (12.f * UIConfiguration::instance().get_ui_scale()));
167 }