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