Subversion Repositories Scribus

Rev

Rev 18007 | Rev 18194 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
12868 fschmid 1
/*
2
For general Scribus (>=1.3.2) copyright and licensing information please refer
3
to the COPYING file provided with the program. Following this notice may exist
4
a copyright and/or license notice that predates the release of Scribus 1.3.2
5
for which a new license (GPL+exception) is in place.
6
*/
7
/***************************************************************************
8
*   Copyright (C) 2008 by Franz Schmid                                     *
9
*   franz.schmid@altmuehlnet.de                                            *
10
*                                                                          *
11
*   This program is free software; you can redistribute it and/or modify   *
12
*   it under the terms of the GNU General Public License as published by   *
13
*   the Free Software Foundation; either version 2 of the License, or      *
14
*   (at your option) any later version.                                    *
15
*                                                                          *
16
*   This program is distributed in the hope that it will be useful,        *
17
*   but WITHOUT ANY WARRANTY; without even the implied warranty of         *
18
*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
19
*   GNU General Public License for more details.                           *
20
*                                                                          *
21
*   You should have received a copy of the GNU General Public License      *
22
*   along with this program; if not, write to the                          *
23
*   Free Software Foundation, Inc.,                                        *
18122 mrdocs 24
*   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.              *
12868 fschmid 25
****************************************************************************/
26
 
27
#include "pathconnect.h"
28
#include "pathconnectdialog.h"
13805 jghali 29
#include "selection.h"
30
#include "scribusdoc.h"
17735 craig 31
#include "undomanager.h"
12868 fschmid 32
 
33
int pathconnect_getPluginAPIVersion()
34
{
35
        return PLUGIN_API_VERSION;
36
}
37
 
38
ScPlugin* pathconnect_getPlugin()
39
{
40
        PathConnectPlugin* plug = new PathConnectPlugin();
41
        Q_CHECK_PTR(plug);
42
        return plug;
43
}
44
 
45
void pathconnect_freePlugin(ScPlugin* plugin)
46
{
47
        PathConnectPlugin* plug = dynamic_cast<PathConnectPlugin*>(plugin);
48
        Q_ASSERT(plug);
49
        delete plug;
50
}
51
 
52
PathConnectPlugin::PathConnectPlugin() : ScActionPlugin()
53
{
54
        // Set action info in languageChange, so we only have to do
55
        // it in one place.
56
        languageChange();
57
}
58
 
17747 craig 59
PathConnectPlugin::~PathConnectPlugin() {}
12868 fschmid 60
 
61
void PathConnectPlugin::languageChange()
62
{
63
        // Note that we leave the unused members unset. They'll be initialised
64
        // with their default ctors during construction.
65
        // Action name
66
        m_actionInfo.name = "PathConnect";
67
        // Action text for menu, including accel
68
        m_actionInfo.text = tr("Connect Paths");
15675 fschmid 69
        m_actionInfo.helpText = tr("Connects two Paths.");
12868 fschmid 70
        // Menu
71
        m_actionInfo.menu = "ItemPathOps";
72
        m_actionInfo.parentMenu = "Item";
73
        m_actionInfo.subMenuName = tr("Path Tools");
74
        m_actionInfo.enabledOnStartup = false;
75
        m_actionInfo.notSuitableFor.append(PageItem::Line);
76
        m_actionInfo.notSuitableFor.append(PageItem::TextFrame);
77
        m_actionInfo.notSuitableFor.append(PageItem::ImageFrame);
78
        m_actionInfo.notSuitableFor.append(PageItem::Polygon);
79
        m_actionInfo.notSuitableFor.append(PageItem::PathText);
80
        m_actionInfo.notSuitableFor.append(PageItem::LatexFrame);
15060 fschmid 81
        m_actionInfo.notSuitableFor.append(PageItem::Symbol);
16191 fschmid 82
        m_actionInfo.notSuitableFor.append(PageItem::RegularPolygon);
16311 fschmid 83
        m_actionInfo.notSuitableFor.append(PageItem::Spiral);
16215 fschmid 84
        m_actionInfo.notSuitableFor.append(PageItem::Arc);
12868 fschmid 85
        m_actionInfo.needsNumObjects = 2;
86
}
87
 
88
const QString PathConnectPlugin::fullTrName() const
89
{
90
        return QObject::tr("PathConnect");
91
}
92
 
93
const ScActionPlugin::AboutData* PathConnectPlugin::getAboutData() const
94
{
95
        AboutData* about = new AboutData;
96
        Q_CHECK_PTR(about);
97
        about->authors = QString::fromUtf8("Franz Schmid <Franz.Schmid@altmuehlnet.de>");
98
        about->shortDescription = tr("Connect Paths");
99
        about->description = tr("Connect 2 Polylines.");
100
        // about->version
101
        // about->releaseDate
102
        // about->copyright
103
        about->license = "GPL";
104
        return about;
105
}
106
 
107
void PathConnectPlugin::deleteAboutData(const AboutData* about) const
108
{
109
        Q_ASSERT(about);
110
        delete about;
111
}
112
 
113
bool PathConnectPlugin::run(ScribusDoc* doc, QString)
114
{
115
        currDoc = doc;
116
        firstUpdate = true;
117
        if (currDoc == 0)
118
                currDoc = ScCore->primaryMainWindow()->doc;
119
        if (currDoc->m_Selection->count() > 1)
120
        {
121
                Item1 = currDoc->m_Selection->itemAt(0);
122
                Item2 = currDoc->m_Selection->itemAt(1);
123
                originalPath1 = Item1->PoLine.copy();
124
                originalPath2 = Item2->PoLine.copy();
125
                originalXPos = Item1->xPos();
126
                originalYPos = Item1->yPos();
127
                PathConnectDialog *dia = new PathConnectDialog(currDoc->scMW());
128
                connect(dia, SIGNAL(updateValues(int, int, int, int)), this, SLOT(updateEffect(int, int, int, int)));
129
                if (dia->exec())
130
                {
131
                        int pointOne = dia->getFirstLinePoint();
132
                        int pointTwo = dia->getSecondLinePoint();
133
                        int mode = dia->getMode();
17747 craig 134
                        UndoTransaction *trans = NULL;
135
                        if(UndoManager::undoEnabled())
136
                                trans = new UndoTransaction(UndoManager::instance()->beginTransaction(Um::BezierCurve,Um::ILine,Um::ConnectPath,"",Um::ILine));
137
 
12868 fschmid 138
                        Item1->PoLine = computePath(pointOne, pointTwo, mode, originalPath1, originalPath2);
139
                        Item1->ClipEdited = true;
140
                        Item1->FrameType = 3;
141
                        currDoc->AdjustItemSize(Item1);
142
                        Item1->OldB2 = Item1->width();
143
                        Item1->OldH2 = Item1->height();
17747 craig 144
                        if(UndoManager::undoEnabled())
145
                        {
146
                                ScItemState<QPair<FPointArray,FPointArray> > *is = new ScItemState<QPair<FPointArray,FPointArray> >(Um::ConnectPath);
147
                                is->set("CONNECT_PATH","connect_path");
148
                                is->set("OLDX",originalXPos);
149
                                is->set("OLDY",originalYPos);
150
                                is->set("NEWX",Item1->xPos());
151
                                is->set("NEWY",Item1->yPos());
152
                                is->setItem(qMakePair(originalPath1,Item1->PoLine));
153
                                UndoManager::instance()->action(Item1,is);
154
                        }
12868 fschmid 155
                        Item1->updateClip();
156
                        Item1->ContourLine = Item1->PoLine.copy();
157
                        currDoc->m_Selection->removeItem(Item1);
158
                        currDoc->itemSelection_DeleteItem();
159
                        currDoc->changed();
17747 craig 160
                        if(trans)
161
                        {
162
                                trans->commit();
163
                                delete trans;
164
                                trans = NULL;
165
                        }
12868 fschmid 166
                }
167
                else
168
                {
169
                        Item1->PoLine = originalPath1.copy();
170
                        Item1->ClipEdited = true;
171
                        Item1->FrameType = 3;
172
                        Item1->setXYPos(originalXPos, originalYPos);
173
                        currDoc->AdjustItemSize(Item1);
174
                        Item1->OldB2 = Item1->width();
175
                        Item1->OldH2 = Item1->height();
176
                        Item1->updateClip();
177
                        Item1->ContourLine = Item1->PoLine.copy();
178
                }
179
                currDoc->view()->DrawNew();
180
                delete dia;
181
        }
182
        return true;
183
}
184
 
185
void PathConnectPlugin::updateEffect(int effectType, int pointOne, int pointTwo, int mode)
186
{
187
        if (effectType == -1)
188
        {
189
                Item1->PoLine = originalPath1.copy();
190
                Item1->ClipEdited = true;
191
                Item1->FrameType = 3;
192
                Item1->setXYPos(originalXPos, originalYPos);
193
                firstUpdate = true;
194
        }
195
        else
196
        {
197
                Item1->setXYPos(originalXPos, originalYPos);
198
                Item1->PoLine = computePath(pointOne, pointTwo, mode, originalPath1, originalPath2);
199
                Item1->ClipEdited = true;
200
                Item1->FrameType = 3;
201
        }
202
        currDoc->AdjustItemSize(Item1);
203
        Item1->OldB2 = Item1->width();
204
        Item1->OldH2 = Item1->height();
205
        Item1->updateClip();
206
        if (firstUpdate)
207
                currDoc->view()->DrawNew();
208
        else
209
        {
210
                QRectF oldR(Item1->getBoundingRect());
211
                QRectF newR(Item2->getBoundingRect());
212
                currDoc->regionsChanged()->update(newR.unite(oldR));
213
        }
214
        if (effectType != -1)
215
                firstUpdate = false;
216
}
217
 
218
FPointArray PathConnectPlugin::computePath(int pointOne, int pointTwo, int mode, FPointArray &p1, FPointArray &p2)
219
{
220
        FPointArray result;
221
        FPointArray path1 = p1.copy();
222
        FPointArray path2 = p2.copy();
13951 fschmid 223
        QTransform ma;
12868 fschmid 224
        ma.translate(Item2->xPos(), Item2->yPos());
225
        ma.rotate(Item2->rotation());
226
        path2.map(ma);
13951 fschmid 227
        QTransform ma2;
12868 fschmid 228
        ma2.translate(originalXPos, originalYPos);
229
        ma2.rotate(Item1->rotation());
230
        ma2 = ma2.inverted();
231
        path2.map(ma2);
232
        FPoint startL1 = path1.point(0);
233
        FPoint startL2 = path2.point(0);
234
        FPoint endL1 = path1.point(path1.size() - 2);
235
        FPoint endL2 = path2.point(path2.size() - 2);
236
        if (pointOne == 0)
237
        {
238
                if (pointTwo == 0)
239
                {
240
                        path2 = reversePath(path2);
241
                        if (mode == 0)
242
                                path2.addQuadPoint(startL2, startL2, startL1, startL1);
243
                        else
244
                        {
245
                                FPoint midP = (startL2 + startL1) * 0.5;
246
                                FPoint corr1 = path1.point(1) + (midP - startL1);
247
                                FPoint corr2 = path2.point(path2.size() - 1) + (midP - startL2);
248
                                path1.setPoint(1, corr1);
249
                                path2.setPoint(path2.size() - 1, corr2);
250
                                path2.setPoint(path2.size() - 2, midP);
251
                                path1.setPoint(0, midP);
252
                        }
253
                        path2.putPoints(path2.size(), path1.size(), path1);
254
                        result = path2.copy();
255
                }
256
                else if (pointTwo == 1)
257
                {
258
                        if (mode == 0)
259
                                path2.addQuadPoint(endL2, endL2, startL1, startL1);
260
                        else
261
                        {
262
                                FPoint midP = (startL1 + endL2) * 0.5;
263
                                FPoint corr1 = path1.point(1) + (midP - startL1);
264
                                FPoint corr2 = path2.point(path2.size() - 1) + (midP - endL2);
265
                                path1.setPoint(1, corr1);
266
                                path2.setPoint(path2.size() - 1, corr2);
267
                                path2.setPoint(path2.size() - 2, midP);
268
                                path1.setPoint(0, midP);
269
                        }
270
                        path2.putPoints(path2.size(), path1.size(), path1);
271
                        result = path2.copy();
272
                }
273
        }
274
        else if (pointOne == 1)
275
        {
276
                if (pointTwo == 0)
277
                {
278
                        if (mode == 0)
279
                                path1.addQuadPoint(endL1, endL1, startL2, startL2);
280
                        else
281
                        {
282
                                FPoint midP = (startL2 + endL1) * 0.5;
283
                                FPoint corr1 = path1.point(path1.size() - 1) + (midP - endL1);
284
                                FPoint corr2 = path2.point(1) + (midP - startL2);
285
                                path1.setPoint(path1.size() - 1, corr1);
286
                                path2.setPoint(1, corr2);
287
                                path1.setPoint(path1.size() - 2, midP);
288
                                path2.setPoint(0, midP);
289
                        }
290
                        path1.putPoints(path1.size(), path2.size(), path2);
291
                        result = path1.copy();
292
                }
293
                else if (pointTwo == 1)
294
                {
295
                        path2 = reversePath(path2);
296
                        if (mode == 0)
297
                                path1.addQuadPoint(endL1, endL1, endL2, endL2);
298
                        else
299
                        {
300
                                FPoint midP = (endL2 + endL1) * 0.5;
301
                                FPoint corr1 = path1.point(path1.size() - 1) + (midP - endL1);
302
                                FPoint corr2 = path2.point(1) + (midP - endL2);
303
                                path1.setPoint(path1.size() - 1, corr1);
304
                                path2.setPoint(1, corr2);
305
                                path1.setPoint(path1.size() - 2, midP);
306
                                path2.setPoint(0, midP);
307
                        }
308
                        path1.putPoints(path1.size(), path2.size(), path2);
309
                        result = path1.copy();
310
                }
311
        }
312
        return result;
313
}
314
 
315
FPointArray PathConnectPlugin::reversePath(FPointArray &path)
316
{
317
        FPointArray result;
318
        for (int a = path.size()-4; a > -1; a -= 4)
319
        {
320
                FPoint p1 = path.point(a);
321
                FPoint p2 = path.point(a+1);
322
                FPoint p3 = path.point(a+2);
323
                FPoint p4 = path.point(a+3);
324
                result.addQuadPoint(p3, p4, p1, p2);
325
        }
326
        return result;
327
}