android: Update app-specific/MIME type icons
[LibreOffice.git] / sw / source / ui / misc / contentcontroldlg.cxx
blobf318fa6a699e1be3364655ff0a9d87cb3aad9a70
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 <contentcontroldlg.hxx>
22 #include <vcl/weld.hxx>
23 #include <cui/cuicharmap.hxx>
24 #include <svl/numformat.hxx>
25 #include <svl/zformat.hxx>
27 #include <wrtsh.hxx>
28 #include <ndtxt.hxx>
29 #include <textcontentcontrol.hxx>
30 #include <IDocumentState.hxx>
31 #include <swuiexp.hxx>
32 #include <numfmtlb.hxx>
34 using namespace com::sun::star;
36 SwContentControlDlg::SwContentControlDlg(weld::Window* pParent, SwWrtShell& rWrtShell)
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_xId(m_xBuilder->weld_spin_button("idspinbutton"))
44 , m_xTabIndex(m_xBuilder->weld_spin_button("tabindexspinbutton"))
45 , m_xCheckboxFrame(m_xBuilder->weld_frame("checkboxframe"))
46 , m_xCheckedState(m_xBuilder->weld_entry("checkboxcheckedentry"))
47 , m_xCheckedStateBtn(m_xBuilder->weld_button("btncheckboxchecked"))
48 , m_xUncheckedState(m_xBuilder->weld_entry("checkboxuncheckedentry"))
49 , m_xUncheckedStateBtn(m_xBuilder->weld_button("btncheckboxunchecked"))
50 , m_xListItemsFrame(m_xBuilder->weld_frame("listitemsframe"))
51 , m_xListItems(m_xBuilder->weld_tree_view("listitems"))
52 , m_xListItemButtons(m_xBuilder->weld_box("listitembuttons"))
53 , m_xInsertBtn(m_xBuilder->weld_button("add"))
54 , m_xRenameBtn(m_xBuilder->weld_button("modify"))
55 , m_xDeleteBtn(m_xBuilder->weld_button("remove"))
56 , m_xMoveUpBtn(m_xBuilder->weld_button("moveup"))
57 , m_xMoveDownBtn(m_xBuilder->weld_button("movedown"))
58 , m_xDateFrame(m_xBuilder->weld_frame("dateframe"))
59 , m_xDateFormat(new SwNumFormatTreeView(m_xBuilder->weld_tree_view("date_formats_treeview")))
60 , m_xOk(m_xBuilder->weld_button("ok"))
62 m_xCheckedStateBtn->connect_clicked(LINK(this, SwContentControlDlg, SelectCharHdl));
63 m_xUncheckedStateBtn->connect_clicked(LINK(this, SwContentControlDlg, SelectCharHdl));
64 m_xListItems->connect_changed(LINK(this, SwContentControlDlg, SelectionChangedHdl));
65 m_xOk->connect_clicked(LINK(this, SwContentControlDlg, OkHdl));
67 // Only 2 items would be visible by default.
68 m_xListItems->set_size_request(-1, m_xListItems->get_height_rows(8));
69 // Only the first column would have a non-zero size by default in the SvHeaderTabListBox case.
70 m_xListItems->set_column_fixed_widths({ 100, 100 });
72 m_xInsertBtn->connect_clicked(LINK(this, SwContentControlDlg, InsertHdl));
73 m_xRenameBtn->connect_clicked(LINK(this, SwContentControlDlg, RenameHdl));
74 m_xDeleteBtn->connect_clicked(LINK(this, SwContentControlDlg, DeleteHdl));
75 m_xMoveUpBtn->connect_clicked(LINK(this, SwContentControlDlg, MoveUpHdl));
76 m_xMoveDownBtn->connect_clicked(LINK(this, SwContentControlDlg, MoveDownHdl));
78 const SwPosition* pStart = rWrtShell.GetCursor()->Start();
79 SwTextNode* pTextNode = pStart->GetNode().GetTextNode();
80 if (!pTextNode)
82 return;
85 SwTextAttr* pAttr = pTextNode->GetTextAttrAt(
86 pStart->GetContentIndex(), RES_TXTATR_CONTENTCONTROL, ::sw::GetTextAttrMode::Parent);
87 if (!pAttr)
89 return;
92 SwTextContentControl* pTextContentControl = static_txtattr_cast<SwTextContentControl*>(pAttr);
93 const SwFormatContentControl& rFormatContentControl = pTextContentControl->GetContentControl();
94 m_pContentControl = rFormatContentControl.GetContentControl();
96 bool bShowingPlaceHolder = m_pContentControl->GetShowingPlaceHolder();
97 TriState eShowingPlaceHolder = bShowingPlaceHolder ? TRISTATE_TRUE : TRISTATE_FALSE;
98 m_xShowingPlaceHolderCB->set_state(eShowingPlaceHolder);
99 m_xShowingPlaceHolderCB->save_state();
101 if (!m_pContentControl->GetAlias().isEmpty())
103 m_xAlias->set_text(m_pContentControl->GetAlias());
104 m_xAlias->save_value();
107 if (!m_pContentControl->GetTag().isEmpty())
109 m_xTag->set_text(m_pContentControl->GetTag());
110 m_xTag->save_value();
113 // The ID is supposed to be a unique ID, but it isn't really used for much
114 // and in MS Word it (supposedly) is automatically made unique if it is a duplicate.
115 // The main purpose for having it here is lookup, not modification,
116 // since AFAIK the only use of the ID is for VBA macro name lookup.
117 // Since it is used as unsigned in VBA, make the UI display the unsigned values too.
118 m_xId->set_range(0, SAL_MAX_UINT32);
119 m_xId->set_increments(1, 10);
120 const sal_uInt32 nId = static_cast<sal_uInt32>(m_pContentControl->GetId());
121 m_xId->set_value(nId);
122 // a one-time chance to set the ID - only allow setting it when it is undefined.
123 if (nId)
124 m_xId->set_editable(false); // still available for copy/paste
125 m_xId->save_value();
127 // And on the contrary, the tabIndex is stored as unsigned,
128 // even though humanly speaking it is much nicer to use -1 to indicate a no tab stop. Oh well.
129 m_xTabIndex->set_range(SAL_MIN_INT32, SAL_MAX_INT32);
130 m_xTabIndex->set_increments(1, 10);
131 const sal_Int32 nTabIndex = static_cast<sal_Int32>(m_pContentControl->GetTabIndex());
132 m_xTabIndex->set_value(nTabIndex);
133 m_xTabIndex->save_value();
135 if (m_pContentControl->GetCheckbox())
137 m_xCheckedState->set_text(m_pContentControl->GetCheckedState());
138 m_xCheckedState->save_value();
139 m_xUncheckedState->set_text(m_pContentControl->GetUncheckedState());
140 m_xUncheckedState->save_value();
142 else
144 m_xCheckboxFrame->set_visible(false);
147 if (m_pContentControl->GetComboBox() || m_pContentControl->GetDropDown())
149 for (const auto& rListItem : m_pContentControl->GetListItems())
151 int nRow = m_xListItems->n_children();
152 m_xListItems->append_text(rListItem.m_aDisplayText);
153 m_xListItems->set_text(nRow, rListItem.m_aValue, 1);
155 m_aSavedListItems = m_pContentControl->GetListItems();
157 else
159 m_xListItemsFrame->set_visible(false);
160 m_xListItemButtons->set_visible(false);
163 if (m_pContentControl->GetDate())
165 m_xDateFormat->SetFormatType(SvNumFormatType::DATE);
166 m_xDateFormat->SetShowLanguageControl(true);
168 // Set height to double of the default.
169 weld::TreeView& rTreeView = dynamic_cast<weld::TreeView&>(m_xDateFormat->get_widget());
170 rTreeView.set_size_request(rTreeView.get_preferred_size().Width(),
171 rTreeView.get_height_rows(10));
173 OUString sFormatString = m_pContentControl->GetDateFormat();
174 OUString sLang = m_pContentControl->GetDateLanguage();
175 if (!sFormatString.isEmpty() && !sLang.isEmpty())
177 SvNumberFormatter* pNumberFormatter = m_rWrtShell.GetNumberFormatter();
178 LanguageType aLangType = LanguageTag(sLang).getLanguageType();
179 sal_uInt32 nFormat = pNumberFormatter->GetEntryKey(sFormatString, aLangType);
180 if (nFormat == NUMBERFORMAT_ENTRY_NOT_FOUND)
182 sal_Int32 nCheckPos = 0;
183 SvNumFormatType nType;
184 pNumberFormatter->PutEntry(sFormatString, nCheckPos, nType, nFormat,
185 LanguageTag(sLang).getLanguageType());
188 if (aLangType != LANGUAGE_DONTKNOW && nFormat != NUMBERFORMAT_ENTRY_NOT_FOUND)
190 m_xDateFormat->SetDefFormat(nFormat);
194 else
196 m_xDateFrame->set_visible(false);
200 SwContentControlDlg::~SwContentControlDlg()
202 if (m_xListItemDialog)
203 m_xListItemDialog.disposeAndClear();
206 IMPL_LINK_NOARG(SwContentControlDlg, OkHdl, weld::Button&, void)
208 if (!m_pContentControl)
210 return;
213 bool bChanged = false;
214 if (m_xShowingPlaceHolderCB->get_state_changed_from_saved())
216 bool bShowingPlaceHolder = m_xShowingPlaceHolderCB->get_state() == TRISTATE_TRUE;
217 m_pContentControl->SetShowingPlaceHolder(bShowingPlaceHolder);
218 bChanged = true;
221 if (m_xAlias->get_value_changed_from_saved())
223 m_pContentControl->SetAlias(m_xAlias->get_text());
224 bChanged = true;
227 if (m_xTag->get_value_changed_from_saved())
229 m_pContentControl->SetTag(m_xTag->get_text());
230 bChanged = true;
233 if (m_xId->get_value_changed_from_saved())
235 m_pContentControl->SetId(o3tl::narrowing<sal_Int32>(m_xId->get_value()));
236 bChanged = true;
239 if (m_xTabIndex->get_value_changed_from_saved())
241 m_pContentControl->SetTabIndex(o3tl::narrowing<sal_uInt32>(m_xTabIndex->get_value()));
242 bChanged = true;
245 if (m_xCheckedState->get_value_changed_from_saved())
247 m_pContentControl->SetCheckedState(m_xCheckedState->get_text());
250 if (m_xUncheckedState->get_value_changed_from_saved())
252 m_pContentControl->SetUncheckedState(m_xUncheckedState->get_text());
255 std::vector<SwContentControlListItem> aItems;
256 for (int i = 0; i < m_xListItems->n_children(); ++i)
258 SwContentControlListItem aItem;
259 aItem.m_aDisplayText = m_xListItems->get_text(i, 0);
260 aItem.m_aValue = m_xListItems->get_text(i, 1);
261 aItems.push_back(aItem);
263 if (aItems != m_aSavedListItems)
265 m_pContentControl->SetListItems(aItems);
266 bChanged = true;
269 if (m_pContentControl->GetDate())
271 SvNumberFormatter* pNumberFormatter = m_rWrtShell.GetNumberFormatter();
272 const SvNumberformat* pFormat = pNumberFormatter->GetEntry(m_xDateFormat->GetFormat());
273 if (pFormat)
275 if (pFormat->GetFormatstring() != m_pContentControl->GetDateFormat())
277 m_pContentControl->SetDateFormat(pFormat->GetFormatstring());
278 bChanged = true;
281 OUString aLanguage = LanguageTag(pFormat->GetLanguage()).getBcp47();
282 if (aLanguage != m_pContentControl->GetDateLanguage())
284 m_pContentControl->SetDateLanguage(aLanguage);
285 bChanged = true;
290 if (bChanged)
292 m_rWrtShell.GetDoc()->getIDocumentState().SetModified();
294 // Make sure that the cursor gets updated with the new list items.
295 m_rWrtShell.HideCursor();
296 m_rWrtShell.ShowCursor();
299 m_xDialog->response(RET_OK);
302 IMPL_LINK(SwContentControlDlg, SelectCharHdl, weld::Button&, rButton, void)
304 SvxCharacterMap aMap(m_xDialog.get(), nullptr, nullptr);
305 sal_UCS4 cBullet = 0;
306 sal_Int32 nIndex = 0;
307 if (&rButton == m_xCheckedStateBtn.get())
309 cBullet = m_pContentControl->GetCheckedState().iterateCodePoints(&nIndex);
311 else if (&rButton == m_xUncheckedStateBtn.get())
313 cBullet = m_pContentControl->GetUncheckedState().iterateCodePoints(&nIndex);
315 aMap.SetChar(cBullet);
316 if (aMap.run() != RET_OK)
318 return;
321 cBullet = aMap.GetChar();
322 if (&rButton == m_xCheckedStateBtn.get())
324 m_xCheckedState->set_text(OUString(&cBullet, 1));
326 else if (&rButton == m_xUncheckedStateBtn.get())
328 m_xUncheckedState->set_text(OUString(&cBullet, 1));
332 IMPL_LINK_NOARG(SwContentControlDlg, InsertHdl, weld::Button&, void)
334 std::shared_ptr<SwContentControlListItem> aItem = std::make_shared<SwContentControlListItem>();
335 SwAbstractDialogFactory& rFact = swui::GetFactory();
336 m_xListItemDialog = rFact.CreateSwContentControlListItemDlg(m_xDialog.get(), *aItem);
337 m_xListItemDialog->StartExecuteAsync([this, aItem](sal_Int32 nResult) {
338 if (nResult == RET_OK)
340 if (aItem->m_aDisplayText.isEmpty() && aItem->m_aValue.isEmpty())
342 // Maintain the invariant that value can't be empty.
343 return;
346 if (aItem->m_aValue.isEmpty())
348 aItem->m_aValue = aItem->m_aDisplayText;
351 int nRow = m_xListItems->n_children();
352 m_xListItems->append_text(aItem->m_aDisplayText);
353 m_xListItems->set_text(nRow, aItem->m_aValue, 1);
356 m_xListItemDialog.disposeAndClear();
360 IMPL_LINK_NOARG(SwContentControlDlg, RenameHdl, weld::Button&, void)
362 int nRow = m_xListItems->get_selected_index();
363 if (nRow < 0)
365 return;
368 std::shared_ptr<SwContentControlListItem> aItem = std::make_shared<SwContentControlListItem>();
369 aItem->m_aDisplayText = m_xListItems->get_text(nRow, 0);
370 aItem->m_aValue = m_xListItems->get_text(nRow, 1);
371 SwAbstractDialogFactory& rFact = swui::GetFactory();
372 m_xListItemDialog = rFact.CreateSwContentControlListItemDlg(m_xDialog.get(), *aItem);
373 m_xListItemDialog->StartExecuteAsync([this, aItem, nRow](sal_Int32 nResult) {
374 if (nResult == RET_OK)
376 if (aItem->m_aDisplayText.isEmpty() && aItem->m_aValue.isEmpty())
378 // Maintain the invariant that value can't be empty.
379 return;
382 if (aItem->m_aValue.isEmpty())
384 aItem->m_aValue = aItem->m_aDisplayText;
387 m_xListItems->set_text(nRow, aItem->m_aDisplayText, 0);
388 m_xListItems->set_text(nRow, aItem->m_aValue, 1);
391 m_xListItemDialog.disposeAndClear();
395 IMPL_LINK_NOARG(SwContentControlDlg, DeleteHdl, weld::Button&, void)
397 int nRow = m_xListItems->get_selected_index();
398 if (nRow < 0)
400 return;
403 m_xListItems->remove(nRow);
406 IMPL_LINK_NOARG(SwContentControlDlg, MoveUpHdl, weld::Button&, void)
408 int nRow = m_xListItems->get_selected_index();
409 if (nRow <= 0)
411 return;
414 SwContentControlListItem aItem;
415 aItem.m_aDisplayText = m_xListItems->get_text(nRow, 0);
416 aItem.m_aValue = m_xListItems->get_text(nRow, 1);
417 m_xListItems->remove(nRow);
418 --nRow;
419 m_xListItems->insert_text(nRow, aItem.m_aDisplayText);
420 m_xListItems->set_text(nRow, aItem.m_aValue, 1);
421 m_xListItems->select(nRow);
424 IMPL_LINK_NOARG(SwContentControlDlg, MoveDownHdl, weld::Button&, void)
426 int nRow = m_xListItems->get_selected_index();
427 int nEndPos = m_xListItems->n_children() - 1;
428 if (nRow < 0 || nRow >= nEndPos)
430 return;
433 SwContentControlListItem aItem;
434 aItem.m_aDisplayText = m_xListItems->get_text(nRow, 0);
435 aItem.m_aValue = m_xListItems->get_text(nRow, 1);
436 m_xListItems->remove(nRow);
437 ++nRow;
438 m_xListItems->insert_text(nRow, aItem.m_aDisplayText);
439 m_xListItems->set_text(nRow, aItem.m_aValue, 1);
440 m_xListItems->select(nRow);
443 IMPL_LINK_NOARG(SwContentControlDlg, SelectionChangedHdl, weld::TreeView&, void)
445 int nRow = m_xListItems->get_selected_index();
446 if (nRow < 0)
448 m_xRenameBtn->set_sensitive(false);
449 m_xDeleteBtn->set_sensitive(false);
451 else
453 m_xRenameBtn->set_sensitive(true);
454 m_xDeleteBtn->set_sensitive(true);
457 if (nRow <= 0)
459 m_xMoveUpBtn->set_sensitive(false);
461 else
463 m_xMoveUpBtn->set_sensitive(true);
466 int nEndPos = m_xListItems->n_children() - 1;
467 if (nRow < 0 || nRow >= nEndPos)
469 m_xMoveDownBtn->set_sensitive(false);
471 else
473 m_xMoveDownBtn->set_sensitive(true);
477 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */