HaikuDepot: Render Native Desktop Icon

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 <no-reply+buildbot@haiku-os.org>
Reviewed-by: Jérôme Duval <jerome.duval@gmail.com>
This commit is contained in:
Andrew Lindesay 2024-11-08 23:54:47 +13:00 committed by waddlesplash
parent 97a8cc6cc2
commit 6afa94a089
8 changed files with 147 additions and 40 deletions

View File

@ -96,3 +96,13 @@ resource(550, "arrow right") #'VICN' array {
$"00000000000040A32442FFFF42FD7201178322040A0201000240A32D00000000"
$"000040A32442FFFF42FD72"
};
resource(560, "native") #'VICN' array {
$"6E63696603033771AA05000201060238CC87BD083D3DCC623981954864C94A29"
$"6B00FFB11BFFFFF9C70202043E24C4AB24B93A24243E24B93A24C4AB3E58B93A"
$"58C4AB58583E58C4AB58B93A060DEE1FBF033E2B38BDF5383135BB91B8603435"
$"C0592C3D35C0592C4335432C43BE5B49B9934CBE5B494FBF8DBF8D49BF8D49C4"
$"554C50435043474347C05947C059503DC5873444BDF547BB914431060A010100"
$"1815FF01178400040A01010018001501178600040A000100000A0101011815FF"
$"01178400040A01010118001501178600040A02010100"
};

View File

@ -91,6 +91,7 @@ enum {
RSRC_INSTALLED = 530,
RSRC_ARROW_LEFT = 540,
RSRC_ARROW_RIGHT = 550,
RSRC_NATIVE = 560,
};

View File

@ -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<BitmapHolderRef> 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<BitmapHolderRef>::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<BitmapHolderRef>::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;
}
}

View File

@ -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<BitmapHolderRef> 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<float>(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<BitmapHolderRef>::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);
}

View File

@ -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();
}

View File

@ -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;
};

View File

@ -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)
{

View File

@ -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);