1/*
2 * Copyright 2010-2017, Haiku, Inc. All Rights Reserved.
3 * Copyright 2009, Pier Luigi Fiorini.
4 * Distributed under the terms of the MIT License.
5 *
6 * Authors:
7 *		Pier Luigi Fiorini, pierluigi.fiorini@gmail.com
8 *		Brian Hill, supernova@tycho.email
9 */
10
11#include "PrefletWin.h"
12
13#include <Alert.h>
14#include <Application.h>
15#include <Button.h>
16#include <Catalog.h>
17#include <FindDirectory.h>
18#include <Notification.h>
19#include <Path.h>
20#include <SeparatorView.h>
21
22#include <notification/Notifications.h>
23
24#include "NotificationsConstants.h"
25#include "PrefletView.h"
26
27
28#undef B_TRANSLATION_CONTEXT
29#define B_TRANSLATION_CONTEXT "PrefletWin"
30
31const BString kSampleMessageID("NotificationsSample");
32
33
34PrefletWin::PrefletWin()
35	:
36	BWindow(BRect(0, 0, 160 + 20 * be_plain_font->Size(), 300),
37		B_TRANSLATE_SYSTEM_NAME("Notifications"),
38		B_TITLED_WINDOW, B_NOT_ZOOMABLE | B_ASYNCHRONOUS_CONTROLS
39		| B_AUTO_UPDATE_SIZE_LIMITS)
40{
41	// Preflet container view
42	fMainView = new PrefletView(this);
43	fMainView->SetBorder(B_NO_BORDER);
44	fMainView->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNLIMITED));
45
46	// Defaults button
47	fDefaults = new BButton("defaults", B_TRANSLATE("Defaults"),
48		new BMessage(kDefaults));
49	fDefaults->SetEnabled(false);
50
51	// Revert button
52	fRevert = new BButton("revert", B_TRANSLATE("Revert"),
53		new BMessage(kRevert));
54	fRevert->SetEnabled(false);
55
56	// Build the layout
57	fButtonsView = new BGroupView();
58	BLayoutBuilder::Group<>(fButtonsView, B_VERTICAL, 0)
59		.AddGroup(B_HORIZONTAL)
60			.Add(fDefaults)
61			.Add(fRevert)
62			.AddGlue()
63			.SetInsets(B_USE_WINDOW_SPACING, 0, B_USE_WINDOW_SPACING,
64				B_USE_WINDOW_SPACING)
65		.End();
66	fButtonsLayout = fButtonsView->GroupLayout();
67
68	BLayoutBuilder::Group<>(this, B_VERTICAL, 0)
69		.SetInsets(0, B_USE_DEFAULT_SPACING, 0, 0)
70		.Add(fMainView)
71		.Add(fButtonsView)
72	.End();
73	fMainView->SetExplicitMinSize(BSize(Frame().Width(), B_SIZE_UNSET));
74
75	ReloadSettings();
76
77	// Center this window on screen and show it
78	CenterOnScreen();
79	Show();
80}
81
82
83void
84PrefletWin::MessageReceived(BMessage* msg)
85{
86	switch (msg->what) {
87		case kApply:
88		case kApplyWithExample:
89		{
90			BPath path;
91
92			status_t ret = B_OK;
93			ret = find_directory(B_USER_SETTINGS_DIRECTORY, &path);
94			if (ret != B_OK)
95				return;
96
97			path.Append(kSettingsFile);
98
99			BMessage settingsStore;
100			int32 count = fMainView->CountTabs();
101			for (int32 i = 0; i < count; i++) {
102				SettingsPane* pane =
103					dynamic_cast<SettingsPane*>(fMainView->PageAt(i));
104				if (pane) {
105					if (pane->Save(settingsStore) == B_OK) {
106						fDefaults->SetEnabled(_DefaultsPossible());
107						fRevert->SetEnabled(_RevertPossible());
108					} else
109						break;
110				}
111			}
112
113			// Save settings file
114			BFile file(path.Path(), B_WRITE_ONLY | B_CREATE_FILE | B_ERASE_FILE);
115			ret = settingsStore.Flatten(&file);
116			if (ret != B_OK) {
117				BAlert* alert = new BAlert("",
118					B_TRANSLATE("An error occurred saving the preferences.\n"
119						"It's possible you are running out of disk space."),
120					B_TRANSLATE("OK"), NULL, NULL, B_WIDTH_AS_USUAL,
121					B_STOP_ALERT);
122				alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE);
123				(void)alert->Go();
124			}
125			file.Unset();
126
127			if (msg->what == kApplyWithExample)
128				_SendExampleNotification();
129
130			break;
131		}
132		case kDefaults:
133			fDefaults->SetEnabled(false);
134			_Defaults();
135			PostMessage(kApply);
136			break;
137		case kRevert:
138			fRevert->SetEnabled(false);
139			_Revert();
140			PostMessage(kApply);
141			break;
142		case kShowButtons: {
143			bool show = msg->GetBool(kShowButtonsKey, true);
144			fButtonsLayout->SetVisible(show);
145			break;
146		}
147		default:
148			BWindow::MessageReceived(msg);
149	}
150}
151
152
153bool
154PrefletWin::QuitRequested()
155{
156	be_app_messenger.SendMessage(B_QUIT_REQUESTED);
157	return true;
158}
159
160
161void
162PrefletWin::SettingChanged(bool showExample)
163{
164	if (showExample)
165		PostMessage(kApplyWithExample);
166	else
167		PostMessage(kApply);
168}
169
170
171void
172PrefletWin::ReloadSettings()
173{
174	BPath path;
175
176	if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK)
177		return;
178
179	// FIXME don't load this again here, share with other tabs!
180	path.Append(kSettingsFile);
181
182	BMessage settings;
183	BFile file(path.Path(), B_READ_ONLY);
184	settings.Unflatten(&file);
185
186	int32 count = fMainView->CountTabs();
187	for (int32 i = 0; i < count; i++) {
188		SettingsPane* pane =
189			dynamic_cast<SettingsPane*>(fMainView->PageAt(i));
190		if (pane)
191			pane->Load(settings);
192	}
193	fDefaults->SetEnabled(_DefaultsPossible());
194}
195
196
197status_t
198PrefletWin::_Revert()
199{
200	int32 count = fMainView->CountTabs();
201	for (int32 i = 0; i < count; i++) {
202		SettingsPane* pane =
203			dynamic_cast<SettingsPane*>(fMainView->PageAt(i));
204		if (pane)
205			pane->Revert();
206	}
207	return B_OK;
208}
209
210
211bool
212PrefletWin::_RevertPossible()
213{
214	int32 count = fMainView->CountTabs();
215	for (int32 i = 0; i < count; i++) {
216		SettingsPane* pane =
217			dynamic_cast<SettingsPane*>(fMainView->PageAt(i));
218		if (pane && pane->RevertPossible())
219			return true;
220	}
221	return false;
222}
223
224
225status_t
226PrefletWin::_Defaults()
227{
228	int32 count = fMainView->CountTabs();
229	for (int32 i = 0; i < count; i++) {
230		SettingsPane* pane =
231			dynamic_cast<SettingsPane*>(fMainView->PageAt(i));
232		if (pane)
233			pane->Defaults();
234	}
235	return B_OK;
236}
237
238
239bool
240PrefletWin::_DefaultsPossible()
241{
242	int32 count = fMainView->CountTabs();
243	for (int32 i = 0; i < count; i++) {
244		SettingsPane* pane =
245			dynamic_cast<SettingsPane*>(fMainView->PageAt(i));
246		if (pane && pane->DefaultsPossible())
247			return true;
248	}
249	return false;
250}
251
252
253void
254PrefletWin::_SendExampleNotification()
255{
256	BNotification notification(B_INFORMATION_NOTIFICATION);
257	notification.SetMessageID(kSampleMessageID);
258	notification.SetGroup(B_TRANSLATE("Notifications"));
259	notification.SetTitle(B_TRANSLATE("Notifications preflet sample"));
260	notification.SetContent(B_TRANSLATE("This is a test notification message"));
261	notification.Send();
262}
263