diff options
author | Caolán McNamara <caolanm@redhat.com> | 2019-06-14 21:56:44 +0100 |
---|---|---|
committer | Caolán McNamara <caolanm@redhat.com> | 2019-06-21 21:33:30 +0200 |
commit | 5261417cbb3051b812164838d19c0f748573df45 (patch) | |
tree | d159cce1d6903854fc13437c5cca5ce15e48281f | |
parent | fda464112540011dd6e2bd267720d2800af3a5f2 (diff) |
weld SpellDialog
a) use EditEngine instead of TextEngine as the former can be hosted in a
foreign widget
b) use a SfxGrabBagItem to hold the custom spellchecking info inside the
EditEngine
c) in longer paragraphs the current word is now auto-scrolled into view
d) rename Invalidate to InvalidateDialog
Change-Id: Ic6db019c32cdfd5f354c58ee7394fdaa040b86e1
Reviewed-on: https://gerrit.libreoffice.org/74119
Tested-by: Jenkins
Reviewed-by: Caolán McNamara <caolanm@redhat.com>
Tested-by: Caolán McNamara <caolanm@redhat.com>
34 files changed, 1369 insertions, 1127 deletions
diff --git a/cui/Library_cui.mk b/cui/Library_cui.mk index b02520529fab..e3cd0c36ba4f 100644 --- a/cui/Library_cui.mk +++ b/cui/Library_cui.mk @@ -135,7 +135,6 @@ $(eval $(call gb_Library_add_exception_objects,cui,\ cui/source/dialogs/SignSignatureLineDialog \ cui/source/dialogs/sdrcelldlg \ cui/source/dialogs/showcols \ - cui/source/dialogs/SpellAttrib \ cui/source/dialogs/SpellDialog \ cui/source/dialogs/splitcelldlg \ cui/source/dialogs/srchxtra \ diff --git a/cui/source/dialogs/SpellAttrib.cxx b/cui/source/dialogs/SpellAttrib.cxx deleted file mode 100644 index 9d761a55b3f1..000000000000 --- a/cui/source/dialogs/SpellAttrib.cxx +++ /dev/null @@ -1,105 +0,0 @@ -/* -*- 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 "SpellAttrib.hxx" -#include <vcl/font.hxx> - -using namespace svx; -using namespace com::sun::star::linguistic2; -using namespace com::sun::star::uno; - - -SpellErrorAttrib::SpellErrorAttrib( const SpellErrorDescription& rDesc ) : - TextAttrib(TEXTATTR_SPELL_ERROR), - m_aSpellErrorDescription( rDesc ) -{ -} - - -void SpellErrorAttrib::SetFont( vcl::Font& ) const -{ - //this attribute doesn't have a visual effect -} - - -std::unique_ptr<TextAttrib> SpellErrorAttrib::Clone() const -{ - return std::unique_ptr<TextAttrib>(new SpellErrorAttrib(*this)); -} - - -bool SpellErrorAttrib::operator==( const TextAttrib& rAttr ) const -{ - return Which() == rAttr.Which() && - m_aSpellErrorDescription == static_cast<const SpellErrorAttrib&>(rAttr).m_aSpellErrorDescription; -} - - -SpellLanguageAttrib::SpellLanguageAttrib(LanguageType eLang) : - TextAttrib(TEXTATTR_SPELL_LANGUAGE), - m_eLanguage(eLang) -{ -} - - -void SpellLanguageAttrib::SetFont( vcl::Font& ) const -{ - //no visual effect -} - - -std::unique_ptr<TextAttrib> SpellLanguageAttrib::Clone() const -{ - return std::unique_ptr<TextAttrib>(new SpellLanguageAttrib(*this)); -} - - -bool SpellLanguageAttrib::operator==( const TextAttrib& rAttr ) const -{ - return Which() == rAttr.Which() && - m_eLanguage == static_cast<const SpellLanguageAttrib&>(rAttr).m_eLanguage; -} - - -SpellBackgroundAttrib::SpellBackgroundAttrib(const Color& rCol) : - TextAttrib(TEXTATTR_SPELL_BACKGROUND), - m_aBackgroundColor(rCol) -{ -} - - -void SpellBackgroundAttrib::SetFont( vcl::Font& rFont ) const -{ - rFont.SetFillColor(m_aBackgroundColor); -} - - -std::unique_ptr<TextAttrib> SpellBackgroundAttrib::Clone() const -{ - return std::unique_ptr<TextAttrib>(new SpellBackgroundAttrib(*this)); -} - - -bool SpellBackgroundAttrib::operator==( const TextAttrib& rAttr ) const -{ - return Which() == rAttr.Which() && - m_aBackgroundColor == static_cast<const SpellBackgroundAttrib&>(rAttr).m_aBackgroundColor; -} - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/dialogs/SpellAttrib.hxx b/cui/source/dialogs/SpellAttrib.hxx index 2a458166b42d..a106bce963b6 100644 --- a/cui/source/dialogs/SpellAttrib.hxx +++ b/cui/source/dialogs/SpellAttrib.hxx @@ -19,7 +19,6 @@ #ifndef INCLUDED_CUI_SOURCE_DIALOGS_SPELLATTRIB_HXX #define INCLUDED_CUI_SOURCE_DIALOGS_SPELLATTRIB_HXX -#include <vcl/txtattr.hxx> #include <i18nlangtag/lang.h> #include <com/sun/star/uno/Reference.h> #include <com/sun/star/uno/Sequence.h> @@ -27,10 +26,6 @@ #include <com/sun/star/linguistic2/XProofreader.hpp> #include <tools/color.hxx> -#define TEXTATTR_SPELL_ERROR (TEXTATTR_USER_START + 1) -#define TEXTATTR_SPELL_LANGUAGE (TEXTATTR_USER_START + 2) -#define TEXTATTR_SPELL_BACKGROUND (TEXTATTR_USER_START + 3) - namespace svx{ struct SpellErrorDescription { @@ -61,16 +56,21 @@ struct SpellErrorDescription aLocale( rLocale ), xGrammarChecker( rxGrammarChecker ), aSuggestions( rSuggestions ) - { - if( pDialogTitle ) - sDialogTitle = *pDialogTitle; - if( pExplanation ) - sExplanation = *pExplanation; - if( pExplanationURL ) - sExplanationURL = *pExplanationURL; - if( pRuleId ) - sRuleId = *pRuleId; - }; + { + if( pDialogTitle ) + sDialogTitle = *pDialogTitle; + if( pExplanation ) + sExplanation = *pExplanation; + if( pExplanationURL ) + sExplanationURL = *pExplanationURL; + if( pRuleId ) + sRuleId = *pRuleId; + }; + + SpellErrorDescription() + : bIsGrammarError(false) + { + } bool operator==( const SpellErrorDescription& rDesc ) const { @@ -86,54 +86,36 @@ struct SpellErrorDescription sExplanationURL == rDesc.sExplanationURL && sRuleId == rDesc.sRuleId; } -}; - - -class SpellErrorAttrib : public TextAttrib -{ -public: - -private: - SpellErrorDescription m_aSpellErrorDescription; - -public: - SpellErrorAttrib( const SpellErrorDescription& ); - - const SpellErrorDescription& GetErrorDescription() const { return m_aSpellErrorDescription; } - - - virtual void SetFont( vcl::Font& rFont ) const override; - virtual std::unique_ptr<TextAttrib> Clone() const override; - virtual bool operator==( const TextAttrib& rAttr ) const override; -}; + css::uno::Sequence<css::uno::Any> toSequence() const + { + css::uno::Sequence<css::uno::Any> aEntries(9); + aEntries[0] <<= bIsGrammarError; + aEntries[1] <<= sErrorText; + aEntries[2] <<= sDialogTitle; + aEntries[3] <<= sExplanation; + aEntries[4] <<= sExplanationURL; + aEntries[5] <<= aLocale; + aEntries[6] <<= xGrammarChecker; + aEntries[7] <<= aSuggestions; + aEntries[8] <<= sRuleId; + return aEntries; + } -class SpellLanguageAttrib : public TextAttrib -{ - LanguageType m_eLanguage; - -public: - SpellLanguageAttrib(LanguageType eLanguage); - - LanguageType GetLanguage() const {return m_eLanguage;} - - virtual void SetFont( vcl::Font& rFont ) const override; - virtual std::unique_ptr<TextAttrib> Clone() const override; - virtual bool operator==( const TextAttrib& rAttr ) const override; + void fromSequence(const css::uno::Sequence<css::uno::Any>& rEntries) + { + rEntries[0] >>= bIsGrammarError; + rEntries[1] >>= sErrorText; + rEntries[2] >>= sDialogTitle; + rEntries[3] >>= sExplanation; + rEntries[4] >>= sExplanationURL; + rEntries[5] >>= aLocale; + rEntries[6] >>= xGrammarChecker; + rEntries[7] >>= aSuggestions; + rEntries[8] >>= sRuleId; + } }; - -class SpellBackgroundAttrib : public TextAttrib -{ - Color m_aBackgroundColor; - -public: - SpellBackgroundAttrib(const Color& rCol); - - virtual void SetFont( vcl::Font& rFont ) const override; - virtual std::unique_ptr<TextAttrib> Clone() const override; - virtual bool operator==( const TextAttrib& rAttr ) const override; -}; }//namespace svx #endif diff --git a/cui/source/dialogs/SpellDialog.cxx b/cui/source/dialogs/SpellDialog.cxx index 0757d011c536..6d77aebe8d07 100644 --- a/cui/source/dialogs/SpellDialog.cxx +++ b/cui/source/dialogs/SpellDialog.cxx @@ -18,25 +18,20 @@ */ #include <memory> -#include <vcl/event.hxx> -#include <vcl/weld.hxx> -#include <vcl/wrkwin.hxx> -#include <vcl/menu.hxx> -#include <vcl/scrbar.hxx> -#include <vcl/settings.hxx> -#include <vcl/svapp.hxx> #include "SpellAttrib.hxx" #include <sfx2/dispatch.hxx> #include <sfx2/bindings.hxx> #include <sfx2/sfxsids.hrc> #include <sfx2/viewfrm.hxx> +#include <svl/grabbagitem.hxx> #include <svl/undo.hxx> #include <unotools/lingucfg.hxx> -#include <vcl/textdata.hxx> -#include <vcl/textview.hxx> -#include <vcl/graphicfilter.hxx> -#include <editeng/unolingu.hxx> +#include <editeng/colritem.hxx> +#include <editeng/eeitem.hxx> +#include <editeng/langitem.hxx> #include <editeng/splwrap.hxx> +#include <editeng/unolingu.hxx> +#include <editeng/wghtitem.hxx> #include <linguistic/lngprops.hxx> #include <linguistic/misc.hxx> #include <com/sun/star/lang/XMultiServiceFactory.hpp> @@ -48,8 +43,15 @@ #include <com/sun/star/linguistic2/XSearchableDictionaryList.hpp> #include <com/sun/star/linguistic2/XSpellChecker1.hpp> #include <sfx2/app.hxx> -#include <vcl/help.hxx> +#include <vcl/cursor.hxx> +#include <vcl/event.hxx> #include <vcl/graph.hxx> +#include <vcl/help.hxx> +#include <vcl/graphicfilter.hxx> +#include <vcl/ptrstyle.hxx> +#include <vcl/settings.hxx> +#include <vcl/svapp.hxx> +#include <vcl/weld.hxx> #include <osl/file.hxx> #include <editeng/optitems.hxx> #include <editeng/svxenum.hxx> @@ -165,81 +167,73 @@ sal_uInt16 SpellUndoAction_Impl::GetId()const // class SvxSpellCheckDialog --------------------------------------------- SpellDialog::SpellDialog(SpellDialogChildWindow* pChildWindow, - vcl::Window * pParent, SfxBindings* _pBindings) - : SfxModelessDialog (_pBindings, pChildWindow, - pParent, "SpellingDialog", "cui/ui/spellingdialog.ui") + weld::Window * pParent, SfxBindings* _pBindings) + : SfxModelessDialogController (_pBindings, pChildWindow, + pParent, "cui/ui/spellingdialog.ui", "SpellingDialog") , aDialogUndoLink(LINK (this, SpellDialog, DialogUndoHdl)) , bFocusLocked(true) , rParent(*pChildWindow) , pImpl( new SpellDialog_Impl ) -{ - m_sTitleSpellingGrammar = GetText(); - m_sTitleSpelling = get<FixedText>("alttitleft")->GetText(); + , m_xAltTitle(m_xBuilder->weld_label("alttitleft")) + , m_xResumeFT(m_xBuilder->weld_label("resumeft")) + , m_xNoSuggestionsFT(m_xBuilder->weld_label("nosuggestionsft")) + , m_xLanguageFT(m_xBuilder->weld_label("languageft")) + , m_xLanguageLB(new LanguageBox(m_xBuilder->weld_combo_box("languagelb"))) + , m_xExplainFT(m_xBuilder->weld_label("explain")) + , m_xExplainLink(m_xBuilder->weld_link_button("explainlink")) + , m_xNotInDictFT(m_xBuilder->weld_label("notindictft")) + , m_xSentenceED(new SentenceEditWindow_Impl) + , m_xSuggestionFT(m_xBuilder->weld_label("suggestionsft")) + , m_xSuggestionLB(m_xBuilder->weld_tree_view("suggestionslb")) + , m_xIgnorePB(m_xBuilder->weld_button("ignore")) + , m_xIgnoreAllPB(m_xBuilder->weld_button("ignoreall")) + , m_xIgnoreRulePB(m_xBuilder->weld_button("ignorerule")) + , m_xAddToDictPB(m_xBuilder->weld_button("add")) + , m_xAddToDictMB(m_xBuilder->weld_menu_button("addmb")) + , m_xChangePB(m_xBuilder->weld_button("change")) + , m_xChangeAllPB(m_xBuilder->weld_button("changeall")) + , m_xAutoCorrPB(m_xBuilder->weld_button("autocorrect")) + , m_xCheckGrammarCB(m_xBuilder->weld_check_button("checkgrammar")) + , m_xOptionsPB(m_xBuilder->weld_button("options")) + , m_xUndoPB(m_xBuilder->weld_button("undo")) + , m_xClosePB(m_xBuilder->weld_button("close")) + , m_xToolbar(m_xBuilder->weld_toolbar("toolbar")) + , m_xSentenceEDWeld(new weld::CustomWeld(*m_xBuilder, "sentence", *m_xSentenceED)) +{ + m_xSentenceED->SetSpellDialog(this); + m_xSentenceED->Init(m_xToolbar.get()); + + m_sTitleSpellingGrammar = m_xDialog->get_title(); + m_sTitleSpelling = m_xAltTitle->get_label(); // fdo#68794 set initial title for cases where no text has been processed // yet to show its language attributes OUString sTitle = rParent.HasGrammarChecking() ? m_sTitleSpellingGrammar : m_sTitleSpelling; - SetText(sTitle.replaceFirst("$LANGUAGE ($LOCATION)", "")); - - m_sResumeST = get<FixedText>("resumeft")->GetText(); - m_sNoSuggestionsST = get<FixedText>("nosuggestionsft")->GetText(); - - get(m_pLanguageFT, "languageft"); - get(m_pLanguageLB, "languagelb"); - get(m_pExplainFT, "explain"); - get(m_pExplainLink, "explainlink"); - get(m_pNotInDictFT, "notindictft"); - get(m_pSentenceED, "sentence"); - Size aEdSize(LogicToPixel(Size(197, 48), MapMode(MapUnit::MapAppFont))); - m_pSentenceED->set_width_request(aEdSize.Width()); - m_pSentenceED->set_height_request(aEdSize.Height()); - get(m_pSuggestionFT, "suggestionsft"); - get(m_pSuggestionLB, "suggestionslb"); - m_pSuggestionLB->SetDropDownLineCount(5); - m_pSuggestionLB->set_width_request(aEdSize.Width()); - get(m_pIgnorePB, "ignore"); - m_sIgnoreOnceST = m_pIgnorePB->GetText(); - get(m_pIgnoreAllPB, "ignoreall"); - get(m_pIgnoreRulePB, "ignorerule"); - get(m_pAddToDictPB, "add"); - get(m_pAddToDictMB, "addmb"); - m_pAddToDictMB->SetHelpId(m_pAddToDictPB->GetHelpId()); - get(m_pChangePB, "change"); - get(m_pChangeAllPB, "changeall"); - get(m_pAutoCorrPB, "autocorrect"); - get(m_pCheckGrammarCB, "checkgrammar"); - get(m_pOptionsPB, "options"); - get(m_pUndoPB, "undo"); - get(m_pClosePB, "close"); - get(m_pToolbar, "toolbar"); - m_pSentenceED->Init(m_pToolbar); - xSpell = LinguMgr::GetSpellChecker(); + m_xDialog->set_title(m_xDialog->strip_mnemonic(sTitle.replaceFirst("$LANGUAGE ($LOCATION)", ""))); - const StyleSettings& rSettings = GetSettings().GetStyleSettings(); - Color aCol = rSettings.GetHelpColor(); - Wallpaper aWall( aCol ); - m_pExplainLink->SetBackground( aWall ); - m_pExplainFT->SetBackground( aWall ); + m_sResumeST = m_xResumeFT->get_label(); + m_sNoSuggestionsST = m_xNoSuggestionsFT->strip_mnemonic(m_xNoSuggestionsFT->get_label()); + + Size aEdSize(m_xSuggestionLB->get_approximate_digit_width() * 60, + m_xSuggestionLB->get_height_rows(6)); + m_xSuggestionLB->set_size_request(aEdSize.Width(), -1); + m_sIgnoreOnceST = m_xIgnorePB->get_label(); + m_xAddToDictMB->set_help_id(m_xAddToDictPB->get_help_id()); + xSpell = LinguMgr::GetSpellChecker(); Init_Impl(); // disable controls if service is missing - Enable(xSpell.is()); + m_xDialog->set_sensitive(xSpell.is()); //InitHdl wants to use virtual methods, so it //can't be called during the ctor, so init //it on next event cycle post-ctor - Application::PostUserEvent( - LINK( this, SpellDialog, InitHdl ), nullptr, true ); + Application::PostUserEvent(LINK(this, SpellDialog, InitHdl)); } SpellDialog::~SpellDialog() { - disposeOnce(); -} - -void SpellDialog::dispose() -{ if (pImpl) { // save possibly modified user-dictionaries @@ -249,90 +243,69 @@ void SpellDialog::dispose() pImpl.reset(); } - m_pLanguageFT.clear(); - m_pLanguageLB.clear(); - m_pExplainFT.clear(); - m_pExplainLink.clear(); - m_pNotInDictFT.clear(); - m_pSentenceED.clear(); - m_pSuggestionFT.clear(); - m_pSuggestionLB.clear(); - m_pIgnorePB.clear(); - m_pIgnoreAllPB.clear(); - m_pIgnoreRulePB.clear(); - m_pAddToDictPB.clear(); - m_pAddToDictMB.clear(); - m_pChangePB.clear(); - m_pChangeAllPB.clear(); - m_pAutoCorrPB.clear(); - m_pCheckGrammarCB.clear(); - m_pOptionsPB.clear(); - m_pUndoPB.clear(); - m_pClosePB.clear(); - m_pToolbar.clear(); - SfxModelessDialog::dispose(); } void SpellDialog::Init_Impl() { // initialize handler - m_pClosePB->SetClickHdl(LINK( this, SpellDialog, CancelHdl ) ); - m_pChangePB->SetClickHdl(LINK( this, SpellDialog, ChangeHdl ) ); - m_pChangeAllPB->SetClickHdl(LINK( this, SpellDialog, ChangeAllHdl ) ); - m_pIgnorePB->SetClickHdl(LINK( this, SpellDialog, IgnoreHdl ) ); - m_pIgnoreAllPB->SetClickHdl(LINK( this, SpellDialog, IgnoreAllHdl ) ); - m_pIgnoreRulePB->SetClickHdl(LINK( this, SpellDialog, IgnoreAllHdl ) ); - m_pUndoPB->SetClickHdl(LINK( this, SpellDialog, UndoHdl ) ); + m_xClosePB->connect_clicked(LINK( this, SpellDialog, CancelHdl ) ); + m_xChangePB->connect_clicked(LINK( this, SpellDialog, ChangeHdl ) ); + m_xChangeAllPB->connect_clicked(LINK( this, SpellDialog, ChangeAllHdl ) ); + m_xIgnorePB->connect_clicked(LINK( this, SpellDialog, IgnoreHdl ) ); + m_xIgnoreAllPB->connect_clicked(LINK( this, SpellDialog, IgnoreAllHdl ) ); + m_xIgnoreRulePB->connect_clicked(LINK( this, SpellDialog, IgnoreAllHdl ) ); + m_xUndoPB->connect_clicked(LINK( this, SpellDialog, UndoHdl ) ); - m_pAutoCorrPB->SetClickHdl( LINK( this, SpellDialog, ExtClickHdl ) ); - m_pCheckGrammarCB->SetClickHdl( LINK( this, SpellDialog, CheckGrammarHdl )); - m_pOptionsPB->SetClickHdl( LINK( this, SpellDialog, ExtClickHdl ) ); + m_xAutoCorrPB->connect_clicked( LINK( this, SpellDialog, ExtClickHdl ) ); + m_xCheckGrammarCB->connect_clicked( LINK( this, SpellDialog, CheckGrammarHdl )); + m_xOptionsPB->connect_clicked( LINK( this, SpellDialog, ExtClickHdl ) ); - m_pSuggestionLB->SetDoubleClickHdl( LINK( this, SpellDialog, DoubleClickChangeHdl ) ); + m_xSuggestionLB->connect_row_activated( LINK( this, SpellDialog, DoubleClickChangeHdl ) ); - m_pSentenceED->SetModifyHdl(LINK ( this, SpellDialog, ModifyHdl) ); + m_xSentenceED->SetModifyHdl(LINK ( this, SpellDialog, ModifyHdl) ); - m_pAddToDictMB->SetSelectHdl(LINK ( this, SpellDialog, AddToDictSelectHdl ) ); - m_pAddToDictPB->SetClickHdl(LINK ( this, SpellDialog, AddToDictClickHdl ) ); + m_xAddToDictMB->connect_selected(LINK ( this, SpellDialog, AddToDictSelectHdl ) ); + m_xAddToDictPB->connect_clicked(LINK ( this, SpellDialog, AddToDictClickHdl ) ); - m_pLanguageLB->SetSelectHdl(LINK( this, SpellDialog, LanguageSelectHdl ) ); + m_xLanguageLB->connect_changed(LINK( this, SpellDialog, LanguageSelectHdl ) ); // initialize language ListBox - m_pLanguageLB->SetLanguageList( SvxLanguageListFlags::SPELL_USED, false, true ); + m_xLanguageLB->SetLanguageList(SvxLanguageListFlags::SPELL_USED, false, false, true); - m_pSentenceED->ClearModifyFlag(); + m_xSentenceED->ClearModifyFlag(); LinguMgr::GetChangeAllList()->clear(); } void SpellDialog::UpdateBoxes_Impl(bool bCallFromSelectHdl) { sal_Int32 i; - m_pSuggestionLB->Clear(); + m_xSuggestionLB->clear(); - const SpellErrorDescription* pSpellErrorDescription = m_pSentenceED->GetAlternatives(); + SpellErrorDescription aSpellErrorDescription; + bool bSpellErrorDescription = m_xSentenceED->GetAlternatives(aSpellErrorDescription); LanguageType nAltLanguage = LANGUAGE_NONE; Sequence< OUString > aNewWords; bool bIsGrammarError = false; - if( pSpellErrorDescription ) + if( bSpellErrorDescription ) { - nAltLanguage = LanguageTag::convertToLanguageType( pSpellErrorDescription->aLocale ); - aNewWords = pSpellErrorDescription->aSuggestions; - bIsGrammarError = pSpellErrorDescription->bIsGrammarError; - m_pExplainLink->SetURL( pSpellErrorDescription->sExplanationURL ); - m_pExplainFT->SetText( pSpellErrorDescription->sExplanation ); + nAltLanguage = LanguageTag::convertToLanguageType( aSpellErrorDescription.aLocale ); + aNewWords = aSpellErrorDescription.aSuggestions; + bIsGrammarError = aSpellErrorDescription.bIsGrammarError; + m_xExplainLink->set_uri( aSpellErrorDescription.sExplanationURL ); + m_xExplainFT->set_label( aSpellErrorDescription.sExplanation ); } - if( pSpellErrorDescription && !pSpellErrorDescription->sDialogTitle.isEmpty() ) + if( bSpellErrorDescription && !aSpellErrorDescription.sDialogTitle.isEmpty() ) { // use this function to apply the correct image to be used... SetTitle_Impl( nAltLanguage ); // then change the title to the one to be actually used - SetText( pSpellErrorDescription->sDialogTitle ); + m_xDialog->set_title(m_xDialog->strip_mnemonic(aSpellErrorDescription.sDialogTitle)); } else SetTitle_Impl( nAltLanguage ); if( !bCallFromSelectHdl ) - m_pLanguageLB->SelectLanguage( nAltLanguage ); + m_xLanguageLB->set_active_id( nAltLanguage ); int nDicts = InitUserDicts(); // enter alternatives @@ -341,76 +314,73 @@ void SpellDialog::UpdateBoxes_Impl(bool bCallFromSelectHdl) for ( i = 0; i < nSize; ++i ) { OUString aTmp( pNewWords[i] ); - if ( LISTBOX_ENTRY_NOTFOUND == m_pSuggestionLB->GetEntryPos( aTmp ) ) - { - m_pSuggestionLB->InsertEntry( aTmp ); - m_pSuggestionLB->SetEntryFlags(m_pSuggestionLB->GetEntryCount() - 1, ListBoxEntryFlags::MultiLine); - } + if (m_xSuggestionLB->find_text(aTmp) == -1) + m_xSuggestionLB->append_text(aTmp); } if(!nSize) - m_pSuggestionLB->InsertEntry(m_sNoSuggestionsST); - m_pAutoCorrPB->Enable( nSize > 0 ); + m_xSuggestionLB->append_text(m_sNoSuggestionsST); + m_xAutoCorrPB->set_sensitive( nSize > 0 ); - m_pSuggestionFT->Enable(nSize > 0); - m_pSuggestionLB->Enable(nSize > 0); + m_xSuggestionFT->set_sensitive(nSize > 0); + m_xSuggestionLB->set_sensitive(nSize > 0); if( nSize ) { - m_pSuggestionLB->SelectEntryPos(0); + m_xSuggestionLB->select(0); } - m_pChangePB->Enable( nSize > 0); - m_pChangeAllPB->Enable(nSize > 0); + m_xChangePB->set_sensitive( nSize > 0); + m_xChangeAllPB->set_sensitive(nSize > 0); bool bShowChangeAll = !bIsGrammarError; - m_pChangeAllPB->Show( bShowChangeAll ); - m_pExplainFT->Show( !bShowChangeAll ); - m_pLanguageLB->Enable( bShowChangeAll ); - m_pIgnoreAllPB->Show( bShowChangeAll ); - - m_pAddToDictMB->Show( bShowChangeAll && nDicts > 1); - m_pAddToDictPB->Show( bShowChangeAll && nDicts <= 1); - m_pIgnoreRulePB->Show( !bShowChangeAll ); - m_pIgnoreRulePB->Enable(pSpellErrorDescription && !pSpellErrorDescription->sRuleId.isEmpty()); - m_pAutoCorrPB->Show( bShowChangeAll && rParent.HasAutoCorrection() ); - - bool bOldShowGrammar = m_pCheckGrammarCB->IsVisible(); - bool bOldShowExplain = m_pExplainLink->IsVisible(); - - m_pCheckGrammarCB->Show(rParent.HasGrammarChecking()); - m_pExplainLink->Show(!m_pExplainLink->GetURL().isEmpty()); - if (m_pExplainFT->GetText().isEmpty()) + m_xChangeAllPB->set_visible( bShowChangeAll ); + m_xExplainFT->set_visible( !bShowChangeAll ); + m_xLanguageLB->set_sensitive( bShowChangeAll ); + m_xIgnoreAllPB->set_visible( bShowChangeAll ); + + m_xAddToDictMB->set_visible( bShowChangeAll && nDicts > 1); + m_xAddToDictPB->set_visible( bShowChangeAll && nDicts <= 1); + m_xIgnoreRulePB->set_visible( !bShowChangeAll ); + m_xIgnoreRulePB->set_sensitive(bSpellErrorDescription && !aSpellErrorDescription.sRuleId.isEmpty()); + m_xAutoCorrPB->set_visible( bShowChangeAll && rParent.HasAutoCorrection() ); + + bool bOldShowGrammar = m_xCheckGrammarCB->get_visible(); + bool bOldShowExplain = m_xExplainLink->get_visible(); + + m_xCheckGrammarCB->set_visible(rParent.HasGrammarChecking()); + m_xExplainLink->set_visible(!m_xExplainLink->get_uri().isEmpty()); + if (m_xExplainFT->get_label().isEmpty()) { - m_pExplainFT->Hide(); - m_pExplainLink->Hide(); + m_xExplainFT->hide(); + m_xExplainLink->hide(); } - if (bOldShowExplain != m_pExplainLink->IsVisible() || bOldShowGrammar != m_pCheckGrammarCB->IsVisible()) - setOptimalLayoutSize(); + if (bOldShowExplain != m_xExplainLink->get_visible() || bOldShowGrammar != m_xCheckGrammarCB->get_visible()) + m_xDialog->resize_to_request(); } - void SpellDialog::SpellContinue_Impl(bool bUseSavedSentence, bool bIgnoreCurrentError ) { //initially or after the last error of a sentence MarkNextError will fail //then GetNextSentence() has to be called followed again by MarkNextError() //MarkNextError is not initially called if the UndoEdit mode is active bool bNextSentence = false; - if((!m_pSentenceED->IsUndoEditMode() && m_pSentenceED->MarkNextError( bIgnoreCurrentError, xSpell )) || - ( bNextSentence = GetNextSentence_Impl(bUseSavedSentence, m_pSentenceED->IsUndoEditMode()) && m_pSentenceED->MarkNextError( false, xSpell ))) + if((!m_xSentenceED->IsUndoEditMode() && m_xSentenceED->MarkNextError( bIgnoreCurrentError, xSpell )) || + ( bNextSentence = GetNextSentence_Impl(bUseSavedSentence, m_xSentenceED->IsUndoEditMode()) && m_xSentenceED->MarkNextError( false, xSpell ))) { - const SpellErrorDescription* pSpellErrorDescription = m_pSentenceED->GetAlternatives(); - if( pSpellErrorDescription ) + SpellErrorDescription aSpellErrorDescription; + bool bSpellErrorDescription = m_xSentenceED->GetAlternatives(aSpellErrorDescription); + if (bSpellErrorDescription) { UpdateBoxes_Impl(); - Control* aControls[] = + weld::Widget* aControls[] = { - m_pNotInDictFT, - m_pSentenceED, - m_pLanguageFT, + m_xNotInDictFT.get(), + m_xSentenceED->GetDrawingArea(), + m_xLanguageFT.get(), nullptr }; sal_Int32 nIdx = 0; do { - aControls[nIdx]->Enable(); + aControls[nIdx]->set_sensitive(true); } while(aControls[++nIdx]); @@ -418,8 +388,8 @@ void SpellDialog::SpellContinue_Impl(bool bUseSavedSentence, bool bIgnoreCurrent if( bNextSentence ) { //remove undo if a new sentence is active - m_pSentenceED->ResetUndo(); - m_pUndoPB->Enable(false); + m_xSentenceED->ResetUndo(); + m_xUndoPB->set_sensitive(false); } } } @@ -428,12 +398,12 @@ void SpellDialog::SpellContinue_Impl(bool bUseSavedSentence, bool bIgnoreCurrent */ IMPL_LINK_NOARG( SpellDialog, InitHdl, void*, void) { - SetUpdateMode( false ); + m_xDialog->freeze(); //show or hide AutoCorrect depending on the modules abilities - m_pAutoCorrPB->Show(rParent.HasAutoCorrection()); + m_xAutoCorrPB->set_visible(rParent.HasAutoCorrection()); SpellContinue_Impl(); - m_pSentenceED->ResetUndo(); - m_pUndoPB->Enable(false); + m_xSentenceED->ResetUndo(); + m_xUndoPB->set_sensitive(false); // get current language UpdateBoxes_Impl(); @@ -442,41 +412,40 @@ IMPL_LINK_NOARG( SpellDialog, InitHdl, void*, void) InitUserDicts(); LockFocusChanges(true); - if( m_pChangePB->IsEnabled() ) - m_pChangePB->GrabFocus(); - else if( m_pIgnorePB->IsEnabled() ) - m_pIgnorePB->GrabFocus(); - else if( m_pClosePB->IsEnabled() ) - m_pClosePB->GrabFocus(); + if( m_xChangePB->get_sensitive() ) + m_xChangePB->grab_focus(); + else if( m_xIgnorePB->get_sensitive() ) + m_xIgnorePB->grab_focus(); + else if( m_xClosePB->get_sensitive() ) + m_xClosePB->grab_focus(); LockFocusChanges(false); //show grammar CheckBox depending on the modules abilities - m_pCheckGrammarCB->Check( rParent.IsGrammarChecking() ); - SetUpdateMode( true ); - Show(); + m_xCheckGrammarCB->set_active(rParent.IsGrammarChecking()); + m_xDialog->thaw(); }; - -IMPL_LINK( SpellDialog, ExtClickHdl, Button *, pBtn, void ) +IMPL_LINK( SpellDialog, ExtClickHdl, weld::Button&, rBtn, void ) { - if (m_pOptionsPB == pBtn) + if (m_xOptionsPB.get() == &rBtn) StartSpellOptDlg_Impl(); - else if (m_pAutoCorrPB == pBtn) + else if (m_xAutoCorrPB.get() == &rBtn) { //get the currently selected wrong word - OUString sCurrentErrorText = m_pSentenceED->GetErrorText(); + OUString sCurrentErrorText = m_xSentenceED->GetErrorText(); //get the wrong word from the XSpellAlternative - const SpellErrorDescription* pSpellErrorDescription = m_pSentenceED->GetAlternatives(); - if( pSpellErrorDescription ) + SpellErrorDescription aSpellErrorDescription; + bool bSpellErrorDescription = m_xSentenceED->GetAlternatives(aSpellErrorDescription); + if (bSpellErrorDescription) { - OUString sWrong(pSpellErrorDescription->sErrorText); + OUString sWrong(aSpellErrorDescription.sErrorText); //if the word has not been edited in the MultiLineEdit then //the current suggestion should be used //if it's not the 'no suggestions' entry if(sWrong == sCurrentErrorText && - m_pSuggestionLB->IsEnabled() && m_pSuggestionLB->GetSelectedEntryCount() > 0 && - m_sNoSuggestionsST != m_pSuggestionLB->GetSelectedEntry()) + m_xSuggestionLB->get_sensitive() && m_xSuggestionLB->get_selected_index() != -1 && + m_sNoSuggestionsST != m_xSuggestionLB->get_selected_text()) { - sCurrentErrorText = m_pSuggestionLB->GetSelectedEntry(); + sCurrentErrorText = m_xSuggestionLB->get_selected_text(); } if(sWrong != sCurrentErrorText) { @@ -488,16 +457,16 @@ IMPL_LINK( SpellDialog, ExtClickHdl, Button *, pBtn, void ) } } -IMPL_LINK( SpellDialog, CheckGrammarHdl, Button*, pBox, void ) +IMPL_LINK_NOARG(SpellDialog, CheckGrammarHdl, weld::Button&, void) { - rParent.SetGrammarChecking( static_cast<CheckBox*>(pBox)->IsChecked() ); + rParent.SetGrammarChecking(m_xCheckGrammarCB->get_active()); Impl_Restore(true); } void SpellDialog::StartSpellOptDlg_Impl() { SfxItemSet aSet( SfxGetpApp()->GetPool(), svl::Items<SID_AUTOSPELL_CHECK,SID_AUTOSPELL_CHECK>{}); - SfxSingleTabDialogController aDlg(GetFrameWeld(), &aSet, "cui/ui/spelloptionsdialog.ui", "SpellOptionsDialog"); + SfxSingleTabDialogController aDlg(m_xDialog.get(), &aSet, "cui/ui/spelloptionsdialog.ui", "SpellOptionsDialog"); TabPageParent aParent(aDlg.get_content_area(), &aDlg); VclPtr<SfxTabPage> xPage = SvxLinguTabPage::Create(aParent, &aSet); @@ -530,54 +499,51 @@ namespace } } - OUString SpellDialog::getReplacementString() const { - OUString sOrigString = m_pSentenceED->GetErrorText(); + OUString sOrigString = m_xSentenceED->GetErrorText(); OUString sReplacement(sOrigString); - if(m_pSuggestionLB->IsEnabled() && - m_pSuggestionLB->GetSelectedEntryCount()>0 && - m_sNoSuggestionsST != m_pSuggestionLB->GetSelectedEntry()) - sReplacement = m_pSuggestionLB->GetSelectedEntry(); + if(m_xSuggestionLB->get_sensitive() && + m_xSuggestionLB->get_selected_index() != -1 && + m_sNoSuggestionsST != m_xSuggestionLB->get_selected_text()) + sReplacement = m_xSuggestionLB->get_selected_text(); return getDotReplacementString(sOrigString, sReplacement); } - -IMPL_LINK_NOARG(SpellDialog, DoubleClickChangeHdl, ListBox&, void) +IMPL_LINK_NOARG(SpellDialog, DoubleClickChangeHdl, weld::TreeView&, void) { - ChangeHdl(nullptr); + ChangeHdl(*m_xChangePB); } -IMPL_LINK_NOARG(SpellDialog, ChangeHdl, Button*, void) +IMPL_LINK_NOARG(SpellDialog, ChangeHdl, weld::Button&, void) { - if(m_pSentenceED->IsUndoEditMode()) + if (m_xSentenceED->IsUndoEditMode()) { SpellContinue_Impl(); } else { - m_pSentenceED->UndoActionStart( SPELLUNDO_CHANGE_GROUP ); + m_xSentenceED->UndoActionStart( SPELLUNDO_CHANGE_GROUP ); OUString aString = getReplacementString(); - m_pSentenceED->ChangeMarkedWord(aString, GetSelectedLang_Impl()); + m_xSentenceED->ChangeMarkedWord(aString, GetSelectedLang_Impl()); SpellContinue_Impl(); - m_pSentenceED->UndoActionEnd(); + m_xSentenceED->UndoActionEnd(); } - if(!m_pChangePB->IsEnabled()) - m_pIgnorePB->GrabFocus(); + if(!m_xChangePB->get_sensitive()) + m_xIgnorePB->grab_focus(); } - -IMPL_LINK_NOARG(SpellDialog, ChangeAllHdl, Button*, void) +IMPL_LINK_NOARG(SpellDialog, ChangeAllHdl, weld::Button&, void) { - m_pSentenceED->UndoActionStart( SPELLUNDO_CHANGE_GROUP ); + m_xSentenceED->UndoActionStart( SPELLUNDO_CHANGE_GROUP ); OUString aString = getReplacementString(); LanguageType eLang = GetSelectedLang_Impl(); // add new word to ChangeAll list - OUString aOldWord( m_pSentenceED->GetErrorText() ); + OUString aOldWord( m_xSentenceED->GetErrorText() ); SvxPrepareAutoCorrect( aOldWord, aString ); Reference<XDictionary> aXDictionary( LinguMgr::GetChangeAllList(), UNO_QUERY ); DictionaryError nAdded = AddEntryToDic( aXDictionary, @@ -590,31 +556,31 @@ IMPL_LINK_NOARG(SpellDialog, ChangeAllHdl, Button*, void) SPELLUNDO_CHANGE_ADD_TO_DICTIONARY, aDialogUndoLink)); pAction->SetDictionary(aXDictionary); pAction->SetAddedWord(aOldWord); - m_pSentenceED->AddUndoAction(std::move(pAction)); + m_xSentenceED->AddUndoAction(std::move(pAction)); } - m_pSentenceED->ChangeMarkedWord(aString, eLang); + m_xSentenceED->ChangeMarkedWord(aString, eLang); SpellContinue_Impl(); - m_pSentenceED->UndoActionEnd(); + m_xSentenceED->UndoActionEnd(); } - -IMPL_LINK( SpellDialog, IgnoreAllHdl, Button *, pButton, void ) +IMPL_LINK( SpellDialog, IgnoreAllHdl, weld::Button&, rButton, void ) { - m_pSentenceED->UndoActionStart( SPELLUNDO_CHANGE_GROUP ); + m_xSentenceED->UndoActionStart( SPELLUNDO_CHANGE_GROUP ); // add word to IgnoreAll list Reference< XDictionary > aXDictionary( LinguMgr::GetIgnoreAllList(), UNO_QUERY ); //in case the error has been changed manually it has to be restored - m_pSentenceED->RestoreCurrentError(); - if (pButton == m_pIgnoreRulePB) + m_xSentenceED->RestoreCurrentError(); + if (&rButton == m_xIgnoreRulePB.get()) { - const SpellErrorDescription* pSpellErrorDescription = m_pSentenceED->GetAlternatives(); + SpellErrorDescription aSpellErrorDescription; + bool bSpellErrorDescription = m_xSentenceED->GetAlternatives(aSpellErrorDescription); try { - if( pSpellErrorDescription && pSpellErrorDescription->xGrammarChecker.is() ) + if( bSpellErrorDescription && aSpellErrorDescription.xGrammarChecker.is() ) { - pSpellErrorDescription->xGrammarChecker->ignoreRule( pSpellErrorDescription->sRuleId, - pSpellErrorDescription->aLocale ); + aSpellErrorDescription.xGrammarChecker->ignoreRule(aSpellErrorDescription.sRuleId, + aSpellErrorDescription.aLocale); // refresh the layout (workaround to launch a dictionary event) aXDictionary->setActive(false); aXDictionary->setActive(true); @@ -626,30 +592,29 @@ IMPL_LINK( SpellDialog, IgnoreAllHdl, Button *, pButton, void ) } else { - OUString sErrorText(m_pSentenceED->GetErrorText()); + OUString sErrorText(m_xSentenceED->GetErrorText()); DictionaryError nAdded = AddEntryToDic( aXDictionary, sErrorText, false, OUString() ); - if(nAdded == DictionaryError::NONE) + if (nAdded == DictionaryError::NONE) { std::unique_ptr<SpellUndoAction_Impl> pAction(new SpellUndoAction_Impl( SPELLUNDO_CHANGE_ADD_TO_DICTIONARY, aDialogUndoLink)); pAction->SetDictionary(aXDictionary); pAction->SetAddedWord(sErrorText); - m_pSentenceED->AddUndoAction(std::move(pAction)); + m_xSentenceED->AddUndoAction(std::move(pAction)); } } SpellContinue_Impl(); - m_pSentenceED->UndoActionEnd(); + m_xSentenceED->UndoActionEnd(); } - -IMPL_LINK_NOARG(SpellDialog, UndoHdl, Button*, void) +IMPL_LINK_NOARG(SpellDialog, UndoHdl, weld::Button&, void) { - m_pSentenceED->Undo(); - if(!m_pSentenceED->GetUndoActionCount()) - m_pUndoPB->Enable(false); + m_xSentenceED->Undo(); + if(!m_xSentenceED->GetUndoActionCount()) + m_xUndoPB->set_sensitive(false); } @@ -660,14 +625,14 @@ IMPL_LINK( SpellDialog, DialogUndoHdl, SpellUndoAction_Impl&, rAction, void ) case SPELLUNDO_CHANGE_TEXTENGINE: { if(rAction.IsEnableChangePB()) - m_pChangePB->Enable(false); + m_xChangePB->set_sensitive(false); if(rAction.IsEnableChangeAllPB()) - m_pChangeAllPB->Enable(false); + m_xChangeAllPB->set_sensitive(false); } break; case SPELLUNDO_CHANGE_NEXTERROR: { - m_pSentenceED->MoveErrorMarkTo(static_cast<sal_Int32>(rAction.GetOldErrorStart()), + m_xSentenceED->MoveErrorMarkTo(static_cast<sal_Int32>(rAction.GetOldErrorStart()), static_cast<sal_Int32>(rAction.GetOldErrorEnd()), false); if(rAction.IsErrorLanguageSelected()) @@ -685,7 +650,7 @@ IMPL_LINK( SpellDialog, DialogUndoHdl, SpellUndoAction_Impl&, rAction, void ) case SPELLUNDO_MOVE_ERROREND : { if(rAction.GetOffset() != 0) - m_pSentenceED->MoveErrorEnd(rAction.GetOffset()); + m_xSentenceED->MoveErrorEnd(rAction.GetOffset()); } break; case SPELLUNDO_UNDO_EDIT_MODE : @@ -705,16 +670,16 @@ void SpellDialog::Impl_Restore(bool bUseSavedSentence) //clear the "ChangeAllList" LinguMgr::GetChangeAllList()->clear(); //get a new sentence - m_pSentenceED->SetText(OUString()); - m_pSentenceED->ResetModified(); + m_xSentenceED->SetText(OUString()); + m_xSentenceED->ResetModified(); //Resolves: fdo#39348 refill the dialog with the currently spelled sentence SpellContinue_Impl(bUseSavedSentence); - m_pIgnorePB->SetText(m_sIgnoreOnceST); + m_xIgnorePB->set_label(m_sIgnoreOnceST); } -IMPL_LINK_NOARG(SpellDialog, IgnoreHdl, Button*, void) +IMPL_LINK_NOARG(SpellDialog, IgnoreHdl, weld::Button&, void) { - if (m_sResumeST == m_pIgnorePB->GetText()) + if (m_sResumeST == m_xIgnorePB->get_label()) { Impl_Restore(false); } @@ -722,35 +687,35 @@ IMPL_LINK_NOARG(SpellDialog, IgnoreHdl, Button*, void) { //in case the error has been changed manually it has to be restored, // since the users choice now was to ignore the error - m_pSentenceED->RestoreCurrentError(); + m_xSentenceED->RestoreCurrentError(); // the word is being ignored SpellContinue_Impl( false, true ); } } - -bool SpellDialog::Close() +void SpellDialog::Close() { + if (IsClosing()) + return; + // We have to call ToggleChildWindow directly; calling SfxDispatcher's // Execute() does not work here when we are in a document with protected // section - in that case, the cursor can move from the editable field to // the protected area, and the slots get disabled because of // SfxDisableFlags::SwOnProtectedCursor (see FN_SPELL_GRAMMAR_DIALOG in .sdi). - SfxViewFrame::Current()->ToggleChildWindow(rParent.GetType()); - - return true; + SfxViewFrame* pViewFrame = SfxViewFrame::Current(); + if (pViewFrame) + pViewFrame->ToggleChildWindow(rParent.GetType()); } - LanguageType SpellDialog::GetSelectedLang_Impl() const { - LanguageType nLang = m_pLanguageLB->GetSelectedLanguage(); + LanguageType nLang = m_xLanguageLB->get_active_id(); return nLang; } - -IMPL_LINK(SpellDialog, LanguageSelectHdl, ListBox&, rBox, void) +IMPL_LINK_NOARG(SpellDialog, LanguageSelectHdl, weld::ComboBox&, void) { //If selected language changes, then add->list should be regenerated to //match @@ -758,37 +723,36 @@ IMPL_LINK(SpellDialog, LanguageSelectHdl, ListBox&, rBox, void) //if currently an error is selected then search for alternatives for //this word and fill the alternatives ListBox accordingly - OUString sError = m_pSentenceED->GetErrorText(); - m_pSuggestionLB->Clear(); - if(!sError.isEmpty()) + OUString sError = m_xSentenceED->GetErrorText(); + m_xSuggestionLB->clear(); + if (!sError.isEmpty()) { - LanguageType eLanguage = static_cast<SvxLanguageBox*>(&rBox)->GetSelectedLanguage(); + LanguageType eLanguage = m_xLanguageLB->get_active_id(); Reference <XSpellAlternatives> xAlt = xSpell->spell( sError, static_cast<sal_uInt16>(eLanguage), Sequence< PropertyValue >() ); if( xAlt.is() ) - m_pSentenceED->SetAlternatives( xAlt ); + m_xSentenceED->SetAlternatives( xAlt ); else { - m_pSentenceED->ChangeMarkedWord( sError, eLanguage ); + m_xSentenceED->ChangeMarkedWord( sError, eLanguage ); SpellContinue_Impl(); } - m_pSentenceED->AddUndoAction(std::make_unique<SpellUndoAction_Impl>(SPELLUNDO_CHANGE_LANGUAGE, aDialogUndoLink)); + m_xSentenceED->AddUndoAction(std::make_unique<SpellUndoAction_Impl>(SPELLUNDO_CHANGE_LANGUAGE, aDialogUndoLink)); } SpellDialog::UpdateBoxes_Impl(true); } - void SpellDialog::SetTitle_Impl(LanguageType nLang) { OUString sTitle = rParent.HasGrammarChecking() ? m_sTitleSpellingGrammar : m_sTitleSpelling; sTitle = sTitle.replaceFirst( "$LANGUAGE ($LOCATION)", SvtLanguageTable::GetLanguageString(nLang) ); - SetText( sTitle ); + m_xDialog->set_title(m_xDialog->strip_mnemonic(sTitle)); } int SpellDialog::InitUserDicts() { - const LanguageType nLang = m_pLanguageLB->GetSelectedLanguage(); + const LanguageType nLang = m_xLanguageLB->get_active_id(); const Reference< XDictionary > *pDic = nullptr; @@ -812,10 +776,7 @@ int SpellDialog::InitUserDicts() bool bEnable = false; const sal_Int32 nSize = pImpl->aDics.getLength(); pDic = pImpl->aDics.getConstArray(); - PopupMenu* pMenu = m_pAddToDictMB->GetPopupMenu(); - assert(pMenu); - pMenu->Clear(); - pMenu->SetMenuFlags(MenuFlags::NoAutoMnemonics); + m_xAddToDictMB->clear(); sal_uInt16 nItemId = 1; // menu items should be enumerated from 1 and not 0 for (sal_Int32 i = 0; i < nSize; ++i) { @@ -830,57 +791,51 @@ int SpellDialog::InitUserDicts() && (nLang == nActLanguage || LANGUAGE_NONE == nActLanguage ) && (!xStor.is() || !xStor->isReadonly()) ) { - pMenu->InsertItem( nItemId, xDicTmp->getName() ); bEnable = true; + OUString aDictionaryImageUrl; uno::Reference< lang::XServiceInfo > xSvcInfo( xDicTmp, uno::UNO_QUERY ); if (xSvcInfo.is()) { - OUString aDictionaryImageUrl( aCfg.GetSpellAndGrammarContextDictionaryImage( - xSvcInfo->getImplementationName()) ); - if (!aDictionaryImageUrl.isEmpty()) - { - Image aImage( aDictionaryImageUrl ); - pMenu->SetItemImage( nItemId, aImage ); - } + aDictionaryImageUrl = aCfg.GetSpellAndGrammarContextDictionaryImage( + xSvcInfo->getImplementationName()); } + m_xAddToDictMB->append_item(OUString::number(nItemId), xDicTmp->getName(), aDictionaryImageUrl); + ++nItemId; } } - m_pAddToDictMB->Enable( bEnable ); - m_pAddToDictPB->Enable( bEnable ); + m_xAddToDictMB->set_sensitive( bEnable ); + m_xAddToDictPB->set_sensitive( bEnable ); int nDicts = nItemId-1; - m_pAddToDictMB->Show( nDicts > 1 ); - m_pAddToDictPB->Show( nDicts <= 1 ); + m_xAddToDictMB->set_visible( nDicts > 1 ); + m_xAddToDictPB->set_visible( nDicts <= 1 ); return nDicts; } - -IMPL_LINK_NOARG(SpellDialog, AddToDictClickHdl, Button*, void) +IMPL_LINK_NOARG(SpellDialog, AddToDictClickHdl, weld::Button&, void) { - AddToDictionaryExecute(1, m_pAddToDictMB->GetPopupMenu()); + AddToDictionaryExecute(OString::number(1)); } - -IMPL_LINK(SpellDialog, AddToDictSelectHdl, MenuButton*, pButton, void ) +IMPL_LINK(SpellDialog, AddToDictSelectHdl, const OString&, rIdent, void) { - AddToDictionaryExecute(pButton->GetCurItemId(), pButton->GetPopupMenu()); + AddToDictionaryExecute(rIdent); } - -void SpellDialog::AddToDictionaryExecute( sal_uInt16 nItemId, PopupMenu const *pMenu ) +void SpellDialog::AddToDictionaryExecute(const OString& rItemId) { - m_pSentenceED->UndoActionStart( SPELLUNDO_CHANGE_GROUP ); + m_xSentenceED->UndoActionStart( SPELLUNDO_CHANGE_GROUP ); //GetErrorText() returns the current error even if the text is already //manually changed - const OUString aNewWord = m_pSentenceED->GetErrorText(); + const OUString aNewWord = m_xSentenceED->GetErrorText(); - OUString aDicName ( pMenu->GetItemText( nItemId ) ); + OUString aDicName(m_xAddToDictMB->get_item_label(rItemId)); uno::Reference< linguistic2::XDictionary > xDic; uno::Reference< linguistic2::XSearchableDictionaryList > xDicList( LinguMgr::GetDictionaryList() ); @@ -902,7 +857,7 @@ void SpellDialog::AddToDictionaryExecute( sal_uInt16 nItemId, PopupMenu const *p SPELLUNDO_CHANGE_ADD_TO_DICTIONARY, aDialogUndoLink)); pAction->SetDictionary( xDic ); pAction->SetAddedWord( aNewWord ); - m_pSentenceED->AddUndoAction( std::move(pAction) ); + m_xSentenceED->AddUndoAction( std::move(pAction) ); } // failed because there is already an entry? if (DictionaryError::NONE != nAddRes && xDic->getEntry( aNewWord ).is()) @@ -910,48 +865,42 @@ void SpellDialog::AddToDictionaryExecute( sal_uInt16 nItemId, PopupMenu const *p } if (DictionaryError::NONE != nAddRes) { - SvxDicError(GetFrameWeld(), nAddRes); + SvxDicError(m_xDialog.get(), nAddRes); return; // don't continue } // go on SpellContinue_Impl(); - m_pSentenceED->UndoActionEnd(); + m_xSentenceED->UndoActionEnd(); } - -IMPL_LINK(SpellDialog, ModifyHdl, Edit&, rEd, void) +IMPL_LINK_NOARG(SpellDialog, ModifyHdl, LinkParamNone*, void) { - if (m_pSentenceED == &rEd) + m_xSuggestionLB->unselect_all(); + m_xSuggestionLB->set_sensitive(false); + m_xAutoCorrPB->set_sensitive(false); + std::unique_ptr<SpellUndoAction_Impl> pSpellAction(new SpellUndoAction_Impl(SPELLUNDO_CHANGE_TEXTENGINE, aDialogUndoLink)); + if(!m_xChangeAllPB->get_sensitive()) { - m_pSuggestionLB->SetNoSelection(); - m_pSuggestionLB->Disable(); - m_pAutoCorrPB->Disable(); - std::unique_ptr<SpellUndoAction_Impl> pSpellAction(new SpellUndoAction_Impl(SPELLUNDO_CHANGE_TEXTENGINE, aDialogUndoLink)); - if(!m_pChangeAllPB->IsEnabled()) - { - m_pChangeAllPB->Enable(); - pSpellAction->SetEnableChangeAllPB(); - } - if(!m_pChangePB->IsEnabled()) - { - m_pChangePB->Enable(); - pSpellAction->SetEnableChangePB(); - } - m_pSentenceED->AddUndoAction(std::move(pSpellAction)); + m_xChangeAllPB->set_sensitive(true); + pSpellAction->SetEnableChangeAllPB(); } -}; - + if(!m_xChangePB->get_sensitive()) + { + m_xChangePB->set_sensitive(true); + pSpellAction->SetEnableChangePB(); + } + m_xSentenceED->AddUndoAction(std::move(pSpellAction)); +} -IMPL_LINK_NOARG(SpellDialog, CancelHdl, Button*, void) +IMPL_LINK_NOARG(SpellDialog, CancelHdl, weld::Button&, void) { //apply changes and ignored text parts first - if there are any - rParent.ApplyChangedSentence(m_pSentenceED->CreateSpellPortions(), false); + rParent.ApplyChangedSentence(m_xSentenceED->CreateSpellPortions(), false); Close(); } - -bool SpellDialog::EventNotify( NotifyEvent& rNEvt ) +void SpellDialog::ToplevelFocusChanged() { /* #i38338# * FIXME: LoseFocus and GetFocus are signals from vcl that @@ -962,66 +911,75 @@ bool SpellDialog::EventNotify( NotifyEvent& rNEvt ) * The only sensible thing would be to call the new Method differently, * e.g. DialogGot/LostFocus or so. */ - if( IsVisible() && !bFocusLocked ) + if (m_xDialog->get_visible() && !bFocusLocked) { - if( rNEvt.GetType() == MouseNotifyEvent::GETFOCUS ) + if (m_xDialog->has_toplevel_focus()) { //notify the child window of the focus change rParent.GetFocus(); } - else if( rNEvt.GetType() == MouseNotifyEvent::LOSEFOCUS ) + else { //notify the child window of the focus change rParent.LoseFocus(); } } - return SfxModelessDialog::EventNotify(rNEvt); } +void SpellDialog::Activate() +{ + SfxModelessDialogController::Activate(); + ToplevelFocusChanged(); +} + +void SpellDialog::Deactivate() +{ + SfxModelessDialogController::Activate(); + ToplevelFocusChanged(); +} void SpellDialog::InvalidateDialog() { if( bFocusLocked ) return; - m_pIgnorePB->SetText(m_sResumeST); - vcl::Window* aDisableArr[] = + m_xIgnorePB->set_label(m_sResumeST); + weld::Widget* aDisableArr[] = { - m_pNotInDictFT, - m_pSentenceED, - m_pSuggestionFT, - m_pSuggestionLB, - m_pLanguageFT, - m_pLanguageLB, - m_pIgnoreAllPB, - m_pIgnoreRulePB, - m_pAddToDictMB, - m_pAddToDictPB, - m_pChangePB, - m_pChangeAllPB, - m_pAutoCorrPB, - m_pUndoPB, + m_xNotInDictFT.get(), + m_xSentenceED->GetDrawingArea(), + m_xSuggestionFT.get(), + m_xSuggestionLB.get(), + m_xLanguageFT.get(), + m_xLanguageLB->get_widget(), + m_xIgnoreAllPB.get(), + m_xIgnoreRulePB.get(), + m_xAddToDictMB.get(), + m_xAddToDictPB.get(), + m_xChangePB.get(), + m_xChangeAllPB.get(), + m_xAutoCorrPB.get(), + m_xUndoPB.get(), nullptr }; sal_Int16 i = 0; while(aDisableArr[i]) { - aDisableArr[i]->Enable(false); + aDisableArr[i]->set_sensitive(false); i++; } - SfxModelessDialog::Deactivate(); + SfxModelessDialogController::Deactivate(); } - bool SpellDialog::GetNextSentence_Impl(bool bUseSavedSentence, bool bRecheck) { bool bRet = false; if(!bUseSavedSentence) { //apply changes and ignored text parts - rParent.ApplyChangedSentence(m_pSentenceED->CreateSpellPortions(), bRecheck); + rParent.ApplyChangedSentence(m_xSentenceED->CreateSpellPortions(), bRecheck); } - m_pSentenceED->ResetIgnoreErrorsAt(); - m_pSentenceED->ResetModified(); + m_xSentenceED->ResetIgnoreErrorsAt(); + m_xSentenceED->ResetModified(); SpellPortions aSentence = bUseSavedSentence ? m_aSavedSentence : rParent.GetNextWrongSentence( bRecheck ); if(!bUseSavedSentence) m_aSavedSentence = aSentence; @@ -1049,7 +1007,7 @@ bool SpellDialog::GetNextSentence_Impl(bool bUseSavedSentence, bool bRecheck) if(!elem.bIsHidden) sText.append(elem.sText); } - m_pSentenceED->SetText(sText.makeStringAndClear()); + m_xSentenceED->SetText(sText.makeStringAndClear()); sal_Int32 nStartPosition = 0; sal_Int32 nEndPosition = 0; @@ -1067,7 +1025,9 @@ bool SpellDialog::GetNextSentence_Impl(bool bUseSavedSentence, bool bRecheck) sServiceName = xNamed->getName(); SpellErrorDescription aDesc( false, elem.xAlternatives->getWord(), elem.xAlternatives->getLocale(), elem.xAlternatives->getAlternatives(), nullptr); - m_pSentenceED->SetAttrib( SpellErrorAttrib(aDesc), 0, nStartPosition, nEndPosition ); + SfxGrabBagItem aSpellErrorDescription(EE_CHAR_GRABBAG); + aSpellErrorDescription.GetGrabBag()["SpellErrorDescription"] <<= aDesc.toSequence(); + m_xSentenceED->SetAttrib(aSpellErrorDescription, nStartPosition, nEndPosition); } else if(elem.bIsGrammarError ) { @@ -1093,19 +1053,23 @@ bool SpellDialog::GetNextSentence_Impl(bool bUseSavedSentence, bool bRecheck) &elem.aGrammarError.aFullComment, &elem.aGrammarError.aRuleIdentifier, &sFullCommentURL ); - m_pSentenceED->SetAttrib( SpellErrorAttrib(aDesc), 0, nStartPosition, nEndPosition ); + + SfxGrabBagItem aSpellErrorDescriptionItem(EE_CHAR_GRABBAG); + aSpellErrorDescriptionItem.GetGrabBag()["SpellErrorDescription"] <<= aDesc.toSequence(); + m_xSentenceED->SetAttrib(aSpellErrorDescriptionItem, nStartPosition, nEndPosition); } - if(elem.bIsField) - m_pSentenceED->SetAttrib( SpellBackgroundAttrib(COL_LIGHTGRAY), 0, nStartPosition, nEndPosition ); - m_pSentenceED->SetAttrib( SpellLanguageAttrib(elem.eLanguage), 0, nStartPosition, nEndPosition ); + + if (elem.bIsField) + m_xSentenceED->SetAttrib(SvxBackgroundColorItem(COL_LIGHTGRAY, EE_CHAR_BKGCOLOR), nStartPosition, nEndPosition); + m_xSentenceED->SetAttrib(SvxLanguageItem(elem.eLanguage, EE_CHAR_LANGUAGE), nStartPosition, nEndPosition); nStartPosition = nEndPosition; } } //the edit field needs to be modified to apply the change from the ApplyChangeAllList if(!bHasReplaced) - m_pSentenceED->ClearModifyFlag(); - m_pSentenceED->ResetUndo(); - m_pUndoPB->Enable(false); + m_xSentenceED->ClearModifyFlag(); + m_xSentenceED->ResetUndo(); + m_xUndoPB->set_sensitive(false); bRet = nStartPosition > 0; } return bRet; @@ -1145,26 +1109,149 @@ bool SpellDialog::ApplyChangeAllList_Impl(SpellPortions& rSentence, bool &bHasRe return bRet; } - -SentenceEditWindow_Impl::SentenceEditWindow_Impl(vcl::Window * pParent, WinBits nBits) - : VclMultiLineEdit(pParent, nBits) - , m_nErrorStart(0) +SentenceEditWindow_Impl::SentenceEditWindow_Impl() + : m_nErrorStart(0) , m_nErrorEnd(0) , m_bIsUndoEditMode(false) { - DisableSelectionOnFocus(); } -SentenceEditWindow_Impl::~SentenceEditWindow_Impl() +void SentenceEditWindow_Impl::SetDrawingArea(weld::DrawingArea* pDrawingArea) +{ + Size aSize(pDrawingArea->get_approximate_digit_width() * 60, + pDrawingArea->get_text_height() * 6); + + pDrawingArea->set_size_request(aSize.Width(), aSize.Height()); + SetOutputSizePixel(aSize); + + weld::CustomWidgetController::SetDrawingArea(pDrawingArea); + + EnableRTL(false); + + const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings(); + Color aBgColor = rStyleSettings.GetWindowColor(); + + OutputDevice& rDevice = pDrawingArea->get_ref_device(); + + rDevice.SetMapMode(MapMode(MapUnit::MapTwip)); + rDevice.SetBackground(aBgColor); + + Size aOutputSize(rDevice.PixelToLogic(aSize)); + aSize = aOutputSize; + aSize.setHeight( aSize.Height() * 4 ); + + m_xEditEngine.reset(new EditEngine(EditEngine::CreatePool())); + m_xEditEngine->SetPaperSize( aSize ); + m_xEditEngine->SetRefDevice( &rDevice ); + + m_xEditEngine->SetControlWord(m_xEditEngine->GetControlWord() | EEControlBits::MARKFIELDS); + + m_xEdView.reset(new EditView(m_xEditEngine.get(), nullptr)); + m_xEdView->setEditViewCallbacks(this); + m_xEdView->SetOutputArea(tools::Rectangle(Point(0,0), aOutputSize)); + + m_xEdView->SetBackgroundColor(aBgColor); + m_xEditEngine->InsertView(m_xEdView.get()); + + pDrawingArea->set_cursor(PointerStyle::Text); +} + +void SentenceEditWindow_Impl::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect) +{ + //note: ClassificationEditView::Paint is similar + + rRenderContext.Push(PushFlags::ALL); + rRenderContext.SetClipRegion(); + + const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings(); + Color aBgColor = rStyleSettings.GetWindowColor(); + + m_xEdView->SetBackgroundColor(aBgColor); + + rRenderContext.SetBackground(aBgColor); + + tools::Rectangle aLogicRect(rRenderContext.PixelToLogic(rRect)); + m_xEdView->Paint(aLogicRect, &rRenderContext); + + if (HasFocus()) + { + m_xEdView->ShowCursor(); + vcl::Cursor* pCursor = m_xEdView->GetCursor(); + pCursor->DrawToDevice(rRenderContext); + } + + std::vector<tools::Rectangle> aLogicRects; + + // get logic selection + m_xEdView->GetSelectionRectangles(aLogicRects); + + rRenderContext.SetLineColor(); + rRenderContext.SetFillColor(COL_BLACK); + rRenderContext.SetRasterOp(RasterOp::Invert); + + for (const auto &rSelectionRect : aLogicRects) + rRenderContext.DrawRect(rSelectionRect); + + rRenderContext.Pop(); +} + +bool SentenceEditWindow_Impl::MouseMove(const MouseEvent& rMEvt) +{ + return m_xEdView->MouseMove(rMEvt); +} + +bool SentenceEditWindow_Impl::MouseButtonDown(const MouseEvent& rMEvt) { - disposeOnce(); + if (!HasFocus()) + GrabFocus(); + + return m_xEdView->MouseButtonDown(rMEvt); } -extern "C" SAL_DLLPUBLIC_EXPORT void makeSentenceEditWindow(VclPtr<vcl::Window> & rRet, VclPtr<vcl::Window> & pParent, VclBuilder::stringmap &) +bool SentenceEditWindow_Impl::MouseButtonUp(const MouseEvent& rMEvt) { - rRet = VclPtr<SentenceEditWindow_Impl>::Create(pParent, WB_BORDER|WB_VSCROLL|WB_IGNORETAB); + return m_xEdView->MouseButtonUp(rMEvt); } +void SentenceEditWindow_Impl::Resize() +{ + OutputDevice& rDevice = GetDrawingArea()->get_ref_device(); + Size aOutputSize(rDevice.PixelToLogic(GetOutputSizePixel())); + Size aSize(aOutputSize); + aSize.setHeight( aSize.Height() * 4 ); + m_xEditEngine->SetPaperSize(aSize); + m_xEdView->SetOutputArea(tools::Rectangle(Point(0,0), aOutputSize)); + weld::CustomWidgetController::Resize(); +} + +SentenceEditWindow_Impl::~SentenceEditWindow_Impl() +{ +} + +namespace +{ + const EECharAttrib* FindCharAttrib(int nStartPosition, int nEndPosition, sal_uInt16 nWhich, std::vector<EECharAttrib>& rAttribList) + { + for (const auto& rTextAtr : rAttribList) + { + if (rTextAtr.pAttr->Which() != nWhich) + continue; + if (rTextAtr.nStart <= nStartPosition && rTextAtr.nEnd >= nEndPosition) + { + return &rTextAtr; + } + } + + return nullptr; + } + + void ExtractErrorDescription(const EECharAttrib& rEECharAttrib, SpellErrorDescription& rSpellErrorDescription) + { + css::uno::Sequence<css::uno::Any> aSequence; + static_cast<const SfxGrabBagItem*>(rEECharAttrib.pAttr)->GetGrabBag().find("SpellErrorDescription")->second >>= aSequence; + rSpellErrorDescription.fromSequence(aSequence); + } +} /*------------------------------------------------------------------------- The selection before inputting a key may have a range or not @@ -1239,309 +1326,312 @@ extern "C" SAL_DLLPUBLIC_EXPORT void makeSentenceEditWindow(VclPtr<vcl::Window> #define ACTION_SELECTFIELD 2 #define ACTION_EXPAND 3 -bool SentenceEditWindow_Impl::PreNotify( NotifyEvent& rNEvt ) +bool SentenceEditWindow_Impl::KeyInput(const KeyEvent& rKeyEvt) { - bool bChange = false; - if(rNEvt.GetType() == MouseNotifyEvent::KEYINPUT) + if (rKeyEvt.GetKeyCode().GetCode() == KEY_TAB) + return false; + + bool bConsumed = false; + + bool bChange = TextEngine::DoesKeyChangeText( rKeyEvt ); + if (bChange && !IsUndoEditMode()) { - const KeyEvent& rKeyEvt = *rNEvt.GetKeyEvent(); - bChange = TextEngine::DoesKeyChangeText( rKeyEvt ); - if(bChange && !IsUndoEditMode() && - rKeyEvt.GetKeyCode().GetCode() != KEY_TAB) + bConsumed = true; + + ESelection aCurrentSelection(m_xEdView->GetSelection()); + aCurrentSelection.Adjust(); + + //determine if the selection contains a field + bool bHasFieldLeft = false; + bool bHasErrorLeft = false; + + bool bHasRange = aCurrentSelection.HasRange(); + sal_uInt8 nSelectionType = 0; // invalid type! + + std::vector<EECharAttrib> aAttribList; + m_xEditEngine->GetCharAttribs(0, aAttribList); + + auto nCursor = aCurrentSelection.nStartPos; + const EECharAttrib* pBackAttr = FindCharAttrib(nCursor, nCursor, EE_CHAR_BKGCOLOR, aAttribList); + const EECharAttrib* pErrorAttr = FindCharAttrib(nCursor, nCursor, EE_CHAR_GRABBAG, aAttribList); + const EECharAttrib* pBackAttrLeft = nullptr; + const EECharAttrib* pErrorAttrLeft = nullptr; + + bool bHasField = pBackAttr != nullptr && (bHasRange || pBackAttr->nEnd > nCursor); + bool bHasError = pErrorAttr != nullptr && (bHasRange || pErrorAttr->nEnd > nCursor); + if (bHasRange) { - TextEngine* pTextEngine = GetTextEngine(); - TextView* pTextView = pTextEngine->GetActiveView(); - TextSelection aCurrentSelection = pTextView->GetSelection(); - aCurrentSelection.Justify(); - //determine if the selection contains a field - bool bHasFieldLeft = false; - bool bHasErrorLeft = false; - - bool bHasRange = aCurrentSelection.HasRange(); - sal_uInt8 nSelectionType = 0; // invalid type! - - TextPaM aCursor(aCurrentSelection.GetStart()); - const TextCharAttrib* pBackAttr = pTextEngine->FindCharAttrib( aCursor, TEXTATTR_SPELL_BACKGROUND ); - const TextCharAttrib* pErrorAttr = pTextEngine->FindCharAttrib( aCursor, TEXTATTR_SPELL_ERROR ); - const TextCharAttrib* pBackAttrLeft = nullptr; - const TextCharAttrib* pErrorAttrLeft = nullptr; - - bool bHasField = pBackAttr != nullptr && (bHasRange || pBackAttr->GetEnd() > aCursor.GetIndex()); - bool bHasError = pErrorAttr != nullptr && (bHasRange || pErrorAttr->GetEnd() > aCursor.GetIndex()); - if(bHasRange) + if (pBackAttr && + pBackAttr->nStart == aCurrentSelection.nStartPos && + pBackAttr->nEnd == aCurrentSelection.nEndPos) { - if(pBackAttr && - pBackAttr->GetStart() == aCurrentSelection.GetStart().GetIndex() && - pBackAttr->GetEnd() == aCurrentSelection.GetEnd().GetIndex()) - { - nSelectionType = FULL; - } - else if(pErrorAttr && - pErrorAttr->GetStart() <= aCurrentSelection.GetStart().GetIndex() && - pErrorAttr->GetEnd() >= aCurrentSelection.GetEnd().GetIndex()) - { - nSelectionType = INSIDE_YES; - } - else - { - nSelectionType = bHasField||bHasError ? BRACE : OUTSIDE_NO; - while(aCursor.GetIndex() < aCurrentSelection.GetEnd().GetIndex()) - { - ++aCursor.GetIndex(); - const TextCharAttrib* pIntBackAttr = pTextEngine->FindCharAttrib( aCursor, TEXTATTR_SPELL_BACKGROUND ); - const TextCharAttrib* pIntErrorAttr = pTextEngine->FindCharAttrib( aCursor, TEXTATTR_SPELL_ERROR ); - //if any attr has been found then BRACE - if(pIntBackAttr || pIntErrorAttr) - nSelectionType = BRACE; - //the field has to be selected - if(pIntBackAttr && !pBackAttr) - pBackAttr = pIntBackAttr; - bHasField |= pIntBackAttr != nullptr; - } - } + nSelectionType = FULL; + } + else if (pErrorAttr && + pErrorAttr->nStart <= aCurrentSelection.nStartPos && + pErrorAttr->nEnd >= aCurrentSelection.nEndPos) + { + nSelectionType = INSIDE_YES; } else { - //no range selection: then 1 2 3 and 8 are possible - const TextCharAttrib* pCurAttr = pBackAttr ? pBackAttr : pErrorAttr; - if(pCurAttr) + nSelectionType = bHasField||bHasError ? BRACE : OUTSIDE_NO; + while (nCursor < aCurrentSelection.nEndPos) { - nSelectionType = pCurAttr->GetStart() == aCurrentSelection.GetStart().GetIndex() ? - LEFT_NO : pCurAttr->GetEnd() == aCurrentSelection.GetEnd().GetIndex() ? RIGHT_NO : INSIDE_NO; + ++nCursor; + const EECharAttrib* pIntBackAttr = FindCharAttrib(nCursor, nCursor, EE_CHAR_BKGCOLOR, aAttribList); + const EECharAttrib* pIntErrorAttr = FindCharAttrib(nCursor, nCursor, EE_CHAR_GRABBAG, aAttribList); + //if any attr has been found then BRACE + if (pIntBackAttr || pIntErrorAttr) + nSelectionType = BRACE; + //the field has to be selected + if (pIntBackAttr && !pBackAttr) + pBackAttr = pIntBackAttr; + bHasField |= pIntBackAttr != nullptr; } - else - nSelectionType = OUTSIDE_NO; + } + } + else + { + //no range selection: then 1 2 3 and 8 are possible + const EECharAttrib* pCurAttr = pBackAttr ? pBackAttr : pErrorAttr; + if (pCurAttr) + { + nSelectionType = pCurAttr->nStart == aCurrentSelection.nStartPos ? + LEFT_NO : pCurAttr->nEnd == aCurrentSelection.nEndPos ? RIGHT_NO : INSIDE_NO; + } + else + nSelectionType = OUTSIDE_NO; - bHasFieldLeft = pBackAttr && pBackAttr->GetEnd() == aCursor.GetIndex(); - if(bHasFieldLeft) - { - pBackAttrLeft = pBackAttr; - pBackAttr = nullptr; - } - bHasErrorLeft = pErrorAttr && pErrorAttr->GetEnd() == aCursor.GetIndex(); - if(bHasErrorLeft) - { - pErrorAttrLeft = pErrorAttr; - pErrorAttr = nullptr; - } + bHasFieldLeft = pBackAttr && pBackAttr->nEnd == nCursor; + if(bHasFieldLeft) + { + pBackAttrLeft = pBackAttr; + pBackAttr = nullptr; + } + bHasErrorLeft = pErrorAttr && pErrorAttr->nEnd == nCursor; + if(bHasErrorLeft) + { + pErrorAttrLeft = pErrorAttr; + pErrorAttr = nullptr; + } - //check previous position if this exists - //that is a redundant in the case the attribute found above already is on the left cursor side - //but it's o.k. for two errors/fields side by side - if(aCursor.GetIndex()) - { - --aCursor.GetIndex(); - pBackAttrLeft = pTextEngine->FindCharAttrib( aCursor, TEXTATTR_SPELL_BACKGROUND ); - pErrorAttrLeft = pTextEngine->FindCharAttrib( aCursor, TEXTATTR_SPELL_ERROR ); - bHasFieldLeft = pBackAttrLeft !=nullptr; - bHasErrorLeft = pErrorAttrLeft != nullptr; - ++aCursor.GetIndex(); - } + //check previous position if this exists + //that is a redundant in the case the attribute found above already is on the left cursor side + //but it's o.k. for two errors/fields side by side + if (nCursor) + { + --nCursor; + pBackAttrLeft = FindCharAttrib(nCursor, nCursor, EE_CHAR_BKGCOLOR, aAttribList); + pErrorAttrLeft = FindCharAttrib(nCursor, nCursor, EE_CHAR_GRABBAG, aAttribList); + bHasFieldLeft = pBackAttrLeft !=nullptr; + bHasErrorLeft = pErrorAttrLeft != nullptr; + ++nCursor; } - //Here we have to determine if the error found is the one currently active - bool bIsErrorActive = (pErrorAttr && pErrorAttr->GetStart() == m_nErrorStart) || - (pErrorAttrLeft && pErrorAttrLeft->GetStart() == m_nErrorStart); + } + //Here we have to determine if the error found is the one currently active + bool bIsErrorActive = (pErrorAttr && pErrorAttr->nStart == m_nErrorStart) || + (pErrorAttrLeft && pErrorAttrLeft->nStart == m_nErrorStart); - SAL_WARN_IF( - nSelectionType == INVALID, "cui.dialogs", - "selection type not set"); + SAL_WARN_IF( + nSelectionType == INVALID, "cui.dialogs", + "selection type not set"); - const vcl::KeyCode& rKeyCode = rKeyEvt.GetKeyCode(); - bool bDelete = rKeyCode.GetCode() == KEY_DELETE; - bool bBackspace = rKeyCode.GetCode() == KEY_BACKSPACE; + const vcl::KeyCode& rKeyCode = rKeyEvt.GetKeyCode(); + bool bDelete = rKeyCode.GetCode() == KEY_DELETE; + bool bBackspace = rKeyCode.GetCode() == KEY_BACKSPACE; - sal_Int8 nAction = ACTION_CONTINUE; - switch(nSelectionType) - { + sal_Int8 nAction = ACTION_CONTINUE; + switch(nSelectionType) + { // 1 - backspace delete any other // UE on field FS on error CO on field FS on error CO - case LEFT_NO : - if(bBackspace) - { - nAction = bHasFieldLeft ? ACTION_SELECTFIELD : ACTION_UNDOEDIT; - //to force the use of pBackAttrLeft - pBackAttr = nullptr; - } - else if(bDelete) - nAction = bHasField ? ACTION_SELECTFIELD : ACTION_CONTINUE; - else - nAction = bHasError && !aCursor.GetIndex() ? ACTION_CONTINUE : - bHasError ? ACTION_EXPAND : bHasErrorLeft ? ACTION_CONTINUE : ACTION_UNDOEDIT; - break; + case LEFT_NO : + if(bBackspace) + { + nAction = bHasFieldLeft ? ACTION_SELECTFIELD : ACTION_UNDOEDIT; + //to force the use of pBackAttrLeft + pBackAttr = nullptr; + } + else if(bDelete) + nAction = bHasField ? ACTION_SELECTFIELD : ACTION_CONTINUE; + else + nAction = bHasError && !nCursor ? ACTION_CONTINUE : + bHasError ? ACTION_EXPAND : bHasErrorLeft ? ACTION_CONTINUE : ACTION_UNDOEDIT; + break; // 2 - on field FS on error C - case INSIDE_NO : - nAction = bHasField ? ACTION_SELECTFIELD : - bIsErrorActive ? ACTION_CONTINUE : ACTION_UNDOEDIT; - break; + case INSIDE_NO : + nAction = bHasField ? ACTION_SELECTFIELD : + bIsErrorActive ? ACTION_CONTINUE : ACTION_UNDOEDIT; + break; // 3 - backspace delete any other // on field FS on error CO UE on field UE on error EX - case RIGHT_NO : - if(bBackspace) - nAction = bHasFieldLeft ? ACTION_SELECTFIELD : ACTION_CONTINUE; - else if(bDelete) - nAction = bHasFieldLeft && bHasError ? ACTION_CONTINUE : ACTION_UNDOEDIT; - else - nAction = bHasFieldLeft && bHasError ? ACTION_EXPAND : - bHasError ? ACTION_CONTINUE : bHasErrorLeft ? ACTION_EXPAND :ACTION_UNDOEDIT; - break; + case RIGHT_NO : + if(bBackspace) + nAction = bHasFieldLeft ? ACTION_SELECTFIELD : ACTION_CONTINUE; + else if(bDelete) + nAction = bHasFieldLeft && bHasError ? ACTION_CONTINUE : ACTION_UNDOEDIT; + else + nAction = bHasFieldLeft && bHasError ? ACTION_EXPAND : + bHasError ? ACTION_CONTINUE : bHasErrorLeft ? ACTION_EXPAND :ACTION_UNDOEDIT; + break; // 4 - on field UE and on error CO - case FULL : - nAction = ACTION_UNDOEDIT; - break; + case FULL : + nAction = ACTION_UNDOEDIT; + break; // 5 - on field FS and on error CO - case INSIDE_YES : - nAction = bHasField ? ACTION_SELECTFIELD : ACTION_CONTINUE; - break; + case INSIDE_YES : + nAction = bHasField ? ACTION_SELECTFIELD : ACTION_CONTINUE; + break; // 6 - on field FS and on error UE - case BRACE : - nAction = bHasField ? ACTION_SELECTFIELD : ACTION_UNDOEDIT; - break; + case BRACE : + nAction = bHasField ? ACTION_SELECTFIELD : ACTION_UNDOEDIT; + break; // 7 - UE // 8 - UE - case OUTSIDE_NO : - case OUTSIDE_YES: - nAction = ACTION_UNDOEDIT; - break; - } - //save the current paragraph - sal_Int32 nCurrentLen = GetText().getLength(); - if(nAction != ACTION_SELECTFIELD) - pTextView->GetWindow()->KeyInput(rKeyEvt); - else + case OUTSIDE_NO : + case OUTSIDE_YES: + nAction = ACTION_UNDOEDIT; + break; + } + //save the current paragraph + sal_Int32 nCurrentLen = m_xEditEngine->GetText().getLength(); + if (nAction != ACTION_SELECTFIELD) + { + m_xEdView->PostKeyEvent(rKeyEvt); + } + else + { + const EECharAttrib* pCharAttr = pBackAttr ? pBackAttr : pBackAttrLeft; + if (pCharAttr) + m_xEdView->SetSelection(ESelection(0, pCharAttr->nStart, 0, pCharAttr->nEnd)); + } + if(nAction == ACTION_EXPAND) + { + DBG_ASSERT(pErrorAttrLeft || pErrorAttr, "where is the error"); + //text has been added on the right and only the 'error attribute has to be corrected + if (pErrorAttrLeft) { - const TextCharAttrib* pCharAttr = pBackAttr ? pBackAttr : pBackAttrLeft; - if(pCharAttr) + SpellErrorDescription aSpellErrorDescription; + ExtractErrorDescription(*pErrorAttrLeft, aSpellErrorDescription); + + std::unique_ptr<SfxPoolItem> xNewError(pErrorAttrLeft->pAttr->Clone()); + sal_Int32 nStart = pErrorAttrLeft->nStart; + sal_Int32 nEnd = pErrorAttrLeft->nEnd + 1; + m_xEditEngine->RemoveAttribs(ESelection(0, nStart, 0, nEnd), false, EE_CHAR_GRABBAG); + SetAttrib(*xNewError, nStart, nEnd); + //only active errors move the mark + if (bIsErrorActive) { - TextPaM aStart(0, pCharAttr->GetStart()); - TextPaM aEnd(0, pCharAttr->GetEnd()); - TextSelection aNewSel(aStart, aEnd); - pTextView->SetSelection( aNewSel); + bool bGrammar = aSpellErrorDescription.bIsGrammarError; + MoveErrorMarkTo(nStart, nEnd, bGrammar); } } - if(nAction == ACTION_EXPAND) + //text has been added on the left then the error attribute has to be expanded and the + //field attribute on the right - if any - has to be contracted + else if (pErrorAttr) { - DBG_ASSERT(pErrorAttrLeft || pErrorAttr, "where is the error"); - //text has been added on the right and only the 'error attribute has to be corrected - if(pErrorAttrLeft) + SpellErrorDescription aSpellErrorDescription; + ExtractErrorDescription(*pErrorAttr, aSpellErrorDescription); + + //determine the change + sal_Int32 nAddedChars = m_xEditEngine->GetText().getLength() - nCurrentLen; + + std::unique_ptr<SfxPoolItem> xNewError(pErrorAttr->pAttr->Clone()); + sal_Int32 nStart = pErrorAttr->nStart + nAddedChars; + sal_Int32 nEnd = pErrorAttr->nEnd + nAddedChars; + m_xEditEngine->RemoveAttribs(ESelection(0, nStart, 0, nEnd), false, EE_CHAR_GRABBAG); + nStart = pErrorAttr->nStart; + SetAttrib(*xNewError, nStart, nEnd); + //only if the error is active the mark is moved here + if (bIsErrorActive) { - std::unique_ptr<TextAttrib> pNewError(pErrorAttrLeft->GetAttr().Clone()); - const sal_Int32 nStart = pErrorAttrLeft->GetStart(); - sal_Int32 nEnd = pErrorAttrLeft->GetEnd(); - pTextEngine->RemoveAttrib( 0, *pErrorAttrLeft ); - SetAttrib( *pNewError, 0, nStart, ++nEnd ); - //only active errors move the mark - if(bIsErrorActive) - { - bool bGrammar = static_cast<const SpellErrorAttrib&>(*pNewError).GetErrorDescription().bIsGrammarError; - MoveErrorMarkTo(nStart, nEnd, bGrammar); - } + bool bGrammar = aSpellErrorDescription.bIsGrammarError; + MoveErrorMarkTo(nStart, nEnd, bGrammar); } - //text has been added on the left then the error attribute has to be expanded and the - //field attribute on the right - if any - has to be contracted - else if(pErrorAttr) - { - //determine the change - sal_Int32 nAddedChars = GetText().getLength() - nCurrentLen; - - std::unique_ptr<TextAttrib> pNewError(pErrorAttr->GetAttr().Clone()); - sal_Int32 nStart = pErrorAttr->GetStart(); - sal_Int32 nEnd = pErrorAttr->GetEnd(); - pTextEngine->RemoveAttrib( 0, *pErrorAttr ); - nStart = nStart - nAddedChars; - SetAttrib( *pNewError, 0, nStart - nAddedChars, nEnd ); - //only if the error is active the mark is moved here - if(bIsErrorActive) - { - bool bGrammar = static_cast<const SpellErrorAttrib&>(*pNewError).GetErrorDescription().bIsGrammarError; - MoveErrorMarkTo(nStart, nEnd, bGrammar); - } - pNewError.reset(); + xNewError.reset(); - if(pBackAttrLeft) - { - std::unique_ptr<TextAttrib> pNewBack(pBackAttrLeft->GetAttr().Clone()); - const sal_Int32 _nStart = pBackAttrLeft->GetStart(); - const sal_Int32 _nEnd = pBackAttrLeft->GetEnd(); - pTextEngine->RemoveAttrib( 0, *pBackAttrLeft ); - SetAttrib( *pNewBack, 0, _nStart, _nEnd - nAddedChars); - } + if (pBackAttrLeft) + { + std::unique_ptr<SfxPoolItem> xNewBack(pBackAttrLeft->pAttr->Clone()); + sal_Int32 _nStart = pBackAttrLeft->nStart + nAddedChars; + sal_Int32 _nEnd = pBackAttrLeft->nEnd + nAddedChars; + m_xEditEngine->RemoveAttribs(ESelection(0, _nStart, 0, _nEnd), false, EE_CHAR_BKGCOLOR); + _nStart = pBackAttrLeft->nStart; + SetAttrib(*xNewBack, _nStart, _nEnd); } } - else if(nAction == ACTION_UNDOEDIT) - { - SetUndoEditMode(true); - } - //make sure the error positions are correct after text changes - //the old attribute may have been deleted - //all changes inside of the current error leave the error attribute at the current - //start position - if(!IsUndoEditMode() && bIsErrorActive) + } + else if(nAction == ACTION_UNDOEDIT) + { + SetUndoEditMode(true); + } + //make sure the error positions are correct after text changes + //the old attribute may have been deleted + //all changes inside of the current error leave the error attribute at the current + //start position + if (!IsUndoEditMode() && bIsErrorActive) + { + const EECharAttrib* pFontColor = FindCharAttrib(nCursor, nCursor, EE_CHAR_COLOR, aAttribList); + const EECharAttrib* pErrorAttrib = FindCharAttrib(m_nErrorStart, m_nErrorStart, EE_CHAR_GRABBAG, aAttribList); + if (pFontColor && pErrorAttrib) { - const TextCharAttrib* pFontColor = pTextEngine->FindCharAttrib( aCursor, TEXTATTR_FONTCOLOR ); - const TextCharAttrib* pErrorAttrib = pTextEngine->FindCharAttrib( TextPaM(0, m_nErrorStart), TEXTATTR_SPELL_ERROR ); - if(pFontColor && pErrorAttrib ) + m_nErrorStart = pFontColor->nStart; + m_nErrorEnd = pFontColor->nEnd; + if (pErrorAttrib->nStart != m_nErrorStart || pErrorAttrib->nEnd != m_nErrorEnd) { - m_nErrorStart = pFontColor->GetStart(); - m_nErrorEnd = pFontColor->GetEnd(); - if(pErrorAttrib->GetStart() != m_nErrorStart || pErrorAttrib->GetEnd() != m_nErrorEnd) - { - std::unique_ptr<TextAttrib> pNewError(pErrorAttrib->GetAttr().Clone()); - pTextEngine->RemoveAttrib( 0, *pErrorAttr ); - SetAttrib( *pNewError, 0, m_nErrorStart, m_nErrorEnd ); - } + std::unique_ptr<SfxPoolItem> xNewError(pErrorAttrib->pAttr->Clone()); + m_xEditEngine->RemoveAttribs(ESelection(0, pErrorAttr->nStart, 0, pErrorAttr->nEnd), false, EE_CHAR_GRABBAG); + SetAttrib(*xNewError, m_nErrorStart, m_nErrorEnd); } } - //this is not a modification anymore - if(nAction != ACTION_SELECTFIELD && !m_bIsUndoEditMode) - CallModifyLink(); } - else - bChange = false; + //this is not a modification anymore + if(nAction != ACTION_SELECTFIELD && !m_bIsUndoEditMode) + CallModifyLink(); } - return bChange || VclMultiLineEdit::PreNotify(rNEvt); + else + bConsumed = m_xEdView->PostKeyEvent(rKeyEvt); + + return bConsumed; } -void SentenceEditWindow_Impl::Init(VclPtr<ToolBox> const &rToolbar) +void SentenceEditWindow_Impl::Init(weld::Toolbar* pToolbar) { - m_xToolbar = rToolbar; - m_xToolbar->SetSelectHdl(LINK(this,SentenceEditWindow_Impl,ToolbarHdl)); + m_pToolbar = pToolbar; + m_pToolbar->connect_clicked(LINK(this,SentenceEditWindow_Impl,ToolbarHdl)); } -IMPL_LINK_NOARG(SentenceEditWindow_Impl, ToolbarHdl, ToolBox *, void) +IMPL_LINK(SentenceEditWindow_Impl, ToolbarHdl, const OString&, rCurItemId, void) { - const sal_uInt16 nCurItemId = m_xToolbar->GetCurItemId(); - if (nCurItemId == m_xToolbar->GetItemId("paste")) + if (rCurItemId == "paste") { - Paste(); + m_xEdView->Paste(); CallModifyLink(); } - else if (nCurItemId == m_xToolbar->GetItemId("insert")) + else if (rCurItemId == "insert") { if (Edit::GetGetSpecialCharsFunction()) { - OUString aChars = Edit::GetGetSpecialCharsFunction()( this, GetFont() ); + OUString aChars = Edit::GetGetSpecialCharsFunction()(GetDrawingArea(), m_xEditEngine->GetStandardFont(0)); if (!aChars.isEmpty()) { - ReplaceSelected(aChars); + ESelection aCurrentSelection(m_xEdView->GetSelection()); + m_xEditEngine->QuickInsertText(aChars, aCurrentSelection); CallModifyLink(); } } } } -void SentenceEditWindow_Impl::dispose() -{ - m_xToolbar.clear(); - VclMultiLineEdit::dispose(); -} - bool SentenceEditWindow_Impl::MarkNextError( bool bIgnoreCurrentError, const css::uno::Reference<css::linguistic2::XSpellChecker1>& xSpell ) { if (bIgnoreCurrentError) m_aIgnoreErrorsAt.insert( m_nErrorStart ); - ExtTextEngine* pTextEngine = GetTextEngine(); - const sal_Int32 nTextLen = pTextEngine->GetTextLen(0); - if(m_nErrorEnd >= nTextLen - 1) + + const sal_Int32 nTextLen = m_xEditEngine->GetTextLen(0); + + if (m_nErrorEnd >= nTextLen - 1) return false; //if it's not already modified the modified flag has to be reset at the end of the marking bool bModified = IsModified(); @@ -1551,42 +1641,62 @@ bool SentenceEditWindow_Impl::MarkNextError( bool bIgnoreCurrentError, const css //create a cursor behind the end of the last error //- or at 0 at the start of the sentence - TextPaM aCursor(0, m_nErrorEnd ? m_nErrorEnd + 1 : 0); - //search for SpellErrorAttrib + int nCursor(m_nErrorEnd ? m_nErrorEnd + 1 : 0); + + //search for SpellErrorDescription + SpellErrorDescription aSpellErrorDescription; + + std::vector<EECharAttrib> aAttribList; + m_xEditEngine->GetCharAttribs(0, aAttribList); - const TextCharAttrib* pNextError = nullptr; //iterate over the text and search for the next error that maybe has //to be replace by a ChangeAllList replacement bool bGrammarError = false; - while(aCursor.GetIndex() < nTextLen) + while (nCursor < nTextLen) { - while(aCursor.GetIndex() < nTextLen && - nullptr == (pNextError = pTextEngine->FindCharAttrib( aCursor, TEXTATTR_SPELL_ERROR))) + const SpellErrorDescription* pSpellErrorDescription = nullptr; + const EECharAttrib* pEECharAttrib = nullptr; + + sal_Int32 nMinPos = nTextLen + 1; + for (const auto& rTextAtr : aAttribList) { - ++aCursor.GetIndex(); + if (rTextAtr.pAttr->Which() != EE_CHAR_GRABBAG) + continue; + if (rTextAtr.nEnd > nCursor && rTextAtr.nStart < nMinPos) + { + nMinPos = rTextAtr.nStart; + pEECharAttrib = &rTextAtr; + } } - // maybe the error found here is already in the ChangeAllList and has to be replaced + if (pEECharAttrib) + { + ExtractErrorDescription(*pEECharAttrib, aSpellErrorDescription); + + bGrammarError = aSpellErrorDescription.bIsGrammarError; + m_nErrorStart = pEECharAttrib->nStart; + m_nErrorEnd = pEECharAttrib->nEnd; + + pSpellErrorDescription = &aSpellErrorDescription; + } + + nCursor = nMinPos; + + // maybe the error found here is already in the ChangeAllList and has to be replaced Reference<XDictionary> xChangeAll( LinguMgr::GetChangeAllList(), UNO_QUERY ); Reference<XDictionaryEntry> xEntry; - const SpellErrorDescription* pSpellErrorDescription = nullptr; - if(pNextError) - { - pSpellErrorDescription = &static_cast<const SpellErrorAttrib&>(pNextError->GetAttr()).GetErrorDescription(); - bGrammarError = pSpellErrorDescription->bIsGrammarError; - m_nErrorStart = pNextError->GetStart(); - m_nErrorEnd = pNextError->GetEnd(); - } - if(xChangeAll->getCount() && pSpellErrorDescription && + if (xChangeAll->getCount() && pSpellErrorDescription && (xEntry = xChangeAll->getEntry( pSpellErrorDescription->sErrorText )).is()) { - OUString sReplacement(getDotReplacementString(GetErrorText(), xEntry->getReplacementText())); - ChangeMarkedWord(sReplacement, LanguageTag::convertToLanguageType( pSpellErrorDescription->aLocale )); + int nLenChange = ChangeMarkedWord(sReplacement, LanguageTag::convertToLanguageType(pSpellErrorDescription->aLocale)); - aCursor.GetIndex() += sReplacement.getLength(); + nCursor += sReplacement.getLength(); + + if (nLenChange) + m_xEditEngine->GetCharAttribs(0, aAttribList); // maybe the error found here is already added to the dictionary and has to be ignored } else if(pSpellErrorDescription && !bGrammarError && @@ -1594,26 +1704,30 @@ bool SentenceEditWindow_Impl::MarkNextError( bool bIgnoreCurrentError, const css static_cast<sal_uInt16>(LanguageTag::convertToLanguageType( pSpellErrorDescription->aLocale )), Sequence< PropertyValue >() )) { - ++aCursor.GetIndex(); + ++nCursor; } else break; } //if an attrib has been found search for the end of the error string - if(aCursor.GetIndex() < nTextLen) + if (nCursor < nTextLen) { - MoveErrorMarkTo(aCursor.GetIndex(), pNextError->GetEnd(), bGrammarError); + MoveErrorMarkTo(nCursor, m_nErrorEnd, bGrammarError); bRet = true; //add an undo action std::unique_ptr<SpellUndoAction_Impl> pAction(new SpellUndoAction_Impl( SPELLUNDO_CHANGE_NEXTERROR, GetSpellDialog()->aDialogUndoLink)); pAction->SetErrorMove(nOldErrorStart, nOldErrorEnd); - const SpellErrorAttrib* pOldAttrib = static_cast<const SpellErrorAttrib*>( - pTextEngine->FindAttrib( TextPaM(0, nOldErrorStart), TEXTATTR_SPELL_ERROR )); - pAction->SetErrorLanguageSelected(pOldAttrib && pOldAttrib->GetErrorDescription().aSuggestions.hasElements() && - LanguageTag( pOldAttrib->GetErrorDescription().aLocale).getLanguageType() == - GetSpellDialog()->m_pLanguageLB->GetSelectedLanguage()); + + if (GetErrorDescription(aSpellErrorDescription, nOldErrorStart)) + { + pAction->SetErrorLanguageSelected(aSpellErrorDescription.aSuggestions.hasElements() && + LanguageTag(aSpellErrorDescription.aLocale).getLanguageType() == GetSpellDialog()->m_xLanguageLB->get_active_id()); + } + else + pAction->SetErrorLanguageSelected(false); + AddUndoAction(std::move(pAction)); } else @@ -1621,75 +1735,93 @@ bool SentenceEditWindow_Impl::MarkNextError( bool bIgnoreCurrentError, const css if( !bModified ) ClearModifyFlag(); SpellDialog* pSpellDialog = GetSpellDialog(); - pSpellDialog->m_pIgnorePB->Enable(bRet); - pSpellDialog->m_pIgnoreAllPB->Enable(bRet); - pSpellDialog->m_pAutoCorrPB->Enable(bRet); - pSpellDialog->m_pAddToDictMB->Enable(bRet); - pSpellDialog->m_pAddToDictPB->Enable(bRet); + pSpellDialog->m_xIgnorePB->set_sensitive(bRet); + pSpellDialog->m_xIgnoreAllPB->set_sensitive(bRet); + pSpellDialog->m_xAutoCorrPB->set_sensitive(bRet); + pSpellDialog->m_xAddToDictMB->set_sensitive(bRet); + pSpellDialog->m_xAddToDictPB->set_sensitive(bRet); return bRet; } - void SentenceEditWindow_Impl::MoveErrorMarkTo(sal_Int32 nStart, sal_Int32 nEnd, bool bGrammarError) { - TextEngine* pTextEngine = GetTextEngine(); - pTextEngine->RemoveAttribs( 0, sal_uInt16(TEXTATTR_FONTCOLOR) ); - pTextEngine->RemoveAttribs( 0, sal_uInt16(TEXTATTR_FONTWEIGHT) ); - pTextEngine->SetAttrib( TextAttribFontWeight(WEIGHT_BOLD), 0, nStart, nEnd ); - pTextEngine->SetAttrib( TextAttribFontColor(bGrammarError ? COL_LIGHTBLUE : COL_LIGHTRED), 0, nStart, nEnd ); + ESelection aAll(0, 0, 0, EE_TEXTPOS_ALL); + m_xEditEngine->RemoveAttribs(aAll, false, EE_CHAR_COLOR); + m_xEditEngine->RemoveAttribs(aAll, false, EE_CHAR_WEIGHT); + m_xEditEngine->RemoveAttribs(aAll, false, EE_CHAR_WEIGHT_CJK); + m_xEditEngine->RemoveAttribs(aAll, false, EE_CHAR_WEIGHT_CTL); + + SfxItemSet aSet(m_xEditEngine->GetEmptyItemSet()); + aSet.Put(SvxColorItem(bGrammarError ? COL_LIGHTBLUE : COL_LIGHTRED, EE_CHAR_COLOR)); + aSet.Put(SvxWeightItem(WEIGHT_BOLD, EE_CHAR_WEIGHT)); + aSet.Put(SvxWeightItem(WEIGHT_BOLD, EE_CHAR_WEIGHT_CJK)); + aSet.Put(SvxWeightItem(WEIGHT_BOLD, EE_CHAR_WEIGHT_CTL)); + + m_xEditEngine->QuickSetAttribs(aSet, ESelection(0, nStart, 0, nEnd)); + // so the editview will autoscroll to make this visible + m_xEdView->SetSelection(ESelection(0, nStart)); + Invalidate(); + m_nErrorStart = nStart; m_nErrorEnd = nEnd; } - -void SentenceEditWindow_Impl::ChangeMarkedWord(const OUString& rNewWord, LanguageType eLanguage) +int SentenceEditWindow_Impl::ChangeMarkedWord(const OUString& rNewWord, LanguageType eLanguage) { + std::vector<EECharAttrib> aAttribList; + m_xEditEngine->GetCharAttribs(0, aAttribList); + //calculate length changes - long nDiffLen = rNewWord.getLength() - m_nErrorEnd + m_nErrorStart; - TextSelection aSel(TextPaM(0, m_nErrorStart), TextPaM(0, m_nErrorEnd)); + auto nDiffLen = rNewWord.getLength() - m_nErrorEnd + m_nErrorStart; //Remove spell error attribute - ExtTextEngine* pTextEngine = GetTextEngine(); - pTextEngine->UndoActionStart(); - const TextCharAttrib* pErrorAttrib = pTextEngine->FindCharAttrib( TextPaM(0, m_nErrorStart), TEXTATTR_SPELL_ERROR ); - std::unique_ptr<TextCharAttrib> pReleasedErrorAttrib; - std::unique_ptr<TextCharAttrib> pReleasedLangAttrib; - std::unique_ptr<TextCharAttrib> pReleasedBackAttrib; + m_xEditEngine->UndoActionStart(SPELLUNDO_MOVE_ERROREND); + const EECharAttrib* pErrorAttrib = FindCharAttrib(m_nErrorStart, m_nErrorStart, EE_CHAR_GRABBAG, aAttribList); DBG_ASSERT(pErrorAttrib, "no error attribute found"); - const SpellErrorDescription* pSpellErrorDescription = nullptr; - if(pErrorAttrib) + bool bSpellErrorDescription = false; + SpellErrorDescription aSpellErrorDescription; + if (pErrorAttrib) { - pReleasedErrorAttrib = pTextEngine->RemoveAttrib(0, *pErrorAttrib); - pSpellErrorDescription = &static_cast<const SpellErrorAttrib&>(pErrorAttrib->GetAttr()).GetErrorDescription(); + ExtractErrorDescription(*pErrorAttrib, aSpellErrorDescription); + m_xEditEngine->RemoveAttribs(ESelection(0, pErrorAttrib->nStart, 0, pErrorAttrib->nEnd), false, EE_CHAR_GRABBAG); + bSpellErrorDescription = true; } - const TextCharAttrib* pBackAttrib = pTextEngine->FindCharAttrib( TextPaM(0, m_nErrorStart), TEXTATTR_SPELL_BACKGROUND ); - pTextEngine->ReplaceText( aSel, rNewWord ); - if(!m_nErrorStart) + const EECharAttrib* pBackAttrib = FindCharAttrib(m_nErrorStart, m_nErrorStart, EE_CHAR_BKGCOLOR, aAttribList); + + ESelection aSel(0, m_nErrorStart, 0, m_nErrorEnd); + m_xEditEngine->QuickInsertText(rNewWord, aSel); + + const sal_Int32 nTextLen = m_xEditEngine->GetTextLen(0); + + if (nDiffLen) + m_xEditEngine->GetCharAttribs(0, aAttribList); + + if (!m_nErrorStart) { //attributes following an error at the start of the text are not moved but expanded from the //text engine - this is done to keep full-paragraph-attributes //in the current case that handling is not desired - const TextCharAttrib* pLangAttrib = - pTextEngine->FindCharAttrib( - TextPaM(0, m_nErrorEnd), TEXTATTR_SPELL_LANGUAGE ); - const sal_Int32 nTextLen = pTextEngine->GetTextLen( 0 ); - if(pLangAttrib && !pLangAttrib->GetStart() && pLangAttrib->GetEnd() == - nTextLen) + const EECharAttrib* pLangAttrib = FindCharAttrib(m_nErrorEnd, m_nErrorEnd, EE_CHAR_LANGUAGE, aAttribList); + + if (pLangAttrib && !pLangAttrib->nStart && pLangAttrib->nEnd == nTextLen) { - SpellLanguageAttrib aNewLangAttrib( static_cast<const SpellLanguageAttrib&>(pLangAttrib->GetAttr()).GetLanguage()); - pReleasedLangAttrib = pTextEngine->RemoveAttrib(0, *pLangAttrib); - pTextEngine->SetAttrib( aNewLangAttrib, 0, m_nErrorEnd + nDiffLen, nTextLen ); + LanguageType eNewLanguage = static_cast<const SvxLanguageItem*>(pLangAttrib->pAttr)->GetLanguage(); + m_xEditEngine->RemoveAttribs(ESelection(0, pLangAttrib->nStart, 0, pLangAttrib->nEnd), false, EE_CHAR_LANGUAGE); + SetAttrib(SvxLanguageItem(eNewLanguage, EE_CHAR_LANGUAGE), m_nErrorEnd + nDiffLen, nTextLen); } } + // undo expanded attributes! - if( pBackAttrib && pBackAttrib->GetStart() < m_nErrorStart && pBackAttrib->GetEnd() == m_nErrorEnd + nDiffLen) + if (pBackAttrib && pBackAttrib->nStart < m_nErrorStart && pBackAttrib->nEnd == m_nErrorEnd + nDiffLen) { - std::unique_ptr<TextAttrib> pNewBackground(pBackAttrib->GetAttr().Clone()); - const sal_Int32 nStart = pBackAttrib->GetStart(); - pReleasedBackAttrib = pTextEngine->RemoveAttrib(0, *pBackAttrib); - pTextEngine->SetAttrib(*pNewBackground, 0, nStart, m_nErrorStart); + std::unique_ptr<SfxPoolItem> xNewBackground(pBackAttrib->pAttr->Clone()); + const sal_Int32 nStart = pBackAttrib->nStart; + + m_xEditEngine->RemoveAttribs(ESelection(0, pBackAttrib->nStart, 0, pBackAttrib->nEnd), false, EE_CHAR_BKGCOLOR); + + SetAttrib(*xNewBackground, nStart, m_nErrorStart); } - pTextEngine->SetModified(true); + m_xEditEngine->SetModified(); //adjust end position long nEndTemp = m_nErrorEnd; @@ -1700,48 +1832,56 @@ void SentenceEditWindow_Impl::ChangeMarkedWord(const OUString& rNewWord, Languag SPELLUNDO_MOVE_ERROREND, GetSpellDialog()->aDialogUndoLink)); pAction->SetOffset(nDiffLen); AddUndoAction(std::move(pAction)); - if(pSpellErrorDescription) - SetAttrib( SpellErrorAttrib(*pSpellErrorDescription), 0, m_nErrorStart, m_nErrorEnd ); - SetAttrib( SpellLanguageAttrib(eLanguage), 0, m_nErrorStart, m_nErrorEnd ); - pTextEngine->UndoActionEnd(); -} + if (bSpellErrorDescription) + { + SfxGrabBagItem aSpellErrorDescriptionItem(EE_CHAR_GRABBAG); + aSpellErrorDescriptionItem.GetGrabBag()["SpellErrorDescription"] <<= aSpellErrorDescription.toSequence(); + SetAttrib(aSpellErrorDescriptionItem, m_nErrorStart, m_nErrorEnd); + } + SetAttrib(SvxLanguageItem(eLanguage, EE_CHAR_LANGUAGE), m_nErrorStart, m_nErrorEnd); + m_xEditEngine->UndoActionEnd(); + Invalidate(); + + return nDiffLen; +} OUString SentenceEditWindow_Impl::GetErrorText() const { - return GetTextEngine()->GetText(TextSelection(TextPaM(0, m_nErrorStart), TextPaM(0, m_nErrorEnd) )); + return m_xEditEngine->GetText(ESelection(0, m_nErrorStart, 0, m_nErrorEnd)); } - -const SpellErrorDescription* SentenceEditWindow_Impl::GetAlternatives() +bool SentenceEditWindow_Impl::GetErrorDescription(SpellErrorDescription& rSpellErrorDescription, sal_Int32 nPosition) { - TextPaM aCursor(0, m_nErrorStart); - const SpellErrorAttrib* pAttrib = static_cast<const SpellErrorAttrib*>( - GetTextEngine()->FindAttrib( aCursor, TEXTATTR_SPELL_ERROR)); - return pAttrib ? &pAttrib->GetErrorDescription() : nullptr; + std::vector<EECharAttrib> aAttribList; + m_xEditEngine->GetCharAttribs(0, aAttribList); + + if (const EECharAttrib* pEECharAttrib = FindCharAttrib(nPosition, nPosition, EE_CHAR_GRABBAG, aAttribList)) + { + ExtractErrorDescription(*pEECharAttrib, rSpellErrorDescription); + return true; + } + + return false; } +bool SentenceEditWindow_Impl::GetAlternatives(SpellErrorDescription& rSpellErrorDescription) +{ + return GetErrorDescription(rSpellErrorDescription, m_nErrorStart); +} void SentenceEditWindow_Impl::RestoreCurrentError() { - TextPaM aCursor(0, m_nErrorStart); - const SpellErrorAttrib* pAttrib = static_cast<const SpellErrorAttrib*>( - GetTextEngine()->FindAttrib( aCursor, TEXTATTR_SPELL_ERROR)); - if( pAttrib ) + SpellErrorDescription aSpellErrorDescription; + if (GetErrorDescription(aSpellErrorDescription, m_nErrorStart)) { - const SpellErrorDescription& rDesc = pAttrib->GetErrorDescription(); - if( rDesc.sErrorText != GetErrorText() ) - ChangeMarkedWord(rDesc.sErrorText, LanguageTag::convertToLanguageType( rDesc.aLocale )); + if (aSpellErrorDescription.sErrorText != GetErrorText() ) + ChangeMarkedWord(aSpellErrorDescription.sErrorText, LanguageTag::convertToLanguageType(aSpellErrorDescription.aLocale)); } } - void SentenceEditWindow_Impl::SetAlternatives( const Reference< XSpellAlternatives>& xAlt ) { - TextPaM aCursor(0, m_nErrorStart); - DBG_ASSERT(static_cast<const SpellErrorAttrib*>( - GetTextEngine()->FindAttrib( aCursor, TEXTATTR_SPELL_ERROR)), "no error set?"); - OUString aWord; lang::Locale aLocale; uno::Sequence< OUString > aAlts; @@ -1756,22 +1896,25 @@ void SentenceEditWindow_Impl::SetAlternatives( const Reference< XSpellAlternativ sServiceName = xNamed->getName(); } SpellErrorDescription aDesc( false, aWord, aLocale, aAlts, nullptr); - GetTextEngine()->SetAttrib( SpellErrorAttrib(aDesc), 0, m_nErrorStart, m_nErrorEnd ); + SfxGrabBagItem aSpellErrorDescription(EE_CHAR_GRABBAG); + aSpellErrorDescription.GetGrabBag()["SpellErrorDescription"] <<= aDesc.toSequence(); + SetAttrib(aSpellErrorDescription, m_nErrorStart, m_nErrorEnd); } -void SentenceEditWindow_Impl::SetAttrib( const TextAttrib& rAttr, sal_uInt32 nPara, sal_Int32 nStart, sal_Int32 nEnd ) +void SentenceEditWindow_Impl::SetAttrib(const SfxPoolItem& rItem, sal_Int32 nStart, sal_Int32 nEnd) { - GetTextEngine()->SetAttrib(rAttr, nPara, nStart, nEnd); + SfxItemSet aSet(m_xEditEngine->GetEmptyItemSet()); + aSet.Put(rItem); + m_xEditEngine->QuickSetAttribs(aSet, ESelection(0, nStart, 0, nEnd)); + Invalidate(); } - void SentenceEditWindow_Impl::SetText( const OUString& rStr ) { m_nErrorStart = m_nErrorEnd = 0; - GetTextEngine()->SetText(rStr); + m_xEditEngine->SetText(rStr); } - struct LanguagePosition_Impl { sal_Int32 nPosition; @@ -1808,6 +1951,7 @@ static void lcl_InsertBreakPosition_Impl( } rBreakPositions.emplace_back(nInsert, eLanguage); } + /*------------------------------------------------------------------------- Returns the text in spell portions. Each portion contains text with an equal language and attribute. The spell alternatives are empty. @@ -1815,35 +1959,39 @@ static void lcl_InsertBreakPosition_Impl( svx::SpellPortions SentenceEditWindow_Impl::CreateSpellPortions() const { svx::SpellPortions aRet; - ExtTextEngine* pTextEngine = GetTextEngine(); - const sal_Int32 nTextLen = pTextEngine->GetTextLen(0); - if(nTextLen) + + const sal_Int32 nTextLen = m_xEditEngine->GetTextLen(0); + + std::vector<EECharAttrib> aAttribList; + m_xEditEngine->GetCharAttribs(0, aAttribList); + + if (nTextLen) { - TextPaM aCursor(0, 0); + int nCursor(0); LanguagePositions_Impl aBreakPositions; - const TextCharAttrib* pLastLang = nullptr; - const TextCharAttrib* pLastError = nullptr; + const EECharAttrib* pLastLang = nullptr; + const EECharAttrib* pLastError = nullptr; LanguageType eLang = LANGUAGE_DONTKNOW; - const TextCharAttrib* pError = nullptr; - while(aCursor.GetIndex() < nTextLen) + const EECharAttrib* pError = nullptr; + while (nCursor < nTextLen) { - const TextCharAttrib* pLang = pTextEngine->FindCharAttrib( aCursor, TEXTATTR_SPELL_LANGUAGE); + const EECharAttrib* pLang = FindCharAttrib(nCursor, nCursor, EE_CHAR_LANGUAGE, aAttribList); if(pLang && pLang != pLastLang) { - eLang = static_cast<const SpellLanguageAttrib&>(pLang->GetAttr()).GetLanguage(); - lcl_InsertBreakPosition_Impl(aBreakPositions, pLang->GetStart(), eLang); - lcl_InsertBreakPosition_Impl(aBreakPositions, pLang->GetEnd(), eLang); + eLang = static_cast<const SvxLanguageItem*>(pLang->pAttr)->GetLanguage(); + lcl_InsertBreakPosition_Impl(aBreakPositions, pLang->nStart, eLang); + lcl_InsertBreakPosition_Impl(aBreakPositions, pLang->nEnd, eLang); pLastLang = pLang; } - pError = pTextEngine->FindCharAttrib( aCursor, TEXTATTR_SPELL_ERROR); - if(pError && pLastError != pError) + pError = FindCharAttrib(nCursor, nCursor, EE_CHAR_GRABBAG, aAttribList); + if (pError && pLastError != pError) { - lcl_InsertBreakPosition_Impl(aBreakPositions, pError->GetStart(), eLang); - lcl_InsertBreakPosition_Impl(aBreakPositions, pError->GetEnd(), eLang); + lcl_InsertBreakPosition_Impl(aBreakPositions, pError->nStart, eLang); + lcl_InsertBreakPosition_Impl(aBreakPositions, pError->nEnd, eLang); pLastError = pError; } - ++aCursor.GetIndex(); + ++nCursor; } if (aBreakPositions.empty()) @@ -1851,11 +1999,10 @@ svx::SpellPortions SentenceEditWindow_Impl::CreateSpellPortions() const //if all content has been overwritten the attributes may have been removed, too svx::SpellPortion aPortion1; aPortion1.eLanguage = GetSpellDialog()->GetSelectedLang_Impl(); - aPortion1.sText = pTextEngine->GetText( - TextSelection(TextPaM(0, 0), TextPaM(0, nTextLen))); - aRet.push_back(aPortion1); + aPortion1.sText = m_xEditEngine->GetText(ESelection(0, 0, 0, nTextLen)); + aRet.push_back(aPortion1); } else { @@ -1870,8 +2017,9 @@ svx::SpellPortions SentenceEditWindow_Impl::CreateSpellPortions() const { svx::SpellPortion aPortion1; aPortion1.eLanguage = eLang; - aPortion1.sText = pTextEngine->GetText( - TextSelection(TextPaM(0, nStart), TextPaM(0, aStart->nPosition))); + + aPortion1.sText = m_xEditEngine->GetText(ESelection(0, nStart, 0, aStart->nPosition)); + bool bIsIgnoreError = m_aIgnoreErrorsAt.find( nStart ) != m_aIgnoreErrorsAt.end(); if( bIsIgnoreError ) { @@ -1884,17 +2032,17 @@ svx::SpellPortions SentenceEditWindow_Impl::CreateSpellPortions() const } } - // quick partly fix of #i71318. Correct fix needs to patch the TextEngine itself... + // quick partly fix of #i71318. Correct fix needs to patch the EditEngine itself... // this one will only prevent text from disappearing. It may to not have the // correct language and will probably not spell checked... - const sal_uInt32 nPara = pTextEngine->GetParagraphCount(); + const sal_uInt32 nPara = m_xEditEngine->GetParagraphCount(); if (nPara > 1) { OUStringBuffer aLeftOverText; for (sal_uInt32 i = 1; i < nPara; ++i) { aLeftOverText.append("\x0a"); // the manual line break... - aLeftOverText.append(pTextEngine->GetText(i)); + aLeftOverText.append(m_xEditEngine->GetText(i)); } if (pError) { // we need to add a new portion containing the left-over text @@ -1908,14 +2056,14 @@ svx::SpellPortions SentenceEditWindow_Impl::CreateSpellPortions() const aRet[ aRet.size() - 1 ].sText += aLeftOverText; } } - } + } + return aRet; } - void SentenceEditWindow_Impl::Undo() { - SfxUndoManager& rUndoMgr = GetTextEngine()->GetUndoManager(); + SfxUndoManager& rUndoMgr = m_xEditEngine->GetUndoManager(); DBG_ASSERT(GetUndoActionCount(), "no undo actions available" ); if(!GetUndoActionCount()) return; @@ -1932,39 +2080,34 @@ void SentenceEditWindow_Impl::Undo() GetSpellDialog()->UpdateBoxes_Impl(); } - void SentenceEditWindow_Impl::ResetUndo() { - GetTextEngine()->ResetUndo(); + SfxUndoManager& rUndo = m_xEditEngine->GetUndoManager(); + rUndo.Clear(); } - void SentenceEditWindow_Impl::AddUndoAction( std::unique_ptr<SfxUndoAction> pAction ) { - SfxUndoManager& rUndoMgr = GetTextEngine()->GetUndoManager(); + SfxUndoManager& rUndoMgr = m_xEditEngine->GetUndoManager(); rUndoMgr.AddUndoAction(std::move(pAction)); - GetSpellDialog()->m_pUndoPB->Enable(); + GetSpellDialog()->m_xUndoPB->set_sensitive(true); } - size_t SentenceEditWindow_Impl::GetUndoActionCount() { - return GetTextEngine()->GetUndoManager().GetUndoActionCount(); + return m_xEditEngine->GetUndoManager().GetUndoActionCount(); } - void SentenceEditWindow_Impl::UndoActionStart( sal_uInt16 nId ) { - GetTextEngine()->UndoActionStart(nId); + m_xEditEngine->UndoActionStart(nId); } - void SentenceEditWindow_Impl::UndoActionEnd() { - GetTextEngine()->UndoActionEnd(); + m_xEditEngine->UndoActionEnd(); } - void SentenceEditWindow_Impl::MoveErrorEnd(long nOffset) { // Shouldn't we always add the real signed value instead??? @@ -1975,44 +2118,47 @@ void SentenceEditWindow_Impl::MoveErrorEnd(long nOffset) } -void SentenceEditWindow_Impl::SetUndoEditMode(bool bSet) +void SentenceEditWindow_Impl::SetUndoEditMode(bool bSet) { DBG_ASSERT(!bSet || m_bIsUndoEditMode != bSet, "SetUndoEditMode with equal values?"); m_bIsUndoEditMode = bSet; //disable all buttons except the Change SpellDialog* pSpellDialog = GetSpellDialog(); - Control* aControls[] = + weld::Widget* aControls[] = { - pSpellDialog->m_pChangeAllPB, - pSpellDialog->m_pExplainFT, - pSpellDialog->m_pIgnoreAllPB, - pSpellDialog->m_pIgnoreRulePB, - pSpellDialog->m_pIgnorePB, - pSpellDialog->m_pSuggestionLB, - pSpellDialog->m_pSuggestionFT, - pSpellDialog->m_pLanguageFT, - pSpellDialog->m_pLanguageLB, - pSpellDialog->m_pAddToDictMB, - pSpellDialog->m_pAddToDictPB, - pSpellDialog->m_pAutoCorrPB, + pSpellDialog->m_xChangeAllPB.get(), + pSpellDialog->m_xExplainFT.get(), + pSpellDialog->m_xIgnoreAllPB.get(), + pSpellDialog->m_xIgnoreRulePB.get(), + pSpellDialog->m_xIgnorePB.get(), + pSpellDialog->m_xSuggestionLB.get(), + pSpellDialog->m_xSuggestionFT.get(), + pSpellDialog->m_xLanguageFT.get(), + pSpellDialog->m_xLanguageLB->get_widget(), + pSpellDialog->m_xAddToDictMB.get(), + pSpellDialog->m_xAddToDictPB.get(), + pSpellDialog->m_xAutoCorrPB.get(), nullptr }; sal_Int32 nIdx = 0; do { - aControls[nIdx]->Enable(false); + aControls[nIdx]->set_sensitive(false); } while(aControls[++nIdx]); //remove error marks - TextEngine* pTextEngine = GetTextEngine(); - pTextEngine->RemoveAttribs( 0, sal_uInt16(TEXTATTR_FONTCOLOR) ); - pTextEngine->RemoveAttribs( 0, sal_uInt16(TEXTATTR_FONTWEIGHT) ); + ESelection aAll(0, 0, 0, EE_TEXTPOS_ALL); + m_xEditEngine->RemoveAttribs(aAll, false, EE_CHAR_COLOR); + m_xEditEngine->RemoveAttribs(aAll, false, EE_CHAR_WEIGHT); + m_xEditEngine->RemoveAttribs(aAll, false, EE_CHAR_WEIGHT_CJK); + m_xEditEngine->RemoveAttribs(aAll, false, EE_CHAR_WEIGHT_CTL); + Invalidate(); //put the appropriate action on the Undo-stack AddUndoAction( std::make_unique<SpellUndoAction_Impl>( SPELLUNDO_UNDO_EDIT_MODE, GetSpellDialog()->aDialogUndoLink) ); - pSpellDialog->m_pChangePB->Enable(); + pSpellDialog->m_xChangePB->set_sensitive(true); } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/dialogs/cuicharmap.cxx b/cui/source/dialogs/cuicharmap.cxx index 61899ea50a8c..f8c38f589465 100644 --- a/cui/source/dialogs/cuicharmap.cxx +++ b/cui/source/dialogs/cuicharmap.cxx @@ -51,7 +51,7 @@ using namespace css; -SvxCharacterMap::SvxCharacterMap(weld::Window* pParent, const SfxItemSet* pSet, +SvxCharacterMap::SvxCharacterMap(weld::Widget* pParent, const SfxItemSet* pSet, const css::uno::Reference<css::frame::XFrame>& rFrame) : SfxDialogController(pParent, "cui/ui/specialcharacters.ui", "SpecialCharactersDialog") , m_xVirDev(VclPtr<VirtualDevice>::Create()) diff --git a/cui/source/factory/dlgfact.cxx b/cui/source/factory/dlgfact.cxx index af99be370a81..4ad9e49084fe 100644 --- a/cui/source/factory/dlgfact.cxx +++ b/cui/source/factory/dlgfact.cxx @@ -271,7 +271,15 @@ short AbstractLinksDialog_Impl::Execute() return m_xDlg->run(); } -IMPL_ABSTDLG_BASE(AbstractSpellDialog_Impl); +short AbstractSpellDialog_Impl::Execute() +{ + return m_xDlg->run(); +} + +bool AbstractSpellDialog_Impl::StartExecuteAsync(AsyncContext &rCtx) +{ + return SfxDialogController::runAsync(m_xDlg, rCtx.maEndDialogFn); +} short AbstractSvxPostItDialog_Impl::Execute() { @@ -524,19 +532,19 @@ const SfxItemSet* AbstractSvxZoomDialog_Impl::GetOutputItemSet() const return m_xDlg->GetOutputItemSet(); } -void AbstractSpellDialog_Impl::Invalidate() +void AbstractSpellDialog_Impl::InvalidateDialog() { - pDlg->InvalidateDialog(); + m_xDlg->InvalidateDialog(); } -vcl::Window* AbstractSpellDialog_Impl::GetWindow() +std::shared_ptr<SfxDialogController> AbstractSpellDialog_Impl::GetController() { - return pDlg; + return m_xDlg; } SfxBindings& AbstractSpellDialog_Impl::GetBindings() { - return pDlg->GetBindings(); + return m_xDlg->GetBindings(); } OUString AbstractTitleDialog_Impl::GetTitle() const @@ -1050,12 +1058,11 @@ VclPtr<AbstractSvxZoomDialog> AbstractDialogFactory_Impl::CreateSvxZoomDialog(we } VclPtr<AbstractSpellDialog> AbstractDialogFactory_Impl::CreateSvxSpellDialog( - vcl::Window* pParent, + weld::Window* pParent, SfxBindings* pBindings, - svx::SpellDialogChildWindow* pSpellChildWindow ) + svx::SpellDialogChildWindow* pSpellChildWindow) { - VclPtrInstance<svx::SpellDialog> pDlg(pSpellChildWindow, pParent, pBindings); - return VclPtr<AbstractSpellDialog_Impl>::Create(pDlg); + return VclPtr<AbstractSpellDialog_Impl>::Create(std::make_unique<svx::SpellDialog>(pSpellChildWindow, pParent, pBindings)); } VclPtr<VclAbstractDialog> AbstractDialogFactory_Impl::CreateActualizeProgressDialog(weld::Window* pParent, diff --git a/cui/source/factory/dlgfact.hxx b/cui/source/factory/dlgfact.hxx index ca07530a4f94..2f83409d2644 100644 --- a/cui/source/factory/dlgfact.hxx +++ b/cui/source/factory/dlgfact.hxx @@ -236,10 +236,16 @@ public: namespace svx{ class SpellDialog;} class AbstractSpellDialog_Impl : public AbstractSpellDialog { - public: - DECL_ABSTDLG_BASE(AbstractSpellDialog_Impl, svx::SpellDialog) - virtual void Invalidate() override; - virtual vcl::Window* GetWindow() override; + std::shared_ptr<svx::SpellDialog> m_xDlg; +public: + explicit AbstractSpellDialog_Impl(std::unique_ptr<svx::SpellDialog> p) + : m_xDlg(std::move(p)) + { + } + virtual short Execute() override; + virtual bool StartExecuteAsync(AsyncContext &rCtx) override; + virtual void InvalidateDialog() override; + virtual std::shared_ptr<SfxDialogController> GetController() override; virtual SfxBindings& GetBindings() override; }; @@ -750,7 +756,7 @@ public: const SdrView* pSdrView, bool bSizeTabPage) override; virtual VclPtr<AbstractSpellDialog> CreateSvxSpellDialog( - vcl::Window* pParent, + weld::Window* pParent, SfxBindings* pBindings, svx::SpellDialogChildWindow* pSpellChildWindow ) override; diff --git a/cui/source/factory/init.cxx b/cui/source/factory/init.cxx index eb3a99d2dfa5..87f3105a0875 100644 --- a/cui/source/factory/init.cxx +++ b/cui/source/factory/init.cxx @@ -23,10 +23,10 @@ // caution: needs C-Linkage since dynamically loaded via symbol name extern "C" { -SAL_DLLPUBLIC_EXPORT bool GetSpecialCharsForEdit(vcl::Window const * i_pParent, const vcl::Font& i_rFont, OUString& o_rResult) +SAL_DLLPUBLIC_EXPORT bool GetSpecialCharsForEdit(weld::Widget* i_pParent, const vcl::Font& i_rFont, OUString& o_rResult) { bool bRet = false; - SvxCharacterMap aDlg(i_pParent ? i_pParent->GetFrameWeld() : nullptr, nullptr, nullptr); + SvxCharacterMap aDlg(i_pParent, nullptr, nullptr); aDlg.DisableFontSelection(); aDlg.SetCharFont(i_rFont); if (aDlg.run() == RET_OK) diff --git a/cui/source/inc/SpellDialog.hxx b/cui/source/inc/SpellDialog.hxx index 83ea575f91f5..ee6d477ec279 100644 --- a/cui/source/inc/SpellDialog.hxx +++ b/cui/source/inc/SpellDialog.hxx @@ -37,6 +37,10 @@ #include <svl/lstner.hxx> #include <vcl/fixedhyper.hxx> #include <vcl/xtextedt.hxx> +#include <vcl/txtattr.hxx> +#include <vcl/customweld.hxx> +#include <editeng/editeng.hxx> +#include <editeng/editview.hxx> #include <editeng/SpellPortions.hxx> #include <set> @@ -55,39 +59,74 @@ namespace svx{ class SpellDialog; struct SpellErrorDescription; -class SentenceEditWindow_Impl : public VclMultiLineEdit +class SentenceEditWindow_Impl : public weld::CustomWidgetController + , public EditViewCallbacks { - using VclMultiLineEdit::SetText; - private: - std::set< sal_Int32 > m_aIgnoreErrorsAt; - VclPtr<ToolBox> m_xToolbar; + std::unique_ptr<EditEngine> m_xEditEngine; + std::unique_ptr<EditView> m_xEdView; + + std::set<sal_Int32> m_aIgnoreErrorsAt; + SpellDialog* m_pSpellDialog; + weld::Toolbar* m_pToolbar; sal_Int32 m_nErrorStart; sal_Int32 m_nErrorEnd; bool m_bIsUndoEditMode; - Link<Edit&,void> m_aModifyLink; + Link<LinkParamNone*,void> m_aModifyLink; + + void CallModifyLink() {m_aModifyLink.Call(nullptr); } - void CallModifyLink() {m_aModifyLink.Call(*this);} + SpellDialog* GetSpellDialog() const { return m_pSpellDialog; } - inline SpellDialog* GetSpellDialog() const; + bool GetErrorDescription(SpellErrorDescription& rSpellErrorDescription, sal_Int32 nPosition); + + DECL_LINK(ToolbarHdl, const OString&, void); - DECL_LINK(ToolbarHdl, ToolBox*, void); protected: - virtual bool PreNotify( NotifyEvent& rNEvt ) override; + virtual void Paint( vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect ) override; + virtual bool MouseMove( const MouseEvent& rMEvt ) override; + virtual bool MouseButtonDown( const MouseEvent& rMEvt ) override; + virtual bool MouseButtonUp( const MouseEvent& rMEvt ) override; + virtual bool KeyInput( const KeyEvent& rKEvt ) override; + virtual void Resize() override; + + virtual void EditViewInvalidate(const tools::Rectangle& rRect) const override + { + weld::DrawingArea* pDrawingArea = GetDrawingArea(); + pDrawingArea->queue_draw_area(rRect.Left(), rRect.Top(), rRect.GetWidth(), rRect.GetHeight()); + } + + virtual void EditViewSelectionChange() const override + { + weld::DrawingArea* pDrawingArea = GetDrawingArea(); + pDrawingArea->queue_draw(); + } + + virtual OutputDevice& EditViewOutputDevice() const override + { + return GetDrawingArea()->get_ref_device(); + } public: - SentenceEditWindow_Impl(vcl::Window* pParent, WinBits nBits); + SentenceEditWindow_Impl(); + virtual void SetDrawingArea(weld::DrawingArea* pDrawingArea) override; + void SetSpellDialog(SpellDialog* pDialog) { m_pSpellDialog = pDialog; } virtual ~SentenceEditWindow_Impl() override; - void Init(VclPtr<ToolBox> const &rToolbar); - void SetModifyHdl(const Link<Edit&,void>& rLink) override { m_aModifyLink = rLink;} + void Init(weld::Toolbar* pToolbar); + void SetModifyHdl(const Link<LinkParamNone*,void>& rLink) + { + m_aModifyLink = rLink; + m_xEditEngine->SetModifyHdl(m_aModifyLink); + } + + void SetAttrib(const SfxPoolItem& rItem, sal_Int32 nStart, sal_Int32 nEnd); - void SetAttrib( const TextAttrib& rAttr, sal_uInt32 nPara, sal_Int32 nStart, sal_Int32 nEnd ); - void SetText( const OUString& rStr ) override; + void SetText(const OUString& rStr); bool MarkNextError( bool bIgnoreCurrentError, const css::uno::Reference<css::linguistic2::XSpellChecker1>& ); - void ChangeMarkedWord(const OUString& rNewWord, LanguageType eLanguage); + int ChangeMarkedWord(const OUString& rNewWord, LanguageType eLanguage); void MoveErrorMarkTo(sal_Int32 nErrorStart, sal_Int32 nErrorEnd, bool bGrammar); OUString GetErrorText() const; void RestoreCurrentError(); @@ -95,12 +134,11 @@ public: void SetAlternatives( const css::uno::Reference<css::linguistic2::XSpellAlternatives>& ); - const SpellErrorDescription* GetAlternatives(); + bool GetAlternatives(SpellErrorDescription& rDesc); - - void ResetModified() { GetTextEngine()->SetModified(false); m_bIsUndoEditMode = false;} - virtual bool IsModified() const override { return GetTextEngine()->IsModified(); } - virtual void dispose() override; + void ClearModifyFlag() { m_xEditEngine->ClearModifyFlag(); } + void ResetModified() { ClearModifyFlag(); m_bIsUndoEditMode = false;} + bool IsModified() const { return m_xEditEngine->IsModified(); } bool IsUndoEditMode() const { return m_bIsUndoEditMode;} void SetUndoEditMode(bool bSet); @@ -122,42 +160,10 @@ public: // class SvxSpellDialog --------------------------------------------- class SpellDialogChildWindow; -class SpellDialog : public SfxModelessDialog +class SpellDialog : public SfxModelessDialogController { - using Window::Invalidate; - friend class SentenceEditWindow_Impl; private: - - VclPtr<FixedText> m_pLanguageFT; - VclPtr<SvxLanguageBox> m_pLanguageLB; - - VclPtr<FixedText> m_pExplainFT; - VclPtr<FixedHyperlink> m_pExplainLink; - - VclPtr<FixedText> m_pNotInDictFT; - VclPtr<SentenceEditWindow_Impl> m_pSentenceED; - - VclPtr<FixedText> m_pSuggestionFT; - VclPtr<ListBox> m_pSuggestionLB; - - VclPtr<PushButton> m_pIgnorePB; - VclPtr<PushButton> m_pIgnoreAllPB; - VclPtr<PushButton> m_pIgnoreRulePB; - VclPtr<PushButton> m_pAddToDictPB; - VclPtr<MenuButton> m_pAddToDictMB; - - VclPtr<PushButton> m_pChangePB; - VclPtr<PushButton> m_pChangeAllPB; - VclPtr<PushButton> m_pAutoCorrPB; - - VclPtr<CheckBox> m_pCheckGrammarCB; - - VclPtr<PushButton> m_pOptionsPB; - VclPtr<PushButton> m_pUndoPB; - VclPtr<CloseButton> m_pClosePB; - VclPtr<ToolBox> m_pToolbar; - OUString m_sResumeST; OUString m_sIgnoreOnceST; OUString m_sNoSuggestionsST; @@ -176,30 +182,58 @@ private: css::uno::Reference< css::linguistic2::XSpellChecker1 > xSpell; - DECL_LINK(ChangeHdl, Button*, void); - DECL_LINK(DoubleClickChangeHdl, ListBox&, void); - DECL_LINK(ChangeAllHdl, Button*, void); - DECL_LINK( IgnoreAllHdl, Button*, void ); - DECL_LINK(IgnoreHdl, Button*, void); - DECL_LINK( CheckGrammarHdl, Button*, void ); - DECL_LINK( ExtClickHdl, Button*, void ); - DECL_LINK(CancelHdl, Button*, void); - DECL_LINK( ModifyHdl, Edit&, void); - DECL_LINK(UndoHdl, Button*, void); - DECL_LINK( AddToDictSelectHdl, MenuButton*, void ); - DECL_LINK( AddToDictClickHdl, Button*, void ); - DECL_LINK( LanguageSelectHdl, ListBox&, void ); - DECL_LINK( DialogUndoHdl, SpellUndoAction_Impl&, void ); - - DECL_LINK( InitHdl, void*, void ); - - void AddToDictionaryExecute( sal_uInt16 ItemId, PopupMenu const *pMenu ); + std::unique_ptr<weld::Label> m_xAltTitle; + std::unique_ptr<weld::Label> m_xResumeFT; + std::unique_ptr<weld::Label> m_xNoSuggestionsFT; + std::unique_ptr<weld::Label> m_xIgnoreOnceFT; + std::unique_ptr<weld::Label> m_xLanguageFT; + std::unique_ptr<LanguageBox> m_xLanguageLB; + std::unique_ptr<weld::Label> m_xExplainFT; + std::unique_ptr<weld::LinkButton> m_xExplainLink; + std::unique_ptr<weld::Label> m_xNotInDictFT; + std::unique_ptr<SentenceEditWindow_Impl> m_xSentenceED; + std::unique_ptr<weld::Label> m_xSuggestionFT; + std::unique_ptr<weld::TreeView> m_xSuggestionLB; + std::unique_ptr<weld::Button> m_xIgnorePB; + std::unique_ptr<weld::Button> m_xIgnoreAllPB; + std::unique_ptr<weld::Button> m_xIgnoreRulePB; + std::unique_ptr<weld::Button> m_xAddToDictPB; + std::unique_ptr<weld::MenuButton> m_xAddToDictMB; + std::unique_ptr<weld::Button> m_xChangePB; + std::unique_ptr<weld::Button> m_xChangeAllPB; + std::unique_ptr<weld::Button> m_xAutoCorrPB; + std::unique_ptr<weld::CheckButton> m_xCheckGrammarCB; + std::unique_ptr<weld::Button> m_xOptionsPB; + std::unique_ptr<weld::Button> m_xUndoPB; + std::unique_ptr<weld::Button> m_xClosePB; + std::unique_ptr<weld::Toolbar> m_xToolbar; + std::unique_ptr<weld::CustomWeld> m_xSentenceEDWeld; + + DECL_LINK(ChangeHdl, weld::Button&, void); + DECL_LINK(DoubleClickChangeHdl, weld::TreeView&, void); + DECL_LINK(ChangeAllHdl, weld::Button&, void); + DECL_LINK(IgnoreAllHdl, weld::Button&, void); + DECL_LINK(IgnoreHdl, weld::Button&, void); + DECL_LINK(CheckGrammarHdl, weld::Button&, void); + DECL_LINK(ExtClickHdl, weld::Button&, void); + DECL_LINK(CancelHdl, weld::Button&, void); + DECL_LINK(ModifyHdl, LinkParamNone*, void); + DECL_LINK(UndoHdl, weld::Button&, void); + DECL_LINK(AddToDictSelectHdl, const OString&, void); + DECL_LINK(AddToDictClickHdl, weld::Button&, void); + DECL_LINK(LanguageSelectHdl, weld::ComboBox&, void); + DECL_LINK(DialogUndoHdl, SpellUndoAction_Impl&, void); + + DECL_LINK(InitHdl, void*, void); + + void AddToDictionaryExecute(const OString& rItemId); void StartSpellOptDlg_Impl(); int InitUserDicts(); void UpdateBoxes_Impl(bool bCallFromSelectHdl = false); void Init_Impl(); void SpellContinue_Impl(bool UseSavedSentence = false, bool bIgnoreCurrentError = false ); void LockFocusChanges( bool bLock ) {bFocusLocked = bLock;} + void ToplevelFocusChanged(); void Impl_Restore(bool bUseSavedSentence); LanguageType GetSelectedLang_Impl() const; @@ -213,25 +247,24 @@ private: void SetTitle_Impl(LanguageType nLang); protected: - virtual bool EventNotify( NotifyEvent& rNEvt ) override; OUString getReplacementString() const; public: SpellDialog( svx::SpellDialogChildWindow* pChildWindow, - vcl::Window * pParent, + weld::Window * pParent, SfxBindings* pBindings); virtual ~SpellDialog() override; - virtual void dispose() override; - virtual bool Close() override; + virtual void Activate() override; + virtual void Deactivate() override; + + virtual void Close() override; void InvalidateDialog(); }; -SpellDialog* SentenceEditWindow_Impl::GetSpellDialog() const {return static_cast<SpellDialog*>(GetParentDialog());} - } //namespace svx #endif diff --git a/cui/uiconfig/ui/spellingdialog.ui b/cui/uiconfig/ui/spellingdialog.ui index a1046a7d76bb..2019f3200f2d 100644 --- a/cui/uiconfig/ui/spellingdialog.ui +++ b/cui/uiconfig/ui/spellingdialog.ui @@ -1,14 +1,40 @@ <?xml version="1.0" encoding="UTF-8"?> -<!-- Generated with glade 3.19.0 --> +<!-- Generated with glade 3.22.1 --> <interface domain="cui"> <requires lib="gtk+" version="3.18"/> - <requires lib="LibreOffice" version="1.0"/> + <object class="GtkMenu" id="addmenu"> + <property name="visible">True</property> + <property name="can_focus">False</property> + </object> + <object class="GtkTreeStore" id="liststore1"> + <columns> + <!-- column-name text --> + <column type="gchararray"/> + <!-- column-name id --> + <column type="gchararray"/> + </columns> + </object> + <object class="GtkListStore" id="liststore6"> + <columns> + <!-- column-name text --> + <column type="gchararray"/> + <!-- column-name id --> + <column type="gchararray"/> + <!-- column-name image --> + <column type="GdkPixbuf"/> + </columns> + </object> <object class="GtkDialog" id="SpellingDialog"> <property name="can_focus">False</property> <property name="border_width">6</property> <property name="title" translatable="yes" context="spellingdialog|SpellingDialog">Spelling: $LANGUAGE ($LOCATION)</property> <property name="resizable">False</property> + <property name="default_width">0</property> + <property name="default_height">0</property> <property name="type_hint">dialog</property> + <child> + <placeholder/> + </child> <child internal-child="vbox"> <object class="GtkBox" id="dialog-vbox1"> <property name="can_focus">False</property> @@ -95,10 +121,25 @@ <property name="row_spacing">6</property> <property name="column_spacing">12</property> <child> - <object class="svxcorelo-SvxLanguageBox" id="languagelb"> + <object class="GtkComboBox" id="languagelb"> <property name="visible">True</property> <property name="can_focus">False</property> <property name="halign">end</property> + <property name="model">liststore6</property> + <property name="entry_text_column">0</property> + <property name="id_column">1</property> + <child> + <object class="GtkCellRendererText" id="cellrenderertext9"/> + <attributes> + <attribute name="text">0</attribute> + </attributes> + </child> + <child> + <object class="GtkCellRendererPixbuf" id="cellrenderertext6"/> + <attributes> + <attribute name="pixbuf">2</attribute> + </attributes> + </child> </object> <packing> <property name="left_attach">1</property> @@ -120,20 +161,6 @@ </packing> </child> <child> - <object class="cuilo-SentenceEditWindow" id="sentence"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="hexpand">True</property> - <property name="vexpand">True</property> - </object> - <packing> - <property name="left_attach">0</property> - <property name="top_attach">3</property> - <property name="width">2</property> - <property name="height">5</property> - </packing> - </child> - <child> <object class="GtkButton" id="change"> <property name="label" translatable="yes" context="spellingdialog|change">Co_rrect</property> <property name="visible">True</property> @@ -298,24 +325,6 @@ </packing> </child> <child> - <object class="GtkTreeView" id="suggestionslb"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="hexpand">True</property> - <property name="vexpand">True</property> - <property name="show_expanders">False</property> - <child internal-child="selection"> - <object class="GtkTreeSelection" id="treeview-selection1"/> - </child> - </object> - <packing> - <property name="left_attach">0</property> - <property name="top_attach">9</property> - <property name="width">2</property> - <property name="height">3</property> - </packing> - </child> - <child> <object class="GtkButton" id="add"> <property name="label" translatable="yes" context="spellingdialog|add">_Add to Dictionary</property> <property name="visible">True</property> @@ -330,13 +339,18 @@ </packing> </child> <child> - <object class="GtkButton" id="addmb:addmenu"> + <object class="GtkMenuButton" id="addmb"> <property name="label" translatable="yes" context="spellingdialog|addmb">_Add to Dictionary</property> <property name="can_focus">True</property> <property name="receives_default">True</property> <property name="no_show_all">True</property> <property name="valign">center</property> <property name="use_underline">True</property> + <property name="popup">addmenu</property> + <property name="use_popover">False</property> + <child> + <placeholder/> + </child> </object> <packing> <property name="left_attach">2</property> @@ -383,7 +397,6 @@ <object class="GtkToolButton" id="paste"> <property name="visible">True</property> <property name="can_focus">False</property> - <property name="action_name">paste</property> <property name="label" translatable="yes" context="spellingdialog|paste">Paste</property> <property name="use_underline">True</property> <property name="icon_name">cmd/sc_paste.png</property> @@ -397,7 +410,6 @@ <object class="GtkToolButton" id="insert"> <property name="visible">True</property> <property name="can_focus">False</property> - <property name="action_name">insert</property> <property name="label" translatable="yes" context="spellingdialog|insert">Special Character</property> <property name="use_underline">True</property> <property name="icon_name">cmd/sc_insertsymbol.png</property> @@ -414,6 +426,73 @@ </packing> </child> <child> + <object class="GtkScrolledWindow"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="border_width">0</property> + <property name="shadow_type">in</property> + <child> + <object class="GtkViewport"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <child> + <object class="GtkDrawingArea" id="sentence"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="events">GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_FOCUS_CHANGE_MASK | GDK_STRUCTURE_MASK</property> + </object> + </child> + </object> + </child> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">3</property> + <property name="width">2</property> + <property name="height">5</property> + </packing> + </child> + <child> + <object class="GtkScrolledWindow"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="hexpand">True</property> + <property name="vexpand">True</property> + <property name="shadow_type">in</property> + <child> + <object class="GtkTreeView" id="suggestionslb"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="hexpand">True</property> + <property name="vexpand">True</property> + <property name="model">liststore1</property> + <property name="headers_visible">False</property> + <property name="show_expanders">False</property> + <child internal-child="selection"> + <object class="GtkTreeSelection" id="treeview-selection1"/> + </child> + <child> + <object class="GtkTreeViewColumn" id="treeviewcolumn2"> + <property name="spacing">6</property> + <child> + <object class="GtkCellRendererText" id="cellrenderertext2"/> + <attributes> + <attribute name="text">0</attribute> + </attributes> + </child> + </object> + </child> + </object> + </child> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">9</property> + <property name="width">2</property> + <property name="height">3</property> + </packing> + </child> + <child> <placeholder/> </child> <child> @@ -435,8 +514,4 @@ <action-widget response="-7">close</action-widget> </action-widgets> </object> - <object class="GtkMenu" id="addmenu"> - <property name="visible">True</property> - <property name="can_focus">False</property> - </object> </interface> diff --git a/extras/source/glade/libreoffice-catalog.xml.in b/extras/source/glade/libreoffice-catalog.xml.in index bdfd89cf081c..ed9f543a4c93 100644 --- a/extras/source/glade/libreoffice-catalog.xml.in +++ b/extras/source/glade/libreoffice-catalog.xml.in @@ -27,9 +27,6 @@ <glade-widget-class title="Search Results Box" name="sfxlo-SearchResultsBox" generic-name="SearchResultsBox" parent="GtkComboBoxText" icon-name="widget-gtk-comboboxtext"/> - <glade-widget-class title="Spelling View" name="cuilo-SentenceEditWindow" - generic-name="SentenceEditWindow" parent="GtkTextView" - icon-name="widget-gtk-textview"/> <glade-widget-class title="Condition Edit" name="rptuilo-ConditionField" generic-name="ConditionEdit" parent="GtkEntry" icon-name="widget-gtk-comboboxtext"/> diff --git a/include/cui/cuicharmap.hxx b/include/cui/cuicharmap.hxx index c69107bf9d1b..fbe9b11f369e 100644 --- a/include/cui/cuicharmap.hxx +++ b/include/cui/cuicharmap.hxx @@ -143,7 +143,7 @@ private: void selectCharByCode(Radix radix); public: - SvxCharacterMap(weld::Window* pParent, const SfxItemSet* pSet, + SvxCharacterMap(weld::Widget* pParent, const SfxItemSet* pSet, const css::uno::Reference<css::frame::XFrame>& rFrame); virtual short run() override; diff --git a/include/sfx2/basedlgs.hxx b/include/sfx2/basedlgs.hxx index 4edf52e46f04..bbcaef188f4d 100644 --- a/include/sfx2/basedlgs.hxx +++ b/include/sfx2/basedlgs.hxx @@ -96,8 +96,7 @@ class SFX2_DLLPUBLIC SfxDialogController : public weld::GenericDialogController private: DECL_DLLPRIVATE_STATIC_LINK(SfxDialogController, InstallLOKNotifierHdl, void*, vcl::ILibreOfficeKitNotifier*); - DECL_DLLPRIVATE_LINK(FocusInHdl, weld::Widget&, void); - DECL_DLLPRIVATE_LINK(FocusOutHdl, weld::Widget&, void); + DECL_DLLPRIVATE_LINK(FocusChangeHdl, weld::Widget&, void); public: SfxDialogController(weld::Widget* pParent, const OUString& rUIFile, const OString& rDialogId); diff --git a/include/svx/ClassificationEditView.hxx b/include/svx/ClassificationEditView.hxx index 7c7070e8a2fd..f3ce3b9cb58e 100644 --- a/include/svx/ClassificationEditView.hxx +++ b/include/svx/ClassificationEditView.hxx @@ -28,8 +28,8 @@ public: virtual OUString CalcFieldValue(const SvxFieldItem& rField, sal_Int32 nPara, sal_Int32 nPos, boost::optional<Color>& rTxtColor, boost::optional<Color>& rFldColor) override; }; -class SVX_DLLPUBLIC ClassificationEditView : public weld::CustomWidgetController, - public EditViewCallbacks +class SVX_DLLPUBLIC ClassificationEditView : public weld::CustomWidgetController + , public EditViewCallbacks { public: ClassificationEditView(); diff --git a/include/svx/langbox.hxx b/include/svx/langbox.hxx index 9232ce898c49..1ba876c4a93e 100644 --- a/include/svx/langbox.hxx +++ b/include/svx/langbox.hxx @@ -170,7 +170,7 @@ public: int find_text(const OUString& rStr) const { return m_xControl->find_text(rStr); } OUString get_text(int nPos) const { return m_xControl->get_text(nPos); } int get_count() const { return m_xControl->get_count(); } - const weld::ComboBox* get_widget() const { return m_xControl.get(); } + weld::ComboBox* get_widget() { return m_xControl.get(); } }; class SVX_DLLPUBLIC SvxLanguageComboBox : public ComboBox, public SvxLanguageBoxBase diff --git a/include/svx/svxdlg.hxx b/include/svx/svxdlg.hxx index e5307196038c..781eafd506a3 100644 --- a/include/svx/svxdlg.hxx +++ b/include/svx/svxdlg.hxx @@ -99,8 +99,8 @@ class AbstractSpellDialog : public VclAbstractDialog protected: virtual ~AbstractSpellDialog() override = default; public: - virtual void Invalidate() = 0; - virtual vcl::Window* GetWindow() = 0; + virtual void InvalidateDialog() = 0; + virtual std::shared_ptr<SfxDialogController> GetController() = 0; virtual SfxBindings& GetBindings() = 0; }; @@ -352,7 +352,7 @@ public: virtual VclPtr<AbstractSvxZoomDialog> CreateSvxZoomDialog(weld::Window* pParent, const SfxItemSet& rCoreSet) = 0; - virtual VclPtr<AbstractSpellDialog> CreateSvxSpellDialog(vcl::Window* pParent, + virtual VclPtr<AbstractSpellDialog> CreateSvxSpellDialog(weld::Window* pParent, SfxBindings* pBindings, svx::SpellDialogChildWindow* pSpellChildWindow )=0; diff --git a/include/vcl/edit.hxx b/include/vcl/edit.hxx index caf759789bef..bc18f3a412e6 100644 --- a/include/vcl/edit.hxx +++ b/include/vcl/edit.hxx @@ -50,7 +50,7 @@ struct Impl_IMEInfos; #define EDIT_NOLIMIT SAL_MAX_INT32 #define EDIT_UPDATEDATA_TIMEOUT 350 -typedef OUString (*FncGetSpecialChars)( vcl::Window* pWin, const vcl::Font& rFont ); +typedef OUString (*FncGetSpecialChars)( weld::Widget* pWin, const vcl::Font& rFont ); class VCL_DLLPUBLIC TextFilter { diff --git a/include/vcl/weld.hxx b/include/vcl/weld.hxx index 7393131fea14..35e645af2467 100644 --- a/include/vcl/weld.hxx +++ b/include/vcl/weld.hxx @@ -337,6 +337,9 @@ class VCL_DLLPUBLIC Window : virtual public Container { protected: Link<Widget&, bool> m_aHelpRequestHdl; + Link<Widget&, void> m_aTopLevelFocusChangedHdl; + + void signal_toplevel_focus_changed() { m_aTopLevelFocusChangedHdl.Call(*this); } public: virtual void set_title(const OUString& rTitle) = 0; @@ -367,6 +370,10 @@ public: virtual css::uno::Reference<css::awt::XWindow> GetXWindow() = 0; void connect_help(const Link<Widget&, bool>& rLink) { m_aHelpRequestHdl = rLink; } + virtual void connect_toplevel_focus_changed(const Link<Widget&, void>& rLink) + { + m_aTopLevelFocusChangedHdl = rLink; + } virtual SystemEnvData get_system_data() const = 0; @@ -1007,9 +1014,11 @@ public: virtual void insert_separator(int pos, const OUString& rId) = 0; void append_separator(const OUString& rId) { insert_separator(-1, rId); } virtual void remove_item(const OString& rId) = 0; + virtual void clear() = 0; virtual void set_item_sensitive(const OString& rIdent, bool bSensitive) = 0; virtual void set_item_active(const OString& rIdent, bool bActive) = 0; virtual void set_item_label(const OString& rIdent, const OUString& rLabel) = 0; + virtual OUString get_item_label(const OString& rIdent) const = 0; virtual void set_item_help_id(const OString& rIdent, const OString& rHelpId) = 0; virtual void set_item_visible(const OString& rIdent, bool bVisible) = 0; virtual OString get_item_help_id(const OString& rIdent) const = 0; @@ -1096,6 +1105,7 @@ public: virtual void set_max_length(int nChars) = 0; // nEndPos can be -1 in order to select all text virtual void select_region(int nStartPos, int nEndPos) = 0; + // returns true if the selection has nonzero length virtual bool get_selection_bounds(int& rStartPos, int& rEndPos) = 0; virtual void replace_selection(const OUString& rText) = 0; // nCursorPos can be -1 to set to the end diff --git a/sc/source/ui/inc/spelleng.hxx b/sc/source/ui/inc/spelleng.hxx index cec0676459a2..2add81559567 100644 --- a/sc/source/ui/inc/spelleng.hxx +++ b/sc/source/ui/inc/spelleng.hxx @@ -28,6 +28,8 @@ class ScDocShell; class ScDocument; class SfxItemPool; +namespace weld { class Window; } + /** Base class for special type of edit engines, i.e. for spell checker and text conversion. */ class ScConversionEngineBase : public ScEditEngineDefaulter { @@ -119,7 +121,7 @@ protected: private: /** Returns the spelling dialog if it is open. */ - vcl::Window* GetDialogParent(); + weld::Window* GetDialogParent(); }; /** Edit engine for text conversion. */ diff --git a/sc/source/ui/view/cellsh.cxx b/sc/source/ui/view/cellsh.cxx index 26020a86ef4f..3d21cd96d3c3 100644 --- a/sc/source/ui/view/cellsh.cxx +++ b/sc/source/ui/view/cellsh.cxx @@ -1209,8 +1209,8 @@ void ScCellShell::GetState(SfxItemSet &rSet) if ( pViewFrame && pViewFrame->HasChildWindow( nWhich ) ) { SfxChildWindow* pChild = pViewFrame->GetChildWindow( nWhich ); - vcl::Window* pWin = ( pChild ? pChild->GetWindow() : nullptr ); - if ( pWin && pWin->IsVisible() ) + std::shared_ptr<SfxDialogController> xController = pChild ? pChild->GetController() : nullptr; + if (xController && xController->getDialog()->get_visible()) { bVisible = true; } diff --git a/sc/source/ui/view/spelleng.cxx b/sc/source/ui/view/spelleng.cxx index 49c076cd420e..af1ea81d735b 100644 --- a/sc/source/ui/view/spelleng.cxx +++ b/sc/source/ui/view/spelleng.cxx @@ -305,10 +305,10 @@ bool ScSpellingEngine::NeedsConversion() bool ScSpellingEngine::ShowTableWrapDialog() { - vcl::Window* pParent = GetDialogParent(); - ScWaitCursorOff aWaitOff( pParent ); + weld::Window* pParent = GetDialogParent(); + weld::WaitObject aWaitOff(pParent); - std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(pParent ? pParent->GetFrameWeld() : nullptr, + std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(pParent, VclMessageType::Question, VclButtonsType::YesNo, ScResId(STR_SPELLING_BEGIN_TAB))); // "delete data?" xBox->set_title(ScResId(STR_MSSG_DOSUBTOTALS_0)); @@ -318,26 +318,37 @@ bool ScSpellingEngine::ShowTableWrapDialog() void ScSpellingEngine::ShowFinishDialog() { - vcl::Window* pParent = GetDialogParent(); - ScWaitCursorOff aWaitOff( pParent ); - std::unique_ptr<weld::MessageDialog> xInfoBox(Application::CreateMessageDialog(pParent ? pParent->GetFrameWeld() : nullptr, + weld::Window* pParent = GetDialogParent(); + weld::WaitObject aWaitOff(pParent); + std::unique_ptr<weld::MessageDialog> xInfoBox(Application::CreateMessageDialog(pParent, VclMessageType::Info, VclButtonsType::Ok, ScResId(STR_SPELLING_STOP_OK))); xInfoBox->run(); } -vcl::Window* ScSpellingEngine::GetDialogParent() +weld::Window* ScSpellingEngine::GetDialogParent() { sal_uInt16 nWinId = ScSpellDialogChildWindow::GetChildWindowId(); SfxViewFrame* pViewFrm = mrViewData.GetViewShell()->GetViewFrame(); if( pViewFrm->HasChildWindow( nWinId ) ) + { if( SfxChildWindow* pChild = pViewFrm->GetChildWindow( nWinId ) ) - if( vcl::Window* pWin = pChild->GetWindow() ) - if( pWin->IsVisible() ) - return pWin; + { + auto xController = pChild->GetController(); + if (xController) + { + if (weld::Window *pRet = xController->getDialog()) + { + if (pRet->get_visible()) + return pRet; + } + } + } + } // fall back to standard dialog parent - return ScDocShell::GetActiveDialogParent(); + vcl::Window* pWin = ScDocShell::GetActiveDialogParent(); + return pWin ? pWin->GetFrameWeld() : nullptr; } ScConversionParam::ScConversionParam( ScConversionType eConvType ) : diff --git a/sd/inc/Outliner.hxx b/sd/inc/Outliner.hxx index 5f4056fdb556..47c3b5d95784 100644 --- a/sd/inc/Outliner.hxx +++ b/sd/inc/Outliner.hxx @@ -30,6 +30,10 @@ class SdrObject; class SdrTextObj; class SdDrawDocument; +namespace weld { +class Window; +} + namespace sd { class View; @@ -516,7 +520,7 @@ private: that the otherwise non-modal search or spell dialogs, if visible, are locked, too. */ - VclPtr<vcl::Window> GetMessageBoxParent(); + weld::Window* GetMessageBoxParent(); }; #endif diff --git a/sd/source/ui/view/Outliner.cxx b/sd/source/ui/view/Outliner.cxx index a98ad3cd0065..a91d5f70d5d4 100644 --- a/sd/source/ui/view/Outliner.cxx +++ b/sd/source/ui/view/Outliner.cxx @@ -1205,8 +1205,8 @@ void SdOutliner::ShowEndOfSearchDialog() aString = SdResId(STR_END_SPELLING); // Show the message in an info box that is modal with respect to the whole application. - VclPtr<vcl::Window> xParent(GetMessageBoxParent()); - std::unique_ptr<weld::MessageDialog> xInfoBox(Application::CreateMessageDialog(xParent ? xParent->GetFrameWeld() : nullptr, + weld::Window* pParent = GetMessageBoxParent(); + std::unique_ptr<weld::MessageDialog> xInfoBox(Application::CreateMessageDialog(pParent, VclMessageType::Info, VclButtonsType::Ok, aString)); xInfoBox->run(); } @@ -1246,8 +1246,8 @@ bool SdOutliner::ShowWrapArroundDialog() // Pop up question box that asks the user whether to wrap around. // The dialog is made modal with respect to the whole application. - VclPtr<vcl::Window> xParent(GetMessageBoxParent()); - std::unique_ptr<weld::MessageDialog> xQueryBox(Application::CreateMessageDialog(xParent ? xParent->GetFrameWeld() : nullptr, + weld::Window* pParent = GetMessageBoxParent(); + std::unique_ptr<weld::MessageDialog> xQueryBox(Application::CreateMessageDialog(pParent, VclMessageType::Question, VclButtonsType::YesNo, SdResId(pStringId))); sal_uInt16 nBoxResult = xQueryBox->run(); @@ -1691,7 +1691,7 @@ bool SdOutliner::ConvertNextDocument() return !mbEndOfSearch; } -VclPtr<vcl::Window> SdOutliner::GetMessageBoxParent() +weld::Window* SdOutliner::GetMessageBoxParent() { // We assume that the parent of the given message box is NULL, i.e. it is // modal with respect to the top application window. However, this @@ -1699,7 +1699,7 @@ VclPtr<vcl::Window> SdOutliner::GetMessageBoxParent() // while the message box is being shown. We also have to take into // account that we are called during a spell check and the search dialog // is not available. - vcl::Window* pSearchDialog = nullptr; + weld::Window* pSearchDialog = nullptr; SfxChildWindow* pChildWindow = nullptr; switch (meMode) { @@ -1720,13 +1720,17 @@ VclPtr<vcl::Window> SdOutliner::GetMessageBoxParent() } if (pChildWindow != nullptr) - pSearchDialog = pChildWindow->GetWindow(); + { + auto xController = pChildWindow->GetController(); + pSearchDialog = xController ? xController->getDialog() : nullptr; + } if (pSearchDialog) return pSearchDialog; std::shared_ptr<sd::ViewShell> pViewShell (mpWeakViewShell.lock()); - return pViewShell->GetActiveWindow(); + auto pWin = pViewShell->GetActiveWindow(); + return pWin ? pWin->GetFrameWeld() : nullptr; } //===== SdOutliner::Implementation ============================================== diff --git a/sfx2/source/appl/appinit.cxx b/sfx2/source/appl/appinit.cxx index 543200717c87..89e1ea98d197 100644 --- a/sfx2/source/appl/appinit.cxx +++ b/sfx2/source/appl/appinit.cxx @@ -142,7 +142,7 @@ Sequence< OUString > SAL_CALL SfxTerminateListener_Impl::getSupportedServiceName } -typedef bool ( *PFunc_getSpecialCharsForEdit)( vcl::Window const * i_pParent, const vcl::Font& i_rFont, OUString& o_rOutString ); +typedef bool (*PFunc_getSpecialCharsForEdit)(weld::Widget* i_pParent, const vcl::Font& i_rFont, OUString& o_rOutString); // Lazy binding of the GetSpecialCharsForEdit function as it resides in @@ -155,11 +155,11 @@ extern "C" { static void thisModule() {} } #else -extern "C" bool GetSpecialCharsForEdit( vcl::Window const * i_pParent, const vcl::Font& i_rFont, OUString& o_rOutString ); +extern "C" bool GetSpecialCharsForEdit(weld::Widget* i_pParent, const vcl::Font& i_rFont, OUString& o_rOutString); #endif -static OUString SfxGetSpecialCharsForEdit(vcl::Window* pParent, const vcl::Font& rFont) +static OUString SfxGetSpecialCharsForEdit(weld::Widget* pParent, const vcl::Font& rFont) { static bool bDetermineFunction = false; static PFunc_getSpecialCharsForEdit pfunc_getSpecialCharsForEdit = nullptr; diff --git a/sfx2/source/dialog/basedlgs.cxx b/sfx2/source/dialog/basedlgs.cxx index f902196eccbe..e1f74636c58f 100644 --- a/sfx2/source/dialog/basedlgs.cxx +++ b/sfx2/source/dialog/basedlgs.cxx @@ -386,9 +386,12 @@ void SfxModelessDialogController::Init(SfxBindings *pBindinx, SfxChildWindow *pC If a ModelessDialog is enabled its ViewFrame will be activated. This is necessary by PluginInFrames. */ -IMPL_LINK_NOARG(SfxDialogController, FocusInHdl, weld::Widget&, void) +IMPL_LINK_NOARG(SfxDialogController, FocusChangeHdl, weld::Widget&, void) { - Activate(); + if (m_xDialog->has_toplevel_focus()) + Activate(); + else + Deactivate(); } void SfxModelessDialogController::Activate() @@ -399,11 +402,6 @@ void SfxModelessDialogController::Activate() m_xImpl->pMgr->Activate_Impl(); } -IMPL_LINK_NOARG(SfxDialogController, FocusOutHdl, weld::Widget&, void) -{ - Deactivate(); -} - void SfxModelessDialogController::Deactivate() { if (!m_xImpl) @@ -676,8 +674,7 @@ SfxDialogController::SfxDialogController(weld::Widget* pParent, const OUString& : GenericDialogController(pParent, rUIFile, rDialogId) { m_xDialog->SetInstallLOKNotifierHdl(LINK(this, SfxDialogController, InstallLOKNotifierHdl)); - m_xDialog->connect_focus_in(LINK(this, SfxDialogController, FocusInHdl)); - m_xDialog->connect_focus_out(LINK(this, SfxDialogController, FocusOutHdl)); + m_xDialog->connect_toplevel_focus_changed(LINK(this, SfxDialogController, FocusChangeHdl)); } IMPL_STATIC_LINK_NOARG(SfxDialogController, InstallLOKNotifierHdl, void*, vcl::ILibreOfficeKitNotifier*) diff --git a/solenv/bin/native-code.py b/solenv/bin/native-code.py index 9ebf741a88b9..d8b940d9efa0 100755 --- a/solenv/bin/native-code.py +++ b/solenv/bin/native-code.py @@ -485,7 +485,6 @@ custom_widgets = [ 'SdPageObjsTLB', 'SearchBox', 'SearchResultsBox', - 'SentenceEditWindow', 'ShowNupOrderWindow', 'ShowNupOrderWindow', 'SidebarDialControl', diff --git a/svx/source/dialog/SpellDialogChildWindow.cxx b/svx/source/dialog/SpellDialogChildWindow.cxx index 51bd2fc6d26b..ae82769dfb9b 100644 --- a/svx/source/dialog/SpellDialogChildWindow.cxx +++ b/svx/source/dialog/SpellDialogChildWindow.cxx @@ -32,10 +32,10 @@ SpellDialogChildWindow::SpellDialogChildWindow ( : SfxChildWindow (_pParent, nId) { SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create(); - m_xAbstractSpellDialog = pFact->CreateSvxSpellDialog(_pParent, + m_xAbstractSpellDialog = pFact->CreateSvxSpellDialog(_pParent->GetFrameWeld(), pBindings, this ); - SetWindow( m_xAbstractSpellDialog->GetWindow() ); + SetController(m_xAbstractSpellDialog->GetController()); SetHideNotDelete(true); } @@ -54,7 +54,7 @@ void SpellDialogChildWindow::InvalidateSpellDialog() { OSL_ASSERT (m_xAbstractSpellDialog); if (m_xAbstractSpellDialog) - m_xAbstractSpellDialog->Invalidate(); + m_xAbstractSpellDialog->InvalidateDialog(); } bool SpellDialogChildWindow::HasAutoCorrection() diff --git a/svx/source/dialog/rubydialog.cxx b/svx/source/dialog/rubydialog.cxx index 7856b12e8687..5f0a6e54a8ac 100644 --- a/svx/source/dialog/rubydialog.cxx +++ b/svx/source/dialog/rubydialog.cxx @@ -280,9 +280,9 @@ void SvxRubyDialog::Close() { if (IsClosing()) return; - SfxViewShell* pViewShell = SfxViewShell::Current(); - if (pViewShell) - pViewShell->GetViewFrame()->ToggleChildWindow(SID_RUBY_DIALOG); + SfxViewFrame* pViewFrame = SfxViewFrame::Current(); + if (pViewFrame) + pViewFrame->ToggleChildWindow(SID_RUBY_DIALOG); } void SvxRubyDialog::Activate() diff --git a/svx/source/dialog/srchdlg.cxx b/svx/source/dialog/srchdlg.cxx index 791116324361..48dbc88ad860 100644 --- a/svx/source/dialog/srchdlg.cxx +++ b/svx/source/dialog/srchdlg.cxx @@ -523,9 +523,9 @@ void SvxSearchDialog::Close() rBindings.GetDispatcher()->Execute( FID_SEARCH_OFF, SfxCallMode::SLOT, ppArgs ); rBindings.Invalidate(SID_SEARCH_DLG); - SfxViewShell* pViewShell = SfxViewShell::Current(); - if (pViewShell) - pViewShell->GetViewFrame()->ToggleChildWindow(SID_SEARCH_DLG); + SfxViewFrame* pViewFrame = SfxViewFrame::Current(); + if (pViewFrame) + pViewFrame->ToggleChildWindow(SID_SEARCH_DLG); } TransliterationFlags SvxSearchDialog::GetTransliterationFlags() const diff --git a/sw/source/uibase/dialog/SwSpellDialogChildWindow.cxx b/sw/source/uibase/dialog/SwSpellDialogChildWindow.cxx index d8c927cba9eb..918d48436145 100644 --- a/sw/source/uibase/dialog/SwSpellDialogChildWindow.cxx +++ b/sw/source/uibase/dialog/SwSpellDialogChildWindow.cxx @@ -383,7 +383,7 @@ The code below would only be part of the solution. if(m_pSpellState->m_xStartRange.is()) { LockFocusNotification( true ); - std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(GetWindow()->GetFrameWeld(), + std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(GetController()->getDialog(), VclMessageType::Question, VclButtonsType::YesNo, SwResId(STR_QUERY_SPELL_CONTINUE))); sal_uInt16 nRet = xBox->run(); if (RET_YES == nRet) @@ -411,10 +411,10 @@ The code below would only be part of the solution. { LockFocusNotification( true ); OUString sInfo( SwResId( bNoDictionaryAvailable ? STR_DICTIONARY_UNAVAILABLE : STR_SPELLING_COMPLETED ) ); - vcl::Window* pThisWindow = GetWindow(); + auto xSpellController = GetController(); // #i84610# std::unique_ptr<weld::MessageDialog> xBox( - Application::CreateMessageDialog( pThisWindow->GetFrameWeld(), + Application::CreateMessageDialog( xSpellController->getDialog(), VclMessageType::Info, VclButtonsType::Ok, sInfo ) ); @@ -422,8 +422,7 @@ The code below would only be part of the solution. LockFocusNotification( false ); // take care that the now valid selection is stored LoseFocus(); - if( pThisWindow ) - pThisWindow->GrabFocus(); + xSpellController->getDialog()->grab_focus(); } } return aRet; diff --git a/vcl/source/app/salvtables.cxx b/vcl/source/app/salvtables.cxx index fadd5607c365..b17e0215258d 100644 --- a/vcl/source/app/salvtables.cxx +++ b/vcl/source/app/salvtables.cxx @@ -695,9 +695,9 @@ public: void SalInstanceWidget::HandleEventListener(VclWindowEvent& rEvent) { - if (rEvent.GetId() == VclEventId::WindowGetFocus || rEvent.GetId() == VclEventId::WindowActivate) + if (rEvent.GetId() == VclEventId::WindowGetFocus) m_aFocusInHdl.Call(*this); - else if (rEvent.GetId() == VclEventId::WindowLoseFocus || rEvent.GetId() == VclEventId::WindowDeactivate) + else if (rEvent.GetId() == VclEventId::WindowLoseFocus) m_aFocusOutHdl.Call(*this); else if (rEvent.GetId() == VclEventId::WindowResize) m_aSizeAllocateHdl.Call(m_xWidget->GetSizePixel()); @@ -1140,6 +1140,22 @@ public: return *m_xWindow->GetSystemData(); } + virtual void connect_toplevel_focus_changed(const Link<weld::Widget&, void>& rLink) override + { + ensure_event_listener(); + weld::Window::connect_toplevel_focus_changed(rLink); + } + + virtual void HandleEventListener(VclWindowEvent& rEvent) override + { + if (rEvent.GetId() == VclEventId::WindowActivate || rEvent.GetId() == VclEventId::WindowDeactivate) + { + signal_toplevel_focus_changed(); + return; + } + SalInstanceContainer::HandleEventListener(rEvent); + } + virtual ~SalInstanceWindow() override { clear_child_help(m_xWindow); @@ -1893,6 +1909,7 @@ public: m_xMenuButton->SetSelectHdl(LINK(this, SalInstanceMenuButton, MenuSelectHdl)); if (PopupMenu* pMenu = m_xMenuButton->GetPopupMenu()) { + pMenu->SetMenuFlags(MenuFlags::NoAutoMnemonics); const auto nCount = pMenu->GetItemCount(); m_nLastId = nCount ? pMenu->GetItemId(nCount-1) : 0; } @@ -1947,6 +1964,12 @@ public: pMenu->RemoveItem(pMenu->GetItemPos(pMenu->GetItemId(rId))); } + virtual void clear() override + { + PopupMenu* pMenu = m_xMenuButton->GetPopupMenu(); + pMenu->Clear(); + } + virtual void set_item_active(const OString& rIdent, bool bActive) override { PopupMenu* pMenu = m_xMenuButton->GetPopupMenu(); @@ -1959,6 +1982,12 @@ public: pMenu->SetItemText(pMenu->GetItemId(rIdent), rText); } + virtual OUString get_item_label(const OString& rIdent) const override + { + PopupMenu* pMenu = m_xMenuButton->GetPopupMenu(); + return pMenu->GetItemText(pMenu->GetItemId(rIdent)); + } + virtual void set_item_visible(const OString& rIdent, bool bShow) override { PopupMenu* pMenu = m_xMenuButton->GetPopupMenu(); diff --git a/vcl/source/control/edit.cxx b/vcl/source/control/edit.cxx index 57d037546c5f..926bc3193a7a 100644 --- a/vcl/source/control/edit.cxx +++ b/vcl/source/control/edit.cxx @@ -1467,7 +1467,7 @@ bool Edit::ImplHandleKeyEvent( const KeyEvent& rKEvt ) if ( pImplFncGetSpecialChars ) { Selection aSaveSel = GetSelection(); // if someone changes the selection in Get/LoseFocus, e.g. URL bar - OUString aChars = pImplFncGetSpecialChars( this, GetFont() ); + OUString aChars = pImplFncGetSpecialChars( GetFrameWeld(), GetFont() ); SetSelection( aSaveSel ); if ( !aChars.isEmpty() ) { @@ -2028,7 +2028,7 @@ void Edit::Command( const CommandEvent& rCEvt ) } else if (sCommand == "specialchar" && pImplFncGetSpecialChars) { - OUString aChars = pImplFncGetSpecialChars( this, GetFont() ); + OUString aChars = pImplFncGetSpecialChars(GetFrameWeld(), GetFont()); SetSelection( aSaveSel ); if (!aChars.isEmpty()) { diff --git a/vcl/source/edit/vclmedit.cxx b/vcl/source/edit/vclmedit.cxx index df9e23683d62..faa8e18061a5 100644 --- a/vcl/source/edit/vclmedit.cxx +++ b/vcl/source/edit/vclmedit.cxx @@ -715,7 +715,7 @@ void TextWindow::KeyInput( const KeyEvent& rKEvent ) { // to maintain the selection mbActivePopup = true; - OUString aChars = Edit::GetGetSpecialCharsFunction()( this, GetFont() ); + OUString aChars = Edit::GetGetSpecialCharsFunction()(GetFrameWeld(), GetFont()); if (!aChars.isEmpty()) { mpExtTextView->InsertText( aChars ); @@ -829,7 +829,7 @@ void TextWindow::Command( const CommandEvent& rCEvt ) } else if (sCommand == "specialchar") { - OUString aChars = Edit::GetGetSpecialCharsFunction()( this, GetFont() ); + OUString aChars = Edit::GetGetSpecialCharsFunction()(GetFrameWeld(), GetFont()); if (!aChars.isEmpty()) { mpExtTextView->InsertText( aChars ); diff --git a/vcl/unx/gtk3/gtk3gtkinst.cxx b/vcl/unx/gtk3/gtk3gtkinst.cxx index 06f49b7aefc1..712dd51b9ae6 100644 --- a/vcl/unx/gtk3/gtk3gtkinst.cxx +++ b/vcl/unx/gtk3/gtk3gtkinst.cxx @@ -2421,7 +2421,7 @@ public: bool bCheck) { GtkWidget* pImage = nullptr; - if (pIconName) + if (pIconName && !pIconName->isEmpty()) { GdkPixbuf* pixbuf = load_icon_by_name(*pIconName); if (!pixbuf) @@ -2497,6 +2497,12 @@ public: gtk_menu_item_set_label(m_aMap[rIdent], MapToGtkAccelerator(rText).getStr()); } + OUString get_item_label(const OString& rIdent) const + { + const gchar* pText = gtk_menu_item_get_label(m_aMap.find(rIdent)->second); + return OUString(pText, pText ? strlen(pText) : 0, RTL_TEXTENCODING_UTF8); + } + void set_item_help_id(const OString& rIdent, const OString& rHelpId) { set_help_id(GTK_WIDGET(m_aMap[rIdent]), rHelpId); @@ -2634,18 +2640,27 @@ class GtkInstanceWindow : public GtkInstanceContainer, public virtual weld::Wind private: GtkWindow* m_pWindow; rtl::Reference<SalGtkXWindow> m_xWindow; //uno api + gulong m_nToplevelFocusChangedSignalId; static void help_pressed(GtkAccelGroup*, GObject*, guint, GdkModifierType, gpointer widget) { GtkInstanceWindow* pThis = static_cast<GtkInstanceWindow*>(widget); pThis->help(); } + + static void signalToplevelFocusChanged(GtkWindow*, GParamSpec*, gpointer widget) + { + GtkInstanceWindow* pThis = static_cast<GtkInstanceWindow*>(widget); + pThis->signal_toplevel_focus_changed(); + } + protected: void help(); public: GtkInstanceWindow(GtkWindow* pWindow, GtkInstanceBuilder* pBuilder, bool bTakeOwnership) : GtkInstanceContainer(GTK_CONTAINER(pWindow), pBuilder, bTakeOwnership) , m_pWindow(pWindow) + , m_nToplevelFocusChangedSignalId(0) { //hook up F1 to show help GtkAccelGroup *pGroup = gtk_accel_group_new(); @@ -2801,8 +2816,31 @@ public: return ImplWindowStateToStr(aData); } + virtual void connect_toplevel_focus_changed(const Link<weld::Widget&, void>& rLink) override + { + assert(!m_nToplevelFocusChangedSignalId); + m_nToplevelFocusChangedSignalId = g_signal_connect(m_pWindow, "notify::has-toplevel-focus", G_CALLBACK(signalToplevelFocusChanged), this); + weld::Window::connect_toplevel_focus_changed(rLink); + } + + virtual void disable_notify_events() override + { + if (m_nToplevelFocusChangedSignalId) + g_signal_handler_block(m_pWidget, m_nToplevelFocusChangedSignalId); + GtkInstanceContainer::disable_notify_events(); + } + + virtual void enable_notify_events() override + { + GtkInstanceContainer::enable_notify_events(); + if (m_nToplevelFocusChangedSignalId) + g_signal_handler_unblock(m_pWidget, m_nToplevelFocusChangedSignalId); + } + virtual ~GtkInstanceWindow() override { + if (m_nToplevelFocusChangedSignalId) + g_signal_handler_disconnect(m_pWindow, m_nToplevelFocusChangedSignalId); if (m_xWindow.is()) m_xWindow->clear(); } @@ -5214,6 +5252,11 @@ public: MenuHelper::remove_item(rId); } + virtual void clear() override + { + clear_items(); + } + virtual void set_item_active(const OString& rIdent, bool bActive) override { MenuHelper::set_item_active(rIdent, bActive); @@ -5229,6 +5272,11 @@ public: MenuHelper::set_item_label(rIdent, rLabel); } + virtual OUString get_item_label(const OString& rIdent) const override + { + return MenuHelper::get_item_label(rIdent); + } + virtual void set_item_visible(const OString& rIdent, bool bVisible) override { MenuHelper::set_item_visible(rIdent, bVisible); |