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