1 /* 2 * Copyright 2008-2010, 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_TRANSLATE_CONTEXT 28 #define B_TRANSLATE_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 << 168 B_TRANSLATE_COMMENT("Default Partition", "Title") << "\n\n" << 169 B_TRANSLATE("Please specify a default partition and a timeout.\n" 170 "The boot menu will load the default partition after " 171 "the timeout unless you select another partition. You " 172 "can also have the boot menu wait indefinitely for you " 173 "to select a partition.\n" 174 "Keep the 'ALT' key pressed to disable the timeout at boot time."); 175 176 fDescription = CreateDescription(rect, "description", text); 177 MakeHeading(fDescription); 178 AddChild(fDescription); 179 LayoutDescriptionVertically(fDescription); 180 rect.top = fDescription->Frame().bottom + kTextDistance; 181 182 BPopUpMenu* popUpMenu = _CreatePopUpMenu(); 183 fDefaultPartition = new BMenuField(rect, "partitions", 184 B_TRANSLATE_COMMENT("Default Partition:", "Menu field label"), 185 popUpMenu); 186 float divider = be_plain_font->StringWidth(fDefaultPartition->Label()) + 3; 187 fDefaultPartition->SetDivider(divider); 188 AddChild(fDefaultPartition); 189 fDefaultPartition->ResizeToPreferred(); 190 191 // timeout slider 192 rect.top = fDefaultPartition->Frame().bottom + kTextDistance; 193 int32 timeout; 194 fSettings->FindInt32("timeout", &timeout); 195 BString timeoutLabel; 196 _GetTimeoutLabel(timeout, timeoutLabel); 197 198 int32 sliderValue = get_index_for_timeout(timeout); 199 200 fTimeoutSlider = new BSlider(rect, "timeout", timeoutLabel.String(), 201 new BMessage(kMsgTimeout), 0, kNumberOfTimeoutOptions-1, 202 B_BLOCK_THUMB, 203 B_FOLLOW_LEFT_RIGHT | B_FOLLOW_TOP); 204 fTimeoutSlider->SetModificationMessage(new BMessage(kMsgTimeout)); 205 fTimeoutSlider->SetValue(sliderValue); 206 fTimeoutSlider->SetLimitLabels(B_TRANSLATE("Immediately"), 207 B_TRANSLATE("Never")); 208 fTimeoutSlider->SetHashMarks(B_HASH_MARKS_BOTTOM); 209 fTimeoutSlider->SetHashMarkCount(kNumberOfTimeoutOptions); 210 fTimeoutSlider->ResizeToPreferred(); 211 AddChild(fTimeoutSlider); 212 213 _Layout(); 214 } 215 216 217 BPopUpMenu* 218 DefaultPartitionPage::_CreatePopUpMenu() 219 { 220 int32 defaultPartitionIndex; 221 fSettings->FindInt32("defaultPartition", &defaultPartitionIndex); 222 223 BMenuItem* selectedItem = NULL; 224 int32 selectedItemIndex = 0; 225 226 BPopUpMenu* menu = new BPopUpMenu(B_TRANSLATE_COMMENT("Partitions", 227 "Pop up menu title")); 228 BMessage message; 229 for (int32 i = 0; fSettings->FindMessage("partition", i, &message) == B_OK; 230 i++) { 231 bool show; 232 if (message.FindBool("show", &show) != B_OK || !show) 233 continue; 234 235 BString name; 236 message.FindString("name", &name); 237 238 BMessage* msg = new BMessage(kMsgPartition); 239 msg->AddInt32("index", i); 240 BMenuItem* item = new BMenuItem(name.String(), msg); 241 menu->AddItem(item); 242 if (defaultPartitionIndex == i || selectedItem == NULL) { 243 selectedItem = item; 244 selectedItemIndex = i; 245 } 246 } 247 fSettings->ReplaceInt32("defaultPartition", selectedItemIndex); 248 selectedItem->SetMarked(true); 249 return menu; 250 } 251 252 253 void 254 DefaultPartitionPage::_GetTimeoutLabel(int32 timeout, BString& label) 255 { 256 const char* text = B_TRANSLATE_NOCOLLECT(get_label_for_timeout(timeout)); 257 label = B_TRANSLATE("Timeout: %s"); 258 label.ReplaceFirst("%s", text); 259 } 260 261 262 void 263 DefaultPartitionPage::_Layout() 264 { 265 LayoutDescriptionVertically(fDescription); 266 267 const float kTextDistance = be_control_look->DefaultItemSpacing(); 268 float left = fDefaultPartition->Frame().left; 269 float top = fDescription->Frame().bottom + kTextDistance; 270 271 fDefaultPartition->MoveTo(left, top); 272 top = fDefaultPartition->Frame().bottom + kTextDistance; 273 274 fTimeoutSlider->MoveTo(left, top); 275 } 276