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
25using std::nothrow;
26
27// constructor
28// * when clicking a point in Remove mode, with other points selected
29RemovePointsCommand::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
49RemovePointsCommand::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
66RemovePointsCommand::~RemovePointsCommand()
67{
68	delete[] fIndex;
69	delete[] fPoint;
70	delete[] fPointIn;
71	delete[] fPointOut;
72	delete[] fConnected;
73	delete[] fOldSelection;
74}
75
76// InitCheck
77status_t
78RemovePointsCommand::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
89status_t
90RemovePointsCommand::Perform()
91{
92	// path points are already removed
93	return InitCheck();
94}
95
96// Undo
97status_t
98RemovePointsCommand::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
131status_t
132RemovePointsCommand::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
162void
163RemovePointsCommand::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
171void
172RemovePointsCommand::_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