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"
26 #include "ardour_ui.h"
27 #include "midi_region_view.h"
28 #include "canvas_patch_change.h"
30 #include "editor_drag.h"
32 using namespace Gnome::Canvas
;
33 using namespace MIDI::Name
;
36 /** @param x x position in pixels.
38 CanvasPatchChange::CanvasPatchChange(
39 MidiRegionView
& region
,
46 string
& custom_device_mode
,
47 ARDOUR::MidiModel::PatchChangePtr patch
)
52 ARDOUR_UI::config()->canvasvar_MidiPatchChangeOutline
.get(),
53 ARDOUR_UI::config()->canvasvar_MidiPatchChangeFill
.get(),
56 , _model_name(model_name
)
57 , _custom_device_mode(custom_device_mode
)
59 , _popup_initialized(false)
64 CanvasPatchChange::~CanvasPatchChange()
69 CanvasPatchChange::initialize_popup_menus()
71 boost::shared_ptr
<ChannelNameSet
> channel_name_set
=
72 MidiPatchManager::instance()
73 .find_channel_name_set(_model_name
, _custom_device_mode
, _patch
->channel());
75 if (!channel_name_set
) {
79 const ChannelNameSet::PatchBanks
& patch_banks
= channel_name_set
->patch_banks();
82 Gtk::Menu::MenuList
& patch_bank_menus
= _popup
.items();
84 for (ChannelNameSet::PatchBanks::const_iterator bank
= patch_banks
.begin();
85 bank
!= patch_banks
.end();
87 Glib::RefPtr
<Glib::Regex
> underscores
= Glib::Regex::create("_");
88 std::string
replacement(" ");
90 Gtk::Menu
& patch_bank_menu
= *manage(new Gtk::Menu());
92 const PatchBank::PatchNameList
& patches
= (*bank
)->patch_name_list();
93 Gtk::Menu::MenuList
& patch_menus
= patch_bank_menu
.items();
95 for (PatchBank::PatchNameList::const_iterator patch
= patches
.begin();
96 patch
!= patches
.end();
98 std::string name
= underscores
->replace((*patch
)->name().c_str(), -1, 0, replacement
);
100 patch_menus
.push_back(
101 Gtk::Menu_Helpers::MenuElem(
104 sigc::mem_fun(*this, &CanvasPatchChange::on_patch_menu_selected
),
105 (*patch
)->patch_primary_key())) );
109 std::string name
= underscores
->replace((*bank
)->name().c_str(), -1, 0, replacement
);
111 patch_bank_menus
.push_back(
112 Gtk::Menu_Helpers::MenuElem(
119 CanvasPatchChange::on_patch_menu_selected(const PatchPrimaryKey
& key
)
121 cerr
<< " got patch program number " << key
.program_number
<< endl
;
122 _region
.change_patch_change (*this, key
);
126 CanvasPatchChange::on_event (GdkEvent
* ev
)
129 case GDK_BUTTON_PRESS
:
131 /* XXX: icky dcast */
132 Editor
* e
= dynamic_cast<Editor
*> (&_region
.get_time_axis_view().editor());
133 if (e
->current_mouse_mode() == Editing::MouseObject
&& e
->internal_editing()) {
135 if (Gtkmm2ext::Keyboard::is_delete_event (&ev
->button
)) {
137 _region
.delete_patch_change (this);
140 } else if (Gtkmm2ext::Keyboard::is_edit_event (&ev
->button
)) {
142 _region
.edit_patch_change (this);
145 } else if (ev
->button
.button
== 1) {
146 e
->drags()->set (new PatchChangeDrag (e
, this, &_region
), ev
);
151 if (ev
->button
.button
== 3) {
152 if (!_popup_initialized
) {
153 initialize_popup_menus();
154 _popup_initialized
= true;
156 _popup
.popup(ev
->button
.button
, ev
->button
.time
);
163 switch (ev
->key
.keyval
) {
167 _region
.previous_patch (*this);
172 _region
.next_patch (*this);
180 if (ev
->scroll
.direction
== GDK_SCROLL_UP
) {
181 _region
.previous_patch (*this);
183 } else if (ev
->scroll
.direction
== GDK_SCROLL_DOWN
) {
184 _region
.next_patch (*this);
189 case GDK_ENTER_NOTIFY
:
190 _region
.patch_entered (this);
193 case GDK_LEAVE_NOTIFY
:
194 _region
.patch_left (this);