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>
AddCommand(Container<Type> * container,const Type * const * items,int32 count,bool ownsItems,int32 index)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>
~AddCommand()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
InitCheck()113 AddCommand<Type>::InitCheck()
114 {
115 return fContainer && fItems ? B_OK : B_NO_INIT;
116 }
117
118
119 template<class Type>
120 status_t
Perform()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
Undo()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
GetName(BString & name)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