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 <config_folders.h>
21 :
22 : #include <i18nutil/unicode.hxx>
23 : #include <tools/stream.hxx>
24 : #include <vcl/builderfactory.hxx>
25 : #include <vcl/svapp.hxx>
26 : #include <vcl/field.hxx>
27 : #include <vcl/helper.hxx>
28 : #include <vcl/settings.hxx>
29 : #include <sal/macros.h>
30 : #include <comphelper/processfactory.hxx>
31 : #include <comphelper/string.hxx>
32 : #include <unotools/charclass.hxx>
33 :
34 : #include <svtools/sampletext.hxx>
35 : #include <svtools/svtresid.hxx>
36 : #include <svtools/svtools.hrc>
37 : #include <svtools/ctrlbox.hxx>
38 : #include <svtools/ctrltool.hxx>
39 : #include <svtools/borderhelper.hxx>
40 :
41 : #include <vcl/i18nhelp.hxx>
42 : #include <vcl/fontcapabilities.hxx>
43 : #include <basegfx/polygon/b2dpolygon.hxx>
44 : #include <basegfx/polygon/b2dpolygontools.hxx>
45 :
46 : #include <com/sun/star/table/BorderLineStyle.hpp>
47 :
48 : #include <rtl/bootstrap.hxx>
49 :
50 : #include <stdio.h>
51 :
52 : #define IMGOUTERTEXTSPACE 5
53 : #define EXTRAFONTSIZE 5
54 : #define GAPTOEXTRAPREVIEW 10
55 : #define MAXPREVIEWWIDTH 120
56 : #define MINGAPWIDTH 2
57 :
58 : #define FONTNAMEBOXMRUENTRIESFILE "/user/config/fontnameboxmruentries"
59 :
60 : using namespace ::com::sun::star;
61 :
62 : class ImplColorListData
63 : {
64 : public:
65 : Color aColor;
66 : bool bColor;
67 :
68 0 : ImplColorListData() : aColor( COL_BLACK ) { bColor = false; }
69 0 : explicit ImplColorListData( const Color& rColor ) : aColor( rColor ) { bColor = true; }
70 : };
71 :
72 51 : void ColorListBox::ImplInit()
73 : {
74 51 : pColorList = new ImpColorList();
75 :
76 51 : const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
77 51 : aImageSize = rStyleSettings.GetListBoxPreviewDefaultPixelSize();
78 51 : EnableUserDraw( true );
79 51 : SetUserItemSize( aImageSize );
80 51 : }
81 :
82 51 : void ColorListBox::ImplDestroyColorEntries()
83 : {
84 102 : for ( size_t n = pColorList->size(); n; )
85 0 : delete (*pColorList)[ --n ];
86 51 : pColorList->clear();
87 51 : }
88 :
89 51 : ColorListBox::ColorListBox( vcl::Window* pParent, WinBits nWinStyle ) :
90 51 : ListBox( pParent, nWinStyle )
91 : {
92 51 : ImplInit();
93 51 : SetEdgeBlending(true);
94 51 : }
95 :
96 0 : ColorListBox::ColorListBox( vcl::Window* pParent, const ResId& rResId ) :
97 0 : ListBox( pParent, rResId )
98 : {
99 0 : ImplInit();
100 0 : SetEdgeBlending(true);
101 0 : }
102 :
103 0 : VCL_BUILDER_DECL_FACTORY(ColorListBox)
104 : {
105 0 : bool bDropdown = VclBuilder::extractDropdown(rMap);
106 0 : WinBits nWinBits = WB_LEFT|WB_VCENTER|WB_3DLOOK|WB_TABSTOP;
107 0 : if (bDropdown)
108 0 : nWinBits |= WB_DROPDOWN;
109 0 : VclPtrInstance<ColorListBox> pListBox(pParent, nWinBits);
110 0 : if (bDropdown)
111 0 : pListBox->EnableAutoSize(true);
112 0 : rRet = pListBox;
113 0 : }
114 :
115 102 : ColorListBox::~ColorListBox()
116 : {
117 51 : disposeOnce();
118 51 : }
119 :
120 51 : void ColorListBox::dispose()
121 : {
122 51 : if ( pColorList )
123 : {
124 51 : ImplDestroyColorEntries();
125 51 : delete pColorList;
126 51 : pColorList = NULL;
127 : }
128 51 : ListBox::dispose();
129 51 : }
130 :
131 0 : sal_Int32 ColorListBox::InsertEntry( const OUString& rStr, sal_Int32 nPos )
132 : {
133 0 : nPos = ListBox::InsertEntry( rStr, nPos );
134 0 : if ( nPos != LISTBOX_ERROR )
135 : {
136 0 : ImplColorListData* pData = new ImplColorListData;
137 0 : if ( static_cast<size_t>(nPos) < pColorList->size() )
138 : {
139 0 : ImpColorList::iterator it = pColorList->begin();
140 0 : ::std::advance( it, nPos );
141 0 : pColorList->insert( it, pData );
142 : }
143 : else
144 : {
145 0 : pColorList->push_back( pData );
146 0 : nPos = pColorList->size() - 1;
147 : }
148 : }
149 0 : return nPos;
150 : }
151 :
152 0 : sal_Int32 ColorListBox::InsertEntry( const Color& rColor, const OUString& rStr,
153 : sal_Int32 nPos )
154 : {
155 0 : nPos = ListBox::InsertEntry( rStr, nPos );
156 0 : if ( nPos != LISTBOX_ERROR )
157 : {
158 0 : ImplColorListData* pData = new ImplColorListData( rColor );
159 0 : if ( static_cast<size_t>(nPos) < pColorList->size() )
160 : {
161 0 : ImpColorList::iterator it = pColorList->begin();
162 0 : ::std::advance( it, nPos );
163 0 : pColorList->insert( it, pData );
164 : }
165 : else
166 : {
167 0 : pColorList->push_back( pData );
168 0 : nPos = pColorList->size() - 1;
169 : }
170 : }
171 0 : return nPos;
172 : }
173 :
174 0 : void ColorListBox::InsertAutomaticEntryColor(const Color &rColor)
175 : {
176 : // insert the "Automatic"-entry always on the first position
177 0 : InsertEntry( rColor, SVT_RESSTR(STR_SVT_AUTOMATIC_COLOR), 0 );
178 0 : }
179 :
180 0 : void ColorListBox::RemoveEntry( sal_Int32 nPos )
181 : {
182 0 : ListBox::RemoveEntry( nPos );
183 0 : if ( 0 <= nPos && static_cast<size_t>(nPos) < pColorList->size() )
184 : {
185 0 : ImpColorList::iterator it = pColorList->begin();
186 0 : ::std::advance( it, nPos );
187 0 : delete *it;
188 0 : pColorList->erase( it );
189 : }
190 0 : }
191 :
192 0 : void ColorListBox::Clear()
193 : {
194 0 : ImplDestroyColorEntries();
195 0 : ListBox::Clear();
196 0 : }
197 :
198 0 : void ColorListBox::CopyEntries( const ColorListBox& rBox )
199 : {
200 : // Liste leeren
201 0 : ImplDestroyColorEntries();
202 :
203 : // Daten kopieren
204 0 : size_t nCount = rBox.pColorList->size();
205 0 : for ( size_t n = 0; n < nCount; n++ )
206 : {
207 0 : ImplColorListData* pData = (*rBox.pColorList)[ n ];
208 0 : sal_Int32 nPos = InsertEntry( rBox.GetEntry( n ), LISTBOX_APPEND );
209 0 : if ( nPos != LISTBOX_ERROR )
210 : {
211 0 : if ( static_cast<size_t>(nPos) < pColorList->size() )
212 : {
213 0 : ImpColorList::iterator it = pColorList->begin();
214 0 : ::std::advance( it, nPos );
215 0 : pColorList->insert( it, new ImplColorListData( *pData ) );
216 : }
217 : else
218 : {
219 0 : pColorList->push_back( new ImplColorListData( *pData ) );
220 : }
221 : }
222 : }
223 0 : }
224 :
225 0 : sal_Int32 ColorListBox::GetEntryPos( const Color& rColor ) const
226 : {
227 0 : for( sal_Int32 n = (sal_Int32) pColorList->size(); n; )
228 : {
229 0 : ImplColorListData* pData = (*pColorList)[ --n ];
230 0 : if ( pData->bColor && ( pData->aColor == rColor ) )
231 0 : return n;
232 : }
233 0 : return LISTBOX_ENTRY_NOTFOUND;
234 : }
235 :
236 0 : Color ColorListBox::GetEntryColor( sal_Int32 nPos ) const
237 : {
238 0 : Color aColor;
239 0 : ImplColorListData* pData = ( 0 <= nPos && static_cast<size_t>(nPos) < pColorList->size() ) ?
240 0 : (*pColorList)[ nPos ] : NULL;
241 0 : if ( pData && pData->bColor )
242 0 : aColor = pData->aColor;
243 0 : return aColor;
244 : }
245 :
246 1 : void ColorListBox::UserDraw( const UserDrawEvent& rUDEvt )
247 : {
248 1 : size_t nPos = rUDEvt.GetItemId();
249 1 : ImplColorListData* pData = ( nPos < pColorList->size() ) ? (*pColorList)[ nPos ] : NULL;
250 1 : if ( pData )
251 : {
252 0 : if ( pData->bColor )
253 : {
254 0 : Point aPos( rUDEvt.GetRect().TopLeft() );
255 :
256 0 : aPos.X() += 2;
257 0 : aPos.Y() += ( rUDEvt.GetRect().GetHeight() - aImageSize.Height() ) / 2;
258 :
259 0 : const Rectangle aRect(aPos, aImageSize);
260 :
261 0 : rUDEvt.GetDevice()->Push();
262 0 : rUDEvt.GetDevice()->SetFillColor( pData->aColor );
263 0 : rUDEvt.GetDevice()->SetLineColor( rUDEvt.GetDevice()->GetTextColor() );
264 0 : rUDEvt.GetDevice()->DrawRect(aRect);
265 0 : rUDEvt.GetDevice()->Pop();
266 :
267 0 : const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
268 0 : const sal_uInt16 nEdgeBlendingPercent(GetEdgeBlending() ? rStyleSettings.GetEdgeBlending() : 0);
269 :
270 0 : if(nEdgeBlendingPercent)
271 : {
272 0 : const Color& rTopLeft(rStyleSettings.GetEdgeBlendingTopLeftColor());
273 0 : const Color& rBottomRight(rStyleSettings.GetEdgeBlendingBottomRightColor());
274 0 : const sal_uInt8 nAlpha((nEdgeBlendingPercent * 255) / 100);
275 0 : const BitmapEx aBlendFrame(createBlendFrame(aRect.GetSize(), nAlpha, rTopLeft, rBottomRight));
276 :
277 0 : if(!aBlendFrame.IsEmpty())
278 : {
279 0 : rUDEvt.GetDevice()->DrawBitmapEx(aRect.TopLeft(), aBlendFrame);
280 0 : }
281 : }
282 :
283 0 : ListBox::DrawEntry( rUDEvt, false, true, false );
284 : }
285 : else
286 0 : ListBox::DrawEntry( rUDEvt, false, true, true );
287 : }
288 : else
289 1 : ListBox::DrawEntry( rUDEvt, true, true, false );
290 1 : }
291 :
292 529500 : BorderWidthImpl::BorderWidthImpl( BorderWidthImplFlags nFlags, double nRate1, double nRate2, double nRateGap ):
293 : m_nFlags( nFlags ),
294 : m_nRate1( nRate1 ),
295 : m_nRate2( nRate2 ),
296 529500 : m_nRateGap( nRateGap )
297 : {
298 529500 : }
299 :
300 469422 : BorderWidthImpl& BorderWidthImpl::operator= ( const BorderWidthImpl& r )
301 : {
302 469422 : m_nFlags = r.m_nFlags;
303 469422 : m_nRate1 = r.m_nRate1;
304 469422 : m_nRate2 = r.m_nRate2;
305 469422 : m_nRateGap = r.m_nRateGap;
306 469422 : return *this;
307 : }
308 :
309 199528 : bool BorderWidthImpl::operator== ( const BorderWidthImpl& r ) const
310 : {
311 398932 : return ( m_nFlags == r.m_nFlags ) &&
312 398769 : ( m_nRate1 == r.m_nRate1 ) &&
313 598222 : ( m_nRate2 == r.m_nRate2 ) &&
314 398857 : ( m_nRateGap == r.m_nRateGap );
315 : }
316 :
317 1266685 : long BorderWidthImpl::GetLine1( long nWidth ) const
318 : {
319 1266685 : long result = static_cast<long>(m_nRate1);
320 1266685 : if ( m_nFlags & BorderWidthImplFlags::CHANGE_LINE1 )
321 : {
322 1263959 : long const nConstant2 = (m_nFlags & BorderWidthImplFlags::CHANGE_LINE2) ? 0 : m_nRate2;
323 1263959 : long const nConstantD = (m_nFlags & BorderWidthImplFlags::CHANGE_DIST ) ? 0 : m_nRateGap;
324 : result = std::max<long>(0,
325 1263959 : static_cast<long>((m_nRate1 * nWidth) + 0.5)
326 1263959 : - (nConstant2 + nConstantD));
327 1263959 : if (result == 0 && m_nRate1 > 0.0 && nWidth > 0)
328 : { // fdo#51777: hack to essentially treat 1 twip DOUBLE border
329 8 : result = 1; // as 1 twip SINGLE border
330 : }
331 : }
332 1266685 : return result;
333 : }
334 :
335 1213054 : long BorderWidthImpl::GetLine2( long nWidth ) const
336 : {
337 1213054 : long result = static_cast<long>(m_nRate2);
338 1213054 : if ( m_nFlags & BorderWidthImplFlags::CHANGE_LINE2)
339 : {
340 1366 : long const nConstant1 = (m_nFlags & BorderWidthImplFlags::CHANGE_LINE1) ? 0 : m_nRate1;
341 1366 : long const nConstantD = (m_nFlags & BorderWidthImplFlags::CHANGE_DIST ) ? 0 : m_nRateGap;
342 : result = std::max<long>(0,
343 1366 : static_cast<long>((m_nRate2 * nWidth) + 0.5)
344 1366 : - (nConstant1 + nConstantD));
345 : }
346 1213054 : return result;
347 : }
348 :
349 1094392 : long BorderWidthImpl::GetGap( long nWidth ) const
350 : {
351 1094392 : long result = static_cast<long>(m_nRateGap);
352 1094392 : if ( m_nFlags & BorderWidthImplFlags::CHANGE_DIST )
353 : {
354 3222 : long const nConstant1 = (m_nFlags & BorderWidthImplFlags::CHANGE_LINE1) ? 0 : m_nRate1;
355 3222 : long const nConstant2 = (m_nFlags & BorderWidthImplFlags::CHANGE_LINE2) ? 0 : m_nRate2;
356 : result = std::max<long>(0,
357 3222 : static_cast<long>((m_nRateGap * nWidth) + 0.5)
358 3222 : - (nConstant1 + nConstant2));
359 : }
360 :
361 : // Avoid having too small distances (less than 0.1pt)
362 1094392 : if ( result < MINGAPWIDTH && m_nRate1 > 0 && m_nRate2 > 0 )
363 16 : result = MINGAPWIDTH;
364 :
365 1094392 : return result;
366 : }
367 :
368 57642 : static double lcl_getGuessedWidth( long nTested, double nRate, bool nChanging )
369 : {
370 57642 : double nWidth = -1.0;
371 57642 : if ( nChanging )
372 20022 : nWidth = double( nTested ) / nRate;
373 : else
374 : {
375 37620 : if ( double( nTested ) == nRate )
376 36322 : nWidth = nRate;
377 : }
378 :
379 57642 : return nWidth;
380 : }
381 :
382 19214 : long BorderWidthImpl::GuessWidth( long nLine1, long nLine2, long nGap )
383 : {
384 19214 : std::vector< double > aToCompare;
385 19214 : bool bInvalid = false;
386 :
387 19214 : bool bLine1Change = bool( m_nFlags & BorderWidthImplFlags::CHANGE_LINE1 );
388 19214 : double nWidth1 = lcl_getGuessedWidth( nLine1, m_nRate1, bLine1Change );
389 19214 : if ( bLine1Change )
390 18735 : aToCompare.push_back( nWidth1 );
391 479 : else if ( !bLine1Change && nWidth1 < 0 )
392 462 : bInvalid = true;
393 :
394 19214 : bool bLine2Change = bool( m_nFlags & BorderWidthImplFlags::CHANGE_LINE2 );
395 19214 : double nWidth2 = lcl_getGuessedWidth( nLine2, m_nRate2, bLine2Change );
396 19214 : if ( bLine2Change )
397 523 : aToCompare.push_back( nWidth2 );
398 18691 : else if ( !bLine2Change && nWidth2 < 0 )
399 547 : bInvalid = true;
400 :
401 19214 : bool bGapChange = bool( m_nFlags & BorderWidthImplFlags::CHANGE_DIST );
402 19214 : double nWidthGap = lcl_getGuessedWidth( nGap, m_nRateGap, bGapChange );
403 19214 : if ( bGapChange && nGap > MINGAPWIDTH )
404 758 : aToCompare.push_back( nWidthGap );
405 18456 : else if ( !bGapChange && nWidthGap < 0 )
406 289 : bInvalid = true;
407 :
408 : // non-constant line width factors must sum to 1
409 : assert((((bLine1Change) ? m_nRate1 : 0) +
410 : ((bLine2Change) ? m_nRate2 : 0) +
411 : ((bGapChange) ? m_nRateGap : 0)) - 1.0 < 0.00001 );
412 :
413 19214 : double nWidth = 0.0;
414 19214 : if ( (!bInvalid) && (!aToCompare.empty()) )
415 : {
416 18557 : nWidth = *aToCompare.begin();
417 18557 : std::vector< double >::iterator pIt = aToCompare.begin();
418 56163 : while ( pIt != aToCompare.end() && !bInvalid )
419 : {
420 19049 : bInvalid = ( nWidth != *pIt );
421 19049 : ++pIt;
422 : }
423 18557 : nWidth = (bInvalid) ? 0.0 : nLine1 + nLine2 + nGap;
424 : }
425 :
426 19214 : return nWidth;
427 : }
428 :
429 : /** Utility class storing the border line width, style and colors. The widths
430 : are defined in Twips.
431 : */
432 : class ImpLineListData
433 : {
434 : private:
435 : BorderWidthImpl m_aWidthImpl;
436 :
437 : Color ( *m_pColor1Fn )( Color );
438 : Color ( *m_pColor2Fn )( Color );
439 : Color ( *m_pColorDistFn )( Color, Color );
440 :
441 : long m_nMinWidth;
442 : sal_uInt16 m_nStyle;
443 :
444 : public:
445 : ImpLineListData( BorderWidthImpl aWidthImpl, sal_uInt16 nStyle,
446 : long nMinWidth=0, Color ( *pColor1Fn ) ( Color ) = &sameColor,
447 : Color ( *pColor2Fn ) ( Color ) = &sameColor, Color ( *pColorDistFn ) ( Color, Color ) = &sameDistColor );
448 :
449 : /** Returns the computed width of the line 1 in twips. */
450 0 : long GetLine1ForWidth( long nWidth ) { return m_aWidthImpl.GetLine1( nWidth ); }
451 :
452 : /** Returns the computed width of the line 2 in twips. */
453 0 : long GetLine2ForWidth( long nWidth ) { return m_aWidthImpl.GetLine2( nWidth ); }
454 :
455 : /** Returns the computed width of the gap in twips. */
456 0 : long GetDistForWidth( long nWidth ) { return m_aWidthImpl.GetGap( nWidth ); }
457 :
458 : Color GetColorLine1( const Color& aMain );
459 : Color GetColorLine2( const Color& aMain );
460 : Color GetColorDist( const Color& aMain, const Color& rDefault );
461 :
462 : /** Returns the minimum width in twips */
463 0 : long GetMinWidth( ) { return m_nMinWidth;}
464 0 : sal_uInt16 GetStyle( ) { return m_nStyle;}
465 : };
466 :
467 0 : ImpLineListData::ImpLineListData( BorderWidthImpl aWidthImpl,
468 : sal_uInt16 nStyle, long nMinWidth, Color ( *pColor1Fn )( Color ),
469 : Color ( *pColor2Fn )( Color ), Color ( *pColorDistFn )( Color, Color ) ) :
470 : m_aWidthImpl( aWidthImpl ),
471 : m_pColor1Fn( pColor1Fn ),
472 : m_pColor2Fn( pColor2Fn ),
473 : m_pColorDistFn( pColorDistFn ),
474 : m_nMinWidth( nMinWidth ),
475 0 : m_nStyle( nStyle )
476 : {
477 0 : }
478 :
479 :
480 0 : Color ImpLineListData::GetColorLine1( const Color& rMain )
481 : {
482 0 : return ( *m_pColor1Fn )( rMain );
483 : }
484 :
485 0 : Color ImpLineListData::GetColorLine2( const Color& rMain )
486 : {
487 0 : return ( *m_pColor2Fn )( rMain );
488 : }
489 :
490 0 : Color ImpLineListData::GetColorDist( const Color& rMain, const Color& rDefault )
491 : {
492 0 : return ( *m_pColorDistFn )( rMain, rDefault );
493 : }
494 :
495 0 : sal_uInt16 LineListBox::GetSelectEntryStyle( sal_Int32 nSelIndex ) const
496 : {
497 0 : sal_uInt16 nStyle = table::BorderLineStyle::SOLID;
498 0 : sal_Int32 nPos = GetSelectEntryPos( nSelIndex );
499 0 : if ( nPos != LISTBOX_ENTRY_NOTFOUND )
500 : {
501 0 : if (!m_sNone.isEmpty())
502 0 : nPos--;
503 0 : nStyle = GetEntryStyle( nPos );
504 : }
505 :
506 0 : return nStyle;
507 : }
508 :
509 :
510 2 : void lclDrawPolygon( OutputDevice& rDev, const basegfx::B2DPolygon& rPolygon, long nWidth, sal_uInt16 nDashing )
511 : {
512 2 : AntialiasingFlags nOldAA = rDev.GetAntialiasing();
513 2 : rDev.SetAntialiasing( nOldAA & ~AntialiasingFlags::EnableB2dDraw );
514 :
515 2 : long nPix = rDev.PixelToLogic(Size(1, 1)).Width();
516 2 : basegfx::B2DPolyPolygon aPolygons = svtools::ApplyLineDashing(rPolygon, nDashing, nPix);
517 :
518 : // Handle problems of width 1px in Pixel mode: 0.5px gives a 1px line
519 2 : if (rDev.GetMapMode().GetMapUnit() == MAP_PIXEL && nWidth == nPix)
520 0 : nWidth = 0;
521 :
522 4 : for ( sal_uInt32 i = 0; i < aPolygons.count( ); i++ )
523 : {
524 2 : basegfx::B2DPolygon aDash = aPolygons.getB2DPolygon( i );
525 4 : basegfx::B2DPoint aStart = aDash.getB2DPoint( 0 );
526 4 : basegfx::B2DPoint aEnd = aDash.getB2DPoint( aDash.count() - 1 );
527 :
528 4 : basegfx::B2DVector aVector( aEnd - aStart );
529 2 : aVector.normalize( );
530 4 : const basegfx::B2DVector aPerpendicular(basegfx::getPerpendicular(aVector));
531 :
532 4 : const basegfx::B2DVector aWidthOffset( double( nWidth ) / 2 * aPerpendicular);
533 4 : basegfx::B2DPolygon aDashPolygon;
534 2 : aDashPolygon.append( aStart + aWidthOffset );
535 2 : aDashPolygon.append( aEnd + aWidthOffset );
536 2 : aDashPolygon.append( aEnd - aWidthOffset );
537 2 : aDashPolygon.append( aStart - aWidthOffset );
538 2 : aDashPolygon.setClosed( true );
539 :
540 2 : rDev.DrawPolygon( aDashPolygon );
541 2 : }
542 :
543 2 : rDev.SetAntialiasing( nOldAA );
544 2 : }
545 :
546 : namespace svtools {
547 :
548 : /**
549 : * Dashing array must start with a line width and end with a blank width.
550 : */
551 132 : std::vector<double> GetDashing( sal_uInt16 nDashing )
552 : {
553 132 : std::vector<double> aPattern;
554 132 : switch (nDashing)
555 : {
556 : case table::BorderLineStyle::DOTTED:
557 61 : aPattern.push_back( 1.0 ); // line
558 61 : aPattern.push_back( 2.0 ); // blank
559 61 : break;
560 : case table::BorderLineStyle::DASHED:
561 21 : aPattern.push_back( 16.0 ); // line
562 21 : aPattern.push_back( 5.0 ); // blank
563 21 : break;
564 : case table::BorderLineStyle::FINE_DASHED:
565 20 : aPattern.push_back( 6.0 ); // line
566 20 : aPattern.push_back( 2.0 ); // blank
567 20 : break;
568 : case table::BorderLineStyle::DASH_DOT:
569 0 : aPattern.push_back( 16.0 ); // line
570 0 : aPattern.push_back( 5.0 ); // blank
571 0 : aPattern.push_back( 5.0 ); // line
572 0 : aPattern.push_back( 5.0 ); // blank
573 0 : break;
574 : case table::BorderLineStyle::DASH_DOT_DOT:
575 0 : aPattern.push_back( 16.0 ); // line
576 0 : aPattern.push_back( 5.0 ); // blank
577 0 : aPattern.push_back( 5.0 ); // line
578 0 : aPattern.push_back( 5.0 ); // blank
579 0 : aPattern.push_back( 5.0 ); // line
580 0 : aPattern.push_back( 5.0 ); // blank
581 0 : break;
582 : default:
583 : ;
584 : }
585 :
586 132 : return aPattern;
587 : }
588 :
589 : namespace {
590 :
591 : class ApplyScale : std::unary_function<double, void>
592 : {
593 : double mfScale;
594 : public:
595 132 : explicit ApplyScale( double fScale ) : mfScale(fScale) {}
596 204 : void operator() ( double& rVal )
597 : {
598 204 : rVal *= mfScale;
599 204 : }
600 : };
601 :
602 : }
603 :
604 97 : std::vector<double> GetLineDashing( sal_uInt16 nDashing, double fScale )
605 : {
606 97 : std::vector<double> aPattern = GetDashing(nDashing);
607 97 : std::for_each(aPattern.begin(), aPattern.end(), ApplyScale(fScale));
608 97 : return aPattern;
609 : }
610 :
611 35 : basegfx::B2DPolyPolygon ApplyLineDashing( const basegfx::B2DPolygon& rPolygon, sal_uInt16 nDashing, double fScale )
612 : {
613 35 : std::vector<double> aPattern = GetDashing(nDashing);
614 35 : std::for_each(aPattern.begin(), aPattern.end(), ApplyScale(fScale));
615 :
616 35 : basegfx::B2DPolyPolygon aPolygons;
617 :
618 35 : if (aPattern.empty())
619 30 : aPolygons.append(rPolygon);
620 : else
621 5 : basegfx::tools::applyLineDashing(rPolygon, aPattern, &aPolygons);
622 :
623 35 : return aPolygons;
624 : }
625 :
626 2 : void DrawLine( OutputDevice& rDev, const Point& rP1, const Point& rP2,
627 : sal_uInt32 nWidth, sal_uInt16 nDashing )
628 : {
629 4 : DrawLine( rDev, basegfx::B2DPoint( rP1.X(), rP1.Y() ),
630 6 : basegfx::B2DPoint( rP2.X(), rP2.Y( ) ), nWidth, nDashing );
631 2 : }
632 :
633 2 : void DrawLine( OutputDevice& rDev, const basegfx::B2DPoint& rP1, const basegfx::B2DPoint& rP2,
634 : sal_uInt32 nWidth, sal_uInt16 nDashing )
635 : {
636 2 : basegfx::B2DPolygon aPolygon;
637 2 : aPolygon.append( rP1 );
638 2 : aPolygon.append( rP2 );
639 2 : lclDrawPolygon( rDev, aPolygon, nWidth, nDashing );
640 2 : }
641 :
642 : }
643 :
644 0 : void LineListBox::ImpGetLine( long nLine1, long nLine2, long nDistance,
645 : Color aColor1, Color aColor2, Color aColorDist,
646 : sal_uInt16 nStyle, Bitmap& rBmp )
647 : {
648 : //TODO, rather than including the " " text to force
649 : //the line height, better would be do drop
650 : //this calculation and draw a bitmap of height
651 : //equal to normal text line and center the
652 : //line within that
653 0 : long nMinWidth = GetTextWidth(OUString("----------"));
654 0 : Size aSize = CalcSubEditSize();
655 0 : aSize.Width() = std::max(nMinWidth, aSize.Width());
656 0 : aSize.Width() -= aTxtSize.Width();
657 0 : aSize.Width() -= 6;
658 0 : aSize.Height() = aTxtSize.Height();
659 :
660 : // SourceUnit nach Twips
661 0 : if ( eSourceUnit == FUNIT_POINT )
662 : {
663 0 : nLine1 /= 5;
664 0 : nLine2 /= 5;
665 0 : nDistance /= 5;
666 : }
667 :
668 : // Linien malen
669 0 : aSize = aVirDev->PixelToLogic( aSize );
670 0 : long nPix = aVirDev->PixelToLogic( Size( 0, 1 ) ).Height();
671 0 : sal_uInt32 n1 = nLine1;
672 0 : sal_uInt32 n2 = nLine2;
673 0 : long nDist = nDistance;
674 0 : n1 += nPix-1;
675 0 : n1 -= n1%nPix;
676 0 : if ( n2 )
677 : {
678 0 : nDist += nPix-1;
679 0 : nDist -= nDist%nPix;
680 0 : n2 += nPix-1;
681 0 : n2 -= n2%nPix;
682 : }
683 0 : long nVirHeight = n1+nDist+n2;
684 0 : if ( nVirHeight > aSize.Height() )
685 0 : aSize.Height() = nVirHeight;
686 : // negative width should not be drawn
687 0 : if ( aSize.Width() > 0 )
688 : {
689 0 : Size aVirSize = aVirDev->LogicToPixel( aSize );
690 0 : if ( aVirDev->GetOutputSizePixel() != aVirSize )
691 0 : aVirDev->SetOutputSizePixel( aVirSize );
692 0 : aVirDev->SetFillColor( aColorDist );
693 0 : aVirDev->DrawRect( Rectangle( Point(), aSize ) );
694 :
695 0 : aVirDev->SetFillColor( aColor1 );
696 :
697 0 : double y1 = double( n1 ) / 2;
698 0 : svtools::DrawLine( *aVirDev.get(), basegfx::B2DPoint( 0, y1 ), basegfx::B2DPoint( aSize.Width( ), y1 ), n1, nStyle );
699 :
700 0 : if ( n2 )
701 : {
702 0 : double y2 = n1 + nDist + double( n2 ) / 2;
703 0 : aVirDev->SetFillColor( aColor2 );
704 0 : svtools::DrawLine( *aVirDev.get(), basegfx::B2DPoint( 0, y2 ), basegfx::B2DPoint( aSize.Width(), y2 ), n2, table::BorderLineStyle::SOLID );
705 : }
706 0 : rBmp = aVirDev->GetBitmap( Point(), Size( aSize.Width(), n1+nDist+n2 ) );
707 : }
708 0 : }
709 :
710 0 : void LineListBox::ImplInit()
711 : {
712 0 : aTxtSize.Width() = GetTextWidth( OUString( " " ) );
713 0 : aTxtSize.Height() = GetTextHeight();
714 0 : pLineList = new ImpLineList();
715 0 : eUnit = FUNIT_POINT;
716 0 : eSourceUnit = FUNIT_POINT;
717 :
718 0 : aVirDev->SetLineColor();
719 0 : aVirDev->SetMapMode( MapMode( MAP_TWIP ) );
720 :
721 0 : UpdatePaintLineColor();
722 0 : }
723 :
724 0 : LineListBox::LineListBox( vcl::Window* pParent, WinBits nWinStyle ) :
725 : ListBox( pParent, nWinStyle ),
726 : m_nWidth( 5 ),
727 : m_sNone( ),
728 : aVirDev( VclPtr<VirtualDevice>::Create() ),
729 : aColor( COL_BLACK ),
730 0 : maPaintCol( COL_BLACK )
731 : {
732 0 : ImplInit();
733 0 : }
734 :
735 0 : VCL_BUILDER_DECL_FACTORY(LineListBox)
736 : {
737 0 : bool bDropdown = VclBuilder::extractDropdown(rMap);
738 0 : WinBits nWinBits = WB_LEFT|WB_VCENTER|WB_3DLOOK|WB_TABSTOP;
739 0 : if (bDropdown)
740 0 : nWinBits |= WB_DROPDOWN;
741 0 : VclPtrInstance<LineListBox> pListBox(pParent, nWinBits);
742 0 : if (bDropdown)
743 0 : pListBox->EnableAutoSize(true);
744 0 : rRet = pListBox;
745 0 : }
746 :
747 0 : LineListBox::~LineListBox()
748 : {
749 0 : disposeOnce();
750 0 : }
751 :
752 0 : void LineListBox::dispose()
753 : {
754 0 : for ( size_t i = 0, n = pLineList->size(); i < n; ++i ) {
755 0 : if ( (*pLineList)[ i ] ) {
756 0 : delete (*pLineList)[ i ];
757 : }
758 : }
759 0 : pLineList->clear();
760 0 : delete pLineList;
761 0 : ListBox::dispose();
762 0 : }
763 :
764 0 : sal_Int32 LineListBox::GetStylePos( sal_Int32 nListPos, long nWidth )
765 : {
766 0 : sal_Int32 nPos = LISTBOX_ENTRY_NOTFOUND;
767 0 : if (!m_sNone.isEmpty())
768 0 : nListPos--;
769 :
770 0 : sal_Int32 n = 0;
771 0 : size_t i = 0;
772 0 : size_t nCount = pLineList->size();
773 0 : while ( nPos == LISTBOX_ENTRY_NOTFOUND && i < nCount )
774 : {
775 0 : ImpLineListData* pData = (*pLineList)[ i ];
776 0 : if ( pData && pData->GetMinWidth() <= nWidth )
777 : {
778 0 : if ( nListPos == n )
779 0 : nPos = static_cast<sal_Int32>(i);
780 0 : n++;
781 : }
782 0 : i++;
783 : }
784 :
785 0 : return nPos;
786 : }
787 :
788 0 : void LineListBox::SelectEntry( sal_uInt16 nStyle, bool bSelect )
789 : {
790 0 : sal_Int32 nPos = GetEntryPos( nStyle );
791 0 : if ( nPos != LISTBOX_ENTRY_NOTFOUND )
792 0 : ListBox::SelectEntryPos( nPos, bSelect );
793 0 : }
794 :
795 0 : void LineListBox::InsertEntry(
796 : const BorderWidthImpl& rWidthImpl, sal_uInt16 nStyle, long nMinWidth,
797 : ColorFunc pColor1Fn, ColorFunc pColor2Fn, ColorDistFunc pColorDistFn )
798 : {
799 : ImpLineListData* pData = new ImpLineListData(
800 0 : rWidthImpl, nStyle, nMinWidth, pColor1Fn, pColor2Fn, pColorDistFn);
801 0 : pLineList->push_back( pData );
802 0 : }
803 :
804 0 : sal_Int32 LineListBox::GetEntryPos( sal_uInt16 nStyle ) const
805 : {
806 0 : for ( size_t i = 0, n = pLineList->size(); i < n; ++i ) {
807 0 : ImpLineListData* pData = (*pLineList)[ i ];
808 0 : if ( pData )
809 : {
810 0 : if ( GetEntryStyle( i ) == nStyle )
811 : {
812 0 : size_t nPos = i;
813 0 : if (!m_sNone.isEmpty())
814 0 : nPos ++;
815 0 : return (sal_Int32)nPos;
816 : }
817 : }
818 : }
819 0 : return LISTBOX_ENTRY_NOTFOUND;
820 : }
821 :
822 0 : sal_uInt16 LineListBox::GetEntryStyle( sal_Int32 nPos ) const
823 : {
824 0 : ImpLineListData* pData = (0 <= nPos && static_cast<size_t>(nPos) < pLineList->size()) ? (*pLineList)[ nPos ] : NULL;
825 0 : return ( pData ) ? pData->GetStyle() : table::BorderLineStyle::NONE;
826 : }
827 :
828 0 : bool LineListBox::UpdatePaintLineColor()
829 : {
830 0 : const StyleSettings& rSettings = GetSettings().GetStyleSettings();
831 0 : Color aNewCol( rSettings.GetWindowColor().IsDark()? rSettings.GetLabelTextColor() : aColor );
832 :
833 0 : bool bRet = aNewCol != maPaintCol;
834 :
835 0 : if( bRet )
836 0 : maPaintCol = aNewCol;
837 :
838 0 : return bRet;
839 : }
840 :
841 0 : void LineListBox::UpdateEntries( long nOldWidth )
842 : {
843 0 : SetUpdateMode( false );
844 :
845 0 : UpdatePaintLineColor( );
846 :
847 0 : sal_Int32 nSelEntry = GetSelectEntryPos();
848 0 : sal_Int32 nTypePos = GetStylePos( nSelEntry, nOldWidth );
849 :
850 : // Remove the old entries
851 0 : while ( GetEntryCount( ) > 0 )
852 0 : ListBox::RemoveEntry( 0 );
853 :
854 : // Add the new entries based on the defined width
855 0 : if (!m_sNone.isEmpty())
856 0 : ListBox::InsertEntry( m_sNone, LISTBOX_APPEND );
857 :
858 0 : sal_uInt16 n = 0;
859 0 : sal_uInt16 nCount = pLineList->size( );
860 0 : while ( n < nCount )
861 : {
862 0 : ImpLineListData* pData = (*pLineList)[ n ];
863 0 : if ( pData && pData->GetMinWidth() <= m_nWidth )
864 : {
865 0 : Bitmap aBmp;
866 : ImpGetLine( pData->GetLine1ForWidth( m_nWidth ),
867 : pData->GetLine2ForWidth( m_nWidth ),
868 : pData->GetDistForWidth( m_nWidth ),
869 : GetColorLine1( GetEntryCount( ) ),
870 : GetColorLine2( GetEntryCount( ) ),
871 : GetColorDist( GetEntryCount( ) ),
872 0 : pData->GetStyle(), aBmp );
873 0 : ListBox::InsertEntry(OUString(" "), Image(aBmp), LISTBOX_APPEND);
874 0 : if ( n == nTypePos )
875 0 : SelectEntryPos( GetEntryCount() - 1 );
876 : }
877 0 : else if ( n == nTypePos )
878 0 : SetNoSelection();
879 0 : n++;
880 : }
881 :
882 0 : SetUpdateMode( true );
883 0 : Invalidate();
884 0 : }
885 :
886 0 : Color LineListBox::GetColorLine1( sal_Int32 nPos )
887 : {
888 0 : Color rResult = GetPaintColor( );
889 :
890 0 : sal_uInt16 nStyle = GetStylePos( nPos, m_nWidth );
891 0 : ImpLineListData* pData = (*pLineList)[ nStyle ];
892 0 : if ( pData )
893 0 : rResult = pData->GetColorLine1( GetColor( ) );
894 :
895 0 : return rResult;
896 : }
897 :
898 0 : Color LineListBox::GetColorLine2( sal_Int32 nPos )
899 : {
900 0 : Color rResult = GetPaintColor( );
901 :
902 0 : sal_uInt16 nStyle = GetStylePos( nPos, m_nWidth );
903 0 : ImpLineListData* pData = (*pLineList)[ nStyle ];
904 0 : if ( pData )
905 0 : rResult = pData->GetColorLine2( GetColor( ) );
906 :
907 0 : return rResult;
908 : }
909 :
910 0 : Color LineListBox::GetColorDist( sal_Int32 nPos )
911 : {
912 0 : Color rResult = GetSettings().GetStyleSettings().GetFieldColor();
913 :
914 0 : sal_uInt16 nStyle = GetStylePos( nPos, m_nWidth );
915 0 : ImpLineListData* pData = (*pLineList)[ nStyle ];
916 0 : if ( pData )
917 0 : rResult = pData->GetColorDist( GetColor( ), rResult );
918 :
919 0 : return rResult;
920 : }
921 :
922 0 : void LineListBox::DataChanged( const DataChangedEvent& rDCEvt )
923 : {
924 0 : ListBox::DataChanged( rDCEvt );
925 :
926 0 : if( ( rDCEvt.GetType() == DataChangedEventType::SETTINGS ) && ( rDCEvt.GetFlags() & AllSettingsFlags::STYLE ) )
927 0 : UpdateEntries( m_nWidth );
928 0 : }
929 :
930 986 : FontNameBox::FontNameBox( vcl::Window* pParent, WinBits nWinStyle ) :
931 986 : ComboBox( pParent, nWinStyle )
932 : {
933 986 : mpFontList = NULL;
934 986 : mbWYSIWYG = false;
935 986 : InitFontMRUEntriesFile();
936 986 : }
937 :
938 0 : VCL_BUILDER_DECL_FACTORY(FontNameBox)
939 : {
940 0 : bool bDropdown = VclBuilder::extractDropdown(rMap);
941 0 : WinBits nWinBits = WB_LEFT|WB_VCENTER|WB_3DLOOK|WB_TABSTOP;
942 0 : if (bDropdown)
943 0 : nWinBits |= WB_DROPDOWN;
944 0 : VclPtrInstance<FontNameBox> pListBox(pParent, nWinBits);
945 0 : if (bDropdown)
946 0 : pListBox->EnableAutoSize(true);
947 0 : rRet = pListBox;
948 0 : }
949 :
950 1972 : FontNameBox::~FontNameBox()
951 : {
952 986 : disposeOnce();
953 986 : }
954 :
955 986 : void FontNameBox::dispose()
956 : {
957 986 : if (mpFontList)
958 : {
959 981 : SaveMRUEntries (maFontMRUEntriesFile);
960 981 : ImplDestroyFontList();
961 : }
962 986 : ComboBox::dispose();
963 986 : }
964 :
965 981 : void FontNameBox::SaveMRUEntries( const OUString& aFontMRUEntriesFile, sal_Unicode cSep ) const
966 : {
967 : OString aEntries(OUStringToOString(GetMRUEntries(cSep),
968 981 : RTL_TEXTENCODING_UTF8));
969 :
970 981 : if (aEntries.isEmpty() || aFontMRUEntriesFile.isEmpty())
971 981 : return;
972 :
973 0 : SvFileStream aStream;
974 0 : aStream.Open( aFontMRUEntriesFile, StreamMode::WRITE | StreamMode::TRUNC );
975 0 : if( ! (aStream.IsOpen() && aStream.IsWritable()) )
976 : {
977 : SAL_INFO("svtools.control", "FontNameBox::SaveMRUEntries: opening mru entries file " << aFontMRUEntriesFile << " failed\n");
978 0 : return;
979 : }
980 :
981 0 : aStream.SetLineDelimiter( LINEEND_LF );
982 0 : aStream.WriteLine( aEntries );
983 0 : aStream.WriteLine( OString() );
984 : }
985 :
986 981 : void FontNameBox::LoadMRUEntries( const OUString& aFontMRUEntriesFile, sal_Unicode cSep )
987 : {
988 981 : if( aFontMRUEntriesFile.isEmpty() )
989 981 : return;
990 :
991 981 : SvFileStream aStream( aFontMRUEntriesFile, StreamMode::READ );
992 981 : if( ! aStream.IsOpen() )
993 : {
994 : SAL_INFO("svtools.control", "FontNameBox::LoadMRUEntries: opening mru entries file " << aFontMRUEntriesFile << " failed\n");
995 981 : return;
996 : }
997 :
998 0 : OString aLine;
999 0 : aStream.ReadLine( aLine );
1000 : OUString aEntries = OStringToOUString(aLine,
1001 0 : RTL_TEXTENCODING_UTF8);
1002 0 : SetMRUEntries( aEntries, cSep );
1003 : }
1004 :
1005 986 : void FontNameBox::InitFontMRUEntriesFile()
1006 : {
1007 986 : OUString sUserConfigDir("${$BRAND_BASE_DIR/" LIBO_ETC_FOLDER "/" SAL_CONFIGFILE( "bootstrap") "::UserInstallation}");
1008 986 : rtl::Bootstrap::expandMacros(sUserConfigDir);
1009 :
1010 986 : maFontMRUEntriesFile = sUserConfigDir;
1011 986 : if( !maFontMRUEntriesFile.isEmpty() )
1012 : {
1013 986 : maFontMRUEntriesFile += FONTNAMEBOXMRUENTRIESFILE;
1014 986 : }
1015 986 : }
1016 :
1017 1962 : void FontNameBox::ImplDestroyFontList()
1018 : {
1019 1962 : delete mpFontList;
1020 1962 : mpFontList = NULL;
1021 1962 : }
1022 :
1023 981 : void FontNameBox::Fill( const FontList* pList )
1024 : {
1025 : // store old text and clear box
1026 981 : OUString aOldText = GetText();
1027 1962 : OUString rEntries = GetMRUEntries();
1028 981 : bool bLoadFromFile = rEntries.isEmpty();
1029 981 : Clear();
1030 :
1031 981 : ImplDestroyFontList();
1032 981 : mpFontList = new ImplFontList;
1033 :
1034 : // insert fonts
1035 981 : sal_uInt16 nFontCount = pList->GetFontNameCount();
1036 85347 : for ( sal_uInt16 i = 0; i < nFontCount; i++ )
1037 : {
1038 84366 : const vcl::FontInfo& rFontInfo = pList->GetFontName( i );
1039 84366 : sal_uLong nIndex = InsertEntry( rFontInfo.GetName() );
1040 84366 : if ( nIndex != LISTBOX_ERROR )
1041 : {
1042 84366 : if ( nIndex < mpFontList->size() ) {
1043 0 : ImplFontList::iterator it = mpFontList->begin();
1044 0 : ::std::advance( it, nIndex );
1045 0 : mpFontList->insert( it, rFontInfo );
1046 : } else {
1047 84366 : mpFontList->push_back( rFontInfo );
1048 : }
1049 : }
1050 : }
1051 :
1052 981 : if ( bLoadFromFile )
1053 981 : LoadMRUEntries (maFontMRUEntriesFile);
1054 : else
1055 0 : SetMRUEntries( rEntries );
1056 :
1057 981 : ImplCalcUserItemSize();
1058 :
1059 : // restore text
1060 981 : if (!aOldText.isEmpty())
1061 1962 : SetText( aOldText );
1062 981 : }
1063 :
1064 986 : void FontNameBox::EnableWYSIWYG( bool bEnable )
1065 : {
1066 986 : if ( bEnable != mbWYSIWYG )
1067 : {
1068 986 : mbWYSIWYG = bEnable;
1069 986 : EnableUserDraw( mbWYSIWYG );
1070 986 : ImplCalcUserItemSize();
1071 : }
1072 986 : }
1073 :
1074 1967 : void FontNameBox::ImplCalcUserItemSize()
1075 : {
1076 1967 : Size aUserItemSz;
1077 1967 : if ( mbWYSIWYG && mpFontList )
1078 : {
1079 981 : aUserItemSz = Size(MAXPREVIEWWIDTH, GetTextHeight() );
1080 981 : aUserItemSz.Height() *= 16;
1081 981 : aUserItemSz.Height() /= 10;
1082 : }
1083 1967 : SetUserItemSize( aUserItemSz );
1084 1967 : }
1085 :
1086 : namespace
1087 : {
1088 0 : long shrinkFontToFit(OUString &rSampleText, long nH, vcl::Font &rFont, OutputDevice &rDevice, Rectangle &rTextRect)
1089 : {
1090 0 : long nWidth = 0;
1091 :
1092 0 : Size aSize( rFont.GetSize() );
1093 :
1094 : //Make sure it fits in the available height
1095 0 : while (aSize.Height() > 0)
1096 : {
1097 0 : if (!rDevice.GetTextBoundRect(rTextRect, rSampleText, 0, 0))
1098 0 : break;
1099 0 : if (rTextRect.GetHeight() <= nH)
1100 : {
1101 0 : nWidth = rTextRect.GetWidth();
1102 0 : break;
1103 : }
1104 :
1105 0 : aSize.Height() -= EXTRAFONTSIZE;
1106 0 : rFont.SetSize(aSize);
1107 0 : rDevice.SetFont(rFont);
1108 : }
1109 :
1110 0 : return nWidth;
1111 : }
1112 : }
1113 :
1114 0 : void FontNameBox::UserDraw( const UserDrawEvent& rUDEvt )
1115 : {
1116 : assert( mpFontList );
1117 :
1118 0 : vcl::FontInfo& rInfo = (*mpFontList)[ rUDEvt.GetItemId() ];
1119 0 : Point aTopLeft = rUDEvt.GetRect().TopLeft();
1120 0 : long nX = aTopLeft.X();
1121 0 : long nH = rUDEvt.GetRect().GetHeight();
1122 :
1123 0 : if ( mbWYSIWYG )
1124 : {
1125 0 : nX += IMGOUTERTEXTSPACE;
1126 :
1127 0 : const bool bSymbolFont = isSymbolFont(rInfo);
1128 :
1129 0 : Color aTextColor = rUDEvt.GetDevice()->GetTextColor();
1130 0 : vcl::Font aOldFont( rUDEvt.GetDevice()->GetFont() );
1131 0 : Size aSize( aOldFont.GetSize() );
1132 0 : aSize.Height() += EXTRAFONTSIZE;
1133 0 : vcl::Font aFont( rInfo );
1134 0 : aFont.SetSize( aSize );
1135 0 : rUDEvt.GetDevice()->SetFont( aFont );
1136 0 : rUDEvt.GetDevice()->SetTextColor( aTextColor );
1137 :
1138 0 : bool bUsingCorrectFont = true;
1139 0 : Rectangle aTextRect;
1140 :
1141 : // Preview the font name
1142 0 : OUString sFontName = rInfo.GetName();
1143 :
1144 : //If it shouldn't or can't draw its own name because it doesn't have the glyphs
1145 0 : if (!canRenderNameOfSelectedFont(*rUDEvt.GetDevice()))
1146 0 : bUsingCorrectFont = false;
1147 : else
1148 : {
1149 : //Make sure it fits in the available height, shrinking the font if necessary
1150 0 : bUsingCorrectFont = shrinkFontToFit(sFontName, nH, aFont, *rUDEvt.GetDevice(), aTextRect) != 0;
1151 : }
1152 :
1153 0 : if (!bUsingCorrectFont)
1154 : {
1155 0 : rUDEvt.GetDevice()->SetFont(aOldFont);
1156 0 : rUDEvt.GetDevice()->GetTextBoundRect(aTextRect, sFontName, 0, 0);
1157 : }
1158 :
1159 0 : long nTextHeight = aTextRect.GetHeight();
1160 0 : long nDesiredGap = (nH-nTextHeight)/2;
1161 0 : long nVertAdjust = nDesiredGap - aTextRect.Top();
1162 0 : Point aPos( nX, aTopLeft.Y() + nVertAdjust );
1163 0 : rUDEvt.GetDevice()->DrawText( aPos, sFontName );
1164 0 : long nTextX = aPos.X() + aTextRect.GetWidth() + GAPTOEXTRAPREVIEW;
1165 :
1166 0 : if (!bUsingCorrectFont)
1167 0 : rUDEvt.GetDevice()->SetFont( aFont );
1168 :
1169 0 : OUString sSampleText;
1170 :
1171 0 : if (!bSymbolFont)
1172 : {
1173 0 : const bool bNameBeginsWithLatinText = rInfo.GetName()[0] <= 'z';
1174 :
1175 0 : if (bNameBeginsWithLatinText || !bUsingCorrectFont)
1176 0 : sSampleText = makeShortRepresentativeTextForSelectedFont(*rUDEvt.GetDevice());
1177 : }
1178 :
1179 : //If we're not a symbol font, but could neither render our own name and
1180 : //we can't determine what script it would like to render, then try a
1181 : //few well known scripts
1182 0 : if (sSampleText.isEmpty() && !bUsingCorrectFont)
1183 : {
1184 : static const UScriptCode aScripts[] =
1185 : {
1186 : USCRIPT_ARABIC,
1187 : USCRIPT_HEBREW,
1188 :
1189 : USCRIPT_BENGALI,
1190 : USCRIPT_GURMUKHI,
1191 : USCRIPT_GUJARATI,
1192 : USCRIPT_ORIYA,
1193 : USCRIPT_TAMIL,
1194 : USCRIPT_TELUGU,
1195 : USCRIPT_KANNADA,
1196 : USCRIPT_MALAYALAM,
1197 : USCRIPT_SINHALA,
1198 : USCRIPT_DEVANAGARI,
1199 :
1200 : USCRIPT_THAI,
1201 : USCRIPT_LAO,
1202 : USCRIPT_GEORGIAN,
1203 : USCRIPT_TIBETAN,
1204 : USCRIPT_SYRIAC,
1205 : USCRIPT_MYANMAR,
1206 : USCRIPT_ETHIOPIC,
1207 : USCRIPT_KHMER,
1208 : USCRIPT_MONGOLIAN,
1209 :
1210 : USCRIPT_KOREAN,
1211 : USCRIPT_JAPANESE,
1212 : USCRIPT_HAN,
1213 : USCRIPT_SIMPLIFIED_HAN,
1214 : USCRIPT_TRADITIONAL_HAN,
1215 :
1216 : USCRIPT_GREEK
1217 : };
1218 :
1219 0 : for (size_t i = 0; i < SAL_N_ELEMENTS(aScripts); ++i)
1220 : {
1221 0 : OUString sText = makeShortRepresentativeTextForScript(aScripts[i]);
1222 0 : if (!sText.isEmpty())
1223 : {
1224 0 : bool bHasSampleTextGlyphs = (-1 == rUDEvt.GetDevice()->HasGlyphs(aFont, sText));
1225 0 : if (bHasSampleTextGlyphs)
1226 : {
1227 0 : sSampleText = sText;
1228 0 : break;
1229 : }
1230 : }
1231 0 : }
1232 :
1233 : static const UScriptCode aMinimalScripts[] =
1234 : {
1235 : USCRIPT_HEBREW, //e.g. biblical hebrew
1236 : USCRIPT_GREEK
1237 : };
1238 :
1239 0 : for (size_t i = 0; i < SAL_N_ELEMENTS(aMinimalScripts); ++i)
1240 : {
1241 0 : OUString sText = makeShortMinimalTextForScript(aMinimalScripts[i]);
1242 0 : if (!sText.isEmpty())
1243 : {
1244 0 : bool bHasSampleTextGlyphs = (-1 == rUDEvt.GetDevice()->HasGlyphs(aFont, sText));
1245 0 : if (bHasSampleTextGlyphs)
1246 : {
1247 0 : sSampleText = sText;
1248 0 : break;
1249 : }
1250 : }
1251 0 : }
1252 : }
1253 :
1254 : //If we're a symbol font, or for some reason the font still couldn't
1255 : //render something representative of what it would like to render then
1256 : //make up some semi-random text that it *can* display
1257 0 : if (bSymbolFont || (!bUsingCorrectFont && sSampleText.isEmpty()))
1258 0 : sSampleText = makeShortRepresentativeSymbolTextForSelectedFont(*rUDEvt.GetDevice());
1259 :
1260 0 : if (!sSampleText.isEmpty())
1261 : {
1262 0 : const Size &rItemSize = rUDEvt.GetDevice()->GetOutputSize();
1263 : //leave a little border at the edge
1264 0 : long nSpace = rItemSize.Width() - nTextX - IMGOUTERTEXTSPACE;
1265 0 : if (nSpace >= 0)
1266 : {
1267 : //Make sure it fits in the available height, and get how wide that would be
1268 0 : long nWidth = shrinkFontToFit(sSampleText, nH, aFont, *rUDEvt.GetDevice(), aTextRect);
1269 : //Chop letters off until it fits in the available width
1270 0 : while (nWidth > nSpace || nWidth > MAXPREVIEWWIDTH)
1271 : {
1272 0 : sSampleText = sSampleText.copy(0, sSampleText.getLength()-1);
1273 0 : nWidth = rUDEvt.GetDevice()->GetTextBoundRect(aTextRect, sSampleText, 0, 0) ?
1274 0 : aTextRect.GetWidth() : 0;
1275 : }
1276 :
1277 : //center the text on the line
1278 0 : if (!sSampleText.isEmpty() && nWidth)
1279 : {
1280 0 : nTextHeight = aTextRect.GetHeight();
1281 0 : nDesiredGap = (nH-nTextHeight)/2;
1282 0 : nVertAdjust = nDesiredGap - aTextRect.Top();
1283 0 : aPos = Point(nTextX + nSpace - nWidth, aTopLeft.Y() + nVertAdjust);
1284 0 : rUDEvt.GetDevice()->DrawText( aPos, sSampleText );
1285 : }
1286 : }
1287 : }
1288 :
1289 0 : rUDEvt.GetDevice()->SetFont( aOldFont );
1290 0 : DrawEntry( rUDEvt, false, false); // draw separator
1291 : }
1292 : else
1293 : {
1294 0 : DrawEntry( rUDEvt, true, true );
1295 : }
1296 0 : }
1297 :
1298 0 : FontStyleBox::FontStyleBox(vcl::Window* pParent, WinBits nBits)
1299 0 : : ComboBox(pParent, nBits)
1300 : {
1301 : //Use the standard texts to get an optimal size and stick to that size.
1302 : //That should stop the character dialog dancing around.
1303 0 : InsertEntry(SVT_RESSTR(STR_SVT_STYLE_LIGHT));
1304 0 : InsertEntry(SVT_RESSTR(STR_SVT_STYLE_LIGHT_ITALIC));
1305 0 : InsertEntry(SVT_RESSTR(STR_SVT_STYLE_NORMAL));
1306 0 : InsertEntry(SVT_RESSTR(STR_SVT_STYLE_NORMAL_ITALIC));
1307 0 : InsertEntry(SVT_RESSTR(STR_SVT_STYLE_BOLD));
1308 0 : InsertEntry(SVT_RESSTR(STR_SVT_STYLE_BOLD_ITALIC));
1309 0 : InsertEntry(SVT_RESSTR(STR_SVT_STYLE_BLACK));
1310 0 : InsertEntry(SVT_RESSTR(STR_SVT_STYLE_BLACK_ITALIC));
1311 0 : aOptimalSize = GetOptimalSize();
1312 0 : Clear();
1313 0 : }
1314 :
1315 0 : Size FontStyleBox::GetOptimalSize() const
1316 : {
1317 0 : if (aOptimalSize.Width() || aOptimalSize.Height())
1318 0 : return aOptimalSize;
1319 0 : return ComboBox::GetOptimalSize();
1320 : }
1321 :
1322 0 : VCL_BUILDER_DECL_FACTORY(FontStyleBox)
1323 : {
1324 0 : bool bDropdown = VclBuilder::extractDropdown(rMap);
1325 0 : WinBits nWinBits = WB_LEFT|WB_VCENTER|WB_3DLOOK|WB_TABSTOP;
1326 0 : if (bDropdown)
1327 0 : nWinBits |= WB_DROPDOWN;
1328 0 : VclPtrInstance<FontStyleBox> pListBox(pParent, nWinBits);
1329 0 : if (bDropdown)
1330 0 : pListBox->EnableAutoSize(true);
1331 0 : rRet = pListBox;
1332 0 : }
1333 :
1334 0 : void FontStyleBox::Select()
1335 : {
1336 : // keep text over fill operation
1337 0 : aLastStyle = GetText();
1338 0 : ComboBox::Select();
1339 0 : }
1340 :
1341 0 : void FontStyleBox::LoseFocus()
1342 : {
1343 : // keep text over fill operation
1344 0 : aLastStyle = GetText();
1345 0 : ComboBox::LoseFocus();
1346 0 : }
1347 :
1348 0 : void FontStyleBox::Modify()
1349 : {
1350 : CharClass aChrCls( ::comphelper::getProcessComponentContext(),
1351 0 : GetSettings().GetLanguageTag() );
1352 0 : OUString aStr = GetText();
1353 0 : sal_Int32 nEntryCount = GetEntryCount();
1354 :
1355 0 : if ( GetEntryPos( aStr ) == COMBOBOX_ENTRY_NOTFOUND )
1356 : {
1357 0 : aStr = aChrCls.uppercase(aStr);
1358 0 : for ( sal_Int32 i = 0; i < nEntryCount; i++ )
1359 : {
1360 0 : OUString aEntryText = aChrCls.uppercase(GetEntry(i));
1361 :
1362 0 : if ( aStr == aEntryText )
1363 : {
1364 0 : SetText( GetEntry( i ) );
1365 0 : break;
1366 : }
1367 0 : }
1368 : }
1369 :
1370 0 : ComboBox::Modify();
1371 0 : }
1372 :
1373 0 : void FontStyleBox::Fill( const OUString& rName, const FontList* pList )
1374 : {
1375 : // note: this method must call ComboBox::SetText(),
1376 : // else aLastStyle will overwritten
1377 : // store prior selection position and clear box
1378 0 : OUString aOldText = GetText();
1379 0 : sal_Int32 nPos = GetEntryPos( aOldText );
1380 0 : Clear();
1381 :
1382 : // does a font with this name already exist?
1383 0 : sal_Handle hFontInfo = pList->GetFirstFontInfo( rName );
1384 0 : if ( hFontInfo )
1385 : {
1386 0 : OUString aStyleText;
1387 0 : FontWeight eLastWeight = WEIGHT_DONTKNOW;
1388 0 : FontItalic eLastItalic = ITALIC_NONE;
1389 0 : FontWidth eLastWidth = WIDTH_DONTKNOW;
1390 0 : bool bNormal = false;
1391 0 : bool bItalic = false;
1392 0 : bool bBold = false;
1393 0 : bool bBoldItalic = false;
1394 0 : bool bInsert = false;
1395 0 : vcl::FontInfo aInfo;
1396 0 : while ( hFontInfo )
1397 : {
1398 0 : aInfo = FontList::GetFontInfo( hFontInfo );
1399 :
1400 0 : FontWeight eWeight = aInfo.GetWeight();
1401 0 : FontItalic eItalic = aInfo.GetItalic();
1402 0 : FontWidth eWidth = aInfo.GetWidthType();
1403 : // Only if the attributes are different, we insert the
1404 : // Font to avoid double Entries in different languages
1405 0 : if ( (eWeight != eLastWeight) || (eItalic != eLastItalic) ||
1406 : (eWidth != eLastWidth) )
1407 : {
1408 0 : if ( bInsert )
1409 0 : InsertEntry( aStyleText );
1410 :
1411 0 : if ( eWeight <= WEIGHT_NORMAL )
1412 : {
1413 0 : if ( eItalic != ITALIC_NONE )
1414 0 : bItalic = true;
1415 : else
1416 0 : bNormal = true;
1417 : }
1418 : else
1419 : {
1420 0 : if ( eItalic != ITALIC_NONE )
1421 0 : bBoldItalic = true;
1422 : else
1423 0 : bBold = true;
1424 : }
1425 :
1426 : // For wrong StyleNames we replace this with the correct once
1427 0 : aStyleText = pList->GetStyleName( aInfo );
1428 0 : bInsert = GetEntryPos( aStyleText ) == LISTBOX_ENTRY_NOTFOUND;
1429 0 : if ( !bInsert )
1430 : {
1431 0 : aStyleText = pList->GetStyleName( eWeight, eItalic );
1432 0 : bInsert = GetEntryPos( aStyleText ) == LISTBOX_ENTRY_NOTFOUND;
1433 : }
1434 :
1435 0 : eLastWeight = eWeight;
1436 0 : eLastItalic = eItalic;
1437 0 : eLastWidth = eWidth;
1438 : }
1439 : else
1440 : {
1441 0 : if ( bInsert )
1442 : {
1443 : // If we have two names for the same attributes
1444 : // we prefer the translated standard names
1445 0 : const OUString& rAttrStyleText = pList->GetStyleName( eWeight, eItalic );
1446 0 : if (rAttrStyleText != aStyleText)
1447 : {
1448 0 : OUString aTempStyleText = pList->GetStyleName( aInfo );
1449 0 : if (rAttrStyleText == aTempStyleText)
1450 0 : aStyleText = rAttrStyleText;
1451 0 : bInsert = GetEntryPos( aStyleText ) == LISTBOX_ENTRY_NOTFOUND;
1452 : }
1453 : }
1454 : }
1455 :
1456 0 : if ( !bItalic && (aStyleText == pList->GetItalicStr()) )
1457 0 : bItalic = true;
1458 0 : else if ( !bBold && (aStyleText == pList->GetBoldStr()) )
1459 0 : bBold = true;
1460 0 : else if ( !bBoldItalic && (aStyleText == pList->GetBoldItalicStr()) )
1461 0 : bBoldItalic = true;
1462 :
1463 0 : hFontInfo = FontList::GetNextFontInfo( hFontInfo );
1464 : }
1465 :
1466 0 : if ( bInsert )
1467 0 : InsertEntry( aStyleText );
1468 :
1469 : // certain style as copy
1470 0 : if ( bNormal )
1471 : {
1472 0 : if ( !bItalic )
1473 0 : InsertEntry( pList->GetItalicStr() );
1474 0 : if ( !bBold )
1475 0 : InsertEntry( pList->GetBoldStr() );
1476 : }
1477 0 : if ( !bBoldItalic )
1478 : {
1479 0 : if ( bNormal || bItalic || bBold )
1480 0 : InsertEntry( pList->GetBoldItalicStr() );
1481 : }
1482 0 : if (!aOldText.isEmpty())
1483 : {
1484 0 : if ( GetEntryPos( aLastStyle ) != LISTBOX_ENTRY_NOTFOUND )
1485 0 : ComboBox::SetText( aLastStyle );
1486 : else
1487 : {
1488 0 : if ( nPos >= GetEntryCount() )
1489 0 : ComboBox::SetText( GetEntry( 0 ) );
1490 : else
1491 0 : ComboBox::SetText( GetEntry( nPos ) );
1492 : }
1493 0 : }
1494 : }
1495 : else
1496 : {
1497 : // insert standard styles if no font
1498 0 : InsertEntry( pList->GetNormalStr() );
1499 0 : InsertEntry( pList->GetItalicStr() );
1500 0 : InsertEntry( pList->GetBoldStr() );
1501 0 : InsertEntry( pList->GetBoldItalicStr() );
1502 0 : if (!aOldText.isEmpty())
1503 : {
1504 0 : if ( nPos > GetEntryCount() )
1505 0 : ComboBox::SetText( GetEntry( 0 ) );
1506 : else
1507 0 : ComboBox::SetText( GetEntry( nPos ) );
1508 : }
1509 0 : }
1510 0 : }
1511 :
1512 986 : FontSizeBox::FontSizeBox( vcl::Window* pParent, WinBits nWinSize ) :
1513 986 : MetricBox( pParent, nWinSize )
1514 : {
1515 986 : ImplInit();
1516 986 : }
1517 :
1518 0 : VCL_BUILDER_DECL_FACTORY(FontSizeBox)
1519 : {
1520 0 : bool bDropdown = VclBuilder::extractDropdown(rMap);
1521 0 : WinBits nWinBits = WB_LEFT|WB_VCENTER|WB_3DLOOK|WB_TABSTOP;
1522 0 : if (bDropdown)
1523 0 : nWinBits |= WB_DROPDOWN;
1524 0 : VclPtrInstance<FontSizeBox> pListBox(pParent, nWinBits);
1525 0 : if (bDropdown)
1526 0 : pListBox->EnableAutoSize(true);
1527 0 : rRet = pListBox;
1528 0 : }
1529 :
1530 986 : void FontSizeBox::ImplInit()
1531 : {
1532 986 : EnableAutocomplete( false );
1533 :
1534 986 : bRelativeMode = false;
1535 986 : bPtRelative = false;
1536 986 : bRelative = false;
1537 986 : bStdSize = false;
1538 986 : pFontList = NULL;
1539 :
1540 986 : SetShowTrailingZeros( false );
1541 986 : SetDecimalDigits( 1 );
1542 986 : SetMin( 20 );
1543 986 : SetMax( 9999 );
1544 986 : SetProminentEntryType( ProminentEntry::MIDDLE );
1545 986 : }
1546 :
1547 0 : void FontSizeBox::Reformat()
1548 : {
1549 0 : FontSizeNames aFontSizeNames( GetSettings().GetUILanguageTag().getLanguageType() );
1550 0 : if ( !bRelativeMode || !aFontSizeNames.IsEmpty() )
1551 : {
1552 0 : long nNewValue = aFontSizeNames.Name2Size( GetText() );
1553 0 : if ( nNewValue)
1554 : {
1555 0 : mnLastValue = nNewValue;
1556 0 : return;
1557 : }
1558 : }
1559 :
1560 0 : MetricBox::Reformat();
1561 : }
1562 :
1563 0 : void FontSizeBox::Modify()
1564 : {
1565 0 : MetricBox::Modify();
1566 :
1567 0 : if ( bRelativeMode )
1568 : {
1569 0 : OUString aStr = comphelper::string::stripStart(GetText(), ' ');
1570 :
1571 0 : bool bNewMode = bRelative;
1572 0 : bool bOldPtRelMode = bPtRelative;
1573 :
1574 0 : if ( bRelative )
1575 : {
1576 0 : bPtRelative = false;
1577 0 : const sal_Unicode* pStr = aStr.getStr();
1578 0 : while ( *pStr )
1579 : {
1580 0 : if ( ((*pStr < '0') || (*pStr > '9')) && (*pStr != '%') && !unicode::isSpace(*pStr) )
1581 : {
1582 0 : if ( ('-' == *pStr || '+' == *pStr) && !bPtRelative )
1583 0 : bPtRelative = true;
1584 0 : else if ( bPtRelative && 'p' == *pStr && 't' == *++pStr )
1585 : ;
1586 : else
1587 : {
1588 0 : bNewMode = false;
1589 0 : break;
1590 : }
1591 : }
1592 0 : pStr++;
1593 : }
1594 : }
1595 : else
1596 : {
1597 0 : if ( -1 != aStr.indexOf('%') )
1598 : {
1599 0 : bNewMode = true;
1600 0 : bPtRelative = false;
1601 : }
1602 :
1603 0 : if ( '-' == aStr[0] || '+' == aStr[0] )
1604 : {
1605 0 : bNewMode = true;
1606 0 : bPtRelative = true;
1607 : }
1608 : }
1609 :
1610 0 : if ( bNewMode != bRelative || bPtRelative != bOldPtRelMode )
1611 0 : SetRelative( bNewMode );
1612 : }
1613 0 : }
1614 :
1615 2659 : void FontSizeBox::Fill( const vcl::FontInfo* pInfo, const FontList* pList )
1616 : {
1617 : // remember for relative mode
1618 2659 : pFontList = pList;
1619 :
1620 : // no font sizes need to be set for relative mode
1621 2659 : if ( bRelative )
1622 1673 : return;
1623 :
1624 : // query font sizes
1625 : const sal_IntPtr* pTempAry;
1626 2659 : const sal_IntPtr* pAry = 0;
1627 :
1628 2659 : if( pInfo )
1629 : {
1630 1673 : aFontInfo = *pInfo;
1631 1673 : pAry = pList->GetSizeAry( *pInfo );
1632 : }
1633 : else
1634 : {
1635 986 : pAry = FontList::GetStdSizeAry();
1636 : }
1637 :
1638 : // first insert font size names (for simplified/traditional chinese)
1639 2659 : FontSizeNames aFontSizeNames( GetSettings().GetUILanguageTag().getLanguageType() );
1640 2659 : if ( pAry == FontList::GetStdSizeAry() )
1641 : {
1642 : // for standard sizes we don't need to bother
1643 2659 : if ( bStdSize && GetEntryCount() && aFontSizeNames.IsEmpty() )
1644 1673 : return;
1645 986 : bStdSize = true;
1646 : }
1647 : else
1648 0 : bStdSize = false;
1649 :
1650 986 : Selection aSelection = GetSelection();
1651 986 : OUString aStr = GetText();
1652 :
1653 986 : Clear();
1654 986 : sal_Int32 nPos = 0;
1655 :
1656 986 : if ( !aFontSizeNames.IsEmpty() )
1657 : {
1658 0 : if ( pAry == FontList::GetStdSizeAry() )
1659 : {
1660 : // for scalable fonts all font size names
1661 0 : sal_uLong nCount = aFontSizeNames.Count();
1662 0 : for( sal_uLong i = 0; i < nCount; i++ )
1663 : {
1664 0 : OUString aSizeName = aFontSizeNames.GetIndexName( i );
1665 0 : sal_IntPtr nSize = aFontSizeNames.GetIndexSize( i );
1666 0 : ComboBox::InsertEntry( aSizeName, nPos );
1667 0 : ComboBox::SetEntryData( nPos, reinterpret_cast<void*>(-nSize) ); // mark as special
1668 0 : nPos++;
1669 0 : }
1670 : }
1671 : else
1672 : {
1673 : // for fixed size fonts only selectable font size names
1674 0 : pTempAry = pAry;
1675 0 : while ( *pTempAry )
1676 : {
1677 0 : OUString aSizeName = aFontSizeNames.Size2Name( *pTempAry );
1678 0 : if ( !aSizeName.isEmpty() )
1679 : {
1680 0 : ComboBox::InsertEntry( aSizeName, nPos );
1681 0 : ComboBox::SetEntryData( nPos, reinterpret_cast<void*>(-(*pTempAry)) ); // mark as special
1682 0 : nPos++;
1683 : }
1684 0 : pTempAry++;
1685 0 : }
1686 : }
1687 : }
1688 :
1689 : // then insert numerical font size values
1690 986 : pTempAry = pAry;
1691 31552 : while ( *pTempAry )
1692 : {
1693 29580 : InsertValue( *pTempAry, FUNIT_NONE, nPos );
1694 29580 : ComboBox::SetEntryData( nPos, reinterpret_cast<void*>(*pTempAry) );
1695 29580 : nPos++;
1696 29580 : pTempAry++;
1697 : }
1698 :
1699 986 : SetText( aStr );
1700 986 : SetSelection( aSelection );
1701 : }
1702 :
1703 0 : void FontSizeBox::EnableRelativeMode( sal_uInt16 nMin, sal_uInt16 nMax, sal_uInt16 nStep )
1704 : {
1705 0 : bRelativeMode = true;
1706 0 : nRelMin = nMin;
1707 0 : nRelMax = nMax;
1708 0 : nRelStep = nStep;
1709 0 : SetUnit( FUNIT_POINT );
1710 0 : }
1711 :
1712 0 : void FontSizeBox::EnablePtRelativeMode( short nMin, short nMax, short nStep )
1713 : {
1714 0 : bRelativeMode = true;
1715 0 : nPtRelMin = nMin;
1716 0 : nPtRelMax = nMax;
1717 0 : nPtRelStep = nStep;
1718 0 : SetUnit( FUNIT_POINT );
1719 0 : }
1720 :
1721 0 : void FontSizeBox::SetRelative( bool bNewRelative )
1722 : {
1723 0 : if ( bRelativeMode )
1724 : {
1725 0 : Selection aSelection = GetSelection();
1726 0 : OUString aStr = comphelper::string::stripStart(GetText(), ' ');
1727 :
1728 0 : if ( bNewRelative )
1729 : {
1730 0 : bRelative = true;
1731 0 : bStdSize = false;
1732 :
1733 0 : if ( bPtRelative )
1734 : {
1735 0 : Clear(); //clear early because SetDecimalDigits is a slow recalc
1736 :
1737 0 : SetDecimalDigits( 1 );
1738 0 : SetMin( nPtRelMin );
1739 0 : SetMax( nPtRelMax );
1740 0 : SetUnit( FUNIT_POINT );
1741 :
1742 0 : short i = nPtRelMin, n = 0;
1743 : // JP 30.06.98: more than 100 values are not useful
1744 0 : while ( i <= nPtRelMax && n++ < 100 )
1745 : {
1746 0 : InsertValue( i );
1747 0 : i = i + nPtRelStep;
1748 : }
1749 : }
1750 : else
1751 : {
1752 0 : Clear(); //clear early because SetDecimalDigits is a slow recalc
1753 :
1754 0 : SetDecimalDigits( 0 );
1755 0 : SetMin( nRelMin );
1756 0 : SetMax( nRelMax );
1757 0 : SetUnit( FUNIT_PERCENT );
1758 :
1759 0 : sal_uInt16 i = nRelMin;
1760 0 : while ( i <= nRelMax )
1761 : {
1762 0 : InsertValue( i );
1763 0 : i = i + nRelStep;
1764 : }
1765 : }
1766 : }
1767 : else
1768 : {
1769 0 : if (pFontList)
1770 0 : Clear(); //clear early because SetDecimalDigits is a slow recalc
1771 0 : bRelative = bPtRelative = false;
1772 0 : SetDecimalDigits( 1 );
1773 0 : SetMin( 20 );
1774 0 : SetMax( 9999 );
1775 0 : SetUnit( FUNIT_POINT );
1776 0 : if ( pFontList )
1777 0 : Fill( &aFontInfo, pFontList );
1778 : }
1779 :
1780 0 : SetText( aStr );
1781 0 : SetSelection( aSelection );
1782 : }
1783 0 : }
1784 :
1785 40132 : OUString FontSizeBox::CreateFieldText( sal_Int64 nValue ) const
1786 : {
1787 40132 : OUString sRet( MetricBox::CreateFieldText( nValue ) );
1788 40132 : if ( bRelativeMode && bPtRelative && (0 <= nValue) && !sRet.isEmpty() )
1789 0 : sRet = "+" + sRet;
1790 40132 : return sRet;
1791 : }
1792 :
1793 4636 : void FontSizeBox::SetValue( sal_Int64 nNewValue, FieldUnit eInUnit )
1794 : {
1795 4636 : if ( !bRelative )
1796 : {
1797 4636 : sal_Int64 nTempValue = MetricField::ConvertValue( nNewValue, GetBaseValue(), GetDecimalDigits(), eInUnit, GetUnit() );
1798 4636 : FontSizeNames aFontSizeNames( GetSettings().GetUILanguageTag().getLanguageType() );
1799 : // conversion loses precision; however font sizes should
1800 : // never have a problem with that
1801 4636 : OUString aName = aFontSizeNames.Size2Name( static_cast<long>(nTempValue) );
1802 4636 : if ( !aName.isEmpty() && (GetEntryPos( aName ) != LISTBOX_ENTRY_NOTFOUND) )
1803 : {
1804 0 : mnLastValue = nTempValue;
1805 0 : SetText( aName );
1806 0 : mnFieldValue = mnLastValue;
1807 0 : SetEmptyFieldValueData( false );
1808 4636 : return;
1809 4636 : }
1810 : }
1811 :
1812 4636 : MetricBox::SetValue( nNewValue, eInUnit );
1813 : }
1814 :
1815 4636 : void FontSizeBox::SetValue( sal_Int64 nNewValue )
1816 : {
1817 4636 : SetValue( nNewValue, FUNIT_NONE );
1818 4636 : }
1819 :
1820 4338 : sal_Int64 FontSizeBox::GetValue( FieldUnit eOutUnit ) const
1821 : {
1822 4338 : if ( !bRelative )
1823 : {
1824 4338 : FontSizeNames aFontSizeNames( GetSettings().GetUILanguageTag().getLanguageType() );
1825 4338 : sal_Int64 nValue = aFontSizeNames.Name2Size( GetText() );
1826 4338 : if ( nValue)
1827 0 : return MetricField::ConvertValue( nValue, GetBaseValue(), GetDecimalDigits(), GetUnit(), eOutUnit );
1828 : }
1829 :
1830 4338 : return MetricBox::GetValue( eOutUnit );
1831 : }
1832 :
1833 4338 : sal_Int64 FontSizeBox::GetValue() const
1834 : {
1835 : // implementation not inline, because it is a virtual function
1836 4338 : return GetValue( FUNIT_NONE );
1837 798 : }
1838 :
1839 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|