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 66912 : BorderWidthImpl::BorderWidthImpl( sal_uInt16 nFlags, double nRate1, double nRate2, double nRateGap ):
315 : m_nFlags( nFlags ),
316 : m_nRate1( nRate1 ),
317 : m_nRate2( nRate2 ),
318 66912 : m_nRateGap( nRateGap )
319 : {
320 66912 : }
321 :
322 58442 : BorderWidthImpl& BorderWidthImpl::operator= ( const BorderWidthImpl& r )
323 : {
324 58442 : m_nFlags = r.m_nFlags;
325 58442 : m_nRate1 = r.m_nRate1;
326 58442 : m_nRate2 = r.m_nRate2;
327 58442 : m_nRateGap = r.m_nRateGap;
328 58442 : return *this;
329 : }
330 :
331 39286 : 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 39286 : ( m_nRateGap == r.m_nRateGap );
337 : }
338 :
339 5314 : long BorderWidthImpl::GetLine1( long nWidth ) const
340 : {
341 5314 : long result = static_cast<long>(m_nRate1);
342 5314 : if ( ( m_nFlags & CHANGE_LINE1 ) > 0 )
343 : {
344 4947 : long const nConstant2 = (m_nFlags & CHANGE_LINE2) ? 0 : m_nRate2;
345 4947 : 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 4947 : - (nConstant2 + nConstantD));
349 4947 : 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 5314 : return result;
355 : }
356 :
357 8096 : long BorderWidthImpl::GetLine2( long nWidth ) const
358 : {
359 8096 : long result = static_cast<long>(m_nRate2);
360 8096 : if ( ( m_nFlags & CHANGE_LINE2 ) > 0 )
361 : {
362 590 : long const nConstant1 = (m_nFlags & CHANGE_LINE1) ? 0 : m_nRate1;
363 590 : 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 590 : - (nConstant1 + nConstantD));
367 : }
368 8096 : return result;
369 : }
370 :
371 5274 : long BorderWidthImpl::GetGap( long nWidth ) const
372 : {
373 5274 : long result = static_cast<long>(m_nRateGap);
374 5274 : if ( ( m_nFlags & CHANGE_DIST ) > 0 )
375 : {
376 824 : long const nConstant1 = (m_nFlags & CHANGE_LINE1) ? 0 : m_nRate1;
377 824 : 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 824 : - (nConstant1 + nConstant2));
381 : }
382 :
383 : // Avoid having too small distances (less than 0.1pt)
384 5274 : if ( result < MINGAPWIDTH && m_nRate1 > 0 && m_nRate2 > 0 )
385 0 : result = MINGAPWIDTH;
386 :
387 5274 : return result;
388 : }
389 :
390 5490 : static double lcl_getGuessedWidth( long nTested, double nRate, bool nChanging )
391 : {
392 5490 : double nWidth = -1.0;
393 5490 : if ( nChanging )
394 2338 : nWidth = double( nTested ) / nRate;
395 : else
396 : {
397 3152 : if ( double( nTested ) == nRate )
398 2534 : nWidth = nRate;
399 : }
400 :
401 5490 : return nWidth;
402 : }
403 :
404 1830 : long BorderWidthImpl::GuessWidth( long nLine1, long nLine2, long nGap )
405 : {
406 1830 : std::vector< double > aToCompare;
407 1830 : bool bInvalid = false;
408 :
409 1830 : bool bLine1Change = ( m_nFlags & CHANGE_LINE1 ) > 0;
410 1830 : double nWidth1 = lcl_getGuessedWidth( nLine1, m_nRate1, bLine1Change );
411 1830 : if ( bLine1Change )
412 1597 : aToCompare.push_back( nWidth1 );
413 233 : else if ( !bLine1Change && nWidth1 < 0 )
414 231 : bInvalid = true;
415 :
416 1830 : bool bLine2Change = ( m_nFlags & CHANGE_LINE2 ) > 0;
417 1830 : double nWidth2 = lcl_getGuessedWidth( nLine2, m_nRate2, bLine2Change );
418 1830 : if ( bLine2Change )
419 331 : aToCompare.push_back( nWidth2 );
420 1499 : else if ( !bLine2Change && nWidth2 < 0 )
421 231 : bInvalid = true;
422 :
423 1830 : bool bGapChange = ( m_nFlags & CHANGE_DIST ) > 0;
424 1830 : double nWidthGap = lcl_getGuessedWidth( nGap, m_nRateGap, bGapChange );
425 1830 : if ( bGapChange && nGap > MINGAPWIDTH )
426 410 : aToCompare.push_back( nWidthGap );
427 1420 : else if ( !bGapChange && nWidthGap < 0 )
428 156 : 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 1830 : double nWidth = 0.0;
436 1830 : if ( (!bInvalid) && (!aToCompare.empty()) )
437 : {
438 1520 : nWidth = *aToCompare.begin();
439 1520 : std::vector< double >::iterator pIt = aToCompare.begin();
440 4850 : while ( pIt != aToCompare.end() && !bInvalid )
441 : {
442 1810 : bInvalid = ( nWidth != *pIt );
443 1810 : ++pIt;
444 : }
445 1520 : nWidth = (bInvalid) ? 0.0 : nLine1 + nLine2 + nGap;
446 : }
447 :
448 1830 : 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 96 : std::vector < double > GetDashing( sal_uInt16 nDashing, MapUnit eUnit )
580 : {
581 96 : ::std::vector < double >aPattern;
582 96 : 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 96 : break;
627 : }
628 :
629 96 : 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 96 : basegfx::B2DPolyPolygon ApplyLineDashing( const basegfx::B2DPolygon& rPolygon, sal_uInt16 nDashing, MapUnit eUnit, double fScale )
645 : {
646 96 : std::vector< double > aPattern = GetDashing( nDashing, eUnit );
647 96 : std::vector< double >::iterator i = aPattern.begin();
648 192 : while( i != aPattern.end() ) {
649 0 : (*i) *= fScale;
650 0 : ++i;
651 : }
652 :
653 96 : basegfx::B2DPolyPolygon aPolygons;
654 96 : if ( ! aPattern.empty() )
655 0 : basegfx::tools::applyLineDashing( rPolygon, aPattern, &aPolygons );
656 : else
657 96 : aPolygons.append( rPolygon );
658 :
659 96 : 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 : //TODO, rather than including the " " text to force
684 : //the line height, better would be do drop
685 : //this calculation and draw a bitmap of height
686 : //equal to normal text line and center the
687 : //line within that
688 0 : long nMinWidth = GetTextWidth(OUString("----------"));
689 0 : Size aSize = CalcSubEditSize();
690 0 : aSize.Width() = std::max(nMinWidth, aSize.Width());
691 0 : aSize.Width() -= aTxtSize.Width();
692 0 : aSize.Width() -= 6;
693 0 : aSize.Height() = aTxtSize.Height();
694 :
695 : // SourceUnit nach Twips
696 0 : if ( eSourceUnit == FUNIT_POINT )
697 : {
698 0 : nLine1 /= 5;
699 0 : nLine2 /= 5;
700 0 : nDistance /= 5;
701 : }
702 :
703 : // Linien malen
704 0 : aSize = aVirDev.PixelToLogic( aSize );
705 0 : long nPix = aVirDev.PixelToLogic( Size( 0, 1 ) ).Height();
706 0 : sal_uInt32 n1 = nLine1;
707 0 : sal_uInt32 n2 = nLine2;
708 0 : long nDist = nDistance;
709 0 : n1 += nPix-1;
710 0 : n1 -= n1%nPix;
711 0 : if ( n2 )
712 : {
713 0 : nDist += nPix-1;
714 0 : nDist -= nDist%nPix;
715 0 : n2 += nPix-1;
716 0 : n2 -= n2%nPix;
717 : }
718 0 : long nVirHeight = n1+nDist+n2;
719 0 : if ( nVirHeight > aSize.Height() )
720 0 : aSize.Height() = nVirHeight;
721 : // negative Breiten muss und darf man nicht painten
722 0 : if ( aSize.Width() > 0 )
723 : {
724 0 : Size aVirSize = aVirDev.LogicToPixel( aSize );
725 0 : if ( aVirDev.GetOutputSizePixel() != aVirSize )
726 0 : aVirDev.SetOutputSizePixel( aVirSize );
727 0 : aVirDev.SetFillColor( aColorDist );
728 0 : aVirDev.DrawRect( Rectangle( Point(), aSize ) );
729 :
730 0 : aVirDev.SetFillColor( aColor1 );
731 :
732 0 : double y1 = double( n1 ) / 2;
733 0 : svtools::DrawLine( aVirDev, basegfx::B2DPoint( 0, y1 ), basegfx::B2DPoint( aSize.Width( ), y1 ), n1, nStyle );
734 :
735 0 : if ( n2 )
736 : {
737 0 : double y2 = n1 + nDist + double( n2 ) / 2;
738 0 : aVirDev.SetFillColor( aColor2 );
739 0 : svtools::DrawLine( aVirDev, basegfx::B2DPoint( 0, y2 ), basegfx::B2DPoint( aSize.Width(), y2 ), n2, STYLE_SOLID );
740 : }
741 0 : rBmp = aVirDev.GetBitmap( Point(), Size( aSize.Width(), n1+nDist+n2 ) );
742 : }
743 0 : }
744 :
745 : // -----------------------------------------------------------------------
746 :
747 0 : void LineListBox::ImplInit()
748 : {
749 0 : aTxtSize.Width() = GetTextWidth( rtl::OUString( " " ) );
750 0 : aTxtSize.Height() = GetTextHeight();
751 0 : pLineList = new ImpLineList();
752 0 : eUnit = FUNIT_POINT;
753 0 : eSourceUnit = FUNIT_POINT;
754 :
755 0 : aVirDev.SetLineColor();
756 0 : aVirDev.SetMapMode( MapMode( MAP_TWIP ) );
757 :
758 0 : UpdatePaintLineColor();
759 0 : }
760 :
761 : // -----------------------------------------------------------------------
762 :
763 0 : LineListBox::LineListBox( Window* pParent, WinBits nWinStyle ) :
764 : ListBox( pParent, nWinStyle ),
765 : m_nWidth( 5 ),
766 : m_sNone( ),
767 : aColor( COL_BLACK ),
768 0 : maPaintCol( COL_BLACK )
769 : {
770 0 : ImplInit();
771 0 : }
772 :
773 0 : extern "C" SAL_DLLPUBLIC_EXPORT Window* SAL_CALL makeLineListBox(Window *pParent, VclBuilder::stringmap &rMap)
774 : {
775 0 : bool bDropdown = extractDropdown(rMap);
776 0 : WinBits nWinBits = WB_LEFT|WB_VCENTER|WB_3DLOOK|WB_TABSTOP;
777 0 : if (bDropdown)
778 0 : nWinBits |= WB_DROPDOWN;
779 0 : LineListBox *pListBox = new LineListBox(pParent, nWinBits);
780 0 : if (bDropdown)
781 0 : pListBox->EnableAutoSize(true);
782 0 : return pListBox;
783 : }
784 :
785 : // -----------------------------------------------------------------------
786 :
787 0 : LineListBox::LineListBox( Window* pParent, const ResId& rResId ) :
788 : ListBox( pParent, rResId ),
789 : m_nWidth( 5 ),
790 : m_sNone( ),
791 : aColor( COL_BLACK ),
792 0 : maPaintCol( COL_BLACK )
793 : {
794 0 : ImplInit();
795 0 : }
796 :
797 : // -----------------------------------------------------------------------
798 :
799 0 : LineListBox::~LineListBox()
800 : {
801 0 : for ( size_t i = 0, n = pLineList->size(); i < n; ++i ) {
802 0 : if ( (*pLineList)[ i ] ) {
803 0 : delete (*pLineList)[ i ];
804 : }
805 : }
806 0 : pLineList->clear();
807 0 : delete pLineList;
808 0 : }
809 :
810 0 : sal_uInt16 LineListBox::GetStylePos( sal_uInt16 nListPos, long nWidth )
811 : {
812 0 : sal_uInt16 nPos = LISTBOX_ENTRY_NOTFOUND;
813 0 : if ( m_sNone.Len( ) > 0 )
814 0 : nListPos--;
815 :
816 0 : sal_uInt16 i = 0;
817 0 : sal_uInt16 n = 0;
818 0 : sal_uInt16 nCount = pLineList->size();
819 0 : while ( nPos == LISTBOX_ENTRY_NOTFOUND && i < nCount )
820 : {
821 0 : ImpLineListData* pData = (*pLineList)[ i ];
822 0 : if ( pData && pData->GetMinWidth() <= nWidth )
823 : {
824 0 : if ( nListPos == n )
825 0 : nPos = i;
826 0 : n++;
827 : }
828 0 : i++;
829 : }
830 :
831 0 : return nPos;
832 : }
833 :
834 :
835 0 : void LineListBox::SelectEntry( sal_uInt16 nStyle, sal_Bool bSelect )
836 : {
837 0 : sal_uInt16 nPos = GetEntryPos( nStyle );
838 0 : if ( nPos != LISTBOX_ENTRY_NOTFOUND )
839 0 : ListBox::SelectEntryPos( nPos, bSelect );
840 0 : }
841 :
842 : // -----------------------------------------------------------------------
843 :
844 0 : sal_uInt16 LineListBox::InsertEntry( const XubString& rStr, sal_uInt16 nPos )
845 : {
846 0 : nPos = ListBox::InsertEntry( rStr, nPos );
847 0 : if ( nPos != LISTBOX_ERROR ) {
848 0 : if ( nPos < pLineList->size() ) {
849 0 : ImpLineList::iterator it = pLineList->begin();
850 0 : ::std::advance( it, nPos );
851 0 : pLineList->insert( it, reinterpret_cast<ImpLineListData *>(NULL) );
852 : } else {
853 0 : pLineList->push_back( NULL );
854 : }
855 : }
856 0 : return nPos;
857 : }
858 :
859 : // -----------------------------------------------------------------------
860 :
861 0 : void LineListBox::InsertEntry(
862 : BorderWidthImpl aWidthImpl,
863 : sal_uInt16 nStyle, long nMinWidth,
864 : Color ( *pColor1Fn )( Color ), Color ( *pColor2Fn )( Color ),
865 : Color ( *pColorDistFn )( Color, Color ) )
866 : {
867 : ImpLineListData* pData = new ImpLineListData(
868 : aWidthImpl, nStyle, nMinWidth,
869 0 : pColor1Fn, pColor2Fn, pColorDistFn );
870 0 : pLineList->push_back( pData );
871 0 : }
872 :
873 : // -----------------------------------------------------------------------
874 :
875 0 : void LineListBox::RemoveEntry( sal_uInt16 nPos )
876 : {
877 0 : ListBox::RemoveEntry( nPos );
878 :
879 0 : if ( nPos < pLineList->size() ) {
880 0 : ImpLineList::iterator it = pLineList->begin();
881 0 : ::std::advance( it, nPos );
882 0 : if ( *it ) delete *it;
883 0 : pLineList->erase( it );
884 : }
885 0 : }
886 :
887 : // -----------------------------------------------------------------------
888 :
889 0 : void LineListBox::Clear()
890 : {
891 0 : for ( size_t i = 0, n = pLineList->size(); i < n; ++i ) {
892 0 : if ( (*pLineList)[ i ] ) {
893 0 : delete (*pLineList)[ i ];
894 : }
895 : }
896 0 : pLineList->clear();
897 :
898 0 : ListBox::Clear();
899 0 : }
900 :
901 : // -----------------------------------------------------------------------
902 :
903 0 : sal_uInt16 LineListBox::GetEntryPos( sal_uInt16 nStyle ) const
904 : {
905 0 : for ( size_t i = 0, n = pLineList->size(); i < n; ++i ) {
906 0 : ImpLineListData* pData = (*pLineList)[ i ];
907 0 : if ( pData )
908 : {
909 0 : if ( GetEntryStyle( i ) == nStyle )
910 : {
911 0 : size_t nPos = i;
912 0 : if ( m_sNone.Len() > 0 )
913 0 : nPos ++;
914 0 : return (sal_uInt16)nPos;
915 : }
916 : }
917 : }
918 0 : return LISTBOX_ENTRY_NOTFOUND;
919 : }
920 :
921 : // -----------------------------------------------------------------------
922 :
923 0 : sal_uInt16 LineListBox::GetEntryStyle( sal_uInt16 nPos ) const
924 : {
925 0 : ImpLineListData* pData = (nPos < pLineList->size()) ? (*pLineList)[ nPos ] : NULL;
926 0 : return ( pData ) ? pData->GetStyle() : STYLE_NONE;
927 : }
928 :
929 : // -----------------------------------------------------------------------
930 :
931 0 : sal_Bool LineListBox::UpdatePaintLineColor( void )
932 : {
933 0 : sal_Bool bRet = sal_True;
934 0 : const StyleSettings& rSettings = GetSettings().GetStyleSettings();
935 0 : Color aNewCol( rSettings.GetWindowColor().IsDark()? rSettings.GetLabelTextColor() : aColor );
936 :
937 0 : bRet = aNewCol != maPaintCol;
938 :
939 0 : if( bRet )
940 0 : maPaintCol = aNewCol;
941 :
942 0 : return bRet;
943 : }
944 :
945 0 : void LineListBox::UpdateEntries( long nOldWidth )
946 : {
947 0 : SetUpdateMode( sal_False );
948 :
949 0 : UpdatePaintLineColor( );
950 :
951 0 : sal_uInt16 nSelEntry = GetSelectEntryPos();
952 0 : sal_uInt16 nTypePos = GetStylePos( nSelEntry, nOldWidth );
953 :
954 : // Remove the old entries
955 0 : while ( GetEntryCount( ) > 0 )
956 0 : ListBox::RemoveEntry( 0 );
957 :
958 : // Add the new entries based on the defined width
959 0 : if ( m_sNone.Len( ) > 0 )
960 0 : ListBox::InsertEntry( m_sNone, LISTBOX_APPEND );
961 :
962 0 : sal_uInt16 n = 0;
963 0 : sal_uInt16 nCount = pLineList->size( );
964 0 : while ( n < nCount )
965 : {
966 0 : ImpLineListData* pData = (*pLineList)[ n ];
967 0 : if ( pData && pData->GetMinWidth() <= m_nWidth )
968 : {
969 0 : Bitmap aBmp;
970 : ImpGetLine( pData->GetLine1ForWidth( m_nWidth ),
971 : pData->GetLine2ForWidth( m_nWidth ),
972 : pData->GetDistForWidth( m_nWidth ),
973 0 : GetColorLine1( GetEntryCount( ) ),
974 0 : GetColorLine2( GetEntryCount( ) ),
975 0 : GetColorDist( GetEntryCount( ) ),
976 0 : pData->GetStyle(), aBmp );
977 0 : ListBox::InsertEntry( rtl::OUString( " " ), aBmp, LISTBOX_APPEND );
978 0 : if ( n == nTypePos )
979 0 : SelectEntryPos( GetEntryCount() - 1 );
980 : }
981 0 : else if ( n == nTypePos )
982 0 : SetNoSelection();
983 0 : n++;
984 : }
985 :
986 0 : SetUpdateMode( sal_True );
987 0 : Invalidate();
988 0 : }
989 :
990 : // -----------------------------------------------------------------------
991 :
992 0 : Color LineListBox::GetColorLine1( sal_uInt16 nPos )
993 : {
994 0 : Color rResult = GetPaintColor( );
995 :
996 0 : sal_uInt16 nStyle = GetStylePos( nPos, m_nWidth );
997 0 : ImpLineListData* pData = (*pLineList)[ nStyle ];
998 0 : if ( pData )
999 0 : rResult = pData->GetColorLine1( GetColor( ) );
1000 :
1001 0 : return rResult;
1002 : }
1003 :
1004 0 : Color LineListBox::GetColorLine2( sal_uInt16 nPos )
1005 : {
1006 0 : Color rResult = GetPaintColor( );
1007 :
1008 0 : sal_uInt16 nStyle = GetStylePos( nPos, m_nWidth );
1009 0 : ImpLineListData* pData = (*pLineList)[ nStyle ];
1010 0 : if ( pData )
1011 0 : rResult = pData->GetColorLine2( GetColor( ) );
1012 :
1013 0 : return rResult;
1014 : }
1015 :
1016 0 : Color LineListBox::GetColorDist( sal_uInt16 nPos )
1017 : {
1018 0 : Color rResult = GetSettings().GetStyleSettings().GetFieldColor();
1019 :
1020 0 : sal_uInt16 nStyle = GetStylePos( nPos, m_nWidth );
1021 0 : ImpLineListData* pData = (*pLineList)[ nStyle ];
1022 0 : if ( pData )
1023 0 : rResult = pData->GetColorDist( GetColor( ), rResult );
1024 :
1025 0 : return rResult;
1026 : }
1027 :
1028 : // -----------------------------------------------------------------------
1029 :
1030 0 : void LineListBox::DataChanged( const DataChangedEvent& rDCEvt )
1031 : {
1032 0 : ListBox::DataChanged( rDCEvt );
1033 :
1034 0 : if( ( rDCEvt.GetType() == DATACHANGED_SETTINGS ) && ( rDCEvt.GetFlags() & SETTINGS_STYLE ) )
1035 0 : UpdateEntries( m_nWidth );
1036 0 : }
1037 :
1038 :
1039 : // ===================================================================
1040 : // FontNameBox
1041 : // ===================================================================
1042 :
1043 0 : FontNameBox::FontNameBox( Window* pParent, WinBits nWinStyle ) :
1044 0 : ComboBox( pParent, nWinStyle )
1045 : {
1046 0 : mpFontList = NULL;
1047 0 : mbWYSIWYG = sal_False;
1048 0 : InitFontMRUEntriesFile();
1049 0 : }
1050 :
1051 : // -------------------------------------------------------------------
1052 :
1053 0 : FontNameBox::FontNameBox( Window* pParent, const ResId& rResId ) :
1054 0 : ComboBox( pParent, rResId )
1055 : {
1056 0 : mpFontList = NULL;
1057 0 : mbWYSIWYG = sal_False;
1058 0 : InitFontMRUEntriesFile();
1059 0 : }
1060 :
1061 0 : extern "C" SAL_DLLPUBLIC_EXPORT Window* SAL_CALL makeFontNameBox(Window *pParent, VclBuilder::stringmap &rMap)
1062 : {
1063 0 : bool bDropdown = extractDropdown(rMap);
1064 0 : WinBits nWinBits = WB_LEFT|WB_VCENTER|WB_3DLOOK|WB_TABSTOP;
1065 0 : if (bDropdown)
1066 0 : nWinBits |= WB_DROPDOWN;
1067 0 : FontNameBox *pListBox = new FontNameBox(pParent, nWinBits);
1068 0 : if (bDropdown)
1069 0 : pListBox->EnableAutoSize(true);
1070 0 : return pListBox;
1071 : }
1072 :
1073 : // -------------------------------------------------------------------
1074 :
1075 0 : FontNameBox::~FontNameBox()
1076 : {
1077 0 : SaveMRUEntries (maFontMRUEntriesFile);
1078 0 : ImplDestroyFontList();
1079 0 : }
1080 :
1081 : // -------------------------------------------------------------------
1082 :
1083 0 : void FontNameBox::SaveMRUEntries( const String& aFontMRUEntriesFile, sal_Unicode cSep ) const
1084 : {
1085 : rtl::OString aEntries(rtl::OUStringToOString(GetMRUEntries(cSep),
1086 0 : RTL_TEXTENCODING_UTF8));
1087 :
1088 0 : if (aEntries.isEmpty() || !aFontMRUEntriesFile.Len())
1089 : return;
1090 :
1091 0 : SvFileStream aStream;
1092 0 : aStream.Open( aFontMRUEntriesFile, STREAM_WRITE | STREAM_TRUNC );
1093 0 : if( ! (aStream.IsOpen() && aStream.IsWritable()) )
1094 : {
1095 : #if OSL_DEBUG_LEVEL > 1
1096 : fprintf( stderr, "FontNameBox::SaveMRUEntries: opening mru entries file %s failed\n", rtl::OUStringToOString(aFontMRUEntriesFile, RTL_TEXTENCODING_UTF8 ).getStr() );
1097 : #endif
1098 : return;
1099 : }
1100 :
1101 0 : aStream.SetLineDelimiter( LINEEND_LF );
1102 0 : aStream.WriteLine( aEntries );
1103 0 : aStream.WriteLine( rtl::OString() );
1104 : }
1105 :
1106 : // -------------------------------------------------------------------
1107 :
1108 0 : void FontNameBox::LoadMRUEntries( const String& aFontMRUEntriesFile, sal_Unicode cSep )
1109 : {
1110 0 : if( ! aFontMRUEntriesFile.Len() )
1111 : return;
1112 :
1113 0 : SvFileStream aStream( aFontMRUEntriesFile, STREAM_READ );
1114 0 : if( ! aStream.IsOpen() )
1115 : {
1116 : #if OSL_DEBUG_LEVEL > 1
1117 : fprintf( stderr, "FontNameBox::LoadMRUEntries: opening mru entries file %s failed\n", rtl::OUStringToOString(aFontMRUEntriesFile, RTL_TEXTENCODING_UTF8).getStr() );
1118 : #endif
1119 : return;
1120 : }
1121 :
1122 0 : rtl::OString aLine;
1123 0 : aStream.ReadLine( aLine );
1124 : rtl::OUString aEntries = rtl::OStringToOUString(aLine,
1125 0 : RTL_TEXTENCODING_UTF8);
1126 0 : SetMRUEntries( aEntries, cSep );
1127 : }
1128 :
1129 : // ------------------------------------------------------------------
1130 :
1131 0 : void FontNameBox::InitFontMRUEntriesFile()
1132 : {
1133 0 : rtl::OUString sUserConfigDir("${$BRAND_BASE_DIR/program/" SAL_CONFIGFILE( "bootstrap") "::UserInstallation}");
1134 0 : rtl::Bootstrap::expandMacros(sUserConfigDir);
1135 :
1136 0 : maFontMRUEntriesFile = sUserConfigDir;
1137 0 : if( maFontMRUEntriesFile.Len() )
1138 : {
1139 0 : maFontMRUEntriesFile.AppendAscii( FONTNAMEBOXMRUENTRIESFILE );
1140 0 : }
1141 0 : }
1142 :
1143 : // -------------------------------------------------------------------
1144 :
1145 0 : void FontNameBox::ImplDestroyFontList()
1146 : {
1147 0 : delete mpFontList;
1148 0 : }
1149 :
1150 : // -------------------------------------------------------------------
1151 :
1152 0 : void FontNameBox::Fill( const FontList* pList )
1153 : {
1154 : // store old text and clear box
1155 0 : XubString aOldText = GetText();
1156 0 : XubString rEntries = GetMRUEntries();
1157 0 : sal_Bool bLoadFromFile = ! rEntries.Len();
1158 0 : Clear();
1159 :
1160 0 : ImplDestroyFontList();
1161 0 : mpFontList = new ImplFontList;
1162 :
1163 : // insert fonts
1164 0 : sal_uInt16 nFontCount = pList->GetFontNameCount();
1165 0 : for ( sal_uInt16 i = 0; i < nFontCount; i++ )
1166 : {
1167 0 : const FontInfo& rFontInfo = pList->GetFontName( i );
1168 0 : sal_uLong nIndex = InsertEntry( rFontInfo.GetName() );
1169 0 : if ( nIndex != LISTBOX_ERROR )
1170 : {
1171 0 : if ( nIndex < mpFontList->size() ) {
1172 0 : ImplFontList::iterator it = mpFontList->begin();
1173 0 : ::std::advance( it, nIndex );
1174 0 : mpFontList->insert( it, rFontInfo );
1175 : } else {
1176 0 : mpFontList->push_back( rFontInfo );
1177 : }
1178 : }
1179 : }
1180 :
1181 0 : if ( bLoadFromFile )
1182 0 : LoadMRUEntries (maFontMRUEntriesFile);
1183 : else
1184 0 : SetMRUEntries( rEntries );
1185 :
1186 0 : ImplCalcUserItemSize();
1187 :
1188 : // restore text
1189 0 : if ( aOldText.Len() )
1190 0 : SetText( aOldText );
1191 0 : }
1192 :
1193 : // -------------------------------------------------------------------
1194 :
1195 0 : void FontNameBox::EnableWYSIWYG( sal_Bool bEnable )
1196 : {
1197 0 : if ( bEnable != mbWYSIWYG )
1198 : {
1199 0 : mbWYSIWYG = bEnable;
1200 0 : EnableUserDraw( mbWYSIWYG );
1201 0 : ImplCalcUserItemSize();
1202 : }
1203 0 : }
1204 :
1205 : // -------------------------------------------------------------------
1206 :
1207 0 : void FontNameBox::ImplCalcUserItemSize()
1208 : {
1209 0 : Size aUserItemSz;
1210 0 : if ( mbWYSIWYG && mpFontList )
1211 : {
1212 0 : aUserItemSz = Size(MAXPREVIEWWIDTH, GetTextHeight() );
1213 0 : aUserItemSz.Height() *= 16;
1214 0 : aUserItemSz.Height() /= 10;
1215 : }
1216 0 : SetUserItemSize( aUserItemSz );
1217 0 : }
1218 :
1219 : namespace
1220 : {
1221 0 : long shrinkFontToFit(rtl::OUString &rSampleText, long nH, Font &rFont, OutputDevice &rDevice, Rectangle &rTextRect)
1222 : {
1223 0 : long nWidth = 0;
1224 :
1225 0 : Size aSize( rFont.GetSize() );
1226 :
1227 : //Make sure it fits in the available height
1228 0 : while (aSize.Height() > 0)
1229 : {
1230 0 : if (!rDevice.GetTextBoundRect(rTextRect, rSampleText, 0, 0))
1231 0 : break;
1232 0 : if (rTextRect.GetHeight() <= nH)
1233 : {
1234 0 : nWidth = rTextRect.GetWidth();
1235 0 : break;
1236 : }
1237 :
1238 0 : aSize.Height() -= EXTRAFONTSIZE;
1239 0 : rFont.SetSize(aSize);
1240 0 : rDevice.SetFont(rFont);
1241 : }
1242 :
1243 0 : return nWidth;
1244 : }
1245 : }
1246 :
1247 : // -------------------------------------------------------------------
1248 :
1249 0 : void FontNameBox::UserDraw( const UserDrawEvent& rUDEvt )
1250 : {
1251 : assert( mpFontList );
1252 :
1253 0 : FontInfo& rInfo = (*mpFontList)[ rUDEvt.GetItemId() ];
1254 0 : Point aTopLeft = rUDEvt.GetRect().TopLeft();
1255 0 : long nX = aTopLeft.X();
1256 0 : long nH = rUDEvt.GetRect().GetHeight();
1257 :
1258 0 : if ( mbWYSIWYG )
1259 : {
1260 0 : nX += IMGOUTERTEXTSPACE;
1261 :
1262 0 : const bool bSymbolFont = isSymbolFont(rInfo);
1263 :
1264 0 : Color aTextColor = rUDEvt.GetDevice()->GetTextColor();
1265 0 : Font aOldFont( rUDEvt.GetDevice()->GetFont() );
1266 0 : Size aSize( aOldFont.GetSize() );
1267 0 : aSize.Height() += EXTRAFONTSIZE;
1268 0 : Font aFont( rInfo );
1269 0 : aFont.SetSize( aSize );
1270 0 : rUDEvt.GetDevice()->SetFont( aFont );
1271 0 : rUDEvt.GetDevice()->SetTextColor( aTextColor );
1272 :
1273 0 : bool bUsingCorrectFont = true;
1274 0 : Rectangle aTextRect;
1275 :
1276 : // Preview the font name
1277 0 : rtl::OUString sFontName = rInfo.GetName();
1278 :
1279 : //If it shouldn't or can't draw its own name because it doesn't have the glyphs
1280 0 : if (!canRenderNameOfSelectedFont(*rUDEvt.GetDevice()))
1281 0 : bUsingCorrectFont = false;
1282 : else
1283 : {
1284 : //Make sure it fits in the available height, shrinking the font if necessary
1285 0 : bUsingCorrectFont = shrinkFontToFit(sFontName, nH, aFont, *rUDEvt.GetDevice(), aTextRect) != 0;
1286 : }
1287 :
1288 0 : if (!bUsingCorrectFont)
1289 : {
1290 0 : rUDEvt.GetDevice()->SetFont(aOldFont);
1291 0 : rUDEvt.GetDevice()->GetTextBoundRect(aTextRect, sFontName, 0, 0);
1292 : }
1293 :
1294 0 : long nTextHeight = aTextRect.GetHeight();
1295 0 : long nDesiredGap = (nH-nTextHeight)/2;
1296 0 : long nVertAdjust = nDesiredGap - aTextRect.Top();
1297 0 : Point aPos( nX, aTopLeft.Y() + nVertAdjust );
1298 0 : rUDEvt.GetDevice()->DrawText( aPos, sFontName );
1299 0 : Rectangle aHack(aPos.X(), aTopLeft.Y() + nH/2 - 5, aPos.X() + 40, aTopLeft.Y() + nH/2 + 5);
1300 0 : long nTextX = aPos.X() + aTextRect.GetWidth() + GAPTOEXTRAPREVIEW;
1301 :
1302 0 : if (!bUsingCorrectFont)
1303 0 : rUDEvt.GetDevice()->SetFont( aFont );
1304 :
1305 0 : rtl::OUString sSampleText;
1306 :
1307 0 : if (!bSymbolFont)
1308 : {
1309 0 : const bool bNameBeginsWithLatinText = rInfo.GetName().GetChar(0) <= 'z';
1310 :
1311 0 : if (bNameBeginsWithLatinText || !bUsingCorrectFont)
1312 0 : sSampleText = makeShortRepresentativeTextForSelectedFont(*rUDEvt.GetDevice());
1313 : }
1314 :
1315 : //If we're not a symbol font, but could neither render our own name and
1316 : //we can't determine what script it would like to render, then try a
1317 : //few well known scripts
1318 0 : if (sSampleText.isEmpty() && !bUsingCorrectFont)
1319 : {
1320 : static const UScriptCode aScripts[] =
1321 : {
1322 : USCRIPT_ARABIC,
1323 : USCRIPT_HEBREW,
1324 :
1325 : USCRIPT_BENGALI,
1326 : USCRIPT_GURMUKHI,
1327 : USCRIPT_GUJARATI,
1328 : USCRIPT_ORIYA,
1329 : USCRIPT_TAMIL,
1330 : USCRIPT_TELUGU,
1331 : USCRIPT_KANNADA,
1332 : USCRIPT_MALAYALAM,
1333 : USCRIPT_SINHALA,
1334 : USCRIPT_DEVANAGARI,
1335 :
1336 : USCRIPT_THAI,
1337 : USCRIPT_LAO,
1338 : USCRIPT_GEORGIAN,
1339 : USCRIPT_TIBETAN,
1340 : USCRIPT_SYRIAC,
1341 : USCRIPT_MYANMAR,
1342 : USCRIPT_ETHIOPIC,
1343 : USCRIPT_KHMER,
1344 : USCRIPT_MONGOLIAN,
1345 :
1346 : USCRIPT_KOREAN,
1347 : USCRIPT_JAPANESE,
1348 : USCRIPT_HAN,
1349 : USCRIPT_SIMPLIFIED_HAN,
1350 : USCRIPT_TRADITIONAL_HAN,
1351 :
1352 : USCRIPT_GREEK
1353 : };
1354 :
1355 0 : for (size_t i = 0; i < SAL_N_ELEMENTS(aScripts); ++i)
1356 : {
1357 0 : rtl::OUString sText = makeShortRepresentativeTextForScript(aScripts[i]);
1358 0 : if (!sText.isEmpty())
1359 : {
1360 0 : bool bHasSampleTextGlyphs = (STRING_LEN == rUDEvt.GetDevice()->HasGlyphs(aFont, sText));
1361 0 : if (bHasSampleTextGlyphs)
1362 : {
1363 0 : sSampleText = sText;
1364 : break;
1365 : }
1366 : }
1367 0 : }
1368 :
1369 : static const UScriptCode aMinimalScripts[] =
1370 : {
1371 : USCRIPT_HEBREW, //e.g. biblical hebrew
1372 : USCRIPT_GREEK
1373 : };
1374 :
1375 0 : for (size_t i = 0; i < SAL_N_ELEMENTS(aMinimalScripts); ++i)
1376 : {
1377 0 : rtl::OUString sText = makeShortMinimalTextForScript(aMinimalScripts[i]);
1378 0 : if (!sText.isEmpty())
1379 : {
1380 0 : bool bHasSampleTextGlyphs = (STRING_LEN == rUDEvt.GetDevice()->HasGlyphs(aFont, sText));
1381 0 : if (bHasSampleTextGlyphs)
1382 : {
1383 0 : sSampleText = sText;
1384 : break;
1385 : }
1386 : }
1387 0 : }
1388 : }
1389 :
1390 : //If we're a symbol font, or for some reason the font still couldn't
1391 : //render something representative of what it would like to render then
1392 : //make up some semi-random text that it *can* display
1393 0 : if (bSymbolFont || (!bUsingCorrectFont && sSampleText.isEmpty()))
1394 0 : sSampleText = makeShortRepresentativeSymbolTextForSelectedFont(*rUDEvt.GetDevice());
1395 :
1396 0 : if (!sSampleText.isEmpty())
1397 : {
1398 0 : const Size &rItemSize = rUDEvt.GetDevice()->GetOutputSize();
1399 : //leave a little border at the edge
1400 0 : long nSpace = rItemSize.Width() - nTextX - IMGOUTERTEXTSPACE;
1401 0 : if (nSpace >= 0)
1402 : {
1403 : //Make sure it fits in the available height, and get how wide that would be
1404 0 : long nWidth = shrinkFontToFit(sSampleText, nH, aFont, *rUDEvt.GetDevice(), aTextRect);
1405 : //Chop letters off until it fits in the available width
1406 0 : while (nWidth > nSpace || nWidth > MAXPREVIEWWIDTH)
1407 : {
1408 0 : sSampleText = sSampleText.copy(0, sSampleText.getLength()-1);
1409 0 : nWidth = rUDEvt.GetDevice()->GetTextBoundRect(aTextRect, sSampleText, 0, 0) ?
1410 0 : aTextRect.GetWidth() : 0;
1411 : }
1412 :
1413 : //center the text on the line
1414 0 : if (!sSampleText.isEmpty() && nWidth)
1415 : {
1416 0 : nTextHeight = aTextRect.GetHeight();
1417 0 : nDesiredGap = (nH-nTextHeight)/2;
1418 0 : nVertAdjust = nDesiredGap - aTextRect.Top();
1419 0 : aPos = Point(nTextX + nSpace - nWidth, aTopLeft.Y() + nVertAdjust);
1420 0 : rUDEvt.GetDevice()->DrawText( aPos, sSampleText );
1421 : }
1422 : }
1423 : }
1424 :
1425 0 : rUDEvt.GetDevice()->SetFont( aOldFont );
1426 0 : DrawEntry( rUDEvt, sal_False, sal_False); // draw seperator
1427 : }
1428 : else
1429 : {
1430 0 : DrawEntry( rUDEvt, sal_True, sal_True );
1431 : }
1432 0 : }
1433 :
1434 : // ===================================================================
1435 : // FontStyleBox
1436 : // ===================================================================
1437 :
1438 0 : FontStyleBox::FontStyleBox( Window* pParent, const ResId& rResId ) :
1439 0 : ComboBox( pParent, rResId )
1440 : {
1441 0 : aLastStyle = GetText();
1442 0 : }
1443 :
1444 0 : FontStyleBox::FontStyleBox( Window* pParent, WinBits nBits ) :
1445 0 : ComboBox( pParent, nBits )
1446 : {
1447 0 : aLastStyle = GetText();
1448 0 : }
1449 :
1450 0 : extern "C" SAL_DLLPUBLIC_EXPORT Window* SAL_CALL makeFontStyleBox(Window *pParent, VclBuilder::stringmap &rMap)
1451 : {
1452 0 : bool bDropdown = extractDropdown(rMap);
1453 0 : WinBits nWinBits = WB_LEFT|WB_VCENTER|WB_3DLOOK|WB_TABSTOP;
1454 0 : if (bDropdown)
1455 0 : nWinBits |= WB_DROPDOWN;
1456 0 : FontStyleBox *pListBox = new FontStyleBox(pParent, nWinBits);
1457 0 : if (bDropdown)
1458 0 : pListBox->EnableAutoSize(true);
1459 0 : return pListBox;
1460 : }
1461 :
1462 0 : FontStyleBox::~FontStyleBox()
1463 : {
1464 0 : }
1465 :
1466 : // -------------------------------------------------------------------
1467 :
1468 0 : void FontStyleBox::Select()
1469 : {
1470 : // keep text over fill operation
1471 0 : aLastStyle = GetText();
1472 0 : ComboBox::Select();
1473 0 : }
1474 :
1475 : // -------------------------------------------------------------------
1476 :
1477 0 : void FontStyleBox::LoseFocus()
1478 : {
1479 : // keep text over fill operation
1480 0 : aLastStyle = GetText();
1481 0 : ComboBox::LoseFocus();
1482 0 : }
1483 :
1484 : // -------------------------------------------------------------------
1485 :
1486 0 : void FontStyleBox::Modify()
1487 : {
1488 : CharClass aChrCls( ::comphelper::getProcessComponentContext(),
1489 0 : GetSettings().GetLanguageTag() );
1490 0 : XubString aStr = GetText();
1491 0 : sal_uInt16 nEntryCount = GetEntryCount();
1492 :
1493 0 : if ( GetEntryPos( aStr ) == COMBOBOX_ENTRY_NOTFOUND )
1494 : {
1495 0 : aStr = aChrCls.uppercase(aStr);
1496 0 : for ( sal_uInt16 i = 0; i < nEntryCount; i++ )
1497 : {
1498 0 : XubString aEntryText = aChrCls.uppercase(GetEntry(i));
1499 :
1500 0 : if ( aStr == aEntryText )
1501 : {
1502 0 : SetText( GetEntry( i ) );
1503 : break;
1504 : }
1505 0 : }
1506 : }
1507 :
1508 0 : ComboBox::Modify();
1509 0 : }
1510 :
1511 : // -------------------------------------------------------------------
1512 :
1513 0 : void FontStyleBox::Fill( const XubString& rName, const FontList* pList )
1514 : {
1515 : // note: this method must call ComboBox::SetText(),
1516 : // else aLastStyle will overwritten
1517 : // store prior selection position and clear box
1518 0 : XubString aOldText = GetText();
1519 0 : sal_uInt16 nPos = GetEntryPos( aOldText );
1520 0 : Clear();
1521 :
1522 : // does a font with this name already exist?
1523 0 : sal_Handle hFontInfo = pList->GetFirstFontInfo( rName );
1524 0 : if ( hFontInfo )
1525 : {
1526 0 : OUString aStyleText;
1527 0 : FontWeight eLastWeight = WEIGHT_DONTKNOW;
1528 0 : FontItalic eLastItalic = ITALIC_NONE;
1529 0 : FontWidth eLastWidth = WIDTH_DONTKNOW;
1530 0 : sal_Bool bNormal = sal_False;
1531 0 : sal_Bool bItalic = sal_False;
1532 0 : sal_Bool bBold = sal_False;
1533 0 : sal_Bool bBoldItalic = sal_False;
1534 0 : sal_Bool bInsert = sal_False;
1535 0 : FontInfo aInfo;
1536 0 : while ( hFontInfo )
1537 : {
1538 0 : aInfo = pList->GetFontInfo( hFontInfo );
1539 :
1540 0 : FontWeight eWeight = aInfo.GetWeight();
1541 0 : FontItalic eItalic = aInfo.GetItalic();
1542 0 : FontWidth eWidth = aInfo.GetWidthType();
1543 : // Only if the attributes are different, we insert the
1544 : // Font to avoid double Entries in different languages
1545 0 : if ( (eWeight != eLastWeight) || (eItalic != eLastItalic) ||
1546 : (eWidth != eLastWidth) )
1547 : {
1548 0 : if ( bInsert )
1549 0 : InsertEntry( aStyleText );
1550 :
1551 0 : if ( eWeight <= WEIGHT_NORMAL )
1552 : {
1553 0 : if ( eItalic != ITALIC_NONE )
1554 0 : bItalic = sal_True;
1555 : else
1556 0 : bNormal = sal_True;
1557 : }
1558 : else
1559 : {
1560 0 : if ( eItalic != ITALIC_NONE )
1561 0 : bBoldItalic = sal_True;
1562 : else
1563 0 : bBold = sal_True;
1564 : }
1565 :
1566 : // For wrong StyleNames we replace this with the correct once
1567 0 : aStyleText = pList->GetStyleName( aInfo );
1568 0 : bInsert = GetEntryPos( aStyleText ) == LISTBOX_ENTRY_NOTFOUND;
1569 0 : if ( !bInsert )
1570 : {
1571 0 : aStyleText = pList->GetStyleName( eWeight, eItalic );
1572 0 : bInsert = GetEntryPos( aStyleText ) == LISTBOX_ENTRY_NOTFOUND;
1573 : }
1574 :
1575 0 : eLastWeight = eWeight;
1576 0 : eLastItalic = eItalic;
1577 0 : eLastWidth = eWidth;
1578 : }
1579 : else
1580 : {
1581 0 : if ( bInsert )
1582 : {
1583 : // If we have two names for the same attributes
1584 : // we prefer the translated standard names
1585 0 : const OUString& rAttrStyleText = pList->GetStyleName( eWeight, eItalic );
1586 0 : if (rAttrStyleText != aStyleText)
1587 : {
1588 0 : OUString aTempStyleText = pList->GetStyleName( aInfo );
1589 0 : if (rAttrStyleText == aTempStyleText)
1590 0 : aStyleText = rAttrStyleText;
1591 0 : bInsert = GetEntryPos( aStyleText ) == LISTBOX_ENTRY_NOTFOUND;
1592 : }
1593 : }
1594 : }
1595 :
1596 0 : if ( !bItalic && (aStyleText == pList->GetItalicStr()) )
1597 0 : bItalic = sal_True;
1598 0 : else if ( !bBold && (aStyleText == pList->GetBoldStr()) )
1599 0 : bBold = sal_True;
1600 0 : else if ( !bBoldItalic && (aStyleText == pList->GetBoldItalicStr()) )
1601 0 : bBoldItalic = sal_True;
1602 :
1603 0 : hFontInfo = pList->GetNextFontInfo( hFontInfo );
1604 : }
1605 :
1606 0 : if ( bInsert )
1607 0 : InsertEntry( aStyleText );
1608 :
1609 : // Bestimmte Styles als Nachbildung
1610 0 : if ( bNormal )
1611 : {
1612 0 : if ( !bItalic )
1613 0 : InsertEntry( pList->GetItalicStr() );
1614 0 : if ( !bBold )
1615 0 : InsertEntry( pList->GetBoldStr() );
1616 : }
1617 0 : if ( !bBoldItalic )
1618 : {
1619 0 : if ( bNormal || bItalic || bBold )
1620 0 : InsertEntry( pList->GetBoldItalicStr() );
1621 : }
1622 0 : if ( aOldText.Len() )
1623 : {
1624 0 : if ( GetEntryPos( aLastStyle ) != LISTBOX_ENTRY_NOTFOUND )
1625 0 : ComboBox::SetText( aLastStyle );
1626 : else
1627 : {
1628 0 : if ( nPos >= GetEntryCount() )
1629 0 : ComboBox::SetText( GetEntry( 0 ) );
1630 : else
1631 0 : ComboBox::SetText( GetEntry( nPos ) );
1632 : }
1633 0 : }
1634 : }
1635 : else
1636 : {
1637 : // Wenn Font nicht, dann Standard-Styles einfuegen
1638 0 : InsertEntry( pList->GetNormalStr() );
1639 0 : InsertEntry( pList->GetItalicStr() );
1640 0 : InsertEntry( pList->GetBoldStr() );
1641 0 : InsertEntry( pList->GetBoldItalicStr() );
1642 0 : if ( aOldText.Len() )
1643 : {
1644 0 : if ( nPos > GetEntryCount() )
1645 0 : ComboBox::SetText( GetEntry( 0 ) );
1646 : else
1647 0 : ComboBox::SetText( GetEntry( nPos ) );
1648 : }
1649 0 : }
1650 0 : }
1651 :
1652 : // ===================================================================
1653 : // FontSizeBox
1654 : // ===================================================================
1655 :
1656 0 : FontSizeBox::FontSizeBox( Window* pParent, WinBits nWinSize ) :
1657 0 : MetricBox( pParent, nWinSize )
1658 : {
1659 0 : ImplInit();
1660 0 : }
1661 :
1662 : // -----------------------------------------------------------------------
1663 :
1664 0 : FontSizeBox::FontSizeBox( Window* pParent, const ResId& rResId ) :
1665 0 : MetricBox( pParent, rResId )
1666 : {
1667 0 : ImplInit();
1668 0 : }
1669 :
1670 0 : extern "C" SAL_DLLPUBLIC_EXPORT Window* SAL_CALL makeFontSizeBox(Window *pParent, VclBuilder::stringmap &rMap)
1671 : {
1672 0 : bool bDropdown = extractDropdown(rMap);
1673 0 : WinBits nWinBits = WB_LEFT|WB_VCENTER|WB_3DLOOK|WB_TABSTOP;
1674 0 : if (bDropdown)
1675 0 : nWinBits |= WB_DROPDOWN;
1676 0 : FontSizeBox* pListBox = new FontSizeBox(pParent, nWinBits);
1677 0 : if (bDropdown)
1678 0 : pListBox->EnableAutoSize(true);
1679 0 : return pListBox;
1680 : }
1681 :
1682 : // -----------------------------------------------------------------------
1683 :
1684 0 : FontSizeBox::~FontSizeBox()
1685 : {
1686 0 : }
1687 :
1688 : // -----------------------------------------------------------------------
1689 :
1690 0 : void FontSizeBox::ImplInit()
1691 : {
1692 0 : EnableAutocomplete( sal_False );
1693 :
1694 0 : bRelativeMode = sal_False;
1695 0 : bPtRelative = sal_False;
1696 0 : bRelative = sal_False;
1697 0 : bStdSize = sal_False;
1698 0 : pFontList = NULL;
1699 :
1700 0 : SetShowTrailingZeros( sal_False );
1701 0 : SetDecimalDigits( 1 );
1702 0 : SetMin( 20 );
1703 0 : SetMax( 9999 );
1704 0 : SetProminentEntryType( PROMINENT_MIDDLE );
1705 0 : }
1706 :
1707 : // -----------------------------------------------------------------------
1708 :
1709 0 : void FontSizeBox::Reformat()
1710 : {
1711 0 : FontSizeNames aFontSizeNames( GetSettings().GetUILanguageTag().getLanguageType() );
1712 0 : if ( !bRelativeMode || !aFontSizeNames.IsEmpty() )
1713 : {
1714 0 : long nNewValue = aFontSizeNames.Name2Size( GetText() );
1715 0 : if ( nNewValue)
1716 : {
1717 0 : mnLastValue = nNewValue;
1718 0 : return;
1719 : }
1720 : }
1721 :
1722 0 : MetricBox::Reformat();
1723 : }
1724 :
1725 : // -----------------------------------------------------------------------
1726 :
1727 0 : void FontSizeBox::Modify()
1728 : {
1729 0 : MetricBox::Modify();
1730 :
1731 0 : if ( bRelativeMode )
1732 : {
1733 0 : XubString aStr = comphelper::string::stripStart(GetText(), ' ');
1734 :
1735 0 : sal_Bool bNewMode = bRelative;
1736 0 : sal_Bool bOldPtRelMode = bPtRelative;
1737 :
1738 0 : if ( bRelative )
1739 : {
1740 0 : bPtRelative = sal_False;
1741 0 : const sal_Unicode* pStr = aStr.GetBuffer();
1742 0 : while ( *pStr )
1743 : {
1744 0 : if ( ((*pStr < '0') || (*pStr > '9')) && (*pStr != '%') )
1745 : {
1746 0 : if ( ('-' == *pStr || '+' == *pStr) && !bPtRelative )
1747 0 : bPtRelative = sal_True;
1748 0 : else if ( bPtRelative && 'p' == *pStr && 't' == *++pStr )
1749 : ;
1750 : else
1751 : {
1752 0 : bNewMode = sal_False;
1753 0 : break;
1754 : }
1755 : }
1756 0 : pStr++;
1757 : }
1758 : }
1759 : else
1760 : {
1761 0 : if ( STRING_NOTFOUND != aStr.Search( '%' ) )
1762 : {
1763 0 : bNewMode = sal_True;
1764 0 : bPtRelative = sal_False;
1765 : }
1766 :
1767 0 : if ( '-' == aStr.GetChar( 0 ) || '+' == aStr.GetChar( 0 ) )
1768 : {
1769 0 : bNewMode = sal_True;
1770 0 : bPtRelative = sal_True;
1771 : }
1772 : }
1773 :
1774 0 : if ( bNewMode != bRelative || bPtRelative != bOldPtRelMode )
1775 0 : SetRelative( bNewMode );
1776 : }
1777 0 : }
1778 :
1779 : // -----------------------------------------------------------------------
1780 :
1781 0 : void FontSizeBox::Fill( const FontInfo* pInfo, const FontList* pList )
1782 : {
1783 : // remember for relative mode
1784 0 : pFontList = pList;
1785 :
1786 : // no font sizes need to be set for relative mode
1787 0 : if ( bRelative )
1788 : return;
1789 :
1790 : // query font sizes
1791 : const long* pTempAry;
1792 0 : const long* pAry = 0;
1793 :
1794 0 : if( pInfo )
1795 : {
1796 0 : aFontInfo = *pInfo;
1797 0 : pAry = pList->GetSizeAry( *pInfo );
1798 : }
1799 : else
1800 : {
1801 0 : pAry = pList->GetStdSizeAry();
1802 : }
1803 :
1804 : // first insert font size names (for simplified/traditional chinese)
1805 0 : FontSizeNames aFontSizeNames( GetSettings().GetUILanguageTag().getLanguageType() );
1806 0 : if ( pAry == pList->GetStdSizeAry() )
1807 : {
1808 : // for standard sizes we don't need to bother
1809 0 : if ( bStdSize && GetEntryCount() && aFontSizeNames.IsEmpty() )
1810 : return;
1811 0 : bStdSize = sal_True;
1812 : }
1813 : else
1814 0 : bStdSize = sal_False;
1815 :
1816 0 : Selection aSelection = GetSelection();
1817 0 : XubString aStr = GetText();
1818 :
1819 0 : Clear();
1820 0 : sal_uInt16 nPos = 0;
1821 :
1822 0 : if ( !aFontSizeNames.IsEmpty() )
1823 : {
1824 0 : if ( pAry == pList->GetStdSizeAry() )
1825 : {
1826 : // for scalable fonts all font size names
1827 0 : sal_uLong nCount = aFontSizeNames.Count();
1828 0 : for( sal_uLong i = 0; i < nCount; i++ )
1829 : {
1830 0 : String aSizeName = aFontSizeNames.GetIndexName( i );
1831 0 : long nSize = aFontSizeNames.GetIndexSize( i );
1832 0 : ComboBox::InsertEntry( aSizeName, nPos );
1833 0 : ComboBox::SetEntryData( nPos, (void*)(-nSize) ); // mark as special
1834 0 : nPos++;
1835 0 : }
1836 : }
1837 : else
1838 : {
1839 : // for fixed size fonts only selectable font size names
1840 0 : pTempAry = pAry;
1841 0 : while ( *pTempAry )
1842 : {
1843 0 : String aSizeName = aFontSizeNames.Size2Name( *pTempAry );
1844 0 : if ( aSizeName.Len() )
1845 : {
1846 0 : ComboBox::InsertEntry( aSizeName, nPos );
1847 0 : ComboBox::SetEntryData( nPos, (void*)(-(*pTempAry)) ); // mark as special
1848 0 : nPos++;
1849 : }
1850 0 : pTempAry++;
1851 0 : }
1852 : }
1853 : }
1854 :
1855 : // then insert numerical font size values
1856 0 : pTempAry = pAry;
1857 0 : while ( *pTempAry )
1858 : {
1859 0 : InsertValue( *pTempAry, FUNIT_NONE, nPos );
1860 0 : ComboBox::SetEntryData( nPos, (void*)(*pTempAry) );
1861 0 : nPos++;
1862 0 : pTempAry++;
1863 : }
1864 :
1865 0 : SetText( aStr );
1866 0 : SetSelection( aSelection );
1867 : }
1868 :
1869 : // -----------------------------------------------------------------------
1870 :
1871 0 : void FontSizeBox::EnableRelativeMode( sal_uInt16 nMin, sal_uInt16 nMax, sal_uInt16 nStep )
1872 : {
1873 0 : bRelativeMode = sal_True;
1874 0 : nRelMin = nMin;
1875 0 : nRelMax = nMax;
1876 0 : nRelStep = nStep;
1877 0 : SetUnit( FUNIT_POINT );
1878 0 : }
1879 :
1880 : // -----------------------------------------------------------------------
1881 :
1882 0 : void FontSizeBox::EnablePtRelativeMode( short nMin, short nMax, short nStep )
1883 : {
1884 0 : bRelativeMode = sal_True;
1885 0 : nPtRelMin = nMin;
1886 0 : nPtRelMax = nMax;
1887 0 : nPtRelStep = nStep;
1888 0 : SetUnit( FUNIT_POINT );
1889 0 : }
1890 :
1891 : // -----------------------------------------------------------------------
1892 :
1893 0 : void FontSizeBox::SetRelative( sal_Bool bNewRelative )
1894 : {
1895 0 : if ( bRelativeMode )
1896 : {
1897 0 : Selection aSelection = GetSelection();
1898 0 : XubString aStr = comphelper::string::stripStart(GetText(), ' ');
1899 :
1900 0 : if ( bNewRelative )
1901 : {
1902 0 : bRelative = sal_True;
1903 0 : bStdSize = sal_False;
1904 :
1905 0 : if ( bPtRelative )
1906 : {
1907 0 : SetDecimalDigits( 1 );
1908 0 : SetMin( nPtRelMin );
1909 0 : SetMax( nPtRelMax );
1910 0 : SetUnit( FUNIT_POINT );
1911 :
1912 0 : Clear();
1913 :
1914 0 : short i = nPtRelMin, n = 0;
1915 : // JP 30.06.98: more than 100 values are not useful
1916 0 : while ( i <= nPtRelMax && n++ < 100 )
1917 : {
1918 0 : InsertValue( i );
1919 0 : i = i + nPtRelStep;
1920 : }
1921 : }
1922 : else
1923 : {
1924 0 : SetDecimalDigits( 0 );
1925 0 : SetMin( nRelMin );
1926 0 : SetMax( nRelMax );
1927 0 : SetCustomUnitText(rtl::OUString('%'));
1928 0 : SetUnit( FUNIT_CUSTOM );
1929 :
1930 0 : Clear();
1931 0 : sal_uInt16 i = nRelMin;
1932 0 : while ( i <= nRelMax )
1933 : {
1934 0 : InsertValue( i );
1935 0 : i = i + nRelStep;
1936 : }
1937 : }
1938 : }
1939 : else
1940 : {
1941 0 : bRelative = bPtRelative = sal_False;
1942 0 : SetDecimalDigits( 1 );
1943 0 : SetMin( 20 );
1944 0 : SetMax( 9999 );
1945 0 : SetUnit( FUNIT_POINT );
1946 0 : if ( pFontList )
1947 0 : Fill( &aFontInfo, pFontList );
1948 : }
1949 :
1950 0 : SetText( aStr );
1951 0 : SetSelection( aSelection );
1952 : }
1953 0 : }
1954 :
1955 : // -----------------------------------------------------------------------
1956 :
1957 0 : XubString FontSizeBox::CreateFieldText( sal_Int64 nValue ) const
1958 : {
1959 0 : XubString sRet( MetricBox::CreateFieldText( nValue ) );
1960 0 : if ( bRelativeMode && bPtRelative && (0 <= nValue) && sRet.Len() )
1961 0 : sRet.Insert( '+', 0 );
1962 0 : return sRet;
1963 : }
1964 :
1965 : // -----------------------------------------------------------------------
1966 :
1967 0 : void FontSizeBox::SetValue( sal_Int64 nNewValue, FieldUnit eInUnit )
1968 : {
1969 0 : if ( !bRelative )
1970 : {
1971 0 : sal_Int64 nTempValue = MetricField::ConvertValue( nNewValue, GetBaseValue(), GetDecimalDigits(), eInUnit, GetUnit() );
1972 0 : FontSizeNames aFontSizeNames( GetSettings().GetUILanguageTag().getLanguageType() );
1973 : // conversion loses precision; however font sizes should
1974 : // never have a problem with that
1975 0 : String aName = aFontSizeNames.Size2Name( static_cast<long>(nTempValue) );
1976 0 : if ( aName.Len() && (GetEntryPos( aName ) != LISTBOX_ENTRY_NOTFOUND) )
1977 : {
1978 0 : mnLastValue = nTempValue;
1979 0 : SetText( aName );
1980 0 : mnFieldValue = mnLastValue;
1981 0 : SetEmptyFieldValueData( sal_False );
1982 0 : return;
1983 0 : }
1984 : }
1985 :
1986 0 : MetricBox::SetValue( nNewValue, eInUnit );
1987 : }
1988 :
1989 : // -----------------------------------------------------------------------
1990 :
1991 0 : void FontSizeBox::SetValue( sal_Int64 nNewValue )
1992 : {
1993 0 : SetValue( nNewValue, FUNIT_NONE );
1994 0 : }
1995 :
1996 0 : sal_Int64 FontSizeBox::GetValue( FieldUnit eOutUnit ) const
1997 : {
1998 0 : if ( !bRelative )
1999 : {
2000 0 : FontSizeNames aFontSizeNames( GetSettings().GetUILanguageTag().getLanguageType() );
2001 0 : sal_Int64 nValue = aFontSizeNames.Name2Size( GetText() );
2002 0 : if ( nValue)
2003 0 : return MetricField::ConvertValue( nValue, GetBaseValue(), GetDecimalDigits(), GetUnit(), eOutUnit );
2004 : }
2005 :
2006 0 : return MetricBox::GetValue( eOutUnit );
2007 : }
2008 :
2009 : // -----------------------------------------------------------------------
2010 :
2011 0 : sal_Int64 FontSizeBox::GetValue() const
2012 : {
2013 : // implementation not inline, because it is a virtual function
2014 0 : return GetValue( FUNIT_NONE );
2015 : }
2016 :
2017 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|