1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: fmgridcl.cxx,v $
10 * $Revision: 1.64.94.3 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_svx.hxx"
35 #include "fmgridif.hxx"
36 #include "fmitems.hxx"
38 #include "fmresids.hrc"
39 #include "fmservs.hxx"
41 #include "formcontrolfactory.hxx"
42 #include "gridcell.hxx"
43 #include "gridcols.hxx"
44 #include "svx/dbaexchange.hxx"
45 #include "svx/dialmgr.hxx"
46 #include "svx/dialogs.hrc"
47 #include "svx/fmgridcl.hxx"
48 #include "svx/svxdlg.hxx"
49 #include "svx/svxids.hrc"
52 #include <com/sun/star/form/XConfirmDeleteListener.hpp>
53 #include <com/sun/star/form/XFormComponent.hpp>
54 #include <com/sun/star/form/XGridColumnFactory.hpp>
55 #include <com/sun/star/io/XPersistObject.hpp>
56 #include <com/sun/star/sdb/CommandType.hpp>
57 #include <com/sun/star/sdb/RowChangeAction.hpp>
58 #include <com/sun/star/sdb/XQueriesSupplier.hpp>
59 #include <com/sun/star/sdbc/DataType.hpp>
60 #include <com/sun/star/sdbc/XPreparedStatement.hpp>
61 #include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
62 #include <com/sun/star/sdbcx/XDeleteRows.hpp>
63 #include <com/sun/star/sdbcx/XTablesSupplier.hpp>
64 #include <com/sun/star/uno/XNamingService.hpp>
65 #include <com/sun/star/util/XNumberFormats.hpp>
66 #include <com/sun/star/util/XNumberFormatsSupplier.hpp>
67 #include <com/sun/star/util/XURLTransformer.hpp>
68 #include <com/sun/star/view/XSelectionSupplier.hpp>
70 #ifndef _SVSTDARR_STRINGSDTOR
71 #define _SVSTDARR_STRINGSDTOR
72 #define _SVSTDARR_ULONGS
73 #include <svtools/svstdarr.hxx>
76 #include <comphelper/extract.hxx>
77 #include <comphelper/numbers.hxx>
78 #include <comphelper/processfactory.hxx>
79 #include <comphelper/property.hxx>
80 #include <connectivity/dbtools.hxx>
81 #include <sfx2/dispatch.hxx>
82 #include <sfx2/viewfrm.hxx>
83 #include <svtools/eitem.hxx>
84 #include <svtools/fmtfield.hxx>
85 #include <svtools/numuno.hxx>
86 #include <tools/multisel.hxx>
87 #include <tools/shl.hxx>
88 #include <tools/diagnose_ex.h>
89 #include <vcl/help.hxx>
90 #include <vcl/image.hxx>
91 #include <vcl/longcurr.hxx>
92 #include <vcl/menu.hxx>
96 using namespace ::com::sun::star::uno
;
97 using namespace ::com::sun::star::view
;
98 using namespace ::com::sun::star::beans
;
99 using namespace ::com::sun::star::lang
;
100 using namespace ::com::sun::star::sdbcx
;
101 using namespace ::com::sun::star::sdbc
;
102 using namespace ::com::sun::star::sdb
;
103 using namespace ::com::sun::star::form
;
104 using namespace ::com::sun::star::util
;
105 using namespace ::com::sun::star::container
;
106 using namespace ::cppu
;
107 using namespace ::svxform
;
108 using namespace ::svx
;
110 //==============================================================================
111 //------------------------------------------------------------------------------
112 ::rtl::OUString
FieldServiceFromId(sal_Int32 nID
)
116 case SID_FM_EDIT
: return FM_COL_TEXTFIELD
;
117 case SID_FM_COMBOBOX
: return FM_COL_COMBOBOX
;
118 case SID_FM_LISTBOX
: return FM_COL_LISTBOX
;
119 case SID_FM_CHECKBOX
: return FM_COL_CHECKBOX
;
120 case SID_FM_DATEFIELD
: return FM_COL_DATEFIELD
;
121 case SID_FM_TIMEFIELD
: return FM_COL_TIMEFIELD
;
122 case SID_FM_NUMERICFIELD
: return FM_COL_NUMERICFIELD
;
123 case SID_FM_CURRENCYFIELD
: return FM_COL_CURRENCYFIELD
;
124 case SID_FM_PATTERNFIELD
: return FM_COL_PATTERNFIELD
;
125 case SID_FM_FORMATTEDFIELD
: return FM_COL_FORMATTEDFIELD
;
127 return ::rtl::OUString();
130 //==============================================================================
131 struct FmGridHeaderData
133 ODataAccessDescriptor aDropData
;
135 sal_Int8 nDropAction
;
136 Reference
< XInterface
> xDroppedStatement
;
137 Reference
< XInterface
> xDroppedResultSet
;
140 //==============================================================================
141 //------------------------------------------------------------------------------
142 const sal_Int16 nChangeTypeOffset
= 1000;
143 void SetMenuItem(const ImageList
& rList
, sal_uInt16 nID
, Menu
* pMenu
, Menu
& rNewMenu
, sal_Bool bDesignMode
= sal_True
, sal_Int16 nOffset
= nChangeTypeOffset
)
145 pMenu
->SetItemImage(nID
, rList
.GetImage(nID
));
146 pMenu
->EnableItem(nID
, bDesignMode
);
147 rNewMenu
.InsertItem(nID
+ nOffset
, pMenu
->GetItemText(nID
));
148 rNewMenu
.SetItemImage(nID
+ nOffset
, rList
.GetImage(nID
));
149 rNewMenu
.SetHelpId(nID
+ nOffset
, pMenu
->GetHelpId(nID
));
150 rNewMenu
.EnableItem(nID
+ nOffset
, bDesignMode
);
153 //------------------------------------------------------------------------------
154 FmGridHeader::FmGridHeader( BrowseBox
* pParent
, WinBits nWinBits
)
155 :EditBrowserHeader(pParent
, nWinBits
)
156 ,DropTargetHelper(this)
157 ,m_pImpl(new FmGridHeaderData
)
161 //------------------------------------------------------------------------------
162 FmGridHeader::~FmGridHeader()
167 //------------------------------------------------------------------------------
168 sal_uInt16
FmGridHeader::GetModelColumnPos(sal_uInt16 nId
) const
170 return static_cast<FmGridControl
*>(GetParent())->GetModelColumnPos(nId
);
172 //---------------------------------------------------------------------------------------
173 void FmGridHeader::notifyColumnSelect(sal_uInt16 nColumnId
)
175 sal_uInt16 nPos
= GetModelColumnPos(nColumnId
);
176 Reference
< XIndexAccess
> xColumns(((FmGridControl
*)GetParent())->GetPeer()->getColumns(), UNO_QUERY
);
177 if ( nPos
< xColumns
->getCount() )
179 Reference
< XSelectionSupplier
> xSelSupplier(xColumns
, UNO_QUERY
);
180 if ( xSelSupplier
.is() )
182 Reference
< XPropertySet
> xColumn
;
183 xColumns
->getByIndex(nPos
) >>= xColumn
;
184 xSelSupplier
->select(makeAny(xColumn
));
188 //------------------------------------------------------------------------------
189 void FmGridHeader::Select()
191 EditBrowserHeader::Select();
192 notifyColumnSelect(GetCurItemId());
195 //------------------------------------------------------------------------------
196 void FmGridHeader::RequestHelp( const HelpEvent
& rHEvt
)
198 sal_uInt16 nItemId
= GetItemId( ScreenToOutputPixel( rHEvt
.GetMousePosPixel() ) );
201 if ( rHEvt
.GetMode() & (HELPMODE_QUICK
| HELPMODE_BALLOON
) )
203 Rectangle aItemRect
= GetItemRect( nItemId
);
204 Point aPt
= OutputToScreenPixel( aItemRect
.TopLeft() );
205 aItemRect
.Left() = aPt
.X();
206 aItemRect
.Top() = aPt
.Y();
207 aPt
= OutputToScreenPixel( aItemRect
.BottomRight() );
208 aItemRect
.Right() = aPt
.X();
209 aItemRect
.Bottom() = aPt
.Y();
211 sal_uInt16 nPos
= GetModelColumnPos(nItemId
);
212 Reference
< ::com::sun::star::container::XIndexContainer
> xColumns(static_cast<FmGridControl
*>(GetParent())->GetPeer()->getColumns());
215 Reference
< ::com::sun::star::beans::XPropertySet
> xColumn
;
216 ::cppu::extractInterface(xColumn
, xColumns
->getByIndex(nPos
));
217 ::rtl::OUString aHelpText
;
218 xColumn
->getPropertyValue(FM_PROP_HELPTEXT
) >>= aHelpText
;
219 if ( aHelpText
.getLength() )
221 if ( rHEvt
.GetMode() & HELPMODE_BALLOON
)
222 Help::ShowBalloon( this, aItemRect
.Center(), aItemRect
, aHelpText
);
224 Help::ShowQuickHelp( this, aItemRect
, aHelpText
);
234 EditBrowserHeader::RequestHelp( rHEvt
);
237 //------------------------------------------------------------------------------
238 sal_Int8
FmGridHeader::AcceptDrop( const AcceptDropEvent
& rEvt
)
240 // drop allowed in design mode only
241 if (!static_cast<FmGridControl
*>(GetParent())->IsDesignMode())
242 return DND_ACTION_NONE
;
244 // search for recognized formats
245 const DataFlavorExVector
& rFlavors
= GetDataFlavorExVector();
246 if (OColumnTransferable::canExtractColumnDescriptor(rFlavors
, CTF_COLUMN_DESCRIPTOR
| CTF_FIELD_DESCRIPTOR
))
247 return rEvt
.mnAction
;
249 return DND_ACTION_NONE
;
252 //------------------------------------------------------------------------------
253 sal_Int8
FmGridHeader::ExecuteDrop( const ExecuteDropEvent
& _rEvt
)
255 if (!static_cast<FmGridControl
*>(GetParent())->IsDesignMode())
256 return DND_ACTION_NONE
;
258 TransferableDataHelper
aDroppedData(_rEvt
.maDropEvent
.Transferable
);
261 sal_Bool bColumnDescriptor
= OColumnTransferable::canExtractColumnDescriptor(aDroppedData
.GetDataFlavorExVector(), CTF_COLUMN_DESCRIPTOR
);
262 sal_Bool bFieldDescriptor
= OColumnTransferable::canExtractColumnDescriptor(aDroppedData
.GetDataFlavorExVector(), CTF_FIELD_DESCRIPTOR
);
263 if (!bColumnDescriptor
&& !bFieldDescriptor
)
265 DBG_ERROR("FmGridHeader::ExecuteDrop: should never have reached this (no extractable format)!");
266 return DND_ACTION_NONE
;
269 // extract the descriptor
270 ::rtl::OUString sDatasouce
, sCommand
, sFieldName
,sDatabaseLocation
,sConnnectionResource
;
271 sal_Int32 nCommandType
= CommandType::COMMAND
;
272 Reference
< XPreparedStatement
> xStatement
;
273 Reference
< XResultSet
> xResultSet
;
274 Reference
< XPropertySet
> xField
;
275 Reference
< XConnection
> xConnection
;
277 ODataAccessDescriptor aColumn
= OColumnTransferable::extractColumnDescriptor(aDroppedData
);
278 if (aColumn
.has(daDataSource
)) aColumn
[daDataSource
] >>= sDatasouce
;
279 if (aColumn
.has(daDatabaseLocation
)) aColumn
[daDatabaseLocation
] >>= sDatabaseLocation
;
280 if (aColumn
.has(daConnectionResource
)) aColumn
[daConnectionResource
] >>= sConnnectionResource
;
281 if (aColumn
.has(daCommand
)) aColumn
[daCommand
] >>= sCommand
;
282 if (aColumn
.has(daCommandType
)) aColumn
[daCommandType
] >>= nCommandType
;
283 if (aColumn
.has(daColumnName
)) aColumn
[daColumnName
] >>= sFieldName
;
284 if (aColumn
.has(daColumnObject
))aColumn
[daColumnObject
] >>= xField
;
285 if (aColumn
.has(daConnection
)) aColumn
[daConnection
] >>= xConnection
;
287 if ( !sFieldName
.getLength()
288 || !sCommand
.getLength()
289 || ( !sDatasouce
.getLength()
290 && !sDatabaseLocation
.getLength()
295 DBG_ERROR( "FmGridHeader::ExecuteDrop: somebody started a nonsense drag operation!!" );
296 return DND_ACTION_NONE
;
302 if (!xConnection
.is())
303 { // the transferable did not contain the connection -> build an own one
306 ::rtl::OUString
sSignificantSource( sDatasouce
.getLength() ? sDatasouce
: sDatabaseLocation
);
307 xConnection
= OStaticDataAccessTools().getConnection_withFeedback(sSignificantSource
, ::rtl::OUString(),::rtl::OUString(),static_cast<FmGridControl
*>(GetParent())->getServiceManager());
309 catch(NoSuchElementException
&)
310 { // allowed, means sDatasouce isn't a valid data source name ....
314 DBG_ERROR("FmGridHeader::ExecuteDrop: could not retrieve the database access object !");
317 if (!xConnection
.is())
319 DBG_ERROR("FmGridHeader::ExecuteDrop: could not retrieve the database access object !");
320 return DND_ACTION_NONE
;
324 // try to obtain the column object
328 Reference
< XServiceInfo
> xServiceInfo(xConnection
, UNO_QUERY
);
329 DBG_ASSERT(xServiceInfo
.is() && xServiceInfo
->supportsService(SRV_SDB_CONNECTION
), "FmGridHeader::ExecuteDrop: invalid connection (no database access connection !)");
332 Reference
< XNameAccess
> xFields
;
333 switch (nCommandType
)
335 case CommandType::TABLE
:
337 Reference
< XTablesSupplier
> xSupplyTables(xConnection
, UNO_QUERY
);
338 Reference
< XColumnsSupplier
> xSupplyColumns
;
339 xSupplyTables
->getTables()->getByName(sCommand
) >>= xSupplyColumns
;
340 xFields
= xSupplyColumns
->getColumns();
343 case CommandType::QUERY
:
345 Reference
< XQueriesSupplier
> xSupplyQueries(xConnection
, UNO_QUERY
);
346 Reference
< XColumnsSupplier
> xSupplyColumns
;
347 xSupplyQueries
->getQueries()->getByName(sCommand
) >>= xSupplyColumns
;
348 xFields
= xSupplyColumns
->getColumns();
353 xStatement
= xConnection
->prepareStatement(sCommand
);
354 // not interested in any results
356 Reference
< XPropertySet
> xStatProps(xStatement
,UNO_QUERY
);
357 xStatProps
->setPropertyValue(rtl::OUString::createFromAscii("MaxRows"), makeAny(sal_Int32(0)));
359 xResultSet
= xStatement
->executeQuery();
360 Reference
< XColumnsSupplier
> xSupplyCols(xResultSet
, UNO_QUERY
);
361 if (xSupplyCols
.is())
362 xFields
= xSupplyCols
->getColumns();
366 if (xFields
.is() && xFields
->hasByName(sFieldName
))
367 xFields
->getByName(sFieldName
) >>= xField
;
371 ::comphelper::disposeComponent(xStatement
);
372 return DND_ACTION_NONE
;
376 // do the drop asynchronously
377 // (85957 - UI actions within the drop are not allowed, but we want to open a popup menu)
378 m_pImpl
->aDropData
= aColumn
;
379 m_pImpl
->aDropData
[daConnection
] <<= xConnection
;
380 m_pImpl
->aDropData
[daColumnObject
] <<= xField
;
382 m_pImpl
->nDropAction
= _rEvt
.mnAction
;
383 m_pImpl
->aDropPosPixel
= _rEvt
.maPosPixel
;
384 m_pImpl
->xDroppedStatement
= xStatement
;
385 m_pImpl
->xDroppedResultSet
= xResultSet
;
387 PostUserEvent(LINK(this, FmGridHeader
, OnAsyncExecuteDrop
));
391 DBG_ERROR("FmGridHeader::ExecuteDrop: caught an exception while creatin' the column !");
392 ::comphelper::disposeComponent(xStatement
);
396 return DND_ACTION_LINK
;
399 //------------------------------------------------------------------------------
400 IMPL_LINK( FmGridHeader
, OnAsyncExecuteDrop
, void*, /*NOTINTERESTEDIN*/ )
402 ::rtl::OUString sCommand
, sFieldName
,sURL
;
403 sal_Int32 nCommandType
= CommandType::COMMAND
;
404 Reference
< XPropertySet
> xField
;
405 Reference
< XConnection
> xConnection
;
407 ::rtl::OUString sDatasouce
= m_pImpl
->aDropData
.getDataSource();
408 if ( !sDatasouce
.getLength() && m_pImpl
->aDropData
.has(daConnectionResource
) )
409 m_pImpl
->aDropData
[daConnectionResource
] >>= sURL
;
410 m_pImpl
->aDropData
[daCommand
] >>= sCommand
;
411 m_pImpl
->aDropData
[daCommandType
] >>= nCommandType
;
412 m_pImpl
->aDropData
[daColumnName
] >>= sFieldName
;
413 m_pImpl
->aDropData
[daConnection
] >>= xConnection
;
414 m_pImpl
->aDropData
[daColumnObject
] >>= xField
;
418 // need number formats
419 Reference
< XNumberFormatsSupplier
> xSupplier
= OStaticDataAccessTools().getNumberFormats(xConnection
, sal_True
);
420 Reference
< XNumberFormats
> xNumberFormats
;
422 xNumberFormats
= xSupplier
->getNumberFormats();
423 if (!xNumberFormats
.is())
425 ::comphelper::disposeComponent(m_pImpl
->xDroppedResultSet
);
426 ::comphelper::disposeComponent(m_pImpl
->xDroppedStatement
);
430 // Vom Feld werden nun zwei Informationen benoetigt:
431 // a.) Name des Feldes fuer Label und ControlSource
432 // b.) FormatKey, um festzustellen, welches Feld erzeugt werden soll
433 sal_Int32 nDataType
= 0;
434 xField
->getPropertyValue(FM_PROP_FIELDTYPE
) >>= nDataType
;
435 // diese Datentypen koennen im Gridcontrol nicht verarbeitet werden
438 case DataType::LONGVARBINARY
:
439 case DataType::BINARY
:
440 case DataType::VARBINARY
:
441 case DataType::OTHER
:
442 ::comphelper::disposeComponent(m_pImpl
->xDroppedResultSet
);
443 ::comphelper::disposeComponent(m_pImpl
->xDroppedStatement
);
447 // Erstellen der Column
448 Reference
< XIndexContainer
> xCols(static_cast<FmGridControl
*>(GetParent())->GetPeer()->getColumns());
449 Reference
< XGridColumnFactory
> xFactory(xCols
, UNO_QUERY
);
451 Point aPos
= OutputToScreenPixel(m_pImpl
->aDropPosPixel
);
452 sal_uInt16 nColId
= GetItemId(m_pImpl
->aDropPosPixel
);
453 // EinfuegePosition, immer vor der aktuellen Spalte
454 sal_uInt16 nPos
= GetModelColumnPos(nColId
);
455 Reference
< XPropertySet
> xCol
, xSecondCol
;
457 // erzeugen der Column in abhaengigkeit vom type, default textfeld
458 SvULongs aPossibleTypes
;
462 case DataType::BOOLEAN
:
463 aPossibleTypes
.Insert(SID_FM_CHECKBOX
, aPossibleTypes
.Count());
465 case DataType::TINYINT
:
466 case DataType::SMALLINT
:
467 case DataType::INTEGER
:
468 aPossibleTypes
.Insert(SID_FM_NUMERICFIELD
, aPossibleTypes
.Count());
469 aPossibleTypes
.Insert(SID_FM_FORMATTEDFIELD
, aPossibleTypes
.Count());
472 case DataType::DOUBLE
:
473 case DataType::NUMERIC
:
474 case DataType::DECIMAL
:
475 aPossibleTypes
.Insert(SID_FM_FORMATTEDFIELD
, aPossibleTypes
.Count());
476 aPossibleTypes
.Insert(SID_FM_NUMERICFIELD
, aPossibleTypes
.Count());
478 case DataType::TIMESTAMP
:
479 aPossibleTypes
.Insert(SID_FM_TWOFIELDS_DATE_N_TIME
, aPossibleTypes
.Count());
480 aPossibleTypes
.Insert(SID_FM_DATEFIELD
, aPossibleTypes
.Count());
481 aPossibleTypes
.Insert(SID_FM_TIMEFIELD
, aPossibleTypes
.Count());
482 aPossibleTypes
.Insert(SID_FM_FORMATTEDFIELD
, aPossibleTypes
.Count());
485 aPossibleTypes
.Insert(SID_FM_DATEFIELD
, aPossibleTypes
.Count());
486 aPossibleTypes
.Insert(SID_FM_FORMATTEDFIELD
, aPossibleTypes
.Count());
489 aPossibleTypes
.Insert(SID_FM_TIMEFIELD
, aPossibleTypes
.Count());
490 aPossibleTypes
.Insert(SID_FM_FORMATTEDFIELD
, aPossibleTypes
.Count());
493 case DataType::VARCHAR
:
494 case DataType::LONGVARCHAR
:
496 aPossibleTypes
.Insert(SID_FM_EDIT
, aPossibleTypes
.Count());
497 aPossibleTypes
.Insert(SID_FM_FORMATTEDFIELD
, aPossibleTypes
.Count());
500 // if it's a currency field, a a "currency field" option
503 if ( ::comphelper::hasProperty(FM_PROP_ISCURRENCY
, xField
)
504 && ::comphelper::getBOOL(xField
->getPropertyValue(FM_PROP_ISCURRENCY
)))
505 aPossibleTypes
.Insert(SID_FM_CURRENCYFIELD
, 0);
509 DBG_ERROR("FmGridHeader::ExecuteDrop: Exception occured!");
512 sal_Int32 nPreferedType
= -1;
513 sal_Bool bDateNTimeCol
= sal_False
;
514 if (aPossibleTypes
.Count() != 0)
516 nPreferedType
= aPossibleTypes
[0];
517 if ((m_pImpl
->nDropAction
== DND_ACTION_LINK
) && (aPossibleTypes
.Count() > 1))
519 ImageList
aImageList( SVX_RES(RID_SVXIMGLIST_FMEXPL
) );
521 PopupMenu
aInsertMenu(SVX_RES(RID_SVXMNU_COLS
));
523 PopupMenu
* pMenu
= aInsertMenu
.GetPopupMenu(SID_FM_INSERTCOL
);
524 for (sal_uInt32 i
=0; i
<aPossibleTypes
.Count(); ++i
)
525 SetMenuItem(aImageList
, sal_uInt16(aPossibleTypes
[(sal_uInt16
)i
]), pMenu
, aTypeMenu
, sal_True
, 0);
526 nPreferedType
= aTypeMenu
.Execute(this, m_pImpl
->aDropPosPixel
);
529 bDateNTimeCol
= nPreferedType
== SID_FM_TWOFIELDS_DATE_N_TIME
;
530 sal_uInt16 nColCount
= bDateNTimeCol
? 2 : 1;
531 ::rtl::OUString sFieldService
;
535 nPreferedType
= nColCount
? SID_FM_DATEFIELD
: SID_FM_TIMEFIELD
;
537 sFieldService
= FieldServiceFromId(nPreferedType
);
538 Reference
< XPropertySet
> xThisRoundCol
;
539 if ( sFieldService
.getLength() )
540 xThisRoundCol
= xFactory
->createColumn(sFieldService
);
542 xSecondCol
= xThisRoundCol
;
544 xCol
= xThisRoundCol
;
548 if (!xCol
.is() || (bDateNTimeCol
&& !xSecondCol
.is()))
550 ::comphelper::disposeComponent(xCol
); // in case only the creation of the second column failed
551 ::comphelper::disposeComponent(m_pImpl
->xDroppedResultSet
);
552 ::comphelper::disposeComponent(m_pImpl
->xDroppedStatement
);
558 String
sTimePostfix( SVX_RES( RID_STR_POSTFIX_TIME
) );
559 xCol
->setPropertyValue(FM_PROP_LABEL
, makeAny( ::rtl::OUString( sFieldName
+ sTimePostfix
) ) );
561 String
sDatePostfix( SVX_RES( RID_STR_POSTFIX_DATE
) );
562 xSecondCol
->setPropertyValue(FM_PROP_LABEL
, makeAny( ::rtl::OUString( sFieldName
+ sDatePostfix
) ) );
565 xCol
->setPropertyValue(FM_PROP_LABEL
, makeAny(sFieldName
));
567 FormControlFactory
aControlFactory( ::comphelper::getProcessServiceFactory() );
568 aControlFactory
.initializeControlModel( DocumentClassification::classifyHostDocument( xCols
), xCol
);
569 aControlFactory
.initializeFieldDependentProperties( xField
, xCol
, xNumberFormats
);
571 xCol
->setPropertyValue(FM_PROP_CONTROLSOURCE
, makeAny(sFieldName
));
572 if ( xSecondCol
.is() )
573 xSecondCol
->setPropertyValue(FM_PROP_CONTROLSOURCE
, makeAny(sFieldName
));
577 String sRealName
,sPurePostfix
;
579 String aPostfix
[] = {
580 String( SVX_RES( RID_STR_POSTFIX_DATE
) ),
581 String( SVX_RES( RID_STR_POSTFIX_TIME
) )
584 for ( size_t i
=0; i
<2; ++i
)
586 sPurePostfix
= aPostfix
[i
];
587 sPurePostfix
.EraseLeadingChars(' ');
588 sPurePostfix
.EraseLeadingChars('(');
589 sPurePostfix
.EraseTrailingChars(')');
590 sRealName
= sFieldName
;
592 sRealName
+= sPurePostfix
;
594 xSecondCol
->setPropertyValue(FM_PROP_NAME
, makeAny(::rtl::OUString(sRealName
)));
596 xCol
->setPropertyValue(FM_PROP_NAME
, makeAny(::rtl::OUString(sRealName
)));
600 xCol
->setPropertyValue(FM_PROP_NAME
, makeAny(sFieldName
));
605 xCols
->insertByIndex(nPos
, aElement
);
609 aElement
<<= xSecondCol
;
610 xCols
->insertByIndex(nPos
== (sal_uInt16
)-1 ? nPos
: ++nPos
, aElement
);
613 // ist die component::Form an die Datenbankangebunden?
614 Reference
< XFormComponent
> xFormCp(xCols
, UNO_QUERY
);
615 Reference
< XPropertySet
> xForm(xFormCp
->getParent(), UNO_QUERY
);
618 if (!::comphelper::getString(xForm
->getPropertyValue(FM_PROP_DATASOURCE
)).getLength())
620 if ( sDatasouce
.getLength() )
621 xForm
->setPropertyValue(FM_PROP_DATASOURCE
, makeAny(sDatasouce
));
623 xForm
->setPropertyValue(FM_PROP_URL
, makeAny(sURL
));
626 if (!::comphelper::getString(xForm
->getPropertyValue(FM_PROP_COMMAND
)).getLength())
628 xForm
->setPropertyValue(FM_PROP_COMMAND
, makeAny(sCommand
));
630 switch (nCommandType
)
632 case CommandType::TABLE
:
633 aCommandType
<<= (sal_Int32
)CommandType::TABLE
;
635 case CommandType::QUERY
:
636 aCommandType
<<= (sal_Int32
)CommandType::QUERY
;
639 aCommandType
<<= (sal_Int32
)CommandType::COMMAND
;
640 xForm
->setPropertyValue(FM_PROP_ESCAPE_PROCESSING
, bool2any((sal_Bool
)(2 == nCommandType
)));
643 xForm
->setPropertyValue(FM_PROP_COMMANDTYPE
, aCommandType
);
649 DBG_ERROR("FmGridHeader::OnAsyncExecuteDrop: caught an exception while creatin' the column !");
650 ::comphelper::disposeComponent(m_pImpl
->xDroppedResultSet
);
651 ::comphelper::disposeComponent(m_pImpl
->xDroppedStatement
);
655 ::comphelper::disposeComponent(m_pImpl
->xDroppedResultSet
);
656 ::comphelper::disposeComponent(m_pImpl
->xDroppedStatement
);
660 //------------------------------------------------------------------------------
661 void FmGridHeader::PreExecuteColumnContextMenu(sal_uInt16 nColId
, PopupMenu
& rMenu
)
663 sal_Bool bDesignMode
= static_cast<FmGridControl
*>(GetParent())->IsDesignMode();
665 Reference
< ::com::sun::star::container::XIndexContainer
> xCols(static_cast<FmGridControl
*>(GetParent())->GetPeer()->getColumns());
666 // Aufbau des Insert Menues
667 // mark the column if nColId != HEADERBAR_ITEM_NOTFOUND
670 sal_uInt16 nPos2
= GetModelColumnPos(nColId
);
672 Reference
< ::com::sun::star::container::XIndexContainer
> xColumns(static_cast<FmGridControl
*>(GetParent())->GetPeer()->getColumns());
673 Reference
< ::com::sun::star::beans::XPropertySet
> xColumn
;
674 ::cppu::extractInterface(xColumn
, xColumns
->getByIndex(nPos2
));
675 Reference
< ::com::sun::star::view::XSelectionSupplier
> xSelSupplier(xColumns
, UNO_QUERY
);
676 if (xSelSupplier
.is())
677 xSelSupplier
->select(makeAny(xColumn
));
680 // EinfuegePosition, immer vor der aktuellen Spalte
681 sal_uInt16 nPos
= GetModelColumnPos(nColId
);
682 sal_Bool bMarked
= nColId
&& static_cast<FmGridControl
*>(GetParent())->isColumnMarked(nColId
);
684 ImageList
aImageList( SVX_RES(RID_SVXIMGLIST_FMEXPL
) );
685 PopupMenu
* pControlMenu
= new PopupMenu
;
687 PopupMenu
* pMenu
= rMenu
.GetPopupMenu(SID_FM_INSERTCOL
);
690 SetMenuItem(aImageList
, SID_FM_EDIT
, pMenu
, *pControlMenu
, bDesignMode
);
691 SetMenuItem(aImageList
, SID_FM_CHECKBOX
, pMenu
, *pControlMenu
, bDesignMode
);
692 SetMenuItem(aImageList
, SID_FM_COMBOBOX
, pMenu
, *pControlMenu
, bDesignMode
);
693 SetMenuItem(aImageList
, SID_FM_LISTBOX
, pMenu
, *pControlMenu
, bDesignMode
);
694 SetMenuItem(aImageList
, SID_FM_DATEFIELD
, pMenu
, *pControlMenu
, bDesignMode
);
695 SetMenuItem(aImageList
, SID_FM_TIMEFIELD
, pMenu
, *pControlMenu
, bDesignMode
);
696 SetMenuItem(aImageList
, SID_FM_NUMERICFIELD
, pMenu
, *pControlMenu
, bDesignMode
);
697 SetMenuItem(aImageList
, SID_FM_CURRENCYFIELD
, pMenu
, *pControlMenu
, bDesignMode
);
698 SetMenuItem(aImageList
, SID_FM_PATTERNFIELD
, pMenu
, *pControlMenu
, bDesignMode
);
699 SetMenuItem(aImageList
, SID_FM_FORMATTEDFIELD
, pMenu
, *pControlMenu
, bDesignMode
);
702 if (pMenu
&& xCols
.is() && nColId
)
704 Reference
< ::com::sun::star::beans::XPropertySet
> xSet
;
705 ::cppu::extractInterface(xSet
, xCols
->getByIndex(nPos
));
707 xSet
->getPropertyValue(FM_PROP_CLASSID
) >>= nClassId
;
709 Reference
< ::com::sun::star::io::XPersistObject
> xServiceQuestion(xSet
, UNO_QUERY
);
710 sal_Int32 nColType
= xServiceQuestion
.is() ? getColumnTypeByModelName(xServiceQuestion
->getServiceName()) : 0;
711 if (nColType
== TYPE_TEXTFIELD
)
712 { // edit fields and formatted fields have the same service name, thus getColumnTypeByModelName returns TYPE_TEXTFIELD
713 // in both cases. And as columns don't have an ::com::sun::star::lang::XServiceInfo interface, we have to distinguish both
714 // types via the existence of special properties
715 Reference
< ::com::sun::star::beans::XPropertySet
> xProps(xSet
, UNO_QUERY
);
718 Reference
< ::com::sun::star::beans::XPropertySetInfo
> xPropsInfo
= xProps
->getPropertySetInfo();
719 if (xPropsInfo
.is() && xPropsInfo
->hasPropertyByName(FM_PROP_FORMATSSUPPLIER
))
720 nColType
= TYPE_FORMATTEDFIELD
;
724 pControlMenu
->EnableItem(SID_FM_EDIT
+ nChangeTypeOffset
, bDesignMode
&& (nColType
!= TYPE_TEXTFIELD
));
725 pControlMenu
->EnableItem(SID_FM_COMBOBOX
+ nChangeTypeOffset
, bDesignMode
&& (nColType
!= TYPE_COMBOBOX
));
726 pControlMenu
->EnableItem(SID_FM_LISTBOX
+ nChangeTypeOffset
, bDesignMode
&& (nColType
!= TYPE_LISTBOX
));
727 pControlMenu
->EnableItem(SID_FM_CHECKBOX
+ nChangeTypeOffset
, bDesignMode
&& (nColType
!= TYPE_CHECKBOX
));
728 pControlMenu
->EnableItem(SID_FM_DATEFIELD
+ nChangeTypeOffset
, bDesignMode
&& (nColType
!= TYPE_DATEFIELD
));
729 pControlMenu
->EnableItem(SID_FM_NUMERICFIELD
+ nChangeTypeOffset
, bDesignMode
&& (nColType
!= TYPE_NUMERICFIELD
));
730 pControlMenu
->EnableItem(SID_FM_TIMEFIELD
+ nChangeTypeOffset
, bDesignMode
&& (nColType
!= TYPE_TIMEFIELD
));
731 pControlMenu
->EnableItem(SID_FM_CURRENCYFIELD
+ nChangeTypeOffset
, bDesignMode
&& (nColType
!= TYPE_CURRENCYFIELD
));
732 pControlMenu
->EnableItem(SID_FM_PATTERNFIELD
+ nChangeTypeOffset
, bDesignMode
&& (nColType
!= TYPE_PATTERNFIELD
));
733 pControlMenu
->EnableItem(SID_FM_FORMATTEDFIELD
+ nChangeTypeOffset
, bDesignMode
&& (nColType
!= TYPE_FORMATTEDFIELD
));
734 rMenu
.SetPopupMenu(SID_FM_CHANGECOL
, pControlMenu
);
737 rMenu
.EnableItem(SID_FM_INSERTCOL
, bDesignMode
&& xCols
.is());
738 rMenu
.EnableItem(SID_FM_DELETECOL
, bDesignMode
&& bMarked
&& xCols
.is());
739 rMenu
.EnableItem(SID_FM_CHANGECOL
, bDesignMode
&& bMarked
&& xCols
.is());
740 rMenu
.EnableItem(SID_FM_SHOW_PROPERTY_BROWSER
, bDesignMode
&& bMarked
&& xCols
.is());
742 PopupMenu
* pShowColsMenu
= rMenu
.GetPopupMenu(SID_FM_SHOWCOLS
);
743 sal_uInt16 nHiddenCols
= 0;
748 // check for hidden cols
749 Reference
< ::com::sun::star::beans::XPropertySet
> xCurCol
;
751 for (sal_uInt16 i
=0; i
<xCols
->getCount(); ++i
)
753 ::cppu::extractInterface(xCurCol
, xCols
->getByIndex(i
));
754 DBG_ASSERT(xCurCol
.is(), "FmGridHeader::PreExecuteColumnContextMenu : the Peer has invalid columns !");
755 aHidden
= xCurCol
->getPropertyValue(FM_PROP_HIDDEN
);
756 DBG_ASSERT(aHidden
.getValueType().getTypeClass() == TypeClass_BOOLEAN
,
757 "FmGridHeader::PreExecuteColumnContextMenu : the property 'hidden' should be boolean !");
758 if (::comphelper::getBOOL(aHidden
))
760 // put the column name into the 'show col' menu
761 if (nHiddenCols
< 16)
762 { // (only the first 16 items to keep the menu rather small)
763 aName
= xCurCol
->getPropertyValue(FM_PROP_LABEL
);
764 pShowColsMenu
->InsertItem(nHiddenCols
+ 1, ::comphelper::getString(aName
), 0, nHiddenCols
);
765 // the ID is arbitrary, but should be unique within the whole menu
771 pShowColsMenu
->EnableItem(SID_FM_SHOWCOLS_MORE
, xCols
.is() && (nHiddenCols
> 16));
772 pShowColsMenu
->EnableItem(SID_FM_SHOWALLCOLS
, xCols
.is() && (nHiddenCols
> 0));
775 // allow the 'hide column' item ?
776 sal_Bool bAllowHide
= bMarked
; // a column is marked
777 bAllowHide
= bAllowHide
|| (!bDesignMode
&& (nPos
!= (sal_uInt16
)-1)); // OR we are in alive mode and have hit a column
778 bAllowHide
= bAllowHide
&& xCols
.is(); // AND we have a column container
779 bAllowHide
= bAllowHide
&& (xCols
->getCount()-nHiddenCols
> 1); // AND there are at least two visible columns
780 rMenu
.EnableItem(SID_FM_HIDECOL
, bAllowHide
);
782 sal_Bool bChecked
= sal_False
;
786 SfxViewFrame
* pCurrentFrame
= SfxViewFrame::Current();
787 SfxItemState eState
= SFX_ITEM_UNKNOWN
;
788 // ask the bindings of the current view frame (which should be the one we're residing in) for the state
791 SfxPoolItem
* pItem
= NULL
;
792 eState
= pCurrentFrame
->GetBindings().QueryState(SID_FM_CTL_PROPERTIES
, pItem
);
794 if (eState
>= SFX_ITEM_AVAILABLE
&& pItem
)
796 bChecked
= pItem
->ISA(SfxBoolItem
) && ((SfxBoolItem
*)pItem
)->GetValue();
797 rMenu
.CheckItem(SID_FM_SHOW_PROPERTY_BROWSER
,bChecked
);
804 enum InspectorAction
{ eOpenInspector
, eCloseInspector
, eUpdateInspector
, eNone
};
806 //------------------------------------------------------------------------------
807 void FmGridHeader::PostExecuteColumnContextMenu(sal_uInt16 nColId
, const PopupMenu
& rMenu
, sal_uInt16 nExecutionResult
)
809 Reference
< ::com::sun::star::container::XIndexContainer
> xCols(static_cast<FmGridControl
*>(GetParent())->GetPeer()->getColumns());
810 sal_uInt16 nPos
= GetModelColumnPos(nColId
);
812 // remove and delet the menu we inserted in PreExecuteColumnContextMenu
813 PopupMenu
* pControlMenu
= rMenu
.GetPopupMenu(SID_FM_CHANGECOL
);
816 ::rtl::OUString aFieldType
;
817 sal_Bool bReplace
= sal_False
;
818 InspectorAction eInspectorAction
= eNone
;
819 Reference
< XPropertySet
> xColumnToInspect
;
820 switch (nExecutionResult
)
822 case SID_FM_DELETECOL
:
824 Reference
< XInterface
> xCol
;
825 ::cppu::extractInterface(xCol
, xCols
->getByIndex(nPos
));
826 xCols
->removeByIndex(nPos
);
827 ::comphelper::disposeComponent(xCol
);
829 case SID_FM_SHOW_PROPERTY_BROWSER
:
830 eInspectorAction
= rMenu
.IsItemChecked( SID_FM_SHOW_PROPERTY_BROWSER
) ? eOpenInspector
: eCloseInspector
;
831 xColumnToInspect
.set( xCols
->getByIndex( nPos
), UNO_QUERY
);
833 case SID_FM_EDIT
+ nChangeTypeOffset
:
836 aFieldType
= FM_COL_TEXTFIELD
;
838 case SID_FM_COMBOBOX
+ nChangeTypeOffset
:
840 case SID_FM_COMBOBOX
:
841 aFieldType
= FM_COL_COMBOBOX
;
843 case SID_FM_LISTBOX
+ nChangeTypeOffset
:
846 aFieldType
= FM_COL_LISTBOX
;
848 case SID_FM_CHECKBOX
+ nChangeTypeOffset
:
850 case SID_FM_CHECKBOX
:
851 aFieldType
= FM_COL_CHECKBOX
;
853 case SID_FM_DATEFIELD
+ nChangeTypeOffset
:
855 case SID_FM_DATEFIELD
:
856 aFieldType
= FM_COL_DATEFIELD
;
858 case SID_FM_TIMEFIELD
+ nChangeTypeOffset
:
860 case SID_FM_TIMEFIELD
:
861 aFieldType
= FM_COL_TIMEFIELD
;
863 case SID_FM_NUMERICFIELD
+ nChangeTypeOffset
:
865 case SID_FM_NUMERICFIELD
:
866 aFieldType
= FM_COL_NUMERICFIELD
;
868 case SID_FM_CURRENCYFIELD
+ nChangeTypeOffset
:
870 case SID_FM_CURRENCYFIELD
:
871 aFieldType
= FM_COL_CURRENCYFIELD
;
873 case SID_FM_PATTERNFIELD
+ nChangeTypeOffset
:
875 case SID_FM_PATTERNFIELD
:
876 aFieldType
= FM_COL_PATTERNFIELD
;
878 case SID_FM_FORMATTEDFIELD
+ nChangeTypeOffset
:
880 case SID_FM_FORMATTEDFIELD
:
881 aFieldType
= FM_COL_FORMATTEDFIELD
;
885 Reference
< ::com::sun::star::beans::XPropertySet
> xCurCol
;
886 ::cppu::extractInterface(xCurCol
, xCols
->getByIndex(nPos
));
887 xCurCol
->setPropertyValue(FM_PROP_HIDDEN
, makeAny((sal_Bool
)sal_True
));
890 case SID_FM_SHOWCOLS_MORE
:
892 //CHINA001 FmShowColsDialog dlg(NULL);
893 //CHINA001 dlg.SetColumns(xCols);
894 //CHINA001 dlg.Execute();
895 SvxAbstractDialogFactory
* pFact
= SvxAbstractDialogFactory::Create();
898 AbstractFmShowColsDialog
* pDlg
= pFact
->CreateFmShowColsDialog(NULL
, RID_SVX_DLG_SHOWGRIDCOLUMNS
);
899 DBG_ASSERT(pDlg
, "Dialogdiet fail!");//CHINA001
900 pDlg
->SetColumns(xCols
);
907 case SID_FM_SHOWALLCOLS
:
909 // just iterate through all the cols ...
910 Reference
< ::com::sun::star::beans::XPropertySet
> xCurCol
;
911 for (sal_uInt16 i
=0; i
<xCols
->getCount(); ++i
)
913 ::cppu::extractInterface(xCurCol
, xCols
->getByIndex(i
));
914 xCurCol
->setPropertyValue(FM_PROP_HIDDEN
, makeAny((sal_Bool
)sal_False
));
916 // TODO : there must be a more clever way to do this ....
917 // with the above the view is updated after every single model update ...
921 if (nExecutionResult
>0 && nExecutionResult
<=16)
922 { // it was a "show column/<colname>" command (there are at most 16 such items)
923 // search the nExecutionResult'th hidden col
924 Reference
< ::com::sun::star::beans::XPropertySet
> xCurCol
;
925 for (sal_uInt16 i
=0; i
<xCols
->getCount() && nExecutionResult
; ++i
)
927 ::cppu::extractInterface(xCurCol
, xCols
->getByIndex(i
));
928 Any aHidden
= xCurCol
->getPropertyValue(FM_PROP_HIDDEN
);
929 if (::comphelper::getBOOL(aHidden
))
930 if (!--nExecutionResult
)
932 xCurCol
->setPropertyValue(FM_PROP_HIDDEN
, makeAny((sal_Bool
)sal_False
));
940 if ( aFieldType
.getLength() )
944 Reference
< XGridColumnFactory
> xFactory( xCols
, UNO_QUERY_THROW
);
945 Reference
< XPropertySet
> xNewCol( xFactory
->createColumn( aFieldType
), UNO_SET_THROW
);
949 // ein paar Properties hinueberretten
950 Reference
< XPropertySet
> xReplaced( xCols
->getByIndex( nPos
), UNO_QUERY
);
952 OStaticDataAccessTools().TransferFormComponentProperties(
953 xReplaced
, xNewCol
, Application::GetSettings().GetUILocale() );
955 xCols
->replaceByIndex( nPos
, makeAny( xNewCol
) );
956 ::comphelper::disposeComponent( xReplaced
);
958 eInspectorAction
= eUpdateInspector
;
959 xColumnToInspect
= xNewCol
;
963 // Standardlabel setzen
964 ::rtl::OUString sLabelBase
= String( SVX_RES( RID_STR_COLUMN
) );
965 // disambiguate the name
966 Reference
< XNameAccess
> xColNames( xCols
, UNO_QUERY
);
967 ::rtl::OUString sLabel
;
968 for ( sal_Int32 i
=1; i
<65535; ++i
)
971 sLabel
+= ::rtl::OUString::valueOf( (sal_Int32
)i
);
972 if ( !xColNames
->hasByName( sLabel
) )
975 // no fallback in case the name is not unique (which is rather improbable) ....
976 xNewCol
->setPropertyValue( FM_PROP_LABEL
, makeAny( sLabel
) );
977 xNewCol
->setPropertyValue( FM_PROP_NAME
, makeAny( sLabel
) );
979 FormControlFactory
determine( ::comphelper::getProcessServiceFactory() );
980 determine
.initializeControlModel( DocumentClassification::classifyHostDocument( xCols
), xNewCol
);
982 xCols
->insertByIndex( nPos
, makeAny( xNewCol
) );
985 catch( const Exception
& )
987 DBG_UNHANDLED_EXCEPTION();
991 SfxViewFrame
* pCurrentFrame
= SfxViewFrame::Current();
992 OSL_ENSURE( pCurrentFrame
, "FmGridHeader::PostExecuteColumnContextMenu: no view frame -> no bindings -> no property browser!" );
995 if ( eInspectorAction
== eUpdateInspector
)
997 if ( !pCurrentFrame
->HasChildWindow( SID_FM_SHOW_PROPERTIES
) )
998 eInspectorAction
= eNone
;
1001 if ( eInspectorAction
!= eNone
)
1003 FmInterfaceItem
aIFaceItem( SID_FM_SHOW_PROPERTY_BROWSER
, xColumnToInspect
);
1004 SfxBoolItem
aShowItem( SID_FM_SHOW_PROPERTIES
, eInspectorAction
== eCloseInspector
? FALSE
: TRUE
);
1006 pCurrentFrame
->GetBindings().GetDispatcher()->Execute( SID_FM_SHOW_PROPERTY_BROWSER
, SFX_CALLMODE_ASYNCHRON
,
1007 &aIFaceItem
, &aShowItem
, 0L );
1012 //------------------------------------------------------------------------------
1013 void FmGridHeader::triggerColumnContextMenu( const ::Point
& _rPreferredPos
)
1016 sal_uInt16 nColId
= GetItemId( _rPreferredPos
);
1019 PopupMenu
aContextMenu( SVX_RES( RID_SVXMNU_COLS
) );
1021 // let derivees modify the menu
1022 PreExecuteColumnContextMenu( nColId
, aContextMenu
);
1023 aContextMenu
.RemoveDisabledEntries( sal_True
, sal_True
);
1026 sal_uInt16 nResult
= aContextMenu
.Execute( this, _rPreferredPos
);
1028 // let derivees handle the result
1029 PostExecuteColumnContextMenu( nColId
, aContextMenu
, nResult
);
1032 //------------------------------------------------------------------------------
1033 void FmGridHeader::Command(const CommandEvent
& rEvt
)
1035 switch (rEvt
.GetCommand())
1037 case COMMAND_CONTEXTMENU
:
1039 if (!rEvt
.IsMouseEvent())
1042 triggerColumnContextMenu( rEvt
.GetMousePosPixel() );
1046 EditBrowserHeader::Command(rEvt
);
1050 //------------------------------------------------------------------------------
1051 FmGridControl::FmGridControl(
1052 Reference
< ::com::sun::star::lang::XMultiServiceFactory
> _rxFactory
,
1054 FmXGridPeer
* _pPeer
,
1056 :DbGridControl(_rxFactory
, pParent
, nBits
)
1058 ,m_nCurrentSelectedColumn(-1)
1059 ,m_nMarkedColumnId(BROWSER_INVALIDID
)
1060 ,m_bSelecting(sal_False
)
1061 ,m_bInColumnMove(sal_False
)
1063 EnableInteractiveRowHeight( );
1066 //------------------------------------------------------------------------------
1067 void FmGridControl::Command(const CommandEvent
& _rEvt
)
1069 if ( COMMAND_CONTEXTMENU
== _rEvt
.GetCommand() )
1071 FmGridHeader
* pMyHeader
= static_cast< FmGridHeader
* >( GetHeaderBar() );
1072 if ( pMyHeader
&& !_rEvt
.IsMouseEvent() )
1073 { // context menu requested by keyboard
1074 if ( 1 == GetSelectColumnCount() || IsDesignMode() )
1076 sal_uInt16 nSelId
= GetColumnId(
1077 sal::static_int_cast
< USHORT
>( FirstSelectedColumn() ) );
1078 ::Rectangle
aColRect( GetFieldRectPixel( 0, nSelId
, sal_False
) );
1080 Point
aRelativePos( pMyHeader
->ScreenToOutputPixel( OutputToScreenPixel( aColRect
.TopCenter() ) ) );
1081 pMyHeader
->triggerColumnContextMenu( aRelativePos
, FmGridHeader::AccessControl() );
1089 DbGridControl::Command( _rEvt
);
1092 // ::com::sun::star::beans::XPropertyChangeListener
1093 //------------------------------------------------------------------------------
1094 void FmGridControl::propertyChange(const ::com::sun::star::beans::PropertyChangeEvent
& evt
)
1096 if (evt
.PropertyName
== FM_PROP_ROWCOUNT
)
1098 // if we're not in the main thread call AdjustRows asynchronously
1099 implAdjustInSolarThread(sal_True
);
1103 const DbGridRowRef
& xRow
= GetCurrentRow();
1104 // waehrend Positionierung wird kein abgleich der Properties vorgenommen
1105 Reference
<XPropertySet
> xSet(evt
.Source
,UNO_QUERY
);
1106 if (xRow
.Is() && (::cppu::any2bool(xSet
->getPropertyValue(FM_PROP_ISNEW
))|| CompareBookmark(getDataSource()->getBookmark(), xRow
->GetBookmark())))
1108 if (evt
.PropertyName
== FM_PROP_ISMODIFIED
)
1110 // modified or clean ?
1111 GridRowStatus eStatus
= ::comphelper::getBOOL(evt
.NewValue
) ? GRS_MODIFIED
: GRS_CLEAN
;
1112 if (eStatus
!= xRow
->GetStatus())
1114 xRow
->SetStatus(eStatus
);
1115 vos::OGuard
aGuard( Application::GetSolarMutex() );
1116 RowModified(GetCurrentPos());
1122 //------------------------------------------------------------------------------
1123 void FmGridControl::SetDesignMode(sal_Bool bMode
)
1125 sal_Bool bOldMode
= IsDesignMode();
1126 DbGridControl::SetDesignMode(bMode
);
1127 if (bOldMode
!= bMode
)
1131 // selection aufheben
1132 markColumn(USHRT_MAX
);
1136 Reference
< ::com::sun::star::container::XIndexContainer
> xColumns(GetPeer()->getColumns());
1137 Reference
< ::com::sun::star::view::XSelectionSupplier
> xSelSupplier(xColumns
, UNO_QUERY
);
1138 if (xSelSupplier
.is())
1140 Any aSelection
= xSelSupplier
->getSelection();
1141 Reference
< ::com::sun::star::beans::XPropertySet
> xColumn
;
1142 if (aSelection
.getValueType().getTypeClass() == TypeClass_INTERFACE
)
1143 ::cppu::extractInterface(xColumn
, aSelection
);
1144 Reference
< XInterface
> xCurrent
;
1145 for (sal_uInt16 i
=0; i
<xColumns
->getCount(); ++i
)
1147 ::cppu::extractInterface(xCurrent
, xColumns
->getByIndex(i
));
1148 if (xCurrent
== xColumn
)
1150 markColumn(GetColumnIdFromModelPos(i
));
1159 //------------------------------------------------------------------------------
1160 void FmGridControl::DeleteSelectedRows()
1165 // how many rows are selected?
1166 sal_Int32 nSelectedRows
= GetSelectRowCount();
1168 // the current line should be deleted but it is currently in edit mode
1169 if ( IsCurrentAppending() )
1171 // is the insert row selected
1172 if (GetEmptyRow().Is() && IsRowSelected(GetRowCount() - 1))
1176 if (nSelectedRows
<= 0)
1179 // try to confirm the delete
1180 Reference
< ::com::sun::star::frame::XDispatchProvider
> xDispatcher
= (::com::sun::star::frame::XDispatchProvider
*)GetPeer();
1181 if (xDispatcher
.is())
1183 ::com::sun::star::util::URL aUrl
;
1184 aUrl
.Complete
= FMURL_CONFIRM_DELETION
;
1185 // #100312# ------------
1186 Reference
< ::com::sun::star::util::XURLTransformer
> xTransformer(
1187 ::comphelper::getProcessServiceFactory()->createInstance(
1188 ::rtl::OUString::createFromAscii("com.sun.star.util.URLTransformer")), UNO_QUERY
);
1189 if( xTransformer
.is() )
1190 xTransformer
->parseStrict( aUrl
);
1192 Reference
< ::com::sun::star::frame::XDispatch
> xDispatch
= xDispatcher
->queryDispatch(aUrl
, rtl::OUString(), 0);
1193 Reference
< ::com::sun::star::form::XConfirmDeleteListener
> xConfirm(xDispatch
, UNO_QUERY
);
1196 ::com::sun::star::sdb::RowChangeEvent aEvent
;
1197 aEvent
.Source
= (Reference
< XInterface
> )(*getDataSource());
1198 aEvent
.Rows
= nSelectedRows
;
1199 aEvent
.Action
= ::com::sun::star::sdb::RowChangeAction::DELETE
;
1200 if (!xConfirm
->confirmDelete(aEvent
))
1205 const MultiSelection
* pRowSelection
= GetSelection();
1206 if ( pRowSelection
&& pRowSelection
->IsAllSelected() )
1208 BeginCursorAction();
1209 CursorWrapper
* pCursor
= getDataSource();
1210 Reference
< XResultSetUpdate
> xUpdateCursor((Reference
< XInterface
>)*pCursor
, UNO_QUERY
);
1213 pCursor
->beforeFirst();
1214 while( pCursor
->next() )
1215 xUpdateCursor
->deleteRow();
1217 SetUpdateMode(sal_False
);
1220 xUpdateCursor
->moveToInsertRow();
1222 catch(const Exception
&)
1224 OSL_ENSURE(0,"Exception caught while deleting rows!");
1226 // An den DatenCursor anpassen
1227 AdjustDataSource(sal_True
);
1229 SetUpdateMode(sal_True
);
1233 Reference
< ::com::sun::star::sdbcx::XDeleteRows
> xDeleteThem((Reference
< XInterface
>)*getDataSource(), UNO_QUERY
);
1235 // colect the bookmarks of the selected rows
1236 Sequence
< Any
> aBookmarks
= getSelectionBookmarks();
1238 // determine the next row to position after deletion
1240 sal_Bool bNewPos
= sal_False
;
1241 // if the current row isn't selected we take the row as row after deletion
1242 OSL_ENSURE( GetCurrentRow().Is(), "FmGridControl::DeleteSelectedRows: no current row here?" );
1243 // crash reports suggest it can happen we don't have a current row - how?
1244 // #154303# / 2008-04-23 / frank.schoenheit@sun.com
1245 if ( !IsRowSelected( GetCurrentPos() ) && !IsCurrentAppending() && GetCurrentRow().Is() )
1247 aBookmark
= GetCurrentRow()->GetBookmark();
1252 // we look for the first row after the selected block for selection
1253 long nIdx
= LastSelectedRow() + 1;
1254 if (nIdx
< GetRowCount() - 1)
1256 // there is a next row to position on
1257 if (SeekCursor(nIdx
))
1259 GetSeekRow()->SetState(m_pSeekCursor
, sal_True
);
1262 // if it's not the row for inserting we keep the bookmark
1263 if (!IsInsertionRow(nIdx
))
1264 aBookmark
= m_pSeekCursor
->getBookmark();
1269 // we look for the first row before the selected block for selection after deletion
1270 nIdx
= FirstSelectedRow() - 1;
1271 if (nIdx
>= 0 && SeekCursor(nIdx
))
1273 GetSeekRow()->SetState(m_pSeekCursor
, sal_True
);
1276 aBookmark
= m_pSeekCursor
->getBookmark();
1281 // Sind alle Zeilen Selectiert
1282 // Zweite bedingung falls keine einguegeZeile existiert
1283 sal_Bool bAllSelected
= GetTotalCount() == nSelectedRows
|| GetRowCount() == nSelectedRows
;
1285 BeginCursorAction();
1287 // now delete the row
1288 Sequence
<sal_Int32
> aDeletedRows
;
1289 SetUpdateMode( FALSE
);
1292 aDeletedRows
= xDeleteThem
->deleteRows(aBookmarks
);
1294 catch(SQLException
&)
1297 SetUpdateMode( TRUE
);
1299 // how many rows are deleted?
1300 sal_Int32 nDeletedRows
= 0;
1301 const sal_Int32
* pSuccess
= aDeletedRows
.getConstArray();
1302 for (sal_Int32 i
= 0; i
< aDeletedRows
.getLength(); i
++)
1308 // sind Zeilen geloescht worden?
1311 SetUpdateMode(sal_False
);
1315 // did we delete all the rows than try to move to the next possible row
1316 if (nDeletedRows
== aDeletedRows
.getLength())
1318 // there exists a new position to move on
1321 if (aBookmark
.hasValue())
1322 getDataSource()->moveToBookmark(aBookmark
);
1323 // no valid bookmark so move to the insert row
1326 Reference
< XResultSetUpdate
> xUpdateCursor((Reference
< XInterface
>)*m_pDataCursor
, UNO_QUERY
);
1327 xUpdateCursor
->moveToInsertRow();
1332 Reference
< ::com::sun::star::beans::XPropertySet
> xSet((Reference
< XInterface
>)*m_pDataCursor
, UNO_QUERY
);
1334 sal_Int32
nRecordCount(0);
1335 xSet
->getPropertyValue(FM_PROP_ROWCOUNT
) >>= nRecordCount
;
1336 if ( m_pDataCursor
->rowDeleted() )
1339 // there are no rows left and we have an insert row
1340 if (!nRecordCount
&& GetEmptyRow().Is())
1342 Reference
< XResultSetUpdate
> xUpdateCursor((Reference
< XInterface
>)*m_pDataCursor
, UNO_QUERY
);
1343 xUpdateCursor
->moveToInsertRow();
1345 else if (nRecordCount
)
1346 // move to the first row
1347 getDataSource()->first();
1350 // not all the rows where deleted, so move to the first row which remained in the resultset
1353 for (sal_Int32 i
= 0; i
< aDeletedRows
.getLength(); i
++)
1357 getDataSource()->moveToBookmark(aBookmarks
.getConstArray()[i
]);
1363 catch(const Exception
&)
1367 // positioning went wrong so try to move to the first row
1368 getDataSource()->first();
1370 catch(const Exception
&)
1375 // An den DatenCursor anpassen
1376 AdjustDataSource(sal_True
);
1378 // es konnten nicht alle Zeilen geloescht werden
1379 // da nie nicht geloeschten wieder selektieren
1380 if (nDeletedRows
< nSelectedRows
)
1382 // waren alle selektiert
1386 if (IsInsertionRow(GetRowCount() - 1)) // einfuegeZeile nicht
1387 SelectRow(GetRowCount() - 1, sal_False
);
1391 // select the remaining rows
1392 for (sal_Int32 i
= 0; i
< aDeletedRows
.getLength(); i
++)
1398 m_pSeekCursor
->moveToBookmark(m_pDataCursor
->getBookmark());
1399 SetSeekPos(m_pSeekCursor
->getRow() - 1);
1400 SelectRow(GetSeekPos());
1403 catch(const Exception
&)
1405 // keep the seekpos in all cases
1406 SetSeekPos(m_pSeekCursor
->getRow() - 1);
1413 SetUpdateMode(sal_True
);
1415 else // Zeile konnte nicht geloescht werden
1420 // currentrow is the insert row?
1421 if (!IsCurrentAppending())
1422 getDataSource()->refreshRow();
1424 catch(const Exception
&)
1430 // if there is no selection anymore we can start editing
1431 if (!GetSelectRowCount())
1436 // XCurrentRecordListener
1437 //------------------------------------------------------------------------------
1438 void FmGridControl::positioned(const ::com::sun::star::lang::EventObject
& /*rEvent*/)
1440 TRACE_RANGE("FmGridControl::positioned");
1441 // position on the data source (force it to be done in the main thread)
1442 implAdjustInSolarThread(sal_False
);
1445 //------------------------------------------------------------------------------
1446 sal_Bool
FmGridControl::commit()
1448 // Commit nur ausfuehren, wenn nicht bereits ein Update vom ::com::sun::star::form::component::GridControl ausgefuehrt
1452 if (Controller().Is() && Controller()->IsModified())
1454 if (!SaveModified())
1461 //------------------------------------------------------------------------------
1462 void FmGridControl::inserted(const ::com::sun::star::lang::EventObject
& /*rEvent*/)
1464 const DbGridRowRef
& xRow
= GetCurrentRow();
1468 // Zeile ist eingefuegt worden, dann den status und mode zuruecksetzen
1469 xRow
->SetState(m_pDataCursor
, sal_False
);
1470 xRow
->SetNew(sal_False
);
1474 // XCancelUpdateRecordListener
1475 //------------------------------------------------------------------------------
1476 void FmGridControl::restored(const ::com::sun::star::lang::EventObject
& rEvent
)
1478 if (!GetCurrentRow().Is())
1481 sal_Bool bAppending
= GetCurrentRow()->IsNew();
1482 sal_Bool bDirty
= GetCurrentRow()->IsModified();
1483 if (bAppending
&& (EditBrowseBox::IsModified() || bDirty
))
1485 if (Controller().Is())
1486 Controller()->ClearModified();
1488 // jetzt die Zeile herausnehmen
1489 RowRemoved(GetRowCount() - 1, 1, sal_True
);
1490 GetNavigationBar().InvalidateAll();
1496 //------------------------------------------------------------------------------
1497 BrowserHeader
* FmGridControl::imp_CreateHeaderBar(BrowseBox
* pParent
)
1499 DBG_ASSERT( pParent
== this, "FmGridControl::imp_CreateHeaderBar: parent?" );
1500 return new FmGridHeader( pParent
);
1503 //------------------------------------------------------------------------------
1504 void FmGridControl::markColumn(sal_uInt16 nId
)
1506 if (GetHeaderBar() && m_nMarkedColumnId
!= nId
)
1509 if (m_nMarkedColumnId
!= BROWSER_INVALIDID
)
1511 HeaderBarItemBits aBits
= GetHeaderBar()->GetItemBits(m_nMarkedColumnId
) & ~HIB_FLAT
;
1512 GetHeaderBar()->SetItemBits(m_nMarkedColumnId
, aBits
);
1516 if (nId
!= BROWSER_INVALIDID
)
1518 HeaderBarItemBits aBits
= GetHeaderBar()->GetItemBits(nId
) | HIB_FLAT
;
1519 GetHeaderBar()->SetItemBits(nId
, aBits
);
1521 m_nMarkedColumnId
= nId
;
1525 //------------------------------------------------------------------------------
1526 sal_Bool
FmGridControl::isColumnMarked(sal_uInt16 nId
) const
1528 return m_nMarkedColumnId
== nId
;
1531 //------------------------------------------------------------------------------
1532 long FmGridControl::QueryMinimumRowHeight()
1534 long nMinimalLogicHeight
= 20; // 0.2 cm
1535 long nMinimalPixelHeight
= LogicToPixel( Point( 0, nMinimalLogicHeight
), MAP_10TH_MM
).Y();
1536 return CalcZoom( nMinimalPixelHeight
);
1539 //------------------------------------------------------------------------------
1540 void FmGridControl::RowHeightChanged()
1542 DbGridControl::RowHeightChanged();
1544 Reference
< XPropertySet
> xModel( GetPeer()->getColumns(), UNO_QUERY
);
1545 DBG_ASSERT( xModel
.is(), "FmGridControl::RowHeightChanged: no model!" );
1550 sal_Int32 nUnzoomedPixelHeight
= CalcReverseZoom( GetDataRowHeight() );
1551 Any aProperty
= makeAny( (sal_Int32
)PixelToLogic( Point( 0, nUnzoomedPixelHeight
), MAP_10TH_MM
).Y() );
1552 xModel
->setPropertyValue( FM_PROP_ROWHEIGHT
, aProperty
);
1554 catch( const Exception
& )
1556 OSL_ENSURE( sal_False
, "FmGridControl::RowHeightChanged: caught an exception!" );
1561 //------------------------------------------------------------------------------
1562 void FmGridControl::ColumnResized(sal_uInt16 nId
)
1564 DbGridControl::ColumnResized(nId
);
1566 // Wert ans model uebergeben
1567 DbGridColumn
* pCol
= DbGridControl::GetColumns().GetObject(GetModelColumnPos(nId
));
1568 Reference
< ::com::sun::star::beans::XPropertySet
> xColModel(pCol
->getModel());
1572 sal_Int32 nColumnWidth
= GetColumnWidth(nId
);
1573 nColumnWidth
= CalcReverseZoom(nColumnWidth
);
1574 // Umrechnen in 10THMM
1575 aWidth
<<= (sal_Int32
)PixelToLogic(Point(nColumnWidth
,0),MAP_10TH_MM
).X();
1576 xColModel
->setPropertyValue(FM_PROP_WIDTH
, aWidth
);
1580 //------------------------------------------------------------------------------
1581 void FmGridControl::CellModified()
1583 DbGridControl::CellModified();
1584 GetPeer()->CellModified();
1587 //------------------------------------------------------------------------------
1588 void FmGridControl::BeginCursorAction()
1590 DbGridControl::BeginCursorAction();
1591 m_pPeer
->stopCursorListening();
1594 //------------------------------------------------------------------------------
1595 void FmGridControl::EndCursorAction()
1597 m_pPeer
->startCursorListening();
1598 DbGridControl::EndCursorAction();
1601 //------------------------------------------------------------------------------
1602 void FmGridControl::ColumnMoved(sal_uInt16 nId
)
1604 m_bInColumnMove
= sal_True
;
1606 DbGridControl::ColumnMoved(nId
);
1607 Reference
< ::com::sun::star::container::XIndexContainer
> xColumns(GetPeer()->getColumns());
1611 // suchen der Spalte und verschieben im Model
1613 DbGridColumn
* pCol
= DbGridControl::GetColumns().GetObject(GetModelColumnPos(nId
));
1614 Reference
< ::com::sun::star::beans::XPropertySet
> xCol
;
1616 // Einfuegen muß sich an den Column Positionen orientieren
1618 Reference
< XInterface
> xCurrent
;
1619 for (i
= 0; !xCol
.is() && i
< xColumns
->getCount(); i
++)
1621 ::cppu::extractInterface(xCurrent
, xColumns
->getByIndex(i
));
1622 if (xCurrent
== pCol
->getModel())
1624 xCol
= pCol
->getModel();
1629 DBG_ASSERT(i
< xColumns
->getCount(), "Falscher ::com::sun::star::sdbcx::Index");
1630 xColumns
->removeByIndex(i
);
1633 xColumns
->insertByIndex(GetModelColumnPos(nId
), aElement
);
1634 pCol
->setModel(xCol
);
1635 // if the column which is shown here is selected ...
1636 if ( isColumnSelected(nId
,pCol
) )
1637 markColumn(nId
); // ... -> mark it
1640 m_bInColumnMove
= sal_False
;
1643 //------------------------------------------------------------------------------
1644 void FmGridControl::InitColumnsByModels(const Reference
< ::com::sun::star::container::XIndexContainer
>& xColumns
)
1646 // Spalten wieder neu setzen
1647 // wenn es nur eine HandleColumn gibt, dann nicht
1648 if (GetModelColCount())
1651 InsertHandleColumn();
1657 SetUpdateMode(sal_False
);
1659 // Einfuegen mu� sich an den Column Positionen orientieren
1663 for (i
= 0; i
< xColumns
->getCount(); ++i
)
1665 Reference
< ::com::sun::star::beans::XPropertySet
> xCol
;
1666 ::cppu::extractInterface(xCol
, xColumns
->getByIndex(i
));
1668 aName
= (const sal_Unicode
*)::comphelper::getString(xCol
->getPropertyValue(FM_PROP_LABEL
));
1670 aWidth
= xCol
->getPropertyValue(FM_PROP_WIDTH
);
1671 sal_Int32 nWidth
= 0;
1672 if (aWidth
>>= nWidth
)
1673 nWidth
= LogicToPixel(Point(nWidth
,0),MAP_10TH_MM
).X();
1675 AppendColumn(aName
, (sal_uInt16
)nWidth
);
1676 DbGridColumn
* pCol
= DbGridControl::GetColumns().GetObject(i
);
1677 pCol
->setModel(xCol
);
1680 // und jetzt noch die hidden columns rausnehmen
1681 // (wir haben das nicht gleich in der oberen Schleife gemacht, da wir dann Probleme mit den
1682 // IDs der Spalten bekommen haetten : AppendColumn vergibt die automatisch, die Spalte _nach_
1683 // einer versteckten braucht aber eine um eine erhoehte ID ....
1685 for (i
= 0; i
< xColumns
->getCount(); ++i
)
1687 Reference
< ::com::sun::star::beans::XPropertySet
> xCol
;
1688 ::cppu::extractInterface(xCol
, xColumns
->getByIndex(i
));
1689 aHidden
= xCol
->getPropertyValue(FM_PROP_HIDDEN
);
1690 if (::comphelper::getBOOL(aHidden
))
1691 HideColumn(GetColumnIdFromModelPos((sal_uInt16
)i
));
1694 SetUpdateMode(sal_True
);
1697 //------------------------------------------------------------------------------
1698 void FmGridControl::InitColumnByField(
1699 DbGridColumn
* _pColumn
, const Reference
< XPropertySet
>& _rxColumnModel
,
1700 const Reference
< XNameAccess
>& _rxFieldsByNames
, const Reference
< XIndexAccess
>& _rxFieldsByIndex
)
1702 DBG_ASSERT( _rxFieldsByNames
== _rxFieldsByIndex
, "FmGridControl::InitColumnByField: invalid container interfaces!" );
1704 // lookup the column which belongs to the control source
1705 ::rtl::OUString sFieldName
;
1706 _rxColumnModel
->getPropertyValue( FM_PROP_CONTROLSOURCE
) >>= sFieldName
;
1707 Reference
< XPropertySet
> xField
;
1708 _rxColumnModel
->getPropertyValue( FM_PROP_BOUNDFIELD
) >>= xField
;
1711 if ( !xField
.is() && /*sFieldName.getLength() && */_rxFieldsByNames
->hasByName( sFieldName
) ) // #i93452# do not check for name length
1712 _rxFieldsByNames
->getByName( sFieldName
) >>= xField
;
1714 // determine the position of this column
1715 sal_Int32 nFieldPos
= -1;
1718 Reference
< XPropertySet
> xCheck
;
1719 sal_Int32 nFieldCount
= _rxFieldsByIndex
->getCount();
1720 for ( sal_Int32 i
= 0; i
< nFieldCount
; ++i
)
1722 _rxFieldsByIndex
->getByIndex( i
) >>= xCheck
;
1723 if ( xField
.get() == xCheck
.get() )
1731 if ( xField
.is() && ( nFieldPos
>= 0 ) )
1733 // some data types are not allowed
1734 sal_Int32 nDataType
= DataType::OTHER
;
1735 xField
->getPropertyValue( FM_PROP_FIELDTYPE
) >>= nDataType
;
1737 sal_Bool bIllegalType
= sal_False
;
1738 switch ( nDataType
)
1740 case DataType::LONGVARBINARY
:
1741 case DataType::BINARY
:
1742 case DataType::VARBINARY
:
1743 case DataType::OTHER
:
1744 bIllegalType
= sal_True
;
1750 _pColumn
->SetObject( (sal_Int16
)nFieldPos
);
1754 // handle readonly columns
1755 sal_Bool bReadOnly
= sal_True
;
1756 xField
->getPropertyValue( FM_PROP_ISREADONLY
) >>= bReadOnly
;
1757 _pColumn
->SetReadOnly( bReadOnly
);
1760 // the control type is determined by the ColumnServiceName
1761 static ::rtl::OUString
s_sPropColumnServiceName( RTL_CONSTASCII_USTRINGPARAM( "ColumnServiceName" ) );
1762 if ( !::comphelper::hasProperty( s_sPropColumnServiceName
, _rxColumnModel
) )
1765 _pColumn
->setModel( _rxColumnModel
);
1767 ::rtl::OUString sColumnServiceName
;
1768 _rxColumnModel
->getPropertyValue( s_sPropColumnServiceName
) >>= sColumnServiceName
;
1770 sal_Int32 nTypeId
= getColumnTypeByModelName( sColumnServiceName
);
1771 _pColumn
->CreateControl( nFieldPos
, xField
, nTypeId
);
1774 //------------------------------------------------------------------------------
1775 void FmGridControl::InitColumnsByFields(const Reference
< ::com::sun::star::container::XIndexAccess
>& _rxFields
)
1777 if ( !_rxFields
.is() )
1780 // Spalten initialisieren
1781 Reference
< XIndexContainer
> xColumns( GetPeer()->getColumns() );
1782 Reference
< XNameAccess
> xFieldsAsNames( _rxFields
, UNO_QUERY
);
1784 // Einfuegen mu� sich an den Column Positionen orientieren
1785 for (sal_Int32 i
= 0; i
< xColumns
->getCount(); i
++)
1787 DbGridColumn
* pCol
= GetColumns().GetObject(i
);
1788 Reference
< XPropertySet
> xColumnModel
;
1789 ::cppu::extractInterface( xColumnModel
, xColumns
->getByIndex( i
) );
1791 InitColumnByField( pCol
, xColumnModel
, xFieldsAsNames
, _rxFields
);
1795 //------------------------------------------------------------------------------
1796 void FmGridControl::HideColumn(sal_uInt16 nId
)
1798 DbGridControl::HideColumn(nId
);
1800 sal_uInt16 nPos
= GetModelColumnPos(nId
);
1801 if (nPos
== (sal_uInt16
)-1)
1804 DbGridColumn
* pColumn
= GetColumns().GetObject(nPos
);
1805 if (pColumn
->IsHidden())
1806 GetPeer()->columnHidden(pColumn
);
1808 if (nId
== m_nMarkedColumnId
)
1809 m_nMarkedColumnId
= (sal_uInt16
)-1;
1811 // -----------------------------------------------------------------------------
1812 sal_Bool
FmGridControl::isColumnSelected(sal_uInt16
/*nId*/,DbGridColumn
* _pColumn
)
1814 OSL_ENSURE(_pColumn
,"Column can not be null!");
1815 sal_Bool bSelected
= sal_False
;
1816 // if the column which is shown here is selected ...
1817 Reference
< ::com::sun::star::view::XSelectionSupplier
> xSelSupplier(GetPeer()->getColumns(), UNO_QUERY
);
1818 if ( xSelSupplier
.is() )
1820 Reference
< ::com::sun::star::beans::XPropertySet
> xColumn
;
1821 xSelSupplier
->getSelection() >>= xColumn
;
1822 bSelected
= (xColumn
.get() == _pColumn
->getModel().get());
1827 //------------------------------------------------------------------------------
1828 void FmGridControl::ShowColumn(sal_uInt16 nId
)
1830 DbGridControl::ShowColumn(nId
);
1832 sal_uInt16 nPos
= GetModelColumnPos(nId
);
1833 if (nPos
== (sal_uInt16
)-1)
1836 DbGridColumn
* pColumn
= GetColumns().GetObject(nPos
);
1837 if (!pColumn
->IsHidden())
1838 GetPeer()->columnVisible(pColumn
);
1840 // if the column which is shown here is selected ...
1841 if ( isColumnSelected(nId
,pColumn
) )
1842 markColumn(nId
); // ... -> mark it
1845 //------------------------------------------------------------------------------
1846 sal_Bool
FmGridControl::selectBookmarks(const Sequence
< Any
>& _rBookmarks
)
1848 vos::OGuard
aGuard( Application::GetSolarMutex() );
1849 // need to lock the SolarMutex so that no paint call disturbs us ...
1851 if ( !m_pSeekCursor
)
1853 DBG_ERROR( "FmGridControl::selectBookmarks: no seek cursor!" );
1857 const Any
* pBookmark
= _rBookmarks
.getConstArray();
1858 const Any
* pBookmarkEnd
= pBookmark
+ _rBookmarks
.getLength();
1862 sal_Bool bAllSuccessfull
= sal_True
;
1865 for (; pBookmark
!= pBookmarkEnd
; ++pBookmark
)
1867 // move the seek cursor to the row given
1868 if (m_pSeekCursor
->moveToBookmark(*pBookmark
))
1869 SelectRow( m_pSeekCursor
->getRow() - 1);
1871 bAllSuccessfull
= sal_False
;
1876 DBG_ERROR("FmGridControl::selectBookmarks: could not move to one of the bookmarks!");
1880 return bAllSuccessfull
;
1883 //------------------------------------------------------------------------------
1884 Sequence
< Any
> FmGridControl::getSelectionBookmarks()
1886 // lock our update so no paint-triggered seeks interfere ...
1887 SetUpdateMode(sal_False
);
1889 sal_Int32 nSelectedRows
= GetSelectRowCount(), i
= 0;
1890 Sequence
< Any
> aBookmarks(nSelectedRows
);
1891 if ( nSelectedRows
)
1893 Any
* pBookmarks
= (Any
*)aBookmarks
.getArray();
1895 // (I'm not sure if the problem isn't deeper : The szenario : a large table displayed by a grid with a
1896 // thread-safe cursor (dBase). On loading the sdb-cursor started a counting thread. While this counting progress
1897 // was running, I tried do delete 3 records from within the grid. Deletion caused a SeekCursor, which did a
1898 // m_pSeekCursor->moveRelative and a m_pSeekCursor->getPosition.
1899 // Unfortunally the first call caused a propertyChanged(RECORDCOUNT) which resulted in a repaint of the
1900 // navigation bar and the grid. The latter itself will result in SeekRow calls. So after (successfully) returning
1901 // from the moveRelative the getPosition returns an invalid value. And so the SeekCursor fails.
1902 // In the consequence ALL parts of code where two calls to the seek cursor are done, while the second call _relys_ on
1903 // the first one, should be secured against recursion, with a broad-minded interpretion of "recursion" : if any of these
1904 // code parts is executed, no other should be accessible. But this sounds very difficult to achieve ....
1907 // The next problem caused by the same behaviuor (SeekCursor causes a propertyChanged) : when adjusting rows we implicitly
1908 // change our selection. So a "FirstSelected(); SeekCursor(); NextSelected();" may produce unpredictable results.
1909 // That's why we _first_ collect the indicies of the selected rows and _then_ their bookmarks.
1910 long nIdx
= FirstSelectedRow();
1913 // (we misuse the bookmarks array for this ...)
1914 pBookmarks
[i
++] <<= (sal_Int32
)nIdx
;
1915 nIdx
= NextSelectedRow();
1917 DBG_ASSERT(i
== nSelectedRows
, "FmGridControl::DeleteSelectedRows : could not collect the row indicies !");
1919 for (i
=0; i
<nSelectedRows
; ++i
)
1921 nIdx
= ::comphelper::getINT32(pBookmarks
[i
]);
1922 if (IsInsertionRow(nIdx
))
1924 // leerzeile nicht loeschen
1925 aBookmarks
.realloc(--nSelectedRows
);
1926 SelectRow(nIdx
,sal_False
); // selection aufheben fuer leerzeile
1930 // Zunaechst den DatenCursor auf den selektierten Satz pos.
1931 if (SeekCursor(nIdx
))
1933 GetSeekRow()->SetState(m_pSeekCursor
, sal_True
);
1935 pBookmarks
[i
] = m_pSeekCursor
->getBookmark();
1939 DBG_ERROR("FmGridControl::DeleteSelectedRows : a bookmark could not be determined !");
1943 SetUpdateMode(sal_True
);
1945 // if one of the SeekCursor-calls failed ....
1946 aBookmarks
.realloc(i
);
1948 // (the alternative : while collecting the bookmarks lock our propertyChanged, this should resolve both our problems.
1949 // but this would be incompatible as we need a locking flag, then ...)
1953 // -----------------------------------------------------------------------------
1956 ::rtl::OUString
getColumnPropertyFromPeer(FmXGridPeer
* _pPeer
,sal_Int32 _nPosition
,const ::rtl::OUString
& _sPropName
)
1958 ::rtl::OUString sRetText
;
1959 if ( _pPeer
&& _nPosition
!= -1)
1961 Reference
<XIndexContainer
> xIndex
= _pPeer
->getColumns();
1962 if ( xIndex
.is() && xIndex
->getCount() > _nPosition
)
1964 Reference
<XPropertySet
> xProp
;
1965 xIndex
->getByIndex( _nPosition
) >>= xProp
;
1967 xProp
->getPropertyValue( _sPropName
) >>= sRetText
;
1973 // Object data and state ------------------------------------------------------
1974 ::rtl::OUString
FmGridControl::GetAccessibleObjectName( ::svt::AccessibleBrowseBoxObjType _eObjType
,sal_Int32 _nPosition
) const
1976 ::rtl::OUString sRetText
;
1979 case ::svt::BBTYPE_BROWSEBOX
:
1982 Reference
<XPropertySet
> xProp(GetPeer()->getColumns(),UNO_QUERY
);
1984 xProp
->getPropertyValue(FM_PROP_NAME
) >>= sRetText
;
1987 case ::svt::BBTYPE_COLUMNHEADERCELL
:
1988 sRetText
= getColumnPropertyFromPeer(
1991 sal::static_int_cast
< sal_uInt16
>(_nPosition
)),
1995 sRetText
= DbGridControl::GetAccessibleObjectName(_eObjType
,_nPosition
);
1999 // -----------------------------------------------------------------------------
2001 ::rtl::OUString
FmGridControl::GetAccessibleObjectDescription( ::svt::AccessibleBrowseBoxObjType _eObjType
,sal_Int32 _nPosition
) const
2003 ::rtl::OUString sRetText
;
2006 case ::svt::BBTYPE_BROWSEBOX
:
2009 Reference
<XPropertySet
> xProp(GetPeer()->getColumns(),UNO_QUERY
);
2011 xProp
->getPropertyValue(FM_PROP_HELPTEXT
) >>= sRetText
;
2014 case ::svt::BBTYPE_COLUMNHEADERCELL
:
2015 sRetText
= getColumnPropertyFromPeer(
2018 sal::static_int_cast
< sal_uInt16
>(_nPosition
)),
2022 sRetText
= DbGridControl::GetAccessibleObjectDescription(_eObjType
,_nPosition
);
2026 // -----------------------------------------------------------------------------
2027 void FmGridControl::Select()
2029 DbGridControl::Select();
2030 // ... betrifft das unsere Spalten ?
2031 const MultiSelection
* pColumnSelection
= GetColumnSelection();
2033 sal_uInt16 nSelectedColumn
=
2034 pColumnSelection
&& pColumnSelection
->GetSelectCount()
2035 ? sal::static_int_cast
< sal_uInt16
>(
2036 ((MultiSelection
*)pColumnSelection
)->FirstSelected())
2038 // die HandleColumn wird nicht selektiert
2039 switch (nSelectedColumn
)
2041 case -1 : break; // no selection
2042 case 0 : nSelectedColumn
= SAL_MAX_UINT16
; break;
2043 // handle col can't be seledted
2045 // get the model col pos instead of the view col pos
2046 nSelectedColumn
= GetModelColumnPos(GetColumnIdFromViewPos(nSelectedColumn
- 1));
2050 if (nSelectedColumn
!= m_nCurrentSelectedColumn
)
2052 // VOR dem Aufruf des select am SelectionSupplier !
2053 m_nCurrentSelectedColumn
= nSelectedColumn
;
2057 m_bSelecting
= sal_True
;
2061 Reference
< XIndexAccess
> xColumns(GetPeer()->getColumns(), UNO_QUERY
);
2062 Reference
< XSelectionSupplier
> xSelSupplier(xColumns
, UNO_QUERY
);
2063 if (xSelSupplier
.is())
2065 if (nSelectedColumn
!= SAL_MAX_UINT16
)
2067 Reference
< XPropertySet
> xColumn
;
2068 ::cppu::extractInterface(xColumn
,xColumns
->getByIndex(nSelectedColumn
));
2069 xSelSupplier
->select(makeAny(xColumn
));
2073 xSelSupplier
->select(Any());
2082 m_bSelecting
= sal_False
;
2086 // -----------------------------------------------------------------------------
2087 sal_Int32
FmGridControl::GetSelectedColumn() const
2089 return m_nCurrentSelectedColumn
;
2091 // -----------------------------------------------------------------------------
2092 void FmGridControl::KeyInput( const KeyEvent
& rKEvt
)
2094 sal_Bool bDone
= sal_False
;
2095 const KeyCode
& rKeyCode
= rKEvt
.GetKeyCode();
2097 && !rKeyCode
.IsShift()
2098 && !rKeyCode
.IsMod1()
2099 && !rKeyCode
.IsMod2()
2102 switch ( rKeyCode
.GetCode() )
2105 GetParent()->GrabFocus();
2109 if ( GetSelectColumnCount() && GetPeer() && m_nCurrentSelectedColumn
>= 0 )
2111 Reference
< ::com::sun::star::container::XIndexContainer
> xCols(GetPeer()->getColumns());
2116 if ( m_nCurrentSelectedColumn
< xCols
->getCount() )
2118 Reference
< XInterface
> xCol
;
2119 xCols
->getByIndex(m_nCurrentSelectedColumn
) >>= xCol
;
2120 xCols
->removeByIndex(m_nCurrentSelectedColumn
);
2121 ::comphelper::disposeComponent(xCol
);
2124 catch(const Exception
&)
2126 OSL_ENSURE(0,"exception occured while deleting a column");
2135 DbGridControl::KeyInput( rKEvt
);
2137 // -----------------------------------------------------------------------------