diff options
Diffstat (limited to 'sw/source/ui/chrdlg')
-rw-r--r-- | sw/source/ui/chrdlg/break.cxx | 213 | ||||
-rw-r--r-- | sw/source/ui/chrdlg/chardlg.cxx | 316 | ||||
-rw-r--r-- | sw/source/ui/chrdlg/drpcps.cxx | 760 | ||||
-rw-r--r-- | sw/source/ui/chrdlg/numpara.cxx | 418 | ||||
-rw-r--r-- | sw/source/ui/chrdlg/pardlg.cxx | 245 | ||||
-rw-r--r-- | sw/source/ui/chrdlg/swuiccoll.cxx | 247 | ||||
-rw-r--r-- | sw/source/ui/chrdlg/tblnumfm.cxx | 46 |
7 files changed, 2245 insertions, 0 deletions
diff --git a/sw/source/ui/chrdlg/break.cxx b/sw/source/ui/chrdlg/break.cxx new file mode 100644 index 0000000000..34048c2564 --- /dev/null +++ b/sw/source/ui/chrdlg/break.cxx @@ -0,0 +1,213 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <vcl/svapp.hxx> +#include <osl/diagnose.h> + +#include <uitool.hxx> +#include <swtypes.hxx> +#include <wrtsh.hxx> +#include <view.hxx> +#include <viewopt.hxx> +#include <break.hxx> +#include <pagedesc.hxx> +#include <poolfmt.hxx> + +#include <strings.hrc> +#include <SwStyleNameMapper.hxx> + +void SwBreakDlg::rememberResult() +{ + m_nKind = 0; + if (m_xLineBtn->get_active()) + { + m_nKind = 1; + m_eClear = static_cast<SwLineBreakClear>(m_xLineClearBox->get_active()); + } + else if(m_xColumnBtn->get_active()) + m_nKind = 2; + else if(m_xPageBtn->get_active()) + { + m_nKind = 3; + const int nPos = m_xPageCollBox->get_active(); + if (nPos != 0 && nPos != -1) + { + m_aTemplate = m_xPageCollBox->get_active_text(); + m_oPgNum.reset(); + if (m_xPageNumBox->get_active()) + { + m_oPgNum = o3tl::narrowing<sal_uInt16>(m_xPageNumEdit->get_value()); + } + } + } +} + +IMPL_LINK_NOARG(SwBreakDlg, ToggleHdl, weld::Toggleable&, void) +{ + CheckEnable(); +} + +IMPL_LINK_NOARG(SwBreakDlg, ChangeHdl, weld::ComboBox&, void) +{ + CheckEnable(); +} + +// Handler for Change Page Number +IMPL_LINK(SwBreakDlg, PageNumHdl, weld::Toggleable&, rBox, void) +{ + if (rBox.get_active()) + m_xPageNumEdit->set_value(1); + else + m_xPageNumEdit->set_text(OUString()); +} + +// By changing the Page number the checkbox is checked. +IMPL_LINK_NOARG(SwBreakDlg, PageNumModifyHdl, weld::SpinButton&, void) +{ + m_xPageNumBox->set_active(true); +} + +/* + * Ok-Handler; + * checks whether pagenumber nPage is a legal pagenumber (left pages with even + * numbers etc. for a page template with alternating pages) + */ +IMPL_LINK_NOARG(SwBreakDlg, OkHdl, weld::Button&, void) +{ + if (m_xPageNumBox->get_active()) + { + // In case of differing page descriptions, test validity + const int nPos = m_xPageCollBox->get_active(); + // position 0 says 'Without'. + const SwPageDesc *pPageDesc; + if (nPos != 0 && nPos != -1) + pPageDesc = m_rSh.FindPageDescByName(m_xPageCollBox->get_active_text(), true); + else + pPageDesc = &m_rSh.GetPageDesc(m_rSh.GetCurPageDesc()); + + OSL_ENSURE(pPageDesc, "Page description not found."); + const sal_uInt16 nUserPage = sal_uInt16(m_xPageNumEdit->get_value()); + bool bOk = true; + switch(pPageDesc->GetUseOn()) + { + case UseOnPage::Mirror: + case UseOnPage::All: break; + case UseOnPage::Left: bOk = 0 == nUserPage % 2; break; + case UseOnPage::Right: bOk = 1 == nUserPage % 2; break; + default:; //prevent warning + } + if(!bOk) + { + std::unique_ptr<weld::Dialog> xDialog(Application::CreateMessageDialog(m_xPageNumEdit.get(), VclMessageType::Info, + VclButtonsType::Ok, SwResId(STR_ILLEGAL_PAGENUM))); + xDialog->run(); + m_xPageNumEdit->grab_focus(); + return; + } + } + rememberResult(); + m_xDialog->response(RET_OK); +} + +SwBreakDlg::SwBreakDlg(weld::Window *pParent, SwWrtShell &rS) + : GenericDialogController(pParent, "modules/swriter/ui/insertbreak.ui", "BreakDialog") + , m_xLineBtn(m_xBuilder->weld_radio_button("linerb")) + , m_xLineClearText(m_xBuilder->weld_label("clearft")) + , m_xLineClearBox(m_xBuilder->weld_combo_box("clearlb")) + , m_xColumnBtn(m_xBuilder->weld_radio_button("columnrb")) + , m_xPageBtn(m_xBuilder->weld_radio_button("pagerb")) + , m_xPageCollText(m_xBuilder->weld_label("styleft")) + , m_xPageCollBox(m_xBuilder->weld_combo_box("stylelb")) + , m_xPageNumBox(m_xBuilder->weld_check_button("pagenumcb")) + , m_xPageNumEdit(m_xBuilder->weld_spin_button("pagenumsb")) + , m_xOkBtn(m_xBuilder->weld_button("ok")) + , m_rSh(rS) + , m_nKind(0) + , m_bHtmlMode(0 != ::GetHtmlMode(rS.GetView().GetDocShell())) +{ + Link<weld::Toggleable&,void> aLk = LINK(this, SwBreakDlg, ToggleHdl); + m_xPageBtn->connect_toggled(aLk); + m_xLineBtn->connect_toggled(aLk); + m_xColumnBtn->connect_toggled(aLk); + m_xPageCollBox->connect_changed(LINK(this, SwBreakDlg, ChangeHdl)); + + m_xOkBtn->connect_clicked(LINK(this, SwBreakDlg, OkHdl)); + m_xPageNumBox->connect_toggled(LINK(this, SwBreakDlg, PageNumHdl)); + m_xPageNumEdit->connect_value_changed(LINK(this, SwBreakDlg, PageNumModifyHdl)); + + // Insert page description to Listbox + const size_t nCount = m_rSh.GetPageDescCnt(); + for (size_t i = 0; i < nCount; ++i) + { + const SwPageDesc &rPageDesc = m_rSh.GetPageDesc(i); + ::InsertStringSorted("", rPageDesc.GetName(), *m_xPageCollBox, 1 ); + } + + OUString aFormatName; + for (sal_uInt16 i = RES_POOLPAGE_BEGIN; i < RES_POOLPAGE_END; ++i) + { + aFormatName = SwStyleNameMapper::GetUIName( i, aFormatName ); + if (m_xPageCollBox->find_text(aFormatName) == -1) + ::InsertStringSorted("", aFormatName, *m_xPageCollBox, 1 ); + } + //add landscape page + aFormatName = SwStyleNameMapper::GetUIName( RES_POOLPAGE_LANDSCAPE, aFormatName ); + if (m_xPageCollBox->find_text(aFormatName) == -1) + ::InsertStringSorted("", aFormatName, *m_xPageCollBox, 1); + CheckEnable(); + m_xPageNumEdit->set_text(OUString()); +} + +void SwBreakDlg::CheckEnable() +{ + bool bEnable = true; + if ( m_bHtmlMode ) + { + m_xColumnBtn->set_sensitive(false); + m_xPageCollBox->set_sensitive(false); + bEnable = false; + } + else if(m_rSh.GetFrameType(nullptr,true) + & (FrameTypeFlags::FLY_ANY | FrameTypeFlags::HEADER | FrameTypeFlags::FOOTER | FrameTypeFlags::FOOTNOTE)) + { + m_xPageBtn->set_sensitive(false); + if (m_xPageBtn->get_active()) + m_xLineBtn->set_active(true); + bEnable = false; + } + const bool bPage = m_xPageBtn->get_active(); + m_xPageCollText->set_sensitive(bPage); + m_xPageCollBox->set_sensitive(bPage); + bool bLine = m_xLineBtn->get_active(); + m_xLineClearText->set_sensitive(bLine); + m_xLineClearBox->set_sensitive(bLine); + + bEnable &= bPage; + if ( bEnable ) + { + // position 0 says 'Without' page template. + const int nPos = m_xPageCollBox->get_active(); + if (nPos == 0 || nPos == -1) + bEnable = false; + } + m_xPageNumBox->set_sensitive(bEnable); + m_xPageNumEdit->set_sensitive(bEnable); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/ui/chrdlg/chardlg.cxx b/sw/source/ui/chrdlg/chardlg.cxx new file mode 100644 index 0000000000..ece33852d7 --- /dev/null +++ b/sw/source/ui/chrdlg/chardlg.cxx @@ -0,0 +1,316 @@ +/* -*- 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 <hintids.hxx> + +#include <comphelper/fileurl.hxx> +#include <svl/urihelper.hxx> +#include <svl/stritem.hxx> +#include <editeng/flstitem.hxx> +#include <sfx2/htmlmode.hxx> +#include <svl/cjkoptions.hxx> +#include <svl/macitem.hxx> +#include <osl/diagnose.h> + +#include <cmdid.h> +#include <swtypes.hxx> +#include <view.hxx> +#include <docsh.hxx> +#include <uitool.hxx> +#include <fmtinfmt.hxx> +#include <macassgn.hxx> +#include <chrdlg.hxx> +#include <swmodule.hxx> +#include <poolfmt.hxx> + +#include <strings.hrc> +#include <chrdlgmodes.hxx> +#include <com/sun/star/ui/dialogs/TemplateDescription.hpp> +#include <com/sun/star/ui/dialogs/XFilePicker3.hpp> +#include <SwStyleNameMapper.hxx> +#include <sfx2/filedlghelper.hxx> +#include <sfx2/frame.hxx> +#include <comphelper/lok.hxx> + +#include <svx/svxdlg.hxx> +#include <svx/flagsdef.hxx> +#include <svx/dialogs.hrc> + +using namespace ::com::sun::star::ui::dialogs; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::uno; +using namespace ::sfx2; + +SwCharDlg::SwCharDlg(weld::Window* pParent, SwView& rVw, const SfxItemSet& rCoreSet, + SwCharDlgMode nDialogMode, const OUString* pStr) + : SfxTabDialogController(pParent, "modules/swriter/ui/characterproperties.ui", + "CharacterPropertiesDialog", &rCoreSet, pStr != nullptr) + , m_rView(rVw) + , m_nDialogMode(nDialogMode) +{ + if (pStr) + { + m_xDialog->set_title(m_xDialog->get_title() + SwResId(STR_TEXTCOLL_HEADER) + *pStr + ")"); + } + SfxAbstractDialogFactory* pFact = SfxAbstractDialogFactory::Create(); + AddTabPage("font", pFact->GetTabPageCreatorFunc(RID_SVXPAGE_CHAR_NAME), nullptr); + AddTabPage("fonteffects", pFact->GetTabPageCreatorFunc(RID_SVXPAGE_CHAR_EFFECTS), nullptr); + AddTabPage("position", pFact->GetTabPageCreatorFunc( RID_SVXPAGE_CHAR_POSITION ), nullptr ); + AddTabPage("asianlayout", pFact->GetTabPageCreatorFunc( RID_SVXPAGE_CHAR_TWOLINES ), nullptr ); + AddTabPage("hyperlink", SwCharURLPage::Create, nullptr); + AddTabPage("background", pFact->GetTabPageCreatorFunc( RID_SVXPAGE_BKG ), nullptr ); + AddTabPage("borders", pFact->GetTabPageCreatorFunc( RID_SVXPAGE_BORDER ), nullptr ); + + if (m_nDialogMode == SwCharDlgMode::Draw || m_nDialogMode == SwCharDlgMode::Ann) + { + RemoveTabPage("hyperlink"); + RemoveTabPage("asianlayout"); + } + else + { + if (!SvtCJKOptions::IsDoubleLinesEnabled()) + RemoveTabPage("asianlayout"); + } + + if (m_nDialogMode != SwCharDlgMode::Std) + RemoveTabPage("borders"); +} + +SwCharDlg::~SwCharDlg() +{ +} + +// set FontList +void SwCharDlg::PageCreated(const OUString& rId, SfxTabPage &rPage) +{ + SfxAllItemSet aSet(*(GetInputSetImpl()->GetPool())); + if (rId == "font") + { + SvxFontListItem aFontListItem( *static_cast<const SvxFontListItem*>( + ( m_rView.GetDocShell()->GetItem( SID_ATTR_CHAR_FONTLIST ) ) ) ); + aSet.Put (SvxFontListItem( aFontListItem.GetFontList(), SID_ATTR_CHAR_FONTLIST)); + if(m_nDialogMode != SwCharDlgMode::Draw && m_nDialogMode != SwCharDlgMode::Ann) + aSet.Put (SfxUInt32Item(SID_FLAG_TYPE,SVX_PREVIEW_CHARACTER)); + rPage.PageCreated(aSet); + } + else if (rId == "fonteffects") + { + aSet.Put( + SfxUInt32Item(SID_FLAG_TYPE, SVX_PREVIEW_CHARACTER | SVX_ENABLE_CHAR_TRANSPARENCY)); + rPage.PageCreated(aSet); + } + else if (rId == "position") + { + aSet.Put (SfxUInt32Item(SID_FLAG_TYPE,SVX_PREVIEW_CHARACTER)); + rPage.PageCreated(aSet); + } + else if (rId == "asianlayout") + { + aSet.Put (SfxUInt32Item(SID_FLAG_TYPE,SVX_PREVIEW_CHARACTER)); + rPage.PageCreated(aSet); + } + else if (rId == "background") + { + SvxBackgroundTabFlags eFlags(SvxBackgroundTabFlags::SHOW_HIGHLIGHTING); + if (m_nDialogMode == SwCharDlgMode::Draw || m_nDialogMode == SwCharDlgMode::Ann) + eFlags = SvxBackgroundTabFlags::SHOW_CHAR_BKGCOLOR; + aSet.Put (SfxUInt32Item(SID_FLAG_TYPE,static_cast<sal_uInt32>(eFlags))); + rPage.PageCreated(aSet); + } +} + +SwCharURLPage::SwCharURLPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rCoreSet) + : SfxTabPage(pPage, pController, "modules/swriter/ui/charurlpage.ui", "CharURLPage", &rCoreSet) + , m_bModified(false) + , m_xURLED(m_xBuilder->weld_entry("urled")) + , m_xTextFT(m_xBuilder->weld_label("textft")) + , m_xTextED(m_xBuilder->weld_entry("texted")) + , m_xNameED(m_xBuilder->weld_entry("nameed")) + , m_xTargetFrameLB(m_xBuilder->weld_combo_box("targetfrmlb")) + , m_xURLPB(m_xBuilder->weld_button("urlpb")) + , m_xEventPB(m_xBuilder->weld_button("eventpb")) + , m_xVisitedLB(m_xBuilder->weld_combo_box("visitedlb")) + , m_xNotVisitedLB(m_xBuilder->weld_combo_box("unvisitedlb")) + , m_xCharStyleContainer(m_xBuilder->weld_widget("charstyle")) +{ + // tdf#120188 like SfxManageStyleSheetPage limit the width of the style combos + const int nMaxWidth(m_xVisitedLB->get_approximate_digit_width() * 50); + m_xVisitedLB->set_size_request(nMaxWidth , -1); + m_xNotVisitedLB->set_size_request(nMaxWidth , -1); + + const SfxUInt16Item* pItem = rCoreSet.GetItemIfSet(SID_HTML_MODE, false); + if (!pItem) + { + if (SfxObjectShell* pShell = SfxObjectShell::Current()) + pItem = pShell->GetItem(SID_HTML_MODE); + } + if (pItem) + { + sal_uInt16 nHtmlMode = pItem->GetValue(); + if (HTMLMODE_ON & nHtmlMode) + m_xCharStyleContainer->hide(); + } + + if(comphelper::LibreOfficeKit::isActive()) + m_xURLPB->hide(); // Hide browse button in online (not supported yet) + else + m_xURLPB->connect_clicked(LINK( this, SwCharURLPage, InsertFileHdl)); + m_xEventPB->connect_clicked(LINK( this, SwCharURLPage, EventHdl)); + + if (SwView* pView = GetActiveView()) + { + ::FillCharStyleListBox(*m_xVisitedLB, pView->GetDocShell()); + ::FillCharStyleListBox(*m_xNotVisitedLB, pView->GetDocShell()); + } + m_xVisitedLB->set_active_id(OUString::number(RES_POOLCHR_INET_VISIT)); + m_xVisitedLB->save_value(); + m_xNotVisitedLB->set_active_id(OUString::number(RES_POOLCHR_INET_NORMAL)); + m_xNotVisitedLB->save_value(); + + TargetList aList; + SfxFrame::GetDefaultTargetList(aList); + + m_xTargetFrameLB->freeze(); + size_t nCount = aList.size(); + for (size_t i = 0; i < nCount; ++i) + { + m_xTargetFrameLB->append_text(aList.at(i)); + } + m_xTargetFrameLB->thaw(); +} + +SwCharURLPage::~SwCharURLPage() +{ +} + +void SwCharURLPage::Reset(const SfxItemSet* rSet) +{ + if (const SwFormatINetFormat* pINetFormat = rSet->GetItemIfSet(RES_TXTATR_INETFMT, false)) + { + m_xURLED->set_text(INetURLObject::decode(pINetFormat->GetValue(), + INetURLObject::DecodeMechanism::Unambiguous)); + m_xURLED->save_value(); + m_xNameED->set_text(pINetFormat->GetName()); + m_xNameED->save_value(); + + OUString sEntry = pINetFormat->GetVisitedFormat(); + if (sEntry.isEmpty()) + { + OSL_ENSURE( false, "<SwCharURLPage::Reset(..)> - missing visited character format at hyperlink attribute" ); + SwStyleNameMapper::FillUIName(RES_POOLCHR_INET_VISIT, sEntry); + } + m_xVisitedLB->set_active_text(sEntry); + + sEntry = pINetFormat->GetINetFormat(); + if (sEntry.isEmpty()) + { + OSL_ENSURE( false, "<SwCharURLPage::Reset(..)> - missing unvisited character format at hyperlink attribute" ); + SwStyleNameMapper::FillUIName(RES_POOLCHR_INET_NORMAL, sEntry); + } + m_xNotVisitedLB->set_active_text(sEntry); + + m_xTargetFrameLB->set_entry_text(pINetFormat->GetTargetFrame()); + m_xVisitedLB->save_value(); + m_xNotVisitedLB->save_value(); + m_xTargetFrameLB->save_value(); + m_oINetMacroTable.emplace(); + + if( pINetFormat->GetMacroTable() ) + m_oINetMacroTable = *pINetFormat->GetMacroTable(); + } + if (const SfxStringItem* pItem = rSet->GetItemIfSet(FN_PARAM_SELECTION, false)) + { + m_xTextED->set_text(pItem->GetValue()); + m_xTextFT->set_sensitive(false); + m_xTextED->set_sensitive(false); + } +} + +bool SwCharURLPage::FillItemSet(SfxItemSet* rSet) +{ + OUString sURL = m_xURLED->get_text(); + if (!sURL.isEmpty()) + { + sURL = URIHelper::SmartRel2Abs(INetURLObject(), sURL, Link<OUString *, bool>(), false ); + // #i100683# file URLs should be normalized in the UI + if ( comphelper::isFileUrl(sURL) ) + sURL = URIHelper::simpleNormalizedMakeRelative(OUString(), sURL); + } + + SwFormatINetFormat aINetFormat(sURL, m_xTargetFrameLB->get_active_text()); + aINetFormat.SetName(m_xNameED->get_text()); + bool bURLModified = m_xURLED->get_value_changed_from_saved(); + bool bNameModified = m_xNameED->get_value_changed_from_saved(); + bool bTargetModified = m_xTargetFrameLB->get_value_changed_from_saved(); + m_bModified = bURLModified || bNameModified || bTargetModified; + + // set valid settings first + OUString sEntry = m_xVisitedLB->get_active_text(); + sal_uInt16 nId = SwStyleNameMapper::GetPoolIdFromUIName( sEntry, SwGetPoolIdFromName::ChrFmt); + aINetFormat.SetVisitedFormatAndId( sEntry, nId ); + + sEntry = m_xNotVisitedLB->get_active_text(); + nId = SwStyleNameMapper::GetPoolIdFromUIName( sEntry, SwGetPoolIdFromName::ChrFmt); + aINetFormat.SetINetFormatAndId( sEntry, nId ); + + if (m_oINetMacroTable && !m_oINetMacroTable->empty()) + aINetFormat.SetMacroTable(&*m_oINetMacroTable); + + if (m_xVisitedLB->get_value_changed_from_saved()) + m_bModified = true; + + if (m_xNotVisitedLB->get_value_changed_from_saved()) + m_bModified = true; + + if (bNameModified) + { + m_bModified = true; + rSet->Put(SfxStringItem(FN_PARAM_SELECTION, m_xTextED->get_text())); + } + if(m_bModified) + rSet->Put(aINetFormat); + return m_bModified; +} + +std::unique_ptr<SfxTabPage> SwCharURLPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrSet) +{ + return std::make_unique<SwCharURLPage>(pPage, pController, *rAttrSet); +} + +IMPL_LINK_NOARG(SwCharURLPage, InsertFileHdl, weld::Button&, void) +{ + FileDialogHelper aDlgHelper(TemplateDescription::FILEOPEN_SIMPLE, + FileDialogFlags::NONE, GetFrameWeld()); + aDlgHelper.SetContext(FileDialogHelper::WriterInsertHyperlink); + if( aDlgHelper.Execute() == ERRCODE_NONE ) + { + const Reference<XFilePicker3>& xFP = aDlgHelper.GetFilePicker(); + m_xURLED->set_text(xFP->getSelectedFiles().getConstArray()[0]); + } +} + +IMPL_LINK_NOARG(SwCharURLPage, EventHdl, weld::Button&, void) +{ + if (SwView* pView = GetActiveView()) + m_bModified |= SwMacroAssignDlg::INetFormatDlg(GetFrameWeld(), + pView->GetWrtShell(), m_oINetMacroTable); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/ui/chrdlg/drpcps.cxx b/sw/source/ui/chrdlg/drpcps.cxx new file mode 100644 index 0000000000..15bdd270a0 --- /dev/null +++ b/sw/source/ui/chrdlg/drpcps.cxx @@ -0,0 +1,760 @@ +/* -*- 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 <hintids.hxx> + +#include <cmdid.h> +#include <docsh.hxx> +#include <swmodule.hxx> +#include <view.hxx> +#include <wrtsh.hxx> +#include <strings.hrc> + +#include <vcl/metric.hxx> +#include <vcl/settings.hxx> + +#include <rtl/ustrbuf.hxx> +#include <svl/stritem.hxx> +#include <editeng/fontitem.hxx> +#include <sfx2/dialoghelper.hxx> +#include <sfx2/htmlmode.hxx> +#include <sfx2/objsh.hxx> +#include <sfx2/printer.hxx> +#include <svtools/unitconv.hxx> +#include <vcl/print.hxx> +#include <vcl/svapp.hxx> +#include <com/sun/star/i18n/BreakIterator.hpp> +#include <com/sun/star/i18n/ScriptType.hpp> +#include <comphelper/processfactory.hxx> +#include <osl/diagnose.h> + +#include <charatr.hxx> +#include <viewopt.hxx> +#include <drpcps.hxx> +#include <paratr.hxx> +#include <uitool.hxx> +#include <charfmt.hxx> + +using namespace css; +using namespace css::uno; +using namespace css::lang; + +const WhichRangesContainer SwDropCapsPage::s_aPageRg(svl::Items<RES_PARATR_DROP, RES_PARATR_DROP>); + +void SwDropCapsPict::SetText( const OUString& rT ) +{ + maText = rT; + UpdatePaintSettings(); +} + +void SwDropCapsPict::SetDrawingArea(weld::DrawingArea* pDrawingArea) +{ + CustomWidgetController::SetDrawingArea(pDrawingArea); + Size aPrefSize(getParagraphPreviewOptimalSize(pDrawingArea->get_ref_device())); + pDrawingArea->set_size_request(aPrefSize.Width(), aPrefSize.Height()); +} + +void SwDropCapsPict::Resize() +{ + CustomWidgetController::Resize(); + UpdatePaintSettings(); +} + +void SwDropCapsPict::SetLines( sal_uInt8 nL ) +{ + mnLines = nL; + UpdatePaintSettings(); +} + +void SwDropCapsPict::SetDistance( sal_uInt16 nD ) +{ + mnDistance = nD; + UpdatePaintSettings(); +} + +void SwDropCapsPict::SetValues( const OUString& rText, sal_uInt8 nLines, sal_uInt16 nDistance ) +{ + maText = rText; + mnLines = nLines; + mnDistance = nDistance; + + UpdatePaintSettings(); +} + +void SwDropCapsPict::InitPrinter() +{ + if( !mpPrinter ) + InitPrinter_(); +} + +// Create Default-String from character-count (A, AB, ABC, ...) +static OUString GetDefaultString(sal_Int32 nChars) +{ + OUStringBuffer aStr(nChars); + for (sal_Int32 i = 0; i < nChars; i++) + aStr.append(static_cast<sal_Unicode>(i + 65)); + return aStr.makeStringAndClear(); +} + +static void calcFontHeightAnyAscent(vcl::RenderContext& rWin, vcl::Font const & _rFont, tools::Long& _nHeight, tools::Long& _nAscent) +{ + if ( !_nHeight ) + { + rWin.Push(vcl::PushFlags::FONT); + rWin.SetFont(_rFont); + FontMetric aMetric(rWin.GetFontMetric()); + _nHeight = aMetric.GetLineHeight(); + _nAscent = aMetric.GetAscent(); + rWin.Pop(); + } +} + +SwDropCapsPict::~SwDropCapsPict() +{ + if (mbDelPrinter) + mpPrinter.disposeAndClear(); +} + +/// Get the details of the first script change. +/// @param[out] start The character position of the start of the segment. +/// @param[out] end The character position of the end of the segment. +/// @param[out] scriptType The script type (Latin, Asian, Complex etc.) +void SwDropCapsPict::GetFirstScriptSegment(sal_Int32 &start, sal_Int32 &end, sal_uInt16 &scriptType) +{ + start = 0; + if( maScriptChanges.empty() ) + { + end = maText.getLength(); + scriptType = css::i18n::ScriptType::LATIN; + } + else + { + end = maScriptChanges[ 0 ].changePos; + scriptType = maScriptChanges[ 0 ].scriptType; + } +} + +/// Get the details of the first script change. +/// @param[in,out] nIdx Index of the current script change. +/// @param[out] start The character position of the start of the segment. +/// @param[in,out] end The character position of the end of the segment. +/// @param[out] scriptType The script type (Latin, Asian, Complex etc.) +/// @returns True if there was a next segment, false if not. +bool SwDropCapsPict::GetNextScriptSegment(size_t &nIdx, sal_Int32 &start, sal_Int32 &end, sal_uInt16 &scriptType) +{ + if (maScriptChanges.empty() || nIdx >= maScriptChanges.size() - 1 || end >= maText.getLength()) + return false; + start = maScriptChanges[nIdx++].changePos; + end = maScriptChanges[ nIdx ].changePos; + scriptType = maScriptChanges[ nIdx ].scriptType; + return true; +} + +#define LINES 10 +#define BORDER 2 + +void SwDropCapsPict::GetFontSettings( vcl::Font& _rFont, sal_uInt16 _nWhich ) +{ + SwView* pView = GetActiveView(); + if (!pView) + return; + SwWrtShell& rWrtShell = pView->GetWrtShell(); + + SfxItemSet aSet( rWrtShell.GetAttrPool(), _nWhich, _nWhich); + rWrtShell.GetCurAttr(aSet); + SvxFontItem aFormatFont(static_cast<const SvxFontItem &>( aSet.Get(_nWhich))); + + _rFont.SetFamily(aFormatFont.GetFamily()); + _rFont.SetFamilyName(aFormatFont.GetFamilyName()); + _rFont.SetPitch(aFormatFont.GetPitch()); + _rFont.SetCharSet(aFormatFont.GetCharSet()); +} + +void SwDropCapsPict::UpdatePaintSettings() +{ + SwView* pView = GetActiveView(); + if (!pView) + return; + SwWrtShell& rWrtShell = pView->GetWrtShell(); + + maBackColor = Application::GetSettings().GetStyleSettings().GetWindowColor(); + maTextLineColor = COL_LIGHTGRAY; + + // gray lines + mnTotLineH = (GetOutputSizePixel().Height() - 2 * BORDER) / LINES; + mnLineH = mnTotLineH - 2; + + vcl::Font aFont; + if (mpPage) + { + // tdf#135244: preview generation should not jump document view + auto aLock(rWrtShell.GetView().GetDocShell()->LockAllViews()); + + if (!mpPage->m_xTemplateBox->get_active()) + { + // query the Font at paragraph's beginning + rWrtShell.Push(); + rWrtShell.SttCursorMove(); + rWrtShell.ClearMark(); + SwWhichPara pSwuifnParaCurr = GoCurrPara; + SwMoveFnCollection const & pSwuifnParaStart = fnParaStart; + rWrtShell.MovePara(pSwuifnParaCurr,pSwuifnParaStart); + // normal + GetFontSettings( aFont, RES_CHRATR_FONT ); + + // CJK + GetFontSettings( maCJKFont, RES_CHRATR_CJK_FONT ); + + // CTL + GetFontSettings( maCTLFont, RES_CHRATR_CTL_FONT ); + + rWrtShell.EndCursorMove(); + rWrtShell.Pop(SwCursorShell::PopMode::DeleteCurrent); + } + else + { + // query Font at character template + SwCharFormat *pFormat = rWrtShell.GetCharStyle( + mpPage->m_xTemplateBox->get_active_text(), + SwWrtShell::GETSTYLE_CREATEANY ); + OSL_ENSURE(pFormat, "character style doesn't exist!"); + const SvxFontItem &rFormatFont = pFormat->GetFont(); + + aFont.SetFamily(rFormatFont.GetFamily()); + aFont.SetFamilyName(rFormatFont.GetFamilyName()); + aFont.SetPitch(rFormatFont.GetPitch()); + aFont.SetCharSet(rFormatFont.GetCharSet()); + } + + const Color& rFontColor = rWrtShell.GetViewOptions()->GetFontColor(); + aFont.SetColor( rFontColor ); + maCJKFont.SetColor( rFontColor ); + maCTLFont.SetColor( rFontColor ); + } + + mnTextH = mnLines * mnTotLineH; + aFont.SetFontSize(Size(0, mnTextH)); + maCJKFont.SetFontSize(Size(0, mnTextH)); + maCTLFont.SetFontSize(Size(0, mnTextH)); + + aFont.SetTransparent(true); + maCJKFont.SetTransparent(true); + maCTLFont.SetTransparent(true); + + aFont.SetFillColor(Application::GetSettings().GetStyleSettings().GetWindowColor()); + maCJKFont.SetFillColor(Application::GetSettings().GetStyleSettings().GetWindowColor()); + maCTLFont.SetFillColor(Application::GetSettings().GetStyleSettings().GetWindowColor()); + + maCJKFont.SetFontSize(Size(0, maCJKFont.GetFontSize().Height())); + maCTLFont.SetFontSize(Size(0, maCTLFont.GetFontSize().Height())); + + aFont.SetFontSize(Size(0, aFont.GetFontSize().Height())); + maFont = aFont; + + CheckScript(); + + maTextSize = CalcTextSize(); + + Invalidate(); +} + +void SwDropCapsPict::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& /*rRect*/) +{ + if (!IsVisible()) + return; + + rRenderContext.SetMapMode(MapMode(MapUnit::MapPixel)); + rRenderContext.SetLineColor(); + + rRenderContext.SetFillColor(maBackColor); + + Size aOutputSizePixel(GetOutputSizePixel()); + + rRenderContext.DrawRect(tools::Rectangle(Point(0, 0), aOutputSizePixel)); + rRenderContext.SetClipRegion(vcl::Region(tools::Rectangle(Point(BORDER, BORDER), + Size(aOutputSizePixel.Width () - 2 * BORDER, + aOutputSizePixel.Height() - 2 * BORDER)))); + + OSL_ENSURE(mnLineH > 0, "We cannot make it that small"); + tools::Long nY0 = (aOutputSizePixel.Height() - (LINES * mnTotLineH)) / 2; + + rRenderContext.SetFillColor(maTextLineColor); + + for (int i = 0; i < LINES; ++i) + { + rRenderContext.DrawRect(tools::Rectangle(Point(BORDER, nY0 + i * mnTotLineH), + Size(aOutputSizePixel.Width() - 2 * BORDER, mnLineH))); + } + + // Text background with gap (240 twips ~ 1 line height) + const tools::Long nDistW = (((static_cast<tools::Long>(mnDistance) * 100) / 240) * mnTotLineH) / 100; + rRenderContext.SetFillColor(maBackColor); + if (mpPage && mpPage->m_xDropCapsBox->get_active()) + { + const Size aTextSize(maTextSize.Width() + nDistW, maTextSize.Height()); + rRenderContext.DrawRect(tools::Rectangle(Point(BORDER, nY0), aTextSize)); + + // draw Text + DrawPrev(rRenderContext, Point(BORDER, nY0)); + } + rRenderContext.SetClipRegion(); +} + +void SwDropCapsPict::DrawPrev(vcl::RenderContext& rRenderContext, const Point& rPt) +{ + Point aPt(rPt); + InitPrinter(); + + vcl::Font aOldFont = mpPrinter->GetFont(); + sal_uInt16 nScript; + size_t nIdx = 0; + sal_Int32 nStart; + sal_Int32 nEnd; + + GetFirstScriptSegment(nStart, nEnd, nScript); + + do + { + SvxFont& rFnt = (nScript == css::i18n::ScriptType::ASIAN) + ? maCJKFont + : ((nScript == css::i18n::ScriptType::COMPLEX) + ? maCTLFont + : maFont); + mpPrinter->SetFont(rFnt); + + rFnt.DrawPrev(&rRenderContext, mpPrinter, aPt, maText, nStart, nEnd - nStart); + + if (!maScriptChanges.empty()) + aPt.AdjustX(maScriptChanges[nIdx].textWidth ); + + if (!GetNextScriptSegment(nIdx, nStart, nEnd, nScript)) + break; + } + while(true); + + mpPrinter->SetFont(aOldFont); +} + +void SwDropCapsPict::CheckScript() +{ + if( maScriptText == maText ) + return; + + maScriptText = maText; + maScriptChanges.clear(); + if( !m_xBreak.is() ) + { + Reference< XComponentContext > xContext = ::comphelper::getProcessComponentContext(); + m_xBreak = css::i18n::BreakIterator::create(xContext); + } + sal_Int16 nScript = m_xBreak->getScriptType( maText, 0 ); + sal_Int32 nChg = 0; + if( css::i18n::ScriptType::WEAK == nScript ) + { + nChg = m_xBreak->endOfScript( maText, nChg, nScript ); + if( nChg < maText.getLength() ) + nScript = m_xBreak->getScriptType( maText, nChg ); + else + nScript = css::i18n::ScriptType::LATIN; + } + + for(;;) + { + nChg = m_xBreak->endOfScript( maText, nChg, nScript ); + maScriptChanges.emplace_back(nScript, nChg ); + if( nChg >= maText.getLength() || nChg < 0 ) + break; + nScript = m_xBreak->getScriptType( maText, nChg ); + } +} + +Size SwDropCapsPict::CalcTextSize() +{ + InitPrinter(); + + sal_uInt16 nScript; + size_t nIdx = 0; + sal_Int32 nStart; + sal_Int32 nEnd; + GetFirstScriptSegment(nStart, nEnd, nScript); + tools::Long nTextWidth = 0; + tools::Long nCJKHeight = 0; + tools::Long nCTLHeight = 0; + tools::Long nHeight = 0; + tools::Long nAscent = 0; + tools::Long nCJKAscent = 0; + tools::Long nCTLAscent = 0; + do + { + SvxFont& rFnt = (nScript == css::i18n::ScriptType::ASIAN) + ? maCJKFont + : ((nScript == css::i18n::ScriptType::COMPLEX) + ? maCTLFont + : maFont); + + sal_uLong nWidth = rFnt.GetTextSize(*mpPrinter, maText, nStart, nEnd-nStart ).Width(); + + if (nIdx < maScriptChanges.size()) + maScriptChanges[nIdx].textWidth = nWidth; + nTextWidth += nWidth; + switch(nScript) + { + case css::i18n::ScriptType::ASIAN: + calcFontHeightAnyAscent(GetDrawingArea()->get_ref_device(), maCJKFont, nCJKHeight, nCJKAscent); + break; + case css::i18n::ScriptType::COMPLEX: + calcFontHeightAnyAscent(GetDrawingArea()->get_ref_device(), maCTLFont, nCTLHeight, nCTLAscent); + break; + default: + calcFontHeightAnyAscent(GetDrawingArea()->get_ref_device(), maFont, nHeight, nAscent); + } + + if (!GetNextScriptSegment(nIdx, nStart, nEnd, nScript)) + break; + } + while(true); + + nHeight -= nAscent; + nCJKHeight -= nCJKAscent; + nCTLHeight -= nCTLAscent; + if (nHeight < nCJKHeight) + nHeight = nCJKHeight; + if (nAscent < nCJKAscent) + nAscent = nCJKAscent; + if (nHeight < nCTLHeight) + nHeight = nCTLHeight; + if (nAscent < nCTLAscent) + nAscent = nCTLAscent; + nHeight += nAscent; + + Size aTextSize(nTextWidth, nHeight); + return aTextSize; +} + +void SwDropCapsPict::InitPrinter_() +{ + SfxViewShell* pSh = SfxViewShell::Current(); + + if (pSh) + mpPrinter = pSh->GetPrinter(); + + if (!mpPrinter) + { + mpPrinter = VclPtr<Printer>::Create(); + mbDelPrinter = true; + } +} + +SwDropCapsDlg::SwDropCapsDlg(weld::Window *pParent, const SfxItemSet &rSet) + : SfxSingleTabDialogController(pParent, &rSet) +{ + auto xNewPage(SwDropCapsPage::Create(get_content_area(), this, &rSet)); + static_cast<SwDropCapsPage*>(xNewPage.get())->SetFormat(false); + SetTabPage(std::move(xNewPage)); +} + +SwDropCapsPage::SwDropCapsPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet &rSet) + : SfxTabPage(pPage, pController, "modules/swriter/ui/dropcapspage.ui", "DropCapPage", &rSet) + , m_bModified(false) + , m_bFormat(true) + , m_xDropCapsBox(m_xBuilder->weld_check_button("checkCB_SWITCH")) + , m_xWholeWordCB(m_xBuilder->weld_check_button("checkCB_WORD")) + , m_xSwitchText(m_xBuilder->weld_label("labelFT_DROPCAPS")) + , m_xDropCapsField(m_xBuilder->weld_spin_button("spinFLD_DROPCAPS")) + , m_xLinesText(m_xBuilder->weld_label("labelTXT_LINES")) + , m_xLinesField(m_xBuilder->weld_spin_button("spinFLD_LINES")) + , m_xDistanceText(m_xBuilder->weld_label("labelTXT_DISTANCE")) + , m_xDistanceField(m_xBuilder->weld_metric_spin_button("spinFLD_DISTANCE", FieldUnit::CM)) + , m_xTextText(m_xBuilder->weld_label("labelTXT_TEXT")) + , m_xTextEdit(m_xBuilder->weld_entry("entryEDT_TEXT")) + , m_xTemplateText(m_xBuilder->weld_label("labelTXT_TEMPLATE")) + , m_xTemplateBox(m_xBuilder->weld_combo_box("comboBOX_TEMPLATE")) + , m_xPict(new weld::CustomWeld(*m_xBuilder, "drawingareaWN_EXAMPLE", m_aPict)) +{ + m_aPict.SetDropCapsPage(this); + + SetExchangeSupport(); + + const sal_uInt16 nHtmlMode = ::GetHtmlMode(static_cast<const SwDocShell*>(SfxObjectShell::Current())); + m_bHtmlMode = (nHtmlMode & HTMLMODE_ON) != 0; + + // tdf#92154 limit comboBOX_TEMPLATE length + const int nMaxWidth(m_xTemplateBox->get_approximate_digit_width() * 50); + m_xTemplateBox->set_size_request(nMaxWidth , -1); + + // In the template dialog the text is not influenceable + m_xTextText->set_sensitive(!m_bFormat); + m_xTextEdit->set_sensitive(!m_bFormat); + + // Metrics + SetFieldUnit(*m_xDistanceField, GetDfltMetric(m_bHtmlMode)); + + // Install handler + Link<weld::SpinButton&,void> aValueChangedLk = LINK(this, SwDropCapsPage, ValueChangedHdl); + m_xDropCapsField->connect_value_changed(aValueChangedLk); + m_xLinesField->connect_value_changed(aValueChangedLk); + Link<weld::MetricSpinButton&,void> aMetricValueChangedLk = LINK(this, SwDropCapsPage, MetricValueChangedHdl); + m_xDistanceField->connect_value_changed(aMetricValueChangedLk); + m_xTextEdit->connect_changed(LINK(this, SwDropCapsPage, ModifyHdl)); + m_xDropCapsBox->connect_toggled(LINK(this, SwDropCapsPage, ClickHdl)); + m_xTemplateBox->connect_changed(LINK(this, SwDropCapsPage, SelectHdl)); + m_xWholeWordCB->connect_toggled(LINK(this, SwDropCapsPage, WholeWordHdl)); +} + +SwDropCapsPage::~SwDropCapsPage() +{ +} + +DeactivateRC SwDropCapsPage::DeactivatePage(SfxItemSet * _pSet) +{ + if (_pSet) + FillSet(*_pSet); + + return DeactivateRC::LeavePage; +} + +std::unique_ptr<SfxTabPage> SwDropCapsPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet *rSet) +{ + return std::make_unique<SwDropCapsPage>(pPage, pController, *rSet); +} + +bool SwDropCapsPage::FillItemSet(SfxItemSet *rSet) +{ + if (m_bModified) + FillSet(*rSet); + return m_bModified; +} + +void SwDropCapsPage::Reset(const SfxItemSet *rSet) +{ + // Characters, lines, gap and text + SwFormatDrop aFormatDrop( rSet->Get(RES_PARATR_DROP) ); + if (aFormatDrop.GetLines() > 1) + { + m_xDropCapsField->set_value(aFormatDrop.GetChars()); + m_xLinesField->set_value(aFormatDrop.GetLines()); + m_xDistanceField->set_value(m_xDistanceField->normalize(aFormatDrop.GetDistance()), FieldUnit::TWIP); + m_xWholeWordCB->set_active(aFormatDrop.GetWholeWord()); + } + else + { + m_xDropCapsField->set_value(1); + m_xLinesField->set_value(3); + m_xDistanceField->set_value(0, FieldUnit::TWIP); + } + + SwView* pView = GetActiveView(); + if (pView) + ::FillCharStyleListBox(*m_xTemplateBox, pView->GetWrtShell().GetView().GetDocShell(), true); + + m_xTemplateBox->insert_text(0, SwResId(SW_STR_NONE)); + + // Reset format + int nSelect = 0; + if (aFormatDrop.GetCharFormat()) + { + int nPos = m_xTemplateBox->find_text(aFormatDrop.GetCharFormat()->GetName()); + if (nPos != -1) + nSelect = nPos; + } + m_xTemplateBox->set_active(nSelect); + + // Enable controls + m_xDropCapsBox->set_active(aFormatDrop.GetLines() > 1); + const sal_Int32 nVal = m_xDropCapsField->get_value(); + if (m_bFormat) + m_xTextEdit->set_text(GetDefaultString(nVal)); + else + { + if (pView) + m_xTextEdit->set_text(pView->GetWrtShell().GetDropText(nVal)); + m_xTextEdit->set_sensitive(true); + m_xTextText->set_sensitive(true); + } + + // Preview + m_aPict.SetValues(m_xTextEdit->get_text(), + sal_uInt8(m_xLinesField->get_value()), + sal_uInt16(m_xDistanceField->denormalize(m_xDistanceField->get_value(FieldUnit::TWIP)))); + + ClickHdl(*m_xDropCapsBox); + m_bModified = false; +} + +IMPL_LINK_NOARG(SwDropCapsPage, ClickHdl, weld::Toggleable&, void) +{ + bool bChecked = m_xDropCapsBox->get_active(); + + m_xWholeWordCB->set_sensitive(bChecked && !m_bHtmlMode); + + m_xSwitchText->set_sensitive(bChecked && !m_xWholeWordCB->get_active()); + m_xDropCapsField->set_sensitive(bChecked && !m_xWholeWordCB->get_active()); + m_xLinesText->set_sensitive( bChecked ); + m_xLinesField->set_sensitive( bChecked ); + m_xDistanceText->set_sensitive( bChecked ); + m_xDistanceField->set_sensitive( bChecked ); + m_xTemplateText->set_sensitive( bChecked ); + m_xTemplateBox->set_sensitive( bChecked ); + m_xTextEdit->set_sensitive( bChecked && !m_bFormat ); + m_xTextText->set_sensitive( bChecked && !m_bFormat ); + + if ( bChecked ) + { + ValueChangedHdl(*m_xDropCapsField); + m_xDropCapsField->grab_focus(); + } + else + m_aPict.SetText(""); + + m_bModified = true; +} + +IMPL_LINK_NOARG(SwDropCapsPage, WholeWordHdl, weld::Toggleable&, void) +{ + m_xDropCapsField->set_sensitive(!m_xWholeWordCB->get_active()); + m_xSwitchText->set_sensitive(!m_xWholeWordCB->get_active()); + + ValueChangedHdl(*m_xDropCapsField); + + m_bModified = true; +} + +void SwDropCapsPage::ModifyEntry(const weld::Entry& rEdit) +{ + OUString sPreview; + + // set text if applicable + if (&rEdit == m_xDropCapsField.get()) + { + const sal_Int32 nVal = !m_xWholeWordCB->get_active() + ? static_cast<sal_Int32>(m_xDropCapsField->get_value()) + : 0; + bool bSetText = false; + + if (SwView* pView = GetActiveView()) + { + if (m_bFormat || pView->GetWrtShell().GetDropText(1).isEmpty()) + sPreview = GetDefaultString(nVal); + else + { + bSetText = true; + sPreview = pView->GetWrtShell().GetDropText(nVal); + } + } + + OUString sEdit(m_xTextEdit->get_text()); + + if (!sEdit.isEmpty() && !sPreview.startsWith(sEdit)) + { + sPreview = sEdit.copy(0, std::min(sEdit.getLength(), sPreview.getLength())); + bSetText = false; + } + + if (bSetText) + m_xTextEdit->set_text(sPreview); + } + else if (&rEdit == m_xTextEdit.get()) // set quantity if applicable + { + const sal_Int32 nTmp = m_xTextEdit->get_text().getLength(); + m_xDropCapsField->set_value(std::max<sal_Int32>(1, nTmp)); + sPreview = m_xTextEdit->get_text(); + } + + // adjust image + if (&rEdit == m_xDropCapsField.get() || &rEdit == m_xTextEdit.get()) + m_aPict.SetText(sPreview); + else if (&rEdit == m_xLinesField.get()) + m_aPict.SetLines(static_cast<sal_uInt8>(m_xLinesField->get_value())); + else + m_aPict.SetDistance(o3tl::narrowing<sal_uInt16>(m_xDistanceField->denormalize(m_xDistanceField->get_value(FieldUnit::TWIP)))); + + m_bModified = true; +} + +IMPL_LINK(SwDropCapsPage, ModifyHdl, weld::Entry&, rEdit, void) +{ + ModifyEntry(rEdit); +} + +IMPL_LINK(SwDropCapsPage, ValueChangedHdl, weld::SpinButton&, rEdit, void) +{ + ModifyEntry(rEdit); +} + +IMPL_LINK(SwDropCapsPage, MetricValueChangedHdl, weld::MetricSpinButton&, rEdit, void) +{ + ModifyEntry(rEdit.get_widget()); +} + +IMPL_LINK_NOARG(SwDropCapsPage, SelectHdl, weld::ComboBox&, void) +{ + m_aPict.UpdatePaintSettings(); + m_bModified = true; +} + +void SwDropCapsPage::FillSet( SfxItemSet &rSet ) +{ + if(!m_bModified) + return; + + SwFormatDrop aFormat; + + bool bOn = m_xDropCapsBox->get_active(); + if (bOn) + { + // quantity, lines, gap + aFormat.GetChars() = static_cast<sal_uInt8>(m_xDropCapsField->get_value()); + aFormat.GetLines() = static_cast<sal_uInt8>(m_xLinesField->get_value()); + aFormat.GetDistance() = o3tl::narrowing<sal_uInt16>(m_xDistanceField->denormalize(m_xDistanceField->get_value(FieldUnit::TWIP))); + aFormat.GetWholeWord() = m_xWholeWordCB->get_active(); + + // template + if (SwView* pView = GetActiveView()) + if (m_xTemplateBox->get_active()) + aFormat.SetCharFormat(pView->GetWrtShell().GetCharStyle(m_xTemplateBox->get_active_text())); + } + else + { + aFormat.GetChars() = 1; + aFormat.GetLines() = 1; + aFormat.GetDistance() = 0; + } + + // set attributes + const SfxPoolItem* pOldItem; + if (nullptr == (pOldItem = GetOldItem(rSet, FN_FORMAT_DROPCAPS)) || aFormat != *pOldItem) + rSet.Put(aFormat); + + // hard text formatting + // Bug 24974: in designer/template catalog this doesn't make sense!! + if (!m_bFormat && m_xDropCapsBox->get_active()) + { + OUString sText(m_xTextEdit->get_text()); + + if (!m_xWholeWordCB->get_active()) + { + sText = sText.copy(0, std::min<sal_Int32>(sText.getLength(), m_xDropCapsField->get_value())); + } + + SfxStringItem aStr(FN_PARAM_1, sText); + rSet.Put(aStr); + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/ui/chrdlg/numpara.cxx b/sw/source/ui/chrdlg/numpara.cxx new file mode 100644 index 0000000000..65875eb79c --- /dev/null +++ b/sw/source/ui/chrdlg/numpara.cxx @@ -0,0 +1,418 @@ +/* -*- 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 <cmdid.h> +#include <swtypes.hxx> +#include <hintids.hxx> +#include <strings.hrc> +#include <sfx2/objsh.hxx> +#include <sfx2/htmlmode.hxx> +#include <svl/eitem.hxx> +#include <svl/stritem.hxx> +#include <svl/intitem.hxx> +#include <fmtline.hxx> +#include <numpara.hxx> + +#include <officecfg/Office/Common.hxx> +#include <sfx2/dispatch.hxx> +#include <sfx2/frame.hxx> +#include <sfx2/viewsh.hxx> + +// tdf#115871 - reset outline and list options to parent settings +const WhichRangesContainer SwParagraphNumTabPage::s_aPageRg( + svl::Items<RES_LINENUMBER, RES_LINENUMBER, SID_ATTR_PARA_NUMRULE, SID_ATTR_PARA_NUMRULE, + SID_ATTR_PARA_OUTLINE_LEVEL, SID_ATTR_PARA_OUTLINE_LEVEL, FN_NUMBER_NEWSTART, + FN_NUMBER_NEWSTART_AT>); + +SwParagraphNumTabPage::SwParagraphNumTabPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rAttr) + : SfxTabPage(pPage, pController, "modules/swriter/ui/numparapage.ui", "NumParaPage", &rAttr) + , msOutlineNumbering(SwResId(STR_OUTLINE_NUMBERING )) + , m_bModified(false) + , m_bCurNumrule(false) + , m_xOutlineStartBX(m_xBuilder->weld_widget("boxOUTLINE")) + , m_xOutlineLvLB(m_xBuilder->weld_combo_box("comboLB_OUTLINE_LEVEL")) + , m_xNumberStyleBX(m_xBuilder->weld_widget("boxNUMBER_STYLE")) + , m_xNumberStyleLB(m_xBuilder->weld_combo_box("comboLB_NUMBER_STYLE")) + , m_xEditNumStyleBtn(m_xBuilder->weld_button("editnumstyle")) + , m_xListLvBX(m_xBuilder->weld_widget("boxLIST_LEVEL")) + , m_xListLvLB(m_xBuilder->weld_combo_box("comboLB_LIST_LEVEL")) + , m_xNewStartCB(m_xBuilder->weld_check_button("checkCB_NEW_START")) + , m_xNewStartBX(m_xBuilder->weld_widget("boxNEW_START")) + , m_xNewStartNumberCB(m_xBuilder->weld_check_button("checkCB_NUMBER_NEW_START")) + , m_xNewStartNF(m_xBuilder->weld_spin_button("spinNF_NEW_START")) + , m_xCountParaFram(m_xBuilder->weld_widget("frameFL_COUNT_PARA")) + , m_xCountParaCB(m_xBuilder->weld_check_button("checkCB_COUNT_PARA")) + , m_xRestartParaCountCB(m_xBuilder->weld_check_button("checkCB_RESTART_PARACOUNT")) + , m_xRestartBX(m_xBuilder->weld_widget("boxRESTART_NO")) + , m_xRestartNF(m_xBuilder->weld_spin_button("spinNF_RESTART_PARA")) +{ + m_xNewStartCB->set_state(TRISTATE_FALSE); + m_xNewStartNumberCB->set_state(TRISTATE_FALSE); + m_xCountParaCB->set_state(TRISTATE_FALSE); + m_xRestartParaCountCB->set_state(TRISTATE_FALSE); + m_xEditNumStyleBtn->set_sensitive(false); + + const SfxUInt16Item* pItem = rAttr.GetItemIfSet(SID_HTML_MODE, false); + if (!pItem) + { + if (SfxObjectShell* pObjSh = SfxObjectShell::Current()) + pItem = pObjSh->GetItem(SID_HTML_MODE); + } + if(pItem) + { + const sal_uInt16 nHtmlMode = pItem->GetValue(); + + if (HTMLMODE_ON & nHtmlMode) + m_xCountParaFram->hide(); + } + + m_xNewStartCB->connect_toggled(LINK(this, SwParagraphNumTabPage, NewStartHdl_Impl)); + m_xNewStartNumberCB->connect_toggled(LINK(this, SwParagraphNumTabPage, NewStartHdl_Impl)); + m_xNumberStyleLB->connect_changed(LINK(this, SwParagraphNumTabPage, StyleHdl_Impl)); + m_xCountParaCB->connect_toggled(LINK(this, SwParagraphNumTabPage, LineCountHdl_Impl)); + m_xRestartParaCountCB->connect_toggled(LINK(this, SwParagraphNumTabPage, LineCountHdl_Impl)); + m_xNumberStyleLB->connect_changed(LINK(this, SwParagraphNumTabPage, EditNumStyleSelectHdl_Impl)); + m_xEditNumStyleBtn->connect_clicked(LINK(this, SwParagraphNumTabPage, EditNumStyleHdl_Impl)); + + if (officecfg::Office::Common::Misc::ExperimentalMode::get()) + m_xListLvBX->show(); + else + m_xListLvBX->hide(); +} + +SwParagraphNumTabPage::~SwParagraphNumTabPage() +{ +} + +std::unique_ptr<SfxTabPage> SwParagraphNumTabPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rSet) +{ + return std::make_unique<SwParagraphNumTabPage>(pPage, pController, *rSet); +} + +bool SwParagraphNumTabPage::FillItemSet( SfxItemSet* rSet ) +{ + if (m_xOutlineLvLB->get_value_changed_from_saved()) + { + const sal_uInt16 aOutlineLv = m_xOutlineLvLB->get_active(); + const SfxUInt16Item* pOldOutlineLv = GetOldItem( *rSet, SID_ATTR_PARA_OUTLINE_LEVEL); + if (pOldOutlineLv) + { + std::unique_ptr<SfxUInt16Item> pOutlineLv(pOldOutlineLv->Clone()); + pOutlineLv->SetValue( aOutlineLv ); + rSet->Put(std::move(pOutlineLv)); + m_bModified = true; + + // Does List Level need to be set to be the same as Outline Level? + if (!m_xListLvLB->get_active() && m_xListLvBX->get_visible() + && !m_xListLvLB->get_value_changed_from_saved()) + { + sal_Int16 nListLevel = std::max<sal_Int16>(1, aOutlineLv); + --nListLevel; // Outline Level is 1 based. List Level is zero based. + rSet->Put(SfxInt16Item(RES_PARATR_LIST_LEVEL, nListLevel)); + } + } + } + + if (m_xListLvLB->get_value_changed_from_saved()) + { + if (m_xListLvBX->get_visible()) + { + sal_Int16 nListLevel = m_xListLvLB->get_active(); + // Does List Level need to be set to be the same as Outline Level? + if (!nListLevel) + { + nListLevel = std::max<sal_Int16>(1, m_xOutlineLvLB->get_active()); + } + --nListLevel; // List Level is zero based, but both listboxes are 1-based. + + rSet->Put(SfxInt16Item(RES_PARATR_LIST_LEVEL, nListLevel)); + m_bModified = true; + } + } + + if (m_xNumberStyleLB->get_value_changed_from_saved()) + { + OUString aStyle; + if (m_xNumberStyleLB->get_active()) + aStyle = m_xNumberStyleLB->get_active_text(); + const SfxStringItem* pOldRule = static_cast<const SfxStringItem*>(GetOldItem( *rSet, SID_ATTR_PARA_NUMRULE)); + if (pOldRule) + { + std::unique_ptr<SfxStringItem> pRule(pOldRule->Clone()); + pRule->SetValue(aStyle); + rSet->Put(std::move(pRule)); + m_bModified = true; + } + } + if (m_xNewStartCB->get_state_changed_from_saved() || + m_xNewStartNumberCB->get_state_changed_from_saved()|| + m_xNewStartNF->get_value_changed_from_saved()) + { + m_bModified = true; + bool bNewStartChecked = TRISTATE_TRUE == m_xNewStartCB->get_state(); + bool bNumberNewStartChecked = TRISTATE_TRUE == m_xNewStartNumberCB->get_state(); + rSet->Put(SfxBoolItem(FN_NUMBER_NEWSTART, bNewStartChecked)); + rSet->Put(SfxUInt16Item(FN_NUMBER_NEWSTART_AT, + bNumberNewStartChecked && bNewStartChecked ? o3tl::narrowing<sal_uInt16>(m_xNewStartNF->get_value()) : USHRT_MAX)); + } + + if (m_xCountParaCB->get_state_changed_from_saved()|| + m_xRestartParaCountCB->get_state_changed_from_saved() || + m_xRestartNF->get_value_changed_from_saved()) + { + SwFormatLineNumber aFormat; + aFormat.SetStartValue( static_cast< sal_uLong >(m_xRestartParaCountCB->get_state() == TRISTATE_TRUE ? + m_xRestartNF->get_value() : 0 )); + aFormat.SetCountLines(m_xCountParaCB->get_active()); + rSet->Put(aFormat); + m_bModified = true; + } + return m_bModified; +} + +void SwParagraphNumTabPage::ChangesApplied() +{ + m_xOutlineLvLB->save_value(); + m_xNumberStyleLB->save_value(); + m_xListLvLB->save_value(); + m_xNewStartCB->save_state(); + m_xNewStartNumberCB->save_state(); + m_xCountParaCB->save_state(); + m_xRestartParaCountCB->save_state(); + m_xRestartNF->save_value(); +} + +void SwParagraphNumTabPage::Reset(const SfxItemSet* rSet) +{ + bool bHasNumberStyle = false; + + SfxItemState eItemState = rSet->GetItemState( GetWhich(SID_ATTR_PARA_OUTLINE_LEVEL) ); + + sal_Int16 nOutlineLv = 1; // 0 is Text Body, 1 is level 1 + if( eItemState >= SfxItemState::DEFAULT ) + { + nOutlineLv = rSet->Get( GetWhich(SID_ATTR_PARA_OUTLINE_LEVEL) ).GetValue(); + m_xOutlineLvLB->set_active(nOutlineLv) ; + } + else + { + m_xOutlineLvLB->set_active(-1); + } + m_xOutlineLvLB->save_value(); + + eItemState = rSet->GetItemState(RES_PARATR_LIST_LEVEL); + if (eItemState >= SfxItemState::DEFAULT) + { + sal_Int16 nListLevel = rSet->Get(RES_PARATR_LIST_LEVEL).GetValue(); // 0 is level 1 + // Although listLevel doesn't have outline's "Text Body" level, treat it the same as level 1 + // so that if the outline level is either 0 or 1, it is considered equal to list level 1. + // This is a rather crucial discrepancy - otherwise the user will rarely see + // list level using the special "Same as outline level, + // and the highly desirable state of keeping the two in sync will rarely be achieved. + if ((!nOutlineLv && !nListLevel) || nListLevel == nOutlineLv - 1) + m_xListLvLB->set_active(0); // highly encourage using "Same as outline level" + else + m_xListLvLB->set_active(nListLevel + 1); + } + else + { + m_xListLvBX->hide(); + } + m_xListLvLB->save_value(); + + eItemState = rSet->GetItemState( GetWhich(SID_ATTR_PARA_NUMRULE) ); + + if( eItemState >= SfxItemState::DEFAULT ) + { + OUString aStyle = static_cast<const SfxStringItem &>(rSet->Get( GetWhich(SID_ATTR_PARA_NUMRULE) )).GetValue(); + if(aStyle.isEmpty()) + aStyle = m_xNumberStyleLB->get_text(0); + + if( aStyle == "Outline") + { + if (m_xNumberStyleLB->find_id("pseudo") == -1) + { + // tdf#145804 show "Chapter Numbering" + m_xNumberStyleLB->append("pseudo", msOutlineNumbering); + } + m_xNumberStyleLB->set_active_id("pseudo"); + m_xNumberStyleLB->save_value(); + } + else + m_xNumberStyleLB->set_active_text(aStyle); + + bHasNumberStyle = true; + } + else + { + m_xNumberStyleLB->set_active(-1); + } + + if (m_xNumberStyleBX->get_sensitive()) + EditNumStyleSelectHdl_Impl(*m_xNumberStyleLB); + + m_xNumberStyleLB->save_value(); + + eItemState = rSet->GetItemState( FN_NUMBER_NEWSTART ); + if(eItemState > SfxItemState::DEFAULT ) + { + m_bCurNumrule = true; + const SfxBoolItem& rStart = static_cast<const SfxBoolItem&>(rSet->Get(FN_NUMBER_NEWSTART)); + + m_xNewStartCB->set_state(rStart.GetValue() ? TRISTATE_TRUE : TRISTATE_FALSE ); + } + else + m_xNewStartCB->set_state(bHasNumberStyle ? TRISTATE_FALSE : TRISTATE_INDET); + + m_xNewStartCB->save_state(); + + eItemState = rSet->GetItemState( FN_NUMBER_NEWSTART_AT); + if( eItemState > SfxItemState::DEFAULT ) + { + const sal_uInt16 nNewStart = rSet->Get(FN_NUMBER_NEWSTART_AT).GetValue(); + const bool bNotMax = USHRT_MAX != nNewStart; + m_xNewStartNumberCB->set_active(bNotMax); + m_xNewStartNF->set_value(bNotMax ? nNewStart : 1); + } + else + m_xNewStartCB->set_state(TRISTATE_INDET); + NewStartHdl_Impl(*m_xNewStartCB); + m_xNewStartNF->save_value(); + m_xNewStartNumberCB->save_state(); + StyleHdl_Impl(*m_xNumberStyleLB); + if( SfxItemState::DEFAULT <= rSet->GetItemState(RES_LINENUMBER)) + { + const SwFormatLineNumber& rNum = rSet->Get(RES_LINENUMBER); + sal_uLong nStartValue = rNum.GetStartValue(); + bool bCount = rNum.IsCount(); + m_xCountParaCB->set_state(bCount ? TRISTATE_TRUE : TRISTATE_FALSE); + m_xRestartParaCountCB->set_state(0 != nStartValue ? TRISTATE_TRUE : TRISTATE_FALSE); + m_xRestartNF->set_value(nStartValue == 0 ? 1 : nStartValue); + LineCountHdl_Impl(*m_xCountParaCB); + } + else + { + m_xCountParaCB->set_state(TRISTATE_INDET); + m_xRestartParaCountCB->set_state(TRISTATE_INDET); + } + m_xCountParaCB->save_state(); + m_xRestartParaCountCB->save_state(); + m_xRestartNF->save_value(); + + m_bModified = false; +} + +void SwParagraphNumTabPage::DisableOutline() +{ + m_xOutlineStartBX->set_sensitive(false); + m_xOutlineStartBX->set_tooltip_text( SwResId(STR_OUTLINENUMBERING_DISABLED) ); +} + +void SwParagraphNumTabPage::DisableNumbering() +{ + m_xNumberStyleBX->set_sensitive(false); + m_xNumberStyleBX->set_tooltip_text( SwResId(STR_OUTLINENUMBERING_DISABLED) ); + m_xListLvBX->set_sensitive(false); +} + +void SwParagraphNumTabPage::EnableNewStart() +{ + m_xNewStartCB->show(); + m_xNewStartBX->show(); +} + +IMPL_LINK_NOARG(SwParagraphNumTabPage, NewStartHdl_Impl, weld::Toggleable&, void) +{ + bool bEnable = m_xNewStartCB->get_active(); + m_xNewStartNumberCB->set_sensitive(bEnable); + m_xNewStartNF->set_sensitive(bEnable && m_xNewStartNumberCB->get_active()); +} + +IMPL_LINK_NOARG(SwParagraphNumTabPage, LineCountHdl_Impl, weld::Toggleable&, void) +{ + m_xRestartParaCountCB->set_sensitive(m_xCountParaCB->get_active()); + + bool bEnableRestartValue = m_xRestartParaCountCB->get_sensitive() && + m_xRestartParaCountCB->get_active(); + m_xRestartBX->set_sensitive(bEnableRestartValue); +} + +IMPL_LINK_NOARG(SwParagraphNumTabPage, EditNumStyleSelectHdl_Impl, weld::ComboBox&, void) +{ + int numSelectPos = m_xNumberStyleLB->get_active(); + // 0 is "None" and -1 is unselected state and a "pseudo" is uneditable "Chapter Numbering" + if (numSelectPos == 0 || numSelectPos == -1 || m_xNumberStyleLB->get_active_id() == "pseudo") + { + m_xEditNumStyleBtn->set_sensitive(false); + m_xListLvBX->set_sensitive(false); + } + else + { + m_xEditNumStyleBtn->set_sensitive(true); + m_xListLvBX->set_sensitive(true); + } +} + +IMPL_LINK_NOARG(SwParagraphNumTabPage, EditNumStyleHdl_Impl, weld::Button&, void) +{ + OUString aTemplName(m_xNumberStyleLB->get_active_text()); + ExecuteEditNumStyle_Impl( SID_STYLE_EDIT, aTemplName, SfxStyleFamily::Pseudo ); +} + +// Internal: Perform functions through the Dispatcher +void SwParagraphNumTabPage::ExecuteEditNumStyle_Impl( + sal_uInt16 nId, const OUString &rStr, SfxStyleFamily nFamily) +{ + SfxViewShell* pViewShell = SfxViewShell::Current(); + + if( !pViewShell) + return; + + SfxDispatcher* pDispatcher = pViewShell->GetDispatcher(); + SfxStringItem aItem(nId, rStr); + SfxUInt16Item aFamily(SID_STYLE_FAMILY, static_cast<sal_uInt16>(nFamily)); + const SfxPoolItem* pItems[ 3 ]; + sal_uInt16 nCount = 0; + if( !rStr.isEmpty() ) + pItems[ nCount++ ] = &aItem; + pItems[ nCount++ ] = &aFamily; + + pItems[ nCount++ ] = nullptr; + + // tdf#145363 we want the current dialog to be the parent of the new dialog + weld::Window* pDialogParent = GetFrameWeld(); + css::uno::Any aAny(pDialogParent->GetXWindow()); + SfxUnoAnyItem aDialogParent(SID_DIALOG_PARENT, aAny); + const SfxPoolItem* pInternalItems[ 2 ]; + pInternalItems[ 0 ] = &aDialogParent; + pInternalItems[ 1 ] = nullptr; + + pDispatcher->Execute( + nId, SfxCallMode::SYNCHRON | SfxCallMode::RECORD, + pItems, 0, pInternalItems); +} + +IMPL_LINK(SwParagraphNumTabPage, StyleHdl_Impl, weld::ComboBox&, rBox, void) +{ + bool bEnable = m_bCurNumrule || rBox.get_active() > 0; + m_xNewStartCB->set_sensitive(bEnable); + NewStartHdl_Impl(*m_xNewStartCB); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/ui/chrdlg/pardlg.cxx b/sw/source/ui/chrdlg/pardlg.cxx new file mode 100644 index 0000000000..379ee335ca --- /dev/null +++ b/sw/source/ui/chrdlg/pardlg.cxx @@ -0,0 +1,245 @@ +/* -*- 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/htmlmode.hxx> +#include <sfx2/tabdlg.hxx> +#include <svl/style.hxx> +#include <svl/cjkoptions.hxx> +#include <docsh.hxx> +#include <wrtsh.hxx> +#include <view.hxx> +#include <swuipardlg.hxx> +#include <pardlg.hxx> +#include <drpcps.hxx> +#include <viewopt.hxx> +#include <numpara.hxx> +#include <strings.hrc> +#include <svx/svxids.hrc> +#include <svl/eitem.hxx> +#include <svl/intitem.hxx> +#include <svx/svxdlg.hxx> +#include <svx/dialogs.hrc> +#include <svx/flagsdef.hxx> +#include <osl/diagnose.h> +#include <officecfg/Office/Common.hxx> + +SwParaDlg::SwParaDlg(weld::Window *pParent, + SwView& rVw, + const SfxItemSet& rCoreSet, + sal_uInt8 nDialogMode, + const OUString *pTitle, + bool bDraw, + const OUString& sDefPage) + : SfxTabDialogController(pParent, + "modules/swriter/ui/paradialog.ui", + "ParagraphPropertiesDialog", + &rCoreSet, nullptr != pTitle) + , m_rView(rVw) + , m_bDrawParaDlg(bDraw) +{ + sal_uInt16 nHtmlMode = ::GetHtmlMode(rVw.GetDocShell()); + bool bHtmlMode = (nHtmlMode & HTMLMODE_ON) == HTMLMODE_ON; + if(pTitle) + { + // Update title + m_xDialog->set_title(m_xDialog->get_title() + SwResId(STR_TEXTCOLL_HEADER) + *pTitle + ")"); + } + // tabs common to paragraph and draw paragraphs (paragraphs inside a text box) + SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create(); + + OSL_ENSURE(pFact->GetTabPageCreatorFunc(RID_SVXPAGE_STD_PARAGRAPH), "GetTabPageCreatorFunc fail!"); + OSL_ENSURE(pFact->GetTabPageRangesFunc(RID_SVXPAGE_STD_PARAGRAPH), "GetTabPageRangesFunc fail!"); + AddTabPage("labelTP_PARA_STD", pFact->GetTabPageCreatorFunc(RID_SVXPAGE_STD_PARAGRAPH), + pFact->GetTabPageRangesFunc(RID_SVXPAGE_STD_PARAGRAPH) ); + + OSL_ENSURE(pFact->GetTabPageCreatorFunc(RID_SVXPAGE_ALIGN_PARAGRAPH), "GetTabPageCreatorFunc fail!"); + OSL_ENSURE(pFact->GetTabPageRangesFunc(RID_SVXPAGE_ALIGN_PARAGRAPH), "GetTabPageRangesFunc fail!"); + AddTabPage("labelTP_PARA_ALIGN", pFact->GetTabPageCreatorFunc(RID_SVXPAGE_ALIGN_PARAGRAPH), + pFact->GetTabPageRangesFunc(RID_SVXPAGE_ALIGN_PARAGRAPH)); + + if (!m_bDrawParaDlg && (!bHtmlMode || officecfg::Office::Common::Filter::HTML::Export::PrintLayout::get())) + { + OSL_ENSURE(pFact->GetTabPageCreatorFunc(RID_SVXPAGE_EXT_PARAGRAPH), "GetTabPageCreatorFunc fail!"); + OSL_ENSURE(pFact->GetTabPageRangesFunc(RID_SVXPAGE_EXT_PARAGRAPH), "GetTabPageRangesFunc fail!"); + AddTabPage("textflow", pFact->GetTabPageCreatorFunc(RID_SVXPAGE_EXT_PARAGRAPH), + pFact->GetTabPageRangesFunc(RID_SVXPAGE_EXT_PARAGRAPH)); + + } + else + RemoveTabPage("textflow"); + + if(!bHtmlMode && SvtCJKOptions::IsAsianTypographyEnabled()) + { + OSL_ENSURE(pFact->GetTabPageCreatorFunc(RID_SVXPAGE_PARA_ASIAN), "GetTabPageCreatorFunc fail!"); + OSL_ENSURE(pFact->GetTabPageRangesFunc(RID_SVXPAGE_PARA_ASIAN), "GetTabPageRangesFunc fail!"); + AddTabPage( "labelTP_PARA_ASIAN", pFact->GetTabPageCreatorFunc(RID_SVXPAGE_PARA_ASIAN), + pFact->GetTabPageRangesFunc(RID_SVXPAGE_PARA_ASIAN) ); + } + else + RemoveTabPage("labelTP_PARA_ASIAN"); + + if(bHtmlMode) + RemoveTabPage("labelTP_TABULATOR"); + else + { + OSL_ENSURE(pFact->GetTabPageCreatorFunc(RID_SVXPAGE_TABULATOR), "GetTabPageCreatorFunc fail!"); + OSL_ENSURE(pFact->GetTabPageRangesFunc(RID_SVXPAGE_TABULATOR), "GetTabPageRangesFunc fail!"); + AddTabPage( "labelTP_TABULATOR", pFact->GetTabPageCreatorFunc(RID_SVXPAGE_TABULATOR), pFact->GetTabPageRangesFunc(RID_SVXPAGE_TABULATOR) ); + } + + // remove unwanted tabs for draw text box paragraph properties + if (m_bDrawParaDlg) + { + RemoveTabPage("labelTP_NUMPARA"); + RemoveTabPage("labelTP_DROPCAPS"); + RemoveTabPage("labelTP_BORDER"); + RemoveTabPage("area"); + RemoveTabPage("transparence"); + } + else + { + if(!(nDialogMode & DLG_ENVELOP)) + AddTabPage("labelTP_NUMPARA", SwParagraphNumTabPage::Create, SwParagraphNumTabPage::GetRanges); + else + RemoveTabPage("labelTP_NUMPARA"); + + AddTabPage("labelTP_DROPCAPS", SwDropCapsPage::Create, SwDropCapsPage::GetRanges); + + if(!bHtmlMode || (nHtmlMode & (HTMLMODE_SOME_STYLES|HTMLMODE_FULL_STYLES))) + { + // add Area and Transparence TabPages + AddTabPage("area", pFact->GetTabPageCreatorFunc( RID_SVXPAGE_AREA ), pFact->GetTabPageRangesFunc( RID_SVXPAGE_AREA )); + AddTabPage("transparence", pFact->GetTabPageCreatorFunc( RID_SVXPAGE_TRANSPARENCE ), pFact->GetTabPageRangesFunc( RID_SVXPAGE_TRANSPARENCE ) ); + } + else + { + RemoveTabPage("area"); + RemoveTabPage("transparence"); + } + + OSL_ENSURE(pFact->GetTabPageCreatorFunc( RID_SVXPAGE_BORDER ), "GetTabPageCreatorFunc fail!"); + OSL_ENSURE(pFact->GetTabPageRangesFunc( RID_SVXPAGE_BORDER ), "GetTabPageRangesFunc fail!"); + AddTabPage("labelTP_BORDER", pFact->GetTabPageCreatorFunc( RID_SVXPAGE_BORDER ), pFact->GetTabPageRangesFunc( RID_SVXPAGE_BORDER ) ); + } + + if (!sDefPage.isEmpty()) + SetCurPageId(sDefPage); +} + +SwParaDlg::~SwParaDlg() +{ +} + +void SwParaDlg::PageCreated(const OUString& rId, SfxTabPage& rPage) +{ + SwWrtShell& rSh = m_rView.GetWrtShell(); + SfxAllItemSet aSet(*(GetInputSetImpl()->GetPool())); + + // Table borders cannot get any shade in Writer + if (rId == "labelTP_BORDER") + { + aSet.Put (SfxUInt16Item(SID_SWMODE_TYPE,static_cast<sal_uInt16>(SwBorderModes::PARA))); + rPage.PageCreated(aSet); + } + else if (rId == "labelTP_PARA_STD") + { + aSet.Put(SfxUInt16Item(SID_SVXSTDPARAGRAPHTABPAGE_PAGEWIDTH, + static_cast< sal_uInt16 >(rSh.GetAnyCurRect(CurRectType::PagePrt).Width()) )); + + if (!m_bDrawParaDlg) + { + // See SvxStdParagraphTabPage::PageCreated: enable RegisterMode, AutoFirstLine, NegativeMode, ContextualMode + constexpr tools::Long constTwips_0_5mm = o3tl::toTwips(5, o3tl::Length::mm10); + aSet.Put(SfxUInt32Item(SID_SVXSTDPARAGRAPHTABPAGE_FLAGSET,0x0002|0x0004|0x0008|0x0010)); + aSet.Put(SfxUInt32Item(SID_SVXSTDPARAGRAPHTABPAGE_ABSLINEDIST, constTwips_0_5mm)); + + } + rPage.PageCreated(aSet); + } + else if (rId == "labelTP_PARA_ALIGN") + { + if (!m_bDrawParaDlg) + { + aSet.Put(SfxBoolItem(SID_SVXPARAALIGNTABPAGE_ENABLEJUSTIFYEXT,true)); + rPage.PageCreated(aSet); + } + } + else if (rId == "textflow") + { + // pagebreak only when the cursor is in the body-area and not in a table + const FrameTypeFlags eType = rSh.GetFrameType(nullptr,true); + if( !(FrameTypeFlags::BODY & eType) || + rSh.GetSelectionType() & SelectionType::Table ) + { + aSet.Put(SfxBoolItem(SID_DISABLE_SVXEXTPARAGRAPHTABPAGE_PAGEBREAK,true)); + rPage.PageCreated(aSet); + } + } + else if (rId == "labelTP_DROPCAPS") + { + static_cast<SwDropCapsPage&>(rPage).SetFormat(false); + } + else if (rId == "labelTP_NUMPARA") + { + SwTextFormatColl* pTmpColl = rSh.GetCurTextFormatColl(); + if( pTmpColl && pTmpColl->IsAssignedToListLevelOfOutlineStyle() ) + { + static_cast<SwParagraphNumTabPage&>(rPage).DisableOutline() ; + } + + static_cast<SwParagraphNumTabPage&>(rPage).EnableNewStart(); + weld::ComboBox& rBox = static_cast<SwParagraphNumTabPage&>(rPage).GetStyleBox(); + SfxStyleSheetBasePool* pPool = m_rView.GetDocShell()->GetStyleSheetPool(); + const SfxStyleSheetBase* pBase = pPool->First(SfxStyleFamily::Pseudo); + std::set<OUString> aNames; + while(pBase) + { + aNames.insert(pBase->GetName()); + pBase = pPool->Next(); + } + aNames.erase(SwResId(STR_POOLNUMRULE_NOLIST)); + for (const auto& rName : aNames) + rBox.append_text(rName); + } + // inits for Area and Transparency TabPages + // The selection attribute lists (XPropertyList derivates, e.g. XColorList for + // the color table) need to be added as items (e.g. SvxColorTableItem) to make + // these pages find the needed attributes for fill style suggestions. + // These are added in SwDocStyleSheet::GetItemSet() for the SfxStyleFamily::Para on + // demand, but could also be directly added from the DrawModel. + else if (rId == "area") + { + SfxItemSetFixed + <SID_COLOR_TABLE, SID_PATTERN_LIST, + SID_OFFER_IMPORT, SID_OFFER_IMPORT> aNew(*aSet.GetPool()); + + aNew.Put(*GetInputSetImpl()); + + // add flag for direct graphic content selection + aNew.Put(SfxBoolItem(SID_OFFER_IMPORT, true)); + + rPage.PageCreated(aNew); + } + else if (rId == "transparence") + { + rPage.PageCreated(*GetInputSetImpl()); + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/ui/chrdlg/swuiccoll.cxx b/sw/source/ui/chrdlg/swuiccoll.cxx new file mode 100644 index 0000000000..8dddc8a410 --- /dev/null +++ b/sw/source/ui/chrdlg/swuiccoll.cxx @@ -0,0 +1,247 @@ +/* -*- 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 <cmdid.h> +#include <o3tl/safeint.hxx> +#include <swmodule.hxx> +#include <view.hxx> +#include <wrtsh.hxx> + +#include <sfx2/styfitem.hxx> + +#include <ccoll.hxx> +#include <fmtcol.hxx> +#include <hintids.hxx> +#include <docsh.hxx> + +#include <swuiccoll.hxx> + +const WhichRangesContainer SwCondCollPage::s_aPageRg(svl::Items<FN_COND_COLL, FN_COND_COLL>); + +SwCondCollPage::SwCondCollPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet &rSet) + : SfxTabPage(pPage, pController, "modules/swriter/ui/conditionpage.ui", "ConditionPage", &rSet) + , m_pCmds(SwCondCollItem::GetCmds()) + , m_pFormat(nullptr) + , m_xTbLinks(m_xBuilder->weld_tree_view("links")) + , m_xStyleLB(m_xBuilder->weld_tree_view("styles")) + , m_xFilterLB(m_xBuilder->weld_combo_box("filter")) + , m_xRemovePB(m_xBuilder->weld_button("remove")) + , m_xAssignPB(m_xBuilder->weld_button("apply")) +{ + m_xStyleLB->make_sorted(); + const auto nHeightRequest = m_xStyleLB->get_height_rows(12); + m_xStyleLB->set_size_request(-1, nHeightRequest); + m_xTbLinks->set_size_request(-1, nHeightRequest); + std::vector<int> aWidths + { + o3tl::narrowing<int>(m_xTbLinks->get_approximate_digit_width() * 40) + }; + m_xTbLinks->set_column_fixed_widths(aWidths); + + const sal_Int32 nStrCount = m_xFilterLB->get_count(); + for (sal_Int32 i = 0; i < nStrCount; ++i) + m_aStrArr.push_back(m_xFilterLB->get_text(i)); + m_xFilterLB->clear(); + + SetExchangeSupport(); + + // Install handlers + m_xTbLinks->connect_row_activated(LINK(this, SwCondCollPage, AssignRemoveTreeListBoxHdl)); + m_xStyleLB->connect_row_activated(LINK(this, SwCondCollPage, AssignRemoveTreeListBoxHdl)); + m_xRemovePB->connect_clicked(LINK(this, SwCondCollPage, AssignRemoveClickHdl)); + m_xAssignPB->connect_clicked(LINK(this, SwCondCollPage, AssignRemoveClickHdl)); + m_xTbLinks->connect_changed(LINK(this, SwCondCollPage, SelectTreeListBoxHdl)); + m_xStyleLB->connect_changed(LINK(this, SwCondCollPage, SelectTreeListBoxHdl)); + m_xFilterLB->connect_changed(LINK(this, SwCondCollPage, SelectListBoxHdl)); + + std::optional<SfxStyleFamilies> xFamilies(SW_MOD()->CreateStyleFamilies()); + size_t nCount = xFamilies->size(); + for (size_t j = 0; j < nCount; ++j) + { + const SfxStyleFamilyItem &rFamilyItem = xFamilies->at(j); + if (SfxStyleFamily::Para == rFamilyItem.GetFamily()) + { + const SfxStyleFilter& rFilterList = rFamilyItem.GetFilterList(); + for (size_t i = 0; i < rFilterList.size(); ++i) + m_xFilterLB->append(OUString::number(int(rFilterList[i].nFlags)), rFilterList[i].aName); + break; + } + } + + m_xFilterLB->set_active(0); + m_xTbLinks->show(); +} + +SwCondCollPage::~SwCondCollPage() +{ +} + +DeactivateRC SwCondCollPage::DeactivatePage(SfxItemSet * _pSet) +{ + if( _pSet ) + FillItemSet(_pSet); + + return DeactivateRC::LeavePage; +} + +std::unique_ptr<SfxTabPage> SwCondCollPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet *rSet) +{ + return std::make_unique<SwCondCollPage>(pPage, pController, *rSet); +} + +bool SwCondCollPage::FillItemSet(SfxItemSet *rSet) +{ + SwCondCollItem aCondItem; + for (size_t i = 0; i < m_aStrArr.size(); ++i) + { + const OUString sEntry = m_xTbLinks->get_text(i, 1); + aCondItem.SetStyle( &sEntry, i); + } + rSet->Put(aCondItem); + return true; +} + +void SwCondCollPage::Reset(const SfxItemSet *) +{ + m_xTbLinks->clear(); + m_xStyleLB->clear(); + + SwView* pView = GetActiveView(); + if (!pView) + return; + + SfxStyleSheetBasePool* pPool = pView->GetWrtShell().GetView().GetDocShell()->GetStyleSheetPool(); + const SfxStyleSheetBase* pBase = pPool->First(SfxStyleFamily::Para); + while (pBase) + { + if (!m_pFormat || pBase->GetName() != m_pFormat->GetName()) + m_xStyleLB->append_text(pBase->GetName()); + pBase = pPool->Next(); + } + m_xStyleLB->select(0); + + for (size_t n = 0; n < m_aStrArr.size(); ++n) + { + m_xTbLinks->append_text(m_aStrArr[n]); + + const SwCollCondition* pCond = nullptr; + if( m_pFormat && RES_CONDTXTFMTCOLL == m_pFormat->Which() && + nullptr != ( pCond = static_cast<SwConditionTextFormatColl*>(m_pFormat)-> + HasCondition( SwCollCondition( nullptr, m_pCmds[n].nCnd, m_pCmds[n].nSubCond ) ) ) + && pCond->GetTextFormatColl() ) + { + m_xTbLinks->set_text(n, pCond->GetTextFormatColl()->GetName(), 1); + } + + if (0 == n) + { + m_xTbLinks->select(0); + SelectTreeListBoxHdl(*m_xTbLinks); + } + } +} + +IMPL_LINK(SwCondCollPage, AssignRemoveClickHdl, weld::Button&, rBtn, void) +{ + AssignRemove(&rBtn); +} + +IMPL_LINK(SwCondCollPage, AssignRemoveTreeListBoxHdl, weld::TreeView&, rBtn, bool) +{ + AssignRemove(&rBtn); + return true; +} + +void SwCondCollPage::AssignRemove(const weld::Widget* pBtn) +{ + int nPos = m_xTbLinks->get_selected_index(); + if (nPos == -1) + { + return; + } + + const bool bAssEnabled = pBtn != m_xRemovePB.get() && m_xAssignPB->get_sensitive(); + m_xAssignPB->set_sensitive(!bAssEnabled); + m_xRemovePB->set_sensitive(bAssEnabled); + if (bAssEnabled) + m_xTbLinks->set_text(nPos, m_xStyleLB->get_selected_text(), 1); + else + m_xTbLinks->set_text(nPos, "", 1); +} + +IMPL_LINK(SwCondCollPage, SelectTreeListBoxHdl, weld::TreeView&, rBox, void) +{ + SelectHdl(&rBox); +} + +IMPL_LINK(SwCondCollPage, SelectListBoxHdl, weld::ComboBox&, rBox, void) +{ + SelectHdl(&rBox); +} + +void SwCondCollPage::SelectHdl(const weld::Widget* pBox) +{ + if (pBox == m_xFilterLB.get()) + { + m_xStyleLB->clear(); + + SwView* pView = GetActiveView(); + if (!pView) + return; + + const sal_Int32 nSelPos = m_xFilterLB->get_active(); + const SfxStyleSearchBits nSearchFlags = static_cast<SfxStyleSearchBits>(m_xFilterLB->get_id(nSelPos).toInt32()); + SfxStyleSheetBasePool* pPool = pView->GetWrtShell().GetView().GetDocShell()->GetStyleSheetPool(); + const SfxStyleSheetBase* pBase = pPool->First(SfxStyleFamily::Para, nSearchFlags); + + bool bEmpty = true; + while (pBase) + { + if (!m_pFormat || pBase->GetName() != m_pFormat->GetName()) + { + m_xStyleLB->append_text(pBase->GetName()); + bEmpty = false; + } + pBase = pPool->Next(); + } + m_xStyleLB->select(bEmpty ? -1 : 0); + SelectHdl(m_xStyleLB.get()); + } + else + { + int nSelected = m_xTbLinks->get_selected_index(); + const OUString sTbEntry = nSelected != -1 + ? m_xTbLinks->get_text(nSelected, 1) + : OUString(); + const OUString sStyle = m_xStyleLB->get_selected_text(); + + m_xAssignPB->set_sensitive(sStyle != sTbEntry); + + if (pBox != m_xStyleLB.get()) + m_xRemovePB->set_sensitive(!sTbEntry.isEmpty()); + } +} + +void SwCondCollPage::SetCollection(SwFormat* pFormat) +{ + m_pFormat = pFormat; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/ui/chrdlg/tblnumfm.cxx b/sw/source/ui/chrdlg/tblnumfm.cxx new file mode 100644 index 0000000000..dd3f575e2b --- /dev/null +++ b/sw/source/ui/chrdlg/tblnumfm.cxx @@ -0,0 +1,46 @@ +/* -*- 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/svxids.hrc> +#include <svx/numinf.hxx> +#include <tblnumfm.hxx> + +#include <svx/dialogs.hrc> +#include <svl/itemset.hxx> +#include <sfx2/sfxdlg.hxx> +#include <sfx2/tabdlg.hxx> + +SwNumFormatDlg::SwNumFormatDlg(weld::Widget* pParent, const SfxItemSet& rSet) + : SfxSingleTabDialogController(pParent, &rSet, "cui/ui/formatnumberdialog.ui", "FormatNumberDialog") + , m_xContent( m_xBuilder->weld_container("content") ) +{ + // Create TabPage + SfxAbstractDialogFactory* pFact = SfxAbstractDialogFactory::Create(); + ::CreateTabPage fnCreatePage = pFact->GetTabPageCreatorFunc(RID_SVXPAGE_NUMBERFORMAT); + if ( fnCreatePage ) + { + std::unique_ptr<SfxTabPage> xNewPage = (*fnCreatePage)(m_xContent.get(), this, &rSet); + SfxAllItemSet aSet(*(rSet.GetPool())); + aSet.Put(xNewPage->GetItemSet().Get( SID_ATTR_NUMBERFORMAT_INFO)); + xNewPage->PageCreated(aSet); + SetTabPage(std::move(xNewPage)); + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |