Blame synfig-studio/src/gui/docks/dockmanager.cpp

Carlos Lopez a09598
/* === S Y N F I G ========================================================= */
Carlos Lopez a09598
/*!	\file dockmanager.cpp
Carlos Lopez a09598
**	\brief Template File
Carlos Lopez a09598
**
Carlos Lopez a09598
**	$Id$
Carlos Lopez a09598
**
Carlos Lopez a09598
**	\legal
Carlos Lopez a09598
**	Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
Carlos Lopez a09598
**	Copyright (c) 2007, 2008 Chris Moore
Carlos Lopez a09598
**
Carlos Lopez a09598
**	This package is free software; you can redistribute it and/or
Carlos Lopez a09598
**	modify it under the terms of the GNU General Public License as
Carlos Lopez a09598
**	published by the Free Software Foundation; either version 2 of
Carlos Lopez a09598
**	the License, or (at your option) any later version.
Carlos Lopez a09598
**
Carlos Lopez a09598
**	This package is distributed in the hope that it will be useful,
Carlos Lopez a09598
**	but WITHOUT ANY WARRANTY; without even the implied warranty of
Carlos Lopez a09598
**	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Carlos Lopez a09598
**	General Public License for more details.
Carlos Lopez a09598
**	\endlegal
Carlos Lopez a09598
*/
Carlos Lopez a09598
/* ========================================================================= */
Carlos Lopez a09598
Carlos Lopez a09598
/* === H E A D E R S ======================================================= */
Carlos Lopez a09598
Carlos Lopez a09598
#ifdef USING_PCH
Carlos Lopez a09598
#	include "pch.h"
Carlos Lopez a09598
#else
Carlos Lopez a09598
#ifdef HAVE_CONFIG_H
Carlos Lopez a09598
#	include <config.h></config.h>
Carlos Lopez a09598
#endif
Carlos Lopez a09598
Nikita Kitaev 5fe12e
#include "docks/dockmanager.h"
Carlos Lopez a09598
#include <stdexcept></stdexcept>
Nikita Kitaev 5fe12e
#include "docks/dockable.h"
464569
#include "docks/dockbook.h"
Nikita Kitaev 5fe12e
#include "docks/dockdialog.h"
Carlos Lopez a09598
#include <synfigapp settings.h=""></synfigapp>
Carlos Lopez a09598
#include <synfigapp main.h=""></synfigapp>
Carlos Lopez a09598
#include <gdkmm general.h=""></gdkmm>
Carlos Lopez a09598
Carlos Lopez a09598
#include "general.h"
Carlos Lopez a09598
464569
#include <gtkmm paned.h=""></gtkmm>
990a0b
#include <gtkmm box.h=""></gtkmm>
464569
#include <gtkmm window.h=""></gtkmm>
464569
464569
Carlos Lopez a09598
#endif
Carlos Lopez a09598
Carlos Lopez a09598
/* === U S I N G =========================================================== */
Carlos Lopez a09598
Carlos Lopez a09598
using namespace std;
Carlos Lopez a09598
using namespace etl;
Carlos Lopez a09598
using namespace synfig;
Carlos Lopez a09598
using namespace studio;
Carlos Lopez a09598
Carlos Lopez a09598
/* === M A C R O S ========================================================= */
Carlos Lopez a09598
Carlos Lopez a09598
/* === P R O C E D U R E S ================================================= */
Carlos Lopez a09598
464569
namespace studio {
464569
	class DockLinkPoint {
464569
	public:
990a0b
		Gtk::Bin *bin;
464569
		Gtk::Paned *paned;
464569
		Gtk::Window *window;
464569
		bool is_first;
464569
990a0b
		DockLinkPoint(): bin(NULL), paned(NULL), window(NULL), is_first(false) { }
990a0b
		explicit DockLinkPoint(Gtk::Bin *bin): bin(bin), paned(NULL), window(NULL), is_first(false) { }
990a0b
		explicit DockLinkPoint(Gtk::Paned *paned, bool is_first): bin(NULL), paned(paned), window(NULL), is_first(is_first) { }
990a0b
		explicit DockLinkPoint(Gtk::Window *window): bin(NULL), paned(NULL), window(window), is_first(false) { }
464569
		explicit DockLinkPoint(Gtk::Widget &widget) {
464569
			Gtk::Container *container = widget.get_parent();
990a0b
			bin = dynamic_cast<gtk::bin*>(container);</gtk::bin*>
464569
			paned = dynamic_cast<gtk::paned*>(container);</gtk::paned*>
464569
			window = dynamic_cast<gtk::window*>(container);</gtk::window*>
464569
			is_first = paned != NULL && paned->get_child1() == &widget;
464569
		}
464569
990a0b
		bool is_valid() { return bin || paned || window; }
464569
464569
		void unlink() {
464569
			if (paned && is_first && paned->get_child1())
464569
				paned->remove(*paned->get_child1());
464569
			else
464569
			if (paned && !is_first && paned->get_child2())
464569
				paned->remove(*paned->get_child2());
464569
			else
464569
			if (window)
464569
				window->remove();
990a0b
			if (bin)
990a0b
				bin->remove();
464569
		}
464569
464569
		void link(Gtk::Widget &widget)
464569
		{
464569
			if (paned && is_first)
464569
				paned->add1(widget);
464569
			else
464569
			if (paned && !is_first)
464569
				paned->add2(widget);
464569
			else
464569
			if (window)
464569
				window->add(widget);
990a0b
			else
990a0b
			if (bin)
990a0b
				bin->add(widget);
464569
		}
464569
	};
464569
}
464569
Carlos Lopez a09598
class studio::DockSettings : public synfigapp::Settings
Carlos Lopez a09598
{
Carlos Lopez a09598
	DockManager* dock_manager;
Carlos Lopez a09598
Carlos Lopez a09598
public:
Carlos Lopez a09598
	DockSettings(DockManager* dock_manager):dock_manager(dock_manager)
Carlos Lopez a09598
	{
Carlos Lopez a09598
		synfigapp::Main::settings().add_domain(this,"dock");
Carlos Lopez a09598
	}
Carlos Lopez a09598
Carlos Lopez a09598
	virtual ~DockSettings()
Carlos Lopez a09598
	{
Carlos Lopez a09598
		synfigapp::Main::settings().remove_domain("dock");
Carlos Lopez a09598
	}
Carlos Lopez a09598
	virtual bool get_value(const synfig::String& key_, synfig::String& value)const
Carlos Lopez a09598
	{
Carlos Lopez a09598
Carlos Lopez a09598
		if(key_.size()>6 && String(key_.begin(),key_.begin()+6)=="dialog")try
Carlos Lopez a09598
		{
Carlos Lopez a09598
			synfig::String key(key_.begin()+7,key_.end());
Carlos Lopez a09598
			synfig::String::size_type separator=key.find_first_of('.');
Carlos Lopez a09598
			int id(atoi(synfig::String(key.begin(),key.begin()+separator).c_str()));
Carlos Lopez a09598
			key=synfig::String(key.begin()+separator+1,key.end());
Carlos Lopez a09598
Carlos Lopez a09598
			DockDialog& dock_dialog(dock_manager->find_dock_dialog(id));
Carlos Lopez a09598
Carlos Lopez a09598
			if(key=="contents_size")
Carlos Lopez a09598
			{
464569
				// TODO:
464569
				//dock_dialog.rebuild_sizes();
464569
				//vector<int>::const_iterator iter(dock_dialog.get_dock_book_sizes().begin());</int>
464569
				//vector<int>::const_iterator end(dock_dialog.get_dock_book_sizes().end());</int>
464569
				//value.clear();
464569
				//for(;iter!=end;++iter)
464569
				//	value+=strprintf("%d ",*iter);
Carlos Lopez a09598
				return true;
Carlos Lopez a09598
			}
Carlos Lopez a09598
			if(key=="pos")
Carlos Lopez a09598
			{
Carlos Lopez a09598
				int x,y; dock_dialog.get_position(x,y);
Carlos Lopez f980b9
				value=strprintf("%d %d",x,y);
Carlos Lopez a09598
				return true;
Carlos Lopez a09598
			}
Carlos Lopez a09598
			if(key=="size")
Carlos Lopez a09598
			{
Carlos Lopez a09598
				int x,y; dock_dialog.get_size(x,y);
Carlos Lopez f980b9
				value=strprintf("%d %d",x,y);
Carlos Lopez a09598
				return true;
Carlos Lopez a09598
			}
Carlos Lopez a09598
			if(key=="contents")
Carlos Lopez a09598
			{
464569
				// TODO:
464569
				//value=dock_dialog.get_contents();
Carlos Lopez a09598
				return true;
Carlos Lopez a09598
			}
Carlos Lopez a09598
			if(key=="comp_selector")
Carlos Lopez a09598
			{
464569
				// TODO:
464569
				//value=dock_dialog.get_composition_selector()?"1":"0";
Carlos Lopez a09598
				return true;
Carlos Lopez a09598
			}
Carlos Lopez a09598
		}catch (...) { return false; }
Carlos Lopez a09598
		return synfigapp::Settings::get_value(key_,value);
Carlos Lopez a09598
	}
Carlos Lopez a09598
Carlos Lopez a09598
	virtual bool set_value(const synfig::String& key_,const synfig::String& value)
Carlos Lopez a09598
	{
Carlos Lopez a09598
Carlos Lopez a09598
		if(key_.size()>6 && String(key_.begin(),key_.begin()+6)=="dialog")
Carlos Lopez a09598
		{
Carlos Lopez a09598
			synfig::String key(key_.begin()+7,key_.end());
Carlos Lopez a09598
			synfig::String::size_type separator=key.find_first_of('.');
Carlos Lopez a09598
			int id(atoi(synfig::String(key.begin(),key.begin()+separator).c_str()));
Carlos Lopez a09598
			key=synfig::String(key.begin()+separator+1,key.end());
Carlos Lopez a09598
Carlos Lopez a09598
			DockDialog& dock_dialog(dock_manager->find_dock_dialog(id));
Carlos Lopez a09598
Carlos Lopez a09598
			if(key=="contents_size")
Carlos Lopez a09598
			{
Carlos Lopez a09598
				try {
Carlos Lopez a09598
				int width, height;
Carlos Lopez a09598
				Gtk::IconSize::lookup(Gtk::IconSize(4),width,height);
Carlos Lopez a09598
				vector<int> data;</int>
Carlos Lopez a09598
				String::size_type n=0;
Carlos Lopez a09598
				String value_(value);
Carlos Lopez a09598
				while(value_.size() && value_.size()>n){
Carlos Lopez a09598
					value_=String(value_.begin()+n,value_.end());
Carlos Lopez a09598
					int size;
Carlos Lopez a09598
					if(!strscanf(value_,"%d",&size))
Carlos Lopez a09598
						break;
Carlos Lopez a09598
Carlos Lopez a09598
					data.push_back(size);
Carlos Lopez a09598
Carlos Lopez a09598
					n=value_.find(" ");
Carlos Lopez a09598
					if(n==String::npos)
Carlos Lopez a09598
						break;
Carlos Lopez a09598
					n++;
Carlos Lopez a09598
				}
464569
				// TODO:
464569
				//dock_dialog.set_dock_book_sizes(data);
Carlos Lopez a09598
				}
Carlos Lopez a09598
				catch(...)
Carlos Lopez a09598
				{
Carlos Lopez a09598
					synfig::error("Exception caught!!!");
Carlos Lopez a09598
					return false;
Carlos Lopez a09598
				}
Carlos Lopez a09598
				return true;
Carlos Lopez a09598
			}
Carlos Lopez a09598
			if(key=="pos")
Carlos Lopez a09598
			{
Carlos Lopez a09598
				int x,y;
Carlos Lopez a09598
				if(!strscanf(value,"%d %d",&x, &y))
Carlos Lopez a09598
					return false;
Carlos Lopez bb2797
				//synfig::info("dock_manager. move to: %d, %d", x,y);
Carlos Lopez a09598
				dock_dialog.move(x,y);
Carlos Lopez a09598
				return true;
Carlos Lopez a09598
			}
Carlos Lopez a09598
			if(key=="size")
Carlos Lopez a09598
			{
Carlos Lopez a09598
				int x,y;
Carlos Lopez a09598
				if(!strscanf(value,"%d %d",&x, &y))
Carlos Lopez a09598
					return false;
Carlos Lopez bb2797
				//synfig::info("dock_manager. size to: %d, %d", x,y);
Carlos Lopez a09598
				dock_dialog.set_default_size(x,y);
Carlos Lopez a09598
				dock_dialog.resize(x,y);
Carlos Lopez a09598
				return true;
Carlos Lopez a09598
			}
Carlos Lopez a09598
			if(key=="contents")
Carlos Lopez a09598
			{
464569
				// TODO:
464569
				//dock_dialog.set_contents(value);
Carlos Lopez a09598
				return true;
Carlos Lopez a09598
			}
Carlos Lopez a09598
			if(key=="comp_selector")
Carlos Lopez a09598
			{
464569
				// TODO:
464569
				//if(value.empty() || value[0]=='0')
464569
				//	dock_dialog.set_composition_selector(false);
464569
				//else
464569
				//	dock_dialog.set_composition_selector(true);
Carlos Lopez a09598
				return true;
Carlos Lopez a09598
			}
Carlos Lopez a09598
		}
Carlos Lopez a09598
		return synfigapp::Settings::set_value(key_,value);
Carlos Lopez a09598
	}
Carlos Lopez a09598
Carlos Lopez a09598
	virtual KeyList get_key_list()const
Carlos Lopez a09598
	{
Carlos Lopez a09598
		synfigapp::Settings::KeyList ret(synfigapp::Settings::get_key_list());
Carlos Lopez a09598
Carlos Lopez a09598
		std::list<dockdialog*>::const_iterator iter;</dockdialog*>
Carlos Lopez a09598
		for(iter=dock_manager->dock_dialog_list_.begin();iter!=dock_manager->dock_dialog_list_.end();++iter)
Carlos Lopez a09598
		{
Carlos Lopez a09598
			ret.push_back(strprintf("dialog.%d.contents",(*iter)->get_id()));
Carlos Lopez a09598
			ret.push_back(strprintf("dialog.%d.comp_selector",(*iter)->get_id()));
Carlos Lopez a09598
			ret.push_back(strprintf("dialog.%d.pos",(*iter)->get_id()));
Carlos Lopez a09598
			ret.push_back(strprintf("dialog.%d.size",(*iter)->get_id()));
Carlos Lopez a09598
			ret.push_back(strprintf("dialog.%d.contents_size",(*iter)->get_id()));
Carlos Lopez a09598
		}
Carlos Lopez a09598
		return ret;
Carlos Lopez a09598
	}
Carlos Lopez a09598
};
Carlos Lopez a09598
Carlos Lopez a09598
/* === M E T H O D S ======================================================= */
Carlos Lopez a09598
Carlos Lopez a09598
DockManager::DockManager():
Carlos Lopez a09598
	dock_settings(new DockSettings(this))
Carlos Lopez a09598
{
Carlos Lopez a09598
}
Carlos Lopez a09598
Carlos Lopez a09598
DockManager::~DockManager()
Carlos Lopez a09598
{
Carlos Lopez a09598
	while(!dock_dialog_list_.empty())
Carlos Lopez a09598
	{
Carlos Lopez a09598
		dock_dialog_list_.back()->close();
Carlos Lopez a09598
	}
Carlos Lopez a09598
	while(!dockable_list_.empty())
Carlos Lopez a09598
	{
Carlos Lopez a09598
		Dockable* dockable(dockable_list_.back());
Carlos Lopez a09598
		// synfig::info("DockManager::~DockManager(): Deleting dockable \"%s\"",dockable->get_name().c_str());
Carlos Lopez a09598
		dockable_list_.pop_back();
Carlos Lopez a09598
		delete dockable;
Carlos Lopez a09598
	}
Carlos Lopez a09598
}
Carlos Lopez a09598
Carlos Lopez a09598
void
Carlos Lopez a09598
DockManager::register_dockable(Dockable& x)
Carlos Lopez a09598
{
Carlos Lopez a09598
	dockable_list_.push_back(&x);
Carlos Lopez a09598
	// synfig::info("DockManager::register_dockable(): Registered dockable \"%s\"",dockable_list_.back()->get_name().c_str());
Carlos Lopez a09598
	signal_dockable_registered()(&x);
Carlos Lopez a09598
}
Carlos Lopez a09598
Carlos Lopez a09598
bool
Carlos Lopez a09598
DockManager::unregister_dockable(Dockable& x)
Carlos Lopez a09598
{
Carlos Lopez a09598
	std::list<dockable*>::iterator iter;</dockable*>
Carlos Lopez a09598
	for(iter=dockable_list_.begin();iter!=dockable_list_.end();++iter)
Carlos Lopez a09598
	{
Carlos Lopez a09598
		if(&x==*iter)
Carlos Lopez a09598
		{
464569
			remove_widget_recursive(x);
Carlos Lopez a09598
			dockable_list_.erase(iter);
Carlos Lopez a09598
			synfig::info("DockManager::unregister_dockable(): \"%s\" has been Unregistered",x.get_name().c_str());
Carlos Lopez a09598
			return true;
Carlos Lopez a09598
		}
Carlos Lopez a09598
	}
Carlos Lopez a09598
	return false;
Carlos Lopez a09598
}
Carlos Lopez a09598
Carlos Lopez a09598
Dockable&
Carlos Lopez a09598
DockManager::find_dockable(const synfig::String& x)
Carlos Lopez a09598
{
Carlos Lopez a09598
	std::list<dockable*>::iterator iter;</dockable*>
Carlos Lopez a09598
	for(iter=dockable_list_.begin();iter!=dockable_list_.end();++iter)
Carlos Lopez a09598
		if((*iter)->get_name()==x)
Carlos Lopez a09598
			return **iter;
Carlos Lopez a09598
Carlos Lopez a09598
	throw std::runtime_error("DockManager::find_dockable(): not found");
Carlos Lopez a09598
}
Carlos Lopez a09598
Carlos Lopez a09598
void
Carlos Lopez a09598
DockManager::present(synfig::String x)
Carlos Lopez a09598
{
Carlos Lopez a09598
	try
Carlos Lopez a09598
	{
Carlos Lopez a09598
		find_dockable(x).present();
Carlos Lopez a09598
	}
Carlos Lopez a09598
	catch(...)
Carlos Lopez a09598
	{
Carlos Lopez a09598
	}
Carlos Lopez a09598
}
Carlos Lopez a09598
Carlos Lopez a09598
DockDialog&
Carlos Lopez a09598
DockManager::find_dock_dialog(int id)
Carlos Lopez a09598
{
Carlos Lopez a09598
	std::list<dockdialog*>::iterator iter;</dockdialog*>
Carlos Lopez a09598
	for(iter=dock_dialog_list_.begin();iter!=dock_dialog_list_.end();++iter)
Carlos Lopez a09598
		if((*iter)->get_id()==id)
Carlos Lopez a09598
			return **iter;
Carlos Lopez a09598
Carlos Lopez a09598
	DockDialog* dock_dialog(new DockDialog());
Carlos Lopez a09598
	dock_dialog->set_id(id);
Carlos Lopez a09598
	return *dock_dialog;
Carlos Lopez a09598
}
Carlos Lopez a09598
Carlos Lopez a09598
const DockDialog&
Carlos Lopez a09598
DockManager::find_dock_dialog(int id)const
Carlos Lopez a09598
{
Carlos Lopez a09598
	std::list<dockdialog*>::const_iterator iter;</dockdialog*>
Carlos Lopez a09598
	for(iter=dock_dialog_list_.begin();iter!=dock_dialog_list_.end();++iter)
Carlos Lopez a09598
		if((*iter)->get_id()==id)
Carlos Lopez a09598
			return **iter;
Carlos Lopez a09598
Carlos Lopez a09598
	throw std::runtime_error("DockManager::find_dock_dialog(int id)const: not found");
Carlos Lopez a09598
}
Carlos Lopez 0dca8f
Carlos Lopez 0dca8f
void
Carlos Lopez 0dca8f
DockManager::show_all_dock_dialogs()
Carlos Lopez 0dca8f
{
Carlos Lopez 0dca8f
	std::list<dockdialog*>::iterator iter;</dockdialog*>
Carlos Lopez 0dca8f
	for(iter=dock_dialog_list_.begin();iter!=dock_dialog_list_.end();++iter)
Carlos Lopez e3dfba
		(*iter)->present();
Carlos Lopez 0dca8f
}
464569
464569
bool
464569
DockManager::swap_widgets(Gtk::Widget &widget1, Gtk::Widget &widget2)
464569
{
464569
	DockLinkPoint point1(widget1);
464569
	DockLinkPoint point2(widget2);
464569
	if (point1.is_valid() && point2.is_valid())
464569
	{
464569
		point1.unlink();
464569
		point2.unlink();
464569
		point1.link(widget2);
464569
		point2.link(widget1);
464569
		return true;
464569
	}
464569
	return false;
464569
}
464569
464569
void
464569
DockManager::remove_widget_recursive(Gtk::Widget &widget)
464569
{
464569
	DockLinkPoint link(widget);
464569
	if (link.is_valid())
464569
	{
464569
		link.unlink();
464569
		if (link.paned)
464569
		{
464569
			Gtk::Widget &widget = link.is_first
464569
								? *link.paned->get_child2()
464569
								: *link.paned->get_child1();
464569
			DockLinkPoint paned_link(*link.paned);
464569
			if (paned_link.is_valid())
464569
			{
464569
				link.paned->remove(widget);
464569
				paned_link.unlink();
464569
				paned_link.link(widget);
464569
				delete link.paned;
464569
			}
464569
		}
464569
		else
464569
		if (link.window) link.window->hide();
464569
	}
464569
	else
464569
	if (widget.get_parent())
464569
	{
464569
		DockBook *book = dynamic_cast<dockbook*>(widget.get_parent());</dockbook*>
464569
		widget.get_parent()->remove(widget);
464569
		if (book && book->pages().empty())
464569
		{
464569
			remove_widget_recursive(*book);
464569
			delete book;
464569
		}
464569
	}
464569
}
464569
464569
464569
bool
464569
DockManager::add_widget(Gtk::Widget &dest_widget, Gtk::Widget &src_widget, bool vertical, bool first)
464569
{
464569
	if (&src_widget == &dest_widget) return false;
464569
464569
	// check for src widget is parent for dest_widget
464569
	for(Gtk::Widget *parent = src_widget.get_parent(); parent != NULL; parent = parent->get_parent())
464569
		if (parent == &dest_widget)
464569
			return swap_widgets(src_widget, dest_widget);
464569
464569
	// unlink dest_widget
464569
	DockLinkPoint dest_link(dest_widget);
464569
	if (!dest_link.is_valid()) return false;
464569
	dest_link.unlink();
464569
464569
	// unlink src_widget
464569
	remove_widget_recursive(src_widget);
464569
464569
	// create new paned and link all
464569
	Gtk::Paned *paned = manage(vertical ? (Gtk::Paned*)new Gtk::VPaned() : (Gtk::Paned*)new Gtk::HPaned());
464569
	paned->show();
464569
	DockLinkPoint(paned, first).link(src_widget);
464569
	DockLinkPoint(paned, !first).link(dest_widget);
464569
	dest_link.link(*paned);
464569
	return true;
464569
}
464569
464569
bool
464569
DockManager::add_dockable(Gtk::Widget &dest_widget, Dockable &dockable, bool vertical, bool first)
464569
{
464569
	DockBook *book = manage(new DockBook());
464569
	book->show();
464569
	if (add_widget(dest_widget, *book, vertical, first))
464569
	{
464569
		book->add(dockable);
464569
		return true;
464569
	}
464569
	delete book;
464569
	return false;
464569
}
464569
464569