1 /* AbiWord
2  * Copyright (C) 1998 AbiSource, Inc.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17  * 02110-1301 USA.
18  */
19 
20 #include <stdlib.h>
21 #include <stdio.h>
22 #include <string.h>
23 
24 #include "ap_Features.h"
25 
26 #include "ut_assert.h"
27 #include "ut_string.h"
28 #include "ut_debugmsg.h"
29 #include "fp_PageSize.h"
30 #include "gr_Painter.h"
31 
32 #include "xap_App.h"
33 #include "xap_Dialog_Id.h"
34 #include "xap_DialogFactory.h"
35 #include "xap_Dlg_MessageBox.h"
36 
37 #include "ap_Dialog_Columns.h"
38 
AP_Dialog_Columns(XAP_DialogFactory * pDlgFactory,XAP_Dialog_Id id)39 AP_Dialog_Columns::AP_Dialog_Columns(XAP_DialogFactory * pDlgFactory, XAP_Dialog_Id id)
40 	: XAP_Dialog_NonPersistent(pDlgFactory,id, "interface/dialogcolumns"),
41 	m_answer(a_OK),
42 	m_pColumnsPreview(NULL),
43 	m_previewDrawer(),
44 	m_iColumns(0),
45 	m_bLineBetween(false),
46 	m_iColumnOrder (0),
47 	m_HeightString("0.0in"),
48 	m_SpaceAfterString("0pt"),
49 	m_pDoc(NULL),
50 	m_pView (NULL),
51 	m_bSpaceAfterChanged(false),
52 	m_bMaxHeightChanged(false),
53 	m_dMarginTop(0.0),
54 	m_dMarginBottom(0.0),
55 	m_dMarginLeft(0.0),
56 	m_dMarginRight(0.0)
57 {
58 }
59 
~AP_Dialog_Columns(void)60 AP_Dialog_Columns::~AP_Dialog_Columns(void)
61 {
62 	DELETEP(m_pColumnsPreview);
63 }
64 
getAnswer(void) const65 AP_Dialog_Columns::tAnswer AP_Dialog_Columns::getAnswer(void) const
66 {
67 	return m_answer;
68 }
69 
_createPreviewFromGC(GR_Graphics * gc,UT_uint32 width,UT_uint32 height)70 void AP_Dialog_Columns::_createPreviewFromGC(GR_Graphics * gc,
71 										   UT_uint32 width,
72 										   UT_uint32 height)
73 {
74 	UT_return_if_fail (gc);
75 
76 	m_pColumnsPreview = new AP_Columns_preview(gc,this);
77 	UT_return_if_fail (m_pColumnsPreview);
78 
79 	m_pColumnsPreview->setWindowSize(width, height);
80 	m_pColumnsPreview->set(m_iColumns, m_bLineBetween);
81 
82 }
83 
setColumns(UT_uint32 iColumns)84 void AP_Dialog_Columns::setColumns(UT_uint32 iColumns)
85 {
86 	m_iColumns = iColumns;
87 
88 	if(m_pColumnsPreview)
89 		m_pColumnsPreview->set(m_iColumns, m_bLineBetween);
90 
91 	enableLineBetweenControl(m_iColumns != 1);
92 }
93 
setColumnOrder(UT_uint32 iOrder)94 void AP_Dialog_Columns::setColumnOrder(UT_uint32 iOrder)
95 {
96 	m_iColumnOrder = iOrder;
97 }
98 
99 /*!
100  * Returns the dimensioned string that defines the maximum height of the
101  * Column.
102 \returns const char * dimensioned string which is the max height of the column.
103 */
getHeightString(void)104 const char * AP_Dialog_Columns::getHeightString(void)
105 {
106 	return m_HeightString.c_str();
107 }
108 
109 /*!
110  * Returns the dimensioned string that defines the space between Columns.
111 \returns const char * dimensioned string which is the space between columns.
112 */
getSpaceAfterString(void)113 const char * AP_Dialog_Columns::getSpaceAfterString(void)
114 {
115 	return m_SpaceAfterString.c_str();
116 }
117 
118 /*!
119  * Returns the increment associated with the dimension defined in the string.
120 \param const char * sz the dimensioned string.
121 \returns double -  the increment associated with the dimension in sz
122 */
getIncrement(const char * sz)123 double AP_Dialog_Columns::getIncrement(const char * sz)
124 {
125 	double inc = 0.1;
126 	UT_Dimension dim =  UT_determineDimension(sz);
127 	if(dim == DIM_IN)
128 	{
129 		inc = 0.02;
130 	}
131 	else if(dim == DIM_CM)
132 	{
133 		inc = 0.1;
134 	}
135 	else if(dim == DIM_MM)
136 	{
137 		inc = 1.0;
138 	}
139 	else if(dim == DIM_PI)
140 	{
141 		inc = 1.0;
142 	}
143 	else if(dim == DIM_PT)
144 	{
145 		inc = 1.0;
146 	}
147 	else if(dim == DIM_PX)
148 	{
149 		inc = 1.0;
150 	}
151 	else
152 	{
153 		inc = 0.02;
154 	}
155 	return inc;
156 }
157 
158 /*!
159  * Sets pointer to the Current View and document. Also sets initial values
160  * for space-after and max column height.
161 \param XAP_Frame * pFrame - pointer to current Frame.
162 */
setViewAndDoc(XAP_Frame * pFrame)163 void AP_Dialog_Columns::setViewAndDoc(XAP_Frame * pFrame)
164 {
165 	gchar  pszAfter[25];
166 	gchar  pszMaxHeight[25];
167 
168 	m_pView = static_cast<FV_View *>(pFrame->getCurrentView());
169 	m_pDoc = m_pView->getDocument();
170 	const gchar ** pszSecProps = NULL;
171 	m_pView->getSectionFormat(&pszSecProps);
172 
173 	_convertToPreferredUnits( pFrame, static_cast<const gchar *>(UT_getAttribute("section-space-after",pszSecProps)), pszAfter);
174 	_convertToPreferredUnits( pFrame, static_cast<const gchar *>(UT_getAttribute("section-max-column-height",pszSecProps)), pszMaxHeight);
175 
176 	if(*pszAfter)
177 	{
178 		m_SpaceAfterString = static_cast<const char *>(pszAfter);
179 	}
180 	if(*pszMaxHeight)
181 	{
182 		UT_DEBUGMSG(("SEVIOR: Initial Height string = %s \n",pszMaxHeight));
183 		m_HeightString = pszMaxHeight;
184 	}
185 	const gchar * pszMarginTop = UT_getAttribute("page-margin-top",pszSecProps);
186 	const gchar * pszMarginBottom =  UT_getAttribute("page-margin-bottom",pszSecProps);
187 	const gchar * pszMarginLeft =  UT_getAttribute("page-margin-left",pszSecProps);
188 	const gchar * pszMarginRight =  UT_getAttribute("page-margin-right",pszSecProps);
189 	if(pszMarginTop && *pszMarginTop)
190 	{
191 		m_dMarginTop = UT_convertToInches(pszMarginTop);
192 	}
193 	if(pszMarginBottom && *pszMarginBottom)
194 	{
195 		m_dMarginBottom = UT_convertToInches(pszMarginBottom);
196 	}
197 	if(pszMarginLeft && *pszMarginLeft)
198 	{
199 		m_dMarginLeft = UT_convertToInches(pszMarginLeft);
200 	}
201 	if(pszMarginRight && *pszMarginRight)
202 	{
203 		m_dMarginRight = UT_convertToInches(pszMarginRight);
204 	}
205 	FREEP(pszSecProps);
206 }
207 
208 /*!
209  * Returns the current width of the document page.
210 \returns UT_sint32 width of page in inches
211 */
getPageWidth(void)212 double AP_Dialog_Columns::getPageWidth(void)
213 {
214 	double width = 1.0;
215 	if(m_pDoc)
216 	{
217 		width =  m_pDoc->m_docPageSize.Width(DIM_IN) - m_dMarginLeft - m_dMarginRight;
218 	}
219 	return width;
220 }
221 
222 
223 /*!
224  * Returns the current height of the document page.
225 \returns UT_sint32 height of page in inches
226 */
getPageHeight(void)227 double AP_Dialog_Columns::getPageHeight(void)
228 {
229 	double height = 1.0;
230 	if(m_pDoc)
231 	{
232 		height =  m_pDoc->m_docPageSize.Height(DIM_IN) - m_dMarginTop - m_dMarginBottom;
233 	}
234 	return height;
235 }
236 
237 /*!
238  * Increment the member variable UT_String defining the dimensioned string
239  * for the space between columns.
240  */
incrementSpaceAfter(bool bIncrement)241 void AP_Dialog_Columns::incrementSpaceAfter(bool bIncrement)
242 {
243 	double inc = getIncrement(m_SpaceAfterString.c_str());
244 	if(!bIncrement)
245 	{
246 		inc = -inc;
247 	}
248 	UT_Dimension dim = UT_determineDimension(getSpaceAfterString(), DIM_none);
249 	m_SpaceAfterString = UT_incrementDimString(m_SpaceAfterString.c_str(),inc);
250 	double dum = UT_convertToInches(getSpaceAfterString());
251 	if(dum < 0.0)
252 	{
253 		m_SpaceAfterString = UT_convertInchesToDimensionString(dim,0.0);
254 	}
255 	m_bSpaceAfterChanged = true;
256 	if(m_pColumnsPreview)
257 		m_pColumnsPreview->set(m_iColumns, m_bLineBetween);
258 }
259 
260 /*!
261  * Increment the member variable UT_String defining the dimensioned string
262  * for the maximum column height.
263  */
incrementMaxHeight(bool bIncrement)264 void AP_Dialog_Columns::incrementMaxHeight(bool bIncrement)
265 {
266 	double inc = getIncrement(m_HeightString.c_str());
267 	if(!bIncrement)
268 	{
269 		inc = -inc;
270 	}
271 	UT_Dimension dim = UT_determineDimension(getHeightString(), DIM_none);
272 	m_HeightString = UT_incrementDimString(m_HeightString.c_str(),inc);
273 	double dum = UT_convertToInches(getHeightString());
274 	if(dum < 0.0)
275 	{
276 		m_HeightString = UT_convertInchesToDimensionString(dim,0.0);
277 	}
278 	m_bMaxHeightChanged = true;
279 	if(m_pColumnsPreview)
280 		m_pColumnsPreview->set(m_iColumns, m_bLineBetween);
281 }
282 
setLineBetween(bool bState)283 void AP_Dialog_Columns::setLineBetween(bool bState)
284 {
285 	m_bLineBetween = bState;
286 
287 	if(m_pColumnsPreview)
288 		m_pColumnsPreview->set(m_iColumns, m_bLineBetween);
289 
290 }
291 
292 /*!
293  * Returns the 100* the fraction of the total page height in the Maximum height string.
294  */
getMaxHeightPercent(void)295 double AP_Dialog_Columns::getMaxHeightPercent(void)
296 {
297 	double height = 100.0*UT_convertToInches(getHeightString())/getPageHeight();
298 	return height;
299 }
300 
301 /*!
302  * Returns the 100* the fraction of the total page height in space after.
303  */
getSpaceAfterPercent(void)304 double AP_Dialog_Columns::getSpaceAfterPercent(void)
305 {
306 	double space = 100.0*UT_convertToInches(getSpaceAfterString())/getPageHeight();
307 	return space;
308 }
309 
310 /*!
311  * Set the member string variable m_HeightString
312 \param const char * szHeight is the string containing the new value
313 */
setMaxHeight(const char * szHeight)314 void AP_Dialog_Columns::setMaxHeight(const char * szHeight)
315 {
316 	UT_Dimension dim = UT_determineDimension(szHeight, DIM_none);
317 	if(dim != DIM_none)
318 	{
319 		m_bMaxHeightChanged = true;
320 		m_HeightString = szHeight;
321 		double dum = UT_convertToInches(getHeightString());
322 		if(dum < 0.0)
323 		{
324 			m_HeightString = UT_convertInchesToDimensionString(dim,0.0);
325 		}
326 		if(m_pColumnsPreview)
327 			m_pColumnsPreview->set(m_iColumns, m_bLineBetween);
328 	}
329 }
330 
331 /*!
332  * Set the member string variable m_SpaceAfterString.
333 \param const char * szAfter is the string containing the new value
334 */
setSpaceAfter(const char * szAfter)335 void AP_Dialog_Columns::setSpaceAfter(const char * szAfter)
336 {
337 	UT_Dimension dim = UT_determineDimension(szAfter, DIM_none);
338 	if(dim != DIM_none)
339 	{
340 		m_bSpaceAfterChanged = true;
341 		m_SpaceAfterString = szAfter;
342 		double dum = UT_convertToInches(getSpaceAfterString());
343 		if(dum < 0.0)
344 		{
345 			m_SpaceAfterString = UT_convertInchesToDimensionString(dim,0.0);
346 		}
347 		if(m_pColumnsPreview)
348 			m_pColumnsPreview->set(m_iColumns, m_bLineBetween);
349 	}
350 }
351 
352 
_drawColumnButton(GR_Graphics * gc,UT_Rect rect,UT_uint32 iColumns)353 void AP_Dialog_Columns::_drawColumnButton(GR_Graphics *gc, UT_Rect rect, UT_uint32 iColumns)
354 {
355 	GR_Painter painter(gc);
356 
357 	painter.clearArea(rect.left, rect.top, rect.width, rect.height);
358 
359 	rect.left += gc->tdu(2);
360 	rect.width -= gc->tdu(4);
361 	rect.top += gc->tdu(2);
362 	rect.height -= gc->tdu(4);
363 	m_previewDrawer.draw(gc, rect, iColumns, false, 0.0, 0.0);
364 }
365 
366 /*!
367  * Converts the string sz into the units seleced for the ruler.
368 \param XAP_Frame * pFrame defined the frame of the application
369 \param const char * sz is the string containing the old value
370 \param const gchar * pRet is the string to which the new value is copied.
371 */
_convertToPreferredUnits(XAP_Frame *,const char * sz,gchar * pRet)372 void AP_Dialog_Columns::_convertToPreferredUnits(XAP_Frame * /*pFrame*/,const char *sz, gchar * pRet)
373 {
374 	UT_Dimension PreferedUnits = DIM_none;
375 	const gchar * pszRulerUnits = NULL;
376 
377 	if (XAP_App::getApp()->getPrefsValue(AP_PREF_KEY_RulerUnits, &pszRulerUnits))
378 	{
379 		PreferedUnits = UT_determineDimension(static_cast<const char *>(pszRulerUnits));
380 	};
381 	strncpy(pRet, static_cast<const gchar *>(UT_reformatDimensionString(PreferedUnits,sz)), 25);
382 }
383 
384 
385 //////////////////////////////////////////////////////////////////
386 //////////////////////////////////////////////////////////////////
387 
AP_Columns_preview(GR_Graphics * gc,AP_Dialog_Columns * pColumns)388 AP_Columns_preview::AP_Columns_preview(GR_Graphics * gc, AP_Dialog_Columns * pColumns)
389 	: XAP_Preview(gc),
390 	m_previewDrawer(),
391 	m_pColumns(pColumns),
392 	m_iColumns(0),
393 	m_bLineBetween (false)
394 {
395 }
396 
~AP_Columns_preview()397 AP_Columns_preview::~AP_Columns_preview()
398 {
399 }
400 
draw(const UT_Rect * clip)401 void AP_Columns_preview::draw(const UT_Rect *clip)
402 {
403 	UT_UNUSED(clip);
404 	GR_Painter painter(m_gc);
405 
406 	UT_sint32 iWidth = m_gc->tlu(getWindowWidth());
407 	UT_sint32 iHeight = m_gc->tlu(getWindowHeight());
408 
409 	double maxHeightPercent = m_pColumns->getMaxHeightPercent();
410 	double SpacePercent = m_pColumns->getSpaceAfterPercent();
411 	UT_Rect pageRect(m_gc->tlu(5), m_gc->tlu(5), iWidth - m_gc->tlu(10), iHeight - m_gc->tlu(10));
412 
413 	painter.fillRect(GR_Graphics::CLR3D_Background, 0, 0, iWidth, iHeight);
414 	painter.clearArea(pageRect.left, pageRect.top, pageRect.width,
415 					pageRect.height);
416 
417 	m_gc->setLineWidth(m_gc->tlu(1));
418 	m_gc->setColor3D(GR_Graphics::CLR3D_Foreground);
419 	painter.drawLine(pageRect.left, pageRect.top,
420 		       pageRect.left + pageRect.width, pageRect.top);
421 	painter.drawLine(pageRect.left, pageRect.top,
422 		       pageRect.left, pageRect.top + pageRect.height);
423 
424 	m_gc->setLineWidth(m_gc->tlu(3));
425 	painter.drawLine(pageRect.left + pageRect.width, pageRect.top + m_gc->tlu(1),
426 				   pageRect.left + pageRect.width,
427 				   pageRect.top + pageRect.height);
428 	painter.drawLine(pageRect.left + m_gc->tlu(1), pageRect.top + pageRect.height,
429 				   pageRect.left + pageRect.width,
430 				   pageRect.top + pageRect.height);
431 
432 
433 	pageRect.top += m_gc->tlu(5);
434 	pageRect.height -= m_gc->tlu(5);
435 	m_previewDrawer.draw(m_gc, pageRect, m_iColumns, m_bLineBetween,maxHeightPercent, SpacePercent);
436 }
437 
438 //////////////////////////////////////////////////////////////////
439 //////////////////////////////////////////////////////////////////
440 
draw(GR_Graphics * gc,UT_Rect & rect,UT_sint32 iColumns,bool bLineBetween,double maxHeightPercent,double SpacePercent)441 void AP_Columns_preview_drawer::draw(GR_Graphics *gc, UT_Rect &rect, UT_sint32 iColumns, bool bLineBetween, double maxHeightPercent, double SpacePercent)
442 {
443 	GR_Painter painter(gc);
444 
445 	UT_sint32 iHalfColumnGap = gc->tlu (rect.width / gc->tlu(20));
446 
447 	UT_sint32 y_start = rect.top + iHalfColumnGap;
448 	UT_sint32 y_end = rect.top + rect.height - iHalfColumnGap;
449 
450 	UT_sint32 y_step = gc->tlu(4);
451 	maxHeightPercent /= 100.0;
452 	SpacePercent /= 100.0;
453 	if(maxHeightPercent < 0.01)
454 		maxHeightPercent = 1.1;
455 
456 	gc->setLineWidth(gc->tlu(1));
457 	UT_RGBColor Line_color(0, 0, 0);
458 	gc->setColor(Line_color);
459 
460 	rect.left += iHalfColumnGap;
461 	rect.width -= 2 * iHalfColumnGap;
462 	double d_ysize = (double) (y_end - y_start);
463 	UT_sint32 iSpace = static_cast<UT_sint32>(SpacePercent* d_ysize);
464 	if(iSpace < y_step)
465 	  iSpace = y_step;
466 	UT_sint32 maxHeight = static_cast<UT_sint32>(maxHeightPercent * d_ysize);
467 	for (UT_sint32 i = 1; i <= iColumns; i++)
468 	{
469 		UT_sint32 curskip = 0;
470 		for(UT_sint32 y = y_start; y < y_end; y += y_step)
471 		{
472 			UT_sint32 xLeft, xRight;
473 
474 			// a little bit of math to avoid/replace a (nasty) switch statement
475 			xLeft = rect.left + iHalfColumnGap + ((i-1) * rect.width/iColumns);
476 			xRight = rect.left - iHalfColumnGap + (i * rect.width / iColumns);
477 			curskip += y_step;
478 			if(curskip >= maxHeight )
479 			{
480 					curskip = 0;
481 					y += iSpace;
482 			}
483 			painter.drawLine(xLeft, y, xRight, y);
484 		}
485 	}
486 
487 	if(bLineBetween)
488 	{
489 		// a bit of math to avoid/replace a (nasty) switch statement
490 		for (UT_sint32 j = 2; j <= iColumns; j++)
491 		{
492 			UT_sint32 x = rect.left + (j-1) * rect.width / iColumns;
493 			painter.drawLine(x, y_start, x, y_end);
494 		}
495 	}
496 }
497 
498