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 
21 #include "gridcontrol.hxx"
22 #include "grideventforwarder.hxx"
23 
24 #include <com/sun/star/uno/XComponentContext.hpp>
25 #include <com/sun/star/view/SelectionType.hpp>
26 #include <com/sun/star/awt/grid/XGridControl.hpp>
27 #include <com/sun/star/awt/grid/XGridDataModel.hpp>
28 #include <com/sun/star/awt/grid/XGridRowSelection.hpp>
29 #include <com/sun/star/awt/grid/XMutableGridDataModel.hpp>
30 #include <com/sun/star/awt/grid/DefaultGridDataModel.hpp>
31 #include <com/sun/star/awt/grid/SortableGridDataModel.hpp>
32 #include <com/sun/star/awt/grid/DefaultGridColumnModel.hpp>
33 #include <toolkit/helper/property.hxx>
34 #include <tools/diagnose_ex.h>
35 #include <toolkit/controls/unocontrolbase.hxx>
36 #include <toolkit/controls/unocontrolmodel.hxx>
37 #include <toolkit/helper/listenermultiplexer.hxx>
38 
39 #include <memory>
40 
41 #include <helper/unopropertyarrayhelper.hxx>
42 
43 using namespace ::com::sun::star;
44 using namespace ::com::sun::star::uno;
45 using namespace ::com::sun::star::awt;
46 using namespace ::com::sun::star::awt::grid;
47 using namespace ::com::sun::star::lang;
48 using namespace ::com::sun::star::beans;
49 using namespace ::com::sun::star::container;
50 using namespace ::com::sun::star::view;
51 using namespace ::com::sun::star::util;
52 
53 namespace toolkit {
54 
55 namespace
56 {
lcl_getDefaultDataModel_throw(const Reference<XComponentContext> & i_context)57     Reference< XGridDataModel > lcl_getDefaultDataModel_throw( const Reference<XComponentContext> & i_context )
58     {
59         Reference< XMutableGridDataModel > const xDelegatorModel( DefaultGridDataModel::create( i_context ), UNO_SET_THROW );
60         Reference< XGridDataModel > const xDataModel( SortableGridDataModel::create( i_context, xDelegatorModel ), UNO_QUERY_THROW );
61         return xDataModel;
62     }
63 
lcl_getDefaultColumnModel_throw(const Reference<XComponentContext> & i_context)64     Reference< XGridColumnModel > lcl_getDefaultColumnModel_throw( const Reference<XComponentContext> & i_context )
65     {
66         Reference< XGridColumnModel > const xColumnModel = DefaultGridColumnModel::create( i_context );
67         return xColumnModel;
68     }
69 }
70 
71 
UnoGridModel(const css::uno::Reference<css::uno::XComponentContext> & rxContext)72 UnoGridModel::UnoGridModel( const css::uno::Reference< css::uno::XComponentContext >& rxContext )
73         :UnoControlModel( rxContext )
74 {
75     ImplRegisterProperty( BASEPROPERTY_BACKGROUNDCOLOR );
76     ImplRegisterProperty( BASEPROPERTY_BORDER );
77     ImplRegisterProperty( BASEPROPERTY_BORDERCOLOR );
78     ImplRegisterProperty( BASEPROPERTY_DEFAULTCONTROL );
79     ImplRegisterProperty( BASEPROPERTY_ENABLED );
80     ImplRegisterProperty( BASEPROPERTY_FILLCOLOR );
81     ImplRegisterProperty( BASEPROPERTY_HELPTEXT );
82     ImplRegisterProperty( BASEPROPERTY_HELPURL );
83     ImplRegisterProperty( BASEPROPERTY_PRINTABLE );
84     ImplRegisterProperty( BASEPROPERTY_SIZEABLE ); // resizable
85     ImplRegisterProperty( BASEPROPERTY_HSCROLL );
86     ImplRegisterProperty( BASEPROPERTY_VSCROLL );
87     ImplRegisterProperty( BASEPROPERTY_TABSTOP );
88     ImplRegisterProperty( BASEPROPERTY_GRID_SHOWROWHEADER );
89     ImplRegisterProperty( BASEPROPERTY_ROW_HEADER_WIDTH );
90     ImplRegisterProperty( BASEPROPERTY_GRID_SHOWCOLUMNHEADER );
91     ImplRegisterProperty( BASEPROPERTY_COLUMN_HEADER_HEIGHT );
92     ImplRegisterProperty( BASEPROPERTY_ROW_HEIGHT );
93     ImplRegisterProperty( BASEPROPERTY_GRID_DATAMODEL, makeAny( lcl_getDefaultDataModel_throw( m_xContext ) ) );
94     ImplRegisterProperty( BASEPROPERTY_GRID_COLUMNMODEL, makeAny( lcl_getDefaultColumnModel_throw( m_xContext ) ) );
95     ImplRegisterProperty( BASEPROPERTY_GRID_SELECTIONMODE );
96     ImplRegisterProperty( BASEPROPERTY_FONTRELIEF );
97     ImplRegisterProperty( BASEPROPERTY_FONTEMPHASISMARK );
98     ImplRegisterProperty( BASEPROPERTY_FONTDESCRIPTOR );
99     ImplRegisterProperty( BASEPROPERTY_TEXTCOLOR );
100     ImplRegisterProperty( BASEPROPERTY_TEXTLINECOLOR );
101     ImplRegisterProperty( BASEPROPERTY_USE_GRID_LINES );
102     ImplRegisterProperty( BASEPROPERTY_GRID_LINE_COLOR );
103     ImplRegisterProperty( BASEPROPERTY_GRID_HEADER_BACKGROUND );
104     ImplRegisterProperty( BASEPROPERTY_GRID_HEADER_TEXT_COLOR );
105     ImplRegisterProperty( BASEPROPERTY_GRID_ROW_BACKGROUND_COLORS );
106     ImplRegisterProperty( BASEPROPERTY_ACTIVE_SEL_BACKGROUND_COLOR );
107     ImplRegisterProperty( BASEPROPERTY_INACTIVE_SEL_BACKGROUND_COLOR );
108     ImplRegisterProperty( BASEPROPERTY_ACTIVE_SEL_TEXT_COLOR );
109     ImplRegisterProperty( BASEPROPERTY_INACTIVE_SEL_TEXT_COLOR );
110     ImplRegisterProperty( BASEPROPERTY_VERTICALALIGN );
111 }
112 
113 
UnoGridModel(const UnoGridModel & rModel)114 UnoGridModel::UnoGridModel( const UnoGridModel& rModel )
115     :UnoControlModel( rModel )
116 {
117     osl_atomic_increment( &m_refCount );
118     {
119         Reference< XGridDataModel > xDataModel;
120         // clone the data model
121         const Reference< XFastPropertySet > xCloneSource( &const_cast< UnoGridModel& >( rModel ) );
122         try
123         {
124             const Reference< XCloneable > xCloneable( xCloneSource->getFastPropertyValue( BASEPROPERTY_GRID_DATAMODEL ), UNO_QUERY_THROW );
125             xDataModel.set( xCloneable->createClone(), UNO_QUERY_THROW );
126         }
127         catch( const Exception& )
128         {
129             DBG_UNHANDLED_EXCEPTION("toolkit.controls");
130         }
131         if ( !xDataModel.is() )
132             xDataModel = lcl_getDefaultDataModel_throw( m_xContext );
133         UnoControlModel::setFastPropertyValue_NoBroadcast( BASEPROPERTY_GRID_DATAMODEL, makeAny( xDataModel ) );
134             // do *not* use setFastPropertyValue here: The UnoControlModel ctor did a simple copy of all property values,
135             // so before this call here, we share our data model with the own of the clone source. setFastPropertyValue,
136             // then, disposes the old data model - which means the data model which in fact belongs to the clone source.
137             // so, call the UnoControlModel's impl-method for setting the value.
138 
139         // clone the column model
140         Reference< XGridColumnModel > xColumnModel;
141         try
142         {
143             const Reference< XCloneable > xCloneable( xCloneSource->getFastPropertyValue( BASEPROPERTY_GRID_COLUMNMODEL ), UNO_QUERY_THROW );
144             xColumnModel.set( xCloneable->createClone(), UNO_QUERY_THROW );
145         }
146         catch( const Exception& )
147         {
148             DBG_UNHANDLED_EXCEPTION("toolkit.controls");
149         }
150         if ( !xColumnModel.is() )
151             xColumnModel = lcl_getDefaultColumnModel_throw( m_xContext );
152         UnoControlModel::setFastPropertyValue_NoBroadcast( BASEPROPERTY_GRID_COLUMNMODEL, makeAny( xColumnModel ) );
153             // same comment as above: do not use our own setPropertyValue here.
154     }
155     osl_atomic_decrement( &m_refCount );
156 }
157 
158 
Clone() const159 rtl::Reference<UnoControlModel> UnoGridModel::Clone() const
160 {
161     return new UnoGridModel( *this );
162 }
163 
164 
165 namespace
166 {
lcl_dispose_nothrow(const Any & i_component)167     void lcl_dispose_nothrow( const Any& i_component )
168     {
169         try
170         {
171             const Reference< XComponent > xComponent( i_component, UNO_QUERY_THROW );
172             xComponent->dispose();
173         }
174         catch( const Exception& )
175         {
176             DBG_UNHANDLED_EXCEPTION("toolkit.controls");
177         }
178     }
179 }
180 
181 
dispose()182 void SAL_CALL UnoGridModel::dispose(  )
183 {
184     lcl_dispose_nothrow( getFastPropertyValue( BASEPROPERTY_GRID_COLUMNMODEL ) );
185     lcl_dispose_nothrow( getFastPropertyValue( BASEPROPERTY_GRID_DATAMODEL ) );
186 
187     UnoControlModel::dispose();
188 }
189 
190 
setFastPropertyValue_NoBroadcast(sal_Int32 nHandle,const Any & rValue)191 void SAL_CALL UnoGridModel::setFastPropertyValue_NoBroadcast( sal_Int32 nHandle, const Any& rValue )
192 {
193     Any aOldSubModel;
194     if ( ( nHandle == BASEPROPERTY_GRID_COLUMNMODEL ) || ( nHandle == BASEPROPERTY_GRID_DATAMODEL ) )
195     {
196         aOldSubModel = getFastPropertyValue( nHandle );
197         if ( aOldSubModel == rValue )
198         {
199             OSL_ENSURE( false, "UnoGridModel::setFastPropertyValue_NoBroadcast: setting the same value, again!" );
200                 // shouldn't this have been caught by convertFastPropertyValue?
201             aOldSubModel.clear();
202         }
203     }
204 
205     UnoControlModel::setFastPropertyValue_NoBroadcast( nHandle, rValue );
206 
207     if ( aOldSubModel.hasValue() )
208         lcl_dispose_nothrow( aOldSubModel );
209 }
210 
211 
getServiceName()212 OUString UnoGridModel::getServiceName()
213 {
214     return "com.sun.star.awt.grid.UnoControlGridModel";
215 }
216 
217 
ImplGetDefaultValue(sal_uInt16 nPropId) const218 Any UnoGridModel::ImplGetDefaultValue( sal_uInt16 nPropId ) const
219 {
220     switch( nPropId )
221     {
222         case BASEPROPERTY_DEFAULTCONTROL:
223             return uno::makeAny( OUString("com.sun.star.awt.grid.UnoControlGrid") );
224         case BASEPROPERTY_GRID_SELECTIONMODE:
225             return uno::makeAny( SelectionType(1) );
226         case BASEPROPERTY_GRID_SHOWROWHEADER:
227         case BASEPROPERTY_USE_GRID_LINES:
228             return uno::makeAny( false );
229         case BASEPROPERTY_ROW_HEADER_WIDTH:
230             return uno::makeAny( sal_Int32( 10 ) );
231         case BASEPROPERTY_GRID_SHOWCOLUMNHEADER:
232             return uno::makeAny( true );
233         case BASEPROPERTY_COLUMN_HEADER_HEIGHT:
234         case BASEPROPERTY_ROW_HEIGHT:
235         case BASEPROPERTY_GRID_HEADER_BACKGROUND:
236         case BASEPROPERTY_GRID_HEADER_TEXT_COLOR:
237         case BASEPROPERTY_GRID_LINE_COLOR:
238         case BASEPROPERTY_GRID_ROW_BACKGROUND_COLORS:
239         case BASEPROPERTY_ACTIVE_SEL_BACKGROUND_COLOR:
240         case BASEPROPERTY_INACTIVE_SEL_BACKGROUND_COLOR:
241         case BASEPROPERTY_ACTIVE_SEL_TEXT_COLOR:
242         case BASEPROPERTY_INACTIVE_SEL_TEXT_COLOR:
243             return Any();
244         default:
245             return UnoControlModel::ImplGetDefaultValue( nPropId );
246     }
247 
248 }
249 
250 
getInfoHelper()251 ::cppu::IPropertyArrayHelper& UnoGridModel::getInfoHelper()
252 {
253     static UnoPropertyArrayHelper aHelper( ImplGetPropertyIds() );
254     return aHelper;
255 }
256 
257 
258 // XMultiPropertySet
getPropertySetInfo()259 Reference< XPropertySetInfo > UnoGridModel::getPropertySetInfo(  )
260 {
261     static Reference< XPropertySetInfo > xInfo( createPropertySetInfo( getInfoHelper() ) );
262     return xInfo;
263 }
264 
265 
266 //= UnoGridControl
267 
UnoGridControl()268 UnoGridControl::UnoGridControl()
269     :UnoGridControl_Base()
270     ,m_aSelectionListeners( *this )
271     ,m_pEventForwarder( new toolkit::GridEventForwarder( *this ) )
272 {
273 }
274 
275 
~UnoGridControl()276 UnoGridControl::~UnoGridControl()
277 {
278 }
279 
280 
GetComponentServiceName()281 OUString UnoGridControl::GetComponentServiceName()
282 {
283     return "Grid";
284 }
285 
286 
dispose()287 void SAL_CALL UnoGridControl::dispose(  )
288 {
289     lang::EventObject aEvt;
290     aEvt.Source = static_cast<cppu::OWeakObject*>(this);
291     m_aSelectionListeners.disposeAndClear( aEvt );
292     UnoControl::dispose();
293 }
294 
295 
createPeer(const uno::Reference<awt::XToolkit> & rxToolkit,const uno::Reference<awt::XWindowPeer> & rParentPeer)296 void SAL_CALL UnoGridControl::createPeer( const uno::Reference< awt::XToolkit > & rxToolkit, const uno::Reference< awt::XWindowPeer >  & rParentPeer )
297 {
298     UnoControlBase::createPeer( rxToolkit, rParentPeer );
299 
300     const Reference< XGridRowSelection > xGrid( getPeer(), UNO_QUERY_THROW );
301     xGrid->addSelectionListener( &m_aSelectionListeners );
302 }
303 
304 
305 namespace
306 {
lcl_setEventForwarding(const Reference<XControlModel> & i_gridControlModel,const std::unique_ptr<toolkit::GridEventForwarder> & i_listener,bool const i_add)307     void lcl_setEventForwarding( const Reference< XControlModel >& i_gridControlModel, const std::unique_ptr< toolkit::GridEventForwarder >& i_listener,
308         bool const i_add )
309     {
310         const Reference< XPropertySet > xModelProps( i_gridControlModel, UNO_QUERY );
311         if ( !xModelProps.is() )
312             return;
313 
314         try
315         {
316             Reference< XContainer > const xColModel(
317                 xModelProps->getPropertyValue("ColumnModel"),
318                 UNO_QUERY_THROW );
319             if ( i_add )
320                 xColModel->addContainerListener( i_listener.get() );
321             else
322                 xColModel->removeContainerListener( i_listener.get() );
323 
324             Reference< XGridDataModel > const xDataModel(
325                 xModelProps->getPropertyValue("GridDataModel"),
326                 UNO_QUERY_THROW
327             );
328             Reference< XMutableGridDataModel > const xMutableDataModel( xDataModel, UNO_QUERY );
329             if ( xMutableDataModel.is() )
330             {
331                 if ( i_add )
332                     xMutableDataModel->addGridDataListener( i_listener.get() );
333                 else
334                     xMutableDataModel->removeGridDataListener( i_listener.get() );
335             }
336         }
337         catch( const Exception& )
338         {
339             DBG_UNHANDLED_EXCEPTION("toolkit.controls");
340         }
341     }
342 }
343 
344 
setModel(const Reference<XControlModel> & i_model)345 sal_Bool SAL_CALL UnoGridControl::setModel( const Reference< XControlModel >& i_model )
346 {
347     lcl_setEventForwarding( getModel(), m_pEventForwarder, false );
348     if ( !UnoGridControl_Base::setModel( i_model ) )
349         return false;
350     lcl_setEventForwarding( getModel(), m_pEventForwarder, true );
351     return true;
352 }
353 
354 
getRowAtPoint(::sal_Int32 x,::sal_Int32 y)355 ::sal_Int32 UnoGridControl::getRowAtPoint(::sal_Int32 x, ::sal_Int32 y)
356 {
357     Reference< XGridControl > const xGrid ( getPeer(), UNO_QUERY_THROW );
358     return xGrid->getRowAtPoint( x, y );
359 }
360 
361 
getColumnAtPoint(::sal_Int32 x,::sal_Int32 y)362 ::sal_Int32 UnoGridControl::getColumnAtPoint(::sal_Int32 x, ::sal_Int32 y)
363 {
364     Reference< XGridControl > const xGrid ( getPeer(), UNO_QUERY_THROW );
365     return xGrid->getColumnAtPoint( x, y );
366 }
367 
368 
getCurrentColumn()369 ::sal_Int32 SAL_CALL UnoGridControl::getCurrentColumn(  )
370 {
371     Reference< XGridControl > const xGrid ( getPeer(), UNO_QUERY_THROW );
372     return xGrid->getCurrentColumn();
373 }
374 
375 
getCurrentRow()376 ::sal_Int32 SAL_CALL UnoGridControl::getCurrentRow(  )
377 {
378     Reference< XGridControl > const xGrid ( getPeer(), UNO_QUERY_THROW );
379     return xGrid->getCurrentRow();
380 }
381 
382 
goToCell(::sal_Int32 i_columnIndex,::sal_Int32 i_rowIndex)383 void SAL_CALL UnoGridControl::goToCell( ::sal_Int32 i_columnIndex, ::sal_Int32 i_rowIndex )
384 {
385     Reference< XGridControl > const xGrid ( getPeer(), UNO_QUERY_THROW );
386     xGrid->goToCell( i_columnIndex, i_rowIndex );
387 }
388 
389 
selectRow(::sal_Int32 i_rowIndex)390 void SAL_CALL UnoGridControl::selectRow( ::sal_Int32 i_rowIndex )
391 {
392     Reference< XGridRowSelection >( getPeer(), UNO_QUERY_THROW )->selectRow( i_rowIndex );
393 }
394 
395 
selectAllRows()396 void SAL_CALL UnoGridControl::selectAllRows()
397 {
398     Reference< XGridRowSelection >( getPeer(), UNO_QUERY_THROW )->selectAllRows();
399 }
400 
401 
deselectRow(::sal_Int32 i_rowIndex)402 void SAL_CALL UnoGridControl::deselectRow( ::sal_Int32 i_rowIndex )
403 {
404     Reference< XGridRowSelection >( getPeer(), UNO_QUERY_THROW )->deselectRow( i_rowIndex );
405 }
406 
407 
deselectAllRows()408 void SAL_CALL UnoGridControl::deselectAllRows()
409 {
410     Reference< XGridRowSelection >( getPeer(), UNO_QUERY_THROW )->deselectAllRows();
411 }
412 
413 
getSelectedRows()414 css::uno::Sequence< ::sal_Int32 > SAL_CALL UnoGridControl::getSelectedRows()
415 {
416     return Reference< XGridRowSelection >( getPeer(), UNO_QUERY_THROW )->getSelectedRows();
417 }
418 
419 
hasSelectedRows()420 sal_Bool SAL_CALL UnoGridControl::hasSelectedRows()
421 {
422     return Reference< XGridRowSelection >( getPeer(), UNO_QUERY_THROW )->hasSelectedRows();
423 }
424 
425 
isRowSelected(::sal_Int32 index)426 sal_Bool SAL_CALL UnoGridControl::isRowSelected(::sal_Int32 index)
427 {
428     return Reference< XGridRowSelection >( getPeer(), UNO_QUERY_THROW )->isRowSelected( index );
429 }
430 
431 
addSelectionListener(const css::uno::Reference<css::awt::grid::XGridSelectionListener> & listener)432 void SAL_CALL UnoGridControl::addSelectionListener(const css::uno::Reference< css::awt::grid::XGridSelectionListener > & listener)
433 {
434     m_aSelectionListeners.addInterface( listener );
435 }
436 
437 
removeSelectionListener(const css::uno::Reference<css::awt::grid::XGridSelectionListener> & listener)438 void SAL_CALL UnoGridControl::removeSelectionListener(const css::uno::Reference< css::awt::grid::XGridSelectionListener > & listener)
439 {
440     m_aSelectionListeners.removeInterface( listener );
441 }
442 
443 }
444 
445 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
stardiv_Toolkit_GridControl_get_implementation(css::uno::XComponentContext *,css::uno::Sequence<css::uno::Any> const &)446 stardiv_Toolkit_GridControl_get_implementation(
447     css::uno::XComponentContext *,
448     css::uno::Sequence<css::uno::Any> const &)
449 {
450     return cppu::acquire(new toolkit::UnoGridControl());
451 }
452 
453 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
stardiv_Toolkit_GridControlModel_get_implementation(css::uno::XComponentContext * context,css::uno::Sequence<css::uno::Any> const &)454 stardiv_Toolkit_GridControlModel_get_implementation(
455     css::uno::XComponentContext *context,
456     css::uno::Sequence<css::uno::Any> const &)
457 {
458     return cppu::acquire(new toolkit::UnoGridModel(context));
459 }
460 
461 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
462