1/*
2 * Copyright 2006, Haiku.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 *		Stephan Aßmus <superstippi@gmx.de>
7 */
8
9#include "ColorProperty.h"
10
11#include <new>
12#include <stdio.h>
13
14#include <Message.h>
15
16#include "support_ui.h"
17#include "ui_defines.h"
18
19using std::nothrow;
20
21// constructor
22ColorProperty::ColorProperty(uint32 identifier)
23	: Property(identifier),
24	  fValue(kBlack)
25{
26}
27
28// constructor
29ColorProperty::ColorProperty(uint32 identifier, rgb_color color)
30	: Property(identifier),
31	  fValue(color)
32{
33}
34
35// constructor
36ColorProperty::ColorProperty(const ColorProperty& other)
37	: Property(other),
38	  fValue(other.fValue)
39{
40}
41
42// constructor
43ColorProperty::ColorProperty(BMessage* archive)
44	: Property(archive),
45	  fValue(kBlack)
46{
47	if (!archive)
48		return;
49
50	if (archive->FindInt32("value", (int32*)&fValue) < B_OK)
51		fValue = kBlack;
52}
53
54// destrucor
55ColorProperty::~ColorProperty()
56{
57}
58
59// Archive
60status_t
61ColorProperty::Archive(BMessage* into, bool deep) const
62{
63	status_t ret = Property::Archive(into, deep);
64
65	if (ret >= B_OK)
66		ret = into->AddInt32("value", (uint32&)fValue);
67
68	// finish off
69	if (ret >= B_OK)
70		ret = into->AddString("class", "ColorProperty");
71
72	return ret;
73}
74
75// Instantiate
76BArchivable*
77ColorProperty::Instantiate(BMessage* archive)
78{
79	if (validate_instantiation(archive, "ColorProperty"))
80		return new ColorProperty(archive);
81
82	return NULL;
83}
84
85// Clone
86Property*
87ColorProperty::Clone() const
88{
89	return new (nothrow) ColorProperty(*this);
90}
91
92// SetValue
93bool
94ColorProperty::SetValue(const char* str)
95{
96	rgb_color value = fValue;
97	if (*str == '#') {
98		str++;
99		int32 length = strlen(str);
100		unsigned scannedColor = 0;
101		char expanded[7];
102		if (length == 3) {
103			// if there are only 3 bytes, than it means that we
104			// need to expand the color (#f60 -> #ff6600)
105			// TODO: There must be an easier way...
106			expanded[0] = *str;
107			expanded[1] = *str++;
108			expanded[2] = *str;
109			expanded[3] = *str++;
110			expanded[4] = *str;
111			expanded[5] = *str++;
112			expanded[6] = 0;
113			str = expanded;
114		}
115		if (sscanf(str, "%x", &scannedColor) == 1) {
116			uint8* colorByte = (uint8*)&scannedColor;
117			value.red	= colorByte[3];
118			value.green	= colorByte[2];
119			value.blue	= colorByte[1];
120			value.alpha	= colorByte[0];
121		}
122	} else {
123		// TODO: parse "named color"
124	}
125	return SetValue(value);
126}
127
128// SetValue
129bool
130ColorProperty::SetValue(const Property* other)
131{
132	const ColorProperty* c = dynamic_cast<const ColorProperty*>(other);
133	if (c)
134		return SetValue(c->Value());
135	return false;
136}
137
138// GetValue
139void
140ColorProperty::GetValue(BString& string)
141{
142	char valueString[16];
143	sprintf(valueString, "#%02x%02x%02x%02x",
144			fValue.red, fValue.green, fValue.blue, fValue.alpha);
145	string << valueString;
146}
147
148// InterpolateTo
149bool
150ColorProperty::InterpolateTo(const Property* other, float scale)
151{
152	const ColorProperty* c = dynamic_cast<const ColorProperty*>(other);
153	if (c) {
154		rgb_color a = fValue;
155		const rgb_color& b = c->fValue;
156		a.red = a.red + (uint8)floorf((b.red - a.red) * scale + 0.5);
157		a.green = a.green + (uint8)floorf((b.green - a.green) * scale + 0.5);
158		a.blue = a.blue + (uint8)floorf((b.blue - a.blue) * scale + 0.5);
159		a.alpha = a.alpha + (uint8)floorf((b.alpha - a.alpha) * scale + 0.5);
160		return SetValue(a);
161	}
162	return false;
163}
164
165// SetValue
166bool
167ColorProperty::SetValue(rgb_color color)
168{
169	if (fValue != color) {
170		fValue = color;
171		return true;
172	}
173	return false;
174}
175
176// Value
177rgb_color
178ColorProperty::Value() const
179{
180	return fValue;
181}
182
183
184
185