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