xref: /haiku/src/apps/icon-o-matic/shape/commands/SplitPointsCommand.cpp (revision e1c4049fed1047bdb957b0529e1921e97ef94770)
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 
25 using 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
30 SplitPointsCommand::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
67 SplitPointsCommand::~SplitPointsCommand()
68 {
69 	delete[] fIndex;
70 	delete[] fPoint;
71 	delete[] fPointIn;
72 	delete[] fPointOut;
73 	delete[] fConnected;
74 }
75 
76 // InitCheck
77 status_t
78 SplitPointsCommand::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
89 status_t
90 SplitPointsCommand::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
123 status_t
124 SplitPointsCommand::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
155 void
156 SplitPointsCommand::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