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

Diff of /gigedit/trunk/src/regionchooser.cpp

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1053 by persson, Sat Mar 3 12:20:01 2007 UTC revision 1115 by schoenebeck, Sat Mar 24 00:22:13 2007 UTC
# Line 19  Line 19 
19    
20  #include "regionchooser.h"  #include "regionchooser.h"
21  #include <gdkmm/cursor.h>  #include <gdkmm/cursor.h>
22    #include <gtkmm/stock.h>
23    #include <gtkmm/spinbutton.h>
24    #include <gtkmm/dialog.h>
25    #include <libintl.h>
26    #include <math.h>
27    
28    #define _(String) gettext(String)
29    
30  RegionChooser::RegionChooser()  RegionChooser::RegionChooser()
31  {  {
# Line 39  RegionChooser::RegionChooser() Line 46  RegionChooser::RegionChooser()
46      colormap->alloc_color(grey1);      colormap->alloc_color(grey1);
47      instrument = 0;      instrument = 0;
48      region = 0;      region = 0;
49        resize.active = false;
50      add_events(Gdk::BUTTON_PRESS_MASK | Gdk::POINTER_MOTION_MASK);      cursor_is_resize = false;
51        h1 = 20;
52        width = 800;
53    
54        actionGroup = Gtk::ActionGroup::create();
55        actionGroup->add(Gtk::Action::create("Properties",
56                                             Gtk::Stock::PROPERTIES),
57                         sigc::mem_fun(*this,
58                                       &RegionChooser::show_region_properties));
59        actionGroup->add(Gtk::Action::create("Remove", Gtk::Stock::REMOVE),
60                         sigc::mem_fun(*this, &RegionChooser::delete_region));
61        actionGroup->add(Gtk::Action::create("Add", Gtk::Stock::ADD),
62                         sigc::mem_fun(*this, &RegionChooser::add_region));
63        actionGroup->add(Gtk::Action::create("Dimensions", _("Dimensions...")),
64                         sigc::mem_fun(*this, &RegionChooser::manage_dimensions));
65    
66        uiManager = Gtk::UIManager::create();
67        uiManager->insert_action_group(actionGroup);
68        Glib::ustring ui_info =
69            "<ui>"
70            "  <popup name='PopupMenuInsideRegion'>"
71            "    <menuitem action='Properties'/>"
72            "    <menuitem action='Dimensions'/>"
73            "    <menuitem action='Remove'/>"
74            "  </popup>"
75            "  <popup name='PopupMenuOutsideRegion'>"
76            "    <menuitem action='Add'/>"
77            "  </popup>"
78            "</ui>";
79        uiManager->add_ui_from_string(ui_info);
80    
81        popup_menu_inside_region = dynamic_cast<Gtk::Menu*>(
82            uiManager->get_widget("/PopupMenuInsideRegion"));
83        popup_menu_outside_region = dynamic_cast<Gtk::Menu*>(
84            uiManager->get_widget("/PopupMenuOutsideRegion"));
85    
86        add_events(Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK |
87                   Gdk::POINTER_MOTION_MASK | Gdk::POINTER_MOTION_HINT_MASK);
88    
89        dimensionManager.articulation_changed_signal.connect(
90            sigc::mem_fun(*this, &RegionChooser::on_dimension_manager_changed)
91        );
92  }  }
93    
94  RegionChooser::~RegionChooser()  RegionChooser::~RegionChooser()
# Line 62  bool RegionChooser::on_expose_event(GdkE Line 110  bool RegionChooser::on_expose_event(GdkE
110  {  {
111      Glib::RefPtr<Gdk::Window> window = get_window();      Glib::RefPtr<Gdk::Window> window = get_window();
112      window->clear();      window->clear();
     const int h1 = 20;  
113      const int h = 40;      const int h = 40;
114      const int w = 800 - 1;      const int w = width - 1;
115      const int bh = int(h * 0.55);      const int bh = int(h * 0.55);
116    
117      Glib::RefPtr<const Gdk::GC> black = get_style()->get_black_gc();      Glib::RefPtr<const Gdk::GC> black = get_style()->get_black_gc();
# Line 105  bool RegionChooser::on_expose_event(GdkE Line 152  bool RegionChooser::on_expose_event(GdkE
152                  window->draw_rectangle(white, true, x3 + 1, 1, x2 - x3 - 1, h1 - 2);                  window->draw_rectangle(white, true, x3 + 1, 1, x2 - x3 - 1, h1 - 2);
153                  x3 = -1;                  x3 = -1;
154              }              }
 //          draw_region(r->KeyRange.low, r->KeyRange.high + 1, i % 3 == 0 ? blue : i % 3 == 1 ? red : green);  
155              i++;              i++;
156          }          }
157    
# Line 135  void RegionChooser::on_size_request(GtkR Line 181  void RegionChooser::on_size_request(GtkR
181  }  }
182    
183    
184    // not used
185  void RegionChooser::draw_region(int from, int to, const Gdk::Color& color)  void RegionChooser::draw_region(int from, int to, const Gdk::Color& color)
186  {  {
     const int h1 = 20;  
187      const int h = 40;      const int h = 40;
188      const int w = 800;      const int w = width;
189      const int bh = int(h * 0.55);      const int bh = int(h * 0.55);
190    
191      Glib::RefPtr<Gdk::Window> window = get_window();      Glib::RefPtr<Gdk::Window> window = get_window();
# Line 175  void RegionChooser::draw_region(int from Line 221  void RegionChooser::draw_region(int from
221  void RegionChooser::set_instrument(gig::Instrument* instrument)  void RegionChooser::set_instrument(gig::Instrument* instrument)
222  {  {
223      this->instrument = instrument;      this->instrument = instrument;
224      region = instrument->GetFirstRegion();      region = instrument ? instrument->GetFirstRegion() : 0;
225      queue_draw();      queue_draw();
226      sel_changed_signal.emit();      sel_changed_signal.emit();
227  }  }
228    
229  void RegionChooser::set_region(gig::Region* region)  bool RegionChooser::on_button_release_event(GdkEventButton* event)
230  {  {
231      this->region = region;      if (resize.active) {
232      queue_draw();          get_window()->pointer_ungrab(event->time);
233            resize.active = false;
234    
235            if (resize.mode == resize.moving_high_limit) {
236                resize.region->KeyRange.high = resize.pos - 1;
237            } else if (resize.mode == resize.moving_low_limit) {
238                resize.region->KeyRange.low = resize.pos;
239            }
240    
241            if (!is_in_resize_zone(event->x, event->y) && cursor_is_resize) {
242                get_window()->set_cursor();
243                cursor_is_resize = false;
244            }
245        }
246        return true;
247  }  }
248    
249  bool RegionChooser::on_button_press_event(GdkEventButton* event)  bool RegionChooser::on_button_press_event(GdkEventButton* event)
250  {  {
251      const int w = 800 - 1;      if (!instrument) return true;
252    
253      if (instrument) {      int k = int(event->x / (width - 1) * 128.0);
254          int i = 0;  
255          for (gig::Region *r = instrument->GetFirstRegion() ;      if (event->type == GDK_BUTTON_PRESS && event->button == 3) {
256               r ;          gig::Region* r = get_region(k);
257               r = instrument->GetNextRegion()) {          if (r) {
258              int x = int(w * (r->KeyRange.low) / 128.0 + 0.5);              region = r;
259              int x2 = int(w * (r->KeyRange.high + 1) / 128.0 + 0.5);              queue_draw();
260              if (event->x >= x && event->x < x2) {              sel_changed_signal.emit();
261                popup_menu_inside_region->popup(event->button, event->time);
262            } else {
263                new_region_pos = k;
264                popup_menu_outside_region->popup(event->button, event->time);
265            }
266        } else {
267            if (is_in_resize_zone(event->x, event->y)) {
268                Gdk::Cursor double_arrow(Gdk::SB_H_DOUBLE_ARROW);
269                get_window()->pointer_grab(false,
270                                           Gdk::BUTTON_RELEASE_MASK |
271                                           Gdk::POINTER_MOTION_MASK |
272                                           Gdk::POINTER_MOTION_HINT_MASK,
273                                           double_arrow, event->time);
274                resize.active = true;
275            } else {
276                gig::Region* r = get_region(k);
277                if (r) {
278                  region = r;                  region = r;
279                  break;                  queue_draw();
280                    sel_changed_signal.emit();
281              }              }
             i++;  
282          }          }
         queue_draw();  
         sel_changed_signal.emit();  
283      }      }
284        return true;
285    }
286    
287    gig::Region* RegionChooser::get_region(int key)
288    {
289        for (gig::Region *r = instrument->GetFirstRegion() ; r ;
290             r = instrument->GetNextRegion()) {
291            if (key < r->KeyRange.low) return 0;
292            if (key <= r->KeyRange.high) return r;
293        }
294        return 0;
295  }  }
296    
 // muspekarexperiment. Fel eventhantering - se example_drawingarea.cc  
 bool inside = false;  
297  bool RegionChooser::on_motion_notify_event(GdkEventMotion* event)  bool RegionChooser::on_motion_notify_event(GdkEventMotion* event)
298  {  {
299      if (event->x > 100 && event->x < 120) {      const int w = width - 1;
300          if (!inside) {      Glib::RefPtr<Gdk::Window> window = get_window();
301              Gdk::Cursor oj(Gdk::CROSSHAIR);      int x, y;
302              get_window()->set_cursor(oj);      Gdk::ModifierType state = Gdk::ModifierType(0);
303              inside = true;      window->get_pointer(x, y, state);
304          }      if (resize.active) {
305      } else if (inside) {          int k = int(double(x) / w * 128.0 + 0.5);
306          get_window()->set_cursor();  
307          inside = false;          if (k < resize.min) k = resize.min;
308            else if (k > resize.max) k = resize.max;
309    
310            if (k != resize.pos) {
311                if (resize.mode == resize.undecided) {
312                    if (k < resize.pos) {
313                        // edit high limit of prev_region
314                        resize.max = resize.region->KeyRange.low;
315                        resize.region = resize.prev_region;
316                        resize.mode = resize.moving_high_limit;
317                    } else {
318                        // edit low limit of region
319                        resize.min = resize.prev_region->KeyRange.high + 1;
320                        resize.mode = resize.moving_low_limit;
321                    }
322                }
323                Glib::RefPtr<const Gdk::GC> black = get_style()->get_black_gc();
324                Glib::RefPtr<const Gdk::GC> white = get_style()->get_white_gc();
325                if (region == resize.region) {
326                    gc->set_foreground(red);
327                    white = gc;
328                }
329                Glib::RefPtr<const Gdk::GC> bg = get_style()->get_bg_gc(Gtk::STATE_NORMAL);
330                int prevx = int(w * resize.pos / 128.0 + 0.5);
331                x = int(w * k / 128.0 + 0.5);
332    
333                if (resize.mode == resize.moving_high_limit) {
334                    if (k > resize.pos) {
335                        window->draw_rectangle(white, true, prevx, 1, x - prevx, h1 - 2);
336                        window->draw_line(black, prevx, 0, x, 0);
337                        window->draw_line(black, prevx, h1 - 1, x, h1 - 1);
338                    } else {
339                        int xx = ((resize.pos == resize.max && resize.max != 128) ? 1 : 0);
340                        window->draw_rectangle(bg, true, x + 1, 0, prevx - x - xx, h1);
341                    }
342                } else {
343                    if (k < resize.pos) {
344                        window->draw_rectangle(white, true, x + 1, 1, prevx - x, h1 - 2);
345                        window->draw_line(black, x, 0, prevx, 0);
346                        window->draw_line(black, x, h1 - 1, prevx, h1 - 1);
347                    } else {
348                        int xx = ((resize.pos == resize.min && resize.min != 0) ? 1 : 0);
349                        window->draw_rectangle(bg, true, prevx + xx, 0, x - prevx - xx, h1);
350                    }
351                }
352                window->draw_line(black, x, 1, x, h1 - 2);
353                resize.pos = k;
354            }
355        } else {
356            if (is_in_resize_zone(x, y)) {
357                if (!cursor_is_resize) {
358                    Gdk::Cursor double_arrow(Gdk::SB_H_DOUBLE_ARROW);
359                    window->set_cursor(double_arrow);
360                    cursor_is_resize = true;
361                }
362            } else if (cursor_is_resize) {
363                window->set_cursor();
364                cursor_is_resize = false;
365            }
366      }      }
367    
368        return true;
369    }
370    
371    bool RegionChooser::is_in_resize_zone(double x, double y) {
372        const int w = width - 1;
373    
374        if (instrument && y >= 0 && y <= h1) {
375            gig::Region* prev_region = 0;
376            gig::Region* next_region;
377            for (gig::Region* r = instrument->GetFirstRegion() ; r ; r = next_region) {
378                next_region = instrument->GetNextRegion();
379    
380                int lo = int(w * (r->KeyRange.low) / 128.0 + 0.5);
381                if (x <= lo - 2) break;
382                if (x < lo + 2) {
383                    resize.region = r;
384                    resize.pos = r->KeyRange.low;
385                    resize.max = r->KeyRange.high;
386    
387                    if (prev_region && prev_region->KeyRange.high + 1 == r->KeyRange.low) {
388                        // we don't know yet if it's the high limit of
389                        // prev_region or the low limit of r that's going
390                        // to be edited
391                        resize.mode = resize.undecided;
392                        resize.min = prev_region->KeyRange.low + 1;
393                        resize.prev_region = prev_region;
394                        return true;
395                    }
396    
397                    // edit low limit
398                    resize.mode = resize.moving_low_limit;
399                    resize.min = prev_region ? prev_region->KeyRange.high + 1 : 0;
400                    return true;
401                }
402                if (!next_region || r->KeyRange.high + 1 != next_region->KeyRange.low) {
403                    int hi = int(w * (r->KeyRange.high + 1) / 128.0 + 0.5);
404                    if (x <= hi - 2) break;
405                    if (x < hi + 2) {
406                        // edit high limit
407                        resize.region = r;
408                        resize.pos = r->KeyRange.high + 1;
409                        resize.mode = resize.moving_high_limit;
410                        resize.min = r->KeyRange.low + 1;
411                        resize.max = next_region ? next_region->KeyRange.low : 128;
412                        return true;
413                    }
414                }
415                prev_region = r;
416            }
417        }
418        return false;
419  }  }
420    
421  sigc::signal<void> RegionChooser::signal_sel_changed()  sigc::signal<void> RegionChooser::signal_sel_changed()
422  {  {
423      return sel_changed_signal;      return sel_changed_signal;
424  }  }
425    
426    void RegionChooser::show_region_properties()
427    {
428        if (!region) return;
429        Gtk::Dialog dialog("Region Properties", true /*modal*/);
430        // add "Keygroup" checkbox
431        Gtk::CheckButton checkBoxKeygroup("Member of a Keygroup (Exclusive Group)");
432        checkBoxKeygroup.set_active(region->KeyGroup);
433        dialog.get_vbox()->pack_start(checkBoxKeygroup);
434        checkBoxKeygroup.show();
435        // add "Keygroup" spinbox
436        Gtk::Adjustment adjustment(1, 1, pow(2,32));
437        Gtk::SpinButton spinBox(adjustment);
438        if (region->KeyGroup) spinBox.set_value(region->KeyGroup);
439        dialog.get_vbox()->pack_start(spinBox);
440        spinBox.show();
441        // add OK and CANCEL buttons to the dialog
442        dialog.add_button(Gtk::Stock::OK, 0);
443        dialog.add_button(Gtk::Stock::CANCEL, 1);
444        dialog.show_all_children();
445        if (!dialog.run()) { // OK selected ...
446            region->KeyGroup =
447                (checkBoxKeygroup.get_active()) ? spinBox.get_value_as_int() : 0;
448        }
449    }
450    
451    void RegionChooser::add_region()
452    {
453        gig::Region* r;
454        for (r = instrument->GetFirstRegion() ; r ; r = instrument->GetNextRegion()) {
455            if (r->KeyRange.low > new_region_pos) break;
456        }
457    
458        region = instrument->AddRegion();
459        region->KeyRange.low = region->KeyRange.high = new_region_pos;
460    
461        instrument->MoveRegion(region, r);
462        queue_draw();
463        sel_changed_signal.emit();
464    }
465    
466    void RegionChooser::delete_region()
467    {
468        instrument->DeleteRegion(region);
469        region = 0;
470        queue_draw();
471        sel_changed_signal.emit();
472    }
473    
474    void RegionChooser::manage_dimensions()
475    {
476        gig::Region* region = get_region();
477        if (!region) return;
478        dimensionManager.show(region);
479    }
480    
481    void RegionChooser::on_dimension_manager_changed() {
482        sel_changed_signal.emit();
483    }

Legend:
Removed from v.1053  
changed lines
  Added in v.1115

  ViewVC Help
Powered by ViewVC