xref: /haiku/src/apps/haikudepot/ui_generic/BitmapView.cpp (revision 909af08f4328301fbdef1ffb41f566c3b5bec0c7)
1 /*
2  * Copyright 2013, Stephan Aßmus <superstippi@gmx.de>.
3  * Copyright 2020-2024, Andrew Lindesay <apl@lindesay.co.nz>.
4  * All rights reserved. Distributed under the terms of the MIT License.
5  */
6 
7 
8 #include "BitmapView.h"
9 
10 #include <algorithm>
11 
12 #include <Bitmap.h>
13 #include <LayoutUtils.h>
14 
15 
16 BitmapView::BitmapView(const char* name)
17 	:
18 	BView(name, B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE | B_TRANSPARENT_BACKGROUND),
19 	fBitmapHolderRef(NULL),
20 	fScaleBitmap(true)
21 {
22 	 SetViewColor(B_TRANSPARENT_COLOR);
23 }
24 
25 
26 BitmapView::~BitmapView()
27 {
28 }
29 
30 
31 void
32 BitmapView::Draw(BRect updateRect)
33 {
34 	if (!fBitmapHolderRef.IsSet())
35 		return;
36 
37 	BRect bounds(Bounds());
38 
39 	const BBitmap* bitmap = fBitmapHolderRef->Bitmap();
40 
41 	BRect bitmapBounds = bitmap->Bounds();
42 	if (bitmapBounds.Width() <= 0.0f || bitmapBounds.Height() <= 0.0f)
43 		return;
44 
45 	float scale = 1.0f;
46 
47 	if (fScaleBitmap) {
48 		float hScale = bounds.Width() / bitmapBounds.Width();
49 		float vScale = bounds.Height() / bitmapBounds.Height();
50 
51 		scale = std::min(hScale, vScale);
52 	}
53 
54 	float width = bitmapBounds.Width() * scale;
55 	float height = bitmapBounds.Height() * scale;
56 
57 	switch (LayoutAlignment().horizontal) {
58 		case B_ALIGN_LEFT:
59 			break;
60 		case B_ALIGN_RIGHT:
61 			bounds.left = floorf(bounds.right - width);
62 			break;
63 		default:
64 		case B_ALIGN_HORIZONTAL_CENTER:
65 			bounds.left = floorf(bounds.left
66 				+ (bounds.Width() - width) / 2.0f);
67 			break;
68 	}
69 	switch (LayoutAlignment().vertical) {
70 		case B_ALIGN_TOP:
71 			break;
72 		case B_ALIGN_BOTTOM:
73 			bounds.top = floorf(bounds.bottom - height);
74 			break;
75 		default:
76 		case B_ALIGN_VERTICAL_CENTER:
77 			bounds.top = floorf(bounds.top
78 				+ (bounds.Height() - height) / 2.0f);
79 			break;
80 	}
81 
82 	bounds.right = ceilf(bounds.left + width);
83 	bounds.bottom = ceilf(bounds.top + height);
84 
85 	SetDrawingMode(B_OP_ALPHA);
86 	DrawBitmap(bitmap, bitmapBounds, bounds, B_FILTER_BITMAP_BILINEAR);
87 }
88 
89 
90 BSize
91 BitmapView::MinSize()
92 {
93 	BSize size(0.0f, 0.0f);
94 
95 	if (fBitmapHolderRef.IsSet()) {
96 		BRect bounds = fBitmapHolderRef->Bitmap()->Bounds();
97 		size.width = bounds.Width();
98 		size.height = bounds.Height();
99 	}
100 
101 	return BLayoutUtils::ComposeSize(ExplicitMinSize(), size);
102 }
103 
104 
105 BSize
106 BitmapView::PreferredSize()
107 {
108 	BSize size = MinSize();
109 	return BLayoutUtils::ComposeSize(ExplicitPreferredSize(), size);
110 }
111 
112 
113 BSize
114 BitmapView::MaxSize()
115 {
116 	BSize size = MinSize();
117 	return BLayoutUtils::ComposeSize(ExplicitMaxSize(), size);
118 }
119 
120 
121 void
122 BitmapView::SetBitmap(BitmapHolderRef bitmapHolderRef)
123 {
124 	if (bitmapHolderRef == fBitmapHolderRef)
125 		return;
126 
127 	BSize size = MinSize();
128 	fBitmapHolderRef = bitmapHolderRef;
129 
130 	BSize newSize = MinSize();
131 	if (size != newSize)
132 		InvalidateLayout();
133 
134 	Invalidate();
135 }
136 
137 
138 void
139 BitmapView::UnsetBitmap()
140 {
141 	if (!fBitmapHolderRef.IsSet())
142 		return;
143 
144 	fBitmapHolderRef.Unset();
145 
146 	InvalidateLayout();
147 	Invalidate();
148 }
149 
150 
151 void
152 BitmapView::SetScaleBitmap(bool scaleBitmap)
153 {
154 	if (scaleBitmap == fScaleBitmap)
155 		return;
156 
157 	fScaleBitmap = scaleBitmap;
158 
159 	Invalidate();
160 }
161