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 30 static const uint32 kMsgOk = 'okok'; 31 static const uint32 kParameterChanged = 'pmch'; 32 33 34 class AbstractParametersPanel::EscapeFilter : public BMessageFilter { 35 public: 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 68 private: 69 AbstractParametersPanel* fPanel; 70 }; 71 72 73 // #pragma mark - 74 75 76 AbstractParametersPanel::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 93 AbstractParametersPanel::~AbstractParametersPanel() 94 { 95 RemoveCommonFilter(fEscapeFilter); 96 delete fEscapeFilter; 97 98 delete_sem(fExitSemaphore); 99 100 if (fEditor == NULL) 101 delete fOkButton; 102 } 103 104 105 bool 106 AbstractParametersPanel::QuitRequested() 107 { 108 release_sem(fExitSemaphore); 109 return false; 110 } 111 112 113 void 114 AbstractParametersPanel::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 136 status_t 137 AbstractParametersPanel::Go(BString& parameters) 138 { 139 BMessage storage; 140 return Go(parameters, storage); 141 } 142 143 144 void 145 AbstractParametersPanel::Cancel() 146 { 147 fReturnStatus = B_CANCELED; 148 release_sem(fExitSemaphore); 149 } 150 151 152 void 153 AbstractParametersPanel::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 if (fEditor == NULL) 175 return; 176 177 // Create controls 178 179 BLayoutBuilder::Group<> builder = BLayoutBuilder::Group<>(this, 180 B_VERTICAL); 181 AddControls(builder, fEditor->View()); 182 183 builder.AddGroup(B_HORIZONTAL, B_USE_DEFAULT_SPACING) 184 .AddGlue() 185 .Add(new BButton(B_TRANSLATE("Cancel"), new BMessage(B_CANCEL))) 186 .Add(fOkButton) 187 .End() 188 .SetInsets(B_USE_DEFAULT_SPACING); 189 190 SetDefaultButton(fOkButton); 191 192 fEditor->SetTo(partition); 193 fEditor->SetModificationMessage(new BMessage(kParameterChanged)); 194 } 195 196 197 status_t 198 AbstractParametersPanel::Go(BString& parameters, BMessage& storage) 199 { 200 // Without an editor, we cannot change anything, anyway 201 if (fEditor == NULL && NeedsEditor()) { 202 parameters = ""; 203 if (ValidWithoutEditor() && fReturnStatus == B_CANCELED) 204 fReturnStatus = B_OK; 205 206 if (!Lock()) 207 return B_ERROR; 208 } else { 209 // run the window thread, to get an initial layout of the controls 210 Hide(); 211 Show(); 212 if (!Lock()) 213 return B_CANCELED; 214 215 // center the panel above the parent window 216 CenterIn(fWindow->Frame()); 217 218 Show(); 219 Unlock(); 220 221 // block this thread now, but keep the window repainting 222 while (true) { 223 status_t status = acquire_sem_etc(fExitSemaphore, 1, 224 B_CAN_INTERRUPT | B_RELATIVE_TIMEOUT, 50000); 225 if (status != B_TIMED_OUT && status != B_INTERRUPTED) 226 break; 227 fWindow->UpdateIfNeeded(); 228 } 229 230 if (!Lock()) 231 return B_CANCELED; 232 233 if (fReturnStatus == B_OK) { 234 if (fEditor != NULL && fEditor->ValidateParameters()) { 235 status_t status = fEditor->GetParameters(parameters); 236 if (status != B_OK) 237 fReturnStatus = status; 238 } 239 if (fReturnStatus == B_OK) 240 fReturnStatus = ParametersReceived(parameters, storage); 241 } 242 } 243 244 status_t status = fReturnStatus; 245 246 Quit(); 247 // NOTE: this object is toast now! 248 249 return status; 250 } 251 252 253 bool 254 AbstractParametersPanel::NeedsEditor() const 255 { 256 return true; 257 } 258 259 260 bool 261 AbstractParametersPanel::ValidWithoutEditor() const 262 { 263 return true; 264 } 265 266 status_t 267 AbstractParametersPanel::ParametersReceived(const BString& parameters, 268 BMessage& storage) 269 { 270 return B_OK; 271 } 272 273 274 void 275 AbstractParametersPanel::AddControls(BLayoutBuilder::Group<>& builder, 276 BView* editorView) 277 { 278 builder.Add(editorView); 279 } 280