| /************************************************************** |
| * |
| * 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_sc.hxx" |
| |
| // System - Includes ----------------------------------------------------- |
| |
| |
| |
| // INCLUDE --------------------------------------------------------------- |
| #include <rangelst.hxx> |
| #include "scitems.hxx" |
| #include <editeng/eeitem.hxx> |
| |
| |
| #include <editeng/brshitem.hxx> |
| #include <editeng/editview.hxx> |
| #include <svx/fmshell.hxx> |
| #include <svx/svdoole2.hxx> |
| #include <sfx2/bindings.hxx> |
| #include <sfx2/viewfrm.hxx> |
| #include <vcl/cursor.hxx> |
| |
| #include "tabview.hxx" |
| #include "tabvwsh.hxx" |
| #include "docsh.hxx" |
| #include "gridwin.hxx" |
| #include "olinewin.hxx" |
| #include "colrowba.hxx" |
| #include "tabcont.hxx" |
| #include "scmod.hxx" |
| #include "uiitems.hxx" |
| #include "sc.hrc" |
| #include "viewutil.hxx" |
| #include "editutil.hxx" |
| #include "inputhdl.hxx" |
| #include "inputwin.hxx" |
| #include "validat.hxx" |
| #include "hintwin.hxx" |
| #include "inputopt.hxx" |
| #include "rfindlst.hxx" |
| #include "hiranges.hxx" |
| #include "viewuno.hxx" |
| #include "chartarr.hxx" |
| #include "anyrefdg.hxx" |
| #include "dpobject.hxx" |
| #include "patattr.hxx" |
| #include "dociter.hxx" |
| #include "seltrans.hxx" |
| #include "fillinfo.hxx" |
| #include "AccessibilityHints.hxx" |
| #include "rangeutl.hxx" |
| #include "client.hxx" |
| #include "tabprotection.hxx" |
| |
| #include <com/sun/star/chart2/data/HighlightedRange.hpp> |
| |
| namespace |
| { |
| |
| ScRange lcl_getSubRangeByIndex( const ScRange& rRange, sal_Int32 nIndex ) |
| { |
| ScAddress aResult( rRange.aStart ); |
| |
| SCCOL nWidth = rRange.aEnd.Col() - rRange.aStart.Col() + 1; |
| SCROW nHeight = rRange.aEnd.Row() - rRange.aStart.Row() + 1; |
| SCTAB nDepth = rRange.aEnd.Tab() - rRange.aStart.Tab() + 1; |
| if( (nWidth > 0) && (nHeight > 0) && (nDepth > 0) ) |
| { |
| // row by row from first to last sheet |
| sal_Int32 nArea = nWidth * nHeight; |
| aResult.IncCol( static_cast< SCsCOL >( nIndex % nWidth ) ); |
| aResult.IncRow( static_cast< SCsROW >( (nIndex % nArea) / nWidth ) ); |
| aResult.IncTab( static_cast< SCsTAB >( nIndex / nArea ) ); |
| if( !rRange.In( aResult ) ) |
| aResult = rRange.aStart; |
| } |
| |
| return ScRange( aResult ); |
| } |
| |
| } // anonymous namespace |
| |
| using namespace com::sun::star; |
| |
| // ----------------------------------------------------------------------- |
| |
| // |
| // --- Public-Funktionen |
| // |
| |
| void ScTabView::ClickCursor( SCCOL nPosX, SCROW nPosY, sal_Bool bControl ) |
| { |
| ScDocument* pDoc = aViewData.GetDocument(); |
| SCTAB nTab = aViewData.GetTabNo(); |
| while (pDoc->IsHorOverlapped( nPosX, nPosY, nTab )) //! ViewData !!! |
| --nPosX; |
| while (pDoc->IsVerOverlapped( nPosX, nPosY, nTab )) |
| --nPosY; |
| |
| sal_Bool bRefMode = SC_MOD()->IsFormulaMode(); |
| |
| if ( bRefMode ) |
| { |
| DoneRefMode( sal_False ); |
| |
| if (bControl) |
| SC_MOD()->AddRefEntry(); |
| |
| InitRefMode( nPosX, nPosY, nTab, SC_REFTYPE_REF ); |
| } |
| else |
| { |
| DoneBlockMode( bControl ); |
| aViewData.ResetOldCursor(); |
| SetCursor( (SCCOL) nPosX, (SCROW) nPosY ); |
| } |
| } |
| |
| void ScTabView::UpdateAutoFillMark() |
| { |
| // single selection or cursor |
| ScRange aMarkRange; |
| sal_Bool bMarked = (aViewData.GetSimpleArea( aMarkRange ) == SC_MARK_SIMPLE); |
| |
| sal_uInt16 i; |
| for (i=0; i<4; i++) |
| if (pGridWin[i] && pGridWin[i]->IsVisible()) |
| pGridWin[i]->UpdateAutoFillMark( bMarked, aMarkRange ); |
| |
| for (i=0; i<2; i++) |
| { |
| if (pColBar[i] && pColBar[i]->IsVisible()) |
| pColBar[i]->SetMark( bMarked, aMarkRange.aStart.Col(), aMarkRange.aEnd.Col() ); |
| if (pRowBar[i] && pRowBar[i]->IsVisible()) |
| pRowBar[i]->SetMark( bMarked, aMarkRange.aStart.Row(), aMarkRange.aEnd.Row() ); |
| } |
| |
| // selection transfer object is checked together with AutoFill marks, |
| // because it has the same requirement of a single continuous block. |
| CheckSelectionTransfer(); // update selection transfer object |
| } |
| |
| void ScTabView::FakeButtonUp( ScSplitPos eWhich ) |
| { |
| if (pGridWin[eWhich]) |
| pGridWin[eWhich]->FakeButtonUp(); |
| } |
| |
| void ScTabView::HideAllCursors() |
| { |
| for (sal_uInt16 i=0; i<4; i++) |
| if (pGridWin[i]) |
| if (pGridWin[i]->IsVisible()) |
| { |
| Cursor* pCur = pGridWin[i]->GetCursor(); |
| if (pCur) |
| if (pCur->IsVisible()) |
| pCur->Hide(); |
| pGridWin[i]->HideCursor(); |
| } |
| } |
| |
| void ScTabView::ShowAllCursors() |
| { |
| for (sal_uInt16 i=0; i<4; i++) |
| if (pGridWin[i]) |
| if (pGridWin[i]->IsVisible()) |
| { |
| pGridWin[i]->ShowCursor(); |
| |
| // #114409# |
| pGridWin[i]->CursorChanged(); |
| } |
| } |
| |
| void ScTabView::HideCursor() |
| { |
| pGridWin[aViewData.GetActivePart()]->HideCursor(); |
| } |
| |
| void ScTabView::ShowCursor() |
| { |
| pGridWin[aViewData.GetActivePart()]->ShowCursor(); |
| |
| // #114409# |
| pGridWin[aViewData.GetActivePart()]->CursorChanged(); |
| } |
| |
| void ScTabView::InvalidateAttribs() |
| { |
| SfxBindings& rBindings = aViewData.GetBindings(); |
| |
| rBindings.Invalidate( SID_STYLE_APPLY ); |
| rBindings.Invalidate( SID_STYLE_FAMILY2 ); |
| // StarCalc kennt nur Absatz- bzw. Zellformat-Vorlagen |
| |
| rBindings.Invalidate( SID_ATTR_CHAR_FONT ); |
| rBindings.Invalidate( SID_ATTR_CHAR_FONTHEIGHT ); |
| rBindings.Invalidate( SID_ATTR_CHAR_COLOR ); |
| |
| rBindings.Invalidate( SID_ATTR_CHAR_WEIGHT ); |
| rBindings.Invalidate( SID_ATTR_CHAR_POSTURE ); |
| rBindings.Invalidate( SID_ATTR_CHAR_UNDERLINE ); |
| rBindings.Invalidate( SID_ULINE_VAL_NONE ); |
| rBindings.Invalidate( SID_ULINE_VAL_SINGLE ); |
| rBindings.Invalidate( SID_ULINE_VAL_DOUBLE ); |
| rBindings.Invalidate( SID_ULINE_VAL_DOTTED ); |
| |
| rBindings.Invalidate( SID_ATTR_CHAR_OVERLINE ); |
| |
| rBindings.Invalidate( SID_ATTR_CHAR_KERNING ); |
| rBindings.Invalidate( SID_SET_SUPER_SCRIPT ); |
| rBindings.Invalidate( SID_SET_SUB_SCRIPT ); |
| rBindings.Invalidate( SID_ATTR_CHAR_STRIKEOUT ); |
| rBindings.Invalidate( SID_ATTR_CHAR_SHADOWED ); |
| |
| rBindings.Invalidate( SID_ATTR_PARA_ADJUST_LEFT ); |
| rBindings.Invalidate( SID_ATTR_PARA_ADJUST_RIGHT ); |
| rBindings.Invalidate( SID_ATTR_PARA_ADJUST_BLOCK ); |
| rBindings.Invalidate( SID_ATTR_PARA_ADJUST_CENTER); |
| rBindings.Invalidate( SID_NUMBER_TYPE_FORMAT); |
| |
| rBindings.Invalidate( SID_ALIGNLEFT ); |
| rBindings.Invalidate( SID_ALIGNRIGHT ); |
| rBindings.Invalidate( SID_ALIGNBLOCK ); |
| rBindings.Invalidate( SID_ALIGNCENTERHOR ); |
| |
| rBindings.Invalidate( SID_ALIGNTOP ); |
| rBindings.Invalidate( SID_ALIGNBOTTOM ); |
| rBindings.Invalidate( SID_ALIGNCENTERVER ); |
| |
| // stuff for sidebar panels |
| { |
| rBindings.Invalidate( SID_H_ALIGNCELL ); |
| rBindings.Invalidate( SID_V_ALIGNCELL ); |
| rBindings.Invalidate( SID_ATTR_ALIGN_INDENT ); |
| rBindings.Invalidate( SID_FRAME_LINECOLOR ); |
| rBindings.Invalidate( SID_FRAME_LINESTYLE ); |
| rBindings.Invalidate( SID_ATTR_BORDER_OUTER ); |
| rBindings.Invalidate( SID_ATTR_BORDER_INNER ); |
| rBindings.Invalidate( SID_SCGRIDSHOW ); |
| rBindings.Invalidate( SID_ATTR_BORDER_DIAG_TLBR ); |
| rBindings.Invalidate( SID_ATTR_BORDER_DIAG_BLTR ); |
| rBindings.Invalidate( SID_NUMBER_TYPE_FORMAT ); |
| } |
| |
| rBindings.Invalidate( SID_BACKGROUND_COLOR ); |
| |
| rBindings.Invalidate( SID_ATTR_ALIGN_LINEBREAK ); |
| rBindings.Invalidate( SID_NUMBER_FORMAT ); |
| |
| rBindings.Invalidate( SID_TEXTDIRECTION_LEFT_TO_RIGHT ); |
| rBindings.Invalidate( SID_TEXTDIRECTION_TOP_TO_BOTTOM ); |
| rBindings.Invalidate( SID_ATTR_PARA_LEFT_TO_RIGHT ); |
| rBindings.Invalidate( SID_ATTR_PARA_RIGHT_TO_LEFT ); |
| |
| // pseudo slots for Format menu |
| rBindings.Invalidate( SID_ALIGN_ANY_HDEFAULT ); |
| rBindings.Invalidate( SID_ALIGN_ANY_LEFT ); |
| rBindings.Invalidate( SID_ALIGN_ANY_HCENTER ); |
| rBindings.Invalidate( SID_ALIGN_ANY_RIGHT ); |
| rBindings.Invalidate( SID_ALIGN_ANY_JUSTIFIED ); |
| rBindings.Invalidate( SID_ALIGN_ANY_VDEFAULT ); |
| rBindings.Invalidate( SID_ALIGN_ANY_TOP ); |
| rBindings.Invalidate( SID_ALIGN_ANY_VCENTER ); |
| rBindings.Invalidate( SID_ALIGN_ANY_BOTTOM ); |
| |
| // rBindings.Invalidate( SID_RANGE_VALUE ); |
| // rBindings.Invalidate( SID_RANGE_FORMULA ); |
| } |
| |
| // SetCursor - Cursor setzen, zeichnen, InputWin updaten |
| // oder Referenz verschicken |
| // ohne Optimierung wegen BugId 29307 |
| |
| #ifdef _MSC_VER |
| #pragma optimize ( "", off ) |
| #endif |
| |
| void ScTabView::SetCursor( SCCOL nPosX, SCROW nPosY, sal_Bool bNew ) |
| { |
| SCCOL nOldX = aViewData.GetCurX(); |
| SCROW nOldY = aViewData.GetCurY(); |
| |
| // DeactivateIP nur noch bei MarkListHasChanged |
| |
| if ( nPosX != nOldX || nPosY != nOldY || bNew ) |
| { |
| ScTabViewShell* pViewShell = aViewData.GetViewShell(); |
| bool bRefMode = ( pViewShell ? pViewShell->IsRefInputMode() : false ); |
| if ( aViewData.HasEditView( aViewData.GetActivePart() ) && !bRefMode ) // 23259 oder so |
| { |
| UpdateInputLine(); |
| } |
| |
| HideAllCursors(); |
| |
| aViewData.SetCurX( nPosX ); |
| aViewData.SetCurY( nPosY ); |
| |
| ShowAllCursors(); |
| |
| CursorPosChanged(); |
| } |
| } |
| |
| #ifdef _MSC_VER |
| #pragma optimize ( "", on ) |
| #endif |
| |
| void ScTabView::CheckSelectionTransfer() |
| { |
| if ( aViewData.IsActive() ) // only for active view |
| { |
| ScModule* pScMod = SC_MOD(); |
| ScSelectionTransferObj* pOld = pScMod->GetSelectionTransfer(); |
| if ( pOld && pOld->GetView() == this && pOld->StillValid() ) |
| { |
| // selection not changed - nothing to do |
| } |
| else |
| { |
| ScSelectionTransferObj* pNew = ScSelectionTransferObj::CreateFromView( this ); |
| if ( pNew ) |
| { |
| // create new selection |
| |
| if (pOld) |
| pOld->ForgetView(); |
| |
| uno::Reference<datatransfer::XTransferable> xRef( pNew ); |
| pScMod->SetSelectionTransfer( pNew ); |
| pNew->CopyToSelection( GetActiveWin() ); // may delete pOld |
| } |
| else if ( pOld && pOld->GetView() == this ) |
| { |
| // remove own selection |
| |
| pOld->ForgetView(); |
| pScMod->SetSelectionTransfer( NULL ); |
| TransferableHelper::ClearSelection( GetActiveWin() ); // may delete pOld |
| } |
| // else: selection from outside: leave unchanged |
| } |
| } |
| } |
| |
| // Eingabezeile / Menues updaten |
| // CursorPosChanged ruft SelectionChanged |
| // SelectionChanged ruft CellContentChanged |
| |
| void ScTabView::CellContentChanged() |
| { |
| SfxBindings& rBindings = aViewData.GetBindings(); |
| |
| rBindings.Invalidate( SID_ATTR_SIZE ); // -> Fehlermeldungen anzeigen |
| rBindings.Invalidate( SID_THESAURUS ); |
| rBindings.Invalidate( SID_HYPERLINK_GETLINK ); |
| |
| InvalidateAttribs(); // Attribut-Updates |
| TestHintWindow(); // Eingabemeldung (Gueltigkeit) |
| |
| aViewData.GetViewShell()->UpdateInputHandler(); |
| } |
| |
| void ScTabView::SelectionChanged() |
| { |
| SfxViewFrame* pViewFrame = aViewData.GetViewShell()->GetViewFrame(); |
| if (pViewFrame) |
| { |
| uno::Reference<frame::XController> xController = pViewFrame->GetFrame().GetController(); |
| if (xController.is()) |
| { |
| ScTabViewObj* pImp = ScTabViewObj::getImplementation( xController ); |
| if (pImp) |
| pImp->SelectionChanged(); |
| } |
| } |
| |
| UpdateAutoFillMark(); // also calls CheckSelectionTransfer |
| |
| SfxBindings& rBindings = aViewData.GetBindings(); |
| |
| rBindings.Invalidate( SID_CURRENTCELL ); // -> Navigator |
| rBindings.Invalidate( SID_AUTO_FILTER ); // -> Menue |
| rBindings.Invalidate( FID_NOTE_VISIBLE ); |
| rBindings.Invalidate( SID_DELETE_NOTE ); |
| |
| // Funktionen, die evtl disabled werden muessen |
| |
| rBindings.Invalidate( FID_INS_ROWBRK ); |
| rBindings.Invalidate( FID_INS_COLBRK ); |
| rBindings.Invalidate( FID_DEL_ROWBRK ); |
| rBindings.Invalidate( FID_DEL_COLBRK ); |
| rBindings.Invalidate( FID_MERGE_ON ); |
| rBindings.Invalidate( FID_MERGE_OFF ); |
| rBindings.Invalidate( FID_MERGE_TOGGLE ); |
| rBindings.Invalidate( SID_AUTOFILTER_HIDE ); |
| rBindings.Invalidate( SID_UNFILTER ); |
| // rBindings.Invalidate( SID_IMPORT_DATA ); // jetzt wieder immer moeglich |
| rBindings.Invalidate( SID_REIMPORT_DATA ); |
| rBindings.Invalidate( SID_REFRESH_DBAREA ); |
| rBindings.Invalidate( SID_OUTLINE_SHOW ); |
| rBindings.Invalidate( SID_OUTLINE_HIDE ); |
| rBindings.Invalidate( SID_OUTLINE_REMOVE ); |
| rBindings.Invalidate( FID_FILL_TO_BOTTOM ); |
| rBindings.Invalidate( FID_FILL_TO_RIGHT ); |
| rBindings.Invalidate( FID_FILL_TO_TOP ); |
| rBindings.Invalidate( FID_FILL_TO_LEFT ); |
| rBindings.Invalidate( FID_FILL_SERIES ); |
| rBindings.Invalidate( SID_SCENARIOS ); |
| rBindings.Invalidate( SID_AUTOFORMAT ); |
| rBindings.Invalidate( SID_OPENDLG_TABOP ); |
| rBindings.Invalidate( SID_DATA_SELECT ); |
| |
| rBindings.Invalidate( SID_CUT ); |
| rBindings.Invalidate( SID_COPY ); |
| rBindings.Invalidate( SID_PASTE ); |
| rBindings.Invalidate( SID_PASTE_SPECIAL ); |
| |
| rBindings.Invalidate( FID_INS_ROW ); |
| rBindings.Invalidate( FID_INS_COLUMN ); |
| rBindings.Invalidate( FID_INS_CELL ); |
| rBindings.Invalidate( FID_INS_CELLSDOWN ); |
| rBindings.Invalidate( FID_INS_CELLSRIGHT ); |
| |
| rBindings.Invalidate( FID_CHG_COMMENT ); |
| |
| // nur wegen Zellschutz: |
| |
| rBindings.Invalidate( SID_CELL_FORMAT_RESET ); |
| rBindings.Invalidate( SID_DELETE ); |
| rBindings.Invalidate( SID_DELETE_CONTENTS ); |
| rBindings.Invalidate( FID_DELETE_CELL ); |
| rBindings.Invalidate( FID_CELL_FORMAT ); |
| rBindings.Invalidate( SID_ENABLE_HYPHENATION ); |
| rBindings.Invalidate( SID_INSERT_POSTIT ); |
| rBindings.Invalidate( SID_CHARMAP ); |
| rBindings.Invalidate( SID_OPENDLG_FUNCTION ); |
| // rBindings.Invalidate( FID_CONDITIONAL_FORMAT ); |
| rBindings.Invalidate( SID_OPENDLG_CONDFRMT ); |
| rBindings.Invalidate( FID_VALIDATION ); |
| rBindings.Invalidate( SID_EXTERNAL_SOURCE ); |
| rBindings.Invalidate( SID_TEXT_TO_COLUMNS ); |
| rBindings.Invalidate( SID_SORT_ASCENDING ); |
| rBindings.Invalidate( SID_SORT_DESCENDING ); |
| |
| if (aViewData.GetViewShell()->HasAccessibilityObjects()) |
| aViewData.GetViewShell()->BroadcastAccessibility(SfxSimpleHint(SC_HINT_ACC_CURSORCHANGED)); |
| |
| CellContentChanged(); |
| } |
| |
| void ScTabView::CursorPosChanged() |
| { |
| sal_Bool bRefMode = SC_MOD()->IsFormulaMode(); |
| if ( !bRefMode ) // Abfrage, damit RefMode bei Tabellenwechsel funktioniert |
| aViewData.GetDocShell()->Broadcast( SfxSimpleHint( FID_KILLEDITVIEW ) ); |
| |
| // Broadcast, damit andere Views des Dokuments auch umschalten |
| |
| ScDocument* pDoc = aViewData.GetDocument(); |
| bool bDP = NULL != pDoc->GetDPAtCursor( |
| aViewData.GetCurX(), aViewData.GetCurY(), aViewData.GetTabNo() ); |
| aViewData.GetViewShell()->SetPivotShell(bDP); |
| |
| // UpdateInputHandler jetzt in CellContentChanged |
| |
| SelectionChanged(); |
| |
| aViewData.SetTabStartCol( SC_TABSTART_NONE ); |
| } |
| |
| void ScTabView::TestHintWindow() |
| { |
| // show input help window and list drop-down button for validity |
| |
| sal_Bool bListValButton = sal_False; |
| ScAddress aListValPos; |
| |
| ScDocument* pDoc = aViewData.GetDocument(); |
| const SfxUInt32Item* pItem = (const SfxUInt32Item*) |
| pDoc->GetAttr( aViewData.GetCurX(), |
| aViewData.GetCurY(), |
| aViewData.GetTabNo(), |
| ATTR_VALIDDATA ); |
| if ( pItem->GetValue() ) |
| { |
| const ScValidationData* pData = pDoc->GetValidationEntry( pItem->GetValue() ); |
| DBG_ASSERT(pData,"ValidationData nicht gefunden"); |
| String aTitle, aMessage; |
| if ( pData && pData->GetInput( aTitle, aMessage ) && aMessage.Len() > 0 ) |
| { |
| //! Abfrage, ob an gleicher Stelle !!!! |
| |
| DELETEZ(pInputHintWindow); |
| |
| ScSplitPos eWhich = aViewData.GetActivePart(); |
| Window* pWin = pGridWin[eWhich]; |
| SCCOL nCol = aViewData.GetCurX(); |
| SCROW nRow = aViewData.GetCurY(); |
| Point aPos = aViewData.GetScrPos( nCol, nRow, eWhich ); |
| Size aWinSize = pWin->GetOutputSizePixel(); |
| // Cursor sichtbar? |
| if ( nCol >= aViewData.GetPosX(WhichH(eWhich)) && |
| nRow >= aViewData.GetPosY(WhichV(eWhich)) && |
| aPos.X() < aWinSize.Width() && aPos.Y() < aWinSize.Height() ) |
| { |
| aPos += pWin->GetPosPixel(); // Position auf Frame |
| long nSizeXPix; |
| long nSizeYPix; |
| aViewData.GetMergeSizePixel( nCol, nRow, nSizeXPix, nSizeYPix ); |
| |
| // HintWindow anlegen, bestimmt seine Groesse selbst |
| pInputHintWindow = new ScHintWindow( pFrameWin, aTitle, aMessage ); |
| Size aHintSize = pInputHintWindow->GetSizePixel(); |
| Size aFrameWinSize = pFrameWin->GetOutputSizePixel(); |
| |
| // passende Position finden |
| // erster Versuch: unter dem Cursor |
| Point aHintPos( aPos.X() + nSizeXPix / 2, aPos.Y() + nSizeYPix + 3 ); |
| if ( aHintPos.Y() + aHintSize.Height() > aFrameWinSize.Height() ) |
| { |
| // zweiter Versuch: rechts vom Cursor |
| aHintPos = Point( aPos.X() + nSizeXPix + 3, aPos.Y() + nSizeYPix / 2 ); |
| if ( aHintPos.X() + aHintSize.Width() > aFrameWinSize.Width() ) |
| { |
| // dritter Versuch: ueber dem Cursor |
| aHintPos = Point( aPos.X() + nSizeXPix / 2, |
| aPos.Y() - aHintSize.Height() - 3 ); |
| if ( aHintPos.Y() < 0 ) |
| { |
| // oben und unten kein Platz - dann Default und abschneiden |
| aHintPos = Point( aPos.X() + nSizeXPix / 2, aPos.Y() + nSizeYPix + 3 ); |
| aHintSize.Height() = aFrameWinSize.Height() - aHintPos.Y(); |
| pInputHintWindow->SetSizePixel( aHintSize ); |
| } |
| } |
| } |
| |
| // X anpassen |
| if ( aHintPos.X() + aHintSize.Width() > aFrameWinSize.Width() ) |
| aHintPos.X() = aFrameWinSize.Width() - aHintSize.Width(); |
| // Y anpassen |
| if ( aHintPos.Y() + aHintSize.Height() > aFrameWinSize.Height() ) |
| aHintPos.Y() = aFrameWinSize.Height() - aHintSize.Height(); |
| |
| pInputHintWindow->SetPosPixel( aHintPos ); |
| pInputHintWindow->ToTop(); |
| pInputHintWindow->Show(); |
| } |
| } |
| else |
| DELETEZ(pInputHintWindow); |
| |
| // list drop-down button |
| if ( pData && pData->HasSelectionList() ) |
| { |
| aListValPos.Set( aViewData.GetCurX(), aViewData.GetCurY(), aViewData.GetTabNo() ); |
| bListValButton = sal_True; |
| } |
| } |
| else |
| DELETEZ(pInputHintWindow); |
| |
| for ( sal_uInt16 i=0; i<4; i++ ) |
| if ( pGridWin[i] && pGridWin[i]->IsVisible() ) |
| pGridWin[i]->UpdateListValPos( bListValButton, aListValPos ); |
| } |
| |
| void ScTabView::RemoveHintWindow() |
| { |
| DELETEZ(pInputHintWindow); |
| } |
| |
| |
| // find window that should not be over the cursor |
| Window* lcl_GetCareWin(SfxViewFrame* pViewFrm) |
| { |
| //! auch Spelling ??? (dann beim Aufruf Membervariable setzen) |
| |
| // Suchen & Ersetzen |
| if ( pViewFrm->HasChildWindow(SID_SEARCH_DLG) ) |
| { |
| SfxChildWindow* pChild = pViewFrm->GetChildWindow(SID_SEARCH_DLG); |
| if (pChild) |
| { |
| Window* pWin = pChild->GetWindow(); |
| if (pWin && pWin->IsVisible()) |
| return pWin; |
| } |
| } |
| |
| // Aenderungen uebernehmen |
| if ( pViewFrm->HasChildWindow(FID_CHG_ACCEPT) ) |
| { |
| SfxChildWindow* pChild = pViewFrm->GetChildWindow(FID_CHG_ACCEPT); |
| if (pChild) |
| { |
| Window* pWin = pChild->GetWindow(); |
| if (pWin && pWin->IsVisible()) |
| return pWin; |
| } |
| } |
| |
| return NULL; |
| } |
| |
| // |
| // Bildschirm an Cursorposition anpassen |
| // |
| |
| void ScTabView::AlignToCursor( SCsCOL nCurX, SCsROW nCurY, ScFollowMode eMode, |
| const ScSplitPos* pWhich ) |
| { |
| // |
| // aktiven Teil umschalten jetzt hier |
| // |
| |
| ScSplitPos eActive = aViewData.GetActivePart(); |
| ScHSplitPos eActiveX = WhichH(eActive); |
| ScVSplitPos eActiveY = WhichV(eActive); |
| sal_Bool bHFix = (aViewData.GetHSplitMode() == SC_SPLIT_FIX); |
| sal_Bool bVFix = (aViewData.GetVSplitMode() == SC_SPLIT_FIX); |
| if (bHFix) |
| if (eActiveX == SC_SPLIT_LEFT && nCurX >= (SCsCOL)aViewData.GetFixPosX()) |
| { |
| ActivatePart( (eActiveY==SC_SPLIT_TOP) ? SC_SPLIT_TOPRIGHT : SC_SPLIT_BOTTOMRIGHT ); |
| eActiveX = SC_SPLIT_RIGHT; |
| } |
| if (bVFix) |
| if (eActiveY == SC_SPLIT_TOP && nCurY >= (SCsROW)aViewData.GetFixPosY()) |
| { |
| ActivatePart( (eActiveX==SC_SPLIT_LEFT) ? SC_SPLIT_BOTTOMLEFT : SC_SPLIT_BOTTOMRIGHT ); |
| eActiveY = SC_SPLIT_BOTTOM; |
| } |
| |
| // |
| // eigentliches Align |
| // |
| |
| if ( eMode != SC_FOLLOW_NONE ) |
| { |
| ScSplitPos eAlign; |
| if (pWhich) |
| eAlign = *pWhich; |
| else |
| eAlign = aViewData.GetActivePart(); |
| ScHSplitPos eAlignX = WhichH(eAlign); |
| ScVSplitPos eAlignY = WhichV(eAlign); |
| |
| SCsCOL nDeltaX = (SCsCOL) aViewData.GetPosX(eAlignX); |
| SCsROW nDeltaY = (SCsROW) aViewData.GetPosY(eAlignY); |
| SCsCOL nSizeX = (SCsCOL) aViewData.VisibleCellsX(eAlignX); |
| SCsROW nSizeY = (SCsROW) aViewData.VisibleCellsY(eAlignY); |
| |
| long nCellSizeX; |
| long nCellSizeY; |
| if ( nCurX >= 0 && nCurY >= 0 ) |
| aViewData.GetMergeSizePixel( (SCCOL)nCurX, (SCROW)nCurY, nCellSizeX, nCellSizeY ); |
| else |
| nCellSizeX = nCellSizeY = 0; |
| Size aScrSize = aViewData.GetScrSize(); |
| long nSpaceX = ( aScrSize.Width() - nCellSizeX ) / 2; |
| long nSpaceY = ( aScrSize.Height() - nCellSizeY ) / 2; |
| // nSpaceY: desired start position of cell for FOLLOW_JUMP, modified if dialog interferes |
| |
| sal_Bool bForceNew = sal_False; // force new calculation of JUMP position (vertical only) |
| |
| // VisibleCellsY == CellsAtY( GetPosY( eWhichY ), 1, eWhichY ) |
| |
| //------------------------------------------------------------------------------- |
| // falls z.B. Suchen-Dialog offen ist, Cursor nicht hinter den Dialog stellen |
| // wenn moeglich, die Zeile mit dem Cursor oberhalb oder unterhalb des Dialogs |
| |
| //! nicht, wenn schon komplett sichtbar |
| |
| if ( eMode == SC_FOLLOW_JUMP ) |
| { |
| Window* pCare = lcl_GetCareWin( aViewData.GetViewShell()->GetViewFrame() ); |
| if (pCare) |
| { |
| sal_Bool bLimit = sal_False; |
| Rectangle aDlgPixel; |
| Size aWinSize; |
| Window* pWin = GetActiveWin(); |
| if (pWin) |
| { |
| aDlgPixel = pCare->GetWindowExtentsRelative( pWin ); |
| aWinSize = pWin->GetOutputSizePixel(); |
| // ueberdeckt der Dialog das GridWin? |
| if ( aDlgPixel.Right() >= 0 && aDlgPixel.Left() < aWinSize.Width() ) |
| { |
| if ( nCurX < nDeltaX || nCurX >= nDeltaX+nSizeX || |
| nCurY < nDeltaY || nCurY >= nDeltaY+nSizeY ) |
| bLimit = sal_True; // es wird sowieso gescrollt |
| else |
| { |
| // Cursor ist auf dem Bildschirm |
| Point aStart = aViewData.GetScrPos( nCurX, nCurY, eAlign ); |
| long nCSX, nCSY; |
| aViewData.GetMergeSizePixel( nCurX, nCurY, nCSX, nCSY ); |
| Rectangle aCursor( aStart, Size( nCSX, nCSY ) ); |
| if ( aCursor.IsOver( aDlgPixel ) ) |
| bLimit = sal_True; // Zelle vom Dialog ueberdeckt |
| } |
| } |
| } |
| |
| if (bLimit) |
| { |
| sal_Bool bBottom = sal_False; |
| long nTopSpace = aDlgPixel.Top(); |
| long nBotSpace = aWinSize.Height() - aDlgPixel.Bottom(); |
| if ( nBotSpace > 0 && nBotSpace > nTopSpace ) |
| { |
| long nDlgBot = aDlgPixel.Bottom(); |
| SCsCOL nWPosX; |
| SCsROW nWPosY; |
| aViewData.GetPosFromPixel( 0,nDlgBot, eAlign, nWPosX, nWPosY ); |
| ++nWPosY; // unter der letzten betroffenen Zelle |
| |
| SCsROW nDiff = nWPosY - nDeltaY; |
| if ( nCurY >= nDiff ) // Pos. kann nicht negativ werden |
| { |
| nSpaceY = nDlgBot + ( nBotSpace - nCellSizeY ) / 2; |
| bBottom = sal_True; |
| bForceNew = sal_True; |
| } |
| } |
| if ( !bBottom && nTopSpace > 0 ) |
| { |
| nSpaceY = ( nTopSpace - nCellSizeY ) / 2; |
| bForceNew = sal_True; |
| } |
| } |
| } |
| } |
| //------------------------------------------------------------------------------- |
| |
| SCsCOL nNewDeltaX = nDeltaX; |
| SCsROW nNewDeltaY = nDeltaY; |
| sal_Bool bDoLine = sal_False; |
| |
| switch (eMode) |
| { |
| case SC_FOLLOW_JUMP: |
| if ( nCurX < nDeltaX || nCurX >= nDeltaX+nSizeX ) |
| { |
| nNewDeltaX = nCurX - static_cast<SCsCOL>(aViewData.CellsAtX( nCurX, -1, eAlignX, static_cast<sal_uInt16>(nSpaceX) )); |
| if (nNewDeltaX < 0) nNewDeltaX = 0; |
| nSizeX = (SCsCOL) aViewData.CellsAtX( nNewDeltaX, 1, eAlignX ); |
| } |
| if ( nCurY < nDeltaY || nCurY >= nDeltaY+nSizeY || bForceNew ) |
| { |
| nNewDeltaY = nCurY - static_cast<SCsROW>(aViewData.CellsAtY( nCurY, -1, eAlignY, static_cast<sal_uInt16>(nSpaceY) )); |
| if (nNewDeltaY < 0) nNewDeltaY = 0; |
| nSizeY = (SCsROW) aViewData.CellsAtY( nNewDeltaY, 1, eAlignY ); |
| } |
| bDoLine = sal_True; |
| break; |
| |
| case SC_FOLLOW_LINE: |
| bDoLine = sal_True; |
| break; |
| |
| case SC_FOLLOW_FIX: |
| if ( nCurX < nDeltaX || nCurX >= nDeltaX+nSizeX ) |
| { |
| nNewDeltaX = nDeltaX + nCurX - aViewData.GetCurX(); |
| if (nNewDeltaX < 0) nNewDeltaX = 0; |
| nSizeX = (SCsCOL) aViewData.CellsAtX( nNewDeltaX, 1, eAlignX ); |
| } |
| if ( nCurY < nDeltaY || nCurY >= nDeltaY+nSizeY ) |
| { |
| nNewDeltaY = nDeltaY + nCurY - aViewData.GetCurY(); |
| if (nNewDeltaY < 0) nNewDeltaY = 0; |
| nSizeY = (SCsROW) aViewData.CellsAtY( nNewDeltaY, 1, eAlignY ); |
| } |
| |
| // like old version of SC_FOLLOW_JUMP: |
| |
| if ( nCurX < nNewDeltaX || nCurX >= nNewDeltaX+nSizeX ) |
| { |
| nNewDeltaX = nCurX - (nSizeX / 2); |
| if (nNewDeltaX < 0) nNewDeltaX = 0; |
| nSizeX = (SCsCOL) aViewData.CellsAtX( nNewDeltaX, 1, eAlignX ); |
| } |
| if ( nCurY < nNewDeltaY || nCurY >= nNewDeltaY+nSizeY ) |
| { |
| nNewDeltaY = nCurY - (nSizeY / 2); |
| if (nNewDeltaY < 0) nNewDeltaY = 0; |
| nSizeY = (SCsROW) aViewData.CellsAtY( nNewDeltaY, 1, eAlignY ); |
| } |
| |
| bDoLine = sal_True; |
| break; |
| |
| case SC_FOLLOW_NONE: |
| break; |
| default: |
| DBG_ERROR("Falscher Cursormodus"); |
| break; |
| } |
| |
| if (bDoLine) |
| { |
| while ( nCurX >= nNewDeltaX+nSizeX ) |
| { |
| nNewDeltaX = nCurX-nSizeX+1; |
| ScDocument* pDoc = aViewData.GetDocument(); |
| SCTAB nTab = aViewData.GetTabNo(); |
| while ( nNewDeltaX < MAXCOL && !pDoc->GetColWidth( nNewDeltaX, nTab ) ) |
| ++nNewDeltaX; |
| nSizeX = (SCsCOL) aViewData.CellsAtX( nNewDeltaX, 1, eAlignX ); |
| } |
| while ( nCurY >= nNewDeltaY+nSizeY ) |
| { |
| nNewDeltaY = nCurY-nSizeY+1; |
| ScDocument* pDoc = aViewData.GetDocument(); |
| SCTAB nTab = aViewData.GetTabNo(); |
| while ( nNewDeltaY < MAXROW && !pDoc->GetRowHeight( nNewDeltaY, nTab ) ) |
| ++nNewDeltaY; |
| nSizeY = (SCsROW) aViewData.CellsAtY( nNewDeltaY, 1, eAlignY ); |
| } |
| if ( nCurX < nNewDeltaX ) nNewDeltaX = nCurX; |
| if ( nCurY < nNewDeltaY ) nNewDeltaY = nCurY; |
| } |
| |
| if ( nNewDeltaX != nDeltaX ) |
| nSizeX = (SCsCOL) aViewData.CellsAtX( nNewDeltaX, 1, eAlignX ); |
| if (nNewDeltaX+nSizeX-1 > MAXCOL) nNewDeltaX = MAXCOL-nSizeX+1; |
| if (nNewDeltaX < 0) nNewDeltaX = 0; |
| |
| if ( nNewDeltaY != nDeltaY ) |
| nSizeY = (SCsROW) aViewData.CellsAtY( nNewDeltaY, 1, eAlignY ); |
| if (nNewDeltaY+nSizeY-1 > MAXROW) nNewDeltaY = MAXROW-nSizeY+1; |
| if (nNewDeltaY < 0) nNewDeltaY = 0; |
| |
| if ( nNewDeltaX != nDeltaX ) ScrollX( nNewDeltaX - nDeltaX, eAlignX ); |
| if ( nNewDeltaY != nDeltaY ) ScrollY( nNewDeltaY - nDeltaY, eAlignY ); |
| } |
| |
| // |
| // nochmal aktiven Teil umschalten |
| // |
| |
| if (bHFix) |
| if (eActiveX == SC_SPLIT_RIGHT && nCurX < (SCsCOL)aViewData.GetFixPosX()) |
| { |
| ActivatePart( (eActiveY==SC_SPLIT_TOP) ? SC_SPLIT_TOPLEFT : SC_SPLIT_BOTTOMLEFT ); |
| eActiveX = SC_SPLIT_LEFT; |
| } |
| if (bVFix) |
| if (eActiveY == SC_SPLIT_BOTTOM && nCurY < (SCsROW)aViewData.GetFixPosY()) |
| { |
| ActivatePart( (eActiveX==SC_SPLIT_LEFT) ? SC_SPLIT_TOPLEFT : SC_SPLIT_TOPRIGHT ); |
| eActiveY = SC_SPLIT_TOP; |
| } |
| } |
| |
| sal_Bool ScTabView::SelMouseButtonDown( const MouseEvent& rMEvt ) |
| { |
| sal_Bool bRet = sal_False; |
| |
| // #i3875# *Hack* |
| sal_Bool bMod1Locked = aViewData.GetViewShell()->GetLockedModifiers() & KEY_MOD1 ? sal_True : sal_False; |
| aViewData.SetSelCtrlMouseClick( rMEvt.IsMod1() || bMod1Locked ); |
| |
| if ( pSelEngine ) |
| { |
| bMoveIsShift = rMEvt.IsShift(); |
| bRet = pSelEngine->SelMouseButtonDown( rMEvt ); |
| bMoveIsShift = sal_False; |
| } |
| |
| aViewData.SetSelCtrlMouseClick( sal_False ); // #i3875# *Hack* |
| |
| return bRet; |
| } |
| |
| // |
| // MoveCursor - mit Anpassung des Bildausschnitts |
| // |
| |
| void ScTabView::MoveCursorAbs( SCsCOL nCurX, SCsROW nCurY, ScFollowMode eMode, |
| sal_Bool bShift, sal_Bool bControl, sal_Bool bKeepOld, sal_Bool bKeepSel ) |
| { |
| if (!bKeepOld) |
| aViewData.ResetOldCursor(); |
| |
| // i123629 |
| if( aViewData.GetViewShell()->GetForceFocusOnCurCell() ) |
| aViewData.GetViewShell()->SetForceFocusOnCurCell( !ValidColRow(nCurX, nCurY) ); |
| |
| if (nCurX < 0) nCurX = 0; |
| if (nCurY < 0) nCurY = 0; |
| if (nCurX > MAXCOL) nCurX = MAXCOL; |
| if (nCurY > MAXROW) nCurY = MAXROW; |
| |
| HideAllCursors(); |
| |
| if ( bShift && bNewStartIfMarking && IsBlockMode() ) |
| { |
| // used for ADD selection mode: start a new block from the cursor position |
| DoneBlockMode( sal_True ); |
| InitBlockMode( aViewData.GetCurX(), aViewData.GetCurY(), aViewData.GetTabNo(), sal_True ); |
| } |
| |
| // aktiven Teil umschalten jetzt in AlignToCursor |
| |
| AlignToCursor( nCurX, nCurY, eMode ); |
| //! auf OS/2: SC_FOLLOW_JUMP statt SC_FOLLOW_LINE, um Nachlaufen zu verhindern ??? |
| |
| if (bKeepSel) |
| SetCursor( nCurX, nCurY ); // Markierung stehenlassen |
| else |
| { |
| sal_Bool bSame = ( nCurX == aViewData.GetCurX() && nCurY == aViewData.GetCurY() ); |
| bMoveIsShift = bShift; |
| pSelEngine->CursorPosChanging( bShift, bControl ); |
| bMoveIsShift = sal_False; |
| aFunctionSet.SetCursorAtCell( nCurX, nCurY, sal_False ); |
| |
| // Wenn der Cursor nicht bewegt wurde, muss das SelectionChanged fuer das |
| // Aufheben der Selektion hier einzeln passieren: |
| if (bSame) |
| SelectionChanged(); |
| } |
| |
| ShowAllCursors(); |
| } |
| |
| void ScTabView::MoveCursorRel( SCsCOL nMovX, SCsROW nMovY, ScFollowMode eMode, |
| sal_Bool bShift, sal_Bool bKeepSel ) |
| { |
| ScDocument* pDoc = aViewData.GetDocument(); |
| SCTAB nTab = aViewData.GetTabNo(); |
| |
| bool bSkipProtected = false, bSkipUnprotected = false; |
| ScTableProtection* pProtect = pDoc->GetTabProtection(nTab); |
| if ( pProtect && pProtect->isProtected() ) |
| { |
| bSkipProtected = !pProtect->isOptionEnabled(ScTableProtection::SELECT_LOCKED_CELLS); |
| bSkipUnprotected = !pProtect->isOptionEnabled(ScTableProtection::SELECT_UNLOCKED_CELLS); |
| } |
| |
| if ( bSkipProtected && bSkipUnprotected ) |
| return; |
| |
| SCsCOL nOldX; |
| SCsROW nOldY; |
| SCsCOL nCurX; |
| SCsROW nCurY; |
| if ( aViewData.IsRefMode() ) |
| { |
| nOldX = (SCsCOL) aViewData.GetRefEndX(); |
| nOldY = (SCsROW) aViewData.GetRefEndY(); |
| nCurX = nOldX + nMovX; |
| nCurY = nOldY + nMovY; |
| } |
| else |
| { |
| nOldX = (SCsCOL) aViewData.GetCurX(); |
| nOldY = (SCsROW) aViewData.GetCurY(); |
| nCurX = (nMovX != 0) ? nOldX+nMovX : (SCsCOL) aViewData.GetOldCurX(); |
| nCurY = (nMovY != 0) ? nOldY+nMovY : (SCsROW) aViewData.GetOldCurY(); |
| } |
| |
| sal_Bool bSkipCell = sal_False; |
| aViewData.ResetOldCursor(); |
| |
| if (nMovX != 0 && VALIDCOLROW(nCurX,nCurY)) |
| { |
| sal_Bool bHFlip = sal_False; |
| do |
| { |
| SCCOL nLastCol = -1; |
| bSkipCell = pDoc->ColHidden(nCurX, nTab, nLastCol) || pDoc->IsHorOverlapped( nCurX, nCurY, nTab ); |
| if (bSkipProtected && !bSkipCell) |
| bSkipCell = pDoc->HasAttrib(nCurX, nCurY, nTab, nCurX, nCurY, nTab, HASATTR_PROTECTED); |
| if (bSkipUnprotected && !bSkipCell) |
| bSkipCell = !pDoc->HasAttrib(nCurX, nCurY, nTab, nCurX, nCurY, nTab, HASATTR_PROTECTED); |
| |
| if (bSkipCell) |
| { |
| if ( nCurX<=0 || nCurX>=MAXCOL ) |
| { |
| if (bHFlip) |
| { |
| nCurX = nOldX; |
| bSkipCell = sal_False; |
| } |
| else |
| { |
| nMovX = -nMovX; |
| if (nMovX > 0) ++nCurX; else --nCurX; // zuruecknehmen |
| bHFlip = sal_True; |
| } |
| } |
| else |
| if (nMovX > 0) ++nCurX; else --nCurX; |
| } |
| } |
| while (bSkipCell); |
| |
| if (pDoc->IsVerOverlapped( nCurX, nCurY, nTab )) |
| { |
| aViewData.SetOldCursor( nCurX,nCurY ); |
| while (pDoc->IsVerOverlapped( nCurX, nCurY, nTab )) |
| --nCurY; |
| } |
| } |
| |
| if (nMovY != 0 && VALIDCOLROW(nCurX,nCurY)) |
| { |
| sal_Bool bVFlip = sal_False; |
| do |
| { |
| SCROW nLastRow = -1; |
| bSkipCell = pDoc->RowHidden(nCurY, nTab, nLastRow) || pDoc->IsVerOverlapped( nCurX, nCurY, nTab ); |
| if (bSkipProtected && !bSkipCell) |
| bSkipCell = pDoc->HasAttrib(nCurX, nCurY, nTab, nCurX, nCurY, nTab, HASATTR_PROTECTED); |
| if (bSkipUnprotected && !bSkipCell) |
| bSkipCell = !pDoc->HasAttrib(nCurX, nCurY, nTab, nCurX, nCurY, nTab, HASATTR_PROTECTED); |
| |
| if (bSkipCell) |
| { |
| if ( nCurY<=0 || nCurY>=MAXROW ) |
| { |
| if (bVFlip) |
| { |
| nCurY = nOldY; |
| bSkipCell = sal_False; |
| } |
| else |
| { |
| nMovY = -nMovY; |
| if (nMovY > 0) ++nCurY; else --nCurY; // zuruecknehmen |
| bVFlip = sal_True; |
| } |
| } |
| else |
| if (nMovY > 0) ++nCurY; else --nCurY; |
| } |
| } |
| while (bSkipCell); |
| |
| if (pDoc->IsHorOverlapped( nCurX, nCurY, nTab )) |
| { |
| aViewData.SetOldCursor( nCurX,nCurY ); |
| while (pDoc->IsHorOverlapped( nCurX, nCurY, nTab )) |
| --nCurX; |
| } |
| } |
| |
| MoveCursorAbs( nCurX, nCurY, eMode, bShift, sal_False, sal_True, bKeepSel ); |
| } |
| |
| void ScTabView::MoveCursorPage( SCsCOL nMovX, SCsROW nMovY, ScFollowMode eMode, sal_Bool bShift, sal_Bool bKeepSel ) |
| { |
| SCCOL nCurX; |
| SCROW nCurY; |
| aViewData.GetMoveCursor( nCurX,nCurY ); |
| |
| ScSplitPos eWhich = aViewData.GetActivePart(); |
| ScHSplitPos eWhichX = WhichH( eWhich ); |
| ScVSplitPos eWhichY = WhichV( eWhich ); |
| |
| SCsCOL nPageX; |
| SCsROW nPageY; |
| if (nMovX >= 0) |
| nPageX = ((SCsCOL) aViewData.CellsAtX( nCurX, 1, eWhichX )) * nMovX; |
| else |
| nPageX = ((SCsCOL) aViewData.CellsAtX( nCurX, -1, eWhichX )) * nMovX; |
| |
| if (nMovY >= 0) |
| nPageY = ((SCsROW) aViewData.CellsAtY( nCurY, 1, eWhichY )) * nMovY; |
| else |
| nPageY = ((SCsROW) aViewData.CellsAtY( nCurY, -1, eWhichY )) * nMovY; |
| |
| if (nMovX != 0 && nPageX == 0) nPageX = (nMovX>0) ? 1 : -1; |
| if (nMovY != 0 && nPageY == 0) nPageY = (nMovY>0) ? 1 : -1; |
| |
| MoveCursorRel( nPageX, nPageY, eMode, bShift, bKeepSel ); |
| } |
| |
| void ScTabView::MoveCursorArea( SCsCOL nMovX, SCsROW nMovY, ScFollowMode eMode, sal_Bool bShift, sal_Bool bKeepSel ) |
| { |
| SCCOL nCurX; |
| SCROW nCurY; |
| aViewData.GetMoveCursor( nCurX,nCurY ); |
| SCCOL nNewX = nCurX; |
| SCROW nNewY = nCurY; |
| |
| ScDocument* pDoc = aViewData.GetDocument(); |
| SCTAB nTab = aViewData.GetTabNo(); |
| |
| // FindAreaPos kennt nur -1 oder 1 als Richtung |
| |
| SCsCOLROW i; |
| if ( nMovX > 0 ) |
| for ( i=0; i<nMovX; i++ ) |
| pDoc->FindAreaPos( nNewX, nNewY, nTab, 1, 0 ); |
| if ( nMovX < 0 ) |
| for ( i=0; i<-nMovX; i++ ) |
| pDoc->FindAreaPos( nNewX, nNewY, nTab, -1, 0 ); |
| if ( nMovY > 0 ) |
| for ( i=0; i<nMovY; i++ ) |
| pDoc->FindAreaPos( nNewX, nNewY, nTab, 0, 1 ); |
| if ( nMovY < 0 ) |
| for ( i=0; i<-nMovY; i++ ) |
| pDoc->FindAreaPos( nNewX, nNewY, nTab, 0, -1 ); |
| |
| if (eMode==SC_FOLLOW_JUMP) // unten/rechts nicht zuviel grau anzeigen |
| { |
| if (nMovX != 0 && nNewX == MAXCOL) |
| eMode = SC_FOLLOW_LINE; |
| if (nMovY != 0 && nNewY == MAXROW) |
| eMode = SC_FOLLOW_LINE; |
| } |
| |
| MoveCursorRel( ((SCsCOL)nNewX)-(SCsCOL)nCurX, ((SCsROW)nNewY)-(SCsROW)nCurY, eMode, bShift, bKeepSel ); |
| } |
| |
| void ScTabView::MoveCursorEnd( SCsCOL nMovX, SCsROW nMovY, ScFollowMode eMode, sal_Bool bShift, sal_Bool bKeepSel ) |
| { |
| ScDocument* pDoc = aViewData.GetDocument(); |
| SCTAB nTab = aViewData.GetTabNo(); |
| |
| SCCOL nCurX; |
| SCROW nCurY; |
| aViewData.GetMoveCursor( nCurX,nCurY ); |
| SCCOL nNewX = nCurX; |
| SCROW nNewY = nCurY; |
| |
| SCCOL nUsedX = 0; |
| SCROW nUsedY = 0; |
| if ( nMovX > 0 || nMovY > 0 ) |
| pDoc->GetPrintArea( nTab, nUsedX, nUsedY ); // Ende holen |
| |
| if (nMovX<0) |
| nNewX=0; |
| else if (nMovX>0) |
| nNewX=nUsedX; // letzter benutzter Bereich |
| |
| if (nMovY<0) |
| nNewY=0; |
| else if (nMovY>0) |
| nNewY=nUsedY; |
| |
| aViewData.ResetOldCursor(); |
| MoveCursorRel( ((SCsCOL)nNewX)-(SCsCOL)nCurX, ((SCsROW)nNewY)-(SCsROW)nCurY, eMode, bShift, bKeepSel ); |
| } |
| |
| void ScTabView::MoveCursorScreen( SCsCOL nMovX, SCsROW nMovY, ScFollowMode eMode, sal_Bool bShift ) |
| { |
| ScDocument* pDoc = aViewData.GetDocument(); |
| SCTAB nTab = aViewData.GetTabNo(); |
| |
| SCCOL nCurX; |
| SCROW nCurY; |
| aViewData.GetMoveCursor( nCurX,nCurY ); |
| SCCOL nNewX = nCurX; |
| SCROW nNewY = nCurY; |
| |
| ScSplitPos eWhich = aViewData.GetActivePart(); |
| SCCOL nPosX = aViewData.GetPosX( WhichH(eWhich) ); |
| SCROW nPosY = aViewData.GetPosY( WhichV(eWhich) ); |
| |
| SCCOL nAddX = aViewData.VisibleCellsX( WhichH(eWhich) ); |
| if (nAddX != 0) |
| --nAddX; |
| SCROW nAddY = aViewData.VisibleCellsY( WhichV(eWhich) ); |
| if (nAddY != 0) |
| --nAddY; |
| |
| if (nMovX<0) |
| nNewX=nPosX; |
| else if (nMovX>0) |
| nNewX=nPosX+nAddX; |
| |
| if (nMovY<0) |
| nNewY=nPosY; |
| else if (nMovY>0) |
| nNewY=nPosY+nAddY; |
| |
| // aViewData.ResetOldCursor(); |
| aViewData.SetOldCursor( nNewX,nNewY ); |
| |
| while (pDoc->IsHorOverlapped( nNewX, nNewY, nTab )) |
| --nNewX; |
| while (pDoc->IsVerOverlapped( nNewX, nNewY, nTab )) |
| --nNewY; |
| |
| MoveCursorAbs( nNewX, nNewY, eMode, bShift, sal_False, sal_True ); |
| } |
| |
| void ScTabView::MoveCursorEnter( sal_Bool bShift ) // bShift -> hoch/runter |
| { |
| const ScInputOptions& rOpt = SC_MOD()->GetInputOptions(); |
| if (!rOpt.GetMoveSelection()) |
| { |
| aViewData.UpdateInputHandler(sal_True); |
| return; |
| } |
| |
| SCsCOL nMoveX = 0; |
| SCsROW nMoveY = 0; |
| switch ((ScDirection)rOpt.GetMoveDir()) |
| { |
| case DIR_BOTTOM: |
| nMoveY = bShift ? -1 : 1; |
| break; |
| case DIR_RIGHT: |
| nMoveX = bShift ? -1 : 1; |
| break; |
| case DIR_TOP: |
| nMoveY = bShift ? 1 : -1; |
| break; |
| case DIR_LEFT: |
| nMoveX = bShift ? 1 : -1; |
| break; |
| } |
| |
| ScMarkData& rMark = aViewData.GetMarkData(); |
| if (rMark.IsMarked() || rMark.IsMultiMarked()) |
| { |
| SCCOL nCurX; |
| SCROW nCurY; |
| aViewData.GetMoveCursor( nCurX,nCurY ); |
| SCCOL nNewX = nCurX; |
| SCROW nNewY = nCurY; |
| SCTAB nTab = aViewData.GetTabNo(); |
| |
| ScDocument* pDoc = aViewData.GetDocument(); |
| pDoc->GetNextPos( nNewX,nNewY, nTab, nMoveX,nMoveY, sal_True,sal_False, rMark ); |
| |
| MoveCursorRel( ((SCsCOL)nNewX)-(SCsCOL)nCurX, ((SCsROW)nNewY)-(SCsROW)nCurY, |
| SC_FOLLOW_LINE, sal_False, sal_True ); |
| |
| // update input line even if cursor was not moved |
| if ( nNewX == nCurX && nNewY == nCurY ) |
| aViewData.UpdateInputHandler(sal_True); |
| } |
| else |
| { |
| if ( nMoveY != 0 && !nMoveX ) |
| { |
| // nach Tab und Enter wieder zur Ausgangsspalte |
| SCCOL nTabCol = aViewData.GetTabStartCol(); |
| if (nTabCol != SC_TABSTART_NONE) |
| { |
| SCCOL nCurX; |
| SCROW nCurY; |
| aViewData.GetMoveCursor( nCurX,nCurY ); |
| nMoveX = ((SCsCOL)nTabCol)-(SCsCOL)nCurX; |
| } |
| } |
| |
| MoveCursorRel( nMoveX,nMoveY, SC_FOLLOW_LINE, sal_False ); |
| } |
| } |
| |
| |
| sal_Bool ScTabView::MoveCursorKeyInput( const KeyEvent& rKeyEvent ) |
| { |
| const KeyCode& rKCode = rKeyEvent.GetKeyCode(); |
| |
| enum { MOD_NONE, MOD_CTRL, MOD_ALT, MOD_BOTH } eModifier = |
| rKCode.IsMod1() ? |
| (rKCode.IsMod2() ? MOD_BOTH : MOD_CTRL) : |
| (rKCode.IsMod2() ? MOD_ALT : MOD_NONE); |
| |
| sal_Bool bSel = rKCode.IsShift(); |
| sal_uInt16 nCode = rKCode.GetCode(); |
| |
| // CURSOR keys |
| SCsCOL nDX = 0; |
| SCsROW nDY = 0; |
| switch( nCode ) |
| { |
| case KEY_LEFT: nDX = -1; break; |
| case KEY_RIGHT: nDX = 1; break; |
| case KEY_UP: nDY = -1; break; |
| case KEY_DOWN: nDY = 1; break; |
| } |
| if( nDX != 0 || nDY != 0 ) |
| { |
| switch( eModifier ) |
| { |
| case MOD_NONE: MoveCursorRel( nDX, nDY, SC_FOLLOW_LINE, bSel ); break; |
| case MOD_CTRL: MoveCursorArea( nDX, nDY, SC_FOLLOW_JUMP, bSel ); break; |
| default: |
| { |
| // added to avoid warnings |
| } |
| } |
| // always sal_True to suppress changes of col/row size (ALT+CURSOR) |
| return sal_True; |
| } |
| |
| // PAGEUP/PAGEDOWN |
| if( (nCode == KEY_PAGEUP) || (nCode == KEY_PAGEDOWN) ) |
| { |
| nDX = (nCode == KEY_PAGEUP) ? -1 : 1; |
| switch( eModifier ) |
| { |
| case MOD_NONE: MoveCursorPage( 0, static_cast<SCsCOLROW>(nDX), SC_FOLLOW_FIX, bSel ); break; |
| case MOD_ALT: MoveCursorPage( nDX, 0, SC_FOLLOW_FIX, bSel ); break; |
| case MOD_CTRL: SelectNextTab( nDX ); break; |
| default: |
| { |
| // added to avoid warnings |
| } |
| } |
| return sal_True; |
| } |
| |
| // HOME/END |
| if( (nCode == KEY_HOME) || (nCode == KEY_END) ) |
| { |
| nDX = (nCode == KEY_HOME) ? -1 : 1; |
| ScFollowMode eMode = (nCode == KEY_HOME) ? SC_FOLLOW_LINE : SC_FOLLOW_JUMP; |
| switch( eModifier ) |
| { |
| case MOD_NONE: MoveCursorEnd( nDX, 0, eMode, bSel ); break; |
| case MOD_CTRL: MoveCursorEnd( nDX, static_cast<SCsCOLROW>(nDX), eMode, bSel ); break; |
| default: |
| { |
| // added to avoid warnings |
| } |
| } |
| return sal_True; |
| } |
| |
| return sal_False; |
| } |
| |
| |
| // naechste/vorherige nicht geschuetzte Zelle |
| void ScTabView::FindNextUnprot( sal_Bool bShift, sal_Bool bInSelection ) |
| { |
| short nMove = bShift ? -1 : 1; |
| |
| ScMarkData& rMark = aViewData.GetMarkData(); |
| sal_Bool bMarked = bInSelection && (rMark.IsMarked() || rMark.IsMultiMarked()); |
| |
| SCCOL nCurX; |
| SCROW nCurY; |
| aViewData.GetMoveCursor( nCurX,nCurY ); |
| SCCOL nNewX = nCurX; |
| SCROW nNewY = nCurY; |
| SCTAB nTab = aViewData.GetTabNo(); |
| |
| ScDocument* pDoc = aViewData.GetDocument(); |
| pDoc->GetNextPos( nNewX,nNewY, nTab, nMove,0, bMarked,sal_True, rMark ); |
| |
| SCCOL nTabCol = aViewData.GetTabStartCol(); |
| if ( nTabCol == SC_TABSTART_NONE ) |
| nTabCol = nCurX; // auf diese Spalte zurueck bei Enter |
| |
| MoveCursorRel( ((SCsCOL)nNewX)-(SCsCOL)nCurX, ((SCsROW)nNewY)-(SCsROW)nCurY, |
| SC_FOLLOW_LINE, sal_False, sal_True ); |
| |
| // in MoveCursorRel wird die TabCol zurueckgesetzt... |
| aViewData.SetTabStartCol( nTabCol ); |
| } |
| |
| void ScTabView::MarkColumns() |
| { |
| SCCOL nStartCol; |
| SCCOL nEndCol; |
| |
| ScMarkData& rMark = aViewData.GetMarkData(); |
| if (rMark.IsMarked()) |
| { |
| ScRange aMarkRange; |
| rMark.GetMarkArea( aMarkRange ); |
| nStartCol = aMarkRange.aStart.Col(); |
| nEndCol = aMarkRange.aEnd.Col(); |
| } |
| else |
| { |
| SCROW nDummy; |
| aViewData.GetMoveCursor( nStartCol, nDummy ); |
| nEndCol=nStartCol; |
| } |
| |
| SCTAB nTab = aViewData.GetTabNo(); |
| DoneBlockMode(); |
| InitBlockMode( nStartCol,0, nTab ); |
| MarkCursor( nEndCol,MAXROW, nTab ); |
| SelectionChanged(); |
| } |
| |
| void ScTabView::MarkRows() |
| { |
| SCROW nStartRow; |
| SCROW nEndRow; |
| |
| ScMarkData& rMark = aViewData.GetMarkData(); |
| if (rMark.IsMarked()) |
| { |
| ScRange aMarkRange; |
| rMark.GetMarkArea( aMarkRange ); |
| nStartRow = aMarkRange.aStart.Row(); |
| nEndRow = aMarkRange.aEnd.Row(); |
| } |
| else |
| { |
| SCCOL nDummy; |
| aViewData.GetMoveCursor( nDummy, nStartRow ); |
| nEndRow=nStartRow; |
| } |
| |
| SCTAB nTab = aViewData.GetTabNo(); |
| DoneBlockMode(); |
| InitBlockMode( 0,nStartRow, nTab ); |
| MarkCursor( MAXCOL,nEndRow, nTab ); |
| SelectionChanged(); |
| } |
| |
| void ScTabView::MarkDataArea( sal_Bool bIncludeCursor ) |
| { |
| ScDocument* pDoc = aViewData.GetDocument(); |
| SCTAB nTab = aViewData.GetTabNo(); |
| SCCOL nStartCol = aViewData.GetCurX(); |
| SCROW nStartRow = aViewData.GetCurY(); |
| SCCOL nEndCol = nStartCol; |
| SCROW nEndRow = nStartRow; |
| |
| pDoc->GetDataArea( nTab, nStartCol, nStartRow, nEndCol, nEndRow, bIncludeCursor, false ); |
| |
| HideAllCursors(); |
| DoneBlockMode(); |
| InitBlockMode( nStartCol, nStartRow, nTab ); |
| MarkCursor( nEndCol, nEndRow, nTab ); |
| ShowAllCursors(); |
| |
| SelectionChanged(); |
| } |
| |
| void ScTabView::MarkMatrixFormula() |
| { |
| ScDocument* pDoc = aViewData.GetDocument(); |
| ScAddress aCursor( aViewData.GetCurX(), aViewData.GetCurY(), aViewData.GetTabNo() ); |
| ScRange aMatrix; |
| if ( pDoc->GetMatrixFormulaRange( aCursor, aMatrix ) ) |
| { |
| MarkRange( aMatrix, sal_False ); // cursor is already within the range |
| } |
| } |
| |
| void ScTabView::MarkRange( const ScRange& rRange, sal_Bool bSetCursor, sal_Bool bContinue ) |
| { |
| SCTAB nTab = rRange.aStart.Tab(); |
| SetTabNo( nTab ); |
| |
| HideAllCursors(); |
| DoneBlockMode( bContinue ); // bContinue==sal_True -> clear old mark |
| if (bSetCursor) // Wenn Cursor gesetzt wird, immer auch alignen |
| { |
| SCCOL nAlignX = rRange.aStart.Col(); |
| SCROW nAlignY = rRange.aStart.Row(); |
| if ( rRange.aStart.Col() == 0 && rRange.aEnd.Col() == MAXCOL ) |
| nAlignX = aViewData.GetPosX(WhichH(aViewData.GetActivePart())); |
| if ( rRange.aStart.Row() == 0 && rRange.aEnd.Row() == MAXROW ) |
| nAlignY = aViewData.GetPosY(WhichV(aViewData.GetActivePart())); |
| AlignToCursor( nAlignX, nAlignY, SC_FOLLOW_JUMP ); |
| } |
| InitBlockMode( rRange.aStart.Col(), rRange.aStart.Row(), nTab ); |
| MarkCursor( rRange.aEnd.Col(), rRange.aEnd.Row(), nTab ); |
| if (bSetCursor) |
| { |
| SCCOL nPosX = rRange.aStart.Col(); |
| SCROW nPosY = rRange.aStart.Row(); |
| ScDocument* pDoc = aViewData.GetDocument(); |
| |
| while (pDoc->IsHorOverlapped( nPosX, nPosY, nTab )) //! ViewData !!! |
| --nPosX; |
| while (pDoc->IsVerOverlapped( nPosX, nPosY, nTab )) |
| --nPosY; |
| |
| aViewData.ResetOldCursor(); |
| SetCursor( nPosX, nPosY ); |
| } |
| ShowAllCursors(); |
| |
| SelectionChanged(); |
| } |
| |
| void ScTabView::Unmark() |
| { |
| ScMarkData& rMark = aViewData.GetMarkData(); |
| if ( rMark.IsMarked() || rMark.IsMultiMarked() ) |
| { |
| SCCOL nCurX; |
| SCROW nCurY; |
| aViewData.GetMoveCursor( nCurX,nCurY ); |
| MoveCursorAbs( nCurX, nCurY, SC_FOLLOW_NONE, sal_False, sal_False ); |
| |
| SelectionChanged(); |
| } |
| } |
| |
| void ScTabView::SetMarkData( const ScMarkData& rNew ) |
| { |
| DoneBlockMode(); |
| InitOwnBlockMode(); |
| aViewData.GetMarkData() = rNew; |
| |
| MarkDataChanged(); |
| } |
| |
| void ScTabView::MarkDataChanged() |
| { |
| // has to be called after making direct changes to mark data (not via MarkCursor etc) |
| |
| UpdateSelectionOverlay(); |
| } |
| |
| void ScTabView::SelectNextTab( short nDir, sal_Bool bExtendSelection ) |
| { |
| if (!nDir) return; |
| DBG_ASSERT( nDir==-1 || nDir==1, "SelectNextTab: falscher Wert"); |
| |
| ScDocument* pDoc = aViewData.GetDocument(); |
| SCTAB nTab = aViewData.GetTabNo(); |
| if (nDir<0) |
| { |
| if (!nTab) return; |
| --nTab; |
| while (!pDoc->IsVisible(nTab)) |
| { |
| if (!nTab) return; |
| --nTab; |
| } |
| } |
| else |
| { |
| SCTAB nCount = pDoc->GetTableCount(); |
| ++nTab; |
| if (nTab >= nCount) return; |
| while (!pDoc->IsVisible(nTab)) |
| { |
| ++nTab; |
| if (nTab >= nCount) return; |
| } |
| } |
| |
| SetTabNo( nTab, sal_False, bExtendSelection ); |
| PaintExtras(); |
| } |
| |
| void ScTabView::UpdateVisibleRange() |
| { |
| for (sal_uInt16 i=0; i<4; i++) |
| if (pGridWin[i] && pGridWin[i]->IsVisible()) |
| pGridWin[i]->UpdateVisibleRange(); |
| } |
| |
| // SetTabNo - angezeigte Tabelle |
| |
| void ScTabView::SetTabNo( SCTAB nTab, sal_Bool bNew, sal_Bool bExtendSelection, bool bSameTabButMoved ) |
| { |
| if ( !ValidTab(nTab) ) |
| { |
| DBG_ERROR("SetTabNo: falsche Tabelle"); |
| return; |
| } |
| |
| if ( nTab != aViewData.GetTabNo() || bNew ) |
| { |
| // #57724# Die FormShell moechte vor dem Umschalten benachrichtigt werden |
| FmFormShell* pFormSh = aViewData.GetViewShell()->GetFormShell(); |
| if (pFormSh) |
| { |
| sal_Bool bAllowed = sal::static_int_cast<sal_Bool>( pFormSh->PrepareClose( sal_True ) ); |
| if (!bAllowed) |
| { |
| //! Fehlermeldung? oder macht das die FormShell selber? |
| //! Fehler-Flag zurueckgeben und Aktionen abbrechen |
| |
| return; // Die FormShell sagt, es kann nicht umgeschaltet werden |
| } |
| } |
| |
| // nicht InputEnterHandler wegen Referenzeingabe ! |
| |
| ScDocument* pDoc = aViewData.GetDocument(); |
| pDoc->MakeTable( nTab ); |
| |
| // Update pending row heights before switching the sheet, so Reschedule from the progress bar |
| // doesn't paint the new sheet with old heights |
| aViewData.GetDocShell()->UpdatePendingRowHeights( nTab ); |
| |
| SCTAB nTabCount = pDoc->GetTableCount(); |
| SCTAB nOldPos = nTab; |
| while (!pDoc->IsVisible(nTab)) // naechste sichtbare suchen |
| { |
| sal_Bool bUp = (nTab>=nOldPos); |
| if (bUp) |
| { |
| ++nTab; |
| if (nTab>=nTabCount) |
| { |
| nTab = nOldPos; |
| bUp = sal_False; |
| } |
| } |
| |
| if (!bUp) |
| { |
| if (nTab != 0) |
| --nTab; |
| else |
| { |
| DBG_ERROR("keine sichtbare Tabelle"); |
| pDoc->SetVisible( 0, sal_True ); |
| } |
| } |
| } |
| |
| // #i71490# Deselect drawing objects before changing the sheet number in view data, |
| // so the handling of notes still has the sheet selected on which the notes are. |
| DrawDeselectAll(); |
| |
| ScModule* pScMod = SC_MOD(); |
| sal_Bool bRefMode = pScMod->IsFormulaMode(); |
| if ( !bRefMode ) // Abfrage, damit RefMode bei Tabellenwechsel funktioniert |
| { |
| DoneBlockMode(); |
| pSelEngine->Reset(); // reset all flags, including locked modifiers |
| aViewData.SetRefTabNo( nTab ); |
| } |
| |
| ScSplitPos eOldActive = aViewData.GetActivePart(); // before switching |
| sal_Bool bFocus = pGridWin[eOldActive]->HasFocus(); |
| |
| aViewData.SetTabNo( nTab ); |
| // UpdateShow noch vor SetCursor, damit UpdateAutoFillMark die richtigen |
| // Fenster findet (wird aus SetCursor gerufen) |
| UpdateShow(); |
| aViewData.ResetOldCursor(); |
| SetCursor( aViewData.GetCurX(), aViewData.GetCurY(), sal_True ); |
| |
| SfxBindings& rBindings = aViewData.GetBindings(); |
| ScMarkData& rMark = aViewData.GetMarkData(); |
| |
| bool bAllSelected = true; |
| for (SCTAB nSelTab = 0; nSelTab < nTabCount; ++nSelTab) |
| { |
| if (!pDoc->IsVisible(nSelTab) || rMark.GetTableSelect(nSelTab)) |
| { |
| if (nTab == nSelTab) |
| // This tab is already in selection. Keep the current |
| // selection. |
| bExtendSelection = true; |
| } |
| else |
| { |
| bAllSelected = false; |
| if (bExtendSelection) |
| // We got what we need. No need to stay in the loop. |
| break; |
| } |
| } |
| if (bAllSelected && !bNew) |
| // #i6327# if all tables are selected, a selection event (#i6330#) will deselect all |
| // (not if called with bNew to update settings) |
| bExtendSelection = false; |
| |
| if (bExtendSelection) |
| rMark.SelectTable( nTab, sal_True ); |
| else |
| { |
| rMark.SelectOneTable( nTab ); |
| rBindings.Invalidate( FID_FILL_TAB ); |
| rBindings.Invalidate( FID_TAB_DESELECTALL ); |
| } |
| |
| bool bUnoRefDialog = pScMod->IsRefDialogOpen() && pScMod->GetCurRefDlgId() == WID_SIMPLE_REF; |
| |
| // recalc zoom-dependent values (before TabChanged, before UpdateEditViewPos) |
| RefreshZoom(); |
| UpdateVarZoom(); |
| |
| if ( bRefMode ) // hide EditView if necessary (after aViewData.SetTabNo !) |
| { |
| for ( sal_uInt16 i=0; i<4; i++ ) |
| if ( pGridWin[i] ) |
| if ( pGridWin[i]->IsVisible() ) |
| pGridWin[i]->UpdateEditViewPos(); |
| } |
| |
| TabChanged( bSameTabButMoved ); // DrawView |
| |
| aViewData.GetViewShell()->WindowChanged(); // falls das aktive Fenster anders ist |
| if ( !bUnoRefDialog ) |
| aViewData.GetViewShell()->DisconnectAllClients(); // important for floating frames |
| else |
| { |
| // hide / show inplace client |
| |
| ScClient* pClient = static_cast<ScClient*>(aViewData.GetViewShell()->GetIPClient()); |
| if ( pClient && pClient->IsObjectInPlaceActive() ) |
| { |
| Rectangle aObjArea = pClient->GetObjArea(); |
| if ( nTab == aViewData.GetRefTabNo() ) |
| { |
| // move to its original position |
| |
| SdrOle2Obj* pDrawObj = pClient->GetDrawObj(); |
| if ( pDrawObj ) |
| { |
| Rectangle aRect = pDrawObj->GetLogicRect(); |
| MapMode aMapMode( MAP_100TH_MM ); |
| Size aOleSize = pDrawObj->GetOrigObjSize( &aMapMode ); |
| aRect.SetSize( aOleSize ); |
| aObjArea = aRect; |
| } |
| } |
| else |
| { |
| // move to an invisible position |
| |
| aObjArea.SetPos( Point( 0, -2*aObjArea.GetHeight() ) ); |
| } |
| pClient->SetObjArea( aObjArea ); |
| } |
| } |
| |
| if ( bFocus && aViewData.GetActivePart() != eOldActive && !bRefMode ) |
| ActiveGrabFocus(); // grab focus to the pane that's active now |
| |
| // Fixierungen |
| |
| sal_Bool bResize = sal_False; |
| if ( aViewData.GetHSplitMode() == SC_SPLIT_FIX ) |
| if (aViewData.UpdateFixX()) |
| bResize = sal_True; |
| if ( aViewData.GetVSplitMode() == SC_SPLIT_FIX ) |
| if (aViewData.UpdateFixY()) |
| bResize = sal_True; |
| if (bResize) |
| RepeatResize(); |
| InvalidateSplit(); |
| |
| // #163911# Update the visible range in each GridWin directly, don't wait for the repaint event. |
| UpdateVisibleRange(); |
| |
| if ( aViewData.IsPagebreakMode() ) |
| UpdatePageBreakData(); //! asynchron ?? |
| |
| // #53551# Form-Layer muss den sichtbaren Ausschnitt der neuen Tabelle kennen |
| // dafuer muss hier schon der MapMode stimmen |
| for (sal_uInt16 i=0; i<4; i++) |
| if (pGridWin[i]) |
| pGridWin[i]->SetMapMode( pGridWin[i]->GetDrawMapMode() ); |
| SetNewVisArea(); |
| |
| PaintGrid(); |
| PaintTop(); |
| PaintLeft(); |
| PaintExtras(); |
| |
| DoResize( aBorderPos, aFrameSize ); |
| rBindings.Invalidate( SID_DELETE_PRINTAREA ); // Menue |
| rBindings.Invalidate( FID_DEL_MANUALBREAKS ); |
| rBindings.Invalidate( FID_RESET_PRINTZOOM ); |
| rBindings.Invalidate( SID_STATUS_DOCPOS ); // Statusbar |
| rBindings.Invalidate( SID_STATUS_PAGESTYLE ); // Statusbar |
| rBindings.Invalidate( SID_CURRENTTAB ); // Navigator |
| rBindings.Invalidate( SID_STYLE_FAMILY2 ); // Gestalter |
| rBindings.Invalidate( SID_STYLE_FAMILY4 ); // Gestalter |
| rBindings.Invalidate( SID_TABLES_COUNT ); |
| |
| if(pScMod->IsRefDialogOpen()) |
| { |
| sal_uInt16 nCurRefDlgId=pScMod->GetCurRefDlgId(); |
| SfxViewFrame* pViewFrm = aViewData.GetViewShell()->GetViewFrame(); |
| SfxChildWindow* pChildWnd = pViewFrm->GetChildWindow( nCurRefDlgId ); |
| if ( pChildWnd ) |
| { |
| IAnyRefDialog* pRefDlg = dynamic_cast<IAnyRefDialog*>(pChildWnd->GetWindow()); |
| pRefDlg->ViewShellChanged(NULL); |
| } |
| } |
| } |
| } |
| |
| // |
| // Paint-Funktionen - nur fuer diese View |
| // |
| |
| void ScTabView::MakeEditView( ScEditEngineDefaulter* pEngine, SCCOL nCol, SCROW nRow ) |
| { |
| DrawDeselectAll(); |
| |
| if (pDrawView) |
| DrawEnableAnim( sal_False ); |
| |
| EditView* pSpellingView = aViewData.GetSpellingView(); |
| |
| for (sal_uInt16 i=0; i<4; i++) |
| if (pGridWin[i]) |
| if ( pGridWin[i]->IsVisible() && !aViewData.HasEditView((ScSplitPos)i) ) |
| { |
| ScHSplitPos eHWhich = WhichH( (ScSplitPos) i ); |
| ScVSplitPos eVWhich = WhichV( (ScSplitPos) i ); |
| SCCOL nScrX = aViewData.GetPosX( eHWhich ); |
| SCROW nScrY = aViewData.GetPosY( eVWhich ); |
| |
| sal_Bool bPosVisible = |
| ( nCol >= nScrX && nCol <= nScrX + aViewData.VisibleCellsX(eHWhich) + 1 && |
| nRow >= nScrY && nRow <= nScrY + aViewData.VisibleCellsY(eVWhich) + 1 ); |
| |
| // #102421# for the active part, create edit view even if outside the visible area, |
| // so input isn't lost (and the edit view may be scrolled into the visible area) |
| |
| // #i26433# during spelling, the spelling view must be active |
| if ( bPosVisible || aViewData.GetActivePart() == (ScSplitPos) i || |
| ( pSpellingView && aViewData.GetEditView((ScSplitPos) i) == pSpellingView ) ) |
| { |
| pGridWin[i]->HideCursor(); |
| |
| pGridWin[i]->DeleteCursorOverlay(); |
| pGridWin[i]->DeleteAutoFillOverlay(); |
| |
| // flush OverlayManager before changing MapMode to text edit |
| pGridWin[i]->flushOverlayManager(); |
| |
| // MapMode must be set after HideCursor |
| pGridWin[i]->SetMapMode(aViewData.GetLogicMode()); |
| |
| aViewData.SetEditEngine( (ScSplitPos) i, pEngine, pGridWin[i], nCol, nRow ); |
| |
| if ( !bPosVisible ) |
| { |
| // move the edit view area to the real (possibly negative) position, |
| // or hide if completely above or left of the window |
| pGridWin[i]->UpdateEditViewPos(); |
| } |
| } |
| } |
| |
| if (aViewData.GetViewShell()->HasAccessibilityObjects()) |
| aViewData.GetViewShell()->BroadcastAccessibility(SfxSimpleHint(SC_HINT_ACC_ENTEREDITMODE)); |
| } |
| |
| void ScTabView::UpdateEditView() |
| { |
| ScSplitPos eActive = aViewData.GetActivePart(); |
| for (sal_uInt16 i=0; i<4; i++) |
| if (aViewData.HasEditView( (ScSplitPos) i )) |
| { |
| EditView* pEditView = aViewData.GetEditView( (ScSplitPos) i ); |
| aViewData.SetEditEngine( (ScSplitPos) i, |
| static_cast<ScEditEngineDefaulter*>(pEditView->GetEditEngine()), |
| pGridWin[i], GetViewData()->GetCurX(), GetViewData()->GetCurY() ); |
| if ( (ScSplitPos)i == eActive ) |
| pEditView->ShowCursor( sal_False ); |
| } |
| } |
| |
| void ScTabView::KillEditView( sal_Bool bNoPaint ) |
| { |
| sal_uInt16 i; |
| SCCOL nCol1 = aViewData.GetEditStartCol(); |
| SCROW nRow1 = aViewData.GetEditStartRow(); |
| SCCOL nCol2 = aViewData.GetEditEndCol(); |
| SCROW nRow2 = aViewData.GetEditEndRow(); |
| sal_Bool bPaint[4]; |
| sal_Bool bNotifyAcc(false); |
| |
| sal_Bool bExtended = nRow1 != nRow2; // Col wird sowieso bis zum Ende gezeichnet |
| sal_Bool bAtCursor = nCol1 <= aViewData.GetCurX() && |
| nCol2 >= aViewData.GetCurX() && |
| nRow1 == aViewData.GetCurY(); |
| for (i=0; i<4; i++) |
| { |
| bPaint[i] = aViewData.HasEditView( (ScSplitPos) i ); |
| if (bPaint[i]) |
| bNotifyAcc = true; |
| } |
| |
| // #108931#; notify accessibility before all things happen |
| if ((bNotifyAcc) && (aViewData.GetViewShell()->HasAccessibilityObjects())) |
| aViewData.GetViewShell()->BroadcastAccessibility(SfxSimpleHint(SC_HINT_ACC_LEAVEEDITMODE)); |
| |
| aViewData.ResetEditView(); |
| for (i=0; i<4; i++) |
| if (pGridWin[i] && bPaint[i]) |
| if (pGridWin[i]->IsVisible()) |
| { |
| pGridWin[i]->ShowCursor(); |
| |
| pGridWin[i]->SetMapMode(pGridWin[i]->GetDrawMapMode()); |
| |
| // #i73567# the cell still has to be repainted |
| if (bExtended || ( bAtCursor && !bNoPaint )) |
| { |
| pGridWin[i]->Draw( nCol1, nRow1, nCol2, nRow2 ); |
| pGridWin[i]->UpdateSelectionOverlay(); |
| } |
| } |
| |
| if (pDrawView) |
| DrawEnableAnim( sal_True ); |
| |
| // GrabFocus immer dann, wenn diese View aktiv ist und |
| // die Eingabezeile den Focus hat |
| |
| sal_Bool bGrabFocus = sal_False; |
| if (aViewData.IsActive()) |
| { |
| ScInputHandler* pInputHdl = SC_MOD()->GetInputHdl(); |
| if ( pInputHdl ) |
| { |
| ScInputWindow* pInputWin = pInputHdl->GetInputWindow(); |
| if (pInputWin && pInputWin->IsInputActive()) |
| bGrabFocus = sal_True; |
| } |
| } |
| |
| if (bGrabFocus) |
| { |
| // So soll es gemacht werden, damit der Sfx es mitbekommt, klappt aber nicht: |
| //! aViewData.GetViewShell()->GetViewFrame()->GetWindow().GrabFocus(); |
| // deshalb erstmal so: |
| GetActiveWin()->GrabFocus(); |
| } |
| |
| // Cursor-Abfrage erst nach GrabFocus |
| |
| for (i=0; i<4; i++) |
| if (pGridWin[i] && pGridWin[i]->IsVisible()) |
| { |
| Cursor* pCur = pGridWin[i]->GetCursor(); |
| if (pCur && pCur->IsVisible()) |
| pCur->Hide(); |
| |
| if(bPaint[i]) |
| { |
| pGridWin[i]->UpdateCursorOverlay(); |
| pGridWin[i]->UpdateAutoFillOverlay(); |
| // pGridWin[i]->UpdateAllOverlays(); |
| } |
| } |
| } |
| |
| void ScTabView::UpdateFormulas() |
| { |
| if ( aViewData.GetDocument()->IsAutoCalcShellDisabled() ) |
| return ; |
| |
| sal_uInt16 i; |
| for (i=0; i<4; i++) |
| if (pGridWin[i]) |
| if (pGridWin[i]->IsVisible()) |
| pGridWin[i]->UpdateFormulas(); |
| |
| if ( aViewData.IsPagebreakMode() ) |
| UpdatePageBreakData(); //! asynchron |
| |
| UpdateHeaderWidth(); |
| |
| // if in edit mode, adjust edit view area because widths/heights may have changed |
| if ( aViewData.HasEditView( aViewData.GetActivePart() ) ) |
| UpdateEditView(); |
| } |
| |
| // PaintArea -Block neu zeichnen |
| |
| void ScTabView::PaintArea( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow, |
| ScUpdateMode eMode ) |
| { |
| sal_uInt16 i; |
| SCCOL nCol1; |
| SCROW nRow1; |
| SCCOL nCol2; |
| SCROW nRow2; |
| |
| PutInOrder( nStartCol, nEndCol ); |
| PutInOrder( nStartRow, nEndRow ); |
| |
| for (i=0; i<4; i++) |
| if (pGridWin[i]) |
| if (pGridWin[i]->IsVisible()) |
| { |
| ScHSplitPos eHWhich = WhichH( (ScSplitPos) i ); |
| ScVSplitPos eVWhich = WhichV( (ScSplitPos) i ); |
| sal_Bool bOut = sal_False; |
| |
| nCol1 = nStartCol; |
| nRow1 = nStartRow; |
| nCol2 = nEndCol; |
| nRow2 = nEndRow; |
| |
| SCCOL nScrX = aViewData.GetPosX( eHWhich ); |
| SCROW nScrY = aViewData.GetPosY( eVWhich ); |
| if (nCol1 < nScrX) nCol1 = nScrX; |
| if (nCol2 < nScrX) |
| { |
| if ( eMode == SC_UPDATE_ALL ) // #91240# for UPDATE_ALL, paint anyway |
| nCol2 = nScrX; // (because of extending strings to the right) |
| else |
| bOut = sal_True; // completely outside the window |
| } |
| if (nRow1 < nScrY) nRow1 = nScrY; |
| if (nRow2 < nScrY) bOut = sal_True; |
| |
| SCCOL nLastX = nScrX + aViewData.VisibleCellsX( eHWhich ) + 1; |
| SCROW nLastY = nScrY + aViewData.VisibleCellsY( eVWhich ) + 1; |
| if (nCol1 > nLastX) bOut = sal_True; |
| if (nCol2 > nLastX) nCol2 = nLastX; |
| if (nRow1 > nLastY) bOut = sal_True; |
| if (nRow2 > nLastY) nRow2 = nLastY; |
| |
| if (!bOut) |
| { |
| if ( eMode == SC_UPDATE_CHANGED ) |
| pGridWin[i]->Draw( nCol1, nRow1, nCol2, nRow2, eMode ); |
| else // ALL oder MARKS |
| { |
| sal_Bool bLayoutRTL = aViewData.GetDocument()->IsLayoutRTL( aViewData.GetTabNo() ); |
| long nLayoutSign = bLayoutRTL ? -1 : 1; |
| |
| Point aStart = aViewData.GetScrPos( nCol1, nRow1, (ScSplitPos) i ); |
| Point aEnd = aViewData.GetScrPos( nCol2+1, nRow2+1, (ScSplitPos) i ); |
| if ( eMode == SC_UPDATE_ALL ) |
| aEnd.X() = bLayoutRTL ? 0 : (pGridWin[i]->GetOutputSizePixel().Width()); |
| aEnd.X() -= nLayoutSign; |
| aEnd.Y() -= 1; |
| |
| // #i85232# include area below cells (could be done in GetScrPos?) |
| if ( eMode == SC_UPDATE_ALL && nRow2 >= MAXROW ) |
| aEnd.Y() = pGridWin[i]->GetOutputSizePixel().Height(); |
| |
| sal_Bool bShowChanges = sal_True; //! ... |
| if (bShowChanges) |
| { |
| aStart.X() -= nLayoutSign; // include change marks |
| aStart.Y() -= 1; |
| } |
| |
| sal_Bool bMarkClipped = aViewData.GetOptions().GetOption( VOPT_CLIPMARKS ); |
| if (bMarkClipped) |
| { |
| // dazu muesste ScColumn::IsEmptyBlock optimiert werden |
| // (auf Search() umstellen) |
| //!if ( nCol1 > 0 && !aViewData.GetDocument()->IsBlockEmpty( |
| //! aViewData.GetTabNo(), |
| //! 0, nRow1, nCol1-1, nRow2 ) ) |
| { |
| long nMarkPixel = (long)( SC_CLIPMARK_SIZE * aViewData.GetPPTX() ); |
| aStart.X() -= nMarkPixel * nLayoutSign; |
| if (!bShowChanges) |
| aStart.X() -= nLayoutSign; // cell grid |
| } |
| } |
| |
| pGridWin[i]->Invalidate( pGridWin[i]->PixelToLogic( Rectangle( aStart,aEnd ) ) ); |
| } |
| } |
| } |
| |
| // #i79909# Calling UpdateAllOverlays here isn't necessary and would lead to overlay calls from a timer, |
| // with a wrong MapMode if editing in a cell (reference input). |
| // #i80499# Overlays need updates in a lot of cases, e.g. changing row/column size, |
| // or showing/hiding outlines. TODO: selections in inactive windows are vanishing. |
| // #i84689# With relative conditional formats, PaintArea may be called often (for each changed cell), |
| // so UpdateAllOverlays was moved to ScTabViewShell::Notify and is called only if PAINT_LEFT/PAINT_TOP |
| // is set (width or height changed). |
| } |
| |
| void ScTabView::PaintRangeFinder( long nNumber ) |
| { |
| ScInputHandler* pHdl = SC_MOD()->GetInputHdl( aViewData.GetViewShell() ); |
| if (pHdl) |
| { |
| ScRangeFindList* pRangeFinder = pHdl->GetRangeFindList(); |
| if ( pRangeFinder && pRangeFinder->GetDocName() == aViewData.GetDocShell()->GetTitle() ) |
| { |
| SCTAB nTab = aViewData.GetTabNo(); |
| sal_uInt16 nCount = (sal_uInt16)pRangeFinder->Count(); |
| for (sal_uInt16 i=0; i<nCount; i++) |
| if ( nNumber < 0 || nNumber == i ) |
| { |
| ScRangeFindData* pData = pRangeFinder->GetObject(i); |
| if (pData) |
| { |
| ScRange aRef = pData->aRef; |
| aRef.Justify(); // Justify fuer die Abfragen unten |
| |
| if ( aRef.aStart == aRef.aEnd ) //! Tab ignorieren? |
| aViewData.GetDocument()->ExtendMerge(aRef); |
| |
| if ( aRef.aStart.Tab() >= nTab && aRef.aEnd.Tab() <= nTab ) |
| { |
| SCCOL nCol1 = aRef.aStart.Col(); |
| SCROW nRow1 = aRef.aStart.Row(); |
| SCCOL nCol2 = aRef.aEnd.Col(); |
| SCROW nRow2 = aRef.aEnd.Row(); |
| |
| // wegnehmen -> Repaint |
| // SC_UPDATE_MARKS: Invalidate, nicht bis zum Zeilenende |
| |
| sal_Bool bHiddenEdge = sal_False; |
| SCROW nTmp; |
| ScDocument* pDoc = aViewData.GetDocument(); |
| SCCOL nLastCol = -1; |
| while ( nCol1 > 0 && pDoc->ColHidden(nCol1, nTab, nLastCol) ) |
| { |
| --nCol1; |
| bHiddenEdge = sal_True; |
| } |
| while ( nCol2 < MAXCOL && pDoc->ColHidden(nCol2, nTab, nLastCol) ) |
| { |
| ++nCol2; |
| bHiddenEdge = sal_True; |
| } |
| nTmp = pDoc->LastVisibleRow(0, nRow1, nTab); |
| if (!ValidRow(nTmp)) |
| nTmp = 0; |
| if (nTmp < nRow1) |
| { |
| nRow1 = nTmp; |
| bHiddenEdge = sal_True; |
| } |
| nTmp = pDoc->FirstVisibleRow(nRow2, MAXROW, nTab); |
| if (!ValidRow(nTmp)) |
| nTmp = MAXROW; |
| if (nTmp > nRow2) |
| { |
| nRow2 = nTmp; |
| bHiddenEdge = sal_True; |
| } |
| |
| if ( nCol2 - nCol1 > 1 && nRow2 - nRow1 > 1 && !bHiddenEdge ) |
| { |
| // nur an den Raendern entlang |
| PaintArea( nCol1, nRow1, nCol2, nRow1, SC_UPDATE_MARKS ); |
| PaintArea( nCol1, nRow1+1, nCol1, nRow2-1, SC_UPDATE_MARKS ); |
| PaintArea( nCol2, nRow1+1, nCol2, nRow2-1, SC_UPDATE_MARKS ); |
| PaintArea( nCol1, nRow2, nCol2, nRow2, SC_UPDATE_MARKS ); |
| } |
| else // alles am Stueck |
| PaintArea( nCol1, nRow1, nCol2, nRow2, SC_UPDATE_MARKS ); |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| // fuer Chart-Daten-Markierung |
| |
| void ScTabView::AddHighlightRange( const ScRange& rRange, const Color& rColor ) |
| { |
| if (!pHighlightRanges) |
| pHighlightRanges = new ScHighlightRanges; |
| pHighlightRanges->Insert( new ScHighlightEntry( rRange, rColor ) ); |
| |
| SCTAB nTab = aViewData.GetTabNo(); |
| if ( nTab >= rRange.aStart.Tab() && nTab <= rRange.aEnd.Tab() ) |
| PaintArea( rRange.aStart.Col(), rRange.aStart.Row(), |
| rRange.aEnd.Col(), rRange.aEnd.Row(), SC_UPDATE_MARKS ); |
| } |
| |
| void ScTabView::ClearHighlightRanges() |
| { |
| if (pHighlightRanges) |
| { |
| ScHighlightRanges* pTemp = pHighlightRanges; |
| pHighlightRanges = NULL; // Repaint ohne Highlight |
| |
| SCTAB nTab = aViewData.GetTabNo(); |
| sal_uLong nCount = pTemp->Count(); |
| for (sal_uLong i=0; i<nCount; i++) |
| { |
| ScHighlightEntry* pEntry = pTemp->GetObject( i ); |
| if (pEntry) |
| { |
| ScRange aRange = pEntry->aRef; |
| if ( nTab >= aRange.aStart.Tab() && nTab <= aRange.aEnd.Tab() ) |
| PaintArea( aRange.aStart.Col(), aRange.aStart.Row(), |
| aRange.aEnd.Col(), aRange.aEnd.Row(), SC_UPDATE_MARKS ); |
| } |
| } |
| delete pTemp; |
| } |
| } |
| |
| void ScTabView::DoChartSelection( |
| const uno::Sequence< chart2::data::HighlightedRange > & rHilightRanges ) |
| { |
| ClearHighlightRanges(); |
| |
| for( sal_Int32 i=0; i<rHilightRanges.getLength(); ++i ) |
| { |
| Color aSelColor( rHilightRanges[i].PreferredColor ); |
| ScRangeList aRangeList; |
| ScDocument* pDoc = aViewData.GetDocShell()->GetDocument(); |
| if( ScRangeStringConverter::GetRangeListFromString( |
| aRangeList, rHilightRanges[i].RangeRepresentation, pDoc, pDoc->GetAddressConvention(), ';' )) |
| { |
| for ( ScRangePtr p = aRangeList.First(); p; p = aRangeList.Next()) |
| { |
| if( rHilightRanges[i].Index == - 1 ) |
| AddHighlightRange( *p, aSelColor ); |
| else |
| AddHighlightRange( lcl_getSubRangeByIndex( *p, rHilightRanges[i].Index ), aSelColor ); |
| } |
| } |
| } |
| } |
| |
| // DrawDragRect - Drag&Drop-Rechteck zeichnen (XOR) |
| |
| //UNUSED2008-05 void ScTabView::DrawDragRect( SCCOL nStartX, SCROW nStartY, SCCOL nEndX, SCROW nEndY, |
| //UNUSED2008-05 ScSplitPos ePos ) |
| //UNUSED2008-05 { |
| //UNUSED2008-05 if ( aViewData.GetHSplitMode() == SC_SPLIT_FIX || aViewData.GetVSplitMode() == SC_SPLIT_FIX ) |
| //UNUSED2008-05 { |
| //UNUSED2008-05 for (sal_uInt16 i=0; i<4; i++) |
| //UNUSED2008-05 if (pGridWin[i]) |
| //UNUSED2008-05 if (pGridWin[i]->IsVisible()) |
| //UNUSED2008-05 pGridWin[i]->DrawDragRect( nStartX, nStartY, nEndX, nEndY ); |
| //UNUSED2008-05 } |
| //UNUSED2008-05 else |
| //UNUSED2008-05 pGridWin[ePos]->DrawDragRect( nStartX, nStartY, nEndX, nEndY ); |
| //UNUSED2008-05 } |
| //UNUSED2008-05 |
| //UNUSED2008-05 // PaintCell - einzelne Zelle neu zeichnen |
| //UNUSED2008-05 |
| //UNUSED2008-05 void ScTabView::PaintCell( SCCOL nCol, SCROW nRow, SCTAB nTab ) |
| //UNUSED2008-05 { |
| //UNUSED2008-05 if ( aViewData.GetTabNo() == nTab ) |
| //UNUSED2008-05 { |
| //UNUSED2008-05 sal_uInt16 i; |
| //UNUSED2008-05 for (i=0; i<4; i++) |
| //UNUSED2008-05 if (pGridWin[i]) |
| //UNUSED2008-05 if (pGridWin[i]->IsVisible()) |
| //UNUSED2008-05 pGridWin[i]->Draw( nCol, nRow, nCol, nRow ); |
| //UNUSED2008-05 } |
| //UNUSED2008-05 } |
| //UNUSED2008-05 |
| //UNUSED2008-05 void ScTabView::PaintLeftRow( SCROW nRow ) |
| //UNUSED2008-05 { |
| //UNUSED2008-05 PaintLeftArea( nRow, nRow ); |
| //UNUSED2008-05 } |
| //UNUSED2008-05 |
| //UNUSED2008-05 void ScTabView::PaintTopCol( SCCOL nCol ) |
| //UNUSED2008-05 { |
| //UNUSED2008-05 PaintTopArea( nCol, nCol ); |
| //UNUSED2008-05 } |
| |
| // PaintGrid - Datenbereiche neu zeichnen |
| |
| void ScTabView::PaintGrid() |
| { |
| sal_uInt16 i; |
| for (i=0; i<4; i++) |
| if (pGridWin[i]) |
| if (pGridWin[i]->IsVisible()) |
| pGridWin[i]->Invalidate(); |
| } |
| |
| // PaintTop - obere Kontrollelemente neu zeichnen |
| |
| void ScTabView::PaintTop() |
| { |
| sal_uInt16 i; |
| for (i=0; i<2; i++) |
| { |
| if (pColBar[i]) |
| pColBar[i]->Invalidate(); |
| if (pColOutline[i]) |
| pColOutline[i]->Invalidate(); |
| } |
| } |
| |
| void ScTabView::CreateAnchorHandles(SdrHdlList& rHdl, const ScAddress& rAddress) |
| { |
| sal_uInt16 i; |
| |
| for(i=0; i<4; i++) |
| { |
| if(pGridWin[i]) |
| { |
| if(pGridWin[i]->IsVisible()) |
| { |
| pGridWin[i]->CreateAnchorHandle(rHdl, rAddress); |
| } |
| } |
| } |
| } |
| |
| void ScTabView::PaintTopArea( SCCOL nStartCol, SCCOL nEndCol ) |
| { |
| // Pixel-Position der linken Kante |
| |
| if ( nStartCol < aViewData.GetPosX(SC_SPLIT_LEFT) || |
| nStartCol < aViewData.GetPosX(SC_SPLIT_RIGHT) ) |
| aViewData.RecalcPixPos(); |
| |
| // Fixierung anpassen (UpdateFixX setzt HSplitPos neu) |
| |
| if ( aViewData.GetHSplitMode() == SC_SPLIT_FIX && nStartCol < aViewData.GetFixPosX() ) |
| if (aViewData.UpdateFixX()) |
| RepeatResize(); |
| |
| // zeichnen |
| |
| if (nStartCol>0) |
| --nStartCol; //! allgemeiner ? |
| |
| sal_Bool bLayoutRTL = aViewData.GetDocument()->IsLayoutRTL( aViewData.GetTabNo() ); |
| long nLayoutSign = bLayoutRTL ? -1 : 1; |
| |
| for (sal_uInt16 i=0; i<2; i++) |
| { |
| ScHSplitPos eWhich = (ScHSplitPos) i; |
| if (pColBar[eWhich]) |
| { |
| Size aWinSize = pColBar[eWhich]->GetSizePixel(); |
| long nStartX = aViewData.GetScrPos( nStartCol, 0, eWhich ).X(); |
| long nEndX; |
| if (nEndCol >= MAXCOL) |
| nEndX = bLayoutRTL ? 0 : ( aWinSize.Width()-1 ); |
| else |
| nEndX = aViewData.GetScrPos( nEndCol+1, 0, eWhich ).X() - nLayoutSign; |
| pColBar[eWhich]->Invalidate( |
| Rectangle( nStartX, 0, nEndX, aWinSize.Height()-1 ) ); |
| } |
| if (pColOutline[eWhich]) |
| pColOutline[eWhich]->Invalidate(); |
| } |
| } |
| |
| |
| // PaintLeft - linke Kontrollelemente neu zeichnen |
| |
| void ScTabView::PaintLeft() |
| { |
| sal_uInt16 i; |
| for (i=0; i<2; i++) |
| { |
| if (pRowBar[i]) |
| pRowBar[i]->Invalidate(); |
| if (pRowOutline[i]) |
| pRowOutline[i]->Invalidate(); |
| } |
| } |
| |
| void ScTabView::PaintLeftArea( SCROW nStartRow, SCROW nEndRow ) |
| { |
| // Pixel-Position der oberen Kante |
| |
| if ( nStartRow < aViewData.GetPosY(SC_SPLIT_TOP) || |
| nStartRow < aViewData.GetPosY(SC_SPLIT_BOTTOM) ) |
| aViewData.RecalcPixPos(); |
| |
| // Fixierung anpassen (UpdateFixY setzt VSplitPos neu) |
| |
| if ( aViewData.GetVSplitMode() == SC_SPLIT_FIX && nStartRow < aViewData.GetFixPosY() ) |
| if (aViewData.UpdateFixY()) |
| RepeatResize(); |
| |
| // zeichnen |
| |
| if (nStartRow>0) |
| --nStartRow; |
| |
| for (sal_uInt16 i=0; i<2; i++) |
| { |
| ScVSplitPos eWhich = (ScVSplitPos) i; |
| if (pRowBar[eWhich]) |
| { |
| Size aWinSize = pRowBar[eWhich]->GetSizePixel(); |
| long nStartY = aViewData.GetScrPos( 0, nStartRow, eWhich ).Y(); |
| long nEndY; |
| if (nEndRow >= MAXROW) |
| nEndY = aWinSize.Height()-1; |
| else |
| nEndY = aViewData.GetScrPos( 0, nEndRow+1, eWhich ).Y() - 1; |
| pRowBar[eWhich]->Invalidate( |
| Rectangle( 0, nStartY, aWinSize.Width()-1, nEndY ) ); |
| } |
| if (pRowOutline[eWhich]) |
| pRowOutline[eWhich]->Invalidate(); |
| } |
| } |
| |
| // InvertBlockMark - Block invertieren |
| |
| void ScTabView::InvertBlockMark(SCCOL nStartX, SCROW nStartY, |
| SCCOL nEndX, SCROW nEndY) |
| { |
| if ( !aViewData.IsActive() ) |
| return; // invertiert wird nur auf aktiver View |
| |
| PutInOrder( nStartX, nEndX ); |
| PutInOrder( nStartY, nEndY ); |
| |
| ScMarkData& rMark = aViewData.GetMarkData(); |
| ScDocShell* pDocSh = aViewData.GetDocShell(); |
| ScDocument* pDoc = pDocSh->GetDocument(); |
| SCTAB nTab = aViewData.GetTabNo(); |
| |
| if ( pDocSh->GetLockCount() ) |
| { |
| // if paint is locked, avoid repeated inverting |
| // add repaint areas to paint lock data instead |
| pDocSh->PostPaint( nStartX,nStartY,nTab, nEndX,nEndY,nTab, PAINT_GRID ); |
| return; |
| } |
| |
| sal_Bool bSingle = rMark.IsMultiMarked(); |
| sal_Bool bMerge = pDoc->HasAttrib( nStartX, nStartY, nTab, nEndX, nEndY, nTab, |
| HASATTR_MERGED | HASATTR_OVERLAPPED ); |
| |
| sal_uInt16 i; |
| if ( bMerge || bSingle ) |
| { |
| for (i=0; i<4; i++) |
| if (pGridWin[i]) |
| if (pGridWin[i]->IsVisible()) |
| pGridWin[i]->InvertSimple( nStartX, nStartY, nEndX, nEndY, |
| bMerge, bBlockNeg ); |
| } |
| else |
| { |
| for (i=0; i<4; i++) |
| if (pGridWin[i]) |
| if (pGridWin[i]->IsVisible()) |
| { |
| ScSplitPos ePos = (ScSplitPos) i; |
| Point aStartPoint = aViewData.GetScrPos( nStartX, nStartY, ePos ); |
| Point aEndPoint = aViewData.GetScrPos( nEndX+1, nEndY+1, ePos ); |
| if ( pDoc->IsLayoutRTL( nTab ) ) |
| { |
| long nTemp = aStartPoint.X(); |
| aStartPoint.X() = aEndPoint.X() + 1; // +1 - excluding start of nEndX+1 |
| aEndPoint.X() = nTemp; |
| } |
| else |
| aEndPoint.X() -= 1; |
| aEndPoint.Y() -= 1; |
| if ( aEndPoint.X() >= aStartPoint.X() && aEndPoint.Y() >= aStartPoint.Y() ) |
| { |
| MapMode aOld = pGridWin[ePos]->GetMapMode(); |
| pGridWin[ePos]->SetMapMode(MAP_PIXEL); |
| pGridWin[ePos]->Invert( Rectangle(aStartPoint,aEndPoint), INVERT_HIGHLIGHT ); |
| pGridWin[ePos]->SetMapMode(aOld); |
| pGridWin[ePos]->CheckInverted(); |
| } |
| } |
| } |
| |
| // |
| // wenn Controls betroffen, neu malen |
| // |
| |
| sal_Bool bHide = sal_True; // wird Teil der Markierung aufgehoben ? |
| if (rMark.IsMarked()) |
| { |
| ScRange aMarkRange; |
| rMark.GetMarkArea( aMarkRange ); |
| if ( aMarkRange.aStart.Col() <= nStartX && aMarkRange.aEnd.Col() >= nEndX && |
| aMarkRange.aStart.Row() <= nStartY && aMarkRange.aEnd.Row() >= nEndY ) |
| { |
| bHide = sal_False; // der ganze Bereich ist markiert |
| } |
| } |
| } |
| |
| sal_Bool ScTabView::PaintExtras() |
| { |
| sal_Bool bRet = sal_False; |
| ScDocument* pDoc = aViewData.GetDocument(); |
| SCTAB nTab = aViewData.GetTabNo(); |
| if (!pDoc->HasTable(nTab)) // Tabelle geloescht ? |
| { |
| SCTAB nCount = pDoc->GetTableCount(); |
| aViewData.SetTabNo(nCount-1); |
| bRet = sal_True; |
| } |
| pTabControl->UpdateStatus(); // sal_True = active |
| return bRet; |
| } |
| |
| void ScTabView::RecalcPPT() |
| { |
| // called after changes that require the PPT values to be recalculated |
| // (currently from detective operations) |
| |
| double nOldX = aViewData.GetPPTX(); |
| double nOldY = aViewData.GetPPTY(); |
| |
| aViewData.RefreshZoom(); // pre-calculate new PPT values |
| |
| sal_Bool bChangedX = ( aViewData.GetPPTX() != nOldX ); |
| sal_Bool bChangedY = ( aViewData.GetPPTY() != nOldY ); |
| if ( bChangedX || bChangedY ) |
| { |
| // call view SetZoom (including draw scale, split update etc) |
| // and paint only if values changed |
| |
| Fraction aZoomX = aViewData.GetZoomX(); |
| Fraction aZoomY = aViewData.GetZoomY(); |
| SetZoom( aZoomX, aZoomY, sal_False ); |
| |
| PaintGrid(); |
| if (bChangedX) |
| PaintTop(); |
| if (bChangedY) |
| PaintLeft(); |
| } |
| } |
| |
| void ScTabView::ActivateView( sal_Bool bActivate, sal_Bool bFirst ) |
| { |
| if ( bActivate == aViewData.IsActive() && !bFirst ) |
| { |
| // keine Assertion mehr - kommt vor, wenn vorher im Drag&Drop |
| // auf ein anderes Dokument umgeschaltet wurde |
| return; |
| } |
| |
| // wird nur bei MDI-(De)Activate gerufen |
| // aViewData.Activate hinten wegen Cursor-Show bei KillEditView |
| // Markierung nicht mehr loeschen - wenn an der ViewData Activate(sal_False) gesetzt ist, |
| // wird die Markierung nicht ausgegeben |
| |
| if (!bActivate) |
| { |
| ScModule* pScMod = SC_MOD(); |
| sal_Bool bRefMode = pScMod->IsFormulaMode(); |
| |
| // Referenzeingabe nicht abbrechen, um Referenzen auf |
| // andere Dokumente zuzulassen |
| |
| if (!bRefMode) |
| { |
| //pScMod->InputEnterHandler(); |
| |
| // #80843# pass view to GetInputHdl, this view may not be current anymore |
| ScInputHandler* pHdl = SC_MOD()->GetInputHdl(aViewData.GetViewShell()); |
| if (pHdl) |
| pHdl->EnterHandler(); |
| } |
| } |
| pTabControl->ActivateView(bActivate); |
| PaintExtras(); |
| |
| aViewData.Activate(bActivate); |
| |
| PaintBlock(sal_False); // Repaint, Markierung je nach Active-Status |
| |
| if (!bActivate) |
| HideAllCursors(); // Cursor |
| else if (!bFirst) |
| ShowAllCursors(); |
| |
| //HMHif (pDrawView) |
| //HMH DrawShowMarkHdl(bActivate); // Drawing-Markierung |
| |
| if (bActivate) |
| { |
| if ( bFirst ) |
| { |
| ScSplitPos eWin = aViewData.GetActivePart(); |
| DBG_ASSERT( pGridWin[eWin], "rottes Dokument, nicht alle SplitPos in GridWin" ); |
| if ( !pGridWin[eWin] ) |
| { |
| eWin = SC_SPLIT_BOTTOMLEFT; |
| if ( !pGridWin[eWin] ) |
| { |
| short i; |
| for ( i=0; i<4; i++ ) |
| { |
| if ( pGridWin[i] ) |
| { |
| eWin = (ScSplitPos) i; |
| break; // for |
| } |
| } |
| DBG_ASSERT( i<4, "und BUMM" ); |
| } |
| aViewData.SetActivePart( eWin ); |
| } |
| } |
| // hier nicht mehr selber GrabFocus rufen! |
| // Wenn das Doc bearbeitet wird, ruft der Sfx selber GrabFocus am Fenster der Shell. |
| // Wenn es z.B. ein Mailbody ist, darf es den Focus nicht bekommen (Bug #43638#) |
| |
| UpdateInputContext(); |
| } |
| else |
| pGridWin[aViewData.GetActivePart()]->ClickExtern(); |
| } |
| |
| void ScTabView::ActivatePart( ScSplitPos eWhich ) |
| { |
| ScSplitPos eOld = aViewData.GetActivePart(); |
| if ( eOld != eWhich ) |
| { |
| bInActivatePart = sal_True; |
| |
| sal_Bool bRefMode = SC_MOD()->IsFormulaMode(); |
| |
| // #40565# the HasEditView call during SetCursor would fail otherwise |
| if ( aViewData.HasEditView(eOld) && !bRefMode ) |
| UpdateInputLine(); |
| |
| ScHSplitPos eOldH = WhichH(eOld); |
| ScVSplitPos eOldV = WhichV(eOld); |
| ScHSplitPos eNewH = WhichH(eWhich); |
| ScVSplitPos eNewV = WhichV(eWhich); |
| sal_Bool bTopCap = pColBar[eOldH] && pColBar[eOldH]->IsMouseCaptured(); |
| sal_Bool bLeftCap = pRowBar[eOldV] && pRowBar[eOldV]->IsMouseCaptured(); |
| |
| sal_Bool bFocus = pGridWin[eOld]->HasFocus(); |
| sal_Bool bCapture = pGridWin[eOld]->IsMouseCaptured(); |
| if (bCapture) |
| pGridWin[eOld]->ReleaseMouse(); |
| pGridWin[eOld]->ClickExtern(); |
| pGridWin[eOld]->HideCursor(); |
| pGridWin[eWhich]->HideCursor(); |
| aViewData.SetActivePart( eWhich ); |
| |
| ScTabViewShell* pShell = aViewData.GetViewShell(); |
| pShell->WindowChanged(); |
| |
| pSelEngine->SetWindow(pGridWin[eWhich]); |
| pSelEngine->SetWhich(eWhich); |
| pSelEngine->SetVisibleArea( Rectangle(Point(), pGridWin[eWhich]->GetOutputSizePixel()) ); |
| |
| pGridWin[eOld]->MoveMouseStatus(*pGridWin[eWhich]); |
| |
| if ( bCapture || pGridWin[eWhich]->IsMouseCaptured() ) |
| { |
| // Tracking statt CaptureMouse, damit sauber abgebrochen werden kann |
| // (SelectionEngine ruft CaptureMouse beim SetWindow) |
| //! Irgendwann sollte die SelectionEngine selber StartTracking rufen!?! |
| pGridWin[eWhich]->ReleaseMouse(); |
| pGridWin[eWhich]->StartTracking(); |
| } |
| |
| if ( bTopCap && pColBar[eNewH] ) |
| { |
| pColBar[eOldH]->SetIgnoreMove(sal_True); |
| pColBar[eNewH]->SetIgnoreMove(sal_False); |
| pHdrSelEng->SetWindow( pColBar[eNewH] ); |
| long nWidth = pColBar[eNewH]->GetOutputSizePixel().Width(); |
| pHdrSelEng->SetVisibleArea( Rectangle( 0, LONG_MIN, nWidth-1, LONG_MAX ) ); |
| pColBar[eNewH]->CaptureMouse(); |
| } |
| if ( bLeftCap && pRowBar[eNewV] ) |
| { |
| pRowBar[eOldV]->SetIgnoreMove(sal_True); |
| pRowBar[eNewV]->SetIgnoreMove(sal_False); |
| pHdrSelEng->SetWindow( pRowBar[eNewV] ); |
| long nHeight = pRowBar[eNewV]->GetOutputSizePixel().Height(); |
| pHdrSelEng->SetVisibleArea( Rectangle( LONG_MIN, 0, LONG_MAX, nHeight-1 ) ); |
| pRowBar[eNewV]->CaptureMouse(); |
| } |
| aHdrFunc.SetWhich(eWhich); |
| |
| pGridWin[eOld]->ShowCursor(); |
| pGridWin[eWhich]->ShowCursor(); |
| |
| SfxInPlaceClient* pClient = aViewData.GetViewShell()->GetIPClient(); |
| sal_Bool bOleActive = ( pClient && pClient->IsObjectInPlaceActive() ); |
| |
| // #103823# don't switch ViewShell's active window during RefInput, because the focus |
| // might change, and subsequent SetReference calls wouldn't find the right EditView |
| if ( !bRefMode && !bOleActive ) |
| aViewData.GetViewShell()->SetWindow( pGridWin[eWhich] ); |
| |
| if ( bFocus && !aViewData.IsAnyFillMode() && !bRefMode ) |
| { |
| // GrabFocus nur, wenn vorher das andere GridWindow den Focus hatte |
| // (z.B. wegen Suchen & Ersetzen) |
| //! aViewData.GetViewShell()->GetViewFrame()->GetWindow().GrabFocus(); |
| pGridWin[eWhich]->GrabFocus(); |
| } |
| |
| bInActivatePart = sal_False; |
| } |
| } |
| |
| void ScTabView::HideListBox() |
| { |
| for (sal_uInt16 i=0; i<4; i++) |
| if (pGridWin[i]) |
| pGridWin[i]->ClickExtern(); |
| } |
| |
| void ScTabView::UpdateInputContext() |
| { |
| ScGridWindow* pWin = pGridWin[aViewData.GetActivePart()]; |
| if (pWin) |
| pWin->UpdateInputContext(); |
| } |
| |
| // GetGridWidth - Breite eines Ausgabebereichs (fuer ViewData) |
| |
| long ScTabView::GetGridWidth( ScHSplitPos eWhich ) |
| { |
| ScSplitPos eGridWhich = ( eWhich == SC_SPLIT_LEFT ) ? SC_SPLIT_BOTTOMLEFT : SC_SPLIT_BOTTOMRIGHT; |
| if (pGridWin[eGridWhich]) |
| return pGridWin[eGridWhich]->GetSizePixel().Width(); |
| else |
| return 0; |
| } |
| |
| // GetGridHeight - Hoehe eines Ausgabebereichs (fuer ViewData) |
| |
| long ScTabView::GetGridHeight( ScVSplitPos eWhich ) |
| { |
| ScSplitPos eGridWhich = ( eWhich == SC_SPLIT_TOP ) ? SC_SPLIT_TOPLEFT : SC_SPLIT_BOTTOMLEFT; |
| if (pGridWin[eGridWhich]) |
| return pGridWin[eGridWhich]->GetSizePixel().Height(); |
| else |
| return 0; |
| } |
| |
| void ScTabView::UpdateInputLine() |
| { |
| SC_MOD()->InputEnterHandler(); |
| } |
| |
| void ScTabView::ZoomChanged() |
| { |
| ScInputHandler* pHdl = SC_MOD()->GetInputHdl(aViewData.GetViewShell()); |
| if (pHdl) |
| pHdl->SetRefScale( aViewData.GetZoomX(), aViewData.GetZoomY() ); |
| |
| UpdateFixPos(); |
| |
| UpdateScrollBars(); |
| |
| // VisArea... |
| // AW: Discussed with NN if there is a reason that new map mode was only set for one window, |
| // but is not. Setting only on one window causes the first repaint to have the old mapMode |
| // in three of four views, so the overlay will save the wrong content e.g. when zooming out. |
| // Changing to setting map mode at all windows. |
| sal_uInt32 a; |
| |
| for(a = 0L; a < 4L; a++) |
| { |
| if(pGridWin[a]) |
| { |
| pGridWin[a]->SetMapMode(pGridWin[a]->GetDrawMapMode()); |
| } |
| } |
| |
| SetNewVisArea(); |
| |
| /* the old code |
| ScGridWindow* pWin = pGridWin[aViewData.GetActivePart()]; |
| if (pWin) |
| { |
| pWin->SetMapMode( pWin->GetDrawMapMode() ); // mit neuem Zoom |
| SetNewVisArea(); // benutzt den gesetzten MapMode |
| } */ |
| |
| InterpretVisible(); // #69343# have everything calculated before painting |
| |
| SfxBindings& rBindings = aViewData.GetBindings(); |
| rBindings.Invalidate( SID_ATTR_ZOOM ); |
| rBindings.Invalidate( SID_ATTR_ZOOMSLIDER ); |
| |
| HideNoteMarker(); |
| |
| // AW: To not change too much, use pWin here |
| ScGridWindow* pWin = pGridWin[aViewData.GetActivePart()]; |
| |
| if ( pWin && aViewData.HasEditView( aViewData.GetActivePart() ) ) |
| { |
| // flush OverlayManager before changing the MapMode |
| pWin->flushOverlayManager(); |
| |
| // #93650# make sure the EditView's position and size are updated |
| // with the right (logic, not drawing) MapMode |
| pWin->SetMapMode( aViewData.GetLogicMode() ); |
| UpdateEditView(); |
| } |
| } |
| |
| void ScTabView::CheckNeedsRepaint() |
| { |
| sal_uInt16 i; |
| for (i=0; i<4; i++) |
| if ( pGridWin[i] && pGridWin[i]->IsVisible() ) |
| pGridWin[i]->CheckNeedsRepaint(); |
| } |
| |
| |
| |
| |
| |