/* * Copyright 2008-2013 Haiku, Inc. All rights reserved. * Distributed under the terms of the MIT license. * * Authors: * Stephan Aßmus * Axel Dörfler, axeld@pinc-software.de. * Karsten Heimrich. */ #include "AbstractParametersPanel.h" #include #include #include #include #include #include #include #include #include #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); }