1/*
2 * Copyright 2007-2015, Axel D��rfler, axeld@pinc-software.de.
3 * Distributed under the terms of the MIT License.
4 */
5
6
7#include "ProgressWindow.h"
8
9#include <Autolock.h>
10#include <Button.h>
11#include <Catalog.h>
12#include <MessageRunner.h>
13#include <Screen.h>
14#include <StatusBar.h>
15
16#include <stdio.h>
17
18
19#undef B_TRANSLATION_CONTEXT
20#define B_TRANSLATION_CONTEXT "ProgressWindow"
21
22
23static const uint32 kMsgShow = 'show';
24
25
26ProgressWindow::ProgressWindow(BWindow* referenceWindow,
27		BMessage* abortMessage)
28	: BWindow(BRect(0, 0, 250, 100), B_TRANSLATE("Progress monitor"),
29		B_MODAL_WINDOW_LOOK, B_FLOATING_APP_WINDOW_FEEL,
30		B_NOT_ZOOMABLE | B_NOT_RESIZABLE | B_ASYNCHRONOUS_CONTROLS
31			| B_NO_WORKSPACE_ACTIVATION),
32	fRunner(NULL)
33{
34	BRect rect = Bounds();
35
36	BView *view = new BView(rect, NULL, B_FOLLOW_ALL, B_WILL_DRAW);
37	view->SetViewUIColor(B_PANEL_BACKGROUND_COLOR);
38	AddChild(view);
39
40	rect = view->Bounds().InsetByCopy(8, 8);
41	fStatusBar = new BStatusBar(rect, "status", NULL, NULL);
42	float width, height;
43	fStatusBar->GetPreferredSize(&width, &height);
44	fStatusBar->ResizeTo(rect.Width(), height);
45	fStatusBar->SetResizingMode(B_FOLLOW_TOP | B_FOLLOW_LEFT_RIGHT);
46	view->AddChild(fStatusBar);
47
48	if (abortMessage != NULL && referenceWindow) {
49		rect.top += height + 8;
50		BButton* button = new BButton(rect, "abort", B_TRANSLATE("Abort"),
51			abortMessage);
52		button->ResizeToPreferred();
53		button->MoveBy((rect.Width() - button->Bounds().Width()) / 2, 0);
54		view->AddChild(button);
55		button->SetTarget(referenceWindow);
56		height = button->Frame().bottom;
57	}
58
59	ResizeTo(Bounds().Width(), height + 8);
60	_Center(referenceWindow);
61	Run();
62}
63
64
65ProgressWindow::~ProgressWindow()
66{
67	delete fRunner;
68}
69
70
71void
72ProgressWindow::_Center(BWindow* referenceWindow)
73{
74	BRect frame;
75	if (referenceWindow != NULL)
76		frame = referenceWindow->Frame();
77	else
78		frame = BScreen().Frame();
79
80	MoveTo(frame.left + (frame.Width() - Bounds().Width()) / 2,
81		frame.top + (frame.Height() - Bounds().Height()) / 2);
82}
83
84void
85ProgressWindow::Start(BWindow* referenceWindow)
86{
87	BAutolock _(this);
88
89	_Center(referenceWindow);
90
91	if (referenceWindow != NULL)
92		SetWorkspaces(referenceWindow->Workspaces());
93
94	fRetrievedUpdate = false;
95	fRetrievedShow = false;
96	delete fRunner;
97
98	BMessage show(kMsgShow);
99	fRunner = new BMessageRunner(this, &show, 1000000, 1);
100}
101
102
103void
104ProgressWindow::Stop()
105{
106	BAutolock _(this);
107
108	delete fRunner;
109	fRunner = NULL;
110
111	if (!IsHidden())
112		Hide();
113}
114
115
116void
117ProgressWindow::MessageReceived(BMessage *message)
118{
119	switch (message->what) {
120		case kMsgShow:
121			if (fRetrievedUpdate && IsHidden()) {
122				Show();
123				Minimize(false);
124			}
125
126			fRetrievedShow = true;
127			break;
128
129		case kMsgProgressStatusUpdate:
130			float percent;
131			if (message->FindFloat("percent", &percent) == B_OK)
132				fStatusBar->Update(percent - fStatusBar->CurrentValue());
133
134			const char *text;
135			if (message->FindString("message", &text) == B_OK)
136				fStatusBar->SetText(text);
137
138			fRetrievedUpdate = true;
139
140			if (fRetrievedShow && IsHidden()) {
141				Show();
142				Minimize(false);
143			}
144			break;
145
146		default:
147			BWindow::MessageReceived(message);
148			break;
149	}
150}
151