Put "Reopen Closed File" and "Clear Recent Files" options inside "File > Open Recent" menu

This commit is contained in:
David Capello 2019-05-27 16:29:53 -03:00
parent cdb98d4cd5
commit 54883012bb
13 changed files with 162 additions and 75 deletions

View File

@ -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" />

View File

@ -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...

View File

@ -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

View File

@ -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;
}
}

View File

@ -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;

View 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

View File

@ -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()) {

View File

@ -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)

View File

@ -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();

View File

@ -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()

View File

@ -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;

View File

@ -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();

View File

@ -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() {