| /************************************************************** |
| * |
| * 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 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_svtools.hxx" |
| #include "imivctl.hxx" |
| |
| IcnCursor_Impl::IcnCursor_Impl( SvxIconChoiceCtrl_Impl* pOwner ) |
| { |
| pView = pOwner; |
| pColumns = 0; |
| pRows = 0; |
| pCurEntry = 0; |
| nDeltaWidth = 0; |
| nDeltaHeight= 0; |
| nCols = 0; |
| nRows = 0; |
| } |
| |
| IcnCursor_Impl::~IcnCursor_Impl() |
| { |
| delete[] pColumns; |
| delete[] pRows; |
| } |
| |
| sal_uInt16 IcnCursor_Impl::GetSortListPos( SvPtrarr* pList, long nValue, |
| int bVertical ) |
| { |
| sal_uInt16 nCount = (sal_uInt16)pList->Count(); |
| if( !nCount ) |
| return 0; |
| |
| sal_uInt16 nCurPos = 0; |
| long nPrevValue = LONG_MIN; |
| while( nCount ) |
| { |
| const Rectangle& rRect= |
| pView->GetEntryBoundRect((SvxIconChoiceCtrlEntry*)(pList->GetObject(nCurPos))); |
| long nCurValue; |
| if( bVertical ) |
| nCurValue = rRect.Top(); |
| else |
| nCurValue = rRect.Left(); |
| if( nValue >= nPrevValue && nValue <= nCurValue ) |
| return (sal_uInt16)nCurPos; |
| nPrevValue = nCurValue; |
| nCount--; |
| nCurPos++; |
| } |
| return pList->Count(); |
| } |
| |
| void IcnCursor_Impl::ImplCreate() |
| { |
| pView->CheckBoundingRects(); |
| DBG_ASSERT(pColumns==0&&pRows==0,"ImplCreate: Not cleared"); |
| |
| SetDeltas(); |
| |
| pColumns = new SvPtrarr[ nCols ]; |
| pRows = new SvPtrarr[ nRows ]; |
| |
| sal_uLong nCount = pView->aEntries.Count(); |
| for( sal_uLong nCur = 0; nCur < nCount; nCur++ ) |
| { |
| SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)pView->aEntries.GetObject( nCur ); |
| // const Rectangle& rRect = pView->GetEntryBoundRect( pEntry ); |
| Rectangle rRect( pView->CalcBmpRect( pEntry,0 ) ); |
| short nY = (short)( ((rRect.Top()+rRect.Bottom())/2) / nDeltaHeight ); |
| short nX = (short)( ((rRect.Left()+rRect.Right())/2) / nDeltaWidth ); |
| |
| // Rundungsfehler abfangen |
| if( nY >= nRows ) |
| nY = sal::static_int_cast< short >(nRows - 1); |
| if( nX >= nCols ) |
| nX = sal::static_int_cast< short >(nCols - 1); |
| |
| sal_uInt16 nIns = GetSortListPos( &pColumns[nX], rRect.Top(), sal_True ); |
| pColumns[ nX ].Insert( pEntry, nIns ); |
| |
| nIns = GetSortListPos( &pRows[nY], rRect.Left(), sal_False ); |
| pRows[ nY ].Insert( pEntry, nIns ); |
| |
| pEntry->nX = nX; |
| pEntry->nY = nY; |
| } |
| } |
| |
| |
| |
| |
| void IcnCursor_Impl::Clear() |
| { |
| if( pColumns ) |
| { |
| delete[] pColumns; |
| delete[] pRows; |
| pColumns = 0; |
| pRows = 0; |
| pCurEntry = 0; |
| nDeltaWidth = 0; |
| nDeltaHeight = 0; |
| } |
| } |
| |
| SvxIconChoiceCtrlEntry* IcnCursor_Impl::SearchCol(sal_uInt16 nCol,sal_uInt16 nTop,sal_uInt16 nBottom, |
| sal_uInt16, sal_Bool bDown, sal_Bool bSimple ) |
| { |
| DBG_ASSERT(pCurEntry,"SearchCol: No reference entry"); |
| SvPtrarr* pList = &(pColumns[ nCol ]); |
| const sal_uInt16 nCount = pList->Count(); |
| if( !nCount ) |
| return 0; |
| |
| const Rectangle& rRefRect = pView->GetEntryBoundRect(pCurEntry); |
| |
| if( bSimple ) |
| { |
| sal_uInt16 nListPos = pList->GetPos( pCurEntry ); |
| DBG_ASSERT(nListPos!=0xffff,"Entry not in Col-List"); |
| if( bDown ) |
| { |
| while( nListPos < nCount-1 ) |
| { |
| nListPos++; |
| SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)pList->GetObject( nListPos ); |
| const Rectangle& rRect = pView->GetEntryBoundRect( pEntry ); |
| if( rRect.Top() > rRefRect.Top() ) |
| return pEntry; |
| } |
| return 0; |
| } |
| else |
| { |
| while( nListPos ) |
| { |
| nListPos--; |
| if( nListPos < nCount ) |
| { |
| SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)pList->GetObject( nListPos ); |
| const Rectangle& rRect = pView->GetEntryBoundRect( pEntry ); |
| if( rRect.Top() < rRefRect.Top() ) |
| return pEntry; |
| } |
| } |
| return 0; |
| } |
| } |
| |
| if( nTop > nBottom ) |
| { |
| sal_uInt16 nTemp = nTop; |
| nTop = nBottom; |
| nBottom = nTemp; |
| } |
| long nMinDistance = LONG_MAX; |
| SvxIconChoiceCtrlEntry* pResult = 0; |
| for( sal_uInt16 nCur = 0; nCur < nCount; nCur++ ) |
| { |
| SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)(pList->GetObject( nCur )); |
| if( pEntry != pCurEntry ) |
| { |
| sal_uInt16 nY = pEntry->nY; |
| if( nY >= nTop && nY <= nBottom ) |
| { |
| const Rectangle& rRect = pView->GetEntryBoundRect( pEntry ); |
| long nDistance = rRect.Top() - rRefRect.Top(); |
| if( nDistance < 0 ) |
| nDistance *= -1; |
| if( nDistance && nDistance < nMinDistance ) |
| { |
| nMinDistance = nDistance; |
| pResult = pEntry; |
| } |
| } |
| } |
| } |
| return pResult; |
| } |
| |
| SvxIconChoiceCtrlEntry* IcnCursor_Impl::SearchRow(sal_uInt16 nRow,sal_uInt16 nLeft,sal_uInt16 nRight, |
| sal_uInt16, sal_Bool bRight, sal_Bool bSimple ) |
| { |
| DBG_ASSERT(pCurEntry,"SearchRow: No reference entry"); |
| SvPtrarr* pList = &(pRows[ nRow ]); |
| const sal_uInt16 nCount = pList->Count(); |
| if( !nCount ) |
| return 0; |
| |
| const Rectangle& rRefRect = pView->GetEntryBoundRect(pCurEntry); |
| |
| if( bSimple ) |
| { |
| sal_uInt16 nListPos = pList->GetPos( pCurEntry ); |
| DBG_ASSERT(nListPos!=0xffff,"Entry not in Row-List"); |
| if( bRight ) |
| { |
| while( nListPos < nCount-1 ) |
| { |
| nListPos++; |
| SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)pList->GetObject( nListPos ); |
| const Rectangle& rRect = pView->GetEntryBoundRect( pEntry ); |
| if( rRect.Left() > rRefRect.Left() ) |
| return pEntry; |
| } |
| return 0; |
| } |
| else |
| { |
| while( nListPos ) |
| { |
| nListPos--; |
| if( nListPos < nCount ) |
| { |
| SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)pList->GetObject( nListPos ); |
| const Rectangle& rRect = pView->GetEntryBoundRect( pEntry ); |
| if( rRect.Left() < rRefRect.Left() ) |
| return pEntry; |
| } |
| } |
| return 0; |
| } |
| |
| } |
| if( nRight < nLeft ) |
| { |
| sal_uInt16 nTemp = nRight; |
| nRight = nLeft; |
| nLeft = nTemp; |
| } |
| long nMinDistance = LONG_MAX; |
| SvxIconChoiceCtrlEntry* pResult = 0; |
| for( sal_uInt16 nCur = 0; nCur < nCount; nCur++ ) |
| { |
| SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)(pList->GetObject( nCur )); |
| if( pEntry != pCurEntry ) |
| { |
| sal_uInt16 nX = pEntry->nX; |
| if( nX >= nLeft && nX <= nRight ) |
| { |
| const Rectangle& rRect = pView->GetEntryBoundRect( pEntry ); |
| long nDistance = rRect.Left() - rRefRect.Left(); |
| if( nDistance < 0 ) |
| nDistance *= -1; |
| if( nDistance && nDistance < nMinDistance ) |
| { |
| nMinDistance = nDistance; |
| pResult = pEntry; |
| } |
| } |
| } |
| } |
| return pResult; |
| } |
| |
| |
| |
| /* |
| Sucht ab dem uebergebenen Eintrag den naechsten rechts- bzw. |
| linksstehenden. Suchverfahren am Beispiel bRight = sal_True: |
| |
| c |
| b c |
| a b c |
| S 1 1 1 ====> Suchrichtung |
| a b c |
| b c |
| c |
| |
| S : Startposition |
| 1 : erstes Suchrechteck |
| a,b,c : 2., 3., 4. Suchrechteck |
| */ |
| |
| SvxIconChoiceCtrlEntry* IcnCursor_Impl::GoLeftRight( SvxIconChoiceCtrlEntry* pCtrlEntry, sal_Bool bRight ) |
| { |
| SvxIconChoiceCtrlEntry* pResult; |
| pCurEntry = pCtrlEntry; |
| Create(); |
| sal_uInt16 nY = pCtrlEntry->nY; |
| sal_uInt16 nX = pCtrlEntry->nX; |
| DBG_ASSERT(nY< nRows,"GoLeftRight:Bad column"); |
| DBG_ASSERT(nX< nCols,"GoLeftRight:Bad row"); |
| // Nachbar auf gleicher Zeile ? |
| if( bRight ) |
| pResult = SearchRow( |
| nY, nX, sal::static_int_cast< sal_uInt16 >(nCols-1), nX, sal_True, sal_True ); |
| else |
| pResult = SearchRow( nY, nX ,0, nX, sal_False, sal_True ); |
| if( pResult ) |
| return pResult; |
| |
| long nCurCol = nX; |
| |
| long nColOffs, nLastCol; |
| if( bRight ) |
| { |
| nColOffs = 1; |
| nLastCol = nCols; |
| } |
| else |
| { |
| nColOffs = -1; |
| nLastCol = -1; // 0-1 |
| } |
| |
| sal_uInt16 nRowMin = nY; |
| sal_uInt16 nRowMax = nY; |
| do |
| { |
| SvxIconChoiceCtrlEntry* pEntry = SearchCol((sal_uInt16)nCurCol,nRowMin,nRowMax,nY,sal_True, sal_False); |
| if( pEntry ) |
| return pEntry; |
| if( nRowMin ) |
| nRowMin--; |
| if( nRowMax < (nRows-1)) |
| nRowMax++; |
| nCurCol += nColOffs; |
| } while( nCurCol != nLastCol ); |
| return 0; |
| } |
| |
| SvxIconChoiceCtrlEntry* IcnCursor_Impl::GoPageUpDown( SvxIconChoiceCtrlEntry* pStart, sal_Bool bDown) |
| { |
| if( pView->IsAutoArrange() && !(pView->nWinBits & WB_ALIGN_TOP) ) |
| { |
| const long nPos = (long)pView->GetEntryListPos( pStart ); |
| long nEntriesInView = (pView->aOutputSize.Height() / pView->nGridDY); |
| nEntriesInView *= |
| ((pView->aOutputSize.Width()+(pView->nGridDX/2)) / pView->nGridDX ); |
| long nNewPos = nPos; |
| if( bDown ) |
| { |
| nNewPos += nEntriesInView; |
| if( nNewPos >= (long)pView->aEntries.Count() ) |
| nNewPos = pView->aEntries.Count() - 1; |
| } |
| else |
| { |
| nNewPos -= nEntriesInView; |
| if( nNewPos < 0 ) |
| nNewPos = 0; |
| } |
| if( nPos != nNewPos ) |
| return (SvxIconChoiceCtrlEntry*)pView->aEntries.GetObject( (sal_uLong)nNewPos ); |
| return 0; |
| } |
| long nOpt = pView->GetEntryBoundRect( pStart ).Top(); |
| if( bDown ) |
| { |
| nOpt += pView->aOutputSize.Height(); |
| nOpt -= pView->nGridDY; |
| } |
| else |
| { |
| nOpt -= pView->aOutputSize.Height(); |
| nOpt += pView->nGridDY; |
| } |
| if( nOpt < 0 ) |
| nOpt = 0; |
| |
| long nPrevErr = LONG_MAX; |
| |
| SvxIconChoiceCtrlEntry* pPrev = pStart; |
| SvxIconChoiceCtrlEntry* pNext = GoUpDown( pStart, bDown ); |
| while( pNext ) |
| { |
| long nCur = pView->GetEntryBoundRect( pNext ).Top(); |
| long nErr = nOpt - nCur; |
| if( nErr < 0 ) |
| nErr *= -1; |
| if( nErr > nPrevErr ) |
| return pPrev; |
| nPrevErr = nErr; |
| pPrev = pNext; |
| pNext = GoUpDown( pNext, bDown ); |
| } |
| if( pPrev != pStart ) |
| return pPrev; |
| return 0; |
| } |
| |
| SvxIconChoiceCtrlEntry* IcnCursor_Impl::GoUpDown( SvxIconChoiceCtrlEntry* pCtrlEntry, sal_Bool bDown) |
| { |
| if( pView->IsAutoArrange() && !(pView->nWinBits & WB_ALIGN_TOP) ) |
| { |
| sal_uLong nPos = pView->GetEntryListPos( pCtrlEntry ); |
| if( bDown && nPos < (pView->aEntries.Count() - 1) ) |
| return (SvxIconChoiceCtrlEntry*)pView->aEntries.GetObject( nPos + 1 ); |
| else if( !bDown && nPos > 0 ) |
| return (SvxIconChoiceCtrlEntry*)pView->aEntries.GetObject( nPos - 1 ); |
| return 0; |
| } |
| |
| SvxIconChoiceCtrlEntry* pResult; |
| pCurEntry = pCtrlEntry; |
| Create(); |
| sal_uInt16 nY = pCtrlEntry->nY; |
| sal_uInt16 nX = pCtrlEntry->nX; |
| DBG_ASSERT(nY<nRows,"GoUpDown:Bad column"); |
| DBG_ASSERT(nX<nCols,"GoUpDown:Bad row"); |
| |
| // Nachbar in gleicher Spalte ? |
| if( bDown ) |
| pResult = SearchCol( |
| nX, nY, sal::static_int_cast< sal_uInt16 >(nRows-1), nY, sal_True, sal_True ); |
| else |
| pResult = SearchCol( nX, nY ,0, nY, sal_False, sal_True ); |
| if( pResult ) |
| return pResult; |
| |
| long nCurRow = nY; |
| |
| long nRowOffs, nLastRow; |
| if( bDown ) |
| { |
| nRowOffs = 1; |
| nLastRow = nRows; |
| } |
| else |
| { |
| nRowOffs = -1; |
| nLastRow = -1; // 0-1 |
| } |
| |
| sal_uInt16 nColMin = nX; |
| sal_uInt16 nColMax = nX; |
| do |
| { |
| SvxIconChoiceCtrlEntry* pEntry = SearchRow((sal_uInt16)nCurRow,nColMin,nColMax,nX,sal_True, sal_False); |
| if( pEntry ) |
| return pEntry; |
| if( nColMin ) |
| nColMin--; |
| if( nColMax < (nCols-1)) |
| nColMax++; |
| nCurRow += nRowOffs; |
| } while( nCurRow != nLastRow ); |
| return 0; |
| } |
| |
| void IcnCursor_Impl::SetDeltas() |
| { |
| const Size& rSize = pView->aVirtOutputSize; |
| nCols = rSize.Width() / pView->nGridDX; |
| if( !nCols ) |
| nCols = 1; |
| nRows = rSize.Height() / pView->nGridDY; |
| if( (nRows * pView->nGridDY) < rSize.Height() ) |
| nRows++; |
| if( !nRows ) |
| nRows = 1; |
| |
| nDeltaWidth = (short)(rSize.Width() / nCols); |
| nDeltaHeight = (short)(rSize.Height() / nRows); |
| if( !nDeltaHeight ) |
| { |
| nDeltaHeight = 1; |
| DBG_WARNING("SetDeltas:Bad height"); |
| } |
| if( !nDeltaWidth ) |
| { |
| nDeltaWidth = 1; |
| DBG_WARNING("SetDeltas:Bad width"); |
| } |
| } |
| |
| void IcnCursor_Impl::CreateGridAjustData( SvPtrarr& rLists, SvxIconChoiceCtrlEntry* pRefEntry) |
| { |
| if( !pRefEntry ) |
| { |
| sal_uInt16 nGridRows = (sal_uInt16)(pView->aVirtOutputSize.Height() / pView->nGridDY); |
| nGridRows++; // wg. Abrundung! |
| |
| if( !nGridRows ) |
| return; |
| for( sal_uInt16 nCurList = 0; nCurList < nGridRows; nCurList++ ) |
| { |
| SvPtrarr* pRow = new SvPtrarr; |
| rLists.Insert( (void*)pRow, nCurList ); |
| } |
| const sal_uLong nCount = pView->aEntries.Count(); |
| for( sal_uLong nCur = 0; nCur < nCount; nCur++ ) |
| { |
| SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)pView->aEntries.GetObject( nCur ); |
| const Rectangle& rRect = pView->GetEntryBoundRect( pEntry ); |
| short nY = (short)( ((rRect.Top()+rRect.Bottom())/2) / pView->nGridDY ); |
| sal_uInt16 nIns = GetSortListPos((SvPtrarr*)rLists[nY],rRect.Left(),sal_False); |
| ((SvPtrarr*)rLists[ nY ])->Insert( pEntry, nIns ); |
| } |
| } |
| else |
| { |
| // Aufbau eines hor. "Schlauchs" auf der RefEntry-Zeile |
| // UEBERLEGEN: BoundingRect nehmen wg. Ueberlappungen??? |
| Rectangle rRefRect( pView->CalcBmpRect( pRefEntry ) ); |
| //const Rectangle& rRefRect = pView->GetEntryBoundRect( pRefEntry ); |
| short nRefRow = (short)( ((rRefRect.Top()+rRefRect.Bottom())/2) / pView->nGridDY ); |
| SvPtrarr* pRow = new SvPtrarr; |
| rLists.Insert( (void*)pRow, 0 ); |
| sal_uLong nCount = pView->aEntries.Count(); |
| for( sal_uLong nCur = 0; nCur < nCount; nCur++ ) |
| { |
| SvxIconChoiceCtrlEntry* pEntry = (SvxIconChoiceCtrlEntry*)pView->aEntries.GetObject( nCur ); |
| Rectangle rRect( pView->CalcBmpRect(pEntry) ); |
| //const Rectangle& rRect = pView->GetEntryBoundRect( pEntry ); |
| short nY = (short)( ((rRect.Top()+rRect.Bottom())/2) / pView->nGridDY ); |
| if( nY == nRefRow ) |
| { |
| sal_uInt16 nIns = GetSortListPos( pRow, rRect.Left(), sal_False ); |
| pRow->Insert( pEntry, nIns ); |
| } |
| } |
| } |
| } |
| |
| //static |
| void IcnCursor_Impl::DestroyGridAdjustData( SvPtrarr& rLists ) |
| { |
| const sal_uInt16 nCount = rLists.Count(); |
| for( sal_uInt16 nCur = 0; nCur < nCount; nCur++ ) |
| { |
| SvPtrarr* pArr = (SvPtrarr*)rLists[ nCur ]; |
| delete pArr; |
| } |
| rLists.Remove( 0, rLists.Count() ); |
| } |
| |
| IcnGridMap_Impl::IcnGridMap_Impl(SvxIconChoiceCtrl_Impl* pView) |
| { |
| _pView = pView; |
| _pGridMap = 0; |
| _nGridCols = 0; |
| _nGridRows = 0; |
| } |
| |
| IcnGridMap_Impl::~IcnGridMap_Impl() |
| { |
| delete[] _pGridMap, _pGridMap=0; |
| } |
| |
| void IcnGridMap_Impl::Expand() |
| { |
| if( !_pGridMap ) |
| Create_Impl(); |
| else |
| { |
| sal_uInt16 nNewGridRows = _nGridRows; |
| sal_uInt16 nNewGridCols = _nGridCols; |
| if( _pView->nWinBits & WB_ALIGN_TOP ) |
| nNewGridRows += 50; |
| else |
| nNewGridCols += 50; |
| |
| sal_Bool* pNewGridMap = new sal_Bool[nNewGridRows*nNewGridCols]; |
| memset( pNewGridMap, 0, nNewGridRows * nNewGridCols * sizeof(sal_Bool) ); |
| memcpy( pNewGridMap, _pGridMap, _nGridRows * _nGridCols * sizeof(sal_Bool) ); |
| delete[] _pGridMap; |
| _pGridMap = pNewGridMap; |
| _nGridRows = nNewGridRows; |
| _nGridCols = nNewGridCols; |
| } |
| } |
| |
| void IcnGridMap_Impl::Create_Impl() |
| { |
| DBG_ASSERT(!_pGridMap,"Unnecessary call to IcnGridMap_Impl::Create_Impl()"); |
| if( _pGridMap ) |
| return; |
| GetMinMapSize( _nGridCols, _nGridRows ); |
| if( _pView->nWinBits & WB_ALIGN_TOP ) |
| _nGridRows += 50; // avoid resize of gridmap too often |
| else |
| _nGridCols += 50; |
| |
| _pGridMap = new sal_Bool[ _nGridRows * _nGridCols]; |
| memset( (void*)_pGridMap, 0, _nGridRows * _nGridCols ); |
| |
| const sal_uLong nCount = _pView->aEntries.Count(); |
| for( sal_uLong nCur=0; nCur < nCount; nCur++ ) |
| OccupyGrids( (SvxIconChoiceCtrlEntry*)_pView->aEntries.GetObject( nCur )); |
| } |
| |
| void IcnGridMap_Impl::GetMinMapSize( sal_uInt16& rDX, sal_uInt16& rDY ) const |
| { |
| long nX, nY; |
| if( _pView->nWinBits & WB_ALIGN_TOP ) |
| { |
| // The view grows in vertical direction. Its max. width is _pView->nMaxVirtWidth |
| nX = _pView->nMaxVirtWidth; |
| if( !nX ) |
| nX = _pView->pView->GetOutputSizePixel().Width(); |
| if( !(_pView->nFlags & F_ARRANGING) ) |
| nX -= _pView->nVerSBarWidth; |
| |
| nY = _pView->aVirtOutputSize.Height(); |
| } |
| else |
| { |
| // The view grows in horizontal direction. Its max. height is _pView->nMaxVirtHeight |
| nY = _pView->nMaxVirtHeight; |
| if( !nY ) |
| nY = _pView->pView->GetOutputSizePixel().Height(); |
| if( !(_pView->nFlags & F_ARRANGING) ) |
| nY -= _pView->nHorSBarHeight; |
| nX = _pView->aVirtOutputSize.Width(); |
| } |
| |
| if( !nX ) |
| nX = DEFAULT_MAX_VIRT_WIDTH; |
| if( !nY ) |
| nY = DEFAULT_MAX_VIRT_HEIGHT; |
| |
| long nDX = nX / _pView->nGridDX; |
| long nDY = nY / _pView->nGridDY; |
| |
| if( !nDX ) |
| nDX++; |
| if( !nDY ) |
| nDY++; |
| |
| rDX = (sal_uInt16)nDX; |
| rDY = (sal_uInt16)nDY; |
| } |
| |
| GridId IcnGridMap_Impl::GetGrid( sal_uInt16 nGridX, sal_uInt16 nGridY ) |
| { |
| Create(); |
| if( _pView->nWinBits & WB_ALIGN_TOP ) |
| return nGridX + ( nGridY * _nGridCols ); |
| else |
| return nGridY + ( nGridX * _nGridRows ); |
| } |
| |
| GridId IcnGridMap_Impl::GetGrid( const Point& rDocPos, sal_Bool* pbClipped ) |
| { |
| Create(); |
| |
| long nX = rDocPos.X(); |
| long nY = rDocPos.Y(); |
| nX -= LROFFS_WINBORDER; |
| nY -= TBOFFS_WINBORDER; |
| nX /= _pView->nGridDX; |
| nY /= _pView->nGridDY; |
| sal_Bool bClipped = sal_False; |
| if( nX >= _nGridCols ) |
| { |
| nX = _nGridCols - 1; |
| bClipped = sal_True; |
| } |
| if( nY >= _nGridRows ) |
| { |
| nY = _nGridRows - 1; |
| bClipped = sal_True; |
| } |
| GridId nId = GetGrid( (sal_uInt16)nX, (sal_uInt16)nY ); |
| if( pbClipped ) |
| *pbClipped = bClipped; |
| DBG_ASSERT(nId <(sal_uLong)(_nGridCols*_nGridRows),"GetGrid failed"); |
| return nId; |
| } |
| |
| Rectangle IcnGridMap_Impl::GetGridRect( GridId nId ) |
| { |
| Create(); |
| sal_uInt16 nGridX, nGridY; |
| GetGridCoord( nId, nGridX, nGridY ); |
| const long nLeft = nGridX * _pView->nGridDX+ LROFFS_WINBORDER; |
| const long nTop = nGridY * _pView->nGridDY + TBOFFS_WINBORDER; |
| return Rectangle( |
| nLeft, nTop, |
| nLeft + _pView->nGridDX, |
| nTop + _pView->nGridDY ); |
| } |
| |
| GridId IcnGridMap_Impl::GetUnoccupiedGrid( sal_Bool bOccupyFound ) |
| { |
| Create(); |
| sal_uLong nStart = 0; |
| sal_Bool bExpanded = sal_False; |
| |
| while( 1 ) |
| { |
| const sal_uLong nCount = (sal_uInt16)(_nGridCols * _nGridRows); |
| for( sal_uLong nCur = nStart; nCur < nCount; nCur++ ) |
| { |
| if( !_pGridMap[ nCur ] ) |
| { |
| if( bOccupyFound ) |
| _pGridMap[ nCur ] = sal_True; |
| return (GridId)nCur; |
| } |
| } |
| DBG_ASSERT(!bExpanded,"ExpandGrid failed"); |
| if( bExpanded ) |
| return 0; // prevent never ending loop |
| bExpanded = sal_True; |
| Expand(); |
| nStart = nCount; |
| } |
| } |
| |
| // ein Eintrag belegt nur das unter seinem Zentrum liegende GridRect |
| // diese Variante ist bedeutend schneller als die Belegung ueber das |
| // Bounding-Rect, kann aber zu kleinen Ueberlappungen fuehren |
| #define OCCUPY_CENTER |
| |
| void IcnGridMap_Impl::OccupyGrids( const SvxIconChoiceCtrlEntry* pEntry, sal_Bool bOccupy ) |
| { |
| if( !_pGridMap || !_pView->IsBoundingRectValid( pEntry->aRect )) |
| return; |
| #ifndef OCCUPY_CENTER |
| OccupyGrids( pEntry->aRect, bOccupy ); |
| #else |
| OccupyGrid( GetGrid( pEntry->aRect.Center()), bOccupy ); |
| #endif |
| |
| } |
| |
| void IcnGridMap_Impl::OccupyGrids( const Rectangle& rRect, sal_Bool bUsed ) |
| { |
| if( !_pGridMap ) |
| return; |
| |
| if( bUsed ) |
| { |
| if( _aLastOccupiedGrid == rRect ) |
| return; |
| _aLastOccupiedGrid = rRect; |
| } |
| else |
| _aLastOccupiedGrid.SetEmpty(); |
| |
| sal_Bool bTopLeftClipped, bBottomRightClipped; |
| GridId nIdTL = GetGrid( rRect.TopLeft(), &bTopLeftClipped ); |
| GridId nIdBR = GetGrid( rRect.BottomRight(), &bBottomRightClipped ); |
| |
| if( bTopLeftClipped && bBottomRightClipped ) |
| return; |
| |
| sal_uInt16 nX1,nX2,nY1,nY2; |
| GetGridCoord( nIdTL, nX1, nY1 ); |
| GetGridCoord( nIdBR, nX2, nY2 ); |
| sal_uInt16 nTemp; |
| if( nX1 > nX2 ) |
| { |
| nTemp = nX1; |
| nX1 = nX2; |
| nX2 = nTemp; |
| } |
| if( nY1 > nY2 ) |
| { |
| nTemp = nY1; |
| nY1 = nY2; |
| nY2 = nTemp; |
| } |
| for( ; nX1 <= nX2; nX1++ ) |
| for( ; nY1 <= nY2; nY1++ ) |
| OccupyGrid( GetGrid( nX1, nY1 ) ); |
| } |
| |
| void IcnGridMap_Impl::Clear() |
| { |
| if( _pGridMap ) |
| { |
| delete[] _pGridMap, _pGridMap=0; |
| _nGridRows = 0; |
| _nGridCols = 0; |
| _aLastOccupiedGrid.SetEmpty(); |
| } |
| } |
| |
| sal_uLong IcnGridMap_Impl::GetGridCount( const Size& rSizePixel, sal_uInt16 nDX, sal_uInt16 nDY) |
| { |
| long ndx = (rSizePixel.Width() - LROFFS_WINBORDER) / nDX; |
| if( ndx < 0 ) ndx *= -1; |
| long ndy = (rSizePixel.Height() - TBOFFS_WINBORDER) / nDY; |
| if( ndy < 0 ) ndy *= -1; |
| return (sal_uLong)(ndx * ndy); |
| } |
| |
| void IcnGridMap_Impl::OutputSizeChanged() |
| { |
| if( _pGridMap ) |
| { |
| sal_uInt16 nCols, nRows; |
| GetMinMapSize( nCols, nRows ); |
| if( _pView->nWinBits & WB_ALIGN_TOP ) |
| { |
| if( nCols != _nGridCols ) |
| Clear(); |
| else if( nRows >= _nGridRows ) |
| Expand(); |
| } |
| else |
| { |
| if( nRows != _nGridRows ) |
| Clear(); |
| else if( nCols >= _nGridCols ) |
| Expand(); |
| } |
| } |
| } |
| |
| // Independendly of the views alignment (TOP or LEFT) the gridmap |
| // should contain the data in a continues region, to make it possible |
| // to copy the whole block if the gridmap needs to be expanded. |
| void IcnGridMap_Impl::GetGridCoord( GridId nId, sal_uInt16& rGridX, sal_uInt16& rGridY ) |
| { |
| Create(); |
| if( _pView->nWinBits & WB_ALIGN_TOP ) |
| { |
| rGridX = (sal_uInt16)(nId % _nGridCols); |
| rGridY = (sal_uInt16)(nId / _nGridCols); |
| } |
| else |
| { |
| rGridX = (sal_uInt16)(nId / _nGridRows); |
| rGridY = (sal_uInt16)(nId % _nGridRows); |
| } |
| } |
| |
| |
| |