From a7d83f19b08eb4c6f79a82fe60c2b86db13f4420 Mon Sep 17 00:00:00 2001 From: David Robillard Date: Sat, 24 Nov 2018 13:44:03 +0100 Subject: Squashed 'waflib/' changes from 6e726eb1..5ea8f99f 5ea8f99f Improve test output spacing 0e23b29f Raise exception when test suite fails to ensure non-zero exit status d6de073b Show run time of unit tests 5b655541 Add short configure option for ultra-strict flags 4687ba6d Use gtest-like test output 258903d9 Fix failure count in test group summaries da07e738 Fix verbose tests with Python 3 git-subtree-dir: waflib git-subtree-split: 5ea8f99f6e1246079c1fe6bb590c38a53aadd40d --- src/gui/App.cpp | 499 ------- src/gui/App.hpp | 196 --- src/gui/Arc.cpp | 44 - src/gui/Arc.hpp | 52 - src/gui/BreadCrumbs.cpp | 229 ---- src/gui/BreadCrumbs.hpp | 119 -- src/gui/ConnectWindow.cpp | 572 -------- src/gui/ConnectWindow.hpp | 116 -- src/gui/GraphBox.cpp | 922 ------------- src/gui/GraphBox.hpp | 213 --- src/gui/GraphCanvas.cpp | 899 ------------ src/gui/GraphCanvas.hpp | 159 --- src/gui/GraphPortModule.cpp | 166 --- src/gui/GraphPortModule.hpp | 79 -- src/gui/GraphTreeWindow.cpp | 235 ---- src/gui/GraphTreeWindow.hpp | 123 -- src/gui/GraphView.cpp | 154 --- src/gui/GraphView.hpp | 98 -- src/gui/GraphWindow.cpp | 85 -- src/gui/GraphWindow.hpp | 80 -- src/gui/LoadGraphWindow.cpp | 257 ---- src/gui/LoadGraphWindow.hpp | 95 -- src/gui/LoadPluginWindow.cpp | 511 ------- src/gui/LoadPluginWindow.hpp | 160 --- src/gui/MessagesWindow.cpp | 141 -- src/gui/MessagesWindow.hpp | 70 - src/gui/NewSubgraphWindow.cpp | 119 -- src/gui/NewSubgraphWindow.hpp | 72 - src/gui/NodeMenu.cpp | 253 ---- src/gui/NodeMenu.hpp | 75 - src/gui/NodeModule.cpp | 518 ------- src/gui/NodeModule.hpp | 104 -- src/gui/ObjectMenu.cpp | 145 -- src/gui/ObjectMenu.hpp | 77 -- src/gui/PluginMenu.cpp | 176 --- src/gui/PluginMenu.hpp | 80 -- src/gui/Port.cpp | 534 -------- src/gui/Port.hpp | 102 -- src/gui/PortMenu.cpp | 174 --- src/gui/PortMenu.hpp | 66 - src/gui/PropertiesWindow.cpp | 591 -------- src/gui/PropertiesWindow.hpp | 129 -- src/gui/RDFS.cpp | 259 ---- src/gui/RDFS.hpp | 80 -- src/gui/RenameWindow.cpp | 137 -- src/gui/RenameWindow.hpp | 64 - src/gui/Style.cpp | 106 -- src/gui/Style.hpp | 56 - src/gui/SubgraphModule.cpp | 102 -- src/gui/SubgraphModule.hpp | 64 - src/gui/ThreadedLoader.cpp | 148 -- src/gui/ThreadedLoader.hpp | 96 -- src/gui/URIEntry.cpp | 192 --- src/gui/URIEntry.hpp | 68 - src/gui/WidgetFactory.cpp | 80 -- src/gui/WidgetFactory.hpp | 58 - src/gui/Window.hpp | 78 -- src/gui/WindowFactory.cpp | 302 ---- src/gui/WindowFactory.hpp | 99 -- src/gui/ingen_gui.cpp | 67 - src/gui/ingen_gui.gladep | 9 - src/gui/ingen_gui.ui | 3049 ----------------------------------------- src/gui/ingen_gui_lv2.cpp | 209 --- src/gui/ingen_style.rc | 155 --- src/gui/rgba.hpp | 58 - src/gui/wscript | 111 -- 66 files changed, 15136 deletions(-) delete mode 100644 src/gui/App.cpp delete mode 100644 src/gui/App.hpp delete mode 100644 src/gui/Arc.cpp delete mode 100644 src/gui/Arc.hpp delete mode 100644 src/gui/BreadCrumbs.cpp delete mode 100644 src/gui/BreadCrumbs.hpp delete mode 100644 src/gui/ConnectWindow.cpp delete mode 100644 src/gui/ConnectWindow.hpp delete mode 100644 src/gui/GraphBox.cpp delete mode 100644 src/gui/GraphBox.hpp delete mode 100644 src/gui/GraphCanvas.cpp delete mode 100644 src/gui/GraphCanvas.hpp delete mode 100644 src/gui/GraphPortModule.cpp delete mode 100644 src/gui/GraphPortModule.hpp delete mode 100644 src/gui/GraphTreeWindow.cpp delete mode 100644 src/gui/GraphTreeWindow.hpp delete mode 100644 src/gui/GraphView.cpp delete mode 100644 src/gui/GraphView.hpp delete mode 100644 src/gui/GraphWindow.cpp delete mode 100644 src/gui/GraphWindow.hpp delete mode 100644 src/gui/LoadGraphWindow.cpp delete mode 100644 src/gui/LoadGraphWindow.hpp delete mode 100644 src/gui/LoadPluginWindow.cpp delete mode 100644 src/gui/LoadPluginWindow.hpp delete mode 100644 src/gui/MessagesWindow.cpp delete mode 100644 src/gui/MessagesWindow.hpp delete mode 100644 src/gui/NewSubgraphWindow.cpp delete mode 100644 src/gui/NewSubgraphWindow.hpp delete mode 100644 src/gui/NodeMenu.cpp delete mode 100644 src/gui/NodeMenu.hpp delete mode 100644 src/gui/NodeModule.cpp delete mode 100644 src/gui/NodeModule.hpp delete mode 100644 src/gui/ObjectMenu.cpp delete mode 100644 src/gui/ObjectMenu.hpp delete mode 100644 src/gui/PluginMenu.cpp delete mode 100644 src/gui/PluginMenu.hpp delete mode 100644 src/gui/Port.cpp delete mode 100644 src/gui/Port.hpp delete mode 100644 src/gui/PortMenu.cpp delete mode 100644 src/gui/PortMenu.hpp delete mode 100644 src/gui/PropertiesWindow.cpp delete mode 100644 src/gui/PropertiesWindow.hpp delete mode 100644 src/gui/RDFS.cpp delete mode 100644 src/gui/RDFS.hpp delete mode 100644 src/gui/RenameWindow.cpp delete mode 100644 src/gui/RenameWindow.hpp delete mode 100644 src/gui/Style.cpp delete mode 100644 src/gui/Style.hpp delete mode 100644 src/gui/SubgraphModule.cpp delete mode 100644 src/gui/SubgraphModule.hpp delete mode 100644 src/gui/ThreadedLoader.cpp delete mode 100644 src/gui/ThreadedLoader.hpp delete mode 100644 src/gui/URIEntry.cpp delete mode 100644 src/gui/URIEntry.hpp delete mode 100644 src/gui/WidgetFactory.cpp delete mode 100644 src/gui/WidgetFactory.hpp delete mode 100644 src/gui/Window.hpp delete mode 100644 src/gui/WindowFactory.cpp delete mode 100644 src/gui/WindowFactory.hpp delete mode 100644 src/gui/ingen_gui.cpp delete mode 100644 src/gui/ingen_gui.gladep delete mode 100644 src/gui/ingen_gui.ui delete mode 100644 src/gui/ingen_gui_lv2.cpp delete mode 100644 src/gui/ingen_style.rc delete mode 100644 src/gui/rgba.hpp delete mode 100644 src/gui/wscript (limited to 'src/gui') diff --git a/src/gui/App.cpp b/src/gui/App.cpp deleted file mode 100644 index 9f1a29ca..00000000 --- a/src/gui/App.cpp +++ /dev/null @@ -1,499 +0,0 @@ -/* - This file is part of Ingen. - Copyright 2007-2017 David Robillard - - 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 - Software Foundation, either version 3 of the License, or 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 Affero General Public License for details. - - You should have received a copy of the GNU Affero General Public License - along with Ingen. If not, see . -*/ - -#include -#include -#include -#include - -#include -#include -#include - -#include "ganv/Edge.hpp" -#include "ingen/Configuration.hpp" -#include "ingen/EngineBase.hpp" -#include "ingen/Interface.hpp" -#include "ingen/Log.hpp" -#include "ingen/QueuedInterface.hpp" -#include "ingen/StreamWriter.hpp" -#include "ingen/World.hpp" -#include "ingen/client/ClientStore.hpp" -#include "ingen/client/GraphModel.hpp" -#include "ingen/client/ObjectModel.hpp" -#include "ingen/client/SigClientInterface.hpp" -#include "ingen/runtime_paths.hpp" -#include "lilv/lilv.h" -#include "raul/Path.hpp" -#include "suil/suil.h" - -#include "App.hpp" -#include "ConnectWindow.hpp" -#include "GraphTreeWindow.hpp" -#include "GraphWindow.hpp" -#include "LoadPluginWindow.hpp" -#include "MessagesWindow.hpp" -#include "NodeModule.hpp" -#include "Port.hpp" -#include "RDFS.hpp" -#include "Style.hpp" -#include "SubgraphModule.hpp" -#include "ThreadedLoader.hpp" -#include "WidgetFactory.hpp" -#include "WindowFactory.hpp" -#include "rgba.hpp" - -namespace Raul { class Deletable; } - -namespace Ingen { - -namespace Client { class PluginModel; } - -using namespace Client; - -namespace GUI { - -class Port; - -Gtk::Main* App::_main = nullptr; - -App::App(Ingen::World* world) - : _style(new Style(*this)) - , _about_dialog(nullptr) - , _window_factory(new WindowFactory(*this)) - , _world(world) - , _sample_rate(48000) - , _block_length(1024) - , _n_threads(1) - , _mean_run_load(0.0f) - , _min_run_load(0.0f) - , _max_run_load(0.0f) - , _enable_signal(true) - , _requested_plugins(false) - , _is_plugin(false) -{ - _world->conf().load_default("ingen", "gui.ttl"); - - WidgetFactory::get_widget_derived("connect_win", _connect_window); - WidgetFactory::get_widget_derived("messages_win", _messages_window); - WidgetFactory::get_widget_derived("graph_tree_win", _graph_tree_window); - WidgetFactory::get_widget("about_win", _about_dialog); - _connect_window->init_dialog(*this); - _messages_window->init_window(*this); - _graph_tree_window->init_window(*this); - _about_dialog->property_program_name() = "Ingen"; - _about_dialog->property_logo_icon_name() = "ingen"; - - PluginModel::set_rdf_world(*world->rdf_world()); - PluginModel::set_lilv_world(world->lilv_world()); - - using namespace std::placeholders; - world->log().set_sink(std::bind(&MessagesWindow::log, _messages_window, _1, _2, _3)); -} - -App::~App() -{ - delete _style; - delete _window_factory; -} - -SPtr -App::create(Ingen::World* world) -{ - suil_init(&world->argc(), &world->argv(), SUIL_ARG_NONE); - - // Add RC file for embedded GUI Gtk style - const std::string rc_path = Ingen::data_file_path("ingen_style.rc"); - Gtk::RC::add_default_file(rc_path); - - _main = Gtk::Main::instance(); - if (!_main) { - Glib::set_application_name("Ingen"); - gtk_window_set_default_icon_name("ingen"); - _main = new Gtk::Main(&world->argc(), &world->argv()); - } - - App* app = new App(world); - - // Load configuration settings - app->style()->load_settings(); - app->style()->apply_settings(); - - // Set default window icon - app->_about_dialog->property_program_name() = "Ingen"; - app->_about_dialog->property_logo_icon_name() = "ingen"; - gtk_window_set_default_icon_name("ingen"); - - return SPtr(app); -} - -void -App::run() -{ - _connect_window->start(*this, world()); - - // Run main iterations here until we're attached to the engine. Otherwise - // with 'ingen -egl' we'd get a bunch of notifications about load - // immediately before even knowing about the root graph or plugins) - while (!_connect_window->attached()) { - if (_main->iteration()) { - break; - } - } - - _main->run(); -} - -void -App::attach(SPtr client) -{ - assert(!_client); - assert(!_store); - assert(!_loader); - - if (_world->engine()) { - _world->engine()->register_client(client); - } - - _client = client; - _store = SPtr(new ClientStore(_world->uris(), _world->log(), sig_client())); - _loader = SPtr(new ThreadedLoader(*this, _world->interface())); - if (!_world->store()) { - _world->set_store(_store); - } - - if (_world->conf().option("dump").get()) { - _dumper = SPtr(new StreamWriter(_world->uri_map(), - _world->uris(), - URI("ingen:/client"), - stderr, - ColorContext::Color::CYAN)); - - sig_client()->signal_message().connect( - sigc::mem_fun(*_dumper.get(), &StreamWriter::message)); - } - - _graph_tree_window->init(*this, *_store); - sig_client()->signal_message().connect(sigc::mem_fun(this, &App::message)); -} - -void -App::detach() -{ - if (_world->interface()) { - _window_factory->clear(); - _store->clear(); - - _loader.reset(); - _store.reset(); - _client.reset(); - _world->set_interface(SPtr()); - } -} - -void -App::request_plugins_if_necessary() -{ - if (!_requested_plugins) { - _world->interface()->get(URI("ingen:/plugins")); - _requested_plugins = true; - } -} - -SPtr -App::sig_client() -{ - SPtr qi = dynamic_ptr_cast(_client); - if (qi) { - return dynamic_ptr_cast(qi->sink()); - } - return dynamic_ptr_cast(_client); -} - -SPtr -App::serialiser() -{ - return _world->serialiser(); -} - -void -App::message(const Message& msg) -{ - if (const Response* const r = boost::get(&msg)) { - response(r->id, r->status, r->subject); - } else if (const Error* const e = boost::get(&msg)) { - error_message(e->message); - } else if (const Put* const p = boost::get(&msg)) { - put(p->uri, p->properties, p->ctx); - } else if (const SetProperty* const s = boost::get(&msg)) { - property_change(s->subject, s->predicate, s->value, s->ctx); - } -} - -void -App::response(int32_t id, Status status, const std::string& subject) -{ - if (status != Status::SUCCESS) { - std::string msg = ingen_status_string(status); - if (!subject.empty()) { - msg += ": " + subject; - } - error_message(msg); - } -} - -void -App::error_message(const std::string& str) -{ - _messages_window->post_error(str); -} - -void -App::set_property(const URI& subject, - const URI& key, - const Atom& value, - Resource::Graph ctx) -{ - // Send message to server - interface()->set_property(subject, key, value, ctx); - - /* The server does not feed back set messages (kludge to prevent control - feedback and bandwidth wastage, see Delta.cpp). So, assume everything - went as planned here and fire the signal ourselves as if the server - feedback came back immediately. */ - if (key != uris().ingen_activity) { - sig_client()->signal_message().emit(SetProperty{0, subject, key, value, ctx}); - } -} - -void -App::set_tooltip(Gtk::Widget* widget, const LilvNode* node) -{ - const std::string comment = RDFS::comment(_world, node); - if (!comment.empty()) { - widget->set_tooltip_text(comment); - } -} - -void -App::put(const URI& uri, - const Properties& properties, - Resource::Graph ctx) -{ - _enable_signal = false; - for (const auto& p : properties) { - property_change(uri, p.first, p.second); - } - _enable_signal = true; - _status_text = status_text(); - signal_status_text_changed.emit(_status_text); -} - -void -App::property_change(const URI& subject, - const URI& key, - const Atom& value, - Resource::Graph ctx) -{ - if (subject != URI("ingen:/engine")) { - return; - } else if (key == uris().param_sampleRate && value.type() == forge().Int) { - _sample_rate = value.get(); - } else if (key == uris().bufsz_maxBlockLength && value.type() == forge().Int) { - _block_length = value.get(); - } else if (key == uris().ingen_numThreads && value.type() == forge().Int) { - _n_threads = value.get(); - } else if (key == uris().ingen_minRunLoad && value.type() == forge().Float) { - _min_run_load = value.get(); - } else if (key == uris().ingen_meanRunLoad && value.type() == forge().Float) { - _mean_run_load = value.get(); - } else if (key == uris().ingen_maxRunLoad && value.type() == forge().Float) { - _max_run_load = value.get(); - } else { - _world->log().warn(fmt("Unknown engine property %1%\n") % key); - return; - } - - if (_enable_signal) { - _status_text = status_text(); - signal_status_text_changed.emit(_status_text); - } -} - -static std::string -fraction_label(float f) -{ - static const uint32_t GREEN = 0x4A8A0EFF; - static const uint32_t RED = 0x960909FF; - - const uint32_t col = rgba_interpolate(GREEN, RED, std::min(f, 1.0f)); - char col_str[8]; - snprintf(col_str, sizeof(col_str), "%02X%02X%02X", - RGBA_R(col), RGBA_G(col), RGBA_B(col)); - return (fmt("%d%%") % col_str % (f * 100)).str(); -} - -std::string -App::status_text() const -{ - return (fmt("%2.1f kHz / %.1f ms, %s, %s DSP") - % (_sample_rate / 1e3f) - % (_block_length * 1e3f / (float)_sample_rate) - % ((_n_threads == 1) - ? "1 thread" - : (fmt("%1% threads") % _n_threads).str()) - % fraction_label(_max_run_load)).str(); -} - -void -App::port_activity(Port* port) -{ - std::pair inserted = _activity_ports.emplace(port, false); - if (inserted.second) { - inserted.first->second = false; - } - - port->set_highlighted(true); -} - -void -App::activity_port_destroyed(Port* port) -{ - auto i = _activity_ports.find(port); - if (i != _activity_ports.end()) { - _activity_ports.erase(i); - } -} - -bool -App::animate() -{ - for (auto i = _activity_ports.begin(); i != _activity_ports.end(); ) { - auto next = i; - ++next; - - if ((*i).second) { // saw it last time, unhighlight and pop - (*i).first->set_highlighted(false); - _activity_ports.erase(i); - } else { - (*i).second = true; - } - - i = next; - } - - return true; -} - -/******** Event Handlers ************/ - -void -App::register_callbacks() -{ - Glib::signal_timeout().connect( - sigc::mem_fun(*this, &App::gtk_main_iteration), 33, G_PRIORITY_DEFAULT); -} - -bool -App::gtk_main_iteration() -{ - if (!_client) { - return false; - } - - animate(); - - if (_messages_window) { - _messages_window->flush(); - } - - _enable_signal = false; - if (_world->engine()) { - if (!_world->engine()->main_iteration()) { - Gtk::Main::quit(); - return false; - } - } else { - dynamic_ptr_cast(_client)->emit(); - } - _enable_signal = true; - - return true; -} - -void -App::show_about() -{ - _about_dialog->run(); - _about_dialog->hide(); -} - -/** Prompt (if necessary) and quit application (if confirmed). - * @return true iff the application quit. - */ -bool -App::quit(Gtk::Window* dialog_parent) -{ - bool quit = true; - if (_world->engine() && _connect_window->attached()) { - Gtk::MessageDialog d( - "The engine is running in this process. Quitting will terminate Ingen." - "\n\n" "Are you sure you want to quit?", - true, Gtk::MESSAGE_WARNING, Gtk::BUTTONS_NONE, true); - if (dialog_parent) { - d.set_transient_for(*dialog_parent); - } - d.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL); - d.add_button(Gtk::Stock::QUIT, Gtk::RESPONSE_CLOSE); - quit = (d.run() == Gtk::RESPONSE_CLOSE); - } - - if (!quit) { - return false; - } - - Gtk::Main::quit(); - - try { - const std::string path = _world->conf().save( - _world->uri_map(), "ingen", "gui.ttl", Configuration::GUI); - std::cout << (fmt("Saved GUI settings to %1%\n") % path); - } catch (const std::exception& e) { - std::cerr << (fmt("Error saving GUI settings (%1%)\n") - % e.what()); - } - - return true; -} - -bool -App::can_control(const Client::PortModel* port) const -{ - return port->is_a(uris().lv2_ControlPort) - || port->is_a(uris().lv2_CVPort) - || (port->is_a(uris().atom_AtomPort) - && (port->supports(uris().atom_Float) - || port->supports(uris().atom_String))); -} - -uint32_t -App::sample_rate() const -{ - return _sample_rate; -} - -} // namespace GUI -} // namespace Ingen diff --git a/src/gui/App.hpp b/src/gui/App.hpp deleted file mode 100644 index 75661449..00000000 --- a/src/gui/App.hpp +++ /dev/null @@ -1,196 +0,0 @@ -/* - This file is part of Ingen. - Copyright 2007-2017 David Robillard - - 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 - Software Foundation, either version 3 of the License, or 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 Affero General Public License for details. - - You should have received a copy of the GNU Affero General Public License - along with Ingen. If not, see . -*/ - -#ifndef INGEN_GUI_APP_HPP -#define INGEN_GUI_APP_HPP - -#include -#include - -#include -#include -#include - -#include "ingen/Atom.hpp" -#include "ingen/Message.hpp" -#include "ingen/Resource.hpp" -#include "ingen/Status.hpp" -#include "ingen/World.hpp" -#include "ingen/ingen.h" -#include "ingen/types.hpp" -#include "lilv/lilv.h" -#include "raul/Deletable.hpp" - -namespace Ingen { - -class Interface; -class Log; -class Port; -class Serialiser; -class StreamWriter; -class World; - -namespace Client { - -class ClientStore; -class GraphModel; -class PluginModel; -class PortModel; -class SigClientInterface; - -} - -namespace GUI { - -class ConnectWindow; -class GraphCanvas; -class GraphTreeView; -class GraphTreeWindow; -class MessagesWindow; -class Port; -class Style; -class ThreadedLoader; -class WindowFactory; - -/** Ingen Gtk Application. - * \ingroup GUI - */ -class INGEN_API App -{ -public: - ~App(); - - void error_message(const std::string& str); - - void attach(SPtr client); - - void detach(); - - void request_plugins_if_necessary(); - - void register_callbacks(); - bool gtk_main_iteration(); - - void show_about(); - bool quit(Gtk::Window* dialog_parent); - - void port_activity(Port* port); - void activity_port_destroyed(Port* port); - bool can_control(const Client::PortModel* port) const; - - bool signal() const { return _enable_signal; } - void enable_signals(bool b) { _enable_signal = b; } - bool disable_signals() { - bool old = _enable_signal; - _enable_signal = false; - return old; - } - - void set_property(const URI& subject, - const URI& key, - const Atom& value, - Resource::Graph ctx = Resource::Graph::DEFAULT); - - /** Set the tooltip for a widget from its RDF documentation. */ - void set_tooltip(Gtk::Widget* widget, const LilvNode* node); - - uint32_t sample_rate() const; - - bool is_plugin() const { return _is_plugin; } - void set_is_plugin(bool b) { _is_plugin = b; } - - ConnectWindow* connect_window() const { return _connect_window; } - MessagesWindow* messages_dialog() const { return _messages_window; } - GraphTreeWindow* graph_tree() const { return _graph_tree_window; } - Style* style() const { return _style; } - WindowFactory* window_factory() const { return _window_factory; } - - Ingen::Forge& forge() const { return _world->forge(); } - SPtr interface() const { return _world->interface(); } - SPtr client() const { return _client; } - SPtr store() const { return _store; } - SPtr loader() const { return _loader; } - - SPtr sig_client(); - - SPtr serialiser(); - - static SPtr create(Ingen::World* world); - - void run(); - - std::string status_text() const; - - sigc::signal signal_status_text_changed; - - inline Ingen::World* world() const { return _world; } - inline Ingen::URIs& uris() const { return _world->uris(); } - inline Ingen::Log& log() const { return _world->log(); } - -protected: - explicit App(Ingen::World* world); - - void message(const Ingen::Message& msg); - - bool animate(); - void response(int32_t id, Ingen::Status status, const std::string& subject); - - void put(const URI& uri, - const Properties& properties, - Resource::Graph ctx); - - void property_change(const URI& subject, - const URI& key, - const Atom& value, - Resource::Graph ctx = Resource::Graph::DEFAULT); - - static Gtk::Main* _main; - - SPtr _client; - SPtr _store; - SPtr _loader; - SPtr _dumper; - - Style* _style; - - ConnectWindow* _connect_window; - MessagesWindow* _messages_window; - GraphTreeWindow* _graph_tree_window; - Gtk::AboutDialog* _about_dialog; - WindowFactory* _window_factory; - - Ingen::World* _world; - - int32_t _sample_rate; - int32_t _block_length; - int32_t _n_threads; - float _mean_run_load; - float _min_run_load; - float _max_run_load; - std::string _status_text; - - typedef std::unordered_map ActivityPorts; - ActivityPorts _activity_ports; - - bool _enable_signal; - bool _requested_plugins; - bool _is_plugin; -}; - -} // namespace GUI -} // namespace Ingen - -#endif // INGEN_GUI_APP_HPP diff --git a/src/gui/Arc.cpp b/src/gui/Arc.cpp deleted file mode 100644 index c14b2e88..00000000 --- a/src/gui/Arc.cpp +++ /dev/null @@ -1,44 +0,0 @@ -/* - This file is part of Ingen. - Copyright 2007-2015 David Robillard - - 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 - Software Foundation, either version 3 of the License, or 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 Affero General Public License for details. - - You should have received a copy of the GNU Affero General Public License - along with Ingen. If not, see . -*/ - -#include "Arc.hpp" -#include "ingen/client/ArcModel.hpp" -#include "ingen/client/BlockModel.hpp" - -#define NS_INTERNALS "http://drobilla.net/ns/ingen-internals#" - -namespace Ingen { -namespace GUI { - -Arc::Arc(Ganv::Canvas& canvas, - SPtr model, - Ganv::Node* src, - Ganv::Node* dst) - : Ganv::Edge(canvas, src, dst) - , _arc_model(model) -{ - SPtr tparent = model->tail()->parent(); - SPtr tparent_block; - if ((tparent_block = dynamic_ptr_cast(tparent))) { - if (tparent_block->plugin_uri() == NS_INTERNALS "BlockDelay") { - g_object_set(_gobj, "dash-length", 4.0, NULL); - set_constraining(false); - } - } -} - -} // namespace GUI -} // namespace Ingen diff --git a/src/gui/Arc.hpp b/src/gui/Arc.hpp deleted file mode 100644 index 382ca305..00000000 --- a/src/gui/Arc.hpp +++ /dev/null @@ -1,52 +0,0 @@ -/* - This file is part of Ingen. - Copyright 2007-2015 David Robillard - - 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 - Software Foundation, either version 3 of the License, or 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 Affero General Public License for details. - - You should have received a copy of the GNU Affero General Public License - along with Ingen. If not, see . -*/ - -#ifndef INGEN_GUI_ARC_HPP -#define INGEN_GUI_ARC_HPP - -#include - -#include "ganv/Edge.hpp" -#include "ingen/types.hpp" - -namespace Ingen { - -namespace Client { class ArcModel; } - -namespace GUI { - -/** An Arc (directed edge) in a Graph. - * - * \ingroup GUI - */ -class Arc : public Ganv::Edge -{ -public: - Arc(Ganv::Canvas& canvas, - SPtr model, - Ganv::Node* src, - Ganv::Node* dst); - - SPtr model() const { return _arc_model; } - -private: - SPtr _arc_model; -}; - -} // namespace GUI -} // namespace Ingen - -#endif // INGEN_GUI_ARC_HPP diff --git a/src/gui/BreadCrumbs.cpp b/src/gui/BreadCrumbs.cpp deleted file mode 100644 index ae7882e3..00000000 --- a/src/gui/BreadCrumbs.cpp +++ /dev/null @@ -1,229 +0,0 @@ -/* - This file is part of Ingen. - Copyright 2007-2015 David Robillard - - 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 - Software Foundation, either version 3 of the License, or 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 Affero General Public License for details. - - You should have received a copy of the GNU Affero General Public License - along with Ingen. If not, see . -*/ - -#include -#include - -#include - -#include "ingen/client/SigClientInterface.hpp" - -#include "App.hpp" -#include "BreadCrumbs.hpp" - -namespace Ingen { -namespace GUI { - -using std::string; - -BreadCrumbs::BreadCrumbs(App& app) - : Gtk::HBox() - , _active_path("/") - , _full_path("/") - , _enable_signal(true) -{ - app.sig_client()->signal_message().connect( - sigc::mem_fun(this, &BreadCrumbs::message)); - - set_can_focus(false); -} - -SPtr -BreadCrumbs::view(const Raul::Path& path) -{ - for (const auto& b : _breadcrumbs) { - if (b->path() == path) { - return b->view(); - } - } - - return SPtr(); -} - -/** Sets up the crumbs to display `path`. - * - * If `path` is already part of the shown path, it will be selected and the - * children preserved. - */ -void -BreadCrumbs::build(Raul::Path path, SPtr view) -{ - bool old_enable_signal = _enable_signal; - _enable_signal = false; - - if (!_breadcrumbs.empty() && (path.is_parent_of(_full_path) || path == _full_path)) { - // Moving to a path we already contain, just switch the active button - for (const auto& b : _breadcrumbs) { - if (b->path() == path) { - b->set_active(true); - if (!b->view()) { - b->set_view(view); - } - - // views are expensive, having two around for the same graph is a bug - assert(b->view() == view); - - } else { - b->set_active(false); - } - } - - _active_path = path; - _enable_signal = old_enable_signal; - - } else if (!_breadcrumbs.empty() && path.is_child_of(_full_path)) { - // Moving to a child of the full path, just append crumbs (preserve view cache) - - string suffix = path.substr(_full_path.length()); - while (suffix.length() > 0) { - if (suffix[0] == '/') { - suffix = suffix.substr(1); - } - const string name = suffix.substr(0, suffix.find("/")); - _full_path = _full_path.child(Raul::Symbol(name)); - BreadCrumb* but = create_crumb(_full_path, view); - pack_start(*but, false, false, 1); - _breadcrumbs.push_back(but); - but->show(); - if (suffix.find("/") == string::npos) { - break; - } else { - suffix = suffix.substr(suffix.find("/")+1); - } - } - - for (const auto& b : _breadcrumbs) { - b->set_active(false); - } - _breadcrumbs.back()->set_active(true); - - } else { - // Rebuild from scratch - // Getting here is bad unless absolutely necessary, since the GraphView cache is lost - - _full_path = path; - _active_path = path; - - // Empty existing breadcrumbs - for (const auto& b : _breadcrumbs) { - remove(*b); - } - _breadcrumbs.clear(); - - // Add root - BreadCrumb* root_but = create_crumb(Raul::Path("/"), view); - pack_start(*root_but, false, false, 1); - _breadcrumbs.push_front(root_but); - root_but->set_active(root_but->path() == _active_path); - - Raul::Path working_path("/"); - string suffix = path.substr(1); - while (suffix.length() > 0) { - if (suffix[0] == '/') { - suffix = suffix.substr(1); - } - const string name = suffix.substr(0, suffix.find("/")); - working_path = working_path.child(Raul::Symbol(name)); - BreadCrumb* but = create_crumb(working_path, view); - pack_start(*but, false, false, 1); - _breadcrumbs.push_back(but); - but->set_active(working_path == _active_path); - but->show(); - if (suffix.find("/") == string::npos) { - break; - } else { - suffix = suffix.substr(suffix.find("/")+1); - } - } - } - - _enable_signal = old_enable_signal; -} - -/** Create a new crumb, assigning it a reference to `view` if their paths - * match, otherwise ignoring `view`. - */ -BreadCrumbs::BreadCrumb* -BreadCrumbs::create_crumb(const Raul::Path& path, - SPtr view) -{ - BreadCrumb* but = manage( - new BreadCrumb(path, - ((view && path == view->graph()->path()) - ? view : SPtr()))); - - but->signal_toggled().connect( - sigc::bind(sigc::mem_fun(this, &BreadCrumbs::breadcrumb_clicked), - but)); - - return but; -} - -void -BreadCrumbs::breadcrumb_clicked(BreadCrumb* crumb) -{ - if (_enable_signal) { - _enable_signal = false; - - if (!crumb->get_active()) { - // Tried to turn off the current active button, bad user, no cookie - crumb->set_active(true); - } else { - signal_graph_selected.emit(crumb->path(), crumb->view()); - if (crumb->path() != _active_path) { - crumb->set_active(false); - } - } - _enable_signal = true; - } -} - -void -BreadCrumbs::message(const Message& msg) -{ - if (const Del* const del = boost::get(&msg)) { - object_destroyed(del->uri); - } -} - -void -BreadCrumbs::object_destroyed(const URI& uri) -{ - for (auto i = _breadcrumbs.begin(); i != _breadcrumbs.end(); ++i) { - if ((*i)->path() == uri.c_str()) { - // Remove all crumbs after the removed one (inclusive) - for (auto j = i; j != _breadcrumbs.end(); ) { - BreadCrumb* bc = *j; - j = _breadcrumbs.erase(j); - remove(*bc); - } - break; - } - } -} - -void -BreadCrumbs::object_moved(const Raul::Path& old_path, const Raul::Path& new_path) -{ - for (const auto& b : _breadcrumbs) { - if (b->path() == old_path) { - b->set_path(new_path); - } - } -} - -} // namespace GUI -} // namespace Ingen diff --git a/src/gui/BreadCrumbs.hpp b/src/gui/BreadCrumbs.hpp deleted file mode 100644 index 467d3bfc..00000000 --- a/src/gui/BreadCrumbs.hpp +++ /dev/null @@ -1,119 +0,0 @@ -/* - This file is part of Ingen. - Copyright 2007-2015 David Robillard - - 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 - Software Foundation, either version 3 of the License, or 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 Affero General Public License for details. - - You should have received a copy of the GNU Affero General Public License - along with Ingen. If not, see . -*/ - -#ifndef INGEN_GUI_BREADCRUMBS_HPP -#define INGEN_GUI_BREADCRUMBS_HPP - -#include - -#include -#include -#include - -#include "raul/Path.hpp" - -#include "ingen/client/GraphModel.hpp" -#include "ingen/types.hpp" - -#include "GraphView.hpp" - -namespace Ingen { -namespace GUI { - -/** Collection of breadcrumb buttons forming a path. - * This doubles as a cache for GraphViews. - * - * \ingroup GUI - */ -class BreadCrumbs : public Gtk::HBox -{ -public: - explicit BreadCrumbs(App& app); - - SPtr view(const Raul::Path& path); - - void build(Raul::Path path, SPtr view); - - sigc::signal > signal_graph_selected; - -private: - /** Breadcrumb button. - * - * Each Breadcrumb stores a reference to a GraphView for quick switching. - * So, the amount of allocated GraphViews at a given time is equal to the - * number of visible breadcrumbs (which is the perfect cache for GUI - * responsiveness balanced with mem consumption). - * - * \ingroup GUI - */ - class BreadCrumb : public Gtk::ToggleButton - { - public: - BreadCrumb(const Raul::Path& path, SPtr view = SPtr()) - : _path(path) - , _view(view) - { - assert(!view || view->graph()->path() == path); - set_border_width(0); - set_path(path); - set_can_focus(false); - show_all(); - } - - void set_view(SPtr view) { - assert(!view || view->graph()->path() == _path); - _view = view; - } - - const Raul::Path& path() const { return _path; } - SPtr view() const { return _view; } - - void set_path(const Raul::Path& path) { - remove(); - const char* text = (path.is_root()) ? "/" : path.symbol(); - Gtk::Label* lab = manage(new Gtk::Label(text)); - lab->set_padding(0, 0); - lab->show(); - add(*lab); - - if (_view && _view->graph()->path() != path) - _view.reset(); - } - - private: - Raul::Path _path; - SPtr _view; - }; - - BreadCrumb* create_crumb(const Raul::Path& path, - SPtr view = SPtr()); - - void breadcrumb_clicked(BreadCrumb* crumb); - - void message(const Message& msg); - void object_destroyed(const URI& uri); - void object_moved(const Raul::Path& old_path, const Raul::Path& new_path); - - Raul::Path _active_path; - Raul::Path _full_path; - bool _enable_signal; - std::list _breadcrumbs; -}; - -} // namespace GUI -} // namespace Ingen - -#endif // INGEN_GUI_BREADCRUMBS_HPP diff --git a/src/gui/ConnectWindow.cpp b/src/gui/ConnectWindow.cpp deleted file mode 100644 index 458a43dd..00000000 --- a/src/gui/ConnectWindow.cpp +++ /dev/null @@ -1,572 +0,0 @@ -/* - This file is part of Ingen. - Copyright 2007-2015 David Robillard - - 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 - Software Foundation, either version 3 of the License, or 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 Affero General Public License for details. - - You should have received a copy of the GNU Affero General Public License - along with Ingen. If not, see . -*/ - -#include -#include -#include -#include - -#include -#include - -#include "raul/Process.hpp" - -#include "ingen/Configuration.hpp" -#include "ingen/EngineBase.hpp" -#include "ingen/Interface.hpp" -#include "ingen/Log.hpp" -#include "ingen/Module.hpp" -#include "ingen/QueuedInterface.hpp" -#include "ingen/World.hpp" -#include "ingen/client/ClientStore.hpp" -#include "ingen/client/GraphModel.hpp" -#include "ingen/client/SigClientInterface.hpp" -#include "ingen/client/SocketClient.hpp" -#include "ingen_config.h" - -#include "App.hpp" -#include "ConnectWindow.hpp" -#include "WindowFactory.hpp" - -using namespace Ingen::Client; - -namespace Ingen { -namespace GUI { - -ConnectWindow::ConnectWindow(BaseObjectType* cobject, - Glib::RefPtr xml) - : Dialog(cobject) - , _xml(std::move(xml)) - , _icon(nullptr) - , _progress_bar(nullptr) - , _progress_label(nullptr) - , _url_entry(nullptr) - , _server_radio(nullptr) - , _port_spinbutton(nullptr) - , _launch_radio(nullptr) - , _internal_radio(nullptr) - , _activate_button(nullptr) - , _deactivate_button(nullptr) - , _disconnect_button(nullptr) - , _connect_button(nullptr) - , _quit_button(nullptr) - , _mode(Mode::CONNECT_REMOTE) - , _connect_uri("unix:///tmp/ingen.sock") - , _ping_id(-1) - , _attached(false) - , _finished_connecting(false) - , _widgets_loaded(false) - , _connect_stage(0) - , _quit_flag(false) -{ -} - -void -ConnectWindow::message(const Message& msg) -{ - if (const Response* const r = boost::get(&msg)) { - ingen_response(r->id, r->status, r->subject); - } else if (const Error* const e = boost::get(&msg)) { - error(e->message); - } -} - -void -ConnectWindow::error(const std::string& msg) -{ - if (!is_visible()) { - present(); - set_connecting_widget_states(); - } - - if (_progress_label) { - _progress_label->set_text(msg); - } - - if (_app && _app->world()) { - _app->world()->log().error(msg + "\n"); - } -} - -void -ConnectWindow::start(App& app, Ingen::World* world) -{ - _app = &app; - - if (world->engine()) { - _mode = Mode::INTERNAL; - } - - set_connected_to(world->interface()); - connect(bool(world->interface())); -} - -void -ConnectWindow::ingen_response(int32_t id, - Status status, - const std::string& subject) -{ - if (id == _ping_id) { - if (status != Status::SUCCESS) { - error("Failed to get root patch"); - } else { - _attached = true; - } - } -} - -void -ConnectWindow::set_connected_to(SPtr engine) -{ - _app->world()->set_interface(engine); - - if (!_widgets_loaded) { - return; - } - - if (engine) { - _icon->set(Gtk::Stock::CONNECT, Gtk::ICON_SIZE_LARGE_TOOLBAR); - _progress_bar->set_fraction(1.0); - _progress_label->set_text("Connected to engine"); - _url_entry->set_sensitive(false); - _url_entry->set_text(engine->uri().string()); - _connect_button->set_sensitive(false); - _disconnect_button->set_label("gtk-disconnect"); - _disconnect_button->set_sensitive(true); - _port_spinbutton->set_sensitive(false); - _launch_radio->set_sensitive(false); - _internal_radio->set_sensitive(false); - _activate_button->set_sensitive(true); - _deactivate_button->set_sensitive(true); - - } else { - _icon->set(Gtk::Stock::DISCONNECT, Gtk::ICON_SIZE_LARGE_TOOLBAR); - _progress_bar->set_fraction(0.0); - _connect_button->set_sensitive(true); - _disconnect_button->set_sensitive(false); - _internal_radio->set_sensitive(true); - _server_radio->set_sensitive(true); - _launch_radio->set_sensitive(true); - _activate_button->set_sensitive(false); - _deactivate_button->set_sensitive(false); - - if (_mode == Mode::CONNECT_REMOTE) { - _url_entry->set_sensitive(true); - } else if (_mode == Mode::LAUNCH_REMOTE) { - _port_spinbutton->set_sensitive(true); - } - - _progress_label->set_text(std::string("Disconnected")); - } -} - -void -ConnectWindow::set_connecting_widget_states() -{ - if (!_widgets_loaded) { - return; - } - - _connect_button->set_sensitive(false); - _disconnect_button->set_label("gtk-cancel"); - _disconnect_button->set_sensitive(true); - _server_radio->set_sensitive(false); - _launch_radio->set_sensitive(false); - _internal_radio->set_sensitive(false); - _url_entry->set_sensitive(false); - _port_spinbutton->set_sensitive(false); -} - -bool -ConnectWindow::connect_remote(const URI& uri) -{ - Ingen::World* world = _app->world(); - - SPtr sci(new SigClientInterface()); - SPtr qi(new QueuedInterface(sci)); - - SPtr iface(world->new_interface(uri, qi)); - if (iface) { - world->set_interface(iface); - _app->attach(qi); - _app->register_callbacks(); - return true; - } - - return false; -} - -/** Set up initial connect stage and launch connect callback. */ -void -ConnectWindow::connect(bool existing) -{ - if (_app->client()) { - error("Already connected"); - return; - } else if (_attached) { - _attached = false; - } - - set_connecting_widget_states(); - _connect_stage = 0; - - Ingen::World* world = _app->world(); - - if (_mode == Mode::CONNECT_REMOTE) { - std::string uri_str = world->conf().option("connect").ptr(); - if (existing) { - uri_str = world->interface()->uri(); - _connect_stage = 1; - SPtr client = dynamic_ptr_cast(world->interface()); - if (client) { - _app->attach(client->respondee()); - _app->register_callbacks(); - } else { - error("Connected with invalid client interface type"); - return; - } - } else if (_widgets_loaded) { - uri_str = _url_entry->get_text(); - } - - if (!URI::is_valid(uri_str)) { - error((fmt("Invalid socket URI %1%") % uri_str).str()); - return; - } - - _connect_uri = URI(uri_str); - - } else if (_mode == Mode::LAUNCH_REMOTE) { - const std::string port = std::to_string(_port_spinbutton->get_value_as_int()); - const char* cmd[] = { "ingen", "-e", "-E", port.c_str(), nullptr }; - - if (!Raul::Process::launch(cmd)) { - error("Failed to launch engine process"); - return; - } - - _connect_uri = URI(std::string("tcp://localhost:") + port); - - } else if (_mode == Mode::INTERNAL) { - if (!world->engine()) { - if (!world->load_module("server")) { - error("Failed to load server module"); - return; - } else if (!world->load_module("jack")) { - error("Failed to load jack module"); - return; - } else if (!world->engine()->activate()) { - error("Failed to activate engine"); - return; - } - } - } - - set_connecting_widget_states(); - if (_widgets_loaded) { - _progress_label->set_text("Connecting..."); - } - Glib::signal_timeout().connect( - sigc::mem_fun(this, &ConnectWindow::gtk_callback), 33); -} - -void -ConnectWindow::disconnect() -{ - _connect_stage = -1; - _attached = false; - - _app->detach(); - set_connected_to(SPtr()); - - if (!_widgets_loaded) { - return; - } - - _activate_button->set_sensitive(false); - _deactivate_button->set_sensitive(false); - - _progress_bar->set_fraction(0.0); - _connect_button->set_sensitive(true); - _disconnect_button->set_sensitive(false); -} - -void -ConnectWindow::activate() -{ - if (!_app->interface()) { - return; - } - - _app->interface()->set_property(URI("ingen:/driver"), - _app->uris().ingen_enabled, - _app->forge().make(true)); -} - -void -ConnectWindow::deactivate() -{ - if (!_app->interface()) { - return; - } - - _app->interface()->set_property(URI("ingen:/driver"), - _app->uris().ingen_enabled, - _app->forge().make(false)); -} - -void -ConnectWindow::on_show() -{ - if (!_widgets_loaded) { - load_widgets(); - } - - if (_attached) { - set_connected_to(_app->interface()); - } - - Gtk::Dialog::on_show(); -} - -void -ConnectWindow::load_widgets() -{ - _xml->get_widget("connect_icon", _icon); - _xml->get_widget("connect_progress_bar", _progress_bar); - _xml->get_widget("connect_progress_label", _progress_label); - _xml->get_widget("connect_server_radiobutton", _server_radio); - _xml->get_widget("connect_url_entry", _url_entry); - _xml->get_widget("connect_launch_radiobutton", _launch_radio); - _xml->get_widget("connect_port_spinbutton", _port_spinbutton); - _xml->get_widget("connect_internal_radiobutton", _internal_radio); - _xml->get_widget("connect_activate_button", _activate_button); - _xml->get_widget("connect_deactivate_button", _deactivate_button); - _xml->get_widget("connect_disconnect_button", _disconnect_button); - _xml->get_widget("connect_connect_button", _connect_button); - _xml->get_widget("connect_quit_button", _quit_button); - - _server_radio->signal_toggled().connect( - sigc::mem_fun(this, &ConnectWindow::server_toggled)); - _launch_radio->signal_toggled().connect( - sigc::mem_fun(this, &ConnectWindow::launch_toggled)); - _internal_radio->signal_clicked().connect( - sigc::mem_fun(this, &ConnectWindow::internal_toggled)); - _activate_button->signal_clicked().connect( - sigc::mem_fun(this, &ConnectWindow::activate)); - _deactivate_button->signal_clicked().connect( - sigc::mem_fun(this, &ConnectWindow::deactivate)); - _disconnect_button->signal_clicked().connect( - sigc::mem_fun(this, &ConnectWindow::disconnect)); - _connect_button->signal_clicked().connect( - sigc::bind(sigc::mem_fun(this, &ConnectWindow::connect), false)); - _quit_button->signal_clicked().connect( - sigc::mem_fun(this, &ConnectWindow::quit_clicked)); - - _url_entry->set_text(_app->world()->conf().option("connect").ptr()); - if (URI::is_valid(_url_entry->get_text())) { - _connect_uri = URI(_url_entry->get_text()); - } - - _port_spinbutton->set_range(1, std::numeric_limits::max()); - _port_spinbutton->set_increments(1, 100); - _port_spinbutton->set_value( - _app->world()->conf().option("engine-port").get()); - - _progress_bar->set_pulse_step(0.01); - _widgets_loaded = true; - - server_toggled(); -} - -void -ConnectWindow::on_hide() -{ - Gtk::Dialog::on_hide(); - if (_app->window_factory()->num_open_graph_windows() == 0) { - quit(); - } -} - -void -ConnectWindow::quit_clicked() -{ - if (_app->quit(this)) { - _quit_flag = true; - } -} - -void -ConnectWindow::server_toggled() -{ - _url_entry->set_sensitive(true); - _port_spinbutton->set_sensitive(false); - _mode = Mode::CONNECT_REMOTE; -} - -void -ConnectWindow::launch_toggled() -{ - _url_entry->set_sensitive(false); - _port_spinbutton->set_sensitive(true); - _mode = Mode::LAUNCH_REMOTE; -} - -void -ConnectWindow::internal_toggled() -{ - _url_entry->set_sensitive(false); - _port_spinbutton->set_sensitive(false); - _mode = Mode::INTERNAL; -} - -void -ConnectWindow::next_stage() -{ - static const char* labels[] = { - "Connecting...", - "Pinging engine...", - "Attaching to engine...", - "Requesting root graph...", - "Loading plugins...", - "Connected" - }; - - - ++_connect_stage; - if (_widgets_loaded) { - _progress_label->set_text(labels[_connect_stage]); - } -} - -bool -ConnectWindow::gtk_callback() -{ - /* If I call this a "state machine" it's not ugly code any more */ - - if (_quit_flag) { - return false; // deregister this callback - } - - // Timing stuff for repeated attach attempts - timeval now; - gettimeofday(&now, nullptr); - static const timeval start = now; - static timeval last = now; - static unsigned attempts = 0; - - // Show if attempted connection goes on for a noticeable amount of time - if (!is_visible()) { - const float ms_since_start = (now.tv_sec - start.tv_sec) * 1000.0f + - (now.tv_usec - start.tv_usec) * 0.001f; - if (ms_since_start > 500) { - present(); - set_connecting_widget_states(); - } - } - - if (_connect_stage == 0) { - const float ms_since_last = (now.tv_sec - last.tv_sec) * 1000.0f + - (now.tv_usec - last.tv_usec) * 0.001f; - if (ms_since_last >= 250) { - last = now; - if (_mode == Mode::INTERNAL) { - SPtr client(new SigClientInterface()); - _app->world()->interface()->set_respondee(client); - _app->attach(client); - _app->register_callbacks(); - next_stage(); - } else if (connect_remote(_connect_uri)) { - next_stage(); - } - } - } else if (_connect_stage == 1) { - _attached = false; - _app->sig_client()->signal_message().connect( - sigc::mem_fun(this, &ConnectWindow::message)); - - _ping_id = g_random_int_range(1, std::numeric_limits::max()); - _app->interface()->set_response_id(_ping_id); - _app->interface()->get(URI("ingen:/engine")); - last = now; - attempts = 0; - next_stage(); - - } else if (_connect_stage == 2) { - if (_attached) { - next_stage(); - } else { - const float ms_since_last = (now.tv_sec - last.tv_sec) * 1000.0f + - (now.tv_usec - last.tv_usec) * 0.001f; - if (attempts > 10) { - error("Failed to ping engine"); - _connect_stage = -1; - } else if (ms_since_last > 1000) { - _app->interface()->set_response_id(_ping_id); - _app->interface()->get(URI("ingen:/engine")); - last = now; - ++attempts; - } - } - } else if (_connect_stage == 3) { - _app->interface()->get(URI(main_uri().string() + "/")); - next_stage(); - } else if (_connect_stage == 4) { - if (_app->store()->size() > 0) { - SPtr root = dynamic_ptr_cast( - _app->store()->object(Raul::Path("/"))); - if (root) { - set_connected_to(_app->interface()); - _app->window_factory()->present_graph(root); - next_stage(); - } - } - } else if (_connect_stage == 5) { - hide(); - _connect_stage = 0; // set ourselves up for next time (if there is one) - _finished_connecting = true; - _app->interface()->set_response_id(1); - return false; // deregister this callback - } - - if (_widgets_loaded) { - _progress_bar->pulse(); - } - - if (_connect_stage == -1) { // we were cancelled - if (_widgets_loaded) { - _icon->set(Gtk::Stock::DISCONNECT, Gtk::ICON_SIZE_LARGE_TOOLBAR); - _progress_bar->set_fraction(0.0); - _connect_button->set_sensitive(true); - _disconnect_button->set_sensitive(false); - _disconnect_button->set_label("gtk-disconnect"); - _progress_label->set_text(std::string("Disconnected")); - } - return false; - } else { - return true; - } -} - -void -ConnectWindow::quit() -{ - _quit_flag = true; - Gtk::Main::quit(); -} - -} // namespace GUI -} // namespace Ingen diff --git a/src/gui/ConnectWindow.hpp b/src/gui/ConnectWindow.hpp deleted file mode 100644 index 08560361..00000000 --- a/src/gui/ConnectWindow.hpp +++ /dev/null @@ -1,116 +0,0 @@ -/* - This file is part of Ingen. - Copyright 2007-2015 David Robillard - - 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 - Software Foundation, either version 3 of the License, or 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 Affero General Public License for details. - - You should have received a copy of the GNU Affero General Public License - along with Ingen. If not, see . -*/ - -#ifndef INGEN_GUI_CONNECTWINDOW_HPP -#define INGEN_GUI_CONNECTWINDOW_HPP - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "ingen/types.hpp" -#include "lilv/lilv.h" - -#include "Window.hpp" - -namespace Ingen { -namespace GUI { - -class App; - -/** The initially visible "Connect to engine" window. - * - * This handles actually connecting to the engine and making sure everything - * is ready before really launching the app. - * - * \ingroup GUI - */ -class ConnectWindow : public Dialog -{ -public: - ConnectWindow(BaseObjectType* cobject, - Glib::RefPtr xml); - - void set_connected_to(SPtr engine); - void start(App& app, Ingen::World* world); - - bool attached() const { return _finished_connecting; } - bool quit_flag() const { return _quit_flag; } - -private: - enum class Mode { CONNECT_REMOTE, LAUNCH_REMOTE, INTERNAL }; - - void message(const Message& msg); - - void error(const std::string& msg); - - void ingen_response(int32_t id, Status status, const std::string& subject); - - void server_toggled(); - void launch_toggled(); - void internal_toggled(); - - void disconnect(); - void next_stage(); - bool connect_remote(const URI& uri); - void connect(bool existing); - void activate(); - void deactivate(); - void quit_clicked(); - void on_show(); - void on_hide(); - - void load_widgets(); - void set_connecting_widget_states(); - - bool gtk_callback(); - void quit(); - - const Glib::RefPtr _xml; - - Gtk::Image* _icon; - Gtk::ProgressBar* _progress_bar; - Gtk::Label* _progress_label; - Gtk::Entry* _url_entry; - Gtk::RadioButton* _server_radio; - Gtk::SpinButton* _port_spinbutton; - Gtk::RadioButton* _launch_radio; - Gtk::RadioButton* _internal_radio; - Gtk::Button* _activate_button; - Gtk::Button* _deactivate_button; - Gtk::Button* _disconnect_button; - Gtk::Button* _connect_button; - Gtk::Button* _quit_button; - - Mode _mode; - URI _connect_uri; - int32_t _ping_id; - bool _attached; - bool _finished_connecting; - bool _widgets_loaded; - int _connect_stage; - bool _quit_flag; -}; - -} // namespace GUI -} // namespace Ingen - -#endif // INGEN_GUI_CONNECTWINDOW_HPP diff --git a/src/gui/GraphBox.cpp b/src/gui/GraphBox.cpp deleted file mode 100644 index 6f9969be..00000000 --- a/src/gui/GraphBox.cpp +++ /dev/null @@ -1,922 +0,0 @@ -/* - This file is part of Ingen. - Copyright 2007-2017 David Robillard - - 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 - Software Foundation, either version 3 of the License, or 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 Affero General Public License for details. - - You should have received a copy of the GNU Affero General Public License - along with Ingen. If not, see . -*/ - -#include -#include -#include - -#include -#include -#include -#include - -#include "ingen/Configuration.hpp" -#include "ingen/Interface.hpp" -#include "ingen/Log.hpp" -#include "ingen/client/ClientStore.hpp" -#include "ingen/client/GraphModel.hpp" - -#include "App.hpp" -#include "BreadCrumbs.hpp" -#include "ConnectWindow.hpp" -#include "GraphCanvas.hpp" -#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" - -#ifdef HAVE_WEBKIT -#include -#endif - -namespace Ingen { - -using namespace Client; - -namespace GUI { - -static const int STATUS_CONTEXT_ENGINE = 0; -static const int STATUS_CONTEXT_GRAPH = 1; -static const int STATUS_CONTEXT_HOVER = 2; - -GraphBox::GraphBox(BaseObjectType* cobject, - const Glib::RefPtr& xml) - : Gtk::VBox(cobject) - , _app(nullptr) - , _window(nullptr) - , _breadcrumbs(nullptr) - , _has_shown_documentation(false) - , _enable_signal(true) -{ - property_visible() = false; - - xml->get_widget("graph_win_alignment", _alignment); - xml->get_widget("graph_win_status_bar", _status_bar); - xml->get_widget("graph_import_menuitem", _menu_import); - xml->get_widget("graph_save_menuitem", _menu_save); - xml->get_widget("graph_save_as_menuitem", _menu_save_as); - xml->get_widget("graph_export_image_menuitem", _menu_export_image); - xml->get_widget("graph_redo_menuitem", _menu_redo); - xml->get_widget("graph_undo_menuitem", _menu_undo); - xml->get_widget("graph_cut_menuitem", _menu_cut); - xml->get_widget("graph_copy_menuitem", _menu_copy); - xml->get_widget("graph_paste_menuitem", _menu_paste); - xml->get_widget("graph_delete_menuitem", _menu_delete); - xml->get_widget("graph_select_all_menuitem", _menu_select_all); - xml->get_widget("graph_close_menuitem", _menu_close); - xml->get_widget("graph_quit_menuitem", _menu_quit); - xml->get_widget("graph_view_control_window_menuitem", _menu_view_control_window); - xml->get_widget("graph_view_engine_window_menuitem", _menu_view_engine_window); - xml->get_widget("graph_properties_menuitem", _menu_view_graph_properties); - xml->get_widget("graph_parent_menuitem", _menu_parent); - xml->get_widget("graph_refresh_menuitem", _menu_refresh); - xml->get_widget("graph_fullscreen_menuitem", _menu_fullscreen); - xml->get_widget("graph_animate_signals_menuitem", _menu_animate_signals); - xml->get_widget("graph_sprung_layout_menuitem", _menu_sprung_layout); - xml->get_widget("graph_human_names_menuitem", _menu_human_names); - xml->get_widget("graph_show_port_names_menuitem", _menu_show_port_names); - xml->get_widget("graph_zoom_in_menuitem", _menu_zoom_in); - xml->get_widget("graph_zoom_out_menuitem", _menu_zoom_out); - xml->get_widget("graph_zoom_normal_menuitem", _menu_zoom_normal); - xml->get_widget("graph_zoom_full_menuitem", _menu_zoom_full); - xml->get_widget("graph_increase_font_size_menuitem", _menu_increase_font_size); - xml->get_widget("graph_decrease_font_size_menuitem", _menu_decrease_font_size); - xml->get_widget("graph_normal_font_size_menuitem", _menu_normal_font_size); - xml->get_widget("graph_doc_pane_menuitem", _menu_show_doc_pane); - xml->get_widget("graph_status_bar_menuitem", _menu_show_status_bar); - xml->get_widget("graph_arrange_menuitem", _menu_arrange); - xml->get_widget("graph_view_messages_window_menuitem", _menu_view_messages_window); - xml->get_widget("graph_view_graph_tree_window_menuitem", _menu_view_graph_tree_window); - xml->get_widget("graph_help_about_menuitem", _menu_help_about); - xml->get_widget("graph_documentation_paned", _doc_paned); - xml->get_widget("graph_documentation_scrolledwindow", _doc_scrolledwindow); - - _menu_view_control_window->property_sensitive() = false; - _menu_import->signal_activate().connect( - sigc::mem_fun(this, &GraphBox::event_import)); - _menu_save->signal_activate().connect( - sigc::mem_fun(this, &GraphBox::event_save)); - _menu_save_as->signal_activate().connect( - sigc::mem_fun(this, &GraphBox::event_save_as)); - _menu_export_image->signal_activate().connect( - sigc::mem_fun(this, &GraphBox::event_export_image)); - _menu_redo->signal_activate().connect( - sigc::mem_fun(this, &GraphBox::event_redo)); - _menu_undo->signal_activate().connect( - sigc::mem_fun(this, &GraphBox::event_undo)); - _menu_copy->signal_activate().connect( - sigc::mem_fun(this, &GraphBox::event_copy)); - _menu_paste->signal_activate().connect( - sigc::mem_fun(this, &GraphBox::event_paste)); - _menu_delete->signal_activate().connect( - sigc::mem_fun(this, &GraphBox::event_delete)); - _menu_select_all->signal_activate().connect( - sigc::mem_fun(this, &GraphBox::event_select_all)); - _menu_close->signal_activate().connect( - sigc::mem_fun(this, &GraphBox::event_close)); - _menu_quit->signal_activate().connect( - sigc::mem_fun(this, &GraphBox::event_quit)); - _menu_parent->signal_activate().connect( - sigc::mem_fun(this, &GraphBox::event_parent_activated)); - _menu_refresh->signal_activate().connect( - sigc::mem_fun(this, &GraphBox::event_refresh_activated)); - _menu_fullscreen->signal_activate().connect( - sigc::mem_fun(this, &GraphBox::event_fullscreen_toggled)); - _menu_animate_signals->signal_activate().connect( - sigc::mem_fun(this, &GraphBox::event_animate_signals_toggled)); - _menu_sprung_layout->signal_activate().connect( - sigc::mem_fun(this, &GraphBox::event_sprung_layout_toggled)); - _menu_human_names->signal_activate().connect( - sigc::mem_fun(this, &GraphBox::event_human_names_toggled)); - _menu_show_doc_pane->signal_activate().connect( - sigc::mem_fun(this, &GraphBox::event_doc_pane_toggled)); - _menu_show_status_bar->signal_activate().connect( - sigc::mem_fun(this, &GraphBox::event_status_bar_toggled)); - _menu_show_port_names->signal_activate().connect( - sigc::mem_fun(this, &GraphBox::event_port_names_toggled)); - _menu_arrange->signal_activate().connect( - sigc::mem_fun(this, &GraphBox::event_arrange)); - _menu_zoom_in->signal_activate().connect( - sigc::mem_fun(this, &GraphBox::event_zoom_in)); - _menu_zoom_out->signal_activate().connect( - sigc::mem_fun(this, &GraphBox::event_zoom_out)); - _menu_zoom_normal->signal_activate().connect( - sigc::mem_fun(this, &GraphBox::event_zoom_normal)); - _menu_zoom_full->signal_activate().connect( - sigc::mem_fun(this, &GraphBox::event_zoom_full)); - _menu_increase_font_size->signal_activate().connect( - sigc::mem_fun(this, &GraphBox::event_increase_font_size)); - _menu_decrease_font_size->signal_activate().connect( - sigc::mem_fun(this, &GraphBox::event_decrease_font_size)); - _menu_normal_font_size->signal_activate().connect( - sigc::mem_fun(this, &GraphBox::event_normal_font_size)); - _menu_view_engine_window->signal_activate().connect( - sigc::mem_fun(this, &GraphBox::event_show_engine)); - _menu_view_graph_properties->signal_activate().connect( - sigc::mem_fun(this, &GraphBox::event_show_properties)); - - Glib::RefPtr clipboard = Gtk::Clipboard::get(); - clipboard->signal_owner_change().connect( - sigc::mem_fun(this, &GraphBox::event_clipboard_changed)); - -#ifdef __APPLE__ - _menu_paste->set_sensitive(true); -#endif - - _status_label = Gtk::manage(new Gtk::Label("STATUS")); - _status_bar->pack_start(*_status_label, false, true, 0); - _status_label->show(); -} - -GraphBox::~GraphBox() -{ - delete _breadcrumbs; -} - -SPtr -GraphBox::create(App& app, SPtr graph) -{ - GraphBox* result = nullptr; - Glib::RefPtr xml = WidgetFactory::create("graph_win"); - xml->get_widget_derived("graph_win_vbox", result); - result->init_box(app); - result->set_graph(graph, SPtr()); - - if (app.is_plugin()) { - result->_menu_close->set_sensitive(false); - result->_menu_quit->set_sensitive(false); - } - - return SPtr(result); -} - -void -GraphBox::init_box(App& app) -{ - _app = &app; - - const URI engine_uri(_app->interface()->uri()); - if (engine_uri == "ingen:/clients/event_writer") { - _status_bar->push("Running internal engine", STATUS_CONTEXT_ENGINE); - } else { - _status_bar->push( - (fmt("Connected to %1%") % engine_uri).str(), - STATUS_CONTEXT_ENGINE); - } - - _menu_view_messages_window->signal_activate().connect( - sigc::mem_fun(_app->messages_dialog(), &MessagesWindow::present)); - _menu_view_graph_tree_window->signal_activate().connect( - sigc::mem_fun(_app->graph_tree(), &GraphTreeWindow::present)); - - _menu_help_about->signal_activate().connect( - sigc::hide_return(sigc::mem_fun(_app, &App::show_about))); - - _breadcrumbs = new BreadCrumbs(*_app); - _breadcrumbs->signal_graph_selected.connect( - sigc::mem_fun(this, &GraphBox::set_graph_from_path)); - - _status_label->set_markup(app.status_text()); - app.signal_status_text_changed.connect( - sigc::mem_fun(*this, &GraphBox::set_status_text)); -} - -void -GraphBox::set_status_text(const std::string& text) -{ - _status_label->set_markup(text); -} - -void -GraphBox::set_graph_from_path(const Raul::Path& path, SPtr view) -{ - if (view) { - assert(view->graph()->path() == path); - _app->window_factory()->present_graph(view->graph(), _window, view); - } else { - SPtr model = dynamic_ptr_cast( - _app->store()->object(path)); - if (model) { - _app->window_factory()->present_graph(model, _window); - } - } -} - -/** Sets the graph for this box and initializes everything. - * - * If `view` is NULL, a new view will be created. - */ -void -GraphBox::set_graph(SPtr graph, - SPtr view) -{ - if (!graph || graph == _graph) { - return; - } - - _enable_signal = false; - - new_port_connection.disconnect(); - removed_port_connection.disconnect(); - edit_mode_connection.disconnect(); - _entered_connection.disconnect(); - _left_connection.disconnect(); - - _status_bar->pop(STATUS_CONTEXT_GRAPH); - - _graph = graph; - _view = view; - - if (!_view) { - _view = _breadcrumbs->view(graph->path()); - } - - if (!_view) { - _view = GraphView::create(*_app, graph); - } - - assert(_view); - - graph->signal_property().connect( - sigc::mem_fun(this, &GraphBox::property_changed)); - - if (!_view->canvas()->supports_sprung_layout()) { - _menu_sprung_layout->set_active(false); - _menu_sprung_layout->set_sensitive(false); - } - - // Add view to our alignment - if (_view->get_parent()) { - _view->get_parent()->remove(*_view.get()); - } - - _alignment->remove(); - _alignment->add(*_view.get()); - - if (_breadcrumbs->get_parent()) { - _breadcrumbs->get_parent()->remove(*_breadcrumbs); - } - - _view->breadcrumb_container()->remove(); - _view->breadcrumb_container()->add(*_breadcrumbs); - _view->breadcrumb_container()->show(); - - _breadcrumbs->build(graph->path(), _view); - _breadcrumbs->show(); - - _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_parent->property_sensitive() = bool(graph->parent()); - - new_port_connection = graph->signal_new_port().connect( - sigc::mem_fun(this, &GraphBox::graph_port_added)); - removed_port_connection = graph->signal_removed_port().connect( - sigc::mem_fun(this, &GraphBox::graph_port_removed)); - - show(); - _alignment->show_all(); - - _menu_human_names->set_active( - _app->world()->conf().option("human-names").get()); - _menu_show_port_names->set_active( - _app->world()->conf().option("port-labels").get()); - - _doc_paned->set_position(std::numeric_limits::max()); - _doc_scrolledwindow->hide(); - - _enable_signal = true; -} - -void -GraphBox::graph_port_added(SPtr port) -{ - if (port->is_input() && _app->can_control(port.get())) { - _menu_view_control_window->property_sensitive() = true; - } -} - -void -GraphBox::graph_port_removed(SPtr 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; -} - -void -GraphBox::property_changed(const URI& predicate, const Atom& value) -{ - if (predicate == _app->uris().ingen_sprungLayout) { - if (value.type() == _app->uris().forge.Bool) { - _menu_sprung_layout->set_active(value.get()); - } - } -} - -void -GraphBox::set_documentation(const std::string& doc, bool html) -{ - _doc_scrolledwindow->remove(); - if (doc.empty()) { - _doc_scrolledwindow->hide(); - return; - } -#ifdef HAVE_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))); - _doc_scrolledwindow->add(*widget); - widget->show(); -#else - Gtk::TextView* view = Gtk::manage(new Gtk::TextView()); - view->get_buffer()->set_text(doc); - view->set_wrap_mode(Gtk::WRAP_WORD); - _doc_scrolledwindow->add(*view); - view->show(); -#endif -} - -void -GraphBox::show_status(const ObjectModel* model) -{ - std::stringstream msg; - msg << model->path(); - - const PortModel* port = nullptr; - const BlockModel* block = nullptr; - - if ((port = dynamic_cast(model))) { - show_port_status(port, port->value()); - - } else if ((block = dynamic_cast(model))) { - const PluginModel* plugin = dynamic_cast(block->plugin()); - if (plugin) { - msg << ((boost::format(" (%1%)") % plugin->human_name()).str()); - } - _status_bar->push(msg.str(), STATUS_CONTEXT_HOVER); - } -} - -void -GraphBox::show_port_status(const PortModel* port, const Atom& value) -{ - std::stringstream msg; - msg << port->path(); - - const BlockModel* parent = dynamic_cast(port->parent().get()); - if (parent) { - const PluginModel* plugin = dynamic_cast(parent->plugin()); - if (plugin) { - const std::string& human_name = plugin->port_human_name(port->index()); - if (!human_name.empty()) { - msg << " (" << human_name << ")"; - } - } - } - - if (value.is_valid()) { - msg << " = " << _app->forge().str(value, true); - } - - _status_bar->pop(STATUS_CONTEXT_HOVER); - _status_bar->push(msg.str(), STATUS_CONTEXT_HOVER); -} - -void -GraphBox::object_entered(const ObjectModel* model) -{ - show_status(model); -} - -void -GraphBox::object_left(const ObjectModel* model) -{ - _status_bar->pop(STATUS_CONTEXT_GRAPH); - _status_bar->pop(STATUS_CONTEXT_HOVER); -} - -void -GraphBox::event_show_engine() -{ - if (_graph) { - _app->connect_window()->show(); - } -} - -void -GraphBox::event_clipboard_changed(GdkEventOwnerChange* ev) -{ - Glib::RefPtr clipboard = Gtk::Clipboard::get(); - _menu_paste->set_sensitive(clipboard->wait_is_text_available()); -} - -void -GraphBox::event_show_properties() -{ - _app->window_factory()->present_properties(_graph); -} - -void -GraphBox::event_import() -{ - _app->window_factory()->present_load_graph(_graph); -} - -void -GraphBox::event_save() -{ - const Atom& document = _graph->get_property(_app->uris().ingen_file); - if (!document.is_valid() || document.type() != _app->uris().forge.URI) { - event_save_as(); - } else { - save_graph(URI(document.ptr())); - } -} - -void -GraphBox::error(const Glib::ustring& message, - const Glib::ustring& secondary_text) -{ - Gtk::MessageDialog dialog( - message, true, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true); - dialog.set_secondary_text(secondary_text); - if (_window) { - dialog.set_transient_for(*_window); - } - dialog.run(); -} - -bool -GraphBox::confirm(const Glib::ustring& message, - const Glib::ustring& secondary_text) -{ - Gtk::MessageDialog dialog( - message, true, Gtk::MESSAGE_WARNING, Gtk::BUTTONS_YES_NO, true); - dialog.set_secondary_text(secondary_text); - if (_window) { - dialog.set_transient_for(*_window); - } - return dialog.run() == Gtk::RESPONSE_YES; -} - -void -GraphBox::save_graph(const URI& uri) -{ - if (_app->interface()->uri().string().substr(0, 3) == "tcp") { - _status_bar->push( - (boost::format("Saved %1% to %2% on client") - % _graph->path() % uri).str(), - STATUS_CONTEXT_GRAPH); - _app->loader()->save_graph(_graph, uri); - } else { - _status_bar->push( - (boost::format("Saved %1% to %2% on server") - % _graph->path() % uri).str(), - STATUS_CONTEXT_GRAPH); - _app->interface()->copy(_graph->uri(), uri); - } -} - -void -GraphBox::event_save_as() -{ - const URIs& uris = _app->uris(); - while (true) { - Gtk::FileChooserDialog dialog( - "Save Graph", Gtk::FILE_CHOOSER_ACTION_SAVE); - if (_window) { - dialog.set_transient_for(*_window); - } - - dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL); - Gtk::Button* save_button = dialog.add_button(Gtk::Stock::SAVE, Gtk::RESPONSE_OK); - save_button->property_has_default() = true; - - Gtk::FileFilter filt; - filt.add_pattern("*.ingen"); - filt.set_name("Ingen bundles"); - dialog.set_filter(filt); - - // Set current folder to most sensible default - const Atom& document = _graph->get_property(uris.ingen_file); - const Atom& dir = _app->world()->conf().option("graph-directory"); - if (document.type() == uris.forge.URI) { - dialog.set_uri(document.ptr()); - } else if (dir.is_valid()) { - dialog.set_current_folder(dir.ptr()); - } - - if (dialog.run() != Gtk::RESPONSE_OK) { - break; - } - - std::string filename = dialog.get_filename(); - std::string basename = Glib::path_get_basename(filename); - - if (basename.find('.') == std::string::npos) { - 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") { - error("File does not appear to be in an Ingen bundle."); - } - } else if (filename.substr(filename.length() - 6) != ".ingen") { - error("Ingen bundles must end in \".ingen\""); - continue; - } - - const std::string symbol(basename.substr(0, basename.find('.'))); - - if (!Raul::Symbol::is_valid(symbol)) { - error( - "Ingen bundle names must be valid symbols.", - "All characters must be _, a-z, A-Z, or 0-9, but the first may not be 0-9."); - continue; - } - - //_graph->set_property(uris.lv2_symbol, Atom(symbol.c_str())); - - bool confirmed = true; - if (Glib::file_test(filename, Glib::FILE_TEST_IS_DIR)) { - if (Glib::file_test(Glib::build_filename(filename, "manifest.ttl"), - Glib::FILE_TEST_EXISTS)) { - confirmed = confirm( - (boost::format("The bundle \"%1%\" already exists." - " Replace it?") % basename).str()); - } else { - confirmed = confirm( - (boost::format("A directory named \"%1%\" already exists," - "but is not an Ingen bundle. " - "Save into it anyway?") % basename).str(), - "This will create at least 2 .ttl files in this directory," - "and possibly several more files and/or directories, recursively. " - "Existing files will be overwritten."); - } - } else if (Glib::file_test(filename, Glib::FILE_TEST_EXISTS)) { - confirmed = confirm( - (boost::format("A file named \"%1%\" already exists. " - "Replace it with an Ingen bundle?") - % basename).str()); - if (confirmed) { - ::g_remove(filename.c_str()); - } - } - - if (confirmed) { - const Glib::ustring uri = Glib::filename_to_uri(filename); - save_graph(URI(uri)); - - const_cast(_graph.get())->set_property( - uris.ingen_file, - _app->forge().alloc_uri(uri.c_str())); - } - - _app->world()->conf().set( - "graph-directory", - _app->world()->forge().alloc(dialog.get_current_folder())); - - break; - } -} - -void -GraphBox::event_export_image() -{ - Gtk::FileChooserDialog dialog("Export Image", Gtk::FILE_CHOOSER_ACTION_SAVE); - dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL); - dialog.add_button(Gtk::Stock::SAVE, Gtk::RESPONSE_OK); - dialog.set_default_response(Gtk::RESPONSE_OK); - if (_window) { - dialog.set_transient_for(*_window); - } - - typedef std::map Types; - Types 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) { - Gtk::FileFilter filt; - filt.add_pattern(t->first); - filt.set_name(t->second); - dialog.add_filter(filt); - 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); - bg_but->set_active(true); - extra->add(*Gtk::manage(bg_but)); - extra->show_all(); - dialog.set_extra_widget(*Gtk::manage(extra)); - - if (dialog.run() == Gtk::RESPONSE_OK) { - const std::string filename = dialog.get_filename(); - if (Glib::file_test(filename, Glib::FILE_TEST_EXISTS)) { - Gtk::MessageDialog confirm( - std::string("File exists! Overwrite ") + filename + "?", - true, Gtk::MESSAGE_WARNING, Gtk::BUTTONS_YES_NO, true); - confirm.set_transient_for(dialog); - if (confirm.run() != Gtk::RESPONSE_YES) { - return; - } - } - _view->canvas()->export_image(filename.c_str(), bg_but->get_active()); - _status_bar->push((boost::format("Rendered %1% to %2%") - % _graph->path() % filename).str(), - STATUS_CONTEXT_GRAPH); - } -} - -void -GraphBox::event_copy() -{ - if (_view) { - _view->canvas()->copy_selection(); - } -} - -void -GraphBox::event_redo() -{ - _app->interface()->redo(); -} - -void -GraphBox::event_undo() -{ - _app->interface()->undo(); -} - -void -GraphBox::event_paste() -{ - if (_view) { - _view->canvas()->paste(); - } -} - -void -GraphBox::event_delete() -{ - if (_view) { - _view->canvas()->destroy_selection(); - } -} - -void -GraphBox::event_select_all() -{ - if (_view) { - _view->canvas()->select_all(); - } -} - -void -GraphBox::event_close() -{ - if (_window) { - _app->window_factory()->remove_graph_window(_window); - } -} - -void -GraphBox::event_quit() -{ - _app->quit(_window); -} - -void -GraphBox::event_zoom_in() -{ - _view->canvas()->set_font_size(_view->canvas()->get_font_size() + 1.0); -} - -void -GraphBox::event_zoom_out() -{ - _view->canvas()->set_font_size(_view->canvas()->get_font_size() - 1.0); -} - -void -GraphBox::event_zoom_normal() -{ - _view->canvas()->set_zoom(1.0); -} - -void -GraphBox::event_zoom_full() -{ - _view->canvas()->zoom_full(); -} - -void -GraphBox::event_increase_font_size() -{ - _view->canvas()->set_font_size(_view->canvas()->get_font_size() + 1.0); -} -void -GraphBox::event_decrease_font_size() -{ - _view->canvas()->set_font_size(_view->canvas()->get_font_size() - 1.0); -} -void -GraphBox::event_normal_font_size() -{ - _view->canvas()->set_font_size(_view->canvas()->get_default_font_size()); -} - -void -GraphBox::event_arrange() -{ - _app->interface()->bundle_begin(); - _view->canvas()->arrange(); - _app->interface()->bundle_end(); -} - -void -GraphBox::event_parent_activated() -{ - SPtr parent = dynamic_ptr_cast(_graph->parent()); - if (parent) { - _app->window_factory()->present_graph(parent, _window); - } -} - -void -GraphBox::event_refresh_activated() -{ - _app->interface()->get(_graph->uri()); -} - -void -GraphBox::event_fullscreen_toggled() -{ - // FIXME: ugh, use GTK signals to track state and know for sure - static bool is_fullscreen = false; - - if (_window) { - if (!is_fullscreen) { - _window->fullscreen(); - is_fullscreen = true; - } else { - _window->unfullscreen(); - is_fullscreen = false; - } - } -} - -void -GraphBox::event_doc_pane_toggled() -{ - if (_menu_show_doc_pane->get_active()) { - _doc_scrolledwindow->show_all(); - if (!_has_shown_documentation) { - const Gtk::Allocation allocation = get_allocation(); - _doc_paned->set_position(allocation.get_width() / 1.61803399); - _has_shown_documentation = true; - } - } else { - _doc_scrolledwindow->hide(); - } -} - -void -GraphBox::event_status_bar_toggled() -{ - if (_menu_show_status_bar->get_active()) { - _status_bar->show(); - } else { - _status_bar->hide(); - } -} - -void -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())); -} - -void -GraphBox::event_sprung_layout_toggled() -{ - const bool sprung = _menu_sprung_layout->get_active(); - - _view->canvas()->set_sprung_layout(sprung); - - Properties properties; - properties.emplace(_app->uris().ingen_sprungLayout, - _app->forge().make(sprung)); - _app->interface()->put(_graph->uri(), properties); -} - -void -GraphBox::event_human_names_toggled() -{ - _view->canvas()->show_human_names(_menu_human_names->get_active()); - _app->world()->conf().set( - "human-names", - _app->world()->forge().make(_menu_human_names->get_active())); -} - -void -GraphBox::event_port_names_toggled() -{ - _app->world()->conf().set( - "port-labels", - _app->world()->forge().make(_menu_show_port_names->get_active())); - if (_menu_show_port_names->get_active()) { - _view->canvas()->set_direction(GANV_DIRECTION_RIGHT); - _view->canvas()->show_port_names(true); - } else { - _view->canvas()->set_direction(GANV_DIRECTION_DOWN); - _view->canvas()->show_port_names(false); - } -} - -} // namespace GUI -} // namespace Ingen diff --git a/src/gui/GraphBox.hpp b/src/gui/GraphBox.hpp deleted file mode 100644 index fd9bf9c0..00000000 --- a/src/gui/GraphBox.hpp +++ /dev/null @@ -1,213 +0,0 @@ -/* - This file is part of Ingen. - Copyright 2007-2016 David Robillard - - 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 - Software Foundation, either version 3 of the License, or 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 Affero General Public License for details. - - You should have received a copy of the GNU Affero General Public License - along with Ingen. If not, see . -*/ - -#ifndef INGEN_GUI_GRAPH_BOX_HPP -#define INGEN_GUI_GRAPH_BOX_HPP - -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "ingen/ingen.h" -#include "ingen/types.hpp" - -#include "Window.hpp" - -namespace Raul { -class Atom; -class Path; -} - -namespace Ingen { - -class URI; - -namespace Client { -class GraphModel; -class PortModel; -class ObjectModel; -} - -namespace GUI { - -class BreadCrumbs; -class LoadGraphBox; -class LoadPluginWindow; -class NewSubgraphWindow; -class GraphDescriptionWindow; -class GraphView; -class GraphWindow; -class SubgraphModule; - -/** A window for a graph. - * - * \ingroup GUI - */ -class INGEN_API GraphBox : public Gtk::VBox -{ -public: - GraphBox(BaseObjectType* cobject, - const Glib::RefPtr& xml); - ~GraphBox(); - - static SPtr create( - App& app, SPtr graph); - - void init_box(App& app); - - void set_status_text(const std::string& text); - - void set_graph(SPtr graph, - SPtr view); - - void set_window(GraphWindow* win) { _window = win; } - - bool documentation_is_visible() { return _doc_scrolledwindow->is_visible(); } - void set_documentation(const std::string& doc, bool html); - - SPtr graph() const { return _graph; } - SPtr view() const { return _view; } - - void show_port_status(const Client::PortModel* port, - const Atom& value); - - void set_graph_from_path(const Raul::Path& path, SPtr view); - - void object_entered(const Client::ObjectModel* model); - void object_left(const Client::ObjectModel* model); - -private: - void graph_port_added(SPtr port); - void graph_port_removed(SPtr port); - void property_changed(const URI& predicate, const Atom& value); - void show_status(const Client::ObjectModel* model); - - void error(const Glib::ustring& message, - const Glib::ustring& secondary_text=""); - - bool confirm(const Glib::ustring& message, - const Glib::ustring& secondary_text=""); - - void save_graph(const URI& uri); - - void event_import(); - void event_save(); - void event_save_as(); - void event_export_image(); - void event_redo(); - void event_undo(); - void event_copy(); - void event_paste(); - void event_delete(); - void event_select_all(); - void event_close(); - void event_quit(); - void event_parent_activated(); - void event_refresh_activated(); - void event_fullscreen_toggled(); - void event_doc_pane_toggled(); - void event_status_bar_toggled(); - void event_animate_signals_toggled(); - void event_sprung_layout_toggled(); - void event_human_names_toggled(); - void event_port_names_toggled(); - void event_zoom_in(); - void event_zoom_out(); - void event_zoom_normal(); - void event_zoom_full(); - void event_increase_font_size(); - void event_decrease_font_size(); - void event_normal_font_size(); - void event_arrange(); - void event_show_properties(); - void event_show_engine(); - void event_clipboard_changed(GdkEventOwnerChange* ev); - - App* _app; - SPtr _graph; - SPtr _view; - GraphWindow* _window; - - sigc::connection new_port_connection; - sigc::connection removed_port_connection; - sigc::connection edit_mode_connection; - - Gtk::MenuItem* _menu_import; - Gtk::MenuItem* _menu_save; - Gtk::MenuItem* _menu_save_as; - Gtk::MenuItem* _menu_export_image; - Gtk::MenuItem* _menu_redo; - Gtk::MenuItem* _menu_undo; - Gtk::MenuItem* _menu_cut; - Gtk::MenuItem* _menu_copy; - Gtk::MenuItem* _menu_paste; - Gtk::MenuItem* _menu_delete; - Gtk::MenuItem* _menu_select_all; - Gtk::MenuItem* _menu_close; - Gtk::MenuItem* _menu_quit; - Gtk::CheckMenuItem* _menu_animate_signals; - Gtk::CheckMenuItem* _menu_sprung_layout; - Gtk::CheckMenuItem* _menu_human_names; - Gtk::CheckMenuItem* _menu_show_port_names; - Gtk::CheckMenuItem* _menu_show_doc_pane; - Gtk::CheckMenuItem* _menu_show_status_bar; - Gtk::MenuItem* _menu_zoom_in; - Gtk::MenuItem* _menu_zoom_out; - Gtk::MenuItem* _menu_zoom_normal; - Gtk::MenuItem* _menu_zoom_full; - Gtk::MenuItem* _menu_increase_font_size; - Gtk::MenuItem* _menu_decrease_font_size; - Gtk::MenuItem* _menu_normal_font_size; - Gtk::MenuItem* _menu_parent; - Gtk::MenuItem* _menu_refresh; - Gtk::MenuItem* _menu_fullscreen; - Gtk::MenuItem* _menu_arrange; - Gtk::MenuItem* _menu_view_engine_window; - Gtk::MenuItem* _menu_view_control_window; - Gtk::MenuItem* _menu_view_graph_properties; - Gtk::MenuItem* _menu_view_messages_window; - Gtk::MenuItem* _menu_view_graph_tree_window; - Gtk::MenuItem* _menu_help_about; - - Gtk::Alignment* _alignment; - BreadCrumbs* _breadcrumbs; - Gtk::Statusbar* _status_bar; - Gtk::Label* _status_label; - - Gtk::HPaned* _doc_paned; - Gtk::ScrolledWindow* _doc_scrolledwindow; - - sigc::connection _entered_connection; - sigc::connection _left_connection; - - /** Invisible bin used to store breadcrumbs when not shown by a view */ - Gtk::Alignment _breadcrumb_bin; - - bool _has_shown_documentation; - bool _enable_signal; -}; - -} // namespace GUI -} // namespace Ingen - -#endif // INGEN_GUI_GRAPH_BOX_HPP diff --git a/src/gui/GraphCanvas.cpp b/src/gui/GraphCanvas.cpp deleted file mode 100644 index 0ae4d709..00000000 --- a/src/gui/GraphCanvas.cpp +++ /dev/null @@ -1,899 +0,0 @@ -/* - This file is part of Ingen. - Copyright 2007-2016 David Robillard - - 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 - Software Foundation, either version 3 of the License, or 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 Affero General Public License for details. - - You should have received a copy of the GNU Affero General Public License - along with Ingen. If not, see . -*/ - -#include -#include -#include -#include -#include - -#include -#include - -#include "ganv/Canvas.hpp" -#include "ganv/Circle.hpp" -#include "ingen/ClashAvoider.hpp" -#include "ingen/Configuration.hpp" -#include "ingen/Interface.hpp" -#include "ingen/Log.hpp" -#include "ingen/Serialiser.hpp" -#include "ingen/World.hpp" -#include "ingen/client/BlockModel.hpp" -#include "ingen/client/ClientStore.hpp" -#include "ingen/client/GraphModel.hpp" -#include "ingen/client/PluginModel.hpp" -#include "ingen/ingen.h" -#include "lv2/lv2plug.in/ns/ext/atom/atom.h" - -#include "App.hpp" -#include "Arc.hpp" -#include "GraphCanvas.hpp" -#include "GraphPortModule.hpp" -#include "GraphWindow.hpp" -#include "LoadPluginWindow.hpp" -#include "NewSubgraphWindow.hpp" -#include "NodeModule.hpp" -#include "PluginMenu.hpp" -#include "Port.hpp" -#include "SubgraphModule.hpp" -#include "ThreadedLoader.hpp" -#include "WidgetFactory.hpp" -#include "WindowFactory.hpp" - -using std::string; - -namespace Ingen { - -using namespace Client; - -namespace GUI { - -static int -port_order(const GanvPort* a, const GanvPort* b, void* data) -{ - const Port* pa = dynamic_cast(Glib::wrap(a)); - const Port* pb = dynamic_cast(Glib::wrap(b)); - if (pa && pb) { - return ((int)pa->model()->index() - (int)pb->model()->index()); - } - return 0; -} - -GraphCanvas::GraphCanvas(App& app, - SPtr graph, - int width, - int height) - : Canvas(width, height) - , _app(app) - , _graph(std::move(graph)) - , _auto_position_count(0) - , _menu_x(0) - , _menu_y(0) - , _paste_count(0) - , _menu(nullptr) - , _internal_menu(nullptr) - , _plugin_menu(nullptr) - , _human_names(true) - , _show_port_names(true) - , _menu_dirty(false) -{ - Glib::RefPtr xml = WidgetFactory::create("canvas_menu"); - xml->get_widget("canvas_menu", _menu); - - xml->get_widget("canvas_menu_add_audio_input", _menu_add_audio_input); - xml->get_widget("canvas_menu_add_audio_output", _menu_add_audio_output); - xml->get_widget("canvas_menu_add_cv_input", _menu_add_cv_input); - xml->get_widget("canvas_menu_add_cv_output", _menu_add_cv_output); - xml->get_widget("canvas_menu_add_control_input", _menu_add_control_input); - xml->get_widget("canvas_menu_add_control_output", _menu_add_control_output); - xml->get_widget("canvas_menu_add_event_input", _menu_add_event_input); - xml->get_widget("canvas_menu_add_event_output", _menu_add_event_output); - xml->get_widget("canvas_menu_load_plugin", _menu_load_plugin); - xml->get_widget("canvas_menu_load_graph", _menu_load_graph); - xml->get_widget("canvas_menu_new_graph", _menu_new_graph); - xml->get_widget("canvas_menu_edit", _menu_edit); - xml->get_widget("canvas_menu_properties", _menu_properties); - - const URIs& uris = _app.uris(); - - // Add port menu items - _menu_add_audio_input->signal_activate().connect( - sigc::bind(sigc::mem_fun(this, &GraphCanvas::menu_add_port), - "audio_in", "Audio In", uris.lv2_AudioPort, false)); - _menu_add_audio_output->signal_activate().connect( - sigc::bind(sigc::mem_fun(this, &GraphCanvas::menu_add_port), - "audio_out", "Audio Out", uris.lv2_AudioPort, true)); - _menu_add_cv_input->signal_activate().connect( - sigc::bind(sigc::mem_fun(this, &GraphCanvas::menu_add_port), - "cv_in", "CV In", uris.lv2_CVPort, false)); - _menu_add_cv_output->signal_activate().connect( - sigc::bind(sigc::mem_fun(this, &GraphCanvas::menu_add_port), - "cv_out", "CV Out", uris.lv2_CVPort, true)); - _menu_add_control_input->signal_activate().connect( - sigc::bind(sigc::mem_fun(this, &GraphCanvas::menu_add_port), - "control_in", "Control In", uris.lv2_ControlPort, false)); - _menu_add_control_output->signal_activate().connect( - sigc::bind(sigc::mem_fun(this, &GraphCanvas::menu_add_port), - "control_out", "Control Out", uris.lv2_ControlPort, true)); - _menu_add_event_input->signal_activate().connect( - sigc::bind(sigc::mem_fun(this, &GraphCanvas::menu_add_port), - "event_in", "Event In", uris.atom_AtomPort, false)); - _menu_add_event_output->signal_activate().connect( - sigc::bind(sigc::mem_fun(this, &GraphCanvas::menu_add_port), - "event_out", "Event Out", uris.atom_AtomPort, true)); - - signal_event.connect( - sigc::mem_fun(this, &GraphCanvas::on_event)); - signal_connect.connect( - sigc::mem_fun(this, &GraphCanvas::connect)); - signal_disconnect.connect( - sigc::mem_fun(this, &GraphCanvas::disconnect)); - - // Connect to model signals to track state - _graph->signal_new_block().connect( - sigc::mem_fun(this, &GraphCanvas::add_block)); - _graph->signal_removed_block().connect( - sigc::mem_fun(this, &GraphCanvas::remove_block)); - _graph->signal_new_port().connect( - sigc::mem_fun(this, &GraphCanvas::add_port)); - _graph->signal_removed_port().connect( - sigc::mem_fun(this, &GraphCanvas::remove_port)); - _graph->signal_new_arc().connect( - sigc::mem_fun(this, &GraphCanvas::connection)); - _graph->signal_removed_arc().connect( - sigc::mem_fun(this, &GraphCanvas::disconnection)); - - _app.store()->signal_new_plugin().connect( - sigc::mem_fun(this, &GraphCanvas::add_plugin)); - _app.store()->signal_plugin_deleted().connect( - sigc::mem_fun(this, &GraphCanvas::remove_plugin)); - - // Connect widget signals to do things - _menu_load_plugin->signal_activate().connect( - sigc::mem_fun(this, &GraphCanvas::menu_load_plugin)); - _menu_load_graph->signal_activate().connect( - sigc::mem_fun(this, &GraphCanvas::menu_load_graph)); - _menu_new_graph->signal_activate().connect( - sigc::mem_fun(this, &GraphCanvas::menu_new_graph)); - _menu_properties->signal_activate().connect( - sigc::mem_fun(this, &GraphCanvas::menu_properties)); - - show_human_names(app.world()->conf().option("human-names").get()); - show_port_names(app.world()->conf().option("port-labels").get()); - set_port_order(port_order, nullptr); -} - -void -GraphCanvas::show_menu(bool position, unsigned button, uint32_t time) -{ - _app.request_plugins_if_necessary(); - - if (!_internal_menu || _menu_dirty) { - build_menus(); - } - - if (position) { - _menu->popup(sigc::mem_fun(this, &GraphCanvas::auto_menu_position), button, time); - } else { - _menu->popup(button, time); - } -} - -void -GraphCanvas::build_menus() -{ - // Build (or clear existing) internal plugin menu - if (_internal_menu) { - _internal_menu->items().clear(); - } else { - _menu->items().push_back( - Gtk::Menu_Helpers::ImageMenuElem( - "In_ternal", - *(manage(new Gtk::Image(Gtk::Stock::EXECUTE, Gtk::ICON_SIZE_MENU))))); - Gtk::MenuItem* internal_menu_item = &(_menu->items().back()); - _internal_menu = Gtk::manage(new Gtk::Menu()); - internal_menu_item->set_submenu(*_internal_menu); - _menu->reorder_child(*internal_menu_item, 4); - } - - // Build skeleton LV2 plugin class heirarchy for 'Plugin' menu - if (_plugin_menu) { - _plugin_menu->clear(); - } else { - _plugin_menu = Gtk::manage(new PluginMenu(*_app.world())); - _menu->items().push_back( - Gtk::Menu_Helpers::ImageMenuElem( - "_Plugin", - *(manage(new Gtk::Image(Gtk::Stock::EXECUTE, Gtk::ICON_SIZE_MENU))))); - Gtk::MenuItem* plugin_menu_item = &(_menu->items().back()); - plugin_menu_item->set_submenu(*_plugin_menu); - _menu->reorder_child(*plugin_menu_item, 5); - _plugin_menu->signal_load_plugin.connect( - sigc::mem_fun(this, &GraphCanvas::load_plugin)); - } - - // Add known plugins to menu heirarchy - SPtr plugins = _app.store()->plugins(); - for (const auto& p : *plugins.get()) { - add_plugin(p.second); - } - - _menu_dirty = false; -} - -void -GraphCanvas::build() -{ - const Store::const_range kids = _app.store()->children_range(_graph); - - // Create modules for blocks - for (Store::const_iterator i = kids.first; i != kids.second; ++i) { - SPtr block = dynamic_ptr_cast(i->second); - if (block && block->parent() == _graph) { - add_block(block); - } - } - - // Create pseudo modules for ports (ports on this canvas, not on our module) - for (const auto& p : _graph->ports()) { - add_port(p); - } - - // Create arcs - for (const auto& a : _graph->arcs()) { - connection(dynamic_ptr_cast(a.second)); - } -} - -static void -show_module_human_names(GanvNode* node, void* data) -{ - bool b = *(bool*)data; - if (GANV_IS_MODULE(node)) { - Ganv::Module* module = Glib::wrap(GANV_MODULE(node)); - NodeModule* nmod = dynamic_cast(module); - if (nmod) { - nmod->show_human_names(b); - } - - GraphPortModule* pmod = dynamic_cast(module); - if (pmod) { - pmod->show_human_names(b); - } - } -} - -void -GraphCanvas::show_human_names(bool b) -{ - _human_names = b; - _app.world()->conf().set("human-names", _app.forge().make(b)); - - for_each_node(show_module_human_names, &b); -} - -static void -ensure_port_labels(GanvNode* node, void* data) -{ - if (GANV_IS_MODULE(node)) { - Ganv::Module* module = Glib::wrap(GANV_MODULE(node)); - for (Ganv::Port* p : *module) { - Ingen::GUI::Port* port = dynamic_cast(p); - if (port) { - port->ensure_label(); - } - } - } -} - -void -GraphCanvas::show_port_names(bool b) -{ - ganv_canvas_set_direction(gobj(), b ? GANV_DIRECTION_RIGHT : GANV_DIRECTION_DOWN); - for_each_node(ensure_port_labels, &b); -} - -void -GraphCanvas::add_plugin(SPtr p) -{ - if (_internal_menu && _app.uris().ingen_Internal == p->type()) { - _internal_menu->items().push_back( - Gtk::Menu_Helpers::MenuElem( - std::string("_") + p->human_name(), - sigc::bind(sigc::mem_fun(this, &GraphCanvas::load_plugin), p))); - } else if (_plugin_menu) { - _plugin_menu->add_plugin(p); - } -} - -void -GraphCanvas::remove_plugin(const URI& uri) -{ - // Flag menus as dirty so they will be rebuilt when needed next - _menu_dirty = true; -} - -void -GraphCanvas::add_block(SPtr bm) -{ - SPtr pm = dynamic_ptr_cast(bm); - NodeModule* module; - if (pm) { - module = SubgraphModule::create(*this, pm, _human_names); - } else { - module = NodeModule::create(*this, bm, _human_names); - } - - module->show(); - _views.emplace(bm, module); - if (_pastees.find(bm->path()) != _pastees.end()) { - module->set_selected(true); - } -} - -void -GraphCanvas::remove_block(SPtr bm) -{ - auto i = _views.find(bm); - - if (i != _views.end()) { - const guint n_ports = i->second->num_ports(); - for (gint p = n_ports - 1; p >= 0; --p) { - delete i->second->get_port(p); - } - delete i->second; - _views.erase(i); - } -} - -void -GraphCanvas::add_port(SPtr pm) -{ - GraphPortModule* view = GraphPortModule::create(*this, pm); - _views.emplace(pm, view); - view->show(); -} - -void -GraphCanvas::remove_port(SPtr pm) -{ - auto i = _views.find(pm); - - // Port on this graph - if (i != _views.end()) { - delete i->second; - _views.erase(i); - - } else { - NodeModule* module = dynamic_cast(_views[pm->parent()]); - module->delete_port_view(pm); - } - - assert(_views.find(pm) == _views.end()); -} - -Ganv::Port* -GraphCanvas::get_port_view(SPtr port) -{ - Ganv::Module* module = _views[port]; - - // Port on this graph - if (module) { - GraphPortModule* ppm = dynamic_cast(module); - return ppm - ? *ppm->begin() - : dynamic_cast(module); - } else { - module = dynamic_cast(_views[port->parent()]); - if (module) { - for (const auto& p : *module) { - GUI::Port* pv = dynamic_cast(p); - if (pv && pv->model() == port) { - return pv; - } - } - } - } - - return nullptr; -} - -/** Called when a connection is added to the model. */ -void -GraphCanvas::connection(SPtr arc) -{ - Ganv::Port* const tail = get_port_view(arc->tail()); - Ganv::Port* const head = get_port_view(arc->head()); - - if (tail && head) { - new GUI::Arc(*this, arc, tail, head); - } else { - _app.log().error(fmt("Unable to find ports to connect %1% => %2%\n") - % arc->tail_path() % arc->head_path()); - } -} - -/** Called when a connection is removed from the model. */ -void -GraphCanvas::disconnection(SPtr arc) -{ - Ganv::Port* const tail = get_port_view(arc->tail()); - Ganv::Port* const head = get_port_view(arc->head()); - - if (tail && head) { - remove_edge_between(tail, head); - if (arc->head()->is_a(_app.uris().lv2_AudioPort)) { - GUI::Port* const h = dynamic_cast(head); - if (h) { - h->activity(_app.forge().make(0.0f)); // Reset peaks - } - } - } else { - _app.log().error(fmt("Unable to find ports to disconnect %1% => %2%\n") - % arc->tail_path() % arc->head_path()); - } -} - -/** Called when the user connects ports on the canvas. */ -void -GraphCanvas::connect(Ganv::Node* tail, Ganv::Node* head) -{ - const GUI::Port* const t = dynamic_cast(tail); - const GUI::Port* const h = dynamic_cast(head); - - if (t && h) { - _app.interface()->connect(t->model()->path(), h->model()->path()); - } -} - -/** Called when the user disconnects ports on the canvas. */ -void -GraphCanvas::disconnect(Ganv::Node* tail, Ganv::Node* head) -{ - const GUI::Port* const t = dynamic_cast(tail); - const GUI::Port* const h = dynamic_cast(head); - - if (t && h) { - _app.interface()->disconnect(t->model()->path(), h->model()->path()); - } -} - -void -GraphCanvas::auto_menu_position(int& x, int& y, bool& push_in) -{ - std::pair scroll_offsets; - get_scroll_offsets(scroll_offsets.first, scroll_offsets.second); - - if (_auto_position_count > 1 && scroll_offsets != _auto_position_scroll_offsets) { - // Scroll changed since last auto position, reset - _menu_x = 0; - _menu_y = 0; - _auto_position_count = 0; - } - - if (_menu_x == 0 && _menu_y == 0) { - // No menu position set, start near top left of canvas - widget().translate_coordinates( - *_app.window_factory()->graph_window(_graph), - 64, 64, _menu_x, _menu_y); - - int origin_x; - int origin_y; - widget().get_window()->get_origin(origin_x, origin_y); - _menu_x += origin_x; - _menu_y += origin_y; - } - - const int cascade = _auto_position_count * 32; - - x = _menu_x + cascade; - y = _menu_y + cascade; - push_in = true; - - ++_auto_position_count; - _auto_position_scroll_offsets = scroll_offsets; -} - -bool -GraphCanvas::on_event(GdkEvent* event) -{ - assert(event); - - bool ret = false; - - switch (event->type) { - case GDK_BUTTON_PRESS: - if (event->button.button == 3) { - _auto_position_count = 1; - _menu_x = (int)event->button.x_root; - _menu_y = (int)event->button.y_root; - show_menu(false, event->button.button, event->button.time); - ret = true; - } - break; - - case GDK_KEY_PRESS: - switch (event->key.keyval) { - case GDK_Delete: - destroy_selection(); - ret = true; - break; - case GDK_Home: - scroll_to(0, 0); - break; - case GDK_space: - case GDK_Menu: - show_menu(true, 3, event->key.time); - default: break; - } - break; - - case GDK_MOTION_NOTIFY: - _paste_count = 0; - break; - - default: break; - } - - return ret; -} - -void -GraphCanvas::clear_selection() -{ - GraphWindow* win = _app.window_factory()->graph_window(_graph); - if (win) { - win->set_documentation("", false); - } - - Ganv::Canvas::clear_selection(); -} - -static void -destroy_node(GanvNode* node, void* data) -{ - if (!GANV_IS_MODULE(node)) { - return; - } - - App* app = (App*)data; - Ganv::Module* module = Glib::wrap(GANV_MODULE(node)); - NodeModule* node_module = dynamic_cast(module); - - if (node_module) { - app->interface()->del(node_module->block()->uri()); - } else { - GraphPortModule* port_module = dynamic_cast(module); - if (port_module && - strcmp(port_module->port()->path().symbol(), "control") && - strcmp(port_module->port()->path().symbol(), "notify")) { - app->interface()->del(port_module->port()->uri()); - } - } -} - -static void -destroy_arc(GanvEdge* arc, void* data) -{ - App* app = (App*)data; - Ganv::Edge* arcmm = Glib::wrap(arc); - - Port* tail = dynamic_cast(arcmm->get_tail()); - Port* head = dynamic_cast(arcmm->get_head()); - app->interface()->disconnect(tail->model()->path(), head->model()->path()); -} - -void -GraphCanvas::destroy_selection() -{ - _app.interface()->bundle_begin(); - for_each_selected_edge(destroy_arc, &_app); - for_each_selected_node(destroy_node, &_app); - _app.interface()->bundle_end(); -} - -static void -serialise_node(GanvNode* node, void* data) -{ - Serialiser* serialiser = (Serialiser*)data; - if (!GANV_IS_MODULE(node)) { - return; - } - - Ganv::Module* module = Glib::wrap(GANV_MODULE(node)); - NodeModule* node_module = dynamic_cast(module); - - if (node_module) { - serialiser->serialise(node_module->block()); - } else { - GraphPortModule* port_module = dynamic_cast(module); - if (port_module) { - serialiser->serialise(port_module->port()); - } - } -} - -static void -serialise_arc(GanvEdge* arc, void* data) -{ - Serialiser* serialiser = (Serialiser*)data; - if (!GANV_IS_EDGE(arc)) { - return; - } - - GUI::Arc* garc = dynamic_cast(Glib::wrap(GANV_EDGE(arc))); - if (garc) { - serialiser->serialise_arc(Sord::Node(), garc->model()); - } -} - -void -GraphCanvas::copy_selection() -{ - std::lock_guard lock(_app.world()->rdf_mutex()); - - Serialiser serialiser(*_app.world()); - serialiser.start_to_string(_graph->path(), _graph->base_uri()); - - for_each_selected_node(serialise_node, &serialiser); - for_each_selected_edge(serialise_arc, &serialiser); - - Glib::RefPtr clipboard = Gtk::Clipboard::get(); - clipboard->set_text(serialiser.finish()); - _paste_count = 0; -} - -void -GraphCanvas::paste() -{ - typedef Properties::const_iterator PropIter; - - std::lock_guard lock(_app.world()->rdf_mutex()); - - const Glib::ustring str = Gtk::Clipboard::get()->wait_for_text(); - SPtr parser = _app.loader()->parser(); - const URIs& uris = _app.uris(); - const Raul::Path& parent = _graph->path(); - if (!parser) { - _app.log().error("Unable to load parser, paste unavailable\n"); - return; - } - - // Prepare for paste - clear_selection(); - _pastees.clear(); - ++_paste_count; - - // Make a client store to serve as clipboard - ClientStore clipboard(_app.world()->uris(), _app.log()); - clipboard.set_plugins(_app.store()->plugins()); - clipboard.put(main_uri(), - {{uris.rdf_type, Property(uris.ingen_Graph)}}); - - // Parse clipboard text into clipboard store - boost::optional base_uri = parser->parse_string( - _app.world(), &clipboard, str, main_uri()); - - // Figure out the copy graph base path - Raul::Path copy_root("/"); - if (base_uri) { - std::string base = *base_uri; - if (base[base.size() - 1] == '/') { - base = base.substr(0, base.size() - 1); - } - copy_root = uri_to_path(URI(base)); - } - - // Find the minimum x and y coordinate of objects to be pasted - float min_x = std::numeric_limits::max(); - float min_y = std::numeric_limits::max(); - for (const auto& c : clipboard) { - if (c.first.parent() == Raul::Path("/")) { - const Atom& x = c.second->get_property(uris.ingen_canvasX); - const Atom& y = c.second->get_property(uris.ingen_canvasY); - if (x.type() == uris.atom_Float) { - min_x = std::min(min_x, x.get()); - } - if (y.type() == uris.atom_Float) { - min_y = std::min(min_y, y.get()); - } - } - } - - // Find canvas paste origin based on pointer position - int widget_point_x, widget_point_y, scroll_x, scroll_y; - widget().get_pointer(widget_point_x, widget_point_y); - get_scroll_offsets(scroll_x, scroll_y); - const int paste_x = widget_point_x + scroll_x + (20.0f * _paste_count); - const int paste_y = widget_point_y + scroll_y + (20.0f * _paste_count); - - _app.interface()->bundle_begin(); - - // Put each top level object in the clipboard store - ClashAvoider avoider(*_app.store().get()); - for (const auto& c : clipboard) { - if (c.first.is_root() || c.first.parent() != Raul::Path("/")) { - continue; - } - - const SPtr node = c.second; - const Raul::Path& old_path = copy_root.child(node->path()); - const URI& old_uri = path_to_uri(old_path); - const Raul::Path& new_path = avoider.map_path(parent.child(node->path())); - - Properties props{{uris.lv2_prototype, - _app.forge().make_urid(old_uri)}}; - - // Set the same types - const auto t = node->properties().equal_range(uris.rdf_type); - props.insert(t.first, t.second); - - // Set coordinates so paste origin is at the mouse pointer - PropIter xi = node->properties().find(uris.ingen_canvasX); - PropIter yi = node->properties().find(uris.ingen_canvasY); - if (xi != node->properties().end()) { - const float x = xi->second.get() - min_x + paste_x; - props.insert({xi->first, Property(_app.forge().make(x), - xi->second.context())}); - } - if (yi != node->properties().end()) { - const float y = yi->second.get() - min_y + paste_y; - props.insert({yi->first, Property(_app.forge().make(y), - yi->second.context())}); - } - - _app.interface()->put(path_to_uri(new_path), props); - _pastees.insert(new_path); - } - - // Connect objects - for (auto a : clipboard.object(Raul::Path("/"))->arcs()) { - _app.interface()->connect( - avoider.map_path(parent.child(a.second->tail_path())), - avoider.map_path(parent.child(a.second->head_path()))); - } - - _app.interface()->bundle_end(); -} - -void -GraphCanvas::generate_port_name( - const string& sym_base, string& symbol, - const string& name_base, string& name) -{ - symbol = sym_base; - name = name_base; - - char num_buf[5]; - uint32_t i = 1; - for ( ; i < 9999; ++i) { - snprintf(num_buf, sizeof(num_buf), "%u", i); - symbol = sym_base + "_"; - symbol += num_buf; - if (!_graph->get_port(Raul::Symbol::symbolify(symbol))) { - break; - } - } - - assert(Raul::Path::is_valid(string("/") + symbol)); - - name.append(" ").append(num_buf); -} - -void -GraphCanvas::menu_add_port(const string& sym_base, - const string& name_base, - const URI& type, - bool is_output) -{ - string sym, name; - generate_port_name(sym_base, sym, name_base, name); - const Raul::Path& path = _graph->path().child(Raul::Symbol(sym)); - - const URIs& uris = _app.uris(); - - Properties props = get_initial_data(Resource::Graph::INTERNAL); - props.emplace(uris.rdf_type, _app.forge().make_urid(type)); - if (type == uris.atom_AtomPort) { - props.emplace(uris.atom_bufferType, Property(uris.atom_Sequence)); - } - props.emplace( - uris.rdf_type, - Property(is_output ? uris.lv2_OutputPort : uris.lv2_InputPort)); - props.emplace(uris.lv2_index, - _app.forge().make(int32_t(_graph->num_ports()))); - props.emplace(uris.lv2_name, _app.forge().alloc(name.c_str())); - _app.interface()->put(path_to_uri(path), props); -} - -void -GraphCanvas::load_plugin(WPtr weak_plugin) -{ - SPtr plugin = weak_plugin.lock(); - if (!plugin) { - return; - } - - Raul::Symbol symbol = plugin->default_block_symbol(); - unsigned offset = _app.store()->child_name_offset(_graph->path(), symbol); - if (offset != 0) { - std::stringstream ss; - ss << symbol << "_" << offset; - symbol = Raul::Symbol(ss.str()); - } - - const URIs& uris = _app.uris(); - const Raul::Path path = _graph->path().child(symbol); - - // FIXME: polyphony? - Properties props = get_initial_data(); - props.emplace(uris.rdf_type, Property(uris.ingen_Block)); - props.emplace(uris.lv2_prototype, uris.forge.make_urid(plugin->uri())); - _app.interface()->put(path_to_uri(path), props); -} - -/** Try to guess a suitable location for a new module. - */ -void -GraphCanvas::get_new_module_location(double& x, double& y) -{ - int scroll_x; - int scroll_y; - get_scroll_offsets(scroll_x, scroll_y); - x = scroll_x + 20; - y = scroll_y + 20; -} - -Properties -GraphCanvas::get_initial_data(Resource::Graph ctx) -{ - Properties result; - const URIs& uris = _app.uris(); - result.emplace(uris.ingen_canvasX, - Property(_app.forge().make((float)_menu_x), ctx)); - result.emplace(uris.ingen_canvasY, - Property(_app.forge().make((float)_menu_y), ctx)); - return result; -} - -void -GraphCanvas::menu_load_plugin() -{ - _app.window_factory()->present_load_plugin(_graph, get_initial_data()); -} - -void -GraphCanvas::menu_load_graph() -{ - _app.window_factory()->present_load_subgraph( - _graph, get_initial_data(Resource::Graph::EXTERNAL)); -} - -void -GraphCanvas::menu_new_graph() -{ - _app.window_factory()->present_new_subgraph( - _graph, get_initial_data(Resource::Graph::EXTERNAL)); -} - -void -GraphCanvas::menu_properties() -{ - _app.window_factory()->present_properties(_graph); -} - -} // namespace GUI -} // namespace Ingen diff --git a/src/gui/GraphCanvas.hpp b/src/gui/GraphCanvas.hpp deleted file mode 100644 index a7340744..00000000 --- a/src/gui/GraphCanvas.hpp +++ /dev/null @@ -1,159 +0,0 @@ -/* - This file is part of Ingen. - Copyright 2007-2015 David Robillard - - 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 - Software Foundation, either version 3 of the License, or 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 Affero General Public License for details. - - You should have received a copy of the GNU Affero General Public License - along with Ingen. If not, see . -*/ - -#ifndef INGEN_GUI_GRAPHCANVAS_HPP -#define INGEN_GUI_GRAPHCANVAS_HPP - -#include -#include -#include - -#include "lilv/lilv.h" - -#include "ganv/Canvas.hpp" -#include "ganv/Module.hpp" -#include "ingen/Node.hpp" -#include "ingen/client/ArcModel.hpp" -#include "ingen/types.hpp" -#include "raul/Path.hpp" - -#include "NodeModule.hpp" - -namespace Ingen { - -namespace Client { class GraphModel; } - -namespace GUI { - -class NodeModule; -class PluginMenu; - -/** Graph canvas widget. - * - * \ingroup GUI - */ -class GraphCanvas : public Ganv::Canvas -{ -public: - GraphCanvas(App& app, - SPtr graph, - int width, - int height); - - virtual ~GraphCanvas() {} - - App& app() { return _app; } - - void build(); - void show_human_names(bool b); - void show_port_names(bool b); - bool show_port_names() const { return _show_port_names; } - - void add_plugin(SPtr p); - void remove_plugin(const URI& uri); - void add_block(SPtr bm); - void remove_block(SPtr bm); - void add_port(SPtr pm); - void remove_port(SPtr pm); - void connection(SPtr arc); - void disconnection(SPtr arc); - - void get_new_module_location(double& x, double& y); - - void clear_selection(); - void destroy_selection(); - void copy_selection(); - void paste(); - - void show_menu(bool position, unsigned button, uint32_t time); - - bool on_event(GdkEvent* event); - -private: - enum class ControlType { NUMBER, BUTTON }; - void generate_port_name( - const std::string& sym_base, std::string& symbol, - const std::string& name_base, std::string& name); - - void menu_add_port(const std::string& sym_base, - const std::string& name_base, - const URI& type, - bool is_output); - - void menu_load_plugin(); - void menu_new_graph(); - void menu_load_graph(); - void menu_properties(); - void load_plugin(WPtr weak_plugin); - - void build_menus(); - - void auto_menu_position(int& x, int& y, bool& push_in); - - typedef std::multimap LV2Children; - - Properties get_initial_data(Resource::Graph ctx=Resource::Graph::DEFAULT); - - Ganv::Port* get_port_view(SPtr port); - - void connect(Ganv::Node* tail, - Ganv::Node* head); - - void disconnect(Ganv::Node* tail, - Ganv::Node* head); - - App& _app; - SPtr _graph; - - typedef std::map, Ganv::Module*> Views; - Views _views; - - int _auto_position_count; - std::pair _auto_position_scroll_offsets; - - int _menu_x; - int _menu_y; - int _paste_count; - - // Track pasted objects so they can be selected when they arrive - std::set _pastees; - - Gtk::Menu* _menu; - Gtk::Menu* _internal_menu; - PluginMenu* _plugin_menu; - Gtk::MenuItem* _menu_add_audio_input; - Gtk::MenuItem* _menu_add_audio_output; - Gtk::MenuItem* _menu_add_control_input; - Gtk::MenuItem* _menu_add_control_output; - Gtk::MenuItem* _menu_add_cv_input; - Gtk::MenuItem* _menu_add_cv_output; - Gtk::MenuItem* _menu_add_event_input; - Gtk::MenuItem* _menu_add_event_output; - Gtk::MenuItem* _menu_load_plugin; - Gtk::MenuItem* _menu_load_graph; - Gtk::MenuItem* _menu_new_graph; - Gtk::MenuItem* _menu_properties; - Gtk::CheckMenuItem* _menu_edit; - - bool _human_names; - bool _show_port_names; - bool _menu_dirty; -}; - -} // namespace GUI -} // namespace Ingen - -#endif // INGEN_GUI_GRAPHCANVAS_HPP diff --git a/src/gui/GraphPortModule.cpp b/src/gui/GraphPortModule.cpp deleted file mode 100644 index 5987b0e3..00000000 --- a/src/gui/GraphPortModule.cpp +++ /dev/null @@ -1,166 +0,0 @@ -/* - This file is part of Ingen. - Copyright 2007-2015 David Robillard - - 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 - Software Foundation, either version 3 of the License, or 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 Affero General Public License for details. - - You should have received a copy of the GNU Affero General Public License - along with Ingen. If not, see . -*/ - -#include -#include -#include - -#include "ingen/Configuration.hpp" -#include "ingen/Interface.hpp" -#include "ingen/client/BlockModel.hpp" -#include "ingen/client/GraphModel.hpp" - -#include "App.hpp" -#include "Style.hpp" -#include "GraphCanvas.hpp" -#include "GraphPortModule.hpp" -#include "GraphWindow.hpp" -#include "Port.hpp" -#include "PortMenu.hpp" -#include "RenameWindow.hpp" -#include "WidgetFactory.hpp" -#include "WindowFactory.hpp" - -namespace Ingen { - -using namespace Client; - -namespace GUI { - -GraphPortModule::GraphPortModule(GraphCanvas& canvas, - SPtr model) - : Ganv::Module(canvas, "", 0, 0, false) // FIXME: coords? - , _model(model) - , _port(nullptr) -{ - assert(model); - - assert(dynamic_ptr_cast(model->parent())); - - set_stacked(model->polyphonic()); - if (model->is_input() && !model->is_numeric()) { - set_is_source(true); - } - - model->signal_property().connect( - sigc::mem_fun(this, &GraphPortModule::property_changed)); - - signal_moved().connect( - sigc::mem_fun(this, &GraphPortModule::store_location)); -} - -GraphPortModule* -GraphPortModule::create(GraphCanvas& canvas, - SPtr model) -{ - GraphPortModule* ret = new GraphPortModule(canvas, model); - Port* port = Port::create(canvas.app(), *ret, model, true); - - ret->set_port(port); - if (model->is_numeric()) { - port->show_control(); - } - - for (const auto& p : model->properties()) { - ret->property_changed(p.first, p.second); - } - - return ret; -} - -App& -GraphPortModule::app() const -{ - return ((GraphCanvas*)canvas())->app(); -} - -bool -GraphPortModule::show_menu(GdkEventButton* ev) -{ - return _port->show_menu(ev); -} - -void -GraphPortModule::store_location(double ax, double ay) -{ - const URIs& uris = app().uris(); - - const Atom x(app().forge().make(static_cast(ax))); - const Atom y(app().forge().make(static_cast(ay))); - - if (x != _model->get_property(uris.ingen_canvasX) || - y != _model->get_property(uris.ingen_canvasY)) - { - app().interface()->put( - _model->uri(), - {{uris.ingen_canvasX, Property(x, Property::Graph::INTERNAL)}, - {uris.ingen_canvasY, Property(y, Property::Graph::INTERNAL)}}); - } -} - -void -GraphPortModule::show_human_names(bool b) -{ - const URIs& uris = app().uris(); - const Atom& name = _model->get_property(uris.lv2_name); - if (b && name.type() == uris.forge.String) { - set_name(name.ptr()); - } else { - set_name(_model->symbol().c_str()); - } -} - -void -GraphPortModule::set_name(const std::string& n) -{ - _port->set_label(n.c_str()); -} - -void -GraphPortModule::property_changed(const URI& key, const Atom& value) -{ - const URIs& uris = app().uris(); - if (value.type() == uris.forge.Float) { - if (key == uris.ingen_canvasX) { - move_to(value.get(), get_y()); - } else if (key == uris.ingen_canvasY) { - move_to(get_x(), value.get()); - } - } else if (value.type() == uris.forge.String) { - if (key == uris.lv2_name && - app().world()->conf().option("human-names").get()) { - set_name(value.ptr()); - } else if (key == uris.lv2_symbol && - !app().world()->conf().option("human-names").get()) { - set_name(value.ptr()); - } - } else if (value.type() == uris.forge.Bool) { - if (key == uris.ingen_polyphonic) { - set_stacked(value.get()); - } - } -} - -void -GraphPortModule::set_selected(gboolean b) -{ - if (b != get_selected()) { - Module::set_selected(b); - } -} - -} // namespace GUI -} // namespace Ingen diff --git a/src/gui/GraphPortModule.hpp b/src/gui/GraphPortModule.hpp deleted file mode 100644 index 97bc2e5b..00000000 --- a/src/gui/GraphPortModule.hpp +++ /dev/null @@ -1,79 +0,0 @@ -/* - This file is part of Ingen. - Copyright 2007-2015 David Robillard - - 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 - Software Foundation, either version 3 of the License, or 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 Affero General Public License for details. - - You should have received a copy of the GNU Affero General Public License - along with Ingen. If not, see . -*/ - -#ifndef INGEN_GUI_GRAPHPORTMODULE_HPP -#define INGEN_GUI_GRAPHPORTMODULE_HPP - -#include - -#include "ganv/Module.hpp" - -#include "Port.hpp" - -namespace Raul { class Atom; } - -namespace Ingen { namespace Client { -class PortModel; -} } - -namespace Ingen { -namespace GUI { - -class GraphCanvas; -class Port; -class PortMenu; - -/** A "module" to represent a graph's port on its own canvas. - * - * Translation: This is the nameless single port pseudo module thingy. - * - * \ingroup GUI - */ -class GraphPortModule : public Ganv::Module -{ -public: - static GraphPortModule* create( - GraphCanvas& canvas, - SPtr model); - - App& app() const; - - virtual void store_location(double ax, double ay); - void show_human_names(bool b); - - void set_name(const std::string& n); - - SPtr port() const { return _model; } - -protected: - GraphPortModule(GraphCanvas& canvas, - SPtr model); - - bool show_menu(GdkEventButton* ev); - void set_selected(gboolean b); - - void set_port(Port* port) { _port = port; } - - void property_changed(const URI& key, const Atom& value); - - SPtr _model; - Port* _port; -}; - -} // namespace GUI -} // namespace Ingen - -#endif // INGEN_GUI_GRAPHPORTMODULE_HPP diff --git a/src/gui/GraphTreeWindow.cpp b/src/gui/GraphTreeWindow.cpp deleted file mode 100644 index 1eb6557b..00000000 --- a/src/gui/GraphTreeWindow.cpp +++ /dev/null @@ -1,235 +0,0 @@ -/* - This file is part of Ingen. - Copyright 2007-2015 David Robillard - - 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 - Software Foundation, either version 3 of the License, or 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 Affero General Public License for details. - - You should have received a copy of the GNU Affero General Public License - along with Ingen. If not, see . -*/ - -#include "App.hpp" -#include "GraphTreeWindow.hpp" -#include "SubgraphModule.hpp" -#include "WindowFactory.hpp" -#include "ingen/Interface.hpp" -#include "ingen/Log.hpp" -#include "ingen/client/ClientStore.hpp" -#include "ingen/client/GraphModel.hpp" -#include "raul/Path.hpp" - -namespace Ingen { - -using namespace Client; - -namespace GUI { - -GraphTreeWindow::GraphTreeWindow(BaseObjectType* cobject, - const Glib::RefPtr& xml) - : Window(cobject) - , _app(nullptr) - , _enable_signal(true) -{ - xml->get_widget_derived("graphs_treeview", _graphs_treeview); - - _graph_treestore = Gtk::TreeStore::create(_graph_tree_columns); - _graphs_treeview->set_window(this); - _graphs_treeview->set_model(_graph_treestore); - Gtk::TreeViewColumn* name_col = Gtk::manage( - new Gtk::TreeViewColumn("Graph", _graph_tree_columns.name_col)); - Gtk::TreeViewColumn* enabled_col = Gtk::manage( - new Gtk::TreeViewColumn("Run", _graph_tree_columns.enabled_col)); - name_col->set_resizable(true); - name_col->set_expand(true); - - _graphs_treeview->append_column(*name_col); - _graphs_treeview->append_column(*enabled_col); - Gtk::CellRendererToggle* enabled_renderer = dynamic_cast( - _graphs_treeview->get_column_cell_renderer(1)); - enabled_renderer->property_activatable() = true; - - _graph_tree_selection = _graphs_treeview->get_selection(); - - _graphs_treeview->signal_row_activated().connect( - sigc::mem_fun(this, &GraphTreeWindow::event_graph_activated)); - enabled_renderer->signal_toggled().connect( - sigc::mem_fun(this, &GraphTreeWindow::event_graph_enabled_toggled)); - - _graphs_treeview->columns_autosize(); -} - -void -GraphTreeWindow::init(App& app, ClientStore& store) -{ - _app = &app; - store.signal_new_object().connect( - sigc::mem_fun(this, &GraphTreeWindow::new_object)); -} - -void -GraphTreeWindow::new_object(SPtr object) -{ - SPtr graph = dynamic_ptr_cast(object); - if (graph) { - add_graph(graph); - } -} - -void -GraphTreeWindow::add_graph(SPtr pm) -{ - if (!pm->parent()) { - Gtk::TreeModel::iterator iter = _graph_treestore->append(); - Gtk::TreeModel::Row row = *iter; - if (pm->path().is_root()) { - row[_graph_tree_columns.name_col] = _app->interface()->uri().string(); - } else { - row[_graph_tree_columns.name_col] = pm->symbol().c_str(); - } - row[_graph_tree_columns.enabled_col] = pm->enabled(); - row[_graph_tree_columns.graph_model_col] = pm; - _graphs_treeview->expand_row(_graph_treestore->get_path(iter), true); - } else { - Gtk::TreeModel::Children children = _graph_treestore->children(); - Gtk::TreeModel::iterator c = find_graph(children, pm->parent()); - - if (c != children.end()) { - Gtk::TreeModel::iterator iter = _graph_treestore->append(c->children()); - Gtk::TreeModel::Row row = *iter; - row[_graph_tree_columns.name_col] = pm->symbol().c_str(); - row[_graph_tree_columns.enabled_col] = pm->enabled(); - row[_graph_tree_columns.graph_model_col] = pm; - _graphs_treeview->expand_row(_graph_treestore->get_path(iter), true); - } - } - - pm->signal_property().connect( - sigc::bind(sigc::mem_fun(this, &GraphTreeWindow::graph_property_changed), - pm)); - - pm->signal_moved().connect( - sigc::bind(sigc::mem_fun(this, &GraphTreeWindow::graph_moved), - pm)); - - pm->signal_destroyed().connect( - sigc::bind(sigc::mem_fun(this, &GraphTreeWindow::remove_graph), - pm)); -} - -void -GraphTreeWindow::remove_graph(SPtr pm) -{ - Gtk::TreeModel::iterator i = find_graph(_graph_treestore->children(), pm); - if (i != _graph_treestore->children().end()) { - _graph_treestore->erase(i); - } -} - -Gtk::TreeModel::iterator -GraphTreeWindow::find_graph(Gtk::TreeModel::Children root, - SPtr graph) -{ - for (Gtk::TreeModel::iterator c = root.begin(); c != root.end(); ++c) { - SPtr pm = (*c)[_graph_tree_columns.graph_model_col]; - if (graph == pm) { - return c; - } else if ((*c)->children().size() > 0) { - Gtk::TreeModel::iterator ret = find_graph(c->children(), graph); - if (ret != c->children().end()) { - return ret; - } - } - } - return root.end(); -} - -/** Show the context menu for the selected graph in the graphs treeview. - */ -void -GraphTreeWindow::show_graph_menu(GdkEventButton* ev) -{ - Gtk::TreeModel::iterator active = _graph_tree_selection->get_selected(); - if (active) { - Gtk::TreeModel::Row row = *active; - SPtr pm = row[_graph_tree_columns.graph_model_col]; - if (pm) { - _app->log().warn("TODO: graph menu from tree window"); - } - } -} - -void -GraphTreeWindow::event_graph_activated(const Gtk::TreeModel::Path& path, - Gtk::TreeView::Column* col) -{ - Gtk::TreeModel::iterator active = _graph_treestore->get_iter(path); - Gtk::TreeModel::Row row = *active; - SPtr pm = row[_graph_tree_columns.graph_model_col]; - - _app->window_factory()->present_graph(pm); -} - -void -GraphTreeWindow::event_graph_enabled_toggled(const Glib::ustring& path_str) -{ - Gtk::TreeModel::Path path(path_str); - Gtk::TreeModel::iterator active = _graph_treestore->get_iter(path); - Gtk::TreeModel::Row row = *active; - - SPtr pm = row[_graph_tree_columns.graph_model_col]; - assert(pm); - - if (_enable_signal) { - _app->set_property(pm->uri(), - _app->uris().ingen_enabled, - _app->forge().make((bool)!pm->enabled())); - } -} - -void -GraphTreeWindow::graph_property_changed(const URI& key, - const Atom& value, - SPtr graph) -{ - const URIs& uris = _app->uris(); - _enable_signal = false; - if (key == uris.ingen_enabled && value.type() == uris.forge.Bool) { - Gtk::TreeModel::iterator i = find_graph(_graph_treestore->children(), graph); - if (i != _graph_treestore->children().end()) { - Gtk::TreeModel::Row row = *i; - row[_graph_tree_columns.enabled_col] = value.get(); - } else { - _app->log().error(fmt("Unable to find graph %1%\n") - % graph->path()); - } - } - _enable_signal = true; -} - -void -GraphTreeWindow::graph_moved(SPtr graph) -{ - _enable_signal = false; - - Gtk::TreeModel::iterator i - = find_graph(_graph_treestore->children(), graph); - - if (i != _graph_treestore->children().end()) { - Gtk::TreeModel::Row row = *i; - row[_graph_tree_columns.name_col] = graph->symbol().c_str(); - } else { - _app->log().error(fmt("Unable to find graph %1%\n") - % graph->path()); - } - - _enable_signal = true; -} - -} // namespace GUI -} // namespace Ingen diff --git a/src/gui/GraphTreeWindow.hpp b/src/gui/GraphTreeWindow.hpp deleted file mode 100644 index 005f39a8..00000000 --- a/src/gui/GraphTreeWindow.hpp +++ /dev/null @@ -1,123 +0,0 @@ -/* - This file is part of Ingen. - Copyright 2007-2015 David Robillard - - 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 - Software Foundation, either version 3 of the License, or 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 Affero General Public License for details. - - You should have received a copy of the GNU Affero General Public License - along with Ingen. If not, see . -*/ - -#ifndef INGEN_GUI_GRAPHTREEWINDOW_HPP -#define INGEN_GUI_GRAPHTREEWINDOW_HPP - -#include -#include -#include -#include - -#include "Window.hpp" - -namespace Raul { class Path; } - -namespace Ingen { - -namespace Client { class ClientStore; class ObjectModel; } - -namespace GUI { - -class GraphWindow; -class GraphTreeView; - -/** Window with a TreeView of all loaded graphs. - * - * \ingroup GUI - */ -class GraphTreeWindow : public Window -{ -public: - GraphTreeWindow(BaseObjectType* cobject, - const Glib::RefPtr& xml); - - void init(App& app, Client::ClientStore& store); - - void new_object(SPtr object); - - void graph_property_changed(const URI& key, - const Atom& value, - SPtr graph); - - void graph_moved(SPtr graph); - - void add_graph(SPtr pm); - void remove_graph(SPtr pm); - void show_graph_menu(GdkEventButton* ev); - -protected: - void event_graph_activated(const Gtk::TreeModel::Path& path, - Gtk::TreeView::Column* col); - - void event_graph_enabled_toggled(const Glib::ustring& path_str); - - Gtk::TreeModel::iterator find_graph( - Gtk::TreeModel::Children root, - SPtr graph); - - GraphTreeView* _graphs_treeview; - - struct GraphTreeModelColumns : public Gtk::TreeModel::ColumnRecord - { - GraphTreeModelColumns() { - add(name_col); - add(enabled_col); - add(graph_model_col); - } - - Gtk::TreeModelColumn name_col; - Gtk::TreeModelColumn enabled_col; - Gtk::TreeModelColumn > graph_model_col; - }; - - App* _app; - GraphTreeModelColumns _graph_tree_columns; - Glib::RefPtr _graph_treestore; - Glib::RefPtr _graph_tree_selection; - bool _enable_signal; -}; - -/** Derived TreeView class to support context menus for graphs */ -class GraphTreeView : public Gtk::TreeView -{ -public: - GraphTreeView(BaseObjectType* cobject, - const Glib::RefPtr& xml) - : Gtk::TreeView(cobject) - , _window(NULL) - {} - - void set_window(GraphTreeWindow* win) { _window = win; } - - bool on_button_press_event(GdkEventButton* ev) { - bool ret = Gtk::TreeView::on_button_press_event(ev); - - if ((ev->type == GDK_BUTTON_PRESS) && (ev->button == 3)) - _window->show_graph_menu(ev); - - return ret; - } - -private: - GraphTreeWindow* _window; - -}; // struct GraphTreeView - -} // namespace GUI -} // namespace Ingen - -#endif // INGEN_GUI_GRAPHTREEWINDOW_HPP diff --git a/src/gui/GraphView.cpp b/src/gui/GraphView.cpp deleted file mode 100644 index e6361249..00000000 --- a/src/gui/GraphView.cpp +++ /dev/null @@ -1,154 +0,0 @@ -/* - This file is part of Ingen. - Copyright 2007-2015 David Robillard - - 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 - Software Foundation, either version 3 of the License, or 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 Affero General Public License for details. - - You should have received a copy of the GNU Affero General Public License - along with Ingen. If not, see . -*/ - -#include -#include - -#include "ingen/Interface.hpp" -#include "ingen/client/GraphModel.hpp" - -#include "App.hpp" -#include "LoadPluginWindow.hpp" -#include "NewSubgraphWindow.hpp" -#include "GraphCanvas.hpp" -#include "GraphTreeWindow.hpp" -#include "GraphView.hpp" -#include "WidgetFactory.hpp" - -namespace Ingen { - -using namespace Client; - -namespace GUI { - -GraphView::GraphView(BaseObjectType* cobject, - const Glib::RefPtr& xml) - : Gtk::Box(cobject) - , _app(nullptr) - , _breadcrumb_container(nullptr) - , _enable_signal(true) -{ - property_visible() = false; - - xml->get_widget("graph_view_breadcrumb_container", _breadcrumb_container); - xml->get_widget("graph_view_toolbar", _toolbar); - xml->get_widget("graph_view_process_but", _process_but); - xml->get_widget("graph_view_poly_spin", _poly_spin); - xml->get_widget("graph_view_scrolledwindow", _canvas_scrolledwindow); - - _toolbar->set_toolbar_style(Gtk::TOOLBAR_ICONS); - _canvas_scrolledwindow->property_hadjustment().get_value()->set_step_increment(10); - _canvas_scrolledwindow->property_vadjustment().get_value()->set_step_increment(10); -} - -GraphView::~GraphView() -{ - _canvas_scrolledwindow->remove(); -} - -void -GraphView::init(App& app) -{ - _app = &app; -} - -void -GraphView::set_graph(SPtr graph) -{ - assert(!_canvas); // FIXME: remove - - assert(_breadcrumb_container); // ensure created - - _graph = graph; - _canvas = SPtr(new GraphCanvas(*_app, graph, 1600*2, 1200*2)); - _canvas->build(); - - _canvas_scrolledwindow->add(_canvas->widget()); - - _poly_spin->set_range(1, 128); - _poly_spin->set_increments(1, 4); - _poly_spin->set_value(graph->internal_poly()); - - for (const auto& p : graph->properties()) { - property_changed(p.first, p.second); - } - - // Connect model signals to track state - graph->signal_property().connect( - sigc::mem_fun(this, &GraphView::property_changed)); - - // Connect widget signals to do things - _process_but->signal_toggled().connect( - sigc::mem_fun(this, &GraphView::process_toggled)); - - _poly_spin->signal_value_changed().connect( - sigc::mem_fun(*this, &GraphView::poly_changed)); - - _canvas->widget().grab_focus(); -} - -SPtr -GraphView::create(App& app, SPtr graph) -{ - GraphView* result = nullptr; - Glib::RefPtr xml = WidgetFactory::create("warehouse_win"); - xml->get_widget_derived("graph_view_box", result); - result->init(app); - result->set_graph(graph); - return SPtr(result); -} - -void -GraphView::process_toggled() -{ - if (!_enable_signal) { - return; - } - - _app->set_property(_graph->uri(), - _app->uris().ingen_enabled, - _app->forge().make((bool)_process_but->get_active())); -} - -void -GraphView::poly_changed() -{ - const int poly = _poly_spin->get_value_as_int(); - if (_enable_signal && poly != (int)_graph->internal_poly()) { - _app->set_property(_graph->uri(), - _app->uris().ingen_polyphony, - _app->forge().make(poly)); - } -} - -void -GraphView::property_changed(const URI& predicate, const Atom& value) -{ - _enable_signal = false; - if (predicate == _app->uris().ingen_enabled) { - if (value.type() == _app->uris().forge.Bool) { - _process_but->set_active(value.get()); - } - } else if (predicate == _app->uris().ingen_polyphony) { - if (value.type() == _app->uris().forge.Int) { - _poly_spin->set_value(value.get()); - } - } - _enable_signal = true; -} - -} // namespace GUI -} // namespace Ingen diff --git a/src/gui/GraphView.hpp b/src/gui/GraphView.hpp deleted file mode 100644 index 03569831..00000000 --- a/src/gui/GraphView.hpp +++ /dev/null @@ -1,98 +0,0 @@ -/* - This file is part of Ingen. - Copyright 2007-2015 David Robillard - - 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 - Software Foundation, either version 3 of the License, or 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 Affero General Public License for details. - - You should have received a copy of the GNU Affero General Public License - along with Ingen. If not, see . -*/ - -#ifndef INGEN_GUI_GRAPHVIEW_HPP -#define INGEN_GUI_GRAPHVIEW_HPP - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "ingen/types.hpp" - -namespace Raul { class Atom; } - -namespace Ingen { - -namespace Client { -class PortModel; -class MetadataModel; -class GraphModel; -class ObjectModel; -} - -namespace GUI { - -class App; -class LoadPluginWindow; -class NewSubgraphWindow; -class GraphCanvas; -class GraphDescriptionWindow; -class SubgraphModule; - -/** The graph specific contents of a GraphWindow (ie the canvas and whatever else). - * - * \ingroup GUI - */ -class GraphView : public Gtk::Box -{ -public: - GraphView(BaseObjectType* cobject, - const Glib::RefPtr& xml); - - ~GraphView(); - - void init(App& app); - - SPtr canvas() const { return _canvas; } - SPtr graph() const { return _graph; } - Gtk::ToolItem* breadcrumb_container() const { return _breadcrumb_container; } - - static SPtr create(App& app, - SPtr graph); - -private: - void set_graph(SPtr graph); - - void process_toggled(); - void poly_changed(); - void clear_clicked(); - - void property_changed(const URI& predicate, const Atom& value); - - App* _app; - - SPtr _graph; - SPtr _canvas; - - Gtk::ScrolledWindow* _canvas_scrolledwindow; - Gtk::Toolbar* _toolbar; - Gtk::ToggleToolButton* _process_but; - Gtk::SpinButton* _poly_spin; - Gtk::ToolItem* _breadcrumb_container; - - bool _enable_signal; -}; - -} // namespace GUI -} // namespace Ingen - -#endif // INGEN_GUI_GRAPHVIEW_HPP diff --git a/src/gui/GraphWindow.cpp b/src/gui/GraphWindow.cpp deleted file mode 100644 index b5a89c79..00000000 --- a/src/gui/GraphWindow.cpp +++ /dev/null @@ -1,85 +0,0 @@ -/* - This file is part of Ingen. - Copyright 2007-2015 David Robillard - - 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 - Software Foundation, either version 3 of the License, or 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 Affero General Public License for details. - - You should have received a copy of the GNU Affero General Public License - along with Ingen. If not, see . -*/ - -#include "ingen/client/ClientStore.hpp" -#include "ingen/client/GraphModel.hpp" - -#include "App.hpp" -#include "GraphCanvas.hpp" -#include "GraphView.hpp" -#include "GraphWindow.hpp" -#include "WindowFactory.hpp" - -namespace Ingen { -namespace GUI { - -GraphWindow::GraphWindow(BaseObjectType* cobject, - const Glib::RefPtr& xml) - : Window(cobject) - , _box(nullptr) - , _position_stored(false) - , _x(0) - , _y(0) -{ - property_visible() = false; - - xml->get_widget_derived("graph_win_vbox", _box); - - set_title("Ingen"); -} - -GraphWindow::~GraphWindow() -{ - delete _box; -} - -void -GraphWindow::init_window(App& app) -{ - Window::init_window(app); - _box->init_box(app); - _box->set_window(this); -} - -void -GraphWindow::on_show() -{ - if (_position_stored) { - move(_x, _y); - } - - Gtk::Window::on_show(); - - _box->view()->canvas()->widget().grab_focus(); -} - -void -GraphWindow::on_hide() -{ - _position_stored = true; - get_position(_x, _y); - Gtk::Window::on_hide(); -} - -bool -GraphWindow::on_key_press_event(GdkEventKey* event) -{ - // Disable Window C-w handling so quit works correctly - return Gtk::Window::on_key_press_event(event); -} - -} // namespace GUI -} // namespace Ingen diff --git a/src/gui/GraphWindow.hpp b/src/gui/GraphWindow.hpp deleted file mode 100644 index b4e51d7b..00000000 --- a/src/gui/GraphWindow.hpp +++ /dev/null @@ -1,80 +0,0 @@ -/* - This file is part of Ingen. - Copyright 2007-2015 David Robillard - - 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 - Software Foundation, either version 3 of the License, or 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 Affero General Public License for details. - - You should have received a copy of the GNU Affero General Public License - along with Ingen. If not, see . -*/ - -#ifndef INGEN_GUI_GRAPH_WINDOW_HPP -#define INGEN_GUI_GRAPH_WINDOW_HPP - -#include - -#include - -#include "ingen/types.hpp" - -#include "GraphBox.hpp" -#include "Window.hpp" - -namespace Ingen { - -namespace Client { -class GraphModel; -} - -namespace GUI { - -/** A window for a graph. - * - * \ingroup GUI - */ -class GraphWindow : public Window -{ -public: - GraphWindow(BaseObjectType* cobject, - const Glib::RefPtr& xml); - - ~GraphWindow(); - - void init_window(App& app); - - SPtr graph() const { return _box->graph(); } - GraphBox* box() const { return _box; } - - bool documentation_is_visible() { return _box->documentation_is_visible(); } - - void set_documentation(const std::string& doc, bool html) { - _box->set_documentation(doc, html); - } - - void show_port_status(const Client::PortModel* model, - const Atom& value) { - _box->show_port_status(model, value); - } - -protected: - void on_hide(); - void on_show(); - bool on_key_press_event(GdkEventKey* event); - -private: - GraphBox* _box; - bool _position_stored; - int _x; - int _y; -}; - -} // namespace GUI -} // namespace Ingen - -#endif // INGEN_GUI_GRAPH_WINDOW_HPP diff --git a/src/gui/LoadGraphWindow.cpp b/src/gui/LoadGraphWindow.cpp deleted file mode 100644 index b02ca510..00000000 --- a/src/gui/LoadGraphWindow.cpp +++ /dev/null @@ -1,257 +0,0 @@ -/* - This file is part of Ingen. - Copyright 2007-2015 David Robillard - - 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 - Software Foundation, either version 3 of the License, or 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 Affero General Public License for details. - - You should have received a copy of the GNU Affero General Public License - along with Ingen. If not, see . -*/ - -#include -#include -#include - -#include -#include - -#include "ingen/Configuration.hpp" -#include "ingen/Interface.hpp" -#include "ingen/client/BlockModel.hpp" -#include "ingen/client/ClientStore.hpp" -#include "ingen/client/GraphModel.hpp" -#include "ingen/runtime_paths.hpp" - -#include "App.hpp" -#include "GraphView.hpp" -#include "LoadGraphWindow.hpp" -#include "Style.hpp" -#include "ThreadedLoader.hpp" - -namespace Ingen { - -using namespace Client; - -namespace GUI { - -LoadGraphWindow::LoadGraphWindow(BaseObjectType* cobject, - const Glib::RefPtr& xml) - : Gtk::FileChooserDialog(cobject) - , _app(nullptr) - , _merge_ports(false) -{ - xml->get_widget("load_graph_symbol_label", _symbol_label); - xml->get_widget("load_graph_symbol_entry", _symbol_entry); - xml->get_widget("load_graph_ports_label", _ports_label); - xml->get_widget("load_graph_merge_ports_radio", _merge_ports_radio); - xml->get_widget("load_graph_insert_ports_radio", _insert_ports_radio); - xml->get_widget("load_graph_poly_voices_radio", _poly_voices_radio); - xml->get_widget("load_graph_poly_from_file_radio", _poly_from_file_radio); - xml->get_widget("load_graph_poly_spinbutton", _poly_spinbutton); - xml->get_widget("load_graph_ok_button", _ok_button); - xml->get_widget("load_graph_cancel_button", _cancel_button); - - _cancel_button->signal_clicked().connect( - sigc::mem_fun(this, &LoadGraphWindow::cancel_clicked)); - _ok_button->signal_clicked().connect( - sigc::mem_fun(this, &LoadGraphWindow::ok_clicked)); - _merge_ports_radio->signal_toggled().connect( - sigc::mem_fun(this, &LoadGraphWindow::merge_ports_selected)); - _insert_ports_radio->signal_toggled().connect( - sigc::mem_fun(this, &LoadGraphWindow::insert_ports_selected)); - _poly_from_file_radio->signal_toggled().connect( - sigc::bind(sigc::mem_fun(_poly_spinbutton, &Gtk::SpinButton::set_sensitive), - false)); - _poly_voices_radio->signal_toggled().connect( - sigc::bind(sigc::mem_fun(_poly_spinbutton, &Gtk::SpinButton::set_sensitive), - true)); - - signal_selection_changed().connect( - sigc::mem_fun(this, &LoadGraphWindow::selection_changed)); - - Gtk::FileFilter file_filter; - file_filter.add_pattern("*.ttl"); - file_filter.set_name("Ingen graph files (*.ttl)"); - add_filter(file_filter); - - Gtk::FileFilter bundle_filter; - bundle_filter.add_pattern("*.ingen"); - bundle_filter.set_name("Ingen bundles (*.ingen)"); - add_filter(bundle_filter); - - property_select_multiple() = true; - - // Add global examples directory to "shortcut folders" (bookmarks) - const FilePath examples_dir = Ingen::data_file_path("graphs"); - if (Glib::file_test(examples_dir, Glib::FILE_TEST_IS_DIR)) { - add_shortcut_folder(examples_dir.string()); - } -} - -void -LoadGraphWindow::present(SPtr graph, - bool import, - Properties data) -{ - _import = import; - set_graph(graph); - _symbol_label->property_visible() = !import; - _symbol_entry->property_visible() = !import; - _ports_label->property_visible() = _import; - _merge_ports_radio->property_visible() = _import; - _insert_ports_radio->property_visible() = _import; - _initial_data = data; - Gtk::Window::present(); -} - -/** Sets the graph model for this window and initializes everything. - * - * This function MUST be called before using the window in any way! - */ -void -LoadGraphWindow::set_graph(SPtr graph) -{ - _graph = graph; - _symbol_entry->set_text(""); - _symbol_entry->set_sensitive(!_import); - _poly_spinbutton->set_value(graph->internal_poly()); -} - -void -LoadGraphWindow::on_show() -{ - const Atom& dir = _app->world()->conf().option("graph-directory"); - if (dir.is_valid()) { - set_current_folder(dir.ptr()); - } - Gtk::FileChooserDialog::on_show(); -} - -void -LoadGraphWindow::merge_ports_selected() -{ - _merge_ports = true; -} - -void -LoadGraphWindow::insert_ports_selected() -{ - _merge_ports = false; -} - -void -LoadGraphWindow::ok_clicked() -{ - if (!_graph) { - hide(); - return; - } - - const URIs& uris = _app->uris(); - - if (_poly_voices_radio->get_active()) { - _initial_data.emplace( - uris.ingen_polyphony, - _app->forge().make(_poly_spinbutton->get_value_as_int())); - } - - if (get_uri() == "") { - return; - } - - if (_import) { - // If unset load_graph will load value - boost::optional parent; - boost::optional symbol; - if (!_graph->path().is_root()) { - parent = _graph->path().parent(); - symbol = _graph->symbol(); - } - - _app->loader()->load_graph( - true, FilePath(get_filename()), parent, symbol, _initial_data); - - } else { - std::list uri_list = get_filenames(); - for (auto u : uri_list) { - // Cascade - Atom& x = _initial_data.find(uris.ingen_canvasX)->second; - x = _app->forge().make(x.get() + 20.0f); - Atom& y = _initial_data.find(uris.ingen_canvasY)->second; - y = _app->forge().make(y.get() + 20.0f); - - Raul::Symbol symbol(symbol_from_filename(u)); - if (uri_list.size() == 1 && _symbol_entry->get_text() != "") { - symbol = Raul::Symbol::symbolify(_symbol_entry->get_text()); - } - - symbol = avoid_symbol_clash(symbol); - - _app->loader()->load_graph( - false, FilePath(URI(u).path()), _graph->path(), symbol, _initial_data); - } - } - - _graph.reset(); - hide(); - - _app->world()->conf().set( - "graph-directory", - _app->world()->forge().alloc(get_current_folder())); -} - -void -LoadGraphWindow::cancel_clicked() -{ - _graph.reset(); - hide(); -} - -Raul::Symbol -LoadGraphWindow::symbol_from_filename(const Glib::ustring& filename) -{ - std::string symbol_str = Glib::path_get_basename(get_filename()); - symbol_str = symbol_str.substr(0, symbol_str.find('.')); - return Raul::Symbol::symbolify(symbol_str); -} - -Raul::Symbol -LoadGraphWindow::avoid_symbol_clash(const Raul::Symbol& symbol) -{ - unsigned offset = _app->store()->child_name_offset( - _graph->path(), symbol); - - if (offset != 0) { - std::stringstream ss; - ss << symbol << "_" << offset; - return Raul::Symbol(ss.str()); - } else { - return symbol; - } -} - -void -LoadGraphWindow::selection_changed() -{ - if (_import) { - return; - } - - if (get_filenames().size() != 1) { - _symbol_entry->set_text(""); - _symbol_entry->set_sensitive(false); - } else { - _symbol_entry->set_text( - avoid_symbol_clash(symbol_from_filename(get_filename())).c_str()); - _symbol_entry->set_sensitive(true); - } -} - -} // namespace GUI -} // namespace Ingen diff --git a/src/gui/LoadGraphWindow.hpp b/src/gui/LoadGraphWindow.hpp deleted file mode 100644 index 8ec5ed4b..00000000 --- a/src/gui/LoadGraphWindow.hpp +++ /dev/null @@ -1,95 +0,0 @@ -/* - This file is part of Ingen. - Copyright 2007-2015 David Robillard - - 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 - Software Foundation, either version 3 of the License, or 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 Affero General Public License for details. - - You should have received a copy of the GNU Affero General Public License - along with Ingen. If not, see . -*/ - -#ifndef INGEN_GUI_LOADGRAPHWINDOW_HPP -#define INGEN_GUI_LOADGRAPHWINDOW_HPP - -#include -#include -#include -#include -#include -#include -#include - -#include "ingen/Node.hpp" -#include "ingen/types.hpp" - -namespace Ingen { - -namespace Client { class GraphModel; } - -namespace GUI { - -/** 'Load Graph' Window. - * - * Loaded from XML as a derived object. - * - * \ingroup GUI - */ -class LoadGraphWindow : public Gtk::FileChooserDialog -{ -public: - LoadGraphWindow(BaseObjectType* cobject, - const Glib::RefPtr& xml); - - void init(App& app) { _app = &app; } - - void set_graph(SPtr graph); - - void present(SPtr graph, - bool import, - Properties data); - -protected: - void on_show(); - -private: - void merge_ports_selected(); - void insert_ports_selected(); - - void selection_changed(); - void cancel_clicked(); - void ok_clicked(); - - Raul::Symbol symbol_from_filename(const Glib::ustring& filename); - Raul::Symbol avoid_symbol_clash(const Raul::Symbol& symbol); - - App* _app; - - Properties _initial_data; - - SPtr _graph; - - Gtk::Label* _symbol_label; - Gtk::Entry* _symbol_entry; - Gtk::Label* _ports_label; - Gtk::RadioButton* _merge_ports_radio; - Gtk::RadioButton* _insert_ports_radio; - Gtk::RadioButton* _poly_voices_radio; - Gtk::RadioButton* _poly_from_file_radio; - Gtk::SpinButton* _poly_spinbutton; - Gtk::Button* _ok_button; - Gtk::Button* _cancel_button; - - bool _import; - bool _merge_ports; -}; - -} // namespace GUI -} // namespace Ingen - -#endif // INGEN_GUI_LOADGRAPHWINDOW_HPP diff --git a/src/gui/LoadPluginWindow.cpp b/src/gui/LoadPluginWindow.cpp deleted file mode 100644 index bd08f457..00000000 --- a/src/gui/LoadPluginWindow.cpp +++ /dev/null @@ -1,511 +0,0 @@ -/* - This file is part of Ingen. - Copyright 2007-2017 David Robillard - - 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 - Software Foundation, either version 3 of the License, or 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 Affero General Public License for details. - - You should have received a copy of the GNU Affero General Public License - along with Ingen. If not, see . -*/ - -#include - -#include - -#include -#include - -#include "ingen/Interface.hpp" -#include "ingen/client/ClientStore.hpp" -#include "ingen/client/GraphModel.hpp" - -#include "App.hpp" -#include "LoadPluginWindow.hpp" -#include "GraphCanvas.hpp" -#include "GraphView.hpp" -#include "GraphWindow.hpp" - -#include "ingen_config.h" - -using std::string; - -namespace Ingen { - -using namespace Client; - -namespace GUI { - -LoadPluginWindow::LoadPluginWindow(BaseObjectType* cobject, - const Glib::RefPtr& xml) - : Window(cobject) - , _name_offset(0) - , _has_shown(false) - , _refresh_list(true) -{ - xml->get_widget("load_plugin_plugins_treeview", _plugins_treeview); - xml->get_widget("load_plugin_polyphonic_checkbutton", _polyphonic_checkbutton); - xml->get_widget("load_plugin_name_entry", _name_entry); - xml->get_widget("load_plugin_add_button", _add_button); - xml->get_widget("load_plugin_close_button", _close_button); - - xml->get_widget("load_plugin_filter_combo", _filter_combo); - xml->get_widget("load_plugin_search_entry", _search_entry); - - // Set up the plugins list - _plugins_liststore = Gtk::ListStore::create(_plugins_columns); - _plugins_treeview->set_model(_plugins_liststore); - _plugins_treeview->append_column("_Name", _plugins_columns._col_name); - _plugins_treeview->append_column("_Type", _plugins_columns._col_type); - _plugins_treeview->append_column("_Project", _plugins_columns._col_project); - _plugins_treeview->append_column("_Author", _plugins_columns._col_author); - _plugins_treeview->append_column("_URI", _plugins_columns._col_uri); - - // This could be nicer.. store the TreeViewColumns locally maybe? - _plugins_treeview->get_column(0)->set_sort_column(_plugins_columns._col_name); - _plugins_treeview->get_column(1)->set_sort_column(_plugins_columns._col_type); - _plugins_treeview->get_column(2)->set_sort_column(_plugins_columns._col_project); - _plugins_treeview->get_column(2)->set_sort_column(_plugins_columns._col_author); - _plugins_treeview->get_column(3)->set_sort_column(_plugins_columns._col_uri); - for (int i = 0; i < 5; ++i) { - _plugins_treeview->get_column(i)->set_resizable(true); - } - - // Set up the search criteria combobox - _criteria_liststore = Gtk::ListStore::create(_criteria_columns); - _filter_combo->set_model(_criteria_liststore); - - Gtk::TreeModel::iterator iter = _criteria_liststore->append(); - Gtk::TreeModel::Row row = *iter; - row[_criteria_columns._col_label] = "Name contains"; - row[_criteria_columns._col_criteria] = CriteriaColumns::Criteria::NAME; - _filter_combo->set_active(iter); - - row = *(iter = _criteria_liststore->append()); - row[_criteria_columns._col_label] = "Type contains"; - row[_criteria_columns._col_criteria] = CriteriaColumns::Criteria::TYPE; - - row = *(iter = _criteria_liststore->append()); - row[_criteria_columns._col_label] = "Project contains"; - row[_criteria_columns._col_criteria] = CriteriaColumns::Criteria::PROJECT; - - row = *(iter = _criteria_liststore->append()); - row[_criteria_columns._col_label] = "Author contains"; - row[_criteria_columns._col_criteria] = CriteriaColumns::Criteria::AUTHOR; - - row = *(iter = _criteria_liststore->append()); - row[_criteria_columns._col_label] = "URI contains"; - row[_criteria_columns._col_criteria] = CriteriaColumns::Criteria::URI; - _filter_combo->pack_start(_criteria_columns._col_label); - - _add_button->signal_clicked().connect( - sigc::mem_fun(this, &LoadPluginWindow::add_clicked)); - _close_button->signal_clicked().connect( - sigc::mem_fun(this, &Window::hide)); - _plugins_treeview->signal_row_activated().connect( - sigc::mem_fun(this, &LoadPluginWindow::plugin_activated)); - _search_entry->signal_activate().connect( - sigc::mem_fun(this, &LoadPluginWindow::add_clicked)); - _search_entry->signal_changed().connect( - sigc::mem_fun(this, &LoadPluginWindow::filter_changed)); - _name_entry->signal_changed().connect( - sigc::mem_fun(this, &LoadPluginWindow::name_changed)); - - _search_entry->signal_icon_release().connect( - sigc::mem_fun(this, &LoadPluginWindow::name_cleared)); - - _selection = _plugins_treeview->get_selection(); - _selection->set_mode(Gtk::SELECTION_MULTIPLE); - _selection->signal_changed().connect( - sigc::mem_fun(this, &LoadPluginWindow::plugin_selection_changed)); - - //m_add_button->grab_default(); -} - -void -LoadPluginWindow::present(SPtr graph, - Properties data) -{ - set_graph(graph); - _initial_data = data; - Gtk::Window::present(); -} - -/** Called every time the user types into the name input box. - * Used to display warning messages, and enable/disable the OK button. - */ -void -LoadPluginWindow::name_changed() -{ - // Toggle add button sensitivity according name legality - if (_selection->get_selected_rows().size() == 1) { - const string sym = _name_entry->get_text(); - if (!Raul::Symbol::is_valid(sym)) { - _add_button->property_sensitive() = false; - } else if (_app->store()->find(_graph->path().child(Raul::Symbol(sym))) - != _app->store()->end()) { - _add_button->property_sensitive() = false; - } else { - _add_button->property_sensitive() = true; - } - } -} - -void -LoadPluginWindow::name_cleared(Gtk::EntryIconPosition pos, const GdkEventButton* event) -{ - _search_entry->set_text(""); -} - -/** Sets the graph controller for this window and initializes everything. - * - * This function MUST be called before using the window in any way! - */ -void -LoadPluginWindow::set_graph(SPtr graph) -{ - if (_graph) { - _graph = graph; - plugin_selection_changed(); - } else { - _graph = graph; - } -} - -/** Populates the plugin list on the first show. - * - * This is done here instead of construction time as the list population is - * really expensive and bogs down creation of a graph. This is especially - * important when many graph notifications are sent at one time from the - * engine. - */ -void -LoadPluginWindow::on_show() -{ - if (!_has_shown) { - _app->store()->signal_new_plugin().connect( - sigc::mem_fun(this, &LoadPluginWindow::add_plugin)); - _has_shown = true; - } - - if (_refresh_list) { - set_plugins(_app->store()->plugins()); - _refresh_list = false; - } - - Gtk::Window::on_show(); -} - -void -LoadPluginWindow::set_plugins(SPtr plugins) -{ - _rows.clear(); - _plugins_liststore->clear(); - - for (const auto& p : *plugins.get()) { - add_plugin(p.second); - } - - _plugins_liststore->set_sort_column(1, Gtk::SORT_ASCENDING); - _plugins_treeview->columns_autosize(); -} - -void -LoadPluginWindow::new_plugin(SPtr pm) -{ - if (is_visible()) { - add_plugin(pm); - } else { - _refresh_list = true; - } -} - -static std::string -get_project_name(SPtr plugin) -{ - std::string name; - if (plugin->lilv_plugin()) { - LilvNode* project = lilv_plugin_get_project(plugin->lilv_plugin()); - if (!project) { - return ""; - } - - LilvNode* doap_name = lilv_new_uri( - plugin->lilv_world(), "http://usefulinc.com/ns/doap#name"); - LilvNodes* names = lilv_world_find_nodes( - plugin->lilv_world(), project, doap_name, nullptr); - - if (names) { - name = lilv_node_as_string(lilv_nodes_get_first(names)); - } - - lilv_nodes_free(names); - lilv_node_free(doap_name); - lilv_node_free(project); - } - return name; -} - -static std::string -get_author_name(SPtr plugin) -{ - std::string name; - if (plugin->lilv_plugin()) { - LilvNode* author = lilv_plugin_get_author_name(plugin->lilv_plugin()); - if (author) { - name = lilv_node_as_string(author); - } - lilv_node_free(author); - } - return name; -} - -void -LoadPluginWindow::set_row(Gtk::TreeModel::Row& row, - SPtr plugin) -{ - const URIs& uris = _app->uris(); - const Atom& name = plugin->get_property(uris.doap_name); - if (name.is_valid() && name.type() == uris.forge.String) { - row[_plugins_columns._col_name] = name.ptr(); - } - - if (uris.lv2_Plugin == plugin->type()) { - row[_plugins_columns._col_type] = lilv_node_as_string( - lilv_plugin_class_get_label( - lilv_plugin_get_class(plugin->lilv_plugin()))); - - row[_plugins_columns._col_project] = get_project_name(plugin); - row[_plugins_columns._col_author] = get_author_name(plugin); - } else if (uris.ingen_Internal == plugin->type()) { - row[_plugins_columns._col_type] = "Internal"; - row[_plugins_columns._col_project] = "Ingen"; - row[_plugins_columns._col_author] = "David Robillard"; - } else if (uris.ingen_Graph == plugin->type()) { - row[_plugins_columns._col_type] = "Graph"; - } else { - row[_plugins_columns._col_type] = ""; - } - - row[_plugins_columns._col_uri] = plugin->uri().string(); - row[_plugins_columns._col_plugin] = plugin; -} - -void -LoadPluginWindow::add_plugin(SPtr plugin) -{ - if (plugin->lilv_plugin() && lilv_plugin_is_replaced(plugin->lilv_plugin())) { - return; - } - - Gtk::TreeModel::iterator iter = _plugins_liststore->append(); - Gtk::TreeModel::Row row = *iter; - _rows.emplace(plugin->uri(), iter); - - set_row(row, plugin); - - plugin->signal_property().connect( - sigc::bind<0>(sigc::mem_fun(this, &LoadPluginWindow::plugin_property_changed), - plugin->uri())); -} - -///// Event Handlers ////// - -void -LoadPluginWindow::plugin_activated(const Gtk::TreeModel::Path& path, - Gtk::TreeViewColumn* col) -{ - add_clicked(); -} - -void -LoadPluginWindow::plugin_selection_changed() -{ - size_t n_selected = _selection->get_selected_rows().size(); - if (n_selected == 0) { - _name_offset = 0; - _name_entry->set_text(""); - _name_entry->set_sensitive(false); - } else if (n_selected == 1) { - Gtk::TreeModel::iterator iter = _plugins_liststore->get_iter( - *_selection->get_selected_rows().begin()); - if (iter) { - Gtk::TreeModel::Row row = *iter; - SPtr p = row.get_value( - _plugins_columns._col_plugin); - _name_offset = _app->store()->child_name_offset( - _graph->path(), p->default_block_symbol()); - _name_entry->set_text(generate_module_name(p, _name_offset)); - _name_entry->set_sensitive(true); - } else { - _name_offset = 0; - _name_entry->set_text(""); - _name_entry->set_sensitive(false); - } - } else { - _name_entry->set_text(""); - _name_entry->set_sensitive(false); - } -} - -/** Generate an automatic name for this Node. - * - * Offset is an offset of the number that will be appended to the plugin's - * label, needed if the user adds multiple plugins faster than the engine - * sends the notification back. - */ -string -LoadPluginWindow::generate_module_name(SPtr plugin, - int offset) -{ - std::stringstream ss; - ss << plugin->default_block_symbol(); - if (offset != 0) { - ss << "_" << offset; - } - return ss.str(); -} - -void -LoadPluginWindow::load_plugin(const Gtk::TreeModel::iterator& iter) -{ - const URIs& uris = _app->uris(); - Gtk::TreeModel::Row row = *iter; - SPtr plugin = row.get_value(_plugins_columns._col_plugin); - bool polyphonic = _polyphonic_checkbutton->get_active(); - string name = _name_entry->get_text(); - - if (name.empty()) { - name = generate_module_name(plugin, _name_offset); - } - - if (name.empty() || !Raul::Symbol::is_valid(name)) { - Gtk::MessageDialog dialog( - *this, - "Unable to choose a default name, please provide one", - false, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true); - - dialog.run(); - } else { - Raul::Path path = _graph->path().child(Raul::Symbol::symbolify(name)); - Properties props = _initial_data; - props.emplace(uris.rdf_type, Property(uris.ingen_Block)); - props.emplace(uris.lv2_prototype, _app->forge().make_urid(plugin->uri())); - props.emplace(uris.ingen_polyphonic, _app->forge().make(polyphonic)); - _app->interface()->put(path_to_uri(path), props); - - if (_selection->get_selected_rows().size() == 1) { - _name_offset = (_name_offset == 0) ? 2 : _name_offset + 1; - _name_entry->set_text(generate_module_name(plugin, _name_offset)); - } - - // Cascade next block - Atom& x = _initial_data.find(uris.ingen_canvasX)->second; - x = _app->forge().make(x.get() + 20.0f); - Atom& y = _initial_data.find(uris.ingen_canvasY)->second; - y = _app->forge().make(y.get() + 20.0f); - } -} - -void -LoadPluginWindow::add_clicked() -{ - _selection->selected_foreach_iter( - sigc::mem_fun(*this, &LoadPluginWindow::load_plugin)); -} - -void -LoadPluginWindow::filter_changed() -{ - _rows.clear(); - _plugins_liststore->clear(); - string search = _search_entry->get_text(); - transform(search.begin(), search.end(), search.begin(), ::toupper); - - // Get selected criteria - const Gtk::TreeModel::Row row = *(_filter_combo->get_active()); - CriteriaColumns::Criteria criteria = row[_criteria_columns._col_criteria]; - - string field; - - Gtk::TreeModel::Row model_row; - Gtk::TreeModel::iterator model_iter; - size_t num_visible = 0; - const URIs& uris = _app->uris(); - - for (const auto& p : *_app->store()->plugins().get()) { - const SPtr plugin = p.second; - const Atom& name = plugin->get_property(uris.doap_name); - - switch (criteria) { - case CriteriaColumns::Criteria::NAME: - if (name.is_valid() && name.type() == uris.forge.String) { - field = name.ptr(); - } - break; - case CriteriaColumns::Criteria::TYPE: - if (plugin->lilv_plugin()) { - field = lilv_node_as_string( - lilv_plugin_class_get_label( - lilv_plugin_get_class(plugin->lilv_plugin()))); - } - break; - case CriteriaColumns::Criteria::PROJECT: - field = get_project_name(plugin); - break; - case CriteriaColumns::Criteria::AUTHOR: - field = get_author_name(plugin); - break; - case CriteriaColumns::Criteria::URI: - field = plugin->uri(); - break; - } - - transform(field.begin(), field.end(), field.begin(), ::toupper); - - if (field.find(search) != string::npos) { - model_iter = _plugins_liststore->append(); - model_row = *model_iter; - set_row(model_row, plugin); - ++num_visible; - } - } - - if (num_visible == 1) { - _selection->unselect_all(); - _selection->select(model_iter); - } -} - -bool -LoadPluginWindow::on_key_press_event(GdkEventKey* event) -{ - if (event->keyval == GDK_w && event->state & GDK_CONTROL_MASK) { - hide(); - return true; - } else { - return Gtk::Window::on_key_press_event(event); - } -} - -void -LoadPluginWindow::plugin_property_changed(const URI& plugin, - const URI& predicate, - const Atom& value) -{ - const URIs& uris = _app->uris(); - if (predicate == uris.doap_name) { - Rows::const_iterator i = _rows.find(plugin); - if (i != _rows.end() && value.type() == uris.forge.String) { - (*i->second)[_plugins_columns._col_name] = value.ptr(); - } - } -} - -} // namespace GUI -} // namespace Ingen diff --git a/src/gui/LoadPluginWindow.hpp b/src/gui/LoadPluginWindow.hpp deleted file mode 100644 index 29314c7a..00000000 --- a/src/gui/LoadPluginWindow.hpp +++ /dev/null @@ -1,160 +0,0 @@ -/* - This file is part of Ingen. - Copyright 2007-2015 David Robillard - - 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 - Software Foundation, either version 3 of the License, or 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 Affero General Public License for details. - - You should have received a copy of the GNU Affero General Public License - along with Ingen. If not, see . -*/ - -#ifndef INGEN_GUI_LOADPLUGINWINDOW_HPP -#define INGEN_GUI_LOADPLUGINWINDOW_HPP - -#include -#include - -#include -#include -#include -#include -#include - -#include "ingen/Node.hpp" -#include "ingen/client/ClientStore.hpp" -#include "ingen/types.hpp" -#include "ingen_config.h" - -#include "Window.hpp" - -namespace Ingen { - -namespace Client { -class GraphModel; -class PluginModel; -} - -namespace GUI { - -/** 'Load Plugin' window. - * - * Loaded from XML as a derived object. - * - * \ingroup GUI - */ -class LoadPluginWindow : public Window -{ -public: - LoadPluginWindow(BaseObjectType* cobject, - const Glib::RefPtr& xml); - - void set_graph(SPtr graph); - void set_plugins(SPtr plugins); - - void add_plugin(SPtr plugin); - - void present(SPtr graph, - Properties data); - -protected: - void on_show(); - bool on_key_press_event(GdkEventKey* event); - -private: - /** Columns for the plugin list */ - class ModelColumns : public Gtk::TreeModel::ColumnRecord { - public: - ModelColumns() { - add(_col_name); - add(_col_type); - add(_col_project); - add(_col_author); - add(_col_uri); - add(_col_plugin); - } - - Gtk::TreeModelColumn _col_name; - Gtk::TreeModelColumn _col_type; - Gtk::TreeModelColumn _col_project; - Gtk::TreeModelColumn _col_author; - Gtk::TreeModelColumn _col_uri; - - // Not displayed: - Gtk::TreeModelColumn< SPtr > _col_plugin; - }; - - /** Column for the filter criteria combo box. */ - class CriteriaColumns : public Gtk::TreeModel::ColumnRecord { - public: - enum class Criteria { NAME, TYPE, PROJECT, AUTHOR, URI, }; - - CriteriaColumns() { - add(_col_label); - add(_col_criteria); - } - - Gtk::TreeModelColumn _col_label; - Gtk::TreeModelColumn _col_criteria; - }; - - void add_clicked(); - void filter_changed(); - void clear_clicked(); - void name_changed(); - void name_cleared(Gtk::EntryIconPosition pos, const GdkEventButton* event); - - void set_row(Gtk::TreeModel::Row& row, - SPtr plugin); - - void new_plugin(SPtr pm); - - void plugin_property_changed(const URI& plugin, - const URI& predicate, - const Atom& value); - - void plugin_activated(const Gtk::TreeModel::Path& path, Gtk::TreeViewColumn* col); - void plugin_selection_changed(); - - std::string generate_module_name(SPtr plugin, - int offset=0); - - void load_plugin(const Gtk::TreeModel::iterator& iter); - - Properties _initial_data; - - SPtr _graph; - - typedef std::map Rows; - Rows _rows; - - Glib::RefPtr _plugins_liststore; - ModelColumns _plugins_columns; - - Glib::RefPtr _criteria_liststore; - CriteriaColumns _criteria_columns; - - Glib::RefPtr _selection; - - int _name_offset; // see comments for generate_plugin_name - - bool _has_shown; - bool _refresh_list; - Gtk::TreeView* _plugins_treeview; - Gtk::CheckButton* _polyphonic_checkbutton; - Gtk::Entry* _name_entry; - Gtk::Button* _close_button; - Gtk::Button* _add_button; - Gtk::ComboBox* _filter_combo; - Gtk::Entry* _search_entry; -}; - -} // namespace GUI -} // namespace Ingen - -#endif // INGEN_GUI_LOADPLUGINWINDOW_HPP diff --git a/src/gui/MessagesWindow.cpp b/src/gui/MessagesWindow.cpp deleted file mode 100644 index 581e732c..00000000 --- a/src/gui/MessagesWindow.cpp +++ /dev/null @@ -1,141 +0,0 @@ -/* - This file is part of Ingen. - Copyright 2007-2016 David Robillard - - 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 - Software Foundation, either version 3 of the License, or 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 Affero General Public License for details. - - You should have received a copy of the GNU Affero General Public License - along with Ingen. If not, see . -*/ - -#include - -#include "ingen/URIs.hpp" - -#include "App.hpp" -#include "MessagesWindow.hpp" - -namespace Ingen { -namespace GUI { -using std::string; - -MessagesWindow::MessagesWindow(BaseObjectType* cobject, - const Glib::RefPtr& xml) - : Window(cobject) -{ - xml->get_widget("messages_textview", _textview); - xml->get_widget("messages_clear_button", _clear_button); - xml->get_widget("messages_close_button", _close_button); - - _clear_button->signal_clicked().connect(sigc::mem_fun(this, &MessagesWindow::clear_clicked)); - _close_button->signal_clicked().connect(sigc::mem_fun(this, &Window::hide)); - - for (int s = Gtk::STATE_NORMAL; s <= Gtk::STATE_INSENSITIVE; ++s) { - _textview->modify_base((Gtk::StateType)s, Gdk::Color("#000000")); - _textview->modify_text((Gtk::StateType)s, Gdk::Color("#EEEEEC")); - } -} - -void -MessagesWindow::init_window(App& app) -{ - Glib::RefPtr tag = Gtk::TextTag::create(); - tag->property_foreground() = "#EF2929"; - _tags.emplace(app.uris().log_Error, tag); - _error_tag = tag; - - tag = Gtk::TextTag::create(); - tag->property_foreground() = "#FCAF3E"; - _tags.emplace(app.uris().log_Warning, tag); - - tag = Gtk::TextTag::create(); - tag->property_foreground() = "#8AE234"; - _tags.emplace(app.uris().log_Trace, tag); - - for (const auto& t : _tags) { - _textview->get_buffer()->get_tag_table()->add(t.second); - } -} - -void -MessagesWindow::post_error(const string& msg) -{ - Glib::RefPtr text_buf = _textview->get_buffer(); - text_buf->insert_with_tag(text_buf->end(), msg, _error_tag); - text_buf->insert(text_buf->end(), "\n"); - - if (!_clear_button->is_sensitive()) { - _clear_button->set_sensitive(true); - } - - set_urgency_hint(true); - if (!is_visible()) { - present(); - } -} - -int -MessagesWindow::log(LV2_URID type, const char* fmt, va_list args) -{ - std::lock_guard lock(_mutex); - -#ifdef HAVE_VASPRINTF - char* buf = nullptr; - const int len = vasprintf(&buf, fmt, args); -#else - char* buf = g_strdup_vprintf(fmt, args); - const int len = strlen(buf); -#endif - - _stream << type << ' ' << buf << '\0'; - free(buf); - - return len; -} - -void -MessagesWindow::flush() -{ - while (true) { - LV2_URID type; - std::string line; - { - std::lock_guard lock(_mutex); - if (!_stream.rdbuf()->in_avail()) { - return; - } - _stream >> type; - std::getline(_stream, line, '\0'); - } - - Glib::RefPtr text_buf = _textview->get_buffer(); - - auto t = _tags.find(type); - if (t != _tags.end()) { - text_buf->insert_with_tag(text_buf->end(), line, t->second); - } else { - text_buf->insert(text_buf->end(), line); - } - } - - if (!_clear_button->is_sensitive()) { - _clear_button->set_sensitive(true); - } -} - -void -MessagesWindow::clear_clicked() -{ - Glib::RefPtr text_buf = _textview->get_buffer(); - text_buf->erase(text_buf->begin(), text_buf->end()); - _clear_button->set_sensitive(false); -} - -} // namespace GUI -} // namespace Ingen diff --git a/src/gui/MessagesWindow.hpp b/src/gui/MessagesWindow.hpp deleted file mode 100644 index fa9eae1d..00000000 --- a/src/gui/MessagesWindow.hpp +++ /dev/null @@ -1,70 +0,0 @@ -/* - This file is part of Ingen. - Copyright 2007-2016 David Robillard - - 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 - Software Foundation, either version 3 of the License, or 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 Affero General Public License for details. - - You should have received a copy of the GNU Affero General Public License - along with Ingen. If not, see . -*/ - -#ifndef INGEN_GUI_MESSAGESWINDOW_HPP -#define INGEN_GUI_MESSAGESWINDOW_HPP - -#include -#include -#include - -#include -#include -#include -#include "lv2/lv2plug.in/ns/ext/log/log.h" - -#include "Window.hpp" - -namespace Ingen { -namespace GUI { - -/** Messages Window. - * - * Loaded from XML as a derived object. - * This is shown when errors occur (e.g. during graph loading). - * - * \ingroup GUI - */ -class MessagesWindow : public Window -{ -public: - MessagesWindow(BaseObjectType* cobject, - const Glib::RefPtr& xml); - - void init_window(App& app); - - int log(LV2_URID type, const char* fmt, va_list args); - void flush(); - - void post_error(const std::string& msg); - -private: - void clear_clicked(); - - std::mutex _mutex; - std::stringstream _stream; - Gtk::TextView* _textview; - Gtk::Button* _clear_button; - Gtk::Button* _close_button; - - Glib::RefPtr _error_tag; - std::map< LV2_URID, Glib::RefPtr > _tags; -}; - -} // namespace GUI -} // namespace Ingen - -#endif // INGEN_GUI_MESSAGESWINDOW_HPP diff --git a/src/gui/NewSubgraphWindow.cpp b/src/gui/NewSubgraphWindow.cpp deleted file mode 100644 index f9dc8fc4..00000000 --- a/src/gui/NewSubgraphWindow.cpp +++ /dev/null @@ -1,119 +0,0 @@ -/* - This file is part of Ingen. - Copyright 2007-2015 David Robillard - - 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 - Software Foundation, either version 3 of the License, or 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 Affero General Public License for details. - - You should have received a copy of the GNU Affero General Public License - along with Ingen. If not, see . -*/ - -#include - -#include "ingen/Interface.hpp" -#include "ingen/client/ClientStore.hpp" -#include "ingen/client/GraphModel.hpp" - -#include "App.hpp" -#include "NewSubgraphWindow.hpp" -#include "GraphView.hpp" - -namespace Ingen { -namespace GUI { - -NewSubgraphWindow::NewSubgraphWindow(BaseObjectType* cobject, - const Glib::RefPtr& xml) - : Window(cobject) -{ - xml->get_widget("new_subgraph_name_entry", _name_entry); - xml->get_widget("new_subgraph_message_label", _message_label); - xml->get_widget("new_subgraph_polyphony_spinbutton", _poly_spinbutton); - xml->get_widget("new_subgraph_ok_button", _ok_button); - xml->get_widget("new_subgraph_cancel_button", _cancel_button); - - _name_entry->signal_changed().connect(sigc::mem_fun(this, &NewSubgraphWindow::name_changed)); - _ok_button->signal_clicked().connect(sigc::mem_fun(this, &NewSubgraphWindow::ok_clicked)); - _cancel_button->signal_clicked().connect(sigc::mem_fun(this, &NewSubgraphWindow::cancel_clicked)); - - _ok_button->property_sensitive() = false; - - _poly_spinbutton->get_adjustment()->configure(1.0, 1.0, 128, 1.0, 10.0, 0); -} - -void -NewSubgraphWindow::present(SPtr graph, - Properties data) -{ - set_graph(graph); - _initial_data = data; - Gtk::Window::present(); -} - -/** Sets the graph controller for this window and initializes everything. - * - * This function MUST be called before using the window in any way! - */ -void -NewSubgraphWindow::set_graph(SPtr graph) -{ - _graph = graph; -} - -/** Called every time the user types into the name input box. - * Used to display warning messages, and enable/disable the OK button. - */ -void -NewSubgraphWindow::name_changed() -{ - std::string name = _name_entry->get_text(); - if (!Raul::Symbol::is_valid(name)) { - _message_label->set_text("Name contains invalid characters."); - _ok_button->property_sensitive() = false; - } else if (_app->store()->find(_graph->path().child(Raul::Symbol(name))) - != _app->store()->end()) { - _message_label->set_text("An object already exists with that name."); - _ok_button->property_sensitive() = false; - } else { - _message_label->set_text(""); - _ok_button->property_sensitive() = true; - } -} - -void -NewSubgraphWindow::ok_clicked() -{ - const uint32_t poly = _poly_spinbutton->get_value_as_int(); - const Raul::Path path = _graph->path().child( - Raul::Symbol::symbolify(_name_entry->get_text())); - - // Create graph - Properties props; - props.emplace(_app->uris().rdf_type, Property(_app->uris().ingen_Graph)); - props.emplace(_app->uris().ingen_polyphony, _app->forge().make(int32_t(poly))); - props.emplace(_app->uris().ingen_enabled, _app->forge().make(bool(true))); - _app->interface()->put( - path_to_uri(path), props, Resource::Graph::INTERNAL); - - // Set external (block perspective) properties - props = _initial_data; - props.emplace(_app->uris().rdf_type, Property(_app->uris().ingen_Graph)); - _app->interface()->put( - path_to_uri(path), _initial_data, Resource::Graph::EXTERNAL); - - hide(); -} - -void -NewSubgraphWindow::cancel_clicked() -{ - hide(); -} - -} // namespace GUI -} // namespace Ingen diff --git a/src/gui/NewSubgraphWindow.hpp b/src/gui/NewSubgraphWindow.hpp deleted file mode 100644 index 395856ba..00000000 --- a/src/gui/NewSubgraphWindow.hpp +++ /dev/null @@ -1,72 +0,0 @@ -/* - This file is part of Ingen. - Copyright 2007-2015 David Robillard - - 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 - Software Foundation, either version 3 of the License, or 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 Affero General Public License for details. - - You should have received a copy of the GNU Affero General Public License - along with Ingen. If not, see . -*/ - -#ifndef INGEN_GUI_NEWSUBGRAPHWINDOW_HPP -#define INGEN_GUI_NEWSUBGRAPHWINDOW_HPP - -#include -#include -#include -#include -#include - -#include "ingen/Node.hpp" -#include "ingen/types.hpp" - -#include "Window.hpp" - -namespace Ingen { - -namespace Client { class GraphModel; } - -namespace GUI { - -/** 'New Subgraph' window. - * - * Loaded from XML as a derived object. - * - * \ingroup GUI - */ -class NewSubgraphWindow : public Window -{ -public: - NewSubgraphWindow(BaseObjectType* cobject, - const Glib::RefPtr& xml); - - void set_graph(SPtr graph); - - void present(SPtr graph, - Properties data); - -private: - void name_changed(); - void ok_clicked(); - void cancel_clicked(); - - Properties _initial_data; - SPtr _graph; - - Gtk::Entry* _name_entry; - Gtk::Label* _message_label; - Gtk::SpinButton* _poly_spinbutton; - Gtk::Button* _ok_button; - Gtk::Button* _cancel_button; -}; - -} // namespace GUI -} // namespace Ingen - -#endif // INGEN_GUI_NEWSUBGRAPHWINDOW_HPP diff --git a/src/gui/NodeMenu.cpp b/src/gui/NodeMenu.cpp deleted file mode 100644 index 1b1b1677..00000000 --- a/src/gui/NodeMenu.cpp +++ /dev/null @@ -1,253 +0,0 @@ -/* - This file is part of Ingen. - Copyright 2007-2015 David Robillard - - 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 - Software Foundation, either version 3 of the License, or 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 Affero General Public License for details. - - You should have received a copy of the GNU Affero General Public License - along with Ingen. If not, see . -*/ - -#include - -#include -#include -#include -#include - -#include "ingen/Interface.hpp" -#include "ingen/Log.hpp" -#include "ingen/URIMap.hpp" -#include "ingen/client/BlockModel.hpp" -#include "ingen/client/PluginModel.hpp" -#include "lv2/lv2plug.in/ns/ext/presets/presets.h" - -#include "App.hpp" -#include "NodeMenu.hpp" -#include "WidgetFactory.hpp" -#include "WindowFactory.hpp" - -namespace Ingen { - -using namespace Client; - -namespace GUI { - -NodeMenu::NodeMenu(BaseObjectType* cobject, - const Glib::RefPtr& xml) - : ObjectMenu(cobject, xml) - , _presets_menu(nullptr) -{ - xml->get_widget("node_popup_gui_menuitem", _popup_gui_menuitem); - xml->get_widget("node_embed_gui_menuitem", _embed_gui_menuitem); - xml->get_widget("node_enabled_menuitem", _enabled_menuitem); - xml->get_widget("node_randomize_menuitem", _randomize_menuitem); -} - -void -NodeMenu::init(App& app, SPtr block) -{ - ObjectMenu::init(app, block); - - _learn_menuitem->signal_activate().connect( - sigc::mem_fun(this, &NodeMenu::on_menu_learn)); - _popup_gui_menuitem->signal_activate().connect( - sigc::mem_fun(signal_popup_gui, &sigc::signal::emit)); - _embed_gui_menuitem->signal_toggled().connect( - sigc::mem_fun(this, &NodeMenu::on_menu_embed_gui)); - _enabled_menuitem->signal_toggled().connect( - sigc::mem_fun(this, &NodeMenu::on_menu_enabled)); - _randomize_menuitem->signal_activate().connect( - sigc::mem_fun(this, &NodeMenu::on_menu_randomize)); - - SPtr plugin = block->plugin_model(); - if (plugin) { - // Get the plugin to receive related presets - _preset_connection = plugin->signal_preset().connect( - sigc::mem_fun(this, &NodeMenu::add_preset)); - - if (!plugin->fetched()) { - _app->interface()->get(plugin->uri()); - plugin->set_fetched(true); - } - } - - if (plugin && plugin->has_ui()) { - _popup_gui_menuitem->show(); - _embed_gui_menuitem->show(); - const Atom& ui_embedded = block->get_property( - _app->uris().ingen_uiEmbedded); - _embed_gui_menuitem->set_active( - ui_embedded.is_valid() && ui_embedded.get()); - } else { - _popup_gui_menuitem->hide(); - _embed_gui_menuitem->hide(); - } - - const Atom& enabled = block->get_property(_app->uris().ingen_enabled); - _enabled_menuitem->set_active(!enabled.is_valid() || enabled.get()); - - if (plugin && _app->uris().lv2_Plugin == plugin->type()) { - _presets_menu = Gtk::manage(new Gtk::Menu()); - _presets_menu->items().push_back( - Gtk::Menu_Helpers::MenuElem( - "_Save Preset...", - sigc::mem_fun(this, &NodeMenu::on_save_preset_activated))); - _presets_menu->items().push_back(Gtk::Menu_Helpers::SeparatorElem()); - - for (const auto& p : plugin->presets()) { - add_preset(p.first, p.second); - } - - items().push_front( - Gtk::Menu_Helpers::ImageMenuElem( - "_Presets", - *(manage(new Gtk::Image(Gtk::Stock::INDEX, Gtk::ICON_SIZE_MENU))))); - - Gtk::MenuItem* presets_menu_item = &(items().front()); - presets_menu_item->set_submenu(*_presets_menu); - } - - if (has_control_inputs()) { - _randomize_menuitem->show(); - } else { - _randomize_menuitem->hide(); - } - - if (plugin && (plugin->uri() == "http://drobilla.net/ns/ingen-internals#Controller" - || plugin->uri() == "http://drobilla.net/ns/ingen-internals#Trigger")) { - _learn_menuitem->show(); - } else { - _learn_menuitem->hide(); - } - - if (!_popup_gui_menuitem->is_visible() && - !_embed_gui_menuitem->is_visible() && - !_randomize_menuitem->is_visible()) { - _separator_menuitem->hide(); - } - - _enable_signal = true; -} - -void -NodeMenu::add_preset(const URI& uri, const std::string& label) -{ - if (_presets_menu) { - _presets_menu->items().push_back( - Gtk::Menu_Helpers::MenuElem( - label, - sigc::bind(sigc::mem_fun(this, &NodeMenu::on_preset_activated), - uri))); - } -} - -void -NodeMenu::on_menu_embed_gui() -{ - signal_embed_gui.emit(_embed_gui_menuitem->get_active()); -} - -void -NodeMenu::on_menu_enabled() -{ - _app->set_property(_object->uri(), - _app->uris().ingen_enabled, - _app->forge().make(bool(_enabled_menuitem->get_active()))); -} - -void -NodeMenu::on_menu_randomize() -{ - _app->interface()->bundle_begin(); - - const SPtr bm = block(); - for (const auto& p : bm->ports()) { - if (p->is_input() && _app->can_control(p.get())) { - float min = 0.0f, max = 1.0f; - bm->port_value_range(p, min, max, _app->sample_rate()); - const float val = g_random_double_range(0.0, 1.0) * (max - min) + min; - _app->set_property(p->uri(), - _app->uris().ingen_value, - _app->forge().make(val)); - } - } - - _app->interface()->bundle_end(); -} - -void -NodeMenu::on_menu_disconnect() -{ - _app->interface()->disconnect_all(_object->parent()->path(), _object->path()); -} - -void -NodeMenu::on_save_preset_activated() -{ - Gtk::FileChooserDialog dialog("Save Preset", Gtk::FILE_CHOOSER_ACTION_SAVE); - dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL); - dialog.add_button(Gtk::Stock::SAVE, Gtk::RESPONSE_OK); - dialog.set_default_response(Gtk::RESPONSE_OK); - dialog.set_current_folder(Glib::build_filename(Glib::get_home_dir(), ".lv2")); - - Gtk::HBox* extra = Gtk::manage(new Gtk::HBox()); - Gtk::Label* label = Gtk::manage(new Gtk::Label("URI (Optional): ")); - Gtk::Entry* entry = Gtk::manage(new Gtk::Entry()); - extra->pack_start(*label, false, true, 4); - extra->pack_start(*entry, true, true, 4); - extra->show_all(); - dialog.set_extra_widget(*Gtk::manage(extra)); - - if (dialog.run() == Gtk::RESPONSE_OK) { - const std::string user_uri = dialog.get_uri(); - const std::string user_path = Glib::filename_from_uri(user_uri); - const std::string dirname = Glib::path_get_dirname(user_path); - const std::string basename = Glib::path_get_basename(user_path); - const std::string sym = Raul::Symbol::symbolify(basename); - const std::string plugname = block()->plugin_model()->human_name(); - const std::string prefix = Raul::Symbol::symbolify(plugname); - const std::string bundle = prefix + "_" + sym + ".preset.lv2/"; - const std::string file = sym + ".ttl"; - const std::string real_path = Glib::build_filename(dirname, bundle, file); - const std::string real_uri = Glib::filename_to_uri(real_path); - - Properties props{ - { _app->uris().rdf_type, - _app->uris().pset_Preset }, - { _app->uris().rdfs_label, - _app->forge().alloc(basename) }, - { _app->uris().lv2_prototype, - _app->forge().make_urid(block()->uri()) }}; - _app->interface()->put(URI(real_uri), props); - } -} - -void -NodeMenu::on_preset_activated(const std::string& uri) -{ - _app->set_property(block()->uri(), - _app->uris().pset_preset, - _app->forge().make_urid(URI(uri))); -} - -bool -NodeMenu::has_control_inputs() -{ - for (const auto& p : block()->ports()) { - if (p->is_input() && p->is_numeric()) { - return true; - } - } - - return false; -} - -} // namespace GUI -} // namespace Ingen diff --git a/src/gui/NodeMenu.hpp b/src/gui/NodeMenu.hpp deleted file mode 100644 index 5d9f1e6d..00000000 --- a/src/gui/NodeMenu.hpp +++ /dev/null @@ -1,75 +0,0 @@ -/* - This file is part of Ingen. - Copyright 2007-2015 David Robillard - - 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 - Software Foundation, either version 3 of the License, or 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 Affero General Public License for details. - - You should have received a copy of the GNU Affero General Public License - along with Ingen. If not, see . -*/ - -#ifndef INGEN_GUI_NODEMENU_HPP -#define INGEN_GUI_NODEMENU_HPP - -#include - -#include -#include -#include - -#include "ObjectMenu.hpp" -#include "ingen/client/BlockModel.hpp" -#include "ingen/types.hpp" - -namespace Ingen { -namespace GUI { - -/** Menu for a Node. - * - * \ingroup GUI - */ -class NodeMenu : public ObjectMenu -{ -public: - NodeMenu(BaseObjectType* cobject, - const Glib::RefPtr& xml); - - void init(App& app, SPtr block); - - bool has_control_inputs(); - - sigc::signal signal_popup_gui; - sigc::signal signal_embed_gui; - -protected: - SPtr block() const { - return dynamic_ptr_cast(_object); - } - - void add_preset(const URI& uri, const std::string& label); - - void on_menu_disconnect(); - void on_menu_embed_gui(); - void on_menu_enabled(); - void on_menu_randomize(); - void on_save_preset_activated(); - void on_preset_activated(const std::string& uri); - - Gtk::MenuItem* _popup_gui_menuitem; - Gtk::CheckMenuItem* _embed_gui_menuitem; - Gtk::CheckMenuItem* _enabled_menuitem; - Gtk::MenuItem* _randomize_menuitem; - Gtk::Menu* _presets_menu; - sigc::connection _preset_connection; -}; - -} // namespace GUI -} // namespace Ingen - -#endif // INGEN_GUI_NODEMENU_HPP diff --git a/src/gui/NodeModule.cpp b/src/gui/NodeModule.cpp deleted file mode 100644 index dadffff0..00000000 --- a/src/gui/NodeModule.cpp +++ /dev/null @@ -1,518 +0,0 @@ -/* - This file is part of Ingen. - Copyright 2007-2016 David Robillard - - 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 - Software Foundation, either version 3 of the License, or 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 Affero General Public License for details. - - You should have received a copy of the GNU Affero General Public License - along with Ingen. If not, see . -*/ - -#include -#include - -#include - -#include "lv2/lv2plug.in/ns/ext/atom/util.h" - -#include "ingen/Atom.hpp" -#include "ingen/Configuration.hpp" -#include "ingen/Interface.hpp" -#include "ingen/Log.hpp" -#include "ingen/client/BlockModel.hpp" -#include "ingen/client/GraphModel.hpp" -#include "ingen/client/PluginModel.hpp" -#include "ingen/client/PluginUI.hpp" - -#include "App.hpp" -#include "GraphCanvas.hpp" -#include "GraphWindow.hpp" -#include "NodeMenu.hpp" -#include "NodeModule.hpp" -#include "Port.hpp" -#include "RenameWindow.hpp" -#include "Style.hpp" -#include "SubgraphModule.hpp" -#include "WidgetFactory.hpp" -#include "WindowFactory.hpp" -#include "ingen_config.h" - -namespace Ingen { - -using namespace Client; - -namespace GUI { - -NodeModule::NodeModule(GraphCanvas& canvas, - SPtr block) - : Ganv::Module(canvas, block->path().symbol(), 0, 0, true) - , _block(block) - , _gui_widget(nullptr) - , _gui_window(nullptr) - , _initialised(false) -{ - block->signal_new_port().connect( - sigc::mem_fun(this, &NodeModule::new_port_view)); - block->signal_removed_port().connect( - sigc::hide_return(sigc::mem_fun(this, &NodeModule::delete_port_view))); - block->signal_property().connect( - sigc::mem_fun(this, &NodeModule::property_changed)); - block->signal_moved().connect( - sigc::mem_fun(this, &NodeModule::rename)); - - signal_event().connect( - sigc::mem_fun(this, &NodeModule::on_event)); - - signal_moved().connect( - sigc::mem_fun(this, &NodeModule::store_location)); - - signal_selected().connect( - sigc::mem_fun(this, &NodeModule::on_selected)); - - const PluginModel* plugin = dynamic_cast(block->plugin()); - if (plugin) { - plugin->signal_changed().connect( - sigc::mem_fun(this, &NodeModule::plugin_changed)); - } - - for (const auto& p : block->properties()) { - property_changed(p.first, p.second); - } - - if (_block->has_property(app().uris().ingen_uiEmbedded, - app().uris().forge.make(true))) { - // Schedule idle callback to embed GUI once ports arrive - Glib::signal_timeout().connect( - sigc::mem_fun(*this, &NodeModule::idle_init), 25, G_PRIORITY_DEFAULT_IDLE); - } else { - _initialised = true; - } -} - -NodeModule::~NodeModule() -{ - delete _gui_widget; - delete _gui_window; -} - -bool -NodeModule::idle_init() -{ - if (_block->ports().size() == 0) { - return true; // Need to embed GUI, but ports haven't shown up yet - } - - // Ports have arrived, embed GUI and deregister this callback - embed_gui(true); - _initialised = true; - return false; -} - -bool -NodeModule::show_menu(GdkEventButton* ev) -{ - WidgetFactory::get_widget_derived("object_menu", _menu); - if (!_menu) { - app().log().error("Failed to load object menu widget\n"); - return false; - } - - _menu->init(app(), _block); - _menu->signal_embed_gui.connect( - sigc::mem_fun(this, &NodeModule::on_embed_gui_toggled)); - _menu->signal_popup_gui.connect( - sigc::hide_return(sigc::mem_fun(this, &NodeModule::popup_gui))); - _menu->popup(ev->button, ev->time); - return true; -} - -NodeModule* -NodeModule::create(GraphCanvas& canvas, - SPtr block, - bool human) -{ - SPtr graph = dynamic_ptr_cast(block); - - NodeModule* ret = (graph) - ? new SubgraphModule(canvas, graph) - : new NodeModule(canvas, block); - - for (const auto& p : block->properties()) { - ret->property_changed(p.first, p.second); - } - - for (const auto& p : block->ports()) { - ret->new_port_view(p); - } - - ret->set_stacked(block->polyphonic()); - - if (human) { - ret->show_human_names(human); // FIXME: double port iteration - } - - return ret; -} - -App& -NodeModule::app() const -{ - return ((GraphCanvas*)canvas())->app(); -} - -void -NodeModule::show_human_names(bool b) -{ - const URIs& uris = app().uris(); - - if (b) { - set_label(block()->label().c_str()); - } else { - set_label(block()->symbol().c_str()); - } - - for (iterator i = begin(); i != end(); ++i) { - Ingen::GUI::Port* const port = dynamic_cast(*i); - Glib::ustring label(port->model()->symbol().c_str()); - if (b) { - const Atom& name_property = port->model()->get_property(uris.lv2_name); - if (name_property.type() == uris.forge.String) { - label = name_property.ptr(); - } else { - Glib::ustring hn = block()->plugin_model()->port_human_name( - port->model()->index()); - if (!hn.empty()) { - label = hn; - } - } - } - (*i)->set_label(label.c_str()); - } -} - -void -NodeModule::port_activity(uint32_t index, const Atom& value) -{ - const URIs& uris = app().uris(); - if (!_plugin_ui) { - return; - } - - if (_block->get_port(index)->is_a(uris.atom_AtomPort)) { - _plugin_ui->port_event(index, - lv2_atom_total_size(value.atom()), - uris.atom_eventTransfer, - value.atom()); - } -} - -void -NodeModule::port_value_changed(uint32_t index, const Atom& value) -{ - const URIs& uris = app().uris(); - if (!_plugin_ui) { - return; - } - - if (value.type() == uris.atom_Float && - _block->get_port(index)->is_numeric()) { - _plugin_ui->port_event(index, sizeof(float), 0, value.ptr()); - } else { - _plugin_ui->port_event(index, - lv2_atom_total_size(value.atom()), - uris.atom_eventTransfer, - value.atom()); - } -} - -void -NodeModule::plugin_changed() -{ - for (iterator p = begin(); p != end(); ++p) { - dynamic_cast(*p)->update_metadata(); - } -} - -void -NodeModule::on_embed_gui_toggled(bool embed) -{ - embed_gui(embed); - app().set_property(_block->uri(), - app().uris().ingen_uiEmbedded, - app().forge().make(embed)); -} - -void -NodeModule::embed_gui(bool embed) -{ - if (embed) { - if (_gui_window) { - app().log().warn("LV2 GUI already popped up, cannot embed\n"); - return; - } - - if (!_plugin_ui) { - _plugin_ui = _block->plugin_model()->ui(app().world(), _block); - } - - if (_plugin_ui) { - _plugin_ui->signal_property_changed().connect( - sigc::mem_fun(app(), &App::set_property)); - - if (!_plugin_ui->instantiate()) { - app().log().error("Failed to instantiate LV2 UI\n"); - } else { - GtkWidget* c_widget = (GtkWidget*)_plugin_ui->get_widget(); - _gui_widget = Glib::wrap(c_widget); - - Gtk::Container* container = new Gtk::EventBox(); - container->set_name("IngenEmbeddedUI"); - container->set_border_width(4.0); - container->add(*_gui_widget); - Ganv::Module::embed(container); - } - } else { - app().log().error("Failed to create LV2 UI\n"); - } - - if (_gui_widget) { - _gui_widget->show_all(); - set_control_values(); - } - - } else { // un-embed - Ganv::Module::embed(nullptr); - _plugin_ui.reset(); - } -} - -void -NodeModule::rename() -{ - if (app().world()->conf().option("port-labels").get() && - !app().world()->conf().option("human-names").get()) { - set_label(_block->path().symbol()); - } -} - -void -NodeModule::new_port_view(SPtr port) -{ - Port::create(app(), *this, port); - - port->signal_value_changed().connect( - sigc::bind<0>(sigc::mem_fun(this, &NodeModule::port_value_changed), - port->index())); - - port->signal_activity().connect( - sigc::bind<0>(sigc::mem_fun(this, &NodeModule::port_activity), - port->index())); -} - -Port* -NodeModule::port(SPtr model) -{ - for (iterator p = begin(); p != end(); ++p) { - Port* const port = dynamic_cast(*p); - if (port->model() == model) { - return port; - } - } - return nullptr; -} - -void -NodeModule::delete_port_view(SPtr model) -{ - Port* p = port(model); - if (p) { - delete p; - } else { - app().log().warn(fmt("Failed to find port %1% on module %2%\n") - % model->path() % _block->path()); - } -} - -bool -NodeModule::popup_gui() -{ - if (_block->plugin() && app().uris().lv2_Plugin == _block->plugin_model()->type()) { - if (_plugin_ui) { - app().log().warn("LV2 GUI already embedded, cannot pop up\n"); - return false; - } - - const PluginModel* const plugin = dynamic_cast(_block->plugin()); - assert(plugin); - - _plugin_ui = plugin->ui(app().world(), _block); - - if (_plugin_ui) { - _plugin_ui->signal_property_changed().connect( - sigc::mem_fun(app(), &App::set_property)); - - if (!_plugin_ui->instantiated() && !_plugin_ui->instantiate()) { - app().log().error("Failed to instantiate LV2 UI\n"); - return false; - } - - GtkWidget* c_widget = (GtkWidget*)_plugin_ui->get_widget(); - _gui_widget = Glib::wrap(c_widget); - - _gui_window = new Gtk::Window(); - if (!_plugin_ui->is_resizable()) { - _gui_window->set_resizable(false); - } - _gui_window->set_title(_block->path() + " UI - Ingen"); - _gui_window->set_role("plugin_ui"); - _gui_window->add(*_gui_widget); - _gui_widget->show_all(); - set_control_values(); - - _gui_window->signal_unmap().connect( - sigc::mem_fun(this, &NodeModule::on_gui_window_close)); - _gui_window->present(); - - return true; - } else { - app().log().warn(fmt("No LV2 GUI for %1%\n") % _block->path()); - } - } - - return false; -} - -void -NodeModule::on_gui_window_close() -{ - delete _gui_window; - _gui_window = nullptr; - _plugin_ui.reset(); - _gui_widget = nullptr; -} - -void -NodeModule::set_control_values() -{ - uint32_t index = 0; - for (const auto& p : _block->ports()) { - if (app().can_control(p.get()) && p->value().is_valid()) { - port_value_changed(index, p->value()); - } - ++index; - } -} - -bool -NodeModule::on_double_click(GdkEventButton* event) -{ - popup_gui(); - return true; -} - -bool -NodeModule::on_event(GdkEvent* ev) -{ - if (ev->type == GDK_BUTTON_PRESS && ev->button.button == 3) { - return show_menu(&ev->button); - } else if (ev->type == GDK_2BUTTON_PRESS) { - return on_double_click(&ev->button); - } else if (ev->type == GDK_ENTER_NOTIFY) { - GraphBox* const box = app().window_factory()->graph_box( - dynamic_ptr_cast(_block->parent())); - if (box) { - box->object_entered(_block.get()); - } - } else if (ev->type == GDK_LEAVE_NOTIFY) { - GraphBox* const box = app().window_factory()->graph_box( - dynamic_ptr_cast(_block->parent())); - if (box) { - box->object_left(_block.get()); - } - } - - return false; -} - -void -NodeModule::store_location(double ax, double ay) -{ - const URIs& uris = app().uris(); - - const Atom x(app().forge().make(static_cast(ax))); - const Atom y(app().forge().make(static_cast(ay))); - - if (x != _block->get_property(uris.ingen_canvasX) || - y != _block->get_property(uris.ingen_canvasY)) - { - app().interface()->put(_block->uri(), {{uris.ingen_canvasX, x}, - {uris.ingen_canvasY, y}}); - } -} - -void -NodeModule::property_changed(const URI& key, const Atom& value) -{ - const URIs& uris = app().uris(); - if (value.type() == uris.forge.Float) { - if (key == uris.ingen_canvasX) { - move_to(value.get(), get_y()); - } else if (key == uris.ingen_canvasY) { - move_to(get_x(), value.get()); - } - } else if (value.type() == uris.forge.Bool) { - if (key == uris.ingen_polyphonic) { - set_stacked(value.get()); - } else if (key == uris.ingen_uiEmbedded && _initialised) { - if (value.get() && !_gui_widget) { - embed_gui(true); - } else if (!value.get() && _gui_widget) { - embed_gui(false); - } - } else if (key == uris.ingen_enabled) { - if (value.get()) { - set_dash_length(0.0); - } else { - set_dash_length(5.0); - } - } - } else if (value.type() == uris.forge.String) { - if (key == uris.lv2_name - && app().world()->conf().option("human-names").get()) { - set_label(value.ptr()); - } - } -} - -bool -NodeModule::on_selected(gboolean selected) -{ - GraphWindow* win = app().window_factory()->parent_graph_window(block()); - if (!win) { - return true; - } - - if (selected && win->documentation_is_visible()) { - GraphWindow* win = app().window_factory()->parent_graph_window(block()); - std::string doc; - bool html = false; -#ifdef HAVE_WEBKIT - html = true; -#endif - if (block()->plugin_model()) { - doc = block()->plugin_model()->documentation(html); - } - win->set_documentation(doc, html); - } - - return true; -} - -} // namespace GUI -} // namespace Ingen diff --git a/src/gui/NodeModule.hpp b/src/gui/NodeModule.hpp deleted file mode 100644 index 863b6ffb..00000000 --- a/src/gui/NodeModule.hpp +++ /dev/null @@ -1,104 +0,0 @@ -/* - This file is part of Ingen. - Copyright 2007-2015 David Robillard - - 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 - Software Foundation, either version 3 of the License, or 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 Affero General Public License for details. - - You should have received a copy of the GNU Affero General Public License - along with Ingen. If not, see . -*/ - -#ifndef INGEN_GUI_NODEMODULE_HPP -#define INGEN_GUI_NODEMODULE_HPP - -#include "ganv/Module.hpp" -#include "ingen/types.hpp" - -#include "Port.hpp" - -namespace Raul { class Atom; } - -namespace Ingen { namespace Client { -class BlockModel; -class PluginUI; -class PortModel; -} } - -namespace Ingen { -namespace GUI { - -class GraphCanvas; -class Port; -class NodeMenu; - -/** A module in a graphn. - * - * This base class is extended for various types of modules. - * - * \ingroup GUI - */ -class NodeModule : public Ganv::Module -{ -public: - static NodeModule* create( - GraphCanvas& canvas, - SPtr block, - bool human); - - virtual ~NodeModule(); - - App& app() const; - - Port* port(SPtr model); - - void delete_port_view(SPtr model); - - virtual void store_location(double ax, double ay); - void show_human_names(bool b); - - SPtr block() const { return _block; } - -protected: - NodeModule(GraphCanvas& canvas, SPtr block); - - virtual bool on_double_click(GdkEventButton* ev); - - bool idle_init(); - bool on_event(GdkEvent* ev); - - void on_embed_gui_toggled(bool embed); - void embed_gui(bool embed); - bool popup_gui(); - void on_gui_window_close(); - bool on_selected(gboolean selected); - - void rename(); - void property_changed(const URI& key, const Atom& value); - - void new_port_view(SPtr port); - - void port_activity(uint32_t index, const Atom& value); - void port_value_changed(uint32_t index, const Atom& value); - void plugin_changed(); - void set_control_values(); - - bool show_menu(GdkEventButton* ev); - - SPtr _block; - NodeMenu* _menu; - SPtr _plugin_ui; - Gtk::Widget* _gui_widget; - Gtk::Window* _gui_window; ///< iff popped up - bool _initialised; -}; - -} // namespace GUI -} // namespace Ingen - -#endif // INGEN_GUI_NODEMODULE_HPP diff --git a/src/gui/ObjectMenu.cpp b/src/gui/ObjectMenu.cpp deleted file mode 100644 index bfce4248..00000000 --- a/src/gui/ObjectMenu.cpp +++ /dev/null @@ -1,145 +0,0 @@ -/* - This file is part of Ingen. - Copyright 2007-2015 David Robillard - - 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 - Software Foundation, either version 3 of the License, or 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 Affero General Public License for details. - - You should have received a copy of the GNU Affero General Public License - along with Ingen. If not, see . -*/ - -#include - -#include "ingen/Forge.hpp" -#include "ingen/Interface.hpp" -#include "ingen/client/ObjectModel.hpp" - -#include "App.hpp" -#include "ObjectMenu.hpp" -#include "WidgetFactory.hpp" -#include "WindowFactory.hpp" - -namespace Ingen { - -using namespace Client; - -namespace GUI { - -ObjectMenu::ObjectMenu(BaseObjectType* cobject, - const Glib::RefPtr& xml) - : Gtk::Menu(cobject) - , _app(nullptr) - , _polyphonic_menuitem(nullptr) - , _disconnect_menuitem(nullptr) - , _rename_menuitem(nullptr) - , _destroy_menuitem(nullptr) - , _properties_menuitem(nullptr) - , _enable_signal(false) -{ - xml->get_widget("object_learn_menuitem", _learn_menuitem); - xml->get_widget("object_unlearn_menuitem", _unlearn_menuitem); - xml->get_widget("object_polyphonic_menuitem", _polyphonic_menuitem); - xml->get_widget("object_disconnect_menuitem", _disconnect_menuitem); - xml->get_widget("object_rename_menuitem", _rename_menuitem); - xml->get_widget("object_destroy_menuitem", _destroy_menuitem); - xml->get_widget("object_properties_menuitem", _properties_menuitem); - xml->get_widget("object_menu_separator", _separator_menuitem); -} - -void -ObjectMenu::init(App& app, SPtr object) -{ - _app = &app; - _object = object; - - _polyphonic_menuitem->signal_toggled().connect( - sigc::mem_fun(this, &ObjectMenu::on_menu_polyphonic)); - - _polyphonic_menuitem->set_active(object->polyphonic()); - - _learn_menuitem->signal_activate().connect( - sigc::mem_fun(this, &ObjectMenu::on_menu_learn)); - - _unlearn_menuitem->signal_activate().connect( - sigc::mem_fun(this, &ObjectMenu::on_menu_unlearn)); - - _disconnect_menuitem->signal_activate().connect( - sigc::mem_fun(this, &ObjectMenu::on_menu_disconnect)); - - _rename_menuitem->signal_activate().connect( - sigc::bind(sigc::mem_fun(_app->window_factory(), &WindowFactory::present_rename), - object)); - - _destroy_menuitem->signal_activate().connect( - sigc::mem_fun(this, &ObjectMenu::on_menu_destroy)); - - _properties_menuitem->signal_activate().connect( - sigc::mem_fun(this, &ObjectMenu::on_menu_properties)); - - object->signal_property().connect(sigc::mem_fun(this, &ObjectMenu::property_changed)); - - _learn_menuitem->hide(); - _unlearn_menuitem->hide(); - - _enable_signal = true; -} - -void -ObjectMenu::on_menu_learn() -{ - _app->interface()->set_property(_object->uri(), - _app->uris().midi_binding, - _app->uris().patch_wildcard.urid); -} - -void -ObjectMenu::on_menu_unlearn() -{ - Properties remove; - remove.emplace(_app->uris().midi_binding, - Property(_app->uris().patch_wildcard)); - _app->interface()->delta(_object->uri(), remove, Properties()); -} - -void -ObjectMenu::on_menu_polyphonic() -{ - if (_enable_signal) { - _app->set_property( - _object->uri(), - _app->uris().ingen_polyphonic, - _app->forge().make(bool(_polyphonic_menuitem->get_active()))); - } -} - -void -ObjectMenu::property_changed(const URI& predicate, const Atom& value) -{ - const URIs& uris = _app->uris(); - _enable_signal = false; - if (predicate == uris.ingen_polyphonic && value.type() == uris.forge.Bool) { - _polyphonic_menuitem->set_active(value.get()); - } - _enable_signal = true; -} - -void -ObjectMenu::on_menu_destroy() -{ - _app->interface()->del(_object->uri()); -} - -void -ObjectMenu::on_menu_properties() -{ - _app->window_factory()->present_properties(_object); -} - -} // namespace GUI -} // namespace Ingen diff --git a/src/gui/ObjectMenu.hpp b/src/gui/ObjectMenu.hpp deleted file mode 100644 index a9b07fd5..00000000 --- a/src/gui/ObjectMenu.hpp +++ /dev/null @@ -1,77 +0,0 @@ -/* - This file is part of Ingen. - Copyright 2007-2015 David Robillard - - 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 - Software Foundation, either version 3 of the License, or 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 Affero General Public License for details. - - You should have received a copy of the GNU Affero General Public License - along with Ingen. If not, see . -*/ - -#ifndef INGEN_GUI_OBJECTMENU_HPP -#define INGEN_GUI_OBJECTMENU_HPP - -#include -#include -#include -#include - -#include "ingen/client/ObjectModel.hpp" -#include "ingen/types.hpp" - -namespace Ingen { -namespace GUI { - -class ObjectControlWindow; -class ObjectPropertiesWindow; -class GraphCanvas; - -/** Menu for a Object. - * - * \ingroup GUI - */ -class ObjectMenu : public Gtk::Menu -{ -public: - ObjectMenu(BaseObjectType* cobject, - const Glib::RefPtr& xml); - - void init(App& app, SPtr object); - - SPtr object() const { return _object; } - App* app() const { return _app; } - -protected: - void on_menu_learn(); - void on_menu_unlearn(); - virtual void on_menu_disconnect() = 0; - void on_menu_polyphonic(); - void on_menu_destroy(); - void on_menu_properties(); - - void property_changed(const URI& predicate, const Atom& value); - - App* _app; - SPtr _object; - Gtk::MenuItem* _learn_menuitem; - Gtk::MenuItem* _unlearn_menuitem; - Gtk::CheckMenuItem* _polyphonic_menuitem; - Gtk::MenuItem* _disconnect_menuitem; - Gtk::MenuItem* _rename_menuitem; - Gtk::MenuItem* _destroy_menuitem; - Gtk::MenuItem* _properties_menuitem; - Gtk::SeparatorMenuItem* _separator_menuitem; - - bool _enable_signal; -}; - -} // namespace GUI -} // namespace Ingen - -#endif // INGEN_GUI_OBJECTMENU_HPP diff --git a/src/gui/PluginMenu.cpp b/src/gui/PluginMenu.cpp deleted file mode 100644 index fc385773..00000000 --- a/src/gui/PluginMenu.cpp +++ /dev/null @@ -1,176 +0,0 @@ -/* - This file is part of Ingen. - Copyright 2014-2015 David Robillard - - 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 - Software Foundation, either version 3 of the License, or 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 Affero General Public License for details. - - You should have received a copy of the GNU Affero General Public License - along with Ingen. If not, see . -*/ - -#include "PluginMenu.hpp" -#include "ingen/Log.hpp" -#include "ingen/client/PluginModel.hpp" - -namespace Ingen { -namespace GUI { - -PluginMenu::PluginMenu(Ingen::World& world) - : _world(world) - , _classless_menu(nullptr, nullptr) -{ - clear(); -} - -void -PluginMenu::clear() -{ - const LilvWorld* lworld = _world.lilv_world(); - const LilvPluginClass* lv2_plugin = lilv_world_get_plugin_class(lworld); - const LilvPluginClasses* classes = lilv_world_get_plugin_classes(lworld); - - // Empty completely - _classless_menu = MenuRecord(nullptr, nullptr); - _class_menus.clear(); - items().clear(); - - // Build skeleton - LV2Children children; - LILV_FOREACH(plugin_classes, i, classes) { - const LilvPluginClass* c = lilv_plugin_classes_get(classes, i); - const LilvNode* p = lilv_plugin_class_get_parent_uri(c); - if (!p) { - p = lilv_plugin_class_get_uri(lv2_plugin); - } - children.emplace(lilv_node_as_string(p), c); - } - - std::set ancestors; - build_plugin_class_menu(this, lv2_plugin, classes, children, ancestors); - - items().push_back(Gtk::Menu_Helpers::MenuElem("_Uncategorized")); - _classless_menu.item = &(items().back()); - _classless_menu.menu = Gtk::manage(new Gtk::Menu()); - _classless_menu.item->set_submenu(*_classless_menu.menu); - _classless_menu.item->hide(); -} - -void -PluginMenu::add_plugin(SPtr p) -{ - typedef ClassMenus::iterator iterator; - - if (!p->lilv_plugin() || lilv_plugin_is_replaced(p->lilv_plugin())) { - return; - } - - const LilvPluginClass* pc = lilv_plugin_get_class(p->lilv_plugin()); - const LilvNode* class_uri = lilv_plugin_class_get_uri(pc); - const char* class_uri_str = lilv_node_as_string(class_uri); - - std::pair range = _class_menus.equal_range(class_uri_str); - if (range.first == _class_menus.end() || range.first == range.second - || range.first->second.menu == this) { - // Add to uncategorized plugin menu - add_plugin_to_menu(_classless_menu, p); - } else { - // For each menu that represents plugin's class (possibly several) - for (auto i = range.first; i != range.second ; ++i) { - add_plugin_to_menu(i->second, p); - } - } -} - -size_t -PluginMenu::build_plugin_class_menu(Gtk::Menu* menu, - const LilvPluginClass* plugin_class, - const LilvPluginClasses* classes, - const LV2Children& children, - std::set& ancestors) -{ - size_t num_items = 0; - const LilvNode* class_uri = lilv_plugin_class_get_uri(plugin_class); - const char* class_uri_str = lilv_node_as_string(class_uri); - - const std::pair kids - = children.equal_range(class_uri_str); - - if (kids.first == children.end()) { - return 0; - } - - // Add submenus - ancestors.insert(class_uri_str); - for (LV2Children::const_iterator i = kids.first; i != kids.second; ++i) { - const LilvPluginClass* c = i->second; - const char* sub_label_str = lilv_node_as_string(lilv_plugin_class_get_label(c)); - const char* sub_uri_str = lilv_node_as_string(lilv_plugin_class_get_uri(c)); - if (ancestors.find(sub_uri_str) != ancestors.end()) { - _world.log().warn(fmt("Infinite LV2 class recursion: %1% <: %2%\n") - % class_uri_str % sub_uri_str); - return 0; - } - - Gtk::Menu_Helpers::MenuElem menu_elem = Gtk::Menu_Helpers::MenuElem( - std::string("_") + sub_label_str); - menu->items().push_back(menu_elem); - Gtk::MenuItem* menu_item = &(menu->items().back()); - - Gtk::Menu* submenu = Gtk::manage(new Gtk::Menu()); - menu_item->set_submenu(*submenu); - - size_t num_child_items = build_plugin_class_menu( - submenu, c, classes, children, ancestors); - - _class_menus.emplace(sub_uri_str, MenuRecord(menu_item, submenu)); - if (num_child_items == 0) { - menu_item->hide(); - } - - ++num_items; - } - ancestors.erase(class_uri_str); - - return num_items; -} - -void -PluginMenu::add_plugin_to_menu(MenuRecord& menu, SPtr p) -{ - const URIs& uris = _world.uris(); - LilvWorld* lworld = _world.lilv_world(); - LilvNode* ingen_Graph = lilv_new_uri(lworld, uris.ingen_Graph.c_str()); - LilvNode* rdf_type = lilv_new_uri(lworld, uris.rdf_type.c_str()); - - bool is_graph = lilv_world_ask(lworld, - lilv_plugin_get_uri(p->lilv_plugin()), - rdf_type, - ingen_Graph); - - menu.menu->items().push_back( - Gtk::Menu_Helpers::MenuElem( - std::string("_") + p->human_name() + (is_graph ? " ⚙" : ""), - sigc::bind(sigc::mem_fun(this, &PluginMenu::load_plugin), p))); - - if (!menu.item->is_visible()) { - menu.item->show(); - } - - lilv_node_free(rdf_type); - lilv_node_free(ingen_Graph); -} - -void -PluginMenu::load_plugin(WPtr weak_plugin) -{ - signal_load_plugin.emit(weak_plugin); -} - -} // namespace GUI -} // namespace Ingen diff --git a/src/gui/PluginMenu.hpp b/src/gui/PluginMenu.hpp deleted file mode 100644 index bc654db5..00000000 --- a/src/gui/PluginMenu.hpp +++ /dev/null @@ -1,80 +0,0 @@ -/* - This file is part of Ingen. - Copyright 2014-2015 David Robillard - - 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 - Software Foundation, either version 3 of the License, or 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 Affero General Public License for details. - - You should have received a copy of the GNU Affero General Public License - along with Ingen. If not, see . -*/ - -#ifndef INGEN_GUI_PLUGINMENU_HPP -#define INGEN_GUI_PLUGINMENU_HPP - -#include -#include -#include - -#include - -#include "ingen/World.hpp" -#include "ingen/types.hpp" -#include "lilv/lilv.h" - -namespace Ingen { - -namespace Client { class PluginModel; } - -namespace GUI { - -/** - Type-hierarchical plugin menu. - - @ingroup GUI -*/ -class PluginMenu : public Gtk::Menu -{ -public: - PluginMenu(Ingen::World& world); - - void clear(); - void add_plugin(SPtr p); - - sigc::signal< void, WPtr > signal_load_plugin; - -private: - struct MenuRecord { - MenuRecord(Gtk::MenuItem* i, Gtk::Menu* m) : item(i), menu(m) {} - Gtk::MenuItem* item; - Gtk::Menu* menu; - }; - - typedef std::multimap LV2Children; - typedef std::multimap ClassMenus; - - /// Recursively add hierarchy rooted at `plugin_class` to `menu`. - size_t build_plugin_class_menu(Gtk::Menu* menu, - const LilvPluginClass* plugin_class, - const LilvPluginClasses* classes, - const LV2Children& children, - std::set& ancestors); - - void add_plugin_to_menu(MenuRecord& menu, SPtr p); - - void load_plugin(WPtr weak_plugin); - - Ingen::World& _world; - MenuRecord _classless_menu; - ClassMenus _class_menus; -}; - -} // namespace GUI -} // namespace Ingen - -#endif // INGEN_GUI_PLUGINMENU_HPP diff --git a/src/gui/Port.cpp b/src/gui/Port.cpp deleted file mode 100644 index 9742cee3..00000000 --- a/src/gui/Port.cpp +++ /dev/null @@ -1,534 +0,0 @@ -/* - This file is part of Ingen. - Copyright 2007-2016 David Robillard - - 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 - Software Foundation, either version 3 of the License, or 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 Affero General Public License for details. - - You should have received a copy of the GNU Affero General Public License - along with Ingen. If not, see . -*/ - -#include -#include - -#include "ganv/Module.hpp" -#include "ingen/Configuration.hpp" -#include "ingen/Interface.hpp" -#include "ingen/Log.hpp" -#include "ingen/URIMap.hpp" -#include "ingen/client/GraphModel.hpp" -#include "ingen/client/PortModel.hpp" - -#include "App.hpp" -#include "GraphWindow.hpp" -#include "Port.hpp" -#include "PortMenu.hpp" -#include "RDFS.hpp" -#include "Style.hpp" -#include "WidgetFactory.hpp" -#include "WindowFactory.hpp" -#include "ingen_config.h" -#include "rgba.hpp" - -using namespace Ingen::Client; - -namespace Ingen { -namespace GUI { - -Port* -Port::create(App& app, - Ganv::Module& module, - SPtr pm, - bool flip) -{ - return new Port(app, module, pm, port_label(app, pm), flip); -} - -/** @param flip Make an input port appear as an output port, and vice versa. - */ -Port::Port(App& app, - Ganv::Module& module, - SPtr pm, - const std::string& name, - bool flip) - : Ganv::Port(module, name, - flip ? (!pm->is_input()) : pm->is_input(), - app.style()->get_port_color(pm.get())) - , _app(app) - , _port_model(pm) - , _entered(false) - , _flipped(flip) -{ - assert(pm); - - if (app.can_control(pm.get())) { - show_control(); - pm->signal_value_changed().connect( - sigc::mem_fun(this, &Port::value_changed)); - } - - port_properties_changed(); - - pm->signal_property().connect( - sigc::mem_fun(this, &Port::property_changed)); - pm->signal_property_removed().connect( - sigc::mem_fun(this, &Port::property_removed)); - pm->signal_activity().connect( - sigc::mem_fun(this, &Port::activity)); - pm->signal_moved().connect( - sigc::mem_fun(this, &Port::moved)); - - signal_value_changed.connect( - sigc::mem_fun(this, &Port::on_value_changed)); - - signal_event().connect( - sigc::mem_fun(this, &Port::on_event)); - - set_is_controllable(pm->is_numeric() && pm->is_input()); - - Ganv::Port::set_beveled(model()->is_a(_app.uris().lv2_ControlPort) || - model()->has_property(_app.uris().atom_bufferType, - _app.uris().atom_Sequence)); - - for (const auto& p : pm->properties()) { - property_changed(p.first, p.second); - } - - update_metadata(); - value_changed(pm->value()); -} - -Port::~Port() -{ - _app.activity_port_destroyed(this); -} - -std::string -Port::port_label(App& app, SPtr pm) -{ - if (!pm) { - return ""; - } - - std::string label; - if (app.world()->conf().option("port-labels").get()) { - if (app.world()->conf().option("human-names").get()) { - const Atom& name = pm->get_property(app.uris().lv2_name); - if (name.type() == app.forge().String) { - label = name.ptr(); - } else { - const SPtr parent( - dynamic_ptr_cast(pm->parent())); - if (parent && parent->plugin_model()) { - label = parent->plugin_model()->port_human_name(pm->index()); - } - } - } else { - label = pm->path().symbol(); - } - } - return label; -} - -void -Port::ensure_label() -{ - if (!get_label()) { - set_label(port_label(_app, _port_model.lock()).c_str()); - } -} - -void -Port::update_metadata() -{ - SPtr pm = _port_model.lock(); - if (pm && _app.can_control(pm.get()) && pm->is_numeric()) { - SPtr parent = dynamic_ptr_cast(pm->parent()); - if (parent) { - float min = 0.0f; - float max = 1.0f; - parent->port_value_range(pm, min, max, _app.sample_rate()); - set_control_min(min); - set_control_max(max); - } - } -} - -bool -Port::show_menu(GdkEventButton* ev) -{ - PortMenu* menu = nullptr; - WidgetFactory::get_widget_derived("object_menu", menu); - if (!menu) { - _app.log().error("Failed to load port menu widget\n"); - return false; - } - - menu->init(_app, model(), _flipped); - menu->popup(ev->button, ev->time); - return true; -} - -void -Port::moved() -{ - if (_app.world()->conf().option("port-labels").get() && - !_app.world()->conf().option("human-names").get()) { - set_label(model()->symbol().c_str()); - } -} - -void -Port::on_value_changed(double value) -{ - const URIs& uris = _app.uris(); - const Atom& current_value = model()->value(); - if (current_value.type() != uris.forge.Float) { - return; // Non-float, unsupported - } - - if (current_value.get() == (float)value) { - return; // No change - } - - const Atom atom = _app.forge().make(float(value)); - _app.set_property(model()->uri(), - _app.world()->uris().ingen_value, - atom); - - if (_entered) { - GraphBox* box = get_graph_box(); - if (box) { - box->show_port_status(model().get(), atom); - } - } -} - -void -Port::value_changed(const Atom& value) -{ - if (value.type() == _app.forge().Float && !get_grabbed()) { - Ganv::Port::set_control_value(value.get()); - } -} - -void -Port::on_scale_point_activated(float f) -{ - _app.set_property(model()->uri(), - _app.world()->uris().ingen_value, - _app.world()->forge().make(f)); -} - -Gtk::Menu* -Port::build_enum_menu() -{ - SPtr block = dynamic_ptr_cast(model()->parent()); - Gtk::Menu* menu = Gtk::manage(new Gtk::Menu()); - - PluginModel::ScalePoints points = block->plugin_model()->port_scale_points( - model()->index()); - for (auto i = points.begin(); i != points.end(); ++i) { - menu->items().push_back(Gtk::Menu_Helpers::MenuElem(i->second)); - Gtk::MenuItem* menu_item = &(menu->items().back()); - menu_item->signal_activate().connect( - sigc::bind(sigc::mem_fun(this, &Port::on_scale_point_activated), - i->first)); - } - - return menu; -} - -void -Port::on_uri_activated(const URI& uri) -{ - _app.set_property(model()->uri(), - _app.world()->uris().ingen_value, - _app.world()->forge().make_urid( - _app.world()->uri_map().map_uri(uri.c_str()))); -} - -Gtk::Menu* -Port::build_uri_menu() -{ - World* world = _app.world(); - SPtr block = dynamic_ptr_cast(model()->parent()); - Gtk::Menu* menu = Gtk::manage(new Gtk::Menu()); - - // Get the port designation, which should be a rdf:Property - const Atom& designation_atom = model()->get_property( - _app.uris().lv2_designation); - if (!designation_atom.is_valid()) { - return nullptr; - } - - LilvNode* designation = lilv_new_uri( - world->lilv_world(), world->forge().str(designation_atom, false).c_str()); - LilvNode* rdfs_range = lilv_new_uri( - world->lilv_world(), LILV_NS_RDFS "range"); - - // Get every class in the range of the port's property - RDFS::URISet ranges; - LilvNodes* range = lilv_world_find_nodes( - world->lilv_world(), designation, rdfs_range, nullptr); - LILV_FOREACH(nodes, r, range) { - ranges.insert(URI(lilv_node_as_string(lilv_nodes_get(range, r)))); - } - RDFS::classes(world, ranges, false); - - // Get all objects in range - RDFS::Objects values = RDFS::instances(world, ranges); - - // Add a menu item for each such class - for (const auto& v : values) { - if (!v.first.empty()) { - const std::string qname = world->rdf_world()->prefixes().qualify(v.second); - const std::string label = qname + " - " + v.first; - menu->items().push_back(Gtk::Menu_Helpers::MenuElem(label)); - Gtk::MenuItem* menu_item = &(menu->items().back()); - menu_item->signal_activate().connect( - sigc::bind(sigc::mem_fun(this, &Port::on_uri_activated), - v.second)); - } - } - - return menu; -} - -bool -Port::on_event(GdkEvent* ev) -{ - GraphBox* box = nullptr; - switch (ev->type) { - case GDK_ENTER_NOTIFY: - _entered = true; - if ((box = get_graph_box())) { - box->object_entered(model().get()); - } - return false; - case GDK_LEAVE_NOTIFY: - _entered = false; - if ((box = get_graph_box())) { - box->object_left(model().get()); - } - return false; - case GDK_BUTTON_PRESS: - if (ev->button.button == 1) { - if (model()->is_enumeration()) { - Gtk::Menu* menu = build_enum_menu(); - menu->popup(ev->button.button, ev->button.time); - return true; - } else if (model()->is_uri()) { - Gtk::Menu* menu = build_uri_menu(); - if (menu) { - menu->popup(ev->button.button, ev->button.time); - return true; - } - } - } else if (ev->button.button == 3) { - return show_menu(&ev->button); - } - break; - default: - break; - } - - return false; -} - -inline static uint32_t -peak_color(float peak) -{ - static const uint32_t min = 0x4A8A0EC0; - static const uint32_t max = 0xFFCE1FC0; - static const uint32_t peak_min = 0xFF561FC0; - static const uint32_t peak_max = 0xFF0A38C0; - - if (peak < 1.0) { - return rgba_interpolate(min, max, peak); - } else { - return rgba_interpolate(peak_min, peak_max, fminf(peak, 2.0f) - 1.0f); - } -} - -void -Port::activity(const Atom& value) -{ - if (model()->is_a(_app.uris().lv2_AudioPort)) { - set_fill_color(peak_color(value.get())); - } else if (_app.can_control(model().get()) && value.type() == _app.uris().atom_Float) { - Ganv::Port::set_control_value(value.get()); - } else { - _app.port_activity(this); - } -} - -GraphBox* -Port::get_graph_box() const -{ - SPtr graph = dynamic_ptr_cast(model()->parent()); - GraphBox* box = _app.window_factory()->graph_box(graph); - if (!box) { - graph = dynamic_ptr_cast(model()->parent()->parent()); - box = _app.window_factory()->graph_box(graph); - } - return box; -} - -void -Port::set_type_tag() -{ - const URIs& uris = _app.uris(); - std::string tag; - if (model()->is_a(_app.uris().lv2_AudioPort)) { - tag = "~"; - } else if (model()->is_a(_app.uris().lv2_CVPort)) { - tag = "ℝ̰"; - } else if (model()->is_a(_app.uris().lv2_ControlPort)) { - if (model()->is_enumeration()) { - tag = "…"; - } else if (model()->is_integer()) { - tag = "ℤ"; - } else if (model()->is_toggle()) { - tag = ((model()->value() != _app.uris().forge.make(0.0f)) - ? "☑" : "☐"); - - } else { - tag = "ℝ"; - } - } else if (model()->is_a(_app.uris().atom_AtomPort)) { - if (model()->supports(_app.uris().atom_Float)) { - if (model()->is_toggle()) { - tag = ((model()->value() != _app.uris().forge.make(0.0f)) - ? "☑" : "☐"); - } else { - tag = "ℝ"; - } - } - if (model()->supports(_app.uris().atom_Int)) { - tag += "ℤ"; - } - if (model()->supports(_app.uris().midi_MidiEvent)) { - tag += "𝕄"; - } - if (model()->supports(_app.uris().patch_Message)) { - if (tag.empty()) { - tag += "="; - } else { - tag += "̿"; - } - } - if (tag.empty()) { - tag = "*"; - } - - if (model()->has_property(uris.atom_bufferType, uris.atom_Sequence)) { - tag += "̤"; - } - } - - if (!tag.empty()) { - set_value_label(tag.c_str()); - } -} - -void -Port::port_properties_changed() -{ - if (model()->is_toggle()) { - set_control_is_toggle(true); - } else if (model()->is_integer()) { - set_control_is_integer(true); - } - set_type_tag(); -} - -void -Port::property_changed(const URI& key, const Atom& value) -{ - const URIs& uris = _app.uris(); - if (value.type() == uris.forge.Float) { - float val = value.get(); - if (key == uris.ingen_value && !get_grabbed()) { - Ganv::Port::set_control_value(val); - if (model()->is_toggle()) { - std::string tag = (val == 0.0f) ? "☐" : "☑"; - if (model()->is_a(_app.uris().lv2_CVPort)) { - tag += "̰"; - } else if (model()->has_property(uris.atom_bufferType, - uris.atom_Sequence)) { - tag += "̤"; - } - set_value_label(tag.c_str()); - } - } else if (key == uris.lv2_minimum) { - if (model()->port_property(uris.lv2_sampleRate)) { - val *= _app.sample_rate(); - } - set_control_min(val); - } else if (key == uris.lv2_maximum) { - if (model()->port_property(uris.lv2_sampleRate)) { - val *= _app.sample_rate(); - } - set_control_max(val); - } - } else if (key == uris.lv2_portProperty) { - port_properties_changed(); - } else if (key == uris.lv2_name) { - if (value.type() == uris.forge.String && - _app.world()->conf().option("port-labels").get() && - _app.world()->conf().option("human-names").get()) { - set_label(value.ptr()); - } - } else if (key == uris.rdf_type || key == uris.atom_bufferType) { - set_fill_color(_app.style()->get_port_color(model().get())); - Ganv::Port::set_beveled(model()->is_a(uris.lv2_ControlPort) || - model()->has_property(uris.atom_bufferType, - uris.atom_Sequence)); - } -} - -void -Port::property_removed(const URI& key, const Atom& value) -{ - const URIs& uris = _app.uris(); - if (key == uris.lv2_minimum || key == uris.lv2_maximum) { - update_metadata(); - } else if (key == uris.rdf_type || key == uris.atom_bufferType) { - Ganv::Port::set_beveled(model()->is_a(uris.lv2_ControlPort) || - model()->has_property(uris.atom_bufferType, - uris.atom_Sequence)); - } -} - -bool -Port::on_selected(gboolean b) -{ - if (b) { - SPtr pm = _port_model.lock(); - if (pm) { - SPtr block = dynamic_ptr_cast(pm->parent()); - GraphWindow* win = _app.window_factory()->parent_graph_window(block); - if (win && win->documentation_is_visible() && block->plugin_model()) { - bool html = false; -#ifdef HAVE_WEBKIT - html = true; -#endif - const std::string& doc = block->plugin_model()->port_documentation( - pm->index(), html); - win->set_documentation(doc, html); - } - } - } - - return true; -} - -} // namespace GUI -} // namespace Ingen diff --git a/src/gui/Port.hpp b/src/gui/Port.hpp deleted file mode 100644 index c714feae..00000000 --- a/src/gui/Port.hpp +++ /dev/null @@ -1,102 +0,0 @@ -/* - This file is part of Ingen. - Copyright 2007-2015 David Robillard - - 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 - Software Foundation, either version 3 of the License, or 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 Affero General Public License for details. - - You should have received a copy of the GNU Affero General Public License - along with Ingen. If not, see . -*/ - -#ifndef INGEN_GUI_PORT_HPP -#define INGEN_GUI_PORT_HPP - -#include -#include - -#include - -#include "ganv/Port.hpp" -#include "ingen/types.hpp" - -namespace Raul { -class Atom; -} - -namespace Ingen { - -class URI; - -namespace Client { class PortModel; } - -namespace GUI { - -class App; -class GraphBox; - -/** A Port on an Module. - * - * \ingroup GUI - */ -class Port : public Ganv::Port -{ -public: - static Port* create( - App& app, - Ganv::Module& module, - SPtr pm, - bool flip = false); - - ~Port(); - - SPtr model() const { return _port_model.lock(); } - - bool show_menu(GdkEventButton* ev); - void update_metadata(); - void ensure_label(); - - void value_changed(const Atom& value); - void activity(const Atom& value); - - bool on_selected(gboolean b); - -private: - Port(App& app, - Ganv::Module& module, - SPtr pm, - const std::string& name, - bool flip = false); - - static std::string port_label(App& app, SPtr pm); - - Gtk::Menu* build_enum_menu(); - Gtk::Menu* build_uri_menu(); - GraphBox* get_graph_box() const; - - void property_changed(const URI& key, const Atom& value); - void property_removed(const URI& key, const Atom& value); - void moved(); - - void on_value_changed(double value); - void on_scale_point_activated(float f); - void on_uri_activated(const URI& uri); - bool on_event(GdkEvent* ev); - void port_properties_changed(); - void set_type_tag(); - - App& _app; - WPtr _port_model; - bool _entered : 1; - bool _flipped : 1; -}; - -} // namespace GUI -} // namespace Ingen - -#endif // INGEN_GUI_PORT_HPP diff --git a/src/gui/PortMenu.cpp b/src/gui/PortMenu.cpp deleted file mode 100644 index c6ec8fa1..00000000 --- a/src/gui/PortMenu.cpp +++ /dev/null @@ -1,174 +0,0 @@ -/* - This file is part of Ingen. - Copyright 2007-2015 David Robillard - - 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 - Software Foundation, either version 3 of the License, or 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 Affero General Public License for details. - - You should have received a copy of the GNU Affero General Public License - along with Ingen. If not, see . -*/ - -#include - -#include "ingen/Interface.hpp" -#include "ingen/client/GraphModel.hpp" -#include "ingen/client/PortModel.hpp" -#include "ingen/types.hpp" - -#include "App.hpp" -#include "PortMenu.hpp" -#include "WindowFactory.hpp" - -namespace Ingen { - -using namespace Client; - -namespace GUI { - -PortMenu::PortMenu(BaseObjectType* cobject, - const Glib::RefPtr& xml) - : ObjectMenu(cobject, xml) - , _internal_graph_port(false) -{ - xml->get_widget("object_menu", _port_menu); - xml->get_widget("port_set_min_menuitem", _set_min_menuitem); - xml->get_widget("port_set_max_menuitem", _set_max_menuitem); - xml->get_widget("port_reset_range_menuitem", _reset_range_menuitem); - xml->get_widget("port_expose_menuitem", _expose_menuitem); -} - -void -PortMenu::init(App& app, SPtr port, bool internal_graph_port) -{ - const URIs& uris = app.uris(); - - ObjectMenu::init(app, port); - _internal_graph_port = internal_graph_port; - - _set_min_menuitem->signal_activate().connect( - sigc::mem_fun(this, &PortMenu::on_menu_set_min)); - - _set_max_menuitem->signal_activate().connect( - sigc::mem_fun(this, &PortMenu::on_menu_set_max)); - - _reset_range_menuitem->signal_activate().connect( - sigc::mem_fun(this, &PortMenu::on_menu_reset_range)); - - _expose_menuitem->signal_activate().connect( - sigc::mem_fun(this, &PortMenu::on_menu_expose)); - - const bool is_control(app.can_control(port.get()) && port->is_numeric()); - const bool is_on_graph(dynamic_ptr_cast(port->parent())); - const bool is_input(port->is_input()); - - if (!is_on_graph) { - _polyphonic_menuitem->set_sensitive(false); - _rename_menuitem->set_sensitive(false); - _destroy_menuitem->set_sensitive(false); - } - - if (port->is_a(uris.atom_AtomPort)) { - _polyphonic_menuitem->hide(); - } - - _reset_range_menuitem->set_visible(is_input && is_control && !is_on_graph); - _set_max_menuitem->set_visible(is_input && is_control); - _set_min_menuitem->set_visible(is_input && is_control); - _expose_menuitem->set_visible(!is_on_graph); - _learn_menuitem->set_visible(is_input && is_control); - _unlearn_menuitem->set_visible(is_input && is_control); - - if (!is_control && is_on_graph) { - _separator_menuitem->hide(); - } - - _enable_signal = true; -} - -void -PortMenu::on_menu_disconnect() -{ - if (_internal_graph_port) { - _app->interface()->disconnect_all( - _object->parent()->path(), _object->path()); - } else { - _app->interface()->disconnect_all( - _object->parent()->path().parent(), _object->path()); - } -} - -void -PortMenu::on_menu_set_min() -{ - const URIs& uris = _app->uris(); - SPtr model = dynamic_ptr_cast(_object); - const Atom& value = model->get_property(uris.ingen_value); - if (value.is_valid()) { - _app->set_property(_object->uri(), uris.lv2_minimum, value); - } -} - -void -PortMenu::on_menu_set_max() -{ - const URIs& uris = _app->uris(); - SPtr model = dynamic_ptr_cast(_object); - const Atom& value = model->get_property(uris.ingen_value); - if (value.is_valid()) { - _app->set_property(_object->uri(), uris.lv2_maximum, value); - } -} - -void -PortMenu::on_menu_reset_range() -{ - const URIs& uris = _app->uris(); - SPtr model = dynamic_ptr_cast(_object); - - // Remove lv2:minimum and lv2:maximum properties - Properties remove; - remove.insert({uris.lv2_minimum, Property(uris.patch_wildcard)}); - remove.insert({uris.lv2_maximum, Property(uris.patch_wildcard)}); - _app->interface()->delta(_object->uri(), remove, Properties()); -} - -void -PortMenu::on_menu_expose() -{ - const URIs& uris = _app->uris(); - SPtr port = dynamic_ptr_cast(_object); - SPtr block = dynamic_ptr_cast(port->parent()); - - const std::string label = block->label() + " " + block->port_label(port); - const Raul::Path path = Raul::Path(block->path() + Raul::Symbol("_" + port->symbol())); - - Ingen::Resource r(*_object.get()); - r.remove_property(uris.lv2_index, uris.patch_wildcard); - r.set_property(uris.lv2_symbol, _app->forge().alloc(path.symbol())); - r.set_property(uris.lv2_name, _app->forge().alloc(label.c_str())); - - // TODO: Pretty kludgey coordinates - const float block_x = block->get_property(uris.ingen_canvasX).get(); - const float block_y = block->get_property(uris.ingen_canvasY).get(); - const float x_off = (label.length() * 16.0f) * (port->is_input() ? -1 : 1); - const float y_off = port->index() * 32.0f; - r.set_property(uris.ingen_canvasX, _app->forge().make(block_x + x_off)); - r.set_property(uris.ingen_canvasY, _app->forge().make(block_y + y_off)); - - _app->interface()->put(path_to_uri(path), r.properties()); - - if (port->is_input()) { - _app->interface()->connect(path, _object->path()); - } else { - _app->interface()->connect(_object->path(), path); - } -} - -} // namespace GUI -} // namespace Ingen diff --git a/src/gui/PortMenu.hpp b/src/gui/PortMenu.hpp deleted file mode 100644 index db567980..00000000 --- a/src/gui/PortMenu.hpp +++ /dev/null @@ -1,66 +0,0 @@ -/* - This file is part of Ingen. - Copyright 2007-2015 David Robillard - - 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 - Software Foundation, either version 3 of the License, or 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 Affero General Public License for details. - - You should have received a copy of the GNU Affero General Public License - along with Ingen. If not, see . -*/ - -#ifndef INGEN_GUI_PORTMENU_HPP -#define INGEN_GUI_PORTMENU_HPP - -#include -#include -#include - -#include "ingen/client/PortModel.hpp" -#include "ingen/types.hpp" - -#include "ObjectMenu.hpp" - -namespace Ingen { -namespace GUI { - -/** Menu for a Port. - * - * \ingroup GUI - */ -class PortMenu : public ObjectMenu -{ -public: - PortMenu(BaseObjectType* cobject, - const Glib::RefPtr& xml); - - void init(App& app, - SPtr port, - bool internal_graph_port = false); - -private: - void on_menu_disconnect(); - void on_menu_set_min(); - void on_menu_set_max(); - void on_menu_reset_range(); - void on_menu_expose(); - - Gtk::Menu* _port_menu; - Gtk::MenuItem* _set_min_menuitem; - Gtk::MenuItem* _set_max_menuitem; - Gtk::MenuItem* _reset_range_menuitem; - Gtk::MenuItem* _expose_menuitem; - - /// True iff this is a (flipped) port on a GraphPortModule in its graph - bool _internal_graph_port; -}; - -} // namespace GUI -} // namespace Ingen - -#endif // INGEN_GUI_PORTMENU_HPP diff --git a/src/gui/PropertiesWindow.cpp b/src/gui/PropertiesWindow.cpp deleted file mode 100644 index 4d47b3ae..00000000 --- a/src/gui/PropertiesWindow.cpp +++ /dev/null @@ -1,591 +0,0 @@ -/* - This file is part of Ingen. - Copyright 2007-2015 David Robillard - - 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 - Software Foundation, either version 3 of the License, or 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 Affero General Public License for details. - - You should have received a copy of the GNU Affero General Public License - along with Ingen. If not, see . -*/ - -#include -#include -#include - -#include -#include - -#include "ingen/Interface.hpp" -#include "ingen/Log.hpp" -#include "ingen/URIMap.hpp" -#include "ingen/World.hpp" -#include "ingen/client/BlockModel.hpp" -#include "ingen/client/PluginModel.hpp" - -#include "App.hpp" -#include "PropertiesWindow.hpp" -#include "RDFS.hpp" -#include "URIEntry.hpp" - -namespace Ingen { - -using namespace Client; - -namespace GUI { - -typedef std::set URISet; - -PropertiesWindow::PropertiesWindow(BaseObjectType* cobject, - const Glib::RefPtr& xml) - : Window(cobject) - , _value_type(0) -{ - xml->get_widget("properties_vbox", _vbox); - xml->get_widget("properties_scrolledwindow", _scrolledwindow); - xml->get_widget("properties_table", _table); - xml->get_widget("properties_key_combo", _key_combo); - xml->get_widget("properties_value_bin", _value_bin); - xml->get_widget("properties_add_button", _add_button); - xml->get_widget("properties_cancel_button", _cancel_button); - xml->get_widget("properties_apply_button", _apply_button); - xml->get_widget("properties_ok_button", _ok_button); - - _key_store = Gtk::ListStore::create(_combo_columns); - _key_combo->set_model(_key_store); - _key_combo->pack_start(_combo_columns.label_col); - - _key_combo->signal_changed().connect( - sigc::mem_fun(this, &PropertiesWindow::key_changed)); - - _add_button->signal_clicked().connect( - sigc::mem_fun(this, &PropertiesWindow::add_clicked)); - - _cancel_button->signal_clicked().connect( - sigc::mem_fun(this, &PropertiesWindow::cancel_clicked)); - - _apply_button->signal_clicked().connect( - sigc::mem_fun(this, &PropertiesWindow::apply_clicked)); - - _ok_button->signal_clicked().connect( - sigc::mem_fun(this, &PropertiesWindow::ok_clicked)); -} - -void -PropertiesWindow::reset() -{ - _property_connection.disconnect(); - _property_removed_connection.disconnect(); - - _key_store->clear(); - _records.clear(); - - _model.reset(); - - _table->children().clear(); - _table->resize(1, 3); - _table->property_n_rows() = 1; -} - -void -PropertiesWindow::present(SPtr model) -{ - set_object(model); - Gtk::Window::present(); -} - -void -PropertiesWindow::add_property(const URI& key, const Atom& value) -{ - World* world = _app->world(); - - const unsigned n_rows = _table->property_n_rows() + 1; - _table->property_n_rows() = n_rows; - - // Column 0: Property - LilvNode* prop = lilv_new_uri(world->lilv_world(), key.c_str()); - std::string name = RDFS::label(world, prop); - if (name.empty()) { - name = world->rdf_world()->prefixes().qualify(key); - } - Gtk::Label* label = new Gtk::Label( - std::string("" + name + "", - 1.0, - 0.5); - label->set_use_markup(true); - _app->set_tooltip(label, prop); - _table->attach(*Gtk::manage(label), 0, 1, n_rows, n_rows + 1, - Gtk::FILL|Gtk::SHRINK, Gtk::SHRINK); - - // Column 1: Value - Gtk::Alignment* align = manage(new Gtk::Alignment(0.0, 0.5, 1.0, 1.0)); - Gtk::CheckButton* present = manage(new Gtk::CheckButton()); - const char* type = _app->world()->uri_map().unmap_uri(value.type()); - Gtk::Widget* val_widget = create_value_widget(key, type, value); - - present->set_active(); - if (val_widget) { - align->add(*Gtk::manage(val_widget)); - _app->set_tooltip(val_widget, prop); - } - - _table->attach(*align, 1, 2, n_rows, n_rows + 1, - Gtk::FILL|Gtk::EXPAND, Gtk::SHRINK); - _table->attach(*present, 2, 3, n_rows, n_rows + 1, - Gtk::FILL, Gtk::SHRINK); - _records.emplace(key, Record(value, align, n_rows, present)); - _table->show_all(); - - lilv_node_free(prop); -} - -bool -PropertiesWindow::datatype_supported(const RDFS::URISet& types, - URI* widget_type) -{ - if (types.find(_app->uris().atom_Int) != types.end()) { - *widget_type = _app->uris().atom_Int; - return true; - } else if (types.find(_app->uris().atom_Float) != types.end()) { - *widget_type = _app->uris().atom_Float; - return true; - } else if (types.find(_app->uris().atom_Bool) != types.end()) { - *widget_type = _app->uris().atom_Bool; - return true; - } else if (types.find(_app->uris().atom_String) != types.end()) { - *widget_type = _app->uris().atom_String; - return true; - } else if (types.find(_app->uris().atom_URID) != types.end()) { - *widget_type = _app->uris().atom_URID; - return true; - } - - return false; -} - -bool -PropertiesWindow::class_supported(const RDFS::URISet& types) -{ - World* world = _app->world(); - LilvNode* rdf_type = lilv_new_uri( - world->lilv_world(), LILV_NS_RDF "type"); - - for (const auto& t : types) { - LilvNode* range = lilv_new_uri(world->lilv_world(), t.c_str()); - LilvNodes* instances = lilv_world_find_nodes( - world->lilv_world(), nullptr, rdf_type, range); - - const bool has_instance = (lilv_nodes_size(instances) > 0); - - lilv_nodes_free(instances); - lilv_node_free(range); - if (has_instance) { - lilv_node_free(rdf_type); - return true; - } - } - - lilv_node_free(rdf_type); - return false; -} - -/** Set the node this window is associated with. - * This function MUST be called before using this object in any way. - */ -void -PropertiesWindow::set_object(SPtr model) -{ - reset(); - _model = model; - - set_title(model->path() + " Properties - Ingen"); - - World* world = _app->world(); - - LilvNode* rdf_type = lilv_new_uri( - world->lilv_world(), LILV_NS_RDF "type"); - LilvNode* rdfs_DataType = lilv_new_uri( - world->lilv_world(), LILV_NS_RDFS "Datatype"); - - // Populate key combo - const URISet props = RDFS::properties(world, model); - std::map entries; - for (const auto& p : props) { - LilvNode* prop = lilv_new_uri(world->lilv_world(), p.c_str()); - const std::string label = RDFS::label(world, prop); - URISet ranges = RDFS::range(world, prop, true); - - lilv_node_free(prop); - if (label.empty() || ranges.empty()) { - // Property has no label or range, can't show a widget for it - continue; - } - - LilvNode* range = lilv_new_uri(world->lilv_world(), (*ranges.begin()).c_str()); - if (RDFS::is_a(world, range, rdfs_DataType)) { - // Range is a datatype, show if type or any subtype is supported - RDFS::datatypes(_app->world(), ranges, false); - URI widget_type("urn:nothing"); - if (datatype_supported(ranges, &widget_type)) { - entries.emplace(label, p); - } - } else { - // Range is presumably a class, show if any instances are known - if (class_supported(ranges)) { - entries.emplace(label, p); - } - } - } - - for (const auto& e : entries) { - Gtk::ListStore::iterator ki = _key_store->append(); - Gtk::ListStore::Row row = *ki; - row[_combo_columns.uri_col] = e.second.string(); - row[_combo_columns.label_col] = e.first; - } - - lilv_node_free(rdfs_DataType); - lilv_node_free(rdf_type); - - for (const auto& p : model->properties()) { - add_property(p.first, p.second); - } - - _table->show_all(); - - _property_connection = model->signal_property().connect( - sigc::mem_fun(this, &PropertiesWindow::add_property)); - _property_removed_connection = model->signal_property_removed().connect( - sigc::mem_fun(this, &PropertiesWindow::remove_property)); -} - -Gtk::Widget* -PropertiesWindow::create_value_widget(const URI& key, - const char* type_uri, - const Atom& value) -{ - if (!type_uri || !URI::is_valid(type_uri)) { - return nullptr; - } - - URI type(type_uri); - Ingen::World* world = _app->world(); - LilvWorld* lworld = world->lilv_world(); - - // See if type is a datatype we support - std::set types{type}; - RDFS::datatypes(_app->world(), types, false); - - URI widget_type("urn:nothing"); - const bool supported = datatype_supported(types, &widget_type); - if (supported) { - type = widget_type; - _value_type = _app->world()->uri_map().map_uri(type); - } - - if (type == _app->uris().atom_Int) { - Gtk::SpinButton* widget = manage(new Gtk::SpinButton(0.0, 0)); - widget->property_numeric() = true; - widget->set_range(INT_MIN, INT_MAX); - widget->set_increments(1, 10); - if (value.is_valid()) { - widget->set_value(value.get()); - } - widget->signal_value_changed().connect( - sigc::bind(sigc::mem_fun(this, &PropertiesWindow::on_change), key)); - return widget; - } else if (type == _app->uris().atom_Float) { - Gtk::SpinButton* widget = manage(new Gtk::SpinButton(0.0, 4)); - widget->property_numeric() = true; - widget->set_snap_to_ticks(false); - widget->set_range(-FLT_MAX, FLT_MAX); - widget->set_increments(0.1, 1.0); - if (value.is_valid()) { - widget->set_value(value.get()); - } - widget->signal_value_changed().connect( - sigc::bind(sigc::mem_fun(this, &PropertiesWindow::on_change), key)); - return widget; - } else if (type == _app->uris().atom_Bool) { - Gtk::CheckButton* widget = manage(new Gtk::CheckButton()); - if (value.is_valid()) { - widget->set_active(value.get()); - } - widget->signal_toggled().connect( - sigc::bind(sigc::mem_fun(this, &PropertiesWindow::on_change), key)); - return widget; - } else if (type == _app->uris().atom_String) { - Gtk::Entry* widget = manage(new Gtk::Entry()); - if (value.is_valid()) { - widget->set_text(value.ptr()); - } - widget->signal_changed().connect( - sigc::bind(sigc::mem_fun(this, &PropertiesWindow::on_change), key)); - return widget; - } else if (type == _app->uris().atom_URID) { - const char* str = (value.is_valid() - ? world->uri_map().unmap_uri(value.get()) - : ""); - - LilvNode* pred = lilv_new_uri(lworld, key.c_str()); - URISet ranges = RDFS::range(world, pred, true); - URIEntry* widget = manage(new URIEntry(_app, ranges, str ? str : "")); - widget->signal_changed().connect( - sigc::bind(sigc::mem_fun(this, &PropertiesWindow::on_change), key)); - lilv_node_free(pred); - return widget; - } - - LilvNode* type_node = lilv_new_uri(lworld, type.c_str()); - LilvNode* rdfs_Class = lilv_new_uri(lworld, LILV_NS_RDFS "Class"); - const bool is_class = RDFS::is_a(world, type_node, rdfs_Class); - lilv_node_free(rdfs_Class); - lilv_node_free(type_node); - - if (type == _app->uris().atom_URI || - type == _app->uris().rdfs_Class || - is_class) { - LilvNode* pred = lilv_new_uri(lworld, key.c_str()); - URISet ranges = RDFS::range(world, pred, true); - const char* str = value.is_valid() ? value.ptr() : ""; - URIEntry* widget = manage(new URIEntry(_app, ranges, str)); - widget->signal_changed().connect( - sigc::bind(sigc::mem_fun(this, &PropertiesWindow::on_change), key)); - lilv_node_free(pred); - return widget; - } - - _app->log().error(fmt("No widget for value type %1%\n") % type); - - return nullptr; -} - -void -PropertiesWindow::on_show() -{ - static const int WIN_PAD = 64; - static const int VBOX_PAD = 16; - - int width = 0; - int height = 0; - - for (const auto& c : _vbox->children()) { - const Gtk::Requisition& req = c.get_widget()->size_request(); - - width = std::max(width, req.width); - height += req.height + VBOX_PAD; - } - - const Gtk::Requisition& req = _table->size_request(); - - width = 1.2 * std::max(width, req.width + 128); - height += req.height; - - set_default_size(width + WIN_PAD, height + WIN_PAD); - resize(width + WIN_PAD, height + WIN_PAD); - Gtk::Window::on_show(); -} - -void -PropertiesWindow::change_property(const URI& key, const Atom& value) -{ - auto r = _records.find(key); - if (r == _records.end()) { - add_property(key, value); - _table->show_all(); - return; - } - - Record& record = r->second; - const char* type = _app->world()->uri_map().unmap_uri(value.type()); - Gtk::Widget* val_widget = create_value_widget(key, type, value); - - if (val_widget) { - record.value_widget->remove(); - record.value_widget->add(*Gtk::manage(val_widget)); - val_widget->show_all(); - } - - record.value = value; -} - -void -PropertiesWindow::remove_property(const URI& key, const Atom& value) -{ - // Bleh, there doesn't seem to be an easy way to remove a Gtk::Table row... - _records.clear(); - _table->children().clear(); - _table->resize(1, 3); - _table->property_n_rows() = 1; - - for (const auto& p : _model->properties()) { - add_property(p.first, p.second); - } - _table->show_all(); -} - -Atom -PropertiesWindow::get_value(LV2_URID type, Gtk::Widget* value_widget) -{ - Forge& forge = _app->forge(); - - if (type == forge.Int) { - Gtk::SpinButton* spin = dynamic_cast(value_widget); - if (spin) { - return _app->forge().make(spin->get_value_as_int()); - } - } else if (type == forge.Float) { - Gtk::SpinButton* spin = dynamic_cast(value_widget); - if (spin) { - return _app->forge().make(static_cast(spin->get_value())); - } - } else if (type == forge.Bool) { - Gtk::CheckButton* check = dynamic_cast(value_widget); - if (check) { - return _app->forge().make(check->get_active()); - } - } else if (type == forge.URI || type == forge.URID) { - URIEntry* uri_entry = dynamic_cast(value_widget); - if (uri_entry && URI::is_valid(uri_entry->get_text())) { - return _app->forge().make_urid(URI(uri_entry->get_text())); - } else { - _app->log().error(fmt("Invalid URI <%1%>\n") % uri_entry->get_text()); - } - } else if (type == forge.String) { - Gtk::Entry* entry = dynamic_cast(value_widget); - if (entry) { - return _app->forge().alloc(entry->get_text()); - } - } - - return Atom(); -} - -void -PropertiesWindow::on_change(const URI& key) -{ - auto r = _records.find(key); - if (r == _records.end()) { - return; - } - - Record& record = r->second; - const Atom value = get_value(record.value.type(), - record.value_widget->get_child()); - - if (value.is_valid()) { - record.value = value; - } else { - _app->log().error(fmt("Failed to get `%1%' value from widget\n") % key); - } -} - -std::string -PropertiesWindow::active_key() const -{ - const Gtk::ListStore::iterator iter = _key_combo->get_active(); - if (!iter) { - return ""; - } - - Glib::ustring prop_uri = (*iter)[_combo_columns.uri_col]; - return prop_uri; -} - -void -PropertiesWindow::key_changed() -{ - _value_bin->remove(); - if (!_key_combo->get_active()) { - return; - } - - LilvWorld* lworld = _app->world()->lilv_world(); - const Gtk::ListStore::Row key_row = *(_key_combo->get_active()); - const Glib::ustring key_uri = key_row[_combo_columns.uri_col]; - LilvNode* prop = lilv_new_uri(lworld, key_uri.c_str()); - - // Try to create a value widget in the range of this property - const URISet ranges = RDFS::range(_app->world(), prop, true); - for (const auto& r : ranges) { - Gtk::Widget* value_widget = create_value_widget( - URI(key_uri), r.c_str(), Atom()); - - if (value_widget) { - _add_button->set_sensitive(true); - _value_bin->remove(); - _value_bin->add(*Gtk::manage(value_widget)); - _value_bin->show_all(); - break; - } - } - - lilv_node_free(prop); -} - -void -PropertiesWindow::add_clicked() -{ - if (!_key_combo->get_active() || !_value_type || !_value_bin->get_child()) { - return; - } - - // Get selected key URI - const Gtk::ListStore::Row key_row = *(_key_combo->get_active()); - const Glib::ustring key_uri = key_row[_combo_columns.uri_col]; - - // Try to get value from value widget - const Atom& value = get_value(_value_type, _value_bin->get_child()); - if (value.is_valid()) { - // Send property to engine - Properties properties; - properties.emplace(URI(key_uri.c_str()), Property(value)); - _app->interface()->put(_model->uri(), properties); - } -} - -void -PropertiesWindow::cancel_clicked() -{ - reset(); - Gtk::Window::hide(); -} - -void -PropertiesWindow::apply_clicked() -{ - Properties remove; - Properties add; - for (const auto& r : _records) { - const URI& uri = r.first; - const Record& record = r.second; - if (record.present_button->get_active()) { - if (!_model->has_property(uri, record.value)) { - add.emplace(uri, record.value); - } - } else { - remove.emplace(uri, record.value); - } - } - - if (remove.empty()) { - _app->interface()->put(_model->uri(), add); - } else { - _app->interface()->delta(_model->uri(), remove, add); - } -} - -void -PropertiesWindow::ok_clicked() -{ - apply_clicked(); - Gtk::Window::hide(); -} - -} // namespace GUI -} // namespace Ingen diff --git a/src/gui/PropertiesWindow.hpp b/src/gui/PropertiesWindow.hpp deleted file mode 100644 index f4a8dd0d..00000000 --- a/src/gui/PropertiesWindow.hpp +++ /dev/null @@ -1,129 +0,0 @@ -/* - This file is part of Ingen. - Copyright 2007-2015 David Robillard - - 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 - Software Foundation, either version 3 of the License, or 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 Affero General Public License for details. - - You should have received a copy of the GNU Affero General Public License - along with Ingen. If not, see . -*/ - -#ifndef INGEN_GUI_PROPERTIES_WINDOW_HPP -#define INGEN_GUI_PROPERTIES_WINDOW_HPP - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "ingen/client/BlockModel.hpp" -#include "ingen/types.hpp" - -#include "Window.hpp" - -namespace Ingen { - -namespace Client { class ObjectModel; } - -namespace GUI { - -/** Object properties window. - * - * Loaded from XML as a derived object. - * - * \ingroup GUI - */ -class PropertiesWindow : public Window -{ -public: - PropertiesWindow(BaseObjectType* cobject, - const Glib::RefPtr& xml); - - void present(SPtr model); - void set_object(SPtr model); - -private: - /** Record of a property (row in the table) */ - struct Record { - Record(const Atom& v, Gtk::Alignment* vw, int r, Gtk::CheckButton* cb) - : value(v), value_widget(vw), row(r), present_button(cb) - {} - Atom value; - Gtk::Alignment* value_widget; - int row; - Gtk::CheckButton* present_button; - }; - - struct ComboColumns : public Gtk::TreeModel::ColumnRecord { - ComboColumns() { - add(label_col); - add(uri_col); - } - Gtk::TreeModelColumn label_col; - Gtk::TreeModelColumn uri_col; - }; - - void add_property(const URI& key, const Atom& value); - void change_property(const URI& key, const Atom& value); - void remove_property(const URI& key, const Atom& value); - void on_change(const URI& key); - - bool datatype_supported(const std::set& types, - URI* widget_type); - - bool class_supported(const std::set& types); - - Gtk::Widget* create_value_widget(const URI& key, - const char* type_uri, - const Atom& value = Atom()); - - Atom get_value(LV2_URID type, Gtk::Widget* value_widget); - - void reset(); - void on_show(); - - std::string active_key() const; - - void key_changed(); - void add_clicked(); - void cancel_clicked(); - void apply_clicked(); - void ok_clicked(); - - typedef std::map Records; - Records _records; - - SPtr _model; - ComboColumns _combo_columns; - Glib::RefPtr _key_store; - sigc::connection _property_connection; - sigc::connection _property_removed_connection; - Gtk::VBox* _vbox; - Gtk::ScrolledWindow* _scrolledwindow; - Gtk::Table* _table; - Gtk::ComboBox* _key_combo; - LV2_URID _value_type; - Gtk::Bin* _value_bin; - Gtk::Button* _add_button; - Gtk::Button* _cancel_button; - Gtk::Button* _apply_button; - Gtk::Button* _ok_button; -}; - -} // namespace GUI -} // namespace Ingen - -#endif // INGEN_GUI_PROPERTIES_WINDOW_HPP diff --git a/src/gui/RDFS.cpp b/src/gui/RDFS.cpp deleted file mode 100644 index 71b3441a..00000000 --- a/src/gui/RDFS.cpp +++ /dev/null @@ -1,259 +0,0 @@ -/* - This file is part of Ingen. - Copyright 2007-2015 David Robillard - - 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 - Software Foundation, either version 3 of the License, or 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 Affero General Public License for details. - - You should have received a copy of the GNU Affero General Public License - along with Ingen. If not, see . -*/ - -#include "ingen/Forge.hpp" -#include "ingen/Log.hpp" -#include "ingen/Resource.hpp" -#include "ingen/World.hpp" -#include "ingen/client/ObjectModel.hpp" -#include "lilv/lilv.h" - -#include "RDFS.hpp" - -namespace Ingen { -namespace GUI { -namespace RDFS { - -std::string -label(World* world, const LilvNode* node) -{ - LilvNode* rdfs_label = lilv_new_uri( - world->lilv_world(), LILV_NS_RDFS "label"); - LilvNodes* labels = lilv_world_find_nodes( - world->lilv_world(), node, rdfs_label, nullptr); - - const LilvNode* first = lilv_nodes_get_first(labels); - std::string label = first ? lilv_node_as_string(first) : ""; - - lilv_nodes_free(labels); - lilv_node_free(rdfs_label); - return label; -} - -std::string -comment(World* world, const LilvNode* node) -{ - LilvNode* rdfs_comment = lilv_new_uri( - world->lilv_world(), LILV_NS_RDFS "comment"); - LilvNodes* comments = lilv_world_find_nodes( - world->lilv_world(), node, rdfs_comment, nullptr); - - const LilvNode* first = lilv_nodes_get_first(comments); - std::string comment = first ? lilv_node_as_string(first) : ""; - - lilv_nodes_free(comments); - lilv_node_free(rdfs_comment); - return comment; -} - -static void -closure(World* world, const LilvNode* pred, URISet& types, bool super) -{ - unsigned added = 0; - do { - added = 0; - URISet klasses; - for (const auto& t : types) { - LilvNode* type = lilv_new_uri(world->lilv_world(), t.c_str()); - LilvNodes* matches = (super) - ? lilv_world_find_nodes( - world->lilv_world(), type, pred, nullptr) - : lilv_world_find_nodes( - world->lilv_world(), nullptr, pred, type); - LILV_FOREACH(nodes, m, matches) { - const LilvNode* klass_node = lilv_nodes_get(matches, m); - if (lilv_node_is_uri(klass_node)) { - URI klass(lilv_node_as_uri(klass_node)); - if (!types.count(klass)) { - ++added; - klasses.insert(klass); - } - } - } - lilv_nodes_free(matches); - lilv_node_free(type); - } - types.insert(klasses.begin(), klasses.end()); - } while (added > 0); -} - -void -classes(World* world, URISet& types, bool super) -{ - LilvNode* rdfs_subClassOf = lilv_new_uri( - world->lilv_world(), LILV_NS_RDFS "subClassOf"); - - closure(world, rdfs_subClassOf, types, super); - - lilv_node_free(rdfs_subClassOf); -} - -void -datatypes(World* world, URISet& types, bool super) -{ - LilvNode* owl_onDatatype = lilv_new_uri( - world->lilv_world(), LILV_NS_OWL "onDatatype"); - - closure(world, owl_onDatatype, types, super); - - lilv_node_free(owl_onDatatype); -} - -URISet -types(World* world, SPtr model) -{ - typedef Properties::const_iterator PropIter; - typedef std::pair PropRange; - - // Start with every rdf:type - URISet types; - types.insert(URI(LILV_NS_RDFS "Resource")); - PropRange range = model->properties().equal_range(world->uris().rdf_type); - for (auto t = range.first; t != range.second; ++t) { - if (t->second.type() == world->forge().URI || - t->second.type() == world->forge().URID) { - const URI type(world->forge().str(t->second, false)); - types.insert(type); - if (world->uris().ingen_Graph == type) { - // Add lv2:Plugin as a type for graphs so plugin properties show up - types.insert(world->uris().lv2_Plugin); - } - } else { - world->log().error(fmt("<%1%> has non-URI type\n") % model->uri()); - } - } - - // Add every superclass of every type, recursively - RDFS::classes(world, types, true); - - return types; -} - -URISet -properties(World* world, SPtr model) -{ - URISet properties; - URISet types = RDFS::types(world, model); - - LilvNode* rdf_type = lilv_new_uri(world->lilv_world(), - LILV_NS_RDF "type"); - LilvNode* rdf_Property = lilv_new_uri(world->lilv_world(), - LILV_NS_RDF "Property"); - LilvNode* rdfs_domain = lilv_new_uri(world->lilv_world(), - LILV_NS_RDFS "domain"); - - LilvNodes* props = lilv_world_find_nodes( - world->lilv_world(), nullptr, rdf_type, rdf_Property); - LILV_FOREACH(nodes, p, props) { - const LilvNode* prop = lilv_nodes_get(props, p); - if (lilv_node_is_uri(prop)) { - LilvNodes* domains = lilv_world_find_nodes( - world->lilv_world(), prop, rdfs_domain, nullptr); - unsigned n_matching_domains = 0; - LILV_FOREACH(nodes, d, domains) { - const LilvNode* domain_node = lilv_nodes_get(domains, d); - if (!lilv_node_is_uri(domain_node)) { - // TODO: Blank node domains (e.g. unions) - continue; - } - - const URI domain(lilv_node_as_uri(domain_node)); - if (types.count(domain)) { - ++n_matching_domains; - } - } - - if (lilv_nodes_size(domains) == 0 || ( - n_matching_domains > 0 && - n_matching_domains == lilv_nodes_size(domains))) { - properties.insert(URI(lilv_node_as_uri(prop))); - } - - lilv_nodes_free(domains); - } - } - - lilv_node_free(rdfs_domain); - lilv_node_free(rdf_Property); - lilv_node_free(rdf_type); - - return properties; -} - -Objects -instances(World* world, const URISet& types) -{ - LilvNode* rdf_type = lilv_new_uri( - world->lilv_world(), LILV_NS_RDF "type"); - - Objects result; - for (const auto& t : types) { - LilvNode* type = lilv_new_uri(world->lilv_world(), t.c_str()); - LilvNodes* objects = lilv_world_find_nodes( - world->lilv_world(), nullptr, rdf_type, type); - LILV_FOREACH(nodes, o, objects) { - const LilvNode* object = lilv_nodes_get(objects, o); - if (!lilv_node_is_uri(object)) { - continue; - } - const std::string label = RDFS::label(world, object); - result.emplace(label, URI(lilv_node_as_string(object))); - } - lilv_node_free(type); - } - - lilv_node_free(rdf_type); - return result; -} - -URISet -range(World* world, const LilvNode* prop, bool recursive) -{ - LilvNode* rdfs_range = lilv_new_uri( - world->lilv_world(), LILV_NS_RDFS "range"); - - LilvNodes* nodes = lilv_world_find_nodes( - world->lilv_world(), prop, rdfs_range, nullptr); - - URISet ranges; - LILV_FOREACH(nodes, n, nodes) { - ranges.insert(URI(lilv_node_as_string(lilv_nodes_get(nodes, n)))); - } - - if (recursive) { - RDFS::classes(world, ranges, false); - } - - lilv_nodes_free(nodes); - lilv_node_free(rdfs_range); - return ranges; -} - -bool -is_a(World* world, const LilvNode* inst, const LilvNode* klass) -{ - LilvNode* rdf_type = lilv_new_uri(world->lilv_world(), LILV_NS_RDF "type"); - - const bool is_instance = lilv_world_ask( - world->lilv_world(), inst, rdf_type, klass); - - lilv_node_free(rdf_type); - return is_instance; -} - -} // namespace RDFS -} // namespace GUI -} // namespace Ingen diff --git a/src/gui/RDFS.hpp b/src/gui/RDFS.hpp deleted file mode 100644 index f59bbdf5..00000000 --- a/src/gui/RDFS.hpp +++ /dev/null @@ -1,80 +0,0 @@ -/* - This file is part of Ingen. - Copyright 2015 David Robillard - - 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 - Software Foundation, either version 3 of the License, or 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 Affero General Public License for details. - - You should have received a copy of the GNU Affero General Public License - along with Ingen. If not, see . -*/ - -#ifndef INGEN_GUI_RDF_HPP -#define INGEN_GUI_RDF_HPP - -#include -#include -#include - -#include "ingen/types.hpp" -#include "lilv/lilv.h" - -namespace Ingen { - -class World; - -namespace Client { class ObjectModel; } - -namespace GUI { - -namespace RDFS { - -/** Set of URIs. */ -typedef std::set URISet; - -/** Label => Resource map. */ -typedef std::map Objects; - -/** Return the label of `node`. */ -std::string label(World* world, const LilvNode* node); - -/** Return the comment of `node`. */ -std::string comment(World* world, const LilvNode* node); - -/** Set `types` to its super/sub class closure. - * @param super If true, find all superclasses, otherwise all subclasses - */ -void classes(World* world, URISet& types, bool super); - -/** Set `types` to its super/sub datatype closure. - * @param super If true, find all supertypes, otherwise all subtypes. - */ -void datatypes(World* world, URISet& types, bool super); - -/** Get all instances of any class in `types`. */ -Objects instances(World* world, const URISet& types); - -/** Get all the types which `model` is an instance of. */ -URISet types(World* world, SPtr model); - -/** Get all the properties with domains appropriate for `model`. */ -URISet properties(World* world, SPtr model); - -/** Return the range (value types) of `prop`. - * @param recursive If true, include all subclasses. - */ -URISet range(World* world, const LilvNode* prop, bool recursive); - -/** Return true iff `inst` is-a `klass`. */ -bool is_a(World* world, const LilvNode* inst, const LilvNode* klass); - -} // namespace RDFS -} // namespace GUI -} // namespace Ingen - -#endif // INGEN_GUI_RDF_HPP diff --git a/src/gui/RenameWindow.cpp b/src/gui/RenameWindow.cpp deleted file mode 100644 index c83143d9..00000000 --- a/src/gui/RenameWindow.cpp +++ /dev/null @@ -1,137 +0,0 @@ -/* - This file is part of Ingen. - Copyright 2007-2015 David Robillard - - 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 - Software Foundation, either version 3 of the License, or 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 Affero General Public License for details. - - You should have received a copy of the GNU Affero General Public License - along with Ingen. If not, see . -*/ - -#include -#include - -#include "ingen/Forge.hpp" -#include "ingen/Interface.hpp" -#include "ingen/client/ClientStore.hpp" -#include "ingen/client/ObjectModel.hpp" -#include "lv2/lv2plug.in/ns/lv2core/lv2.h" - -#include "App.hpp" -#include "RenameWindow.hpp" - -namespace Ingen { - -using namespace Client; - -namespace GUI { - -RenameWindow::RenameWindow(BaseObjectType* cobject, - const Glib::RefPtr& xml) - : Window(cobject) -{ - xml->get_widget("rename_symbol_entry", _symbol_entry); - xml->get_widget("rename_label_entry", _label_entry); - xml->get_widget("rename_message_label", _message_label); - xml->get_widget("rename_cancel_button", _cancel_button); - xml->get_widget("rename_ok_button", _ok_button); - - _symbol_entry->signal_changed().connect( - sigc::mem_fun(this, &RenameWindow::values_changed)); - _label_entry->signal_changed().connect( - sigc::mem_fun(this, &RenameWindow::values_changed)); - _cancel_button->signal_clicked().connect( - sigc::mem_fun(this, &RenameWindow::cancel_clicked)); - _ok_button->signal_clicked().connect( - sigc::mem_fun(this, &RenameWindow::ok_clicked)); - - _ok_button->property_sensitive() = false; -} - -/** Set the object this window is renaming. - * This function MUST be called before using this object in any way. - */ -void -RenameWindow::set_object(SPtr object) -{ - _object = object; - _symbol_entry->set_text(object->path().symbol()); - const Atom& name_atom = object->get_property(_app->uris().lv2_name); - _label_entry->set_text( - (name_atom.type() == _app->forge().String) ? name_atom.ptr() : ""); -} - -void -RenameWindow::present(SPtr object) -{ - set_object(object); - _symbol_entry->grab_focus(); - Gtk::Window::present(); -} - -void -RenameWindow::values_changed() -{ - const std::string& symbol = _symbol_entry->get_text(); - if (!Raul::Symbol::is_valid(symbol)) { - _message_label->set_text("Invalid symbol"); - _ok_button->property_sensitive() = false; - } else if (_object->symbol() != symbol && - _app->store()->object( - _object->parent()->path().child(Raul::Symbol(symbol)))) { - _message_label->set_text("An object already exists with that path"); - _ok_button->property_sensitive() = false; - } else { - _message_label->set_text(""); - _ok_button->property_sensitive() = true; - } -} - -void -RenameWindow::cancel_clicked() -{ - _symbol_entry->set_text(""); - hide(); -} - -/** Rename the object. - * - * It shouldn't be possible for this to be called with an invalid name set - * (since the Rename button should be deactivated). This is just shinification - * though - the engine will handle invalid names gracefully. - */ -void -RenameWindow::ok_clicked() -{ - const URIs& uris = _app->uris(); - const std::string& symbol_str = _symbol_entry->get_text(); - const std::string& label = _label_entry->get_text(); - Raul::Path path = _object->path(); - const Atom& name_atom = _object->get_property(uris.lv2_name); - - if (!label.empty() && (name_atom.type() != uris.forge.String || - label != name_atom.ptr())) { - _app->set_property(path_to_uri(path), - uris.lv2_name, - _app->forge().alloc(label)); - } - - if (Raul::Symbol::is_valid(symbol_str)) { - const Raul::Symbol symbol(symbol_str); - if (symbol != _object->symbol()) { - path = _object->path().parent().child(symbol); - _app->interface()->move(_object->path(), path); - } - } - - hide(); -} - -} // namespace GUI -} // namespace Ingen diff --git a/src/gui/RenameWindow.hpp b/src/gui/RenameWindow.hpp deleted file mode 100644 index 36264879..00000000 --- a/src/gui/RenameWindow.hpp +++ /dev/null @@ -1,64 +0,0 @@ -/* - This file is part of Ingen. - Copyright 2007-2015 David Robillard - - 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 - Software Foundation, either version 3 of the License, or 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 Affero General Public License for details. - - You should have received a copy of the GNU Affero General Public License - along with Ingen. If not, see . -*/ - -#ifndef INGEN_GUI_RENAMEWINDOW_HPP -#define INGEN_GUI_RENAMEWINDOW_HPP - -#include -#include -#include -#include - -#include "ingen/client/ObjectModel.hpp" -#include "ingen/types.hpp" - -#include "Window.hpp" - -namespace Ingen { -namespace GUI { - -/** Rename window. Handles renaming of any (Ingen) object. - * - * \ingroup GUI - */ -class RenameWindow : public Window -{ -public: - RenameWindow(BaseObjectType* cobject, - const Glib::RefPtr& xml); - - void present(SPtr object); - -private: - void set_object(SPtr object); - - void values_changed(); - void cancel_clicked(); - void ok_clicked(); - - SPtr _object; - - Gtk::Entry* _symbol_entry; - Gtk::Entry* _label_entry; - Gtk::Label* _message_label; - Gtk::Button* _cancel_button; - Gtk::Button* _ok_button; -}; - -} // namespace GUI -} // namespace Ingen - -#endif // INGEN_GUI_RENAMEWINDOW_HPP diff --git a/src/gui/Style.cpp b/src/gui/Style.cpp deleted file mode 100644 index 81e6fb6c..00000000 --- a/src/gui/Style.cpp +++ /dev/null @@ -1,106 +0,0 @@ -/* - This file is part of Ingen. - Copyright 2007-2015 David Robillard - - 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 - Software Foundation, either version 3 of the License, or 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 Affero General Public License for details. - - You should have received a copy of the GNU Affero General Public License - along with Ingen. If not, see . -*/ - -#include -#include -#include -#include -#include - -#include "ganv/Port.hpp" -#include "ingen/Log.hpp" -#include "ingen/Parser.hpp" -#include "ingen/client/PluginModel.hpp" -#include "ingen/client/PortModel.hpp" - -#include "App.hpp" -#include "Style.hpp" -#include "Port.hpp" - -namespace Ingen { -namespace GUI { - -using namespace Ingen::Client; - -Style::Style(App& app) - // Colours from the Tango palette with modified V - : _app(app) -#ifdef INGEN_USE_LIGHT_THEME - , _audio_port_color(0xC8E6ABFF) // Green - , _control_port_color(0xAAC0E6FF) // Blue - , _cv_port_color(0xACE6E0FF) // Teal (between audio and control) - , _event_port_color(0xE6ABABFF) // Red - , _string_port_color(0xD8ABE6FF) // Plum -#else - , _audio_port_color(0x4A8A0EFF) // Green - , _control_port_color(0x244678FF) // Blue - , _cv_port_color(0x248780FF) // Teal (between audio and control) - , _event_port_color(0x960909FF) // Red - , _string_port_color(0x5C3566FF) // Plum -#endif -{ -} - -/** Loads settings from the rc file. Passing no parameter will load from - * the default location. - */ -void -Style::load_settings(std::string filename) -{ - /* ... */ -} - -/** Saves settings to rc file. Passing no parameter will save to the - * default location. - */ -void -Style::save_settings(std::string filename) -{ - /* ... */ -} - -/** Applies the current loaded settings to whichever parts of the app - * need updating. - */ -void -Style::apply_settings() -{ - /* ... */ -} - -uint32_t -Style::get_port_color(const Client::PortModel* p) -{ - const URIs& uris = _app.uris(); - if (p->is_a(uris.lv2_AudioPort)) { - return _audio_port_color; - } else if (p->is_a(uris.lv2_ControlPort)) { - return _control_port_color; - } else if (p->is_a(uris.lv2_CVPort)) { - return _cv_port_color; - } else if (p->supports(uris.atom_String)) { - return _string_port_color; - } else if (_app.can_control(p)) { - return _control_port_color; - } else if (p->is_a(uris.atom_AtomPort)) { - return _event_port_color; - } - - return 0x555555FF; -} - -} // namespace GUI -} // namespace Ingen diff --git a/src/gui/Style.hpp b/src/gui/Style.hpp deleted file mode 100644 index 8e628a3d..00000000 --- a/src/gui/Style.hpp +++ /dev/null @@ -1,56 +0,0 @@ -/* - This file is part of Ingen. - Copyright 2007-2015 David Robillard - - 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 - Software Foundation, either version 3 of the License, or 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 Affero General Public License for details. - - You should have received a copy of the GNU Affero General Public License - along with Ingen. If not, see . -*/ - -#ifndef INGEN_GUI_STYLE_HPP -#define INGEN_GUI_STYLE_HPP - -#include -#include - -namespace Ingen { namespace Client { class PortModel; } } - -namespace Ingen { -namespace GUI { - -class App; -class Port; - -class Style -{ -public: - explicit Style(App& app); - - void load_settings(std::string filename = ""); - void save_settings(std::string filename = ""); - - void apply_settings(); - - uint32_t get_port_color(const Client::PortModel* p); - -private: - App& _app; - - uint32_t _audio_port_color; - uint32_t _control_port_color; - uint32_t _cv_port_color; - uint32_t _event_port_color; - uint32_t _string_port_color; -}; - -} // namespace GUI -} // namespace Ingen - -#endif // INGEN_GUI_STYLE_HPP diff --git a/src/gui/SubgraphModule.cpp b/src/gui/SubgraphModule.cpp deleted file mode 100644 index 6bbcf534..00000000 --- a/src/gui/SubgraphModule.cpp +++ /dev/null @@ -1,102 +0,0 @@ -/* - This file is part of Ingen. - Copyright 2007-2015 David Robillard - - 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 - Software Foundation, either version 3 of the License, or 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 Affero General Public License for details. - - You should have received a copy of the GNU Affero General Public License - along with Ingen. If not, see . -*/ - -#include -#include - -#include "ingen/Interface.hpp" -#include "ingen/client/GraphModel.hpp" - -#include "App.hpp" -#include "NodeModule.hpp" -#include "GraphCanvas.hpp" -#include "GraphWindow.hpp" -#include "Port.hpp" -#include "SubgraphModule.hpp" -#include "WindowFactory.hpp" - -namespace Ingen { - -using namespace Client; - -namespace GUI { - -SubgraphModule::SubgraphModule(GraphCanvas& canvas, - SPtr graph) - : NodeModule(canvas, graph) - , _graph(graph) -{ - assert(graph); -} - -bool -SubgraphModule::on_double_click(GdkEventButton* event) -{ - assert(_graph); - - SPtr parent = dynamic_ptr_cast(_graph->parent()); - - GraphWindow* const preferred = ( (parent && (event->state & GDK_SHIFT_MASK)) - ? nullptr - : app().window_factory()->graph_window(parent) ); - - app().window_factory()->present_graph(_graph, preferred); - return true; -} - -void -SubgraphModule::store_location(double ax, double ay) -{ - const URIs& uris = app().uris(); - - const Atom x(app().forge().make(static_cast(ax))); - const Atom y(app().forge().make(static_cast(ay))); - - if (x != _block->get_property(uris.ingen_canvasX) || - y != _block->get_property(uris.ingen_canvasY)) - { - app().interface()->put(_graph->uri(), - {{uris.ingen_canvasX, x}, - {uris.ingen_canvasY, y}}, - Resource::Graph::EXTERNAL); - } -} - -/** Browse to this graph in current (parent's) window - * (unless an existing window is displaying it) - */ -void -SubgraphModule::browse_to_graph() -{ - assert(_graph->parent()); - - SPtr parent = dynamic_ptr_cast(_graph->parent()); - - GraphWindow* const preferred = (parent) - ? app().window_factory()->graph_window(parent) - : nullptr; - - app().window_factory()->present_graph(_graph, preferred); -} - -void -SubgraphModule::menu_remove() -{ - app().interface()->del(_graph->uri()); -} - -} // namespace GUI -} // namespace Ingen diff --git a/src/gui/SubgraphModule.hpp b/src/gui/SubgraphModule.hpp deleted file mode 100644 index 1b8df2fa..00000000 --- a/src/gui/SubgraphModule.hpp +++ /dev/null @@ -1,64 +0,0 @@ -/* - This file is part of Ingen. - Copyright 2007-2015 David Robillard - - 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 - Software Foundation, either version 3 of the License, or 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 Affero General Public License for details. - - You should have received a copy of the GNU Affero General Public License - along with Ingen. If not, see . -*/ - -#ifndef INGEN_GUI_SUBGRAPHMODULE_HPP -#define INGEN_GUI_SUBGRAPHMODULE_HPP - -#include "ingen/types.hpp" - -#include "NodeModule.hpp" -#include "GraphPortModule.hpp" - -namespace Ingen { namespace Client { -class GraphModel; -class GraphWindow; -class PortModel; -} } - -namespace Ingen { -namespace GUI { - -class GraphCanvas; - -/** A module to represent a subgraph - * - * \ingroup GUI - */ -class SubgraphModule : public NodeModule -{ -public: - SubgraphModule(GraphCanvas& canvas, - SPtr graph); - - virtual ~SubgraphModule() {} - - bool on_double_click(GdkEventButton* event); - - void store_location(double ax, double ay); - - void browse_to_graph(); - void menu_remove(); - - SPtr graph() const { return _graph; } - -protected: - SPtr _graph; -}; - -} // namespace GUI -} // namespace Ingen - -#endif // INGEN_GUI_SUBGRAPHMODULE_HPP diff --git a/src/gui/ThreadedLoader.cpp b/src/gui/ThreadedLoader.cpp deleted file mode 100644 index 7a80fa6e..00000000 --- a/src/gui/ThreadedLoader.cpp +++ /dev/null @@ -1,148 +0,0 @@ -/* - This file is part of Ingen. - Copyright 2007-2015 David Robillard - - 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 - Software Foundation, either version 3 of the License, or 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 Affero General Public License for details. - - You should have received a copy of the GNU Affero General Public License - along with Ingen. If not, see . -*/ - -#include -#include - -#include "ingen/Log.hpp" -#include "ingen/Module.hpp" -#include "ingen/World.hpp" -#include "ingen/client/GraphModel.hpp" - -#include "App.hpp" -#include "ThreadedLoader.hpp" - -using boost::optional; - -namespace Ingen { -namespace GUI { - -ThreadedLoader::ThreadedLoader(App& app, SPtr engine) - : _app(app) - , _sem(0) - , _engine(std::move(engine)) - , _exit_flag(false) - , _thread(&ThreadedLoader::run, this) -{ - if (!parser()) { - app.log().warn("Parser unavailable, graph loading disabled\n"); - } -} - -ThreadedLoader::~ThreadedLoader() -{ - _exit_flag = true; - _sem.post(); - if (_thread.joinable()) { - _thread.join(); - } -} - -SPtr -ThreadedLoader::parser() -{ - return _app.world()->parser(); -} - -void -ThreadedLoader::run() -{ - while (_sem.wait() && !_exit_flag) { - std::lock_guard lock(_mutex); - while (!_events.empty()) { - _events.front()(); - _events.pop_front(); - } - } -} - -void -ThreadedLoader::load_graph(bool merge, - const FilePath& file_path, - optional engine_parent, - optional engine_symbol, - optional engine_data) -{ - std::lock_guard lock(_mutex); - - Glib::ustring engine_base = ""; - if (engine_parent) { - if (merge) { - engine_base = engine_parent.get(); - } else { - engine_base = engine_parent.get().base(); - } - } - - _events.push_back(sigc::hide_return( - sigc::bind(sigc::mem_fun(this, &ThreadedLoader::load_graph_event), - file_path, - engine_parent, - engine_symbol, - engine_data))); - - _sem.post(); -} - -void -ThreadedLoader::load_graph_event(const FilePath& file_path, - optional engine_parent, - optional engine_symbol, - optional engine_data) -{ - std::lock_guard lock(_app.world()->rdf_mutex()); - - _app.world()->parser()->parse_file(_app.world(), - _app.world()->interface().get(), - file_path, - engine_parent, - engine_symbol, - engine_data); -} - -void -ThreadedLoader::save_graph(SPtr model, const URI& uri) -{ - std::lock_guard lock(_mutex); - - _events.push_back(sigc::hide_return( - sigc::bind(sigc::mem_fun(this, &ThreadedLoader::save_graph_event), - model, - uri))); - - _sem.post(); -} - -void -ThreadedLoader::save_graph_event(SPtr model, - const URI& uri) -{ - assert(uri.scheme() == "file"); - if (_app.serialiser()) { - std::lock_guard lock(_app.world()->rdf_mutex()); - - if (uri.string().find(".ingen") != std::string::npos) { - _app.serialiser()->write_bundle(model, uri); - } else { - _app.serialiser()->start_to_file(model->path(), std::string(uri.path())); - _app.serialiser()->serialise(model); - _app.serialiser()->finish(); - } - } -} - -} // namespace GUI -} // namespace Ingen diff --git a/src/gui/ThreadedLoader.hpp b/src/gui/ThreadedLoader.hpp deleted file mode 100644 index 79ef6466..00000000 --- a/src/gui/ThreadedLoader.hpp +++ /dev/null @@ -1,96 +0,0 @@ -/* - This file is part of Ingen. - Copyright 2007-2015 David Robillard - - 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 - Software Foundation, either version 3 of the License, or 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 Affero General Public License for details. - - You should have received a copy of the GNU Affero General Public License - along with Ingen. If not, see . -*/ - -#ifndef INGEN_GUI_THREADEDLOADER_HPP -#define INGEN_GUI_THREADEDLOADER_HPP - -#include - -#include -#include -#include -#include - -#include - -#include "ingen/FilePath.hpp" -#include "ingen/Interface.hpp" -#include "ingen/Parser.hpp" -#include "ingen/Serialiser.hpp" -#include "raul/Semaphore.hpp" - -namespace Ingen { - -class URI; - -namespace GUI { - -/** Thread for loading graph files. - * - * This is a seperate thread so it can send all the loading message without - * blocking everything else, so the app can respond to the incoming events - * caused as a result of the graph loading, while the graph loads. - * - * Implemented as a slave with a list of closures (events) which processes - * all events in the (mutex protected) list each time it's whipped. - * - * \ingroup GUI - */ -class ThreadedLoader -{ -public: - ThreadedLoader(App& app, - SPtr engine); - - ~ThreadedLoader(); - - void load_graph(bool merge, - const FilePath& file_path, - boost::optional engine_parent, - boost::optional engine_symbol, - boost::optional engine_data); - - void save_graph(SPtr model, const URI& uri); - - SPtr parser(); - -private: - void load_graph_event(const FilePath& file_path, - boost::optional engine_parent, - boost::optional engine_symbol, - boost::optional engine_data); - - void save_graph_event(SPtr model, - const URI& filename); - - /** Returns nothing and takes no parameters (because they have all been bound) */ - typedef sigc::slot Closure; - - void run(); - - App& _app; - Raul::Semaphore _sem; - SPtr _engine; - std::mutex _mutex; - std::list _events; - bool _exit_flag; - std::thread _thread; -}; - -} // namespace GUI -} // namespace Ingen - -#endif // INGEN_GUI_LOADERRTHREAD_HPP diff --git a/src/gui/URIEntry.cpp b/src/gui/URIEntry.cpp deleted file mode 100644 index 0b81afd7..00000000 --- a/src/gui/URIEntry.cpp +++ /dev/null @@ -1,192 +0,0 @@ -/* - This file is part of Ingen. - Copyright 2015 David Robillard - - 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 - Software Foundation, either version 3 of the License, or 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 Affero General Public License for details. - - You should have received a copy of the GNU Affero General Public License - along with Ingen. If not, see . -*/ - -#include - -#include "App.hpp" -#include "RDFS.hpp" -#include "URIEntry.hpp" - -namespace Ingen { -namespace GUI { - -URIEntry::URIEntry(App* app, std::set types, const std::string& value) - : Gtk::HBox(false, 4) - , _app(app) - , _types(std::move(types)) - , _menu_button(Gtk::manage(new Gtk::Button("≡"))) - , _entry(Gtk::manage(new Gtk::Entry())) -{ - pack_start(*_entry, true, true); - pack_start(*_menu_button, false, true); - - _entry->set_text(value); - - _menu_button->signal_event().connect( - sigc::mem_fun(this, &URIEntry::menu_button_event)); -} - -Gtk::Menu* -URIEntry::build_value_menu() -{ - World* world = _app->world(); - LilvWorld* lworld = world->lilv_world(); - Gtk::Menu* menu = new Gtk::Menu(); - - LilvNode* owl_onDatatype = lilv_new_uri(lworld, LILV_NS_OWL "onDatatype"); - LilvNode* rdf_type = lilv_new_uri(lworld, LILV_NS_RDF "type"); - LilvNode* rdfs_Class = lilv_new_uri(lworld, LILV_NS_RDFS "Class"); - LilvNode* rdfs_Datatype = lilv_new_uri(lworld, LILV_NS_RDFS "Datatype"); - LilvNode* rdfs_subClassOf = lilv_new_uri(lworld, LILV_NS_RDFS "subClassOf"); - - RDFS::Objects values = RDFS::instances(world, _types); - - for (const auto& v : values) { - const LilvNode* inst = lilv_new_uri(lworld, v.second.c_str()); - std::string label = v.first; - if (label.empty()) { - // No label, show raw URI - label = lilv_node_as_string(inst); - } - - if (lilv_world_ask(world->lilv_world(), inst, rdf_type, rdfs_Class) || - lilv_world_ask(world->lilv_world(), inst, rdf_type, rdfs_Datatype)) { - // This value is a class or datatype... - if (!lilv_world_ask(lworld, inst, rdfs_subClassOf, nullptr) && - !lilv_world_ask(lworld, inst, owl_onDatatype, nullptr)) { - // ... which is not a subtype of another, add menu - add_class_menu_item(menu, inst, label); - } - } else { - // Value is not a class, add item - menu->items().push_back( - Gtk::Menu_Helpers::MenuElem( - std::string("_") + label, - sigc::bind(sigc::mem_fun(this, &URIEntry::uri_chosen), - std::string(lilv_node_as_uri(inst))))); - _app->set_tooltip(&menu->items().back(), inst); - } - } - - lilv_node_free(owl_onDatatype); - lilv_node_free(rdf_type); - lilv_node_free(rdfs_Class); - lilv_node_free(rdfs_Datatype); - lilv_node_free(rdfs_subClassOf); - - return menu; -} - -Gtk::Menu* -URIEntry::build_subclass_menu(const LilvNode* klass) -{ - World* world = _app->world(); - LilvWorld* lworld = world->lilv_world(); - - LilvNode* owl_onDatatype = lilv_new_uri(lworld, LILV_NS_OWL "onDatatype"); - LilvNode* rdfs_subClassOf = lilv_new_uri(lworld, LILV_NS_RDFS "subClassOf"); - - LilvNodes* subclasses = lilv_world_find_nodes( - lworld, nullptr, rdfs_subClassOf, klass); - LilvNodes* subtypes = lilv_world_find_nodes( - lworld, nullptr, owl_onDatatype, klass); - - if (lilv_nodes_size(subclasses) == 0 && lilv_nodes_size(subtypes) == 0) { - return nullptr; - } - - Gtk::Menu* menu = new Gtk::Menu(); - - // Add "header" item for choosing this class itself - add_leaf_menu_item(menu, klass, RDFS::label(world, klass)); - menu->items().push_back(Gtk::Menu_Helpers::SeparatorElem()); - - // Put subclasses/types in a map keyed by label (to sort menu) - std::map entries; - LILV_FOREACH(nodes, s, subclasses) { - const LilvNode* node = lilv_nodes_get(subclasses, s); - entries.emplace(RDFS::label(world, node), node); - } - LILV_FOREACH(nodes, s, subtypes) { - const LilvNode* node = lilv_nodes_get(subtypes, s); - entries.emplace(RDFS::label(world, node), node); - } - - // Add an item (possibly with a submenu) for each subclass/type - for (const auto& e : entries) { - add_class_menu_item(menu, e.second, e.first); - } - - lilv_nodes_free(subtypes); - lilv_nodes_free(subclasses); - lilv_node_free(rdfs_subClassOf); - lilv_node_free(owl_onDatatype); - - return menu; -} - -void -URIEntry::add_leaf_menu_item(Gtk::Menu* menu, - const LilvNode* node, - const std::string& label) -{ - menu->items().push_back( - Gtk::Menu_Helpers::MenuElem( - std::string("_") + label, - sigc::bind(sigc::mem_fun(this, &URIEntry::uri_chosen), - std::string(lilv_node_as_uri(node))))); - - _app->set_tooltip(&menu->items().back(), node); -} - -void -URIEntry::add_class_menu_item(Gtk::Menu* menu, - const LilvNode* klass, - const std::string& label) -{ - Gtk::Menu* submenu = build_subclass_menu(klass); - - if (submenu) { - menu->items().push_back(Gtk::Menu_Helpers::MenuElem(label)); - menu->items().back().set_submenu(*Gtk::manage(submenu)); - } else { - add_leaf_menu_item(menu, klass, label); - } - - _app->set_tooltip(&menu->items().back(), klass); -} - -void -URIEntry::uri_chosen(const std::string& uri) -{ - _entry->set_text(uri); -} - -bool -URIEntry::menu_button_event(GdkEvent* ev) -{ - if (ev->type != GDK_BUTTON_PRESS) { - return false; - } - - Gtk::Menu* menu = Gtk::manage(build_value_menu()); - menu->popup(ev->button.button, ev->button.time); - - return true; -} - -} // namespace GUI -} // namespace Ingen diff --git a/src/gui/URIEntry.hpp b/src/gui/URIEntry.hpp deleted file mode 100644 index 2f55a3d9..00000000 --- a/src/gui/URIEntry.hpp +++ /dev/null @@ -1,68 +0,0 @@ -/* - This file is part of Ingen. - Copyright 2015 David Robillard - - 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 - Software Foundation, either version 3 of the License, or 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 Affero General Public License for details. - - You should have received a copy of the GNU Affero General Public License - along with Ingen. If not, see . -*/ - -#ifndef INGEN_GUI_URI_ENTRY_HPP -#define INGEN_GUI_URI_ENTRY_HPP - -#include -#include -#include -#include - -#include "lilv/lilv.h" - -namespace Ingen { -namespace GUI { - -class App; - -class URIEntry : public Gtk::HBox { -public: - /** Create a widget for entering URIs. - * - * If `types` is given, then a menu button will be shown which pops up a - * enu for easily choosing known values with valid types. - */ - URIEntry(App* app, std::set types, const std::string& value); - - std::string get_text() { return _entry->get_text(); } - Glib::SignalProxy0 signal_changed() { return _entry->signal_changed(); } - -private: - Gtk::Menu* build_value_menu(); - Gtk::Menu* build_subclass_menu(const LilvNode* klass); - - void add_leaf_menu_item(Gtk::Menu* menu, - const LilvNode* node, - const std::string& label); - - void add_class_menu_item(Gtk::Menu* menu, - const LilvNode* klass, - const std::string& label); - - void uri_chosen(const std::string& uri); - bool menu_button_event(GdkEvent* ev); - - App* _app; - const std::set _types; - Gtk::Button* _menu_button; - Gtk::Entry* _entry; -}; - -} // namespace GUI -} // namespace Ingen - -#endif // INGEN_GUI_URI_ENTRY_HPP diff --git a/src/gui/WidgetFactory.cpp b/src/gui/WidgetFactory.cpp deleted file mode 100644 index afb6a07f..00000000 --- a/src/gui/WidgetFactory.cpp +++ /dev/null @@ -1,80 +0,0 @@ -/* - This file is part of Ingen. - Copyright 2007-2015 David Robillard - - 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 - Software Foundation, either version 3 of the License, or 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 Affero General Public License for details. - - You should have received a copy of the GNU Affero General Public License - along with Ingen. If not, see . -*/ - -#include -#include - -#include "ingen/Log.hpp" -#include "ingen/runtime_paths.hpp" - -#include "WidgetFactory.hpp" - -namespace Ingen { -namespace GUI { - -Glib::ustring WidgetFactory::ui_filename = ""; - -inline static bool -is_readable(const std::string& filename) -{ - std::ifstream fs(filename.c_str()); - const bool fail = fs.fail(); - fs.close(); - return !fail; -} - -void -WidgetFactory::find_ui_file() -{ - // Try file in bundle (directory where executable resides) - ui_filename = Ingen::bundle_file_path("ingen_gui.ui"); - if (is_readable(ui_filename)) { - return; - } - - // Try ENGINE_UI_PATH from the environment - const char* const env_path = getenv("INGEN_UI_PATH"); - if (env_path && is_readable(env_path)) { - ui_filename = env_path; - return; - } - - // Try the default system installed path - ui_filename = Ingen::data_file_path("ingen_gui.ui"); - if (is_readable(ui_filename)) { - return; - } - - throw std::runtime_error((fmt("Unable to find ingen_gui.ui in %1%\n") - % INGEN_DATA_DIR).str()); -} - -Glib::RefPtr -WidgetFactory::create(const std::string& toplevel_widget) -{ - if (ui_filename.empty()) { - find_ui_file(); - } - - if (toplevel_widget.empty()) { - return Gtk::Builder::create_from_file(ui_filename); - } else { - return Gtk::Builder::create_from_file(ui_filename, toplevel_widget.c_str()); - } -} - -} // namespace GUI -} // namespace Ingen diff --git a/src/gui/WidgetFactory.hpp b/src/gui/WidgetFactory.hpp deleted file mode 100644 index 92f4dffe..00000000 --- a/src/gui/WidgetFactory.hpp +++ /dev/null @@ -1,58 +0,0 @@ -/* - This file is part of Ingen. - Copyright 2007-2015 David Robillard - - 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 - Software Foundation, either version 3 of the License, or 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 Affero General Public License for details. - - You should have received a copy of the GNU Affero General Public License - along with Ingen. If not, see . -*/ - -#ifndef INGEN_GUI_GLADEFACTORY_HPP -#define INGEN_GUI_GLADEFACTORY_HPP - -#include - -#include -#include - -namespace Ingen { -namespace GUI { - -/** Loads widgets from an XML description. - * Purely static. - * - * \ingroup GUI - */ -class WidgetFactory { -public: - static Glib::RefPtr - create(const std::string& toplevel_widget=""); - - template - static void get_widget(const Glib::ustring& name, T*& widget) { - Glib::RefPtr xml = create(name); - xml->get_widget(name, widget); - } - - template - static void get_widget_derived(const Glib::ustring& name, T*& widget) { - Glib::RefPtr xml = create(name); - xml->get_widget_derived(name, widget); - } - -private: - static void find_ui_file(); - static Glib::ustring ui_filename; -}; - -} // namespace GUI -} // namespace Ingen - -#endif // INGEN_GUI_GLADEFACTORY_HPP diff --git a/src/gui/Window.hpp b/src/gui/Window.hpp deleted file mode 100644 index 2a5c9843..00000000 --- a/src/gui/Window.hpp +++ /dev/null @@ -1,78 +0,0 @@ -/* - This file is part of Ingen. - Copyright 2007-2015 David Robillard - - 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 - Software Foundation, either version 3 of the License, or 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 Affero General Public License for details. - - You should have received a copy of the GNU Affero General Public License - along with Ingen. If not, see . -*/ - -#ifndef INGEN_GUI_WINDOW_HPP -#define INGEN_GUI_WINDOW_HPP - -#include -#include - -namespace Ingen { - -namespace GUI { - -class App; - -/** Ingen GUI Window - * \ingroup GUI - */ -class Window : public Gtk::Window -{ -public: - Window() : Gtk::Window(), _app(nullptr) {} - explicit Window(BaseObjectType* cobject) : Gtk::Window(cobject), _app(nullptr) {} - - virtual void init_window(App& app) { _app = &app; } - - bool on_key_press_event(GdkEventKey* event) { - if (event->keyval == GDK_w && event->state & GDK_CONTROL_MASK) { - hide(); - return true; - } - return Gtk::Window::on_key_press_event(event); - } - - static bool key_press_handler(Gtk::Window* win, GdkEventKey* event); - - App* _app; -}; - -/** Ingen GUI Dialog - * \ingroup GUI - */ -class Dialog : public Gtk::Dialog -{ -public: - Dialog() : Gtk::Dialog(), _app(nullptr) {} - explicit Dialog(BaseObjectType* cobject) : Gtk::Dialog(cobject), _app(nullptr) {} - - virtual void init_dialog(App& app) { _app = &app; } - - bool on_key_press_event(GdkEventKey* event) { - if (event->keyval == GDK_w && event->state & GDK_CONTROL_MASK) { - hide(); - return true; - } - return Gtk::Window::on_key_press_event(event); - } - - App* _app; -}; - -} // namespace GUI -} // namespace Ingen - -#endif // INGEN_GUI_WINDOW_HPP diff --git a/src/gui/WindowFactory.cpp b/src/gui/WindowFactory.cpp deleted file mode 100644 index 5dbdbe98..00000000 --- a/src/gui/WindowFactory.cpp +++ /dev/null @@ -1,302 +0,0 @@ -/* - This file is part of Ingen. - Copyright 2007-2015 David Robillard - - 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 - Software Foundation, either version 3 of the License, or 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 Affero General Public License for details. - - You should have received a copy of the GNU Affero General Public License - along with Ingen. If not, see . -*/ - -#include -#include - -#include "ingen/Log.hpp" -#include "ingen/client/GraphModel.hpp" - -#include "App.hpp" -#include "LoadGraphWindow.hpp" -#include "LoadPluginWindow.hpp" -#include "NewSubgraphWindow.hpp" -#include "GraphView.hpp" -#include "GraphWindow.hpp" -#include "PropertiesWindow.hpp" -#include "RenameWindow.hpp" -#include "WidgetFactory.hpp" -#include "WindowFactory.hpp" - -namespace Ingen { - -using namespace Client; - -namespace GUI { - -WindowFactory::WindowFactory(App& app) - : _app(app) - , _main_box(nullptr) - , _load_plugin_win(nullptr) - , _load_graph_win(nullptr) - , _new_subgraph_win(nullptr) - , _properties_win(nullptr) -{ - WidgetFactory::get_widget_derived("load_plugin_win", _load_plugin_win); - WidgetFactory::get_widget_derived("load_graph_win", _load_graph_win); - WidgetFactory::get_widget_derived("new_subgraph_win", _new_subgraph_win); - WidgetFactory::get_widget_derived("properties_win", _properties_win); - WidgetFactory::get_widget_derived("rename_win", _rename_win); - - if (!(_load_plugin_win && _load_graph_win && _new_subgraph_win - && _properties_win && _rename_win)) { - throw std::runtime_error("failed to load window widgets\n"); - } - - _load_plugin_win->init_window(app); - _load_graph_win->init(app); - _new_subgraph_win->init_window(app); - _properties_win->init_window(app); - _rename_win->init_window(app); -} - -WindowFactory::~WindowFactory() -{ - for (const auto& w : _graph_windows) { - delete w.second; - } -} - -void -WindowFactory::clear() -{ - for (const auto& w : _graph_windows) { - delete w.second; - } - - _graph_windows.clear(); -} - -/** Returns the number of Graph windows currently visible. - */ -size_t -WindowFactory::num_open_graph_windows() -{ - size_t ret = 0; - for (const auto& w : _graph_windows) { - if (w.second->is_visible()) { - ++ret; - } - } - - return ret; -} - -GraphBox* -WindowFactory::graph_box(SPtr graph) -{ - GraphWindow* window = graph_window(graph); - if (window) { - return window->box(); - } else { - return _main_box; - } -} - -GraphWindow* -WindowFactory::graph_window(SPtr graph) -{ - if (!graph) { - return nullptr; - } - - auto w = _graph_windows.find(graph->path()); - - return (w == _graph_windows.end()) ? nullptr : w->second; -} - -GraphWindow* -WindowFactory::parent_graph_window(SPtr block) -{ - if (!block) { - return nullptr; - } - - return graph_window(dynamic_ptr_cast(block->parent())); -} - -/** Present a GraphWindow for a Graph. - * - * If `preferred` is not NULL, it will be set to display `graph` if the graph - * does not already have a visible window, otherwise that window will be - * presented and `preferred` left unmodified. - */ -void -WindowFactory::present_graph(SPtr graph, - GraphWindow* preferred, - SPtr view) -{ - assert(!view || view->graph() == graph); - - auto w = _graph_windows.find(graph->path()); - - if (w != _graph_windows.end()) { - (*w).second->present(); - } else if (preferred) { - w = _graph_windows.find(preferred->graph()->path()); - assert((*w).second == preferred); - - preferred->box()->set_graph(graph, view); - _graph_windows.erase(w); - _graph_windows[graph->path()] = preferred; - preferred->present(); - - } else { - GraphWindow* win = new_graph_window(graph, view); - win->present(); - } -} - -GraphWindow* -WindowFactory::new_graph_window(SPtr graph, - SPtr view) -{ - assert(!view || view->graph() == graph); - - GraphWindow* win = nullptr; - WidgetFactory::get_widget_derived("graph_win", win); - if (!win) { - _app.log().error("Failed to load graph window widget\n"); - return nullptr; - } - - win->init_window(_app); - - win->box()->set_graph(graph, view); - _graph_windows[graph->path()] = win; - - win->signal_delete_event().connect( - sigc::bind<0>(sigc::mem_fun(this, &WindowFactory::remove_graph_window), - win)); - - return win; -} - -bool -WindowFactory::remove_graph_window(GraphWindow* win, GdkEventAny* ignored) -{ - if (_graph_windows.size() <= 1) { - return !_app.quit(win); - } - - auto w = _graph_windows.find(win->graph()->path()); - - assert((*w).second == win); - _graph_windows.erase(w); - - delete win; - - return false; -} - -void -WindowFactory::present_load_plugin(SPtr graph, - Properties data) -{ - _app.request_plugins_if_necessary(); - - auto w = _graph_windows.find(graph->path()); - - if (w != _graph_windows.end()) { - _load_plugin_win->set_transient_for(*w->second); - } - - _load_plugin_win->set_modal(false); - _load_plugin_win->set_type_hint(Gdk::WINDOW_TYPE_HINT_DIALOG); - if (w->second) { - int width, height; - w->second->get_size(width, height); - _load_plugin_win->set_default_size(width - width / 8, height / 2); - } - _load_plugin_win->set_title( - std::string("Load Plugin - ") + graph->path() + " - Ingen"); - _load_plugin_win->present(graph, data); -} - -void -WindowFactory::present_load_graph(SPtr graph, - Properties data) -{ - auto w = _graph_windows.find(graph->path()); - - if (w != _graph_windows.end()) { - _load_graph_win->set_transient_for(*w->second); - } - - _load_graph_win->present(graph, true, data); -} - -void -WindowFactory::present_load_subgraph(SPtr graph, - Properties data) -{ - auto w = _graph_windows.find(graph->path()); - - if (w != _graph_windows.end()) { - _load_graph_win->set_transient_for(*w->second); - } - - _load_graph_win->present(graph, false, data); -} - -void -WindowFactory::present_new_subgraph(SPtr graph, - Properties data) -{ - auto w = _graph_windows.find(graph->path()); - - if (w != _graph_windows.end()) { - _new_subgraph_win->set_transient_for(*w->second); - } - - _new_subgraph_win->present(graph, data); -} - -void -WindowFactory::present_rename(SPtr object) -{ - auto w = _graph_windows.find(object->path()); - if (w == _graph_windows.end()) { - w = _graph_windows.find(object->path().parent()); - } - - if (w != _graph_windows.end()) { - _rename_win->set_transient_for(*w->second); - } - - _rename_win->present(object); -} - -void -WindowFactory::present_properties(SPtr object) -{ - auto w = _graph_windows.find(object->path()); - if (w == _graph_windows.end()) { - w = _graph_windows.find(object->path().parent()); - } - if (w == _graph_windows.end()) { - w = _graph_windows.find(object->path().parent().parent()); - } - - if (w != _graph_windows.end()) { - _properties_win->set_transient_for(*w->second); - } - - _properties_win->present(object); -} - -} // namespace GUI -} // namespace Ingen diff --git a/src/gui/WindowFactory.hpp b/src/gui/WindowFactory.hpp deleted file mode 100644 index ea8b909b..00000000 --- a/src/gui/WindowFactory.hpp +++ /dev/null @@ -1,99 +0,0 @@ -/* - This file is part of Ingen. - Copyright 2007-2015 David Robillard - - 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 - Software Foundation, either version 3 of the License, or 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 Affero General Public License for details. - - You should have received a copy of the GNU Affero General Public License - along with Ingen. If not, see . -*/ - -#ifndef INGEN_GUI_WINDOWFACTORY_HPP -#define INGEN_GUI_WINDOWFACTORY_HPP - -#include - -#include "ingen/Node.hpp" -#include "ingen/types.hpp" - -namespace Ingen { - -namespace Client { -class BlockModel; -class ObjectModel; -class GraphModel; -} - -namespace GUI { - -class App; -class GraphBox; -class GraphView; -class GraphWindow; -class LoadGraphWindow; -class LoadPluginWindow; -class NewSubgraphWindow; -class PropertiesWindow; -class RenameWindow; - -/** Manager/Factory for all windows. - * - * This serves as a nice centralized spot for all window management issues, - * as well as an enumeration of all windows (the goal being to reduce that - * number as much as possible). - */ -class WindowFactory { -public: - explicit WindowFactory(App& app); - ~WindowFactory(); - - size_t num_open_graph_windows(); - - GraphBox* graph_box(SPtr graph); - GraphWindow* graph_window(SPtr graph); - GraphWindow* parent_graph_window(SPtr block); - - void present_graph( - SPtr graph, - GraphWindow* preferred = NULL, - SPtr view = SPtr()); - - void present_load_plugin(SPtr graph, Properties data=Properties()); - void present_load_graph(SPtr graph, Properties data=Properties()); - void present_load_subgraph(SPtr graph, Properties data=Properties()); - void present_new_subgraph(SPtr graph, Properties data=Properties()); - void present_rename(SPtr object); - void present_properties(SPtr object); - - bool remove_graph_window(GraphWindow* win, GdkEventAny* ignored = NULL); - - void set_main_box(GraphBox* box) { _main_box = box; } - - void clear(); - -private: - typedef std::map GraphWindowMap; - - GraphWindow* new_graph_window(SPtr graph, - SPtr view); - - App& _app; - GraphBox* _main_box; - GraphWindowMap _graph_windows; - LoadPluginWindow* _load_plugin_win; - LoadGraphWindow* _load_graph_win; - NewSubgraphWindow* _new_subgraph_win; - PropertiesWindow* _properties_win; - RenameWindow* _rename_win; -}; - -} // namespace GUI -} // namespace Ingen - -#endif // INGEN_GUI_WINDOWFACTORY_HPP diff --git a/src/gui/ingen_gui.cpp b/src/gui/ingen_gui.cpp deleted file mode 100644 index 677296fd..00000000 --- a/src/gui/ingen_gui.cpp +++ /dev/null @@ -1,67 +0,0 @@ -/* - This file is part of Ingen. - Copyright 2007-2018 David Robillard - - 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 - Software Foundation, either version 3 of the License, or 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 Affero General Public License for details. - - You should have received a copy of the GNU Affero General Public License - along with Ingen. If not, see . -*/ - -#include "ingen/Configuration.hpp" -#include "ingen/Module.hpp" -#include "ingen/QueuedInterface.hpp" -#include "ingen/client/SigClientInterface.hpp" - -#include "App.hpp" - -namespace Ingen { -namespace GUI { - -struct GUIModule : public Module { - using SigClientInterface = Client::SigClientInterface; - - void load(World* world) { - URI uri(world->conf().option("connect").ptr()); - if (!world->interface()) { - world->set_interface( - world->new_interface(URI(uri), make_client(world))); - } else if (!dynamic_ptr_cast( - world->interface()->respondee())) { - world->interface()->set_respondee(make_client(world)); - } - - app = GUI::App::create(world); - } - - void run(World* world) { - app->run(); - } - - SPtr make_client(World* const world) { - SPtr sci(new SigClientInterface()); - return world->engine() ? sci : SPtr(new QueuedInterface(sci)); - } - - SPtr app; -}; - -} // namespace GUI -} // namespace Ingen - -extern "C" { - -Ingen::Module* -ingen_module_load() -{ - Glib::thread_init(); - return new Ingen::GUI::GUIModule(); -} - -} // extern "C" diff --git a/src/gui/ingen_gui.gladep b/src/gui/ingen_gui.gladep deleted file mode 100644 index 184ff460..00000000 --- a/src/gui/ingen_gui.gladep +++ /dev/null @@ -1,9 +0,0 @@ - - - - - Ingen - ingen - C++ - FALSE - diff --git a/src/gui/ingen_gui.ui b/src/gui/ingen_gui.ui deleted file mode 100644 index 9e751064..00000000 --- a/src/gui/ingen_gui.ui +++ /dev/null @@ -1,3049 +0,0 @@ - - - - - - False - True - normal - Ingen - @INGEN_VERSION@ - Copyright 2005-2015 David Robillard <http://drobilla.net> - http://drobilla.net/software/ingen - Licensed under the GNU Affero GPL, Version 3 or later. - -See COPYING file included with this distribution, or http://www.gnu.org/licenses/agpl.txt for more information - David Robillard <d@drobilla.net> - translator-credits - Usability / UI Design: - Thorsten Wilms - True - - - False - - - False - - - False - True - end - 0 - - - - - - - True - False - - - True - False - _Edit - True - True - - - - - True - False - - - - - _Input - True - False - True - False - - - False - - - True - False - _Audio - True - - - - - - True - False - C_V - True - - - - - - True - False - _Control - True - - - - - - True - False - _Event - True - - - - - - - - - - _Output - True - False - True - False - - - False - - - True - False - _Audio - True - - - - - - True - False - C_V - True - - - - - - True - False - _Control - True - - - - - - True - False - _Event - True - - - - - - - - - - _Find Plugin... - True - False - True - False - - - - - - _Load Graph... - True - False - True - False - - - - - - _New Graph... - True - False - True - False - - - - - - True - False - - - - - P_roperties... - True - False - True - False - - - - - - False - 8 - Configuration - Ingen - - - True - False - 6 - - - True - False - 2 - 2 - - - True - False - <b>Graph Search Path: </b> - True - - - GTK_FILL - - - - - - True - True - False - False - True - True - - - 1 - 2 - - - - - - True - False - <i>Example: /foo/bar:/home/user/graphs</i> - True - - - 1 - 2 - 1 - 2 - GTK_FILL - - - - - - True - False - 0 - - - 1 - 2 - GTK_FILL - - - - - - True - False - 0 - - - - - True - False - 6 - end - - - gtk-save - True - True - False - True - - - False - False - 0 - - - - - gtk-cancel - True - True - False - True - - - False - False - 1 - - - - - gtk-ok - True - True - False - True - - - False - False - 2 - - - - - False - True - 1 - - - - - - - False - 6 - Engine - Ingen - False - dialog - - - True - False - 6 - - - True - False - end - - - gtk-quit - True - True - True - False - True - - - False - False - 0 - - - - - gtk-disconnect - True - False - True - True - False - True - - - False - False - 1 - - - - - gtk-connect - True - True - True - True - False - True - - - False - False - 2 - - - - - False - False - end - 0 - - - - - True - False - - - True - False - - - True - False - 12 - gtk-disconnect - 3 - - - False - True - 0 - - - - - True - False - 5 - True - - - True - False - 0.10000000149 - - - False - False - 0 - - - - - True - False - 0 - Not connected - - - False - True - 1 - - - - - True - True - 1 - - - - - True - False - 0 - - - - - True - False - - - False - True - 4 - 1 - - - - - True - False - 3 - 2 - 8 - - - True - False - - - True - False - True - False - False - True - True - 1 - True - - - False - False - 0 - - - - - 1 - 2 - 1 - 2 - GTK_FILL - 8 - - - - - True - False - - - True - True - True - 28 - unix:///tmp/ingen.sock - False - False - True - True - - - True - True - 0 - - - - - 1 - 2 - GTK_FILL - GTK_FILL - 8 - - - - - _Connect to engine at: - True - True - False - True - True - - - GTK_FILL - - - - - - _Launch separate engine on port: - True - True - False - True - True - connect_server_radiobutton - - - 1 - 2 - GTK_FILL - - - - - - Start local _JACK engine - True - True - False - True - True - connect_server_radiobutton - - - 2 - 3 - GTK_FILL - - - - - - True - False - 0 - - - 1 - 2 - 2 - 3 - GTK_FILL - - - - - - True - True - 2 - - - - - True - False - - - False - True - 3 - - - - - True - False - 6 - start - - - D_eactivate - True - False - True - True - True - - - False - False - 0 - - - - - _Activate - True - False - True - True - True - - - False - False - 1 - - - - - True - True - 6 - 4 - - - - - False - True - 2 - - - - - - connect_quit_button - connect_disconnect_button - connect_connect_button - - - - 320 - 340 - False - 8 - Graphs - Ingen - - - True - True - 3 - in - - - True - True - True - - - - - - - False - Ingen - 776 - 480 - - - True - False - - - True - False - - - True - False - _File - True - - - False - - - _Import... - True - False - True - False - - - - - - - True - False - - - - - gtk-save - True - False - True - True - - - - - - - Save _As... - True - False - True - False - - - - - - - _Export Image... - True - False - True - False - - - - - - - True - False - - - - - gtk-close - True - False - True - True - - - - - - - gtk-quit - True - False - True - True - - - - - - - - - - - True - False - _Edit - True - - - False - - - gtk-undo - True - False - True - True - - - - - - - gtk-redo - True - False - True - True - - - - - - - True - False - - - - - gtk-cut - True - False - False - True - True - - - - - - gtk-copy - True - False - True - True - - - - - - - gtk-paste - True - False - False - True - True - - - - - - - gtk-delete - True - False - True - True - - - - - - - gtk-select-all - True - False - True - True - - - - - - - True - False - - - - - Arrange - True - False - True - False - - - - - - True - False - - - - - C_ontrols... - True - False - True - False - - - - - - - gtk-properties - True - False - True - True - - - - - - - - - - - True - False - _View - True - - - False - - - True - False - Update control ports as values change. - Animate Signa_ls - True - - - - - - True - False - Sprung Layou_t - True - - - - - - True - False - - - - - True - False - _Human names - True - True - - - - - - True - False - Port _Names - True - True - - - - - - True - False - _Documentation Pane - True - - - - - - True - False - _Status Bar - True - True - - - - - - True - False - - - - - gtk-zoom-in - True - False - True - True - - - - - - gtk-zoom-out - True - False - True - True - - - - - - gtk-zoom-100 - True - False - True - True - - - - - - gtk-zoom-fit - True - False - True - True - - - - - - True - False - - - - - True - False - _Increase Font Size - True - - - - - - True - False - _Decrease Font Size - True - - - - - - True - False - _Normal Font Size - True - - - - - - True - False - - - - - _Parent - True - False - True - True - - - - - - - gtk-refresh - True - False - True - True - - - - - - - gtk-fullscreen - True - False - True - True - - - - - - - - - - - True - False - _Windows - True - - - - False - - - _Engine - True - False - True - False - - - - - - - _Graph Tree - True - False - True - False - - - - - - - _Messages - True - False - True - False - - - - - - - - - - - True - False - _Help - True - - - - False - - - Right-click the canvas to add objects - True - False - True - False - - - - - True - False - - - - - gtk-about - True - False - True - True - - - - - - - - - - False - False - 0 - - - - - True - False - - - True - False - - - - - - True - False - - - - - False - in - - - - - - False - True - - - - - True - True - 1 - - - - - True - False - 2 - - - False - True - 2 - - - - - - - False - Load Graph - Ingen - center-on-parent - dialog - - - False - 24 - - - True - False - end - - - gtk-cancel - True - True - True - False - True - - - False - False - 0 - - - - - gtk-open - True - True - True - True - False - True - - - False - False - 1 - - - - - False - True - end - 0 - - - - - True - False - 0 - 0 - - - True - False - 3 - 3 - 12 - 12 - - - True - False - 0 - Polyphony: - True - - - 1 - 2 - GTK_FILL - - - - - - Load from _File - True - True - False - True - True - True - load_graph_poly_voices_radio - - - 2 - 3 - 1 - 2 - GTK_FILL - - - - - - True - False - 0 - Ports: - True - - - 2 - 3 - GTK_FILL - - - - - _Insert new ports - True - True - False - True - True - True - load_graph_merge_ports_radio - - - 2 - 3 - 2 - 3 - GTK_FILL - - - - - _Merge with existing ports - True - True - False - True - True - True - True - - - 1 - 2 - 2 - 3 - GTK_FILL - - - - - True - False - 6 - - - _Voices: - True - True - False - True - True - True - True - - - False - False - 0 - - - - - True - True - - False - False - True - True - 1 - - - False - True - 1 - - - - - 1 - 2 - 1 - 2 - GTK_FILL - GTK_FILL - - - - - True - False - 0 - _Symbol: - True - True - load_graph_symbol_entry - - - GTK_FILL - - - - - - True - True - - True - False - False - True - True - - - 1 - 3 - GTK_FILL - - - - - - - False - False - 2 - - - - - - load_graph_cancel_button - load_graph_ok_button - - - - False - 8 - Load Plugin - Ingen - center-on-parent - True - dialog - - - True - False - 1 - - - True - True - 2 - - - True - True - 2 - True - True - - - - - True - True - 0 - - - - - True - False - 3 - 3 - 12 - - - True - False - 1 - Node _Symbol: - True - True - load_plugin_name_entry - - - 2 - 3 - GTK_FILL - - - - - - True - False - - - 1 - 2 - 1 - 2 - GTK_FILL - GTK_FILL - - - - - True - False - - - 1 - 2 - GTK_FILL - GTK_FILL - - - - - True - False - - - 2 - 3 - 1 - 2 - GTK_FILL - GTK_FILL - - - - - True - False - - - True - True - False - False - True - True - - - True - True - 0 - - - - - _Polyphonic - True - True - False - True - True - True - - - False - False - 8 - 1 - - - - - 1 - 2 - 2 - 3 - GTK_FILL - 6 - - - - - True - True - True - gtk-clear - False - False - True - True - - - 1 - 3 - GTK_FILL - - - - - True - False - - - GTK_FILL - - - - - - True - False - 4 - - - gtk-close - True - True - True - True - - - False - False - 0 - - - - - gtk-add - True - True - True - True - - - False - False - 1 - - - - - 2 - 3 - 2 - 3 - GTK_FILL - GTK_FILL - - - - - False - False - 1 - - - - - - - 400 - 180 - False - 8 - Messages - Ingen - - - True - False - 6 - - - True - True - in - - - True - True - 1 - 1 - False - word - 5 - 5 - False - False - - - - - True - True - 0 - - - - - True - False - 6 - end - - - gtk-clear - True - False - True - True - False - True - - - False - False - 0 - - - - - gtk-close - True - True - False - True - - - False - False - 1 - - - - - False - True - 1 - - - - - - - 320 - False - 8 - Create Subgraph - Ingen - False - center-on-parent - dialog - - - True - False - - - True - False - 2 - 2 - - - True - False - 0 - _Symbol: - True - new_subgraph_name_entry - - - GTK_FILL - GTK_EXPAND - 5 - - - - - True - False - 0 - _Polyphony: - True - new_subgraph_polyphony_spinbutton - - - 1 - 2 - GTK_FILL - GTK_EXPAND - 5 - - - - - True - True - - True - False - False - True - True - 1 - - - 1 - 2 - 1 - 2 - GTK_FILL - - 4 - - - - - True - True - - True - False - False - True - True - - - 1 - 2 - - 4 - - - - - True - True - 0 - - - - - True - False - True - - - False - False - 1 - - - - - True - False - 4 - end - - - gtk-cancel - True - True - True - True - - - False - False - 0 - - - - - gtk-ok - True - True - True - True - True - True - - - False - False - 1 - - - - - True - True - 2 - - - - - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - Show GUI... - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - False - - - - - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Embed GUI - - - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Enabled - True - - - - - Randomi_ze - False - True - False - - - - - False - Set Value as Mi_nimum - True - - - - - False - Set Value as Ma_ximum - True - - - - - False - Re_set Range - True - - - - - False - _Expose - True - - - - - True - False - - - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - P_olyphonic - True - - - - - True - False - _Learn - True - - - - - True - False - _Unlearn - True - - - - - Dis_connect - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - True - False - - - - - gtk-delete - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - True - True - - - - - _Rename... - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - True - False - - - - - _Properties... - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - True - False - - - - - False - - - gtk-properties - True - False - True - True - - - - - - False - 8 - Port Properties - Ingen - False - mouse - - - True - False - 8 - - - True - False - end - - - gtk-cancel - True - True - True - False - True - - - False - False - 0 - - - - - gtk-ok - True - True - True - True - False - True - - - False - False - 1 - - - - - False - True - end - 0 - - - - - True - False - 2 - 2 - 2 - 4 - - - True - True - False - False - True - True - 1 - 5 - True - - - 1 - 2 - - - - - - True - True - False - False - True - True - 1 - 5 - True - - - 1 - 2 - 1 - 2 - - - - - - True - False - 0 - Minimum Value: - - - GTK_FILL - - - - - - True - False - 0 - Maximum Value: - - - 1 - 2 - GTK_FILL - - - - - - True - True - 2 - - - - - - - False - 12 - center-on-parent - - - True - False - 12 - - - True - True - automatic - automatic - - - True - False - queue - none - - - True - False - 3 - 12 - 6 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - True - True - 0 - - - - - True - False - 6 - - - True - False - - - False - True - 0 - - - - - True - False - - - True - True - 1 - - - - - gtk-add - True - False - True - True - True - - - False - True - 2 - - - - - False - True - 1 - - - - - True - False - 6 - end - - - gtk-cancel - True - True - True - True - True - - - False - False - 0 - - - - - gtk-apply - True - True - True - True - - - False - False - 1 - - - - - gtk-ok - True - True - True - True - True - True - - - False - False - 2 - - - - - False - True - end - 1 - - - - - - - 250 - False - Rename - center-on-parent - True - dialog - - - True - False - 5 - - - True - False - 2 - 2 - 8 - - - True - False - _Symbol: - True - rename_symbol_entry - - - GTK_FILL - - - - - True - True - - True - False - False - True - True - - - 1 - 2 - 1 - 2 - - - - - True - False - _Label: - True - rename_label_entry - - - 1 - 2 - GTK_FILL - - - - - True - True - True - - True - False - False - True - True - - - 1 - 2 - - - - - True - True - 0 - - - - - True - False - - - True - True - 12 - 1 - - - - - True - False - 8 - end - - - gtk-cancel - True - True - True - True - True - - - False - False - 0 - - - - - gtk-ok - True - True - True - True - False - True - - - False - False - 1 - - - - - False - True - 2 - - - - - - - False - Warehouse - Ingen - - - True - False - 6 - 12 - 12 - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - True - False - 0 - 4 - <b>Name</b> - True - True - - - False - False - 0 - - - - - True - False - 1 - 0 - 1 - 1 - 4 - - - True - False - - - - - True - True - 1 - - - - - True - True - False - True - - - False - True - 2 - - - - - False - False - 0 - - - - - 4 - 5 - 8 - - - - - True - False - - - True - False - 0 - - - True - True - never - - - True - False - none - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - - - - - - - True - True - 0 - - - - - - - True - False - - - True - False - - - True - False - icons - 1 - - - True - False - - - - - - False - - - - - True - True - 0 - - - - - True - False - icons - False - 1 - - - True - False - True - gtk-execute - True - - - False - True - - - - - True - False - - - True - False - 4 - gtk-copy - - - - - False - - - - - True - False - - - True - True - False - False - True - True - 1 - True - - - - - False - - - - - False - True - 1 - - - - - False - False - 0 - - - - - True - False - True - True - GDK_EXPOSURE_MASK | GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_MOTION_MASK | GDK_BUTTON1_MOTION_MASK | GDK_BUTTON2_MOTION_MASK | GDK_BUTTON3_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK | GDK_FOCUS_CHANGE_MASK | GDK_STRUCTURE_MASK | GDK_PROPERTY_CHANGE_MASK | GDK_VISIBILITY_NOTIFY_MASK | GDK_PROXIMITY_IN_MASK | GDK_PROXIMITY_OUT_MASK | GDK_SUBSTRUCTURE_MASK | GDK_SCROLL_MASK - 1 - in - - - - - - True - True - 1 - - - - - 2 - 3 - GTK_FILL - - - - - True - False - - - 1 - 2 - GTK_FILL - - - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - True - False - 0 - 1 - 4 - <b>Name</b> - True - True - - - False - False - 0 - - - - - True - False - 1 - 0 - 1 - 1 - 4 - - - True - False - - - - - True - True - 1 - - - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 12 - False - False - True - True - 4 - True - - - False - True - 2 - - - - - False - False - 0 - - - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 63 - False - - - False - True - 1 - - - - - 3 - 4 - 8 - - - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - True - False - 0 - 4 - <b>Name</b> - True - True - - - False - False - 0 - - - - - True - True - - False - False - False - True - True - - - True - True - 1 - - - - - False - False - 0 - - - - - 5 - 6 - 8 - - - - - - diff --git a/src/gui/ingen_gui_lv2.cpp b/src/gui/ingen_gui_lv2.cpp deleted file mode 100644 index 57881741..00000000 --- a/src/gui/ingen_gui_lv2.cpp +++ /dev/null @@ -1,209 +0,0 @@ -/* - This file is part of Ingen. - Copyright 2007-2015 David Robillard - - 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 - Software Foundation, either version 3 of the License, or 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 Affero General Public License for details. - - You should have received a copy of the GNU Affero General Public License - along with Ingen. If not, see . -*/ - -#include "ingen/AtomReader.hpp" -#include "ingen/AtomSink.hpp" -#include "ingen/AtomWriter.hpp" -#include "ingen/World.hpp" -#include "ingen/client/ClientStore.hpp" -#include "ingen/client/GraphModel.hpp" -#include "ingen/client/SigClientInterface.hpp" -#include "ingen/ingen.h" -#include "ingen/runtime_paths.hpp" -#include "ingen/types.hpp" -#include "lv2/lv2plug.in/ns/extensions/ui/ui.h" - -#include "App.hpp" -#include "GraphBox.hpp" - -#define INGEN_LV2_UI_URI INGEN_NS "GraphUIGtk2" - -namespace Ingen { - -/** A sink that writes atoms to a port via the UI extension. */ -struct IngenLV2AtomSink : public AtomSink { - IngenLV2AtomSink(URIs& uris, - LV2UI_Write_Function ui_write, - LV2UI_Controller ui_controller) - : _uris(uris) - , _ui_write(ui_write) - , _ui_controller(ui_controller) - {} - - bool write(const LV2_Atom* atom, int32_t default_id) { - _ui_write(_ui_controller, - 0, - lv2_atom_total_size(atom), - _uris.atom_eventTransfer, - atom); - return true; - } - - URIs& _uris; - LV2UI_Write_Function _ui_write; - LV2UI_Controller _ui_controller; -}; - -struct IngenLV2UI { - IngenLV2UI() - : argc(0) - , argv(nullptr) - , forge(nullptr) - , world(nullptr) - , sink(nullptr) - {} - - int argc; - char** argv; - Forge* forge; - World* world; - IngenLV2AtomSink* sink; - SPtr app; - SPtr view; - SPtr engine; - SPtr reader; - SPtr client; -}; - -} // namespace Ingen - -static LV2UI_Handle -instantiate(const LV2UI_Descriptor* descriptor, - const char* plugin_uri, - const char* bundle_path, - LV2UI_Write_Function write_function, - LV2UI_Controller controller, - LV2UI_Widget* widget, - const LV2_Feature* const* features) -{ -#if __cplusplus >= 201103L - using Ingen::SPtr; -#endif - - Ingen::set_bundle_path(bundle_path); - - Ingen::IngenLV2UI* ui = new Ingen::IngenLV2UI(); - - LV2_URID_Map* map = nullptr; - LV2_URID_Unmap* unmap = nullptr; - LV2_Log_Log* log = nullptr; - for (int i = 0; features[i]; ++i) { - if (!strcmp(features[i]->URI, LV2_URID__map)) { - map = (LV2_URID_Map*)features[i]->data; - } else if (!strcmp(features[i]->URI, LV2_URID__unmap)) { - unmap = (LV2_URID_Unmap*)features[i]->data; - } else if (!strcmp(features[i]->URI, LV2_LOG__log)) { - log = (LV2_Log_Log*)features[i]->data; - } - } - - ui->world = new Ingen::World(map, unmap, log); - ui->forge = new Ingen::Forge(ui->world->uri_map()); - - ui->world->load_configuration(ui->argc, ui->argv); - - if (!ui->world->load_module("client")) { - delete ui; - return nullptr; - } - - ui->sink = new Ingen::IngenLV2AtomSink( - ui->world->uris(), write_function, controller); - - // Set up an engine interface that writes LV2 atoms - ui->engine = SPtr( - new Ingen::AtomWriter( - ui->world->uri_map(), ui->world->uris(), *ui->sink)); - - ui->world->set_interface(ui->engine); - - // Create App and client - ui->app = Ingen::GUI::App::create(ui->world); - ui->client = SPtr( - new Ingen::Client::SigClientInterface()); - ui->app->set_is_plugin(true); - ui->app->attach(ui->client); - - ui->reader = SPtr( - new Ingen::AtomReader(ui->world->uri_map(), - ui->world->uris(), - ui->world->log(), - *ui->client.get())); - - // Create empty root graph model - Ingen::Properties props; - props.emplace(ui->app->uris().rdf_type, - Ingen::Property(ui->app->uris().ingen_Graph)); - ui->app->store()->put(Ingen::main_uri(), props); - - // Create a GraphBox for the root and set as the UI widget - SPtr root = - Ingen::dynamic_ptr_cast( - ui->app->store()->object(Raul::Path("/"))); - ui->view = Ingen::GUI::GraphBox::create(*ui->app, root); - ui->view->unparent(); - *widget = ui->view->gobj(); - - // Request the actual root graph - ui->world->interface()->get(Ingen::main_uri()); - - return ui; -} - -static void -cleanup(LV2UI_Handle handle) -{ - Ingen::IngenLV2UI* ui = (Ingen::IngenLV2UI*)handle; - delete ui; -} - -static void -port_event(LV2UI_Handle handle, - uint32_t port_index, - uint32_t buffer_size, - uint32_t format, - const void* buffer) -{ - Ingen::IngenLV2UI* ui = (Ingen::IngenLV2UI*)handle; - const LV2_Atom* atom = (const LV2_Atom*)buffer; - ui->reader->write(atom); -} - -static const void* -extension_data(const char* uri) -{ - return nullptr; -} - -static const LV2UI_Descriptor descriptor = { - INGEN_LV2_UI_URI, - instantiate, - cleanup, - port_event, - extension_data -}; - -LV2_SYMBOL_EXPORT -const LV2UI_Descriptor* -lv2ui_descriptor(uint32_t index) -{ - switch (index) { - case 0: - return &descriptor; - default: - return nullptr; - } -} diff --git a/src/gui/ingen_style.rc b/src/gui/ingen_style.rc deleted file mode 100644 index 4763e12a..00000000 --- a/src/gui/ingen_style.rc +++ /dev/null @@ -1,155 +0,0 @@ -style "ingen-default" -{ - GtkMenuItem::selected_shadow_type = out - - GtkWidget::interior_focus = 1 - GtkWidget::focus_padding = 1 - - GtkButton::default_border = { 0, 0, 0, 0 } - GtkButton::default_outside_border = { 0, 0, 0, 0 } - - GtkCheckButton::indicator_size = 12 - GtkExpander::expander_size = 16 - GtkMenuBar::internal-padding = 0 - GtkPaned::handle_size = 6 - GtkRange::slider_width = 15 - GtkRange::stepper_size = 15 - GtkRange::trough_border = 0 - GtkScrollbar::min_slider_length = 30 - GtkTreeView::expander_size = 14 - GtkTreeView::odd_row_color = "#343" - - xthickness = 1 - ythickness = 1 - - fg[NORMAL] = "#B8BBB9" - fg[PRELIGHT] = "#B8BBB9" - fg[ACTIVE] = "#B8BBB9" - fg[SELECTED] = "#B8BBB9" - fg[INSENSITIVE] = "#48494B" - - bg[NORMAL] = "#1E2224" - bg[PRELIGHT] = "#333537" - bg[ACTIVE] = "#333537" - bg[SELECTED] = "#00A150" - bg[INSENSITIVE] = "#1E2224" - - base[NORMAL] = "#111" - base[PRELIGHT] = "#222" - base[ACTIVE] = "#0A2" - base[SELECTED] = "#0A2" - base[INSENSITIVE] = "#444" - - text[NORMAL] = "#FFF" - text[PRELIGHT] = "#FFF" - text[ACTIVE] = "#FFF" - text[SELECTED] = "#FFF" - text[INSENSITIVE] = "#666" - - engine "clearlooks" - { - contrast = 1.0 - } -} - -style "ingen-progressbar" = "ingen-default" -{ - xthickness = 1 - ythickness = 1 -} - -style "ingen-wide" = "ingen-default" -{ - xthickness = 2 - ythickness = 2 -} - -style "ingen-notebook" = "ingen-wide" -{ - bg[NORMAL] = "#383B39" - bg[ACTIVE] = "#383B39" -} - -style "ingen-tasklist" = "ingen-default" -{ - xthickness = 5 - ythickness = 3 -} - -style "ingen-menu" = "ingen-default" -{ - xthickness = 5 - ythickness = 5 - bg[NORMAL] = "#262626" -} - -style "ingen-menu-item" = "ingen-default" -{ - xthickness = 2 - ythickness = 3 -} - -style "ingen-menu-itembar" = "ingen-default" -{ - xthickness = 3 - ythickness = 3 -} - -style "ingen-tree" = "ingen-default" -{ - xthickness = 2 - ythickness = 2 -} - -style "ingen-frame-title" = "ingen-default" -{ - fg[NORMAL] = "#B8BBB9" -} - -style "ingen-panel" = "ingen-default" -{ - xthickness = 3 - ythickness = 3 -} - -style "ingen-tooltips" = "ingen-default" -{ - xthickness = 4 - ythickness = 4 - bg[NORMAL] = "#585B59" -} - -style "ingen-combo" = "ingen-default" -{ - xthickness = 1 - ythickness = 2 -} - -class "*Ingen*GtkWidget" style : highest "ingen-default" -class "*Ingen*GtkButton" style : highest "ingen-wide" -class "*Ingen*GtkRange" style : highest "ingen-wide" -class "*Ingen*GtkFrame" style : highest "ingen-wide" -class "*Ingen*GtkStatusbar" style : highest "ingen-wide" -class "*Ingen*GtkMenu" style : highest "ingen-menu" -class "*Ingen*GtkMenuItem" style : highest "ingen-menu-item" -widget_class "*Ingen*MenuItem.*" style : highest "ingen-menu-item" -widget_class "*Ingen*.GtkAccelMenuItem.*" style : highest "ingen-menu-item" -widget_class "*Ingen*.GtkRadioMenuItem.*" style : highest "ingen-menu-item" -widget_class "*Ingen*.GtkCheckMenuItem.*" style : highest "ingen-menu-item" -widget_class "*Ingen*.GtkImageMenuItem.*" style : highest "ingen-menu-item" -widget_class "*Ingen*.GtkSeparatorMenuItem.*" style : highest "ingen-menu-item" -class "*Ingen*GtkEntry" style : highest "ingen-wide" -widget_class "*Ingen*.tooltips.*.GtkToggleButton" style : highest "ingen-tasklist" -widget_class "*Ingen*.GtkTreeView.GtkButton" style : highest "ingen-tree" -widget_class "*Ingen*.GtkCTree.GtkButton" style : highest "ingen-tree" -widget_class "*Ingen*.GtkList.GtkButton" style : highest "ingen-tree" -widget_class "*Ingen*.GtkCList.GtkButton" style : highest "ingen-tree" -widget_class "*Ingen*.GtkFrame.GtkLabel" style : highest "ingen-frame-title" -widget_class "*Ingen*BasePWidget.GtkEventBox.GtkTable.GtkFrame" style : highest "ingen-panel" -widget "gtk-tooltips" style : highest "ingen-tooltips" -class "*Ingen*GtkNotebook" style : highest "ingen-notebook" -class "*Ingen*GtkProgressBar" style : highest "ingen-progressbar" -widget_class "*Ingen*.GtkComboBox.GtkButton" style : highest "ingen-combo" -widget_class "*Ingen*.GtkCombo.GtkButton" style : highest "ingen-combo" - -widget "*Ingen*" style : highest "ingen-default" diff --git a/src/gui/rgba.hpp b/src/gui/rgba.hpp deleted file mode 100644 index dae3f179..00000000 --- a/src/gui/rgba.hpp +++ /dev/null @@ -1,58 +0,0 @@ -/* - This file is part of Ingen. - Copyright 2007-2016 David Robillard - - 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 - Software Foundation, either version 3 of the License, or 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 Affero General Public License for details. - - You should have received a copy of the GNU Affero General Public License - along with Ingen. If not, see . -*/ - -#ifndef INGEN_GUI_RGBA_HPP -#define INGEN_GUI_RGBA_HPP - -#include - -namespace Ingen { -namespace GUI { - -static inline uint32_t -rgba_to_uint(uint8_t r, uint8_t g, uint8_t b, uint8_t a) -{ - return ((((uint32_t)(r)) << 24) | - (((uint32_t)(g)) << 16) | - (((uint32_t)(b)) << 8) | - (((uint32_t)(a)))); -} - -static inline uint8_t -mono_interpolate(uint8_t v1, uint8_t v2, float f) -{ - return ((int)rint((v2) * (f) + (v1) * (1 - (f)))); -} - -#define RGBA_R(x) (((uint32_t)(x)) >> 24) -#define RGBA_G(x) ((((uint32_t)(x)) >> 16) & 0xFF) -#define RGBA_B(x) ((((uint32_t)(x)) >> 8) & 0xFF) -#define RGBA_A(x) (((uint32_t)(x)) & 0xFF) - -static inline uint32_t -rgba_interpolate(uint32_t c1, uint32_t c2, float f) -{ - return rgba_to_uint( - mono_interpolate(RGBA_R(c1), RGBA_R(c2), f), - mono_interpolate(RGBA_G(c1), RGBA_G(c2), f), - mono_interpolate(RGBA_B(c1), RGBA_B(c2), f), - mono_interpolate(RGBA_A(c1), RGBA_A(c2), f)); -} - -} // namespace GUI -} // namespace Ingen - -#endif // INGEN_GUI_RGBA_HPP diff --git a/src/gui/wscript b/src/gui/wscript deleted file mode 100644 index e4d777ad..00000000 --- a/src/gui/wscript +++ /dev/null @@ -1,111 +0,0 @@ -#!/usr/bin/env python -import waflib.extras.autowaf as autowaf -import waflib.Utils as Utils -import waflib.Options as Options - -def options(ctx): - opt = ctx.get_option_group('Configuration options') - opt.add_option('--light-theme', action='store_true', dest='light_theme', - help='use light coloured theme') - -def configure(conf): - autowaf.check_pkg(conf, 'glibmm-2.4', uselib_store='GLIBMM', - atleast_version='2.14.0', mandatory=False) - autowaf.check_pkg(conf, 'gthread-2.0', uselib_store='GTHREAD', - atleast_version='2.14.0', mandatory=False) - autowaf.check_pkg(conf, 'gtkmm-2.4', uselib_store='GTKMM', - atleast_version='2.14.0', mandatory=False) - autowaf.check_pkg(conf, 'ganv-1', uselib_store='GANV', - atleast_version='1.5.4', mandatory=False) - if not Options.options.no_webkit: - autowaf.check_pkg(conf, 'webkit-1.0', uselib_store='WEBKIT', - atleast_version='1.4.0', mandatory=False) - - if conf.env.HAVE_GANV and conf.env.HAVE_GTKMM: - autowaf.define(conf, 'INGEN_BUILD_GUI', 1) - - if Options.options.light_theme: - autowaf.define(conf, 'INGEN_USE_LIGHT_THEME', 1) - -def build(bld): - obj = bld(features = 'cxx cxxshlib', - export_includes = ['../..'], - includes = ['../..'], - name = 'libingen_gui', - target = 'ingen_gui', - install_path = '${LIBDIR}', - use = 'libingen libingen_client') - autowaf.use_lib(bld, obj, ''' - GANV - GLADEMM - GLIBMM - GNOMECANVAS - GTKMM - LILV - LV2 - RAUL - SIGCPP - SORD - SOUP - SUIL - WEBKIT - ''') - - obj.source = ''' - App.cpp - Arc.cpp - BreadCrumbs.cpp - ConnectWindow.cpp - GraphBox.cpp - GraphCanvas.cpp - GraphPortModule.cpp - GraphTreeWindow.cpp - GraphView.cpp - GraphWindow.cpp - LoadGraphWindow.cpp - LoadPluginWindow.cpp - MessagesWindow.cpp - NewSubgraphWindow.cpp - NodeMenu.cpp - NodeModule.cpp - ObjectMenu.cpp - PluginMenu.cpp - Port.cpp - PortMenu.cpp - PropertiesWindow.cpp - RDFS.cpp - RenameWindow.cpp - Style.cpp - SubgraphModule.cpp - ThreadedLoader.cpp - URIEntry.cpp - WidgetFactory.cpp - WindowFactory.cpp - ingen_gui.cpp - ''' - - # XML UI definition - bld(features = 'subst', - source = 'ingen_gui.ui', - target = '../../ingen_gui.ui', - install_path = '${DATADIR}/ingen', - chmod = Utils.O755, - INGEN_VERSION = bld.env.INGEN_VERSION) - - # Gtk style - bld(features = 'subst', - is_copy = True, - source = 'ingen_style.rc', - target = '../../ingen_style.rc', - install_path = '${DATADIR}/ingen', - chmod = Utils.O755) - - # LV2 UI - obj = bld(features = 'cxx cxxshlib', - source = 'ingen_gui_lv2.cpp', - includes = ['.', '../..'], - name = 'ingen_gui_lv2', - target = 'ingen_gui_lv2', - install_path = '${LV2DIR}/ingen.lv2/', - use = 'libingen libingen_gui') - autowaf.use_lib(bld, obj, 'LV2 SERD SORD LILV RAUL GLIBMM GTKMM') -- cgit v1.2.1