RemoteDrawingEngine: Reduce RP_READ_BITMAP result timeout.
[haiku.git] / src / apps / bootmanager / DrivesPage.cpp
blob0babdb7d4a341fa8e3f4f357203062864645f40b
1 /*
2 * Copyright 2011, Axel Dörfler, axeld@pinc-software.de.
3 * Distributed under the terms of the MIT License.
4 */
7 #include "DrivesPage.h"
9 #include <Catalog.h>
10 #include <ControlLook.h>
11 #include <DiskDeviceRoster.h>
12 #include <DiskDevice.h>
13 #include <LayoutBuilder.h>
14 #include <ListView.h>
15 #include <Path.h>
16 #include <ScrollView.h>
17 #include <TextView.h>
18 #include <Bitmap.h>
20 #include <StringForSize.h>
22 #include "BootDrive.h"
23 #include "WizardView.h"
26 #undef B_TRANSLATION_CONTEXT
27 #define B_TRANSLATION_CONTEXT "DrivesPage"
30 const uint32 kMsgSelectionChanged = 'slch';
33 class DriveItem : public BListItem {
34 public:
35 DriveItem(const BDiskDevice& device,
36 const BootMenuList& menus);
37 virtual ~DriveItem();
39 bool IsInstalled() const;
40 bool CanBeInstalled() const;
41 bool IsBootDrive() const;
42 const char* Path() const { return fPath.Path(); }
44 BootDrive* Drive() { return fDrive; }
46 protected:
47 virtual void DrawItem(BView* owner, BRect frame,
48 bool complete = false);
49 virtual void Update(BView* owner, const BFont* font);
51 private:
52 BootDrive* fDrive;
53 BBitmap* fIcon;
54 BString fName;
55 BPath fPath;
56 BString fSize;
57 float fBaselineOffset;
58 float fSecondBaselineOffset;
59 float fSizeWidth;
60 status_t fCanBeInstalled;
61 bool fIsInstalled;
65 DriveItem::DriveItem(const BDiskDevice& device, const BootMenuList& menus)
67 fBaselineOffset(0),
68 fSizeWidth(0)
70 device.GetPath(&fPath);
71 if (device.Name() != NULL && device.Name()[0])
72 fName = device.Name();
73 else if (strstr(fPath.Path(), "usb") != NULL)
74 fName = B_TRANSLATE_COMMENT("USB Drive", "Default disk name");
75 else
76 fName = B_TRANSLATE_COMMENT("Hard Drive", "Default disk name");
78 fIcon = new BBitmap(BRect(0, 0, B_LARGE_ICON - 1, B_LARGE_ICON - 1),
79 B_RGBA32);
80 if (device.GetIcon(fIcon, B_LARGE_ICON) != B_OK)
81 memset(fIcon->Bits(), 0, fIcon->BitsLength());
83 fDrive = new BootDrive(fPath.Path());
85 fIsInstalled = fDrive->InstalledMenu(menus) != NULL;
86 fCanBeInstalled = fDrive->CanMenuBeInstalled(menus);
88 char buffer[256];
89 fSize = string_for_size(device.Size(), buffer, sizeof(buffer));
93 DriveItem::~DriveItem()
95 delete fDrive;
96 delete fIcon;
100 bool
101 DriveItem::IsInstalled() const
103 return fIsInstalled;
107 bool
108 DriveItem::CanBeInstalled() const
110 return fCanBeInstalled == B_OK;
114 bool
115 DriveItem::IsBootDrive() const
117 return fDrive->IsBootDrive();
121 void
122 DriveItem::DrawItem(BView* owner, BRect frame, bool complete)
124 owner->PushState();
125 owner->SetDrawingMode(B_OP_ALPHA);
127 if (IsSelected() || complete) {
128 if (IsSelected()) {
129 owner->SetHighColor(ui_color(B_LIST_SELECTED_BACKGROUND_COLOR));
130 owner->SetLowColor(owner->HighColor());
131 } else
132 owner->SetHighColor(owner->LowColor());
134 owner->FillRect(frame);
137 if (!IsEnabled()) {
138 rgb_color textColor;
139 if (IsSelected())
140 textColor = ui_color(B_LIST_SELECTED_ITEM_TEXT_COLOR);
141 else
142 textColor = ui_color(B_LIST_ITEM_TEXT_COLOR);
144 if (textColor.red + textColor.green + textColor.blue > 128 * 3)
145 owner->SetHighColor(tint_color(textColor, B_DARKEN_1_TINT));
146 else
147 owner->SetHighColor(tint_color(textColor, B_LIGHTEN_1_TINT));
148 } else {
149 if (IsSelected())
150 owner->SetHighColor(ui_color(B_LIST_SELECTED_ITEM_TEXT_COLOR));
151 else
152 owner->SetHighColor(ui_color(B_LIST_ITEM_TEXT_COLOR));
156 // icon
157 owner->MovePenTo(frame.left + 4, frame.top + 1);
158 owner->DrawBitmap(fIcon);
160 // device
161 owner->MovePenTo(frame.left + 8 + fIcon->Bounds().Width(),
162 frame.top + fSecondBaselineOffset);
163 owner->DrawString(fPath.Path());
165 // name
166 BFont boldFont;
167 BFont ownerFont;
168 owner->GetFont(&ownerFont);
169 owner->GetFont(&boldFont);
170 boldFont.SetFace(B_BOLD_FACE);
171 owner->SetFont(&boldFont);
173 BPoint namePosition(frame.left + 8 + fIcon->Bounds().Width(),
174 frame.top + fBaselineOffset);
176 owner->MovePenTo(namePosition);
177 owner->DrawString(fName.String());
179 float nameWidth = owner->StringWidth(fName.String());
180 float messageWidth = frame.right - 4 - fSizeWidth
181 - (frame.left + 8 + fIcon->Bounds().Width()) - nameWidth
182 - fBaselineOffset * 2;
184 if (fCanBeInstalled != B_OK) {
185 rgb_color highColor = owner->HighColor();
186 owner->SetHighColor(ui_color(B_FAILURE_COLOR));
187 owner->MovePenBy(fBaselineOffset, 0);
188 const char* message;
189 switch (fCanBeInstalled) {
190 case B_PARTITION_TOO_SMALL:
191 message = B_TRANSLATE_COMMENT("No space available!",
192 "Cannot install");
193 break;
194 case B_ENTRY_NOT_FOUND:
195 message = B_TRANSLATE_COMMENT("Incompatible format!",
196 "Cannot install");
197 break;
198 default:
199 message = B_TRANSLATE_COMMENT("Cannot access!",
200 "Cannot install");
201 break;
203 BString truncatedMessage = message;
204 owner->TruncateString(&truncatedMessage, B_TRUNCATE_END, messageWidth);
205 owner->DrawString(truncatedMessage);
206 owner->SetHighColor(highColor);
208 owner->SetFont(&ownerFont);
209 // size
210 BPoint sizePosition(frame.right - 4 - fSizeWidth,
211 frame.top + fBaselineOffset);
212 if (sizePosition.x > namePosition.x + nameWidth) {
213 owner->MovePenTo(sizePosition);
214 owner->DrawString(fSize.String());
217 owner->PopState();
221 void
222 DriveItem::Update(BView* owner, const BFont* font)
224 fSizeWidth = font->StringWidth(fSize.String());
226 BFont boldFont(font);
227 boldFont.SetFace(B_BOLD_FACE);
228 float width = 8 + boldFont.StringWidth(fPath.Path())
229 + be_control_look->DefaultItemSpacing() + fSizeWidth;
230 float pathWidth = font->StringWidth(fPath.Path());
231 if (width < pathWidth)
232 width = pathWidth;
234 SetWidth(width);
236 font_height fheight;
237 font->GetHeight(&fheight);
239 float lineHeight = ceilf(fheight.ascent) + ceilf(fheight.descent)
240 + ceilf(fheight.leading);
242 fBaselineOffset = 2 + ceilf(fheight.ascent + fheight.leading / 2);
243 fSecondBaselineOffset = fBaselineOffset + lineHeight;
245 SetHeight(2 * lineHeight + 4);
249 // #pragma mark -
252 DrivesPage::DrivesPage(WizardView* wizardView, const BootMenuList& menus,
253 BMessage* settings, const char* name)
255 WizardPageView(settings, name),
256 fWizardView(wizardView),
257 fHasInstallableItems(false)
259 BString text;
260 text << B_TRANSLATE_COMMENT("Drives", "Title") << "\n"
261 << B_TRANSLATE("Please select the drive you want the boot manager to "
262 "be installed to or uninstalled from.");
263 BTextView* description = CreateDescription("description", text);
264 MakeHeading(description);
266 fDrivesView = new BListView("drives", B_SINGLE_SELECTION_LIST,
267 B_WILL_DRAW | B_FRAME_EVENTS | B_NAVIGABLE | B_FULL_UPDATE_ON_RESIZE);
268 fDrivesView->SetSelectionMessage(new BMessage(kMsgSelectionChanged));
270 BScrollView* scrollView = new BScrollView("scrollView", fDrivesView, 0,
271 false, true);
273 SetLayout(new BGroupLayout(B_VERTICAL));
275 BLayoutBuilder::Group<>((BGroupLayout*)GetLayout())
276 .Add(description, 0.5)
277 .Add(scrollView, 1);
279 _UpdateWizardButtons(NULL);
280 _FillDrivesView(menus);
284 DrivesPage::~DrivesPage()
289 void
290 DrivesPage::PageCompleted()
292 DriveItem* item = _SelectedDriveItem();
294 if (fSettings->ReplaceString("disk", item->Path()) != B_OK)
295 fSettings->AddString("disk", item->Path());
299 void
300 DrivesPage::AttachedToWindow()
302 fDrivesView->SetTarget(this);
306 void
307 DrivesPage::MessageReceived(BMessage* message)
309 switch (message->what) {
310 case kMsgSelectionChanged:
312 _UpdateWizardButtons(_SelectedDriveItem());
313 break;
316 default:
317 WizardPageView::MessageReceived(message);
318 break;
323 /*! Builds the list view items, and adds them to fDriveView.
324 Sets the fHasInstallableItems member to indicate if there
325 are any possible install targets. Automatically
326 selects the boot drive.
328 void
329 DrivesPage::_FillDrivesView(const BootMenuList& menus)
331 const char* selected = fSettings->FindString("disk");
333 BDiskDeviceRoster roster;
334 BDiskDevice device;
335 while (roster.GetNextDevice(&device) == B_OK) {
336 if (device.HasMedia() && !device.IsReadOnly()) {
337 DriveItem* item = new DriveItem(device, menus);
338 if (item->CanBeInstalled())
339 fHasInstallableItems = true;
340 fDrivesView->AddItem(item);
342 if ((selected == NULL && item->IsBootDrive())
343 || (selected != NULL && !strcmp(item->Path(), selected))) {
344 fDrivesView->Select(fDrivesView->CountItems() - 1);
345 _UpdateWizardButtons(item);
352 DriveItem*
353 DrivesPage::_SelectedDriveItem()
355 return (DriveItem*)fDrivesView->ItemAt(fDrivesView->CurrentSelection());
359 void
360 DrivesPage::_UpdateWizardButtons(DriveItem* item)
362 fWizardView->SetPreviousButtonHidden(!fHasInstallableItems);
363 fWizardView->SetPreviousButtonLabel(
364 B_TRANSLATE_COMMENT("Uninstall", "Button"));
365 if (item == NULL) {
366 fWizardView->SetPreviousButtonEnabled(false);
367 fWizardView->SetNextButtonEnabled(false);
368 } else {
369 fWizardView->SetPreviousButtonEnabled(
370 item->CanBeInstalled() && item->IsInstalled());
371 fWizardView->SetNextButtonEnabled(item->CanBeInstalled());
373 fWizardView->SetNextButtonLabel(
374 item->IsInstalled() && item->CanBeInstalled()
375 ? B_TRANSLATE_COMMENT("Update", "Button")
376 : B_TRANSLATE_COMMENT("Install", "Button"));