1/* 2 * Copyright 2008-2013 Haiku, Inc. All rights reserved. 3 * Distributed under the terms of the MIT license. 4 * 5 * Authors: 6 * Stephan Aßmus <superstippi@gmx.de> 7 * Axel Dörfler, axeld@pinc-software.de. 8 * Karsten Heimrich. <host.haiku@gmx.de> 9 */ 10 11 12#include "AbstractParametersPanel.h" 13 14#include <driver_settings.h> 15#include <stdio.h> 16 17#include <Button.h> 18#include <Catalog.h> 19#include <DiskSystemAddOn.h> 20#include <DiskSystemAddOnManager.h> 21#include <GroupLayout.h> 22#include <MessageFilter.h> 23#include <String.h> 24 25 26#undef B_TRANSLATION_CONTEXT 27#define B_TRANSLATION_CONTEXT "AbstractParametersPanel" 28 29 30static const uint32 kMsgOk = 'okok'; 31static const uint32 kParameterChanged = 'pmch'; 32 33 34class AbstractParametersPanel::EscapeFilter : public BMessageFilter { 35public: 36 EscapeFilter(AbstractParametersPanel* target) 37 : 38 BMessageFilter(B_ANY_DELIVERY, B_ANY_SOURCE), 39 fPanel(target) 40 { 41 } 42 43 virtual ~EscapeFilter() 44 { 45 } 46 47 virtual filter_result Filter(BMessage* message, BHandler** target) 48 { 49 filter_result result = B_DISPATCH_MESSAGE; 50 switch (message->what) { 51 case B_KEY_DOWN: 52 case B_UNMAPPED_KEY_DOWN: { 53 uint32 key; 54 if (message->FindInt32("raw_char", (int32*)&key) >= B_OK) { 55 if (key == B_ESCAPE) { 56 result = B_SKIP_MESSAGE; 57 fPanel->Cancel(); 58 } 59 } 60 break; 61 } 62 default: 63 break; 64 } 65 return result; 66 } 67 68private: 69 AbstractParametersPanel* fPanel; 70}; 71 72 73// #pragma mark - 74 75 76AbstractParametersPanel::AbstractParametersPanel(BWindow* window) 77 : 78 BWindow(BRect(300.0, 200.0, 600.0, 300.0), 0, B_MODAL_WINDOW_LOOK, 79 B_MODAL_SUBSET_WINDOW_FEEL, 80 B_ASYNCHRONOUS_CONTROLS | B_AUTO_UPDATE_SIZE_LIMITS), 81 fOkButton(new BButton(B_TRANSLATE("OK"), new BMessage(kMsgOk))), 82 fReturnStatus(B_CANCELED), 83 fEditor(NULL), 84 fEscapeFilter(new EscapeFilter(this)), 85 fExitSemaphore(create_sem(0, "AbstractParametersPanel exit")), 86 fWindow(window) 87{ 88 AddCommonFilter(fEscapeFilter); 89 AddToSubset(fWindow); 90} 91 92 93AbstractParametersPanel::~AbstractParametersPanel() 94{ 95 RemoveCommonFilter(fEscapeFilter); 96 delete fEscapeFilter; 97 98 delete_sem(fExitSemaphore); 99 100 if (fEditor == NULL) 101 delete fOkButton; 102} 103 104 105bool 106AbstractParametersPanel::QuitRequested() 107{ 108 release_sem(fExitSemaphore); 109 return false; 110} 111 112 113void 114AbstractParametersPanel::MessageReceived(BMessage* message) 115{ 116 switch (message->what) { 117 case B_CANCEL: 118 Cancel(); 119 break; 120 121 case kMsgOk: 122 fReturnStatus = B_OK; 123 release_sem(fExitSemaphore); 124 break; 125 126 case kParameterChanged: 127 fOkButton->SetEnabled(fEditor->ValidateParameters()); 128 break; 129 130 default: 131 BWindow::MessageReceived(message); 132 } 133} 134 135 136status_t 137AbstractParametersPanel::Go(BString& parameters) 138{ 139 // Without an editor, we cannot change anything, anyway 140 if (fEditor == NULL) { 141 parameters = ""; 142 if (fReturnStatus == B_CANCELED) 143 fReturnStatus = B_OK; 144 145 if (!Lock()) 146 return B_ERROR; 147 } else { 148 // run the window thread, to get an initial layout of the controls 149 Hide(); 150 Show(); 151 if (!Lock()) 152 return B_CANCELED; 153 154 // center the panel above the parent window 155 CenterIn(fWindow->Frame()); 156 157 Show(); 158 Unlock(); 159 160 // block this thread now, but keep the window repainting 161 while (true) { 162 status_t status = acquire_sem_etc(fExitSemaphore, 1, 163 B_CAN_INTERRUPT | B_RELATIVE_TIMEOUT, 50000); 164 if (status != B_TIMED_OUT && status != B_INTERRUPTED) 165 break; 166 fWindow->UpdateIfNeeded(); 167 } 168 169 if (!Lock()) 170 return B_CANCELED; 171 172 if (fReturnStatus == B_OK) { 173 if (fEditor->ValidateParameters()) { 174 status_t err = fEditor->GetParameters(parameters); 175 if (err != B_OK) 176 fReturnStatus = err; 177 } 178 } 179 } 180 181 status_t status = fReturnStatus; 182 183 Quit(); 184 // NOTE: this object is toast now! 185 186 return status; 187} 188 189 190void 191AbstractParametersPanel::Cancel() 192{ 193 fReturnStatus = B_CANCELED; 194 release_sem(fExitSemaphore); 195} 196 197 198void 199AbstractParametersPanel::Init(B_PARAMETER_EDITOR_TYPE type, 200 const BString& diskSystem, BPartition* partition) 201{ 202 // Create partition parameter editor 203 204 status_t status = B_ERROR; 205 if (diskSystem.IsEmpty()) { 206 status = partition->GetParameterEditor(type, &fEditor); 207 } else { 208 DiskSystemAddOnManager* manager = DiskSystemAddOnManager::Default(); 209 BDiskSystemAddOn* addOn = manager->GetAddOn(diskSystem); 210 if (addOn != NULL) { 211 // put the add-on 212 manager->PutAddOn(addOn); 213 214 status = addOn->GetParameterEditor(type, &fEditor); 215 } 216 } 217 if (status != B_OK && status != B_NOT_SUPPORTED) 218 fReturnStatus = status; 219 220 if (fEditor == NULL) 221 return; 222 223 // Create controls 224 225 BLayoutBuilder::Group<> builder = BLayoutBuilder::Group<>(this, 226 B_VERTICAL); 227 AddControls(builder, fEditor->View()); 228 229 builder.AddGroup(B_HORIZONTAL, B_USE_DEFAULT_SPACING) 230 .AddGlue() 231 .Add(new BButton(B_TRANSLATE("Cancel"), new BMessage(B_CANCEL))) 232 .Add(fOkButton) 233 .End() 234 .SetInsets(B_USE_DEFAULT_SPACING); 235 236 SetDefaultButton(fOkButton); 237 238 fEditor->SetTo(partition); 239 fEditor->SetModificationMessage(new BMessage(kParameterChanged)); 240} 241 242 243void 244AbstractParametersPanel::AddControls(BLayoutBuilder::Group<>& builder, 245 BView* editorView) 246{ 247 builder.Add(editorView); 248} 249