1 module fluid.default_theme;
2 
3 import fluid.node;
4 import fluid.frame;
5 import fluid.style;
6 import fluid.label;
7 import fluid.button;
8 import fluid.slider;
9 import fluid.backend;
10 import fluid.structs;
11 import fluid.checkbox;
12 import fluid.radiobox;
13 import fluid.typeface;
14 import fluid.drag_slot;
15 import fluid.separator;
16 import fluid.file_input;
17 import fluid.text_input;
18 import fluid.popup_frame;
19 import fluid.number_input;
20 import fluid.scroll_input;
21 
22 /// Theme with no properties set.
23 ///
24 /// Unlike `Theme.init` or `null`, which will be replaced by fluidDefaultTheme or the parent's theme, this can be used as
25 /// a valid theme for any node. This makes it useful for automatic tests, since it has guaranteed no margins, padding,
26 /// or other properties that may confuse the tester.
27 Theme nullTheme;
28 
29 /// Default theme that Fluid will use if no theme is supplied. It is a very simple theme that does the minimum to make
30 /// the role of each node understandable.
31 Theme fluidDefaultTheme;
32 
33 @NodeTag
34 enum FluidTag {
35     warning,
36 }
37 
38 Rule warningRule;
39 
40 static this() {
41 
42     const warningColor = color("#ffe186");
43     const warningAccentColor = color("#ffc30f");
44 
45     Image loadBWImage(string filename)(int width, int height) @trusted {
46 
47         import std.array;
48         import std.format;
49         import std.algorithm;
50 
51         const area = width * height;
52 
53         auto file = cast(ubyte[]) import(filename);
54         auto data = file.map!(a => Color(0, 0, 0, a)).array;
55 
56         assert(data.length == area, format!"Wrong %s area %s, expected %s"(filename, data.length, area));
57 
58         // TODO use Format.alpha
59         return Image(data, width, height);
60 
61     }
62 
63     with (Rule) {
64 
65         warningRule = rule(
66             Rule.padding.sideX = 16,
67             Rule.padding.sideY = 6,
68             Rule.border = 1,
69             Rule.borderStyle = colorBorder(warningAccentColor),
70             Rule.backgroundColor = warningColor,
71             Rule.textColor = color("#000"),
72         );
73 
74         nullTheme.add(
75             rule!Node(),
76         );
77 
78         fluidDefaultTheme.add(
79             rule!Node(
80                 typeface = Typeface.defaultTypeface,
81                 textColor = color("#000"),
82                 selectionBackgroundColor = color("#55b9ff"),
83             ),
84             rule!Frame(
85                 backgroundColor = color("#fff"),
86             ),
87             rule!Button(
88                 backgroundColor = color("#dadada"),
89                 mouseCursor = FluidMouseCursor.pointer,
90                 margin.sideY = 2,
91                 padding.sideX = 6,
92 
93                 when!"a.isHovered"(backgroundColor = color("#aaa")),
94                 when!"a.isFocused"(backgroundColor = color("#bbb")),  // TODO use an outline for focus
95                 when!"a.isPressed"(backgroundColor = color("#888")),
96                 when!"a.isDisabled"(
97                     textColor = color("000a"),
98                     backgroundColor = color("eee5"),
99                     // TODO disabled should apply opacity, and should work for every node
100                 ),
101             ),
102             rule!FrameButton(
103                 mouseCursor = FluidMouseCursor.pointer,
104             ),
105             rule!TextInput(
106                 backgroundColor = color("#fff"),
107                 borderStyle = colorBorder(color("#aaa")),
108                 mouseCursor = FluidMouseCursor.text,
109 
110                 margin.sideY = 2,
111                 padding.sideX = 6,
112                 border.sideBottom = 2,
113 
114                 when!"a.isEmpty"(textColor = color("#000a")),
115                 when!"a.isFocused"(borderStyle = colorBorder(color("#555")))
116                     .otherwise(selectionBackgroundColor = color("#ccc")),
117                 when!"a.isDisabled"(
118                     textColor = color("#000a"),
119                     backgroundColor = color("#fff5"),
120                 ),
121             ),
122             rule!NumberInputSpinner(
123                 mouseCursor = FluidMouseCursor.pointer,
124                 extra = new NumberInputSpinner.Extra(loadBWImage!"arrows-alpha"(40, 64)),
125             ),
126             rule!AbstractSlider(
127                 backgroundColor = color("#ddd"),
128                 lineColor = color("#ddd"),
129             ),
130             rule!SliderHandle(
131                 backgroundColor = color("#aaa"),
132             ),
133             rule!ScrollInput(
134                 backgroundColor = color("#eee"),
135             ),
136             rule!ScrollInputHandle(
137                 backgroundColor = color("#aaa"),
138 
139                 when!"a.isHovered"(backgroundColor = color("#888")),
140                 when!"a.isFocused"(backgroundColor = color("#777")),
141                 when!"a.isPressed"(backgroundColor = color("#555")),
142                 when!"a.isDisabled"(backgroundColor = color("#aaa5")),
143             ),
144             rule!PopupFrame(
145                 border = 1,
146                 borderStyle = colorBorder(color("#555a")),
147                 children!Button(
148                     backgroundColor = color("#0000"),
149                     margin = 0,
150                     when!"a.isHovered"(backgroundColor = color("#dadada")),
151                     when!"a.isFocused"(backgroundColor = color("#ccc")),
152                     when!"a.isPressed"(backgroundColor = color("#aaa")),
153                     when!"a.isDisabled"(
154                         textColor = color("000a"),
155                         backgroundColor = color("eee5"),
156                     ),
157                 ),
158             ),
159             /*rule!FileInputSuggestion(
160                 margin = 0,
161                 backgroundColor = color("#fff"),
162                 when!"a.isSelected"(backgroundColor = color("#55b9ff"))
163             ),*/
164             rule!Checkbox(
165                 margin.sideX = 8,
166                 margin.sideY = 4,
167                 border = 1,
168                 padding = 1,
169                 borderStyle = colorBorder(color("#555")),
170                 mouseCursor = FluidMouseCursor.pointer,
171 
172                 when!"a.isFocused"(backgroundColor = color("#ddd")),
173                 when!"a.isChecked"(
174                     extra = new Checkbox.Extra(loadBWImage!"checkmark-alpha"(64, 50)),
175                 ),
176             ),
177             rule!Radiobox(
178                 margin.sideX = 8,
179                 margin.sideY = 4,
180                 border = 0,
181                 borderStyle = null,
182                 padding = 2,
183                 extra = new Radiobox.Extra(1, color("#555"), color("#5552")),
184 
185                 when!"a.isFocused"(backgroundColor = color("#ddd")),
186                 when!"a.isChecked"(
187                     extra = new Radiobox.Extra(1, color("#555"), color("#000"))
188                 ),
189             ),
190             rule!Separator(
191                 padding = 4,
192                 lineColor = color("#ccc"),
193             ),
194             rule!DragSlot(
195                 padding.sideX = 6,
196                 padding.sideY = 0,
197                 border = 1,
198                 borderStyle = colorBorder(color("#555a")),
199                 backgroundColor = color("#fff"),
200                 margin = 4,  // for testing
201             ),
202             rule!DragHandle(
203                 lineColor = color("#ccc"),
204                 padding.sideX = 8,
205                 padding.sideY = 6,
206                 extra = new DragHandle.Extra(5),
207             ),
208 
209             // Warning
210             rule!(Frame, FluidTag.warning)(
211                 warningRule,
212                 children(
213                     textColor = color("#000"),
214                 ),
215                 children!Button(
216                     border = 1,
217                     borderStyle = colorBorder(warningAccentColor),
218                     backgroundColor = color("#fff"),
219                 ),
220             ),
221             rule!(Label, FluidTag.warning)(
222                 warningRule,
223             ),
224         );
225 
226     }
227 
228 }