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:
dave 2006-09-10 20:11:40 +00:00
parent 6f9b8bde52
commit dfe695186d
17 changed files with 127 additions and 47 deletions

View File

@ -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;

View File

@ -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;

View File

@ -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()
{

View File

@ -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);
}

View File

@ -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 {

View File

@ -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));
}

View File

@ -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)

View File

@ -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)

View File

@ -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);

View File

@ -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),

View File

@ -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();

View File

@ -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!

View File

@ -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();

View File

@ -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) {

View File

@ -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));
}

View File

@ -68,6 +68,8 @@ public:
void enable();
void disable();
void zoom_full();
private:
PatchController* _patch;
OmFlowCanvas* _canvas;

View File

@ -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);
}