xref: /haiku/src/apps/bootmanager/DefaultPartitionPage.cpp (revision 68ea01249e1e2088933cb12f9c28d4e5c5d1c9ef)
1 /*
2  * Copyright 2008-2011, Haiku, Inc. All rights reserved.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		Michael Pfeiffer <laplace@users.sourceforge.net>
7  */
8 
9 
10 #include "DefaultPartitionPage.h"
11 
12 
13 #include <Catalog.h>
14 #include <ControlLook.h>
15 #include <Locale.h>
16 #include <Message.h>
17 #include <MenuItem.h>
18 #include <MenuField.h>
19 #include <PopUpMenu.h>
20 #include <RadioButton.h>
21 #include <Slider.h>
22 #include <string.h>
23 #include <String.h>
24 #include <TextView.h>
25 
26 
27 #undef B_TRANSLATION_CONTEXT
28 #define B_TRANSLATION_CONTEXT "DefaultPartitionPage"
29 
30 
31 enum {
32 	kMsgPartition = 'part',
33 	kMsgTimeout = 'time'
34 };
35 
36 
37 // The timeout code to wait indefinitely
38 // Note: The timeout is encoded in seconds, -1 indicates to wait indefinitely
39 const int32 kTimeoutIndefinitely = -1;
40 const int32 kDefaultTimeout = kTimeoutIndefinitely;
41 
42 struct TimeoutOption {
43 	int32 timeout;
44 	const char* label;
45 };
46 
47 static const TimeoutOption gTimeoutOptions[] = {
48 	{ 0, B_TRANSLATE_MARK("Immediately")},
49 	{ 1, B_TRANSLATE_MARK("After one second")},
50 	{ 2, B_TRANSLATE_MARK("After two seconds")},
51 	{ 3, B_TRANSLATE_MARK("After three seconds")},
52 	{ 4, B_TRANSLATE_MARK("After four seconds")},
53 	{ 5, B_TRANSLATE_MARK("After five seconds")},
54 	{ 60, B_TRANSLATE_MARK("After one minute")},
55 	{ kTimeoutIndefinitely, B_TRANSLATE_MARK("Never")}
56 };
57 
58 
59 #define kNumberOfTimeoutOptions \
60 	(int32)(sizeof(gTimeoutOptions) / sizeof(TimeoutOption))
61 
62 
63 static int32
64 get_index_for_timeout(int32 timeout)
65 {
66 	int32 defaultIndex = 0;
67 	for (int32 i = 0; i < kNumberOfTimeoutOptions; i ++) {
68 		if (gTimeoutOptions[i].timeout == timeout)
69 			return i;
70 
71 		if (gTimeoutOptions[i].timeout == kDefaultTimeout)
72 			defaultIndex = i;
73 	}
74 	return defaultIndex;
75 }
76 
77 
78 static int32
79 get_timeout_for_index(int32 index)
80 {
81 	if (index < 0)
82 		return gTimeoutOptions[0].timeout;
83 	if (index >= kNumberOfTimeoutOptions)
84 		return gTimeoutOptions[kNumberOfTimeoutOptions-1].timeout;
85 	return gTimeoutOptions[index].timeout;
86 }
87 
88 
89 const char*
90 get_label_for_timeout(int32 timeout)
91 {
92 	int32 index = get_index_for_timeout(timeout);
93 	return gTimeoutOptions[index].label;
94 }
95 
96 
97 // #pragma mark -
98 
99 
100 DefaultPartitionPage::DefaultPartitionPage(BMessage* settings, BRect frame,
101 	const char* name)
102 	:
103 	WizardPageView(settings, frame, name, B_FOLLOW_ALL,
104 		B_WILL_DRAW | B_FRAME_EVENTS | B_FULL_UPDATE_ON_RESIZE)
105 {
106 	_BuildUI();
107 }
108 
109 
110 DefaultPartitionPage::~DefaultPartitionPage()
111 {
112 }
113 
114 
115 void
116 DefaultPartitionPage::FrameResized(float width, float height)
117 {
118 	WizardPageView::FrameResized(width, height);
119 	_Layout();
120 }
121 
122 
123 void
124 DefaultPartitionPage::AttachedToWindow()
125 {
126 	fDefaultPartition->Menu()->SetTargetForItems(this);
127 	fTimeoutSlider->SetTarget(this);
128 }
129 
130 
131 void
132 DefaultPartitionPage::MessageReceived(BMessage* msg)
133 {
134 	switch (msg->what) {
135 		case kMsgPartition:
136 		{
137 			int32 index;
138 			msg->FindInt32("index", &index);
139 			fSettings->ReplaceInt32("defaultPartition", index);
140 			break;
141 		}
142 		case kMsgTimeout:
143 		{
144 			int32 sliderValue = fTimeoutSlider->Value();
145 			int32 timeout = get_timeout_for_index(sliderValue);
146 			fSettings->ReplaceInt32("timeout", timeout);
147 
148 			BString label;
149 			_GetTimeoutLabel(timeout, label);
150 			fTimeoutSlider->SetLabel(label.String());
151 			break;
152 		}
153 
154 		default:
155 			WizardPageView::MessageReceived(msg);
156 	}
157 }
158 
159 
160 void
161 DefaultPartitionPage::_BuildUI()
162 {
163 	const float kTextDistance = be_control_look->DefaultItemSpacing();
164 	BRect rect(Bounds());
165 
166 	BString text;
167 	text << B_TRANSLATE_COMMENT("Default Partition", "Title") << "\n"
168 		<< B_TRANSLATE("Please specify a default partition and a timeout.\n"
169 			"The boot menu will load the default partition after "
170 			"the timeout unless you select another partition. You "
171 			"can also have the boot menu wait indefinitely for you "
172 			"to select a partition.\n"
173 			"Keep the 'ALT' key pressed to disable the timeout at boot time.");
174 
175 	fDescription = CreateDescription(rect, "description", text);
176 	MakeHeading(fDescription);
177 	AddChild(fDescription);
178 	LayoutDescriptionVertically(fDescription);
179 	rect.top = fDescription->Frame().bottom + kTextDistance;
180 
181 	BPopUpMenu* popUpMenu = _CreatePopUpMenu();
182 	fDefaultPartition = new BMenuField(rect, "partitions",
183 		B_TRANSLATE_COMMENT("Default Partition:", "Menu field label"),
184 		popUpMenu);
185 	float divider = be_plain_font->StringWidth(fDefaultPartition->Label()) + 3;
186 	fDefaultPartition->SetDivider(divider);
187 	AddChild(fDefaultPartition);
188 	fDefaultPartition->ResizeToPreferred();
189 
190 	// timeout slider
191 	rect.top = fDefaultPartition->Frame().bottom + kTextDistance;
192 	int32 timeout;
193 	fSettings->FindInt32("timeout", &timeout);
194 	BString timeoutLabel;
195 	_GetTimeoutLabel(timeout, timeoutLabel);
196 
197 	int32 sliderValue = get_index_for_timeout(timeout);
198 
199 	fTimeoutSlider = new BSlider(rect, "timeout", timeoutLabel.String(),
200 		new BMessage(kMsgTimeout), 0, kNumberOfTimeoutOptions-1,
201 		B_BLOCK_THUMB,
202 		B_FOLLOW_LEFT_RIGHT | B_FOLLOW_TOP);
203 	fTimeoutSlider->SetModificationMessage(new BMessage(kMsgTimeout));
204 	fTimeoutSlider->SetValue(sliderValue);
205 	fTimeoutSlider->SetLimitLabels(B_TRANSLATE("Immediately"),
206 		B_TRANSLATE("Never"));
207 	fTimeoutSlider->SetHashMarks(B_HASH_MARKS_BOTTOM);
208 	fTimeoutSlider->SetHashMarkCount(kNumberOfTimeoutOptions);
209 	fTimeoutSlider->ResizeToPreferred();
210 	AddChild(fTimeoutSlider);
211 
212 	_Layout();
213 }
214 
215 
216 BPopUpMenu*
217 DefaultPartitionPage::_CreatePopUpMenu()
218 {
219 	int32 defaultPartitionIndex;
220 	fSettings->FindInt32("defaultPartition", &defaultPartitionIndex);
221 
222 	BMenuItem* selectedItem = NULL;
223 	int32 selectedItemIndex = 0;
224 
225 	BPopUpMenu* menu = new BPopUpMenu(B_TRANSLATE_COMMENT("Partitions",
226 		"Pop up menu title"));
227 	BMessage message;
228 	for (int32 i = 0; fSettings->FindMessage("partition", i, &message) == B_OK;
229 			i++) {
230 		bool show;
231 		if (message.FindBool("show", &show) != B_OK || !show)
232 			continue;
233 
234 		BString name;
235 		message.FindString("name", &name);
236 
237 		BMessage* msg = new BMessage(kMsgPartition);
238 		msg->AddInt32("index", i);
239 		BMenuItem* item = new BMenuItem(name.String(), msg);
240 		menu->AddItem(item);
241 		if (defaultPartitionIndex == i || selectedItem == NULL) {
242 			selectedItem = item;
243 			selectedItemIndex = i;
244 		}
245 	}
246 	fSettings->ReplaceInt32("defaultPartition", selectedItemIndex);
247 	selectedItem->SetMarked(true);
248 	return menu;
249 }
250 
251 
252 void
253 DefaultPartitionPage::_GetTimeoutLabel(int32 timeout, BString& label)
254 {
255 	const char* text = B_TRANSLATE_NOCOLLECT(get_label_for_timeout(timeout));
256 	label = B_TRANSLATE("Timeout: %s");
257 	label.ReplaceFirst("%s", text);
258 }
259 
260 
261 void
262 DefaultPartitionPage::_Layout()
263 {
264 	LayoutDescriptionVertically(fDescription);
265 
266 	const float kTextDistance = be_control_look->DefaultItemSpacing();
267 	float left = fDefaultPartition->Frame().left;
268 	float top = fDescription->Frame().bottom + kTextDistance;
269 
270 	fDefaultPartition->MoveTo(left, top);
271 	top = fDefaultPartition->Frame().bottom + kTextDistance;
272 
273 	fTimeoutSlider->MoveTo(left, top);
274 }
275