haiku/src/apps/drivesetup/AbstractParametersPanel.cpp

284 lines
5.6 KiB
C++

/*
* Copyright 2008-2013 Haiku, Inc. All rights reserved.
* Distributed under the terms of the MIT license.
*
* Authors:
* Stephan Aßmus <superstippi@gmx.de>
* Axel Dörfler, axeld@pinc-software.de.
* Karsten Heimrich. <host.haiku@gmx.de>
*/
#include "AbstractParametersPanel.h"
#include <driver_settings.h>
#include <stdio.h>
#include <Button.h>
#include <Catalog.h>
#include <DiskSystemAddOn.h>
#include <DiskSystemAddOnManager.h>
#include <GroupLayout.h>
#include <MessageFilter.h>
#include <String.h>
#undef B_TRANSLATION_CONTEXT
#define B_TRANSLATION_CONTEXT "AbstractParametersPanel"
static const uint32 kMsgOk = 'okok';
static const uint32 kParameterChanged = 'pmch';
class AbstractParametersPanel::EscapeFilter : public BMessageFilter {
public:
EscapeFilter(AbstractParametersPanel* target)
:
BMessageFilter(B_ANY_DELIVERY, B_ANY_SOURCE),
fPanel(target)
{
}
virtual ~EscapeFilter()
{
}
virtual filter_result Filter(BMessage* message, BHandler** target)
{
filter_result result = B_DISPATCH_MESSAGE;
switch (message->what) {
case B_KEY_DOWN:
case B_UNMAPPED_KEY_DOWN: {
uint32 key;
if (message->FindInt32("raw_char", (int32*)&key) >= B_OK) {
if (key == B_ESCAPE) {
result = B_SKIP_MESSAGE;
fPanel->Cancel();
}
}
break;
}
default:
break;
}
return result;
}
private:
AbstractParametersPanel* fPanel;
};
// #pragma mark -
AbstractParametersPanel::AbstractParametersPanel(BWindow* window)
:
BWindow(BRect(300.0, 200.0, 600.0, 300.0), 0, B_MODAL_WINDOW_LOOK,
B_MODAL_SUBSET_WINDOW_FEEL,
B_ASYNCHRONOUS_CONTROLS | B_AUTO_UPDATE_SIZE_LIMITS),
fOkButton(new BButton(B_TRANSLATE("OK"), new BMessage(kMsgOk))),
fReturnStatus(B_CANCELED),
fEditor(NULL),
fEscapeFilter(new EscapeFilter(this)),
fExitSemaphore(create_sem(0, "AbstractParametersPanel exit")),
fWindow(window)
{
AddCommonFilter(fEscapeFilter);
AddToSubset(fWindow);
}
AbstractParametersPanel::~AbstractParametersPanel()
{
RemoveCommonFilter(fEscapeFilter);
delete fEscapeFilter;
delete_sem(fExitSemaphore);
if (fOkButton->Window() == NULL)
delete fOkButton;
}
bool
AbstractParametersPanel::QuitRequested()
{
release_sem(fExitSemaphore);
return false;
}
void
AbstractParametersPanel::MessageReceived(BMessage* message)
{
switch (message->what) {
case B_CANCEL:
Cancel();
break;
case kMsgOk:
fReturnStatus = B_OK;
release_sem(fExitSemaphore);
break;
case kParameterChanged:
fOkButton->SetEnabled(fEditor->ValidateParameters());
break;
default:
BWindow::MessageReceived(message);
}
}
status_t
AbstractParametersPanel::Go(BString& parameters)
{
BMessage storage;
return Go(parameters, storage);
}
void
AbstractParametersPanel::Cancel()
{
fReturnStatus = B_CANCELED;
release_sem(fExitSemaphore);
}
void
AbstractParametersPanel::Init(B_PARAMETER_EDITOR_TYPE type,
const BString& diskSystem, BPartition* partition)
{
// Create partition parameter editor
status_t status = B_ERROR;
if (diskSystem.IsEmpty()) {
status = partition->GetParameterEditor(type, &fEditor);
} else {
DiskSystemAddOnManager* manager = DiskSystemAddOnManager::Default();
BDiskSystemAddOn* addOn = manager->GetAddOn(diskSystem);
if (addOn != NULL) {
// put the add-on
manager->PutAddOn(addOn);
status = addOn->GetParameterEditor(type, &fEditor);
}
}
if (status != B_OK && status != B_NOT_SUPPORTED)
fReturnStatus = status;
// Create controls
BLayoutBuilder::Group<> builder = BLayoutBuilder::Group<>(this,
B_VERTICAL);
if (fEditor == NULL)
AddControls(builder, NULL);
else
AddControls(builder, fEditor->View());
builder.AddGroup(B_HORIZONTAL, B_USE_DEFAULT_SPACING)
.AddGlue()
.Add(new BButton(B_TRANSLATE("Cancel"), new BMessage(B_CANCEL)))
.Add(fOkButton)
.End()
.SetInsets(B_USE_DEFAULT_SPACING);
SetDefaultButton(fOkButton);
if (fEditor != NULL) {
fEditor->SetTo(partition);
fEditor->SetModificationMessage(new BMessage(kParameterChanged));
}
}
status_t
AbstractParametersPanel::Go(BString& parameters, BMessage& storage)
{
// Without an editor, we cannot change anything, anyway
if (fEditor == NULL && NeedsEditor()) {
parameters = "";
if (ValidWithoutEditor() && fReturnStatus == B_CANCELED)
fReturnStatus = B_OK;
if (!Lock())
return B_ERROR;
} else {
// run the window thread, to get an initial layout of the controls
Hide();
Show();
if (!Lock())
return B_CANCELED;
// center the panel above the parent window
CenterIn(fWindow->Frame());
Show();
Unlock();
// block this thread now, but keep the window repainting
while (true) {
status_t status = acquire_sem_etc(fExitSemaphore, 1,
B_CAN_INTERRUPT | B_RELATIVE_TIMEOUT, 50000);
if (status != B_TIMED_OUT && status != B_INTERRUPTED)
break;
fWindow->UpdateIfNeeded();
}
if (!Lock())
return B_CANCELED;
if (fReturnStatus == B_OK) {
if (fEditor != NULL && fEditor->ValidateParameters()) {
status_t status = fEditor->GetParameters(parameters);
if (status != B_OK)
fReturnStatus = status;
}
if (fReturnStatus == B_OK)
fReturnStatus = ParametersReceived(parameters, storage);
}
}
status_t status = fReturnStatus;
Quit();
// NOTE: this object is toast now!
return status;
}
bool
AbstractParametersPanel::NeedsEditor() const
{
return true;
}
bool
AbstractParametersPanel::ValidWithoutEditor() const
{
return true;
}
status_t
AbstractParametersPanel::ParametersReceived(const BString& parameters,
BMessage& storage)
{
return B_OK;
}
void
AbstractParametersPanel::AddControls(BLayoutBuilder::Group<>& builder,
BView* editorView)
{
if (editorView != NULL)
builder.Add(editorView);
}