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