1/*
2 * Copyright 2016-2022 Haiku, Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 *		John Scipione, jscipione@gmail.com
7 */
8
9
10#include "ColorListView.h"
11
12#include <algorithm>
13
14#include <math.h>
15#include <stdio.h>
16
17#include <Bitmap.h>
18#include <String.h>
19
20#include "ColorItem.h"
21#include "ThemeView.h"
22
23
24// golden ratio
25#ifdef M_PHI
26#	undef M_PHI
27#endif
28#define M_PHI 1.61803398874989484820
29
30
31//	#pragma mark - ColorListView
32
33
34ColorListView::ColorListView(const char* name,
35	list_view_type type, uint32 flags)
36	:
37	BListView(name, type, flags)
38{
39}
40
41
42ColorListView::~ColorListView()
43{
44}
45
46
47bool
48ColorListView::InitiateDrag(BPoint where, int32 index, bool wasSelected)
49{
50	ColorItem* colorItem
51		= dynamic_cast<ColorItem*>(ItemAt(index));
52	if (colorItem == NULL)
53		return false;
54
55	rgb_color color = colorItem->Color();
56
57	BString hexStr;
58	hexStr.SetToFormat("#%.2X%.2X%.2X", color.red, color.green, color.blue);
59
60	BMessage message(B_PASTE);
61	message.AddData("text/plain", B_MIME_TYPE, hexStr.String(),
62		hexStr.Length());
63	message.AddData(kRGBColor, B_RGB_COLOR_TYPE, &color, sizeof(color));
64
65	float itemHeight = colorItem->Height() - 5;
66	BRect rect(0.0f, 0.0f, roundf(itemHeight * M_PHI) - 1, itemHeight - 1);
67
68	BBitmap* bitmap = new BBitmap(rect, B_RGB32, true);
69	if (bitmap->Lock()) {
70		BView* view = new BView(rect, "", B_FOLLOW_NONE, B_WILL_DRAW);
71		bitmap->AddChild(view);
72
73		view->SetHighColor(B_TRANSPARENT_COLOR);
74		view->FillRect(view->Bounds());
75
76		++rect.top;
77		++rect.left;
78
79		view->SetHighColor(0, 0, 0, 100);
80		view->FillRect(rect);
81		rect.OffsetBy(-1.0f, -1.0f);
82
83		view->SetHighColor(std::min(255, (int)(1.2 * color.red + 40)),
84			std::min(255, (int)(1.2 * color.green + 40)),
85			std::min(255, (int)(1.2 * color.blue + 40)));
86		view->StrokeRect(rect);
87
88		++rect.left;
89		++rect.top;
90
91		view->SetHighColor((int32)(0.8 * color.red),
92			(int32)(0.8 * color.green),
93			(int32)(0.8 * color.blue));
94		view->StrokeRect(rect);
95
96		--rect.right;
97		--rect.bottom;
98
99		view->SetHighColor(color.red, color.green, color.blue);
100		view->FillRect(rect);
101		view->Sync();
102
103		bitmap->Unlock();
104	}
105
106	DragMessage(&message, bitmap, B_OP_ALPHA, BPoint(14.0f, 14.0f));
107
108	return true;
109}
110
111
112void
113ColorListView::MessageReceived(BMessage* message)
114{
115	// if we received a dropped message, see if it contains color data
116	if (message->WasDropped()) {
117		BPoint dropPoint = message->DropPoint();
118		ConvertFromScreen(&dropPoint);
119		int32 index = IndexOf(dropPoint);
120		ColorItem* item = dynamic_cast<ColorItem*>(ItemAt(index));
121		rgb_color* color;
122		ssize_t size;
123		if (item != NULL && message->FindData(kRGBColor, B_RGB_COLOR_TYPE,
124				(const void**)&color, &size) == B_OK) {
125			// build message to send to ThemeView
126			uint32 command = index == CurrentSelection()
127				? MSG_SET_CURRENT_COLOR : MSG_SET_COLOR;
128			BMessage setColorMessage = BMessage(command);
129			setColorMessage.AddData(kRGBColor, B_RGB_COLOR_TYPE, color, size);
130			// if setting different color, add which color to set
131			if (command == MSG_SET_COLOR)
132				setColorMessage.AddString(kName, item->Text());
133
134			// build messenger and send message
135			BMessenger messenger = BMessenger(Parent());
136			if (messenger.IsValid()) {
137				messenger.SendMessage(&setColorMessage);
138				if (command == MSG_SET_COLOR) {
139					// redraw item, MSG_SET_CURRENT_COLOR does this for us
140					item->SetColor(*color);
141					InvalidateItem(index);
142				}
143			}
144		}
145	}
146
147	BListView::MessageReceived(message);
148}
149