Implemented UI for bootman.

TODO:
- Implement/integrate low level stuff (see BootDrive.h)
  - reading the partition table
  - reading/writing the MBR
  - writing the boot menu
- Open file dialog for selection of backup MBR file
- Write error message in case of I/O errors
- Test



git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@24689 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Michael Pfeiffer 2008-03-30 19:55:13 +00:00
parent e954dc800b
commit 0255f41188
30 changed files with 2507 additions and 1 deletions

View File

@ -24,7 +24,7 @@ if $(INCLUDE_GPL_ADDONS) = 1 {
GPL_ONLY = "" ;
}
BEOS_BIN = "[" addattr alert arp base64 basename bc beep bzip2 cal cat
BEOS_BIN = "[" addattr alert arp base64 basename bc beep bootman bzip2 cal cat
catattr chgrp chmod chop chown chroot cksum clear clockconfig cmp comm
compress cp copyattr $(X86_ONLY)CortexAddOnHost
csplit ctags cut date dc dd desklink df diff diff3 dircolors dirname

View File

@ -3,6 +3,7 @@ SubDir HAIKU_TOP src apps ;
SubInclude HAIKU_TOP src apps 3dmov ;
SubInclude HAIKU_TOP src apps aboutsystem ;
SubInclude HAIKU_TOP src apps bsnow ;
SubInclude HAIKU_TOP src apps bootman ;
SubInclude HAIKU_TOP src apps cdplayer ;
SubInclude HAIKU_TOP src apps clock ;
SubInclude HAIKU_TOP src apps codycam ;

View File

@ -0,0 +1,36 @@
/*
* Copyright 2008, Michael Pfeiffer, laplace@users.sourceforge.net. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef BOOT_DRIVE_H
#define BOOT_DRIVE_H
#include <File.h>
#include <Message.h>
/*
Setting BMessage Format:
"disk" String (path to boot disk)
"partition" array of BMessage:
"show" bool (flag if entry should be added to boot menu)
"name" String (the name as shown in boot menu)
"type" String (short name of file system: bfs, dos)
"path" String (path to partition in /dev/...)
"size" long (size of partition in bytes)
*/
class BootDrive
{
public:
BootDrive() {}
virtual ~BootDrive() {}
virtual bool IsBootMenuInstalled() = 0;
virtual status_t ReadPartitions(BMessage *message) = 0;
virtual status_t WriteBootMenu(BMessage *message) = 0;
virtual status_t SaveMasterBootRecord(BFile *file) = 0;
virtual status_t RestoreMasterBootRecord(BFile *file) = 0;
};
#endif // BOOT_DRIVE_H

View File

@ -0,0 +1,72 @@
/*
* Copyright 2008, Michael Pfeiffer, laplace@users.sourceforge.net. All rights reserved.
* Copyright 2007, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#include "BootManagerWindow.h"
#include <Alert.h>
#include <Application.h>
#include <TextView.h>
static const char* kSignature = "application/x-vnd.Haiku-bootman";
class BootManager : public BApplication {
public:
BootManager();
virtual void ReadyToRun();
virtual void AboutRequested();
};
BootManager::BootManager()
: BApplication(kSignature)
{
}
void
BootManager::ReadyToRun()
{
BootManagerWindow * window = new BootManagerWindow();
window->Show();
}
void
BootManager::AboutRequested()
{
BAlert *alert = new BAlert("about", "Haiku Boot Manager\n"
"\twritten by Michael Pfeiffer\n"
"\tCopyright 2008, Haiku Inc.\n", "Ok");
BTextView *view = alert->TextView();
BFont font;
view->SetStylable(true);
view->GetFont(&font);
font.SetSize(18);
font.SetFace(B_BOLD_FACE);
view->SetFontAndColor(0, 18, &font);
alert->Go();
}
// #pragma mark -
int
main(int /*argc*/, char** /*argv*/)
{
BootManager application;
application.Run();
return 0;
}

View File

@ -0,0 +1,388 @@
/*
* Copyright 2008, Michael Pfeiffer, laplace@users.sourceforge.net. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#include "BootManagerController.h"
#include "WizardView.h"
#include "EntryPage.h"
#include "PartitionsPage.h"
#include "DefaultPartitionPage.h"
#include "DescriptionPage.h"
#include "FileSelectionPage.h"
// TODO remove
#define USE_TEST_BOOT_DRIVE 1
#if USE_TEST_BOOT_DRIVE
#include "TestBootDrive.h"
#endif
#include <Alert.h>
#include <Application.h>
#include <File.h>
#include <FindDirectory.h>
#include <Path.h>
#include <String.h>
BootManagerController::BootManagerController()
{
#if USE_TEST_BOOT_DRIVE
fBootDrive = new TestBootDrive();
#else
// TODO implement
fBootDrive = NULL;
#endif
// set defaults
fSettings.AddBool("install", true);
fSettings.AddInt32("defaultPartition", 0);
fSettings.AddInt32("timeout", -1);
BPath path;
if (find_directory(B_USER_SETTINGS_DIRECTORY, &path, true) == B_OK) {
path.Append("bootman/MBR");
fSettings.AddString("file", path.Path());
} else {
fSettings.AddString("file", "");
}
fBootDrive->ReadPartitions(&fSettings);
}
BootManagerController::~BootManagerController()
{
}
int32
BootManagerController::InitialState()
{
return kStateEntry;
}
int32
BootManagerController::NextState(int32 state)
{
switch (state) {
case kStateEntry:
{
bool install;
fSettings.FindBool("install", &install);
if (install) {
if (fBootDrive->IsBootMenuInstalled())
return kStatePartitions;
else
return kStateSaveMBR;
}
else
return kStateUninstall;
}
case kStateSaveMBR:
if (_SaveMBR())
return kStateMBRSaved;
break;
case kStateMBRSaved:
return kStatePartitions;
case kStatePartitions:
if (_HasSelectedPartitions())
return kStateDefaultPartitions;
break;
case kStateDefaultPartitions:
return kStateInstallSummary;
case kStateInstallSummary:
if (_WriteBootMenu())
return kStateInstalled;
break;
case kStateInstalled:
be_app->PostMessage(B_QUIT_REQUESTED);
break;
case kStateUninstall:
if (_RestoreMBR())
return kStateUninstalled;
break;
case kStateUninstalled:
be_app->PostMessage(B_QUIT_REQUESTED);
break;
}
// cannot leave the current state/page
return -1;
}
bool
BootManagerController::_HasSelectedPartitions()
{
BMessage message;
for (int32 i = 0; fSettings.FindMessage("partition", i, &message) == B_OK; i ++) {
bool show;
if (message.FindBool("show", &show) == B_OK && show)
return true;
}
BAlert* alert = new BAlert("info", "At least one partition must be selected!",
"OK");
alert->Go();
return false;
}
bool
BootManagerController::_WriteBootMenu()
{
BAlert* alert = new BAlert("confirm", "About to write the boot menu "
"to disk. Are you sure you want to continue?", "Write Boot Menu", "Back",
NULL, B_WIDTH_AS_USUAL, B_WARNING_ALERT);
if (alert->Go() == 1)
return false;
status_t status = fBootDrive->WriteBootMenu(&fSettings);
fSettings.RemoveName("installStatus");
fSettings.AddInt32("installStatus", status);
return true;
}
bool
BootManagerController::_SaveMBR()
{
BFile file("", B_READ_WRITE | B_CREATE_FILE | B_ERASE_FILE);
status_t state = fBootDrive->SaveMasterBootRecord(&file);
fSettings.RemoveName("saveMBRStatus");
fSettings.AddInt32("saveMBRStatus", state);
return true;
}
bool
BootManagerController::_RestoreMBR()
{
BString disk;
BString path;
fSettings.FindString("disk", &disk);
fSettings.FindString("file", &path);
BString message;
message << "About to restore the Master Boot Record (MBR) of "
<< disk << " from " << path << ". "
"Do you wish to continue?";
BAlert* alert = new BAlert("confirm", message.String(),
"Restore MBR", "Back",
NULL, B_WIDTH_AS_USUAL, B_WARNING_ALERT);
if (alert->Go() == 1)
return false;
BFile file(path.String(), B_READ_ONLY);
status_t state = fBootDrive->RestoreMasterBootRecord(&file);
fSettings.RemoveName("restoreMBRStatus");
fSettings.AddInt32("restoreMBRStatus", state);
return true;
}
WizardPageView*
BootManagerController::CreatePage(int32 state, WizardView* wizard)
{
WizardPageView* page = NULL;
BRect frame = wizard->PageFrame();
switch (state) {
case kStateEntry:
page = new EntryPage(&fSettings, frame, "entry");
wizard->SetPreviousButtonHidden(true);
break;
case kStateSaveMBR:
page = _CreateSaveMBRPage(frame);
wizard->SetPreviousButtonHidden(false);
break;
case kStateMBRSaved:
page = _CreateMBRSavedPage(frame);
break;
case kStatePartitions:
page = new PartitionsPage(&fSettings, frame, "partitions");
wizard->SetPreviousButtonHidden(false);
break;
case kStateDefaultPartitions:
page = new DefaultPartitionPage(&fSettings, frame, "default");
break;
case kStateInstallSummary:
page = _CreateInstallSummaryPage(frame);
wizard->SetNextButtonLabel("Next");
break;
case kStateInstalled:
page = _CreateInstalledPage(frame);
wizard->SetNextButtonLabel("Done");
break;
case kStateUninstall:
page = _CreateUninstallPage(frame);
wizard->SetPreviousButtonHidden(false);
wizard->SetNextButtonLabel("Next");
break;
case kStateUninstalled:
// TODO prevent overwriting MBR after clicking "Previous"
page = _CreateUninstalledPage(frame);
wizard->SetNextButtonLabel("Done");
break;
}
return page;
}
WizardPageView*
BootManagerController::_CreateSaveMBRPage(BRect frame)
{
BString description;
BString disk;
fSettings.FindString("disk", &disk);
description <<
"Backup Master Boot Record\n\n"
"The Master Boot Record (MBR) of the boot device:\n"
"\t" << disk << "\n"
"will now be saved to disk. Please select a file to "
"save the MBR into.\n\n"
"If something goes wrong with the installation or if "
"you later wish to remove the boot menu, simply run the "
"bootman program and choose to 'Uninstall' option.";
FileSelectionPage* page = new FileSelectionPage(&fSettings, frame, "saveMBR", description.String());
return page;
}
WizardPageView*
BootManagerController::_CreateMBRSavedPage(BRect frame)
{
BString description;
BString file;
fSettings.FindString("file", &file);
description <<
"Old Master Boot Record Saved\n\n"
"The old Master Boot Record was successfully save to "
<< file << ".\n";
DescriptionPage* page = new DescriptionPage(frame, "summary", description.String(), true);
return page;
}
WizardPageView*
BootManagerController::_CreateInstallSummaryPage(BRect frame)
{
BString description;
BString disk;
fSettings.FindString("disk", &disk);
description <<
"Summary\n\n"
"About to write the following boot menu to the boot disk "
"(" << disk << "). Please verify the information below "
"before continuing.\n\n";
BMessage message;
for (int32 i = 0; fSettings.FindMessage("partition", i, &message) == B_OK; i ++) {
bool show;
if (message.FindBool("show", &show) != B_OK || !show)
continue;
BString name;
BString path;
message.FindString("name", &name);
message.FindString("path", &path);
description << name << "\t(" << path << ")\n";
}
DescriptionPage* page = new DescriptionPage(frame, "summary", description.String(), true);
return page;
}
WizardPageView*
BootManagerController::_CreateInstalledPage(BRect frame)
{
const char* description;
int32 status;
fSettings.FindInt32("installStatus", &status);
if (status == B_OK) {
description = "Installation Boot Menu Completed\n\n"
"The boot manager has been successfully installed "
"on your system.";
} else {
// TODO
description = "Installation Boot Menu Failed\n\n"
"TODO";
}
DescriptionPage* page = new DescriptionPage(frame, "done", description, true);
return page;
}
WizardPageView*
BootManagerController::_CreateUninstallPage(BRect frame)
{
BString description;
description <<
"Uninstall Boot Manager\n\n"
"Please locate the Master Boot Record (MBR) save file to "
"restore from. This is the file that was created when the "
"boot manager was first installed.";
FileSelectionPage* page = new FileSelectionPage(&fSettings, frame, "restoreMBR", description.String());
return page;
}
WizardPageView*
BootManagerController::_CreateUninstalledPage(BRect frame)
{
BString description;
BString disk;
BString file;
fSettings.FindString("disk", &disk);
fSettings.FindString("file", &file);
int32 status;
fSettings.FindInt32("restoreMBRStatus", &status);
if (status == B_OK) {
description <<
"Uninstallation Boot Menu Completed\n\n"
"The Master Boot Record of the boot device "
"(" << disk << ") has been successfully restored from "
<< file << ".";
} else {
// TODO
description <<
"Uninstallation Boot Menu Failed\n\n"
"TODO";
}
DescriptionPage* page = new DescriptionPage(frame, "summary", description.String(), true);
return page;
}

View File

@ -0,0 +1,76 @@
/*
* Copyright 2008, Michael Pfeiffer, laplace@users.sourceforge.net. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef BOOT_MANAGER_CONTROLLER_H
#define BOOT_MANAGER_CONTROLLER_H
#include "WizardController.h"
#include <Message.h>
class BootDrive;
class WizardView;
class WizardPageView;
class BRect;
/*
Remainder of Settings Message Format:
(See also BootDrive.h)
"install" bool (whether install or uninstall should be performed)
"file" String (the file where the backup of the MBR is saved)
"defaultPartition" int32 (index of default partition)
"timeout" int32 (timeout in seconds, -1 for no timeout)
"installStatus" int32 (status_t)
"saveMBRStatus" int32 (status_t)
"restoreMBRStatus" int32 (status_t)
*/
class BootManagerController : public WizardController
{
public:
BootManagerController();
virtual ~BootManagerController();
protected:
virtual int32 InitialState();
virtual int32 NextState(int32 state);
virtual WizardPageView* CreatePage(int32 state, WizardView* wizard);
private:
enum State {
kStateEntry,
// Install states
kStateSaveMBR,
kStateMBRSaved,
kStatePartitions,
kStateDefaultPartitions,
kStateInstallSummary,
kStateInstalled,
// Uninstall states
kStateUninstall,
kStateUninstalled
};
bool _HasSelectedPartitions();
bool _WriteBootMenu();
bool _SaveMBR();
bool _RestoreMBR();
WizardPageView* _CreateSaveMBRPage(BRect frame);
WizardPageView* _CreateMBRSavedPage(BRect frame);
WizardPageView* _CreateInstallSummaryPage(BRect frame);
WizardPageView* _CreateInstalledPage(BRect frame);
WizardPageView* _CreateUninstallPage(BRect frame);
WizardPageView* _CreateUninstalledPage(BRect frame);
BMessage fSettings;
BootDrive* fBootDrive;
};
#endif // BOOT_MANAGER_CONTROLLER_H

View File

@ -0,0 +1,98 @@
/*
* Copyright 2008, Michael Pfeiffer, laplace@users.sourceforge.net. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#include "BootManagerWindow.h"
#include "WizardView.h"
#include "EntryPage.h"
#include "PartitionsPage.h"
#include "DefaultPartitionPage.h"
#include <Application.h>
#include <Screen.h>
#include <math.h>
BootManagerWindow::BootManagerWindow()
: BWindow(BRect(100, 100, 500, 400), "Boot Manager", B_TITLED_WINDOW,
B_ASYNCHRONOUS_CONTROLS)
, fWindowCentered(false)
{
float minWidth, maxWidth, minHeight, maxHeight;
GetSizeLimits(&minWidth, &maxWidth, &minHeight, &maxHeight);
SetSizeLimits(250, maxWidth, 250, maxHeight);
fWizardView = new WizardView(Bounds(), "wizard", B_FOLLOW_ALL);
AddChild(fWizardView);
fController.Initialize(fWizardView);
}
BootManagerWindow::~BootManagerWindow()
{
}
void
BootManagerWindow::MessageReceived(BMessage* msg)
{
switch (msg->what) {
case kMessageNext:
fController.Next(fWizardView);
break;
case kMessagePrevious:
fController.Previous(fWizardView);
break;
default:
BWindow::MessageReceived(msg);
}
}
bool
BootManagerWindow::QuitRequested()
{
be_app->PostMessage(B_QUIT_REQUESTED);
return true;
}
void
BootManagerWindow::WindowActivated(bool active)
{
_CenterWindow();
}
void
BootManagerWindow::_CenterWindow()
{
if (fWindowCentered)
return;
fWindowCentered = true;
BScreen screen(this);
if (!screen.IsValid())
return;
BRect frame = screen.Frame();
BRect windowFrame = Frame();
float left = floor((frame.Width() - windowFrame.Width()) / 2);
float top = floor((frame.Height() - windowFrame.Height()) / 2);
if (left < 20)
left = 20;
if (top < 20)
top = 20;
MoveTo(left, top);
}

View File

@ -0,0 +1,36 @@
/*
* Copyright 2008, Michael Pfeiffer, laplace@users.sourceforge.net. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef BOOT_MANAGER_WINDOW_H
#define BOOT_MANAGER_WINDOW_H
#include <Window.h>
#include "BootManagerController.h"
class WizardView;
class BootManagerWindow : public BWindow
{
public:
BootManagerWindow();
virtual ~BootManagerWindow();
virtual void MessageReceived(BMessage* message);
virtual bool QuitRequested();
virtual void WindowActivated(bool active);
private:
void _CenterWindow();
bool fWindowCentered;
BootManagerController fController;
WizardView* fWizardView;
};
#endif // BOOT_MANAGER_WINDOW_H

View File

@ -0,0 +1,202 @@
/*
* Copyright 2008, Michael Pfeiffer, laplace@users.sourceforge.net. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#include "DefaultPartitionPage.h"
#include <Message.h>
#include <MenuItem.h>
#include <MenuField.h>
#include <PopUpMenu.h>
#include <RadioButton.h>
#include <TextView.h>
#include <string.h>
#include <String.h>
const uint32 kMsgPartition = 'part';
const uint32 kMsgTimeout = 'time';
DefaultPartitionPage::DefaultPartitionPage(BMessage* settings, BRect frame, const char* name)
: WizardPageView(settings, frame, name, B_FOLLOW_ALL,
B_WILL_DRAW | B_FRAME_EVENTS | B_FULL_UPDATE_ON_RESIZE)
{
_BuildUI();
}
DefaultPartitionPage::~DefaultPartitionPage()
{
}
void
DefaultPartitionPage::FrameResized(float width, float height)
{
WizardPageView::FrameResized(width, height);
_Layout();
}
void
DefaultPartitionPage::AttachedToWindow()
{
fDefaultPartition->Menu()->SetTargetForItems(this);
fWait0->SetTarget(this);
fWait5->SetTarget(this);
fWait10->SetTarget(this);
fWait15->SetTarget(this);
}
void
DefaultPartitionPage::MessageReceived(BMessage* msg)
{
switch (msg->what) {
case kMsgPartition:
{
int32 index;
msg->FindInt32("index", &index);
fSettings->ReplaceInt32("defaultPartition", index);
}
break;
case kMsgTimeout:
{
int32 timeout;
msg->FindInt32("timeout", &timeout);
fSettings->ReplaceInt32("timeout", timeout);
}
break;
default:
WizardPageView::MessageReceived(msg);
}
}
static const float kTextDistance = 10;
void
DefaultPartitionPage::_BuildUI()
{
BRect rect(Bounds());
fDescription = CreateDescription(rect, "description",
"Default Partition\n\n"
"Please specify a default partition and a timeout.\n"
"The boot menu will load the default partition after "
"the timeout unless you select another partition. You "
"can also have the boot menu wait indefinitely for you "
"to select a partition."
);
MakeHeading(fDescription);
AddChild(fDescription);
LayoutDescriptionVertically(fDescription);
rect.top = fDescription->Frame().bottom + kTextDistance;
fDescription->SetViewColor(255, 0, 0);
BPopUpMenu* popUpMenu = _CreatePopUpMenu();
fDefaultPartition = new BMenuField(rect, "partitions", "Default Partition:",
popUpMenu);
float divider = be_plain_font->StringWidth(fDefaultPartition->Label()) + 3;
fDefaultPartition->SetDivider(divider);
AddChild(fDefaultPartition);
fDefaultPartition->ResizeToPreferred();
fDefaultPartition->SetViewColor(0, 255, 0);
rect.top = fDefaultPartition->Frame().bottom + kTextDistance;
int32 timeout;
fSettings->FindInt32("timeout", &timeout);
fWait0 = _CreateWaitRadioButton(rect, "wait0", "Wait Indefinitely", -1, timeout);
fWait0->SetViewColor(0, 0, 255);
fWait5 = _CreateWaitRadioButton(rect, "wait5", "Wait 5 Seconds", 5, timeout);
fWait10 = _CreateWaitRadioButton(rect, "wait10", "Wait 10 Seconds", 10, timeout);
fWait15 = _CreateWaitRadioButton(rect, "wait15", "Wait 15 Seconds", 15, timeout);
_Layout();
}
BPopUpMenu*
DefaultPartitionPage::_CreatePopUpMenu()
{
int32 defaultPartitionIndex;
fSettings->FindInt32("defaultPartition", &defaultPartitionIndex);
BMenuItem* selectedItem = NULL;
int32 selectedItemIndex = 0;
BPopUpMenu* menu = new BPopUpMenu("Partitions");
BMessage message;
for (int32 i = 0; fSettings->FindMessage("partition", i, &message) == B_OK; i ++) {
bool show;
if (message.FindBool("show", &show) != B_OK || !show)
continue;
BString name;
message.FindString("name", &name);
BMessage* msg = new BMessage(kMsgPartition);
msg->AddInt32("index", i);
BMenuItem* item = new BMenuItem(name.String(), msg);
menu->AddItem(item);
if (defaultPartitionIndex == i || selectedItem == NULL) {
selectedItem = item;
selectedItemIndex = i;
}
}
fSettings->ReplaceInt32("defaultPartition", selectedItemIndex);
selectedItem->SetMarked(true);
return menu;
}
BRadioButton*
DefaultPartitionPage::_CreateWaitRadioButton(BRect rect, const char* name, const char* label, int32 timeout,
int32 defaultTimeout)
{
BMessage* msg = new BMessage(kMsgTimeout);
msg->AddInt32("timeout", timeout);
BRadioButton* button = new BRadioButton(rect, name, label, msg);
AddChild(button);
button->ResizeToPreferred();
if (timeout == defaultTimeout)
button->SetValue(1);
return button;
}
#include <stdio.h>
void
DefaultPartitionPage::_Layout()
{
LayoutDescriptionVertically(fDescription);
float left = fDefaultPartition->Frame().left;
float top = fDescription->Frame().bottom + kTextDistance;
printf("top %f\n", top);
BView* controls[] = {
fDefaultPartition,
fWait0,
fWait5,
fWait10,
fWait15
};
for (int i = 0; i < 5; i ++) {
printf("*");
BView* view = controls[i];
view->MoveTo(left, top);
top = view->Frame().bottom + 3;
}
printf("\n");
}

View File

@ -0,0 +1,45 @@
/*
* Copyright 2008, Michael Pfeiffer, laplace@users.sourceforge.net. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef DEFAULT_PARTITON_PAGE_H
#define DEFAULT_PARTITON_PAGE_H
#include "WizardPageView.h"
class BMenuField;
class BMessage;
class BRadioButton;
class BPopUpMenu;
class BTextView;
class DefaultPartitionPage : public WizardPageView
{
public:
DefaultPartitionPage(BMessage* settings, BRect frame, const char* name);
virtual ~DefaultPartitionPage();
virtual void FrameResized(float width, float height);
virtual void AttachedToWindow();
virtual void MessageReceived(BMessage* msg);
private:
void _BuildUI();
BPopUpMenu* _CreatePopUpMenu();
BRadioButton* _CreateWaitRadioButton(BRect frame, const char* name, const char* label,
int32 timeout, int32 defaultTimeout);
void _Layout();
BTextView* fDescription;
BMenuField* fDefaultPartition;
BRadioButton* fWait0;
BRadioButton* fWait5;
BRadioButton* fWait10;
BRadioButton* fWait15;
};
#endif // DEFAULT_PARTITON_PAGE_H

View File

@ -0,0 +1,60 @@
/*
* Copyright 2008, Michael Pfeiffer, laplace@users.sourceforge.net. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#include "DescriptionPage.h"
#include <RadioButton.h>
#include <TextView.h>
#include <string.h>
DescriptionPage::DescriptionPage(BRect frame, const char* name,
const char* description, bool hasHeading)
: WizardPageView(NULL, frame, name, B_FOLLOW_ALL,
B_WILL_DRAW | B_FRAME_EVENTS | B_FULL_UPDATE_ON_RESIZE)
{
_BuildUI(description, hasHeading);
}
DescriptionPage::~DescriptionPage()
{
}
void
DescriptionPage::FrameResized(float width, float height)
{
WizardPageView::FrameResized(width, height);
_Layout();
}
static const float kTextDistance = 10;
void
DescriptionPage::_BuildUI(const char* description, bool hasHeading)
{
BRect rect(Bounds());
fDescription = CreateDescription(rect, "description", description);
if (hasHeading)
MakeHeading(fDescription);
fDescription->SetTabWidth(85);
AddChild(fDescription);
_Layout();
}
void
DescriptionPage::_Layout()
{
LayoutDescriptionVertically(fDescription);
}

View File

@ -0,0 +1,30 @@
/*
* Copyright 2008, Michael Pfeiffer, laplace@users.sourceforge.net. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef DESCRIPTION_PAGE_H
#define DESCRIPTION_PAGE_H
#include "WizardPageView.h"
class BTextView;
class DescriptionPage : public WizardPageView
{
public:
DescriptionPage(BRect frame, const char* name, const char* description, bool hasHeading);
virtual ~DescriptionPage();
virtual void FrameResized(float width, float height);
private:
void _BuildUI(const char* description, bool hasHeading);
void _Layout();
BTextView* fDescription;
};
#endif // DESCRIPTION_PAGE_H

View File

@ -0,0 +1,108 @@
/*
* Copyright 2008, Michael Pfeiffer, laplace@users.sourceforge.net. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#include "EntryPage.h"
#include <RadioButton.h>
#include <TextView.h>
#include <string.h>
EntryPage::EntryPage(BMessage* settings, BRect frame, const char* name)
: WizardPageView(settings, frame, name, B_FOLLOW_ALL,
B_WILL_DRAW | B_FRAME_EVENTS | B_FULL_UPDATE_ON_RESIZE)
{
_BuildUI();
}
EntryPage::~EntryPage()
{
}
void
EntryPage::FrameResized(float width, float height)
{
WizardPageView::FrameResized(width, height);
_Layout();
}
void
EntryPage::PageCompleted()
{
fSettings->ReplaceBool("install", fInstall->Value() != 0);
}
static const float kTextDistance = 10;
void
EntryPage::_BuildUI()
{
BRect rect(Bounds());
fInstall = new BRadioButton(rect, "install",
"",
new BMessage('null'));
AddChild(fInstall);
fInstall->ResizeToPreferred();
BRect textRect(rect);
textRect.left = fInstall->Frame().right + kTextDistance;
fInstallText = CreateDescription(textRect, "installText",
"Install Boot Menu\n\n"
"Choose this option to install a boot menu, "
"allowing you to select which operating "
"system to boot when you turn on your "
"computer.\n");
MakeHeading(fInstallText);
AddChild(fInstallText);
fUninstall = new BRadioButton(rect, "uninstall",
"",
new BMessage('null'));
AddChild(fUninstall);
fUninstall->ResizeToPreferred();
fUninstallText = CreateDescription(textRect, "uninstallText",
"Uninstall Boot Menu\n\n"
"Choose this option to remove the boot menu "
"previously installed by this program.\n"
);
MakeHeading(fUninstallText);
AddChild(fUninstallText);
bool install;
fSettings->FindBool("install", &install);
if (install)
fInstall->SetValue(1);
else
fUninstall->SetValue(1);
_Layout();
}
void
EntryPage::_Layout()
{
LayoutDescriptionVertically(fInstallText);
float left = fUninstall->Frame().left;
float top = fInstallText->Frame().bottom;
fUninstall->MoveTo(left, top);
left = fUninstallText->Frame().left;
fUninstallText->MoveTo(left, top);
LayoutDescriptionVertically(fUninstallText);
}

View File

@ -0,0 +1,36 @@
/*
* Copyright 2008, Michael Pfeiffer, laplace@users.sourceforge.net. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef ENTRY_PAGE_H
#define ENTRY_PAGE_H
#include "WizardPageView.h"
class BRadioButton;
class BTextView;
class EntryPage : public WizardPageView
{
public:
EntryPage(BMessage* settings, BRect frame, const char* name);
virtual ~EntryPage();
virtual void FrameResized(float width, float height);
virtual void PageCompleted();
private:
void _BuildUI();
void _Layout();
BRadioButton* fInstall;
BTextView* fInstallText;
BRadioButton* fUninstall;
BTextView* fUninstallText;
};
#endif // ENTRY_PAGE_H

View File

@ -0,0 +1,97 @@
/*
* Copyright 2008, Michael Pfeiffer, laplace@users.sourceforge.net. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#include "FileSelectionPage.h"
#include <Button.h>
#include <RadioButton.h>
#include <TextControl.h>
#include <TextView.h>
#include <string.h>
#include <String.h>
FileSelectionPage::FileSelectionPage(BMessage* settings, BRect frame, const char* name,
const char* description)
: WizardPageView(settings, frame, name, B_FOLLOW_ALL,
B_WILL_DRAW | B_FRAME_EVENTS | B_FULL_UPDATE_ON_RESIZE)
{
_BuildUI(description);
}
FileSelectionPage::~FileSelectionPage()
{
}
void
FileSelectionPage::FrameResized(float width, float height)
{
WizardPageView::FrameResized(width, height);
_Layout();
}
void
FileSelectionPage::PageCompleted()
{
fSettings->ReplaceString("file", fFile->Text());
}
const float kTextDistance = 10;
const float kFileButtonDistance = 10;
void
FileSelectionPage::_BuildUI(const char* description)
{
BRect rect(Bounds());
fDescription = CreateDescription(rect, "description", description);
MakeHeading(fDescription);
AddChild(fDescription);
BString file;
fSettings->FindString("file", &file);
// TODO align text and button
fFile = new BTextControl(rect, "file", "File:", file.String(), new BMessage());
fFile->SetDivider(be_plain_font->StringWidth(fFile->Label()) + 5);
AddChild(fFile);
// TODO open file dialog
fSelect = new BButton(rect, "select", "Select", new BMessage(),
B_FOLLOW_RIGHT);
fSelect->ResizeToPreferred();
float left = rect.right - fSelect->Frame().Width();
fSelect->MoveTo(left, 0);
AddChild(fSelect);
_Layout();
}
void
FileSelectionPage::_Layout()
{
LayoutDescriptionVertically(fDescription);
float left = fFile->Frame().left;
float top = fDescription->Frame().bottom + kTextDistance;
fFile->MoveTo(left, top);
float width = fSelect->Frame().left - kFileButtonDistance - left;
float height = fFile->Frame().Height();
fFile->ResizeTo(width, height);
left = fSelect->Frame().left;
fSelect->MoveTo(left, top);
}

View File

@ -0,0 +1,36 @@
/*
* Copyright 2008, Michael Pfeiffer, laplace@users.sourceforge.net. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef FILE_SELECTION_PAGE_H
#define FILE_SELECTION_PAGE_H
#include "WizardPageView.h"
class BButton;
class BTextControl;
class BTextView;
class FileSelectionPage : public WizardPageView
{
public:
FileSelectionPage(BMessage* settings, BRect frame, const char* name, const char* description);
virtual ~FileSelectionPage();
virtual void FrameResized(float width, float height);
virtual void PageCompleted();
private:
void _BuildUI(const char* description);
void _Layout();
BTextView* fDescription;
BTextControl* fFile;
BButton* fSelect;
};
#endif // FILE_SELECTION_PAGE_H

21
src/apps/bootman/Jamfile Normal file
View File

@ -0,0 +1,21 @@
SubDir HAIKU_TOP src apps bootman ;
SetSubDirSupportedPlatformsBeOSCompatible ;
Application bootman :
BootManager.cpp
BootManagerController.cpp
BootManagerWindow.cpp
DefaultPartitionPage.cpp
DescriptionPage.cpp
EntryPage.cpp
FileSelectionPage.cpp
PartitionsPage.cpp
TestBootDrive.cpp
UninstallPage.cpp
WizardController.cpp
WizardPageView.cpp
WizardView.cpp
: be
: bootman.rdef
;

View File

@ -0,0 +1,337 @@
/*
* Copyright 2008, Michael Pfeiffer, laplace@users.sourceforge.net. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#include "PartitionsPage.h"
#include <CheckBox.h>
#include <RadioButton.h>
#include <ScrollView.h>
#include <StringView.h>
#include <TextControl.h>
#include <TextView.h>
#include <string.h>
#include <String.h>
const uint32 kMessageShow = 'show';
const uint32 kMessageName = 'name';
PartitionsPage::PartitionsPage(BMessage* settings, BRect frame, const char* name)
: WizardPageView(settings, frame, name, B_FOLLOW_ALL,
B_WILL_DRAW | B_FRAME_EVENTS | B_FULL_UPDATE_ON_RESIZE)
{
_BuildUI();
}
PartitionsPage::~PartitionsPage()
{
}
void
PartitionsPage::PageCompleted()
{
int32 i;
const int32 n = fPartitions->CountChildren();
for (i = 0; i < n; i ++) {
BView* row = fPartitions->ChildAt(i);
int32 j;
const int32 m = row->CountChildren();
for (j = 0; j < m; j ++) {
BView* child = row->ChildAt(j);
BControl* control = dynamic_cast<BControl*>(child);
if (control == NULL)
continue;
int32 index;
BMessage* message = control->Message();
if (message == NULL || message->FindInt32("index", &index) != B_OK)
continue;
BMessage partition;
if (fSettings->FindMessage("partition", index, &partition) != B_OK)
continue;
if (kMessageShow == message->what) {
partition.ReplaceBool("show", control->Value() == 1);
} else if (kMessageName == message->what &&
dynamic_cast<BTextControl*>(control) != NULL) {
partition.ReplaceString("name", ((BTextControl*)control)->Text());
}
fSettings->ReplaceMessage("partition", index, &partition);
}
}
}
void
PartitionsPage::FrameResized(float width, float height)
{
WizardPageView::FrameResized(width, height);
_Layout();
}
static const float kTextDistance = 10;
void
PartitionsPage::_BuildUI()
{
BRect rect(Bounds());
fDescription = CreateDescription(rect, "description",
"Partitions\n\n"
"The following partitions were detected. Please "
"check the box next to the partitions to be included "
"in the boot menu. You can also set the names of the "
"partitions as you would like them to appear in the "
"boot menu."
);
MakeHeading(fDescription);
AddChild(fDescription);
LayoutDescriptionVertically(fDescription);
rect.left = fDescription->Frame().left + 1;
rect.top = fDescription->Frame().bottom + kTextDistance;
rect.right -= B_V_SCROLL_BAR_WIDTH;
rect.bottom -= B_H_SCROLL_BAR_HEIGHT + 3;
fPartitions = new BView(rect, "partitions", B_FOLLOW_ALL,
B_WILL_DRAW);
fPartitionsScrollView = new BScrollView("scrollView", fPartitions,
B_FOLLOW_ALL,
0,
true, true);
fPartitionsScrollView->SetViewColor(ViewColor());
AddChild(fPartitionsScrollView);
_FillPartitionsView(fPartitions);
_Layout();
}
void
PartitionsPage::_Layout()
{
LayoutDescriptionVertically(fDescription);
float left = fPartitionsScrollView->Frame().left;
float top = fDescription->Frame().bottom + kTextDistance;
fPartitionsScrollView->MoveTo(left, top);
float width = fPartitionsScrollView->Frame().Width();
float height = Bounds().bottom - top;
fPartitionsScrollView->ResizeTo(width, height);
BScrollBar* scrollbar = fPartitionsScrollView->ScrollBar(B_HORIZONTAL);
float max = fPartitionsWidth - fPartitions->Bounds().IntegerWidth();
if (max < 0)
max = 0;
scrollbar->SetRange(0, max);
scrollbar = fPartitionsScrollView->ScrollBar(B_VERTICAL);
max = fPartitionsHeight - fPartitions->Bounds().IntegerHeight();
if (max < 0)
max = 0;
scrollbar->SetRange(0, max);
}
const rgb_color kOddRowColor = {224, 255, 224};
const rgb_color kEvenRowColor = {224, 224, 255};
void
PartitionsPage::_FillPartitionsView(BView* view)
{
const int32 inset = 1;
font_height fontHeight;
be_plain_font->GetHeight(&fontHeight);
const int32 height = (int32)(6 + 2*inset + fontHeight.ascent + fontHeight.descent);
const int32 kDistance = (int32)(ceil(be_plain_font->StringWidth("x")));
// show | name | type | size | path
int32 showWidth = 0;
int32 nameWidth = 0;
int32 typeWidth = 0;
int32 sizeWidth = 0;
int32 pathWidth = 0;
_ComputeColumnWidths(showWidth, nameWidth, typeWidth, sizeWidth, pathWidth);
int32 totalWidth = showWidth + nameWidth + typeWidth + sizeWidth + pathWidth +
2*inset + 4 * kDistance;
int32 rowNumber = 0;
BRect frame(view->Bounds());
frame.bottom = frame.top + height;
frame.right = frame.left + 65000;
BMessage message;
for (int32 i = 0; fSettings->FindMessage("partition", i, &message) == B_OK; i ++, rowNumber ++) {
// get partition data
bool show;
BString name;
BString type;
BString path;
int64 size;
message.FindBool("show", &show);
message.FindString("name", &name);
message.FindString("type", &type);
message.FindString("path", &path);
message.FindInt64("size", &size);
// create row for partition data
BView* row = new BView(frame, "row", B_FOLLOW_TOP | B_FOLLOW_LEFT, 0);
row->SetViewColor(((rowNumber % 2) == 0) ? kEvenRowColor : kOddRowColor);
view->AddChild(row);
frame.OffsetBy(0, height);
// box
BRect rect(row->Bounds());
rect.InsetBy(inset, inset);
rect.right = rect.left + showWidth;
BCheckBox* checkBox = new BCheckBox(rect, "show", "",
_CreateControlMessage(kMessageShow, i));
if (show)
checkBox->SetValue(1);
row->AddChild(checkBox);
rect.OffsetBy(showWidth + kDistance, 0);
// name
rect.right = rect.left + nameWidth;
BTextControl* nameControl = new BTextControl(rect, "name", "", name.String(),
_CreateControlMessage(kMessageName, i));
nameControl->SetDivider(0);
row->AddChild(nameControl);
rect.OffsetBy(nameWidth + kDistance, 0);
// type
rect.right = rect.left + typeWidth;
BStringView* typeView = new BStringView(rect, "type", type.String());
row->AddChild(typeView);
rect.OffsetBy(typeWidth + kDistance, 0);
// size
BString sizeText;
_CreateSizeText(size, &sizeText);
rect.right = rect.left + sizeWidth;
BStringView* sizeView = new BStringView(rect, "type", sizeText.String());
sizeView->SetAlignment(B_ALIGN_RIGHT);
row->AddChild(sizeView);
rect.OffsetBy(sizeWidth + kDistance, 0);
// path
rect.right = rect.left + pathWidth;
BStringView* pathView = new BStringView(rect, "path", path.String());
row->AddChild(pathView);
}
fPartitionsWidth = totalWidth;
fPartitionsHeight = frame.Height();
}
void
PartitionsPage::_ComputeColumnWidths(int32& showWidth, int32& nameWidth,
int32& typeWidth, int32& sizeWidth, int32& pathWidth)
{
BCheckBox checkBox(BRect(0, 0, 100, 100), "show", "", new BMessage());
checkBox.ResizeToPreferred();
showWidth = checkBox.Bounds().IntegerWidth();
// reserve space for about 16 characters
nameWidth = (int32)ceil(be_plain_font->StringWidth("oooooooooooooooo"));
const int32 kTextControlInsets = 6;
const int32 kStringViewInsets = 2;
BMessage message;
for (int32 i = 0; fSettings->FindMessage("partition", i, &message) == B_OK; i ++) {
// get partition data
BString name;
BString type;
BString path;
int64 size;
message.FindString("name", &name);
message.FindString("type", &type);
message.FindString("path", &path);
message.FindInt64("size", &size);
BString sizeText;
_CreateSizeText(size, &sizeText);
int32 width = (int32)ceil(be_plain_font->StringWidth(name.String())) +
kTextControlInsets;
if (nameWidth < width)
nameWidth = width;
width = (int32)ceil(be_plain_font->StringWidth(type.String())) +
kStringViewInsets;
if (typeWidth < width)
typeWidth = width;
width = (int32)ceil(be_plain_font->StringWidth(path.String())) +
kStringViewInsets;
if (pathWidth < width)
pathWidth = width;
width = (int32)ceil(be_plain_font->StringWidth(sizeText.String())) +
kStringViewInsets;
if (sizeWidth < width)
sizeWidth = width;
}
}
static const char kPrefix[] = " KMGTPE";
void
PartitionsPage::_CreateSizeText(int64 size, BString* text)
{
if (size < 0) {
(*text) << "Error";
return;
}
int index = 0;
int n = 7;
int64 remainder = 0;
for (; size >= 1000 && index <= n; index ++) {
remainder = size % 1000;
size /= 1000;
}
// round
size = size + ((remainder + 500) / 1000);
if (index == 0)
(*text) << size << " B";
else if (index < n)
(*text) << size << " " << kPrefix[index] << "B";
else
(*text) << "-";
}
BMessage*
PartitionsPage::_CreateControlMessage(uint32 what, int32 index)
{
BMessage* message = new BMessage(what);
message->AddInt32("index", index);
return message;
}

View File

@ -0,0 +1,42 @@
/*
* Copyright 2008, Michael Pfeiffer, laplace@users.sourceforge.net. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef PARTITONS_PAGE_H
#define PARTITONS_PAGE_H
#include "WizardPageView.h"
class BTextView;
class BScrollView;
class PartitionsPage : public WizardPageView
{
public:
PartitionsPage(BMessage* settings, BRect frame, const char* name);
virtual ~PartitionsPage();
virtual void PageCompleted();
virtual void FrameResized(float width, float height);
private:
void _BuildUI();
void _Layout();
void _FillPartitionsView(BView* view);
void _CreateSizeText(int64 size, BString* text);
BMessage* _CreateControlMessage(uint32 what, int32 partitionIndex);
void _ComputeColumnWidths(int32& showWidth, int32& nameWidth, int32& typeWidth,
int32& sizeWidth, int32& pathWidth);
BTextView* fDescription;
BView* fPartitions;
BScrollView* fPartitionsScrollView;
float fPartitionsWidth;
float fPartitionsHeight;
};
#endif // PARTITONS_PAGE_H

View File

@ -0,0 +1,93 @@
/*
* Copyright 2008, Michael Pfeiffer, laplace@users.sourceforge.net. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#include "TestBootDrive.h"
#include <stdio.h>
TestBootDrive::TestBootDrive()
{
}
TestBootDrive::~TestBootDrive()
{
}
bool
TestBootDrive::IsBootMenuInstalled()
{
return true;
}
status_t
TestBootDrive::ReadPartitions(BMessage *message)
{
message->AddString("disk", "/dev/disk/ide/ata/0/master/0/raw");
BMessage partition;
partition.AddBool("show", true);
partition.AddString("name", "Haiku");
partition.AddString("type", "bfs");
partition.AddString("path", "/dev/disk/ide/ata/0/master/0/0_0");
partition.AddInt64("size", 3 * (int64)1024 * 1024 * 1024);
message->AddMessage("partition", &partition);
partition.MakeEmpty();
partition.AddBool("show", true);
partition.AddString("name", "no name");
partition.AddString("type", "dos");
partition.AddString("path", "/dev/disk/ide/ata/0/slave/0/0_0");
partition.AddInt64("size", 10 * (int64)1024 * 1024 * 1024);
message->AddMessage("partition", &partition);
partition.MakeEmpty();
partition.AddBool("show", true);
partition.AddString("name", "Data");
partition.AddString("type", "unknown");
partition.AddString("path", "/dev/disk/ide/ata/0/slave/0/0_1");
partition.AddInt64("size", 250 * (int64)1024 * 1024 * 1024);
message->AddMessage("partition", &partition);
return B_OK;
}
status_t
TestBootDrive::WriteBootMenu(BMessage *message)
{
printf("WriteBootMenu:\n");
message->PrintToStream();
BMessage partition;
int32 index = 0;
for (; message->FindMessage("partition", index, &partition) == B_OK; index ++) {
printf("Partition %d:\n", (int)index);
partition.PrintToStream();
}
return B_OK;
}
status_t
TestBootDrive::SaveMasterBootRecord(BFile *file)
{
return B_OK;
}
status_t
TestBootDrive::RestoreMasterBootRecord(BFile *file)
{
return B_OK;
}

View File

@ -0,0 +1,23 @@
/*
* Copyright 2008, Michael Pfeiffer, laplace@users.sourceforge.net. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef TEST_BOOT_DRIVE_H
#define TEST_BOOT_DRIVER_H
#include "BootDrive.h"
class TestBootDrive : public BootDrive
{
public:
TestBootDrive();
virtual ~TestBootDrive();
virtual bool IsBootMenuInstalled();
virtual status_t ReadPartitions(BMessage *message);
virtual status_t WriteBootMenu(BMessage *message);
virtual status_t SaveMasterBootRecord(BFile *file);
virtual status_t RestoreMasterBootRecord(BFile *file);
};
#endif // TEST_BOOT_DRIVER_H

View File

@ -0,0 +1,62 @@
/*
* Copyright 2008, Michael Pfeiffer, laplace@users.sourceforge.net. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#include "UninstallPage.h"
#include <RadioButton.h>
#include <TextView.h>
#include <string.h>
UninstallPage::UninstallPage(BMessage* settings, BRect frame, const char* name)
: WizardPageView(settings, frame, name, B_FOLLOW_ALL,
B_WILL_DRAW | B_FRAME_EVENTS | B_FULL_UPDATE_ON_RESIZE)
{
_BuildUI();
}
UninstallPage::~UninstallPage()
{
}
void
UninstallPage::FrameResized(float width, float height)
{
WizardPageView::FrameResized(width, height);
_Layout();
}
static const float kTextDistance = 10;
void
UninstallPage::_BuildUI()
{
BRect rect(Bounds());
fDescription = CreateDescription(rect, "description",
"Uninstall Boot Manager\n\n"
"Please locate the Master Boot Record (MBR) save file to "
"restore from. This is the file that was created when the "
"boot manager was first installed.");
MakeHeading(fDescription);
AddChild(fDescription);
_Layout();
}
void
UninstallPage::_Layout()
{
LayoutDescriptionVertically(fDescription);
}

View File

@ -0,0 +1,30 @@
/*
* Copyright 2008, Michael Pfeiffer, laplace@users.sourceforge.net. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef UNINSTALL_PAGE_H
#define UNINSTALL_PAGE_H
#include "WizardPageView.h"
class BTextView;
class UninstallPage : public WizardPageView
{
public:
UninstallPage(BMessage* settings, BRect frame, const char* name);
virtual ~UninstallPage();
virtual void FrameResized(float width, float height);
private:
void _BuildUI();
void _Layout();
BTextView* fDescription;
};
#endif // UNINSTALL_PAGE_H

View File

@ -0,0 +1,95 @@
/*
* Copyright 2008, Michael Pfeiffer, laplace@users.sourceforge.net. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#include "WizardController.h"
#include "WizardView.h"
#include "WizardPageView.h"
void
WizardController::StateStack::MakeEmpty()
{
StateStack* stack = this;
StateStack* next;
do {
next = stack->Next();
delete stack;
stack = next;
} while (next != NULL);
}
WizardController::WizardController()
: fStack(NULL)
{
}
WizardController::~WizardController()
{
if (fStack != NULL) {
fStack->MakeEmpty();
fStack = NULL;
}
}
void
WizardController::Initialize(WizardView* view)
{
if (fStack == NULL)
_PushState(InitialState());
_ShowPage(view);
}
void
WizardController::Next(WizardView* wizard)
{
wizard->PageCompleted();
if (fStack == NULL)
return;
int state = NextState(fStack->State());
if (state < 0)
return;
_PushState(state);
_ShowPage(wizard);
}
void
WizardController::Previous(WizardView* wizard)
{
wizard->PageCompleted();
if (fStack != NULL) {
StateStack* stack = fStack;
fStack = fStack->Next();
delete stack;
}
_ShowPage(wizard);
}
void
WizardController::_PushState(int32 state)
{
fStack = new StateStack(state, fStack);
}
void
WizardController::_ShowPage(WizardView* wizard)
{
if (fStack == NULL)
return;
WizardPageView* page = CreatePage(fStack->State(), wizard);
wizard->SetPage(page);
}

View File

@ -0,0 +1,64 @@
/*
* Copyright 2008, Michael Pfeiffer, laplace@users.sourceforge.net. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef WIZARD_CONTROLLER_H
#define WIZARD_CONTROLLER_H
#include <SupportDefs.h>
class WizardView;
class WizardPageView;
class WizardController
{
public:
WizardController();
virtual ~WizardController();
virtual void Initialize(WizardView* wizard);
virtual void Next(WizardView* wizard);
virtual void Previous(WizardView* wizard);
protected:
virtual int32 InitialState() = 0;
virtual int32 NextState(int32 state) = 0;
virtual WizardPageView* CreatePage(int32 state, WizardView* wizard) = 0;
private:
class StateStack {
public:
StateStack(int32 state, StateStack* next)
: fState(state)
, fNext(next)
{
}
int32 State() {
return fState;
}
StateStack* Next() {
return fNext;
}
void MakeEmpty();
private:
int32 fState;
StateStack* fNext;
};
void _PushState(int32 state);
void _ShowPage(WizardView* wizard);
StateStack* fStack;
};
#endif // WIZARD_CONTROLLER_H

View File

@ -0,0 +1,79 @@
/*
* Copyright 2008, Michael Pfeiffer, laplace@users.sourceforge.net. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#include "WizardPageView.h"
#include <TextView.h>
#include <math.h>
#include <string.h>
WizardPageView::WizardPageView(BMessage* settings, BRect frame, const char* name,
uint32 resizingMode, uint32 flags)
: BView(frame, name, resizingMode, flags)
, fSettings(settings)
{
SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
}
WizardPageView::~WizardPageView()
{
}
void
WizardPageView::PageCompleted()
{
}
BTextView*
WizardPageView::CreateDescription(BRect frame, const char* name,
const char* description)
{
BTextView* view = new BTextView(frame, "text",
frame.OffsetToCopy(0, 0),
B_FOLLOW_LEFT_RIGHT | B_FOLLOW_TOP,
B_WILL_DRAW | B_PULSE_NEEDED | B_FRAME_EVENTS);
view->MakeEditable(false);
view->SetViewColor(ViewColor());
view->SetStylable(true);
view->SetText(description);
return view;
}
void
WizardPageView::MakeHeading(BTextView* view)
{
const char* text = view->Text();
const char* firstLineEnd = strchr(text, '\n');
if (firstLineEnd != NULL) {
int indexFirstLineEnd = firstLineEnd - text;
BFont font;
view->GetFont(&font);
font.SetSize(ceil(font.Size() * 1.2));
font.SetFace(B_BOLD_FACE);
view->SetFontAndColor(0, indexFirstLineEnd, &font);
}
}
void
WizardPageView::LayoutDescriptionVertically(BTextView* view)
{
view->SetTextRect(view->Bounds());
float height = view->TextHeight(0, 32000);
float width = view->Bounds().Width();
view->ResizeTo(width, height);
view->SetTextRect(view->Bounds());
}

View File

@ -0,0 +1,37 @@
/*
* Copyright 2008, Michael Pfeiffer, laplace@users.sourceforge.net. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef WIZARD_PAGE_VIEW_H
#define WIZARD_PAGE_VIEW_H
#include <Button.h>
#include <Message.h>
#include <TextView.h>
#include <View.h>
class WizardPageView : public BView
{
public:
WizardPageView(BMessage* settings, BRect frame, const char* name,
uint32 resizingMode = B_FOLLOW_ALL, uint32 flags = B_WILL_DRAW);
virtual ~WizardPageView();
virtual void PageCompleted();
virtual BTextView* CreateDescription(BRect frame, const char* name,
const char* description);
virtual void MakeHeading(BTextView* view);
virtual void LayoutDescriptionVertically(BTextView* view);
protected:
BMessage* fSettings;
private:
void _BuildUI();
};
#endif // WIZARD_PAGE_VIEW_H

View File

@ -0,0 +1,158 @@
/*
* Copyright 2008, Michael Pfeiffer, laplace@users.sourceforge.net. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#include "WizardView.h"
#include "WizardPageView.h"
#include <Box.h>
static const float kSeparatorHeight = 2;
static const float kSeparatorDistance = 5;
static const float kBorderWidth = 10;
static const float kBorderHeight = 5;
WizardView::WizardView(BRect frame, const char* name, uint32 resizingMode)
: BView(frame, name, resizingMode, 0)
, fSeparator(NULL)
, fPrevious(NULL)
, fNext(NULL)
, fPage(NULL)
{
_BuildUI();
SetPreviousButtonHidden(true);
}
WizardView::~WizardView()
{
}
BRect
WizardView::PageFrame()
{
float left = kBorderWidth;
float right = Bounds().right - kBorderWidth;
float top = kBorderHeight;
float bottom = fSeparator->Frame().top - kSeparatorDistance - 1;
return BRect(left, top, right, bottom);
}
void
WizardView::SetPage(WizardPageView* page)
{
if (fPage == page)
return;
if (fPage != NULL) {
RemoveChild(fPage);
delete fPage;
}
fPage = page;
if (page == NULL)
return;
BRect frame = PageFrame();
page->MoveTo(frame.left, frame.top);
page->ResizeTo(frame.Width()+1, frame.Height()+1);
AddChild(page);
}
void
WizardView::PageCompleted()
{
if (fPage != NULL)
fPage->PageCompleted();
}
void
WizardView::SetPreviousButtonEnabled(bool enabled)
{
fPrevious->SetEnabled(enabled);
}
void
WizardView::SetNextButtonEnabled(bool enabled)
{
fNext->SetEnabled(enabled);
}
void
WizardView::SetPreviousButtonLabel(const char* text)
{
fPrevious->SetLabel(text);
fPrevious->ResizeToPreferred();
}
void
WizardView::SetNextButtonLabel(const char* text)
{
BRect frame = fNext->Frame();
fNext->SetLabel(text);
fNext->ResizeToPreferred();
BRect newFrame = fNext->Frame();
fNext->MoveBy(frame.Width() - newFrame.Width(),
frame.Height() - newFrame.Height());
}
void
WizardView::SetPreviousButtonHidden(bool hide)
{
if (hide) {
if (!fPrevious->IsHidden())
fPrevious->Hide();
} else {
if (fPrevious->IsHidden())
fPrevious->Show();
}
}
void
WizardView::_BuildUI()
{
SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
float width = Bounds().Width();
float height = Bounds().Height();
fSeparator = new BBox(BRect(kBorderWidth, 0,
width - 1 - kBorderWidth, kSeparatorHeight - 1),
"separator",
B_FOLLOW_LEFT_RIGHT | B_FOLLOW_BOTTOM);
AddChild(fSeparator);
fPrevious = new BButton(BRect(0, 0, 100, 20), "previous", "Previous",
new BMessage(kMessagePrevious),
B_FOLLOW_LEFT | B_FOLLOW_BOTTOM);
AddChild(fPrevious);
fPrevious->ResizeToPreferred();
fNext = new BButton(BRect(0, 0, 100, 20), "next", "Next",
new BMessage(kMessageNext),
B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM);
AddChild(fNext);
fNext->ResizeToPreferred();
// layout views
float buttonHeight = fPrevious->Bounds().Height();
float buttonTop = height - 1 - buttonHeight - kBorderHeight;
fPrevious->MoveTo(kBorderWidth, buttonTop);
fSeparator->MoveTo(kBorderWidth, buttonTop - kSeparatorDistance - kSeparatorHeight);
fNext->MoveTo(width - fNext->Bounds().Width() - kBorderWidth - 1, buttonTop);
}

View File

@ -0,0 +1,50 @@
/*
* Copyright 2008, Michael Pfeiffer, laplace@users.sourceforge.net. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef WIZARD_VIEW_H
#define WIZARD_VIEW_H
#include <Box.h>
#include <Button.h>
#include <View.h>
class BTextView;
class WizardPageView;
const uint32 kMessageNext = 'next';
const uint32 kMessagePrevious = 'prev';
class WizardView : public BView
{
public:
WizardView(BRect frame, const char* name, uint32 resizingMode);
virtual ~WizardView();
virtual BRect PageFrame();
virtual void SetPage(WizardPageView* page);
virtual void PageCompleted();
virtual void SetPreviousButtonEnabled(bool enabled);
virtual void SetNextButtonEnabled(bool enabled);
virtual void SetPreviousButtonLabel(const char* text);
virtual void SetNextButtonLabel(const char* text);
virtual void SetPreviousButtonHidden(bool hide);
private:
void _BuildUI();
BBox* fSeparator;
BButton* fPrevious;
BButton* fNext;
WizardPageView* fPage;
};
#endif // WIZARD_VIEW_H

View File

@ -0,0 +1,94 @@
/*
* Copyright 2008, Haiku Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Michael Pfeiffer <laplace@users.sourceforge.net>
*
*/
resource(1, "BEOS:APP_FLAGS") (#'APPF') $"00000000";
resource(1, "BEOS:APP_VERSION") #'APPV' array {
$"0000000000000000000000000000000000000000000000000000000000000000"
$"0000000000000000000000000000000000000000000000000000000000000000"
$"0000000000000000000000000000000000000000000000000000000000000000"
$"0000000000000000000000000000000000000000000000000000000000000000"
$"0000000000000000000000000000000000000000000000000000000000000000"
$"0000000000000000000000000000000000000000000000000000000000000000"
$"0000000000000000000000000000000000000000000000000000000000000000"
$"0000000000000000000000000000000000000000000000000000000000000000"
$"0000000000000000000000000000000000000000000000000000000000000000"
$"0000000000000000000000000000000000000000000000000000000000000000"
$"000000000000000000000000000000000000000080031200FC105760EC111000"
$"EC088BC800000000FC1057808003220080052980800294408000600380032200"
$"8005298000000002FC1057C0FC105A7C000000018003E7800000000280032200"
$"800529808002944080006003EC02ECB88005298000000000FC1057D0EC111000"
$"EC01BE200000000200000000FC105A7C000000018003E7800000000280006003"
$"000000028001DEE88001DEF8EC02ECB88004B38000000000FC1058108003E780"
$"EC01BE20EC02ECB8FC105810EC111000EC01BE7C00000001FC10582000000000"
$"EC02ECBCFFFFFFFFEC05B434FC1058B88005298080029440FC10585080019244"
$"FC1059B8EC02ECB8FC105850EC111000EC01BE7C8002A680FC105870EC111000"
$"80052980FFFFFFFFEC05B434FC10593800000004000201DC800060038003E780"
$"8005298000000000FC105890420C0000EC019C080000010043300000EC111000"
$"8004B38000000000"
};
resource(101, "BEOS:L:STD_ICON") #'ICON' array {
$"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
$"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
$"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
$"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
$"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
$"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
$"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
$"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
$"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
$"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
$"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
$"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
$"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
$"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
$"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
$"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
$"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
$"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
$"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
$"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
$"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
$"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
$"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
$"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
$"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
$"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
$"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
$"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
$"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
$"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
$"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
$"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
};
resource(101, "BEOS:M:STD_ICON") #'MICN' array {
$"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
$"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
$"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
$"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
$"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
$"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
$"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
$"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
$"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
$"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
$"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
$"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
$"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
$"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
$"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
$"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
};
resource(1, "BEOS:APP_SIG") (#'MIMS') "application/x-vnd.Haiku-bootman";
resource(1, "BEOS:FILE_TYPES") message { };