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