⛏️ index : haiku.git

/*
 * Copyright 2004-2020, Haiku, Inc.
 * Distributed under the terms of the MIT License.
 *
 * Authors:
 *		Adrien Destugues, pulkomandy@pulkomandy.tk
 *		Michael Wilber
 */


#include "IconView.h"

#include <new>
#include <stdio.h>
#include <string.h>

#include <ControlLook.h>
#include <Entry.h>
#include <IconUtils.h>
#include <Node.h>
#include <NodeInfo.h>


using std::nothrow;


IconView::IconView(icon_size iconSize)
	:
	BView("IconView", B_WILL_DRAW),
	fIconSize(iconSize),
	fIconBitmap(NULL),
	fDrawIcon(false)
{
	SetViewUIColor(B_PANEL_BACKGROUND_COLOR);
}


IconView::~IconView()
{
	delete fIconBitmap;
	fIconBitmap = NULL;
}


status_t
IconView::SetIcon(const BPath& path, icon_size iconSize)
{
	fDrawIcon = false;

	if (iconSize != fIconSize || fIconBitmap == NULL) {
		BBitmap* bitmap = new BBitmap(BRect(BPoint(0, 0),
			be_control_look->ComposeIconSize(iconSize)), B_RGBA32);
		if (bitmap == NULL)
			return B_NO_MEMORY;

		delete fIconBitmap;
		fIconBitmap = bitmap;
		fIconSize = iconSize;
	}

	status_t status = fIconBitmap->InitCheck();
	if (status != B_OK)
		return status;

	BEntry entry(path.Path());
	BNode node(&entry);
	BNodeInfo info(&node);

	status = info.GetTrackerIcon(fIconBitmap,
		(icon_size)fIconBitmap->Bounds().IntegerWidth());
	if (status != B_OK)
		return status;

	if (!fIconBitmap->IsValid())
		return fIconBitmap->InitCheck();

	_SetSize();

	fDrawIcon = true;
	Invalidate();
	return B_OK;
}


status_t
IconView::SetIcon(const uint8_t* data, size_t size, icon_size iconSize)
{
	fDrawIcon = false;

	if (iconSize != fIconSize || fIconBitmap == NULL) {
		BBitmap* bitmap = new BBitmap(BRect(BPoint(0, 0),
			be_control_look->ComposeIconSize(iconSize)), B_RGBA32);
		if (bitmap == NULL)
			return B_NO_MEMORY;

		delete fIconBitmap;
		fIconBitmap = bitmap;
		fIconSize = iconSize;
	}

	status_t status = fIconBitmap->InitCheck();
	if (status != B_OK)
		return status;

	status = BIconUtils::GetVectorIcon(data, size, fIconBitmap);
	if (status != B_OK)
		return status;

	if (!fIconBitmap->IsValid())
		return fIconBitmap->InitCheck();

	_SetSize();

	fDrawIcon = true;
	Invalidate();
	return B_OK;
}


status_t
IconView::SetIcon(const BBitmap* icon)
{
	if (icon == NULL) {
		fDrawIcon = false;
		return B_OK;
	}

	delete fIconBitmap;
	fIconBitmap = new BBitmap(icon);
	if (fIconBitmap == NULL)
		return B_NO_MEMORY;

	status_t status = fIconBitmap->InitCheck();
	if (status != B_OK)
		return status;

	fIconSize = (icon_size)-1;
	_SetSize();

	fDrawIcon = true;
	Invalidate();
	return B_OK;
}


void
IconView::DrawIcon(bool draw)
{
	if (draw == fDrawIcon)
		return;

	fDrawIcon = draw;
	Invalidate();
}


void
IconView::Draw(BRect area)
{
	if (fDrawIcon && fIconBitmap != NULL) {
		SetDrawingMode(B_OP_ALPHA);
		SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_OVERLAY);
		DrawBitmap(fIconBitmap);
		SetDrawingMode(B_OP_COPY);
	} else
		BView::Draw(area);
}


status_t
IconView::InitCheck() const
{
	if (fIconBitmap == NULL)
		return B_NO_MEMORY;

	return fIconBitmap->InitCheck();
}


void
IconView::_SetSize()
{
	SetExplicitMinSize(fIconBitmap->Bounds().Size());
	SetExplicitMaxSize(fIconBitmap->Bounds().Size());
	SetExplicitPreferredSize(fIconBitmap->Bounds().Size());
}