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