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