1/*
2 * Copyright 2001 Werner Freytag - please read to the LICENSE file
3 *
4 * Copyright 2002-2015, Stephan Aßmus <superstippi@gmx.de>
5 * All rights reserved.
6 *
7 */
8
9#include "ColorPreview.h"
10
11#include <stdio.h>
12
13#include <Bitmap.h>
14#include <ControlLook.h>
15#include <Cursor.h>
16#include <LayoutUtils.h>
17#include <MessageRunner.h>
18#include <String.h>
19#include <Window.h>
20
21#include "cursors.h"
22#include "support_ui.h"
23
24
25ColorPreview::ColorPreview(BRect frame, rgb_color color)
26	:
27	BControl(frame, "colorpreview", "", new BMessage(MSG_COLOR_PREVIEW),
28		B_FOLLOW_TOP | B_FOLLOW_LEFT, B_WILL_DRAW),
29	fColor(color),
30	fOldColor(color),
31
32	fMouseDown(false),
33
34	fMessageRunner(0),
35	fBorderStyle(B_FANCY_BORDER)
36{
37}
38
39
40ColorPreview::ColorPreview(rgb_color color)
41	:
42	BControl("colorpreview", "", new BMessage(MSG_COLOR_PREVIEW), B_WILL_DRAW),
43	fColor(color),
44	fOldColor(color),
45
46	fMouseDown(false),
47
48	fMessageRunner(0),
49	fBorderStyle(B_FANCY_BORDER)
50{
51}
52
53
54BSize
55ColorPreview::MinSize()
56{
57	BSize minSize(32, 36);
58	return BLayoutUtils::ComposeSize(ExplicitMinSize(), minSize);
59}
60
61
62BSize
63ColorPreview::PreferredSize()
64{
65	BSize preferredSize(66, 70);
66	return BLayoutUtils::ComposeSize(ExplicitPreferredSize(), preferredSize);
67}
68
69
70BSize
71ColorPreview::MaxSize()
72{
73	BSize maxSize(B_SIZE_UNLIMITED, B_SIZE_UNLIMITED);
74	return BLayoutUtils::ComposeSize(ExplicitMaxSize(), maxSize);
75}
76
77
78void
79ColorPreview::AttachedToWindow()
80{
81	BControl::AttachedToWindow();
82	SetViewColor(B_TRANSPARENT_COLOR);
83}
84
85
86void
87ColorPreview::Draw(BRect updateRect)
88{
89	BRect bounds(Bounds());
90
91	// Frame
92	if (fBorderStyle == B_FANCY_BORDER) {
93		rgb_color color = LowColor();
94		be_control_look->DrawTextControlBorder(this, bounds, updateRect, color);
95	}
96
97	BRect r(bounds.left, bounds.top, bounds.right,
98		bounds.top + bounds.Height() / 2);
99	SetHighColor(fColor);
100	FillRect(r);
101
102	r.top = r.bottom + 1;
103	r.bottom = bounds.bottom;
104	SetHighColor(fOldColor);
105	FillRect(r);
106}
107
108
109void
110ColorPreview::MessageReceived(BMessage* message)
111{
112	if (message->what == MSG_MESSAGERUNNER) {
113
114		BPoint	where;
115		uint32	buttons;
116
117		GetMouse(&where, &buttons);
118
119		_DragColor(where);
120
121	} else {
122#ifdef HAIKU_TARGET_PLATFORM_DANO
123		const
124#endif
125		char* nameFound;
126		type_code typeFound;
127
128		if (message->GetInfo(B_RGB_COLOR_TYPE, 0,
129							 &nameFound, &typeFound) != B_OK) {
130			BControl::MessageReceived(message);
131			return;
132		}
133
134	   	rgb_color* color;
135		ssize_t numBytes;
136		message->FindData(nameFound, typeFound,
137						  (const void**)&color, &numBytes);
138
139		BPoint where;
140		bool droppedOnNewArea = false;
141		if (message->FindPoint("_drop_point_", &where) == B_OK) {
142			ConvertFromScreen(&where);
143			if (where.y > Bounds().top + (Bounds().IntegerHeight() >> 1))
144				droppedOnNewArea = true;
145		}
146
147		if (droppedOnNewArea)
148			SetNewColor(*color);
149		else
150			SetColor(*color);
151		Invoke();
152	}
153}
154
155
156void
157ColorPreview::MouseDown(BPoint where)
158{
159	Window()->Activate();
160
161	fMouseDown = true;
162
163	fMessageRunner = new BMessageRunner(
164		this, new BMessage(MSG_MESSAGERUNNER), 300000, 1);
165
166	SetMouseEventMask(B_POINTER_EVENTS,
167					  B_SUSPEND_VIEW_FOCUS | B_LOCK_WINDOW_FOCUS);
168
169	BRect rect = Bounds().InsetByCopy(2.0, 2.0);
170	rect.top = rect.bottom/2 + 1;
171
172	if (rect.Contains( where ) ) {
173		fColor = fOldColor;
174		Draw( Bounds() );
175		Invoke();
176	}
177
178}
179
180
181void
182ColorPreview::MouseUp(BPoint where)
183{
184	delete fMessageRunner;
185	fMessageRunner = NULL;
186
187	fMouseDown = false;
188	BControl::MouseUp(where);
189}
190
191
192void
193ColorPreview::MouseMoved(BPoint where, uint32 transit, const BMessage* message)
194{
195	if (transit == B_ENTERED_VIEW) {
196		BCursor cursor(kDropperCursor);
197		SetViewCursor(&cursor, true);
198	}
199	if (fMouseDown)
200		_DragColor(where);
201}
202
203
204status_t
205ColorPreview::Invoke(BMessage* message)
206{
207	if (message == NULL)
208		message = Message();
209
210	if (message) {
211		message->RemoveName("color");
212		message->AddData("color", B_RGB_COLOR_TYPE, &fColor, sizeof(fColor));
213	}
214
215	return BControl::Invoke(message);
216}
217
218
219void
220ColorPreview::SetColor(rgb_color color)
221{
222	color.alpha = 255;
223	fColor = color;
224
225	Invalidate();
226}
227
228
229void
230ColorPreview::SetNewColor(rgb_color color)
231{
232	fColor = color;
233	fOldColor = color;
234
235	Invalidate();
236}
237
238
239// #pragma mark -
240
241
242void
243ColorPreview::_DragColor(BPoint where)
244{
245	BBitmap* bitmap = new BBitmap(BRect(0.0, 0.0, 15.0, 15.0), B_RGB32);
246	BMessage message = make_color_drop_message(fColor, bitmap);
247
248	DragMessage(&message, bitmap, B_OP_ALPHA, BPoint(9.0, 9.0));
249
250	MouseUp(where);
251}
252
253