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 (fOkButton->Window() == 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 BMessage storage; 140 return Go(parameters, storage); 141} 142 143 144void 145AbstractParametersPanel::Cancel() 146{ 147 fReturnStatus = B_CANCELED; 148 release_sem(fExitSemaphore); 149} 150 151 152void 153AbstractParametersPanel::Init(B_PARAMETER_EDITOR_TYPE type, 154 const BString& diskSystem, BPartition* partition) 155{ 156 // Create partition parameter editor 157 158 status_t status = B_ERROR; 159 if (diskSystem.IsEmpty()) { 160 status = partition->GetParameterEditor(type, &fEditor); 161 } else { 162 DiskSystemAddOnManager* manager = DiskSystemAddOnManager::Default(); 163 BDiskSystemAddOn* addOn = manager->GetAddOn(diskSystem); 164 if (addOn != NULL) { 165 // put the add-on 166 manager->PutAddOn(addOn); 167 168 status = addOn->GetParameterEditor(type, &fEditor); 169 } 170 } 171 if (status != B_OK && status != B_NOT_SUPPORTED) 172 fReturnStatus = status; 173 174 // Create controls 175 176 BLayoutBuilder::Group<> builder = BLayoutBuilder::Group<>(this, 177 B_VERTICAL); 178 179 if (fEditor == NULL) 180 AddControls(builder, NULL); 181 else 182 AddControls(builder, fEditor->View()); 183 184 builder.AddGroup(B_HORIZONTAL, B_USE_DEFAULT_SPACING) 185 .AddGlue() 186 .Add(new BButton(B_TRANSLATE("Cancel"), new BMessage(B_CANCEL))) 187 .Add(fOkButton) 188 .End() 189 .SetInsets(B_USE_DEFAULT_SPACING); 190 191 SetDefaultButton(fOkButton); 192 193 if (fEditor != NULL) { 194 fEditor->SetTo(partition); 195 fEditor->SetModificationMessage(new BMessage(kParameterChanged)); 196 } 197} 198 199 200status_t 201AbstractParametersPanel::Go(BString& parameters, BMessage& storage) 202{ 203 // Without an editor, we cannot change anything, anyway 204 if (fEditor == NULL && NeedsEditor()) { 205 parameters = ""; 206 if (ValidWithoutEditor() && fReturnStatus == B_CANCELED) 207 fReturnStatus = B_OK; 208 209 if (!Lock()) 210 return B_ERROR; 211 } else { 212 // run the window thread, to get an initial layout of the controls 213 Hide(); 214 Show(); 215 if (!Lock()) 216 return B_CANCELED; 217 218 // center the panel above the parent window 219 CenterIn(fWindow->Frame()); 220 221 Show(); 222 Unlock(); 223 224 // block this thread now, but keep the window repainting 225 while (true) { 226 status_t status = acquire_sem_etc(fExitSemaphore, 1, 227 B_CAN_INTERRUPT | B_RELATIVE_TIMEOUT, 50000); 228 if (status != B_TIMED_OUT && status != B_INTERRUPTED) 229 break; 230 fWindow->UpdateIfNeeded(); 231 } 232 233 if (!Lock()) 234 return B_CANCELED; 235 236 if (fReturnStatus == B_OK) { 237 if (fEditor != NULL && fEditor->ValidateParameters()) { 238 status_t status = fEditor->GetParameters(parameters); 239 if (status != B_OK) 240 fReturnStatus = status; 241 } 242 if (fReturnStatus == B_OK) 243 fReturnStatus = ParametersReceived(parameters, storage); 244 } 245 } 246 247 status_t status = fReturnStatus; 248 249 Quit(); 250 // NOTE: this object is toast now! 251 252 return status; 253} 254 255 256bool 257AbstractParametersPanel::NeedsEditor() const 258{ 259 return true; 260} 261 262 263bool 264AbstractParametersPanel::ValidWithoutEditor() const 265{ 266 return true; 267} 268 269status_t 270AbstractParametersPanel::ParametersReceived(const BString& parameters, 271 BMessage& storage) 272{ 273 return B_OK; 274} 275 276 277void 278AbstractParametersPanel::AddControls(BLayoutBuilder::Group<>& builder, 279 BView* editorView) 280{ 281 if (editorView != NULL) 282 builder.Add(editorView); 283} 284