xref: /haiku/src/apps/haikudepot/ui/ScreenshotWindow.cpp (revision c210060f388242d472176b1fa8603d3a69d1f0c4)
1d5ef985eSStephan Aßmus /*
2d5ef985eSStephan Aßmus  * Copyright 2014, Stephan Aßmus <superstippi@gmx.de>.
339f99591SJulian Harnath  * Copyright 2017, Julian Harnath <julian.harnath@rwth-aachen.de>.
4d5ef985eSStephan Aßmus  * All rights reserved. Distributed under the terms of the MIT License.
5d5ef985eSStephan Aßmus  */
6d5ef985eSStephan Aßmus 
7d5ef985eSStephan Aßmus #include "ScreenshotWindow.h"
8d5ef985eSStephan Aßmus 
9d5ef985eSStephan Aßmus #include <algorithm>
10d5ef985eSStephan Aßmus #include <stdio.h>
11d5ef985eSStephan Aßmus 
12d5ef985eSStephan Aßmus #include <Autolock.h>
13d5ef985eSStephan Aßmus #include <Catalog.h>
14d5ef985eSStephan Aßmus #include <LayoutBuilder.h>
15*c210060fSJulian Harnath #include <StringView.h>
16d5ef985eSStephan Aßmus 
17*c210060fSJulian Harnath #include "BarberPole.h"
18d5ef985eSStephan Aßmus #include "BitmapView.h"
19d5ef985eSStephan Aßmus #include "WebAppInterface.h"
20d5ef985eSStephan Aßmus 
21d5ef985eSStephan Aßmus 
22d5ef985eSStephan Aßmus #undef B_TRANSLATION_CONTEXT
23d5ef985eSStephan Aßmus #define B_TRANSLATION_CONTEXT "ScreenshotWindow"
24d5ef985eSStephan Aßmus 
25d5ef985eSStephan Aßmus 
2639f99591SJulian Harnath static const rgb_color kBackgroundColor = { 51, 102, 152, 255 };
2739f99591SJulian Harnath 	// Drawn as a border around the screenshots and also what's behind their
2839f99591SJulian Harnath 	// transparent regions
2939f99591SJulian Harnath 
3039f99591SJulian Harnath 
31d5ef985eSStephan Aßmus ScreenshotWindow::ScreenshotWindow(BWindow* parent, BRect frame)
32d5ef985eSStephan Aßmus 	:
33d5ef985eSStephan Aßmus 	BWindow(frame, B_TRANSLATE("Screenshot"),
34d5ef985eSStephan Aßmus 		B_FLOATING_WINDOW_LOOK, B_FLOATING_SUBSET_WINDOW_FEEL,
35d5ef985eSStephan Aßmus 		B_ASYNCHRONOUS_CONTROLS | B_AUTO_UPDATE_SIZE_LIMITS),
36*c210060fSJulian Harnath 	fNumScreenshots(0),
37d5ef985eSStephan Aßmus 	fDownloadPending(false),
38d5ef985eSStephan Aßmus 	fWorkerThread(-1)
39d5ef985eSStephan Aßmus {
40d5ef985eSStephan Aßmus 	AddToSubset(parent);
41d5ef985eSStephan Aßmus 
42*c210060fSJulian Harnath 	atomic_set(&fCurrentScreenshotIndex, 0);
43*c210060fSJulian Harnath 
44*c210060fSJulian Harnath 	fBarberPole = new BarberPole("barber pole");
45*c210060fSJulian Harnath 	fBarberPole->SetExplicitMaxSize(BSize(200, B_SIZE_UNLIMITED));
46*c210060fSJulian Harnath 
47*c210060fSJulian Harnath 	fIndexView = new BStringView("screenshot index", NULL);
48*c210060fSJulian Harnath 
49*c210060fSJulian Harnath 	fToolBar = new BToolBar();
50*c210060fSJulian Harnath 	fToolBar->AddAction(MSG_PREVIOUS_SCREENSHOT, this, NULL /* todo: icon */,
51*c210060fSJulian Harnath 		B_TRANSLATE("Show previous screenshot"),
52*c210060fSJulian Harnath 		B_TRANSLATE("Previous"));
53*c210060fSJulian Harnath 	fToolBar->AddAction(MSG_NEXT_SCREENSHOT, this, NULL /* todo: icon */,
54*c210060fSJulian Harnath 		B_TRANSLATE("Show next screenshot"),
55*c210060fSJulian Harnath 		B_TRANSLATE("Next"));
56*c210060fSJulian Harnath 	fToolBar->AddGlue();
57*c210060fSJulian Harnath 	fToolBar->AddView(fIndexView);
58*c210060fSJulian Harnath 	fToolBar->AddGlue();
59*c210060fSJulian Harnath 	fToolBar->AddView(fBarberPole);
60*c210060fSJulian Harnath 
61d5ef985eSStephan Aßmus 	fScreenshotView = new BitmapView("screenshot view");
62d5ef985eSStephan Aßmus 	fScreenshotView->SetExplicitMaxSize(
63d5ef985eSStephan Aßmus 		BSize(B_SIZE_UNLIMITED, B_SIZE_UNLIMITED));
64d5ef985eSStephan Aßmus 
652afa3f3bSStephan Aßmus 	BGroupView* groupView = new BGroupView(B_VERTICAL);
6639f99591SJulian Harnath 	groupView->SetViewColor(kBackgroundColor);
672afa3f3bSStephan Aßmus 
68d5ef985eSStephan Aßmus 	// Build layout
69*c210060fSJulian Harnath 	BLayoutBuilder::Group<>(this, B_VERTICAL, 0)
70*c210060fSJulian Harnath 		.SetInsets(0, 5, 0, 0)
71*c210060fSJulian Harnath 		.Add(fToolBar)
72*c210060fSJulian Harnath 		.AddStrut(5)
732afa3f3bSStephan Aßmus 		.AddGroup(groupView)
74d5ef985eSStephan Aßmus 			.Add(fScreenshotView)
75d5ef985eSStephan Aßmus 			.SetInsets(B_USE_WINDOW_INSETS)
762afa3f3bSStephan Aßmus 		.End()
77d5ef985eSStephan Aßmus 	;
78d5ef985eSStephan Aßmus 
7939f99591SJulian Harnath 	fScreenshotView->SetLowColor(kBackgroundColor);
8039f99591SJulian Harnath 		// Set after attaching all views to prevent it from being overriden
8139f99591SJulian Harnath 		// again by BitmapView::AllAttached()
8239f99591SJulian Harnath 
832afa3f3bSStephan Aßmus 	CenterOnScreen();
84d5ef985eSStephan Aßmus }
85d5ef985eSStephan Aßmus 
86d5ef985eSStephan Aßmus 
87d5ef985eSStephan Aßmus ScreenshotWindow::~ScreenshotWindow()
88d5ef985eSStephan Aßmus {
89d5ef985eSStephan Aßmus 	BAutolock locker(&fLock);
90d5ef985eSStephan Aßmus 
91d5ef985eSStephan Aßmus 	if (fWorkerThread >= 0)
92d5ef985eSStephan Aßmus 		wait_for_thread(fWorkerThread, NULL);
93d5ef985eSStephan Aßmus }
94d5ef985eSStephan Aßmus 
95d5ef985eSStephan Aßmus 
96d5ef985eSStephan Aßmus bool
97d5ef985eSStephan Aßmus ScreenshotWindow::QuitRequested()
98d5ef985eSStephan Aßmus {
99d5ef985eSStephan Aßmus 	if (fOnCloseTarget.IsValid() && fOnCloseMessage.what != 0)
100d5ef985eSStephan Aßmus 		fOnCloseTarget.SendMessage(&fOnCloseMessage);
101d5ef985eSStephan Aßmus 
102d5ef985eSStephan Aßmus 	Hide();
103d5ef985eSStephan Aßmus 	return false;
104d5ef985eSStephan Aßmus }
105d5ef985eSStephan Aßmus 
106d5ef985eSStephan Aßmus 
107d5ef985eSStephan Aßmus void
108d5ef985eSStephan Aßmus ScreenshotWindow::MessageReceived(BMessage* message)
109d5ef985eSStephan Aßmus {
110d5ef985eSStephan Aßmus 	switch (message->what) {
111*c210060fSJulian Harnath 		case MSG_NEXT_SCREENSHOT:
112*c210060fSJulian Harnath 		{
113*c210060fSJulian Harnath 			atomic_add(&fCurrentScreenshotIndex, 1);
114*c210060fSJulian Harnath 			_UpdateToolBar();
115*c210060fSJulian Harnath 			_DownloadScreenshot();
116*c210060fSJulian Harnath 			break;
117*c210060fSJulian Harnath 		}
118*c210060fSJulian Harnath 
119*c210060fSJulian Harnath 		case MSG_PREVIOUS_SCREENSHOT:
120*c210060fSJulian Harnath 			atomic_add(&fCurrentScreenshotIndex, -1);
121*c210060fSJulian Harnath 			_UpdateToolBar();
122*c210060fSJulian Harnath 			_DownloadScreenshot();
123*c210060fSJulian Harnath 			break;
124*c210060fSJulian Harnath 
125*c210060fSJulian Harnath 		case MSG_DOWNLOAD_START:
126*c210060fSJulian Harnath 			fBarberPole->Start();
127*c210060fSJulian Harnath 			break;
128*c210060fSJulian Harnath 
129*c210060fSJulian Harnath 		case MSG_DOWNLOAD_STOP:
130*c210060fSJulian Harnath 			fBarberPole->Stop();
131*c210060fSJulian Harnath 			break;
132*c210060fSJulian Harnath 
133d5ef985eSStephan Aßmus 		default:
134d5ef985eSStephan Aßmus 			BWindow::MessageReceived(message);
135d5ef985eSStephan Aßmus 			break;
136d5ef985eSStephan Aßmus 	}
137d5ef985eSStephan Aßmus }
138d5ef985eSStephan Aßmus 
139d5ef985eSStephan Aßmus 
140d5ef985eSStephan Aßmus void
141d5ef985eSStephan Aßmus ScreenshotWindow::SetOnCloseMessage(
142d5ef985eSStephan Aßmus 	const BMessenger& messenger, const BMessage& message)
143d5ef985eSStephan Aßmus {
144d5ef985eSStephan Aßmus 	fOnCloseTarget = messenger;
145d5ef985eSStephan Aßmus 	fOnCloseMessage = message;
146d5ef985eSStephan Aßmus }
147d5ef985eSStephan Aßmus 
148d5ef985eSStephan Aßmus 
149d5ef985eSStephan Aßmus void
150d5ef985eSStephan Aßmus ScreenshotWindow::SetPackage(const PackageInfoRef& package)
151d5ef985eSStephan Aßmus {
152d5ef985eSStephan Aßmus 	if (fPackage == package)
153d5ef985eSStephan Aßmus 		return;
154d5ef985eSStephan Aßmus 
155d5ef985eSStephan Aßmus 	fPackage = package;
156d5ef985eSStephan Aßmus 
157d5ef985eSStephan Aßmus 	BString title = B_TRANSLATE("Screenshot");
158d5ef985eSStephan Aßmus 	if (package.Get() != NULL) {
159d5ef985eSStephan Aßmus 		title = package->Title();
160d5ef985eSStephan Aßmus 		_DownloadScreenshot();
161d5ef985eSStephan Aßmus 	}
162d5ef985eSStephan Aßmus 	SetTitle(title);
163*c210060fSJulian Harnath 
164*c210060fSJulian Harnath 	atomic_set(&fCurrentScreenshotIndex, 0);
165*c210060fSJulian Harnath 	fNumScreenshots = fPackage->ScreenshotInfos().CountItems();
166*c210060fSJulian Harnath 
167*c210060fSJulian Harnath 	_UpdateToolBar();
168d5ef985eSStephan Aßmus }
169d5ef985eSStephan Aßmus 
170d5ef985eSStephan Aßmus 
171d5ef985eSStephan Aßmus // #pragma mark - private
172d5ef985eSStephan Aßmus 
173d5ef985eSStephan Aßmus 
174d5ef985eSStephan Aßmus void
175d5ef985eSStephan Aßmus ScreenshotWindow::_DownloadScreenshot()
176d5ef985eSStephan Aßmus {
177d5ef985eSStephan Aßmus 	BAutolock locker(&fLock);
178d5ef985eSStephan Aßmus 
179d5ef985eSStephan Aßmus 	if (fWorkerThread >= 0) {
180d5ef985eSStephan Aßmus 		fDownloadPending = true;
181d5ef985eSStephan Aßmus 		return;
182d5ef985eSStephan Aßmus 	}
183d5ef985eSStephan Aßmus 
184d5ef985eSStephan Aßmus 	thread_id thread = spawn_thread(&_DownloadThreadEntry,
185d5ef985eSStephan Aßmus 		"Screenshot Loader", B_NORMAL_PRIORITY, this);
186d5ef985eSStephan Aßmus 	if (thread >= 0)
187d5ef985eSStephan Aßmus 		_SetWorkerThread(thread);
188d5ef985eSStephan Aßmus }
189d5ef985eSStephan Aßmus 
190d5ef985eSStephan Aßmus 
191d5ef985eSStephan Aßmus void
192d5ef985eSStephan Aßmus ScreenshotWindow::_SetWorkerThread(thread_id thread)
193d5ef985eSStephan Aßmus {
194d5ef985eSStephan Aßmus 	if (!Lock())
195d5ef985eSStephan Aßmus 		return;
196d5ef985eSStephan Aßmus 
197d5ef985eSStephan Aßmus //	bool enabled = thread < 0;
198d5ef985eSStephan Aßmus //
199d5ef985eSStephan Aßmus //	fPreviewsButton->SetEnabled(enabled);
200d5ef985eSStephan Aßmus //	fNextButton->SetEnabled(enabled);
201d5ef985eSStephan Aßmus //	fCloseButton->SetEnabled(enabled);
202d5ef985eSStephan Aßmus 
203d5ef985eSStephan Aßmus 	if (thread >= 0) {
204d5ef985eSStephan Aßmus 		fWorkerThread = thread;
205d5ef985eSStephan Aßmus 		resume_thread(fWorkerThread);
206d5ef985eSStephan Aßmus 	} else {
207d5ef985eSStephan Aßmus 		fWorkerThread = -1;
208d5ef985eSStephan Aßmus 
209d5ef985eSStephan Aßmus 		if (fDownloadPending) {
210d5ef985eSStephan Aßmus 			_DownloadScreenshot();
211d5ef985eSStephan Aßmus 			fDownloadPending = false;
212d5ef985eSStephan Aßmus 		}
213d5ef985eSStephan Aßmus 	}
214d5ef985eSStephan Aßmus 
215d5ef985eSStephan Aßmus 	Unlock();
216d5ef985eSStephan Aßmus }
217d5ef985eSStephan Aßmus 
218d5ef985eSStephan Aßmus 
219d5ef985eSStephan Aßmus int32
220d5ef985eSStephan Aßmus ScreenshotWindow::_DownloadThreadEntry(void* data)
221d5ef985eSStephan Aßmus {
222d5ef985eSStephan Aßmus 	ScreenshotWindow* window
223d5ef985eSStephan Aßmus 		= reinterpret_cast<ScreenshotWindow*>(data);
224d5ef985eSStephan Aßmus 	window->_DownloadThread();
225d5ef985eSStephan Aßmus 	window->_SetWorkerThread(-1);
226d5ef985eSStephan Aßmus 	return 0;
227d5ef985eSStephan Aßmus }
228d5ef985eSStephan Aßmus 
229d5ef985eSStephan Aßmus 
230d5ef985eSStephan Aßmus void
231d5ef985eSStephan Aßmus ScreenshotWindow::_DownloadThread()
232d5ef985eSStephan Aßmus {
233d5ef985eSStephan Aßmus 	printf("_DownloadThread()\n");
234d5ef985eSStephan Aßmus 	if (!Lock()) {
235d5ef985eSStephan Aßmus 		printf("  failed to lock screenshot window\n");
236d5ef985eSStephan Aßmus 		return;
237d5ef985eSStephan Aßmus 	}
238d5ef985eSStephan Aßmus 
2392a36368bSMichael Lotz 	fScreenshotView->UnsetBitmap();
240d5ef985eSStephan Aßmus 
241d5ef985eSStephan Aßmus 	ScreenshotInfoList screenshotInfos;
242d5ef985eSStephan Aßmus 	if (fPackage.Get() != NULL)
243d5ef985eSStephan Aßmus 		screenshotInfos = fPackage->ScreenshotInfos();
244d5ef985eSStephan Aßmus 
245d5ef985eSStephan Aßmus 	Unlock();
246d5ef985eSStephan Aßmus 
247d5ef985eSStephan Aßmus 	if (screenshotInfos.CountItems() == 0) {
248d5ef985eSStephan Aßmus 		printf("  package has no screenshots\n");
249d5ef985eSStephan Aßmus 		return;
250d5ef985eSStephan Aßmus 	}
251d5ef985eSStephan Aßmus 
252d5ef985eSStephan Aßmus 	// Obtain the correct code for the screenshot to display
253d5ef985eSStephan Aßmus 	// TODO: Once navigation buttons are added, we could use the
254d5ef985eSStephan Aßmus 	// ScreenshotInfo at the "current" index.
255*c210060fSJulian Harnath 	const ScreenshotInfo& info = screenshotInfos.ItemAtFast(
256*c210060fSJulian Harnath 		atomic_get(&fCurrentScreenshotIndex));
257d5ef985eSStephan Aßmus 
258d5ef985eSStephan Aßmus 	BMallocIO buffer;
259d5ef985eSStephan Aßmus 	WebAppInterface interface;
260d5ef985eSStephan Aßmus 
261*c210060fSJulian Harnath 	BMessenger messenger(this);
262*c210060fSJulian Harnath 	messenger.SendMessage(MSG_DOWNLOAD_START);
263*c210060fSJulian Harnath 
264d5ef985eSStephan Aßmus 	// Retrieve screenshot from web-app
265d5ef985eSStephan Aßmus 	status_t status = interface.RetrieveScreenshot(info.Code(),
266d5ef985eSStephan Aßmus 		info.Width(), info.Height(), &buffer);
267*c210060fSJulian Harnath 
268*c210060fSJulian Harnath 	messenger.SendMessage(MSG_DOWNLOAD_STOP);
269*c210060fSJulian Harnath 
270d5ef985eSStephan Aßmus 	if (status == B_OK && Lock()) {
271d5ef985eSStephan Aßmus 		printf("got screenshot");
272d5ef985eSStephan Aßmus 		fScreenshot = BitmapRef(new(std::nothrow)SharedBitmap(buffer), true);
2732a36368bSMichael Lotz 		fScreenshotView->SetBitmap(fScreenshot);
2742afa3f3bSStephan Aßmus 		_ResizeToFitAndCenter();
275d5ef985eSStephan Aßmus 		Unlock();
276d5ef985eSStephan Aßmus 	} else {
277d5ef985eSStephan Aßmus 		printf("  failed to download screenshot\n");
278d5ef985eSStephan Aßmus 	}
279d5ef985eSStephan Aßmus }
2802afa3f3bSStephan Aßmus 
2812afa3f3bSStephan Aßmus 
2822afa3f3bSStephan Aßmus void
2832afa3f3bSStephan Aßmus ScreenshotWindow::_ResizeToFitAndCenter()
2842afa3f3bSStephan Aßmus {
2852afa3f3bSStephan Aßmus 	float minWidth;
2862afa3f3bSStephan Aßmus 	float minHeight;
2872afa3f3bSStephan Aßmus 	GetSizeLimits(&minWidth, NULL, &minHeight, NULL);
2882afa3f3bSStephan Aßmus 	ResizeTo(minWidth, minHeight);
2892afa3f3bSStephan Aßmus 	CenterOnScreen();
2902afa3f3bSStephan Aßmus }
291*c210060fSJulian Harnath 
292*c210060fSJulian Harnath 
293*c210060fSJulian Harnath void
294*c210060fSJulian Harnath ScreenshotWindow::_UpdateToolBar()
295*c210060fSJulian Harnath {
296*c210060fSJulian Harnath 	int32 currentIndex = atomic_get(&fCurrentScreenshotIndex);
297*c210060fSJulian Harnath 	fToolBar->SetActionEnabled(MSG_PREVIOUS_SCREENSHOT,
298*c210060fSJulian Harnath 		currentIndex > 0);
299*c210060fSJulian Harnath 	fToolBar->SetActionEnabled(MSG_NEXT_SCREENSHOT,
300*c210060fSJulian Harnath 		currentIndex < fNumScreenshots - 2);
301*c210060fSJulian Harnath 
302*c210060fSJulian Harnath 	BString text;
303*c210060fSJulian Harnath 	text << currentIndex + 1;
304*c210060fSJulian Harnath 	text << " / ";
305*c210060fSJulian Harnath 	text << fNumScreenshots;
306*c210060fSJulian Harnath 	fIndexView->SetText(text);
307*c210060fSJulian Harnath }
308