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/.
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 #ifndef INCLUDED_SFX2_ITEMCONNECT_HXX
21 #define INCLUDED_SFX2_ITEMCONNECT_HXX
23 #include <sal/config.h>
24 #include <sfx2/dllapi.h>
28 #include <sfx2/itemwrapper.hxx>
29 #include <sfx2/controlwrapper.hxx>
33 typedef int ItemConnFlags
;
35 /** No special state for the connection. */
36 const ItemConnFlags ITEMCONN_NONE
= 0x0000;
38 /** Connection is inactive - virtual functions will not be called. */
39 const ItemConnFlags ITEMCONN_INACTIVE
= 0x0001;
41 /** Enable control(s), if the item is known. */
42 const ItemConnFlags ITEMCONN_ENABLE_KNOWN
= 0x0010;
43 /** Disable control(s), if the item is unknown. */
44 const ItemConnFlags ITEMCONN_DISABLE_UNKNOWN
= 0x0020;
45 /** Show control(s), if the item is known. */
46 const ItemConnFlags ITEMCONN_SHOW_KNOWN
= 0x0040;
47 /** Hide control(s), if the item is unknown. */
48 const ItemConnFlags ITEMCONN_HIDE_UNKNOWN
= 0x0080;
50 /** Default value for constructors. */
51 const ItemConnFlags ITEMCONN_DEFAULT
= ITEMCONN_NONE
;
54 // Base connection classes
57 /** A helper for SfxTabPages to connect controls to items.
59 This is the base class of all control connection classes. Their purpose is
60 to connect one or more controls from an SfxTabPage with an item from an
61 item set. The goal is to omit any additional code in the virtual functions
62 Reset() and FillItemSet() in classes derived from SfxTabPage.
64 Examples of connections:
65 - A check box with an SfxBoolItem,
66 - A metric (spin) field with an SfxInt32Item.
67 - A group of radio buttons with an SfxEnumItem.
69 Each SfxTabPage will contain a list of connection objects (derived from
70 this class). The connection objects remember the item and control(s) they
71 have to work on. The SfxTabPage will call the DoApplyFlags(), DoReset(),
72 and DoFillItemSet() functions of all connection objects it knows. The code
73 to initialize control(s) from the item value and fill the item from
74 control(s) has to be written only once for each control type.
76 Additional flags passed in the constructor allow to control the behaviour
77 of the control(s) if the item is supported/unsupported in the currently
78 used item set. For example, it is possible to specify that a control will
79 be disabled or hidden if the item is not supported. This is done before
82 The special flag ITEMCONN_CLONE_ITEM controls how to create new items in
83 the DoFillItemSet() function. The standard (and faster) method is to create
84 a temporary item on the stack and put it into the item set. But this does
85 not work if the item set expects a special item type derived from a common
86 item class, i.e. a Boolean item derived from SfxBoolItem providing special
87 item representation text. As this code does not know the item type, the
88 item cannot be created on the stack. For this case the flag specifies to
89 use the virtual Clone() method of the pool default item. This will create
90 an item of the correct type but can still be used in conjunction with i.e.
91 the standard BoolItemWrapper.
93 How to use the item connection feature:
95 A) Single item <-> single control connection
97 Example: An SfxBoolItem and a check box.
99 A1) Create a new item wrapper class derived from the SingleItemWrapper
100 template, or use the template directly, or use one of the
101 predefined item wrappers. See documentation of the
102 SingleItemWrapper template for details (itemwrapper.hxx).
103 A2) Create a new control wrapper class derived from the
104 SingleControlWrapper template and implement the abstract functions,
105 or use one of the predefined control wrappers. See documentation of
106 the SingleControlWrapper template for details (controlwrapper.hxx).
107 A3) Create a new connection class derived from one of the following
108 base classes, and implement the abstract functions, or use the
109 ItemControlConnection template directly, or use one of the
110 predefined connections.
111 A4) Create connection objects in the constructor of the tab page, and
112 insert them into the tab page with SfxTabPage::AddItemConnection().
113 A5) Remove old code from the tab page's Reset() and FillItemSet()
114 functions, if necessary.
116 B) Single item <-> multiple controls connections
118 B1) See step A1. If the item contains multiple values (and not a
119 structure that contains all the values for the different controls),
120 the best way is to use the IdentItemWrapper template, that works
121 with the item itself. This way it is possible to provide a 'data
122 type' that contains the values for all controls.
123 B2) Create a new control wrapper class derived from the
124 MultiControlWrapper template. Add single control wrapper members
125 for all controls to this class and register them in the
126 constructor, using the RegisterControlWrapper() function. Implement
127 the abstract functions GetControlValue() and SetControlValue().
128 These functions should call the respective functions of the own
129 single control wrappers and either fill a new data object (the item
130 itself in most cases, see step B1) with all the values from the
131 controls, or fill all the controls from the data object.
132 B3) Create a new connection class derived from ItemControlConnection,
133 or use the ItemControlConnection template directly. The multiple
134 control wrapper from step B2 acts like a single control, therefore
135 it is possible to use the ItemControlConnection.
136 B4) See steps A4 and A5.
138 C) Multiple items <-> single control connections
142 D) Multiple items <-> multiple controls connections
146 The current tree of base classes/templates and standard connections:
150 +- DummyItemConnection [1]
152 +- ItemControlConnection< ItemWrpT, ControlWrpT >
154 | +- CheckBoxConnection [1]
156 | +- NumericConnection< ItemWrpT > [1]
158 | | +- [ValueType]NumericConnection [1] [2]
160 | +- MetricConnection< ItemWrpT > [1]
162 | | +- [ValueType]MetricConnection [1] [2]
164 | +- ListBoxConnection< ItemWrpT > [1]
166 | | +- [ValueType]ListBoxConnection [1] [2]
168 | +- ValueSetConnection< ItemWrpT > [1]
170 | +- [ValueType]ValueSetConnection [1] [2]
172 +- ItemConnectionArray [1]
175 [1] Standard connections ready to use.
176 [2] [ValueType] is one of Int16, UInt16, Int32, UInt32.
178 class SFX2_DLLPUBLIC ItemConnectionBase
181 virtual ~ItemConnectionBase();
183 /** Returns true if this connection is active. */
184 bool IsActive() const;
186 /** Calls the virtual ApplyFlags() function, if connection is active. */
187 void DoApplyFlags( const SfxItemSet
* pItemSet
);
188 /** Calls the virtual Reset() function, if connection is active. */
189 void DoReset( const SfxItemSet
* pItemSet
);
190 /** Calls the virtual FillItemSet() function, if connection is active. */
191 bool DoFillItemSet( SfxItemSet
& rDestSet
, const SfxItemSet
& rOldSet
);
194 explicit ItemConnectionBase( ItemConnFlags nFlags
= ITEMCONN_DEFAULT
);
196 /** Derived classes implement actions according to current flags here. */
197 virtual void ApplyFlags( const SfxItemSet
* pItemSet
) = 0;
198 /** Derived classes implement initializing controls from item sets here. */
199 virtual void Reset( const SfxItemSet
* pItemSet
) = 0;
200 /** Derived classes implement filling item sets from controls here. */
201 virtual bool FillItemSet( SfxItemSet
& rDestSet
, const SfxItemSet
& rOldSet
) = 0;
203 /** Returns whether to enable a control, according to current flags. */
204 TriState
GetEnableState( bool bKnown
) const;
205 /** Returns whether to show a control, according to current flags. */
206 TriState
GetShowState( bool bKnown
) const;
209 ItemConnectionBase( const ItemConnectionBase
& ) = delete;
210 ItemConnectionBase
& operator=( const ItemConnectionBase
& ) = delete;
212 ItemConnFlags mnFlags
; /// Flags for additional options.
216 /** Base class template for single item <-> single control connection objects.
218 This template uses functions provided by the SingleItemWrapper and the
219 SingleControlWrapper template classes. The virtual functions ApplyFlags(),
220 Reset(), and FillItemSet() are implemented here in a generic way using the
221 virtual functions of the wrapper classes. Derived classes only have to
222 create or otherwise provide appropriate wrappers.
224 template< typename ItemWrpT
, typename ControlWrpT
>
225 class ItemControlConnection
: public ItemConnectionBase
228 typedef ItemWrpT ItemWrapperType
;
229 typedef ControlWrpT ControlWrapperType
;
230 typedef ItemControlConnection
< ItemWrpT
, ControlWrpT
> ItemControlConnectionType
;
231 typedef typename
ItemWrpT::ItemType ItemType
;
232 typedef typename
ItemWrpT::ItemValueType ItemValueType
;
233 typedef typename
ControlWrpT::ControlType ControlType
;
234 typedef typename
ControlWrpT::ControlValueType ControlValueType
;
236 typedef std::unique_ptr
< ItemWrpT
> ItemWrapperRef
;
237 typedef std::unique_ptr
< ControlWrpT
> ControlWrapperRef
;
239 /** Receives pointer to a newly created control wrapper.
240 @descr Takes ownership of the control wrapper. */
241 explicit ItemControlConnection( sal_uInt16 nSlot
, ControlWrpT
* pNewCtrlWrp
,
242 ItemConnFlags nFlags
= ITEMCONN_DEFAULT
);
244 /** Convenience constructor. Receives reference to a control directly.
245 @descr May only be used, if ControlWrpT::ControlWrpT( ControlType& )
246 constructor exists. */
247 explicit ItemControlConnection( sal_uInt16 nSlot
, ControlType
& rControl
,
248 ItemConnFlags nFlags
= ITEMCONN_DEFAULT
);
250 virtual ~ItemControlConnection();
253 /** Actions according to current flags for the control. */
254 virtual void ApplyFlags( const SfxItemSet
* pItemSet
) override
;
255 /** Resets the control according to the item contents. */
256 virtual void Reset( const SfxItemSet
* pItemSet
) override
;
257 /** Fills the item set according to the control's state. */
258 virtual bool FillItemSet( SfxItemSet
& rDestSet
, const SfxItemSet
& rOldSet
) override
;
260 ItemWrapperType maItemWrp
;
261 ControlWrapperRef mxCtrlWrp
;
265 // Standard connections
268 /** This is a helper class to enable/disable/show/hide a control only.
270 This class does nothing special in the Reset() and FillItemSet() functions.
271 It can be used to control the visibility of i.e. fixed lines or fixed texts
272 related to the availability of an item by passing the appropriate flags to
273 the constructor of this connection.
275 class SFX2_DLLPUBLIC DummyItemConnection
:
276 public ItemConnectionBase
, public DummyWindowWrapper
279 explicit DummyItemConnection( sal_uInt16 nSlot
, vcl::Window
& rWindow
,
280 ItemConnFlags nFlags
= ITEMCONN_DEFAULT
);
283 virtual void ApplyFlags( const SfxItemSet
* pItemSet
) override
;
284 virtual void Reset( const SfxItemSet
* pItemSet
) override
;
285 virtual bool FillItemSet( SfxItemSet
& rDestSet
, const SfxItemSet
& rOldSet
) override
;
292 /** Connection between an SfxBoolItem and a VCL CheckBox. */
293 typedef ItemControlConnection
< BoolItemWrapper
, CheckBoxWrapper
> CheckBoxConnection
;
296 /** Connection between an item and the VCL MetricField.
298 Adds support of different field units during control value <-> item value
299 conversion. The field unit passed to the constructor applies for the item
300 values, while the field unit used in the control has to be set at the
303 template< typename ItemWrpT
>
304 class MetricConnection
: public ItemControlConnection
< ItemWrpT
,
305 MetricFieldWrapper
< typename
ItemWrpT::ItemValueType
> >
307 typedef ItemControlConnection
< ItemWrpT
,
308 MetricFieldWrapper
< typename
ItemWrpT::ItemValueType
> >
309 ItemControlConnectionType
;
312 typedef typename
ItemControlConnectionType::ControlWrapperType MetricFieldWrapperType
;
314 explicit MetricConnection( sal_uInt16 nSlot
, MetricField
& rField
,
315 FieldUnit eItemUnit
= FUNIT_NONE
, ItemConnFlags nFlags
= ITEMCONN_DEFAULT
);
319 /** Connection between an item and a VCL ListBox.
321 Optionally a map can be passed that maps list box positions to item values.
322 This map MUST be terminated with an entry containing
323 WRAPPER_LISTBOX_ENTRY_NOTFOUND as list box position. The item value
324 contained in this last entry is used as default item value in case of an
327 template< typename ItemWrpT
>
328 class ListBoxConnection
: public ItemControlConnection
< ItemWrpT
,
329 ListBoxWrapper
< typename
ItemWrpT::ItemValueType
> >
331 typedef ItemControlConnection
< ItemWrpT
,
332 ListBoxWrapper
< typename
ItemWrpT::ItemValueType
> >
333 ItemControlConnectionType
;
336 typedef typename
ItemControlConnectionType::ControlWrapperType ListBoxWrapperType
;
337 typedef typename
ListBoxWrapperType::MapEntryType MapEntryType
;
339 explicit ListBoxConnection( sal_uInt16 nSlot
, ListBox
& rListBox
,
340 const MapEntryType
* pMap
= nullptr, ItemConnFlags nFlags
= ITEMCONN_DEFAULT
);
344 /** Connection between an item and an SVTOOLS ValueSet.
346 Optionally a map can be passed that maps value set identifiers to item
347 values. This map MUST be terminated with an entry containing
348 WRAPPER_VALUESET_ITEM_NOTFOUND as value set identifier. The item value
349 contained in this last entry is used as default item value in case of an
352 template< typename ItemWrpT
>
353 class ValueSetConnection
: public ItemControlConnection
< ItemWrpT
,
354 ValueSetWrapper
< typename
ItemWrpT::ItemValueType
> >
356 typedef ItemControlConnection
< ItemWrpT
,
357 ValueSetWrapper
< typename
ItemWrpT::ItemValueType
> >
358 ItemControlConnectionType
;
361 typedef typename
ItemControlConnectionType::ControlWrapperType ValueSetWrapperType
;
362 typedef typename
ValueSetWrapperType::MapEntryType MapEntryType
;
364 explicit ValueSetConnection( sal_uInt16 nSlot
, ValueSet
& rValueSet
,
365 const MapEntryType
* pMap
= nullptr, ItemConnFlags nFlags
= ITEMCONN_DEFAULT
);
369 // Array of connections
372 class ItemConnectionArrayImpl
;
374 /** A container of connection objects.
376 This is a connection with the only purpose to contain other connection
377 objects. This way it is possible to create a tree structure of connections
378 for a convenient connection management. This class is used by the class
379 SfxTabPage to store all connections.
381 class ItemConnectionArray
: public ItemConnectionBase
384 explicit ItemConnectionArray();
385 virtual ~ItemConnectionArray();
387 /** Adds a new connection to the list.
388 @descr Takes ownership of the connection! */
389 void AddConnection( ItemConnectionBase
* pConnection
);
392 virtual void ApplyFlags( const SfxItemSet
* pItemSet
) override
;
393 virtual void Reset( const SfxItemSet
* pItemSet
) override
;
394 virtual bool FillItemSet( SfxItemSet
& rDestSet
, const SfxItemSet
& rOldSet
) override
;
397 std::unique_ptr
< ItemConnectionArrayImpl
> mxImpl
;
401 // *** Implementation of template functions ***
404 // Base connection classes
407 template< typename ItemWrpT
, typename ControlWrpT
>
408 ItemControlConnection
< ItemWrpT
, ControlWrpT
>::ItemControlConnection(
409 sal_uInt16 nSlot
, ControlWrpT
* pNewCtrlWrp
, ItemConnFlags nFlags
) :
410 ItemConnectionBase( nFlags
),
412 mxCtrlWrp( pNewCtrlWrp
)
416 template< typename ItemWrpT
, typename ControlWrpT
>
417 ItemControlConnection
< ItemWrpT
, ControlWrpT
>::ItemControlConnection(
418 sal_uInt16 nSlot
, ControlType
& rControl
, ItemConnFlags nFlags
) :
419 ItemConnectionBase( nFlags
),
421 mxCtrlWrp( new ControlWrpT( rControl
) )
425 template< typename ItemWrpT
, typename ControlWrpT
>
426 ItemControlConnection
< ItemWrpT
, ControlWrpT
>::~ItemControlConnection()
430 template< typename ItemWrpT
, typename ControlWrpT
>
431 void ItemControlConnection
< ItemWrpT
, ControlWrpT
>::ApplyFlags( const SfxItemSet
* pItemSet
)
433 bool bKnown
= ItemWrapperHelper::IsKnownItem( *pItemSet
, maItemWrp
.GetSlotId() );
434 mxCtrlWrp
->ModifyControl( GetEnableState( bKnown
), GetShowState( bKnown
) );
437 template< typename ItemWrpT
, typename ControlWrpT
>
438 void ItemControlConnection
< ItemWrpT
, ControlWrpT
>::Reset( const SfxItemSet
* pItemSet
)
440 const ItemType
* pItem
= maItemWrp
.GetUniqueItem( *pItemSet
);
441 mxCtrlWrp
->SetControlDontKnow( pItem
== nullptr );
443 mxCtrlWrp
->SetControlValue( maItemWrp
.GetItemValue( *pItem
) );
446 template< typename ItemWrpT
, typename ControlWrpT
>
447 bool ItemControlConnection
< ItemWrpT
, ControlWrpT
>::FillItemSet(
448 SfxItemSet
& rDestSet
, const SfxItemSet
& rOldSet
)
450 const ItemType
* pOldItem
= maItemWrp
.GetUniqueItem( rOldSet
);
451 bool bChanged
= false;
452 if( !mxCtrlWrp
->IsControlDontKnow() )
454 // first store the control value in a local variable
455 ControlValueType
aCtrlValue( mxCtrlWrp
->GetControlValue() );
456 // convert to item value type -> possible to convert i.e. from 'T' to 'const T&'
457 ItemValueType
aNewValue( aCtrlValue
);
458 // do not rely on existence of ItemValueType::operator!=
459 if( !pOldItem
|| !(maItemWrp
.GetItemValue( *pOldItem
) == aNewValue
) )
461 sal_uInt16 nWhich
= ItemWrapperHelper::GetWhichId( rDestSet
, maItemWrp
.GetSlotId() );
462 std::unique_ptr
< ItemType
> xItem(
463 static_cast< ItemType
* >( maItemWrp
.GetDefaultItem( rDestSet
).Clone() ) );
464 xItem
->SetWhich( nWhich
);
465 maItemWrp
.SetItemValue( *xItem
, aNewValue
);
466 rDestSet
.Put( *xItem
);
471 ItemWrapperHelper::RemoveDefaultItem( rDestSet
, rOldSet
, maItemWrp
.GetSlotId() );
476 // Standard connections
479 template< typename ItemWrpT
>
480 MetricConnection
< ItemWrpT
>::MetricConnection(
481 sal_uInt16 nSlot
, MetricField
& rField
, FieldUnit eItemUnit
, ItemConnFlags nFlags
) :
482 ItemControlConnectionType( nSlot
, new MetricFieldWrapperType( rField
, eItemUnit
), nFlags
)
487 template< typename ItemWrpT
>
488 ListBoxConnection
< ItemWrpT
>::ListBoxConnection(
489 sal_uInt16 nSlot
, ListBox
& rListBox
, const MapEntryType
* pMap
, ItemConnFlags nFlags
) :
490 ItemControlConnectionType( nSlot
, new ListBoxWrapperType( rListBox
, pMap
), nFlags
)
495 template< typename ItemWrpT
>
496 ValueSetConnection
< ItemWrpT
>::ValueSetConnection(
497 sal_uInt16 nSlot
, ValueSet
& rValueSet
, const MapEntryType
* pMap
, ItemConnFlags nFlags
) :
498 ItemControlConnectionType( nSlot
, new ValueSetWrapperType( rValueSet
, pMap
), nFlags
)
507 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */