1/*
2 * Copyright 2006, Haiku. All rights reserved.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 *		Stephan A��mus <superstippi@gmx.de>
7 */
8
9#include "SplitPointsCommand.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-SplitPointsCmd"
23
24
25using std::nothrow;
26
27// constructor
28// * when hitting the Delete key, so the selected points are the
29// same as the ones to be removed
30SplitPointsCommand::SplitPointsCommand(VectorPath* path,
31									   const int32* indices,
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{
41	if (indices && count > 0) {
42		fIndex = new (nothrow) int32[count];
43		fPoint = new (nothrow) BPoint[count];
44		fPointIn = new (nothrow) BPoint[count];
45		fPointOut = new (nothrow) BPoint[count];
46		fConnected = new (nothrow) bool[count];
47		fCount = count;
48	}
49
50	if (InitCheck() < B_OK)
51		return;
52
53	memcpy(fIndex, indices, count * sizeof(int32));
54	for (int32 i = 0; i < count; i++) {
55		if (!fPath->GetPointsAt(fIndex[i],
56								fPoint[i],
57								fPointIn[i],
58								fPointOut[i],
59								&fConnected[i])) {
60			fPath = NULL;
61			break;
62		}
63	}
64}
65
66// destructor
67SplitPointsCommand::~SplitPointsCommand()
68{
69	delete[] fIndex;
70	delete[] fPoint;
71	delete[] fPointIn;
72	delete[] fPointOut;
73	delete[] fConnected;
74}
75
76// InitCheck
77status_t
78SplitPointsCommand::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
90SplitPointsCommand::Perform()
91{
92	status_t status = B_OK;
93
94	AutoNotificationSuspender _(fPath);
95
96	// NOTE: fCount guaranteed > 0
97	// add points again at their respective index
98	for (int32 i = 0; i < fCount; i++) {
99		int32 index = fIndex[i] + 1 + i;
100			// "+ 1" to insert behind existing point
101			// "+ i" to adjust for already inserted points
102		if (fPath->AddPoint(fPoint[i], index)) {
103			fPath->SetPoint(index - 1,
104							fPoint[i],
105							fPointIn[i],
106							fPoint[i],
107							true);
108			fPath->SetPoint(index,
109							fPoint[i],
110							fPoint[i],
111							fPointOut[i],
112							true);
113		} else {
114			status = B_ERROR;
115			break;
116		}
117	}
118
119	return status;
120}
121
122// Undo
123status_t
124SplitPointsCommand::Undo()
125{
126	status_t status = B_OK;
127
128	AutoNotificationSuspender _(fPath);
129
130	// remove inserted points and reset modified
131	// points to previous condition
132	for (int32 i = 0; i < fCount; i++) {
133		int32 index = fIndex[i] + 1;
134		if (fPath->RemovePoint(index)) {
135			fPath->SetPoint(index - 1,
136							fPoint[i],
137							fPointIn[i],
138							fPointOut[i],
139							fConnected[i]);
140		} else {
141			status = B_ERROR;
142			break;
143		}
144	}
145
146	if (status >= B_OK) {
147		// restore selection
148		_Select(fIndex, fCount);
149	}
150
151	return status;
152}
153
154// GetName
155void
156SplitPointsCommand::GetName(BString& name)
157{
158	static BStringFormat format(B_TRANSLATE("Split {0, plural, "
159		"one{vertex} other{vertices}}"));
160	format.Format(name, fCount);
161}
162
163