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