From 68ed4f7dd6c679488ce2f1e0f6e47e678138836e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stephan=20A=C3=9Fmus?= Date: Sat, 3 Aug 2013 22:36:45 +0200 Subject: [PATCH] HaikuDepot: More work on package info view * Display rating via RatingView and additional BStringView decoration * Display radio buttons to switch between About, Ratings and Changelog pages. (Will be replaced again...) * Implement preliminary UserRatingsView showing all user ratings (currently in a single BTextView, will be much more detailed later on). * Implement ChangelogView, simply showing the dummy changelogs in a BTextView. * Layout tweaks --- src/apps/haiku-depot/PackageInfoView.cpp | 398 +++++++++++++++++++++-- src/apps/haiku-depot/PackageListView.cpp | 2 +- 2 files changed, 369 insertions(+), 31 deletions(-) diff --git a/src/apps/haiku-depot/PackageInfoView.cpp b/src/apps/haiku-depot/PackageInfoView.cpp index a2b05bcb43..3a6132581d 100644 --- a/src/apps/haiku-depot/PackageInfoView.cpp +++ b/src/apps/haiku-depot/PackageInfoView.cpp @@ -15,6 +15,8 @@ #include #include #include +#include +#include #include @@ -22,6 +24,9 @@ #define B_TRANSLATION_CONTEXT "PackageInfoView" +static const rgb_color kLightBlack = (rgb_color){ 60, 60, 60, 255 }; + + class BitmapView : public BView { public: BitmapView(const char* name) @@ -88,9 +93,99 @@ private: }; +// #pragma mark - AboutView + + +class RatingView : public BView { +public: + RatingView() + : + BView("package rating view", B_WILL_DRAW), + fStarBitmap(501), + fRating(-1.0f) + { + SetViewColor(B_TRANSPARENT_COLOR); + SetLowColor(ui_color(B_PANEL_BACKGROUND_COLOR)); + } + + virtual ~RatingView() + { + } + + virtual void Draw(BRect updateRect) + { + FillRect(updateRect, B_SOLID_LOW); + + if (fRating < 0.0f) + return; + + const BBitmap* star = fStarBitmap.Bitmap(SharedBitmap::SIZE_16); + if (star == NULL) { + fprintf(stderr, "No star icon found in application resources.\n"); + return; + } + + SetDrawingMode(B_OP_OVER); + + float x = 0; + for (int i = 0; i < 5; i++) { + DrawBitmap(star, BPoint(x, 0)); + x += 16 + 2; + } + + if (fRating >= 5.0f) + return; + + SetDrawingMode(B_OP_OVER); + + BRect rect(Bounds()); + rect.left = ceilf(rect.left + (fRating / 5.0f) * rect.Width()); + + rgb_color color = LowColor(); + color.alpha = 190; + SetHighColor(color); + + SetDrawingMode(B_OP_ALPHA); + FillRect(rect, B_SOLID_HIGH); + } + + virtual BSize MinSize() + { + return BSize(16 * 5 + 2 * 4, 16 + 2); + } + + virtual BSize PreferredSize() + { + return MinSize(); + } + + virtual BSize MaxSize() + { + return MinSize(); + } + + void SetRating(float rating) + { + fRating = rating; + Invalidate(); + } + +private: + SharedBitmap fStarBitmap; + float fRating; +}; + + // #pragma mark - TitleView +enum { + MSG_SHOW_ABOUT_PAGE = 'shap', + MSG_SHOW_RATINGS_PAGE = 'shrp', + MSG_SHOW_CHANGELOG_PAGE = 'shcp', +}; + + class TitleView : public BGroupView { public: TitleView() @@ -113,23 +208,71 @@ public: // Publisher font GetFont(&font); - font.SetSize(std::max(9.0f, floorf(font.Size() * 0.9f))); + font.SetSize(std::max(9.0f, floorf(font.Size() * 0.92f))); font.SetFamilyAndStyle(family, "Italic"); fPublisherView->SetFont(&font); - + fPublisherView->SetHighColor(kLightBlack); + fPublisherView->SetExplicitAlignment(BAlignment(B_ALIGN_RIGHT, + B_ALIGN_VERTICAL_UNSET)); + + // Rating view + fRatingView = new RatingView(); + + fAvgRating = new BStringView("package average rating", ""); + // small font + GetFont(&font); + font.SetSize(ceilf(font.Size() * 1.2f)); + fAvgRating->SetFont(&font); + fAvgRating->SetHighColor(kLightBlack); + + fVoteInfo = new BStringView("package vote info", ""); + // small font + GetFont(&font); + font.SetSize(std::max(9.0f, floorf(font.Size() * 0.85f))); + fVoteInfo->SetFont(&font); + fVoteInfo->SetHighColor(kLightBlack); + + fAboutPageButton = new BRadioButton("about page button", + B_TRANSLATE("About"), new BMessage(MSG_SHOW_ABOUT_PAGE)); + fAboutPageButton->SetValue(B_CONTROL_ON); + + fRatingsPageButton = new BRadioButton("ratings page button", + B_TRANSLATE("Ratings"), new BMessage(MSG_SHOW_RATINGS_PAGE)); + + fChangelogPageButton = new BRadioButton("changelog page button", + B_TRANSLATE("Changelog"), new BMessage(MSG_SHOW_CHANGELOG_PAGE)); + BLayoutBuilder::Group<>(this) .Add(fIconView) - .AddGroup(B_VERTICAL, 0.0f) + .AddGroup(B_VERTICAL, 1.0f) .Add(fTitleView) .Add(fPublisherView) +// .SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET)) .End() - .AddGlue() + .AddGlue(0.2f) + .AddGroup(B_HORIZONTAL, B_USE_SMALL_SPACING) + .Add(fRatingView) + .Add(fAvgRating) + .Add(fVoteInfo) + .End() + .AddGlue(3.0f) + .Add(fAboutPageButton) + .Add(fRatingsPageButton) + .Add(fChangelogPageButton) ; + + Clear(); } virtual ~TitleView() { - Clear(); + } + + void SetTarget(BHandler* handler) + { + fAboutPageButton->SetTarget(handler); + fRatingsPageButton->SetTarget(handler); + fChangelogPageButton->SetTarget(handler); } void SetPackage(const PackageInfo& package) @@ -145,6 +288,31 @@ public: publisher.ReplaceAll("%Publisher%", package.Publisher().Name()); fPublisherView->SetText(publisher); + RatingSummary ratingSummary = package.CalculateRatingSummary(); + + fRatingView->SetRating(ratingSummary.averageRating); + + BString avgRating; + avgRating.SetToFormat("%.1f", ratingSummary.averageRating); + fAvgRating->SetText(avgRating); + + BString votes; + votes.SetToFormat("%d", ratingSummary.ratingCount); + + BString voteInfo(B_TRANSLATE("(%Votes%)")); + voteInfo.ReplaceAll("%Votes%", votes); + + fVoteInfo->SetText(voteInfo); + + if (fAboutPageButton->IsHidden(fAboutPageButton)) + fAboutPageButton->Show(); + if (fRatingsPageButton->IsHidden(fRatingsPageButton)) + fRatingsPageButton->Show(); + if (fChangelogPageButton->IsHidden(fChangelogPageButton)) + fChangelogPageButton->Show(); + + fAboutPageButton->SetValue(B_CONTROL_ON); + InvalidateLayout(); Invalidate(); } @@ -153,12 +321,31 @@ public: { fTitleView->SetText(""); fPublisherView->SetText(""); + fRatingView->SetRating(-1.0f); + fAvgRating->SetText(""); + fVoteInfo->SetText(""); + + if (!fAboutPageButton->IsHidden(fAboutPageButton)) + fAboutPageButton->Hide(); + if (!fRatingsPageButton->IsHidden(fRatingsPageButton)) + fRatingsPageButton->Hide(); + if (!fChangelogPageButton->IsHidden(fChangelogPageButton)) + fChangelogPageButton->Hide(); } private: BitmapView* fIconView; + BStringView* fTitleView; BStringView* fPublisherView; + + RatingView* fRatingView; + BStringView* fAvgRating; + BStringView* fVoteInfo; + + BRadioButton* fAboutPageButton; + BRadioButton* fRatingsPageButton; + BRadioButton* fChangelogPageButton; }; @@ -170,7 +357,7 @@ public: AboutView() : BView("about view", B_WILL_DRAW), - fLayout(new BGroupLayout(B_VERTICAL)), + fLayout(new BGroupLayout(B_HORIZONTAL)), fEmailIcon("text/x-email"), fWebsiteIcon("text/html") { @@ -189,24 +376,28 @@ public: fEmailIconView = new BitmapView("email icon view"); fEmailLinkView = new BStringView("email link view", ""); fEmailLinkView->SetFont(&smallFont); - fEmailLinkView->SetHighColor(60, 60, 60); + fEmailLinkView->SetHighColor(kLightBlack); fWebsiteIconView = new BitmapView("website icon view"); fWebsiteLinkView = new BStringView("website link view", ""); fWebsiteLinkView->SetFont(&smallFont); - fWebsiteLinkView->SetHighColor(60, 60, 60); + fWebsiteLinkView->SetHighColor(kLightBlack); BLayoutBuilder::Group<>(fLayout) - .Add(fDescriptionView) - .AddGroup(B_HORIZONTAL) + .Add(fDescriptionView, 1.0f) + .AddGroup(B_VERTICAL, 0.0f) .AddGlue() - .AddGrid(B_USE_HALF_ITEM_SPACING, B_USE_HALF_ITEM_SPACING) - .Add(fEmailIconView, 0, 0) - .Add(fEmailLinkView, 1, 0) - .Add(fWebsiteIconView, 0, 1) - .Add(fWebsiteLinkView, 1, 1) + .AddGroup(B_HORIZONTAL) +// .AddGlue() + .AddGrid(B_USE_HALF_ITEM_SPACING, B_USE_HALF_ITEM_SPACING) + .Add(fEmailIconView, 0, 0) + .Add(fEmailLinkView, 1, 0) + .Add(fWebsiteIconView, 0, 1) + .Add(fWebsiteLinkView, 1, 1) + .End() .End() .End() + .SetExplicitMaxSize(BSize(B_SIZE_UNSET, B_SIZE_UNLIMITED)) ; } @@ -251,28 +442,30 @@ private: }; -// #pragma mark - PagesView +// #pragma mark - UserRatingsView -class PagesView : public BView { +class UserRatingsView : public BView { public: - PagesView() + UserRatingsView() : - BView("pages view", B_WILL_DRAW), - fLayout(new BCardLayout()) + BView("package ratings view", B_WILL_DRAW), + fLayout(new BGroupLayout(B_HORIZONTAL)) { - SetViewColor(B_TRANSPARENT_COLOR); - SetLowColor(ui_color(B_PANEL_BACKGROUND_COLOR)); + SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); + SetLayout(fLayout); - fAboutView = new AboutView(); + fTextView = new BTextView("ratings view"); + fTextView->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); + fTextView->MakeEditable(false); - fLayout->AddView(fAboutView); - - fLayout->SetVisibleItem(0L); + BLayoutBuilder::Group<>(fLayout) + .Add(fTextView, 1.0f) + ; } - virtual ~PagesView() + virtual ~UserRatingsView() { Clear(); } @@ -283,18 +476,159 @@ public: void SetPackage(const PackageInfo& package) { + fTextView->SetText(""); + + const UserRatingList& userRatings = package.UserRatings(); + + // TODO: Sort by age or usefullness rating + // TODO: Optionally hide ratings that are not in the system language + + for (int i = userRatings.CountItems() - 1; i >= 0; i--) { + const UserRating& rating = userRatings.ItemAtFast(i); + const BString& comment = rating.Comment(); + if (comment.Length() == 0) + continue; + + int offset = fTextView->TextLength(); + if (offset > 0) { + // Insert separator lines + fTextView->Insert(offset, "\n\n", 2); + offset += 2; + } + + fTextView->Insert(offset, comment.String(), comment.Length()); + } + } + + void Clear() + { + fTextView->SetText(""); + } + +private: + BGroupLayout* fLayout; + BTextView* fTextView; +}; + + +// #pragma mark - ChangelogView + + +class ChangelogView : public BView { +public: + ChangelogView() + : + BView("package changelog view", B_WILL_DRAW), + fLayout(new BGroupLayout(B_HORIZONTAL)) + { + SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); + + SetLayout(fLayout); + + fTextView = new BTextView("changelog view"); + fTextView->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); + fTextView->MakeEditable(false); + + BLayoutBuilder::Group<>(fLayout) + .Add(fTextView, 1.0f) + ; + } + + virtual ~ChangelogView() + { + Clear(); + } + + virtual void Draw(BRect updateRect) + { + } + + void SetPackage(const PackageInfo& package) + { + fTextView->SetText(package.Changelog()); + } + + void Clear() + { + fTextView->SetText(""); + } + +private: + BGroupLayout* fLayout; + BTextView* fTextView; +}; + + +// #pragma mark - PagesView + + +class PagesView : public BView { +public: + PagesView() + : + BView("pages view", 0), + fLayout(new BCardLayout()) + { + SetViewColor(B_TRANSPARENT_COLOR); + SetLowColor(ui_color(B_PANEL_BACKGROUND_COLOR)); + SetLayout(fLayout); + + fAboutView = new AboutView(); + fUserRatingsView = new UserRatingsView(); + fChangelogView = new ChangelogView(); + + fLayout->AddView(fAboutView); + fLayout->AddView(fUserRatingsView); + fLayout->AddView(fChangelogView); + + fLayout->SetVisibleItem(0L); + } + + virtual ~PagesView() + { + Clear(); + } + + virtual void MessageReceived(BMessage* message) + { + switch (message->what) { + case MSG_SHOW_ABOUT_PAGE: + fLayout->SetVisibleItem(0L); + break; + case MSG_SHOW_RATINGS_PAGE: + fLayout->SetVisibleItem(1L); + break; + case MSG_SHOW_CHANGELOG_PAGE: + fLayout->SetVisibleItem(2L); + break; + + default: + BView::MessageReceived(message); + break; + } + } + + void SetPackage(const PackageInfo& package) + { + fLayout->SetVisibleItem(0L); fAboutView->SetPackage(package); + fUserRatingsView->SetPackage(package); + fChangelogView->SetPackage(package); } void Clear() { fAboutView->Clear(); + fUserRatingsView->Clear(); + fChangelogView->Clear(); } private: - BCardLayout* fLayout; + BCardLayout* fLayout; - AboutView* fAboutView; + AboutView* fAboutView; + UserRatingsView* fUserRatingsView; + ChangelogView* fChangelogView; }; @@ -310,7 +644,10 @@ PackageInfoView::PackageInfoView() BLayoutBuilder::Group<>(this) .Add(fTitleView, 0.0f) - .Add(fPagesView) + .AddGroup(B_HORIZONTAL) + .Add(BSpaceLayoutItem::CreateHorizontalStrut(32.0f)) + .Add(fPagesView) + .End() ; } @@ -323,6 +660,7 @@ PackageInfoView::~PackageInfoView() void PackageInfoView::AttachedToWindow() { + fTitleView->SetTarget(fPagesView); } diff --git a/src/apps/haiku-depot/PackageListView.cpp b/src/apps/haiku-depot/PackageListView.cpp index 94ac30dec8..7f69117f38 100644 --- a/src/apps/haiku-depot/PackageListView.cpp +++ b/src/apps/haiku-depot/PackageListView.cpp @@ -244,7 +244,7 @@ enum { PackageRow::PackageRow(const PackageInfo& package) : - Inherited(), + Inherited(ceilf(be_plain_font->Size() * 1.8f)), fPackage(package) { // Package icon and title