gui: disconnect all ports of a flowcanvas box. Fixes #56
[ladish.git] / gui / canvas.cpp
blob318d8487cb83ee8536b7b84354a3e3333e9dfff6
1 /* -*- Mode: C ; c-basic-offset: 2 -*- */
2 /*
3 * LADI Session Handler (ladish)
5 * Copyright (C) 2008, 2009 Nedko Arnaudov <nedko@arnaudov.name>
6 * Copyright (C) 2007 Dave Robillard <http://drobilla.net>
8 **************************************************************************
9 * This file contains implements the canvas functionality through flowcanvas
10 **************************************************************************
12 * LADI Session Handler is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
17 * LADI Session Handler is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with LADI Session Handler. If not, see <http://www.gnu.org/licenses/>
24 * or write to the Free Software Foundation, Inc.,
25 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
28 #include <flowcanvas/Canvas.hpp>
29 #include <flowcanvas/Port.hpp>
30 #include <flowcanvas/Module.hpp>
32 #include "canvas.h"
34 class canvas_cls: public FlowCanvas::Canvas
36 public:
37 canvas_cls(
38 double width,
39 double height,
40 void (* connect_request)(void * port1_context, void * port2_context),
41 void (* disconnect_request)(void * port1_context, void * port2_context),
42 void (* module_location_changed)(void * module_context, double x, double y))
43 : FlowCanvas::Canvas(width, height)
44 , m_connect_request(connect_request)
45 , m_disconnect_request(disconnect_request)
46 , m_module_location_changed(module_location_changed)
49 virtual ~canvas_cls() {}
51 virtual void on_realize()
53 log_info("canvas_cls::on_realize");
54 FlowCanvas::Canvas::on_realize();
55 scroll_to_center();
58 virtual void on_size_allocate(Gtk::Allocation& allocation)
60 //log_info("canvas_cls::on_size_allocate");
61 FlowCanvas::Canvas::on_size_allocate(allocation);
62 if (is_realized())
64 //log_info("... realized");
65 scroll_to_center();
69 virtual void connect(boost::shared_ptr<FlowCanvas::Connectable> port1, boost::shared_ptr<FlowCanvas::Connectable> port2);
70 virtual void disconnect(boost::shared_ptr<FlowCanvas::Connectable> port1, boost::shared_ptr<FlowCanvas::Connectable> port2);
72 void (* m_connect_request)(void * port1_context, void * port2_context);
73 void (* m_disconnect_request)(void * port1_context, void * port2_context);
74 void (* m_module_location_changed)(void * module_context, double x, double y);
77 class module_cls: public FlowCanvas::Module
79 public:
80 module_cls(
81 boost::shared_ptr<FlowCanvas::Canvas> canvas,
82 const std::string& name,
83 double x,
84 double y,
85 bool show_title,
86 bool show_port_labels,
87 void * module_context)
88 : FlowCanvas::Module(canvas, name, x, y, show_title, show_port_labels)
89 , m_context(module_context)
92 virtual ~module_cls() {}
94 virtual void store_location()
96 boost::dynamic_pointer_cast<canvas_cls>(canvas().lock())->m_module_location_changed(m_context, property_x(), property_y());
99 void create_menu()
101 _menu = new Gtk::Menu();
102 _menu->items().push_back(Gtk::Menu_Helpers::MenuElem("Disconnect All", sigc::mem_fun(this, &module_cls::menu_disconnect_all)));
105 void menu_disconnect_all()
107 for (FlowCanvas::PortVector::iterator p = _ports.begin(); p != _ports.end(); p++)
109 (*p)->disconnect_all();
113 void * m_context;
116 class port_cls: public FlowCanvas::Port
118 public:
119 port_cls(
120 boost::shared_ptr<FlowCanvas::Module> module,
121 const std::string& name,
122 bool is_input,
123 uint32_t color,
124 void * port_context)
125 : FlowCanvas::Port(module, name, is_input, color)
126 , context(port_context)
129 virtual ~port_cls() {}
131 void * context;
134 bool
135 canvas_init(
136 void)
138 Gnome::Canvas::init();
139 return true;
142 bool
143 canvas_create(
144 double width,
145 double height,
146 void (* connect_request)(void * port1_context, void * port2_context),
147 void (* disconnect_request)(void * port1_context, void * port2_context),
148 void (* module_location_changed)(void * module_context, double x, double y),
149 canvas_handle * canvas_handle_ptr)
151 boost::shared_ptr<canvas_cls> * canvas;
153 canvas = new boost::shared_ptr<canvas_cls>(new canvas_cls(width, height, connect_request, disconnect_request, module_location_changed));
155 *canvas_handle_ptr = (canvas_handle)canvas;
157 return true;
160 #define canvas_ptr ((boost::shared_ptr<canvas_cls> *)canvas)
162 GtkWidget *
163 canvas_get_widget(
164 canvas_handle canvas)
166 return ((Gtk::Widget *)canvas_ptr->get())->gobj();
169 void
170 canvas_destroy(
171 canvas_handle canvas)
173 delete canvas_ptr;
176 void
177 canvas_clear(
178 canvas_handle canvas)
180 FlowCanvas::ItemList modules = canvas_ptr->get()->items(); // copy
181 for (FlowCanvas::ItemList::iterator m = modules.begin(); m != modules.end(); ++m)
183 boost::shared_ptr<FlowCanvas::Module> module = boost::dynamic_pointer_cast<FlowCanvas::Module>(*m);
184 if (!module)
185 continue;
187 FlowCanvas::PortVector ports = module->ports(); // copy
188 for (FlowCanvas::PortVector::iterator p = ports.begin(); p != ports.end(); ++p)
190 boost::shared_ptr<FlowCanvas::Port> port = boost::dynamic_pointer_cast<FlowCanvas::Port>(*p);
191 ASSERT(port != NULL);
192 module->remove_port(port);
193 port->hide();
196 ASSERT(module->ports().empty());
197 canvas_ptr->get()->remove_item(module);
201 void
202 canvas_get_size(
203 canvas_handle canvas,
204 double * width_ptr,
205 double * height_ptr)
207 *width_ptr = canvas_ptr->get()->width();
208 *height_ptr = canvas_ptr->get()->height();
211 void
212 canvas_scroll_to_center(
213 canvas_handle canvas)
215 if (canvas_ptr->get()->is_realized())
217 //log_info("realized");
218 canvas_ptr->get()->scroll_to_center();
220 else
222 //log_info("NOT realized");
226 void
227 canvas_set_zoom(
228 canvas_handle canvas,
229 double pix_per_unit)
231 canvas_ptr->get()->set_zoom(pix_per_unit);
234 void
235 canvas_arrange(
236 canvas_handle canvas)
238 Glib::RefPtr<Gdk::Window> win = canvas_ptr->get()->get_window();
239 if (!win)
241 return;
244 canvas_ptr->get()->arrange();
246 // arrange does not cause locations stored, emulate it
247 FlowCanvas::ItemList modules = canvas_ptr->get()->items(); // copy
248 for (FlowCanvas::ItemList::iterator m = modules.begin(); m != modules.end(); ++m)
250 boost::shared_ptr<FlowCanvas::Module> module = boost::dynamic_pointer_cast<FlowCanvas::Module>(*m);
251 if (!module)
252 continue;
254 module->store_location();
258 bool
259 canvas_create_module(
260 canvas_handle canvas,
261 const char * name,
262 double x,
263 double y,
264 bool show_title,
265 bool show_port_labels,
266 void * module_context,
267 canvas_module_handle * module_handle_ptr)
269 boost::shared_ptr<FlowCanvas::Module> * module;
271 module = new boost::shared_ptr<FlowCanvas::Module>(new module_cls(*canvas_ptr, name, x, y, show_title, show_port_labels, module_context));
272 canvas_ptr->get()->add_item(*module);
273 module->get()->resize();
275 *module_handle_ptr = (canvas_module_handle)module;
277 return true;
280 #define module_ptr ((boost::shared_ptr<FlowCanvas::Module> *)module)
282 void
283 canvas_set_module_name(
284 canvas_module_handle module,
285 const char * name)
287 module_ptr->get()->set_name(name);
290 bool
291 canvas_destroy_module(
292 canvas_handle canvas,
293 canvas_module_handle module)
295 canvas_ptr->get()->remove_item(*module_ptr);
296 delete module_ptr;
297 return true;
300 bool
301 canvas_create_port(
302 canvas_handle canvas,
303 canvas_module_handle module,
304 const char * name,
305 bool is_input,
306 int color,
307 void * port_context,
308 canvas_port_handle * port_handle_ptr)
310 boost::shared_ptr<port_cls> * port;
312 port = new boost::shared_ptr<port_cls>(new port_cls(*module_ptr, name, is_input, color, port_context));
314 module_ptr->get()->add_port(*port);
315 module_ptr->get()->resize();
317 *port_handle_ptr = (canvas_port_handle)port;
319 return true;
322 #undef module_ptr
323 #define port_ptr ((boost::shared_ptr<port_cls> *)port)
325 bool
326 canvas_destroy_port(
327 canvas_handle canvas,
328 canvas_port_handle port)
330 boost::shared_ptr<FlowCanvas::Module> module = port_ptr->get()->module().lock();
331 module->remove_port(*port_ptr);
332 delete port_ptr;
333 module->resize();
334 return true;
338 canvas_get_port_color(
339 canvas_port_handle port)
341 return port_ptr->get()->color();
344 void
345 canvas_set_port_name(
346 canvas_port_handle port,
347 const char * name)
349 port_ptr->get()->set_name(name);
352 #undef port_ptr
353 #define port1_ptr ((boost::shared_ptr<port_cls> *)port1)
354 #define port2_ptr ((boost::shared_ptr<port_cls> *)port2)
356 bool
357 canvas_add_connection(
358 canvas_handle canvas,
359 canvas_port_handle port1,
360 canvas_port_handle port2,
361 uint32_t color)
363 canvas_ptr->get()->add_connection(*port1_ptr, *port2_ptr, color);
364 return true;
367 bool
368 canvas_remove_connection(
369 canvas_handle canvas,
370 canvas_port_handle port1,
371 canvas_port_handle port2)
373 canvas_ptr->get()->remove_connection(*port1_ptr, *port2_ptr);
374 return true;
377 #undef port1_ptr
378 #undef port2_ptr
380 void
381 canvas_cls::connect(
382 boost::shared_ptr<FlowCanvas::Connectable> c1,
383 boost::shared_ptr<FlowCanvas::Connectable> c2)
385 if (m_connect_request != NULL)
387 boost::shared_ptr<port_cls> port1 = boost::dynamic_pointer_cast<port_cls>(c1);
388 boost::shared_ptr<port_cls> port2 = boost::dynamic_pointer_cast<port_cls>(c2);
389 m_connect_request(port1->context, port2->context);
393 void
394 canvas_cls::disconnect(
395 boost::shared_ptr<FlowCanvas::Connectable> c1,
396 boost::shared_ptr<FlowCanvas::Connectable> c2)
398 if (m_disconnect_request != NULL)
400 boost::shared_ptr<port_cls> port1 = boost::dynamic_pointer_cast<port_cls>(c1);
401 boost::shared_ptr<port_cls> port2 = boost::dynamic_pointer_cast<port_cls>(c2);
402 m_disconnect_request(port1->context, port2->context);
406 bool
407 canvas_enum_modules(
408 canvas_handle canvas,
409 void * callback_context,
410 bool (* callback)(void * context, canvas_module_handle module))
412 return false;
415 bool
416 canvas_enum_module_ports(
417 canvas_handle canvas,
418 canvas_module_handle module,
419 void * callback_context,
420 bool (* callback)(void * context, canvas_port_handle port))
422 return false;