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