/* This file is part of Ingen. * Copyright (C) 2007-2009 Dave Robillard * * Ingen is free software; you can redistribute it and/or modify it under the * terms of the GNU General Public License as published by the Free Software * Foundation; either version 2 of the License, or (at your option) any later * version. * * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "ingen-config.h" #include "client/PatchModel.hpp" #include "App.hpp" #include "GladeFactory.hpp" #include "LoadPatchWindow.hpp" #include "LoadPluginWindow.hpp" #include "LoadRemotePatchWindow.hpp" #include "LoadSubpatchWindow.hpp" #include "NewSubpatchWindow.hpp" #include "NodeControlWindow.hpp" #include "NodePropertiesWindow.hpp" #include "PatchPropertiesWindow.hpp" #include "PatchView.hpp" #include "PatchWindow.hpp" #include "PortPropertiesWindow.hpp" #include "RenameWindow.hpp" #include "WindowFactory.hpp" #ifdef HAVE_CURL #include "UploadPatchWindow.hpp" #endif namespace Ingen { namespace GUI { WindowFactory::WindowFactory() : _load_plugin_win(NULL) , _load_patch_win(NULL) , _load_remote_patch_win(NULL) , _upload_patch_win(NULL) , _new_subpatch_win(NULL) , _load_subpatch_win(NULL) , _patch_properties_win(NULL) , _node_properties_win(NULL) , _port_properties_win(NULL) { Glib::RefPtr xml = GladeFactory::new_glade_reference(); xml->get_widget_derived("load_plugin_win", _load_plugin_win); xml->get_widget_derived("load_patch_win", _load_patch_win); xml->get_widget_derived("load_remote_patch_win", _load_remote_patch_win); xml->get_widget_derived("new_subpatch_win", _new_subpatch_win); xml->get_widget_derived("load_subpatch_win", _load_subpatch_win); xml->get_widget_derived("patch_properties_win", _patch_properties_win); xml->get_widget_derived("node_properties_win", _node_properties_win); xml->get_widget_derived("port_properties_win", _port_properties_win); xml->get_widget_derived("rename_win", _rename_win); #ifdef HAVE_CURL xml->get_widget_derived("upload_patch_win", _upload_patch_win); #endif } WindowFactory::~WindowFactory() { for (PatchWindowMap::iterator i = _patch_windows.begin(); i != _patch_windows.end(); ++i) delete i->second; for (ControlWindowMap::iterator i = _control_windows.begin(); i != _control_windows.end(); ++i) delete i->second; } void WindowFactory::clear() { for (PatchWindowMap::iterator i = _patch_windows.begin(); i != _patch_windows.end(); ++i) delete i->second; _patch_windows.clear(); for (ControlWindowMap::iterator i = _control_windows.begin(); i != _control_windows.end(); ++i) delete i->second; _control_windows.clear(); } /** Returns the number of Patch windows currently visible. */ size_t WindowFactory::num_open_patch_windows() { size_t ret = 0; for (PatchWindowMap::iterator i = _patch_windows.begin(); i != _patch_windows.end(); ++i) if (i->second->is_visible()) ++ret; return ret; } PatchWindow* WindowFactory::patch_window(SharedPtr patch) { PatchWindowMap::iterator w = _patch_windows.find(patch->path()); return (w == _patch_windows.end()) ? NULL : w->second; } NodeControlWindow* WindowFactory::control_window(SharedPtr node) { ControlWindowMap::iterator w = _control_windows.find(node->path()); return (w == _control_windows.end()) ? NULL : w->second; } /** Present a PatchWindow for a Patch. * * If @a preferred is not NULL, it will be set to display @a patch if the patch * does not already have a visible window, otherwise that window will be presented and * @a preferred left unmodified. */ void WindowFactory::present_patch(SharedPtr patch, PatchWindow* preferred, SharedPtr view) { assert( !view || view->patch() == patch); PatchWindowMap::iterator w = _patch_windows.find(patch->path()); if (w != _patch_windows.end()) { (*w).second->present(); } else if (preferred) { w = _patch_windows.find(preferred->patch()->path()); assert((*w).second == preferred); preferred->set_patch(patch, view); _patch_windows.erase(w); _patch_windows[patch->path()] = preferred; preferred->present(); } else { PatchWindow* win = new_patch_window(patch, view); win->present(); } } PatchWindow* WindowFactory::new_patch_window(SharedPtr patch, SharedPtr view) { assert( !view || view->patch() == patch); Glib::RefPtr xml = GladeFactory::new_glade_reference("patch_win"); PatchWindow* win = NULL; xml->get_widget_derived("patch_win", win); assert(win); win->set_patch(patch, view); _patch_windows[patch->path()] = win; win->signal_delete_event().connect(sigc::bind<0>( sigc::mem_fun(this, &WindowFactory::remove_patch_window), win)); return win; } bool WindowFactory::remove_patch_window(PatchWindow* win, GdkEventAny* ignored) { if (_patch_windows.size() <= 1) { Gtk::MessageDialog d(*win, "Closing the only open patch window will exit the GUI\n" "(If the engine is remote it will remain running)\n\n" "Are you sure you want to quit?", true, Gtk::MESSAGE_WARNING, Gtk::BUTTONS_NONE, true); d.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL); d.add_button(Gtk::Stock::QUIT, Gtk::RESPONSE_CLOSE); int ret = d.run(); if (ret == Gtk::RESPONSE_CLOSE) App::instance().quit(); else return true; } PatchWindowMap::iterator w = _patch_windows.find(win->patch()->path()); assert((*w).second == win); _patch_windows.erase(w); delete win; return false; } void WindowFactory::present_controls(SharedPtr node) { NodeControlWindow* win = control_window(node); if (win) { win->present(); } else { win = new_control_window(node); win->present(); } } NodeControlWindow* WindowFactory::new_control_window(SharedPtr node) { uint32_t poly = 1; if (node->polyphonic() && node->parent()) poly = ((PatchModel*)node->parent().get())->internal_polyphony(); NodeControlWindow* win = new NodeControlWindow(node, poly); _control_windows[node->path()] = win; win->signal_delete_event().connect(sigc::bind<0>( sigc::mem_fun(this, &WindowFactory::remove_control_window), win)); return win; } bool WindowFactory::remove_control_window(NodeControlWindow* win, GdkEventAny* ignored) { ControlWindowMap::iterator w = _control_windows.find(win->node()->path()); assert((*w).second == win); _control_windows.erase(w); delete win; return true; } void WindowFactory::present_load_plugin(SharedPtr patch, GraphObject::Properties data) { PatchWindowMap::iterator w = _patch_windows.find(patch->path()); if (w != _patch_windows.end()) _load_plugin_win->set_transient_for(*w->second); _load_plugin_win->set_modal(false); _load_plugin_win->present(patch, data); } void WindowFactory::present_load_patch(SharedPtr patch, GraphObject::Properties data) { PatchWindowMap::iterator w = _patch_windows.find(patch->path()); if (w != _patch_windows.end()) _load_patch_win->set_transient_for(*w->second); _load_patch_win->set_merge(); // Import is the only choice _load_patch_win->present(patch, data); } void WindowFactory::present_load_remote_patch(SharedPtr patch, GraphObject::Properties data) { PatchWindowMap::iterator w = _patch_windows.find(patch->path()); if (w != _patch_windows.end()) _load_remote_patch_win->set_transient_for(*w->second); _load_remote_patch_win->set_merge(); // Import is the only choice _load_remote_patch_win->present(patch, data); } void WindowFactory::present_upload_patch(SharedPtr patch) { #ifdef HAVE_CURL PatchWindowMap::iterator w = _patch_windows.find(patch->path()); if (w != _patch_windows.end()) _upload_patch_win->set_transient_for(*w->second); _upload_patch_win->present(patch); #endif } void WindowFactory::present_new_subpatch(SharedPtr patch, GraphObject::Properties data) { PatchWindowMap::iterator w = _patch_windows.find(patch->path()); if (w != _patch_windows.end()) _new_subpatch_win->set_transient_for(*w->second); _new_subpatch_win->present(patch, data); } void WindowFactory::present_load_subpatch(SharedPtr patch, GraphObject::Properties data) { PatchWindowMap::iterator w = _patch_windows.find(patch->path()); if (w != _patch_windows.end()) _load_subpatch_win->set_transient_for(*w->second); _load_subpatch_win->present(patch, data); } void WindowFactory::present_rename(SharedPtr object) { PatchWindowMap::iterator w = _patch_windows.find(object->path()); if (w != _patch_windows.end()) _rename_win->set_transient_for(*w->second); _rename_win->present(object); } void WindowFactory::present_properties(SharedPtr object) { SharedPtr patch = PtrCast(object); if (patch) { PatchWindowMap::iterator w = _patch_windows.find(patch->path()); if (w != _patch_windows.end()) _patch_properties_win->set_transient_for(*w->second); _patch_properties_win->present(patch); return; } SharedPtr node = PtrCast(object); if (node) { PatchWindowMap::iterator w = _patch_windows.find(node->path().parent()); if (w != _patch_windows.end()) _node_properties_win->set_transient_for(*w->second); _node_properties_win->present(node); return; } SharedPtr port = PtrCast(object); if (port) { PatchWindowMap::iterator w = _patch_windows.find(port->path().parent().parent()); if (w != _patch_windows.end()) _patch_properties_win->set_transient_for(*w->second); _port_properties_win->present(port); return; } } } // namespace GUI } // namespace Ingen