ITEM: Refactor ItemType
[LibreOffice.git] / sw / source / ui / frmdlg / cption.cxx
blob292ac69838a25c8f6ea6e4b00332ee3c1fcf29c5
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <utility>
21 #include <view.hxx>
22 #include <wrtsh.hxx>
23 #include <cption.hxx>
24 #include <fldmgr.hxx>
25 #include <expfld.hxx>
26 #include <numrule.hxx>
27 #include <poolfmt.hxx>
28 #include <docsh.hxx>
29 #include <calc.hxx>
30 #include <uitool.hxx>
31 #include <doc.hxx>
32 #include <modcfg.hxx>
33 #include <swmodule.hxx>
34 #include <com/sun/star/frame/XModel.hpp>
35 #include <com/sun/star/text/XTextGraphicObjectsSupplier.hpp>
36 #include <com/sun/star/text/XTextTablesSupplier.hpp>
37 #include <com/sun/star/text/XTextEmbeddedObjectsSupplier.hpp>
38 #include <com/sun/star/text/XTextFramesSupplier.hpp>
39 #include <comphelper/string.hxx>
40 #include <vcl/weld.hxx>
41 #include <strings.hrc>
42 #include <SwStyleNameMapper.hxx>
43 #include <unotxdoc.hxx>
45 using namespace ::com::sun::star;
47 namespace {
49 class SwSequenceOptionDialog : public weld::GenericDialogController
51 SwView& m_rView;
52 OUString m_aFieldTypeName;
54 std::unique_ptr<weld::ComboBox> m_xLbLevel;
55 std::unique_ptr<weld::Entry> m_xEdDelim;
57 std::unique_ptr<weld::ComboBox> m_xLbCharStyle;
58 std::unique_ptr<weld::CheckButton> m_xApplyBorderAndShadowCB;
60 //#i61007# order of captions
61 std::unique_ptr<weld::ComboBox> m_xLbCaptionOrder;
63 public:
64 SwSequenceOptionDialog(weld::Window *pParent, SwView &rV, OUString aSeqFieldType);
65 void Apply();
67 bool IsApplyBorderAndShadow() const { return m_xApplyBorderAndShadowCB->get_active(); }
68 void SetApplyBorderAndShadow( bool bSet ) { m_xApplyBorderAndShadowCB->set_active(bSet); }
70 //#i61007# order of captions
71 bool IsOrderNumberingFirst() const { return m_xLbCaptionOrder->get_active() == 1; }
72 void SetOrderNumberingFirst(bool bSet) { m_xLbCaptionOrder->set_active(bSet ? 1 : 0); }
74 void SetCharacterStyle(const OUString& rStyle);
75 OUString GetCharacterStyle() const;
80 OUString SwCaptionDialog::s_aSepTextSave(u": "_ustr); // Caption separator text
82 //Resolves: tdf#47427 disallow typing *or* pasting invalid content into the category box
83 OUString TextFilterAutoConvert::filter(const OUString &rText)
85 if (!rText.isEmpty() && rText != m_sNone && !SwCalc::IsValidVarName(rText))
86 return m_sLastGoodText;
87 m_sLastGoodText = rText;
88 return rText;
91 SwCaptionDialog::SwCaptionDialog(weld::Window *pParent, SwView &rV)
92 : SfxDialogController(pParent, u"modules/swriter/ui/insertcaption.ui"_ustr, u"InsertCaptionDialog"_ustr)
93 , m_sNone(SwResId(SW_STR_NONE))
94 , m_aTextFilter(m_sNone)
95 , m_rView(rV)
96 , m_pMgr(new SwFieldMgr(m_rView.GetWrtShellPtr()))
97 , m_bCopyAttributes(false)
98 , m_bOrderNumberingFirst(SwModule::get()->GetModuleConfig()->IsCaptionOrderNumberingFirst())
99 , m_xTextEdit(m_xBuilder->weld_entry(u"caption_edit"_ustr))
100 , m_xCategoryBox(m_xBuilder->weld_combo_box(u"category"_ustr))
101 , m_xFormatText(m_xBuilder->weld_label(u"numbering_label"_ustr))
102 , m_xFormatBox(m_xBuilder->weld_combo_box(u"numbering"_ustr))
103 , m_xNumberingSeparatorFT(m_xBuilder->weld_label(u"num_separator"_ustr))
104 , m_xNumberingSeparatorED(m_xBuilder->weld_entry(u"num_separator_edit"_ustr))
105 , m_xSepText(m_xBuilder->weld_label(u"separator_label"_ustr))
106 , m_xSepEdit(m_xBuilder->weld_entry(u"separator_edit"_ustr))
107 , m_xPosBox(m_xBuilder->weld_combo_box(u"position"_ustr))
108 , m_xOKButton(m_xBuilder->weld_button(u"ok"_ustr))
109 , m_xAutoCaptionButton(m_xBuilder->weld_button(u"auto"_ustr))
110 , m_xOptionButton(m_xBuilder->weld_button(u"options"_ustr))
111 , m_xPreview(new weld::CustomWeld(*m_xBuilder, u"preview"_ustr, m_aPreview))
113 //#i61007# order of captions
114 ApplyCaptionOrder();
115 SwWrtShell &rSh = m_rView.GetWrtShell();
116 rtl::Reference< SwXTextDocument > xModel = m_rView.GetDocShell()->GetBaseModel();
118 SelectionType eType = rSh.GetSelectionType();
119 if ( eType & SelectionType::Ole )
121 eType = SelectionType::Graphic;
122 m_xNameAccess = xModel->getEmbeddedObjects();
125 m_xCategoryBox->connect_changed(LINK(this, SwCaptionDialog, ModifyComboHdl));
126 Link<weld::Entry&,void> aLk = LINK(this, SwCaptionDialog, ModifyEntryHdl);
127 m_xTextEdit->connect_changed(aLk);
128 m_xNumberingSeparatorED->connect_changed(aLk);
129 m_xSepEdit->connect_changed(aLk);
131 m_xFormatBox->connect_changed(LINK(this, SwCaptionDialog, SelectListBoxHdl));
132 m_xOKButton->connect_clicked(LINK(this, SwCaptionDialog, OKHdl));
133 m_xOptionButton->connect_clicked(LINK(this, SwCaptionDialog, OptionHdl));
134 m_xAutoCaptionButton->connect_clicked(LINK(this, SwCaptionDialog, CaptionHdl));
135 m_xAutoCaptionButton->set_accessible_description(SwResId(STR_A11Y_DESC_AUTO));
137 m_xCategoryBox->append_text(m_sNone);
138 size_t nCount = m_pMgr->GetFieldTypeCount();
139 for (size_t i = 0; i < nCount; ++i)
141 SwFieldType *pType = m_pMgr->GetFieldType( SwFieldIds::Unknown, i );
142 if( pType->Which() == SwFieldIds::SetExp &&
143 static_cast<SwSetExpFieldType *>( pType)->GetType() & nsSwGetSetExpType::GSE_SEQ )
144 m_xCategoryBox->append_text(pType->GetName());
147 OUString sString;
148 sal_uInt16 nPoolId = 0;
149 if (eType & SelectionType::Graphic)
151 nPoolId = RES_POOLCOLL_LABEL_FIGURE;
153 SwSetExpFieldType* pTypeIll= static_cast<SwSetExpFieldType*>(rSh.GetFieldType(SwFieldIds::SetExp, SwResId(STR_POOLCOLL_LABEL_ABB)));
154 if(rSh.IsUsed(*pTypeIll)) //default to illustration for legacy docs
156 nPoolId = RES_POOLCOLL_LABEL_ABB;
160 sString = m_rView.GetOldGrfCat();
161 m_bCopyAttributes = true;
162 //if not OLE
163 if(!m_xNameAccess.is())
165 m_xNameAccess = xModel->getGraphicObjects();
169 else if( eType & SelectionType::Table )
171 nPoolId = RES_POOLCOLL_LABEL_TABLE;
172 sString = m_rView.GetOldTabCat();
173 m_xNameAccess = xModel->getTextTables();
175 else if( eType & SelectionType::Frame )
177 nPoolId = RES_POOLCOLL_LABEL_FRAME;
178 sString = m_rView.GetOldFrameCat();
179 m_xNameAccess = xModel->getTextFrames();
181 else if( eType == SelectionType::Text )
183 nPoolId = RES_POOLCOLL_LABEL_FRAME;
184 sString = m_rView.GetOldFrameCat();
186 else if( eType & SelectionType::DrawObject )
188 nPoolId = RES_POOLCOLL_LABEL_DRAWING;
189 sString = m_rView.GetOldDrwCat();
191 if( nPoolId )
193 if (sString.isEmpty())
194 sString = SwStyleNameMapper::GetUIName(nPoolId, OUString());
195 auto nIndex = m_xCategoryBox->find_text(sString);
196 if (nIndex != -1)
197 m_xCategoryBox->set_active(nIndex);
198 else
199 m_xCategoryBox->set_entry_text(sString);
202 // aFormatBox
203 sal_uInt16 nSelFormat = SVX_NUM_ARABIC;
204 nCount = m_pMgr->GetFieldTypeCount();
205 for ( size_t i = nCount; i; )
207 SwFieldType* pFieldType = m_pMgr->GetFieldType(SwFieldIds::Unknown, --i);
208 if (pFieldType->GetName() == m_xCategoryBox->get_active_text())
210 nSelFormat = o3tl::narrowing<sal_uInt16>(static_cast<SwSetExpFieldType*>(pFieldType)->GetSeqFormat());
211 break;
215 sal_uInt16 nFormatCount = m_pMgr->GetFormatCount(SwFieldTypesEnum::Sequence, false);
216 for ( sal_uInt16 i = 0; i < nFormatCount; ++i )
218 const sal_uInt16 nFormatId = m_pMgr->GetFormatId(SwFieldTypesEnum::Sequence, i);
219 m_xFormatBox->append(OUString::number(nFormatId), m_pMgr->GetFormatStr(SwFieldTypesEnum::Sequence, i));
220 if (nFormatId == nSelFormat)
221 m_xFormatBox->set_active(i);
224 // aPosBox
225 if (eType == SelectionType::Graphic
226 || eType == SelectionType::Table
227 || eType == (SelectionType::Table | SelectionType::NumberList)
228 || eType == (SelectionType::Table | SelectionType::Text)
229 || eType == (SelectionType::Table | SelectionType::NumberList | SelectionType::Text)
230 || eType == SelectionType::DrawObject
231 || eType == (SelectionType::DrawObject | SelectionType::Ornament))
233 m_xPosBox->append_text(SwResId(STR_CAPTION_ABOVE));
234 m_xPosBox->append_text(SwResId(STR_CAPTION_BELOW));
236 else if(eType == SelectionType::Frame
237 || eType == SelectionType::Text)
239 m_xPosBox->append_text(SwResId(STR_CAPTION_BEGINNING));
240 m_xPosBox->append_text(SwResId(STR_CAPTION_END));
243 if (eType & SelectionType::Table)
245 m_xPosBox->set_active(0);
247 else
249 m_xPosBox->set_active(1);
252 ModifyHdl();
254 m_xSepEdit->set_text(s_aSepTextSave);
255 m_xTextEdit->grab_focus();
256 DrawSample();
259 IMPL_LINK_NOARG(SwCaptionDialog, OKHdl, weld::Button&, void)
261 Apply();
262 m_xDialog->response(RET_OK);
265 void SwCaptionDialog::Apply()
267 InsCaptionOpt aOpt;
268 aOpt.UseCaption() = true;
269 OUString aName(m_xCategoryBox->get_active_text());
270 if ( aName == m_sNone )
272 aOpt.SetCategory( OUString() );
273 aOpt.SetNumSeparator( OUString() );
275 else
277 aOpt.SetCategory(comphelper::string::strip(aName, ' '));
278 aOpt.SetNumSeparator(m_xNumberingSeparatorED->get_text());
280 aOpt.SetNumType(m_xFormatBox->get_active_id().toUInt32());
281 aOpt.SetSeparator(m_xSepEdit->get_sensitive() ? m_xSepEdit->get_text() : OUString());
282 aOpt.SetCaption(m_xTextEdit->get_text());
283 aOpt.SetPos(m_xPosBox->get_active());
284 aOpt.IgnoreSeqOpts() = true;
285 aOpt.CopyAttributes() = m_bCopyAttributes;
286 aOpt.SetCharacterStyle( m_sCharacterStyle );
287 m_rView.InsertCaption( &aOpt );
288 s_aSepTextSave = m_xSepEdit->get_text();
291 short SwCaptionDialog::run()
293 short nRet = SfxDialogController::run();
294 if (nRet == RET_OK)
295 Apply();
296 return nRet;
299 IMPL_LINK_NOARG(SwCaptionDialog, OptionHdl, weld::Button&, void)
301 OUString sFieldTypeName = m_xCategoryBox->get_active_text();
302 if(sFieldTypeName == m_sNone)
303 sFieldTypeName.clear();
304 auto pDlg = std::make_shared<SwSequenceOptionDialog>(m_xDialog.get(), m_rView, sFieldTypeName);
305 pDlg->SetApplyBorderAndShadow(m_bCopyAttributes);
306 pDlg->SetCharacterStyle( m_sCharacterStyle );
307 pDlg->SetOrderNumberingFirst( m_bOrderNumberingFirst );
309 GenericDialogController::runAsync(pDlg, [pDlg, this](sal_Int32 nResult){
310 if (nResult == RET_OK) {
311 pDlg->Apply();
312 m_bCopyAttributes = pDlg->IsApplyBorderAndShadow();
313 m_sCharacterStyle = pDlg->GetCharacterStyle();
314 //#i61007# order of captions
315 if( m_bOrderNumberingFirst != pDlg->IsOrderNumberingFirst() )
317 m_bOrderNumberingFirst = pDlg->IsOrderNumberingFirst();
318 SwModule::get()->GetModuleConfig()->SetCaptionOrderNumberingFirst(m_bOrderNumberingFirst);
319 ApplyCaptionOrder();
321 DrawSample();
326 IMPL_LINK_NOARG(SwCaptionDialog, SelectListBoxHdl, weld::ComboBox&, void)
328 DrawSample();
331 void SwCaptionDialog::ModifyHdl()
333 SwWrtShell &rSh = m_rView.GetWrtShell();
334 OUString sFieldTypeName = m_xCategoryBox->get_active_text();
335 bool bCorrectFieldName = !sFieldTypeName.isEmpty();
336 bool bNone = sFieldTypeName == m_sNone;
337 SwFieldType* pType = (bCorrectFieldName && !bNone)
338 ? rSh.GetFieldType( SwFieldIds::SetExp, sFieldTypeName )
339 : nullptr;
340 m_xOKButton->set_sensitive( bCorrectFieldName &&
341 (!pType ||
342 static_cast<SwSetExpFieldType*>(pType)->GetType() == nsSwGetSetExpType::GSE_SEQ) );
343 m_xOptionButton->set_sensitive(m_xOKButton->get_sensitive() && !bNone);
344 m_xNumberingSeparatorFT->set_sensitive(m_bOrderNumberingFirst && !bNone);
345 m_xNumberingSeparatorED->set_sensitive(m_bOrderNumberingFirst && !bNone);
346 m_xFormatText->set_sensitive(!bNone);
347 m_xFormatBox->set_sensitive(!bNone);
348 m_xSepText->set_sensitive(!bNone);
349 m_xSepEdit->set_sensitive(!bNone);
350 DrawSample();
353 IMPL_LINK_NOARG(SwCaptionDialog, ModifyEntryHdl, weld::Entry&, void)
355 ModifyHdl();
358 IMPL_LINK_NOARG(SwCaptionDialog, ModifyComboHdl, weld::ComboBox&, void)
360 OUString sText = m_xCategoryBox->get_active_text();
361 OUString sAllowedText = m_aTextFilter.filter(sText);
362 if (sText != sAllowedText)
364 m_xCategoryBox->set_entry_text(sAllowedText);
365 m_xCategoryBox->select_entry_region(sAllowedText.getLength(), sAllowedText.getLength());
367 ModifyHdl();
370 IMPL_LINK_NOARG(SwCaptionDialog, CaptionHdl, weld::Button&, void)
372 SfxItemSet aSet(m_rView.GetDocShell()->GetDoc()->GetAttrPool());
373 SwCaptionOptDlg aDlg(m_xDialog.get(), aSet);
374 aDlg.run();
377 void SwCaptionDialog::DrawSample()
379 OUString aStr;
380 OUString sCaption = m_xTextEdit->get_text();
382 // number
383 OUString sFieldTypeName = m_xCategoryBox->get_active_text();
384 bool bNone = sFieldTypeName == m_sNone;
385 if( !bNone )
387 const sal_uInt16 nNumFormat = m_xFormatBox->get_active_id().toUInt32();
388 if (SVX_NUM_NUMBER_NONE != nNumFormat)
390 // category
391 //#i61007# order of captions
392 if( !m_bOrderNumberingFirst )
394 aStr = sFieldTypeName;
395 if ( !aStr.isEmpty() )
396 aStr += " ";
399 SwWrtShell &rSh = m_rView.GetWrtShell();
400 SwSetExpFieldType* pFieldType = static_cast<SwSetExpFieldType*>(rSh.GetFieldType(
401 SwFieldIds::SetExp, sFieldTypeName ));
402 if( pFieldType && pFieldType->GetOutlineLvl() < MAXLEVEL )
404 SwNumberTree::tNumberVector aNumVector;
405 aNumVector.insert(aNumVector.end(), pFieldType->GetOutlineLvl() + 1, 1);
407 OUString sNumber( rSh.GetOutlineNumRule()->
408 MakeNumString(aNumVector, false ));
409 if( !sNumber.isEmpty() )
410 aStr += sNumber + pFieldType->GetDelimiter();
413 switch( nNumFormat )
415 case SVX_NUM_CHARS_UPPER_LETTER: aStr += "A"; break;
416 case SVX_NUM_CHARS_UPPER_LETTER_N: aStr += "A"; break;
417 case SVX_NUM_CHARS_LOWER_LETTER: aStr += "a"; break;
418 case SVX_NUM_CHARS_LOWER_LETTER_N: aStr += "a"; break;
419 case SVX_NUM_ROMAN_UPPER: aStr += "I"; break;
420 case SVX_NUM_ROMAN_LOWER: aStr += "i"; break;
421 default: aStr += "1"; break;
423 //#i61007# order of captions
424 if( m_bOrderNumberingFirst )
426 aStr += m_xNumberingSeparatorED->get_text() + sFieldTypeName;
430 if( !sCaption.isEmpty() )
432 aStr += m_xSepEdit->get_text();
435 aStr += sCaption;
436 // do preview!
437 m_aPreview.SetPreviewText(aStr);
440 SwCaptionDialog::~SwCaptionDialog()
444 SwSequenceOptionDialog::SwSequenceOptionDialog(weld::Window *pParent, SwView &rV, OUString aSeqFieldType )
445 : GenericDialogController(pParent, u"modules/swriter/ui/captionoptions.ui"_ustr, u"CaptionOptionsDialog"_ustr)
446 , m_rView(rV)
447 , m_aFieldTypeName(std::move(aSeqFieldType))
448 , m_xLbLevel(m_xBuilder->weld_combo_box(u"level"_ustr))
449 , m_xEdDelim(m_xBuilder->weld_entry(u"separator"_ustr))
450 , m_xLbCharStyle(m_xBuilder->weld_combo_box(u"style"_ustr))
451 , m_xApplyBorderAndShadowCB(m_xBuilder->weld_check_button(u"border_and_shadow"_ustr))
452 , m_xLbCaptionOrder(m_xBuilder->weld_combo_box(u"caption_order"_ustr))
454 SwWrtShell &rSh = m_rView.GetWrtShell();
456 const OUString sNone(SwResId(SW_STR_NONE));
458 m_xLbLevel->append_text(sNone);
459 for (sal_uInt16 n = 0; n < MAXLEVEL; ++n)
460 m_xLbLevel->append_text(OUString::number(n + 1));
462 SwSetExpFieldType* pFieldType = static_cast<SwSetExpFieldType*>(rSh.GetFieldType(
463 SwFieldIds::SetExp, m_aFieldTypeName ));
465 sal_Unicode nLvl = MAXLEVEL;
466 OUString sDelim(u": "_ustr);
467 if( pFieldType )
469 sDelim = pFieldType->GetDelimiter();
470 nLvl = pFieldType->GetOutlineLvl();
473 m_xLbLevel->set_active(nLvl < MAXLEVEL ? nLvl + 1 : 0);
474 m_xEdDelim->set_text(sDelim);
476 m_xLbCharStyle->append_text(sNone);
477 ::FillCharStyleListBox(*m_xLbCharStyle, m_rView.GetDocShell(), true, true);
478 m_xLbCharStyle->set_active(0);
481 void SwSequenceOptionDialog::Apply()
483 SwWrtShell &rSh = m_rView.GetWrtShell();
484 SwSetExpFieldType* pFieldType = static_cast<SwSetExpFieldType*>(rSh.GetFieldType(
485 SwFieldIds::SetExp, m_aFieldTypeName ));
487 sal_Int8 nLvl = static_cast<sal_Int8>(m_xLbLevel->get_active() - 1);
488 sal_Unicode cDelim = m_xEdDelim->get_text()[0];
490 bool bUpdate = true;
491 if( pFieldType )
493 pFieldType->SetDelimiter( OUString(cDelim) );
494 pFieldType->SetOutlineLvl( nLvl );
496 else if( !m_aFieldTypeName.isEmpty() && nLvl < MAXLEVEL )
498 // then we have to insert that
499 SwSetExpFieldType aFieldType( rSh.GetDoc(), m_aFieldTypeName, nsSwGetSetExpType::GSE_SEQ );
500 aFieldType.SetDelimiter( OUString(cDelim) );
501 aFieldType.SetOutlineLvl( nLvl );
502 rSh.InsertFieldType( aFieldType );
504 else
505 bUpdate = false;
507 if( bUpdate )
508 rSh.UpdateExpFields();
511 OUString SwSequenceOptionDialog::GetCharacterStyle() const
513 if (m_xLbCharStyle->get_active() != -1)
514 return m_xLbCharStyle->get_active_text();
515 return OUString();
518 void SwSequenceOptionDialog::SetCharacterStyle(const OUString& rStyle)
520 const int nPos = m_xLbCharStyle->find_text(rStyle);
521 if (nPos == -1)
522 m_xLbCharStyle->set_active(0);
523 else
524 m_xLbCharStyle->set_active(nPos);
527 // #i61007# order of captions
528 void SwCaptionDialog::ApplyCaptionOrder()
530 m_xNumberingSeparatorFT->set_sensitive(m_bOrderNumberingFirst);
531 m_xNumberingSeparatorED->set_sensitive(m_bOrderNumberingFirst);
534 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */