xref: /haiku/src/apps/icon-o-matic/shape/commands/SplitPointsCommand.cpp (revision 02354704729d38c3b078c696adc1bbbd33cbcf72)
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 
24 using 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
29 SplitPointsCommand::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
66 SplitPointsCommand::~SplitPointsCommand()
67 {
68 	delete[] fIndex;
69 	delete[] fPoint;
70 	delete[] fPointIn;
71 	delete[] fPointOut;
72 	delete[] fConnected;
73 }
74 
75 // InitCheck
76 status_t
77 SplitPointsCommand::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
88 status_t
89 SplitPointsCommand::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
122 status_t
123 SplitPointsCommand::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
154 void
155 SplitPointsCommand::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