Coverage Report

Created: 2026-08-14 10:22

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/sw/inc/formatcontentcontrol.hxx
Line
Count
Source
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
#pragma once
21
22
#include <com/sun/star/text/XTextContent.hpp>
23
#include <com/sun/star/beans/PropertyValue.hpp>
24
25
#include <cppuhelper/weakref.hxx>
26
#include <sal/types.h>
27
#include <svl/poolitem.hxx>
28
#include <unotools/weakref.hxx>
29
30
#include "calbck.hxx"
31
#include "swdllapi.h"
32
33
namespace vcl
34
{
35
class KeyCode;
36
}
37
class SwContentControl;
38
class SwTextContentControl;
39
class SwTextNode;
40
class SwXContentControl;
41
42
enum class SwContentControlType
43
{
44
    RICH_TEXT,
45
    CHECKBOX,
46
    DROP_DOWN_LIST,
47
    PICTURE,
48
    DATE,
49
    PLAIN_TEXT,
50
    COMBO_BOX,
51
};
52
53
/// SfxPoolItem subclass that wraps an SwContentControl.
54
class SW_DLLPUBLIC SwFormatContentControl final : public SfxPoolItem
55
{
56
    std::shared_ptr<SwContentControl> m_pContentControl;
57
    SwTextContentControl* m_pTextAttr;
58
59
public:
60
9.90k
    SwTextContentControl* GetTextAttr() { return m_pTextAttr; }
61
    void SetTextAttr(SwTextContentControl* pTextAttr);
62
63
    /// This method must be called when the hint is actually copied.
64
    void DoCopy(SwTextNode& rTargetTextNode);
65
66
    DECLARE_ITEM_TYPE_FUNCTION(SwFormatContentControl)
67
    explicit SwFormatContentControl(sal_uInt16 nWhich);
68
69
    explicit SwFormatContentControl(const std::shared_ptr<SwContentControl>& pContentControl,
70
                                    sal_uInt16 nWhich);
71
    ~SwFormatContentControl() override;
72
73
    /// SfxPoolItem
74
    bool operator==(const SfxPoolItem&) const override;
75
    SwFormatContentControl* Clone(SfxItemPool* pPool = nullptr) const override;
76
77
    /**
78
     * Notify clients registered at m_pContentControl that this content control is being
79
     * (re-)moved.
80
     */
81
    void NotifyChangeTextNode(SwTextNode* pTextNode);
82
    SwTextNode* GetTextNode() const;
83
    static SwFormatContentControl* CreatePoolDefault(sal_uInt16 nWhich);
84
2.66k
    const std::shared_ptr<SwContentControl>& GetContentControl() const { return m_pContentControl; }
85
86
    void dumpAsXml(xmlTextWriterPtr pWriter) const override;
87
};
88
89
/// Represents one list item in a content control dropdown list.
90
class SW_DLLPUBLIC SwContentControlListItem
91
{
92
public:
93
    /// This may be empty, ToString() falls back to m_aValue.
94
    OUString m_aDisplayText;
95
    /// This must not be empty.
96
    OUString m_aValue;
97
98
    void dumpAsXml(xmlTextWriterPtr pWriter) const;
99
100
    const OUString& ToString() const;
101
102
    bool operator==(const SwContentControlListItem& rOther) const;
103
104
    static void ItemsToAny(const std::vector<SwContentControlListItem>& rItems,
105
                           css::uno::Any& rVal);
106
107
    static std::vector<SwContentControlListItem> ItemsFromAny(const css::uno::Any& rVal);
108
};
109
110
/// Stores the properties of a content control.
111
class SW_DLLPUBLIC SwContentControl final : public sw::BroadcastingModify
112
{
113
    unotools::WeakReference<SwXContentControl> m_wXContentControl;
114
115
    SwFormatContentControl* m_pFormat;
116
117
    /// Can be nullptr if not in a document for undo purposes.
118
    SwTextNode* m_pTextNode;
119
120
    /// Current content is placeholder text.
121
    bool m_bShowingPlaceHolder = false;
122
123
    /// Display the content control as a checkbox.
124
    bool m_bCheckbox = false;
125
126
    /// If m_bCheckbox is true, is the checkbox checked?
127
    bool m_bChecked = false;
128
129
    /// If m_bCheckbox is true, the value of a checked checkbox.
130
    OUString m_aCheckedState;
131
132
    /// If m_bCheckbox is true, the value of an unchecked checkbox.
133
    OUString m_aUncheckedState;
134
135
    std::vector<SwContentControlListItem> m_aListItems;
136
137
    bool m_bPicture = false;
138
139
    bool m_bDate = false;
140
141
    /// If m_bDate is true, the date format in a syntax accepted by SvNumberFormatter::PutEntry().
142
    OUString m_aDateFormat;
143
144
    /// If m_bDate is true, the date's BCP 47 language tag.
145
    OUString m_aDateLanguage;
146
147
    /// Date in YYYY-MM-DDT00:00:00Z format.
148
    OUString m_aCurrentDate;
149
150
    /// Plain text, i.e. not rich text.
151
    bool m_bPlainText = false;
152
153
    /// Same as drop-down, but free-form input is also accepted.
154
    bool m_bComboBox = false;
155
156
    /// Same as combo box, but free-form input is not accepted.
157
    bool m_bDropDown = false;
158
159
    /// The placeholder's doc part: just remembered.
160
    OUString m_aPlaceholderDocPart;
161
162
    /// The data bindings's prefix mappings: just remembered.
163
    OUString m_aDataBindingPrefixMappings;
164
165
    /// The data bindings's XPath: just remembered.
166
    OUString m_aDataBindingXpath;
167
168
    /// The data bindings's store item ID: just remembered.
169
    OUString m_aDataBindingStoreItemID;
170
171
    /// The color: just remembered.
172
    OUString m_aColor;
173
174
    /// The appearance: just remembered.
175
    OUString m_aAppearance;
176
177
    /// The alias.
178
    OUString m_aAlias;
179
180
    /// The tag: just remembered.
181
    OUString m_aTag;
182
183
    /// The id: just remembered.
184
    sal_Int32 m_nId = 0;
185
186
    /// The tabIndex: just remembered.
187
    sal_uInt32 m_nTabIndex = 0;
188
189
    /// The control and content locks: mostly just remembered.
190
    OUString m_aLock;
191
192
    /// The multiline property: just remembered.
193
    OUString m_aMultiLine;
194
195
    /// Stores a list item index, in case the doc model is not yet updated.
196
    // i.e. temporarily store the selected item until the text is inserted by GotoContentControl.
197
    std::optional<size_t> m_oSelectedListItem;
198
199
    /// Stores a date timestamp, in case the doc model is not yet updated.
200
    // i.e. temporarily store the date until the text is inserted by GotoContentControl.
201
    std::optional<double> m_oSelectedDate;
202
203
    /**
204
     * E.g. checkbox is read-only by default, but we still update contents on interaction
205
     * internally. This flag is true for the duration of that interaction.
206
     */
207
    bool m_bReadWrite = false;
208
209
public:
210
    SwTextContentControl* GetTextAttr() const;
211
212
0
    SwTextNode* GetTextNode() const { return m_pTextNode; }
213
214
20.6k
    SwFormatContentControl* GetFormatContentControl() const { return m_pFormat; }
215
216
6.28k
    void SetFormatContentControl(SwFormatContentControl* pFormat) { m_pFormat = pFormat; };
217
218
    void NotifyChangeTextNode(SwTextNode* pTextNode);
219
220
    const unotools::WeakReference<SwXContentControl>& GetXContentControl() const
221
0
    {
222
0
        return m_wXContentControl;
223
0
    }
224
225
    void SetXContentControl(const rtl::Reference<SwXContentControl>& xContentControl);
226
227
    virtual void SwClientNotify(const SwModify&, const SfxHint&) override;
228
229
    explicit SwContentControl(SwFormatContentControl* pFormat);
230
231
    virtual ~SwContentControl() override;
232
233
    void SetShowingPlaceHolder(bool bShowingPlaceHolder)
234
3.14k
    {
235
3.14k
        m_bShowingPlaceHolder = bShowingPlaceHolder;
236
3.14k
    }
237
238
0
    bool GetShowingPlaceHolder() const { return m_bShowingPlaceHolder; }
239
240
3.14k
    void SetCheckbox(bool bCheckbox) { m_bCheckbox = bCheckbox; }
241
242
0
    bool GetCheckbox() const { return m_bCheckbox; }
243
244
3.14k
    void SetChecked(bool bChecked) { m_bChecked = bChecked; }
245
246
0
    bool GetChecked() const { return m_bChecked; }
247
248
3.14k
    void SetCheckedState(const OUString& rCheckedState) { m_aCheckedState = rCheckedState; }
249
250
0
    const OUString& GetCheckedState() const { return m_aCheckedState; }
251
252
3.14k
    void SetUncheckedState(const OUString& rUncheckedState) { m_aUncheckedState = rUncheckedState; }
253
254
0
    const OUString& GetUncheckedState() const { return m_aUncheckedState; }
255
256
0
    const std::vector<SwContentControlListItem>& GetListItems() const { return m_aListItems; }
257
258
    void SetListItems(const std::vector<SwContentControlListItem>& rListItems)
259
3.14k
    {
260
3.14k
        m_aListItems = rListItems;
261
3.14k
    }
262
    void SetListItems(std::vector<SwContentControlListItem>&& rListItems)
263
0
    {
264
0
        m_aListItems = std::move(rListItems);
265
0
    }
266
267
    bool AddListItem(size_t nZIndex, const OUString& rDisplayText, const OUString& rValue);
268
    void DeleteListItem(size_t nZIndex);
269
    void ClearListItems();
270
271
3.14k
    void SetPicture(bool bPicture) { m_bPicture = bPicture; }
272
273
0
    bool GetPicture() const { return m_bPicture; }
274
275
3.14k
    void SetDate(bool bDate) { m_bDate = bDate; }
276
277
0
    bool GetDate() const { return m_bDate; }
278
279
3.14k
    void SetDateFormat(const OUString& rDateFormat) { m_aDateFormat = rDateFormat; }
280
281
0
    const OUString& GetDateFormat() const { return m_aDateFormat; }
282
283
3.14k
    void SetDateLanguage(const OUString& rDateLanguage) { m_aDateLanguage = rDateLanguage; }
284
285
0
    const OUString& GetDateLanguage() const { return m_aDateLanguage; }
286
287
3.14k
    void SetCurrentDate(const OUString& rCurrentDate) { m_aCurrentDate = rCurrentDate; }
288
289
0
    const OUString& GetCurrentDate() const { return m_aCurrentDate; }
290
291
    /// Formats fCurrentDate and sets it.
292
    void SetCurrentDateValue(double fCurrentDate);
293
294
    /// Parses m_aCurrentDate and returns it.
295
    std::optional<double> GetCurrentDateValue() const;
296
297
    /// Formats m_oSelectedDate, taking m_aDateFormat and m_aDateLanguage into account.
298
    OUString GetDateString(bool bAsISO8601 = false) const;
299
300
3.14k
    void SetPlainText(bool bPlainText) { m_bPlainText = bPlainText; }
301
302
0
    bool GetPlainText() const { return m_bPlainText; }
303
304
3.14k
    void SetComboBox(bool bComboBox) { m_bComboBox = bComboBox; }
305
306
0
    bool GetComboBox() const { return m_bComboBox; }
307
308
3.14k
    void SetDropDown(bool bDropDown) { m_bDropDown = bDropDown; }
309
310
0
    bool GetDropDown() const { return m_bDropDown; }
311
312
    void SetPlaceholderDocPart(const OUString& rPlaceholderDocPart)
313
3.14k
    {
314
3.14k
        m_aPlaceholderDocPart = rPlaceholderDocPart;
315
3.14k
    }
316
317
0
    const OUString& GetPlaceholderDocPart() const { return m_aPlaceholderDocPart; }
318
319
    void SetSelectedListItem(std::optional<size_t> oSelectedListItem)
320
0
    {
321
0
        m_oSelectedListItem = oSelectedListItem;
322
0
    }
323
324
0
    const std::optional<size_t>& GetSelectedListItem() const { return m_oSelectedListItem; }
325
326
    /// Get a copy of selected list item's index,
327
    /// potentially even if the selection is already written out to text (i.e. validated).
328
    std::optional<size_t> GetSelectedListItem(bool bCheckDocModel) const;
329
330
0
    void SetSelectedDate(std::optional<double> oSelectedDate) { m_oSelectedDate = oSelectedDate; }
331
332
0
    const std::optional<double>& GetSelectedDate() const { return m_oSelectedDate; }
333
334
    /// Should this character (during key input) interact with the content control?
335
    bool IsInteractingCharacter(sal_Unicode cCh);
336
337
    /// Given rKeyCode as a keyboard event, should a popup be opened for this content control?
338
    bool ShouldOpenPopup(const vcl::KeyCode& rKeyCode);
339
340
    void dumpAsXml(xmlTextWriterPtr pWriter) const;
341
342
    void SetDataBindingPrefixMappings(const OUString& rDataBindingPrefixMappings)
343
3.14k
    {
344
3.14k
        m_aDataBindingPrefixMappings = rDataBindingPrefixMappings;
345
3.14k
    }
346
347
0
    const OUString& GetDataBindingPrefixMappings() const { return m_aDataBindingPrefixMappings; }
348
349
    void SetDataBindingXpath(const OUString& rDataBindingXpath)
350
3.14k
    {
351
3.14k
        m_aDataBindingXpath = rDataBindingXpath;
352
3.14k
    }
353
354
0
    const OUString& GetDataBindingXpath() const { return m_aDataBindingXpath; }
355
356
    void SetDataBindingStoreItemID(const OUString& rDataBindingStoreItemID)
357
3.14k
    {
358
3.14k
        m_aDataBindingStoreItemID = rDataBindingStoreItemID;
359
3.14k
    }
360
361
0
    const OUString& GetDataBindingStoreItemID() const { return m_aDataBindingStoreItemID; }
362
363
3.14k
    void SetColor(const OUString& rColor) { m_aColor = rColor; }
364
365
0
    const OUString& GetColor() const { return m_aColor; }
366
367
3.14k
    void SetAppearance(const OUString& rAppearance) { m_aAppearance = rAppearance; }
368
369
0
    const OUString& GetAppearance() const { return m_aAppearance; }
370
371
3.14k
    void SetAlias(const OUString& rAlias) { m_aAlias = rAlias; }
372
373
0
    const OUString& GetAlias() const { return m_aAlias; }
374
375
3.14k
    void SetTag(const OUString& rTag) { m_aTag = rTag; }
376
377
0
    const OUString& GetTag() const { return m_aTag; }
378
379
3.14k
    void SetId(sal_Int32 nId) { m_nId = nId; }
380
381
0
    sal_Int32 GetId() const { return m_nId; }
382
383
3.14k
    void SetTabIndex(sal_uInt32 nTabIndex) { m_nTabIndex = nTabIndex; }
384
385
0
    sal_uInt32 GetTabIndex() const { return m_nTabIndex; }
386
387
    // At the design level, define how the control should be locked. No effect at implementation lvl
388
    void SetLock(bool bLockContent, bool bLockControl);
389
3.14k
    void SetLock(const OUString& rLock) { m_aLock = rLock; }
390
391
    // At the design level, get how the control is locked. Does not reflect actual implementation.
392
    std::optional<bool> GetLock(bool bControl) const;
393
0
    const OUString& GetLock() const { return m_aLock; }
394
395
0
    void SetReadWrite(bool bReadWrite) { m_bReadWrite = bReadWrite; }
396
397
    // At the implementation level, define whether the user can directly modify the contents.
398
0
    bool GetReadWrite() const { return m_bReadWrite; }
399
400
3.14k
    void SetMultiLine(const OUString& rMultiline) { m_aMultiLine = rMultiline; }
401
402
0
    const OUString& GetMultiLine() const { return m_aMultiLine; }
403
404
    SwContentControlType GetType() const;
405
406
    // Ballot Box with X
407
    static constexpr OUString CHECKED_STATE = u"\u2612"_ustr;
408
    // Ballot Box
409
    static constexpr OUString UNCHECKED_STATE = u"\u2610"_ustr;
410
};
411
412
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */