xref: /haiku/src/apps/icon-o-matic/generic/command/AddCommand.h (revision e1c4049fed1047bdb957b0529e1921e97ef94770)
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