xref: /haiku/src/apps/drivesetup/AbstractParametersPanel.cpp (revision 1e60bdeab63fa7a57bc9a55b032052e95a18bd2c)
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