diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 16:51:28 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 16:51:28 +0000 |
commit | 940b4d1848e8c70ab7642901a68594e8016caffc (patch) | |
tree | eb72f344ee6c3d9b80a7ecc079ea79e9fba8676d /svx/source/tbxctrls | |
parent | Initial commit. (diff) | |
download | libreoffice-940b4d1848e8c70ab7642901a68594e8016caffc.tar.xz libreoffice-940b4d1848e8c70ab7642901a68594e8016caffc.zip |
Adding upstream version 1:7.0.4.upstream/1%7.0.4upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
26 files changed, 14773 insertions, 0 deletions
diff --git a/svx/source/tbxctrls/Palette.cxx b/svx/source/tbxctrls/Palette.cxx new file mode 100644 index 000000000..ccfe7b81e --- /dev/null +++ b/svx/source/tbxctrls/Palette.cxx @@ -0,0 +1,364 @@ +/* -*- 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 <svx/Palette.hxx> +#include <tools/stream.hxx> + +#include <palettes.hxx> + +Palette::~Palette() +{ +} + +PaletteASE::~PaletteASE() +{ +} + +PaletteASE::PaletteASE( const OUString &rFPath, const OUString &rFName ) : + mbValidPalette( false ), + maFPath ( rFPath ), + maASEPaletteName ( rFName ) +{ + LoadPalette(); +} + +void PaletteASE::LoadColorSet(SvxColorValueSet& rColorSet) +{ + rColorSet.Clear(); + int nIx = 1; + for (const auto& rColor : maColors) + { + rColorSet.InsertItem(nIx, rColor.first, rColor.second); + ++nIx; + } +} + +const OUString& PaletteASE::GetName() +{ + return maASEPaletteName; +} + +const OUString& PaletteASE::GetPath() +{ + return maFPath; +} + +bool PaletteASE::IsValid() +{ + return mbValidPalette; +} + +// CMYK values from 0 to 1 +// TODO: Deduplicate me (taken from core/cui/source/dialogs/colorpicker.cxx) +static void lcl_CMYKtoRGB( float fCyan, float fMagenta, float fYellow, float fKey, float& dR, float& dG, float& dB ) +{ + fCyan = (fCyan * ( 1.0 - fKey )) + fKey; + fMagenta = (fMagenta * ( 1.0 - fKey )) + fKey; + fYellow = (fYellow * ( 1.0 - fKey )) + fKey; + + dR = std::max( std::min( ( 1.0 - fCyan ), 1.0), 0.0 ); + dG = std::max( std::min( ( 1.0 - fMagenta ), 1.0), 0.0 ); + dB = std::max( std::min( ( 1.0 - fYellow ), 1.0), 0.0 ); +} + +void PaletteASE::LoadPalette() +{ + SvFileStream aFile(maFPath, StreamMode::READ); + aFile.SetEndian(SvStreamEndian::BIG); + + // Verify magic first 4 characters + char cMagic[5] = {0}; + if ((aFile.ReadBytes(cMagic, 4) != 4) || (strncmp(cMagic, "ASEF", 4) != 0)) + { + mbValidPalette = false; + return; + } + + // Ignore the version number + aFile.SeekRel(4); + + sal_uInt32 nBlocks = 0; + aFile.ReadUInt32(nBlocks); + for (sal_uInt32 nI = 0; nI < nBlocks; nI++) { + sal_uInt32 nChunkType = 0; + aFile.ReadUInt32(nChunkType); + // End chunk + if (nChunkType == 0) + break; + + // Grab chunk size, name length + sal_uInt16 nChunkSize = 0; + sal_uInt16 nChars = 0; + aFile.ReadUInt16(nChunkSize); + aFile.ReadUInt16(nChars); + + OUString aPaletteName(""); + if (nChars > 1) + aPaletteName = read_uInt16s_ToOUString(aFile, nChars); + else + aFile.SeekRel(2); + + if (nChunkType == 0xC0010000) + { + // Got a start chunk, so set palette name + maASEPaletteName = aPaletteName; + // Is there color data? (shouldn't happen in a start block, but check anyway) + if (nChunkSize > ((nChars * 2) + 2)) + aPaletteName.clear(); + else + continue; + } + + char cColorModel[5] = {0}; + aFile.ReadBytes(cColorModel, 4); + OString aColorModel(cColorModel); + // r, g, and b are floats ranging from 0 to 1 + float r = 0, g = 0, b = 0; + + if (aColorModel.equalsIgnoreAsciiCase("cmyk")) + { + float c = 0, m = 0, y = 0, k = 0; + aFile.ReadFloat(c); + aFile.ReadFloat(m); + aFile.ReadFloat(y); + aFile.ReadFloat(k); + lcl_CMYKtoRGB(c, m, y, k, r, g, b); + } + else if (aColorModel.equalsIgnoreAsciiCase("rgb ")) + { + aFile.ReadFloat(r); + aFile.ReadFloat(g); + aFile.ReadFloat(b); + } + else if (aColorModel.equalsIgnoreAsciiCase("gray")) + { + float nVal = 0; + aFile.ReadFloat(nVal); + r = g = b = nVal; + } + else + { + float nL = 0, nA = 0, nB = 0; + aFile.ReadFloat(nL); + aFile.ReadFloat(nA); + aFile.ReadFloat(nB); + // TODO: How to convert LAB to RGB? + r = g = b = 0; + } + + // Ignore color type + aFile.SeekRel(2); + maColors.emplace_back(Color(r * 255, g * 255, b * 255), aPaletteName); + } + + mbValidPalette = true; +} + +// PaletteGPL ------------------------------------------------------------------ + +static OString lcl_getToken(const OString& rStr, sal_Int32& index); + +PaletteGPL::PaletteGPL( const OUString &rFPath, const OUString &rFName ) : + mbLoadedPalette( false ), + mbValidPalette( false ), + maFName( rFName ), + maFPath( rFPath ) +{ + LoadPaletteHeader(); +} + +PaletteGPL::~PaletteGPL() +{ +} + +const OUString& PaletteGPL::GetName() +{ + return maGPLPaletteName; +} + +const OUString& PaletteGPL::GetPath() +{ + return maFPath; +} + +void PaletteGPL::LoadColorSet(SvxColorValueSet& rColorSet) +{ + LoadPalette(); + + rColorSet.Clear(); + int nIx = 1; + for (const auto& rColor : maColors) + { + rColorSet.InsertItem(nIx, rColor.first, rColor.second); + ++nIx; + } +} + +bool PaletteGPL::IsValid() +{ + return mbValidPalette; +} + +bool PaletteGPL::ReadPaletteHeader(SvFileStream& rFileStream) +{ + OString aLine; + OString aPaletteName; + + rFileStream.ReadLine(aLine); + if( !aLine.startsWith("GIMP Palette") ) return false; + rFileStream.ReadLine(aLine); + if( aLine.startsWith("Name: ", &aPaletteName) ) + { + maGPLPaletteName = OStringToOUString(aPaletteName, RTL_TEXTENCODING_ASCII_US); + rFileStream.ReadLine(aLine); + if( aLine.startsWith("Columns: ")) + rFileStream.ReadLine(aLine); // we can ignore this + } + else + { + maGPLPaletteName = maFName; + } + return true; +} + +void PaletteGPL::LoadPaletteHeader() +{ + SvFileStream aFile(maFPath, StreamMode::READ); + mbValidPalette = ReadPaletteHeader( aFile ); +} + +void PaletteGPL::LoadPalette() +{ + if( mbLoadedPalette ) return; + mbLoadedPalette = true; + + // TODO add error handling!!! + SvFileStream aFile(maFPath, StreamMode::READ); + mbValidPalette = ReadPaletteHeader( aFile ); + + if( !mbValidPalette ) return; + + OString aLine; + do { + if (aLine[0] != '#' && aLine[0] != '\n') + { + // TODO check if r,g,b are 0<= x <=255, or just clamp? + sal_Int32 nIndex = 0; + OString token; + + token = lcl_getToken(aLine, nIndex); + if(token.isEmpty() || nIndex == -1) continue; + sal_Int32 r = token.toInt32(); + + token = lcl_getToken(aLine, nIndex); + if(token.isEmpty() || nIndex == -1) continue; + sal_Int32 g = token.toInt32(); + + token = lcl_getToken(aLine, nIndex); + if(token.isEmpty()) continue; + sal_Int32 b = token.toInt32(); + + OString name; + if(nIndex != -1) + name = aLine.copy(nIndex); + + maColors.emplace_back( + Color(r, g, b), + OStringToOUString(name, RTL_TEXTENCODING_ASCII_US)); + } + } while (aFile.ReadLine(aLine)); +} + +// finds first token in rStr from index, separated by whitespace +// returns position of next token in index +static OString lcl_getToken(const OString& rStr, sal_Int32& index) +{ + sal_Int32 substart, toklen = 0; + OUString aWhitespaceChars( " \n\t" ); + + while(index < rStr.getLength() && + aWhitespaceChars.indexOf( rStr[index] ) != -1) + ++index; + if(index == rStr.getLength()) + { + index = -1; + return OString(); + } + substart = index; + + //counts length of token + while(index < rStr.getLength() && + aWhitespaceChars.indexOf( rStr[index] ) == -1 ) + { + ++index; + ++toklen; + } + + //counts to position of next token + while(index < rStr.getLength() && + aWhitespaceChars.indexOf( rStr[index] ) != -1 ) + ++index; + if(index == rStr.getLength()) + index = -1; + + return rStr.copy(substart, toklen); +} + +// PaletteSOC ------------------------------------------------------------------ + +PaletteSOC::PaletteSOC( const OUString &rFPath, const OUString &rFName ) : + mbLoadedPalette( false ), + maFPath( rFPath ), + maSOCPaletteName( rFName ) +{ +} + +PaletteSOC::~PaletteSOC() +{ +} + +const OUString& PaletteSOC::GetName() +{ + return maSOCPaletteName; +} + +const OUString& PaletteSOC::GetPath() +{ + return maFPath; +} + +void PaletteSOC::LoadColorSet(SvxColorValueSet& rColorSet) +{ + if( !mbLoadedPalette ) + { + mbLoadedPalette = true; + mpColorList = XPropertyList::AsColorList(XPropertyList::CreatePropertyListFromURL(XPropertyListType::Color, maFPath)); + (void)mpColorList->Load(); + } + rColorSet.Clear(); + if( mpColorList.is() ) + rColorSet.addEntriesForXColorList( *mpColorList ); +} + +bool PaletteSOC::IsValid() +{ + return true; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/tbxctrls/PaletteManager.cxx b/svx/source/tbxctrls/PaletteManager.cxx new file mode 100644 index 000000000..1431793c3 --- /dev/null +++ b/svx/source/tbxctrls/PaletteManager.cxx @@ -0,0 +1,353 @@ +/* -*- 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 <memory> +#include <svx/PaletteManager.hxx> +#include <tools/urlobj.hxx> +#include <osl/file.hxx> +#include <unotools/pathoptions.hxx> +#include <sfx2/objsh.hxx> +#include <svx/drawitem.hxx> +#include <svx/strings.hrc> +#include <svx/svxids.hrc> +#include <svx/dialmgr.hxx> +#include <svx/tbxcolorupdate.hxx> +#include <svtools/colrdlg.hxx> +#include <vcl/svapp.hxx> +#include <vcl/settings.hxx> +#include <stack> +#include <set> +#include <officecfg/Office/Common.hxx> +#include <com/sun/star/frame/XDispatchProvider.hpp> +#include <com/sun/star/frame/XDispatch.hpp> +#include <com/sun/star/frame/Desktop.hpp> +#include <com/sun/star/util/XURLTransformer.hpp> +#include <com/sun/star/util/URLTransformer.hpp> + +#include <palettes.hxx> + +PaletteManager::PaletteManager() : + mnMaxRecentColors(Application::GetSettings().GetStyleSettings().GetColorValueSetColumnCount()), + mnNumOfPalettes(2), + mnCurrentPalette(0), + mnColorCount(0), + mpBtnUpdater(nullptr), + maColorSelectFunction(PaletteManager::DispatchColorCommand), + m_context(comphelper::getProcessComponentContext()) +{ + SfxObjectShell* pDocSh = SfxObjectShell::Current(); + if(pDocSh) + { + const SfxPoolItem* pItem = nullptr; + if( nullptr != ( pItem = pDocSh->GetItem(SID_COLOR_TABLE) ) ) + pColorList = static_cast<const SvxColorListItem*>(pItem)->GetColorList(); + } + if(!pColorList.is()) + pColorList = XColorList::CreateStdColorList(); + LoadPalettes(); + mnNumOfPalettes += m_Palettes.size(); + +} + +PaletteManager::~PaletteManager() +{ +} + +void PaletteManager::LoadPalettes() +{ + m_Palettes.clear(); + OUString aPalPaths = SvtPathOptions().GetPalettePath(); + + std::stack<OUString> aDirs; + sal_Int32 nIndex = 0; + do + { + aDirs.push(aPalPaths.getToken(0, ';', nIndex)); + } + while (nIndex >= 0); + + std::set<OUString> aNames; + //try all entries palette path list user first, then + //system, ignoring duplicate file names + while (!aDirs.empty()) + { + OUString aPalPath = aDirs.top(); + aDirs.pop(); + + osl::Directory aDir(aPalPath); + osl::DirectoryItem aDirItem; + osl::FileStatus aFileStat( osl_FileStatus_Mask_FileName | + osl_FileStatus_Mask_FileURL | + osl_FileStatus_Mask_Type ); + if( aDir.open() == osl::FileBase::E_None ) + { + while( aDir.getNextItem(aDirItem) == osl::FileBase::E_None ) + { + aDirItem.getFileStatus(aFileStat); + if(aFileStat.isRegular() || aFileStat.isLink()) + { + OUString aFName = aFileStat.getFileName(); + INetURLObject aURLObj( aFileStat.getFileURL() ); + OUString aFNameWithoutExt = aURLObj.GetBase(); + if (aNames.find(aFName) == aNames.end()) + { + std::unique_ptr<Palette> pPalette; + if( aFName.endsWithIgnoreAsciiCase(".gpl") ) + pPalette.reset(new PaletteGPL(aFileStat.getFileURL(), aFNameWithoutExt)); + else if( aFName.endsWithIgnoreAsciiCase(".soc") ) + pPalette.reset(new PaletteSOC(aFileStat.getFileURL(), aFNameWithoutExt)); + else if ( aFName.endsWithIgnoreAsciiCase(".ase") ) + pPalette.reset(new PaletteASE(aFileStat.getFileURL(), aFNameWithoutExt)); + + if( pPalette && pPalette->IsValid() ) + m_Palettes.push_back( std::move(pPalette) ); + aNames.insert(aFNameWithoutExt); + } + } + } + } + } +} + +void PaletteManager::ReloadColorSet(SvxColorValueSet &rColorSet) +{ + if( mnCurrentPalette == 0) + { + rColorSet.Clear(); + css::uno::Sequence< sal_Int32 > CustomColorList( officecfg::Office::Common::UserColors::CustomColor::get() ); + css::uno::Sequence< OUString > CustomColorNameList( officecfg::Office::Common::UserColors::CustomColorName::get() ); + int nIx = 1; + for (int i = 0; i < CustomColorList.getLength(); ++i) + { + Color aColor(CustomColorList[i]); + rColorSet.InsertItem(nIx, aColor, CustomColorNameList[i]); + ++nIx; + } + } + else if( mnCurrentPalette == mnNumOfPalettes - 1 ) + { + // Add doc colors to palette + SfxObjectShell* pDocSh = SfxObjectShell::Current(); + if (pDocSh) + { + std::set<Color> aColors = pDocSh->GetDocColors(); + mnColorCount = aColors.size(); + rColorSet.Clear(); + rColorSet.addEntriesForColorSet(aColors, SvxResId( RID_SVXSTR_DOC_COLOR_PREFIX ) + " " ); + } + } + else + { + m_Palettes[mnCurrentPalette - 1]->LoadColorSet( rColorSet ); + mnColorCount = rColorSet.GetItemCount(); + } +} + +void PaletteManager::ReloadRecentColorSet(SvxColorValueSet& rColorSet) +{ + maRecentColors.clear(); + rColorSet.Clear(); + css::uno::Sequence< sal_Int32 > Colorlist(officecfg::Office::Common::UserColors::RecentColor::get()); + css::uno::Sequence< OUString > ColorNamelist(officecfg::Office::Common::UserColors::RecentColorName::get()); + int nIx = 1; + const bool bHasColorNames = Colorlist.getLength() == ColorNamelist.getLength(); + for (int i = 0; i < Colorlist.getLength(); ++i) + { + Color aColor(Colorlist[i]); + OUString sColorName = bHasColorNames ? ColorNamelist[i] : ("#" + aColor.AsRGBHexString().toAsciiUpperCase()); + maRecentColors.emplace_back(aColor, sColorName); + rColorSet.InsertItem(nIx, aColor, sColorName); + ++nIx; + } +} + +std::vector<OUString> PaletteManager::GetPaletteList() +{ + std::vector<OUString> aPaletteNames; + + aPaletteNames.push_back( SvxResId( RID_SVXSTR_CUSTOM_PAL ) ); + for (auto const& it : m_Palettes) + { + aPaletteNames.push_back( (*it).GetName() ); + } + aPaletteNames.push_back( SvxResId ( RID_SVXSTR_DOC_COLORS ) ); + + return aPaletteNames; +} + +void PaletteManager::SetPalette( sal_Int32 nPos ) +{ + mnCurrentPalette = nPos; + if( nPos != mnNumOfPalettes - 1 && nPos != 0) + { + pColorList = XPropertyList::AsColorList( + XPropertyList::CreatePropertyListFromURL( + XPropertyListType::Color, GetSelectedPalettePath())); + auto name = GetPaletteName(); // may change pColorList + pColorList->SetName(name); + if(pColorList->Load()) + { + SfxObjectShell* pShell = SfxObjectShell::Current(); + if (pShell != nullptr) + { + SvxColorListItem aColorItem(pColorList, SID_COLOR_TABLE); + pShell->PutItem( aColorItem ); + } + } + } + OUString aPaletteName(officecfg::Office::Common::UserColors::PaletteName::get()); + if (aPaletteName != GetPaletteName()) + { + std::shared_ptr<comphelper::ConfigurationChanges> batch(comphelper::ConfigurationChanges::create(m_context)); + officecfg::Office::Common::UserColors::PaletteName::set(GetPaletteName(), batch); + batch->commit(); + } +} + +sal_Int32 PaletteManager::GetPalette() const +{ + return mnCurrentPalette; +} + +OUString PaletteManager::GetPaletteName() +{ + std::vector<OUString> aNames(GetPaletteList()); + if(mnCurrentPalette != mnNumOfPalettes - 1 && mnCurrentPalette != 0) + { + SfxObjectShell* pDocSh = SfxObjectShell::Current(); + if(pDocSh) + { + const SfxPoolItem* pItem = nullptr; + if( nullptr != ( pItem = pDocSh->GetItem(SID_COLOR_TABLE) ) ) + pColorList = static_cast<const SvxColorListItem*>(pItem)->GetColorList(); + } + } + return aNames[mnCurrentPalette]; +} + +OUString PaletteManager::GetSelectedPalettePath() +{ + if(mnCurrentPalette != mnNumOfPalettes - 1 && mnCurrentPalette != 0) + return m_Palettes[mnCurrentPalette - 1]->GetPath(); + else + return OUString(); +} + +long PaletteManager::GetColorCount() const +{ + return mnColorCount; +} + +long PaletteManager::GetRecentColorCount() const +{ + return maRecentColors.size(); +} + +void PaletteManager::AddRecentColor(const Color& rRecentColor, const OUString& rName, bool bFront) +{ + auto itColor = std::find_if(maRecentColors.begin(), + maRecentColors.end(), + [rRecentColor] (const NamedColor &a) { return a.first == rRecentColor; }); + // if recent color to be added is already in list, remove it + if( itColor != maRecentColors.end() ) + maRecentColors.erase( itColor ); + + if (maRecentColors.size() == mnMaxRecentColors) + maRecentColors.pop_back(); + if (bFront) + maRecentColors.push_front(std::make_pair(rRecentColor, rName)); + else + maRecentColors.emplace_back(rRecentColor, rName); + css::uno::Sequence< sal_Int32 > aColorList(maRecentColors.size()); + css::uno::Sequence< OUString > aColorNameList(maRecentColors.size()); + for (size_t i = 0; i < maRecentColors.size(); ++i) + { + aColorList[i] = static_cast<sal_Int32>(maRecentColors[i].first); + aColorNameList[i] = maRecentColors[i].second; + } + std::shared_ptr<comphelper::ConfigurationChanges> batch(comphelper::ConfigurationChanges::create(m_context)); + officecfg::Office::Common::UserColors::RecentColor::set(aColorList, batch); + officecfg::Office::Common::UserColors::RecentColorName::set(aColorNameList, batch); + batch->commit(); +} + +void PaletteManager::SetBtnUpdater(svx::ToolboxButtonColorUpdaterBase* pBtnUpdater) +{ + mpBtnUpdater = pBtnUpdater; +} + +void PaletteManager::SetColorSelectFunction(const std::function<void(const OUString&, const NamedColor&)>& aColorSelectFunction) +{ + maColorSelectFunction = aColorSelectFunction; +} + +void PaletteManager::PopupColorPicker(weld::Window* pParent, const OUString& aCommand, const Color& rInitialColor) +{ + // The calling object goes away during aColorDlg.Execute(), so we must copy this + OUString aCommandCopy = aCommand; + SvColorDialog aColorDlg; + aColorDlg.SetColor(rInitialColor); + aColorDlg.SetMode(svtools::ColorPickerMode::Modify); + if (aColorDlg.Execute(pParent) == RET_OK) + { + Color aLastColor = aColorDlg.GetColor(); + OUString sColorName = "#" + aLastColor.AsRGBHexString().toAsciiUpperCase(); + NamedColor aNamedColor = std::make_pair(aLastColor, sColorName); + if (mpBtnUpdater) + mpBtnUpdater->Update(aNamedColor); + AddRecentColor(aLastColor, sColorName); + maColorSelectFunction(aCommandCopy, aNamedColor); + } +} + +void PaletteManager::DispatchColorCommand(const OUString& aCommand, const NamedColor& rColor) +{ + using namespace css::uno; + using namespace css::frame; + using namespace css::beans; + using namespace css::util; + + Reference<XComponentContext> xContext(comphelper::getProcessComponentContext()); + Reference<XDesktop2> xDesktop = Desktop::create(xContext); + Reference<XFrame> xFrame(xDesktop->getCurrentFrame()); + Reference<XDispatchProvider> xDispatchProvider(xFrame, UNO_QUERY); + if (xDispatchProvider.is()) + { + INetURLObject aObj( aCommand ); + + Sequence<PropertyValue> aArgs(1); + aArgs[0].Name = aObj.GetURLPath(); + aArgs[0].Value <<= sal_Int32(rColor.first); + + URL aTargetURL; + aTargetURL.Complete = aCommand; + Reference<XURLTransformer> xURLTransformer(URLTransformer::create(comphelper::getProcessComponentContext())); + xURLTransformer->parseStrict(aTargetURL); + + Reference<XDispatch> xDispatch = xDispatchProvider->queryDispatch(aTargetURL, OUString(), 0); + if (xDispatch.is()) + { + xDispatch->dispatch(aTargetURL, aArgs); + if (xFrame->getContainerWindow().is()) + xFrame->getContainerWindow()->setFocus(); + } + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/tbxctrls/SvxColorChildWindow.cxx b/svx/source/tbxctrls/SvxColorChildWindow.cxx new file mode 100644 index 000000000..c7fb9a683 --- /dev/null +++ b/svx/source/tbxctrls/SvxColorChildWindow.cxx @@ -0,0 +1,43 @@ +/* -*- 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 <svx/SvxColorChildWindow.hxx> +#include <svx/svxids.hrc> +#include <colrctrl.hxx> + +SFX_IMPL_DOCKINGWINDOW_WITHID( SvxColorChildWindow, SID_COLOR_CONTROL ) + +// Derivation from SfxChildWindow as "container" for animator +SvxColorChildWindow::SvxColorChildWindow( vcl::Window* _pParent, + sal_uInt16 nId, + SfxBindings* pBindings, + SfxChildWinInfo* pInfo ) : + SfxChildWindow( _pParent, nId ) +{ + VclPtr<SvxColorDockingWindow> pWin = VclPtr<SvxColorDockingWindow>::Create( pBindings, this, + _pParent ); + + SetWindow(pWin); + + SetAlignment(SfxChildAlignment::RIGHT); + + pWin->Initialize( pInfo ); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/tbxctrls/SvxColorValueSet.cxx b/svx/source/tbxctrls/SvxColorValueSet.cxx new file mode 100644 index 000000000..c9423cb84 --- /dev/null +++ b/svx/source/tbxctrls/SvxColorValueSet.cxx @@ -0,0 +1,169 @@ +/* -*- 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 <svx/SvxColorValueSet.hxx> +#include <svx/xtable.hxx> +#include <vcl/svapp.hxx> +#include <vcl/settings.hxx> +#include <osl/diagnose.h> + +SvxColorValueSet::SvxColorValueSet(std::unique_ptr<weld::ScrolledWindow> pWindow) + : ValueSet(std::move(pWindow)) +{ + SetEdgeBlending(true); +} + +sal_uInt32 SvxColorValueSet::getMaxRowCount() +{ + return StyleSettings::GetColorValueSetMaximumRowCount(); +} + +sal_uInt32 SvxColorValueSet::getEntryEdgeLength() +{ + const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings(); + + return rStyleSettings.GetListBoxPreviewDefaultPixelSize().Height() + 1; +} + +sal_uInt32 SvxColorValueSet::getColumnCount() +{ + const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings(); + + return rStyleSettings.GetColorValueSetColumnCount(); +} + +void SvxColorValueSet::addEntriesForXColorList(const XColorList& rXColorList, sal_uInt32 nStartIndex) +{ + const sal_uInt32 nColorCount(rXColorList.Count()); + + for(sal_uInt32 nIndex(0); nIndex < nColorCount; nIndex++, nStartIndex++) + { + const XColorEntry* pEntry = rXColorList.GetColor(nIndex); + + if(pEntry) + { + InsertItem(nStartIndex, pEntry->GetColor(), pEntry->GetName()); + } + else + { + OSL_ENSURE(false, "OOps, XColorList with empty entries (!)"); + } + } +} + +void SvxColorValueSet::addEntriesForColorSet(const std::set<Color>& rColorSet, const OUString& rNamePrefix) +{ + sal_uInt32 nStartIndex = 1; + if(rNamePrefix.getLength() != 0) + { + for(const auto& rColor : rColorSet) + { + InsertItem(nStartIndex, rColor, rNamePrefix + OUString::number(nStartIndex)); + nStartIndex++; + } + } + else + { + for(const auto& rColor : rColorSet) + { + InsertItem(nStartIndex, rColor, ""); + nStartIndex++; + } + } +} + +Size SvxColorValueSet::layoutAllVisible(sal_uInt32 nEntryCount) +{ + if(!nEntryCount) + { + nEntryCount++; + } + + const sal_uInt32 nRowCount(ceil(double(nEntryCount)/SvxColorValueSet::getColumnCount())); + const Size aItemSize(SvxColorValueSet::getEntryEdgeLength() - 2, SvxColorValueSet::getEntryEdgeLength() - 2); + const WinBits aWinBits(GetStyle() & ~WB_VSCROLL); + + if (nRowCount > SvxColorValueSet::getMaxRowCount()) + { + SetStyle(aWinBits|WB_VSCROLL); + } + else + { + SetStyle(aWinBits); + } + + SetColCount(SvxColorValueSet::getColumnCount()); + SetLineCount(std::min(nRowCount, SvxColorValueSet::getMaxRowCount())); + SetItemWidth(aItemSize.Width()); + SetItemHeight(aItemSize.Height()); + + return CalcWindowSizePixel(aItemSize); +} + +void SvxColorValueSet::Resize() +{ + layoutToGivenHeight(GetOutputSizePixel().Height(), GetItemCount()); + ValueSet::Resize(); +} + +Size SvxColorValueSet::layoutToGivenHeight(sal_uInt32 nHeight, sal_uInt32 nEntryCount) +{ + if(!nEntryCount) + { + nEntryCount++; + } + + const Size aItemSize(SvxColorValueSet::getEntryEdgeLength() - 2, SvxColorValueSet::getEntryEdgeLength() - 2); + const WinBits aWinBits(GetStyle() & ~WB_VSCROLL); + + // get size with all fields disabled + const WinBits aWinBitsNoScrollNoFields(GetStyle() & ~(WB_VSCROLL|WB_NAMEFIELD|WB_NONEFIELD)); + SetStyle(aWinBitsNoScrollNoFields); + const Size aSizeNoScrollNoFields(CalcWindowSizePixel(aItemSize, SvxColorValueSet::getColumnCount())); + + // get size with all needed fields + SetStyle(aWinBits); + Size aNewSize(CalcWindowSizePixel(aItemSize, SvxColorValueSet::getColumnCount())); + + const Size aItemSizePixel(CalcItemSizePixel(aItemSize)); + // calculate field height and available height for requested height + const sal_uInt32 nFieldHeight(aNewSize.Height() - aSizeNoScrollNoFields.Height()); + const sal_uInt32 nAvailableHeight(nHeight >= nFieldHeight ? nHeight - nFieldHeight + aItemSizePixel.Height() - 1 : 0); + + // calculate how many lines can be shown there + const sal_uInt32 nLineCount(nAvailableHeight / aItemSizePixel.Height()); + const sal_uInt32 nLineMax(ceil(double(nEntryCount)/SvxColorValueSet::getColumnCount())); + + if(nLineMax > nLineCount) + { + SetStyle(aWinBits|WB_VSCROLL); + } + + // set height to wanted height + aNewSize.setHeight( nHeight ); + + SetItemWidth(aItemSize.Width()); + SetItemHeight(aItemSize.Height()); + SetColCount(SvxColorValueSet::getColumnCount()); + SetLineCount(nLineCount); + + return aNewSize; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/tbxctrls/SvxPresetListBox.cxx b/svx/source/tbxctrls/SvxPresetListBox.cxx new file mode 100644 index 000000000..eb31bec38 --- /dev/null +++ b/svx/source/tbxctrls/SvxPresetListBox.cxx @@ -0,0 +1,110 @@ +/* -*- 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 <svx/SvxPresetListBox.hxx> +#include <svx/xtable.hxx> +#include <vcl/commandevent.hxx> +#include <vcl/image.hxx> +#include <vcl/svapp.hxx> + +SvxPresetListBox::SvxPresetListBox(std::unique_ptr<weld::ScrolledWindow> pWindow) + : ValueSet(std::move(pWindow)) + , aIconSize(60, 64) +{ + SetEdgeBlending(true); +} + +void SvxPresetListBox::SetDrawingArea(weld::DrawingArea* pDrawingArea) +{ + ValueSet::SetDrawingArea(pDrawingArea); + SetStyle(GetStyle() | WB_ITEMBORDER); +} + +void SvxPresetListBox::Resize() +{ + DrawLayout(); + WinBits aWinBits(GetStyle()); + aWinBits |= WB_VSCROLL; + SetStyle(aWinBits); + ValueSet::Resize(); +} + +bool SvxPresetListBox::Command(const CommandEvent& rEvent) +{ + if (rEvent.GetCommand() != CommandEventId::ContextMenu) + return CustomWidgetController::Command(rEvent); + const sal_uInt16 nIndex = GetSelectedItemId(); + if(nIndex > 0) + { + std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(GetDrawingArea(), "svx/ui/presetmenu.ui")); + std::unique_ptr<weld::Menu> xMenu(xBuilder->weld_menu("menu")); + OnMenuItemSelected(xMenu->popup_at_rect(GetDrawingArea(), tools::Rectangle(rEvent.GetMousePosPixel(), Size(1,1)))); + return true; + } + return false; +} + +void SvxPresetListBox::DrawLayout() +{ + SetColCount(nColCount); + SetLineCount(5); +} + +template< typename ListType, typename EntryType > +void SvxPresetListBox::FillPresetListBoxImpl(ListType & pList, sal_uInt32 nStartIndex) +{ + const Size aSize( GetIconSize() ); + BitmapEx aBitmap; + for(long nIndex = 0; nIndex < pList.Count(); nIndex++, nStartIndex++) + { + aBitmap = pList.GetBitmapForPreview(nIndex, aSize); + EntryType* pItem = static_cast<EntryType*>( pList.Get(nIndex) ); + InsertItem(nStartIndex, Image(aBitmap), pItem->GetName()); + } +} + +void SvxPresetListBox::FillPresetListBox(XGradientList& pList, sal_uInt32 nStartIndex) +{ + FillPresetListBoxImpl< XGradientList, XGradientEntry>( pList, nStartIndex ); +} + +void SvxPresetListBox::FillPresetListBox(XHatchList& pList, sal_uInt32 nStartIndex) +{ + FillPresetListBoxImpl< XHatchList, XHatchEntry>( pList, nStartIndex ); +} + +void SvxPresetListBox::FillPresetListBox(XBitmapList& pList, sal_uInt32 nStartIndex) +{ + FillPresetListBoxImpl< XBitmapList, XBitmapEntry >( pList, nStartIndex ); +} + +void SvxPresetListBox::FillPresetListBox(XPatternList& pList, sal_uInt32 nStartIndex) +{ + FillPresetListBoxImpl< XPatternList, XBitmapEntry >( pList, nStartIndex ); +} + +void SvxPresetListBox::OnMenuItemSelected(const OString& rIdent) +{ + if (rIdent == "rename") + maRenameHdl.Call(this); + else if (rIdent == "delete") + maDeleteHdl.Call(this); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/tbxctrls/bulletsnumbering.cxx b/svx/source/tbxctrls/bulletsnumbering.cxx new file mode 100644 index 000000000..d30a6aabc --- /dev/null +++ b/svx/source/tbxctrls/bulletsnumbering.cxx @@ -0,0 +1,242 @@ +/* -*- 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/. + */ + +#include <com/sun/star/text/DefaultNumberingProvider.hpp> +#include <com/sun/star/text/XNumberingFormatter.hpp> + +#include <comphelper/propertysequence.hxx> +#include <i18nlangtag/languagetag.hxx> +#include <svtools/popupwindowcontroller.hxx> +#include <svtools/toolbarmenu.hxx> +#include <svx/strings.hrc> +#include <svx/dialmgr.hxx> +#include <svx/numvset.hxx> +#include <vcl/commandinfoprovider.hxx> +#include <vcl/toolbox.hxx> +#include <vcl/settings.hxx> +#include <vcl/svapp.hxx> + +namespace { + +class NumberingToolBoxControl; + +class NumberingPopup : public WeldToolbarPopup +{ + NumberingPageType mePageType; + NumberingToolBoxControl& mrController; + std::unique_ptr<SvxNumValueSet> mxValueSet; + std::unique_ptr<weld::CustomWeld> mxValueSetWin; + std::unique_ptr<weld::Button> mxMoreButton; + DECL_LINK(VSSelectValueSetHdl, ValueSet*, void); + DECL_LINK(VSButtonClickSetHdl, weld::Button&, void); + + virtual void GrabFocus() override; + +public: + NumberingPopup(NumberingToolBoxControl& rController, weld::Widget* pParent, NumberingPageType ePageType); + + virtual void statusChanged( const css::frame::FeatureStateEvent& rEvent ) override; +}; + +class NumberingToolBoxControl : public svt::PopupWindowController +{ + NumberingPageType mePageType; + +public: + explicit NumberingToolBoxControl( const css::uno::Reference< css::uno::XComponentContext >& rxContext ); + virtual VclPtr<vcl::Window> createVclPopupWindow( vcl::Window* pParent ) override; + std::unique_ptr<WeldToolbarPopup> weldPopupWindow() override; + + // XInitialization + virtual void SAL_CALL initialize( const css::uno::Sequence< css::uno::Any >& aArguments ) override; + + // XServiceInfo + virtual OUString SAL_CALL getImplementationName() override; + virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override; +}; + +} + +NumberingPopup::NumberingPopup(NumberingToolBoxControl& rController, + weld::Widget* pParent, NumberingPageType ePageType) + : WeldToolbarPopup(rController.getFrameInterface(), pParent, "svx/ui/numberingwindow.ui", "NumberingWindow") + , mePageType(ePageType) + , mrController(rController) + , mxValueSet(new SvxNumValueSet(m_xBuilder->weld_scrolled_window("valuesetwin"))) + , mxValueSetWin(new weld::CustomWeld(*m_xBuilder, "valueset", *mxValueSet)) + , mxMoreButton(m_xBuilder->weld_button("more")) +{ + mxValueSet->SetStyle(WB_MENUSTYLEVALUESET | WB_FLATVALUESET | WB_NO_DIRECTSELECT); + mxValueSet->init(mePageType); + + if ( mePageType != NumberingPageType::BULLET ) + { + css::uno::Reference< css::text::XDefaultNumberingProvider > xDefNum = css::text::DefaultNumberingProvider::create( mrController.getContext() ); + if ( xDefNum.is() ) + { + css::lang::Locale aLocale = Application::GetSettings().GetLanguageTag().getLocale(); + css::uno::Reference< css::text::XNumberingFormatter > xFormat( xDefNum, css::uno::UNO_QUERY ); + + if ( mePageType == NumberingPageType::SINGLENUM ) + { + css::uno::Sequence< css::uno::Sequence< css::beans::PropertyValue > > aNumberings( + xDefNum->getDefaultContinuousNumberingLevels( aLocale ) ); + mxValueSet->SetNumberingSettings( aNumberings, xFormat, aLocale ); + } + else if ( mePageType == NumberingPageType::OUTLINE ) + { + css::uno::Sequence< css::uno::Reference< css::container::XIndexAccess > > aOutline( + xDefNum->getDefaultOutlineNumberings( aLocale ) ); + mxValueSet->SetOutlineNumberingSettings( aOutline, xFormat, aLocale ); + } + } + } + + weld::DrawingArea* pDrawingArea = mxValueSet->GetDrawingArea(); + OutputDevice& rRefDevice = pDrawingArea->get_ref_device(); + Size aItemSize(rRefDevice.LogicToPixel(Size(30, 42), MapMode(MapUnit::MapAppFont))); + mxValueSet->SetExtraSpacing( 2 ); + Size aSize(mxValueSet->CalcWindowSizePixel(aItemSize)); + pDrawingArea->set_size_request(aSize.Width(), aSize.Height()); + mxValueSet->SetOutputSizePixel(aSize); + mxValueSet->SetColor(Application::GetSettings().GetStyleSettings().GetFieldColor()); + + OUString aMoreItemText; + if ( mePageType == NumberingPageType::BULLET ) + { + aMoreItemText = SvxResId( RID_SVXSTR_MOREBULLETS ); + AddStatusListener( ".uno:CurrentBulletListType" ); + } + else if ( mePageType == NumberingPageType::SINGLENUM ) + { + aMoreItemText = SvxResId( RID_SVXSTR_MORENUMBERING ); + AddStatusListener( ".uno:CurrentNumListType" ); + } + else + { + aMoreItemText = SvxResId( RID_SVXSTR_MORE ); + AddStatusListener( ".uno:CurrentOutlineType" ); + } + + auto xImage = vcl::CommandInfoProvider::GetXGraphicForCommand(".uno:OutlineBullet", mrController.getFrameInterface()); + mxMoreButton->set_image(xImage); + mxMoreButton->set_label(aMoreItemText); + mxMoreButton->connect_clicked(LINK(this, NumberingPopup, VSButtonClickSetHdl)); + + mxValueSet->SetSelectHdl(LINK(this, NumberingPopup, VSSelectValueSetHdl)); +} + +void NumberingPopup::statusChanged( const css::frame::FeatureStateEvent& rEvent ) +{ + mxValueSet->SetNoSelection(); + + sal_Int32 nSelItem; + if ( rEvent.State >>= nSelItem ) + mxValueSet->SelectItem( nSelItem ); +} + +IMPL_LINK_NOARG(NumberingPopup, VSSelectValueSetHdl, ValueSet*, void) +{ + sal_uInt16 nSelItem = mxValueSet->GetSelectedItemId(); + if ( mePageType == NumberingPageType::BULLET ) + { + auto aArgs( comphelper::InitPropertySequence( { { "SetBullet", css::uno::makeAny( nSelItem ) } } ) ); + mrController.dispatchCommand( ".uno:SetBullet", aArgs ); + } + else if ( mePageType == NumberingPageType::SINGLENUM ) + { + auto aArgs( comphelper::InitPropertySequence( { { "SetNumber", css::uno::makeAny( nSelItem ) } } ) ); + mrController.dispatchCommand( ".uno:SetNumber", aArgs ); + } + else + { + auto aArgs( comphelper::InitPropertySequence( { { "SetOutline", css::uno::makeAny( nSelItem ) } } ) ); + mrController.dispatchCommand( ".uno:SetOutline", aArgs ); + } + mrController.EndPopupMode(); +} + +void NumberingPopup::GrabFocus() +{ + mxValueSet->GrabFocus(); +} + +IMPL_LINK_NOARG(NumberingPopup, VSButtonClickSetHdl, weld::Button&, void) +{ + auto aArgs( comphelper::InitPropertySequence( { { "Page", css::uno::makeAny( OUString("customize") ) } } ) ); + mrController.dispatchCommand( ".uno:OutlineBullet", aArgs ); + + mrController.EndPopupMode(); +} + +NumberingToolBoxControl::NumberingToolBoxControl( const css::uno::Reference< css::uno::XComponentContext >& rxContext ): + svt::PopupWindowController( rxContext, css::uno::Reference< css::frame::XFrame >(), OUString() ), + mePageType( NumberingPageType::SINGLENUM ) +{ +} + +std::unique_ptr<WeldToolbarPopup> NumberingToolBoxControl::weldPopupWindow() +{ + return std::make_unique<NumberingPopup>(*this, m_pToolbar, mePageType); +} + +VclPtr<vcl::Window> NumberingToolBoxControl::createVclPopupWindow( vcl::Window* pParent ) +{ + mxInterimPopover = VclPtr<InterimToolbarPopup>::Create(getFrameInterface(), pParent, + std::make_unique<NumberingPopup>(*this, pParent->GetFrameWeld(), mePageType)); + + mxInterimPopover->Show(); + + return mxInterimPopover; +} + +void SAL_CALL NumberingToolBoxControl::initialize( const css::uno::Sequence< css::uno::Any >& aArguments ) +{ + svt::PopupWindowController::initialize( aArguments ); + + if ( m_aCommandURL == ".uno:DefaultBullet" ) + mePageType = NumberingPageType::BULLET; + else if ( m_aCommandURL == ".uno:SetOutline" ) + mePageType = NumberingPageType::OUTLINE; + + if (m_pToolbar) + { + mxPopoverContainer.reset(new ToolbarPopupContainer(m_pToolbar)); + m_pToolbar->set_item_popover(m_aCommandURL.toUtf8(), mxPopoverContainer->getTopLevel()); + return; + } + + ToolBox* pToolBox = nullptr; + sal_uInt16 nId = 0; + if (getToolboxId(nId, &pToolBox)) + { + ToolBoxItemBits nBits = ( mePageType == NumberingPageType::OUTLINE ) ? ToolBoxItemBits::DROPDOWNONLY : ToolBoxItemBits::DROPDOWN; + pToolBox->SetItemBits( nId, pToolBox->GetItemBits( nId ) | nBits ); + } +} + +OUString SAL_CALL NumberingToolBoxControl::getImplementationName() +{ + return "com.sun.star.comp.svx.NumberingToolBoxControl"; +} + +css::uno::Sequence< OUString > SAL_CALL NumberingToolBoxControl::getSupportedServiceNames() +{ + return { "com.sun.star.frame.ToolbarController" }; +} + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * +com_sun_star_comp_svx_NumberingToolBoxControl_get_implementation( + css::uno::XComponentContext *rxContext, + css::uno::Sequence<css::uno::Any> const & ) +{ + return cppu::acquire( new NumberingToolBoxControl( rxContext ) ); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/tbxctrls/colrctrl.cxx b/svx/source/tbxctrls/colrctrl.cxx new file mode 100644 index 000000000..7091a6738 --- /dev/null +++ b/svx/source/tbxctrls/colrctrl.cxx @@ -0,0 +1,427 @@ +/* -*- 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 <sal/config.h> + +#include <sot/exchange.hxx> +#include <svx/strings.hrc> +#include <svx/svxids.hrc> + +#include <sfx2/viewsh.hxx> +#include <sfx2/objsh.hxx> +#include <sfx2/dispatch.hxx> +#include <sfx2/viewfrm.hxx> +#include <vcl/image.hxx> +#include <vcl/transfer.hxx> + +#include <colrctrl.hxx> + +#include <svx/svdview.hxx> +#include <svx/drawitem.hxx> +#include <svx/xfillit0.hxx> +#include <svx/xflclit.hxx> +#include <editeng/colritem.hxx> +#include <svx/xlineit0.hxx> +#include <svx/xlnclit.hxx> +#include <svx/xtable.hxx> +#include <svx/dialmgr.hxx> +#include <helpids.h> +#include <vcl/svapp.hxx> +#include <vcl/virdev.hxx> + +#include <com/sun/star/beans/NamedValue.hpp> + +using namespace com::sun::star; + +class SvxColorValueSetData final : public TransferDataContainer +{ +private: + uno::Sequence<beans::NamedValue> m_Data; + + virtual void AddSupportedFormats() override; + virtual bool GetData(const css::datatransfer::DataFlavor& rFlavor, const OUString& rDestDoc) override; + +public: + SvxColorValueSetData() + { + } + + void SetData(const uno::Sequence<beans::NamedValue>& rData) + { + m_Data = rData; + ClearFormats(); // invalidate m_aAny so new data will take effect + } +}; + +void SvxColorValueSetData::AddSupportedFormats() +{ + AddFormat( SotClipboardFormatId::XFA ); +} + +bool SvxColorValueSetData::GetData( const css::datatransfer::DataFlavor& rFlavor, const OUString& /*rDestDoc*/ ) +{ + bool bRet = false; + + if( SotExchange::GetFormat( rFlavor ) == SotClipboardFormatId::XFA ) + { + SetAny(uno::makeAny(m_Data)); + bRet = true; + } + + return bRet; +} + +void SvxColorValueSet_docking::SetDrawingArea(weld::DrawingArea* pDrawingArea) +{ + SvxColorValueSet::SetDrawingArea(pDrawingArea); + SetAccessibleName(SvxResId(STR_COLORTABLE)); + SetStyle(GetStyle() | WB_ITEMBORDER); + + m_xHelper.set(new SvxColorValueSetData); + rtl::Reference<TransferDataContainer> xHelper(m_xHelper.get()); + SetDragDataTransferrable(xHelper, DND_ACTION_COPY); +} + +SvxColorValueSet_docking::SvxColorValueSet_docking(std::unique_ptr<weld::ScrolledWindow> xWindow) + : SvxColorValueSet(std::move(xWindow)) + , mbLeftButton(true) +{ +} + +bool SvxColorValueSet_docking::MouseButtonDown( const MouseEvent& rMEvt ) +{ + bool bRet; + + // For Mac still handle differently! + if( rMEvt.IsLeft() ) + { + mbLeftButton = true; + bRet = SvxColorValueSet::MouseButtonDown( rMEvt ); + } + else + { + mbLeftButton = false; + MouseEvent aMEvt( rMEvt.GetPosPixel(), + rMEvt.GetClicks(), + rMEvt.GetMode(), + MOUSE_LEFT, + rMEvt.GetModifier() ); + bRet = SvxColorValueSet::MouseButtonDown( aMEvt ); + } + + return bRet; +} + +bool SvxColorValueSet_docking::MouseButtonUp( const MouseEvent& rMEvt ) +{ + bool bRet; + + // For Mac still handle differently! + if( rMEvt.IsLeft() ) + { + mbLeftButton = true; + bRet = SvxColorValueSet::MouseButtonUp( rMEvt ); + } + else + { + mbLeftButton = false; + MouseEvent aMEvt( rMEvt.GetPosPixel(), + rMEvt.GetClicks(), + rMEvt.GetMode(), + MOUSE_LEFT, + rMEvt.GetModifier() ); + bRet = SvxColorValueSet::MouseButtonUp( aMEvt ); + } + SetNoSelection(); + + return bRet; +} + +bool SvxColorValueSet_docking::StartDrag() +{ + sal_uInt16 nPos = GetSelectedItemId(); + Color aItemColor( GetItemColor( nPos ) ); + OUString sItemText( GetItemText( nPos ) ); + + drawing::FillStyle eStyle = ((1 == nPos) + ? drawing::FillStyle_NONE + : drawing::FillStyle_SOLID); + + uno::Sequence<beans::NamedValue> props(2); + XFillColorItem const color(sItemText, aItemColor); + props[0].Name = "FillColor"; + color.QueryValue(props[0].Value, 0); + XFillStyleItem const style(eStyle); + props[1].Name = "FillStyle"; + style.QueryValue(props[1].Value, 0); + + m_xHelper->SetData(props); + + return false; +} + +static constexpr sal_uInt16 gnLeftSlot = SID_ATTR_FILL_COLOR; +static constexpr sal_uInt16 gnRightSlot = SID_ATTR_LINE_COLOR; + +SvxColorDockingWindow::SvxColorDockingWindow(SfxBindings* _pBindings, SfxChildWindow* pCW, vcl::Window* _pParent) + : SfxDockingWindow(_pBindings, pCW, _pParent, + "DockingColorWindow", "svx/ui/dockingcolorwindow.ui") + , pColorList() + , xColorSet(new SvxColorValueSet_docking(m_xBuilder->weld_scrolled_window("valuesetwin"))) + , xColorSetWin(new weld::CustomWeld(*m_xBuilder, "valueset", *xColorSet)) +{ + SetText(SvxResId(STR_COLORTABLE)); + SetQuickHelpText(SvxResId(RID_SVXSTR_COLORBAR)); + SetSizePixel(LogicToPixel(Size(150, 22), MapMode(MapUnit::MapAppFont))); + SetHelpId(HID_CTRL_COLOR); + + xColorSet->SetSelectHdl( LINK( this, SvxColorDockingWindow, SelectHdl ) ); + xColorSet->SetHelpId(HID_COLOR_CTL_COLORS); + + // Get the model from the view shell. Using SfxObjectShell::Current() + // is unreliable when called at the wrong times. + SfxObjectShell* pDocSh = nullptr; + if (_pBindings != nullptr) + { + SfxDispatcher* pDispatcher = _pBindings->GetDispatcher(); + if (pDispatcher != nullptr) + { + SfxViewFrame* pFrame = pDispatcher->GetFrame(); + if (pFrame != nullptr) + { + SfxViewShell* pViewShell = pFrame->GetViewShell(); + if (pViewShell != nullptr) + pDocSh = pViewShell->GetObjectShell(); + } + } + } + + if ( pDocSh ) + { + const SfxPoolItem* pItem = pDocSh->GetItem( SID_COLOR_TABLE ); + if( pItem ) + { + pColorList = static_cast<const SvxColorListItem*>(pItem)->GetColorList(); + FillValueSet(); + } + } + + Size aItemSize = xColorSet->CalcItemSizePixel(Size(SvxColorValueSet::getEntryEdgeLength(), SvxColorValueSet::getEntryEdgeLength())); + aItemSize.setWidth( aItemSize.Width() + SvxColorValueSet::getEntryEdgeLength() ); + aItemSize.setWidth( aItemSize.Width() / 2 ); + aItemSize.setHeight( aItemSize.Height() + SvxColorValueSet::getEntryEdgeLength() ); + aItemSize.setHeight( aItemSize.Height() / 2 ); + + fprintf(stderr, "size is %ld %ld\n", aItemSize.Width(), aItemSize.Height()); + + if (_pBindings != nullptr) + StartListening(*_pBindings, DuplicateHandling::Prevent); +} + +SvxColorDockingWindow::~SvxColorDockingWindow() +{ + disposeOnce(); +} + +void SvxColorDockingWindow::dispose() +{ + EndListening( GetBindings() ); + xColorSetWin.reset(); + xColorSet.reset(); + SfxDockingWindow::dispose(); +} + +void SvxColorDockingWindow::Notify( SfxBroadcaster& , const SfxHint& rHint ) +{ + const SfxPoolItemHint* pPoolItemHint = dynamic_cast<const SfxPoolItemHint*>(&rHint); + if ( pPoolItemHint + && ( dynamic_cast<const SvxColorListItem*>(pPoolItemHint->GetObject()) != nullptr ) ) + { + // The list of colors has changed + pColorList = static_cast<SvxColorListItem*>( pPoolItemHint->GetObject() )->GetColorList(); + FillValueSet(); + } +} + +void SvxColorDockingWindow::FillValueSet() +{ + if( !pColorList.is() ) + return; + + xColorSet->Clear(); + + xColorSet->addEntriesForXColorList(*pColorList, 2); + + // create the last entry for 'invisible/none' + const Size aColorSize(SvxColorValueSet::getEntryEdgeLength(), SvxColorValueSet::getEntryEdgeLength()); + long nPtX = aColorSize.Width() - 1; + long nPtY = aColorSize.Height() - 1; + ScopedVclPtrInstance< VirtualDevice > pVD; + + pVD->SetOutputSizePixel( aColorSize ); + pVD->SetLineColor( COL_BLACK ); + pVD->SetBackground( Wallpaper( COL_WHITE ) ); + pVD->DrawLine( Point(), Point( nPtX, nPtY ) ); + pVD->DrawLine( Point( 0, nPtY ), Point( nPtX, 0 ) ); + + BitmapEx aBmp( pVD->GetBitmapEx( Point(), aColorSize ) ); + + xColorSet->InsertItem( sal_uInt16(1), Image(aBmp), SvxResId( RID_SVXSTR_INVISIBLE ) ); +} + +bool SvxColorDockingWindow::Close() +{ + SfxBoolItem aItem( SID_COLOR_CONTROL, false ); + GetBindings().GetDispatcher()->ExecuteList(SID_COLOR_CONTROL, + SfxCallMode::ASYNCHRON | SfxCallMode::RECORD, { &aItem }); + SfxDockingWindow::Close(); + return true; +} + +IMPL_LINK_NOARG(SvxColorDockingWindow, SelectHdl, ValueSet*, void) +{ + SfxDispatcher* pDispatcher = GetBindings().GetDispatcher(); + sal_uInt16 nPos = xColorSet->GetSelectedItemId(); + Color aColor( xColorSet->GetItemColor( nPos ) ); + OUString aStr( xColorSet->GetItemText( nPos ) ); + + if (xColorSet->IsLeftButton()) + { + if ( gnLeftSlot == SID_ATTR_FILL_COLOR ) + { + if ( nPos == 1 ) // invisible + { + XFillStyleItem aXFillStyleItem( drawing::FillStyle_NONE ); + pDispatcher->ExecuteList(gnLeftSlot, SfxCallMode::RECORD, + { &aXFillStyleItem }); + } + else + { + bool bDone = false; + + // If we have a DrawView and we are in TextEdit mode, then + // not the area color but the text color is assigned + SfxViewShell* pViewSh = SfxViewShell::Current(); + if ( pViewSh ) + { + SdrView* pView = pViewSh->GetDrawView(); + if ( pView && pView->IsTextEdit() ) + { + SvxColorItem aTextColorItem( aColor, SID_ATTR_CHAR_COLOR ); + pDispatcher->ExecuteList(SID_ATTR_CHAR_COLOR, + SfxCallMode::RECORD, { &aTextColorItem }); + bDone = true; + } + } + if ( !bDone ) + { + XFillStyleItem aXFillStyleItem( drawing::FillStyle_SOLID ); + XFillColorItem aXFillColorItem( aStr, aColor ); + pDispatcher->ExecuteList(gnLeftSlot, SfxCallMode::RECORD, + { &aXFillColorItem, &aXFillStyleItem }); + } + } + } + else if ( nPos != 1 ) // invisible + { + SvxColorItem aLeftColorItem( aColor, gnLeftSlot ); + pDispatcher->ExecuteList(gnLeftSlot, SfxCallMode::RECORD, + { &aLeftColorItem }); + } + } + else + { + if ( gnRightSlot == SID_ATTR_LINE_COLOR ) + { + if( nPos == 1 ) // invisible + { + XLineStyleItem aXLineStyleItem( drawing::LineStyle_NONE ); + pDispatcher->ExecuteList(gnRightSlot, SfxCallMode::RECORD, + { &aXLineStyleItem }); + } + else + { + // If the LineStyle is invisible, it is set to SOLID + SfxViewShell* pViewSh = SfxViewShell::Current(); + if ( pViewSh ) + { + SdrView* pView = pViewSh->GetDrawView(); + if ( pView ) + { + SfxItemSet aAttrSet( pView->GetModel()->GetItemPool() ); + pView->GetAttributes( aAttrSet ); + if ( aAttrSet.GetItemState( XATTR_LINESTYLE ) != SfxItemState::DONTCARE ) + { + drawing::LineStyle eXLS = + aAttrSet.Get( XATTR_LINESTYLE ).GetValue(); + if ( eXLS == drawing::LineStyle_NONE ) + { + XLineStyleItem aXLineStyleItem( drawing::LineStyle_SOLID ); + pDispatcher->ExecuteList(gnRightSlot, + SfxCallMode::RECORD, { &aXLineStyleItem }); + } + } + } + } + + XLineColorItem aXLineColorItem( aStr, aColor ); + pDispatcher->ExecuteList(gnRightSlot, SfxCallMode::RECORD, + { &aXLineColorItem }); + } + } + else if ( nPos != 1 ) // invisible + { + SvxColorItem aRightColorItem( aColor, gnRightSlot ); + pDispatcher->ExecuteList(gnRightSlot, SfxCallMode::RECORD, + { &aRightColorItem }); + } + } +} + +void SvxColorDockingWindow::GetFocus() +{ + SfxDockingWindow::GetFocus(); + if (xColorSet) + { + // Grab the focus to the color value set so that it can be controlled + // with the keyboard. + xColorSet->GrabFocus(); + } +} + +bool SvxColorDockingWindow::EventNotify( NotifyEvent& rNEvt ) +{ + bool bRet = false; + if( rNEvt.GetType() == MouseNotifyEvent::KEYINPUT ) + { + KeyEvent aKeyEvt = *rNEvt.GetKeyEvent(); + sal_uInt16 nKeyCode = aKeyEvt.GetKeyCode().GetCode(); + switch( nKeyCode ) + { + case KEY_ESCAPE: + GrabFocusToDocument(); + bRet = true; + break; + } + } + + return bRet || SfxDockingWindow::EventNotify(rNEvt); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/tbxctrls/extrusioncontrols.cxx b/svx/source/tbxctrls/extrusioncontrols.cxx new file mode 100644 index 000000000..8f4e2fd5d --- /dev/null +++ b/svx/source/tbxctrls/extrusioncontrols.cxx @@ -0,0 +1,936 @@ +/* -*- 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 <svtools/toolbarmenu.hxx> +#include <vcl/toolbox.hxx> + +#include <svx/strings.hrc> +#include <svx/svdtrans.hxx> +#include <svx/dialmgr.hxx> + +#include <helpids.h> +#include "extrusioncontrols.hxx" +#include <extrusiondepthdialog.hxx> + +#include <bitmaps.hlst> + +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::util; +using namespace ::com::sun::star::graphic; + +namespace svx +{ + +static const sal_Int32 gSkewList[] = { 135, 90, 45, 180, 0, -360, -135, -90, -45 }; +static const char g_sExtrusionDirection[] = ".uno:ExtrusionDirection"; +static const char g_sExtrusionProjection[] = ".uno:ExtrusionProjection"; + +static const OUStringLiteral aLightOffBmps[] = +{ + RID_SVXBMP_LIGHT_OFF_FROM_TOP_LEFT, + RID_SVXBMP_LIGHT_OFF_FROM_TOP, + RID_SVXBMP_LIGHT_OFF_FROM_TOP_RIGHT, + RID_SVXBMP_LIGHT_OFF_FROM_LEFT, + "", + RID_SVXBMP_LIGHT_OFF_FROM_RIGHT, + RID_SVXBMP_LIGHT_OFF_FROM_BOTTOM_LEFT, + RID_SVXBMP_LIGHT_OFF_FROM_BOTTOM, + RID_SVXBMP_LIGHT_OFF_FROM_BOTTOM_RIGHT +}; + +static const OUStringLiteral aLightOnBmps[] = +{ + RID_SVXBMP_LIGHT_ON_FROM_TOP_LEFT, + RID_SVXBMP_LIGHT_ON_FROM_TOP, + RID_SVXBMP_LIGHT_ON_FROM_TOP_RIGHT, + RID_SVXBMP_LIGHT_ON_FROM_LEFT, + "", + RID_SVXBMP_LIGHT_ON_FROM_RIGHT, + RID_SVXBMP_LIGHT_ON_FROM_BOTTOM_LEFT, + RID_SVXBMP_LIGHT_ON_FROM_BOTTOM, + RID_SVXBMP_LIGHT_ON_FROM_BOTTOM_RIGHT +}; + +static const OUStringLiteral aLightPreviewBmps[] = +{ + RID_SVXBMP_LIGHT_PREVIEW_FROM_TOP_LEFT, + RID_SVXBMP_LIGHT_PREVIEW_FROM_TOP, + RID_SVXBMP_LIGHT_PREVIEW_FROM_TOP_RIGHT, + RID_SVXBMP_LIGHT_PREVIEW_FROM_LEFT, + RID_SVXBMP_LIGHT_PREVIEW_FROM_RIGHT, + RID_SVXBMP_LIGHT_PREVIEW_FROM_FRONT, + RID_SVXBMP_LIGHT_PREVIEW_FROM_BOTTOM_LEFT, + RID_SVXBMP_LIGHT_PREVIEW_FROM_BOTTOM, + RID_SVXBMP_LIGHT_PREVIEW_FROM_BOTTOM_RIGHT +}; + +static const OUStringLiteral aDirectionBmps[] = +{ + RID_SVXBMP_DIRECTION_DIRECTION_NW, + RID_SVXBMP_DIRECTION_DIRECTION_N, + RID_SVXBMP_DIRECTION_DIRECTION_NE, + RID_SVXBMP_DIRECTION_DIRECTION_W, + RID_SVXBMP_DIRECTION_DIRECTION_NONE, + RID_SVXBMP_DIRECTION_DIRECTION_E, + RID_SVXBMP_DIRECTION_DIRECTION_SW, + RID_SVXBMP_DIRECTION_DIRECTION_S, + RID_SVXBMP_DIRECTION_DIRECTION_SE +}; + +static const char* aDirectionStrs[] = +{ + RID_SVXSTR_DIRECTION_NW, + RID_SVXSTR_DIRECTION_N, + RID_SVXSTR_DIRECTION_NE, + RID_SVXSTR_DIRECTION_W, + RID_SVXSTR_DIRECTION_NONE, + RID_SVXSTR_DIRECTION_E, + RID_SVXSTR_DIRECTION_SW, + RID_SVXSTR_DIRECTION_S, + RID_SVXSTR_DIRECTION_SE +}; + +ExtrusionDirectionWindow::ExtrusionDirectionWindow( + svt::PopupWindowController* pControl, + weld::Widget* pParent) + : WeldToolbarPopup(pControl->getFrameInterface(), pParent, "svx/ui/directionwindow.ui", "DirectionWindow") + , mxControl(pControl) + , mxDirectionSet(new ValueSet(nullptr)) + , mxDirectionSetWin(new weld::CustomWeld(*m_xBuilder, "valueset", *mxDirectionSet)) + , mxPerspective(m_xBuilder->weld_radio_button("perspective")) + , mxParallel(m_xBuilder->weld_radio_button("parallel")) +{ + mxDirectionSet->SetStyle(WB_TABSTOP | WB_MENUSTYLEVALUESET | WB_FLATVALUESET | WB_NOBORDER | WB_NO_DIRECTSELECT); + + for (sal_uInt16 i = DIRECTION_NW; i <= DIRECTION_SE; ++i) + { + maImgDirection[i] = Image(StockImage::Yes, aDirectionBmps[i]); + } + + mxDirectionSet->SetSelectHdl( LINK( this, ExtrusionDirectionWindow, SelectValueSetHdl ) ); + mxDirectionSet->SetColCount( 3 ); + mxDirectionSet->EnableFullItemMode( false ); + + for (sal_uInt16 i = DIRECTION_NW; i <= DIRECTION_SE; ++i) + { + mxDirectionSet->InsertItem(i + 1, maImgDirection[i], SvxResId(aDirectionStrs[i])); + } + + Size aSize(72, 72); + mxDirectionSet->GetDrawingArea()->set_size_request(aSize.Width(), aSize.Height()); + mxDirectionSet->SetOutputSizePixel(aSize); + + mxPerspective->connect_clicked(LINK(this, ExtrusionDirectionWindow, SelectToolbarMenuHdl)); + mxParallel->connect_clicked(LINK(this, ExtrusionDirectionWindow, SelectToolbarMenuHdl)); + + AddStatusListener( g_sExtrusionDirection ); + AddStatusListener( g_sExtrusionProjection ); +} + +void ExtrusionDirectionWindow::GrabFocus() +{ + mxDirectionSet->GrabFocus(); +} + +ExtrusionDirectionWindow::~ExtrusionDirectionWindow() +{ +} + +void ExtrusionDirectionWindow::implSetDirection( sal_Int32 nSkew, bool bEnabled ) +{ + sal_uInt16 nItemId; + for( nItemId = DIRECTION_NW; nItemId <= DIRECTION_SE; nItemId++ ) + { + if( gSkewList[nItemId] == nSkew ) + break; + } + + if( nItemId <= DIRECTION_SE ) + { + mxDirectionSet->SelectItem( nItemId+1 ); + } + else + { + mxDirectionSet->SetNoSelection(); + } + + if (bEnabled) + mxDirectionSet->Enable(); + else + mxDirectionSet->Disable(); +} + +void ExtrusionDirectionWindow::implSetProjection( sal_Int32 nProjection, bool bEnabled ) +{ + mxPerspective->set_active(nProjection == 0 && bEnabled); + mxParallel->set_active(nProjection == 1 && bEnabled); + mxPerspective->set_sensitive(bEnabled); + mxParallel->set_sensitive(bEnabled); +} + +void ExtrusionDirectionWindow::statusChanged( + const css::frame::FeatureStateEvent& Event +) +{ + if( Event.FeatureURL.Main == g_sExtrusionDirection ) + { + if( !Event.IsEnabled ) + { + implSetDirection( -1, false ); + } + else + { + sal_Int32 nValue = 0; + if( Event.State >>= nValue ) + implSetDirection( nValue, true ); + } + } + else if( Event.FeatureURL.Main == g_sExtrusionProjection ) + { + if( !Event.IsEnabled ) + { + implSetProjection( -1, false ); + } + else + { + sal_Int32 nValue = 0; + if( Event.State >>= nValue ) + implSetProjection( nValue, true ); + } + } +} + +IMPL_LINK_NOARG(ExtrusionDirectionWindow, SelectValueSetHdl, ValueSet*, void) +{ + Sequence< PropertyValue > aArgs( 1 ); + aArgs[0].Name = OUString(g_sExtrusionDirection).copy(5); + aArgs[0].Value <<= gSkewList[mxDirectionSet->GetSelectedItemId()-1]; + + mxControl->dispatchCommand( g_sExtrusionDirection, aArgs ); + + mxControl->EndPopupMode(); +} + +IMPL_LINK_NOARG(ExtrusionDirectionWindow, SelectToolbarMenuHdl, weld::Button&, void) +{ + int nProjection = mxPerspective->get_active() ? 0 : 1; + + Sequence< PropertyValue > aArgs( 1 ); + aArgs[0].Name = OUString(g_sExtrusionProjection).copy(5); + aArgs[0].Value <<= static_cast<sal_Int32>(nProjection); + + mxControl->dispatchCommand( g_sExtrusionProjection, aArgs ); + implSetProjection( nProjection, true ); + + mxControl->EndPopupMode(); +} + +ExtrusionDirectionControl::ExtrusionDirectionControl( + const Reference< XComponentContext >& rxContext +) : svt::PopupWindowController( + rxContext, + Reference< css::frame::XFrame >(), + ".uno:ExtrusionDirectionFloater" + ) +{ +} + +std::unique_ptr<WeldToolbarPopup> ExtrusionDirectionControl::weldPopupWindow() +{ + return std::make_unique<ExtrusionDirectionWindow>(this, m_pToolbar); +} + +VclPtr<vcl::Window> ExtrusionDirectionControl::createVclPopupWindow( vcl::Window* pParent ) +{ + mxInterimPopover = VclPtr<InterimToolbarPopup>::Create(getFrameInterface(), pParent, + std::make_unique<ExtrusionDirectionWindow>(this, pParent->GetFrameWeld())); + + mxInterimPopover->Show(); + + return mxInterimPopover; +} + +// XInitialization +void SAL_CALL ExtrusionDirectionControl::initialize( const css::uno::Sequence< css::uno::Any >& aArguments ) +{ + svt::PopupWindowController::initialize( aArguments ); + + ToolBox* pToolBox = nullptr; + sal_uInt16 nId = 0; + if ( getToolboxId( nId, &pToolBox ) ) + pToolBox->SetItemBits( nId, pToolBox->GetItemBits( nId ) | ToolBoxItemBits::DROPDOWNONLY ); +} + +// XServiceInfo + + +OUString ExtrusionDirectionControl::getImplementationName() +{ + return "com.sun.star.comp.svx.ExtrusionDirectionController"; +} + + +Sequence< OUString > ExtrusionDirectionControl::getSupportedServiceNames() +{ + return { "com.sun.star.frame.ToolbarController" }; +} + + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface* +com_sun_star_comp_svx_ExtrusionDirectionControl_get_implementation( + css::uno::XComponentContext* xContext, + css::uno::Sequence<css::uno::Any> const &) +{ + return cppu::acquire(new ExtrusionDirectionControl(xContext)); +} + + +ExtrusionDepthDialog::ExtrusionDepthDialog(weld::Window* pParent, double fDepth, FieldUnit eDefaultUnit) + : GenericDialogController(pParent, "svx/ui/extrustiondepthdialog.ui", "ExtrustionDepthDialog") + , m_xMtrDepth(m_xBuilder->weld_metric_spin_button("depth", eDefaultUnit)) +{ + m_xMtrDepth->set_value(static_cast<int>(fDepth) * 100, FieldUnit::MM_100TH); +} + +ExtrusionDepthDialog::~ExtrusionDepthDialog() +{ +} + +double ExtrusionDepthDialog::getDepth() const +{ + return static_cast<double>(m_xMtrDepth->get_value(FieldUnit::MM_100TH)) / 100.0; +} + +double const aDepthListInch[] = { 0, 1270,2540,5080,10160 }; +double const aDepthListMM[] = { 0, 1000, 2500, 5000, 10000 }; + +static const OUStringLiteral gsExtrusionDepth( ".uno:ExtrusionDepth" ); +static const OUStringLiteral gsMetricUnit( ".uno:MetricUnit" ); + +ExtrusionDepthWindow::ExtrusionDepthWindow(svt::PopupWindowController* pControl, weld::Widget* pParent) + : WeldToolbarPopup(pControl->getFrameInterface(), pParent, "svx/ui/depthwindow.ui", "DepthWindow") + , mxControl(pControl) + , mxDepth0(m_xBuilder->weld_radio_button("depth0")) + , mxDepth1(m_xBuilder->weld_radio_button("depth1")) + , mxDepth2(m_xBuilder->weld_radio_button("depth2")) + , mxDepth3(m_xBuilder->weld_radio_button("depth3")) + , mxDepth4(m_xBuilder->weld_radio_button("depth4")) + , mxInfinity(m_xBuilder->weld_radio_button("infinity")) + , mxCustom(m_xBuilder->weld_radio_button("custom")) + , meUnit(FieldUnit::NONE) + , mfDepth( -1.0 ) + , mbSettingValue(false) +{ + mxDepth0->connect_toggled(LINK(this, ExtrusionDepthWindow, SelectHdl)); + mxDepth1->connect_toggled(LINK(this, ExtrusionDepthWindow, SelectHdl)); + mxDepth2->connect_toggled(LINK(this, ExtrusionDepthWindow, SelectHdl)); + mxDepth3->connect_toggled(LINK(this, ExtrusionDepthWindow, SelectHdl)); + mxDepth4->connect_toggled(LINK(this, ExtrusionDepthWindow, SelectHdl)); + mxInfinity->connect_toggled(LINK(this, ExtrusionDepthWindow, SelectHdl)); + mxCustom->connect_clicked(LINK(this, ExtrusionDepthWindow, ClickHdl)); + + AddStatusListener( gsExtrusionDepth ); + AddStatusListener( gsMetricUnit ); +} + +void ExtrusionDepthWindow::GrabFocus() +{ + mxDepth0->grab_focus(); +} + +void ExtrusionDepthWindow::implSetDepth( double fDepth ) +{ + mfDepth = fDepth; + + bool bSettingValue = mbSettingValue; + mbSettingValue = true; + + mxCustom->set_active(true); + bool bIsMetric = IsMetric(meUnit); + mxDepth0->set_active(fDepth == (bIsMetric ? aDepthListMM[0] : aDepthListInch[0])); + mxDepth1->set_active(fDepth == (bIsMetric ? aDepthListMM[1] : aDepthListInch[1])); + mxDepth2->set_active(fDepth == (bIsMetric ? aDepthListMM[2] : aDepthListInch[2])); + mxDepth3->set_active(fDepth == (bIsMetric ? aDepthListMM[3] : aDepthListInch[3])); + mxDepth4->set_active(fDepth == (bIsMetric ? aDepthListMM[4] : aDepthListInch[4])); + mxInfinity->set_active(fDepth >= 338666); + + mbSettingValue = bSettingValue; +} + +void ExtrusionDepthWindow::implFillStrings( FieldUnit eUnit ) +{ + meUnit = eUnit; + + const char* aDepths[] = + { + RID_SVXSTR_DEPTH_0, + RID_SVXSTR_DEPTH_1, + RID_SVXSTR_DEPTH_2, + RID_SVXSTR_DEPTH_3, + RID_SVXSTR_DEPTH_4 + }; + + const char* aDepthsInch[] = + { + RID_SVXSTR_DEPTH_0_INCH, + RID_SVXSTR_DEPTH_1_INCH, + RID_SVXSTR_DEPTH_2_INCH, + RID_SVXSTR_DEPTH_3_INCH, + RID_SVXSTR_DEPTH_4_INCH + }; + + assert(SAL_N_ELEMENTS(aDepths) == SAL_N_ELEMENTS(aDepthsInch)); + + const char** pResource = IsMetric(eUnit) ? aDepths : aDepthsInch; + + mxDepth0->set_label(SvxResId(pResource[0])); + mxDepth1->set_label(SvxResId(pResource[1])); + mxDepth2->set_label(SvxResId(pResource[2])); + mxDepth3->set_label(SvxResId(pResource[3])); + mxDepth4->set_label(SvxResId(pResource[4])); +} + +void ExtrusionDepthWindow::statusChanged( + const css::frame::FeatureStateEvent& Event +) +{ + if( Event.FeatureURL.Main == gsExtrusionDepth ) + { + if( !Event.IsEnabled ) + { + implSetDepth( 0 ); + } + else + { + double fValue = 0.0; + if( Event.State >>= fValue ) + implSetDepth( fValue ); + } + } + else if( Event.FeatureURL.Main == gsMetricUnit ) + { + if( Event.IsEnabled ) + { + sal_Int32 nValue = 0; + if( Event.State >>= nValue ) + { + implFillStrings( static_cast<FieldUnit>(nValue) ); + if( mfDepth >= 0.0 ) + implSetDepth( mfDepth ); + } + } + } +} + +IMPL_LINK_NOARG(ExtrusionDepthWindow, ClickHdl, weld::Button&, void) +{ + SelectHdl(*mxCustom); +} + +IMPL_LINK(ExtrusionDepthWindow, SelectHdl, weld::ToggleButton&, rButton, void) +{ + if (mbSettingValue || !rButton.get_active()) + return; + + if (mxCustom->get_active()) + { + const OUString aCommand( ".uno:ExtrusionDepthDialog" ); + + Sequence< PropertyValue > aArgs( 2 ); + aArgs[0].Name = "Depth"; + aArgs[0].Value <<= mfDepth; + aArgs[1].Name = "Metric"; + aArgs[1].Value <<= static_cast<sal_Int32>( meUnit ); + + rtl::Reference<svt::PopupWindowController> xControl(mxControl); + xControl->EndPopupMode(); + xControl->dispatchCommand(aCommand, aArgs); + } + else + { + double fDepth; + + if (mxInfinity->get_active()) + { + fDepth = 338666.6; + } + else + { + int nSelected; + if (mxDepth0->get_active()) + nSelected = 0; + else if (mxDepth1->get_active()) + nSelected = 1; + else if (mxDepth2->get_active()) + nSelected = 2; + else if (mxDepth3->get_active()) + nSelected = 3; + else + nSelected = 4; + + fDepth = IsMetric( meUnit ) ? aDepthListMM[nSelected] : aDepthListInch[nSelected]; + } + + Sequence< PropertyValue > aArgs( 1 ); + aArgs[0].Name = OUString(gsExtrusionDepth).copy(5); + aArgs[0].Value <<= fDepth; + + mxControl->dispatchCommand( gsExtrusionDepth, aArgs ); + implSetDepth( fDepth ); + + mxControl->EndPopupMode(); + } +} + +// ExtrusionDirectionControl +ExtrusionDepthController::ExtrusionDepthController( + const Reference< XComponentContext >& rxContext +) : svt::PopupWindowController( + rxContext, + Reference< css::frame::XFrame >(), + ".uno:ExtrusionDepthFloater" + ) +{ +} + +std::unique_ptr<WeldToolbarPopup> ExtrusionDepthController::weldPopupWindow() +{ + return std::make_unique<ExtrusionDepthWindow>(this, m_pToolbar); +} + +VclPtr<vcl::Window> ExtrusionDepthController::createVclPopupWindow( vcl::Window* pParent ) +{ + mxInterimPopover = VclPtr<InterimToolbarPopup>::Create(getFrameInterface(), pParent, + std::make_unique<ExtrusionDepthWindow>(this, pParent->GetFrameWeld())); + + mxInterimPopover->Show(); + + return mxInterimPopover; +} + +// XInitialization +void SAL_CALL ExtrusionDepthController::initialize( const css::uno::Sequence< css::uno::Any >& aArguments ) +{ + svt::PopupWindowController::initialize( aArguments ); + + ToolBox* pToolBox = nullptr; + sal_uInt16 nId = 0; + if ( getToolboxId( nId, &pToolBox ) ) + pToolBox->SetItemBits( nId, pToolBox->GetItemBits( nId ) | ToolBoxItemBits::DROPDOWNONLY ); +} + +// XServiceInfo + + +OUString ExtrusionDepthController::getImplementationName() +{ + return "com.sun.star.comp.svx.ExtrusionDepthController"; +} + + +Sequence< OUString > ExtrusionDepthController::getSupportedServiceNames() +{ + return { "com.sun.star.frame.ToolbarController" }; +} + + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface* +com_sun_star_comp_svx_ExtrusionDepthController_get_implementation( + css::uno::XComponentContext* xContext, + css::uno::Sequence<css::uno::Any> const &) +{ + return cppu::acquire(new ExtrusionDepthController(xContext)); +} + + +static const char g_sExtrusionLightingDirection[] = ".uno:ExtrusionLightingDirection"; +static const char g_sExtrusionLightingIntensity[] = ".uno:ExtrusionLightingIntensity"; + +ExtrusionLightingWindow::ExtrusionLightingWindow(svt::PopupWindowController* pControl, + weld::Widget* pParent) + : WeldToolbarPopup(pControl->getFrameInterface(), pParent, "svx/ui/lightingwindow.ui", "LightingWindow") + , mxControl(pControl) + , mxLightingSet(new ValueSet(nullptr)) + , mxLightingSetWin(new weld::CustomWeld(*m_xBuilder, "valueset", *mxLightingSet)) + , mxBright(m_xBuilder->weld_radio_button("bright")) + , mxNormal(m_xBuilder->weld_radio_button("normal")) + , mxDim(m_xBuilder->weld_radio_button("dim")) +{ + mxLightingSet->SetStyle(WB_TABSTOP | WB_MENUSTYLEVALUESET | WB_FLATVALUESET | WB_NOBORDER | WB_NO_DIRECTSELECT); + + for (sal_uInt16 i = FROM_TOP_LEFT; i <= FROM_BOTTOM_RIGHT; ++i) + { + if( i != FROM_FRONT ) + { + maImgLightingOff[i] = Image(StockImage::Yes, aLightOffBmps[i]); + maImgLightingOn[i] = Image(StockImage::Yes, aLightOnBmps[i]); + } + maImgLightingPreview[i] = Image(StockImage::Yes, aLightPreviewBmps[i]); + } + + mxLightingSet->SetHelpId( HID_VALUESET_EXTRUSION_LIGHTING ); + + mxLightingSet->SetSelectHdl( LINK( this, ExtrusionLightingWindow, SelectValueSetHdl ) ); + mxLightingSet->SetColCount( 3 ); + mxLightingSet->EnableFullItemMode( false ); + + for (sal_uInt16 i = FROM_TOP_LEFT; i <= FROM_BOTTOM_RIGHT; ++i) + { + if( i != FROM_FRONT ) + { + mxLightingSet->InsertItem( i+1, maImgLightingOff[i] ); + } + else + { + mxLightingSet->InsertItem( 5, maImgLightingPreview[FROM_FRONT] ); + } + } + Size aSize(72, 72); + mxLightingSet->GetDrawingArea()->set_size_request(aSize.Width(), aSize.Height()); + mxLightingSet->SetOutputSizePixel(aSize); + + mxBright->connect_clicked(LINK(this, ExtrusionLightingWindow, SelectToolbarMenuHdl)); + mxNormal->connect_clicked(LINK(this, ExtrusionLightingWindow, SelectToolbarMenuHdl)); + mxDim->connect_clicked(LINK(this, ExtrusionLightingWindow, SelectToolbarMenuHdl)); + + AddStatusListener( g_sExtrusionLightingDirection ); + AddStatusListener( g_sExtrusionLightingIntensity ); +} + +void ExtrusionLightingWindow::GrabFocus() +{ + mxLightingSet->GrabFocus(); +} + +ExtrusionLightingWindow::~ExtrusionLightingWindow() +{ +} + +void ExtrusionLightingWindow::implSetIntensity( int nLevel, bool bEnabled ) +{ + mxBright->set_sensitive(bEnabled); + mxBright->set_active(nLevel == 0 && bEnabled); + mxNormal->set_sensitive(bEnabled); + mxNormal->set_active(nLevel == 1 && bEnabled); + mxDim->set_sensitive(bEnabled); + mxDim->set_active(nLevel == 2 && bEnabled); +} + +void ExtrusionLightingWindow::implSetDirection( int nDirection, bool bEnabled ) +{ + if( !bEnabled ) + nDirection = FROM_FRONT; + + sal_uInt16 nItemId; + for( nItemId = FROM_TOP_LEFT; nItemId <= FROM_BOTTOM_RIGHT; nItemId++ ) + { + if( nItemId == FROM_FRONT ) + { + mxLightingSet->SetItemImage( nItemId + 1, maImgLightingPreview[ nDirection ] ); + } + else + { + mxLightingSet->SetItemImage( + nItemId + 1, + static_cast<sal_uInt16>(nDirection) == nItemId ? maImgLightingOn[nItemId] : maImgLightingOff[nItemId] + ); + } + } + + if (bEnabled) + mxLightingSet->Enable(); + else + mxLightingSet->Disable(); +} + +void ExtrusionLightingWindow::statusChanged( + const css::frame::FeatureStateEvent& Event +) +{ + if( Event.FeatureURL.Main == g_sExtrusionLightingIntensity ) + { + if( !Event.IsEnabled ) + { + implSetIntensity( 0, false ); + } + else + { + sal_Int32 nValue = 0; + if( Event.State >>= nValue ) + implSetIntensity( nValue, true ); + } + } + else if( Event.FeatureURL.Main == g_sExtrusionLightingDirection ) + { + if( !Event.IsEnabled ) + { + implSetDirection( 0, false ); + } + else + { + sal_Int32 nValue = 0; + if( Event.State >>= nValue ) + implSetDirection( nValue, true ); + } + } +} + +IMPL_LINK_NOARG(ExtrusionLightingWindow, SelectValueSetHdl, ValueSet*, void) +{ + sal_Int32 nDirection = mxLightingSet->GetSelectedItemId(); + + if( (nDirection > 0) && (nDirection < 10) ) + { + nDirection--; + + Sequence< PropertyValue > aArgs( 1 ); + aArgs[0].Name = OUString(g_sExtrusionLightingDirection).copy(5); + aArgs[0].Value <<= nDirection; + + mxControl->dispatchCommand( g_sExtrusionLightingDirection, aArgs ); + + implSetDirection( nDirection, true ); + } + + mxControl->EndPopupMode(); +} + +IMPL_LINK_NOARG(ExtrusionLightingWindow, SelectToolbarMenuHdl, weld::Button&, void) +{ + int nLevel; + if (mxBright->get_active()) + nLevel = 0; + else if (mxNormal->get_active()) + nLevel = 1; + else + nLevel = 2; + + Sequence< PropertyValue > aArgs( 1 ); + aArgs[0].Name = OUString(g_sExtrusionLightingIntensity).copy(5); + aArgs[0].Value <<= static_cast<sal_Int32>(nLevel); + + mxControl->dispatchCommand( g_sExtrusionLightingIntensity, aArgs ); + + implSetIntensity( nLevel, true ); + + mxControl->EndPopupMode(); +} + +ExtrusionLightingControl::ExtrusionLightingControl( + const Reference< XComponentContext >& rxContext +) : svt::PopupWindowController( rxContext, + Reference< css::frame::XFrame >(), + ".uno:ExtrusionDirectionFloater" + ) +{ +} + +std::unique_ptr<WeldToolbarPopup> ExtrusionLightingControl::weldPopupWindow() +{ + return std::make_unique<ExtrusionLightingWindow>(this, m_pToolbar); +} + +VclPtr<vcl::Window> ExtrusionLightingControl::createVclPopupWindow( vcl::Window* pParent ) +{ + mxInterimPopover = VclPtr<InterimToolbarPopup>::Create(getFrameInterface(), pParent, + std::make_unique<ExtrusionLightingWindow>(this, pParent->GetFrameWeld())); + + mxInterimPopover->Show(); + + return mxInterimPopover; +} + +// XInitialization +void SAL_CALL ExtrusionLightingControl::initialize( const css::uno::Sequence< css::uno::Any >& aArguments ) +{ + svt::PopupWindowController::initialize( aArguments ); + + ToolBox* pToolBox = nullptr; + sal_uInt16 nId = 0; + if ( getToolboxId( nId, &pToolBox ) ) + pToolBox->SetItemBits( nId, pToolBox->GetItemBits( nId ) | ToolBoxItemBits::DROPDOWNONLY ); +} + +// XServiceInfo + + +OUString ExtrusionLightingControl::getImplementationName() +{ + return "com.sun.star.comp.svx.ExtrusionLightingController"; +} + + +Sequence< OUString > ExtrusionLightingControl::getSupportedServiceNames() +{ + return { "com.sun.star.frame.ToolbarController" }; +} + + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface* +com_sun_star_comp_svx_ExtrusionLightingControl_get_implementation( + css::uno::XComponentContext* xContext, + css::uno::Sequence<css::uno::Any> const &) +{ + return cppu::acquire(new ExtrusionLightingControl(xContext)); +} + + +static const char g_sExtrusionSurface[] = ".uno:ExtrusionSurface"; + +ExtrusionSurfaceWindow::ExtrusionSurfaceWindow(svt::PopupWindowController* pControl, weld::Widget* pParent) + : WeldToolbarPopup(pControl->getFrameInterface(), pParent, "svx/ui/surfacewindow.ui", "SurfaceWindow") + , mxControl(pControl) + , mxWireFrame(m_xBuilder->weld_radio_button("wireframe")) + , mxMatt(m_xBuilder->weld_radio_button("matt")) + , mxPlastic(m_xBuilder->weld_radio_button("plastic")) + , mxMetal(m_xBuilder->weld_radio_button("metal")) +{ + mxWireFrame->connect_clicked(LINK(this, ExtrusionSurfaceWindow, SelectHdl)); + mxMatt->connect_clicked(LINK(this, ExtrusionSurfaceWindow, SelectHdl)); + mxPlastic->connect_clicked(LINK(this, ExtrusionSurfaceWindow, SelectHdl)); + mxMetal->connect_clicked(LINK(this, ExtrusionSurfaceWindow, SelectHdl)); + + AddStatusListener( g_sExtrusionSurface ); +} + +void ExtrusionSurfaceWindow::GrabFocus() +{ + mxWireFrame->grab_focus(); +} + +void ExtrusionSurfaceWindow::implSetSurface( int nSurface, bool bEnabled ) +{ + mxWireFrame->set_active(nSurface == 0 && bEnabled); + mxWireFrame->set_sensitive(bEnabled); + mxMatt->set_active(nSurface == 1 && bEnabled); + mxMatt->set_sensitive(bEnabled); + mxPlastic->set_active(nSurface == 2 && bEnabled); + mxPlastic->set_sensitive(bEnabled); + mxMetal->set_active(nSurface == 3 && bEnabled); + mxMetal->set_sensitive(bEnabled); +} + +void ExtrusionSurfaceWindow::statusChanged( + const css::frame::FeatureStateEvent& Event +) +{ + if( Event.FeatureURL.Main == g_sExtrusionSurface ) + { + if( !Event.IsEnabled ) + { + implSetSurface( 0, false ); + } + else + { + sal_Int32 nValue = 0; + if( Event.State >>= nValue ) + implSetSurface( nValue, true ); + } + } +} + +IMPL_LINK_NOARG(ExtrusionSurfaceWindow, SelectHdl, weld::Button&, void) +{ + sal_Int32 nSurface; + if (mxWireFrame->get_active()) + nSurface = 0; + else if (mxMatt->get_active()) + nSurface = 1; + else if (mxPlastic->get_active()) + nSurface = 2; + else + nSurface = 3; + + Sequence< PropertyValue > aArgs( 1 ); + aArgs[0].Name = OUString(g_sExtrusionSurface).copy(5); + aArgs[0].Value <<= nSurface; + + mxControl->dispatchCommand( g_sExtrusionSurface, aArgs ); + + implSetSurface( nSurface, true ); + + mxControl->EndPopupMode(); +} + +ExtrusionSurfaceControl::ExtrusionSurfaceControl( + const Reference< XComponentContext >& rxContext +) +: svt::PopupWindowController( + rxContext, + Reference< css::frame::XFrame >(), + ".uno:ExtrusionSurfaceFloater" + ) +{ +} + +std::unique_ptr<WeldToolbarPopup> ExtrusionSurfaceControl::weldPopupWindow() +{ + return std::make_unique<ExtrusionSurfaceWindow>(this, m_pToolbar); +} + +VclPtr<vcl::Window> ExtrusionSurfaceControl::createVclPopupWindow( vcl::Window* pParent ) +{ + mxInterimPopover = VclPtr<InterimToolbarPopup>::Create(getFrameInterface(), pParent, + std::make_unique<ExtrusionSurfaceWindow>(this, pParent->GetFrameWeld())); + + mxInterimPopover->Show(); + + return mxInterimPopover; +} + +// XInitialization +void SAL_CALL ExtrusionSurfaceControl::initialize( const css::uno::Sequence< css::uno::Any >& aArguments ) +{ + svt::PopupWindowController::initialize( aArguments ); + + ToolBox* pToolBox = nullptr; + sal_uInt16 nId = 0; + if ( getToolboxId( nId, &pToolBox ) ) + pToolBox->SetItemBits( nId, pToolBox->GetItemBits( nId ) | ToolBoxItemBits::DROPDOWNONLY ); +} + +// XServiceInfo + + +OUString ExtrusionSurfaceControl::getImplementationName() +{ + return "com.sun.star.comp.svx.ExtrusionSurfaceController"; +} + + +Sequence< OUString > ExtrusionSurfaceControl::getSupportedServiceNames() +{ + return { "com.sun.star.frame.ToolbarController" }; +} + + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface* +com_sun_star_comp_svx_ExtrusionSurfaceControl_get_implementation( + css::uno::XComponentContext* xContext, + css::uno::Sequence<css::uno::Any> const &) +{ + return cppu::acquire(new ExtrusionSurfaceControl(xContext)); +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/tbxctrls/extrusioncontrols.hxx b/svx/source/tbxctrls/extrusioncontrols.hxx new file mode 100644 index 000000000..0a051e2c4 --- /dev/null +++ b/svx/source/tbxctrls/extrusioncontrols.hxx @@ -0,0 +1,220 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_SVX_SOURCE_TBXCTRLS_EXTRUSIONCONTROLS_HXX +#define INCLUDED_SVX_SOURCE_TBXCTRLS_EXTRUSIONCONTROLS_HXX + +#include <svtools/toolbarmenu.hxx> +#include <svtools/popupwindowcontroller.hxx> +#include <svtools/valueset.hxx> +#include <vcl/customweld.hxx> + +// enum to index light images +#define FROM_TOP_LEFT 0 +#define FROM_TOP 1 +#define FROM_TOP_RIGHT 2 +#define FROM_LEFT 3 +#define FROM_FRONT 4 +#define FROM_RIGHT 5 +#define FROM_BOTTOM_LEFT 6 +#define FROM_BOTTOM 7 +#define FROM_BOTTOM_RIGHT 8 + +#define DIRECTION_NW 0 +#define DIRECTION_N 1 +#define DIRECTION_NE 2 +#define DIRECTION_W 3 +#define DIRECTION_NONE 4 +#define DIRECTION_E 5 +#define DIRECTION_SW 6 +#define DIRECTION_S 7 +#define DIRECTION_SE 8 + +namespace svx +{ +class ExtrusionDirectionWindow final : public WeldToolbarPopup +{ +public: + ExtrusionDirectionWindow(svt::PopupWindowController* pControl, weld::Widget* pParentWindow); + virtual void GrabFocus() override; + virtual ~ExtrusionDirectionWindow() override; + + virtual void statusChanged( const css::frame::FeatureStateEvent& Event ) override; + +private: + rtl::Reference<svt::PopupWindowController> mxControl; + std::unique_ptr<ValueSet> mxDirectionSet; + std::unique_ptr<weld::CustomWeld> mxDirectionSetWin; + std::unique_ptr<weld::RadioButton> mxPerspective; + std::unique_ptr<weld::RadioButton> mxParallel; + + Image maImgDirection[9]; + + DECL_LINK( SelectToolbarMenuHdl, weld::Button&, void ); + DECL_LINK( SelectValueSetHdl, ValueSet*, void ); + + void implSetDirection( sal_Int32 nSkew, bool bEnabled ); + void implSetProjection( sal_Int32 nProjection, bool bEnabled ); + +}; + +class ExtrusionDirectionControl : public svt::PopupWindowController +{ +public: + explicit ExtrusionDirectionControl( const css::uno::Reference< css::uno::XComponentContext >& rxContext ); + + virtual std::unique_ptr<WeldToolbarPopup> weldPopupWindow() override; + virtual VclPtr<vcl::Window> createVclPopupWindow( vcl::Window* pParent ) override; + + // XInitialization + virtual void SAL_CALL initialize( const css::uno::Sequence< css::uno::Any >& aArguments ) override; + + // XServiceInfo + virtual OUString SAL_CALL getImplementationName() override; + virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override; +}; + +class ExtrusionDepthWindow final : public WeldToolbarPopup +{ +private: + rtl::Reference<svt::PopupWindowController> mxControl; + std::unique_ptr<weld::RadioButton> mxDepth0; + std::unique_ptr<weld::RadioButton> mxDepth1; + std::unique_ptr<weld::RadioButton> mxDepth2; + std::unique_ptr<weld::RadioButton> mxDepth3; + std::unique_ptr<weld::RadioButton> mxDepth4; + std::unique_ptr<weld::RadioButton> mxInfinity; + std::unique_ptr<weld::RadioButton> mxCustom; + + FieldUnit meUnit; + double mfDepth; + bool mbSettingValue; + + DECL_LINK( SelectHdl, weld::ToggleButton&, void ); + DECL_LINK( ClickHdl, weld::Button&, void ); + + void implFillStrings( FieldUnit eUnit ); + void implSetDepth( double fDepth ); + +public: + ExtrusionDepthWindow(svt::PopupWindowController* pControl, weld::Widget* pParentWindow); + virtual void GrabFocus() override; + + virtual void statusChanged( const css::frame::FeatureStateEvent& Event ) override; +}; + +class ExtrusionDepthController : public svt::PopupWindowController +{ +public: + explicit ExtrusionDepthController( const css::uno::Reference< css::uno::XComponentContext >& rxContext ); + + virtual std::unique_ptr<WeldToolbarPopup> weldPopupWindow() override; + virtual VclPtr<vcl::Window> createVclPopupWindow( vcl::Window* pParent ) override; + + // XInitialization + virtual void SAL_CALL initialize( const css::uno::Sequence< css::uno::Any >& aArguments ) override; + + // XServiceInfo + virtual OUString SAL_CALL getImplementationName() override; + virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override; +}; + +class ExtrusionLightingWindow final : public WeldToolbarPopup +{ +private: + rtl::Reference<svt::PopupWindowController> mxControl; + std::unique_ptr<ValueSet> mxLightingSet; + std::unique_ptr<weld::CustomWeld> mxLightingSetWin; + std::unique_ptr<weld::RadioButton> mxBright; + std::unique_ptr<weld::RadioButton> mxNormal; + std::unique_ptr<weld::RadioButton> mxDim; + + Image maImgLightingOff[9]; + Image maImgLightingOn[9]; + Image maImgLightingPreview[9]; + + void implSetIntensity( int nLevel, bool bEnabled ); + void implSetDirection( int nDirection, bool bEnabled ); + + DECL_LINK( SelectToolbarMenuHdl, weld::Button&, void ); + DECL_LINK( SelectValueSetHdl, ValueSet*, void ); +public: + ExtrusionLightingWindow(svt::PopupWindowController* pControl, weld::Widget* pParentWindow); + virtual void GrabFocus() override; + virtual ~ExtrusionLightingWindow() override; + + virtual void statusChanged( const css::frame::FeatureStateEvent& Event ) override; +}; + +class ExtrusionLightingControl : public svt::PopupWindowController +{ +public: + explicit ExtrusionLightingControl( const css::uno::Reference< css::uno::XComponentContext >& rxContext ); + + virtual std::unique_ptr<WeldToolbarPopup> weldPopupWindow() override; + virtual VclPtr<vcl::Window> createVclPopupWindow( vcl::Window* pParent ) override; + + // XInitialization + virtual void SAL_CALL initialize( const css::uno::Sequence< css::uno::Any >& aArguments ) override; + + // XServiceInfo + virtual OUString SAL_CALL getImplementationName() override; + virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override; +}; + +class ExtrusionSurfaceWindow final : public WeldToolbarPopup +{ +private: + rtl::Reference<svt::PopupWindowController> mxControl; + std::unique_ptr<weld::RadioButton> mxWireFrame; + std::unique_ptr<weld::RadioButton> mxMatt; + std::unique_ptr<weld::RadioButton> mxPlastic; + std::unique_ptr<weld::RadioButton> mxMetal; + + DECL_LINK( SelectHdl, weld::Button&, void ); + + void implSetSurface( int nSurface, bool bEnabled ); + +public: + ExtrusionSurfaceWindow(svt::PopupWindowController* pControl, weld::Widget* pParentWindow); + virtual void GrabFocus() override; + + virtual void statusChanged( const css::frame::FeatureStateEvent& Event ) override; +}; + + +class ExtrusionSurfaceControl : public svt::PopupWindowController +{ +public: + explicit ExtrusionSurfaceControl( const css::uno::Reference< css::uno::XComponentContext >& rxContext ); + + virtual std::unique_ptr<WeldToolbarPopup> weldPopupWindow() override; + virtual VclPtr<vcl::Window> createVclPopupWindow( vcl::Window* pParent ) override; + + // XInitialization + virtual void SAL_CALL initialize( const css::uno::Sequence< css::uno::Any >& aArguments ) override; + + // XServiceInfo + virtual OUString SAL_CALL getImplementationName() override; + virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override; +}; + +} +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/tbxctrls/fillctrl.cxx b/svx/source/tbxctrls/fillctrl.cxx new file mode 100644 index 000000000..588e77f07 --- /dev/null +++ b/svx/source/tbxctrls/fillctrl.cxx @@ -0,0 +1,979 @@ +/* -*- 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 <sfx2/dispatch.hxx> +#include <sfx2/objsh.hxx> +#include <sfx2/viewfrm.hxx> +#include <sfx2/viewsh.hxx> +#include <rtl/ustring.hxx> +#include <vcl/event.hxx> +#include <vcl/settings.hxx> +#include <vcl/toolbox.hxx> +#include <svx/svxids.hrc> + +#define TMP_STR_BEGIN "[" +#define TMP_STR_END "]" + +#include <svx/drawitem.hxx> +#include <svx/xfillit0.hxx> +#include <svx/xtable.hxx> +#include <svx/fillctrl.hxx> +#include <svx/itemwin.hxx> +#include <svx/xflclit.hxx> +#include <svx/xflgrit.hxx> +#include <svx/xflhtit.hxx> +#include <svx/xbtmpit.hxx> +#include <boost/property_tree/ptree.hpp> +#include <memory> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::util; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::lang; + +SFX_IMPL_TOOLBOX_CONTROL( SvxFillToolBoxControl, XFillStyleItem ); + +SvxFillToolBoxControl::SvxFillToolBoxControl( + sal_uInt16 nSlotId, + sal_uInt16 nId, + ToolBox& rTbx ) + : SfxToolBoxControl( nSlotId, nId, rTbx ) + , mpStyleItem() + , mpColorItem() + , mpFillGradientItem() + , mpHatchItem() + , mpBitmapItem() + , mxFillControl(nullptr) + , mpLbFillType(nullptr) + , mpToolBoxColor(nullptr) + , mpLbFillAttr(nullptr) + , meLastXFS(static_cast<drawing::FillStyle>(-1)) + , mnLastPosGradient(0) + , mnLastPosHatch(0) + , mnLastPosBitmap(0) +{ + addStatusListener( ".uno:FillColor"); + addStatusListener( ".uno:FillGradient"); + addStatusListener( ".uno:FillHatch"); + addStatusListener( ".uno:FillBitmap"); + addStatusListener( ".uno:ColorTableState"); + addStatusListener( ".uno:GradientListState"); + addStatusListener( ".uno:HatchListState"); + addStatusListener( ".uno:BitmapListState"); +} + +SvxFillToolBoxControl::~SvxFillToolBoxControl() +{ +} + +void SvxFillToolBoxControl::StateChanged( + sal_uInt16 nSID, + SfxItemState eState, + const SfxPoolItem* pState) +{ + const bool bDisabled(SfxItemState::DISABLED == eState); + + switch(nSID) + { + case SID_ATTR_FILL_STYLE: + { + if(bDisabled) + { + mpLbFillType->set_sensitive(false); + mpLbFillType->set_active(-1); + mpLbFillAttr->show(); + mpLbFillAttr->set_sensitive(false); + mpLbFillAttr->set_active(-1); + mpToolBoxColor->hide(); + meLastXFS = static_cast<drawing::FillStyle>(-1); + mpStyleItem.reset(); + } + + if(eState >= SfxItemState::DEFAULT) + { + const XFillStyleItem* pItem = dynamic_cast< const XFillStyleItem* >(pState); + + if(pItem) + { + mpStyleItem.reset(pItem->Clone()); + mpLbFillType->set_sensitive(true); + drawing::FillStyle eXFS = mpStyleItem->GetValue(); + meLastXFS = eXFS; + mpLbFillType->set_active(sal::static_int_cast< sal_Int32 >(eXFS)); + + if(drawing::FillStyle_NONE == eXFS) + { + mpLbFillAttr->set_active(-1); + mpLbFillAttr->set_sensitive(false); + } + + Update(); + break; + } + } + + mpLbFillType->set_active(-1); + mpLbFillAttr->show(); + mpLbFillAttr->set_sensitive(false); + mpLbFillAttr->set_active(-1); + mpToolBoxColor->hide(); + meLastXFS = static_cast<drawing::FillStyle>(-1); + mpStyleItem.reset(); + mxFillControl->Resize(); + break; + } + case SID_ATTR_FILL_COLOR: + { + if(SfxItemState::DEFAULT == eState) + { + mpColorItem.reset(pState ? static_cast<XFillColorItem*>(pState->Clone()) : nullptr); + } + + if(mpStyleItem && drawing::FillStyle_SOLID == mpStyleItem->GetValue()) + { + mpLbFillAttr->hide(); + mpToolBoxColor->show(); + mxFillControl->Resize(); + + Update(); + } + break; + } + case SID_ATTR_FILL_GRADIENT: + { + if(SfxItemState::DEFAULT == eState) + { + mpFillGradientItem.reset(pState ? static_cast<XFillGradientItem*>(pState->Clone()) : nullptr); + } + + if(mpStyleItem && drawing::FillStyle_GRADIENT == mpStyleItem->GetValue()) + { + mpLbFillAttr->show(); + mpToolBoxColor->hide(); + mxFillControl->Resize(); + + if(SfxItemState::DEFAULT == eState) + { + mpLbFillAttr->set_sensitive(true); + Update(); + } + else if(SfxItemState::DISABLED == eState ) + { + mpLbFillAttr->set_sensitive(false); + mpLbFillAttr->set_active(-1); + } + else + { + mpLbFillAttr->set_active(-1); + } + } + break; + } + case SID_ATTR_FILL_HATCH: + { + if(SfxItemState::DEFAULT == eState) + { + mpHatchItem.reset(pState ? static_cast<XFillHatchItem*>(pState->Clone()) : nullptr); + } + + if(mpStyleItem && drawing::FillStyle_HATCH == mpStyleItem->GetValue()) + { + mpLbFillAttr->show(); + mpToolBoxColor->hide(); + mxFillControl->Resize(); + + if(SfxItemState::DEFAULT == eState) + { + mpLbFillAttr->set_sensitive(true); + Update(); + } + else if(SfxItemState::DISABLED == eState ) + { + mpLbFillAttr->set_sensitive(false); + mpLbFillAttr->set_active(-1); + } + else + { + mpLbFillAttr->set_active(-1); + } + } + break; + } + case SID_ATTR_FILL_BITMAP: + { + if(SfxItemState::DEFAULT == eState) + { + mpBitmapItem.reset(pState ? static_cast<XFillBitmapItem*>(pState->Clone()) : nullptr); + } + + if(mpStyleItem && drawing::FillStyle_BITMAP == mpStyleItem->GetValue()) + { + mpLbFillAttr->show(); + mpToolBoxColor->hide(); + mxFillControl->Resize(); + + if(SfxItemState::DEFAULT == eState) + { + mpLbFillAttr->set_sensitive(true); + Update(); + } + else if(SfxItemState::DISABLED == eState ) + { + mpLbFillAttr->set_sensitive(false); + mpLbFillAttr->set_active(-1); + } + else + { + mpLbFillAttr->set_active(-1); + } + } + break; + } + case SID_GRADIENT_LIST: + { + if(SfxItemState::DEFAULT == eState) + { + if(mpStyleItem && drawing::FillStyle_GRADIENT == mpStyleItem->GetValue()) + { + if(mpFillGradientItem) + { + const OUString aString( mpFillGradientItem->GetName() ); + const SfxObjectShell* pSh = SfxObjectShell::Current(); + + mpLbFillAttr->clear(); + mpLbFillAttr->set_sensitive(true); + SvxFillAttrBox::Fill(*mpLbFillAttr, pSh->GetItem(SID_GRADIENT_LIST)->GetGradientList()); + mpLbFillAttr->set_active_text(aString); + } + else + { + mpLbFillAttr->set_active(-1); + } + } + } + break; + } + case SID_HATCH_LIST: + { + if(SfxItemState::DEFAULT == eState) + { + if(mpStyleItem && drawing::FillStyle_HATCH == mpStyleItem->GetValue()) + { + if(mpHatchItem) + { + const OUString aString( mpHatchItem->GetName() ); + const SfxObjectShell* pSh = SfxObjectShell::Current(); + + mpLbFillAttr->clear(); + mpLbFillAttr->set_sensitive(true); + SvxFillAttrBox::Fill(*mpLbFillAttr, pSh->GetItem(SID_HATCH_LIST)->GetHatchList()); + mpLbFillAttr->set_active_text(aString); + } + else + { + mpLbFillAttr->set_active(-1); + } + } + } + break; + } + case SID_BITMAP_LIST: + { + if(SfxItemState::DEFAULT == eState) + { + if(mpStyleItem && drawing::FillStyle_BITMAP == mpStyleItem->GetValue()) + { + if(mpBitmapItem) + { + const OUString aString( mpBitmapItem->GetName() ); + const SfxObjectShell* pSh = SfxObjectShell::Current(); + + mpLbFillAttr->clear(); + mpLbFillAttr->set_sensitive(true); + SvxFillAttrBox::Fill(*mpLbFillAttr, pSh->GetItem(SID_BITMAP_LIST)->GetBitmapList()); + mpLbFillAttr->set_active_text(aString); + } + else + { + mpLbFillAttr->set_active(-1); + } + } + } + break; + } + } +} + +void SvxFillToolBoxControl::Update() +{ + if(mpStyleItem) + { + const drawing::FillStyle eXFS = mpStyleItem->GetValue(); + SfxObjectShell* pSh = SfxObjectShell::Current(); + + switch( eXFS ) + { + case drawing::FillStyle_NONE: + { + mpLbFillAttr->show(); + mpToolBoxColor->hide(); + mxFillControl->Resize(); + break; + } + case drawing::FillStyle_SOLID: + { + if(mpColorItem) + { + mpLbFillAttr->hide(); + mpToolBoxColor->show(); + mxFillControl->Resize(); + } + break; + } + case drawing::FillStyle_GRADIENT: + { + mpLbFillAttr->show(); + mpToolBoxColor->hide(); + mxFillControl->Resize(); + + if(pSh && pSh->GetItem(SID_GRADIENT_LIST)) + { + mpLbFillAttr->set_sensitive(true); + mpLbFillAttr->clear(); + SvxFillAttrBox::Fill(*mpLbFillAttr, pSh->GetItem(SID_GRADIENT_LIST)->GetGradientList()); + + if(mpFillGradientItem) + { + const OUString aString(mpFillGradientItem->GetName()); + + mpLbFillAttr->set_active_text(aString); + + // Check if the entry is not in the list + if (mpLbFillAttr->get_active_text() != aString) + { + sal_Int32 nCount = mpLbFillAttr->get_count(); + OUString aTmpStr; + if( nCount > 0 ) + { + // Last entry gets tested against temporary entry + aTmpStr = mpLbFillAttr->get_text( nCount - 1 ); + if( aTmpStr.startsWith(TMP_STR_BEGIN) && + aTmpStr.endsWith(TMP_STR_END) ) + { + mpLbFillAttr->remove(nCount - 1); + } + } + aTmpStr = TMP_STR_BEGIN + aString + TMP_STR_END; + + XGradientList aGradientList( "", ""/*TODO?*/ ); + aGradientList.Insert(std::make_unique<XGradientEntry>(mpFillGradientItem->GetGradientValue(), aTmpStr)); + aGradientList.SetDirty( false ); + const BitmapEx aBmp = aGradientList.GetUiBitmap( 0 ); + + if (!aBmp.IsEmpty()) + { + ScopedVclPtrInstance< VirtualDevice > pVD; + const Size aBmpSize(aBmp.GetSizePixel()); + pVD->SetOutputSizePixel(aBmpSize, false); + pVD->DrawBitmapEx(Point(), aBmp); + mpLbFillAttr->append("", aGradientList.Get(0)->GetName(), *pVD); + mpLbFillAttr->set_active(mpLbFillAttr->get_count() - 1); + } + } + + } + else + { + mpLbFillAttr->set_active(-1); + } + } + else + { + mpLbFillAttr->set_active(-1); + } + break; + } + case drawing::FillStyle_HATCH: + { + mpLbFillAttr->show(); + mpToolBoxColor->hide(); + mxFillControl->Resize(); + + if(pSh && pSh->GetItem(SID_HATCH_LIST)) + { + mpLbFillAttr->set_sensitive(true); + mpLbFillAttr->clear(); + SvxFillAttrBox::Fill(*mpLbFillAttr, pSh->GetItem(SID_HATCH_LIST)->GetHatchList()); + + if(mpHatchItem) + { + const OUString aString(mpHatchItem->GetName()); + + mpLbFillAttr->set_active_text( aString ); + + // Check if the entry is not in the list + if( mpLbFillAttr->get_active_text() != aString ) + { + const sal_Int32 nCount = mpLbFillAttr->get_count(); + OUString aTmpStr; + if( nCount > 0 ) + { + // Last entry gets tested against temporary entry + aTmpStr = mpLbFillAttr->get_text( nCount - 1 ); + if( aTmpStr.startsWith(TMP_STR_BEGIN) && + aTmpStr.endsWith(TMP_STR_END) ) + { + mpLbFillAttr->remove( nCount - 1 ); + } + } + aTmpStr = TMP_STR_BEGIN + aString + TMP_STR_END; + + XHatchList aHatchList( "", ""/*TODO?*/ ); + aHatchList.Insert(std::make_unique<XHatchEntry>(mpHatchItem->GetHatchValue(), aTmpStr)); + aHatchList.SetDirty( false ); + const BitmapEx & aBmp = aHatchList.GetUiBitmap( 0 ); + + if( !aBmp.IsEmpty() ) + { + ScopedVclPtrInstance< VirtualDevice > pVD; + const Size aBmpSize(aBmp.GetSizePixel()); + pVD->SetOutputSizePixel(aBmpSize, false); + pVD->DrawBitmapEx(Point(), aBmp); + mpLbFillAttr->append("", aHatchList.GetHatch(0)->GetName(), *pVD); + mpLbFillAttr->set_active(mpLbFillAttr->get_count() - 1); + } + } + } + else + { + mpLbFillAttr->set_active(-1); + } + } + else + { + mpLbFillAttr->set_active(-1); + } + break; + } + case drawing::FillStyle_BITMAP: + { + mpLbFillAttr->show(); + mpToolBoxColor->hide(); + mxFillControl->Resize(); + + if(pSh && pSh->GetItem(SID_BITMAP_LIST)) + { + mpLbFillAttr->set_sensitive(true); + mpLbFillAttr->clear(); + SvxFillAttrBox::Fill(*mpLbFillAttr, pSh->GetItem(SID_BITMAP_LIST)->GetBitmapList()); + + if(mpBitmapItem) + { + const OUString aString(mpBitmapItem->GetName()); + + mpLbFillAttr->set_active_text(aString); + + // Check if the entry is not in the list + if (mpLbFillAttr->get_active_text() != aString) + { + sal_Int32 nCount = mpLbFillAttr->get_count(); + OUString aTmpStr; + if( nCount > 0 ) + { + // Last entry gets tested against temporary entry + aTmpStr = mpLbFillAttr->get_text(nCount - 1); + if( aTmpStr.startsWith(TMP_STR_BEGIN) && + aTmpStr.endsWith(TMP_STR_END) ) + { + mpLbFillAttr->remove(nCount - 1); + } + } + aTmpStr = TMP_STR_BEGIN + aString + TMP_STR_END; + + XBitmapListRef xBitmapList = + XPropertyList::AsBitmapList( + XPropertyList::CreatePropertyList( + XPropertyListType::Bitmap, "TmpList", ""/*TODO?*/)); + xBitmapList->Insert(std::make_unique<XBitmapEntry>(mpBitmapItem->GetGraphicObject(), aTmpStr)); + xBitmapList->SetDirty( false ); + SvxFillAttrBox::Fill(*mpLbFillAttr, xBitmapList); + mpLbFillAttr->set_active(mpLbFillAttr->get_count() - 1); + } + + } + else + { + mpLbFillAttr->set_active(-1); + } + } + else + { + mpLbFillAttr->set_active(-1); + } + break; + } + default: + OSL_ENSURE(false, "Non supported FillType (!)"); + break; + } + } + +} + +VclPtr<InterimItemWindow> SvxFillToolBoxControl::CreateItemWindow(vcl::Window *pParent) +{ + if(GetSlotId() == SID_ATTR_FILL_STYLE) + { + mxFillControl.reset(VclPtr<FillControl>::Create(pParent, m_xFrame)); + + mpLbFillType = mxFillControl->mxLbFillType.get(); + mpLbFillAttr = mxFillControl->mxLbFillAttr.get(); + mpToolBoxColor = mxFillControl->mxToolBoxColor.get(); + + mpLbFillType->connect_changed(LINK(this,SvxFillToolBoxControl,SelectFillTypeHdl)); + mpLbFillAttr->connect_changed(LINK(this,SvxFillToolBoxControl,SelectFillAttrHdl)); + + + return mxFillControl; + } + return VclPtr<InterimItemWindow>(); +} + +FillControl::FillControl(vcl::Window* pParent, const css::uno::Reference<css::frame::XFrame>& rFrame) + : InterimItemWindow(pParent, "svx/ui/fillctrlbox.ui", "FillCtrlBox") + , mxLbFillType(m_xBuilder->weld_combo_box("type")) + , mxToolBoxColor(m_xBuilder->weld_toolbar("color")) + , mxColorDispatch(new ToolbarUnoDispatcher(*mxToolBoxColor, *m_xBuilder, rFrame)) + , mxLbFillAttr(m_xBuilder->weld_combo_box("attr")) + , mnTypeCurPos(0) + , mnAttrCurPos(0) +{ + mxLbFillAttr->connect_key_press(LINK(this, FillControl, AttrKeyInputHdl)); + mxLbFillType->connect_key_press(LINK(this, FillControl, TypeKeyInputHdl)); + mxToolBoxColor->connect_key_press(LINK(this, FillControl, ColorKeyInputHdl)); + + mxLbFillType->connect_get_property_tree(LINK(this, FillControl, DumpAsPropertyTreeHdl)); + + mxLbFillType->connect_focus_in(LINK(this, FillControl, TypeFocusHdl)); + mxLbFillAttr->connect_focus_in(LINK(this, FillControl, AttrFocusHdl)); + + SvxFillTypeBox::Fill(*mxLbFillType); + + SetOptimalSize(); +} + +IMPL_STATIC_LINK(FillControl, DumpAsPropertyTreeHdl, boost::property_tree::ptree&, rTree, void) +{ + rTree.put("command", ".uno:FillStyle"); +} + +void FillControl::ReleaseFocus_Impl() +{ + SfxViewShell* pCurSh = SfxViewShell::Current(); + if (pCurSh) + { + vcl::Window* pShellWnd = pCurSh->GetWindow(); + if (pShellWnd) + pShellWnd->GrabFocus(); + } +} + +IMPL_LINK(FillControl, TypeKeyInputHdl, const KeyEvent&, rKEvt, bool) +{ + const vcl::KeyCode& rKeyCode = rKEvt.GetKeyCode(); + sal_uInt16 nCode = rKeyCode.GetCode(); + + if (nCode == KEY_ESCAPE) + { + mxLbFillType->set_active(mnTypeCurPos); + ReleaseFocus_Impl(); + return true; + } + + if (nCode != KEY_TAB) + return false; + if (rKeyCode.IsShift()) + return ChildKeyInput(rKEvt); + if (mxLbFillAttr->get_visible() && !mxLbFillAttr->get_sensitive()) + return ChildKeyInput(rKEvt); + return false; +} + +IMPL_LINK_NOARG(FillControl, TypeFocusHdl, weld::Widget&, void) +{ + mnTypeCurPos = mxLbFillType->get_active(); +} + +IMPL_LINK_NOARG(FillControl, AttrFocusHdl, weld::Widget&, void) +{ + mnAttrCurPos = mxLbFillAttr->get_active(); +} + +IMPL_LINK(FillControl, AttrKeyInputHdl, const KeyEvent&, rKEvt, bool) +{ + const vcl::KeyCode& rKeyCode = rKEvt.GetKeyCode(); + sal_uInt16 nCode = rKeyCode.GetCode(); + + if (nCode == KEY_ESCAPE) + { + mxLbFillAttr->set_active(mnAttrCurPos); + ReleaseFocus_Impl(); + return true; + } + + return ChildKeyInput(rKEvt); +} + +IMPL_LINK(FillControl, ColorKeyInputHdl, const KeyEvent&, rKEvt, bool) +{ + return ChildKeyInput(rKEvt); +} + +void FillControl::GetFocus() +{ + if (mxLbFillType) + mxLbFillType->grab_focus(); + InterimItemWindow::GetFocus(); +} + +FillControl::~FillControl() +{ + disposeOnce(); +} + +void FillControl::dispose() +{ + mxLbFillAttr.reset(); + mxColorDispatch.reset(); + mxToolBoxColor.reset(); + mxLbFillType.reset(); + InterimItemWindow::dispose(); +} + +IMPL_LINK_NOARG(SvxFillToolBoxControl, SelectFillTypeHdl, weld::ComboBox&, void) +{ + const drawing::FillStyle eXFS = static_cast<drawing::FillStyle>(mpLbFillType->get_active()); + + if(meLastXFS != eXFS) + { + mpLbFillAttr->clear(); + SfxObjectShell* pSh = SfxObjectShell::Current(); + const XFillStyleItem aXFillStyleItem(eXFS); + + // #i122676# Do no longer trigger two Execute calls, one for SID_ATTR_FILL_STYLE + // and one for setting the fill attribute itself, but add two SfxPoolItems to the + // call to get just one action at the SdrObject and to create only one Undo action, too. + // Checked that this works in all apps. + switch( eXFS ) + { + default: + case drawing::FillStyle_NONE: + { + mpLbFillAttr->show(); + mpToolBoxColor->hide(); + mpLbFillAttr->set_sensitive(false); + + // #i122676# need to call a single SID_ATTR_FILL_STYLE change + SfxViewFrame::Current()->GetDispatcher()->ExecuteList( + SID_ATTR_FILL_STYLE, SfxCallMode::RECORD, + { &aXFillStyleItem }); + break; + } + case drawing::FillStyle_SOLID: + { + mpLbFillAttr->hide(); + mpToolBoxColor->show(); + const OUString aTmpStr; + const ::Color aColor = mpColorItem->GetColorValue(); + const XFillColorItem aXFillColorItem( aTmpStr, aColor ); + + // #i122676# change FillStyle and Color in one call + SfxViewFrame::Current()->GetDispatcher()->ExecuteList( + SID_ATTR_FILL_COLOR, SfxCallMode::RECORD, + { &aXFillColorItem, &aXFillStyleItem }); + break; + } + case drawing::FillStyle_GRADIENT: + { + mpLbFillAttr->show(); + mpToolBoxColor->hide(); + + if(pSh && pSh->GetItem(SID_GRADIENT_LIST)) + { + if(!mpLbFillAttr->get_count()) + { + mpLbFillAttr->set_sensitive(true); + mpLbFillAttr->clear(); + SvxFillAttrBox::Fill(*mpLbFillAttr, pSh->GetItem(SID_GRADIENT_LIST)->GetGradientList()); + } + + if (mnLastPosGradient != -1) + { + const SvxGradientListItem * pItem = pSh->GetItem(SID_GRADIENT_LIST); + + if(mnLastPosGradient < pItem->GetGradientList()->Count()) + { + const XGradient aGradient = pItem->GetGradientList()->GetGradient(mnLastPosGradient)->GetGradient(); + const XFillGradientItem aXFillGradientItem(mpLbFillAttr->get_text(mnLastPosGradient), aGradient); + + // #i122676# change FillStyle and Gradient in one call + SfxViewFrame::Current()->GetDispatcher()->ExecuteList( + SID_ATTR_FILL_GRADIENT, SfxCallMode::RECORD, + { &aXFillGradientItem, &aXFillStyleItem }); + mpLbFillAttr->set_active(mnLastPosGradient); + } + } + } + else + { + mpLbFillAttr->set_sensitive(false); + } + break; + } + case drawing::FillStyle_HATCH: + { + mpLbFillAttr->show(); + mpToolBoxColor->hide(); + + if(pSh && pSh->GetItem(SID_HATCH_LIST)) + { + if(!mpLbFillAttr->get_count()) + { + mpLbFillAttr->set_sensitive(true); + mpLbFillAttr->clear(); + SvxFillAttrBox::Fill(*mpLbFillAttr, pSh->GetItem(SID_HATCH_LIST)->GetHatchList()); + } + + if (mnLastPosHatch != -1) + { + const SvxHatchListItem * pItem = pSh->GetItem(SID_HATCH_LIST); + + if(mnLastPosHatch < pItem->GetHatchList()->Count()) + { + const XHatch aHatch = pItem->GetHatchList()->GetHatch(mnLastPosHatch)->GetHatch(); + const XFillHatchItem aXFillHatchItem(mpLbFillAttr->get_active_text(), aHatch); + + // #i122676# change FillStyle and Hatch in one call + SfxViewFrame::Current()->GetDispatcher()->ExecuteList( + SID_ATTR_FILL_HATCH, SfxCallMode::RECORD, + { &aXFillHatchItem, &aXFillStyleItem }); + mpLbFillAttr->set_active(mnLastPosHatch); + } + } + } + else + { + mpLbFillAttr->set_sensitive(false); + } + break; + } + case drawing::FillStyle_BITMAP: + { + mpLbFillAttr->show(); + mpToolBoxColor->hide(); + + if(pSh && pSh->GetItem(SID_BITMAP_LIST)) + { + if(!mpLbFillAttr->get_count()) + { + mpLbFillAttr->set_sensitive(true); + mpLbFillAttr->clear(); + SvxFillAttrBox::Fill(*mpLbFillAttr, pSh->GetItem(SID_BITMAP_LIST)->GetBitmapList()); + } + + if (mnLastPosBitmap != -1) + { + const SvxBitmapListItem * pItem = pSh->GetItem(SID_BITMAP_LIST); + + if(mnLastPosBitmap < pItem->GetBitmapList()->Count()) + { + const XBitmapEntry* pXBitmapEntry = pItem->GetBitmapList()->GetBitmap(mnLastPosBitmap); + const XFillBitmapItem aXFillBitmapItem(mpLbFillAttr->get_active_text(), pXBitmapEntry->GetGraphicObject()); + + // #i122676# change FillStyle and Bitmap in one call + SfxViewFrame::Current()->GetDispatcher()->ExecuteList( + SID_ATTR_FILL_BITMAP, SfxCallMode::RECORD, + { &aXFillBitmapItem, &aXFillStyleItem }); + mpLbFillAttr->set_active(mnLastPosBitmap); + } + } + } + else + { + mpLbFillAttr->set_sensitive(false); + } + break; + } + } + + meLastXFS = eXFS; + + mxFillControl->Resize(); + } +} + +IMPL_LINK_NOARG(SvxFillToolBoxControl, SelectFillAttrHdl, weld::ComboBox&, void) +{ + const drawing::FillStyle eXFS = static_cast<drawing::FillStyle>(mpLbFillType->get_active()); + const XFillStyleItem aXFillStyleItem(eXFS); + SfxObjectShell* pSh = SfxObjectShell::Current(); + + // #i122676# dependent from bFillStyleChange, do execute a single or two + // changes in one Execute call + const bool bFillStyleChange(meLastXFS != eXFS); + + switch(eXFS) + { + case drawing::FillStyle_SOLID: + { + if(bFillStyleChange) + { + // #i122676# Single FillStyle change call needed here + SfxViewFrame::Current()->GetDispatcher()->ExecuteList( + SID_ATTR_FILL_STYLE, SfxCallMode::RECORD, + { &aXFillStyleItem }); + } + break; + } + case drawing::FillStyle_GRADIENT: + { + sal_Int32 nPos = mpLbFillAttr->get_active(); + + if (nPos == -1) + { + nPos = mnLastPosGradient; + } + + if (nPos != -1 && pSh && pSh->GetItem(SID_GRADIENT_LIST)) + { + const SvxGradientListItem * pItem = pSh->GetItem(SID_GRADIENT_LIST); + + if(nPos < pItem->GetGradientList()->Count()) + { + const XGradient aGradient = pItem->GetGradientList()->GetGradient(nPos)->GetGradient(); + const XFillGradientItem aXFillGradientItem(mpLbFillAttr->get_active_text(), aGradient); + + // #i122676# Change FillStyle and Gradient in one call + SfxViewFrame::Current()->GetDispatcher()->ExecuteList( + SID_ATTR_FILL_GRADIENT, SfxCallMode::RECORD, + bFillStyleChange + ? std::initializer_list<SfxPoolItem const*>{ &aXFillGradientItem, &aXFillStyleItem } + : std::initializer_list<SfxPoolItem const*>{ &aXFillGradientItem }); + } + } + + if (nPos != -1) + { + mnLastPosGradient = nPos; + } + break; + } + case drawing::FillStyle_HATCH: + { + sal_Int32 nPos = mpLbFillAttr->get_active(); + + if (nPos == -1) + { + nPos = mnLastPosHatch; + } + + if (nPos != -1 && pSh && pSh->GetItem(SID_HATCH_LIST)) + { + const SvxHatchListItem * pItem = pSh->GetItem(SID_HATCH_LIST); + + if(nPos < pItem->GetHatchList()->Count()) + { + const XHatch aHatch = pItem->GetHatchList()->GetHatch(nPos)->GetHatch(); + const XFillHatchItem aXFillHatchItem( mpLbFillAttr->get_active_text(), aHatch); + + // #i122676# Change FillStyle and Hatch in one call + SfxViewFrame::Current()->GetDispatcher()->ExecuteList( + SID_ATTR_FILL_HATCH, SfxCallMode::RECORD, + bFillStyleChange + ? std::initializer_list<SfxPoolItem const*>{ &aXFillHatchItem, &aXFillStyleItem } + : std::initializer_list<SfxPoolItem const*>{ &aXFillHatchItem }); + } + } + + if (nPos != -1) + { + mnLastPosHatch = nPos; + } + break; + } + case drawing::FillStyle_BITMAP: + { + sal_Int32 nPos = mpLbFillAttr->get_active(); + + if (nPos == -1) + { + nPos = mnLastPosBitmap; + } + + if (nPos != -1 && pSh && pSh->GetItem(SID_BITMAP_LIST)) + { + const SvxBitmapListItem * pItem = pSh->GetItem(SID_BITMAP_LIST); + + if(nPos < pItem->GetBitmapList()->Count()) + { + const XBitmapEntry* pXBitmapEntry = pItem->GetBitmapList()->GetBitmap(nPos); + const XFillBitmapItem aXFillBitmapItem(mpLbFillAttr->get_active_text(), pXBitmapEntry->GetGraphicObject()); + + // #i122676# Change FillStyle and Bitmap in one call + SfxViewFrame::Current()->GetDispatcher()->ExecuteList( + SID_ATTR_FILL_BITMAP, SfxCallMode::RECORD, + bFillStyleChange + ? std::initializer_list<SfxPoolItem const*>{ &aXFillBitmapItem, &aXFillStyleItem } + : std::initializer_list<SfxPoolItem const*>{ &aXFillBitmapItem }); + } + } + + if (nPos != -1) + { + mnLastPosBitmap = nPos; + } + break; + } + default: break; + } +} + +void FillControl::SetOptimalSize() +{ + Size aSize(mxLbFillType->get_preferred_size()); + Size aFirstSize(mxToolBoxColor->get_preferred_size()); + auto nWidth = std::max(aFirstSize.Width(), LogicToPixel(Size(55, 0), MapMode(MapUnit::MapAppFont)).Width()); + auto nHeight = std::max(aSize.Height(), aFirstSize.Height()); + mxToolBoxColor->set_size_request(nWidth, -1); + mxLbFillAttr->set_size_request(42, -1); //something narrow so the toolbar sets the overall size of this column + SetSizePixel(Size(m_xContainer->get_preferred_size().Width(), nHeight)); +} + +void FillControl::DataChanged(const DataChangedEvent& rDCEvt) +{ + if((rDCEvt.GetType() == DataChangedEventType::SETTINGS) && + (rDCEvt.GetFlags() & AllSettingsFlags::STYLE)) + { + SetOptimalSize(); + } + InterimItemWindow::DataChanged(rDCEvt); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/tbxctrls/fontworkgallery.cxx b/svx/source/tbxctrls/fontworkgallery.cxx new file mode 100644 index 000000000..1b2f1189b --- /dev/null +++ b/svx/source/tbxctrls/fontworkgallery.cxx @@ -0,0 +1,731 @@ +/* -*- 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 <com/sun/star/text/WritingMode.hpp> + +#include <vcl/toolbox.hxx> +#include <vcl/virdev.hxx> + +#include <svl/itempool.hxx> + +#include <svtools/toolbarmenu.hxx> +#include <svtools/popupwindowcontroller.hxx> + +#include <svx/fmmodel.hxx> +#include <svx/dialmgr.hxx> +#include <svx/strings.hrc> +#include <svx/svdpage.hxx> +#include <svx/svdobj.hxx> +#include <svx/svdview.hxx> + +#include <svx/gallery.hxx> +#include <svx/fontworkgallery.hxx> + +#include <algorithm> +#include <memory> + +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::beans; + +namespace svx +{ + +const int nColCount = 4; +const int nLineCount = 4; + +FontWorkGalleryDialog::FontWorkGalleryDialog(weld::Window* pParent, SdrView& rSdrView) + : GenericDialogController(pParent, "svx/ui/fontworkgallerydialog.ui", "FontworkGalleryDialog") + , mnThemeId(0xffff) + , mrSdrView(rSdrView) + , mppSdrObject(nullptr) + , mpDestModel(nullptr) + , maCtlFavorites(m_xBuilder->weld_scrolled_window("ctlFavoriteswin")) + , mxCtlFavorites(new weld::CustomWeld(*m_xBuilder, "ctlFavorites", maCtlFavorites)) + , mxOKButton(m_xBuilder->weld_button("ok")) +{ + Size aSize(maCtlFavorites.GetDrawingArea()->get_ref_device().LogicToPixel(Size(200, 200), MapMode(MapUnit::MapAppFont))); + mxCtlFavorites->set_size_request(aSize.Width(), aSize.Height()); + + maCtlFavorites.SetDoubleClickHdl( LINK( this, FontWorkGalleryDialog, DoubleClickFavoriteHdl ) ); + mxOKButton->connect_clicked(LINK(this, FontWorkGalleryDialog, ClickOKHdl)); + + maCtlFavorites.SetColCount( nColCount ); + maCtlFavorites.SetLineCount( nLineCount ); + maCtlFavorites.SetExtraSpacing( 3 ); + + initFavorites( GALLERY_THEME_FONTWORK ); + fillFavorites( GALLERY_THEME_FONTWORK ); +} + +FontWorkGalleryDialog::~FontWorkGalleryDialog() +{ +} + +void FontWorkGalleryDialog::initFavorites(sal_uInt16 nThemeId) +{ + // the favorites are read via the gallery + sal_uInt32 nFavCount = GalleryExplorer::GetSdrObjCount( nThemeId ); + + // lock gallery theme + GalleryExplorer::BeginLocking(nThemeId); + + sal_uInt32 nModelPos; + FmFormModel *pModel = nullptr; + + for( nModelPos = 0; nModelPos < nFavCount; nModelPos++ ) + { + BitmapEx aThumb; + + if (GalleryExplorer::GetSdrObj(nThemeId, nModelPos, pModel, &aThumb) && !!aThumb) + { + ScopedVclPtrInstance< VirtualDevice > pVDev; + const Point aNull(0, 0); + + if (pVDev->GetDPIScaleFactor() > 1) + aThumb.Scale(pVDev->GetDPIScaleFactor(), pVDev->GetDPIScaleFactor()); + + const Size aSize(aThumb.GetSizePixel()); + + pVDev->SetOutputSizePixel(aSize); + + static const sal_uInt32 nLen(8); + static const Color aW(COL_WHITE); + static const Color aG(0xef, 0xef, 0xef); + + pVDev->DrawCheckered(aNull, aSize, nLen, aW, aG); + + pVDev->DrawBitmapEx(aNull, aThumb); + maFavoritesHorizontal.emplace_back(pVDev->GetBitmapEx(aNull, aSize)); + } + } + + // release gallery theme + GalleryExplorer::EndLocking(nThemeId); +} + +void FontWorkGalleryDialog::fillFavorites(sal_uInt16 nThemeId) +{ + mnThemeId = nThemeId; + + Size aThumbSize(maCtlFavorites.GetOutputSizePixel()); + aThumbSize.setWidth( aThumbSize.Width() / nColCount ); + aThumbSize.setHeight( aThumbSize.Height() / nLineCount ); + aThumbSize.AdjustWidth( -12 ); + aThumbSize.AdjustHeight( -12 ); + + auto nFavCount = maFavoritesHorizontal.size(); + + // ValueSet favorites + if( nFavCount > (nColCount * nLineCount) ) + { + WinBits nWinBits = maCtlFavorites.GetStyle(); + nWinBits |= WB_VSCROLL; + maCtlFavorites.SetStyle( nWinBits ); + } + + maCtlFavorites.Clear(); + + for( size_t nFavorite = 1; nFavorite <= nFavCount; nFavorite++ ) + { + OUString aStr = SvxResId(RID_SVXFLOAT3D_FAVORITE) + " " + OUString::number(nFavorite); + Image aThumbImage( maFavoritesHorizontal[nFavorite-1] ); + maCtlFavorites.InsertItem( static_cast<sal_uInt16>(nFavorite), aThumbImage, aStr ); + } + + if (maCtlFavorites.GetItemCount()) + maCtlFavorites.SelectItem(1); +} + +void FontWorkGalleryDialog::SetSdrObjectRef( SdrObject** ppSdrObject, SdrModel* pModel ) +{ + mppSdrObject = ppSdrObject; + mpDestModel = pModel; +} + +void FontWorkGalleryDialog::insertSelectedFontwork() +{ + sal_uInt16 nItemId = maCtlFavorites.GetSelectedItemId(); + + if( nItemId > 0 ) + { + std::unique_ptr<FmFormModel> pModel(new FmFormModel()); + pModel->GetItemPool().FreezeIdRanges(); + + if( GalleryExplorer::GetSdrObj( mnThemeId, nItemId-1, pModel.get() ) ) + { + SdrPage* pPage = pModel->GetPage(0); + if( pPage && pPage->GetObjCount() ) + { + // tdf#116993 Calc uses a 'special' mode for this dialog in being the + // only caller of ::SetSdrObjectRef. Only in that case mpDestModel seems + // to be the correct target SdrModel. + // If this is not used, the correct SdrModel seems to be the one from + // the mrSdrView that is used to insert (InsertObjectAtView below) the + // cloned SdrObject. + const bool bUseSpecialCalcMode(nullptr != mppSdrObject && nullptr != mpDestModel); + + // center shape on current view + OutputDevice* pOutDev(mrSdrView.GetFirstOutputDevice()); + + if (pOutDev) + { + // Clone directly to target SdrModel (may be different due to user/caller (!)) + SdrObject* pNewObject( + pPage->GetObj(0)->CloneSdrObject( + bUseSpecialCalcMode ? *mpDestModel : mrSdrView.getSdrModelFromSdrView())); + + pNewObject->MakeNameUnique(); + + // tdf#117629 + // Since the 'old' ::CloneSdrObject also copies the SdrPage* the + // SdrObject::getUnoShape() *will* create the wrong UNO API object + // early. This IS one of the reasons I do change these things - this + // error does not happen with my next change I am working on already + // ARGH! For now, reset the SdrPage* to nullptr. + // What sense does it have to copy the SdrPage* of the original SdrObject ?!? + // TTTT: This also *might* be the hidden reason for the strange code at the + // end of SdrObject::SetPage that tries to delete the SvxShape under some + // circumstances... + // pNewObject->SetPage(nullptr); + + tools::Rectangle aObjRect( pNewObject->GetLogicRect() ); + tools::Rectangle aVisArea = pOutDev->PixelToLogic(tools::Rectangle(Point(0,0), pOutDev->GetOutputSizePixel())); + Point aPagePos = aVisArea.Center(); + aPagePos.AdjustX( -(aObjRect.GetWidth() / 2) ); + aPagePos.AdjustY( -(aObjRect.GetHeight() / 2) ); + tools::Rectangle aNewObjectRectangle(aPagePos, aObjRect.GetSize()); + pNewObject->SetLogicRect(aNewObjectRectangle); + + if (bUseSpecialCalcMode) + { + *mppSdrObject = pNewObject; + } + else + { + SdrPageView* pPV(mrSdrView.GetSdrPageView()); + + if (nullptr != pPV) + { + mrSdrView.InsertObjectAtView( pNewObject, *pPV ); + } + else + { + // tdf#116993 no target -> delete clone + SdrObject::Free(pNewObject); + } + } + } + } + } + } +} + +IMPL_LINK_NOARG(FontWorkGalleryDialog, ClickOKHdl, weld::Button&, void) +{ + insertSelectedFontwork(); + m_xDialog->response(RET_OK); +} + +IMPL_LINK_NOARG(FontWorkGalleryDialog, DoubleClickFavoriteHdl, ValueSet*, void) +{ + insertSelectedFontwork(); + m_xDialog->response(RET_OK); +} + +namespace { + +class FontworkAlignmentWindow final : public WeldToolbarPopup +{ +public: + FontworkAlignmentWindow(svt::PopupWindowController* pControl, weld::Widget* pParentWindow); + virtual void GrabFocus() override + { + mxLeft->grab_focus(); + } + virtual void statusChanged( const css::frame::FeatureStateEvent& Event ) override; + +private: + rtl::Reference<svt::PopupWindowController> mxControl; + std::unique_ptr<weld::RadioButton> mxLeft; + std::unique_ptr<weld::RadioButton> mxCenter; + std::unique_ptr<weld::RadioButton> mxRight; + std::unique_ptr<weld::RadioButton> mxWord; + std::unique_ptr<weld::RadioButton> mxStretch; + bool mbSettingValue; + + DECL_LINK( SelectHdl, weld::ToggleButton&, void ); + + void implSetAlignment( int nAlignmentMode, bool bEnabled ); +}; + +} + +static const OUStringLiteral gsFontworkAlignment(".uno:FontworkAlignment"); + +FontworkAlignmentWindow::FontworkAlignmentWindow(svt::PopupWindowController* pControl, weld::Widget* pParent) + : WeldToolbarPopup(pControl->getFrameInterface(), pParent, "svx/ui/fontworkalignmentcontrol.ui", "FontworkAlignmentControl") + , mxControl(pControl) + , mxLeft(m_xBuilder->weld_radio_button("left")) + , mxCenter(m_xBuilder->weld_radio_button("center")) + , mxRight(m_xBuilder->weld_radio_button("right")) + , mxWord(m_xBuilder->weld_radio_button("word")) + , mxStretch(m_xBuilder->weld_radio_button("stretch")) + , mbSettingValue(false) +{ + mxLeft->connect_toggled(LINK(this, FontworkAlignmentWindow, SelectHdl)); + mxCenter->connect_toggled(LINK(this, FontworkAlignmentWindow, SelectHdl)); + mxRight->connect_toggled(LINK(this, FontworkAlignmentWindow, SelectHdl)); + mxWord->connect_toggled(LINK(this, FontworkAlignmentWindow, SelectHdl)); + mxStretch->connect_toggled(LINK(this, FontworkAlignmentWindow, SelectHdl)); + + AddStatusListener( gsFontworkAlignment ); +} + +void FontworkAlignmentWindow::implSetAlignment( int nSurface, bool bEnabled ) +{ + bool bSettingValue = mbSettingValue; + mbSettingValue = true; + mxLeft->set_active(nSurface == 0 && bEnabled); + mxLeft->set_sensitive(bEnabled); + mxCenter->set_active(nSurface == 1 && bEnabled); + mxCenter->set_sensitive(bEnabled); + mxRight->set_active(nSurface == 2 && bEnabled); + mxRight->set_sensitive(bEnabled); + mxWord->set_active(nSurface == 3 && bEnabled); + mxWord->set_sensitive(bEnabled); + mxStretch->set_active(nSurface == 4 && bEnabled); + mxStretch->set_sensitive(bEnabled); + mbSettingValue = bSettingValue; +} + +void FontworkAlignmentWindow::statusChanged( const css::frame::FeatureStateEvent& Event ) +{ + if( Event.FeatureURL.Main == gsFontworkAlignment ) + { + if( !Event.IsEnabled ) + { + implSetAlignment( 0, false ); + } + else + { + sal_Int32 nValue = 0; + if( Event.State >>= nValue ) + implSetAlignment( nValue, true ); + } + } +} + +IMPL_LINK(FontworkAlignmentWindow, SelectHdl, weld::ToggleButton&, rButton, void) +{ + if (mbSettingValue || !rButton.get_active()) + return; + + sal_Int32 nAlignment; + if (mxLeft->get_active()) + nAlignment = 0; + else if (mxCenter->get_active()) + nAlignment = 1; + else if (mxRight->get_active()) + nAlignment = 2; + else if (mxWord->get_active()) + nAlignment = 3; + else + nAlignment = 4; + + Sequence< PropertyValue > aArgs( 1 ); + aArgs[0].Name = OUString(gsFontworkAlignment).copy(5); + aArgs[0].Value <<= nAlignment; + + mxControl->dispatchCommand( gsFontworkAlignment, aArgs ); + + implSetAlignment( nAlignment, true ); + + mxControl->EndPopupMode(); +} + +namespace { + +class FontworkAlignmentControl : public svt::PopupWindowController +{ +public: + explicit FontworkAlignmentControl( const css::uno::Reference< css::uno::XComponentContext >& rxContext ); + + virtual std::unique_ptr<WeldToolbarPopup> weldPopupWindow() override; + virtual VclPtr<vcl::Window> createVclPopupWindow( vcl::Window* pParent ) override; + + // XInitialization + virtual void SAL_CALL initialize( const css::uno::Sequence< css::uno::Any >& aArguments ) override; + + // XServiceInfo + virtual OUString SAL_CALL getImplementationName() override; + virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override; +}; + +} + +FontworkAlignmentControl::FontworkAlignmentControl( const Reference< XComponentContext >& rxContext ) +: svt::PopupWindowController( rxContext, Reference< css::frame::XFrame >(), ".uno:FontworkAlignment" ) +{ +} + +std::unique_ptr<WeldToolbarPopup> FontworkAlignmentControl::weldPopupWindow() +{ + return std::make_unique<FontworkAlignmentWindow>(this, m_pToolbar); +} + +VclPtr<vcl::Window> FontworkAlignmentControl::createVclPopupWindow( vcl::Window* pParent ) +{ + mxInterimPopover = VclPtr<InterimToolbarPopup>::Create(getFrameInterface(), pParent, + std::make_unique<FontworkAlignmentWindow>(this, pParent->GetFrameWeld())); + + mxInterimPopover->Show(); + + return mxInterimPopover; +} + +// XInitialization +void SAL_CALL FontworkAlignmentControl::initialize( const css::uno::Sequence< css::uno::Any >& aArguments ) +{ + svt::PopupWindowController::initialize( aArguments ); + + ToolBox* pToolBox = nullptr; + sal_uInt16 nId = 0; + if ( getToolboxId( nId, &pToolBox ) ) + pToolBox->SetItemBits( nId, pToolBox->GetItemBits( nId ) | ToolBoxItemBits::DROPDOWNONLY ); +} + +// XServiceInfo + + +OUString FontworkAlignmentControl::getImplementationName() +{ + return "com.sun.star.comp.svx.FontworkAlignmentController"; +} + + +Sequence< OUString > FontworkAlignmentControl::getSupportedServiceNames() +{ + return { "com.sun.star.frame.ToolbarController" }; +} + + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface* +com_sun_star_comp_svx_FontworkAlignmentControl_get_implementation( + css::uno::XComponentContext* xContext, + css::uno::Sequence<css::uno::Any> const &) +{ + return cppu::acquire(new FontworkAlignmentControl(xContext)); +} + +namespace { + +class FontworkCharacterSpacingWindow final : public WeldToolbarPopup +{ +public: + FontworkCharacterSpacingWindow(svt::PopupWindowController* pControl, weld::Widget* pParentWindow); + virtual void GrabFocus() override; + + virtual void statusChanged( const css::frame::FeatureStateEvent& Event ) override; +private: + rtl::Reference<svt::PopupWindowController> mxControl; + std::unique_ptr<weld::RadioButton> mxVeryTight; + std::unique_ptr<weld::RadioButton> mxTight; + std::unique_ptr<weld::RadioButton> mxNormal; + std::unique_ptr<weld::RadioButton> mxLoose; + std::unique_ptr<weld::RadioButton> mxVeryLoose; + std::unique_ptr<weld::RadioButton> mxCustom; + std::unique_ptr<weld::CheckButton> mxKernPairs; + bool mbSettingValue; + + DECL_LINK( SelectHdl, weld::ToggleButton&, void ); + DECL_LINK( ClickHdl, weld::Button&, void ); + + void implSetCharacterSpacing( sal_Int32 nCharacterSpacing, bool bEnabled ); + void implSetKernCharacterPairs(bool bKernOnOff, bool bEnabled); +}; + +} + +static const OUStringLiteral gsFontworkCharacterSpacing(".uno:FontworkCharacterSpacing"); +static const OUStringLiteral gsFontworkKernCharacterPairs(".uno:FontworkKernCharacterPairs"); + +FontworkCharacterSpacingWindow::FontworkCharacterSpacingWindow(svt::PopupWindowController* pControl, weld::Widget* pParent) + : WeldToolbarPopup(pControl->getFrameInterface(), pParent, "svx/ui/fontworkcharacterspacingcontrol.ui", "FontworkCharacterSpacingControl") + , mxControl(pControl) + , mxVeryTight(m_xBuilder->weld_radio_button("verytight")) + , mxTight(m_xBuilder->weld_radio_button("tight")) + , mxNormal(m_xBuilder->weld_radio_button("normal")) + , mxLoose(m_xBuilder->weld_radio_button("loose")) + , mxVeryLoose(m_xBuilder->weld_radio_button("veryloose")) + , mxCustom(m_xBuilder->weld_radio_button("custom")) + , mxKernPairs(m_xBuilder->weld_check_button("kernpairs")) + , mbSettingValue(false) +{ + mxVeryTight->connect_toggled(LINK(this, FontworkCharacterSpacingWindow, SelectHdl)); + mxTight->connect_toggled(LINK(this, FontworkCharacterSpacingWindow, SelectHdl)); + mxNormal->connect_toggled(LINK(this, FontworkCharacterSpacingWindow, SelectHdl)); + mxLoose->connect_toggled(LINK(this, FontworkCharacterSpacingWindow, SelectHdl)); + mxVeryLoose->connect_toggled(LINK(this, FontworkCharacterSpacingWindow, SelectHdl)); + mxCustom->connect_clicked(LINK(this, FontworkCharacterSpacingWindow, ClickHdl)); + + mxKernPairs->connect_toggled(LINK(this, FontworkCharacterSpacingWindow, SelectHdl)); + + AddStatusListener( gsFontworkCharacterSpacing ); + AddStatusListener( gsFontworkKernCharacterPairs ); + + // See TODO in svx/source/toolbars/fontworkbar.cxx for SID_FONTWORK_KERN_CHARACTER_PAIRS, + // the kernpairs setting is ignored, so hide the widget entirely + mxKernPairs->hide(); +} + +void FontworkCharacterSpacingWindow::GrabFocus() +{ + mxVeryTight->grab_focus(); +} + +void FontworkCharacterSpacingWindow::implSetCharacterSpacing( sal_Int32 nCharacterSpacing, bool bEnabled ) +{ + bool bSettingValue = mbSettingValue; + mbSettingValue = true; + + mxVeryTight->set_sensitive(bEnabled); + mxTight->set_sensitive(bEnabled); + mxNormal->set_sensitive(bEnabled); + mxLoose->set_sensitive(bEnabled); + mxVeryLoose->set_sensitive(bEnabled); + mxCustom->set_sensitive(bEnabled); + + mxVeryTight->set_active(false); + mxTight->set_active(false); + mxNormal->set_active(false); + mxLoose->set_active(false); + mxVeryLoose->set_active(false); + mxCustom->set_active(true); + + switch(nCharacterSpacing) + { + case 80: + mxVeryTight->set_active(true); + break; + case 90: + mxTight->set_active(true); + break; + case 100: + mxNormal->set_active(true); + break; + case 120: + mxLoose->set_active(true); + break; + case 150: + mxVeryLoose->set_active(true); + break; + } + + mbSettingValue = bSettingValue; +} + +void FontworkCharacterSpacingWindow::implSetKernCharacterPairs(bool bKernOnOff, bool bEnabled) +{ + mxKernPairs->set_sensitive(bEnabled); + mxKernPairs->set_active(bKernOnOff); +} + +void FontworkCharacterSpacingWindow::statusChanged( const css::frame::FeatureStateEvent& Event ) +{ + if( Event.FeatureURL.Main == gsFontworkCharacterSpacing ) + { + if( !Event.IsEnabled ) + { + implSetCharacterSpacing( 0, false ); + } + else + { + sal_Int32 nValue = 0; + if( Event.State >>= nValue ) + implSetCharacterSpacing( nValue, true ); + } + } + else if( Event.FeatureURL.Main == gsFontworkKernCharacterPairs ) + { + if( !Event.IsEnabled ) + { + implSetKernCharacterPairs(false, false); + } + else + { + bool bValue = false; + if( Event.State >>= bValue ) + implSetKernCharacterPairs(bValue, true); + } + } +} + +IMPL_LINK_NOARG(FontworkCharacterSpacingWindow, ClickHdl, weld::Button&, void) +{ + SelectHdl(*mxCustom); +} + +IMPL_LINK(FontworkCharacterSpacingWindow, SelectHdl, weld::ToggleButton&, rButton, void) +{ + if (mbSettingValue || !rButton.get_active()) + return; + + if (&rButton == mxCustom.get()) + { + Sequence< PropertyValue > aArgs( 1 ); + aArgs[0].Name = OUString(gsFontworkCharacterSpacing).copy(5); + aArgs[0].Value <<= sal_Int32(100); + + rtl::Reference<svt::PopupWindowController> xControl(mxControl); + xControl->EndPopupMode(); + xControl->dispatchCommand(".uno:FontworkCharacterSpacingDialog", aArgs); + } + else if (&rButton == mxKernPairs.get()) + { + Sequence< PropertyValue > aArgs( 1 ); + aArgs[0].Name = OUString(gsFontworkKernCharacterPairs).copy(5); + bool bKernOnOff = mxKernPairs->get_active(); + aArgs[0].Value <<= bKernOnOff; + + mxControl->dispatchCommand( gsFontworkKernCharacterPairs, aArgs ); + + implSetKernCharacterPairs(bKernOnOff, true); + } + else + { + sal_Int32 nCharacterSpacing; + if (&rButton == mxVeryTight.get()) + nCharacterSpacing = 80; + else if (&rButton == mxTight.get()) + nCharacterSpacing = 90; + else if (&rButton == mxLoose.get()) + nCharacterSpacing = 120; + else if (&rButton == mxVeryLoose.get()) + nCharacterSpacing = 150; + else + nCharacterSpacing = 100; + + Sequence< PropertyValue > aArgs( 1 ); + aArgs[0].Name = OUString(gsFontworkCharacterSpacing).copy(5); + aArgs[0].Value <<= nCharacterSpacing; + + mxControl->dispatchCommand( gsFontworkCharacterSpacing, aArgs ); + + implSetCharacterSpacing( nCharacterSpacing, true ); + } + + mxControl->EndPopupMode(); +} + +namespace { + +class FontworkCharacterSpacingControl : public svt::PopupWindowController +{ +public: + explicit FontworkCharacterSpacingControl( const css::uno::Reference< css::uno::XComponentContext >& rxContext ); + + virtual std::unique_ptr<WeldToolbarPopup> weldPopupWindow() override; + virtual VclPtr<vcl::Window> createVclPopupWindow( vcl::Window* pParent ) override; + + // XInitialization + virtual void SAL_CALL initialize( const css::uno::Sequence< css::uno::Any >& aArguments ) override; + + // XServiceInfo + virtual OUString SAL_CALL getImplementationName() override; + virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override; +}; + +} + +FontworkCharacterSpacingControl::FontworkCharacterSpacingControl( const Reference< XComponentContext >& rxContext ) +: svt::PopupWindowController( rxContext, Reference< css::frame::XFrame >(), ".uno:FontworkCharacterSpacingFloater" ) +{ +} + +std::unique_ptr<WeldToolbarPopup> FontworkCharacterSpacingControl::weldPopupWindow() +{ + return std::make_unique<FontworkCharacterSpacingWindow>(this, m_pToolbar); +} + +VclPtr<vcl::Window> FontworkCharacterSpacingControl::createVclPopupWindow( vcl::Window* pParent ) +{ + mxInterimPopover = VclPtr<InterimToolbarPopup>::Create(getFrameInterface(), pParent, + std::make_unique<FontworkCharacterSpacingWindow>(this, pParent->GetFrameWeld())); + + mxInterimPopover->Show(); + + return mxInterimPopover; +} + +// XInitialization +void SAL_CALL FontworkCharacterSpacingControl::initialize( const css::uno::Sequence< css::uno::Any >& aArguments ) +{ + svt::PopupWindowController::initialize( aArguments ); + + ToolBox* pToolBox = nullptr; + sal_uInt16 nId = 0; + if ( getToolboxId( nId, &pToolBox ) ) + pToolBox->SetItemBits( nId, pToolBox->GetItemBits( nId ) | ToolBoxItemBits::DROPDOWNONLY ); +} + +// XServiceInfo + + +OUString FontworkCharacterSpacingControl::getImplementationName() +{ + return "com.sun.star.comp.svx.FontworkCharacterSpacingController"; +} + + +Sequence< OUString > FontworkCharacterSpacingControl::getSupportedServiceNames() +{ + Sequence<OUString> aSNS { "com.sun.star.frame.ToolbarController" }; + return aSNS; +} + + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface* +com_sun_star_comp_svx_FontworkCharacterSpacingControl_get_implementation( + css::uno::XComponentContext* xContext, + css::uno::Sequence<css::uno::Any> const &) +{ + return cppu::acquire(new FontworkCharacterSpacingControl(xContext)); +} + +FontworkCharacterSpacingDialog::FontworkCharacterSpacingDialog(weld::Window* pParent, sal_Int32 nScale) + : GenericDialogController(pParent, "svx/ui/fontworkspacingdialog.ui", "FontworkSpacingDialog") + , m_xMtrScale(m_xBuilder->weld_metric_spin_button("entry", FieldUnit::PERCENT)) +{ + m_xMtrScale->set_value(nScale, FieldUnit::PERCENT); +} + +FontworkCharacterSpacingDialog::~FontworkCharacterSpacingDialog() +{ +} + +sal_Int32 FontworkCharacterSpacingDialog::getScale() const +{ + return static_cast<sal_Int32>(m_xMtrScale->get_value(FieldUnit::PERCENT)); +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/tbxctrls/formatpaintbrushctrl.cxx b/svx/source/tbxctrls/formatpaintbrushctrl.cxx new file mode 100644 index 000000000..912643710 --- /dev/null +++ b/svx/source/tbxctrls/formatpaintbrushctrl.cxx @@ -0,0 +1,105 @@ +/* -*- 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 <svx/formatpaintbrushctrl.hxx> + +#include <svl/eitem.hxx> +#include <vcl/toolbox.hxx> +#include <vcl/settings.hxx> + + +namespace svx +{ + + +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::beans; + +SFX_IMPL_TOOLBOX_CONTROL( FormatPaintBrushToolBoxControl, SfxBoolItem ); + +FormatPaintBrushToolBoxControl::FormatPaintBrushToolBoxControl( sal_uInt16 nSlotId, sal_uInt16 nId, ToolBox& rTbx ) + : SfxToolBoxControl( nSlotId, nId, rTbx ) + , m_bPersistentCopy(false) + , m_aDoubleClickTimer() +{ + sal_uInt64 nDblClkTime = rTbx.GetSettings().GetMouseSettings().GetDoubleClickTime(); + + m_aDoubleClickTimer.SetInvokeHandler( LINK(this, FormatPaintBrushToolBoxControl, WaitDoubleClickHdl) ); + m_aDoubleClickTimer.SetTimeout(nDblClkTime); +} + + +FormatPaintBrushToolBoxControl::~FormatPaintBrushToolBoxControl() +{ + m_aDoubleClickTimer.Stop(); +} + + +void FormatPaintBrushToolBoxControl::impl_executePaintBrush() +{ + Sequence< PropertyValue > aArgs( 1 ); + aArgs[0].Name = "PersistentCopy"; + aArgs[0].Value <<= m_bPersistentCopy; + Dispatch( ".uno:FormatPaintbrush" + , aArgs ); +} + + +void FormatPaintBrushToolBoxControl::DoubleClick() +{ + m_aDoubleClickTimer.Stop(); + + m_bPersistentCopy = true; + impl_executePaintBrush(); +} + + +void FormatPaintBrushToolBoxControl::Click() +{ + m_bPersistentCopy = false; + m_aDoubleClickTimer.Start(); +} + + +IMPL_LINK_NOARG(FormatPaintBrushToolBoxControl, WaitDoubleClickHdl, Timer *, void) +{ + //there was no second click during waiting + impl_executePaintBrush(); +} + + +void FormatPaintBrushToolBoxControl::Select(sal_uInt16 /*nSelectModifier*/) +{ +} + + +void FormatPaintBrushToolBoxControl::StateChanged( sal_uInt16 nSID, SfxItemState eState, + const SfxPoolItem* pState ) +{ + if( eState != SfxItemState::DEFAULT && eState != SfxItemState::SET ) + m_bPersistentCopy = false; + SfxToolBoxControl::StateChanged( nSID, eState, pState ); +} + + +} //namespace svx + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/tbxctrls/grafctrl.cxx b/svx/source/tbxctrls/grafctrl.cxx new file mode 100644 index 000000000..1db6225da --- /dev/null +++ b/svx/source/tbxctrls/grafctrl.cxx @@ -0,0 +1,977 @@ +/* -*- 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 <vcl/toolbox.hxx> +#include <vcl/idle.hxx> +#include <svl/intitem.hxx> +#include <svl/itempool.hxx> +#include <svl/eitem.hxx> +#include <svl/whiter.hxx> +#include <sfx2/viewsh.hxx> +#include <sfx2/request.hxx> +#include <sfx2/basedlgs.hxx> +#include <vcl/InterimItemWindow.hxx> +#include <sfx2/sfxdlg.hxx> +#include <tools/urlobj.hxx> + +#include <svx/dialogs.hrc> +#include <svx/svxids.hrc> +#include <svx/strings.hrc> +#include <editeng/brushitem.hxx> +#include <editeng/sizeitem.hxx> +#include <svx/sdgcpitm.hxx> + +#include <svx/dialmgr.hxx> +#include <svx/svdview.hxx> +#include <svx/svdmodel.hxx> +#include <svx/svdograf.hxx> +#include <svx/svdundo.hxx> +#include <svx/svdtrans.hxx> +#include <svx/grafctrl.hxx> +#include <svx/tbxcolor.hxx> +#include <sdgcoitm.hxx> +#include <svx/sdggaitm.hxx> +#include <svx/sdgluitm.hxx> +#include <svx/sdgmoitm.hxx> +#include <sdgtritm.hxx> +#include <bitmaps.hlst> + +#include <com/sun/star/frame/XDispatchProvider.hpp> + +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::frame; +using namespace ::com::sun::star::util; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::lang; + +#define TOOLBOX_NAME "colorbar" +#define RID_SVXSTR_UNDO_GRAFCROP RID_SVXSTR_GRAFCROP + +namespace { + +class ImplGrafControl final : public InterimItemWindow +{ +private: + Idle maIdle; + OUString maCommand; + Reference<XFrame> mxFrame; + std::unique_ptr<weld::Image> mxImage; + std::unique_ptr<weld::MetricSpinButton> mxField; + + DECL_LINK(ValueChangedHdl, weld::MetricSpinButton&, void); + DECL_LINK(KeyInputHdl, const KeyEvent&, bool); + DECL_LINK(ImplModifyHdl, Timer*, void); + +public: + ImplGrafControl( vcl::Window* pParent, const OUString& rCmd, const Reference< XFrame >& rFrame ); + virtual ~ImplGrafControl() override; + virtual void dispose() override; + + virtual void GetFocus() override; + void Update( const SfxPoolItem* pItem ); + void set_field_text(const OUString& rStr) { mxField->set_text(rStr); } + void set_sensitive(bool bSensitive) + { + Enable(bSensitive); + mxImage->set_sensitive(bSensitive); + mxField->set_sensitive(bSensitive); + } +}; + +} + +IMPL_LINK_NOARG(ImplGrafControl, ValueChangedHdl, weld::MetricSpinButton&, void) +{ + maIdle.Start(); +} + +IMPL_LINK_NOARG(ImplGrafControl, ImplModifyHdl, Timer*, void) +{ + const sal_Int64 nVal = mxField->get_value(FieldUnit::NONE); + + // Convert value to an any to be usable with dispatch API + Any a; + if ( maCommand == ".uno:GrafRed" || + maCommand == ".uno:GrafGreen" || + maCommand == ".uno:GrafBlue" || + maCommand == ".uno:GrafLuminance" || + maCommand == ".uno:GrafContrast" ) + a <<= sal_Int16( nVal ); + else if ( maCommand == ".uno:GrafGamma" || + maCommand == ".uno:GrafTransparence" ) + a <<= sal_Int32( nVal ); + + if ( a.hasValue() ) + { + INetURLObject aObj( maCommand ); + + Sequence< PropertyValue > aArgs( 1 ); + aArgs[0].Name = aObj.GetURLPath(); + aArgs[0].Value = a; + + SfxToolBoxControl::Dispatch( + Reference< XDispatchProvider >( mxFrame->getController(), UNO_QUERY ), + maCommand, + aArgs ); + } +} + +void ImplGrafControl::Update( const SfxPoolItem* pItem ) +{ + if( pItem ) + { + long nValue; + + if ( maCommand == ".uno:GrafTransparence" ) + nValue = static_cast<const SfxUInt16Item*>( pItem )->GetValue(); + else if ( maCommand == ".uno:GrafGamma" ) + nValue = static_cast<const SfxUInt32Item*>( pItem )->GetValue(); + else + nValue = static_cast<const SfxInt16Item*>( pItem )->GetValue(); + + mxField->set_value(nValue, FieldUnit::NONE); + } + else + mxField->set_text(OUString()); +} + +namespace { + +struct CommandToRID +{ + const char* pCommand; + const char* sResId; +}; + +} + +static OUString ImplGetRID( const OUString& aCommand ) +{ + static const CommandToRID aImplCommandToResMap[] = + { + { ".uno:GrafRed", RID_SVXBMP_GRAF_RED }, + { ".uno:GrafGreen", RID_SVXBMP_GRAF_GREEN }, + { ".uno:GrafBlue", RID_SVXBMP_GRAF_BLUE }, + { ".uno:GrafLuminance", RID_SVXBMP_GRAF_LUMINANCE }, + { ".uno:GrafContrast", RID_SVXBMP_GRAF_CONTRAST }, + { ".uno:GrafGamma", RID_SVXBMP_GRAF_GAMMA }, + { ".uno:GrafTransparence", RID_SVXBMP_GRAF_TRANSPARENCE }, + { nullptr, "" } + }; + + OUString sRID; + + sal_Int32 i( 0 ); + while ( aImplCommandToResMap[ i ].pCommand ) + { + if ( aCommand.equalsAscii( aImplCommandToResMap[ i ].pCommand )) + { + sRID = OUString::createFromAscii(aImplCommandToResMap[i].sResId); + break; + } + ++i; + } + + return sRID; +} + +ImplGrafControl::ImplGrafControl( + vcl::Window* pParent, + const OUString& rCmd, + const Reference< XFrame >& rFrame) + : InterimItemWindow(pParent, "svx/ui/grafctrlbox.ui", "GrafCtrlBox") + , maCommand(rCmd) + , mxFrame(rFrame) + , mxImage(m_xBuilder->weld_image("image")) + , mxField(m_xBuilder->weld_metric_spin_button("spinfield", FieldUnit::NONE)) +{ + OUString sResId(ImplGetRID(rCmd)); + mxImage->set_from_icon_name(sResId); + mxImage->set_toolbar_background(); + + SetBackground( Wallpaper() ); // transparent background + + mxField->set_help_id(OUStringToOString(rCmd, RTL_TEXTENCODING_UTF8)); + mxField->get_widget().connect_key_press(LINK(this, ImplGrafControl, KeyInputHdl)); + mxField->connect_value_changed(LINK(this, ImplGrafControl, ValueChangedHdl)); + + if (maCommand == ".uno:GrafGamma") + { + mxField->set_digits(2); + + mxField->set_range(10, 1000, FieldUnit::NONE); + mxField->set_increments(10, 100, FieldUnit::NONE); + } + else + { + const long nMinVal = maCommand == ".uno:GrafTransparence" ? 0 : -100; + + mxField->set_unit(FieldUnit::PERCENT); + mxField->set_digits(0); + + mxField->set_range(nMinVal, 100, FieldUnit::PERCENT); + mxField->set_increments(1, 10, FieldUnit::PERCENT); + } + + maIdle.SetInvokeHandler( LINK( this, ImplGrafControl, ImplModifyHdl ) ); + + SetSizePixel(m_xContainer->get_preferred_size()); +} + +IMPL_LINK(ImplGrafControl, KeyInputHdl, const KeyEvent&, rKEvt, bool) +{ + return ChildKeyInput(rKEvt); +} + +ImplGrafControl::~ImplGrafControl() +{ + disposeOnce(); +} + +void ImplGrafControl::dispose() +{ + mxImage.reset(); + mxField.reset(); + InterimItemWindow::dispose(); +} + +void ImplGrafControl::GetFocus() +{ + if (mxField) + mxField->grab_focus(); + InterimItemWindow::GetFocus(); +} + +namespace { + +class ImplGrafModeControl final : public InterimItemWindow +{ +private: + sal_uInt16 mnCurPos; + Reference< XFrame > mxFrame; + std::unique_ptr<weld::ComboBox> m_xWidget; + + DECL_LINK(SelectHdl, weld::ComboBox&, void); + DECL_LINK(KeyInputHdl, const KeyEvent&, bool); + DECL_LINK(FocusInHdl, weld::Widget&, void); + + static void ImplReleaseFocus(); + +public: + ImplGrafModeControl( vcl::Window* pParent, const Reference< XFrame >& rFrame ); + virtual void dispose() override; + virtual ~ImplGrafModeControl() override; + + virtual void GetFocus() override + { + if (m_xWidget) + m_xWidget->grab_focus(); + InterimItemWindow::GetFocus(); + } + + void set_sensitive(bool bSensitive) + { + Enable(bSensitive); + m_xWidget->set_sensitive(true); + } + + void set_active(int nActive) + { + m_xWidget->set_active(nActive); + } + + void Update( const SfxPoolItem* pItem ); +}; + +} + +ImplGrafModeControl::ImplGrafModeControl(vcl::Window* pParent, const Reference<XFrame>& rFrame) + : InterimItemWindow(pParent, "svx/ui/grafmodebox.ui", "GrafModeBox") + , mnCurPos(0) + , mxFrame(rFrame) + , m_xWidget(m_xBuilder->weld_combo_box("grafmode")) +{ + m_xWidget->append_text( SvxResId( RID_SVXSTR_GRAFMODE_STANDARD ) ); + m_xWidget->append_text( SvxResId( RID_SVXSTR_GRAFMODE_GREYS ) ); + m_xWidget->append_text( SvxResId( RID_SVXSTR_GRAFMODE_MONO ) ); + m_xWidget->append_text( SvxResId( RID_SVXSTR_GRAFMODE_WATERMARK ) ); + + m_xWidget->connect_changed(LINK(this, ImplGrafModeControl, SelectHdl)); + m_xWidget->connect_key_press(LINK(this, ImplGrafModeControl, KeyInputHdl)); + m_xWidget->connect_focus_in(LINK(this, ImplGrafModeControl, FocusInHdl)); + + SetSizePixel(m_xWidget->get_preferred_size()); +} + +void ImplGrafModeControl::dispose() +{ + m_xWidget.reset(); + InterimItemWindow::dispose(); +} + +ImplGrafModeControl::~ImplGrafModeControl() +{ + disposeOnce(); +} + +IMPL_LINK(ImplGrafModeControl, SelectHdl, weld::ComboBox&, rBox, void) +{ + Sequence< PropertyValue > aArgs( 1 ); + aArgs[0].Name = "GrafMode"; + aArgs[0].Value <<= sal_Int16(rBox.get_active()); + + /* #i33380# DR 2004-09-03 Moved the following line above the Dispatch() call. + This instance may be deleted in the meantime (i.e. when a dialog is opened + while in Dispatch()), accessing members will crash in this case. */ + ImplReleaseFocus(); + + SfxToolBoxControl::Dispatch( + Reference< XDispatchProvider >( mxFrame->getController(), UNO_QUERY ), + ".uno:GrafMode", + aArgs ); +} + +IMPL_LINK(ImplGrafModeControl, KeyInputHdl, const KeyEvent&, rKEvt, bool) +{ + bool bHandled(false); + + if (rKEvt.GetKeyCode().GetCode() == KEY_ESCAPE) + { + m_xWidget->set_active(mnCurPos); + ImplReleaseFocus(); + bHandled = true; + } + + return bHandled || ChildKeyInput(rKEvt); +} + +IMPL_LINK_NOARG(ImplGrafModeControl, FocusInHdl, weld::Widget&, void) +{ + mnCurPos = m_xWidget->get_active(); +} + +void ImplGrafModeControl::ImplReleaseFocus() +{ + if( SfxViewShell::Current() ) + { + vcl::Window* pShellWnd = SfxViewShell::Current()->GetWindow(); + + if( pShellWnd ) + pShellWnd->GrabFocus(); + } +} + +void ImplGrafModeControl::Update( const SfxPoolItem* pItem ) +{ + if( pItem ) + m_xWidget->set_active(static_cast<const SfxUInt16Item*>(pItem)->GetValue()); + else + m_xWidget->set_active(-1); +} + +SvxGrafToolBoxControl::SvxGrafToolBoxControl( sal_uInt16 nSlotId, sal_uInt16 nId, ToolBox& rTbx) : + SfxToolBoxControl( nSlotId, nId, rTbx ) +{ + rTbx.SetItemBits( nId, ToolBoxItemBits::DROPDOWN | rTbx.GetItemBits( nId ) ); + rTbx.Invalidate(); +} + +SvxGrafToolBoxControl::~SvxGrafToolBoxControl() +{ +} + +void SvxGrafToolBoxControl::StateChanged( sal_uInt16, SfxItemState eState, const SfxPoolItem* pState ) +{ + ImplGrafControl* pCtrl = static_cast<ImplGrafControl*>( GetToolBox().GetItemWindow( GetId() ) ); + DBG_ASSERT( pCtrl, "Control not found" ); + + if( eState == SfxItemState::DISABLED ) + { + pCtrl->set_sensitive(false); + pCtrl->set_field_text( OUString() ); + } + else + { + pCtrl->set_sensitive(true); + + if( eState == SfxItemState::DEFAULT ) + pCtrl->Update( pState ); + else + pCtrl->Update( nullptr ); + } +} + +VclPtr<InterimItemWindow> SvxGrafToolBoxControl::CreateItemWindow( vcl::Window *pParent ) +{ + return VclPtr<ImplGrafControl>::Create( pParent, m_aCommandURL, m_xFrame ).get(); +} + +SFX_IMPL_TOOLBOX_CONTROL( SvxGrafRedToolBoxControl, SfxInt16Item ); + +SvxGrafRedToolBoxControl::SvxGrafRedToolBoxControl( sal_uInt16 nSlotId, sal_uInt16 nId, ToolBox& rTbx ) : + SvxGrafToolBoxControl( nSlotId, nId, rTbx ) +{ +} + +SFX_IMPL_TOOLBOX_CONTROL( SvxGrafGreenToolBoxControl, SfxInt16Item ); + +SvxGrafGreenToolBoxControl::SvxGrafGreenToolBoxControl( sal_uInt16 nSlotId, sal_uInt16 nId, ToolBox& rTbx ) : + SvxGrafToolBoxControl( nSlotId, nId, rTbx ) +{ +} + +SFX_IMPL_TOOLBOX_CONTROL( SvxGrafBlueToolBoxControl, SfxInt16Item ); + +SvxGrafBlueToolBoxControl::SvxGrafBlueToolBoxControl( sal_uInt16 nSlotId, sal_uInt16 nId, ToolBox& rTbx ) : + SvxGrafToolBoxControl( nSlotId, nId, rTbx ) +{ +} + +SFX_IMPL_TOOLBOX_CONTROL( SvxGrafLuminanceToolBoxControl, SfxInt16Item ); + +SvxGrafLuminanceToolBoxControl::SvxGrafLuminanceToolBoxControl( sal_uInt16 nSlotId, sal_uInt16 nId, ToolBox& rTbx ) : + SvxGrafToolBoxControl( nSlotId, nId, rTbx ) +{ +} + +SFX_IMPL_TOOLBOX_CONTROL( SvxGrafContrastToolBoxControl, SfxInt16Item ); + +SvxGrafContrastToolBoxControl::SvxGrafContrastToolBoxControl( sal_uInt16 nSlotId, sal_uInt16 nId, ToolBox& rTbx ) : + SvxGrafToolBoxControl( nSlotId, nId, rTbx ) +{ +} + +SFX_IMPL_TOOLBOX_CONTROL( SvxGrafGammaToolBoxControl, SfxUInt32Item ); + +SvxGrafGammaToolBoxControl::SvxGrafGammaToolBoxControl( sal_uInt16 nSlotId, sal_uInt16 nId, ToolBox& rTbx ) : + SvxGrafToolBoxControl( nSlotId, nId, rTbx ) +{ +} + +SFX_IMPL_TOOLBOX_CONTROL( SvxGrafTransparenceToolBoxControl, SfxUInt16Item ); + +SvxGrafTransparenceToolBoxControl::SvxGrafTransparenceToolBoxControl( sal_uInt16 nSlotId, sal_uInt16 nId, ToolBox& rTbx ) : + SvxGrafToolBoxControl( nSlotId, nId, rTbx ) +{ +} + +SFX_IMPL_TOOLBOX_CONTROL( SvxGrafModeToolBoxControl, SfxUInt16Item ); + +SvxGrafModeToolBoxControl::SvxGrafModeToolBoxControl( sal_uInt16 nSlotId, sal_uInt16 nId, ToolBox& rTbx ) : + SfxToolBoxControl( nSlotId, nId, rTbx ) +{ +} + +SvxGrafModeToolBoxControl::~SvxGrafModeToolBoxControl() +{ +} + +void SvxGrafModeToolBoxControl::StateChanged( sal_uInt16, SfxItemState eState, const SfxPoolItem* pState ) + +{ + ImplGrafModeControl* pCtrl = static_cast<ImplGrafModeControl*>( GetToolBox().GetItemWindow( GetId() ) ); + DBG_ASSERT( pCtrl, "Control not found" ); + + if( eState == SfxItemState::DISABLED ) + { + pCtrl->set_sensitive(false); + pCtrl->set_active(-1); + } + else + { + pCtrl->set_sensitive(true); + + if( eState == SfxItemState::DEFAULT ) + pCtrl->Update( pState ); + else + pCtrl->Update( nullptr ); + } +} + +VclPtr<InterimItemWindow> SvxGrafModeToolBoxControl::CreateItemWindow( vcl::Window *pParent ) +{ + return VclPtr<ImplGrafModeControl>::Create( pParent, m_xFrame ).get(); +} + +void SvxGrafAttrHelper::ExecuteGrafAttr( SfxRequest& rReq, SdrView& rView ) +{ + SfxItemPool& rPool = rView.GetModel()->GetItemPool(); + SfxItemSet aSet( rPool, svl::Items<SDRATTR_GRAF_FIRST, SDRATTR_GRAF_LAST>{} ); + OUString aUndoStr; + const bool bUndo = rView.IsUndoEnabled(); + + if( bUndo ) + { + aUndoStr = rView.GetDescriptionOfMarkedObjects() + " "; + } + + const SfxItemSet* pArgs = rReq.GetArgs(); + const SfxPoolItem* pItem; + sal_uInt16 nSlot = rReq.GetSlot(); + + if( !pArgs || SfxItemState::SET != pArgs->GetItemState( nSlot, false, &pItem )) + pItem = nullptr; + + switch( nSlot ) + { + case SID_ATTR_GRAF_RED: + { + if( pItem ) + { + aSet.Put( SdrGrafRedItem( static_cast<const SfxInt16Item*>(pItem)->GetValue() )); + if( bUndo ) + aUndoStr += SvxResId( RID_SVXSTR_UNDO_GRAFRED ); + } + } + break; + + case SID_ATTR_GRAF_GREEN: + { + if( pItem ) + { + aSet.Put( SdrGrafGreenItem( static_cast<const SfxInt16Item*>(pItem)->GetValue() )); + if( bUndo ) + aUndoStr += SvxResId( RID_SVXSTR_UNDO_GRAFGREEN ); + } + } + break; + + case SID_ATTR_GRAF_BLUE: + { + if( pItem ) + { + aSet.Put( SdrGrafBlueItem( static_cast<const SfxInt16Item*>(pItem)->GetValue() )); + if( bUndo ) + aUndoStr += SvxResId( RID_SVXSTR_UNDO_GRAFBLUE ); + } + } + break; + + case SID_ATTR_GRAF_LUMINANCE: + { + if( pItem ) + { + aSet.Put( SdrGrafLuminanceItem( static_cast<const SfxInt16Item*>(pItem)->GetValue() )); + if( bUndo ) + aUndoStr += SvxResId( RID_SVXSTR_UNDO_GRAFLUMINANCE ); + } + } + break; + + case SID_ATTR_GRAF_CONTRAST: + { + if( pItem ) + { + aSet.Put( SdrGrafContrastItem( static_cast<const SfxInt16Item*>(pItem)->GetValue() )); + if( bUndo ) + aUndoStr += SvxResId( RID_SVXSTR_UNDO_GRAFCONTRAST ); + } + } + break; + + case SID_ATTR_GRAF_GAMMA: + { + if( pItem ) + { + aSet.Put( SdrGrafGamma100Item( static_cast<const SfxUInt32Item*>(pItem)->GetValue() )); + if( bUndo ) + aUndoStr += SvxResId( RID_SVXSTR_UNDO_GRAFGAMMA ); + } + } + break; + + case SID_ATTR_GRAF_TRANSPARENCE: + { + if( pItem ) + { + aSet.Put( SdrGrafTransparenceItem( static_cast<const SfxUInt16Item*>(pItem)->GetValue() )); + if( bUndo ) + aUndoStr += SvxResId( RID_SVXSTR_UNDO_GRAFTRANSPARENCY ); + } + } + break; + + case SID_ATTR_GRAF_MODE: + { + if( pItem ) + { + aSet.Put( SdrGrafModeItem( static_cast<GraphicDrawMode>(static_cast<const SfxUInt16Item*>(pItem)->GetValue()) )); + if( bUndo ) + aUndoStr += SvxResId( RID_SVXSTR_UNDO_GRAFMODE ); + } + } + break; + + case SID_ATTR_GRAF_CROP: + { + const SdrMarkList& rMarkList = rView.GetMarkedObjectList(); + + if( 0 < rMarkList.GetMarkCount() ) + { + SdrGrafObj* pObj = static_cast<SdrGrafObj*>( rMarkList.GetMark( 0 )->GetMarkedSdrObj() ); + + if( ( pObj->GetGraphicType() != GraphicType::NONE ) && + ( pObj->GetGraphicType() != GraphicType::Default ) ) + { + SfxItemSet aGrfAttr( rPool, svl::Items<SDRATTR_GRAFCROP, SDRATTR_GRAFCROP>{} ); + const MapUnit eOldMetric = rPool.GetMetric( 0 ); + const MapMode aMap100( MapUnit::Map100thMM ); + const MapMode aMapTwip( MapUnit::MapTwip ); + + aGrfAttr.Put(pObj->GetMergedItemSet()); + rPool.SetDefaultMetric( MapUnit::MapTwip ); + + SfxItemSet aCropDlgAttr( + rPool, + svl::Items< + SDRATTR_GRAFCROP, SDRATTR_GRAFCROP, + SID_ATTR_PAGE_SIZE, SID_ATTR_PAGE_SIZE, + SID_ATTR_GRAF_CROP, SID_ATTR_GRAF_FRMSIZE, + SID_ATTR_GRAF_GRAPHIC, SID_ATTR_GRAF_GRAPHIC>{}); + + aCropDlgAttr.Put( SvxBrushItem( pObj->GetGraphic(), GPOS_MM, SID_ATTR_GRAF_GRAPHIC ) ); + aCropDlgAttr.Put( SvxSizeItem( SID_ATTR_PAGE_SIZE, + OutputDevice::LogicToLogic( + Size( 200000, 200000 ), aMap100, aMapTwip ) ) ); + aCropDlgAttr.Put( SvxSizeItem( SID_ATTR_GRAF_FRMSIZE, OutputDevice::LogicToLogic( + pObj->GetLogicRect().GetSize(), aMap100, aMapTwip ) ) ); + + const SdrGrafCropItem& rCrop = aGrfAttr.Get( SDRATTR_GRAFCROP ); + Size aLTSize( OutputDevice::LogicToLogic( + Size( rCrop.GetLeft(), rCrop.GetTop() ), aMap100, aMapTwip ) ); + Size aRBSize( OutputDevice::LogicToLogic( + Size( rCrop.GetRight(), rCrop.GetBottom() ), aMap100, aMapTwip ) ); + + aCropDlgAttr.Put( SdrGrafCropItem( aLTSize.Width(), aLTSize.Height(), + aRBSize.Width(), aRBSize.Height() ) ); + + vcl::Window* pParent(SfxViewShell::Current() ? SfxViewShell::Current()->GetWindow() : nullptr); + SfxSingleTabDialogController aCropDialog(pParent ? pParent->GetFrameWeld() : nullptr, + &aCropDlgAttr); + const OUString aCropStr(SvxResId(RID_SVXSTR_GRAFCROP)); + + SfxAbstractDialogFactory* pFact = SfxAbstractDialogFactory::Create(); + ::CreateTabPage fnCreatePage = pFact->GetTabPageCreatorFunc( RID_SVXPAGE_GRFCROP ); + std::unique_ptr<SfxTabPage> xTabPage = (*fnCreatePage)(aCropDialog.get_content_area(), &aCropDialog, &aCropDlgAttr); + xTabPage->SetPageTitle(aCropStr); + aCropDialog.SetTabPage(std::move(xTabPage)); + + if (aCropDialog.run() == RET_OK) + { + const SfxItemSet* pOutAttr = aCropDialog.GetOutputItemSet(); + + if( pOutAttr ) + { + aUndoStr += SvxResId( RID_SVXSTR_UNDO_GRAFCROP ); + + // set crop attributes + if( SfxItemState::SET <= pOutAttr->GetItemState( SDRATTR_GRAFCROP ) ) + { + const SdrGrafCropItem& rNewCrop = pOutAttr->Get( SDRATTR_GRAFCROP ); + + aLTSize = OutputDevice::LogicToLogic( Size( rNewCrop.GetLeft(), rNewCrop.GetTop() ), aMapTwip, aMap100 ); + aRBSize = OutputDevice::LogicToLogic( Size( rNewCrop.GetRight(), rNewCrop.GetBottom() ), aMapTwip, aMap100 ); + aSet.Put( SdrGrafCropItem( aLTSize.Width(), aLTSize.Height(), aRBSize.Width(), aRBSize.Height() ) ); + } + + // set new logic rect + if( SfxItemState::SET <= pOutAttr->GetItemState( SID_ATTR_GRAF_FRMSIZE ) ) + { + Point aNewOrigin( pObj->GetLogicRect().TopLeft() ); + const Size& rGrfSize = static_cast<const SvxSizeItem&>( pOutAttr->Get( SID_ATTR_GRAF_FRMSIZE ) ).GetSize(); + Size aNewGrfSize( OutputDevice::LogicToLogic( rGrfSize, aMapTwip, aMap100 ) ); + Size aOldGrfSize( pObj->GetLogicRect().GetSize() ); + + tools::Rectangle aNewRect( aNewOrigin, aNewGrfSize ); + Point aOffset( (aNewGrfSize.Width() - aOldGrfSize.Width()) >> 1, + (aNewGrfSize.Height() - aOldGrfSize.Height()) >> 1 ); + + // #106181# rotate snap rect before setting it + const GeoStat& aGeo = pObj->GetGeoStat(); + + if (aGeo.nRotationAngle!=0 || aGeo.nShearAngle!=0) + { + tools::Polygon aPol(aNewRect); + + // also transform origin offset + if (aGeo.nShearAngle!=0) + { + ShearPoly(aPol, + aNewRect.TopLeft(), + aGeo.nTan); + ShearPoint(aOffset, Point(0,0), aGeo.nTan); + } + if (aGeo.nRotationAngle!=0) + { + RotatePoly(aPol, + aNewRect.TopLeft(), + aGeo.nSin,aGeo.nCos); + RotatePoint(aOffset, Point(0,0), aGeo.nSin,aGeo.nCos); + } + + // apply offset + aPol.Move( -aOffset.X(), -aOffset.Y() ); + aNewRect=aPol.GetBoundRect(); + } + else + { + aNewRect.Move( -aOffset.X(), -aOffset.Y() ); + } + + if( !aSet.Count() ) + rView.SetMarkedObjRect( aNewRect ); + else + { + if( bUndo ) + { + rView.BegUndo( aUndoStr ); + rView.AddUndo( rView.GetModel()->GetSdrUndoFactory().CreateUndoGeoObject( *pObj ) ); + } + pObj->SetSnapRect( aNewRect ); + rView.SetAttributes( aSet ); + + if( bUndo ) + rView.EndUndo(); + aSet.ClearItem(); + } + } + } + } + + rPool.SetDefaultMetric( eOldMetric ); + } + } + } + break; + + case SID_COLOR_SETTINGS: + { + svx::ToolboxAccess aToolboxAccess( TOOLBOX_NAME ); + aToolboxAccess.toggleToolbox(); + rReq.Done(); + break; + } + + default: + break; + } + + if( aSet.Count() ) + { + if( bUndo ) + rView.BegUndo( aUndoStr ); + + rView.SetAttributes( aSet ); + + if( bUndo ) + rView.EndUndo(); + } +} + +void SvxGrafAttrHelper::GetGrafAttrState( SfxItemSet& rSet, SdrView const & rView ) +{ + SfxItemPool& rPool = rView.GetModel()->GetItemPool(); + SfxItemSet aAttrSet( rPool ); + SfxWhichIter aIter( rSet ); + sal_uInt16 nWhich = aIter.FirstWhich(); + const SdrMarkList& rMarkList = rView.GetMarkedObjectList(); + bool bEnableColors = true; + bool bEnableTransparency = true; + bool bEnableCrop = ( 1 == rMarkList.GetMarkCount() ); + + for( size_t i = 0, nCount = rMarkList.GetMarkCount(); i < nCount; ++i ) + { + SdrGrafObj* pGrafObj = dynamic_cast< SdrGrafObj* >( rMarkList.GetMark( i )->GetMarkedSdrObj() ); + + if( !pGrafObj || + ( pGrafObj->GetGraphicType() == GraphicType::NONE ) || + ( pGrafObj->GetGraphicType() == GraphicType::Default )) + { + bEnableColors = bEnableTransparency = bEnableCrop = false; + break; + } + else if( bEnableTransparency && ( pGrafObj->HasGDIMetaFile() || pGrafObj->IsAnimated() ) ) + { + bEnableTransparency = false; + } + } + + rView.GetAttributes( aAttrSet ); + + while( nWhich ) + { + sal_uInt16 nSlotId = SfxItemPool::IsWhich( nWhich ) ? rPool.GetSlotId( nWhich ) : nWhich; + + switch( nSlotId ) + { + case SID_ATTR_GRAF_MODE: + { + if( SfxItemState::DEFAULT <= aAttrSet.GetItemState( SDRATTR_GRAFMODE ) ) + { + if( bEnableColors ) + { + rSet.Put( SfxUInt16Item( nSlotId, + sal::static_int_cast< sal_uInt16 >( aAttrSet.Get(SDRATTR_GRAFMODE).GetValue() ) ) ); + } + else + { + rSet.DisableItem( SID_ATTR_GRAF_MODE ); + } + } + } + break; + + case SID_ATTR_GRAF_RED: + { + if( SfxItemState::DEFAULT <= aAttrSet.GetItemState( SDRATTR_GRAFRED ) ) + { + if( bEnableColors ) + { + rSet.Put( SfxInt16Item( nSlotId, aAttrSet.Get(SDRATTR_GRAFRED).GetValue() ) ); + } + else + { + rSet.DisableItem( SID_ATTR_GRAF_RED ); + } + } + } + break; + + case SID_ATTR_GRAF_GREEN: + { + if( SfxItemState::DEFAULT <= aAttrSet.GetItemState( SDRATTR_GRAFGREEN ) ) + { + if( bEnableColors ) + { + rSet.Put( SfxInt16Item( nSlotId, aAttrSet.Get(SDRATTR_GRAFGREEN).GetValue()) ); + } + else + { + rSet.DisableItem( SID_ATTR_GRAF_GREEN ); + } + } + } + break; + + case SID_ATTR_GRAF_BLUE: + { + if( SfxItemState::DEFAULT <= aAttrSet.GetItemState( SDRATTR_GRAFBLUE ) ) + { + if( bEnableColors ) + { + rSet.Put( SfxInt16Item( nSlotId, aAttrSet.Get(SDRATTR_GRAFBLUE).GetValue()) ); + } + else + { + rSet.DisableItem( SID_ATTR_GRAF_BLUE ); + } + } + } + break; + + case SID_ATTR_GRAF_LUMINANCE: + { + if( SfxItemState::DEFAULT <= aAttrSet.GetItemState( SDRATTR_GRAFLUMINANCE ) ) + { + if( bEnableColors ) + { + rSet.Put( SfxInt16Item( nSlotId, aAttrSet.Get(SDRATTR_GRAFLUMINANCE).GetValue()) ); + } + else + { + rSet.DisableItem( SID_ATTR_GRAF_LUMINANCE ); + } + } + } + break; + + case SID_ATTR_GRAF_CONTRAST: + { + if( SfxItemState::DEFAULT <= aAttrSet.GetItemState( SDRATTR_GRAFCONTRAST ) ) + { + if( bEnableColors ) + { + rSet.Put( SfxInt16Item( nSlotId, + aAttrSet.Get(SDRATTR_GRAFCONTRAST).GetValue()) ); + } + else + { + rSet.DisableItem( SID_ATTR_GRAF_CONTRAST ); + } + } + } + break; + + case SID_ATTR_GRAF_GAMMA: + { + if( SfxItemState::DEFAULT <= aAttrSet.GetItemState( SDRATTR_GRAFGAMMA ) ) + { + if( bEnableColors ) + { + rSet.Put( SfxUInt32Item( nSlotId, + aAttrSet.Get(SDRATTR_GRAFGAMMA).GetValue() ) ); + } + else + { + rSet.DisableItem( SID_ATTR_GRAF_GAMMA ); + } + } + } + break; + + case SID_ATTR_GRAF_TRANSPARENCE: + { + if( SfxItemState::DEFAULT <= aAttrSet.GetItemState( SDRATTR_GRAFTRANSPARENCE ) ) + { + if( bEnableTransparency ) + { + rSet.Put( SfxUInt16Item( nSlotId, + aAttrSet.Get(SDRATTR_GRAFTRANSPARENCE).GetValue() ) ); + } + else + { + rSet.DisableItem( SID_ATTR_GRAF_TRANSPARENCE ); + } + } + } + break; + + case SID_ATTR_GRAF_CROP: + { + if( !bEnableCrop ) + rSet.DisableItem( nSlotId ); + } + break; + + case SID_COLOR_SETTINGS : + { + svx::ToolboxAccess aToolboxAccess( TOOLBOX_NAME ); + rSet.Put( SfxBoolItem( nWhich, aToolboxAccess.isToolboxVisible() ) ); + break; + } + + default: + break; + } + + nWhich = aIter.NextWhich(); + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/tbxctrls/itemwin.cxx b/svx/source/tbxctrls/itemwin.cxx new file mode 100644 index 000000000..0b0ee21ee --- /dev/null +++ b/svx/source/tbxctrls/itemwin.cxx @@ -0,0 +1,351 @@ +/* -*- 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 <com/sun/star/drawing/FillStyle.hpp> +#include <com/sun/star/frame/XDispatchProvider.hpp> +#include <com/sun/star/frame/XFrame.hpp> + +#include <sfx2/tbxctrl.hxx> +#include <sfx2/viewsh.hxx> +#include <sfx2/module.hxx> + +#include <vcl/event.hxx> +#include <vcl/svapp.hxx> +#include <vcl/settings.hxx> + +#include <svx/dialmgr.hxx> +#include <svx/strings.hrc> + +#include <svx/xlnwtit.hxx> +#include <svx/xtable.hxx> +#include <svx/itemwin.hxx> +#include <svtools/unitconv.hxx> +#include "linemetricbox.hxx" + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::frame; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::beans; + +SvxMetricField::SvxMetricField( + vcl::Window* pParent, const Reference< XFrame >& rFrame ) + : InterimItemWindow(pParent, "svx/ui/metricfieldbox.ui", "MetricFieldBox") + , m_xWidget(m_xBuilder->weld_metric_spin_button("metricfield", FieldUnit::MM)) + , nCurValue(0) + , eDestPoolUnit(MapUnit::Map100thMM) + , eDlgUnit(SfxModule::GetModuleFieldUnit(rFrame)) + , mxFrame(rFrame) +{ + m_xWidget->set_range(0, 5000, FieldUnit::NONE); + m_xWidget->connect_value_changed(LINK(this, SvxMetricField, ModifyHdl)); + m_xWidget->connect_focus_in(LINK(this, SvxMetricField, FocusInHdl)); + m_xWidget->get_widget().connect_key_press(LINK(this, SvxMetricField, KeyInputHdl)); + + SetFieldUnit(*m_xWidget, eDlgUnit); + + SetSizePixel(m_xWidget->get_preferred_size()); +} + +void SvxMetricField::dispose() +{ + m_xWidget.reset(); + InterimItemWindow::dispose(); +} + +SvxMetricField::~SvxMetricField() +{ + disposeOnce(); +} + +void SvxMetricField::set_sensitive(bool bSensitive) +{ + Enable(bSensitive); + m_xWidget->set_sensitive(bSensitive); + if (!bSensitive) + m_xWidget->set_text(""); +} + +void SvxMetricField::Update( const XLineWidthItem* pItem ) +{ + if ( pItem ) + { + // tdf#132169 we always get the value in MapUnit::Map100thMM but have + // to set it in the core metric of the target application + if (pItem->GetValue() != GetCoreValue(*m_xWidget, MapUnit::Map100thMM)) + SetMetricValue(*m_xWidget, pItem->GetValue(), MapUnit::Map100thMM); + } + else + m_xWidget->set_text(""); +} + +IMPL_LINK_NOARG(SvxMetricField, ModifyHdl, weld::MetricSpinButton&, void) +{ + auto nTmp = GetCoreValue(*m_xWidget, eDestPoolUnit); + XLineWidthItem aLineWidthItem( nTmp ); + + Any a; + Sequence< PropertyValue > aArgs( 1 ); + aArgs[0].Name = "LineWidth"; + aLineWidthItem.QueryValue( a ); + aArgs[0].Value = a; + SfxToolBoxControl::Dispatch( Reference< XDispatchProvider >( mxFrame->getController(), UNO_QUERY ), + ".uno:LineWidth", + aArgs ); +} + +void SvxMetricField::ReleaseFocus_Impl() +{ + if( SfxViewShell::Current() ) + { + vcl::Window* pShellWnd = SfxViewShell::Current()->GetWindow(); + if ( pShellWnd ) + pShellWnd->GrabFocus(); + } +} + +void SvxMetricField::SetDestCoreUnit( MapUnit eUnit ) +{ + eDestPoolUnit = eUnit; +} + +void SvxMetricField::RefreshDlgUnit() +{ + FieldUnit eTmpUnit = SfxModule::GetModuleFieldUnit( mxFrame ); + if ( eDlgUnit != eTmpUnit ) + { + eDlgUnit = eTmpUnit; + SetFieldUnit(*m_xWidget, eDlgUnit); + } +} + +IMPL_LINK_NOARG(SvxMetricField, FocusInHdl, weld::Widget&, void) +{ + nCurValue = m_xWidget->get_value(FieldUnit::NONE); +} + +IMPL_LINK(SvxMetricField, KeyInputHdl, const KeyEvent&, rKEvt, bool) +{ + bool bHandled = false; + + sal_uInt16 nCode = rKEvt.GetKeyCode().GetCode(); + + if (nCode == KEY_ESCAPE) + { + m_xWidget->set_value(nCurValue, FieldUnit::NONE); + ModifyHdl(*m_xWidget); + ReleaseFocus_Impl(); + bHandled = true; + } + + return bHandled || ChildKeyInput(rKEvt); +} + +void SvxMetricField::DataChanged( const DataChangedEvent& rDCEvt ) +{ + if ( (rDCEvt.GetType() == DataChangedEventType::SETTINGS) && + (rDCEvt.GetFlags() & AllSettingsFlags::STYLE) ) + { + SetSizePixel(m_xWidget->get_preferred_size()); + } + + InterimItemWindow::DataChanged( rDCEvt ); +} + +void SvxMetricField::GetFocus() +{ + if (m_xWidget) + m_xWidget->grab_focus(); + InterimItemWindow::GetFocus(); +} + +void SvxFillTypeBox::Fill(weld::ComboBox& rListBox) +{ + rListBox.freeze(); + + rListBox.append_text(SvxResId(RID_SVXSTR_INVISIBLE)); + rListBox.append_text(SvxResId(RID_SVXSTR_COLOR)); + rListBox.append_text(SvxResId(RID_SVXSTR_GRADIENT)); + rListBox.append_text(SvxResId(RID_SVXSTR_HATCH)); + rListBox.append_text(SvxResId(RID_SVXSTR_BITMAP)); + rListBox.append_text(SvxResId(RID_SVXSTR_PATTERN)); + + rListBox.thaw(); + + rListBox.set_active(1); // solid color +} + +namespace +{ + void formatBitmapExToSize(BitmapEx& rBitmapEx, const Size& rSize) + { + if(!rBitmapEx.IsEmpty() && !rSize.IsEmpty()) + { + ScopedVclPtrInstance< VirtualDevice > pVirtualDevice; + pVirtualDevice->SetOutputSizePixel(rSize); + + if(rBitmapEx.IsTransparent()) + { + const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings(); + + if(rStyleSettings.GetPreviewUsesCheckeredBackground()) + { + const Point aNull(0, 0); + static const sal_uInt32 nLen(8); + static const Color aW(COL_WHITE); + static const Color aG(0xef, 0xef, 0xef); + + pVirtualDevice->DrawCheckered(aNull, rSize, nLen, aW, aG); + } + else + { + pVirtualDevice->SetBackground(rStyleSettings.GetFieldColor()); + pVirtualDevice->Erase(); + } + } + + if(rBitmapEx.GetSizePixel().Width() >= rSize.Width() && rBitmapEx.GetSizePixel().Height() >= rSize.Height()) + { + rBitmapEx.Scale(rSize); + pVirtualDevice->DrawBitmapEx(Point(0, 0), rBitmapEx); + } + else + { + const Size aBitmapSize(rBitmapEx.GetSizePixel()); + + for(long y(0); y < rSize.Height(); y += aBitmapSize.Height()) + { + for(long x(0); x < rSize.Width(); x += aBitmapSize.Width()) + { + pVirtualDevice->DrawBitmapEx( + Point(x, y), + rBitmapEx); + } + } + } + + rBitmapEx = pVirtualDevice->GetBitmapEx(Point(0, 0), rSize); + } + } +} // end of anonymous namespace + +void SvxFillAttrBox::Fill(weld::ComboBox& rBox, const XHatchListRef &pList) +{ + if( !pList.is() ) + return; + + long nCount = pList->Count(); + ScopedVclPtrInstance< VirtualDevice > pVD; + rBox.freeze(); + + for( long i = 0; i < nCount; i++ ) + { + const XHatchEntry* pEntry = pList->GetHatch(i); + const BitmapEx aBitmapEx = pList->GetUiBitmap( i ); + if( !aBitmapEx.IsEmpty() ) + { + const Size aBmpSize(aBitmapEx.GetSizePixel()); + pVD->SetOutputSizePixel(aBmpSize, false); + pVD->DrawBitmapEx(Point(), aBitmapEx); + rBox.append("", pEntry->GetName(), *pVD); + } + else + rBox.append_text(pEntry->GetName()); + } + + rBox.thaw(); +} + +void SvxFillAttrBox::Fill(weld::ComboBox& rBox, const XGradientListRef &pList) +{ + if( !pList.is() ) + return; + + long nCount = pList->Count(); + ScopedVclPtrInstance< VirtualDevice > pVD; + rBox.freeze(); + + for( long i = 0; i < nCount; i++ ) + { + const XGradientEntry* pEntry = pList->GetGradient(i); + const BitmapEx aBitmapEx = pList->GetUiBitmap( i ); + if( !aBitmapEx.IsEmpty() ) + { + const Size aBmpSize(aBitmapEx.GetSizePixel()); + pVD->SetOutputSizePixel(aBmpSize, false); + pVD->DrawBitmapEx(Point(), aBitmapEx); + rBox.append("", pEntry->GetName(), *pVD); + } + else + rBox.append_text(pEntry->GetName()); + } + + rBox.thaw(); +} + +void SvxFillAttrBox::Fill(weld::ComboBox& rBox, const XBitmapListRef &pList) +{ + if( !pList.is() ) + return; + + long nCount = pList->Count(); + const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings(); + const Size aSize(rStyleSettings.GetListBoxPreviewDefaultPixelSize()); + ScopedVclPtrInstance< VirtualDevice > pVD; + pVD->SetOutputSizePixel(aSize, false); + rBox.freeze(); + + for( long i = 0; i < nCount; i++ ) + { + const XBitmapEntry* pEntry = pList->GetBitmap( i ); + BitmapEx aBitmapEx = pEntry->GetGraphicObject().GetGraphic().GetBitmapEx(); + formatBitmapExToSize(aBitmapEx, aSize); + pVD->DrawBitmapEx(Point(), aBitmapEx); + rBox.append("", pEntry->GetName(), *pVD); + } + + rBox.thaw(); +} + +void SvxFillAttrBox::Fill(weld::ComboBox& rBox, const XPatternListRef &pList) +{ + if( !pList.is() ) + return; + + long nCount = pList->Count(); + const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings(); + const Size aSize(rStyleSettings.GetListBoxPreviewDefaultPixelSize()); + ScopedVclPtrInstance< VirtualDevice > pVD; + pVD->SetOutputSizePixel(aSize, false); + rBox.freeze(); + + for( long i = 0; i < nCount; i++ ) + { + const XBitmapEntry* pEntry = pList->GetBitmap( i ); + BitmapEx aBitmapEx = pEntry->GetGraphicObject().GetGraphic().GetBitmapEx(); + formatBitmapExToSize(aBitmapEx, aSize); + pVD->DrawBitmapEx(Point(), aBitmapEx); + rBox.append("", pEntry->GetName(), *pVD); + } + + rBox.thaw(); + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/tbxctrls/layctrl.cxx b/svx/source/tbxctrls/layctrl.cxx new file mode 100644 index 000000000..88b110e8c --- /dev/null +++ b/svx/source/tbxctrls/layctrl.cxx @@ -0,0 +1,803 @@ +/* -*- 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 <vcl/customweld.hxx> +#include <vcl/event.hxx> +#include <vcl/settings.hxx> +#include <vcl/svapp.hxx> +#include <vcl/toolbox.hxx> + +#include <svx/strings.hrc> +#include <svx/layctrl.hxx> +#include <svx/dialmgr.hxx> +#include <comphelper/processfactory.hxx> +#include <svtools/colorcfg.hxx> +#include <svtools/toolbarmenu.hxx> +#include <com/sun/star/util/URLTransformer.hpp> +#include <com/sun/star/frame/XDispatchProvider.hpp> + +// namespaces +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::util; +using namespace ::com::sun::star::frame; + +namespace { + +class TableWidget final : public weld::CustomWidgetController +{ +private: + rtl::Reference<SvxTableToolBoxControl> mxControl; + OUString maCommand; + + long nCol; + long nLine; + + static const long TABLE_CELLS_HORIZ; + static const long TABLE_CELLS_VERT; + + long mnTableCellWidth; + long mnTableCellHeight; + + long mnTableWidth; + long mnTableHeight; + + ::Color aFontColor; + ::Color aLineColor; + ::Color aFillColor; + ::Color aHighlightFillColor; + ::Color aBackgroundColor; + + void Update(long nNewCol, long nNewLine); + void InsertTable(); + +public: + TableWidget(SvxTableToolBoxControl* pControl, const OUString& rCommand); + + virtual void SetDrawingArea(weld::DrawingArea* pDrawingArea) override; + + virtual bool KeyInput(const KeyEvent&) override; + virtual bool MouseButtonDown(const MouseEvent&) override; + virtual bool MouseMove(const MouseEvent&) override; + virtual bool MouseButtonUp(const MouseEvent&) override; + virtual void Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect) override; +}; + +class TableWindow final : public WeldToolbarPopup +{ +private: + std::unique_ptr<weld::Button> mxTableButton; + std::unique_ptr<TableWidget> mxTableWidget; + std::unique_ptr<weld::CustomWeld> mxTableWidgetWin; + rtl::Reference<SvxTableToolBoxControl> mxControl; + + DECL_LINK(SelectHdl, weld::Button&, void); + +public: + TableWindow( SvxTableToolBoxControl* pControl, weld::Widget* pParent, + const OUString& rCmd); + virtual void GrabFocus() override + { + mxTableWidget->GrabFocus(); + } +}; + +} + +const long TableWidget::TABLE_CELLS_HORIZ = 10; +const long TableWidget::TABLE_CELLS_VERT = 15; + +IMPL_LINK_NOARG(TableWindow, SelectHdl, weld::Button&, void) +{ + mxControl->CloseAndShowTableDialog(); +} + +TableWindow::TableWindow(SvxTableToolBoxControl* pControl, weld::Widget* pParent, const OUString& rCmd) + : WeldToolbarPopup(pControl->getFrameInterface(), pParent, "svx/ui/tablewindow.ui", "TableWindow") + , mxTableButton(m_xBuilder->weld_button("moreoptions")) + , mxTableWidget(new TableWidget(pControl, rCmd)) + , mxTableWidgetWin(new weld::CustomWeld(*m_xBuilder, "table", *mxTableWidget)) + , mxControl(pControl) +{ + mxTableButton->set_label( SvxResId( RID_SVXSTR_MORE ) ); + mxTableButton->connect_clicked( LINK( this, TableWindow, SelectHdl ) ); + mxTableButton->show(); +} + +TableWidget::TableWidget(SvxTableToolBoxControl* pControl, const OUString& rCommand) + : mxControl(pControl) + , maCommand(rCommand) + , nCol(0) + , nLine(0) + , mnTableCellWidth(0) + , mnTableCellHeight(0) + , mnTableWidth(0) + , mnTableHeight(0) +{ + const StyleSettings& rStyles = Application::GetSettings().GetStyleSettings(); + svtools::ColorConfig aColorConfig; + aFontColor = aColorConfig.GetColorValue( svtools::FONTCOLOR ).nColor; + aLineColor = rStyles.GetShadowColor(); + aFillColor = rStyles.GetWindowColor(); + aHighlightFillColor = rStyles.GetHighlightColor(); + aBackgroundColor = rStyles.GetFaceColor(); +} + +void TableWidget::SetDrawingArea(weld::DrawingArea* pDrawingArea) +{ + float fScaleFactor = pDrawingArea->get_ref_device().GetDPIScaleFactor(); + + mnTableCellWidth = 15 * fScaleFactor; + mnTableCellHeight = 15 * fScaleFactor; + + mnTableWidth = TABLE_CELLS_HORIZ*mnTableCellWidth; + mnTableHeight = TABLE_CELLS_VERT*mnTableCellHeight; + + //Â + 1 to leave space to draw the right/bottom borders + Size aSize(mnTableWidth + 1, mnTableHeight + 1); + pDrawingArea->set_size_request(aSize.Width(), aSize.Height()); + CustomWidgetController::SetDrawingArea(pDrawingArea); + SetOutputSizePixel(aSize); +} + +bool TableWidget::MouseMove(const MouseEvent& rMEvt) +{ + Point aPos = rMEvt.GetPosPixel(); + Point aMousePos( aPos ); + + long nNewCol = ( aMousePos.X() + mnTableCellWidth ) / mnTableCellWidth; + long nNewLine = ( aMousePos.Y() + mnTableCellHeight ) / mnTableCellHeight; + + Update( nNewCol, nNewLine ); + + return true; +} + +bool TableWidget::KeyInput(const KeyEvent& rKEvt) +{ + bool bHandled = false; + sal_uInt16 nModifier = rKEvt.GetKeyCode().GetModifier(); + sal_uInt16 nKey = rKEvt.GetKeyCode().GetCode(); + if ( !nModifier ) + { + bHandled = true; + long nNewCol = nCol; + long nNewLine = nLine; + switch(nKey) + { + case KEY_UP: + if ( nNewLine > 1 ) + nNewLine--; + else + mxControl->EndPopupMode(); + break; + case KEY_DOWN: + if ( nNewLine < TABLE_CELLS_VERT ) + { + nNewLine++; + if ( nNewCol == 0 ) + nNewCol = 1; + } + else + mxControl->CloseAndShowTableDialog(); + break; + case KEY_LEFT: + if ( nNewCol > 1 ) + nNewCol--; + else + mxControl->EndPopupMode(); + break; + case KEY_RIGHT: + if ( nNewCol < TABLE_CELLS_HORIZ ) + { + nNewCol++; + if ( nNewLine == 0 ) + nNewLine = 1; + } + else + mxControl->CloseAndShowTableDialog(); + break; + case KEY_ESCAPE: + mxControl->EndPopupMode(); + break; + case KEY_RETURN: + InsertTable(); + mxControl->EndPopupMode(); + return true; + default: + bHandled = false; + } + if ( bHandled ) + { + Update( nNewCol, nNewLine ); + } + } + else if (KEY_MOD1 == nModifier && KEY_RETURN == nKey) + { + InsertTable(); + mxControl->EndPopupMode(); + return true; + } + + return bHandled; +} + +bool TableWidget::MouseButtonUp(const MouseEvent&) +{ + InsertTable(); + mxControl->EndPopupMode(); + return true; +} + +bool TableWidget::MouseButtonDown(const MouseEvent&) +{ + return true; +} + +void TableWidget::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle&) +{ + rRenderContext.Push(PushFlags::FONT); + + rRenderContext.SetBackground( aBackgroundColor ); + vcl::Font aFont = rRenderContext.GetFont(); + aFont.SetColor( aFontColor ); + aFont.SetFillColor( aBackgroundColor ); + aFont.SetTransparent( false ); + rRenderContext.SetFont( aFont ); + + const long nSelectionWidth = nCol * mnTableCellWidth; + const long nSelectionHeight = nLine * mnTableCellHeight; + + // the non-selected parts of the table + rRenderContext.SetLineColor(aLineColor); + rRenderContext.SetFillColor(aFillColor); + rRenderContext.DrawRect(tools::Rectangle(nSelectionWidth, 0, mnTableWidth, nSelectionHeight)); + rRenderContext.DrawRect(tools::Rectangle(0, nSelectionHeight, nSelectionWidth, mnTableHeight)); + rRenderContext.DrawRect(tools::Rectangle(nSelectionWidth, nSelectionHeight, mnTableWidth, mnTableHeight)); + + // the selection + if (nCol > 0 && nLine > 0) + { + rRenderContext.SetFillColor(aHighlightFillColor); + rRenderContext.DrawRect(tools::Rectangle(0, 0, nSelectionWidth, nSelectionHeight)); + } + + // lines inside of the table + rRenderContext.SetLineColor(aLineColor); + for (long i = 1; i < TABLE_CELLS_VERT; ++i) + { + rRenderContext.DrawLine(Point(0, i*mnTableCellHeight), + Point(mnTableWidth, i*mnTableCellHeight)); + } + + for (long i = 1; i < TABLE_CELLS_HORIZ; ++i) + { + rRenderContext.DrawLine(Point( i*mnTableCellWidth, 0), + Point( i*mnTableCellWidth, mnTableHeight)); + } + + // the text near the mouse cursor telling the table dimensions + if (!nCol || !nLine) + { + rRenderContext.Pop(); + return; + } + + OUString aText = OUString::number( nCol ) + " x " + OUString::number( nLine ); + if (maCommand == ".uno:ShowMultiplePages") + { + aText += " " + SvxResId(RID_SVXSTR_PAGES); + } + + Size aTextSize(rRenderContext.GetTextWidth(aText), rRenderContext.GetTextHeight()); + + long nTextX = nSelectionWidth + mnTableCellWidth; + long nTextY = nSelectionHeight + mnTableCellHeight; + const long nTipBorder = 2; + + if (aTextSize.Width() + mnTableCellWidth + 2 * nTipBorder < nSelectionWidth) + nTextX = nSelectionWidth - mnTableCellWidth - aTextSize.Width(); + + if (aTextSize.Height() + mnTableCellHeight + 2 * nTipBorder < nSelectionHeight) + nTextY = nSelectionHeight - mnTableCellHeight - aTextSize.Height(); + + rRenderContext.SetLineColor(aLineColor); + rRenderContext.SetFillColor(aBackgroundColor); + rRenderContext.DrawRect(tools::Rectangle(nTextX - 2 * nTipBorder, + nTextY - 2 * nTipBorder, + nTextX + aTextSize.Width() + nTipBorder, + nTextY + aTextSize.Height() + nTipBorder)); + + // #i95350# force RTL output + if (IsRTLEnabled()) + aText = u"\u202D" + aText; + + rRenderContext.DrawText(Point(nTextX, nTextY), aText); + + rRenderContext.Pop(); +} + +void TableWidget::InsertTable() +{ + if (nCol && nLine) + { + Sequence< PropertyValue > aArgs( 2 ); + aArgs[0].Name = "Columns"; + aArgs[0].Value <<= sal_Int16( nCol ); + aArgs[1].Name = "Rows"; + aArgs[1].Value <<= sal_Int16( nLine ); + + mxControl->TableDialog( aArgs ); + } +} + +void TableWidget::Update( long nNewCol, long nNewLine ) +{ + if ( nNewCol < 0 || nNewCol > TABLE_CELLS_HORIZ ) + nNewCol = 0; + + if ( nNewLine < 0 || nNewLine > TABLE_CELLS_VERT ) + nNewLine = 0; + + if ( nNewCol != nCol || nNewLine != nLine ) + { + nCol = nNewCol; + nLine = nNewLine; + Invalidate(tools::Rectangle(0, 0, mnTableWidth, mnTableHeight)); + } +} + +void SvxTableToolBoxControl::TableDialog( const Sequence< PropertyValue >& rArgs ) +{ + Reference< XDispatchProvider > xDispatchProvider( m_xFrame, UNO_QUERY ); + if ( xDispatchProvider.is() ) + { + css::util::URL aTargetURL; + Reference < XURLTransformer > xTrans( URLTransformer::create(::comphelper::getProcessComponentContext()) ); + aTargetURL.Complete = m_aCommandURL; + xTrans->parseStrict( aTargetURL ); + + Reference< XDispatch > xDispatch = xDispatchProvider->queryDispatch( aTargetURL, OUString(), 0 ); + if ( xDispatch.is() ) + xDispatch->dispatch( aTargetURL, rArgs ); + } +} + +void SvxTableToolBoxControl::CloseAndShowTableDialog() +{ + // close the toolbar tool + EndPopupMode(); + + // and open the table dialog instead + TableDialog( Sequence< PropertyValue >() ); +} + +namespace { + +class ColumnsWidget final : public weld::CustomWidgetController +{ +private: + static constexpr long WIDTH = 5; + + rtl::Reference<SvxColumnsToolBoxControl> mxControl; + weld::SpinButton& mrSpinButton; + + ::Color aLineColor; + ::Color aHighlightLineColor; + ::Color aFillColor; + ::Color aHighlightFillColor; + ::Color aFaceColor; + long nCol; + long nMX; + bool m_bMod1; + + DECL_LINK(ValueChangedHdl, weld::SpinButton&, void); + DECL_LINK(ActivateHdl, weld::Entry&, bool); + + void InsertColumns(); + void UpdateSize_Impl( long nNewCol ); +public: + ColumnsWidget(SvxColumnsToolBoxControl* pControl, weld::SpinButton& rSpinButton); + + virtual void SetDrawingArea(weld::DrawingArea* pDrawingArea) override; + + virtual bool KeyInput(const KeyEvent&) override; + virtual bool MouseButtonDown(const MouseEvent&) override; + virtual bool MouseMove(const MouseEvent&) override; + virtual bool MouseButtonUp(const MouseEvent&) override; + virtual void Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect) override; +}; + + +class ColumnsWindow final : public WeldToolbarPopup +{ +private: + std::unique_ptr<weld::SpinButton> mxSpinButton; + std::unique_ptr<ColumnsWidget> mxColumnsWidget; + std::unique_ptr<weld::CustomWeld> mxColumnsWidgetWin; + rtl::Reference<SvxColumnsToolBoxControl> mxControl; + +public: + ColumnsWindow(SvxColumnsToolBoxControl* pControl, weld::Widget* pParent); + + virtual void GrabFocus() override + { + mxColumnsWidget->GrabFocus(); + } +}; + +} + +ColumnsWindow::ColumnsWindow(SvxColumnsToolBoxControl* pControl, weld::Widget* pParent) + : WeldToolbarPopup(pControl->getFrameInterface(), pParent, "svx/ui/columnswindow.ui", "ColumnsWindow") + , mxSpinButton(m_xBuilder->weld_spin_button("spinbutton")) + , mxColumnsWidget(new ColumnsWidget(pControl, *mxSpinButton)) + , mxColumnsWidgetWin(new weld::CustomWeld(*m_xBuilder, "columns", *mxColumnsWidget)) + , mxControl(pControl) +{ +} + +ColumnsWidget::ColumnsWidget(SvxColumnsToolBoxControl* pControl, weld::SpinButton& rSpinButton) + : mxControl(pControl) + , mrSpinButton(rSpinButton) + , nCol(1) + , nMX(0) + , m_bMod1(false) +{ + mrSpinButton.connect_value_changed(LINK(this, ColumnsWidget, ValueChangedHdl)); + mrSpinButton.connect_activate(LINK(this, ColumnsWidget, ActivateHdl)); + + const StyleSettings& rStyles = Application::GetSettings().GetStyleSettings(); + svtools::ColorConfig aColorConfig; + aLineColor = aColorConfig.GetColorValue( svtools::FONTCOLOR ).nColor; + aHighlightLineColor = rStyles.GetHighlightTextColor(); + aFillColor = rStyles.GetWindowColor(); + aHighlightFillColor = rStyles.GetHighlightColor(); + aFaceColor = rStyles.GetFaceColor(); +} + +IMPL_LINK_NOARG(ColumnsWidget, ValueChangedHdl, weld::SpinButton&, void) +{ + UpdateSize_Impl(mrSpinButton.get_value()); +} + +IMPL_LINK_NOARG(ColumnsWidget, ActivateHdl, weld::Entry&, bool) +{ + InsertColumns(); + mxControl->EndPopupMode(); + return true; +} + +void ColumnsWidget::SetDrawingArea(weld::DrawingArea* pDrawingArea) +{ + OutputDevice& rDevice = pDrawingArea->get_ref_device(); + Size aLogicSize = rDevice.LogicToPixel( Size( 95, 155 ), MapMode( MapUnit::Map10thMM ) ); + nMX = aLogicSize.Width(); + Size aSize(nMX*WIDTH-1, aLogicSize.Height()); + pDrawingArea->set_size_request(aSize.Width(), aSize.Height()); + CustomWidgetController::SetDrawingArea(pDrawingArea); + SetOutputSizePixel(aSize); +} + +bool ColumnsWidget::MouseMove(const MouseEvent& rMEvt) +{ + Point aPos = rMEvt.GetPosPixel(); + + long nNewCol = 1; + if ( aPos.X() > 0 ) + nNewCol = aPos.X() / nMX + 1; + if ( nNewCol > 20 ) + nNewCol = 20; + UpdateSize_Impl( nNewCol ); + + return true; +} + +void ColumnsWidget::UpdateSize_Impl( long nNewCol ) +{ + if ( nNewCol != nCol ) + { + Size aWinSize = GetOutputSizePixel(); + + Invalidate( tools::Rectangle( 0, aWinSize.Height() - 2, + aWinSize.Width(), aWinSize.Height() ) ); + + long nMinCol = 0, nMaxCol = 0; + + if ( nNewCol < nCol ) + { + nMinCol = nNewCol; + nMaxCol = nCol; + } + else + { + nMinCol = nCol; + nMaxCol = nNewCol; + } + + Invalidate( tools::Rectangle( nMinCol*nMX-1, 0, + nMaxCol*nMX+1, aWinSize.Height() - 2 ) ); + nCol = nNewCol; + mrSpinButton.set_value(nCol); + } +} + +bool ColumnsWidget::MouseButtonDown(const MouseEvent&) +{ + return true; +} + +bool ColumnsWidget::KeyInput(const KeyEvent& rKEvt) +{ + bool bHandled = false; + sal_uInt16 nModifier = rKEvt.GetKeyCode().GetModifier(); + sal_uInt16 nKey = rKEvt.GetKeyCode().GetCode(); + if(!nModifier) + { + if( KEY_LEFT == nKey || KEY_RIGHT == nKey || + KEY_RETURN == nKey ||KEY_ESCAPE == nKey || + KEY_UP == nKey) + { + bHandled = true; + long nNewCol = nCol; + switch(nKey) + { + case KEY_LEFT : + if(nNewCol) + nNewCol--; + break; + case KEY_RIGHT : + nNewCol++; + break; + case KEY_RETURN : + InsertColumns(); + mxControl->EndPopupMode(); + break; + case KEY_ESCAPE : + case KEY_UP : + mxControl->EndPopupMode(); + break; + } + UpdateSize_Impl( nNewCol ); + } + } + else if(KEY_MOD1 == nModifier && KEY_RETURN == nKey) + { + m_bMod1 = true; + InsertColumns(); + mxControl->EndPopupMode(); + } + return bHandled; +} + +bool ColumnsWidget::MouseButtonUp(const MouseEvent&) +{ + InsertColumns(); + mxControl->EndPopupMode(); + return true; +} + +void ColumnsWidget::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle&) +{ + rRenderContext.Push(PushFlags::FONT); + + rRenderContext.SetBackground(); + vcl::Font aFont( rRenderContext.GetFont() ); + aFont.SetColor( aLineColor ); + aFont.SetFillColor( aFaceColor ); + aFont.SetTransparent( false ); + rRenderContext.SetFont( aFont ); + + long i; + long nLineWidth; + Size aSize(GetOutputSizePixel()); + + for (i = 0; i < WIDTH; i++) + { + if (i < nCol) + { + rRenderContext.SetLineColor(aHighlightLineColor); + rRenderContext.SetFillColor(aHighlightFillColor); + } + else + { + rRenderContext.SetLineColor(aLineColor); + rRenderContext.SetFillColor(aFillColor); + } + + rRenderContext.DrawRect(tools::Rectangle(i * nMX - 1, -1, i * nMX + nMX, aSize.Height() - 1)); + + long j = 4; + while (j < aSize.Height() - 4) + { + if (!(j % 16)) + nLineWidth = 10; + else + nLineWidth = 4; + rRenderContext.DrawLine(Point(i * nMX + 4, j), Point(i * nMX + nMX - nLineWidth - 4, j)); + j += 4; + } + } + + rRenderContext.SetLineColor(); + rRenderContext.SetFillColor(aFaceColor); + + rRenderContext.DrawRect(tools::Rectangle(0, + aSize.Height() - 2, + aSize.Width() / 2 - 1, + aSize.Height())); + + rRenderContext.DrawRect(tools::Rectangle(aSize.Width() / 2, + aSize.Height() - 2, + aSize.Width(), + aSize.Height())); + + rRenderContext.SetLineColor(aLineColor); + rRenderContext.SetFillColor(); + rRenderContext.DrawRect(tools::Rectangle( 0, 0, aSize.Width() - 1, aSize.Height() - 1)); + + rRenderContext.Pop(); +} + +void SvxColumnsToolBoxControl::InsertColumns(const Sequence< PropertyValue >& rArgs) +{ + Reference< XDispatchProvider > xDispatchProvider( m_xFrame, UNO_QUERY ); + if ( xDispatchProvider.is() ) + { + css::util::URL aTargetURL; + Reference < XURLTransformer > xTrans( URLTransformer::create(::comphelper::getProcessComponentContext()) ); + aTargetURL.Complete = m_aCommandURL; + xTrans->parseStrict( aTargetURL ); + + Reference< XDispatch > xDispatch = xDispatchProvider->queryDispatch( aTargetURL, OUString(), 0 ); + if ( xDispatch.is() ) + xDispatch->dispatch( aTargetURL, rArgs ); + } +} + +void ColumnsWidget::InsertColumns() +{ + if (nCol) + { + Sequence< PropertyValue > aArgs( 2 ); + aArgs[0].Name = "Columns"; + aArgs[0].Value <<= sal_Int16( nCol ); + aArgs[1].Name = "Modifier"; + aArgs[1].Value <<= sal_Int16( m_bMod1 ? KEY_MOD1 : 0 ); + mxControl->InsertColumns(aArgs); + } +} + +SvxTableToolBoxControl::SvxTableToolBoxControl(const css::uno::Reference<css::uno::XComponentContext>& rContext) + : PopupWindowController(rContext, nullptr, OUString()) +{ +} + +void SvxTableToolBoxControl::initialize( const css::uno::Sequence< css::uno::Any >& rArguments ) +{ + PopupWindowController::initialize(rArguments); + + ToolBox* pToolBox = nullptr; + sal_uInt16 nId = 0; + if (getToolboxId(nId, &pToolBox) && pToolBox->GetItemCommand(nId) == m_aCommandURL) + pToolBox->SetItemBits(nId, ToolBoxItemBits::DROPDOWNONLY | pToolBox->GetItemBits(nId)); +} + +SvxTableToolBoxControl::~SvxTableToolBoxControl() +{ +} + +std::unique_ptr<WeldToolbarPopup> SvxTableToolBoxControl::weldPopupWindow() +{ + return std::make_unique<TableWindow>(this, m_pToolbar, m_aCommandURL); +} + +VclPtr<vcl::Window> SvxTableToolBoxControl::createVclPopupWindow( vcl::Window* pParent ) +{ + ToolBox* pToolBox = nullptr; + sal_uInt16 nId = 0; + bool bToolBox = getToolboxId(nId, &pToolBox); + + mxInterimPopover = VclPtr<InterimToolbarPopup>::Create(getFrameInterface(), pParent, + std::make_unique<TableWindow>(this, pParent->GetFrameWeld(), m_aCommandURL)); + + mxInterimPopover->SetText(bToolBox ? pToolBox->GetItemText(nId) : OUString()); + + mxInterimPopover->Show(); + + return mxInterimPopover; +} + +OUString SvxTableToolBoxControl::getImplementationName() +{ + return "com.sun.star.comp.svx.TableToolBoxControl"; +} + +css::uno::Sequence<OUString> SvxTableToolBoxControl::getSupportedServiceNames() +{ + return { "com.sun.star.frame.ToolbarController" }; +} + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * +com_sun_star_comp_svx_TableToolBoxControl_get_implementation( + css::uno::XComponentContext* rContext, + css::uno::Sequence<css::uno::Any> const & ) +{ + return cppu::acquire(new SvxTableToolBoxControl(rContext)); +} + +SvxColumnsToolBoxControl::SvxColumnsToolBoxControl(const css::uno::Reference<css::uno::XComponentContext>& rContext) + : PopupWindowController(rContext, nullptr, OUString()) +{ +} + +void SvxColumnsToolBoxControl::initialize( const css::uno::Sequence< css::uno::Any >& rArguments ) +{ + PopupWindowController::initialize(rArguments); + + ToolBox* pToolBox = nullptr; + sal_uInt16 nId = 0; + if (getToolboxId(nId, &pToolBox) && pToolBox->GetItemCommand(nId) == m_aCommandURL) + pToolBox->SetItemBits(nId, ToolBoxItemBits::DROPDOWNONLY | pToolBox->GetItemBits(nId)); +} + +SvxColumnsToolBoxControl::~SvxColumnsToolBoxControl() +{ +} + +std::unique_ptr<WeldToolbarPopup> SvxColumnsToolBoxControl::weldPopupWindow() +{ + return std::make_unique<ColumnsWindow>(this, m_pToolbar); +} + +VclPtr<vcl::Window> SvxColumnsToolBoxControl::createVclPopupWindow(vcl::Window* pParent) +{ + ToolBox* pToolBox = nullptr; + sal_uInt16 nId = 0; + bool bToolBox = getToolboxId(nId, &pToolBox); + + mxInterimPopover = VclPtr<InterimToolbarPopup>::Create(getFrameInterface(), pParent, + std::make_unique<ColumnsWindow>(this, pParent->GetFrameWeld())); + + mxInterimPopover->SetText(bToolBox ? pToolBox->GetItemText(nId) : OUString()); + + mxInterimPopover->Show(); + + return mxInterimPopover; +} + +OUString SvxColumnsToolBoxControl::getImplementationName() +{ + return "com.sun.star.comp.svx.ColumnsToolBoxControl"; +} + +css::uno::Sequence<OUString> SvxColumnsToolBoxControl::getSupportedServiceNames() +{ + return { "com.sun.star.frame.ToolbarController" }; +} + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * +com_sun_star_comp_svx_ColumnsToolBoxControl_get_implementation( + css::uno::XComponentContext* rContext, + css::uno::Sequence<css::uno::Any> const & ) +{ + return cppu::acquire(new SvxColumnsToolBoxControl(rContext)); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/tbxctrls/lboxctrl.cxx b/svx/source/tbxctrls/lboxctrl.cxx new file mode 100644 index 000000000..1c9a90203 --- /dev/null +++ b/svx/source/tbxctrls/lboxctrl.cxx @@ -0,0 +1,223 @@ +/* -*- 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 <sal/config.h> + +#include <sal/types.h> +#include <vcl/lstbox.hxx> +#include <vcl/toolbox.hxx> +#include <sfx2/bindings.hxx> +#include <svtools/toolbarmenu.hxx> +#include <svx/dialmgr.hxx> +#include <svx/lboxctrl.hxx> +#include <vcl/settings.hxx> +#include <tools/urlobj.hxx> + +#include <svx/strings.hrc> + +#include <comphelper/processfactory.hxx> +#include <com/sun/star/util/URLTransformer.hpp> +#include <com/sun/star/frame/XDispatchProvider.hpp> + + +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::util; +using namespace ::com::sun::star::frame; + +class SvxPopupWindowListBox final : public svtools::ToolbarPopup +{ + VclPtr<ListBox> m_pListBox; + rtl::Reference<SvxUndoRedoControl> m_xControl; + + DECL_LINK( SelectHdl, ListBox&, void ); + +public: + SvxPopupWindowListBox(SvxUndoRedoControl* pControl, vcl::Window* pParent); + virtual ~SvxPopupWindowListBox() override; + virtual void dispose() override; + + ListBox & GetListBox() { return *m_pListBox; } + + void SetInfo(sal_Int32 nCount); +}; + +SvxPopupWindowListBox::SvxPopupWindowListBox(SvxUndoRedoControl* pControl, vcl::Window* pParent) + : ToolbarPopup(pControl->getFrameInterface(), pParent, "FloatingUndoRedo", "svx/ui/floatingundoredo.ui") + , m_xControl(pControl) +{ + get(m_pListBox, "treeview"); + WinBits nBits(m_pListBox->GetStyle()); + nBits &= ~WB_SIMPLEMODE; + m_pListBox->SetStyle(nBits); + Size aSize(LogicToPixel(Size(100, 85), MapMode(MapUnit::MapAppFont))); + m_pListBox->set_width_request(aSize.Width()); + m_pListBox->set_height_request(aSize.Height()); + m_pListBox->EnableMultiSelection( true, true ); + SetBackground( GetSettings().GetStyleSettings().GetDialogColor() ); + + m_pListBox->SetSelectHdl( LINK( this, SvxPopupWindowListBox, SelectHdl ) ); +} + +SvxPopupWindowListBox::~SvxPopupWindowListBox() +{ + disposeOnce(); +} + +void SvxPopupWindowListBox::dispose() +{ + m_pListBox.clear(); + ToolbarPopup::dispose(); +} + +void SvxPopupWindowListBox::SetInfo( sal_Int32 nCount ) +{ + const char* pId; + if (nCount == 1) + pId = m_xControl->getCommandURL() == ".uno:Undo" ? RID_SVXSTR_NUM_UNDO_ACTION : RID_SVXSTR_NUM_REDO_ACTION; + else + pId = m_xControl->getCommandURL() == ".uno:Undo" ? RID_SVXSTR_NUM_UNDO_ACTIONS : RID_SVXSTR_NUM_REDO_ACTIONS; + OUString aActionStr = SvxResId(pId); + OUString aText = aActionStr.replaceAll("$(ARG1)", OUString::number(nCount)); + SetText(aText); +} + +IMPL_LINK(SvxPopupWindowListBox, SelectHdl, ListBox&, rListBox, void) +{ + if (rListBox.IsTravelSelect()) + SetInfo(rListBox.GetSelectedEntryCount()); + else + { + m_xControl->Do(GetListBox().GetSelectedEntryCount()); + EndPopupMode(); + } +} + +void SvxUndoRedoControl::Do(sal_Int16 nCount) +{ + Reference< XDispatchProvider > xDispatchProvider( m_xFrame, UNO_QUERY ); + if ( xDispatchProvider.is() ) + { + css::util::URL aTargetURL; + Reference < XURLTransformer > xTrans( URLTransformer::create(::comphelper::getProcessComponentContext()) ); + aTargetURL.Complete = m_aCommandURL; + xTrans->parseStrict( aTargetURL ); + + Reference< XDispatch > xDispatch = xDispatchProvider->queryDispatch( aTargetURL, OUString(), 0 ); + if ( xDispatch.is() ) + { + INetURLObject aObj( m_aCommandURL ); + Sequence< PropertyValue > aArgs( 1 ); + aArgs[0].Name = aObj.GetURLPath(); + aArgs[0].Value <<= nCount; + xDispatch->dispatch(aTargetURL, aArgs); + } + } +} + +SvxUndoRedoControl::SvxUndoRedoControl(const css::uno::Reference<css::uno::XComponentContext>& rContext) + : PopupWindowController(rContext, nullptr, OUString()) +{ +} + +void SvxUndoRedoControl::initialize( const css::uno::Sequence< css::uno::Any >& rArguments ) +{ + PopupWindowController::initialize(rArguments); + + ToolBox* pToolBox = nullptr; + sal_uInt16 nId = 0; + if (getToolboxId(nId, &pToolBox) && getModuleName() != "com.sun.star.script.BasicIDE") + { + pToolBox->SetItemBits(nId, ToolBoxItemBits::DROPDOWN | pToolBox->GetItemBits(nId)); + aDefaultTooltip = pToolBox->GetQuickHelpText(nId); + } +} + +SvxUndoRedoControl::~SvxUndoRedoControl() +{ +} + +// XStatusListener +void SAL_CALL SvxUndoRedoControl::statusChanged(const css::frame::FeatureStateEvent& rEvent) +{ + if (rEvent.FeatureURL.Main == ".uno:GetUndoStrings" || rEvent.FeatureURL.Main == ".uno:GetRedoStrings") + { + css::uno::Sequence<OUString> aStrings; + rEvent.State >>= aStrings; + aUndoRedoList = comphelper::sequenceToContainer<std::vector<OUString>>(aStrings); + return; + } + + PopupWindowController::statusChanged(rEvent); + + ToolBox* pToolBox = nullptr; + sal_uInt16 nId = 0; + if (!getToolboxId(nId, &pToolBox)) + return; + + if (!rEvent.IsEnabled) + { + pToolBox->SetQuickHelpText(nId, aDefaultTooltip); + return; + } + + OUString aQuickHelpText; + if (rEvent.State >>= aQuickHelpText) + pToolBox->SetQuickHelpText(nId, aQuickHelpText); +} + +VclPtr<vcl::Window> SvxUndoRedoControl::createVclPopupWindow(vcl::Window* pParent) +{ + if ( m_aCommandURL == ".uno:Undo" ) + updateStatus( ".uno:GetUndoStrings"); + else + updateStatus( ".uno:GetRedoStrings"); + + auto xPopupWin = VclPtr<SvxPopupWindowListBox>::Create(this, pParent); + + ListBox &rListBox = xPopupWin->GetListBox(); + + for(const OUString & s : aUndoRedoList) + rListBox.InsertEntry( s ); + + rListBox.SelectEntryPos(0); + xPopupWin->SetInfo(rListBox.GetSelectedEntryCount()); + + return xPopupWin; +} + +OUString SvxUndoRedoControl::getImplementationName() +{ + return "com.sun.star.comp.svx.UndoRedoToolBoxControl"; +} + +css::uno::Sequence<OUString> SvxUndoRedoControl::getSupportedServiceNames() +{ + return { "com.sun.star.frame.ToolbarController" }; +} + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * +com_sun_star_comp_svx_UndoRedoToolBoxControl_get_implementation( + css::uno::XComponentContext* rContext, + css::uno::Sequence<css::uno::Any> const & ) +{ + return cppu::acquire(new SvxUndoRedoControl(rContext)); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/tbxctrls/linectrl.cxx b/svx/source/tbxctrls/linectrl.cxx new file mode 100644 index 000000000..df0115f5b --- /dev/null +++ b/svx/source/tbxctrls/linectrl.cxx @@ -0,0 +1,635 @@ +/* -*- 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 <tools/debug.hxx> +#include <vcl/settings.hxx> +#include <vcl/svapp.hxx> +#include <vcl/toolbox.hxx> +#include <sfx2/objsh.hxx> + +#include <svtools/toolbarmenu.hxx> +#include <svtools/popupwindowcontroller.hxx> +#include <svtools/valueset.hxx> + +#include <svx/strings.hrc> +#include <svx/svxids.hrc> +#include <helpids.h> + +#include <svx/drawitem.hxx> +#include <svx/xlineit0.hxx> +#include <svx/xlndsit.hxx> +#include <svx/xlnstit.hxx> +#include <svx/xlnedit.hxx> +#include <svx/xtable.hxx> +#include <svx/linectrl.hxx> +#include <svx/itemwin.hxx> +#include <svx/dialmgr.hxx> +#include <svx/tbxcolorupdate.hxx> + +#include <memory> + +#include <comphelper/lok.hxx> + +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::util; +using namespace ::com::sun::star::frame; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star; + +// For End Line Controller +#define MAX_LINES 12 + +SvxLineStyleToolBoxControl::SvxLineStyleToolBoxControl( const css::uno::Reference<css::uno::XComponentContext>& rContext ) + : svt::PopupWindowController( rContext, nullptr, OUString() ) +{ + addStatusListener(".uno:LineDash"); +} + +SvxLineStyleToolBoxControl::~SvxLineStyleToolBoxControl() +{ +} + +void SAL_CALL SvxLineStyleToolBoxControl::statusChanged( const frame::FeatureStateEvent& rEvent ) +{ + ToolBox* pToolBox = nullptr; + sal_uInt16 nId = 0; + if (!getToolboxId(nId, &pToolBox) && !m_pToolbar) + return; + + OString sId(m_aCommandURL.toUtf8()); + + if ( rEvent.FeatureURL.Complete == m_aCommandURL ) + { + if (m_pToolbar) + m_pToolbar->set_item_sensitive(sId, rEvent.IsEnabled); + else + pToolBox->EnableItem( nId, rEvent.IsEnabled ); + } + + m_xBtnUpdater->Update(rEvent); + + SfxObjectShell* pSh = SfxObjectShell::Current(); + if (pSh) + { + const SvxDashListItem* pItem = pSh->GetItem( SID_DASH_LIST ); + if (pItem) + { + XDashListRef xList = pItem->GetDashList(); + int nIndex = m_xBtnUpdater->GetStyleIndex(); + switch (nIndex) + { + case -1: + case 0: + { + BitmapEx aEmpty(xList->GetBitmapForUISolidLine()); + aEmpty.Erase(Application::GetSettings().GetStyleSettings().GetFieldColor()); + if (m_pToolbar) + { + Graphic aGraf(aEmpty); + m_pToolbar->set_item_image(sId, aGraf.GetXGraphic()); + } + else + pToolBox->SetItemImage(nId, Image(aEmpty)); + break; + } + case 1: + if (m_pToolbar) + { + Graphic aGraf(xList->GetBitmapForUISolidLine()); + m_pToolbar->set_item_image(sId, aGraf.GetXGraphic()); + } + else + pToolBox->SetItemImage(nId, Image(xList->GetBitmapForUISolidLine())); + break; + default: + if (m_pToolbar) + { + Graphic aGraf(xList->GetUiBitmap(nIndex - 2)); + m_pToolbar->set_item_image(sId, aGraf.GetXGraphic()); + } + else + pToolBox->SetItemImage(nId, Image(xList->GetUiBitmap(nIndex - 2))); + break; + } + } + } +} + +void SAL_CALL SvxLineStyleToolBoxControl::execute(sal_Int16 /*KeyModifier*/) +{ + if (m_pToolbar) + { + // Toggle the popup also when toolbutton is activated + const OString aId(m_aCommandURL.toUtf8()); + m_pToolbar->set_menu_item_active(aId, !m_pToolbar->get_menu_item_active(aId)); + } + else + { + // Open the popup also when Enter key is pressed. + createPopupWindow(); + } +} + +void SvxLineStyleToolBoxControl::initialize( const css::uno::Sequence<css::uno::Any>& rArguments ) +{ + svt::PopupWindowController::initialize( rArguments ); + + if (m_pToolbar) + { + mxPopoverContainer.reset(new ToolbarPopupContainer(m_pToolbar)); + m_pToolbar->set_item_popover(m_aCommandURL.toUtf8(), mxPopoverContainer->getTopLevel()); + } + + ToolBox* pToolBox = nullptr; + sal_uInt16 nId = 0; + if ( getToolboxId( nId, &pToolBox ) ) + { + pToolBox->SetItemBits( nId, pToolBox->GetItemBits( nId ) | ToolBoxItemBits::DROPDOWNONLY ); + } + + m_xBtnUpdater.reset(new svx::ToolboxButtonLineStyleUpdater); +} + +void SvxLineStyleToolBoxControl::setLineStyleSelectFunction(const LineStyleSelectFunction& rLineStyleSelectFunction) +{ + m_aLineStyleSelectFunction = rLineStyleSelectFunction; +} + +void SvxLineStyleToolBoxControl::dispatchLineStyleCommand(const OUString& rCommand, const Sequence<PropertyValue>& rArgs) +{ + if (m_aLineStyleSelectFunction && m_aLineStyleSelectFunction(rCommand, rArgs[0].Value)) + return; + + dispatchCommand(rCommand, rArgs); +} + +std::unique_ptr<WeldToolbarPopup> SvxLineStyleToolBoxControl::weldPopupWindow() +{ + return std::make_unique<SvxLineBox>(this, m_pToolbar, m_xBtnUpdater->GetStyleIndex()); +} + +VclPtr<vcl::Window> SvxLineStyleToolBoxControl::createVclPopupWindow( vcl::Window* pParent ) +{ + mxInterimPopover = VclPtr<InterimToolbarPopup>::Create(getFrameInterface(), pParent, + std::make_unique<SvxLineBox>(this, pParent->GetFrameWeld(), m_xBtnUpdater->GetStyleIndex())); + + mxInterimPopover->Show(); + + return mxInterimPopover; +} + +OUString SvxLineStyleToolBoxControl::getImplementationName() +{ + return "com.sun.star.comp.svx.LineStyleToolBoxControl"; +} + +css::uno::Sequence<OUString> SvxLineStyleToolBoxControl::getSupportedServiceNames() +{ + return { "com.sun.star.frame.ToolbarController" }; +} + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * +com_sun_star_comp_svx_LineStyleToolBoxControl_get_implementation( + css::uno::XComponentContext* rContext, + css::uno::Sequence<css::uno::Any> const & ) +{ + return cppu::acquire( new SvxLineStyleToolBoxControl( rContext ) ); +} + +namespace { + +class SvxLineEndToolBoxControl final : public svt::PopupWindowController +{ +public: + explicit SvxLineEndToolBoxControl( const css::uno::Reference<css::uno::XComponentContext>& rContext ); + + // XInitialization + virtual void SAL_CALL initialize( const css::uno::Sequence<css::uno::Any>& rArguments ) override; + + // XServiceInfo + virtual OUString SAL_CALL getImplementationName() override; + virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override; + + virtual void SAL_CALL execute(sal_Int16 nKeyModifier) override; + +private: + virtual std::unique_ptr<WeldToolbarPopup> weldPopupWindow() override; + virtual VclPtr<vcl::Window> createVclPopupWindow( vcl::Window* pParent ) override; +}; + +class SvxLineEndWindow final : public WeldToolbarPopup +{ +private: + XLineEndListRef mpLineEndList; + rtl::Reference<SvxLineEndToolBoxControl> mxControl; + std::unique_ptr<ValueSet> mxLineEndSet; + std::unique_ptr<weld::CustomWeld> mxLineEndSetWin; + sal_uInt16 mnLines; + Size maBmpSize; + + DECL_LINK( SelectHdl, ValueSet*, void ); + void FillValueSet(); + void SetSize(); + + virtual void GrabFocus() override + { + mxLineEndSet->GrabFocus(); + } + +public: + SvxLineEndWindow(SvxLineEndToolBoxControl* pControl, weld::Widget* pParent); + virtual void statusChanged( const css::frame::FeatureStateEvent& rEvent ) override; +}; + +} + +static constexpr sal_uInt16 gnCols = 2; + +SvxLineEndWindow::SvxLineEndWindow(SvxLineEndToolBoxControl* pControl, weld::Widget* pParent) + : WeldToolbarPopup(pControl->getFrameInterface(), pParent, "svx/ui/floatinglineend.ui", "FloatingLineEnd") + , mxControl(pControl) + , mxLineEndSet(new ValueSet(m_xBuilder->weld_scrolled_window("valuesetwin"))) + , mxLineEndSetWin(new weld::CustomWeld(*m_xBuilder, "valueset", *mxLineEndSet)) + , mnLines(12) +{ + mxLineEndSet->SetStyle(mxLineEndSet->GetStyle() | WB_ITEMBORDER | WB_3DLOOK | WB_NO_DIRECTSELECT); + mxLineEndSet->SetHelpId(HID_POPUP_LINEEND_CTRL); + m_xTopLevel->set_help_id(HID_POPUP_LINEEND); + + SfxObjectShell* pDocSh = SfxObjectShell::Current(); + if ( pDocSh ) + { + const SfxPoolItem* pItem = pDocSh->GetItem( SID_LINEEND_LIST ); + if( pItem ) + mpLineEndList = static_cast<const SvxLineEndListItem*>( pItem )->GetLineEndList(); + } + DBG_ASSERT( mpLineEndList.is(), "LineEndList not found" ); + + mxLineEndSet->SetSelectHdl( LINK( this, SvxLineEndWindow, SelectHdl ) ); + mxLineEndSet->SetColCount( gnCols ); + + // ValueSet fill with entries of LineEndList + FillValueSet(); + + AddStatusListener( ".uno:LineEndListState"); +} + +IMPL_LINK_NOARG(SvxLineEndWindow, SelectHdl, ValueSet*, void) +{ + std::unique_ptr<XLineEndItem> pLineEndItem; + std::unique_ptr<XLineStartItem> pLineStartItem; + sal_uInt16 nId = mxLineEndSet->GetSelectedItemId(); + + if( nId == 1 ) + { + pLineStartItem.reset(new XLineStartItem()); + } + else if( nId == 2 ) + { + pLineEndItem.reset(new XLineEndItem()); + } + else if( nId % 2 ) // beginning of line + { + const XLineEndEntry* pEntry = mpLineEndList->GetLineEnd( (nId - 1) / 2 - 1 ); + pLineStartItem.reset(new XLineStartItem(pEntry->GetName(), pEntry->GetLineEnd())); + } + else // end of line + { + const XLineEndEntry* pEntry = mpLineEndList->GetLineEnd( nId / 2 - 2 ); + pLineEndItem.reset(new XLineEndItem(pEntry->GetName(), pEntry->GetLineEnd())); + } + + Sequence< PropertyValue > aArgs( 1 ); + Any a; + + if ( pLineStartItem ) + { + aArgs[0].Name = "LineStart"; + pLineStartItem->QueryValue( a ); + aArgs[0].Value = a; + } + else + { + aArgs[0].Name = "LineEnd"; + pLineEndItem->QueryValue( a ); + aArgs[0].Value = a; + } + + /* #i33380# DR 2004-09-03 Moved the following line above the Dispatch() call. + This instance may be deleted in the meantime (i.e. when a dialog is opened + while in Dispatch()), accessing members will crash in this case. */ + mxLineEndSet->SetNoSelection(); + + mxControl->dispatchCommand(mxControl->getCommandURL(), aArgs); + + mxControl->EndPopupMode(); +} + +void SvxLineEndWindow::FillValueSet() +{ + if( !mpLineEndList.is() ) + return; + + ScopedVclPtrInstance< VirtualDevice > pVD; + + long nCount = mpLineEndList->Count(); + + // First entry: no line end. + // An entry is temporarily added to get the UI bitmap + basegfx::B2DPolyPolygon aNothing; + mpLineEndList->Insert(std::make_unique<XLineEndEntry>(aNothing, + comphelper::LibreOfficeKit::isActive() ? SvxResId(RID_SVXSTR_INVISIBLE) + : SvxResId(RID_SVXSTR_NONE))); + const XLineEndEntry* pEntry = mpLineEndList->GetLineEnd(nCount); + BitmapEx aBmp = mpLineEndList->GetUiBitmap( nCount ); + OSL_ENSURE( !aBmp.IsEmpty(), "UI bitmap was not created" ); + + maBmpSize = aBmp.GetSizePixel(); + pVD->SetOutputSizePixel( maBmpSize, false ); + maBmpSize.setWidth( maBmpSize.Width() / 2 ); + Point aPt0( 0, 0 ); + Point aPt1( maBmpSize.Width(), 0 ); + + pVD->DrawBitmapEx( Point(), aBmp ); + mxLineEndSet->InsertItem(1, Image(pVD->GetBitmapEx(aPt0, maBmpSize)), pEntry->GetName()); + mxLineEndSet->InsertItem(2, Image(pVD->GetBitmapEx(aPt1, maBmpSize)), pEntry->GetName()); + + mpLineEndList->Remove(nCount); + + for( long i = 0; i < nCount; i++ ) + { + pEntry = mpLineEndList->GetLineEnd( i ); + DBG_ASSERT( pEntry, "Could not access LineEndEntry" ); + aBmp = mpLineEndList->GetUiBitmap( i ); + OSL_ENSURE( !aBmp.IsEmpty(), "UI bitmap was not created" ); + + pVD->DrawBitmapEx( aPt0, aBmp ); + mxLineEndSet->InsertItem(static_cast<sal_uInt16>((i+1)*2L+1), + Image(pVD->GetBitmapEx(aPt0, maBmpSize)), pEntry->GetName()); + mxLineEndSet->InsertItem(static_cast<sal_uInt16>((i+2)*2L), + Image(pVD->GetBitmapEx(aPt1, maBmpSize)), pEntry->GetName()); + } + mnLines = std::min( static_cast<sal_uInt16>(nCount + 1), sal_uInt16(MAX_LINES) ); + mxLineEndSet->SetLineCount( mnLines ); + + SetSize(); +} + +void SvxLineEndWindow::statusChanged( const css::frame::FeatureStateEvent& rEvent ) +{ + if ( rEvent.FeatureURL.Complete == ".uno:LineEndListState" ) + { + // The list of line ends (LineEndList) has changed + css::uno::Reference< css::uno::XWeak > xWeak; + if ( rEvent.State >>= xWeak ) + { + mpLineEndList.set( static_cast< XLineEndList* >( xWeak.get() ) ); + DBG_ASSERT( mpLineEndList.is(), "LineEndList not found" ); + + mxLineEndSet->Clear(); + FillValueSet(); + } + } +} + +void SvxLineEndWindow::SetSize() +{ + sal_uInt16 nItemCount = mxLineEndSet->GetItemCount(); + sal_uInt16 nMaxLines = nItemCount / gnCols; + + WinBits nBits = mxLineEndSet->GetStyle(); + if ( mnLines == nMaxLines ) + nBits &= ~WB_VSCROLL; + else + nBits |= WB_VSCROLL; + mxLineEndSet->SetStyle( nBits ); + + Size aSize( maBmpSize ); + aSize.AdjustWidth(6 ); + aSize.AdjustHeight(6 ); + aSize = mxLineEndSet->CalcWindowSizePixel( aSize ); + mxLineEndSet->GetDrawingArea()->set_size_request(aSize.Width(), aSize.Height()); + mxLineEndSet->SetOutputSizePixel(aSize); +} + +SvxLineEndToolBoxControl::SvxLineEndToolBoxControl( const css::uno::Reference<css::uno::XComponentContext>& rContext ) + : svt::PopupWindowController( rContext, nullptr, OUString() ) +{ +} + +void SAL_CALL SvxLineEndToolBoxControl::execute(sal_Int16 /*KeyModifier*/) +{ + if (m_pToolbar) + { + // Toggle the popup also when toolbutton is activated + const OString aId(m_aCommandURL.toUtf8()); + m_pToolbar->set_menu_item_active(aId, !m_pToolbar->get_menu_item_active(aId)); + } + else + { + // Open the popup also when Enter key is pressed. + createPopupWindow(); + } +} + +void SvxLineEndToolBoxControl::initialize( const css::uno::Sequence<css::uno::Any>& rArguments ) +{ + svt::PopupWindowController::initialize( rArguments ); + + if (m_pToolbar) + { + mxPopoverContainer.reset(new ToolbarPopupContainer(m_pToolbar)); + m_pToolbar->set_item_popover(m_aCommandURL.toUtf8(), mxPopoverContainer->getTopLevel()); + } + + ToolBox* pToolBox = nullptr; + sal_uInt16 nId = 0; + if ( getToolboxId( nId, &pToolBox ) ) + pToolBox->SetItemBits( nId, pToolBox->GetItemBits( nId ) | ToolBoxItemBits::DROPDOWNONLY ); +} + +std::unique_ptr<WeldToolbarPopup> SvxLineEndToolBoxControl::weldPopupWindow() +{ + return std::make_unique<SvxLineEndWindow>(this, m_pToolbar); +} + +VclPtr<vcl::Window> SvxLineEndToolBoxControl::createVclPopupWindow( vcl::Window* pParent ) +{ + mxInterimPopover = VclPtr<InterimToolbarPopup>::Create(getFrameInterface(), pParent, + std::make_unique<SvxLineEndWindow>(this, pParent->GetFrameWeld())); + + mxInterimPopover->Show(); + + mxInterimPopover->SetText(SvxResId(RID_SVXSTR_LINEEND)); + + return mxInterimPopover; +} + +OUString SvxLineEndToolBoxControl::getImplementationName() +{ + return "com.sun.star.comp.svx.LineEndToolBoxControl"; +} + +css::uno::Sequence<OUString> SvxLineEndToolBoxControl::getSupportedServiceNames() +{ + return { "com.sun.star.frame.ToolbarController" }; +} + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * +com_sun_star_comp_svx_LineEndToolBoxControl_get_implementation( + css::uno::XComponentContext* rContext, + css::uno::Sequence<css::uno::Any> const & ) +{ + return cppu::acquire( new SvxLineEndToolBoxControl( rContext ) ); +} + +SvxLineBox::SvxLineBox(SvxLineStyleToolBoxControl* pControl, weld::Widget* pParent, int nInitialIndex) + : WeldToolbarPopup(pControl->getFrameInterface(), pParent, "svx/ui/floatinglinestyle.ui", "FloatingLineStyle") + , mxControl(pControl) + , mxLineStyleSet(new ValueSet(m_xBuilder->weld_scrolled_window("valuesetwin"))) + , mxLineStyleSetWin(new weld::CustomWeld(*m_xBuilder, "valueset", *mxLineStyleSet)) +{ + mxLineStyleSet->SetStyle(WB_FLATVALUESET | WB_ITEMBORDER | WB_3DLOOK | WB_NO_DIRECTSELECT); + + FillControl(); + + mxLineStyleSet->SelectItem(nInitialIndex + 1); + + mxLineStyleSet->SetSelectHdl( LINK( this, SvxLineBox, SelectHdl ) ); +} + +void SvxLineBox::GrabFocus() +{ + mxLineStyleSet->GrabFocus(); +} + +SvxLineBox::~SvxLineBox() +{ +} + +// Fills the listbox (provisional) with strings + +void SvxLineBox::Fill( const XDashListRef &pList ) +{ + mxLineStyleSet->Clear(); + + if( !pList.is() ) + return; + + // entry for 'none' + mxLineStyleSet->InsertItem(1, Image(), pList->GetStringForUiNoLine()); + + // entry for solid line + auto aBmp = pList->GetBitmapForUISolidLine(); + Size aBmpSize = aBmp.GetSizePixel(); + mxLineStyleSet->InsertItem(2, Image(aBmp), pList->GetStringForUiSolidLine()); + + // entries for dashed lines + long nCount = pList->Count(); + for( long i = 0; i < nCount; i++ ) + { + const XDashEntry* pEntry = pList->GetDash(i); + const BitmapEx aBitmap = pList->GetUiBitmap(i); + + mxLineStyleSet->InsertItem(i + 3, Image(aBitmap), pEntry->GetName()); + } + + sal_uInt16 nLines = std::min( static_cast<sal_uInt16>(nCount + 2), sal_uInt16(MAX_LINES) ); + mxLineStyleSet->SetLineCount(nLines); + + WinBits nBits = mxLineStyleSet->GetStyle(); + if ( nLines == mxLineStyleSet->GetItemCount() ) + nBits &= ~WB_VSCROLL; + else + nBits |= WB_VSCROLL; + mxLineStyleSet->SetStyle( nBits ); + + Size aSize(aBmpSize); + aSize.AdjustWidth(6); + aSize.AdjustHeight(6); + aSize = mxLineStyleSet->CalcWindowSizePixel(aSize); + mxLineStyleSet->GetDrawingArea()->set_size_request(aSize.Width(), aSize.Height()); + mxLineStyleSet->SetOutputSizePixel(aSize); +} + +IMPL_LINK_NOARG(SvxLineBox, SelectHdl, ValueSet*, void) +{ + drawing::LineStyle eXLS; + sal_Int32 nPos = mxLineStyleSet->GetSelectedItemId(); + --nPos; // ids start at 1, get the pos of the id + + switch ( nPos ) + { + case 0: + eXLS = drawing::LineStyle_NONE; + break; + + case 1: + eXLS = drawing::LineStyle_SOLID; + break; + + default: + { + eXLS = drawing::LineStyle_DASH; + + if ( nPos != -1 && + SfxObjectShell::Current() && + SfxObjectShell::Current()->GetItem( SID_DASH_LIST ) ) + { + // LineDashItem will only be sent if it also has a dash. + // Notify cares! + SvxDashListItem const * pItem = SfxObjectShell::Current()->GetItem( SID_DASH_LIST ); + const XDashEntry* pEntry = pItem->GetDashList()->GetDash(nPos - 2); + XLineDashItem aLineDashItem(pEntry->GetName(), pEntry->GetDash()); + + Any a; + Sequence< PropertyValue > aArgs( 1 ); + aArgs[0].Name = "LineDash"; + aLineDashItem.QueryValue ( a ); + aArgs[0].Value = a; + mxControl->dispatchLineStyleCommand(".uno:LineDash", aArgs); + } + } + break; + } + + XLineStyleItem aLineStyleItem( eXLS ); + Any a; + Sequence< PropertyValue > aArgs( 1 ); + aArgs[0].Name = "XLineStyle"; + aLineStyleItem.QueryValue ( a ); + aArgs[0].Value = a; + mxControl->dispatchLineStyleCommand(".uno:XLineStyle", aArgs); + + mxControl->EndPopupMode(); +} + +void SvxLineBox::FillControl() +{ + SfxObjectShell* pSh = SfxObjectShell::Current(); + if (pSh) + { + const SvxDashListItem* pItem = pSh->GetItem( SID_DASH_LIST ); + if (pItem) + Fill(pItem->GetDashList()); + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/tbxctrls/linemetricbox.hxx b/svx/source/tbxctrls/linemetricbox.hxx new file mode 100644 index 000000000..3596227b0 --- /dev/null +++ b/svx/source/tbxctrls/linemetricbox.hxx @@ -0,0 +1,58 @@ +/* -*- 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 . + */ +#pragma once + +#include <vcl/InterimItemWindow.hxx> +#include <svx/svxdllapi.h> + +class XLineWidthItem; + +class SvxMetricField final : public InterimItemWindow +{ +private: + std::unique_ptr<weld::MetricSpinButton> m_xWidget; + int nCurValue; + MapUnit eDestPoolUnit; + FieldUnit eDlgUnit; + css::uno::Reference< css::frame::XFrame > mxFrame; + + DECL_LINK(ModifyHdl, weld::MetricSpinButton&, void); + DECL_LINK(KeyInputHdl, const KeyEvent&, bool); + DECL_LINK(FocusInHdl, weld::Widget&, void); + + static void ReleaseFocus_Impl(); + + virtual void DataChanged( const DataChangedEvent& rDCEvt ) override; + + virtual void GetFocus() override; + +public: + SvxMetricField( vcl::Window* pParent, + const css::uno::Reference< css::frame::XFrame >& rFrame ); + virtual void dispose() override; + virtual ~SvxMetricField() override; + + void Update( const XLineWidthItem* pItem ); + void SetDestCoreUnit( MapUnit eUnit ); + void RefreshDlgUnit(); + + void set_sensitive(bool bSensitive); +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/tbxctrls/linewidthctrl.cxx b/svx/source/tbxctrls/linewidthctrl.cxx new file mode 100644 index 000000000..256793a7e --- /dev/null +++ b/svx/source/tbxctrls/linewidthctrl.cxx @@ -0,0 +1,101 @@ +/* -*- 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 <vcl/toolbox.hxx> +#include <sfx2/app.hxx> +#include <sfx2/objsh.hxx> +#include <svx/svxids.hrc> +#include <svx/xlnwtit.hxx> +#include <svx/linectrl.hxx> +#include <svx/itemwin.hxx> +#include "linemetricbox.hxx" + +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::util; +using namespace ::com::sun::star::frame; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star; + +SFX_IMPL_TOOLBOX_CONTROL( SvxLineWidthToolBoxControl, XLineWidthItem ); + +SvxLineWidthToolBoxControl::SvxLineWidthToolBoxControl( + sal_uInt16 nSlotId, sal_uInt16 nId, ToolBox& rTbx ) : + SfxToolBoxControl( nSlotId, nId, rTbx ) +{ + addStatusListener( ".uno:MetricUnit"); +} + + +SvxLineWidthToolBoxControl::~SvxLineWidthToolBoxControl() +{ +} + +void SvxLineWidthToolBoxControl::StateChanged( + sal_uInt16 nSID, SfxItemState eState, const SfxPoolItem* pState ) +{ + SvxMetricField* pFld = static_cast<SvxMetricField*>( + GetToolBox().GetItemWindow( GetId() )); + DBG_ASSERT( pFld, "Window not found" ); + + if ( nSID == SID_ATTR_METRIC ) + { + pFld->RefreshDlgUnit(); + } + else + { + if ( eState == SfxItemState::DISABLED ) + { + pFld->set_sensitive(false); + } + else + { + pFld->set_sensitive(true); + + if ( eState == SfxItemState::DEFAULT ) + { + DBG_ASSERT( dynamic_cast<const XLineWidthItem*>( pState) != nullptr, "wrong ItemType" ); + + pFld->SetDestCoreUnit(GetCoreMetric()); + + pFld->Update( static_cast<const XLineWidthItem*>(pState) ); + } + else + pFld->Update( nullptr ); + } + } +} + +MapUnit SvxLineWidthToolBoxControl::GetCoreMetric() +{ + SfxObjectShell* pSh = SfxObjectShell::Current(); + SfxItemPool& rPool = pSh ? pSh->GetPool() : SfxGetpApp()->GetPool(); + sal_uInt16 nWhich = rPool.GetWhich(SID_ATTR_LINE_WIDTH); + return rPool.GetMetric(nWhich); +} + +VclPtr<InterimItemWindow> SvxLineWidthToolBoxControl::CreateItemWindow(vcl::Window *pParent) +{ + VclPtr<SvxMetricField> pWindow = VclPtr<SvxMetricField>::Create(pParent, m_xFrame); + pWindow->Show(); + + return pWindow; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/tbxctrls/tbcontrl.cxx b/svx/source/tbxctrls/tbcontrl.cxx new file mode 100644 index 000000000..8780b03f2 --- /dev/null +++ b/svx/source/tbxctrls/tbcontrl.cxx @@ -0,0 +1,4039 @@ +/* -*- 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 <typeinfo> +#include <utility> + +#include <comphelper/configurationlistener.hxx> +#include <comphelper/propertysequence.hxx> +#include <tools/color.hxx> +#include <svl/poolitem.hxx> +#include <svl/itemset.hxx> +#include <vcl/commandinfoprovider.hxx> +#include <vcl/event.hxx> +#include <vcl/toolbox.hxx> +#include <vcl/customweld.hxx> +#include <vcl/vclptr.hxx> +#include <vcl/weldutils.hxx> +#include <svtools/valueset.hxx> +#include <svtools/ctrlbox.hxx> +#include <svl/style.hxx> +#include <svtools/ctrltool.hxx> +#include <svtools/borderhelper.hxx> +#include <vcl/InterimItemWindow.hxx> +#include <sfx2/tplpitem.hxx> +#include <sfx2/sfxstatuslistener.hxx> +#include <toolkit/helper/vclunohelper.hxx> +#include <sfx2/viewfrm.hxx> +#include <unotools/fontoptions.hxx> +#include <vcl/svapp.hxx> +#include <vcl/settings.hxx> +#include <vcl/virdev.hxx> +#include <com/sun/star/awt/FontDescriptor.hpp> +#include <com/sun/star/table/BorderLine2.hpp> +#include <com/sun/star/style/XStyleFamiliesSupplier.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/util/XNumberFormatsSupplier.hpp> +#include <com/sun/star/frame/XDispatchProvider.hpp> +#include <com/sun/star/frame/XFrame.hpp> +#include <svx/strings.hrc> +#include <svx/svxids.hrc> +#include <helpids.h> +#include <sfx2/sidebar/Sidebar.hxx> +#include <sfx2/sidebar/SidebarToolBox.hxx> +#include <svx/xtable.hxx> +#include <editeng/editids.hrc> +#include <editeng/fontitem.hxx> +#include <editeng/fhgtitem.hxx> +#include <editeng/boxitem.hxx> +#include <editeng/charreliefitem.hxx> +#include <editeng/contouritem.hxx> +#include <editeng/colritem.hxx> +#include <editeng/crossedoutitem.hxx> +#include <editeng/emphasismarkitem.hxx> +#include <editeng/flstitem.hxx> +#include <editeng/lineitem.hxx> +#include <editeng/postitem.hxx> +#include <editeng/shdditem.hxx> +#include <editeng/udlnitem.hxx> +#include <editeng/wghtitem.hxx> +#include <editeng/svxfont.hxx> +#include <editeng/cmapitem.hxx> +#include <svx/colorwindow.hxx> +#include <svx/colorbox.hxx> +#include <svx/tbcontrl.hxx> +#include <svx/dialmgr.hxx> +#include <svx/PaletteManager.hxx> +#include <memory> + +#include <svx/tbxcolorupdate.hxx> +#include <editeng/eerdll.hxx> +#include <editeng/editrids.hrc> +#include <svx/xdef.hxx> +#include <svx/xfillit0.hxx> +#include <svx/xflclit.hxx> +#include <svl/currencytable.hxx> +#include <svtools/langtab.hxx> +#include <cppu/unotype.hxx> +#include <cppuhelper/supportsservice.hxx> +#include <officecfg/Office/Common.hxx> +#include <o3tl/safeint.hxx> +#include <o3tl/typed_flags_set.hxx> +#include <bitmaps.hlst> +#include <sal/log.hxx> +#include <unotools/collatorwrapper.hxx> +#include <boost/property_tree/ptree.hpp> + +#include <comphelper/lok.hxx> + +#define MAX_MRU_FONTNAME_ENTRIES 5 + +#define COMBO_WIDTH_IN_CHARS 18 + +// namespaces +using namespace ::editeng; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::frame; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::lang; + +namespace +{ +class SvxStyleBox_Base +{ +public: + SvxStyleBox_Base(std::unique_ptr<weld::ComboBox> xWidget, const OUString& rCommand, SfxStyleFamily eFamily, + const Reference<XDispatchProvider>& rDispatchProvider, + const Reference<XFrame>& _xFrame,const OUString& rClearFormatKey, + const OUString& rMoreKey, bool bInSpecialMode, SvxStyleToolBoxControl& rCtrl); + + virtual ~SvxStyleBox_Base() + { + } + + void SetFamily( SfxStyleFamily eNewFamily ); + + void SetDefaultStyle( const OUString& rDefault ) { sDefaultStyle = rDefault; } + + int get_count() const { return m_xWidget->get_count(); } + OUString get_text(int nIndex) const { return m_xWidget->get_text(nIndex); } + OUString get_active_text() const { return m_xWidget->get_active_text(); } + + void append_text(const OUString& rStr) + { + OUString sId(OUString::number(m_xWidget->get_count())); + m_xWidget->append(sId, rStr); + } + + void insert_separator(int pos, const OUString& rId) + { + m_xWidget->insert_separator(pos, rId); + } + + virtual void set_sensitive(bool bSensitive) + { + m_xWidget->set_sensitive(bSensitive); + } + + void set_active_or_entry_text(const OUString& rText) + { + const int nFound = m_xWidget->find_text(rText); + if (nFound != -1) + m_xWidget->set_active(nFound); + else + m_xWidget->set_entry_text(rText); + } + + void set_active(int nActive) + { + m_xWidget->set_active(nActive); + } + + void freeze() + { + m_xWidget->freeze(); + } + + void save_value() + { + m_xWidget->save_value(); + } + + void clear() + { + m_xWidget->clear(); + m_nMaxUserDrawFontWidth = 0; + } + + void thaw() + { + m_xWidget->thaw(); + } + + virtual bool DoKeyInput(const KeyEvent& rKEvt); + +private: + DECL_LINK(SelectHdl, weld::ComboBox&, void); + DECL_LINK(KeyInputHdl, const KeyEvent&, bool); + DECL_LINK(ActivateHdl, weld::ComboBox&, bool); + DECL_LINK(FocusOutHdl, weld::Widget&, void); + DECL_LINK(DumpAsPropertyTreeHdl, boost::property_tree::ptree&, void); + DECL_LINK(CustomRenderHdl, weld::ComboBox::render_args, void); + DECL_LINK(CustomGetSizeHdl, OutputDevice&, Size); + + /// Calculate the optimal width of the dropdown. Very expensive operation, triggers lots of font measurement. + void CalcOptimalExtraUserWidth(vcl::RenderContext& rRenderContext); + + void Select(bool bNonTravelSelect); + +protected: + SvxStyleToolBoxControl& m_rCtrl; + + std::unique_ptr<weld::Builder> m_xMenuBuilder; + std::unique_ptr<weld::Menu> m_xMenu; + std::unique_ptr<weld::ComboBox> m_xWidget; + + SfxStyleFamily eStyleFamily; + int m_nMaxUserDrawFontWidth; + bool bRelease; + Reference< XDispatchProvider > m_xDispatchProvider; + Reference< XFrame > m_xFrame; + OUString m_aCommand; + OUString aClearFormatKey; + OUString aMoreKey; + OUString sDefaultStyle; + bool bInSpecialMode; + + void ReleaseFocus(); + static Color TestColorsVisible(const Color &FontCol, const Color &BackCol); + static void UserDrawEntry(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect, const OUString &rStyleName); + void SetupEntry(vcl::RenderContext& rRenderContext, sal_Int32 nItem, const tools::Rectangle& rRect, const OUString& rStyleName, bool bIsNotSelected); + static bool AdjustFontForItemHeight(OutputDevice& rDevice, tools::Rectangle const & rTextRect, long nHeight); + DECL_LINK(MenuSelectHdl, const OString&, void); + DECL_STATIC_LINK(SvxStyleBox_Base, ShowMoreHdl, void*, void); +}; + +class SvxStyleBox_Impl final : public InterimItemWindow + , public SvxStyleBox_Base +{ +public: + SvxStyleBox_Impl(vcl::Window* pParent, const OUString& rCommand, SfxStyleFamily eFamily, const Reference< XDispatchProvider >& rDispatchProvider, + const Reference< XFrame >& _xFrame,const OUString& rClearFormatKey, const OUString& rMoreKey, bool bInSpecialMode, SvxStyleToolBoxControl& rCtrl); + + virtual ~SvxStyleBox_Impl() override + { + disposeOnce(); + } + + virtual void dispose() override + { + m_xWidget.reset(); + m_xMenu.reset(); + m_xMenuBuilder.reset(); + InterimItemWindow::dispose(); + } + + virtual bool DoKeyInput(const KeyEvent& rKEvt) override; + +private: + + virtual void set_sensitive(bool bSensitive) override + { + m_xWidget->set_sensitive(bSensitive); + if (bSensitive) + InterimItemWindow::Enable(); + else + InterimItemWindow::Disable(); + } + + virtual void DataChanged(const DataChangedEvent& rDCEvt) override; + virtual void GetFocus() override + { + if (m_xWidget) + m_xWidget->grab_focus(); + InterimItemWindow::GetFocus(); + } + void SetOptimalSize(); +}; + +class SvxFontNameBox_Impl; +class SvxFontNameBox_Base; + +class SvxFontNameToolBoxControl final : public cppu::ImplInheritanceHelper<svt::ToolboxController, + css::lang::XServiceInfo> +{ +public: + SvxFontNameToolBoxControl(); + + // XStatusListener + virtual void SAL_CALL statusChanged( const css::frame::FeatureStateEvent& rEvent ) override; + + // XToolbarController + virtual css::uno::Reference<css::awt::XWindow> SAL_CALL createItemWindow(const css::uno::Reference<css::awt::XWindow>& rParent) override; + + // XComponent + virtual void SAL_CALL dispose() override; + + // XServiceInfo + virtual OUString SAL_CALL getImplementationName() override; + virtual sal_Bool SAL_CALL supportsService( const OUString& rServiceName ) override; + virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override; + +private: + VclPtr<SvxFontNameBox_Impl> m_xVclBox; + std::unique_ptr<SvxFontNameBox_Base> m_xWeldBox; + SvxFontNameBox_Base* m_pBox; +}; + +class FontOptionsListener final : public comphelper::ConfigurationListenerProperty<bool> +{ +private: + SvxFontNameBox_Base& m_rBox; + + virtual void setProperty(const css::uno::Any &rProperty) override; +public: + FontOptionsListener(const rtl::Reference<comphelper::ConfigurationListener>& rListener, const OUString& rProp, SvxFontNameBox_Base& rBox) + : comphelper::ConfigurationListenerProperty<bool>(rListener, rProp) + , m_rBox(rBox) + { + } +}; + +class SvxFontNameBox_Base +{ +private: + rtl::Reference<comphelper::ConfigurationListener> m_xListener; + FontOptionsListener m_aWYSIWYG; + FontOptionsListener m_aHistory; + +protected: + SvxFontNameToolBoxControl& m_rCtrl; + + std::unique_ptr<FontNameBox> m_xWidget; + const FontList* pFontList; + ::std::unique_ptr<FontList> m_aOwnFontList; + vcl::Font aCurFont; + sal_uInt16 nFtCount; + bool bRelease; + Reference< XDispatchProvider > m_xDispatchProvider; + Reference< XFrame > m_xFrame; + bool mbCheckingUnknownFont; + + void ReleaseFocus_Impl(); + + void Select(bool bNonTravelSelect); + + void EndPreview() + { + Sequence< PropertyValue > aArgs; + SfxToolBoxControl::Dispatch( m_xDispatchProvider, + ".uno:CharEndPreviewFontName", + aArgs ); + } + void CheckAndMarkUnknownFont(); + +public: + SvxFontNameBox_Base(std::unique_ptr<weld::ComboBox> xWidget, const Reference<XDispatchProvider>& rDispatchProvider, + const Reference<XFrame>& rFrame, SvxFontNameToolBoxControl& rCtrl); + virtual ~SvxFontNameBox_Base() + { + m_xListener->dispose(); + } + + void FillList(); + void Update( const css::awt::FontDescriptor* pFontDesc ); + sal_uInt16 GetListCount() const { return nFtCount; } + void Clear() { m_xWidget->clear(); nFtCount = 0; } + void Fill( const FontList* pList ) + { + m_xWidget->Fill(pList); + nFtCount = pList->GetFontNameCount(); + } + + void SetOwnFontList(::std::unique_ptr<FontList> && _aOwnFontList) { m_aOwnFontList = std::move(_aOwnFontList); } + + virtual void set_sensitive(bool bSensitive) + { + m_xWidget->set_sensitive(bSensitive); + } + + void set_active_or_entry_text(const OUString& rText); + + void statusChanged_Impl(const css::frame::FeatureStateEvent& rEvent); + + virtual bool DoKeyInput(const KeyEvent& rKEvt); + + void EnableControls(); + + DECL_LINK(SelectHdl, weld::ComboBox&, void); + DECL_LINK(KeyInputHdl, const KeyEvent&, bool); + DECL_LINK(ActivateHdl, weld::ComboBox&, bool); + DECL_LINK(FocusInHdl, weld::Widget&, void); + DECL_LINK(FocusOutHdl, weld::Widget&, void); + DECL_LINK(DumpAsPropertyTreeHdl, boost::property_tree::ptree&, void); +}; + +void FontOptionsListener::setProperty(const css::uno::Any &rProperty) +{ + comphelper::ConfigurationListenerProperty<bool>::setProperty(rProperty); + m_rBox.EnableControls(); +} + +class SvxFontNameBox_Impl final : public InterimItemWindow + , public SvxFontNameBox_Base +{ +private: + virtual void DataChanged( const DataChangedEvent& rDCEvt ) override; + virtual void GetFocus() override + { + if (m_xWidget) + m_xWidget->grab_focus(); + InterimItemWindow::GetFocus(); + } + + void SetOptimalSize(); + + virtual bool DoKeyInput(const KeyEvent& rKEvt) override; + +public: + SvxFontNameBox_Impl(vcl::Window* pParent, const Reference<XDispatchProvider>& rDispatchProvider, + const Reference<XFrame>& rFrame, SvxFontNameToolBoxControl& rCtrl); + + virtual void dispose() override + { + m_xWidget.reset(); + InterimItemWindow::dispose(); + } + + virtual ~SvxFontNameBox_Impl() override + { + disposeOnce(); + } + + virtual Reference< css::accessibility::XAccessible > CreateAccessible() override; + + virtual void set_sensitive(bool bSensitive) override + { + m_xWidget->set_sensitive(bSensitive); + if (bSensitive) + InterimItemWindow::Enable(); + else + InterimItemWindow::Disable(); + } +}; + + +// SelectHdl needs the Modifiers, get them in MouseButtonUp +class SvxFrmValueSet_Impl final : public ValueSet +{ +private: + sal_uInt16 nModifier; + + virtual bool MouseButtonUp(const MouseEvent& rMEvt) override + { + nModifier = rMEvt.GetModifier(); + return ValueSet::MouseButtonUp(rMEvt); + } + +public: + SvxFrmValueSet_Impl() + : ValueSet(nullptr) + , nModifier(0) + { + } + sal_uInt16 GetModifier() const {return nModifier;} +}; + +} + +namespace { + +class SvxFrameToolBoxControl; + +class SvxFrameWindow_Impl final : public WeldToolbarPopup +{ +private: + rtl::Reference<SvxFrameToolBoxControl> mxControl; + std::unique_ptr<SvxFrmValueSet_Impl> mxFrameSet; + std::unique_ptr<weld::CustomWeld> mxFrameSetWin; + std::vector<BitmapEx> aImgVec; + bool bParagraphMode; + + void InitImageList(); + void CalcSizeValueSet(); + DECL_LINK( SelectHdl, ValueSet*, void ); + +public: + SvxFrameWindow_Impl(SvxFrameToolBoxControl* pControl, weld::Widget* pParent); + virtual void GrabFocus() override + { + mxFrameSet->GrabFocus(); + } + + virtual void statusChanged( const css::frame::FeatureStateEvent& rEvent ) override; +}; + +class SvxFrameToolBoxControl : public svt::PopupWindowController +{ +public: + explicit SvxFrameToolBoxControl( const css::uno::Reference< css::uno::XComponentContext >& rContext ); + + // XInitialization + virtual void SAL_CALL initialize( const css::uno::Sequence< css::uno::Any >& rArguments ) override; + + // XServiceInfo + virtual OUString SAL_CALL getImplementationName() override; + virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override; + + virtual void SAL_CALL execute(sal_Int16 nKeyModifier) override; +private: + virtual std::unique_ptr<WeldToolbarPopup> weldPopupWindow() override; + virtual VclPtr<vcl::Window> createVclPopupWindow( vcl::Window* pParent ) override; +}; + + class LineListBox final : public ValueSet + { + public: + typedef Color (*ColorFunc)(Color); + typedef Color (*ColorDistFunc)(Color, Color); + + LineListBox(); + + /** Set the width in Twips */ + Size SetWidth( long nWidth ) + { + long nOldWidth = m_nWidth; + m_nWidth = nWidth; + return UpdateEntries( nOldWidth ); + } + + void SetNone( const OUString& sNone ) + { + m_sNone = sNone; + } + + /** Insert a listbox entry with all widths in Twips. */ + void InsertEntry(const BorderWidthImpl& rWidthImpl, + SvxBorderLineStyle nStyle, long nMinWidth = 0, + ColorFunc pColor1Fn = &sameColor, + ColorFunc pColor2Fn = &sameColor, + ColorDistFunc pColorDistFn = &sameDistColor); + + SvxBorderLineStyle GetEntryStyle( sal_Int32 nPos ) const; + + SvxBorderLineStyle GetSelectEntryStyle() const; + + void SetSourceUnit( FieldUnit eNewUnit ) { eSourceUnit = eNewUnit; } + + const Color& GetColor() const { return aColor; } + + virtual void SetDrawingArea(weld::DrawingArea* pDrawingArea) override; + private: + + void ImpGetLine(long nLine1, long nLine2, long nDistance, + Color nColor1, Color nColor2, Color nColorDist, + SvxBorderLineStyle nStyle, BitmapEx& rBmp); + + void UpdatePaintLineColor(); // returns sal_True if maPaintCol has changed + + Size UpdateEntries( long nOldWidth ); + sal_Int32 GetStylePos( sal_Int32 nListPos, long nWidth ); + + const Color& GetPaintColor() const + { + return maPaintCol; + } + + Color GetColorLine1( sal_Int32 nPos ); + Color GetColorLine2( sal_Int32 nPos ); + Color GetColorDist( sal_Int32 nPos ); + + LineListBox( const LineListBox& ) = delete; + LineListBox& operator =( const LineListBox& ) = delete; + + std::vector<std::unique_ptr<ImpLineListData>> m_vLineList; + long m_nWidth; + OUString m_sNone; + ScopedVclPtr<VirtualDevice> aVirDev; + Size aTxtSize; + Color const aColor; + Color maPaintCol; + FieldUnit eSourceUnit; + }; + + SvxBorderLineStyle LineListBox::GetSelectEntryStyle() const + { + SvxBorderLineStyle nStyle = SvxBorderLineStyle::SOLID; + size_t nPos = GetSelectItemPos(); + if (nPos != VALUESET_ITEM_NOTFOUND) + { + if (!m_sNone.isEmpty()) + --nPos; + nStyle = GetEntryStyle( nPos ); + } + + return nStyle; + } + + void LineListBox::ImpGetLine( long nLine1, long nLine2, long nDistance, + Color aColor1, Color aColor2, Color aColorDist, + SvxBorderLineStyle nStyle, BitmapEx& rBmp ) + { + auto nMinWidth = GetDrawingArea()->get_ref_device().approximate_digit_width() * COMBO_WIDTH_IN_CHARS; + Size aSize(nMinWidth, aTxtSize.Height()); + aSize.AdjustWidth( -(aTxtSize.Width()) ); + aSize.AdjustWidth( -6 ); + + // SourceUnit to Twips + if ( eSourceUnit == FieldUnit::POINT ) + { + nLine1 /= 5; + nLine2 /= 5; + nDistance /= 5; + } + + // Paint the lines + aSize = aVirDev->PixelToLogic( aSize ); + long nPix = aVirDev->PixelToLogic( Size( 0, 1 ) ).Height(); + sal_uInt32 n1 = nLine1; + sal_uInt32 n2 = nLine2; + long nDist = nDistance; + n1 += nPix-1; + n1 -= n1%nPix; + if ( n2 ) + { + nDist += nPix-1; + nDist -= nDist%nPix; + n2 += nPix-1; + n2 -= n2%nPix; + } + long nVirHeight = n1+nDist+n2; + if ( nVirHeight > aSize.Height() ) + aSize.setHeight( nVirHeight ); + // negative width should not be drawn + if ( aSize.Width() <= 0 ) + return; + + Size aVirSize = aVirDev->LogicToPixel( aSize ); + if ( aVirDev->GetOutputSizePixel() != aVirSize ) + aVirDev->SetOutputSizePixel( aVirSize ); + aVirDev->SetFillColor( aColorDist ); + aVirDev->DrawRect( tools::Rectangle( Point(), aSize ) ); + + aVirDev->SetFillColor( aColor1 ); + + double y1 = double( n1 ) / 2; + svtools::DrawLine( *aVirDev, basegfx::B2DPoint( 0, y1 ), basegfx::B2DPoint( aSize.Width( ), y1 ), n1, nStyle ); + + if ( n2 ) + { + double y2 = n1 + nDist + double( n2 ) / 2; + aVirDev->SetFillColor( aColor2 ); + svtools::DrawLine( *aVirDev, basegfx::B2DPoint( 0, y2 ), basegfx::B2DPoint( aSize.Width(), y2 ), n2, SvxBorderLineStyle::SOLID ); + } + rBmp = aVirDev->GetBitmapEx( Point(), Size( aSize.Width(), n1+nDist+n2 ) ); + } + + LineListBox::LineListBox() + : ValueSet(nullptr) + , m_nWidth( 5 ) + , m_sNone() + , aVirDev(VclPtr<VirtualDevice>::Create()) + , aColor(COL_BLACK) + , maPaintCol(COL_BLACK) + , eSourceUnit(FieldUnit::POINT) + { + aVirDev->SetLineColor(); + aVirDev->SetMapMode( MapMode( MapUnit::MapTwip ) ); + } + + void LineListBox::SetDrawingArea(weld::DrawingArea* pDrawingArea) + { + ValueSet::SetDrawingArea(pDrawingArea); + + OutputDevice& rDevice = pDrawingArea->get_ref_device(); + + aTxtSize.setWidth( rDevice.approximate_digit_width() ); + aTxtSize.setHeight( rDevice.GetTextHeight() ); + + UpdatePaintLineColor(); + } + + sal_Int32 LineListBox::GetStylePos( sal_Int32 nListPos, long nWidth ) + { + sal_Int32 nPos = -1; + if (!m_sNone.isEmpty()) + nListPos--; + + sal_Int32 n = 0; + size_t i = 0; + size_t nCount = m_vLineList.size(); + while ( nPos == -1 && i < nCount ) + { + auto& pData = m_vLineList[ i ]; + if ( pData->GetMinWidth() <= nWidth ) + { + if ( nListPos == n ) + nPos = static_cast<sal_Int32>(i); + n++; + } + i++; + } + + return nPos; + } + + void LineListBox::InsertEntry( + const BorderWidthImpl& rWidthImpl, SvxBorderLineStyle nStyle, long nMinWidth, + ColorFunc pColor1Fn, ColorFunc pColor2Fn, ColorDistFunc pColorDistFn ) + { + m_vLineList.emplace_back(new ImpLineListData( + rWidthImpl, nStyle, nMinWidth, pColor1Fn, pColor2Fn, pColorDistFn)); + } + + SvxBorderLineStyle LineListBox::GetEntryStyle( sal_Int32 nPos ) const + { + ImpLineListData* pData = (0 <= nPos && o3tl::make_unsigned(nPos) < m_vLineList.size()) ? m_vLineList[ nPos ].get() : nullptr; + return pData ? pData->GetStyle() : SvxBorderLineStyle::NONE; + } + + void LineListBox::UpdatePaintLineColor() + { + const StyleSettings& rSettings = Application::GetSettings().GetStyleSettings(); + Color aNewCol( rSettings.GetWindowColor().IsDark()? rSettings.GetLabelTextColor() : aColor ); + + bool bRet = aNewCol != maPaintCol; + + if( bRet ) + maPaintCol = aNewCol; + } + + Size LineListBox::UpdateEntries( long nOldWidth ) + { + Size aSize; + + UpdatePaintLineColor( ); + + sal_Int32 nSelEntry = GetSelectItemPos(); + sal_Int32 nTypePos = GetStylePos( nSelEntry, nOldWidth ); + + // Remove the old entries + Clear(); + + sal_uInt16 nId(1); + + // Add the new entries based on the defined width + if (!m_sNone.isEmpty()) + InsertItem(nId++, Image(), m_sNone); + + sal_uInt16 n = 0; + sal_uInt16 nCount = m_vLineList.size( ); + while ( n < nCount ) + { + auto& pData = m_vLineList[ n ]; + if ( pData->GetMinWidth() <= m_nWidth ) + { + BitmapEx aBmp; + ImpGetLine( pData->GetLine1ForWidth( m_nWidth ), + pData->GetLine2ForWidth( m_nWidth ), + pData->GetDistForWidth( m_nWidth ), + GetColorLine1( GetItemCount( ) ), + GetColorLine2( GetItemCount( ) ), + GetColorDist( GetItemCount( ) ), + pData->GetStyle(), aBmp ); + InsertItem(nId, Image(aBmp)); + Size aBmpSize = aBmp.GetSizePixel(); + if (aBmpSize.Width() > aSize.Width()) + aSize.setWidth(aBmpSize.getWidth()); + if (aBmpSize.Height() > aSize.Height()) + aSize.setHeight(aBmpSize.getHeight()); + if ( n == nTypePos ) + SelectItem(nId); + } + else if ( n == nTypePos ) + SetNoSelection(); + n++; + ++nId; + } + + Invalidate(); + + return aSize; + } + + Color LineListBox::GetColorLine1( sal_Int32 nPos ) + { + sal_Int32 nStyle = GetStylePos( nPos, m_nWidth ); + if (nStyle == -1) + return GetPaintColor( ); + auto& pData = m_vLineList[ nStyle ]; + return pData->GetColorLine1( GetColor( ) ); + } + + Color LineListBox::GetColorLine2( sal_Int32 nPos ) + { + sal_Int32 nStyle = GetStylePos( nPos, m_nWidth ); + if (nStyle == -1) + return GetPaintColor( ); + auto& pData = m_vLineList[ nStyle ]; + return pData->GetColorLine2( GetColor( ) ); + } + + Color LineListBox::GetColorDist( sal_Int32 nPos ) + { + Color rResult = Application::GetSettings().GetStyleSettings().GetFieldColor(); + + sal_Int32 nStyle = GetStylePos( nPos, m_nWidth ); + if (nStyle == -1) + return rResult; + auto& pData = m_vLineList[ nStyle ]; + return pData->GetColorDist( GetColor( ), rResult ); + } +} + +namespace { + +class SvxLineWindow_Impl final : public WeldToolbarPopup +{ +private: + rtl::Reference<SvxFrameToolBoxControl> m_xControl; + std::unique_ptr<LineListBox> m_xLineStyleLb; + std::unique_ptr<weld::CustomWeld> m_xLineStyleLbWin; + bool m_bIsWriter; + + DECL_LINK( SelectHdl, ValueSet*, void ); + +public: + SvxLineWindow_Impl(SvxFrameToolBoxControl* pControl, weld::Widget* pParent); + virtual void GrabFocus() override + { + m_xLineStyleLb->GrabFocus(); + } +}; + +} + +class SvxStyleToolBoxControl; + +class SfxStyleControllerItem_Impl : public SfxStatusListener +{ + public: + SfxStyleControllerItem_Impl( const Reference< XDispatchProvider >& rDispatchProvider, + sal_uInt16 nSlotId, + const OUString& rCommand, + SvxStyleToolBoxControl& rTbxCtl ); + + protected: + virtual void StateChanged( SfxItemState eState, const SfxPoolItem* pState ) override; + + private: + SvxStyleToolBoxControl& rControl; +}; + +#define BUTTON_PADDING 10 +#define ITEM_HEIGHT 30 + +SvxStyleBox_Base::SvxStyleBox_Base(std::unique_ptr<weld::ComboBox> xWidget, + const OUString& rCommand, + SfxStyleFamily eFamily, + const Reference< XDispatchProvider >& rDispatchProvider, + const Reference< XFrame >& _xFrame, + const OUString& rClearFormatKey, + const OUString& rMoreKey, + bool bInSpec, SvxStyleToolBoxControl& rCtrl) + : m_rCtrl(rCtrl) + , m_xMenuBuilder(Application::CreateBuilder(nullptr, "svx/ui/stylemenu.ui")) + , m_xMenu(m_xMenuBuilder->weld_menu("menu")) + , m_xWidget(std::move(xWidget)) + , eStyleFamily( eFamily ) + , m_nMaxUserDrawFontWidth(0) + , bRelease( true ) + , m_xDispatchProvider( rDispatchProvider ) + , m_xFrame(_xFrame) + , m_aCommand( rCommand ) + , aClearFormatKey( rClearFormatKey ) + , aMoreKey( rMoreKey ) + , bInSpecialMode( bInSpec ) +{ + m_xWidget->connect_changed(LINK(this, SvxStyleBox_Base, SelectHdl)); + m_xWidget->connect_key_press(LINK(this, SvxStyleBox_Base, KeyInputHdl)); + m_xWidget->connect_entry_activate(LINK(this, SvxStyleBox_Base, ActivateHdl)); + m_xWidget->connect_focus_out(LINK(this, SvxStyleBox_Base, FocusOutHdl)); + m_xWidget->connect_get_property_tree(LINK(this, SvxStyleBox_Base, DumpAsPropertyTreeHdl)); + m_xWidget->set_help_id(HID_STYLE_LISTBOX); + m_xWidget->set_entry_completion(true); + m_xMenu->connect_activate(LINK(this, SvxStyleBox_Base, MenuSelectHdl)); + + m_xWidget->connect_custom_get_size(LINK(this, SvxStyleBox_Base, CustomGetSizeHdl)); + m_xWidget->connect_custom_render(LINK(this, SvxStyleBox_Base, CustomRenderHdl)); + m_xWidget->set_custom_renderer(true); + + m_xWidget->set_entry_width_chars(COMBO_WIDTH_IN_CHARS); +} + +IMPL_LINK(SvxStyleBox_Base, CustomGetSizeHdl, OutputDevice&, rArg, Size) +{ + CalcOptimalExtraUserWidth(rArg); + return Size(m_nMaxUserDrawFontWidth, ITEM_HEIGHT); +} + +SvxStyleBox_Impl::SvxStyleBox_Impl(vcl::Window* pParent, + const OUString& rCommand, + SfxStyleFamily eFamily, + const Reference< XDispatchProvider >& rDispatchProvider, + const Reference< XFrame >& _xFrame, + const OUString& rClearFormatKey, + const OUString& rMoreKey, + bool bInSpec, SvxStyleToolBoxControl& rCtrl) + : InterimItemWindow(pParent, "svx/ui/applystylebox.ui", "ApplyStyleBox") + , SvxStyleBox_Base(m_xBuilder->weld_combo_box("applystyle"), rCommand, eFamily, + rDispatchProvider, _xFrame, rClearFormatKey, rMoreKey, bInSpec, rCtrl) +{ + set_id("applystyle"); + SetOptimalSize(); +} + +void SvxStyleBox_Base::ReleaseFocus() +{ + if ( !bRelease ) + { + bRelease = true; + return; + } + if ( m_xFrame.is() && m_xFrame->getContainerWindow().is() ) + m_xFrame->getContainerWindow()->setFocus(); +} + +IMPL_LINK(SvxStyleBox_Base, MenuSelectHdl, const OString&, rMenuIdent, void) +{ + OUString sEntry = m_xWidget->get_active_text(); + + ReleaseFocus(); // It must be after getting entry pos! + Sequence<PropertyValue> aArgs(2); + aArgs[0].Name = "Param"; + aArgs[0].Value <<= sEntry; + aArgs[1].Name = "Family"; + aArgs[1].Value <<= sal_Int16( eStyleFamily ); + + if (rMenuIdent == "update") + { + SfxToolBoxControl::Dispatch( m_xDispatchProvider, + ".uno:StyleUpdateByExample", aArgs ); + } + else if (rMenuIdent == "edit") + { + SfxToolBoxControl::Dispatch( m_xDispatchProvider, + ".uno:EditStyle", aArgs ); + } +} + +IMPL_STATIC_LINK_NOARG(SvxStyleBox_Base, ShowMoreHdl, void*, void) +{ + SfxViewFrame* pViewFrm = SfxViewFrame::Current(); + DBG_ASSERT( pViewFrm, "SvxStyleBox_Base::Select(): no viewframe" ); + if (!pViewFrm) + return; + pViewFrm->ShowChildWindow(SID_SIDEBAR); + ::sfx2::sidebar::Sidebar::ShowPanel("StyleListPanel", pViewFrm->GetFrame().GetFrameInterface(), true); +} + +IMPL_LINK(SvxStyleBox_Base, SelectHdl, weld::ComboBox&, rCombo, void) +{ + Select(rCombo.changed_by_direct_pick()); // only when picked from the list +} + +IMPL_LINK_NOARG(SvxStyleBox_Base, ActivateHdl, weld::ComboBox&, bool) +{ + Select(true); + return true; +} + +void SvxStyleBox_Base::Select(bool bNonTravelSelect) +{ + if (!bNonTravelSelect) + return; + + OUString aSearchEntry(m_xWidget->get_active_text()); + bool bDoIt = true, bClear = false; + if( bInSpecialMode ) + { + if( aSearchEntry == aClearFormatKey && m_xWidget->get_active() == 0 ) + { + aSearchEntry = sDefaultStyle; + bClear = true; + //not only apply default style but also call 'ClearFormatting' + Sequence< PropertyValue > aEmptyVals; + SfxToolBoxControl::Dispatch( m_xDispatchProvider, ".uno:ResetAttributes", + aEmptyVals); + } + else if (aSearchEntry == aMoreKey && m_xWidget->get_active() == (m_xWidget->get_count() - 1)) + { + Application::PostUserEvent(LINK(nullptr, SvxStyleBox_Base, ShowMoreHdl)); + //tdf#113214 change text back to previous entry + set_active_or_entry_text(m_xWidget->get_saved_value()); + bDoIt = false; + } + } + + //Do we need to create a new style? + SfxObjectShell *pShell = SfxObjectShell::Current(); + SfxStyleSheetBasePool* pPool = pShell->GetStyleSheetPool(); + SfxStyleSheetBase* pStyle = nullptr; + + bool bCreateNew = false; + + if ( pPool ) + { + pStyle = pPool->First(eStyleFamily); + while ( pStyle && pStyle->GetName() != aSearchEntry ) + pStyle = pPool->Next(); + } + + if ( !pStyle ) + { + // cannot find the style for whatever reason + // therefore create a new style + bCreateNew = true; + } + + /* #i33380# DR 2004-09-03 Moved the following line above the Dispatch() call. + This instance may be deleted in the meantime (i.e. when a dialog is opened + while in Dispatch()), accessing members will crash in this case. */ + ReleaseFocus(); + + if( bDoIt ) + { + if ( bClear ) + set_active_or_entry_text(aSearchEntry); + m_xWidget->save_value(); + + Sequence< PropertyValue > aArgs( 2 ); + aArgs[0].Value <<= aSearchEntry; + aArgs[1].Name = "Family"; + aArgs[1].Value <<= sal_Int16( eStyleFamily ); + if( bCreateNew ) + { + aArgs[0].Name = "Param"; + SfxToolBoxControl::Dispatch( m_xDispatchProvider, ".uno:StyleNewByExample", aArgs); + } + else + { + aArgs[0].Name = "Template"; + SfxToolBoxControl::Dispatch( m_xDispatchProvider, m_aCommand, aArgs ); + } + } +} + +void SvxStyleBox_Base::SetFamily( SfxStyleFamily eNewFamily ) +{ + eStyleFamily = eNewFamily; +} + +IMPL_LINK_NOARG(SvxStyleBox_Base, FocusOutHdl, weld::Widget&, void) +{ + if (!m_xWidget->has_focus()) // a combobox can be comprised of different subwidget so double-check if none of those has focus + set_active_or_entry_text(m_xWidget->get_saved_value()); +} + +IMPL_LINK(SvxStyleBox_Base, KeyInputHdl, const KeyEvent&, rKEvt, bool) +{ + return DoKeyInput(rKEvt); +} + +bool SvxStyleBox_Base::DoKeyInput(const KeyEvent& rKEvt) +{ + bool bHandled = false; + + sal_uInt16 nCode = rKEvt.GetKeyCode().GetCode(); + + switch (nCode) + { + case KEY_TAB: + bRelease = false; + Select(true); + break; + case KEY_ESCAPE: + set_active_or_entry_text(m_xWidget->get_saved_value()); + if (!m_rCtrl.IsInSidebar()) + { + ReleaseFocus(); + bHandled = true; + } + break; + } + + return bHandled; +} + +bool SvxStyleBox_Impl::DoKeyInput(const KeyEvent& rKEvt) +{ + return SvxStyleBox_Base::DoKeyInput(rKEvt) || ChildKeyInput(rKEvt); +} + +void SvxStyleBox_Impl::DataChanged( const DataChangedEvent& rDCEvt ) +{ + if ( (rDCEvt.GetType() == DataChangedEventType::SETTINGS) && + (rDCEvt.GetFlags() & AllSettingsFlags::STYLE) ) + { + SetOptimalSize(); + } + + InterimItemWindow::DataChanged( rDCEvt ); +} + +bool SvxStyleBox_Base::AdjustFontForItemHeight(OutputDevice& rDevice, tools::Rectangle const & rTextRect, long nHeight) +{ + if (rTextRect.Bottom() > nHeight) + { + // the text does not fit, adjust the font size + double ratio = static_cast< double >( nHeight ) / rTextRect.Bottom(); + vcl::Font aFont(rDevice.GetFont()); + Size aPixelSize(aFont.GetFontSize()); + aPixelSize.setWidth( aPixelSize.Width() * ratio ); + aPixelSize.setHeight( aPixelSize.Height() * ratio ); + aFont.SetFontSize(aPixelSize); + rDevice.SetFont(aFont); + return true; + } + return false; +} + +void SvxStyleBox_Impl::SetOptimalSize() +{ + // set width in chars low so the size request will not be overridden + m_xWidget->set_entry_width_chars(1); + // tdf#132338 purely using this calculation to keep things their traditional width + Size aSize(LogicToPixel(Size(COMBO_WIDTH_IN_CHARS * 4, 0), MapMode(MapUnit::MapAppFont))); + m_xWidget->set_size_request(aSize.Width(), -1); + + SetSizePixel(get_preferred_size()); +} + +void SvxStyleBox_Base::UserDrawEntry(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect, const OUString &rStyleName) +{ + // IMG_TXT_DISTANCE in ilstbox.hxx is 6, then 1 is added as + // nBorder, and we are adding 1 in order to look better when + // italics is present + const int nLeftDistance = 8; + + tools::Rectangle aTextRect; + rRenderContext.GetTextBoundRect(aTextRect, rStyleName); + + Point aPos(rRect.TopLeft()); + aPos.AdjustX(nLeftDistance ); + + if (!AdjustFontForItemHeight(rRenderContext, aTextRect, rRect.GetHeight())) + aPos.AdjustY((rRect.GetHeight() - aTextRect.Bottom() ) / 2); + + rRenderContext.DrawText(aPos, rStyleName); +} + +void SvxStyleBox_Base::SetupEntry(vcl::RenderContext& rRenderContext, sal_Int32 nItem, const tools::Rectangle& rRect, const OUString& rStyleName, bool bIsNotSelected) +{ + const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings(); + if (!bIsNotSelected) + rRenderContext.SetTextColor(rStyleSettings.GetHighlightTextColor()); + else + rRenderContext.SetTextColor(rStyleSettings.GetDialogTextColor()); + + // handle the push-button + if (!bIsNotSelected) + { + if (nItem == 0 || nItem == m_xWidget->get_count() - 1) + m_xWidget->set_item_menu(OString::number(nItem), nullptr); + else + m_xWidget->set_item_menu(OString::number(nItem), m_xMenu.get()); + } + + if (nItem > 0 && nItem < m_xWidget->get_count() - 1) + { + SfxObjectShell *pShell = SfxObjectShell::Current(); + SfxStyleSheetBasePool* pPool = pShell->GetStyleSheetPool(); + SfxStyleSheetBase* pStyle = nullptr; + + if ( pPool ) + { + pStyle = pPool->First(eStyleFamily); + while (pStyle && pStyle->GetName() != rStyleName) + pStyle = pPool->Next(); + } + + if (pStyle ) + { + std::unique_ptr<const SfxItemSet> const pItemSet(pStyle->GetItemSetForPreview()); + if (!pItemSet) return; + + const SvxFontItem * const pFontItem = + pItemSet->GetItem<SvxFontItem>(SID_ATTR_CHAR_FONT); + const SvxFontHeightItem * const pFontHeightItem = + pItemSet->GetItem<SvxFontHeightItem>(SID_ATTR_CHAR_FONTHEIGHT); + + if ( pFontItem && pFontHeightItem ) + { + Size aFontSize( 0, pFontHeightItem->GetHeight() ); + Size aPixelSize(rRenderContext.LogicToPixel(aFontSize, MapMode(pShell->GetMapUnit()))); + + // setup the font properties + SvxFont aFont; + aFont.SetFamilyName(pFontItem->GetFamilyName()); + aFont.SetStyleName(pFontItem->GetStyleName()); + aFont.SetFontSize(aPixelSize); + + const SfxPoolItem *pItem = pItemSet->GetItem( SID_ATTR_CHAR_WEIGHT ); + if ( pItem ) + aFont.SetWeight( static_cast< const SvxWeightItem* >( pItem )->GetWeight() ); + + pItem = pItemSet->GetItem( SID_ATTR_CHAR_POSTURE ); + if ( pItem ) + aFont.SetItalic( static_cast< const SvxPostureItem* >( pItem )->GetPosture() ); + + pItem = pItemSet->GetItem( SID_ATTR_CHAR_CONTOUR ); + if ( pItem ) + aFont.SetOutline( static_cast< const SvxContourItem* >( pItem )->GetValue() ); + + pItem = pItemSet->GetItem( SID_ATTR_CHAR_SHADOWED ); + if ( pItem ) + aFont.SetShadow( static_cast< const SvxShadowedItem* >( pItem )->GetValue() ); + + pItem = pItemSet->GetItem( SID_ATTR_CHAR_RELIEF ); + if ( pItem ) + aFont.SetRelief( static_cast< const SvxCharReliefItem* >( pItem )->GetValue() ); + + pItem = pItemSet->GetItem( SID_ATTR_CHAR_UNDERLINE ); + if ( pItem ) + aFont.SetUnderline( static_cast< const SvxUnderlineItem* >( pItem )->GetLineStyle() ); + + pItem = pItemSet->GetItem( SID_ATTR_CHAR_OVERLINE ); + if ( pItem ) + aFont.SetOverline( static_cast< const SvxOverlineItem* >( pItem )->GetValue() ); + + pItem = pItemSet->GetItem( SID_ATTR_CHAR_STRIKEOUT ); + if ( pItem ) + aFont.SetStrikeout( static_cast< const SvxCrossedOutItem* >( pItem )->GetStrikeout() ); + + pItem = pItemSet->GetItem( SID_ATTR_CHAR_CASEMAP ); + if ( pItem ) + aFont.SetCaseMap(static_cast<const SvxCaseMapItem*>(pItem)->GetCaseMap()); + + pItem = pItemSet->GetItem( SID_ATTR_CHAR_EMPHASISMARK ); + if ( pItem ) + aFont.SetEmphasisMark( static_cast< const SvxEmphasisMarkItem* >( pItem )->GetEmphasisMark() ); + + // setup the device & draw + Color aFontCol = COL_AUTO, aBackCol = COL_AUTO; + + rRenderContext.SetFont(aFont); + + pItem = pItemSet->GetItem( SID_ATTR_CHAR_COLOR ); + // text color, when nothing is selected + if ( (nullptr != pItem) && bIsNotSelected) + aFontCol = static_cast< const SvxColorItem* >( pItem )->GetValue(); + + drawing::FillStyle style = drawing::FillStyle_NONE; + // which kind of Fill style is selected + pItem = pItemSet->GetItem( XATTR_FILLSTYLE ); + // only when ok and not selected + if ( (nullptr != pItem) && bIsNotSelected) + style = static_cast< const XFillStyleItem* >( pItem )->GetValue(); + + switch(style) + { + case drawing::FillStyle_SOLID: + { + // set background color + pItem = pItemSet->GetItem( XATTR_FILLCOLOR ); + if ( nullptr != pItem ) + aBackCol = static_cast< const XFillColorItem* >( pItem )->GetColorValue(); + + if ( aBackCol != COL_AUTO ) + { + rRenderContext.SetFillColor(aBackCol); + rRenderContext.DrawRect(rRect); + } + } + break; + + default: break; + //TODO Draw the other background styles: gradient, hatching and bitmap + } + + // when the font and background color are too similar, adjust the Font-Color + if( (aFontCol != COL_AUTO) || (aBackCol != COL_AUTO) ) + aFontCol = TestColorsVisible(aFontCol, (aBackCol != COL_AUTO) ? aBackCol : rRenderContext.GetBackground().GetColor()); + + // set text color + if ( aFontCol != COL_AUTO ) + rRenderContext.SetTextColor(aFontCol); + } + } + } +} + +IMPL_LINK(SvxStyleBox_Base, CustomRenderHdl, weld::ComboBox::render_args, aPayload, void) +{ + vcl::RenderContext& rRenderContext = std::get<0>(aPayload); + const ::tools::Rectangle& rRect = std::get<1>(aPayload); + bool bSelected = std::get<2>(aPayload); + const OUString& rId = std::get<3>(aPayload); + + sal_uInt32 nIndex = rId.toUInt32(); + + OUString aStyleName(m_xWidget->get_text(nIndex)); + + rRenderContext.Push(PushFlags::FILLCOLOR | PushFlags::FONT | PushFlags::TEXTCOLOR); + + SetupEntry(rRenderContext, nIndex, rRect, aStyleName, !bSelected); + + UserDrawEntry(rRenderContext, rRect, aStyleName); + + rRenderContext.Pop(); +} + +void SvxStyleBox_Base::CalcOptimalExtraUserWidth(vcl::RenderContext& rRenderContext) +{ + if (m_nMaxUserDrawFontWidth) + return; + + long nMaxNormalFontWidth = 0; + sal_Int32 nEntryCount = m_xWidget->get_count(); + for (sal_Int32 i = 0; i < nEntryCount; ++i) + { + OUString sStyleName(get_text(i)); + tools::Rectangle aTextRectForDefaultFont; + rRenderContext.GetTextBoundRect(aTextRectForDefaultFont, sStyleName); + + const long nWidth = aTextRectForDefaultFont.GetWidth(); + + nMaxNormalFontWidth = std::max(nWidth, nMaxNormalFontWidth); + } + + m_nMaxUserDrawFontWidth = nMaxNormalFontWidth; + for (sal_Int32 i = 1; i < nEntryCount-1; ++i) + { + OUString sStyleName(get_text(i)); + + rRenderContext.Push(PushFlags::FILLCOLOR | PushFlags::FONT | PushFlags::TEXTCOLOR); + SetupEntry(rRenderContext, i, tools::Rectangle(0, 0, RECT_MAX, ITEM_HEIGHT), sStyleName, true); + tools::Rectangle aTextRectForActualFont; + rRenderContext.GetTextBoundRect(aTextRectForActualFont, sStyleName); + if (AdjustFontForItemHeight(rRenderContext, aTextRectForActualFont, ITEM_HEIGHT)) + { + //Font didn't fit, so it was changed, refetch with final font size + rRenderContext.GetTextBoundRect(aTextRectForActualFont, sStyleName); + } + rRenderContext.Pop(); + + const int nWidth = aTextRectForActualFont.GetWidth() + m_xWidget->get_menu_button_width() + BUTTON_PADDING; + + m_nMaxUserDrawFontWidth = std::max(nWidth, m_nMaxUserDrawFontWidth); + } +} + +// test is the color between Font- and background-color to be identify +// return is always the Font-Color +// when both light or dark, change the Contrast +// in other case do not change the origin color +// when the color is R=G=B=128 the DecreaseContrast make 128 the need an exception +Color SvxStyleBox_Base::TestColorsVisible(const Color &FontCol, const Color &BackCol) +{ + const sal_uInt8 ChgVal = 60; // increase/decrease the Contrast + + Color retCol = FontCol; + if ((FontCol.IsDark() == BackCol.IsDark()) && (FontCol.IsBright() == BackCol.IsBright())) + { + sal_uInt8 lumi = retCol.GetLuminance(); + + if((lumi > 120) && (lumi < 140)) + retCol.DecreaseLuminance(ChgVal / 2); + else + retCol.DecreaseContrast(ChgVal); + } + + return retCol; +} + +IMPL_LINK(SvxStyleBox_Base, DumpAsPropertyTreeHdl, boost::property_tree::ptree&, rTree, void) +{ + boost::property_tree::ptree aEntries; + + for (int i = 0, nEntryCount = m_xWidget->get_count(); i < nEntryCount; ++i) + { + boost::property_tree::ptree aEntry; + aEntry.put("", m_xWidget->get_text(i)); + aEntries.push_back(std::make_pair("", aEntry)); + } + + rTree.add_child("entries", aEntries); + + boost::property_tree::ptree aSelected; + + int nActive = m_xWidget->get_active(); + + if (nActive != -1) + { + boost::property_tree::ptree aEntry; + aEntry.put("", nActive); + aSelected.push_back(std::make_pair("", aEntry)); + } + + rTree.put("selectedCount", nActive == -1 ? 0 : 1); + rTree.add_child("selectedEntries", aSelected); + rTree.put("command", ".uno:StyleApply"); +} + +static bool lcl_GetDocFontList(const FontList** ppFontList, SvxFontNameBox_Base* pBox) +{ + bool bChanged = false; + const SfxObjectShell* pDocSh = SfxObjectShell::Current(); + const SvxFontListItem* pFontListItem = nullptr; + + if ( pDocSh ) + pFontListItem = + static_cast<const SvxFontListItem*>(pDocSh->GetItem( SID_ATTR_CHAR_FONTLIST )); + else + { + ::std::unique_ptr<FontList> aFontList(new FontList(Application::GetDefaultDevice())); + *ppFontList = aFontList.get(); + pBox->SetOwnFontList(std::move(aFontList)); + bChanged = true; + } + + if ( pFontListItem ) + { + const FontList* pNewFontList = pFontListItem->GetFontList(); + DBG_ASSERT( pNewFontList, "Doc-FontList not available!" ); + + // No old list, but a new list + if ( !*ppFontList && pNewFontList ) + { + // => take over + *ppFontList = pNewFontList; + bChanged = true; + } + else + { + // Comparing the font lists is not perfect. + // When you change the font list in the Doc, you can track + // changes here only on the Listbox, because ppFontList + // has already been updated. + bChanged = + ( ( *ppFontList != pNewFontList ) || + pBox->GetListCount() != pNewFontList->GetFontNameCount() ); + // HACK: Comparing is incomplete + + if ( bChanged ) + *ppFontList = pNewFontList; + } + + if ( pBox ) + pBox->set_sensitive(true); + } + else if ( pBox && ( pDocSh || !ppFontList )) + { + // Disable box only when we have a SfxObjectShell and didn't get a font list OR + // we don't have a SfxObjectShell and no current font list. + // It's possible that we currently have no SfxObjectShell, but a current font list. + // See #i58471: When a user set the focus into the font name combo box and opens + // the help window with F1. After closing the help window, we disable the font name + // combo box. The SfxObjectShell::Current() method returns in that case zero. But the + // font list hasn't changed and therefore the combo box shouldn't be disabled! + pBox->set_sensitive(false); + } + + // Fill the FontBox, also the new list if necessary + if ( pBox && bChanged ) + { + if ( *ppFontList ) + pBox->Fill( *ppFontList ); + else + pBox->Clear(); + } + return bChanged; +} + +SvxFontNameBox_Base::SvxFontNameBox_Base(std::unique_ptr<weld::ComboBox> xWidget, + const Reference<XDispatchProvider>& rDispatchProvider, + const Reference<XFrame>& rFrame, + SvxFontNameToolBoxControl& rCtrl) + : m_xListener(new comphelper::ConfigurationListener("/org.openoffice.Office.Common/Font/View")) + , m_aWYSIWYG(m_xListener, "ShowFontBoxWYSIWYG", *this) + , m_aHistory(m_xListener, "History", *this) + , m_rCtrl(rCtrl) + , m_xWidget(new FontNameBox(std::move(xWidget))) + , pFontList(nullptr) + , nFtCount(0) + , bRelease(true) + , m_xDispatchProvider(rDispatchProvider) + , m_xFrame(rFrame) + , mbCheckingUnknownFont(false) +{ + EnableControls(); + + m_xWidget->connect_changed(LINK(this, SvxFontNameBox_Base, SelectHdl)); + m_xWidget->connect_key_press(LINK(this, SvxFontNameBox_Base, KeyInputHdl)); + m_xWidget->connect_entry_activate(LINK(this, SvxFontNameBox_Base, ActivateHdl)); + m_xWidget->connect_focus_in(LINK(this, SvxFontNameBox_Base, FocusInHdl)); + m_xWidget->connect_focus_out(LINK(this, SvxFontNameBox_Base, FocusOutHdl)); + m_xWidget->connect_get_property_tree(LINK(this, SvxFontNameBox_Base, DumpAsPropertyTreeHdl)); + + m_xWidget->set_entry_width_chars(COMBO_WIDTH_IN_CHARS); +} + +SvxFontNameBox_Impl::SvxFontNameBox_Impl(vcl::Window* pParent, const Reference<XDispatchProvider>& rDispatchProvider, + const Reference<XFrame>& rFrame, SvxFontNameToolBoxControl& rCtrl) + : InterimItemWindow(pParent, "svx/ui/fontnamebox.ui", "FontNameBox") + , SvxFontNameBox_Base(m_xBuilder->weld_combo_box("fontnamecombobox"), rDispatchProvider, rFrame, rCtrl) +{ + set_id("fontnamecombobox"); + SetOptimalSize(); +} + +void SvxFontNameBox_Base::FillList() +{ + if (!m_xWidget) // e.g. disposed + return; + // Save old Selection, set back in the end + int nStartPos, nEndPos; + m_xWidget->get_entry_selection_bounds(nStartPos, nEndPos); + + // Did Doc-Fontlist change? + lcl_GetDocFontList(&pFontList, this); + + m_xWidget->select_entry_region(nStartPos, nEndPos); +} + +void SvxFontNameBox_Base::CheckAndMarkUnknownFont() +{ + if (mbCheckingUnknownFont) //tdf#117537 block rentry + return; + mbCheckingUnknownFont = true; + OUString fontname = m_xWidget->get_active_text(); + lcl_GetDocFontList( &pFontList, this ); + // If the font is unknown, show it in italic. + vcl::Font font = m_xWidget->get_entry_font(); + if( pFontList != nullptr && pFontList->IsAvailable( fontname )) + { + if( font.GetItalic() != ITALIC_NONE ) + { + font.SetItalic( ITALIC_NONE ); + m_xWidget->set_entry_font(font); + m_xWidget->set_tooltip_text(SvxResId(RID_SVXSTR_CHARFONTNAME)); + } + } + else + { + if( font.GetItalic() != ITALIC_NORMAL ) + { + font.SetItalic( ITALIC_NORMAL ); + m_xWidget->set_entry_font(font); + m_xWidget->set_tooltip_text(SvxResId(RID_SVXSTR_CHARFONTNAME_NOTAVAILABLE)); + } + } + mbCheckingUnknownFont = false; +} + +void SvxFontNameBox_Base::Update( const css::awt::FontDescriptor* pFontDesc ) +{ + if ( pFontDesc ) + { + aCurFont.SetFamilyName ( pFontDesc->Name ); + aCurFont.SetFamily ( FontFamily( pFontDesc->Family ) ); + aCurFont.SetStyleName ( pFontDesc->StyleName ); + aCurFont.SetPitch ( FontPitch( pFontDesc->Pitch ) ); + aCurFont.SetCharSet ( rtl_TextEncoding( pFontDesc->CharSet ) ); + } + OUString aCurName = aCurFont.GetFamilyName(); + OUString aText = m_xWidget->get_active_text(); + if (aText != aCurName) + set_active_or_entry_text(aCurName); +} + +void SvxFontNameBox_Base::set_active_or_entry_text(const OUString& rText) +{ + m_xWidget->set_active_or_entry_text(rText); + CheckAndMarkUnknownFont(); +} + +IMPL_LINK_NOARG(SvxFontNameBox_Base, FocusInHdl, weld::Widget&, void) +{ + FillList(); +} + +IMPL_LINK(SvxFontNameBox_Base, KeyInputHdl, const KeyEvent&, rKEvt, bool) +{ + return DoKeyInput(rKEvt); +} + +bool SvxFontNameBox_Base::DoKeyInput(const KeyEvent& rKEvt) +{ + bool bHandled = false; + + sal_uInt16 nCode = rKEvt.GetKeyCode().GetCode(); + + switch (nCode) + { + case KEY_TAB: + bRelease = false; + Select(true); + break; + + case KEY_ESCAPE: + set_active_or_entry_text(m_xWidget->get_saved_value()); + if (!m_rCtrl.IsInSidebar()) + { + ReleaseFocus_Impl(); + bHandled = true; + } + EndPreview(); + break; + } + + return bHandled; +} + +bool SvxFontNameBox_Impl::DoKeyInput(const KeyEvent& rKEvt) +{ + return SvxFontNameBox_Base::DoKeyInput(rKEvt) || ChildKeyInput(rKEvt); +} + +IMPL_LINK_NOARG(SvxFontNameBox_Base, FocusOutHdl, weld::Widget&, void) +{ + if (!m_xWidget->has_focus()) // a combobox can be comprised of different subwidget so double-check if none of those has focus + { + set_active_or_entry_text(m_xWidget->get_saved_value()); + // send EndPreview + EndPreview(); + } +} + +void SvxFontNameBox_Impl::SetOptimalSize() +{ + // set width in chars low so the size request will not be overridden + m_xWidget->set_entry_width_chars(1); + // tdf#132338 purely using this calculation to keep things their traditional width + Size aSize(LogicToPixel(Size(COMBO_WIDTH_IN_CHARS * 4, 0), MapMode(MapUnit::MapAppFont))); + m_xWidget->set_size_request(aSize.Width(), -1); + + SetSizePixel(get_preferred_size()); +} + +void SvxFontNameBox_Impl::DataChanged( const DataChangedEvent& rDCEvt ) +{ + if ( (rDCEvt.GetType() == DataChangedEventType::SETTINGS) && + (rDCEvt.GetFlags() & AllSettingsFlags::STYLE) ) + { + SetOptimalSize(); + } + else if ( ( rDCEvt.GetType() == DataChangedEventType::FONTS ) || + ( rDCEvt.GetType() == DataChangedEventType::DISPLAY ) ) + { + // The old font list in shell has likely been destroyed at this point, so we need to get + // the new one before doing anything further. + lcl_GetDocFontList( &pFontList, this ); + } +} + +void SvxFontNameBox_Base::ReleaseFocus_Impl() +{ + if ( !bRelease ) + { + bRelease = true; + return; + } + if ( m_xFrame.is() && m_xFrame->getContainerWindow().is() ) + m_xFrame->getContainerWindow()->setFocus(); +} + +void SvxFontNameBox_Base::EnableControls() +{ + bool bEnableMRU = m_aHistory.get(); + sal_uInt16 nEntries = bEnableMRU ? MAX_MRU_FONTNAME_ENTRIES : 0; + + bool bNewWYSIWYG = m_aWYSIWYG.get(); + bool bOldWYSIWYG = m_xWidget->IsWYSIWYGEnabled(); + + if (m_xWidget->get_max_mru_count() != nEntries || bNewWYSIWYG != bOldWYSIWYG) + { + // refill in the next GetFocus-Handler + pFontList = nullptr; + Clear(); + m_xWidget->set_max_mru_count(nEntries); + } + + if (bNewWYSIWYG != bOldWYSIWYG) + m_xWidget->EnableWYSIWYG(bNewWYSIWYG); +} + +IMPL_LINK(SvxFontNameBox_Base, SelectHdl, weld::ComboBox&, rCombo, void) +{ + Select(rCombo.changed_by_direct_pick()); // only when picked from the list +} + +IMPL_LINK_NOARG(SvxFontNameBox_Base, ActivateHdl, weld::ComboBox&, bool) +{ + Select(true); + return true; +} + +void SvxFontNameBox_Base::Select(bool bNonTravelSelect) +{ + Sequence< PropertyValue > aArgs( 1 ); + std::unique_ptr<SvxFontItem> pFontItem; + if ( pFontList ) + { + FontMetric aFontMetric( pFontList->Get(m_xWidget->get_active_text(), + aCurFont.GetWeight(), + aCurFont.GetItalic() ) ); + aCurFont = aFontMetric; + + pFontItem.reset( new SvxFontItem( aFontMetric.GetFamilyType(), + aFontMetric.GetFamilyName(), + aFontMetric.GetStyleName(), + aFontMetric.GetPitch(), + aFontMetric.GetCharSet(), + SID_ATTR_CHAR_FONT ) ); + + Any a; + pFontItem->QueryValue( a ); + aArgs[0].Value = a; + } + + if (bNonTravelSelect) + { + CheckAndMarkUnknownFont(); + // #i33380# DR 2004-09-03 Moved the following line above the Dispatch() call. + // This instance may be deleted in the meantime (i.e. when a dialog is opened + // while in Dispatch()), accessing members will crash in this case. + ReleaseFocus_Impl(); + EndPreview(); + if (pFontItem) + { + aArgs[0].Name = "CharFontName"; + SfxToolBoxControl::Dispatch( m_xDispatchProvider, + ".uno:CharFontName", + aArgs ); + } + } + else + { + if (pFontItem) + { + aArgs[0].Name = "CharPreviewFontName"; + SfxToolBoxControl::Dispatch( m_xDispatchProvider, + ".uno:CharPreviewFontName", + aArgs ); + } + } +} + +IMPL_LINK(SvxFontNameBox_Base, DumpAsPropertyTreeHdl, boost::property_tree::ptree&, rTree, void) +{ + boost::property_tree::ptree aEntries; + + for (int i = 0, nEntryCount = m_xWidget->get_count(); i < nEntryCount; ++i) + { + boost::property_tree::ptree aEntry; + aEntry.put("", m_xWidget->get_text(i)); + aEntries.push_back(std::make_pair("", aEntry)); + } + + rTree.add_child("entries", aEntries); + + boost::property_tree::ptree aSelected; + + int nSelectedEntry = m_xWidget->get_active(); + if (nSelectedEntry != -1) + { + boost::property_tree::ptree aEntry; + aEntry.put("", m_xWidget->get_text(nSelectedEntry)); + aSelected.push_back(std::make_pair("", aEntry)); + } + + rTree.put("selectedCount", nSelectedEntry == -1 ? 0 : 1); + rTree.add_child("selectedEntries", aSelected); + rTree.put("command", ".uno:CharFontName"); +} + +ColorWindow::ColorWindow(const OUString& rCommand, + std::shared_ptr<PaletteManager> const & rPaletteManager, + ColorStatus& rColorStatus, + sal_uInt16 nSlotId, + const Reference< XFrame >& rFrame, + weld::Window* pParentWindow, + const MenuOrToolMenuButton& rMenuButton, + ColorSelectFunction const & aFunction) + : WeldToolbarPopup(rFrame, rMenuButton.get_widget(), "svx/ui/colorwindow.ui", "palette_popup_window") + , theSlotId(nSlotId) + , maCommand(rCommand) + , mpParentWindow(pParentWindow) + , maMenuButton(rMenuButton) + , mxPaletteManager(rPaletteManager) + , mrColorStatus(rColorStatus) + , maColorSelectFunction(aFunction) + , mxColorSet(new SvxColorValueSet(m_xBuilder->weld_scrolled_window("colorsetwin"))) + , mxRecentColorSet(new SvxColorValueSet(nullptr)) + , mxPaletteListBox(m_xBuilder->weld_combo_box("palette_listbox")) + , mxButtonAutoColor(m_xBuilder->weld_button("auto_color_button")) + , mxButtonNoneColor(m_xBuilder->weld_button("none_color_button")) + , mxButtonPicker(m_xBuilder->weld_button("color_picker_button")) + , mxAutomaticSeparator(m_xBuilder->weld_widget("separator4")) + , mxColorSetWin(new weld::CustomWeld(*m_xBuilder, "colorset", *mxColorSet)) + , mxRecentColorSetWin(new weld::CustomWeld(*m_xBuilder, "recent_colorset", *mxRecentColorSet)) + , mpDefaultButton(nullptr) +{ + mxColorSet->SetStyle( WinBits(WB_FLATVALUESET | WB_ITEMBORDER | WB_3DLOOK | WB_NO_DIRECTSELECT | WB_TABSTOP) ); + mxRecentColorSet->SetStyle( WinBits(WB_FLATVALUESET | WB_ITEMBORDER | WB_3DLOOK | WB_NO_DIRECTSELECT | WB_TABSTOP) ); + + switch ( theSlotId ) + { + case SID_ATTR_CHAR_COLOR_BACKGROUND: + case SID_BACKGROUND_COLOR: + case SID_ATTR_CHAR_BACK_COLOR: + case SID_TABLE_CELL_BACKGROUND_COLOR: + { + mxButtonAutoColor->set_label( SvxResId( RID_SVXSTR_NOFILL ) ); + break; + } + case SID_AUTHOR_COLOR: + { + mxButtonAutoColor->set_label( SvxResId( RID_SVXSTR_BY_AUTHOR ) ); + break; + } + case SID_BMPMASK_COLOR: + { + mxButtonAutoColor->set_label( SvxResId( RID_SVXSTR_TRANSPARENT ) ); + break; + } + case SID_ATTR_CHAR_COLOR: + case SID_ATTR_CHAR_COLOR2: + case SID_EXTRUSION_3D_COLOR: + { + mxButtonAutoColor->set_label(EditResId(RID_SVXSTR_AUTOMATIC)); + break; + } + case SID_FM_CTL_PROPERTIES: + { + mxButtonAutoColor->set_label( SvxResId( RID_SVXSTR_DEFAULT ) ); + break; + } + default: + { + mxButtonAutoColor->hide(); + mxAutomaticSeparator->hide(); + break; + } + } + + mxPaletteListBox->connect_changed(LINK(this, ColorWindow, SelectPaletteHdl)); + std::vector<OUString> aPaletteList = mxPaletteManager->GetPaletteList(); + mxPaletteListBox->freeze(); + for (const auto& rPalette : aPaletteList) + mxPaletteListBox->append_text(rPalette); + mxPaletteListBox->thaw(); + OUString aPaletteName( officecfg::Office::Common::UserColors::PaletteName::get() ); + mxPaletteListBox->set_active_text(aPaletteName); + const int nSelectedEntry(mxPaletteListBox->get_active()); + if (nSelectedEntry != -1) + mxPaletteManager->SetPalette(nSelectedEntry); + + mxButtonAutoColor->connect_clicked(LINK(this, ColorWindow, AutoColorClickHdl)); + mxButtonNoneColor->connect_clicked(LINK(this, ColorWindow, AutoColorClickHdl)); + mxButtonPicker->connect_clicked(LINK(this, ColorWindow, OpenPickerClickHdl)); + + mxColorSet->SetSelectHdl(LINK( this, ColorWindow, SelectHdl)); + mxRecentColorSet->SetSelectHdl(LINK( this, ColorWindow, SelectHdl)); + m_xTopLevel->set_help_id(HID_POPUP_COLOR); + mxColorSet->SetHelpId(HID_POPUP_COLOR_CTRL); + + mxPaletteManager->ReloadColorSet(*mxColorSet); + const sal_uInt32 nMaxItems(SvxColorValueSet::getMaxRowCount() * SvxColorValueSet::getColumnCount()); + Size aSize = mxColorSet->layoutAllVisible(nMaxItems); + mxColorSet->set_size_request(aSize.Width(), aSize.Height()); + + mxPaletteManager->ReloadRecentColorSet(*mxRecentColorSet); + aSize = mxRecentColorSet->layoutAllVisible(mxPaletteManager->GetRecentColorCount()); + mxRecentColorSet->set_size_request(aSize.Width(), aSize.Height()); + + AddStatusListener( ".uno:ColorTableState" ); + AddStatusListener( maCommand ); + if ( maCommand == ".uno:FrameLineColor" ) + { + AddStatusListener( ".uno:BorderTLBR" ); + AddStatusListener( ".uno:BorderBLTR" ); + } +} + +void ColorWindow::GrabFocus() +{ + if (mxColorSet->IsNoSelection() && mpDefaultButton) + mpDefaultButton->grab_focus(); + else + mxColorSet->GrabFocus(); +} + +void ColorWindow::ShowNoneButton() +{ + mxButtonNoneColor->show(); +} + +ColorWindow::~ColorWindow() +{ +} + +NamedColor ColorWindow::GetSelectEntryColor(ValueSet const * pColorSet) +{ + Color aColor = pColorSet->GetItemColor(pColorSet->GetSelectedItemId()); + OUString sColorName = pColorSet->GetItemText(pColorSet->GetSelectedItemId()); + return std::make_pair(aColor, sColorName); +} + +namespace +{ + NamedColor GetAutoColor(sal_uInt16 nSlotId) + { + Color aColor; + OUString sColorName; + switch (nSlotId) + { + case SID_ATTR_CHAR_COLOR_BACKGROUND: + case SID_BACKGROUND_COLOR: + case SID_ATTR_CHAR_BACK_COLOR: + case SID_TABLE_CELL_BACKGROUND_COLOR: + aColor = COL_TRANSPARENT; + sColorName = SvxResId(RID_SVXSTR_NOFILL); + break; + case SID_AUTHOR_COLOR: + aColor = COL_TRANSPARENT; + sColorName = SvxResId(RID_SVXSTR_BY_AUTHOR); + break; + case SID_BMPMASK_COLOR: + aColor = COL_TRANSPARENT; + sColorName = SvxResId(RID_SVXSTR_TRANSPARENT); + break; + case SID_FM_CTL_PROPERTIES: + aColor = COL_TRANSPARENT; + sColorName = SvxResId(RID_SVXSTR_DEFAULT); + break; + case SID_ATTR_CHAR_COLOR: + case SID_ATTR_CHAR_COLOR2: + case SID_EXTRUSION_3D_COLOR: + default: + aColor = COL_AUTO; + sColorName = EditResId(RID_SVXSTR_AUTOMATIC); + break; + } + + return std::make_pair(aColor, sColorName); + } + + NamedColor GetNoneColor() + { + return std::make_pair(COL_NONE_COLOR, comphelper::LibreOfficeKit::isActive() ? SvxResId(RID_SVXSTR_INVISIBLE) + : SvxResId(RID_SVXSTR_NONE)); + } +} + +NamedColor ColorWindow::GetSelectEntryColor() const +{ + if (!mxColorSet->IsNoSelection()) + return GetSelectEntryColor(mxColorSet.get()); + if (!mxRecentColorSet->IsNoSelection()) + return GetSelectEntryColor(mxRecentColorSet.get()); + if (mxButtonNoneColor.get() == mpDefaultButton) + return GetNoneColor(); + return GetAutoColor(); +} + +IMPL_LINK(ColorWindow, SelectHdl, ValueSet*, pColorSet, void) +{ + NamedColor aNamedColor = GetSelectEntryColor(pColorSet); + + if (pColorSet != mxRecentColorSet.get()) + { + mxPaletteManager->AddRecentColor(aNamedColor.first, aNamedColor.second); + if (!maMenuButton.get_active()) + mxPaletteManager->ReloadRecentColorSet(*mxRecentColorSet); + } + + maSelectedLink.Call(aNamedColor); + + // deliberate take a copy here in case maMenuButton.set_inactive + // triggers a callback that destroys ourself + ColorSelectFunction aColorSelectFunction(maColorSelectFunction); + OUString sCommand(maCommand); + + maMenuButton.set_inactive(); + + aColorSelectFunction(sCommand, aNamedColor); +} + +IMPL_LINK_NOARG(ColorWindow, SelectPaletteHdl, weld::ComboBox&, void) +{ + int nPos = mxPaletteListBox->get_active(); + mxPaletteManager->SetPalette( nPos ); + mxPaletteManager->ReloadColorSet(*mxColorSet); + mxColorSet->layoutToGivenHeight(mxColorSet->GetOutputSizePixel().Height(), mxPaletteManager->GetColorCount()); +} + +NamedColor ColorWindow::GetAutoColor() const +{ + return ::GetAutoColor(theSlotId); +} + +IMPL_LINK(ColorWindow, AutoColorClickHdl, weld::Button&, rButton, void) +{ + NamedColor aNamedColor = &rButton == mxButtonAutoColor.get() ? GetAutoColor() : GetNoneColor(); + + mxColorSet->SetNoSelection(); + mxRecentColorSet->SetNoSelection(); + mpDefaultButton = &rButton; + + maSelectedLink.Call(aNamedColor); + + // deliberate take a copy here in case maMenuButton.set_inactive + // triggers a callback that destroys ourself + ColorSelectFunction aColorSelectFunction(maColorSelectFunction); + OUString sCommand(maCommand); + + maMenuButton.set_inactive(); + + aColorSelectFunction(sCommand, aNamedColor); +} + +IMPL_LINK_NOARG(ColorWindow, OpenPickerClickHdl, weld::Button&, void) +{ + // copy before set_inactive + auto nColor = GetSelectEntryColor().first; + auto pParentWindow = mpParentWindow; + OUString sCommand = maCommand; + std::shared_ptr<PaletteManager> xPaletteManager(mxPaletteManager); + + maMenuButton.set_inactive(); + + xPaletteManager->PopupColorPicker(pParentWindow, sCommand, nColor); +} + +void ColorWindow::SetNoSelection() +{ + mxColorSet->SetNoSelection(); + mxRecentColorSet->SetNoSelection(); + mpDefaultButton = nullptr; +} + +bool ColorWindow::IsNoSelection() const +{ + if (!mxColorSet->IsNoSelection()) + return false; + if (!mxRecentColorSet->IsNoSelection()) + return false; + return !mxButtonAutoColor->get_visible() && !mxButtonNoneColor->get_visible(); +} + +void ColorWindow::statusChanged( const css::frame::FeatureStateEvent& rEvent ) +{ + if (rEvent.FeatureURL.Complete == ".uno:ColorTableState") + { + if (rEvent.IsEnabled && mxPaletteManager->GetPalette() == 0) + { + mxPaletteManager->ReloadColorSet(*mxColorSet); + mxColorSet->layoutToGivenHeight(mxColorSet->GetOutputSizePixel().Height(), mxPaletteManager->GetColorCount()); + } + } + else + { + mrColorStatus.statusChanged(rEvent); + SelectEntry(mrColorStatus.GetColor()); + } +} + +bool ColorWindow::SelectValueSetEntry(SvxColorValueSet* pColorSet, const Color& rColor) +{ + for (size_t i = 1; i <= pColorSet->GetItemCount(); ++i) + { + if (rColor == pColorSet->GetItemColor(i)) + { + pColorSet->SelectItem(i); + return true; + } + } + return false; +} + +void ColorWindow::SelectEntry(const NamedColor& rNamedColor) +{ + SetNoSelection(); + + const Color &rColor = rNamedColor.first; + + if (mxButtonAutoColor->get_visible() && (rColor == COL_TRANSPARENT || rColor == COL_AUTO)) + { + mpDefaultButton = mxButtonAutoColor.get(); + return; + } + + if (mxButtonNoneColor->get_visible() && rColor == COL_NONE_COLOR) + { + mpDefaultButton = mxButtonNoneColor.get(); + return; + } + + // try current palette + bool bFoundColor = SelectValueSetEntry(mxColorSet.get(), rColor); + // try recently used + if (!bFoundColor) + bFoundColor = SelectValueSetEntry(mxRecentColorSet.get(), rColor); + // if it's not there, add it there now to the end of the recently used + // so its available somewhere handy, but not without trashing the + // whole recently used + if (!bFoundColor) + { + const OUString& rColorName = rNamedColor.second; + mxPaletteManager->AddRecentColor(rColor, rColorName, false); + mxPaletteManager->ReloadRecentColorSet(*mxRecentColorSet); + SelectValueSetEntry(mxRecentColorSet.get(), rColor); + } +} + +void ColorWindow::SelectEntry(const Color& rColor) +{ + OUString sColorName = "#" + rColor.AsRGBHexString().toAsciiUpperCase(); + ColorWindow::SelectEntry(std::make_pair(rColor, sColorName)); +} + +ColorStatus::ColorStatus() : + maColor( COL_TRANSPARENT ), + maTLBRColor( COL_TRANSPARENT ), + maBLTRColor( COL_TRANSPARENT ) +{ +} + +ColorStatus::~ColorStatus() +{ +} + +void ColorStatus::statusChanged( const css::frame::FeatureStateEvent& rEvent ) +{ + Color aColor( COL_TRANSPARENT ); + css::table::BorderLine2 aTable; + + if ( rEvent.State >>= aTable ) + { + SvxBorderLine aLine; + SvxBoxItem::LineToSvxLine( aTable, aLine, false ); + if ( !aLine.isEmpty() ) + aColor = aLine.GetColor(); + } + else + rEvent.State >>= aColor; + + if ( rEvent.FeatureURL.Path == "BorderTLBR" ) + maTLBRColor = aColor; + else if ( rEvent.FeatureURL.Path == "BorderBLTR" ) + maBLTRColor = aColor; + else + maColor = aColor; +} + +Color ColorStatus::GetColor() +{ + Color aColor( maColor ); + + if ( maTLBRColor != COL_TRANSPARENT ) + { + if ( aColor != maTLBRColor && aColor != COL_TRANSPARENT ) + return COL_TRANSPARENT; + aColor = maTLBRColor; + } + + if ( maBLTRColor != COL_TRANSPARENT ) + { + if ( aColor != maBLTRColor && aColor != COL_TRANSPARENT ) + return COL_TRANSPARENT; + return maBLTRColor; + } + + return aColor; +} + + +SvxFrameWindow_Impl::SvxFrameWindow_Impl(SvxFrameToolBoxControl* pControl, weld::Widget* pParent) + : WeldToolbarPopup(pControl->getFrameInterface(), pParent, "svx/ui/floatingframeborder.ui", "FloatingFrameBorder") + , mxControl(pControl) + , mxFrameSet(new SvxFrmValueSet_Impl) + , mxFrameSetWin(new weld::CustomWeld(*m_xBuilder, "valueset", *mxFrameSet)) + , bParagraphMode(false) +{ + mxFrameSet->SetStyle(WB_ITEMBORDER | WB_DOUBLEBORDER | WB_3DLOOK | WB_NO_DIRECTSELECT); + AddStatusListener(".uno:BorderReducedMode"); + InitImageList(); + + /* + * 1 2 3 4 + * ------------------------------------- + * NONE LEFT RIGHT LEFTRIGHT + * TOP BOTTOM TOPBOTTOM OUTER + * ------------------------------------- + * HOR HORINNER VERINNER ALL <- can be switched of via bParagraphMode + */ + + sal_uInt16 i = 0; + + for ( i=1; i<9; i++ ) + mxFrameSet->InsertItem(i, Image(aImgVec[i-1])); + + //bParagraphMode should have been set in StateChanged + if ( !bParagraphMode ) + for ( i = 9; i < 13; i++ ) + mxFrameSet->InsertItem(i, Image(aImgVec[i-1])); + + mxFrameSet->SetColCount( 4 ); + mxFrameSet->SetSelectHdl( LINK( this, SvxFrameWindow_Impl, SelectHdl ) ); + CalcSizeValueSet(); + + mxFrameSet->SetHelpId( HID_POPUP_FRAME ); + mxFrameSet->SetAccessibleName( SvxResId(RID_SVXSTR_FRAME) ); +} + +namespace { + +enum class FrmValidFlags { + NONE = 0x00, + Left = 0x01, + Right = 0x02, + Top = 0x04, + Bottom = 0x08, + HInner = 0x10, + VInner = 0x20, + AllMask = 0x3f, +}; + +} + +namespace o3tl { + template<> struct typed_flags<FrmValidFlags> : is_typed_flags<FrmValidFlags, 0x3f> {}; +} + +// By default unset lines remain unchanged. +// Via Shift unset lines are reset + +IMPL_LINK_NOARG(SvxFrameWindow_Impl, SelectHdl, ValueSet*, void) +{ + SvxBoxItem aBorderOuter( SID_ATTR_BORDER_OUTER ); + SvxBoxInfoItem aBorderInner( SID_ATTR_BORDER_INNER ); + SvxBorderLine theDefLine; + SvxBorderLine *pLeft = nullptr, + *pRight = nullptr, + *pTop = nullptr, + *pBottom = nullptr; + sal_uInt16 nSel = mxFrameSet->GetSelectedItemId(); + sal_uInt16 nModifier = mxFrameSet->GetModifier(); + FrmValidFlags nValidFlags = FrmValidFlags::NONE; + + theDefLine.GuessLinesWidths(theDefLine.GetBorderLineStyle(), + DEF_LINE_WIDTH_0); + switch ( nSel ) + { + case 1: nValidFlags |= FrmValidFlags::AllMask; + break; // NONE + case 2: pLeft = &theDefLine; + nValidFlags |= FrmValidFlags::Left; + break; // LEFT + case 3: pRight = &theDefLine; + nValidFlags |= FrmValidFlags::Right; + break; // RIGHT + case 4: pLeft = pRight = &theDefLine; + nValidFlags |= FrmValidFlags::Right|FrmValidFlags::Left; + break; // LEFTRIGHT + case 5: pTop = &theDefLine; + nValidFlags |= FrmValidFlags::Top; + break; // TOP + case 6: pBottom = &theDefLine; + nValidFlags |= FrmValidFlags::Bottom; + break; // BOTTOM + case 7: pTop = pBottom = &theDefLine; + nValidFlags |= FrmValidFlags::Bottom|FrmValidFlags::Top; + break; // TOPBOTTOM + case 8: pLeft = pRight = pTop = pBottom = &theDefLine; + nValidFlags |= FrmValidFlags::Left | FrmValidFlags::Right | FrmValidFlags::Top | FrmValidFlags::Bottom; + break; // OUTER + + // Inner Table: + case 9: // HOR + pTop = pBottom = &theDefLine; + aBorderInner.SetLine( &theDefLine, SvxBoxInfoItemLine::HORI ); + aBorderInner.SetLine( nullptr, SvxBoxInfoItemLine::VERT ); + nValidFlags |= FrmValidFlags::HInner|FrmValidFlags::Top|FrmValidFlags::Bottom; + break; + + case 10: // HORINNER + pLeft = pRight = pTop = pBottom = &theDefLine; + aBorderInner.SetLine( &theDefLine, SvxBoxInfoItemLine::HORI ); + aBorderInner.SetLine( nullptr, SvxBoxInfoItemLine::VERT ); + nValidFlags |= FrmValidFlags::Right|FrmValidFlags::Left|FrmValidFlags::HInner|FrmValidFlags::Top|FrmValidFlags::Bottom; + break; + + case 11: // VERINNER + pLeft = pRight = pTop = pBottom = &theDefLine; + aBorderInner.SetLine( nullptr, SvxBoxInfoItemLine::HORI ); + aBorderInner.SetLine( &theDefLine, SvxBoxInfoItemLine::VERT ); + nValidFlags |= FrmValidFlags::Right|FrmValidFlags::Left|FrmValidFlags::VInner|FrmValidFlags::Top|FrmValidFlags::Bottom; + break; + + case 12: // ALL + pLeft = pRight = pTop = pBottom = &theDefLine; + aBorderInner.SetLine( &theDefLine, SvxBoxInfoItemLine::HORI ); + aBorderInner.SetLine( &theDefLine, SvxBoxInfoItemLine::VERT ); + nValidFlags |= FrmValidFlags::AllMask; + break; + + default: + break; + } + aBorderOuter.SetLine( pLeft, SvxBoxItemLine::LEFT ); + aBorderOuter.SetLine( pRight, SvxBoxItemLine::RIGHT ); + aBorderOuter.SetLine( pTop, SvxBoxItemLine::TOP ); + aBorderOuter.SetLine( pBottom, SvxBoxItemLine::BOTTOM ); + + if(nModifier == KEY_SHIFT) + nValidFlags |= FrmValidFlags::AllMask; + aBorderInner.SetValid( SvxBoxInfoItemValidFlags::TOP, bool(nValidFlags&FrmValidFlags::Top )); + aBorderInner.SetValid( SvxBoxInfoItemValidFlags::BOTTOM, bool(nValidFlags&FrmValidFlags::Bottom )); + aBorderInner.SetValid( SvxBoxInfoItemValidFlags::LEFT, bool(nValidFlags&FrmValidFlags::Left)); + aBorderInner.SetValid( SvxBoxInfoItemValidFlags::RIGHT, bool(nValidFlags&FrmValidFlags::Right )); + aBorderInner.SetValid( SvxBoxInfoItemValidFlags::HORI, bool(nValidFlags&FrmValidFlags::HInner )); + aBorderInner.SetValid( SvxBoxInfoItemValidFlags::VERT, bool(nValidFlags&FrmValidFlags::VInner)); + aBorderInner.SetValid( SvxBoxInfoItemValidFlags::DISTANCE ); + aBorderInner.SetValid( SvxBoxInfoItemValidFlags::DISABLE, false ); + + Any a; + Sequence< PropertyValue > aArgs( 2 ); + aArgs[0].Name = "OuterBorder"; + aBorderOuter.QueryValue( a ); + aArgs[0].Value = a; + aArgs[1].Name = "InnerBorder"; + aBorderInner.QueryValue( a ); + aArgs[1].Value = a; + + if (mxFrameSet) + { + /* #i33380# Moved the following line above the Dispatch() call. + This instance may be deleted in the meantime (i.e. when a dialog is opened + while in Dispatch()), accessing members will crash in this case. */ + mxFrameSet->SetNoSelection(); + } + + mxControl->dispatchCommand( ".uno:SetBorderStyle", aArgs ); + + mxControl->EndPopupMode(); +} + +void SvxFrameWindow_Impl::statusChanged( const css::frame::FeatureStateEvent& rEvent ) +{ + if ( rEvent.FeatureURL.Complete == ".uno:BorderReducedMode" ) + { + bool bValue; + if ( rEvent.State >>= bValue ) + { + bParagraphMode = bValue; + //initial calls mustn't insert or remove elements + if(mxFrameSet->GetItemCount()) + { + bool bTableMode = ( mxFrameSet->GetItemCount() == 12 ); + bool bResize = false; + + if ( bTableMode && bParagraphMode ) + { + for ( sal_uInt16 i = 9; i < 13; i++ ) + mxFrameSet->RemoveItem(i); + bResize = true; + } + else if ( !bTableMode && !bParagraphMode ) + { + for ( sal_uInt16 i = 9; i < 13; i++ ) + mxFrameSet->InsertItem(i, Image(aImgVec[i-1])); + bResize = true; + } + + if ( bResize ) + { + CalcSizeValueSet(); + } + } + } + } +} + +void SvxFrameWindow_Impl::CalcSizeValueSet() +{ + weld::DrawingArea* pDrawingArea = mxFrameSet->GetDrawingArea(); + const OutputDevice& rDevice = pDrawingArea->get_ref_device(); + Size aItemSize( 20 * rDevice.GetDPIScaleFactor(), 20 * rDevice.GetDPIScaleFactor() ); + Size aSize = mxFrameSet->CalcWindowSizePixel( aItemSize ); + pDrawingArea->set_size_request(aSize.Width(), aSize.Height()); + mxFrameSet->SetOutputSizePixel(aSize); +} + +void SvxFrameWindow_Impl::InitImageList() +{ + aImgVec.clear(); + aImgVec.emplace_back(RID_SVXBMP_FRAME1); + aImgVec.emplace_back(RID_SVXBMP_FRAME2); + aImgVec.emplace_back(RID_SVXBMP_FRAME3); + aImgVec.emplace_back(RID_SVXBMP_FRAME4); + aImgVec.emplace_back(RID_SVXBMP_FRAME5); + aImgVec.emplace_back(RID_SVXBMP_FRAME6); + aImgVec.emplace_back(RID_SVXBMP_FRAME7); + aImgVec.emplace_back(RID_SVXBMP_FRAME8); + aImgVec.emplace_back(RID_SVXBMP_FRAME9); + aImgVec.emplace_back(RID_SVXBMP_FRAME10); + aImgVec.emplace_back(RID_SVXBMP_FRAME11); + aImgVec.emplace_back(RID_SVXBMP_FRAME12); +} + +static Color lcl_mediumColor( Color aMain, Color /*aDefault*/ ) +{ + return SvxBorderLine::threeDMediumColor( aMain ); +} + +SvxLineWindow_Impl::SvxLineWindow_Impl(SvxFrameToolBoxControl* pControl, weld::Widget* pParent) + : WeldToolbarPopup(pControl->getFrameInterface(), pParent, "svx/ui/floatingframeborder.ui", "FloatingFrameBorder") + , m_xControl(pControl) + , m_xLineStyleLb(new LineListBox) + , m_xLineStyleLbWin(new weld::CustomWeld(*m_xBuilder, "valueset", *m_xLineStyleLb)) + , m_bIsWriter(false) +{ + try + { + Reference< lang::XServiceInfo > xServices(mxFrame->getController()->getModel(), UNO_QUERY_THROW); + m_bIsWriter = xServices->supportsService("com.sun.star.text.TextDocument"); + } + catch(const uno::Exception& ) + { + } + + m_xLineStyleLb->SetStyle( WinBits(WB_FLATVALUESET | WB_ITEMBORDER | WB_3DLOOK | WB_NO_DIRECTSELECT | WB_TABSTOP) ); + + m_xLineStyleLb->SetSourceUnit( FieldUnit::TWIP ); + m_xLineStyleLb->SetNone( comphelper::LibreOfficeKit::isActive() ? SvxResId(RID_SVXSTR_INVISIBLE) + :SvxResId(RID_SVXSTR_NONE) ); + + m_xLineStyleLb->InsertEntry( SvxBorderLine::getWidthImpl( SvxBorderLineStyle::SOLID ), SvxBorderLineStyle::SOLID ); + m_xLineStyleLb->InsertEntry( SvxBorderLine::getWidthImpl( SvxBorderLineStyle::DOTTED ), SvxBorderLineStyle::DOTTED ); + m_xLineStyleLb->InsertEntry( SvxBorderLine::getWidthImpl( SvxBorderLineStyle::DASHED ), SvxBorderLineStyle::DASHED ); + + // Double lines + m_xLineStyleLb->InsertEntry( SvxBorderLine::getWidthImpl( SvxBorderLineStyle::DOUBLE ), SvxBorderLineStyle::DOUBLE ); + m_xLineStyleLb->InsertEntry( SvxBorderLine::getWidthImpl( SvxBorderLineStyle::THINTHICK_SMALLGAP ), SvxBorderLineStyle::THINTHICK_SMALLGAP, 20 ); + m_xLineStyleLb->InsertEntry( SvxBorderLine::getWidthImpl( SvxBorderLineStyle::THINTHICK_MEDIUMGAP ), SvxBorderLineStyle::THINTHICK_MEDIUMGAP ); + m_xLineStyleLb->InsertEntry( SvxBorderLine::getWidthImpl( SvxBorderLineStyle::THINTHICK_LARGEGAP ), SvxBorderLineStyle::THINTHICK_LARGEGAP ); + m_xLineStyleLb->InsertEntry( SvxBorderLine::getWidthImpl( SvxBorderLineStyle::THICKTHIN_SMALLGAP ), SvxBorderLineStyle::THICKTHIN_SMALLGAP, 20 ); + m_xLineStyleLb->InsertEntry( SvxBorderLine::getWidthImpl( SvxBorderLineStyle::THICKTHIN_MEDIUMGAP ), SvxBorderLineStyle::THICKTHIN_MEDIUMGAP ); + m_xLineStyleLb->InsertEntry( SvxBorderLine::getWidthImpl( SvxBorderLineStyle::THICKTHIN_LARGEGAP ), SvxBorderLineStyle::THICKTHIN_LARGEGAP ); + + // Engraved / Embossed + m_xLineStyleLb->InsertEntry( SvxBorderLine::getWidthImpl( SvxBorderLineStyle::EMBOSSED ), SvxBorderLineStyle::EMBOSSED, 15, + &SvxBorderLine::threeDLightColor, &SvxBorderLine::threeDDarkColor, + &lcl_mediumColor ); + m_xLineStyleLb->InsertEntry( SvxBorderLine::getWidthImpl( SvxBorderLineStyle::ENGRAVED ), SvxBorderLineStyle::ENGRAVED, 15, + &SvxBorderLine::threeDDarkColor, &SvxBorderLine::threeDLightColor, + &lcl_mediumColor ); + + // Inset / Outset + m_xLineStyleLb->InsertEntry( SvxBorderLine::getWidthImpl( SvxBorderLineStyle::OUTSET ), SvxBorderLineStyle::OUTSET, 10, + &SvxBorderLine::lightColor, &SvxBorderLine::darkColor ); + m_xLineStyleLb->InsertEntry( SvxBorderLine::getWidthImpl( SvxBorderLineStyle::INSET ), SvxBorderLineStyle::INSET, 10, + &SvxBorderLine::darkColor, &SvxBorderLine::lightColor ); + Size aSize = m_xLineStyleLb->SetWidth( 20 ); // 1pt by default + + m_xLineStyleLb->SetSelectHdl( LINK( this, SvxLineWindow_Impl, SelectHdl ) ); + + m_xContainer->set_help_id(HID_POPUP_LINE); + + aSize.AdjustWidth(6); + aSize.AdjustHeight(6); + aSize = m_xLineStyleLb->CalcWindowSizePixel(aSize); + m_xLineStyleLb->GetDrawingArea()->set_size_request(aSize.Width(), aSize.Height()); + m_xLineStyleLb->SetOutputSizePixel(aSize); +} + +IMPL_LINK_NOARG(SvxLineWindow_Impl, SelectHdl, ValueSet*, void) +{ + SvxLineItem aLineItem( SID_FRAME_LINESTYLE ); + SvxBorderLineStyle nStyle = m_xLineStyleLb->GetSelectEntryStyle(); + + if ( m_xLineStyleLb->GetSelectItemPos( ) > 0 ) + { + SvxBorderLine aTmp; + aTmp.SetBorderLineStyle( nStyle ); + aTmp.SetWidth( 20 ); // TODO Make it depend on a width field + aLineItem.SetLine( &aTmp ); + } + else + aLineItem.SetLine( nullptr ); + + Any a; + Sequence< PropertyValue > aArgs( 1 ); + aArgs[0].Name = "LineStyle"; + aLineItem.QueryValue( a, m_bIsWriter ? CONVERT_TWIPS : 0 ); + aArgs[0].Value = a; + + m_xControl->dispatchCommand( ".uno:LineStyle", aArgs ); + + m_xControl->EndPopupMode(); +} + +SfxStyleControllerItem_Impl::SfxStyleControllerItem_Impl( + const Reference< XDispatchProvider >& rDispatchProvider, + sal_uInt16 nSlotId, // Family-ID + const OUString& rCommand, // .uno: command bound to this item + SvxStyleToolBoxControl& rTbxCtl ) // controller instance, which the item is assigned to. + : SfxStatusListener( rDispatchProvider, nSlotId, rCommand ), + rControl( rTbxCtl ) +{ +} + +void SfxStyleControllerItem_Impl::StateChanged( + SfxItemState eState, const SfxPoolItem* pState ) +{ + switch ( GetId() ) + { + case SID_STYLE_FAMILY1: + case SID_STYLE_FAMILY2: + case SID_STYLE_FAMILY3: + case SID_STYLE_FAMILY4: + case SID_STYLE_FAMILY5: + { + const sal_uInt16 nIdx = GetId() - SID_STYLE_FAMILY_START; + + if ( SfxItemState::DEFAULT == eState ) + { + const SfxTemplateItem* pStateItem = + dynamic_cast<const SfxTemplateItem*>( pState ); + DBG_ASSERT( pStateItem != nullptr, "SfxTemplateItem expected" ); + rControl.SetFamilyState( nIdx, pStateItem ); + } + else + rControl.SetFamilyState( nIdx, nullptr ); + break; + } + } +} + +struct SvxStyleToolBoxControl::Impl +{ + OUString aClearForm; + OUString aMore; + ::std::vector< OUString > aDefaultStyles; + bool bSpecModeWriter; + bool bSpecModeCalc; + + VclPtr<SvxStyleBox_Impl> m_xVclBox; + std::unique_ptr<SvxStyleBox_Base> m_xWeldBox; + SvxStyleBox_Base* m_pBox; + + Impl() + :aClearForm ( SvxResId( RID_SVXSTR_CLEARFORM ) ) + ,aMore ( SvxResId( RID_SVXSTR_MORE_STYLES ) ) + ,bSpecModeWriter ( false ) + ,bSpecModeCalc ( false ) + ,m_pBox ( nullptr ) + { + + + } + void InitializeStyles(const Reference < frame::XModel >& xModel) + { + aDefaultStyles.clear(); + + //now convert the default style names to the localized names + try + { + Reference< style::XStyleFamiliesSupplier > xStylesSupplier( xModel, UNO_QUERY_THROW ); + Reference< lang::XServiceInfo > xServices( xModel, UNO_QUERY_THROW ); + bSpecModeWriter = xServices->supportsService("com.sun.star.text.TextDocument"); + if(bSpecModeWriter) + { + Reference<container::XNameAccess> xParaStyles; + xStylesSupplier->getStyleFamilies()->getByName("ParagraphStyles") >>= + xParaStyles; + static const std::vector<OUString> aWriterStyles = + { + "Standard", + "Text body", + "Title", + "Subtitle", + "Heading 1", + "Heading 2", + "Heading 3", + "Quotations" + }; + for( const OUString& aStyle: aWriterStyles ) + { + try + { + Reference< beans::XPropertySet > xStyle; + xParaStyles->getByName( aStyle ) >>= xStyle; + OUString sName; + xStyle->getPropertyValue("DisplayName") >>= sName; + if( !sName.isEmpty() ) + aDefaultStyles.push_back(sName); + } + catch( const uno::Exception& ) + {} + } + + } + else if( ( + bSpecModeCalc = xServices->supportsService( + "com.sun.star.sheet.SpreadsheetDocument"))) + { + static const char* aCalcStyles[] = + { + "Default", + "Heading1", + "Result", + "Result2" + }; + Reference<container::XNameAccess> xCellStyles; + xStylesSupplier->getStyleFamilies()->getByName("CellStyles") >>= xCellStyles; + for(const char* pCalcStyle : aCalcStyles) + { + try + { + const OUString sStyleName( OUString::createFromAscii( pCalcStyle ) ); + if( xCellStyles->hasByName( sStyleName ) ) + { + Reference< beans::XPropertySet > xStyle( xCellStyles->getByName( sStyleName), UNO_QUERY_THROW ); + OUString sName; + xStyle->getPropertyValue("DisplayName") >>= sName; + if( !sName.isEmpty() ) + aDefaultStyles.push_back(sName); + } + } + catch( const uno::Exception& ) + {} + } + } + } + catch(const uno::Exception& ) + { + OSL_FAIL("error while initializing style names"); + } + } +}; + +// mapping table from bound items. BE CAREFUL this table must be in the +// same order as the uno commands bound to the slots SID_STYLE_FAMILY1..n +// MAX_FAMILIES must also be correctly set! +static const char* StyleSlotToStyleCommand[MAX_FAMILIES] = +{ + ".uno:CharStyle", + ".uno:ParaStyle", + ".uno:FrameStyle", + ".uno:PageStyle", + ".uno:TemplateFamily5" +}; + +SvxStyleToolBoxControl::SvxStyleToolBoxControl() + : pImpl(new Impl) + , pStyleSheetPool(nullptr) + , nActFamily(0xffff) +{ + for (sal_uInt16 i = 0; i < MAX_FAMILIES; ++i) + { + pBoundItems[i] = nullptr; + m_xBoundItems[i].clear(); + pFamilyState[i] = nullptr; + } +} + +SvxStyleToolBoxControl::~SvxStyleToolBoxControl() +{ +} + +void SAL_CALL SvxStyleToolBoxControl::initialize(const Sequence<Any>& rArguments) +{ + svt::ToolboxController::initialize(rArguments); + + // After initialize we should have a valid frame member where we can retrieve our + // dispatch provider. + if ( m_xFrame.is() ) + { + pImpl->InitializeStyles(m_xFrame->getController()->getModel()); + Reference< XDispatchProvider > xDispatchProvider( m_xFrame->getController(), UNO_QUERY ); + for ( sal_uInt16 i=0; i<MAX_FAMILIES; i++ ) + { + pBoundItems[i] = new SfxStyleControllerItem_Impl( xDispatchProvider, + SID_STYLE_FAMILY_START + i, + OUString::createFromAscii( StyleSlotToStyleCommand[i] ), + *this ); + m_xBoundItems[i].set( static_cast< OWeakObject* >( pBoundItems[i] ), UNO_QUERY ); + pFamilyState[i] = nullptr; + } + } +} + +// XComponent +void SAL_CALL SvxStyleToolBoxControl::dispose() +{ + svt::ToolboxController::dispose(); + + SolarMutexGuard aSolarMutexGuard; + pImpl->m_xVclBox.disposeAndClear(); + pImpl->m_xWeldBox.reset(); + pImpl->m_pBox = nullptr; + + for (SfxStyleControllerItem_Impl* pBoundItem : pBoundItems) + { + if (!pBoundItem) + continue; + pBoundItem->UnBind(); + } + unbindListener(); + + for( sal_uInt16 i=0; i<MAX_FAMILIES; i++ ) + { + if ( m_xBoundItems[i].is() ) + { + try + { + m_xBoundItems[i]->dispose(); + } + catch ( Exception& ) + { + } + + m_xBoundItems[i].clear(); + pBoundItems[i] = nullptr; + } + pFamilyState[i].reset(); + } + pStyleSheetPool = nullptr; + pImpl.reset(); +} + +OUString SvxStyleToolBoxControl::getImplementationName() +{ + return "com.sun.star.comp.svx.StyleToolBoxControl"; +} + +sal_Bool SvxStyleToolBoxControl::supportsService( const OUString& rServiceName ) +{ + return cppu::supportsService( this, rServiceName ); +} + +css::uno::Sequence< OUString > SvxStyleToolBoxControl::getSupportedServiceNames() +{ + return { "com.sun.star.frame.ToolbarController" }; +} + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * +com_sun_star_comp_svx_StyleToolBoxControl_get_implementation( + css::uno::XComponentContext*, + css::uno::Sequence<css::uno::Any> const & ) +{ + return cppu::acquire( new SvxStyleToolBoxControl() ); +} + +void SAL_CALL SvxStyleToolBoxControl::update() +{ + for (SfxStyleControllerItem_Impl* pBoundItem : pBoundItems) + pBoundItem->ReBind(); + bindListener(); +} + +SfxStyleFamily SvxStyleToolBoxControl::GetActFamily() const +{ + switch ( nActFamily-1 + SID_STYLE_FAMILY_START ) + { + case SID_STYLE_FAMILY1: return SfxStyleFamily::Char; + case SID_STYLE_FAMILY2: return SfxStyleFamily::Para; + case SID_STYLE_FAMILY3: return SfxStyleFamily::Frame; + case SID_STYLE_FAMILY4: return SfxStyleFamily::Page; + case SID_STYLE_FAMILY5: return SfxStyleFamily::Pseudo; + default: + OSL_FAIL( "unknown style family" ); + break; + } + return SfxStyleFamily::Para; +} + +void SvxStyleToolBoxControl::FillStyleBox() +{ + SvxStyleBox_Base* pBox = pImpl->m_pBox; + + DBG_ASSERT( pStyleSheetPool, "StyleSheetPool not found!" ); + DBG_ASSERT( pBox, "Control not found!" ); + + if ( pStyleSheetPool && pBox && nActFamily!=0xffff ) + { + const SfxStyleFamily eFamily = GetActFamily(); + SfxStyleSheetBase* pStyle = nullptr; + bool bDoFill = false; + + auto xIter = pStyleSheetPool->CreateIterator(eFamily, SfxStyleSearchBits::Used); + sal_uInt16 nCount = xIter->Count(); + + // Check whether fill is necessary + pStyle = xIter->First(); + //!!! TODO: This condition isn't right any longer, because we always show some default entries + //!!! so the list doesn't show the count + if ( nCount != pBox->get_count() ) + { + bDoFill = true; + } + else + { + sal_uInt16 i= 0; + while ( pStyle && !bDoFill ) + { + bDoFill = ( pBox->get_text(i) != pStyle->GetName() ); + pStyle = xIter->Next(); + i++; + } + } + + if ( bDoFill ) + { + OUString aStrSel(pBox->get_active_text()); + pBox->freeze(); + pBox->clear(); + + std::vector<OUString> aStyles; + + { + pStyle = xIter->Next(); + + if( pImpl->bSpecModeWriter || pImpl->bSpecModeCalc ) + { + while ( pStyle ) + { + // sort out default styles + bool bInsert = true; + OUString aName( pStyle->GetName() ); + for( auto const & _i: pImpl->aDefaultStyles ) + { + if( _i == aName ) + { + bInsert = false; + break; + } + } + + if( bInsert ) + aStyles.push_back(aName); + pStyle = xIter->Next(); + } + } + else + { + while ( pStyle ) + { + aStyles.push_back(pStyle->GetName()); + pStyle = xIter->Next(); + } + } + } + + if (pImpl->bSpecModeWriter || pImpl->bSpecModeCalc) + { + pBox->append_text(pImpl->aClearForm); + pBox->insert_separator(1, "separator"); + + // insert default styles + for (const auto &rStyle : pImpl->aDefaultStyles) + pBox->append_text(rStyle); + } + + std::sort(aStyles.begin(), aStyles.end()); + + for (const auto& rStyle : aStyles) + pBox->append_text(rStyle); + + if (pImpl->bSpecModeWriter || pImpl->bSpecModeCalc) + pBox->append_text(pImpl->aMore); + + pBox->thaw(); + pBox->set_active_or_entry_text(aStrSel); + pBox->SetFamily( eFamily ); + } + } +} + +void SvxStyleToolBoxControl::SelectStyle( const OUString& rStyleName ) +{ + SvxStyleBox_Base* pBox = pImpl->m_pBox; + DBG_ASSERT( pBox, "Control not found!" ); + + if ( pBox ) + { + OUString aStrSel(pBox->get_active_text()); + + if ( !rStyleName.isEmpty() ) + { + if ( rStyleName != aStrSel ) + pBox->set_active_or_entry_text( rStyleName ); + } + else + pBox->set_active(-1); + pBox->save_value(); + } +} + +void SvxStyleToolBoxControl::Update() +{ + SfxStyleSheetBasePool* pPool = nullptr; + SfxObjectShell* pDocShell = SfxObjectShell::Current(); + + if ( pDocShell ) + pPool = pDocShell->GetStyleSheetPool(); + + sal_uInt16 i; + for ( i=0; i<MAX_FAMILIES; i++ ) + if( pFamilyState[i] ) + break; + + if ( i==MAX_FAMILIES || !pPool ) + { + pStyleSheetPool = pPool; + return; + } + + + const SfxTemplateItem* pItem = nullptr; + + if ( nActFamily == 0xffff || nullptr == (pItem = pFamilyState[nActFamily-1].get()) ) + // Current range not within allowed ranges or default + { + pStyleSheetPool = pPool; + nActFamily = 2; + + pItem = pFamilyState[nActFamily-1].get(); + if ( !pItem ) + { + nActFamily++; + pItem = pFamilyState[nActFamily-1].get(); + } + } + else if ( pPool != pStyleSheetPool ) + pStyleSheetPool = pPool; + + FillStyleBox(); // Decides by itself whether Fill is needed + + if ( pItem ) + SelectStyle( pItem->GetStyleName() ); +} + +void SvxStyleToolBoxControl::SetFamilyState( sal_uInt16 nIdx, + const SfxTemplateItem* pItem ) +{ + pFamilyState[nIdx].reset( pItem == nullptr ? nullptr : new SfxTemplateItem( *pItem ) ); + Update(); +} + +void SvxStyleToolBoxControl::statusChanged( const css::frame::FeatureStateEvent& rEvent ) +{ + SolarMutexGuard aGuard; + + if (m_pToolbar) + m_pToolbar->set_item_sensitive(m_aCommandURL.toUtf8(), rEvent.IsEnabled); + else + { + ToolBox* pToolBox = nullptr; + sal_uInt16 nId = 0; + if (!getToolboxId( nId, &pToolBox ) ) + return; + pToolBox->EnableItem( nId, rEvent.IsEnabled ); + } + + if (rEvent.IsEnabled) + Update(); +} + +css::uno::Reference<css::awt::XWindow> SvxStyleToolBoxControl::createItemWindow(const css::uno::Reference< css::awt::XWindow>& rParent) +{ + uno::Reference< awt::XWindow > xItemWindow; + + if (m_pBuilder) + { + SolarMutexGuard aSolarMutexGuard; + + std::unique_ptr<weld::ComboBox> xWidget(m_pBuilder->weld_combo_box("applystyle")); + + xItemWindow = css::uno::Reference<css::awt::XWindow>(new weld::TransportAsXWindow(xWidget.get())); + + pImpl->m_xWeldBox.reset(new SvxStyleBox_Base(std::move(xWidget), + ".uno:StyleApply", + SfxStyleFamily::Para, + Reference< XDispatchProvider >( m_xFrame->getController(), UNO_QUERY ), + m_xFrame, + pImpl->aClearForm, + pImpl->aMore, + pImpl->bSpecModeWriter || pImpl->bSpecModeCalc, *this)); + pImpl->m_pBox = pImpl->m_xWeldBox.get(); + } + else + { + VclPtr<vcl::Window> pParent = VCLUnoHelper::GetWindow(rParent); + if ( pParent ) + { + SolarMutexGuard aSolarMutexGuard; + + pImpl->m_xVclBox = VclPtr<SvxStyleBox_Impl>::Create(pParent, + ".uno:StyleApply", + SfxStyleFamily::Para, + Reference< XDispatchProvider >( m_xFrame->getController(), UNO_QUERY ), + m_xFrame, + pImpl->aClearForm, + pImpl->aMore, + pImpl->bSpecModeWriter || pImpl->bSpecModeCalc, *this); + pImpl->m_pBox = pImpl->m_xVclBox.get(); + xItemWindow = VCLUnoHelper::GetInterface(pImpl->m_xVclBox); + } + } + + if (pImpl->m_pBox && !pImpl->aDefaultStyles.empty()) + pImpl->m_pBox->SetDefaultStyle(pImpl->aDefaultStyles[0]); + + return xItemWindow; +} + +SvxFontNameToolBoxControl::SvxFontNameToolBoxControl() + : m_pBox(nullptr) +{ +} + +void SvxFontNameBox_Base::statusChanged_Impl( const css::frame::FeatureStateEvent& rEvent ) +{ + if ( !rEvent.IsEnabled ) + { + set_sensitive(false); + Update( nullptr ); + } + else + { + set_sensitive(true); + + css::awt::FontDescriptor aFontDesc; + if ( rEvent.State >>= aFontDesc ) + Update(&aFontDesc); + else + set_active_or_entry_text(""); + m_xWidget->save_value(); + } +} + +void SvxFontNameToolBoxControl::statusChanged( const css::frame::FeatureStateEvent& rEvent ) +{ + SolarMutexGuard aGuard; + m_pBox->statusChanged_Impl(rEvent); + + if (m_pToolbar) + m_pToolbar->set_item_sensitive(m_aCommandURL.toUtf8(), rEvent.IsEnabled); + else + { + ToolBox* pToolBox = nullptr; + sal_uInt16 nId = 0; + if (!getToolboxId( nId, &pToolBox ) ) + return; + pToolBox->EnableItem( nId, rEvent.IsEnabled ); + } +} + +css::uno::Reference<css::awt::XWindow> SvxFontNameToolBoxControl::createItemWindow(const css::uno::Reference<css::awt::XWindow>& rParent) +{ + uno::Reference< awt::XWindow > xItemWindow; + + if (m_pBuilder) + { + SolarMutexGuard aSolarMutexGuard; + + std::unique_ptr<weld::ComboBox> xWidget(m_pBuilder->weld_combo_box("fontnamecombobox")); + + xItemWindow = css::uno::Reference<css::awt::XWindow>(new weld::TransportAsXWindow(xWidget.get())); + + m_xWeldBox.reset(new SvxFontNameBox_Base(std::move(xWidget), + Reference<XDispatchProvider>(m_xFrame->getController(), UNO_QUERY), + m_xFrame, *this)); + m_pBox = m_xWeldBox.get(); + } + else + { + VclPtr<vcl::Window> pParent = VCLUnoHelper::GetWindow(rParent); + if ( pParent ) + { + SolarMutexGuard aSolarMutexGuard; + m_xVclBox = VclPtr<SvxFontNameBox_Impl>::Create(pParent, + Reference<XDispatchProvider>(m_xFrame->getController(), UNO_QUERY), + m_xFrame, *this); + m_pBox = m_xVclBox.get(); + xItemWindow = VCLUnoHelper::GetInterface(m_xVclBox); + } + } + + return xItemWindow; +} + +void SvxFontNameToolBoxControl::dispose() +{ + ToolboxController::dispose(); + + SolarMutexGuard aSolarMutexGuard; + m_xVclBox.disposeAndClear(); + m_xWeldBox.reset(); + m_pBox = nullptr; +} + +OUString SvxFontNameToolBoxControl::getImplementationName() +{ + return "com.sun.star.comp.svx.FontNameToolBoxControl"; +} + +sal_Bool SvxFontNameToolBoxControl::supportsService( const OUString& rServiceName ) +{ + return cppu::supportsService( this, rServiceName ); +} + +css::uno::Sequence< OUString > SvxFontNameToolBoxControl::getSupportedServiceNames() +{ + return { "com.sun.star.frame.ToolbarController" }; +} + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * +com_sun_star_comp_svx_FontNameToolBoxControl_get_implementation( + css::uno::XComponentContext*, + css::uno::Sequence<css::uno::Any> const & ) +{ + return cppu::acquire( new SvxFontNameToolBoxControl() ); +} + +SvxColorToolBoxControl::SvxColorToolBoxControl( const css::uno::Reference<css::uno::XComponentContext>& rContext ) : + ImplInheritanceHelper( rContext, nullptr, OUString() ), + m_bSplitButton(true), + m_nSlotId(0), + m_aColorSelectFunction(PaletteManager::DispatchColorCommand) +{ +} + +namespace { + +sal_uInt16 MapCommandToSlotId(const OUString& rCommand) +{ + if (rCommand == ".uno:Color") + return SID_ATTR_CHAR_COLOR; + else if (rCommand == ".uno:FontColor") + return SID_ATTR_CHAR_COLOR2; + else if (rCommand == ".uno:BackColor") + return SID_ATTR_CHAR_COLOR_BACKGROUND; + else if (rCommand == ".uno:CharBackColor") + return SID_ATTR_CHAR_BACK_COLOR; + else if (rCommand == ".uno:BackgroundColor") + return SID_BACKGROUND_COLOR; + else if (rCommand == ".uno:TableCellBackgroundColor") + return SID_TABLE_CELL_BACKGROUND_COLOR; + else if (rCommand == ".uno:Extrusion3DColor") + return SID_EXTRUSION_3D_COLOR; + else if (rCommand == ".uno:XLineColor") + return SID_ATTR_LINE_COLOR; + else if (rCommand == ".uno:FillColor") + return SID_ATTR_FILL_COLOR; + else if (rCommand == ".uno:FrameLineColor") + return SID_FRAME_LINECOLOR; + + SAL_WARN("svx.tbxcrtls", "Unknown color command: " << rCommand); + return 0; +} + +} + +void SvxColorToolBoxControl::initialize( const css::uno::Sequence<css::uno::Any>& rArguments ) +{ + PopupWindowController::initialize( rArguments ); + + m_nSlotId = MapCommandToSlotId( m_aCommandURL ); + + if ( m_nSlotId == SID_ATTR_LINE_COLOR || m_nSlotId == SID_ATTR_FILL_COLOR || + m_nSlotId == SID_FRAME_LINECOLOR || m_nSlotId == SID_BACKGROUND_COLOR ) + { + // Sidebar uses wide buttons for those. + m_bSplitButton = !m_bSidebar; + } + + auto aProperties = vcl::CommandInfoProvider::GetCommandProperties(getCommandURL(), getModuleName()); + OUString aCommandLabel = vcl::CommandInfoProvider::GetLabelForCommand(aProperties); + + OString aId(m_aCommandURL.toUtf8()); + + if (m_pToolbar) + { + mxPopoverContainer.reset(new ToolbarPopupContainer(m_pToolbar)); + m_pToolbar->set_item_popover(aId, mxPopoverContainer->getTopLevel()); + m_xBtnUpdater.reset(new svx::ToolboxButtonColorUpdater(m_nSlotId, aId, m_pToolbar, !m_bSplitButton, aCommandLabel, m_xFrame)); + return; + } + + ToolBox* pToolBox = nullptr; + sal_uInt16 nId = 0; + if (getToolboxId(nId, &pToolBox)) + { + m_xBtnUpdater.reset( new svx::VclToolboxButtonColorUpdater( m_nSlotId, nId, pToolBox, !m_bSplitButton, aCommandLabel, m_aCommandURL, m_xFrame ) ); + pToolBox->SetItemBits( nId, pToolBox->GetItemBits( nId ) | ( m_bSplitButton ? ToolBoxItemBits::DROPDOWN : ToolBoxItemBits::DROPDOWNONLY ) ); + } +} + +void SvxColorToolBoxControl::update() +{ + PopupWindowController::update(); + + switch( m_nSlotId ) + { + case SID_ATTR_CHAR_COLOR2: + addStatusListener( ".uno:CharColorExt"); + break; + + case SID_ATTR_CHAR_COLOR_BACKGROUND: + addStatusListener( ".uno:CharBackgroundExt"); + break; + + case SID_FRAME_LINECOLOR: + addStatusListener( ".uno:BorderTLBR"); + addStatusListener( ".uno:BorderBLTR"); + break; + } +} + +void SvxColorToolBoxControl::EnsurePaletteManager() +{ + if (!m_xPaletteManager) + { + m_xPaletteManager = std::make_shared<PaletteManager>(); + m_xPaletteManager->SetBtnUpdater(m_xBtnUpdater.get()); + } +} + +SvxColorToolBoxControl::~SvxColorToolBoxControl() +{ + if (m_xPaletteManager) + m_xPaletteManager->SetBtnUpdater(nullptr); +} + +void SvxColorToolBoxControl::setColorSelectFunction(const ColorSelectFunction& aColorSelectFunction) +{ + m_aColorSelectFunction = aColorSelectFunction; + if (m_xPaletteManager) + m_xPaletteManager->SetColorSelectFunction(aColorSelectFunction); +} + +std::unique_ptr<WeldToolbarPopup> SvxColorToolBoxControl::weldPopupWindow() +{ + EnsurePaletteManager(); + + const css::uno::Reference<css::awt::XWindow> xParent = m_xFrame->getContainerWindow(); + weld::Window* pParentFrame = Application::GetFrameWeld(xParent); + + const OString aId(m_aCommandURL.toUtf8()); + + auto xPopover = std::make_unique<ColorWindow>( + m_aCommandURL, + m_xPaletteManager, + m_aColorStatus, + m_nSlotId, + m_xFrame, + pParentFrame, + MenuOrToolMenuButton(m_pToolbar, aId), + m_aColorSelectFunction); + + if ( m_bSplitButton ) + xPopover->SetSelectedHdl( LINK( this, SvxColorToolBoxControl, SelectedHdl ) ); + + return xPopover; +} + +VclPtr<vcl::Window> SvxColorToolBoxControl::createVclPopupWindow( vcl::Window* pParent ) +{ + ToolBox* pToolBox = nullptr; + sal_uInt16 nId = 0; + if (!getToolboxId(nId, &pToolBox)) + return nullptr; + + const css::uno::Reference<css::awt::XWindow> xParent = m_xFrame->getContainerWindow(); + weld::Window* pParentFrame = Application::GetFrameWeld(xParent); + + EnsurePaletteManager(); + + auto xPopover = std::make_unique<ColorWindow>( + m_aCommandURL, + m_xPaletteManager, + m_aColorStatus, + m_nSlotId, + m_xFrame, + pParentFrame, + MenuOrToolMenuButton(this, pToolBox, nId), + m_aColorSelectFunction); + + if ( m_bSplitButton ) + xPopover->SetSelectedHdl( LINK( this, SvxColorToolBoxControl, SelectedHdl ) ); + + mxInterimPopover = VclPtr<InterimToolbarPopup>::Create(getFrameInterface(), pParent, + std::move(xPopover), true); + + auto aProperties = vcl::CommandInfoProvider::GetCommandProperties(m_aCommandURL, m_sModuleName); + OUString aWindowTitle = vcl::CommandInfoProvider::GetLabelForCommand(aProperties); + mxInterimPopover->SetText(aWindowTitle); + + mxInterimPopover->Show(); + + return mxInterimPopover; +} + +IMPL_LINK(SvxColorToolBoxControl, SelectedHdl, const NamedColor&, rColor, void) +{ + m_xBtnUpdater->Update(rColor); +} + +void SvxColorToolBoxControl::statusChanged( const css::frame::FeatureStateEvent& rEvent ) +{ + ToolBox* pToolBox = nullptr; + sal_uInt16 nId = 0; + if (!getToolboxId(nId, &pToolBox) && !m_pToolbar) + return; + + if ( rEvent.FeatureURL.Complete == m_aCommandURL ) + { + if (m_pToolbar) + m_pToolbar->set_item_sensitive(m_aCommandURL.toUtf8(), rEvent.IsEnabled); + else + pToolBox->EnableItem( nId, rEvent.IsEnabled ); + } + + bool bValue; + if ( !m_bSplitButton ) + { + m_aColorStatus.statusChanged( rEvent ); + m_xBtnUpdater->Update( m_aColorStatus.GetColor() ); + } + else if ( rEvent.State >>= bValue ) + { + if (m_pToolbar) + m_pToolbar->set_item_active(m_aCommandURL.toUtf8(), bValue); + else if (pToolBox) + pToolBox->CheckItem( nId, bValue ); + } +} + +void SvxColorToolBoxControl::execute(sal_Int16 /*nSelectModifier*/) +{ + if ( !m_bSplitButton ) + { + if (m_pToolbar) + { + // Toggle the popup also when toolbutton is activated + const OString aId(m_aCommandURL.toUtf8()); + m_pToolbar->set_menu_item_active(aId, !m_pToolbar->get_menu_item_active(aId)); + } + else + { + // Open the popup also when Enter key is pressed. + createPopupWindow(); + } + return; + } + + OUString aCommand = m_aCommandURL; + Color aColor = m_xBtnUpdater->GetCurrentColor(); + + switch( m_nSlotId ) + { + case SID_ATTR_CHAR_COLOR2 : + aCommand = ".uno:CharColorExt"; + break; + + case SID_ATTR_CHAR_COLOR_BACKGROUND : + aCommand = ".uno:CharBackgroundExt"; + break; + } + + auto aArgs( comphelper::InitPropertySequence( { + { m_aCommandURL.copy(5), css::uno::makeAny(aColor) } + } ) ); + dispatchCommand( aCommand, aArgs ); + + EnsurePaletteManager(); + OUString sColorName = m_xBtnUpdater->GetCurrentColorName(); + m_xPaletteManager->AddRecentColor(aColor, sColorName); +} + +sal_Bool SvxColorToolBoxControl::opensSubToolbar() +{ + // We mark this controller as a sub-toolbar controller, so we get notified + // (through updateImage method) on button image changes, and could redraw + // the last used color on top of it. + return true; +} + +void SvxColorToolBoxControl::updateImage() +{ + m_xBtnUpdater->Update(m_xBtnUpdater->GetCurrentColor(), true); +} + +OUString SvxColorToolBoxControl::getSubToolbarName() +{ + return OUString(); +} + +void SvxColorToolBoxControl::functionSelected( const OUString& /*rCommand*/ ) +{ +} + +OUString SvxColorToolBoxControl::getImplementationName() +{ + return "com.sun.star.comp.svx.ColorToolBoxControl"; +} + +css::uno::Sequence<OUString> SvxColorToolBoxControl::getSupportedServiceNames() +{ + return { "com.sun.star.frame.ToolbarController" }; +} + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * +com_sun_star_comp_svx_ColorToolBoxControl_get_implementation( + css::uno::XComponentContext* rContext, + css::uno::Sequence<css::uno::Any> const & ) +{ + return cppu::acquire( new SvxColorToolBoxControl( rContext ) ); +} + +SvxFrameToolBoxControl::SvxFrameToolBoxControl( const css::uno::Reference< css::uno::XComponentContext >& rContext ) + : svt::PopupWindowController( rContext, nullptr, OUString() ) +{ +} + +void SAL_CALL SvxFrameToolBoxControl::execute(sal_Int16 /*KeyModifier*/) +{ + if (m_pToolbar) + { + // Toggle the popup also when toolbutton is activated + const OString aId(m_aCommandURL.toUtf8()); + m_pToolbar->set_menu_item_active(aId, !m_pToolbar->get_menu_item_active(aId)); + } + else + { + // Open the popup also when Enter key is pressed. + createPopupWindow(); + } +} + +void SvxFrameToolBoxControl::initialize( const css::uno::Sequence< css::uno::Any >& rArguments ) +{ + svt::PopupWindowController::initialize( rArguments ); + + if (m_pToolbar) + { + mxPopoverContainer.reset(new ToolbarPopupContainer(m_pToolbar)); + m_pToolbar->set_item_popover(m_aCommandURL.toUtf8(), mxPopoverContainer->getTopLevel()); + } + + ToolBox* pToolBox = nullptr; + sal_uInt16 nId = 0; + if (getToolboxId(nId, &pToolBox)) + pToolBox->SetItemBits( nId, pToolBox->GetItemBits( nId ) | ToolBoxItemBits::DROPDOWNONLY ); +} + +std::unique_ptr<WeldToolbarPopup> SvxFrameToolBoxControl::weldPopupWindow() +{ + if ( m_aCommandURL == ".uno:LineStyle" ) + return std::make_unique<SvxLineWindow_Impl>(this, m_pToolbar); + return std::make_unique<SvxFrameWindow_Impl>(this, m_pToolbar); +} + +VclPtr<vcl::Window> SvxFrameToolBoxControl::createVclPopupWindow( vcl::Window* pParent ) +{ + if ( m_aCommandURL == ".uno:LineStyle" ) + { + mxInterimPopover = VclPtr<InterimToolbarPopup>::Create(getFrameInterface(), pParent, + std::make_unique<SvxLineWindow_Impl>(this, pParent->GetFrameWeld())); + + mxInterimPopover->Show(); + + mxInterimPopover->SetText(SvxResId(RID_SVXSTR_FRAME_STYLE)); + + return mxInterimPopover; + } + + mxInterimPopover = VclPtr<InterimToolbarPopup>::Create(getFrameInterface(), pParent, + std::make_unique<SvxFrameWindow_Impl>(this, pParent->GetFrameWeld())); + + mxInterimPopover->Show(); + + mxInterimPopover->SetText(SvxResId(RID_SVXSTR_FRAME)); + + return mxInterimPopover; +} + +OUString SvxFrameToolBoxControl::getImplementationName() +{ + return "com.sun.star.comp.svx.FrameToolBoxControl"; +} + +css::uno::Sequence< OUString > SvxFrameToolBoxControl::getSupportedServiceNames() +{ + return { "com.sun.star.frame.ToolbarController" }; +} + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * +com_sun_star_comp_svx_FrameToolBoxControl_get_implementation( + css::uno::XComponentContext* rContext, + css::uno::Sequence<css::uno::Any> const & ) +{ + return cppu::acquire( new SvxFrameToolBoxControl( rContext ) ); +} + +SvxCurrencyToolBoxControl::SvxCurrencyToolBoxControl( const css::uno::Reference<css::uno::XComponentContext>& rContext ) : + PopupWindowController( rContext, nullptr, OUString() ), + m_eLanguage( Application::GetSettings().GetLanguageTag().getLanguageType() ), + m_nFormatKey( NUMBERFORMAT_ENTRY_NOT_FOUND ) +{ +} + +SvxCurrencyToolBoxControl::~SvxCurrencyToolBoxControl() {} + +namespace +{ + class SvxCurrencyList_Impl : public WeldToolbarPopup + { + private: + rtl::Reference<SvxCurrencyToolBoxControl> m_xControl; + std::unique_ptr<weld::Label> m_xLabel; + std::unique_ptr<weld::TreeView> m_xCurrencyLb; + std::unique_ptr<weld::Button> m_xOkBtn; + OUString& m_rSelectedFormat; + LanguageType& m_eSelectedLanguage; + + std::vector<OUString> m_aFormatEntries; + LanguageType m_eFormatLanguage; + DECL_LINK(RowActivatedHdl, weld::TreeView&, bool); + DECL_LINK(OKHdl, weld::Button&, void); + + virtual void GrabFocus() override; + + public: + SvxCurrencyList_Impl(SvxCurrencyToolBoxControl* pControl, weld::Widget* pParent, OUString& rSelectedFormat, LanguageType& eSelectedLanguage) + : WeldToolbarPopup(pControl->getFrameInterface(), pParent, "svx/ui/currencywindow.ui", "CurrencyWindow") + , m_xControl(pControl) + , m_xLabel(m_xBuilder->weld_label("label")) + , m_xCurrencyLb(m_xBuilder->weld_tree_view("currency")) + , m_xOkBtn(m_xBuilder->weld_button("ok")) + , m_rSelectedFormat(rSelectedFormat) + , m_eSelectedLanguage(eSelectedLanguage) + { + std::vector< OUString > aList; + std::vector< sal_uInt16 > aCurrencyList; + const NfCurrencyTable& rCurrencyTable = SvNumberFormatter::GetTheCurrencyTable(); + sal_uInt16 nLen = rCurrencyTable.size(); + + SvNumberFormatter aFormatter( m_xControl->getContext(), LANGUAGE_SYSTEM ); + m_eFormatLanguage = aFormatter.GetLanguage(); + + SvxCurrencyToolBoxControl::GetCurrencySymbols( aList, true, aCurrencyList ); + + sal_uInt16 nPos = 0, nCount = 0; + sal_Int32 nSelectedPos = -1; + bool bIsSymbol; + NfWSStringsDtor aStringsDtor; + + OUString sLongestString; + + m_xCurrencyLb->freeze(); + for( const auto& rItem : aList ) + { + sal_uInt16& rCurrencyIndex = aCurrencyList[ nCount ]; + if ( rCurrencyIndex < nLen ) + { + m_xCurrencyLb->append_text(rItem); + + if (rItem.getLength() > sLongestString.getLength()) + sLongestString = rItem; + + const NfCurrencyEntry& aCurrencyEntry = rCurrencyTable[ rCurrencyIndex ]; + + bIsSymbol = nPos >= nLen; + + sal_uInt16 nDefaultFormat = aFormatter.GetCurrencyFormatStrings( aStringsDtor, aCurrencyEntry, bIsSymbol ); + const OUString& rFormatStr = aStringsDtor[ nDefaultFormat ]; + m_aFormatEntries.push_back( rFormatStr ); + if( rFormatStr == m_rSelectedFormat ) + nSelectedPos = nPos; + ++nPos; + } + ++nCount; + } + m_xCurrencyLb->thaw(); + // enable multiple selection enabled so we can start with nothing selected + m_xCurrencyLb->set_selection_mode(SelectionMode::Multiple); + m_xCurrencyLb->connect_row_activated( LINK( this, SvxCurrencyList_Impl, RowActivatedHdl ) ); + m_xLabel->set_label(SvxResId(RID_SVXSTR_TBLAFMT_CURRENCY)); + m_xCurrencyLb->select( nSelectedPos ); + m_xOkBtn->connect_clicked(LINK(this, SvxCurrencyList_Impl, OKHdl)); + + // gtk will initially make a best guess depending on the first few entries, so copy the probable + // longest entry to the start temporarily and force in the width at this point + m_xCurrencyLb->insert_text(0, sLongestString); + m_xCurrencyLb->set_size_request(m_xCurrencyLb->get_preferred_size().Width(), m_xCurrencyLb->get_height_rows(12)); + m_xCurrencyLb->remove(0); + } + }; + + void SvxCurrencyList_Impl::GrabFocus() + { + m_xCurrencyLb->grab_focus(); + } + + IMPL_LINK_NOARG(SvxCurrencyList_Impl, OKHdl, weld::Button&, void) + { + RowActivatedHdl(*m_xCurrencyLb); + } + + IMPL_LINK_NOARG(SvxCurrencyList_Impl, RowActivatedHdl, weld::TreeView&, bool) + { + if (!m_xControl.is()) + return true; + + // multiple selection enabled so we can start with nothing selected, + // so force single selection after something is picked + int nSelected = m_xCurrencyLb->get_selected_index(); + if (nSelected == -1) + return true; + + m_xCurrencyLb->set_selection_mode(SelectionMode::Single); + + m_rSelectedFormat = m_aFormatEntries[nSelected]; + m_eSelectedLanguage = m_eFormatLanguage; + + m_xControl->execute(nSelected + 1); + + m_xControl->EndPopupMode(); + + return true; + } +} + +void SvxCurrencyToolBoxControl::initialize( const css::uno::Sequence< css::uno::Any >& rArguments ) +{ + PopupWindowController::initialize(rArguments); + + if (m_pToolbar) + { + mxPopoverContainer.reset(new ToolbarPopupContainer(m_pToolbar)); + m_pToolbar->set_item_popover(m_aCommandURL.toUtf8(), mxPopoverContainer->getTopLevel()); + return; + } + + ToolBox* pToolBox = nullptr; + sal_uInt16 nId = 0; + if (getToolboxId(nId, &pToolBox) && pToolBox->GetItemCommand(nId) == m_aCommandURL) + pToolBox->SetItemBits(nId, ToolBoxItemBits::DROPDOWN | pToolBox->GetItemBits(nId)); +} + +std::unique_ptr<WeldToolbarPopup> SvxCurrencyToolBoxControl::weldPopupWindow() +{ + return std::make_unique<SvxCurrencyList_Impl>(this, m_pToolbar, m_aFormatString, m_eLanguage); +} + +VclPtr<vcl::Window> SvxCurrencyToolBoxControl::createVclPopupWindow( vcl::Window* pParent ) +{ + mxInterimPopover = VclPtr<InterimToolbarPopup>::Create(getFrameInterface(), pParent, + std::make_unique<SvxCurrencyList_Impl>(this, pParent->GetFrameWeld(), m_aFormatString, m_eLanguage)); + + mxInterimPopover->Show(); + + return mxInterimPopover; +} + +void SvxCurrencyToolBoxControl::execute( sal_Int16 nSelectModifier ) +{ + sal_uInt32 nFormatKey; + if (m_aFormatString.isEmpty()) + nFormatKey = NUMBERFORMAT_ENTRY_NOT_FOUND; + else + { + if ( nSelectModifier > 0 ) + { + try + { + uno::Reference< util::XNumberFormatsSupplier > xRef( m_xFrame->getController()->getModel(), uno::UNO_QUERY ); + uno::Reference< util::XNumberFormats > rxNumberFormats( xRef->getNumberFormats(), uno::UNO_SET_THROW ); + css::lang::Locale aLocale = LanguageTag::convertToLocale( m_eLanguage ); + nFormatKey = rxNumberFormats->queryKey( m_aFormatString, aLocale, false ); + if ( nFormatKey == NUMBERFORMAT_ENTRY_NOT_FOUND ) + nFormatKey = rxNumberFormats->addNew( m_aFormatString, aLocale ); + } + catch( const uno::Exception& ) + { + nFormatKey = m_nFormatKey; + } + } + else + nFormatKey = m_nFormatKey; + } + + if( nFormatKey != NUMBERFORMAT_ENTRY_NOT_FOUND ) + { + Sequence< PropertyValue > aArgs( 1 ); + aArgs[0].Name = "NumberFormatCurrency"; + aArgs[0].Value <<= nFormatKey; + dispatchCommand( m_aCommandURL, aArgs ); + m_nFormatKey = nFormatKey; + } + else + PopupWindowController::execute( nSelectModifier ); +} + +OUString SvxCurrencyToolBoxControl::getImplementationName() +{ + return "com.sun.star.comp.svx.CurrencyToolBoxControl"; +} + +css::uno::Sequence<OUString> SvxCurrencyToolBoxControl::getSupportedServiceNames() +{ + return { "com.sun.star.frame.ToolbarController" }; +} + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * +com_sun_star_comp_svx_CurrencyToolBoxControl_get_implementation( + css::uno::XComponentContext* rContext, + css::uno::Sequence<css::uno::Any> const & ) +{ + return cppu::acquire( new SvxCurrencyToolBoxControl( rContext ) ); +} + +Reference< css::accessibility::XAccessible > SvxFontNameBox_Impl::CreateAccessible() +{ + FillList(); + return InterimItemWindow::CreateAccessible(); +} + +//static +void SvxCurrencyToolBoxControl::GetCurrencySymbols( std::vector<OUString>& rList, bool bFlag, + std::vector<sal_uInt16>& rCurrencyList ) +{ + rCurrencyList.clear(); + + const NfCurrencyTable& rCurrencyTable = SvNumberFormatter::GetTheCurrencyTable(); + sal_uInt16 nCount = rCurrencyTable.size(); + + sal_uInt16 nStart = 1; + + OUString aString( ApplyLreOrRleEmbedding( rCurrencyTable[0].GetSymbol() ) + " " ); + aString += ApplyLreOrRleEmbedding( SvtLanguageTable::GetLanguageString( + rCurrencyTable[0].GetLanguage() ) ); + + rList.push_back( aString ); + rCurrencyList.push_back( sal_uInt16(-1) ); // nAuto + + if( bFlag ) + { + rList.push_back( aString ); + rCurrencyList.push_back( 0 ); + ++nStart; + } + + CollatorWrapper aCollator( ::comphelper::getProcessComponentContext() ); + aCollator.loadDefaultCollator( Application::GetSettings().GetLanguageTag().getLocale(), 0 ); + + const OUString aTwoSpace(" "); + + for( sal_uInt16 i = 1; i < nCount; ++i ) + { + OUString aStr( ApplyLreOrRleEmbedding( rCurrencyTable[i].GetBankSymbol() ) ); + aStr += aTwoSpace; + aStr += ApplyLreOrRleEmbedding( rCurrencyTable[i].GetSymbol() ); + aStr += aTwoSpace; + aStr += ApplyLreOrRleEmbedding( SvtLanguageTable::GetLanguageString( + rCurrencyTable[i].GetLanguage() ) ); + + std::vector<OUString>::size_type j = nStart; + for( ; j < rList.size(); ++j ) + if ( aCollator.compareString( aStr, rList[j] ) < 0 ) + break; // insert before first greater than + + rList.insert( rList.begin() + j, aStr ); + rCurrencyList.insert( rCurrencyList.begin() + j, i ); + } + + // Append ISO codes to symbol list. + // XXX If this is to be changed, various other places would had to be + // adapted that assume this order! + std::vector<OUString>::size_type nCont = rList.size(); + + for ( sal_uInt16 i = 1; i < nCount; ++i ) + { + bool bInsert = true; + OUString aStr( ApplyLreOrRleEmbedding( rCurrencyTable[i].GetBankSymbol() ) ); + + std::vector<OUString>::size_type j = nCont; + for ( ; j < rList.size() && bInsert; ++j ) + { + if( rList[j] == aStr ) + bInsert = false; + else if ( aCollator.compareString( aStr, rList[j] ) < 0 ) + break; // insert before first greater than + } + if ( bInsert ) + { + rList.insert( rList.begin() + j, aStr ); + rCurrencyList.insert( rCurrencyList.begin() + j, i ); + } + } +} + +ListBoxColorWrapper::ListBoxColorWrapper(ColorListBox* pControl) + : mpControl(pControl) +{ +} + +void ListBoxColorWrapper::operator()(const OUString& /*rCommand*/, const NamedColor& rColor) +{ + mpControl->Selected(rColor); +} + +void ColorListBox::EnsurePaletteManager() +{ + if (!m_xPaletteManager) + { + m_xPaletteManager = std::make_shared<PaletteManager>(); + m_xPaletteManager->SetColorSelectFunction(std::ref(m_aColorWrapper)); + } +} + +void ColorListBox::SetSlotId(sal_uInt16 nSlotId, bool bShowNoneButton) +{ + m_nSlotId = nSlotId; + m_bShowNoneButton = bShowNoneButton; + m_xButton->set_popover(nullptr); + m_xColorWindow.reset(); + m_aSelectedColor = bShowNoneButton ? GetNoneColor() : GetAutoColor(m_nSlotId); + ShowPreview(m_aSelectedColor); + createColorWindow(); +} + +ColorListBox::ColorListBox(std::unique_ptr<weld::MenuButton> pControl, weld::Window* pTopLevel) + : m_xButton(std::move(pControl)) + , m_pTopLevel(pTopLevel) + , m_aColorWrapper(this) + , m_aAutoDisplayColor(Application::GetSettings().GetStyleSettings().GetDialogColor()) + , m_nSlotId(0) + , m_bShowNoneButton(false) +{ + m_xButton->connect_toggled(LINK(this, ColorListBox, ToggleHdl)); + m_aSelectedColor = GetAutoColor(m_nSlotId); + LockWidthRequest(); + ShowPreview(m_aSelectedColor); +} + +IMPL_LINK(ColorListBox, ToggleHdl, weld::ToggleButton&, rButton, void) +{ + if (rButton.get_active()) + getColorWindow()->GrabFocus(); +} + +ColorListBox::~ColorListBox() +{ +} + +ColorWindow* ColorListBox::getColorWindow() const +{ + if (!m_xColorWindow) + const_cast<ColorListBox*>(this)->createColorWindow(); + return m_xColorWindow.get(); +} + +void ColorListBox::createColorWindow() +{ + const SfxViewFrame* pViewFrame = SfxViewFrame::Current(); + const SfxFrame* pFrame = pViewFrame ? &pViewFrame->GetFrame() : nullptr; + css::uno::Reference<css::frame::XFrame> xFrame(pFrame ? pFrame->GetFrameInterface() : uno::Reference<css::frame::XFrame>()); + + EnsurePaletteManager(); + + m_xColorWindow.reset(new ColorWindow( + OUString() /*m_aCommandURL*/, + m_xPaletteManager, + m_aColorStatus, + m_nSlotId, + xFrame, + m_pTopLevel, + m_xButton.get(), + m_aColorWrapper)); + + SetNoSelection(); + m_xButton->set_popover(m_xColorWindow->getTopLevel()); + if (m_bShowNoneButton) + m_xColorWindow->ShowNoneButton(); + m_xColorWindow->SelectEntry(m_aSelectedColor); +} + +void ColorListBox::SelectEntry(const NamedColor& rColor) +{ + if (rColor.second.trim().isEmpty()) + { + SelectEntry(rColor.first); + return; + } + ColorWindow* pColorWindow = getColorWindow(); + pColorWindow->SelectEntry(rColor); + m_aSelectedColor = pColorWindow->GetSelectEntryColor(); + ShowPreview(m_aSelectedColor); +} + +void ColorListBox::SelectEntry(const Color& rColor) +{ + ColorWindow* pColorWindow = getColorWindow(); + pColorWindow->SelectEntry(rColor); + m_aSelectedColor = pColorWindow->GetSelectEntryColor(); + ShowPreview(m_aSelectedColor); +} + +void ColorListBox::Selected(const NamedColor& rColor) +{ + ShowPreview(rColor); + m_aSelectedColor = rColor; + if (m_aSelectedLink.IsSet()) + m_aSelectedLink.Call(*this); +} + +//to avoid the box resizing every time the color is changed to +//the optimal size of the individual color, get the longest +//standard color and stick with that as the size for all +void ColorListBox::LockWidthRequest() +{ + NamedColor aLongestColor; + long nMaxStandardColorTextWidth = 0; + XColorListRef const xColorTable = XColorList::CreateStdColorList(); + for (long i = 0; i != xColorTable->Count(); ++i) + { + XColorEntry& rEntry = *xColorTable->GetColor(i); + auto nColorTextWidth = m_xButton->get_pixel_size(rEntry.GetName()).Width(); + if (nColorTextWidth > nMaxStandardColorTextWidth) + { + nMaxStandardColorTextWidth = nColorTextWidth; + aLongestColor.second = rEntry.GetName(); + } + } + ShowPreview(aLongestColor); + m_xButton->set_size_request(m_xButton->get_preferred_size().Width(), -1); +} + +void ColorListBox::ShowPreview(const NamedColor &rColor) +{ + const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings(); + Size aImageSize(rStyleSettings.GetListBoxPreviewDefaultPixelSize()); + + ScopedVclPtrInstance<VirtualDevice> xDevice; + xDevice->SetOutputSize(aImageSize); + const tools::Rectangle aRect(Point(0, 0), aImageSize); + if (m_bShowNoneButton && rColor.first == COL_NONE_COLOR) + { + const Color aW(COL_WHITE); + const Color aG(0xef, 0xef, 0xef); + xDevice->DrawCheckered(aRect.TopLeft(), aRect.GetSize(), 8, aW, aG); + xDevice->SetFillColor(); + } + else + { + if (rColor.first == COL_AUTO) + xDevice->SetFillColor(m_aAutoDisplayColor); + else + xDevice->SetFillColor(rColor.first); + } + + xDevice->SetLineColor(rStyleSettings.GetDisableColor()); + xDevice->DrawRect(aRect); + + m_xButton->set_image(xDevice.get()); + m_xButton->set_label(rColor.second); +} + +MenuOrToolMenuButton::MenuOrToolMenuButton(weld::MenuButton* pMenuButton) + : m_pMenuButton(pMenuButton) + , m_pToolbar(nullptr) + , m_pControl(nullptr) + , m_nId(0) +{ +} + +MenuOrToolMenuButton::MenuOrToolMenuButton(weld::Toolbar* pToolbar, const OString& rIdent) + : m_pMenuButton(nullptr) + , m_pToolbar(pToolbar) + , m_aIdent(rIdent) + , m_pControl(nullptr) + , m_nId(0) +{ +} + +MenuOrToolMenuButton::MenuOrToolMenuButton(SvxColorToolBoxControl* pControl, ToolBox* pToolbar, sal_uInt16 nId) + : m_pMenuButton(nullptr) + , m_pToolbar(nullptr) + , m_pControl(pControl) + , m_xToolBox(pToolbar) + , m_nId(nId) +{ +} + +MenuOrToolMenuButton::~MenuOrToolMenuButton() +{ +} + +bool MenuOrToolMenuButton::get_active() const +{ + if (m_pMenuButton) + return m_pMenuButton->get_active(); + if (m_pToolbar) + return m_pToolbar->get_menu_item_active(m_aIdent); + return m_xToolBox->GetDownItemId() == m_nId; +} + +void MenuOrToolMenuButton::set_inactive() const +{ + if (m_pMenuButton) + { + if (m_pMenuButton->get_active()) + m_pMenuButton->set_active(false); + return; + } + if (m_pToolbar) + { + if (m_pToolbar->get_menu_item_active(m_aIdent)) + m_pToolbar->set_menu_item_active(m_aIdent, false); + return; + } + m_pControl->EndPopupMode(); +} + +weld::Widget* MenuOrToolMenuButton::get_widget() const +{ + if (m_pMenuButton) + return m_pMenuButton; + if (m_pToolbar) + return m_pToolbar; + return m_xToolBox->GetFrameWeld(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/tbxctrls/tbunocontroller.cxx b/svx/source/tbxctrls/tbunocontroller.cxx new file mode 100644 index 000000000..8e42177bf --- /dev/null +++ b/svx/source/tbxctrls/tbunocontroller.cxx @@ -0,0 +1,550 @@ +/* -*- 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 <com/sun/star/awt/FontDescriptor.hpp> +#include <com/sun/star/frame/XFrame.hpp> +#include <com/sun/star/frame/status/FontHeight.hpp> +#include <com/sun/star/frame/XDispatchProvider.hpp> +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/util/XURLTransformer.hpp> + +#include <vcl/event.hxx> +#include <vcl/svapp.hxx> +#include <vcl/weldutils.hxx> +#include <vcl/window.hxx> +#include <vcl/settings.hxx> +#include <toolkit/helper/vclunohelper.hxx> +#include <svtools/ctrltool.hxx> +#include <svtools/ctrlbox.hxx> +#include <svtools/toolboxcontroller.hxx> +#include <cppuhelper/queryinterface.hxx> +#include <cppuhelper/supportsservice.hxx> + +#include <memory> + +#include <vcl/InterimItemWindow.hxx> +#include <sfx2/sidebar/SidebarToolBox.hxx> +#include <boost/property_tree/ptree.hpp> + +using namespace ::com::sun::star; + +namespace { + +class SvxFontSizeBox_Base; +class SvxFontSizeBox_Impl; + +class FontHeightToolBoxControl : public svt::ToolboxController, + public lang::XServiceInfo +{ + public: + explicit FontHeightToolBoxControl( + const css::uno::Reference< css::uno::XComponentContext >& rServiceManager ); + + // XInterface + virtual css::uno::Any SAL_CALL queryInterface( const css::uno::Type& aType ) override; + virtual void SAL_CALL acquire() throw () override; + virtual void SAL_CALL release() throw () override; + + // XServiceInfo + virtual OUString SAL_CALL getImplementationName() override; + virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override; + virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override; + + // XComponent + virtual void SAL_CALL dispose() override; + + // XStatusListener + virtual void SAL_CALL statusChanged( const css::frame::FeatureStateEvent& Event ) override; + + // XToolbarController + virtual void SAL_CALL execute( sal_Int16 KeyModifier ) override; + virtual void SAL_CALL click() override; + virtual void SAL_CALL doubleClick() override; + virtual css::uno::Reference< css::awt::XWindow > SAL_CALL createPopupWindow() override; + virtual css::uno::Reference< css::awt::XWindow > SAL_CALL createItemWindow( const css::uno::Reference< css::awt::XWindow >& Parent ) override; + + void dispatchCommand( const css::uno::Sequence< css::beans::PropertyValue >& rArgs ); + using svt::ToolboxController::dispatchCommand; + + private: + VclPtr<SvxFontSizeBox_Impl> m_xVclBox; + std::unique_ptr<SvxFontSizeBox_Base> m_xWeldBox; + SvxFontSizeBox_Base* m_pBox; + css::awt::FontDescriptor m_aCurrentFont; +}; + +class SvxFontSizeBox_Base +{ +public: + SvxFontSizeBox_Base(std::unique_ptr<weld::ComboBox> xWidget, + const uno::Reference< frame::XFrame >& _xFrame, + FontHeightToolBoxControl& rCtrl); + + virtual ~SvxFontSizeBox_Base() + { + } + + virtual void set_sensitive(bool bSensitive) + { + m_xWidget->set_sensitive(bSensitive); + } + + void statusChanged_Impl(long nHeight, bool bErase); + void UpdateFont(const css::awt::FontDescriptor& rCurrentFont); + +protected: + FontHeightToolBoxControl& m_rCtrl; + OUString m_aCurText; + bool m_bRelease; + uno::Reference<frame::XFrame> m_xFrame; + std::unique_ptr<FontSizeBox> m_xWidget; + + void ReleaseFocus_Impl(); + void Select(); + + virtual bool DoKeyInput(const KeyEvent& rKEvt); + + DECL_LINK(SelectHdl, weld::ComboBox&, void); + DECL_LINK(KeyInputHdl, const KeyEvent&, bool); + DECL_LINK(ActivateHdl, weld::ComboBox&, bool); + DECL_LINK(FocusOutHdl, weld::Widget&, void); + DECL_LINK(DumpAsPropertyTreeHdl, boost::property_tree::ptree&, void); +}; + +class SvxFontSizeBox_Impl final : public InterimItemWindow + , public SvxFontSizeBox_Base +{ +public: + SvxFontSizeBox_Impl(vcl::Window* pParent, + const uno::Reference< frame::XFrame >& _xFrame, + FontHeightToolBoxControl& rCtrl); + + virtual void dispose() override + { + m_xWidget.reset(); + InterimItemWindow::dispose(); + } + + virtual void GetFocus() override + { + if (m_xWidget) + m_xWidget->grab_focus(); + InterimItemWindow::GetFocus(); + } + + virtual ~SvxFontSizeBox_Impl() override + { + disposeOnce(); + } + + void SetOptimalSize(); + + virtual void DataChanged(const DataChangedEvent& rDCEvt) override; + + virtual void set_sensitive(bool bSensitive) override + { + m_xWidget->set_sensitive(bSensitive); + if (bSensitive) + InterimItemWindow::Enable(); + else + InterimItemWindow::Disable(); + } + +private: + virtual bool DoKeyInput(const KeyEvent& rKEvt) override; +}; + +SvxFontSizeBox_Base::SvxFontSizeBox_Base(std::unique_ptr<weld::ComboBox> xWidget, + const uno::Reference<frame::XFrame>& rFrame, + FontHeightToolBoxControl& rCtrl) + : m_rCtrl(rCtrl) + , m_bRelease(true) + , m_xFrame(rFrame) + , m_xWidget(new FontSizeBox(std::move(xWidget))) +{ + m_xWidget->set_value(0); + m_xWidget->set_active_or_entry_text(""); + m_xWidget->disable_entry_completion(); + + m_xWidget->connect_changed(LINK(this, SvxFontSizeBox_Base, SelectHdl)); + m_xWidget->connect_key_press(LINK(this, SvxFontSizeBox_Base, KeyInputHdl)); + m_xWidget->connect_entry_activate(LINK(this, SvxFontSizeBox_Base, ActivateHdl)); + m_xWidget->connect_focus_out(LINK(this, SvxFontSizeBox_Base, FocusOutHdl)); + m_xWidget->connect_get_property_tree(LINK(this, SvxFontSizeBox_Base, DumpAsPropertyTreeHdl)); +} + +void SvxFontSizeBox_Base::ReleaseFocus_Impl() +{ + if ( !m_bRelease ) + { + m_bRelease = true; + return; + } + + if ( m_xFrame.is() && m_xFrame->getContainerWindow().is() ) + m_xFrame->getContainerWindow()->setFocus(); +} + +IMPL_LINK(SvxFontSizeBox_Base, SelectHdl, weld::ComboBox&, rCombo, void) +{ + if (rCombo.changed_by_direct_pick()) // only when picked from the list + Select(); +} + +IMPL_LINK_NOARG(SvxFontSizeBox_Base, ActivateHdl, weld::ComboBox&, bool) +{ + Select(); + return true; +} + +void SvxFontSizeBox_Base::Select() +{ + sal_Int64 nSelVal = m_xWidget->get_value(); + float fSelVal = float( nSelVal ) / 10; + + uno::Sequence< beans::PropertyValue > aArgs( 1 ); + aArgs[0].Name = "FontHeight.Height"; + aArgs[0].Value <<= fSelVal; + + /* #i33380# DR 2004-09-03 Moved the following line above the Dispatch() call. + This instance may be deleted in the meantime (i.e. when a dialog is opened + while in Dispatch()), accessing members will crash in this case. */ + ReleaseFocus_Impl(); + + m_rCtrl.dispatchCommand( aArgs ); +} + +void SvxFontSizeBox_Base::statusChanged_Impl( long nPoint, bool bErase ) +{ + if ( !bErase ) + { + // convert the metric + long nVal = nPoint; + + // changed => set new value + if (m_xWidget->get_value() != nVal) + m_xWidget->set_value(nVal); + } + else + { + // delete value in the display + m_xWidget->set_value(-1L); + m_xWidget->set_active_or_entry_text(""); + } + m_aCurText = m_xWidget->get_active_text(); +} + +void SvxFontSizeBox_Base::UpdateFont(const css::awt::FontDescriptor& rCurrentFont) +{ + // filling up the sizes list + auto nOldVal = m_xWidget->get_value(); // memorize old value + std::unique_ptr<FontList> xFontList(new FontList(Application::GetDefaultDevice())); + + if (!rCurrentFont.Name.isEmpty()) + { + FontMetric aFontMetric; + aFontMetric.SetFamilyName(rCurrentFont.Name); + aFontMetric.SetStyleName(rCurrentFont.StyleName); + aFontMetric.SetFontHeight(rCurrentFont.Height); + m_xWidget->Fill(&aFontMetric, xFontList.get()); + } + else + { + m_xWidget->Fill(nullptr, xFontList.get()); + } + m_xWidget->set_value(nOldVal); // restore old value + m_aCurText = m_xWidget->get_active_text(); // memorize to reset at ESC +} + +IMPL_LINK(SvxFontSizeBox_Base, KeyInputHdl, const KeyEvent&, rKEvt, bool) +{ + return DoKeyInput(rKEvt); +} + +bool SvxFontSizeBox_Base::DoKeyInput(const KeyEvent& rKEvt) +{ + bool bHandled = false; + + sal_uInt16 nCode = rKEvt.GetKeyCode().GetCode(); + + switch (nCode) + { + case KEY_TAB: + m_bRelease = false; + Select(); + break; + + case KEY_ESCAPE: + m_xWidget->set_active_or_entry_text(m_aCurText); + if (!m_rCtrl.IsInSidebar()) + { + ReleaseFocus_Impl(); + bHandled = true; + } + break; + } + + return bHandled; +} + +bool SvxFontSizeBox_Impl::DoKeyInput(const KeyEvent& rKEvt) +{ + return SvxFontSizeBox_Base::DoKeyInput(rKEvt) || ChildKeyInput(rKEvt); +} + +IMPL_LINK_NOARG(SvxFontSizeBox_Base, FocusOutHdl, weld::Widget&, void) +{ + if (!m_xWidget->has_focus()) // a combobox can be comprised of different subwidget so double-check if none of those has focus + m_xWidget->set_active_or_entry_text(m_aCurText); +} + +void SvxFontSizeBox_Impl::SetOptimalSize() +{ + SetSizePixel(get_preferred_size()); +} + +SvxFontSizeBox_Impl::SvxFontSizeBox_Impl(vcl::Window* pParent, + const uno::Reference<frame::XFrame>& rFrame, + FontHeightToolBoxControl& rCtrl) + : InterimItemWindow(pParent, "svx/ui/fontsizebox.ui", "FontSizeBox") + , SvxFontSizeBox_Base(m_xBuilder->weld_combo_box("fontsizecombobox"), rFrame, rCtrl) +{ +} + +void SvxFontSizeBox_Impl::DataChanged( const DataChangedEvent& rDCEvt ) +{ + if ( (rDCEvt.GetType() == DataChangedEventType::SETTINGS) && + (rDCEvt.GetFlags() & AllSettingsFlags::STYLE) ) + { + SetOptimalSize(); + } +} + +IMPL_LINK(SvxFontSizeBox_Base, DumpAsPropertyTreeHdl, boost::property_tree::ptree&, rTree, void) +{ + boost::property_tree::ptree aEntries; + + for (int i = 0, nCount = m_xWidget->get_count(); i < nCount; ++i) + { + boost::property_tree::ptree aEntry; + aEntry.put("", m_xWidget->get_text(i)); + aEntries.push_back(std::make_pair("", aEntry)); + } + + rTree.add_child("entries", aEntries); + + boost::property_tree::ptree aSelected; + + int nActive = m_xWidget->get_active(); + if (nActive != -1) + { + boost::property_tree::ptree aEntry; + aEntry.put("", nActive); + aSelected.push_back(std::make_pair("", aEntry)); + } + + rTree.put("selectedCount", nActive == -1 ? 0 : 1); + rTree.add_child("selectedEntries", aSelected); + + rTree.put("command", ".uno:FontHeight"); +} + +FontHeightToolBoxControl::FontHeightToolBoxControl( const uno::Reference< uno::XComponentContext >& rxContext ) + : svt::ToolboxController( rxContext, + uno::Reference< frame::XFrame >(), + ".uno:FontHeight" ), + m_pBox( nullptr ) +{ + addStatusListener( ".uno:CharFontName"); +} + +// XInterface +css::uno::Any SAL_CALL FontHeightToolBoxControl::queryInterface( const css::uno::Type& aType ) +{ + uno::Any a = ToolboxController::queryInterface( aType ); + if ( a.hasValue() ) + return a; + + return ::cppu::queryInterface( aType, static_cast< lang::XServiceInfo* >( this )); +} + +void SAL_CALL FontHeightToolBoxControl::acquire() throw () +{ + ToolboxController::acquire(); +} + +void SAL_CALL FontHeightToolBoxControl::release() throw () +{ + ToolboxController::release(); +} + +// XServiceInfo +sal_Bool SAL_CALL FontHeightToolBoxControl::supportsService( const OUString& ServiceName ) +{ + return cppu::supportsService(this, ServiceName); +} + +OUString SAL_CALL FontHeightToolBoxControl::getImplementationName() +{ + return "com.sun.star.svx.FontHeightToolBoxController"; +} + +uno::Sequence< OUString > SAL_CALL FontHeightToolBoxControl::getSupportedServiceNames( ) +{ + return { "com.sun.star.frame.ToolbarController" }; +} + +// XComponent +void SAL_CALL FontHeightToolBoxControl::dispose() +{ + svt::ToolboxController::dispose(); + + SolarMutexGuard aSolarMutexGuard; + m_xVclBox.disposeAndClear(); + m_xWeldBox.reset(); + m_pBox = nullptr; +} + +// XStatusListener +void SAL_CALL FontHeightToolBoxControl::statusChanged( + const frame::FeatureStateEvent& rEvent ) +{ + if ( m_pBox ) + { + SolarMutexGuard aSolarMutexGuard; + if (rEvent.FeatureURL.Path == "FontHeight") + { + if ( rEvent.IsEnabled ) + { + m_pBox->set_sensitive(true); + frame::status::FontHeight aFontHeight; + if ( rEvent.State >>= aFontHeight ) + m_pBox->statusChanged_Impl( long( 10. * aFontHeight.Height ), false ); + else + m_pBox->statusChanged_Impl( long( -1 ), true ); + } + else + { + m_pBox->set_sensitive(false); + m_pBox->statusChanged_Impl( long( -1 ), true ); + } + + if (m_pToolbar) + m_pToolbar->set_item_sensitive(m_aCommandURL.toUtf8(), rEvent.IsEnabled); + else + { + ToolBox* pToolBox = nullptr; + sal_uInt16 nId = 0; + if (getToolboxId(nId, &pToolBox)) + pToolBox->EnableItem(nId, rEvent.IsEnabled); + } + } + else if ( rEvent.FeatureURL.Path == "CharFontName" ) + { + if ( rEvent.State >>= m_aCurrentFont ) + m_pBox->UpdateFont( m_aCurrentFont ); + } + } +} + +// XToolbarController +void SAL_CALL FontHeightToolBoxControl::execute( sal_Int16 /*KeyModifier*/ ) +{ +} + +void SAL_CALL FontHeightToolBoxControl::click() +{ +} + +void SAL_CALL FontHeightToolBoxControl::doubleClick() +{ +} + +uno::Reference< awt::XWindow > SAL_CALL FontHeightToolBoxControl::createPopupWindow() +{ + return uno::Reference< awt::XWindow >(); +} + +uno::Reference< awt::XWindow > SAL_CALL FontHeightToolBoxControl::createItemWindow( + const uno::Reference< awt::XWindow >& xParent ) +{ + uno::Reference< awt::XWindow > xItemWindow; + + if (m_pBuilder) + { + SolarMutexGuard aSolarMutexGuard; + + std::unique_ptr<weld::ComboBox> xWidget(m_pBuilder->weld_combo_box("fontsizecombobox")); + + xItemWindow = css::uno::Reference<css::awt::XWindow>(new weld::TransportAsXWindow(xWidget.get())); + + m_xWeldBox.reset(new SvxFontSizeBox_Base(std::move(xWidget), m_xFrame, *this)); + m_pBox = m_xWeldBox.get(); + //Get the box to fill itself with all its sizes + m_pBox->UpdateFont(m_aCurrentFont); + } + else + { + VclPtr<vcl::Window> pParent = VCLUnoHelper::GetWindow( xParent ); + if ( pParent ) + { + SolarMutexGuard aSolarMutexGuard; + m_xVclBox = VclPtr<SvxFontSizeBox_Impl>::Create( pParent, m_xFrame, *this ); + m_pBox = m_xVclBox.get(); + //Get the box to fill itself with all its sizes + m_pBox->UpdateFont(m_aCurrentFont); + //Make it size itself to its optimal size re above sizes + m_xVclBox->SetOptimalSize(); + xItemWindow = VCLUnoHelper::GetInterface(m_xVclBox); + } + } + + return xItemWindow; +} + +void FontHeightToolBoxControl::dispatchCommand( + const uno::Sequence< beans::PropertyValue >& rArgs ) +{ + uno::Reference< frame::XDispatchProvider > xDispatchProvider( m_xFrame, uno::UNO_QUERY ); + if ( xDispatchProvider.is() ) + { + util::URL aURL; + uno::Reference< frame::XDispatch > xDispatch; + uno::Reference< util::XURLTransformer > xURLTransformer = getURLTransformer(); + + aURL.Complete = ".uno:FontHeight"; + xURLTransformer->parseStrict( aURL ); + xDispatch = xDispatchProvider->queryDispatch( aURL, OUString(), 0 ); + if ( xDispatch.is() ) + xDispatch->dispatch( aURL, rArgs ); + } +} + +} + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * +com_sun_star_svx_FontHeightToolBoxController_get_implementation( + css::uno::XComponentContext *rxContext, + css::uno::Sequence<css::uno::Any> const &) +{ + return cppu::acquire(new FontHeightToolBoxControl(rxContext)); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/tbxctrls/tbunosearchcontrollers.cxx b/svx/source/tbxctrls/tbunosearchcontrollers.cxx new file mode 100644 index 000000000..716e7cb9e --- /dev/null +++ b/svx/source/tbxctrls/tbunosearchcontrollers.cxx @@ -0,0 +1,1662 @@ +/* -*- 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 <sal/config.h> + +#include <map> +#include <vector> + +#include <config_feature_desktop.h> + +#include <svx/strings.hrc> +#include <svx/dialmgr.hxx> + +#include <comphelper/propertysequence.hxx> +#include <cppuhelper/queryinterface.hxx> +#include <cppuhelper/supportsservice.hxx> +#include <cppuhelper/weak.hxx> +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/frame/DispatchDescriptor.hpp> +#include <com/sun/star/frame/XDispatch.hpp> +#include <com/sun/star/frame/XDispatchProvider.hpp> +#include <com/sun/star/frame/XLayoutManager.hpp> +#include <com/sun/star/frame/XStatusListener.hpp> +#include <com/sun/star/lang/XInitialization.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/text/XTextRange.hpp> +#include <com/sun/star/ui/XUIElement.hpp> +#include <com/sun/star/util/URL.hpp> +#include <com/sun/star/util/URLTransformer.hpp> +#include <com/sun/star/util/SearchAlgorithms.hpp> +#include <com/sun/star/util/SearchAlgorithms2.hpp> + +#include <vcl/InterimItemWindow.hxx> +#include <svl/ctloptions.hxx> +#include <svl/srchitem.hxx> +#include <svtools/acceleratorexecute.hxx> +#include <svtools/toolboxcontroller.hxx> +#include <toolkit/helper/vclunohelper.hxx> +#include <vcl/toolbox.hxx> +#include <vcl/svapp.hxx> +#include <rtl/instance.hxx> +#include <svx/labelitemwindow.hxx> +#include <svx/srchdlg.hxx> +#include <vcl/event.hxx> + +#include <findtextfield.hxx> + +using namespace css; + +namespace { + +static const char COMMAND_FINDTEXT[] = ".uno:FindText"; +static const char COMMAND_DOWNSEARCH[] = ".uno:DownSearch"; +static const char COMMAND_UPSEARCH[] = ".uno:UpSearch"; +static const char COMMAND_FINDALL[] = ".uno:FindAll"; +static const char COMMAND_MATCHCASE[] = ".uno:MatchCase"; +static const char COMMAND_SEARCHFORMATTED[] = ".uno:SearchFormattedDisplayString"; + +static const sal_Int32 REMEMBER_SIZE = 10; + +class CheckButtonItemWindow final : public InterimItemWindow +{ +public: + CheckButtonItemWindow(vcl::Window* pParent, const OUString& rLabel) + : InterimItemWindow(pParent, "svx/ui/checkbuttonbox.ui", "CheckButtonBox") + , m_xWidget(m_xBuilder->weld_check_button("checkbutton")) + { + m_xWidget->connect_key_press(LINK(this, CheckButtonItemWindow, KeyInputHdl)); + m_xWidget->set_label(rLabel); + SetSizePixel(m_xWidget->get_preferred_size()); + } + + bool get_active() const + { + return m_xWidget->get_active(); + } + + virtual void dispose() override + { + m_xWidget.reset(); + InterimItemWindow::dispose(); + } + + virtual ~CheckButtonItemWindow() override + { + disposeOnce(); + } + + virtual void GetFocus() override + { + if (m_xWidget) + m_xWidget->grab_focus(); + InterimItemWindow::GetFocus(); + } + +private: + std::unique_ptr<weld::CheckButton> m_xWidget; + + DECL_LINK(KeyInputHdl, const KeyEvent&, bool); +}; + +IMPL_LINK(CheckButtonItemWindow, KeyInputHdl, const KeyEvent&, rKeyEvent, bool) +{ + return ChildKeyInput(rKeyEvent); +} + +void impl_executeSearch( const css::uno::Reference< css::uno::XComponentContext >& rxContext, + const css::uno::Reference< css::frame::XFrame >& xFrame, + const ToolBox* pToolBox, + const bool aSearchBackwards, + const bool aFindAll = false ) +{ + css::uno::Reference< css::util::XURLTransformer > xURLTransformer( css::util::URLTransformer::create( rxContext ) ); + css::util::URL aURL; + aURL.Complete = ".uno:ExecuteSearch"; + xURLTransformer->parseStrict(aURL); + + OUString sFindText; + bool aMatchCase = false; + bool bSearchFormatted = false; + if ( pToolBox ) + { + ToolBox::ImplToolItems::size_type nItemCount = pToolBox->GetItemCount(); + for ( ToolBox::ImplToolItems::size_type i=0; i<nItemCount; ++i ) + { + sal_uInt16 id = pToolBox->GetItemId(i); + OUString sItemCommand = pToolBox->GetItemCommand(id); + if ( sItemCommand == COMMAND_FINDTEXT ) + { + FindTextFieldControl* pItemWin = static_cast<FindTextFieldControl*>(pToolBox->GetItemWindow(id)); + if (pItemWin) + sFindText = pItemWin->get_active_text(); + } else if ( sItemCommand == COMMAND_MATCHCASE ) + { + CheckButtonItemWindow* pItemWin = static_cast<CheckButtonItemWindow*>(pToolBox->GetItemWindow(id)); + if (pItemWin) + aMatchCase = pItemWin->get_active(); + } else if ( sItemCommand == COMMAND_SEARCHFORMATTED ) + { + CheckButtonItemWindow* pItemWin = static_cast<CheckButtonItemWindow*>(pToolBox->GetItemWindow(id)); + if (pItemWin) + bSearchFormatted = pItemWin->get_active(); + } + } + } + + SvtCTLOptions aCTLOptions; + TransliterationFlags nFlags = TransliterationFlags::NONE; + if (!aMatchCase) + nFlags |= TransliterationFlags::IGNORE_CASE; + if (aCTLOptions.IsCTLFontEnabled()) + nFlags |= TransliterationFlags::IGNORE_DIACRITICS_CTL + | TransliterationFlags::IGNORE_KASHIDA_CTL; + + auto aArgs( comphelper::InitPropertySequence( { + { "SearchItem.SearchString", css::uno::makeAny( sFindText ) }, + { "SearchItem.Backward", css::uno::makeAny( aSearchBackwards ) }, + { "SearchItem.SearchFlags", css::uno::makeAny( sal_Int32(0) ) }, + { "SearchItem.TransliterateFlags", css::uno::makeAny( static_cast<sal_Int32>(nFlags) ) }, + { "SearchItem.Command", css::uno::makeAny( static_cast<sal_Int16>(aFindAll ?SvxSearchCmd::FIND_ALL : SvxSearchCmd::FIND ) ) }, + { "SearchItem.AlgorithmType", css::uno::makeAny( sal_Int16(css::util::SearchAlgorithms_ABSOLUTE) ) }, + { "SearchItem.AlgorithmType2", css::uno::makeAny( sal_Int16(css::util::SearchAlgorithms2::ABSOLUTE) ) }, + { "SearchItem.SearchFormatted", css::uno::makeAny( bSearchFormatted ) } + } ) ); + + css::uno::Reference< css::frame::XDispatchProvider > xDispatchProvider(xFrame, css::uno::UNO_QUERY); + if ( xDispatchProvider.is() ) + { + css::uno::Reference< css::frame::XDispatch > xDispatch = xDispatchProvider->queryDispatch( aURL, OUString(), 0 ); + if ( xDispatch.is() && !aURL.Complete.isEmpty() ) + xDispatch->dispatch( aURL, aArgs ); + } +} + +} + +FindTextFieldControl::FindTextFieldControl( vcl::Window* pParent, + css::uno::Reference< css::frame::XFrame > const & xFrame, + const css::uno::Reference< css::uno::XComponentContext >& xContext) : + InterimItemWindow(pParent, "svx/ui/findbox.ui", "FindBox"), + m_nAsyncGetFocusId(nullptr), + m_xWidget(m_xBuilder->weld_combo_box("find")), + m_xFrame(xFrame), + m_xContext(xContext), + m_pAcc(svt::AcceleratorExecute::createAcceleratorHelper()) +{ + m_xWidget->set_entry_placeholder_text(SvxResId(RID_SVXSTR_FINDBAR_FIND)); + m_xWidget->set_entry_completion(true, true); + m_pAcc->init(m_xContext, m_xFrame); + + m_xWidget->connect_focus_in(LINK(this, FindTextFieldControl, FocusInHdl)); + m_xWidget->connect_key_press(LINK(this, FindTextFieldControl, KeyInputHdl)); + m_xWidget->connect_entry_activate(LINK(this, FindTextFieldControl, ActivateHdl)); + + m_xWidget->set_size_request(250, -1); + SetSizePixel(m_xWidget->get_preferred_size()); +} + +void FindTextFieldControl::Remember_Impl(const OUString& rStr) +{ + const sal_Int32 nCount = m_xWidget->get_count(); + + for (sal_Int32 i=0; i<nCount; ++i) + { + if (rStr == m_xWidget->get_text(i)) + return; + } + + if (nCount == REMEMBER_SIZE) + m_xWidget->remove(REMEMBER_SIZE-1); + + m_xWidget->insert_text(0, rStr); +} + +void FindTextFieldControl::SetTextToSelected_Impl() +{ + OUString aString; + + try + { + css::uno::Reference<css::frame::XController> xController(m_xFrame->getController(), css::uno::UNO_SET_THROW); + css::uno::Reference<css::frame::XModel> xModel(xController->getModel(), css::uno::UNO_SET_THROW); + css::uno::Reference<css::container::XIndexAccess> xIndexAccess(xModel->getCurrentSelection(), css::uno::UNO_QUERY_THROW); + if (xIndexAccess->getCount() > 0) + { + css::uno::Reference<css::text::XTextRange> xTextRange(xIndexAccess->getByIndex(0), css::uno::UNO_QUERY_THROW); + aString = xTextRange->getString(); + } + } + catch ( ... ) + { + } + + if ( !aString.isEmpty() ) + { + // If something is selected in the document, prepopulate with this + m_xWidget->set_entry_text(aString); + m_aChangeHdl.Call(*m_xWidget); + } + else if (get_count() > 0) + { + // Else, prepopulate with last search word (fdo#84256) + m_xWidget->set_entry_text(m_xWidget->get_text(0)); + } +} + +IMPL_LINK(FindTextFieldControl, KeyInputHdl, const KeyEvent&, rKeyEvent, bool) +{ + if (isDisposed()) + return true; + + bool bRet = false; + + bool bShift = rKeyEvent.GetKeyCode().IsShift(); + bool bMod1 = rKeyEvent.GetKeyCode().IsMod1(); + sal_uInt16 nCode = rKeyEvent.GetKeyCode().GetCode(); + + // Close the search bar on Escape + if ( KEY_ESCAPE == nCode ) + { + bRet = true; + GrabFocusToDocument(); + + // hide the findbar + css::uno::Reference< css::beans::XPropertySet > xPropSet(m_xFrame, css::uno::UNO_QUERY); + if (xPropSet.is()) + { + css::uno::Reference< css::frame::XLayoutManager > xLayoutManager; + css::uno::Any aValue = xPropSet->getPropertyValue("LayoutManager"); + aValue >>= xLayoutManager; + if (xLayoutManager.is()) + { + const OUString sResourceURL( "private:resource/toolbar/findbar" ); + xLayoutManager->hideElement( sResourceURL ); + xLayoutManager->destroyElement( sResourceURL ); + } + } + } + // Select text in the search box when Ctrl-F pressed + else if ( bMod1 && nCode == KEY_F ) + m_xWidget->select_entry_region(0, -1); + + // Execute the search when Return, Ctrl-G or F3 pressed + else if ( KEY_RETURN == nCode || (bMod1 && (KEY_G == nCode)) || (KEY_F3 == nCode) ) + { + ActivateFind(bShift); + bRet = true; + } + else + { + auto awtKey = svt::AcceleratorExecute::st_VCLKey2AWTKey(rKeyEvent.GetKeyCode()); + const OUString aCommand(m_pAcc->findCommand(awtKey)); + if (aCommand == ".uno:SearchDialog") + bRet = m_pAcc->execute(awtKey); + } + + return bRet || ChildKeyInput(rKeyEvent); +} + +void FindTextFieldControl::ActivateFind(bool bShift) +{ + Remember_Impl(m_xWidget->get_active_text()); + + vcl::Window* pWindow = GetParent(); + ToolBox* pToolBox = static_cast<ToolBox*>(pWindow); + + impl_executeSearch(m_xContext, m_xFrame, pToolBox, bShift); +} + +IMPL_LINK_NOARG(FindTextFieldControl, ActivateHdl, weld::ComboBox&, bool) +{ + if (isDisposed()) + return true; + + ActivateFind(false); + + return true; +} + +IMPL_LINK_NOARG(FindTextFieldControl, OnAsyncGetFocus, void*, void) +{ + m_nAsyncGetFocusId = nullptr; + m_xWidget->select_entry_region(0, -1); +} + +void FindTextFieldControl::FocusIn() +{ + if (m_nAsyncGetFocusId || !m_xWidget) + return; + + // do it async to defeat entry in combobox having its own ideas about the focus + m_nAsyncGetFocusId = Application::PostUserEvent(LINK(this, FindTextFieldControl, OnAsyncGetFocus)); + + GrabFocus(); // tdf#137993 ensure the toplevel vcl::Window is activated so SfxViewFrame::Current is valid +} + +IMPL_LINK_NOARG(FindTextFieldControl, FocusInHdl, weld::Widget&, void) +{ + FocusIn(); +} + +void FindTextFieldControl::dispose() +{ + if (m_nAsyncGetFocusId) + { + Application::RemoveUserEvent(m_nAsyncGetFocusId); + m_nAsyncGetFocusId = nullptr; + } + m_xWidget.reset(); + InterimItemWindow::dispose(); +} + +FindTextFieldControl::~FindTextFieldControl() +{ + disposeOnce(); +} + +void FindTextFieldControl::connect_changed(const Link<weld::ComboBox&, void>& rLink) +{ + m_aChangeHdl = rLink; + m_xWidget->connect_changed(rLink); +} + +int FindTextFieldControl::get_count() const +{ + return m_xWidget->get_count(); +} + +OUString FindTextFieldControl::get_text(int nIndex) const +{ + return m_xWidget->get_text(nIndex); +} + +OUString FindTextFieldControl::get_active_text() const +{ + return m_xWidget->get_active_text(); +} + +void FindTextFieldControl::append_text(const OUString& rText) +{ + m_xWidget->append_text(rText); +} + +void FindTextFieldControl::set_entry_message_type(weld::EntryMessageType eType) +{ + m_xWidget->set_entry_message_type(eType); +} + +void FindTextFieldControl::GetFocus() +{ + if (m_xWidget) + m_xWidget->grab_focus(); + InterimItemWindow::GetFocus(); + FocusIn(); +} + +namespace { + +class SearchToolbarControllersManager +{ +public: + + SearchToolbarControllersManager(); + + static SearchToolbarControllersManager& createControllersManager(); + + void registryController( const css::uno::Reference< css::frame::XFrame >& xFrame, const css::uno::Reference< css::frame::XStatusListener >& xStatusListener, const OUString& sCommandURL ); + void freeController ( const css::uno::Reference< css::frame::XFrame >& xFrame, const OUString& sCommandURL ); + css::uno::Reference< css::frame::XStatusListener > findController( const css::uno::Reference< css::frame::XFrame >& xFrame, const OUString& sCommandURL ); + + void saveSearchHistory(const FindTextFieldControl* m_pFindTextFieldControl); + void loadSearchHistory(FindTextFieldControl* m_pFindTextFieldControl); + +private: + + typedef ::std::vector< css::beans::PropertyValue > SearchToolbarControllersVec; + typedef ::std::map< css::uno::Reference< css::frame::XFrame >, SearchToolbarControllersVec > SearchToolbarControllersMap; + SearchToolbarControllersMap aSearchToolbarControllersMap; + std::vector<OUString> m_aSearchStrings; + +}; + +SearchToolbarControllersManager::SearchToolbarControllersManager() +{ +} + +class theSearchToolbarControllersManager + : public rtl::Static<SearchToolbarControllersManager, + theSearchToolbarControllersManager> +{ +}; + +SearchToolbarControllersManager& SearchToolbarControllersManager::createControllersManager() +{ + return theSearchToolbarControllersManager::get(); +} + +void SearchToolbarControllersManager::saveSearchHistory(const FindTextFieldControl* pFindTextFieldControl) +{ + const sal_Int32 nECount( pFindTextFieldControl->get_count() ); + m_aSearchStrings.resize( nECount ); + for( sal_Int32 i=0; i<nECount; ++i ) + { + m_aSearchStrings[i] = pFindTextFieldControl->get_text(i); + } +} + +void SearchToolbarControllersManager::loadSearchHistory(FindTextFieldControl* pFindTextFieldControl) +{ + for( size_t i=0; i<m_aSearchStrings.size(); ++i ) + { + pFindTextFieldControl->append_text(m_aSearchStrings[i]); + } +} + +void SearchToolbarControllersManager::registryController( const css::uno::Reference< css::frame::XFrame >& xFrame, const css::uno::Reference< css::frame::XStatusListener >& xStatusListener, const OUString& sCommandURL ) +{ + SearchToolbarControllersMap::iterator pIt = aSearchToolbarControllersMap.find(xFrame); + if (pIt == aSearchToolbarControllersMap.end()) + { + SearchToolbarControllersVec lControllers(1); + lControllers[0].Name = sCommandURL; + lControllers[0].Value <<= xStatusListener; + aSearchToolbarControllersMap.emplace(xFrame, lControllers); + } + else + { + sal_Int32 nSize = pIt->second.size(); + for (sal_Int32 i=0; i<nSize; ++i) + { + if (pIt->second[i].Name == sCommandURL) + return; + } + + pIt->second.resize(nSize+1); + pIt->second[nSize].Name = sCommandURL; + pIt->second[nSize].Value <<= xStatusListener; + } +} + +void SearchToolbarControllersManager::freeController( const css::uno::Reference< css::frame::XFrame >& xFrame, const OUString& sCommandURL ) +{ + SearchToolbarControllersMap::iterator pIt = aSearchToolbarControllersMap.find(xFrame); + if (pIt != aSearchToolbarControllersMap.end()) + { + auto pItCtrl = std::find_if(pIt->second.begin(), pIt->second.end(), + [&sCommandURL](const css::beans::PropertyValue& rCtrl) { return rCtrl.Name == sCommandURL; }); + if (pItCtrl != pIt->second.end()) + pIt->second.erase(pItCtrl); + + if (pIt->second.empty()) + aSearchToolbarControllersMap.erase(pIt); + } +} + +css::uno::Reference< css::frame::XStatusListener > SearchToolbarControllersManager::findController( const css::uno::Reference< css::frame::XFrame >& xFrame, const OUString& sCommandURL ) +{ + css::uno::Reference< css::frame::XStatusListener > xStatusListener; + + SearchToolbarControllersMap::iterator pIt = aSearchToolbarControllersMap.find(xFrame); + if (pIt != aSearchToolbarControllersMap.end()) + { + auto pItCtrl = std::find_if(pIt->second.begin(), pIt->second.end(), + [&sCommandURL](const css::beans::PropertyValue& rCtrl) { return rCtrl.Name == sCommandURL; }); + if (pItCtrl != pIt->second.end()) + pItCtrl->Value >>= xStatusListener; + } + + return xStatusListener; +} + +class FindTextToolbarController : public svt::ToolboxController, + public css::lang::XServiceInfo +{ +public: + + FindTextToolbarController( const css::uno::Reference< css::uno::XComponentContext > & rxContext ); + + // XInterface + virtual css::uno::Any SAL_CALL queryInterface( const css::uno::Type& aType ) override; + virtual void SAL_CALL acquire() throw () override; + virtual void SAL_CALL release() throw () override; + + // XServiceInfo + virtual OUString SAL_CALL getImplementationName() override; + virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override; + virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override; + + // XComponent + virtual void SAL_CALL dispose() override; + + // XInitialization + virtual void SAL_CALL initialize( const css::uno::Sequence< css::uno::Any >& aArguments ) override; + + // XToolbarController + virtual css::uno::Reference< css::awt::XWindow > SAL_CALL createItemWindow( const css::uno::Reference< css::awt::XWindow >& Parent ) override; + + // XStatusListener + virtual void SAL_CALL statusChanged( const css::frame::FeatureStateEvent& Event ) override; + + DECL_LINK(EditModifyHdl, weld::ComboBox&, void); + +private: + + void textfieldChanged(); + + VclPtr<FindTextFieldControl> m_pFindTextFieldControl; + + sal_uInt16 m_nDownSearchId; + sal_uInt16 m_nUpSearchId; + sal_uInt16 m_nFindAllId; + +}; + +FindTextToolbarController::FindTextToolbarController( const css::uno::Reference< css::uno::XComponentContext >& rxContext ) + : svt::ToolboxController(rxContext, css::uno::Reference< css::frame::XFrame >(), COMMAND_FINDTEXT) + , m_pFindTextFieldControl(nullptr) + , m_nDownSearchId(0) + , m_nUpSearchId(0) + , m_nFindAllId(0) +{ +} + +// XInterface +css::uno::Any SAL_CALL FindTextToolbarController::queryInterface( const css::uno::Type& aType ) +{ + css::uno::Any a = ToolboxController::queryInterface( aType ); + if ( a.hasValue() ) + return a; + + return ::cppu::queryInterface( aType, static_cast< css::lang::XServiceInfo* >( this ) ); +} + +void SAL_CALL FindTextToolbarController::acquire() throw () +{ + ToolboxController::acquire(); +} + +void SAL_CALL FindTextToolbarController::release() throw () +{ + ToolboxController::release(); +} + +// XServiceInfo +OUString SAL_CALL FindTextToolbarController::getImplementationName() +{ + return "com.sun.star.svx.FindTextToolboxController"; +} + +sal_Bool SAL_CALL FindTextToolbarController::supportsService( const OUString& ServiceName ) +{ + return cppu::supportsService(this, ServiceName); +} + +css::uno::Sequence< OUString > SAL_CALL FindTextToolbarController::getSupportedServiceNames() +{ + return { "com.sun.star.frame.ToolbarController" }; +} + +// XComponent +void SAL_CALL FindTextToolbarController::dispose() +{ + SolarMutexGuard aSolarMutexGuard; + + SearchToolbarControllersManager::createControllersManager().freeController(m_xFrame, m_aCommandURL); + + svt::ToolboxController::dispose(); + if (m_pFindTextFieldControl != nullptr) { + SearchToolbarControllersManager::createControllersManager() + .saveSearchHistory(m_pFindTextFieldControl); + m_pFindTextFieldControl.disposeAndClear(); + } +} + +// XInitialization +void SAL_CALL FindTextToolbarController::initialize( const css::uno::Sequence< css::uno::Any >& aArguments ) +{ + svt::ToolboxController::initialize(aArguments); + + VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow( getParent() ); + ToolBox* pToolBox = static_cast<ToolBox*>(pWindow.get()); + if ( pToolBox ) + { + m_nDownSearchId = pToolBox->GetItemId(COMMAND_DOWNSEARCH); + m_nUpSearchId = pToolBox->GetItemId(COMMAND_UPSEARCH); + m_nFindAllId = pToolBox->GetItemId(COMMAND_FINDALL); + } + + SearchToolbarControllersManager::createControllersManager().registryController(m_xFrame, css::uno::Reference< css::frame::XStatusListener >(static_cast< ::cppu::OWeakObject* >(this), css::uno::UNO_QUERY), m_aCommandURL); +} + +css::uno::Reference< css::awt::XWindow > SAL_CALL FindTextToolbarController::createItemWindow( const css::uno::Reference< css::awt::XWindow >& xParent ) +{ + css::uno::Reference< css::awt::XWindow > xItemWindow; + + VclPtr<vcl::Window> pParent = VCLUnoHelper::GetWindow( xParent ); + if ( pParent ) + { + ToolBox* pToolbar = static_cast<ToolBox*>(pParent.get()); + m_pFindTextFieldControl = VclPtr<FindTextFieldControl>::Create(pToolbar, m_xFrame, m_xContext); + + m_pFindTextFieldControl->connect_changed(LINK(this, FindTextToolbarController, EditModifyHdl)); + SearchToolbarControllersManager::createControllersManager().loadSearchHistory(m_pFindTextFieldControl); + } + xItemWindow = VCLUnoHelper::GetInterface( m_pFindTextFieldControl ); + + return xItemWindow; +} + +// XStatusListener +void SAL_CALL FindTextToolbarController::statusChanged( const css::frame::FeatureStateEvent& rEvent ) +{ + SolarMutexGuard aSolarMutexGuard; + if ( m_bDisposed ) + return; + + OUString aFeatureURL = rEvent.FeatureURL.Complete; + if ( aFeatureURL == "AppendSearchHistory" ) + { + m_pFindTextFieldControl->Remember_Impl(m_pFindTextFieldControl->get_active_text()); + } + // enable up/down buttons in case there is already text (from the search history) + textfieldChanged(); +} + +IMPL_LINK_NOARG(FindTextToolbarController, EditModifyHdl, weld::ComboBox&, void) +{ + // Clear SearchLabel when search string altered + #if HAVE_FEATURE_DESKTOP + SvxSearchDialogWrapper::SetSearchLabel(SearchLabel::Empty); + #endif + + textfieldChanged(); +} + +void FindTextToolbarController::textfieldChanged() { + // enable or disable item DownSearch/UpSearch/FindAll of findbar + VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow( getParent() ); + ToolBox* pToolBox = static_cast<ToolBox*>(pWindow.get()); + if ( pToolBox && m_pFindTextFieldControl ) + { + bool enableButtons = !m_pFindTextFieldControl->get_active_text().isEmpty(); + pToolBox->EnableItem(m_nDownSearchId, enableButtons); + pToolBox->EnableItem(m_nUpSearchId, enableButtons); + pToolBox->EnableItem(m_nFindAllId, enableButtons); + } +} + +class UpDownSearchToolboxController : public svt::ToolboxController, + public css::lang::XServiceInfo +{ +public: + enum Type { UP, DOWN }; + + UpDownSearchToolboxController( const css::uno::Reference< css::uno::XComponentContext >& rxContext, Type eType ); + + // XInterface + virtual css::uno::Any SAL_CALL queryInterface( const css::uno::Type& aType ) override; + virtual void SAL_CALL acquire() throw () override; + virtual void SAL_CALL release() throw () override; + + // XServiceInfo + virtual OUString SAL_CALL getImplementationName() override; + virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override; + virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override; + + // XComponent + virtual void SAL_CALL dispose() override; + + // XInitialization + virtual void SAL_CALL initialize( const css::uno::Sequence< css::uno::Any >& aArguments ) override; + + // XToolbarController + virtual void SAL_CALL execute( sal_Int16 KeyModifier ) override; + + // XStatusListener + virtual void SAL_CALL statusChanged( const css::frame::FeatureStateEvent& rEvent ) override; + +private: + Type meType; +}; + +UpDownSearchToolboxController::UpDownSearchToolboxController( const css::uno::Reference< css::uno::XComponentContext > & rxContext, Type eType ) + : svt::ToolboxController( rxContext, + css::uno::Reference< css::frame::XFrame >(), + (eType == UP) ? OUString( COMMAND_UPSEARCH ): OUString( COMMAND_DOWNSEARCH ) ), + meType( eType ) +{ +} + +// XInterface +css::uno::Any SAL_CALL UpDownSearchToolboxController::queryInterface( const css::uno::Type& aType ) +{ + css::uno::Any a = ToolboxController::queryInterface( aType ); + if ( a.hasValue() ) + return a; + + return ::cppu::queryInterface( aType, static_cast< css::lang::XServiceInfo* >( this ) ); +} + +void SAL_CALL UpDownSearchToolboxController::acquire() throw () +{ + ToolboxController::acquire(); +} + +void SAL_CALL UpDownSearchToolboxController::release() throw () +{ + ToolboxController::release(); +} + +// XServiceInfo +OUString SAL_CALL UpDownSearchToolboxController::getImplementationName() +{ + return meType == UpDownSearchToolboxController::UP? + OUString( "com.sun.star.svx.UpSearchToolboxController" ) : + OUString( "com.sun.star.svx.DownSearchToolboxController" ); +} + +sal_Bool SAL_CALL UpDownSearchToolboxController::supportsService( const OUString& ServiceName ) +{ + return cppu::supportsService(this, ServiceName); +} + +css::uno::Sequence< OUString > SAL_CALL UpDownSearchToolboxController::getSupportedServiceNames() +{ + return { "com.sun.star.frame.ToolbarController" }; +} + +// XComponent +void SAL_CALL UpDownSearchToolboxController::dispose() +{ + SolarMutexGuard aSolarMutexGuard; + + SearchToolbarControllersManager::createControllersManager().freeController(m_xFrame, m_aCommandURL); + + svt::ToolboxController::dispose(); +} + +// XInitialization +void SAL_CALL UpDownSearchToolboxController::initialize( const css::uno::Sequence< css::uno::Any >& aArguments ) +{ + svt::ToolboxController::initialize( aArguments ); + SearchToolbarControllersManager::createControllersManager().registryController(m_xFrame, css::uno::Reference< css::frame::XStatusListener >(static_cast< ::cppu::OWeakObject* >(this), css::uno::UNO_QUERY), m_aCommandURL); +} + +// XToolbarController +void SAL_CALL UpDownSearchToolboxController::execute( sal_Int16 /*KeyModifier*/ ) +{ + if ( m_bDisposed ) + throw css::lang::DisposedException(); + + VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow( getParent() ); + ToolBox* pToolBox = static_cast<ToolBox*>(pWindow.get()); + + impl_executeSearch(m_xContext, m_xFrame, pToolBox, meType == UP ); + + css::frame::FeatureStateEvent aEvent; + aEvent.FeatureURL.Complete = "AppendSearchHistory"; + css::uno::Reference< css::frame::XStatusListener > xStatusListener = SearchToolbarControllersManager::createControllersManager().findController(m_xFrame, COMMAND_FINDTEXT); + if (xStatusListener.is()) + xStatusListener->statusChanged( aEvent ); +} + +// XStatusListener +void SAL_CALL UpDownSearchToolboxController::statusChanged( const css::frame::FeatureStateEvent& /*rEvent*/ ) +{ +} + +class MatchCaseToolboxController : public svt::ToolboxController, + public css::lang::XServiceInfo +{ +public: + MatchCaseToolboxController( const css::uno::Reference< css::uno::XComponentContext >& rxContext ); + + // XInterface + virtual css::uno::Any SAL_CALL queryInterface( const css::uno::Type& aType ) override; + virtual void SAL_CALL acquire() throw () override; + virtual void SAL_CALL release() throw () override; + + // XServiceInfo + virtual OUString SAL_CALL getImplementationName() override; + virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override; + virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override; + + // XComponent + virtual void SAL_CALL dispose() override; + + // XInitialization + virtual void SAL_CALL initialize( const css::uno::Sequence< css::uno::Any >& aArguments ) override; + + // XToolbarController + virtual css::uno::Reference< css::awt::XWindow > SAL_CALL createItemWindow( const css::uno::Reference< css::awt::XWindow >& Parent ) override; + + // XStatusListener + virtual void SAL_CALL statusChanged( const css::frame::FeatureStateEvent& rEvent ) override; + +private: + VclPtr<CheckButtonItemWindow> m_xMatchCaseControl; +}; + +MatchCaseToolboxController::MatchCaseToolboxController( const css::uno::Reference< css::uno::XComponentContext >& rxContext ) + : svt::ToolboxController( rxContext, + css::uno::Reference< css::frame::XFrame >(), + COMMAND_MATCHCASE ) + , m_xMatchCaseControl(nullptr) +{ +} + +// XInterface +css::uno::Any SAL_CALL MatchCaseToolboxController::queryInterface( const css::uno::Type& aType ) +{ + css::uno::Any a = ToolboxController::queryInterface( aType ); + if ( a.hasValue() ) + return a; + + return ::cppu::queryInterface( aType, static_cast< css::lang::XServiceInfo* >( this ) ); +} + +void SAL_CALL MatchCaseToolboxController::acquire() throw () +{ + ToolboxController::acquire(); +} + +void SAL_CALL MatchCaseToolboxController::release() throw () +{ + ToolboxController::release(); +} + +// XServiceInfo +OUString SAL_CALL MatchCaseToolboxController::getImplementationName() +{ + return "com.sun.star.svx.MatchCaseToolboxController"; +} + +sal_Bool SAL_CALL MatchCaseToolboxController::supportsService( const OUString& ServiceName ) +{ + return cppu::supportsService(this, ServiceName); +} + +css::uno::Sequence< OUString > SAL_CALL MatchCaseToolboxController::getSupportedServiceNames() +{ + return { "com.sun.star.frame.ToolbarController" }; +} + +// XComponent +void SAL_CALL MatchCaseToolboxController::dispose() +{ + SolarMutexGuard aSolarMutexGuard; + + SearchToolbarControllersManager::createControllersManager().freeController(m_xFrame, m_aCommandURL); + + svt::ToolboxController::dispose(); + + m_xMatchCaseControl.disposeAndClear(); +} + +// XInitialization +void SAL_CALL MatchCaseToolboxController::initialize( const css::uno::Sequence< css::uno::Any >& aArguments ) +{ + svt::ToolboxController::initialize(aArguments); + + SearchToolbarControllersManager::createControllersManager().registryController(m_xFrame, css::uno::Reference< css::frame::XStatusListener >(static_cast< ::cppu::OWeakObject* >(this), css::uno::UNO_QUERY), m_aCommandURL); +} + +css::uno::Reference< css::awt::XWindow > SAL_CALL MatchCaseToolboxController::createItemWindow( const css::uno::Reference< css::awt::XWindow >& xParent ) +{ + css::uno::Reference< css::awt::XWindow > xItemWindow; + + VclPtr<vcl::Window> pParent = VCLUnoHelper::GetWindow( xParent ); + if ( pParent ) + { + ToolBox* pToolbar = static_cast<ToolBox*>(pParent.get()); + m_xMatchCaseControl = VclPtr<CheckButtonItemWindow>::Create(pToolbar, SvxResId(RID_SVXSTR_FINDBAR_MATCHCASE)); + } + xItemWindow = VCLUnoHelper::GetInterface(m_xMatchCaseControl); + + return xItemWindow; +} + +// XStatusListener +void SAL_CALL MatchCaseToolboxController::statusChanged( const css::frame::FeatureStateEvent& ) +{ +} + +class SearchFormattedToolboxController : public svt::ToolboxController, + public css::lang::XServiceInfo +{ +public: + SearchFormattedToolboxController( const css::uno::Reference< css::uno::XComponentContext >& rxContext ); + + // XInterface + virtual css::uno::Any SAL_CALL queryInterface( const css::uno::Type& aType ) override; + virtual void SAL_CALL acquire() throw () override; + virtual void SAL_CALL release() throw () override; + + // XServiceInfo + virtual OUString SAL_CALL getImplementationName() override; + virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override; + virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override; + + // XComponent + virtual void SAL_CALL dispose() override; + + // XInitialization + virtual void SAL_CALL initialize( const css::uno::Sequence< css::uno::Any >& aArguments ) override; + + // XToolbarController + virtual css::uno::Reference< css::awt::XWindow > SAL_CALL createItemWindow( const css::uno::Reference< css::awt::XWindow >& Parent ) override; + + // XStatusListener + virtual void SAL_CALL statusChanged( const css::frame::FeatureStateEvent& rEvent ) override; + +private: + VclPtr<CheckButtonItemWindow> m_xSearchFormattedControl; +}; + +SearchFormattedToolboxController::SearchFormattedToolboxController( const css::uno::Reference< css::uno::XComponentContext >& rxContext ) + : svt::ToolboxController( rxContext, + css::uno::Reference< css::frame::XFrame >(), + COMMAND_SEARCHFORMATTED ) + , m_xSearchFormattedControl(nullptr) +{ +} + +// XInterface +css::uno::Any SAL_CALL SearchFormattedToolboxController::queryInterface( const css::uno::Type& aType ) +{ + css::uno::Any a = ToolboxController::queryInterface( aType ); + if ( a.hasValue() ) + return a; + + return ::cppu::queryInterface( aType, static_cast< css::lang::XServiceInfo* >( this ) ); +} + +void SAL_CALL SearchFormattedToolboxController::acquire() throw () +{ + ToolboxController::acquire(); +} + +void SAL_CALL SearchFormattedToolboxController::release() throw () +{ + ToolboxController::release(); +} + +// XServiceInfo +OUString SAL_CALL SearchFormattedToolboxController::getImplementationName() +{ + return "com.sun.star.svx.SearchFormattedToolboxController"; +} + +sal_Bool SAL_CALL SearchFormattedToolboxController::supportsService( const OUString& ServiceName ) +{ + return cppu::supportsService(this, ServiceName); +} + +css::uno::Sequence< OUString > SAL_CALL SearchFormattedToolboxController::getSupportedServiceNames() +{ + return { "com.sun.star.frame.ToolbarController" }; +} + +// XComponent +void SAL_CALL SearchFormattedToolboxController::dispose() +{ + SolarMutexGuard aSolarMutexGuard; + + SearchToolbarControllersManager::createControllersManager().freeController(m_xFrame, m_aCommandURL); + + svt::ToolboxController::dispose(); + + m_xSearchFormattedControl.disposeAndClear(); +} + +// XInitialization +void SAL_CALL SearchFormattedToolboxController::initialize( const css::uno::Sequence< css::uno::Any >& aArguments ) +{ + svt::ToolboxController::initialize(aArguments); + + SearchToolbarControllersManager::createControllersManager().registryController(m_xFrame, css::uno::Reference< css::frame::XStatusListener >(static_cast< ::cppu::OWeakObject* >(this), css::uno::UNO_QUERY), m_aCommandURL); +} + +css::uno::Reference< css::awt::XWindow > SAL_CALL SearchFormattedToolboxController::createItemWindow( const css::uno::Reference< css::awt::XWindow >& xParent ) +{ + css::uno::Reference< css::awt::XWindow > xItemWindow; + + VclPtr<vcl::Window> pParent = VCLUnoHelper::GetWindow( xParent ); + if ( pParent ) + { + ToolBox* pToolbar = static_cast<ToolBox*>(pParent.get()); + m_xSearchFormattedControl = VclPtr<CheckButtonItemWindow>::Create(pToolbar, SvxResId(RID_SVXSTR_FINDBAR_SEARCHFORMATTED)); + } + xItemWindow = VCLUnoHelper::GetInterface(m_xSearchFormattedControl); + + return xItemWindow; +} + +// XStatusListener +void SAL_CALL SearchFormattedToolboxController::statusChanged( const css::frame::FeatureStateEvent& ) +{ +} + +class FindAllToolboxController : public svt::ToolboxController, + public css::lang::XServiceInfo +{ +public: + FindAllToolboxController( const css::uno::Reference< css::uno::XComponentContext >& rxContext ); + + // XInterface + virtual css::uno::Any SAL_CALL queryInterface( const css::uno::Type& aType ) override; + virtual void SAL_CALL acquire() throw () override; + virtual void SAL_CALL release() throw () override; + + // XServiceInfo + virtual OUString SAL_CALL getImplementationName() override; + virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override; + virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override; + + // XComponent + virtual void SAL_CALL dispose() override; + + // XInitialization + virtual void SAL_CALL initialize( const css::uno::Sequence< css::uno::Any >& aArguments ) override; + + // XToolbarController + virtual void SAL_CALL execute( sal_Int16 KeyModifier ) override; + + // XStatusListener + virtual void SAL_CALL statusChanged( const css::frame::FeatureStateEvent& rEvent ) override; +}; + +FindAllToolboxController::FindAllToolboxController( const css::uno::Reference< css::uno::XComponentContext > & rxContext ) + : svt::ToolboxController( rxContext, + css::uno::Reference< css::frame::XFrame >(), + ".uno:FindAll" ) +{ +} + +// XInterface +css::uno::Any SAL_CALL FindAllToolboxController::queryInterface( const css::uno::Type& aType ) +{ + css::uno::Any a = ToolboxController::queryInterface( aType ); + if ( a.hasValue() ) + return a; + + return ::cppu::queryInterface( aType, static_cast< css::lang::XServiceInfo* >( this ) ); +} + +void SAL_CALL FindAllToolboxController::acquire() throw () +{ + ToolboxController::acquire(); +} + +void SAL_CALL FindAllToolboxController::release() throw () +{ + ToolboxController::release(); +} + +// XServiceInfo +OUString SAL_CALL FindAllToolboxController::getImplementationName() +{ + return "com.sun.star.svx.FindAllToolboxController"; +} + + +sal_Bool SAL_CALL FindAllToolboxController::supportsService( const OUString& ServiceName ) +{ + return cppu::supportsService(this, ServiceName); +} + +css::uno::Sequence< OUString > SAL_CALL FindAllToolboxController::getSupportedServiceNames() +{ + return { "com.sun.star.frame.ToolbarController" }; +} + +// XComponent +void SAL_CALL FindAllToolboxController::dispose() +{ + SolarMutexGuard aSolarMutexGuard; + + SearchToolbarControllersManager::createControllersManager().freeController(m_xFrame, m_aCommandURL); + + svt::ToolboxController::dispose(); +} + +// XInitialization +void SAL_CALL FindAllToolboxController::initialize( const css::uno::Sequence< css::uno::Any >& aArguments ) +{ + svt::ToolboxController::initialize( aArguments ); + SearchToolbarControllersManager::createControllersManager().registryController(m_xFrame, css::uno::Reference< css::frame::XStatusListener >(static_cast< ::cppu::OWeakObject* >(this), css::uno::UNO_QUERY), m_aCommandURL); +} + +// XToolbarController +void SAL_CALL FindAllToolboxController::execute( sal_Int16 /*KeyModifier*/ ) +{ + if ( m_bDisposed ) + throw css::lang::DisposedException(); + + VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow( getParent() ); + ToolBox* pToolBox = static_cast<ToolBox*>(pWindow.get()); + + impl_executeSearch(m_xContext, m_xFrame, pToolBox, false, true); +} + +// XStatusListener +void SAL_CALL FindAllToolboxController::statusChanged( const css::frame::FeatureStateEvent& /*rEvent*/ ) +{ +} + +class ExitSearchToolboxController : public svt::ToolboxController, + public css::lang::XServiceInfo +{ +public: + ExitSearchToolboxController( const css::uno::Reference< css::uno::XComponentContext >& rxContext ); + + // XInterface + virtual css::uno::Any SAL_CALL queryInterface( const css::uno::Type& aType ) override; + virtual void SAL_CALL acquire() throw () override; + virtual void SAL_CALL release() throw () override; + + // XServiceInfo + virtual OUString SAL_CALL getImplementationName() override; + virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override; + virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override; + + // XComponent + virtual void SAL_CALL dispose() override; + + // XInitialization + virtual void SAL_CALL initialize( const css::uno::Sequence< css::uno::Any >& aArguments ) override; + + // XToolbarController + virtual void SAL_CALL execute( sal_Int16 KeyModifier ) override; + + // XStatusListener + virtual void SAL_CALL statusChanged( const css::frame::FeatureStateEvent& rEvent ) override; +}; + +ExitSearchToolboxController::ExitSearchToolboxController( const css::uno::Reference< css::uno::XComponentContext > & rxContext ) + : svt::ToolboxController( rxContext, + css::uno::Reference< css::frame::XFrame >(), + ".uno:ExitSearch" ) +{ +} + +// XInterface +css::uno::Any SAL_CALL ExitSearchToolboxController::queryInterface( const css::uno::Type& aType ) +{ + css::uno::Any a = ToolboxController::queryInterface( aType ); + if ( a.hasValue() ) + return a; + + return ::cppu::queryInterface( aType, static_cast< css::lang::XServiceInfo* >( this ) ); +} + +void SAL_CALL ExitSearchToolboxController::acquire() throw () +{ + ToolboxController::acquire(); +} + +void SAL_CALL ExitSearchToolboxController::release() throw () +{ + ToolboxController::release(); +} + +// XServiceInfo +OUString SAL_CALL ExitSearchToolboxController::getImplementationName() +{ + return "com.sun.star.svx.ExitFindbarToolboxController"; +} + + +sal_Bool SAL_CALL ExitSearchToolboxController::supportsService( const OUString& ServiceName ) +{ + return cppu::supportsService(this, ServiceName); +} + +css::uno::Sequence< OUString > SAL_CALL ExitSearchToolboxController::getSupportedServiceNames() +{ + return { "com.sun.star.frame.ToolbarController" }; +} + +// XComponent +void SAL_CALL ExitSearchToolboxController::dispose() +{ + SolarMutexGuard aSolarMutexGuard; + + SearchToolbarControllersManager::createControllersManager().freeController(m_xFrame, m_aCommandURL); + + svt::ToolboxController::dispose(); +} + +// XInitialization +void SAL_CALL ExitSearchToolboxController::initialize( const css::uno::Sequence< css::uno::Any >& aArguments ) +{ + svt::ToolboxController::initialize( aArguments ); + SearchToolbarControllersManager::createControllersManager().registryController(m_xFrame, css::uno::Reference< css::frame::XStatusListener >(static_cast< ::cppu::OWeakObject* >(this), css::uno::UNO_QUERY), m_aCommandURL); +} + +// XToolbarController +void SAL_CALL ExitSearchToolboxController::execute( sal_Int16 /*KeyModifier*/ ) +{ + vcl::Window *pFocusWindow = Application::GetFocusWindow(); + if ( pFocusWindow ) + pFocusWindow->GrabFocusToDocument(); + + // hide the findbar + css::uno::Reference< css::beans::XPropertySet > xPropSet(m_xFrame, css::uno::UNO_QUERY); + if (xPropSet.is()) + { + css::uno::Reference< css::frame::XLayoutManager > xLayoutManager; + css::uno::Any aValue = xPropSet->getPropertyValue("LayoutManager"); + aValue >>= xLayoutManager; + if (xLayoutManager.is()) + { + const OUString sResourceURL( "private:resource/toolbar/findbar" ); + xLayoutManager->hideElement( sResourceURL ); + xLayoutManager->destroyElement( sResourceURL ); + } + } +} + +// XStatusListener +void SAL_CALL ExitSearchToolboxController::statusChanged( const css::frame::FeatureStateEvent& /*rEvent*/ ) +{ +} + +class SearchLabelToolboxController : public svt::ToolboxController, + public css::lang::XServiceInfo +{ +public: + SearchLabelToolboxController( const css::uno::Reference< css::uno::XComponentContext >& rxContext ); + + // XInterface + virtual css::uno::Any SAL_CALL queryInterface( const css::uno::Type& aType ) override; + virtual void SAL_CALL acquire() throw () override; + virtual void SAL_CALL release() throw () override; + + // XServiceInfo + virtual OUString SAL_CALL getImplementationName() override; + virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override; + virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override; + + // XComponent + virtual void SAL_CALL dispose() override; + + // XInitialization + virtual void SAL_CALL initialize( const css::uno::Sequence< css::uno::Any >& aArguments ) override; + + // XToolbarController + virtual css::uno::Reference< css::awt::XWindow > SAL_CALL createItemWindow( const css::uno::Reference< css::awt::XWindow >& Parent ) override; + + // XStatusListener + virtual void SAL_CALL statusChanged( const css::frame::FeatureStateEvent& rEvent ) override; + +private: + VclPtr<LabelItemWindow> m_xSL; +}; + +SearchLabelToolboxController::SearchLabelToolboxController( const css::uno::Reference< css::uno::XComponentContext > & rxContext ) + : svt::ToolboxController( rxContext, + css::uno::Reference< css::frame::XFrame >(), + ".uno:SearchLabel" ) +{ +} + +// XInterface +css::uno::Any SAL_CALL SearchLabelToolboxController::queryInterface( const css::uno::Type& aType ) +{ + css::uno::Any a = ToolboxController::queryInterface( aType ); + if ( a.hasValue() ) + return a; + + return ::cppu::queryInterface( aType, static_cast< css::lang::XServiceInfo* >( this ) ); +} + +void SAL_CALL SearchLabelToolboxController::acquire() throw () +{ + ToolboxController::acquire(); +} + +void SAL_CALL SearchLabelToolboxController::release() throw () +{ + ToolboxController::release(); +} + +// XServiceInfo +OUString SAL_CALL SearchLabelToolboxController::getImplementationName() +{ + return "com.sun.star.svx.SearchLabelToolboxController"; +} + + +sal_Bool SAL_CALL SearchLabelToolboxController::supportsService( const OUString& ServiceName ) +{ + return cppu::supportsService(this, ServiceName); +} + +css::uno::Sequence< OUString > SAL_CALL SearchLabelToolboxController::getSupportedServiceNames() +{ + return { "com.sun.star.frame.ToolbarController" }; +} + +// XComponent +void SAL_CALL SearchLabelToolboxController::dispose() +{ + SolarMutexGuard aSolarMutexGuard; + + SearchToolbarControllersManager::createControllersManager().freeController(m_xFrame, m_aCommandURL); + + svt::ToolboxController::dispose(); + m_xSL.disposeAndClear(); +} + +// XInitialization +void SAL_CALL SearchLabelToolboxController::initialize( const css::uno::Sequence< css::uno::Any >& aArguments ) +{ + svt::ToolboxController::initialize( aArguments ); + SearchToolbarControllersManager::createControllersManager().registryController(m_xFrame, css::uno::Reference< css::frame::XStatusListener >(static_cast< ::cppu::OWeakObject* >(this), css::uno::UNO_QUERY), m_aCommandURL); +} + +// XStatusListener +void SAL_CALL SearchLabelToolboxController::statusChanged( const css::frame::FeatureStateEvent& ) +{ + if (m_xSL) + { + OUString aStr = SvxSearchDialogWrapper::GetSearchLabel(); + m_xSL->set_label(aStr); + m_xSL->SetOptimalSize(); + Size aSize(m_xSL->GetSizePixel()); + long nWidth = !aStr.isEmpty() ? aSize.getWidth() : 16; + m_xSL->SetSizePixel(Size(nWidth, aSize.Height())); + } +} + +css::uno::Reference< css::awt::XWindow > SAL_CALL SearchLabelToolboxController::createItemWindow( const css::uno::Reference< css::awt::XWindow >& Parent ) +{ + ToolBox* pToolBox = nullptr; + sal_uInt16 nId = 0; + if (getToolboxId(nId, &pToolBox)) + pToolBox->SetItemWindowNonInteractive(nId, true); + + m_xSL = VclPtr<LabelItemWindow>::Create(VCLUnoHelper::GetWindow(Parent), ""); + m_xSL->SetSizePixel(Size(16, m_xSL->GetSizePixel().Height())); + return VCLUnoHelper::GetInterface(m_xSL); +} + +// protocol handler for "vnd.sun.star.findbar:*" URLs +// The dispatch object will be used for shortcut commands for findbar +class FindbarDispatcher : public css::lang::XServiceInfo, + public css::lang::XInitialization, + public css::frame::XDispatchProvider, + public css::frame::XDispatch, + public ::cppu::OWeakObject +{ +public: + + FindbarDispatcher(); + virtual ~FindbarDispatcher() override; + + // XInterface + virtual css::uno::Any SAL_CALL queryInterface( const css::uno::Type& aType ) override; + virtual void SAL_CALL acquire() throw() override; + virtual void SAL_CALL release() throw() override; + + // XServiceInfo + virtual OUString SAL_CALL getImplementationName() override; + virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override; + virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override; + + // XInitialization + virtual void SAL_CALL initialize( const css::uno::Sequence< css::uno::Any >& aArguments ) override; + + // XDispatchProvider + virtual css::uno::Reference< css::frame::XDispatch > SAL_CALL queryDispatch( const css::util::URL& aURL, const OUString& sTargetFrameName , sal_Int32 nSearchFlags ) override; + virtual css::uno::Sequence< css::uno::Reference< css::frame::XDispatch > > SAL_CALL queryDispatches( const css::uno::Sequence< css::frame::DispatchDescriptor >& lDescriptions ) override; + + // XDispatch + virtual void SAL_CALL dispatch( const css::util::URL& aURL, const css::uno::Sequence< css::beans::PropertyValue >& lArguments ) override; + virtual void SAL_CALL addStatusListener( const css::uno::Reference< css::frame::XStatusListener >& xListener, const css::util::URL& aURL ) override; + virtual void SAL_CALL removeStatusListener( const css::uno::Reference< css::frame::XStatusListener >& xListener, const css::util::URL& aURL ) override; + +private: + + css::uno::Reference< css::frame::XFrame > m_xFrame; + +}; + +FindbarDispatcher::FindbarDispatcher() +{ +} + +FindbarDispatcher::~FindbarDispatcher() +{ + m_xFrame = nullptr; +} + +// XInterface +css::uno::Any SAL_CALL FindbarDispatcher::queryInterface( const css::uno::Type& aType ) +{ + css::uno::Any aReturn( ::cppu::queryInterface( aType, + static_cast< css::lang::XServiceInfo* >(this), + static_cast< css::lang::XInitialization* >(this), + static_cast< css::frame::XDispatchProvider* >(this), + static_cast< css::frame::XDispatch* >(this)) ); + + if ( aReturn.hasValue() ) + return aReturn; + + return OWeakObject::queryInterface( aType ); +} + +void SAL_CALL FindbarDispatcher::acquire() throw() +{ + OWeakObject::acquire(); +} + +void SAL_CALL FindbarDispatcher::release() throw() +{ + OWeakObject::release(); +} + +// XServiceInfo +OUString SAL_CALL FindbarDispatcher::getImplementationName() +{ + return "com.sun.star.comp.svx.Impl.FindbarDispatcher"; +} + +sal_Bool SAL_CALL FindbarDispatcher::supportsService( const OUString& ServiceName ) +{ + return cppu::supportsService(this, ServiceName); +} + +css::uno::Sequence< OUString > SAL_CALL FindbarDispatcher::getSupportedServiceNames() +{ + return { "com.sun.star.comp.svx.FindbarDispatcher", "com.sun.star.frame.ProtocolHandler" }; +} + +// XInitialization +void SAL_CALL FindbarDispatcher::initialize( const css::uno::Sequence< css::uno::Any >& aArguments ) +{ + if ( aArguments.hasElements() ) + aArguments[0] >>= m_xFrame; +} + +// XDispatchProvider +css::uno::Reference< css::frame::XDispatch > SAL_CALL FindbarDispatcher::queryDispatch( const css::util::URL& aURL, const OUString& /*sTargetFrameName*/, sal_Int32 /*nSearchFlags*/ ) +{ + css::uno::Reference< css::frame::XDispatch > xDispatch; + + if ( aURL.Protocol == "vnd.sun.star.findbar:" ) + xDispatch = this; + + return xDispatch; +} + +css::uno::Sequence < css::uno::Reference< css::frame::XDispatch > > SAL_CALL FindbarDispatcher::queryDispatches( const css::uno::Sequence < css::frame::DispatchDescriptor >& seqDescripts ) +{ + sal_Int32 nCount = seqDescripts.getLength(); + css::uno::Sequence < css::uno::Reference < XDispatch > > lDispatcher( nCount ); + + std::transform(seqDescripts.begin(), seqDescripts.end(), lDispatcher.begin(), + [this](const css::frame::DispatchDescriptor& rDescript) -> css::uno::Reference < XDispatch > { + return queryDispatch( rDescript.FeatureURL, rDescript.FrameName, rDescript.SearchFlags ); }); + + return lDispatcher; +} + +// XDispatch +void SAL_CALL FindbarDispatcher::dispatch( const css::util::URL& aURL, const css::uno::Sequence < css::beans::PropertyValue >& /*lArgs*/ ) +{ + //vnd.sun.star.findbar:FocusToFindbar - set cursor to the FindTextFieldControl of the findbar + if ( aURL.Path != "FocusToFindbar" ) + return; + + css::uno::Reference< css::beans::XPropertySet > xPropSet(m_xFrame, css::uno::UNO_QUERY); + if(!xPropSet.is()) + return; + + css::uno::Reference< css::frame::XLayoutManager > xLayoutManager; + css::uno::Any aValue = xPropSet->getPropertyValue("LayoutManager"); + aValue >>= xLayoutManager; + if (!xLayoutManager.is()) + return; + + const OUString sResourceURL( "private:resource/toolbar/findbar" ); + css::uno::Reference< css::ui::XUIElement > xUIElement = xLayoutManager->getElement(sResourceURL); + if (!xUIElement.is()) + { + // show the findbar if necessary + xLayoutManager->createElement( sResourceURL ); + xLayoutManager->showElement( sResourceURL ); + xUIElement = xLayoutManager->getElement( sResourceURL ); + if ( !xUIElement.is() ) + return; + } + + css::uno::Reference< css::awt::XWindow > xWindow(xUIElement->getRealInterface(), css::uno::UNO_QUERY); + VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow( xWindow ); + ToolBox* pToolBox = static_cast<ToolBox*>(pWindow.get()); + if ( pToolBox ) + { + ToolBox::ImplToolItems::size_type nItemCount = pToolBox->GetItemCount(); + for ( ToolBox::ImplToolItems::size_type i=0; i<nItemCount; ++i ) + { + sal_uInt16 id = pToolBox->GetItemId(i); + OUString sItemCommand = pToolBox->GetItemCommand(id); + if ( sItemCommand == COMMAND_FINDTEXT ) + { + vcl::Window* pItemWin = pToolBox->GetItemWindow( id ); + if ( pItemWin ) + { + SolarMutexGuard aSolarMutexGuard; + FindTextFieldControl* pFindTextFieldControl = dynamic_cast<FindTextFieldControl*>(pItemWin); + if ( pFindTextFieldControl ) + pFindTextFieldControl->SetTextToSelected_Impl(); + pItemWin->GrabFocus(); + return; + } + } + } + } +} + +void SAL_CALL FindbarDispatcher::addStatusListener( const css::uno::Reference< css::frame::XStatusListener >& /*xControl*/, const css::util::URL& /*aURL*/ ) +{ +} + +void SAL_CALL FindbarDispatcher::removeStatusListener( const css::uno::Reference< css::frame::XStatusListener >& /*xControl*/, const css::util::URL& /*aURL*/ ) +{ +} + +} + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * +com_sun_star_svx_FindTextToolboxController_get_implementation( + css::uno::XComponentContext *context, + css::uno::Sequence<css::uno::Any> const &) +{ + return cppu::acquire(new FindTextToolbarController(context)); +} + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * +com_sun_star_svx_ExitFindbarToolboxController_get_implementation( + css::uno::XComponentContext *context, + css::uno::Sequence<css::uno::Any> const &) +{ + return cppu::acquire(new ExitSearchToolboxController(context)); +} + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * +com_sun_star_svx_UpSearchToolboxController_get_implementation( + css::uno::XComponentContext *context, + css::uno::Sequence<css::uno::Any> const &) +{ + return cppu::acquire(new UpDownSearchToolboxController(context, UpDownSearchToolboxController::UP)); +} + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * +com_sun_star_svx_DownSearchToolboxController_get_implementation( + css::uno::XComponentContext *context, + css::uno::Sequence<css::uno::Any> const &) +{ + return cppu::acquire(new UpDownSearchToolboxController(context, UpDownSearchToolboxController::DOWN)); +} + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * +com_sun_star_svx_MatchCaseToolboxController_get_implementation( + css::uno::XComponentContext *context, + css::uno::Sequence<css::uno::Any> const &) +{ + return cppu::acquire(new MatchCaseToolboxController(context)); +} + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * +com_sun_star_svx_SearchFormattedToolboxController_get_implementation( + css::uno::XComponentContext *context, + css::uno::Sequence<css::uno::Any> const &) +{ + return cppu::acquire(new SearchFormattedToolboxController(context)); +} + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * +com_sun_star_svx_FindAllToolboxController_get_implementation( + css::uno::XComponentContext *context, + css::uno::Sequence<css::uno::Any> const &) +{ + return cppu::acquire(new FindAllToolboxController(context)); +} + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * +com_sun_star_svx_SearchLabelToolboxController_get_implementation( + css::uno::XComponentContext *context, + css::uno::Sequence<css::uno::Any> const &) +{ + return cppu::acquire(new SearchLabelToolboxController(context)); +} + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * +com_sun_star_comp_svx_Impl_FindbarDispatcher_get_implementation( + SAL_UNUSED_PARAMETER css::uno::XComponentContext *, + css::uno::Sequence<css::uno::Any> const &) +{ + return cppu::acquire(new FindbarDispatcher); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/tbxctrls/tbxcolor.cxx b/svx/source/tbxctrls/tbxcolor.cxx new file mode 100644 index 000000000..4aa985bb7 --- /dev/null +++ b/svx/source/tbxctrls/tbxcolor.cxx @@ -0,0 +1,95 @@ +/* -*- 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 <svx/tbxcolor.hxx> +#include <sfx2/viewfrm.hxx> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <osl/diagnose.h> +#include <tools/diagnose_ex.h> + + +namespace svx +{ + + + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::frame; + using namespace ::com::sun::star::beans; + + ToolboxAccess::ToolboxAccess( const OUString& rToolboxName ) : + m_sToolboxResName ( "private:resource/toolbar/" ) + { + m_sToolboxResName += rToolboxName; + + // the layout manager + if ( SfxViewFrame::Current() ) + { + try + { + Reference< XFrame > xFrame = SfxViewFrame::Current()->GetFrame().GetFrameInterface(); + Reference< XPropertySet > xFrameProps( xFrame, UNO_QUERY ); + if ( xFrameProps.is() ) + xFrameProps->getPropertyValue( "LayoutManager" ) >>= m_xLayouter; + } + catch ( Exception const & ) + { + TOOLS_WARN_EXCEPTION( "svx.tbxcrtls", "ToolboxAccess::Ctor()" ); + } + } + } + + + void ToolboxAccess::toggleToolbox() const + { + try + { + Reference< XLayoutManager > xManager( m_xLayouter ); + OSL_ENSURE( xManager. is(), "ToolboxAccess::toggleToolbox: couldn't obtain the layout manager!" ); + if ( xManager. is() ) + { + if ( xManager->isElementVisible( m_sToolboxResName ) ) + { + xManager->hideElement( m_sToolboxResName ); + xManager->destroyElement( m_sToolboxResName ); + } + else + { + xManager->createElement( m_sToolboxResName ); + xManager->showElement( m_sToolboxResName ); + } + } + } + catch( const Exception& ) + { + TOOLS_WARN_EXCEPTION( "svx", "ToolboxAccess::toggleToolbox" ); + } + } + + + bool ToolboxAccess::isToolboxVisible() const + { + return ( m_xLayouter.is() && m_xLayouter->isElementVisible( m_sToolboxResName ) ); + } + + +} + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/tbxctrls/tbxcolorupdate.cxx b/svx/source/tbxctrls/tbxcolorupdate.cxx new file mode 100644 index 000000000..e1920affc --- /dev/null +++ b/svx/source/tbxctrls/tbxcolorupdate.cxx @@ -0,0 +1,338 @@ +/* -*- 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 <sfx2/objsh.hxx> +#include <svx/drawitem.hxx> +#include <svx/tbxcolorupdate.hxx> +#include <svx/svxids.hrc> +#include <svx/xdef.hxx> +#include <svx/xlineit0.hxx> +#include <svx/xlndsit.hxx> + +#include <vcl/commandinfoprovider.hxx> +#include <vcl/svapp.hxx> +#include <vcl/toolbox.hxx> +#include <vcl/virdev.hxx> +#include <vcl/weld.hxx> +#include <vcl/settings.hxx> + +#include <svx/strings.hrc> +#include <svx/dialmgr.hxx> + +namespace svx +{ + ToolboxButtonColorUpdaterBase::ToolboxButtonColorUpdaterBase(bool bWideButton, const OUString& rCommandLabel, + const OUString& rCommandURL, + const css::uno::Reference<css::frame::XFrame>& rFrame) + : mbWideButton(bWideButton) + , mbWasHiContrastMode(Application::GetSettings().GetStyleSettings().GetHighContrastMode()) + , maCurColor(COL_TRANSPARENT) + , meImageType(vcl::ImageType::Size16) + , maCommandLabel(rCommandLabel) + , maCommandURL(rCommandURL) + , mxFrame(rFrame) + { + } + + void ToolboxButtonColorUpdaterBase::Init(sal_uInt16 nSlotId) + { + switch (nSlotId) + { + case SID_ATTR_CHAR_COLOR: + case SID_ATTR_CHAR_COLOR2: + Update(NamedColor(COL_DEFAULT_FONT, SvxResId(RID_SVXSTR_COLOR_DEFAULT_FONT))); + break; + case SID_FRAME_LINECOLOR: + Update(NamedColor(COL_DEFAULT_FRAMELINE, SvxResId(RID_SVXSTR_COLOR_DEFAULT_FRAMELINE))); + break; + case SID_ATTR_CHAR_COLOR_BACKGROUND: + case SID_ATTR_CHAR_BACK_COLOR: + case SID_BACKGROUND_COLOR: + case SID_TABLE_CELL_BACKGROUND_COLOR: + Update(NamedColor(COL_DEFAULT_HIGHLIGHT, SvxResId(RID_SVXSTR_COLOR_DEFAULT_HIGHLIGHT))); + break; + case SID_ATTR_LINE_COLOR: + Update(NamedColor(COL_DEFAULT_SHAPE_STROKE, SvxResId(RID_SVXSTR_COLOR_DEFAULT_SHAPE_STROKE))); + break; + case SID_ATTR_FILL_COLOR: + Update(NamedColor(COL_DEFAULT_SHAPE_FILLING, SvxResId(RID_SVXSTR_COLOR_DEFAULT_SHAPE_FILLING))); + break; + default: + Update(COL_TRANSPARENT); + } + } + + VclToolboxButtonColorUpdater::VclToolboxButtonColorUpdater( + sal_uInt16 nSlotId, sal_uInt16 nTbxBtnId, ToolBox* pToolBox, bool bWideButton, + const OUString& rCommandLabel, const OUString& rCommandURL, + const css::uno::Reference<css::frame::XFrame>& rFrame) + : ToolboxButtonColorUpdaterBase(bWideButton, rCommandLabel, rCommandURL, rFrame) + , mnBtnId(nTbxBtnId) + , mpTbx(pToolBox) + { + Init(nSlotId); + } + + void VclToolboxButtonColorUpdater::SetQuickHelpText(const OUString& rText) + { + mpTbx->SetQuickHelpText(mnBtnId, rText); + } + + OUString VclToolboxButtonColorUpdater::GetQuickHelpText() const + { + return mpTbx->GetQuickHelpText(mnBtnId); + } + + void VclToolboxButtonColorUpdater::SetImage(VirtualDevice* pVirDev) + { + mpTbx->SetItemImage(mnBtnId, Image(pVirDev->GetBitmapEx(Point(0,0), maBmpSize))); + } + + VclPtr<VirtualDevice> VclToolboxButtonColorUpdater::CreateVirtualDevice() const + { + auto xRet = VclPtr<VirtualDevice>::Create(*mpTbx, + DeviceFormat::DEFAULT, DeviceFormat::DEFAULT); + xRet->SetBackground(mpTbx->GetControlBackground()); + return xRet; + } + + vcl::ImageType VclToolboxButtonColorUpdater::GetImageSize() const + { + return mpTbx->GetImageSize(); + } + + Size VclToolboxButtonColorUpdater::GetItemSize(const Size& rImageSize) const + { + if (mbWideButton) + return mpTbx->GetItemContentSize(mnBtnId); + return rImageSize; + } + + ToolboxButtonColorUpdaterBase::~ToolboxButtonColorUpdaterBase() + {} + + void ToolboxButtonColorUpdaterBase::Update(const NamedColor &rNamedColor) + { + Update(rNamedColor.first); + if (!mbWideButton) + { + // Also show the current color as QuickHelpText + OUString colorSuffix = OUString(" (%1)").replaceFirst("%1", rNamedColor.second); + OUString colorHelpText = maCommandLabel + colorSuffix; + + SetQuickHelpText(colorHelpText); + } + } + + void ToolboxButtonColorUpdaterBase::Update(const Color& rColor, bool bForceUpdate) + { + vcl::ImageType eImageType = GetImageSize(); + +#ifdef IOS // tdf#126966 + eImageType = vcl::ImageType::Size32; +#endif + + const bool bSizeChanged = (meImageType != eImageType); + meImageType = eImageType; + const bool bDisplayModeChanged = (mbWasHiContrastMode != Application::GetSettings().GetStyleSettings().GetHighContrastMode()); + Color aColor(rColor); + + // !!! #109290# Workaround for SetFillColor with COL_AUTO + if (aColor == COL_AUTO) + aColor = COL_TRANSPARENT; + + if ((maCurColor == aColor) && !bSizeChanged && !bDisplayModeChanged && !bForceUpdate) + return; + + auto xImage = vcl::CommandInfoProvider::GetXGraphicForCommand(maCommandURL, mxFrame, meImageType); + Image aImage(xImage); + + Size aItemSize = GetItemSize(aImage.GetSizePixel()); + if (!aItemSize.Width() || !aItemSize.Height()) + return; + + ScopedVclPtr<VirtualDevice> pVirDev(CreateVirtualDevice()); + pVirDev->SetOutputSizePixel(aItemSize); + maBmpSize = aItemSize; + + if (maBmpSize.Width() == maBmpSize.Height()) + // tdf#84985 align color bar with icon bottom edge; integer arithmetic e.g. 26 - 26/4 <> 26 * 3/4 + maUpdRect = tools::Rectangle(Point( 0, maBmpSize.Height() - maBmpSize.Height() / 4), Size(maBmpSize.Width(), maBmpSize.Height() / 4)); + else + maUpdRect = tools::Rectangle(Point( maBmpSize.Height() + 2, 2), Point(maBmpSize.Width() - 3, maBmpSize.Height() - 3)); + + pVirDev->Push(PushFlags::CLIPREGION); + + // tdf#135121 don't include the part of the image which we will + // overwrite with the target color so that for the transparent color + // case the original background of the device is shown + vcl::Region aRegion(tools::Rectangle(Point(0, 0), maBmpSize)); + aRegion.Exclude(maUpdRect); + pVirDev->SetClipRegion(aRegion); + + pVirDev->DrawImage(Point(0, 0), aImage); + + pVirDev->Pop(); + + const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings(); + mbWasHiContrastMode = rStyleSettings.GetHighContrastMode(); + + if ((COL_TRANSPARENT != aColor) && (maBmpSize.Width() == maBmpSize.Height())) + pVirDev->SetLineColor(aColor); + else + pVirDev->SetLineColor(rStyleSettings.GetDisableColor()); + + // use not only COL_TRANSPARENT for detection of transparence, + // but the method/way which is designed to do that + const bool bIsTransparent(0xff == aColor.GetTransparency()); + maCurColor = aColor; + + if (bIsTransparent) + { + pVirDev->SetFillColor(); + } + else + { + pVirDev->SetFillColor(maCurColor); + } + + pVirDev->DrawRect(maUpdRect); + + SetImage(pVirDev.get()); + } + + OUString ToolboxButtonColorUpdaterBase::GetCurrentColorName() + { + OUString sColorName = GetQuickHelpText(); + // The obtained string is of format: color context (color name) + // Generate a substring which contains only the color name + sal_Int32 nStart = sColorName.indexOf('('); + sColorName = sColorName.copy( nStart + 1 ); + sal_Int32 nLength = sColorName.getLength(); + if(nLength > 0) + sColorName = sColorName.copy( 0, nLength - 1); + return sColorName; + } + + ToolboxButtonColorUpdater::ToolboxButtonColorUpdater(sal_uInt16 nSlotId, const OString& rTbxBtnId, weld::Toolbar* ptrTbx, bool bWideButton, + const OUString& rCommandLabel, const css::uno::Reference<css::frame::XFrame>& rFrame) + : ToolboxButtonColorUpdaterBase(bWideButton, rCommandLabel, OUString::fromUtf8(rTbxBtnId), rFrame) + , msBtnId(rTbxBtnId) + , mpTbx(ptrTbx) + { + Init(nSlotId); + } + + void ToolboxButtonColorUpdater::SetQuickHelpText(const OUString& rText) + { + mpTbx->set_item_tooltip_text(msBtnId, rText); + } + + OUString ToolboxButtonColorUpdater::GetQuickHelpText() const + { + return mpTbx->get_item_tooltip_text(msBtnId); + } + + void ToolboxButtonColorUpdater::SetImage(VirtualDevice* pVirDev) + { + mpTbx->set_item_image(msBtnId, pVirDev); + } + + VclPtr<VirtualDevice> ToolboxButtonColorUpdater::CreateVirtualDevice() const + { + return mpTbx->create_virtual_device(); + } + + vcl::ImageType ToolboxButtonColorUpdater::GetImageSize() const + { + return mpTbx->get_icon_size(); + } + + Size ToolboxButtonColorUpdater::GetItemSize(const Size& rImageSize) const + { + auto nWidth = rImageSize.Width(); + if (mbWideButton) + nWidth = nWidth * 5; + return Size(nWidth, rImageSize.Height()); + } + + ToolboxButtonLineStyleUpdater::ToolboxButtonLineStyleUpdater() + : m_eXLS(css::drawing::LineStyle_NONE) + , m_nDashStyleIndex(-1) + { + } + + void ToolboxButtonLineStyleUpdater::Update(const com::sun::star::frame::FeatureStateEvent& rEvent) + { + if (rEvent.FeatureURL.Complete == ".uno:LineDash") + { + m_nDashStyleIndex = -1; + + SfxObjectShell* pSh = SfxObjectShell::Current(); + if (!pSh) + return; + const SvxDashListItem* pItem = pSh->GetItem( SID_DASH_LIST ); + if (!pItem) + return; + + XLineDashItem aDashItem; + aDashItem.PutValue(rEvent.State, 0); + const XDash& rDash = aDashItem.GetDashValue(); + + XDashListRef xLineStyleList = pItem->GetDashList(); + for (long i = 0; i < xLineStyleList->Count(); ++i) + { + const XDashEntry* pEntry = xLineStyleList->GetDash(i); + const XDash& rEntry = pEntry->GetDash(); + if (rDash == rEntry) + { + m_nDashStyleIndex = i; + break; + } + } + } + else if (rEvent.FeatureURL.Complete == ".uno:XLineStyle") + { + XLineStyleItem aLineStyleItem; + aLineStyleItem.PutValue(rEvent.State, 0); + + m_eXLS = aLineStyleItem.GetValue(); + } + } + + int ToolboxButtonLineStyleUpdater::GetStyleIndex() const + { + int nRet; + switch (m_eXLS) + { + case css::drawing::LineStyle_NONE: + nRet = 0; + break; + case css::drawing::LineStyle_SOLID: + nRet = 1; + break; + default: + nRet = m_nDashStyleIndex + 2; + break; + } + return nRet; + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/tbxctrls/tbxdrctl.cxx b/svx/source/tbxctrls/tbxdrctl.cxx new file mode 100644 index 000000000..782c6a8f0 --- /dev/null +++ b/svx/source/tbxctrls/tbxdrctl.cxx @@ -0,0 +1,99 @@ +/* -*- 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 <svl/eitem.hxx> +#include <vcl/toolbox.hxx> + +#include <svx/tbxctl.hxx> + +#include <com/sun/star/frame/XLayoutManager.hpp> + +SFX_IMPL_TOOLBOX_CONTROL(SvxTbxCtlDraw, SfxBoolItem); + +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::frame; + + +SvxTbxCtlDraw::SvxTbxCtlDraw( sal_uInt16 nSlotId, sal_uInt16 nId, ToolBox& rTbx ) : + SfxToolBoxControl( nSlotId, nId, rTbx ) +{ + rTbx.SetItemBits( nId, ToolBoxItemBits::CHECKABLE | rTbx.GetItemBits( nId ) ); + rTbx.Invalidate(); +} + +void SAL_CALL SvxTbxCtlDraw::initialize( const css::uno::Sequence< css::uno::Any >& aArguments ) +{ + svt::ToolboxController::initialize(aArguments); + /* + * Toolbar name is defined as "private:resource/toolbar/drawbar" in writer and calc, + * "private:resource/toolbar/toolbar" in draw and impress. Control is added for this + * difference. + */ + if( m_aCommandURL==".uno:TrackChangesBar") + m_sToolboxName="private:resource/toolbar/changes"; + else if ( m_sModuleName == "com.sun.star.presentation.PresentationDocument" || m_sModuleName == "com.sun.star.drawing.DrawingDocument" ) + m_sToolboxName="private:resource/toolbar/toolbar"; + else + m_sToolboxName="private:resource/toolbar/drawbar"; +} + + +void SvxTbxCtlDraw::StateChanged( sal_uInt16 nSID, SfxItemState eState, + const SfxPoolItem* pState ) +{ + GetToolBox().EnableItem( GetId(), ( eState != SfxItemState::DISABLED ) ); + SfxToolBoxControl::StateChanged( nSID, eState, pState ); + + Reference< XLayoutManager > xLayoutMgr = getLayoutManager(); + if ( xLayoutMgr.is() ) + GetToolBox().CheckItem( + GetId(), xLayoutMgr->isElementVisible( m_sToolboxName ) ); +} + + +void SvxTbxCtlDraw::toggleToolbox() +{ + Reference< XLayoutManager > xLayoutMgr = getLayoutManager(); + if ( xLayoutMgr.is() ) + { + bool bCheck = false; + if ( xLayoutMgr->isElementVisible( m_sToolboxName ) ) + { + xLayoutMgr->hideElement( m_sToolboxName ); + xLayoutMgr->destroyElement( m_sToolboxName ); + } + else + { + bCheck = true; + xLayoutMgr->createElement( m_sToolboxName ); + xLayoutMgr->showElement( m_sToolboxName ); + } + + GetToolBox().CheckItem( GetId(), bCheck ); + } +} + + +void SvxTbxCtlDraw::Select(sal_uInt16 /*nSelectModifier*/) +{ + toggleToolbox(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/tbxctrls/verttexttbxctrl.cxx b/svx/source/tbxctrls/verttexttbxctrl.cxx new file mode 100644 index 000000000..18d6b2b8b --- /dev/null +++ b/svx/source/tbxctrls/verttexttbxctrl.cxx @@ -0,0 +1,163 @@ +/* -*- 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 <cppuhelper/supportsservice.hxx> +#include <svx/verttexttbxctrl.hxx> +#include <svl/languageoptions.hxx> +#include <vcl/toolbox.hxx> +#include <vcl/weld.hxx> +#include <rtl/ustring.hxx> + +SvxCTLTextTbxCtrl::SvxCTLTextTbxCtrl(const css::uno::Reference<css::uno::XComponentContext>& rContext) + : SvxVertCTLTextTbxCtrl(rContext) +{ + addStatusListener(".uno:CTLFontState"); +} + +OUString SvxCTLTextTbxCtrl::getImplementationName() +{ + return "com.sun.star.comp.svx.CTLToolBoxControl"; +} + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * +com_sun_star_comp_svx_CTLToolBoxControl_get_implementation( + css::uno::XComponentContext* rContext, + css::uno::Sequence<css::uno::Any> const & ) +{ + return cppu::acquire(new SvxCTLTextTbxCtrl(rContext)); +} + +SvxVertTextTbxCtrl::SvxVertTextTbxCtrl(const css::uno::Reference<css::uno::XComponentContext>& rContext) + : SvxVertCTLTextTbxCtrl(rContext) +{ + addStatusListener(".uno:VerticalTextState"); +} + +OUString SvxVertTextTbxCtrl::getImplementationName() +{ + return "com.sun.star.comp.svx.VertTextToolBoxControl"; +} + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * +com_sun_star_comp_svx_VertTextToolBoxControl_get_implementation( + css::uno::XComponentContext* rContext, + css::uno::Sequence<css::uno::Any> const & ) +{ + return cppu::acquire(new SvxVertTextTbxCtrl(rContext)); +} + +SvxVertCTLTextTbxCtrl::SvxVertCTLTextTbxCtrl(const css::uno::Reference<css::uno::XComponentContext>& rContext) + : SvxVertCTLTextTbxCtrl_Base(rContext, nullptr, OUString()) + , m_bVisible(false) +{ +} + +SvxVertCTLTextTbxCtrl::~SvxVertCTLTextTbxCtrl( ) +{ +} + +void SAL_CALL SvxVertCTLTextTbxCtrl::initialize(const css::uno::Sequence<css::uno::Any>& rArguments) +{ + SvxVertCTLTextTbxCtrl_Base::initialize(rArguments); + // fdo#83320 Hide vertical text commands early + setFastPropertyValue_NoBroadcast(1, css::uno::makeAny(true)); + + if (m_pToolbar) + { + m_bVisible = m_pToolbar->get_item_visible(m_aCommandURL.toUtf8()); + return; + } + + ToolBox* pToolBox = nullptr; + sal_uInt16 nItemId = 0; + getToolboxId(nItemId, &pToolBox); + m_bVisible = pToolBox && pToolBox->IsItemVisible(nItemId); +} + +void SAL_CALL SvxVertCTLTextTbxCtrl::statusChanged(const css::frame::FeatureStateEvent& rEvent) +{ + ToolBox* pToolBox = nullptr; + sal_uInt16 nItemId = 0; + bool bVclToolBox = getToolboxId(nItemId, &pToolBox); + + bool bEnabled = false; + if (rEvent.FeatureURL.Complete == ".uno:VerticalTextState") + { + SvtLanguageOptions aLangOptions; + bEnabled = m_bVisible && aLangOptions.IsVerticalTextEnabled(); + } + else if (rEvent.FeatureURL.Complete == ".uno:CTLFontState") + { + SvtLanguageOptions aLangOptions; + bEnabled = m_bVisible && aLangOptions.IsCTLFontEnabled(); + } + else + { + // normal command + bool bValue = false; + rEvent.State >>= bValue; + + if (m_pToolbar) + { + OString sId = m_aCommandURL.toUtf8(); + m_pToolbar->set_item_active(sId, bValue); + m_pToolbar->set_item_sensitive(sId, rEvent.IsEnabled); + } + + if (bVclToolBox) + { + pToolBox->CheckItem(nItemId, bValue); + pToolBox->EnableItem(nItemId, rEvent.IsEnabled); + } + + return; + } + + if (m_pToolbar) + { + m_pToolbar->set_item_visible(m_aCommandURL.toUtf8(), bEnabled); + return; + } + + if (bVclToolBox) + { + pToolBox->ShowItem(nItemId, bEnabled); + + vcl::Window* pParent = pToolBox->GetParent(); + if (WindowType::FLOATINGWINDOW == pParent->GetType()) + { + Size aSize(pToolBox->CalcWindowSizePixel()); + pToolBox->SetPosSizePixel( Point(), aSize ); + pParent->SetOutputSizePixel( aSize ); + } + } +} + +// XServiceInfo +sal_Bool SAL_CALL SvxVertCTLTextTbxCtrl::supportsService( const OUString& ServiceName ) +{ + return cppu::supportsService(this, ServiceName); +} + +css::uno::Sequence< OUString > SvxVertCTLTextTbxCtrl::getSupportedServiceNames() +{ + return { "com.sun.star.frame.ToolbarController" }; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |