1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <tools/stream.hxx>
21 #include <vcl/builder.hxx>
22 #include <vcl/svapp.hxx>
23 #include <vcl/field.hxx>
24 #include <vcl/helper.hxx>
25 #include <sal/macros.h>
26 #include <comphelper/processfactory.hxx>
27 #include <comphelper/string.hxx>
28 #include <unotools/charclass.hxx>
30 #include <svtools/sampletext.hxx>
31 #include <svtools/svtresid.hxx>
32 #include <svtools/svtools.hrc>
33 #include <svtools/ctrlbox.hxx>
34 #include <svtools/ctrltool.hxx>
35 #include <svtools/borderhelper.hxx>
37 #include <vcl/i18nhelp.hxx>
38 #include <vcl/fontcapabilities.hxx>
39 #include <basegfx/polygon/b2dpolygon.hxx>
40 #include <basegfx/polygon/b2dpolygontools.hxx>
42 #include <rtl/bootstrap.hxx>
44 #if OSL_DEBUG_LEVEL > 1
50 #define IMGOUTERTEXTSPACE 5
51 #define EXTRAFONTSIZE 5
52 #define GAPTOEXTRAPREVIEW 10
53 #define MAXPREVIEWWIDTH 120
56 #define FONTNAMEBOXMRUENTRIESFILE "/user/config/fontnameboxmruentries"
58 using namespace ::com::sun::star
;
60 // ========================================================================
62 // ========================================================================
64 // --------------------
65 // - ImplColorListData -
66 // --------------------
68 class ImplColorListData
74 ImplColorListData() : aColor( COL_BLACK
) { bColor
= sal_False
; }
75 ImplColorListData( const Color
& rColor
) : aColor( rColor
) { bColor
= sal_True
; }
78 // -----------------------------------------------------------------------
80 void ColorListBox::ImplInit()
82 pColorList
= new ImpColorList();
84 const StyleSettings
& rStyleSettings
= Application::GetSettings().GetStyleSettings();
85 aImageSize
= rStyleSettings
.GetListBoxPreviewDefaultPixelSize();
86 EnableUserDraw( sal_True
);
87 SetUserItemSize( aImageSize
);
90 // -----------------------------------------------------------------------
92 void ColorListBox::ImplDestroyColorEntries()
94 for ( size_t n
= pColorList
->size(); n
; )
95 delete (*pColorList
)[ --n
];
99 // -----------------------------------------------------------------------
101 ColorListBox::ColorListBox( Window
* pParent
, WinBits nWinStyle
) :
102 ListBox( pParent
, nWinStyle
)
105 SetEdgeBlending(true);
108 // -----------------------------------------------------------------------
110 ColorListBox::ColorListBox( Window
* pParent
, const ResId
& rResId
) :
111 ListBox( pParent
, rResId
)
114 SetEdgeBlending(true);
119 bool extractDropdown(VclBuilder::stringmap
&rMap
)
121 bool bDropdown
= true;
122 VclBuilder::stringmap::iterator aFind
= rMap
.find(OString(RTL_CONSTASCII_STRINGPARAM("dropdown")));
123 if (aFind
!= rMap
.end())
125 bDropdown
= toBool(aFind
->second
);
132 extern "C" SAL_DLLPUBLIC_EXPORT Window
* SAL_CALL
makeColorListBox(Window
*pParent
, VclBuilder::stringmap
&rMap
)
134 bool bDropdown
= extractDropdown(rMap
);
135 WinBits nWinBits
= WB_LEFT
|WB_VCENTER
|WB_3DLOOK
|WB_TABSTOP
;
137 nWinBits
|= WB_DROPDOWN
;
138 ColorListBox
*pListBox
= new ColorListBox(pParent
, nWinBits
);
140 pListBox
->EnableAutoSize(true);
144 // -----------------------------------------------------------------------
146 ColorListBox::~ColorListBox()
148 ImplDestroyColorEntries();
152 // -----------------------------------------------------------------------
154 sal_uInt16
ColorListBox::InsertEntry( const XubString
& rStr
, sal_uInt16 nPos
)
156 nPos
= ListBox::InsertEntry( rStr
, nPos
);
157 if ( nPos
!= LISTBOX_ERROR
)
159 ImplColorListData
* pData
= new ImplColorListData
;
160 if ( nPos
< pColorList
->size() )
162 ImpColorList::iterator it
= pColorList
->begin();
163 ::std::advance( it
, nPos
);
164 pColorList
->insert( it
, pData
);
168 pColorList
->push_back( pData
);
169 nPos
= pColorList
->size() - 1;
175 // -----------------------------------------------------------------------
177 sal_uInt16
ColorListBox::InsertEntry( const Color
& rColor
, const XubString
& rStr
,
180 nPos
= ListBox::InsertEntry( rStr
, nPos
);
181 if ( nPos
!= LISTBOX_ERROR
)
183 ImplColorListData
* pData
= new ImplColorListData( rColor
);
184 if ( nPos
< pColorList
->size() )
186 ImpColorList::iterator it
= pColorList
->begin();
187 ::std::advance( it
, nPos
);
188 pColorList
->insert( it
, pData
);
192 pColorList
->push_back( pData
);
193 nPos
= pColorList
->size() - 1;
199 // -----------------------------------------------------------------------
201 void ColorListBox::InsertAutomaticEntryColor(const Color
&rColor
)
203 // insert the "Automatic"-entry always on the first position
204 InsertEntry( rColor
, SVT_RESSTR(STR_SVT_AUTOMATIC_COLOR
), 0 );
207 // -----------------------------------------------------------------------
209 void ColorListBox::RemoveEntry( sal_uInt16 nPos
)
211 ListBox::RemoveEntry( nPos
);
212 if ( nPos
< pColorList
->size() )
214 ImpColorList::iterator it
= pColorList
->begin();
215 ::std::advance( it
, nPos
);
217 pColorList
->erase( it
);
221 // -----------------------------------------------------------------------
223 void ColorListBox::Clear()
225 ImplDestroyColorEntries();
229 // -----------------------------------------------------------------------
231 void ColorListBox::CopyEntries( const ColorListBox
& rBox
)
234 ImplDestroyColorEntries();
237 size_t nCount
= rBox
.pColorList
->size();
238 for ( size_t n
= 0; n
< nCount
; n
++ )
240 ImplColorListData
* pData
= (*rBox
.pColorList
)[ n
];
241 sal_uInt16 nPos
= InsertEntry( rBox
.GetEntry( n
), LISTBOX_APPEND
);
242 if ( nPos
!= LISTBOX_ERROR
)
244 if ( nPos
< pColorList
->size() )
246 ImpColorList::iterator it
= pColorList
->begin();
247 ::std::advance( it
, nPos
);
248 pColorList
->insert( it
, new ImplColorListData( *pData
) );
252 pColorList
->push_back( new ImplColorListData( *pData
) );
258 // -----------------------------------------------------------------------
260 sal_uInt16
ColorListBox::GetEntryPos( const Color
& rColor
) const
262 for( sal_uInt16 n
= (sal_uInt16
) pColorList
->size(); n
; )
264 ImplColorListData
* pData
= (*pColorList
)[ --n
];
265 if ( pData
->bColor
&& ( pData
->aColor
== rColor
) )
268 return LISTBOX_ENTRY_NOTFOUND
;
271 // -----------------------------------------------------------------------
273 Color
ColorListBox::GetEntryColor( sal_uInt16 nPos
) const
276 ImplColorListData
* pData
= ( nPos
< pColorList
->size() ) ? (*pColorList
)[ nPos
] : NULL
;
277 if ( pData
&& pData
->bColor
)
278 aColor
= pData
->aColor
;
282 // -----------------------------------------------------------------------
284 void ColorListBox::UserDraw( const UserDrawEvent
& rUDEvt
)
286 size_t nPos
= rUDEvt
.GetItemId();
287 ImplColorListData
* pData
= ( nPos
< pColorList
->size() ) ? (*pColorList
)[ nPos
] : NULL
;
292 Point
aPos( rUDEvt
.GetRect().TopLeft() );
295 aPos
.Y() += ( rUDEvt
.GetRect().GetHeight() - aImageSize
.Height() ) / 2;
297 const Rectangle
aRect(aPos
, aImageSize
);
299 rUDEvt
.GetDevice()->Push();
300 rUDEvt
.GetDevice()->SetFillColor( pData
->aColor
);
301 rUDEvt
.GetDevice()->SetLineColor( rUDEvt
.GetDevice()->GetTextColor() );
302 rUDEvt
.GetDevice()->DrawRect(aRect
);
303 rUDEvt
.GetDevice()->Pop();
305 const StyleSettings
& rStyleSettings
= Application::GetSettings().GetStyleSettings();
306 const sal_uInt16
nEdgeBlendingPercent(GetEdgeBlending() ? rStyleSettings
.GetEdgeBlending() : 0);
308 if(nEdgeBlendingPercent
)
310 const Color
& rTopLeft(rStyleSettings
.GetEdgeBlendingTopLeftColor());
311 const Color
& rBottomRight(rStyleSettings
.GetEdgeBlendingBottomRightColor());
312 const sal_uInt8
nAlpha((nEdgeBlendingPercent
* 255) / 100);
313 const BitmapEx
aBlendFrame(createBlendFrame(aRect
.GetSize(), nAlpha
, rTopLeft
, rBottomRight
));
315 if(!aBlendFrame
.IsEmpty())
317 rUDEvt
.GetDevice()->DrawBitmapEx(aRect
.TopLeft(), aBlendFrame
);
321 ListBox::DrawEntry( rUDEvt
, sal_False
, sal_True
, sal_False
);
324 ListBox::DrawEntry( rUDEvt
, sal_False
, sal_True
, sal_True
);
327 ListBox::DrawEntry( rUDEvt
, sal_True
, sal_True
, sal_False
);
330 // =======================================================================
332 // =======================================================================
334 BorderWidthImpl::BorderWidthImpl( sal_uInt16 nFlags
, double nRate1
, double nRate2
, double nRateGap
):
338 m_nRateGap( nRateGap
)
342 BorderWidthImpl
& BorderWidthImpl::operator= ( const BorderWidthImpl
& r
)
344 m_nFlags
= r
.m_nFlags
;
345 m_nRate1
= r
.m_nRate1
;
346 m_nRate2
= r
.m_nRate2
;
347 m_nRateGap
= r
.m_nRateGap
;
351 bool BorderWidthImpl::operator== ( const BorderWidthImpl
& r
) const
353 return ( m_nFlags
== r
.m_nFlags
) &&
354 ( m_nRate1
== r
.m_nRate1
) &&
355 ( m_nRate2
== r
.m_nRate2
) &&
356 ( m_nRateGap
== r
.m_nRateGap
);
359 long BorderWidthImpl::GetLine1( long nWidth
) const
361 long result
= static_cast<long>(m_nRate1
);
362 if ( ( m_nFlags
& CHANGE_LINE1
) > 0 )
364 long const nConstant2
= (m_nFlags
& CHANGE_LINE2
) ? 0 : m_nRate2
;
365 long const nConstantD
= (m_nFlags
& CHANGE_DIST
) ? 0 : m_nRateGap
;
366 result
= std::max
<long>(0,
367 static_cast<long>((m_nRate1
* nWidth
) + 0.5)
368 - (nConstant2
+ nConstantD
));
369 if (result
== 0 && m_nRate1
> 0.0 && nWidth
> 0)
370 { // fdo#51777: hack to essentially treat 1 twip DOUBLE border
371 result
= 1; // as 1 twip SINGLE border
377 long BorderWidthImpl::GetLine2( long nWidth
) const
379 long result
= static_cast<long>(m_nRate2
);
380 if ( ( m_nFlags
& CHANGE_LINE2
) > 0 )
382 long const nConstant1
= (m_nFlags
& CHANGE_LINE1
) ? 0 : m_nRate1
;
383 long const nConstantD
= (m_nFlags
& CHANGE_DIST
) ? 0 : m_nRateGap
;
384 result
= std::max
<long>(0,
385 static_cast<long>((m_nRate2
* nWidth
) + 0.5)
386 - (nConstant1
+ nConstantD
));
391 long BorderWidthImpl::GetGap( long nWidth
) const
393 long result
= static_cast<long>(m_nRateGap
);
394 if ( ( m_nFlags
& CHANGE_DIST
) > 0 )
396 long const nConstant1
= (m_nFlags
& CHANGE_LINE1
) ? 0 : m_nRate1
;
397 long const nConstant2
= (m_nFlags
& CHANGE_LINE2
) ? 0 : m_nRate2
;
398 result
= std::max
<long>(0,
399 static_cast<long>((m_nRateGap
* nWidth
) + 0.5)
400 - (nConstant1
+ nConstant2
));
403 // Avoid having too small distances (less than 0.1pt)
404 if ( result
< MINGAPWIDTH
&& m_nRate1
> 0 && m_nRate2
> 0 )
405 result
= MINGAPWIDTH
;
410 static double lcl_getGuessedWidth( long nTested
, double nRate
, bool nChanging
)
412 double nWidth
= -1.0;
414 nWidth
= double( nTested
) / nRate
;
417 if ( double( nTested
) == nRate
)
424 long BorderWidthImpl::GuessWidth( long nLine1
, long nLine2
, long nGap
)
426 std::vector
< double > aToCompare
;
427 bool bInvalid
= false;
429 bool bLine1Change
= ( m_nFlags
& CHANGE_LINE1
) > 0;
430 double nWidth1
= lcl_getGuessedWidth( nLine1
, m_nRate1
, bLine1Change
);
432 aToCompare
.push_back( nWidth1
);
433 else if ( !bLine1Change
&& nWidth1
< 0 )
436 bool bLine2Change
= ( m_nFlags
& CHANGE_LINE2
) > 0;
437 double nWidth2
= lcl_getGuessedWidth( nLine2
, m_nRate2
, bLine2Change
);
439 aToCompare
.push_back( nWidth2
);
440 else if ( !bLine2Change
&& nWidth2
< 0 )
443 bool bGapChange
= ( m_nFlags
& CHANGE_DIST
) > 0;
444 double nWidthGap
= lcl_getGuessedWidth( nGap
, m_nRateGap
, bGapChange
);
445 if ( bGapChange
&& nGap
> MINGAPWIDTH
)
446 aToCompare
.push_back( nWidthGap
);
447 else if ( !bGapChange
&& nWidthGap
< 0 )
450 // non-constant line width factors must sum to 1
451 assert((((bLine1Change
) ? m_nRate1
: 0) +
452 ((bLine2Change
) ? m_nRate2
: 0) +
453 ((bGapChange
) ? m_nRateGap
: 0)) - 1.0 < 0.00001 );
456 if ( (!bInvalid
) && (!aToCompare
.empty()) )
458 nWidth
= *aToCompare
.begin();
459 std::vector
< double >::iterator pIt
= aToCompare
.begin();
460 while ( pIt
!= aToCompare
.end() && !bInvalid
)
462 bInvalid
= ( nWidth
!= *pIt
);
465 nWidth
= (bInvalid
) ? 0.0 : nLine1
+ nLine2
+ nGap
;
471 /** Utility class storing the border line width, style and colors. The widths
472 are defined in Twips.
474 class ImpLineListData
477 BorderWidthImpl m_aWidthImpl
;
479 Color ( *m_pColor1Fn
)( Color
);
480 Color ( *m_pColor2Fn
)( Color
);
481 Color ( *m_pColorDistFn
)( Color
, Color
);
487 ImpLineListData( BorderWidthImpl aWidthImpl
, sal_uInt16 nStyle
,
488 long nMinWidth
=0, Color ( *pColor1Fn
) ( Color
) = &sameColor
,
489 Color ( *pColor2Fn
) ( Color
) = &sameColor
, Color ( *pColorDistFn
) ( Color
, Color
) = &sameDistColor
);
491 /** Returns the computed width of the line 1 in twips. */
492 long GetLine1ForWidth( long nWidth
) { return m_aWidthImpl
.GetLine1( nWidth
); }
494 /** Returns the computed width of the line 2 in twips. */
495 long GetLine2ForWidth( long nWidth
) { return m_aWidthImpl
.GetLine2( nWidth
); }
497 /** Returns the computed width of the gap in twips. */
498 long GetDistForWidth( long nWidth
) { return m_aWidthImpl
.GetGap( nWidth
); }
500 Color
GetColorLine1( const Color
& aMain
);
501 Color
GetColorLine2( const Color
& aMain
);
502 Color
GetColorDist( const Color
& aMain
, const Color
& rDefault
);
504 /** Returns the minimum width in twips */
506 sal_uInt16
GetStyle( );
509 ImpLineListData::ImpLineListData( BorderWidthImpl aWidthImpl
,
510 sal_uInt16 nStyle
, long nMinWidth
, Color ( *pColor1Fn
)( Color
),
511 Color ( *pColor2Fn
)( Color
), Color ( *pColorDistFn
)( Color
, Color
) ) :
512 m_aWidthImpl( aWidthImpl
),
513 m_pColor1Fn( pColor1Fn
),
514 m_pColor2Fn( pColor2Fn
),
515 m_pColorDistFn( pColorDistFn
),
516 m_nMinWidth( nMinWidth
),
521 long ImpLineListData::GetMinWidth( )
526 Color
ImpLineListData::GetColorLine1( const Color
& rMain
)
528 return ( *m_pColor1Fn
)( rMain
);
531 Color
ImpLineListData::GetColorLine2( const Color
& rMain
)
533 return ( *m_pColor2Fn
)( rMain
);
536 Color
ImpLineListData::GetColorDist( const Color
& rMain
, const Color
& rDefault
)
538 return ( *m_pColorDistFn
)( rMain
, rDefault
);
541 sal_uInt16
LineListBox::GetSelectEntryStyle( sal_uInt16 nSelIndex
) const
543 sal_uInt16 nStyle
= STYLE_SOLID
;
544 sal_uInt16 nPos
= GetSelectEntryPos( nSelIndex
);
545 if ( nPos
!= LISTBOX_ENTRY_NOTFOUND
)
547 if ( m_sNone
.Len( ) > 0 )
549 nStyle
= GetEntryStyle( nPos
);
555 sal_uInt16
ImpLineListData::GetStyle( )
560 // -----------------------------------------------------------------------
562 void lclDrawPolygon( OutputDevice
& rDev
, const basegfx::B2DPolygon
& rPolygon
, long nWidth
, sal_uInt16 nDashing
)
564 sal_uInt16 nOldAA
= rDev
.GetAntialiasing();
565 rDev
.SetAntialiasing( nOldAA
& ~ANTIALIASING_ENABLE_B2DDRAW
);
567 basegfx::B2DPolyPolygon aPolygons
= svtools::ApplyLineDashing( rPolygon
, nDashing
, rDev
.GetMapMode().GetMapUnit() );
568 for ( sal_uInt32 i
= 0; i
< aPolygons
.count( ); i
++ )
570 basegfx::B2DPolygon aDash
= aPolygons
.getB2DPolygon( i
);
571 basegfx::B2DPoint aStart
= aDash
.getB2DPoint( 0 );
572 basegfx::B2DPoint aEnd
= aDash
.getB2DPoint( aDash
.count() - 1 );
574 basegfx::B2DVector
aVector( aEnd
- aStart
);
575 aVector
.normalize( );
576 const basegfx::B2DVector
aPerpendicular(basegfx::getPerpendicular(aVector
));
578 // Handle problems of width 1px in Pixel mode: 0.5px gives a 1px line
579 long nPix
= rDev
.PixelToLogic( Size( 0, 1 ) ).Height();
580 if ( rDev
.GetMapMode().GetMapUnit() == MAP_PIXEL
&& nWidth
== nPix
)
583 const basegfx::B2DVector
aWidthOffset( double( nWidth
) / 2 * aPerpendicular
);
584 basegfx::B2DPolygon aDashPolygon
;
585 aDashPolygon
.append( aStart
+ aWidthOffset
);
586 aDashPolygon
.append( aEnd
+ aWidthOffset
);
587 aDashPolygon
.append( aEnd
- aWidthOffset
);
588 aDashPolygon
.append( aStart
- aWidthOffset
);
589 aDashPolygon
.setClosed( true );
591 rDev
.DrawPolygon( aDashPolygon
);
594 rDev
.SetAntialiasing( nOldAA
);
599 std::vector
< double > GetDashing( sal_uInt16 nDashing
, MapUnit eUnit
)
601 ::std::vector
< double >aPattern
;
605 if ( eUnit
== MAP_TWIP
)
607 aPattern
.push_back( 30.0 );
608 aPattern
.push_back( 110.0 );
610 else if ( eUnit
== MAP_100TH_MM
)
612 aPattern
.push_back( 50 );
613 aPattern
.push_back( 200 );
615 else if ( eUnit
== MAP_PIXEL
)
617 aPattern
.push_back( 1.0 );
618 aPattern
.push_back( 3.0 );
622 if ( eUnit
== MAP_TWIP
)
624 aPattern
.push_back( 110 );
625 aPattern
.push_back( 110 );
627 else if ( eUnit
== MAP_100TH_MM
)
629 aPattern
.push_back( 200 );
630 aPattern
.push_back( 200 );
632 else if ( eUnit
== MAP_PIXEL
)
634 aPattern
.push_back( 10 );
635 aPattern
.push_back( 20 );
638 case STYLE_FINE_DASHED
:
639 if ( eUnit
== MAP_PIXEL
)
641 aPattern
.push_back( 4 );
642 aPattern
.push_back( 1 );
652 basegfx::B2DPolyPolygon
ApplyLineDashing( const basegfx::B2DPolygon
& rPolygon
, sal_uInt16 nDashing
, MapUnit eUnit
)
654 std::vector
< double > aPattern
= GetDashing( nDashing
, eUnit
);
655 basegfx::B2DPolyPolygon aPolygons
;
656 if ( ! aPattern
.empty() )
657 basegfx::tools::applyLineDashing( rPolygon
, aPattern
, &aPolygons
);
659 aPolygons
.append( rPolygon
);
664 basegfx::B2DPolyPolygon
ApplyLineDashing( const basegfx::B2DPolygon
& rPolygon
, sal_uInt16 nDashing
, MapUnit eUnit
, double fScale
)
666 std::vector
< double > aPattern
= GetDashing( nDashing
, eUnit
);
667 std::vector
< double >::iterator i
= aPattern
.begin();
668 while( i
!= aPattern
.end() ) {
673 basegfx::B2DPolyPolygon aPolygons
;
674 if ( ! aPattern
.empty() )
675 basegfx::tools::applyLineDashing( rPolygon
, aPattern
, &aPolygons
);
677 aPolygons
.append( rPolygon
);
682 void DrawLine( OutputDevice
& rDev
, const Point
& rP1
, const Point
& rP2
,
683 sal_uInt32 nWidth
, sal_uInt16 nDashing
)
685 DrawLine( rDev
, basegfx::B2DPoint( rP1
.X(), rP1
.Y() ),
686 basegfx::B2DPoint( rP2
.X(), rP2
.Y( ) ), nWidth
, nDashing
);
689 void DrawLine( OutputDevice
& rDev
, const basegfx::B2DPoint
& rP1
, const basegfx::B2DPoint
& rP2
,
690 sal_uInt32 nWidth
, sal_uInt16 nDashing
)
692 basegfx::B2DPolygon aPolygon
;
693 aPolygon
.append( rP1
);
694 aPolygon
.append( rP2
);
695 lclDrawPolygon( rDev
, aPolygon
, nWidth
, nDashing
);
699 void LineListBox::ImpGetLine( long nLine1
, long nLine2
, long nDistance
,
700 Color aColor1
, Color aColor2
, Color aColorDist
,
701 sal_uInt16 nStyle
, Bitmap
& rBmp
)
703 //TODO, rather than including the " " text to force
704 //the line height, better would be do drop
705 //this calculation and draw a bitmap of height
706 //equal to normal text line and center the
708 long nMinWidth
= GetTextWidth(OUString("----------"));
709 Size aSize
= CalcSubEditSize();
710 aSize
.Width() = std::max(nMinWidth
, aSize
.Width());
711 aSize
.Width() -= aTxtSize
.Width();
713 aSize
.Height() = aTxtSize
.Height();
715 // SourceUnit nach Twips
716 if ( eSourceUnit
== FUNIT_POINT
)
724 aSize
= aVirDev
.PixelToLogic( aSize
);
725 long nPix
= aVirDev
.PixelToLogic( Size( 0, 1 ) ).Height();
726 sal_uInt32 n1
= nLine1
;
727 sal_uInt32 n2
= nLine2
;
728 long nDist
= nDistance
;
738 long nVirHeight
= n1
+nDist
+n2
;
739 if ( nVirHeight
> aSize
.Height() )
740 aSize
.Height() = nVirHeight
;
741 // negative Breiten muss und darf man nicht painten
742 if ( aSize
.Width() > 0 )
744 Size aVirSize
= aVirDev
.LogicToPixel( aSize
);
745 if ( aVirDev
.GetOutputSizePixel() != aVirSize
)
746 aVirDev
.SetOutputSizePixel( aVirSize
);
747 aVirDev
.SetFillColor( aColorDist
);
748 aVirDev
.DrawRect( Rectangle( Point(), aSize
) );
750 aVirDev
.SetFillColor( aColor1
);
752 double y1
= double( n1
) / 2;
753 svtools::DrawLine( aVirDev
, basegfx::B2DPoint( 0, y1
), basegfx::B2DPoint( aSize
.Width( ), y1
), n1
, nStyle
);
757 double y2
= n1
+ nDist
+ double( n2
) / 2;
758 aVirDev
.SetFillColor( aColor2
);
759 svtools::DrawLine( aVirDev
, basegfx::B2DPoint( 0, y2
), basegfx::B2DPoint( aSize
.Width(), y2
), n2
, STYLE_SOLID
);
761 rBmp
= aVirDev
.GetBitmap( Point(), Size( aSize
.Width(), n1
+nDist
+n2
) );
765 // -----------------------------------------------------------------------
767 void LineListBox::ImplInit()
769 aTxtSize
.Width() = GetTextWidth( OUString( " " ) );
770 aTxtSize
.Height() = GetTextHeight();
771 pLineList
= new ImpLineList();
773 eSourceUnit
= FUNIT_POINT
;
775 aVirDev
.SetLineColor();
776 aVirDev
.SetMapMode( MapMode( MAP_TWIP
) );
778 UpdatePaintLineColor();
781 // -----------------------------------------------------------------------
783 LineListBox::LineListBox( Window
* pParent
, WinBits nWinStyle
) :
784 ListBox( pParent
, nWinStyle
),
788 maPaintCol( COL_BLACK
)
793 extern "C" SAL_DLLPUBLIC_EXPORT Window
* SAL_CALL
makeLineListBox(Window
*pParent
, VclBuilder::stringmap
&rMap
)
795 bool bDropdown
= extractDropdown(rMap
);
796 WinBits nWinBits
= WB_LEFT
|WB_VCENTER
|WB_3DLOOK
|WB_TABSTOP
;
798 nWinBits
|= WB_DROPDOWN
;
799 LineListBox
*pListBox
= new LineListBox(pParent
, nWinBits
);
801 pListBox
->EnableAutoSize(true);
805 // -----------------------------------------------------------------------
807 LineListBox::LineListBox( Window
* pParent
, const ResId
& rResId
) :
808 ListBox( pParent
, rResId
),
812 maPaintCol( COL_BLACK
)
817 // -----------------------------------------------------------------------
819 LineListBox::~LineListBox()
821 for ( size_t i
= 0, n
= pLineList
->size(); i
< n
; ++i
) {
822 if ( (*pLineList
)[ i
] ) {
823 delete (*pLineList
)[ i
];
830 sal_uInt16
LineListBox::GetStylePos( sal_uInt16 nListPos
, long nWidth
)
832 sal_uInt16 nPos
= LISTBOX_ENTRY_NOTFOUND
;
833 if ( m_sNone
.Len( ) > 0 )
838 sal_uInt16 nCount
= pLineList
->size();
839 while ( nPos
== LISTBOX_ENTRY_NOTFOUND
&& i
< nCount
)
841 ImpLineListData
* pData
= (*pLineList
)[ i
];
842 if ( pData
&& pData
->GetMinWidth() <= nWidth
)
855 void LineListBox::SelectEntry( sal_uInt16 nStyle
, sal_Bool bSelect
)
857 sal_uInt16 nPos
= GetEntryPos( nStyle
);
858 if ( nPos
!= LISTBOX_ENTRY_NOTFOUND
)
859 ListBox::SelectEntryPos( nPos
, bSelect
);
862 // -----------------------------------------------------------------------
864 sal_uInt16
LineListBox::InsertEntry( const XubString
& rStr
, sal_uInt16 nPos
)
866 nPos
= ListBox::InsertEntry( rStr
, nPos
);
867 if ( nPos
!= LISTBOX_ERROR
) {
868 if ( nPos
< pLineList
->size() ) {
869 ImpLineList::iterator it
= pLineList
->begin();
870 ::std::advance( it
, nPos
);
871 pLineList
->insert( it
, reinterpret_cast<ImpLineListData
*>(NULL
) );
873 pLineList
->push_back( NULL
);
879 // -----------------------------------------------------------------------
881 void LineListBox::InsertEntry(
882 BorderWidthImpl aWidthImpl
,
883 sal_uInt16 nStyle
, long nMinWidth
,
884 Color ( *pColor1Fn
)( Color
), Color ( *pColor2Fn
)( Color
),
885 Color ( *pColorDistFn
)( Color
, Color
) )
887 ImpLineListData
* pData
= new ImpLineListData(
888 aWidthImpl
, nStyle
, nMinWidth
,
889 pColor1Fn
, pColor2Fn
, pColorDistFn
);
890 pLineList
->push_back( pData
);
893 // -----------------------------------------------------------------------
895 void LineListBox::RemoveEntry( sal_uInt16 nPos
)
897 ListBox::RemoveEntry( nPos
);
899 if ( nPos
< pLineList
->size() ) {
900 ImpLineList::iterator it
= pLineList
->begin();
901 ::std::advance( it
, nPos
);
902 if ( *it
) delete *it
;
903 pLineList
->erase( it
);
907 // -----------------------------------------------------------------------
909 void LineListBox::Clear()
911 for ( size_t i
= 0, n
= pLineList
->size(); i
< n
; ++i
) {
912 if ( (*pLineList
)[ i
] ) {
913 delete (*pLineList
)[ i
];
921 // -----------------------------------------------------------------------
923 sal_uInt16
LineListBox::GetEntryPos( sal_uInt16 nStyle
) const
925 for ( size_t i
= 0, n
= pLineList
->size(); i
< n
; ++i
) {
926 ImpLineListData
* pData
= (*pLineList
)[ i
];
929 if ( GetEntryStyle( i
) == nStyle
)
932 if ( m_sNone
.Len() > 0 )
934 return (sal_uInt16
)nPos
;
938 return LISTBOX_ENTRY_NOTFOUND
;
941 // -----------------------------------------------------------------------
943 sal_uInt16
LineListBox::GetEntryStyle( sal_uInt16 nPos
) const
945 ImpLineListData
* pData
= (nPos
< pLineList
->size()) ? (*pLineList
)[ nPos
] : NULL
;
946 return ( pData
) ? pData
->GetStyle() : STYLE_NONE
;
949 // -----------------------------------------------------------------------
951 sal_Bool
LineListBox::UpdatePaintLineColor( void )
953 sal_Bool bRet
= sal_True
;
954 const StyleSettings
& rSettings
= GetSettings().GetStyleSettings();
955 Color
aNewCol( rSettings
.GetWindowColor().IsDark()? rSettings
.GetLabelTextColor() : aColor
);
957 bRet
= aNewCol
!= maPaintCol
;
960 maPaintCol
= aNewCol
;
965 void LineListBox::UpdateEntries( long nOldWidth
)
967 SetUpdateMode( sal_False
);
969 UpdatePaintLineColor( );
971 sal_uInt16 nSelEntry
= GetSelectEntryPos();
972 sal_uInt16 nTypePos
= GetStylePos( nSelEntry
, nOldWidth
);
974 // Remove the old entries
975 while ( GetEntryCount( ) > 0 )
976 ListBox::RemoveEntry( 0 );
978 // Add the new entries based on the defined width
979 if ( m_sNone
.Len( ) > 0 )
980 ListBox::InsertEntry( m_sNone
, LISTBOX_APPEND
);
983 sal_uInt16 nCount
= pLineList
->size( );
986 ImpLineListData
* pData
= (*pLineList
)[ n
];
987 if ( pData
&& pData
->GetMinWidth() <= m_nWidth
)
990 ImpGetLine( pData
->GetLine1ForWidth( m_nWidth
),
991 pData
->GetLine2ForWidth( m_nWidth
),
992 pData
->GetDistForWidth( m_nWidth
),
993 GetColorLine1( GetEntryCount( ) ),
994 GetColorLine2( GetEntryCount( ) ),
995 GetColorDist( GetEntryCount( ) ),
996 pData
->GetStyle(), aBmp
);
997 ListBox::InsertEntry( OUString( " " ), aBmp
, LISTBOX_APPEND
);
999 SelectEntryPos( GetEntryCount() - 1 );
1001 else if ( n
== nTypePos
)
1006 SetUpdateMode( sal_True
);
1010 // -----------------------------------------------------------------------
1012 Color
LineListBox::GetColorLine1( sal_uInt16 nPos
)
1014 Color rResult
= GetPaintColor( );
1016 sal_uInt16 nStyle
= GetStylePos( nPos
, m_nWidth
);
1017 ImpLineListData
* pData
= (*pLineList
)[ nStyle
];
1019 rResult
= pData
->GetColorLine1( GetColor( ) );
1024 Color
LineListBox::GetColorLine2( sal_uInt16 nPos
)
1026 Color rResult
= GetPaintColor( );
1028 sal_uInt16 nStyle
= GetStylePos( nPos
, m_nWidth
);
1029 ImpLineListData
* pData
= (*pLineList
)[ nStyle
];
1031 rResult
= pData
->GetColorLine2( GetColor( ) );
1036 Color
LineListBox::GetColorDist( sal_uInt16 nPos
)
1038 Color rResult
= GetSettings().GetStyleSettings().GetFieldColor();
1040 sal_uInt16 nStyle
= GetStylePos( nPos
, m_nWidth
);
1041 ImpLineListData
* pData
= (*pLineList
)[ nStyle
];
1043 rResult
= pData
->GetColorDist( GetColor( ), rResult
);
1048 // -----------------------------------------------------------------------
1050 void LineListBox::DataChanged( const DataChangedEvent
& rDCEvt
)
1052 ListBox::DataChanged( rDCEvt
);
1054 if( ( rDCEvt
.GetType() == DATACHANGED_SETTINGS
) && ( rDCEvt
.GetFlags() & SETTINGS_STYLE
) )
1055 UpdateEntries( m_nWidth
);
1059 // ===================================================================
1061 // ===================================================================
1063 FontNameBox::FontNameBox( Window
* pParent
, WinBits nWinStyle
) :
1064 ComboBox( pParent
, nWinStyle
)
1067 mbWYSIWYG
= sal_False
;
1068 InitFontMRUEntriesFile();
1071 // -------------------------------------------------------------------
1073 FontNameBox::FontNameBox( Window
* pParent
, const ResId
& rResId
) :
1074 ComboBox( pParent
, rResId
)
1077 mbWYSIWYG
= sal_False
;
1078 InitFontMRUEntriesFile();
1081 extern "C" SAL_DLLPUBLIC_EXPORT Window
* SAL_CALL
makeFontNameBox(Window
*pParent
, VclBuilder::stringmap
&rMap
)
1083 bool bDropdown
= extractDropdown(rMap
);
1084 WinBits nWinBits
= WB_LEFT
|WB_VCENTER
|WB_3DLOOK
|WB_TABSTOP
;
1086 nWinBits
|= WB_DROPDOWN
;
1087 FontNameBox
*pListBox
= new FontNameBox(pParent
, nWinBits
);
1089 pListBox
->EnableAutoSize(true);
1093 // -------------------------------------------------------------------
1095 FontNameBox::~FontNameBox()
1097 SaveMRUEntries (maFontMRUEntriesFile
);
1098 ImplDestroyFontList();
1101 // -------------------------------------------------------------------
1103 void FontNameBox::SaveMRUEntries( const String
& aFontMRUEntriesFile
, sal_Unicode cSep
) const
1105 OString
aEntries(OUStringToOString(GetMRUEntries(cSep
),
1106 RTL_TEXTENCODING_UTF8
));
1108 if (aEntries
.isEmpty() || !aFontMRUEntriesFile
.Len())
1111 SvFileStream aStream
;
1112 aStream
.Open( aFontMRUEntriesFile
, STREAM_WRITE
| STREAM_TRUNC
);
1113 if( ! (aStream
.IsOpen() && aStream
.IsWritable()) )
1115 #if OSL_DEBUG_LEVEL > 1
1116 fprintf( stderr
, "FontNameBox::SaveMRUEntries: opening mru entries file %s failed\n", OUStringToOString(aFontMRUEntriesFile
, RTL_TEXTENCODING_UTF8
).getStr() );
1121 aStream
.SetLineDelimiter( LINEEND_LF
);
1122 aStream
.WriteLine( aEntries
);
1123 aStream
.WriteLine( OString() );
1126 // -------------------------------------------------------------------
1128 void FontNameBox::LoadMRUEntries( const String
& aFontMRUEntriesFile
, sal_Unicode cSep
)
1130 if( ! aFontMRUEntriesFile
.Len() )
1133 SvFileStream
aStream( aFontMRUEntriesFile
, STREAM_READ
);
1134 if( ! aStream
.IsOpen() )
1136 #if OSL_DEBUG_LEVEL > 1
1137 fprintf( stderr
, "FontNameBox::LoadMRUEntries: opening mru entries file %s failed\n", OUStringToOString(aFontMRUEntriesFile
, RTL_TEXTENCODING_UTF8
).getStr() );
1143 aStream
.ReadLine( aLine
);
1144 OUString aEntries
= OStringToOUString(aLine
,
1145 RTL_TEXTENCODING_UTF8
);
1146 SetMRUEntries( aEntries
, cSep
);
1149 // ------------------------------------------------------------------
1151 void FontNameBox::InitFontMRUEntriesFile()
1153 OUString
sUserConfigDir("${$BRAND_BASE_DIR/program/" SAL_CONFIGFILE( "bootstrap") "::UserInstallation}");
1154 rtl::Bootstrap::expandMacros(sUserConfigDir
);
1156 maFontMRUEntriesFile
= sUserConfigDir
;
1157 if( maFontMRUEntriesFile
.Len() )
1159 maFontMRUEntriesFile
.AppendAscii( FONTNAMEBOXMRUENTRIESFILE
);
1163 // -------------------------------------------------------------------
1165 void FontNameBox::ImplDestroyFontList()
1170 // -------------------------------------------------------------------
1172 void FontNameBox::Fill( const FontList
* pList
)
1174 // store old text and clear box
1175 XubString aOldText
= GetText();
1176 XubString rEntries
= GetMRUEntries();
1177 sal_Bool bLoadFromFile
= ! rEntries
.Len();
1180 ImplDestroyFontList();
1181 mpFontList
= new ImplFontList
;
1184 sal_uInt16 nFontCount
= pList
->GetFontNameCount();
1185 for ( sal_uInt16 i
= 0; i
< nFontCount
; i
++ )
1187 const FontInfo
& rFontInfo
= pList
->GetFontName( i
);
1188 sal_uLong nIndex
= InsertEntry( rFontInfo
.GetName() );
1189 if ( nIndex
!= LISTBOX_ERROR
)
1191 if ( nIndex
< mpFontList
->size() ) {
1192 ImplFontList::iterator it
= mpFontList
->begin();
1193 ::std::advance( it
, nIndex
);
1194 mpFontList
->insert( it
, rFontInfo
);
1196 mpFontList
->push_back( rFontInfo
);
1201 if ( bLoadFromFile
)
1202 LoadMRUEntries (maFontMRUEntriesFile
);
1204 SetMRUEntries( rEntries
);
1206 ImplCalcUserItemSize();
1209 if ( aOldText
.Len() )
1210 SetText( aOldText
);
1213 // -------------------------------------------------------------------
1215 void FontNameBox::EnableWYSIWYG( sal_Bool bEnable
)
1217 if ( bEnable
!= mbWYSIWYG
)
1219 mbWYSIWYG
= bEnable
;
1220 EnableUserDraw( mbWYSIWYG
);
1221 ImplCalcUserItemSize();
1225 // -------------------------------------------------------------------
1227 void FontNameBox::ImplCalcUserItemSize()
1230 if ( mbWYSIWYG
&& mpFontList
)
1232 aUserItemSz
= Size(MAXPREVIEWWIDTH
, GetTextHeight() );
1233 aUserItemSz
.Height() *= 16;
1234 aUserItemSz
.Height() /= 10;
1236 SetUserItemSize( aUserItemSz
);
1241 long shrinkFontToFit(OUString
&rSampleText
, long nH
, Font
&rFont
, OutputDevice
&rDevice
, Rectangle
&rTextRect
)
1245 Size
aSize( rFont
.GetSize() );
1247 //Make sure it fits in the available height
1248 while (aSize
.Height() > 0)
1250 if (!rDevice
.GetTextBoundRect(rTextRect
, rSampleText
, 0, 0))
1252 if (rTextRect
.GetHeight() <= nH
)
1254 nWidth
= rTextRect
.GetWidth();
1258 aSize
.Height() -= EXTRAFONTSIZE
;
1259 rFont
.SetSize(aSize
);
1260 rDevice
.SetFont(rFont
);
1267 // -------------------------------------------------------------------
1269 void FontNameBox::UserDraw( const UserDrawEvent
& rUDEvt
)
1271 assert( mpFontList
);
1273 FontInfo
& rInfo
= (*mpFontList
)[ rUDEvt
.GetItemId() ];
1274 Point aTopLeft
= rUDEvt
.GetRect().TopLeft();
1275 long nX
= aTopLeft
.X();
1276 long nH
= rUDEvt
.GetRect().GetHeight();
1280 nX
+= IMGOUTERTEXTSPACE
;
1282 const bool bSymbolFont
= isSymbolFont(rInfo
);
1284 Color aTextColor
= rUDEvt
.GetDevice()->GetTextColor();
1285 Font
aOldFont( rUDEvt
.GetDevice()->GetFont() );
1286 Size
aSize( aOldFont
.GetSize() );
1287 aSize
.Height() += EXTRAFONTSIZE
;
1288 Font
aFont( rInfo
);
1289 aFont
.SetSize( aSize
);
1290 rUDEvt
.GetDevice()->SetFont( aFont
);
1291 rUDEvt
.GetDevice()->SetTextColor( aTextColor
);
1293 bool bUsingCorrectFont
= true;
1294 Rectangle aTextRect
;
1296 // Preview the font name
1297 OUString sFontName
= rInfo
.GetName();
1299 //If it shouldn't or can't draw its own name because it doesn't have the glyphs
1300 if (!canRenderNameOfSelectedFont(*rUDEvt
.GetDevice()))
1301 bUsingCorrectFont
= false;
1304 //Make sure it fits in the available height, shrinking the font if necessary
1305 bUsingCorrectFont
= shrinkFontToFit(sFontName
, nH
, aFont
, *rUDEvt
.GetDevice(), aTextRect
) != 0;
1308 if (!bUsingCorrectFont
)
1310 rUDEvt
.GetDevice()->SetFont(aOldFont
);
1311 rUDEvt
.GetDevice()->GetTextBoundRect(aTextRect
, sFontName
, 0, 0);
1314 long nTextHeight
= aTextRect
.GetHeight();
1315 long nDesiredGap
= (nH
-nTextHeight
)/2;
1316 long nVertAdjust
= nDesiredGap
- aTextRect
.Top();
1317 Point
aPos( nX
, aTopLeft
.Y() + nVertAdjust
);
1318 rUDEvt
.GetDevice()->DrawText( aPos
, sFontName
);
1319 long nTextX
= aPos
.X() + aTextRect
.GetWidth() + GAPTOEXTRAPREVIEW
;
1321 if (!bUsingCorrectFont
)
1322 rUDEvt
.GetDevice()->SetFont( aFont
);
1324 OUString sSampleText
;
1328 const bool bNameBeginsWithLatinText
= rInfo
.GetName().GetChar(0) <= 'z';
1330 if (bNameBeginsWithLatinText
|| !bUsingCorrectFont
)
1331 sSampleText
= makeShortRepresentativeTextForSelectedFont(*rUDEvt
.GetDevice());
1334 //If we're not a symbol font, but could neither render our own name and
1335 //we can't determine what script it would like to render, then try a
1336 //few well known scripts
1337 if (sSampleText
.isEmpty() && !bUsingCorrectFont
)
1339 static const UScriptCode aScripts
[] =
1368 USCRIPT_SIMPLIFIED_HAN
,
1369 USCRIPT_TRADITIONAL_HAN
,
1374 for (size_t i
= 0; i
< SAL_N_ELEMENTS(aScripts
); ++i
)
1376 OUString sText
= makeShortRepresentativeTextForScript(aScripts
[i
]);
1377 if (!sText
.isEmpty())
1379 bool bHasSampleTextGlyphs
= (STRING_LEN
== rUDEvt
.GetDevice()->HasGlyphs(aFont
, sText
));
1380 if (bHasSampleTextGlyphs
)
1382 sSampleText
= sText
;
1388 static const UScriptCode aMinimalScripts
[] =
1390 USCRIPT_HEBREW
, //e.g. biblical hebrew
1394 for (size_t i
= 0; i
< SAL_N_ELEMENTS(aMinimalScripts
); ++i
)
1396 OUString sText
= makeShortMinimalTextForScript(aMinimalScripts
[i
]);
1397 if (!sText
.isEmpty())
1399 bool bHasSampleTextGlyphs
= (STRING_LEN
== rUDEvt
.GetDevice()->HasGlyphs(aFont
, sText
));
1400 if (bHasSampleTextGlyphs
)
1402 sSampleText
= sText
;
1409 //If we're a symbol font, or for some reason the font still couldn't
1410 //render something representative of what it would like to render then
1411 //make up some semi-random text that it *can* display
1412 if (bSymbolFont
|| (!bUsingCorrectFont
&& sSampleText
.isEmpty()))
1413 sSampleText
= makeShortRepresentativeSymbolTextForSelectedFont(*rUDEvt
.GetDevice());
1415 if (!sSampleText
.isEmpty())
1417 const Size
&rItemSize
= rUDEvt
.GetDevice()->GetOutputSize();
1418 //leave a little border at the edge
1419 long nSpace
= rItemSize
.Width() - nTextX
- IMGOUTERTEXTSPACE
;
1422 //Make sure it fits in the available height, and get how wide that would be
1423 long nWidth
= shrinkFontToFit(sSampleText
, nH
, aFont
, *rUDEvt
.GetDevice(), aTextRect
);
1424 //Chop letters off until it fits in the available width
1425 while (nWidth
> nSpace
|| nWidth
> MAXPREVIEWWIDTH
)
1427 sSampleText
= sSampleText
.copy(0, sSampleText
.getLength()-1);
1428 nWidth
= rUDEvt
.GetDevice()->GetTextBoundRect(aTextRect
, sSampleText
, 0, 0) ?
1429 aTextRect
.GetWidth() : 0;
1432 //center the text on the line
1433 if (!sSampleText
.isEmpty() && nWidth
)
1435 nTextHeight
= aTextRect
.GetHeight();
1436 nDesiredGap
= (nH
-nTextHeight
)/2;
1437 nVertAdjust
= nDesiredGap
- aTextRect
.Top();
1438 aPos
= Point(nTextX
+ nSpace
- nWidth
, aTopLeft
.Y() + nVertAdjust
);
1439 rUDEvt
.GetDevice()->DrawText( aPos
, sSampleText
);
1444 rUDEvt
.GetDevice()->SetFont( aOldFont
);
1445 DrawEntry( rUDEvt
, sal_False
, sal_False
); // draw separator
1449 DrawEntry( rUDEvt
, sal_True
, sal_True
);
1453 // ===================================================================
1455 // ===================================================================
1457 FontStyleBox::FontStyleBox( Window
* pParent
, const ResId
& rResId
) :
1458 ComboBox( pParent
, rResId
)
1460 aLastStyle
= GetText();
1463 FontStyleBox::FontStyleBox( Window
* pParent
, WinBits nBits
) :
1464 ComboBox( pParent
, nBits
)
1466 aLastStyle
= GetText();
1469 extern "C" SAL_DLLPUBLIC_EXPORT Window
* SAL_CALL
makeFontStyleBox(Window
*pParent
, VclBuilder::stringmap
&rMap
)
1471 bool bDropdown
= extractDropdown(rMap
);
1472 WinBits nWinBits
= WB_LEFT
|WB_VCENTER
|WB_3DLOOK
|WB_TABSTOP
;
1474 nWinBits
|= WB_DROPDOWN
;
1475 FontStyleBox
*pListBox
= new FontStyleBox(pParent
, nWinBits
);
1477 pListBox
->EnableAutoSize(true);
1481 FontStyleBox::~FontStyleBox()
1485 // -------------------------------------------------------------------
1487 void FontStyleBox::Select()
1489 // keep text over fill operation
1490 aLastStyle
= GetText();
1494 // -------------------------------------------------------------------
1496 void FontStyleBox::LoseFocus()
1498 // keep text over fill operation
1499 aLastStyle
= GetText();
1500 ComboBox::LoseFocus();
1503 // -------------------------------------------------------------------
1505 void FontStyleBox::Modify()
1507 CharClass
aChrCls( ::comphelper::getProcessComponentContext(),
1508 GetSettings().GetLanguageTag() );
1509 XubString aStr
= GetText();
1510 sal_uInt16 nEntryCount
= GetEntryCount();
1512 if ( GetEntryPos( aStr
) == COMBOBOX_ENTRY_NOTFOUND
)
1514 aStr
= aChrCls
.uppercase(aStr
);
1515 for ( sal_uInt16 i
= 0; i
< nEntryCount
; i
++ )
1517 XubString aEntryText
= aChrCls
.uppercase(GetEntry(i
));
1519 if ( aStr
== aEntryText
)
1521 SetText( GetEntry( i
) );
1530 // -------------------------------------------------------------------
1532 void FontStyleBox::Fill( const XubString
& rName
, const FontList
* pList
)
1534 // note: this method must call ComboBox::SetText(),
1535 // else aLastStyle will overwritten
1536 // store prior selection position and clear box
1537 XubString aOldText
= GetText();
1538 sal_uInt16 nPos
= GetEntryPos( aOldText
);
1541 // does a font with this name already exist?
1542 sal_Handle hFontInfo
= pList
->GetFirstFontInfo( rName
);
1545 OUString aStyleText
;
1546 FontWeight eLastWeight
= WEIGHT_DONTKNOW
;
1547 FontItalic eLastItalic
= ITALIC_NONE
;
1548 FontWidth eLastWidth
= WIDTH_DONTKNOW
;
1549 sal_Bool bNormal
= sal_False
;
1550 sal_Bool bItalic
= sal_False
;
1551 sal_Bool bBold
= sal_False
;
1552 sal_Bool bBoldItalic
= sal_False
;
1553 sal_Bool bInsert
= sal_False
;
1557 aInfo
= pList
->GetFontInfo( hFontInfo
);
1559 FontWeight eWeight
= aInfo
.GetWeight();
1560 FontItalic eItalic
= aInfo
.GetItalic();
1561 FontWidth eWidth
= aInfo
.GetWidthType();
1562 // Only if the attributes are different, we insert the
1563 // Font to avoid double Entries in different languages
1564 if ( (eWeight
!= eLastWeight
) || (eItalic
!= eLastItalic
) ||
1565 (eWidth
!= eLastWidth
) )
1568 InsertEntry( aStyleText
);
1570 if ( eWeight
<= WEIGHT_NORMAL
)
1572 if ( eItalic
!= ITALIC_NONE
)
1579 if ( eItalic
!= ITALIC_NONE
)
1580 bBoldItalic
= sal_True
;
1585 // For wrong StyleNames we replace this with the correct once
1586 aStyleText
= pList
->GetStyleName( aInfo
);
1587 bInsert
= GetEntryPos( aStyleText
) == LISTBOX_ENTRY_NOTFOUND
;
1590 aStyleText
= pList
->GetStyleName( eWeight
, eItalic
);
1591 bInsert
= GetEntryPos( aStyleText
) == LISTBOX_ENTRY_NOTFOUND
;
1594 eLastWeight
= eWeight
;
1595 eLastItalic
= eItalic
;
1596 eLastWidth
= eWidth
;
1602 // If we have two names for the same attributes
1603 // we prefer the translated standard names
1604 const OUString
& rAttrStyleText
= pList
->GetStyleName( eWeight
, eItalic
);
1605 if (rAttrStyleText
!= aStyleText
)
1607 OUString aTempStyleText
= pList
->GetStyleName( aInfo
);
1608 if (rAttrStyleText
== aTempStyleText
)
1609 aStyleText
= rAttrStyleText
;
1610 bInsert
= GetEntryPos( aStyleText
) == LISTBOX_ENTRY_NOTFOUND
;
1615 if ( !bItalic
&& (aStyleText
== pList
->GetItalicStr()) )
1617 else if ( !bBold
&& (aStyleText
== pList
->GetBoldStr()) )
1619 else if ( !bBoldItalic
&& (aStyleText
== pList
->GetBoldItalicStr()) )
1620 bBoldItalic
= sal_True
;
1622 hFontInfo
= pList
->GetNextFontInfo( hFontInfo
);
1626 InsertEntry( aStyleText
);
1628 // Bestimmte Styles als Nachbildung
1632 InsertEntry( pList
->GetItalicStr() );
1634 InsertEntry( pList
->GetBoldStr() );
1638 if ( bNormal
|| bItalic
|| bBold
)
1639 InsertEntry( pList
->GetBoldItalicStr() );
1641 if ( aOldText
.Len() )
1643 if ( GetEntryPos( aLastStyle
) != LISTBOX_ENTRY_NOTFOUND
)
1644 ComboBox::SetText( aLastStyle
);
1647 if ( nPos
>= GetEntryCount() )
1648 ComboBox::SetText( GetEntry( 0 ) );
1650 ComboBox::SetText( GetEntry( nPos
) );
1656 // Wenn Font nicht, dann Standard-Styles einfuegen
1657 InsertEntry( pList
->GetNormalStr() );
1658 InsertEntry( pList
->GetItalicStr() );
1659 InsertEntry( pList
->GetBoldStr() );
1660 InsertEntry( pList
->GetBoldItalicStr() );
1661 if ( aOldText
.Len() )
1663 if ( nPos
> GetEntryCount() )
1664 ComboBox::SetText( GetEntry( 0 ) );
1666 ComboBox::SetText( GetEntry( nPos
) );
1671 // ===================================================================
1673 // ===================================================================
1675 FontSizeBox::FontSizeBox( Window
* pParent
, WinBits nWinSize
) :
1676 MetricBox( pParent
, nWinSize
)
1681 // -----------------------------------------------------------------------
1683 FontSizeBox::FontSizeBox( Window
* pParent
, const ResId
& rResId
) :
1684 MetricBox( pParent
, rResId
)
1689 extern "C" SAL_DLLPUBLIC_EXPORT Window
* SAL_CALL
makeFontSizeBox(Window
*pParent
, VclBuilder::stringmap
&rMap
)
1691 bool bDropdown
= extractDropdown(rMap
);
1692 WinBits nWinBits
= WB_LEFT
|WB_VCENTER
|WB_3DLOOK
|WB_TABSTOP
;
1694 nWinBits
|= WB_DROPDOWN
;
1695 FontSizeBox
* pListBox
= new FontSizeBox(pParent
, nWinBits
);
1697 pListBox
->EnableAutoSize(true);
1701 // -----------------------------------------------------------------------
1703 FontSizeBox::~FontSizeBox()
1707 // -----------------------------------------------------------------------
1709 void FontSizeBox::ImplInit()
1711 EnableAutocomplete( sal_False
);
1713 bRelativeMode
= sal_False
;
1714 bPtRelative
= sal_False
;
1715 bRelative
= sal_False
;
1716 bStdSize
= sal_False
;
1719 SetShowTrailingZeros( sal_False
);
1720 SetDecimalDigits( 1 );
1723 SetProminentEntryType( PROMINENT_MIDDLE
);
1726 // -----------------------------------------------------------------------
1728 void FontSizeBox::Reformat()
1730 FontSizeNames
aFontSizeNames( GetSettings().GetUILanguageTag().getLanguageType() );
1731 if ( !bRelativeMode
|| !aFontSizeNames
.IsEmpty() )
1733 long nNewValue
= aFontSizeNames
.Name2Size( GetText() );
1736 mnLastValue
= nNewValue
;
1741 MetricBox::Reformat();
1744 // -----------------------------------------------------------------------
1746 void FontSizeBox::Modify()
1748 MetricBox::Modify();
1750 if ( bRelativeMode
)
1752 XubString aStr
= comphelper::string::stripStart(GetText(), ' ');
1754 sal_Bool bNewMode
= bRelative
;
1755 sal_Bool bOldPtRelMode
= bPtRelative
;
1759 bPtRelative
= sal_False
;
1760 const sal_Unicode
* pStr
= aStr
.GetBuffer();
1763 if ( ((*pStr
< '0') || (*pStr
> '9')) && (*pStr
!= '%') )
1765 if ( ('-' == *pStr
|| '+' == *pStr
) && !bPtRelative
)
1766 bPtRelative
= sal_True
;
1767 else if ( bPtRelative
&& 'p' == *pStr
&& 't' == *++pStr
)
1771 bNewMode
= sal_False
;
1780 if ( STRING_NOTFOUND
!= aStr
.Search( '%' ) )
1782 bNewMode
= sal_True
;
1783 bPtRelative
= sal_False
;
1786 if ( '-' == aStr
.GetChar( 0 ) || '+' == aStr
.GetChar( 0 ) )
1788 bNewMode
= sal_True
;
1789 bPtRelative
= sal_True
;
1793 if ( bNewMode
!= bRelative
|| bPtRelative
!= bOldPtRelMode
)
1794 SetRelative( bNewMode
);
1798 // -----------------------------------------------------------------------
1800 void FontSizeBox::Fill( const FontInfo
* pInfo
, const FontList
* pList
)
1802 // remember for relative mode
1805 // no font sizes need to be set for relative mode
1810 const long* pTempAry
;
1811 const long* pAry
= 0;
1816 pAry
= pList
->GetSizeAry( *pInfo
);
1820 pAry
= pList
->GetStdSizeAry();
1823 // first insert font size names (for simplified/traditional chinese)
1824 FontSizeNames
aFontSizeNames( GetSettings().GetUILanguageTag().getLanguageType() );
1825 if ( pAry
== pList
->GetStdSizeAry() )
1827 // for standard sizes we don't need to bother
1828 if ( bStdSize
&& GetEntryCount() && aFontSizeNames
.IsEmpty() )
1830 bStdSize
= sal_True
;
1833 bStdSize
= sal_False
;
1835 Selection aSelection
= GetSelection();
1836 XubString aStr
= GetText();
1839 sal_uInt16 nPos
= 0;
1841 if ( !aFontSizeNames
.IsEmpty() )
1843 if ( pAry
== pList
->GetStdSizeAry() )
1845 // for scalable fonts all font size names
1846 sal_uLong nCount
= aFontSizeNames
.Count();
1847 for( sal_uLong i
= 0; i
< nCount
; i
++ )
1849 String aSizeName
= aFontSizeNames
.GetIndexName( i
);
1850 long nSize
= aFontSizeNames
.GetIndexSize( i
);
1851 ComboBox::InsertEntry( aSizeName
, nPos
);
1852 ComboBox::SetEntryData( nPos
, (void*)(-nSize
) ); // mark as special
1858 // for fixed size fonts only selectable font size names
1862 String aSizeName
= aFontSizeNames
.Size2Name( *pTempAry
);
1863 if ( aSizeName
.Len() )
1865 ComboBox::InsertEntry( aSizeName
, nPos
);
1866 ComboBox::SetEntryData( nPos
, (void*)(-(*pTempAry
)) ); // mark as special
1874 // then insert numerical font size values
1878 InsertValue( *pTempAry
, FUNIT_NONE
, nPos
);
1879 ComboBox::SetEntryData( nPos
, (void*)(*pTempAry
) );
1885 SetSelection( aSelection
);
1888 // -----------------------------------------------------------------------
1890 void FontSizeBox::EnableRelativeMode( sal_uInt16 nMin
, sal_uInt16 nMax
, sal_uInt16 nStep
)
1892 bRelativeMode
= sal_True
;
1896 SetUnit( FUNIT_POINT
);
1899 // -----------------------------------------------------------------------
1901 void FontSizeBox::EnablePtRelativeMode( short nMin
, short nMax
, short nStep
)
1903 bRelativeMode
= sal_True
;
1907 SetUnit( FUNIT_POINT
);
1910 // -----------------------------------------------------------------------
1912 void FontSizeBox::SetRelative( sal_Bool bNewRelative
)
1914 if ( bRelativeMode
)
1916 Selection aSelection
= GetSelection();
1917 XubString aStr
= comphelper::string::stripStart(GetText(), ' ');
1921 bRelative
= sal_True
;
1922 bStdSize
= sal_False
;
1926 SetDecimalDigits( 1 );
1927 SetMin( nPtRelMin
);
1928 SetMax( nPtRelMax
);
1929 SetUnit( FUNIT_POINT
);
1933 short i
= nPtRelMin
, n
= 0;
1934 // JP 30.06.98: more than 100 values are not useful
1935 while ( i
<= nPtRelMax
&& n
++ < 100 )
1943 SetDecimalDigits( 0 );
1946 SetCustomUnitText(OUString('%'));
1947 SetUnit( FUNIT_CUSTOM
);
1950 sal_uInt16 i
= nRelMin
;
1951 while ( i
<= nRelMax
)
1960 bRelative
= bPtRelative
= sal_False
;
1961 SetDecimalDigits( 1 );
1964 SetUnit( FUNIT_POINT
);
1966 Fill( &aFontInfo
, pFontList
);
1970 SetSelection( aSelection
);
1974 // -----------------------------------------------------------------------
1976 OUString
FontSizeBox::CreateFieldText( sal_Int64 nValue
) const
1978 OUString
sRet( MetricBox::CreateFieldText( nValue
) );
1979 if ( bRelativeMode
&& bPtRelative
&& (0 <= nValue
) && !sRet
.isEmpty() )
1984 // -----------------------------------------------------------------------
1986 void FontSizeBox::SetValue( sal_Int64 nNewValue
, FieldUnit eInUnit
)
1990 sal_Int64 nTempValue
= MetricField::ConvertValue( nNewValue
, GetBaseValue(), GetDecimalDigits(), eInUnit
, GetUnit() );
1991 FontSizeNames
aFontSizeNames( GetSettings().GetUILanguageTag().getLanguageType() );
1992 // conversion loses precision; however font sizes should
1993 // never have a problem with that
1994 String aName
= aFontSizeNames
.Size2Name( static_cast<long>(nTempValue
) );
1995 if ( aName
.Len() && (GetEntryPos( aName
) != LISTBOX_ENTRY_NOTFOUND
) )
1997 mnLastValue
= nTempValue
;
1999 mnFieldValue
= mnLastValue
;
2000 SetEmptyFieldValueData( sal_False
);
2005 MetricBox::SetValue( nNewValue
, eInUnit
);
2008 // -----------------------------------------------------------------------
2010 void FontSizeBox::SetValue( sal_Int64 nNewValue
)
2012 SetValue( nNewValue
, FUNIT_NONE
);
2015 // -----------------------------------------------------------------------
2017 sal_Int64
FontSizeBox::GetValue( sal_uInt16 nPos
, FieldUnit eOutUnit
) const
2021 sal_Int64 nComboVal
= static_cast<sal_Int64
>(reinterpret_cast<long>(ComboBox::GetEntryData( nPos
)));
2022 if ( nComboVal
< 0 ) // marked as special?
2024 return MetricField::ConvertValue( -nComboVal
, mnBaseValue
, GetDecimalDigits(),
2029 // do normal font size processing
2030 sal_Int64 nRetValue
= MetricBox::GetValue( nPos
, eOutUnit
);
2034 // -----------------------------------------------------------------------
2036 sal_Int64
FontSizeBox::GetValue( FieldUnit eOutUnit
) const
2040 FontSizeNames
aFontSizeNames( GetSettings().GetUILanguageTag().getLanguageType() );
2041 sal_Int64 nValue
= aFontSizeNames
.Name2Size( GetText() );
2043 return MetricField::ConvertValue( nValue
, GetBaseValue(), GetDecimalDigits(), GetUnit(), eOutUnit
);
2046 return MetricBox::GetValue( eOutUnit
);
2049 // -----------------------------------------------------------------------
2051 sal_Int64
FontSizeBox::GetValue() const
2053 // implementation not inline, because it is a virtual function
2054 return GetValue( FUNIT_NONE
);
2057 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */