xref: /haiku/src/apps/icon-o-matic/generic/gui/SwatchView.cpp (revision 16d5c24e533eb14b7b8a99ee9f3ec9ba66335b1e)
1 /*
2  * Copyright 2006, Haiku.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		Stephan Aßmus <superstippi@gmx.de>
7  */
8 
9 #include "SwatchView.h"
10 
11 #include <stdio.h>
12 
13 #include <Bitmap.h>
14 #include <Cursor.h>
15 #include <Looper.h>
16 #include <Message.h>
17 #include <TypeConstants.h>
18 #include <Window.h>
19 
20 #include "cursors.h"
21 #include "ui_defines.h"
22 #include "support.h"
23 #include "support_ui.h"
24 
25 #define DRAG_INIT_DIST 10.0
26 
27 // constructor
28 SwatchView::SwatchView(const char* name, BMessage* message,
29 					   BHandler* target, rgb_color color,
30 					   float width, float height)
31 	: BView(BRect(0.0, 0.0, width, height), name,
32 			B_FOLLOW_NONE, B_WILL_DRAW),
33 	  fColor(color),
34 	  fTrackingStart(-1.0, -1.0),
35 	  fActive(false),
36 	  fDropInvokes(false),
37 	  fClickMessage(message),
38 	  fDroppedMessage(NULL),
39 	  fTarget(target),
40 	  fWidth(width),
41 	  fHeight(height)
42 {
43 	SetViewColor(B_TRANSPARENT_32_BIT);
44 	SetHighColor(fColor);
45 }
46 
47 // destructor
48 SwatchView::~SwatchView()
49 {
50 	delete fClickMessage;
51 	delete fDroppedMessage;
52 }
53 
54 #if LIB_LAYOUT
55 // layoutprefs
56 minimax
57 SwatchView::layoutprefs()
58 {
59 	if (fWidth > 6.0 && fHeight > 6.0) {
60 		mpm.mini.x = mpm.maxi.x = fWidth;
61 		mpm.mini.y = mpm.maxi.y = fHeight;
62 	} else {
63 		mpm.mini.x = 6.0;
64 		mpm.maxi.x = 10000.0;
65 		mpm.mini.y = 6.0;
66 		mpm.maxi.y = 10000.0;
67 	}
68 	mpm.weight = 1.0;
69 	return mpm;
70 }
71 
72 // layout
73 BRect
74 SwatchView::layout(BRect frame)
75 {
76 	MoveTo(frame.LeftTop());
77 	ResizeTo(frame.Width(), frame.Height());
78 	return Frame();
79 }
80 #endif // LIB_LAYOUT
81 
82 inline void
83 blend_color(rgb_color& a, const rgb_color& b, float alpha)
84 {
85 	float alphaInv = 1.0 - alpha;
86 	a.red = (uint8)(b.red * alphaInv + a.red * alpha);
87 	a.green = (uint8)(b.green * alphaInv + a.green * alpha);
88 	a.blue = (uint8)(b.blue * alphaInv + a.blue * alpha);
89 }
90 
91 // Draw
92 void
93 SwatchView::Draw(BRect updateRect)
94 {
95 	BRect r(Bounds());
96 
97 	rgb_color colorLight = tint_color(fColor, B_LIGHTEN_2_TINT);
98 	rgb_color colorShadow = tint_color(fColor, B_DARKEN_2_TINT);
99 
100 	if (fColor.alpha < 255) {
101 		// left/top
102 		float alpha = fColor.alpha / 255.0;
103 
104 		rgb_color h = colorLight;
105 		blend_color(h, kAlphaHigh, alpha);
106 		rgb_color l = colorLight;
107 		blend_color(l, kAlphaLow, alpha);
108 
109 		SetHighColor(h);
110 		SetLowColor(l);
111 
112 		StrokeLine(BPoint(r.left, r.bottom - 1),
113 				   BPoint(r.left, r.top), kDottedBig);
114 		StrokeLine(BPoint(r.left + 1, r.top),
115 				   BPoint(r.right, r.top), kDottedBig);
116 
117 		// right/bottom
118 		h = colorShadow;
119 		blend_color(h, kAlphaHigh, alpha);
120 		l = colorShadow;
121 		blend_color(l, kAlphaLow, alpha);
122 
123 		SetHighColor(h);
124 		SetLowColor(l);
125 
126 		StrokeLine(BPoint(r.right, r.top + 1),
127 				   BPoint(r.right, r.bottom), kDottedBig);
128 		StrokeLine(BPoint(r.right - 1, r.bottom),
129 				   BPoint(r.left, r.bottom), kDottedBig);
130 
131 		// fill
132 		r.InsetBy(1.0, 1.0);
133 
134 		h = fColor;
135 		blend_color(h, kAlphaHigh, alpha);
136 		l = fColor;
137 		blend_color(l, kAlphaLow, alpha);
138 
139 		SetHighColor(h);
140 		SetLowColor(l);
141 
142 		FillRect(r, kDottedBig);
143 	} else {
144 		_StrokeRect(r, colorLight, colorShadow);
145 		r.InsetBy(1.0, 1.0);
146 		SetHighColor(fColor);
147 		FillRect(r);
148 	}
149 }
150 
151 // MessageReceived
152 void
153 SwatchView::MessageReceived(BMessage* message)
154 {
155 	switch (message->what) {
156 		case B_PASTE: {
157 			rgb_color color;
158 			if (restore_color_from_message(message,
159 										   color) >= B_OK) {
160 				SetColor(color);
161 				_Invoke(fDroppedMessage);
162 			}
163 			break;
164 		}
165 		default:
166 			BView::MessageReceived(message);
167 			break;
168 	}
169 }
170 
171 // MouseDown
172 void
173 SwatchView::MouseDown(BPoint where)
174 {
175 	if (Bounds().Contains(where))
176 		fTrackingStart = where;
177 }
178 
179 // MouseUp
180 void
181 SwatchView::MouseUp(BPoint where)
182 {
183 	if (Bounds().Contains(where)
184 		&& Bounds().Contains(fTrackingStart))
185 		_Invoke(fClickMessage);
186 	fTrackingStart.x = -1.0;
187 	fTrackingStart.y = -1.0;
188 }
189 
190 // MouseMoved
191 void
192 SwatchView::MouseMoved(BPoint where, uint32 transit,
193 					   const BMessage* dragMessage)
194 {
195 	if (transit == B_ENTERED_VIEW) {
196 		BCursor cursor(kDropperCursor);
197 		SetViewCursor(&cursor, true);
198 	}
199 	if (Bounds().Contains(fTrackingStart)) {
200 		if (point_point_distance(where, fTrackingStart)
201 			> DRAG_INIT_DIST || transit == B_EXITED_VIEW) {
202 			_DragColor();
203 			fTrackingStart.x = -1.0;
204 			fTrackingStart.y = -1.0;
205 		}
206 	}
207 }
208 
209 // SetColor
210 void
211 SwatchView::SetColor(rgb_color color)
212 {
213 	fColor = color;
214 	SetHighColor(fColor);
215 	Invalidate();
216 }
217 
218 // SetClickedMessage
219 void
220 SwatchView::SetClickedMessage(BMessage* message)
221 {
222 	delete fClickMessage;
223 	fClickMessage = message;
224 }
225 
226 // SetDroppedMessage
227 void
228 SwatchView::SetDroppedMessage(BMessage* message)
229 {
230 	delete fDroppedMessage;
231 	fDroppedMessage = message;
232 }
233 
234 // _Invoke
235 void
236 SwatchView::_Invoke(const BMessage* _message)
237 {
238 	if (_message) {
239 		BHandler* target = fTarget ? fTarget
240 							: dynamic_cast<BHandler*>(Window());
241 		BLooper* looper;
242 		if (target && (looper = target->Looper())) {
243 			BMessage message(*_message);
244 			message.AddPointer("be:source", (void*)this);
245 			message.AddInt64("be:when", system_time());
246 			message.AddBool("begin", true);
247 			store_color_in_message(&message, fColor);
248 			looper->PostMessage(&message, target);
249 		}
250 	}
251 }
252 
253 // _StrokeRect
254 void
255 SwatchView::_StrokeRect(BRect r, rgb_color leftTop,
256 						rgb_color rightBottom)
257 {
258 	BeginLineArray(4);
259 		AddLine(BPoint(r.left, r.bottom - 1),
260 				BPoint(r.left, r.top), leftTop);
261 		AddLine(BPoint(r.left + 1, r.top),
262 				BPoint(r.right, r.top), leftTop);
263 		AddLine(BPoint(r.right, r.top + 1),
264 				BPoint(r.right, r.bottom), rightBottom);
265 		AddLine(BPoint(r.right - 1, r.bottom),
266 				BPoint(r.left, r.bottom), rightBottom);
267 	EndLineArray();
268 }
269 
270 // _DragColor
271 void
272 SwatchView::_DragColor()
273 {
274 	BBitmap *bitmap = new BBitmap(BRect(0.0, 0.0, 15.0, 15.0), B_RGB32);
275 	BMessage message = make_color_drop_message(fColor, bitmap);
276 
277 	DragMessage(&message, bitmap, B_OP_ALPHA, BPoint(9.0, 9.0));
278 }
279 
280