/* * Copyright 2006-2007, 2023, Haiku. * Distributed under the terms of the MIT License. * * Authors: * Stephan Aßmus * Zardshard */ #ifndef CONTAINER_H #define CONTAINER_H #include #include #include #include #include #include "IconBuild.h" class BReferenceable; _BEGIN_ICON_NAMESPACE template class ContainerListener { public: ContainerListener(); virtual ~ContainerListener(); virtual void ItemAdded(Type* item, int32 index) = 0; virtual void ItemRemoved(Type* item) = 0; }; /*! Wraps \c BList and provides some additional features. -# It allows listeners to listen when an item is added or removed. -# It can take ownership of the objects that it stores. -# It casts list items into the correct type. */ // TODO: some of these features are provided by BObjectList template class Container { public: Container(bool ownsItems); virtual ~Container(); bool AddItem(Type* item); bool AddItem(Type* item, int32 index); bool RemoveItem(Type* item); Type* RemoveItem(int32 index); void MakeEmpty(); int32 CountItems() const; bool HasItem(Type* item) const; int32 IndexOf(Type* item) const; Type* ItemAt(int32 index) const; Type* ItemAtFast(int32 index) const; bool AddListener(ContainerListener* listener); bool RemoveListener(ContainerListener* listener); private: void _NotifyItemAdded(Type* item, int32 index) const; void _NotifyItemRemoved(Type* item) const; private: BList fItems; bool fOwnsItems; BList fListeners; }; template ContainerListener::ContainerListener() {} template ContainerListener::~ContainerListener() {} template Container::Container(bool ownsItems) : fItems(16), fOwnsItems(ownsItems), fListeners(2) { } template Container::~Container() { int32 count = fListeners.CountItems(); if (count > 0) { debugger("~Container() - there are still" "listeners attached\n"); } MakeEmpty(); } // #pragma mark - template bool Container::AddItem(Type* item) { return AddItem(item, CountItems()); } template bool Container::AddItem(Type* item, int32 index) { if (!item) return false; // prevent adding the same item twice if (HasItem(item)) return false; if (fItems.AddItem((void*)item, index)) { _NotifyItemAdded(item, index); return true; } fprintf(stderr, "Container::AddItem() - out of memory!\n"); return false; } template bool Container::RemoveItem(Type* item) { if (fItems.RemoveItem((void*)item)) { _NotifyItemRemoved(item); return true; } return false; } template Type* Container::RemoveItem(int32 index) { Type* item = (Type*)fItems.RemoveItem(index); if (item) { _NotifyItemRemoved(item); } return item; } template void Container::MakeEmpty() { int32 count = CountItems(); for (int32 i = 0; i < count; i++) { Type* item = ItemAtFast(i); _NotifyItemRemoved(item); #ifdef ICON_O_MATIC if (fOwnsItems) item->ReleaseReference(); #else if (fOwnsItems) delete item; #endif } fItems.MakeEmpty(); } // #pragma mark - template int32 Container::CountItems() const { return fItems.CountItems(); } template bool Container::HasItem(Type* item) const { return fItems.HasItem(item); } template int32 Container::IndexOf(Type* item) const { return fItems.IndexOf((void*)item); } template Type* Container::ItemAt(int32 index) const { return (Type*)fItems.ItemAt(index); } template Type* Container::ItemAtFast(int32 index) const { return (Type*)fItems.ItemAtFast(index); } // #pragma mark - template bool Container::AddListener(ContainerListener* listener) { if (listener && !fListeners.HasItem(listener)) return fListeners.AddItem(listener); return false; } template bool Container::RemoveListener(ContainerListener* listener) { return fListeners.RemoveItem(listener); } // #pragma mark - template void Container::_NotifyItemAdded(Type* item, int32 index) const { BList listeners(fListeners); int32 count = listeners.CountItems(); for (int32 i = 0; i < count; i++) { ContainerListener* listener = (ContainerListener*)listeners.ItemAtFast(i); listener->ItemAdded(item, index); } } template void Container::_NotifyItemRemoved(Type* item) const { BList listeners(fListeners); int32 count = listeners.CountItems(); for (int32 i = 0; i < count; i++) { ContainerListener* listener = (ContainerListener*)listeners.ItemAtFast(i); listener->ItemRemoved(item); } } _END_ICON_NAMESPACE #endif // CONTAINER_H