mirror of
https://github.com/aseprite/aseprite.git
synced 2025-01-26 12:35:33 +00:00
Replace signals/slots impl with the observable library
This commit is contained in:
parent
bfb65c3d96
commit
da128d3a6e
3
.gitmodules
vendored
3
.gitmodules
vendored
@ -30,3 +30,6 @@
|
||||
[submodule "src/clip"]
|
||||
path = src/clip
|
||||
url = https://github.com/aseprite/clip.git
|
||||
[submodule "src/observable"]
|
||||
path = src/observable
|
||||
url = https://github.com/dacap/observable.git
|
||||
|
@ -80,12 +80,18 @@ endif()
|
||||
######################################################################
|
||||
# Aseprite Libraries (in preferred order to be built)
|
||||
|
||||
# Disable observable tests
|
||||
set(OBSERVABLE_TESTS OFF CACHE BOOL "Compile observable tests")
|
||||
add_subdirectory(observable)
|
||||
include_directories(observable)
|
||||
|
||||
# Our base library
|
||||
add_subdirectory(base)
|
||||
|
||||
# Directory where base/config.h file is located
|
||||
include_directories(${BASE_INCLUDE_DIR})
|
||||
|
||||
# Disable clip
|
||||
# Disable clip examples
|
||||
set(CLIP_EXAMPLES OFF CACHE BOOL "Compile clip examples")
|
||||
add_subdirectory(clip)
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2001-2015 David Capello
|
||||
// Copyright (C) 2001-2016 David Capello
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License version 2 as
|
||||
@ -9,6 +9,7 @@
|
||||
#define APP_APP_MENUS_H_INCLUDED
|
||||
#pragma once
|
||||
|
||||
#include "base/connection.h"
|
||||
#include "base/disable_copying.h"
|
||||
#include "base/unique_ptr.h"
|
||||
#include "ui/base.h"
|
||||
|
@ -16,58 +16,44 @@
|
||||
|
||||
namespace app {
|
||||
|
||||
EditorObservers::EditorObservers()
|
||||
{
|
||||
}
|
||||
|
||||
void EditorObservers::addObserver(EditorObserver* observer)
|
||||
{
|
||||
m_observers.addObserver(observer);
|
||||
}
|
||||
|
||||
void EditorObservers::removeObserver(EditorObserver* observer)
|
||||
{
|
||||
m_observers.removeObserver(observer);
|
||||
}
|
||||
|
||||
void EditorObservers::notifyDestroyEditor(Editor* editor)
|
||||
{
|
||||
m_observers.notifyObservers(&EditorObserver::onDestroyEditor, editor);
|
||||
notifyObservers(&EditorObserver::onDestroyEditor, editor);
|
||||
}
|
||||
|
||||
void EditorObservers::notifyStateChanged(Editor* editor)
|
||||
{
|
||||
m_observers.notifyObservers(&EditorObserver::onStateChanged, editor);
|
||||
notifyObservers(&EditorObserver::onStateChanged, editor);
|
||||
}
|
||||
|
||||
void EditorObservers::notifyScrollChanged(Editor* editor)
|
||||
{
|
||||
m_observers.notifyObservers(&EditorObserver::onScrollChanged, editor);
|
||||
notifyObservers(&EditorObserver::onScrollChanged, editor);
|
||||
}
|
||||
|
||||
void EditorObservers::notifyZoomChanged(Editor* editor)
|
||||
{
|
||||
m_observers.notifyObservers(&EditorObserver::onZoomChanged, editor);
|
||||
notifyObservers(&EditorObserver::onZoomChanged, editor);
|
||||
}
|
||||
|
||||
void EditorObservers::notifyBeforeFrameChanged(Editor* editor)
|
||||
{
|
||||
m_observers.notifyObservers(&EditorObserver::onBeforeFrameChanged, editor);
|
||||
notifyObservers(&EditorObserver::onBeforeFrameChanged, editor);
|
||||
}
|
||||
|
||||
void EditorObservers::notifyAfterFrameChanged(Editor* editor)
|
||||
{
|
||||
m_observers.notifyObservers(&EditorObserver::onAfterFrameChanged, editor);
|
||||
notifyObservers(&EditorObserver::onAfterFrameChanged, editor);
|
||||
}
|
||||
|
||||
void EditorObservers::notifyBeforeLayerChanged(Editor* editor)
|
||||
{
|
||||
m_observers.notifyObservers(&EditorObserver::onBeforeLayerChanged, editor);
|
||||
notifyObservers(&EditorObserver::onBeforeLayerChanged, editor);
|
||||
}
|
||||
|
||||
void EditorObservers::notifyAfterLayerChanged(Editor* editor)
|
||||
{
|
||||
m_observers.notifyObservers(&EditorObserver::onAfterLayerChanged, editor);
|
||||
notifyObservers(&EditorObserver::onAfterLayerChanged, editor);
|
||||
}
|
||||
|
||||
} // namespace app
|
||||
|
@ -10,18 +10,13 @@
|
||||
#pragma once
|
||||
|
||||
#include "app/ui/editor/editor_observer.h"
|
||||
#include "base/observers.h"
|
||||
#include "base/observable.h"
|
||||
|
||||
namespace app {
|
||||
class Editor;
|
||||
|
||||
class EditorObservers {
|
||||
class EditorObservers : public base::Observable<EditorObserver> {
|
||||
public:
|
||||
EditorObservers();
|
||||
|
||||
void addObserver(EditorObserver* observer);
|
||||
void removeObserver(EditorObserver* observer);
|
||||
|
||||
void notifyDestroyEditor(Editor* editor);
|
||||
void notifyStateChanged(Editor* editor);
|
||||
void notifyScrollChanged(Editor* editor);
|
||||
@ -30,9 +25,6 @@ namespace app {
|
||||
void notifyAfterFrameChanged(Editor* editor);
|
||||
void notifyBeforeLayerChanged(Editor* editor);
|
||||
void notifyAfterLayerChanged(Editor* editor);
|
||||
|
||||
private:
|
||||
base::Observers<EditorObserver> m_observers;
|
||||
};
|
||||
|
||||
} // namespace app
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2001-2015 David Capello
|
||||
// Copyright (C) 2001-2016 David Capello
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License version 2 as
|
||||
@ -9,6 +9,7 @@
|
||||
#define APP_UI_RECENT_LISTBOX_H_INCLUDED
|
||||
#pragma once
|
||||
|
||||
#include "base/connection.h"
|
||||
#include "ui/listbox.h"
|
||||
|
||||
namespace app {
|
||||
|
@ -11,7 +11,6 @@
|
||||
|
||||
#include "app/color.h"
|
||||
#include "app/tools/active_tool_observer.h"
|
||||
#include "base/observers.h"
|
||||
#include "base/time.h"
|
||||
#include "doc/context_observer.h"
|
||||
#include "doc/document_observer.h"
|
||||
|
@ -31,7 +31,6 @@ set(BASE_SOURCES
|
||||
base64.cpp
|
||||
cfile.cpp
|
||||
chrono.cpp
|
||||
connection.cpp
|
||||
convert_to.cpp
|
||||
debug.cpp
|
||||
dll.cpp
|
||||
@ -65,8 +64,9 @@ if(WIN32)
|
||||
win32_exception.cpp)
|
||||
endif()
|
||||
|
||||
# TODO remove dependency with observable library
|
||||
add_library(base-lib ${BASE_SOURCES})
|
||||
target_link_libraries(base-lib modp_b64)
|
||||
target_link_libraries(base-lib obs modp_b64)
|
||||
|
||||
if(WIN32)
|
||||
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
|
||||
|
@ -1,27 +0,0 @@
|
||||
// Aseprite Base Library
|
||||
// Copyright (c) 2001-2015 David Capello
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
// Read LICENSE.txt for more information.
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "base/connection.h"
|
||||
|
||||
#include "base/signal.h"
|
||||
|
||||
namespace base {
|
||||
|
||||
void Connection::disconnect()
|
||||
{
|
||||
if (!m_slot)
|
||||
return;
|
||||
|
||||
m_signal->disconnectSlot(m_slot);
|
||||
delete m_slot;
|
||||
m_slot = NULL;
|
||||
}
|
||||
|
||||
} // namespace base
|
@ -8,52 +8,12 @@
|
||||
#define BASE_CONNETION_H_INCLUDED
|
||||
#pragma once
|
||||
|
||||
#include "obs/connection.h"
|
||||
|
||||
namespace base {
|
||||
|
||||
class Signal;
|
||||
class Slot;
|
||||
|
||||
class Connection {
|
||||
public:
|
||||
Connection() : m_signal(nullptr), m_slot(nullptr) {
|
||||
}
|
||||
|
||||
Connection(Signal* signal, Slot* slot) :
|
||||
m_signal(signal), m_slot(slot) {
|
||||
}
|
||||
|
||||
void disconnect();
|
||||
|
||||
operator bool() {
|
||||
return (m_slot != nullptr);
|
||||
}
|
||||
|
||||
private:
|
||||
Signal* m_signal;
|
||||
Slot* m_slot;
|
||||
};
|
||||
|
||||
class ScopedConnection {
|
||||
public:
|
||||
ScopedConnection() {
|
||||
}
|
||||
|
||||
ScopedConnection(const Connection& conn) : m_conn(conn) {
|
||||
}
|
||||
|
||||
ScopedConnection& operator=(const Connection& conn) {
|
||||
m_conn.disconnect();
|
||||
m_conn = conn;
|
||||
return *this;
|
||||
}
|
||||
|
||||
~ScopedConnection() {
|
||||
m_conn.disconnect();
|
||||
}
|
||||
|
||||
private:
|
||||
Connection m_conn;
|
||||
};
|
||||
using Connection = obs::connection;
|
||||
using ScopedConnection = obs::scoped_connection;
|
||||
|
||||
} // namespace base
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite Base Library
|
||||
// Copyright (c) 2001-2013 David Capello
|
||||
// Copyright (c) 2001-2016 David Capello
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
// Read LICENSE.txt for more information.
|
||||
@ -8,43 +8,31 @@
|
||||
#define BASE_OBSERVABLE_H_INCLUDED
|
||||
#pragma once
|
||||
|
||||
#include "base/observers.h"
|
||||
#include "obs/observable.h"
|
||||
|
||||
namespace base {
|
||||
|
||||
template<typename Observer>
|
||||
class Observable {
|
||||
class Observable : private obs::observable<Observer> {
|
||||
typedef obs::observable<Observer> Base;
|
||||
public:
|
||||
|
||||
void addObserver(Observer* observer) {
|
||||
m_observers.addObserver(observer);
|
||||
Base::add_observer(observer);
|
||||
}
|
||||
|
||||
void removeObserver(Observer* observer) {
|
||||
m_observers.removeObserver(observer);
|
||||
Base::remove_observer(observer);
|
||||
}
|
||||
|
||||
void notifyObservers(void (Observer::*method)()) {
|
||||
m_observers.notifyObservers(method);
|
||||
Base::notify_observers(method);
|
||||
}
|
||||
|
||||
template<typename A1>
|
||||
void notifyObservers(void (Observer::*method)(A1), A1 a1) {
|
||||
m_observers.template notifyObservers<A1>(method, a1);
|
||||
template<typename ...Args>
|
||||
void notifyObservers(void (Observer::*method)(Args...), Args ...args) {
|
||||
Base::template notify_observers<Args...>(method, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template<typename A1, typename A2>
|
||||
void notifyObservers(void (Observer::*method)(A1, A2), A1 a1, A2 a2) {
|
||||
m_observers.template notifyObservers<A1, A2>(method, a1, a2);
|
||||
}
|
||||
|
||||
template<typename A1, typename A2, typename A3>
|
||||
void notifyObservers(void (Observer::*method)(A1, A2, A3), A1 a1, A2 a2, A3 a3) {
|
||||
m_observers.template notifyObservers<A1, A2, A3>(method, a1, a2, a3);
|
||||
}
|
||||
|
||||
private:
|
||||
Observers<Observer> m_observers;
|
||||
};
|
||||
|
||||
} // namespace base
|
||||
|
@ -1,97 +0,0 @@
|
||||
// Aseprite Base Library
|
||||
// Copyright (c) 2001-2016 David Capello
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
// Read LICENSE.txt for more information.
|
||||
|
||||
#ifndef BASE_OBSERVERS_H_INCLUDED
|
||||
#define BASE_OBSERVERS_H_INCLUDED
|
||||
#pragma once
|
||||
|
||||
#include "base/debug.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
|
||||
namespace base {
|
||||
|
||||
template<typename T>
|
||||
class Observers {
|
||||
public:
|
||||
typedef T observer_type;
|
||||
typedef std::vector<observer_type*> list_type;
|
||||
typedef typename list_type::iterator iterator;
|
||||
typedef typename list_type::const_iterator const_iterator;
|
||||
|
||||
bool empty() const { return m_observers.empty(); }
|
||||
std::size_t size() const { return m_observers.size(); }
|
||||
|
||||
// Adds the observer in the collection. The observer is owned by the
|
||||
// collection and will be destroyed calling the T::dispose() member
|
||||
// function.
|
||||
void addObserver(observer_type* observer) {
|
||||
ASSERT(std::find(m_observers.begin(), m_observers.end(), observer) == m_observers.end() && "You've tried to add an observer that already is in the collection");
|
||||
m_observers.push_back(observer);
|
||||
}
|
||||
|
||||
// Removes the observer from the collection. After calling this
|
||||
// function you own the observer so you have to dispose it.
|
||||
void removeObserver(observer_type* observer) {
|
||||
iterator it = std::find(m_observers.begin(), m_observers.end(), observer);
|
||||
if (it != m_observers.end())
|
||||
m_observers.erase(it);
|
||||
else {
|
||||
ASSERT(false && "You've tried to remove an observer that isn't in the collection");
|
||||
}
|
||||
}
|
||||
|
||||
void notifyObservers(void (observer_type::*method)()) {
|
||||
list_type copy = m_observers;
|
||||
for (iterator
|
||||
it = copy.begin(),
|
||||
end = copy.end(); it != end; ++it) {
|
||||
if (*it)
|
||||
((*it)->*method)();
|
||||
}
|
||||
}
|
||||
|
||||
template<typename A1>
|
||||
void notifyObservers(void (observer_type::*method)(A1), A1 a1) {
|
||||
list_type copy = m_observers;
|
||||
for (iterator
|
||||
it = copy.begin(),
|
||||
end = copy.end(); it != end; ++it) {
|
||||
if (*it)
|
||||
((*it)->*method)(a1);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename A1, typename A2>
|
||||
void notifyObservers(void (observer_type::*method)(A1, A2), A1 a1, A2 a2) {
|
||||
list_type copy = m_observers;
|
||||
for (iterator
|
||||
it = copy.begin(),
|
||||
end = copy.end(); it != end; ++it) {
|
||||
if (*it)
|
||||
((*it)->*method)(a1, a2);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename A1, typename A2, typename A3>
|
||||
void notifyObservers(void (observer_type::*method)(A1, A2, A3), A1 a1, A2 a2, A3 a3) {
|
||||
list_type copy = m_observers;
|
||||
for (iterator
|
||||
it = copy.begin(),
|
||||
end = copy.end(); it != end; ++it) {
|
||||
if (*it)
|
||||
((*it)->*method)(a1, a2, a3);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
list_type m_observers;
|
||||
};
|
||||
|
||||
} // namespace base
|
||||
|
||||
#endif // BASE_OBSERVERS_H_INCLUDED
|
@ -1,5 +1,5 @@
|
||||
// Aseprite Base Library
|
||||
// Copyright (c) 2001-2015 David Capello
|
||||
// Copyright (c) 2001-2016 David Capello
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
// Read LICENSE.txt for more information.
|
||||
@ -8,321 +8,18 @@
|
||||
#define BASE_SIGNAL_H_INCLUDED
|
||||
#pragma once
|
||||
|
||||
#include "base/connection.h"
|
||||
#include "base/remove_from_container.h"
|
||||
#include "base/slot.h"
|
||||
|
||||
#include <vector>
|
||||
#include "obs/signal.h"
|
||||
|
||||
namespace base {
|
||||
|
||||
class Signal {
|
||||
public:
|
||||
virtual ~Signal() { }
|
||||
virtual void disconnectSlot(Slot* slot) = 0;
|
||||
};
|
||||
|
||||
// Signal0_base<R> - Base class to delegate responsibility to
|
||||
// functions of zero arguments.
|
||||
template<typename R>
|
||||
class Signal0_base : public Signal {
|
||||
public:
|
||||
typedef R ReturnType;
|
||||
typedef Slot0<R> SlotType;
|
||||
typedef std::vector<SlotType*> SlotList;
|
||||
using Signal0 = obs::signal0<R>;
|
||||
|
||||
Signal0_base() { }
|
||||
~Signal0_base() {
|
||||
for (SlotType* slot : m_slots)
|
||||
delete slot;
|
||||
}
|
||||
|
||||
Signal0_base(const Signal0_base&) { }
|
||||
Signal0_base operator=(const Signal0_base&) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
Connection addSlot(SlotType* slot) {
|
||||
m_slots.push_back(slot);
|
||||
return Connection(this, slot);
|
||||
}
|
||||
|
||||
template<typename F>
|
||||
Connection connect(const F& f) {
|
||||
return addSlot(new Slot0_fun<R, F>(f));
|
||||
}
|
||||
|
||||
template<class T>
|
||||
Connection connect(R (T::*m)(), T* t) {
|
||||
return addSlot(new Slot0_mem<R, T>(m, t));
|
||||
}
|
||||
|
||||
virtual void disconnectSlot(Slot* slot) override {
|
||||
base::remove_from_container(m_slots, static_cast<SlotType*>(slot));
|
||||
}
|
||||
|
||||
protected:
|
||||
SlotList m_slots;
|
||||
};
|
||||
|
||||
// Signal0<R>
|
||||
template<typename R>
|
||||
class Signal0 : public Signal0_base<R> {
|
||||
public:
|
||||
// GCC needs redefinitions
|
||||
typedef Signal0_base<R> Base;
|
||||
typedef Slot0<R> SlotType;
|
||||
typedef typename Base::SlotList SlotList;
|
||||
|
||||
Signal0() {
|
||||
}
|
||||
|
||||
R operator()(R default_result = R()) {
|
||||
R result(default_result);
|
||||
SlotList copy = Base::m_slots;
|
||||
for (typename SlotList::iterator it = copy.begin(), end = copy.end(); it != end; ++it) {
|
||||
SlotType* slot = *it;
|
||||
result = (*slot)();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename Merger>
|
||||
R operator()(R default_result, const Merger& m) {
|
||||
R result(default_result);
|
||||
Merger merger(m);
|
||||
SlotList copy = Base::m_slots;
|
||||
for (typename SlotList::iterator it = copy.begin(), end = copy.end(); it != end; ++it) {
|
||||
SlotType* slot = *it;
|
||||
result = merger(result, (*slot)());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
// Signal0<void>
|
||||
template<>
|
||||
class Signal0<void> : public Signal0_base<void> {
|
||||
public:
|
||||
// GCC needs redefinitions
|
||||
typedef Signal0_base<void> Base;
|
||||
typedef Slot0<void> SlotType;
|
||||
typedef Base::SlotList SlotList;
|
||||
|
||||
Signal0() { }
|
||||
|
||||
void operator()() {
|
||||
SlotList copy = Base::m_slots;
|
||||
for (SlotList::iterator it = copy.begin(), end = copy.end(); it != end; ++it) {
|
||||
SlotType* slot = *it;
|
||||
(*slot)();
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
// Signal1_base<R, A1> - Base class to delegate responsibility to
|
||||
// functions of one argument.
|
||||
template<typename R, typename A1>
|
||||
class Signal1_base : public Signal {
|
||||
public:
|
||||
typedef R ReturnType;
|
||||
typedef Slot1<R, A1> SlotType;
|
||||
typedef std::vector<SlotType*> SlotList;
|
||||
using Signal1 = obs::signal1<R, A1>;
|
||||
|
||||
Signal1_base() { }
|
||||
~Signal1_base() {
|
||||
for (SlotType* slot : m_slots)
|
||||
delete slot;
|
||||
}
|
||||
|
||||
Signal1_base(const Signal1_base&) { }
|
||||
Signal1_base operator=(const Signal1_base&) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
Connection addSlot(SlotType* slot) {
|
||||
m_slots.push_back(slot);
|
||||
return Connection(this, slot);
|
||||
}
|
||||
|
||||
template<typename F>
|
||||
Connection connect(const F& f) {
|
||||
return addSlot(new Slot1_fun<R, F, A1>(f));
|
||||
}
|
||||
|
||||
template<class T>
|
||||
Connection connect(R (T::*m)(A1), T* t) {
|
||||
return addSlot(new Slot1_mem<R, T, A1>(m, t));
|
||||
}
|
||||
|
||||
virtual void disconnectSlot(Slot* slot) override {
|
||||
base::remove_from_container(m_slots, static_cast<SlotType*>(slot));
|
||||
}
|
||||
|
||||
protected:
|
||||
SlotList m_slots;
|
||||
};
|
||||
|
||||
// Signal1<R, A1>
|
||||
template<typename R, typename A1>
|
||||
class Signal1 : public Signal1_base<R, A1>
|
||||
{
|
||||
public:
|
||||
// GCC needs redefinitions
|
||||
typedef Signal1_base<R, A1> Base;
|
||||
typedef Slot1<R, A1> SlotType;
|
||||
typedef typename Base::SlotList SlotList;
|
||||
|
||||
Signal1() { }
|
||||
|
||||
R operator()(A1 a1, R default_result = R()) {
|
||||
R result(default_result);
|
||||
SlotList copy = Base::m_slots;
|
||||
for (typename SlotList::iterator it = copy.begin(), end = copy.end(); it != end; ++it) {
|
||||
SlotType* slot = *it;
|
||||
result = (*slot)(a1);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename Merger>
|
||||
R operator()(A1 a1, R default_result, const Merger& m) {
|
||||
R result(default_result);
|
||||
Merger merger(m);
|
||||
SlotList copy = Base::m_slots;
|
||||
for (typename SlotList::iterator it = copy.begin(), end = copy.end(); it != end; ++it) {
|
||||
SlotType* slot = *it;
|
||||
result = merger(result, (*slot)(a1));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
// Signal1<void, A1>
|
||||
template<typename A1>
|
||||
class Signal1<void, A1> : public Signal1_base<void, A1>
|
||||
{
|
||||
public:
|
||||
// GCC needs redefinitions
|
||||
typedef Signal1_base<void, A1> Base;
|
||||
typedef Slot1<void, A1> SlotType;
|
||||
typedef typename Base::SlotList SlotList;
|
||||
|
||||
Signal1() { }
|
||||
|
||||
void operator()(A1 a1) {
|
||||
SlotList copy = Base::m_slots;
|
||||
for (typename SlotList::iterator it = copy.begin(), end = copy.end(); it != end; ++it) {
|
||||
SlotType* slot = *it;
|
||||
(*slot)(a1);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
// Signal2_base<R, A1, A2> - Base class to delegate responsibility to
|
||||
// functions of two arguments.
|
||||
template<typename R, typename A1, typename A2>
|
||||
class Signal2_base : public Signal {
|
||||
public:
|
||||
typedef R ReturnType;
|
||||
typedef Slot2<R, A1, A2> SlotType;
|
||||
typedef std::vector<SlotType*> SlotList;
|
||||
|
||||
Signal2_base() { }
|
||||
~Signal2_base() {
|
||||
for (SlotType* slot : m_slots)
|
||||
delete slot;
|
||||
}
|
||||
|
||||
Signal2_base(const Signal2_base&) { }
|
||||
Signal2_base operator=(const Signal2_base&) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
Connection addSlot(SlotType* slot) {
|
||||
m_slots.push_back(slot);
|
||||
return Connection(this, slot);
|
||||
}
|
||||
|
||||
template<typename F>
|
||||
Connection connect(const F& f) {
|
||||
return addSlot(new Slot2_fun<R, F, A1, A2>(f));
|
||||
}
|
||||
|
||||
template<class T>
|
||||
Connection connect(R (T::*m)(A1, A2), T* t) {
|
||||
return addSlot(new Slot2_mem<R, T, A1, A2>(m, t));
|
||||
}
|
||||
|
||||
virtual void disconnectSlot(Slot* slot) override {
|
||||
base::remove_from_container(m_slots, static_cast<SlotType*>(slot));
|
||||
}
|
||||
|
||||
protected:
|
||||
SlotList m_slots;
|
||||
};
|
||||
|
||||
// Signal2<R, A1>
|
||||
template<typename R, typename A1, typename A2>
|
||||
class Signal2 : public Signal2_base<R, A1, A2> {
|
||||
public:
|
||||
// GCC needs redefinitions
|
||||
typedef Signal2_base<R, A1, A2> Base;
|
||||
typedef Slot2<R, A1, A2> SlotType;
|
||||
typedef typename Base::SlotList SlotList;
|
||||
|
||||
Signal2() {
|
||||
}
|
||||
|
||||
R operator()(A1 a1, A2 a2, R default_result = R()) {
|
||||
R result(default_result);
|
||||
SlotList copy = Base::m_slots;
|
||||
for (typename SlotList::iterator it = copy.begin(), end = copy.end(); it != end; ++it) {
|
||||
SlotType* slot = *it;
|
||||
result = (*slot)(a1, a2);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename Merger>
|
||||
R operator()(A1 a1, A2 a2, R default_result, const Merger& m) {
|
||||
R result(default_result);
|
||||
Merger merger(m);
|
||||
SlotList copy = Base::m_slots;
|
||||
for (typename SlotList::iterator it = copy.begin(), end = copy.end(); it != end; ++it) {
|
||||
SlotType* slot = *it;
|
||||
result = merger(result, (*slot)(a1, a2));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
// Signal2<void, A1>
|
||||
template<typename A1, typename A2>
|
||||
class Signal2<void, A1, A2> : public Signal2_base<void, A1, A2> {
|
||||
public:
|
||||
// GCC needs redefinitions
|
||||
typedef Signal2_base<void, A1, A2> Base;
|
||||
typedef Slot2<void, A1, A2> SlotType;
|
||||
typedef typename Base::SlotList SlotList;
|
||||
|
||||
Signal2() {
|
||||
}
|
||||
|
||||
void operator()(A1 a1, A2 a2) {
|
||||
SlotList copy = Base::m_slots;
|
||||
for (typename SlotList::iterator it = copy.begin(), end = copy.end(); it != end; ++it) {
|
||||
SlotType* slot = *it;
|
||||
(*slot)(a1, a2);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
using Signal2 = obs::signal2<R, A1, A2>;
|
||||
|
||||
} // namespace base
|
||||
|
||||
|
188
src/base/slot.h
188
src/base/slot.h
@ -1,188 +0,0 @@
|
||||
// Aseprite Base Library
|
||||
// Copyright (c) 2001-2013, 2015 David Capello
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
// Read LICENSE.txt for more information.
|
||||
|
||||
#ifndef BASE_SLOT_H_INCLUDED
|
||||
#define BASE_SLOT_H_INCLUDED
|
||||
#pragma once
|
||||
|
||||
#include "base/disable_copying.h"
|
||||
|
||||
namespace base {
|
||||
|
||||
class Slot {
|
||||
public:
|
||||
Slot() { }
|
||||
virtual ~Slot() { }
|
||||
|
||||
private:
|
||||
DISABLE_COPYING(Slot);
|
||||
};
|
||||
|
||||
// Slot0 - Base class for delegates of zero arguments.
|
||||
template<typename R>
|
||||
class Slot0 : public Slot {
|
||||
public:
|
||||
Slot0() { }
|
||||
Slot0(const Slot0& s) { (void)s; }
|
||||
virtual ~Slot0() { }
|
||||
virtual R operator()() = 0;
|
||||
};
|
||||
|
||||
// Slot0_fun - hold a F instance and use the function call operator
|
||||
template<typename R, typename F>
|
||||
class Slot0_fun : public Slot0<R> {
|
||||
F f;
|
||||
public:
|
||||
Slot0_fun(const F& f) : f(f) { }
|
||||
Slot0_fun(const Slot0_fun& s) : Slot0<R>(s), f(s.f) { }
|
||||
~Slot0_fun() { }
|
||||
R operator()() { return f(); }
|
||||
};
|
||||
|
||||
template<typename F>
|
||||
class Slot0_fun<void, F> : public Slot0<void> {
|
||||
F f;
|
||||
public:
|
||||
Slot0_fun(const F& f) : f(f) { }
|
||||
Slot0_fun(const Slot0_fun& s) : Slot0<void>(s), f(s.f) { }
|
||||
~Slot0_fun() { }
|
||||
void operator()() { f(); }
|
||||
};
|
||||
|
||||
// Slot0_mem - pointer to a member function of the T class
|
||||
template<typename R, class T>
|
||||
class Slot0_mem : public Slot0<R> {
|
||||
R (T::*m)();
|
||||
T* t;
|
||||
public:
|
||||
Slot0_mem(R (T::*m)(), T* t) : m(m), t(t) { }
|
||||
Slot0_mem(const Slot0_mem& s) : Slot0<R>(s), m(s.m), t(s.t) { }
|
||||
~Slot0_mem() { }
|
||||
R operator()() { return (t->*m)(); }
|
||||
};
|
||||
|
||||
template<class T>
|
||||
class Slot0_mem<void, T> : public Slot0<void> {
|
||||
void (T::*m)();
|
||||
T* t;
|
||||
public:
|
||||
Slot0_mem(void (T::*m)(), T* t) : m(m), t(t) { }
|
||||
Slot0_mem(const Slot0_mem& s) : Slot0<void>(s), m(s.m), t(s.t) { }
|
||||
~Slot0_mem() { }
|
||||
void operator()() { (t->*m)(); }
|
||||
};
|
||||
|
||||
// Slot1 - Base class for delegates of one argument.
|
||||
template<typename R, typename A1>
|
||||
class Slot1 : public Slot {
|
||||
public:
|
||||
Slot1() { }
|
||||
Slot1(const Slot1& s) { (void)s; }
|
||||
virtual ~Slot1() { }
|
||||
virtual R operator()(A1 a1) = 0;
|
||||
};
|
||||
|
||||
// Slot1_fun - hold a F instance and use the function call operator
|
||||
template<typename R, typename F, typename A1>
|
||||
class Slot1_fun : public Slot1<R, A1> {
|
||||
F f;
|
||||
public:
|
||||
Slot1_fun(const F& f) : f(f) { }
|
||||
Slot1_fun(const Slot1_fun& s) : Slot1<R, A1>(s), f(s.f) { }
|
||||
~Slot1_fun() { }
|
||||
R operator()(A1 a1) { return f(a1); }
|
||||
};
|
||||
|
||||
template<typename F, typename A1>
|
||||
class Slot1_fun<void, F, A1> : public Slot1<void, A1> {
|
||||
F f;
|
||||
public:
|
||||
Slot1_fun(const F& f) : f(f) { }
|
||||
Slot1_fun(const Slot1_fun& s) : Slot1<void, A1>(s), f(s.f) { }
|
||||
~Slot1_fun() { }
|
||||
void operator()(A1 a1) { f(a1); }
|
||||
};
|
||||
|
||||
// Slot1_mem - pointer to a member function of the T class
|
||||
template<typename R, class T, typename A1>
|
||||
class Slot1_mem : public Slot1<R, A1> {
|
||||
R (T::*m)(A1);
|
||||
T* t;
|
||||
public:
|
||||
Slot1_mem(R (T::*m)(A1), T* t) : m(m), t(t) { }
|
||||
Slot1_mem(const Slot1_mem& s) : Slot1<R, A1>(s), m(s.m), t(s.t) { }
|
||||
~Slot1_mem() { }
|
||||
R operator()(A1 a1) { return (t->*m)(a1); }
|
||||
};
|
||||
|
||||
template<class T, typename A1>
|
||||
class Slot1_mem<void, T, A1> : public Slot1<void, A1> {
|
||||
void (T::*m)(A1);
|
||||
T* t;
|
||||
public:
|
||||
Slot1_mem(void (T::*m)(A1), T* t) : m(m), t(t) { }
|
||||
Slot1_mem(const Slot1_mem& s) : Slot1<void, A1>(s), m(s.m), t(s.t) { }
|
||||
~Slot1_mem() { }
|
||||
void operator()(A1 a1) { (t->*m)(a1); }
|
||||
};
|
||||
|
||||
// Slot2 - Base class for delegates of two arguments.
|
||||
template<typename R, typename A1, typename A2>
|
||||
class Slot2 : public Slot {
|
||||
public:
|
||||
Slot2() { }
|
||||
Slot2(const Slot2& s) { (void)s; }
|
||||
virtual ~Slot2() { }
|
||||
virtual R operator()(A1 a1, A2 a2) = 0;
|
||||
};
|
||||
|
||||
// Slot2_fun - hold a F instance and use the function call operator
|
||||
template<typename R, typename F, typename A1, typename A2>
|
||||
class Slot2_fun : public Slot2<R, A1, A2> {
|
||||
F f;
|
||||
public:
|
||||
Slot2_fun(const F& f) : f(f) { }
|
||||
Slot2_fun(const Slot2_fun& s) : Slot2<R, A1, A2>(s), f(s.f) { }
|
||||
~Slot2_fun() { }
|
||||
R operator()(A1 a1, A2 a2) { return f(a1, a2); }
|
||||
};
|
||||
|
||||
template<typename F, typename A1, typename A2>
|
||||
class Slot2_fun<void, F, A1, A2> : public Slot2<void, A1, A2> {
|
||||
F f;
|
||||
public:
|
||||
Slot2_fun(const F& f) : f(f) { }
|
||||
Slot2_fun(const Slot2_fun& s) : Slot2<void, A1, A2>(s), f(s.f) { }
|
||||
~Slot2_fun() { }
|
||||
void operator()(A1 a1, A2 a2) { f(a1, a2); }
|
||||
};
|
||||
|
||||
// Slot2_mem - pointer to a member function of the T class
|
||||
template<typename R, class T, typename A1, typename A2>
|
||||
class Slot2_mem : public Slot2<R, A1, A2> {
|
||||
R (T::*m)(A1, A2);
|
||||
T* t;
|
||||
public:
|
||||
Slot2_mem(R (T::*m)(A1, A2), T* t) : m(m), t(t) { }
|
||||
Slot2_mem(const Slot2_mem& s) : Slot2<R, A1, A2>(s), m(s.m), t(s.t) { }
|
||||
~Slot2_mem() { }
|
||||
R operator()(A1 a1, A2 a2) { return (t->*m)(a1, a2); }
|
||||
};
|
||||
|
||||
template<class T, typename A1, typename A2>
|
||||
class Slot2_mem<void, T, A1, A2> : public Slot2<void, A1, A2> {
|
||||
void (T::*m)(A1, A2);
|
||||
T* t;
|
||||
public:
|
||||
Slot2_mem(void (T::*m)(A1, A2), T* t) : m(m), t(t) { }
|
||||
Slot2_mem(const Slot2_mem& s) : Slot2<void, A1, A2>(s), m(s.m), t(s.t) { }
|
||||
~Slot2_mem() { }
|
||||
void operator()(A1 a1, A2 a2) { return (t->*m)(a1, a2); }
|
||||
};
|
||||
|
||||
} // namespace base
|
||||
|
||||
#endif
|
1
src/observable
Submodule
1
src/observable
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit 873aaa15d9bcd98fcee3a35a9d35b826d6805ab4
|
Loading…
x
Reference in New Issue
Block a user