xref: /aoo41x/main/cui/source/dialogs/cuicharmap.cxx (revision cdf0e10c)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_cui.hxx"
30 
31 // include ---------------------------------------------------------------
32 
33 #include <stdio.h>
34 
35 #define _CUI_CHARMAP_CXX_
36 #include <tools/shl.hxx>
37 #include <tools/debug.hxx>
38 #include <vcl/sound.hxx>
39 #include <vcl/svapp.hxx>
40 #include <vcl/msgbox.hxx>
41 #include <svtools/colorcfg.hxx>
42 #include <svl/eitem.hxx>
43 #include <svl/intitem.hxx>
44 #include <svl/stritem.hxx>
45 #include <svl/itempool.hxx>
46 
47 #include <rtl/textenc.h>
48 #include <svx/ucsubset.hxx>
49 
50 #include <cuires.hrc>
51 #include <dialmgr.hxx>
52 #include "cuicharmap.hxx"
53 #include <sfx2/request.hxx>
54 #include <sfx2/sfxsids.hrc>
55 #include <sfx2/app.hxx>
56 #include <editeng/fontitem.hxx>
57 #include "charmap.hrc"
58 #include "macroass.hxx"
59 
60 // class SvxCharacterMap =================================================
61 
62 SvxCharacterMap::SvxCharacterMap( Window* pParent, sal_Bool bOne, const SfxItemSet* pSet ) :
63     SfxModalDialog( pParent, CUI_RES( RID_SVXDLG_CHARMAP ) ),
64     mpCharMapData( 0 )
65 {
66 	SFX_ITEMSET_ARG( pSet, pItem, SfxBoolItem, FN_PARAM_1, sal_False );
67 	if ( pItem )
68 		bOne = pItem->GetValue();
69 
70     mpCharMapData =  new SvxCharMapData( this, bOne, &CUI_MGR() );
71 
72     SFX_ITEMSET_ARG( pSet, pCharItem, SfxInt32Item, SID_ATTR_CHAR, sal_False );
73 	if ( pCharItem )
74         SetChar( pCharItem->GetValue() );
75 
76 	SFX_ITEMSET_ARG( pSet, pDisableItem, SfxBoolItem, FN_PARAM_2, sal_False );
77 	if ( pDisableItem && pDisableItem->GetValue() )
78 		DisableFontSelection();
79 
80 	SFX_ITEMSET_ARG( pSet, pFontItem, SvxFontItem, SID_ATTR_CHAR_FONT, sal_False );
81 	SFX_ITEMSET_ARG( pSet, pFontNameItem, SfxStringItem, SID_FONT_NAME, sal_False );
82 	if ( pFontItem )
83 	{
84 		Font aFont( pFontItem->GetFamilyName(), pFontItem->GetStyleName(), GetCharFont().GetSize() );
85 		aFont.SetCharSet( pFontItem->GetCharSet() );
86 		aFont.SetPitch( pFontItem->GetPitch() );
87 		SetCharFont( aFont );
88 	}
89 	else if ( pFontNameItem )
90 	{
91 		Font aFont( GetCharFont() );
92 		aFont.SetName( pFontNameItem->GetValue() );
93 		SetCharFont( aFont );
94 	}
95 
96     FreeResource();
97 	CreateOutputItemSet( pSet ? *pSet->GetPool() : SFX_APP()->GetPool() );
98 }
99 
100 // -----------------------------------------------------------------------
101 
102 SvxCharacterMap::~SvxCharacterMap()
103 {
104     delete mpCharMapData;
105 }
106 
107 // -----------------------------------------------------------------------
108 
109 const Font& SvxCharacterMap::GetCharFont() const
110 {
111     return mpCharMapData->aFont;
112 }
113 
114 // -----------------------------------------------------------------------
115 
116 void SvxCharacterMap::SetChar( sal_UCS4 c )
117 {
118     mpCharMapData->aShowSet.SelectCharacter( c );
119 }
120 
121 // -----------------------------------------------------------------------
122 
123 sal_UCS4 SvxCharacterMap::GetChar() const
124 {
125     return mpCharMapData->aShowSet.GetSelectCharacter();
126 }
127 
128 // -----------------------------------------------------------------------
129 
130 String SvxCharacterMap::GetCharacters() const
131 {
132     return mpCharMapData->aShowText.GetText();
133 }
134 
135 
136 // -----------------------------------------------------------------------
137 
138 void SvxCharacterMap::DisableFontSelection()
139 {
140     mpCharMapData->aFontText.Disable();
141     mpCharMapData->aFontLB.Disable();
142 }
143 
144 void SvxCharacterMap::SetCharFont( const Font& rFont )
145 {
146     mpCharMapData->SetCharFont( rFont );
147 }
148 
149 short SvxCharacterMap::Execute()
150 {
151 	short nResult = SfxModalDialog::Execute();
152 	if ( nResult == RET_OK )
153 	{
154 		SfxItemSet* pSet = GetItemSet();
155 		if ( pSet )
156 		{
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() ) );
164 		}
165 	}
166 
167 	return nResult;
168 }
169 
170 
171 // class SvxShowText =====================================================
172 
173 SvxShowText::SvxShowText( Window* pParent, const ResId& rResId, sal_Bool bCenter )
174 :   Control( pParent, rResId ),
175     mbCenter( bCenter)
176 {}
177 
178 // -----------------------------------------------------------------------
179 
180 void SvxShowText::Paint( const Rectangle& )
181 {
182     Color aTextCol = GetTextColor();
183 
184     const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
185     const Color aWindowTextColor( rStyleSettings.GetDialogTextColor() );
186     SetTextColor( aWindowTextColor );
187 
188     const String aText = GetText();
189     const Size aSize = GetOutputSizePixel();
190     Point aPoint( 2, mnY );
191 
192     // adjust position using ink boundary if possible
193     Rectangle aBoundRect;
194     if( !GetTextBoundRect( aBoundRect, aText ) || aBoundRect.IsEmpty() )
195         aPoint.X() = (aSize.Width() - GetTextWidth( aText )) / 2;
196     else
197     {
198         // adjust position before it gets out of bounds
199         aBoundRect += aPoint;
200 
201         // shift back vertically if needed
202         int nYLDelta = aBoundRect.Top();
203         int nYHDelta = aSize.Height() - aBoundRect.Bottom();
204         if( nYLDelta <= 0 )
205             aPoint.Y() -= nYLDelta - 1;
206         else if( nYHDelta <= 0 )
207             aPoint.Y() += nYHDelta - 1;
208 
209         if( mbCenter )
210         {
211             // move glyph to middle of cell
212             aPoint.X() = -aBoundRect.Left()
213                        + (aSize.Width() - aBoundRect.GetWidth()) / 2;
214         }
215         else
216         {
217             // shift back horizontally if needed
218             int nXLDelta = aBoundRect.Left();
219             int nXHDelta = aSize.Width() - aBoundRect.Right();
220             if( nXLDelta <= 0 )
221                 aPoint.X() -= nXLDelta - 1;
222             else if( nXHDelta <= 0 )
223                 aPoint.X() += nXHDelta - 1;
224         }
225     }
226 
227     DrawText( aPoint, aText );
228     SetTextColor( aTextCol );
229 }
230 
231 // -----------------------------------------------------------------------
232 
233 void SvxShowText::SetFont( const Font& rFont )
234 {
235     long nWinHeight = GetOutputSizePixel().Height();
236     Font aFont = rFont;
237     aFont.SetWeight( WEIGHT_NORMAL );
238     aFont.SetAlign( ALIGN_TOP );
239     aFont.SetSize( PixelToLogic( Size( 0, nWinHeight/2 ) ) );
240     aFont.SetTransparent( sal_True );
241     Control::SetFont( aFont );
242     mnY = ( nWinHeight - GetTextHeight() ) / 2;
243 
244     Invalidate();
245 }
246 
247 // -----------------------------------------------------------------------
248 
249 void SvxShowText::SetText( const String& rText )
250 {
251     Control::SetText( rText );
252     Invalidate();
253 }
254 
255 // -----------------------------------------------------------------------
256 
257 SvxShowText::~SvxShowText()
258 {}
259 
260 // class SvxCharacterMap =================================================
261 
262 SvxCharMapData::SvxCharMapData( SfxModalDialog* pDialog, sal_Bool bOne_, ResMgr* pResContext )
263 :   mpDialog( pDialog ),
264     aShowSet        ( pDialog, ResId( CT_SHOWSET, *pResContext ) ),
265     aShowText       ( pDialog, ResId( CT_SHOWTEXT, *pResContext ) ),
266 //    aShowShortcut   ( pDialog, ResId( CT_ASSIGN, *pResContext ) ),
267     aOKBtn          ( pDialog, ResId( BTN_CHAR_OK, *pResContext ) ),
268     aCancelBtn      ( pDialog, ResId( BTN_CHAR_CANCEL, *pResContext ) ),
269     aHelpBtn        ( pDialog, ResId( BTN_CHAR_HELP, *pResContext ) ),
270     aDeleteBtn      ( pDialog, ResId( BTN_DELETE, *pResContext ) ),
271 //    aAssignBtn      ( pDialog, ResId( BT_ASSIGN, *pResContext ) ),
272     aFontText       ( pDialog, ResId( FT_FONT, *pResContext ) ),
273     aFontLB         ( pDialog, ResId( LB_FONT, *pResContext ) ),
274     aSubsetText     ( pDialog, ResId( FT_SUBSET, *pResContext ) ),
275     aSubsetLB       ( pDialog, ResId( LB_SUBSET, *pResContext ) ),
276     aSymbolText     ( pDialog, ResId( FT_SYMBOLE, *pResContext ) ),
277     aShowChar       ( pDialog, ResId( CT_SHOWCHAR, *pResContext ), sal_True ),
278     aCharCodeText   ( pDialog, ResId( FT_CHARCODE, *pResContext ) ),
279 //    aAssignText     ( pDialog, ResId( FT_ASSIGN, *pResContext ) ),
280     bOne( bOne_ ),
281     pSubsetMap( NULL )
282 {
283     aFont = pDialog->GetFont();
284     aFont.SetTransparent( sal_True );
285     aFont.SetFamily( FAMILY_DONTKNOW );
286     aFont.SetPitch( PITCH_DONTKNOW );
287     aFont.SetCharSet( RTL_TEXTENCODING_DONTKNOW );
288 
289     if ( bOne )
290     {
291         Size aDlgSize = pDialog->GetSizePixel();
292         pDialog->SetSizePixel( Size( aDlgSize.Width(),
293             aDlgSize.Height()-aShowText.GetSizePixel().Height() ) );
294         aSymbolText.Hide();
295         aShowText.Hide();
296         aDeleteBtn.Hide();
297     }
298 
299     String aDefStr( aFont.GetName() );
300     String aLastName;
301     int nCount = mpDialog->GetDevFontCount();
302     for ( int i = 0; i < nCount; i++ )
303     {
304         String aFontName( mpDialog->GetDevFont( i ).GetName() );
305         if ( aFontName != aLastName )
306         {
307             aLastName = aFontName;
308             sal_uInt16 nPos = aFontLB.InsertEntry( aFontName );
309             aFontLB.SetEntryData( nPos, (void*)(sal_uLong)i );
310         }
311     }
312     // the font may not be in the list =>
313     // try to find a font name token in list and select found font,
314     // else select topmost entry
315     FASTBOOL bFound = (aFontLB.GetEntryPos( aDefStr ) == LISTBOX_ENTRY_NOTFOUND );
316     if( !bFound )
317     {
318         for ( xub_StrLen i = 0; i < aDefStr.GetTokenCount(); ++i )
319         {
320             String aToken = aDefStr.GetToken(i);
321             if ( aFontLB.GetEntryPos( aToken ) != LISTBOX_ENTRY_NOTFOUND )
322             {
323                 aDefStr = aToken;
324                 bFound = sal_True;
325                 break;
326             }
327         }
328     }
329 
330     if ( bFound )
331         aFontLB.SelectEntry( aDefStr );
332     else if ( aFontLB.GetEntryCount() )
333         aFontLB.SelectEntryPos(0);
334     FontSelectHdl( &aFontLB );
335 
336     aOKBtn.SetClickHdl( LINK( this, SvxCharMapData, OKHdl ) );
337     aFontLB.SetSelectHdl( LINK( this, SvxCharMapData, FontSelectHdl ) );
338     aSubsetLB.SetSelectHdl( LINK( this, SvxCharMapData, SubsetSelectHdl ) );
339     aShowSet.SetDoubleClickHdl( LINK( this, SvxCharMapData, CharDoubleClickHdl ) );
340     aShowSet.SetSelectHdl( LINK( this, SvxCharMapData, CharSelectHdl ) );
341     aShowSet.SetHighlightHdl( LINK( this, SvxCharMapData, CharHighlightHdl ) );
342     aShowSet.SetPreSelectHdl( LINK( this, SvxCharMapData, CharPreSelectHdl ) );
343     aDeleteBtn.SetClickHdl( LINK( this, SvxCharMapData, DeleteHdl ) );
344 //    aAssignBtn.SetClickHdl( LINK( this, SvxCharMapData, AssignHdl ) );
345 
346 	if( SvxShowCharSet::getSelectedChar() == ' ')
347         aOKBtn.Disable();
348     else
349         aOKBtn.Enable();
350 
351     // left align aShowText field
352     int nLeftEdge = aSymbolText.GetPosPixel().X();
353     nLeftEdge += aSymbolText.GetTextWidth( aSymbolText.GetText() );
354     Size aNewSize = aShowText.GetOutputSizePixel();
355     aShowText.SetPosPixel( Point( nLeftEdge+4, aShowText.GetPosPixel().Y() ) );
356 }
357 
358 // -----------------------------------------------------------------------
359 
360 void SvxCharMapData::SetCharFont( const Font& rFont )
361 {
362     // first get the underlying info in order to get font names
363     // like "Times New Roman;Times" resolved
364     Font aTmp( mpDialog->GetFontMetric( rFont ) );
365 
366     if ( aFontLB.GetEntryPos( aTmp.GetName() ) == LISTBOX_ENTRY_NOTFOUND )
367         return;
368 
369     aFontLB.SelectEntry( aTmp.GetName() );
370     aFont = aTmp;
371     FontSelectHdl( &aFontLB );
372 
373     // for compatibility reasons
374     mpDialog->ModalDialog::SetFont( aFont );
375 }
376 
377 // -----------------------------------------------------------------------
378 
379 IMPL_LINK( SvxCharMapData, OKHdl, OKButton *, EMPTYARG )
380 {
381     String aStr = aShowText.GetText();
382 
383     if ( !aStr.Len() )
384     {
385         sal_UCS4 cChar = aShowSet.GetSelectCharacter();
386         // using the new UCS4 constructor
387 	rtl::OUString aOUStr( &cChar, 1 );
388         aShowText.SetText( aOUStr );
389     }
390     mpDialog->EndDialog( sal_True );
391     return 0;
392 }
393 
394 // -----------------------------------------------------------------------
395 
396 IMPL_LINK( SvxCharMapData, FontSelectHdl, ListBox *, EMPTYARG )
397 {
398     sal_uInt16 nPos = aFontLB.GetSelectEntryPos(),
399         nFont = (sal_uInt16)(sal_uLong)aFontLB.GetEntryData( nPos );
400     aFont = mpDialog->GetDevFont( nFont );
401 	aFont.SetWeight( WEIGHT_DONTKNOW );
402 	aFont.SetItalic( ITALIC_NONE );
403     aFont.SetWidthType( WIDTH_DONTKNOW );
404 	aFont.SetPitch( PITCH_DONTKNOW );
405 	aFont.SetFamily( FAMILY_DONTKNOW );
406 
407     // notify children using this font
408     aShowSet.SetFont( aFont );
409     aShowChar.SetFont( aFont );
410     aShowText.SetFont( aFont );
411 
412     // right align some fields to aShowSet
413     int nRightEdge = aShowSet.GetPosPixel().X() + aShowSet.GetOutputSizePixel().Width();
414     Size aNewSize = aSubsetLB.GetOutputSizePixel();
415     aNewSize.setWidth( nRightEdge - aSubsetLB.GetPosPixel().X() );
416     aSubsetLB.SetOutputSizePixel( aNewSize );
417 
418     // setup unicode subset listbar with font specific subsets,
419     // hide unicode subset listbar for symbol fonts
420     // TODO: get info from the Font once it provides it
421     if( pSubsetMap)
422         delete pSubsetMap;
423     pSubsetMap = NULL;
424 
425     sal_Bool bNeedSubset = (aFont.GetCharSet() != RTL_TEXTENCODING_SYMBOL);
426     if( bNeedSubset )
427     {
428         FontCharMap aFontCharMap;
429         aShowSet.GetFontCharMap( aFontCharMap );
430         pSubsetMap = new SubsetMap( &aFontCharMap );
431 
432         // update subset listbox for new font's unicode subsets
433         aSubsetLB.Clear();
434         // TODO: is it worth to improve the stupid linear search?
435         bool bFirst = true;
436         const Subset* s;
437         while( NULL != (s = pSubsetMap->GetNextSubset( bFirst ))  )
438         {
439             sal_uInt16 nPos_ = aSubsetLB.InsertEntry( s->GetName() );
440             aSubsetLB.SetEntryData( nPos_, (void*)s );
441             // NOTE: subset must live at least as long as the selected font
442             if( bFirst )
443                 aSubsetLB.SelectEntryPos( nPos_ );
444             bFirst = false;
445         }
446         if( aSubsetLB.GetEntryCount() <= 1 )
447             bNeedSubset = sal_False;
448     }
449 
450     aSubsetText.Show( bNeedSubset);
451     aSubsetLB.Show( bNeedSubset);
452 
453     return 0;
454 }
455 
456 // -----------------------------------------------------------------------
457 
458 IMPL_LINK( SvxCharMapData, SubsetSelectHdl, ListBox *, EMPTYARG )
459 {
460     sal_uInt16 nPos = aSubsetLB.GetSelectEntryPos();
461     const Subset* pSubset = reinterpret_cast<const Subset*> (aSubsetLB.GetEntryData(nPos));
462     if( pSubset )
463     {
464         sal_UCS4 cFirst = pSubset->GetRangeMin();
465         aShowSet.SelectCharacter( cFirst );
466     }
467     aSubsetLB.SelectEntryPos( nPos );
468     return 0;
469 }
470 
471 // -----------------------------------------------------------------------
472 
473 IMPL_LINK( SvxCharMapData, CharDoubleClickHdl, Control *, EMPTYARG )
474 {
475     mpDialog->EndDialog( sal_True );
476     return 0;
477 }
478 
479 // -----------------------------------------------------------------------
480 
481 IMPL_LINK( SvxCharMapData, CharSelectHdl, Control *, EMPTYARG )
482 {
483     if ( !bOne )
484     {
485         String aText = aShowText.GetText();
486 
487         if ( aText.Len() == CHARMAP_MAXLEN )
488             Sound::Beep( SOUND_WARNING );
489         else
490         {
491             sal_UCS4 cChar = aShowSet.GetSelectCharacter();
492             // using the new UCS4 constructor
493             rtl::OUString aOUStr( &cChar, 1 );
494             aShowText.SetText( aText + aOUStr );
495         }
496 
497     }
498     aOKBtn.Enable();
499     return 0;
500 }
501 
502 // -----------------------------------------------------------------------
503 
504 IMPL_LINK( SvxCharMapData, CharHighlightHdl, Control *, EMPTYARG )
505 {
506     String aText;
507     sal_UCS4 cChar = aShowSet.GetSelectCharacter();
508     sal_Bool bSelect = (cChar > 0);
509 
510     // show char sample
511     if ( bSelect )
512     {
513 		// using the new UCS4 constructor
514 		aText = rtl::OUString( &cChar, 1 );
515 
516         const Subset* pSubset = NULL;
517         if( pSubsetMap )
518             pSubset = pSubsetMap->GetSubsetByUnicode( cChar );
519         if( pSubset )
520             aSubsetLB.SelectEntry( pSubset->GetName() );
521         else
522             aSubsetLB.SetNoSelection();
523     }
524     aShowChar.SetText( aText );
525     aShowChar.Update();
526 
527     // show char code
528     if ( bSelect )
529     {
530         char aBuf[32];
531         snprintf( aBuf, sizeof(aBuf), "U+%04X", static_cast<unsigned>(cChar) );
532         if( cChar < 0x0100 )
533             snprintf( aBuf+6, sizeof(aBuf)-6, " (%u)", static_cast<unsigned>(cChar) );
534         aText = String::CreateFromAscii( aBuf );
535     }
536     aCharCodeText.SetText( aText );
537 
538     return 0;
539 }
540 
541 // -----------------------------------------------------------------------
542 
543 IMPL_LINK( SvxCharMapData, CharPreSelectHdl, Control *, EMPTYARG )
544 {
545     // adjust subset selection
546     if( pSubsetMap )
547     {
548         sal_UCS4 cChar = aShowSet.GetSelectCharacter();
549         const Subset* pSubset = pSubsetMap->GetSubsetByUnicode( cChar );
550         if( pSubset )
551             aSubsetLB.SelectEntry( pSubset->GetName() );
552     }
553 
554     aOKBtn.Enable();
555     return 0;
556 }
557 
558 // -----------------------------------------------------------------------
559 
560 IMPL_LINK( SvxCharMapData, DeleteHdl, PushButton *, EMPTYARG )
561 {
562     aShowText.SetText( String() );
563     aOKBtn.Disable();
564     return 0;
565 }
566 
567 #include <sfx2/objsh.hxx>
568 #include <vcl/msgbox.hxx>
569 #include <svl/stritem.hxx>
570 
571 IMPL_LINK( SvxCharMapData, AssignHdl, PushButton *, EMPTYARG )
572 {
573 	SfxAllItemSet aSet( SfxObjectShell::Current()->GetPool() );
574 	aSet.Put( SfxStringItem( SID_CHARMAP, String::CreateFromAscii("test") ) );
575 	SfxModalDialog* pDlg = new SfxMacroAssignDlg( mpDialog, com::sun::star::uno::Reference < com::sun::star::frame::XFrame >(), aSet );
576 	if ( pDlg && pDlg->Execute() == RET_OK )
577 	{
578 		const SfxItemSet* pOutSet = pDlg->GetOutputItemSet();
579 		const SfxPoolItem* pItem;
580 		if( SFX_ITEM_SET == pOutSet->GetItemState( SID_CHARMAP, sal_False, &pItem ) )
581 		{
582 			// show assigned shortcut
583 		}
584 	}
585 
586 	delete pDlg;
587 
588     return 0;
589 }
590