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