xref: /haiku/src/apps/icon-o-matic/shape/commands/RemovePointsCommand.cpp (revision e1c4049fed1047bdb957b0529e1921e97ef94770)
1 /*
2  * Copyright 2006, Haiku.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		Stephan Aßmus <superstippi@gmx.de>
7  */
8 
9 #include "RemovePointsCommand.h"
10 
11 #include <new>
12 #include <stdio.h>
13 
14 #include <Catalog.h>
15 #include <Locale.h>
16 #include <StringFormat.h>
17 
18 #include "VectorPath.h"
19 
20 
21 #undef B_TRANSLATION_CONTEXT
22 #define B_TRANSLATION_CONTEXT "Icon-O-Matic-RemovePointsCmd"
23 
24 
25 using std::nothrow;
26 
27 // constructor
28 // * when clicking a point in Remove mode, with other points selected
29 RemovePointsCommand::RemovePointsCommand(VectorPath* path,
30 										 int32 index,
31 										 const int32* selected,
32 										 int32 count)
33 	: PathCommand(path),
34 	  fIndex(NULL),
35 	  fPoint(NULL),
36 	  fPointIn(NULL),
37 	  fPointOut(NULL),
38 	  fConnected(NULL),
39 	  fCount(0),
40 	  fOldSelection(NULL),
41 	  fOldSelectionCount(count)
42 {
43 	_Init(&index, 1, selected, count);
44 }
45 
46 // constructor
47 // * when hitting the Delete key, so the selected points are the
48 // same as the ones to be removed
49 RemovePointsCommand::RemovePointsCommand(VectorPath* path,
50 										 const int32* selected,
51 										 int32 count)
52 	: PathCommand(path),
53 	  fIndex(NULL),
54 	  fPoint(NULL),
55 	  fPointIn(NULL),
56 	  fPointOut(NULL),
57 	  fConnected(NULL),
58 	  fCount(0),
59 	  fOldSelection(NULL),
60 	  fOldSelectionCount(count)
61 {
62 	_Init(selected, count, selected, count);
63 }
64 
65 // destructor
66 RemovePointsCommand::~RemovePointsCommand()
67 {
68 	delete[] fIndex;
69 	delete[] fPoint;
70 	delete[] fPointIn;
71 	delete[] fPointOut;
72 	delete[] fConnected;
73 	delete[] fOldSelection;
74 }
75 
76 // InitCheck
77 status_t
78 RemovePointsCommand::InitCheck()
79 {
80 	status_t status = PathCommand::InitCheck();
81 	if (status < B_OK)
82 		return status;
83 	if (!fIndex || !fPoint || !fPointIn || !fPointOut || !fConnected)
84 		status = B_NO_MEMORY;
85 	return status;
86 }
87 
88 // Perform
89 status_t
90 RemovePointsCommand::Perform()
91 {
92 	// path points are already removed
93 	return InitCheck();
94 }
95 
96 // Undo
97 status_t
98 RemovePointsCommand::Undo()
99 {
100 	status_t status = InitCheck();
101 	if (status < B_OK)
102 		return status;
103 
104 	AutoNotificationSuspender _(fPath);
105 
106 	// add points again at their respective index
107 	for (int32 i = 0; i < fCount; i++) {
108 		if (fPath->AddPoint(fPoint[i], fIndex[i])) {
109 			fPath->SetPoint(fIndex[i],
110 							fPoint[i],
111 							fPointIn[i],
112 							fPointOut[i],
113 							fConnected[i]);
114 		} else {
115 			status = B_ERROR;
116 			break;
117 		}
118 	}
119 
120 	fPath->SetClosed(fWasClosed);
121 
122 	if (status >= B_OK) {
123 		// select the added points
124 		_Select(fIndex, fCount);
125 	}
126 
127 	return status;
128 }
129 
130 // Redo
131 status_t
132 RemovePointsCommand::Redo()
133 {
134 	status_t status = InitCheck();
135 	if (status < B_OK)
136 		return status;
137 
138 	AutoNotificationSuspender _(fPath);
139 
140 	// remove points
141 	// the loop assumes the indices in the collection
142 	// are increasing (removal at "index[i] - i" to account
143 	// for items already removed)
144 	for (int32 i = 0; i < fCount; i++) {
145 		if (!fPath->RemovePoint(fIndex[i] - i)) {
146 			status = B_ERROR;
147 			break;
148 		}
149 	}
150 
151 	fPath->SetClosed(fWasClosed && fPath->CountPoints() > 1);
152 
153 	if (status >= B_OK) {
154 		// restore selection
155 		_Select(fOldSelection, fOldSelectionCount);
156 	}
157 
158 	return status;
159 }
160 
161 // GetName
162 void
163 RemovePointsCommand::GetName(BString& name)
164 {
165 	static BStringFormat format(B_TRANSLATE("Remove {0, plural, "
166 		"one{vertex} other{vertices}}"));
167 	format.Format(name, fCount);
168 }
169 
170 // _Init
171 void
172 RemovePointsCommand::_Init(const int32* indices, int32 count,
173 						 const int32* selection, int32 selectionCount)
174 {
175 	if (indices && count > 0) {
176 		fIndex = new (nothrow) int32[count];
177 		fPoint = new (nothrow) BPoint[count];
178 		fPointIn = new (nothrow) BPoint[count];
179 		fPointOut = new (nothrow) BPoint[count];
180 		fConnected = new (nothrow) bool[count];
181 		fCount = count;
182 	}
183 
184 	if (InitCheck() < B_OK)
185 		return;
186 
187 	memcpy(fIndex, indices, count * sizeof(int32));
188 	for (int32 i = 0; i < count; i++) {
189 		if (!fPath->GetPointsAt(fIndex[i],
190 								fPoint[i],
191 								fPointIn[i],
192 								fPointOut[i],
193 								&fConnected[i])) {
194 			fPath = NULL;
195 			break;
196 		}
197 	}
198 
199 	if (fPath)
200 		fWasClosed = fPath->IsClosed();
201 
202 	if (selectionCount > 0 && selection) {
203 		fOldSelectionCount = selectionCount;
204 		fOldSelection = new (nothrow) int32[selectionCount];
205 		memcpy(fOldSelection, selection, selectionCount * sizeof(int32));
206 	}
207 }
208