xref: /haiku/src/preferences/appearance/LookAndFeelSettingsView.cpp (revision 820dca4df6c7bf955c46e8f6521b9408f50b2900)
1 /*
2  *  Copyright 2010-2012 Haiku, Inc. All rights reserved.
3  *  Distributed under the terms of the MIT license.
4  *
5  *	Authors:
6  *		Stephan Aßmus <superstippi@gmx.de>
7  *		Alexander von Gluck <kallisti5@unixzen.com>
8  *		John Scipione <jscipione@gmail.com>
9  *		Ryan Leavengood <leavengood@gmail.com>
10  */
11 
12 
13 #include "LookAndFeelSettingsView.h"
14 
15 #include <stdio.h>
16 #include <stdlib.h>
17 
18 #include <Alert.h>
19 #include <Alignment.h>
20 #include <Box.h>
21 #include <Button.h>
22 #include <Catalog.h>
23 #include <CheckBox.h>
24 #include <GridLayoutBuilder.h>
25 #include <GroupLayoutBuilder.h>
26 #include <InterfaceDefs.h>
27 #include <LayoutBuilder.h>
28 #include <Locale.h>
29 #include <MenuField.h>
30 #include <MenuItem.h>
31 #include <PopUpMenu.h>
32 #include <ScrollBar.h>
33 #include <StringView.h>
34 #include <Size.h>
35 #include <Slider.h>
36 #include <SpaceLayoutItem.h>
37 #include <StringView.h>
38 #include <TextView.h>
39 
40 #include "APRWindow.h"
41 #include "FakeScrollBar.h"
42 
43 
44 #undef B_TRANSLATION_CONTEXT
45 #define B_TRANSLATION_CONTEXT "DecorSettingsView"
46 	// This was not renamed to keep from breaking translations
47 
48 
49 static const int32 kMsgSetDecor = 'deco';
50 static const int32 kMsgDecorInfo = 'idec';
51 
52 static const int32 kMsgDoubleScrollBarArrows = 'dsba';
53 
54 static const int32 kMsgArrowStyleSingle = 'mass';
55 static const int32 kMsgArrowStyleDouble = 'masd';
56 
57 static const int32 kMsgKnobStyleNone = 'mksn';
58 static const int32 kMsgKnobStyleDots = 'mksd';
59 static const int32 kMsgKnobStyleLines = 'mksl';
60 
61 static const bool kDefaultDoubleScrollBarArrowsSetting = false;
62 
63 
64 //	#pragma mark -
65 
66 
67 LookAndFeelSettingsView::LookAndFeelSettingsView(const char* name)
68 	:
69 	BView(name, 0),
70 	fDecorInfoButton(NULL),
71 	fDecorMenuField(NULL),
72 	fDecorMenu(NULL)
73 {
74 	// Decorator menu
75 	_BuildDecorMenu();
76 	fDecorMenuField = new BMenuField("decorator",
77 		B_TRANSLATE("Window decorator:"), fDecorMenu);
78 
79 	fDecorInfoButton = new BButton(B_TRANSLATE("About"),
80 		new BMessage(kMsgDecorInfo));
81 
82 	// scroll bar arrow style
83 	BBox* arrowStyleBox = new BBox("arrow style");
84 	arrowStyleBox->SetLabel(B_TRANSLATE("Arrow style"));
85 
86 	fSavedDoubleArrowsValue = _DoubleScrollBarArrows();
87 
88 	fArrowStyleSingle = new FakeScrollBar(true, false,
89 		new BMessage(kMsgArrowStyleSingle));
90 	fArrowStyleDouble = new FakeScrollBar(true, true,
91 		new BMessage(kMsgArrowStyleDouble));
92 
93 	BView* arrowStyleView;
94 	arrowStyleView = BLayoutBuilder::Group<>()
95 		.AddGroup(B_VERTICAL, 1)
96 			.Add(new BStringView("single", B_TRANSLATE("Single:")))
97 			.Add(fArrowStyleSingle)
98 			.Add(new BStringView("spacer", ""))
99 			.Add(new BStringView("double", B_TRANSLATE("Double:")))
100 			.Add(fArrowStyleDouble)
101 			.SetInsets(B_USE_DEFAULT_SPACING, B_USE_DEFAULT_SPACING,
102 				B_USE_DEFAULT_SPACING, B_USE_DEFAULT_SPACING)
103 			.End()
104 		.View();
105 	arrowStyleBox->AddChild(arrowStyleView);
106 	arrowStyleBox->SetExplicitAlignment(BAlignment(B_ALIGN_LEFT,
107 		B_ALIGN_VERTICAL_CENTER));
108 
109 	BStringView* scrollBarLabel
110 		= new BStringView("scroll bar", "Scroll bar:");
111 	scrollBarLabel->SetExplicitAlignment(
112 		BAlignment(B_ALIGN_LEFT, B_ALIGN_TOP));
113 
114 	SetLayout(new BGroupLayout(B_VERTICAL));
115 
116 	// control layout
117 	AddChild(BGroupLayoutBuilder(B_VERTICAL, B_USE_DEFAULT_SPACING)
118 		.AddGroup(B_VERTICAL, B_USE_DEFAULT_SPACING)
119 			.Add(BGridLayoutBuilder(B_USE_DEFAULT_SPACING,
120 					B_USE_DEFAULT_SPACING)
121 				.Add(fDecorMenuField->CreateLabelLayoutItem(), 0, 0)
122 		        .Add(fDecorMenuField->CreateMenuBarLayoutItem(), 1, 0)
123 				.Add(fDecorInfoButton, 2, 0)
124 			)
125 			.AddGroup(B_HORIZONTAL, B_USE_DEFAULT_SPACING)
126 				.Add(scrollBarLabel)
127 				.Add(arrowStyleBox)
128 			.End()
129 			.AddGlue()
130 		.End()
131 		.SetInsets(B_USE_DEFAULT_SPACING, B_USE_DEFAULT_SPACING,
132 			B_USE_DEFAULT_SPACING, B_USE_DEFAULT_SPACING)
133 	);
134 	// TODO : Decorator Preview Image?
135 }
136 
137 
138 LookAndFeelSettingsView::~LookAndFeelSettingsView()
139 {
140 }
141 
142 
143 void
144 LookAndFeelSettingsView::AttachedToWindow()
145 {
146 	if (Parent() != NULL)
147 		SetViewColor(Parent()->ViewColor());
148 	else
149 		SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
150 
151 	fDecorMenu->SetTargetForItems(this);
152 	fDecorInfoButton->SetTarget(this);
153 	fArrowStyleSingle->SetTarget(this);
154 	fArrowStyleDouble->SetTarget(this);
155 
156 	if (fSavedDoubleArrowsValue)
157 		fArrowStyleDouble->SetValue(B_CONTROL_ON);
158 	else
159 		fArrowStyleSingle->SetValue(B_CONTROL_ON);
160 }
161 
162 
163 void
164 LookAndFeelSettingsView::MessageReceived(BMessage *msg)
165 {
166 	switch (msg->what) {
167 		case kMsgSetDecor:
168 		{
169 			BString newDecor;
170 			if (msg->FindString("decor", &newDecor) == B_OK)
171 				_SetDecor(newDecor);
172 			break;
173 		}
174 
175 		case kMsgDecorInfo:
176 		{
177 			DecorInfo* decor = fDecorUtility.FindDecorator(fCurrentDecor);
178 			if (decor == NULL)
179 				break;
180 
181 			BString authorsText(decor->Authors().String());
182 			authorsText.ReplaceAll(", ", "\n    ");
183 
184 			BString infoText("Name: %decorName\n"
185 				"Authors:\n    %decorAuthors\n"
186 				"URL: %decorURL\n"
187 				"License: %decorLic\n"
188 				"Description:\n    %decorDesc\n");
189 
190 			infoText.ReplaceFirst("%decorName", decor->Name().String());
191 			infoText.ReplaceFirst("%decorAuthors", authorsText.String());
192 			infoText.ReplaceFirst("%decorLic", decor->LicenseName().String());
193 			infoText.ReplaceFirst("%decorURL", decor->SupportURL().String());
194 			infoText.ReplaceFirst("%decorDesc", decor->ShortDescription().String());
195 
196 			BAlert *infoAlert = new BAlert(B_TRANSLATE("About Decorator"),
197 				infoText.String(), B_TRANSLATE("OK"));
198 			infoAlert->SetFlags(infoAlert->Flags() | B_CLOSE_ON_ESCAPE);
199 			infoAlert->Go();
200 
201 			break;
202 		}
203 
204 		case kMsgArrowStyleSingle:
205 			_SetDoubleScrollBarArrows(false);
206 			break;
207 
208 		case kMsgArrowStyleDouble:
209 			_SetDoubleScrollBarArrows(true);
210 			break;
211 
212 		default:
213 			BView::MessageReceived(msg);
214 			break;
215 	}
216 }
217 
218 
219 void
220 LookAndFeelSettingsView::_BuildDecorMenu()
221 {
222 	fDecorMenu = new BPopUpMenu(B_TRANSLATE("Choose Decorator"));
223 
224 	// collect the current system decor settings
225 	int32 count = fDecorUtility.CountDecorators();
226 	for (int32 i = 0; i < count; ++i) {
227 		DecorInfo* decorator = fDecorUtility.DecoratorAt(i);
228 		if (decorator == NULL) {
229 			fprintf(stderr, "Decorator : error NULL entry @ %" B_PRId32
230 				" / %" B_PRId32 "\n", i, count);
231 			continue;
232 		}
233 
234 		BString decorName = decorator->Name();
235 
236 		BMessage* message = new BMessage(kMsgSetDecor);
237 		message->AddString("decor", decorName);
238 
239 		BMenuItem* item = new BMenuItem(decorName, message);
240 
241 		fDecorMenu->AddItem(item);
242 	}
243 
244 	_AdoptToCurrentDecor();
245 }
246 
247 
248 void
249 LookAndFeelSettingsView::_SetDecor(const BString& name)
250 {
251 	_SetDecor(fDecorUtility.FindDecorator(name));
252 }
253 
254 
255 void
256 LookAndFeelSettingsView::_SetDecor(DecorInfo* decorInfo)
257 {
258 	if (fDecorUtility.SetDecorator(decorInfo) == B_OK) {
259 		_AdoptToCurrentDecor();
260 		Window()->PostMessage(kMsgUpdate);
261 	}
262 }
263 
264 
265 void
266 LookAndFeelSettingsView::_AdoptToCurrentDecor()
267 {
268 	fCurrentDecor = fDecorUtility.CurrentDecorator()->Name();
269 	if (fSavedDecor.Length() == 0)
270 		fSavedDecor = fCurrentDecor;
271 	_AdoptInterfaceToCurrentDecor();
272 }
273 
274 void
275 LookAndFeelSettingsView::_AdoptInterfaceToCurrentDecor()
276 {
277 	BMenuItem* item = fDecorMenu->FindItem(fCurrentDecor);
278 	if (item != NULL)
279 		item->SetMarked(true);
280 }
281 
282 
283 bool
284 LookAndFeelSettingsView::_DoubleScrollBarArrows()
285 {
286 	scroll_bar_info info;
287 	get_scroll_bar_info(&info);
288 
289 	return info.double_arrows;
290 }
291 
292 
293 void
294 LookAndFeelSettingsView::_SetDoubleScrollBarArrows(bool doubleArrows)
295 {
296 	scroll_bar_info info;
297 	get_scroll_bar_info(&info);
298 
299 	info.double_arrows = doubleArrows;
300 	set_scroll_bar_info(&info);
301 
302 	if (doubleArrows)
303 		fArrowStyleDouble->SetValue(B_CONTROL_ON);
304 	else
305 		fArrowStyleSingle->SetValue(B_CONTROL_ON);
306 
307 	Window()->PostMessage(kMsgUpdate);
308 }
309 
310 
311 bool
312 LookAndFeelSettingsView::IsDefaultable()
313 {
314 	return fCurrentDecor != fDecorUtility.DefaultDecorator()->Name()
315 		|| _DoubleScrollBarArrows() != false;
316 }
317 
318 
319 void
320 LookAndFeelSettingsView::SetDefaults()
321 {
322 	_SetDecor(fDecorUtility.DefaultDecorator());
323 	_SetDoubleScrollBarArrows(false);
324 }
325 
326 
327 bool
328 LookAndFeelSettingsView::IsRevertable()
329 {
330 	return fCurrentDecor != fSavedDecor
331 		|| _DoubleScrollBarArrows() != fSavedDoubleArrowsValue;
332 }
333 
334 
335 void
336 LookAndFeelSettingsView::Revert()
337 {
338 	_SetDecor(fSavedDecor);
339 	_SetDoubleScrollBarArrows(fSavedDoubleArrowsValue);
340 }
341