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 25 ValueHandlerRoster::ValueHandlerRoster() 26 : 27 fLock("value handler roster") 28 { 29 } 30 31 32 ValueHandlerRoster::~ValueHandlerRoster() 33 { 34 } 35 36 /*static*/ ValueHandlerRoster* 37 ValueHandlerRoster::Default() 38 { 39 return sDefaultInstance; 40 } 41 42 43 /*static*/ status_t 44 ValueHandlerRoster::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 68 ValueHandlerRoster::DeleteDefault() 69 { 70 ValueHandlerRoster* roster = sDefaultInstance; 71 sDefaultInstance = NULL; 72 delete roster; 73 } 74 75 76 status_t 77 ValueHandlerRoster::Init() 78 { 79 return fLock.InitCheck(); 80 } 81 82 83 status_t 84 ValueHandlerRoster::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 116 status_t 117 ValueHandlerRoster::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 142 status_t 143 ValueHandlerRoster::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 158 status_t 159 ValueHandlerRoster::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 174 bool 175 ValueHandlerRoster::RegisterHandler(ValueHandler* handler) 176 { 177 if (!fValueHandlers.AddItem(handler)) 178 return false; 179 180 handler->AcquireReference(); 181 return true; 182 } 183 184 185 void 186 ValueHandlerRoster::UnregisterHandler(ValueHandler* handler) 187 { 188 if (fValueHandlers.RemoveItem(handler)) 189 handler->ReleaseReference(); 190 } 191