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 30 using 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 */ 44 template<class Type> 45 class 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 72 template<class Type> 73 AddCommand<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 98 template<class Type> 99 AddCommand<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 111 template<class Type> 112 status_t 113 AddCommand<Type>::InitCheck() 114 { 115 return fContainer && fItems ? B_OK : B_NO_INIT; 116 } 117 118 119 template<class Type> 120 status_t 121 AddCommand<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 138 template<class Type> 139 status_t 140 AddCommand<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 152 template<class Type> 153 void 154 AddCommand<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