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 .
20 #include <hintids.hxx>
21 #include <vcl/settings.hxx>
22 #include <vcl/virdev.hxx>
23 #include <sfx2/tabdlg.hxx>
24 #include <editeng/brushitem.hxx>
25 #include <unotools/configmgr.hxx>
26 #include <SwStyleNameMapper.hxx>
32 #include <swmodule.hxx>
34 #include <outline.hxx>
36 #include <poolfmt.hxx>
37 #include <shellres.hxx>
38 #include <svl/style.hxx>
39 #include <charfmt.hxx>
40 #include <docstyle.hxx>
41 #include <viewopt.hxx>
42 #include <outline.hrc>
43 #include <strings.hrc>
45 #include <svtools/colorcfg.hxx>
47 #include <IDocumentOutlineNodes.hxx>
49 using namespace ::com::sun::star
;
53 class SwNumNamesDlg
: public weld::GenericDialogController
55 std::unique_ptr
<weld::Entry
> m_xFormEdit
;
56 std::unique_ptr
<weld::TreeView
> m_xFormBox
;
57 std::unique_ptr
<weld::Button
> m_xOKBtn
;
59 DECL_LINK( ModifyHdl
, weld::Entry
&, void );
60 DECL_LINK( SelectHdl
, weld::TreeView
&, void );
61 DECL_LINK( DoubleClickHdl
, weld::TreeView
&, bool );
64 explicit SwNumNamesDlg(weld::Window
*pParent
);
65 void SetUserNames(const OUString
*pList
[]);
66 OUString
GetName() const { return m_xFormEdit
->get_text(); }
67 int GetCurEntryPos() const { return m_xFormBox
->get_selected_index(); }
72 // remember selected entry
73 IMPL_LINK( SwNumNamesDlg
, SelectHdl
, weld::TreeView
&, rBox
, void )
75 m_xFormEdit
->set_text(rBox
.get_selected_text());
76 m_xFormEdit
->select_region(0, -1);
79 /** set user defined names
81 * @param pList list of user defined names; unknown positions for the user are 0.
83 void SwNumNamesDlg::SetUserNames(const OUString
*pList
[])
85 sal_uInt16 nSelect
= 0;
86 for (sal_uInt16 i
= 0; i
< SwChapterNumRules::nMaxRules
; ++i
)
90 m_xFormBox
->remove(i
);
91 m_xFormBox
->insert_text(i
, *pList
[i
]);
96 m_xFormBox
->select(std::min(nSelect
, o3tl::narrowing
<sal_uInt16
>(m_xFormBox
->n_children() - 1)));
97 SelectHdl(*m_xFormBox
);
100 // unlock OK-Button when text is in Edit
101 IMPL_LINK( SwNumNamesDlg
, ModifyHdl
, weld::Entry
&, rBox
, void )
103 m_xOKBtn
->set_sensitive(!rBox
.get_text().isEmpty());
107 IMPL_LINK_NOARG(SwNumNamesDlg
, DoubleClickHdl
, weld::TreeView
&, bool)
109 m_xDialog
->response(RET_OK
);
113 SwNumNamesDlg::SwNumNamesDlg(weld::Window
*pParent
)
114 : GenericDialogController(pParent
,
115 u
"modules/swriter/ui/numberingnamedialog.ui"_ustr
,
116 u
"NumberingNameDialog"_ustr
)
117 , m_xFormEdit(m_xBuilder
->weld_entry(u
"entry"_ustr
))
118 , m_xFormBox(m_xBuilder
->weld_tree_view(u
"form"_ustr
))
119 , m_xOKBtn(m_xBuilder
->weld_button(u
"ok"_ustr
))
121 for (auto const& aID
: OUTLINE_STYLE
)
122 m_xFormBox
->append_text(SwResId(aID
));
124 m_xFormEdit
->connect_changed(LINK(this, SwNumNamesDlg
, ModifyHdl
));
125 m_xFormBox
->connect_selection_changed(LINK(this, SwNumNamesDlg
, SelectHdl
));
126 m_xFormBox
->connect_row_activated(LINK(this, SwNumNamesDlg
, DoubleClickHdl
));
127 m_xFormBox
->set_size_request(-1, m_xFormBox
->get_height_rows(9));
130 static sal_uInt16
lcl_BitToLevel(sal_uInt16 nActLevel
)
132 constexpr sal_uInt16 MAXLEVEL_MASK
= USHRT_MAX
>> (sizeof(sal_uInt16
) * CHAR_BIT
- MAXLEVEL
);
133 assert((nActLevel
& MAXLEVEL_MASK
) == nActLevel
);
134 sal_uInt16 nTmp
= nActLevel
& MAXLEVEL_MASK
; // a safety measure
135 sal_uInt16 nTmpLevel
= 0;
136 while( 0 != (nTmp
>>= 1) )
141 sal_uInt16
SwOutlineTabDialog::s_nNumLevel
= 1;
143 SwOutlineTabDialog::SwOutlineTabDialog(weld::Window
* pParent
, const SfxItemSet
* pSwItemSet
,
145 : SfxTabDialogController(pParent
, u
"modules/swriter/ui/outlinenumbering.ui"_ustr
, u
"OutlineNumberingDialog"_ustr
, pSwItemSet
)
147 , m_pChapterNumRules(SwModule::get()->GetChapterNumRules())
148 , m_bModified(m_rWrtSh
.IsModified())
149 , m_xMenuButton(m_xBuilder
->weld_menu_button(u
"format"_ustr
))
151 m_xMenuButton
->connect_toggled(LINK(this, SwOutlineTabDialog
, FormHdl
));
152 m_xMenuButton
->connect_selected(LINK(this, SwOutlineTabDialog
, MenuSelectHdl
));
154 m_xNumRule
.reset(new SwNumRule(*rSh
.GetOutlineNumRule()));
155 GetCancelButton().connect_clicked(LINK(this, SwOutlineTabDialog
, CancelHdl
));
157 if (auto nOutlinePos
= m_rWrtSh
.GetOutlinePos(MAXLEVEL
); nOutlinePos
!= SwOutlineNodes::npos
)
159 int nTmp
= m_rWrtSh
.getIDocumentOutlineNodesAccess()->getOutlineLevel(nOutlinePos
);
160 assert(nTmp
< MAXLEVEL
);
161 SetActNumLevel(nTmp
< 0 ? USHRT_MAX
: (1 << nTmp
));
164 AddTabPage(u
"position"_ustr
, &SwNumPositionTabPage::Create
, nullptr);
165 AddTabPage(u
"numbering"_ustr
, &SwOutlineSettingsTabPage::Create
, nullptr);
170 for( i
= 0; i
< MAXLEVEL
; ++i
)
172 // if the style wasn't created yet, it's still at this position
173 if( !m_rWrtSh
.GetParaStyle( sHeadline
=
174 SwStyleNameMapper::GetUIName( static_cast< sal_uInt16
>(RES_POOLCOLL_HEADLINE1
+ i
),
176 m_aCollNames
[i
] = sHeadline
;
179 // query the text templates' outlining levels
180 const sal_uInt16 nCount
= m_rWrtSh
.GetTextFormatCollCount();
181 for(i
= 0; i
< nCount
; ++i
)
183 SwTextFormatColl
&rTextColl
= m_rWrtSh
.GetTextFormatColl(i
);
184 if(!rTextColl
.IsDefault())
186 if(rTextColl
.IsAssignedToListLevelOfOutlineStyle())
188 int nOutLevel
= rTextColl
.GetAssignedOutlineStyleLevel();
189 m_aCollNames
[ nOutLevel
] = rTextColl
.GetName();
195 SwOutlineTabDialog::~SwOutlineTabDialog()
199 void SwOutlineTabDialog::PageCreated(const OUString
& rPageId
, SfxTabPage
& rPage
)
201 if (rPageId
== "position")
203 static_cast<SwNumPositionTabPage
&>(rPage
).SetWrtShell(&m_rWrtSh
);
204 static_cast<SwNumPositionTabPage
&>(rPage
).SetOutlineTabDialog(this);
206 else if (rPageId
== "numbering")
208 static_cast<SwOutlineSettingsTabPage
&>(rPage
).SetWrtShell(&m_rWrtSh
);
212 IMPL_LINK_NOARG(SwOutlineTabDialog
, CancelHdl
, weld::Button
&, void)
215 m_rWrtSh
.ResetModified();
216 m_xDialog
->response(RET_CANCEL
);
219 IMPL_LINK_NOARG(SwOutlineTabDialog
, FormHdl
, weld::Toggleable
&, void)
221 if (!m_xMenuButton
->get_active())
225 for(sal_uInt16 i
= 0; i
< SwChapterNumRules::nMaxRules
; ++i
)
227 const SwNumRulesWithName
*pRules
= m_pChapterNumRules
->GetRules(i
);
230 m_xMenuButton
->set_item_label("form" + OUString::number(i
+ 1), pRules
->GetName());
234 IMPL_LINK(SwOutlineTabDialog
, MenuSelectHdl
, const OUString
&, rIdent
, void)
236 sal_uInt8 nLevelNo
= 0;
238 if (rIdent
== "form1")
240 else if (rIdent
== "form2")
242 else if (rIdent
== "form3")
244 else if (rIdent
== "form4")
246 else if (rIdent
== "form5")
248 else if (rIdent
== "form6")
250 else if (rIdent
== "form7")
252 else if (rIdent
== "form8")
254 else if (rIdent
== "form9")
256 else if (rIdent
== "saveas")
258 SwNumNamesDlg
aDlg(m_xDialog
.get());
259 const OUString
*aStrArr
[SwChapterNumRules::nMaxRules
];
260 for(sal_uInt16 i
= 0; i
< SwChapterNumRules::nMaxRules
; ++i
)
262 const SwNumRulesWithName
*pRules
= m_pChapterNumRules
->GetRules(i
);
264 aStrArr
[i
] = &pRules
->GetName();
266 aStrArr
[i
] = nullptr;
268 aDlg
.SetUserNames(aStrArr
);
269 if (aDlg
.run() == RET_OK
)
271 const OUString
aName(aDlg
.GetName());
272 m_pChapterNumRules
->ApplyNumRules( SwNumRulesWithName(
273 *m_xNumRule
, aName
), aDlg
.GetCurEntryPos() );
274 m_xMenuButton
->set_item_label("form" + OUString::number(aDlg
.GetCurEntryPos() + 1), aName
);
281 const SwNumRulesWithName
*pRules
= m_pChapterNumRules
->GetRules(nLevelNo
- 1);
284 pRules
->ResetNumRule(m_rWrtSh
, *m_xNumRule
);
285 m_xNumRule
->SetRuleType( OUTLINE_RULE
);
286 SfxTabPage
* pOutlinePage
= GetTabPage(u
"numbering");
287 assert(pOutlinePage
);
288 static_cast<SwOutlineSettingsTabPage
*>(pOutlinePage
)->SetNumRule(m_xNumRule
.get());
291 *m_xNumRule
= *m_rWrtSh
.GetOutlineNumRule();
294 SfxTabPage
* pPage
= GetCurTabPage();
295 pPage
->Reset(GetOutputItemSet());
298 sal_uInt16
SwOutlineTabDialog::GetLevel(std::u16string_view rFormatName
) const
300 for(sal_uInt16 i
= 0; i
< MAXLEVEL
; ++i
)
302 if(m_aCollNames
[i
] == rFormatName
)
308 short SwOutlineTabDialog::Ok()
310 SfxTabDialogController::Ok();
311 // set levels for all created templates; has to be done in order to
312 // delete possibly cancelled assignments again.
314 // encapsulate changes into an action to avoid effects on the current cursor
315 // position during the changes.
316 m_rWrtSh
.StartAction();
318 const SwNumRule
* pOutlineRule
= m_rWrtSh
.GetOutlineNumRule();
320 sal_uInt16 i
, nCount
= m_rWrtSh
.GetTextFormatCollCount();
321 for( i
= 0; i
< nCount
; ++i
)
323 SwTextFormatColl
&rTextColl
= m_rWrtSh
.GetTextFormatColl(i
);
324 if( !rTextColl
.IsDefault() )
326 const SfxPoolItem
& rItem
=
327 rTextColl
.GetFormatAttr(RES_PARATR_NUMRULE
, false);
329 if (static_cast<sal_uInt8
>(GetLevel(rTextColl
.GetName())) == MAXLEVEL
)
331 if(rTextColl
.IsAssignedToListLevelOfOutlineStyle())
333 rTextColl
.DeleteAssignmentToListLevelOfOutlineStyle();
335 if (static_cast<const SwNumRuleItem
&>(rItem
).GetValue() ==
336 pOutlineRule
->GetName())
338 rTextColl
.ResetFormatAttr(RES_PARATR_NUMRULE
);
343 rTextColl
.AssignToListLevelOfOutlineStyle(GetLevel(rTextColl
.GetName()));
345 if (static_cast<const SwNumRuleItem
&>(rItem
).GetValue() !=
346 pOutlineRule
->GetName())
348 SwNumRuleItem
aItem(pOutlineRule
->GetName());
349 rTextColl
.SetFormatAttr(aItem
);
355 for(i
= 0; i
< MAXLEVEL
; ++i
)
358 ::SwStyleNameMapper::FillUIName( static_cast< sal_uInt16
>(RES_POOLCOLL_HEADLINE1
+ i
),
360 SwTextFormatColl
* pColl
= m_rWrtSh
.FindTextFormatCollByName( sHeadline
);
361 if( !pColl
&& m_aCollNames
[i
] != sHeadline
)
363 SwTextFormatColl
* pTextColl
= m_rWrtSh
.GetTextCollFromPool(
364 static_cast< sal_uInt16
>(RES_POOLCOLL_HEADLINE1
+ i
) );
365 pTextColl
->DeleteAssignmentToListLevelOfOutlineStyle();
366 pTextColl
->ResetFormatAttr(RES_PARATR_NUMRULE
);
368 if( !m_aCollNames
[i
].isEmpty() )
370 pTextColl
= m_rWrtSh
.GetParaStyle(
371 m_aCollNames
[i
], SwWrtShell::GETSTYLE_CREATESOME
);
374 pTextColl
->AssignToListLevelOfOutlineStyle(i
);
375 SwNumRuleItem
aItem(pOutlineRule
->GetName());
376 pTextColl
->SetFormatAttr(aItem
);
382 m_rWrtSh
.SetOutlineNumRule(*m_xNumRule
);
385 m_rWrtSh
.EndAction();
390 SwOutlineSettingsTabPage::SwOutlineSettingsTabPage(weld::Container
* pPage
, weld::DialogController
* pController
,
391 const SfxItemSet
& rSet
)
392 : SfxTabPage(pPage
, pController
, u
"modules/swriter/ui/outlinenumberingpage.ui"_ustr
, u
"OutlineNumberingPage"_ustr
, &rSet
)
393 , m_aNoFormatName(SwResId(SW_STR_NONE
))
395 , m_pNumRule(nullptr)
396 , m_pCollNames(nullptr)
398 , m_xLevelLB(m_xBuilder
->weld_tree_view(u
"level"_ustr
))
399 , m_xCollBox(m_xBuilder
->weld_combo_box(u
"style"_ustr
))
400 , m_xNumberBox(new SwNumberingTypeListBox(m_xBuilder
->weld_combo_box(u
"numbering"_ustr
)))
401 , m_xCharFormatLB(m_xBuilder
->weld_combo_box(u
"charstyle"_ustr
))
402 , m_xAllLevelFT(m_xBuilder
->weld_label(u
"sublevelsft"_ustr
))
403 , m_xAllLevelNF(m_xBuilder
->weld_spin_button(u
"sublevelsnf"_ustr
))
404 , m_xPrefixED(m_xBuilder
->weld_entry(u
"prefix"_ustr
))
405 , m_xSuffixED(m_xBuilder
->weld_entry(u
"suffix"_ustr
))
406 , m_xStartEdit(m_xBuilder
->weld_spin_button(u
"startat"_ustr
))
407 , m_xPreviewWIN(new weld::CustomWeld(*m_xBuilder
, u
"preview"_ustr
, m_aPreviewWIN
))
409 SetExchangeSupport();
411 m_xNumberBox
->Reload(SwInsertNumTypes::NoNumbering
| SwInsertNumTypes::Extended
);
412 m_xCollBox
->make_sorted();
413 m_xCollBox
->append_text(m_aNoFormatName
);
414 m_xLevelLB
->connect_selection_changed(LINK(this, SwOutlineSettingsTabPage
, LevelHdl
));
415 m_xAllLevelNF
->connect_value_changed(LINK(this, SwOutlineSettingsTabPage
, ToggleComplete
));
416 m_xCollBox
->connect_changed(LINK(this, SwOutlineSettingsTabPage
, CollSelect
));
417 m_xNumberBox
->connect_changed(LINK(this, SwOutlineSettingsTabPage
, NumberSelect
));
418 m_xPrefixED
->connect_changed(LINK(this, SwOutlineSettingsTabPage
, DelimModify
));
419 m_xSuffixED
->connect_changed(LINK(this, SwOutlineSettingsTabPage
, DelimModify
));
420 m_xStartEdit
->connect_value_changed(LINK(this, SwOutlineSettingsTabPage
, StartModified
));
421 m_xCharFormatLB
->make_sorted();
422 m_xCharFormatLB
->connect_changed(LINK(this, SwOutlineSettingsTabPage
, CharFormatHdl
));
425 void SwOutlineSettingsTabPage::Update()
427 // if a template was already selected for this level, select it in the ListBox
428 m_xCollBox
->set_sensitive(USHRT_MAX
!= m_nActLevel
);
429 if(USHRT_MAX
== m_nActLevel
)
431 bool bSamePrefix
= true;
432 bool bSameSuffix
= true;
433 bool bSameType
= true;
434 bool bSameComplete
= true;
435 bool bSameStart
= true;
436 bool bSameCharFormat
= true;
438 const SwNumFormat
* aNumFormatArr
[MAXLEVEL
];
439 const SwCharFormat
* pFirstFormat
= nullptr;
441 for(sal_uInt16 i
= 0; i
< MAXLEVEL
; i
++)
444 aNumFormatArr
[ i
] = &m_pNumRule
->Get(i
);
446 pFirstFormat
= aNumFormatArr
[i
]->GetCharFormat();
449 bSameType
&= aNumFormatArr
[i
]->GetNumberingType() == aNumFormatArr
[0]->GetNumberingType();
450 bSameStart
&= aNumFormatArr
[i
]->GetStart() == aNumFormatArr
[0]->GetStart();
451 bSamePrefix
&= aNumFormatArr
[i
]->GetPrefix() == aNumFormatArr
[0]->GetPrefix();
452 bSameSuffix
&= aNumFormatArr
[i
]->GetSuffix() == aNumFormatArr
[0]->GetSuffix();
453 bSameComplete
&= aNumFormatArr
[i
]->GetIncludeUpperLevels() == aNumFormatArr
[0]->GetIncludeUpperLevels();
454 const SwCharFormat
* pFormat
= aNumFormatArr
[i
]->GetCharFormat();
455 bSameCharFormat
&= (!pFirstFormat
&& !pFormat
)
456 || (pFirstFormat
&& pFormat
&& pFormat
->GetName() == pFirstFormat
->GetName());
459 CheckForStartValue_Impl(aNumFormatArr
[0]->GetNumberingType());
461 m_xNumberBox
->SelectNumberingType( aNumFormatArr
[0]->GetNumberingType() );
463 m_xNumberBox
->SetNoSelection();
465 m_xStartEdit
->set_value(aNumFormatArr
[0]->GetStart());
467 m_xStartEdit
->set_text(OUString());
469 m_xPrefixED
->set_text(aNumFormatArr
[0]->GetPrefix());
471 m_xPrefixED
->set_text(OUString());
473 m_xSuffixED
->set_text(aNumFormatArr
[0]->GetSuffix());
475 m_xSuffixED
->set_text(OUString());
480 m_xCharFormatLB
->set_active_text(pFirstFormat
->GetName());
482 m_xCharFormatLB
->set_active_text(SwViewShell::GetShellRes()->aStrNone
);
485 m_xCharFormatLB
->set_active(-1);
487 m_xAllLevelFT
->set_sensitive(true);
488 m_xAllLevelNF
->set_sensitive(true);
489 m_xAllLevelNF
->set_max(MAXLEVEL
);
492 m_xAllLevelNF
->set_value(aNumFormatArr
[0]->GetIncludeUpperLevels());
496 m_xAllLevelNF
->set_text(OUString());
501 sal_uInt16 nTmpLevel
= lcl_BitToLevel(m_nActLevel
);
502 OUString
aColl(m_pCollNames
[nTmpLevel
]);
504 m_xCollBox
->set_active_text(aColl
);
506 m_xCollBox
->set_active_text(m_aNoFormatName
);
507 const SwNumFormat
&rFormat
= m_pNumRule
->Get(nTmpLevel
);
509 m_xNumberBox
->SelectNumberingType( rFormat
.GetNumberingType() );
510 m_xPrefixED
->set_text(rFormat
.GetPrefix());
511 m_xSuffixED
->set_text(rFormat
.GetSuffix());
512 const SwCharFormat
* pFormat
= rFormat
.GetCharFormat();
514 m_xCharFormatLB
->set_active_text(pFormat
->GetName());
516 m_xCharFormatLB
->set_active_text(SwViewShell::GetShellRes()->aStrNone
);
518 if (nTmpLevel
|| rFormat
.HasListFormat())
520 m_xAllLevelFT
->set_sensitive(true);
521 m_xAllLevelNF
->set_sensitive(true);
522 m_xAllLevelNF
->set_max(nTmpLevel
+ 1);
523 m_xAllLevelNF
->set_min(rFormat
.HasListFormat() ? 0 : 1);
524 m_xAllLevelNF
->set_value(rFormat
.GetIncludeUpperLevels());
528 m_xAllLevelNF
->set_text(OUString());
529 m_xAllLevelNF
->set_sensitive(false);
530 m_xAllLevelFT
->set_sensitive(false);
532 CheckForStartValue_Impl(rFormat
.GetNumberingType());
533 m_xStartEdit
->set_value( rFormat
.GetStart() );
538 IMPL_LINK( SwOutlineSettingsTabPage
, LevelHdl
, weld::TreeView
&, rBox
, void )
540 auto aRows
= rBox
.get_selected_rows();
541 assert(aRows
.empty() || aRows
.size() == 1); // Single selection only
542 if (aRows
.empty() || aRows
[0] == MAXLEVEL
)
544 m_nActLevel
= USHRT_MAX
;
548 m_nActLevel
= 1 << aRows
[0];
553 IMPL_LINK(SwOutlineSettingsTabPage
, ToggleComplete
, weld::SpinButton
&, rEdit
, void)
555 sal_uInt16 nMask
= 1;
556 for(sal_uInt16 i
= 0; i
< MAXLEVEL
; i
++)
558 if(m_nActLevel
& nMask
)
560 SwNumFormat
aNumFormat(m_pNumRule
->Get(i
));
561 aNumFormat
.SetIncludeUpperLevels( std::min( static_cast<sal_uInt8
>(rEdit
.get_value()),
562 static_cast<sal_uInt8
>(i
+ 1)) );
563 // Set the same prefix/suffix to generate list format with changed IncludedUpperLevels
564 aNumFormat
.SetListFormat(aNumFormat
.GetPrefix(), aNumFormat
.GetSuffix(), i
);
565 m_pNumRule
->Set(i
, aNumFormat
);
572 IMPL_LINK( SwOutlineSettingsTabPage
, CollSelect
, weld::ComboBox
&, rBox
, void )
576 const OUString
aCollName(rBox
.get_active_text());
577 //0xFFFF not allowed here (disable)
578 sal_uInt16 nTmpLevel
= lcl_BitToLevel(m_nActLevel
);
579 OUString
sOldName( m_pCollNames
[nTmpLevel
] );
581 for( i
= 0; i
< MAXLEVEL
; ++i
)
582 m_pCollNames
[i
] = m_aSaveCollNames
[i
];
584 m_pCollNames
[nTmpLevel
] = aCollName
;
585 // template already in use?
586 for( i
= 0; i
< MAXLEVEL
; ++i
)
587 if(i
!= nTmpLevel
&& m_pCollNames
[i
] == aCollName
)
588 m_pCollNames
[i
].clear();
590 // search the oldname and put it into the current entries
591 if( !sOldName
.isEmpty() )
592 for( i
= 0; i
< MAXLEVEL
; ++i
)
593 if( m_aSaveCollNames
[ i
] == sOldName
&& i
!= nTmpLevel
&&
594 m_pCollNames
[ i
].isEmpty() )
597 for( n
= 0; n
< MAXLEVEL
; ++n
)
598 if( m_pCollNames
[ n
] == sOldName
)
602 // it was an outline level name and the current entries is zero.
603 m_pCollNames
[ i
] = sOldName
;
610 void SwOutlineSettingsTabPage::CollSave()
612 for (sal_uInt8 i
= 0; i
< MAXLEVEL
; ++i
)
613 m_aSaveCollNames
[i
] = m_pCollNames
[i
];
616 IMPL_LINK_NOARG(SwOutlineSettingsTabPage
, NumberSelect
, weld::ComboBox
&, void)
618 sal_uInt16 nMask
= 1;
619 SvxNumType nNumberType
= m_xNumberBox
->GetSelectedNumberingType();
620 for(sal_uInt16 i
= 0; i
< MAXLEVEL
; i
++)
622 if(m_nActLevel
& nMask
)
624 SwNumFormat
aNumFormat(m_pNumRule
->Get(i
));
625 aNumFormat
.SetNumberingType(nNumberType
);
626 // ensure that HasListFormat
627 aNumFormat
.SetListFormat(aNumFormat
.GetPrefix(), aNumFormat
.GetSuffix(), i
);
628 m_pNumRule
->Set(i
, aNumFormat
);
629 CheckForStartValue_Impl(nNumberType
);
636 IMPL_LINK_NOARG(SwOutlineSettingsTabPage
, DelimModify
, weld::Entry
&, void)
638 sal_uInt16 nMask
= 1;
639 for(sal_uInt16 i
= 0; i
< MAXLEVEL
; i
++)
641 if(m_nActLevel
& nMask
)
643 SwNumFormat
aNumFormat(m_pNumRule
->Get(i
));
644 aNumFormat
.SetListFormat( m_xPrefixED
->get_text(), m_xSuffixED
->get_text(), i
);
645 m_pNumRule
->Set(i
, aNumFormat
);
652 IMPL_LINK( SwOutlineSettingsTabPage
, StartModified
, weld::SpinButton
&, rEdit
, void )
654 sal_uInt16 nMask
= 1;
655 for(sal_uInt16 i
= 0; i
< MAXLEVEL
; i
++)
657 if(m_nActLevel
& nMask
)
659 SwNumFormat
aNumFormat(m_pNumRule
->Get(i
));
660 aNumFormat
.SetStart(o3tl::narrowing
<sal_uInt16
>(rEdit
.get_value()));
661 m_pNumRule
->Set(i
, aNumFormat
);
668 IMPL_LINK_NOARG(SwOutlineSettingsTabPage
, CharFormatHdl
, weld::ComboBox
&, void)
670 OUString sEntry
= m_xCharFormatLB
->get_active_text();
671 sal_uInt16 nMask
= 1;
672 bool bFormatNone
= sEntry
== SwViewShell::GetShellRes()->aStrNone
;
673 SwCharFormat
* pFormat
= nullptr;
676 sal_uInt16 nChCount
= m_pSh
->GetCharFormatCount();
677 for(sal_uInt16 i
= 0; i
< nChCount
; i
++)
679 SwCharFormat
& rChFormat
= m_pSh
->GetCharFormat(i
);
680 if(rChFormat
.GetName() == sEntry
)
682 pFormat
= &rChFormat
;
688 SfxStyleSheetBasePool
* pPool
= m_pSh
->GetView().GetDocShell()->GetStyleSheetPool();
689 SfxStyleSheetBase
* pBase
;
690 pBase
= pPool
->Find(sEntry
, SfxStyleFamily::Char
);
692 pBase
= &pPool
->Make(sEntry
, SfxStyleFamily::Page
);
693 pFormat
= static_cast<SwDocStyleSheet
*>(pBase
)->GetCharFormat();
698 for(sal_uInt16 i
= 0; i
< MAXLEVEL
; i
++)
700 if(m_nActLevel
& nMask
)
702 SwNumFormat
aNumFormat(m_pNumRule
->Get(i
));
704 aNumFormat
.SetCharFormat(nullptr);
706 aNumFormat
.SetCharFormat(pFormat
);
707 m_pNumRule
->Set(i
, aNumFormat
);
713 SwOutlineSettingsTabPage::~SwOutlineSettingsTabPage()
717 void SwOutlineSettingsTabPage::SetWrtShell(SwWrtShell
* pShell
)
720 // query this document's NumRules
721 m_pNumRule
= static_cast<SwOutlineTabDialog
*>(GetDialogController())->GetNumRule();
722 m_pCollNames
= static_cast<SwOutlineTabDialog
*>(GetDialogController())->GetCollNames();
726 m_aPreviewWIN
.SetNumRule(m_pNumRule
);
727 m_aPreviewWIN
.SetOutlineNames(m_pCollNames
);
728 // set start value - nActLevel must be 1 here
729 sal_uInt16 nTmpLevel
= lcl_BitToLevel(m_nActLevel
);
730 const SwNumFormat
& rNumFormat
= m_pNumRule
->Get( nTmpLevel
);
731 m_xStartEdit
->set_value( rNumFormat
.GetStart() );
733 // create pool formats for headlines
734 for (sal_uInt16 i
= 0; i
< MAXLEVEL
; ++i
)
736 m_xCollBox
->append_text( SwStyleNameMapper::GetUIName(
737 static_cast< sal_uInt16
>(RES_POOLCOLL_HEADLINE1
+ i
), OUString()));
738 m_xLevelLB
->append_text( OUString::number(i
+ 1) );
740 OUString sStr
= "1 - " + OUString::number(MAXLEVEL
);
741 m_xLevelLB
->append_text(sStr
);
743 // query the texttemplates' outlining levels
744 const sal_uInt16 nCount
= m_pSh
->GetTextFormatCollCount();
745 for (sal_uInt16 i
= 0; i
< nCount
; ++i
)
747 SwTextFormatColl
&rTextColl
= m_pSh
->GetTextFormatColl(i
);
748 if(!rTextColl
.IsDefault())
750 sStr
= rTextColl
.GetName();
751 if (m_xCollBox
->find_text(sStr
) == -1)
752 m_xCollBox
->append_text(sStr
);
756 m_xNumberBox
->SelectNumberingType(rNumFormat
.GetNumberingType());
758 // collect char styles
759 m_xCharFormatLB
->clear();
760 m_xCharFormatLB
->append_text(SwViewShell::GetShellRes()->aStrNone
);
763 ::FillCharStyleListBox(*m_xCharFormatLB
,
764 m_pSh
->GetView().GetDocShell());
768 void SwOutlineSettingsTabPage::ActivatePage(const SfxItemSet
& )
770 m_nActLevel
= SwOutlineTabDialog::GetActNumLevel();
771 if(m_nActLevel
!= USHRT_MAX
)
772 m_xLevelLB
->select(lcl_BitToLevel(m_nActLevel
));
774 m_xLevelLB
->select(MAXLEVEL
);
775 LevelHdl(*m_xLevelLB
);
778 DeactivateRC
SwOutlineSettingsTabPage::DeactivatePage(SfxItemSet
*)
780 SwOutlineTabDialog::SetActNumLevel(m_nActLevel
);
781 return DeactivateRC::LeavePage
;
784 bool SwOutlineSettingsTabPage::FillItemSet( SfxItemSet
* )
789 void SwOutlineSettingsTabPage::Reset( const SfxItemSet
* rSet
)
794 std::unique_ptr
<SfxTabPage
> SwOutlineSettingsTabPage::Create(weld::Container
* pPage
, weld::DialogController
* pController
,
795 const SfxItemSet
* rAttrSet
)
797 return std::make_unique
<SwOutlineSettingsTabPage
>(pPage
, pController
, *rAttrSet
);
800 void SwOutlineSettingsTabPage::CheckForStartValue_Impl(sal_uInt16 nNumberingType
)
802 bool bIsNull
= m_xStartEdit
->get_value() == 0;
803 bool bNoZeroAllowed
= nNumberingType
< SVX_NUM_ARABIC
||
804 SVX_NUM_CHARS_UPPER_LETTER_N
== nNumberingType
||
805 SVX_NUM_CHARS_LOWER_LETTER_N
== nNumberingType
;
806 m_xStartEdit
->set_min(bNoZeroAllowed
? 1 : 0);
807 if (bIsNull
&& bNoZeroAllowed
)
808 StartModified(*m_xStartEdit
);
811 static tools::Long
lcl_DrawBullet(vcl::RenderContext
* pVDev
, const SwNumFormat
& rFormat
, tools::Long nXStart
, tools::Long nYStart
, const Size
& rSize
)
813 vcl::Font
aTmpFont(pVDev
->GetFont());
815 // via Uno it's possible that no font has been set!
816 vcl::Font
aFont(rFormat
.GetBulletFont() ? *rFormat
.GetBulletFont() : aTmpFont
);
817 Size
aTmpSize(rSize
);
818 aTmpSize
.setWidth( aTmpSize
.Width() * ( rFormat
.GetBulletRelSize()) );
819 aTmpSize
.setWidth( aTmpSize
.Width() / 100 ) ;
820 aTmpSize
.setHeight( aTmpSize
.Height() * ( rFormat
.GetBulletRelSize()) );
821 aTmpSize
.setHeight( aTmpSize
.Height() / 100 ) ;
822 // in case of a height of zero it is drawn in original height
823 if(!aTmpSize
.Height())
824 aTmpSize
.setHeight( 1 );
825 aFont
.SetFontSize(aTmpSize
);
826 aFont
.SetTransparent(true);
827 Color aBulletColor
= rFormat
.GetBulletColor();
828 if(aBulletColor
== COL_AUTO
)
829 aBulletColor
= pVDev
->GetFillColor().IsDark() ? COL_WHITE
: COL_BLACK
;
830 else if(aBulletColor
== pVDev
->GetFillColor())
831 aBulletColor
.Invert();
832 aFont
.SetColor(aBulletColor
);
833 pVDev
->SetFont( aFont
);
834 sal_UCS4 cBullet
= rFormat
.GetBulletChar();
835 OUString
aText(&cBullet
, 1);
836 tools::Long nY
= nYStart
;
837 nY
-= ((aTmpSize
.Height() - rSize
.Height())/ 2);
838 pVDev
->DrawText( Point(nXStart
, nY
), aText
);
839 tools::Long nRet
= pVDev
->GetTextWidth(aText
);
841 pVDev
->SetFont(aTmpFont
);
845 static tools::Long
lcl_DrawGraphic(vcl::RenderContext
& rVDev
, const SwNumFormat
&rFormat
, tools::Long nXStart
, tools::Long nYStart
, tools::Long nDivision
)
847 const SvxBrushItem
* pBrushItem
= rFormat
.GetBrush();
848 tools::Long nRet
= 0;
851 const Graphic
* pGraphic
= pBrushItem
->GetGraphic();
854 Size
aGSize( rFormat
.GetGraphicSize());
855 aGSize
.setWidth( aGSize
.Width() / nDivision
);
856 nRet
= aGSize
.Width();
857 aGSize
.setHeight( aGSize
.Height() / nDivision
);
858 pGraphic
->Draw(rVDev
, Point(nXStart
, nYStart
), rVDev
.PixelToLogic(aGSize
));
864 void NumberingPreview::Paint(vcl::RenderContext
& rRenderContext
, const tools::Rectangle
&)
866 const Size
aSize(rRenderContext
.PixelToLogic(GetOutputSizePixel()));
868 ScopedVclPtrInstance
<VirtualDevice
> pVDev(rRenderContext
);
869 pVDev
->SetMapMode(rRenderContext
.GetMapMode());
870 pVDev
->SetOutputSize(aSize
);
872 const SwViewOption
& pOpt
= SwViewOption::GetCurrentViewOptions();
873 const Color
& rDocColor
= pOpt
.GetDocColor();
874 const Color
& rDocBoundariesColor
= pOpt
.GetDocBoundariesColor();
875 const Color
& rFontColor
= pOpt
.GetFontColor();
877 pVDev
->SetFillColor(rDocColor
);
878 pVDev
->SetLineColor(rDocBoundariesColor
);
879 pVDev
->DrawRect(tools::Rectangle(Point(0,0), aSize
));
883 tools::Long nWidthRelation
= 30; // chapter dialog
886 nWidthRelation
= m_nPageWidth
/ aSize
.Width();
888 nWidthRelation
= nWidthRelation
* 2 / 3;
890 nWidthRelation
= nWidthRelation
/ 4;
894 const tools::Long nXStep
= aSize
.Width() / (3 * MAXLEVEL
* ((MAXLEVEL
< 10) ? 2 : 1));
895 const tools::Long nYStep
= (aSize
.Height() - 6)/ MAXLEVEL
;
896 tools::Long nYStart
= 4;
897 m_aStdFont
= OutputDevice::GetDefaultFont(DefaultFontType::UI_SANS
, GetAppLanguage(),
898 GetDefaultFontFlags::OnlyOne
, &rRenderContext
);
900 if (svtools::ColorConfig().GetColorValue(svtools::FONTCOLOR
, false).nColor
== COL_AUTO
)
901 m_aStdFont
.SetColor( rDocColor
.IsDark() ? COL_WHITE
: COL_BLACK
);
903 m_aStdFont
.SetColor( rFontColor
);
905 const tools::Long nFontHeight
= nYStep
* ( m_bPosition
? 15 : 6 ) / 10;
906 m_aStdFont
.SetFontSize(Size( 0, nFontHeight
));
908 tools::Long nPreNum
= m_pActNum
->Get(0).GetStart();
912 const tools::Long nLineHeight
= nFontHeight
* 8 / 7;
913 sal_uInt8 nStart
= 0;
914 while (!(m_nActLevel
& (1 << nStart
)))
918 if(nStart
) // so that possible predecessors and successors are showed
921 SwNumberTree::tNumberVector aNumVector
;
922 sal_uInt8 nEnd
= std::min(sal_uInt8(nStart
+ 3), MAXLEVEL
);
923 for (sal_uInt8 nLevel
= nStart
; nLevel
< nEnd
; ++nLevel
)
925 const SwNumFormat
&rFormat
= m_pActNum
->Get(nLevel
);
926 aNumVector
.push_back(rFormat
.GetStart());
928 tools::Long
nXStart( 0 );
929 tools::Long
nTextOffset( 0 );
930 tools::Long
nNumberXPos( 0 );
931 if (rFormat
.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION
)
933 nXStart
= rFormat
.GetAbsLSpace() / nWidthRelation
;
934 nTextOffset
= rFormat
.GetCharTextDistance() / nWidthRelation
;
935 nNumberXPos
= nXStart
;
936 const tools::Long nFirstLineOffset
= (-rFormat
.GetFirstLineOffset()) / nWidthRelation
;
938 if(nFirstLineOffset
<= nNumberXPos
)
939 nNumberXPos
-= nFirstLineOffset
;
943 else if (rFormat
.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT
)
945 const tools::Long
nTmpNumberXPos((rFormat
.GetIndentAt() + rFormat
.GetFirstLineIndent()) / nWidthRelation
);
946 nNumberXPos
= (nTmpNumberXPos
< 0) ? 0 : nTmpNumberXPos
;
949 tools::Long nBulletWidth
= 0;
950 if (SVX_NUM_BITMAP
== rFormat
.GetNumberingType())
952 nBulletWidth
= lcl_DrawGraphic(*pVDev
, rFormat
, nNumberXPos
,
953 nYStart
, nWidthRelation
);
955 else if (SVX_NUM_CHAR_SPECIAL
== rFormat
.GetNumberingType())
957 nBulletWidth
= lcl_DrawBullet(pVDev
.get(), rFormat
, nNumberXPos
,
958 nYStart
, m_aStdFont
.GetFontSize());
962 pVDev
->SetFont(m_aStdFont
);
963 if(m_pActNum
->IsContinusNum())
964 aNumVector
[nLevel
] = nPreNum
;
965 OUString
aText(m_pActNum
->MakeNumString( aNumVector
));
966 pVDev
->DrawText( Point(nNumberXPos
, nYStart
), aText
);
967 nBulletWidth
= pVDev
->GetTextWidth(aText
);
970 if ( rFormat
.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT
&&
971 rFormat
.GetLabelFollowedBy() == SvxNumberFormat::SPACE
)
973 pVDev
->SetFont(m_aStdFont
);
975 pVDev
->DrawText( Point(nNumberXPos
, nYStart
), aText
);
976 nBulletWidth
+= pVDev
->GetTextWidth(aText
);
979 tools::Long
nTextXPos(0);
980 if (rFormat
.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION
)
984 nTextXPos
= nTextXPos
+ nTextOffset
;
985 if (nNumberXPos
+ nBulletWidth
+ nTextOffset
> nTextXPos
)
986 nTextXPos
= nNumberXPos
+ nBulletWidth
+ nTextOffset
;
988 else if (rFormat
.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT
)
990 switch (rFormat
.GetLabelFollowedBy())
992 case SvxNumberFormat::LISTTAB
:
994 nTextXPos
= rFormat
.GetListtabPos() / nWidthRelation
;
995 if (nTextXPos
< nNumberXPos
+ nBulletWidth
)
997 nTextXPos
= nNumberXPos
+ nBulletWidth
;
1001 case SvxNumberFormat::SPACE
:
1002 case SvxNumberFormat::NOTHING
:
1003 case SvxNumberFormat::NEWLINE
:
1005 nTextXPos
= nNumberXPos
+ nBulletWidth
;
1010 nXStart
= rFormat
.GetIndentAt() / nWidthRelation
;
1013 tools::Rectangle
aRect1(Point(nTextXPos
, nYStart
+ nFontHeight
/ 2), Size(aSize
.Width() / 2, 2));
1014 pVDev
->SetFillColor(rRenderContext
.GetSettings().GetStyleSettings().GetWindowColor()); // COL_BLACK );
1015 pVDev
->DrawRect(aRect1
);
1017 tools::Rectangle
aRect2(Point(nXStart
, nYStart
+ nLineHeight
+ nFontHeight
/ 2), Size(aSize
.Width() / 2, 2));
1018 pVDev
->DrawRect(aRect2
);
1019 nYStart
+= 2 * nLineHeight
;
1024 SwNumberTree::tNumberVector aNumVector
;
1025 const tools::Long nLineHeight
= nFontHeight
* 3 / 2;
1026 for (sal_uInt8 nLevel
= 0; nLevel
< MAXLEVEL
; ++nLevel
, nYStart
= nYStart
+ nYStep
)
1028 const SwNumFormat
&rFormat
= m_pActNum
->Get(nLevel
);
1029 aNumVector
.push_back(rFormat
.GetStart());
1030 tools::Long
nXStart(0);
1031 if (rFormat
.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION
)
1033 nXStart
= rFormat
.GetAbsLSpace() / nWidthRelation
;
1035 else if (rFormat
.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT
)
1037 const tools::Long
nTmpXStart((rFormat
.GetIndentAt() + rFormat
.GetFirstLineIndent() ) / nWidthRelation
);
1038 nXStart
= (nTmpXStart
< 0) ? 0 : nTmpXStart
;
1042 tools::Long nTextOffset
;
1043 if (SVX_NUM_BITMAP
== rFormat
.GetNumberingType())
1045 lcl_DrawGraphic(*pVDev
, rFormat
, nXStart
, nYStart
, nWidthRelation
);
1046 nTextOffset
= nLineHeight
+ nXStep
;
1048 else if (SVX_NUM_CHAR_SPECIAL
== rFormat
.GetNumberingType())
1050 nTextOffset
= lcl_DrawBullet(pVDev
.get(), rFormat
, nXStart
, nYStart
, m_aStdFont
.GetFontSize());
1051 nTextOffset
+= nXStep
;
1055 pVDev
->SetFont(m_aStdFont
);
1056 if (m_pActNum
->IsContinusNum())
1057 aNumVector
[nLevel
] = nPreNum
;
1058 OUString
aText(m_pActNum
->MakeNumString( aNumVector
));
1059 pVDev
->DrawText( Point(nXStart
, nYStart
), aText
);
1060 nTextOffset
= pVDev
->GetTextWidth(aText
) + nXStep
;
1063 pVDev
->SetFont(m_aStdFont
);
1065 Point(nXStart
+ nTextOffset
, nYStart
),
1066 (m_pOutlineNames
== nullptr
1067 ? utl::ConfigManager::getProductName()
1068 : m_pOutlineNames
[nLevel
]));
1072 rRenderContext
.DrawOutDev(Point(0,0), aSize
, Point(0,0), aSize
, *pVDev
);
1075 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */