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