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