BControl: Move icon code to separate class BIcon

This commit is contained in:
Ingo Weinhold
2013-12-22 14:45:34 +01:00
parent 5414b3c445
commit 97bf0ce362
3 changed files with 21 additions and 475 deletions
+5 -8
View File
@@ -19,6 +19,10 @@ enum {
class BBitmap;
class BWindow;
namespace BPrivate {
class BIcon;
};
class BControl : public BView, public BInvoker {
public:
@@ -88,13 +92,6 @@ private:
struct IconData;
private:
static BBitmap* _ConvertToRGB32(const BBitmap* bitmap,
bool noAppServerLink = false);
static status_t _TrimBitmap(const BBitmap* bitmap,
bool keepAspect, BBitmap*& _trimmedBitmap);
status_t _MakeBitmaps(const BBitmap* bitmap,
uint32 flags);
virtual void _ReservedControl2();
virtual void _ReservedControl3();
virtual void _ReservedControl4();
@@ -110,7 +107,7 @@ private:
bool fFocusChanging;
bool fTracking;
bool fWantsNav;
IconData* fIconData;
BPrivate::BIcon* fIcon;
#ifdef B_HAIKU_64_BIT
uint32 _reserved[2];
+15 -467
View File
@@ -4,7 +4,6 @@
*
* Authors:
* Marc Flerackers, [email protected]
* Stephan Aßmus, [email protected]
* Ingo Weinhold, [email protected]
*/
@@ -14,14 +13,12 @@
#include <stdlib.h>
#include <string.h>
#include <Bitmap.h>
#include <Control.h>
#include <ObjectList.h>
#include <PropertyInfo.h>
#include <Window.h>
#include <AutoDeleter.h>
#include <binary_compatibility/Interface.h>
#include <Icon.h>
static property_info sPropertyList[] = {
@@ -50,85 +47,6 @@ static property_info sPropertyList[] = {
};
struct BControl::IconData {
public:
IconData()
:
fEnabledBitmaps(8, true),
fDisabledBitmaps(8, true)
{
}
~IconData()
{
DeleteBitmaps();
}
BBitmap* CreateBitmap(const BRect& bounds, color_space colorSpace,
uint32 which)
{
BBitmap* bitmap = new(std::nothrow) BBitmap(bounds, colorSpace);
if (bitmap == NULL || !bitmap->IsValid() || !SetBitmap(bitmap, which)) {
delete bitmap;
return NULL;
}
return bitmap;
}
BBitmap* CopyBitmap(const BBitmap& bitmapToClone, uint32 which)
{
BBitmap* bitmap = new(std::nothrow) BBitmap(bitmapToClone);
if (bitmap == NULL || !bitmap->IsValid() || !SetBitmap(bitmap, which)) {
delete bitmap;
return NULL;
}
return bitmap;
}
bool SetBitmap(BBitmap* bitmap, uint32 which)
{
IconList& list = (which & B_DISABLED_ICON_BITMAP) == 0
? fEnabledBitmaps : fDisabledBitmaps;
which &= ~uint32(B_DISABLED_ICON_BITMAP);
int32 count = list.CountItems();
if ((int32)which < count) {
list.ReplaceItem(which, bitmap);
return true;
}
while (list.CountItems() < (int32)which) {
if (!list.AddItem((BBitmap*)NULL))
return false;
}
return list.AddItem(bitmap);
}
BBitmap* Bitmap(uint32 which) const
{
const IconList& list = (which & B_DISABLED_ICON_BITMAP) == 0
? fEnabledBitmaps : fDisabledBitmaps;
return list.ItemAt(which & ~uint32(B_DISABLED_ICON_BITMAP));
}
void DeleteBitmaps()
{
fEnabledBitmaps.MakeEmpty(true);
fDisabledBitmaps.MakeEmpty(true);
}
private:
typedef BObjectList<BBitmap> IconList;
private:
IconList fEnabledBitmaps;
IconList fDisabledBitmaps;
};
BControl::BControl(BRect frame, const char *name, const char *label,
BMessage *message, uint32 resizingMode, uint32 flags)
: BView(frame, name, resizingMode, flags)
@@ -154,7 +72,7 @@ BControl::BControl(const char *name, const char *label, BMessage *message,
BControl::~BControl()
{
free(fLabel);
delete fIconData;
delete fIcon;
SetMessage(NULL);
}
@@ -608,88 +526,13 @@ BControl::Perform(perform_code code, void* _data)
status_t
BControl::SetIcon(const BBitmap* bitmap, uint32 flags)
{
if (bitmap == NULL) {
delete fIconData;
fIconData = NULL;
return B_OK;
status_t error = BIcon::UpdateIcon(bitmap, flags, fIcon);
if (error == B_OK) {
InvalidateLayout();
Invalidate();
}
if (!bitmap->IsValid())
return B_BAD_VALUE;
// check the color space
bool hasAlpha = false;
bool canUseForMakeBitmaps = false;
switch (bitmap->ColorSpace()) {
case B_RGBA32:
case B_RGBA32_BIG:
hasAlpha = true;
// fall through
case B_RGB32:
case B_RGB32_BIG:
canUseForMakeBitmaps = true;
break;
case B_UVLA32:
case B_LABA32:
case B_HSIA32:
case B_HSVA32:
case B_HLSA32:
case B_CMYA32:
case B_RGBA15:
case B_RGBA15_BIG:
case B_CMAP8:
hasAlpha = true;
break;
default:
break;
}
BBitmap* trimmedBitmap = NULL;
// trim the bitmap, if requested and the bitmap actually has alpha
status_t error;
if ((flags & (B_TRIM_ICON_BITMAP | B_TRIM_ICON_BITMAP_KEEP_ASPECT)) != 0
&& hasAlpha) {
if (bitmap->ColorSpace() == B_RGBA32) {
error = _TrimBitmap(bitmap,
(flags & B_TRIM_ICON_BITMAP_KEEP_ASPECT) != 0, trimmedBitmap);
} else {
BBitmap* rgb32Bitmap = _ConvertToRGB32(bitmap, true);
if (rgb32Bitmap != NULL) {
error = _TrimBitmap(rgb32Bitmap,
(flags & B_TRIM_ICON_BITMAP_KEEP_ASPECT) != 0,
trimmedBitmap);
delete rgb32Bitmap;
} else
error = B_NO_MEMORY;
}
if (error != B_OK)
return error;
bitmap = trimmedBitmap;
canUseForMakeBitmaps = true;
}
// create the bitmaps
if (canUseForMakeBitmaps) {
error = _MakeBitmaps(bitmap, flags);
} else {
if (BBitmap* rgb32Bitmap = _ConvertToRGB32(bitmap, true)) {
error = _MakeBitmaps(rgb32Bitmap, flags);
delete rgb32Bitmap;
} else
error = B_NO_MEMORY;
}
delete trimmedBitmap;
InvalidateLayout();
Invalidate();
return error;
}
@@ -697,43 +540,21 @@ BControl::SetIcon(const BBitmap* bitmap, uint32 flags)
status_t
BControl::SetIconBitmap(const BBitmap* bitmap, uint32 which, uint32 flags)
{
if (fIconData == NULL) {
fIconData = new(std::nothrow) IconData;
if (fIconData == NULL)
return B_NO_MEMORY;
status_t error = BIcon::SetIconBitmap(bitmap, which, flags, fIcon);
if (error != B_OK) {
InvalidateLayout();
Invalidate();
}
BBitmap* ourBitmap = NULL;
if (bitmap != NULL) {
if (!bitmap->IsValid())
return B_BAD_VALUE;
if ((flags & B_KEEP_ICON_BITMAP) != 0) {
ourBitmap = const_cast<BBitmap*>(bitmap);
} else {
ourBitmap = _ConvertToRGB32(bitmap);
if (ourBitmap == NULL)
return B_NO_MEMORY;
}
}
if (!fIconData->SetBitmap(ourBitmap, which)) {
if (ourBitmap != bitmap)
delete ourBitmap;
return B_NO_MEMORY;
}
InvalidateLayout();
Invalidate();
return B_OK;
return error;
}
const BBitmap*
BControl::IconBitmap(uint32 which) const
{
return fIconData != NULL ? fIconData->Bitmap(which) : NULL;
return fIcon != NULL ? fIcon->Bitmap(which) : NULL;
}
@@ -770,279 +591,6 @@ B_IF_GCC_2(_ReservedControl1__8BControl, _ZN8BControl17_ReservedControl1Ev)(
}
/*static*/ BBitmap*
BControl::_ConvertToRGB32(const BBitmap* bitmap, bool noAppServerLink)
{
BBitmap* rgb32Bitmap = new(std::nothrow) BBitmap(bitmap->Bounds(),
noAppServerLink ? B_BITMAP_NO_SERVER_LINK : 0, B_RGBA32);
if (rgb32Bitmap == NULL)
return NULL;
if (!rgb32Bitmap->IsValid() || rgb32Bitmap->ImportBits(bitmap)!= B_OK) {
delete rgb32Bitmap;
return NULL;
}
return rgb32Bitmap;
}
/*static*/ status_t
BControl::_TrimBitmap(const BBitmap* bitmap, bool keepAspect,
BBitmap*& _trimmedBitmap)
{
if (bitmap == NULL || !bitmap->IsValid()
|| bitmap->ColorSpace() != B_RGBA32) {
return B_BAD_VALUE;
}
uint8* bits = (uint8*)bitmap->Bits();
uint32 bpr = bitmap->BytesPerRow();
uint32 width = bitmap->Bounds().IntegerWidth() + 1;
uint32 height = bitmap->Bounds().IntegerHeight() + 1;
BRect trimmed(INT32_MAX, INT32_MAX, INT32_MIN, INT32_MIN);
for (uint32 y = 0; y < height; y++) {
uint8* b = bits + 3;
bool rowHasAlpha = false;
for (uint32 x = 0; x < width; x++) {
if (*b) {
rowHasAlpha = true;
if (x < trimmed.left)
trimmed.left = x;
if (x > trimmed.right)
trimmed.right = x;
}
b += 4;
}
if (rowHasAlpha) {
if (y < trimmed.top)
trimmed.top = y;
if (y > trimmed.bottom)
trimmed.bottom = y;
}
bits += bpr;
}
if (!trimmed.IsValid())
return B_BAD_VALUE;
if (keepAspect) {
float minInset = trimmed.left;
minInset = min_c(minInset, trimmed.top);
minInset = min_c(minInset, bitmap->Bounds().right - trimmed.right);
minInset = min_c(minInset, bitmap->Bounds().bottom - trimmed.bottom);
trimmed = bitmap->Bounds().InsetByCopy(minInset, minInset);
}
trimmed = trimmed & bitmap->Bounds();
BBitmap* trimmedBitmap = new(std::nothrow) BBitmap(
trimmed.OffsetToCopy(B_ORIGIN), B_BITMAP_NO_SERVER_LINK, B_RGBA32);
if (trimmedBitmap == NULL)
return B_NO_MEMORY;
bits = (uint8*)bitmap->Bits();
bits += 4 * (int32)trimmed.left + bpr * (int32)trimmed.top;
uint8* dst = (uint8*)trimmedBitmap->Bits();
uint32 trimmedWidth = trimmedBitmap->Bounds().IntegerWidth() + 1;
uint32 trimmedHeight = trimmedBitmap->Bounds().IntegerHeight() + 1;
uint32 trimmedBPR = trimmedBitmap->BytesPerRow();
for (uint32 y = 0; y < trimmedHeight; y++) {
memcpy(dst, bits, trimmedWidth * 4);
dst += trimmedBPR;
bits += bpr;
}
_trimmedBitmap = trimmedBitmap;
return B_OK;
}
status_t
BControl::_MakeBitmaps(const BBitmap* bitmap, uint32 flags)
{
// make our own versions of the bitmap
BRect b(bitmap->Bounds());
IconData* iconData = new(std::nothrow) IconData;
if (iconData == NULL)
return B_NO_MEMORY;
ObjectDeleter<IconData> iconDataDeleter(iconData);
color_space format = bitmap->ColorSpace();
BBitmap* normalBitmap = iconData->CreateBitmap(b, format,
B_INACTIVE_ICON_BITMAP);
if (normalBitmap == NULL)
return B_NO_MEMORY;
BBitmap* disabledBitmap = NULL;
if ((flags & B_CREATE_DISABLED_ICON_BITMAPS) != 0) {
disabledBitmap = iconData->CreateBitmap(b, format,
B_INACTIVE_ICON_BITMAP | B_DISABLED_ICON_BITMAP);
if (disabledBitmap == NULL)
return B_NO_MEMORY;
}
BBitmap* clickedBitmap = NULL;
if ((flags & (B_CREATE_ACTIVE_ICON_BITMAP
| B_CREATE_PARTIALLY_ACTIVE_ICON_BITMAP)) != 0) {
clickedBitmap = iconData->CreateBitmap(b, format, B_ACTIVE_ICON_BITMAP);
if (clickedBitmap == NULL)
return B_NO_MEMORY;
}
BBitmap* disabledClickedBitmap = NULL;
if (disabledBitmap != NULL && clickedBitmap != NULL) {
disabledClickedBitmap = iconData->CreateBitmap(b, format,
B_ACTIVE_ICON_BITMAP | B_DISABLED_ICON_BITMAP);
if (disabledClickedBitmap == NULL)
return B_NO_MEMORY;
}
// copy bitmaps from file bitmap
uint8* nBits = normalBitmap != NULL ? (uint8*)normalBitmap->Bits() : NULL;
uint8* dBits = disabledBitmap != NULL
? (uint8*)disabledBitmap->Bits() : NULL;
uint8* cBits = clickedBitmap != NULL ? (uint8*)clickedBitmap->Bits() : NULL;
uint8* dcBits = disabledClickedBitmap != NULL
? (uint8*)disabledClickedBitmap->Bits() : NULL;
uint8* fBits = (uint8*)bitmap->Bits();
int32 nbpr = normalBitmap->BytesPerRow();
int32 fbpr = bitmap->BytesPerRow();
int32 pixels = b.IntegerWidth() + 1;
int32 lines = b.IntegerHeight() + 1;
if (format == B_RGB32 || format == B_RGB32_BIG) {
// nontransparent version
// iterate over color components
for (int32 y = 0; y < lines; y++) {
for (int32 x = 0; x < pixels; x++) {
int32 nOffset = 4 * x;
int32 fOffset = 4 * x;
nBits[nOffset + 0] = fBits[fOffset + 0];
nBits[nOffset + 1] = fBits[fOffset + 1];
nBits[nOffset + 2] = fBits[fOffset + 2];
nBits[nOffset + 3] = 255;
// clicked bits are darker (lame method...)
if (cBits != NULL) {
cBits[nOffset + 0] = uint8((float)nBits[nOffset + 0] * 0.8);
cBits[nOffset + 1] = uint8((float)nBits[nOffset + 1] * 0.8);
cBits[nOffset + 2] = uint8((float)nBits[nOffset + 2] * 0.8);
cBits[nOffset + 3] = 255;
}
// disabled bits have less contrast (lame method...)
if (dBits != NULL) {
uint8 grey = 216;
float dist = (nBits[nOffset + 0] - grey) * 0.4;
dBits[nOffset + 0] = (uint8)(grey + dist);
dist = (nBits[nOffset + 1] - grey) * 0.4;
dBits[nOffset + 1] = (uint8)(grey + dist);
dist = (nBits[nOffset + 2] - grey) * 0.4;
dBits[nOffset + 2] = (uint8)(grey + dist);
dBits[nOffset + 3] = 255;
}
// disabled bits have less contrast (lame method...)
if (dcBits != NULL) {
uint8 grey = 188;
float dist = (nBits[nOffset + 0] - grey) * 0.4;
dcBits[nOffset + 0] = (uint8)(grey + dist);
dist = (nBits[nOffset + 1] - grey) * 0.4;
dcBits[nOffset + 1] = (uint8)(grey + dist);
dist = (nBits[nOffset + 2] - grey) * 0.4;
dcBits[nOffset + 2] = (uint8)(grey + dist);
dcBits[nOffset + 3] = 255;
}
}
fBits += fbpr;
nBits += nbpr;
if (cBits != NULL)
cBits += nbpr;
if (dBits != NULL)
dBits += nbpr;
if (dcBits != NULL)
dcBits += nbpr;
}
} else if (format == B_RGBA32 || format == B_RGBA32_BIG) {
// transparent version
// iterate over color components
for (int32 y = 0; y < lines; y++) {
for (int32 x = 0; x < pixels; x++) {
int32 nOffset = 4 * x;
int32 fOffset = 4 * x;
nBits[nOffset + 0] = fBits[fOffset + 0];
nBits[nOffset + 1] = fBits[fOffset + 1];
nBits[nOffset + 2] = fBits[fOffset + 2];
nBits[nOffset + 3] = fBits[fOffset + 3];
// clicked bits are darker (lame method...)
if (cBits != NULL) {
cBits[nOffset + 0] = (uint8)(nBits[nOffset + 0] * 0.8);
cBits[nOffset + 1] = (uint8)(nBits[nOffset + 1] * 0.8);
cBits[nOffset + 2] = (uint8)(nBits[nOffset + 2] * 0.8);
cBits[nOffset + 3] = fBits[fOffset + 3];
}
// disabled bits have less opacity
if (dBits != NULL) {
uint8 grey = ((uint16)nBits[nOffset + 0] * 10
+ nBits[nOffset + 1] * 60
+ nBits[nOffset + 2] * 30) / 100;
float dist = (nBits[nOffset + 0] - grey) * 0.3;
dBits[nOffset + 0] = (uint8)(grey + dist);
dist = (nBits[nOffset + 1] - grey) * 0.3;
dBits[nOffset + 1] = (uint8)(grey + dist);
dist = (nBits[nOffset + 2] - grey) * 0.3;
dBits[nOffset + 2] = (uint8)(grey + dist);
dBits[nOffset + 3] = (uint8)(fBits[fOffset + 3] * 0.3);
}
// disabled bits have less contrast (lame method...)
if (dcBits != NULL) {
dcBits[nOffset + 0] = (uint8)(dBits[nOffset + 0] * 0.8);
dcBits[nOffset + 1] = (uint8)(dBits[nOffset + 1] * 0.8);
dcBits[nOffset + 2] = (uint8)(dBits[nOffset + 2] * 0.8);
dcBits[nOffset + 3] = (uint8)(fBits[fOffset + 3] * 0.3);
}
}
fBits += fbpr;
nBits += nbpr;
if (cBits != NULL)
cBits += nbpr;
if (dBits != NULL)
dBits += nbpr;
if (dcBits != NULL)
dcBits += nbpr;
}
} else {
// unsupported format
return B_BAD_VALUE;
}
// make the partially-on bitmaps a copy of the on bitmaps
if ((flags & B_CREATE_PARTIALLY_ACTIVE_ICON_BITMAP) != 0) {
if (iconData->CopyBitmap(clickedBitmap,
B_PARTIALLY_ACTIVATE_ICON_BITMAP) == NULL) {
return B_NO_MEMORY;
}
if ((flags & B_CREATE_DISABLED_ICON_BITMAPS) != 0) {
if (iconData->CopyBitmap(disabledClickedBitmap,
B_PARTIALLY_ACTIVATE_ICON_BITMAP | B_DISABLED_ICON_BITMAP)
== NULL) {
return B_NO_MEMORY;
}
}
}
delete fIconData;
fIconData = iconDataDeleter.Detach();
return B_OK;
}
void BControl::_ReservedControl2() {}
void BControl::_ReservedControl3() {}
void BControl::_ReservedControl4() {}
@@ -1065,7 +613,7 @@ BControl::InitData(BMessage *data)
fFocusChanging = false;
fTracking = false;
fWantsNav = Flags() & B_NAVIGABLE;
fIconData = NULL;
fIcon = NULL;
if (data && data->HasString("_fname"))
SetFont(be_plain_font, B_FONT_FAMILY_AND_STYLE);
+1
View File
@@ -74,6 +74,7 @@ for architectureObject in [ MultiArchSubDirSetup ] {
GroupLayout.cpp
GroupLayoutBuilder.cpp
GroupView.cpp
Icon.cpp
Input.cpp
InterfaceDefs.cpp
Layout.cpp