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