From 710a39414569995bd5a8631a948c939dc73bcef9 Mon Sep 17 00:00:00 2001 From: Akshay Deep Date: Thu, 11 May 2017 13:27:38 +0530 Subject: GSoC: Glyph View and Recent Characters Control in Special Characters dialog Change-Id: Ia55f3fefe7c14327cff2e996ab0038dc52f9b017 Reviewed-on: https://gerrit.libreoffice.org/37496 Reviewed-by: Samuel Mehrbrodt Tested-by: Samuel Mehrbrodt --- cui/source/dialogs/charwin.cxx | 213 ++++++++++++++++ cui/source/dialogs/cuicharmap.cxx | 504 +++++++++++++++++++++++--------------- cui/source/factory/init.cxx | 5 +- cui/source/inc/charwin.hxx | 56 +++++ cui/source/inc/cuicharmap.hxx | 22 +- 5 files changed, 598 insertions(+), 202 deletions(-) create mode 100644 cui/source/dialogs/charwin.cxx create mode 100644 cui/source/inc/charwin.hxx (limited to 'cui/source') diff --git a/cui/source/dialogs/charwin.cxx b/cui/source/dialogs/charwin.cxx new file mode 100644 index 000000000000..5f9a7fa49765 --- /dev/null +++ b/cui/source/dialogs/charwin.cxx @@ -0,0 +1,213 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * 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 . + */ + +#include +#include +#include "charwin.hxx" +#include +#include +#include +#include "cuicharmap.hxx" +#include "macroass.hxx" + +using namespace com::sun::star; + + +SvxCharView::SvxCharView(vcl::Window* pParent) + : Control(pParent, WB_TABSTOP | WB_BORDER) + , mnY(0) +{ +} + +VCL_BUILDER_FACTORY(SvxCharView) + +void SvxCharView::MouseButtonDown( const MouseEvent& rMEvt ) +{ + if ( rMEvt.IsLeft() ) + { + maMouseClickHdl.Call(this); + if ( !(rMEvt.GetClicks() % 2) ) + { + InsertCharToDoc(); + } + } + + Control::MouseButtonDown(rMEvt); +} + +void SvxCharView::KeyInput( const KeyEvent& rKEvt ) +{ + vcl::KeyCode aCode = rKEvt.GetKeyCode(); + + switch (aCode.GetCode()) + { + case KEY_SPACE: + case KEY_RETURN: + InsertCharToDoc(); + break; + } + Control::KeyInput(rKEvt); +} + +void SvxCharView::InsertCharToDoc() +{ + if(GetText().isEmpty()) + return; + + uno::Reference< uno::XComponentContext > xContext( comphelper::getProcessComponentContext() ); + + uno::Sequence aArgs(2); + aArgs[0].Name = OUString::fromUtf8("Symbols"); + aArgs[0].Value <<= GetText(); + + aArgs[1].Name = OUString::fromUtf8("FontName"); + aArgs[1].Value <<= maFont.GetFamilyName(); + + comphelper::dispatchCommand(".uno:InsertSymbol", aArgs); +} + +void SvxCharView::Paint(vcl::RenderContext& rRenderContext, const ::tools::Rectangle&) +{ + rRenderContext.SetFont(maFont); + + const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings(); + const Color aWindowTextColor(rStyleSettings.GetFieldTextColor()); + Color aHighlightColor(rStyleSettings.GetHighlightColor()); + Color aHighlightTextColor(rStyleSettings.GetHighlightTextColor()); + Color aLightColor(rStyleSettings.GetLightColor()); + + const OUString aText = GetText(); + const Size aSize(GetOutputSizePixel()); + + long nAvailWidth = aSize.Width(); + long nWinHeight = GetOutputSizePixel().Height(); + + bool bGotBoundary = true; + bool bShrankFont = false; + vcl::Font aOrigFont(rRenderContext.GetFont()); + Size aFontSize(aOrigFont.GetFontSize()); + ::tools::Rectangle aBoundRect; + + for (long nFontHeight = aFontSize.Height(); nFontHeight > 0; nFontHeight -= 1) + { + if (!rRenderContext.GetTextBoundRect( aBoundRect, aText ) || aBoundRect.IsEmpty()) + { + bGotBoundary = false; + break; + } + + //only shrink in the single glyph large view mode + long nTextWidth = aBoundRect.GetWidth(); + if (nAvailWidth > nTextWidth) + break; + vcl::Font aFont(aOrigFont); + aFontSize.Height() = nFontHeight; + aFont.SetFontSize(aFontSize); + rRenderContext.SetFont(aFont); + mnY = (nWinHeight - GetTextHeight()) / 2; + bShrankFont = true; + } + + Point aPoint(2, mnY); + + if (!bGotBoundary) + aPoint.X() = (aSize.Width() - rRenderContext.GetTextWidth(aText)) / 2; + else + { + // adjust position + aBoundRect += aPoint; + + // vertical adjustment + 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; + + // centrally align glyph + aPoint.X() = -aBoundRect.Left() + (aSize.Width() - aBoundRect.GetWidth()) / 2; + } + + if (HasFocus()) + { + rRenderContext.SetFillColor(aHighlightColor); + rRenderContext.DrawRect(tools::Rectangle(Point(0, 0), Size(GetOutputSizePixel().Width(), GetOutputSizePixel().Height()))); + + rRenderContext.SetTextColor(aHighlightTextColor); + rRenderContext.DrawText(aPoint, aText); + } + else + { + rRenderContext.SetFillColor(aLightColor); + rRenderContext.DrawRect(tools::Rectangle(Point(0, 0), Size(GetOutputSizePixel().Width(), GetOutputSizePixel().Height()))); + + rRenderContext.SetTextColor(aWindowTextColor); + rRenderContext.DrawText(aPoint, aText); + } + + if (bShrankFont) + rRenderContext.SetFont(aOrigFont); +} + +void SvxCharView::setInsertCharHdl(const Link &rLink) +{ + maInsertCharHdl = rLink; +} + +void SvxCharView::setMouseClickHdl(const Link &rLink) +{ + maMouseClickHdl = rLink; +} + +void SvxCharView::SetFont( const vcl::Font& rFont ) +{ + long nWinHeight = GetOutputSizePixel().Height(); + maFont = vcl::Font(rFont); + maFont.SetWeight(WEIGHT_NORMAL); + maFont.SetAlignment(ALIGN_TOP); + maFont.SetFontSize(PixelToLogic(Size(0, nWinHeight / 2))); + maFont.SetTransparent(true); + Control::SetFont(maFont); + + mnY = (nWinHeight - GetTextHeight()) / 2; + + Invalidate(); +} + +Size SvxCharView::GetOptimalSize() const +{ + const vcl::Font &rFont = GetFont(); + const Size rFontSize = rFont.GetFontSize(); + long nWinHeight = LogicToPixel(rFontSize).Height() * 2; + return Size( GetTextWidth( GetText() ) + 2 * 12, nWinHeight ); +} + +void SvxCharView::Resize() +{ + Control::Resize(); + SetFont(GetFont()); +} + + +void SvxCharView::SetText( const OUString& rText ) +{ + Control::SetText( rText ); + Invalidate(); +} diff --git a/cui/source/dialogs/cuicharmap.cxx b/cui/source/dialogs/cuicharmap.cxx index 8d1180a9e9b3..59c9225a3e42 100644 --- a/cui/source/dialogs/cuicharmap.cxx +++ b/cui/source/dialogs/cuicharmap.cxx @@ -33,6 +33,11 @@ #include #include #include +#include +#include +#include +#include +#include #include #include @@ -43,18 +48,19 @@ #include #include "macroass.hxx" +using namespace css; + // class SvxCharacterMap ================================================= SvxCharacterMap::SvxCharacterMap( vcl::Window* pParent, bool bOne_, const SfxItemSet* pSet ) : SfxModalDialog(pParent, "SpecialCharactersDialog", "cui/ui/specialcharacters.ui") , bOne( bOne_ ) , pSubsetMap( nullptr ) + , mxContext(comphelper::getProcessComponentContext()) { get(m_pShowSet, "showcharset"); get(m_pShowChar, "showchar"); m_pShowChar->SetCentered(true); - get(m_pShowText, "showtext"); - m_pShowText->SetMaxTextLen(CHARMAP_MAXLEN); get(m_pOKBtn, "ok"); get(m_pFontText, "fontft"); get(m_pFontLB, "fontlb"); @@ -68,7 +74,23 @@ SvxCharacterMap::SvxCharacterMap( vcl::Window* pParent, bool bOne_, const SfxIte get(m_pDecimalCodeText, "decimalvalue"); //lock the size request of this widget to the width of the original .ui string m_pHexCodeText->set_width_request(m_pHexCodeText->get_preferred_size().Width()); - get(m_pSymbolText, "symboltext"); + + get( m_pRecentCharView[0], "viewchar1" ); + get( m_pRecentCharView[1], "viewchar2" ); + get( m_pRecentCharView[2], "viewchar3" ); + get( m_pRecentCharView[3], "viewchar4" ); + get( m_pRecentCharView[4], "viewchar5" ); + get( m_pRecentCharView[5], "viewchar6" ); + get( m_pRecentCharView[6], "viewchar7" ); + get( m_pRecentCharView[7], "viewchar8" ); + get( m_pRecentCharView[8], "viewchar9" ); + get( m_pRecentCharView[9], "viewchar10" ); + get( m_pRecentCharView[10], "viewchar11" ); + get( m_pRecentCharView[11], "viewchar12" ); + get( m_pRecentCharView[12], "viewchar13" ); + get( m_pRecentCharView[13], "viewchar14" ); + get( m_pRecentCharView[14], "viewchar15" ); + get( m_pRecentCharView[15], "viewchar16" ); const SfxBoolItem* pItem = SfxItemSet::GetItem(pSet, FN_PARAM_1, false); if ( pItem ) @@ -108,19 +130,42 @@ SvxCharacterMap::~SvxCharacterMap() disposeOnce(); } +short SvxCharacterMap::Execute() +{ + if( SvxShowCharSet::getSelectedChar() == ' ') + { + m_pOKBtn->Disable(); + } + else + { + sal_UCS4 cChar = m_pShowSet->GetSelectCharacter(); + // using the new UCS4 constructor + OUString aOUStr( &cChar, 1 ); + m_pShowChar->SetText(aOUStr); + m_pOKBtn->Enable(); + } + + return ModalDialog::Execute(); +} + void SvxCharacterMap::dispose() { + for(int i = 0; i < 16; i++) + m_pRecentCharView[i].clear(); + m_pShowSet.clear(); - m_pShowText.clear(); m_pOKBtn.clear(); m_pFontText.clear(); m_pFontLB.clear(); m_pSubsetText.clear(); m_pSubsetLB.clear(); - m_pSymbolText.clear(); m_pShowChar.clear(); m_pHexCodeText.clear(); m_pDecimalCodeText.clear(); + + maRecentCharList.clear(); + maRecentCharFontList.clear(); + SfxModalDialog::dispose(); } @@ -137,172 +182,94 @@ sal_UCS4 SvxCharacterMap::GetChar() const } -OUString SvxCharacterMap::GetCharacters() const -{ - return m_pShowText->GetText(); -} - - void SvxCharacterMap::DisableFontSelection() { m_pFontText->Disable(); m_pFontLB->Disable(); } -short SvxCharacterMap::Execute() + +void SvxCharacterMap::getRecentCharacterList() { - short nResult = SfxModalDialog::Execute(); - if ( nResult == RET_OK ) + //retrieve recent character list + css::uno::Sequence< OUString > rRecentCharList( officecfg::Office::Common::RecentCharacters::RecentCharacterList::get() ); + for (int i = 0; i < rRecentCharList.getLength(); ++i) { - SfxItemSet* pSet = GetItemSet(); - if ( pSet ) - { - const SfxItemPool* pPool = pSet->GetPool(); - const vcl::Font& rFont( GetCharFont() ); - pSet->Put( SfxStringItem( pPool->GetWhich(SID_CHARMAP), GetCharacters() ) ); - pSet->Put( SvxFontItem( rFont.GetFamilyType(), rFont.GetFamilyName(), - rFont.GetStyleName(), rFont.GetPitch(), rFont.GetCharSet(), pPool->GetWhich(SID_ATTR_CHAR_FONT) ) ); - pSet->Put( SfxStringItem( pPool->GetWhich(SID_FONT_NAME), rFont.GetFamilyName() ) ); - pSet->Put( SfxInt32Item( pPool->GetWhich(SID_ATTR_CHAR), GetChar() ) ); - } + maRecentCharList.push_back(rRecentCharList[i]); } - return nResult; + //retrieve recent character font list + css::uno::Sequence< OUString > rRecentCharFontList( officecfg::Office::Common::RecentCharacters::RecentCharacterFontList::get() ); + for (int i = 0; i < rRecentCharFontList.getLength(); ++i) + { + maRecentCharFontList.push_back(rRecentCharFontList[i]); + } } - -// class SvxShowText ===================================================== - -SvxShowText::SvxShowText(vcl::Window* pParent) - : Control(pParent) - , mnY(0) - , mbCenter(false) -{} - -VCL_BUILDER_FACTORY(SvxShowText) - -void SvxShowText::Paint(vcl::RenderContext& rRenderContext, const ::tools::Rectangle&) +void SvxCharacterMap::updateRecentCharControl() { - rRenderContext.SetFont(maFont); - - Color aTextCol = rRenderContext.GetTextColor(); - - const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings(); - const Color aWindowTextColor(rStyleSettings.GetDialogTextColor()); - rRenderContext.SetTextColor(aWindowTextColor); - - const OUString aText = GetText(); - const Size aSize(GetOutputSizePixel()); - - long nAvailWidth = aSize.Width(); - long nWinHeight = GetOutputSizePixel().Height(); - - bool bGotBoundary = true; - bool bShrankFont = false; - vcl::Font aOrigFont(rRenderContext.GetFont()); - Size aFontSize(aOrigFont.GetFontSize()); - ::tools::Rectangle aBoundRect; - - for (long nFontHeight = aFontSize.Height(); nFontHeight > 0; nFontHeight -= 5) + int i = 0; + for ( std::deque< OUString >::iterator it = maRecentCharList.begin(), it2 = maRecentCharFontList.begin(); + it != maRecentCharList.end() || it2 != maRecentCharFontList.end(); + ++it, ++it2, i++) { - if (!rRenderContext.GetTextBoundRect( aBoundRect, aText ) || aBoundRect.IsEmpty()) - { - bGotBoundary = false; - break; - } - if (!mbCenter) - break; - //only shrink in the single glyph large view mode - long nTextWidth = aBoundRect.GetWidth(); - if (nAvailWidth > nTextWidth) - break; - vcl::Font aFont(aOrigFont); - aFontSize.Height() = nFontHeight; - aFont.SetFontSize(aFontSize); - rRenderContext.SetFont(aFont); - mnY = (nWinHeight - GetTextHeight()) / 2; - bShrankFont = true; + m_pRecentCharView[i]->SetText(*it); + vcl::Font rFont = m_pRecentCharView[i]->GetControlFont(); + rFont.SetFamilyName( *it2 ); + m_pRecentCharView[i]->SetFont(rFont); + m_pRecentCharView[i]->Show(); } - Point aPoint(2, mnY); - // adjust position using ink boundary if possible - if (!bGotBoundary) - aPoint.X() = (aSize.Width() - rRenderContext.GetTextWidth(aText)) / 2; - else + for(; i < 16 ; i++) { - // 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; - } + m_pRecentCharView[i]->SetText(OUString()); + m_pRecentCharView[i]->Hide(); } - - rRenderContext.DrawText(aPoint, aText); - rRenderContext.SetTextColor(aTextCol); - if (bShrankFont) - rRenderContext.SetFont(aOrigFont); } - -void SvxShowText::SetFont( const vcl::Font& rFont ) +void SvxCharacterMap::updateRecentCharacterList(const OUString& sTitle, const OUString& rFont) { - long nWinHeight = GetOutputSizePixel().Height(); - maFont = vcl::Font(rFont); - maFont.SetWeight(WEIGHT_NORMAL); - maFont.SetAlignment(ALIGN_TOP); - maFont.SetFontSize(PixelToLogic(Size(0, nWinHeight / 2))); - maFont.SetTransparent(true); - Control::SetFont(maFont); + auto itChar = std::find_if(maRecentCharList.begin(), + maRecentCharList.end(), + [sTitle] (const OUString & a) { return a == sTitle; }); - mnY = (nWinHeight - GetTextHeight()) / 2; + auto itChar2 = std::find_if(maRecentCharFontList.begin(), + maRecentCharFontList.end(), + [rFont] (const OUString & a) { return a == rFont; }); - Invalidate(); -} + // if recent char to be added is already in list, remove it + if( itChar != maRecentCharList.end() && itChar2 != maRecentCharFontList.end() ) + { + maRecentCharList.erase( itChar ); + maRecentCharFontList.erase( itChar2); + } -Size SvxShowText::GetOptimalSize() const -{ - const vcl::Font &rFont = GetFont(); - const Size rFontSize = rFont.GetFontSize(); - long nWinHeight = LogicToPixel(rFontSize).Height() * 2; - return Size( GetTextWidth( GetText() ) + 2 * 12, nWinHeight ); -} + if (maRecentCharList.size() == 16) + { + maRecentCharList.pop_back(); + maRecentCharFontList.pop_back(); + } -void SvxShowText::Resize() -{ - Control::Resize(); - SetFont(GetFont()); //force recalculation of size -} + maRecentCharList.push_front(sTitle); + maRecentCharFontList.push_front(rFont); + css::uno::Sequence< OUString > aRecentCharList(maRecentCharList.size()); + css::uno::Sequence< OUString > aRecentCharFontList(maRecentCharFontList.size()); -void SvxShowText::SetText( const OUString& rText ) -{ - Control::SetText( rText ); - Invalidate(); -} + for (size_t i = 0; i < maRecentCharList.size(); ++i) + { + aRecentCharList[i] = maRecentCharList[i]; + aRecentCharFontList[i] = maRecentCharFontList[i]; + } + std::shared_ptr batch(comphelper::ConfigurationChanges::create(mxContext)); + officecfg::Office::Common::RecentCharacters::RecentCharacterList::set(aRecentCharList, batch); + officecfg::Office::Common::RecentCharacters::RecentCharacterFontList::set(aRecentCharFontList, batch); + batch->commit(); + + updateRecentCharControl(); +} -// class SvxCharacterMap ================================================= void SvxCharacterMap::init() { @@ -312,12 +279,6 @@ void SvxCharacterMap::init() aFont.SetPitch( PITCH_DONTKNOW ); aFont.SetCharSet( RTL_TEXTENCODING_DONTKNOW ); - if (bOne) - { - m_pSymbolText->Hide(); - m_pShowText->Hide(); - } - OUString aDefStr( aFont.GetFamilyName() ); OUString aLastName; int nCount = GetDevFontCount(); @@ -357,9 +318,9 @@ void SvxCharacterMap::init() m_pFontLB->SelectEntryPos(0); FontSelectHdl(*m_pFontLB); - m_pOKBtn->SetClickHdl( LINK( this, SvxCharacterMap, OKHdl ) ); m_pFontLB->SetSelectHdl( LINK( this, SvxCharacterMap, FontSelectHdl ) ); m_pSubsetLB->SetSelectHdl( LINK( this, SvxCharacterMap, SubsetSelectHdl ) ); + m_pOKBtn->SetClickHdl( LINK( this, SvxCharacterMap, InsertClickHdl ) ); m_pShowSet->SetDoubleClickHdl( LINK( this, SvxCharacterMap, CharDoubleClickHdl ) ); m_pShowSet->SetSelectHdl( LINK( this, SvxCharacterMap, CharSelectHdl ) ); m_pShowSet->SetHighlightHdl( LINK( this, SvxCharacterMap, CharHighlightHdl ) ); @@ -368,9 +329,26 @@ void SvxCharacterMap::init() m_pHexCodeText->SetModifyHdl( LINK( this, SvxCharacterMap, HexCodeChangeHdl ) ); if( SvxShowCharSet::getSelectedChar() == ' ') + { m_pOKBtn->Disable(); + } else + { + sal_UCS4 cChar = m_pShowSet->GetSelectCharacter(); + // using the new UCS4 constructor + OUString aOUStr( &cChar, 1 ); + m_pShowChar->SetText(aOUStr); m_pOKBtn->Enable(); + } + + getRecentCharacterList(); + updateRecentCharControl(); + + for(int i = 0; i < 16; i++) + { + m_pRecentCharView[i]->setMouseClickHdl(LINK(this,SvxCharacterMap, RecentClickHdl)); + m_pRecentCharView[i]->SetLoseFocusHdl(LINK(this,SvxCharacterMap, LoseFocusHdl)); + } } @@ -399,20 +377,6 @@ void SvxCharacterMap::SetCharFont( const vcl::Font& rFont ) } -IMPL_LINK_NOARG(SvxCharacterMap, OKHdl, Button*, void) -{ - OUString aStr = m_pShowText->GetText(); - - if ( aStr.isEmpty() ) - { - sal_UCS4 cChar = m_pShowSet->GetSelectCharacter(); - // using the new UCS4 constructor - OUString aOUStr( &cChar, 1 ); - m_pShowText->SetText( aOUStr ); - } - EndDialog( RET_OK ); -} - void SvxCharacterMap::fillAllSubsets(ListBox &rListBox) { SubsetMap aAll(nullptr); @@ -426,6 +390,25 @@ void SvxCharacterMap::fillAllSubsets(ListBox &rListBox) } +void SvxCharacterMap::insertCharToDoc(const OUString& sGlyph) +{ + if(sGlyph.isEmpty()) + return; + + uno::Reference< uno::XComponentContext > xContext( comphelper::getProcessComponentContext() ); + + uno::Sequence aArgs(2); + aArgs[0].Name = OUString::fromUtf8("Symbols"); + aArgs[0].Value <<= sGlyph; + + aArgs[1].Name = OUString::fromUtf8("FontName"); + aArgs[1].Value <<= aFont.GetFamilyName(); + comphelper::dispatchCommand(".uno:InsertSymbol", aArgs); + + updateRecentCharacterList(sGlyph, aFont.GetFamilyName()); +} + + IMPL_LINK_NOARG(SvxCharacterMap, FontSelectHdl, ListBox&, void) { const sal_Int32 nPos = m_pFontLB->GetSelectEntryPos(); @@ -440,7 +423,6 @@ IMPL_LINK_NOARG(SvxCharacterMap, FontSelectHdl, ListBox&, void) // notify children using this font m_pShowSet->SetFont( aFont ); m_pShowChar->SetFont( aFont ); - m_pShowText->SetControlFont( aFont ); // setup unicode subset listbar with font specific subsets, // hide unicode subset listbar for symbol fonts @@ -490,46 +472,39 @@ IMPL_LINK_NOARG(SvxCharacterMap, SubsetSelectHdl, ListBox&, void) m_pSubsetLB->SelectEntryPos( nPos ); } +IMPL_LINK(SvxCharacterMap, RecentClickHdl, SvxCharView*, rView, void) +{ + m_pShowChar->SetText( rView->GetText() ); + m_pShowChar->SetFont(rView->GetFont()); + m_pShowChar->Update(); + rView->GrabFocus(); + rView->Invalidate(); + m_pOKBtn->Enable(); +} IMPL_LINK_NOARG(SvxCharacterMap, CharDoubleClickHdl, SvxShowCharSet*, void) { - if (bOne) - { - sal_UCS4 cChar = m_pShowSet->GetSelectCharacter(); - m_pShowText->SetText(OUString(&cChar, 1)); - } - EndDialog( RET_OK ); + sal_UCS4 cChar = m_pShowSet->GetSelectCharacter(); + // using the new UCS4 constructor + OUString aOUStr( &cChar, 1 ); + insertCharToDoc(aOUStr); } - IMPL_LINK_NOARG(SvxCharacterMap, CharSelectHdl, SvxShowCharSet*, void) { - if ( !bOne ) - { - OUString aText = m_pShowText->GetText(); - Selection aSelection = m_pShowText->GetSelection(); - aSelection.Justify(); - long nLen = aSelection.Len(); - - if ( aText.getLength() != CHARMAP_MAXLEN || nLen > 0 ) - { - sal_UCS4 cChar = m_pShowSet->GetSelectCharacter(); - // using the new UCS4 constructor - OUString aOUStr( &cChar, 1 ); + m_pOKBtn->Enable(); +} - long nPos = aSelection.Min(); - if( aText.getLength() ) - { - m_pShowText->SetText( aText.copy( 0, nPos ) + aOUStr + aText.copy( nPos + nLen ) ); - } - else - m_pShowText->SetText( aOUStr ); +IMPL_LINK_NOARG(SvxCharacterMap, InsertClickHdl, Button*, void) +{ + insertCharToDoc(m_pShowChar->GetText()); + EndDialog(RET_OK); +} - m_pShowText->SetSelection(Selection(nPos + aOUStr.getLength())); - } - } - m_pOKBtn->Enable(); +IMPL_STATIC_LINK(SvxCharacterMap, LoseFocusHdl, Control&, pItem, void) +{ + pItem.Invalidate(); } @@ -555,8 +530,13 @@ IMPL_LINK_NOARG(SvxCharacterMap, CharHighlightHdl, SvxShowCharSet*, void) else m_pSubsetLB->SetNoSelection(); } - m_pShowChar->SetText( aText ); - m_pShowChar->Update(); + + if(m_pShowSet->HasFocus()) + { + m_pShowChar->SetText( aText ); + m_pShowChar->SetFont( aFont ); + m_pShowChar->Update(); + } // show char codes if ( bSelect ) @@ -624,4 +604,136 @@ IMPL_LINK_NOARG(SvxCharacterMap, CharPreSelectHdl, SvxShowCharSet*, void) m_pOKBtn->Enable(); } + +// class SvxShowText ===================================================== + +SvxShowText::SvxShowText(vcl::Window* pParent) + : Control(pParent) + , mnY(0) + , mbCenter(false) +{} + +VCL_BUILDER_FACTORY(SvxShowText) + +void SvxShowText::Paint(vcl::RenderContext& rRenderContext, const ::tools::Rectangle&) +{ + rRenderContext.SetFont(maFont); + + Color aTextCol = rRenderContext.GetTextColor(); + + const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings(); + const Color aWindowTextColor(rStyleSettings.GetDialogTextColor()); + rRenderContext.SetTextColor(aWindowTextColor); + + const OUString aText = GetText(); + const Size aSize(GetOutputSizePixel()); + + long nAvailWidth = aSize.Width(); + long nWinHeight = GetOutputSizePixel().Height(); + + bool bGotBoundary = true; + bool bShrankFont = false; + vcl::Font aOrigFont(rRenderContext.GetFont()); + Size aFontSize(aOrigFont.GetFontSize()); + ::tools::Rectangle aBoundRect; + + for (long nFontHeight = aFontSize.Height(); nFontHeight > 0; nFontHeight -= 5) + { + if (!rRenderContext.GetTextBoundRect( aBoundRect, aText ) || aBoundRect.IsEmpty()) + { + bGotBoundary = false; + break; + } + if (!mbCenter) + break; + //only shrink in the single glyph large view mode + long nTextWidth = aBoundRect.GetWidth(); + if (nAvailWidth > nTextWidth) + break; + vcl::Font aFont(aOrigFont); + aFontSize.Height() = nFontHeight; + aFont.SetFontSize(aFontSize); + rRenderContext.SetFont(aFont); + mnY = (nWinHeight - GetTextHeight()) / 2; + bShrankFont = true; + } + + Point aPoint(2, mnY); + // adjust position using ink boundary if possible + if (!bGotBoundary) + aPoint.X() = (aSize.Width() - rRenderContext.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; + } + } + + rRenderContext.DrawText(aPoint, aText); + rRenderContext.SetTextColor(aTextCol); + if (bShrankFont) + rRenderContext.SetFont(aOrigFont); +} + + +void SvxShowText::SetFont( const vcl::Font& rFont ) +{ + long nWinHeight = GetOutputSizePixel().Height(); + maFont = vcl::Font(rFont); + maFont.SetWeight(WEIGHT_NORMAL); + maFont.SetAlignment(ALIGN_TOP); + maFont.SetFontSize(PixelToLogic(Size(0, nWinHeight / 2))); + maFont.SetTransparent(true); + Control::SetFont(maFont); + + mnY = (nWinHeight - GetTextHeight()) / 2; + + Invalidate(); +} + +Size SvxShowText::GetOptimalSize() const +{ + const vcl::Font &rFont = GetFont(); + const Size rFontSize = rFont.GetFontSize(); + long nWinHeight = LogicToPixel(rFontSize).Height() * 2; + return Size( GetTextWidth( GetText() ) + 2 * 12, nWinHeight ); +} + +void SvxShowText::Resize() +{ + Control::Resize(); + SetFont(GetFont()); //force recalculation of size +} + + +void SvxShowText::SetText( const OUString& rText ) +{ + Control::SetText( rText ); + Invalidate(); +} + + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/factory/init.cxx b/cui/source/factory/init.cxx index fd7cbc63e50c..e23077a0342b 100644 --- a/cui/source/factory/init.cxx +++ b/cui/source/factory/init.cxx @@ -32,7 +32,10 @@ SAL_DLLPUBLIC_EXPORT bool GetSpecialCharsForEdit(vcl::Window* i_pParent, const v aDlg->SetCharFont(i_rFont); if ( aDlg->Execute() == RET_OK ) { - o_rResult = aDlg->GetCharacters(); + sal_UCS4 cChar = aDlg->GetChar(); + // using the new UCS4 constructor + OUString aOUStr( &cChar, 1 ); + o_rResult = aOUStr; bRet = true; } return bRet; diff --git a/cui/source/inc/charwin.hxx b/cui/source/inc/charwin.hxx new file mode 100644 index 000000000000..7feb06800fe5 --- /dev/null +++ b/cui/source/inc/charwin.hxx @@ -0,0 +1,56 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * 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 . + */ + +#ifndef INCLUDED_CUI_SOURCE_INC_CHARWIN_HXX +#define INCLUDED_CUI_SOURCE_INC_CHARWIN_HXX + +#include + +class SvxCharView : public Control +{ +public: + SvxCharView(vcl::Window* pParent); + + void SetFont( const vcl::Font& rFont ); + void SetText( const OUString& rText ) override; + void InsertCharToDoc(); + + virtual void Resize() override; + + virtual Size GetOptimalSize() const override; + + void setInsertCharHdl(const Link &rLink); + void setMouseClickHdl(const Link &rLink); + +protected: + virtual void Paint(vcl::RenderContext& rRenderContext, const ::tools::Rectangle&) override; + + virtual void MouseButtonDown( const MouseEvent& rMEvt ) override; + + virtual void KeyInput( const KeyEvent& rKEvt ) override; + +private: + long mnY; + vcl::Font maFont; + + Link maInsertCharHdl; + Link maMouseClickHdl; +}; + +#endif diff --git a/cui/source/inc/cuicharmap.hxx b/cui/source/inc/cuicharmap.hxx index 8d83798ecdbe..4f1a63f5ec71 100644 --- a/cui/source/inc/cuicharmap.hxx +++ b/cui/source/inc/cuicharmap.hxx @@ -26,7 +26,9 @@ #include #include #include +#include "charwin.hxx" +using namespace ::com::sun::star; class SubsetMap; #define CHARMAP_MAXLEN 32 @@ -68,22 +70,26 @@ private: void init(); VclPtr m_pShowSet; - VclPtr m_pShowText; VclPtr m_pOKBtn; VclPtr m_pFontText; VclPtr m_pFontLB; VclPtr m_pSubsetText; VclPtr m_pSubsetLB; - VclPtr m_pSymbolText; VclPtr m_pShowChar; VclPtr m_pHexCodeText; VclPtr m_pDecimalCodeText; + VclPtr m_pRecentCharView[16]; vcl::Font aFont; bool bOne; const SubsetMap* pSubsetMap; + + std::deque maRecentCharList; + std::deque maRecentCharFontList; + + uno::Reference< uno::XComponentContext > mxContext; + enum class Radix : sal_Int16 {decimal = 10, hexadecimal=16}; - DECL_LINK(OKHdl, Button*, void); DECL_LINK(FontSelectHdl, ListBox&, void); DECL_LINK(SubsetSelectHdl, ListBox&, void); DECL_LINK(CharDoubleClickHdl, SvxShowCharSet*,void); @@ -92,6 +98,9 @@ private: DECL_LINK(CharPreSelectHdl, SvxShowCharSet*, void); DECL_LINK(DecimalCodeChangeHdl, Edit&, void); DECL_LINK(HexCodeChangeHdl, Edit&, void); + DECL_LINK(RecentClickHdl, SvxCharView*, void); + DECL_LINK(InsertClickHdl, Button*, void); + DECL_STATIC_LINK(SvxCharacterMap, LoseFocusHdl, Control&, void); static void fillAllSubsets(ListBox &rListBox); void selectCharByCode(Radix radix); @@ -99,6 +108,7 @@ private: public: SvxCharacterMap( vcl::Window* pParent, bool bOne=true, const SfxItemSet* pSet=nullptr ); virtual ~SvxCharacterMap() override; + virtual short Execute() override; virtual void dispose() override; void DisableFontSelection(); @@ -109,9 +119,11 @@ public: void SetChar( sal_UCS4 ); sal_UCS4 GetChar() const; - OUString GetCharacters() const; + void getRecentCharacterList(); //gets both recent char and recent char font list + void updateRecentCharacterList(const OUString& rChar, const OUString& rFont); - virtual short Execute() override; + void updateRecentCharControl(); + void insertCharToDoc(const OUString& sChar); }; #endif -- cgit v1.2.3