/[svn]/gigedit/trunk/src/dimregionchooser.cpp
ViewVC logotype

Contents of /gigedit/trunk/src/dimregionchooser.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1089 - (show annotations) (download)
Sat Mar 10 08:58:30 2007 UTC (13 years, 4 months ago) by persson
File size: 16020 byte(s)
* handle strange gigs with unused dimensions with bits == 0

1 /*
2 * Copyright (C) 2006, 2007 Andreas Persson
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2, or (at
7 * your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with program; see the file COPYING. If not, write to the Free
16 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
17 * 02110-1301 USA.
18 */
19
20 #include "dimregionchooser.h"
21
22 DimRegionChooser::DimRegionChooser()
23 {
24 // get_window() would return 0 because the Gdk::Window has not yet been realized
25 // So we can only allocate the colors here - the rest will happen in on_realize().
26 Glib::RefPtr<Gdk::Colormap> colormap = get_default_colormap();
27
28 black = Gdk::Color("black");
29 white = Gdk::Color("white");
30 red = Gdk::Color("#8070ff");
31 blue = Gdk::Color("blue");
32 green = Gdk::Color("green");
33
34 colormap->alloc_color(black);
35 colormap->alloc_color(white);
36 colormap->alloc_color(red);
37 colormap->alloc_color(blue);
38 colormap->alloc_color(green);
39 instrument = 0;
40 region = 0;
41 dimregno = -1;
42 focus_line = 0;
43 set_flags(Gtk::CAN_FOCUS);
44 add_events(Gdk::BUTTON_PRESS_MASK);
45
46 for (int i = 0 ; i < 256 ; i++) {
47 dimvalue_from[i] = 0;
48 dimvalue_to[i] = 1;
49 }
50 }
51
52 DimRegionChooser::~DimRegionChooser()
53 {
54 }
55
56 void DimRegionChooser::on_realize()
57 {
58 // We need to call the base on_realize()
59 Gtk::DrawingArea::on_realize();
60
61 // Now we can allocate any additional resources we need
62 Glib::RefPtr<Gdk::Window> window = get_window();
63 gc = Gdk::GC::create(window);
64 }
65
66 bool DimRegionChooser::on_expose_event(GdkEventExpose* event)
67 {
68 if (!region) return true;
69
70 // This is where we draw on the window
71 Glib::RefPtr<Gdk::Window> window = get_window();
72 Glib::RefPtr<Pango::Context> context = get_pango_context();
73
74 Glib::RefPtr<Pango::Layout> layout = Pango::Layout::create(context);
75
76 window->clear();
77 const int h = 20;
78 const int w = 800;
79 int y = 0;
80 double maxwidth = 0;
81 for (int i = 0 ; i < region->Dimensions ; i++) {
82
83 int nbZones = region->pDimensionDefinitions[i].zones;
84 if (nbZones) {
85 char* dstr;
86 char dstrbuf[10];
87 switch (region->pDimensionDefinitions[i].dimension) {
88 case gig::dimension_none: dstr="none"; break;
89 case gig::dimension_samplechannel: dstr="samplechannel"; break;
90 case gig::dimension_layer: dstr="layer"; break;
91 case gig::dimension_velocity: dstr="velocity"; break;
92 case gig::dimension_channelaftertouch: dstr="channelaftertouch"; break;
93 case gig::dimension_releasetrigger: dstr="releasetrigger"; break;
94 case gig::dimension_keyboard: dstr="keyboard"; break;
95 case gig::dimension_roundrobin: dstr="roundrobin"; break;
96 case gig::dimension_random: dstr="random"; break;
97 case gig::dimension_smartmidi: dstr="smartmidi"; break;
98 case gig::dimension_roundrobinkeyboard: dstr="roundrobinkeyboard"; break;
99 case gig::dimension_modwheel: dstr="modwheel"; break;
100 case gig::dimension_breath: dstr="breath"; break;
101 case gig::dimension_foot: dstr="foot"; break;
102 case gig::dimension_portamentotime: dstr="portamentotime"; break;
103 case gig::dimension_effect1: dstr="effect1"; break;
104 case gig::dimension_effect2: dstr="effect2"; break;
105 case gig::dimension_genpurpose1: dstr="genpurpose1"; break;
106 case gig::dimension_genpurpose2: dstr="genpurpose2"; break;
107 case gig::dimension_genpurpose3: dstr="genpurpose3"; break;
108 case gig::dimension_genpurpose4: dstr="genpurpose4"; break;
109 case gig::dimension_sustainpedal: dstr="sustainpedal"; break;
110 case gig::dimension_portamento: dstr="portamento"; break;
111 case gig::dimension_sostenutopedal: dstr="sostenutopedal"; break;
112 case gig::dimension_softpedal: dstr="softpedal"; break;
113 case gig::dimension_genpurpose5: dstr="genpurpose5"; break;
114 case gig::dimension_genpurpose6: dstr="genpurpose6"; break;
115 case gig::dimension_genpurpose7: dstr="genpurpose7"; break;
116 case gig::dimension_genpurpose8: dstr="genpurpose8"; break;
117 case gig::dimension_effect1depth: dstr="effect1depth"; break;
118 case gig::dimension_effect2depth: dstr="effect2depth"; break;
119 case gig::dimension_effect3depth: dstr="effect3depth"; break;
120 case gig::dimension_effect4depth: dstr="effect4depth"; break;
121 case gig::dimension_effect5depth: dstr="effect5depth"; break;
122 default:
123 sprintf(dstrbuf, "%d",
124 region->pDimensionDefinitions[i].dimension);
125 dstr = dstrbuf;
126 break;
127 }
128 layout->set_text(dstr);
129
130 Pango::Rectangle rectangle = layout->get_logical_extents();
131 double text_w = double(rectangle.get_width()) / Pango::SCALE;
132 if (text_w > maxwidth) maxwidth = text_w;
133 double text_h = double(rectangle.get_height()) / Pango::SCALE;
134 Glib::RefPtr<const Gdk::GC> fg = get_style()->get_fg_gc(get_state());
135 window->draw_layout(fg, 4, int(y + (h - text_h) / 2 + 0.5), layout);
136
137 }
138 y += h;
139 }
140 y = 0;
141 int bitpos = 0;
142 label_width = int(maxwidth + 10);
143 for (int i = 0 ; i < region->Dimensions ; i++) {
144 int nbZones = region->pDimensionDefinitions[i].zones;
145 if (nbZones) {
146
147 if (has_focus() && focus_line == i) {
148 Gdk::Rectangle farea(0, y, 150, 20);
149 get_style()->paint_focus(window, get_state(), farea, *this, "", 0, y, label_width, 20);
150 }
151
152 Glib::RefPtr<const Gdk::GC> black = get_style()->get_black_gc();
153 window->draw_line(black, label_width, y, w - 1, y);
154 window->draw_line(black, w - 1, y + h - 1, label_width, y + h - 1);
155 window->draw_rectangle(get_style()->get_white_gc(), true, label_width + 1, y + 1, (w - label_width - 2), h - 2);
156
157 int c = 0;
158 if (dimregno >= 0) {
159 int mask = ~(((1 << region->pDimensionDefinitions[i].bits) - 1) << bitpos);
160 c = dimregno & mask; // mask away this dimension
161 }
162 bool customsplits =
163 ((region->pDimensionDefinitions[i].split_type == gig::split_type_normal &&
164 region->pDimensionRegions[c]->DimensionUpperLimits[i]) ||
165 (region->pDimensionDefinitions[i].dimension == gig::dimension_velocity &&
166 region->pDimensionRegions[c]->VelocityUpperLimit));
167
168 if (customsplits) {
169 window->draw_line(black, label_width, y + 1, label_width, y + h - 2);
170 for (int j = 0 ; j < nbZones ; j++) {
171 gig::DimensionRegion *d = region->pDimensionRegions[c + (j << bitpos)];
172 int upperLimit = d->DimensionUpperLimits[i];
173 if (!upperLimit) upperLimit = d->VelocityUpperLimit;
174 int v = upperLimit + 1;
175 int x = int((w - label_width - 1) * v / 128.0 + 0.5);
176 window->draw_line(black, label_width + x, y + 1, label_width + x, y + h - 2);
177 }
178 } else {
179 for (int j = 0 ; j <= nbZones ; j++) {
180 int x = int((w - label_width - 1) * j / double(nbZones) + 0.5);
181 window->draw_line(black, label_width + x, y + 1, label_width + x, y + h - 2);
182 }
183 }
184
185 if (dimregno >= 0) {
186 gc->set_foreground(red);
187 int dr = (dimregno >> bitpos) & ((1 << region->pDimensionDefinitions[i].bits) - 1);
188 if (customsplits) {
189 int x1 = 0;
190 for (int j = 0 ; j < nbZones ; j++) {
191 gig::DimensionRegion *d = region->pDimensionRegions[c + (j << bitpos)];
192 int upperLimit = d->DimensionUpperLimits[i];
193 if (!upperLimit) upperLimit = d->VelocityUpperLimit;
194 int v = upperLimit + 1;
195 int x2 = int((w - label_width - 1) * v / 128.0 + 0.5);
196 if (j == dr && x1 < x2) {
197 window->draw_rectangle(gc, true, label_width + x1 + 1, y + 1, (x2 - x1) - 1, h - 2);
198 break;
199 }
200 x1 = x2;
201 }
202 } else {
203 if (dr < nbZones) {
204 int x1 = int((w - label_width - 1) * dr / double(nbZones) + 0.5);
205 int x2 = int((w - label_width - 1) * (dr + 1) / double(nbZones) + 0.5);
206 window->draw_rectangle(gc, true, label_width + x1 + 1, y + 1, (x2 - x1) - 1, h - 2);
207 }
208 }
209 }
210
211 y += h;
212 }
213 bitpos += region->pDimensionDefinitions[i].bits;
214 }
215
216 return true;
217 }
218
219
220 void DimRegionChooser::on_size_request(GtkRequisition* requisition)
221 {
222 printf("DimRegionChooser::on_size_request\n");
223 *requisition = GtkRequisition();
224 requisition->height = region ? nbDimensions * 20 : 0;
225 requisition->width = 800;
226 }
227
228 void DimRegionChooser::set_instrument(gig::Instrument* instrument)
229 {
230 this->instrument = instrument;
231 this->region = 0;
232 this->dimregno = -1;
233 queue_draw();
234 }
235
236 void DimRegionChooser::set_region(gig::Region* region)
237 {
238 this->region = region;
239 dimregno = 0;
240 int bitcount = 0;
241 nbDimensions = 0;
242 for (int dim = 0 ; dim < region->Dimensions ; dim++) {
243 if (region->pDimensionDefinitions[dim].bits == 0) continue;
244 nbDimensions++;
245
246 int from = dimvalue_from[region->pDimensionDefinitions[dim].dimension];
247 int to = dimvalue_to[region->pDimensionDefinitions[dim].dimension];
248 int z;
249 switch (region->pDimensionDefinitions[dim].split_type) {
250 case gig::split_type_normal:
251 z = int((to + from) / 2.0 / region->pDimensionDefinitions[dim].zone_size);
252 break;
253 case gig::split_type_bit:
254 z = std::min(from, region->pDimensionDefinitions[dim].zones - 1);
255 break;
256 }
257 int mask =
258 ~(((1 << region->pDimensionDefinitions[dim].bits) - 1) <<
259 bitcount);
260 dimregno &= mask;
261 dimregno |= (z << bitcount);
262 bitcount += region->pDimensionDefinitions[dim].bits;
263 }
264 dimreg = region->pDimensionRegions[dimregno];
265 sel_changed_signal.emit();
266 queue_resize();
267 }
268
269 /*
270 void DimRegionChooser::set_dimregno(int x) {
271 this->dimregno = x;
272 queue_draw();
273 }
274 */
275
276 bool DimRegionChooser::on_button_press_event(GdkEventButton* event)
277 {
278 const int h = 20;
279 const int w = 800;
280
281 if (region) {
282 if (event->y < nbDimensions * h &&
283 event->x >= label_width && event->x < w) {
284
285 int ydim = int(event->y / h);
286 int dim;
287 for (dim = 0 ; dim < region->Dimensions ; dim++) {
288 if (region->pDimensionDefinitions[dim].bits == 0) continue;
289 if (ydim == 0) break;
290 ydim--;
291 }
292 int nbZones = region->pDimensionDefinitions[dim].zones;
293
294 int z = -1;
295 int bitpos = 0;
296 for (int i = 0 ; i < dim ; i++) {
297 bitpos += region->pDimensionDefinitions[i].bits;
298 }
299
300 int i = dim;
301 if (dimregno < 0) dimregno = 0;
302 int mask = ~(((1 << region->pDimensionDefinitions[i].bits) - 1) << bitpos);
303 int c = dimregno & mask; // mask away this dimension
304
305 bool customsplits =
306 ((region->pDimensionDefinitions[i].split_type == gig::split_type_normal &&
307 region->pDimensionRegions[c]->DimensionUpperLimits[i]) ||
308 (region->pDimensionDefinitions[i].dimension == gig::dimension_velocity &&
309 region->pDimensionRegions[c]->VelocityUpperLimit));
310 if (customsplits) {
311 int val = int((event->x - label_width) * 128 / (w - label_width - 1));
312
313 if (region->pDimensionRegions[c]->DimensionUpperLimits[i]) {
314 for (z = 0 ; z < nbZones ; z++) {
315 gig::DimensionRegion *d = region->pDimensionRegions[c + (z << bitpos)];
316 if (val <= d->DimensionUpperLimits[i]) break;
317 }
318 } else {
319 for (z = 0 ; z < nbZones ; z++) {
320 gig::DimensionRegion *d = region->pDimensionRegions[c + (z << bitpos)];
321 if (val <= d->VelocityUpperLimit) break;
322 }
323 }
324 } else {
325 z = int((event->x - label_width) * nbZones / (w - label_width - 1));
326 }
327
328 printf("dim=%d z=%d dimensionsource=%d split_type=%d zones=%d zone_size=%f\n", dim, z,
329 region->pDimensionDefinitions[dim].dimension,
330 region->pDimensionDefinitions[dim].split_type,
331 region->pDimensionDefinitions[dim].zones,
332 region->pDimensionDefinitions[dim].zone_size);
333 #if 0
334 switch (region->pDimensionDefinitions[dim].split_type) {
335 case gig::split_type_normal:
336 dimvalue_from[region->pDimensionDefinitions[dim].dimension] =
337 int(z * region->pDimensionDefinitions[dim].zone_size);
338 dimvalue_to[region->pDimensionDefinitions[dim].dimension] =
339 int((z + 1) * region->pDimensionDefinitions[dim].zone_size) - 1;
340 break;
341 case gig::split_type_bit:
342 dimvalue_from[region->pDimensionDefinitions[dim].dimension] = z;
343 dimvalue_to[region->pDimensionDefinitions[dim].dimension] = z + 1;
344 break;
345 }
346 #endif
347
348 dimregno = c | (z << bitpos);
349
350 focus_line = dim;
351 if (has_focus()) queue_draw();
352 else grab_focus();
353 dimreg = region->pDimensionRegions[dimregno];
354 sel_changed_signal.emit();
355 }
356 }
357 return true;
358 }
359
360 sigc::signal<void> DimRegionChooser::signal_sel_changed()
361 {
362 return sel_changed_signal;
363 }
364
365 bool DimRegionChooser::on_focus(Gtk::DirectionType direction)
366 {
367 // TODO: kolla att region finns osv, dvs att det g�r att s�tta
368 // fokus.
369 if (direction == Gtk::DIR_TAB_FORWARD ||
370 direction == Gtk::DIR_DOWN) {
371 if (!has_focus()) {
372 focus_line = 0;
373 grab_focus();
374 return true;
375 } else {
376 if (focus_line + 1 < region->Dimensions) {
377 focus_line++;
378 queue_draw();
379 return true;
380 } else {
381 return false;
382 }
383 }
384 } else if (direction == Gtk::DIR_TAB_BACKWARD ||
385 direction == Gtk::DIR_UP) {
386 if (!has_focus()) {
387 focus_line = region->Dimensions - 1;
388 grab_focus();
389 return true;
390 } else {
391 if (focus_line > 0) {
392 focus_line--;
393 queue_draw();
394 return true;
395 } else {
396 return false;
397 }
398 }
399 } else if (!has_focus()) {
400 // TODO: kolla att focus_line finns!
401 grab_focus();
402 return true;
403 } else {
404 // TODO: �ka eller minska v�rde!
405 }
406 }

  ViewVC Help
Powered by ViewVC