Compiling, but untested, option change notifications. Doesn't seem to affect Aegisub aversely.

Has the limitation that one object can only subscribe once to one option value, but that shouldn't actually be a problem. (One object cannot have two different of its member functions subscribing to one option value.)

Originally committed to SVN as r4415.
This commit is contained in:
Niels Martin Hansen 2010-06-03 05:07:47 +00:00
parent 90893f1048
commit 5e8d5b221b
4 changed files with 57 additions and 13 deletions

View file

@ -205,6 +205,10 @@
RelativePath="..\..\libaegisub\common\option.cpp" RelativePath="..\..\libaegisub\common\option.cpp"
> >
</File> </File>
<File
RelativePath="..\..\libaegisub\common\option_value.cpp"
>
</File>
<File <File
RelativePath="..\..\libaegisub\common\option_visit.cpp" RelativePath="..\..\libaegisub\common\option_visit.cpp"
> >

View file

@ -24,6 +24,7 @@ libaegisub_2_2_la_SOURCES = \
common/charset_ucd.cpp \ common/charset_ucd.cpp \
common/mru.cpp \ common/mru.cpp \
common/option.cpp \ common/option.cpp \
common/option_value.cpp \
common/option_visit.cpp \ common/option_visit.cpp \
common/log.cpp \ common/log.cpp \
common/validator.cpp \ common/validator.cpp \

View file

@ -0,0 +1,41 @@
// Copyright (c) 2010, Niels M Hansen <nielsm@aegisub.org>
//
// Permission to use, copy, modify, and distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
//
// $Id$
/// @file option_value.cpp
/// @brief Container for holding an actual option value.
/// @ingroup libaegisub
#include "libaegisub/option_value.h"
namespace agi {
void OptionValue::NotifyChanged() {
for (ChangeListenerSet::const_iterator nfcb = listeners.begin(); nfcb != listeners.end(); ++nfcb) {
nfcb->first->*(nfcb->second);
}
}
void OptionValue::Subscribe(OptionValueListener *listener, OptionValueListener::ChangeEvent function) {
assert(listeners.find(listener) == listeners.end());
listeners[listener] = function;
}
void OptionValue::Unsubscribe(OptionValueListener *listener, OptionValueListener::ChangeEvent function) {
assert(listeners.find(listener) != listeners.end() && listeners[listener] == function);
listeners.erase(listener);
}
};

View file

@ -20,6 +20,7 @@
#ifndef LAGI_PRE #ifndef LAGI_PRE
#include <fstream> #include <fstream>
#include <map>
#include <stdint.h> #include <stdint.h>
#include "libaegisub/cajun/reader.h" #include "libaegisub/cajun/reader.h"
@ -48,16 +49,16 @@ class ConfigVisitor;
/// signature. /// signature.
class OptionValueListener { class OptionValueListener {
public: public:
// (I might have messed up the syntax here. It's supposed to be a pointer /// @brief Type of a notification callback function for option value changes
// to a member function of an OptionValueListener-derived class.) typedef void (OptionValueListener::*ChangeEvent)(const OptionValue &option);
typedef void (OptionValueListener::*ChangeEvent)(const OptionValue *option);
}; };
/// @class OptionValue /// @class OptionValue
/// Holds an actual option. /// Holds an actual option.
class OptionValue { class OptionValue {
std::set<OptionValueListener*> listeners; typedef std::map<OptionValueListener*, OptionValueListener::ChangeEvent> ChangeListenerSet;
ChangeListenerSet listeners;
protected: protected:
void NotifyChanged(); void NotifyChanged();
@ -125,11 +126,8 @@ public:
virtual void GetDefaultListBool(std::vector<bool> &out) const { throw OptionValueErrorInvalidListType("Attempt to retrive string bool from non-bool list"); } virtual void GetDefaultListBool(std::vector<bool> &out) const { throw OptionValueErrorInvalidListType("Attempt to retrive string bool from non-bool list"); }
void Subscribe(OptionValueListener*); void Subscribe(OptionValueListener *listener, OptionValueListener::ChangeEvent function);
void Unsubscribe(OptionValueListener*); void Unsubscribe(OptionValueListener *listener, OptionValueListener::ChangeEvent function);
void Subscribe(OptionValueListener *listener, OptionValueListener::ChangeEvent handler);
void Unsubscribe(OptionValueListener *listener, OptionValueListener::ChangeEvent handler);
}; };
@ -142,11 +140,11 @@ public:
OptionValue##type_name(std::string member_name, type member_value): \ OptionValue##type_name(std::string member_name, type member_value): \
value(member_value), name(member_name) {} \ value(member_value), name(member_name) {} \
type Get##type_name() const { return value; } \ type Get##type_name() const { return value; } \
void Set##type_name(const type new_val) { value = new_val; } \ void Set##type_name(const type new_val) { value = new_val; NotifyChanged(); } \
type GetDefault##type_name() const { return value_default; } \ type GetDefault##type_name() const { return value_default; } \
OptionType GetType() const { return OptionValue::Type_##type_name; } \ OptionType GetType() const { return OptionValue::Type_##type_name; } \
std::string GetName() const { return name; } \ std::string GetName() const { return name; } \
void Reset() { value = value_default; } \ void Reset() { value = value_default; NotifyChanged(); } \
bool IsDefault() const { return (value == value_default) ? 1 : 0; } \ bool IsDefault() const { return (value == value_default) ? 1 : 0; } \
}; };
@ -181,11 +179,11 @@ protected:
virtual std::string GetString() const { return "";} \ virtual std::string GetString() const { return "";} \
OptionValueList##type_name(std::string member_name): name(member_name) {} \ OptionValueList##type_name(std::string member_name): name(member_name) {} \
void GetList##type_name(std::vector<type> &out) const { out = array; } \ void GetList##type_name(std::vector<type> &out) const { out = array; } \
void SetList##type_name(const std::vector<type> val) { array = val;} \ void SetList##type_name(const std::vector<type> val) { array = val; NotifyChanged(); } \
void GetDefaultList##type_name(std::vector<type> &out) const { out = array_default; } \ void GetDefaultList##type_name(std::vector<type> &out) const { out = array_default; } \
OptionType GetType() const { return OptionValue::Type_List_##type_name; } \ OptionType GetType() const { return OptionValue::Type_List_##type_name; } \
std::string GetName() const { return name; } \ std::string GetName() const { return name; } \
void Reset() { array = array_default; } \ void Reset() { array = array_default; NotifyChanged(); } \
bool IsDefault() const { return (array == array_default) ? 1 : 0; } \ bool IsDefault() const { return (array == array_default) ? 1 : 0; } \
}; };