1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 .
26 #include <numrule.hxx>
27 #include <poolfmt.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>
44 using namespace ::com::sun::star
;
48 class SwSequenceOptionDialog
: public weld::GenericDialogController
51 OUString m_aFieldTypeName
;
53 std::unique_ptr
<weld::ComboBox
> m_xLbLevel
;
54 std::unique_ptr
<weld::Entry
> m_xEdDelim
;
56 std::unique_ptr
<weld::ComboBox
> m_xLbCharStyle
;
57 std::unique_ptr
<weld::CheckButton
> m_xApplyBorderAndShadowCB
;
59 //#i61007# order of captions
60 std::unique_ptr
<weld::ComboBox
> m_xLbCaptionOrder
;
63 SwSequenceOptionDialog(weld::Window
*pParent
, SwView
&rV
, OUString aSeqFieldType
);
66 bool IsApplyBorderAndShadow() const { return m_xApplyBorderAndShadowCB
->get_active(); }
67 void SetApplyBorderAndShadow( bool bSet
) { m_xApplyBorderAndShadowCB
->set_active(bSet
); }
69 //#i61007# order of captions
70 bool IsOrderNumberingFirst() const { return m_xLbCaptionOrder
->get_active() == 1; }
71 void SetOrderNumberingFirst(bool bSet
) { m_xLbCaptionOrder
->set_active(bSet
? 1 : 0); }
73 void SetCharacterStyle(const OUString
& rStyle
);
74 OUString
GetCharacterStyle() const;
79 OUString
SwCaptionDialog::s_aSepTextSave(": "); // Caption separator text
81 //Resolves: tdf#47427 disallow typing *or* pasting invalid content into the category box
82 OUString
TextFilterAutoConvert::filter(const OUString
&rText
)
84 if (!rText
.isEmpty() && rText
!= m_sNone
&& !SwCalc::IsValidVarName(rText
))
85 return m_sLastGoodText
;
86 m_sLastGoodText
= rText
;
90 SwCaptionDialog::SwCaptionDialog(weld::Window
*pParent
, SwView
&rV
)
91 : SfxDialogController(pParent
, "modules/swriter/ui/insertcaption.ui", "InsertCaptionDialog")
92 , m_sNone(SwResId(SW_STR_NONE
))
93 , m_aTextFilter(m_sNone
)
95 , m_pMgr(new SwFieldMgr(m_rView
.GetWrtShellPtr()))
96 , m_bCopyAttributes(false)
97 , m_bOrderNumberingFirst(SW_MOD()->GetModuleConfig()->IsCaptionOrderNumberingFirst())
98 , m_xTextEdit(m_xBuilder
->weld_entry("caption_edit"))
99 , m_xCategoryBox(m_xBuilder
->weld_combo_box("category"))
100 , m_xFormatText(m_xBuilder
->weld_label("numbering_label"))
101 , m_xFormatBox(m_xBuilder
->weld_combo_box("numbering"))
102 , m_xNumberingSeparatorFT(m_xBuilder
->weld_label("num_separator"))
103 , m_xNumberingSeparatorED(m_xBuilder
->weld_entry("num_separator_edit"))
104 , m_xSepText(m_xBuilder
->weld_label("separator_label"))
105 , m_xSepEdit(m_xBuilder
->weld_entry("separator_edit"))
106 , m_xPosBox(m_xBuilder
->weld_combo_box("position"))
107 , m_xOKButton(m_xBuilder
->weld_button("ok"))
108 , m_xAutoCaptionButton(m_xBuilder
->weld_button("auto"))
109 , m_xOptionButton(m_xBuilder
->weld_button("options"))
110 , m_xPreview(new weld::CustomWeld(*m_xBuilder
, "preview", m_aPreview
))
112 //#i61007# order of captions
114 SwWrtShell
&rSh
= m_rView
.GetWrtShell();
115 uno::Reference
< frame::XModel
> xModel
= m_rView
.GetDocShell()->GetBaseModel();
117 SelectionType eType
= rSh
.GetSelectionType();
118 if ( eType
& SelectionType::Ole
)
120 eType
= SelectionType::Graphic
;
121 uno::Reference
< text::XTextEmbeddedObjectsSupplier
> xObjs(xModel
, uno::UNO_QUERY
);
122 m_xNameAccess
= xObjs
->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());
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;
163 if(!m_xNameAccess
.is())
165 uno::Reference
< text::XTextGraphicObjectsSupplier
> xGraphics(xModel
, uno::UNO_QUERY
);
166 m_xNameAccess
= xGraphics
->getGraphicObjects();
170 else if( eType
& SelectionType::Table
)
172 nPoolId
= RES_POOLCOLL_LABEL_TABLE
;
173 sString
= m_rView
.GetOldTabCat();
174 uno::Reference
< text::XTextTablesSupplier
> xTables(xModel
, uno::UNO_QUERY
);
175 m_xNameAccess
= xTables
->getTextTables();
177 else if( eType
& SelectionType::Frame
)
179 nPoolId
= RES_POOLCOLL_LABEL_FRAME
;
180 sString
= m_rView
.GetOldFrameCat();
181 uno::Reference
< text::XTextFramesSupplier
> xFrames(xModel
, uno::UNO_QUERY
);
182 m_xNameAccess
= xFrames
->getTextFrames();
184 else if( eType
== SelectionType::Text
)
186 nPoolId
= RES_POOLCOLL_LABEL_FRAME
;
187 sString
= m_rView
.GetOldFrameCat();
189 else if( eType
& SelectionType::DrawObject
)
191 nPoolId
= RES_POOLCOLL_LABEL_DRAWING
;
192 sString
= m_rView
.GetOldDrwCat();
196 if (sString
.isEmpty())
197 sString
= SwStyleNameMapper::GetUIName(nPoolId
, OUString());
198 auto nIndex
= m_xCategoryBox
->find_text(sString
);
200 m_xCategoryBox
->set_active(nIndex
);
202 m_xCategoryBox
->set_entry_text(sString
);
206 sal_uInt16 nSelFormat
= SVX_NUM_ARABIC
;
207 nCount
= m_pMgr
->GetFieldTypeCount();
208 for ( size_t i
= nCount
; i
; )
210 SwFieldType
* pFieldType
= m_pMgr
->GetFieldType(SwFieldIds::Unknown
, --i
);
211 if (pFieldType
->GetName() == m_xCategoryBox
->get_active_text())
213 nSelFormat
= o3tl::narrowing
<sal_uInt16
>(static_cast<SwSetExpFieldType
*>(pFieldType
)->GetSeqFormat());
218 sal_uInt16 nFormatCount
= m_pMgr
->GetFormatCount(SwFieldTypesEnum::Sequence
, false);
219 for ( sal_uInt16 i
= 0; i
< nFormatCount
; ++i
)
221 const sal_uInt16 nFormatId
= m_pMgr
->GetFormatId(SwFieldTypesEnum::Sequence
, i
);
222 m_xFormatBox
->append(OUString::number(nFormatId
), m_pMgr
->GetFormatStr(SwFieldTypesEnum::Sequence
, i
));
223 if (nFormatId
== nSelFormat
)
224 m_xFormatBox
->set_active(i
);
228 if (eType
== SelectionType::Graphic
229 || eType
== SelectionType::Table
230 || eType
== (SelectionType::Table
| SelectionType::NumberList
)
231 || eType
== (SelectionType::Table
| SelectionType::Text
)
232 || eType
== (SelectionType::Table
| SelectionType::NumberList
| SelectionType::Text
)
233 || eType
== SelectionType::DrawObject
234 || eType
== (SelectionType::DrawObject
| SelectionType::Ornament
))
236 m_xPosBox
->append_text(SwResId(STR_CAPTION_ABOVE
));
237 m_xPosBox
->append_text(SwResId(STR_CAPTION_BELOW
));
239 else if(eType
== SelectionType::Frame
240 || eType
== SelectionType::Text
)
242 m_xPosBox
->append_text(SwResId(STR_CAPTION_BEGINNING
));
243 m_xPosBox
->append_text(SwResId(STR_CAPTION_END
));
246 if (eType
& SelectionType::Table
)
248 m_xPosBox
->set_active(0);
252 m_xPosBox
->set_active(1);
257 m_xSepEdit
->set_text(s_aSepTextSave
);
258 m_xTextEdit
->grab_focus();
262 IMPL_LINK_NOARG(SwCaptionDialog
, OKHdl
, weld::Button
&, void)
265 m_xDialog
->response(RET_OK
);
268 void SwCaptionDialog::Apply()
271 aOpt
.UseCaption() = true;
272 OUString
aName(m_xCategoryBox
->get_active_text());
273 if ( aName
== m_sNone
)
275 aOpt
.SetCategory( OUString() );
276 aOpt
.SetNumSeparator( OUString() );
280 aOpt
.SetCategory(comphelper::string::strip(aName
, ' '));
281 aOpt
.SetNumSeparator(m_xNumberingSeparatorED
->get_text());
283 aOpt
.SetNumType(m_xFormatBox
->get_active_id().toUInt32());
284 aOpt
.SetSeparator(m_xSepEdit
->get_sensitive() ? m_xSepEdit
->get_text() : OUString());
285 aOpt
.SetCaption(m_xTextEdit
->get_text());
286 aOpt
.SetPos(m_xPosBox
->get_active());
287 aOpt
.IgnoreSeqOpts() = true;
288 aOpt
.CopyAttributes() = m_bCopyAttributes
;
289 aOpt
.SetCharacterStyle( m_sCharacterStyle
);
290 m_rView
.InsertCaption( &aOpt
);
291 s_aSepTextSave
= m_xSepEdit
->get_text();
294 short SwCaptionDialog::run()
296 short nRet
= SfxDialogController::run();
302 IMPL_LINK_NOARG(SwCaptionDialog
, OptionHdl
, weld::Button
&, void)
304 OUString sFieldTypeName
= m_xCategoryBox
->get_active_text();
305 if(sFieldTypeName
== m_sNone
)
306 sFieldTypeName
.clear();
307 auto pDlg
= std::make_shared
<SwSequenceOptionDialog
>(m_xDialog
.get(), m_rView
, sFieldTypeName
);
308 pDlg
->SetApplyBorderAndShadow(m_bCopyAttributes
);
309 pDlg
->SetCharacterStyle( m_sCharacterStyle
);
310 pDlg
->SetOrderNumberingFirst( m_bOrderNumberingFirst
);
312 GenericDialogController::runAsync(pDlg
, [pDlg
, this](sal_Int32 nResult
){
313 if (nResult
== RET_OK
) {
315 m_bCopyAttributes
= pDlg
->IsApplyBorderAndShadow();
316 m_sCharacterStyle
= pDlg
->GetCharacterStyle();
317 //#i61007# order of captions
318 if( m_bOrderNumberingFirst
!= pDlg
->IsOrderNumberingFirst() )
320 m_bOrderNumberingFirst
= pDlg
->IsOrderNumberingFirst();
321 SW_MOD()->GetModuleConfig()->SetCaptionOrderNumberingFirst(m_bOrderNumberingFirst
);
329 IMPL_LINK_NOARG(SwCaptionDialog
, SelectListBoxHdl
, weld::ComboBox
&, void)
334 void SwCaptionDialog::ModifyHdl()
336 SwWrtShell
&rSh
= m_rView
.GetWrtShell();
337 OUString sFieldTypeName
= m_xCategoryBox
->get_active_text();
338 bool bCorrectFieldName
= !sFieldTypeName
.isEmpty();
339 bool bNone
= sFieldTypeName
== m_sNone
;
340 SwFieldType
* pType
= (bCorrectFieldName
&& !bNone
)
341 ? rSh
.GetFieldType( SwFieldIds::SetExp
, sFieldTypeName
)
343 m_xOKButton
->set_sensitive( bCorrectFieldName
&&
345 static_cast<SwSetExpFieldType
*>(pType
)->GetType() == nsSwGetSetExpType::GSE_SEQ
) );
346 m_xOptionButton
->set_sensitive(m_xOKButton
->get_sensitive() && !bNone
);
347 m_xNumberingSeparatorFT
->set_sensitive(m_bOrderNumberingFirst
&& !bNone
);
348 m_xNumberingSeparatorED
->set_sensitive(m_bOrderNumberingFirst
&& !bNone
);
349 m_xFormatText
->set_sensitive(!bNone
);
350 m_xFormatBox
->set_sensitive(!bNone
);
351 m_xSepText
->set_sensitive(!bNone
);
352 m_xSepEdit
->set_sensitive(!bNone
);
356 IMPL_LINK_NOARG(SwCaptionDialog
, ModifyEntryHdl
, weld::Entry
&, void)
361 IMPL_LINK_NOARG(SwCaptionDialog
, ModifyComboHdl
, weld::ComboBox
&, void)
363 OUString sText
= m_xCategoryBox
->get_active_text();
364 OUString sAllowedText
= m_aTextFilter
.filter(sText
);
365 if (sText
!= sAllowedText
)
367 m_xCategoryBox
->set_entry_text(sAllowedText
);
368 m_xCategoryBox
->select_entry_region(sAllowedText
.getLength(), sAllowedText
.getLength());
373 IMPL_LINK_NOARG(SwCaptionDialog
, CaptionHdl
, weld::Button
&, void)
375 SfxItemSet
aSet(m_rView
.GetDocShell()->GetDoc()->GetAttrPool());
376 SwCaptionOptDlg
aDlg(m_xDialog
.get(), aSet
);
380 void SwCaptionDialog::DrawSample()
383 OUString sCaption
= m_xTextEdit
->get_text();
386 OUString sFieldTypeName
= m_xCategoryBox
->get_active_text();
387 bool bNone
= sFieldTypeName
== m_sNone
;
390 const sal_uInt16 nNumFormat
= m_xFormatBox
->get_active_id().toUInt32();
391 if (SVX_NUM_NUMBER_NONE
!= nNumFormat
)
394 //#i61007# order of captions
395 if( !m_bOrderNumberingFirst
)
397 aStr
= sFieldTypeName
;
398 if ( !aStr
.isEmpty() )
402 SwWrtShell
&rSh
= m_rView
.GetWrtShell();
403 SwSetExpFieldType
* pFieldType
= static_cast<SwSetExpFieldType
*>(rSh
.GetFieldType(
404 SwFieldIds::SetExp
, sFieldTypeName
));
405 if( pFieldType
&& pFieldType
->GetOutlineLvl() < MAXLEVEL
)
407 SwNumberTree::tNumberVector aNumVector
;
408 aNumVector
.insert(aNumVector
.end(), pFieldType
->GetOutlineLvl() + 1, 1);
410 OUString
sNumber( rSh
.GetOutlineNumRule()->
411 MakeNumString(aNumVector
, false ));
412 if( !sNumber
.isEmpty() )
413 aStr
+= sNumber
+ pFieldType
->GetDelimiter();
418 case SVX_NUM_CHARS_UPPER_LETTER
: aStr
+= "A"; break;
419 case SVX_NUM_CHARS_UPPER_LETTER_N
: aStr
+= "A"; break;
420 case SVX_NUM_CHARS_LOWER_LETTER
: aStr
+= "a"; break;
421 case SVX_NUM_CHARS_LOWER_LETTER_N
: aStr
+= "a"; break;
422 case SVX_NUM_ROMAN_UPPER
: aStr
+= "I"; break;
423 case SVX_NUM_ROMAN_LOWER
: aStr
+= "i"; break;
424 default: aStr
+= "1"; break;
426 //#i61007# order of captions
427 if( m_bOrderNumberingFirst
)
429 aStr
+= m_xNumberingSeparatorED
->get_text() + sFieldTypeName
;
433 if( !sCaption
.isEmpty() )
435 aStr
+= m_xSepEdit
->get_text();
440 m_aPreview
.SetPreviewText(aStr
);
443 SwCaptionDialog::~SwCaptionDialog()
447 SwSequenceOptionDialog::SwSequenceOptionDialog(weld::Window
*pParent
, SwView
&rV
, OUString aSeqFieldType
)
448 : GenericDialogController(pParent
, "modules/swriter/ui/captionoptions.ui", "CaptionOptionsDialog")
450 , m_aFieldTypeName(std::move(aSeqFieldType
))
451 , m_xLbLevel(m_xBuilder
->weld_combo_box("level"))
452 , m_xEdDelim(m_xBuilder
->weld_entry("separator"))
453 , m_xLbCharStyle(m_xBuilder
->weld_combo_box("style"))
454 , m_xApplyBorderAndShadowCB(m_xBuilder
->weld_check_button("border_and_shadow"))
455 , m_xLbCaptionOrder(m_xBuilder
->weld_combo_box("caption_order"))
457 SwWrtShell
&rSh
= m_rView
.GetWrtShell();
459 const OUString
sNone(SwResId(SW_STR_NONE
));
461 m_xLbLevel
->append_text(sNone
);
462 for (sal_uInt16 n
= 0; n
< MAXLEVEL
; ++n
)
463 m_xLbLevel
->append_text(OUString::number(n
+ 1));
465 SwSetExpFieldType
* pFieldType
= static_cast<SwSetExpFieldType
*>(rSh
.GetFieldType(
466 SwFieldIds::SetExp
, m_aFieldTypeName
));
468 sal_Unicode nLvl
= MAXLEVEL
;
469 OUString
sDelim(": ");
472 sDelim
= pFieldType
->GetDelimiter();
473 nLvl
= pFieldType
->GetOutlineLvl();
476 m_xLbLevel
->set_active(nLvl
< MAXLEVEL
? nLvl
+ 1 : 0);
477 m_xEdDelim
->set_text(sDelim
);
479 m_xLbCharStyle
->append_text(sNone
);
480 ::FillCharStyleListBox(*m_xLbCharStyle
, m_rView
.GetDocShell(), true, true);
481 m_xLbCharStyle
->set_active(0);
484 void SwSequenceOptionDialog::Apply()
486 SwWrtShell
&rSh
= m_rView
.GetWrtShell();
487 SwSetExpFieldType
* pFieldType
= static_cast<SwSetExpFieldType
*>(rSh
.GetFieldType(
488 SwFieldIds::SetExp
, m_aFieldTypeName
));
490 sal_Int8 nLvl
= static_cast<sal_Int8
>(m_xLbLevel
->get_active() - 1);
491 sal_Unicode cDelim
= m_xEdDelim
->get_text()[0];
496 pFieldType
->SetDelimiter( OUString(cDelim
) );
497 pFieldType
->SetOutlineLvl( nLvl
);
499 else if( !m_aFieldTypeName
.isEmpty() && nLvl
< MAXLEVEL
)
501 // then we have to insert that
502 SwSetExpFieldType
aFieldType( rSh
.GetDoc(), m_aFieldTypeName
, nsSwGetSetExpType::GSE_SEQ
);
503 aFieldType
.SetDelimiter( OUString(cDelim
) );
504 aFieldType
.SetOutlineLvl( nLvl
);
505 rSh
.InsertFieldType( aFieldType
);
511 rSh
.UpdateExpFields();
514 OUString
SwSequenceOptionDialog::GetCharacterStyle() const
516 if (m_xLbCharStyle
->get_active() != -1)
517 return m_xLbCharStyle
->get_active_text();
521 void SwSequenceOptionDialog::SetCharacterStyle(const OUString
& rStyle
)
523 const int nPos
= m_xLbCharStyle
->find_text(rStyle
);
525 m_xLbCharStyle
->set_active(0);
527 m_xLbCharStyle
->set_active(nPos
);
530 // #i61007# order of captions
531 void SwCaptionDialog::ApplyCaptionOrder()
533 m_xNumberingSeparatorFT
->set_sensitive(m_bOrderNumberingFirst
);
534 m_xNumberingSeparatorED
->set_sensitive(m_bOrderNumberingFirst
);
537 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */