2 * Copyright 2014, Stephan Aßmus <superstippi@gmx.de>.
3 * Copyright 2017, Julian Harnath <julian.harnath@rwth-aachen.de>.
4 * All rights reserved. Distributed under the terms of the MIT License.
7 #include "ScreenshotWindow.h"
14 #include <LayoutBuilder.h>
15 #include <MessageRunner.h>
16 #include <StringView.h>
18 #include "BarberPole.h"
19 #include "BitmapView.h"
20 #include "WebAppInterface.h"
23 #undef B_TRANSLATION_CONTEXT
24 #define B_TRANSLATION_CONTEXT "ScreenshotWindow"
27 static const rgb_color kBackgroundColor
= { 51, 102, 152, 255 };
28 // Drawn as a border around the screenshots and also what's behind their
29 // transparent regions
31 static BitmapRef
sNextButtonIcon(
32 new(std::nothrow
) SharedBitmap(505), true);
33 static BitmapRef
sPreviousButtonIcon(
34 new(std::nothrow
) SharedBitmap(506), true);
37 ScreenshotWindow::ScreenshotWindow(BWindow
* parent
, BRect frame
)
39 BWindow(frame
, B_TRANSLATE("Screenshot"),
40 B_FLOATING_WINDOW_LOOK
, B_FLOATING_SUBSET_WINDOW_FEEL
,
41 B_ASYNCHRONOUS_CONTROLS
| B_AUTO_UPDATE_SIZE_LIMITS
),
42 fBarberPoleShown(false),
43 fDownloadPending(false),
48 atomic_set(&fCurrentScreenshotIndex
, 0);
50 fBarberPole
= new BarberPole("barber pole");
51 fBarberPole
->SetExplicitMaxSize(BSize(100, B_SIZE_UNLIMITED
));
54 fIndexView
= new BStringView("screenshot index", NULL
);
56 fToolBar
= new BToolBar();
57 fToolBar
->AddAction(MSG_PREVIOUS_SCREENSHOT
, this,
58 sNextButtonIcon
->Bitmap(SharedBitmap::SIZE_22
),
60 fToolBar
->AddAction(MSG_NEXT_SCREENSHOT
, this,
61 sPreviousButtonIcon
->Bitmap(SharedBitmap::SIZE_22
),
63 fToolBar
->AddView(fIndexView
);
65 fToolBar
->AddView(fBarberPole
);
67 fScreenshotView
= new BitmapView("screenshot view");
68 fScreenshotView
->SetExplicitMaxSize(
69 BSize(B_SIZE_UNLIMITED
, B_SIZE_UNLIMITED
));
70 fScreenshotView
->SetScaleBitmap(false);
72 BGroupView
* groupView
= new BGroupView(B_VERTICAL
);
73 groupView
->SetViewColor(kBackgroundColor
);
76 BLayoutBuilder::Group
<>(this, B_VERTICAL
, 0)
77 .SetInsets(0, 3, 0, 0)
82 .SetInsets(B_USE_WINDOW_INSETS
)
86 fScreenshotView
->SetLowColor(kBackgroundColor
);
87 // Set after attaching all views to prevent it from being overriden
88 // again by BitmapView::AllAttached()
94 ScreenshotWindow::~ScreenshotWindow()
96 BAutolock
locker(&fLock
);
98 if (fWorkerThread
>= 0)
99 wait_for_thread(fWorkerThread
, NULL
);
104 ScreenshotWindow::QuitRequested()
106 if (fOnCloseTarget
.IsValid() && fOnCloseMessage
.what
!= 0)
107 fOnCloseTarget
.SendMessage(&fOnCloseMessage
);
115 ScreenshotWindow::MessageReceived(BMessage
* message
)
117 switch (message
->what
) {
118 case MSG_NEXT_SCREENSHOT
:
120 atomic_add(&fCurrentScreenshotIndex
, 1);
122 _DownloadScreenshot();
126 case MSG_PREVIOUS_SCREENSHOT
:
127 atomic_add(&fCurrentScreenshotIndex
, -1);
129 _DownloadScreenshot();
132 case MSG_DOWNLOAD_START
:
133 if (!fBarberPoleShown
) {
134 fBarberPole
->Start();
136 fBarberPoleShown
= true;
140 case MSG_DOWNLOAD_STOP
:
141 if (fBarberPoleShown
) {
144 fBarberPoleShown
= true;
149 BWindow::MessageReceived(message
);
156 ScreenshotWindow::SetOnCloseMessage(
157 const BMessenger
& messenger
, const BMessage
& message
)
159 fOnCloseTarget
= messenger
;
160 fOnCloseMessage
= message
;
165 ScreenshotWindow::SetPackage(const PackageInfoRef
& package
)
167 if (fPackage
== package
)
172 BString title
= B_TRANSLATE("Screenshot");
173 if (package
.Get() != NULL
) {
174 title
= package
->Title();
175 _DownloadScreenshot();
179 atomic_set(&fCurrentScreenshotIndex
, 0);
186 ScreenshotWindow::CleanupIcons()
188 sNextButtonIcon
.Unset();
189 sPreviousButtonIcon
.Unset();
193 // #pragma mark - private
197 ScreenshotWindow::_DownloadScreenshot()
199 BAutolock
locker(&fLock
);
201 if (fWorkerThread
>= 0) {
202 fDownloadPending
= true;
206 thread_id thread
= spawn_thread(&_DownloadThreadEntry
,
207 "Screenshot Loader", B_NORMAL_PRIORITY
, this);
209 _SetWorkerThread(thread
);
214 ScreenshotWindow::_SetWorkerThread(thread_id thread
)
219 // bool enabled = thread < 0;
221 // fPreviewsButton->SetEnabled(enabled);
222 // fNextButton->SetEnabled(enabled);
223 // fCloseButton->SetEnabled(enabled);
226 fWorkerThread
= thread
;
227 resume_thread(fWorkerThread
);
231 if (fDownloadPending
) {
232 _DownloadScreenshot();
233 fDownloadPending
= false;
242 ScreenshotWindow::_DownloadThreadEntry(void* data
)
244 ScreenshotWindow
* window
245 = reinterpret_cast<ScreenshotWindow
*>(data
);
246 window
->_DownloadThread();
247 window
->_SetWorkerThread(-1);
253 ScreenshotWindow::_DownloadThread()
255 printf("_DownloadThread()\n");
257 printf(" failed to lock screenshot window\n");
261 fScreenshotView
->UnsetBitmap();
263 ScreenshotInfoList screenshotInfos
;
264 if (fPackage
.Get() != NULL
)
265 screenshotInfos
= fPackage
->ScreenshotInfos();
269 if (screenshotInfos
.CountItems() == 0) {
270 printf(" package has no screenshots\n");
274 // Obtain the correct code for the screenshot to display
275 // TODO: Once navigation buttons are added, we could use the
276 // ScreenshotInfo at the "current" index.
277 const ScreenshotInfo
& info
= screenshotInfos
.ItemAtFast(
278 atomic_get(&fCurrentScreenshotIndex
));
281 WebAppInterface interface
;
283 // Only indicate being busy with the download if it takes a little while
284 BMessenger
messenger(this);
285 BMessageRunner
delayedMessenger(messenger
,
286 new BMessage(MSG_DOWNLOAD_START
),
287 kProgressIndicatorDelay
, 1);
289 // Retrieve screenshot from web-app
290 status_t status
= interface
.RetrieveScreenshot(info
.Code(),
291 info
.Width(), info
.Height(), &buffer
);
293 delayedMessenger
.SetCount(0);
294 messenger
.SendMessage(MSG_DOWNLOAD_STOP
);
296 if (status
== B_OK
&& Lock()) {
297 printf("got screenshot");
298 fScreenshot
= BitmapRef(new(std::nothrow
)SharedBitmap(buffer
), true);
299 fScreenshotView
->SetBitmap(fScreenshot
);
300 _ResizeToFitAndCenter();
303 printf(" failed to download screenshot\n");
309 ScreenshotWindow::_ResizeToFitAndCenter()
311 // Find out dimensions of the largest screenshot of this package
312 ScreenshotInfoList screenshotInfos
;
313 if (fPackage
.Get() != NULL
)
314 screenshotInfos
= fPackage
->ScreenshotInfos();
316 int32 largestScreenshotWidth
= 0;
317 int32 largestScreenshotHeight
= 0;
319 const uint32 numScreenshots
= fPackage
->ScreenshotInfos().CountItems();
320 for (uint32 i
= 0; i
< numScreenshots
; i
++) {
321 const ScreenshotInfo
& info
= screenshotInfos
.ItemAtFast(i
);
322 if (info
.Width() > largestScreenshotWidth
)
323 largestScreenshotWidth
= info
.Width();
324 if (info
.Height() > largestScreenshotHeight
)
325 largestScreenshotHeight
= info
.Height();
328 fScreenshotView
->SetExplicitMinSize(
329 BSize(largestScreenshotWidth
, largestScreenshotHeight
));
332 // TODO: Limit window size to screen size (with a little margin),
333 // the image should then become scrollable.
337 GetSizeLimits(&minWidth
, NULL
, &minHeight
, NULL
);
338 ResizeTo(minWidth
, minHeight
);
344 ScreenshotWindow::_UpdateToolBar()
346 const int32 numScreenshots
= fPackage
->ScreenshotInfos().CountItems();
347 const int32 currentIndex
= atomic_get(&fCurrentScreenshotIndex
);
349 fToolBar
->SetActionEnabled(MSG_PREVIOUS_SCREENSHOT
,
351 fToolBar
->SetActionEnabled(MSG_NEXT_SCREENSHOT
,
352 currentIndex
< numScreenshots
- 1);
355 text
<< currentIndex
+ 1;
357 text
<< numScreenshots
;
358 fIndexView
->SetText(text
);