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