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
get_index_for_timeout(int32 timeout)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
get_timeout_for_index(int32 index)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*
get_label_for_timeout(int32 timeout)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
DefaultPartitionPage(BMessage * settings,BRect frame,const char * name)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
~DefaultPartitionPage()110 DefaultPartitionPage::~DefaultPartitionPage()
111 {
112 }
113
114
115 void
FrameResized(float width,float height)116 DefaultPartitionPage::FrameResized(float width, float height)
117 {
118 WizardPageView::FrameResized(width, height);
119 _Layout();
120 }
121
122
123 void
AttachedToWindow()124 DefaultPartitionPage::AttachedToWindow()
125 {
126 fDefaultPartition->Menu()->SetTargetForItems(this);
127 fTimeoutSlider->SetTarget(this);
128 }
129
130
131 void
MessageReceived(BMessage * msg)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
_BuildUI()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*
_CreatePopUpMenu()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
_GetTimeoutLabel(int32 timeout,BString & label)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
_Layout()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