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 	begin                : June 2005
9 	copyright            : (C) 2005 by Craig Bradney
10 	email                : cbradney@zip.com.au
11 ***************************************************************************/
12 
13 /***************************************************************************
14 *                                                                         *
15 *   Scribus program is free software; you can redistribute it and/or modify  *
16 *   it under the terms of the GNU General Public License as published by  *
17 *   the Free Software Foundation; either version 2 of the License, or     *
18 *   (at your option) any later version.                                   *
19 *                                                                         *
20 ***************************************************************************/
21 
22 #include "aligndistribute.h"
23 
24 #include <QComboBox>
25 #include <QEvent>
26 #include <QImage>
27 #include <QLabel>
28 #include <QLayout>
29 #include <QLineEdit>
30 #include <QLocale>
31 #include <QMessageBox>
32 #include <QPixmap>
33 #include <QPushButton>
34 #include <QTabWidget>
35 #include <QToolButton>
36 #include <QToolTip>
37 #include <QVariant>
38 
39 #include "commonstrings.h"
40 #include "iconmanager.h"
41 #include "localemgr.h"
42 #include "scpage.h"
43 #include "scribusapp.h"
44 #include "scribusdoc.h"
45 #include "scribusstructs.h"
46 #include "selection.h"
47 #include "ui/scrspinbox.h"
48 #include "undomanager.h"
49 #include "units.h"
50 
51 //TODO Distribute with
52 
AlignDistributePalette(QWidget * parent,const char * name)53 AlignDistributePalette::AlignDistributePalette( QWidget* parent, const char* name) : ScDockPalette(parent, name, Qt::WindowFlags())
54 {
55 	setupUi(this);
56 	setSizePolicy( QSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum));
57 	setObjectName(name);
58 
59 	//set up scrspinboxes
60 	distributeDistSpinBox->setValues(-10000.0, 10000.0, 2, 0.0);
61 
62 	resize( QSize(100, 100).expandedTo(minimumSizeHint()) );
63 	languageChange();
64 	init();
65 	setDoc(nullptr);
66 
67 	connect(ScQApp, SIGNAL(iconSetChanged()), this, SLOT(iconSetChange()));
68 	connect(ScQApp, SIGNAL(localeChanged()), this, SLOT(localeChange()));
69 }
70 
~AlignDistributePalette()71 AlignDistributePalette::~AlignDistributePalette()
72 {
73 }
74 
changeEvent(QEvent * e)75 void AlignDistributePalette::changeEvent(QEvent *e)
76 {
77 	if (e->type() == QEvent::LanguageChange)
78 	{
79 		languageChange();
80 		return;
81 	}
82 	ScDockPalette::changeEvent(e);
83 }
84 
languageChange()85 void AlignDistributePalette::languageChange()
86 {
87 	retranslateUi(this);
88 
89 	int alignComboValue=alignRelativeToCombo->currentIndex();
90 	alignRelativeToCombo->clear();
91 	alignRelativeToCombo->addItem( tr( "First Selected" ) );
92 	alignRelativeToCombo->addItem( tr( "Last Selected" ) );
93 	alignRelativeToCombo->addItem( tr( "Page" ) );
94 	alignRelativeToCombo->addItem( tr( "Margins" ) );
95 	alignRelativeToCombo->addItem( tr( "Guide" ) );
96 	alignRelativeToCombo->addItem( tr( "Selection" ) );
97 	alignRelativeToCombo->setCurrentIndex(alignComboValue);
98 	alignRelativeToCombo->setToolTip( tr( "<qt>Align relative to the:<ul><li>First selected item</li><li>Second Selected Item</li><li>The current page</li><li>The margins of the current page</li><li>A Guide</li><li>The selection</ul></qt>" ) );
99 	alignToChanged(alignComboValue);
100 
101 	int alignMethodValue=alignMoveOrResizeCombo->currentIndex();
102 	alignMoveOrResizeCombo->clear();
103 	alignMoveOrResizeCombo->addItem( tr("Move") );
104 	alignMoveOrResizeCombo->addItem( tr("Resize") );
105 	alignMoveOrResizeCombo->setToolTip( tr( "<qt>When aligning one side of an item do one of the following:<ul><li>Always move the other side too (preserve existing width and height)</li><li>Keep the other side fixed (resize the item instead of moving it) whenever possible</li></ul></qt>" ));
106 	alignMethodChanged(alignMethodValue);
107 
108 	alignGuideLineEdit->setToolTip( tr( "The location of the selected guide to align to" ) );
109 	alignLeftOutToolButton->setToolTip( tr( "Align right sides of items to left side of anchor" ) );
110 	alignRightOutToolButton->setToolTip( tr( "Align left sides of items to right side of anchor" ) );
111 	alignBottomInToolButton->setToolTip( tr( "Align bottoms" ) );
112 	alignRightInToolButton->setToolTip( tr( "Align right sides" ) );
113 	alignBottomOutToolButton->setToolTip( tr( "Align tops of items to bottom of anchor" ) );
114 	alignCenterHorToolButton->setToolTip( tr( "Center on vertical axis" ) );
115 	alignLeftInToolButton->setToolTip( tr( "Align left sides" ) );
116 	alignCenterVerToolButton->setToolTip( tr( "Center on horizontal axis" ) );
117 	alignTopOutToolButton->setToolTip( tr( "Align bottoms of items to top of anchor" ) );
118 	alignTopInToolButton->setToolTip( tr( "Align tops" ) );
119 
120 	distributeDistHToolButton->setToolTip( tr( "Make horizontal gaps between items equal" ) );
121 	distributeDistValueHToolButton->setToolTip( tr( "Make horizontal gaps between items equal to the value specified" ) );
122 
123 	distributeRightToolButton->setToolTip( tr( "Distribute right sides equidistantly" ) );
124 	distributeBottomToolButton->setToolTip( tr( "Distribute bottoms equidistantly" ) );
125 	distributeCenterHToolButton->setToolTip( tr( "Distribute centers equidistantly horizontally" ) );
126 	distributeDistVToolButton->setToolTip( tr( "Make vertical gaps between items equal" ) );
127 	distributeDistValueVToolButton->setToolTip( tr( "Make vertical gaps between items equal to the value specified" ) );
128 	distributeLeftToolButton->setToolTip( tr( "Distribute left sides equidistantly" ) );
129 	distributeCenterVToolButton->setToolTip( tr( "Distribute centers equidistantly vertically" ) );
130 	distributeTopToolButton->setToolTip( tr( "Distribute tops equidistantly" ) );
131 	distributeAcrossPageToolButton->setToolTip( tr( "Make horizontal gaps between items and sides of page equal" ) );
132 	distributeDownPageToolButton->setToolTip( tr( "Make vertical gaps between items and the top and bottom of page equal" ) );
133 	distributeAcrossMarginsToolButton->setToolTip( tr( "Make horizontal gaps between items and sides of page margins equal" ) );
134 	distributeDownMarginsToolButton->setToolTip( tr( "Make vertical gaps between items and the top and bottom of page margins equal" ) );
135 
136 	distributeDistSpinBox->setToolTip( tr( "Distribute the items with the distance specified" ) );
137 	reverseDistributionCheckBox->setToolTip( tr("When distributing by a set distance, reverse the direction of the distribution of items") );
138 
139 	guideInfoTextNone = tr("None Selected");
140 
141 	swapLeftToolButton->setToolTip( tr( "Swap items to the left" ) );
142 	swapRightToolButton->setToolTip( tr( "Swap items to the right" ) );
143 }
144 
init()145 void AlignDistributePalette::init()
146 {
147 	undoManager = UndoManager::instance();
148 
149 	iconSetChange();
150 
151 	connect(alignLeftOutToolButton, SIGNAL(clicked()), this, SLOT(alignLeftOut()));
152 	connect(alignRightOutToolButton, SIGNAL(clicked()), this, SLOT(alignRightOut()));
153 	connect(alignBottomInToolButton, SIGNAL(clicked()), this, SLOT(alignBottomIn()));
154 	connect(alignRightInToolButton, SIGNAL(clicked()), this, SLOT(alignRightIn()));
155 	connect(alignBottomOutToolButton, SIGNAL(clicked()), this, SLOT(alignBottomOut()));
156 	connect(alignCenterHorToolButton, SIGNAL(clicked()), this, SLOT(alignCenterHor()));
157 	connect(alignLeftInToolButton, SIGNAL(clicked()), this, SLOT(alignLeftIn()));
158 	connect(alignCenterVerToolButton, SIGNAL(clicked()), this, SLOT(alignCenterVer()));
159 	connect(alignTopOutToolButton, SIGNAL(clicked()), this, SLOT(alignTopOut()));
160 	connect(alignTopInToolButton, SIGNAL(clicked()), this, SLOT(alignTopIn()));
161 	connect(distributeDistHToolButton, SIGNAL(clicked()), this, SLOT(distributeDistH()));
162 	connect(distributeDistValueHToolButton, SIGNAL(clicked()), this, SLOT(distributeDistValH()));
163 	connect(distributeRightToolButton, SIGNAL(clicked()), this, SLOT(distributeRight()));
164 	connect(distributeBottomToolButton, SIGNAL(clicked()), this, SLOT(distributeBottom()));
165 	connect(distributeCenterHToolButton, SIGNAL(clicked()), this, SLOT(distributeCenterH()));
166 	connect(distributeDistVToolButton, SIGNAL(clicked()), this, SLOT(distributeDistV()));
167 	connect(distributeDistValueVToolButton, SIGNAL(clicked()), this, SLOT(distributeDistValV()));
168 	connect(distributeLeftToolButton, SIGNAL(clicked()), this, SLOT(distributeLeft()));
169 	connect(distributeCenterVToolButton, SIGNAL(clicked()), this, SLOT(distributeCenterV()));
170 	connect(distributeTopToolButton, SIGNAL(clicked()), this, SLOT(distributeTop()));
171 	connect(distributeAcrossPageToolButton, SIGNAL(clicked()), this, SLOT(distributeDistAcrossPage()));
172 	connect(distributeDownPageToolButton, SIGNAL(clicked()), this, SLOT(distributeDistDownPage()));
173 	connect(distributeAcrossMarginsToolButton, SIGNAL(clicked()), this, SLOT(distributeDistAcrossMargins()));
174 	connect(distributeDownMarginsToolButton, SIGNAL(clicked()), this, SLOT(distributeDistDownMargins()));
175 	connect(swapLeftToolButton, SIGNAL(clicked()), this, SLOT(swapLeft()));
176 	connect(swapRightToolButton, SIGNAL(clicked()), this, SLOT(swapRight()));
177 
178 	alignRelativeToCombo->setCurrentIndex(0);
179 	alignToChanged(0);
180 	alignMethodChanged(0);
181 	connect(alignRelativeToCombo, SIGNAL(activated(int)), this, SLOT(alignToChanged(int)));
182 	connect(alignMoveOrResizeCombo, SIGNAL(activated(int)), this, SLOT(alignMethodChanged(int)));
183 
184 	unitRatio = 1.0;
185 	guideDirection = -1;
186 
187 	guideInfoText = guideInfoTextNone;
188 	alignGuideLineEdit->setText(guideInfoTextNone);
189 }
190 
iconSetChange()191 void AlignDistributePalette::iconSetChange()
192 {
193 	IconManager& im = IconManager::instance();
194 
195 	alignLeftOutToolButton->setIcon(im.loadIcon("22/align-horizontal-left-out.png"));
196 	alignLeftInToolButton->setIcon(im.loadIcon("22/align-horizontal-left.png"));
197 	alignCenterHorToolButton->setIcon(im.loadIcon("22/align-horizontal-center.png"));
198 	alignRightInToolButton->setIcon(im.loadIcon("22/align-horizontal-right.png"));
199 	alignRightOutToolButton->setIcon(im.loadIcon("22/align-horizontal-right-out.png"));
200 
201 	alignTopOutToolButton->setIcon(im.loadIcon("22/align-vertical-top-out.png"));
202 	alignTopInToolButton->setIcon(im.loadIcon("22/align-vertical-top.png"));
203 	alignCenterVerToolButton->setIcon(im.loadIcon("22/align-vertical-center.png"));
204 	alignBottomInToolButton->setIcon(im.loadIcon("22/align-vertical-bottom.png"));
205 	alignBottomOutToolButton->setIcon(im.loadIcon("22/align-vertical-bottom-out.png"));
206 
207 	distributeLeftToolButton->setIcon(im.loadIcon("22/distribute-horizontal-left.png"));
208 	distributeCenterHToolButton->setIcon(im.loadIcon("22/distribute-horizontal-center.png"));
209 	distributeRightToolButton->setIcon(im.loadIcon("22/distribute-horizontal-right.png"));
210 	distributeDistHToolButton->setIcon(im.loadIcon("22/distribute-horizontal-equal.png"));
211 
212 	distributeBottomToolButton->setIcon(im.loadIcon("22/distribute-vertical-bottom.png"));
213 	distributeCenterVToolButton->setIcon(im.loadIcon("22/distribute-vertical-center.png"));
214 	distributeTopToolButton->setIcon(im.loadIcon("22/distribute-vertical-top.png"));
215 	distributeDistVToolButton->setIcon(im.loadIcon("22/distribute-vertical-equal.png"));
216 
217 	distributeAcrossPageToolButton->setIcon(im.loadIcon("22/distribute-horizontal-page.png"));
218 	distributeDownPageToolButton->setIcon(im.loadIcon("22/distribute-vertical-page.png"));
219 	distributeAcrossMarginsToolButton->setIcon(im.loadIcon("22/distribute-horizontal-margin.png"));
220 	distributeDownMarginsToolButton->setIcon(im.loadIcon("22/distribute-vertical-margin.png"));
221 	distributeDistValueHToolButton->setIcon(im.loadIcon("22/distribute-horizontal-x.png"));
222 	distributeDistValueVToolButton->setIcon(im.loadIcon("22/distribute-vertical-y.png"));
223 
224 	swapLeftToolButton->setIcon(im.loadIcon("22/swap-left.png"));
225 	swapRightToolButton->setIcon(im.loadIcon("22/swap-right.png"));
226 }
227 
unitChange()228 void AlignDistributePalette::unitChange()
229 {
230 	if (currDoc != nullptr)
231 	{
232 		unitRatio = unitGetRatioFromIndex(currDoc->unitIndex());
233 		distributeDistSpinBox->setNewUnit(currDoc->unitIndex());
234 		enableGuideButtons();
235 	}
236 }
237 
setDoc(ScribusDoc * newDoc)238 void AlignDistributePalette::setDoc(ScribusDoc* newDoc)
239 {
240 	currDoc = newDoc;
241 	if (currDoc != nullptr)
242 		alignObjects = &(currDoc->AObjects);
243 	else
244 		alignObjects = nullptr;
245 	unitChange();
246 }
247 
alignLeftOut()248 void AlignDistributePalette::alignLeftOut()
249 {
250 	if (currDoc != nullptr)
251 		currDoc->itemSelection_AlignLeftOut(currAlignTo, currAlignMethod, guidePosition);
252 }
253 
alignLeftIn()254 void AlignDistributePalette::alignLeftIn()
255 {
256 	if (currDoc != nullptr)
257 		currDoc->itemSelection_AlignLeftIn(currAlignTo, currAlignMethod, guidePosition);
258 }
259 
alignCenterHor()260 void AlignDistributePalette::alignCenterHor()
261 {
262 	if (currDoc != nullptr)
263 		currDoc->itemSelection_AlignCenterHor(currAlignTo, currAlignMethod, guidePosition);
264 }
265 
alignRightIn()266 void AlignDistributePalette::alignRightIn()
267 {
268 	if (currDoc != nullptr)
269 		currDoc->itemSelection_AlignRightIn(currAlignTo, currAlignMethod, guidePosition);
270 }
271 
alignRightOut()272 void AlignDistributePalette::alignRightOut()
273 {
274 	if (currDoc != nullptr)
275 		currDoc->itemSelection_AlignRightOut(currAlignTo, currAlignMethod, guidePosition);
276 }
277 
alignTopOut()278 void AlignDistributePalette::alignTopOut()
279 {
280 	if (currDoc != nullptr)
281 		currDoc->itemSelection_AlignTopOut(currAlignTo, currAlignMethod, guidePosition);
282 }
283 
alignTopIn()284 void AlignDistributePalette::alignTopIn()
285 {
286 	if (currDoc != nullptr)
287 		currDoc->itemSelection_AlignTopIn(currAlignTo, currAlignMethod, guidePosition);
288 }
289 
290 
alignCenterVer()291 void AlignDistributePalette::alignCenterVer()
292 {
293 	if (currDoc != nullptr)
294 		currDoc->itemSelection_AlignCenterVer(currAlignTo, currAlignMethod, guidePosition);
295 }
296 
297 
alignBottomIn()298 void AlignDistributePalette::alignBottomIn()
299 {
300 	if (currDoc != nullptr)
301 		currDoc->itemSelection_AlignBottomIn(currAlignTo, currAlignMethod, guidePosition);
302 }
303 
alignBottomOut()304 void AlignDistributePalette::alignBottomOut()
305 {
306 	if (currDoc != nullptr)
307 		currDoc->itemSelection_AlignBottomOut(currAlignTo, currAlignMethod, guidePosition);
308 }
309 
distributeLeft()310 void AlignDistributePalette::distributeLeft()
311 {
312 	if (currDoc != nullptr)
313 		currDoc->itemSelection_DistributeLeft();
314 }
315 
distributeCenterH()316 void AlignDistributePalette::distributeCenterH()
317 {
318 	if (currDoc != nullptr)
319 		currDoc->itemSelection_DistributeCenterH();
320 }
321 
distributeRight()322 void AlignDistributePalette::distributeRight()
323 {
324 	if (currDoc != nullptr)
325 		currDoc->itemSelection_DistributeRight();
326 }
327 
distributeDistH(bool usingDistance)328 void AlignDistributePalette::distributeDistH(bool usingDistance)
329 {
330 	if (currDoc != nullptr)
331 		currDoc->itemSelection_DistributeDistH(usingDistance, distributeDistSpinBox->value(), reverseDistributionCheckBox->isChecked());
332 }
333 
distributeDistValH()334 void AlignDistributePalette::distributeDistValH()
335 {
336 	distributeDistSpinBox->interpretText();
337 	if (currDoc != nullptr)
338 		distributeDistH(true);
339 }
340 
distributeDistAcrossPage()341 void AlignDistributePalette::distributeDistAcrossPage()
342 {
343 	if (currDoc != nullptr)
344 		currDoc->itemSelection_DistributeAcrossPage();
345 }
346 
distributeDistDownPage()347 void AlignDistributePalette::distributeDistDownPage()
348 {
349 	if (currDoc != nullptr)
350 		currDoc->itemSelection_DistributeDownPage();
351 }
352 
distributeDistAcrossMargins()353 void AlignDistributePalette::distributeDistAcrossMargins()
354 {
355 	if (currDoc != nullptr)
356 		currDoc->itemSelection_DistributeAcrossPage(true);
357 }
358 
distributeDistDownMargins()359 void AlignDistributePalette::distributeDistDownMargins()
360 {
361 	if (currDoc != nullptr)
362 		currDoc->itemSelection_DistributeDownPage(true);
363 }
364 
365 
distributeBottom()366 void AlignDistributePalette::distributeBottom()
367 {
368 	if (currDoc != nullptr)
369 		currDoc->itemSelection_DistributeBottom();
370 }
371 
distributeCenterV()372 void AlignDistributePalette::distributeCenterV()
373 {
374 	if (currDoc != nullptr)
375 		currDoc->itemSelection_DistributeCenterV();
376 }
377 
distributeTop()378 void AlignDistributePalette::distributeTop()
379 {
380 	if (currDoc != nullptr)
381 		currDoc->itemSelection_DistributeTop();
382 }
383 
distributeDistV(bool usingDistance)384 void AlignDistributePalette::distributeDistV(bool usingDistance)
385 {
386 	if (currDoc != nullptr)
387 		currDoc->itemSelection_DistributeDistV(usingDistance, distributeDistSpinBox->value(), reverseDistributionCheckBox->isChecked());
388 }
389 
distributeDistValV()390 void AlignDistributePalette::distributeDistValV()
391 {
392 	distributeDistSpinBox->interpretText();
393 	if (currDoc != nullptr)
394 		distributeDistV(true);
395 }
396 
swapLeft()397 void AlignDistributePalette::swapLeft()
398 {
399 	if (currDoc != nullptr)
400 		currDoc->itemSelection_SwapLeft();
401 }
402 
swapRight()403 void AlignDistributePalette::swapRight()
404 {
405 	if (currDoc != nullptr)
406 		currDoc->itemSelection_SwapRight();
407 }
408 
alignToChanged(int newAlignTo)409 void AlignDistributePalette::alignToChanged(int newAlignTo)
410 {
411 	currAlignTo = ScribusDoc::AlignTo(newAlignTo);
412 	enableGuideButtons();
413 }
alignMethodChanged(int newAlignMethod)414 void AlignDistributePalette::alignMethodChanged(int newAlignMethod)
415 {
416 	currAlignMethod = ScribusDoc::AlignMethod(newAlignMethod);
417 	enableGuideButtons();
418 }
419 
setGuide(int direction,qreal position)420 void AlignDistributePalette::setGuide(int direction, qreal position)
421 {
422 	//direction 0=H, 1=V
423 // 	qDebug()<<"AlignDistributePalette::setGuide("<<direction<<""<<position<<")";
424 	guideDirection = direction;
425 	guidePosition = position;
426 	enableGuideButtons();
427 }
428 
429 
localeChange()430 void AlignDistributePalette::localeChange()
431 {
432 	const QLocale& l(LocaleManager::instance().userPreferredLocale());
433 	distributeDistSpinBox->setLocale(l);
434 }
435 
enableGuideButtons()436 void AlignDistributePalette::enableGuideButtons()
437 {
438 	QString suffix;
439 	double unitRatio = 1.0;
440 	int precision = 1;
441 	if (currDoc != nullptr)
442 	{
443 		suffix = unitGetSuffixFromIndex(currDoc->unitIndex());
444 		unitRatio = unitGetRatioFromIndex(currDoc->unitIndex());
445 		precision = unitGetPrecisionFromIndex(currDoc->unitIndex());
446 	}
447 	bool setterH = true, setterV = true;
448 	switch (guideDirection)
449 	{
450 		case -1:
451 			guideInfoText = guideInfoTextNone;
452 			if (currAlignTo == ScribusDoc::alignGuide)
453 				setterH = setterV = false;
454 			break;
455 		case 0:
456 			guideInfoText = tr("Y: %1%2").arg(guidePosition * unitRatio, 0, 'f', precision).arg(suffix);
457 			if (currAlignTo == ScribusDoc::alignGuide)
458 			{
459 				setterV = false;
460 				setterH = true;
461 			}
462 			break;
463 		case 1:
464 			guideInfoText = tr("X: %1%2").arg(guidePosition * unitRatio, 0, 'f', precision).arg(suffix);
465 			if (currAlignTo == ScribusDoc::alignGuide)
466 			{
467 				setterV = true;
468 				setterH = false;
469 			}
470 			break;
471 	}
472 	bool setterO = true;
473 	if (currAlignTo == ScribusDoc::alignGuide)
474 		setterO = false;
475 
476 	alignLeftInToolButton->setEnabled(setterV);
477 	alignLeftOutToolButton->setEnabled(setterO);
478 	alignRightInToolButton->setEnabled(setterV);
479 	alignRightOutToolButton->setEnabled(setterO);
480 	alignCenterHorToolButton->setEnabled(setterV);
481 
482 	alignTopInToolButton->setEnabled(setterH);
483 	alignTopOutToolButton->setEnabled(setterO);
484 	alignBottomInToolButton->setEnabled(setterH);
485 	alignBottomOutToolButton->setEnabled(setterO);
486 	alignCenterVerToolButton->setEnabled(setterH);
487 
488 	alignGuideLineEdit->setText(guideInfoText);
489 }
490