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 the flags passed in the constructor. */
184 inline ItemConnFlags
GetFlags() const { return mnFlags
; }
186 /** Returns true if this connection is active. */
187 bool IsActive() const;
189 /** Calls the virtual ApplyFlags() function, if connection is active. */
190 void DoApplyFlags( const SfxItemSet
& rItemSet
);
191 /** Calls the virtual Reset() function, if connection is active. */
192 void DoReset( const SfxItemSet
& rItemSet
);
193 /** Calls the virtual FillItemSet() function, if connection is active. */
194 bool DoFillItemSet( SfxItemSet
& rDestSet
, const SfxItemSet
& rOldSet
);
197 explicit ItemConnectionBase( ItemConnFlags nFlags
= ITEMCONN_DEFAULT
);
199 /** Derived classes implement actions according to current flags here. */
200 virtual void ApplyFlags( const SfxItemSet
& rItemSet
) = 0;
201 /** Derived classes implement initializing controls from item sets here. */
202 virtual void Reset( const SfxItemSet
& rItemSet
) = 0;
203 /** Derived classes implement filling item sets from controls here. */
204 virtual bool FillItemSet( SfxItemSet
& rDestSet
, const SfxItemSet
& rOldSet
) = 0;
206 /** Returns whether to enable a control, according to current flags. */
207 TriState
GetEnableState( bool bKnown
) const;
208 /** Returns whether to show a control, according to current flags. */
209 TriState
GetShowState( bool bKnown
) const;
212 ItemConnectionBase( const ItemConnectionBase
& ) SAL_DELETED_FUNCTION
;
213 ItemConnectionBase
& operator=( const ItemConnectionBase
& ) SAL_DELETED_FUNCTION
;
215 ItemConnFlags mnFlags
; /// Flags for additional options.
220 /** Base class template for single item <-> single control connection objects.
222 This template uses functions provided by the SingleItemWrapper and the
223 SingleControlWrapper template classes. The virtual functions ApplyFlags(),
224 Reset(), and FillItemSet() are implemented here in a generic way using the
225 virtual functions of the wrapper classes. Derived classes only have to
226 create or otherwise provide appropriate wrappers.
228 template< typename ItemWrpT
, typename ControlWrpT
>
229 class ItemControlConnection
: public ItemConnectionBase
232 typedef ItemWrpT ItemWrapperType
;
233 typedef ControlWrpT ControlWrapperType
;
234 typedef ItemControlConnection
< ItemWrpT
, ControlWrpT
> ItemControlConnectionType
;
235 typedef typename
ItemWrpT::ItemType ItemType
;
236 typedef typename
ItemWrpT::ItemValueType ItemValueType
;
237 typedef typename
ControlWrpT::ControlType ControlType
;
238 typedef typename
ControlWrpT::ControlValueType ControlValueType
;
240 typedef std::unique_ptr
< ItemWrpT
> ItemWrapperRef
;
241 typedef std::unique_ptr
< ControlWrpT
> ControlWrapperRef
;
243 /** Receives pointer to a newly created control wrapper.
244 @descr Takes ownership of the control wrapper. */
245 explicit ItemControlConnection( sal_uInt16 nSlot
, ControlWrpT
* pNewCtrlWrp
,
246 ItemConnFlags nFlags
= ITEMCONN_DEFAULT
);
248 /** Convenience constructor. Receives reference to a control directly.
249 @descr May only be used, if ControlWrpT::ControlWrpT( ControlType& )
250 constructor exists. */
251 explicit ItemControlConnection( sal_uInt16 nSlot
, ControlType
& rControl
,
252 ItemConnFlags nFlags
= ITEMCONN_DEFAULT
);
254 virtual ~ItemControlConnection();
257 /** Actions according to current flags for the control. */
258 virtual void ApplyFlags( const SfxItemSet
& rItemSet
) SAL_OVERRIDE
;
259 /** Resets the control according to the item contents. */
260 virtual void Reset( const SfxItemSet
& rItemSet
) SAL_OVERRIDE
;
261 /** Fills the item set according to the control's state. */
262 virtual bool FillItemSet( SfxItemSet
& rDestSet
, const SfxItemSet
& rOldSet
) SAL_OVERRIDE
;
264 ItemWrapperType maItemWrp
;
265 ControlWrapperRef mxCtrlWrp
;
269 // Standard connections
272 /** This is a helper class to enable/disable/show/hide a control only.
274 This class does nothing special in the Reset() and FillItemSet() functions.
275 It can be used to control the visibility of i.e. fixed lines or fixed texts
276 related to the availability of an item by passing the appropriate flags to
277 the constructor of this connection.
279 class SFX2_DLLPUBLIC DummyItemConnection
:
280 public ItemConnectionBase
, public DummyWindowWrapper
283 explicit DummyItemConnection( sal_uInt16 nSlot
, vcl::Window
& rWindow
,
284 ItemConnFlags nFlags
= ITEMCONN_DEFAULT
);
287 virtual void ApplyFlags( const SfxItemSet
& rItemSet
) SAL_OVERRIDE
;
288 virtual void Reset( const SfxItemSet
& rItemSet
) SAL_OVERRIDE
;
289 virtual bool FillItemSet( SfxItemSet
& rDestSet
, const SfxItemSet
& rOldSet
) SAL_OVERRIDE
;
297 /** Connection between an SfxBoolItem and a VCL CheckBox. */
298 typedef ItemControlConnection
< BoolItemWrapper
, CheckBoxWrapper
> CheckBoxConnection
;
302 /** Connection between an item and the VCL NumericField. */
303 template< typename ItemWrpT
>
304 class NumericConnection
: public ItemControlConnection
< ItemWrpT
,
305 NumericFieldWrapper
< typename
ItemWrpT::ItemValueType
> >
307 typedef ItemControlConnection
< ItemWrpT
,
308 NumericFieldWrapper
< typename
ItemWrpT::ItemValueType
> >
309 ItemControlConnectionType
;
312 typedef typename
ItemControlConnectionType::ControlWrapperType NumericFieldWrapperType
;
314 explicit NumericConnection( sal_uInt16 nSlot
, NumericField
& rField
,
315 ItemConnFlags nFlags
= ITEMCONN_DEFAULT
);
320 typedef NumericConnection
< UInt16ItemWrapper
> UInt16NumericConnection
;
321 typedef NumericConnection
< UInt32ItemWrapper
> UInt32NumericConnection
;
325 /** Connection between an item and the VCL MetricField.
327 Adds support of different field units during control value <-> item value
328 conversion. The field unit passed to the constructor applies for the item
329 values, while the field unit used in the control has to be set at the
332 template< typename ItemWrpT
>
333 class MetricConnection
: public ItemControlConnection
< ItemWrpT
,
334 MetricFieldWrapper
< typename
ItemWrpT::ItemValueType
> >
336 typedef ItemControlConnection
< ItemWrpT
,
337 MetricFieldWrapper
< typename
ItemWrpT::ItemValueType
> >
338 ItemControlConnectionType
;
341 typedef typename
ItemControlConnectionType::ControlWrapperType MetricFieldWrapperType
;
343 explicit MetricConnection( sal_uInt16 nSlot
, MetricField
& rField
,
344 FieldUnit eItemUnit
= FUNIT_NONE
, ItemConnFlags nFlags
= ITEMCONN_DEFAULT
);
349 typedef MetricConnection
< UInt16ItemWrapper
> UInt16MetricConnection
;
350 typedef MetricConnection
< UInt32ItemWrapper
> UInt32MetricConnection
;
354 /** Connection between an item and a VCL ListBox.
356 Optionally a map can be passed that maps list box positions to item values.
357 This map MUST be terminated with an entry containing
358 WRAPPER_LISTBOX_ENTRY_NOTFOUND as list box position. The item value
359 contained in this last entry is used as default item value in case of an
362 template< typename ItemWrpT
>
363 class ListBoxConnection
: public ItemControlConnection
< ItemWrpT
,
364 ListBoxWrapper
< typename
ItemWrpT::ItemValueType
> >
366 typedef ItemControlConnection
< ItemWrpT
,
367 ListBoxWrapper
< typename
ItemWrpT::ItemValueType
> >
368 ItemControlConnectionType
;
371 typedef typename
ItemControlConnectionType::ControlWrapperType ListBoxWrapperType
;
372 typedef typename
ListBoxWrapperType::MapEntryType MapEntryType
;
374 explicit ListBoxConnection( sal_uInt16 nSlot
, ListBox
& rListBox
,
375 const MapEntryType
* pMap
= 0, ItemConnFlags nFlags
= ITEMCONN_DEFAULT
);
380 typedef ListBoxConnection
< UInt16ItemWrapper
> UInt16ListBoxConnection
;
381 typedef ListBoxConnection
< UInt32ItemWrapper
> UInt32ListBoxConnection
;
385 /** Connection between an item and an SVTOOLS ValueSet.
387 Optionally a map can be passed that maps value set identifiers to item
388 values. This map MUST be terminated with an entry containing
389 WRAPPER_VALUESET_ITEM_NOTFOUND as value set identifier. The item value
390 contained in this last entry is used as default item value in case of an
393 template< typename ItemWrpT
>
394 class ValueSetConnection
: public ItemControlConnection
< ItemWrpT
,
395 ValueSetWrapper
< typename
ItemWrpT::ItemValueType
> >
397 typedef ItemControlConnection
< ItemWrpT
,
398 ValueSetWrapper
< typename
ItemWrpT::ItemValueType
> >
399 ItemControlConnectionType
;
402 typedef typename
ItemControlConnectionType::ControlWrapperType ValueSetWrapperType
;
403 typedef typename
ValueSetWrapperType::MapEntryType MapEntryType
;
405 explicit ValueSetConnection( sal_uInt16 nSlot
, ValueSet
& rValueSet
,
406 const MapEntryType
* pMap
= 0, ItemConnFlags nFlags
= ITEMCONN_DEFAULT
);
411 typedef ValueSetConnection
< UInt16ItemWrapper
> UInt16ValueSetConnection
;
412 typedef ValueSetConnection
< UInt32ItemWrapper
> UInt32ValueSetConnection
;
415 // Array of connections
418 class ItemConnectionArrayImpl
;
420 /** A container of connection objects.
422 This is a connection with the only purpose to contain other connection
423 objects. This way it is possible to create a tree structure of connections
424 for a convenient connection management. This class is used by the class
425 SfxTabPage to store all connections.
427 class ItemConnectionArray
: public ItemConnectionBase
430 explicit ItemConnectionArray();
431 virtual ~ItemConnectionArray();
433 /** Adds a new connection to the list.
434 @descr Takes ownership of the connection! */
435 void AddConnection( ItemConnectionBase
* pConnection
);
438 virtual void ApplyFlags( const SfxItemSet
& rItemSet
) SAL_OVERRIDE
;
439 virtual void Reset( const SfxItemSet
& rItemSet
) SAL_OVERRIDE
;
440 virtual bool FillItemSet( SfxItemSet
& rDestSet
, const SfxItemSet
& rOldSet
) SAL_OVERRIDE
;
443 std::unique_ptr
< ItemConnectionArrayImpl
> mxImpl
;
449 // *** Implementation of template functions ***
453 // Base connection classes
456 template< typename ItemWrpT
, typename ControlWrpT
>
457 ItemControlConnection
< ItemWrpT
, ControlWrpT
>::ItemControlConnection(
458 sal_uInt16 nSlot
, ControlWrpT
* pNewCtrlWrp
, ItemConnFlags nFlags
) :
459 ItemConnectionBase( nFlags
),
461 mxCtrlWrp( pNewCtrlWrp
)
465 template< typename ItemWrpT
, typename ControlWrpT
>
466 ItemControlConnection
< ItemWrpT
, ControlWrpT
>::ItemControlConnection(
467 sal_uInt16 nSlot
, ControlType
& rControl
, ItemConnFlags nFlags
) :
468 ItemConnectionBase( nFlags
),
470 mxCtrlWrp( new ControlWrpT( rControl
) )
474 template< typename ItemWrpT
, typename ControlWrpT
>
475 ItemControlConnection
< ItemWrpT
, ControlWrpT
>::~ItemControlConnection()
479 template< typename ItemWrpT
, typename ControlWrpT
>
480 void ItemControlConnection
< ItemWrpT
, ControlWrpT
>::ApplyFlags( const SfxItemSet
& rItemSet
)
482 bool bKnown
= ItemWrapperHelper::IsKnownItem( rItemSet
, maItemWrp
.GetSlotId() );
483 mxCtrlWrp
->ModifyControl( GetEnableState( bKnown
), GetShowState( bKnown
) );
486 template< typename ItemWrpT
, typename ControlWrpT
>
487 void ItemControlConnection
< ItemWrpT
, ControlWrpT
>::Reset( const SfxItemSet
& rItemSet
)
489 const ItemType
* pItem
= maItemWrp
.GetUniqueItem( rItemSet
);
490 mxCtrlWrp
->SetControlDontKnow( pItem
== 0 );
492 mxCtrlWrp
->SetControlValue( maItemWrp
.GetItemValue( *pItem
) );
495 template< typename ItemWrpT
, typename ControlWrpT
>
496 bool ItemControlConnection
< ItemWrpT
, ControlWrpT
>::FillItemSet(
497 SfxItemSet
& rDestSet
, const SfxItemSet
& rOldSet
)
499 const ItemType
* pOldItem
= maItemWrp
.GetUniqueItem( rOldSet
);
500 bool bChanged
= false;
501 if( !mxCtrlWrp
->IsControlDontKnow() )
503 // first store the control value in a local variable
504 ControlValueType
aCtrlValue( mxCtrlWrp
->GetControlValue() );
505 // convert to item value type -> possible to convert i.e. from 'T' to 'const T&'
506 ItemValueType
aNewValue( aCtrlValue
);
507 // do not rely on existence of ItemValueType::operator!=
508 if( !pOldItem
|| !(maItemWrp
.GetItemValue( *pOldItem
) == aNewValue
) )
510 sal_uInt16 nWhich
= ItemWrapperHelper::GetWhichId( rDestSet
, maItemWrp
.GetSlotId() );
511 std::unique_ptr
< ItemType
> xItem(
512 static_cast< ItemType
* >( maItemWrp
.GetDefaultItem( rDestSet
).Clone() ) );
513 xItem
->SetWhich( nWhich
);
514 maItemWrp
.SetItemValue( *xItem
, aNewValue
);
515 rDestSet
.Put( *xItem
);
520 ItemWrapperHelper::RemoveDefaultItem( rDestSet
, rOldSet
, maItemWrp
.GetSlotId() );
525 // Standard connections
528 template< typename ItemWrpT
>
529 NumericConnection
< ItemWrpT
>::NumericConnection(
530 sal_uInt16 nSlot
, NumericField
& rField
, ItemConnFlags nFlags
) :
531 ItemControlConnectionType( nSlot
, rField
, nFlags
)
537 template< typename ItemWrpT
>
538 MetricConnection
< ItemWrpT
>::MetricConnection(
539 sal_uInt16 nSlot
, MetricField
& rField
, FieldUnit eItemUnit
, ItemConnFlags nFlags
) :
540 ItemControlConnectionType( nSlot
, new MetricFieldWrapperType( rField
, eItemUnit
), nFlags
)
546 template< typename ItemWrpT
>
547 ListBoxConnection
< ItemWrpT
>::ListBoxConnection(
548 sal_uInt16 nSlot
, ListBox
& rListBox
, const MapEntryType
* pMap
, ItemConnFlags nFlags
) :
549 ItemControlConnectionType( nSlot
, new ListBoxWrapperType( rListBox
, pMap
), nFlags
)
555 template< typename ItemWrpT
>
556 ValueSetConnection
< ItemWrpT
>::ValueSetConnection(
557 sal_uInt16 nSlot
, ValueSet
& rValueSet
, const MapEntryType
* pMap
, ItemConnFlags nFlags
) :
558 ItemControlConnectionType( nSlot
, new ValueSetWrapperType( rValueSet
, pMap
), nFlags
)
568 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */