xref: /aoo42x/main/svx/source/fmcomp/fmgridcl.cxx (revision cdf0e10c)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_svx.hxx"
30 
31 #include "svx/dbexch.hrc"
32 #include "svx/fmgridif.hxx"
33 #include "fmitems.hxx"
34 #include "fmprop.hrc"
35 #include "svx/fmtools.hxx"
36 #include "svx/fmresids.hrc"
37 #include "fmservs.hxx"
38 #include "fmurl.hxx"
39 #include "formcontrolfactory.hxx"
40 #include "gridcell.hxx"
41 #include "gridcols.hxx"
42 #include "svx/dbaexchange.hxx"
43 #include "svx/dialmgr.hxx"
44 #include "svx/dialogs.hrc"
45 #include "svx/fmgridcl.hxx"
46 #include "svx/svxdlg.hxx"
47 #include "svx/svxids.hrc"
48 #include "trace.hxx"
49 
50 #include <com/sun/star/form/XConfirmDeleteListener.hpp>
51 #include <com/sun/star/form/XFormComponent.hpp>
52 #include <com/sun/star/form/XGridColumnFactory.hpp>
53 #include <com/sun/star/io/XPersistObject.hpp>
54 #include <com/sun/star/sdb/CommandType.hpp>
55 #include <com/sun/star/sdb/RowChangeAction.hpp>
56 #include <com/sun/star/sdb/XQueriesSupplier.hpp>
57 #include <com/sun/star/sdbc/DataType.hpp>
58 #include <com/sun/star/sdbc/XPreparedStatement.hpp>
59 #include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
60 #include <com/sun/star/sdbcx/XDeleteRows.hpp>
61 #include <com/sun/star/sdbcx/XTablesSupplier.hpp>
62 #include <com/sun/star/uno/XNamingService.hpp>
63 #include <com/sun/star/util/XNumberFormats.hpp>
64 #include <com/sun/star/util/XNumberFormatsSupplier.hpp>
65 #include <com/sun/star/util/XURLTransformer.hpp>
66 #include <com/sun/star/view/XSelectionSupplier.hpp>
67 
68 #ifndef _SVSTDARR_STRINGSDTOR
69 #define _SVSTDARR_STRINGSDTOR
70 #define _SVSTDARR_ULONGS
71 #include <svl/svstdarr.hxx>
72 #endif
73 
74 #include <comphelper/extract.hxx>
75 #include <comphelper/numbers.hxx>
76 #include <comphelper/processfactory.hxx>
77 #include <comphelper/property.hxx>
78 #include <connectivity/dbtools.hxx>
79 #include <sfx2/dispatch.hxx>
80 #include <sfx2/viewfrm.hxx>
81 #include <svl/eitem.hxx>
82 #include <svtools/fmtfield.hxx>
83 #include <svl/numuno.hxx>
84 #include <tools/multisel.hxx>
85 #include <tools/shl.hxx>
86 #include <tools/diagnose_ex.h>
87 #include <vcl/help.hxx>
88 #include <vcl/image.hxx>
89 #include <vcl/longcurr.hxx>
90 #include <vcl/menu.hxx>
91 
92 #include <math.h>
93 
94 using namespace ::com::sun::star::uno;
95 using namespace ::com::sun::star::view;
96 using namespace ::com::sun::star::beans;
97 using namespace ::com::sun::star::lang;
98 using namespace ::com::sun::star::sdbcx;
99 using namespace ::com::sun::star::sdbc;
100 using namespace ::com::sun::star::sdb;
101 using namespace ::com::sun::star::form;
102 using namespace ::com::sun::star::util;
103 using namespace ::com::sun::star::container;
104 using namespace ::cppu;
105 using namespace ::svxform;
106 using namespace ::svx;
107 
108 //==============================================================================
109 //------------------------------------------------------------------------------
110 ::rtl::OUString FieldServiceFromId(sal_Int32 nID)
111 {
112 	switch (nID)
113 	{
114 		case SID_FM_EDIT			: return FM_COL_TEXTFIELD;
115 		case SID_FM_COMBOBOX		: return FM_COL_COMBOBOX;
116 		case SID_FM_LISTBOX 		: return FM_COL_LISTBOX;
117 		case SID_FM_CHECKBOX		: return FM_COL_CHECKBOX;
118 		case SID_FM_DATEFIELD		: return FM_COL_DATEFIELD;
119 		case SID_FM_TIMEFIELD		: return FM_COL_TIMEFIELD;
120 		case SID_FM_NUMERICFIELD	: return FM_COL_NUMERICFIELD;
121 		case SID_FM_CURRENCYFIELD	: return FM_COL_CURRENCYFIELD;
122 		case SID_FM_PATTERNFIELD	: return FM_COL_PATTERNFIELD;
123 		case SID_FM_FORMATTEDFIELD	: return FM_COL_FORMATTEDFIELD;
124 	}
125 	return ::rtl::OUString();
126 }
127 
128 //==============================================================================
129 struct FmGridHeaderData
130 {
131 	ODataAccessDescriptor	aDropData;
132 	Point					aDropPosPixel;
133 	sal_Int8				nDropAction;
134 	Reference< XInterface > xDroppedStatement;
135 	Reference< XInterface > xDroppedResultSet;
136 };
137 
138 //==============================================================================
139 //------------------------------------------------------------------------------
140 const sal_Int16 nChangeTypeOffset = 1000;
141 void SetMenuItem(const ImageList& rList, sal_uInt16 nID, Menu* pMenu, Menu& rNewMenu, sal_Bool bDesignMode = sal_True, sal_Int16 nOffset = nChangeTypeOffset)
142 {
143 	pMenu->SetItemImage(nID, rList.GetImage(nID));
144 	pMenu->EnableItem(nID, bDesignMode);
145 	rNewMenu.InsertItem(nID + nOffset, pMenu->GetItemText(nID));
146 	rNewMenu.SetItemImage(nID + nOffset, rList.GetImage(nID));
147 	rNewMenu.SetHelpId(nID + nOffset, pMenu->GetHelpId(nID));
148 	rNewMenu.EnableItem(nID + nOffset, bDesignMode);
149 }
150 
151 //------------------------------------------------------------------------------
152 FmGridHeader::FmGridHeader( BrowseBox* pParent, WinBits nWinBits)
153 		:EditBrowserHeader(pParent, nWinBits)
154 		,DropTargetHelper(this)
155 		,m_pImpl(new FmGridHeaderData)
156 {
157 }
158 
159 //------------------------------------------------------------------------------
160 FmGridHeader::~FmGridHeader()
161 {
162 	delete m_pImpl;
163 }
164 
165 //------------------------------------------------------------------------------
166 sal_uInt16 FmGridHeader::GetModelColumnPos(sal_uInt16 nId) const
167 {
168 	return static_cast<FmGridControl*>(GetParent())->GetModelColumnPos(nId);
169 }
170 //---------------------------------------------------------------------------------------
171 void FmGridHeader::notifyColumnSelect(sal_uInt16 nColumnId)
172 {
173 	sal_uInt16 nPos = GetModelColumnPos(nColumnId);
174 	Reference< XIndexAccess >  xColumns(((FmGridControl*)GetParent())->GetPeer()->getColumns(), UNO_QUERY);
175 	if ( nPos < xColumns->getCount() )
176 	{
177 		Reference< XSelectionSupplier >  xSelSupplier(xColumns, UNO_QUERY);
178 		if ( xSelSupplier.is() )
179 		{
180 			Reference< XPropertySet >  xColumn;
181 			xColumns->getByIndex(nPos) >>= xColumn;
182 			xSelSupplier->select(makeAny(xColumn));
183 		}
184 	}
185 }
186 //------------------------------------------------------------------------------
187 void FmGridHeader::Select()
188 {
189 	EditBrowserHeader::Select();
190 	notifyColumnSelect(GetCurItemId());
191 }
192 
193 //------------------------------------------------------------------------------
194 void FmGridHeader::RequestHelp( const HelpEvent& rHEvt )
195 {
196 	sal_uInt16 nItemId = GetItemId( ScreenToOutputPixel( rHEvt.GetMousePosPixel() ) );
197 	if ( nItemId )
198 	{
199 		if ( rHEvt.GetMode() & (HELPMODE_QUICK | HELPMODE_BALLOON) )
200 		{
201 			Rectangle aItemRect = GetItemRect( nItemId );
202 			Point aPt = OutputToScreenPixel( aItemRect.TopLeft() );
203 			aItemRect.Left()   = aPt.X();
204 			aItemRect.Top()    = aPt.Y();
205 			aPt = OutputToScreenPixel( aItemRect.BottomRight() );
206 			aItemRect.Right()  = aPt.X();
207 			aItemRect.Bottom() = aPt.Y();
208 
209 			sal_uInt16 nPos = GetModelColumnPos(nItemId);
210 			Reference< ::com::sun::star::container::XIndexContainer >  xColumns(static_cast<FmGridControl*>(GetParent())->GetPeer()->getColumns());
211 			try
212 			{
213 				Reference< ::com::sun::star::beans::XPropertySet >	xColumn(xColumns->getByIndex(nPos),UNO_QUERY);
214 				::rtl::OUString aHelpText;
215 				xColumn->getPropertyValue(FM_PROP_HELPTEXT) >>= aHelpText;
216                 if ( !aHelpText.getLength() )
217                     xColumn->getPropertyValue(FM_PROP_DESCRIPTION) >>= aHelpText;
218 				if ( aHelpText.getLength() )
219 				{
220 					if ( rHEvt.GetMode() & HELPMODE_BALLOON )
221 						Help::ShowBalloon( this, aItemRect.Center(), aItemRect, aHelpText );
222 					else
223 						Help::ShowQuickHelp( this, aItemRect, aHelpText );
224 					return;
225 				}
226 			}
227 			catch(Exception&)
228 			{
229 				return;
230 			}
231 		}
232 	}
233 	EditBrowserHeader::RequestHelp( rHEvt );
234 }
235 
236 //------------------------------------------------------------------------------
237 sal_Int8 FmGridHeader::AcceptDrop( const AcceptDropEvent& rEvt )
238 {
239 	// drop allowed in design mode only
240 	if (!static_cast<FmGridControl*>(GetParent())->IsDesignMode())
241 		return DND_ACTION_NONE;
242 
243 	// search for recognized formats
244 	const DataFlavorExVector& rFlavors = GetDataFlavorExVector();
245 	if (OColumnTransferable::canExtractColumnDescriptor(rFlavors, CTF_COLUMN_DESCRIPTOR | CTF_FIELD_DESCRIPTOR))
246 		return rEvt.mnAction;
247 
248 	return DND_ACTION_NONE;
249 }
250 
251 //------------------------------------------------------------------------------
252 sal_Int8 FmGridHeader::ExecuteDrop( const ExecuteDropEvent& _rEvt )
253 {
254 	if (!static_cast<FmGridControl*>(GetParent())->IsDesignMode())
255 		return DND_ACTION_NONE;
256 
257 	TransferableDataHelper aDroppedData(_rEvt.maDropEvent.Transferable);
258 
259 	// check the formats
260 	sal_Bool bColumnDescriptor	= OColumnTransferable::canExtractColumnDescriptor(aDroppedData.GetDataFlavorExVector(), CTF_COLUMN_DESCRIPTOR);
261 	sal_Bool bFieldDescriptor	= OColumnTransferable::canExtractColumnDescriptor(aDroppedData.GetDataFlavorExVector(), CTF_FIELD_DESCRIPTOR);
262 	if (!bColumnDescriptor && !bFieldDescriptor)
263 	{
264 		DBG_ERROR("FmGridHeader::ExecuteDrop: should never have reached this (no extractable format)!");
265 		return DND_ACTION_NONE;
266 	}
267 
268 	// extract the descriptor
269 	::rtl::OUString sDatasouce, sCommand, sFieldName,sDatabaseLocation,sConnnectionResource;
270 	sal_Int32		nCommandType = CommandType::COMMAND;
271 	Reference< XPreparedStatement > 	xStatement;
272 	Reference< XResultSet > 			xResultSet;
273 	Reference< XPropertySet >			xField;
274 	Reference< XConnection >			xConnection;
275 
276 	ODataAccessDescriptor aColumn = OColumnTransferable::extractColumnDescriptor(aDroppedData);
277 	if (aColumn.has(daDataSource))	aColumn[daDataSource]	>>= sDatasouce;
278 	if (aColumn.has(daDatabaseLocation))	aColumn[daDatabaseLocation]	>>= sDatabaseLocation;
279 	if (aColumn.has(daConnectionResource))	aColumn[daConnectionResource] >>= sConnnectionResource;
280 	if (aColumn.has(daCommand)) 	aColumn[daCommand]		>>= sCommand;
281 	if (aColumn.has(daCommandType)) aColumn[daCommandType]	>>= nCommandType;
282 	if (aColumn.has(daColumnName))	aColumn[daColumnName]	>>= sFieldName;
283 	if (aColumn.has(daColumnObject))aColumn[daColumnObject] >>= xField;
284 	if (aColumn.has(daConnection))	aColumn[daConnection]	>>= xConnection;
285 
286 	if  (   !sFieldName.getLength()
287         ||  !sCommand.getLength()
288         ||  (   !sDatasouce.getLength()
289             &&  !sDatabaseLocation.getLength()
290             &&  !xConnection.is()
291             )
292         )
293 	{
294 		DBG_ERROR( "FmGridHeader::ExecuteDrop: somebody started a nonsense drag operation!!" );
295 		return DND_ACTION_NONE;
296 	}
297 
298 	try
299 	{
300 		// need a connection
301 		if (!xConnection.is())
302 		{	// the transferable did not contain the connection -> build an own one
303 			try
304 			{
305                 ::rtl::OUString sSignificantSource( sDatasouce.getLength() ? sDatasouce : sDatabaseLocation );
306 				xConnection = OStaticDataAccessTools().getConnection_withFeedback(sSignificantSource, ::rtl::OUString(),::rtl::OUString(),static_cast<FmGridControl*>(GetParent())->getServiceManager());
307 			}
308 			catch(NoSuchElementException&)
309 			{	// allowed, means sDatasouce isn't a valid data source name ....
310 			}
311 			catch(Exception&)
312 			{
313 				DBG_ERROR("FmGridHeader::ExecuteDrop: could not retrieve the database access object !");
314 			}
315 
316 			if (!xConnection.is())
317 			{
318 				DBG_ERROR("FmGridHeader::ExecuteDrop: could not retrieve the database access object !");
319 				return DND_ACTION_NONE;
320 			}
321 		}
322 
323 		// try to obtain the column object
324 		if (!xField.is())
325 		{
326 #ifdef DBG_UTIL
327 			Reference< XServiceInfo >  xServiceInfo(xConnection, UNO_QUERY);
328 			DBG_ASSERT(xServiceInfo.is() && xServiceInfo->supportsService(SRV_SDB_CONNECTION), "FmGridHeader::ExecuteDrop: invalid connection (no database access connection !)");
329 #endif
330 
331 			Reference< XNameAccess > xFields;
332 			switch (nCommandType)
333 			{
334 				case CommandType::TABLE:
335 				{
336 					Reference< XTablesSupplier > xSupplyTables(xConnection, UNO_QUERY);
337 					Reference< XColumnsSupplier >  xSupplyColumns;
338 					xSupplyTables->getTables()->getByName(sCommand) >>= xSupplyColumns;
339 					xFields = xSupplyColumns->getColumns();
340 				}
341 				break;
342 				case CommandType::QUERY:
343 				{
344 					Reference< XQueriesSupplier > xSupplyQueries(xConnection, UNO_QUERY);
345 					Reference< XColumnsSupplier > xSupplyColumns;
346 					xSupplyQueries->getQueries()->getByName(sCommand) >>= xSupplyColumns;
347 					xFields  = xSupplyColumns->getColumns();
348 				}
349 				break;
350 				default:
351 				{
352 					xStatement = xConnection->prepareStatement(sCommand);
353 					// not interested in any results
354 
355 					Reference< XPropertySet > xStatProps(xStatement,UNO_QUERY);
356 					xStatProps->setPropertyValue(rtl::OUString::createFromAscii("MaxRows"), makeAny(sal_Int32(0)));
357 
358 					xResultSet = xStatement->executeQuery();
359 					Reference< XColumnsSupplier >  xSupplyCols(xResultSet, UNO_QUERY);
360 					if (xSupplyCols.is())
361 						xFields = xSupplyCols->getColumns();
362 				}
363 			}
364 
365 			if (xFields.is() && xFields->hasByName(sFieldName))
366 				xFields->getByName(sFieldName) >>= xField;
367 
368 			if (!xField.is())
369 			{
370 				::comphelper::disposeComponent(xStatement);
371 				return DND_ACTION_NONE;
372 			}
373 		}
374 
375 		// do the drop asynchronously
376 		// (85957 - UI actions within the drop are not allowed, but we want to open a popup menu)
377 		m_pImpl->aDropData = aColumn;
378 		m_pImpl->aDropData[daConnection] <<= xConnection;
379 		m_pImpl->aDropData[daColumnObject] <<= xField;
380 
381 		m_pImpl->nDropAction = _rEvt.mnAction;
382 		m_pImpl->aDropPosPixel = _rEvt.maPosPixel;
383 		m_pImpl->xDroppedStatement = xStatement;
384 		m_pImpl->xDroppedResultSet = xResultSet;
385 
386 		PostUserEvent(LINK(this, FmGridHeader, OnAsyncExecuteDrop));
387 	}
388 	catch (Exception&)
389 	{
390 		DBG_ERROR("FmGridHeader::ExecuteDrop: caught an exception while creatin' the column !");
391 		::comphelper::disposeComponent(xStatement);
392 		return sal_False;
393 	}
394 
395 	return DND_ACTION_LINK;
396 }
397 
398 //------------------------------------------------------------------------------
399 IMPL_LINK( FmGridHeader, OnAsyncExecuteDrop, void*, /*NOTINTERESTEDIN*/ )
400 {
401 	::rtl::OUString 			sCommand, sFieldName,sURL;
402 	sal_Int32					nCommandType = CommandType::COMMAND;
403 	Reference< XPropertySet >	xField;
404 	Reference< XConnection >	xConnection;
405 
406 	::rtl::OUString sDatasouce = m_pImpl->aDropData.getDataSource();
407 	if ( !sDatasouce.getLength() && m_pImpl->aDropData.has(daConnectionResource) )
408 		m_pImpl->aDropData[daConnectionResource]	>>= sURL;
409 	m_pImpl->aDropData[daCommand]		>>= sCommand;
410 	m_pImpl->aDropData[daCommandType]	>>= nCommandType;
411 	m_pImpl->aDropData[daColumnName]	>>= sFieldName;
412 	m_pImpl->aDropData[daConnection]	>>= xConnection;
413 	m_pImpl->aDropData[daColumnObject]	>>= xField;
414 
415 	try
416 	{
417 		// need number formats
418 		Reference< XNumberFormatsSupplier > xSupplier = OStaticDataAccessTools().getNumberFormats(xConnection, sal_True);
419 		Reference< XNumberFormats >  xNumberFormats;
420 		if (xSupplier.is())
421 			xNumberFormats = xSupplier->getNumberFormats();
422 		if (!xNumberFormats.is())
423 		{
424 			::comphelper::disposeComponent(m_pImpl->xDroppedResultSet);
425 			::comphelper::disposeComponent(m_pImpl->xDroppedStatement);
426 			return 0L;
427 		}
428 
429 		// Vom Feld werden nun zwei Informationen benoetigt:
430 		// a.) Name des Feldes fuer Label und ControlSource
431 		// b.) FormatKey, um festzustellen, welches Feld erzeugt werden soll
432 		sal_Int32 nDataType = 0;
433 		xField->getPropertyValue(FM_PROP_FIELDTYPE) >>= nDataType;
434 		// diese Datentypen koennen im Gridcontrol nicht verarbeitet werden
435 		switch (nDataType)
436 		{
437 			case DataType::BLOB:
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);
444 				return 0L;
445 		}
446 
447 		// Erstellen der Column
448 		Reference< XIndexContainer >  xCols(static_cast<FmGridControl*>(GetParent())->GetPeer()->getColumns());
449 		Reference< XGridColumnFactory >  xFactory(xCols, UNO_QUERY);
450 
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;
456 
457 		// erzeugen der Column in abhaengigkeit vom type, default textfeld
458 		SvULongs aPossibleTypes;
459 		switch (nDataType)
460 		{
461 			case DataType::BIT:
462 			case DataType::BOOLEAN:
463 				aPossibleTypes.Insert(SID_FM_CHECKBOX, aPossibleTypes.Count());
464 				break;
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());
470 				break;
471 			case DataType::REAL:
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());
477 				break;
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());
483 				break;
484 			case DataType::DATE:
485 				aPossibleTypes.Insert(SID_FM_DATEFIELD, aPossibleTypes.Count());
486 				aPossibleTypes.Insert(SID_FM_FORMATTEDFIELD, aPossibleTypes.Count());
487 				break;
488 			case DataType::TIME:
489 				aPossibleTypes.Insert(SID_FM_TIMEFIELD, aPossibleTypes.Count());
490 				aPossibleTypes.Insert(SID_FM_FORMATTEDFIELD, aPossibleTypes.Count());
491 				break;
492 			case DataType::CHAR:
493 			case DataType::VARCHAR:
494 			case DataType::LONGVARCHAR:
495 			default:
496 				aPossibleTypes.Insert(SID_FM_EDIT, aPossibleTypes.Count());
497 				aPossibleTypes.Insert(SID_FM_FORMATTEDFIELD, aPossibleTypes.Count());
498 				break;
499 		}
500 		// if it's a currency field, a a "currency field" option
501 		try
502 		{
503 			if	(	::comphelper::hasProperty(FM_PROP_ISCURRENCY, xField)
504 				&&	::comphelper::getBOOL(xField->getPropertyValue(FM_PROP_ISCURRENCY)))
505 				aPossibleTypes.Insert(SID_FM_CURRENCYFIELD, 0);
506 		}
507 		catch(Exception&)
508 		{
509 			DBG_ERROR("FmGridHeader::ExecuteDrop: Exception occured!");
510 		}
511 
512 		sal_Int32 nPreferedType = -1;
513 		sal_Bool bDateNTimeCol = sal_False;
514 		if (aPossibleTypes.Count() != 0)
515 		{
516 			nPreferedType = aPossibleTypes[0];
517 			if ((m_pImpl->nDropAction == DND_ACTION_LINK) && (aPossibleTypes.Count() > 1))
518 			{
519 				ImageList aImageList( SVX_RES(RID_SVXIMGLIST_FMEXPL) );
520 
521 				PopupMenu aInsertMenu(SVX_RES(RID_SVXMNU_COLS));
522 				PopupMenu aTypeMenu;
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);
527 			}
528 
529 			bDateNTimeCol = nPreferedType == SID_FM_TWOFIELDS_DATE_N_TIME;
530 			sal_uInt16 nColCount = bDateNTimeCol ? 2 : 1;
531 			::rtl::OUString sFieldService;
532 			while (nColCount--)
533 			{
534 				if (bDateNTimeCol)
535 					nPreferedType = nColCount ? SID_FM_DATEFIELD : SID_FM_TIMEFIELD;
536 
537 				sFieldService = FieldServiceFromId(nPreferedType);
538 				Reference< XPropertySet >  xThisRoundCol;
539 				if ( sFieldService.getLength() )
540 					xThisRoundCol = xFactory->createColumn(sFieldService);
541 				if (nColCount)
542 					xSecondCol = xThisRoundCol;
543 				else
544 					xCol = xThisRoundCol;
545 			}
546 		}
547 
548 		if (!xCol.is() || (bDateNTimeCol && !xSecondCol.is()))
549 		{
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);
553 			return 0L;
554 		}
555 
556 		if (bDateNTimeCol)
557 		{
558             String sTimePostfix( SVX_RES( RID_STR_POSTFIX_TIME ) );
559             xCol->setPropertyValue(FM_PROP_LABEL, makeAny( ::rtl::OUString( sFieldName + sTimePostfix ) ) );
560 
561             String sDatePostfix( SVX_RES( RID_STR_POSTFIX_DATE ) );
562             xSecondCol->setPropertyValue(FM_PROP_LABEL, makeAny( ::rtl::OUString( sFieldName + sDatePostfix ) ) );
563 		}
564 		else
565 			xCol->setPropertyValue(FM_PROP_LABEL, makeAny(sFieldName));
566 
567         FormControlFactory aControlFactory( ::comphelper::getProcessServiceFactory() );
568         aControlFactory.initializeControlModel( DocumentClassification::classifyHostDocument( xCols ), xCol );
569         aControlFactory.initializeFieldDependentProperties( xField, xCol, xNumberFormats );
570 
571 		xCol->setPropertyValue(FM_PROP_CONTROLSOURCE, makeAny(sFieldName));
572 		if ( xSecondCol.is() )
573 			xSecondCol->setPropertyValue(FM_PROP_CONTROLSOURCE, makeAny(sFieldName));
574 
575 		if (bDateNTimeCol)
576 		{
577 			String sRealName,sPurePostfix;
578 
579             String aPostfix[] = {
580                 String( SVX_RES( RID_STR_POSTFIX_DATE ) ),
581                 String( SVX_RES( RID_STR_POSTFIX_TIME ) )
582             };
583 
584 			for ( size_t i=0; i<2; ++i )
585 			{
586                 sPurePostfix = aPostfix[i];
587 				sPurePostfix.EraseLeadingChars(' ');
588 				sPurePostfix.EraseLeadingChars('(');
589 				sPurePostfix.EraseTrailingChars(')');
590 				sRealName = sFieldName;
591 				sRealName += '_';
592 				sRealName += sPurePostfix;
593 				if (i)
594 					xSecondCol->setPropertyValue(FM_PROP_NAME, makeAny(::rtl::OUString(sRealName)));
595 				else
596 					xCol->setPropertyValue(FM_PROP_NAME, makeAny(::rtl::OUString(sRealName)));
597 			}
598 		}
599 		else
600 			xCol->setPropertyValue(FM_PROP_NAME, makeAny(sFieldName));
601 
602 		// jetzt einfuegen
603 		Any aElement;
604 		aElement <<= xCol;
605 		xCols->insertByIndex(nPos, aElement);
606 
607 		if (bDateNTimeCol)
608 		{
609 			aElement <<= xSecondCol;
610 			xCols->insertByIndex(nPos == (sal_uInt16)-1 ? nPos : ++nPos, aElement);
611 		}
612 
613 		// ist die component::Form an die Datenbankangebunden?
614 		Reference< XFormComponent >  xFormCp(xCols, UNO_QUERY);
615 		Reference< XPropertySet >  xForm(xFormCp->getParent(), UNO_QUERY);
616 		if (xForm.is())
617 		{
618 			if (!::comphelper::getString(xForm->getPropertyValue(FM_PROP_DATASOURCE)).getLength())
619 			{
620 				if ( sDatasouce.getLength() )
621 					xForm->setPropertyValue(FM_PROP_DATASOURCE, makeAny(sDatasouce));
622 				else
623 					xForm->setPropertyValue(FM_PROP_URL, makeAny(sURL));
624 			}
625 
626 			if (!::comphelper::getString(xForm->getPropertyValue(FM_PROP_COMMAND)).getLength())
627 			{
628 				xForm->setPropertyValue(FM_PROP_COMMAND, makeAny(sCommand));
629 				Any aCommandType;
630 				switch (nCommandType)
631 				{
632 					case CommandType::TABLE:
633 						aCommandType <<= (sal_Int32)CommandType::TABLE;
634 						break;
635 					case CommandType::QUERY:
636 						aCommandType <<= (sal_Int32)CommandType::QUERY;
637 						break;
638 					default:
639 						aCommandType <<= (sal_Int32)CommandType::COMMAND;
640 						xForm->setPropertyValue(FM_PROP_ESCAPE_PROCESSING, bool2any((sal_Bool)(2 == nCommandType)));
641 						break;
642 				}
643 				xForm->setPropertyValue(FM_PROP_COMMANDTYPE, aCommandType);
644 			}
645 		}
646 	}
647 	catch (Exception&)
648 	{
649 		DBG_ERROR("FmGridHeader::OnAsyncExecuteDrop: caught an exception while creatin' the column !");
650 		::comphelper::disposeComponent(m_pImpl->xDroppedResultSet);
651 		::comphelper::disposeComponent(m_pImpl->xDroppedStatement);
652 		return 0L;
653 	}
654 
655 	::comphelper::disposeComponent(m_pImpl->xDroppedResultSet);
656 	::comphelper::disposeComponent(m_pImpl->xDroppedStatement);
657 	return 1L;
658 }
659 
660 //------------------------------------------------------------------------------
661 void FmGridHeader::PreExecuteColumnContextMenu(sal_uInt16 nColId, PopupMenu& rMenu)
662 {
663 	sal_Bool bDesignMode = static_cast<FmGridControl*>(GetParent())->IsDesignMode();
664 
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
668 	if(nColId > 0)
669 	{
670 		sal_uInt16 nPos2 = GetModelColumnPos(nColId);
671 
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));
678 	}
679 
680 	// EinfuegePosition, immer vor der aktuellen Spalte
681 	sal_uInt16 nPos = GetModelColumnPos(nColId);
682 	sal_Bool bMarked = nColId && static_cast<FmGridControl*>(GetParent())->isColumnMarked(nColId);
683 
684 	ImageList aImageList( SVX_RES(RID_SVXIMGLIST_FMEXPL) );
685 	PopupMenu* pControlMenu = new PopupMenu;
686 
687 	PopupMenu* pMenu = rMenu.GetPopupMenu(SID_FM_INSERTCOL);
688 	if (pMenu)
689 	{
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);
700 	}
701 
702 	if (pMenu && xCols.is() && nColId)
703 	{
704 		Reference< ::com::sun::star::beans::XPropertySet > xSet;
705 		::cppu::extractInterface(xSet, xCols->getByIndex(nPos));
706 		sal_Int16 nClassId;
707 		xSet->getPropertyValue(FM_PROP_CLASSID) >>= nClassId;
708 
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);
716 			if (xProps.is())
717 			{
718 				Reference< ::com::sun::star::beans::XPropertySetInfo >	xPropsInfo = xProps->getPropertySetInfo();
719 				if (xPropsInfo.is() && xPropsInfo->hasPropertyByName(FM_PROP_FORMATSSUPPLIER))
720 					nColType = TYPE_FORMATTEDFIELD;
721 			}
722 		}
723 
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);
735 	}
736 
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());
741 
742 	PopupMenu* pShowColsMenu = rMenu.GetPopupMenu(SID_FM_SHOWCOLS);
743 	sal_uInt16 nHiddenCols = 0;
744 	if (pShowColsMenu)
745 	{
746 		if (xCols.is())
747 		{
748 			// check for hidden cols
749 			Reference< ::com::sun::star::beans::XPropertySet >	xCurCol;
750 			Any aHidden,aName;
751 			for (sal_uInt16 i=0; i<xCols->getCount(); ++i)
752 			{
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))
759 				{
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
766 					}
767 					++nHiddenCols;
768 				}
769 			}
770 		}
771 		pShowColsMenu->EnableItem(SID_FM_SHOWCOLS_MORE, xCols.is() && (nHiddenCols > 16));
772 		pShowColsMenu->EnableItem(SID_FM_SHOWALLCOLS, xCols.is() && (nHiddenCols > 0));
773 	}
774 
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);
781 
782 	sal_Bool bChecked = sal_False;
783 	if (bMarked)
784 	{
785 
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
789 		if (pCurrentFrame)
790 		{
791 			SfxPoolItem* pItem = NULL;
792 			eState = pCurrentFrame->GetBindings().QueryState(SID_FM_CTL_PROPERTIES, pItem);
793 
794 			if (eState >= SFX_ITEM_AVAILABLE && pItem )
795 			{
796 				bChecked = pItem->ISA(SfxBoolItem) && ((SfxBoolItem*)pItem)->GetValue();
797 				rMenu.CheckItem(SID_FM_SHOW_PROPERTY_BROWSER,bChecked);
798 			}
799 			delete pItem;
800 		}
801 	}
802 }
803 
804 enum InspectorAction { eOpenInspector, eCloseInspector, eUpdateInspector, eNone };
805 
806 //------------------------------------------------------------------------------
807 void FmGridHeader::PostExecuteColumnContextMenu(sal_uInt16 nColId, const PopupMenu& rMenu, sal_uInt16 nExecutionResult)
808 {
809 	Reference< ::com::sun::star::container::XIndexContainer >  xCols(static_cast<FmGridControl*>(GetParent())->GetPeer()->getColumns());
810 	sal_uInt16 nPos = GetModelColumnPos(nColId);
811 
812 	// remove and delet the menu we inserted in PreExecuteColumnContextMenu
813 	PopupMenu* pControlMenu = rMenu.GetPopupMenu(SID_FM_CHANGECOL);
814 	delete pControlMenu;
815 
816 	::rtl::OUString aFieldType;
817 	sal_Bool	bReplace = sal_False;
818     InspectorAction eInspectorAction = eNone;
819     Reference< XPropertySet > xColumnToInspect;
820 	switch (nExecutionResult)
821 	{
822 		case SID_FM_DELETECOL:
823 		{
824 			Reference< XInterface >  xCol;
825 			::cppu::extractInterface(xCol, xCols->getByIndex(nPos));
826 			xCols->removeByIndex(nPos);
827 			::comphelper::disposeComponent(xCol);
828 		}	break;
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 );
832             break;
833 		case SID_FM_EDIT + nChangeTypeOffset:
834 			bReplace = sal_True;
835 		case SID_FM_EDIT:
836 			aFieldType = FM_COL_TEXTFIELD;
837 			break;
838 		case SID_FM_COMBOBOX + nChangeTypeOffset:
839 			bReplace = sal_True;
840 		case SID_FM_COMBOBOX:
841 			aFieldType = FM_COL_COMBOBOX;
842 			break;
843 		case SID_FM_LISTBOX + nChangeTypeOffset:
844 			bReplace = sal_True;
845 		case SID_FM_LISTBOX:
846 			aFieldType = FM_COL_LISTBOX;
847 			break;
848 		case SID_FM_CHECKBOX + nChangeTypeOffset:
849 			bReplace = sal_True;
850 		case SID_FM_CHECKBOX:
851 			aFieldType = FM_COL_CHECKBOX;
852 			break;
853 		case SID_FM_DATEFIELD + nChangeTypeOffset:
854 			bReplace = sal_True;
855 		case SID_FM_DATEFIELD:
856 			aFieldType = FM_COL_DATEFIELD;
857 			break;
858 		case SID_FM_TIMEFIELD + nChangeTypeOffset:
859 			bReplace = sal_True;
860 		case SID_FM_TIMEFIELD:
861 			aFieldType = FM_COL_TIMEFIELD;
862 			break;
863 		case SID_FM_NUMERICFIELD + nChangeTypeOffset:
864 			bReplace = sal_True;
865 		case SID_FM_NUMERICFIELD:
866 			aFieldType = FM_COL_NUMERICFIELD;
867 			break;
868 		case SID_FM_CURRENCYFIELD + nChangeTypeOffset:
869 			bReplace = sal_True;
870 		case SID_FM_CURRENCYFIELD:
871 			aFieldType = FM_COL_CURRENCYFIELD;
872 			break;
873 		case SID_FM_PATTERNFIELD + nChangeTypeOffset:
874 			bReplace = sal_True;
875 		case SID_FM_PATTERNFIELD:
876 			aFieldType = FM_COL_PATTERNFIELD;
877 			break;
878 		case SID_FM_FORMATTEDFIELD + nChangeTypeOffset:
879 			bReplace = sal_True;
880 		case SID_FM_FORMATTEDFIELD:
881 			aFieldType = FM_COL_FORMATTEDFIELD;
882 			break;
883 		case SID_FM_HIDECOL:
884 		{
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));
888 		}
889 		break;
890 		case SID_FM_SHOWCOLS_MORE:
891 		{
892 			SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
893 			if(pFact)
894 			{
895 				AbstractFmShowColsDialog* pDlg = pFact->CreateFmShowColsDialog(NULL);
896 				DBG_ASSERT(pDlg, "Dialogdiet fail!");//CHINA001
897 				pDlg->SetColumns(xCols);
898 				pDlg->Execute();
899 				delete pDlg;
900 			}
901 
902 		}
903 		break;
904 		case SID_FM_SHOWALLCOLS:
905 		{
906 			// just iterate through all the cols ...
907 			Reference< ::com::sun::star::beans::XPropertySet >	xCurCol;
908 			for (sal_uInt16 i=0; i<xCols->getCount(); ++i)
909 			{
910 				::cppu::extractInterface(xCurCol, xCols->getByIndex(i));
911 				xCurCol->setPropertyValue(FM_PROP_HIDDEN, makeAny((sal_Bool)sal_False));
912 			}
913 			// TODO : there must be a more clever way to do this ....
914 			// with the above the view is updated after every single model update ...
915 		}
916 		break;
917 		default:
918 			if (nExecutionResult>0 && nExecutionResult<=16)
919 			{	// it was a "show column/<colname>" command (there are at most 16 such items)
920 				// search the nExecutionResult'th hidden col
921 				Reference< ::com::sun::star::beans::XPropertySet >	xCurCol;
922 				for (sal_uInt16 i=0; i<xCols->getCount() && nExecutionResult; ++i)
923 				{
924 					::cppu::extractInterface(xCurCol, xCols->getByIndex(i));
925 					Any aHidden = xCurCol->getPropertyValue(FM_PROP_HIDDEN);
926 					if (::comphelper::getBOOL(aHidden))
927 						if (!--nExecutionResult)
928 						{
929 							xCurCol->setPropertyValue(FM_PROP_HIDDEN, makeAny((sal_Bool)sal_False));
930 							break;
931 						}
932 				}
933 			}
934 			break;
935 	}
936 
937 	if ( aFieldType.getLength() )
938 	{
939         try
940         {
941             Reference< XGridColumnFactory > xFactory( xCols, UNO_QUERY_THROW );
942             Reference< XPropertySet > xNewCol( xFactory->createColumn( aFieldType ), UNO_SET_THROW );
943 
944             if ( bReplace )
945             {
946                 // ein paar Properties hinueberretten
947                 Reference< XPropertySet > xReplaced( xCols->getByIndex( nPos ), UNO_QUERY );
948 
949                 OStaticDataAccessTools().TransferFormComponentProperties(
950                     xReplaced, xNewCol, Application::GetSettings().GetUILocale() );
951 
952                 xCols->replaceByIndex( nPos, makeAny( xNewCol ) );
953                 ::comphelper::disposeComponent( xReplaced );
954 
955                 eInspectorAction = eUpdateInspector;
956                 xColumnToInspect = xNewCol;
957             }
958             else
959             {
960                 FormControlFactory factory( ::comphelper::getProcessServiceFactory() );
961 
962                 ::rtl::OUString sLabel = factory.getDefaultUniqueName_ByComponentType(
963                     Reference< XNameAccess >( xCols, UNO_QUERY_THROW ), xNewCol );
964                 xNewCol->setPropertyValue( FM_PROP_LABEL, makeAny( sLabel ) );
965                 xNewCol->setPropertyValue( FM_PROP_NAME, makeAny( sLabel ) );
966 
967                 factory.initializeControlModel( DocumentClassification::classifyHostDocument( xCols ), xNewCol );
968 
969                 xCols->insertByIndex( nPos, makeAny( xNewCol ) );
970             }
971         }
972         catch( const Exception& )
973         {
974         	DBG_UNHANDLED_EXCEPTION();
975         }
976 	}
977 
978     SfxViewFrame* pCurrentFrame = SfxViewFrame::Current();
979     OSL_ENSURE( pCurrentFrame, "FmGridHeader::PostExecuteColumnContextMenu: no view frame -> no bindings -> no property browser!" );
980     if ( pCurrentFrame )
981     {
982         if ( eInspectorAction == eUpdateInspector )
983         {
984             if ( !pCurrentFrame->HasChildWindow( SID_FM_SHOW_PROPERTIES ) )
985                 eInspectorAction = eNone;
986         }
987 
988         if ( eInspectorAction != eNone )
989         {
990             FmInterfaceItem aIFaceItem( SID_FM_SHOW_PROPERTY_BROWSER, xColumnToInspect );
991             SfxBoolItem aShowItem( SID_FM_SHOW_PROPERTIES, eInspectorAction == eCloseInspector ? sal_False : sal_True );
992 
993             pCurrentFrame->GetBindings().GetDispatcher()->Execute( SID_FM_SHOW_PROPERTY_BROWSER, SFX_CALLMODE_ASYNCHRON,
994                                       &aIFaceItem, &aShowItem, 0L );
995         }
996     }
997 }
998 
999 //------------------------------------------------------------------------------
1000 void FmGridHeader::triggerColumnContextMenu( const ::Point& _rPreferredPos )
1001 {
1002 	// the affected col
1003 	sal_uInt16 nColId = GetItemId( _rPreferredPos );
1004 
1005 	// the menu
1006 	PopupMenu aContextMenu( SVX_RES( RID_SVXMNU_COLS ) );
1007 
1008 	// let derivees modify the menu
1009 	PreExecuteColumnContextMenu( nColId, aContextMenu );
1010 	aContextMenu.RemoveDisabledEntries( sal_True, sal_True );
1011 
1012 	// execute the menu
1013 	sal_uInt16 nResult = aContextMenu.Execute( this, _rPreferredPos );
1014 
1015 	// let derivees handle the result
1016 	PostExecuteColumnContextMenu( nColId, aContextMenu, nResult );
1017 }
1018 
1019 //------------------------------------------------------------------------------
1020 void FmGridHeader::Command(const CommandEvent& rEvt)
1021 {
1022 	switch (rEvt.GetCommand())
1023 	{
1024 		case COMMAND_CONTEXTMENU:
1025 		{
1026 			if (!rEvt.IsMouseEvent())
1027 				return;
1028 
1029 			triggerColumnContextMenu( rEvt.GetMousePosPixel() );
1030 		}
1031 		break;
1032 		default:
1033 			EditBrowserHeader::Command(rEvt);
1034 	}
1035 }
1036 
1037 //------------------------------------------------------------------------------
1038 FmGridControl::FmGridControl(
1039 				Reference< ::com::sun::star::lang::XMultiServiceFactory > _rxFactory,
1040 				Window* pParent,
1041 				FmXGridPeer* _pPeer,
1042 				WinBits nBits)
1043 		:DbGridControl(_rxFactory, pParent, nBits)
1044         ,m_pPeer(_pPeer)
1045         ,m_nCurrentSelectedColumn(-1)
1046 		,m_nMarkedColumnId(BROWSER_INVALIDID)
1047         ,m_bSelecting(sal_False)
1048         ,m_bInColumnMove(sal_False)
1049 {
1050     EnableInteractiveRowHeight( );
1051 }
1052 
1053 //------------------------------------------------------------------------------
1054 void FmGridControl::Command(const CommandEvent& _rEvt)
1055 {
1056 	if ( COMMAND_CONTEXTMENU == _rEvt.GetCommand() )
1057 	{
1058 		FmGridHeader* pMyHeader = static_cast< FmGridHeader* >( GetHeaderBar() );
1059         if ( pMyHeader && !_rEvt.IsMouseEvent() )
1060 		{	// context menu requested by keyboard
1061 			if	( 1 == GetSelectColumnCount() || IsDesignMode() )
1062 			{
1063 				sal_uInt16 nSelId = GetColumnId(
1064                     sal::static_int_cast< sal_uInt16 >( FirstSelectedColumn() ) );
1065 				::Rectangle aColRect( GetFieldRectPixel( 0, nSelId, sal_False ) );
1066 
1067                 Point aRelativePos( pMyHeader->ScreenToOutputPixel( OutputToScreenPixel( aColRect.TopCenter() ) ) );
1068                 pMyHeader->triggerColumnContextMenu( aRelativePos, FmGridHeader::AccessControl() );
1069 
1070 				// handled
1071 				return;
1072 			}
1073 		}
1074 	}
1075 
1076 	DbGridControl::Command( _rEvt );
1077 }
1078 
1079 // ::com::sun::star::beans::XPropertyChangeListener
1080 //------------------------------------------------------------------------------
1081 void FmGridControl::propertyChange(const ::com::sun::star::beans::PropertyChangeEvent& evt)
1082 {
1083 	if (evt.PropertyName == FM_PROP_ROWCOUNT)
1084 	{
1085 		// if we're not in the main thread call AdjustRows asynchronously
1086 		implAdjustInSolarThread(sal_True);
1087 		return;
1088 	}
1089 
1090 	const DbGridRowRef& xRow = GetCurrentRow();
1091 	// waehrend Positionierung wird kein abgleich  der Properties vorgenommen
1092 	Reference<XPropertySet> xSet(evt.Source,UNO_QUERY);
1093 	if (xRow.Is() && (::cppu::any2bool(xSet->getPropertyValue(FM_PROP_ISNEW))|| CompareBookmark(getDataSource()->getBookmark(), xRow->GetBookmark())))
1094 	{
1095 		if (evt.PropertyName == FM_PROP_ISMODIFIED)
1096 		{
1097 			// modified or clean ?
1098 			GridRowStatus eStatus = ::comphelper::getBOOL(evt.NewValue) ? GRS_MODIFIED : GRS_CLEAN;
1099 			if (eStatus != xRow->GetStatus())
1100 			{
1101 				xRow->SetStatus(eStatus);
1102 				vos::OGuard aGuard( Application::GetSolarMutex() );
1103 				RowModified(GetCurrentPos());
1104 			}
1105 		}
1106 	}
1107 }
1108 
1109 //------------------------------------------------------------------------------
1110 void FmGridControl::SetDesignMode(sal_Bool bMode)
1111 {
1112 	sal_Bool bOldMode = IsDesignMode();
1113 	DbGridControl::SetDesignMode(bMode);
1114 	if (bOldMode != bMode)
1115 	{
1116 		if (!bMode)
1117 		{
1118 			// selection aufheben
1119 			markColumn(USHRT_MAX);
1120 		}
1121 		else
1122 		{
1123 			Reference< ::com::sun::star::container::XIndexContainer >  xColumns(GetPeer()->getColumns());
1124 			Reference< ::com::sun::star::view::XSelectionSupplier >  xSelSupplier(xColumns, UNO_QUERY);
1125 			if (xSelSupplier.is())
1126 			{
1127 				Any aSelection = xSelSupplier->getSelection();
1128 				Reference< ::com::sun::star::beans::XPropertySet >	xColumn;
1129 				if (aSelection.getValueType().getTypeClass() == TypeClass_INTERFACE)
1130 					::cppu::extractInterface(xColumn, aSelection);
1131 				Reference< XInterface >  xCurrent;
1132 				for (sal_uInt16 i=0; i<xColumns->getCount(); ++i)
1133 				{
1134 					::cppu::extractInterface(xCurrent, xColumns->getByIndex(i));
1135 					if (xCurrent == xColumn)
1136 					{
1137 						markColumn(GetColumnIdFromModelPos(i));
1138 						break;
1139 					}
1140 				}
1141 			}
1142 		}
1143 	}
1144 }
1145 
1146 //------------------------------------------------------------------------------
1147 void FmGridControl::DeleteSelectedRows()
1148 {
1149 	if (!m_pSeekCursor)
1150 		return;
1151 
1152 	// how many rows are selected?
1153 	sal_Int32 nSelectedRows = GetSelectRowCount();
1154 
1155     // the current line should be deleted but it is currently in edit mode
1156 	if ( IsCurrentAppending() )
1157         return;
1158     // is the insert row selected
1159 	if (GetEmptyRow().Is() && IsRowSelected(GetRowCount() - 1))
1160 		nSelectedRows -= 1;
1161 
1162 	// nothing to do
1163 	if (nSelectedRows <= 0)
1164 		return;
1165 
1166 	// try to confirm the delete
1167 	Reference< ::com::sun::star::frame::XDispatchProvider >  xDispatcher = (::com::sun::star::frame::XDispatchProvider*)GetPeer();
1168 	if (xDispatcher.is())
1169 	{
1170 		::com::sun::star::util::URL aUrl;
1171 		aUrl.Complete = FMURL_CONFIRM_DELETION;
1172 		// #100312# ------------
1173 		Reference< ::com::sun::star::util::XURLTransformer > xTransformer(
1174 			::comphelper::getProcessServiceFactory()->createInstance(
1175 			::rtl::OUString::createFromAscii("com.sun.star.util.URLTransformer")), UNO_QUERY);
1176 		if( xTransformer.is() )
1177 			xTransformer->parseStrict( aUrl );
1178 
1179 		Reference< ::com::sun::star::frame::XDispatch >  xDispatch = xDispatcher->queryDispatch(aUrl, rtl::OUString(), 0);
1180 		Reference< ::com::sun::star::form::XConfirmDeleteListener >  xConfirm(xDispatch, UNO_QUERY);
1181 		if (xConfirm.is())
1182 		{
1183 			::com::sun::star::sdb::RowChangeEvent aEvent;
1184 			aEvent.Source = (Reference< XInterface > )(*getDataSource());
1185 			aEvent.Rows = nSelectedRows;
1186 			aEvent.Action = ::com::sun::star::sdb::RowChangeAction::DELETE;
1187 			if (!xConfirm->confirmDelete(aEvent))
1188 				return;
1189 		}
1190 	}
1191 
1192 	const MultiSelection* pRowSelection = GetSelection();
1193 	if ( pRowSelection && pRowSelection->IsAllSelected() )
1194 	{
1195 		BeginCursorAction();
1196 		CursorWrapper* pCursor = getDataSource();
1197 		Reference< XResultSetUpdate >  xUpdateCursor((Reference< XInterface >)*pCursor, UNO_QUERY);
1198 		try
1199 		{
1200 			pCursor->beforeFirst();
1201 			while( pCursor->next() )
1202 				xUpdateCursor->deleteRow();
1203 
1204 			SetUpdateMode(sal_False);
1205 			SetNoSelection();
1206 
1207 			xUpdateCursor->moveToInsertRow();
1208 		}
1209 		catch(const Exception&)
1210 		{
1211 			OSL_ENSURE(0,"Exception caught while deleting rows!");
1212 		}
1213 		// An den DatenCursor anpassen
1214 		AdjustDataSource(sal_True);
1215 		EndCursorAction();
1216 		SetUpdateMode(sal_True);
1217 	}
1218 	else
1219 	{
1220 		Reference< ::com::sun::star::sdbcx::XDeleteRows >  xDeleteThem((Reference< XInterface >)*getDataSource(), UNO_QUERY);
1221 
1222 		// colect the bookmarks of the selected rows
1223 		Sequence < Any> aBookmarks = getSelectionBookmarks();
1224 
1225 		// determine the next row to position after deletion
1226 		Any aBookmark;
1227 		sal_Bool bNewPos = sal_False;
1228 		// if the current row isn't selected we take the row as row after deletion
1229         OSL_ENSURE( GetCurrentRow().Is(), "FmGridControl::DeleteSelectedRows: no current row here?" );
1230             // crash reports suggest it can happen we don't have a current row - how?
1231             // #154303# / 2008-04-23 / frank.schoenheit@sun.com
1232 		if ( !IsRowSelected( GetCurrentPos() ) && !IsCurrentAppending() && GetCurrentRow().Is() )
1233 		{
1234 			aBookmark = GetCurrentRow()->GetBookmark();
1235 			bNewPos   = sal_True;
1236 		}
1237 		else
1238 		{
1239 			// we look for the first row after the selected block for selection
1240 			long nIdx = LastSelectedRow() + 1;
1241 			if (nIdx < GetRowCount() - 1)
1242 			{
1243 				// there is a next row to position on
1244 				if (SeekCursor(nIdx))
1245 				{
1246 					GetSeekRow()->SetState(m_pSeekCursor, sal_True);
1247 
1248 					bNewPos = sal_True;
1249 					// if it's not the row for inserting we keep the bookmark
1250 					if (!IsInsertionRow(nIdx))
1251 						aBookmark = m_pSeekCursor->getBookmark();
1252 				}
1253 			}
1254 			else
1255 			{
1256 				// we look for the first row before the selected block for selection after deletion
1257 				nIdx = FirstSelectedRow() - 1;
1258 				if (nIdx >= 0 && SeekCursor(nIdx))
1259 				{
1260 					GetSeekRow()->SetState(m_pSeekCursor, sal_True);
1261 
1262 					bNewPos = sal_True;
1263 					aBookmark = m_pSeekCursor->getBookmark();
1264 				}
1265 			}
1266 		}
1267 
1268 		// Sind alle Zeilen Selectiert
1269 		// Zweite bedingung falls keine einguegeZeile existiert
1270 		sal_Bool bAllSelected = GetTotalCount() == nSelectedRows || GetRowCount() == nSelectedRows;
1271 
1272 		BeginCursorAction();
1273 
1274 		// now delete the row
1275 		Sequence <sal_Int32> aDeletedRows;
1276         SetUpdateMode( sal_False );
1277 		try
1278 		{
1279 			aDeletedRows = xDeleteThem->deleteRows(aBookmarks);
1280 		}
1281 		catch(SQLException&)
1282 		{
1283 		}
1284         SetUpdateMode( sal_True );
1285 
1286 		// how many rows are deleted?
1287 		sal_Int32 nDeletedRows = 0;
1288 		const sal_Int32* pSuccess = aDeletedRows.getConstArray();
1289 		for (sal_Int32 i = 0; i < aDeletedRows.getLength(); i++)
1290 		{
1291 			if (pSuccess[i])
1292 				++nDeletedRows;
1293 		}
1294 
1295 		// sind Zeilen geloescht worden?
1296 		if (nDeletedRows)
1297 		{
1298 			SetUpdateMode(sal_False);
1299 			SetNoSelection();
1300 			try
1301 			{
1302 				// did we delete all the rows than try to move to the next possible row
1303 				if (nDeletedRows == aDeletedRows.getLength())
1304 				{
1305 					// there exists a new position to move on
1306 					if (bNewPos)
1307 					{
1308 						if (aBookmark.hasValue())
1309 							getDataSource()->moveToBookmark(aBookmark);
1310 						// no valid bookmark so move to the insert row
1311 						else
1312 						{
1313 							Reference< XResultSetUpdate >  xUpdateCursor((Reference< XInterface >)*m_pDataCursor, UNO_QUERY);
1314 							xUpdateCursor->moveToInsertRow();
1315 						}
1316 					}
1317 					else
1318 					{
1319 						Reference< ::com::sun::star::beans::XPropertySet >	xSet((Reference< XInterface >)*m_pDataCursor, UNO_QUERY);
1320 
1321                         sal_Int32 nRecordCount(0);
1322 						xSet->getPropertyValue(FM_PROP_ROWCOUNT) >>= nRecordCount;
1323                         if ( m_pDataCursor->rowDeleted() )
1324                             --nRecordCount;
1325 
1326 						// there are no rows left and we have an insert row
1327 						if (!nRecordCount && GetEmptyRow().Is())
1328 						{
1329 							Reference< XResultSetUpdate >  xUpdateCursor((Reference< XInterface >)*m_pDataCursor, UNO_QUERY);
1330 							xUpdateCursor->moveToInsertRow();
1331 						}
1332 						else if (nRecordCount)
1333 							// move to the first row
1334 							getDataSource()->first();
1335 					}
1336 				}
1337 				// not all the rows where deleted, so move to the first row which remained in the resultset
1338 				else
1339 				{
1340 					for (sal_Int32 i = 0; i < aDeletedRows.getLength(); i++)
1341 					{
1342 						if (!pSuccess[i])
1343 						{
1344 							getDataSource()->moveToBookmark(aBookmarks.getConstArray()[i]);
1345 							break;
1346 						}
1347 					}
1348 				}
1349 			}
1350 			catch(const Exception&)
1351 			{
1352 				try
1353 				{
1354 					// positioning went wrong so try to move to the first row
1355 					getDataSource()->first();
1356 				}
1357 				catch(const Exception&)
1358 				{
1359 				}
1360 			}
1361 
1362 			// An den DatenCursor anpassen
1363 			AdjustDataSource(sal_True);
1364 
1365 			// es konnten nicht alle Zeilen geloescht werden
1366 			// da nie nicht geloeschten wieder selektieren
1367 			if (nDeletedRows < nSelectedRows)
1368 			{
1369 				// waren alle selektiert
1370 				if (bAllSelected)
1371 				{
1372 					SelectAll();
1373 					if (IsInsertionRow(GetRowCount() - 1))	// einfuegeZeile nicht
1374 						SelectRow(GetRowCount() - 1, sal_False);
1375 				}
1376 				else
1377 				{
1378 					// select the remaining rows
1379 					for (sal_Int32 i = 0; i < aDeletedRows.getLength(); i++)
1380 					{
1381 						try
1382 						{
1383 							if (!pSuccess[i])
1384 							{
1385 								m_pSeekCursor->moveToBookmark(m_pDataCursor->getBookmark());
1386 								SetSeekPos(m_pSeekCursor->getRow() - 1);
1387 								SelectRow(GetSeekPos());
1388 							}
1389 						}
1390 						catch(const Exception&)
1391 						{
1392 							// keep the seekpos in all cases
1393 							SetSeekPos(m_pSeekCursor->getRow() - 1);
1394 						}
1395 					}
1396 				}
1397 			}
1398 
1399 			EndCursorAction();
1400 			SetUpdateMode(sal_True);
1401 		}
1402 		else // Zeile konnte nicht geloescht werden
1403 		{
1404 			EndCursorAction();
1405 			try
1406 			{
1407 				// currentrow is the insert row?
1408 				if (!IsCurrentAppending())
1409 					getDataSource()->refreshRow();
1410 			}
1411 			catch(const Exception&)
1412 			{
1413 			}
1414 		}
1415 	}
1416 
1417 	// if there is no selection anymore we can start editing
1418 	if (!GetSelectRowCount())
1419 		ActivateCell();
1420 }
1421 
1422 
1423 // XCurrentRecordListener
1424 //------------------------------------------------------------------------------
1425 void FmGridControl::positioned(const ::com::sun::star::lang::EventObject& /*rEvent*/)
1426 {
1427 	TRACE_RANGE("FmGridControl::positioned");
1428 	// position on the data source (force it to be done in the main thread)
1429 	implAdjustInSolarThread(sal_False);
1430 }
1431 
1432 //------------------------------------------------------------------------------
1433 sal_Bool FmGridControl::commit()
1434 {
1435 	// Commit nur ausfuehren, wenn nicht bereits ein Update vom ::com::sun::star::form::component::GridControl ausgefuehrt
1436 	// wird
1437 	if (!IsUpdating())
1438 	{
1439 		if (Controller().Is() && Controller()->IsModified())
1440 		{
1441 			if (!SaveModified())
1442 				return sal_False;
1443 		}
1444 	}
1445 	return sal_True;
1446 }
1447 
1448 //------------------------------------------------------------------------------
1449 void FmGridControl::inserted(const ::com::sun::star::lang::EventObject& /*rEvent*/)
1450 {
1451 	const DbGridRowRef& xRow = GetCurrentRow();
1452 	if (!xRow.Is())
1453 		return;
1454 
1455 	// Zeile ist eingefuegt worden, dann den status und mode zuruecksetzen
1456 	xRow->SetState(m_pDataCursor, sal_False);
1457 	xRow->SetNew(sal_False);
1458 
1459 }
1460 
1461 // XCancelUpdateRecordListener
1462 //------------------------------------------------------------------------------
1463 void FmGridControl::restored(const ::com::sun::star::lang::EventObject& rEvent)
1464 {
1465 	if (!GetCurrentRow().Is())
1466 		return;
1467 
1468 	sal_Bool bAppending = GetCurrentRow()->IsNew();
1469 	sal_Bool bDirty 	= GetCurrentRow()->IsModified();
1470 	if (bAppending && (EditBrowseBox::IsModified() || bDirty))
1471 	{
1472 		if (Controller().Is())
1473 			Controller()->ClearModified();
1474 
1475 		// jetzt die Zeile herausnehmen
1476 		RowRemoved(GetRowCount() - 1, 1, sal_True);
1477 		GetNavigationBar().InvalidateAll();
1478 	}
1479 
1480 	positioned(rEvent);
1481 }
1482 
1483 //------------------------------------------------------------------------------
1484 BrowserHeader* FmGridControl::imp_CreateHeaderBar(BrowseBox* pParent)
1485 {
1486     DBG_ASSERT( pParent == this, "FmGridControl::imp_CreateHeaderBar: parent?" );
1487     return new FmGridHeader( pParent );
1488 }
1489 
1490 //------------------------------------------------------------------------------
1491 void FmGridControl::markColumn(sal_uInt16 nId)
1492 {
1493 	if (GetHeaderBar() && m_nMarkedColumnId != nId)
1494 	{
1495 		// deselektieren
1496 		if (m_nMarkedColumnId != BROWSER_INVALIDID)
1497 		{
1498 			HeaderBarItemBits aBits = GetHeaderBar()->GetItemBits(m_nMarkedColumnId) & ~HIB_FLAT;
1499 			GetHeaderBar()->SetItemBits(m_nMarkedColumnId, aBits);
1500 		}
1501 
1502 
1503 		if (nId != BROWSER_INVALIDID)
1504 		{
1505 			HeaderBarItemBits aBits = GetHeaderBar()->GetItemBits(nId) | HIB_FLAT;
1506 			GetHeaderBar()->SetItemBits(nId, aBits);
1507 		}
1508 		m_nMarkedColumnId = nId;
1509 	}
1510 }
1511 
1512 //------------------------------------------------------------------------------
1513 sal_Bool FmGridControl::isColumnMarked(sal_uInt16 nId) const
1514 {
1515 	return m_nMarkedColumnId == nId;
1516 }
1517 
1518 //------------------------------------------------------------------------------
1519 long FmGridControl::QueryMinimumRowHeight()
1520 {
1521     long nMinimalLogicHeight = 20; // 0.2 cm
1522     long nMinimalPixelHeight = LogicToPixel( Point( 0, nMinimalLogicHeight ), MAP_10TH_MM ).Y();
1523     return CalcZoom( nMinimalPixelHeight );
1524 }
1525 
1526 //------------------------------------------------------------------------------
1527 void FmGridControl::RowHeightChanged()
1528 {
1529     DbGridControl::RowHeightChanged();
1530 
1531     Reference< XPropertySet > xModel( GetPeer()->getColumns(), UNO_QUERY );
1532     DBG_ASSERT( xModel.is(), "FmGridControl::RowHeightChanged: no model!" );
1533     if ( xModel.is() )
1534     {
1535         try
1536         {
1537 			sal_Int32 nUnzoomedPixelHeight = CalcReverseZoom( GetDataRowHeight() );
1538 			Any aProperty = makeAny( (sal_Int32)PixelToLogic( Point( 0, nUnzoomedPixelHeight ), MAP_10TH_MM ).Y() );
1539             xModel->setPropertyValue( FM_PROP_ROWHEIGHT, aProperty );
1540         }
1541         catch( const Exception& )
1542         {
1543         	OSL_ENSURE( sal_False, "FmGridControl::RowHeightChanged: caught an exception!" );
1544         }
1545     }
1546 }
1547 
1548 //------------------------------------------------------------------------------
1549 void FmGridControl::ColumnResized(sal_uInt16 nId)
1550 {
1551 	DbGridControl::ColumnResized(nId);
1552 
1553 	// Wert ans model uebergeben
1554 	DbGridColumn* pCol = DbGridControl::GetColumns().GetObject(GetModelColumnPos(nId));
1555 	Reference< ::com::sun::star::beans::XPropertySet >	xColModel(pCol->getModel());
1556 	if (xColModel.is())
1557 	{
1558 		Any aWidth;
1559 		sal_Int32 nColumnWidth = GetColumnWidth(nId);
1560 		nColumnWidth = CalcReverseZoom(nColumnWidth);
1561 		// Umrechnen in 10THMM
1562 		aWidth <<= (sal_Int32)PixelToLogic(Point(nColumnWidth,0),MAP_10TH_MM).X();
1563 		xColModel->setPropertyValue(FM_PROP_WIDTH, aWidth);
1564 	}
1565 }
1566 
1567 //------------------------------------------------------------------------------
1568 void FmGridControl::CellModified()
1569 {
1570 	DbGridControl::CellModified();
1571 	GetPeer()->CellModified();
1572 }
1573 
1574 //------------------------------------------------------------------------------
1575 void FmGridControl::BeginCursorAction()
1576 {
1577 	DbGridControl::BeginCursorAction();
1578 	m_pPeer->stopCursorListening();
1579 }
1580 
1581 //------------------------------------------------------------------------------
1582 void FmGridControl::EndCursorAction()
1583 {
1584 	m_pPeer->startCursorListening();
1585 	DbGridControl::EndCursorAction();
1586 }
1587 
1588 //------------------------------------------------------------------------------
1589 void FmGridControl::ColumnMoved(sal_uInt16 nId)
1590 {
1591 	m_bInColumnMove = sal_True;
1592 
1593 	DbGridControl::ColumnMoved(nId);
1594 	Reference< ::com::sun::star::container::XIndexContainer >  xColumns(GetPeer()->getColumns());
1595 
1596 	if (xColumns.is())
1597 	{
1598 		// suchen der Spalte und verschieben im Model
1599 		// ColumnPos holen
1600 		DbGridColumn* pCol = DbGridControl::GetColumns().GetObject(GetModelColumnPos(nId));
1601 		Reference< ::com::sun::star::beans::XPropertySet >	xCol;
1602 
1603 		// Einfuegen muß sich an den Column Positionen orientieren
1604 		sal_Int32 i;
1605 		Reference< XInterface > xCurrent;
1606 		for (i = 0; !xCol.is() && i < xColumns->getCount(); i++)
1607 		{
1608 			::cppu::extractInterface(xCurrent, xColumns->getByIndex(i));
1609 			if (xCurrent == pCol->getModel())
1610 			{
1611 				xCol = pCol->getModel();
1612 				break;
1613 			}
1614 		}
1615 
1616 		DBG_ASSERT(i < xColumns->getCount(), "Falscher ::com::sun::star::sdbcx::Index");
1617 		xColumns->removeByIndex(i);
1618 		Any aElement;
1619 		aElement <<= xCol;
1620 		xColumns->insertByIndex(GetModelColumnPos(nId), aElement);
1621 		pCol->setModel(xCol);
1622 		// if the column which is shown here is selected ...
1623 		if ( isColumnSelected(nId,pCol) )
1624 			markColumn(nId); // ... -> mark it
1625 	}
1626 
1627 	m_bInColumnMove = sal_False;
1628 }
1629 
1630 //------------------------------------------------------------------------------
1631 void FmGridControl::InitColumnsByModels(const Reference< ::com::sun::star::container::XIndexContainer >& xColumns)
1632 {
1633 	// Spalten wieder neu setzen
1634 	// wenn es nur eine HandleColumn gibt, dann nicht
1635 	if (GetModelColCount())
1636 	{
1637 		RemoveColumns();
1638 		InsertHandleColumn();
1639 	}
1640 
1641 	if (!xColumns.is())
1642 		return;
1643 
1644 	SetUpdateMode(sal_False);
1645 
1646 	// Einfuegen mu� sich an den Column Positionen orientieren
1647 	sal_Int32 i;
1648 	String aName;
1649 	Any aWidth;
1650 	for (i = 0; i < xColumns->getCount(); ++i)
1651 	{
1652 		Reference< ::com::sun::star::beans::XPropertySet > xCol;
1653 		::cppu::extractInterface(xCol, xColumns->getByIndex(i));
1654 
1655 		aName  = (const sal_Unicode*)::comphelper::getString(xCol->getPropertyValue(FM_PROP_LABEL));
1656 
1657 		aWidth = xCol->getPropertyValue(FM_PROP_WIDTH);
1658 		sal_Int32 nWidth = 0;
1659 		if (aWidth >>= nWidth)
1660 			nWidth = LogicToPixel(Point(nWidth,0),MAP_10TH_MM).X();
1661 
1662 		AppendColumn(aName, (sal_uInt16)nWidth);
1663 		DbGridColumn* pCol = DbGridControl::GetColumns().GetObject(i);
1664 		pCol->setModel(xCol);
1665 	}
1666 
1667 	// und jetzt noch die hidden columns rausnehmen
1668 	// (wir haben das nicht gleich in der oberen Schleife gemacht, da wir dann Probleme mit den
1669 	// IDs der Spalten bekommen haetten : AppendColumn vergibt die automatisch, die Spalte _nach_
1670 	// einer versteckten braucht aber eine um eine erhoehte ID ....
1671 	Any aHidden;
1672 	for (i = 0; i < xColumns->getCount(); ++i)
1673 	{
1674 		Reference< ::com::sun::star::beans::XPropertySet > xCol;
1675 		::cppu::extractInterface(xCol, xColumns->getByIndex(i));
1676 		aHidden = xCol->getPropertyValue(FM_PROP_HIDDEN);
1677 		if (::comphelper::getBOOL(aHidden))
1678 			HideColumn(GetColumnIdFromModelPos((sal_uInt16)i));
1679 	}
1680 
1681 	SetUpdateMode(sal_True);
1682 }
1683 
1684 //------------------------------------------------------------------------------
1685 void FmGridControl::InitColumnByField(
1686 	DbGridColumn* _pColumn, const Reference< XPropertySet >& _rxColumnModel,
1687 	const Reference< XNameAccess >& _rxFieldsByNames, const Reference< XIndexAccess >& _rxFieldsByIndex )
1688 {
1689 	DBG_ASSERT( _rxFieldsByNames == _rxFieldsByIndex, "FmGridControl::InitColumnByField: invalid container interfaces!" );
1690 
1691 	// lookup the column which belongs to the control source
1692 	::rtl::OUString sFieldName;
1693 	_rxColumnModel->getPropertyValue( FM_PROP_CONTROLSOURCE ) >>= sFieldName;
1694     Reference< XPropertySet > xField;
1695     _rxColumnModel->getPropertyValue( FM_PROP_BOUNDFIELD ) >>= xField;
1696 
1697 
1698 	if ( !xField.is() && /*sFieldName.getLength() && */_rxFieldsByNames->hasByName( sFieldName ) ) // #i93452# do not check for name length
1699 		_rxFieldsByNames->getByName( sFieldName ) >>= xField;
1700 
1701 	// determine the position of this column
1702 	sal_Int32 nFieldPos = -1;
1703 	if ( xField.is() )
1704 	{
1705 		Reference< XPropertySet > xCheck;
1706 		sal_Int32 nFieldCount = _rxFieldsByIndex->getCount();
1707 		for ( sal_Int32 i = 0; i < nFieldCount; ++i)
1708 		{
1709 			_rxFieldsByIndex->getByIndex( i ) >>= xCheck;
1710 			if ( xField.get() == xCheck.get() )
1711 			{
1712 				nFieldPos = i;
1713 				break;
1714 			}
1715 		}
1716 	}
1717 
1718 	if ( xField.is() && ( nFieldPos >= 0 ) )
1719 	{
1720 		// some data types are not allowed
1721 		sal_Int32 nDataType = DataType::OTHER;
1722 		xField->getPropertyValue( FM_PROP_FIELDTYPE ) >>= nDataType;
1723 
1724 		sal_Bool bIllegalType = sal_False;
1725 		switch ( nDataType )
1726 		{
1727 			case DataType::BLOB:
1728 			case DataType::LONGVARBINARY:
1729 			case DataType::BINARY:
1730 			case DataType::VARBINARY:
1731 			case DataType::OTHER:
1732 				bIllegalType = sal_True;
1733 				break;
1734 		}
1735 
1736 		if ( bIllegalType )
1737 		{
1738 			_pColumn->SetObject( (sal_Int16)nFieldPos );
1739 			return;
1740 		}
1741 /*
1742 		// handle readonly columns
1743 		sal_Bool bReadOnly = sal_True;
1744 		xField->getPropertyValue( FM_PROP_ISREADONLY ) >>= bReadOnly;
1745 		_pColumn->SetReadOnly( bReadOnly );
1746 */
1747 	}
1748 
1749 	// the control type is determined by the ColumnServiceName
1750 	static ::rtl::OUString s_sPropColumnServiceName( RTL_CONSTASCII_USTRINGPARAM( "ColumnServiceName" ) );
1751 	if ( !::comphelper::hasProperty( s_sPropColumnServiceName, _rxColumnModel ) )
1752 		return;
1753 
1754 	_pColumn->setModel( _rxColumnModel );
1755 
1756 	::rtl::OUString sColumnServiceName;
1757 	_rxColumnModel->getPropertyValue( s_sPropColumnServiceName ) >>= sColumnServiceName;
1758 
1759 	sal_Int32 nTypeId = getColumnTypeByModelName( sColumnServiceName );
1760 	_pColumn->CreateControl( nFieldPos, xField, nTypeId );
1761 }
1762 
1763 //------------------------------------------------------------------------------
1764 void FmGridControl::InitColumnsByFields(const Reference< ::com::sun::star::container::XIndexAccess >& _rxFields)
1765 {
1766 	if ( !_rxFields.is() )
1767 		return;
1768 
1769 	// Spalten initialisieren
1770 	Reference< XIndexContainer > xColumns( GetPeer()->getColumns() );
1771 	Reference< XNameAccess > xFieldsAsNames( _rxFields, UNO_QUERY );
1772 
1773 	// Einfuegen muss sich an den Column Positionen orientieren
1774 	for (sal_Int32 i = 0; i < xColumns->getCount(); i++)
1775 	{
1776 		DbGridColumn* pCol = GetColumns().GetObject(i);
1777 		OSL_ENSURE(pCol,"No grid column!");
1778 		if ( pCol )
1779 		{
1780 			Reference< XPropertySet > xColumnModel;
1781 			::cppu::extractInterface( xColumnModel, xColumns->getByIndex( i ) );
1782 
1783 			InitColumnByField( pCol, xColumnModel, xFieldsAsNames, _rxFields );
1784 		}
1785 	}
1786 }
1787 
1788 //------------------------------------------------------------------------------
1789 void FmGridControl::HideColumn(sal_uInt16 nId)
1790 {
1791 	DbGridControl::HideColumn(nId);
1792 
1793 	sal_uInt16 nPos = GetModelColumnPos(nId);
1794 	if (nPos == (sal_uInt16)-1)
1795 		return;
1796 
1797 	DbGridColumn* pColumn = GetColumns().GetObject(nPos);
1798 	if (pColumn->IsHidden())
1799 		GetPeer()->columnHidden(pColumn);
1800 
1801 	if (nId == m_nMarkedColumnId)
1802 		m_nMarkedColumnId = (sal_uInt16)-1;
1803 }
1804 // -----------------------------------------------------------------------------
1805 sal_Bool FmGridControl::isColumnSelected(sal_uInt16 /*nId*/,DbGridColumn* _pColumn)
1806 {
1807 	OSL_ENSURE(_pColumn,"Column can not be null!");
1808 	sal_Bool bSelected = sal_False;
1809 	// if the column which is shown here is selected ...
1810 	Reference< ::com::sun::star::view::XSelectionSupplier >  xSelSupplier(GetPeer()->getColumns(), UNO_QUERY);
1811 	if ( xSelSupplier.is() )
1812 	{
1813 		Reference< ::com::sun::star::beans::XPropertySet >	xColumn;
1814 		xSelSupplier->getSelection() >>= xColumn;
1815 		bSelected = (xColumn.get() == _pColumn->getModel().get());
1816 	}
1817 	return bSelected;
1818 }
1819 
1820 //------------------------------------------------------------------------------
1821 void FmGridControl::ShowColumn(sal_uInt16 nId)
1822 {
1823 	DbGridControl::ShowColumn(nId);
1824 
1825 	sal_uInt16 nPos = GetModelColumnPos(nId);
1826 	if (nPos == (sal_uInt16)-1)
1827 		return;
1828 
1829 	DbGridColumn* pColumn = GetColumns().GetObject(nPos);
1830 	if (!pColumn->IsHidden())
1831 		GetPeer()->columnVisible(pColumn);
1832 
1833 	// if the column which is shown here is selected ...
1834 	if ( isColumnSelected(nId,pColumn) )
1835 		markColumn(nId); // ... -> mark it
1836 }
1837 
1838 //------------------------------------------------------------------------------
1839 sal_Bool FmGridControl::selectBookmarks(const Sequence< Any >& _rBookmarks)
1840 {
1841 	vos::OGuard aGuard( Application::GetSolarMutex() );
1842 		// need to lock the SolarMutex so that no paint call disturbs us ...
1843 
1844 	if ( !m_pSeekCursor )
1845 	{
1846 		DBG_ERROR( "FmGridControl::selectBookmarks: no seek cursor!" );
1847 		return sal_False;
1848 	}
1849 
1850 	const Any* pBookmark = _rBookmarks.getConstArray();
1851 	const Any* pBookmarkEnd = pBookmark + _rBookmarks.getLength();
1852 
1853 	SetNoSelection();
1854 
1855 	sal_Bool bAllSuccessfull = sal_True;
1856 	try
1857 	{
1858 		for (; pBookmark != pBookmarkEnd; ++pBookmark)
1859 		{
1860 			// move the seek cursor to the row given
1861 			if (m_pSeekCursor->moveToBookmark(*pBookmark))
1862 				SelectRow( m_pSeekCursor->getRow() - 1);
1863 			else
1864 				bAllSuccessfull = sal_False;
1865 		}
1866 	}
1867 	catch(Exception&)
1868 	{
1869 		DBG_ERROR("FmGridControl::selectBookmarks: could not move to one of the bookmarks!");
1870 		return sal_False;
1871 	}
1872 
1873 	return bAllSuccessfull;
1874 }
1875 
1876 //------------------------------------------------------------------------------
1877 Sequence< Any> FmGridControl::getSelectionBookmarks()
1878 {
1879 	// lock our update so no paint-triggered seeks interfere ...
1880 	SetUpdateMode(sal_False);
1881 
1882 	sal_Int32 nSelectedRows = GetSelectRowCount(), i = 0;
1883 	Sequence< Any> aBookmarks(nSelectedRows);
1884 	if ( nSelectedRows )
1885 	{
1886 		Any* pBookmarks = (Any*)aBookmarks.getArray();
1887 
1888 		// (I'm not sure if the problem isn't deeper : The szenario : a large table displayed by a grid with a
1889 		// thread-safe cursor (dBase). On loading the sdb-cursor started a counting thread. While this counting progress
1890 		// was running, I tried do delete 3 records from within the grid. Deletion caused a SeekCursor, which did a
1891 		// m_pSeekCursor->moveRelative and a m_pSeekCursor->getPosition.
1892 		// Unfortunally the first call caused a propertyChanged(RECORDCOUNT) which resulted in a repaint of the
1893 		// navigation bar and the grid. The latter itself will result in SeekRow calls. So after (successfully) returning
1894 		// from the moveRelative the getPosition returns an invalid value. And so the SeekCursor fails.
1895 		// In the consequence ALL parts of code where two calls to the seek cursor are done, while the second call _relys_ on
1896 		// the first one, should be secured against recursion, with a broad-minded interpretion of "recursion" : if any of these
1897 		// code parts is executed, no other should be accessible. But this sounds very difficult to achieve ....
1898 		// )
1899 
1900 		// The next problem caused by the same behaviuor (SeekCursor causes a propertyChanged) : when adjusting rows we implicitly
1901 		// change our selection. So a "FirstSelected(); SeekCursor(); NextSelected();" may produce unpredictable results.
1902 		// That's why we _first_ collect the indicies of the selected rows and _then_ their bookmarks.
1903 		long nIdx = FirstSelectedRow();
1904 		while (nIdx >= 0)
1905 		{
1906 			// (we misuse the bookmarks array for this ...)
1907 			pBookmarks[i++] <<= (sal_Int32)nIdx;
1908 			nIdx = NextSelectedRow();
1909 		}
1910 		DBG_ASSERT(i == nSelectedRows, "FmGridControl::DeleteSelectedRows : could not collect the row indicies !");
1911 
1912 		for (i=0; i<nSelectedRows; ++i)
1913 		{
1914 			nIdx = ::comphelper::getINT32(pBookmarks[i]);
1915 			if (IsInsertionRow(nIdx))
1916 			{
1917 				// leerzeile nicht loeschen
1918 				aBookmarks.realloc(--nSelectedRows);
1919 				SelectRow(nIdx,sal_False);			// selection aufheben fuer leerzeile
1920 				break;
1921 			}
1922 
1923 			// Zunaechst den DatenCursor auf den selektierten Satz pos.
1924 			if (SeekCursor(nIdx))
1925 			{
1926 				GetSeekRow()->SetState(m_pSeekCursor, sal_True);
1927 
1928 				pBookmarks[i] = m_pSeekCursor->getBookmark();
1929 			}
1930 	#ifdef DBG_UTIL
1931 			else
1932 				DBG_ERROR("FmGridControl::DeleteSelectedRows : a bookmark could not be determined !");
1933 	#endif
1934 		}
1935 	}
1936 	SetUpdateMode(sal_True);
1937 
1938 	// if one of the SeekCursor-calls failed ....
1939 	aBookmarks.realloc(i);
1940 
1941 	// (the alternative : while collecting the bookmarks lock our propertyChanged, this should resolve both our problems.
1942 	// but this would be incompatible as we need a locking flag, then ...)
1943 
1944 	return aBookmarks;
1945 }
1946 // -----------------------------------------------------------------------------
1947 namespace
1948 {
1949 	::rtl::OUString getColumnPropertyFromPeer(FmXGridPeer* _pPeer,sal_Int32 _nPosition,const ::rtl::OUString& _sPropName)
1950 	{
1951 		::rtl::OUString sRetText;
1952 		if ( _pPeer && _nPosition != -1)
1953 		{
1954 			Reference<XIndexContainer> xIndex = _pPeer->getColumns();
1955 			if ( xIndex.is() && xIndex->getCount() > _nPosition )
1956 			{
1957 				Reference<XPropertySet> xProp;
1958 				xIndex->getByIndex( _nPosition ) >>= xProp;
1959 				if ( xProp.is() )
1960 					xProp->getPropertyValue( _sPropName ) >>= sRetText;
1961 			}
1962 		}
1963 		return sRetText;
1964 	}
1965 }
1966 // Object data and state ------------------------------------------------------
1967 ::rtl::OUString FmGridControl::GetAccessibleObjectName( ::svt::AccessibleBrowseBoxObjType _eObjType,sal_Int32 _nPosition ) const
1968 {
1969     ::rtl::OUString sRetText;
1970     switch( _eObjType )
1971     {
1972         case ::svt::BBTYPE_BROWSEBOX:
1973             if ( GetPeer() )
1974 			{
1975 				Reference<XPropertySet> xProp(GetPeer()->getColumns(),UNO_QUERY);
1976 				if ( xProp.is() )
1977 					xProp->getPropertyValue(FM_PROP_NAME) >>= sRetText;
1978 			}
1979 			break;
1980         case ::svt::BBTYPE_COLUMNHEADERCELL:
1981 			sRetText = getColumnPropertyFromPeer(
1982                 GetPeer(),
1983                 GetModelColumnPos(
1984                     sal::static_int_cast< sal_uInt16 >(_nPosition)),
1985                 FM_PROP_LABEL);
1986 			break;
1987 		default:
1988 			sRetText = DbGridControl::GetAccessibleObjectName(_eObjType,_nPosition);
1989     }
1990     return sRetText;
1991 }
1992 // -----------------------------------------------------------------------------
1993 
1994 ::rtl::OUString FmGridControl::GetAccessibleObjectDescription( ::svt::AccessibleBrowseBoxObjType _eObjType,sal_Int32 _nPosition ) const
1995 {
1996     ::rtl::OUString sRetText;
1997     switch( _eObjType )
1998     {
1999         case ::svt::BBTYPE_BROWSEBOX:
2000 			if ( GetPeer() )
2001 			{
2002 				Reference<XPropertySet> xProp(GetPeer()->getColumns(),UNO_QUERY);
2003 				if ( xProp.is() )
2004                 {
2005 					xProp->getPropertyValue(FM_PROP_HELPTEXT) >>= sRetText;
2006                     if ( !sRetText.getLength() )
2007                         xProp->getPropertyValue(FM_PROP_DESCRIPTION) >>= sRetText;
2008                 }
2009 			}
2010 			break;
2011 		case ::svt::BBTYPE_COLUMNHEADERCELL:
2012 			sRetText = getColumnPropertyFromPeer(
2013                 GetPeer(),
2014                 GetModelColumnPos(
2015                     sal::static_int_cast< sal_uInt16 >(_nPosition)),
2016                 FM_PROP_HELPTEXT);
2017             if ( !sRetText.getLength() )
2018                 sRetText = getColumnPropertyFromPeer(
2019                             GetPeer(),
2020                             GetModelColumnPos(
2021                                 sal::static_int_cast< sal_uInt16 >(_nPosition)),
2022                             FM_PROP_DESCRIPTION);
2023 
2024 			break;
2025 		default:
2026             sRetText = DbGridControl::GetAccessibleObjectDescription(_eObjType,_nPosition);
2027     }
2028     return sRetText;
2029 }
2030 // -----------------------------------------------------------------------------
2031 void FmGridControl::Select()
2032 {
2033 	DbGridControl::Select();
2034 	// ... betrifft das unsere Spalten ?
2035 	const MultiSelection* pColumnSelection = GetColumnSelection();
2036 
2037 	sal_uInt16 nSelectedColumn =
2038 		pColumnSelection && pColumnSelection->GetSelectCount()
2039 			? sal::static_int_cast< sal_uInt16 >(
2040                 ((MultiSelection*)pColumnSelection)->FirstSelected())
2041 			: SAL_MAX_UINT16;
2042 	// die HandleColumn wird nicht selektiert
2043 	switch (nSelectedColumn)
2044 	{
2045 		case SAL_MAX_UINT16: break;	// no selection
2046 		case  0	: nSelectedColumn = SAL_MAX_UINT16; break;
2047                     // handle col can't be seledted
2048 		default	:
2049 			// get the model col pos instead of the view col pos
2050 			nSelectedColumn = GetModelColumnPos(GetColumnIdFromViewPos(nSelectedColumn - 1));
2051 			break;
2052 	}
2053 
2054 	if (nSelectedColumn != m_nCurrentSelectedColumn)
2055 	{
2056 		// VOR dem Aufruf des select am SelectionSupplier !
2057 		m_nCurrentSelectedColumn = nSelectedColumn;
2058 
2059 		if (!m_bSelecting)
2060 		{
2061 			m_bSelecting = sal_True;
2062 
2063 			try
2064 			{
2065 				Reference< XIndexAccess >  xColumns(GetPeer()->getColumns(), UNO_QUERY);
2066 				Reference< XSelectionSupplier >  xSelSupplier(xColumns, UNO_QUERY);
2067 				if (xSelSupplier.is())
2068 				{
2069 					if (nSelectedColumn != SAL_MAX_UINT16)
2070 					{
2071 						Reference< XPropertySet >  xColumn;
2072 						::cppu::extractInterface(xColumn,xColumns->getByIndex(nSelectedColumn));
2073 						xSelSupplier->select(makeAny(xColumn));
2074 					}
2075 					else
2076 					{
2077 						xSelSupplier->select(Any());
2078 					}
2079 				}
2080 			}
2081 			catch(Exception&)
2082 			{
2083 			}
2084 
2085 
2086 			m_bSelecting = sal_False;
2087 		}
2088 	}
2089 }
2090 // -----------------------------------------------------------------------------
2091 sal_Int32 FmGridControl::GetSelectedColumn() const
2092 {
2093 	return m_nCurrentSelectedColumn;
2094 }
2095 // -----------------------------------------------------------------------------
2096 void FmGridControl::KeyInput( const KeyEvent& rKEvt )
2097 {
2098 	sal_Bool bDone = sal_False;
2099 	const KeyCode& rKeyCode = rKEvt.GetKeyCode();
2100 	if (	IsDesignMode()
2101 		&&	!rKeyCode.IsShift()
2102 		&&	!rKeyCode.IsMod1()
2103 		&&	!rKeyCode.IsMod2()
2104 		&&	GetParent() )
2105 	{
2106 		switch ( rKeyCode.GetCode() )
2107 		{
2108 			case KEY_ESCAPE:
2109 				GetParent()->GrabFocus();
2110 				bDone = sal_True;
2111 				break;
2112 			case KEY_DELETE:
2113 				if ( GetSelectColumnCount() && GetPeer() && m_nCurrentSelectedColumn >= 0 )
2114 				{
2115 					Reference< ::com::sun::star::container::XIndexContainer >  xCols(GetPeer()->getColumns());
2116 					if ( xCols.is() )
2117 					{
2118 						try
2119 						{
2120 							if ( m_nCurrentSelectedColumn < xCols->getCount() )
2121 							{
2122 								Reference< XInterface >  xCol;
2123 								xCols->getByIndex(m_nCurrentSelectedColumn) >>= xCol;
2124 								xCols->removeByIndex(m_nCurrentSelectedColumn);
2125 								::comphelper::disposeComponent(xCol);
2126 							}
2127 						}
2128 						catch(const Exception&)
2129 						{
2130 							OSL_ENSURE(0,"exception occured while deleting a column");
2131 						}
2132 					}
2133 				}
2134 				bDone = sal_True;
2135 				break;
2136 		}
2137 	}
2138 	if ( !bDone )
2139 		DbGridControl::KeyInput( rKEvt );
2140 }
2141 // -----------------------------------------------------------------------------
2142 
2143 
2144 
2145