1/* 2 * Copyright 2006-2007, 2023, Haiku. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Stephan A��mus <superstippi@gmx.de> 7 * Zardshard 8 */ 9#ifndef ADD_COMMAND_H 10#define ADD_COMMAND_H 11 12#include <new> 13#include <stdio.h> 14#include <string.h> 15 16#include <Catalog.h> 17#include <Locale.h> 18#include <Referenceable.h> 19#include <StringFormat.h> 20 21#include "Command.h" 22#include "Container.h" 23#include "IconBuild.h" 24 25 26#undef B_TRANSLATION_CONTEXT 27#define B_TRANSLATION_CONTEXT "Icon-O-Matic-AddItemsCmd" 28 29 30using std::nothrow; 31 32 33_BEGIN_ICON_NAMESPACE 34 class BReferenceable; 35_END_ICON_NAMESPACE 36 37_USING_ICON_NAMESPACE 38 39 40/*! Adds items to a \c Container. 41 42 \note This class should be subclassed and the \c GetName member overridden. 43*/ 44template<class Type> 45class AddCommand : public Command { 46 public: 47 AddCommand( 48 Container<Type>* container, 49 const Type* const* items, 50 int32 count, 51 bool ownsItems, 52 int32 index); 53 virtual ~AddCommand(); 54 55 virtual status_t InitCheck(); 56 57 virtual status_t Perform(); 58 virtual status_t Undo(); 59 60 virtual void GetName(BString& name); 61 62 protected: 63 Container<Type>* fContainer; 64 Type** fItems; 65 int32 fCount; 66 bool fOwnsItems; 67 int32 fIndex; 68 bool fItemsAdded; 69}; 70 71 72template<class Type> 73AddCommand<Type>::AddCommand(Container<Type>* container, 74 const Type* const* items, int32 count, bool ownsItems, int32 index) 75 : Command(), 76 fContainer(container), 77 fItems(items && count > 0 ? new (nothrow) Type*[count] : NULL), 78 fCount(count), 79 fOwnsItems(ownsItems), 80 fIndex(index), 81 fItemsAdded(false) 82{ 83 if (!fContainer || !fItems) 84 return; 85 86 memcpy(fItems, items, sizeof(Type*) * fCount); 87 88 if (!fOwnsItems) { 89 // Add references to items 90 for (int32 i = 0; i < fCount; i++) { 91 if (fItems[i] != NULL) 92 fItems[i]->AcquireReference(); 93 } 94 } 95} 96 97 98template<class Type> 99AddCommand<Type>::~AddCommand() 100{ 101 if (!fItemsAdded && fItems) { 102 for (int32 i = 0; i < fCount; i++) { 103 if (fItems[i] != NULL) 104 fItems[i]->ReleaseReference(); 105 } 106 } 107 delete[] fItems; 108} 109 110 111template<class Type> 112status_t 113AddCommand<Type>::InitCheck() 114{ 115 return fContainer && fItems ? B_OK : B_NO_INIT; 116} 117 118 119template<class Type> 120status_t 121AddCommand<Type>::Perform() 122{ 123 // add items to container 124 for (int32 i = 0; i < fCount; i++) { 125 if (fItems[i] && !fContainer->AddItem(fItems[i], fIndex + i)) { 126 // roll back 127 for (int32 j = i - 1; j >= 0; j--) 128 fContainer->RemoveItem(fItems[j]); 129 return B_ERROR; 130 } 131 } 132 fItemsAdded = true; 133 134 return B_OK; 135} 136 137 138template<class Type> 139status_t 140AddCommand<Type>::Undo() 141{ 142 // remove items from container 143 for (int32 i = 0; i < fCount; i++) { 144 fContainer->RemoveItem(fItems[i]); 145 } 146 fItemsAdded = false; 147 148 return B_OK; 149} 150 151 152template<class Type> 153void 154AddCommand<Type>::GetName(BString& name) 155{ 156 static BStringFormat format(B_TRANSLATE("Add {0, plural, " 157 "one{item} other{items}}")); 158 format.Format(name, fCount); 159} 160#endif // ADD_COMMAND_H 161