1 | // Aseprite |
2 | // Copyright (C) 2019 Igara Studio S.A. |
3 | // Copyright (C) 2001-2018 David Capello |
4 | // |
5 | // This program is distributed under the terms of |
6 | // the End-User License Agreement for Aseprite. |
7 | |
8 | #ifndef APP_PREF_OPTION_H_INCLUDED |
9 | #define APP_PREF_OPTION_H_INCLUDED |
10 | #pragma once |
11 | |
12 | #include "obs/signal.h" |
13 | #include <string> |
14 | |
15 | #ifdef ENABLE_SCRIPTING |
16 | #include "app/script/values.h" |
17 | #endif |
18 | |
19 | namespace app { |
20 | |
21 | class OptionBase; |
22 | |
23 | class Section { |
24 | public: |
25 | Section(const std::string& name) : m_name(name) { } |
26 | virtual ~Section() { } |
27 | const char* name() const { return m_name.c_str(); } |
28 | |
29 | virtual Section* section(const char* id) = 0; |
30 | virtual OptionBase* option(const char* id) = 0; |
31 | |
32 | obs::signal<void()> BeforeChange; |
33 | obs::signal<void()> AfterChange; |
34 | |
35 | private: |
36 | std::string m_name; |
37 | }; |
38 | |
39 | class OptionBase { |
40 | public: |
41 | OptionBase(Section* section, const char* id) |
42 | : m_section(section) |
43 | , m_id(id) { |
44 | } |
45 | virtual ~OptionBase() { } |
46 | const char* section() const { return m_section->name(); } |
47 | const char* id() const { return m_id; } |
48 | |
49 | #ifdef ENABLE_SCRIPTING |
50 | virtual void pushLua(lua_State* L) = 0; |
51 | virtual void fromLua(lua_State* L, int index) = 0; |
52 | #endif |
53 | |
54 | protected: |
55 | Section* m_section; |
56 | const char* m_id; |
57 | }; |
58 | |
59 | template<typename T> |
60 | class Option : public OptionBase { |
61 | public: |
62 | Option(Section* section, const char* id, const T& defaultValue = T()) |
63 | : OptionBase(section, id) |
64 | , m_default(defaultValue) |
65 | , m_value(defaultValue) |
66 | , m_dirty(false) { |
67 | } |
68 | |
69 | const T& operator()() const { |
70 | return m_value; |
71 | } |
72 | |
73 | const T& operator()(const T& newValue) { |
74 | setValue(newValue); |
75 | return m_value; |
76 | } |
77 | |
78 | // operator=() changes the value and the default value of the |
79 | // option. E.g. it's used when we copy two complete Sections, |
80 | // from default settings to user settings, or viceversa (the |
81 | // default value is always involved). |
82 | Option& operator=(const Option& opt) { |
83 | setValueAndDefault(opt.m_value); |
84 | return *this; |
85 | } |
86 | |
87 | // Changes the default value and the current one. |
88 | void setValueAndDefault(const T& value) { |
89 | bool wasDirty = isDirty(); |
90 | |
91 | setDefaultValue(value); |
92 | setValue(value); |
93 | |
94 | if (!wasDirty) |
95 | cleanDirtyFlag(); |
96 | } |
97 | |
98 | const T& defaultValue() const { return m_default; } |
99 | void setDefaultValue(const T& defValue) { |
100 | m_default = defValue; |
101 | } |
102 | |
103 | bool isDirty() const { return m_dirty; } |
104 | void forceDirtyFlag() { m_dirty = true; } |
105 | void cleanDirtyFlag() { m_dirty = false; } |
106 | |
107 | void setValue(const T& newValue) { |
108 | if (m_value == newValue) { |
109 | m_dirty = true; |
110 | return; |
111 | } |
112 | |
113 | BeforeChange(newValue); |
114 | if (m_section) |
115 | m_section->BeforeChange(); |
116 | |
117 | m_value = newValue; |
118 | m_dirty = true; |
119 | |
120 | AfterChange(newValue); |
121 | if (m_section) |
122 | m_section->AfterChange(); |
123 | } |
124 | |
125 | void clearValue() { |
126 | m_value = m_default; |
127 | m_dirty = false; |
128 | } |
129 | |
130 | #ifdef ENABLE_SCRIPTING |
131 | void pushLua(lua_State* L) override { |
132 | script::push_value_to_lua<T>(L, m_value); |
133 | } |
134 | void fromLua(lua_State* L, int index) override { |
135 | setValue(script::get_value_from_lua<T>(L, index)); |
136 | } |
137 | #endif |
138 | |
139 | obs::signal<void(const T&)> BeforeChange; |
140 | obs::signal<void(const T&)> AfterChange; |
141 | |
142 | private: |
143 | T m_default; |
144 | T m_value; |
145 | bool m_dirty; |
146 | |
147 | Option(); |
148 | Option(const Option& opt); |
149 | }; |
150 | |
151 | } // namespace app |
152 | |
153 | #endif |
154 | |