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 .
22 #include <tools/shl.hxx>
23 #include <vcl/svapp.hxx>
24 #include <svtools/colorcfg.hxx>
25 #include <svl/eitem.hxx>
26 #include <svl/intitem.hxx>
27 #include <svl/itempool.hxx>
29 #include <rtl/textenc.h>
30 #include <svx/ucsubset.hxx>
31 #include <sfx2/objsh.hxx>
32 #include <vcl/msgbox.hxx>
33 #include <svl/stritem.hxx>
36 #include <dialmgr.hxx>
37 #include "cuicharmap.hxx"
38 #include <sfx2/request.hxx>
39 #include <sfx2/sfxsids.hrc>
40 #include <sfx2/app.hxx>
41 #include <editeng/fontitem.hxx>
42 #include "macroass.hxx"
44 // class SvxCharacterMap =================================================
46 SvxCharacterMap::SvxCharacterMap( Window
* pParent
, sal_Bool bOne_
, const SfxItemSet
* pSet
)
47 : SfxModalDialog(pParent
, "SpecialCharactersDialog", "cui/ui/specialcharacters.ui")
51 get(m_pShowSet
, "showcharset");
52 get(m_pShowChar
, "showchar");
53 m_pShowChar
->SetCentered(true);
54 get(m_pShowText
, "showtext");
56 get(m_pDeleteBtn
, "delete");
57 get(m_pDeleteLastBtn
, "deletelast");
58 get(m_pFontText
, "fontft");
59 get(m_pFontLB
, "fontlb");
60 m_pFontLB
->SetStyle(m_pFontLB
->GetStyle() | WB_SORT
);
61 get(m_pSubsetText
, "subsetft");
62 get(m_pSubsetLB
, "subsetlb");
63 //lock the size request of this widget to the width of all possible entries
64 fillAllSubsets(*m_pSubsetLB
);
65 m_pSubsetLB
->set_width_request(m_pSubsetLB
->get_preferred_size().Width());
66 get(m_pCharCodeText
, "charcodeft");
67 //lock the size request of this widget to the width of the original .ui string
68 m_pCharCodeText
->set_width_request(m_pCharCodeText
->get_preferred_size().Width());
69 get(m_pSymbolText
, "symboltext");
70 //lock the size request of this widget to double the height of the label
71 m_pShowText
->set_height_request(m_pSymbolText
->get_preferred_size().Height() * 3);
73 SFX_ITEMSET_ARG( pSet
, pItem
, SfxBoolItem
, FN_PARAM_1
, sal_False
);
75 bOne
= pItem
->GetValue();
79 SFX_ITEMSET_ARG( pSet
, pCharItem
, SfxInt32Item
, SID_ATTR_CHAR
, sal_False
);
81 SetChar( pCharItem
->GetValue() );
83 SFX_ITEMSET_ARG( pSet
, pDisableItem
, SfxBoolItem
, FN_PARAM_2
, sal_False
);
84 if ( pDisableItem
&& pDisableItem
->GetValue() )
85 DisableFontSelection();
87 SFX_ITEMSET_ARG( pSet
, pFontItem
, SvxFontItem
, SID_ATTR_CHAR_FONT
, sal_False
);
88 SFX_ITEMSET_ARG( pSet
, pFontNameItem
, SfxStringItem
, SID_FONT_NAME
, sal_False
);
91 Font
aTmpFont( pFontItem
->GetFamilyName(), pFontItem
->GetStyleName(), GetCharFont().GetSize() );
92 aTmpFont
.SetCharSet( pFontItem
->GetCharSet() );
93 aTmpFont
.SetPitch( pFontItem
->GetPitch() );
94 SetCharFont( aTmpFont
);
96 else if ( pFontNameItem
)
98 Font
aTmpFont( GetCharFont() );
99 aTmpFont
.SetName( pFontNameItem
->GetValue() );
100 SetCharFont( aTmpFont
);
103 CreateOutputItemSet( pSet
? *pSet
->GetPool() : SFX_APP()->GetPool() );
106 // -----------------------------------------------------------------------
108 SvxCharacterMap::~SvxCharacterMap()
112 // -----------------------------------------------------------------------
114 const Font
& SvxCharacterMap::GetCharFont() const
119 // -----------------------------------------------------------------------
121 void SvxCharacterMap::SetChar( sal_UCS4 c
)
123 m_pShowSet
->SelectCharacter( c
);
126 // -----------------------------------------------------------------------
128 sal_UCS4
SvxCharacterMap::GetChar() const
130 return m_pShowSet
->GetSelectCharacter();
133 // -----------------------------------------------------------------------
135 String
SvxCharacterMap::GetCharacters() const
137 return m_pShowText
->GetText();
141 // -----------------------------------------------------------------------
143 void SvxCharacterMap::DisableFontSelection()
145 m_pFontText
->Disable();
146 m_pFontLB
->Disable();
149 short SvxCharacterMap::Execute()
151 short nResult
= SfxModalDialog::Execute();
152 if ( nResult
== RET_OK
)
154 SfxItemSet
* pSet
= GetItemSet();
157 const SfxItemPool
* pPool
= pSet
->GetPool();
158 const Font
& rFont( GetCharFont() );
159 pSet
->Put( SfxStringItem( pPool
->GetWhich(SID_CHARMAP
), GetCharacters() ) );
160 pSet
->Put( SvxFontItem( rFont
.GetFamily(), rFont
.GetName(),
161 rFont
.GetStyleName(), rFont
.GetPitch(), rFont
.GetCharSet(), pPool
->GetWhich(SID_ATTR_CHAR_FONT
) ) );
162 pSet
->Put( SfxStringItem( pPool
->GetWhich(SID_FONT_NAME
), rFont
.GetName() ) );
163 pSet
->Put( SfxInt32Item( pPool
->GetWhich(SID_ATTR_CHAR
), GetChar() ) );
171 // class SvxShowText =====================================================
173 SvxShowText::SvxShowText(Window
* pParent
, sal_Bool bCenter
)
174 : Control( pParent
),
178 extern "C" SAL_DLLPUBLIC_EXPORT Window
* SAL_CALL
makeSvxShowText(Window
*pParent
, VclBuilder::stringmap
&)
180 return new SvxShowText(pParent
);
183 // -----------------------------------------------------------------------
185 void SvxShowText::Paint( const Rectangle
& )
187 Color aTextCol
= GetTextColor();
189 const StyleSettings
& rStyleSettings
= Application::GetSettings().GetStyleSettings();
190 const Color
aWindowTextColor( rStyleSettings
.GetDialogTextColor() );
191 SetTextColor( aWindowTextColor
);
193 const String aText
= GetText();
194 const Size aSize
= GetOutputSizePixel();
196 long nAvailWidth
= aSize
.Width();
197 long nWinHeight
= GetOutputSizePixel().Height();
199 bool bGotBoundary
= true;
200 bool bShrankFont
= false;
201 Font
aOrigFont(GetFont());
202 Size
aFontSize(aOrigFont
.GetSize());
203 Rectangle aBoundRect
;
205 for (long nFontHeight
= aFontSize
.Height(); nFontHeight
> 0; nFontHeight
-= 5)
207 if( !GetTextBoundRect( aBoundRect
, aText
) || aBoundRect
.IsEmpty() )
209 bGotBoundary
= false;
214 //only shrink in the single glyph large view mode
215 long nTextWidth
= aBoundRect
.GetWidth();
216 if (nAvailWidth
> nTextWidth
)
218 Font
aFont(aOrigFont
);
219 aFontSize
.Height() = nFontHeight
;
220 aFont
.SetSize(aFontSize
);
221 Control::SetFont(aFont
);
222 mnY
= ( nWinHeight
- GetTextHeight() ) / 2;
226 Point
aPoint( 2, mnY
);
227 // adjust position using ink boundary if possible
229 aPoint
.X() = (aSize
.Width() - GetTextWidth( aText
)) / 2;
232 // adjust position before it gets out of bounds
233 aBoundRect
+= aPoint
;
235 // shift back vertically if needed
236 int nYLDelta
= aBoundRect
.Top();
237 int nYHDelta
= aSize
.Height() - aBoundRect
.Bottom();
239 aPoint
.Y() -= nYLDelta
- 1;
240 else if( nYHDelta
<= 0 )
241 aPoint
.Y() += nYHDelta
- 1;
245 // move glyph to middle of cell
246 aPoint
.X() = -aBoundRect
.Left()
247 + (aSize
.Width() - aBoundRect
.GetWidth()) / 2;
251 // shift back horizontally if needed
252 int nXLDelta
= aBoundRect
.Left();
253 int nXHDelta
= aSize
.Width() - aBoundRect
.Right();
255 aPoint
.X() -= nXLDelta
- 1;
256 else if( nXHDelta
<= 0 )
257 aPoint
.X() += nXHDelta
- 1;
261 DrawText( aPoint
, aText
);
262 SetTextColor( aTextCol
);
264 Control::SetFont(aOrigFont
);
267 // -----------------------------------------------------------------------
269 void SvxShowText::SetFont( const Font
& rFont
)
271 long nWinHeight
= GetOutputSizePixel().Height();
273 aFont
.SetWeight( WEIGHT_NORMAL
);
274 aFont
.SetAlign( ALIGN_TOP
);
275 aFont
.SetSize( PixelToLogic( Size( 0, nWinHeight
/2 ) ) );
276 aFont
.SetTransparent( sal_True
);
277 Control::SetFont( aFont
);
278 mnY
= ( nWinHeight
- GetTextHeight() ) / 2;
283 Size
SvxShowText::GetOptimalSize() const
285 const Font
&rFont
= GetFont();
286 const Size rFontSize
= rFont
.GetSize();
287 long nWinHeight
= LogicToPixel(rFontSize
).Height() * 2;
288 return Size( GetTextWidth( GetText() ) + 2 * 12, nWinHeight
);
291 void SvxShowText::Resize()
294 SetFont(GetFont()); //force recalculation of size
297 // -----------------------------------------------------------------------
299 void SvxShowText::SetText( const OUString
& rText
)
301 Control::SetText( rText
);
305 // -----------------------------------------------------------------------
307 SvxShowText::~SvxShowText()
310 // class SvxCharacterMap =================================================
312 void SvxCharacterMap::init()
315 aFont
.SetTransparent( sal_True
);
316 aFont
.SetFamily( FAMILY_DONTKNOW
);
317 aFont
.SetPitch( PITCH_DONTKNOW
);
318 aFont
.SetCharSet( RTL_TEXTENCODING_DONTKNOW
);
322 m_pSymbolText
->Hide();
324 m_pDeleteBtn
->Hide();
325 m_pDeleteLastBtn
->Hide();
328 OUString
aDefStr( aFont
.GetName() );
330 int nCount
= GetDevFontCount();
331 for ( int i
= 0; i
< nCount
; i
++ )
333 String
aFontName( GetDevFont( i
).GetName() );
334 if ( aFontName
!= aLastName
)
336 aLastName
= aFontName
;
337 sal_uInt16 nPos
= m_pFontLB
->InsertEntry( aFontName
);
338 m_pFontLB
->SetEntryData( nPos
, (void*)(sal_uLong
)i
);
341 // the font may not be in the list =>
342 // try to find a font name token in list and select found font,
343 // else select topmost entry
344 bool bFound
= (m_pFontLB
->GetEntryPos( aDefStr
) == LISTBOX_ENTRY_NOTFOUND
);
347 sal_Int32 nIndex
= 0;
350 OUString aToken
= aDefStr
.getToken(0, ';', nIndex
);
351 if ( m_pFontLB
->GetEntryPos( aToken
) != LISTBOX_ENTRY_NOTFOUND
)
358 while ( nIndex
>= 0 );
362 m_pFontLB
->SelectEntry( aDefStr
);
363 else if ( m_pFontLB
->GetEntryCount() )
364 m_pFontLB
->SelectEntryPos(0);
365 FontSelectHdl(m_pFontLB
);
367 m_pOKBtn
->SetClickHdl( LINK( this, SvxCharacterMap
, OKHdl
) );
368 m_pFontLB
->SetSelectHdl( LINK( this, SvxCharacterMap
, FontSelectHdl
) );
369 m_pSubsetLB
->SetSelectHdl( LINK( this, SvxCharacterMap
, SubsetSelectHdl
) );
370 m_pShowSet
->SetDoubleClickHdl( LINK( this, SvxCharacterMap
, CharDoubleClickHdl
) );
371 m_pShowSet
->SetSelectHdl( LINK( this, SvxCharacterMap
, CharSelectHdl
) );
372 m_pShowSet
->SetHighlightHdl( LINK( this, SvxCharacterMap
, CharHighlightHdl
) );
373 m_pShowSet
->SetPreSelectHdl( LINK( this, SvxCharacterMap
, CharPreSelectHdl
) );
374 m_pDeleteLastBtn
->SetClickHdl( LINK( this, SvxCharacterMap
, DeleteLastHdl
) );
375 m_pDeleteBtn
->SetClickHdl( LINK( this, SvxCharacterMap
, DeleteHdl
) );
377 if( SvxShowCharSet::getSelectedChar() == ' ')
383 // -----------------------------------------------------------------------
385 void SvxCharacterMap::SetCharFont( const Font
& rFont
)
387 // first get the underlying info in order to get font names
388 // like "Times New Roman;Times" resolved
389 Font
aTmp( GetFontMetric( rFont
) );
391 if ( m_pFontLB
->GetEntryPos( aTmp
.GetName() ) == LISTBOX_ENTRY_NOTFOUND
)
394 m_pFontLB
->SelectEntry( aTmp
.GetName() );
396 FontSelectHdl(m_pFontLB
);
398 // for compatibility reasons
399 ModalDialog::SetFont( aFont
);
402 // -----------------------------------------------------------------------
404 IMPL_LINK_NOARG(SvxCharacterMap
, OKHdl
)
406 String aStr
= m_pShowText
->GetText();
410 sal_UCS4 cChar
= m_pShowSet
->GetSelectCharacter();
411 // using the new UCS4 constructor
412 OUString
aOUStr( &cChar
, 1 );
413 m_pShowText
->SetText( aOUStr
);
415 EndDialog( sal_True
);
419 void SvxCharacterMap::fillAllSubsets(ListBox
&rListBox
)
421 SubsetMap
aAll(NULL
);
424 while (const Subset
*s
= aAll
.GetNextSubset(bFirst
))
426 rListBox
.InsertEntry( s
->GetName() );
431 // -----------------------------------------------------------------------
433 IMPL_LINK_NOARG(SvxCharacterMap
, FontSelectHdl
)
435 sal_uInt16 nPos
= m_pFontLB
->GetSelectEntryPos(),
436 nFont
= (sal_uInt16
)(sal_uLong
)m_pFontLB
->GetEntryData( nPos
);
437 aFont
= GetDevFont( nFont
);
438 aFont
.SetWeight( WEIGHT_DONTKNOW
);
439 aFont
.SetItalic( ITALIC_NONE
);
440 aFont
.SetWidthType( WIDTH_DONTKNOW
);
441 aFont
.SetPitch( PITCH_DONTKNOW
);
442 aFont
.SetFamily( FAMILY_DONTKNOW
);
444 // notify children using this font
445 m_pShowSet
->SetFont( aFont
);
446 m_pShowChar
->SetFont( aFont
);
447 m_pShowText
->SetFont( aFont
);
449 // setup unicode subset listbar with font specific subsets,
450 // hide unicode subset listbar for symbol fonts
451 // TODO: get info from the Font once it provides it
454 m_pSubsetLB
->Clear();
456 sal_Bool bNeedSubset
= (aFont
.GetCharSet() != RTL_TEXTENCODING_SYMBOL
);
459 FontCharMap aFontCharMap
;
460 m_pShowSet
->GetFontCharMap( aFontCharMap
);
461 pSubsetMap
= new SubsetMap( &aFontCharMap
);
463 // update subset listbox for new font's unicode subsets
464 // TODO: is it worth to improve the stupid linear search?
467 while( NULL
!= (s
= pSubsetMap
->GetNextSubset( bFirst
)) )
469 sal_uInt16 nPos_
= m_pSubsetLB
->InsertEntry( s
->GetName() );
470 m_pSubsetLB
->SetEntryData( nPos_
, (void*)s
);
471 // NOTE: subset must live at least as long as the selected font
473 m_pSubsetLB
->SelectEntryPos( nPos_
);
476 if( m_pSubsetLB
->GetEntryCount() <= 1 )
477 bNeedSubset
= sal_False
;
480 m_pSubsetText
->Enable(bNeedSubset
);
481 m_pSubsetLB
->Enable(bNeedSubset
);
486 // -----------------------------------------------------------------------
488 IMPL_LINK_NOARG(SvxCharacterMap
, SubsetSelectHdl
)
490 sal_uInt16 nPos
= m_pSubsetLB
->GetSelectEntryPos();
491 const Subset
* pSubset
= reinterpret_cast<const Subset
*> (m_pSubsetLB
->GetEntryData(nPos
));
494 sal_UCS4 cFirst
= pSubset
->GetRangeMin();
495 m_pShowSet
->SelectCharacter( cFirst
);
497 m_pSubsetLB
->SelectEntryPos( nPos
);
501 // -----------------------------------------------------------------------
503 IMPL_LINK_NOARG(SvxCharacterMap
, CharDoubleClickHdl
)
505 EndDialog( sal_True
);
509 // -----------------------------------------------------------------------
511 IMPL_LINK_NOARG(SvxCharacterMap
, CharSelectHdl
)
515 String aText
= m_pShowText
->GetText();
517 if ( aText
.Len() != CHARMAP_MAXLEN
)
519 sal_UCS4 cChar
= m_pShowSet
->GetSelectCharacter();
520 // using the new UCS4 constructor
521 OUString
aOUStr( &cChar
, 1 );
522 m_pShowText
->SetText( aText
+ aOUStr
);
527 m_pDeleteLastBtn
->Enable();
531 // -----------------------------------------------------------------------
533 IMPL_LINK_NOARG(SvxCharacterMap
, CharHighlightHdl
)
536 sal_UCS4 cChar
= m_pShowSet
->GetSelectCharacter();
537 sal_Bool bSelect
= (cChar
> 0);
542 // using the new UCS4 constructor
543 aText
= OUString( &cChar
, 1 );
545 const Subset
* pSubset
= NULL
;
547 pSubset
= pSubsetMap
->GetSubsetByUnicode( cChar
);
549 m_pSubsetLB
->SelectEntry( pSubset
->GetName() );
551 m_pSubsetLB
->SetNoSelection();
553 m_pShowChar
->SetText( aText
);
554 m_pShowChar
->Update();
560 snprintf( aBuf
, sizeof(aBuf
), "U+%04X", static_cast<unsigned>(cChar
) );
562 snprintf( aBuf
+6, sizeof(aBuf
)-6, " (%u)", static_cast<unsigned>(cChar
) );
563 aText
= OUString::createFromAscii(aBuf
);
565 m_pCharCodeText
->SetText( aText
);
570 // -----------------------------------------------------------------------
572 IMPL_LINK_NOARG(SvxCharacterMap
, CharPreSelectHdl
)
574 // adjust subset selection
577 sal_UCS4 cChar
= m_pShowSet
->GetSelectCharacter();
578 const Subset
* pSubset
= pSubsetMap
->GetSubsetByUnicode( cChar
);
580 m_pSubsetLB
->SelectEntry( pSubset
->GetName() );
587 // -----------------------------------------------------------------------
589 IMPL_LINK_NOARG(SvxCharacterMap
, DeleteLastHdl
)
591 OUString aCurrentText
= m_pShowText
->GetText();
592 m_pShowText
->SetText( aCurrentText
.copy( 0, aCurrentText
.getLength() - 1 ) );
593 if ( m_pShowText
->GetText() == "" )
596 m_pDeleteLastBtn
->Disable();
601 IMPL_LINK_NOARG(SvxCharacterMap
, DeleteHdl
)
603 m_pShowText
->SetText( String() );
605 m_pDeleteLastBtn
->Disable();
609 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */