1/*
2 * Copyright 2006, Haiku.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 *		Stephan A��mus <superstippi@gmx.de>
7 */
8
9#include "InsertPointCommand.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-InsertPointCmd"
22
23
24using std::nothrow;
25
26// constructor
27InsertPointCommand::InsertPointCommand(VectorPath* path,
28									  int32 index,
29									  const int32* selected,
30									  int32 count)
31	: PathCommand(path),
32	  fIndex(index),
33	  fOldSelection(NULL),
34	  fOldSelectionCount(count)
35{
36	if (fPath && (!fPath->GetPointsAt(fIndex, fPoint, fPointIn, fPointOut)
37				  || !fPath->GetPointOutAt(fIndex - 1, fPreviousOut)
38				  || !fPath->GetPointInAt(fIndex + 1, fNextIn))) {
39		fPath = NULL;
40	}
41	if (fOldSelectionCount > 0 && selected) {
42		fOldSelection = new (nothrow) int32[count];
43		memcpy(fOldSelection, selected, count * sizeof(int32));
44	}
45}
46
47// destructor
48InsertPointCommand::~InsertPointCommand()
49{
50	delete[] fOldSelection;
51}
52
53// Perform
54status_t
55InsertPointCommand::Perform()
56{
57	status_t status = InitCheck();
58	if (status < B_OK)
59		return status;
60
61	// path point is already added
62	// but in/out points might still have changed
63	fPath->GetPointInAt(fIndex, fPointIn);
64	fPath->GetPointOutAt(fIndex, fPointOut);
65
66	return status;
67}
68
69// Undo
70status_t
71InsertPointCommand::Undo()
72{
73	status_t status = InitCheck();
74	if (status < B_OK)
75		return status;
76
77	AutoNotificationSuspender _(fPath);
78
79	// remove the inserted point
80	if (fPath->RemovePoint(fIndex)) {
81		// remember current previous "out" and restore it
82		BPoint previousOut = fPreviousOut;
83		fPath->GetPointOutAt(fIndex - 1, fPreviousOut);
84		fPath->SetPointOut(fIndex - 1, previousOut);
85		// remember current next "in" and restore it
86		BPoint nextIn = fNextIn;
87		fPath->GetPointInAt(fIndex, fNextIn);
88		fPath->SetPointIn(fIndex, nextIn);
89		// restore previous selection
90		_Select(fOldSelection, fOldSelectionCount);
91	} else {
92		status = B_ERROR;
93	}
94
95	return status;
96}
97
98// Redo
99status_t
100InsertPointCommand::Redo()
101{
102	status_t status = InitCheck();
103	if (status < B_OK)
104		return status;
105
106
107	AutoNotificationSuspender _(fPath);
108
109	// insert point again
110	if (fPath->AddPoint(fPoint, fIndex)) {
111		fPath->SetPoint(fIndex, fPoint, fPointIn, fPointOut, true);
112		// remember current previous "out" and restore it
113		BPoint previousOut = fPreviousOut;
114		fPath->GetPointOutAt(fIndex - 1, fPreviousOut);
115		fPath->SetPointOut(fIndex - 1, previousOut);
116		// remember current next "in" and restore it
117		BPoint nextIn = fNextIn;
118		fPath->GetPointInAt(fIndex + 1, fNextIn);
119		fPath->SetPointIn(fIndex + 1, nextIn);
120		// select inserted point
121		_Select(&fIndex, 1);
122	} else {
123		status = B_ERROR;
124	}
125
126	return status;
127}
128
129// GetName
130void
131InsertPointCommand::GetName(BString& name)
132{
133	name << B_TRANSLATE("Insert vertex");
134}
135
136