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

Generated by: LCOV version 1.10