Add missing header text
[ladish.git] / gui / canvas.cpp
blob223125497c8b401ed5101a0b04010ed9519178c6
1 /* -*- Mode: C ; c-basic-offset: 2 -*- */
2 /*
3 * LADI Session Handler (ladish)
5 * Copyright (C) 2008, 2009, 2010, 2011 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 * context,
41 void (* connect_request)(void * port1_context, void * port2_context),
42 void (* disconnect_request)(void * port1_context, void * port2_context),
43 void (* module_location_changed)(void * module_context, double x, double y),
44 void (* fill_canvas_menu)(GtkMenu * menu, void * canvas_context),
45 void (* fill_module_menu)(GtkMenu * menu, void * module_context),
46 void (* fill_port_menu)(GtkMenu * menu, void * port_context))
47 : FlowCanvas::Canvas(width, height)
48 , m_context(context)
49 , m_connect_request(connect_request)
50 , m_disconnect_request(disconnect_request)
51 , m_module_location_changed(module_location_changed)
52 , m_fill_canvas_menu(fill_canvas_menu)
53 , m_fill_module_menu(fill_module_menu)
54 , m_fill_port_menu(fill_port_menu)
57 virtual ~canvas_cls() {}
59 virtual void on_realize()
61 log_info("canvas_cls::on_realize");
62 FlowCanvas::Canvas::on_realize();
63 scroll_to_center();
66 virtual void on_size_allocate(Gtk::Allocation& allocation)
68 //log_info("canvas_cls::on_size_allocate");
69 FlowCanvas::Canvas::on_size_allocate(allocation);
70 if (is_realized())
72 //log_info("... realized");
73 scroll_to_center();
77 virtual bool canvas_event(GdkEvent * event);
79 virtual void connect(boost::shared_ptr<FlowCanvas::Connectable> port1, boost::shared_ptr<FlowCanvas::Connectable> port2);
80 virtual void disconnect(boost::shared_ptr<FlowCanvas::Connectable> port1, boost::shared_ptr<FlowCanvas::Connectable> port2);
82 void * m_context;
83 void (* m_connect_request)(void * port1_context, void * port2_context);
84 void (* m_disconnect_request)(void * port1_context, void * port2_context);
85 void (* m_module_location_changed)(void * module_context, double x, double y);
86 void (* m_fill_canvas_menu)(GtkMenu * menu, void * canvas_context);
87 void (* m_fill_module_menu)(GtkMenu * menu, void * module_context);
88 void (* m_fill_port_menu)(GtkMenu * menu, void * port_context);
91 class module_cls: public FlowCanvas::Module
93 public:
94 module_cls(
95 boost::shared_ptr<FlowCanvas::Canvas> canvas,
96 const std::string& name,
97 double x,
98 double y,
99 bool show_title,
100 bool show_port_labels,
101 void * module_context)
102 : FlowCanvas::Module(canvas, name, x, y, show_title, show_port_labels)
103 , m_context(module_context)
106 virtual ~module_cls() {}
108 virtual void store_location()
110 boost::dynamic_pointer_cast<canvas_cls>(canvas().lock())->m_module_location_changed(m_context, property_x(), property_y());
113 void create_menu()
115 _menu = new Gtk::Menu();
116 _menu->signal_selection_done().connect(sigc::mem_fun(this, &module_cls::on_menu_hide));
117 _menu->items().push_back(Gtk::Menu_Helpers::MenuElem(_("Disconnect All"), sigc::mem_fun(this, &module_cls::menu_disconnect_all)));
118 void (* fill_module_menu)(GtkMenu * menu, void * module_context) = boost::dynamic_pointer_cast<canvas_cls>(canvas().lock())->m_fill_module_menu;
119 if (fill_module_menu != NULL)
121 fill_module_menu(_menu->gobj(), m_context);
123 _menu->show_all();
126 void menu_disconnect_all()
128 for (FlowCanvas::PortVector::iterator p = _ports.begin(); p != _ports.end(); p++)
130 (*p)->disconnect_all();
134 void on_menu_hide()
136 delete _menu;
137 _menu = NULL;
140 void * m_context;
143 class port_cls: public FlowCanvas::Port
145 public:
146 port_cls(
147 boost::shared_ptr<FlowCanvas::Module> module,
148 const std::string& name,
149 bool is_input,
150 uint32_t color,
151 void * port_context)
152 : FlowCanvas::Port(module, name, is_input, color)
153 , m_context(port_context)
156 virtual ~port_cls() {}
158 void popup_menu(guint button, guint32 activate_time)
160 create_menu();
161 if (_menu)
162 _menu->popup(button, activate_time);
165 virtual void create_menu()
167 void (* fill_port_menu)(GtkMenu * menu, void * port_context);
169 /* Cannot call FlowCanvas::Port::create_menu() because on_menu_hide() is not virtual */
170 _menu = new Gtk::Menu();
171 _menu->items().push_back(Gtk::Menu_Helpers::MenuElem(_("Disconnect All"), sigc::mem_fun(this, &Port::disconnect_all)));
172 _menu->signal_selection_done().connect(sigc::mem_fun(this, &port_cls::on_menu_hide));
174 fill_port_menu = boost::dynamic_pointer_cast<canvas_cls>(module().lock()->canvas().lock())->m_fill_port_menu;
175 if (fill_port_menu != NULL)
177 fill_port_menu(_menu->gobj(), m_context);
179 _menu->show_all();
182 void on_menu_hide()
184 delete _menu;
185 _menu = NULL;
188 void * m_context;
191 bool
192 canvas_init(
193 void)
195 Gnome::Canvas::init();
196 return true;
199 bool
200 canvas_create(
201 double width,
202 double height,
203 void * canvas_context,
204 void (* connect_request)(void * port1_context, void * port2_context),
205 void (* disconnect_request)(void * port1_context, void * port2_context),
206 void (* module_location_changed)(void * module_context, double x, double y),
207 void (* fill_canvas_menu)(GtkMenu * menu, void * canvas_context),
208 void (* fill_module_menu)(GtkMenu * menu, void * module_context),
209 void (* fill_port_menu)(GtkMenu * menu, void * port_context),
210 canvas_handle * canvas_handle_ptr)
212 boost::shared_ptr<canvas_cls> * canvas;
214 canvas = new boost::shared_ptr<canvas_cls>(new canvas_cls(width,
215 height,
216 canvas_context,
217 connect_request,
218 disconnect_request,
219 module_location_changed,
220 fill_canvas_menu,
221 fill_module_menu,
222 fill_port_menu));
224 *canvas_handle_ptr = (canvas_handle)canvas;
226 return true;
229 #define canvas_ptr ((boost::shared_ptr<canvas_cls> *)canvas)
231 GtkWidget *
232 canvas_get_widget(
233 canvas_handle canvas)
235 return ((Gtk::Widget *)canvas_ptr->get())->gobj();
238 void
239 canvas_destroy(
240 canvas_handle canvas)
242 delete canvas_ptr;
245 void
246 canvas_clear(
247 canvas_handle canvas)
249 FlowCanvas::ItemList modules = canvas_ptr->get()->items(); // copy
250 for (FlowCanvas::ItemList::iterator m = modules.begin(); m != modules.end(); ++m)
252 boost::shared_ptr<FlowCanvas::Module> module = boost::dynamic_pointer_cast<FlowCanvas::Module>(*m);
253 if (!module)
254 continue;
256 FlowCanvas::PortVector ports = module->ports(); // copy
257 for (FlowCanvas::PortVector::iterator p = ports.begin(); p != ports.end(); ++p)
259 boost::shared_ptr<FlowCanvas::Port> port = boost::dynamic_pointer_cast<FlowCanvas::Port>(*p);
260 ASSERT(port != NULL);
261 module->remove_port(port);
262 port->hide();
265 ASSERT(module->ports().empty());
266 canvas_ptr->get()->remove_item(module);
270 void
271 canvas_get_size(
272 canvas_handle canvas,
273 double * width_ptr,
274 double * height_ptr)
276 *width_ptr = canvas_ptr->get()->width();
277 *height_ptr = canvas_ptr->get()->height();
280 void
281 canvas_scroll_to_center(
282 canvas_handle canvas)
284 if (canvas_ptr->get()->is_realized())
286 //log_info("realized");
287 canvas_ptr->get()->scroll_to_center();
289 else
291 //log_info("NOT realized");
295 double
296 canvas_get_zoom(
297 canvas_handle canvas)
299 return canvas_ptr->get()->get_zoom();
302 void
303 canvas_set_zoom(
304 canvas_handle canvas,
305 double pix_per_unit)
307 canvas_ptr->get()->set_zoom(pix_per_unit);
310 void
311 canvas_set_zoom_fit(
312 canvas_handle canvas)
314 canvas_ptr->get()->zoom_full();
317 void
318 canvas_arrange(
319 canvas_handle canvas)
321 Glib::RefPtr<Gdk::Window> win = canvas_ptr->get()->get_window();
322 if (win)
324 canvas_ptr->get()->arrange();
328 size_t
329 canvas_get_selected_modules_count(
330 canvas_handle canvas)
332 return canvas_ptr->get()->selected_items().size();
335 bool
336 canvas_get_one_selected_module(
337 canvas_handle canvas,
338 void ** module_context_ptr)
340 int i;
342 std::list<boost::shared_ptr<FlowCanvas::Item> > modules = canvas_ptr->get()->selected_items();
343 if (modules.size() != 1)
345 return false;
348 i = 0;
349 for (std::list<boost::shared_ptr<FlowCanvas::Item> >::iterator m = modules.begin(); m != modules.end(); ++m)
351 boost::shared_ptr<module_cls> module = boost::dynamic_pointer_cast<module_cls>(*m);
352 if (module == NULL)
354 ASSERT_NO_PASS;
355 return false;
358 if (i == 0)
360 *module_context_ptr = module->m_context;
361 i++;
362 continue;
366 if (i != 1)
368 ASSERT_NO_PASS;
369 return false;
372 return true;
375 bool
376 canvas_get_two_selected_modules(
377 canvas_handle canvas,
378 void ** module1_context_ptr,
379 void ** module2_context_ptr)
381 int i;
383 std::list<boost::shared_ptr<FlowCanvas::Item> > modules = canvas_ptr->get()->selected_items();
384 if (modules.size() != 2)
386 return false;
389 i = 0;
390 for (std::list<boost::shared_ptr<FlowCanvas::Item> >::iterator m = modules.begin(); m != modules.end(); ++m)
392 boost::shared_ptr<module_cls> module = boost::dynamic_pointer_cast<module_cls>(*m);
393 if (module == NULL)
395 ASSERT_NO_PASS;
396 return false;
399 switch (i)
401 case 0:
402 *module1_context_ptr = module->m_context;
403 i++;
404 continue;
405 case 1:
406 *module2_context_ptr = module->m_context;
407 i++;
408 continue;
412 if (i != 2)
414 ASSERT_NO_PASS;
415 return false;
418 return true;
421 bool
422 canvas_create_module(
423 canvas_handle canvas,
424 const char * name,
425 double x,
426 double y,
427 bool show_title,
428 bool show_port_labels,
429 void * module_context,
430 canvas_module_handle * module_handle_ptr)
432 boost::shared_ptr<FlowCanvas::Module> * module;
434 module = new boost::shared_ptr<FlowCanvas::Module>(new module_cls(*canvas_ptr, name, x, y, show_title, show_port_labels, module_context));
435 canvas_ptr->get()->add_item(*module);
436 module->get()->resize();
438 *module_handle_ptr = (canvas_module_handle)module;
440 return true;
443 #define module_ptr ((boost::shared_ptr<FlowCanvas::Module> *)module)
445 void
446 canvas_set_module_name(
447 canvas_module_handle module,
448 const char * name)
450 module_ptr->get()->set_name(name);
451 module_ptr->get()->resize();
454 const char *
455 canvas_get_module_name(
456 canvas_module_handle module)
458 return module_ptr->get()->name().c_str();
461 bool
462 canvas_destroy_module(
463 canvas_handle canvas,
464 canvas_module_handle module)
466 canvas_ptr->get()->remove_item(*module_ptr);
467 delete module_ptr;
468 return true;
471 bool
472 canvas_create_port(
473 canvas_handle canvas,
474 canvas_module_handle module,
475 const char * name,
476 bool is_input,
477 int color,
478 void * port_context,
479 canvas_port_handle * port_handle_ptr)
481 boost::shared_ptr<port_cls> * port;
483 port = new boost::shared_ptr<port_cls>(new port_cls(*module_ptr, name, is_input, color, port_context));
485 module_ptr->get()->add_port(*port);
486 module_ptr->get()->resize();
488 *port_handle_ptr = (canvas_port_handle)port;
490 return true;
493 #undef module_ptr
494 #define port_ptr ((boost::shared_ptr<port_cls> *)port)
496 bool
497 canvas_destroy_port(
498 canvas_handle canvas,
499 canvas_port_handle port)
501 boost::shared_ptr<FlowCanvas::Module> module = port_ptr->get()->module().lock();
502 module->remove_port(*port_ptr);
503 delete port_ptr;
504 module->resize();
505 return true;
509 canvas_get_port_color(
510 canvas_port_handle port)
512 return port_ptr->get()->color();
515 void
516 canvas_set_port_name(
517 canvas_port_handle port,
518 const char * name)
520 port_ptr->get()->set_name(name);
521 port_ptr->get()->module().lock()->resize();
524 const char *
525 canvas_get_port_name(
526 canvas_port_handle port)
528 return port_ptr->get()->name().c_str();
531 #undef port_ptr
532 #define port1_ptr ((boost::shared_ptr<port_cls> *)port1)
533 #define port2_ptr ((boost::shared_ptr<port_cls> *)port2)
535 bool
536 canvas_add_connection(
537 canvas_handle canvas,
538 canvas_port_handle port1,
539 canvas_port_handle port2,
540 uint32_t color)
542 canvas_ptr->get()->add_connection(*port1_ptr, *port2_ptr, color);
543 return true;
546 bool
547 canvas_remove_connection(
548 canvas_handle canvas,
549 canvas_port_handle port1,
550 canvas_port_handle port2)
552 canvas_ptr->get()->remove_connection(*port1_ptr, *port2_ptr);
553 return true;
556 #undef port1_ptr
557 #undef port2_ptr
559 bool canvas_cls::canvas_event(GdkEvent * event)
561 assert(event);
563 if (m_fill_canvas_menu != NULL && event->type == GDK_BUTTON_PRESS && event->button.button == 3)
565 Gtk::Menu * menu_ptr;
566 menu_ptr = new Gtk::Menu();
567 m_fill_canvas_menu(menu_ptr->gobj(), m_context);
568 menu_ptr->show_all();
569 menu_ptr->popup(event->button.button, event->button.time);
570 return true;
573 return Canvas::canvas_event(event);
576 void
577 canvas_cls::connect(
578 boost::shared_ptr<FlowCanvas::Connectable> c1,
579 boost::shared_ptr<FlowCanvas::Connectable> c2)
581 if (m_connect_request != NULL)
583 boost::shared_ptr<port_cls> port1 = boost::dynamic_pointer_cast<port_cls>(c1);
584 boost::shared_ptr<port_cls> port2 = boost::dynamic_pointer_cast<port_cls>(c2);
585 m_connect_request(port1->m_context, port2->m_context);
589 void
590 canvas_cls::disconnect(
591 boost::shared_ptr<FlowCanvas::Connectable> c1,
592 boost::shared_ptr<FlowCanvas::Connectable> c2)
594 if (m_disconnect_request != NULL)
596 boost::shared_ptr<port_cls> port1 = boost::dynamic_pointer_cast<port_cls>(c1);
597 boost::shared_ptr<port_cls> port2 = boost::dynamic_pointer_cast<port_cls>(c2);
598 m_disconnect_request(port1->m_context, port2->m_context);
602 bool
603 canvas_enum_modules(
604 canvas_handle canvas,
605 void * callback_context,
606 bool (* callback)(void * context, canvas_module_handle module))
608 return false;
611 bool
612 canvas_enum_module_ports(
613 canvas_handle canvas,
614 canvas_module_handle module,
615 void * callback_context,
616 bool (* callback)(void * context, canvas_port_handle port))
618 return false;