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