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 "PropertyItemView.h"
10
11#include <stdio.h>
12
13#include <Message.h>
14#include <Window.h>
15
16#include "support_ui.h"
17#include "ui_defines.h"
18
19#include "CommonPropertyIDs.h"
20#include "Property.h"
21#include "PropertyEditorFactory.h"
22#include "PropertyEditorView.h"
23#include "PropertyListView.h"
24
25// constructor
26PropertyItemView::PropertyItemView(Property* property)
27	: BView(BRect(0.0, 0.0, 10.0, 10.0), "property item",
28			B_FOLLOW_LEFT_RIGHT | B_FOLLOW_TOP,
29			B_NAVIGABLE | B_WILL_DRAW | B_FRAME_EVENTS | B_FULL_UPDATE_ON_RESIZE),
30	  fParent(NULL),
31	  fEditorView(/*factory->*/EditorFor(property)),
32	  	// NOTE: can be NULL if property is NULL or unkown
33	  fSelected(false),
34	  fEnabled(true),
35	  fLabelWidth(0.0)
36{
37	if (fEditorView) {
38		AddChild(fEditorView);
39		fEditorView->SetItemView(this);
40	}
41}
42
43// destructor
44PropertyItemView::~PropertyItemView()
45{
46}
47
48// Draw
49void
50PropertyItemView::Draw(BRect updateRect)
51{
52	const Property* property = GetProperty();
53	if (property && fParent) {
54		BRect b(Bounds());
55
56		// just draw background and label
57		rgb_color highColor = HighColor();
58		rgb_color labelColor = highColor;
59
60		if (!fEnabled) {
61			if (highColor.red + highColor.green + highColor.blue < 128 * 3)
62				labelColor = tint_color(HighColor(), B_LIGHTEN_2_TINT);
63			else
64				labelColor = tint_color(HighColor(), B_DARKEN_2_TINT);
65		}
66
67		SetHighColor(labelColor);
68		BFont font;
69		GetFont(&font);
70
71		BString truncated(name_for_id(property->Identifier()));
72		font.TruncateString(&truncated, B_TRUNCATE_MIDDLE, fLabelWidth - 10.0);
73
74		font_height fh;
75		font.GetHeight(&fh);
76
77		FillRect(BRect(b.left, b.top, b.left + fLabelWidth, b.bottom), B_SOLID_LOW);
78		DrawString(truncated.String(), BPoint(b.left + 5.0,
79											  floorf(b.top + b.Height() / 2.0
80												  		   + fh.ascent / 2.0)));
81
82		// draw a "separator" line behind the label
83
84		rgb_color lowColor = LowColor();
85			// Dark Themes
86		if (lowColor.red + lowColor.green + lowColor.blue > 128 * 3)
87			SetHighColor(tint_color(LowColor(), B_DARKEN_1_TINT));
88		else
89			SetHighColor(tint_color(LowColor(), B_LIGHTEN_1_TINT));
90
91		StrokeLine(BPoint(b.left + fLabelWidth - 1.0, b.top),
92				   BPoint(b.left + fLabelWidth - 1.0, b.bottom), B_SOLID_HIGH);
93		SetHighColor(highColor);
94	}
95}
96
97// FrameResized
98void
99PropertyItemView::FrameResized(float width, float height)
100{
101	if (fEditorView) {
102		fEditorView->MoveTo(fLabelWidth, 0.0);
103		fEditorView->ResizeTo(width - fLabelWidth, height);
104		fEditorView->FrameResized(fEditorView->Bounds().Width(),
105								 fEditorView->Bounds().Height());
106	}
107}
108
109// MakeFocus
110void
111PropertyItemView::MakeFocus(bool focused)
112{
113	if (fEditorView)
114		fEditorView->MakeFocus(focused);
115}
116
117// MouseDown
118void
119PropertyItemView::MouseDown(BPoint where)
120{
121	if (fParent) {
122		// select ourself
123		fParent->Select(this);
124		if (fEditorView)
125			fEditorView->MakeFocus(true);
126
127		if (BMessage* message = Window()->CurrentMessage()) {
128			int32 clicks;
129			if (message->FindInt32("clicks", &clicks) >= B_OK) {
130				if (clicks >= 2)
131					fParent->DoubleClicked(this);
132				else
133					fParent->Clicked(this);
134			}
135		}
136	}
137}
138
139// MouseUp
140void
141PropertyItemView::MouseUp(BPoint where)
142{
143}
144
145// MouseMoved
146void
147PropertyItemView::MouseMoved(BPoint where, uint32 transit, const BMessage* dragMessage)
148{
149}
150
151// PreferredHeight
152float
153PropertyItemView::PreferredHeight() const
154{
155	font_height fh;
156	GetFontHeight(&fh);
157
158	float height = floorf(4.0 + fh.ascent + fh.descent);
159	if (fEditorView)
160		height = max_c(height, fEditorView->PreferredHeight());
161
162	return height;
163}
164
165// PreferredLabelWidth
166float
167PropertyItemView::PreferredLabelWidth() const
168{
169	float width = 0.0;
170	if (const Property* property = GetProperty())
171		width = ceilf(StringWidth(name_for_id(property->Identifier())) + 10.0);
172	return width;
173}
174
175// SetLabelWidth
176void
177PropertyItemView::SetLabelWidth(float width)
178{
179	if (width < 0.0)
180		width = 0.0;
181/*	if (fEditorView && width > Bounds().Width() - fEditorView->Bounds().Width())
182		width = Bounds().Width() - fEditorView->Bounds().Width();
183	else if (width > Bounds().Width())
184		width = Bounds().Width();*/
185
186	fLabelWidth = width;
187}
188
189// SetSelected
190void
191PropertyItemView::SetSelected(bool selected)
192{
193	fSelected = selected;
194	_UpdateLowColor();
195}
196
197// SetEnabled
198void
199PropertyItemView::SetEnabled(bool enabled)
200{
201	if (fEnabled != enabled) {
202		fEnabled = enabled;
203		fEditorView->SetEnabled(fEnabled);
204	}
205}
206
207// IsFocused
208bool
209PropertyItemView::IsFocused() const
210{
211	if (fEditorView)
212		return fEditorView->IsFocused();
213	return false;
214}
215
216// GetProperty
217Property*
218PropertyItemView::GetProperty() const
219{
220	if (fEditorView)
221		return fEditorView->GetProperty();
222	return NULL;
223}
224
225// SetProperty
226bool
227PropertyItemView::AdoptProperty(Property* property)
228{
229	if (fEditorView && fEditorView->AdoptProperty(property)) {
230		_UpdateLowColor();
231		return true;
232	}
233	return false;
234}
235
236// SetListView
237void
238PropertyItemView::SetListView(PropertyListView* parent)
239{
240	fParent = parent;
241	_UpdateLowColor();
242}
243
244// UpdateObject
245void
246PropertyItemView::UpdateObject()
247{
248	if (fParent && fEditorView) {
249		if (const Property* p = fEditorView->GetProperty())
250			fParent->UpdateObject(p->Identifier());
251	}
252}
253
254// #pragma mark -
255
256// _UpdateLowColor
257void
258PropertyItemView::_UpdateLowColor()
259{
260	rgb_color lowColor = fParent ? fParent->LowColor()
261		: ui_color(B_LIST_BACKGROUND_COLOR);
262	if (fSelected) {
263		lowColor = ui_color(B_LIST_SELECTED_BACKGROUND_COLOR);
264		SetHighColor(ui_color(B_LIST_SELECTED_ITEM_TEXT_COLOR));
265	} else {
266		SetHighColor(ui_color(B_LIST_ITEM_TEXT_COLOR));
267	}
268	if (lowColor != LowColor()) {
269		SetLowColor(lowColor);
270		Invalidate();
271	}
272}
273
274