LCOV - code coverage report
Current view: top level - svx/source/fmcomp - gridctrl.cxx (source / functions) Hit Total Coverage
Test: commit e02a6cb2c3e2b23b203b422e4e0680877f232636 Lines: 0 1738 0.0 %
Date: 2014-04-14 Functions: 0 140 0.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10