1 // Aseprite
2 // Copyright (C) 2017-2018  David Capello
3 //
4 // This program is distributed under the terms of
5 // the End-User License Agreement for Aseprite.
6 
7 #ifndef APP_EXTENSIONS_H_INCLUDED
8 #define APP_EXTENSIONS_H_INCLUDED
9 #pragma once
10 
11 #include "base/unique_ptr.h"
12 #include "obs/signal.h"
13 
14 #include <map>
15 #include <string>
16 #include <vector>
17 
18 namespace render {
19   class DitheringMatrix;
20 }
21 
22 namespace app {
23 
24   // Key=theme/palette/etc. id
25   // Value=theme/palette/etc. path
26   typedef std::map<std::string, std::string> ExtensionItems;
27 
28   class Extensions;
29 
30   struct ExtensionInfo {
31     std::string name;
32     std::string version;
33     std::string dstPath;
34     std::string commonPath;
35   };
36 
37   class Extension {
38     friend class Extensions;
39   public:
40     class DitheringMatrixInfo {
41     public:
DitheringMatrixInfo()42       DitheringMatrixInfo() : m_matrix(nullptr) { }
DitheringMatrixInfo(const std::string & path,const std::string & name)43       DitheringMatrixInfo(const std::string& path,
44                           const std::string& name)
45         : m_path(path), m_name(name), m_matrix(nullptr) { }
46 
name()47       const std::string& name() const { return m_name; }
48       const render::DitheringMatrix& matrix() const;
49       void destroyMatrix();
50 
51     private:
52       std::string m_path;
53       std::string m_name;
54       mutable render::DitheringMatrix* m_matrix;
55     };
56 
57     Extension(const std::string& path,
58               const std::string& name,
59               const std::string& version,
60               const std::string& displayName,
61               const bool isEnabled,
62               const bool isBuiltinExtension);
63     ~Extension();
64 
path()65     const std::string& path() const { return m_path; }
name()66     const std::string& name() const { return m_name; }
version()67     const std::string& version() const { return m_version; }
displayName()68     const std::string& displayName() const { return m_displayName; }
69 
languages()70     const ExtensionItems& languages() const { return m_languages; }
themes()71     const ExtensionItems& themes() const { return m_themes; }
palettes()72     const ExtensionItems& palettes() const { return m_palettes; }
73 
74     void addLanguage(const std::string& id, const std::string& path);
75     void addTheme(const std::string& id, const std::string& path);
76     void addPalette(const std::string& id, const std::string& path);
77     void addDitheringMatrix(const std::string& id,
78                             const std::string& path,
79                             const std::string& name);
80 
isEnabled()81     bool isEnabled() const { return m_isEnabled; }
isInstalled()82     bool isInstalled() const { return m_isInstalled; }
83     bool canBeDisabled() const;
84     bool canBeUninstalled() const;
85 
hasLanguages()86     bool hasLanguages() const { return !m_languages.empty(); }
hasThemes()87     bool hasThemes() const { return !m_themes.empty(); }
hasPalettes()88     bool hasPalettes() const { return !m_palettes.empty(); }
hasDitheringMatrices()89     bool hasDitheringMatrices() const { return !m_ditheringMatrices.empty(); }
90 
91   private:
92     void enable(const bool state);
93     void uninstall();
94     void uninstallFiles(const std::string& path);
95     bool isCurrentTheme() const;
96     bool isDefaultTheme() const;
97 
98     ExtensionItems m_languages;
99     ExtensionItems m_themes;
100     ExtensionItems m_palettes;
101     std::map<std::string, DitheringMatrixInfo> m_ditheringMatrices;
102     std::string m_path;
103     std::string m_name;
104     std::string m_version;
105     std::string m_displayName;
106     bool m_isEnabled;
107     bool m_isInstalled;
108     bool m_isBuiltinExtension;
109   };
110 
111   class Extensions {
112   public:
113     typedef std::vector<Extension*> List;
114     typedef List::iterator iterator;
115 
116     Extensions();
117     ~Extensions();
118 
begin()119     iterator begin() { return m_extensions.begin(); }
end()120     iterator end() { return m_extensions.end(); }
121 
122     void enableExtension(Extension* extension, const bool state);
123     void uninstallExtension(Extension* extension);
124     ExtensionInfo getCompressedExtensionInfo(const std::string& zipFn);
125     Extension* installCompressedExtension(const std::string& zipFn,
126                                           const ExtensionInfo& info);
127 
128     std::string languagePath(const std::string& langId);
129     std::string themePath(const std::string& themeId);
130     std::string palettePath(const std::string& palId);
131     ExtensionItems palettes() const;
132     const render::DitheringMatrix* ditheringMatrix(const std::string& matrixId);
133     std::vector<Extension::DitheringMatrixInfo> ditheringMatrices();
134 
135     obs::signal<void(Extension*)> NewExtension;
136     obs::signal<void(Extension*)> LanguagesChange;
137     obs::signal<void(Extension*)> ThemesChange;
138     obs::signal<void(Extension*)> PalettesChange;
139     obs::signal<void(Extension*)> DitheringMatricesChange;
140 
141   private:
142     Extension* loadExtension(const std::string& path,
143                              const std::string& fullPackageFilename,
144                              const bool isBuiltinExtension);
145     void generateExtensionSignals(Extension* extension);
146 
147     List m_extensions;
148     std::string m_userExtensionsPath;
149   };
150 
151 } // namespace app
152 
153 #endif
154