/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
void NavigationBar::PositionDataSource(sal_Int32 nRecord)
{ if (m_bPositioning) return; // the MoveToPosition may cause a LoseFocus which would lead to a second MoveToPosition, // so protect against this recursion
m_bPositioning = true; static_cast<DbGridControl*>(GetParent())->MoveToPosition(nRecord - 1);
m_bPositioning = false;
}
// set handlers for buttons
m_xFirstBtn->connect_clicked(LINK(this,NavigationBar,OnClick));
m_xLastBtn->connect_clicked(LINK(this,NavigationBar,OnClick));
m_xNewBtn->connect_clicked(LINK(this,NavigationBar,OnClick));
if ( bAll )
{
m_nCurrentPos = nCurrentPos; int i = 0; while (ControlMap[i] != DbGridControlNavigationBarState::NONE)
SetState(ControlMap[i++]);
} else// is in the center
{
m_nCurrentPos = nCurrentPos;
SetState(DbGridControlNavigationBarState::Count);
SetState(DbGridControlNavigationBarState::Absolute);
}
}
if (!pParent->IsOpen() || pParent->IsDesignMode() || !pParent->IsEnabled()
|| pParent->IsFilterMode() ) returnfalse; else
{ // check if we have a master state provider if (pParent->m_aMasterStateProvider.IsSet())
{
tools::Long nState = pParent->m_aMasterStateProvider.Call( nWhich ); if (nState>=0) return (nState>0);
}
void NavigationBar::SetState(DbGridControlNavigationBarState nWhich)
{ bool bAvailable = GetState(nWhich);
DbGridControl* pParent = static_cast<DbGridControl*>(GetParent());
weld::Widget* pWnd = nullptr; switch (nWhich)
{ case DbGridControlNavigationBarState::First:
pWnd = m_xFirstBtn.get(); break; case DbGridControlNavigationBarState::Prev:
pWnd = m_xPrevBtn.get(); break; case DbGridControlNavigationBarState::Next:
pWnd = m_xNextBtn.get(); break; case DbGridControlNavigationBarState::Last:
pWnd = m_xLastBtn.get(); break; case DbGridControlNavigationBarState::New:
pWnd = m_xNewBtn.get(); break; case DbGridControlNavigationBarState::Absolute:
pWnd = m_xAbsolute->GetWidget(); if (bAvailable)
m_xAbsolute->set_text(OUString::number(m_nCurrentPos + 1)); else
m_xAbsolute->set_text(OUString()); break; case DbGridControlNavigationBarState::Text:
pWnd = m_xRecordText.get(); break; case DbGridControlNavigationBarState::Of:
pWnd = m_xRecordOf.get(); break; case DbGridControlNavigationBarState::Count:
{
pWnd = m_xRecordCount.get();
OUString aText; if (bAvailable)
{ if (pParent->GetOptions() & DbGridControlOptions::Insert)
{ if (pParent->IsCurrentAppending() && !pParent->IsModified())
aText = OUString::number(pParent->GetRowCount()); else
aText = OUString::number(pParent->GetRowCount() - 1);
} else
aText = OUString::number(pParent->GetRowCount()); if(!pParent->m_bRecordCountFinal)
aText += " *";
} else
aText.clear();
// add the number of selected rows, if applicable if (pParent->GetSelectRowCount())
{
OUString aExtendedInfo = aText + " (" +
OUString::number(pParent->GetSelectRowCount()) + ")";
m_xRecordCount->set_label(aExtendedInfo);
} else
m_xRecordCount->set_label(aText);
pParent->SetRealRowCount(aText);
} break; default: break;
}
DBG_ASSERT(pWnd, "no window"); if (!(pWnd && (pWnd->get_sensitive() != bAvailable))) return;
// this "pWnd->IsEnabled() != bAvailable" is a little hack : Window::Enable always generates a user // event (ImplGenerateMouseMove) even if nothing happened. This may lead to some unwanted effects, so we // do this check. // For further explanation see Bug 69900.
pWnd->set_sensitive(bAvailable); if (!bAvailable)
{ if (pWnd == m_xNextBtn.get())
m_xNextRepeater->Stop(); elseif (pWnd == m_xPrevBtn.get())
m_xPrevRepeater->Stop();
}
}
void DbGridControl::InsertHandleColumn()
{ // BrowseBox has problems when painting without a handleColumn (hide it here) if (HasHandle())
BrowseBox::InsertHandleColumn(GetDefaultColumnWidth(OUString())); else
BrowseBox::InsertHandleColumn(0);
}
m_bWantDestruction = true;
osl::MutexGuard aGuard(m_aDestructionSafety); if (!m_aFieldListeners.empty())
DisconnectFromFields();
m_pCursorDisposeListener.reset();
if (m_nDeleteEvent)
Application::RemoveUserEvent(m_nDeleteEvent);
if (m_pDataSourcePropMultiplexer.is())
{
m_pDataSourcePropMultiplexer->dispose();
m_pDataSourcePropMultiplexer.clear(); // this should delete the multiplexer delete m_pDataSourcePropListener;
m_pDataSourcePropListener = nullptr;
}
m_xRowSetListener.clear();
m_pDataCursor.reset();
m_pSeekCursor.reset();
m_aBar.disposeAndClear();
m_aRearrangeIdle.Stop();
EditBrowseBox::dispose();
}
void DbGridControl::RearrangeAtIdle()
{ if (isDisposed()) return;
m_aRearrangeIdle.Start();
}
// as the selected rows may have changed, update the according display in our navigation bar
m_aBar->InvalidateState(DbGridControlNavigationBarState::Count);
if (m_pGridListener)
m_pGridListener->selectionChanged();
}
// reset number of sentences to zero in the browser
EditBrowseBox::RemoveRows();
m_aBar->InvalidateAll(m_nCurrentPos, true);
}
void DbGridControl::ArrangeControls(sal_uInt16& nX, sal_uInt16 nY)
{ // positioning of the controls if (m_bNavigationBar)
{
tools::Rectangle aRect(GetControlArea());
nX = m_aBar->GetPreferredWidth();
m_aBar->SetPosSizePixel(Point(0, nY + 1), Size(nX, aRect.GetSize().Height() - 1));
}
}
void DbGridControl::EnableHandle(bool bEnable)
{ if (m_bHandle == bEnable) return;
// HandleColumn is only hidden because there are a lot of problems while painting otherwise
RemoveColumn( HandleColumnId );
m_bHandle = bEnable;
InsertHandleColumn();
}
// note: if we have a navigation bar, we always have an AUTO_HSCROLL. In particular, // _bHideScrollbars is ignored then if ( _bNavigationBar )
{
_rMode |= BrowserMode::AUTO_HSCROLL;
_rMode &= ~BrowserMode::NO_HSCROLL;
}
return nOldMode != _rMode;
}
}
void DbGridControl::EnableNavigationBar(bool bEnable)
{ if (m_bNavigationBar == bEnable) return;
m_bNavigationBar = bEnable;
if (bEnable)
{
m_aBar->Show();
m_aBar->Enable();
m_aBar->InvalidateAll(m_nCurrentPos, true);
DbGridControlOptions DbGridControl::SetOptions(DbGridControlOptions nOpt)
{
DBG_ASSERT(!m_xCurrentRow.is() || !m_xCurrentRow->IsModified(), "DbGridControl::SetOptions : please do not call when editing a record (things are much easier this way ;) !");
// for the next setDataSource (which is triggered by a refresh, for instance)
m_nOptionMask = nOpt;
// normalize the new options
Reference< XPropertySet > xDataSourceSet = m_pDataCursor->getPropertySet(); if (xDataSourceSet.is())
{ // check what kind of options are available
sal_Int32 nPrivileges = 0;
xDataSourceSet->getPropertyValue(FM_PROP_PRIVILEGES) >>= nPrivileges; if ((nPrivileges & Privilege::INSERT) == 0)
nOpt &= ~DbGridControlOptions::Insert; if ((nPrivileges & Privilege::UPDATE) == 0)
nOpt &= ~DbGridControlOptions::Update; if ((nPrivileges & Privilege::DELETE) == 0)
nOpt &= ~DbGridControlOptions::Delete;
} else
nOpt = DbGridControlOptions::Readonly;
// need to do something after that ? if (nOpt == m_nOptions) return m_nOptions;
// the 'update' option only affects our BrowserMode (with or w/o focus rect)
BrowserMode nNewMode = m_nMode; if (!(m_nMode & BrowserMode::CURSOR_WO_FOCUS))
{ if (nOpt & DbGridControlOptions::Update)
nNewMode |= BrowserMode::HIDECURSOR; else
nNewMode &= ~BrowserMode::HIDECURSOR;
} else
nNewMode &= ~BrowserMode::HIDECURSOR; // should not be necessary if EnablePermanentCursor is used to change the cursor behaviour, but to be sure ...
if (nNewMode != m_nMode)
{
SetMode(nNewMode);
m_nMode = nNewMode;
}
// _after_ setting the mode because this results in an ActivateCell
DeactivateCell();
bool bInsertChanged = (nOpt & DbGridControlOptions::Insert) != (m_nOptions & DbGridControlOptions::Insert);
m_nOptions = nOpt; // we need to set this before the code below because it indirectly uses m_nOptions
// the 'insert' option affects our empty row if (bInsertChanged)
{ if (m_nOptions & DbGridControlOptions::Insert)
{ // the insert option is to be set
m_xEmptyRow = new DbGridRow();
RowInserted(GetRowCount());
} else
{ // the insert option is to be reset
m_xEmptyRow = nullptr; if ((GetCurRow() == GetRowCount() - 1) && (GetCurRow() > 0))
GoToRowColumnId(GetCurRow() - 1, GetCurColumnId());
RowRemoved(GetRowCount());
}
}
// the 'delete' options has no immediate consequences
void DbGridControl::EnablePermanentCursor(bool bEnable)
{ if (IsPermanentCursorEnabled() == bEnable) return;
if (bEnable)
{
m_nMode &= ~BrowserMode::HIDECURSOR; // without this BrowserMode::CURSOR_WO_FOCUS won't have any affect
m_nMode |= BrowserMode::CURSOR_WO_FOCUS;
} else
{ if (m_nOptions & DbGridControlOptions::Update)
m_nMode |= BrowserMode::HIDECURSOR; // no cursor at all else
m_nMode &= ~BrowserMode::HIDECURSOR; // at least the "non-permanent" cursor
void DbGridControl::refreshController(sal_uInt16 _nColId, GrantControlAccess /*_aAccess*/)
{ if ((GetCurColumnId() == _nColId) && IsEditing())
{ // the controller which is currently active needs to be refreshed
DeactivateCell();
ActivateCell();
}
}
if (m_pDataSourcePropMultiplexer.is())
{
m_pDataSourcePropMultiplexer->dispose();
m_pDataSourcePropMultiplexer.clear(); // this should delete the multiplexer delete m_pDataSourcePropListener;
m_pDataSourcePropListener = nullptr;
}
m_xRowSetListener.clear();
// is the new cursor valid ? // the cursor is only valid if it contains some columns // if there is no cursor or the cursor is not valid we have to clean up and leave if (!_xCursor.is() || !Reference< XColumnsSupplier > (_xCursor, UNO_QUERY_THROW)->getColumns()->hasElements())
{
RemoveRows(); return;
}
// did the data cursor change?
sal_uInt16 nCurPos = GetColumnPos(GetCurColumnId());
{
::osl::MutexGuard aGuard(m_aAdjustSafety); if (m_nAsynAdjustEvent)
{ // the adjust was thought to work with the old cursor which we don't have anymore
RemoveUserEvent(m_nAsynAdjustEvent);
m_nAsynAdjustEvent = nullptr;
}
}
// get a new formatter and data cursor
m_xFormatter = nullptr;
Reference< css::util::XNumberFormatsSupplier > xSupplier = getNumberFormats(getConnection(_xCursor), true); if (xSupplier.is())
{
m_xFormatter = css::util::NumberFormatter::create(m_xContext);
m_xFormatter->attachNumberFormatsSupplier(xSupplier);
// retrieve the datebase of the Numberformatter try
{
xSupplier->getNumberFormatSettings()->getPropertyValue(u"NullDate"_ustr) >>= m_aNullDate;
} catch(Exception&)
{
}
}
m_pDataCursor.reset(new CursorWrapper(_xCursor));
// now create a cursor for painting rows // we need that cursor only if we are not in insert only mode
Reference< XResultSet > xClone;
Reference< XResultSetAccess > xAccess( _xCursor, UNO_QUERY ); try
{
xClone = xAccess.is() ? xAccess->createResultSet() : Reference< XResultSet > ();
} catch(Exception&)
{
} if (xClone.is())
m_pSeekCursor.reset(new CursorWrapper(xClone));
// property listening on the data source // (Normally one class would be sufficient : the multiplexer which could forward the property change to us. // But for that we would have been derived from ::comphelper::OPropertyChangeListener, which isn't exported. // So we introduce a second class, which is a ::comphelper::OPropertyChangeListener (in the implementation file we know this class) // and forwards the property changes to our special method "DataSourcePropertyChanged".) if (m_pDataCursor)
{
m_pDataSourcePropListener = new FmXGridSourcePropListener(this);
m_pDataSourcePropMultiplexer = new ::comphelper::OPropertyChangeMultiplexer(m_pDataSourcePropListener, m_pDataCursor->getPropertySet() );
m_pDataSourcePropMultiplexer->addProperty(FM_PROP_ISMODIFIED);
m_pDataSourcePropMultiplexer->addProperty(FM_PROP_ISNEW);
}
BrowserMode nOldMode = m_nMode; if (m_pSeekCursor)
{ try
{
Reference< XPropertySet > xSet(_xCursor, UNO_QUERY); if (xSet.is())
{ // check what kind of options are available
sal_Int32 nConcurrency = ResultSetConcurrency::READ_ONLY;
xSet->getPropertyValue(FM_PROP_RESULTSET_CONCURRENCY) >>= nConcurrency;
m_xRowSetListener = new RowSetEventListener(this);
Reference< XRowsChangeBroadcaster> xChangeBroad(xSet,UNO_QUERY); if ( xChangeBroad.is( ) )
xChangeBroad->addRowsChangeListener(m_xRowSetListener);
// insert the currently known rows // and one row if we are able to insert rows if (m_nOptions & DbGridControlOptions::Insert)
{ // insert the empty row for insertion
m_xEmptyRow = new DbGridRow();
++nRecordCount;
} if (nRecordCount)
{
m_xPaintRow = m_xSeekRow = new DbGridRow(m_pSeekCursor.get(), true);
m_xDataRow = new DbGridRow(m_pDataCursor.get(), false);
RowInserted(0, nRecordCount, false);
if (m_xSeekRow->IsValid()) try
{
m_nSeekPos = m_pSeekCursor->getRow() - 1;
} catch( const Exception& )
{
DBG_UNHANDLED_EXCEPTION("svx");
m_nSeekPos = -1;
}
} else
{ // no rows so we don't need a seekcursor
m_pSeekCursor.reset();
}
}
// go to the old column if (nCurPos == BROWSER_INVALIDID || nCurPos >= ColCount())
nCurPos = 0;
// Column zero is a valid choice and guaranteed to exist, // but invisible to the user; if we have at least one // user-visible column, go to that one. if (nCurPos == 0 && ColCount() > 1)
nCurPos = 1;
// there are rows so go to the selected current column if (nRecordCount)
GoToRowColumnId(0, GetColumnId(nCurPos)); // else stop the editing if necessary elseif (IsEditing())
DeactivateCell();
// now reset the mode if (m_nMode != nOldMode)
SetMode(m_nMode);
// RecalcRows was already called while resizing if (!IsResizing() && GetRowCount())
RecalcRows(GetTopRow(), GetVisibleRows(), true);
sal_uInt16 DbGridControl::AppendColumn(const OUString& rName, sal_uInt16 nWidth, sal_uInt16 nModelPos, sal_uInt16 nId)
{
DBG_ASSERT(nId == BROWSER_INVALIDID, "DbGridControl::AppendColumn : I want to set the ID myself ...");
sal_uInt16 nRealPos = nModelPos; if (nModelPos != HEADERBAR_APPEND)
{ // calc the view pos. we can't use our converting functions because the new column // has no VCL-representation, yet.
sal_Int16 nViewPos = nModelPos; while (nModelPos--)
{ if ( m_aColumns[ nModelPos ]->IsHidden() )
--nViewPos;
} // restore nModelPos, we need it later
nModelPos = nRealPos; // the position the base class gets is the view pos + 1 (because of the handle column)
nRealPos = nViewPos + 1;
}
// calculate the new id for (nId=1; (GetModelColumnPos(nId) != GRID_COLUMN_NOT_FOUND) && size_t(nId) <= m_aColumns.size(); ++nId)
;
DBG_ASSERT(GetViewColumnPos(nId) == GRID_COLUMN_NOT_FOUND, "DbGridControl::AppendColumn : inconsistent internal state !"); // my column's models say "there is no column with id nId", but the view (the base class) says "there is a column ..."
// remove the col from the model
sal_uInt16 nOldModelPos = GetModelColumnPos(nId); #ifdef DBG_UTIL
DbGridColumn* pCol = m_aColumns[ nOldModelPos ].get();
DBG_ASSERT(!pCol->IsHidden(), "DbGridControl::ColumnMoved : moved a hidden col ? how this ?"); #endif
// for the new model pos we can't use GetModelColumnPos because we are altering the model at the moment // so the method won't work (in fact it would return the old model pos)
// the new view pos is calculated easily
sal_uInt16 nNewViewPos = GetViewColumnPos(nId);
// from that we can compute the new model pos
size_t nNewModelPos; for (nNewModelPos = 0; nNewModelPos < m_aColumns.size(); ++nNewModelPos)
{ if (!m_aColumns[ nNewModelPos ]->IsHidden())
{ if (!nNewViewPos) break; else
--nNewViewPos;
}
}
DBG_ASSERT( nNewModelPos < m_aColumns.size(), "DbGridControl::ColumnMoved : could not find the new model position !");
// this will work. of course the model isn't fully consistent with our view right now, but let's // look at the situation : a column has been moved with in the VIEW from pos m to n, say m<n (in the // other case we can use analogue arguments). // All cols k with m<k<=n have been shifted left on pos, the former col m now has pos n. // In the model this affects a range of cols x to y, where x<=m and y<=n. And the number of hidden cols // within this range is constant, so we may calculate the view pos from the model pos in the above way.
// for instance, let's look at a grid with six columns where the third one is hidden. this will // initially look like this :
// We know the new view pos (3) of the moved column because our base class tells us. So we look at our // model for the 4th (the pos is zero-based) visible column, it is at (model) position 4. And this is // exactly the pos where we have to re-insert our column's model, so it looks ike this :
// Now, all is consistent again. // (except of the hidden column : The cycling of the cols occurred on the model, not on the view. maybe // the user expected the latter but there really is no good argument against our method ;) ...)
// And no, this large explanation isn't just because I wanted to play a board game or something like // that. It's because it took me a while to see it myself, and the whole theme (hidden cols, model col // positions, view col positions) is really painful (at least for me) so the above pictures helped me a lot ;)
bool DbGridControl::SeekRow(sal_Int32 nRow)
{ // in filter mode or in insert only mode we don't have any cursor! if ( !SeekCursor( nRow ) ) returnfalse;
if ( IsFilterMode() )
{
DBG_ASSERT( IsFilterRow( nRow ), "DbGridControl::SeekRow(): No filter row, wrong mode" );
m_xPaintRow = m_xEmptyRow;
} else
{ // on the current position we have to take the current row for display as we want // to have the most recent values for display if ( ( nRow == m_nCurrentPos ) && getDisplaySynchron() )
m_xPaintRow = m_xCurrentRow; // seek to the empty insert row elseif ( IsInsertionRow( nRow ) )
m_xPaintRow = m_xEmptyRow; else
{
m_xSeekRow->SetState( m_pSeekCursor.get(), true );
m_xPaintRow = m_xSeekRow;
}
}
EditBrowseBox::SeekRow(nRow);
return m_nSeekPos >= 0;
}
// Is called whenever the visible amount of data changes void DbGridControl::VisibleRowsChanged( sal_Int32 nNewTopRow, sal_uInt16 nLinesOnScreen )
{
RecalcRows(nNewTopRow, nLinesOnScreen, false);
}
void DbGridControl::RecalcRows(sal_Int32 nNewTopRow, sal_uInt16 nLinesOnScreen, bool bUpdateCursor)
{ // If no cursor -> no rows in the browser. if (!m_pSeekCursor)
{
DBG_ASSERT(GetRowCount() == 0,"DbGridControl: without cursor no rows are allowed to be there"); return;
}
// ignore any implicitly made updates bool bDisablePaint = !bUpdateCursor && IsPaintEnabled(); if (bDisablePaint)
EnablePaint(false);
// adjust cache to the visible area
Reference< XPropertySet > xSet = m_pSeekCursor->getPropertySet();
sal_Int32 nCacheSize = 0;
xSet->getPropertyValue(FM_PROP_FETCHSIZE) >>= nCacheSize; bool bCacheAligned = false; // no further cursor movements after initializing (m_nSeekPos < 0) because it is already // positioned on the first sentence
tools::Long nDelta = nNewTopRow - GetTopRow(); // limit for relative positioning
tools::Long nLimit = nCacheSize ? nCacheSize / 2 : 0;
// more lines on screen than in cache if (nLimit < nLinesOnScreen)
{
Any aCacheSize;
aCacheSize <<= sal_Int32(nLinesOnScreen*2);
xSet->setPropertyValue(FM_PROP_FETCHSIZE, aCacheSize); // here we need to update the cursor for sure
bUpdateCursor = true;
bCacheAligned = true;
nLimit = nLinesOnScreen;
}
// In the following, all positionings are done as it is // ensured that there are enough lines in the data cache
// window goes downwards with less than two windows difference or // the cache was updated and no rowcount yet if (nDelta < nLimit && (nDelta > 0
|| (bCacheAligned && m_nTotalCount < 0)) )
SeekCursor(nNewTopRow + nLinesOnScreen - 1); elseif (nDelta < 0 && std::abs(nDelta) < nLimit)
SeekCursor(nNewTopRow); elseif (nDelta != 0 || bUpdateCursor)
SeekCursor(nNewTopRow, true);
AdjustRows();
// ignore any updates implicit made
EnablePaint(true);
}
if (m_bRecordCountFinal && m_nTotalCount < 0)
{ // if we have an insert row we have to reduce to count by 1 // as the total count reflects only the existing rows in database
m_nTotalCount = GetRowCount() + nNumRows; if (m_xEmptyRow.is())
--m_nTotalCount;
} elseif (m_nTotalCount >= 0)
m_nTotalCount += nNumRows;
if (m_bRecordCountFinal && m_nTotalCount < 0)
{
m_nTotalCount = GetRowCount() - nNumRows; // if we have an insert row reduce by 1 if (m_xEmptyRow.is())
--m_nTotalCount;
} elseif (m_nTotalCount >= 0)
m_nTotalCount -= nNumRows;
// Did the number of rows change? // Here we need to consider that there might be an additional row for adding new data sets
// add additional AppendRow for insertion if (m_nOptions & DbGridControlOptions::Insert)
++nRecordCount;
// If there is currently an insertion, so do not consider this added row in RecordCount or Appendrow if (!IsUpdating() && m_bRecordCountFinal && IsModified() && m_xCurrentRow != m_xEmptyRow &&
m_xCurrentRow->IsNew())
++nRecordCount; // ensured with !m_bUpdating: otherwise the edited data set (that SaveRow added and why this // method was called) would be called twice (if m_bUpdating == sal_True): once in RecordCount // and a second time here (60787 - FS)
if (nRecordCount != GetRowCount())
{
tools::Long nDelta = GetRowCount() - static_cast<tools::Long>(nRecordCount); if (nDelta > 0) // too many
{
RowRemoved(GetRowCount() - nDelta, nDelta, false); // some rows are gone, thus, repaint starting at the current position
Invalidate();
sal_Int32 nNewPos = AlignSeekCursor(); if (m_bSynchDisplay)
EditBrowseBox::GoToRow(nNewPos);
SetCurrent(nNewPos); // there are rows so go to the selected current column if (nRecordCount)
GoToRowColumnId(nNewPos, GetColumnId(GetCurColumnId())); if (!IsResizing() && GetRowCount())
RecalcRows(GetTopRow(), GetVisibleRows(), true);
m_aBar->InvalidateAll(m_nCurrentPos, true);
} else// too few
RowInserted(GetRowCount(), -nDelta);
}
bool DbGridControl::SetCurrent(sal_Int32 nNewRow)
{ // Each movement of the datacursor must start with BeginCursorAction and end with // EndCursorAction to block all notifications during the movement
BeginCursorAction();
try
{ // compare positions if (SeekCursor(nNewRow))
{ if (IsFilterRow(nNewRow)) // special mode for filtering
{
m_xCurrentRow = m_xDataRow = m_xPaintRow = m_xEmptyRow;
m_nCurrentPos = nNewRow;
} else
{ bool bNewRowInserted = false; // Should we go to the insertrow ? if (IsInsertionRow(nNewRow))
{ // to we need to move the cursor to the insert row? // we need to insert the if the current row isn't the insert row or if the // cursor triggered the move by itself and we need a reinitialization of the row
Reference< XPropertySet > xCursorProps = m_pDataCursor->getPropertySet(); if ( !::comphelper::getBOOL(xCursorProps->getPropertyValue(FM_PROP_ISNEW)) )
{
Reference< XResultSetUpdate > xUpdateCursor(Reference< XInterface >(*m_pDataCursor), UNO_QUERY);
xUpdateCursor->moveToInsertRow();
}
bNewRowInserted = true;
} else
{
if ( !m_pSeekCursor->isBeforeFirst() && !m_pSeekCursor->isAfterLast() )
{
Any aBookmark = m_pSeekCursor->getBookmark(); if (!m_xCurrentRow.is() || m_xCurrentRow->IsNew() || !CompareBookmark(aBookmark, m_pDataCursor->getBookmark()))
{ // adjust the cursor to the new desired row if (!m_pDataCursor->moveToBookmark(aBookmark))
{
EndCursorAction(); returnfalse;
}
}
}
}
m_xDataRow->SetState(m_pDataCursor.get(), false);
m_xCurrentRow = m_xDataRow;
tools::Long nPaintPos = -1; // do we have to repaint the last regular row in case of setting defaults or autovalues if (m_nCurrentPos >= 0 && m_nCurrentPos >= (GetRowCount() - 2))
nPaintPos = m_nCurrentPos;
m_nCurrentPos = nNewRow;
// repaint the new row to display all defaults if (bNewRowInserted)
RowModified(m_nCurrentPos); if (nPaintPos >= 0)
RowModified(nPaintPos);
}
} else
{
OSL_FAIL("DbGridControl::SetCurrent : SeekRow failed !");
EndCursorAction(); returnfalse;
}
} catch ( const Exception& )
{
DBG_UNHANDLED_EXCEPTION("svx");
EndCursorAction(); returnfalse;
}
EndCursorAction(); returntrue;
}
void DbGridControl::CursorMoved()
{
// cursor movement due to deletion or insertion of rows if (m_pDataCursor && m_nCurrentPos != GetCurRow())
{
DeactivateCell();
SetCurrent(GetCurRow());
}
// select the new column when they moved if ( IsDesignMode() && GetSelectedColumnCount() > 0 && GetCurColumnId() )
{
SelectColumnId( GetCurColumnId() );
}
if ( m_nLastColId != GetCurColumnId() )
onColumnChange();
m_nLastColId = GetCurColumnId();
if ( m_nLastRowId != GetCurRow() )
--> --------------------
--> maximum size reached
--> --------------------
Messung V0.5
¤ Dauer der Verarbeitung: 0.22 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.