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 <config_folders.h>
22 #include <i18nutil/unicode.hxx>
23 #include <tools/stream.hxx>
24 #include <vcl/builderfactory.hxx>
25 #include <vcl/svapp.hxx>
26 #include <vcl/field.hxx>
27 #include <vcl/helper.hxx>
28 #include <vcl/settings.hxx>
29 #include <sal/macros.h>
30 #include <comphelper/processfactory.hxx>
31 #include <comphelper/string.hxx>
32 #include <unotools/charclass.hxx>
34 #include <svtools/sampletext.hxx>
35 #include <svtools/svtresid.hxx>
36 #include <svtools/svtools.hrc>
37 #include <svtools/ctrlbox.hxx>
38 #include <svtools/ctrltool.hxx>
39 #include <svtools/borderhelper.hxx>
41 #include <vcl/i18nhelp.hxx>
42 #include <vcl/fontcapabilities.hxx>
43 #include <basegfx/polygon/b2dpolygon.hxx>
44 #include <basegfx/polygon/b2dpolygontools.hxx>
46 #include <com/sun/star/table/BorderLineStyle.hpp>
48 #include <rtl/bootstrap.hxx>
52 #define IMGOUTERTEXTSPACE 5
53 #define EXTRAFONTSIZE 5
54 #define GAPTOEXTRAPREVIEW 10
55 #define MAXPREVIEWWIDTH 120
58 #define FONTNAMEBOXMRUENTRIESFILE "/user/config/fontnameboxmruentries"
60 using namespace ::com::sun::star
;
62 class ImplColorListData
68 ImplColorListData() : aColor( COL_BLACK
) { bColor
= false; }
69 ImplColorListData( const Color
& rColor
) : aColor( rColor
) { bColor
= true; }
72 void ColorListBox::ImplInit()
74 pColorList
= new ImpColorList();
76 const StyleSettings
& rStyleSettings
= Application::GetSettings().GetStyleSettings();
77 aImageSize
= rStyleSettings
.GetListBoxPreviewDefaultPixelSize();
78 EnableUserDraw( true );
79 SetUserItemSize( aImageSize
);
82 void ColorListBox::ImplDestroyColorEntries()
84 for ( size_t n
= pColorList
->size(); n
; )
85 delete (*pColorList
)[ --n
];
89 ColorListBox::ColorListBox( vcl::Window
* pParent
, WinBits nWinStyle
) :
90 ListBox( pParent
, nWinStyle
)
93 SetEdgeBlending(true);
96 ColorListBox::ColorListBox( vcl::Window
* pParent
, const ResId
& rResId
) :
97 ListBox( pParent
, rResId
)
100 SetEdgeBlending(true);
103 VCL_BUILDER_DECL_FACTORY(ColorListBox
)
105 bool bDropdown
= VclBuilder::extractDropdown(rMap
);
106 WinBits nWinBits
= WB_LEFT
|WB_VCENTER
|WB_3DLOOK
|WB_TABSTOP
;
108 nWinBits
|= WB_DROPDOWN
;
109 VclPtrInstance
<ColorListBox
> pListBox(pParent
, nWinBits
);
111 pListBox
->EnableAutoSize(true);
115 ColorListBox::~ColorListBox()
120 void ColorListBox::dispose()
124 ImplDestroyColorEntries();
131 sal_Int32
ColorListBox::InsertEntry( const OUString
& rStr
, sal_Int32 nPos
)
133 nPos
= ListBox::InsertEntry( rStr
, nPos
);
134 if ( nPos
!= LISTBOX_ERROR
)
136 ImplColorListData
* pData
= new ImplColorListData
;
137 if ( static_cast<size_t>(nPos
) < pColorList
->size() )
139 ImpColorList::iterator it
= pColorList
->begin();
140 ::std::advance( it
, nPos
);
141 pColorList
->insert( it
, pData
);
145 pColorList
->push_back( pData
);
146 nPos
= pColorList
->size() - 1;
152 sal_Int32
ColorListBox::InsertEntry( const Color
& rColor
, const OUString
& rStr
,
155 nPos
= ListBox::InsertEntry( rStr
, nPos
);
156 if ( nPos
!= LISTBOX_ERROR
)
158 ImplColorListData
* pData
= new ImplColorListData( rColor
);
159 if ( static_cast<size_t>(nPos
) < pColorList
->size() )
161 ImpColorList::iterator it
= pColorList
->begin();
162 ::std::advance( it
, nPos
);
163 pColorList
->insert( it
, pData
);
167 pColorList
->push_back( pData
);
168 nPos
= pColorList
->size() - 1;
174 void ColorListBox::InsertAutomaticEntryColor(const Color
&rColor
)
176 // insert the "Automatic"-entry always on the first position
177 InsertEntry( rColor
, SVT_RESSTR(STR_SVT_AUTOMATIC_COLOR
), 0 );
180 void ColorListBox::RemoveEntry( sal_Int32 nPos
)
182 ListBox::RemoveEntry( nPos
);
183 if ( 0 <= nPos
&& static_cast<size_t>(nPos
) < pColorList
->size() )
185 ImpColorList::iterator it
= pColorList
->begin();
186 ::std::advance( it
, nPos
);
188 pColorList
->erase( it
);
192 void ColorListBox::Clear()
194 ImplDestroyColorEntries();
198 void ColorListBox::CopyEntries( const ColorListBox
& rBox
)
201 ImplDestroyColorEntries();
204 size_t nCount
= rBox
.pColorList
->size();
205 for ( size_t n
= 0; n
< nCount
; n
++ )
207 ImplColorListData
* pData
= (*rBox
.pColorList
)[ n
];
208 sal_Int32 nPos
= InsertEntry( rBox
.GetEntry( n
), LISTBOX_APPEND
);
209 if ( nPos
!= LISTBOX_ERROR
)
211 if ( static_cast<size_t>(nPos
) < pColorList
->size() )
213 ImpColorList::iterator it
= pColorList
->begin();
214 ::std::advance( it
, nPos
);
215 pColorList
->insert( it
, new ImplColorListData( *pData
) );
219 pColorList
->push_back( new ImplColorListData( *pData
) );
225 sal_Int32
ColorListBox::GetEntryPos( const Color
& rColor
) const
227 for( sal_Int32 n
= (sal_Int32
) pColorList
->size(); n
; )
229 ImplColorListData
* pData
= (*pColorList
)[ --n
];
230 if ( pData
->bColor
&& ( pData
->aColor
== rColor
) )
233 return LISTBOX_ENTRY_NOTFOUND
;
236 Color
ColorListBox::GetEntryColor( sal_Int32 nPos
) const
239 ImplColorListData
* pData
= ( 0 <= nPos
&& static_cast<size_t>(nPos
) < pColorList
->size() ) ?
240 (*pColorList
)[ nPos
] : NULL
;
241 if ( pData
&& pData
->bColor
)
242 aColor
= pData
->aColor
;
246 void ColorListBox::UserDraw( const UserDrawEvent
& rUDEvt
)
248 size_t nPos
= rUDEvt
.GetItemId();
249 ImplColorListData
* pData
= ( nPos
< pColorList
->size() ) ? (*pColorList
)[ nPos
] : NULL
;
254 Point
aPos( rUDEvt
.GetRect().TopLeft() );
257 aPos
.Y() += ( rUDEvt
.GetRect().GetHeight() - aImageSize
.Height() ) / 2;
259 const Rectangle
aRect(aPos
, aImageSize
);
261 vcl::RenderContext
* pRenderContext
= rUDEvt
.GetRenderContext();
262 pRenderContext
->Push();
263 pRenderContext
->SetFillColor(pData
->aColor
);
264 pRenderContext
->SetLineColor(pRenderContext
->GetTextColor());
265 pRenderContext
->DrawRect(aRect
);
266 pRenderContext
->Pop();
268 const StyleSettings
& rStyleSettings
= Application::GetSettings().GetStyleSettings();
269 const sal_uInt16
nEdgeBlendingPercent(GetEdgeBlending() ? rStyleSettings
.GetEdgeBlending() : 0);
271 if(nEdgeBlendingPercent
)
273 const Color
& rTopLeft(rStyleSettings
.GetEdgeBlendingTopLeftColor());
274 const Color
& rBottomRight(rStyleSettings
.GetEdgeBlendingBottomRightColor());
275 const sal_uInt8
nAlpha((nEdgeBlendingPercent
* 255) / 100);
276 const BitmapEx
aBlendFrame(createBlendFrame(aRect
.GetSize(), nAlpha
, rTopLeft
, rBottomRight
));
278 if(!aBlendFrame
.IsEmpty())
280 pRenderContext
->DrawBitmapEx(aRect
.TopLeft(), aBlendFrame
);
284 ListBox::DrawEntry( rUDEvt
, false, true, false );
287 ListBox::DrawEntry( rUDEvt
, false, true, true );
290 ListBox::DrawEntry( rUDEvt
, true, true, false );
293 BorderWidthImpl::BorderWidthImpl( BorderWidthImplFlags nFlags
, double nRate1
, double nRate2
, double nRateGap
):
297 m_nRateGap( nRateGap
)
301 BorderWidthImpl
& BorderWidthImpl::operator= ( const BorderWidthImpl
& r
)
303 m_nFlags
= r
.m_nFlags
;
304 m_nRate1
= r
.m_nRate1
;
305 m_nRate2
= r
.m_nRate2
;
306 m_nRateGap
= r
.m_nRateGap
;
310 bool BorderWidthImpl::operator== ( const BorderWidthImpl
& r
) const
312 return ( m_nFlags
== r
.m_nFlags
) &&
313 ( m_nRate1
== r
.m_nRate1
) &&
314 ( m_nRate2
== r
.m_nRate2
) &&
315 ( m_nRateGap
== r
.m_nRateGap
);
318 long BorderWidthImpl::GetLine1( long nWidth
) const
320 long result
= static_cast<long>(m_nRate1
);
321 if ( m_nFlags
& BorderWidthImplFlags::CHANGE_LINE1
)
323 long const nConstant2
= (m_nFlags
& BorderWidthImplFlags::CHANGE_LINE2
) ? 0 : m_nRate2
;
324 long const nConstantD
= (m_nFlags
& BorderWidthImplFlags::CHANGE_DIST
) ? 0 : m_nRateGap
;
325 result
= std::max
<long>(0,
326 static_cast<long>((m_nRate1
* nWidth
) + 0.5)
327 - (nConstant2
+ nConstantD
));
328 if (result
== 0 && m_nRate1
> 0.0 && nWidth
> 0)
329 { // fdo#51777: hack to essentially treat 1 twip DOUBLE border
330 result
= 1; // as 1 twip SINGLE border
336 long BorderWidthImpl::GetLine2( long nWidth
) const
338 long result
= static_cast<long>(m_nRate2
);
339 if ( m_nFlags
& BorderWidthImplFlags::CHANGE_LINE2
)
341 long const nConstant1
= (m_nFlags
& BorderWidthImplFlags::CHANGE_LINE1
) ? 0 : m_nRate1
;
342 long const nConstantD
= (m_nFlags
& BorderWidthImplFlags::CHANGE_DIST
) ? 0 : m_nRateGap
;
343 result
= std::max
<long>(0,
344 static_cast<long>((m_nRate2
* nWidth
) + 0.5)
345 - (nConstant1
+ nConstantD
));
350 long BorderWidthImpl::GetGap( long nWidth
) const
352 long result
= static_cast<long>(m_nRateGap
);
353 if ( m_nFlags
& BorderWidthImplFlags::CHANGE_DIST
)
355 long const nConstant1
= (m_nFlags
& BorderWidthImplFlags::CHANGE_LINE1
) ? 0 : m_nRate1
;
356 long const nConstant2
= (m_nFlags
& BorderWidthImplFlags::CHANGE_LINE2
) ? 0 : m_nRate2
;
357 result
= std::max
<long>(0,
358 static_cast<long>((m_nRateGap
* nWidth
) + 0.5)
359 - (nConstant1
+ nConstant2
));
362 // Avoid having too small distances (less than 0.1pt)
363 if ( result
< MINGAPWIDTH
&& m_nRate1
> 0 && m_nRate2
> 0 )
364 result
= MINGAPWIDTH
;
369 static double lcl_getGuessedWidth( long nTested
, double nRate
, bool nChanging
)
371 double nWidth
= -1.0;
373 nWidth
= double( nTested
) / nRate
;
376 if ( double( nTested
) == nRate
)
383 long BorderWidthImpl::GuessWidth( long nLine1
, long nLine2
, long nGap
)
385 std::vector
< double > aToCompare
;
386 bool bInvalid
= false;
388 bool bLine1Change
= bool( m_nFlags
& BorderWidthImplFlags::CHANGE_LINE1
);
389 double nWidth1
= lcl_getGuessedWidth( nLine1
, m_nRate1
, bLine1Change
);
391 aToCompare
.push_back( nWidth1
);
392 else if ( !bLine1Change
&& nWidth1
< 0 )
395 bool bLine2Change
= bool( m_nFlags
& BorderWidthImplFlags::CHANGE_LINE2
);
396 double nWidth2
= lcl_getGuessedWidth( nLine2
, m_nRate2
, bLine2Change
);
398 aToCompare
.push_back( nWidth2
);
399 else if ( !bLine2Change
&& nWidth2
< 0 )
402 bool bGapChange
= bool( m_nFlags
& BorderWidthImplFlags::CHANGE_DIST
);
403 double nWidthGap
= lcl_getGuessedWidth( nGap
, m_nRateGap
, bGapChange
);
404 if ( bGapChange
&& nGap
> MINGAPWIDTH
)
405 aToCompare
.push_back( nWidthGap
);
406 else if ( !bGapChange
&& nWidthGap
< 0 )
409 // non-constant line width factors must sum to 1
410 assert((((bLine1Change
) ? m_nRate1
: 0) +
411 ((bLine2Change
) ? m_nRate2
: 0) +
412 ((bGapChange
) ? m_nRateGap
: 0)) - 1.0 < 0.00001 );
415 if ( (!bInvalid
) && (!aToCompare
.empty()) )
417 nWidth
= *aToCompare
.begin();
418 std::vector
< double >::iterator pIt
= aToCompare
.begin();
419 while ( pIt
!= aToCompare
.end() && !bInvalid
)
421 bInvalid
= ( nWidth
!= *pIt
);
424 nWidth
= (bInvalid
) ? 0.0 : nLine1
+ nLine2
+ nGap
;
430 /** Utility class storing the border line width, style and colors. The widths
431 are defined in Twips.
433 class ImpLineListData
436 BorderWidthImpl m_aWidthImpl
;
438 Color ( *m_pColor1Fn
)( Color
);
439 Color ( *m_pColor2Fn
)( Color
);
440 Color ( *m_pColorDistFn
)( Color
, Color
);
446 ImpLineListData( BorderWidthImpl aWidthImpl
, sal_uInt16 nStyle
,
447 long nMinWidth
=0, Color ( *pColor1Fn
) ( Color
) = &sameColor
,
448 Color ( *pColor2Fn
) ( Color
) = &sameColor
, Color ( *pColorDistFn
) ( Color
, Color
) = &sameDistColor
);
450 /** Returns the computed width of the line 1 in twips. */
451 long GetLine1ForWidth( long nWidth
) { return m_aWidthImpl
.GetLine1( nWidth
); }
453 /** Returns the computed width of the line 2 in twips. */
454 long GetLine2ForWidth( long nWidth
) { return m_aWidthImpl
.GetLine2( nWidth
); }
456 /** Returns the computed width of the gap in twips. */
457 long GetDistForWidth( long nWidth
) { return m_aWidthImpl
.GetGap( nWidth
); }
459 Color
GetColorLine1( const Color
& aMain
);
460 Color
GetColorLine2( const Color
& aMain
);
461 Color
GetColorDist( const Color
& aMain
, const Color
& rDefault
);
463 /** Returns the minimum width in twips */
464 long GetMinWidth( ) { return m_nMinWidth
;}
465 sal_uInt16
GetStyle( ) { return m_nStyle
;}
468 ImpLineListData::ImpLineListData( BorderWidthImpl aWidthImpl
,
469 sal_uInt16 nStyle
, long nMinWidth
, Color ( *pColor1Fn
)( Color
),
470 Color ( *pColor2Fn
)( Color
), Color ( *pColorDistFn
)( Color
, Color
) ) :
471 m_aWidthImpl( aWidthImpl
),
472 m_pColor1Fn( pColor1Fn
),
473 m_pColor2Fn( pColor2Fn
),
474 m_pColorDistFn( pColorDistFn
),
475 m_nMinWidth( nMinWidth
),
481 Color
ImpLineListData::GetColorLine1( const Color
& rMain
)
483 return ( *m_pColor1Fn
)( rMain
);
486 Color
ImpLineListData::GetColorLine2( const Color
& rMain
)
488 return ( *m_pColor2Fn
)( rMain
);
491 Color
ImpLineListData::GetColorDist( const Color
& rMain
, const Color
& rDefault
)
493 return ( *m_pColorDistFn
)( rMain
, rDefault
);
496 sal_uInt16
LineListBox::GetSelectEntryStyle( sal_Int32 nSelIndex
) const
498 sal_uInt16 nStyle
= table::BorderLineStyle::SOLID
;
499 sal_Int32 nPos
= GetSelectEntryPos( nSelIndex
);
500 if ( nPos
!= LISTBOX_ENTRY_NOTFOUND
)
502 if (!m_sNone
.isEmpty())
504 nStyle
= GetEntryStyle( nPos
);
511 void lclDrawPolygon( OutputDevice
& rDev
, const basegfx::B2DPolygon
& rPolygon
, long nWidth
, sal_uInt16 nDashing
)
513 AntialiasingFlags nOldAA
= rDev
.GetAntialiasing();
514 rDev
.SetAntialiasing( nOldAA
& ~AntialiasingFlags::EnableB2dDraw
);
516 long nPix
= rDev
.PixelToLogic(Size(1, 1)).Width();
517 basegfx::B2DPolyPolygon aPolygons
= svtools::ApplyLineDashing(rPolygon
, nDashing
, nPix
);
519 // Handle problems of width 1px in Pixel mode: 0.5px gives a 1px line
520 if (rDev
.GetMapMode().GetMapUnit() == MAP_PIXEL
&& nWidth
== nPix
)
523 for ( sal_uInt32 i
= 0; i
< aPolygons
.count( ); i
++ )
525 basegfx::B2DPolygon aDash
= aPolygons
.getB2DPolygon( i
);
526 basegfx::B2DPoint aStart
= aDash
.getB2DPoint( 0 );
527 basegfx::B2DPoint aEnd
= aDash
.getB2DPoint( aDash
.count() - 1 );
529 basegfx::B2DVector
aVector( aEnd
- aStart
);
530 aVector
.normalize( );
531 const basegfx::B2DVector
aPerpendicular(basegfx::getPerpendicular(aVector
));
533 const basegfx::B2DVector
aWidthOffset( double( nWidth
) / 2 * aPerpendicular
);
534 basegfx::B2DPolygon aDashPolygon
;
535 aDashPolygon
.append( aStart
+ aWidthOffset
);
536 aDashPolygon
.append( aEnd
+ aWidthOffset
);
537 aDashPolygon
.append( aEnd
- aWidthOffset
);
538 aDashPolygon
.append( aStart
- aWidthOffset
);
539 aDashPolygon
.setClosed( true );
541 rDev
.DrawPolygon( aDashPolygon
);
544 rDev
.SetAntialiasing( nOldAA
);
550 * Dashing array must start with a line width and end with a blank width.
552 std::vector
<double> GetDashing( sal_uInt16 nDashing
)
554 std::vector
<double> aPattern
;
557 case table::BorderLineStyle::DOTTED
:
558 aPattern
.push_back( 1.0 ); // line
559 aPattern
.push_back( 2.0 ); // blank
561 case table::BorderLineStyle::DASHED
:
562 aPattern
.push_back( 16.0 ); // line
563 aPattern
.push_back( 5.0 ); // blank
565 case table::BorderLineStyle::FINE_DASHED
:
566 aPattern
.push_back( 6.0 ); // line
567 aPattern
.push_back( 2.0 ); // blank
569 case table::BorderLineStyle::DASH_DOT
:
570 aPattern
.push_back( 16.0 ); // line
571 aPattern
.push_back( 5.0 ); // blank
572 aPattern
.push_back( 5.0 ); // line
573 aPattern
.push_back( 5.0 ); // blank
575 case table::BorderLineStyle::DASH_DOT_DOT
:
576 aPattern
.push_back( 16.0 ); // line
577 aPattern
.push_back( 5.0 ); // blank
578 aPattern
.push_back( 5.0 ); // line
579 aPattern
.push_back( 5.0 ); // blank
580 aPattern
.push_back( 5.0 ); // line
581 aPattern
.push_back( 5.0 ); // blank
592 class ApplyScale
: std::unary_function
<double, void>
596 ApplyScale( double fScale
) : mfScale(fScale
) {}
597 void operator() ( double& rVal
)
605 std::vector
<double> GetLineDashing( sal_uInt16 nDashing
, double fScale
)
607 std::vector
<double> aPattern
= GetDashing(nDashing
);
608 std::for_each(aPattern
.begin(), aPattern
.end(), ApplyScale(fScale
));
612 basegfx::B2DPolyPolygon
ApplyLineDashing( const basegfx::B2DPolygon
& rPolygon
, sal_uInt16 nDashing
, double fScale
)
614 std::vector
<double> aPattern
= GetDashing(nDashing
);
615 std::for_each(aPattern
.begin(), aPattern
.end(), ApplyScale(fScale
));
617 basegfx::B2DPolyPolygon aPolygons
;
619 if (aPattern
.empty())
620 aPolygons
.append(rPolygon
);
622 basegfx::tools::applyLineDashing(rPolygon
, aPattern
, &aPolygons
);
627 void DrawLine( OutputDevice
& rDev
, const Point
& rP1
, const Point
& rP2
,
628 sal_uInt32 nWidth
, sal_uInt16 nDashing
)
630 DrawLine( rDev
, basegfx::B2DPoint( rP1
.X(), rP1
.Y() ),
631 basegfx::B2DPoint( rP2
.X(), rP2
.Y( ) ), nWidth
, nDashing
);
634 void DrawLine( OutputDevice
& rDev
, const basegfx::B2DPoint
& rP1
, const basegfx::B2DPoint
& rP2
,
635 sal_uInt32 nWidth
, sal_uInt16 nDashing
)
637 basegfx::B2DPolygon aPolygon
;
638 aPolygon
.append( rP1
);
639 aPolygon
.append( rP2
);
640 lclDrawPolygon( rDev
, aPolygon
, nWidth
, nDashing
);
645 void LineListBox::ImpGetLine( long nLine1
, long nLine2
, long nDistance
,
646 Color aColor1
, Color aColor2
, Color aColorDist
,
647 sal_uInt16 nStyle
, Bitmap
& rBmp
)
649 //TODO, rather than including the " " text to force
650 //the line height, better would be do drop
651 //this calculation and draw a bitmap of height
652 //equal to normal text line and center the
654 long nMinWidth
= GetTextWidth(OUString("----------"));
655 Size aSize
= CalcSubEditSize();
656 aSize
.Width() = std::max(nMinWidth
, aSize
.Width());
657 aSize
.Width() -= aTxtSize
.Width();
659 aSize
.Height() = aTxtSize
.Height();
661 // SourceUnit nach Twips
662 if ( eSourceUnit
== FUNIT_POINT
)
670 aSize
= aVirDev
->PixelToLogic( aSize
);
671 long nPix
= aVirDev
->PixelToLogic( Size( 0, 1 ) ).Height();
672 sal_uInt32 n1
= nLine1
;
673 sal_uInt32 n2
= nLine2
;
674 long nDist
= nDistance
;
684 long nVirHeight
= n1
+nDist
+n2
;
685 if ( nVirHeight
> aSize
.Height() )
686 aSize
.Height() = nVirHeight
;
687 // negative width should not be drawn
688 if ( aSize
.Width() > 0 )
690 Size aVirSize
= aVirDev
->LogicToPixel( aSize
);
691 if ( aVirDev
->GetOutputSizePixel() != aVirSize
)
692 aVirDev
->SetOutputSizePixel( aVirSize
);
693 aVirDev
->SetFillColor( aColorDist
);
694 aVirDev
->DrawRect( Rectangle( Point(), aSize
) );
696 aVirDev
->SetFillColor( aColor1
);
698 double y1
= double( n1
) / 2;
699 svtools::DrawLine( *aVirDev
.get(), basegfx::B2DPoint( 0, y1
), basegfx::B2DPoint( aSize
.Width( ), y1
), n1
, nStyle
);
703 double y2
= n1
+ nDist
+ double( n2
) / 2;
704 aVirDev
->SetFillColor( aColor2
);
705 svtools::DrawLine( *aVirDev
.get(), basegfx::B2DPoint( 0, y2
), basegfx::B2DPoint( aSize
.Width(), y2
), n2
, table::BorderLineStyle::SOLID
);
707 rBmp
= aVirDev
->GetBitmap( Point(), Size( aSize
.Width(), n1
+nDist
+n2
) );
711 void LineListBox::ImplInit()
713 aTxtSize
.Width() = GetTextWidth( OUString( " " ) );
714 aTxtSize
.Height() = GetTextHeight();
715 pLineList
= new ImpLineList();
717 eSourceUnit
= FUNIT_POINT
;
719 aVirDev
->SetLineColor();
720 aVirDev
->SetMapMode( MapMode( MAP_TWIP
) );
722 UpdatePaintLineColor();
725 LineListBox::LineListBox( vcl::Window
* pParent
, WinBits nWinStyle
) :
726 ListBox( pParent
, nWinStyle
),
729 aVirDev( VclPtr
<VirtualDevice
>::Create() ),
731 maPaintCol( COL_BLACK
)
736 VCL_BUILDER_DECL_FACTORY(LineListBox
)
738 bool bDropdown
= VclBuilder::extractDropdown(rMap
);
739 WinBits nWinBits
= WB_LEFT
|WB_VCENTER
|WB_3DLOOK
|WB_TABSTOP
;
741 nWinBits
|= WB_DROPDOWN
;
742 VclPtrInstance
<LineListBox
> pListBox(pParent
, nWinBits
);
744 pListBox
->EnableAutoSize(true);
748 LineListBox::~LineListBox()
753 void LineListBox::dispose()
755 for ( size_t i
= 0, n
= pLineList
->size(); i
< n
; ++i
) {
756 if ( (*pLineList
)[ i
] ) {
757 delete (*pLineList
)[ i
];
765 sal_Int32
LineListBox::GetStylePos( sal_Int32 nListPos
, long nWidth
)
767 sal_Int32 nPos
= LISTBOX_ENTRY_NOTFOUND
;
768 if (!m_sNone
.isEmpty())
773 size_t nCount
= pLineList
->size();
774 while ( nPos
== LISTBOX_ENTRY_NOTFOUND
&& i
< nCount
)
776 ImpLineListData
* pData
= (*pLineList
)[ i
];
777 if ( pData
&& pData
->GetMinWidth() <= nWidth
)
780 nPos
= static_cast<sal_Int32
>(i
);
789 void LineListBox::SelectEntry( sal_uInt16 nStyle
, bool bSelect
)
791 sal_Int32 nPos
= GetEntryPos( nStyle
);
792 if ( nPos
!= LISTBOX_ENTRY_NOTFOUND
)
793 ListBox::SelectEntryPos( nPos
, bSelect
);
796 void LineListBox::InsertEntry(
797 const BorderWidthImpl
& rWidthImpl
, sal_uInt16 nStyle
, long nMinWidth
,
798 ColorFunc pColor1Fn
, ColorFunc pColor2Fn
, ColorDistFunc pColorDistFn
)
800 ImpLineListData
* pData
= new ImpLineListData(
801 rWidthImpl
, nStyle
, nMinWidth
, pColor1Fn
, pColor2Fn
, pColorDistFn
);
802 pLineList
->push_back( pData
);
805 sal_Int32
LineListBox::GetEntryPos( sal_uInt16 nStyle
) const
807 for ( size_t i
= 0, n
= pLineList
->size(); i
< n
; ++i
) {
808 ImpLineListData
* pData
= (*pLineList
)[ i
];
811 if ( GetEntryStyle( i
) == nStyle
)
814 if (!m_sNone
.isEmpty())
816 return (sal_Int32
)nPos
;
820 return LISTBOX_ENTRY_NOTFOUND
;
823 sal_uInt16
LineListBox::GetEntryStyle( sal_Int32 nPos
) const
825 ImpLineListData
* pData
= (0 <= nPos
&& static_cast<size_t>(nPos
) < pLineList
->size()) ? (*pLineList
)[ nPos
] : NULL
;
826 return ( pData
) ? pData
->GetStyle() : table::BorderLineStyle::NONE
;
829 bool LineListBox::UpdatePaintLineColor()
831 const StyleSettings
& rSettings
= GetSettings().GetStyleSettings();
832 Color
aNewCol( rSettings
.GetWindowColor().IsDark()? rSettings
.GetLabelTextColor() : aColor
);
834 bool bRet
= aNewCol
!= maPaintCol
;
837 maPaintCol
= aNewCol
;
842 void LineListBox::UpdateEntries( long nOldWidth
)
844 SetUpdateMode( false );
846 UpdatePaintLineColor( );
848 sal_Int32 nSelEntry
= GetSelectEntryPos();
849 sal_Int32 nTypePos
= GetStylePos( nSelEntry
, nOldWidth
);
851 // Remove the old entries
852 while ( GetEntryCount( ) > 0 )
853 ListBox::RemoveEntry( 0 );
855 // Add the new entries based on the defined width
856 if (!m_sNone
.isEmpty())
857 ListBox::InsertEntry( m_sNone
, LISTBOX_APPEND
);
860 sal_uInt16 nCount
= pLineList
->size( );
863 ImpLineListData
* pData
= (*pLineList
)[ n
];
864 if ( pData
&& pData
->GetMinWidth() <= m_nWidth
)
867 ImpGetLine( pData
->GetLine1ForWidth( m_nWidth
),
868 pData
->GetLine2ForWidth( m_nWidth
),
869 pData
->GetDistForWidth( m_nWidth
),
870 GetColorLine1( GetEntryCount( ) ),
871 GetColorLine2( GetEntryCount( ) ),
872 GetColorDist( GetEntryCount( ) ),
873 pData
->GetStyle(), aBmp
);
874 ListBox::InsertEntry(OUString(" "), Image(aBmp
), LISTBOX_APPEND
);
876 SelectEntryPos( GetEntryCount() - 1 );
878 else if ( n
== nTypePos
)
883 SetUpdateMode( true );
887 Color
LineListBox::GetColorLine1( sal_Int32 nPos
)
889 Color rResult
= GetPaintColor( );
891 sal_uInt16 nStyle
= GetStylePos( nPos
, m_nWidth
);
892 ImpLineListData
* pData
= (*pLineList
)[ nStyle
];
894 rResult
= pData
->GetColorLine1( GetColor( ) );
899 Color
LineListBox::GetColorLine2( sal_Int32 nPos
)
901 Color rResult
= GetPaintColor( );
903 sal_uInt16 nStyle
= GetStylePos( nPos
, m_nWidth
);
904 ImpLineListData
* pData
= (*pLineList
)[ nStyle
];
906 rResult
= pData
->GetColorLine2( GetColor( ) );
911 Color
LineListBox::GetColorDist( sal_Int32 nPos
)
913 Color rResult
= GetSettings().GetStyleSettings().GetFieldColor();
915 sal_uInt16 nStyle
= GetStylePos( nPos
, m_nWidth
);
916 ImpLineListData
* pData
= (*pLineList
)[ nStyle
];
918 rResult
= pData
->GetColorDist( GetColor( ), rResult
);
923 void LineListBox::DataChanged( const DataChangedEvent
& rDCEvt
)
925 ListBox::DataChanged( rDCEvt
);
927 if( ( rDCEvt
.GetType() == DataChangedEventType::SETTINGS
) && ( rDCEvt
.GetFlags() & AllSettingsFlags::STYLE
) )
928 UpdateEntries( m_nWidth
);
931 FontNameBox::FontNameBox( vcl::Window
* pParent
, WinBits nWinStyle
) :
932 ComboBox( pParent
, nWinStyle
)
936 InitFontMRUEntriesFile();
939 VCL_BUILDER_DECL_FACTORY(FontNameBox
)
941 bool bDropdown
= VclBuilder::extractDropdown(rMap
);
942 WinBits nWinBits
= WB_LEFT
|WB_VCENTER
|WB_3DLOOK
|WB_TABSTOP
;
944 nWinBits
|= WB_DROPDOWN
;
945 VclPtrInstance
<FontNameBox
> pListBox(pParent
, nWinBits
);
947 pListBox
->EnableAutoSize(true);
951 FontNameBox::~FontNameBox()
956 void FontNameBox::dispose()
960 SaveMRUEntries (maFontMRUEntriesFile
);
961 ImplDestroyFontList();
966 void FontNameBox::SaveMRUEntries( const OUString
& aFontMRUEntriesFile
, sal_Unicode cSep
) const
968 OString
aEntries(OUStringToOString(GetMRUEntries(cSep
),
969 RTL_TEXTENCODING_UTF8
));
971 if (aEntries
.isEmpty() || aFontMRUEntriesFile
.isEmpty())
974 SvFileStream aStream
;
975 aStream
.Open( aFontMRUEntriesFile
, StreamMode::WRITE
| StreamMode::TRUNC
);
976 if( ! (aStream
.IsOpen() && aStream
.IsWritable()) )
978 SAL_WARN("svtools.control", "FontNameBox::SaveMRUEntries: opening mru entries file " << aFontMRUEntriesFile
<< " failed\n");
982 aStream
.SetLineDelimiter( LINEEND_LF
);
983 aStream
.WriteLine( aEntries
);
984 aStream
.WriteLine( OString() );
987 void FontNameBox::LoadMRUEntries( const OUString
& aFontMRUEntriesFile
, sal_Unicode cSep
)
989 if( aFontMRUEntriesFile
.isEmpty() )
992 SvFileStream
aStream( aFontMRUEntriesFile
, StreamMode::READ
);
993 if( ! aStream
.IsOpen() )
995 SAL_WARN("svtools.control", "FontNameBox::LoadMRUEntries: opening mru entries file " << aFontMRUEntriesFile
<< " failed\n");
1000 aStream
.ReadLine( aLine
);
1001 OUString aEntries
= OStringToOUString(aLine
,
1002 RTL_TEXTENCODING_UTF8
);
1003 SetMRUEntries( aEntries
, cSep
);
1006 void FontNameBox::InitFontMRUEntriesFile()
1008 OUString
sUserConfigDir("${$BRAND_BASE_DIR/" LIBO_ETC_FOLDER
"/" SAL_CONFIGFILE( "bootstrap") "::UserInstallation}");
1009 rtl::Bootstrap::expandMacros(sUserConfigDir
);
1011 maFontMRUEntriesFile
= sUserConfigDir
;
1012 if( !maFontMRUEntriesFile
.isEmpty() )
1014 maFontMRUEntriesFile
+= FONTNAMEBOXMRUENTRIESFILE
;
1018 void FontNameBox::ImplDestroyFontList()
1024 void FontNameBox::Fill( const FontList
* pList
)
1026 // store old text and clear box
1027 OUString aOldText
= GetText();
1028 OUString rEntries
= GetMRUEntries();
1029 bool bLoadFromFile
= rEntries
.isEmpty();
1032 ImplDestroyFontList();
1033 mpFontList
= new ImplFontList
;
1036 sal_uInt16 nFontCount
= pList
->GetFontNameCount();
1037 for ( sal_uInt16 i
= 0; i
< nFontCount
; i
++ )
1039 const vcl::FontInfo
& rFontInfo
= pList
->GetFontName( i
);
1040 sal_uLong nIndex
= InsertEntry( rFontInfo
.GetName() );
1041 if ( nIndex
!= LISTBOX_ERROR
)
1043 if ( nIndex
< mpFontList
->size() ) {
1044 ImplFontList::iterator it
= mpFontList
->begin();
1045 ::std::advance( it
, nIndex
);
1046 mpFontList
->insert( it
, rFontInfo
);
1048 mpFontList
->push_back( rFontInfo
);
1053 if ( bLoadFromFile
)
1054 LoadMRUEntries (maFontMRUEntriesFile
);
1056 SetMRUEntries( rEntries
);
1058 ImplCalcUserItemSize();
1061 if (!aOldText
.isEmpty())
1062 SetText( aOldText
);
1065 void FontNameBox::EnableWYSIWYG( bool bEnable
)
1067 if ( bEnable
!= mbWYSIWYG
)
1069 mbWYSIWYG
= bEnable
;
1070 EnableUserDraw( mbWYSIWYG
);
1071 ImplCalcUserItemSize();
1075 void FontNameBox::ImplCalcUserItemSize()
1078 if ( mbWYSIWYG
&& mpFontList
)
1080 aUserItemSz
= Size(MAXPREVIEWWIDTH
, GetTextHeight() );
1081 aUserItemSz
.Height() *= 16;
1082 aUserItemSz
.Height() /= 10;
1084 SetUserItemSize( aUserItemSz
);
1089 long shrinkFontToFit(OUString
&rSampleText
, long nH
, vcl::Font
&rFont
, OutputDevice
&rDevice
, Rectangle
&rTextRect
)
1093 Size
aSize( rFont
.GetSize() );
1095 //Make sure it fits in the available height
1096 while (aSize
.Height() > 0)
1098 if (!rDevice
.GetTextBoundRect(rTextRect
, rSampleText
, 0, 0))
1100 if (rTextRect
.GetHeight() <= nH
)
1102 nWidth
= rTextRect
.GetWidth();
1106 aSize
.Height() -= EXTRAFONTSIZE
;
1107 rFont
.SetSize(aSize
);
1108 rDevice
.SetFont(rFont
);
1115 void FontNameBox::UserDraw( const UserDrawEvent
& rUDEvt
)
1117 assert( mpFontList
);
1119 vcl::FontInfo
& rInfo
= (*mpFontList
)[ rUDEvt
.GetItemId() ];
1120 Point aTopLeft
= rUDEvt
.GetRect().TopLeft();
1121 long nX
= aTopLeft
.X();
1122 long nH
= rUDEvt
.GetRect().GetHeight();
1126 nX
+= IMGOUTERTEXTSPACE
;
1128 const bool bSymbolFont
= isSymbolFont(rInfo
);
1129 vcl::RenderContext
* pRenderContext
= rUDEvt
.GetRenderContext();
1131 Color aTextColor
= pRenderContext
->GetTextColor();
1132 vcl::Font
aOldFont(pRenderContext
->GetFont());
1133 Size
aSize( aOldFont
.GetSize() );
1134 aSize
.Height() += EXTRAFONTSIZE
;
1135 vcl::Font
aFont( rInfo
);
1136 aFont
.SetSize( aSize
);
1137 pRenderContext
->SetFont(aFont
);
1138 pRenderContext
->SetTextColor(aTextColor
);
1140 bool bUsingCorrectFont
= true;
1141 Rectangle aTextRect
;
1143 // Preview the font name
1144 OUString sFontName
= rInfo
.GetName();
1146 //If it shouldn't or can't draw its own name because it doesn't have the glyphs
1147 if (!canRenderNameOfSelectedFont(*pRenderContext
))
1148 bUsingCorrectFont
= false;
1151 //Make sure it fits in the available height, shrinking the font if necessary
1152 bUsingCorrectFont
= shrinkFontToFit(sFontName
, nH
, aFont
, *pRenderContext
, aTextRect
) != 0;
1155 if (!bUsingCorrectFont
)
1157 pRenderContext
->SetFont(aOldFont
);
1158 pRenderContext
->GetTextBoundRect(aTextRect
, sFontName
, 0, 0);
1161 long nTextHeight
= aTextRect
.GetHeight();
1162 long nDesiredGap
= (nH
-nTextHeight
)/2;
1163 long nVertAdjust
= nDesiredGap
- aTextRect
.Top();
1164 Point
aPos( nX
, aTopLeft
.Y() + nVertAdjust
);
1165 pRenderContext
->DrawText(aPos
, sFontName
);
1166 long nTextX
= aPos
.X() + aTextRect
.GetWidth() + GAPTOEXTRAPREVIEW
;
1168 if (!bUsingCorrectFont
)
1169 pRenderContext
->SetFont(aFont
);
1171 OUString sSampleText
;
1175 const bool bNameBeginsWithLatinText
= rInfo
.GetName()[0] <= 'z';
1177 if (bNameBeginsWithLatinText
|| !bUsingCorrectFont
)
1178 sSampleText
= makeShortRepresentativeTextForSelectedFont(*pRenderContext
);
1181 //If we're not a symbol font, but could neither render our own name and
1182 //we can't determine what script it would like to render, then try a
1183 //few well known scripts
1184 if (sSampleText
.isEmpty() && !bUsingCorrectFont
)
1186 static const UScriptCode aScripts
[] =
1215 USCRIPT_SIMPLIFIED_HAN
,
1216 USCRIPT_TRADITIONAL_HAN
,
1221 for (size_t i
= 0; i
< SAL_N_ELEMENTS(aScripts
); ++i
)
1223 OUString sText
= makeShortRepresentativeTextForScript(aScripts
[i
]);
1224 if (!sText
.isEmpty())
1226 bool bHasSampleTextGlyphs
= (-1 == pRenderContext
->HasGlyphs(aFont
, sText
));
1227 if (bHasSampleTextGlyphs
)
1229 sSampleText
= sText
;
1235 static const UScriptCode aMinimalScripts
[] =
1237 USCRIPT_HEBREW
, //e.g. biblical hebrew
1241 for (size_t i
= 0; i
< SAL_N_ELEMENTS(aMinimalScripts
); ++i
)
1243 OUString sText
= makeShortMinimalTextForScript(aMinimalScripts
[i
]);
1244 if (!sText
.isEmpty())
1246 bool bHasSampleTextGlyphs
= (-1 == pRenderContext
->HasGlyphs(aFont
, sText
));
1247 if (bHasSampleTextGlyphs
)
1249 sSampleText
= sText
;
1256 //If we're a symbol font, or for some reason the font still couldn't
1257 //render something representative of what it would like to render then
1258 //make up some semi-random text that it *can* display
1259 if (bSymbolFont
|| (!bUsingCorrectFont
&& sSampleText
.isEmpty()))
1260 sSampleText
= makeShortRepresentativeSymbolTextForSelectedFont(*pRenderContext
);
1262 if (!sSampleText
.isEmpty())
1264 const Size
&rItemSize
= rUDEvt
.GetWindow()->GetOutputSize();
1266 //leave a little border at the edge
1267 long nSpace
= rItemSize
.Width() - nTextX
- IMGOUTERTEXTSPACE
;
1270 //Make sure it fits in the available height, and get how wide that would be
1271 long nWidth
= shrinkFontToFit(sSampleText
, nH
, aFont
, *pRenderContext
, aTextRect
);
1272 //Chop letters off until it fits in the available width
1273 while (nWidth
> nSpace
|| nWidth
> MAXPREVIEWWIDTH
)
1275 sSampleText
= sSampleText
.copy(0, sSampleText
.getLength()-1);
1276 nWidth
= pRenderContext
->GetTextBoundRect(aTextRect
, sSampleText
, 0, 0) ?
1277 aTextRect
.GetWidth() : 0;
1280 //center the text on the line
1281 if (!sSampleText
.isEmpty() && nWidth
)
1283 nTextHeight
= aTextRect
.GetHeight();
1284 nDesiredGap
= (nH
-nTextHeight
)/2;
1285 nVertAdjust
= nDesiredGap
- aTextRect
.Top();
1286 aPos
= Point(nTextX
+ nSpace
- nWidth
, aTopLeft
.Y() + nVertAdjust
);
1287 pRenderContext
->DrawText(aPos
, sSampleText
);
1292 pRenderContext
->SetFont(aOldFont
);
1293 DrawEntry( rUDEvt
, false, false); // draw separator
1297 DrawEntry( rUDEvt
, true, true );
1301 FontStyleBox::FontStyleBox(vcl::Window
* pParent
, WinBits nBits
)
1302 : ComboBox(pParent
, nBits
)
1304 //Use the standard texts to get an optimal size and stick to that size.
1305 //That should stop the character dialog dancing around.
1306 InsertEntry(SVT_RESSTR(STR_SVT_STYLE_LIGHT
));
1307 InsertEntry(SVT_RESSTR(STR_SVT_STYLE_LIGHT_ITALIC
));
1308 InsertEntry(SVT_RESSTR(STR_SVT_STYLE_NORMAL
));
1309 InsertEntry(SVT_RESSTR(STR_SVT_STYLE_NORMAL_ITALIC
));
1310 InsertEntry(SVT_RESSTR(STR_SVT_STYLE_BOLD
));
1311 InsertEntry(SVT_RESSTR(STR_SVT_STYLE_BOLD_ITALIC
));
1312 InsertEntry(SVT_RESSTR(STR_SVT_STYLE_BLACK
));
1313 InsertEntry(SVT_RESSTR(STR_SVT_STYLE_BLACK_ITALIC
));
1314 aOptimalSize
= GetOptimalSize();
1318 Size
FontStyleBox::GetOptimalSize() const
1320 if (aOptimalSize
.Width() || aOptimalSize
.Height())
1321 return aOptimalSize
;
1322 return ComboBox::GetOptimalSize();
1325 VCL_BUILDER_DECL_FACTORY(FontStyleBox
)
1327 bool bDropdown
= VclBuilder::extractDropdown(rMap
);
1328 WinBits nWinBits
= WB_LEFT
|WB_VCENTER
|WB_3DLOOK
|WB_TABSTOP
;
1330 nWinBits
|= WB_DROPDOWN
;
1331 VclPtrInstance
<FontStyleBox
> pListBox(pParent
, nWinBits
);
1333 pListBox
->EnableAutoSize(true);
1337 void FontStyleBox::Select()
1339 // keep text over fill operation
1340 aLastStyle
= GetText();
1344 void FontStyleBox::LoseFocus()
1346 // keep text over fill operation
1347 aLastStyle
= GetText();
1348 ComboBox::LoseFocus();
1351 void FontStyleBox::Modify()
1353 CharClass
aChrCls( ::comphelper::getProcessComponentContext(),
1354 GetSettings().GetLanguageTag() );
1355 OUString aStr
= GetText();
1356 sal_Int32 nEntryCount
= GetEntryCount();
1358 if ( GetEntryPos( aStr
) == COMBOBOX_ENTRY_NOTFOUND
)
1360 aStr
= aChrCls
.uppercase(aStr
);
1361 for ( sal_Int32 i
= 0; i
< nEntryCount
; i
++ )
1363 OUString aEntryText
= aChrCls
.uppercase(GetEntry(i
));
1365 if ( aStr
== aEntryText
)
1367 SetText( GetEntry( i
) );
1376 void FontStyleBox::Fill( const OUString
& rName
, const FontList
* pList
)
1378 // note: this method must call ComboBox::SetText(),
1379 // else aLastStyle will overwritten
1380 // store prior selection position and clear box
1381 OUString aOldText
= GetText();
1382 sal_Int32 nPos
= GetEntryPos( aOldText
);
1385 // does a font with this name already exist?
1386 sal_Handle hFontInfo
= pList
->GetFirstFontInfo( rName
);
1389 OUString aStyleText
;
1390 FontWeight eLastWeight
= WEIGHT_DONTKNOW
;
1391 FontItalic eLastItalic
= ITALIC_NONE
;
1392 FontWidth eLastWidth
= WIDTH_DONTKNOW
;
1393 bool bNormal
= false;
1394 bool bItalic
= false;
1396 bool bBoldItalic
= false;
1397 bool bInsert
= false;
1398 vcl::FontInfo aInfo
;
1401 aInfo
= FontList::GetFontInfo( hFontInfo
);
1403 FontWeight eWeight
= aInfo
.GetWeight();
1404 FontItalic eItalic
= aInfo
.GetItalic();
1405 FontWidth eWidth
= aInfo
.GetWidthType();
1406 // Only if the attributes are different, we insert the
1407 // Font to avoid double Entries in different languages
1408 if ( (eWeight
!= eLastWeight
) || (eItalic
!= eLastItalic
) ||
1409 (eWidth
!= eLastWidth
) )
1412 InsertEntry( aStyleText
);
1414 if ( eWeight
<= WEIGHT_NORMAL
)
1416 if ( eItalic
!= ITALIC_NONE
)
1423 if ( eItalic
!= ITALIC_NONE
)
1429 // For wrong StyleNames we replace this with the correct once
1430 aStyleText
= pList
->GetStyleName( aInfo
);
1431 bInsert
= GetEntryPos( aStyleText
) == LISTBOX_ENTRY_NOTFOUND
;
1434 aStyleText
= pList
->GetStyleName( eWeight
, eItalic
);
1435 bInsert
= GetEntryPos( aStyleText
) == LISTBOX_ENTRY_NOTFOUND
;
1438 eLastWeight
= eWeight
;
1439 eLastItalic
= eItalic
;
1440 eLastWidth
= eWidth
;
1446 // If we have two names for the same attributes
1447 // we prefer the translated standard names
1448 const OUString
& rAttrStyleText
= pList
->GetStyleName( eWeight
, eItalic
);
1449 if (rAttrStyleText
!= aStyleText
)
1451 OUString aTempStyleText
= pList
->GetStyleName( aInfo
);
1452 if (rAttrStyleText
== aTempStyleText
)
1453 aStyleText
= rAttrStyleText
;
1454 bInsert
= GetEntryPos( aStyleText
) == LISTBOX_ENTRY_NOTFOUND
;
1459 if ( !bItalic
&& (aStyleText
== pList
->GetItalicStr()) )
1461 else if ( !bBold
&& (aStyleText
== pList
->GetBoldStr()) )
1463 else if ( !bBoldItalic
&& (aStyleText
== pList
->GetBoldItalicStr()) )
1466 hFontInfo
= FontList::GetNextFontInfo( hFontInfo
);
1470 InsertEntry( aStyleText
);
1472 // certain style as copy
1476 InsertEntry( pList
->GetItalicStr() );
1478 InsertEntry( pList
->GetBoldStr() );
1482 if ( bNormal
|| bItalic
|| bBold
)
1483 InsertEntry( pList
->GetBoldItalicStr() );
1485 if (!aOldText
.isEmpty())
1487 if ( GetEntryPos( aLastStyle
) != LISTBOX_ENTRY_NOTFOUND
)
1488 ComboBox::SetText( aLastStyle
);
1491 if ( nPos
>= GetEntryCount() )
1492 ComboBox::SetText( GetEntry( 0 ) );
1494 ComboBox::SetText( GetEntry( nPos
) );
1500 // insert standard styles if no font
1501 InsertEntry( pList
->GetNormalStr() );
1502 InsertEntry( pList
->GetItalicStr() );
1503 InsertEntry( pList
->GetBoldStr() );
1504 InsertEntry( pList
->GetBoldItalicStr() );
1505 if (!aOldText
.isEmpty())
1507 if ( nPos
> GetEntryCount() )
1508 ComboBox::SetText( GetEntry( 0 ) );
1510 ComboBox::SetText( GetEntry( nPos
) );
1515 FontSizeBox::FontSizeBox( vcl::Window
* pParent
, WinBits nWinSize
) :
1516 MetricBox( pParent
, nWinSize
)
1521 VCL_BUILDER_DECL_FACTORY(FontSizeBox
)
1523 bool bDropdown
= VclBuilder::extractDropdown(rMap
);
1524 WinBits nWinBits
= WB_LEFT
|WB_VCENTER
|WB_3DLOOK
|WB_TABSTOP
;
1526 nWinBits
|= WB_DROPDOWN
;
1527 VclPtrInstance
<FontSizeBox
> pListBox(pParent
, nWinBits
);
1529 pListBox
->EnableAutoSize(true);
1533 void FontSizeBox::ImplInit()
1535 EnableAutocomplete( false );
1537 bRelativeMode
= false;
1538 bPtRelative
= false;
1543 SetShowTrailingZeros( false );
1544 SetDecimalDigits( 1 );
1547 SetProminentEntryType( ProminentEntry::MIDDLE
);
1550 void FontSizeBox::Reformat()
1552 FontSizeNames
aFontSizeNames( GetSettings().GetUILanguageTag().getLanguageType() );
1553 if ( !bRelativeMode
|| !aFontSizeNames
.IsEmpty() )
1555 long nNewValue
= aFontSizeNames
.Name2Size( GetText() );
1558 mnLastValue
= nNewValue
;
1563 MetricBox::Reformat();
1566 void FontSizeBox::Modify()
1568 MetricBox::Modify();
1570 if ( bRelativeMode
)
1572 OUString aStr
= comphelper::string::stripStart(GetText(), ' ');
1574 bool bNewMode
= bRelative
;
1575 bool bOldPtRelMode
= bPtRelative
;
1579 bPtRelative
= false;
1580 const sal_Unicode
* pStr
= aStr
.getStr();
1583 if ( ((*pStr
< '0') || (*pStr
> '9')) && (*pStr
!= '%') && !unicode::isSpace(*pStr
) )
1585 if ( ('-' == *pStr
|| '+' == *pStr
) && !bPtRelative
)
1587 else if ( bPtRelative
&& 'p' == *pStr
&& 't' == *++pStr
)
1598 else if (!aStr
.isEmpty())
1600 if ( -1 != aStr
.indexOf('%') )
1603 bPtRelative
= false;
1606 if ( '-' == aStr
[0] || '+' == aStr
[0] )
1613 if ( bNewMode
!= bRelative
|| bPtRelative
!= bOldPtRelMode
)
1614 SetRelative( bNewMode
);
1618 void FontSizeBox::Fill( const vcl::FontInfo
* pInfo
, const FontList
* pList
)
1620 // remember for relative mode
1623 // no font sizes need to be set for relative mode
1628 const sal_IntPtr
* pTempAry
;
1629 const sal_IntPtr
* pAry
= 0;
1634 pAry
= pList
->GetSizeAry( *pInfo
);
1638 pAry
= FontList::GetStdSizeAry();
1641 // first insert font size names (for simplified/traditional chinese)
1642 FontSizeNames
aFontSizeNames( GetSettings().GetUILanguageTag().getLanguageType() );
1643 if ( pAry
== FontList::GetStdSizeAry() )
1645 // for standard sizes we don't need to bother
1646 if ( bStdSize
&& GetEntryCount() && aFontSizeNames
.IsEmpty() )
1653 Selection aSelection
= GetSelection();
1654 OUString aStr
= GetText();
1659 if ( !aFontSizeNames
.IsEmpty() )
1661 if ( pAry
== FontList::GetStdSizeAry() )
1663 // for scalable fonts all font size names
1664 sal_uLong nCount
= aFontSizeNames
.Count();
1665 for( sal_uLong i
= 0; i
< nCount
; i
++ )
1667 OUString aSizeName
= aFontSizeNames
.GetIndexName( i
);
1668 sal_IntPtr nSize
= aFontSizeNames
.GetIndexSize( i
);
1669 ComboBox::InsertEntry( aSizeName
, nPos
);
1670 ComboBox::SetEntryData( nPos
, reinterpret_cast<void*>(-nSize
) ); // mark as special
1676 // for fixed size fonts only selectable font size names
1680 OUString aSizeName
= aFontSizeNames
.Size2Name( *pTempAry
);
1681 if ( !aSizeName
.isEmpty() )
1683 ComboBox::InsertEntry( aSizeName
, nPos
);
1684 ComboBox::SetEntryData( nPos
, reinterpret_cast<void*>(-(*pTempAry
)) ); // mark as special
1692 // then insert numerical font size values
1696 InsertValue( *pTempAry
, FUNIT_NONE
, nPos
);
1697 ComboBox::SetEntryData( nPos
, reinterpret_cast<void*>(*pTempAry
) );
1703 SetSelection( aSelection
);
1706 void FontSizeBox::EnableRelativeMode( sal_uInt16 nMin
, sal_uInt16 nMax
, sal_uInt16 nStep
)
1708 bRelativeMode
= true;
1712 SetUnit( FUNIT_POINT
);
1715 void FontSizeBox::EnablePtRelativeMode( short nMin
, short nMax
, short nStep
)
1717 bRelativeMode
= true;
1721 SetUnit( FUNIT_POINT
);
1724 void FontSizeBox::SetRelative( bool bNewRelative
)
1726 if ( bRelativeMode
)
1728 Selection aSelection
= GetSelection();
1729 OUString aStr
= comphelper::string::stripStart(GetText(), ' ');
1738 Clear(); //clear early because SetDecimalDigits is a slow recalc
1740 SetDecimalDigits( 1 );
1741 SetMin( nPtRelMin
);
1742 SetMax( nPtRelMax
);
1743 SetUnit( FUNIT_POINT
);
1745 short i
= nPtRelMin
, n
= 0;
1746 // JP 30.06.98: more than 100 values are not useful
1747 while ( i
<= nPtRelMax
&& n
++ < 100 )
1755 Clear(); //clear early because SetDecimalDigits is a slow recalc
1757 SetDecimalDigits( 0 );
1760 SetUnit( FUNIT_PERCENT
);
1762 sal_uInt16 i
= nRelMin
;
1763 while ( i
<= nRelMax
)
1773 Clear(); //clear early because SetDecimalDigits is a slow recalc
1774 bRelative
= bPtRelative
= false;
1775 SetDecimalDigits( 1 );
1778 SetUnit( FUNIT_POINT
);
1780 Fill( &aFontInfo
, pFontList
);
1784 SetSelection( aSelection
);
1788 OUString
FontSizeBox::CreateFieldText( sal_Int64 nValue
) const
1790 OUString
sRet( MetricBox::CreateFieldText( nValue
) );
1791 if ( bRelativeMode
&& bPtRelative
&& (0 <= nValue
) && !sRet
.isEmpty() )
1796 void FontSizeBox::SetValue( sal_Int64 nNewValue
, FieldUnit eInUnit
)
1800 sal_Int64 nTempValue
= MetricField::ConvertValue( nNewValue
, GetBaseValue(), GetDecimalDigits(), eInUnit
, GetUnit() );
1801 FontSizeNames
aFontSizeNames( GetSettings().GetUILanguageTag().getLanguageType() );
1802 // conversion loses precision; however font sizes should
1803 // never have a problem with that
1804 OUString aName
= aFontSizeNames
.Size2Name( static_cast<long>(nTempValue
) );
1805 if ( !aName
.isEmpty() && (GetEntryPos( aName
) != LISTBOX_ENTRY_NOTFOUND
) )
1807 mnLastValue
= nTempValue
;
1809 mnFieldValue
= mnLastValue
;
1810 SetEmptyFieldValueData( false );
1815 MetricBox::SetValue( nNewValue
, eInUnit
);
1818 void FontSizeBox::SetValue( sal_Int64 nNewValue
)
1820 SetValue( nNewValue
, FUNIT_NONE
);
1823 sal_Int64
FontSizeBox::GetValue( FieldUnit eOutUnit
) const
1827 FontSizeNames
aFontSizeNames( GetSettings().GetUILanguageTag().getLanguageType() );
1828 sal_Int64 nValue
= aFontSizeNames
.Name2Size( GetText() );
1830 return MetricField::ConvertValue( nValue
, GetBaseValue(), GetDecimalDigits(), GetUnit(), eOutUnit
);
1833 return MetricBox::GetValue( eOutUnit
);
1836 sal_Int64
FontSizeBox::GetValue() const
1838 // implementation not inline, because it is a virtual function
1839 return GetValue( FUNIT_NONE
);
1842 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */