LCOV - code coverage report
Current view: top level - libreoffice/svx/source/fmcomp - gridctrl.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 0 1717 0.0 %
Date: 2012-12-27 Functions: 0 140 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : 
      21             : #include <sal/macros.h>
      22             : #include "fmhelp.hrc"
      23             : #include <svx/gridctrl.hxx>
      24             : #include "gridcell.hxx"
      25             : #include "svx/dbtoolsclient.hxx"
      26             : #include "svx/fmtools.hxx"
      27             : #include <svtools/stringtransfer.hxx>
      28             : 
      29             : #include "fmprop.hrc"
      30             : #include <com/sun/star/sdbc/ResultSetConcurrency.hpp>
      31             : #include <com/sun/star/accessibility/XAccessible.hpp>
      32             : #include <com/sun/star/sdb/XResultSetAccess.hpp>
      33             : #include <com/sun/star/sdb/RowChangeAction.hpp>
      34             : #include <com/sun/star/sdb/XRowsChangeBroadcaster.hpp>
      35             : #include <com/sun/star/sdbc/XResultSetUpdate.hpp>
      36             : #include <com/sun/star/sdbcx/Privilege.hpp>
      37             : #include <com/sun/star/container/XChild.hpp>
      38             : #include <com/sun/star/util/NumberFormatter.hpp>
      39             : #include <com/sun/star/util/XNumberFormatsSupplier.hpp>
      40             : #include <com/sun/star/util/XCloneable.hpp>
      41             : #include <com/sun/star/beans/XPropertySet.hpp>
      42             : #include <com/sun/star/beans/PropertyChangeEvent.hpp>
      43             : #include <comphelper/extract.hxx>
      44             : #include <comphelper/processfactory.hxx>
      45             : #include <tools/resid.hxx>
      46             : #include <tools/diagnose_ex.h>
      47             : #include <vcl/menu.hxx>
      48             : 
      49             : #include "svx/fmresids.hrc"
      50             : 
      51             : #include <svx/svxids.hrc>
      52             : #include <tools/shl.hxx>
      53             : #include <svx/dialmgr.hxx>
      54             : #include "fmservs.hxx"
      55             : #include "sdbdatacolumn.hxx"
      56             : 
      57             : #include <comphelper/stl_types.hxx>
      58             : #include <comphelper/property.hxx>
      59             : #include "trace.hxx"
      60             : 
      61             : #include <algorithm>
      62             : 
      63             : using namespace ::svxform;
      64             : using namespace ::svt;
      65             : using namespace ::com::sun::star::beans;
      66             : using namespace ::com::sun::star::lang;
      67             : using namespace ::com::sun::star::uno;
      68             : using namespace ::com::sun::star::sdbc;
      69             : using namespace ::com::sun::star::sdbcx;
      70             : using namespace ::com::sun::star::sdb;
      71             : using namespace ::com::sun::star::datatransfer;
      72             : using namespace ::com::sun::star::container;
      73             : using namespace com::sun::star::accessibility;
      74             : 
      75             : #define ROWSTATUS(row)  !row.Is() ? "NULL" : row->GetStatus() == GRS_CLEAN ? "CLEAN" : row->GetStatus() == GRS_MODIFIED ? "MODIFIED" : row->GetStatus() == GRS_DELETED ? "DELETED" : "INVALID"
      76             : 
      77             : 
      78             : #define DEFAULT_BROWSE_MODE             \
      79             :               BROWSER_COLUMNSELECTION   \
      80             :             | BROWSER_MULTISELECTION    \
      81             :             | BROWSER_KEEPSELECTION     \
      82             :             | BROWSER_TRACKING_TIPS     \
      83             :             | BROWSER_HLINESFULL        \
      84             :             | BROWSER_VLINESFULL        \
      85             :             | BROWSER_HEADERBAR_NEW     \
      86             : 
      87           0 : class RowSetEventListener : public ::cppu::WeakImplHelper1<XRowsChangeListener>
      88             : {
      89             :     DbGridControl* m_pControl;
      90             : public:
      91           0 :     RowSetEventListener(DbGridControl* i_pControl) : m_pControl(i_pControl)
      92             :     {
      93           0 :     }
      94             : private:
      95             :     // XEventListener
      96           0 :     virtual void SAL_CALL disposing(const ::com::sun::star::lang::EventObject& /*i_aEvt*/) throw ( RuntimeException )
      97             :     {
      98           0 :     }
      99           0 :     virtual void SAL_CALL rowsChanged(const ::com::sun::star::sdb::RowsChangeEvent& i_aEvt) throw ( RuntimeException )
     100             :     {
     101           0 :         if ( i_aEvt.Action == RowChangeAction::UPDATE )
     102             :         {
     103           0 :             ::DbGridControl::GrantControlAccess aAccess;
     104           0 :             CursorWrapper* pSeek = m_pControl->GetSeekCursor(aAccess);
     105           0 :             const DbGridRowRef& rSeekRow = m_pControl->GetSeekRow(aAccess);
     106           0 :             const Any* pIter = i_aEvt.Bookmarks.getConstArray();
     107           0 :             const Any* pEnd  = pIter + i_aEvt.Bookmarks.getLength();
     108           0 :             for(;pIter != pEnd;++pIter)
     109             :             {
     110           0 :                 pSeek->moveToBookmark(*pIter);
     111             :                 // get the data
     112           0 :                 rSeekRow->SetState(pSeek, sal_True);
     113           0 :                 sal_Int32 nSeekPos = pSeek->getRow() - 1;
     114           0 :                 m_pControl->SetSeekPos(nSeekPos,aAccess);
     115           0 :                 m_pControl->RowModified(nSeekPos);
     116             :             }
     117             :         }
     118           0 :     }
     119             : };
     120             : //==============================================================================
     121             : 
     122             : class GridFieldValueListener;
     123             : DECLARE_STL_MAP(sal_uInt16, GridFieldValueListener*, ::std::less<sal_uInt16>, ColumnFieldValueListeners);
     124             : 
     125             : //==============================================================================
     126             : 
     127             : DBG_NAME(GridFieldValueListener)
     128             : class GridFieldValueListener : protected ::comphelper::OPropertyChangeListener
     129             : {
     130             :     osl::Mutex                          m_aMutex;
     131             :     DbGridControl&                      m_rParent;
     132             :     ::comphelper::OPropertyChangeMultiplexer*   m_pRealListener;
     133             :     sal_uInt16                          m_nId;
     134             :     sal_Int16                           m_nSuspended;
     135             :     sal_Bool                            m_bDisposed : 1;
     136             : 
     137             : public:
     138             :     GridFieldValueListener(DbGridControl& _rParent, const Reference< XPropertySet >& xField, sal_uInt16 _nId);
     139             :     virtual ~GridFieldValueListener();
     140             : 
     141             :     virtual void _propertyChanged(const PropertyChangeEvent& evt) throw( RuntimeException );
     142             : 
     143           0 :     void suspend() { ++m_nSuspended; }
     144           0 :     void resume() { --m_nSuspended; }
     145             : 
     146             :     void dispose();
     147             : };
     148             : //------------------------------------------------------------------------------
     149           0 : GridFieldValueListener::GridFieldValueListener(DbGridControl& _rParent, const Reference< XPropertySet >& _rField, sal_uInt16 _nId)
     150             :     :OPropertyChangeListener(m_aMutex)
     151             :     ,m_rParent(_rParent)
     152             :     ,m_pRealListener(NULL)
     153             :     ,m_nId(_nId)
     154             :     ,m_nSuspended(0)
     155           0 :     ,m_bDisposed(sal_False)
     156             : {
     157             :     DBG_CTOR(GridFieldValueListener, NULL);
     158           0 :     if (_rField.is())
     159             :     {
     160           0 :         m_pRealListener = new ::comphelper::OPropertyChangeMultiplexer(this, _rField);
     161           0 :         m_pRealListener->addProperty(FM_PROP_VALUE);
     162           0 :         m_pRealListener->acquire();
     163             :     }
     164           0 : }
     165             : 
     166             : //------------------------------------------------------------------------------
     167           0 : GridFieldValueListener::~GridFieldValueListener()
     168             : {
     169             :     DBG_DTOR(GridFieldValueListener, NULL);
     170           0 :     dispose();
     171           0 : }
     172             : 
     173             : //------------------------------------------------------------------------------
     174           0 : void GridFieldValueListener::_propertyChanged(const PropertyChangeEvent& _evt) throw( RuntimeException )
     175             : {
     176             :     DBG_ASSERT(m_nSuspended>=0, "GridFieldValueListener::_propertyChanged : resume > suspend !");
     177           0 :     if (m_nSuspended <= 0)
     178           0 :         m_rParent.FieldValueChanged(m_nId, _evt);
     179           0 : }
     180             : 
     181             : //------------------------------------------------------------------------------
     182           0 : void GridFieldValueListener::dispose()
     183             : {
     184           0 :     if (m_bDisposed)
     185             :     {
     186             :         DBG_ASSERT(m_pRealListener == NULL, "GridFieldValueListener::dispose : inconsistent !");
     187           0 :         return;
     188             :     }
     189             : 
     190           0 :     if (m_pRealListener)
     191             :     {
     192           0 :         m_pRealListener->dispose();
     193           0 :         m_pRealListener->release();
     194           0 :         m_pRealListener = NULL;
     195             :     }
     196             : 
     197           0 :     m_bDisposed = sal_True;
     198           0 :     m_rParent.FieldListenerDisposing(m_nId);
     199             : }
     200             : 
     201             : //==============================================================================
     202             : 
     203             : class DisposeListenerGridBridge : public FmXDisposeListener
     204             : {
     205             :     osl::Mutex              m_aMutex;
     206             :     DbGridControl&          m_rParent;
     207             :     FmXDisposeMultiplexer*  m_pRealListener;
     208             : 
     209             : public:
     210             :     DisposeListenerGridBridge(  DbGridControl& _rParent, const Reference< XComponent >& _rxObject, sal_Int16 _rId = -1);
     211             :     virtual ~DisposeListenerGridBridge();
     212             : 
     213           0 :     virtual void disposing(const EventObject& _rEvent, sal_Int16 _nId) throw( RuntimeException ) { m_rParent.disposing(_nId, _rEvent); }
     214             : };
     215             : 
     216             : //==============================================================================
     217             : 
     218             : 
     219             : DBG_NAME(DisposeListenerGridBridge)
     220             : //------------------------------------------------------------------------------
     221           0 : DisposeListenerGridBridge::DisposeListenerGridBridge(DbGridControl& _rParent, const Reference< XComponent >& _rxObject, sal_Int16 _rId)
     222             :     :FmXDisposeListener(m_aMutex)
     223             :     ,m_rParent(_rParent)
     224           0 :     ,m_pRealListener(NULL)
     225             : {
     226             :     DBG_CTOR(DisposeListenerGridBridge,NULL);
     227             : 
     228           0 :     if (_rxObject.is())
     229             :     {
     230           0 :         m_pRealListener = new FmXDisposeMultiplexer(this, _rxObject, _rId);
     231           0 :         m_pRealListener->acquire();
     232             :     }
     233           0 : }
     234             : 
     235             : //------------------------------------------------------------------------------
     236           0 : DisposeListenerGridBridge::~DisposeListenerGridBridge()
     237             : {
     238           0 :     if (m_pRealListener)
     239             :     {
     240           0 :         m_pRealListener->dispose();
     241           0 :         m_pRealListener->release();
     242           0 :         m_pRealListener = NULL;
     243             :     }
     244             : 
     245             :     DBG_DTOR(DisposeListenerGridBridge,NULL);
     246           0 : }
     247             : 
     248             : //==============================================================================
     249             : 
     250             : static sal_uInt16 ControlMap[] =
     251             :     {
     252             :         DbGridControl::NavigationBar::RECORD_TEXT,
     253             :         DbGridControl::NavigationBar::RECORD_ABSOLUTE,
     254             :         DbGridControl::NavigationBar::RECORD_OF,
     255             :         DbGridControl::NavigationBar::RECORD_COUNT,
     256             :         DbGridControl::NavigationBar::RECORD_FIRST,
     257             :         DbGridControl::NavigationBar::RECORD_NEXT,
     258             :         DbGridControl::NavigationBar::RECORD_PREV,
     259             :         DbGridControl::NavigationBar::RECORD_LAST,
     260             :         DbGridControl::NavigationBar::RECORD_NEW,
     261             :         0
     262             :     };
     263             : 
     264             : //------------------------------------------------------------------------------
     265           0 : sal_Bool CompareBookmark(const Any& aLeft, const Any& aRight)
     266             : {
     267           0 :     return ::comphelper::compare(aLeft, aRight);
     268             : }
     269             : 
     270             : //==============================================================================
     271           0 : class FmXGridSourcePropListener : public ::comphelper::OPropertyChangeListener
     272             : {
     273             :     DbGridControl* m_pParent;
     274             : 
     275             :     // a DbGridControl has no mutex, so we use our own as the base class expects one
     276             :     osl::Mutex      m_aMutex;
     277             :     sal_Int16           m_nSuspended;
     278             : 
     279             : public:
     280             :     FmXGridSourcePropListener(DbGridControl* _pParent);
     281             : 
     282           0 :     void suspend() { ++m_nSuspended; }
     283           0 :     void resume() { --m_nSuspended; }
     284             : 
     285             :     virtual void _propertyChanged(const PropertyChangeEvent& evt) throw( RuntimeException );
     286             : };
     287             : 
     288             : //------------------------------------------------------------------------------
     289           0 : FmXGridSourcePropListener::FmXGridSourcePropListener(DbGridControl* _pParent)
     290             :     :OPropertyChangeListener(m_aMutex)
     291             :     ,m_pParent(_pParent)
     292           0 :     ,m_nSuspended(0)
     293             : {
     294             :     DBG_ASSERT(m_pParent, "FmXGridSourcePropListener::FmXGridSourcePropListener : invalid parent !");
     295           0 : }
     296             : 
     297             : //------------------------------------------------------------------------------
     298           0 : void FmXGridSourcePropListener::_propertyChanged(const PropertyChangeEvent& evt) throw( RuntimeException )
     299             : {
     300             :     DBG_ASSERT(m_nSuspended>=0, "FmXGridSourcePropListener::_propertyChanged : resume > suspend !");
     301           0 :     if (m_nSuspended <= 0)
     302           0 :         m_pParent->DataSourcePropertyChanged(evt);
     303           0 : }
     304             : 
     305             : //==============================================================================
     306             : //------------------------------------------------------------------------------
     307           0 : DbGridControl::NavigationBar::AbsolutePos::AbsolutePos(Window* pParent, WinBits nStyle)
     308           0 :                    :NumericField(pParent, nStyle)
     309             : {
     310           0 :     SetMin(1);
     311           0 :     SetFirst(1);
     312           0 :     SetSpinSize(1);
     313             : 
     314           0 :     SetDecimalDigits(0);
     315           0 :     SetStrictFormat(sal_True);
     316           0 : }
     317             : 
     318             : //------------------------------------------------------------------------------
     319           0 : void DbGridControl::NavigationBar::AbsolutePos::KeyInput(const KeyEvent& rEvt)
     320             : {
     321           0 :     if (rEvt.GetKeyCode() == KEY_RETURN && GetText().Len())
     322             :     {
     323           0 :         sal_Int64 nRecord = GetValue();
     324           0 :         if (nRecord < GetMin() || nRecord > GetMax())
     325           0 :             return;
     326             :         else
     327           0 :             ((NavigationBar*)GetParent())->PositionDataSource(static_cast<sal_Int32>(nRecord));
     328             :     }
     329           0 :     else if (rEvt.GetKeyCode() == KEY_TAB)
     330           0 :         GetParent()->GetParent()->GrabFocus();
     331             :     else
     332           0 :         NumericField::KeyInput(rEvt);
     333             : }
     334             : 
     335             : //------------------------------------------------------------------------------
     336           0 : void DbGridControl::NavigationBar::AbsolutePos::LoseFocus()
     337             : {
     338           0 :     NumericField::LoseFocus();
     339           0 :     sal_Int64 nRecord = GetValue();
     340           0 :     if (nRecord < GetMin() || nRecord > GetMax())
     341           0 :         return;
     342             :     else
     343             :     {
     344           0 :         ((NavigationBar*)GetParent())->PositionDataSource(static_cast<sal_Int32>(nRecord));
     345           0 :         ((NavigationBar*)GetParent())->InvalidateState(NavigationBar::RECORD_ABSOLUTE);
     346             :     }
     347             : }
     348             : 
     349             : //------------------------------------------------------------------------------
     350           0 : void DbGridControl::NavigationBar::PositionDataSource(sal_Int32 nRecord)
     351             : {
     352           0 :     if (m_bPositioning)
     353           0 :         return;
     354             :     // the MoveToPosition may cause a LoseFocus which would lead to a second MoveToPosition, so protect agains this
     355             :     // recursion
     356             :     // 68167 - 13.08.99 - FS
     357           0 :     m_bPositioning = sal_True;
     358           0 :     ((DbGridControl*)GetParent())->MoveToPosition(nRecord - 1);
     359           0 :     m_bPositioning = sal_False;
     360             : }
     361             : 
     362             : //------------------------------------------------------------------------------
     363           0 : DbGridControl::NavigationBar::NavigationBar(Window* pParent, WinBits nStyle)
     364             :           :Control(pParent, nStyle)
     365             :           ,m_aRecordText(this, WB_VCENTER)
     366             :           ,m_aAbsolute(this, WB_CENTER | WB_VCENTER)
     367             :           ,m_aRecordOf(this, WB_VCENTER)
     368             :           ,m_aRecordCount(this, WB_VCENTER)
     369             :           ,m_aFirstBtn(this, WB_RECTSTYLE|WB_NOPOINTERFOCUS)
     370             :           ,m_aPrevBtn(this, WB_REPEAT|WB_RECTSTYLE|WB_NOPOINTERFOCUS)
     371             :           ,m_aNextBtn(this, WB_REPEAT|WB_RECTSTYLE|WB_NOPOINTERFOCUS)
     372             :           ,m_aLastBtn(this, WB_RECTSTYLE|WB_NOPOINTERFOCUS)
     373             :           ,m_aNewBtn(this, WB_RECTSTYLE|WB_NOPOINTERFOCUS)
     374             :           ,m_nDefaultWidth(0)
     375             :           ,m_nCurrentPos(-1)
     376           0 :           ,m_bPositioning(sal_False)
     377             : {
     378           0 :     m_aFirstBtn.SetSymbol(SYMBOL_FIRST);
     379           0 :     m_aPrevBtn.SetSymbol(SYMBOL_PREV);
     380           0 :     m_aNextBtn.SetSymbol(SYMBOL_NEXT);
     381           0 :     m_aLastBtn.SetSymbol(SYMBOL_LAST);
     382           0 :     m_aNewBtn.SetModeImage(((DbGridControl*)pParent)->GetImage(DbGridControl_Base::NEW));
     383             : 
     384           0 :     m_aFirstBtn.SetHelpId(HID_GRID_TRAVEL_FIRST);
     385           0 :     m_aPrevBtn.SetHelpId(HID_GRID_TRAVEL_PREV);
     386           0 :     m_aNextBtn.SetHelpId(HID_GRID_TRAVEL_NEXT);
     387           0 :     m_aLastBtn.SetHelpId(HID_GRID_TRAVEL_LAST);
     388           0 :     m_aNewBtn.SetHelpId(HID_GRID_TRAVEL_NEW);
     389           0 :     m_aAbsolute.SetHelpId(HID_GRID_TRAVEL_ABSOLUTE);
     390           0 :     m_aRecordCount.SetHelpId(HID_GRID_NUMBEROFRECORDS);
     391             : 
     392             :     // Handler fuer Buttons einrichten
     393           0 :     m_aFirstBtn.SetClickHdl(LINK(this,NavigationBar,OnClick));
     394           0 :     m_aPrevBtn.SetClickHdl(LINK(this,NavigationBar,OnClick));
     395           0 :     m_aNextBtn.SetClickHdl(LINK(this,NavigationBar,OnClick));
     396           0 :     m_aLastBtn.SetClickHdl(LINK(this,NavigationBar,OnClick));
     397           0 :     m_aNewBtn.SetClickHdl(LINK(this,NavigationBar,OnClick));
     398             : 
     399           0 :     m_aRecordText.SetText(XubString(SVX_RES(RID_STR_REC_TEXT)));
     400           0 :     m_aRecordOf.SetText(XubString(SVX_RES(RID_STR_REC_FROM_TEXT)));
     401           0 :     m_aRecordCount.SetText(rtl::OUString('?'));
     402             : 
     403           0 :     m_nDefaultWidth = ArrangeControls();
     404             : 
     405           0 :     m_aFirstBtn.Disable();
     406           0 :     m_aPrevBtn.Disable();
     407           0 :     m_aNextBtn.Disable();
     408           0 :     m_aLastBtn.Disable();
     409           0 :     m_aNewBtn.Disable();
     410           0 :     m_aRecordText.Disable();
     411           0 :     m_aRecordOf.Disable();
     412           0 :     m_aRecordCount.Disable();
     413           0 :     m_aAbsolute.Disable();
     414             : 
     415           0 :     AllSettings aSettings = m_aNextBtn.GetSettings();
     416           0 :     MouseSettings aMouseSettings = aSettings.GetMouseSettings();
     417           0 :     aMouseSettings.SetButtonRepeat(aMouseSettings.GetButtonRepeat() / 4);
     418           0 :     aSettings.SetMouseSettings(aMouseSettings);
     419           0 :     m_aNextBtn.SetSettings(aSettings, sal_True);
     420           0 :     m_aPrevBtn.SetSettings(aSettings, sal_True);
     421             : 
     422           0 :     m_aFirstBtn.Show();
     423           0 :     m_aPrevBtn.Show();
     424           0 :     m_aNextBtn.Show();
     425           0 :     m_aLastBtn.Show();
     426           0 :     m_aNewBtn.Show();
     427           0 :     m_aRecordText.Show();
     428           0 :     m_aRecordOf.Show();
     429           0 :     m_aRecordCount.Show();
     430           0 :     m_aAbsolute.Show();
     431           0 : }
     432             : 
     433             : namespace
     434             : {
     435           0 :     void SetPosAndSize(Button& _rButton,Point& _rPos,const Size& _rSize)
     436             :     {
     437           0 :         _rButton.SetPosPixel( _rPos );
     438           0 :         _rButton.SetSizePixel( _rSize );
     439           0 :         _rPos.X() += (sal_uInt16)_rSize.Width();
     440           0 :     }
     441             : }
     442             : //------------------------------------------------------------------------------
     443           0 : sal_uInt16 DbGridControl::NavigationBar::ArrangeControls()
     444             : {
     445             :     // Positionierung der Controls
     446             :     // Basisgroessen ermitteln
     447           0 :     Rectangle   aRect(((DbGridControl*)GetParent())->GetControlArea());
     448           0 :     const long  nH      = aRect.GetSize().Height();
     449           0 :     Size        aBorder = LogicToPixel(Size(2, 2),MAP_APPFONT);
     450           0 :     aBorder = Size(CalcZoom(aBorder.Width()), CalcZoom(aBorder.Height()));
     451           0 :     sal_uInt16      nX = 1;
     452           0 :     sal_uInt16      nY = 0;
     453             : 
     454             :     // Ist der Font des Edits groesser als das Feld?
     455           0 :     if (m_aAbsolute.GetTextHeight() > nH)
     456             :     {
     457           0 :         Font aApplFont (m_aAbsolute.GetFont());
     458           0 :         const Size pointAbsoluteSize(m_aAbsolute.PixelToLogic( Size( 0, nH - 2 ), MapMode(MAP_POINT) ));
     459           0 :         aApplFont.SetSize( pointAbsoluteSize );
     460           0 :         m_aAbsolute.SetControlFont( aApplFont );
     461             : 
     462           0 :         aApplFont.SetTransparent( sal_True );
     463           0 :         m_aRecordText.SetControlFont( aApplFont );
     464           0 :         m_aRecordOf.SetControlFont( aApplFont );
     465           0 :         m_aRecordCount.SetControlFont( aApplFont );
     466             :     }
     467             : 
     468             :     // Controls Groessen und Positionen setzen
     469             :     //
     470           0 :     XubString aText = m_aRecordText.GetText();
     471           0 :     long nTextWidth = m_aRecordText.GetTextWidth(aText);
     472           0 :     m_aRecordText.SetPosPixel(Point(nX,nY));
     473           0 :     m_aRecordText.SetSizePixel(Size(nTextWidth,nH));
     474           0 :     nX = sal::static_int_cast< sal_uInt16 >(nX + nTextWidth + aBorder.Width());
     475             : 
     476             :     // count an extra hairspace (U+200A) left and right
     477           0 :     const rtl::OUString sevenDigits(m_aAbsolute.CreateFieldText(6000000));
     478           0 :     const rtl::OUString hairSpace(static_cast<sal_Unicode>(0x200A));
     479           0 :     rtl::OUString textPattern(hairSpace);
     480           0 :     textPattern += sevenDigits;
     481           0 :     textPattern += hairSpace;
     482           0 :     nTextWidth = m_aAbsolute.GetTextWidth( textPattern );
     483           0 :     m_aAbsolute.SetPosPixel(Point(nX,nY));
     484           0 :     m_aAbsolute.SetSizePixel(Size(nTextWidth, nH));
     485           0 :     nX = sal::static_int_cast< sal_uInt16 >(nX + nTextWidth + aBorder.Width());
     486             : 
     487           0 :     aText      = m_aRecordOf.GetText();
     488           0 :     nTextWidth = m_aRecordOf.GetTextWidth(aText);
     489           0 :     m_aRecordOf.SetPosPixel(Point(nX,nY));
     490           0 :     m_aRecordOf.SetSizePixel(Size(nTextWidth,nH));
     491           0 :     nX = sal::static_int_cast< sal_uInt16 >(nX + nTextWidth + aBorder.Width());
     492             : 
     493           0 :     textPattern = sevenDigits + " * (" + sevenDigits + ")";
     494           0 :     nTextWidth = m_aRecordCount.GetTextWidth( textPattern );
     495           0 :     m_aRecordCount.SetPosPixel(Point(nX,nY));
     496           0 :     m_aRecordCount.SetSizePixel(Size(nTextWidth,nH));
     497           0 :     nX = sal::static_int_cast< sal_uInt16 >(nX + nTextWidth + aBorder.Width());
     498             : 
     499           0 :     Point aButtonPos(nX,nY);
     500           0 :     const Size  aButtonSize(nH,nH);
     501           0 :     SetPosAndSize(m_aFirstBtn, aButtonPos, aButtonSize);
     502           0 :     SetPosAndSize(m_aPrevBtn, aButtonPos, aButtonSize);
     503           0 :     SetPosAndSize(m_aNextBtn, aButtonPos, aButtonSize);
     504           0 :     SetPosAndSize(m_aLastBtn, aButtonPos, aButtonSize);
     505           0 :     SetPosAndSize(m_aNewBtn, aButtonPos, aButtonSize);
     506             : 
     507           0 :     nX = sal::static_int_cast< sal_uInt16 >(aButtonPos.X() + 1);
     508             : 
     509           0 :     return nX;
     510             : }
     511             : 
     512             : //------------------------------------------------------------------------------
     513           0 : IMPL_LINK(DbGridControl::NavigationBar, OnClick, Button *, pButton )
     514             : {
     515           0 :     DbGridControl* pParent = (DbGridControl*)GetParent();
     516             : 
     517           0 :     if (pParent->m_aMasterSlotExecutor.IsSet())
     518             :     {
     519           0 :         long lResult = 0;
     520           0 :         if (pButton == &m_aFirstBtn)
     521           0 :             lResult = pParent->m_aMasterSlotExecutor.Call((void*)RECORD_FIRST);
     522           0 :         else if( pButton == &m_aPrevBtn )
     523           0 :             lResult = pParent->m_aMasterSlotExecutor.Call((void*)RECORD_PREV);
     524           0 :         else if( pButton == &m_aNextBtn )
     525           0 :             lResult = pParent->m_aMasterSlotExecutor.Call((void*)RECORD_NEXT);
     526           0 :         else if( pButton == &m_aLastBtn )
     527           0 :             lResult = pParent->m_aMasterSlotExecutor.Call((void*)RECORD_LAST);
     528           0 :         else if( pButton == &m_aNewBtn )
     529           0 :             lResult = pParent->m_aMasterSlotExecutor.Call((void*)RECORD_NEW);
     530             : 
     531           0 :         if (lResult)
     532             :             // the link already handled it
     533           0 :             return 0;
     534             :     }
     535             : 
     536           0 :     if (pButton == &m_aFirstBtn)
     537           0 :         pParent->MoveToFirst();
     538           0 :     else if( pButton == &m_aPrevBtn )
     539           0 :         pParent->MoveToPrev();
     540           0 :     else if( pButton == &m_aNextBtn )
     541           0 :         pParent->MoveToNext();
     542           0 :     else if( pButton == &m_aLastBtn )
     543           0 :         pParent->MoveToLast();
     544           0 :     else if( pButton == &m_aNewBtn )
     545           0 :         pParent->AppendNew();
     546           0 :     return 0;
     547             : }
     548             : 
     549             : //------------------------------------------------------------------------------
     550           0 : void DbGridControl::NavigationBar::InvalidateAll(sal_Int32 nCurrentPos, sal_Bool bAll)
     551             : {
     552           0 :     if (m_nCurrentPos != nCurrentPos || nCurrentPos < 0 || bAll)
     553             :     {
     554           0 :         DbGridControl* pParent = (DbGridControl*)GetParent();
     555             : 
     556           0 :         sal_Int32 nAdjustedRowCount = pParent->GetRowCount() - ((pParent->GetOptions() & DbGridControl::OPT_INSERT) ? 2 : 1);
     557             : 
     558             :         // Wann muß alles invalidiert werden
     559           0 :         bAll = bAll || m_nCurrentPos <= 0;
     560           0 :         bAll = bAll || nCurrentPos <= 0;
     561           0 :         bAll = bAll || m_nCurrentPos >= nAdjustedRowCount;
     562           0 :         bAll = bAll || nCurrentPos >= nAdjustedRowCount;
     563             : 
     564           0 :         if ( bAll )
     565             :         {
     566           0 :             m_nCurrentPos = nCurrentPos;
     567           0 :             int i = 0;
     568           0 :             while (ControlMap[i])
     569           0 :                 SetState(ControlMap[i++]);
     570             :         }
     571             :         else    // befindet sich in der Mitte
     572             :         {
     573           0 :             m_nCurrentPos = nCurrentPos;
     574           0 :             SetState(NavigationBar::RECORD_COUNT);
     575           0 :             SetState(NavigationBar::RECORD_ABSOLUTE);
     576             :         }
     577             :     }
     578           0 : }
     579             : 
     580             : //------------------------------------------------------------------------------
     581           0 : sal_Bool DbGridControl::NavigationBar::GetState(sal_uInt16 nWhich) const
     582             : {
     583           0 :     DbGridControl* pParent = (DbGridControl*)GetParent();
     584             : 
     585           0 :     if (!pParent->IsOpen() || pParent->IsDesignMode() || !pParent->IsEnabled()
     586           0 :         || pParent->IsFilterMode() )
     587           0 :         return sal_False;
     588             :     else
     589             :     {
     590             :         // check if we have a master state provider
     591           0 :         if (pParent->m_aMasterStateProvider.IsSet())
     592             :         {
     593           0 :             long nState = pParent->m_aMasterStateProvider.Call(reinterpret_cast< void* >( nWhich ) );
     594           0 :             if (nState>=0)
     595           0 :                 return (nState>0);
     596             :         }
     597             : 
     598           0 :         sal_Bool bAvailable = sal_True;
     599             : 
     600           0 :         switch (nWhich)
     601             :         {
     602             :             case NavigationBar::RECORD_FIRST:
     603             :             case NavigationBar::RECORD_PREV:
     604           0 :                 bAvailable = m_nCurrentPos > 0;
     605           0 :                 break;
     606             :             case NavigationBar::RECORD_NEXT:
     607           0 :                 if(pParent->m_bRecordCountFinal)
     608             :                 {
     609           0 :                     bAvailable = m_nCurrentPos < pParent->GetRowCount() - 1;
     610           0 :                     if (!bAvailable && pParent->GetOptions() & DbGridControl::OPT_INSERT)
     611           0 :                         bAvailable = (m_nCurrentPos == pParent->GetRowCount() - 2) && pParent->IsModified();
     612             :                 }
     613           0 :                 break;
     614             :             case NavigationBar::RECORD_LAST:
     615           0 :                 if(pParent->m_bRecordCountFinal)
     616             :                 {
     617           0 :                     if (pParent->GetOptions() & DbGridControl::OPT_INSERT)
     618           0 :                         bAvailable = pParent->IsCurrentAppending() ? pParent->GetRowCount() > 1 :
     619           0 :                                      m_nCurrentPos != pParent->GetRowCount() - 2;
     620             :                     else
     621           0 :                         bAvailable = m_nCurrentPos != pParent->GetRowCount() - 1;
     622             :                 }
     623           0 :                 break;
     624             :             case NavigationBar::RECORD_NEW:
     625           0 :                 bAvailable = (pParent->GetOptions() & DbGridControl::OPT_INSERT) && pParent->GetRowCount() && m_nCurrentPos < pParent->GetRowCount() - 1;
     626           0 :                 break;
     627             :             case NavigationBar::RECORD_ABSOLUTE:
     628           0 :                 bAvailable = pParent->GetRowCount() > 0;
     629           0 :                 break;
     630             :         }
     631           0 :         return bAvailable;
     632             :     }
     633             : }
     634             : 
     635             : //------------------------------------------------------------------------------
     636           0 : void DbGridControl::NavigationBar::SetState(sal_uInt16 nWhich)
     637             : {
     638           0 :     sal_Bool bAvailable = GetState(nWhich);
     639           0 :     DbGridControl* pParent = (DbGridControl*)GetParent();
     640           0 :     Window* pWnd = NULL;
     641           0 :     switch (nWhich)
     642             :     {
     643             :         case NavigationBar::RECORD_FIRST:
     644           0 :             pWnd = &m_aFirstBtn;
     645           0 :             break;
     646             :         case NavigationBar::RECORD_PREV:
     647           0 :             pWnd = &m_aPrevBtn;
     648           0 :             break;
     649             :         case NavigationBar::RECORD_NEXT:
     650           0 :             pWnd = &m_aNextBtn;
     651           0 :             break;
     652             :         case NavigationBar::RECORD_LAST:
     653           0 :             pWnd = &m_aLastBtn;
     654           0 :             break;
     655             :         case NavigationBar::RECORD_NEW:
     656           0 :             pWnd = &m_aNewBtn;
     657           0 :             break;
     658             :         case NavigationBar::RECORD_ABSOLUTE:
     659           0 :             pWnd = &m_aAbsolute;
     660           0 :             if (bAvailable)
     661             :             {
     662           0 :                 if (pParent->m_nTotalCount >= 0)
     663             :                 {
     664           0 :                     if (pParent->IsCurrentAppending())
     665           0 :                         m_aAbsolute.SetMax(pParent->m_nTotalCount + 1);
     666             :                     else
     667           0 :                         m_aAbsolute.SetMax(pParent->m_nTotalCount);
     668             :                 }
     669             :                 else
     670           0 :                     m_aAbsolute.SetMax(LONG_MAX);
     671             : 
     672           0 :                 m_aAbsolute.SetValue(m_nCurrentPos + 1);
     673             :             }
     674             :             else
     675           0 :                 m_aAbsolute.SetText(String());
     676           0 :             break;
     677             :         case NavigationBar::RECORD_TEXT:
     678           0 :             pWnd = &m_aRecordText;
     679           0 :             break;
     680             :         case NavigationBar::RECORD_OF:
     681           0 :             pWnd = &m_aRecordOf;
     682           0 :             break;
     683             :         case NavigationBar::RECORD_COUNT:
     684             :         {
     685           0 :             pWnd = &m_aRecordCount;
     686           0 :             String aText;
     687           0 :             if (bAvailable)
     688             :             {
     689           0 :                 if (pParent->GetOptions() & DbGridControl::OPT_INSERT)
     690             :                 {
     691           0 :                     if (pParent->IsCurrentAppending() && !pParent->IsModified())
     692           0 :                         aText = m_aAbsolute.CreateFieldText(pParent->GetRowCount());
     693             :                     else
     694           0 :                         aText = m_aAbsolute.CreateFieldText(pParent->GetRowCount() - 1);
     695             :                 }
     696             :                 else
     697           0 :                     aText = m_aAbsolute.CreateFieldText(pParent->GetRowCount());
     698           0 :                 if(!pParent->m_bRecordCountFinal)
     699           0 :                     aText += rtl::OUString(" *");
     700             :             }
     701             :             else
     702           0 :                 aText = String();
     703             : 
     704             :             // add the number of selected rows, if applicable
     705           0 :             if (pParent->GetSelectRowCount())
     706             :             {
     707           0 :                 String aExtendedInfo(aText);
     708           0 :                 aExtendedInfo.AppendAscii(" (");
     709           0 :                 aExtendedInfo += m_aAbsolute.CreateFieldText(pParent->GetSelectRowCount());
     710           0 :                 aExtendedInfo += ')';
     711           0 :                 pWnd->SetText(aExtendedInfo);
     712             :             }
     713             :             else
     714           0 :                 pWnd->SetText(aText);
     715             : 
     716           0 :             pParent->SetRealRowCount(aText);
     717           0 :         }   break;
     718             :     }
     719             :     DBG_ASSERT(pWnd, "kein Fenster");
     720           0 :     if (pWnd && (pWnd->IsEnabled() != bAvailable))
     721             :         // this "pWnd->IsEnabled() != bAvailable" is a little hack : Window::Enable always generates a user
     722             :         // event (ImplGenerateMouseMove) even if nothing happened. This may lead to some unwanted effects, so we
     723             :         // do this check.
     724             :         // For further explanation see Bug 69900.
     725           0 :         pWnd->Enable(bAvailable);
     726           0 : }
     727             : 
     728             : //------------------------------------------------------------------------------
     729           0 : void DbGridControl::NavigationBar::Resize()
     730             : {
     731           0 :     Control::Resize();
     732           0 :     ArrangeControls();
     733           0 : }
     734             : 
     735             : //------------------------------------------------------------------------------
     736           0 : void DbGridControl::NavigationBar::Paint(const Rectangle& rRect)
     737             : {
     738           0 :     Control::Paint(rRect);
     739           0 :     Point aAbsolutePos = m_aAbsolute.GetPosPixel();
     740           0 :     Size  aAbsoluteSize = m_aAbsolute.GetSizePixel();
     741             : 
     742           0 :     DrawLine(Point(aAbsolutePos.X() - 1, 0 ),
     743           0 :              Point(aAbsolutePos.X() - 1, aAbsolutePos.Y() + aAbsoluteSize.Height()));
     744             : 
     745           0 :     DrawLine(Point(aAbsolutePos.X() + aAbsoluteSize.Width() + 1, 0 ),
     746           0 :              Point(aAbsolutePos.X() + aAbsoluteSize.Width() + 1, aAbsolutePos.Y() + aAbsoluteSize.Height()));
     747           0 : }
     748             : 
     749             : //------------------------------------------------------------------------------
     750           0 : void DbGridControl::NavigationBar::StateChanged( StateChangedType nType )
     751             : {
     752           0 :     Control::StateChanged( nType );
     753             : 
     754             :     Window* pWindows[] = {  &m_aRecordText,
     755             :                             &m_aAbsolute,
     756             :                             &m_aRecordOf,
     757             :                             &m_aRecordCount,
     758             :                             &m_aFirstBtn,
     759             :                             &m_aPrevBtn,
     760             :                             &m_aNextBtn,
     761             :                             &m_aLastBtn,
     762             :                             &m_aNewBtn
     763           0 :                         };
     764             : 
     765           0 :     switch ( nType )
     766             :     {
     767             :         case STATE_CHANGE_MIRRORING:
     768             :         {
     769           0 :             sal_Bool bIsRTLEnabled = IsRTLEnabled();
     770           0 :             for ( size_t i=0; i < (sizeof (pWindows) / sizeof(pWindows[0])); ++i )
     771           0 :                 pWindows[i]->EnableRTL( bIsRTLEnabled );
     772             :         }
     773           0 :         break;
     774             : 
     775             :         case STATE_CHANGE_ZOOM:
     776             :         {
     777           0 :             Fraction aZoom = GetZoom();
     778             : 
     779             :             // not all of these controls need to know the new zoom, but to be sure ...
     780           0 :             Font aFont( GetSettings().GetStyleSettings().GetFieldFont() );
     781           0 :             if ( IsControlFont() )
     782           0 :                 aFont.Merge( GetControlFont() );
     783             : 
     784           0 :             for (size_t i=0; i < sizeof(pWindows)/sizeof(pWindows[0]); ++i)
     785             :             {
     786           0 :                 pWindows[i]->SetZoom(aZoom);
     787           0 :                 pWindows[i]->SetZoomedPointFont(aFont);
     788             :             }
     789             : 
     790           0 :             SetZoomedPointFont( aFont );
     791             : 
     792             :             // rearrange the controls
     793           0 :             m_nDefaultWidth = ArrangeControls();
     794             :         }
     795           0 :         break;
     796             :     }
     797           0 : }
     798             : 
     799             : //------------------------------------------------------------------------------
     800           0 : DbGridRow::DbGridRow(CursorWrapper* pCur, sal_Bool bPaintCursor)
     801           0 :           :m_bIsNew(sal_False)
     802             : {
     803             : 
     804           0 :     if (pCur && pCur->Is())
     805             :     {
     806           0 :         Reference< XIndexAccess >  xColumns(pCur->getColumns(), UNO_QUERY);
     807             :         DataColumn* pColumn;
     808           0 :         for (sal_Int32 i = 0; i < xColumns->getCount(); ++i)
     809             :         {
     810           0 :             Reference< XPropertySet > xColSet;
     811           0 :             ::cppu::extractInterface(xColSet, xColumns->getByIndex(i));
     812           0 :             pColumn = new DataColumn(xColSet);
     813           0 :             m_aVariants.push_back( pColumn );
     814           0 :         }
     815             : 
     816           0 :         if (pCur->rowDeleted())
     817           0 :             m_eStatus = GRS_DELETED;
     818             :         else
     819             :         {
     820           0 :             if (bPaintCursor)
     821           0 :                 m_eStatus = (pCur->isAfterLast() || pCur->isBeforeFirst()) ? GRS_INVALID : GRS_CLEAN;
     822             :             else
     823             :             {
     824           0 :                 Reference< XPropertySet > xSet = pCur->getPropertySet();
     825           0 :                 if (xSet.is())
     826             :                 {
     827           0 :                     m_bIsNew = ::comphelper::getBOOL(xSet->getPropertyValue(FM_PROP_ISNEW));
     828           0 :                     if (!m_bIsNew && (pCur->isAfterLast() || pCur->isBeforeFirst()))
     829           0 :                         m_eStatus = GRS_INVALID;
     830           0 :                     else if (::comphelper::getBOOL(xSet->getPropertyValue(FM_PROP_ISMODIFIED)))
     831           0 :                         m_eStatus = GRS_MODIFIED;
     832             :                     else
     833           0 :                         m_eStatus = GRS_CLEAN;
     834             :                 }
     835             :                 else
     836           0 :                     m_eStatus = GRS_INVALID;
     837             :             }
     838             :         }
     839           0 :         if (!m_bIsNew && IsValid())
     840           0 :             m_aBookmark = pCur->getBookmark();
     841             :         else
     842           0 :             m_aBookmark = Any();
     843             :     }
     844             :     else
     845           0 :         m_eStatus = GRS_INVALID;
     846           0 : }
     847             : 
     848             : //------------------------------------------------------------------------------
     849           0 : DbGridRow::~DbGridRow()
     850             : {
     851           0 :     for ( size_t i = 0, n = m_aVariants.size(); i < n; ++i )
     852           0 :         delete m_aVariants[ i ];
     853           0 :     m_aVariants.clear();
     854           0 : }
     855             : 
     856             : //------------------------------------------------------------------------------
     857           0 : void DbGridRow::SetState(CursorWrapper* pCur, sal_Bool bPaintCursor)
     858             : {
     859           0 :     if (pCur && pCur->Is())
     860             :     {
     861           0 :         if (pCur->rowDeleted())
     862             :         {
     863           0 :             m_eStatus = GRS_DELETED;
     864           0 :             m_bIsNew = sal_False;
     865             :         }
     866             :         else
     867             :         {
     868           0 :             m_eStatus = GRS_CLEAN;
     869           0 :             if (!bPaintCursor)
     870             :             {
     871           0 :                 Reference< XPropertySet > xSet = pCur->getPropertySet();
     872             :                 DBG_ASSERT(xSet.is(), "DbGridRow::SetState : invalid cursor !");
     873             : 
     874           0 :                 if (::comphelper::getBOOL(xSet->getPropertyValue(FM_PROP_ISMODIFIED)))
     875           0 :                     m_eStatus = GRS_MODIFIED;
     876           0 :                 m_bIsNew = ::comphelper::getBOOL(xSet->getPropertyValue(FM_PROP_ISNEW));
     877             :             }
     878             :             else
     879           0 :                 m_bIsNew = sal_False;
     880             :         }
     881             : 
     882             :         try
     883             :         {
     884           0 :             if (!m_bIsNew && IsValid())
     885           0 :                 m_aBookmark = pCur->getBookmark();
     886             :             else
     887           0 :                 m_aBookmark = Any();
     888             :         }
     889           0 :         catch(SQLException&)
     890             :         {
     891             :             DBG_UNHANDLED_EXCEPTION();
     892           0 :             m_aBookmark = Any();
     893           0 :             m_eStatus = GRS_INVALID;
     894           0 :             m_bIsNew = sal_False;
     895             :         }
     896             :     }
     897             :     else
     898             :     {
     899           0 :         m_aBookmark = Any();
     900           0 :         m_eStatus = GRS_INVALID;
     901           0 :         m_bIsNew = sal_False;
     902             :     }
     903           0 : }
     904             : 
     905             : DBG_NAME(DbGridControl);
     906             : //------------------------------------------------------------------------------
     907           0 : DbGridControl::DbGridControl(
     908             :                 Reference< XMultiServiceFactory > _rxFactory,
     909             :                 Window* pParent,
     910             :                 WinBits nBits)
     911             :             :DbGridControl_Base(pParent, EBBF_NONE, nBits, DEFAULT_BROWSE_MODE )
     912             :             ,m_xServiceFactory(_rxFactory)
     913             :             ,m_aBar(this)
     914             :             ,m_nAsynAdjustEvent(0)
     915             :             ,m_pDataSourcePropMultiplexer(NULL)
     916             :             ,m_pDataSourcePropListener(NULL)
     917             :             ,m_pFieldListeners(NULL)
     918             :             ,m_pCursorDisposeListener(NULL)
     919             :             ,m_pGridListener(NULL)
     920             :             ,m_pDataCursor(NULL)
     921             :             ,m_pSeekCursor(NULL)
     922             :             ,m_nSeekPos(-1)
     923             :             ,m_nTotalCount(-1)
     924           0 :             ,m_aNullDate(OTypeConversionClient().getStandardDate())
     925             :             ,m_nMode(DEFAULT_BROWSE_MODE)
     926             :             ,m_nCurrentPos(-1)
     927             :             ,m_nDeleteEvent(0)
     928             :             ,m_nOptions(OPT_READONLY)
     929             :             ,m_nOptionMask(OPT_INSERT | OPT_UPDATE | OPT_DELETE)
     930             :             ,m_nLastColId((sal_uInt16)-1)
     931             :             ,m_nLastRowId(-1)
     932             :             ,m_bDesignMode(sal_False)
     933             :             ,m_bRecordCountFinal(sal_False)
     934             :             ,m_bMultiSelection(sal_True)
     935             :             ,m_bNavigationBar(sal_True)
     936             :             ,m_bSynchDisplay(sal_True)
     937             :             ,m_bForceROController(sal_False)
     938             :             ,m_bHandle(sal_True)
     939             :             ,m_bFilterMode(sal_False)
     940             :             ,m_bWantDestruction(sal_False)
     941             :             ,m_bInAdjustDataSource(sal_False)
     942             :             ,m_bPendingAdjustRows(sal_False)
     943             :             ,m_bHideScrollbars( sal_False )
     944           0 :             ,m_bUpdating(sal_False)
     945             : {
     946             :     DBG_CTOR(DbGridControl,NULL);
     947             : 
     948           0 :     String sName(SVX_RES(RID_STR_NAVIGATIONBAR));
     949           0 :     m_aBar.SetAccessibleName(sName);
     950           0 :     m_aBar.Show();
     951           0 :     ImplInitWindow( InitAll );
     952           0 : }
     953             : 
     954             : //------------------------------------------------------------------------------
     955           0 : void DbGridControl::InsertHandleColumn()
     956             : {
     957             :     // Handle Column einfuegen
     958             :     // Da die BrowseBox ohne handleColums Paintprobleme hat
     959             :     // wird diese versteckt
     960           0 :     if (HasHandle())
     961           0 :         BrowseBox::InsertHandleColumn(GetDefaultColumnWidth(String()));
     962             :     else
     963           0 :         BrowseBox::InsertHandleColumn(0);
     964           0 : }
     965             : 
     966             : //------------------------------------------------------------------------------
     967           0 : void DbGridControl::Init()
     968             : {
     969           0 :     BrowserHeader* pNewHeader = CreateHeaderBar(this);
     970           0 :     pHeader->SetMouseTransparent(sal_False);
     971             : 
     972           0 :     SetHeaderBar(pNewHeader);
     973           0 :     SetMode(m_nMode);
     974           0 :     SetCursorColor(Color(0xFF, 0, 0));
     975             : 
     976           0 :     InsertHandleColumn();
     977           0 : }
     978             : 
     979             : //------------------------------------------------------------------------------
     980           0 : DbGridControl::~DbGridControl()
     981             : {
     982           0 :     RemoveColumns();
     983             : 
     984             :     {
     985           0 :         m_bWantDestruction = sal_True;
     986           0 :         osl::MutexGuard aGuard(m_aDestructionSafety);
     987           0 :         if (m_pFieldListeners)
     988           0 :             DisconnectFromFields();
     989           0 :         if (m_pCursorDisposeListener)
     990             :         {
     991           0 :             delete m_pCursorDisposeListener;
     992           0 :             m_pCursorDisposeListener = NULL;
     993           0 :         }
     994             :     }
     995             : 
     996           0 :     if (m_nDeleteEvent)
     997           0 :         Application::RemoveUserEvent(m_nDeleteEvent);
     998             : 
     999           0 :     if (m_pDataSourcePropMultiplexer)
    1000             :     {
    1001           0 :         m_pDataSourcePropMultiplexer->dispose();
    1002           0 :         m_pDataSourcePropMultiplexer->release();    // this should delete the multiplexer
    1003           0 :         delete m_pDataSourcePropListener;
    1004           0 :         m_pDataSourcePropMultiplexer = NULL;
    1005           0 :         m_pDataSourcePropListener = NULL;
    1006             :     }
    1007           0 :     m_xRowSetListener.clear();
    1008             : 
    1009           0 :     delete m_pDataCursor;
    1010           0 :     delete m_pSeekCursor;
    1011             : 
    1012             :     DBG_DTOR(DbGridControl,NULL);
    1013           0 : }
    1014             : 
    1015             : //------------------------------------------------------------------------------
    1016           0 : void DbGridControl::StateChanged( StateChangedType nType )
    1017             : {
    1018           0 :     DbGridControl_Base::StateChanged( nType );
    1019             : 
    1020           0 :     switch (nType)
    1021             :     {
    1022             :         case STATE_CHANGE_MIRRORING:
    1023           0 :             ImplInitWindow( InitWritingMode );
    1024           0 :             Invalidate();
    1025           0 :             break;
    1026             : 
    1027             :         case STATE_CHANGE_ZOOM:
    1028             :         {
    1029           0 :             ImplInitWindow( InitFont );
    1030             : 
    1031             :             // and give it a chance to rearrange
    1032           0 :             Point aPoint = GetControlArea().TopLeft();
    1033           0 :             sal_uInt16 nX = (sal_uInt16)aPoint.X();
    1034           0 :             ArrangeControls(nX, (sal_uInt16)aPoint.Y());
    1035           0 :             ReserveControlArea((sal_uInt16)nX);
    1036             :         }
    1037           0 :         break;
    1038             :         case STATE_CHANGE_CONTROLFONT:
    1039           0 :             ImplInitWindow( InitFont );
    1040           0 :             Invalidate();
    1041           0 :             break;
    1042             :         case STATE_CHANGE_CONTROLFOREGROUND:
    1043           0 :             ImplInitWindow( InitForeground );
    1044           0 :             Invalidate();
    1045           0 :             break;
    1046             :         case STATE_CHANGE_CONTROLBACKGROUND:
    1047           0 :             ImplInitWindow( InitBackground );
    1048           0 :             Invalidate();
    1049           0 :             break;
    1050             :     }
    1051           0 : }
    1052             : 
    1053             : //------------------------------------------------------------------------------
    1054           0 : void DbGridControl::DataChanged( const DataChangedEvent& rDCEvt )
    1055             : {
    1056           0 :     DbGridControl_Base::DataChanged( rDCEvt );
    1057           0 :     if ( (rDCEvt.GetType() == DATACHANGED_SETTINGS ) &&
    1058           0 :          (rDCEvt.GetFlags() & SETTINGS_STYLE) )
    1059             :     {
    1060           0 :         ImplInitWindow( InitAll );
    1061           0 :         Invalidate();
    1062             :     }
    1063           0 : }
    1064             : 
    1065             : //------------------------------------------------------------------------------
    1066           0 : void DbGridControl::Select()
    1067             : {
    1068           0 :     DbGridControl_Base::Select();
    1069             : 
    1070             :     // as the selected rows may have changed, udate the according display in our navigation bar
    1071           0 :     m_aBar.InvalidateState(NavigationBar::RECORD_COUNT);
    1072             : 
    1073           0 :     if (m_pGridListener)
    1074           0 :         m_pGridListener->selectionChanged();
    1075           0 : }
    1076             : 
    1077             : //------------------------------------------------------------------------------
    1078           0 : void DbGridControl::ImplInitWindow( const InitWindowFacet _eInitWhat )
    1079             : {
    1080           0 :     for ( size_t i = 0; i < m_aColumns.size(); ++i )
    1081             :     {
    1082           0 :         DbGridColumn* pCol = m_aColumns[ i ];
    1083           0 :         if (pCol)
    1084           0 :             pCol->ImplInitWindow( GetDataWindow(), _eInitWhat );
    1085             :     }
    1086             : 
    1087           0 :     if ( ( _eInitWhat & InitWritingMode ) != 0 )
    1088             :     {
    1089           0 :         if ( m_bNavigationBar )
    1090             :         {
    1091           0 :             m_aBar.EnableRTL( IsRTLEnabled() );
    1092             :         }
    1093             :     }
    1094             : 
    1095           0 :     if ( ( _eInitWhat & InitFont ) != 0 )
    1096             :     {
    1097           0 :         if ( m_bNavigationBar )
    1098             :         {
    1099           0 :             Font aFont = m_aBar.GetSettings().GetStyleSettings().GetFieldFont();
    1100           0 :             if ( IsControlFont() )
    1101           0 :                 m_aBar.SetControlFont( GetControlFont() );
    1102             :             else
    1103           0 :                 m_aBar.SetControlFont();
    1104             : 
    1105           0 :             m_aBar.SetZoom( GetZoom() );
    1106             :         }
    1107             :     }
    1108             : 
    1109           0 :     if ( ( _eInitWhat & InitBackground ) != 0 )
    1110             :     {
    1111           0 :         if (IsControlBackground())
    1112             :         {
    1113           0 :             GetDataWindow().SetBackground(GetControlBackground());
    1114           0 :             GetDataWindow().SetControlBackground(GetControlBackground());
    1115           0 :             GetDataWindow().SetFillColor(GetControlBackground());
    1116             :         }
    1117             :         else
    1118             :         {
    1119           0 :             GetDataWindow().SetControlBackground();
    1120           0 :             GetDataWindow().SetFillColor(GetFillColor());
    1121             :         }
    1122             :     }
    1123           0 : }
    1124             : 
    1125             : //------------------------------------------------------------------------------
    1126           0 : void DbGridControl::RemoveRows(sal_Bool bNewCursor)
    1127             : {
    1128             :     // Hat sich der DatenCursor verandert ?
    1129           0 :     if (!bNewCursor)
    1130             :     {
    1131           0 :         DELETEZ(m_pSeekCursor);
    1132           0 :         m_xPaintRow = m_xDataRow = m_xEmptyRow  = m_xCurrentRow = m_xSeekRow = NULL;
    1133           0 :         m_nCurrentPos = m_nSeekPos = -1;
    1134           0 :         m_nOptions  = OPT_READONLY;
    1135             : 
    1136           0 :         RowRemoved(0, GetRowCount(), sal_False);
    1137           0 :         m_nTotalCount = -1;
    1138             :     }
    1139             :     else
    1140             :     {
    1141           0 :         RemoveRows();
    1142             :     }
    1143           0 : }
    1144             : 
    1145             : //------------------------------------------------------------------------------
    1146           0 : void DbGridControl::RemoveRows()
    1147             : {
    1148             :     // we're going to remove all columns and all row, so deactivate the current cell
    1149           0 :     if (IsEditing())
    1150           0 :         DeactivateCell();
    1151             : 
    1152             :     // alle Columns deinitialisieren
    1153             :     // existieren Spalten, dann alle Controller freigeben
    1154           0 :     for (size_t i = 0; i < m_aColumns.size(); i++)
    1155           0 :         m_aColumns[ i ]->Clear();
    1156             : 
    1157           0 :     DELETEZ(m_pSeekCursor);
    1158           0 :     DELETEZ(m_pDataCursor);
    1159             : 
    1160           0 :     m_xPaintRow = m_xDataRow = m_xEmptyRow  = m_xCurrentRow = m_xSeekRow = NULL;
    1161           0 :     m_nCurrentPos = m_nSeekPos = m_nTotalCount  = -1;
    1162           0 :     m_nOptions  = OPT_READONLY;
    1163             : 
    1164             :     // Anzahl Saetze im Browser auf 0 zuruecksetzen
    1165           0 :     DbGridControl_Base::RemoveRows();
    1166           0 :     m_aBar.InvalidateAll(m_nCurrentPos, sal_True);
    1167           0 : }
    1168             : 
    1169             : //------------------------------------------------------------------------------
    1170           0 : void DbGridControl::ArrangeControls(sal_uInt16& nX, sal_uInt16 nY)
    1171             : {
    1172             :     // Positionierung der Controls
    1173           0 :     if (m_bNavigationBar)
    1174             :     {
    1175           0 :         nX = m_aBar.GetDefaultWidth();
    1176           0 :         Rectangle   aRect(GetControlArea());
    1177           0 :         m_aBar.SetPosSizePixel(Point(0,nY + 1), Size(nX, aRect.GetSize().Height() - 1));
    1178             :     }
    1179           0 : }
    1180             : 
    1181             : //------------------------------------------------------------------------------
    1182           0 : void DbGridControl::EnableHandle(sal_Bool bEnable)
    1183             : {
    1184           0 :     if (m_bHandle == bEnable)
    1185           0 :         return;
    1186             : 
    1187             :     // HandleColumn wird nur ausgeblendet,
    1188             :     // da es sonst etliche Probleme mit dem Zeichnen gibt
    1189           0 :     RemoveColumn( HandleColumnId );
    1190           0 :     m_bHandle = bEnable;
    1191           0 :     InsertHandleColumn();
    1192             : }
    1193             : 
    1194             : //------------------------------------------------------------------------------
    1195             : namespace
    1196             : {
    1197           0 :     bool adjustModeForScrollbars( BrowserMode& _rMode, sal_Bool _bNavigationBar, sal_Bool _bHideScrollbars )
    1198             :     {
    1199           0 :         BrowserMode nOldMode = _rMode;
    1200             : 
    1201           0 :         if ( !_bNavigationBar )
    1202             :         {
    1203           0 :             _rMode &= ~BROWSER_AUTO_HSCROLL;
    1204             :         }
    1205             : 
    1206           0 :         if ( _bHideScrollbars )
    1207             :         {
    1208           0 :             _rMode |= ( BROWSER_NO_HSCROLL | BROWSER_NO_VSCROLL );
    1209           0 :             _rMode &= ~( BROWSER_AUTO_HSCROLL | BROWSER_AUTO_VSCROLL );
    1210             :         }
    1211             :         else
    1212             :         {
    1213           0 :             _rMode |= ( BROWSER_AUTO_HSCROLL | BROWSER_AUTO_VSCROLL );
    1214           0 :             _rMode &= ~( BROWSER_NO_HSCROLL | BROWSER_NO_VSCROLL );
    1215             :         }
    1216             : 
    1217             :         // note: if we have a navigation bar, we always have a AUTO_HSCROLL. In particular,
    1218             :         // _bHideScrollbars is ignored then
    1219           0 :         if ( _bNavigationBar )
    1220             :         {
    1221           0 :             _rMode |= BROWSER_AUTO_HSCROLL;
    1222           0 :             _rMode &= ~BROWSER_NO_HSCROLL;
    1223             :         }
    1224             : 
    1225           0 :         return nOldMode != _rMode;
    1226             :     }
    1227             : }
    1228             : 
    1229             : //------------------------------------------------------------------------------
    1230           0 : void DbGridControl::EnableNavigationBar(sal_Bool bEnable)
    1231             : {
    1232           0 :     if (m_bNavigationBar == bEnable)
    1233           0 :         return;
    1234             : 
    1235           0 :     m_bNavigationBar = bEnable;
    1236             : 
    1237           0 :     if (bEnable)
    1238             :     {
    1239           0 :         m_aBar.Show();
    1240           0 :         m_aBar.Enable();
    1241           0 :         m_aBar.InvalidateAll(m_nCurrentPos, sal_True);
    1242             : 
    1243           0 :         if ( adjustModeForScrollbars( m_nMode, m_bNavigationBar, m_bHideScrollbars ) )
    1244           0 :             SetMode( m_nMode );
    1245             : 
    1246             :         // liefert die Groe�e der Reserved ControlArea
    1247           0 :         Point aPoint = GetControlArea().TopLeft();
    1248           0 :         sal_uInt16 nX = (sal_uInt16)aPoint.X();
    1249             : 
    1250           0 :         ArrangeControls(nX, (sal_uInt16)aPoint.Y());
    1251           0 :         ReserveControlArea((sal_uInt16)nX);
    1252             :     }
    1253             :     else
    1254             :     {
    1255           0 :         m_aBar.Hide();
    1256           0 :         m_aBar.Disable();
    1257             : 
    1258           0 :         if ( adjustModeForScrollbars( m_nMode, m_bNavigationBar, m_bHideScrollbars ) )
    1259           0 :             SetMode( m_nMode );
    1260             : 
    1261           0 :         ReserveControlArea();
    1262             :     }
    1263             : }
    1264             : 
    1265             : //------------------------------------------------------------------------------
    1266           0 : sal_uInt16 DbGridControl::SetOptions(sal_uInt16 nOpt)
    1267             : {
    1268             :     DBG_ASSERT(!m_xCurrentRow || !m_xCurrentRow->IsModified(),
    1269             :         "DbGridControl::SetOptions : please do not call when editing a record (things are much easier this way ;) !");
    1270             : 
    1271             :     // for the next setDataSource (which is triggered by a refresh, for instance)
    1272           0 :     m_nOptionMask = nOpt;
    1273             : 
    1274             :     // normalize the new options
    1275           0 :     Reference< XPropertySet > xDataSourceSet = m_pDataCursor->getPropertySet();
    1276           0 :     if (xDataSourceSet.is())
    1277             :     {
    1278             :         // feststellen welche Updatem�glichkeiten bestehen
    1279           0 :         sal_Int32 nPrivileges = 0;
    1280           0 :         xDataSourceSet->getPropertyValue(FM_PROP_PRIVILEGES) >>= nPrivileges;
    1281           0 :         if ((nPrivileges & Privilege::INSERT) == 0)
    1282           0 :             nOpt &= ~OPT_INSERT;
    1283           0 :         if ((nPrivileges & Privilege::UPDATE) == 0)
    1284           0 :             nOpt &= ~OPT_UPDATE;
    1285           0 :         if ((nPrivileges & Privilege::DELETE) == 0)
    1286           0 :             nOpt &= ~OPT_DELETE;
    1287             :     }
    1288             :     else
    1289           0 :         nOpt = OPT_READONLY;
    1290             : 
    1291             :     // need to do something after that ?
    1292           0 :     if (nOpt == m_nOptions)
    1293           0 :         return m_nOptions;
    1294             : 
    1295             :     // the 'update' option only affects our BrowserMode (with or w/o focus rect)
    1296           0 :     BrowserMode nNewMode = m_nMode;
    1297           0 :     if ((m_nMode & BROWSER_CURSOR_WO_FOCUS) == 0)
    1298             :     {
    1299           0 :         if (nOpt & OPT_UPDATE)
    1300           0 :             nNewMode |= BROWSER_HIDECURSOR;
    1301             :         else
    1302           0 :             nNewMode &= ~BROWSER_HIDECURSOR;
    1303             :     }
    1304             :     else
    1305           0 :         nNewMode &= ~BROWSER_HIDECURSOR;
    1306             :         // should not be neccessary if EnablePermanentCursor is used to change the cursor behaviour, but to be sure ...
    1307             : 
    1308           0 :     if (nNewMode != m_nMode)
    1309             :     {
    1310           0 :         SetMode(nNewMode);
    1311           0 :         m_nMode = nNewMode;
    1312             :     }
    1313             : 
    1314             :     // _after_ setting the mode because this results in an ActivateCell
    1315           0 :     DeactivateCell();
    1316             : 
    1317           0 :     sal_Bool bInsertChanged = (nOpt & OPT_INSERT) != (m_nOptions & OPT_INSERT);
    1318           0 :     m_nOptions = nOpt;
    1319             :         // we need to set this before the code below because it indirectly uses m_nOptions
    1320             : 
    1321             :     // the 'insert' option affects our empty row
    1322           0 :     if (bInsertChanged)
    1323             :     {
    1324           0 :         if (m_nOptions & OPT_INSERT)
    1325             :         {   // the insert option is to be set
    1326           0 :             m_xEmptyRow = new DbGridRow();
    1327           0 :             RowInserted(GetRowCount(), 1, sal_True);
    1328             :         }
    1329             :         else
    1330             :         {   // the insert option is to be reset
    1331           0 :             m_xEmptyRow = NULL;
    1332           0 :             if ((GetCurRow() == GetRowCount() - 1) && (GetCurRow() > 0))
    1333           0 :                 GoToRowColumnId(GetCurRow() - 1, GetCurColumnId());
    1334           0 :             RowRemoved(GetRowCount(), 1, sal_True);
    1335             :         }
    1336             :     }
    1337             : 
    1338             :     // the 'delete' options has no immediate consequences
    1339             : 
    1340           0 :     ActivateCell();
    1341           0 :     Invalidate();
    1342           0 :     return m_nOptions;
    1343             : }
    1344             : 
    1345             : //------------------------------------------------------------------------------
    1346           0 : void DbGridControl::ForceHideScrollbars( sal_Bool _bForce )
    1347             : {
    1348           0 :     if ( m_bHideScrollbars == _bForce )
    1349           0 :         return;
    1350             : 
    1351           0 :     m_bHideScrollbars = _bForce;
    1352             : 
    1353           0 :     if ( adjustModeForScrollbars( m_nMode, m_bNavigationBar, m_bHideScrollbars ) )
    1354           0 :         SetMode( m_nMode );
    1355             : }
    1356             : 
    1357             : //------------------------------------------------------------------------------
    1358           0 : void DbGridControl::EnablePermanentCursor(sal_Bool bEnable)
    1359             : {
    1360           0 :     if (IsPermanentCursorEnabled() == bEnable)
    1361           0 :         return;
    1362             : 
    1363           0 :     if (bEnable)
    1364             :     {
    1365           0 :         m_nMode &= ~BROWSER_HIDECURSOR;     // without this BROWSER_CURSOR_WO_FOCUS won't have any affect
    1366           0 :         m_nMode |= BROWSER_CURSOR_WO_FOCUS;
    1367             :     }
    1368             :     else
    1369             :     {
    1370           0 :         if (m_nOptions & OPT_UPDATE)
    1371           0 :             m_nMode |= BROWSER_HIDECURSOR;      // no cursor at all
    1372             :         else
    1373           0 :             m_nMode &= ~BROWSER_HIDECURSOR;     // at least the "non-permanent" cursor
    1374             : 
    1375           0 :         m_nMode &= ~BROWSER_CURSOR_WO_FOCUS;
    1376             :     }
    1377           0 :     SetMode(m_nMode);
    1378             : 
    1379           0 :     sal_Bool bWasEditing = IsEditing();
    1380           0 :     DeactivateCell();
    1381           0 :     if (bWasEditing)
    1382           0 :         ActivateCell();
    1383             : }
    1384             : 
    1385             : //------------------------------------------------------------------------------
    1386           0 : sal_Bool DbGridControl::IsPermanentCursorEnabled() const
    1387             : {
    1388           0 :     return ((m_nMode & BROWSER_CURSOR_WO_FOCUS) != 0) && ((m_nMode & BROWSER_HIDECURSOR) == 0);
    1389             : }
    1390             : 
    1391             : //------------------------------------------------------------------------------
    1392           0 : void DbGridControl::refreshController(sal_uInt16 _nColId, GrantControlAccess /*_aAccess*/)
    1393             : {
    1394           0 :     if ((GetCurColumnId() == _nColId) && IsEditing())
    1395             :     {   // the controller which is currently active needs to be refreshed
    1396           0 :         DeactivateCell();
    1397           0 :         ActivateCell();
    1398             :     }
    1399           0 : }
    1400             : 
    1401             : //------------------------------------------------------------------------------
    1402           0 : void DbGridControl::setDataSource(const Reference< XRowSet >& _xCursor, sal_uInt16 nOpts)
    1403             : {
    1404           0 :     if (!_xCursor.is() && !m_pDataCursor)
    1405             :         return;
    1406             : 
    1407           0 :     if (m_pDataSourcePropMultiplexer)
    1408             :     {
    1409           0 :         m_pDataSourcePropMultiplexer->dispose();
    1410           0 :         m_pDataSourcePropMultiplexer->release();    // this should delete the multiplexer
    1411           0 :         delete m_pDataSourcePropListener;
    1412           0 :         m_pDataSourcePropMultiplexer = NULL;
    1413           0 :         m_pDataSourcePropListener = NULL;
    1414             :     }
    1415           0 :     m_xRowSetListener.clear();
    1416             : 
    1417             :     // is the new cursor valid ?
    1418             :     // the cursor is only valid if it contains some columns
    1419             :     // if there is no cursor or the cursor is not valid we have to clean up an leave
    1420           0 :     if (!_xCursor.is() || !Reference< XColumnsSupplier > (_xCursor, UNO_QUERY)->getColumns()->hasElements())
    1421             :     {
    1422           0 :         RemoveRows();
    1423             :         return;
    1424             :     }
    1425             : 
    1426             :     // Hat sich der DatenCursor verandert ?
    1427           0 :     sal_uInt16 nCurPos = GetColumnPos(GetCurColumnId());
    1428             : 
    1429           0 :     SetUpdateMode(sal_False);
    1430           0 :     RemoveRows();
    1431           0 :     DisconnectFromFields();
    1432             : 
    1433           0 :     DELETEZ(m_pCursorDisposeListener);
    1434             : 
    1435             :     {
    1436           0 :         ::osl::MutexGuard aGuard(m_aAdjustSafety);
    1437           0 :         if (m_nAsynAdjustEvent)
    1438             :         {
    1439             :             // the adjust was thought to work with the old cursor which we don't have anymore
    1440           0 :             RemoveUserEvent(m_nAsynAdjustEvent);
    1441           0 :             m_nAsynAdjustEvent = 0;
    1442           0 :         }
    1443             :     }
    1444             : 
    1445             :     // get a new formatter and data cursor
    1446           0 :     m_xFormatter = NULL;
    1447           0 :     OStaticDataAccessTools aStaticTools;
    1448           0 :     Reference< ::com::sun::star::util::XNumberFormatsSupplier >  xSupplier = aStaticTools.getNumberFormats(aStaticTools.getRowSetConnection(_xCursor), sal_True);
    1449           0 :     if (xSupplier.is())
    1450             :     {
    1451             :         m_xFormatter = Reference< ::com::sun::star::util::XNumberFormatter >(
    1452             :             ::com::sun::star::util::NumberFormatter::create(comphelper::getComponentContext(m_xServiceFactory)),
    1453           0 :             UNO_QUERY);
    1454           0 :         m_xFormatter->attachNumberFormatsSupplier(xSupplier);
    1455             : 
    1456             :         // retrieve the datebase of the Numberformatter
    1457             :         try
    1458             :         {
    1459           0 :             xSupplier->getNumberFormatSettings()->getPropertyValue(rtl::OUString("NullDate")) >>= m_aNullDate;
    1460             :         }
    1461           0 :         catch(Exception&)
    1462             :         {
    1463             :         }
    1464             :     }
    1465             : 
    1466           0 :     m_pDataCursor = new CursorWrapper(_xCursor);
    1467             : 
    1468             :     // now create a cursor for painting rows
    1469             :     // we need that cursor only if we are not in insert only mode
    1470           0 :     Reference< XResultSet > xClone;
    1471           0 :     Reference< XResultSetAccess > xAccess( _xCursor, UNO_QUERY );
    1472             :     try
    1473             :     {
    1474           0 :         xClone = xAccess.is() ? xAccess->createResultSet() : Reference< XResultSet > ();
    1475             :     }
    1476           0 :     catch(Exception&)
    1477             :     {
    1478             :     }
    1479           0 :     if (xClone.is())
    1480           0 :         m_pSeekCursor = new CursorWrapper(xClone);
    1481             : 
    1482             :     // property listening on the data source
    1483             :     // (Normally one class would be sufficient : the multiplexer which could forward the property change to us.
    1484             :     // But for that we would have been derived from ::comphelper::OPropertyChangeListener, which isn't exported.
    1485             :     // So we introduce a second class, which is a ::comphelper::OPropertyChangeListener (in the implementation file we know this class)
    1486             :     // and forwards the property changes to a our special method "DataSourcePropertyChanged".)
    1487           0 :     if (m_pDataCursor)
    1488             :     {
    1489           0 :         m_pDataSourcePropListener = new FmXGridSourcePropListener(this);
    1490           0 :         m_pDataSourcePropMultiplexer = new ::comphelper::OPropertyChangeMultiplexer(m_pDataSourcePropListener, m_pDataCursor->getPropertySet() );
    1491           0 :         m_pDataSourcePropMultiplexer->acquire();
    1492           0 :         m_pDataSourcePropMultiplexer->addProperty(FM_PROP_ISMODIFIED);
    1493           0 :         m_pDataSourcePropMultiplexer->addProperty(FM_PROP_ISNEW);
    1494             :     }
    1495             : 
    1496           0 :     BrowserMode nOldMode = m_nMode;
    1497           0 :     if (m_pSeekCursor)
    1498             :     {
    1499             :         try
    1500             :         {
    1501           0 :             Reference< XPropertySet >  xSet(_xCursor, UNO_QUERY);
    1502           0 :             if (xSet.is())
    1503             :             {
    1504             :                 // feststellen welche Updatemoeglichkeiten bestehen
    1505           0 :                 sal_Int32 nConcurrency = ResultSetConcurrency::READ_ONLY;
    1506           0 :                 xSet->getPropertyValue(FM_PROP_RESULTSET_CONCURRENCY) >>= nConcurrency;
    1507             : 
    1508           0 :                 if ( ResultSetConcurrency::UPDATABLE == nConcurrency )
    1509             :                 {
    1510           0 :                     sal_Int32 nPrivileges = 0;
    1511           0 :                     xSet->getPropertyValue(FM_PROP_PRIVILEGES) >>= nPrivileges;
    1512             : 
    1513             :                     // Insert Option should be set if insert only otherwise you won't see any rows
    1514             :                     // and no insertion is possible
    1515           0 :                     if ((m_nOptionMask & OPT_INSERT) && ((nPrivileges & Privilege::INSERT) == Privilege::INSERT) && (nOpts & OPT_INSERT))
    1516           0 :                         m_nOptions |= OPT_INSERT;
    1517           0 :                     if ((m_nOptionMask & OPT_UPDATE) && ((nPrivileges & Privilege::UPDATE) == Privilege::UPDATE) && (nOpts & OPT_UPDATE))
    1518           0 :                         m_nOptions |= OPT_UPDATE;
    1519           0 :                     if ((m_nOptionMask & OPT_DELETE) && ((nPrivileges & Privilege::DELETE) == Privilege::DELETE) && (nOpts & OPT_DELETE))
    1520           0 :                         m_nOptions |= OPT_DELETE;
    1521             :                 }
    1522           0 :             }
    1523             :         }
    1524           0 :         catch( const Exception& )
    1525             :         {
    1526             :             DBG_UNHANDLED_EXCEPTION();
    1527             :         }
    1528             : 
    1529           0 :         sal_Bool bPermanentCursor = IsPermanentCursorEnabled();
    1530           0 :         m_nMode = DEFAULT_BROWSE_MODE;
    1531             : 
    1532           0 :         if ( bPermanentCursor )
    1533             :         {
    1534           0 :             m_nMode |= BROWSER_CURSOR_WO_FOCUS;
    1535           0 :             m_nMode &= ~BROWSER_HIDECURSOR;
    1536             :         }
    1537             :         else
    1538             :         {
    1539             :             // Duerfen Updates gemacht werden, kein Focus-RechtEck
    1540           0 :             if ( m_nOptions & OPT_UPDATE )
    1541           0 :                 m_nMode |= BROWSER_HIDECURSOR;
    1542             :         }
    1543             : 
    1544           0 :         if ( m_bMultiSelection )
    1545           0 :             m_nMode |= BROWSER_MULTISELECTION;
    1546             :         else
    1547           0 :             m_nMode &= ~BROWSER_MULTISELECTION;
    1548             : 
    1549           0 :         adjustModeForScrollbars( m_nMode, m_bNavigationBar, m_bHideScrollbars );
    1550             : 
    1551           0 :         Reference< XColumnsSupplier >  xSupplyColumns(_xCursor, UNO_QUERY);
    1552           0 :         if (xSupplyColumns.is())
    1553           0 :             InitColumnsByFields(Reference< XIndexAccess > (xSupplyColumns->getColumns(), UNO_QUERY));
    1554             : 
    1555           0 :         ConnectToFields();
    1556             :     }
    1557             : 
    1558           0 :     sal_uInt32 nRecordCount(0);
    1559             : 
    1560           0 :     if (m_pSeekCursor)
    1561             :     {
    1562           0 :         Reference< XPropertySet > xSet = m_pDataCursor->getPropertySet();
    1563           0 :         xSet->getPropertyValue(FM_PROP_ROWCOUNT) >>= nRecordCount;
    1564           0 :         m_bRecordCountFinal = ::comphelper::getBOOL(xSet->getPropertyValue(FM_PROP_ROWCOUNTFINAL));
    1565             : 
    1566           0 :         m_xRowSetListener = new RowSetEventListener(this);
    1567           0 :         Reference< XRowsChangeBroadcaster> xChangeBroad(xSet,UNO_QUERY);
    1568           0 :         if ( xChangeBroad.is( ) )
    1569           0 :             xChangeBroad->addRowsChangeListener(m_xRowSetListener);
    1570             : 
    1571             : 
    1572             :         // insert the currently known rows
    1573             :         // and one row if we are able to insert rows
    1574           0 :         if (m_nOptions & OPT_INSERT)
    1575             :         {
    1576             :             // insert the empty row for insertion
    1577           0 :             m_xEmptyRow = new DbGridRow();
    1578           0 :             ++nRecordCount;
    1579             :         }
    1580           0 :         if (nRecordCount)
    1581             :         {
    1582           0 :             m_xPaintRow = m_xSeekRow = new DbGridRow(m_pSeekCursor, sal_True);
    1583           0 :             m_xDataRow  = new DbGridRow(m_pDataCursor, sal_False);
    1584           0 :             RowInserted(0, nRecordCount, sal_False);
    1585             : 
    1586           0 :             if (m_xSeekRow->IsValid())
    1587             :                 try
    1588             :                 {
    1589           0 :                     m_nSeekPos = m_pSeekCursor->getRow() - 1;
    1590             :                 }
    1591           0 :                 catch( const Exception& )
    1592             :                 {
    1593             :                     DBG_UNHANDLED_EXCEPTION();
    1594           0 :                     m_nSeekPos = -1;
    1595             :                 }
    1596             :         }
    1597             :         else
    1598             :         {
    1599             :             // no rows so we don't need a seekcursor
    1600           0 :             DELETEZ(m_pSeekCursor);
    1601           0 :         }
    1602             :     }
    1603             : 
    1604             :     // Zur alten Spalte gehen
    1605           0 :     if (nCurPos == BROWSER_INVALIDID || nCurPos >= ColCount())
    1606           0 :         nCurPos = 0;
    1607             : 
    1608             :     // there are rows so go to the selected current column
    1609           0 :     if (nRecordCount)
    1610           0 :         GoToRowColumnId(0, GetColumnId(nCurPos));
    1611             :     // else stop the editing if neccessary
    1612           0 :     else if (IsEditing())
    1613           0 :         DeactivateCell();
    1614             : 
    1615             :     // now reset the mode
    1616           0 :     if (m_nMode != nOldMode)
    1617           0 :         SetMode(m_nMode);
    1618             : 
    1619             :     // beim Resizen wird RecalcRows gerufen
    1620           0 :     if (!IsResizing() && GetRowCount())
    1621           0 :         RecalcRows(GetTopRow(), GetVisibleRows(), sal_True);
    1622             : 
    1623           0 :     m_aBar.InvalidateAll(m_nCurrentPos, sal_True);
    1624           0 :     SetUpdateMode(sal_True);
    1625             : 
    1626             :     // start listening on the seek cursor
    1627           0 :     if (m_pSeekCursor)
    1628           0 :         m_pCursorDisposeListener = new DisposeListenerGridBridge(*this, Reference< XComponent > ((Reference< XInterface >)*m_pSeekCursor, UNO_QUERY), 0);
    1629             : }
    1630             : 
    1631             : //------------------------------------------------------------------------------
    1632           0 : void DbGridControl::RemoveColumns()
    1633             : {
    1634           0 :     if ( IsEditing() )
    1635           0 :         DeactivateCell();
    1636             : 
    1637           0 :     for (size_t i = 0, n = m_aColumns.size(); i < n; i++)
    1638           0 :         delete m_aColumns[ i ];
    1639           0 :     m_aColumns.clear();
    1640             : 
    1641           0 :     DbGridControl_Base::RemoveColumns();
    1642           0 : }
    1643             : 
    1644             : //------------------------------------------------------------------------------
    1645           0 : DbGridColumn* DbGridControl::CreateColumn(sal_uInt16 nId) const
    1646             : {
    1647           0 :     return new DbGridColumn(nId, *(DbGridControl*)this);
    1648             : }
    1649             : 
    1650             : //------------------------------------------------------------------------------
    1651           0 : sal_uInt16 DbGridControl::AppendColumn(const XubString& rName, sal_uInt16 nWidth, sal_uInt16 nModelPos, sal_uInt16 nId)
    1652             : {
    1653             :     DBG_ASSERT(nId == BROWSER_INVALIDID, "DbGridControl::AppendColumn : I want to set the ID myself ...");
    1654           0 :     sal_uInt16 nRealPos = nModelPos;
    1655           0 :     if (nModelPos != HEADERBAR_APPEND)
    1656             :     {
    1657             :         // calc the view pos. we can't use our converting functions because the new column
    1658             :         // has no VCL-representation, yet.
    1659           0 :         sal_Int16 nViewPos = nModelPos;
    1660           0 :         while (nModelPos--)
    1661             :         {
    1662           0 :             if ( m_aColumns[ nModelPos ]->IsHidden() )
    1663           0 :                 --nViewPos;
    1664             :         }
    1665             :         // restore nModelPos, we need it later
    1666           0 :         nModelPos = nRealPos;
    1667             :         // the position the base class gets is the view pos + 1 (because of the handle column)
    1668           0 :         nRealPos = nViewPos + 1;
    1669             :     }
    1670             : 
    1671             :     // calculate the new id
    1672           0 :     for (nId=1; (GetModelColumnPos(nId) != GRID_COLUMN_NOT_FOUND) && (nId <= m_aColumns.size()); ++nId)
    1673             :         ;
    1674             :     DBG_ASSERT(GetViewColumnPos(nId) == GRID_COLUMN_NOT_FOUND, "DbGridControl::AppendColumn : inconsistent internal state !");
    1675             :         // my column's models say "there is no column with id nId", but the view (the base class) says "there is a column ..."
    1676             : 
    1677           0 :     DbGridControl_Base::AppendColumn(rName, nWidth, nRealPos, nId);
    1678           0 :     if (nModelPos == HEADERBAR_APPEND)
    1679           0 :         m_aColumns.push_back( CreateColumn(nId) );
    1680             :     else
    1681             :     {
    1682           0 :         DbGridColumns::iterator it = m_aColumns.begin();
    1683           0 :         ::std::advance( it, nModelPos );
    1684           0 :         m_aColumns.insert( it, CreateColumn(nId) );
    1685             :     }
    1686             : 
    1687           0 :     return nId;
    1688             : }
    1689             : 
    1690             : //------------------------------------------------------------------------------
    1691           0 : void DbGridControl::RemoveColumn(sal_uInt16 nId)
    1692             : {
    1693           0 :     DbGridControl_Base::RemoveColumn(nId);
    1694             : 
    1695           0 :     const sal_uInt16 nIndex = GetModelColumnPos(nId);
    1696           0 :     if(nIndex != GRID_COLUMN_NOT_FOUND)
    1697             :     {
    1698           0 :         delete m_aColumns[nIndex];
    1699           0 :         m_aColumns.erase( m_aColumns.begin()+nIndex );
    1700             :     }
    1701           0 : }
    1702             : 
    1703             : //------------------------------------------------------------------------------
    1704           0 : void DbGridControl::ColumnMoved(sal_uInt16 nId)
    1705             : {
    1706           0 :     DbGridControl_Base::ColumnMoved(nId);
    1707             : 
    1708             :     // remove the col from the model
    1709           0 :     sal_uInt16 nOldModelPos = GetModelColumnPos(nId);
    1710             : #ifdef DBG_UTIL
    1711             :     DbGridColumn* pCol = m_aColumns[ (sal_uInt32)nOldModelPos ];
    1712             :     DBG_ASSERT(!pCol->IsHidden(), "DbGridControl::ColumnMoved : moved a hidden col ? how this ?");
    1713             : #endif
    1714             : 
    1715             :     // for the new model pos we can't use GetModelColumnPos because we are altering the model at the moment
    1716             :     // so the method won't work (in fact it would return the old model pos)
    1717             : 
    1718             :     // the new view pos is calculated easily
    1719           0 :     sal_uInt16 nNewViewPos = GetViewColumnPos(nId);
    1720             : 
    1721             :     // from that we can compute the new model pos
    1722             :     sal_uInt16 nNewModelPos;
    1723           0 :     for (nNewModelPos = 0; nNewModelPos < m_aColumns.size(); ++nNewModelPos)
    1724             :     {
    1725           0 :         if (!m_aColumns[ nNewModelPos ]->IsHidden())
    1726             :         {
    1727           0 :             if (!nNewViewPos)
    1728           0 :                 break;
    1729             :             else
    1730           0 :                 --nNewViewPos;
    1731             :         }
    1732             :     }
    1733             :     DBG_ASSERT( nNewModelPos < m_aColumns.size(), "DbGridControl::ColumnMoved : could not find the new model position !");
    1734             : 
    1735             :     // this will work. of course the model isn't fully consistent with our view right now, but let's
    1736             :     // look at the situation : a column has been moved with in the VIEW from pos m to n, say m<n (in the
    1737             :     // other case we can use analogue arguments).
    1738             :     // All cols k with m<k<=n have been shifted left on pos, the former col m now has pos n.
    1739             :     // In the model this affects a range of cols x to y, where x<=m and y<=n. And the number of hidden cols
    1740             :     // within this range is constant, so we may calculate the view pos from the model pos in the above way.
    1741             :     //
    1742             :     // for instance, let's look at a grid with six columns where the third one is hidden. this will
    1743             :     // initially look like this :
    1744             :     //
    1745             :     //              +---+---+---+---+---+---+
    1746             :     // model pos    | 0 | 1 |*2*| 3 | 4 | 5 |
    1747             :     //              +---+---+---+---+---+---+
    1748             :     // ID           | 1 | 2 | 3 | 4 | 5 | 6 |
    1749             :     //              +---+---+---+---+---+---+
    1750             :     // view pos     | 0 | 1 | - | 2 | 3 | 4 |
    1751             :     //              +---+---+---+---+---+---+
    1752             :     //
    1753             :     // if we move the column at (view) pos 1 to (view) pos 3 we have :
    1754             :     //
    1755             :     //              +---+---+---+---+---+---+
    1756             :     // model pos    | 0 | 3 |*2*| 4 | 1 | 5 |   // not reflecting the changes, yet
    1757             :     //              +---+---+---+---+---+---+
    1758             :     // ID           | 1 | 4 | 3 | 5 | 2 | 6 |   // already reflecting the changes
    1759             :     //              +---+---+---+---+---+---+
    1760             :     // view pos     | 0 | 1 | - | 2 | 3 | 4 |
    1761             :     //              +---+---+---+---+---+---+
    1762             :     //
    1763             :     // or, sorted by the out-of-date model positions :
    1764             :     //
    1765             :     //              +---+---+---+---+---+---+
    1766             :     // model pos    | 0 | 1 |*2*| 3 | 4 | 5 |
    1767             :     //              +---+---+---+---+---+---+
    1768             :     // ID           | 1 | 2 | 3 | 4 | 5 | 6 |
    1769             :     //              +---+---+---+---+---+---+
    1770             :     // view pos     | 0 | 3 | - | 1 | 2 | 4 |
    1771             :     //              +---+---+---+---+---+---+
    1772             :     //
    1773             :     // We know the new view pos (3) of the moved column because our base class tells us. So we look at our
    1774             :     // model for the 4th (the pos is zero-based) visible column, it is at (model) position 4. And this is
    1775             :     // exactly the pos where we have to re-insert our column's model, so it looks ike this :
    1776             :     //
    1777             :     //              +---+---+---+---+---+---+
    1778             :     // model pos    | 0 |*1*| 2 | 3 | 4 | 5 |
    1779             :     //              +---+---+---+---+---+---+
    1780             :     // ID           | 1 | 3 | 4 | 5 | 2 | 6 |
    1781             :     //              +---+---+---+---+---+---+
    1782             :     // view pos     | 0 | - | 1 | 2 | 3 | 4 |
    1783             :     //              +---+---+---+---+---+---+
    1784             :     //
    1785             :     // Now, all is consistent again.
    1786             :     // (except of the hidden column : The cycling of the cols occurred on the model, not on the view. maybe
    1787             :     // the user expected the latter but there really is no good argument against our method ;) ...)
    1788             :     //
    1789             :     // And no, this large explanation isn't just because I wanted to play a board game or something like
    1790             :     // that. It's because it took me a while to see it myself, and the whole theme (hidden cols, model col
    1791             :     // positions, view col positions)  is really painful (at least for me) so the above pictures helped me a lot ;)
    1792             : 
    1793             : 
    1794           0 :     DbGridColumn* temp = m_aColumns[ nOldModelPos ];
    1795             : 
    1796           0 :     DbGridColumns::iterator it = m_aColumns.begin();
    1797           0 :     ::std::advance( it, nOldModelPos );
    1798           0 :     m_aColumns.erase( it );
    1799             : 
    1800           0 :     it = m_aColumns.begin();
    1801           0 :     ::std::advance( it, nNewModelPos );
    1802           0 :     m_aColumns.insert( it, temp );
    1803           0 : }
    1804             : 
    1805             : //------------------------------------------------------------------------------
    1806           0 : sal_Bool DbGridControl::SeekRow(long nRow)
    1807             : {
    1808             :     // in filter mode or in insert only mode we don't have any cursor!
    1809           0 :     if ( !SeekCursor( nRow ) )
    1810           0 :         return sal_False;
    1811             : 
    1812           0 :     if ( IsFilterMode() )
    1813             :     {
    1814             :         DBG_ASSERT( IsFilterRow( nRow ), "DbGridControl::SeekRow(): No filter row, wrong mode" );
    1815           0 :         m_xPaintRow = m_xEmptyRow;
    1816             :     }
    1817             :     else
    1818             :     {
    1819             :         // on the current position we have to take the current row for display as we want
    1820             :         // to have the most recent values for display
    1821           0 :         if ( ( nRow == m_nCurrentPos ) && getDisplaySynchron() )
    1822           0 :             m_xPaintRow = m_xCurrentRow;
    1823             :         // seek to the empty insert row
    1824           0 :         else if ( IsInsertionRow( nRow ) )
    1825           0 :             m_xPaintRow = m_xEmptyRow;
    1826             :         else
    1827             :         {
    1828           0 :             m_xSeekRow->SetState( m_pSeekCursor, sal_True );
    1829           0 :             m_xPaintRow = m_xSeekRow;
    1830             :         }
    1831             :     }
    1832             : 
    1833           0 :     DbGridControl_Base::SeekRow(nRow);
    1834             : 
    1835           0 :     return m_nSeekPos >= 0;
    1836             : }
    1837             : //------------------------------------------------------------------------------
    1838             : // Wird aufgerufen, wenn die dargestellte Datenmenge sich aendert
    1839             : //------------------------------------------------------------------------------
    1840           0 : void DbGridControl::VisibleRowsChanged( long nNewTopRow, sal_uInt16 nLinesOnScreen )
    1841             : {
    1842           0 :     RecalcRows(nNewTopRow, nLinesOnScreen , sal_False);
    1843           0 : }
    1844             : 
    1845             : //------------------------------------------------------------------------------
    1846           0 : void DbGridControl::RecalcRows(long nNewTopRow, sal_uInt16 nLinesOnScreen, sal_Bool bUpdateCursor)
    1847             : {
    1848             :     DBG_CHKTHIS( DbGridControl, NULL );
    1849             :     // Wenn kein Cursor -> keine Rows im Browser.
    1850           0 :     if (!m_pSeekCursor)
    1851             :     {
    1852             :         DBG_ASSERT(GetRowCount() == 0,"DbGridControl: ohne Cursor darf es keine Rows geben");
    1853           0 :         return;
    1854             :     }
    1855             : 
    1856             :     // ignore any updates implicit made
    1857           0 :     sal_Bool bDisablePaint = !bUpdateCursor && IsPaintEnabled();
    1858           0 :     if (bDisablePaint)
    1859           0 :         EnablePaint(sal_False);
    1860             : 
    1861             :     // Cache an den sichtbaren Bereich anpassen
    1862           0 :     Reference< XPropertySet > xSet = m_pSeekCursor->getPropertySet();
    1863           0 :     sal_Int32 nCacheSize = 0;
    1864           0 :     xSet->getPropertyValue(FM_PROP_FETCHSIZE) >>= nCacheSize;
    1865           0 :     sal_Bool bCacheAligned   = sal_False;
    1866             :     // Nach der Initialisierung (m_nSeekPos < 0) keine Cursorbewegung, da bereits auf den ersten
    1867             :     // Satz positioniert
    1868           0 :     long nDelta = nNewTopRow - GetTopRow();
    1869             :     // Limit fuer relative Positionierung
    1870           0 :     long nLimit = (nCacheSize) ? nCacheSize / 2 : 0;
    1871             : 
    1872             :     // mehr Zeilen auf dem Bildschirm als im Cache
    1873           0 :     if (nLimit < nLinesOnScreen)
    1874             :     {
    1875           0 :         Any aCacheSize;
    1876           0 :         aCacheSize <<= sal_Int32(nLinesOnScreen*2);
    1877           0 :         xSet->setPropertyValue(FM_PROP_FETCHSIZE, aCacheSize);
    1878             :         // jetzt auf alle Faelle den Cursor anpassen
    1879           0 :         bUpdateCursor = sal_True;
    1880           0 :         bCacheAligned = sal_True;
    1881           0 :         nLimit = nLinesOnScreen;
    1882             :     }
    1883             : 
    1884             :     // Im folgenden werden die Positionierungen so vorgenommen, da� sichergestellt ist
    1885             :     // da� ausreichend Zeilen im DatenCache vorhanden sind
    1886             : 
    1887             :     // Fenster geht nach unten, weniger als zwei Fenster Differenz
    1888             :     // oder Cache angepasst und noch kein Rowcount
    1889           0 :     if (nDelta < nLimit && (nDelta > 0
    1890             :         || (bCacheAligned && m_nTotalCount < 0)) )
    1891           0 :         SeekCursor(nNewTopRow + nLinesOnScreen - 1, sal_False);
    1892           0 :     else if (nDelta < 0 && Abs(nDelta) < nLimit)
    1893           0 :         SeekCursor(nNewTopRow, sal_False);
    1894           0 :     else if (nDelta != 0 || bUpdateCursor)
    1895           0 :         SeekCursor(nNewTopRow, sal_True);
    1896             : 
    1897           0 :     AdjustRows();
    1898             : 
    1899             :     // ignore any updates implicit made
    1900           0 :     EnablePaint(sal_True);
    1901             : }
    1902             : 
    1903             : //------------------------------------------------------------------------------
    1904           0 : void DbGridControl::RowInserted(long nRow, long nNumRows, sal_Bool bDoPaint, sal_Bool bKeepSelection)
    1905             : {
    1906           0 :     if (nNumRows)
    1907             :     {
    1908           0 :         if (m_bRecordCountFinal && m_nTotalCount < 0)
    1909             :         {
    1910             :             // if we have an insert row we have to reduce to count by 1
    1911             :             // as the total count reflects only the existing rows in database
    1912           0 :             m_nTotalCount = GetRowCount() + nNumRows;
    1913           0 :             if (m_xEmptyRow.Is())
    1914           0 :                 --m_nTotalCount;
    1915             :         }
    1916           0 :         else if (m_nTotalCount >= 0)
    1917           0 :             m_nTotalCount += nNumRows;
    1918             : 
    1919           0 :         DbGridControl_Base::RowInserted(nRow, nNumRows, bDoPaint, bKeepSelection);
    1920           0 :         m_aBar.InvalidateState(NavigationBar::RECORD_COUNT);
    1921             :     }
    1922           0 : }
    1923             : 
    1924             : //------------------------------------------------------------------------------
    1925           0 : void DbGridControl::RowRemoved(long nRow, long nNumRows, sal_Bool bDoPaint)
    1926             : {
    1927           0 :     if (nNumRows)
    1928             :     {
    1929           0 :         if (m_bRecordCountFinal && m_nTotalCount < 0)
    1930             :         {
    1931           0 :             m_nTotalCount = GetRowCount() - nNumRows;
    1932             :             // if we have an insert row reduce by 1
    1933           0 :             if (m_xEmptyRow.Is())
    1934           0 :                 --m_nTotalCount;
    1935             :         }
    1936           0 :         else if (m_nTotalCount >= 0)
    1937           0 :             m_nTotalCount -= nNumRows;
    1938             : 
    1939           0 :         DbGridControl_Base::RowRemoved(nRow, nNumRows, bDoPaint);
    1940           0 :         m_aBar.InvalidateState(NavigationBar::RECORD_COUNT);
    1941             :     }
    1942           0 : }
    1943             : 
    1944             : //------------------------------------------------------------------------------
    1945           0 : void DbGridControl::AdjustRows()
    1946             : {
    1947           0 :     if (!m_pSeekCursor)
    1948           0 :         return;
    1949             : 
    1950           0 :     Reference< XPropertySet > xSet = m_pDataCursor->getPropertySet();
    1951             : 
    1952             :     // Aktualisieren des RecordCounts
    1953           0 :     sal_Int32 nRecordCount = 0;
    1954           0 :     xSet->getPropertyValue(FM_PROP_ROWCOUNT) >>= nRecordCount;
    1955           0 :     if (!m_bRecordCountFinal)
    1956           0 :         m_bRecordCountFinal = ::comphelper::getBOOL(xSet->getPropertyValue(FM_PROP_ROWCOUNTFINAL));
    1957             : 
    1958             :     // hat sich die aktuelle Anzahl Rows veraendert
    1959             :     // hierbei muss auch beruecksichtigt werden,
    1960             :     // das eine zusaetzliche Zeile zum einfuegen von Datensaetzen vorhanden sein kann
    1961             : 
    1962             :     // zusaetzliche AppendRow fuers einfuegen
    1963           0 :     if (m_nOptions & OPT_INSERT)
    1964           0 :         ++nRecordCount;
    1965             : 
    1966             :     // wird gerade eingefuegt, dann gehoert die gerade hinzuzufuegende
    1967             :     // Zeile nicht zum RecordCount und die Appendrow ebenfalls nicht
    1968           0 :     if (!IsUpdating() && m_bRecordCountFinal && IsModified() && m_xCurrentRow != m_xEmptyRow &&
    1969           0 :         m_xCurrentRow->IsNew())
    1970           0 :         ++nRecordCount;
    1971             :     // das ist mit !m_bUpdating abgesichert : innerhalb von SaveRow (m_bUpdating == sal_True) wuerde sonst der Datensatz, den ich editiere
    1972             :     // (und den SaveRow gerade angefuegt hat, wodurch diese Methode hier getriggert wurde), doppelt zaehlen : einmal ist er schon
    1973             :     // in dem normalen RecordCount drin, zum zweiten wuerde er hier gezaehlt werden (60787 - FS)
    1974             : 
    1975           0 :     if (nRecordCount != GetRowCount())
    1976             :     {
    1977           0 :         long nDelta = GetRowCount() - (long)nRecordCount;
    1978           0 :         if (nDelta > 0)                                         // zuviele
    1979             :         {
    1980           0 :             RowRemoved(GetRowCount() - nDelta, nDelta, sal_False);
    1981             :             // es sind Zeilen weggefallen, dann ab der aktuellen Position neu zeichen
    1982           0 :             Invalidate();
    1983             : 
    1984           0 :             sal_Int32 nNewPos = AlignSeekCursor();
    1985           0 :             if (m_bSynchDisplay)
    1986           0 :                 DbGridControl_Base::GoToRow(nNewPos);
    1987             : 
    1988           0 :             SetCurrent(nNewPos);
    1989             :             // there are rows so go to the selected current column
    1990           0 :             if (nRecordCount)
    1991           0 :                 GoToRowColumnId(nNewPos, GetColumnId(GetCurColumnId()));
    1992           0 :             if (!IsResizing() && GetRowCount())
    1993           0 :                 RecalcRows(GetTopRow(), GetVisibleRows(), sal_True);
    1994           0 :             m_aBar.InvalidateAll(m_nCurrentPos, sal_True);
    1995             :         }
    1996             :         else                                                    // zuwenig
    1997           0 :             RowInserted(GetRowCount(), -nDelta, sal_True);
    1998             :     }
    1999             : 
    2000           0 :     if (m_bRecordCountFinal && m_nTotalCount < 0)
    2001             :     {
    2002           0 :         if (m_nOptions & OPT_INSERT)
    2003           0 :             m_nTotalCount = GetRowCount() - 1;
    2004             :         else
    2005           0 :             m_nTotalCount = GetRowCount();
    2006             :     }
    2007           0 :     m_aBar.InvalidateState(NavigationBar::RECORD_COUNT);
    2008             : }
    2009             : 
    2010             : //------------------------------------------------------------------------------
    2011           0 : DbGridControl_Base::RowStatus DbGridControl::GetRowStatus(long nRow) const
    2012             : {
    2013           0 :     if (IsFilterRow(nRow))
    2014           0 :         return DbGridControl_Base::FILTER;
    2015           0 :     else if (m_nCurrentPos >= 0 && nRow == m_nCurrentPos)
    2016             :     {
    2017             :         // neue Zeile
    2018           0 :         if (!IsValid(m_xCurrentRow))
    2019           0 :             return DbGridControl_Base::DELETED;
    2020           0 :         else if (IsModified())
    2021           0 :             return DbGridControl_Base::MODIFIED;
    2022           0 :         else if (m_xCurrentRow->IsNew())
    2023           0 :             return DbGridControl_Base::CURRENTNEW;
    2024             :         else
    2025           0 :             return DbGridControl_Base::CURRENT;
    2026             :     }
    2027           0 :     else if (IsInsertionRow(nRow))
    2028           0 :         return DbGridControl_Base::NEW;
    2029           0 :     else if (!IsValid(m_xSeekRow))
    2030           0 :         return DbGridControl_Base::DELETED;
    2031             :     else
    2032           0 :         return DbGridControl_Base::CLEAN;
    2033             : }
    2034             : 
    2035             : //------------------------------------------------------------------------------
    2036           0 : void DbGridControl::PaintStatusCell(OutputDevice& rDev, const Rectangle& rRect) const
    2037             : {
    2038           0 :     DbGridControl_Base::PaintStatusCell(rDev, rRect);
    2039           0 : }
    2040             : 
    2041             : //------------------------------------------------------------------------------
    2042           0 : void DbGridControl::PaintCell(OutputDevice& rDev, const Rectangle& rRect, sal_uInt16 nColumnId) const
    2043             : {
    2044           0 :     if (!IsValid(m_xPaintRow))
    2045           0 :         return;
    2046             : 
    2047           0 :     size_t Location = GetModelColumnPos(nColumnId);
    2048           0 :     DbGridColumn* pColumn = (Location < m_aColumns.size() ) ? m_aColumns[ Location ] : NULL;
    2049           0 :     if (pColumn)
    2050             :     {
    2051           0 :         Rectangle aArea(rRect);
    2052           0 :         if ((GetMode() & BROWSER_CURSOR_WO_FOCUS) == BROWSER_CURSOR_WO_FOCUS)
    2053             :         {
    2054           0 :             aArea.Top() += 1;
    2055           0 :             aArea.Bottom() -= 1;
    2056             :         }
    2057           0 :         pColumn->Paint(rDev, aArea, m_xPaintRow, getNumberFormatter());
    2058             :     }
    2059             : }
    2060             : 
    2061             : //------------------------------------------------------------------------------
    2062           0 : sal_Bool DbGridControl::CursorMoving(long nNewRow, sal_uInt16 nNewCol)
    2063             : {
    2064             :     DBG_CHKTHIS( DbGridControl, NULL );
    2065             : 
    2066           0 :     DeactivateCell( sal_False );
    2067             : 
    2068           0 :     if  (   m_pDataCursor
    2069             :         &&  ( m_nCurrentPos != nNewRow )
    2070           0 :         && !SetCurrent( nNewRow )
    2071             :         )
    2072             :     {
    2073           0 :         ActivateCell();
    2074           0 :         return sal_False;
    2075             :     }
    2076             : 
    2077           0 :     if ( !DbGridControl_Base::CursorMoving( nNewRow, nNewCol ) )
    2078           0 :         return sal_False;
    2079             : 
    2080           0 :     return sal_True;
    2081             : }
    2082             : 
    2083             : //------------------------------------------------------------------------------
    2084           0 : sal_Bool DbGridControl::SetCurrent(long nNewRow)
    2085             : {
    2086             :     // Each movement of the datacursor must start with BeginCursorAction and end with
    2087             :     // EndCursorAction to block all notifications during the movement
    2088           0 :     BeginCursorAction();
    2089             : 
    2090             :     try
    2091             :     {
    2092             :         // Abgleichen der Positionen
    2093           0 :         if (SeekCursor(nNewRow))
    2094             :         {
    2095           0 :             if (IsFilterRow(nNewRow))   // special mode for filtering
    2096             :             {
    2097           0 :                 m_xCurrentRow = m_xDataRow = m_xPaintRow = m_xEmptyRow;
    2098           0 :                 m_nCurrentPos = nNewRow;
    2099             :             }
    2100             :             else
    2101             :             {
    2102           0 :                 sal_Bool bNewRowInserted = sal_False;
    2103             :                 // Should we go to the insertrow ?
    2104           0 :                 if (IsInsertionRow(nNewRow))
    2105             :                 {
    2106             :                     // to we need to move the cursor to the insert row?
    2107             :                     // we need to insert the if the current row isn't the insert row or if the
    2108             :                     // cursor triggered the move by itselt and we need a reinitialization of the row
    2109           0 :                     Reference< XPropertySet > xCursorProps = m_pDataCursor->getPropertySet();
    2110           0 :                     if ( !::comphelper::getBOOL(xCursorProps->getPropertyValue(FM_PROP_ISNEW)) )
    2111             :                     {
    2112           0 :                         Reference< XResultSetUpdate > xUpdateCursor((Reference< XInterface >)*m_pDataCursor, UNO_QUERY);
    2113           0 :                         xUpdateCursor->moveToInsertRow();
    2114             :                     }
    2115           0 :                     bNewRowInserted = sal_True;
    2116             :                 }
    2117             :                 else
    2118             :                 {
    2119             : 
    2120           0 :                     if ( !m_pSeekCursor->isBeforeFirst() && !m_pSeekCursor->isAfterLast() )
    2121             :                     {
    2122           0 :                         Any aBookmark = m_pSeekCursor->getBookmark();
    2123           0 :                         if (!m_xCurrentRow || m_xCurrentRow->IsNew() || !CompareBookmark(aBookmark, m_pDataCursor->getBookmark()))
    2124             :                         {
    2125             :                             // adjust the cursor to the new desired row
    2126           0 :                             if (!m_pDataCursor->moveToBookmark(aBookmark))
    2127             :                             {
    2128           0 :                                 EndCursorAction();
    2129           0 :                                 return sal_False;
    2130             :                             }
    2131           0 :                         }
    2132             :                     }
    2133             :                 }
    2134           0 :                 m_xDataRow->SetState(m_pDataCursor, sal_False);
    2135           0 :                 m_xCurrentRow = m_xDataRow;
    2136             : 
    2137           0 :                 long nPaintPos = -1;
    2138             :                 // do we have to repaint the last regular row in case of setting defaults or autovalues
    2139           0 :                 if (m_nCurrentPos >= 0 && m_nCurrentPos >= (GetRowCount() - 2))
    2140           0 :                     nPaintPos = m_nCurrentPos;
    2141             : 
    2142           0 :                 m_nCurrentPos = nNewRow;
    2143             : 
    2144             :                 // repaint the new row to display all defaults
    2145           0 :                 if (bNewRowInserted)
    2146           0 :                     RowModified(m_nCurrentPos);
    2147           0 :                 if (nPaintPos >= 0)
    2148           0 :                     RowModified(nPaintPos);
    2149             :             }
    2150             :         }
    2151             :         else
    2152             :         {
    2153             :             OSL_FAIL("DbGridControl::SetCurrent : SeekRow failed !");
    2154           0 :             EndCursorAction();
    2155           0 :             return sal_False;
    2156             :         }
    2157             :     }
    2158           0 :     catch ( const Exception& )
    2159             :     {
    2160             :         DBG_UNHANDLED_EXCEPTION();
    2161           0 :         EndCursorAction();
    2162           0 :         return sal_False;
    2163             :     }
    2164             : 
    2165           0 :     EndCursorAction();
    2166           0 :     return sal_True;
    2167             : }
    2168             : 
    2169             : //------------------------------------------------------------------------------
    2170           0 : void DbGridControl::CursorMoved()
    2171             : {
    2172             :     DBG_CHKTHIS( DbGridControl, NULL );
    2173             : 
    2174             :     // CursorBewegung durch loeschen oder einfuegen von Zeilen
    2175           0 :     if (m_pDataCursor && m_nCurrentPos != GetCurRow())
    2176             :     {
    2177           0 :         DeactivateCell(sal_True);
    2178           0 :         SetCurrent(GetCurRow());
    2179             :     }
    2180             : 
    2181           0 :     DbGridControl_Base::CursorMoved();
    2182           0 :     m_aBar.InvalidateAll(m_nCurrentPos);
    2183             : 
    2184             :     // select the new column when they moved
    2185           0 :     if ( IsDesignMode() && GetSelectedColumnCount() > 0 && GetCurColumnId() )
    2186             :     {
    2187           0 :         SelectColumnId( GetCurColumnId() );
    2188             :     }
    2189             : 
    2190           0 :     if ( m_nLastColId != GetCurColumnId() )
    2191           0 :         onColumnChange();
    2192           0 :     m_nLastColId = GetCurColumnId();
    2193             : 
    2194           0 :     if ( m_nLastRowId != GetCurRow() )
    2195           0 :         onRowChange();
    2196           0 :     m_nLastRowId = GetCurRow();
    2197           0 : }
    2198             : 
    2199             : //------------------------------------------------------------------------------
    2200           0 : void DbGridControl::onRowChange()
    2201             : {
    2202             :     // not interested in
    2203           0 : }
    2204             : 
    2205             : //------------------------------------------------------------------------------
    2206           0 : void DbGridControl::onColumnChange()
    2207             : {
    2208           0 :     if ( m_pGridListener )
    2209           0 :         m_pGridListener->columnChanged();
    2210           0 : }
    2211             : 
    2212             : //------------------------------------------------------------------------------
    2213           0 : void DbGridControl::setDisplaySynchron(sal_Bool bSync)
    2214             : {
    2215           0 :     if (bSync != m_bSynchDisplay)
    2216             :     {
    2217           0 :         m_bSynchDisplay = bSync;
    2218           0 :         if (m_bSynchDisplay)
    2219           0 :             AdjustDataSource(sal_False);
    2220             :     }
    2221           0 : }
    2222             : 
    2223             : //------------------------------------------------------------------------------
    2224           0 : void DbGridControl::AdjustDataSource(sal_Bool bFull)
    2225             : {
    2226             :     TRACE_RANGE("DbGridControl::AdjustDataSource");
    2227           0 :     SolarMutexGuard aGuard;
    2228             :     // wird die aktuelle Zeile gerade neu bestimmt,
    2229             :     // wird kein abgleich vorgenommen
    2230             : 
    2231           0 :     if (bFull)
    2232           0 :         m_xCurrentRow = NULL;
    2233             :     // if we are on the same row only repaint
    2234             :     // but this is only possible for rows which are not inserted, in that case the comparision result
    2235             :     // may not be correct
    2236             :     else
    2237           0 :         if  (   m_xCurrentRow.Is()
    2238           0 :             &&  !m_xCurrentRow->IsNew()
    2239           0 :             &&  !m_pDataCursor->isBeforeFirst()
    2240           0 :             &&  !m_pDataCursor->isAfterLast()
    2241           0 :             &&  !m_pDataCursor->rowDeleted()
    2242             :             )
    2243             :         {
    2244           0 :             sal_Bool bEqualBookmarks = CompareBookmark( m_xCurrentRow->GetBookmark(), m_pDataCursor->getBookmark() );
    2245             : 
    2246           0 :             sal_Bool bDataCursorIsOnNew = sal_False;
    2247           0 :             m_pDataCursor->getPropertySet()->getPropertyValue( FM_PROP_ISNEW ) >>= bDataCursorIsOnNew;
    2248             : 
    2249           0 :             if ( bEqualBookmarks && !bDataCursorIsOnNew )
    2250             :             {
    2251             :                 // position of my data cursor is the same as the position our current row points tpo
    2252             :                 // sync the status, repaint, done
    2253             :                 DBG_ASSERT(m_xDataRow == m_xCurrentRow, "Fehler in den Datenzeilen");
    2254             :                 TRACE_RANGE_MESSAGE1("same position, new state : %s", ROWSTATUS(m_xCurrentRow));
    2255           0 :                 RowModified(m_nCurrentPos);
    2256             :                 return;
    2257             :             }
    2258             :         }
    2259             : 
    2260             :     // weg von der Row des DatenCursors
    2261           0 :     if (m_xPaintRow == m_xCurrentRow)
    2262           0 :         m_xPaintRow = m_xSeekRow;
    2263             : 
    2264             :     // keine aktuelle Zeile dann komplett anpassen
    2265           0 :     if (!m_xCurrentRow)
    2266           0 :         AdjustRows();
    2267             : 
    2268           0 :     sal_Int32 nNewPos = AlignSeekCursor();
    2269           0 :     if (nNewPos < 0)    // keine Position gefunden
    2270             :         return;
    2271             : 
    2272           0 :     m_bInAdjustDataSource = sal_True;
    2273           0 :     if (nNewPos != m_nCurrentPos)
    2274             :     {
    2275           0 :         if (m_bSynchDisplay)
    2276           0 :             DbGridControl_Base::GoToRow(nNewPos);
    2277             : 
    2278           0 :         if (!m_xCurrentRow.Is())
    2279             :             // das tritt zum Beispiel auf, wenn man die n (n>1) letzten Datensaetze geloescht hat, waehrend der Cursor auf dem letzten
    2280             :             // steht : AdjustRows entfernt dann zwei Zeilen aus der BrowseBox, wodurch diese ihre CurrentRow um zwei nach unten
    2281             :             // korrigiert, so dass dann das GoToRow in's Leere laeuft (da wir uns ja angeblich schon an der richtigen Position
    2282             :             // befinden)
    2283           0 :             SetCurrent(nNewPos);
    2284             :     }
    2285             :     else
    2286             :     {
    2287           0 :         SetCurrent(nNewPos);
    2288           0 :         RowModified(nNewPos);
    2289             :     }
    2290           0 :     m_bInAdjustDataSource = sal_False;
    2291             : 
    2292             :     // Wird der DatenCursor von aussen bewegt, wird die selektion aufgehoben
    2293           0 :     SetNoSelection();
    2294           0 :     m_aBar.InvalidateAll(m_nCurrentPos, m_xCurrentRow.Is());
    2295             : }
    2296             : 
    2297             : //------------------------------------------------------------------------------
    2298           0 : sal_Int32 DbGridControl::AlignSeekCursor()
    2299             : {
    2300             :     DBG_CHKTHIS( DbGridControl, NULL );
    2301             :     // Positioniert den SeekCursor auf den DatenCursor, Daten werden nicht uebertragen
    2302             : 
    2303           0 :     if (!m_pSeekCursor)
    2304           0 :         return -1;
    2305             : 
    2306           0 :     Reference< XPropertySet > xSet = m_pDataCursor->getPropertySet();
    2307             : 
    2308             :     // jetzt den seekcursor an den DatenCursor angleichen
    2309           0 :     if (::comphelper::getBOOL(xSet->getPropertyValue(FM_PROP_ISNEW)))
    2310           0 :         m_nSeekPos = GetRowCount() - 1;
    2311             :     else
    2312             :     {
    2313             :         try
    2314             :         {
    2315           0 :             if ( m_pDataCursor->isBeforeFirst() )
    2316             :             {
    2317             :                 // this is somewhat strange, but can nevertheless happen
    2318             :                 DBG_WARNING( "DbGridControl::AlignSeekCursor: nobody should tamper with my cursor this way (before first)!" );
    2319           0 :                 m_pSeekCursor->first();
    2320           0 :                 m_pSeekCursor->previous();
    2321           0 :                 m_nSeekPos = -1;
    2322             :             }
    2323           0 :             else if ( m_pDataCursor->isAfterLast() )
    2324             :             {
    2325             :                 DBG_WARNING( "DbGridControl::AlignSeekCursor: nobody should tamper with my cursor this way (after last)!" );
    2326           0 :                 m_pSeekCursor->last();
    2327           0 :                 m_pSeekCursor->next();
    2328           0 :                 m_nSeekPos = -1;
    2329             :             }
    2330             :             else
    2331             :             {
    2332           0 :                 m_pSeekCursor->moveToBookmark(m_pDataCursor->getBookmark());
    2333           0 :                 if (!CompareBookmark(m_pDataCursor->getBookmark(), m_pSeekCursor->getBookmark()))
    2334             :                     // dummerweise kann das moveToBookmark indirekt dazu fuehren, dass der Seek-Cursor wieder neu positoniert wird (wenn
    2335             :                     // naemlich das mit all seinen zu feuernden Events relativ komplexe moveToBookmark irgendwo ein Update ausloest),
    2336             :                     // also muss ich es nochmal versuchen
    2337           0 :                     m_pSeekCursor->moveToBookmark(m_pDataCursor->getBookmark());
    2338             :                     // Nicht dass das jetzt nicht auch schief gegangen sein koennte, aber es ist zumindest unwahrscheinlicher geworden.
    2339             :                     // Und die Alternative waere eine Schleife so lange bis es stimmt, und das kann auch nicht die Loesung sein
    2340           0 :                 m_nSeekPos = m_pSeekCursor->getRow() - 1;
    2341             :             }
    2342             :         }
    2343           0 :         catch(Exception&)
    2344             :         {
    2345             :         }
    2346             :     }
    2347           0 :     return m_nSeekPos;
    2348             : }
    2349             : //------------------------------------------------------------------------------
    2350           0 : sal_Bool DbGridControl::SeekCursor(long nRow, sal_Bool bAbsolute)
    2351             : {
    2352             :     DBG_CHKTHIS( DbGridControl, NULL );
    2353             :     // Positioniert den SeekCursor, Daten werden nicht uebertragen
    2354             : 
    2355             :     // additions for the filtermode
    2356           0 :     if (IsFilterRow(nRow))
    2357             :     {
    2358           0 :         m_nSeekPos = 0;
    2359           0 :         return sal_True;
    2360             :     }
    2361             : 
    2362           0 :     if (!m_pSeekCursor)
    2363           0 :         return sal_False;
    2364             : 
    2365             :     // Befinden wir uns gerade beim Einfuegen
    2366           0 :     if (IsValid(m_xCurrentRow) && m_xCurrentRow->IsNew() &&
    2367             :         nRow >= m_nCurrentPos)
    2368             :     {
    2369             :         // dann darf auf alle Faelle nicht weiter nach unten gescrollt werden
    2370             :         // da der letzte Datensatz bereits erreicht wurde!
    2371           0 :         if (nRow == m_nCurrentPos)
    2372             :         {
    2373             :             // auf die aktuelle Zeile bewegt, dann muß kein abgleich gemacht werden, wenn
    2374             :             // gerade ein Datensatz eingefuegt wird
    2375           0 :             m_nSeekPos = nRow;
    2376             :         }
    2377           0 :         else if (IsInsertionRow(nRow))  // Leerzeile zum Einfuegen von Datensaetzen
    2378           0 :             m_nSeekPos = nRow;
    2379             :     }
    2380           0 :     else if (IsInsertionRow(nRow))  // Leerzeile zum Einfuegen von Datensaetzen
    2381           0 :         m_nSeekPos = nRow;
    2382           0 :     else if ((-1 == nRow) && (GetRowCount() == ((m_nOptions & OPT_INSERT) ? 1 : 0)) && m_pSeekCursor->isAfterLast())
    2383           0 :         m_nSeekPos = nRow;
    2384             :     else
    2385             :     {
    2386             : 
    2387           0 :         sal_Bool bSuccess=sal_False;
    2388           0 :         long nSteps = 0;
    2389             :         try
    2390             :         {
    2391           0 :             if ( m_pSeekCursor->rowDeleted() )
    2392             :             {
    2393             :                 // somebody deleted the current row of the seek cursor. Move it away from this row.
    2394           0 :                 m_pSeekCursor->next();
    2395           0 :                 if ( m_pSeekCursor->isAfterLast() || m_pSeekCursor->isBeforeFirst() )
    2396           0 :                     bAbsolute = sal_True;
    2397             :             }
    2398             : 
    2399           0 :             if ( !bAbsolute )
    2400             :             {
    2401             :                 DBG_ASSERT( !m_pSeekCursor->isAfterLast() && !m_pSeekCursor->isBeforeFirst(),
    2402             :                     "DbGridControl::SeekCursor: how did the seek cursor get to this position?!" );
    2403           0 :                 nSteps = nRow - (m_pSeekCursor->getRow() - 1);
    2404           0 :                 bAbsolute = bAbsolute || (abs(nSteps) > 100);
    2405             :             }
    2406             : 
    2407           0 :             if ( bAbsolute )
    2408             :             {
    2409           0 :                 bSuccess = m_pSeekCursor->absolute(nRow + 1);
    2410           0 :                 if (bSuccess)
    2411           0 :                     m_nSeekPos = nRow;
    2412             :             }
    2413             :             else
    2414             :             {
    2415           0 :                 if (nSteps > 0)                                 // auf den letzten benoetigten Datensatz positionieren
    2416             :                 {
    2417           0 :                     if (m_pSeekCursor->isAfterLast())
    2418           0 :                         bSuccess = sal_False;
    2419           0 :                     else if (m_pSeekCursor->isBeforeFirst())
    2420           0 :                         bSuccess = m_pSeekCursor->absolute(nSteps);
    2421             :                     else
    2422           0 :                         bSuccess = m_pSeekCursor->relative(nSteps);
    2423             :                 }
    2424           0 :                 else if (nSteps < 0)
    2425             :                 {
    2426           0 :                     if (m_pSeekCursor->isBeforeFirst())
    2427           0 :                         bSuccess = sal_False;
    2428           0 :                     else if (m_pSeekCursor->isAfterLast())
    2429           0 :                         bSuccess = m_pSeekCursor->absolute(nSteps);
    2430             :                     else
    2431           0 :                         bSuccess = m_pSeekCursor->relative(nSteps);
    2432             :                 }
    2433             :                 else
    2434             :                 {
    2435           0 :                     m_nSeekPos = nRow;
    2436           0 :                     return sal_True;
    2437             :                 }
    2438             :             }
    2439             :         }
    2440           0 :         catch(Exception&)
    2441             :         {
    2442             :             OSL_FAIL("DbGridControl::SeekCursor : failed ...");
    2443             :         }
    2444             : 
    2445             :         try
    2446             :         {
    2447           0 :             if (!bSuccess)
    2448             :             {
    2449           0 :                 if (bAbsolute || nSteps > 0)
    2450             :                 {
    2451           0 :                     if (m_pSeekCursor->isLast())
    2452           0 :                         bSuccess=sal_True;
    2453             :                     else
    2454           0 :                         bSuccess = m_pSeekCursor->last();
    2455             :                 }
    2456             :                 else
    2457             :                 {
    2458           0 :                     if (m_pSeekCursor->isFirst())
    2459           0 :                         bSuccess = sal_True;
    2460             :                     else
    2461           0 :                         bSuccess = m_pSeekCursor->first();
    2462             :                 }
    2463             :             }
    2464             : 
    2465           0 :             if (bSuccess)
    2466           0 :                 m_nSeekPos = m_pSeekCursor->getRow() - 1;
    2467             :             else
    2468           0 :                 m_nSeekPos = -1;
    2469             :         }
    2470           0 :         catch(Exception&)
    2471             :         {
    2472             :             OSL_FAIL("DbGridControl::SeekCursor : failed ...");
    2473             :             DBG_UNHANDLED_EXCEPTION();
    2474           0 :             m_nSeekPos = -1;                        // kein Datensatz mehr vorhanden
    2475             :         }
    2476             :     }
    2477           0 :     return m_nSeekPos == nRow;
    2478             : }
    2479             : //------------------------------------------------------------------------------
    2480           0 : void DbGridControl::MoveToFirst()
    2481             : {
    2482           0 :     if (m_pSeekCursor && (GetCurRow() != 0))
    2483           0 :         MoveToPosition(0);
    2484           0 : }
    2485             : 
    2486             : //------------------------------------------------------------------------------
    2487           0 : void DbGridControl::MoveToLast()
    2488             : {
    2489           0 :     if (!m_pSeekCursor)
    2490           0 :         return;
    2491             : 
    2492           0 :     if (m_nTotalCount < 0)          // RecordCount steht noch nicht fest
    2493             :     {
    2494             :         try
    2495             :         {
    2496           0 :             sal_Bool bRes = m_pSeekCursor->last();
    2497             : 
    2498           0 :             if (bRes)
    2499             :             {
    2500           0 :                 m_nSeekPos = m_pSeekCursor->getRow() - 1;
    2501           0 :                 AdjustRows();
    2502             :             }
    2503             :         }
    2504           0 :         catch(Exception&)
    2505             :         {
    2506             :         }
    2507             :     }
    2508             : 
    2509             :     // auf den letzen Datensatz positionieren, nicht auf die Leerzeile
    2510           0 :     if (m_nOptions & OPT_INSERT)
    2511             :     {
    2512           0 :         if ((GetRowCount() - 1) > 0)
    2513           0 :             MoveToPosition(GetRowCount() - 2);
    2514             :     }
    2515           0 :     else if (GetRowCount())
    2516           0 :         MoveToPosition(GetRowCount() - 1);
    2517             : }
    2518             : 
    2519             : //------------------------------------------------------------------------------
    2520           0 : void DbGridControl::MoveToPrev()
    2521             : {
    2522           0 :     long nNewRow = std::max(GetCurRow() - 1L, 0L);
    2523           0 :     if (GetCurRow() != nNewRow)
    2524           0 :         MoveToPosition(nNewRow);
    2525           0 : }
    2526             : 
    2527             : //------------------------------------------------------------------------------
    2528           0 : void DbGridControl::MoveToNext()
    2529             : {
    2530           0 :     if (!m_pSeekCursor)
    2531           0 :         return;
    2532             : 
    2533           0 :     if (m_nTotalCount > 0)
    2534             :     {
    2535             :         // move the data cursor to the right position
    2536           0 :         long nNewRow = std::min(GetRowCount() - 1, GetCurRow() + 1);
    2537           0 :         if (GetCurRow() != nNewRow)
    2538           0 :             MoveToPosition(nNewRow);
    2539             :     }
    2540             :     else
    2541             :     {
    2542           0 :         sal_Bool bOk = sal_False;
    2543             :         try
    2544             :         {
    2545             :             // try to move to next row
    2546             :             // when not possible our paint cursor is already on the last row
    2547             :             // then we must be sure that the data cursor is on the position
    2548             :             // we call ourself again
    2549           0 :             bOk = m_pSeekCursor->next();
    2550           0 :             if (bOk)
    2551             :             {
    2552           0 :                 m_nSeekPos = m_pSeekCursor->getRow() - 1;
    2553           0 :                 MoveToPosition(GetCurRow() + 1);
    2554             :             }
    2555             :         }
    2556           0 :         catch(SQLException &)
    2557             :         {
    2558             :             DBG_UNHANDLED_EXCEPTION();
    2559             :         }
    2560             : 
    2561           0 :         if(!bOk)
    2562             :         {
    2563           0 :             AdjustRows();
    2564           0 :             if (m_nTotalCount > 0) // only to avoid infinte recursion
    2565           0 :                 MoveToNext();
    2566             :         }
    2567             :     }
    2568             : }
    2569             : 
    2570             : //------------------------------------------------------------------------------
    2571           0 : void DbGridControl::MoveToPosition(sal_uInt32 nPos)
    2572             : {
    2573           0 :     if (!m_pSeekCursor)
    2574           0 :         return;
    2575             : 
    2576           0 :     if (m_nTotalCount < 0 && (long)nPos >= GetRowCount())
    2577             :     {
    2578             :         try
    2579             :         {
    2580           0 :             if (!m_pSeekCursor->absolute(nPos + 1))
    2581             :             {
    2582           0 :                 AdjustRows();
    2583           0 :                 return;
    2584             :             }
    2585             :             else
    2586             :             {
    2587           0 :                 m_nSeekPos = m_pSeekCursor->getRow() - 1;
    2588           0 :                 AdjustRows();
    2589             :             }
    2590             :         }
    2591           0 :         catch(Exception&)
    2592             :         {
    2593             :             return;
    2594             :         }
    2595             :     }
    2596           0 :     DbGridControl_Base::GoToRow(nPos);
    2597           0 :     m_aBar.InvalidateAll(m_nCurrentPos);
    2598             : }
    2599             : 
    2600             : //------------------------------------------------------------------------------
    2601           0 : void DbGridControl::AppendNew()
    2602             : {
    2603           0 :     if (!m_pSeekCursor || !(m_nOptions & OPT_INSERT))
    2604           0 :         return;
    2605             : 
    2606           0 :     if (m_nTotalCount < 0)          // RecordCount steht noch nicht fest
    2607             :     {
    2608             :         try
    2609             :         {
    2610           0 :             sal_Bool bRes = m_pSeekCursor->last();
    2611             : 
    2612           0 :             if (bRes)
    2613             :             {
    2614           0 :                 m_nSeekPos = m_pSeekCursor->getRow() - 1;
    2615           0 :                 AdjustRows();
    2616             :             }
    2617             :         }
    2618           0 :         catch(Exception&)
    2619             :         {
    2620             :             return;
    2621             :         }
    2622             :     }
    2623             : 
    2624           0 :     long nNewRow = m_nTotalCount + 1;
    2625           0 :     if (nNewRow > 0 && GetCurRow() != nNewRow)
    2626           0 :         MoveToPosition(nNewRow - 1);
    2627             : }
    2628             : 
    2629             : //------------------------------------------------------------------------------
    2630           0 : void DbGridControl::SetDesignMode(sal_Bool bMode)
    2631             : {
    2632           0 :     if (IsDesignMode() != bMode)
    2633             :     {
    2634             :         // Enable/Disable f�r den Designmode anpassen damit die Headerbar konfigurierbar bleibt
    2635           0 :         if (bMode)
    2636             :         {
    2637           0 :             if (!IsEnabled())
    2638             :             {
    2639           0 :                 Enable();
    2640           0 :                 GetDataWindow().Disable();
    2641             :             }
    2642             :         }
    2643             :         else
    2644             :         {
    2645             :             // komplett disablen
    2646           0 :             if (!GetDataWindow().IsEnabled())
    2647           0 :                 Disable();
    2648             :         }
    2649             : 
    2650           0 :         m_bDesignMode = bMode;
    2651           0 :         GetDataWindow().SetMouseTransparent(bMode);
    2652           0 :         SetMouseTransparent(bMode);
    2653             : 
    2654           0 :         m_aBar.InvalidateAll(m_nCurrentPos, sal_True);
    2655             :     }
    2656           0 : }
    2657             : 
    2658             : //------------------------------------------------------------------------------
    2659           0 : void DbGridControl::SetFilterMode(sal_Bool bMode)
    2660             : {
    2661           0 :     if (IsFilterMode() != bMode)
    2662             :     {
    2663           0 :         m_bFilterMode = bMode;
    2664             : 
    2665           0 :         if (bMode)
    2666             :         {
    2667           0 :             SetUpdateMode(sal_False);
    2668             : 
    2669             :             // es gibt kein Cursor mehr
    2670           0 :             if (IsEditing())
    2671           0 :                 DeactivateCell();
    2672           0 :             RemoveRows(sal_False);
    2673             : 
    2674           0 :             m_xEmptyRow = new DbGridRow();
    2675             : 
    2676             :             // setting the new filter controls
    2677           0 :             for ( size_t i = 0; i < m_aColumns.size(); ++i )
    2678             :             {
    2679           0 :                 DbGridColumn* pCurCol = m_aColumns[ i ];
    2680           0 :                 if (!pCurCol->IsHidden())
    2681           0 :                     pCurCol->UpdateControl();
    2682             :             }
    2683             : 
    2684             :             // one row for filtering
    2685           0 :             RowInserted(0, 1, sal_True);
    2686           0 :             SetUpdateMode(sal_True);
    2687             :         }
    2688             :         else
    2689           0 :             setDataSource(Reference< XRowSet > ());
    2690             :     }
    2691           0 : }
    2692             : // -----------------------------------------------------------------------------
    2693           0 : String DbGridControl::GetCellText(long _nRow, sal_uInt16 _nColId) const
    2694             : {
    2695           0 :     size_t Location = GetModelColumnPos( _nColId );
    2696           0 :     DbGridColumn* pColumn = ( Location < m_aColumns.size() ) ? m_aColumns[ Location ] : NULL;
    2697           0 :     String sRet;
    2698           0 :     if ( const_cast<DbGridControl*>(this)->SeekRow(_nRow) )
    2699           0 :         sRet = GetCurrentRowCellText(pColumn, m_xPaintRow);
    2700           0 :     return sRet;
    2701             : }
    2702             : //------------------------------------------------------------------------------
    2703           0 : XubString DbGridControl::GetCurrentRowCellText(DbGridColumn* pColumn,const DbGridRowRef& _rRow) const
    2704             : {
    2705             :     // Ausgabe des Textes fuer eine Zelle
    2706           0 :     XubString aText;
    2707           0 :     if ( pColumn && IsValid(m_xPaintRow) )
    2708           0 :         aText = pColumn->GetCellText(_rRow, m_xFormatter);
    2709           0 :     return aText;
    2710             : }
    2711             : 
    2712             : //------------------------------------------------------------------------------
    2713           0 : sal_uInt32 DbGridControl::GetTotalCellWidth(long nRow, sal_uInt16 nColId)
    2714             : {
    2715           0 :     if (SeekRow(nRow))
    2716             :     {
    2717           0 :         size_t Location = GetModelColumnPos( nColId );
    2718           0 :         DbGridColumn* pColumn = ( Location < m_aColumns.size() ) ? m_aColumns[ Location ] : NULL;
    2719           0 :         return GetDataWindow().GetTextWidth(GetCurrentRowCellText(pColumn,m_xPaintRow));
    2720             :     }
    2721             :     else
    2722           0 :         return 30;  //xxxx
    2723             : }
    2724             : 
    2725             : //------------------------------------------------------------------------------
    2726           0 : void DbGridControl::PreExecuteRowContextMenu(sal_uInt16 /*nRow*/, PopupMenu& rMenu)
    2727             : {
    2728           0 :     sal_Bool bDelete = (m_nOptions & OPT_DELETE) && GetSelectRowCount() && !IsCurrentAppending();
    2729             :     // ist nur die Leerzeile selektiert, dann nicht loeschen
    2730           0 :     bDelete = bDelete && !((m_nOptions & OPT_INSERT) && GetSelectRowCount() == 1 && IsRowSelected(GetRowCount() - 1));
    2731             : 
    2732           0 :     rMenu.EnableItem(SID_FM_DELETEROWS, bDelete);
    2733           0 :     rMenu.EnableItem(SID_FM_RECORD_SAVE, IsModified());
    2734             : 
    2735             :     // the undo is more difficult
    2736           0 :     sal_Bool bCanUndo = IsModified();
    2737           0 :     long nState = -1;
    2738           0 :     if (m_aMasterStateProvider.IsSet())
    2739           0 :         nState = m_aMasterStateProvider.Call((void*)SID_FM_RECORD_UNDO);
    2740           0 :     bCanUndo &= ( 0 != nState );
    2741             : 
    2742           0 :     rMenu.EnableItem(SID_FM_RECORD_UNDO, bCanUndo);
    2743           0 : }
    2744             : 
    2745             : //------------------------------------------------------------------------------
    2746           0 : void DbGridControl::PostExecuteRowContextMenu(sal_uInt16 /*nRow*/, const PopupMenu& /*rMenu*/, sal_uInt16 nExecutionResult)
    2747             : {
    2748           0 :     switch (nExecutionResult)
    2749             :     {
    2750             :         case SID_FM_DELETEROWS:
    2751             :             // delete asynchron
    2752           0 :             if (m_nDeleteEvent)
    2753           0 :                 Application::RemoveUserEvent(m_nDeleteEvent);
    2754           0 :             m_nDeleteEvent = Application::PostUserEvent(LINK(this,DbGridControl,OnDelete));
    2755           0 :             break;
    2756             :         case SID_FM_RECORD_UNDO:
    2757           0 :             Undo();
    2758           0 :             break;
    2759             :         case SID_FM_RECORD_SAVE:
    2760           0 :             SaveRow();
    2761           0 :             break;
    2762             :         default:
    2763           0 :             break;
    2764             :     }
    2765           0 : }
    2766             : 
    2767             : //------------------------------------------------------------------------------
    2768           0 : void DbGridControl::DataSourcePropertyChanged(const PropertyChangeEvent& evt) throw( RuntimeException )
    2769             : {
    2770             :     TRACE_RANGE("DbGridControl::DataSourcePropertyChanged");
    2771           0 :     SolarMutexGuard aGuard;
    2772             :     // prop "IsModified" changed ?
    2773             :     // during update don't care about the modified state
    2774           0 :     if (!IsUpdating() && evt.PropertyName.compareTo(FM_PROP_ISMODIFIED) == COMPARE_EQUAL)
    2775             :     {
    2776           0 :         Reference< XPropertySet > xSource(evt.Source, UNO_QUERY);
    2777             :         DBG_ASSERT( xSource.is(), "DbGridControl::DataSourcePropertyChanged: invalid event source!" );
    2778           0 :         sal_Bool bIsNew = sal_False;
    2779           0 :         if (xSource.is())
    2780           0 :             bIsNew = ::comphelper::getBOOL(xSource->getPropertyValue(FM_PROP_ISNEW));
    2781             : 
    2782           0 :         if (bIsNew && m_xCurrentRow.Is())
    2783             :         {
    2784             :             DBG_ASSERT(::comphelper::getBOOL(xSource->getPropertyValue(FM_PROP_ROWCOUNTFINAL)), "DbGridControl::DataSourcePropertyChanged : somebody moved the form to a new record before the row count was final !");
    2785           0 :             sal_Int32 nRecordCount = 0;
    2786           0 :             xSource->getPropertyValue(FM_PROP_ROWCOUNT) >>= nRecordCount;
    2787           0 :             if (::comphelper::getBOOL(evt.NewValue))
    2788             :             {   // modified state changed from sal_False to sal_True and we're on a insert row
    2789             :                 // -> we've to add a new grid row
    2790           0 :                 if ((nRecordCount == GetRowCount() - 1)  && m_xCurrentRow->IsNew())
    2791             :                 {
    2792           0 :                     RowInserted(GetRowCount(), 1, sal_True);
    2793           0 :                     InvalidateStatusCell(m_nCurrentPos);
    2794           0 :                     m_aBar.InvalidateAll(m_nCurrentPos);
    2795             :                 }
    2796             :             }
    2797             :             else
    2798             :             {   // modified state changed from sal_True to sal_False and we're on a insert row
    2799             :                 // we have two "new row"s at the moment : the one we're editing currently (where the current
    2800             :                 // column is the only dirty element) and a "new new" row which is completely clean. As the first
    2801             :                 // one is about to be cleaned, too, the second one is obsolet now.
    2802           0 :                 if (m_xCurrentRow->IsNew() && nRecordCount == (GetRowCount() - 2))
    2803             :                 {
    2804           0 :                     RowRemoved(GetRowCount() - 1, 1, sal_True);
    2805           0 :                     InvalidateStatusCell(m_nCurrentPos);
    2806           0 :                     m_aBar.InvalidateAll(m_nCurrentPos);
    2807             :                 }
    2808             :             }
    2809             :         }
    2810           0 :         if (m_xCurrentRow.Is())
    2811             :         {
    2812           0 :             m_xCurrentRow->SetStatus(::comphelper::getBOOL(evt.NewValue) ? GRS_MODIFIED : GRS_CLEAN);
    2813           0 :             m_xCurrentRow->SetNew( bIsNew );
    2814           0 :             InvalidateStatusCell(m_nCurrentPos);
    2815             :             TRACE_RANGE_MESSAGE1("modified flag changed, new state : %s", ROWSTATUS(m_xCurrentRow));
    2816           0 :         }
    2817           0 :     }
    2818           0 : }
    2819             : 
    2820             : //------------------------------------------------------------------------------
    2821           0 : void DbGridControl::StartDrag( sal_Int8 /*nAction*/, const Point& rPosPixel )
    2822             : {
    2823           0 :     if (!m_pSeekCursor || IsResizing())
    2824           0 :         return;
    2825             : 
    2826           0 :     sal_uInt16 nColId = GetColumnAtXPosPixel(rPosPixel.X());
    2827           0 :     long   nRow = GetRowAtYPosPixel(rPosPixel.Y());
    2828           0 :     if (nColId != HandleColumnId && nRow >= 0)
    2829             :     {
    2830           0 :         if (GetDataWindow().IsMouseCaptured())
    2831           0 :             GetDataWindow().ReleaseMouse();
    2832             : 
    2833           0 :         size_t Location = GetModelColumnPos( nColId );
    2834           0 :         DbGridColumn* pColumn = ( Location < m_aColumns.size() ) ? m_aColumns[ Location ] : NULL;
    2835           0 :         OStringTransferable* pTransferable = new OStringTransferable(GetCurrentRowCellText(pColumn,m_xPaintRow));
    2836           0 :         Reference< XTransferable > xEnsureDelete(pTransferable);
    2837           0 :         pTransferable->StartDrag(this, DND_ACTION_COPY);
    2838             :     }
    2839             : }
    2840             : 
    2841             : //------------------------------------------------------------------------------
    2842           0 : sal_Bool DbGridControl::canCopyCellText(sal_Int32 _nRow, sal_Int16 _nColId)
    2843             : {
    2844             :     return  (_nRow >= 0)
    2845           0 :         &&  (_nRow < GetRowCount())
    2846             :         &&  (_nColId != HandleColumnId)
    2847           0 :         &&  (_nColId <= ColCount());
    2848             : }
    2849             : 
    2850             : //------------------------------------------------------------------------------
    2851           0 : void DbGridControl::copyCellText(sal_Int32 _nRow, sal_Int16 _nColId)
    2852             : {
    2853             :     DBG_ASSERT(canCopyCellText(_nRow, _nColId), "DbGridControl::copyCellText: invalid call!");
    2854           0 :     DbGridColumn* pColumn = m_aColumns[ GetModelColumnPos(_nColId) ];
    2855           0 :     SeekRow(_nRow);
    2856           0 :     OStringTransfer::CopyString( GetCurrentRowCellText( pColumn,m_xPaintRow ), this );
    2857           0 : }
    2858             : 
    2859             : //------------------------------------------------------------------------------
    2860           0 : void DbGridControl::executeRowContextMenu( long _nRow, const Point& _rPreferredPos )
    2861             : {
    2862           0 :     PopupMenu aContextMenu( SVX_RES( RID_SVXMNU_ROWS ) );
    2863             : 
    2864           0 :     PreExecuteRowContextMenu( (sal_uInt16)_nRow, aContextMenu );
    2865           0 :     aContextMenu.RemoveDisabledEntries( sal_True, sal_True );
    2866           0 :     PostExecuteRowContextMenu( (sal_uInt16)_nRow, aContextMenu, aContextMenu.Execute( this, _rPreferredPos ) );
    2867             : 
    2868             :     // TODO: why this weird cast to sal_uInt16? What if we really have more than 65535 lines?
    2869             :     // -> change this to sal_uInt32
    2870           0 : }
    2871             : 
    2872             : //------------------------------------------------------------------------------
    2873           0 : void DbGridControl::Command(const CommandEvent& rEvt)
    2874             : {
    2875           0 :     switch (rEvt.GetCommand())
    2876             :     {
    2877             :         case COMMAND_CONTEXTMENU:
    2878             :         {
    2879           0 :             if ( !m_pSeekCursor )
    2880             :             {
    2881           0 :                 DbGridControl_Base::Command(rEvt);
    2882           0 :                 return;
    2883             :             }
    2884             : 
    2885           0 :             if ( !rEvt.IsMouseEvent() )
    2886             :             {   // context menu requested by keyboard
    2887           0 :                 if ( GetSelectRowCount() )
    2888             :                 {
    2889           0 :                     long nRow = FirstSelectedRow( );
    2890             : 
    2891           0 :                     ::Rectangle aRowRect( GetRowRectPixel( nRow, sal_True ) );
    2892           0 :                     executeRowContextMenu( nRow, aRowRect.LeftCenter() );
    2893             : 
    2894             :                     // handled
    2895             :                     return;
    2896             :                 }
    2897             :             }
    2898             : 
    2899           0 :             sal_uInt16 nColId = GetColumnAtXPosPixel(rEvt.GetMousePosPixel().X());
    2900           0 :             long   nRow = GetRowAtYPosPixel(rEvt.GetMousePosPixel().Y());
    2901             : 
    2902           0 :             if (nColId == HandleColumnId)
    2903             :             {
    2904           0 :                 executeRowContextMenu( nRow, rEvt.GetMousePosPixel() );
    2905             :             }
    2906           0 :             else if (canCopyCellText(nRow, nColId))
    2907             :             {
    2908           0 :                 PopupMenu aContextMenu(SVX_RES(RID_SVXMNU_CELL));
    2909           0 :                 aContextMenu.RemoveDisabledEntries(sal_True, sal_True);
    2910           0 :                 switch (aContextMenu.Execute(this, rEvt.GetMousePosPixel()))
    2911             :                 {
    2912             :                     case SID_COPY:
    2913           0 :                         copyCellText(nRow, nColId);
    2914           0 :                         break;
    2915           0 :                 }
    2916             :             }
    2917             :             else
    2918             :             {
    2919           0 :                 DbGridControl_Base::Command(rEvt);
    2920           0 :                 return;
    2921             :             }
    2922             :         }
    2923             :         default:
    2924           0 :             DbGridControl_Base::Command(rEvt);
    2925             :     }
    2926             : }
    2927             : 
    2928             : //------------------------------------------------------------------------------
    2929           0 : IMPL_LINK(DbGridControl, OnDelete, void*, /*EMPTYTAG*/ )
    2930             : {
    2931             :     DBG_CHKTHIS(DbGridControl, NULL );
    2932           0 :     m_nDeleteEvent = 0;
    2933           0 :     DeleteSelectedRows();
    2934           0 :     return 0;
    2935             : }
    2936             : 
    2937             : //------------------------------------------------------------------------------
    2938           0 : void DbGridControl::DeleteSelectedRows()
    2939             : {
    2940             :     DBG_ASSERT(GetSelection(), "keine selection!!!");
    2941             : 
    2942           0 :     if (!m_pSeekCursor)
    2943           0 :         return;
    2944             : }
    2945             : 
    2946             : //------------------------------------------------------------------------------
    2947           0 : CellController* DbGridControl::GetController(long /*nRow*/, sal_uInt16 nColumnId)
    2948             : {
    2949           0 :     if (!IsValid(m_xCurrentRow) || !IsEnabled())
    2950           0 :         return NULL;
    2951             : 
    2952           0 :     size_t Location = GetModelColumnPos(nColumnId);
    2953           0 :     DbGridColumn* pColumn = ( Location < m_aColumns.size() ) ? m_aColumns[ Location ] : NULL;
    2954           0 :     if (!pColumn)
    2955           0 :         return NULL;
    2956             : 
    2957           0 :     CellController* pReturn = NULL;
    2958           0 :     if (IsFilterMode())
    2959           0 :         pReturn = &pColumn->GetController();
    2960             :     else
    2961             :     {
    2962           0 :         if (::comphelper::hasProperty(FM_PROP_ENABLED, pColumn->getModel()))
    2963             :         {
    2964           0 :             if (!::comphelper::getBOOL(pColumn->getModel()->getPropertyValue(FM_PROP_ENABLED)))
    2965           0 :                 return NULL;
    2966             :         }
    2967             : 
    2968           0 :         sal_Bool bInsert = (m_xCurrentRow->IsNew() && (m_nOptions & OPT_INSERT));
    2969           0 :         sal_Bool bUpdate = (!m_xCurrentRow->IsNew() && (m_nOptions & OPT_UPDATE));
    2970             : 
    2971           0 :         if ((bInsert && !pColumn->IsAutoValue()) || bUpdate || m_bForceROController)
    2972             :         {
    2973           0 :             pReturn = &pColumn->GetController();
    2974           0 :             if (pReturn)
    2975             :             {
    2976             :                 // wenn es eine Edit-Zeile ist, kann ich ihr das forced read-only mitgeben
    2977           0 :                 if (!pReturn->ISA(EditCellController) && !pReturn->ISA(SpinCellController))
    2978             :                     // ich konnte den Controller in forceROController nicht auf ReadOnly setzen
    2979           0 :                     if (!bInsert && !bUpdate)
    2980             :                         // ich bin nur hier, da m_bForceROController gesetzt war
    2981             :                         // -> lieber kein Controller als einer ohne RO
    2982           0 :                         pReturn = NULL;
    2983             :             }
    2984             :         }
    2985             :     }
    2986           0 :     return pReturn;
    2987             : }
    2988             : 
    2989             : //------------------------------------------------------------------------------
    2990           0 : void DbGridControl::InitController(CellControllerRef& /*rController*/, long /*nRow*/, sal_uInt16 nColumnId)
    2991             : {
    2992           0 :     size_t Location = GetModelColumnPos(nColumnId);
    2993           0 :     DbGridColumn* pColumn = ( Location < m_aColumns.size() ) ? m_aColumns[ Location ] : NULL;
    2994           0 :     if (pColumn)
    2995           0 :         pColumn->UpdateFromField(m_xCurrentRow, m_xFormatter);
    2996           0 : }
    2997             : 
    2998             : //------------------------------------------------------------------------------
    2999           0 : void DbGridControl::CellModified()
    3000             : {
    3001             :     TRACE_RANGE("DbGridControl::CellModified");
    3002             : 
    3003             :     {
    3004           0 :         ::osl::MutexGuard aGuard(m_aAdjustSafety);
    3005           0 :         if (m_nAsynAdjustEvent)
    3006             :         {
    3007             :             TRACE_RANGE_MESSAGE1("forcing a synchron call to ", m_bPendingAdjustRows ? "AdjustRows" : "AdustDataSource");
    3008           0 :             RemoveUserEvent(m_nAsynAdjustEvent);
    3009           0 :             m_nAsynAdjustEvent = 0;
    3010             : 
    3011             :             // force the call : this should be no problem as we're probably running in the solar thread here
    3012             :             // (cell modified is triggered by user actions)
    3013           0 :             if (m_bPendingAdjustRows)
    3014           0 :                 AdjustRows();
    3015             :             else
    3016           0 :                 AdjustDataSource();
    3017           0 :         }
    3018             :     }
    3019             : 
    3020           0 :     if (!IsFilterMode() && IsValid(m_xCurrentRow) && !m_xCurrentRow->IsModified())
    3021             :     {
    3022             :         // Einschalten des Editiermodus
    3023             :         // Datensatz soll eingefuegt werden
    3024           0 :         if (m_xCurrentRow->IsNew())
    3025             :         {
    3026           0 :             m_xCurrentRow->SetStatus(GRS_MODIFIED);
    3027             :             TRACE_RANGE_MESSAGE("current row is new, new state : MODIFIED");
    3028             :             // wenn noch keine Zeile hinzugefuegt wurde, dann neue hinzunehmen
    3029           0 :             if (m_nCurrentPos == GetRowCount() - 1)
    3030             :             {
    3031             :                 // RowCount um einen erhoehen
    3032           0 :                 RowInserted(GetRowCount(), 1, sal_True);
    3033           0 :                 InvalidateStatusCell(m_nCurrentPos);
    3034           0 :                 m_aBar.InvalidateAll(m_nCurrentPos);
    3035             :             }
    3036             :         }
    3037           0 :         else if (m_xCurrentRow->GetStatus() != GRS_MODIFIED)
    3038             :         {
    3039           0 :             m_xCurrentRow->SetState(m_pDataCursor, sal_False);
    3040             :             TRACE_RANGE_MESSAGE1("current row is not new, after SetState, new state : %s", ROWSTATUS(m_xCurrentRow));
    3041           0 :             m_xCurrentRow->SetStatus(GRS_MODIFIED);
    3042             :             TRACE_RANGE_MESSAGE("current row is not new, new state : MODIFIED");
    3043           0 :             InvalidateStatusCell(m_nCurrentPos);
    3044             :         }
    3045             :     }
    3046           0 : }
    3047             : 
    3048             : //------------------------------------------------------------------------------
    3049           0 : void DbGridControl::Dispatch(sal_uInt16 nId)
    3050             : {
    3051           0 :     if (nId == BROWSER_CURSORENDOFFILE)
    3052             :     {
    3053           0 :         if (m_nOptions & OPT_INSERT)
    3054           0 :             AppendNew();
    3055             :         else
    3056           0 :             MoveToLast();
    3057             :     }
    3058             :     else
    3059           0 :         DbGridControl_Base::Dispatch(nId);
    3060           0 : }
    3061             : 
    3062             : //------------------------------------------------------------------------------
    3063           0 : void DbGridControl::Undo()
    3064             : {
    3065           0 :     if (!IsFilterMode() && IsValid(m_xCurrentRow) && IsModified())
    3066             :     {
    3067             :         // check if we have somebody doin' the UNDO for us
    3068           0 :         long nState = -1;
    3069           0 :         if (m_aMasterStateProvider.IsSet())
    3070           0 :             nState = m_aMasterStateProvider.Call((void*)SID_FM_RECORD_UNDO);
    3071           0 :         if (nState>0)
    3072             :         {   // yes, we have, and the slot is enabled
    3073             :             DBG_ASSERT(m_aMasterSlotExecutor.IsSet(), "DbGridControl::Undo : a state, but no execute link ?");
    3074           0 :             long lResult = m_aMasterSlotExecutor.Call((void*)SID_FM_RECORD_UNDO);
    3075           0 :             if (lResult)
    3076             :                 // handled
    3077           0 :                 return;
    3078             :         }
    3079           0 :         else if (nState == 0)
    3080             :             // yes, we have, and the slot is disabled
    3081           0 :             return;
    3082             : 
    3083           0 :         BeginCursorAction();
    3084             : 
    3085           0 :         sal_Bool bAppending = m_xCurrentRow->IsNew();
    3086           0 :         sal_Bool bDirty     = m_xCurrentRow->IsModified();
    3087             : 
    3088             :         try
    3089             :         {
    3090             :             // Editieren abbrechen
    3091           0 :             Reference< XResultSetUpdate >  xUpdateCursor((Reference< XInterface >)*m_pDataCursor, UNO_QUERY);
    3092             :             // no effects if we're not updating currently
    3093           0 :             if (bAppending)
    3094             :                 // just refresh the row
    3095           0 :                 xUpdateCursor->moveToInsertRow();
    3096             :             else
    3097           0 :                 xUpdateCursor->cancelRowUpdates();
    3098             : 
    3099             :         }
    3100           0 :         catch(Exception&)
    3101             :         {
    3102             :             DBG_UNHANDLED_EXCEPTION();
    3103             :         }
    3104             : 
    3105           0 :         EndCursorAction();
    3106             : 
    3107           0 :         m_xDataRow->SetState(m_pDataCursor, sal_False);
    3108           0 :         if (&m_xPaintRow == &m_xCurrentRow)
    3109           0 :             m_xPaintRow = m_xCurrentRow = m_xDataRow;
    3110             :         else
    3111           0 :             m_xCurrentRow = m_xDataRow;
    3112             : 
    3113           0 :         if (bAppending && (DbGridControl_Base::IsModified() || bDirty))
    3114             :         // remove the row
    3115           0 :             if (m_nCurrentPos == GetRowCount() - 2)
    3116             :             {   // maybe we already removed it (in resetCurrentRow, called if the above moveToInsertRow
    3117             :                 // caused our data source form to be reset - which should be the usual case ....)
    3118           0 :                 RowRemoved(GetRowCount() - 1, 1, sal_True);
    3119           0 :                 m_aBar.InvalidateAll(m_nCurrentPos);
    3120             :             }
    3121             : 
    3122           0 :         RowModified(m_nCurrentPos);
    3123             :     }
    3124             : }
    3125             : 
    3126             : //------------------------------------------------------------------------------
    3127           0 : void DbGridControl::resetCurrentRow()
    3128             : {
    3129           0 :     if (IsModified())
    3130             :     {
    3131             :         // scenario : we're on the insert row, the row is dirty, and thus there exists a "second" insert row (which
    3132             :         // is clean). Normally in DataSourcePropertyChanged we would remove this second row if the modified state of
    3133             :         // the insert row changes from sal_True to sal_False. But if our current cell is the only modified element (means the
    3134             :         // data source isn't modified) and we're reset this DataSourcePropertyChanged would never be called, so we
    3135             :         // would never delete the obsolet "second insert row". Thus in this special case this method here
    3136             :         // is the only possibility to determine the redundance of the row (resetCurrentRow is called when the
    3137             :         // "first insert row" is about to be cleaned, so of course the "second insert row" is redundant now)
    3138           0 :         Reference< XPropertySet > xDataSource = getDataSource()->getPropertySet();
    3139           0 :         if (xDataSource.is() && !::comphelper::getBOOL(xDataSource->getPropertyValue(FM_PROP_ISMODIFIED)))
    3140             :         {
    3141             :             // are we on a new row currently ?
    3142           0 :             if (m_xCurrentRow->IsNew())
    3143             :             {
    3144           0 :                 if (m_nCurrentPos == GetRowCount() - 2)
    3145             :                 {
    3146           0 :                     RowRemoved(GetRowCount() - 1, 1, sal_True);
    3147           0 :                     m_aBar.InvalidateAll(m_nCurrentPos);
    3148             :                 }
    3149             :             }
    3150             :         }
    3151             : 
    3152             :         // update the rows
    3153           0 :         m_xDataRow->SetState(m_pDataCursor, sal_False);
    3154           0 :         if (&m_xPaintRow == &m_xCurrentRow)
    3155           0 :             m_xPaintRow = m_xCurrentRow = m_xDataRow;
    3156             :         else
    3157           0 :             m_xCurrentRow = m_xDataRow;
    3158             :     }
    3159             : 
    3160           0 :     RowModified(GetCurRow());       // will update the current controller if affected
    3161           0 : }
    3162             : 
    3163             : //------------------------------------------------------------------------------
    3164           0 : void DbGridControl::RowModified( long nRow, sal_uInt16 /*nColId*/ )
    3165             : {
    3166           0 :     if (nRow == m_nCurrentPos && IsEditing())
    3167             :     {
    3168           0 :         CellControllerRef aTmpRef = Controller();
    3169           0 :         aTmpRef->ClearModified();
    3170           0 :         InitController(aTmpRef, m_nCurrentPos, GetCurColumnId());
    3171             :     }
    3172           0 :     DbGridControl_Base::RowModified(nRow);
    3173           0 : }
    3174             : 
    3175             : //------------------------------------------------------------------------------
    3176           0 : sal_Bool DbGridControl::IsModified() const
    3177             : {
    3178           0 :     return !IsFilterMode() && IsValid(m_xCurrentRow) && (m_xCurrentRow->IsModified() || DbGridControl_Base::IsModified());
    3179             : }
    3180             : 
    3181             : //------------------------------------------------------------------------------
    3182           0 : sal_Bool DbGridControl::IsCurrentAppending() const
    3183             : {
    3184           0 :     return m_xCurrentRow.Is() && m_xCurrentRow->IsNew();
    3185             : }
    3186             : 
    3187             : //------------------------------------------------------------------------------
    3188           0 : sal_Bool DbGridControl::IsInsertionRow(long nRow) const
    3189             : {
    3190           0 :     return (m_nOptions & OPT_INSERT) && m_nTotalCount >= 0 && (nRow == GetRowCount() - 1);
    3191             : }
    3192             : 
    3193             : //------------------------------------------------------------------------------
    3194           0 : sal_Bool DbGridControl::SaveModified()
    3195             : {
    3196             :     TRACE_RANGE("DbGridControl::SaveModified");
    3197             :     DBG_ASSERT(IsValid(m_xCurrentRow), "GridControl:: Invalid row");
    3198           0 :     if (!IsValid(m_xCurrentRow))
    3199           0 :         return sal_True;
    3200             : 
    3201             :     // Uebernimmt die Dateneingabe fuer das Feld
    3202             :     // Hat es aenderungen im aktuellen Eingabefeld gegeben ?
    3203           0 :     if (!DbGridControl_Base::IsModified())
    3204           0 :         return sal_True;
    3205             : 
    3206           0 :     size_t Location = GetModelColumnPos( GetCurColumnId() );
    3207           0 :     DbGridColumn* pColumn = ( Location < m_aColumns.size() ) ? m_aColumns[ Location ] : NULL;
    3208           0 :     sal_Bool bOK = pColumn->Commit();
    3209             :     DBG_ASSERT( Controller().Is(), "DbGridControl::SaveModified: was modified, by have no controller?!" );
    3210           0 :     if ( !Controller().Is() )
    3211             :         // this might happen if the callbacks implicitly triggered by Commit
    3212             :         // fiddled with the form or the control ...
    3213             :         // (Note that this here is a workaround, at most. We need a general concept how
    3214             :         // to treat this, you can imagine an arbitrary number of scenarios where a callback
    3215             :         // triggers something which leaves us in an expected state.)
    3216             :         // #i67147# / 2006-07-17 / frank.schoenheit@sun.com
    3217           0 :         return bOK;
    3218             : 
    3219           0 :     if (bOK)
    3220             :     {
    3221           0 :         Controller()->ClearModified();
    3222             : 
    3223           0 :         if ( IsValid(m_xCurrentRow) )
    3224             :         {
    3225           0 :             m_xCurrentRow->SetState(m_pDataCursor, sal_False);
    3226             :             TRACE_RANGE_MESSAGE1("explicit SetState, new state : %s", ROWSTATUS(m_xCurrentRow));
    3227           0 :             InvalidateStatusCell( m_nCurrentPos );
    3228             :         }
    3229             : #ifdef DBG_UTIL
    3230             :         else
    3231             :         {
    3232             :             TRACE_RANGE_MESSAGE1("no SetState, new state : %s", ROWSTATUS(m_xCurrentRow));
    3233             :         }
    3234             : #endif
    3235             :     }
    3236             :     else
    3237             :     {
    3238             :         // reset the modified flag ....
    3239           0 :         Controller()->SetModified();
    3240             :     }
    3241             : 
    3242           0 :     return bOK;
    3243             : }
    3244             : 
    3245             : //------------------------------------------------------------------------------
    3246           0 : sal_Bool DbGridControl::SaveRow()
    3247             : {
    3248             :     TRACE_RANGE("DbGridControl::SaveRow");
    3249             :     // gueltige Zeile
    3250           0 :     if (!IsValid(m_xCurrentRow) || !IsModified())
    3251           0 :         return sal_True;
    3252             :     // Wert des Controllers noch nicht gespeichert
    3253           0 :     else if (Controller().Is() && Controller()->IsModified())
    3254             :     {
    3255           0 :         if (!SaveModified())
    3256           0 :             return sal_False;
    3257             :     }
    3258           0 :     m_bUpdating = sal_True;
    3259             : 
    3260           0 :     BeginCursorAction();
    3261           0 :     sal_Bool bAppending = m_xCurrentRow->IsNew();
    3262           0 :     sal_Bool bSuccess = sal_False;
    3263             :     try
    3264             :     {
    3265           0 :         Reference< XResultSetUpdate >  xUpdateCursor((Reference< XInterface >)*m_pDataCursor, UNO_QUERY);
    3266           0 :         if (bAppending)
    3267           0 :             xUpdateCursor->insertRow();
    3268             :         else
    3269           0 :             xUpdateCursor->updateRow();
    3270           0 :         bSuccess = sal_True;
    3271             :     }
    3272           0 :     catch(SQLException&)
    3273             :     {
    3274           0 :         EndCursorAction();
    3275           0 :         m_bUpdating = sal_False;
    3276           0 :         return sal_False;
    3277             :     }
    3278             : 
    3279             :     try
    3280             :     {
    3281           0 :         if (bSuccess)
    3282             :         {
    3283             :             // if we are appending we still sit on the insert row
    3284             :             // we don't move just clear the flags not to move on the current row
    3285           0 :             m_xCurrentRow->SetState(m_pDataCursor, sal_False);
    3286             :             TRACE_RANGE_MESSAGE1("explicit SetState after a successfull update, new state : %s", ROWSTATUS(m_xCurrentRow));
    3287           0 :             m_xCurrentRow->SetNew(sal_False);
    3288             : 
    3289             :             // adjust the seekcursor if it is on the same position as the datacursor
    3290           0 :             if (m_nSeekPos == m_nCurrentPos || bAppending)
    3291             :             {
    3292             :                 // get the bookmark to refetch the data
    3293             :                 // in insert mode we take the new bookmark of the data cursor
    3294           0 :                 Any aBookmark = bAppending ? m_pDataCursor->getBookmark() : m_pSeekCursor->getBookmark();
    3295           0 :                 m_pSeekCursor->moveToBookmark(aBookmark);
    3296             :                 // get the data
    3297           0 :                 m_xSeekRow->SetState(m_pSeekCursor, sal_True);
    3298           0 :                 m_nSeekPos = m_pSeekCursor->getRow() - 1;
    3299             :             }
    3300             :         }
    3301             :         // and repaint the row
    3302           0 :         RowModified(m_nCurrentPos);
    3303             :     }
    3304           0 :     catch(Exception&)
    3305             :     {
    3306             :     }
    3307             : 
    3308           0 :     m_bUpdating = sal_False;
    3309           0 :     EndCursorAction();
    3310             : 
    3311             :     // The old code returned (nRecords != 0) here.
    3312             :     // Me thinks this is wrong : If something goes wrong while update the record, an exception will be thrown,
    3313             :     // which results in a "return sal_False" (see above). If no exception is thrown, everything is fine. If nRecords
    3314             :     // is zero, this simply means all fields had their original values.
    3315             :     // FS - 06.12.99 - 70502
    3316           0 :     return sal_True;
    3317             : }
    3318             : 
    3319             : //------------------------------------------------------------------------------
    3320           0 : long DbGridControl::PreNotify(NotifyEvent& rEvt)
    3321             : {
    3322             :     // keine Events der Navbar behandeln
    3323           0 :     if (m_aBar.IsWindowOrChild(rEvt.GetWindow()))
    3324           0 :         return BrowseBox::PreNotify(rEvt);
    3325             : 
    3326           0 :     switch (rEvt.GetType())
    3327             :     {
    3328             :         case EVENT_KEYINPUT:
    3329             :         {
    3330           0 :             const KeyEvent* pKeyEvent = rEvt.GetKeyEvent();
    3331             : 
    3332           0 :             sal_uInt16 nCode = pKeyEvent->GetKeyCode().GetCode();
    3333           0 :             sal_Bool   bShift = pKeyEvent->GetKeyCode().IsShift();
    3334           0 :             sal_Bool   bCtrl = pKeyEvent->GetKeyCode().IsMod1();
    3335           0 :             sal_Bool   bAlt = pKeyEvent->GetKeyCode().IsMod2();
    3336           0 :             if ( ( KEY_TAB == nCode ) && bCtrl && !bAlt )
    3337             :             {
    3338             :                 // Ctrl-Tab is used to step out of the control, without traveling to the
    3339             :                 // remaining cells first
    3340             :                 // -> build a new key event without the Ctrl-key, and let the very base class handle it
    3341           0 :                 KeyCode aNewCode( KEY_TAB, bShift, sal_False, sal_False, sal_False );
    3342           0 :                 KeyEvent aNewEvent( pKeyEvent->GetCharCode(), aNewCode );
    3343             : 
    3344             :                 // call the Control - our direct base class will interpret this in a way we do not want (and do
    3345             :                 // a cell traveling)
    3346           0 :                 Control::KeyInput( aNewEvent );
    3347           0 :                 return 1;
    3348             :             }
    3349             : 
    3350           0 :             if ( !bShift && !bCtrl && ( KEY_ESCAPE == nCode ) )
    3351             :             {
    3352           0 :                 if (IsModified())
    3353             :                 {
    3354           0 :                     Undo();
    3355           0 :                     return 1;
    3356             :                 }
    3357             :             }
    3358           0 :             else if ( ( KEY_DELETE == nCode ) && !bShift && !bCtrl )    // delete rows
    3359             :             {
    3360           0 :                 if ((m_nOptions & OPT_DELETE) && GetSelectRowCount())
    3361             :                 {
    3362             :                     // delete asynchron
    3363           0 :                     if (m_nDeleteEvent)
    3364           0 :                         Application::RemoveUserEvent(m_nDeleteEvent);
    3365           0 :                     m_nDeleteEvent = Application::PostUserEvent(LINK(this,DbGridControl,OnDelete));
    3366           0 :                     return 1;
    3367             :                 }
    3368             :             }
    3369             :         }   // kein break!
    3370             :         default:
    3371           0 :             return DbGridControl_Base::PreNotify(rEvt);
    3372             :     }
    3373             : }
    3374             : 
    3375             : //------------------------------------------------------------------------------
    3376           0 : sal_Bool DbGridControl::IsTabAllowed(sal_Bool bRight) const
    3377             : {
    3378           0 :     if (bRight)
    3379             :         // Tab nur wenn nicht auf der letzten Zelle
    3380           0 :         return GetCurRow() < (GetRowCount() - 1) || !m_bRecordCountFinal ||
    3381           0 :                GetViewColumnPos(GetCurColumnId()) < (GetViewColCount() - 1);
    3382             :     else
    3383             :     {
    3384             :         // Tab nur wenn nicht auf der ersten Zelle
    3385           0 :         return GetCurRow() > 0 || (GetCurColumnId() && GetViewColumnPos(GetCurColumnId()) > 0);
    3386             :     }
    3387             : }
    3388             : 
    3389             : //------------------------------------------------------------------------------
    3390           0 : void DbGridControl::KeyInput( const KeyEvent& rEvt )
    3391             : {
    3392           0 :     if (rEvt.GetKeyCode().GetFunction() == KEYFUNC_COPY)
    3393             :     {
    3394           0 :         long nRow = GetCurRow();
    3395           0 :         sal_uInt16 nColId = GetCurColumnId();
    3396           0 :         if (nRow >= 0 && nRow < GetRowCount() && nColId < ColCount())
    3397             :         {
    3398           0 :             size_t Location = GetModelColumnPos( nColId );
    3399           0 :             DbGridColumn* pColumn = ( Location < m_aColumns.size() ) ? m_aColumns[ Location ] : NULL;
    3400           0 :             OStringTransfer::CopyString( GetCurrentRowCellText( pColumn,m_xPaintRow ), this );
    3401           0 :             return;
    3402             :         }
    3403             :     }
    3404           0 :     DbGridControl_Base::KeyInput(rEvt);
    3405             : }
    3406             : 
    3407             : //------------------------------------------------------------------------------
    3408           0 : void DbGridControl::HideColumn(sal_uInt16 nId)
    3409             : {
    3410           0 :     DeactivateCell();
    3411             : 
    3412             :     // determine the col for the focus to set to after removal
    3413           0 :     sal_uInt16 nPos = GetViewColumnPos(nId);
    3414           0 :     sal_uInt16 nNewColId = nPos == (ColCount()-1)
    3415           0 :         ? GetColumnIdFromViewPos(nPos-1)    // last col is to be removed -> take the previous
    3416           0 :         : GetColumnIdFromViewPos(nPos+1);   // take the next
    3417             : 
    3418           0 :     long lCurrentWidth = GetColumnWidth(nId);
    3419           0 :     DbGridControl_Base::RemoveColumn(nId);
    3420             :         // don't use my own RemoveColumn, this would remove it from m_aColumns, too
    3421             : 
    3422             :     // update my model
    3423           0 :     size_t Location = GetModelColumnPos( nId );
    3424           0 :     DbGridColumn* pColumn = ( Location < m_aColumns.size() ) ? m_aColumns[ Location ] : NULL;
    3425             :     DBG_ASSERT(pColumn, "DbGridControl::HideColumn : somebody did hide a nonexistent column !");
    3426           0 :     if (pColumn)
    3427             :     {
    3428           0 :         pColumn->m_bHidden = sal_True;
    3429           0 :         pColumn->m_nLastVisibleWidth = CalcReverseZoom(lCurrentWidth);
    3430             :     }
    3431             : 
    3432             :     // and reset the focus
    3433           0 :     if ( nId == GetCurColumnId() )
    3434           0 :         GoToColumnId( nNewColId );
    3435           0 : }
    3436             : 
    3437             : //------------------------------------------------------------------------------
    3438           0 : void DbGridControl::ShowColumn(sal_uInt16 nId)
    3439             : {
    3440           0 :     sal_uInt16 nPos = GetModelColumnPos(nId);
    3441             :     DBG_ASSERT(nPos != GRID_COLUMN_NOT_FOUND, "DbGridControl::ShowColumn : invalid argument !");
    3442           0 :     if (nPos == GRID_COLUMN_NOT_FOUND)
    3443             :         return;
    3444             : 
    3445           0 :     DbGridColumn* pColumn = m_aColumns[ nPos ];
    3446           0 :     if (!pColumn->IsHidden())
    3447             :     {
    3448             :         DBG_ASSERT(GetViewColumnPos(nId) != GRID_COLUMN_NOT_FOUND, "DbGridControl::ShowColumn : inconsistent internal state !");
    3449             :             // if the column isn't marked as hidden, it should be visible, shouldn't it ?
    3450             :         return;
    3451             :     }
    3452             :     DBG_ASSERT(GetViewColumnPos(nId) == GRID_COLUMN_NOT_FOUND, "DbGridControl::ShowColumn : inconsistent internal state !");
    3453             :         // the opposite situation ...
    3454             : 
    3455             :     // to determine the new view position we need an adjacent non-hidden column
    3456           0 :     sal_uInt16 nNextNonHidden = BROWSER_INVALIDID;
    3457             :     // first search the cols to the right
    3458           0 :     for ( size_t i = nPos + 1; i < m_aColumns.size(); ++i )
    3459             :     {
    3460           0 :         DbGridColumn* pCurCol = m_aColumns[ i ];
    3461           0 :         if (!pCurCol->IsHidden())
    3462             :         {
    3463           0 :             nNextNonHidden = i;
    3464           0 :             break;
    3465             :         }
    3466             :     }
    3467           0 :     if ((nNextNonHidden == BROWSER_INVALIDID) && (nPos > 0))
    3468             :     {
    3469             :         // then to the left
    3470           0 :         for ( size_t i = nPos; i > 0; --i )
    3471             :         {
    3472           0 :             DbGridColumn* pCurCol = m_aColumns[ i-1 ];
    3473           0 :             if (!pCurCol->IsHidden())
    3474             :             {
    3475           0 :                 nNextNonHidden = i-1;
    3476           0 :                 break;
    3477             :             }
    3478             :         }
    3479             :     }
    3480             :     sal_uInt16 nNewViewPos = (nNextNonHidden == BROWSER_INVALIDID)
    3481             :         ? 1 // there is no visible column -> insert behinde the handle col
    3482           0 :         : GetViewColumnPos( m_aColumns[ nNextNonHidden ]->GetId() ) + 1;
    3483             :             // the first non-handle col has "view pos" 0, but the pos arg for InsertDataColumn expects
    3484             :             // a position 1 for the first non-handle col -> +1
    3485             :     DBG_ASSERT(nNewViewPos != GRID_COLUMN_NOT_FOUND, "DbGridControl::ShowColumn : inconsistent internal state !");
    3486             :         // we found a col marked as visible but got no view pos for it ...
    3487             : 
    3488           0 :     if ((nNextNonHidden<nPos) && (nNextNonHidden != BROWSER_INVALIDID))
    3489             :         // nNextNonHidden is a column to the left, so we want to insert the new col _right_ beside it's pos
    3490           0 :         ++nNewViewPos;
    3491             : 
    3492           0 :     DeactivateCell();
    3493             : 
    3494           0 :     ::rtl::OUString aName;
    3495           0 :     pColumn->getModel()->getPropertyValue(FM_PROP_LABEL) >>= aName;
    3496           0 :     InsertDataColumn(nId, aName, CalcZoom(pColumn->m_nLastVisibleWidth), HIB_CENTER | HIB_VCENTER | HIB_CLICKABLE, nNewViewPos);
    3497           0 :     pColumn->m_bHidden = sal_False;
    3498             : 
    3499           0 :     ActivateCell();
    3500           0 :     Invalidate();
    3501             : }
    3502             : 
    3503             : //------------------------------------------------------------------------------
    3504           0 : sal_uInt16 DbGridControl::GetColumnIdFromModelPos( sal_uInt16 nPos ) const
    3505             : {
    3506           0 :     if (nPos >= m_aColumns.size())
    3507             :     {
    3508             :         OSL_FAIL("DbGridControl::GetColumnIdFromModelPos : invalid argument !");
    3509           0 :         return GRID_COLUMN_NOT_FOUND;
    3510             :     }
    3511             : 
    3512           0 :     DbGridColumn* pCol = m_aColumns[ nPos ];
    3513             : #if (OSL_DEBUG_LEVEL > 0) || defined DBG_UTIL
    3514             :     // in der Debug-Version rechnen wir die ModelPos in eine ViewPos um und vergleichen das mit dem Wert,
    3515             :     // den wir zurueckliefern werden (nId an der entsprechenden Col in m_aColumns)
    3516             : 
    3517             :     if (!pCol->IsHidden())
    3518             :     {   // macht nur Sinn, wenn die Spalte sichtbar ist
    3519             :         sal_uInt16 nViewPos = nPos;
    3520             :         for ( size_t i = 0; i < m_aColumns.size() && i < nPos; ++i)
    3521             :             if ( m_aColumns[ i ]->IsHidden())
    3522             :                 --nViewPos;
    3523             : 
    3524             :         DBG_ASSERT(pCol && GetColumnIdFromViewPos(nViewPos) == pCol->GetId(),
    3525             :             "DbGridControl::GetColumnIdFromModelPos : this isn't consistent .... did I misunderstand something ?");
    3526             :     }
    3527             : #endif
    3528           0 :     return pCol->GetId();
    3529             : }
    3530             : 
    3531             : //------------------------------------------------------------------------------
    3532           0 : sal_uInt16 DbGridControl::GetModelColumnPos( sal_uInt16 nId ) const
    3533             : {
    3534           0 :     for ( size_t i = 0; i < m_aColumns.size(); ++i )
    3535           0 :         if ( m_aColumns[ i ]->GetId() == nId )
    3536           0 :             return i;
    3537             : 
    3538           0 :     return GRID_COLUMN_NOT_FOUND;
    3539             : }
    3540             : 
    3541             : //------------------------------------------------------------------------------
    3542           0 : void DbGridControl::implAdjustInSolarThread(sal_Bool _bRows)
    3543             : {
    3544             :     TRACE_RANGE("DbGridControl::implAdjustInSolarThread");
    3545           0 :     ::osl::MutexGuard aGuard(m_aAdjustSafety);
    3546           0 :     if (::osl::Thread::getCurrentIdentifier() != Application::GetMainThreadIdentifier())
    3547             :     {
    3548           0 :         m_nAsynAdjustEvent = PostUserEvent(LINK(this, DbGridControl, OnAsyncAdjust), reinterpret_cast< void* >( _bRows ));
    3549           0 :         m_bPendingAdjustRows = _bRows;
    3550             : #ifdef DBG_UTIL
    3551             :         if (_bRows)
    3552             :             TRACE_RANGE_MESSAGE("posting an AdjustRows")
    3553             :         else
    3554             :             TRACE_RANGE_MESSAGE("posting an AdjustDataSource")
    3555             : #endif
    3556             :     }
    3557             :     else
    3558             :     {
    3559             : #ifdef DBG_UTIL
    3560             :         if (_bRows)
    3561             :             TRACE_RANGE_MESSAGE("doing an AdjustRows")
    3562             :         else
    3563             :             TRACE_RANGE_MESSAGE("doing an AdjustDataSource")
    3564             : #endif
    3565             :         // always adjust the rows before adjusting the data source
    3566             :         // If this is not necessary (because the row count did not change), nothing is done
    3567             :         // The problem is that we can't rely on the order of which the calls come in: If the cursor was moved
    3568             :         // to a position behind row count know 'til now, the cursorMoved notification may come before the
    3569             :         // RowCountChanged notification
    3570             :         // 94093 - 02.11.2001 - frank.schoenheit@sun.com
    3571           0 :         AdjustRows();
    3572             : 
    3573           0 :         if ( !_bRows )
    3574           0 :             AdjustDataSource();
    3575           0 :     }
    3576           0 : }
    3577             : 
    3578             : //------------------------------------------------------------------------------
    3579           0 : IMPL_LINK(DbGridControl, OnAsyncAdjust, void*, pAdjustWhat)
    3580             : {
    3581           0 :     m_nAsynAdjustEvent = 0;
    3582             : 
    3583           0 :     AdjustRows();
    3584             :         // see implAdjustInSolarThread for a comment why we do this every time
    3585             : 
    3586           0 :     if ( !pAdjustWhat )
    3587           0 :         AdjustDataSource();
    3588             : 
    3589           0 :     return 0L;
    3590             : }
    3591             : 
    3592             : //------------------------------------------------------------------------------
    3593           0 : void DbGridControl::BeginCursorAction()
    3594             : {
    3595           0 :     if (m_pFieldListeners)
    3596             :     {
    3597           0 :         ColumnFieldValueListeners* pListeners = (ColumnFieldValueListeners*)m_pFieldListeners;
    3598           0 :         ConstColumnFieldValueListenersIterator aIter = pListeners->begin();
    3599           0 :         while (aIter != pListeners->end())
    3600             :         {
    3601           0 :             GridFieldValueListener* pCurrent = (*aIter).second;
    3602           0 :             if (pCurrent)
    3603           0 :                 pCurrent->suspend();
    3604           0 :             ++aIter;
    3605             :         }
    3606             :     }
    3607             : 
    3608           0 :     if (m_pDataSourcePropListener)
    3609           0 :         m_pDataSourcePropListener->suspend();
    3610           0 : }
    3611             : 
    3612             : //------------------------------------------------------------------------------
    3613           0 : void DbGridControl::EndCursorAction()
    3614             : {
    3615           0 :     if (m_pFieldListeners)
    3616             :     {
    3617           0 :         ColumnFieldValueListeners* pListeners = (ColumnFieldValueListeners*)m_pFieldListeners;
    3618           0 :         ConstColumnFieldValueListenersIterator aIter = pListeners->begin();
    3619           0 :         while (aIter != pListeners->end())
    3620             :         {
    3621           0 :             GridFieldValueListener* pCurrent = (*aIter).second;
    3622           0 :             if (pCurrent)
    3623           0 :                 pCurrent->resume();
    3624           0 :             ++aIter;
    3625             :         }
    3626             :     }
    3627             : 
    3628           0 :     if (m_pDataSourcePropListener)
    3629           0 :         m_pDataSourcePropListener->resume();
    3630           0 : }
    3631             : 
    3632             : //------------------------------------------------------------------------------
    3633           0 : void DbGridControl::ConnectToFields()
    3634             : {
    3635           0 :     ColumnFieldValueListeners* pListeners = (ColumnFieldValueListeners*)m_pFieldListeners;
    3636             :     DBG_ASSERT(!pListeners || pListeners->empty(), "DbGridControl::ConnectToFields : please call DisconnectFromFields first !");
    3637             : 
    3638           0 :     if (!pListeners)
    3639             :     {
    3640           0 :         pListeners = new ColumnFieldValueListeners;
    3641           0 :         m_pFieldListeners = pListeners;
    3642             :     }
    3643             : 
    3644           0 :     for ( size_t i = 0; i < m_aColumns.size(); ++i )
    3645             :     {
    3646           0 :         DbGridColumn* pCurrent = m_aColumns[ i ];
    3647           0 :         sal_uInt16 nViewPos = pCurrent ? GetViewColumnPos(pCurrent->GetId()) : GRID_COLUMN_NOT_FOUND;
    3648           0 :         if (GRID_COLUMN_NOT_FOUND == nViewPos)
    3649           0 :             continue;
    3650             : 
    3651           0 :         Reference< XPropertySet >  xField = pCurrent->GetField();
    3652           0 :         if (!xField.is())
    3653           0 :             continue;
    3654             : 
    3655             :         // column is visible and bound here
    3656           0 :         GridFieldValueListener*& rpListener = (*pListeners)[pCurrent->GetId()];
    3657             :         DBG_ASSERT(!rpListener, "DbGridControl::ConnectToFields : already a listener for this column ?!");
    3658           0 :         rpListener = new GridFieldValueListener(*this, xField, pCurrent->GetId());
    3659           0 :     }
    3660           0 : }
    3661             : 
    3662             : //------------------------------------------------------------------------------
    3663           0 : void DbGridControl::DisconnectFromFields()
    3664             : {
    3665           0 :     if (!m_pFieldListeners)
    3666           0 :         return;
    3667             : 
    3668           0 :     ColumnFieldValueListeners* pListeners = (ColumnFieldValueListeners*)m_pFieldListeners;
    3669           0 :     while (pListeners->size())
    3670             :     {
    3671             : #ifdef DBG_UTIL
    3672             :         sal_Int32 nOldSize = pListeners->size();
    3673             : #endif
    3674           0 :         pListeners->begin()->second->dispose();
    3675             :         DBG_ASSERT(nOldSize > (sal_Int32)pListeners->size(), "DbGridControl::DisconnectFromFields : dispose on a listener should result in a removal from my list !");
    3676             :     }
    3677             : 
    3678           0 :     delete pListeners;
    3679           0 :     m_pFieldListeners = NULL;
    3680             : }
    3681             : 
    3682             : //------------------------------------------------------------------------------
    3683           0 : void DbGridControl::FieldValueChanged(sal_uInt16 _nId, const PropertyChangeEvent& /*_evt*/)
    3684             : {
    3685           0 :     osl::MutexGuard aPreventDestruction(m_aDestructionSafety);
    3686             :     // needed as this may run in a thread other than the main one
    3687           0 :     if (GetRowStatus(GetCurRow()) != DbGridControl_Base::MODIFIED)
    3688             :         // all other cases are handled elsewhere
    3689             :         return;
    3690             : 
    3691           0 :     size_t Location = GetModelColumnPos( _nId );
    3692           0 :     DbGridColumn* pColumn = ( Location < m_aColumns.size() ) ? m_aColumns[ Location ] : NULL;
    3693           0 :     if (pColumn)
    3694             :     {
    3695           0 :         sal_Bool bAcquiredPaintSafety = sal_False;
    3696           0 :         while (!m_bWantDestruction && !bAcquiredPaintSafety)
    3697           0 :             bAcquiredPaintSafety  = Application::GetSolarMutex().tryToAcquire();
    3698             : 
    3699           0 :         if (m_bWantDestruction)
    3700             :         {   // at this moment, within another thread, our destructor tries to destroy the listener which called this method
    3701             :             // => don't do anything
    3702             :             // 73365 - 23.02.00 - FS
    3703           0 :             if (bAcquiredPaintSafety)
    3704             :                 // though the above while-loop suggests that (m_bWantDestruction && bAcquiredPaintSafety) is impossible,
    3705             :                 // it isnt't, as m_bWantDestruction isn't protected with any mutex
    3706           0 :                 Application::GetSolarMutex().release();
    3707             :             return;
    3708             :         }
    3709             :         // here we got the solar mutex, transfer it to a guard for safety reasons
    3710           0 :         SolarMutexGuard aPaintSafety;
    3711           0 :         Application::GetSolarMutex().release();
    3712             : 
    3713             :         // and finally do the update ...
    3714           0 :         pColumn->UpdateFromField(m_xCurrentRow, m_xFormatter);
    3715           0 :         RowModified(GetCurRow(), _nId);
    3716           0 :     }
    3717             : }
    3718             : 
    3719             : //------------------------------------------------------------------------------
    3720           0 : void DbGridControl::FieldListenerDisposing(sal_uInt16 _nId)
    3721             : {
    3722           0 :     ColumnFieldValueListeners* pListeners = (ColumnFieldValueListeners*)m_pFieldListeners;
    3723           0 :     if (!pListeners)
    3724             :     {
    3725             :         OSL_FAIL("DbGridControl::FieldListenerDisposing : invalid call (have no listener array) !");
    3726             :         return;
    3727             :     }
    3728             : 
    3729           0 :     ColumnFieldValueListenersIterator aPos = pListeners->find(_nId);
    3730           0 :     if (aPos == pListeners->end())
    3731             :     {
    3732             :         OSL_FAIL("DbGridControl::FieldListenerDisposing : invalid call (did not find the listener) !");
    3733             :         return;
    3734             :     }
    3735             : 
    3736           0 :     delete aPos->second;
    3737             : 
    3738           0 :     pListeners->erase(aPos);
    3739             : }
    3740             : 
    3741             : //------------------------------------------------------------------------------
    3742           0 : void DbGridControl::disposing(sal_uInt16 _nId, const EventObject& /*_rEvt*/)
    3743             : {
    3744           0 :     if (_nId == 0)
    3745             :     {   // the seek cursor is beeing disposed
    3746           0 :         ::osl::MutexGuard aGuard(m_aAdjustSafety);
    3747           0 :         setDataSource(NULL,0); // our clone was disposed so we set our datasource to null to avoid later acces to it
    3748           0 :         if (m_nAsynAdjustEvent)
    3749             :         {
    3750           0 :             RemoveUserEvent(m_nAsynAdjustEvent);
    3751           0 :             m_nAsynAdjustEvent = 0;
    3752           0 :         }
    3753             :     }
    3754           0 : }
    3755             : // -----------------------------------------------------------------------------
    3756           0 : sal_Int32 DbGridControl::GetAccessibleControlCount() const
    3757             : {
    3758           0 :     return DbGridControl_Base::GetAccessibleControlCount() + 1; // the navigation control
    3759             : }
    3760             : // -----------------------------------------------------------------------------
    3761           0 : Reference<XAccessible > DbGridControl::CreateAccessibleControl( sal_Int32 _nIndex )
    3762             : {
    3763           0 :     Reference<XAccessible > xRet;
    3764           0 :     if ( _nIndex == DbGridControl_Base::GetAccessibleControlCount() )
    3765             :     {
    3766           0 :         xRet = m_aBar.GetAccessible();
    3767             :     }
    3768             :     else
    3769           0 :         xRet = DbGridControl_Base::CreateAccessibleControl( _nIndex );
    3770           0 :     return xRet;
    3771             : }
    3772             : // -----------------------------------------------------------------------------
    3773           0 : Reference< XAccessible > DbGridControl::CreateAccessibleCell( sal_Int32 _nRow, sal_uInt16 _nColumnPos )
    3774             : {
    3775           0 :     sal_uInt16 nColumnId = GetColumnId( _nColumnPos );
    3776           0 :     size_t Location = GetModelColumnPos(nColumnId);
    3777           0 :     DbGridColumn* pColumn = ( Location < m_aColumns.size() ) ? m_aColumns[ Location ] : NULL;
    3778           0 :     if ( pColumn )
    3779             :     {
    3780           0 :         Reference< ::com::sun::star::awt::XControl> xInt(pColumn->GetCell());
    3781           0 :         Reference< ::com::sun::star::awt::XCheckBox> xBox(xInt,UNO_QUERY);
    3782           0 :         if ( xBox.is() )
    3783             :         {
    3784           0 :             TriState eValue = STATE_NOCHECK;
    3785           0 :             switch( xBox->getState() )
    3786             :             {
    3787             :                 case 0:
    3788           0 :                     eValue = STATE_NOCHECK;
    3789           0 :                     break;
    3790             :                 case 1:
    3791           0 :                     eValue = STATE_CHECK;
    3792           0 :                     break;
    3793             :                 case 2:
    3794           0 :                     eValue = STATE_DONTKNOW;
    3795           0 :                     break;
    3796             :             }
    3797           0 :             return DbGridControl_Base::CreateAccessibleCheckBoxCell( _nRow, _nColumnPos,eValue );
    3798           0 :         }
    3799             :     }
    3800           0 :     return DbGridControl_Base::CreateAccessibleCell( _nRow, _nColumnPos );
    3801             : }
    3802             : // -----------------------------------------------------------------------------
    3803             : 
    3804             : 
    3805             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10