mirror of
https://github.com/aseprite/aseprite.git
synced 2024-09-03 05:29:13 +00:00
Put "Reopen Closed File" and "Clear Recent Files" options inside "File > Open Recent" menu
This commit is contained in:
parent
cdb98d4cd5
commit
54883012bb
@ -591,8 +591,12 @@
|
||||
<menu text="@.file">
|
||||
<item command="NewFile" text="@.file_new" />
|
||||
<item command="OpenFile" text="@.file_open" />
|
||||
<item id="recent_list" text="@.file_open_recent" />
|
||||
<item command="ReopenClosedFile" text="@.file_reopen_closed" />
|
||||
<menu text="@.file_open_recent">
|
||||
<item command="ReopenClosedFile" text="@.file_reopen_closed" />
|
||||
<separator id="recent_files_placeholder" />
|
||||
<separator />
|
||||
<item command="ClearRecentFiles" text="@.file_clear_recent_files" />
|
||||
</menu>
|
||||
<separator />
|
||||
<item command="SaveFile" text="@.file_save" />
|
||||
<item command="SaveFileAs" text="@.file_save_as" />
|
||||
|
@ -238,6 +238,7 @@ ChangePixelFormat_Indexed = Indexed
|
||||
ChangePixelFormat_MoreOptions = More Options
|
||||
Clear = Clear
|
||||
ClearCel = Clear Cel
|
||||
ClearRecentFiles = Clear Recent Files
|
||||
CloseAllFiles = Close All Files
|
||||
CloseFile = Close File
|
||||
ColorCurve = Color Curve
|
||||
@ -692,7 +693,9 @@ file = &File
|
||||
file_new = &New...
|
||||
file_open = &Open...
|
||||
file_open_recent = Open &Recent
|
||||
file_reopen_closed = Reopen Close&d File
|
||||
file_reopen_closed = &Reopen Closed File
|
||||
file_no_recent_file = No Recent File
|
||||
file_clear_recent_files = &Clear Recent Files
|
||||
file_save = &Save
|
||||
file_save_as = Save &As...
|
||||
file_export = Expor&t...
|
||||
|
@ -204,6 +204,7 @@ if(ENABLE_UI)
|
||||
commands/cmd_change_color.cpp
|
||||
commands/cmd_clear.cpp
|
||||
commands/cmd_clear_cel.cpp
|
||||
commands/cmd_clear_recent_files.cpp
|
||||
commands/cmd_close_file.cpp
|
||||
commands/cmd_color_quantization.cpp
|
||||
commands/cmd_contiguous_fill.cpp
|
||||
|
@ -1,4 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2019 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2018 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
@ -301,7 +302,7 @@ AppMenus* AppMenus::instance()
|
||||
}
|
||||
|
||||
AppMenus::AppMenus()
|
||||
: m_recentListMenuitem(nullptr)
|
||||
: m_recentFilesPlaceholder(nullptr)
|
||||
, m_osMenu(nullptr)
|
||||
{
|
||||
m_recentFilesConn =
|
||||
@ -453,61 +454,62 @@ void AppMenus::initTheme()
|
||||
|
||||
bool AppMenus::rebuildRecentList()
|
||||
{
|
||||
AppMenuItem* list_menuitem = dynamic_cast<AppMenuItem*>(m_recentListMenuitem);
|
||||
MenuItem* menuitem;
|
||||
if (!m_recentFilesPlaceholder)
|
||||
return true;
|
||||
|
||||
// Update the recent file list menu item
|
||||
if (list_menuitem) {
|
||||
if (list_menuitem->hasSubmenuOpened())
|
||||
return false;
|
||||
Menu* menu = dynamic_cast<Menu*>(m_recentFilesPlaceholder->parent());
|
||||
if (!menu)
|
||||
return false;
|
||||
|
||||
Command* cmd_open_file =
|
||||
Commands::instance()->byId(CommandId::OpenFile());
|
||||
AppMenuItem* owner = dynamic_cast<AppMenuItem*>(menu->getOwnerMenuItem());
|
||||
if (!owner || owner->hasSubmenuOpened())
|
||||
return false;
|
||||
|
||||
Menu* submenu = list_menuitem->getSubmenu();
|
||||
if (submenu) {
|
||||
list_menuitem->setSubmenu(NULL);
|
||||
submenu->deferDelete();
|
||||
int insertIndex = menu->getChildIndex(m_recentFilesPlaceholder)+1;
|
||||
|
||||
// Remove active items
|
||||
while (auto appItem = dynamic_cast<AppMenuItem*>(menu->at(insertIndex))) {
|
||||
menu->removeChild(appItem);
|
||||
appItem->deferDelete();
|
||||
}
|
||||
|
||||
Command* openFile = Commands::instance()->byId(CommandId::OpenFile());
|
||||
|
||||
auto recent = App::instance()->recentFiles();
|
||||
base::paths files;
|
||||
files.insert(files.end(),
|
||||
recent->pinnedFiles().begin(),
|
||||
recent->pinnedFiles().end());
|
||||
files.insert(files.end(),
|
||||
recent->recentFiles().begin(),
|
||||
recent->recentFiles().end());
|
||||
if (!files.empty()) {
|
||||
Params params;
|
||||
for (const auto& fn : files) {
|
||||
params.set("filename", fn.c_str());
|
||||
|
||||
auto menuitem = new AppMenuItem(base::get_file_name(fn).c_str(),
|
||||
openFile, params);
|
||||
menuitem->setIsRecentFileItem(true);
|
||||
menu->insertChild(insertIndex++, menuitem);
|
||||
}
|
||||
}
|
||||
else {
|
||||
auto menuitem = new AppMenuItem(
|
||||
Strings::main_menu_file_no_recent_file(), nullptr);
|
||||
menuitem->setIsRecentFileItem(true);
|
||||
menuitem->setEnabled(false);
|
||||
menu->insertChild(insertIndex++, menuitem);
|
||||
}
|
||||
|
||||
// Build the menu of recent files
|
||||
submenu = new Menu();
|
||||
list_menuitem->setSubmenu(submenu);
|
||||
|
||||
auto recent = App::instance()->recentFiles();
|
||||
base::paths files;
|
||||
files.insert(files.end(),
|
||||
recent->pinnedFiles().begin(),
|
||||
recent->pinnedFiles().end());
|
||||
files.insert(files.end(),
|
||||
recent->recentFiles().begin(),
|
||||
recent->recentFiles().end());
|
||||
if (!files.empty()) {
|
||||
Params params;
|
||||
for (const auto& fn : files) {
|
||||
params.set("filename", fn.c_str());
|
||||
menuitem = new AppMenuItem(
|
||||
base::get_file_name(fn).c_str(),
|
||||
cmd_open_file,
|
||||
params);
|
||||
submenu->addChild(menuitem);
|
||||
}
|
||||
}
|
||||
else {
|
||||
menuitem = new AppMenuItem("Nothing", NULL, Params());
|
||||
menuitem->setEnabled(false);
|
||||
submenu->addChild(menuitem);
|
||||
}
|
||||
|
||||
// Sync native menus
|
||||
if (list_menuitem->native() &&
|
||||
list_menuitem->native()->menuItem) {
|
||||
os::Menus* menus = os::instance()->menus();
|
||||
os::Menu* osMenu = (menus ? menus->createMenu(): nullptr);
|
||||
if (osMenu) {
|
||||
createNativeSubmenus(osMenu, submenu);
|
||||
list_menuitem->native()->menuItem->setSubmenu(osMenu);
|
||||
}
|
||||
// Sync native menus
|
||||
if (owner->native() &&
|
||||
owner->native()->menuItem) {
|
||||
os::Menus* menus = os::instance()->menus();
|
||||
os::Menu* osMenu = (menus ? menus->createMenu(): nullptr);
|
||||
if (osMenu) {
|
||||
createNativeSubmenus(osMenu, menu);
|
||||
owner->native()->menuItem->setSubmenu(osMenu);
|
||||
}
|
||||
}
|
||||
|
||||
@ -563,7 +565,14 @@ Widget* AppMenus::convertXmlelemToMenuitem(TiXmlElement* elem)
|
||||
// is it a <separator>?
|
||||
if (strcmp(elem->Value(), "separator") == 0) {
|
||||
auto item = new MenuSeparator;
|
||||
if (id) item->setId(id);
|
||||
if (id) {
|
||||
item->setId(id);
|
||||
|
||||
// Recent list menu
|
||||
if (std::strcmp(id, "recent_files_placeholder") == 0) {
|
||||
m_recentFilesPlaceholder = item;
|
||||
}
|
||||
}
|
||||
return item;
|
||||
}
|
||||
|
||||
@ -598,11 +607,7 @@ Widget* AppMenus::convertXmlelemToMenuitem(TiXmlElement* elem)
|
||||
|
||||
// Has it a ID?
|
||||
if (id) {
|
||||
// Recent list menu
|
||||
if (std::strcmp(id, "recent_list") == 0) {
|
||||
m_recentListMenuitem = menuitem;
|
||||
}
|
||||
else if (std::strcmp(id, "help_menu") == 0) {
|
||||
if (std::strcmp(id, "help_menu") == 0) {
|
||||
m_helpMenuitem = menuitem;
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2019 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2018 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
@ -49,7 +50,6 @@ namespace app {
|
||||
bool rebuildRecentList();
|
||||
|
||||
Menu* getRootMenu() { return m_rootMenu.get(); }
|
||||
MenuItem* getRecentListMenuitem() { return m_recentListMenuitem; }
|
||||
Menu* getTabPopupMenu() { return m_tabPopupMenu.get(); }
|
||||
Menu* getDocumentTabPopupMenu() { return m_documentTabPopupMenu.get(); }
|
||||
Menu* getLayerPopupMenu() { return m_layerPopupMenu.get(); }
|
||||
@ -84,7 +84,7 @@ namespace app {
|
||||
#endif
|
||||
|
||||
std::unique_ptr<Menu> m_rootMenu;
|
||||
MenuItem* m_recentListMenuitem;
|
||||
Widget* m_recentFilesPlaceholder;
|
||||
MenuItem* m_helpMenuitem;
|
||||
std::unique_ptr<Menu> m_tabPopupMenu;
|
||||
std::unique_ptr<Menu> m_documentTabPopupMenu;
|
||||
|
49
src/app/commands/cmd_clear_recent_files.cpp
Normal file
49
src/app/commands/cmd_clear_recent_files.cpp
Normal file
@ -0,0 +1,49 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2019 Igara Studio S.A.
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
// the End-User License Agreement for Aseprite.
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "app/app.h"
|
||||
#include "app/commands/command.h"
|
||||
#include "app/recent_files.h"
|
||||
|
||||
namespace app {
|
||||
|
||||
class ClearRecentFilesCommand : public Command {
|
||||
public:
|
||||
ClearRecentFilesCommand();
|
||||
|
||||
protected:
|
||||
bool onEnabled(Context* ctx) override;
|
||||
void onExecute(Context* ctx) override;
|
||||
};
|
||||
|
||||
ClearRecentFilesCommand::ClearRecentFilesCommand()
|
||||
: Command(CommandId::ClearRecentFiles(), CmdUIOnlyFlag)
|
||||
{
|
||||
}
|
||||
|
||||
bool ClearRecentFilesCommand::onEnabled(Context* ctx)
|
||||
{
|
||||
auto recent = App::instance()->recentFiles();
|
||||
return (recent &&
|
||||
(!recent->recentFiles().empty() ||
|
||||
!recent->recentFolders().empty()));
|
||||
}
|
||||
|
||||
void ClearRecentFilesCommand::onExecute(Context* ctx)
|
||||
{
|
||||
App::instance()->recentFiles()->clear();
|
||||
}
|
||||
|
||||
Command* CommandFactory::createClearRecentFilesCommand()
|
||||
{
|
||||
return new ClearRecentFilesCommand;
|
||||
}
|
||||
|
||||
} // namespace app
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2018 Igara Studio S.A.
|
||||
// Copyright (C) 2018-2019 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2018 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
@ -780,7 +780,7 @@ private:
|
||||
void fillMenusList(ListBox* listbox, Menu* menu, int level) {
|
||||
for (auto child : menu->children()) {
|
||||
if (AppMenuItem* menuItem = dynamic_cast<AppMenuItem*>(child)) {
|
||||
if (menuItem == AppMenus::instance()->getRecentListMenuitem())
|
||||
if (menuItem->isRecentFileItem())
|
||||
continue;
|
||||
|
||||
KeyItem* keyItem = new KeyItem(
|
||||
@ -917,7 +917,7 @@ void KeyboardShortcutsCommand::fillMenusKeys(app::KeyboardShortcuts& keys,
|
||||
{
|
||||
for (auto child : menu->children()) {
|
||||
if (AppMenuItem* menuItem = dynamic_cast<AppMenuItem*>(child)) {
|
||||
if (menuItem == AppMenus::instance()->getRecentListMenuitem())
|
||||
if (menuItem->isRecentFileItem())
|
||||
continue;
|
||||
|
||||
if (menuItem->getCommand()) {
|
||||
|
@ -39,6 +39,7 @@ FOR_EACH_COMMAND(ChangeBrush)
|
||||
FOR_EACH_COMMAND(ChangeColor)
|
||||
FOR_EACH_COMMAND(Clear)
|
||||
FOR_EACH_COMMAND(ClearCel)
|
||||
FOR_EACH_COMMAND(ClearRecentFiles)
|
||||
FOR_EACH_COMMAND(CloseAllFiles)
|
||||
FOR_EACH_COMMAND(CloseFile)
|
||||
FOR_EACH_COMMAND(ColorCurve)
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2018 Igara Studio S.A.
|
||||
// Copyright (C) 2018-2019 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2018 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
@ -23,10 +23,10 @@ namespace app {
|
||||
kRecentFolders,
|
||||
kCollections };
|
||||
public:
|
||||
const base::paths& pinnedFiles() { return m_paths[kPinnedFiles]; }
|
||||
const base::paths& recentFiles() { return m_paths[kRecentFiles]; }
|
||||
const base::paths& pinnedFolders() { return m_paths[kPinnedFolders]; }
|
||||
const base::paths& recentFolders() { return m_paths[kRecentFolders]; }
|
||||
const base::paths& pinnedFiles() const { return m_paths[kPinnedFiles]; }
|
||||
const base::paths& recentFiles() const { return m_paths[kRecentFiles]; }
|
||||
const base::paths& pinnedFolders() const { return m_paths[kPinnedFolders]; }
|
||||
const base::paths& recentFolders() const { return m_paths[kRecentFolders]; }
|
||||
|
||||
RecentFiles(const int limit);
|
||||
~RecentFiles();
|
||||
|
@ -1,4 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2019 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2017 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
@ -35,18 +36,24 @@ using namespace ui;
|
||||
Params AppMenuItem::s_contextParams;
|
||||
|
||||
AppMenuItem::AppMenuItem(const std::string& text,
|
||||
Command* command, const Params& params)
|
||||
Command* command,
|
||||
const Params& params)
|
||||
: MenuItem(text)
|
||||
, m_key(nullptr)
|
||||
, m_command(command)
|
||||
, m_params(params)
|
||||
, m_isRecentFileItem(false)
|
||||
, m_native(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
AppMenuItem::~AppMenuItem()
|
||||
{
|
||||
delete m_native;
|
||||
if (m_native) {
|
||||
if (m_native->menuItem)
|
||||
m_native->menuItem->dispose();
|
||||
delete m_native;
|
||||
}
|
||||
}
|
||||
|
||||
void AppMenuItem::setKey(const KeyPtr& key)
|
||||
@ -59,8 +66,11 @@ void AppMenuItem::setNative(const Native& native)
|
||||
{
|
||||
if (!m_native)
|
||||
m_native = new Native(native);
|
||||
else
|
||||
else {
|
||||
if (m_native->menuItem)
|
||||
m_native->menuItem->dispose();
|
||||
*m_native = native;
|
||||
}
|
||||
}
|
||||
|
||||
void AppMenuItem::syncNativeMenuItemKeyShortcut()
|
||||
|
@ -41,6 +41,9 @@ namespace app {
|
||||
KeyPtr key() { return m_key; }
|
||||
void setKey(const KeyPtr& key);
|
||||
|
||||
void setIsRecentFileItem(bool state) { m_isRecentFileItem = state; }
|
||||
bool isRecentFileItem() const { return m_isRecentFileItem; }
|
||||
|
||||
Command* getCommand() { return m_command; }
|
||||
const Params& getParams() const { return m_params; }
|
||||
|
||||
@ -60,6 +63,7 @@ namespace app {
|
||||
KeyPtr m_key;
|
||||
Command* m_command;
|
||||
Params m_params;
|
||||
bool m_isRecentFileItem;
|
||||
Native* m_native;
|
||||
|
||||
static Params s_contextParams;
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite UI Library
|
||||
// Copyright (C) 2018 Igara Studio S.A.
|
||||
// Copyright (C) 2018-2019 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2018 David Capello
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
@ -409,6 +409,15 @@ Manager* Widget::manager() const
|
||||
return Manager::getDefault();
|
||||
}
|
||||
|
||||
int Widget::getChildIndex(Widget* child)
|
||||
{
|
||||
auto it = std::find(m_children.begin(), m_children.end(), child);
|
||||
if (it != m_children.end())
|
||||
return it - m_children.begin();
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
Widget* Widget::nextSibling()
|
||||
{
|
||||
assert_ui_thread();
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite UI Library
|
||||
// Copyright (C) 2018 Igara Studio S.A.
|
||||
// Copyright (C) 2018-2019 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2018 David Capello
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
@ -169,6 +169,7 @@ namespace ui {
|
||||
const WidgetsList& children() const { return m_children; }
|
||||
|
||||
Widget* at(int index) { return m_children[index]; }
|
||||
int getChildIndex(Widget* child);
|
||||
|
||||
// Returns the first/last child or NULL if it doesn't exist.
|
||||
Widget* firstChild() {
|
||||
|
Loading…
Reference in New Issue
Block a user