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 (fOkButton->Window() == 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 // 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 200 status_t 201 AbstractParametersPanel::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 256 bool 257 AbstractParametersPanel::NeedsEditor() const 258 { 259 return true; 260 } 261 262 263 bool 264 AbstractParametersPanel::ValidWithoutEditor() const 265 { 266 return true; 267 } 268 269 status_t 270 AbstractParametersPanel::ParametersReceived(const BString& parameters, 271 BMessage& storage) 272 { 273 return B_OK; 274 } 275 276 277 void 278 AbstractParametersPanel::AddControls(BLayoutBuilder::Group<>& builder, 279 BView* editorView) 280 { 281 if (editorView != NULL) 282 builder.Add(editorView); 283 } 284