| // Copyright 2017 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef GARNET_LIB_UI_GFX_ENGINE_RESOURCE_MAP_H_ |
| #define GARNET_LIB_UI_GFX_ENGINE_RESOURCE_MAP_H_ |
| |
| #include "garnet/lib/ui/gfx/resources/resource.h" |
| #include "garnet/lib/ui/gfx/resources/variable.h" |
| #include "garnet/lib/ui/scenic/util/error_reporter.h" |
| |
| #include <unordered_map> |
| |
| namespace scenic_impl { |
| namespace gfx { |
| |
| class ResourceMap { |
| public: |
| explicit ResourceMap( |
| ErrorReporter* error_reporter = ErrorReporter::Default()); |
| ~ResourceMap(); |
| |
| void Clear(); |
| |
| // Attempt to add the resource; return true if successful. Return false if |
| // the ID is already present in the map, which is left unchanged. |
| bool AddResource(ResourceId id, ResourcePtr resource); |
| |
| // Attempt to remove the specified resource. Return true if successful, and |
| // false if the ID was not present in the map. |
| bool RemoveResource(ResourceId id); |
| |
| size_t size() const { return resources_.size(); } |
| |
| enum class ErrorBehavior { kDontReportErrors, kReportErrors }; |
| |
| // Attempt to find the resource within the map. If it is found, verify that |
| // it has the correct type, and return it. Return nullptr and report an |
| // error if it is not found, or if type validation fails. |
| // |
| // example: |
| // ResourceType someResource = map.FindResource<ResourceType>(); |
| template <class ResourceT> |
| fxl::RefPtr<ResourceT> FindResource( |
| ResourceId id, |
| ErrorBehavior report_errors = ErrorBehavior::kReportErrors) { |
| auto it = resources_.find(id); |
| |
| if (it == resources_.end()) { |
| if (report_errors == ErrorBehavior::kReportErrors) { |
| error_reporter_->ERROR() << "No resource exists with ID " << id; |
| } |
| return fxl::RefPtr<ResourceT>(); |
| }; |
| |
| auto resource_ptr = it->second->GetDelegate(ResourceT::kTypeInfo); |
| if (resource_ptr == nullptr) { |
| if (report_errors == ErrorBehavior::kReportErrors) { |
| error_reporter_->ERROR() |
| << "Type mismatch for resource ID " << id << ": actual type is " |
| << it->second->type_info().name << ", expected a sub-type of " |
| << ResourceT::kTypeInfo.name; |
| } |
| return fxl::RefPtr<ResourceT>(); |
| } |
| |
| return fxl::RefPtr<ResourceT>(static_cast<ResourceT*>(resource_ptr)); |
| } |
| |
| template <class ResourceT> |
| fxl::RefPtr<ResourceT> FindVariableResource(ResourceId id) { |
| auto it = resources_.find(id); |
| |
| if (it == resources_.end()) { |
| error_reporter_->ERROR() << "No resource exists with ID " << id; |
| return fxl::RefPtr<ResourceT>(); |
| }; |
| |
| auto resource_ptr = it->second->GetDelegate(Variable::kTypeInfo); |
| |
| if (resource_ptr == nullptr) { |
| error_reporter_->ERROR() |
| << "Type mismatch for resource ID " << id << ": actual type is " |
| << it->second->type_info().name << ", expected a sub-type of " |
| << Variable::kTypeInfo.name; |
| return fxl::RefPtr<ResourceT>(); |
| } |
| |
| Variable* variable_ptr = static_cast<Variable*>(resource_ptr); |
| if (ResourceT::ValueType() != variable_ptr->value_type()) { |
| error_reporter_->ERROR() |
| << "Type mismatch for Variable resource ID " << id |
| << ": actual type is " << variable_ptr->value_type() << ", expected " |
| << ResourceT::ValueType(); |
| return fxl::RefPtr<ResourceT>(); |
| } |
| |
| return fxl::RefPtr<ResourceT>(static_cast<ResourceT*>(resource_ptr)); |
| } |
| |
| private: |
| std::unordered_map<ResourceId, ResourcePtr> resources_; |
| ErrorReporter* const error_reporter_; |
| }; |
| |
| } // namespace gfx |
| } // namespace scenic_impl |
| |
| #endif // GARNET_LIB_UI_GFX_ENGINE_RESOURCE_MAP_H_ |