1 /* B.Jumblr
2  * Pattern-controlled audio stream / sample re-sequencer LV2 plugin
3  *
4  * Copyright (C) 2018, 2019 by Sven Jähnichen
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 3, or (at your option)
9  * any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19  */
20 
21 #ifndef BJUMBLRGUI_HPP_
22 #define BJUMBLRGUI_HPP_
23 
24 #include <lv2/lv2plug.in/ns/lv2core/lv2.h>
25 #include <lv2/lv2plug.in/ns/extensions/ui/ui.h>
26 #include <lv2/lv2plug.in/ns/ext/atom/atom.h>
27 #include <lv2/lv2plug.in/ns/ext/atom/forge.h>
28 #include <lv2/lv2plug.in/ns/ext/time/time.h>
29 #include <lv2/lv2plug.in/ns/ext/midi/midi.h>
30 #include <iostream>
31 #include <algorithm>
32 
33 #include "BWidgets/Widget.hpp"
34 #include "BWidgets/Window.hpp"
35 #include "BWidgets/Label.hpp"
36 #include "BWidgets/DrawingSurface.hpp"
37 #include "BWidgets/DialValue.hpp"
38 #include "BWidgets/PopupListBox.hpp"
39 #include "BWidgets/LeftButton.hpp"
40 #include "BWidgets/PlusButton.hpp"
41 #include "BWidgets/MinusButton.hpp"
42 #include "BWidgets/ImageIcon.hpp"
43 #include "BWidgets/TextToggleButton.hpp"
44 #include "screen.h"
45 
46 #ifdef LOCALEFILE
47 #include LOCALEFILE
48 #else
49 #include "Locale_EN.hpp"
50 #endif
51 
52 #include "drawbutton.hpp"
53 #include "HaloButton.hpp"
54 #include "HaloToggleButton.hpp"
55 #include "HomeButton.hpp"
56 #include "LoadButton.hpp"
57 #include "PadSurface.hpp"
58 #include "definitions.h"
59 #include "Ports.hpp"
60 #include "Urids.hpp"
61 #include "Pad.hpp"
62 #include "PadMessage.hpp"
63 #include "Journal.hpp"
64 #include "MonitorWidget.hpp"
65 #include "MarkerWidget.hpp"
66 #include "SymbolWidget.hpp"
67 #include "SampleChooser.hpp"
68 
69 #define BG_FILE "inc/surface.png"
70 #define HELP_URL "https://github.com/sjaehn/BJumblr/blob/master/README.md"
71 #define YT_URL "https://www.youtube.com/watch?v=DFSi7TMqvMw"
72 #define MAXUNDO 20
73 
74 #ifndef WWW_BROWSER_CMD
75 #define WWW_BROWSER_CMD "x-www-browser"
76 #endif
77 
78 #define RESIZE(widget, x, y, w, h, sz) {widget.moveTo ((x) * (sz), (y) * (sz)); widget.resize ((w) * (sz), (h) * (sz));}
79 
80 enum editIndex
81 {
82 	EDIT_CUT	= 0,
83 	EDIT_COPY	= 1,
84 	EDIT_XFLIP	= 2,
85 	EDIT_YFLIP	= 3,
86 	EDIT_PASTE	= 4,
87 	EDIT_RESET	= 5,
88 	EDIT_UNDO	= 6,
89 	EDIT_REDO	= 7,
90 	MAXEDIT		= 8
91 };
92 
93 const std::string editLabels[MAXEDIT] =
94 {
95 	BJUMBLR_LABEL_SELECT_CUT,
96 	BJUMBLR_LABEL_SELECT_COPY,
97 	BJUMBLR_LABEL_SELECT_XFLIP,
98 	BJUMBLR_LABEL_SELECT_YFLIP,
99 	BJUMBLR_LABEL_PASTE,
100 	BJUMBLR_LABEL_RESET,
101 	BJUMBLR_LABEL_UNDO,
102 	BJUMBLR_LABEL_REDO};
103 
104 class BJumblrGUI : public BWidgets::Window
105 {
106 public:
107 	BJumblrGUI (const char *bundle_path, const LV2_Feature *const *features, PuglNativeView parentWindow);
108 	~BJumblrGUI ();
109 	void port_event (uint32_t port_index, uint32_t buffer_size, uint32_t format, const void *buffer);
110 	void send_ui_on ();
111 	void send_ui_off ();
112 	void send_samplePath ();
113 	void send_sampleAmp();
114 	void send_editMode ();
115 	void send_maxPage ();
116 	void send_playbackPage ();
117 	void send_requestMidiLearn ();
118 	void send_pad (int page);
119 	void send_pad (int page, int row, int step);
120 	void send_flip ();
121 	virtual void onConfigureRequest (BEvents::ExposeEvent* event) override;
122 	virtual void onCloseRequest (BEvents::WidgetEvent* event) override;
123 	virtual void onKeyPressed (BEvents::KeyEvent* event) override;
124 	virtual void onKeyReleased (BEvents::KeyEvent* event) override;
125 	void applyTheme (BStyles::Theme& theme) override;
126 
127 	LV2UI_Controller controller;
128 	LV2UI_Write_Function write_function;
129 
130 private:
131 	static void valueChangedCallback(BEvents::Event* event);
132 	static void pageClickedCallback(BEvents::Event* event);
133 	static void pageSymbolClickedCallback(BEvents::Event* event);
134 	static void pagePlayClickedCallback(BEvents::Event* event);
135 	static void pageScrollClickedCallback(BEvents::Event* event);
136 	static void midiSymbolClickedCallback(BEvents::Event* event);
137 	static void midiButtonClickedCallback(BEvents::Event* event);
138 	static void midiStatusChangedCallback(BEvents::Event* event);
139 	static void levelChangedCallback(BEvents::Event* event);
140 	static void edit1ChangedCallback(BEvents::Event* event);
141 	static void edit2ChangedCallback(BEvents::Event* event);
142 	static void padsPressedCallback (BEvents::Event* event);
143 	static void padsScrolledCallback (BEvents::Event* event);
144 	static void padsFocusedCallback (BEvents::Event* event);
145 	static void loadButtonClickedCallback (BEvents::Event* event);
146 	static void syncButtonClickedCallback (BEvents::Event* event);
147 	static void delayButtonsClickedCallback (BEvents::Event* event);
148 	static void patternFlippedClickedCallback (BEvents::Event* event);
149 	static void helpButtonClickedCallback (BEvents::Event* event);
150 	static void ytButtonClickedCallback (BEvents::Event* event);
151 	virtual void resize () override;
152 	void pushPage ();
153 	void popPage ();
154 	void gotoPage (const int page);
155 	void insertPage (const int page);
156 	void deletePage (const int page);
157 	void swapPage (const int page1, const int page2);
158 	void updatePageContainer ();
159 	bool validatePad (int page);
160 	bool validatePad (int page, int row, int step, Pad& pad);
161 
162 	void setMarkers();
163 	void drawPad ();
164 	void drawPad (int row, int step);
165 	void drawPad (cairo_t* cr, int row, int step);
166 
167 	std::string pluginPath;
168 	double sz;
169 	cairo_surface_t* bgImageSurface;
170 
171 	BJumblrURIs uris;
172 	LV2_Atom_Forge forge;
173 
174 	// Controllers
175 	std::array<BWidgets::ValueWidget*, MAXCONTROLLERS> controllerWidgets;
176 	std::array<float, MAXCONTROLLERS> controllers;
177 	int editMode;
178 
179 	//Pads
180 	class Pattern
181 	{
182 	public:
183 		void clear ();
184 		Pad getPad (const size_t row, const size_t step) const;
185 		void setPad (const size_t row, const size_t step, const Pad& pad);
186 		std::vector<PadMessage> undo ();
187 		std::vector<PadMessage> redo ();
188 		void store ();
189 	private:
190 		Journal<std::vector<PadMessage>, MAXUNDO> journal;
191 		std::array<std::array<Pad, MAXSTEPS>, MAXSTEPS> pads;
192 		struct
193 		{
194 			std::vector<PadMessage> oldMessage;
195 			std::vector<PadMessage> newMessage;
196 		} changes;
197 	};
198 
199 	std::array<Pattern, MAXPAGES> pattern;
200 	bool patternFlipped;
201 
202 	struct ClipBoard
203 	{
204 		std::vector<std::vector<Pad>> data;
205 		std::pair<int, int> origin;
206 		std::pair<int, int> extends;
207 		bool ready = true;
208 		std::chrono::steady_clock::time_point time;
209 	};
210 
211 	ClipBoard clipBoard;
212 
213 	// Cursor
214 	float cursor;
215 	bool wheelScrolled;
216 	bool padPressed;
217 	bool deleteMode;
218 
219 	std::string samplePath;
220 	int64_t sampleStart;
221 	int64_t sampleEnd;
222 	bool sampleLoop;
223 
224 	// Pages
225 	int actPage;
226 	int nrPages;
227 	int pageOffset;
228 
229 	//Widgets
230 	BWidgets::Widget mContainer;
231 	BWidgets::Label messageLabel;
232 	BWidgets::ValueWidget pageWidget;
233 	SymbolWidget pageBackSymbol;
234 	SymbolWidget pageForwardSymbol;
235 
236 	BWidgets::Label sourceLabel;
237 	BWidgets::Label calibrationLabel;
238 	BWidgets::Label stepEditModeLabel;
239 	BWidgets::Label stepSizeLabel;
240 	BWidgets::Label patternSizeLabel;
241 	BWidgets::Label padLevelLabel;
242 	BWidgets::Label playbackLabel;
243 	BWidgets::Label speedLabel;
244 
245 	struct Tab
246 	{
247 		BWidgets::Widget container;
248 		BWidgets::ImageIcon icon;
249 		SymbolWidget playSymbol;
250 		SymbolWidget midiSymbol;
251 		std::array<SymbolWidget, 4> symbols;
252 		std::array<BWidgets::ValueWidget, 4> midiWidgets;
253 	};
254 
255 	std::array<Tab, MAXPAGES> tabs;
256 
257 	BWidgets::ValueWidget midiBox;
258 	BWidgets::Label midiText;
259 	BWidgets::Label midiStatusLabel;
260 	BWidgets::PopupListBox midiStatusListBox;
261 	BWidgets::Label midiChannelLabel;
262 	BWidgets::PopupListBox midiChannelListBox;
263 	BWidgets::Label midiNoteLabel;
264 	BWidgets::PopupListBox midiNoteListBox;
265 	BWidgets::Label midiValueLabel;
266 	BWidgets::PopupListBox midiValueListBox;
267 	BWidgets::TextToggleButton midiLearnButton;
268 	BWidgets::TextButton midiCancelButton;
269 	BWidgets::TextButton midiOkButton;
270 
271 	BWidgets::Widget flipButton;
272 	PadSurface padSurface;
273 	MarkerWidget markerFwd;
274 	MarkerWidget markerRev;
275 	MonitorWidget monitorWidget;
276 	BWidgets::PopupListBox sourceListBox;
277 	LoadButton loadButton;
278 	BWidgets::Label sampleNameLabel;
279 	BWidgets::Dial sampleAmpDial;
280 	HaloToggleButton playButton;
281 	HaloToggleButton bypassButton;
282 	HaloButton stopButton;
283 	std::array<HaloToggleButton, EDIT_RESET> edit1Buttons;
284 	std::array<HaloButton, MAXEDIT - EDIT_RESET> edit2Buttons;
285 	BWidgets::ValueWidget syncWidget;
286 	BWidgets::LeftButton zeroStepOffsetButton;
287 	BWidgets::MinusButton decStepOffsetButton;
288 	HomeButton hostSyncButton;
289 	BWidgets::PlusButton incStepOffsetButton;
290 	BWidgets::PopupListBox editModeListBox;
291 	BWidgets::PopupListBox stepSizeListBox;
292 	BWidgets::PopupListBox stepBaseListBox;
293 	BWidgets::PopupListBox padSizeListBox;
294 	std::array<HaloToggleButton, 5> levelButtons;
295 	BWidgets::DialValue levelDial;
296 	BWidgets::Label delayDisplayLabel;
297 	BWidgets::RangeWidget manualProgressionDelayWidget;
298 	HaloButton resetDelayButton;
299 	HaloButton increaseDelayButton;
300 	HaloButton decreaseDelayButton;
301 	HaloButton setStartDelayButton;
302 	BWidgets::DialValue speedDial;
303 	HaloButton helpButton;
304 	HaloButton ytButton;
305 	SampleChooser* fileChooser;
306 
307 
308 	// Definition of styles
309 	BColors::ColorSet fgColors = {{{0.75, 0.75, 0.0, 1.0}, {1.0, 1.0, 0.25, 1.0}, {0.1, 0.1, 0.0, 1.0}, {0.0, 0.0, 0.0, 0.0}}};
310 	BColors::ColorSet tgColors = {{BColors::grey, BColors::white, BColors::grey, BColors::darkgrey}};
311 	BColors::ColorSet buttonBgColors = {{{0.4, 0.4, 0.4, 1.0}, {0.6, 0.6, 0.6, 1.0}, {0.05, 0.05, 0.05, 1.0}, {0.0, 0.0, 0.0, 1.0}}};
312 	BColors::ColorSet knobBgColors = {{{0.15, 0.15, 0.15, 1.0}, {0.3, 0.3, 0.3, 1.0}, {0.05, 0.05, 0.05, 1.0}, {0.0, 0.0, 0.0, 1.0}}};
313 	BColors::ColorSet tgBgColors = {{{0.0, 0.03, 0.06, 1.0}, {0.3, 0.3, 0.3, 1.0}, {0.0, 0.0, 0.0, 1.0}, {0.0, 0.0, 0.0, 1.0}}};
314 	BColors::ColorSet ltColors = {{{1.0, 1.0, 1.0, 1.0}, {1.0, 1.0, 1.0, 1.0}, {0.25, 0.25, 0.25, 1.0}, {0.0, 0.0, 0.0, 1.0}}};
315 	BColors::ColorSet wvColors = {{{1.0, 1.0, 1.0, 0.15}, {1.0, 1.0, 1.0, 0.15}, {0.25, 0.25, 0.25, 0.15}, {0.0, 0.0, 0.0, 0.15}}};
316 	BColors::ColorSet blkColors = {{{0.0, 0.0, 0.0, 0.75}, {0.0, 0.0, 0.0, 1.0}, {0.0, 0.0, 0.0, 0.25}, {0.0, 0.0, 0.0, 0.0}}};
317 	BColors::Color ink = {0.0, 0.25, 0.5, 1.0};
318 	BColors::Color evenPadBgColor = {0.0, 0.05, 0.2, 1.0};
319 	BColors::Color oddPadBgColor = {0.0, 0.0, 0.0, 1.0};
320 
321 	BStyles::Border border = {{ink, 1.0}, 0.0, 2.0, 0.0};
322 	BStyles::Border menuBorder = {{BColors::grey, 1.0}, 0.0, 0.0, 0.0};
323 	BStyles::Border labelborder = {BStyles::noLine, 4.0, 0.0, 0.0};
324 	BStyles::Border boxlabelborder = {{BColors::grey, 1.0}, 0.0, 3.0, 0.0};
325 	BStyles::Border focusborder = BStyles::Border (BStyles::Line (BColors::Color (0.0, 0.0, 0.0, 0.5), 2.0));
326 	BStyles::Fill widgetBg = BStyles::noFill;
327 	BStyles::Fill tabBg = BStyles::Fill (BColors::Color (0.75, 0.75, 0.0, 0.5));
328 	BStyles::Fill activeTabBg = BStyles::Fill (BColors::Color (0.75, 0.75, 0.0, 1.0));
329 	BStyles::Fill menuBg = BStyles::Fill (BColors::Color (0.0, 0.0, 0.05, 1.0));
330 	BStyles::Fill screenBg = BStyles::Fill (BColors::Color (0.0, 0.0, 0.0, 0.8));
331 	BStyles::Fill boxBg = BStyles::Fill (BColors::Color (0.0, 0.0, 0.0, 0.9));
332 	BStyles::Font ctLabelFont = BStyles::Font ("Sans", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL, 12.0,
333 						   BStyles::TEXT_ALIGN_CENTER, BStyles::TEXT_VALIGN_MIDDLE);
334    	BStyles::Font tLabelFont = BStyles::Font ("Sans", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD, 12.0,
335    						   BStyles::TEXT_ALIGN_CENTER, BStyles::TEXT_VALIGN_MIDDLE);
336 	BStyles::Font tgLabelFont = BStyles::Font ("Sans", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL, 12.0,
337 						   BStyles::TEXT_ALIGN_CENTER, BStyles::TEXT_VALIGN_MIDDLE);
338 	BStyles::Font lfLabelFont = BStyles::Font ("Sans", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL, 12.0,
339 						   BStyles::TEXT_ALIGN_LEFT, BStyles::TEXT_VALIGN_MIDDLE);
340 	BStyles::Font boldLfLabelFont = BStyles::Font ("Sans", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD, 12.0,
341 						   BStyles::TEXT_ALIGN_LEFT, BStyles::TEXT_VALIGN_MIDDLE);
342 	BStyles::Font smLabelFont = BStyles::Font ("Sans", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL, 8.0,
343 						   BStyles::TEXT_ALIGN_CENTER, BStyles::TEXT_VALIGN_MIDDLE);
344 	BStyles::StyleSet defaultStyles = {"default", {{"background", STYLEPTR (&BStyles::noFill)},
345 					  {"border", STYLEPTR (&BStyles::noBorder)}}};
346 	BStyles::StyleSet labelStyles = {"labels", {{"background", STYLEPTR (&BStyles::noFill)},
347 					{"border", STYLEPTR (&labelborder)},
348 					{"textcolors", STYLEPTR (&BColors::whites)},
349 					{"font", STYLEPTR (&ctLabelFont)}}};
350 	BStyles::StyleSet smlabelStyles = {"labels", {{"background", STYLEPTR (&BStyles::noFill)},
351 					  {"border", STYLEPTR (&labelborder)},
352 					  {"textcolors", STYLEPTR (&BColors::whites)},
353 					  {"font", STYLEPTR (&smLabelFont)}}};
354 	BStyles::StyleSet focusStyles = {"labels", {{"background", STYLEPTR (&screenBg)},
355 					{"border", STYLEPTR (&focusborder)},
356 					{"textcolors", STYLEPTR (&ltColors)},
357 					{"font", STYLEPTR (&lfLabelFont)}}};
358 
359 	BStyles::Theme theme = BStyles::Theme
360 	({
361 		defaultStyles,
362 		{"B.Jumblr", 		{{"background", STYLEPTR (&BStyles::blackFill)},
363 					 {"border", STYLEPTR (&BStyles::noBorder)}}},
364 		{"main", 		{{"background", STYLEPTR (&widgetBg)},
365 					 {"border", STYLEPTR (&BStyles::noBorder)}}},
366  		{"monitor", 		{{"uses", STYLEPTR (&defaultStyles)},
367  					 {"fgcolors", STYLEPTR (&wvColors)}}},
368 		{"widget", 		{{"uses", STYLEPTR (&defaultStyles)}}},
369 		{"widget/focus",	{{"uses", STYLEPTR (&focusStyles)}}},
370 		{"screen", 		{{"background", STYLEPTR (&screenBg)},
371 					 {"border", STYLEPTR (&BStyles::noBorder)}}},
372 		{"tab", 		{{"background", STYLEPTR (&tabBg)},
373 					 {"border", STYLEPTR (&BStyles::noBorder)},
374 			 		 {"fgcolors", STYLEPTR (&blkColors)}}},
375 		{"activetab", 		{{"background", STYLEPTR (&activeTabBg)},
376 					 {"border", STYLEPTR (&BStyles::noBorder)},
377 			 		 {"fgcolors", STYLEPTR (&blkColors)}}},
378 		{"symbol", 		{{"uses", STYLEPTR (&defaultStyles)},
379 					 {"fgcolors", STYLEPTR (&blkColors)}}},
380 		{"symbol/focus",	{{"uses", STYLEPTR (&focusStyles)}}},
381 		{"box", 		{{"background", STYLEPTR (&boxBg)},
382 					{"border", STYLEPTR (&border)}}},
383 		{"box/focus",		{{"uses", STYLEPTR (&focusStyles)}}},
384 		{"boxlabel",		{{"background", STYLEPTR (&boxBg)},
385 					 {"border", STYLEPTR (&boxlabelborder)},
386 					 {"textcolors", STYLEPTR (&BColors::whites)},
387  					 {"font", STYLEPTR (&lfLabelFont)}}},
388  		{"smboxlabel",		{{"background", STYLEPTR (&boxBg)},
389  					 {"border", STYLEPTR (&boxlabelborder)},
390  					 {"textcolors", STYLEPTR (&BColors::whites)},
391   					 {"font", STYLEPTR (&smLabelFont)}}},
392 		{"button", 		{{"background", STYLEPTR (&BStyles::blackFill)},
393 					 {"border", STYLEPTR (&border)},
394 				 	 {"bgcolors", STYLEPTR (&buttonBgColors)}}},
395 		{"tgbutton", 		{{"border", STYLEPTR (&BStyles::noBorder)},
396 					 {"textcolors", STYLEPTR (&tgColors)},
397 					 {"bgcolors", STYLEPTR (&tgBgColors)},
398 					 {"font", STYLEPTR (&tgLabelFont)}}},
399 		{"tgbutton/focus",	{{"uses", STYLEPTR (&focusStyles)}}},
400 		{"dial", 		{{"uses", STYLEPTR (&defaultStyles)},
401 					 {"fgcolors", STYLEPTR (&fgColors)},
402 					 {"bgcolors", STYLEPTR (&knobBgColors)},
403 					 {"textcolors", STYLEPTR (&fgColors)},
404 					 {"font", STYLEPTR (&ctLabelFont)}}},
405 		{"dial/focus", 		{{"uses", STYLEPTR (&focusStyles)}}},
406 		{"tlabel",	 	{{"uses", STYLEPTR (&smlabelStyles)},
407 					 {"font", STYLEPTR (&tLabelFont)}}},
408 		{"ylabel",	 	{{"uses", STYLEPTR (&smlabelStyles)},
409 					 {"textcolors", STYLEPTR (&fgColors)}}},
410 		{"ctlabel",	 	{{"uses", STYLEPTR (&labelStyles)}}},
411 		{"lflabel",	 	{{"uses", STYLEPTR (&labelStyles)},
412 					 {"font", STYLEPTR (&lfLabelFont)}}},
413 		{"menu",	 	{{"border", STYLEPTR (&menuBorder)},
414 					 {"background", STYLEPTR (&menuBg)}}},
415 		{"menu/item",	 	{{"uses", STYLEPTR (&defaultStyles)},
416 					 {"border", STYLEPTR (&labelborder)},
417 					 {"textcolors", STYLEPTR (&BColors::whites)},
418 					 {"font", STYLEPTR (&lfLabelFont)}}},
419 		{"menu/button",	 	{{"border", STYLEPTR (&menuBorder)},
420 					 {"background", STYLEPTR (&menuBg)},
421 					 {"bgcolors", STYLEPTR (&buttonBgColors)}}},
422 		{"menu/listbox",	{{"border", STYLEPTR (&menuBorder)},
423 					 {"background", STYLEPTR (&menuBg)}}},
424 		{"menu/listbox/item",	{{"uses", STYLEPTR (&defaultStyles)},
425 					 {"border", STYLEPTR (&labelborder)},
426 					 {"textcolors", STYLEPTR (&BColors::whites)},
427 					 {"font", STYLEPTR (&lfLabelFont)}}},
428 		{"menu/listbox/button",	{{"border", STYLEPTR (&menuBorder)},
429 					 {"background", STYLEPTR (&menuBg)},
430 					 {"bgcolors", STYLEPTR (&buttonBgColors)}}},
431 		{"filechooser",	 			{{"border", STYLEPTR (&menuBorder)},
432 					 		 {"background", STYLEPTR (&menuBg)}}},
433 		{"filechooser/label",			{{"background", STYLEPTR (&menuBg)},
434 					 		 {"border", STYLEPTR (&labelborder)},
435 					 	 	 {"textcolors", STYLEPTR (&BColors::whites)},
436 					 	 	 {"font", STYLEPTR (&lfLabelFont)}}},
437 		{"filechooser/textbox", 		{{"background", STYLEPTR (&menuBg)},
438 					 		 {"border", STYLEPTR (&boxlabelborder)},
439 					 	 	 {"textcolors", STYLEPTR (&BColors::whites)},
440 					 	 	 {"font", STYLEPTR (&lfLabelFont)}}},
441 		{"filechooser/scrollbar",		{{"uses", STYLEPTR (&defaultStyles)},
442 					 		 {"fgcolors", STYLEPTR (&blkColors)},
443 				 	 		 {"bgcolors", STYLEPTR (&knobBgColors)}}},
444 		{"filechooser/marker",			{{"uses", STYLEPTR (&defaultStyles)},
445 				 	 		 {"bgcolors", STYLEPTR (&fgColors)}}},
446 		{"filechooser/checkbox",		{{"uses", STYLEPTR (&defaultStyles)},
447 				 	 		 {"fgcolors", STYLEPTR (&fgColors)},
448 					 		 {"bgcolors", STYLEPTR (&knobBgColors)}}},
449 		{"filechooser/listbox",			{{"border", STYLEPTR (&menuBorder)},
450 					 		 {"background", STYLEPTR (&menuBg)}}},
451 		{"filechooser/listbox/item",		{{"uses", STYLEPTR (&defaultStyles)},
452 					 		 {"border", STYLEPTR (&labelborder)},
453 					 	 	 {"textcolors", STYLEPTR (&BColors::whites)},
454 					 	 	 {"font", STYLEPTR (&lfLabelFont)}}},
455 		{"filechooser/listbox/item/dir",	{{"uses", STYLEPTR (&defaultStyles)},
456 					 		 {"border", STYLEPTR (&labelborder)},
457 					 	 	 {"textcolors", STYLEPTR (&BColors::whites)},
458 					 	 	 {"font", STYLEPTR (&boldLfLabelFont)}}},
459 		{"filechooser/listbox/item/file",	{{"uses", STYLEPTR (&defaultStyles)},
460 					 		 {"border", STYLEPTR (&labelborder)},
461 					 	 	 {"textcolors", STYLEPTR (&BColors::whites)},
462 					 	 	 {"font", STYLEPTR (&lfLabelFont)}}},
463 		{"filechooser/listbox/button",		{{"border", STYLEPTR (&menuBorder)},
464 					 		 {"background", STYLEPTR (&menuBg)},
465 					 	 	 {"bgcolors", STYLEPTR (&buttonBgColors)}}},
466 		{"filechooser/popup",	 		{{"border", STYLEPTR (&menuBorder)},
467 					 		 {"background", STYLEPTR (&menuBg)}}},
468 		{"filechooser/popup/item",	 	{{"uses", STYLEPTR (&defaultStyles)},
469 					 		 {"border", STYLEPTR (&labelborder)},
470 					 	 	 {"textcolors", STYLEPTR (&BColors::whites)},
471 					 	 	 {"font", STYLEPTR (&lfLabelFont)}}},
472 		{"filechooser/popup/button",	 	{{"border", STYLEPTR (&menuBorder)},
473 					 		 {"background", STYLEPTR (&menuBg)},
474 					 	 	 {"bgcolors", STYLEPTR (&buttonBgColors)}}},
475 		{"filechooser/popup/listbox",		{{"border", STYLEPTR (&menuBorder)},
476 					 		 {"background", STYLEPTR (&menuBg)}}},
477 		{"filechooser/popup/listbox/item",	{{"uses", STYLEPTR (&defaultStyles)},
478 					 		 {"border", STYLEPTR (&labelborder)},
479 					 	 	 {"textcolors", STYLEPTR (&BColors::whites)},
480 					 	 	 {"font", STYLEPTR (&lfLabelFont)}}},
481 		{"filechooser/popup/listbox/button",	{{"border", STYLEPTR (&menuBorder)},
482 					 		 {"background", STYLEPTR (&menuBg)},
483 					 	 	 {"bgcolors", STYLEPTR (&buttonBgColors)}}}
484 	});
485 };
486 
487 #endif /* BJUMBLRGUI_HPP_ */
488