Merge branch 'main' into beta

This commit is contained in:
David Capello 2022-05-05 09:56:45 -03:00
commit 8d2863a58b
24 changed files with 253 additions and 48 deletions

2
.gitmodules vendored
View File

@ -71,7 +71,7 @@
url = https://github.com/aseprite/curl.git url = https://github.com/aseprite/curl.git
[submodule "third_party/IXWebSocket"] [submodule "third_party/IXWebSocket"]
path = third_party/IXWebSocket path = third_party/IXWebSocket
url = https://github.com/machinezone/IXWebSocket url = https://github.com/aseprite/IXWebSocket.git
[submodule "third_party/cityhash"] [submodule "third_party/cityhash"]
path = third_party/cityhash path = third_party/cityhash
url = https://github.com/aseprite/cityhash.git url = https://github.com/aseprite/cityhash.git

View File

@ -1,12 +1,12 @@
# Aseprite # Aseprite
# Copyright (C) 2018-2021 Igara Studio S.A. # Copyright (C) 2018-2022 Igara Studio S.A.
# Copyright (C) 2001-2018 David Capello # Copyright (C) 2001-2018 David Capello
cmake_minimum_required(VERSION 3.4) cmake_minimum_required(VERSION 3.4)
set(CMAKE_CXX_STANDARD 14) set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF) # We use -std=c++14 instead of -std=gnu++14 in macOS set(CMAKE_CXX_EXTENSIONS OFF) # We use -std=c++17 instead of -std=gnu++17 in macOS
if(COMMAND cmake_policy) if(COMMAND cmake_policy)
# CMP0003: Libraries linked via full path no longer produce linker search paths. # CMP0003: Libraries linked via full path no longer produce linker search paths.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 16 KiB

View File

@ -192,6 +192,8 @@
<part id="combobox_arrow_right" x="99" y="196" w="9" h="9" /> <part id="combobox_arrow_right" x="99" y="196" w="9" h="9" />
<part id="combobox_arrow_right_selected" x="115" y="196" w="9" h="9" /> <part id="combobox_arrow_right_selected" x="115" y="196" w="9" h="9" />
<part id="combobox_arrow_right_disabled" x="131" y="196" w="9" h="9" /> <part id="combobox_arrow_right_disabled" x="131" y="196" w="9" h="9" />
<part id="arrow_circle_cw" x="99" y="243" w="10" h="10" />
<part id="arrow_circle_cw_selected" x="115" y="243" w="10" h="10" />
<part id="newfolder" x="99" y="211" w="9" h="9" /> <part id="newfolder" x="99" y="211" w="9" h="9" />
<part id="newfolder_selected" x="115" y="211" w="9" h="9" /> <part id="newfolder_selected" x="115" y="211" w="9" h="9" />
<part id="list_view" x="96" y="224" w="9" h="9" /> <part id="list_view" x="96" y="224" w="9" h="9" />
@ -647,6 +649,10 @@
<icon part="combobox_arrow_up_selected" state="selected" /> <icon part="combobox_arrow_up_selected" state="selected" />
<icon part="combobox_arrow_up_disabled" state="disabled" /> <icon part="combobox_arrow_up_disabled" state="disabled" />
</style> </style>
<style id="refresh_button" extends="mini_button">
<icon part="arrow_circle_cw" />
<icon part="arrow_circle_cw_selected" state="selected" />
</style>
<style id="new_folder_button" extends="mini_button"> <style id="new_folder_button" extends="mini_button">
<icon part="newfolder" /> <icon part="newfolder" />
<icon part="newfolder_selected" state="selected" /> <icon part="newfolder_selected" state="selected" />

View File

@ -158,6 +158,7 @@
<option id="show_menu_bar" type="bool" default="true" /> <option id="show_menu_bar" type="bool" default="true" />
<option id="recent_items" type="int" default="16" /> <option id="recent_items" type="int" default="16" />
<option id="osx_async_view" type="bool" default="true" /> <option id="osx_async_view" type="bool" default="true" />
<option id="x11_stylus_id" type="std::string" />
</section> </section>
<section id="undo" text="Undo"> <section id="undo" text="Undo">
<option id="size_limit" type="int" default="0" /> <option id="size_limit" type="int" default="0" />
@ -170,6 +171,7 @@
<option id="zoom_with_slide" type="bool" default="false" /> <option id="zoom_with_slide" type="bool" default="false" />
<option id="zoom_from_center_with_wheel" type="bool" default="false" /> <option id="zoom_from_center_with_wheel" type="bool" default="false" />
<option id="zoom_from_center_with_keys" type="bool" default="false" /> <option id="zoom_from_center_with_keys" type="bool" default="false" />
<option id="invert_brush_size_wheel" type="bool" default="false" />
<option id="show_scrollbars" type="bool" default="true" /> <option id="show_scrollbars" type="bool" default="true" />
<option id="auto_scroll" type="bool" default="true" /> <option id="auto_scroll" type="bool" default="true" />
<option id="right_click_mode" type="RightClickMode" default="RightClickMode::PAINT_BGCOLOR" /> <option id="right_click_mode" type="RightClickMode" default="RightClickMode::PAINT_BGCOLOR" />

View File

@ -728,6 +728,7 @@ generating = Generating...
go_back_button_tooltip = Go back one folder go_back_button_tooltip = Go back one folder
go_forward_button_tooltip = Go forward one folder go_forward_button_tooltip = Go forward one folder
go_up_button_tooltip = Up to parent folder go_up_button_tooltip = Up to parent folder
refresh_button_tooltip = Refresh folder view
new_folder_button_tooltip = New folder new_folder_button_tooltip = New folder
list_view_button_tooltip = List View list_view_button_tooltip = List View
small_icon_view_button_tooltip = Small Icons View small_icon_view_button_tooltip = Small Icons View
@ -851,6 +852,7 @@ section_drag_value = Drag Value
default_wheel_behavior = Default default_wheel_behavior = Default
custom_wheel_behavior = Custom custom_wheel_behavior = Custom
slide_as_wheel = Interpret two fingers slide on Trackpad as mouse wheel slide_as_wheel = Interpret two fingers slide on Trackpad as mouse wheel
invert_brush_size_wheel = Invert the mouse wheel direction for increasing the brush size
drag_angle = Angle: drag_angle = Angle:
drag_angle_tooltip = Direction of the mouse to indicate an increment of the value drag_angle_tooltip = Direction of the mouse to indicate an increment of the value
drag_distance = Distance: drag_distance = Distance:

View File

@ -1,5 +1,5 @@
<!-- Aseprite --> <!-- Aseprite -->
<!-- Copyright (C) 2019 Igara Studio S.A. --> <!-- Copyright (C) 2019-2022 Igara Studio S.A. -->
<!-- Copyright (C) 2001-2018 David Capello --> <!-- Copyright (C) 2001-2018 David Capello -->
<gui> <gui>
<window id="file_selector" text=""> <window id="file_selector" text="">
@ -21,6 +21,8 @@
<item icon="big_icon_view" tooltip="@.big_icon_view_button_tooltip" tooltip_dir="bottom" /> <item icon="big_icon_view" tooltip="@.big_icon_view_button_tooltip" tooltip_dir="bottom" />
</buttonset> </buttonset>
<combobox id="location" expansive="true" /> <combobox id="location" expansive="true" />
<button text="" id="refresh_button" style="refresh_button"
tooltip="@.refresh_button_tooltip" tooltip_dir="bottom" />
</box> </box>
<vbox id="file_view_placeholder" expansive="true" /> <vbox id="file_view_placeholder" expansive="true" />
<grid columns="2"> <grid columns="2">

View File

@ -50,6 +50,8 @@
pref="editor.zoom_with_wheel" /> pref="editor.zoom_with_wheel" />
<check text="@options.slide_zoom" id="slide_zoom" <check text="@options.slide_zoom" id="slide_zoom"
pref="editor.zoom_with_slide" /> pref="editor.zoom_with_slide" />
<check text="@.invert_brush_size_wheel" id="invert_brush_size_scroll"
pref="editor.invert_brush_size_wheel" />
<view expansive="true"> <view expansive="true">
<listbox id="wheel_actions" /> <listbox id="wheel_actions" />
</view> </view>

2
laf

@ -1 +1 @@
Subproject commit df53f4ac0cecada789bf84b4283947d2591833bd Subproject commit 8f9e7892e0da31e423e224b199f53d8ffefce32b

View File

@ -71,6 +71,8 @@
#if LAF_MACOS #if LAF_MACOS
#include "os/osx/system.h" #include "os/osx/system.h"
#elif LAF_LINUX
#include "os/x11/system.h"
#endif #endif
#include <iostream> #include <iostream>
@ -95,6 +97,7 @@ namespace {
class ConsoleEngineDelegate : public script::EngineDelegate { class ConsoleEngineDelegate : public script::EngineDelegate {
public: public:
ConsoleEngineDelegate(Console& console) : m_console(console) { }
void onConsoleError(const char* text) override { void onConsoleError(const char* text) override {
onConsolePrint(text); onConsolePrint(text);
} }
@ -102,7 +105,7 @@ public:
m_console.printf("%s\n", text); m_console.printf("%s\n", text);
} }
private: private:
Console m_console; Console& m_console;
}; };
} // anonymous namespace } // anonymous namespace
@ -236,6 +239,7 @@ int App::initialize(const AppOptions& options)
m_coreModules = new CoreModules; m_coreModules = new CoreModules;
#if LAF_WINDOWS #if LAF_WINDOWS
if (options.disableWintab() || if (options.disableWintab() ||
!preferences().experimental.loadWintabDriver() || !preferences().experimental.loadWintabDriver() ||
preferences().tablet.api() == "pointer") { preferences().tablet.api() == "pointer") {
@ -245,11 +249,20 @@ int App::initialize(const AppOptions& options)
system->setTabletAPI(os::TabletAPI::WintabPackets); system->setTabletAPI(os::TabletAPI::WintabPackets);
else // preferences().tablet.api() == "wintab" else // preferences().tablet.api() == "wintab"
system->setTabletAPI(os::TabletAPI::Wintab); system->setTabletAPI(os::TabletAPI::Wintab);
#endif
#if LAF_MACOS #elif LAF_MACOS
if (!preferences().general.osxAsyncView()) if (!preferences().general.osxAsyncView())
os::osx_set_async_view(false); os::osx_set_async_view(false);
#elif LAF_LINUX
{
const std::string& stylusId = preferences().general.x11StylusId();
if (!stylusId.empty())
os::x11_set_user_defined_string_to_detect_stylus(stylusId);
}
#endif #endif
system->setAppName(get_app_name()); system->setAppName(get_app_name());
@ -485,7 +498,7 @@ void App::run()
Console console; Console console;
#ifdef ENABLE_SCRIPTING #ifdef ENABLE_SCRIPTING
// Use the app::Console() for script errors // Use the app::Console() for script errors
ConsoleEngineDelegate delegate; ConsoleEngineDelegate delegate(console);
script::ScopedEngineDelegate setEngineDelegate(m_engine.get(), &delegate); script::ScopedEngineDelegate setEngineDelegate(m_engine.get(), &delegate);
#endif #endif

View File

@ -1,5 +1,5 @@
// Aseprite // Aseprite
// Copyright (C) 2019-2021 Igara Studio S.A. // Copyright (C) 2019-2022 Igara Studio S.A.
// Copyright (C) 2001-2018 David Capello // Copyright (C) 2001-2018 David Capello
// //
// This program is distributed under the terms of // This program is distributed under the terms of
@ -206,6 +206,7 @@ bool FilterManagerImpl::applyStep()
void FilterManagerImpl::apply() void FilterManagerImpl::apply()
{ {
CommandResult result;
bool cancelled = false; bool cancelled = false;
begin(); begin();
@ -257,7 +258,15 @@ void FilterManagerImpl::apply()
position())); position()));
} }
} }
result = CommandResult(CommandResult::kOk);
} }
else {
result = CommandResult(CommandResult::kCanceled);
}
ASSERT(m_reader.context());
m_reader.context()->setCommandResult(result);
} }
void FilterManagerImpl::applyToTarget() void FilterManagerImpl::applyToTarget()

View File

@ -12,7 +12,6 @@
#include "app/app.h" #include "app/app.h"
#include "app/commands/filters/filter_manager_impl.h" #include "app/commands/filters/filter_manager_impl.h"
#include "app/console.h" #include "app/console.h"
#include "app/context_access.h"
#include "app/i18n/strings.h" #include "app/i18n/strings.h"
#include "app/ini_file.h" #include "app/ini_file.h"
#include "app/modules/editors.h" #include "app/modules/editors.h"

View File

@ -1,5 +1,5 @@
// Aseprite // Aseprite
// Copyright (C) 2018-2021 Igara Studio S.A. // Copyright (C) 2018-2022 Igara Studio S.A.
// Copyright (C) 2001-2018 David Capello // Copyright (C) 2001-2018 David Capello
// //
// This program is distributed under the terms of // This program is distributed under the terms of
@ -14,6 +14,7 @@
#include "app/app.h" #include "app/app.h"
#include "app/context.h" #include "app/context.h"
#include "app/modules/gui.h" #include "app/modules/gui.h"
#include "app/ui/main_window.h"
#include "app/ui/status_bar.h" #include "app/ui/status_bar.h"
#include "base/memory.h" #include "base/memory.h"
#include "base/string.h" #include "base/string.h"
@ -24,21 +25,39 @@
#include <cstdio> #include <cstdio>
#include <memory> #include <memory>
#define TRACE_CON(...) // TRACEARGS(__VA_ARGS__)
namespace app { namespace app {
using namespace ui; using namespace ui;
class Console::ConsoleWindow : public Window { Console::ConsoleWindow* Console::m_console = nullptr;
class Console::ConsoleWindow final : public Window {
public: public:
ConsoleWindow() : Window(Window::WithTitleBar, "Console"), ConsoleWindow() : Window(Window::WithTitleBar, "Console"),
m_textbox("", WORDWRAP), m_textbox("", WORDWRAP),
m_button("Cancel") { m_button("Cancel") {
TRACE_CON("CON: ConsoleWindow this=", this);
m_button.Click.connect([this]{ closeWindow(&m_button); }); m_button.Click.connect([this]{ closeWindow(&m_button); });
// When the main window is closed, we should close the console (in
// other case the main message loop will continue running for the
// console too).
m_mainWindowClosedConn =
App::instance()->mainWindow()->Close.connect(
[this]{ closeWindow(nullptr); });
// When the window is closed, we clear the text // When the window is closed, we clear the text
Close.connect( Close.connect(
[this]{ [this]{
m_mainWindowClosedConn.disconnect();
m_textbox.setText(std::string()); m_textbox.setText(std::string());
Console::m_console->deferDelete();
Console::m_console = nullptr;
TRACE_CON("CON: Close signal");
}); });
m_view.attachToView(&m_textbox); m_view.attachToView(&m_textbox);
@ -55,17 +74,33 @@ public:
initTheme(); initTheme();
} }
~ConsoleWindow() {
TRACE_CON("CON: ~ConsoleWindow this=", this);
}
void addMessage(const std::string& msg) { void addMessage(const std::string& msg) {
if (!m_hasText) { if (!m_hasText) {
m_hasText = true; m_hasText = true;
centerConsole(); centerConsole();
} }
gfx::Size maxSize = m_view.getScrollableSize();
gfx::Size visible = m_view.visibleSize();
gfx::Point pt = m_view.viewScroll();
const bool autoScroll = (pt.y >= maxSize.h - visible.h);
m_textbox.setText(m_textbox.text() + msg); m_textbox.setText(m_textbox.text() + msg);
if (autoScroll) {
maxSize = m_view.getScrollableSize();
visible = m_view.visibleSize();
pt.y = maxSize.h - visible.h;
m_view.setViewScroll(pt);
}
} }
bool isConsoleVisible() const { bool hasConsoleText() const {
return (m_hasText && isVisible()); return m_hasText;
} }
void centerConsole() { void centerConsole() {
@ -83,19 +118,66 @@ public:
} }
private: private:
// As Esc key activates the close button only on foreground windows,
// we have to override this method to allow pressing the window
// close button using Esc key even in this window (which runs in the
// background).
bool shouldProcessEscKeyToCloseWindow() const override {
return true;
}
bool onProcessMessage(ui::Message* msg) override { bool onProcessMessage(ui::Message* msg) override {
switch (msg->type()) { switch (msg->type()) {
case ui::kKeyDownMessage: case ui::kKeyDownMessage: {
auto scancode = static_cast<KeyMessage*>(msg)->scancode();
#if defined __APPLE__ #if defined __APPLE__
if (msg->onlyCmdPressed()) if (msg->onlyCmdPressed())
#else #else
if (msg->onlyCtrlPressed()) if (msg->onlyCtrlPressed())
#endif #endif
{ {
if (static_cast<KeyMessage*>(msg)->scancode() == kKeyC) if (scancode == kKeyC)
set_clipboard_text(m_textbox.text()); set_clipboard_text(m_textbox.text());
} }
// Esc to close the window.
if (auto closeButton = this->closeButton()) {
bool p = msg->propagateToParent();
msg->setPropagateToParent(false);
if (closeButton->sendMessage(msg))
return true;
msg->setPropagateToParent(p);
}
// Send Enter key to the Close button, Tab to change focus
if ((scancode == kKeyEnter) ||
(scancode == kKeyEnterPad))
return m_button.sendMessage(msg);
if (scancode == kKeyTab) {
if (auto mgr = manager())
return mgr->processFocusMovementMessage(msg);
}
// All keys are used if we have this window focused (so they
// don't trigger commands)
return true;
}
case ui::kKeyUpMessage:
if (auto closeButton = this->closeButton()) {
bool p = msg->propagateToParent();
msg->setPropagateToParent(false);
if (closeButton->sendMessage(msg))
return true;
msg->setPropagateToParent(p);
}
break; break;
} }
return Window::onProcessMessage(msg); return Window::onProcessMessage(msg);
@ -107,18 +189,18 @@ private:
m_button.setMinSize(gfx::Size(60*ui::guiscale(), 0)); m_button.setMinSize(gfx::Size(60*ui::guiscale(), 0));
} }
obs::scoped_connection m_mainWindowClosedConn;
View m_view; View m_view;
TextBox m_textbox; TextBox m_textbox;
Button m_button; Button m_button;
bool m_hasText = false; bool m_hasText = false;
}; };
int Console::m_consoleCounter = 0;
std::unique_ptr<Console::ConsoleWindow> Console::m_console = nullptr;
Console::Console(Context* ctx) Console::Console(Context* ctx)
: m_withUI(false) : m_withUI(false)
{ {
TRACE_CON("CON: Console this=", this, "ctx=", ctx, "is_ui_thread=", ui::is_ui_thread(), "{");
if (!ui::is_ui_thread()) if (!ui::is_ui_thread())
return; return;
@ -136,27 +218,26 @@ Console::Console(Context* ctx)
if (!m_withUI) if (!m_withUI)
return; return;
++m_consoleCounter; TRACE_CON("CON: -> withUI=", m_withUI);
if (m_console || m_consoleCounter > 1)
return;
m_console.reset(new ConsoleWindow); if (!m_console)
m_console = new ConsoleWindow;
} }
Console::~Console() Console::~Console()
{ {
TRACE_CON("CON: } ~Console this=", this, "withUI=", m_withUI);
if (!m_withUI) if (!m_withUI)
return; return;
--m_consoleCounter; if (m_console &&
m_console->hasConsoleText() &&
if (m_console && m_console->isConsoleVisible()) { !m_console->isVisible()) {
m_console->manager()->attractFocus(m_console.get()); m_console->manager()->attractFocus(m_console);
m_console->openWindowInForeground(); m_console->openWindow();
TRACE_CON("CON: openWindow");
} }
if (m_consoleCounter == 0)
m_console.reset();
} }
void Console::printf(const char* format, ...) void Console::printf(const char* format, ...)

View File

@ -1,5 +1,5 @@
// Aseprite // Aseprite
// Copyright (C) 2018-2020 Igara Studio S.A. // Copyright (C) 2018-2022 Igara Studio S.A.
// Copyright (C) 2001-2017 David Capello // Copyright (C) 2001-2017 David Capello
// //
// This program is distributed under the terms of // This program is distributed under the terms of
@ -10,7 +10,6 @@
#pragma once #pragma once
#include <exception> #include <exception>
#include <memory>
namespace app { namespace app {
class Context; class Context;
@ -29,8 +28,7 @@ namespace app {
class ConsoleWindow; class ConsoleWindow;
bool m_withUI; bool m_withUI;
static int m_consoleCounter; static ConsoleWindow* m_console;
static std::unique_ptr<Console::ConsoleWindow> m_console;
}; };
} // namespace app } // namespace app

View File

@ -1,5 +1,5 @@
// Aseprite // Aseprite
// Copyright (C) 2018-2021 Igara Studio S.A. // Copyright (C) 2018-2022 Igara Studio S.A.
// Copyright (C) 2001-2018 David Capello // Copyright (C) 2001-2018 David Capello
// //
// This program is distributed under the terms of // This program is distributed under the terms of
@ -165,6 +165,8 @@ void Context::executeCommand(Command* command, const Params& params)
if (!command) if (!command)
return; return;
m_result.reset();
Console console; Console console;
LOG(VERBOSE, "CTXT: Executing command %s\n", command->id().c_str()); LOG(VERBOSE, "CTXT: Executing command %s\n", command->id().c_str());
try { try {
@ -213,17 +215,23 @@ void Context::executeCommand(Command* command, const Params& params)
#endif #endif
} }
catch (base::Exception& e) { catch (base::Exception& e) {
m_result = CommandResult(CommandResult::kError);
LOG(ERROR, "CTXT: Exception caught executing %s command\n%s\n", LOG(ERROR, "CTXT: Exception caught executing %s command\n%s\n",
command->id().c_str(), e.what()); command->id().c_str(), e.what());
Console::showException(e); Console::showException(e);
} }
catch (std::exception& e) { catch (std::exception& e) {
m_result = CommandResult(CommandResult::kError);
LOG(ERROR, "CTXT: std::exception caught executing %s command\n%s\n", LOG(ERROR, "CTXT: std::exception caught executing %s command\n%s\n",
command->id().c_str(), e.what()); command->id().c_str(), e.what());
console.printf("An error ocurred executing the command.\n\nDetails:\n%s", e.what()); console.printf("An error ocurred executing the command.\n\nDetails:\n%s", e.what());
} }
#ifdef NDEBUG #ifdef NDEBUG
catch (...) { catch (...) {
m_result = CommandResult(CommandResult::kError);
LOG(ERROR, "CTXT: Unknown exception executing %s command\n", LOG(ERROR, "CTXT: Unknown exception executing %s command\n",
command->id().c_str()); command->id().c_str());
@ -236,6 +244,11 @@ void Context::executeCommand(Command* command, const Params& params)
#endif #endif
} }
void Context::setCommandResult(const CommandResult& result)
{
m_result = result;
}
void Context::onAddDocument(Doc* doc) void Context::onAddDocument(Doc* doc)
{ {
m_lastSelectedDoc = doc; m_lastSelectedDoc = doc;

View File

@ -1,5 +1,5 @@
// Aseprite // Aseprite
// Copyright (C) 2018-2021 Igara Studio S.A. // Copyright (C) 2018-2022 Igara Studio S.A.
// Copyright (C) 2001-2018 David Capello // Copyright (C) 2001-2018 David Capello
// //
// This program is distributed under the terms of // This program is distributed under the terms of
@ -37,6 +37,24 @@ namespace app {
class DocView; class DocView;
class Preferences; class Preferences;
class CommandResult {
public:
enum Type {
kOk,
// Exception throw (e.g. cannot lock sprite)
kError,
// Canceled by user.
kCanceled,
};
CommandResult(Type type = Type::kOk) : m_type(type) { }
Type type() const { return m_type; }
void reset() { m_type = Type::kOk; }
private:
Type m_type;
};
class CommandPreconditionException : public base::Exception { class CommandPreconditionException : public base::Exception {
public: public:
CommandPreconditionException() throw() CommandPreconditionException() throw()
@ -100,6 +118,9 @@ namespace app {
void executeCommandFromMenuOrShortcut(Command* command, const Params& params = Params()); void executeCommandFromMenuOrShortcut(Command* command, const Params& params = Params());
virtual void executeCommand(Command* command, const Params& params = Params()); virtual void executeCommand(Command* command, const Params& params = Params());
void setCommandResult(const CommandResult& result);
const CommandResult& commandResult() { return m_result; }
virtual DocView* getFirstDocView(Doc* document) const { virtual DocView* getFirstDocView(Doc* document) const {
return nullptr; return nullptr;
} }
@ -134,6 +155,9 @@ namespace app {
Doc* m_lastSelectedDoc; Doc* m_lastSelectedDoc;
mutable std::unique_ptr<Preferences> m_preferences; mutable std::unique_ptr<Preferences> m_preferences;
// Result of the execution of a command.
CommandResult m_result;
DISABLE_COPYING(Context); DISABLE_COPYING(Context);
}; };

View File

@ -1,5 +1,5 @@
// Aseprite // Aseprite
// Copyright (C) 2018-2021 Igara Studio S.A. // Copyright (C) 2018-2022 Igara Studio S.A.
// Copyright (C) 2001-2018 David Capello // Copyright (C) 2001-2018 David Capello
// //
// This program is distributed under the terms of // This program is distributed under the terms of
@ -333,9 +333,10 @@ private:
return nullptr; return nullptr;
ObjectId palId = read32(s); ObjectId palId = read32(s);
Palette* pal = loadObject<Palette*>("pal", palId, &Reader::readPalette); std::unique_ptr<Palette> pal(
loadObject<Palette*>("pal", palId, &Reader::readPalette));
if (pal) if (pal)
spr->setPalette(pal, true); spr->setPalette(pal.get(), true);
} }
} }

View File

@ -1,5 +1,5 @@
// Aseprite // Aseprite
// Copyright (C) 2019 Igara Studio S.A. // Copyright (C) 2019-2022 Igara Studio S.A.
// Copyright (C) 2018 David Capello // Copyright (C) 2018 David Capello
// //
// This program is distributed under the terms of // This program is distributed under the terms of
@ -52,6 +52,15 @@ int Command_call(lua_State* L)
} }
ctx->executeCommand(command, params); ctx->executeCommand(command, params);
if (ctx->commandResult().type() == CommandResult::kOk) {
lua_pushboolean(L, true);
}
else {
// TODO rollback/cancel the whole current transaction?
// or just throw an luaL_error()?
lua_pushboolean(L, false);
}
return 1; return 1;
} }

View File

@ -270,6 +270,18 @@ void StateWithWheelBehavior::processWheelAction(
ToolPreferences::Brush& brush = ToolPreferences::Brush& brush =
Preferences::instance().tool(tool).brush; Preferences::instance().tool(tool).brush;
#if LAF_WINDOWS || LAF_LINUX
// By default on macOS the mouse wheel is correct, up increase
// brush size, and down decrease it. But on Windows and Linux
// it's inverted.
dz = -dz;
#endif
// We can configure the mouse wheel for brush size to behave as
// in previous versions.
if (Preferences::instance().editor.invertBrushSizeWheel())
dz = -dz;
brush.size( brush.size(
base::clamp( base::clamp(
int(initialBrushSize()+dz), int(initialBrushSize()+dz),

View File

@ -1,5 +1,5 @@
// Aseprite // Aseprite
// Copyright (C) 2019-2021 Igara Studio S.A. // Copyright (C) 2019-2022 Igara Studio S.A.
// Copyright (C) 2001-2018 David Capello // Copyright (C) 2001-2018 David Capello
// //
// This program is distributed under the terms of // This program is distributed under the terms of
@ -282,6 +282,9 @@ protected:
bool back = (msg->altPressed() && scancode == kKeyLeft); bool back = (msg->altPressed() && scancode == kKeyLeft);
bool forward = (msg->altPressed() && scancode == kKeyRight); bool forward = (msg->altPressed() && scancode == kKeyRight);
#endif #endif
bool refresh = (scancode == kKeyF5 ||
(msg->ctrlPressed() && scancode == kKeyR) ||
(msg->cmdPressed() && scancode == kKeyR));
if (up) { if (up) {
m_filesel->goUp(); m_filesel->goUp();
@ -299,6 +302,9 @@ protected:
m_filesel->goForward(); m_filesel->goForward();
return true; return true;
} }
if (refresh) {
m_filesel->refreshCurrentFolder();
}
return false; return false;
} }
} }
@ -322,6 +328,7 @@ FileSelector::FileSelector(FileSelectorType type)
goBackButton()->setFocusStop(false); goBackButton()->setFocusStop(false);
goForwardButton()->setFocusStop(false); goForwardButton()->setFocusStop(false);
goUpButton()->setFocusStop(false); goUpButton()->setFocusStop(false);
refreshButton()->setFocusStop(false);
newFolderButton()->setFocusStop(false); newFolderButton()->setFocusStop(false);
viewType()->setFocusStop(false); viewType()->setFocusStop(false);
for (auto child : viewType()->children()) for (auto child : viewType()->children())
@ -340,6 +347,7 @@ FileSelector::FileSelector(FileSelectorType type)
goBackButton()->Click.connect([this]{ onGoBack(); }); goBackButton()->Click.connect([this]{ onGoBack(); });
goForwardButton()->Click.connect([this]{ onGoForward(); }); goForwardButton()->Click.connect([this]{ onGoForward(); });
goUpButton()->Click.connect([this]{ onGoUp(); }); goUpButton()->Click.connect([this]{ onGoUp(); });
refreshButton()->Click.connect([this] { onRefreshFolder(); });
newFolderButton()->Click.connect([this]{ onNewFolder(); }); newFolderButton()->Click.connect([this]{ onNewFolder(); });
viewType()->ItemChange.connect([this]{ onChangeViewType(); }); viewType()->ItemChange.connect([this]{ onChangeViewType(); });
location()->CloseListBox.connect([this]{ onLocationCloseListBox(); }); location()->CloseListBox.connect([this]{ onLocationCloseListBox(); });
@ -382,6 +390,11 @@ void FileSelector::goInsideFolder()
} }
} }
void FileSelector::refreshCurrentFolder()
{
onRefreshFolder();
}
bool FileSelector::show( bool FileSelector::show(
const std::string& title, const std::string& title,
const std::string& initialPath, const std::string& initialPath,
@ -876,6 +889,14 @@ void FileSelector::onGoUp()
m_fileList->goUp(); m_fileList->goUp();
} }
void FileSelector::onRefreshFolder()
{
auto fs = FileSystemModule::instance();
fs->refresh();
m_fileList->setCurrentFolder(m_fileList->currentFolder());
}
void FileSelector::onNewFolder() void FileSelector::onNewFolder()
{ {
app::gen::NewFolderWindow window; app::gen::NewFolderWindow window;

View File

@ -37,6 +37,7 @@ namespace app {
void goForward(); void goForward();
void goUp(); void goUp();
void goInsideFolder(); void goInsideFolder();
void refreshCurrentFolder();
// Shows the dialog to select a file in the program. // Shows the dialog to select a file in the program.
bool show(const std::string& title, bool show(const std::string& title,
@ -60,6 +61,7 @@ namespace app {
void onFileListFileSelected(); void onFileListFileSelected();
void onFileListFileAccepted(); void onFileListFileAccepted();
void onFileListCurrentFolderChanged(); void onFileListCurrentFolderChanged();
void onRefreshFolder();
std::string getSelectedExtension() const; std::string getSelectedExtension() const;
class ArrowNavigator; class ArrowNavigator;

View File

@ -83,7 +83,7 @@ protected:
return true; return true;
case kKeyDownMessage: case kKeyDownMessage:
if (window()->isForeground() && if (window()->shouldProcessEscKeyToCloseWindow() &&
static_cast<KeyMessage*>(msg)->scancode() == kKeyEsc) { static_cast<KeyMessage*>(msg)->scancode() == kKeyEsc) {
setSelected(true); setSelected(true);
return true; return true;
@ -91,7 +91,7 @@ protected:
break; break;
case kKeyUpMessage: case kKeyUpMessage:
if (window()->isForeground() && if (window()->shouldProcessEscKeyToCloseWindow() &&
static_cast<KeyMessage*>(msg)->scancode() == kKeyEsc) { static_cast<KeyMessage*>(msg)->scancode() == kKeyEsc) {
if (isSelected()) { if (isSelected()) {
setSelected(false); setSelected(false);

View File

@ -1,5 +1,5 @@
// Aseprite UI Library // Aseprite UI Library
// Copyright (C) 2019-2021 Igara Studio S.A. // Copyright (C) 2019-2022 Igara Studio S.A.
// Copyright (C) 2001-2017 David Capello // Copyright (C) 2001-2017 David Capello
// //
// This file is released under the terms of the MIT license. // This file is released under the terms of the MIT license.
@ -72,11 +72,20 @@ namespace ui {
gfx::Rect lastNativeFrame() const { return m_lastFrame; } gfx::Rect lastNativeFrame() const { return m_lastFrame; }
void loadNativeFrame(const gfx::Rect& frame); void loadNativeFrame(const gfx::Rect& frame);
// Esc key closes the current window (presses the little close
// button decorator) only on foreground windows, but you can
// override this to allow this behavior in other kind of windows.
virtual bool shouldProcessEscKeyToCloseWindow() const {
return isForeground();
}
// Signals // Signals
obs::signal<void (Event&)> Open; obs::signal<void (Event&)> Open;
obs::signal<void (CloseEvent&)> Close; obs::signal<void (CloseEvent&)> Close;
protected: protected:
ButtonBase* closeButton() { return m_closeButton; }
virtual bool onProcessMessage(Message* msg) override; virtual bool onProcessMessage(Message* msg) override;
virtual void onInvalidateRegion(const gfx::Region& region) override; virtual void onInvalidateRegion(const gfx::Region& region) override;
virtual void onResize(ResizeEvent& ev) override; virtual void onResize(ResizeEvent& ev) override;

@ -1 +1 @@
Subproject commit 9bbd1f1b30bfa6fb52bf1388ab336ef39d0faead Subproject commit b6f36191c2022f5936f272da82dcaa36b9114918