1/*
2 * Copyright 2006-2007, Haiku Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 *		Stephan Aßmus <superstippi@gmx.de>
7 */
8
9#include "IconObjectListView.h"
10
11#include <new>
12#include <stdio.h>
13#include <string.h>
14
15#include <Catalog.h>
16#include <Locale.h>
17
18#include "CommandStack.h"
19#include "CommonPropertyIDs.h"
20#include "IconObject.h"
21#include "Property.h"
22#include "PropertyItemView.h"
23#include "PropertyObject.h"
24#include "Selection.h"
25#include "SetPropertiesCommand.h"
26
27
28#undef B_TRANSLATION_CONTEXT
29#define B_TRANSLATION_CONTEXT "Icon-O-Matic-PropertiesList"
30
31
32using std::nothrow;
33
34// constructor
35IconObjectListView::IconObjectListView()
36	: PropertyListView(),
37
38	  fSelection(NULL),
39	  fCommandStack(NULL),
40	  fObject(NULL),
41	  fIgnoreObjectChange(false)
42{
43}
44
45// destructor
46IconObjectListView::~IconObjectListView()
47{
48	SetSelection(NULL);
49	_SetObject(NULL);
50}
51
52// Draw
53void
54IconObjectListView::Draw(BRect updateRect)
55{
56	PropertyListView::Draw(updateRect);
57
58	if (fObject)
59		return;
60
61	// display helpful messages
62	const char* message1 = B_TRANSLATE_CONTEXT(
63		"Click on an object in", "Empty property list - 1st line");
64	const char* message2 = B_TRANSLATE_CONTEXT(
65		"any of the other lists to", "Empty property list - 2nd line");
66	const char* message3 = B_TRANSLATE_CONTEXT(
67		"edit it's properties here.", "Empty property list - 3rd line");
68
69	// Dark Themes
70	rgb_color lowColor = LowColor();
71	if (lowColor.red + lowColor.green + lowColor.blue > 128 * 3)
72		SetHighColor(tint_color(LowColor(), B_DARKEN_2_TINT));
73	else
74		SetHighColor(tint_color(LowColor(), B_LIGHTEN_2_TINT));
75
76	font_height fh;
77	GetFontHeight(&fh);
78	BRect b(Bounds());
79
80	BPoint middle;
81	float textHeight = (fh.ascent + fh.descent) * 1.5;
82	middle.y = (b.top + b.bottom) / 2.0 - textHeight;
83	middle.x = (b.left + b.right - StringWidth(message1)) / 2.0;
84	DrawString(message1, middle);
85
86	middle.y += textHeight;
87	middle.x = (b.left + b.right - StringWidth(message2)) / 2.0;
88	DrawString(message2, middle);
89
90	middle.y += textHeight;
91	middle.x = (b.left + b.right - StringWidth(message3)) / 2.0;
92	DrawString(message3, middle);
93}
94
95// PropertyChanged
96void
97IconObjectListView::PropertyChanged(const Property* previous,
98									const Property* current)
99{
100	if (!fCommandStack || !fObject)
101		return;
102
103	PropertyObject* oldObject = new (nothrow) PropertyObject();
104	if (oldObject)
105		oldObject->AddProperty(previous->Clone());
106
107	PropertyObject* newObject = new (nothrow) PropertyObject();
108	if (newObject)
109		newObject->AddProperty(current->Clone());
110
111	IconObject** objects = new (nothrow) IconObject*[1];
112	if (objects)
113		objects[0] = fObject;
114
115	Command* command = new (nothrow) SetPropertiesCommand(objects, 1,
116														  oldObject,
117														  newObject);
118	fIgnoreObjectChange = true;
119	fCommandStack->Perform(command);
120	fIgnoreObjectChange = false;
121}
122
123// PasteProperties
124void
125IconObjectListView::PasteProperties(const PropertyObject* object)
126{
127	// TODO: command for this
128	if (fObject)
129		fObject->SetToPropertyObject(object);
130
131	PropertyListView::PasteProperties(object);
132}
133
134// IsEditingMultipleObjects
135bool
136IconObjectListView::IsEditingMultipleObjects()
137{
138	return false;
139}
140
141// #pragma mark -
142
143// ObjectChanged
144void
145IconObjectListView::ObjectChanged(const Observable* object)
146{
147	if (object == fSelection) {
148		Selectable* selected = fSelection->SelectableAt(0);
149		_SetObject(dynamic_cast<IconObject*>(selected));
150	}
151
152	if (object == fObject/* && !fIgnoreObjectChange*/) {
153//printf("IconObjectListView::ObjectChanged(fObject)\n");
154		SetTo(fObject->MakePropertyObject());
155	}
156}
157
158// #pragma mark -
159
160// SetSelection
161void
162IconObjectListView::SetSelection(Selection* selection)
163{
164	if (fSelection == selection)
165		return;
166
167	if (fSelection)
168		fSelection->RemoveObserver(this);
169
170	fSelection = selection;
171
172	if (fSelection)
173		fSelection->AddObserver(this);
174}
175
176// SetCommandStack
177void
178IconObjectListView::SetCommandStack(CommandStack* stack)
179{
180	fCommandStack = stack;
181}
182
183// FocusNameProperty
184void
185IconObjectListView::FocusNameProperty()
186{
187	if (fObject == NULL)
188		return;
189
190	int32 count = _CountItems();
191	for (int32 i = 0; i < count; i++) {
192		PropertyItemView* item = _ItemAt(i);
193		Property* property = item->GetProperty();
194		if (property != NULL && property->Identifier() == PROPERTY_NAME) {
195			item->MakeFocus(true);
196			break;
197		}
198	}
199}
200
201
202// #pragma mark -
203
204// _SetObject
205void
206IconObjectListView::_SetObject(IconObject* object)
207{
208	if (fObject == object)
209		return;
210
211	if (fObject) {
212		fObject->RemoveObserver(this);
213		fObject->ReleaseReference();
214	}
215
216	fObject = object;
217	PropertyObject* propertyObject = NULL;
218
219	if (fObject) {
220		fObject->AcquireReference();
221		fObject->AddObserver(this);
222		propertyObject = fObject->MakePropertyObject();
223	}
224
225	SetTo(propertyObject);
226}
227
228