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