summaryrefslogtreecommitdiffstats
path: root/src/gui/GraphBox.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui/GraphBox.cpp')
-rw-r--r--src/gui/GraphBox.cpp196
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