1 /// Intermediate module for binding rendering libraries to Isodi.
2 ///
3 /// All functions in this module should be implemented by the bindings.
4 module isodi.bind;
5 
6 import isodi.anchor;
7 import isodi.position;
8 
9 public {
10     import isodi.cell;
11     import isodi.model;
12     import isodi.anchor;
13     import isodi.display;
14     import isodi.pack_list;
15 }
16 
17 /// Defines type of a log message
18 enum LogType {
19 
20     info,     /// General information, usually white.
21     success,  /// An operation (eg. test) has succeeded, usually green.
22     error,    /// An operation (eg. test) has failed, usually red.
23 
24 }
25 
26 
27 @safe:
28 
29 
30 /// Put text in color using ANSI codes on POSIX platforms.
31 ///
32 /// On other platforms, this just returns the original string.
33 string colorText(string text, LogType type) {
34 
35     version (Posix) {
36 
37         import std.format : format;
38 
39         string fString() {
40 
41             // Posix platforms
42             with (LogType)
43             final switch (type) {
44 
45                 case info: return "%s";
46                 case success: return "\033[32m%s\033[0m";
47                 case error: return "\033[91m%s\033[0m";
48 
49             }
50 
51         }
52 
53         return fString.format(text);
54 
55     }
56 
57     else return text;
58 
59 }
60 
61 /// Interface of Isodi renderer bindings. Implement the functions to match behavior of your renderer.
62 interface Bindings {
63 
64     /// An instance of a binding object.
65     static Bindings inst;
66 
67     /// Output the given text to log.
68     ///
69     /// This is renderer dependent, because some renderers supply their own logging functionality, for example,
70     /// $(LINK2 https://godotengine.org, Godot Engine).
71     ///
72     /// Params:
73     ///     text = Text to output.
74     ///     type = Type of the log message.
75     void log(string text, LogType type = LogType.info);
76 
77     /// Create an instance of the `Display` in order to fit the needs of the renderer.
78     Display createDisplay();
79 
80     /// Create a pack list to manage packs.
81     PackList createPackList();
82 
83     /// Create a cell.
84     Cell createCell(Display display, const Position position, const string type);
85 
86     /// Create an anchor
87     Anchor createAnchor(Display);
88 
89     /// Create a model
90     Model createModel(Display, const string type);
91 
92     /// Register a binding object
93     mixin template Register(T) {
94 
95         static this() {
96 
97             import isodi.bind : Bindings;
98             Bindings.inst = new T;
99 
100         }
101 
102     }
103 
104     /// Register a constructor.
105     mixin template Constructor(BaseType, Extension) {
106 
107         import std.traits : Parameters;
108 
109         private enum Name = "create" ~ __traits(identifier, BaseType);
110         private alias ParamTypes = Parameters!(__traits(getMember, Bindings, Name));
111 
112         mixin("BaseType " ~ Name ~ q{ (ParamTypes args) {
113 
114             return new Extension(args);
115 
116         }});
117 
118     }
119 
120 }
121 
122 /// Helper for calling renderer bindings.
123 alias Renderer = Bindings.inst;