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

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

Parent Directory Parent Directory | Revision Log Revision Log


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

1 persson 1052 /*
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 persson 1078 double maxwidth = 0;
81 persson 1052 for (int i = 0 ; i < region->Dimensions ; i++) {
82 persson 1071
83     int nbZones = region->pDimensionDefinitions[i].zones;
84     if (nbZones) {
85 persson 1052 char* dstr;
86 persson 1071 char dstrbuf[10];
87 persson 1052 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 persson 1077 case gig::dimension_smartmidi: dstr="smartmidi"; break;
98     case gig::dimension_roundrobinkeyboard: dstr="roundrobinkeyboard"; break;
99 persson 1052 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 persson 1071 default:
123     sprintf(dstrbuf, "%d",
124     region->pDimensionDefinitions[i].dimension);
125     dstr = dstrbuf;
126     break;
127 persson 1052 }
128     layout->set_text(dstr);
129    
130     Pango::Rectangle rectangle = layout->get_logical_extents();
131 persson 1078 double text_w = double(rectangle.get_width()) / Pango::SCALE;
132     if (text_w > maxwidth) maxwidth = text_w;
133 persson 1052 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 persson 1078 }
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 persson 1052 if (has_focus() && focus_line == i) {
148 persson 1078 Gdk::Rectangle farea(0, y, 150, 20);
149     get_style()->paint_focus(window, get_state(), farea, *this, "", 0, y, label_width, 20);
150 persson 1052 }
151    
152     Glib::RefPtr<const Gdk::GC> black = get_style()->get_black_gc();
153 persson 1078 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 persson 1052
157 persson 1071 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 persson 1078 window->draw_line(black, label_width, y + 1, label_width, y + h - 2);
170 persson 1071 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 persson 1078 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 persson 1052 }
178     } else {
179 persson 1071 for (int j = 0 ; j <= nbZones ; j++) {
180 persson 1078 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 persson 1052 }
183     }
184    
185     if (dimregno >= 0) {
186     gc->set_foreground(red);
187 persson 1071 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 persson 1078 int x2 = int((w - label_width - 1) * v / 128.0 + 0.5);
196 persson 1071 if (j == dr && x1 < x2) {
197 persson 1078 window->draw_rectangle(gc, true, label_width + x1 + 1, y + 1, (x2 - x1) - 1, h - 2);
198 persson 1052 break;
199     }
200     x1 = x2;
201     }
202     } else {
203 persson 1071 if (dr < nbZones) {
204 persson 1078 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 persson 1052 }
208     }
209     }
210    
211     y += h;
212     }
213 persson 1071 bitpos += region->pDimensionDefinitions[i].bits;
214 persson 1052 }
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 persson 1089 requisition->height = region ? nbDimensions * 20 : 0;
225 persson 1052 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 persson 1089 nbDimensions = 0;
242 persson 1052 for (int dim = 0 ; dim < region->Dimensions ; dim++) {
243 persson 1089 if (region->pDimensionDefinitions[dim].bits == 0) continue;
244     nbDimensions++;
245    
246 persson 1052 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 persson 1089 if (event->y < nbDimensions * h &&
283 persson 1078 event->x >= label_width && event->x < w) {
284 persson 1052
285 persson 1089 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 persson 1071 int nbZones = region->pDimensionDefinitions[dim].zones;
293 persson 1052
294     int z = -1;
295 persson 1071 int bitpos = 0;
296     for (int i = 0 ; i < dim ; i++) {
297     bitpos += region->pDimensionDefinitions[i].bits;
298     }
299 persson 1052
300 persson 1071 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 persson 1052
305 persson 1071 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 persson 1078 int val = int((event->x - label_width) * 128 / (w - label_width - 1));
312 persson 1071
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 persson 1052 }
318 persson 1071 } 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 persson 1052 }
324 persson 1071 } else {
325 persson 1078 z = int((event->x - label_width) * nbZones / (w - label_width - 1));
326 persson 1052 }
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 persson 1071 #if 0
334 persson 1052 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 persson 1071 #endif
347 persson 1052
348 persson 1071 dimregno = c | (z << bitpos);
349 persson 1052
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