Zoom Full feature in FlowCanvas/Ingenuity.
Fix for reattaching to running engine (reponse ID bug). More GUI work. git-svn-id: http://svn.drobilla.net/lad@126 a436a847-0d15-0410-975c-d299462d15a1
This commit is contained in:
parent
6f9b8bde52
commit
dfe695186d
|
@ -77,9 +77,10 @@ public:
|
|||
list<Module*>& selected_modules() { return m_selected_modules; }
|
||||
list<Connection*>& selected_connections() { return m_selected_connections; }
|
||||
|
||||
float zoom() { return m_zoom; }
|
||||
void zoom(float pix_per_unit);
|
||||
|
||||
double get_zoom() { return m_zoom; }
|
||||
void set_zoom(double pix_per_unit);
|
||||
void zoom_full();
|
||||
|
||||
double width() const { return m_width; }
|
||||
double height() const { return m_height; }
|
||||
|
||||
|
@ -132,7 +133,7 @@ private:
|
|||
Port* m_selected_port; ///< Selected port (hilited red from clicking once)
|
||||
Port* m_connect_port; ///< Port for which a connection is being made (if applicable)
|
||||
|
||||
float m_zoom; ///< Current zoom level
|
||||
double m_zoom; ///< Current zoom level
|
||||
double m_width;
|
||||
double m_height;
|
||||
|
||||
|
|
|
@ -43,7 +43,7 @@ public:
|
|||
|
||||
void destroy_all_ports(bool resize = true);
|
||||
|
||||
void zoom(float z);
|
||||
void zoom(double z);
|
||||
void resize();
|
||||
|
||||
void move(double dx, double dy);
|
||||
|
@ -87,7 +87,7 @@ protected:
|
|||
virtual void on_double_click(GdkEventButton* ev) {}
|
||||
virtual void on_middle_click(GdkEventButton* ev) {}
|
||||
virtual void on_right_click(GdkEventButton* ev) {}
|
||||
|
||||
|
||||
bool m_add_to_canvas;
|
||||
double m_border_width;
|
||||
double m_width;
|
||||
|
|
|
@ -15,7 +15,9 @@
|
|||
*/
|
||||
|
||||
#include "FlowCanvas.h"
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cmath>
|
||||
#include <map>
|
||||
#include <iostream>
|
||||
#include <cmath>
|
||||
|
@ -73,18 +75,16 @@ FlowCanvas::on_map()
|
|||
{
|
||||
Gnome::Canvas::Canvas::on_map();
|
||||
assert(get_window());
|
||||
get_window()->set_cursor(Gdk::Cursor(Gdk::HAND1));
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
FlowCanvas::zoom(float pix_per_unit)
|
||||
FlowCanvas::set_zoom(double pix_per_unit)
|
||||
{
|
||||
// Round to .25
|
||||
m_zoom = static_cast<int>(pix_per_unit*4) / 4.0;
|
||||
if (m_zoom < 0.25)
|
||||
m_zoom = 0.25;
|
||||
|
||||
if (m_zoom == pix_per_unit)
|
||||
return;
|
||||
|
||||
m_zoom = pix_per_unit;
|
||||
set_pixels_per_unit(m_zoom);
|
||||
|
||||
for (ModuleMap::iterator m = m_modules.begin(); m != m_modules.end(); ++m)
|
||||
|
@ -92,6 +92,49 @@ FlowCanvas::zoom(float pix_per_unit)
|
|||
}
|
||||
|
||||
|
||||
void
|
||||
FlowCanvas::zoom_full()
|
||||
{
|
||||
int win_width, win_height;
|
||||
Glib::RefPtr<Gdk::Window> win = get_window();
|
||||
win->get_size(win_width, win_height);
|
||||
|
||||
// Box containing all canvas items
|
||||
double left = DBL_MAX;
|
||||
double right = DBL_MIN;
|
||||
double top = DBL_MIN;
|
||||
double bottom = DBL_MAX;
|
||||
|
||||
for (ModuleMap::iterator m = m_modules.begin(); m != m_modules.end(); ++m) {
|
||||
Module* const mod = (*m).second;
|
||||
if (mod->property_x() < left)
|
||||
left = mod->property_x();
|
||||
if (mod->property_x() + mod->width() > right)
|
||||
right = mod->property_x() + mod->width();
|
||||
if (mod->property_y() < bottom)
|
||||
bottom = mod->property_y();
|
||||
if (mod->property_y() + mod->height() > top)
|
||||
top = mod->property_y() + mod->height();
|
||||
}
|
||||
const double bound_width = right - left;
|
||||
const double bound_height = top - bottom;
|
||||
|
||||
static const double pad = 4.0;
|
||||
|
||||
const double new_zoom = std::min(
|
||||
((double)win_width / (double)(right - left + pad*2.0)),
|
||||
((double)win_height / (double)(top - bottom + pad*2.0)));
|
||||
|
||||
set_zoom(new_zoom);
|
||||
|
||||
int scroll_x, scroll_y;
|
||||
w2c(lrintf(left - pad), lrintf(bottom - pad), scroll_x, scroll_y);
|
||||
|
||||
scroll_to(scroll_x, scroll_y);
|
||||
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
FlowCanvas::clear_selection()
|
||||
{
|
||||
|
|
|
@ -233,9 +233,9 @@ Module::module_event(GdkEvent* event)
|
|||
|
||||
|
||||
void
|
||||
Module::zoom(float z)
|
||||
Module::zoom(double z)
|
||||
{
|
||||
m_canvas_title.property_size() = static_cast<int>(roundf(10000.0f * z));
|
||||
m_canvas_title.property_size() = static_cast<int>(floor((double)10000.0f * z));
|
||||
for (PortList::iterator p = m_ports.begin(); p != m_ports.end(); ++p)
|
||||
(*p)->zoom(z);
|
||||
}
|
||||
|
|
|
@ -66,7 +66,7 @@ OSCEngineReceiver::OSCEngineReceiver(CountedPtr<Engine> engine, size_t queue_siz
|
|||
}
|
||||
|
||||
// For debugging, print all incoming OSC messages
|
||||
//lo_server_add_method(_server, NULL, NULL, generic_cb, NULL);
|
||||
lo_server_add_method(_server, NULL, NULL, generic_cb, NULL);
|
||||
|
||||
// Set response address for this message.
|
||||
// It's important this is first and returns nonzero.
|
||||
|
@ -222,7 +222,7 @@ OSCEngineReceiver::set_response_address_cb(const char* path, const char* types,
|
|||
//cerr << "** osc responder\n";
|
||||
|
||||
if (!strcmp(url, me->_osc_responder->url())) {
|
||||
// Nice one, same address
|
||||
// Nice one, same address, do nothing (just set the ID below)
|
||||
//cerr << "** Using cached response address, hooray" << endl;
|
||||
} else {
|
||||
// Shitty deal, make a new one
|
||||
|
@ -231,6 +231,7 @@ OSCEngineReceiver::set_response_address_cb(const char* path, const char* types,
|
|||
new OSCResponder(me->_engine->broadcaster(), id, url));
|
||||
|
||||
me->set_responder(me->_osc_responder);
|
||||
|
||||
// (responder takes ownership of url, no leak)
|
||||
}
|
||||
|
||||
|
@ -241,6 +242,8 @@ OSCEngineReceiver::set_response_address_cb(const char* path, const char* types,
|
|||
me->set_responder(me->_osc_responder);
|
||||
//cerr << "** Setting response address to " << url << "(2)" << endl;
|
||||
}
|
||||
|
||||
me->set_next_response_id(id);
|
||||
|
||||
// Don't respond
|
||||
} else {
|
||||
|
|
|
@ -189,7 +189,7 @@ QueuedEngineInterface::destroy(const string& path)
|
|||
void
|
||||
QueuedEngineInterface::clear_patch(const string& patch_path)
|
||||
{
|
||||
push_queued(new ClearPatchEvent(*_engine.get(), _responder, now(), patch_path));
|
||||
push_queued(new ClearPatchEvent(*_engine.get(), _responder, now(), this, patch_path));
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -80,7 +80,10 @@ protected:
|
|||
QueuedEventSource* source = NULL)
|
||||
: Event(engine, responder, time)
|
||||
, _pre_processed(false), _blocking(blocking), _source(source)
|
||||
{}
|
||||
{
|
||||
if (blocking)
|
||||
assert(_source);
|
||||
}
|
||||
|
||||
// NULL event base (for internal events only!)
|
||||
QueuedEvent(Engine& engine)
|
||||
|
|
|
@ -30,8 +30,8 @@
|
|||
namespace Ingen {
|
||||
|
||||
|
||||
ClearPatchEvent::ClearPatchEvent(Engine& engine, CountedPtr<Responder> responder, SampleCount timestamp, const string& patch_path)
|
||||
: QueuedEvent(engine, responder, true),
|
||||
ClearPatchEvent::ClearPatchEvent(Engine& engine, CountedPtr<Responder> responder, FrameTime time, QueuedEventSource* source, const string& patch_path)
|
||||
: QueuedEvent(engine, responder, time, true, source),
|
||||
m_patch_path(patch_path),
|
||||
m_patch(NULL),
|
||||
m_process(false)
|
||||
|
|
|
@ -35,7 +35,7 @@ class Patch;
|
|||
class ClearPatchEvent : public QueuedEvent
|
||||
{
|
||||
public:
|
||||
ClearPatchEvent(Engine& engine, CountedPtr<Responder> responder, SampleCount timestamp, const string& patch_path);
|
||||
ClearPatchEvent(Engine& engine, CountedPtr<Responder> responder, FrameTime time, QueuedEventSource* source, const string& patch_path);
|
||||
|
||||
void pre_process();
|
||||
void execute(SampleCount nframes, FrameTime start, FrameTime end);
|
||||
|
|
|
@ -34,8 +34,8 @@
|
|||
namespace Ingen {
|
||||
|
||||
|
||||
DestroyEvent::DestroyEvent(Engine& engine, CountedPtr<Responder> responder, FrameTime time, QueuedEventSource* source, const string& path, bool lock_mutex)
|
||||
: QueuedEvent(engine, responder, time, true, source),
|
||||
DestroyEvent::DestroyEvent(Engine& engine, CountedPtr<Responder> responder, FrameTime time, QueuedEventSource* source, const string& path, bool block)
|
||||
: QueuedEvent(engine, responder, time, source, source),
|
||||
m_path(path),
|
||||
m_node(NULL),
|
||||
m_patch_listnode(NULL),
|
||||
|
@ -47,8 +47,8 @@ DestroyEvent::DestroyEvent(Engine& engine, CountedPtr<Responder> responder, Fram
|
|||
}
|
||||
|
||||
|
||||
DestroyEvent::DestroyEvent(Engine& engine, CountedPtr<Responder> responder, SampleCount timestamp, Node* node, bool lock_mutex)
|
||||
: QueuedEvent(engine, responder, true),
|
||||
DestroyEvent::DestroyEvent(Engine& engine, CountedPtr<Responder> responder, FrameTime time, QueuedEventSource* source, Node* node, bool block)
|
||||
: QueuedEvent(engine, responder, block, source),
|
||||
m_path(node->path()),
|
||||
m_node(node),
|
||||
m_patch_listnode(NULL),
|
||||
|
|
|
@ -44,8 +44,8 @@ class DisconnectPortEvent;
|
|||
class DestroyEvent : public QueuedEvent
|
||||
{
|
||||
public:
|
||||
DestroyEvent(Engine& engine, CountedPtr<Responder> responder, FrameTime timestamp, QueuedEventSource* source, const string& path, bool lock_mutex = true);
|
||||
DestroyEvent(Engine& engine, CountedPtr<Responder> responder, FrameTime timestamp, Node* node, bool lock_mutex = true);
|
||||
DestroyEvent(Engine& engine, CountedPtr<Responder> responder, FrameTime timestamp, QueuedEventSource* source, const string& path, bool block = true);
|
||||
DestroyEvent(Engine& engine, CountedPtr<Responder> responder, FrameTime timestamp, QueuedEventSource* source, Node* node, bool block = true);
|
||||
~DestroyEvent();
|
||||
|
||||
void pre_process();
|
||||
|
|
|
@ -47,7 +47,7 @@ LoadPluginWindow::LoadPluginWindow(BaseObjectType* cobject, const Glib::RefPtr<G
|
|||
xml->get_widget("load_plugin_clear_button", m_clear_button);
|
||||
xml->get_widget("load_plugin_add_button", m_add_button);
|
||||
xml->get_widget("load_plugin_close_button", m_close_button);
|
||||
//xml->get_widget("load_plugin_ok_button", m_ok_button);
|
||||
//xml->get_widget("load_plugin_ok_button", m_add_button);
|
||||
|
||||
xml->get_widget("load_plugin_filter_combo", m_filter_combo);
|
||||
xml->get_widget("load_plugin_search_entry", m_search_entry);
|
||||
|
@ -94,10 +94,11 @@ LoadPluginWindow::LoadPluginWindow(BaseObjectType* cobject, const Glib::RefPtr<G
|
|||
m_clear_button->signal_clicked().connect( sigc::mem_fun(this, &LoadPluginWindow::clear_clicked));
|
||||
m_add_button->signal_clicked().connect( sigc::mem_fun(this, &LoadPluginWindow::add_clicked));
|
||||
m_close_button->signal_clicked().connect( sigc::mem_fun(this, &LoadPluginWindow::close_clicked));
|
||||
//m_ok_button->signal_clicked().connect( sigc::mem_fun(this, &LoadPluginWindow::ok_clicked));
|
||||
//m_add_button->signal_clicked().connect( sigc::mem_fun(this, &LoadPluginWindow::ok_clicked));
|
||||
m_plugins_treeview->signal_row_activated().connect(sigc::mem_fun(this, &LoadPluginWindow::plugin_activated));
|
||||
m_search_entry->signal_activate().connect( sigc::mem_fun(this, &LoadPluginWindow::add_clicked));
|
||||
m_search_entry->signal_changed().connect( sigc::mem_fun(this, &LoadPluginWindow::filter_changed));
|
||||
m_node_name_entry->signal_changed().connect( sigc::mem_fun(this, &LoadPluginWindow::name_changed));
|
||||
|
||||
m_selection = m_plugins_treeview->get_selection();
|
||||
m_selection->signal_changed().connect(sigc::mem_fun(this, &LoadPluginWindow::plugin_selection_changed));
|
||||
|
@ -106,6 +107,29 @@ LoadPluginWindow::LoadPluginWindow(BaseObjectType* cobject, const Glib::RefPtr<G
|
|||
}
|
||||
|
||||
|
||||
/** 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()
|
||||
{
|
||||
string name = m_node_name_entry->get_text();
|
||||
if (!Path::is_valid_name(name)) {
|
||||
//m_message_label->set_text("Name contains invalid characters.");
|
||||
m_add_button->property_sensitive() = false;
|
||||
} else if (m_patch_controller->patch_model()->get_node(name)) {
|
||||
//m_message_label->set_text("An object already exists with that name.");
|
||||
m_add_button->property_sensitive() = false;
|
||||
} else if (name.length() == 0) {
|
||||
//m_message_label->set_text("");
|
||||
m_add_button->property_sensitive() = false;
|
||||
} else {
|
||||
//m_message_label->set_text("");
|
||||
m_add_button->property_sensitive() = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** Sets the patch controller for this window and initializes everything.
|
||||
*
|
||||
* This function MUST be called before using the window in any way!
|
||||
|
|
|
@ -107,6 +107,7 @@ private:
|
|||
//void ok_clicked();
|
||||
void filter_changed();
|
||||
void clear_clicked();
|
||||
void name_changed();
|
||||
|
||||
void plugin_activated(const Gtk::TreeModel::Path& path, Gtk::TreeViewColumn* col);
|
||||
void plugin_selection_changed();
|
||||
|
|
|
@ -423,9 +423,9 @@ PatchController::add_node(CountedPtr<NodeModel> object)
|
|||
node->y(y);
|
||||
|
||||
// Set zoom to 1.0 so module isn't messed up (Death to GnomeCanvas)
|
||||
float old_zoom = m_patch_view->canvas()->zoom();
|
||||
float old_zoom = m_patch_view->canvas()->get_zoom();
|
||||
if (old_zoom != 1.0)
|
||||
m_patch_view->canvas()->zoom(1.0);
|
||||
m_patch_view->canvas()->set_zoom(1.0);
|
||||
|
||||
nc->create_module(m_patch_view->canvas());
|
||||
assert(nc->module());
|
||||
|
@ -433,7 +433,7 @@ PatchController::add_node(CountedPtr<NodeModel> object)
|
|||
|
||||
// Reset zoom
|
||||
if (old_zoom != 1.0) {
|
||||
m_patch_view->canvas()->zoom(old_zoom);
|
||||
m_patch_view->canvas()->set_zoom(old_zoom);
|
||||
nc->module()->zoom(old_zoom);
|
||||
}
|
||||
}
|
||||
|
@ -496,17 +496,13 @@ PatchController::add_port(CountedPtr<PortModel> pm)
|
|||
if (m_patch_view != NULL) {
|
||||
|
||||
// Set zoom to 1.0 so module isn't messed up (Death to GnomeCanvas)
|
||||
float old_zoom = m_patch_view->canvas()->zoom();
|
||||
if (old_zoom != 1.0)
|
||||
m_patch_view->canvas()->zoom(1.0);
|
||||
float old_zoom = m_patch_view->canvas()->get_zoom();
|
||||
m_patch_view->canvas()->set_zoom(1.0);
|
||||
|
||||
pc->create_module(m_patch_view->canvas());
|
||||
|
||||
// Reset zoom
|
||||
if (old_zoom != 1.0) {
|
||||
m_patch_view->canvas()->zoom(old_zoom);
|
||||
pc->module()->zoom(old_zoom);
|
||||
}
|
||||
pc->module()->zoom(old_zoom);
|
||||
}
|
||||
|
||||
if (m_control_window != NULL) {
|
||||
|
|
|
@ -42,12 +42,16 @@ PatchView::PatchView(BaseObjectType* cobject, const Glib::RefPtr<Gnome::Glade::X
|
|||
{
|
||||
property_visible() = false;
|
||||
|
||||
xml->get_widget("patch_view_scrolledwindow", _canvas_scrolledwindow);
|
||||
xml->get_widget("patch_view_breadcrumb_container", _breadcrumb_container);
|
||||
xml->get_widget("patch_view_process_but", _process_but);
|
||||
xml->get_widget("patch_view_poly_spin", _poly_spin);
|
||||
xml->get_widget("patch_view_clear_but", _clear_but);
|
||||
xml->get_widget("patch_view_destroy_but", _destroy_but);
|
||||
xml->get_widget("patch_view_refresh_but", _refresh_but);
|
||||
xml->get_widget("patch_view_save_but", _save_but);
|
||||
xml->get_widget("patch_view_zoom_full_but", _zoom_full_but);
|
||||
xml->get_widget("patch_view_zoom_normal_but", _zoom_normal_but);
|
||||
xml->get_widget("patch_view_poly_spin", _poly_spin);
|
||||
xml->get_widget("patch_view_process_but", _process_but);
|
||||
xml->get_widget("patch_view_breadcrumb_container", _breadcrumb_container);
|
||||
xml->get_widget("patch_view_scrolledwindow", _canvas_scrolledwindow);
|
||||
|
||||
_process_but->signal_toggled().connect(sigc::mem_fun(this, &PatchView::process_toggled));
|
||||
}
|
||||
|
@ -64,7 +68,7 @@ PatchView::patch_controller(PatchController* pc)
|
|||
_patch = pc;
|
||||
|
||||
_canvas = new OmFlowCanvas(pc, 1600*2, 1200*2);
|
||||
|
||||
|
||||
_canvas_scrolledwindow->add(*_canvas);
|
||||
//_canvas->show();
|
||||
//_canvas_scrolledwindow->show();
|
||||
|
@ -75,6 +79,9 @@ PatchView::patch_controller(PatchController* pc)
|
|||
|
||||
pc->patch_model()->enabled_sig.connect(sigc::mem_fun(this, &PatchView::enable));
|
||||
pc->patch_model()->disabled_sig.connect(sigc::mem_fun(this, &PatchView::disable));
|
||||
|
||||
_zoom_normal_but->signal_clicked().connect(sigc::bind(sigc::mem_fun(static_cast<FlowCanvas*>(_canvas), &FlowCanvas::set_zoom), 1.0));
|
||||
_zoom_full_but->signal_clicked().connect(sigc::mem_fun(static_cast<FlowCanvas*>(_canvas), &FlowCanvas::zoom_full));
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -68,6 +68,8 @@ public:
|
|||
void enable();
|
||||
void disable();
|
||||
|
||||
void zoom_full();
|
||||
|
||||
private:
|
||||
PatchController* _patch;
|
||||
OmFlowCanvas* _canvas;
|
||||
|
|
|
@ -205,9 +205,9 @@ Patchage::idle_callback()
|
|||
void
|
||||
Patchage::zoom_changed()
|
||||
{
|
||||
const float z = m_zoom_slider->get_value();
|
||||
const double z = m_zoom_slider->get_value();
|
||||
|
||||
m_canvas->zoom(z);
|
||||
m_canvas->set_zoom(z);
|
||||
m_state_manager->set_zoom(z);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue