1/*
2 * Copyright 2014 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 "ColorMenuItem.h"
11
12#include <math.h>
13#include <string.h>
14#include <syslog.h>
15
16#include <algorithm>
17
18#include <MenuField.h>
19#include <MenuPrivate.h>
20
21
22// golden ratio
23#ifdef M_PHI
24#	undef M_PHI
25#endif
26#define M_PHI 1.61803398874989484820
27
28
29//	#pragma - ColorMenuItem
30
31
32BColorMenuItem::BColorMenuItem(const char* label, BMessage* message,
33	rgb_color color, char shortcut, uint32 modifiers)
34	:
35	BMenuItem(label, message, shortcut, modifiers),
36	fColor(color)
37{
38}
39
40
41BColorMenuItem::BColorMenuItem(BMenu* menu, rgb_color color,
42	BMessage* message)
43	:
44	BMenuItem(menu, message),
45	fColor(color)
46{
47}
48
49
50BColorMenuItem::BColorMenuItem(BMessage* data)
51	:
52	BMenuItem(data)
53{
54	if (data->HasColor("_color")) {
55		rgb_color color;
56
57		color = data->GetColor("_color", (rgb_color){ 0, 0, 0 });
58		fColor = color;
59	} else
60		fColor = (rgb_color){ 0, 0, 0 };
61}
62
63
64BArchivable*
65BColorMenuItem::Instantiate(BMessage* data)
66{
67	if (validate_instantiation(data, "BColorMenuItem"))
68		return new BColorMenuItem(data);
69
70	return NULL;
71}
72
73
74status_t
75BColorMenuItem::Archive(BMessage* data, bool deep) const
76{
77	status_t result = BMenuItem::Archive(data, deep);
78
79	if (result == B_OK)
80		result = data->AddColor("_color", fColor);
81
82	return result;
83}
84
85
86void
87BColorMenuItem::DrawContent()
88{
89	float leftMargin = _LeftMargin();
90	float padding = _Padding();
91	float colorRectWidth = _ColorRectWidth();
92
93	BRect colorRect(Frame().InsetByCopy(2.0f, 2.0f));
94	colorRect.left = colorRect.right = leftMargin;
95	colorRect.right += colorRectWidth;
96
97	rgb_color highColor = Menu()->HighColor();
98
99	Menu()->SetDrawingMode(B_OP_OVER);
100
101	Menu()->SetHighColor(fColor);
102	Menu()->FillRect(colorRect);
103
104	Menu()->SetHighColor(ui_color(B_CONTROL_BORDER_COLOR));
105	Menu()->StrokeRect(colorRect);
106
107	float width = colorRectWidth + padding;
108
109	Menu()->MovePenBy(width, 0.0f);
110	Menu()->SetHighColor(highColor);
111
112	BMenuItem::DrawContent();
113}
114
115
116void
117BColorMenuItem::GetContentSize(float* _width, float* _height)
118{
119	float labelWidth;
120	float height;
121	BMenuItem::GetContentSize(&labelWidth, &height);
122
123	if (_width != NULL)
124		*_width = _LeftMargin() + _ColorRectWidth() + _Padding() + labelWidth;
125
126	if (_height != NULL)
127		*_height = height;
128}
129
130
131void
132BColorMenuItem::SetMarked(bool mark)
133{
134	BMenuItem::SetMarked(mark);
135
136	if (!mark)
137		return;
138
139	// we are marking the item
140
141	BMenu* menu = Menu();
142	if (menu == NULL)
143		return;
144
145	// we have a parent menu
146
147	BMenu* _menu = menu;
148	while ((_menu = _menu->Supermenu()) != NULL)
149		menu = _menu;
150
151	// went up the hierarchy to found the topmost menu
152
153	if (menu == NULL || menu->Parent() == NULL)
154		return;
155
156	// our topmost menu has a parent
157
158	if (dynamic_cast<BMenuField*>(menu->Parent()) == NULL)
159		return;
160
161	// our topmost menu's parent is a BMenuField
162
163	BMenuItem* topLevelItem = menu->ItemAt((int32)0);
164
165	if (topLevelItem == NULL)
166		return;
167
168	// our topmost menu has a menu item
169
170	BColorMenuItem* topLevelColorMenuItem
171		= dynamic_cast<BColorMenuItem*>(topLevelItem);
172	if (topLevelColorMenuItem == NULL)
173		return;
174
175	// our topmost menu's item is a BColorMenuItem
176
177	// update the color
178	topLevelColorMenuItem->SetColor(fColor);
179	menu->Invalidate();
180}
181
182
183//	#pragma mark - BColorMenuItem private methods
184
185
186float
187BColorMenuItem::_LeftMargin()
188{
189	BPrivate::MenuPrivate menuPrivate(Menu());
190	float leftMargin;
191	menuPrivate.GetItemMargins(&leftMargin, NULL, NULL, NULL);
192	return leftMargin;
193}
194
195
196float
197BColorMenuItem::_Padding()
198{
199	return floorf(std::max(14.0f, be_plain_font->Size() + 2) / 2);
200}
201
202
203float
204BColorMenuItem::_ColorRectWidth()
205{
206	return floorf(std::max(14.0f, be_plain_font->Size() + 2) * M_PHI);
207}
208
209
210
211// #pragma mark - BColorMenuItem reserved virtual methods
212
213
214void BColorMenuItem::_ReservedColorMenuItem1() {}
215void BColorMenuItem::_ReservedColorMenuItem2() {}
216void BColorMenuItem::_ReservedColorMenuItem3() {}
217void BColorMenuItem::_ReservedColorMenuItem4() {}
218void BColorMenuItem::_ReservedColorMenuItem5() {}
219void BColorMenuItem::_ReservedColorMenuItem6() {}
220void BColorMenuItem::_ReservedColorMenuItem7() {}
221void BColorMenuItem::_ReservedColorMenuItem8() {}
222void BColorMenuItem::_ReservedColorMenuItem9() {}
223void BColorMenuItem::_ReservedColorMenuItem10() {}
224void BColorMenuItem::_ReservedColorMenuItem11() {}
225void BColorMenuItem::_ReservedColorMenuItem12() {}
226void BColorMenuItem::_ReservedColorMenuItem13() {}
227void BColorMenuItem::_ReservedColorMenuItem14() {}
228void BColorMenuItem::_ReservedColorMenuItem15() {}
229void BColorMenuItem::_ReservedColorMenuItem16() {}
230void BColorMenuItem::_ReservedColorMenuItem17() {}
231void BColorMenuItem::_ReservedColorMenuItem18() {}
232void BColorMenuItem::_ReservedColorMenuItem19() {}
233void BColorMenuItem::_ReservedColorMenuItem20() {}
234