2 * Copyright 2011, Axel Dörfler, axeld@pinc-software.de.
3 * Distributed under the terms of the MIT License.
7 #include "DrivesPage.h"
10 #include <ControlLook.h>
11 #include <DiskDeviceRoster.h>
12 #include <DiskDevice.h>
13 #include <LayoutBuilder.h>
16 #include <ScrollView.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
{
35 DriveItem(const BDiskDevice
& device
,
36 const BootMenuList
& menus
);
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
; }
47 virtual void DrawItem(BView
* owner
, BRect frame
,
48 bool complete
= false);
49 virtual void Update(BView
* owner
, const BFont
* font
);
57 float fBaselineOffset
;
58 float fSecondBaselineOffset
;
60 status_t fCanBeInstalled
;
65 DriveItem::DriveItem(const BDiskDevice
& device
, const BootMenuList
& menus
)
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");
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),
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
);
89 fSize
= string_for_size(device
.Size(), buffer
, sizeof(buffer
));
93 DriveItem::~DriveItem()
101 DriveItem::IsInstalled() const
108 DriveItem::CanBeInstalled() const
110 return fCanBeInstalled
== B_OK
;
115 DriveItem::IsBootDrive() const
117 return fDrive
->IsBootDrive();
122 DriveItem::DrawItem(BView
* owner
, BRect frame
, bool complete
)
125 owner
->SetDrawingMode(B_OP_ALPHA
);
127 if (IsSelected() || complete
) {
129 owner
->SetHighColor(ui_color(B_LIST_SELECTED_BACKGROUND_COLOR
));
130 owner
->SetLowColor(owner
->HighColor());
132 owner
->SetHighColor(owner
->LowColor());
134 owner
->FillRect(frame
);
140 textColor
= ui_color(B_LIST_SELECTED_ITEM_TEXT_COLOR
);
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
));
147 owner
->SetHighColor(tint_color(textColor
, B_LIGHTEN_1_TINT
));
150 owner
->SetHighColor(ui_color(B_LIST_SELECTED_ITEM_TEXT_COLOR
));
152 owner
->SetHighColor(ui_color(B_LIST_ITEM_TEXT_COLOR
));
157 owner
->MovePenTo(frame
.left
+ 4, frame
.top
+ 1);
158 owner
->DrawBitmap(fIcon
);
161 owner
->MovePenTo(frame
.left
+ 8 + fIcon
->Bounds().Width(),
162 frame
.top
+ fSecondBaselineOffset
);
163 owner
->DrawString(fPath
.Path());
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);
189 switch (fCanBeInstalled
) {
190 case B_PARTITION_TOO_SMALL
:
191 message
= B_TRANSLATE_COMMENT("No space available!",
194 case B_ENTRY_NOT_FOUND
:
195 message
= B_TRANSLATE_COMMENT("Incompatible format!",
199 message
= B_TRANSLATE_COMMENT("Cannot access!",
203 BString truncatedMessage
= message
;
204 owner
->TruncateString(&truncatedMessage
, B_TRUNCATE_END
, messageWidth
);
205 owner
->DrawString(truncatedMessage
);
206 owner
->SetHighColor(highColor
);
208 owner
->SetFont(&ownerFont
);
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());
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
)
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);
252 DrivesPage::DrivesPage(WizardView
* wizardView
, const BootMenuList
& menus
,
253 BMessage
* settings
, const char* name
)
255 WizardPageView(settings
, name
),
256 fWizardView(wizardView
),
257 fHasInstallableItems(false)
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,
273 SetLayout(new BGroupLayout(B_VERTICAL
));
275 BLayoutBuilder::Group
<>((BGroupLayout
*)GetLayout())
276 .Add(description
, 0.5)
279 _UpdateWizardButtons(NULL
);
280 _FillDrivesView(menus
);
284 DrivesPage::~DrivesPage()
290 DrivesPage::PageCompleted()
292 DriveItem
* item
= _SelectedDriveItem();
294 if (fSettings
->ReplaceString("disk", item
->Path()) != B_OK
)
295 fSettings
->AddString("disk", item
->Path());
300 DrivesPage::AttachedToWindow()
302 fDrivesView
->SetTarget(this);
307 DrivesPage::MessageReceived(BMessage
* message
)
309 switch (message
->what
) {
310 case kMsgSelectionChanged
:
312 _UpdateWizardButtons(_SelectedDriveItem());
317 WizardPageView::MessageReceived(message
);
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.
329 DrivesPage::_FillDrivesView(const BootMenuList
& menus
)
331 const char* selected
= fSettings
->FindString("disk");
333 BDiskDeviceRoster roster
;
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
);
353 DrivesPage::_SelectedDriveItem()
355 return (DriveItem
*)fDrivesView
->ItemAt(fDrivesView
->CurrentSelection());
360 DrivesPage::_UpdateWizardButtons(DriveItem
* item
)
362 fWizardView
->SetPreviousButtonHidden(!fHasInstallableItems
);
363 fWizardView
->SetPreviousButtonLabel(
364 B_TRANSLATE_COMMENT("Uninstall", "Button"));
366 fWizardView
->SetPreviousButtonEnabled(false);
367 fWizardView
->SetNextButtonEnabled(false);
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"));