2 * Copyright 2013-214, 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 "FeaturedPackagesView.h"
13 #include <LayoutBuilder.h>
15 #include <ScrollView.h>
16 #include <StringView.h>
17 #include <SpaceLayoutItem.h>
19 #include "BitmapView.h"
20 #include "MainWindow.h"
21 #include "MarkupTextView.h"
22 #include "MessagePackageListener.h"
23 #include "RatingView.h"
24 #include "ScrollableGroupView.h"
27 #undef B_TRANSLATION_CONTEXT
28 #define B_TRANSLATION_CONTEXT "FeaturedPackagesView"
31 static const rgb_color kLightBlack
= (rgb_color
){ 60, 60, 60, 255 };
33 static BitmapRef
sInstalledIcon(new(std::nothrow
) SharedBitmap(504), true);
36 // #pragma mark - PackageView
39 class PackageView
: public BGroupView
{
43 BGroupView("package view", B_HORIZONTAL
),
45 new(std::nothrow
) OnePackageMessagePackageListener(this)),
48 SetViewUIColor(B_LIST_BACKGROUND_COLOR
);
49 SetHighUIColor(B_LIST_ITEM_TEXT_COLOR
);
50 SetEventMask(B_POINTER_EVENTS
);
52 fIconView
= new BitmapView("package icon view");
53 fInstalledIconView
= new BitmapView("installed icon view");
54 fTitleView
= new BStringView("package title view", "");
55 fPublisherView
= new BStringView("package publisher view", "");
62 font
.SetSize(ceilf(font
.Size() * 1.8f
));
63 font
.GetFamilyAndStyle(&family
, &style
);
64 font
.SetFamilyAndStyle(family
, "Bold");
65 fTitleView
->SetFont(&font
);
69 font
.SetSize(std::max(9.0f
, floorf(font
.Size() * 0.92f
)));
70 font
.SetFamilyAndStyle(family
, "Italic");
71 fPublisherView
->SetFont(&font
);
74 fSummaryView
= new BTextView("package summary");
75 fSummaryView
->MakeSelectable(false);
76 fSummaryView
->MakeEditable(false);
77 font
= BFont(be_plain_font
);
78 rgb_color color
= HighColor();
79 fSummaryView
->SetFontAndColor(&font
, B_FONT_ALL
, &color
);
82 fRatingView
= new RatingView("package rating view");
84 fAvgRating
= new BStringView("package average rating", "");
85 fAvgRating
->SetFont(&font
);
87 fVoteInfo
= new BStringView("package vote info", "");
90 font
.SetSize(std::max(9.0f
, floorf(font
.Size() * 0.85f
)));
91 fVoteInfo
->SetFont(&font
);
92 fVoteInfo
->SetHighUIColor(HighUIColor());
94 BLayoutBuilder::Group
<>(this)
96 .AddGroup(B_VERTICAL
, 1.0f
, 2.2f
)
97 .AddGroup(B_HORIZONTAL
)
99 .Add(fInstalledIconView
)
103 .SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED
, B_SIZE_UNSET
))
106 .AddGroup(B_HORIZONTAL
, 0.8f
)
112 .Add(fSummaryView
, 2.0f
)
114 .SetInsets(B_USE_WINDOW_INSETS
)
120 virtual ~PackageView()
122 fPackageListener
->SetPackage(PackageInfoRef(NULL
));
123 delete fPackageListener
;
126 virtual void AllAttached()
128 for (int32 index
= 0; index
< CountChildren(); ++index
) {
129 ChildAt(index
)->SetViewUIColor(ViewUIColor());
130 ChildAt(index
)->SetLowUIColor(ViewUIColor());
131 ChildAt(index
)->SetHighUIColor(HighUIColor());
135 virtual void MessageReceived(BMessage
* message
)
137 switch (message
->what
) {
138 case B_MOUSE_WHEEL_CHANGED
:
139 Window()->PostMessage(message
, Parent());
142 case MSG_UPDATE_PACKAGE
:
145 if (message
->FindUInt32("changes", &changes
) != B_OK
)
147 UpdatePackage(changes
, fPackageListener
->Package());
151 case B_COLORS_UPDATED
:
153 if (message
->HasColor(ui_color_name(B_LIST_ITEM_TEXT_COLOR
)))
160 virtual void MouseDown(BPoint where
)
162 BRect bounds
= Bounds();
163 BRect parentBounds
= Parent()->Bounds();
164 ConvertFromParent(&parentBounds
);
165 bounds
= bounds
& parentBounds
;
167 if (bounds
.Contains(where
) && Window()->IsActive()) {
168 BMessage
message(MSG_PACKAGE_SELECTED
);
169 message
.AddString("name", PackageName());
170 Window()->PostMessage(&message
);
174 void SetPackage(const PackageInfoRef
& package
)
176 fPackageListener
->SetPackage(package
);
178 _SetIcon(package
->Icon());
179 _SetInstalled(package
->State() == ACTIVATED
);
181 fTitleView
->SetText(package
->Title());
183 BString publisher
= package
->Publisher().Name();
184 fPublisherView
->SetText(publisher
);
186 BString summary
= package
->ShortDescription();
187 fSummaryView
->SetText(summary
);
189 _SetRating(package
->CalculateRatingSummary());
195 void UpdatePackage(uint32 changeMask
, const PackageInfoRef
& package
)
197 if ((changeMask
& PKG_CHANGED_TITLE
) != 0)
198 fTitleView
->SetText(package
->Title());
199 if ((changeMask
& PKG_CHANGED_SUMMARY
) != 0)
200 fSummaryView
->SetText(package
->ShortDescription());
201 if ((changeMask
& PKG_CHANGED_RATINGS
) != 0)
202 _SetRating(package
->CalculateRatingSummary());
203 if ((changeMask
& PKG_CHANGED_STATE
) != 0)
204 _SetInstalled(package
->State() == ACTIVATED
);
205 if ((changeMask
& PKG_CHANGED_ICON
) != 0)
206 _SetIcon(package
->Icon());
211 fPackageListener
->SetPackage(PackageInfoRef(NULL
));
213 fIconView
->UnsetBitmap();
214 fInstalledIconView
->UnsetBitmap();
215 fTitleView
->SetText("");
216 fPublisherView
->SetText("");
217 fSummaryView
->SetText("");
218 fRatingView
->SetRating(-1.0f
);
219 fAvgRating
->SetText("");
220 fVoteInfo
->SetText("");
223 const char* PackageTitle() const
225 return fTitleView
->Text();
228 const char* PackageName() const
230 if (fPackageListener
->Package().Get() != NULL
)
231 return fPackageListener
->Package()->Name();
236 void SetSelected(bool selected
)
238 if (fSelected
== selected
)
240 fSelected
= selected
;
247 color_which bgColor
= B_LIST_BACKGROUND_COLOR
;
248 color_which textColor
= B_LIST_ITEM_TEXT_COLOR
;
251 bgColor
= B_LIST_SELECTED_BACKGROUND_COLOR
;
252 textColor
= B_LIST_SELECTED_ITEM_TEXT_COLOR
;
255 List
<BView
*, true> views
;
258 views
.Add(fIconView
);
259 views
.Add(fInstalledIconView
);
260 views
.Add(fTitleView
);
261 views
.Add(fPublisherView
);
262 views
.Add(fSummaryView
);
263 views
.Add(fRatingView
);
264 views
.Add(fAvgRating
);
265 views
.Add(fVoteInfo
);
267 for (int32 i
= 0; i
< views
.CountItems(); i
++) {
268 BView
* view
= views
.ItemAtFast(i
);
270 view
->SetViewUIColor(bgColor
);
271 view
->SetLowUIColor(bgColor
);
272 view
->SetHighUIColor(textColor
);
276 BFont
font(be_plain_font
);
277 rgb_color color
= HighColor();
278 fSummaryView
->SetFontAndColor(&font
, B_FONT_ALL
, &color
);
281 void _SetRating(const RatingSummary
& ratingSummary
)
283 fRatingView
->SetRating(ratingSummary
.averageRating
);
285 if (ratingSummary
.ratingCount
> 0) {
287 avgRating
.SetToFormat("%.1f", ratingSummary
.averageRating
);
288 fAvgRating
->SetText(avgRating
);
291 votes
.SetToFormat("%d", ratingSummary
.ratingCount
);
293 BString
voteInfo(B_TRANSLATE("(%Votes%)"));
294 voteInfo
.ReplaceAll("%Votes%", votes
);
296 fVoteInfo
->SetText(voteInfo
);
298 fAvgRating
->SetText("");
299 fVoteInfo
->SetText("");
303 void _SetInstalled(bool installed
)
306 fInstalledIconView
->SetBitmap(sInstalledIcon
,
307 SharedBitmap::SIZE_16
);
309 fInstalledIconView
->UnsetBitmap();
312 void _SetIcon(const BitmapRef
& icon
)
314 if (icon
.Get() != NULL
) {
315 fIconView
->SetBitmap(icon
, SharedBitmap::SIZE_64
);
317 fIconView
->UnsetBitmap();
321 OnePackageMessagePackageListener
* fPackageListener
;
323 BitmapView
* fIconView
;
324 BitmapView
* fInstalledIconView
;
326 BStringView
* fTitleView
;
327 BStringView
* fPublisherView
;
329 BTextView
* fSummaryView
;
331 RatingView
* fRatingView
;
332 BStringView
* fAvgRating
;
333 BStringView
* fVoteInfo
;
337 BString fPackageName
;
341 // #pragma mark - FeaturedPackagesView
344 FeaturedPackagesView::FeaturedPackagesView()
346 BView("featured package view", 0)
348 BGroupLayout
* layout
= new BGroupLayout(B_VERTICAL
);
351 fContainerView
= new ScrollableGroupView();
352 fContainerView
->SetViewUIColor(B_LIST_BACKGROUND_COLOR
);
353 fPackageListLayout
= fContainerView
->GroupLayout();
355 BScrollView
* scrollView
= new BScrollView(
356 "featured packages scroll view", fContainerView
,
357 0, false, true, B_FANCY_BORDER
);
359 BScrollBar
* scrollBar
= scrollView
->ScrollBar(B_VERTICAL
);
360 if (scrollBar
!= NULL
)
361 scrollBar
->SetSteps(10.0f
, 20.0f
);
363 BLayoutBuilder::Group
<>(this)
364 .Add(scrollView
, 1.0f
)
369 FeaturedPackagesView::~FeaturedPackagesView()
375 FeaturedPackagesView::AddPackage(const PackageInfoRef
& package
)
377 // Find insertion index (alphabetical)
379 for (int32 i
= 0; BLayoutItem
* item
= fPackageListLayout
->ItemAt(i
); i
++) {
380 PackageView
* view
= dynamic_cast<PackageView
*>(item
->View());
384 BString name
= view
->PackageName();
385 if (name
== package
->Name()) {
386 // Don't add packages more than once
390 BString title
= view
->PackageTitle();
391 if (title
.Compare(package
->Title()) < 0)
395 PackageView
* view
= new PackageView();
396 view
->SetPackage(package
);
398 fPackageListLayout
->AddView(index
, view
);
403 FeaturedPackagesView::RemovePackage(const PackageInfoRef
& package
)
406 for (int32 i
= 0; BLayoutItem
* item
= fPackageListLayout
->ItemAt(i
); i
++) {
407 PackageView
* view
= dynamic_cast<PackageView
*>(item
->View());
411 BString name
= view
->PackageName();
412 if (name
== package
->Name()) {
422 FeaturedPackagesView::Clear()
424 for (int32 i
= fPackageListLayout
->CountItems() - 1;
425 BLayoutItem
* item
= fPackageListLayout
->ItemAt(i
); i
--) {
426 BView
* view
= dynamic_cast<PackageView
*>(item
->View());
436 FeaturedPackagesView::SelectPackage(const PackageInfoRef
& package
,
439 BString selectedName
;
440 if (package
.Get() != NULL
)
441 selectedName
= package
->Name();
443 for (int32 i
= 0; BLayoutItem
* item
= fPackageListLayout
->ItemAt(i
); i
++) {
444 PackageView
* view
= dynamic_cast<PackageView
*>(item
->View());
448 BString name
= view
->PackageName();
449 bool match
= (name
== selectedName
);
450 view
->SetSelected(match
);
452 if (match
&& scrollToEntry
) {
453 // Scroll the view so that the package entry shows up in the middle
454 fContainerView
->ScrollTo(0,
456 - fContainerView
->Bounds().Height() / 2
457 + view
->Bounds().Height() / 2);
464 FeaturedPackagesView::CleanupIcons()
466 sInstalledIcon
.Unset();