Blame synfig-studio/src/gui/mainwindow.cpp

9b19d5
/* === S Y N F I G ========================================================= */
9b19d5
/*!	\file mainwindow.cpp
9b19d5
**	\brief MainWindow
9b19d5
**
9b19d5
**	$Id$
9b19d5
**
9b19d5
**	\legal
9b19d5
**	......... ... 2013 Ivan Mahonin
9b19d5
**
9b19d5
**	This package is free software; you can redistribute it and/or
9b19d5
**	modify it under the terms of the GNU General Public License as
9b19d5
**	published by the Free Software Foundation; either version 2 of
9b19d5
**	the License, or (at your option) any later version.
9b19d5
**
9b19d5
**	This package is distributed in the hope that it will be useful,
9b19d5
**	but WITHOUT ANY WARRANTY; without even the implied warranty of
9b19d5
**	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
9b19d5
**	General Public License for more details.
9b19d5
**	\endlegal
9b19d5
*/
9b19d5
/* ========================================================================= */
9b19d5
9b19d5
/* === H E A D E R S ======================================================= */
9b19d5
9b19d5
#ifdef USING_PCH
9b19d5
#	include "pch.h"
9b19d5
#else
9b19d5
#ifdef HAVE_CONFIG_H
9b19d5
#	include <config.h></config.h>
9b19d5
#endif
9b19d5
bw 94d8a6
#include <synfig general.h=""></synfig>
bw 94d8a6
abdbf2
#include <gui localization.h=""></gui>
bw 94d8a6
a488c9
#include "mainwindow.h"
ec177c
#include "canvasview.h"
839371
#include "docks/dockable.h"
f24ab7
#include "docks/dockbook.h"
839371
#include "docks/dockmanager.h"
990a0b
#include "docks/dockdroparea.h"
81cb2a
#include "dialogs/dialog_input.h"
9b19d5
0bf1ea
#include <synfigapp main.h=""></synfigapp>
0bf1ea
8a95fc
#include <gtkmm menubar.h=""></gtkmm>
363ac2
#include <gtkmm box.h=""></gtkmm>
8a95fc
Rodolfo Ribeiro Gomes 37680c
#include <gtkmm textview.h=""></gtkmm>
Rodolfo Ribeiro Gomes 37680c
Rodolfo Ribeiro Gomes 025eec
#include "gui/widgets/widget_time.h"
Rodolfo Ribeiro Gomes f49551
#include "gui/widgets/widget_vector.h"
Rodolfo Ribeiro Gomes f49551
9b19d5
#endif
9b19d5
9b19d5
/* === U S I N G =========================================================== */
9b19d5
9b19d5
using namespace std;
9b19d5
using namespace etl;
0bf1ea
using namespace synfig;
9b19d5
using namespace studio;
9b19d5
9b19d5
/* === M A C R O S ========================================================= */
9b19d5
0bf1ea
#define GRAB_HINT_DATA(y)	{ \
0bf1ea
		String x; \
0bf1ea
		if(synfigapp::Main::settings().get_value(String("pref.")+y+"_hints",x)) \
0bf1ea
		{ \
0bf1ea
			set_type_hint((Gdk::WindowTypeHint)atoi(x.c_str()));	\
0bf1ea
		} \
0bf1ea
	}
0bf1ea
9b19d5
/* === G L O B A L S ======================================================= */
9b19d5
9b19d5
/* === P R O C E D U R E S ================================================= */
9b19d5
9b19d5
/* === M E T H O D S ======================================================= */
9b19d5
Rodolfo Ribeiro Gomes b62117
MainWindow::MainWindow() :
Rodolfo Ribeiro Gomes cbe448
	save_workspace_merge_id(0), custom_workspaces_merge_id(0)
9b19d5
{
Rodolfo Ribeiro Gomes f49551
	register_custom_widget_types();
Rodolfo Ribeiro Gomes 230b91
0bf1ea
	set_default_size(600, 400);
0bf1ea
f24ab7
	main_dock_book_ = manage(new DockBook());
f24ab7
	main_dock_book_->allow_empty = true;
f24ab7
	main_dock_book_->show();
363ac2
990a0b
	class Bin : public Gtk::Bin {
990a0b
	public:
990a0b
		Bin() { }
990a0b
	protected:
990a0b
		void on_size_allocate(Gtk::Allocation &allocation) {
990a0b
			Gtk::Bin::on_size_allocate(allocation);
990a0b
			if (get_child() != NULL)
990a0b
				get_child()->size_allocate(allocation);
990a0b
		}
990a0b
	};
990a0b
8e0196
	bin_ = manage((Gtk::Bin*)new Bin());
f24ab7
	bin_->add(*main_dock_book_);
8e0196
	bin_->show();
363ac2
363ac2
	Gtk::VBox *vbox = manage(new Gtk::VBox());
a316ef
a316ef
	Gtk::Widget* menubar = App::ui_manager()->get_widget("/menubar-main");
a316ef
	if (menubar != NULL)
a316ef
	{
363ac2
		vbox->pack_start(*menubar, false, false, 0);
a316ef
	}
a316ef
8e0196
	vbox->pack_end(*bin_, true, true, 0);
363ac2
	vbox->show();
627b6c
	if(!App::enable_mainwin_menubar && menubar) menubar->hide();
Yu Chen 1bae28
363ac2
	add(*vbox);
8a95fc
ac4c88
	init_menus();
e8e764
	window_action_group = Gtk::ActionGroup::create("mainwindow-window");
Yu Chen ca1b1f
	App::ui_manager()->insert_action_group(window_action_group);
ac4c88
0865f9
	App::signal_recent_files_changed().connect(
0865f9
		sigc::mem_fun(*this, &MainWindow::on_recent_files_changed) );
0bf1ea
Rodolfo Ribeiro Gomes 4d2447
	App::signal_custom_workspaces_changed().connect(
Rodolfo Ribeiro Gomes 4d2447
		sigc::mem_fun(*this, &MainWindow::on_custom_workspaces_changed) );
Rodolfo Ribeiro Gomes 4d2447
839371
	signal_delete_event().connect(
839371
		sigc::ptr_fun(App::shutdown_request) );
839371
839371
	App::dock_manager->signal_dockable_registered().connect(
839371
		sigc::mem_fun(*this,&MainWindow::on_dockable_registered) );
839371
[d.j.a.y] Jerome Blanchi d5e08d
	App::dock_manager->signal_dockable_unregistered().connect(
[d.j.a.y] Jerome Blanchi d5e08d
		sigc::mem_fun(*this,&MainWindow::on_dockable_unregistered) );
[d.j.a.y] Jerome Blanchi d5e08d
650be2
	GRAB_HINT_DATA("mainwindow");
9b19d5
}
9b19d5
Yu Chen 1bae28
MainWindow::~MainWindow(){ }
9b19d5
3d521f
void
3d521f
MainWindow::show_dialog_input()
3d521f
{
49c639
	App::dialog_input->reset();
81cb2a
	App::dialog_input->present();
3d521f
}
3d521f
ec177c
void
a316ef
MainWindow::init_menus()
8a95fc
{
ac4c88
	Glib::RefPtr<gtk::actiongroup> action_group = Gtk::ActionGroup::create("mainwindow");</gtk::actiongroup>
a316ef
3d521f
	// file
Yu Chen cbb267
	action_group->add( Gtk::Action::create("new", Gtk::StockID("synfig-new_doc"), _("New"), _("Create a new document")),
a316ef
		sigc::hide_return(sigc::ptr_fun(&studio::App::new_instance))
a316ef
	);
Yu Chen 7f87f4
	action_group->add( Gtk::Action::create("open", Gtk::StockID("synfig-open"), _("Open"), _("Open an existing document")),
ac4c88
		sigc::hide_return(sigc::bind(sigc::ptr_fun(&studio::App::dialog_open), ""))
a316ef
	);
Yu Chen e87a04
	action_group->add( Gtk::Action::create("quit", Gtk::StockID("gtk-quit"), _("Quit")),
Yu Chen e87a04
		sigc::hide_return(sigc::ptr_fun(&studio::App::quit))
Yu Chen e87a04
	);
Yu Chen e87a04
Yu Chen e87a04
	// Edit menu
3d521f
	action_group->add( Gtk::Action::create("input-devices", _("Input Devices...")),
3d521f
		sigc::ptr_fun(&MainWindow::show_dialog_input)
3d521f
	);
Yu Chen 85f462
	action_group->add( Gtk::Action::create("setup", _("Preferences...")),
3d521f
		sigc::ptr_fun(&studio::App::show_setup)
3d521f
	);
a316ef
Yu Chen fc950e
	// View menu
Rodolfo Ribeiro Gomes 3b3f0c
	Glib::RefPtr<gtk::toggleaction> toggle_menubar = Gtk::ToggleAction::create("toggle-mainwin-menubar", _("Show Menubar"));</gtk::toggleaction>
Rodolfo Ribeiro Gomes 3b3f0c
	toggle_menubar->set_active(App::enable_mainwin_menubar);
Yu Chen fc950e
	action_group->add(toggle_menubar, sigc::mem_fun(*this, &studio::MainWindow::toggle_show_menubar));
Yu Chen fc950e
Yu Chen a3d404
	// pre defined workspace (window ui layout)
Yu Chen 1a0ab6
	action_group->add( Gtk::Action::create("workspace-compositing", _("Compositing")),
Yu Chen 1a0ab6
		sigc::ptr_fun(App::set_workspace_compositing)
3d521f
	);
Yu Chen 1a0ab6
	action_group->add( Gtk::Action::create("workspace-animating", _("Animating")),
Yu Chen 1a0ab6
		sigc::ptr_fun(App::set_workspace_animating)
3d521f
	);
Yu Chen 1a0ab6
	action_group->add( Gtk::Action::create("workspace-default", _("Default")),
Yu Chen 1a0ab6
		sigc::ptr_fun(App::set_workspace_default)
3d521f
	);
Rodolfo Ribeiro Gomes a80b23
	action_group->add( Gtk::Action::create("save-workspace", Gtk::StockID("synfig-save_as"), _("Save workspace...")),
Rodolfo Ribeiro Gomes 4d2447
		sigc::ptr_fun(App::save_custom_workspace)
Rodolfo Ribeiro Gomes 4d2447
	);
3d521f
9e8228
	action_group->add( Gtk::Action::create("edit-workspacelist", _("Edit workspaces...")),
Rodolfo Ribeiro Gomes cbe448
		sigc::ptr_fun(App::edit_custom_workspace_list)
Rodolfo Ribeiro Gomes cbe448
	);
Rodolfo Ribeiro Gomes cbe448
3d521f
	// help
3d521f
	#define URL(action_name,title,url) \
3d521f
		action_group->add( Gtk::Action::create(action_name, title), \
118374
			sigc::bind(sigc::ptr_fun(&studio::App::open_uri),url))
3d521f
	#define WIKI(action_name,title,page) \
3b3496
		URL(action_name,title, "https://wiki.synfig.org/" + String(page))
3d521f
3d521f
	action_group->add( Gtk::Action::create("help", Gtk::Stock::HELP),
3d521f
		sigc::ptr_fun(studio::App::dialog_help)
3d521f
	);
3d521f
3d521f
	// TRANSLATORS:         | Help menu entry:              | A wiki page:          |
3d521f
	WIKI("help-tutorials",	_("Tutorials"),					_("/Category:Tutorials"));
3d521f
	WIKI("help-reference",	_("Reference"),					_("/Category:Reference"));
3d521f
	WIKI("help-faq",		_("Frequently Asked Questions"),_("/FAQ")				);
5d89e1
	URL("help-support",		_("Get Support"),				_("https://forums.synfig.org/")	);
3d521f
Yu Chen 1034aa
	action_group->add( Gtk::Action::create(
Yu Chen 770123
			"help-about", Gtk::StockID("synfig-about"), _("About Synfig Studio")),
3d521f
		sigc::ptr_fun(studio::App::dialog_about)
3d521f
	);
3d521f
3d521f
	// TODO: open recent
3d521f
	//filemenu->items().push_back(Gtk::Menu_Helpers::MenuElem(_("Open Recent"),*recent_files_menu));
3d521f
ac4c88
	App::ui_manager()->insert_action_group(action_group);
Rodolfo Ribeiro Gomes b62117
Rodolfo Ribeiro Gomes b62117
	add_custom_workspace_menu_item_handlers();
a316ef
}
8a95fc
Rodolfo Ribeiro Gomes f49551
void MainWindow::register_custom_widget_types()
Rodolfo Ribeiro Gomes f49551
{
Rodolfo Ribeiro Gomes f49551
	Widget_Vector::register_type();
Rodolfo Ribeiro Gomes 025eec
	Widget_Time::register_type();
Rodolfo Ribeiro Gomes f49551
}
839371
8a95fc
void
Yu Chen fc950e
MainWindow::toggle_show_menubar()
Yu Chen fc950e
{
Yu Chen fc950e
	Gtk::Widget* menubar = App::ui_manager()->get_widget("/menubar-main");
Yu Chen fc950e
Rodolfo Ribeiro Gomes c7a97c
	App::enable_mainwin_menubar = !App::enable_mainwin_menubar;
Rodolfo Ribeiro Gomes c7a97c
Rodolfo Ribeiro Gomes c7a97c
	if(App::enable_mainwin_menubar)
Yu Chen fc950e
		menubar->show();
Rodolfo Ribeiro Gomes c7a97c
	else
Rodolfo Ribeiro Gomes c7a97c
		menubar->hide();
Yu Chen fc950e
}
Yu Chen fc950e
Rodolfo Ribeiro Gomes b62117
void MainWindow::add_custom_workspace_menu_item_handlers()
Rodolfo Ribeiro Gomes b62117
{
Rodolfo Ribeiro Gomes b62117
	std::string ui_info_menu =
Rodolfo Ribeiro Gomes b62117
			"<menu action="menu-window">"</menu>
Rodolfo Ribeiro Gomes b62117
			"	<menu action="menu-workspace">"</menu>
Rodolfo Ribeiro Gomes b62117
			"	    <separator name="sep-window2">"</separator>
Rodolfo Ribeiro Gomes b62117
			"		<menuitem action="save-workspace">"</menuitem>
Rodolfo Ribeiro Gomes cbe448
			"		<menuitem action="edit-workspacelist">"</menuitem>
Rodolfo Ribeiro Gomes b62117
			"	"
Rodolfo Ribeiro Gomes b62117
			"";
Rodolfo Ribeiro Gomes b62117
Rodolfo Ribeiro Gomes b62117
	std::string ui_info =
Rodolfo Ribeiro Gomes b62117
			"<ui>"</ui>
Rodolfo Ribeiro Gomes b62117
			"  <popup action="menu-main" name="menu-main">" + ui_info_menu + "</popup>"
Rodolfo Ribeiro Gomes b62117
			"  <menubar action="menubar-main" name="menubar-main">" + ui_info_menu + "</menubar>"
Rodolfo Ribeiro Gomes b62117
			"";
Rodolfo Ribeiro Gomes b62117
Rodolfo Ribeiro Gomes b62117
	save_workspace_merge_id = App::ui_manager()->add_ui_from_string(ui_info);
Rodolfo Ribeiro Gomes b62117
}
Rodolfo Ribeiro Gomes b62117
Rodolfo Ribeiro Gomes b62117
void MainWindow::remove_custom_workspace_menu_item_handlers()
Rodolfo Ribeiro Gomes b62117
{
Rodolfo Ribeiro Gomes b62117
	App::ui_manager()->remove_ui(save_workspace_merge_id);
Rodolfo Ribeiro Gomes b62117
}
Rodolfo Ribeiro Gomes b62117
Rodolfo Ribeiro Gomes 37680c
bool
Rodolfo Ribeiro Gomes 37680c
MainWindow::on_key_press_event(GdkEventKey* key_event)
Rodolfo Ribeiro Gomes 37680c
{
Rodolfo Ribeiro Gomes 37680c
	Gtk::Widget * widget = get_focus();
Rodolfo Ribeiro Gomes 0dfb65
	if (widget && (dynamic_cast<gtk::editable*>(widget) || dynamic_cast<gtk::textview*>(widget) || dynamic_cast<gtk::drawingarea*>(widget))) {</gtk::drawingarea*></gtk::textview*></gtk::editable*>
Rodolfo Ribeiro Gomes 37680c
		bool handled = gtk_window_propagate_key_event(this->gobj(), key_event);
Rodolfo Ribeiro Gomes 37680c
		if (handled)
Rodolfo Ribeiro Gomes 37680c
			return true;
Rodolfo Ribeiro Gomes 37680c
	}
Rodolfo Ribeiro Gomes 37680c
	return Gtk::Window::on_key_press_event(key_event);
Rodolfo Ribeiro Gomes 37680c
}
Rodolfo Ribeiro Gomes 37680c
6534e7
void
de146d
MainWindow::make_short_filenames(
6534e7
	const std::vector<synfig::string> &fullnames,</synfig::string>
6534e7
	std::vector<synfig::string> &shortnames )</synfig::string>
6534e7
{
de146d
	if (fullnames.size() == 1)
de146d
	{
de146d
		shortnames.resize(1);
de146d
		shortnames[0] = etl::basename(fullnames[0]);
de146d
		return;
de146d
	}
de146d
6534e7
	const int count = (int)fullnames.size();
6534e7
	vector< vector<string> > dirs(count);</string>
6534e7
	vector< vector<bool> > dirflags(count);</bool>
6534e7
	shortnames.clear();
6534e7
	shortnames.resize(count);
6534e7
6534e7
	// build dir lists
6534e7
	for(int i = 0; i < count; ++i) {
6534e7
		int j = 0;
de146d
		String fullname = fullnames[i];
de146d
		if (fullname.substr(0, 7) == "file://")
de146d
			fullname = fullname.substr(7);
de146d
		while(j < (int)fullname.size())
6534e7
		{
de146d
			size_t k = fullname.find_first_of(ETL_DIRECTORY_SEPARATORS, j);
de146d
			if (k == string::npos) k = fullname.size();
de146d
			string sub = fullname.substr(j, k - j);
6534e7
			if (!sub.empty() && sub != "...")
6534e7
				dirs[i].insert(dirs[i].begin(), sub);
6534e7
			j = (int)k + 1;
6534e7
		}
6534e7
6534e7
		dirflags[i].resize(dirs.size(), false);
6534e7
	}
6534e7
6534e7
	// find shotest paths which shows that files are different
6534e7
	for(int i = 0; i < count; ++i) {
6534e7
		for(int j = 0; j < count; ++j) {
6534e7
			if (i == j) continue;
6534e7
			for(int k = 0; k < (int)dirs[i].size(); ++k) {
6534e7
				dirflags[i][k] = true;
6534e7
				if (k >= (int)dirs[j].size() || dirs[i][k] != dirs[j][k])
6534e7
					break;
6534e7
			}
6534e7
		}
6534e7
	}
6534e7
6534e7
	// remove non-informative dirs from middle of shortest paths
6534e7
	// holes will shown as "/.../" at final stage
6534e7
	for(int i = 0; i < count; ++i) {
6534e7
		for(int k = 1; k < (int)dirs[i].size() && dirflags[i][k]; ++k) {
6534e7
			dirflags[i][k] = false;
6534e7
			for(int j = 0; j < count; ++j) {
6534e7
				if (i == j) continue;
6534e7
				int index = -1;
6534e7
				for(int l = 0; l < (int)dirs[i].size(); ++l) {
6534e7
					if (dirflags[i][l]) {
6534e7
						++index;
6534e7
						while(index < (int)dirs[j].size() && dirs[i][l] != dirs[j][index])
6534e7
							++index;
6534e7
					}
6534e7
				}
6534e7
				if (index < (int)dirs[j].size()) {
6534e7
					dirflags[i][k] = true;
6534e7
					break;
6534e7
				}
6534e7
			}
6534e7
		}
6534e7
	}
6534e7
6534e7
	// concatenate dir-lists to short names
6534e7
	for(int i = 0; i < count; ++i) {
6534e7
		int prevk = 0;
6534e7
		for(int k = 0; k < (int)dirs[i].size(); ++k) {
6534e7
			if (dirflags[i][k]) {
6534e7
				if (prevk < k) shortnames[i] = "/"+shortnames[i];
6534e7
				if (prevk < k-1) shortnames[i] = "/..."+shortnames[i];
6534e7
				shortnames[i] = dirs[i][k] + shortnames[i];
6534e7
				prevk = k;
6534e7
			}
6534e7
		}
6534e7
	}
6534e7
}
Yu Chen fc950e
Yu Chen fc950e
void
0865f9
MainWindow::on_recent_files_changed()
0865f9
{
0865f9
	Glib::RefPtr<gtk::actiongroup> action_group = Gtk::ActionGroup::create("mainwindow-recentfiles");</gtk::actiongroup>
0865f9
6534e7
	vector<string> fullnames(App::get_recent_files().begin(), App::get_recent_files().end());</string>
6534e7
	vector<string> shortnames;</string>
de146d
	make_short_filenames(fullnames, shortnames);
6534e7
0865f9
	std::string menu_items;
6534e7
	for(int i = 0; i < (int)fullnames.size(); ++i)
0865f9
	{
6534e7
		std::string raw = shortnames[i];
0865f9
		std::string quoted;
0865f9
		size_t pos = 0, last_pos = 0;
0865f9
0865f9
		// replace _ in filenames by __ or it won't show up in the menu
0865f9
		for (pos = last_pos = 0; (pos = raw.find('_', pos)) != string::npos; last_pos = pos)
0865f9
			quoted += raw.substr(last_pos, ++pos - last_pos) + '_';
0865f9
		quoted += raw.substr(last_pos);
0865f9
6534e7
		std::string action_name = strprintf("file-recent-%d", i);
0865f9
		menu_items += "<menuitem action="" + action_name +"">";</menuitem>
0865f9
6534e7
		action_group->add( Gtk::Action::create(action_name, quoted, fullnames[i]),
6534e7
			sigc::hide_return(sigc::bind(sigc::ptr_fun(&App::open),fullnames[i]))
0865f9
		);
0865f9
	}
0865f9
0865f9
	std::string ui_info =
0865f9
		"<menu action="menu-file"><menu action="menu-open-recent">"</menu></menu>
0865f9
	  + menu_items
0865f9
	  + "";
0865f9
	std::string ui_info_popup =
0865f9
		"<ui><popup action="menu-main">" + ui_info + "</popup></ui>";
0865f9
	std::string ui_info_menubar =
0865f9
		"<ui><menubar action="menubar-main">" + ui_info + "</menubar></ui>";
0865f9
bd7d8b
	// remove group if exists
bd7d8b
	typedef std::vector< Glib::RefPtr<gtk::actiongroup> > ActionGroupList;</gtk::actiongroup>
bd7d8b
	ActionGroupList groups = App::ui_manager()->get_action_groups();
bd7d8b
	for(ActionGroupList::const_iterator i = groups.begin(); i != groups.end(); ++i)
bd7d8b
		if ((*i)->get_name() == action_group->get_name())
Rodolfo Ribeiro Gomes 4d2447
			App::ui_manager()->remove_action_group(*i);
Rodolfo Ribeiro Gomes 4d2447
	groups.clear();
Rodolfo Ribeiro Gomes 4d2447
Rodolfo Ribeiro Gomes 4d2447
	App::ui_manager()->insert_action_group(action_group);
Rodolfo Ribeiro Gomes 4d2447
	App::ui_manager()->add_ui_from_string(ui_info_popup);
Rodolfo Ribeiro Gomes 4d2447
	App::ui_manager()->add_ui_from_string(ui_info_menubar);
Rodolfo Ribeiro Gomes 4d2447
}
Rodolfo Ribeiro Gomes 4d2447
Rodolfo Ribeiro Gomes 4d2447
void
Rodolfo Ribeiro Gomes 4d2447
MainWindow::on_custom_workspaces_changed()
Rodolfo Ribeiro Gomes 4d2447
{
Rodolfo Ribeiro Gomes 4d2447
	Glib::RefPtr<gtk::actiongroup> action_group = Gtk::ActionGroup::create("mainwindow-customworkspaces");</gtk::actiongroup>
Rodolfo Ribeiro Gomes 4d2447
Rodolfo Ribeiro Gomes 4d2447
	vector<string> workspaces = App::get_workspaces();</string>
Rodolfo Ribeiro Gomes 4d2447
Rodolfo Ribeiro Gomes 4d2447
	std::string menu_items;
Rodolfo Ribeiro Gomes 36b16f
	unsigned int num_custom_workspaces = 0;
Rodolfo Ribeiro Gomes 36b16f
	for (auto it = workspaces.cbegin(); it != workspaces.cend(); ++it, ++num_custom_workspaces) {
Rodolfo Ribeiro Gomes 4d2447
		std::string raw = *it;
Rodolfo Ribeiro Gomes 4d2447
		std::string quoted;
Rodolfo Ribeiro Gomes 4d2447
		size_t pos = 0, last_pos = 0;
Rodolfo Ribeiro Gomes 4d2447
Rodolfo Ribeiro Gomes 4d2447
		// replace _ in names by __ or it won't show up in the menu
Rodolfo Ribeiro Gomes 4d2447
		for (pos = last_pos = 0; (pos = raw.find('_', pos)) != string::npos; last_pos = pos)
Rodolfo Ribeiro Gomes 4d2447
			quoted += raw.substr(last_pos, ++pos - last_pos) + '_';
Rodolfo Ribeiro Gomes 4d2447
		quoted += raw.substr(last_pos);
Rodolfo Ribeiro Gomes 4d2447
Rodolfo Ribeiro Gomes 36b16f
		std::string action_name = strprintf("custom-workspace-%d", num_custom_workspaces);
Rodolfo Ribeiro Gomes 4d2447
		menu_items += "<menuitem action="" + action_name +"">";</menuitem>
Rodolfo Ribeiro Gomes 4d2447
Rodolfo Ribeiro Gomes 4d2447
		action_group->add( Gtk::Action::create(action_name, quoted),
Rodolfo Ribeiro Gomes 36b16f
			sigc::bind(sigc::ptr_fun(&App::set_workspace_from_name), workspaces[num_custom_workspaces])
Rodolfo Ribeiro Gomes 4d2447
		);
Rodolfo Ribeiro Gomes 4d2447
	}
Rodolfo Ribeiro Gomes b62117
	if (num_custom_workspaces > 0)
Rodolfo Ribeiro Gomes b62117
		menu_items = "<separator name="sep-window1">" + menu_items;</separator>
Rodolfo Ribeiro Gomes b62117
Rodolfo Ribeiro Gomes b62117
	remove_custom_workspace_menu_item_handlers();
Rodolfo Ribeiro Gomes cbe448
	if (custom_workspaces_merge_id)
Rodolfo Ribeiro Gomes cbe448
		App::ui_manager()->remove_ui(custom_workspaces_merge_id);
Rodolfo Ribeiro Gomes 4d2447
Rodolfo Ribeiro Gomes 4d2447
	std::string ui_info =
Rodolfo Ribeiro Gomes 4d2447
		"<menu action="menu-window"><menu action="menu-workspace">"</menu></menu>
Rodolfo Ribeiro Gomes 4d2447
	  + menu_items
Rodolfo Ribeiro Gomes 4d2447
	  + "";
Rodolfo Ribeiro Gomes 4d2447
	std::string ui_info_popup =
Rodolfo Ribeiro Gomes cbe448
		"<popup action="menu-main">" + ui_info + "</popup>";
Rodolfo Ribeiro Gomes 4d2447
	std::string ui_info_menubar =
Rodolfo Ribeiro Gomes cbe448
		"<menubar action="menubar-main">" + ui_info + "</menubar>";
Rodolfo Ribeiro Gomes 4d2447
Rodolfo Ribeiro Gomes 4d2447
	// remove group if exists
Rodolfo Ribeiro Gomes 4d2447
	typedef std::vector< Glib::RefPtr<gtk::actiongroup> > ActionGroupList;</gtk::actiongroup>
Rodolfo Ribeiro Gomes 4d2447
	ActionGroupList groups = App::ui_manager()->get_action_groups();
Rodolfo Ribeiro Gomes 36b16f
	for(ActionGroupList::const_iterator it = groups.begin(); it != groups.end(); ++it)
Rodolfo Ribeiro Gomes b62117
		if ((*it)->get_name() == action_group->get_name()) {
Rodolfo Ribeiro Gomes 36b16f
			App::ui_manager()->remove_action_group(*it);
Rodolfo Ribeiro Gomes b62117
			break;
Rodolfo Ribeiro Gomes b62117
		}
bd7d8b
	groups.clear();
Rodolfo Ribeiro Gomes cbe448
	App::ui_manager()->ensure_update();
bd7d8b
0865f9
	App::ui_manager()->insert_action_group(action_group);
Rodolfo Ribeiro Gomes cbe448
	custom_workspaces_merge_id = App::ui_manager()->add_ui_from_string("<ui>" + ui_info_popup + ui_info_menubar + "</ui>");
Rodolfo Ribeiro Gomes b62117
Rodolfo Ribeiro Gomes b62117
	add_custom_workspace_menu_item_handlers();
0865f9
}
0865f9
0865f9
void
839371
MainWindow::on_dockable_registered(Dockable* dockable)
839371
{
Yu Chen 15b598
Yu Chen 15b598
	// replace _ in panel names (filenames) by __ or it won't show up in the menu,
Yu Chen 15b598
	// this block code is just a copy from MainWindow::on_recent_files_changed().
Yu Chen 15b598
	std::string raw = dockable->get_local_name();
Yu Chen 15b598
	std::string quoted;
Yu Chen 15b598
	size_t pos = 0, last_pos = 0;
Yu Chen 15b598
	for (pos = last_pos = 0; (pos = raw.find('_', pos)) != string::npos; last_pos = pos)
Yu Chen 15b598
		quoted += raw.substr(last_pos, ++pos - last_pos) + '_';
Yu Chen 15b598
	quoted += raw.substr(last_pos);
Yu Chen 15b598
Yu Chen 15b598
	window_action_group->add( Gtk::Action::create("panel-" + dockable->get_name(), quoted),
839371
		sigc::mem_fun(*dockable, &Dockable::present)
839371
	);
839371
839371
	std::string ui_info =
Yu Chen ca1b1f
		"<menu action="menu-window">"</menu>
839371
	    "<menuitem action="panel-" + dockable-&gt;get_name() + "">"</menuitem>
Yu Chen aba2a3
	    "";
839371
	std::string ui_info_popup =
839371
		"<ui><popup action="menu-main">" + ui_info + "</popup></ui>";
839371
	std::string ui_info_menubar =
839371
		"<ui><menubar action="menubar-main">" + ui_info + "</menubar></ui>";
839371
[d.j.a.y] Jerome Blanchi 2f1ef9
	Gtk::UIManager::ui_merge_id merge_id_popup = App::ui_manager()->add_ui_from_string(ui_info_popup);
[d.j.a.y] Jerome Blanchi 2f1ef9
	Gtk::UIManager::ui_merge_id merge_id_menubar = App::ui_manager()->add_ui_from_string(ui_info_menubar);
[d.j.a.y] Jerome Blanchi 2f1ef9
[d.j.a.y] Jerome Blanchi 2f1ef9
	// record CanvasView toolbar and popup id's
[d.j.a.y] Jerome Blanchi 2f1ef9
	CanvasView *canvas_view = dynamic_cast<canvasview*>(dockable);</canvasview*>
[d.j.a.y] Jerome Blanchi 2f1ef9
	if(canvas_view)
[d.j.a.y] Jerome Blanchi 2f1ef9
	{
[d.j.a.y] Jerome Blanchi 2f1ef9
		canvas_view->set_popup_id(merge_id_popup);
[d.j.a.y] Jerome Blanchi 2f1ef9
		canvas_view->set_toolbar_id(merge_id_menubar);
[d.j.a.y] Jerome Blanchi 2f1ef9
	}
839371
}
839371
[d.j.a.y] Jerome Blanchi d5e08d
void
[d.j.a.y] Jerome Blanchi d5e08d
MainWindow::on_dockable_unregistered(Dockable* dockable)
[d.j.a.y] Jerome Blanchi d5e08d
{
[d.j.a.y] Jerome Blanchi ee2ca5
	// remove the document from the menus
[d.j.a.y] Jerome Blanchi ee2ca5
	CanvasView *canvas_view = dynamic_cast<canvasview*>(dockable);</canvasview*>
[d.j.a.y] Jerome Blanchi ee2ca5
	if(canvas_view)
[d.j.a.y] Jerome Blanchi ee2ca5
	{
[d.j.a.y] Jerome Blanchi ee2ca5
		App::ui_manager()->remove_ui(canvas_view->get_popup_id());
[d.j.a.y] Jerome Blanchi ee2ca5
		App::ui_manager()->remove_ui(canvas_view->get_toolbar_id());
[d.j.a.y] Jerome Blanchi ee2ca5
	}
[d.j.a.y] Jerome Blanchi d5e08d
}
9b19d5
/* === E N T R Y P O I N T ================================================= */