xref: /haiku/src/apps/activitymonitor/ActivityWindow.cpp (revision fc1ca2da5cfcb00ffdf791606d5ae97fdd58a638)
1 /*
2  * Copyright 2008, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
3  * Distributed under the terms of the MIT License.
4  */
5 
6 
7 #include "ActivityWindow.h"
8 
9 #include <stdio.h>
10 
11 #include <Application.h>
12 #include <File.h>
13 #include <FindDirectory.h>
14 #ifdef __HAIKU__
15 #include <GroupLayout.h>
16 #endif
17 #include <Menu.h>
18 #include <MenuBar.h>
19 #include <MenuItem.h>
20 #include <Path.h>
21 #include <Roster.h>
22 
23 #include "ActivityMonitor.h"
24 #include "ActivityView.h"
25 
26 
27 static const uint32 kMsgAddView = 'advw';
28 
29 
30 ActivityWindow::ActivityWindow()
31 	: BWindow(BRect(100, 100, 500, 250), "ActivityMonitor", B_TITLED_WINDOW,
32 		B_ASYNCHRONOUS_CONTROLS | B_QUIT_ON_WINDOW_CLOSE)
33 {
34 	BMessage settings;
35 	_LoadSettings(settings);
36 
37 	BRect frame;
38 	if (settings.FindRect("window frame", &frame) == B_OK) {
39 		MoveTo(frame.LeftTop());
40 		ResizeTo(frame.Width(), frame.Height());
41 	}
42 
43 #ifdef __HAIKU__
44 	BGroupLayout* layout = new BGroupLayout(B_VERTICAL);
45 	SetLayout(layout);
46 
47 	// create GUI
48 
49 	BMenuBar* menuBar = new BMenuBar("menu");
50 	layout->AddView(menuBar);
51 
52 	fLayout = new BGroupLayout(B_VERTICAL);
53 	float inset = ceilf(be_plain_font->Size() * 0.7);
54 	fLayout->SetInsets(inset, inset, inset, inset);
55 	fLayout->SetSpacing(inset);
56 
57 	BView* top = new BView("top", 0, fLayout);
58 	top->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
59 	layout->AddView(top);
60 
61 	BMessage viewState;
62 	int32 count = 0;
63 	for (int32 i = 0; settings.FindMessage("activity view", i, &viewState)
64 			== B_OK; i++) {
65 		ActivityView* view = new ActivityView("ActivityMonitor", &viewState);
66 		fLayout->AddItem(view->CreateHistoryLayoutItem());
67 		fLayout->AddItem(view->CreateLegendLayoutItem());
68 		count++;
69 	}
70 	if (count == 0) {
71 		ActivityView* view = new ActivityView("ActivityMonitor", NULL);
72 		fLayout->AddItem(view->CreateHistoryLayoutItem());
73 		fLayout->AddItem(view->CreateLegendLayoutItem());
74 	}
75 
76 #else
77 	BView *layout = new BView(Bounds(), "topmost", B_FOLLOW_NONE, 0);
78 	AddChild(layout);
79 
80 	// create GUI
81 	BRect mbRect(Bounds());
82 	mbRect.bottom = 10;
83 	BMenuBar* menuBar = new BMenuBar(mbRect, "menu");
84 	layout->AddChild(menuBar);
85 
86 	BRect topRect(Bounds());
87 	topRect.top = menuBar->Bounds().bottom + 1;
88 
89 	BView* top = new BView(topRect, "top", B_FOLLOW_ALL, 0);
90 	top->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
91 	layout->AddChild(top);
92 
93 	BMessage viewState;
94 	int32 count = 0;
95 	ActivityView *aview;
96 	BRect rect;
97 	for (int32 i = 0; settings.FindMessage("activity view", i, &viewState)
98 			== B_OK; i++) {
99 		aview = new ActivityView("ActivityMonitor", &viewState);
100 		if (!rect.IsValid())
101 			rect = aview->Bounds();
102 		else
103 			rect.OffsetBySelf(0.0, aview->Bounds().Height());
104 		top->AddChild(aview);
105 		count++;
106 	}
107 	if (count == 0)
108 		top->AddChild(new ActivityView("ActivityMonitor", NULL));
109 
110 #endif
111 	// add menu
112 
113 	// "File" menu
114 	BMenu* menu = new BMenu("File");
115 	BMenuItem* item;
116 
117 	menu->AddItem(new BMenuItem("Add View", new BMessage(kMsgAddView)));
118 	menu->AddSeparatorItem();
119 
120 	menu->AddItem(item = new BMenuItem("About ActivityMonitor" B_UTF8_ELLIPSIS,
121 		new BMessage(B_ABOUT_REQUESTED)));
122 	menu->AddSeparatorItem();
123 
124 	menu->AddItem(new BMenuItem("Quit", new BMessage(B_QUIT_REQUESTED), 'Q'));
125 	menu->SetTargetForItems(this);
126 	item->SetTarget(be_app);
127 	menuBar->AddItem(menu);
128 }
129 
130 
131 ActivityWindow::~ActivityWindow()
132 {
133 }
134 
135 
136 status_t
137 ActivityWindow::_OpenSettings(BFile& file, uint32 mode)
138 {
139 	BPath path;
140 	if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK)
141 		return B_ERROR;
142 
143 	path.Append("ActivityMonitor settings");
144 
145 	return file.SetTo(path.Path(), mode);
146 }
147 
148 
149 status_t
150 ActivityWindow::_LoadSettings(BMessage& settings)
151 {
152 	BFile file;
153 	status_t status = _OpenSettings(file, B_READ_ONLY);
154 	if (status < B_OK)
155 		return status;
156 
157 	return settings.Unflatten(&file);
158 }
159 
160 
161 status_t
162 ActivityWindow::_SaveSettings()
163 {
164 	BFile file;
165 	status_t status = _OpenSettings(file, B_WRITE_ONLY | B_CREATE_FILE
166 		| B_ERASE_FILE);
167 	if (status < B_OK)
168 		return status;
169 
170 	BMessage settings('actm');
171 	status = settings.AddRect("window frame", Frame());
172 	if (status != B_OK)
173 		return status;
174 
175 #ifdef __HAIKU__
176 	BView* top = fLayout->View();
177 #else
178 	BView* top = ChildAt(0);
179 #endif
180 	int32 count = top->CountChildren();
181 	for (int32 i = 0; i < count; i++) {
182 		ActivityView* view = dynamic_cast<ActivityView*>(top->ChildAt(i));
183 		if (view == NULL)
184 			continue;
185 
186 		BMessage* viewState = new BMessage;
187 		status = view->SaveState(*viewState);
188 		if (status == B_OK)
189 			status = settings.AddMessage("activity view", viewState);
190 		if (status != B_OK) {
191 			delete viewState;
192 			break;
193 		}
194 	}
195 
196 	if (status == B_OK)
197 		status = settings.Flatten(&file);
198 
199 	return status;
200 }
201 
202 
203 int32
204 ActivityWindow::ActivityViewCount()
205 {
206 #ifdef __HAIKU__
207 	return fLayout->View()->CountChildren();
208 #else
209 	return 1;
210 #endif
211 }
212 
213 
214 void
215 ActivityWindow::_MessageDropped(BMessage* message)
216 {
217 	entry_ref ref;
218 	if (message->FindRef("refs", &ref) != B_OK) {
219 		// TODO: If app, then launch it, and add ActivityView for this one?
220 	}
221 }
222 
223 
224 void
225 ActivityWindow::MessageReceived(BMessage* message)
226 {
227 	if (message->WasDropped()) {
228 		_MessageDropped(message);
229 		return;
230 	}
231 
232 	switch (message->what) {
233 		case B_REFS_RECEIVED:
234 		case B_SIMPLE_DATA:
235 			_MessageDropped(message);
236 			break;
237 
238 		case kMsgAddView:
239 		{
240 #ifdef __HAIKU__
241 			BView* firstView = fLayout->View()->ChildAt(0);
242 
243 			ActivityView* view = new ActivityView("ActivityMonitor", NULL);
244 			fLayout->AddItem(view->CreateHistoryLayoutItem());
245 			fLayout->AddItem(view->CreateLegendLayoutItem());
246 
247 			if (firstView != NULL)
248 				ResizeBy(0, firstView->Bounds().Height() + fLayout->Spacing());
249 #endif
250 			break;
251 		}
252 
253 		case kMsgRemoveView:
254 		{
255 #ifdef __HAIKU__
256 			BView* view;
257 			if (message->FindPointer("view", (void**)&view) != B_OK)
258 				break;
259 
260 			view->RemoveSelf();
261 			ResizeBy(0, -view->Bounds().Height() - fLayout->Spacing());
262 			delete view;
263 #endif
264 			break;
265 		}
266 
267 		default:
268 			BWindow::MessageReceived(message);
269 			break;
270 	}
271 }
272 
273 
274 bool
275 ActivityWindow::QuitRequested()
276 {
277 	_SaveSettings();
278 	be_app->PostMessage(B_QUIT_REQUESTED);
279 	return true;
280 }
281