Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include <svx/dialmgr.hxx>
21 : #include <svx/dialogs.hrc>
22 : #include <tools/shl.hxx>
23 : #include <i18npool/mslangid.hxx>
24 : #include <svtools/valueset.hxx>
25 : #include <svl/languageoptions.hxx>
26 : #include <helpid.hrc>
27 : #include <editeng/numitem.hxx>
28 : #include <svl/eitem.hxx>
29 : #include <vcl/svapp.hxx>
30 : #include <svx/gallery.hxx>
31 : #include <svl/urihelper.hxx>
32 : #include <editeng/brshitem.hxx>
33 : #include <svl/intitem.hxx>
34 : #include <sfx2/objsh.hxx>
35 : #include <vcl/graph.hxx>
36 : #include <vcl/msgbox.hxx>
37 : #include <editeng/flstitem.hxx>
38 : #include <svx/dlgutil.hxx>
39 : #include <svx/xtable.hxx>
40 : #include <svx/drawitem.hxx>
41 : #include <svx/numvset.hxx>
42 : #include <svx/htmlmode.hxx>
43 : #include <unotools/pathoptions.hxx>
44 : #include <svtools/ctrltool.hxx>
45 : #include <editeng/unolingu.hxx>
46 : #include <com/sun/star/style/NumberingType.hpp>
47 : #include <com/sun/star/lang/XMultiServiceFactory.hpp>
48 : #include <com/sun/star/container/XIndexAccess.hpp>
49 : #include <com/sun/star/text/XDefaultNumberingProvider.hpp>
50 : #include <com/sun/star/text/XNumberingFormatter.hpp>
51 : #include <com/sun/star/beans/PropertyValue.hpp>
52 : #include <comphelper/processfactory.hxx>
53 : #include <com/sun/star/text/XNumberingTypeInfo.hpp>
54 :
55 : #include <algorithm>
56 : #include <sfx2/opengrf.hxx>
57 :
58 : using namespace com::sun::star::uno;
59 : using namespace com::sun::star::beans;
60 : using namespace com::sun::star::lang;
61 : using namespace com::sun::star::i18n;
62 : using namespace com::sun::star::text;
63 : using namespace com::sun::star::container;
64 : using namespace com::sun::star::style;
65 : using rtl::OUString;
66 :
67 : #define C2U(cChar) OUString::createFromAscii(cChar)
68 : #define NUM_PAGETYPE_BULLET 0
69 : #define NUM_PAGETYPE_SINGLENUM 1
70 : #define NUM_PAGETYPE_NUM 2
71 : #define NUM_PAGETYPE_BMP 3
72 :
73 : static const sal_Char cNumberingType[] = "NumberingType";
74 : static const sal_Char cValue[] = "Value";
75 : static const sal_Char cParentNumbering[] = "ParentNumbering";
76 : static const sal_Char cPrefix[] = "Prefix";
77 : static const sal_Char cSuffix[] = "Suffix";
78 : static const sal_Char cBulletChar[] = "BulletChar";
79 : static const sal_Char cBulletFontName[] = "BulletFontName";
80 :
81 : // The selection of bullets from the star symbol
82 : static const sal_Unicode aBulletTypes[] =
83 : {
84 : 0x2022,
85 : 0x25cf,
86 : 0xe00c,
87 : 0xe00a,
88 : 0x2794,
89 : 0x27a2,
90 : 0x2717,
91 : 0x2714
92 : };
93 :
94 0 : static Font& lcl_GetDefaultBulletFont()
95 : {
96 : static sal_Bool bInit = 0;
97 : static Font aDefBulletFont( rtl::OUString("StarSymbol"),
98 0 : String(), Size( 0, 14 ) );
99 0 : if(!bInit)
100 : {
101 0 : aDefBulletFont.SetCharSet( RTL_TEXTENCODING_SYMBOL );
102 0 : aDefBulletFont.SetFamily( FAMILY_DONTKNOW );
103 0 : aDefBulletFont.SetPitch( PITCH_DONTKNOW );
104 0 : aDefBulletFont.SetWeight( WEIGHT_DONTKNOW );
105 0 : aDefBulletFont.SetTransparent( sal_True );
106 0 : bInit = sal_True;
107 : }
108 0 : return aDefBulletFont;
109 : }
110 :
111 0 : static void lcl_PaintLevel(OutputDevice* pVDev, sal_Int16 nNumberingType,
112 : const OUString& rBulletChar, const OUString& rText, const OUString& rFontName,
113 : Point& rLeft, Font& rRuleFont, const Font& rTextFont)
114 : {
115 :
116 0 : if(NumberingType::CHAR_SPECIAL == nNumberingType )
117 : {
118 0 : rRuleFont.SetStyleName(rFontName);
119 0 : pVDev->SetFont(rRuleFont);
120 0 : pVDev->DrawText(rLeft, rBulletChar);
121 0 : rLeft.X() += pVDev->GetTextWidth(rBulletChar);
122 : }
123 : else
124 : {
125 0 : pVDev->SetFont(rTextFont);
126 0 : pVDev->DrawText(rLeft, rText);
127 0 : rLeft.X() += pVDev->GetTextWidth(rText);
128 : }
129 0 : }
130 0 : void SvxNumValueSet::UserDraw( const UserDrawEvent& rUDEvt )
131 : {
132 : static sal_uInt16 aLinesArr[] =
133 : {
134 : 15, 10,
135 : 20, 30,
136 : 25, 50,
137 : 30, 70,
138 : 35, 90, // up to here line positions
139 : 05, 10, // character positions
140 : 10, 30,
141 : 15, 50,
142 : 20, 70,
143 : 25, 90,
144 : };
145 :
146 0 : const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
147 0 : const Color aBackColor = rStyleSettings.GetFieldColor();
148 0 : const Color aTextColor = rStyleSettings.GetFieldTextColor();
149 :
150 0 : OutputDevice* pDev = rUDEvt.GetDevice();
151 0 : Rectangle aRect = rUDEvt.GetRect();
152 0 : sal_uInt16 nItemId = rUDEvt.GetItemId();
153 0 : long nRectWidth = aRect.GetWidth();
154 0 : long nRectHeight = aRect.GetHeight();
155 0 : Size aRectSize(nRectWidth, aRect.GetHeight());
156 0 : Point aBLPos = aRect.TopLeft();
157 0 : Font aOldFont = pDev->GetFont();
158 0 : Color aOldColor = pDev->GetLineColor();
159 0 : pDev->SetLineColor(aTextColor);
160 : Font aFont(OutputDevice::GetDefaultFont(
161 0 : DEFAULTFONT_UI_SANS, MsLangId::getSystemLanguage(), DEFAULTFONT_FLAGS_ONLYONE));
162 :
163 0 : Size aSize = aFont.GetSize();
164 :
165 0 : Font aRuleFont( lcl_GetDefaultBulletFont() );
166 0 : aSize.Height() = nRectHeight/6;
167 0 : aRuleFont.SetSize(aSize);
168 0 : aRuleFont.SetColor(aTextColor);
169 0 : aRuleFont.SetFillColor(aBackColor);
170 0 : if(nPageType == NUM_PAGETYPE_BULLET)
171 0 : aFont = aRuleFont;
172 0 : else if(nPageType == NUM_PAGETYPE_NUM)
173 : {
174 0 : aSize.Height() = nRectHeight/8;
175 : }
176 0 : aFont.SetColor(aTextColor);
177 0 : aFont.SetFillColor(aBackColor);
178 0 : aFont.SetSize( aSize );
179 0 : pDev->SetFont(aFont);
180 :
181 0 : if(!pVDev)
182 : {
183 : // The lines are only one time in the virtual device, only the outline
184 : // page is currently done
185 0 : pVDev = new VirtualDevice(*pDev);
186 0 : pVDev->SetMapMode(pDev->GetMapMode());
187 0 : pVDev->EnableRTL( IsRTLEnabled() );
188 0 : pVDev->SetOutputSize( aRectSize );
189 0 : aOrgRect = aRect;
190 0 : pVDev->SetFillColor( aBackColor );
191 0 : pVDev->DrawRect(aOrgRect);
192 :
193 0 : if(aBackColor == aLineColor)
194 0 : aLineColor.Invert();
195 0 : pVDev->SetLineColor(aLineColor);
196 : // Draw line only once
197 0 : if(nPageType != NUM_PAGETYPE_NUM)
198 : {
199 0 : Point aStart(aBLPos.X() + nRectWidth *25 / 100,0);
200 0 : Point aEnd(aBLPos.X() + nRectWidth * 9 / 10,0);
201 0 : for( sal_uInt16 i = 11; i < 100; i += 33)
202 : {
203 0 : aStart.Y() = aEnd.Y() = aBLPos.Y() + nRectHeight * i / 100;
204 0 : pVDev->DrawLine(aStart, aEnd);
205 0 : aStart.Y() = aEnd.Y() = aBLPos.Y() + nRectHeight * (i + 11) / 100;
206 0 : pVDev->DrawLine(aStart, aEnd);
207 : }
208 : }
209 : }
210 : pDev->DrawOutDev( aRect.TopLeft(), aRectSize,
211 0 : aOrgRect.TopLeft(), aRectSize,
212 0 : *pVDev );
213 : // Now comes the text
214 0 : const OUString sValue(C2U(cValue));
215 0 : if( NUM_PAGETYPE_SINGLENUM == nPageType ||
216 : NUM_PAGETYPE_BULLET == nPageType )
217 : {
218 0 : Point aStart(aBLPos.X() + nRectWidth / 9,0);
219 0 : for( sal_uInt16 i = 0; i < 3; i++ )
220 : {
221 0 : sal_uInt16 nY = 11 + i * 33;
222 0 : aStart.Y() = aBLPos.Y() + nRectHeight * nY / 100;
223 0 : String sText;
224 0 : if(nPageType == NUM_PAGETYPE_BULLET)
225 : {
226 0 : sText = aBulletTypes[nItemId - 1];
227 0 : aStart.Y() -= pDev->GetTextHeight()/2;
228 0 : aStart.X() = aBLPos.X() + 5;
229 : }
230 : else
231 : {
232 0 : if(xFormatter.is() && aNumSettings.getLength() > nItemId - 1)
233 : {
234 0 : Sequence<PropertyValue> aLevel = aNumSettings.getConstArray()[nItemId - 1];
235 : try
236 : {
237 0 : aLevel.realloc(aLevel.getLength() + 1);
238 0 : PropertyValue& rValue = aLevel.getArray()[aLevel.getLength() - 1];
239 0 : rValue.Name = sValue;
240 0 : rValue.Value <<= (sal_Int32)(i + 1);
241 0 : sText = xFormatter->makeNumberingString( aLevel, aLocale );
242 : }
243 0 : catch(Exception&)
244 : {
245 : OSL_FAIL("Exception in DefaultNumberingProvider::makeNumberingString");
246 0 : }
247 : }
248 : // start just next to the left edge
249 0 : aStart.X() = aBLPos.X() + 2;
250 0 : aStart.Y() -= pDev->GetTextHeight()/2;
251 : }
252 0 : pDev->DrawText(aStart, sText);
253 0 : }
254 : }
255 0 : else if(NUM_PAGETYPE_NUM == nPageType )
256 : {
257 : // Outline numbering has to be painted into the virtual device
258 : // to get correct lines
259 : // has to be made again
260 0 : pVDev->DrawRect(aOrgRect);
261 0 : long nStartX = aOrgRect.TopLeft().X();
262 0 : long nStartY = aOrgRect.TopLeft().Y();
263 :
264 0 : if(xFormatter.is() && aOutlineSettings.getLength() > nItemId - 1)
265 : {
266 0 : Reference<XIndexAccess> xLevel = aOutlineSettings.getArray()[nItemId - 1];
267 : try
268 : {
269 0 : OUString sLevelTexts[5];
270 0 : OUString sFontNames[5];
271 0 : OUString sBulletChars[5];
272 : sal_Int16 aNumberingTypes[5];
273 0 : OUString sPrefixes[5];
274 0 : OUString sSuffixes[5];
275 : sal_Int16 aParentNumberings[5];
276 :
277 0 : sal_Int32 nLevelCount = xLevel->getCount();
278 0 : if(nLevelCount > 5)
279 0 : nLevelCount = 5;
280 0 : for( sal_Int32 i = 0; i < nLevelCount && i < 5; i++)
281 : {
282 0 : long nTop = nStartY + nRectHeight * (aLinesArr[2 * i + 11])/100 ;
283 0 : Point aLeft(nStartX + nRectWidth * (aLinesArr[2 * i + 10])/ 100, nTop );
284 :
285 0 : Any aLevelAny = xLevel->getByIndex(i);
286 0 : Sequence<PropertyValue> aLevel;
287 0 : aLevelAny >>= aLevel;
288 0 : const PropertyValue* pValues = aLevel.getConstArray();
289 0 : aNumberingTypes[i] = 0;
290 0 : for(sal_Int32 nProperty = 0; nProperty < aLevel.getLength() - 1; nProperty++)
291 : {
292 0 : if ( pValues[nProperty].Name == cNumberingType )
293 0 : pValues[nProperty].Value >>= aNumberingTypes[i];
294 0 : else if ( pValues[nProperty].Name == cBulletFontName )
295 0 : pValues[nProperty].Value >>= sFontNames[i];
296 0 : else if ( pValues[nProperty].Name == cBulletChar )
297 0 : pValues[nProperty].Value >>= sBulletChars[i];
298 0 : else if ( pValues[nProperty].Name == cPrefix )
299 0 : pValues[nProperty].Value >>= sPrefixes[i];
300 0 : else if ( pValues[nProperty].Name == cSuffix )
301 0 : pValues[nProperty].Value >>= sSuffixes[i];
302 0 : else if ( pValues[nProperty].Name == cParentNumbering )
303 0 : pValues[nProperty].Value >>= aParentNumberings[i];
304 : }
305 0 : Sequence< PropertyValue > aProperties(2);
306 0 : PropertyValue* pProperties = aProperties.getArray();
307 0 : pProperties[0].Name = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("NumberingType"));
308 0 : pProperties[0].Value <<= aNumberingTypes[i];
309 0 : pProperties[1].Name = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Value"));
310 0 : pProperties[1].Value <<= (sal_Int32)1;
311 : try
312 : {
313 0 : sLevelTexts[i] = xFormatter->makeNumberingString( aProperties, aLocale );
314 : }
315 0 : catch(Exception&)
316 : {
317 : OSL_FAIL("Exception in DefaultNumberingProvider::makeNumberingString");
318 : }
319 :
320 0 : aLeft.Y() -= (pDev->GetTextHeight()/2);
321 0 : if(!sPrefixes[i].isEmpty() &&
322 0 : !sPrefixes[i].equalsAsciiL(" ", 1) &&
323 0 : sPrefixes[i].getStr()[0] != 0)
324 : {
325 0 : pVDev->SetFont(aFont);
326 0 : pVDev->DrawText(aLeft, sPrefixes[i]);
327 0 : aLeft.X() += pDev->GetTextWidth(sPrefixes[i]);
328 : }
329 0 : if(aParentNumberings[i])
330 : {
331 : //insert old numberings here
332 0 : sal_Int32 nStartLevel = std::min((sal_Int32)aParentNumberings[i], i);
333 0 : for(sal_Int32 nParentLevel = i - nStartLevel; nParentLevel < i; nParentLevel++)
334 : {
335 0 : OUString sTmp(sLevelTexts[nParentLevel]);
336 0 : sTmp += C2U(".");
337 : lcl_PaintLevel(pVDev,
338 0 : aNumberingTypes[nParentLevel],
339 : sBulletChars[nParentLevel],
340 : sTmp,
341 : sFontNames[nParentLevel],
342 : aLeft,
343 : aRuleFont,
344 0 : aFont);
345 0 : }
346 : }
347 : lcl_PaintLevel(pVDev,
348 0 : aNumberingTypes[i],
349 0 : sBulletChars[i],
350 0 : sLevelTexts[i],
351 0 : sFontNames[i],
352 : aLeft,
353 : aRuleFont,
354 0 : aFont);
355 0 : if(!sSuffixes[i].isEmpty()&&
356 0 : !sSuffixes[i].equalsAsciiL(" ", 1) &&
357 0 : sSuffixes[i].getStr()[0] != 0)
358 : {
359 0 : pVDev->SetFont(aFont);
360 0 : pVDev->DrawText(aLeft, sSuffixes[i]);
361 0 : aLeft.X() += pDev->GetTextWidth(sSuffixes[i]);
362 : }
363 :
364 0 : long nLineTop = nStartY + nRectHeight * aLinesArr[2 * i + 1]/100 ;
365 0 : Point aLineLeft(aLeft.X(), nLineTop );
366 0 : Point aLineRight(nStartX + nRectWidth * 90 /100, nLineTop );
367 0 : pVDev->DrawLine(aLineLeft, aLineRight);
368 0 : }
369 :
370 : }
371 : #ifdef DBG_UTIL
372 : catch(Exception&)
373 : {
374 : static sal_Bool bAssert = sal_False;
375 : if(!bAssert)
376 : {
377 : OSL_FAIL("exception in ::UserDraw");
378 : bAssert = sal_True;
379 : }
380 : }
381 : #else
382 0 : catch(Exception&)
383 : {
384 0 : }
385 : #endif
386 : }
387 : pDev->DrawOutDev( aRect.TopLeft(), aRectSize,
388 0 : aOrgRect.TopLeft(), aRectSize,
389 0 : *pVDev );
390 : }
391 :
392 0 : pDev->SetFont(aOldFont);
393 0 : pDev->SetLineColor(aOldColor);
394 0 : }
395 :
396 0 : SvxNumValueSet::SvxNumValueSet( Window* pParent, const ResId& rResId, sal_uInt16 nType )
397 0 : : ValueSet( pParent, rResId )
398 : {
399 0 : init(nType);
400 0 : }
401 :
402 0 : void SvxNumValueSet::init(sal_uInt16 nType)
403 : {
404 0 : aLineColor = COL_LIGHTGRAY;
405 0 : nPageType = nType;
406 0 : bHTMLMode = sal_False;
407 0 : pVDev = NULL;
408 :
409 0 : SetColCount( 4 );
410 0 : SetLineCount( 2 );
411 0 : SetStyle( GetStyle() | WB_ITEMBORDER | WB_DOUBLEBORDER );
412 0 : if(NUM_PAGETYPE_BULLET == nType)
413 : {
414 0 : for ( sal_uInt16 i = 0; i < 8; i++ )
415 : {
416 0 : InsertItem( i + 1, i );
417 0 : SetItemText( i + 1, SVX_RESSTR( RID_SVXSTR_BULLET_DESCRIPTIONS + i ) );
418 : }
419 : }
420 0 : }
421 :
422 0 : SvxNumValueSet::~SvxNumValueSet()
423 : {
424 0 : delete pVDev;
425 0 : }
426 :
427 0 : void SvxNumValueSet::SetNumberingSettings(
428 : const Sequence<Sequence<PropertyValue> >& aNum,
429 : Reference<XNumberingFormatter>& xFormat,
430 : const Locale& rLocale )
431 : {
432 0 : aNumSettings = aNum;
433 0 : xFormatter = xFormat;
434 0 : aLocale = rLocale;
435 0 : if(aNum.getLength() > 8)
436 0 : SetStyle( GetStyle()|WB_VSCROLL);
437 0 : for ( sal_uInt16 i = 0; i < aNum.getLength(); i++ )
438 : {
439 0 : InsertItem( i + 1, i );
440 0 : if( i < 8 )
441 0 : SetItemText( i + 1, SVX_RESSTR( RID_SVXSTR_SINGLENUM_DESCRIPTIONS + i ));
442 : }
443 0 : }
444 :
445 0 : void SvxNumValueSet::SetOutlineNumberingSettings(
446 : Sequence<Reference<XIndexAccess> >& rOutline,
447 : Reference<XNumberingFormatter>& xFormat,
448 : const Locale& rLocale)
449 : {
450 0 : aOutlineSettings = rOutline;
451 0 : xFormatter = xFormat;
452 0 : aLocale = rLocale;
453 0 : if(aOutlineSettings.getLength() > 8)
454 0 : SetStyle( GetStyle() | WB_VSCROLL );
455 0 : for ( sal_uInt16 i = 0; i < aOutlineSettings.getLength(); i++ )
456 : {
457 0 : InsertItem( i + 1, i );
458 0 : if( i < 8 )
459 0 : SetItemText( i + 1, SVX_RESSTR( RID_SVXSTR_OUTLINENUM_DESCRIPTIONS + i ));
460 : }
461 0 : }
462 :
463 0 : SvxBmpNumValueSet::SvxBmpNumValueSet( Window* pParent, const ResId& rResId )
464 0 : : SvxNumValueSet( pParent, rResId, NUM_PAGETYPE_BMP )
465 : {
466 0 : init();
467 0 : }
468 :
469 0 : void SvxBmpNumValueSet::init()
470 : {
471 0 : bGrfNotFound = sal_False;
472 0 : GalleryExplorer::BeginLocking(GALLERY_THEME_BULLETS);
473 0 : SetStyle( GetStyle() | WB_VSCROLL );
474 0 : SetLineCount( 3 );
475 0 : aFormatTimer.SetTimeout(300);
476 0 : aFormatTimer.SetTimeoutHdl(LINK(this, SvxBmpNumValueSet, FormatHdl_Impl));
477 0 : }
478 :
479 :
480 0 : SvxBmpNumValueSet::~SvxBmpNumValueSet()
481 : {
482 0 : GalleryExplorer::EndLocking(GALLERY_THEME_BULLETS);
483 0 : aFormatTimer.Stop();
484 0 : }
485 :
486 0 : void SvxBmpNumValueSet::UserDraw( const UserDrawEvent& rUDEvt )
487 : {
488 0 : SvxNumValueSet::UserDraw(rUDEvt);
489 :
490 0 : Rectangle aRect = rUDEvt.GetRect();
491 0 : OutputDevice* pDev = rUDEvt.GetDevice();
492 0 : sal_uInt16 nItemId = rUDEvt.GetItemId();
493 0 : Point aBLPos = aRect.TopLeft();
494 :
495 0 : int nRectHeight = aRect.GetHeight();
496 0 : Size aSize(nRectHeight/8, nRectHeight/8);
497 :
498 0 : Graphic aGraphic;
499 0 : if(!GalleryExplorer::GetGraphicObj( GALLERY_THEME_BULLETS, nItemId - 1,
500 0 : &aGraphic, NULL))
501 : {
502 0 : bGrfNotFound = sal_True;
503 : }
504 : else
505 : {
506 0 : Point aPos(aBLPos.X() + 5, 0);
507 0 : for( sal_uInt16 i = 0; i < 3; i++ )
508 : {
509 0 : sal_uInt16 nY = 11 + i * 33;
510 0 : aPos.Y() = aBLPos.Y() + nRectHeight * nY / 100;
511 0 : aGraphic.Draw( pDev, aPos, aSize );
512 : }
513 0 : }
514 0 : }
515 :
516 0 : IMPL_LINK_NOARG(SvxBmpNumValueSet, FormatHdl_Impl)
517 : {
518 : // only when a graphics was not there, it needs to be formatted
519 0 : if(bGrfNotFound)
520 : {
521 0 : bGrfNotFound = sal_False;
522 0 : Format();
523 : }
524 0 : Invalidate();
525 0 : return 0;
526 : }
527 :
528 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|