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