repository_infos: Enable automatic updates on the main Haiku repostiory.
[haiku.git] / src / apps / activitymonitor / ActivityWindow.cpp
blobf72794c161cbd8afb08e0cb6d7fadcfa582a3b7c
1 /*
2 * Copyright 2008-2015, Axel Dörfler, axeld@pinc-software.de.
3 * Distributed under the terms of the MIT License.
4 */
7 #include "ActivityWindow.h"
9 #include <stdio.h>
11 #include <Application.h>
12 #include <Catalog.h>
13 #include <File.h>
14 #include <FindDirectory.h>
15 #ifdef __HAIKU__
16 #include <GroupLayout.h>
17 #endif
18 #include <Menu.h>
19 #include <MenuBar.h>
20 #include <MenuItem.h>
21 #include <Path.h>
22 #include <Roster.h>
24 #include "ActivityMonitor.h"
25 #include "ActivityView.h"
26 #include "DataSource.h"
27 #include "SettingsWindow.h"
29 #undef B_TRANSLATION_CONTEXT
30 #define B_TRANSLATION_CONTEXT "ActivityWindow"
33 static const uint32 kMsgAddView = 'advw';
34 static const uint32 kMsgAlwaysOnTop = 'alot';
35 static const uint32 kMsgShowSettings = 'shst';
38 ActivityWindow::ActivityWindow()
40 BWindow(BRect(100, 100, 500, 350), B_TRANSLATE_SYSTEM_NAME("ActivityMonitor"),
41 B_TITLED_WINDOW, B_ASYNCHRONOUS_CONTROLS | B_QUIT_ON_WINDOW_CLOSE)
43 BMessage settings;
44 _LoadSettings(settings);
46 BRect frame;
47 if (settings.FindRect("window frame", &frame) == B_OK) {
48 MoveTo(frame.LeftTop());
49 ResizeTo(frame.Width(), frame.Height());
50 } else {
51 float scaling = be_plain_font->Size() / 12.0f;
52 ResizeTo(Frame().Width() * scaling, Frame().Height() * scaling);
53 CenterOnScreen();
56 #ifdef __HAIKU__
57 BGroupLayout* layout = new BGroupLayout(B_VERTICAL, 0);
58 SetLayout(layout);
60 // create GUI
62 BMenuBar* menuBar = new BMenuBar("menu");
63 layout->AddView(menuBar);
65 fLayout = new BGroupLayout(B_VERTICAL);
66 float inset = ceilf(be_plain_font->Size() * 0.7);
67 fLayout->SetInsets(B_USE_WINDOW_SPACING);
68 fLayout->SetSpacing(inset);
70 BView* top = new BView("top", 0, fLayout);
71 layout->AddView(top);
72 top->SetViewUIColor(B_PANEL_BACKGROUND_COLOR);
74 BMessage viewState;
75 int32 count = 0;
76 for (int32 i = 0; settings.FindMessage("activity view", i, &viewState)
77 == B_OK; i++) {
78 ActivityView* view = new ActivityView("ActivityMonitor", &viewState);
79 fLayout->AddItem(view->CreateHistoryLayoutItem());
80 fLayout->AddItem(view->CreateLegendLayoutItem());
81 count++;
83 if (count == 0) {
84 // Add default views (memory & CPU usage)
85 _AddDefaultView();
86 _AddDefaultView();
88 #else // !__HAIKU__
89 BView *layout = new BView(Bounds(), "topmost", B_FOLLOW_NONE, 0);
90 AddChild(layout);
92 // create GUI
93 BRect mbRect(Bounds());
94 mbRect.bottom = 10;
95 BMenuBar* menuBar = new BMenuBar(mbRect, "menu");
96 layout->AddChild(menuBar);
98 BRect topRect(Bounds());
99 topRect.top = menuBar->Bounds().bottom + 1;
101 BView* top = new BView(topRect, "top", B_FOLLOW_ALL, 0);
102 layout->AddChild(top);
104 BMessage viewState;
105 int32 count = 0;
106 ActivityView *aview;
107 BRect rect;
108 for (int32 i = 0; settings.FindMessage("activity view", i, &viewState)
109 == B_OK; i++) {
110 aview = new ActivityView("ActivityMonitor", &viewState);
111 if (!rect.IsValid())
112 rect = aview->Bounds();
113 else
114 rect.OffsetBySelf(0.0, aview->Bounds().Height());
115 top->AddChild(aview);
116 count++;
118 if (count == 0)
119 top->AddChild(new ActivityView("ActivityMonitor", NULL));
121 #endif
122 // add menu
124 // "File" menu
125 BMenu* menu = new BMenu(B_TRANSLATE("File"));
126 menu->AddItem(new BMenuItem(B_TRANSLATE("Add graph"),
127 new BMessage(kMsgAddView)));
128 menu->AddSeparatorItem();
130 menu->AddItem(new BMenuItem(B_TRANSLATE("Quit"),
131 new BMessage(B_QUIT_REQUESTED), 'Q'));
132 menu->SetTargetForItems(this);
133 menuBar->AddItem(menu);
135 // "Settings" menu
136 menu = new BMenu(B_TRANSLATE("Settings"));
137 menu->AddItem(new BMenuItem(B_TRANSLATE("Settings" B_UTF8_ELLIPSIS),
138 new BMessage(kMsgShowSettings)));
140 menu->AddSeparatorItem();
141 fAlwaysOnTop = new BMenuItem(B_TRANSLATE("Always on top"), new BMessage(kMsgAlwaysOnTop));
142 _SetAlwaysOnTop(settings.GetBool("always on top", false));
143 menu->AddItem(fAlwaysOnTop);
145 menu->SetTargetForItems(this);
146 menuBar->AddItem(menu);
150 ActivityWindow::~ActivityWindow()
155 void
156 ActivityWindow::MessageReceived(BMessage* message)
158 if (message->WasDropped()) {
159 _MessageDropped(message);
160 return;
163 switch (message->what) {
164 case B_REFS_RECEIVED:
165 case B_SIMPLE_DATA:
166 _MessageDropped(message);
167 break;
169 case kMsgAddView:
171 #ifdef __HAIKU__
172 BView* firstView = fLayout->View()->ChildAt(0);
174 _AddDefaultView();
176 if (firstView != NULL)
177 ResizeBy(0, firstView->Bounds().Height() + fLayout->Spacing());
178 #endif
179 break;
182 case kMsgRemoveView:
184 #ifdef __HAIKU__
185 BView* view;
186 if (message->FindPointer("view", (void**)&view) != B_OK)
187 break;
189 view->RemoveSelf();
190 ResizeBy(0, -view->Bounds().Height() - fLayout->Spacing());
191 delete view;
192 #endif
193 break;
196 case kMsgShowSettings:
198 if (fSettingsWindow.IsValid()) {
199 // Just bring the window to front (via scripting)
200 BMessage toFront(B_SET_PROPERTY);
201 toFront.AddSpecifier("Active");
202 toFront.AddBool("data", true);
203 fSettingsWindow.SendMessage(&toFront);
204 } else {
205 // Open new settings window
206 BWindow* window = new SettingsWindow(this);
207 window->Show();
209 fSettingsWindow = window;
211 break;
214 case kMsgAlwaysOnTop:
216 _SetAlwaysOnTop(!fAlwaysOnTop->IsMarked());
217 break;
220 case kMsgTimeIntervalUpdated:
221 BroadcastToActivityViews(message);
222 break;
224 default:
225 BWindow::MessageReceived(message);
226 break;
231 bool
232 ActivityWindow::QuitRequested()
234 _SaveSettings();
235 be_app->PostMessage(B_QUIT_REQUESTED);
236 return true;
240 int32
241 ActivityWindow::ActivityViewCount() const
243 #ifdef __HAIKU__
244 return fLayout->View()->CountChildren();
245 #else
246 return 1;
247 #endif
251 ActivityView*
252 ActivityWindow::ActivityViewAt(int32 index) const
254 return dynamic_cast<ActivityView*>(fLayout->View()->ChildAt(index));
258 bool
259 ActivityWindow::IsAlwaysOnTop() const
261 return fAlwaysOnTop->IsMarked();
265 void
266 ActivityWindow::BroadcastToActivityViews(BMessage* message, BView* exceptToView)
268 BView* view;
269 for (int32 i = 0; (view = ActivityViewAt(i)) != NULL; i++) {
270 if (view != exceptToView)
271 PostMessage(message, view);
276 bigtime_t
277 ActivityWindow::RefreshInterval() const
279 ActivityView* view = ActivityViewAt(0);
280 if (view != 0)
281 return view->RefreshInterval();
283 return 100000;
287 status_t
288 ActivityWindow::_OpenSettings(BFile& file, uint32 mode)
290 BPath path;
291 if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK)
292 return B_ERROR;
294 path.Append("ActivityMonitor settings");
296 return file.SetTo(path.Path(), mode);
300 status_t
301 ActivityWindow::_LoadSettings(BMessage& settings)
303 BFile file;
304 status_t status = _OpenSettings(file, B_READ_ONLY);
305 if (status < B_OK)
306 return status;
308 return settings.Unflatten(&file);
312 status_t
313 ActivityWindow::_SaveSettings()
315 BFile file;
316 status_t status = _OpenSettings(file, B_WRITE_ONLY | B_CREATE_FILE
317 | B_ERASE_FILE);
318 if (status < B_OK)
319 return status;
321 BMessage settings('actm');
322 status = settings.AddRect("window frame", Frame());
323 if (status != B_OK)
324 return status;
326 status = settings.SetBool("always on top", fAlwaysOnTop->IsMarked());
327 if (status != B_OK)
328 return status;
330 #ifdef __HAIKU__
331 BView* top = fLayout->View();
332 #else
333 BView* top = ChildAt(0);
334 #endif
335 int32 count = top->CountChildren();
336 for (int32 i = 0; i < count; i++) {
337 ActivityView* view = dynamic_cast<ActivityView*>(top->ChildAt(i));
338 if (view == NULL)
339 continue;
341 BMessage viewState;
342 status = view->SaveState(viewState);
343 if (status == B_OK)
344 status = settings.AddMessage("activity view", &viewState);
345 if (status != B_OK)
346 break;
349 if (status == B_OK)
350 status = settings.Flatten(&file);
352 return status;
356 void
357 ActivityWindow::_AddDefaultView()
359 BMessage settings;
360 settings.AddInt64("refresh interval", RefreshInterval());
362 ActivityView* view = new ActivityView("ActivityMonitor", &settings);
364 switch (ActivityViewCount()) {
365 case 0:
366 // The first view defaults to memory usage
367 view->AddDataSource(new UsedMemoryDataSource());
368 view->AddDataSource(new CachedMemoryDataSource());
369 break;
370 case 2:
371 // The third view defaults to network in/out
372 view->AddDataSource(new NetworkUsageDataSource(true));
373 view->AddDataSource(new NetworkUsageDataSource(false));
374 break;
375 case 1:
376 default:
377 // Everything beyond that defaults to a CPU usage view
378 view->AddDataSource(new CPUUsageDataSource());
379 break;
382 fLayout->AddItem(view->CreateHistoryLayoutItem());
383 fLayout->AddItem(view->CreateLegendLayoutItem());
387 void
388 ActivityWindow::_MessageDropped(BMessage* message)
390 entry_ref ref;
391 if (message->FindRef("refs", &ref) != B_OK) {
392 // TODO: If app, then launch it, and add ActivityView for this one?
397 void
398 ActivityWindow::_SetAlwaysOnTop(bool alwaysOnTop)
400 SetFeel(alwaysOnTop ? B_FLOATING_ALL_WINDOW_FEEL : B_NORMAL_WINDOW_FEEL);
401 fAlwaysOnTop->SetMarked(alwaysOnTop);
402 if (fSettingsWindow.IsValid() && alwaysOnTop) {
403 // Change the settings window feel to modal (via scripting)
404 BMessage toFront(B_SET_PROPERTY);
405 toFront.AddSpecifier("Feel");
406 toFront.AddInt32("data", B_MODAL_ALL_WINDOW_FEEL);
407 fSettingsWindow.SendMessage(&toFront);