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:
EscapeFilter(AbstractParametersPanel * target)36 EscapeFilter(AbstractParametersPanel* target)
37 :
38 BMessageFilter(B_ANY_DELIVERY, B_ANY_SOURCE),
39 fPanel(target)
40 {
41 }
42
~EscapeFilter()43 virtual ~EscapeFilter()
44 {
45 }
46
Filter(BMessage * message,BHandler ** target)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
AbstractParametersPanel(BWindow * window)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
~AbstractParametersPanel()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
QuitRequested()106 AbstractParametersPanel::QuitRequested()
107 {
108 release_sem(fExitSemaphore);
109 return false;
110 }
111
112
113 void
MessageReceived(BMessage * message)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
Go(BString & parameters)137 AbstractParametersPanel::Go(BString& parameters)
138 {
139 BMessage storage;
140 return Go(parameters, storage);
141 }
142
143
144 void
Cancel()145 AbstractParametersPanel::Cancel()
146 {
147 fReturnStatus = B_CANCELED;
148 release_sem(fExitSemaphore);
149 }
150
151
152 void
Init(B_PARAMETER_EDITOR_TYPE type,const BString & diskSystem,BPartition * partition)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
Go(BString & parameters,BMessage & storage)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
NeedsEditor() const257 AbstractParametersPanel::NeedsEditor() const
258 {
259 return true;
260 }
261
262
263 bool
ValidWithoutEditor() const264 AbstractParametersPanel::ValidWithoutEditor() const
265 {
266 return true;
267 }
268
269 status_t
ParametersReceived(const BString & parameters,BMessage & storage)270 AbstractParametersPanel::ParametersReceived(const BString& parameters,
271 BMessage& storage)
272 {
273 return B_OK;
274 }
275
276
277 void
AddControls(BLayoutBuilder::Group<> & builder,BView * editorView)278 AbstractParametersPanel::AddControls(BLayoutBuilder::Group<>& builder,
279 BView* editorView)
280 {
281 if (editorView != NULL)
282 builder.Add(editorView);
283 }
284