Coverage Report

Created: 2026-03-31 11:00

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/svx/source/inc/fmexpl.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
#ifndef INCLUDED_SVX_SOURCE_INC_FMEXPL_HXX
20
#define INCLUDED_SVX_SOURCE_INC_FMEXPL_HXX
21
22
#include <config_options.h>
23
#include <svl/lstner.hxx>
24
#include <svl/SfxBroadcaster.hxx>
25
#include <vcl/window.hxx>
26
#include <sfx2/childwin.hxx>
27
#include <svl/poolitem.hxx>
28
#include <sfx2/bindings.hxx>
29
#include <sfx2/dockwin.hxx>
30
#include <sfx2/ctrlitem.hxx>
31
32
#include <com/sun/star/form/XForm.hpp>
33
#include <com/sun/star/form/XFormComponent.hpp>
34
#include <com/sun/star/beans/PropertyChangeEvent.hpp>
35
#include <com/sun/star/container/XContainerListener.hpp>
36
#include <com/sun/star/beans/XPropertyChangeListener.hpp>
37
#include <com/sun/star/container/XIndexContainer.hpp>
38
39
#include <svx/fmview.hxx>
40
41
#include "fmexch.hxx"
42
#include <vector>
43
#include <set>
44
#include <cppuhelper/implbase.hxx>
45
46
class FmFormShell;
47
class SdrObject;
48
class FmFormModel;
49
class FmFormView;
50
class SdrMarkList;
51
52
53
class FmEntryData;
54
class FmNavInsertedHint final : public SfxHint
55
{
56
    FmEntryData* pEntryData;
57
    sal_uInt32 nPos;
58
59
public:
60
    FmNavInsertedHint( FmEntryData* pInsertedEntryData, sal_uInt32 nRelPos );
61
    virtual ~FmNavInsertedHint() override;
62
63
0
    FmEntryData* GetEntryData() const { return pEntryData; }
64
0
    sal_uInt32 GetRelPos() const { return nPos; }
65
};
66
67
68
class FmNavModelReplacedHint final : public SfxHint
69
{
70
    FmEntryData* pEntryData;    // the data of the entry that has got a new model
71
72
public:
73
    FmNavModelReplacedHint( FmEntryData* pAffectedEntryData );
74
    virtual ~FmNavModelReplacedHint() override;
75
76
0
    FmEntryData* GetEntryData() const { return pEntryData; }
77
};
78
79
80
class FmNavRemovedHint final : public SfxHint
81
{
82
    FmEntryData* pEntryData;
83
84
public:
85
    FmNavRemovedHint( FmEntryData* pInsertedEntryData );
86
    virtual ~FmNavRemovedHint() override;
87
88
0
    FmEntryData* GetEntryData() const { return pEntryData; }
89
};
90
91
92
class FmNavNameChangedHint final : public SfxHint
93
{
94
    FmEntryData*    pEntryData;
95
    OUString          aNewName;
96
97
public:
98
    FmNavNameChangedHint( FmEntryData* pData, OUString aNewName );
99
    virtual ~FmNavNameChangedHint() override;
100
101
0
    FmEntryData*    GetEntryData() const { return pEntryData; }
102
0
    const OUString& GetNewName() const { return aNewName; }
103
};
104
105
106
class FmNavClearedHint final : public SfxHint
107
{
108
public:
109
    FmNavClearedHint();
110
    virtual ~FmNavClearedHint() override;
111
};
112
113
114
class FmNavViewMarksChanged final : public SfxHint
115
{
116
    FmFormView* pView;
117
public:
118
    FmNavViewMarksChanged(FmFormView* pWhichView)
119
0
        : SfxHint(SfxHintId::FmNavViewMarksChanged) { pView = pWhichView; }
120
121
0
    const FmFormView* GetAffectedView() const { return pView; }
122
};
123
124
125
class FmEntryDataList;
126
class FmEntryData
127
{
128
private:
129
    css::uno::Reference< css::uno::XInterface >       m_xNormalizedIFace;
130
    css::uno::Reference< css::beans::XPropertySet >   m_xProperties;
131
    css::uno::Reference< css::container::XChild >     m_xChild;
132
133
protected:
134
    OUString            m_aNormalImage;
135
    OUString            aText;
136
137
    std::unique_ptr<FmEntryDataList>
138
                        pChildList;
139
    FmEntryData*        pParent;
140
141
protected:
142
    void    newObject( const css::uno::Reference< css::uno::XInterface >& _rxIFace );
143
144
public:
145
146
    FmEntryData( FmEntryData* pParentData, const css::uno::Reference< css::uno::XInterface >& _rIFace );
147
    virtual ~FmEntryData();
148
149
0
    void    SetText( const OUString& rText ){ aText = rText; }
150
0
    void    SetParent( FmEntryData* pParentData ){ pParent = pParentData; }
151
152
0
    const OUString& GetNormalImage() const { return m_aNormalImage; }
153
154
0
    const OUString& GetText() const { return aText; }
155
0
    FmEntryData*    GetParent() const { return pParent; }
156
0
    FmEntryDataList* GetChildList() const { return pChildList.get(); }
157
158
    virtual bool IsEqualWithoutChildren( FmEntryData* pEntryData );
159
160
    // note that the interface returned is normalized, i.e. querying the given XInterface of the object
161
    // for XInterface must return the interface itself.
162
    const css::uno::Reference< css::uno::XInterface >& GetElement() const
163
0
    {
164
0
        return m_xNormalizedIFace;
165
0
    }
166
167
    const css::uno::Reference< css::beans::XPropertySet >& GetPropertySet() const
168
0
    {
169
0
        return m_xProperties;
170
0
    }
171
172
    const css::uno::Reference< css::container::XChild >& GetChildIFace() const
173
0
    {
174
0
        return m_xChild;
175
0
    }
176
};
177
178
179
class FmEntryDataList final
180
{
181
private:
182
    std::vector< std::unique_ptr<FmEntryData> > maEntryDataList;
183
184
public:
185
    FmEntryDataList();
186
    ~FmEntryDataList();
187
188
    FmEntryData*    at( size_t Index )
189
0
        { return maEntryDataList.at(Index).get(); }
190
191
0
    size_t          size() const { return maEntryDataList.size(); }
192
    void            removeNoDelete( FmEntryData* pItem );
193
    void            insert( std::unique_ptr<FmEntryData> pItem, size_t Index );
194
    void            clear();
195
};
196
197
198
// FmNavRequestSelectHint - someone tells the NavigatorTree to select certain entries
199
200
typedef std::set<FmEntryData*> FmEntryDataArray;
201
202
class FmNavRequestSelectHint final : public SfxHint
203
{
204
    FmEntryDataArray    m_arredToSelect;
205
    bool                m_bMixedSelection;
206
public:
207
    FmNavRequestSelectHint()
208
0
        : SfxHint(SfxHintId::FmNavRequestSelect),
209
0
          m_bMixedSelection(false)
210
0
    {
211
0
    }
212
213
0
    void SetMixedSelection(bool bMixedSelection) { m_bMixedSelection = bMixedSelection; }
214
0
    bool IsMixedSelection() const { return m_bMixedSelection; }
215
0
    void AddItem(FmEntryData* pEntry) { m_arredToSelect.insert(pEntry); }
216
0
    void ClearItems() { m_arredToSelect.clear(); }
217
0
    FmEntryDataArray& GetItems() { return m_arredToSelect; }
218
};
219
220
221
class FmFormData final : public FmEntryData
222
{
223
    css::uno::Reference< css::form::XForm >           m_xForm;
224
225
public:
226
    FmFormData(const css::uno::Reference< css::form::XForm >& _rxForm, FmFormData* _pParent);
227
    virtual ~FmFormData() override;
228
229
0
    const css::uno::Reference< css::form::XForm >& GetFormIface() const { return m_xForm; }
230
231
    virtual bool IsEqualWithoutChildren( FmEntryData* pEntryData ) override;
232
};
233
234
235
class FmControlData final : public FmEntryData
236
{
237
    css::uno::Reference< css::form::XFormComponent >  m_xFormComponent;
238
239
    OUString GetImage() const;
240
241
public:
242
243
    FmControlData(
244
        const css::uno::Reference< css::form::XFormComponent >& _rxComponent,
245
        FmFormData* _pParent
246
    );
247
    virtual ~FmControlData() override;
248
249
0
    const css::uno::Reference< css::form::XFormComponent >& GetFormComponent() const { return m_xFormComponent; }
250
    virtual bool IsEqualWithoutChildren( FmEntryData* pEntryData ) override;
251
252
    void ModelReplaced(const css::uno::Reference< css::form::XFormComponent >& _rxNew);
253
};
254
255
256
namespace svxform
257
{
258
259
260
    class NavigatorTreeModel;
261
262
    class OFormComponentObserver final
263
        :public ::cppu::WeakImplHelper <   css::beans::XPropertyChangeListener
264
                                        ,   css::container::XContainerListener
265
                                        >
266
    {
267
        ::svxform::NavigatorTreeModel*  m_pNavModel;
268
        sal_uInt32 m_nLocks;
269
        bool   m_bCanUndo;
270
271
    public:
272
        OFormComponentObserver( ::svxform::NavigatorTreeModel* pModel );
273
274
    // XEventListenerListener
275
        virtual void SAL_CALL disposing(const css::lang::EventObject& Source) override;
276
277
    // css::beans::XPropertyChangeListener
278
        virtual void SAL_CALL propertyChange(const css::beans::PropertyChangeEvent& evt) override;
279
280
    // css::container::XContainerListener
281
282
        virtual void SAL_CALL elementInserted(const  css::container::ContainerEvent& rEvent) override;
283
        virtual void SAL_CALL elementReplaced(const  css::container::ContainerEvent& rEvent) override;
284
        virtual void SAL_CALL elementRemoved(const  css::container::ContainerEvent& rEvent) override;
285
286
0
        void Lock() { m_nLocks++; }
287
0
        void UnLock() { m_nLocks--; }
288
0
        bool IsLocked() const { return m_nLocks != 0; }
289
0
        bool CanUndo() const { return m_bCanUndo; }
290
0
        void ReleaseModel() { m_pNavModel = nullptr; }
291
    private:
292
        void Insert(const css::uno::Reference< css::uno::XInterface >& xIface, sal_Int32 nIndex);
293
        void Remove( const css::uno::Reference< css::uno::XInterface >& _rxElement );
294
    };
295
296
    class NavigatorTreeModel final : public SfxBroadcaster
297
                           ,public SfxListener
298
    {
299
        friend class NavigatorTree;
300
        friend class OFormComponentObserver;
301
302
        std::unique_ptr<FmEntryDataList>
303
                                    m_pRootList;
304
        FmFormShell*                m_pFormShell;
305
        FmFormPage*                 m_pFormPage;
306
        FmFormModel*                m_pFormModel;
307
        rtl::Reference<OFormComponentObserver> m_pPropChangeList;
308
309
        void UpdateContent( const css::uno::Reference< css::form::XForms >& xForms );
310
311
        void InsertForm(const css::uno::Reference< css::form::XForm >& xForm, sal_uInt32 nRelPos);
312
        void RemoveForm(FmFormData const * pFormData);
313
314
        void InsertFormComponent(const css::uno::Reference< css::form::XFormComponent >& xComp, sal_uInt32 nRelPos);
315
        void RemoveFormComponent(FmControlData const * pControlData);
316
        void InsertSdrObj(const SdrObject* pSdrObj);
317
        void RemoveSdrObj(const SdrObject* pSdrObj);
318
319
        void ReplaceFormComponent(const css::uno::Reference< css::form::XFormComponent >& xOld, const css::uno::Reference< css::form::XFormComponent >& xNew);
320
321
        void BroadcastMarkedObjects(const SdrMarkList& mlMarked);
322
            // send a RequestSelectHint with the currently selected objects
323
        bool InsertFormComponent(FmNavRequestSelectHint& rHint, SdrObject* pObject);
324
            // is a helper for previous, manages the ... in SdrObjGroups;
325
            // returns sal_True if the object is a FormComponent (or recursively consists only of such)
326
327
    public:
328
        NavigatorTreeModel();
329
        virtual ~NavigatorTreeModel() override;
330
331
        void FillBranch( FmFormData* pParentData );
332
        void UpdateContent( FmFormShell* pNewShell );
333
334
        void Insert(FmEntryData* pEntryData, sal_uInt32 nRelPos = SAL_MAX_UINT32,
335
                                             bool bAlterModel = false);
336
        void Remove(FmEntryData* pEntryData, bool bAlterModel = false);
337
338
        static bool Rename( FmEntryData* pEntryData, const OUString& rNewText );
339
340
        void Clear();
341
        void SetModified();
342
343
        css::uno::Reference< css::form::XForms >    GetForms() const;
344
0
        FmFormShell*        GetFormShell() const { return m_pFormShell; }
345
0
        FmFormPage*         GetFormPage() const { return m_pFormPage; }
346
        FmEntryData*        FindData( const css::uno::Reference< css::uno::XInterface >& xElement, FmEntryDataList* pDataList, bool bRecurs=true );
347
        FmEntryData*        FindData( const OUString& rText, FmFormData const * pParentData, bool bRecurs );
348
0
        FmEntryDataList*    GetRootList() const { return m_pRootList.get(); }
349
        static css::uno::Reference< css::container::XIndexContainer >   GetFormComponents( FmFormData const * pParentFormData );
350
351
        virtual void Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) override;
352
    };
353
354
    class NavigatorTree;
355
356
    class NavigatorTreeDropTarget final : public DropTargetHelper
357
    {
358
    private:
359
        NavigatorTree& m_rTreeView;
360
361
        virtual sal_Int8 AcceptDrop( const AcceptDropEvent& rEvt ) override;
362
        virtual sal_Int8 ExecuteDrop( const ExecuteDropEvent& rEvt ) override;
363
364
    public:
365
        NavigatorTreeDropTarget(NavigatorTree& rTreeView);
366
    };
367
368
    typedef std::set<std::unique_ptr<weld::TreeIter>> SvLBoxEntrySortedArray;
369
370
    class NavigatorTree final : public SfxListener
371
    {
372
        std::unique_ptr<weld::TreeView> m_xTreeView;
373
        NavigatorTreeDropTarget m_aDropTargetHelper;
374
375
        enum SELDATA_ITEMS      { SDI_DIRTY, SDI_ALL, SDI_NORMALIZED, SDI_NORMALIZED_FORMARK };
376
377
        Timer               m_aSynchronizeTimer;
378
        // the meta-data about my current selection
379
        SvLBoxEntrySortedArray  m_arrCurrentSelection;
380
        // the entries which, in the view, are currently marked as "cut" (painted semi-transparent)
381
        ListBoxEntrySet         m_aCutEntries;
382
383
        ::svxform::OControlExchangeHelper m_aControlExchange;
384
385
        std::unique_ptr<NavigatorTreeModel> m_pNavModel;
386
        std::unique_ptr<weld::TreeIter> m_xRootEntry;
387
        std::unique_ptr<weld::TreeIter> m_xEditEntry;
388
389
        ImplSVEvent *       nEditEvent;
390
391
        SELDATA_ITEMS       m_sdiState;
392
393
        sal_uInt16          m_nSelectLock;
394
        sal_uInt16          m_nFormsSelected;
395
        sal_uInt16          m_nControlsSelected;
396
        sal_uInt16          m_nHiddenControls;      // (the number is included in m_nControlsSelected)
397
398
        bool            m_bDragDataDirty        : 1;    // ditto
399
        bool            m_bPrevSelectionMixed   : 1;
400
        bool            m_bRootSelected         : 1;
401
        bool            m_bInitialUpdate        : 1;    // am I the first time in the UpdateContent?
402
        bool            m_bKeyboardCut          : 1;
403
        bool            m_bEditing              : 1;
404
405
        FmControlData*  NewControl(const OUString& rServiceName, const weld::TreeIter& rParentEntry, bool bEditName);
406
        void            NewForm(const weld::TreeIter& rParentEntry);
407
        std::unique_ptr<weld::TreeIter> Insert(const FmEntryData* pEntryData, int nRelPos);
408
        void            Remove( FmEntryData* pEntryData );
409
410
411
        void CollectSelectionData(SELDATA_ITEMS sdiHow);
412
            // Collects the currently selected entries in m_arrCurrentSelection, normalizes the list if requested.
413
            // - SDI_NORMALIZED simply means that all entries that already have a selected ancestor are not collected.
414
            // - SDI_NORMALIZED_FORMARK means that the procedure is the same as for SDI_NORMALIZED,
415
            //   but entries whose direct parent is not selected are collected (independent of the
416
            //   status of further ancestors). The same applies for forms that are selected,
417
            //   regardless of the status of any ancestors.
418
            // For both normalized modes, the m_nFormsSelected, ... contain the correct number,
419
            // even if not all of these entries end up in m_arrCurrentSelection.
420
            // SDI_DIRTY is of course not allowed as a parameter.
421
422
        // a single interface for all selected entries
423
        void    ShowSelectionProperties(bool bForce = false);
424
        // delete all selected elements
425
        void    DeleteSelection();
426
427
        void SynchronizeSelection(FmEntryDataArray& arredToSelect);
428
            // after calling this method, exactly the entries marked in the array are selected
429
        void SynchronizeSelection();
430
            // makes the same, takes the MarkList of the View
431
        void SynchronizeMarkList();
432
            // reverse direction of SynchronizeMarkList: selects in the view all controls corresponding to the current selection
433
434
        void CollectObjects(FmFormData const * pFormData, bool bDeep, ::std::set< css::uno::Reference< css::form::XFormComponent > >& _rObjects);
435
436
        // in the Select I usually update the Marklist of the corresponding view,
437
        // with the following functions I can control the locking of this behavior
438
0
        void LockSelectionHandling() { ++m_nSelectLock; }
439
0
        void UnlockSelectionHandling() { --m_nSelectLock; }
440
0
        bool IsSelectionHandlingLocked() const { return m_nSelectLock>0; }
441
442
0
        bool IsEditingActive() const { return m_bEditing; }
443
444
        static bool IsHiddenControl(FmEntryData const * pEntryData);
445
446
        DECL_LINK( KeyInputHdl, const KeyEvent&, bool );
447
        DECL_LINK( PopupMenuHdl, const CommandEvent&, bool );
448
449
        DECL_LINK(EditingEntryHdl, const weld::TreeIter&, bool);
450
        typedef std::pair<const weld::TreeIter&, OUString> IterString;
451
        DECL_LINK(EditedEntryHdl, const IterString&, bool);
452
453
        DECL_LINK( OnEdit, void*, void );
454
455
        DECL_LINK( OnEntrySelDesel, weld::TreeView&, void );
456
        DECL_LINK( OnSynchronizeTimer, Timer*, void );
457
458
        DECL_LINK( OnClipboardAction, OLocalExchange&, void );
459
460
        DECL_LINK( DragBeginHdl, bool&, bool );
461
462
    public:
463
        NavigatorTree(std::unique_ptr<weld::TreeView> xTreeView);
464
        virtual ~NavigatorTree() override;
465
466
        void Clear();
467
        void UpdateContent( FmFormShell* pFormShell );
468
        void MarkViewObj( FmFormData const * pFormData, bool bDeep );
469
        void MarkViewObj( FmControlData const * pControlData );
470
        void UnmarkAllViewObj();
471
472
0
        void GrabFocus() { m_xTreeView->grab_focus(); }
473
474
        bool IsFormEntry(const weld::TreeIter& rEntry);
475
        bool IsFormComponentEntry(const weld::TreeIter& rEntry);
476
477
        OUString GenerateName(const FmEntryData& rEntryData);
478
479
0
        NavigatorTreeModel*    GetNavModel() const { return m_pNavModel.get(); }
480
        std::unique_ptr<weld::TreeIter> FindEntry(FmEntryData* pEntryData);
481
482
        virtual void Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) override;
483
484
0
        weld::TreeView& get_widget() { return *m_xTreeView; }
485
486
        sal_Int8    AcceptDrop(const AcceptDropEvent& rEvt);
487
        sal_Int8    ExecuteDrop(const ExecuteDropEvent& rEvt);
488
489
    private:
490
        sal_Int8    implAcceptDataTransfer( const DataFlavorExVector& _rFlavors, sal_Int8 _nAction, const weld::TreeIter* _pTargetEntry, bool _bDnD );
491
492
        sal_Int8    implExecuteDataTransfer( const OControlTransferData& _rData, sal_Int8 _nAction, const Point& _rDropPos, bool _bDnD );
493
        sal_Int8    implExecuteDataTransfer( const OControlTransferData& _rData, sal_Int8 _nAction, const weld::TreeIter* _pTargetEntry, bool _bDnD );
494
495
        // check if a cut, copy, or drag operation can be started in the current situation
496
        bool        implAllowExchange( sal_Int8 _nAction, bool* _pHasNonHidden = nullptr );
497
        // check if a paste with the current clipboard content can be accepted
498
        bool        implAcceptPaste( );
499
500
        // fills m_aControlExchange in preparation of a DnD or clipboard operation
501
        bool        implPrepareExchange( sal_Int8 _nAction );
502
503
        void        ModelHasRemoved(const weld::TreeIter* _pEntry);
504
505
        void        doPaste();
506
        void        doCopy();
507
        void        doCut();
508
509
0
        bool    doingKeyboardCut( ) const { return m_bKeyboardCut; }
510
    };
511
512
    class NavigatorFrame final : public SfxDockingWindow, public SfxControllerItem
513
    {
514
    private:
515
        std::unique_ptr<NavigatorTree> m_xNavigatorTree;
516
517
        virtual bool Close() override;
518
        virtual void GetFocus() override;
519
        virtual Size CalcDockingSize( SfxChildAlignment ) override;
520
        virtual SfxChildAlignment CheckAlignment( SfxChildAlignment, SfxChildAlignment ) override;
521
522
        using SfxDockingWindow::StateChanged;
523
524
    public:
525
        NavigatorFrame( SfxBindings *pBindings, SfxChildWindow *pMgr,
526
                       vcl::Window* pParent );
527
        virtual ~NavigatorFrame() override;
528
        virtual void dispose() override;
529
530
        void UpdateContent( FmFormShell* pFormShell );
531
        void StateChangedAtToolBoxControl( sal_uInt16 nSID, SfxItemState eState, const SfxPoolItem* pState ) override;
532
        void FillInfo( SfxChildWinInfo& rInfo ) const override;
533
    };
534
535
    class UNLESS_MERGELIBS(SVXCORE_DLLPUBLIC) NavigatorFrameManager final : public SfxChildWindow
536
    {
537
    public:
538
        SVX_DLLPRIVATE NavigatorFrameManager( vcl::Window *pParent, sal_uInt16 nId, SfxBindings *pBindings,
539
                          SfxChildWinInfo *pInfo );
540
        SFX_DECL_CHILDWINDOW( NavigatorFrameManager );
541
    };
542
}
543
544
#endif // INCLUDED_SVX_SOURCE_INC_FMEXPL_HXX
545
546
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */