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