LibreOffice Module sw (master) 1
contentcontroldlg.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
20#include <contentcontroldlg.hxx>
21
22#include <vcl/weld.hxx>
23#include <cui/cuicharmap.hxx>
24#include <svl/numformat.hxx>
25#include <svl/zformat.hxx>
26
27#include <wrtsh.hxx>
28#include <ndtxt.hxx>
30#include <IDocumentState.hxx>
31#include <swuiexp.hxx>
32#include <numfmtlb.hxx>
33
34using namespace com::sun::star;
35
37 : SfxDialogController(pParent, "modules/swriter/ui/contentcontroldlg.ui",
38 "ContentControlDialog")
39 , m_rWrtShell(rWrtShell)
40 , m_xShowingPlaceHolderCB(m_xBuilder->weld_check_button("showing_place_holder"))
41 , m_xAlias(m_xBuilder->weld_entry("aliasentry"))
42 , m_xTag(m_xBuilder->weld_entry("tagentry"))
43 , m_xCheckboxFrame(m_xBuilder->weld_frame("checkboxframe"))
44 , m_xCheckedState(m_xBuilder->weld_entry("checkboxcheckedentry"))
45 , m_xCheckedStateBtn(m_xBuilder->weld_button("btncheckboxchecked"))
46 , m_xUncheckedState(m_xBuilder->weld_entry("checkboxuncheckedentry"))
47 , m_xUncheckedStateBtn(m_xBuilder->weld_button("btncheckboxunchecked"))
48 , m_xListItemsFrame(m_xBuilder->weld_frame("listitemsframe"))
49 , m_xListItems(m_xBuilder->weld_tree_view("listitems"))
50 , m_xListItemButtons(m_xBuilder->weld_box("listitembuttons"))
51 , m_xInsertBtn(m_xBuilder->weld_button("add"))
52 , m_xRenameBtn(m_xBuilder->weld_button("modify"))
53 , m_xDeleteBtn(m_xBuilder->weld_button("remove"))
54 , m_xMoveUpBtn(m_xBuilder->weld_button("moveup"))
55 , m_xMoveDownBtn(m_xBuilder->weld_button("movedown"))
56 , m_xDateFrame(m_xBuilder->weld_frame("dateframe"))
57 , m_xDateFormat(new SwNumFormatTreeView(m_xBuilder->weld_tree_view("date_formats_treeview")))
58 , m_xOk(m_xBuilder->weld_button("ok"))
59{
60 m_xCheckedStateBtn->connect_clicked(LINK(this, SwContentControlDlg, SelectCharHdl));
61 m_xUncheckedStateBtn->connect_clicked(LINK(this, SwContentControlDlg, SelectCharHdl));
62 m_xListItems->connect_changed(LINK(this, SwContentControlDlg, SelectionChangedHdl));
63 m_xOk->connect_clicked(LINK(this, SwContentControlDlg, OkHdl));
64
65 // Only 2 items would be visible by default.
66 m_xListItems->set_size_request(-1, m_xListItems->get_height_rows(8));
67 // Only the first column would have a non-zero size by default in the SvHeaderTabListBox case.
68 m_xListItems->set_column_fixed_widths({ 100, 100 });
69
70 m_xInsertBtn->connect_clicked(LINK(this, SwContentControlDlg, InsertHdl));
71 m_xRenameBtn->connect_clicked(LINK(this, SwContentControlDlg, RenameHdl));
72 m_xDeleteBtn->connect_clicked(LINK(this, SwContentControlDlg, DeleteHdl));
73 m_xMoveUpBtn->connect_clicked(LINK(this, SwContentControlDlg, MoveUpHdl));
74 m_xMoveDownBtn->connect_clicked(LINK(this, SwContentControlDlg, MoveDownHdl));
75
76 const SwPosition* pStart = rWrtShell.GetCursor()->Start();
77 SwTextNode* pTextNode = pStart->GetNode().GetTextNode();
78 if (!pTextNode)
79 {
80 return;
81 }
82
83 SwTextAttr* pAttr = pTextNode->GetTextAttrAt(
85 if (!pAttr)
86 {
87 return;
88 }
89
90 SwTextContentControl* pTextContentControl = static_txtattr_cast<SwTextContentControl*>(pAttr);
91 const SwFormatContentControl& rFormatContentControl = pTextContentControl->GetContentControl();
92 m_pContentControl = rFormatContentControl.GetContentControl();
93
94 bool bShowingPlaceHolder = m_pContentControl->GetShowingPlaceHolder();
95 TriState eShowingPlaceHolder = bShowingPlaceHolder ? TRISTATE_TRUE : TRISTATE_FALSE;
96 m_xShowingPlaceHolderCB->set_state(eShowingPlaceHolder);
97 m_xShowingPlaceHolderCB->save_state();
98
99 if (!m_pContentControl->GetAlias().isEmpty())
100 {
101 m_xAlias->set_text(m_pContentControl->GetAlias());
102 m_xAlias->save_value();
103 }
104
105 if (!m_pContentControl->GetTag().isEmpty())
106 {
107 m_xTag->set_text(m_pContentControl->GetTag());
108 m_xTag->save_value();
109 }
110
111 if (m_pContentControl->GetCheckbox())
112 {
113 m_xCheckedState->set_text(m_pContentControl->GetCheckedState());
114 m_xCheckedState->save_value();
115 m_xUncheckedState->set_text(m_pContentControl->GetUncheckedState());
116 m_xUncheckedState->save_value();
117 }
118 else
119 {
120 m_xCheckboxFrame->set_visible(false);
121 }
122
123 if (m_pContentControl->GetComboBox() || m_pContentControl->GetDropDown())
124 {
125 for (const auto& rListItem : m_pContentControl->GetListItems())
126 {
127 int nRow = m_xListItems->n_children();
128 m_xListItems->append_text(rListItem.m_aDisplayText);
129 m_xListItems->set_text(nRow, rListItem.m_aValue, 1);
130 }
131 m_aSavedListItems = m_pContentControl->GetListItems();
132 }
133 else
134 {
135 m_xListItemsFrame->set_visible(false);
136 m_xListItemButtons->set_visible(false);
137 }
138
139 if (m_pContentControl->GetDate())
140 {
141 m_xDateFormat->SetFormatType(SvNumFormatType::DATE);
142 m_xDateFormat->SetShowLanguageControl(true);
143
144 // Set height to double of the default.
145 weld::TreeView& rTreeView = dynamic_cast<weld::TreeView&>(m_xDateFormat->get_widget());
146 rTreeView.set_size_request(rTreeView.get_preferred_size().Width(),
147 rTreeView.get_height_rows(10));
148
149 OUString sFormatString = m_pContentControl->GetDateFormat();
150 OUString sLang = m_pContentControl->GetDateLanguage();
151 if (!sFormatString.isEmpty() && !sLang.isEmpty())
152 {
154 LanguageType aLangType = LanguageTag(sLang).getLanguageType();
155 sal_uInt32 nFormat = pNumberFormatter->GetEntryKey(sFormatString, aLangType);
156 if (nFormat == NUMBERFORMAT_ENTRY_NOT_FOUND)
157 {
158 sal_Int32 nCheckPos = 0;
160 pNumberFormatter->PutEntry(sFormatString, nCheckPos, nType, nFormat,
161 LanguageTag(sLang).getLanguageType());
162 }
163
164 if (aLangType != LANGUAGE_DONTKNOW && nFormat != NUMBERFORMAT_ENTRY_NOT_FOUND)
165 {
166 m_xDateFormat->SetDefFormat(nFormat);
167 }
168 }
169 }
170 else
171 {
172 m_xDateFrame->set_visible(false);
173 }
174}
175
177
179{
180 if (!m_pContentControl)
181 {
182 return;
183 }
184
185 bool bChanged = false;
186 if (m_xShowingPlaceHolderCB->get_state_changed_from_saved())
187 {
188 bool bShowingPlaceHolder = m_xShowingPlaceHolderCB->get_state() == TRISTATE_TRUE;
189 m_pContentControl->SetShowingPlaceHolder(bShowingPlaceHolder);
190 bChanged = true;
191 }
192
193 if (m_xAlias->get_value_changed_from_saved())
194 {
195 m_pContentControl->SetAlias(m_xAlias->get_text());
196 bChanged = true;
197 }
198
199 if (m_xTag->get_value_changed_from_saved())
200 {
201 m_pContentControl->SetTag(m_xTag->get_text());
202 bChanged = true;
203 }
204
205 if (m_xCheckedState->get_value_changed_from_saved())
206 {
207 m_pContentControl->SetCheckedState(m_xCheckedState->get_text());
208 }
209
210 if (m_xUncheckedState->get_value_changed_from_saved())
211 {
212 m_pContentControl->SetUncheckedState(m_xUncheckedState->get_text());
213 }
214
215 std::vector<SwContentControlListItem> aItems;
216 for (int i = 0; i < m_xListItems->n_children(); ++i)
217 {
219 aItem.m_aDisplayText = m_xListItems->get_text(i, 0);
220 aItem.m_aValue = m_xListItems->get_text(i, 1);
221 aItems.push_back(aItem);
222 }
223 if (aItems != m_aSavedListItems)
224 {
225 m_pContentControl->SetListItems(aItems);
226 bChanged = true;
227 }
228
229 if (m_pContentControl->GetDate())
230 {
231 SvNumberFormatter* pNumberFormatter = m_rWrtShell.GetNumberFormatter();
232 const SvNumberformat* pFormat = pNumberFormatter->GetEntry(m_xDateFormat->GetFormat());
233 if (pFormat)
234 {
235 if (pFormat->GetFormatstring() != m_pContentControl->GetDateFormat())
236 {
237 m_pContentControl->SetDateFormat(pFormat->GetFormatstring());
238 bChanged = true;
239 }
240
241 OUString aLanguage = LanguageTag(pFormat->GetLanguage()).getBcp47();
242 if (aLanguage != m_pContentControl->GetDateLanguage())
243 {
244 m_pContentControl->SetDateLanguage(aLanguage);
245 bChanged = true;
246 }
247 }
248 }
249
250 if (bChanged)
251 {
252 m_rWrtShell.GetDoc()->getIDocumentState().SetModified();
253
254 // Make sure that the cursor gets updated with the new list items.
255 m_rWrtShell.HideCursor();
256 m_rWrtShell.ShowCursor();
257 }
258
259 m_xDialog->response(RET_OK);
260}
261
262IMPL_LINK(SwContentControlDlg, SelectCharHdl, weld::Button&, rButton, void)
263{
264 SvxCharacterMap aMap(m_xDialog.get(), nullptr, nullptr);
265 sal_UCS4 cBullet = 0;
266 sal_Int32 nIndex = 0;
267 if (&rButton == m_xCheckedStateBtn.get())
268 {
269 cBullet = m_pContentControl->GetCheckedState().iterateCodePoints(&nIndex);
270 }
271 else if (&rButton == m_xUncheckedStateBtn.get())
272 {
273 cBullet = m_pContentControl->GetUncheckedState().iterateCodePoints(&nIndex);
274 }
275 aMap.SetChar(cBullet);
276 if (aMap.run() != RET_OK)
277 {
278 return;
279 }
280
281 cBullet = aMap.GetChar();
282 if (&rButton == m_xCheckedStateBtn.get())
283 {
284 m_xCheckedState->set_text(OUString(&cBullet, 1));
285 }
286 else if (&rButton == m_xUncheckedStateBtn.get())
287 {
288 m_xUncheckedState->set_text(OUString(&cBullet, 1));
289 }
290}
291
293{
297 rFact.CreateSwContentControlListItemDlg(m_xDialog.get(), aItem));
298 if (!pDlg->Execute())
299 {
300 return;
301 }
302
303 if (aItem.m_aDisplayText.isEmpty() && aItem.m_aValue.isEmpty())
304 {
305 // Maintain the invariant that value can't be empty.
306 return;
307 }
308
309 if (aItem.m_aValue.isEmpty())
310 {
311 aItem.m_aValue = aItem.m_aDisplayText;
312 }
313
314 int nRow = m_xListItems->n_children();
315 m_xListItems->append_text(aItem.m_aDisplayText);
316 m_xListItems->set_text(nRow, aItem.m_aValue, 1);
317}
318
320{
321 int nRow = m_xListItems->get_selected_index();
322 if (nRow < 0)
323 {
324 return;
325 }
326
328 aItem.m_aDisplayText = m_xListItems->get_text(nRow, 0);
329 aItem.m_aValue = m_xListItems->get_text(nRow, 1);
332 rFact.CreateSwContentControlListItemDlg(m_xDialog.get(), aItem));
333 if (!pDlg->Execute())
334 {
335 return;
336 }
337
338 if (aItem.m_aDisplayText.isEmpty() && aItem.m_aValue.isEmpty())
339 {
340 // Maintain the invariant that value can't be empty.
341 return;
342 }
343
344 if (aItem.m_aValue.isEmpty())
345 {
346 aItem.m_aValue = aItem.m_aDisplayText;
347 }
348
349 m_xListItems->set_text(nRow, aItem.m_aDisplayText, 0);
350 m_xListItems->set_text(nRow, aItem.m_aValue, 1);
351}
352
354{
355 int nRow = m_xListItems->get_selected_index();
356 if (nRow < 0)
357 {
358 return;
359 }
360
361 m_xListItems->remove(nRow);
362}
363
365{
366 int nRow = m_xListItems->get_selected_index();
367 if (nRow <= 0)
368 {
369 return;
370 }
371
373 aItem.m_aDisplayText = m_xListItems->get_text(nRow, 0);
374 aItem.m_aValue = m_xListItems->get_text(nRow, 1);
375 m_xListItems->remove(nRow);
376 --nRow;
377 m_xListItems->insert_text(nRow, aItem.m_aDisplayText);
378 m_xListItems->set_text(nRow, aItem.m_aValue, 1);
379 m_xListItems->select(nRow);
380}
381
383{
384 int nRow = m_xListItems->get_selected_index();
385 int nEndPos = m_xListItems->n_children() - 1;
386 if (nRow < 0 || nRow >= nEndPos)
387 {
388 return;
389 }
390
392 aItem.m_aDisplayText = m_xListItems->get_text(nRow, 0);
393 aItem.m_aValue = m_xListItems->get_text(nRow, 1);
394 m_xListItems->remove(nRow);
395 ++nRow;
396 m_xListItems->insert_text(nRow, aItem.m_aDisplayText);
397 m_xListItems->set_text(nRow, aItem.m_aValue, 1);
398 m_xListItems->select(nRow);
399}
400
402{
403 int nRow = m_xListItems->get_selected_index();
404 if (nRow < 0)
405 {
406 m_xRenameBtn->set_sensitive(false);
407 m_xDeleteBtn->set_sensitive(false);
408 }
409 else
410 {
411 m_xRenameBtn->set_sensitive(true);
412 m_xDeleteBtn->set_sensitive(true);
413 }
414
415 if (nRow <= 0)
416 {
417 m_xMoveUpBtn->set_sensitive(false);
418 }
419 else
420 {
421 m_xMoveUpBtn->set_sensitive(true);
422 }
423
424 int nEndPos = m_xListItems->n_children() - 1;
425 if (nRow < 0 || nRow >= nEndPos)
426 {
427 m_xMoveDownBtn->set_sensitive(false);
428 }
429 else
430 {
431 m_xMoveDownBtn->set_sensitive(true);
432 }
433}
434
435/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Reference< XExecutableDialog > m_xDialog
LanguageType getLanguageType(bool bResolveSystem=true) const
const OUString & getBcp47(bool bResolveSystem=true) const
constexpr tools::Long Width() const
bool PutEntry(OUString &rString, sal_Int32 &nCheckPos, SvNumFormatType &nType, sal_uInt32 &nKey, LanguageType eLnge=LANGUAGE_DONTKNOW, bool bReplaceBooleanEquivalent=true)
sal_uInt32 GetEntryKey(std::u16string_view sStr, LanguageType eLnge=LANGUAGE_DONTKNOW)
const SvNumberformat * GetEntry(sal_uInt32 nKey) const
LanguageType GetLanguage() const
const OUString & GetFormatstring() const
virtual VclPtr< AbstractSwContentControlListItemDlg > CreateSwContentControlListItemDlg(weld::Window *pParent, SwContentControlListItem &rItem)=0
The content control dialog allows editing the properties of the content control under the cursor.
std::unique_ptr< weld::Box > m_xListItemButtons
std::unique_ptr< weld::Button > m_xUncheckedStateBtn
std::unique_ptr< weld::Button > m_xRenameBtn
std::vector< SwContentControlListItem > m_aSavedListItems
std::unique_ptr< weld::Frame > m_xDateFrame
std::shared_ptr< SwContentControl > m_pContentControl
std::unique_ptr< weld::Button > m_xMoveUpBtn
std::unique_ptr< weld::Button > m_xInsertBtn
std::unique_ptr< weld::TreeView > m_xListItems
std::unique_ptr< weld::Frame > m_xListItemsFrame
std::unique_ptr< weld::CheckButton > m_xShowingPlaceHolderCB
std::unique_ptr< weld::Button > m_xMoveDownBtn
std::unique_ptr< weld::Frame > m_xCheckboxFrame
std::unique_ptr< weld::Entry > m_xAlias
std::unique_ptr< weld::Entry > m_xUncheckedState
SwContentControlDlg(weld::Window *pParent, SwWrtShell &rSh)
std::unique_ptr< weld::Button > m_xCheckedStateBtn
std::unique_ptr< weld::Button > m_xDeleteBtn
virtual ~SwContentControlDlg() override
std::unique_ptr< weld::Entry > m_xTag
std::unique_ptr< SwNumFormatTreeView > m_xDateFormat
std::unique_ptr< weld::Button > m_xOk
std::unique_ptr< weld::Entry > m_xCheckedState
Represents one list item in a content control dropdown list.
OUString m_aValue
This must not be empty.
OUString m_aDisplayText
This may be empty, ToString() falls back to m_aValue.
SwCursor * GetCursor(bool bMakeTableCursor=true) const
Return pointer to the current shell cursor.
Definition: crsrsh.cxx:194
SvNumberFormatter * GetNumberFormatter()
Query NumberFormatter from document.
Definition: editsh.cxx:756
SfxPoolItem subclass that wraps an SwContentControl.
const std::shared_ptr< SwContentControl > & GetContentControl() const
SwTextNode * GetTextNode()
Inline methods from Node.hxx.
Definition: ndtxt.hxx:897
const SwPosition * Start() const
Definition: pam.hxx:266
A wrapper around SfxPoolItem to store the start position of (usually) a text portion,...
Definition: txatbase.hxx:44
const SwFormatContentControl & GetContentControl() const
Definition: txatbase.hxx:220
SwTextAttr subclass that tracks the location of the wrapped SwFormatContentControl.
SwTextNode is a paragraph in the document model.
Definition: ndtxt.hxx:111
SwTextAttr * GetTextAttrAt(sal_Int32 const nIndex, sal_uInt16 const nWhich, ::sw::GetTextAttrMode const eMode=::sw::GetTextAttrMode::Default) const
get the innermost text attribute covering position nIndex.
Definition: ndtxt.cxx:1790
Used by the UI to modify the document model.
Definition: wrtsh.hxx:97
virtual int get_height_rows(int nRows) const=0
virtual void set_size_request(int nWidth, int nHeight)=0
virtual Size get_preferred_size() const=0
IMPL_LINK_NOARG(SwContentControlDlg, OkHdl, weld::Button &, void)
IMPL_LINK(SwContentControlDlg, SelectCharHdl, weld::Button &, rButton, void)
TriState
TRISTATE_FALSE
TRISTATE_TRUE
constexpr TypedWhichId< SwFormatContentControl > RES_TXTATR_CONTENTCONTROL(56)
sal_Int32 nIndex
#define LANGUAGE_DONTKNOW
int i
@ Parent
EXPAND : (Start < nIndex <= End)
SwAbstractDialogFactory & GetFactory()
Definition: swuiexp.cxx:26
HashMap_OWString_Interface aMap
QPRO_FUNC_TYPE nType
Marks a position in the document model.
Definition: pam.hxx:37
SwNode & GetNode() const
Definition: pam.hxx:80
sal_Int32 GetContentIndex() const
Definition: pam.hxx:84
RET_OK
sal_uInt32 sal_UCS4
SvNumFormatType
constexpr sal_uInt32 NUMBERFORMAT_ENTRY_NOT_FOUND