2 Copyright (C) 2000-2010 Paul Davis
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.
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.
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.
22 #include <glibmm/regex.h>
24 #include "gtkmm2ext/keyboard.h"
25 #include "ardour/midi_patch_manager.h"
27 #include "ardour_ui.h"
28 #include "midi_region_view.h"
29 #include "canvas_patch_change.h"
31 #include "editor_drag.h"
33 using namespace Gnome::Canvas
;
34 using namespace MIDI::Name
;
35 using namespace Gtkmm2ext
;
38 /** @param x x position in pixels.
40 CanvasPatchChange::CanvasPatchChange(
41 MidiRegionView
& region
,
48 string
& custom_device_mode
,
49 ARDOUR::MidiModel::PatchChangePtr patch
)
54 ARDOUR_UI::config()->canvasvar_MidiPatchChangeOutline
.get(),
55 ARDOUR_UI::config()->canvasvar_MidiPatchChangeFill
.get(),
58 , _model_name(model_name
)
59 , _custom_device_mode(custom_device_mode
)
61 , _popup_initialized(false)
66 CanvasPatchChange::~CanvasPatchChange()
71 CanvasPatchChange::initialize_popup_menus()
73 boost::shared_ptr
<ChannelNameSet
> channel_name_set
=
74 MidiPatchManager::instance()
75 .find_channel_name_set(_model_name
, _custom_device_mode
, _patch
->channel());
77 if (!channel_name_set
) {
81 const ChannelNameSet::PatchBanks
& patch_banks
= channel_name_set
->patch_banks();
84 Gtk::Menu::MenuList
& patch_bank_menus
= _popup
.items();
86 for (ChannelNameSet::PatchBanks::const_iterator bank
= patch_banks
.begin();
87 bank
!= patch_banks
.end();
89 Glib::RefPtr
<Glib::Regex
> underscores
= Glib::Regex::create("_");
90 std::string
replacement(" ");
92 Gtk::Menu
& patch_bank_menu
= *manage(new Gtk::Menu());
94 const PatchBank::PatchNameList
& patches
= (*bank
)->patch_name_list();
95 Gtk::Menu::MenuList
& patch_menus
= patch_bank_menu
.items();
97 for (PatchBank::PatchNameList::const_iterator patch
= patches
.begin();
98 patch
!= patches
.end();
100 std::string name
= underscores
->replace((*patch
)->name().c_str(), -1, 0, replacement
);
102 patch_menus
.push_back(
103 Gtk::Menu_Helpers::MenuElem(
106 sigc::mem_fun(*this, &CanvasPatchChange::on_patch_menu_selected
),
107 (*patch
)->patch_primary_key())) );
111 std::string name
= underscores
->replace((*bank
)->name().c_str(), -1, 0, replacement
);
113 patch_bank_menus
.push_back(
114 Gtk::Menu_Helpers::MenuElem(
121 CanvasPatchChange::on_patch_menu_selected(const PatchPrimaryKey
& key
)
123 _region
.change_patch_change (*this, key
);
127 CanvasPatchChange::on_event (GdkEvent
* ev
)
130 case GDK_BUTTON_PRESS
:
132 /* XXX: icky dcast */
133 Editor
* e
= dynamic_cast<Editor
*> (&_region
.get_time_axis_view().editor());
134 if (e
->current_mouse_mode() == Editing::MouseObject
&& e
->internal_editing()) {
136 if (Gtkmm2ext::Keyboard::is_delete_event (&ev
->button
)) {
138 _region
.delete_patch_change (this);
141 } else if (Gtkmm2ext::Keyboard::is_edit_event (&ev
->button
)) {
143 _region
.edit_patch_change (this);
146 } else if (ev
->button
.button
== 1) {
147 e
->drags()->set (new PatchChangeDrag (e
, this, &_region
), ev
);
152 if (ev
->button
.button
== 3) {
153 if (!_popup_initialized
) {
154 initialize_popup_menus();
155 _popup_initialized
= true;
157 if (!_popup
.items().empty()) {
158 _popup
.popup(ev
->button
.button
, ev
->button
.time
);
166 switch (ev
->key
.keyval
) {
170 if (Keyboard::modifier_state_contains (ev
->scroll
.state
, Keyboard::PrimaryModifier
)) {
171 _region
.previous_bank (*this);
173 _region
.previous_patch (*this);
179 if (Keyboard::modifier_state_contains (ev
->scroll
.state
, Keyboard::PrimaryModifier
)) {
180 _region
.next_bank (*this);
182 _region
.next_patch (*this);
191 if (ev
->scroll
.direction
== GDK_SCROLL_UP
) {
192 if (Keyboard::modifier_state_contains (ev
->scroll
.state
, Keyboard::PrimaryModifier
)) {
193 _region
.previous_bank (*this);
195 _region
.previous_patch (*this);
198 } else if (ev
->scroll
.direction
== GDK_SCROLL_DOWN
) {
199 if (Keyboard::modifier_state_contains (ev
->scroll
.state
, Keyboard::PrimaryModifier
)) {
200 _region
.next_bank (*this);
202 _region
.next_patch (*this);
208 case GDK_ENTER_NOTIFY
:
209 _region
.patch_entered (this);
212 case GDK_LEAVE_NOTIFY
:
213 _region
.patch_left (this);