diff options
Diffstat (limited to 'src/gui/GraphBox.cpp')
-rw-r--r-- | src/gui/GraphBox.cpp | 196 |
1 files changed, 126 insertions, 70 deletions
diff --git a/src/gui/GraphBox.cpp b/src/gui/GraphBox.cpp index 5ce54d99..47c567e3 100644 --- a/src/gui/GraphBox.cpp +++ b/src/gui/GraphBox.cpp @@ -1,6 +1,6 @@ /* This file is part of Ingen. - Copyright 2007-2017 David Robillard <http://drobilla.net/> + Copyright 2007-2024 David Robillard <http://drobilla.net/> Ingen is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free @@ -14,6 +14,8 @@ along with Ingen. If not, see <http://www.gnu.org/licenses/>. */ +#include "GraphBox.hpp" + #include "App.hpp" #include "BreadCrumbs.hpp" #include "ConnectWindow.hpp" @@ -21,38 +23,93 @@ #include "GraphTreeWindow.hpp" #include "GraphView.hpp" #include "GraphWindow.hpp" -#include "LoadGraphWindow.hpp" -#include "LoadPluginWindow.hpp" #include "MessagesWindow.hpp" -#include "NewSubgraphWindow.hpp" -#include "Style.hpp" #include "ThreadedLoader.hpp" #include "WidgetFactory.hpp" #include "WindowFactory.hpp" #include "ingen_config.h" -#include "ingen/Configuration.hpp" -#include "ingen/Interface.hpp" -#include "ingen/Log.hpp" -#include "ingen/client/ClientStore.hpp" -#include "ingen/client/GraphModel.hpp" -#include "ingen/fmt.hpp" - -#include <boost/format.hpp> +#include <ganv/canvas.h> +#include <ingen/Atom.hpp> +#include <ingen/Configuration.hpp> +#include <ingen/Forge.hpp> +#include <ingen/Interface.hpp> +#include <ingen/Properties.hpp> +#include <ingen/Resource.hpp> +#include <ingen/URI.hpp> +#include <ingen/URIs.hpp> +#include <ingen/World.hpp> +#include <ingen/client/BlockModel.hpp> +#include <ingen/client/ClientStore.hpp> +#include <ingen/client/GraphModel.hpp> +#include <ingen/client/ObjectModel.hpp> +#include <ingen/client/PluginModel.hpp> +#include <ingen/client/PortModel.hpp> +#include <ingen/fmt.hpp> +#include <raul/Path.hpp> +#include <raul/Symbol.hpp> + +#include <gdk/gdk.h> +#include <glib.h> #include <glib/gstdio.h> +#include <glibmm/convert.h> #include <glibmm/fileutils.h> +#include <glibmm/miscutils.h> +#include <glibmm/propertyproxy.h> +#include <glibmm/refptr.h> +#include <glibmm/ustring.h> +#include <gtkmm/alignment.h> +#include <gtkmm/box.h> +#include <gtkmm/builder.h> +#include <gtkmm/button.h> +#include <gtkmm/checkbutton.h> +#include <gtkmm/checkmenuitem.h> +#include <gtkmm/clipboard.h> +#include <gtkmm/container.h> +#include <gtkmm/dialog.h> +#include <gtkmm/enums.h> +#include <gtkmm/filechooser.h> +#include <gtkmm/filechooserdialog.h> +#include <gtkmm/filefilter.h> +#include <gtkmm/label.h> +#include <gtkmm/menuitem.h> +#include <gtkmm/messagedialog.h> +#include <gtkmm/object.h> +#include <gtkmm/paned.h> +#include <gtkmm/scrolledwindow.h> +#include <gtkmm/statusbar.h> #include <gtkmm/stock.h> -#ifdef HAVE_WEBKIT -#include <webkit/webkit.h> +#include <gtkmm/textbuffer.h> +#include <gtkmm/textview.h> +#include <gtkmm/toolitem.h> +#include <gtkmm/widget.h> +#include <sigc++/adaptors/retype_return.h> +#include <sigc++/connection.h> +#include <sigc++/functors/mem_fun.h> +#include <sigc++/signal.h> + +#if USE_WEBKIT +# include <webkit/webkit.h> #endif +#include <algorithm> #include <cassert> +#include <cstdint> +#include <cstdio> +#include <limits> +#include <map> +#include <memory> #include <sstream> #include <string> +#include <utility> namespace ingen { -using namespace client; +using client::BlockModel; +using client::GraphModel; +using client::ObjectModel; +using client::PluginModel; +using client::PortModel; namespace gui { @@ -63,11 +120,6 @@ static const int STATUS_CONTEXT_HOVER = 2; GraphBox::GraphBox(BaseObjectType* cobject, const Glib::RefPtr<Gtk::Builder>& xml) : Gtk::VBox(cobject) - , _app(nullptr) - , _window(nullptr) - , _breadcrumbs(nullptr) - , _has_shown_documentation(false) - , _enable_signal(true) { property_visible() = false; @@ -176,7 +228,7 @@ GraphBox::GraphBox(BaseObjectType* cobject, _menu_view_graph_properties->signal_activate().connect( sigc::mem_fun(this, &GraphBox::event_show_properties)); - Glib::RefPtr<Gtk::Clipboard> clipboard = Gtk::Clipboard::get(); + const Glib::RefPtr<Gtk::Clipboard> clipboard = Gtk::Clipboard::get(); clipboard->signal_owner_change().connect( sigc::mem_fun(this, &GraphBox::event_clipboard_changed)); @@ -194,21 +246,25 @@ GraphBox::~GraphBox() delete _breadcrumbs; } -SPtr<GraphBox> -GraphBox::create(App& app, SPtr<const GraphModel> graph) +std::shared_ptr<GraphBox> +GraphBox::create(App& app, const std::shared_ptr<const GraphModel>& graph) { GraphBox* result = nullptr; - Glib::RefPtr<Gtk::Builder> xml = WidgetFactory::create("graph_win"); + const Glib::RefPtr<Gtk::Builder> xml = WidgetFactory::create("graph_win"); xml->get_widget_derived("graph_win_vbox", result); + if (!result) { + return {}; + } + result->init_box(app); - result->set_graph(graph, SPtr<GraphView>()); + result->set_graph(graph, nullptr); if (app.is_plugin()) { result->_menu_close->set_sensitive(false); result->_menu_quit->set_sensitive(false); } - return SPtr<GraphBox>(result); + return std::shared_ptr<GraphBox>(result); } void @@ -248,13 +304,14 @@ GraphBox::set_status_text(const std::string& text) } void -GraphBox::set_graph_from_path(const Raul::Path& path, SPtr<GraphView> view) +GraphBox::set_graph_from_path(const raul::Path& path, + const std::shared_ptr<GraphView>& view) { if (view) { assert(view->graph()->path() == path); _app->window_factory()->present_graph(view->graph(), _window, view); } else { - SPtr<const GraphModel> model = dynamic_ptr_cast<const GraphModel>( + auto model = std::dynamic_pointer_cast<const GraphModel>( _app->store()->object(path)); if (model) { _app->window_factory()->present_graph(model, _window); @@ -267,8 +324,8 @@ GraphBox::set_graph_from_path(const Raul::Path& path, SPtr<GraphView> view) * If `view` is null, a new view will be created. */ void -GraphBox::set_graph(SPtr<const GraphModel> graph, - SPtr<GraphView> view) +GraphBox::set_graph(const std::shared_ptr<const GraphModel>& graph, + const std::shared_ptr<GraphView>& view) { if (!graph || graph == _graph) { return; @@ -307,11 +364,11 @@ GraphBox::set_graph(SPtr<const GraphModel> graph, // Add view to our alignment if (_view->get_parent()) { - _view->get_parent()->remove(*_view.get()); + _view->get_parent()->remove(*_view); } _alignment->remove(); - _alignment->add(*_view.get()); + _alignment->add(*_view); if (_breadcrumbs->get_parent()) { _breadcrumbs->get_parent()->remove(*_breadcrumbs); @@ -326,14 +383,14 @@ GraphBox::set_graph(SPtr<const GraphModel> graph, _menu_view_control_window->property_sensitive() = false; - for (const auto& p : graph->ports()) { - if (_app->can_control(p.get())) { - _menu_view_control_window->property_sensitive() = true; - break; - } - } + _menu_view_control_window->property_sensitive() = + std::any_of(graph->ports().begin(), + graph->ports().end(), + [this](const auto& p) { + return _app->can_control(p.get()); + }); - _menu_parent->property_sensitive() = bool(graph->parent()); + _menu_parent->property_sensitive() = !!graph->parent(); new_port_connection = graph->signal_new_port().connect( sigc::mem_fun(this, &GraphBox::graph_port_added)); @@ -355,7 +412,7 @@ GraphBox::set_graph(SPtr<const GraphModel> graph, } void -GraphBox::graph_port_added(SPtr<const PortModel> port) +GraphBox::graph_port_added(const std::shared_ptr<const PortModel>& port) { if (port->is_input() && _app->can_control(port.get())) { _menu_view_control_window->property_sensitive() = true; @@ -363,20 +420,18 @@ GraphBox::graph_port_added(SPtr<const PortModel> port) } void -GraphBox::graph_port_removed(SPtr<const PortModel> port) +GraphBox::graph_port_removed(const std::shared_ptr<const PortModel>& port) { if (!(port->is_input() && _app->can_control(port.get()))) { return; } - for (const auto& p : _graph->ports()) { - if (p->is_input() && _app->can_control(p.get())) { - _menu_view_control_window->property_sensitive() = true; - return; - } - } - - _menu_view_control_window->property_sensitive() = false; + _menu_view_control_window->property_sensitive() = + std::any_of(_graph->ports().begin(), + _graph->ports().end(), + [this](const auto& p) { + return p->is_input() && _app->can_control(p.get()); + }); } void @@ -397,7 +452,7 @@ GraphBox::set_documentation(const std::string& doc, bool html) _doc_scrolledwindow->hide(); return; } -#ifdef HAVE_WEBKIT +#if USE_WEBKIT WebKitWebView* view = WEBKIT_WEB_VIEW(webkit_web_view_new()); webkit_web_view_load_html_string(view, doc.c_str(), ""); Gtk::Widget* widget = Gtk::manage(Glib::wrap(GTK_WIDGET(view))); @@ -425,7 +480,7 @@ GraphBox::show_status(const ObjectModel* model) show_port_status(port, port->value()); } else if ((block = dynamic_cast<const BlockModel*>(model))) { - const PluginModel* plugin = dynamic_cast<const PluginModel*>(block->plugin()); + const auto* plugin = dynamic_cast<const PluginModel*>(block->plugin()); if (plugin) { msg << fmt(" (%1%)", plugin->human_name()); } @@ -441,7 +496,7 @@ GraphBox::show_port_status(const PortModel* port, const Atom& value) const BlockModel* parent = dynamic_cast<const BlockModel*>(port->parent().get()); if (parent) { - const PluginModel* plugin = dynamic_cast<const PluginModel*>(parent->plugin()); + const auto* plugin = dynamic_cast<const PluginModel*>(parent->plugin()); if (plugin) { const std::string& human_name = plugin->port_human_name(port->index()); if (!human_name.empty()) { @@ -482,7 +537,7 @@ GraphBox::event_show_engine() void GraphBox::event_clipboard_changed(GdkEventOwnerChange* ev) { - Glib::RefPtr<Gtk::Clipboard> clipboard = Gtk::Clipboard::get(); + const Glib::RefPtr<Gtk::Clipboard> clipboard = Gtk::Clipboard::get(); _menu_paste->set_sensitive(clipboard->wait_is_text_available()); } @@ -591,8 +646,8 @@ GraphBox::event_save_as() filename += ".ingen"; basename += ".ingen"; } else if (filename.substr(filename.length() - 4) == ".ttl") { - const Glib::ustring dir = Glib::path_get_dirname(filename); - if (dir.substr(dir.length() - 6) != ".ingen") { + const Glib::ustring dirname = Glib::path_get_dirname(filename); + if (dirname.substr(dirname.length() - 6) != ".ingen") { error("<b>File does not appear to be in an Ingen bundle."); } } else if (filename.substr(filename.length() - 6) != ".ingen") { @@ -602,7 +657,7 @@ GraphBox::event_save_as() const std::string symbol(basename.substr(0, basename.find('.'))); - if (!Raul::Symbol::is_valid(symbol)) { + if (!raul::Symbol::is_valid(symbol)) { error( "<b>Ingen bundle names must be valid symbols.</b>", "All characters must be _, a-z, A-Z, or 0-9, but the first may not be 0-9."); @@ -664,24 +719,23 @@ GraphBox::event_export_image() dialog.set_transient_for(*_window); } - using Types = std::map<std::string, std::string>; - Types types; + std::map<std::string, std::string> types; types["*.dot"] = "Graphviz DOT"; types["*.pdf"] = "Portable Document Format"; types["*.ps"] = "PostScript"; types["*.svg"] = "Scalable Vector Graphics"; - for (Types::const_iterator t = types.begin(); t != types.end(); ++t) { + for (const auto& t : types) { Gtk::FileFilter filt; - filt.add_pattern(t->first); - filt.set_name(t->second); + filt.add_pattern(t.first); + filt.set_name(t.second); dialog.add_filter(filt); - if (t->first == "*.pdf") { + if (t.first == "*.pdf") { dialog.set_filter(filt); } } - Gtk::CheckButton* bg_but = new Gtk::CheckButton("Draw _Background", true); - Gtk::Alignment* extra = new Gtk::Alignment(1.0, 0.5, 0.0, 0.0); + auto* bg_but = new Gtk::CheckButton("Draw _Background", true); + auto* extra = new Gtk::Alignment(1.0, 0.5, 0.0, 0.0); bg_but->set_active(true); extra->add(*Gtk::manage(bg_but)); extra->show_all(); @@ -813,7 +867,9 @@ GraphBox::event_arrange() void GraphBox::event_parent_activated() { - SPtr<client::GraphModel> parent = dynamic_ptr_cast<client::GraphModel>(_graph->parent()); + auto parent = + std::dynamic_pointer_cast<client::GraphModel>(_graph->parent()); + if (parent) { _app->window_factory()->present_graph(parent, _window); } @@ -828,10 +884,10 @@ GraphBox::event_refresh_activated() void GraphBox::event_fullscreen_toggled() { - // FIXME: ugh, use GTK signals to track state and know for sure - static bool is_fullscreen = false; - if (_window) { + // FIXME: ugh, use GTK signals to track state and know for sure + static bool is_fullscreen = false; + if (!is_fullscreen) { _window->fullscreen(); is_fullscreen = true; @@ -873,7 +929,7 @@ GraphBox::event_animate_signals_toggled() _app->interface()->set_property( URI("ingen:/clients/this"), _app->uris().ingen_broadcast, - _app->forge().make((bool)_menu_animate_signals->get_active())); + _app->forge().make(_menu_animate_signals->get_active())); } void |