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>
43 #include <unotxdoc.hxx>
45 using namespace ::com::sun::star
;
49 class SwSequenceOptionDialog
: public weld::GenericDialogController
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
;
64 SwSequenceOptionDialog(weld::Window
*pParent
, SwView
&rV
, OUString aSeqFieldType
);
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
;
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
)
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
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());
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 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();
193 if (sString
.isEmpty())
194 sString
= SwStyleNameMapper::GetUIName(nPoolId
, OUString());
195 auto nIndex
= m_xCategoryBox
->find_text(sString
);
197 m_xCategoryBox
->set_active(nIndex
);
199 m_xCategoryBox
->set_entry_text(sString
);
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());
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
);
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);
249 m_xPosBox
->set_active(1);
254 m_xSepEdit
->set_text(s_aSepTextSave
);
255 m_xTextEdit
->grab_focus();
259 IMPL_LINK_NOARG(SwCaptionDialog
, OKHdl
, weld::Button
&, void)
262 m_xDialog
->response(RET_OK
);
265 void SwCaptionDialog::Apply()
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() );
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();
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
) {
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
);
326 IMPL_LINK_NOARG(SwCaptionDialog
, SelectListBoxHdl
, weld::ComboBox
&, void)
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
)
340 m_xOKButton
->set_sensitive( bCorrectFieldName
&&
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
);
353 IMPL_LINK_NOARG(SwCaptionDialog
, ModifyEntryHdl
, weld::Entry
&, void)
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());
370 IMPL_LINK_NOARG(SwCaptionDialog
, CaptionHdl
, weld::Button
&, void)
372 SfxItemSet
aSet(m_rView
.GetDocShell()->GetDoc()->GetAttrPool());
373 SwCaptionOptDlg
aDlg(m_xDialog
.get(), aSet
);
377 void SwCaptionDialog::DrawSample()
380 OUString sCaption
= m_xTextEdit
->get_text();
383 OUString sFieldTypeName
= m_xCategoryBox
->get_active_text();
384 bool bNone
= sFieldTypeName
== m_sNone
;
387 const sal_uInt16 nNumFormat
= m_xFormatBox
->get_active_id().toUInt32();
388 if (SVX_NUM_NUMBER_NONE
!= nNumFormat
)
391 //#i61007# order of captions
392 if( !m_bOrderNumberingFirst
)
394 aStr
= sFieldTypeName
;
395 if ( !aStr
.isEmpty() )
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();
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();
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
)
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
);
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];
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
);
508 rSh
.UpdateExpFields();
511 OUString
SwSequenceOptionDialog::GetCharacterStyle() const
513 if (m_xLbCharStyle
->get_active() != -1)
514 return m_xLbCharStyle
->get_active_text();
518 void SwSequenceOptionDialog::SetCharacterStyle(const OUString
& rStyle
)
520 const int nPos
= m_xLbCharStyle
->find_text(rStyle
);
522 m_xLbCharStyle
->set_active(0);
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: */