1// Aseprite
2// Copyright (C) 2019 Igara Studio S.A.
3// Copyright (C) 2017-2018 David Capello
4//
5// This program is distributed under the terms of
6// the End-User License Agreement for Aseprite.
7
8#ifdef HAVE_CONFIG_H
9#include "config.h"
10#endif
11
12#include "app/app.h"
13#include "app/doc.h"
14#include "app/pref/option.h"
15#include "app/pref/preferences.h"
16#include "app/script/docobj.h"
17#include "app/script/engine.h"
18#include "app/script/luacpp.h"
19#include "doc/sprite.h"
20
21#include <cstring>
22
23namespace app {
24namespace script {
25
26namespace {
27
28struct AppPreferences { };
29
30int Section_index(lua_State* L)
31{
32 Section* section = get_ptr<Section>(L, 1);
33
34 const char* id = lua_tostring(L, 2);
35 if (!id)
36 return luaL_error(L, "optionName in 'app.preferences.%s.optionName' must be a string",
37 section->name());
38
39 OptionBase* option = section->option(id);
40 if (!option) {
41 Section* subSection = section->section(
42 (section->name() && *section->name() ? std::string(section->name()) + "." + id:
43 std::string(id)).c_str());
44 if (subSection) {
45 push_ptr(L, subSection);
46 return 1;
47 }
48 return luaL_error(L, "option '%s' in section '%s' doesn't exist", id, section->name());
49 }
50
51 option->pushLua(L);
52 return 1;
53}
54
55int Section_newindex(lua_State* L)
56{
57 Section* section = get_ptr<Section>(L, 1);
58
59 const char* id = lua_tostring(L, 2);
60 if (!id)
61 return luaL_error(L, "optionName in 'app.preferences.%s.optionName' must be a string",
62 section->name());
63
64 OptionBase* option = section->option(id);
65 if (!option)
66 return luaL_error(L, "option '%s' in section '%s' doesn't exist",
67 id, section->name());
68
69 option->fromLua(L, 3);
70 return 0;
71}
72
73int ToolPref_function(lua_State* L)
74{
75 auto tool = get_tool_from_arg(L, 1);
76 if (!tool)
77 return luaL_error(L, "tool preferences not found");
78
79 // If we don't have the UI available, we reset the tools
80 // preferences, so scripts that are executed in batch mode have a
81 // reproducible behavior.
82 if (!App::instance()->isGui())
83 Preferences::instance().resetToolPreferences(tool);
84
85 ToolPreferences& toolPref = Preferences::instance().tool(tool);
86 push_ptr(L, (Section*)&toolPref);
87 return 1;
88}
89
90int DocPref_function(lua_State* L)
91{
92 auto sprite = may_get_docobj<Sprite>(L, 1);
93 DocumentPreferences& docPref =
94 Preferences::instance().document(
95 sprite ? static_cast<const Doc*>(sprite->document()): nullptr);
96 push_ptr(L, (Section*)&docPref);
97 return 1;
98}
99
100int AppPreferences_index(lua_State* L)
101{
102 const char* id = lua_tostring(L, 2);
103 if (!id)
104 return luaL_error(L, "id in 'app.preferences.id' must be a string");
105
106 if (std::strcmp(id, "tool") == 0) {
107 lua_pushcfunction(L, ToolPref_function);
108 return 1;
109 }
110 else if (std::strcmp(id, "document") == 0) {
111 lua_pushcfunction(L, DocPref_function);
112 return 1;
113 }
114
115 Section* section = Preferences::instance().section(id);
116 if (!section)
117 return luaL_error(L, "section '%s' in preferences doesn't exist", id);
118
119 push_ptr(L, section);
120 return 1;
121}
122
123const luaL_Reg Section_methods[] = {
124 { "__index", Section_index },
125 { "__newindex", Section_newindex },
126 { nullptr, nullptr }
127};
128
129const luaL_Reg AppPreferences_methods[] = {
130 { "__index", AppPreferences_index },
131 { nullptr, nullptr }
132};
133
134} // anonymous namespace
135
136DEF_MTNAME(Section);
137DEF_MTNAME(AppPreferences);
138
139void register_app_preferences_object(lua_State* L)
140{
141 REG_CLASS(L, Section);
142 REG_CLASS(L, AppPreferences);
143
144 lua_getglobal(L, "app");
145 lua_pushstring(L, "preferences");
146 push_new<AppPreferences>(L);
147 lua_rawset(L, -3);
148 lua_pop(L, 1);
149}
150
151} // namespace script
152} // namespace app
153