mirror of
https://github.com/aseprite/aseprite.git
synced 2024-10-06 23:09:58 +00:00
Merge branch 'main' into beta
This commit is contained in:
commit
76a815cc2c
@ -325,17 +325,15 @@ int App::initialize(const AppOptions& options)
|
||||
// Show the main window (this is not modal, the code continues)
|
||||
m_mainWindow->openWindow();
|
||||
|
||||
// Redraw the whole screen.
|
||||
manager->invalidate();
|
||||
|
||||
// Pump some messages so we receive the first
|
||||
// Manager::onNewDisplayConfiguration() and we known the manager
|
||||
// initial size. This is required so if the OpenFileCommand
|
||||
// (called when we're processing the CLI with OpenBatchOfFiles)
|
||||
// shows a dialog to open a sequence of files, the dialog is
|
||||
// centered correctly to the manager bounds.
|
||||
ui::MessageLoop loop(manager);
|
||||
loop.pumpMessages();
|
||||
// To know the initial manager size we call to
|
||||
// Manager::updateAllDisplaysWithNewScale(...) so we receive a
|
||||
// Manager::onNewDisplayConfiguration() (which will update the
|
||||
// bounds of the manager for first time). This is required so if
|
||||
// the OpenFileCommand (called when we're processing the CLI with
|
||||
// OpenBatchOfFiles) shows a dialog to open a sequence of files,
|
||||
// the dialog is centered correctly to the manager bounds.
|
||||
const int scale = Preferences::instance().general.screenScale();
|
||||
manager->updateAllDisplaysWithNewScale(scale);
|
||||
}
|
||||
#endif // ENABLE_UI
|
||||
|
||||
|
@ -70,14 +70,6 @@ Doc::Doc(Sprite* sprite)
|
||||
Doc::~Doc()
|
||||
{
|
||||
DOC_TRACE("DOC: Deleting", this);
|
||||
|
||||
try {
|
||||
notify_observers<Doc*>(&DocObserver::onDestroy, this);
|
||||
}
|
||||
catch (...) {
|
||||
LOG(ERROR, "DOC: Exception on DocObserver::onDestroy()\n");
|
||||
}
|
||||
|
||||
removeFromContext();
|
||||
}
|
||||
|
||||
@ -592,6 +584,13 @@ Doc* Doc::duplicate(DuplicateType type) const
|
||||
|
||||
void Doc::close()
|
||||
{
|
||||
try {
|
||||
notify_observers<Doc*>(&DocObserver::onCloseDocument, this);
|
||||
}
|
||||
catch (...) {
|
||||
LOG(ERROR, "DOC: Exception on DocObserver::onCloseDocument()\n");
|
||||
}
|
||||
|
||||
removeFromContext();
|
||||
}
|
||||
|
||||
|
@ -17,7 +17,7 @@ namespace app {
|
||||
public:
|
||||
virtual ~DocObserver() { }
|
||||
|
||||
virtual void onDestroy(Doc* doc) { }
|
||||
virtual void onCloseDocument(Doc* doc) { }
|
||||
virtual void onFileNameChanged(Doc* doc) { }
|
||||
|
||||
// General update. If an observer receives this event, it's because
|
||||
|
@ -506,8 +506,11 @@ bool CustomizedGuiManager::onProcessMessage(Message* msg)
|
||||
switch (msg->type()) {
|
||||
|
||||
case kCloseDisplayMessage:
|
||||
// When the main display is closed...
|
||||
if (msg->display() == this->display()) {
|
||||
// Only call the exit command/close the app when the the main
|
||||
// display is the closed window in this kCloseDisplayMessage
|
||||
// message and it's the current running foreground window.
|
||||
if (msg->display() == this->display() &&
|
||||
getForegroundWindow() == App::instance()->mainWindow()) {
|
||||
// Execute the "Exit" command.
|
||||
Command* command = Commands::instance()->byId(CommandId::Exit());
|
||||
UIContext::instance()->executeCommandFromMenuOrShortcut(command);
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include "app/doc.h"
|
||||
#include "app/doc_undo.h"
|
||||
#include "app/doc_undo_observer.h"
|
||||
#include "app/pref/preferences.h"
|
||||
#include "app/script/docobj.h"
|
||||
#include "app/script/engine.h"
|
||||
#include "app/script/luacpp.h"
|
||||
@ -122,7 +123,7 @@ private:
|
||||
class AppEvents : public Events
|
||||
, private ContextObserver {
|
||||
public:
|
||||
enum : EventType { Unknown = -1, SiteChange };
|
||||
enum : EventType { Unknown = -1, SiteChange, FgColorChange, BgColorChange };
|
||||
|
||||
AppEvents() {
|
||||
}
|
||||
@ -130,6 +131,10 @@ public:
|
||||
EventType eventType(const char* eventName) const {
|
||||
if (std::strcmp(eventName, "sitechange") == 0)
|
||||
return SiteChange;
|
||||
else if (std::strcmp(eventName, "fgcolorchange") == 0)
|
||||
return FgColorChange;
|
||||
else if (std::strcmp(eventName, "bgcolorchange") == 0)
|
||||
return BgColorChange;
|
||||
else
|
||||
return Unknown;
|
||||
}
|
||||
@ -138,24 +143,49 @@ private:
|
||||
|
||||
void onAddFirstListener(EventType eventType) override {
|
||||
switch (eventType) {
|
||||
case SiteChange: {
|
||||
case SiteChange:
|
||||
App::instance()->context()->add_observer(this);
|
||||
break;
|
||||
}
|
||||
case FgColorChange:
|
||||
m_fgConn = Preferences::instance().colorBar.fgColor
|
||||
.AfterChange.connect([this]{ onFgColorChange(); });
|
||||
break;
|
||||
case BgColorChange:
|
||||
m_bgConn = Preferences::instance().colorBar.bgColor
|
||||
.AfterChange.connect([this]{ onBgColorChange(); });
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void onRemoveLastListener(EventType eventType) override {
|
||||
switch (eventType) {
|
||||
case SiteChange: {
|
||||
case SiteChange:
|
||||
App::instance()->context()->remove_observer(this);
|
||||
break;
|
||||
}
|
||||
case FgColorChange:
|
||||
m_fgConn.disconnect();
|
||||
break;
|
||||
case BgColorChange:
|
||||
m_bgConn.disconnect();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void onFgColorChange() {
|
||||
call(FgColorChange);
|
||||
}
|
||||
|
||||
void onBgColorChange() {
|
||||
call(BgColorChange);
|
||||
}
|
||||
|
||||
// ContextObserver impl
|
||||
void onActiveSiteChange(const Site& site) override { call(SiteChange); }
|
||||
void onActiveSiteChange(const Site& site) override {
|
||||
call(SiteChange);
|
||||
}
|
||||
|
||||
obs::scoped_connection m_fgConn;
|
||||
obs::scoped_connection m_bgConn;
|
||||
};
|
||||
|
||||
class SpriteEvents : public Events
|
||||
@ -170,11 +200,12 @@ public:
|
||||
}
|
||||
|
||||
~SpriteEvents() {
|
||||
if (m_observingUndo) {
|
||||
doc()->undoHistory()->remove_observer(this);
|
||||
m_observingUndo = false;
|
||||
auto doc = this->doc();
|
||||
ASSERT(doc);
|
||||
if (doc) {
|
||||
disconnectFromUndoHistory(doc);
|
||||
doc->remove_observer(this);
|
||||
}
|
||||
doc()->remove_observer(this);
|
||||
}
|
||||
|
||||
EventType eventType(const char* eventName) const {
|
||||
@ -185,11 +216,13 @@ public:
|
||||
}
|
||||
|
||||
// DocObserver impl
|
||||
void onDestroy(Doc* doc) override {
|
||||
void onCloseDocument(Doc* doc) override {
|
||||
auto it = g_spriteEvents.find(m_spriteId);
|
||||
ASSERT(it != g_spriteEvents.end());
|
||||
if (it != g_spriteEvents.end())
|
||||
if (it != g_spriteEvents.end()) {
|
||||
// As this is an unique_ptr, here we are calling ~SpriteEvents()
|
||||
g_spriteEvents.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
// DocUndoObserver impl
|
||||
@ -211,10 +244,7 @@ private:
|
||||
void onRemoveLastListener(EventType eventType) override {
|
||||
switch (eventType) {
|
||||
case Change: {
|
||||
if (m_observingUndo) {
|
||||
doc()->undoHistory()->remove_observer(this);
|
||||
m_observingUndo = false;
|
||||
}
|
||||
disconnectFromUndoHistory(doc());
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -228,6 +258,13 @@ private:
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void disconnectFromUndoHistory(Doc* doc) {
|
||||
if (m_observingUndo) {
|
||||
doc->undoHistory()->remove_observer(this);
|
||||
m_observingUndo = false;
|
||||
}
|
||||
}
|
||||
|
||||
ObjectId m_spriteId;
|
||||
bool m_observingUndo = false;
|
||||
};
|
||||
|
@ -13,11 +13,14 @@
|
||||
#include "app/script/engine.h"
|
||||
#include "app/script/luacpp.h"
|
||||
#include "app/script/security.h"
|
||||
#include "ui/timer.h"
|
||||
#include "ui/manager.h"
|
||||
#include "ui/system.h"
|
||||
|
||||
#include <ixwebsocket/IXNetSystem.h>
|
||||
#include <ixwebsocket/IXWebSocket.h>
|
||||
#include <sstream>
|
||||
#include <set>
|
||||
|
||||
namespace app {
|
||||
namespace script {
|
||||
@ -27,6 +30,18 @@ namespace {
|
||||
// Additional "enum" value to make message callback simpler
|
||||
#define MESSAGE_TYPE_BINARY ((int)ix::WebSocketMessageType::Fragment + 10)
|
||||
|
||||
static std::unique_ptr<ui::Timer> g_timer;
|
||||
static std::set<ix::WebSocket*> g_connections;
|
||||
|
||||
static void close_ws(ix::WebSocket* ws)
|
||||
{
|
||||
ws->stop();
|
||||
|
||||
g_connections.erase(ws);
|
||||
if (g_connections.empty())
|
||||
g_timer.reset();
|
||||
}
|
||||
|
||||
int WebSocket_new(lua_State* L)
|
||||
{
|
||||
static std::once_flag f;
|
||||
@ -55,7 +70,19 @@ int WebSocket_new(lua_State* L)
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
|
||||
int type = lua_getfield(L, 1, "onreceive");
|
||||
int type = lua_getfield(L, 1, "minreconnectwait");
|
||||
if (type == LUA_TNUMBER) {
|
||||
ws->setMinWaitBetweenReconnectionRetries(1000 * lua_tonumber(L, -1));
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
|
||||
type = lua_getfield(L, 1, "maxreconnectwait");
|
||||
if (type == LUA_TNUMBER) {
|
||||
ws->setMaxWaitBetweenReconnectionRetries(1000 * lua_tonumber(L, -1));
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
|
||||
type = lua_getfield(L, 1, "onreceive");
|
||||
if (type == LUA_TFUNCTION) {
|
||||
int onreceiveRef = luaL_ref(L, LUA_REGISTRYINDEX);
|
||||
|
||||
@ -80,6 +107,8 @@ int WebSocket_new(lua_State* L)
|
||||
});
|
||||
}
|
||||
else {
|
||||
// Set a default handler to avoid a std::bad_function_call exception
|
||||
ws->setOnMessageCallback([](const ix::WebSocketMessagePtr& msg) { });
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
}
|
||||
@ -90,7 +119,7 @@ int WebSocket_new(lua_State* L)
|
||||
int WebSocket_gc(lua_State* L)
|
||||
{
|
||||
auto ws = get_ptr<ix::WebSocket>(L, 1);
|
||||
ws->stop();
|
||||
close_ws(ws);
|
||||
delete ws;
|
||||
return 0;
|
||||
}
|
||||
@ -151,13 +180,24 @@ int WebSocket_connect(lua_State* L)
|
||||
{
|
||||
auto ws = get_ptr<ix::WebSocket>(L, 1);
|
||||
ws->start();
|
||||
|
||||
if (g_connections.empty()) {
|
||||
#ifdef ENABLE_UI
|
||||
if (App::instance()->isGui()) {
|
||||
g_timer = std::make_unique<ui::Timer>(33, ui::Manager::getDefault());
|
||||
g_timer->start();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
g_connections.insert(ws);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int WebSocket_close(lua_State* L)
|
||||
{
|
||||
auto ws = get_ptr<ix::WebSocket>(L, 1);
|
||||
ws->stop();
|
||||
close_ws(ws);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -198,14 +238,14 @@ void register_websocket_class(lua_State* L)
|
||||
lua_newtable(L);
|
||||
lua_pushvalue(L, -1);
|
||||
lua_setglobal(L, "WebSocketMessageType");
|
||||
setfield_integer(L, "Text", (int)ix::WebSocketMessageType::Message);
|
||||
setfield_integer(L, "Binary", MESSAGE_TYPE_BINARY);
|
||||
setfield_integer(L, "Open", (int)ix::WebSocketMessageType::Open);
|
||||
setfield_integer(L, "Close", (int)ix::WebSocketMessageType::Close);
|
||||
setfield_integer(L, "Error", (int)ix::WebSocketMessageType::Error);
|
||||
setfield_integer(L, "Ping", (int)ix::WebSocketMessageType::Ping);
|
||||
setfield_integer(L, "Pong", (int)ix::WebSocketMessageType::Pong);
|
||||
setfield_integer(L, "Fragment", (int)ix::WebSocketMessageType::Fragment);
|
||||
setfield_integer(L, "TEXT", (int)ix::WebSocketMessageType::Message);
|
||||
setfield_integer(L, "BINARY", MESSAGE_TYPE_BINARY);
|
||||
setfield_integer(L, "OPEN", (int)ix::WebSocketMessageType::Open);
|
||||
setfield_integer(L, "CLOSE", (int)ix::WebSocketMessageType::Close);
|
||||
setfield_integer(L, "ERROR", (int)ix::WebSocketMessageType::Error);
|
||||
setfield_integer(L, "PING", (int)ix::WebSocketMessageType::Ping);
|
||||
setfield_integer(L, "PONG", (int)ix::WebSocketMessageType::Pong);
|
||||
setfield_integer(L, "FRAGMENT", (int)ix::WebSocketMessageType::Fragment);
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
|
||||
|
@ -394,10 +394,12 @@ Widget* WidgetLoader::convertXmlElementToWidget(const TiXmlElement* elem, Widget
|
||||
else if (elem_name == "slider") {
|
||||
const char *min = elem->Attribute("min");
|
||||
const char *max = elem->Attribute("max");
|
||||
const bool readonly = bool_attr(elem, "readonly", false);
|
||||
int min_value = (min ? strtol(min, nullptr, 10): 0);
|
||||
int max_value = (max ? strtol(max, nullptr, 10): 0);
|
||||
|
||||
widget = new Slider(min_value, max_value, min_value);
|
||||
static_cast<Slider*>(widget)->setReadOnly(readonly);
|
||||
}
|
||||
else if (elem_name == "textbox") {
|
||||
const char* text = (elem->GetText() ? elem->GetText(): "");
|
||||
|
@ -133,6 +133,9 @@ static Item convert_to_item(TiXmlElement* elem)
|
||||
if (name == "listbox")
|
||||
return item.typeIncl("ui::ListBox",
|
||||
"ui/listbox.h");
|
||||
if (name == "listitem")
|
||||
return item.typeIncl("ui::ListItem",
|
||||
"ui/listitem.h");
|
||||
if (name == "panel")
|
||||
return item.typeIncl("ui::Panel",
|
||||
"ui/panel.h");
|
||||
|
Loading…
Reference in New Issue
Block a user