Merge branch 'main' into beta

This commit is contained in:
David Capello 2021-10-20 11:53:47 -03:00
commit 76a815cc2c
8 changed files with 131 additions and 49 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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