From 6afa94a0896259ded7b5b5fc27180f44196c2eca Mon Sep 17 00:00:00 2001 From: Andrew Lindesay Date: Fri, 8 Nov 2024 23:54:47 +1300 Subject: [PATCH] HaikuDepot: Render Native Desktop Icon MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Render an icon to indicate that the package provides a native application. Change-Id: I3aa6468be488a62b317d3107ad1490916c857ca2 Reviewed-on: https://review.haiku-os.org/c/haiku/+/8528 Tested-by: Commit checker robot Reviewed-by: Jérôme Duval --- src/apps/haikudepot/HaikuDepot.rdef | 10 +++ src/apps/haikudepot/HaikuDepotConstants.h | 1 + .../haikudepot/ui/FeaturedPackagesView.cpp | 67 +++++++++++++--- src/apps/haikudepot/ui/PackageListView.cpp | 80 ++++++++++++------- src/apps/haikudepot/ui/SharedIcons.cpp | 11 +++ src/apps/haikudepot/ui/SharedIcons.h | 2 + src/apps/haikudepot/util/PackageUtils.cpp | 14 ++++ src/apps/haikudepot/util/PackageUtils.h | 2 + 8 files changed, 147 insertions(+), 40 deletions(-) diff --git a/src/apps/haikudepot/HaikuDepot.rdef b/src/apps/haikudepot/HaikuDepot.rdef index 1889a0d165..328c03391d 100644 --- a/src/apps/haikudepot/HaikuDepot.rdef +++ b/src/apps/haikudepot/HaikuDepot.rdef @@ -96,3 +96,13 @@ resource(550, "arrow right") #'VICN' array { $"00000000000040A32442FFFF42FD7201178322040A0201000240A32D00000000" $"000040A32442FFFF42FD72" }; + +resource(560, "native") #'VICN' array { + $"6E63696603033771AA05000201060238CC87BD083D3DCC623981954864C94A29" + $"6B00FFB11BFFFFF9C70202043E24C4AB24B93A24243E24B93A24C4AB3E58B93A" + $"58C4AB58583E58C4AB58B93A060DEE1FBF033E2B38BDF5383135BB91B8603435" + $"C0592C3D35C0592C4335432C43BE5B49B9934CBE5B494FBF8DBF8D49BF8D49C4" + $"554C50435043474347C05947C059503DC5873444BDF547BB914431060A010100" + $"1815FF01178400040A01010018001501178600040A000100000A0101011815FF" + $"01178400040A01010118001501178600040A02010100" +}; \ No newline at end of file diff --git a/src/apps/haikudepot/HaikuDepotConstants.h b/src/apps/haikudepot/HaikuDepotConstants.h index da7e60f629..92d868c3bd 100644 --- a/src/apps/haikudepot/HaikuDepotConstants.h +++ b/src/apps/haikudepot/HaikuDepotConstants.h @@ -91,6 +91,7 @@ enum { RSRC_INSTALLED = 530, RSRC_ARROW_LEFT = 540, RSRC_ARROW_RIGHT = 550, + RSRC_NATIVE = 560, }; diff --git a/src/apps/haikudepot/ui/FeaturedPackagesView.cpp b/src/apps/haikudepot/ui/FeaturedPackagesView.cpp index 54dd4e05fa..e55a3a72d4 100644 --- a/src/apps/haikudepot/ui/FeaturedPackagesView.cpp +++ b/src/apps/haikudepot/ui/FeaturedPackagesView.cpp @@ -45,6 +45,12 @@ // The title area will be this many times the width of an "M". #define M_COUNT_TITLE 10 +// The fraction of the icon width that is left of the trailing icon +#define TRAILING_ICON_PADDING_LEFT_FACTOR 0.1 + +// The faction of an M-space that is left between the title and the first trailing icon. +#define TITLE_RIGHT_TRAILING_ICON_PADDING_M_FACTOR 0.1 + // #pragma mark - PackageView @@ -642,12 +648,33 @@ public: if (!textRect.IsValid()) return; - const BBitmap* installedIconBitmap = SharedIcons::IconInstalled16Scaled()->Bitmap(); + std::vector trailingIconBitmaps; + + if (PackageUtils::State(pkg) == ACTIVATED) + trailingIconBitmaps.push_back(SharedIcons::IconInstalled16Scaled()); + + if (PackageUtils::IsNativeDesktop(pkg)) + trailingIconBitmaps.push_back(SharedIcons::IconNative16Scaled()); + + float trailingIconsWidth = 0.0f; + + for (std::vector::iterator it = trailingIconBitmaps.begin(); + it != trailingIconBitmaps.end(); it++) { + trailingIconsWidth += (*it)->Bitmap()->Bounds().Width() + * (1.0 + TRAILING_ICON_PADDING_LEFT_FACTOR); + } SetDrawingMode(B_OP_COPY); SetHighUIColor(selected ? B_LIST_SELECTED_ITEM_TEXT_COLOR : B_LIST_ITEM_TEXT_COLOR); SetFont(fTitleFont); + float titleRightTrailingIconsPadding = 0.0f; + + if (!trailingIconBitmaps.empty()) { + titleRightTrailingIconsPadding = StringWidth("M") + * TITLE_RIGHT_TRAILING_ICON_PADDING_M_FACTOR; + } + font_height fontHeight; fTitleFont->GetHeight(&fontHeight); BPoint pt = textRect.LeftTop() + BPoint(0.0, + fontHeight.ascent); @@ -656,21 +683,35 @@ public: PackageUtils::TitleOrName(pkg, title); BString renderedText = title; - float installedIconAllowance = installedIconBitmap->Bounds().Width() * 1.5; - TruncateString(&renderedText, B_TRUNCATE_END, textRect.Width() - installedIconAllowance); + TruncateString(&renderedText, B_TRUNCATE_END, textRect.Width() + - (titleRightTrailingIconsPadding + trailingIconsWidth)); DrawString(renderedText, pt); - if (PackageUtils::State(pkg) == ACTIVATED) { - float stringWidth = StringWidth(title); - BRect iconRect = BRect( - BPoint(textRect.left + stringWidth + (installedIconBitmap->Bounds().Width() / 2.0), - textRect.top + (textRect.Height() / 2.0) - - (installedIconBitmap->Bounds().Height() / 2.0)), - installedIconBitmap->Bounds().Size()); - SetDrawingMode(B_OP_ALPHA); - DrawBitmap(installedIconBitmap, installedIconBitmap->Bounds(), iconRect, - B_FILTER_BITMAP_BILINEAR); + // now draw the trailing icons. + + float stringWidth = StringWidth(title); + float trailingIconX = textRect.left + stringWidth + titleRightTrailingIconsPadding; + float trailingIconMidY = textRect.top + (textRect.Height() / 2.0); + + SetDrawingMode(B_OP_ALPHA); + + for (std::vector::iterator it = trailingIconBitmaps.begin(); + it != trailingIconBitmaps.end(); it++) { + const BBitmap* bitmap = (*it)->Bitmap(); + BRect bitmapBounds = bitmap->Bounds(); + + float trailingIconTopLeftPtX = ceilf( + trailingIconX + (bitmapBounds.Width() * TRAILING_ICON_PADDING_LEFT_FACTOR)) + 0.5; + float trailingIconTopLeftPtY = ceilf( + trailingIconMidY - (bitmapBounds.Height() / 2.0)) + 0.5; + + BRect trailingIconRect(BPoint(trailingIconTopLeftPtX, trailingIconTopLeftPtY), + bitmap->Bounds().Size()); + + DrawBitmap(bitmap, bitmapBounds, trailingIconRect, B_FILTER_BITMAP_BILINEAR); + + trailingIconX = trailingIconRect.right; } } diff --git a/src/apps/haikudepot/ui/PackageListView.cpp b/src/apps/haikudepot/ui/PackageListView.cpp index cc77dd9714..d37fe01dd5 100644 --- a/src/apps/haikudepot/ui/PackageListView.cpp +++ b/src/apps/haikudepot/ui/PackageListView.cpp @@ -80,7 +80,8 @@ public: PackageIconAndTitleField( const char* packageName, const char* string, - bool isActivated); + bool isActivated, + bool isNativeDesktop); virtual ~PackageIconAndTitleField(); const BString PackageName() const @@ -89,9 +90,13 @@ public: bool IsActivated() const { return fIsActivated; } + bool IsNativeDesktop() const + { return fIsNativeDesktop; } + private: const BString fPackageName; const bool fIsActivated; + const bool fIsNativeDesktop; }; @@ -243,11 +248,12 @@ private: PackageIconAndTitleField::PackageIconAndTitleField(const char* packageName, const char* string, - bool isActivated) + bool isActivated, bool isNativeDesktop) : Inherited(string), fPackageName(packageName), - fIsActivated(isActivated) + fIsActivated(isActivated), + fIsNativeDesktop(isNativeDesktop) { } @@ -402,28 +408,38 @@ PackageColumn::DrawField(BField* field, BRect rect, BView* parent) // TODO (andponlin) factor this out as this method is getting too large. BSize iconSize = BControlLook::ComposeIconSize(16); - BSize indicatorSize = BControlLook::ComposeIconSize(8); + BSize trailingIconSize = BControlLook::ComposeIconSize(8); + float trailingIconPaddingFactor = 0.2f; BRect iconRect; BRect titleRect; - BRect activatedIndicatorRect; float titleTextWidth = 0.0f; float textMargin = 8.0f; // copied from ColumnTypes.cpp - bool showActivated = packageIconAndTitleField->IsActivated(); + + std::vector trailingIconBitmaps; + + if (packageIconAndTitleField->IsActivated()) + trailingIconBitmaps.push_back(SharedIcons::IconInstalled16Scaled()); + + if (packageIconAndTitleField->IsNativeDesktop()) + trailingIconBitmaps.push_back(SharedIcons::IconNative16Scaled()); // If there is not enough space then drop the "activated" indicator in order to make more // room for the title. - if (showActivated) { + float trailingIconsWidth = static_cast(trailingIconBitmaps.size()) + * (trailingIconSize.Width() * (1.0 + trailingIconPaddingFactor)); + + if (!trailingIconBitmaps.empty()) { static float sMinimalTextPart = -1.0; if (sMinimalTextPart < 0.0) sMinimalTextPart = parent->StringWidth("M") * 5.0; float minimalWidth - = iconSize.Width() + indicatorSize.Width() + sTextMargin + sMinimalTextPart; + = iconSize.Width() + trailingIconsWidth + sTextMargin + sMinimalTextPart; if (rect.Width() <= minimalWidth) - showActivated = false; + trailingIconBitmaps.clear(); } // Calculate the location of the icon. @@ -436,9 +452,7 @@ PackageColumn::DrawField(BField* field, BRect rect, BView* parent) titleRect = rect; titleRect.left = iconRect.right; - - if (showActivated) - titleRect.right -= (indicatorSize.Width() + sTextMargin); + titleRect.right -= trailingIconsWidth; // Figure out if the text needs to be truncated. @@ -448,13 +462,6 @@ PackageColumn::DrawField(BField* field, BRect rect, BView* parent) packageIconAndTitleField->SetClippedString(truncatedString.String()); titleTextWidth = parent->StringWidth(truncatedString); - // Calculate the location of the activated indicator. - - activatedIndicatorRect - = BRect(BPoint(ceilf(titleRect.left + titleTextWidth + (1.5f * textMargin)) + 0.5f, - ceilf(iconRect.top) + 0.5f), - indicatorSize); - // Draw the icon. BitmapHolderRef bitmapHolderRef; @@ -479,13 +486,33 @@ PackageColumn::DrawField(BField* field, BRect rect, BView* parent) DrawString(packageIconAndTitleField->ClippedString(), parent, titleRect); - // draw the installed indicator icon. + // Draw the trailing icons + + if (!trailingIconBitmaps.empty()) { + + BRect trailingIconRect( + BPoint(titleRect.left + titleTextWidth + textMargin, iconRect.top), + trailingIconSize); - if (showActivated) { - const BBitmap* installedIconBitmap = SharedIcons::IconInstalled16Scaled()->Bitmap(); parent->SetDrawingMode(B_OP_ALPHA); - parent->DrawBitmap(installedIconBitmap, installedIconBitmap->Bounds(), - activatedIndicatorRect, B_FILTER_BITMAP_BILINEAR); + + for (std::vector::iterator it = trailingIconBitmaps.begin(); + it != trailingIconBitmaps.end(); it++) { + const BBitmap* bitmap = (*it)->Bitmap(); + BRect bitmapBounds = bitmap->Bounds(); + + BRect trailingIconAlignedRect + = BRect(BPoint(ceilf(trailingIconRect.LeftTop().x) + 0.5, + ceilf(trailingIconRect.LeftTop().y) + 0.5), + trailingIconRect.Size()); + + parent->DrawBitmap(bitmap, bitmapBounds, trailingIconAlignedRect, + B_FILTER_BITMAP_BILINEAR); + + trailingIconRect.OffsetBy( + trailingIconSize.Width() * (1.0 + trailingIconPaddingFactor), 0); + } + parent->SetDrawingMode(B_OP_OVER); } @@ -680,9 +707,8 @@ PackageRow::UpdateIconAndTitle() BString title; PackageUtils::TitleOrName(fPackage, title); - BField* field - = new PackageIconAndTitleField(fPackage->Name(), title, - PackageUtils::State(fPackage) == ACTIVATED); + BField* field = new PackageIconAndTitleField(fPackage->Name(), title, + PackageUtils::State(fPackage) == ACTIVATED, PackageUtils::IsNativeDesktop(fPackage)); SetField(field, kTitleColumn); } diff --git a/src/apps/haikudepot/ui/SharedIcons.cpp b/src/apps/haikudepot/ui/SharedIcons.cpp index f9cdccab9b..b0dc9dc06e 100644 --- a/src/apps/haikudepot/ui/SharedIcons.cpp +++ b/src/apps/haikudepot/ui/SharedIcons.cpp @@ -22,6 +22,7 @@ BitmapHolderRef SharedIcons::sIconInstalled16Scaled; BitmapHolderRef SharedIcons::sIconArrowLeft22Scaled; BitmapHolderRef SharedIcons::sIconArrowRight22Scaled; BitmapHolderRef SharedIcons::sIconHTMLPackage16Scaled; +BitmapHolderRef SharedIcons::sNative16Scaled; /*static*/ BitmapHolderRef @@ -101,6 +102,15 @@ SharedIcons::IconHTMLPackage16Scaled() } +/*static*/ BitmapHolderRef +SharedIcons::IconNative16Scaled() +{ + if (!SharedIcons::sNative16Scaled.IsSet()) + SharedIcons::sNative16Scaled = SharedIcons::_CreateIconForResource(RSRC_NATIVE, 16); + return SharedIcons::sNative16Scaled; +} + + /*static*/ void SharedIcons::UnsetAllIcons() { @@ -110,6 +120,7 @@ SharedIcons::UnsetAllIcons() sIconInstalled16Scaled.Unset(); sIconArrowLeft22Scaled.Unset(); sIconArrowRight22Scaled.Unset(); + sNative16Scaled.Unset(); sIconHTMLPackage16Scaled.Unset(); } diff --git a/src/apps/haikudepot/ui/SharedIcons.h b/src/apps/haikudepot/ui/SharedIcons.h index e070d9d212..ec51a2935a 100644 --- a/src/apps/haikudepot/ui/SharedIcons.h +++ b/src/apps/haikudepot/ui/SharedIcons.h @@ -22,6 +22,7 @@ public: static BitmapHolderRef IconInstalled16Scaled(); static BitmapHolderRef IconArrowLeft22Scaled(); static BitmapHolderRef IconArrowRight22Scaled(); + static BitmapHolderRef IconNative16Scaled(); // icons from mime types static BitmapHolderRef IconHTMLPackage16Scaled(); @@ -43,6 +44,7 @@ private: static BitmapHolderRef sIconArrowLeft22Scaled; static BitmapHolderRef sIconArrowRight22Scaled; static BitmapHolderRef sIconHTMLPackage16Scaled; + static BitmapHolderRef sNative16Scaled; }; diff --git a/src/apps/haikudepot/util/PackageUtils.cpp b/src/apps/haikudepot/util/PackageUtils.cpp index 872639e868..9547bf86ea 100644 --- a/src/apps/haikudepot/util/PackageUtils.cpp +++ b/src/apps/haikudepot/util/PackageUtils.cpp @@ -52,6 +52,20 @@ PackageUtils::Summary(const PackageInfoRef& package, BString& summary) } +/*static*/ bool +PackageUtils::IsNativeDesktop(const PackageInfoRef& package) +{ + if (package.IsSet()) { + PackageClassificationInfoRef classificationInfo = package->PackageClassificationInfo(); + + if (classificationInfo.IsSet()) + return classificationInfo->IsNativeDesktop(); + } + + return false; +} + + /*static*/ PackageLocalizedTextRef PackageUtils::NewLocalizedText(const PackageInfoRef& package) { diff --git a/src/apps/haikudepot/util/PackageUtils.h b/src/apps/haikudepot/util/PackageUtils.h index 93cc6d5850..4abfe06141 100644 --- a/src/apps/haikudepot/util/PackageUtils.h +++ b/src/apps/haikudepot/util/PackageUtils.h @@ -15,6 +15,8 @@ public: static void Title(const PackageInfoRef& package, BString& title); static void Summary(const PackageInfoRef& package, BString& summary); + static bool IsNativeDesktop(const PackageInfoRef& package); + static PackageLocalizedTextRef NewLocalizedText(const PackageInfoRef& package);