1/*
2 * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Distributed under the terms of the MIT License.
4 */
5
6
7#include "ValueHandlerRoster.h"
8
9#include <new>
10
11#include <AutoDeleter.h>
12#include <AutoLocker.h>
13
14#include "AddressValueHandler.h"
15#include "BoolValueHandler.h"
16#include "EnumerationValueHandler.h"
17#include "FloatValueHandler.h"
18#include "StringValueHandler.h"
19#include "Value.h"
20
21
22/*static*/ ValueHandlerRoster* ValueHandlerRoster::sDefaultInstance = NULL;
23
24
25ValueHandlerRoster::ValueHandlerRoster()
26	:
27	fLock("value handler roster"),
28	fValueHandlers(20, false)
29{
30}
31
32
33ValueHandlerRoster::~ValueHandlerRoster()
34{
35	for(int32 i = 0; ValueHandler* handler = fValueHandlers.ItemAt(i); i++)
36		handler->ReleaseReference();
37}
38
39/*static*/ ValueHandlerRoster*
40ValueHandlerRoster::Default()
41{
42	return sDefaultInstance;
43}
44
45
46/*static*/ status_t
47ValueHandlerRoster::CreateDefault()
48{
49	if (sDefaultInstance != NULL)
50		return B_OK;
51
52	ValueHandlerRoster* roster = new(std::nothrow) ValueHandlerRoster;
53	if (roster == NULL)
54		return B_NO_MEMORY;
55	ObjectDeleter<ValueHandlerRoster> rosterDeleter(roster);
56
57	status_t error = roster->Init();
58	if (error != B_OK)
59		return error;
60
61	error = roster->RegisterDefaultHandlers();
62	if (error != B_OK)
63		return error;
64
65	sDefaultInstance = rosterDeleter.Detach();
66	return B_OK;
67}
68
69
70/*static*/ void
71ValueHandlerRoster::DeleteDefault()
72{
73	ValueHandlerRoster* roster = sDefaultInstance;
74	sDefaultInstance = NULL;
75	delete roster;
76}
77
78
79status_t
80ValueHandlerRoster::Init()
81{
82	return fLock.InitCheck();
83}
84
85
86status_t
87ValueHandlerRoster::RegisterDefaultHandlers()
88{
89	status_t error;
90
91	#undef REGISTER_HANDLER
92	#define REGISTER_HANDLER(name)											\
93		{																	\
94			name##ValueHandler* handler										\
95				= new(std::nothrow) name##ValueHandler;						\
96			if (handler == NULL)											\
97				return B_NO_MEMORY;											\
98			BReference<name##ValueHandler> handlerReference(handler, true);	\
99																			\
100			error = handler->Init();										\
101			if (error != B_OK)												\
102				return error;												\
103																			\
104			if (!RegisterHandler(handler))									\
105				return B_NO_MEMORY;											\
106		}
107
108	REGISTER_HANDLER(Address)
109	REGISTER_HANDLER(Bool)
110	REGISTER_HANDLER(Enumeration)
111	REGISTER_HANDLER(Float)
112	REGISTER_HANDLER(Integer)
113	REGISTER_HANDLER(String)
114
115	return B_OK;
116}
117
118
119status_t
120ValueHandlerRoster::FindValueHandler(Value* value, ValueHandler*& _handler)
121{
122	// find the best-supporting handler
123	AutoLocker<BLocker> locker(fLock);
124
125	ValueHandler* bestHandler = NULL;
126	float bestSupport = 0;
127
128	for (int32 i = 0; ValueHandler* handler = fValueHandlers.ItemAt(i); i++) {
129		float support = handler->SupportsValue(value);
130		if (support > 0 && support > bestSupport) {
131			bestHandler = handler;
132			bestSupport = support;
133		}
134	}
135
136	if (bestHandler == NULL)
137		return B_ENTRY_NOT_FOUND;
138
139	bestHandler->AcquireReference();
140	_handler = bestHandler;
141	return B_OK;
142}
143
144
145status_t
146ValueHandlerRoster::GetValueFormatter(Value* value,
147	ValueFormatter*& _formatter)
148{
149	// get the best supporting value handler
150	ValueHandler* handler;
151	status_t error = FindValueHandler(value, handler);
152	if (error != B_OK)
153		return error;
154	BReference<ValueHandler> handlerReference(handler, true);
155
156	// create the formatter
157	return handler->GetValueFormatter(value, _formatter);
158}
159
160
161status_t
162ValueHandlerRoster::GetTableCellValueRenderer(Value* value,
163	TableCellValueRenderer*& _renderer)
164{
165	// get the best supporting value handler
166	ValueHandler* handler;
167	status_t error = FindValueHandler(value, handler);
168	if (error != B_OK)
169		return error;
170	BReference<ValueHandler> handlerReference(handler, true);
171
172	// create the renderer
173	return handler->GetTableCellValueRenderer(value, _renderer);
174}
175
176
177bool
178ValueHandlerRoster::RegisterHandler(ValueHandler* handler)
179{
180	if (!fValueHandlers.AddItem(handler))
181		return false;
182
183	handler->AcquireReference();
184	return true;
185}
186
187
188void
189ValueHandlerRoster::UnregisterHandler(ValueHandler* handler)
190{
191	if (fValueHandlers.RemoveItem(handler))
192		handler->ReleaseReference();
193}
194