summaryrefslogtreecommitdiff
path: root/svx/source/fmcomp/fmgridcl.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'svx/source/fmcomp/fmgridcl.cxx')
-rw-r--r--svx/source/fmcomp/fmgridcl.cxx2144
1 files changed, 2144 insertions, 0 deletions
diff --git a/svx/source/fmcomp/fmgridcl.cxx b/svx/source/fmcomp/fmgridcl.cxx
new file mode 100644
index 000000000000..d64b0c9ab958
--- /dev/null
+++ b/svx/source/fmcomp/fmgridcl.cxx
@@ -0,0 +1,2144 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_svx.hxx"
+
+#include "dbexch.hrc"
+#include "fmgridif.hxx"
+#include "fmitems.hxx"
+#include "fmprop.hrc"
+#include "svx/fmtools.hxx"
+#include "fmresids.hrc"
+#include "fmservs.hxx"
+#include "fmurl.hxx"
+#include "formcontrolfactory.hxx"
+#include "gridcell.hxx"
+#include "gridcols.hxx"
+#include "svx/dbaexchange.hxx"
+#include "svx/dialmgr.hxx"
+#include "svx/dialogs.hrc"
+#include "svx/fmgridcl.hxx"
+#include "svx/svxdlg.hxx"
+#include "svx/svxids.hrc"
+#include "trace.hxx"
+
+#include <com/sun/star/form/XConfirmDeleteListener.hpp>
+#include <com/sun/star/form/XFormComponent.hpp>
+#include <com/sun/star/form/XGridColumnFactory.hpp>
+#include <com/sun/star/io/XPersistObject.hpp>
+#include <com/sun/star/sdb/CommandType.hpp>
+#include <com/sun/star/sdb/RowChangeAction.hpp>
+#include <com/sun/star/sdb/XQueriesSupplier.hpp>
+#include <com/sun/star/sdbc/DataType.hpp>
+#include <com/sun/star/sdbc/XPreparedStatement.hpp>
+#include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
+#include <com/sun/star/sdbcx/XDeleteRows.hpp>
+#include <com/sun/star/sdbcx/XTablesSupplier.hpp>
+#include <com/sun/star/uno/XNamingService.hpp>
+#include <com/sun/star/util/XNumberFormats.hpp>
+#include <com/sun/star/util/XNumberFormatsSupplier.hpp>
+#include <com/sun/star/util/XURLTransformer.hpp>
+#include <com/sun/star/view/XSelectionSupplier.hpp>
+
+#ifndef _SVSTDARR_STRINGSDTOR
+#define _SVSTDARR_STRINGSDTOR
+#define _SVSTDARR_ULONGS
+#include <svl/svstdarr.hxx>
+#endif
+
+#include <comphelper/extract.hxx>
+#include <comphelper/numbers.hxx>
+#include <comphelper/processfactory.hxx>
+#include <comphelper/property.hxx>
+#include <connectivity/dbtools.hxx>
+#include <sfx2/dispatch.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <svl/eitem.hxx>
+#include <svtools/fmtfield.hxx>
+#include <svl/numuno.hxx>
+#include <tools/multisel.hxx>
+#include <tools/shl.hxx>
+#include <tools/diagnose_ex.h>
+#include <vcl/help.hxx>
+#include <vcl/image.hxx>
+#include <vcl/longcurr.hxx>
+#include <vcl/menu.hxx>
+
+#include <math.h>
+
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::view;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::sdbcx;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::sdb;
+using namespace ::com::sun::star::form;
+using namespace ::com::sun::star::util;
+using namespace ::com::sun::star::container;
+using namespace ::cppu;
+using namespace ::svxform;
+using namespace ::svx;
+
+//==============================================================================
+//------------------------------------------------------------------------------
+::rtl::OUString FieldServiceFromId(sal_Int32 nID)
+{
+ switch (nID)
+ {
+ case SID_FM_EDIT : return FM_COL_TEXTFIELD;
+ case SID_FM_COMBOBOX : return FM_COL_COMBOBOX;
+ case SID_FM_LISTBOX : return FM_COL_LISTBOX;
+ case SID_FM_CHECKBOX : return FM_COL_CHECKBOX;
+ case SID_FM_DATEFIELD : return FM_COL_DATEFIELD;
+ case SID_FM_TIMEFIELD : return FM_COL_TIMEFIELD;
+ case SID_FM_NUMERICFIELD : return FM_COL_NUMERICFIELD;
+ case SID_FM_CURRENCYFIELD : return FM_COL_CURRENCYFIELD;
+ case SID_FM_PATTERNFIELD : return FM_COL_PATTERNFIELD;
+ case SID_FM_FORMATTEDFIELD : return FM_COL_FORMATTEDFIELD;
+ }
+ return ::rtl::OUString();
+}
+
+//==============================================================================
+struct FmGridHeaderData
+{
+ ODataAccessDescriptor aDropData;
+ Point aDropPosPixel;
+ sal_Int8 nDropAction;
+ Reference< XInterface > xDroppedStatement;
+ Reference< XInterface > xDroppedResultSet;
+};
+
+//==============================================================================
+//------------------------------------------------------------------------------
+const sal_Int16 nChangeTypeOffset = 1000;
+void SetMenuItem(const ImageList& rList, sal_uInt16 nID, Menu* pMenu, Menu& rNewMenu, sal_Bool bDesignMode = sal_True, sal_Int16 nOffset = nChangeTypeOffset)
+{
+ pMenu->SetItemImage(nID, rList.GetImage(nID));
+ pMenu->EnableItem(nID, bDesignMode);
+ rNewMenu.InsertItem(nID + nOffset, pMenu->GetItemText(nID));
+ rNewMenu.SetItemImage(nID + nOffset, rList.GetImage(nID));
+ rNewMenu.SetHelpId(nID + nOffset, pMenu->GetHelpId(nID));
+ rNewMenu.EnableItem(nID + nOffset, bDesignMode);
+}
+
+//------------------------------------------------------------------------------
+FmGridHeader::FmGridHeader( BrowseBox* pParent, WinBits nWinBits)
+ :EditBrowserHeader(pParent, nWinBits)
+ ,DropTargetHelper(this)
+ ,m_pImpl(new FmGridHeaderData)
+{
+}
+
+//------------------------------------------------------------------------------
+FmGridHeader::~FmGridHeader()
+{
+ delete m_pImpl;
+}
+
+//------------------------------------------------------------------------------
+sal_uInt16 FmGridHeader::GetModelColumnPos(sal_uInt16 nId) const
+{
+ return static_cast<FmGridControl*>(GetParent())->GetModelColumnPos(nId);
+}
+//---------------------------------------------------------------------------------------
+void FmGridHeader::notifyColumnSelect(sal_uInt16 nColumnId)
+{
+ sal_uInt16 nPos = GetModelColumnPos(nColumnId);
+ Reference< XIndexAccess > xColumns(((FmGridControl*)GetParent())->GetPeer()->getColumns(), UNO_QUERY);
+ if ( nPos < xColumns->getCount() )
+ {
+ Reference< XSelectionSupplier > xSelSupplier(xColumns, UNO_QUERY);
+ if ( xSelSupplier.is() )
+ {
+ Reference< XPropertySet > xColumn;
+ xColumns->getByIndex(nPos) >>= xColumn;
+ xSelSupplier->select(makeAny(xColumn));
+ }
+ }
+}
+//------------------------------------------------------------------------------
+void FmGridHeader::Select()
+{
+ EditBrowserHeader::Select();
+ notifyColumnSelect(GetCurItemId());
+}
+
+//------------------------------------------------------------------------------
+void FmGridHeader::RequestHelp( const HelpEvent& rHEvt )
+{
+ sal_uInt16 nItemId = GetItemId( ScreenToOutputPixel( rHEvt.GetMousePosPixel() ) );
+ if ( nItemId )
+ {
+ if ( rHEvt.GetMode() & (HELPMODE_QUICK | HELPMODE_BALLOON) )
+ {
+ Rectangle aItemRect = GetItemRect( nItemId );
+ Point aPt = OutputToScreenPixel( aItemRect.TopLeft() );
+ aItemRect.Left() = aPt.X();
+ aItemRect.Top() = aPt.Y();
+ aPt = OutputToScreenPixel( aItemRect.BottomRight() );
+ aItemRect.Right() = aPt.X();
+ aItemRect.Bottom() = aPt.Y();
+
+ sal_uInt16 nPos = GetModelColumnPos(nItemId);
+ Reference< ::com::sun::star::container::XIndexContainer > xColumns(static_cast<FmGridControl*>(GetParent())->GetPeer()->getColumns());
+ try
+ {
+ Reference< ::com::sun::star::beans::XPropertySet > xColumn(xColumns->getByIndex(nPos),UNO_QUERY);
+ ::rtl::OUString aHelpText;
+ xColumn->getPropertyValue(FM_PROP_HELPTEXT) >>= aHelpText;
+ if ( !aHelpText.getLength() )
+ xColumn->getPropertyValue(FM_PROP_DESCRIPTION) >>= aHelpText;
+ if ( aHelpText.getLength() )
+ {
+ if ( rHEvt.GetMode() & HELPMODE_BALLOON )
+ Help::ShowBalloon( this, aItemRect.Center(), aItemRect, aHelpText );
+ else
+ Help::ShowQuickHelp( this, aItemRect, aHelpText );
+ return;
+ }
+ }
+ catch(Exception&)
+ {
+ return;
+ }
+ }
+ }
+ EditBrowserHeader::RequestHelp( rHEvt );
+}
+
+//------------------------------------------------------------------------------
+sal_Int8 FmGridHeader::AcceptDrop( const AcceptDropEvent& rEvt )
+{
+ // drop allowed in design mode only
+ if (!static_cast<FmGridControl*>(GetParent())->IsDesignMode())
+ return DND_ACTION_NONE;
+
+ // search for recognized formats
+ const DataFlavorExVector& rFlavors = GetDataFlavorExVector();
+ if (OColumnTransferable::canExtractColumnDescriptor(rFlavors, CTF_COLUMN_DESCRIPTOR | CTF_FIELD_DESCRIPTOR))
+ return rEvt.mnAction;
+
+ return DND_ACTION_NONE;
+}
+
+//------------------------------------------------------------------------------
+sal_Int8 FmGridHeader::ExecuteDrop( const ExecuteDropEvent& _rEvt )
+{
+ if (!static_cast<FmGridControl*>(GetParent())->IsDesignMode())
+ return DND_ACTION_NONE;
+
+ TransferableDataHelper aDroppedData(_rEvt.maDropEvent.Transferable);
+
+ // check the formats
+ sal_Bool bColumnDescriptor = OColumnTransferable::canExtractColumnDescriptor(aDroppedData.GetDataFlavorExVector(), CTF_COLUMN_DESCRIPTOR);
+ sal_Bool bFieldDescriptor = OColumnTransferable::canExtractColumnDescriptor(aDroppedData.GetDataFlavorExVector(), CTF_FIELD_DESCRIPTOR);
+ if (!bColumnDescriptor && !bFieldDescriptor)
+ {
+ DBG_ERROR("FmGridHeader::ExecuteDrop: should never have reached this (no extractable format)!");
+ return DND_ACTION_NONE;
+ }
+
+ // extract the descriptor
+ ::rtl::OUString sDatasouce, sCommand, sFieldName,sDatabaseLocation,sConnnectionResource;
+ sal_Int32 nCommandType = CommandType::COMMAND;
+ Reference< XPreparedStatement > xStatement;
+ Reference< XResultSet > xResultSet;
+ Reference< XPropertySet > xField;
+ Reference< XConnection > xConnection;
+
+ ODataAccessDescriptor aColumn = OColumnTransferable::extractColumnDescriptor(aDroppedData);
+ if (aColumn.has(daDataSource)) aColumn[daDataSource] >>= sDatasouce;
+ if (aColumn.has(daDatabaseLocation)) aColumn[daDatabaseLocation] >>= sDatabaseLocation;
+ if (aColumn.has(daConnectionResource)) aColumn[daConnectionResource] >>= sConnnectionResource;
+ if (aColumn.has(daCommand)) aColumn[daCommand] >>= sCommand;
+ if (aColumn.has(daCommandType)) aColumn[daCommandType] >>= nCommandType;
+ if (aColumn.has(daColumnName)) aColumn[daColumnName] >>= sFieldName;
+ if (aColumn.has(daColumnObject))aColumn[daColumnObject] >>= xField;
+ if (aColumn.has(daConnection)) aColumn[daConnection] >>= xConnection;
+
+ if ( !sFieldName.getLength()
+ || !sCommand.getLength()
+ || ( !sDatasouce.getLength()
+ && !sDatabaseLocation.getLength()
+ && !xConnection.is()
+ )
+ )
+ {
+ DBG_ERROR( "FmGridHeader::ExecuteDrop: somebody started a nonsense drag operation!!" );
+ return DND_ACTION_NONE;
+ }
+
+ try
+ {
+ // need a connection
+ if (!xConnection.is())
+ { // the transferable did not contain the connection -> build an own one
+ try
+ {
+ ::rtl::OUString sSignificantSource( sDatasouce.getLength() ? sDatasouce : sDatabaseLocation );
+ xConnection = OStaticDataAccessTools().getConnection_withFeedback(sSignificantSource, ::rtl::OUString(),::rtl::OUString(),static_cast<FmGridControl*>(GetParent())->getServiceManager());
+ }
+ catch(NoSuchElementException&)
+ { // allowed, means sDatasouce isn't a valid data source name ....
+ }
+ catch(Exception&)
+ {
+ DBG_ERROR("FmGridHeader::ExecuteDrop: could not retrieve the database access object !");
+ }
+
+ if (!xConnection.is())
+ {
+ DBG_ERROR("FmGridHeader::ExecuteDrop: could not retrieve the database access object !");
+ return DND_ACTION_NONE;
+ }
+ }
+
+ // try to obtain the column object
+ if (!xField.is())
+ {
+#ifdef DBG_UTIL
+ Reference< XServiceInfo > xServiceInfo(xConnection, UNO_QUERY);
+ DBG_ASSERT(xServiceInfo.is() && xServiceInfo->supportsService(SRV_SDB_CONNECTION), "FmGridHeader::ExecuteDrop: invalid connection (no database access connection !)");
+#endif
+
+ Reference< XNameAccess > xFields;
+ switch (nCommandType)
+ {
+ case CommandType::TABLE:
+ {
+ Reference< XTablesSupplier > xSupplyTables(xConnection, UNO_QUERY);
+ Reference< XColumnsSupplier > xSupplyColumns;
+ xSupplyTables->getTables()->getByName(sCommand) >>= xSupplyColumns;
+ xFields = xSupplyColumns->getColumns();
+ }
+ break;
+ case CommandType::QUERY:
+ {
+ Reference< XQueriesSupplier > xSupplyQueries(xConnection, UNO_QUERY);
+ Reference< XColumnsSupplier > xSupplyColumns;
+ xSupplyQueries->getQueries()->getByName(sCommand) >>= xSupplyColumns;
+ xFields = xSupplyColumns->getColumns();
+ }
+ break;
+ default:
+ {
+ xStatement = xConnection->prepareStatement(sCommand);
+ // not interested in any results
+
+ Reference< XPropertySet > xStatProps(xStatement,UNO_QUERY);
+ xStatProps->setPropertyValue(rtl::OUString::createFromAscii("MaxRows"), makeAny(sal_Int32(0)));
+
+ xResultSet = xStatement->executeQuery();
+ Reference< XColumnsSupplier > xSupplyCols(xResultSet, UNO_QUERY);
+ if (xSupplyCols.is())
+ xFields = xSupplyCols->getColumns();
+ }
+ }
+
+ if (xFields.is() && xFields->hasByName(sFieldName))
+ xFields->getByName(sFieldName) >>= xField;
+
+ if (!xField.is())
+ {
+ ::comphelper::disposeComponent(xStatement);
+ return DND_ACTION_NONE;
+ }
+ }
+
+ // do the drop asynchronously
+ // (85957 - UI actions within the drop are not allowed, but we want to open a popup menu)
+ m_pImpl->aDropData = aColumn;
+ m_pImpl->aDropData[daConnection] <<= xConnection;
+ m_pImpl->aDropData[daColumnObject] <<= xField;
+
+ m_pImpl->nDropAction = _rEvt.mnAction;
+ m_pImpl->aDropPosPixel = _rEvt.maPosPixel;
+ m_pImpl->xDroppedStatement = xStatement;
+ m_pImpl->xDroppedResultSet = xResultSet;
+
+ PostUserEvent(LINK(this, FmGridHeader, OnAsyncExecuteDrop));
+ }
+ catch (Exception&)
+ {
+ DBG_ERROR("FmGridHeader::ExecuteDrop: caught an exception while creatin' the column !");
+ ::comphelper::disposeComponent(xStatement);
+ return sal_False;
+ }
+
+ return DND_ACTION_LINK;
+}
+
+//------------------------------------------------------------------------------
+IMPL_LINK( FmGridHeader, OnAsyncExecuteDrop, void*, /*NOTINTERESTEDIN*/ )
+{
+ ::rtl::OUString sCommand, sFieldName,sURL;
+ sal_Int32 nCommandType = CommandType::COMMAND;
+ Reference< XPropertySet > xField;
+ Reference< XConnection > xConnection;
+
+ ::rtl::OUString sDatasouce = m_pImpl->aDropData.getDataSource();
+ if ( !sDatasouce.getLength() && m_pImpl->aDropData.has(daConnectionResource) )
+ m_pImpl->aDropData[daConnectionResource] >>= sURL;
+ m_pImpl->aDropData[daCommand] >>= sCommand;
+ m_pImpl->aDropData[daCommandType] >>= nCommandType;
+ m_pImpl->aDropData[daColumnName] >>= sFieldName;
+ m_pImpl->aDropData[daConnection] >>= xConnection;
+ m_pImpl->aDropData[daColumnObject] >>= xField;
+
+ try
+ {
+ // need number formats
+ Reference< XNumberFormatsSupplier > xSupplier = OStaticDataAccessTools().getNumberFormats(xConnection, sal_True);
+ Reference< XNumberFormats > xNumberFormats;
+ if (xSupplier.is())
+ xNumberFormats = xSupplier->getNumberFormats();
+ if (!xNumberFormats.is())
+ {
+ ::comphelper::disposeComponent(m_pImpl->xDroppedResultSet);
+ ::comphelper::disposeComponent(m_pImpl->xDroppedStatement);
+ return 0L;
+ }
+
+ // Vom Feld werden nun zwei Informationen benoetigt:
+ // a.) Name des Feldes fuer Label und ControlSource
+ // b.) FormatKey, um festzustellen, welches Feld erzeugt werden soll
+ sal_Int32 nDataType = 0;
+ xField->getPropertyValue(FM_PROP_FIELDTYPE) >>= nDataType;
+ // diese Datentypen koennen im Gridcontrol nicht verarbeitet werden
+ switch (nDataType)
+ {
+ case DataType::BLOB:
+ case DataType::LONGVARBINARY:
+ case DataType::BINARY:
+ case DataType::VARBINARY:
+ case DataType::OTHER:
+ ::comphelper::disposeComponent(m_pImpl->xDroppedResultSet);
+ ::comphelper::disposeComponent(m_pImpl->xDroppedStatement);
+ return 0L;
+ }
+
+ // Erstellen der Column
+ Reference< XIndexContainer > xCols(static_cast<FmGridControl*>(GetParent())->GetPeer()->getColumns());
+ Reference< XGridColumnFactory > xFactory(xCols, UNO_QUERY);
+
+ Point aPos = OutputToScreenPixel(m_pImpl->aDropPosPixel);
+ sal_uInt16 nColId = GetItemId(m_pImpl->aDropPosPixel);
+ // EinfuegePosition, immer vor der aktuellen Spalte
+ sal_uInt16 nPos = GetModelColumnPos(nColId);
+ Reference< XPropertySet > xCol, xSecondCol;
+
+ // erzeugen der Column in abhaengigkeit vom type, default textfeld
+ SvULongs aPossibleTypes;
+ switch (nDataType)
+ {
+ case DataType::BIT:
+ case DataType::BOOLEAN:
+ aPossibleTypes.Insert(SID_FM_CHECKBOX, aPossibleTypes.Count());
+ break;
+ case DataType::TINYINT:
+ case DataType::SMALLINT:
+ case DataType::INTEGER:
+ aPossibleTypes.Insert(SID_FM_NUMERICFIELD, aPossibleTypes.Count());
+ aPossibleTypes.Insert(SID_FM_FORMATTEDFIELD, aPossibleTypes.Count());
+ break;
+ case DataType::REAL:
+ case DataType::DOUBLE:
+ case DataType::NUMERIC:
+ case DataType::DECIMAL:
+ aPossibleTypes.Insert(SID_FM_FORMATTEDFIELD, aPossibleTypes.Count());
+ aPossibleTypes.Insert(SID_FM_NUMERICFIELD, aPossibleTypes.Count());
+ break;
+ case DataType::TIMESTAMP:
+ aPossibleTypes.Insert(SID_FM_TWOFIELDS_DATE_N_TIME, aPossibleTypes.Count());
+ aPossibleTypes.Insert(SID_FM_DATEFIELD, aPossibleTypes.Count());
+ aPossibleTypes.Insert(SID_FM_TIMEFIELD, aPossibleTypes.Count());
+ aPossibleTypes.Insert(SID_FM_FORMATTEDFIELD, aPossibleTypes.Count());
+ break;
+ case DataType::DATE:
+ aPossibleTypes.Insert(SID_FM_DATEFIELD, aPossibleTypes.Count());
+ aPossibleTypes.Insert(SID_FM_FORMATTEDFIELD, aPossibleTypes.Count());
+ break;
+ case DataType::TIME:
+ aPossibleTypes.Insert(SID_FM_TIMEFIELD, aPossibleTypes.Count());
+ aPossibleTypes.Insert(SID_FM_FORMATTEDFIELD, aPossibleTypes.Count());
+ break;
+ case DataType::CHAR:
+ case DataType::VARCHAR:
+ case DataType::LONGVARCHAR:
+ default:
+ aPossibleTypes.Insert(SID_FM_EDIT, aPossibleTypes.Count());
+ aPossibleTypes.Insert(SID_FM_FORMATTEDFIELD, aPossibleTypes.Count());
+ break;
+ }
+ // if it's a currency field, a a "currency field" option
+ try
+ {
+ if ( ::comphelper::hasProperty(FM_PROP_ISCURRENCY, xField)
+ && ::comphelper::getBOOL(xField->getPropertyValue(FM_PROP_ISCURRENCY)))
+ aPossibleTypes.Insert(SID_FM_CURRENCYFIELD, 0);
+ }
+ catch(Exception&)
+ {
+ DBG_ERROR("FmGridHeader::ExecuteDrop: Exception occured!");
+ }
+
+ sal_Int32 nPreferedType = -1;
+ sal_Bool bDateNTimeCol = sal_False;
+ if (aPossibleTypes.Count() != 0)
+ {
+ nPreferedType = aPossibleTypes[0];
+ if ((m_pImpl->nDropAction == DND_ACTION_LINK) && (aPossibleTypes.Count() > 1))
+ {
+ ImageList aImageList( SVX_RES(RID_SVXIMGLIST_FMEXPL) );
+
+ PopupMenu aInsertMenu(SVX_RES(RID_SVXMNU_COLS));
+ PopupMenu aTypeMenu;
+ PopupMenu* pMenu = aInsertMenu.GetPopupMenu(SID_FM_INSERTCOL);
+ for (sal_uInt32 i=0; i<aPossibleTypes.Count(); ++i)
+ SetMenuItem(aImageList, sal_uInt16(aPossibleTypes[(sal_uInt16)i]), pMenu, aTypeMenu, sal_True, 0);
+ nPreferedType = aTypeMenu.Execute(this, m_pImpl->aDropPosPixel);
+ }
+
+ bDateNTimeCol = nPreferedType == SID_FM_TWOFIELDS_DATE_N_TIME;
+ sal_uInt16 nColCount = bDateNTimeCol ? 2 : 1;
+ ::rtl::OUString sFieldService;
+ while (nColCount--)
+ {
+ if (bDateNTimeCol)
+ nPreferedType = nColCount ? SID_FM_DATEFIELD : SID_FM_TIMEFIELD;
+
+ sFieldService = FieldServiceFromId(nPreferedType);
+ Reference< XPropertySet > xThisRoundCol;
+ if ( sFieldService.getLength() )
+ xThisRoundCol = xFactory->createColumn(sFieldService);
+ if (nColCount)
+ xSecondCol = xThisRoundCol;
+ else
+ xCol = xThisRoundCol;
+ }
+ }
+
+ if (!xCol.is() || (bDateNTimeCol && !xSecondCol.is()))
+ {
+ ::comphelper::disposeComponent(xCol); // in case only the creation of the second column failed
+ ::comphelper::disposeComponent(m_pImpl->xDroppedResultSet);
+ ::comphelper::disposeComponent(m_pImpl->xDroppedStatement);
+ return 0L;
+ }
+
+ if (bDateNTimeCol)
+ {
+ String sTimePostfix( SVX_RES( RID_STR_POSTFIX_TIME ) );
+ xCol->setPropertyValue(FM_PROP_LABEL, makeAny( ::rtl::OUString( sFieldName + sTimePostfix ) ) );
+
+ String sDatePostfix( SVX_RES( RID_STR_POSTFIX_DATE ) );
+ xSecondCol->setPropertyValue(FM_PROP_LABEL, makeAny( ::rtl::OUString( sFieldName + sDatePostfix ) ) );
+ }
+ else
+ xCol->setPropertyValue(FM_PROP_LABEL, makeAny(sFieldName));
+
+ FormControlFactory aControlFactory( ::comphelper::getProcessServiceFactory() );
+ aControlFactory.initializeControlModel( DocumentClassification::classifyHostDocument( xCols ), xCol );
+ aControlFactory.initializeFieldDependentProperties( xField, xCol, xNumberFormats );
+
+ xCol->setPropertyValue(FM_PROP_CONTROLSOURCE, makeAny(sFieldName));
+ if ( xSecondCol.is() )
+ xSecondCol->setPropertyValue(FM_PROP_CONTROLSOURCE, makeAny(sFieldName));
+
+ if (bDateNTimeCol)
+ {
+ String sRealName,sPurePostfix;
+
+ String aPostfix[] = {
+ String( SVX_RES( RID_STR_POSTFIX_DATE ) ),
+ String( SVX_RES( RID_STR_POSTFIX_TIME ) )
+ };
+
+ for ( size_t i=0; i<2; ++i )
+ {
+ sPurePostfix = aPostfix[i];
+ sPurePostfix.EraseLeadingChars(' ');
+ sPurePostfix.EraseLeadingChars('(');
+ sPurePostfix.EraseTrailingChars(')');
+ sRealName = sFieldName;
+ sRealName += '_';
+ sRealName += sPurePostfix;
+ if (i)
+ xSecondCol->setPropertyValue(FM_PROP_NAME, makeAny(::rtl::OUString(sRealName)));
+ else
+ xCol->setPropertyValue(FM_PROP_NAME, makeAny(::rtl::OUString(sRealName)));
+ }
+ }
+ else
+ xCol->setPropertyValue(FM_PROP_NAME, makeAny(sFieldName));
+
+ // jetzt einfuegen
+ Any aElement;
+ aElement <<= xCol;
+ xCols->insertByIndex(nPos, aElement);
+
+ if (bDateNTimeCol)
+ {
+ aElement <<= xSecondCol;
+ xCols->insertByIndex(nPos == (sal_uInt16)-1 ? nPos : ++nPos, aElement);
+ }
+
+ // ist die component::Form an die Datenbankangebunden?
+ Reference< XFormComponent > xFormCp(xCols, UNO_QUERY);
+ Reference< XPropertySet > xForm(xFormCp->getParent(), UNO_QUERY);
+ if (xForm.is())
+ {
+ if (!::comphelper::getString(xForm->getPropertyValue(FM_PROP_DATASOURCE)).getLength())
+ {
+ if ( sDatasouce.getLength() )
+ xForm->setPropertyValue(FM_PROP_DATASOURCE, makeAny(sDatasouce));
+ else
+ xForm->setPropertyValue(FM_PROP_URL, makeAny(sURL));
+ }
+
+ if (!::comphelper::getString(xForm->getPropertyValue(FM_PROP_COMMAND)).getLength())
+ {
+ xForm->setPropertyValue(FM_PROP_COMMAND, makeAny(sCommand));
+ Any aCommandType;
+ switch (nCommandType)
+ {
+ case CommandType::TABLE:
+ aCommandType <<= (sal_Int32)CommandType::TABLE;
+ break;
+ case CommandType::QUERY:
+ aCommandType <<= (sal_Int32)CommandType::QUERY;
+ break;
+ default:
+ aCommandType <<= (sal_Int32)CommandType::COMMAND;
+ xForm->setPropertyValue(FM_PROP_ESCAPE_PROCESSING, bool2any((sal_Bool)(2 == nCommandType)));
+ break;
+ }
+ xForm->setPropertyValue(FM_PROP_COMMANDTYPE, aCommandType);
+ }
+ }
+ }
+ catch (Exception&)
+ {
+ DBG_ERROR("FmGridHeader::OnAsyncExecuteDrop: caught an exception while creatin' the column !");
+ ::comphelper::disposeComponent(m_pImpl->xDroppedResultSet);
+ ::comphelper::disposeComponent(m_pImpl->xDroppedStatement);
+ return 0L;
+ }
+
+ ::comphelper::disposeComponent(m_pImpl->xDroppedResultSet);
+ ::comphelper::disposeComponent(m_pImpl->xDroppedStatement);
+ return 1L;
+}
+
+//------------------------------------------------------------------------------
+void FmGridHeader::PreExecuteColumnContextMenu(sal_uInt16 nColId, PopupMenu& rMenu)
+{
+ sal_Bool bDesignMode = static_cast<FmGridControl*>(GetParent())->IsDesignMode();
+
+ Reference< ::com::sun::star::container::XIndexContainer > xCols(static_cast<FmGridControl*>(GetParent())->GetPeer()->getColumns());
+ // Aufbau des Insert Menues
+ // mark the column if nColId != HEADERBAR_ITEM_NOTFOUND
+ if(nColId > 0)
+ {
+ sal_uInt16 nPos2 = GetModelColumnPos(nColId);
+
+ Reference< ::com::sun::star::container::XIndexContainer > xColumns(static_cast<FmGridControl*>(GetParent())->GetPeer()->getColumns());
+ Reference< ::com::sun::star::beans::XPropertySet> xColumn;
+ ::cppu::extractInterface(xColumn, xColumns->getByIndex(nPos2));
+ Reference< ::com::sun::star::view::XSelectionSupplier > xSelSupplier(xColumns, UNO_QUERY);
+ if (xSelSupplier.is())
+ xSelSupplier->select(makeAny(xColumn));
+ }
+
+ // EinfuegePosition, immer vor der aktuellen Spalte
+ sal_uInt16 nPos = GetModelColumnPos(nColId);
+ sal_Bool bMarked = nColId && static_cast<FmGridControl*>(GetParent())->isColumnMarked(nColId);
+
+ ImageList aImageList( SVX_RES(RID_SVXIMGLIST_FMEXPL) );
+ PopupMenu* pControlMenu = new PopupMenu;
+
+ PopupMenu* pMenu = rMenu.GetPopupMenu(SID_FM_INSERTCOL);
+ if (pMenu)
+ {
+ SetMenuItem(aImageList, SID_FM_EDIT, pMenu, *pControlMenu, bDesignMode);
+ SetMenuItem(aImageList, SID_FM_CHECKBOX, pMenu, *pControlMenu, bDesignMode);
+ SetMenuItem(aImageList, SID_FM_COMBOBOX, pMenu, *pControlMenu, bDesignMode);
+ SetMenuItem(aImageList, SID_FM_LISTBOX, pMenu, *pControlMenu, bDesignMode);
+ SetMenuItem(aImageList, SID_FM_DATEFIELD, pMenu, *pControlMenu, bDesignMode);
+ SetMenuItem(aImageList, SID_FM_TIMEFIELD, pMenu, *pControlMenu, bDesignMode);
+ SetMenuItem(aImageList, SID_FM_NUMERICFIELD, pMenu, *pControlMenu, bDesignMode);
+ SetMenuItem(aImageList, SID_FM_CURRENCYFIELD, pMenu, *pControlMenu, bDesignMode);
+ SetMenuItem(aImageList, SID_FM_PATTERNFIELD, pMenu, *pControlMenu, bDesignMode);
+ SetMenuItem(aImageList, SID_FM_FORMATTEDFIELD, pMenu, *pControlMenu, bDesignMode);
+ }
+
+ if (pMenu && xCols.is() && nColId)
+ {
+ Reference< ::com::sun::star::beans::XPropertySet > xSet;
+ ::cppu::extractInterface(xSet, xCols->getByIndex(nPos));
+ sal_Int16 nClassId;
+ xSet->getPropertyValue(FM_PROP_CLASSID) >>= nClassId;
+
+ Reference< ::com::sun::star::io::XPersistObject > xServiceQuestion(xSet, UNO_QUERY);
+ sal_Int32 nColType = xServiceQuestion.is() ? getColumnTypeByModelName(xServiceQuestion->getServiceName()) : 0;
+ if (nColType == TYPE_TEXTFIELD)
+ { // edit fields and formatted fields have the same service name, thus getColumnTypeByModelName returns TYPE_TEXTFIELD
+ // in both cases. And as columns don't have an ::com::sun::star::lang::XServiceInfo interface, we have to distinguish both
+ // types via the existence of special properties
+ Reference< ::com::sun::star::beans::XPropertySet > xProps(xSet, UNO_QUERY);
+ if (xProps.is())
+ {
+ Reference< ::com::sun::star::beans::XPropertySetInfo > xPropsInfo = xProps->getPropertySetInfo();
+ if (xPropsInfo.is() && xPropsInfo->hasPropertyByName(FM_PROP_FORMATSSUPPLIER))
+ nColType = TYPE_FORMATTEDFIELD;
+ }
+ }
+
+ pControlMenu->EnableItem(SID_FM_EDIT + nChangeTypeOffset, bDesignMode && (nColType != TYPE_TEXTFIELD));
+ pControlMenu->EnableItem(SID_FM_COMBOBOX + nChangeTypeOffset, bDesignMode && (nColType != TYPE_COMBOBOX));
+ pControlMenu->EnableItem(SID_FM_LISTBOX + nChangeTypeOffset, bDesignMode && (nColType != TYPE_LISTBOX));
+ pControlMenu->EnableItem(SID_FM_CHECKBOX + nChangeTypeOffset, bDesignMode && (nColType != TYPE_CHECKBOX));
+ pControlMenu->EnableItem(SID_FM_DATEFIELD + nChangeTypeOffset, bDesignMode && (nColType != TYPE_DATEFIELD));
+ pControlMenu->EnableItem(SID_FM_NUMERICFIELD + nChangeTypeOffset, bDesignMode && (nColType != TYPE_NUMERICFIELD));
+ pControlMenu->EnableItem(SID_FM_TIMEFIELD + nChangeTypeOffset, bDesignMode && (nColType != TYPE_TIMEFIELD));
+ pControlMenu->EnableItem(SID_FM_CURRENCYFIELD + nChangeTypeOffset, bDesignMode && (nColType != TYPE_CURRENCYFIELD));
+ pControlMenu->EnableItem(SID_FM_PATTERNFIELD + nChangeTypeOffset, bDesignMode && (nColType != TYPE_PATTERNFIELD));
+ pControlMenu->EnableItem(SID_FM_FORMATTEDFIELD + nChangeTypeOffset, bDesignMode && (nColType != TYPE_FORMATTEDFIELD));
+ rMenu.SetPopupMenu(SID_FM_CHANGECOL, pControlMenu);
+ }
+
+ rMenu.EnableItem(SID_FM_INSERTCOL, bDesignMode && xCols.is());
+ rMenu.EnableItem(SID_FM_DELETECOL, bDesignMode && bMarked && xCols.is());
+ rMenu.EnableItem(SID_FM_CHANGECOL, bDesignMode && bMarked && xCols.is());
+ rMenu.EnableItem(SID_FM_SHOW_PROPERTY_BROWSER, bDesignMode && bMarked && xCols.is());
+
+ PopupMenu* pShowColsMenu = rMenu.GetPopupMenu(SID_FM_SHOWCOLS);
+ sal_uInt16 nHiddenCols = 0;
+ if (pShowColsMenu)
+ {
+ if (xCols.is())
+ {
+ // check for hidden cols
+ Reference< ::com::sun::star::beans::XPropertySet > xCurCol;
+ Any aHidden,aName;
+ for (sal_uInt16 i=0; i<xCols->getCount(); ++i)
+ {
+ ::cppu::extractInterface(xCurCol, xCols->getByIndex(i));
+ DBG_ASSERT(xCurCol.is(), "FmGridHeader::PreExecuteColumnContextMenu : the Peer has invalid columns !");
+ aHidden = xCurCol->getPropertyValue(FM_PROP_HIDDEN);
+ DBG_ASSERT(aHidden.getValueType().getTypeClass() == TypeClass_BOOLEAN,
+ "FmGridHeader::PreExecuteColumnContextMenu : the property 'hidden' should be boolean !");
+ if (::comphelper::getBOOL(aHidden))
+ {
+ // put the column name into the 'show col' menu
+ if (nHiddenCols < 16)
+ { // (only the first 16 items to keep the menu rather small)
+ aName = xCurCol->getPropertyValue(FM_PROP_LABEL);
+ pShowColsMenu->InsertItem(nHiddenCols + 1, ::comphelper::getString(aName), 0, nHiddenCols);
+ // the ID is arbitrary, but should be unique within the whole menu
+ }
+ ++nHiddenCols;
+ }
+ }
+ }
+ pShowColsMenu->EnableItem(SID_FM_SHOWCOLS_MORE, xCols.is() && (nHiddenCols > 16));
+ pShowColsMenu->EnableItem(SID_FM_SHOWALLCOLS, xCols.is() && (nHiddenCols > 0));
+ }
+
+ // allow the 'hide column' item ?
+ sal_Bool bAllowHide = bMarked; // a column is marked
+ bAllowHide = bAllowHide || (!bDesignMode && (nPos != (sal_uInt16)-1)); // OR we are in alive mode and have hit a column
+ bAllowHide = bAllowHide && xCols.is(); // AND we have a column container
+ bAllowHide = bAllowHide && (xCols->getCount()-nHiddenCols > 1); // AND there are at least two visible columns
+ rMenu.EnableItem(SID_FM_HIDECOL, bAllowHide);
+
+ sal_Bool bChecked = sal_False;
+ if (bMarked)
+ {
+
+ SfxViewFrame* pCurrentFrame = SfxViewFrame::Current();
+ SfxItemState eState = SFX_ITEM_UNKNOWN;
+ // ask the bindings of the current view frame (which should be the one we're residing in) for the state
+ if (pCurrentFrame)
+ {
+ SfxPoolItem* pItem = NULL;
+ eState = pCurrentFrame->GetBindings().QueryState(SID_FM_CTL_PROPERTIES, pItem);
+
+ if (eState >= SFX_ITEM_AVAILABLE && pItem )
+ {
+ bChecked = pItem->ISA(SfxBoolItem) && ((SfxBoolItem*)pItem)->GetValue();
+ rMenu.CheckItem(SID_FM_SHOW_PROPERTY_BROWSER,bChecked);
+ }
+ delete pItem;
+ }
+ }
+}
+
+enum InspectorAction { eOpenInspector, eCloseInspector, eUpdateInspector, eNone };
+
+//------------------------------------------------------------------------------
+void FmGridHeader::PostExecuteColumnContextMenu(sal_uInt16 nColId, const PopupMenu& rMenu, sal_uInt16 nExecutionResult)
+{
+ Reference< ::com::sun::star::container::XIndexContainer > xCols(static_cast<FmGridControl*>(GetParent())->GetPeer()->getColumns());
+ sal_uInt16 nPos = GetModelColumnPos(nColId);
+
+ // remove and delet the menu we inserted in PreExecuteColumnContextMenu
+ PopupMenu* pControlMenu = rMenu.GetPopupMenu(SID_FM_CHANGECOL);
+ delete pControlMenu;
+
+ ::rtl::OUString aFieldType;
+ sal_Bool bReplace = sal_False;
+ InspectorAction eInspectorAction = eNone;
+ Reference< XPropertySet > xColumnToInspect;
+ switch (nExecutionResult)
+ {
+ case SID_FM_DELETECOL:
+ {
+ Reference< XInterface > xCol;
+ ::cppu::extractInterface(xCol, xCols->getByIndex(nPos));
+ xCols->removeByIndex(nPos);
+ ::comphelper::disposeComponent(xCol);
+ } break;
+ case SID_FM_SHOW_PROPERTY_BROWSER:
+ eInspectorAction = rMenu.IsItemChecked( SID_FM_SHOW_PROPERTY_BROWSER ) ? eOpenInspector : eCloseInspector;
+ xColumnToInspect.set( xCols->getByIndex( nPos ), UNO_QUERY );
+ break;
+ case SID_FM_EDIT + nChangeTypeOffset:
+ bReplace = sal_True;
+ case SID_FM_EDIT:
+ aFieldType = FM_COL_TEXTFIELD;
+ break;
+ case SID_FM_COMBOBOX + nChangeTypeOffset:
+ bReplace = sal_True;
+ case SID_FM_COMBOBOX:
+ aFieldType = FM_COL_COMBOBOX;
+ break;
+ case SID_FM_LISTBOX + nChangeTypeOffset:
+ bReplace = sal_True;
+ case SID_FM_LISTBOX:
+ aFieldType = FM_COL_LISTBOX;
+ break;
+ case SID_FM_CHECKBOX + nChangeTypeOffset:
+ bReplace = sal_True;
+ case SID_FM_CHECKBOX:
+ aFieldType = FM_COL_CHECKBOX;
+ break;
+ case SID_FM_DATEFIELD + nChangeTypeOffset:
+ bReplace = sal_True;
+ case SID_FM_DATEFIELD:
+ aFieldType = FM_COL_DATEFIELD;
+ break;
+ case SID_FM_TIMEFIELD + nChangeTypeOffset:
+ bReplace = sal_True;
+ case SID_FM_TIMEFIELD:
+ aFieldType = FM_COL_TIMEFIELD;
+ break;
+ case SID_FM_NUMERICFIELD + nChangeTypeOffset:
+ bReplace = sal_True;
+ case SID_FM_NUMERICFIELD:
+ aFieldType = FM_COL_NUMERICFIELD;
+ break;
+ case SID_FM_CURRENCYFIELD + nChangeTypeOffset:
+ bReplace = sal_True;
+ case SID_FM_CURRENCYFIELD:
+ aFieldType = FM_COL_CURRENCYFIELD;
+ break;
+ case SID_FM_PATTERNFIELD + nChangeTypeOffset:
+ bReplace = sal_True;
+ case SID_FM_PATTERNFIELD:
+ aFieldType = FM_COL_PATTERNFIELD;
+ break;
+ case SID_FM_FORMATTEDFIELD + nChangeTypeOffset:
+ bReplace = sal_True;
+ case SID_FM_FORMATTEDFIELD:
+ aFieldType = FM_COL_FORMATTEDFIELD;
+ break;
+ case SID_FM_HIDECOL:
+ {
+ Reference< ::com::sun::star::beans::XPropertySet > xCurCol;
+ ::cppu::extractInterface(xCurCol, xCols->getByIndex(nPos));
+ xCurCol->setPropertyValue(FM_PROP_HIDDEN, makeAny((sal_Bool)sal_True));
+ }
+ break;
+ case SID_FM_SHOWCOLS_MORE:
+ {
+ SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
+ if(pFact)
+ {
+ AbstractFmShowColsDialog* pDlg = pFact->CreateFmShowColsDialog(NULL);
+ DBG_ASSERT(pDlg, "Dialogdiet fail!");//CHINA001
+ pDlg->SetColumns(xCols);
+ pDlg->Execute();
+ delete pDlg;
+ }
+
+ }
+ break;
+ case SID_FM_SHOWALLCOLS:
+ {
+ // just iterate through all the cols ...
+ Reference< ::com::sun::star::beans::XPropertySet > xCurCol;
+ for (sal_uInt16 i=0; i<xCols->getCount(); ++i)
+ {
+ ::cppu::extractInterface(xCurCol, xCols->getByIndex(i));
+ xCurCol->setPropertyValue(FM_PROP_HIDDEN, makeAny((sal_Bool)sal_False));
+ }
+ // TODO : there must be a more clever way to do this ....
+ // with the above the view is updated after every single model update ...
+ }
+ break;
+ default:
+ if (nExecutionResult>0 && nExecutionResult<=16)
+ { // it was a "show column/<colname>" command (there are at most 16 such items)
+ // search the nExecutionResult'th hidden col
+ Reference< ::com::sun::star::beans::XPropertySet > xCurCol;
+ for (sal_uInt16 i=0; i<xCols->getCount() && nExecutionResult; ++i)
+ {
+ ::cppu::extractInterface(xCurCol, xCols->getByIndex(i));
+ Any aHidden = xCurCol->getPropertyValue(FM_PROP_HIDDEN);
+ if (::comphelper::getBOOL(aHidden))
+ if (!--nExecutionResult)
+ {
+ xCurCol->setPropertyValue(FM_PROP_HIDDEN, makeAny((sal_Bool)sal_False));
+ break;
+ }
+ }
+ }
+ break;
+ }
+
+ if ( aFieldType.getLength() )
+ {
+ try
+ {
+ Reference< XGridColumnFactory > xFactory( xCols, UNO_QUERY_THROW );
+ Reference< XPropertySet > xNewCol( xFactory->createColumn( aFieldType ), UNO_SET_THROW );
+
+ if ( bReplace )
+ {
+ // ein paar Properties hinueberretten
+ Reference< XPropertySet > xReplaced( xCols->getByIndex( nPos ), UNO_QUERY );
+
+ OStaticDataAccessTools().TransferFormComponentProperties(
+ xReplaced, xNewCol, Application::GetSettings().GetUILocale() );
+
+ xCols->replaceByIndex( nPos, makeAny( xNewCol ) );
+ ::comphelper::disposeComponent( xReplaced );
+
+ eInspectorAction = eUpdateInspector;
+ xColumnToInspect = xNewCol;
+ }
+ else
+ {
+ FormControlFactory factory( ::comphelper::getProcessServiceFactory() );
+
+ ::rtl::OUString sLabel = factory.getDefaultUniqueName_ByComponentType(
+ Reference< XNameAccess >( xCols, UNO_QUERY_THROW ), xNewCol );
+ xNewCol->setPropertyValue( FM_PROP_LABEL, makeAny( sLabel ) );
+ xNewCol->setPropertyValue( FM_PROP_NAME, makeAny( sLabel ) );
+
+ factory.initializeControlModel( DocumentClassification::classifyHostDocument( xCols ), xNewCol );
+
+ xCols->insertByIndex( nPos, makeAny( xNewCol ) );
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+ }
+
+ SfxViewFrame* pCurrentFrame = SfxViewFrame::Current();
+ OSL_ENSURE( pCurrentFrame, "FmGridHeader::PostExecuteColumnContextMenu: no view frame -> no bindings -> no property browser!" );
+ if ( pCurrentFrame )
+ {
+ if ( eInspectorAction == eUpdateInspector )
+ {
+ if ( !pCurrentFrame->HasChildWindow( SID_FM_SHOW_PROPERTIES ) )
+ eInspectorAction = eNone;
+ }
+
+ if ( eInspectorAction != eNone )
+ {
+ FmInterfaceItem aIFaceItem( SID_FM_SHOW_PROPERTY_BROWSER, xColumnToInspect );
+ SfxBoolItem aShowItem( SID_FM_SHOW_PROPERTIES, eInspectorAction == eCloseInspector ? FALSE : TRUE );
+
+ pCurrentFrame->GetBindings().GetDispatcher()->Execute( SID_FM_SHOW_PROPERTY_BROWSER, SFX_CALLMODE_ASYNCHRON,
+ &aIFaceItem, &aShowItem, 0L );
+ }
+ }
+}
+
+//------------------------------------------------------------------------------
+void FmGridHeader::triggerColumnContextMenu( const ::Point& _rPreferredPos )
+{
+ // the affected col
+ sal_uInt16 nColId = GetItemId( _rPreferredPos );
+
+ // the menu
+ PopupMenu aContextMenu( SVX_RES( RID_SVXMNU_COLS ) );
+
+ // let derivees modify the menu
+ PreExecuteColumnContextMenu( nColId, aContextMenu );
+ aContextMenu.RemoveDisabledEntries( sal_True, sal_True );
+
+ // execute the menu
+ sal_uInt16 nResult = aContextMenu.Execute( this, _rPreferredPos );
+
+ // let derivees handle the result
+ PostExecuteColumnContextMenu( nColId, aContextMenu, nResult );
+}
+
+//------------------------------------------------------------------------------
+void FmGridHeader::Command(const CommandEvent& rEvt)
+{
+ switch (rEvt.GetCommand())
+ {
+ case COMMAND_CONTEXTMENU:
+ {
+ if (!rEvt.IsMouseEvent())
+ return;
+
+ triggerColumnContextMenu( rEvt.GetMousePosPixel() );
+ }
+ break;
+ default:
+ EditBrowserHeader::Command(rEvt);
+ }
+}
+
+//------------------------------------------------------------------------------
+FmGridControl::FmGridControl(
+ Reference< ::com::sun::star::lang::XMultiServiceFactory > _rxFactory,
+ Window* pParent,
+ FmXGridPeer* _pPeer,
+ WinBits nBits)
+ :DbGridControl(_rxFactory, pParent, nBits)
+ ,m_pPeer(_pPeer)
+ ,m_nCurrentSelectedColumn(-1)
+ ,m_nMarkedColumnId(BROWSER_INVALIDID)
+ ,m_bSelecting(sal_False)
+ ,m_bInColumnMove(sal_False)
+{
+ EnableInteractiveRowHeight( );
+}
+
+//------------------------------------------------------------------------------
+void FmGridControl::Command(const CommandEvent& _rEvt)
+{
+ if ( COMMAND_CONTEXTMENU == _rEvt.GetCommand() )
+ {
+ FmGridHeader* pMyHeader = static_cast< FmGridHeader* >( GetHeaderBar() );
+ if ( pMyHeader && !_rEvt.IsMouseEvent() )
+ { // context menu requested by keyboard
+ if ( 1 == GetSelectColumnCount() || IsDesignMode() )
+ {
+ sal_uInt16 nSelId = GetColumnId(
+ sal::static_int_cast< USHORT >( FirstSelectedColumn() ) );
+ ::Rectangle aColRect( GetFieldRectPixel( 0, nSelId, sal_False ) );
+
+ Point aRelativePos( pMyHeader->ScreenToOutputPixel( OutputToScreenPixel( aColRect.TopCenter() ) ) );
+ pMyHeader->triggerColumnContextMenu( aRelativePos, FmGridHeader::AccessControl() );
+
+ // handled
+ return;
+ }
+ }
+ }
+
+ DbGridControl::Command( _rEvt );
+}
+
+// ::com::sun::star::beans::XPropertyChangeListener
+//------------------------------------------------------------------------------
+void FmGridControl::propertyChange(const ::com::sun::star::beans::PropertyChangeEvent& evt)
+{
+ if (evt.PropertyName == FM_PROP_ROWCOUNT)
+ {
+ // if we're not in the main thread call AdjustRows asynchronously
+ implAdjustInSolarThread(sal_True);
+ return;
+ }
+
+ const DbGridRowRef& xRow = GetCurrentRow();
+ // waehrend Positionierung wird kein abgleich der Properties vorgenommen
+ Reference<XPropertySet> xSet(evt.Source,UNO_QUERY);
+ if (xRow.Is() && (::cppu::any2bool(xSet->getPropertyValue(FM_PROP_ISNEW))|| CompareBookmark(getDataSource()->getBookmark(), xRow->GetBookmark())))
+ {
+ if (evt.PropertyName == FM_PROP_ISMODIFIED)
+ {
+ // modified or clean ?
+ GridRowStatus eStatus = ::comphelper::getBOOL(evt.NewValue) ? GRS_MODIFIED : GRS_CLEAN;
+ if (eStatus != xRow->GetStatus())
+ {
+ xRow->SetStatus(eStatus);
+ vos::OGuard aGuard( Application::GetSolarMutex() );
+ RowModified(GetCurrentPos());
+ }
+ }
+ }
+}
+
+//------------------------------------------------------------------------------
+void FmGridControl::SetDesignMode(sal_Bool bMode)
+{
+ sal_Bool bOldMode = IsDesignMode();
+ DbGridControl::SetDesignMode(bMode);
+ if (bOldMode != bMode)
+ {
+ if (!bMode)
+ {
+ // selection aufheben
+ markColumn(USHRT_MAX);
+ }
+ else
+ {
+ Reference< ::com::sun::star::container::XIndexContainer > xColumns(GetPeer()->getColumns());
+ Reference< ::com::sun::star::view::XSelectionSupplier > xSelSupplier(xColumns, UNO_QUERY);
+ if (xSelSupplier.is())
+ {
+ Any aSelection = xSelSupplier->getSelection();
+ Reference< ::com::sun::star::beans::XPropertySet > xColumn;
+ if (aSelection.getValueType().getTypeClass() == TypeClass_INTERFACE)
+ ::cppu::extractInterface(xColumn, aSelection);
+ Reference< XInterface > xCurrent;
+ for (sal_uInt16 i=0; i<xColumns->getCount(); ++i)
+ {
+ ::cppu::extractInterface(xCurrent, xColumns->getByIndex(i));
+ if (xCurrent == xColumn)
+ {
+ markColumn(GetColumnIdFromModelPos(i));
+ break;
+ }
+ }
+ }
+ }
+ }
+}
+
+//------------------------------------------------------------------------------
+void FmGridControl::DeleteSelectedRows()
+{
+ if (!m_pSeekCursor)
+ return;
+
+ // how many rows are selected?
+ sal_Int32 nSelectedRows = GetSelectRowCount();
+
+ // the current line should be deleted but it is currently in edit mode
+ if ( IsCurrentAppending() )
+ return;
+ // is the insert row selected
+ if (GetEmptyRow().Is() && IsRowSelected(GetRowCount() - 1))
+ nSelectedRows -= 1;
+
+ // nothing to do
+ if (nSelectedRows <= 0)
+ return;
+
+ // try to confirm the delete
+ Reference< ::com::sun::star::frame::XDispatchProvider > xDispatcher = (::com::sun::star::frame::XDispatchProvider*)GetPeer();
+ if (xDispatcher.is())
+ {
+ ::com::sun::star::util::URL aUrl;
+ aUrl.Complete = FMURL_CONFIRM_DELETION;
+ // #100312# ------------
+ Reference< ::com::sun::star::util::XURLTransformer > xTransformer(
+ ::comphelper::getProcessServiceFactory()->createInstance(
+ ::rtl::OUString::createFromAscii("com.sun.star.util.URLTransformer")), UNO_QUERY);
+ if( xTransformer.is() )
+ xTransformer->parseStrict( aUrl );
+
+ Reference< ::com::sun::star::frame::XDispatch > xDispatch = xDispatcher->queryDispatch(aUrl, rtl::OUString(), 0);
+ Reference< ::com::sun::star::form::XConfirmDeleteListener > xConfirm(xDispatch, UNO_QUERY);
+ if (xConfirm.is())
+ {
+ ::com::sun::star::sdb::RowChangeEvent aEvent;
+ aEvent.Source = (Reference< XInterface > )(*getDataSource());
+ aEvent.Rows = nSelectedRows;
+ aEvent.Action = ::com::sun::star::sdb::RowChangeAction::DELETE;
+ if (!xConfirm->confirmDelete(aEvent))
+ return;
+ }
+ }
+
+ const MultiSelection* pRowSelection = GetSelection();
+ if ( pRowSelection && pRowSelection->IsAllSelected() )
+ {
+ BeginCursorAction();
+ CursorWrapper* pCursor = getDataSource();
+ Reference< XResultSetUpdate > xUpdateCursor((Reference< XInterface >)*pCursor, UNO_QUERY);
+ try
+ {
+ pCursor->beforeFirst();
+ while( pCursor->next() )
+ xUpdateCursor->deleteRow();
+
+ SetUpdateMode(sal_False);
+ SetNoSelection();
+
+ xUpdateCursor->moveToInsertRow();
+ }
+ catch(const Exception&)
+ {
+ OSL_ENSURE(0,"Exception caught while deleting rows!");
+ }
+ // An den DatenCursor anpassen
+ AdjustDataSource(sal_True);
+ EndCursorAction();
+ SetUpdateMode(sal_True);
+ }
+ else
+ {
+ Reference< ::com::sun::star::sdbcx::XDeleteRows > xDeleteThem((Reference< XInterface >)*getDataSource(), UNO_QUERY);
+
+ // colect the bookmarks of the selected rows
+ Sequence < Any> aBookmarks = getSelectionBookmarks();
+
+ // determine the next row to position after deletion
+ Any aBookmark;
+ sal_Bool bNewPos = sal_False;
+ // if the current row isn't selected we take the row as row after deletion
+ OSL_ENSURE( GetCurrentRow().Is(), "FmGridControl::DeleteSelectedRows: no current row here?" );
+ // crash reports suggest it can happen we don't have a current row - how?
+ // #154303# / 2008-04-23 / frank.schoenheit@sun.com
+ if ( !IsRowSelected( GetCurrentPos() ) && !IsCurrentAppending() && GetCurrentRow().Is() )
+ {
+ aBookmark = GetCurrentRow()->GetBookmark();
+ bNewPos = sal_True;
+ }
+ else
+ {
+ // we look for the first row after the selected block for selection
+ long nIdx = LastSelectedRow() + 1;
+ if (nIdx < GetRowCount() - 1)
+ {
+ // there is a next row to position on
+ if (SeekCursor(nIdx))
+ {
+ GetSeekRow()->SetState(m_pSeekCursor, sal_True);
+
+ bNewPos = sal_True;
+ // if it's not the row for inserting we keep the bookmark
+ if (!IsInsertionRow(nIdx))
+ aBookmark = m_pSeekCursor->getBookmark();
+ }
+ }
+ else
+ {
+ // we look for the first row before the selected block for selection after deletion
+ nIdx = FirstSelectedRow() - 1;
+ if (nIdx >= 0 && SeekCursor(nIdx))
+ {
+ GetSeekRow()->SetState(m_pSeekCursor, sal_True);
+
+ bNewPos = sal_True;
+ aBookmark = m_pSeekCursor->getBookmark();
+ }
+ }
+ }
+
+ // Sind alle Zeilen Selectiert
+ // Zweite bedingung falls keine einguegeZeile existiert
+ sal_Bool bAllSelected = GetTotalCount() == nSelectedRows || GetRowCount() == nSelectedRows;
+
+ BeginCursorAction();
+
+ // now delete the row
+ Sequence <sal_Int32> aDeletedRows;
+ SetUpdateMode( FALSE );
+ try
+ {
+ aDeletedRows = xDeleteThem->deleteRows(aBookmarks);
+ }
+ catch(SQLException&)
+ {
+ }
+ SetUpdateMode( TRUE );
+
+ // how many rows are deleted?
+ sal_Int32 nDeletedRows = 0;
+ const sal_Int32* pSuccess = aDeletedRows.getConstArray();
+ for (sal_Int32 i = 0; i < aDeletedRows.getLength(); i++)
+ {
+ if (pSuccess[i])
+ ++nDeletedRows;
+ }
+
+ // sind Zeilen geloescht worden?
+ if (nDeletedRows)
+ {
+ SetUpdateMode(sal_False);
+ SetNoSelection();
+ try
+ {
+ // did we delete all the rows than try to move to the next possible row
+ if (nDeletedRows == aDeletedRows.getLength())
+ {
+ // there exists a new position to move on
+ if (bNewPos)
+ {
+ if (aBookmark.hasValue())
+ getDataSource()->moveToBookmark(aBookmark);
+ // no valid bookmark so move to the insert row
+ else
+ {
+ Reference< XResultSetUpdate > xUpdateCursor((Reference< XInterface >)*m_pDataCursor, UNO_QUERY);
+ xUpdateCursor->moveToInsertRow();
+ }
+ }
+ else
+ {
+ Reference< ::com::sun::star::beans::XPropertySet > xSet((Reference< XInterface >)*m_pDataCursor, UNO_QUERY);
+
+ sal_Int32 nRecordCount(0);
+ xSet->getPropertyValue(FM_PROP_ROWCOUNT) >>= nRecordCount;
+ if ( m_pDataCursor->rowDeleted() )
+ --nRecordCount;
+
+ // there are no rows left and we have an insert row
+ if (!nRecordCount && GetEmptyRow().Is())
+ {
+ Reference< XResultSetUpdate > xUpdateCursor((Reference< XInterface >)*m_pDataCursor, UNO_QUERY);
+ xUpdateCursor->moveToInsertRow();
+ }
+ else if (nRecordCount)
+ // move to the first row
+ getDataSource()->first();
+ }
+ }
+ // not all the rows where deleted, so move to the first row which remained in the resultset
+ else
+ {
+ for (sal_Int32 i = 0; i < aDeletedRows.getLength(); i++)
+ {
+ if (!pSuccess[i])
+ {
+ getDataSource()->moveToBookmark(aBookmarks.getConstArray()[i]);
+ break;
+ }
+ }
+ }
+ }
+ catch(const Exception&)
+ {
+ try
+ {
+ // positioning went wrong so try to move to the first row
+ getDataSource()->first();
+ }
+ catch(const Exception&)
+ {
+ }
+ }
+
+ // An den DatenCursor anpassen
+ AdjustDataSource(sal_True);
+
+ // es konnten nicht alle Zeilen geloescht werden
+ // da nie nicht geloeschten wieder selektieren
+ if (nDeletedRows < nSelectedRows)
+ {
+ // waren alle selektiert
+ if (bAllSelected)
+ {
+ SelectAll();
+ if (IsInsertionRow(GetRowCount() - 1)) // einfuegeZeile nicht
+ SelectRow(GetRowCount() - 1, sal_False);
+ }
+ else
+ {
+ // select the remaining rows
+ for (sal_Int32 i = 0; i < aDeletedRows.getLength(); i++)
+ {
+ try
+ {
+ if (!pSuccess[i])
+ {
+ m_pSeekCursor->moveToBookmark(m_pDataCursor->getBookmark());
+ SetSeekPos(m_pSeekCursor->getRow() - 1);
+ SelectRow(GetSeekPos());
+ }
+ }
+ catch(const Exception&)
+ {
+ // keep the seekpos in all cases
+ SetSeekPos(m_pSeekCursor->getRow() - 1);
+ }
+ }
+ }
+ }
+
+ EndCursorAction();
+ SetUpdateMode(sal_True);
+ }
+ else // Zeile konnte nicht geloescht werden
+ {
+ EndCursorAction();
+ try
+ {
+ // currentrow is the insert row?
+ if (!IsCurrentAppending())
+ getDataSource()->refreshRow();
+ }
+ catch(const Exception&)
+ {
+ }
+ }
+ }
+
+ // if there is no selection anymore we can start editing
+ if (!GetSelectRowCount())
+ ActivateCell();
+}
+
+
+// XCurrentRecordListener
+//------------------------------------------------------------------------------
+void FmGridControl::positioned(const ::com::sun::star::lang::EventObject& /*rEvent*/)
+{
+ TRACE_RANGE("FmGridControl::positioned");
+ // position on the data source (force it to be done in the main thread)
+ implAdjustInSolarThread(sal_False);
+}
+
+//------------------------------------------------------------------------------
+sal_Bool FmGridControl::commit()
+{
+ // Commit nur ausfuehren, wenn nicht bereits ein Update vom ::com::sun::star::form::component::GridControl ausgefuehrt
+ // wird
+ if (!IsUpdating())
+ {
+ if (Controller().Is() && Controller()->IsModified())
+ {
+ if (!SaveModified())
+ return sal_False;
+ }
+ }
+ return sal_True;
+}
+
+//------------------------------------------------------------------------------
+void FmGridControl::inserted(const ::com::sun::star::lang::EventObject& /*rEvent*/)
+{
+ const DbGridRowRef& xRow = GetCurrentRow();
+ if (!xRow.Is())
+ return;
+
+ // Zeile ist eingefuegt worden, dann den status und mode zuruecksetzen
+ xRow->SetState(m_pDataCursor, sal_False);
+ xRow->SetNew(sal_False);
+
+}
+
+// XCancelUpdateRecordListener
+//------------------------------------------------------------------------------
+void FmGridControl::restored(const ::com::sun::star::lang::EventObject& rEvent)
+{
+ if (!GetCurrentRow().Is())
+ return;
+
+ sal_Bool bAppending = GetCurrentRow()->IsNew();
+ sal_Bool bDirty = GetCurrentRow()->IsModified();
+ if (bAppending && (EditBrowseBox::IsModified() || bDirty))
+ {
+ if (Controller().Is())
+ Controller()->ClearModified();
+
+ // jetzt die Zeile herausnehmen
+ RowRemoved(GetRowCount() - 1, 1, sal_True);
+ GetNavigationBar().InvalidateAll();
+ }
+
+ positioned(rEvent);
+}
+
+//------------------------------------------------------------------------------
+BrowserHeader* FmGridControl::imp_CreateHeaderBar(BrowseBox* pParent)
+{
+ DBG_ASSERT( pParent == this, "FmGridControl::imp_CreateHeaderBar: parent?" );
+ return new FmGridHeader( pParent );
+}
+
+//------------------------------------------------------------------------------
+void FmGridControl::markColumn(sal_uInt16 nId)
+{
+ if (GetHeaderBar() && m_nMarkedColumnId != nId)
+ {
+ // deselektieren
+ if (m_nMarkedColumnId != BROWSER_INVALIDID)
+ {
+ HeaderBarItemBits aBits = GetHeaderBar()->GetItemBits(m_nMarkedColumnId) & ~HIB_FLAT;
+ GetHeaderBar()->SetItemBits(m_nMarkedColumnId, aBits);
+ }
+
+
+ if (nId != BROWSER_INVALIDID)
+ {
+ HeaderBarItemBits aBits = GetHeaderBar()->GetItemBits(nId) | HIB_FLAT;
+ GetHeaderBar()->SetItemBits(nId, aBits);
+ }
+ m_nMarkedColumnId = nId;
+ }
+}
+
+//------------------------------------------------------------------------------
+sal_Bool FmGridControl::isColumnMarked(sal_uInt16 nId) const
+{
+ return m_nMarkedColumnId == nId;
+}
+
+//------------------------------------------------------------------------------
+long FmGridControl::QueryMinimumRowHeight()
+{
+ long nMinimalLogicHeight = 20; // 0.2 cm
+ long nMinimalPixelHeight = LogicToPixel( Point( 0, nMinimalLogicHeight ), MAP_10TH_MM ).Y();
+ return CalcZoom( nMinimalPixelHeight );
+}
+
+//------------------------------------------------------------------------------
+void FmGridControl::RowHeightChanged()
+{
+ DbGridControl::RowHeightChanged();
+
+ Reference< XPropertySet > xModel( GetPeer()->getColumns(), UNO_QUERY );
+ DBG_ASSERT( xModel.is(), "FmGridControl::RowHeightChanged: no model!" );
+ if ( xModel.is() )
+ {
+ try
+ {
+ sal_Int32 nUnzoomedPixelHeight = CalcReverseZoom( GetDataRowHeight() );
+ Any aProperty = makeAny( (sal_Int32)PixelToLogic( Point( 0, nUnzoomedPixelHeight ), MAP_10TH_MM ).Y() );
+ xModel->setPropertyValue( FM_PROP_ROWHEIGHT, aProperty );
+ }
+ catch( const Exception& )
+ {
+ OSL_ENSURE( sal_False, "FmGridControl::RowHeightChanged: caught an exception!" );
+ }
+ }
+}
+
+//------------------------------------------------------------------------------
+void FmGridControl::ColumnResized(sal_uInt16 nId)
+{
+ DbGridControl::ColumnResized(nId);
+
+ // Wert ans model uebergeben
+ DbGridColumn* pCol = DbGridControl::GetColumns().GetObject(GetModelColumnPos(nId));
+ Reference< ::com::sun::star::beans::XPropertySet > xColModel(pCol->getModel());
+ if (xColModel.is())
+ {
+ Any aWidth;
+ sal_Int32 nColumnWidth = GetColumnWidth(nId);
+ nColumnWidth = CalcReverseZoom(nColumnWidth);
+ // Umrechnen in 10THMM
+ aWidth <<= (sal_Int32)PixelToLogic(Point(nColumnWidth,0),MAP_10TH_MM).X();
+ xColModel->setPropertyValue(FM_PROP_WIDTH, aWidth);
+ }
+}
+
+//------------------------------------------------------------------------------
+void FmGridControl::CellModified()
+{
+ DbGridControl::CellModified();
+ GetPeer()->CellModified();
+}
+
+//------------------------------------------------------------------------------
+void FmGridControl::BeginCursorAction()
+{
+ DbGridControl::BeginCursorAction();
+ m_pPeer->stopCursorListening();
+}
+
+//------------------------------------------------------------------------------
+void FmGridControl::EndCursorAction()
+{
+ m_pPeer->startCursorListening();
+ DbGridControl::EndCursorAction();
+}
+
+//------------------------------------------------------------------------------
+void FmGridControl::ColumnMoved(sal_uInt16 nId)
+{
+ m_bInColumnMove = sal_True;
+
+ DbGridControl::ColumnMoved(nId);
+ Reference< ::com::sun::star::container::XIndexContainer > xColumns(GetPeer()->getColumns());
+
+ if (xColumns.is())
+ {
+ // suchen der Spalte und verschieben im Model
+ // ColumnPos holen
+ DbGridColumn* pCol = DbGridControl::GetColumns().GetObject(GetModelColumnPos(nId));
+ Reference< ::com::sun::star::beans::XPropertySet > xCol;
+
+ // Einfuegen muß sich an den Column Positionen orientieren
+ sal_Int32 i;
+ Reference< XInterface > xCurrent;
+ for (i = 0; !xCol.is() && i < xColumns->getCount(); i++)
+ {
+ ::cppu::extractInterface(xCurrent, xColumns->getByIndex(i));
+ if (xCurrent == pCol->getModel())
+ {
+ xCol = pCol->getModel();
+ break;
+ }
+ }
+
+ DBG_ASSERT(i < xColumns->getCount(), "Falscher ::com::sun::star::sdbcx::Index");
+ xColumns->removeByIndex(i);
+ Any aElement;
+ aElement <<= xCol;
+ xColumns->insertByIndex(GetModelColumnPos(nId), aElement);
+ pCol->setModel(xCol);
+ // if the column which is shown here is selected ...
+ if ( isColumnSelected(nId,pCol) )
+ markColumn(nId); // ... -> mark it
+ }
+
+ m_bInColumnMove = sal_False;
+}
+
+//------------------------------------------------------------------------------
+void FmGridControl::InitColumnsByModels(const Reference< ::com::sun::star::container::XIndexContainer >& xColumns)
+{
+ // Spalten wieder neu setzen
+ // wenn es nur eine HandleColumn gibt, dann nicht
+ if (GetModelColCount())
+ {
+ RemoveColumns();
+ InsertHandleColumn();
+ }
+
+ if (!xColumns.is())
+ return;
+
+ SetUpdateMode(sal_False);
+
+ // Einfuegen mu� sich an den Column Positionen orientieren
+ sal_Int32 i;
+ String aName;
+ Any aWidth;
+ for (i = 0; i < xColumns->getCount(); ++i)
+ {
+ Reference< ::com::sun::star::beans::XPropertySet > xCol;
+ ::cppu::extractInterface(xCol, xColumns->getByIndex(i));
+
+ aName = (const sal_Unicode*)::comphelper::getString(xCol->getPropertyValue(FM_PROP_LABEL));
+
+ aWidth = xCol->getPropertyValue(FM_PROP_WIDTH);
+ sal_Int32 nWidth = 0;
+ if (aWidth >>= nWidth)
+ nWidth = LogicToPixel(Point(nWidth,0),MAP_10TH_MM).X();
+
+ AppendColumn(aName, (sal_uInt16)nWidth);
+ DbGridColumn* pCol = DbGridControl::GetColumns().GetObject(i);
+ pCol->setModel(xCol);
+ }
+
+ // und jetzt noch die hidden columns rausnehmen
+ // (wir haben das nicht gleich in der oberen Schleife gemacht, da wir dann Probleme mit den
+ // IDs der Spalten bekommen haetten : AppendColumn vergibt die automatisch, die Spalte _nach_
+ // einer versteckten braucht aber eine um eine erhoehte ID ....
+ Any aHidden;
+ for (i = 0; i < xColumns->getCount(); ++i)
+ {
+ Reference< ::com::sun::star::beans::XPropertySet > xCol;
+ ::cppu::extractInterface(xCol, xColumns->getByIndex(i));
+ aHidden = xCol->getPropertyValue(FM_PROP_HIDDEN);
+ if (::comphelper::getBOOL(aHidden))
+ HideColumn(GetColumnIdFromModelPos((sal_uInt16)i));
+ }
+
+ SetUpdateMode(sal_True);
+}
+
+//------------------------------------------------------------------------------
+void FmGridControl::InitColumnByField(
+ DbGridColumn* _pColumn, const Reference< XPropertySet >& _rxColumnModel,
+ const Reference< XNameAccess >& _rxFieldsByNames, const Reference< XIndexAccess >& _rxFieldsByIndex )
+{
+ DBG_ASSERT( _rxFieldsByNames == _rxFieldsByIndex, "FmGridControl::InitColumnByField: invalid container interfaces!" );
+
+ // lookup the column which belongs to the control source
+ ::rtl::OUString sFieldName;
+ _rxColumnModel->getPropertyValue( FM_PROP_CONTROLSOURCE ) >>= sFieldName;
+ Reference< XPropertySet > xField;
+ _rxColumnModel->getPropertyValue( FM_PROP_BOUNDFIELD ) >>= xField;
+
+
+ if ( !xField.is() && /*sFieldName.getLength() && */_rxFieldsByNames->hasByName( sFieldName ) ) // #i93452# do not check for name length
+ _rxFieldsByNames->getByName( sFieldName ) >>= xField;
+
+ // determine the position of this column
+ sal_Int32 nFieldPos = -1;
+ if ( xField.is() )
+ {
+ Reference< XPropertySet > xCheck;
+ sal_Int32 nFieldCount = _rxFieldsByIndex->getCount();
+ for ( sal_Int32 i = 0; i < nFieldCount; ++i)
+ {
+ _rxFieldsByIndex->getByIndex( i ) >>= xCheck;
+ if ( xField.get() == xCheck.get() )
+ {
+ nFieldPos = i;
+ break;
+ }
+ }
+ }
+
+ if ( xField.is() && ( nFieldPos >= 0 ) )
+ {
+ // some data types are not allowed
+ sal_Int32 nDataType = DataType::OTHER;
+ xField->getPropertyValue( FM_PROP_FIELDTYPE ) >>= nDataType;
+
+ sal_Bool bIllegalType = sal_False;
+ switch ( nDataType )
+ {
+ case DataType::BLOB:
+ case DataType::LONGVARBINARY:
+ case DataType::BINARY:
+ case DataType::VARBINARY:
+ case DataType::OTHER:
+ bIllegalType = sal_True;
+ break;
+ }
+
+ if ( bIllegalType )
+ {
+ _pColumn->SetObject( (sal_Int16)nFieldPos );
+ return;
+ }
+/*
+ // handle readonly columns
+ sal_Bool bReadOnly = sal_True;
+ xField->getPropertyValue( FM_PROP_ISREADONLY ) >>= bReadOnly;
+ _pColumn->SetReadOnly( bReadOnly );
+*/
+ }
+
+ // the control type is determined by the ColumnServiceName
+ static ::rtl::OUString s_sPropColumnServiceName( RTL_CONSTASCII_USTRINGPARAM( "ColumnServiceName" ) );
+ if ( !::comphelper::hasProperty( s_sPropColumnServiceName, _rxColumnModel ) )
+ return;
+
+ _pColumn->setModel( _rxColumnModel );
+
+ ::rtl::OUString sColumnServiceName;
+ _rxColumnModel->getPropertyValue( s_sPropColumnServiceName ) >>= sColumnServiceName;
+
+ sal_Int32 nTypeId = getColumnTypeByModelName( sColumnServiceName );
+ _pColumn->CreateControl( nFieldPos, xField, nTypeId );
+}
+
+//------------------------------------------------------------------------------
+void FmGridControl::InitColumnsByFields(const Reference< ::com::sun::star::container::XIndexAccess >& _rxFields)
+{
+ if ( !_rxFields.is() )
+ return;
+
+ // Spalten initialisieren
+ Reference< XIndexContainer > xColumns( GetPeer()->getColumns() );
+ Reference< XNameAccess > xFieldsAsNames( _rxFields, UNO_QUERY );
+
+ // Einfuegen muss sich an den Column Positionen orientieren
+ for (sal_Int32 i = 0; i < xColumns->getCount(); i++)
+ {
+ DbGridColumn* pCol = GetColumns().GetObject(i);
+ OSL_ENSURE(pCol,"No grid column!");
+ if ( pCol )
+ {
+ Reference< XPropertySet > xColumnModel;
+ ::cppu::extractInterface( xColumnModel, xColumns->getByIndex( i ) );
+
+ InitColumnByField( pCol, xColumnModel, xFieldsAsNames, _rxFields );
+ }
+ }
+}
+
+//------------------------------------------------------------------------------
+void FmGridControl::HideColumn(sal_uInt16 nId)
+{
+ DbGridControl::HideColumn(nId);
+
+ sal_uInt16 nPos = GetModelColumnPos(nId);
+ if (nPos == (sal_uInt16)-1)
+ return;
+
+ DbGridColumn* pColumn = GetColumns().GetObject(nPos);
+ if (pColumn->IsHidden())
+ GetPeer()->columnHidden(pColumn);
+
+ if (nId == m_nMarkedColumnId)
+ m_nMarkedColumnId = (sal_uInt16)-1;
+}
+// -----------------------------------------------------------------------------
+sal_Bool FmGridControl::isColumnSelected(sal_uInt16 /*nId*/,DbGridColumn* _pColumn)
+{
+ OSL_ENSURE(_pColumn,"Column can not be null!");
+ sal_Bool bSelected = sal_False;
+ // if the column which is shown here is selected ...
+ Reference< ::com::sun::star::view::XSelectionSupplier > xSelSupplier(GetPeer()->getColumns(), UNO_QUERY);
+ if ( xSelSupplier.is() )
+ {
+ Reference< ::com::sun::star::beans::XPropertySet > xColumn;
+ xSelSupplier->getSelection() >>= xColumn;
+ bSelected = (xColumn.get() == _pColumn->getModel().get());
+ }
+ return bSelected;
+}
+
+//------------------------------------------------------------------------------
+void FmGridControl::ShowColumn(sal_uInt16 nId)
+{
+ DbGridControl::ShowColumn(nId);
+
+ sal_uInt16 nPos = GetModelColumnPos(nId);
+ if (nPos == (sal_uInt16)-1)
+ return;
+
+ DbGridColumn* pColumn = GetColumns().GetObject(nPos);
+ if (!pColumn->IsHidden())
+ GetPeer()->columnVisible(pColumn);
+
+ // if the column which is shown here is selected ...
+ if ( isColumnSelected(nId,pColumn) )
+ markColumn(nId); // ... -> mark it
+}
+
+//------------------------------------------------------------------------------
+sal_Bool FmGridControl::selectBookmarks(const Sequence< Any >& _rBookmarks)
+{
+ vos::OGuard aGuard( Application::GetSolarMutex() );
+ // need to lock the SolarMutex so that no paint call disturbs us ...
+
+ if ( !m_pSeekCursor )
+ {
+ DBG_ERROR( "FmGridControl::selectBookmarks: no seek cursor!" );
+ return sal_False;
+ }
+
+ const Any* pBookmark = _rBookmarks.getConstArray();
+ const Any* pBookmarkEnd = pBookmark + _rBookmarks.getLength();
+
+ SetNoSelection();
+
+ sal_Bool bAllSuccessfull = sal_True;
+ try
+ {
+ for (; pBookmark != pBookmarkEnd; ++pBookmark)
+ {
+ // move the seek cursor to the row given
+ if (m_pSeekCursor->moveToBookmark(*pBookmark))
+ SelectRow( m_pSeekCursor->getRow() - 1);
+ else
+ bAllSuccessfull = sal_False;
+ }
+ }
+ catch(Exception&)
+ {
+ DBG_ERROR("FmGridControl::selectBookmarks: could not move to one of the bookmarks!");
+ return sal_False;
+ }
+
+ return bAllSuccessfull;
+}
+
+//------------------------------------------------------------------------------
+Sequence< Any> FmGridControl::getSelectionBookmarks()
+{
+ // lock our update so no paint-triggered seeks interfere ...
+ SetUpdateMode(sal_False);
+
+ sal_Int32 nSelectedRows = GetSelectRowCount(), i = 0;
+ Sequence< Any> aBookmarks(nSelectedRows);
+ if ( nSelectedRows )
+ {
+ Any* pBookmarks = (Any*)aBookmarks.getArray();
+
+ // (I'm not sure if the problem isn't deeper : The szenario : a large table displayed by a grid with a
+ // thread-safe cursor (dBase). On loading the sdb-cursor started a counting thread. While this counting progress
+ // was running, I tried do delete 3 records from within the grid. Deletion caused a SeekCursor, which did a
+ // m_pSeekCursor->moveRelative and a m_pSeekCursor->getPosition.
+ // Unfortunally the first call caused a propertyChanged(RECORDCOUNT) which resulted in a repaint of the
+ // navigation bar and the grid. The latter itself will result in SeekRow calls. So after (successfully) returning
+ // from the moveRelative the getPosition returns an invalid value. And so the SeekCursor fails.
+ // In the consequence ALL parts of code where two calls to the seek cursor are done, while the second call _relys_ on
+ // the first one, should be secured against recursion, with a broad-minded interpretion of "recursion" : if any of these
+ // code parts is executed, no other should be accessible. But this sounds very difficult to achieve ....
+ // )
+
+ // The next problem caused by the same behaviuor (SeekCursor causes a propertyChanged) : when adjusting rows we implicitly
+ // change our selection. So a "FirstSelected(); SeekCursor(); NextSelected();" may produce unpredictable results.
+ // That's why we _first_ collect the indicies of the selected rows and _then_ their bookmarks.
+ long nIdx = FirstSelectedRow();
+ while (nIdx >= 0)
+ {
+ // (we misuse the bookmarks array for this ...)
+ pBookmarks[i++] <<= (sal_Int32)nIdx;
+ nIdx = NextSelectedRow();
+ }
+ DBG_ASSERT(i == nSelectedRows, "FmGridControl::DeleteSelectedRows : could not collect the row indicies !");
+
+ for (i=0; i<nSelectedRows; ++i)
+ {
+ nIdx = ::comphelper::getINT32(pBookmarks[i]);
+ if (IsInsertionRow(nIdx))
+ {
+ // leerzeile nicht loeschen
+ aBookmarks.realloc(--nSelectedRows);
+ SelectRow(nIdx,sal_False); // selection aufheben fuer leerzeile
+ break;
+ }
+
+ // Zunaechst den DatenCursor auf den selektierten Satz pos.
+ if (SeekCursor(nIdx))
+ {
+ GetSeekRow()->SetState(m_pSeekCursor, sal_True);
+
+ pBookmarks[i] = m_pSeekCursor->getBookmark();
+ }
+ #ifdef DBG_UTIL
+ else
+ DBG_ERROR("FmGridControl::DeleteSelectedRows : a bookmark could not be determined !");
+ #endif
+ }
+ }
+ SetUpdateMode(sal_True);
+
+ // if one of the SeekCursor-calls failed ....
+ aBookmarks.realloc(i);
+
+ // (the alternative : while collecting the bookmarks lock our propertyChanged, this should resolve both our problems.
+ // but this would be incompatible as we need a locking flag, then ...)
+
+ return aBookmarks;
+}
+// -----------------------------------------------------------------------------
+namespace
+{
+ ::rtl::OUString getColumnPropertyFromPeer(FmXGridPeer* _pPeer,sal_Int32 _nPosition,const ::rtl::OUString& _sPropName)
+ {
+ ::rtl::OUString sRetText;
+ if ( _pPeer && _nPosition != -1)
+ {
+ Reference<XIndexContainer> xIndex = _pPeer->getColumns();
+ if ( xIndex.is() && xIndex->getCount() > _nPosition )
+ {
+ Reference<XPropertySet> xProp;
+ xIndex->getByIndex( _nPosition ) >>= xProp;
+ if ( xProp.is() )
+ xProp->getPropertyValue( _sPropName ) >>= sRetText;
+ }
+ }
+ return sRetText;
+ }
+}
+// Object data and state ------------------------------------------------------
+::rtl::OUString FmGridControl::GetAccessibleObjectName( ::svt::AccessibleBrowseBoxObjType _eObjType,sal_Int32 _nPosition ) const
+{
+ ::rtl::OUString sRetText;
+ switch( _eObjType )
+ {
+ case ::svt::BBTYPE_BROWSEBOX:
+ if ( GetPeer() )
+ {
+ Reference<XPropertySet> xProp(GetPeer()->getColumns(),UNO_QUERY);
+ if ( xProp.is() )
+ xProp->getPropertyValue(FM_PROP_NAME) >>= sRetText;
+ }
+ break;
+ case ::svt::BBTYPE_COLUMNHEADERCELL:
+ sRetText = getColumnPropertyFromPeer(
+ GetPeer(),
+ GetModelColumnPos(
+ sal::static_int_cast< sal_uInt16 >(_nPosition)),
+ FM_PROP_LABEL);
+ break;
+ default:
+ sRetText = DbGridControl::GetAccessibleObjectName(_eObjType,_nPosition);
+ }
+ return sRetText;
+}
+// -----------------------------------------------------------------------------
+
+::rtl::OUString FmGridControl::GetAccessibleObjectDescription( ::svt::AccessibleBrowseBoxObjType _eObjType,sal_Int32 _nPosition ) const
+{
+ ::rtl::OUString sRetText;
+ switch( _eObjType )
+ {
+ case ::svt::BBTYPE_BROWSEBOX:
+ if ( GetPeer() )
+ {
+ Reference<XPropertySet> xProp(GetPeer()->getColumns(),UNO_QUERY);
+ if ( xProp.is() )
+ {
+ xProp->getPropertyValue(FM_PROP_HELPTEXT) >>= sRetText;
+ if ( !sRetText.getLength() )
+ xProp->getPropertyValue(FM_PROP_DESCRIPTION) >>= sRetText;
+ }
+ }
+ break;
+ case ::svt::BBTYPE_COLUMNHEADERCELL:
+ sRetText = getColumnPropertyFromPeer(
+ GetPeer(),
+ GetModelColumnPos(
+ sal::static_int_cast< sal_uInt16 >(_nPosition)),
+ FM_PROP_HELPTEXT);
+ if ( !sRetText.getLength() )
+ sRetText = getColumnPropertyFromPeer(
+ GetPeer(),
+ GetModelColumnPos(
+ sal::static_int_cast< sal_uInt16 >(_nPosition)),
+ FM_PROP_DESCRIPTION);
+
+ break;
+ default:
+ sRetText = DbGridControl::GetAccessibleObjectDescription(_eObjType,_nPosition);
+ }
+ return sRetText;
+}
+// -----------------------------------------------------------------------------
+void FmGridControl::Select()
+{
+ DbGridControl::Select();
+ // ... betrifft das unsere Spalten ?
+ const MultiSelection* pColumnSelection = GetColumnSelection();
+
+ sal_uInt16 nSelectedColumn =
+ pColumnSelection && pColumnSelection->GetSelectCount()
+ ? sal::static_int_cast< sal_uInt16 >(
+ ((MultiSelection*)pColumnSelection)->FirstSelected())
+ : SAL_MAX_UINT16;
+ // die HandleColumn wird nicht selektiert
+ switch (nSelectedColumn)
+ {
+ case SAL_MAX_UINT16: break; // no selection
+ case 0 : nSelectedColumn = SAL_MAX_UINT16; break;
+ // handle col can't be seledted
+ default :
+ // get the model col pos instead of the view col pos
+ nSelectedColumn = GetModelColumnPos(GetColumnIdFromViewPos(nSelectedColumn - 1));
+ break;
+ }
+
+ if (nSelectedColumn != m_nCurrentSelectedColumn)
+ {
+ // VOR dem Aufruf des select am SelectionSupplier !
+ m_nCurrentSelectedColumn = nSelectedColumn;
+
+ if (!m_bSelecting)
+ {
+ m_bSelecting = sal_True;
+
+ try
+ {
+ Reference< XIndexAccess > xColumns(GetPeer()->getColumns(), UNO_QUERY);
+ Reference< XSelectionSupplier > xSelSupplier(xColumns, UNO_QUERY);
+ if (xSelSupplier.is())
+ {
+ if (nSelectedColumn != SAL_MAX_UINT16)
+ {
+ Reference< XPropertySet > xColumn;
+ ::cppu::extractInterface(xColumn,xColumns->getByIndex(nSelectedColumn));
+ xSelSupplier->select(makeAny(xColumn));
+ }
+ else
+ {
+ xSelSupplier->select(Any());
+ }
+ }
+ }
+ catch(Exception&)
+ {
+ }
+
+
+ m_bSelecting = sal_False;
+ }
+ }
+}
+// -----------------------------------------------------------------------------
+sal_Int32 FmGridControl::GetSelectedColumn() const
+{
+ return m_nCurrentSelectedColumn;
+}
+// -----------------------------------------------------------------------------
+void FmGridControl::KeyInput( const KeyEvent& rKEvt )
+{
+ sal_Bool bDone = sal_False;
+ const KeyCode& rKeyCode = rKEvt.GetKeyCode();
+ if ( IsDesignMode()
+ && !rKeyCode.IsShift()
+ && !rKeyCode.IsMod1()
+ && !rKeyCode.IsMod2()
+ && GetParent() )
+ {
+ switch ( rKeyCode.GetCode() )
+ {
+ case KEY_ESCAPE:
+ GetParent()->GrabFocus();
+ bDone = sal_True;
+ break;
+ case KEY_DELETE:
+ if ( GetSelectColumnCount() && GetPeer() && m_nCurrentSelectedColumn >= 0 )
+ {
+ Reference< ::com::sun::star::container::XIndexContainer > xCols(GetPeer()->getColumns());
+ if ( xCols.is() )
+ {
+ try
+ {
+ if ( m_nCurrentSelectedColumn < xCols->getCount() )
+ {
+ Reference< XInterface > xCol;
+ xCols->getByIndex(m_nCurrentSelectedColumn) >>= xCol;
+ xCols->removeByIndex(m_nCurrentSelectedColumn);
+ ::comphelper::disposeComponent(xCol);
+ }
+ }
+ catch(const Exception&)
+ {
+ OSL_ENSURE(0,"exception occured while deleting a column");
+ }
+ }
+ }
+ bDone = sal_True;
+ break;
+ }
+ }
+ if ( !bDone )
+ DbGridControl::KeyInput( rKEvt );
+}
+// -----------------------------------------------------------------------------
+
+
+