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/.
11 #include <swmodule.hxx>
13 #include <poolfmt.hxx>
16 #include <titlepage.hxx>
17 #include <fmtpdsc.hxx>
18 #include <pagedesc.hxx>
22 bool lcl_GetPageDesc(SwWrtShell
& rSh
, sal_uInt16
&rPageNo
, std::unique_ptr
<const SwFormatPageDesc
>* ppPageFormatDesc
)
25 SfxItemSetFixed
<RES_PAGEDESC
, RES_PAGEDESC
> aSet(rSh
.GetAttrPool());
26 if (rSh
.GetCurAttr(aSet
))
28 if (const SwFormatPageDesc
* pDescItem
= aSet
.GetItemIfSet( RES_PAGEDESC
))
30 ::std::optional
<sal_uInt16
> oNumOffset
= pDescItem
->GetNumOffset();
32 rPageNo
= *oNumOffset
;
34 ppPageFormatDesc
->reset(static_cast<const SwFormatPageDesc
*>(pDescItem
->Clone()));
41 void lcl_ChangePage(SwWrtShell
& rSh
, sal_uInt16 nNewNumber
, const SwPageDesc
*pNewDesc
)
43 const size_t nCurIdx
= rSh
.GetCurPageDesc();
44 const SwPageDesc
&rCurrentDesc
= rSh
.GetPageDesc(nCurIdx
);
46 std::unique_ptr
<const SwFormatPageDesc
> pPageFormatDesc
;
48 lcl_GetPageDesc(rSh
, nDontCare
, &pPageFormatDesc
);
50 // If we want a new number then set it, otherwise reuse the existing one
54 // -1: Allow special case to prevent inheriting re-numbering from the existing page.
55 nPgNo
= nNewNumber
== SAL_MAX_UINT16
? 0 : nNewNumber
;
57 else if (pPageFormatDesc
)
59 ::std::optional
<sal_uInt16
> oNumOffset
= pPageFormatDesc
->GetNumOffset();
64 // If we want a new descriptor then set it, otherwise reuse the existing one
65 if (pNewDesc
|| nPgNo
)
67 SwFormatPageDesc
aPageFormatDesc(pNewDesc
? pNewDesc
: &rCurrentDesc
);
68 if (nPgNo
) aPageFormatDesc
.SetNumOffset(nPgNo
);
69 rSh
.SetAttrItem(aPageFormatDesc
);
73 void lcl_PushCursor(SwWrtShell
& rSh
)
77 rSh
.SwCursorShell::Push();
80 void lcl_PopCursor(SwWrtShell
& rSh
)
82 rSh
.SwCursorShell::Pop(SwCursorShell::PopMode::DeleteCurrent
);
87 sal_uInt16
lcl_GetCurrentPage(const SwWrtShell
& rSh
)
90 sal_uInt16 nPhyNum
=1, nVirtNum
=1;
91 rSh
.GetPageNumber(0, true, nPhyNum
, nVirtNum
, sDummy
);
95 bool lcl_GotoPage(SwWrtShell
& rSh
, const sal_uInt16 nStartingPage
, sal_uInt16 nOffset
= 0)
97 rSh
.GotoPage(nStartingPage
, /*bRecord=*/false);
99 sal_uInt16 nCurrentPage
= lcl_GetCurrentPage(rSh
);
100 // return false if at document end (unless that was the requested destination)
101 if (nCurrentPage
== rSh
.GetPageCnt())
102 return nCurrentPage
== nStartingPage
+ nOffset
;
104 if (nCurrentPage
!= nStartingPage
)
106 assert(nStartingPage
!= 1 && "Physical page 1 couldn't be found/moved to?");
107 // Probably there is an auto-inserted blank page to handle odd/even, which Goto doesn't understand.
108 rSh
.GotoPage(nStartingPage
+ 1, /*bRecord=*/false);
110 nCurrentPage
= lcl_GetCurrentPage(rSh
);
111 assert(nCurrentPage
== nStartingPage
+ 1 && "Impossible, since unknown goes to last page");
112 if (nCurrentPage
!= nStartingPage
+ 1)
115 // Now that we have the correct starting point, move to the correct offset.
123 * Only include the Index page in the list if the page count implies one
124 * to reduce confusing things
126 void SwTitlePageDlg::FillList()
128 sal_uInt16 nTitlePages
= m_xPageCountNF
->get_value();
129 m_xPagePropertiesLB
->clear();
131 m_xPagePropertiesLB
->append_text(mpTitleDesc
->GetName());
132 if (nTitlePages
> 1 && mpIndexDesc
)
133 m_xPagePropertiesLB
->append_text(mpIndexDesc
->GetName());
135 m_xPagePropertiesLB
->append_text(mpNormalDesc
->GetName());
136 m_xPagePropertiesLB
->set_active(0);
139 sal_uInt16
SwTitlePageDlg::GetInsertPosition() const
141 sal_uInt16 nPage
= 1;
142 if (m_xPageStartNF
->get_sensitive())
143 nPage
= m_xPageStartNF
->get_value();
147 SwTitlePageDlg::SwTitlePageDlg(weld::Window
*pParent
)
148 : SfxDialogController(pParent
, "modules/swriter/ui/titlepage.ui", "DLG_TITLEPAGE")
149 , mpTitleDesc(nullptr)
150 , mpIndexDesc(nullptr)
151 , mpNormalDesc(nullptr)
152 , m_xUseExistingPagesRB(m_xBuilder
->weld_radio_button("RB_USE_EXISTING_PAGES"))
153 , m_xPageCountNF(m_xBuilder
->weld_spin_button("NF_PAGE_COUNT"))
154 , m_xDocumentStartRB(m_xBuilder
->weld_radio_button("RB_DOCUMENT_START"))
155 , m_xPageStartRB(m_xBuilder
->weld_radio_button("RB_PAGE_START"))
156 , m_xPageStartNF(m_xBuilder
->weld_spin_button("NF_PAGE_START"))
157 , m_xRestartNumberingCB(m_xBuilder
->weld_check_button("CB_RESTART_NUMBERING"))
158 , m_xRestartNumberingNF(m_xBuilder
->weld_spin_button("NF_RESTART_NUMBERING"))
159 , m_xSetPageNumberCB(m_xBuilder
->weld_check_button("CB_SET_PAGE_NUMBER"))
160 , m_xSetPageNumberNF(m_xBuilder
->weld_spin_button("NF_SET_PAGE_NUMBER"))
161 , m_xPagePropertiesLB(m_xBuilder
->weld_combo_box("LB_PAGE_PROPERTIES"))
162 , m_xPagePropertiesPB(m_xBuilder
->weld_button("PB_PAGE_PROPERTIES"))
163 , m_xOkPB(m_xBuilder
->weld_button("ok"))
165 SwView
* pView
= GetActiveView();
168 SwWrtShell
& rWrtShell
= pView
->GetWrtShell();
170 m_xOkPB
->connect_clicked(LINK(this, SwTitlePageDlg
, OKHdl
));
171 m_xRestartNumberingCB
->connect_toggled(LINK(this, SwTitlePageDlg
, RestartNumberingHdl
));
172 m_xSetPageNumberCB
->connect_toggled(LINK(this, SwTitlePageDlg
, SetPageNumberHdl
));
173 m_xPageStartNF
->set_max(rWrtShell
.GetPageCnt() + 1);
175 sal_uInt16 nSetPage
= 1;
176 sal_uInt16 nResetPage
= 1;
177 sal_uInt16 nTitlePages
= 1;
178 lcl_PushCursor(rWrtShell
);
180 SwView
& rView
= rWrtShell
.GetView();
181 rView
.InvalidateRulerPos();
183 bool bMaybeResetNumbering
= false;
185 mpTitleDesc
= rWrtShell
.GetPageDescFromPool(RES_POOLPAGE_FIRST
);
186 mpIndexDesc
= rWrtShell
.GetPageDescFromPool(RES_POOLPAGE_REGISTER
);
187 mpNormalDesc
= rWrtShell
.GetPageDescFromPool(RES_POOLPAGE_STANDARD
);
189 rWrtShell
.StartOfSection();
190 if (lcl_GetPageDesc(rWrtShell
, nSetPage
, &mpPageFormatDesc
))
192 if (mpPageFormatDesc
->GetPageDesc() == mpTitleDesc
)
194 while (rWrtShell
.SttNxtPg())
196 const size_t nCurIdx
= rWrtShell
.GetCurPageDesc();
197 const SwPageDesc
& rPageDesc
= rWrtShell
.GetPageDesc(nCurIdx
);
199 if (mpIndexDesc
!= &rPageDesc
)
201 mpNormalDesc
= &rPageDesc
;
202 bMaybeResetNumbering
= lcl_GetPageDesc(rWrtShell
, nResetPage
, nullptr);
209 lcl_PopCursor(rWrtShell
);
211 m_xUseExistingPagesRB
->set_active(true);
212 m_xPageCountNF
->set_value(nTitlePages
);
213 m_xPageCountNF
->connect_value_changed(LINK(this, SwTitlePageDlg
, ValueChangeHdl
));
215 m_xDocumentStartRB
->set_active(true);
216 m_xPageStartNF
->set_sensitive(false);
217 m_xPageStartNF
->set_value(lcl_GetCurrentPage(rWrtShell
));
218 Link
<weld::Toggleable
&,void> aStartPageHdl
= LINK(this, SwTitlePageDlg
, StartPageHdl
);
219 m_xDocumentStartRB
->connect_toggled(aStartPageHdl
);
220 m_xPageStartRB
->connect_toggled(aStartPageHdl
);
222 m_xRestartNumberingNF
->set_value(nResetPage
);
223 if (bMaybeResetNumbering
&& nResetPage
> 0)
225 m_xRestartNumberingCB
->set_active(true);
227 m_xRestartNumberingNF
->set_sensitive(m_xRestartNumberingCB
->get_active());
229 m_xSetPageNumberNF
->set_value(nSetPage
);
231 m_xSetPageNumberCB
->set_active(true);
232 m_xSetPageNumberNF
->set_sensitive(m_xSetPageNumberCB
->get_active());
235 m_xPagePropertiesPB
->connect_clicked(LINK(this, SwTitlePageDlg
, EditHdl
));
238 IMPL_LINK_NOARG(SwTitlePageDlg
, ValueChangeHdl
, weld::SpinButton
&, void)
240 if (m_xPageCountNF
->get_value() == 1 || m_xPageCountNF
->get_value() == 2)
244 IMPL_LINK_NOARG(SwTitlePageDlg
, RestartNumberingHdl
, weld::Toggleable
&, void)
246 m_xRestartNumberingNF
->set_sensitive(m_xRestartNumberingCB
->get_active());
249 IMPL_LINK_NOARG(SwTitlePageDlg
, SetPageNumberHdl
, weld::Toggleable
&, void)
251 m_xSetPageNumberNF
->set_sensitive(m_xSetPageNumberCB
->get_active());
254 IMPL_LINK_NOARG(SwTitlePageDlg
, StartPageHdl
, weld::Toggleable
&, void)
256 m_xPageStartNF
->set_sensitive(m_xPageStartRB
->get_active());
259 SwTitlePageDlg::~SwTitlePageDlg()
263 IMPL_LINK_NOARG(SwTitlePageDlg
, EditHdl
, weld::Button
&, void)
265 SwView
* pView
= GetActiveView();
268 SwWrtShell
& rWrtShell
= pView
->GetWrtShell();
269 SwView
& rView
= rWrtShell
.GetView();
270 rView
.GetDocShell()->FormatPage(getDialog(), m_xPagePropertiesLB
->get_active_text(), "page", rWrtShell
);
271 rView
.InvalidateRulerPos();
274 IMPL_LINK_NOARG(SwTitlePageDlg
, OKHdl
, weld::Button
&, void)
276 SwView
* pView
= GetActiveView();
279 SwWrtShell
& rWrtShell
= pView
->GetWrtShell();
280 lcl_PushCursor(rWrtShell
);
282 rWrtShell
.StartUndo();
284 SwFormatPageDesc
aTitleDesc(mpTitleDesc
);
286 if (m_xSetPageNumberCB
->get_active())
287 aTitleDesc
.SetNumOffset(m_xSetPageNumberNF
->get_value());
288 else if (mpPageFormatDesc
)
289 aTitleDesc
.SetNumOffset(mpPageFormatDesc
->GetNumOffset());
291 sal_uInt16 nNumTitlePages
= m_xPageCountNF
->get_value();
292 if (!m_xUseExistingPagesRB
->get_active())
294 // Assuming that a failure to GotoPage means the end of the document,
295 // insert new pages after the last page.
296 if (!lcl_GotoPage(rWrtShell
, GetInsertPosition()))
299 // Add one more page as a content page to follow the new title pages.
300 rWrtShell
.InsertPageBreak();
302 for (sal_uInt16 nI
= 0; nI
< nNumTitlePages
; ++nI
)
303 rWrtShell
.InsertPageBreak();
304 // In order to be able to access these new pages, the layout needs to be recalculated first.
305 rWrtShell
.CalcLayout();
308 if (lcl_GotoPage(rWrtShell
, GetInsertPosition()))
310 rWrtShell
.SetAttrItem(aTitleDesc
);
311 for (sal_uInt16 nI
= 1; nI
< nNumTitlePages
; ++nI
)
313 if (rWrtShell
.SttNxtPg())
314 lcl_ChangePage(rWrtShell
, SAL_MAX_UINT16
, mpIndexDesc
);
318 if ((m_xRestartNumberingCB
->get_active() || nNumTitlePages
> 1)
319 && lcl_GotoPage(rWrtShell
, GetInsertPosition(), nNumTitlePages
))
322 = m_xRestartNumberingCB
->get_active() ? m_xRestartNumberingNF
->get_value() : 0;
323 const SwPageDesc
* pNewDesc
= nNumTitlePages
> 1 ? mpNormalDesc
: nullptr;
324 lcl_ChangePage(rWrtShell
, nPgNo
, pNewDesc
);
328 lcl_PopCursor(rWrtShell
);
329 if (!m_xUseExistingPagesRB
->get_active())
330 lcl_GotoPage(rWrtShell
, GetInsertPosition());
331 m_xDialog
->response(RET_OK
);
334 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */