/************************************************************** * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * *************************************************************/ // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_cui.hxx" // include --------------------------------------------------------------- #include #define _CUI_CHARMAP_CXX_ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "cuicharmap.hxx" #include #include #include #include #include "charmap.hrc" #include "macroass.hxx" // class SvxCharacterMap ================================================= SvxCharacterMap::SvxCharacterMap( Window* pParent, sal_Bool bOne, const SfxItemSet* pSet ) : SfxModalDialog( pParent, CUI_RES( RID_SVXDLG_CHARMAP ) ), mpCharMapData( 0 ) { SFX_ITEMSET_ARG( pSet, pItem, SfxBoolItem, FN_PARAM_1 ); if ( pItem ) bOne = pItem->GetValue(); mpCharMapData = new SvxCharMapData( this, bOne, &CUI_MGR() ); SFX_ITEMSET_ARG( pSet, pCharItem, SfxInt32Item, SID_ATTR_CHAR ); if ( pCharItem ) SetChar( pCharItem->GetValue() ); SFX_ITEMSET_ARG( pSet, pDisableItem, SfxBoolItem, FN_PARAM_2 ); if ( pDisableItem && pDisableItem->GetValue() ) DisableFontSelection(); SFX_ITEMSET_ARG( pSet, pFontItem, SvxFontItem, SID_ATTR_CHAR_FONT ); SFX_ITEMSET_ARG( pSet, pFontNameItem, SfxStringItem, SID_FONT_NAME ); if ( pFontItem ) { Font aFont( pFontItem->GetFamilyName(), pFontItem->GetStyleName(), GetCharFont().GetSize() ); aFont.SetCharSet( pFontItem->GetCharSet() ); aFont.SetPitch( pFontItem->GetPitch() ); SetCharFont( aFont ); } else if ( pFontNameItem ) { Font aFont( GetCharFont() ); aFont.SetName( pFontNameItem->GetValue() ); SetCharFont( aFont ); } FreeResource(); CreateOutputItemSet( pSet ? *pSet->GetPool() : SFX_APP()->GetPool() ); } // ----------------------------------------------------------------------- SvxCharacterMap::~SvxCharacterMap() { delete mpCharMapData; } // ----------------------------------------------------------------------- const Font& SvxCharacterMap::GetCharFont() const { return mpCharMapData->aFont; } // ----------------------------------------------------------------------- void SvxCharacterMap::SetChar( sal_UCS4 c ) { mpCharMapData->aShowSet.SelectCharacter( c ); } // ----------------------------------------------------------------------- sal_UCS4 SvxCharacterMap::GetChar() const { return mpCharMapData->aShowSet.GetSelectCharacter(); } // ----------------------------------------------------------------------- String SvxCharacterMap::GetCharacters() const { return mpCharMapData->aShowText.GetText(); } // ----------------------------------------------------------------------- void SvxCharacterMap::DisableFontSelection() { mpCharMapData->aFontText.Disable(); mpCharMapData->aFontLB.Disable(); } void SvxCharacterMap::SetCharFont( const Font& rFont ) { mpCharMapData->SetCharFont( rFont ); } short SvxCharacterMap::Execute() { short nResult = SfxModalDialog::Execute(); if ( nResult == RET_OK ) { SfxItemSet* pSet = GetItemSet(); if ( pSet ) { const SfxItemPool* pPool = pSet->GetPool(); const Font& rFont( GetCharFont() ); pSet->Put( SfxStringItem( pPool->GetWhich(SID_CHARMAP), GetCharacters() ) ); pSet->Put( SvxFontItem( rFont.GetFamily(), rFont.GetName(), rFont.GetStyleName(), rFont.GetPitch(), rFont.GetCharSet(), pPool->GetWhich(SID_ATTR_CHAR_FONT) ) ); pSet->Put( SfxStringItem( pPool->GetWhich(SID_FONT_NAME), rFont.GetName() ) ); pSet->Put( SfxInt32Item( pPool->GetWhich(SID_ATTR_CHAR), GetChar() ) ); } } return nResult; } // class SvxShowText ===================================================== SvxShowText::SvxShowText( Window* pParent, const ResId& rResId, sal_Bool bCenter ) : Control( pParent, rResId ), mbCenter( bCenter) {} // ----------------------------------------------------------------------- void SvxShowText::Paint( const Rectangle& ) { Color aTextCol = GetTextColor(); const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings(); const Color aWindowTextColor( rStyleSettings.GetDialogTextColor() ); SetTextColor( aWindowTextColor ); const String aText = GetText(); const Size aSize = GetOutputSizePixel(); Point aPoint( 2, mnY ); // adjust position using ink boundary if possible Rectangle aBoundRect; if( !GetTextBoundRect( aBoundRect, aText ) || aBoundRect.IsEmpty() ) aPoint.X() = (aSize.Width() - GetTextWidth( aText )) / 2; else { // adjust position before it gets out of bounds aBoundRect += aPoint; // shift back vertically if needed int nYLDelta = aBoundRect.Top(); int nYHDelta = aSize.Height() - aBoundRect.Bottom(); if( nYLDelta <= 0 ) aPoint.Y() -= nYLDelta - 1; else if( nYHDelta <= 0 ) aPoint.Y() += nYHDelta - 1; if( mbCenter ) { // move glyph to middle of cell aPoint.X() = -aBoundRect.Left() + (aSize.Width() - aBoundRect.GetWidth()) / 2; } else { // shift back horizontally if needed int nXLDelta = aBoundRect.Left(); int nXHDelta = aSize.Width() - aBoundRect.Right(); if( nXLDelta <= 0 ) aPoint.X() -= nXLDelta - 1; else if( nXHDelta <= 0 ) aPoint.X() += nXHDelta - 1; } } DrawText( aPoint, aText ); SetTextColor( aTextCol ); } // ----------------------------------------------------------------------- void SvxShowText::SetFont( const Font& rFont ) { long nWinHeight = GetOutputSizePixel().Height(); Font aFont = rFont; aFont.SetWeight( WEIGHT_NORMAL ); aFont.SetAlign( ALIGN_TOP ); aFont.SetSize( PixelToLogic( Size( 0, nWinHeight/2 ) ) ); aFont.SetTransparent( sal_True ); Control::SetFont( aFont ); mnY = ( nWinHeight - GetTextHeight() ) / 2; Invalidate(); } // ----------------------------------------------------------------------- void SvxShowText::SetText( const String& rText ) { Control::SetText( rText ); Invalidate(); } // ----------------------------------------------------------------------- SvxShowText::~SvxShowText() {} // class SvxCharacterMap ================================================= SvxCharMapData::SvxCharMapData( SfxModalDialog* pDialog, sal_Bool bOne_, ResMgr* pResContext ) : mpDialog( pDialog ), aFontText ( pDialog, ResId( FT_FONT, *pResContext ) ), aFontLB ( pDialog, ResId( LB_FONT, *pResContext ) ), aSubsetText ( pDialog, ResId( FT_SUBSET, *pResContext ) ), aSubsetLB ( pDialog, ResId( LB_SUBSET, *pResContext ) ), aShowSet ( pDialog, ResId( CT_SHOWSET, *pResContext ) ), aSymbolText ( pDialog, ResId( FT_SYMBOLE, *pResContext ) ), aShowText ( pDialog, ResId( CT_SHOWTEXT, *pResContext ) ), // aShowShortcut ( pDialog, ResId( CT_ASSIGN, *pResContext ) ), aOKBtn ( pDialog, ResId( BTN_CHAR_OK, *pResContext ) ), aCancelBtn ( pDialog, ResId( BTN_CHAR_CANCEL, *pResContext ) ), aHelpBtn ( pDialog, ResId( BTN_CHAR_HELP, *pResContext ) ), aDeleteBtn ( pDialog, ResId( BTN_DELETE, *pResContext ) ), // aAssignBtn ( pDialog, ResId( BT_ASSIGN, *pResContext ) ), aShowChar ( pDialog, ResId( CT_SHOWCHAR, *pResContext ), sal_True ), aCharCodeText ( pDialog, ResId( FT_CHARCODE, *pResContext ) ), // aAssignText ( pDialog, ResId( FT_ASSIGN, *pResContext ) ), bOne( bOne_ ), pSubsetMap( NULL ) { aFont = pDialog->GetFont(); aFont.SetTransparent( sal_True ); aFont.SetFamily( FAMILY_DONTKNOW ); aFont.SetPitch( PITCH_DONTKNOW ); aFont.SetCharSet( RTL_TEXTENCODING_DONTKNOW ); if ( bOne ) { Size aDlgSize = pDialog->GetSizePixel(); pDialog->SetSizePixel( Size( aDlgSize.Width(), aDlgSize.Height()-aShowText.GetSizePixel().Height() ) ); aSymbolText.Hide(); aShowText.Hide(); aDeleteBtn.Hide(); } String aDefStr( aFont.GetName() ); String aLastName; int nCount = mpDialog->GetDevFontCount(); for ( int i = 0; i < nCount; i++ ) { String aFontName( mpDialog->GetDevFont( i ).GetName() ); if ( aFontName != aLastName ) { aLastName = aFontName; sal_uInt16 nPos = aFontLB.InsertEntry( aFontName ); aFontLB.SetEntryData( nPos, (void*)(sal_uLong)i ); } } // the font may not be in the list => // try to find a font name token in list and select found font, // else select topmost entry bool bFound = (aFontLB.GetEntryPos( aDefStr ) == LISTBOX_ENTRY_NOTFOUND ); if( !bFound ) { for ( xub_StrLen i = 0; i < aDefStr.GetTokenCount(); ++i ) { String aToken = aDefStr.GetToken(i); if ( aFontLB.GetEntryPos( aToken ) != LISTBOX_ENTRY_NOTFOUND ) { aDefStr = aToken; bFound = true; break; } } } if ( bFound ) aFontLB.SelectEntry( aDefStr ); else if ( aFontLB.GetEntryCount() ) aFontLB.SelectEntryPos(0); FontSelectHdl( &aFontLB ); aOKBtn.SetClickHdl( LINK( this, SvxCharMapData, OKHdl ) ); aFontLB.SetSelectHdl( LINK( this, SvxCharMapData, FontSelectHdl ) ); aSubsetLB.SetSelectHdl( LINK( this, SvxCharMapData, SubsetSelectHdl ) ); aShowSet.SetDoubleClickHdl( LINK( this, SvxCharMapData, CharDoubleClickHdl ) ); aShowSet.SetSelectHdl( LINK( this, SvxCharMapData, CharSelectHdl ) ); aShowSet.SetHighlightHdl( LINK( this, SvxCharMapData, CharHighlightHdl ) ); aShowSet.SetPreSelectHdl( LINK( this, SvxCharMapData, CharPreSelectHdl ) ); aDeleteBtn.SetClickHdl( LINK( this, SvxCharMapData, DeleteHdl ) ); // aAssignBtn.SetClickHdl( LINK( this, SvxCharMapData, AssignHdl ) ); if( SvxShowCharSet::getSelectedChar() == ' ') aOKBtn.Disable(); else aOKBtn.Enable(); // left align aShowText field int nLeftEdge = aSymbolText.GetPosPixel().X(); nLeftEdge += aSymbolText.GetTextWidth( aSymbolText.GetText() ); Size aNewSize = aShowText.GetOutputSizePixel(); aShowText.SetPosPixel( Point( nLeftEdge+4, aShowText.GetPosPixel().Y() ) ); } // ----------------------------------------------------------------------- void SvxCharMapData::SetCharFont( const Font& rFont ) { // first get the underlying info in order to get font names // like "Times New Roman;Times" resolved Font aTmp( mpDialog->GetFontMetric( rFont ) ); if ( aFontLB.GetEntryPos( aTmp.GetName() ) == LISTBOX_ENTRY_NOTFOUND ) return; aFontLB.SelectEntry( aTmp.GetName() ); aFont = aTmp; FontSelectHdl( &aFontLB ); // for compatibility reasons mpDialog->ModalDialog::SetFont( aFont ); } // ----------------------------------------------------------------------- IMPL_LINK( SvxCharMapData, OKHdl, OKButton *, EMPTYARG ) { String aStr = aShowText.GetText(); if ( !aStr.Len() ) { sal_UCS4 cChar = aShowSet.GetSelectCharacter(); // using the new UCS4 constructor rtl::OUString aOUStr( &cChar, 1 ); aShowText.SetText( aOUStr ); } mpDialog->EndDialog( sal_True ); return 0; } // ----------------------------------------------------------------------- IMPL_LINK( SvxCharMapData, FontSelectHdl, ListBox *, EMPTYARG ) { sal_uInt16 nPos = aFontLB.GetSelectEntryPos(), nFont = (sal_uInt16)(sal_uLong)aFontLB.GetEntryData( nPos ); aFont = mpDialog->GetDevFont( nFont ); aFont.SetWeight( WEIGHT_DONTKNOW ); aFont.SetItalic( ITALIC_NONE ); aFont.SetWidthType( WIDTH_DONTKNOW ); aFont.SetPitch( PITCH_DONTKNOW ); aFont.SetFamily( FAMILY_DONTKNOW ); // notify children using this font aShowSet.SetFont( aFont ); aShowChar.SetFont( aFont ); aShowText.SetFont( aFont ); // right align some fields to aShowSet int nRightEdge = aShowSet.GetPosPixel().X() + aShowSet.GetOutputSizePixel().Width(); Size aNewSize = aSubsetLB.GetOutputSizePixel(); aNewSize.setWidth( nRightEdge - aSubsetLB.GetPosPixel().X() ); aSubsetLB.SetOutputSizePixel( aNewSize ); // setup unicode subset listbar with font specific subsets, // hide unicode subset listbar for symbol fonts // TODO: get info from the Font once it provides it if( pSubsetMap) delete pSubsetMap; pSubsetMap = NULL; sal_Bool bNeedSubset = (aFont.GetCharSet() != RTL_TEXTENCODING_SYMBOL); if( bNeedSubset ) { FontCharMap aFontCharMap; aShowSet.GetFontCharMap( aFontCharMap ); pSubsetMap = new SubsetMap( &aFontCharMap ); // update subset listbox for new font's unicode subsets aSubsetLB.Clear(); // TODO: is it worth to improve the stupid linear search? bool bFirst = true; const Subset* s; while( NULL != (s = pSubsetMap->GetNextSubset( bFirst )) ) { sal_uInt16 nPos_ = aSubsetLB.InsertEntry( s->GetName() ); aSubsetLB.SetEntryData( nPos_, (void*)s ); // NOTE: subset must live at least as long as the selected font if( bFirst ) aSubsetLB.SelectEntryPos( nPos_ ); bFirst = false; } if( aSubsetLB.GetEntryCount() <= 1 ) bNeedSubset = sal_False; } aSubsetText.Show( bNeedSubset); aSubsetLB.Show( bNeedSubset); return 0; } // ----------------------------------------------------------------------- IMPL_LINK( SvxCharMapData, SubsetSelectHdl, ListBox *, EMPTYARG ) { sal_uInt16 nPos = aSubsetLB.GetSelectEntryPos(); const Subset* pSubset = reinterpret_cast (aSubsetLB.GetEntryData(nPos)); if( pSubset ) { sal_UCS4 cFirst = pSubset->GetRangeMin(); aShowSet.SelectCharacter( cFirst ); } aSubsetLB.SelectEntryPos( nPos ); return 0; } // ----------------------------------------------------------------------- IMPL_LINK( SvxCharMapData, CharDoubleClickHdl, Control *, EMPTYARG ) { mpDialog->EndDialog( sal_True ); return 0; } // ----------------------------------------------------------------------- IMPL_LINK( SvxCharMapData, CharSelectHdl, Control *, EMPTYARG ) { if ( !bOne ) { String aText = aShowText.GetText(); if ( aText.Len() == CHARMAP_MAXLEN ) Sound::Beep( SOUND_WARNING ); else { sal_UCS4 cChar = aShowSet.GetSelectCharacter(); // using the new UCS4 constructor rtl::OUString aOUStr( &cChar, 1 ); aShowText.SetText( aText + aOUStr ); } } aOKBtn.Enable(); return 0; } // ----------------------------------------------------------------------- IMPL_LINK( SvxCharMapData, CharHighlightHdl, Control *, EMPTYARG ) { String aText; sal_UCS4 cChar = aShowSet.GetSelectCharacter(); sal_Bool bSelect = (cChar > 0); // show char sample if ( bSelect ) { // using the new UCS4 constructor aText = rtl::OUString( &cChar, 1 ); const Subset* pSubset = NULL; if( pSubsetMap ) pSubset = pSubsetMap->GetSubsetByUnicode( cChar ); if( pSubset ) aSubsetLB.SelectEntry( pSubset->GetName() ); else aSubsetLB.SetNoSelection(); } aShowChar.SetText( aText ); aShowChar.Update(); // show char code if ( bSelect ) { char aBuf[32]; snprintf( aBuf, sizeof(aBuf), "U+%04X", static_cast(cChar) ); if( cChar < 0x0100 ) snprintf( aBuf+6, sizeof(aBuf)-6, " (%u)", static_cast(cChar) ); aText = String::CreateFromAscii( aBuf ); } aCharCodeText.SetText( aText ); return 0; } // ----------------------------------------------------------------------- IMPL_LINK( SvxCharMapData, CharPreSelectHdl, Control *, EMPTYARG ) { // adjust subset selection if( pSubsetMap ) { sal_UCS4 cChar = aShowSet.GetSelectCharacter(); const Subset* pSubset = pSubsetMap->GetSubsetByUnicode( cChar ); if( pSubset ) aSubsetLB.SelectEntry( pSubset->GetName() ); } aOKBtn.Enable(); return 0; } // ----------------------------------------------------------------------- IMPL_LINK( SvxCharMapData, DeleteHdl, PushButton *, EMPTYARG ) { aShowText.SetText( String() ); aOKBtn.Disable(); return 0; } #include #include #include IMPL_LINK( SvxCharMapData, AssignHdl, PushButton *, EMPTYARG ) { SfxAllItemSet aSet( SfxObjectShell::Current()->GetPool() ); aSet.Put( SfxStringItem( SID_CHARMAP, String::CreateFromAscii("test") ) ); SfxModalDialog* pDlg = new SfxMacroAssignDlg( mpDialog, com::sun::star::uno::Reference < com::sun::star::frame::XFrame >(), aSet ); if ( pDlg && pDlg->Execute() == RET_OK ) { const SfxItemSet* pOutSet = pDlg->GetOutputItemSet(); const SfxPoolItem* pItem; if( SFX_ITEM_SET == pOutSet->GetItemState( SID_CHARMAP, sal_False, &pItem ) ) { // show assigned shortcut } } delete pDlg; return 0; }