2015-02-12 12:16:25 -03:00
|
|
|
// Aseprite
|
|
|
|
// Copyright (C) 2001-2015 David Capello
|
|
|
|
//
|
|
|
|
// This program is free software; you can redistribute it and/or modify
|
|
|
|
// it under the terms of the GNU General Public License version 2 as
|
|
|
|
// published by the Free Software Foundation.
|
2007-09-18 23:57:02 +00:00
|
|
|
|
2013-08-05 21:20:19 -03:00
|
|
|
#ifdef HAVE_CONFIG_H
|
2007-09-18 23:57:02 +00:00
|
|
|
#include "config.h"
|
2013-08-05 21:20:19 -03:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#include "app/app_menus.h"
|
|
|
|
|
|
|
|
#include "app/app.h"
|
|
|
|
#include "app/commands/command.h"
|
|
|
|
#include "app/commands/commands.h"
|
|
|
|
#include "app/commands/params.h"
|
|
|
|
#include "app/console.h"
|
|
|
|
#include "app/gui_xml.h"
|
|
|
|
#include "app/recent_files.h"
|
2014-10-29 11:58:03 -03:00
|
|
|
#include "app/resource_finder.h"
|
2013-08-05 21:20:19 -03:00
|
|
|
#include "app/tools/tool_box.h"
|
|
|
|
#include "app/ui/app_menuitem.h"
|
2014-10-29 11:58:03 -03:00
|
|
|
#include "app/ui/keyboard_shortcuts.h"
|
2013-08-05 21:20:19 -03:00
|
|
|
#include "app/ui/main_window.h"
|
|
|
|
#include "app/util/filetoks.h"
|
2012-07-09 13:20:58 -03:00
|
|
|
#include "base/bind.h"
|
2014-10-29 11:58:03 -03:00
|
|
|
#include "base/fs.h"
|
2014-09-21 11:59:39 -03:00
|
|
|
#include "base/path.h"
|
2013-08-05 21:20:19 -03:00
|
|
|
#include "ui/ui.h"
|
2007-09-18 23:57:02 +00:00
|
|
|
|
2009-12-16 23:24:57 +00:00
|
|
|
#include "tinyxml.h"
|
2014-09-21 11:59:39 -03:00
|
|
|
|
|
|
|
#include <cstdio>
|
|
|
|
#include <cstring>
|
2009-12-16 23:24:57 +00:00
|
|
|
|
2013-08-05 21:20:19 -03:00
|
|
|
namespace app {
|
|
|
|
|
2012-06-17 22:02:54 -03:00
|
|
|
using namespace ui;
|
|
|
|
|
2012-07-09 13:20:58 -03:00
|
|
|
static void destroy_instance(AppMenus* instance)
|
2007-09-18 23:57:02 +00:00
|
|
|
{
|
2012-07-09 13:20:58 -03:00
|
|
|
delete instance;
|
2007-09-18 23:57:02 +00:00
|
|
|
}
|
|
|
|
|
2012-07-09 13:20:58 -03:00
|
|
|
// static
|
|
|
|
AppMenus* AppMenus::instance()
|
2007-09-18 23:57:02 +00:00
|
|
|
{
|
2012-07-09 13:20:58 -03:00
|
|
|
static AppMenus* instance = NULL;
|
|
|
|
if (!instance) {
|
|
|
|
instance = new AppMenus;
|
|
|
|
App::instance()->Exit.connect(Bind<void>(&destroy_instance, instance));
|
|
|
|
}
|
|
|
|
return instance;
|
2007-09-18 23:57:02 +00:00
|
|
|
}
|
|
|
|
|
2012-07-09 13:20:58 -03:00
|
|
|
AppMenus::AppMenus()
|
|
|
|
: m_recentListMenuitem(NULL)
|
2007-09-18 23:57:02 +00:00
|
|
|
{
|
2015-03-02 11:18:33 -03:00
|
|
|
m_recentFilesConn =
|
|
|
|
App::instance()->getRecentFiles()->Changed.connect(
|
|
|
|
Bind(&AppMenus::rebuildRecentList, this));
|
2012-07-09 13:20:58 -03:00
|
|
|
}
|
2012-01-05 19:45:03 -03:00
|
|
|
|
2012-07-09 13:20:58 -03:00
|
|
|
void AppMenus::reload()
|
|
|
|
{
|
2013-10-14 19:58:11 -03:00
|
|
|
XmlDocumentRef doc(GuiXml::instance()->doc());
|
2015-04-02 20:42:43 -03:00
|
|
|
TiXmlHandle handle(doc.get());
|
2010-10-27 17:21:12 -03:00
|
|
|
const char* path = GuiXml::instance()->filename();
|
2007-09-18 23:57:02 +00:00
|
|
|
|
2014-10-29 11:58:03 -03:00
|
|
|
////////////////////////////////////////
|
|
|
|
// Load menus
|
2009-12-16 23:24:57 +00:00
|
|
|
|
2010-10-27 17:21:12 -03:00
|
|
|
PRINTF(" - Loading menus from \"%s\"...\n", path);
|
2009-12-16 23:24:57 +00:00
|
|
|
|
2012-07-09 13:20:58 -03:00
|
|
|
m_rootMenu.reset(loadMenuById(handle, "main_menu"));
|
2009-12-16 23:24:57 +00:00
|
|
|
|
2011-08-22 21:37:14 -03:00
|
|
|
// Add a warning element because the user is not using the last well-known gui.xml file.
|
|
|
|
if (GuiXml::instance()->version() != VERSION)
|
2012-07-09 13:20:58 -03:00
|
|
|
m_rootMenu->insertChild(0, createInvalidVersionMenuitem());
|
2011-08-22 21:37:14 -03:00
|
|
|
|
2010-10-27 21:02:48 -03:00
|
|
|
PRINTF("Main menu loaded.\n");
|
|
|
|
|
2015-02-22 21:18:53 -03:00
|
|
|
m_tabPopupMenu.reset(loadMenuById(handle, "tab_popup"));
|
2012-07-09 13:20:58 -03:00
|
|
|
m_documentTabPopupMenu.reset(loadMenuById(handle, "document_tab_popup"));
|
|
|
|
m_layerPopupMenu.reset(loadMenuById(handle, "layer_popup"));
|
|
|
|
m_framePopupMenu.reset(loadMenuById(handle, "frame_popup"));
|
|
|
|
m_celPopupMenu.reset(loadMenuById(handle, "cel_popup"));
|
|
|
|
m_celMovementPopupMenu.reset(loadMenuById(handle, "cel_movement_popup"));
|
2015-03-10 16:44:18 -03:00
|
|
|
m_frameTagPopupMenu.reset(loadMenuById(handle, "frame_tag_popup"));
|
2015-05-08 14:36:54 -03:00
|
|
|
m_palettePopupMenu.reset(loadMenuById(handle, "palette_popup"));
|
2007-09-23 20:13:58 +00:00
|
|
|
|
2014-10-29 11:58:03 -03:00
|
|
|
////////////////////////////////////////
|
|
|
|
// Load keyboard shortcuts for commands
|
2010-10-27 17:21:12 -03:00
|
|
|
|
|
|
|
PRINTF(" - Loading commands keyboard shortcuts from \"%s\"...\n", path);
|
2009-12-16 23:24:57 +00:00
|
|
|
|
2010-10-27 17:21:12 -03:00
|
|
|
TiXmlElement* xmlKey = handle
|
|
|
|
.FirstChild("gui")
|
2014-10-29 11:58:03 -03:00
|
|
|
.FirstChild("keyboard").ToElement();
|
|
|
|
|
|
|
|
KeyboardShortcuts::instance()->clear();
|
|
|
|
KeyboardShortcuts::instance()->importFile(xmlKey, KeySource::Original);
|
|
|
|
|
|
|
|
// Load user settings
|
|
|
|
{
|
|
|
|
ResourceFinder rf;
|
|
|
|
rf.includeUserDir("user.aseprite-keys");
|
|
|
|
std::string fn = rf.getFirstOrCreateDefault();
|
|
|
|
if (base::is_file(fn))
|
|
|
|
KeyboardShortcuts::instance()->importFile(fn, KeySource::UserDefined);
|
2010-10-27 21:02:48 -03:00
|
|
|
}
|
2012-07-09 13:20:58 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
bool AppMenus::rebuildRecentList()
|
|
|
|
{
|
|
|
|
MenuItem* list_menuitem = m_recentListMenuitem;
|
|
|
|
MenuItem* menuitem;
|
|
|
|
|
|
|
|
// Update the recent file list menu item
|
|
|
|
if (list_menuitem) {
|
|
|
|
if (list_menuitem->hasSubmenuOpened())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
Command* cmd_open_file = CommandsModule::instance()->getCommandByName(CommandId::OpenFile);
|
|
|
|
|
|
|
|
Menu* submenu = list_menuitem->getSubmenu();
|
|
|
|
if (submenu) {
|
|
|
|
list_menuitem->setSubmenu(NULL);
|
|
|
|
submenu->deferDelete();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Build the menu of recent files
|
|
|
|
submenu = new Menu();
|
|
|
|
list_menuitem->setSubmenu(submenu);
|
|
|
|
|
|
|
|
RecentFiles::const_iterator it = App::instance()->getRecentFiles()->files_begin();
|
|
|
|
RecentFiles::const_iterator end = App::instance()->getRecentFiles()->files_end();
|
|
|
|
|
|
|
|
if (it != end) {
|
|
|
|
Params params;
|
|
|
|
|
|
|
|
for (; it != end; ++it) {
|
|
|
|
const char* filename = it->c_str();
|
|
|
|
params.set("filename", filename);
|
|
|
|
|
2014-09-21 11:59:39 -03:00
|
|
|
menuitem = new AppMenuItem(
|
|
|
|
base::get_file_name(filename).c_str(),
|
2015-03-11 15:40:22 -03:00
|
|
|
cmd_open_file,
|
|
|
|
params);
|
2012-07-09 13:20:58 -03:00
|
|
|
submenu->addChild(menuitem);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
2015-03-11 15:40:22 -03:00
|
|
|
menuitem = new AppMenuItem("Nothing", NULL, Params());
|
2012-07-09 13:20:58 -03:00
|
|
|
menuitem->setEnabled(false);
|
|
|
|
submenu->addChild(menuitem);
|
|
|
|
}
|
2007-09-18 23:57:02 +00:00
|
|
|
}
|
|
|
|
|
2012-07-09 13:20:58 -03:00
|
|
|
return true;
|
2007-09-18 23:57:02 +00:00
|
|
|
}
|
|
|
|
|
2012-07-09 13:20:58 -03:00
|
|
|
Menu* AppMenus::loadMenuById(TiXmlHandle& handle, const char* id)
|
2007-09-18 23:57:02 +00:00
|
|
|
{
|
2010-08-03 23:33:44 -03:00
|
|
|
ASSERT(id != NULL);
|
2009-10-09 01:34:06 +00:00
|
|
|
|
2012-07-09 13:20:58 -03:00
|
|
|
//PRINTF("loadMenuById(%s)\n", id);
|
2009-12-16 23:24:57 +00:00
|
|
|
|
|
|
|
// <gui><menus><menu>
|
|
|
|
TiXmlElement* xmlMenu = handle
|
|
|
|
.FirstChild("gui")
|
|
|
|
.FirstChild("menus")
|
|
|
|
.FirstChild("menu").ToElement();
|
|
|
|
while (xmlMenu) {
|
|
|
|
const char* menu_id = xmlMenu->Attribute("id");
|
|
|
|
|
|
|
|
if (menu_id && strcmp(menu_id, id) == 0)
|
2012-07-09 13:20:58 -03:00
|
|
|
return convertXmlelemToMenu(xmlMenu);
|
2009-12-16 23:24:57 +00:00
|
|
|
|
|
|
|
xmlMenu = xmlMenu->NextSiblingElement();
|
2007-09-18 23:57:02 +00:00
|
|
|
}
|
2008-01-06 19:30:17 +00:00
|
|
|
|
2012-07-09 13:20:58 -03:00
|
|
|
throw base::Exception("Error loading menu '%s'\nReinstall the application.", id);
|
2007-09-18 23:57:02 +00:00
|
|
|
}
|
|
|
|
|
2012-07-09 13:20:58 -03:00
|
|
|
Menu* AppMenus::convertXmlelemToMenu(TiXmlElement* elem)
|
2007-09-18 23:57:02 +00:00
|
|
|
{
|
2011-04-22 23:00:35 -03:00
|
|
|
Menu* menu = new Menu();
|
2007-09-23 20:13:58 +00:00
|
|
|
|
2012-07-09 13:20:58 -03:00
|
|
|
//PRINTF("convertXmlelemToMenu(%s, %s, %s)\n", elem->Value(), elem->Attribute("id"), elem->Attribute("text"));
|
2007-09-23 20:13:58 +00:00
|
|
|
|
2009-12-16 23:24:57 +00:00
|
|
|
TiXmlElement* child = elem->FirstChildElement();
|
|
|
|
while (child) {
|
2012-07-09 13:20:58 -03:00
|
|
|
Widget* menuitem = convertXmlelemToMenuitem(child);
|
2009-12-16 23:24:57 +00:00
|
|
|
if (menuitem)
|
2011-03-29 21:35:17 -03:00
|
|
|
menu->addChild(menuitem);
|
2009-12-16 23:24:57 +00:00
|
|
|
else
|
2011-01-20 23:33:57 -03:00
|
|
|
throw base::Exception("Error converting the element \"%s\" to a menu-item.\n",
|
2012-01-05 19:45:03 -03:00
|
|
|
static_cast<const char*>(child->Value()));
|
2007-09-23 20:13:58 +00:00
|
|
|
|
2009-12-16 23:24:57 +00:00
|
|
|
child = child->NextSiblingElement();
|
2007-09-18 23:57:02 +00:00
|
|
|
}
|
|
|
|
|
2007-09-23 20:13:58 +00:00
|
|
|
return menu;
|
2007-09-18 23:57:02 +00:00
|
|
|
}
|
|
|
|
|
2012-07-09 13:20:58 -03:00
|
|
|
Widget* AppMenus::convertXmlelemToMenuitem(TiXmlElement* elem)
|
2007-09-18 23:57:02 +00:00
|
|
|
{
|
2009-12-16 23:24:57 +00:00
|
|
|
// is it a <separator>?
|
|
|
|
if (strcmp(elem->Value(), "separator") == 0)
|
2015-06-23 14:00:00 -03:00
|
|
|
return new Separator("", HORIZONTAL);
|
2007-09-18 23:57:02 +00:00
|
|
|
|
2009-12-16 23:24:57 +00:00
|
|
|
const char* command_name = elem->Attribute("command");
|
|
|
|
Command* command =
|
2011-01-20 20:49:03 -03:00
|
|
|
command_name ? CommandsModule::instance()->getCommandByName(command_name):
|
2012-01-05 19:45:03 -03:00
|
|
|
NULL;
|
2009-10-09 01:34:06 +00:00
|
|
|
|
|
|
|
// load params
|
|
|
|
Params params;
|
|
|
|
if (command) {
|
2009-12-16 23:24:57 +00:00
|
|
|
TiXmlElement* xmlParam = elem->FirstChildElement("param");
|
|
|
|
while (xmlParam) {
|
|
|
|
const char* param_name = xmlParam->Attribute("name");
|
|
|
|
const char* param_value = xmlParam->Attribute("value");
|
|
|
|
|
|
|
|
if (param_name && param_value)
|
2012-01-05 19:45:03 -03:00
|
|
|
params.set(param_name, param_value);
|
2009-12-16 23:24:57 +00:00
|
|
|
|
|
|
|
xmlParam = xmlParam->NextSiblingElement();
|
2009-10-09 01:34:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-08-05 21:20:19 -03:00
|
|
|
// Create the item
|
2015-03-11 15:40:22 -03:00
|
|
|
AppMenuItem* menuitem = new AppMenuItem(elem->Attribute("text"), command, params);
|
2007-09-18 23:57:02 +00:00
|
|
|
if (!menuitem)
|
2009-10-09 01:34:06 +00:00
|
|
|
return NULL;
|
2007-09-18 23:57:02 +00:00
|
|
|
|
2007-09-23 20:13:58 +00:00
|
|
|
/* has it a ID? */
|
2009-12-16 23:24:57 +00:00
|
|
|
const char* id = elem->Attribute("id");
|
|
|
|
if (id) {
|
2007-09-18 23:57:02 +00:00
|
|
|
/* recent list menu */
|
2007-11-28 14:19:36 +00:00
|
|
|
if (strcmp(id, "recent_list") == 0) {
|
2012-07-09 13:20:58 -03:00
|
|
|
m_recentListMenuitem = menuitem;
|
2007-09-18 23:57:02 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-04-22 23:00:35 -03:00
|
|
|
// Has it a sub-menu (<menu>)?
|
2009-12-16 23:24:57 +00:00
|
|
|
if (strcmp(elem->Value(), "menu") == 0) {
|
2011-04-22 23:00:35 -03:00
|
|
|
// Create the sub-menu
|
2012-07-09 13:20:58 -03:00
|
|
|
Menu* subMenu = convertXmlelemToMenu(elem);
|
2011-04-22 23:00:35 -03:00
|
|
|
if (!subMenu)
|
2011-01-20 23:33:57 -03:00
|
|
|
throw base::Exception("Error reading the sub-menu\n");
|
2007-09-18 23:57:02 +00:00
|
|
|
|
2011-04-22 23:00:35 -03:00
|
|
|
menuitem->setSubmenu(subMenu);
|
2007-09-23 20:13:58 +00:00
|
|
|
}
|
2007-09-18 23:57:02 +00:00
|
|
|
|
2007-09-23 20:13:58 +00:00
|
|
|
return menuitem;
|
|
|
|
}
|
2007-09-18 23:57:02 +00:00
|
|
|
|
2012-07-09 13:20:58 -03:00
|
|
|
Widget* AppMenus::createInvalidVersionMenuitem()
|
2011-08-22 21:37:14 -03:00
|
|
|
{
|
2015-03-11 15:40:22 -03:00
|
|
|
AppMenuItem* menuitem = new AppMenuItem("WARNING!");
|
2011-08-22 21:37:14 -03:00
|
|
|
Menu* subMenu = new Menu();
|
2015-03-11 15:40:22 -03:00
|
|
|
subMenu->addChild(new AppMenuItem(PACKAGE " is using a customized gui.xml (maybe from your HOME directory)."));
|
|
|
|
subMenu->addChild(new AppMenuItem("You should update your customized gui.xml file to the new version to get"));
|
|
|
|
subMenu->addChild(new AppMenuItem("the latest commands available."));
|
2015-06-23 14:00:00 -03:00
|
|
|
subMenu->addChild(new Separator("", HORIZONTAL));
|
2015-03-11 15:40:22 -03:00
|
|
|
subMenu->addChild(new AppMenuItem("You can bypass this validation adding the correct version"));
|
|
|
|
subMenu->addChild(new AppMenuItem("number in <gui version=\"" VERSION "\"> element."));
|
2011-08-22 21:37:14 -03:00
|
|
|
menuitem->setSubmenu(subMenu);
|
|
|
|
return menuitem;
|
|
|
|
}
|
|
|
|
|
2015-03-11 15:40:22 -03:00
|
|
|
void AppMenus::applyShortcutToMenuitemsWithCommand(Command* command, const Params& params, Key* key)
|
2014-10-29 11:58:03 -03:00
|
|
|
{
|
|
|
|
applyShortcutToMenuitemsWithCommand(m_rootMenu, command, params, key);
|
|
|
|
}
|
|
|
|
|
2015-03-11 15:40:22 -03:00
|
|
|
void AppMenus::applyShortcutToMenuitemsWithCommand(Menu* menu, Command* command, const Params& params, Key* key)
|
2007-09-23 20:13:58 +00:00
|
|
|
{
|
2012-07-17 21:42:02 -03:00
|
|
|
UI_FOREACH_WIDGET(menu->getChildren(), it) {
|
|
|
|
Widget* child = *it;
|
2007-09-18 23:57:02 +00:00
|
|
|
|
2015-06-23 14:37:22 -03:00
|
|
|
if (child->type() == kMenuItemWidget) {
|
2014-11-06 21:04:32 -03:00
|
|
|
AppMenuItem* menuitem = dynamic_cast<AppMenuItem*>(child);
|
|
|
|
if (!menuitem)
|
|
|
|
continue;
|
2011-04-22 23:00:35 -03:00
|
|
|
|
|
|
|
Command* mi_command = menuitem->getCommand();
|
2015-03-11 15:40:22 -03:00
|
|
|
const Params& mi_params = menuitem->getParams();
|
2009-10-09 01:34:06 +00:00
|
|
|
|
2014-09-21 11:59:39 -03:00
|
|
|
if ((mi_command) &&
|
2015-05-01 19:41:18 -03:00
|
|
|
(base::utf8_icmp(mi_command->id(), command->id()) == 0) &&
|
2015-03-11 15:40:22 -03:00
|
|
|
(mi_params == params)) {
|
2014-10-29 11:58:03 -03:00
|
|
|
// Set the keyboard shortcut to be shown in this menu-item
|
|
|
|
menuitem->setKey(key);
|
2009-10-09 01:34:06 +00:00
|
|
|
}
|
2007-09-18 23:57:02 +00:00
|
|
|
|
2011-04-22 23:00:35 -03:00
|
|
|
if (Menu* submenu = menuitem->getSubmenu())
|
2014-10-29 11:58:03 -03:00
|
|
|
applyShortcutToMenuitemsWithCommand(submenu, command, params, key);
|
2007-09-18 23:57:02 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2013-08-05 21:20:19 -03:00
|
|
|
|
|
|
|
} // namespace app
|