1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 // MARKER(update_precomp.py): autogen include statement, do not remove 23 #include "precompiled_sc.hxx" 24 25 #include "scitems.hxx" 26 27 #include <memory> //auto_ptr 28 #include <editeng/adjitem.hxx> 29 #include <svx/algitem.hxx> 30 #include <svx/dbexch.hrc> 31 #include <editeng/editview.hxx> 32 #include <editeng/editstat.hxx> 33 #include <editeng/flditem.hxx> 34 #include <svx/svdetc.hxx> 35 #include <editeng/editobj.hxx> 36 #include <sfx2/dispatch.hxx> 37 #include <sfx2/viewfrm.hxx> 38 #include <sfx2/docfile.hxx> 39 #include <svl/stritem.hxx> 40 #include <svtools/svlbox.hxx> 41 #include <svtools/svtabbx.hxx> 42 #include <svl/urlbmk.hxx> 43 #include <tools/urlobj.hxx> 44 #include <vcl/cursor.hxx> 45 #include <vcl/sound.hxx> 46 #include <vcl/graph.hxx> 47 #include <vcl/hatch.hxx> 48 #include <sot/formats.hxx> 49 #include <sot/clsids.hxx> 50 51 #include <svx/svdview.hxx> // for Command-Handler (COMMAND_INSERTTEXT) 52 #include <editeng/outliner.hxx> // for Command-Handler (COMMAND_INSERTTEXT) 53 #include <svx/svditer.hxx> 54 #include <svx/svdocapt.hxx> 55 #include <svx/svdpagv.hxx> 56 57 #include <com/sun/star/sheet/DataPilotFieldFilter.hpp> 58 #include <com/sun/star/sheet/DataPilotFieldOrientation.hpp> 59 #include <com/sun/star/sheet/DataPilotTableHeaderData.hpp> 60 #include <com/sun/star/sheet/DataPilotTableResultData.hpp> 61 #include <com/sun/star/sheet/DataPilotTablePositionData.hpp> 62 #include <com/sun/star/sheet/DataPilotTablePositionType.hpp> 63 #include <com/sun/star/sheet/MemberResultFlags.hpp> 64 #include <com/sun/star/awt/KeyModifier.hpp> 65 #include <com/sun/star/awt/MouseButton.hpp> 66 #include <com/sun/star/script/vba/VBAEventId.hpp> 67 #include <com/sun/star/script/vba/XVBAEventProcessor.hpp> 68 69 #include "gridwin.hxx" 70 #include "tabvwsh.hxx" 71 #include "docsh.hxx" 72 #include "viewdata.hxx" 73 #include "tabview.hxx" 74 #include "select.hxx" 75 #include "scmod.hxx" 76 #include "document.hxx" 77 #include "attrib.hxx" 78 #include "dbcolect.hxx" 79 #include "stlpool.hxx" 80 #include "printfun.hxx" 81 #include "cbutton.hxx" 82 #include "sc.hrc" 83 #include "globstr.hrc" 84 #include "editutil.hxx" 85 #include "scresid.hxx" 86 #include "inputhdl.hxx" 87 #include "uiitems.hxx" // Filter-Dialog - auslagern !!! 88 #include "filtdlg.hxx" 89 #include "impex.hxx" // Sylk-ID for CB 90 #include "cell.hxx" // für Edit-Felder 91 #include "patattr.hxx" 92 #include "notemark.hxx" 93 #include "rfindlst.hxx" 94 #include "docpool.hxx" 95 #include "output.hxx" 96 #include "docfunc.hxx" 97 #include "dbdocfun.hxx" 98 #include "dpobject.hxx" 99 #include "dpoutput.hxx" 100 #include "transobj.hxx" 101 #include "drwtrans.hxx" 102 #include "seltrans.hxx" 103 #include "sizedev.hxx" 104 #include "AccessibilityHints.hxx" 105 #include "dpsave.hxx" 106 #include "viewuno.hxx" 107 #include "compiler.hxx" 108 #include "editable.hxx" 109 #include "fillinfo.hxx" 110 #include "scitems.hxx" 111 #include "userdat.hxx" 112 #include "drwlayer.hxx" 113 #include "attrib.hxx" 114 #include "validat.hxx" 115 #include "tabprotection.hxx" 116 #include "postit.hxx" 117 #include "dpcontrol.hxx" 118 #include "cellsuno.hxx" 119 120 #include "drawview.hxx" 121 #include <svx/sdrpagewindow.hxx> 122 #include <svx/sdr/overlay/overlaymanager.hxx> 123 #include <vcl/svapp.hxx> 124 #include <svx/sdr/overlay/overlayselection.hxx> 125 126 using namespace com::sun::star; 127 using ::com::sun::star::uno::Sequence; 128 using ::com::sun::star::uno::Any; 129 130 const sal_uInt8 SC_NESTEDBUTTON_NONE = 0; 131 const sal_uInt8 SC_NESTEDBUTTON_DOWN = 1; 132 const sal_uInt8 SC_NESTEDBUTTON_UP = 2; 133 134 #define SC_AUTOFILTER_ALL 0 135 #define SC_AUTOFILTER_TOP10 1 136 #define SC_AUTOFILTER_CUSTOM 2 137 #define SC_AUTOFILTER_EMPTY 3 138 #define SC_AUTOFILTER_NOTEMPTY 4 139 140 // Modi für die FilterListBox 141 enum ScFilterBoxMode 142 { 143 SC_FILTERBOX_FILTER, 144 SC_FILTERBOX_DATASELECT, 145 SC_FILTERBOX_SCENARIO, 146 SC_FILTERBOX_PAGEFIELD 147 }; 148 149 extern SfxViewShell* pScActiveViewShell; // global.cxx 150 extern sal_uInt16 nScClickMouseModifier; // global.cxx 151 extern sal_uInt16 nScFillModeMouseModifier; // global.cxx 152 153 #define SC_FILTERLISTBOX_LINES 12 154 155 // ============================================================================ 156 157 ScGridWindow::VisibleRange::VisibleRange() : 158 mnCol1(0), mnCol2(MAXCOL), mnRow1(0), mnRow2(MAXROW) 159 { 160 } 161 162 bool ScGridWindow::VisibleRange::isInside(SCCOL nCol, SCROW nRow) const 163 { 164 return mnCol1 <= nCol && nCol <= mnCol2 && mnRow1 <= nRow && nRow <= mnRow2; 165 } 166 167 // ============================================================================ 168 169 class ScFilterListBox : public ListBox 170 { 171 private: 172 ScGridWindow* pGridWin; 173 SCCOL nCol; 174 SCROW nRow; 175 sal_Bool bButtonDown; 176 sal_Bool bInit; 177 sal_Bool bCancelled; 178 sal_Bool bInSelect; 179 bool mbListHasDates; 180 sal_uLong nSel; 181 ScFilterBoxMode eMode; 182 183 protected: 184 virtual void LoseFocus(); 185 void SelectHdl(); 186 187 public: 188 ScFilterListBox( Window* pParent, ScGridWindow* pGrid, 189 SCCOL nNewCol, SCROW nNewRow, ScFilterBoxMode eNewMode ); 190 ~ScFilterListBox(); 191 192 virtual long PreNotify( NotifyEvent& rNEvt ); 193 virtual void Select(); 194 195 SCCOL GetCol() const { return nCol; } 196 SCROW GetRow() const { return nRow; } 197 ScFilterBoxMode GetMode() const { return eMode; } 198 sal_Bool IsDataSelect() const { return (eMode == SC_FILTERBOX_DATASELECT); } 199 void EndInit(); 200 sal_Bool IsInInit() const { return bInit; } 201 void SetCancelled() { bCancelled = sal_True; } 202 sal_Bool IsInSelect() const { return bInSelect; } 203 void SetListHasDates(bool b) { mbListHasDates = b; } 204 bool HasDates() const { return mbListHasDates; } 205 }; 206 207 //------------------------------------------------------------------- 208 209 // ListBox in einem FloatingWindow (pParent) 210 ScFilterListBox::ScFilterListBox( Window* pParent, ScGridWindow* pGrid, 211 SCCOL nNewCol, SCROW nNewRow, ScFilterBoxMode eNewMode ) : 212 ListBox( pParent, WB_AUTOHSCROLL ), 213 pGridWin( pGrid ), 214 nCol( nNewCol ), 215 nRow( nNewRow ), 216 bButtonDown( sal_False ), 217 bInit( sal_True ), 218 bCancelled( sal_False ), 219 bInSelect( sal_False ), 220 mbListHasDates(false), 221 nSel( 0 ), 222 eMode( eNewMode ) 223 { 224 } 225 226 __EXPORT ScFilterListBox::~ScFilterListBox() 227 { 228 if (IsMouseCaptured()) 229 ReleaseMouse(); 230 } 231 232 void ScFilterListBox::EndInit() 233 { 234 sal_uInt16 nPos = GetSelectEntryPos(); 235 if ( LISTBOX_ENTRY_NOTFOUND == nPos ) 236 nSel = 0; 237 else 238 nSel = nPos; 239 240 bInit = sal_False; 241 } 242 243 void __EXPORT ScFilterListBox::LoseFocus() 244 { 245 #ifndef UNX 246 Hide(); 247 #endif 248 } 249 250 // ----------------------------------------------------------------------- 251 252 long ScFilterListBox::PreNotify( NotifyEvent& rNEvt ) 253 { 254 long nDone = 0; 255 if ( rNEvt.GetType() == EVENT_KEYINPUT ) 256 { 257 KeyEvent aKeyEvt = *rNEvt.GetKeyEvent(); 258 KeyCode aCode = aKeyEvt.GetKeyCode(); 259 if ( !aCode.GetModifier() ) // ohne alle Modifiers 260 { 261 sal_uInt16 nKey = aCode.GetCode(); 262 if ( nKey == KEY_RETURN ) 263 { 264 SelectHdl(); // auswählen 265 nDone = 1; 266 } 267 else if ( nKey == KEY_ESCAPE ) 268 { 269 pGridWin->ClickExtern(); // löscht die List-Box !!! 270 nDone = 1; 271 } 272 } 273 } 274 275 return nDone ? nDone : ListBox::PreNotify( rNEvt ); 276 } 277 278 void __EXPORT ScFilterListBox::Select() 279 { 280 ListBox::Select(); 281 SelectHdl(); 282 } 283 284 void __EXPORT ScFilterListBox::SelectHdl() 285 { 286 if ( !IsTravelSelect() && !bInit && !bCancelled ) 287 { 288 sal_uInt16 nPos = GetSelectEntryPos(); 289 if ( LISTBOX_ENTRY_NOTFOUND != nPos ) 290 { 291 nSel = nPos; 292 if (!bButtonDown) 293 { 294 // #i81298# set bInSelect flag, so the box isn't deleted from modifications within FilterSelect 295 bInSelect = sal_True; 296 pGridWin->FilterSelect( nSel ); 297 bInSelect = sal_False; 298 } 299 } 300 } 301 } 302 303 // ============================================================================ 304 305 // use a System floating window for the above filter listbox 306 class ScFilterFloatingWindow : public FloatingWindow 307 { 308 public: 309 ScFilterFloatingWindow( Window* pParent, WinBits nStyle = WB_STDFLOATWIN ); 310 virtual ~ScFilterFloatingWindow(); 311 // required for System FloatingWindows that will not process KeyInput by themselves 312 virtual Window* GetPreferredKeyInputWindow(); 313 }; 314 315 ScFilterFloatingWindow::ScFilterFloatingWindow( Window* pParent, WinBits nStyle ) : 316 FloatingWindow( pParent, nStyle|WB_SYSTEMWINDOW ) // make it a system floater 317 {} 318 319 ScFilterFloatingWindow::~ScFilterFloatingWindow() 320 { 321 EndPopupMode(); 322 } 323 324 Window* ScFilterFloatingWindow::GetPreferredKeyInputWindow() 325 { 326 // redirect keyinput in the child window 327 return GetWindow(WINDOW_FIRSTCHILD) ? GetWindow(WINDOW_FIRSTCHILD)->GetPreferredKeyInputWindow() : NULL; // will be the FilterBox 328 } 329 330 // ============================================================================ 331 332 sal_Bool lcl_IsEditableMatrix( ScDocument* pDoc, const ScRange& rRange ) 333 { 334 // Wenn es ein editierbarer Bereich ist, und rechts unten eine Matrix-Zelle 335 // mit Origin links oben liegt, enthält der Bereich genau die Matrix. 336 //! Direkt die MatrixEdges Funktionen von der Column herausreichen ??? 337 338 if ( !pDoc->IsBlockEditable( rRange.aStart.Tab(), rRange.aStart.Col(),rRange.aStart.Row(), 339 rRange.aEnd.Col(),rRange.aEnd.Row() ) ) 340 return sal_False; 341 342 ScAddress aPos; 343 const ScBaseCell* pCell = pDoc->GetCell( rRange.aEnd ); 344 return ( pCell && pCell->GetCellType() == CELLTYPE_FORMULA && 345 ((ScFormulaCell*)pCell)->GetMatrixOrigin(aPos) && aPos == rRange.aStart ); 346 347 } 348 349 void lcl_UnLockComment( ScDrawView* pView, SdrPageView* pPV, SdrModel* pDrDoc, const Point& rPos, ScViewData* pViewData ) 350 { 351 if (!pView && !pPV && !pDrDoc && !pViewData) 352 return; 353 354 ScDocument& rDoc = *pViewData->GetDocument(); 355 ScAddress aCellPos( pViewData->GetCurX(), pViewData->GetCurY(), pViewData->GetTabNo() ); 356 ScPostIt* pNote = rDoc.GetNote( aCellPos ); 357 SdrObject* pObj = pNote ? pNote->GetCaption() : 0; 358 if( pObj && pObj->GetLogicRect().IsInside( rPos ) && ScDrawLayer::IsNoteCaption( pObj ) ) 359 { 360 const ScProtectionAttr* pProtAttr = static_cast< const ScProtectionAttr* > (rDoc.GetAttr( aCellPos.Col(), aCellPos.Row(), aCellPos.Tab(), ATTR_PROTECTION ) ); 361 bool bProtectAttr = pProtAttr->GetProtection() || pProtAttr->GetHideCell() ; 362 bool bProtectDoc = rDoc.IsTabProtected( aCellPos.Tab() ) || pViewData->GetSfxDocShell()->IsReadOnly() ; 363 // unlock internal layer (if not protected), will be relocked in ScDrawView::MarkListHasChanged() 364 pView->LockInternalLayer( bProtectDoc && bProtectAttr ); 365 } 366 } 367 368 sal_Bool lcl_GetHyperlinkCell(ScDocument* pDoc, SCCOL& rPosX, SCROW& rPosY, SCTAB nTab, ScBaseCell*& rpCell ) 369 { 370 sal_Bool bFound = sal_False; 371 do 372 { 373 pDoc->GetCell( rPosX, rPosY, nTab, rpCell ); 374 if ( !rpCell || rpCell->GetCellType() == CELLTYPE_NOTE ) 375 { 376 if ( rPosX <= 0 ) 377 return sal_False; // alles leer bis links 378 else 379 --rPosX; // weitersuchen 380 } 381 else if ( rpCell->GetCellType() == CELLTYPE_EDIT) 382 bFound = sal_True; 383 else if (rpCell->GetCellType() == CELLTYPE_FORMULA && 384 static_cast<ScFormulaCell*>(rpCell)->IsHyperLinkCell()) 385 bFound = sal_True; 386 else 387 return sal_False; // andere Zelle 388 } 389 while ( !bFound ); 390 391 return bFound; 392 } 393 394 // --------------------------------------------------------------------------- 395 // WB_DIALOGCONTROL nötig für UNO-Controls 396 ScGridWindow::ScGridWindow( Window* pParent, ScViewData* pData, ScSplitPos eWhichPos ) 397 : Window( pParent, WB_CLIPCHILDREN | WB_DIALOGCONTROL ), 398 DropTargetHelper( this ), 399 DragSourceHelper( this ), 400 mpOOCursors( NULL ), 401 mpOOSelection( NULL ), 402 mpOOAutoFill( NULL ), 403 mpOODragRect( NULL ), 404 mpOOHeader( NULL ), 405 mpOOShrink( NULL ), 406 mpAutoFillRect(static_cast<Rectangle*>(NULL)), 407 pViewData( pData ), 408 eWhich( eWhichPos ), 409 pNoteMarker( NULL ), 410 pFilterBox( NULL ), 411 pFilterFloat( NULL ), 412 mpDPFieldPopup(NULL), 413 mpFilterButton(NULL), 414 nCursorHideCount( 0 ), 415 bMarking( sal_False ), 416 nButtonDown( 0 ), 417 bEEMouse( sal_False ), 418 nMouseStatus( SC_GM_NONE ), 419 nNestedButtonState( SC_NESTEDBUTTON_NONE ), 420 bDPMouse( sal_False ), 421 bRFMouse( sal_False ), 422 nPagebreakMouse( SC_PD_NONE ), 423 bPagebreakDrawn( sal_False ), 424 nPageScript( 0 ), 425 bDragRect( sal_False ), 426 meDragInsertMode( INS_NONE ), 427 nCurrentPointer( 0 ), 428 bIsInScroll( sal_False ), 429 bIsInPaint( sal_False ), 430 aComboButton( this ), 431 aCurMousePos( 0,0 ), 432 nPaintCount( 0 ), 433 bNeedsRepaint( sal_False ), 434 bAutoMarkVisible( sal_False ), 435 bListValButton( sal_False ) 436 { 437 switch(eWhich) 438 { 439 case SC_SPLIT_TOPLEFT: 440 eHWhich = SC_SPLIT_LEFT; 441 eVWhich = SC_SPLIT_TOP; 442 break; 443 case SC_SPLIT_TOPRIGHT: 444 eHWhich = SC_SPLIT_RIGHT; 445 eVWhich = SC_SPLIT_TOP; 446 break; 447 case SC_SPLIT_BOTTOMLEFT: 448 eHWhich = SC_SPLIT_LEFT; 449 eVWhich = SC_SPLIT_BOTTOM; 450 break; 451 case SC_SPLIT_BOTTOMRIGHT: 452 eHWhich = SC_SPLIT_RIGHT; 453 eVWhich = SC_SPLIT_BOTTOM; 454 break; 455 default: 456 DBG_ERROR("GridWindow: wrong position"); 457 } 458 459 SetBackground(); 460 461 SetMapMode(pViewData->GetLogicMode(eWhich)); 462 // EnableDrop(); 463 EnableChildTransparentMode(); 464 SetDialogControlFlags( WINDOW_DLGCTRL_RETURN | WINDOW_DLGCTRL_WANTFOCUS ); 465 466 SetHelpId( HID_SC_WIN_GRIDWIN ); 467 SetUniqueId( HID_SC_WIN_GRIDWIN ); 468 469 SetDigitLanguage( SC_MOD()->GetOptDigitLanguage() ); 470 EnableRTL( sal_False ); 471 } 472 473 __EXPORT ScGridWindow::~ScGridWindow() 474 { 475 // #114409# 476 ImpDestroyOverlayObjects(); 477 478 delete pFilterBox; 479 delete pFilterFloat; 480 delete pNoteMarker; 481 } 482 483 void __EXPORT ScGridWindow::Resize( const Size& ) 484 { 485 // gar nix 486 } 487 488 void ScGridWindow::ClickExtern() 489 { 490 do 491 { 492 // #i81298# don't delete the filter box when called from its select handler 493 // (possible through row header size update) 494 // #i84277# when initializing the filter box, a Basic error can deactivate the view 495 if ( pFilterBox && ( pFilterBox->IsInSelect() || pFilterBox->IsInInit() ) ) 496 { 497 break; 498 } 499 500 DELETEZ(pFilterBox); 501 DELETEZ(pFilterFloat); 502 } 503 while (false); 504 505 if (mpDPFieldPopup.get()) 506 { 507 mpDPFieldPopup->close(false); 508 mpDPFieldPopup.reset(); 509 } 510 } 511 512 IMPL_LINK( ScGridWindow, PopupModeEndHdl, FloatingWindow*, EMPTYARG ) 513 { 514 if (pFilterBox) 515 pFilterBox->SetCancelled(); // nicht mehr auswählen 516 GrabFocus(); 517 return 0; 518 } 519 520 IMPL_LINK( ScGridWindow, PopupSpellingHdl, SpellCallbackInfo*, pInfo ) 521 { 522 if( pInfo->nCommand == SPELLCMD_STARTSPELLDLG ) 523 pViewData->GetDispatcher().Execute( SID_SPELL_DIALOG, SFX_CALLMODE_ASYNCHRON ); 524 return 0; 525 } 526 527 void ScGridWindow::ExecPageFieldSelect( SCCOL nCol, SCROW nRow, sal_Bool bHasSelection, const String& rStr ) 528 { 529 //! gridwin2 ? 530 531 ScDocument* pDoc = pViewData->GetDocument(); 532 SCTAB nTab = pViewData->GetTabNo(); 533 ScDPObject* pDPObj = pDoc->GetDPAtCursor(nCol, nRow, nTab); 534 if ( pDPObj && nCol > 0 ) 535 { 536 // look for the dimension header left of the drop-down arrow 537 sal_uInt16 nOrient = sheet::DataPilotFieldOrientation_HIDDEN; 538 long nField = pDPObj->GetHeaderDim( ScAddress( nCol-1, nRow, nTab ), nOrient ); 539 if ( nField >= 0 && nOrient == sheet::DataPilotFieldOrientation_PAGE ) 540 { 541 ScDPSaveData aSaveData( *pDPObj->GetSaveData() ); 542 543 sal_Bool bIsDataLayout; 544 String aDimName = pDPObj->GetDimName( nField, bIsDataLayout ); 545 if ( !bIsDataLayout ) 546 { 547 ScDPSaveDimension* pDim = aSaveData.GetDimensionByName(aDimName); 548 549 if ( bHasSelection ) 550 pDim->SetCurrentPage( &rStr ); 551 else 552 pDim->SetCurrentPage( NULL ); 553 554 ScDPObject aNewObj( *pDPObj ); 555 aNewObj.SetSaveData( aSaveData ); 556 ScDBDocFunc aFunc( *pViewData->GetDocShell() ); 557 aFunc.DataPilotUpdate( pDPObj, &aNewObj, sal_True, sal_False ); 558 pViewData->GetView()->CursorPosChanged(); // shells may be switched 559 } 560 } 561 } 562 } 563 564 void ScGridWindow::LaunchPageFieldMenu( SCCOL nCol, SCROW nRow ) 565 { 566 //! merge position/size handling with DoAutoFilterMenue 567 568 delete pFilterBox; 569 delete pFilterFloat; 570 571 sal_uInt16 i; 572 ScDocument* pDoc = pViewData->GetDocument(); 573 SCTAB nTab = pViewData->GetTabNo(); 574 sal_Bool bLayoutRTL = pDoc->IsLayoutRTL( nTab ); 575 576 long nSizeX = 0; 577 long nSizeY = 0; 578 long nHeight = 0; 579 pViewData->GetMergeSizePixel( nCol, nRow, nSizeX, nSizeY ); 580 Point aPos = pViewData->GetScrPos( nCol, nRow, eWhich ); 581 if ( bLayoutRTL ) 582 aPos.X() -= nSizeX; 583 584 Rectangle aCellRect( OutputToScreenPixel(aPos), Size(nSizeX,nSizeY) ); 585 586 aPos.X() -= 1; 587 aPos.Y() += nSizeY - 1; 588 589 pFilterFloat = new ScFilterFloatingWindow( this, WinBits(WB_BORDER) ); // not resizable etc. 590 pFilterFloat->SetPopupModeEndHdl( LINK( this, ScGridWindow, PopupModeEndHdl ) ); 591 pFilterBox = new ScFilterListBox( pFilterFloat, this, nCol, nRow, SC_FILTERBOX_PAGEFIELD ); 592 if ( bLayoutRTL ) 593 pFilterBox->EnableMirroring(); 594 595 nSizeX += 1; 596 597 { 598 Font aOldFont = GetFont(); SetFont( pFilterBox->GetFont() ); 599 MapMode aOldMode = GetMapMode(); SetMapMode( MAP_PIXEL ); 600 601 nHeight = GetTextHeight(); 602 nHeight *= SC_FILTERLISTBOX_LINES; 603 604 SetMapMode( aOldMode ); 605 SetFont( aOldFont ); 606 } 607 608 // SetSize comes later 609 610 TypedScStrCollection aStrings( 128, 128 ); 611 612 // get list box entries and selection 613 sal_Bool bHasCurrentPage = sal_False; 614 String aCurrentPage; 615 ScDPObject* pDPObj = pDoc->GetDPAtCursor(nCol, nRow, nTab); 616 if ( pDPObj && nCol > 0 ) 617 { 618 // look for the dimension header left of the drop-down arrow 619 sal_uInt16 nOrient = sheet::DataPilotFieldOrientation_HIDDEN; 620 long nField = pDPObj->GetHeaderDim( ScAddress( nCol-1, nRow, nTab ), nOrient ); 621 if ( nField >= 0 && nOrient == sheet::DataPilotFieldOrientation_PAGE ) 622 { 623 pDPObj->FillPageList( aStrings, nField ); 624 625 // get current page from SaveData 626 627 ScDPSaveData* pSaveData = pDPObj->GetSaveData(); 628 sal_Bool bIsDataLayout; 629 String aDimName = pDPObj->GetDimName( nField, bIsDataLayout ); 630 if ( pSaveData && !bIsDataLayout ) 631 { 632 ScDPSaveDimension* pDim = pSaveData->GetExistingDimensionByName(aDimName); 633 if ( pDim && pDim->HasCurrentPage() ) 634 { 635 aCurrentPage = pDim->GetCurrentPage(); 636 bHasCurrentPage = sal_True; 637 } 638 } 639 } 640 } 641 642 // include all entry widths for the size of the drop-down 643 long nMaxText = 0; 644 sal_uInt16 nCount = aStrings.GetCount(); 645 for (i=0; i<nCount; i++) 646 { 647 TypedStrData* pData = aStrings[i]; 648 long nTextWidth = pFilterBox->GetTextWidth( pData->GetString() ); 649 if ( nTextWidth > nMaxText ) 650 nMaxText = nTextWidth; 651 } 652 653 // add scrollbar width if needed (string entries are counted here) 654 // (scrollbar is shown if the box is exactly full?) 655 if ( nCount >= SC_FILTERLISTBOX_LINES ) 656 nMaxText += GetSettings().GetStyleSettings().GetScrollBarSize(); 657 658 nMaxText += 4; // for borders 659 660 if ( nMaxText > nSizeX ) 661 nSizeX = nMaxText; // just modify width - starting position is unchanged 662 663 // adjust position and size to window 664 665 Size aParentSize = GetParent()->GetOutputSizePixel(); 666 Size aSize( nSizeX, nHeight ); 667 668 if ( aSize.Height() > aParentSize.Height() ) 669 aSize.Height() = aParentSize.Height(); 670 if ( aPos.Y() + aSize.Height() > aParentSize.Height() ) 671 aPos.Y() = aParentSize.Height() - aSize.Height(); 672 673 pFilterBox->SetSizePixel( aSize ); 674 pFilterBox->Show(); // Show must be called before SetUpdateMode 675 pFilterBox->SetUpdateMode(sal_False); 676 677 pFilterFloat->SetOutputSizePixel( aSize ); 678 pFilterFloat->StartPopupMode( aCellRect, FLOATWIN_POPUPMODE_DOWN|FLOATWIN_POPUPMODE_GRABFOCUS); 679 680 // fill the list box 681 sal_Bool bWait = ( nCount > 100 ); 682 683 if (bWait) 684 EnterWait(); 685 686 for (i=0; i<nCount; i++) 687 pFilterBox->InsertEntry( aStrings[i]->GetString() ); 688 689 pFilterBox->SetSeparatorPos( 0 ); 690 691 if (bWait) 692 LeaveWait(); 693 694 pFilterBox->SetUpdateMode(sal_True); 695 696 sal_uInt16 nSelPos = LISTBOX_ENTRY_NOTFOUND; 697 if (bHasCurrentPage) 698 nSelPos = pFilterBox->GetEntryPos( aCurrentPage ); 699 700 if ( nSelPos == LISTBOX_ENTRY_NOTFOUND ) 701 nSelPos = 0; // first entry 702 703 pFilterBox->GrabFocus(); 704 705 // call Select after GrabFocus, so the focus rectangle ends up in the right position 706 if ( nSelPos != LISTBOX_ENTRY_NOTFOUND ) 707 pFilterBox->SelectEntryPos( nSelPos ); 708 709 pFilterBox->EndInit(); 710 711 nMouseStatus = SC_GM_FILTER; 712 CaptureMouse(); 713 } 714 715 void ScGridWindow::LaunchDPFieldMenu( SCCOL nCol, SCROW nRow ) 716 { 717 SCTAB nTab = pViewData->GetTabNo(); 718 ScDPObject* pDPObj = pViewData->GetDocument()->GetDPAtCursor(nCol, nRow, nTab); 719 if (!pDPObj) 720 return; 721 722 // Get the geometry of the cell. 723 Point aScrPos = pViewData->GetScrPos(nCol, nRow, eWhich); 724 long nSizeX, nSizeY; 725 pViewData->GetMergeSizePixel(nCol, nRow, nSizeX, nSizeY); 726 Size aScrSize(nSizeX-1, nSizeY-1); 727 728 DPLaunchFieldPopupMenu(OutputToScreenPixel(aScrPos), aScrSize, ScAddress(nCol, nRow, nTab), pDPObj); 729 } 730 731 void ScGridWindow::DoScenarioMenue( const ScRange& rScenRange ) 732 { 733 delete pFilterBox; 734 delete pFilterFloat; 735 736 SCCOL nCol = rScenRange.aEnd.Col(); // Zelle unterhalb des Buttons 737 SCROW nRow = rScenRange.aStart.Row(); 738 if (nRow == 0) 739 { 740 nRow = rScenRange.aEnd.Row() + 1; // Bereich ganz oben -> Button unterhalb 741 if (nRow>MAXROW) nRow = MAXROW; 742 //! Texthöhe addieren (wenn sie an der View gespeichert ist...) 743 } 744 745 ScDocument* pDoc = pViewData->GetDocument(); 746 SCTAB nTab = pViewData->GetTabNo(); 747 sal_Bool bLayoutRTL = pDoc->IsLayoutRTL( nTab ); 748 749 long nSizeX = 0; 750 long nSizeY = 0; 751 long nHeight = 0; 752 pViewData->GetMergeSizePixel( nCol, nRow, nSizeX, nSizeY ); 753 Point aPos = pViewData->GetScrPos( nCol, nRow, eWhich ); 754 if ( bLayoutRTL ) 755 aPos.X() -= nSizeX; 756 Rectangle aCellRect( OutputToScreenPixel(aPos), Size(nSizeX,nSizeY) ); 757 aCellRect.Top() -= nSizeY; 758 aCellRect.Bottom() -= nSizeY - 1; 759 // Die ListBox direkt unter der schwarzen Linie auf dem Zellgitter 760 // (wenn die Linie verdeckt wird, sieht es komisch aus...) 761 762 pFilterFloat = new ScFilterFloatingWindow( this, WinBits(WB_BORDER) ); // nicht resizable etc. 763 pFilterFloat->SetPopupModeEndHdl( LINK( this, ScGridWindow, PopupModeEndHdl ) ); 764 pFilterBox = new ScFilterListBox( pFilterFloat, this, nCol, nRow, SC_FILTERBOX_SCENARIO ); 765 if ( bLayoutRTL ) 766 pFilterBox->EnableMirroring(); 767 768 nSizeX += 1; 769 770 { 771 Font aOldFont = GetFont(); SetFont( pFilterBox->GetFont() ); 772 MapMode aOldMode = GetMapMode(); SetMapMode( MAP_PIXEL ); 773 774 nHeight = GetTextHeight(); 775 nHeight *= SC_FILTERLISTBOX_LINES; 776 777 SetMapMode( aOldMode ); 778 SetFont( aOldFont ); 779 } 780 781 // SetSize später 782 /* 783 pFilterBox->SetSelectionMode( SINGLE_SELECTION ); 784 pFilterBox->SetTabs( nFilterBoxTabs, MapUnit( MAP_APPFONT )); 785 pFilterBox->SetTabJustify( 1, bLayoutRTL ? AdjustRight : AdjustLeft ); 786 */ 787 788 // ParentSize Abfrage fehlt 789 Size aSize( nSizeX, nHeight ); 790 pFilterBox->SetSizePixel( aSize ); 791 pFilterBox->Show(); // Show muss vor SetUpdateMode kommen !!! 792 pFilterBox->SetUpdateMode(sal_False); 793 794 // SetOutputSizePixel/StartPopupMode erst unten, wenn die Größe feststeht 795 796 // Listbox füllen 797 798 long nMaxText = 0; 799 String aCurrent; 800 String aTabName; 801 SCTAB nTabCount = pDoc->GetTableCount(); 802 SCTAB nEntryCount = 0; 803 for (SCTAB i=nTab+1; i<nTabCount && pDoc->IsScenario(i); i++) 804 { 805 if (pDoc->HasScenarioRange( i, rScenRange )) 806 if (pDoc->GetName( i, aTabName )) 807 { 808 pFilterBox->InsertEntry( aTabName ); 809 if (pDoc->IsActiveScenario(i)) 810 aCurrent = aTabName; 811 long nTextWidth = pFilterBox->GetTextWidth( aTabName ); 812 if ( nTextWidth > nMaxText ) 813 nMaxText = nTextWidth; 814 ++nEntryCount; 815 } 816 } 817 if (nEntryCount > SC_FILTERLISTBOX_LINES) 818 nMaxText += GetSettings().GetStyleSettings().GetScrollBarSize(); 819 nMaxText += 4; // für Rand 820 if ( nMaxText > 300 ) 821 nMaxText = 300; // auch nicht uebertreiben (Pixel) 822 823 if (nMaxText > nSizeX) // Größe auf benötigte Größe anpassen 824 { 825 long nDiff = nMaxText - nSizeX; 826 aSize = Size( nMaxText, nHeight ); 827 pFilterBox->SetSizePixel( aSize ); 828 pFilterFloat->SetOutputSizePixel( aSize ); 829 830 if ( !bLayoutRTL ) 831 { 832 // also move popup position 833 long nNewX = aCellRect.Left() - nDiff; 834 if ( nNewX < 0 ) 835 nNewX = 0; 836 aCellRect.Left() = nNewX; 837 } 838 } 839 840 pFilterFloat->SetOutputSizePixel( aSize ); 841 pFilterFloat->StartPopupMode( aCellRect, FLOATWIN_POPUPMODE_DOWN|FLOATWIN_POPUPMODE_GRABFOCUS ); 842 843 pFilterBox->SetUpdateMode(sal_True); 844 pFilterBox->GrabFocus(); 845 846 // Select erst nach GrabFocus, damit das Focus-Rechteck richtig landet 847 //! SvLBoxEntry* pSelect = NULL; 848 sal_uInt16 nPos = LISTBOX_ENTRY_NOTFOUND; 849 if (aCurrent.Len()) 850 { 851 nPos = pFilterBox->GetEntryPos( aCurrent ); 852 //! pSelect = pFilterBox->GetEntry( nPos ); 853 } 854 if (/*!pSelect*/ LISTBOX_ENTRY_NOTFOUND == nPos && pFilterBox->GetEntryCount() > 0 ) 855 nPos = 0; 856 //! pSelect = pFilterBox->GetEntry(0); // einer sollte immer selektiert sein 857 if (/*pSelect*/ LISTBOX_ENTRY_NOTFOUND != nPos ) 858 pFilterBox->SelectEntryPos(nPos); 859 860 pFilterBox->EndInit(); 861 862 // Szenario-Auswahl kommt aus MouseButtonDown: 863 // der nächste MouseMove auf die Filterbox ist wie ein ButtonDown 864 865 nMouseStatus = SC_GM_FILTER; 866 CaptureMouse(); 867 } 868 869 sal_Bool ScGridWindow::HasScenarioRange( sal_uInt16 nCol, sal_Int32 nRow, ScRange& rScenRange ) 870 { 871 ScDocument* pDoc = pViewData->GetDocument(); 872 sal_uInt16 nTab = pViewData->GetTabNo(); 873 sal_uInt16 nTabCount = pDoc->GetTableCount(); 874 if ( nTab+1<nTabCount && pDoc->IsScenario(nTab+1) && !pDoc->IsScenario(nTab) ) 875 { 876 sal_uInt16 i; 877 ScMarkData aMarks; 878 for (i=nTab+1; i<nTabCount && pDoc->IsScenario(i); i++) 879 pDoc->MarkScenario( i, nTab, aMarks, sal_False, SC_SCENARIO_SHOWFRAME ); 880 ScRangeList aRanges; 881 aMarks.FillRangeListWithMarks( &aRanges, sal_False ); 882 sal_uInt16 nRangeCount = (sal_uInt16)aRanges.Count(); 883 for (i=0; i<nRangeCount; i++) 884 { 885 ScRange aRange = *aRanges.GetObject(i); 886 pDoc->ExtendTotalMerge( aRange ); 887 sal_Bool bTextBelow = ( aRange.aStart.Row() == 0 ); 888 sal_Bool bIsInScen = sal_False; 889 if ( bTextBelow ) 890 { 891 bIsInScen = (aRange.aStart.Col() == nCol && aRange.aEnd.Row() == nRow-1); 892 } 893 else 894 { 895 bIsInScen = (aRange.aStart.Col() == nCol && aRange.aStart.Row() == nRow+1); 896 } 897 if (bIsInScen) 898 { 899 rScenRange = aRange; 900 return sal_True; 901 } 902 } 903 } 904 return sal_False; 905 } 906 void ScGridWindow::DoAutoFilterMenue( SCCOL nCol, SCROW nRow, sal_Bool bDataSelect ) 907 { 908 delete pFilterBox; 909 delete pFilterFloat; 910 911 sal_uInt16 i; 912 ScDocument* pDoc = pViewData->GetDocument(); 913 SCTAB nTab = pViewData->GetTabNo(); 914 sal_Bool bLayoutRTL = pDoc->IsLayoutRTL( nTab ); 915 916 long nSizeX = 0; 917 long nSizeY = 0; 918 long nHeight = 0; 919 pViewData->GetMergeSizePixel( nCol, nRow, nSizeX, nSizeY ); 920 // The button height should not use the merged cell height, should still use single row height 921 nSizeY = pViewData->ToPixel(pDoc->GetRowHeight(nRow, nTab), pViewData->GetPPTY()); 922 Point aPos = pViewData->GetScrPos( nCol, nRow, eWhich ); 923 if ( bLayoutRTL ) 924 aPos.X() -= nSizeX; 925 926 Rectangle aCellRect( OutputToScreenPixel(aPos), Size(nSizeX,nSizeY) ); 927 928 aPos.X() -= 1; 929 aPos.Y() += nSizeY - 1; 930 931 pFilterFloat = new ScFilterFloatingWindow( this, WinBits(WB_BORDER) ); // nicht resizable etc. 932 pFilterFloat->SetPopupModeEndHdl( LINK( this, ScGridWindow, PopupModeEndHdl ) ); 933 pFilterBox = new ScFilterListBox( 934 pFilterFloat, this, nCol, nRow, bDataSelect ? SC_FILTERBOX_DATASELECT : SC_FILTERBOX_FILTER ); 935 if ( bLayoutRTL ) 936 pFilterBox->EnableMirroring(); 937 938 nSizeX += 1; 939 940 { 941 Font aOldFont = GetFont(); SetFont( pFilterBox->GetFont() ); 942 MapMode aOldMode = GetMapMode(); SetMapMode( MAP_PIXEL ); 943 944 nHeight = GetTextHeight(); 945 nHeight *= SC_FILTERLISTBOX_LINES; 946 947 SetMapMode( aOldMode ); 948 SetFont( aOldFont ); 949 } 950 951 // SetSize später 952 /* 953 pFilterBox->SetSelectionMode( SINGLE_SELECTION ); 954 pFilterBox->SetTabs( nFilterBoxTabs, MapUnit( MAP_APPFONT )); 955 pFilterBox->SetTabJustify( 1, bLayoutRTL ? AdjustRight : AdjustLeft ); 956 */ 957 958 sal_Bool bEmpty = sal_False; 959 TypedScStrCollection aStrings( 128, 128 ); 960 if ( bDataSelect ) // Auswahl-Liste 961 { 962 // Liste fuellen 963 aStrings.SetCaseSensitive( sal_True ); 964 pDoc->GetDataEntries( nCol, nRow, nTab, aStrings ); 965 if ( aStrings.GetCount() == 0 ) 966 bEmpty = sal_True; 967 } 968 else // AutoFilter 969 { 970 //! wird der Titel ueberhaupt ausgewertet ??? 971 String aString; 972 pDoc->GetString( nCol, nRow, nTab, aString ); 973 pFilterBox->SetText( aString ); 974 975 long nMaxText = 0; 976 977 // default entries 978 static const sal_uInt16 nDefIDs[] = { SCSTR_ALLFILTER, SCSTR_TOP10FILTER, SCSTR_STDFILTER, SCSTR_EMPTY, SCSTR_NOTEMPTY }; 979 const sal_uInt16 nDefCount = sizeof(nDefIDs) / sizeof(sal_uInt16); 980 for (i=0; i<nDefCount; i++) 981 { 982 String aEntry( (ScResId) nDefIDs[i] ); 983 pFilterBox->InsertEntry( aEntry ); 984 long nTextWidth = pFilterBox->GetTextWidth( aEntry ); 985 if ( nTextWidth > nMaxText ) 986 nMaxText = nTextWidth; 987 } 988 pFilterBox->SetSeparatorPos( nDefCount - 1 ); 989 990 // get list entries 991 bool bHasDates = false; 992 pDoc->GetFilterEntries( nCol, nRow, nTab, true, aStrings, bHasDates); 993 pFilterBox->SetListHasDates(bHasDates); 994 995 // check widths of numerical entries (string entries are not included) 996 // so all numbers are completely visible 997 sal_uInt16 nCount = aStrings.GetCount(); 998 for (i=0; i<nCount; i++) 999 { 1000 TypedStrData* pData = aStrings[i]; 1001 if ( !pData->IsStrData() ) // only numerical entries 1002 { 1003 long nTextWidth = pFilterBox->GetTextWidth( pData->GetString() ); 1004 if ( nTextWidth > nMaxText ) 1005 nMaxText = nTextWidth; 1006 } 1007 } 1008 1009 // add scrollbar width if needed (string entries are counted here) 1010 // (scrollbar is shown if the box is exactly full?) 1011 if ( nCount + nDefCount >= SC_FILTERLISTBOX_LINES ) 1012 nMaxText += GetSettings().GetStyleSettings().GetScrollBarSize(); 1013 1014 nMaxText += 4; // for borders 1015 1016 if ( nMaxText > nSizeX ) 1017 nSizeX = nMaxText; // just modify width - starting position is unchanged 1018 } 1019 1020 if (!bEmpty) 1021 { 1022 // Position und Größe an Fenster anpassen 1023 //! vorher Abfrage, ob die Einträge hineinpassen (Breite) 1024 1025 Size aParentSize = GetParent()->GetOutputSizePixel(); 1026 Size aSize( nSizeX, nHeight ); 1027 1028 if ( aSize.Height() > aParentSize.Height() ) 1029 aSize.Height() = aParentSize.Height(); 1030 if ( aPos.Y() + aSize.Height() > aParentSize.Height() ) 1031 aPos.Y() = aParentSize.Height() - aSize.Height(); 1032 1033 pFilterBox->SetSizePixel( aSize ); 1034 pFilterBox->Show(); // Show muss vor SetUpdateMode kommen !!! 1035 pFilterBox->SetUpdateMode(sal_False); 1036 1037 pFilterFloat->SetOutputSizePixel( aSize ); 1038 pFilterFloat->StartPopupMode( aCellRect, FLOATWIN_POPUPMODE_DOWN|FLOATWIN_POPUPMODE_GRABFOCUS); 1039 1040 // Listbox fuellen 1041 sal_uInt16 nCount = aStrings.GetCount(); 1042 sal_Bool bWait = ( nCount > 100 ); 1043 1044 if (bWait) 1045 EnterWait(); 1046 1047 for (i=0; i<nCount; i++) 1048 pFilterBox->InsertEntry( aStrings[i]->GetString() ); 1049 1050 if (bWait) 1051 LeaveWait(); 1052 1053 pFilterBox->SetUpdateMode(sal_True); 1054 } 1055 1056 //! SvLBoxEntry* pSelect = NULL; 1057 sal_uInt16 nSelPos = LISTBOX_ENTRY_NOTFOUND; 1058 1059 if (!bDataSelect) // AutoFilter: aktiven Eintrag selektieren 1060 { 1061 ScDBData* pDBData = pDoc->GetDBAtCursor( nCol, nRow, nTab ); 1062 if (pDBData) 1063 { 1064 ScQueryParam aParam; 1065 pDBData->GetQueryParam( aParam ); // kann nur MAXQUERY Einträge ergeben 1066 1067 sal_Bool bValid = sal_True; 1068 for (SCSIZE j=0; j<MAXQUERY && bValid; j++) // bisherige Filter-Einstellungen 1069 if (aParam.GetEntry(j).bDoQuery) 1070 { 1071 //! Abfrage mit DrawButtons zusammenfassen! 1072 1073 ScQueryEntry& rEntry = aParam.GetEntry(j); 1074 if (j>0) 1075 if (rEntry.eConnect != SC_AND) 1076 bValid = sal_False; 1077 if (rEntry.nField == nCol) 1078 { 1079 if (rEntry.eOp == SC_EQUAL) 1080 { 1081 String* pStr = rEntry.pStr; 1082 if (pStr) 1083 { 1084 nSelPos = pFilterBox->GetEntryPos( *pStr ); 1085 //! pSelect = pFilterBox->GetEntry( nPos ); 1086 } 1087 } 1088 else if (rEntry.eOp == SC_TOPVAL && rEntry.pStr && 1089 rEntry.pStr->EqualsAscii("10")) 1090 nSelPos = SC_AUTOFILTER_TOP10; 1091 else 1092 nSelPos = SC_AUTOFILTER_CUSTOM; 1093 } 1094 } 1095 1096 if (!bValid) 1097 nSelPos = SC_AUTOFILTER_CUSTOM; 1098 } 1099 } 1100 else 1101 { 1102 1103 sal_uLong nIndex = ((SfxUInt32Item*)pDoc->GetAttr( 1104 nCol, nRow, nTab, ATTR_VALIDDATA ))->GetValue(); 1105 if ( nIndex ) 1106 { 1107 const ScValidationData* pData = pDoc->GetValidationEntry( nIndex ); 1108 if (pData) 1109 { 1110 TypedStrData* pNew = NULL; 1111 String aDocStr; 1112 pDoc->GetString( nCol, nRow, nTab, aDocStr ); 1113 if ( pDoc->HasValueData( nCol, nRow, nTab ) ) 1114 { 1115 double fVal = pDoc->GetValue(ScAddress(nCol, nRow, nTab)); 1116 pNew = new TypedStrData( aDocStr, fVal, SC_STRTYPE_VALUE ); 1117 } 1118 else 1119 pNew = new TypedStrData( aDocStr, 0.0, SC_STRTYPE_STANDARD ); 1120 1121 bool bSortList = ( pData->GetListType() == ValidListType::SORTEDASCENDING); 1122 if ( bSortList ) 1123 { 1124 sal_uInt16 nStrIndex; 1125 if (aStrings.Search(pNew,nStrIndex)) 1126 nSelPos = nStrIndex; 1127 } 1128 else 1129 { 1130 sal_uInt16 nCount = aStrings.GetCount(); 1131 for (i = 0; ((i < nCount) && ( LISTBOX_ENTRY_NOTFOUND == nSelPos)); i++) 1132 { 1133 if ( aStrings.Compare(aStrings[i], pNew)==0 ) 1134 nSelPos = i; 1135 } 1136 } 1137 delete pNew; 1138 } 1139 } 1140 } 1141 1142 // neu (309): irgendwas muss immer selektiert sein: 1143 if ( LISTBOX_ENTRY_NOTFOUND == nSelPos && pFilterBox->GetEntryCount() > 0 && !bDataSelect) 1144 nSelPos = 0; 1145 1146 // keine leere Auswahl-Liste anzeigen: 1147 1148 if ( bEmpty ) 1149 { 1150 DELETEZ(pFilterBox); // war nix 1151 DELETEZ(pFilterFloat); 1152 Sound::Beep(); // bemerkbar machen 1153 } 1154 else 1155 { 1156 // pFilterBox->Show(); // schon vorne 1157 pFilterBox->GrabFocus(); 1158 1159 // Select erst nach GrabFocus, damit das Focus-Rechteck richtig landet 1160 if ( LISTBOX_ENTRY_NOTFOUND != nSelPos ) 1161 pFilterBox->SelectEntryPos( nSelPos ); 1162 else 1163 { 1164 if (bDataSelect) 1165 pFilterBox->SetNoSelection(); 1166 } 1167 1168 pFilterBox->EndInit(); 1169 1170 if (!bDataSelect) 1171 { 1172 // AutoFilter (aus MouseButtonDown): 1173 // der nächste MouseMove auf die Filterbox ist wie ein ButtonDown 1174 1175 nMouseStatus = SC_GM_FILTER; 1176 CaptureMouse(); 1177 } 1178 } 1179 } 1180 1181 void ScGridWindow::FilterSelect( sal_uLong nSel ) 1182 { 1183 String aString; 1184 /* 1185 SvLBoxEntry* pEntry = pFilterBox->GetEntry( nSel ); 1186 if (pEntry) 1187 { 1188 SvLBoxString* pStringEntry = (SvLBoxString*) pEntry->GetFirstItem( SV_ITEM_ID_LBOXSTRING ); 1189 if ( pStringEntry ) 1190 aString = pStringEntry->GetText(); 1191 } 1192 */ 1193 aString = pFilterBox->GetEntry( static_cast< sal_uInt16 >( nSel ) ); 1194 1195 SCCOL nCol = pFilterBox->GetCol(); 1196 SCROW nRow = pFilterBox->GetRow(); 1197 switch ( pFilterBox->GetMode() ) 1198 { 1199 case SC_FILTERBOX_DATASELECT: 1200 ExecDataSelect( nCol, nRow, aString ); 1201 break; 1202 case SC_FILTERBOX_FILTER: 1203 ExecFilter( nSel, nCol, nRow, aString, pFilterBox->HasDates() ); 1204 break; 1205 case SC_FILTERBOX_SCENARIO: 1206 pViewData->GetView()->UseScenario( aString ); 1207 break; 1208 case SC_FILTERBOX_PAGEFIELD: 1209 // first entry is "all" 1210 ExecPageFieldSelect( nCol, nRow, (nSel != 0), aString ); 1211 break; 1212 } 1213 1214 if (pFilterFloat) 1215 pFilterFloat->EndPopupMode(); 1216 1217 GrabFocus(); // unter OS/2 stimmt der Focus sonst nicht 1218 } 1219 1220 void ScGridWindow::ExecDataSelect( SCCOL nCol, SCROW nRow, const String& rStr ) 1221 { 1222 if ( rStr.Len() ) 1223 { 1224 SCTAB nTab = pViewData->GetTabNo(); 1225 ScViewFunc* pView = pViewData->GetView(); 1226 pView->EnterData( nCol, nRow, nTab, rStr ); 1227 1228 // #i52307# CellContentChanged is not in EnterData so it isn't called twice 1229 // if the cursor is moved afterwards. 1230 pView->CellContentChanged(); 1231 } 1232 } 1233 1234 void ScGridWindow::ExecFilter( sal_uLong nSel, 1235 SCCOL nCol, SCROW nRow, 1236 const String& aValue, bool bCheckForDates ) 1237 { 1238 SCTAB nTab = pViewData->GetTabNo(); 1239 ScDocument* pDoc = pViewData->GetDocument(); 1240 1241 ScDBData* pDBData = pDoc->GetDBAtCursor( nCol, nRow, nTab ); 1242 if (pDBData) 1243 { 1244 ScQueryParam aParam; 1245 pDBData->GetQueryParam( aParam ); // kann nur MAXQUERY Einträge ergeben 1246 1247 if (SC_AUTOFILTER_CUSTOM == nSel) 1248 { 1249 SCTAB nAreaTab; 1250 SCCOL nStartCol; 1251 SCROW nStartRow; 1252 SCCOL nEndCol; 1253 SCROW nEndRow; 1254 pDBData->GetArea( nAreaTab, nStartCol,nStartRow,nEndCol,nEndRow ); 1255 pViewData->GetView()->MarkRange( ScRange( nStartCol,nStartRow,nAreaTab,nEndCol,nEndRow,nAreaTab)); 1256 pViewData->GetView()->SetCursor(nCol,nRow); //! auch ueber Slot ?? 1257 pViewData->GetDispatcher().Execute( SID_FILTER, SFX_CALLMODE_SLOT | SFX_CALLMODE_RECORD ); 1258 } 1259 else 1260 { 1261 sal_Bool bDeleteOld = sal_False; 1262 SCSIZE nQueryPos = 0; 1263 sal_Bool bFound = sal_False; 1264 if (!aParam.bInplace) 1265 bDeleteOld = sal_True; 1266 if (aParam.bRegExp) 1267 bDeleteOld = sal_True; 1268 for (SCSIZE i=0; i<MAXQUERY && !bDeleteOld; i++) // bisherige Filter-Einstellungen 1269 if (aParam.GetEntry(i).bDoQuery) 1270 { 1271 //! Abfrage mit DrawButtons zusammenfassen! 1272 1273 ScQueryEntry& rEntry = aParam.GetEntry(i); 1274 if (i>0) 1275 if (rEntry.eConnect != SC_AND) 1276 bDeleteOld = sal_True; 1277 1278 if (rEntry.nField == nCol) 1279 { 1280 if (bFound) // diese Spalte zweimal? 1281 bDeleteOld = sal_True; 1282 nQueryPos = i; 1283 bFound = sal_True; 1284 } 1285 if (!bFound) 1286 nQueryPos = i + 1; 1287 } 1288 1289 if (bDeleteOld) 1290 { 1291 SCSIZE nEC = aParam.GetEntryCount(); 1292 for (SCSIZE i=0; i<nEC; i++) 1293 aParam.GetEntry(i).Clear(); 1294 nQueryPos = 0; 1295 aParam.bInplace = sal_True; 1296 aParam.bRegExp = sal_False; 1297 } 1298 1299 if ( nQueryPos < MAXQUERY || SC_AUTOFILTER_ALL == nSel ) // löschen geht immer 1300 { 1301 if (nSel) 1302 { 1303 ScQueryEntry& rNewEntry = aParam.GetEntry(nQueryPos); 1304 1305 rNewEntry.bDoQuery = sal_True; 1306 rNewEntry.bQueryByString = sal_True; 1307 rNewEntry.nField = nCol; 1308 rNewEntry.bQueryByDate = bCheckForDates; 1309 if ( nSel == SC_AUTOFILTER_TOP10 ) 1310 { 1311 rNewEntry.eOp = SC_TOPVAL; 1312 *rNewEntry.pStr = String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("10")); 1313 } 1314 else if ( nSel == SC_AUTOFILTER_EMPTY) { 1315 rNewEntry.pStr->Erase(); 1316 rNewEntry.bQueryByString = sal_False; 1317 rNewEntry.eOp = SC_EQUAL; 1318 rNewEntry.nVal = SC_EMPTYFIELDS; 1319 } 1320 else if (nSel == SC_AUTOFILTER_NOTEMPTY) 1321 { 1322 rNewEntry.pStr->Erase(); 1323 rNewEntry.bQueryByString = sal_False; 1324 rNewEntry.eOp = SC_EQUAL; 1325 rNewEntry.nVal = SC_NONEMPTYFIELDS; 1326 } 1327 else 1328 { 1329 rNewEntry.eOp = SC_EQUAL; 1330 *rNewEntry.pStr = aValue; 1331 } 1332 if (nQueryPos > 0) 1333 rNewEntry.eConnect = SC_AND; 1334 } 1335 else 1336 { 1337 if (bFound) 1338 aParam.DeleteQuery(nQueryPos); 1339 } 1340 1341 // #100597# end edit mode - like in ScCellShell::ExecuteDB 1342 if ( pViewData->HasEditView( pViewData->GetActivePart() ) ) 1343 { 1344 SC_MOD()->InputEnterHandler(); 1345 pViewData->GetViewShell()->UpdateInputHandler(); 1346 } 1347 1348 pViewData->GetView()->Query( aParam, NULL, sal_True ); 1349 pDBData->SetQueryParam( aParam ); // speichern 1350 } 1351 else // "Zuviele Bedingungen" 1352 pViewData->GetView()->ErrorMessage( STR_FILTER_TOOMANY ); 1353 } 1354 } 1355 else 1356 { 1357 DBG_ERROR("Wo ist der Datenbankbereich?"); 1358 } 1359 } 1360 1361 void ScGridWindow::SetPointer( const Pointer& rPointer ) 1362 { 1363 nCurrentPointer = 0; 1364 Window::SetPointer( rPointer ); 1365 } 1366 1367 void ScGridWindow::MoveMouseStatus( ScGridWindow& rDestWin ) 1368 { 1369 if (nButtonDown) 1370 { 1371 rDestWin.nButtonDown = nButtonDown; 1372 rDestWin.nMouseStatus = nMouseStatus; 1373 } 1374 1375 if (bRFMouse) 1376 { 1377 rDestWin.bRFMouse = bRFMouse; 1378 rDestWin.bRFSize = bRFSize; 1379 rDestWin.nRFIndex = nRFIndex; 1380 rDestWin.nRFAddX = nRFAddX; 1381 rDestWin.nRFAddY = nRFAddY; 1382 bRFMouse = sal_False; 1383 } 1384 1385 if (nPagebreakMouse) 1386 { 1387 rDestWin.nPagebreakMouse = nPagebreakMouse; 1388 rDestWin.nPagebreakBreak = nPagebreakBreak; 1389 rDestWin.nPagebreakPrev = nPagebreakPrev; 1390 rDestWin.aPagebreakSource = aPagebreakSource; 1391 rDestWin.aPagebreakDrag = aPagebreakDrag; 1392 nPagebreakMouse = SC_PD_NONE; 1393 } 1394 } 1395 1396 sal_Bool ScGridWindow::TestMouse( const MouseEvent& rMEvt, sal_Bool bAction ) 1397 { 1398 // MouseEvent buttons must only be checked if bAction==TRUE 1399 // to allow changing the mouse pointer in MouseMove, 1400 // but not start AutoFill with right button (#74229#). 1401 // with bAction==sal_True, SetFillMode / SetDragMode is called 1402 1403 if ( bAction && !rMEvt.IsLeft() ) 1404 return sal_False; 1405 1406 sal_Bool bNewPointer = sal_False; 1407 1408 SfxInPlaceClient* pClient = pViewData->GetViewShell()->GetIPClient(); 1409 sal_Bool bOleActive = ( pClient && pClient->IsObjectInPlaceActive() ); 1410 1411 if ( pViewData->IsActive() && !bOleActive ) 1412 { 1413 ScDocument* pDoc = pViewData->GetDocument(); 1414 SCTAB nTab = pViewData->GetTabNo(); 1415 sal_Bool bLayoutRTL = pDoc->IsLayoutRTL( nTab ); 1416 1417 // Auto-Fill 1418 1419 ScRange aMarkRange; 1420 if (pViewData->GetSimpleArea( aMarkRange ) == SC_MARK_SIMPLE) 1421 { 1422 if (aMarkRange.aStart.Tab() == pViewData->GetTabNo() && mpAutoFillRect) 1423 { 1424 Point aMousePos = rMEvt.GetPosPixel(); 1425 if (mpAutoFillRect->IsInside(aMousePos)) 1426 { 1427 SetPointer( Pointer( POINTER_CROSS ) ); //! dickeres Kreuz ? 1428 if (bAction) 1429 { 1430 SCCOL nX = aMarkRange.aEnd.Col(); 1431 SCROW nY = aMarkRange.aEnd.Row(); 1432 1433 if ( lcl_IsEditableMatrix( pViewData->GetDocument(), aMarkRange ) ) 1434 pViewData->SetDragMode( 1435 aMarkRange.aStart.Col(), aMarkRange.aStart.Row(), nX, nY, SC_FILL_MATRIX ); 1436 else 1437 pViewData->SetFillMode( 1438 aMarkRange.aStart.Col(), aMarkRange.aStart.Row(), nX, nY ); 1439 1440 // #108266# The simple selection must also be recognized when dragging, 1441 // where the Marking flag is set and MarkToSimple won't work anymore. 1442 pViewData->GetMarkData().MarkToSimple(); 1443 } 1444 bNewPointer = sal_True; 1445 } 1446 } 1447 } 1448 1449 // Embedded-Rechteck 1450 1451 if (pDoc->IsEmbedded()) 1452 { 1453 ScRange aRange; 1454 pDoc->GetEmbedded( aRange ); 1455 if ( pViewData->GetTabNo() == aRange.aStart.Tab() ) 1456 { 1457 Point aStartPos = pViewData->GetScrPos( aRange.aStart.Col(), aRange.aStart.Row(), eWhich ); 1458 Point aEndPos = pViewData->GetScrPos( aRange.aEnd.Col()+1, aRange.aEnd.Row()+1, eWhich ); 1459 Point aMousePos = rMEvt.GetPosPixel(); 1460 if ( bLayoutRTL ) 1461 { 1462 aStartPos.X() += 2; 1463 aEndPos.X() += 2; 1464 } 1465 sal_Bool bTop = ( aMousePos.X() >= aStartPos.X()-3 && aMousePos.X() <= aStartPos.X()+1 && 1466 aMousePos.Y() >= aStartPos.Y()-3 && aMousePos.Y() <= aStartPos.Y()+1 ); 1467 sal_Bool bBottom = ( aMousePos.X() >= aEndPos.X()-3 && aMousePos.X() <= aEndPos.X()+1 && 1468 aMousePos.Y() >= aEndPos.Y()-3 && aMousePos.Y() <= aEndPos.Y()+1 ); 1469 if ( bTop || bBottom ) 1470 { 1471 SetPointer( Pointer( POINTER_CROSS ) ); 1472 if (bAction) 1473 { 1474 sal_uInt8 nMode = bTop ? SC_FILL_EMBED_LT : SC_FILL_EMBED_RB; 1475 pViewData->SetDragMode( 1476 aRange.aStart.Col(), aRange.aStart.Row(), 1477 aRange.aEnd.Col(), aRange.aEnd.Row(), nMode ); 1478 } 1479 bNewPointer = sal_True; 1480 } 1481 } 1482 } 1483 } 1484 1485 if (!bNewPointer && bAction) 1486 { 1487 // SetPointer( POINTER_ARROW ); // in Fu... 1488 pViewData->ResetFillMode(); 1489 } 1490 1491 return bNewPointer; 1492 } 1493 1494 void __EXPORT ScGridWindow::MouseButtonDown( const MouseEvent& rMEvt ) 1495 { 1496 nNestedButtonState = SC_NESTEDBUTTON_DOWN; 1497 1498 HandleMouseButtonDown( rMEvt ); 1499 1500 if ( nNestedButtonState == SC_NESTEDBUTTON_UP ) 1501 { 1502 // #i41690# If an object is deactivated from MouseButtonDown, it might reschedule, 1503 // so MouseButtonUp comes before the MouseButtonDown call is finished. In this case, 1504 // simulate another MouseButtonUp call, so the selection state is consistent. 1505 1506 nButtonDown = rMEvt.GetButtons(); 1507 FakeButtonUp(); 1508 1509 if ( IsTracking() ) 1510 EndTracking(); // normally done in VCL as part of MouseButtonUp handling 1511 } 1512 nNestedButtonState = SC_NESTEDBUTTON_NONE; 1513 } 1514 1515 void ScGridWindow::HandleMouseButtonDown( const MouseEvent& rMEvt ) 1516 { 1517 // We have to check if a context menu is shown and we have an UI 1518 // active inplace client. In that case we have to ignore the event. 1519 // Otherwise we would crash (context menu has been 1520 // opened by inplace client and we would deactivate the inplace client, 1521 // the context menu is closed by VCL asynchronously which in the end 1522 // would work on deleted objects or the context menu has no parent anymore) 1523 // See #126086# and #128122# 1524 SfxViewShell* pViewSh = pViewData->GetViewShell(); 1525 SfxInPlaceClient* pClient = pViewSh->GetIPClient(); 1526 if ( pClient && 1527 pClient->IsObjectInPlaceActive() && 1528 PopupMenu::IsInExecute() ) 1529 return; 1530 1531 aCurMousePos = rMEvt.GetPosPixel(); 1532 1533 // Filter-Popup beendet sich mit eigenem Mausklick, nicht erst beim Klick 1534 // in das GridWindow, darum ist die folgende Abfrage nicht mehr nötig: 1535 #if 0 1536 // merken, dass FilterBox gelöscht wird, damit sichergestellt 1537 // ist, dass in diesem Handler nicht an gleicher Stelle wieder 1538 // eine neue geöffnet wird. 1539 sal_Bool bWasFilterBox = ( pFilterBox != NULL && 1540 ((Window*)pFilterBox)->IsVisible() && 1541 !pFilterBox->IsDataSelect() ); 1542 SCCOL nOldColFBox = bWasFilterBox ? pFilterBox->GetCol() : 0; 1543 SCROW nOldRowFBox = bWasFilterBox ? pFilterBox->GetRow() : 0; 1544 #endif 1545 1546 ClickExtern(); // löscht FilterBox, wenn vorhanden 1547 1548 HideNoteMarker(); // Notiz-Anzeige 1549 1550 bEEMouse = sal_False; 1551 1552 ScModule* pScMod = SC_MOD(); 1553 if (pScMod->IsModalMode(pViewData->GetSfxDocShell())) 1554 { 1555 Sound::Beep(); 1556 return; 1557 } 1558 1559 pScActiveViewShell = pViewData->GetViewShell(); // falls auf Link geklickt wird 1560 nScClickMouseModifier = rMEvt.GetModifier(); // um Control-Klick immer zu erkennen 1561 1562 sal_Bool bDetective = pViewData->GetViewShell()->IsAuditShell(); 1563 sal_Bool bRefMode = pViewData->IsRefMode(); // Referenz angefangen 1564 sal_Bool bFormulaMode = pScMod->IsFormulaMode(); // nächster Klick -> Referenz 1565 sal_Bool bEditMode = pViewData->HasEditView(eWhich); // auch bei Mode==SC_INPUT_TYPE 1566 sal_Bool bDouble = (rMEvt.GetClicks() == 2); 1567 1568 // DeactivateIP passiert nur noch bei MarkListHasChanged 1569 1570 // im GrabFocus Aufruf kann eine Fehlermeldung hochkommen 1571 // (z.B. beim Umbenennen von Tabellen per Tab-Reiter) 1572 1573 if ( !nButtonDown || !bDouble ) // single (first) click is always valid 1574 nButtonDown = rMEvt.GetButtons(); // set nButtonDown first, so StopMarking works 1575 1576 // pViewData->GetViewShell()->GetViewFrame()->GetWindow().GrabFocus(); 1577 if ( ( bEditMode && pViewData->GetActivePart() == eWhich ) || !bFormulaMode ) 1578 GrabFocus(); 1579 1580 // #i31846# need to cancel a double click if the first click has set the "ignore" state, 1581 // but a single (first) click is always valid 1582 if ( nMouseStatus == SC_GM_IGNORE && bDouble ) 1583 { 1584 nButtonDown = 0; 1585 nMouseStatus = SC_GM_NONE; 1586 return; 1587 } 1588 1589 if ( bDetective ) // Detektiv-Fuell-Modus 1590 { 1591 if ( rMEvt.IsLeft() && !rMEvt.GetModifier() ) 1592 { 1593 Point aPos = rMEvt.GetPosPixel(); 1594 SCsCOL nPosX; 1595 SCsROW nPosY; 1596 pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY ); 1597 1598 SfxInt16Item aPosXItem( SID_RANGE_COL, nPosX ); 1599 SfxInt32Item aPosYItem( SID_RANGE_ROW, nPosY ); 1600 pViewData->GetDispatcher().Execute( SID_FILL_SELECT, SFX_CALLMODE_SLOT | SFX_CALLMODE_RECORD, 1601 &aPosXItem, &aPosYItem, (void*)0L ); 1602 1603 } 1604 nButtonDown = 0; 1605 nMouseStatus = SC_GM_NONE; 1606 return; 1607 } 1608 1609 if (!bDouble) 1610 nMouseStatus = SC_GM_NONE; 1611 1612 if (!bFormulaMode) 1613 { 1614 if ( pViewData->GetActivePart() != eWhich ) 1615 pViewData->GetView()->ActivatePart( eWhich ); 1616 } 1617 else 1618 { 1619 ScViewSelectionEngine* pSelEng = pViewData->GetView()->GetSelEngine(); 1620 pSelEng->SetWindow(this); 1621 pSelEng->SetWhich(eWhich); 1622 pSelEng->SetVisibleArea( Rectangle(Point(), GetOutputSizePixel()) ); 1623 } 1624 1625 if (bEditMode && (pViewData->GetRefTabNo() == pViewData->GetTabNo())) 1626 { 1627 Point aPos = rMEvt.GetPosPixel(); 1628 SCsCOL nPosX; 1629 SCsROW nPosY; 1630 pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY ); 1631 1632 EditView* pEditView; 1633 SCCOL nEditCol; 1634 SCROW nEditRow; 1635 pViewData->GetEditView( eWhich, pEditView, nEditCol, nEditRow ); 1636 SCCOL nEndCol = pViewData->GetEditEndCol(); 1637 SCROW nEndRow = pViewData->GetEditEndRow(); 1638 1639 if ( nPosX >= (SCsCOL) nEditCol && nPosX <= (SCsCOL) nEndCol && 1640 nPosY >= (SCsROW) nEditRow && nPosY <= (SCsROW) nEndRow ) 1641 { 1642 // #53966# beim Klick in die Tabellen-EditView immer den Focus umsetzen 1643 if (bFormulaMode) // sonst ist es oben schon passiert 1644 GrabFocus(); 1645 1646 pScMod->SetInputMode( SC_INPUT_TABLE ); 1647 bEEMouse = sal_True; 1648 bEditMode = pEditView->MouseButtonDown( rMEvt ); 1649 return; 1650 } 1651 } 1652 1653 if (pScMod->GetIsWaterCan()) 1654 { 1655 //! was is mit'm Mac ??? 1656 if ( rMEvt.GetModifier() + rMEvt.GetButtons() == MOUSE_RIGHT ) 1657 { 1658 nMouseStatus = SC_GM_WATERUNDO; 1659 return; 1660 } 1661 } 1662 1663 // Reihenfolge passend zum angezeigten Cursor: 1664 // RangeFinder, AutoFill, PageBreak, Drawing 1665 1666 if ( HitRangeFinder( rMEvt.GetPosPixel(), bRFSize, &nRFIndex, &nRFAddX, &nRFAddY ) ) 1667 { 1668 bRFMouse = sal_True; // die anderen Variablen sind oben initialisiert 1669 1670 if ( pViewData->GetActivePart() != eWhich ) 1671 pViewData->GetView()->ActivatePart( eWhich ); //! schon oben immer ??? 1672 1673 // CaptureMouse(); 1674 StartTracking(); 1675 return; 1676 } 1677 1678 sal_Bool bCrossPointer = TestMouse( rMEvt, sal_True ); 1679 if ( bCrossPointer ) 1680 { 1681 if ( bDouble ) 1682 pViewData->GetView()->FillCrossDblClick(); 1683 else 1684 pScMod->InputEnterHandler(); // Autofill etc. 1685 } 1686 1687 if ( !bCrossPointer ) 1688 { 1689 nPagebreakMouse = HitPageBreak( rMEvt.GetPosPixel(), &aPagebreakSource, 1690 &nPagebreakBreak, &nPagebreakPrev ); 1691 if (nPagebreakMouse) 1692 { 1693 bPagebreakDrawn = sal_False; 1694 // CaptureMouse(); 1695 StartTracking(); 1696 PagebreakMove( rMEvt, sal_False ); 1697 return; 1698 } 1699 } 1700 1701 if (!bFormulaMode && !bEditMode && rMEvt.IsLeft()) 1702 { 1703 if ( !bCrossPointer && DrawMouseButtonDown(rMEvt) ) 1704 { 1705 //if (DrawHasMarkedObj()) 1706 // pViewData->GetViewShell()->SetDrawShellOrSub(); // Draw-Objekt selektiert 1707 return; 1708 } 1709 1710 pViewData->GetViewShell()->SetDrawShell( sal_False ); // kein Draw-Objekt selektiert 1711 1712 // TestMouse schon oben passiert 1713 } 1714 1715 Point aPos = rMEvt.GetPosPixel(); 1716 SCsCOL nPosX; 1717 SCsROW nPosY; 1718 pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY ); 1719 SCTAB nTab = pViewData->GetTabNo(); 1720 ScDocument* pDoc = pViewData->GetDocument(); 1721 1722 // AutoFilter buttons 1723 1724 if ( !bDouble && !bFormulaMode && rMEvt.IsLeft() ) 1725 { 1726 SCsCOL nRealPosX; 1727 SCsROW nRealPosY; 1728 pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nRealPosX, nRealPosY, false );//the real row/col 1729 ScMergeFlagAttr* pRealPosAttr = (ScMergeFlagAttr*) 1730 pDoc->GetAttr( nRealPosX, nRealPosY, nTab, ATTR_MERGE_FLAG ); 1731 ScMergeFlagAttr* pAttr = (ScMergeFlagAttr*) 1732 pDoc->GetAttr( nPosX, nPosY, nTab, ATTR_MERGE_FLAG ); 1733 if( pRealPosAttr->HasAutoFilter() ) 1734 { 1735 SC_MOD()->InputEnterHandler(); 1736 if (DoAutoFilterButton( nRealPosX, nRealPosY, rMEvt)) 1737 return; 1738 } 1739 if( pAttr->HasAutoFilter() ) 1740 { 1741 SC_MOD()->InputEnterHandler(); //Add for i85305 1742 if (DoAutoFilterButton( nPosX, nPosY, rMEvt)) 1743 return; 1744 } 1745 if (pAttr->HasButton()) 1746 { 1747 DoPushButton( nPosX, nPosY, rMEvt ); // setzt evtl. bPivotMouse / bDPMouse 1748 return; 1749 } 1750 1751 // List Validity drop-down button 1752 1753 if ( bListValButton ) 1754 { 1755 Rectangle aButtonRect = GetListValButtonRect( aListValPos ); 1756 if ( aButtonRect.IsInside( aPos ) ) 1757 { 1758 DoAutoFilterMenue( aListValPos.Col(), aListValPos.Row(), sal_True ); 1759 1760 nMouseStatus = SC_GM_FILTER; // not set in DoAutoFilterMenue for bDataSelect 1761 CaptureMouse(); 1762 return; 1763 } 1764 } 1765 } 1766 1767 // scenario selection 1768 1769 ScRange aScenRange; 1770 if ( rMEvt.IsLeft() && HasScenarioButton( aPos, aScenRange ) ) 1771 { 1772 DoScenarioMenue( aScenRange ); 1773 return; 1774 } 1775 1776 // Doppelklick angefangen ? 1777 1778 // StopMarking kann aus DrawMouseButtonDown gerufen werden 1779 1780 if ( nMouseStatus != SC_GM_IGNORE && !bRefMode ) 1781 { 1782 if ( bDouble && !bCrossPointer ) 1783 { 1784 if (nMouseStatus == SC_GM_TABDOWN) 1785 nMouseStatus = SC_GM_DBLDOWN; 1786 } 1787 else 1788 nMouseStatus = SC_GM_TABDOWN; 1789 } 1790 1791 // Links in Edit-Zellen 1792 1793 sal_Bool bAlt = rMEvt.IsMod2(); 1794 if ( !bAlt && rMEvt.IsLeft() && 1795 GetEditUrl(rMEvt.GetPosPixel()) ) // Klick auf Link: Cursor nicht bewegen 1796 { 1797 SetPointer( Pointer( POINTER_REFHAND ) ); 1798 nMouseStatus = SC_GM_URLDOWN; // auch nur dann beim ButtonUp ausfuehren 1799 return; 1800 } 1801 1802 // Gridwin - SelectionEngine 1803 1804 if ( rMEvt.IsLeft() ) 1805 { 1806 ScViewSelectionEngine* pSelEng = pViewData->GetView()->GetSelEngine(); 1807 pSelEng->SetWindow(this); 1808 pSelEng->SetWhich(eWhich); 1809 pSelEng->SetVisibleArea( Rectangle(Point(), GetOutputSizePixel()) ); 1810 1811 // SelMouseButtonDown an der View setzt noch das bMoveIsShift Flag 1812 if ( pViewData->GetView()->SelMouseButtonDown( rMEvt ) ) 1813 { 1814 if (IsMouseCaptured()) 1815 { 1816 // Tracking statt CaptureMouse, damit sauber abgebrochen werden kann 1817 //! Irgendwann sollte die SelectionEngine selber StartTracking rufen!?! 1818 ReleaseMouse(); 1819 StartTracking(); 1820 } 1821 pViewData->GetMarkData().SetMarking(sal_True); 1822 return; 1823 } 1824 } 1825 } 1826 1827 void __EXPORT ScGridWindow::MouseButtonUp( const MouseEvent& rMEvt ) 1828 { 1829 aCurMousePos = rMEvt.GetPosPixel(); 1830 ScDocument* pDoc = pViewData->GetDocument(); 1831 ScMarkData& rMark = pViewData->GetMarkData(); 1832 1833 // #i41690# detect a MouseButtonUp call from within MouseButtonDown 1834 // (possible through Reschedule from storing an OLE object that is deselected) 1835 1836 if ( nNestedButtonState == SC_NESTEDBUTTON_DOWN ) 1837 nNestedButtonState = SC_NESTEDBUTTON_UP; 1838 1839 if (nButtonDown != rMEvt.GetButtons()) 1840 nMouseStatus = SC_GM_IGNORE; // reset und return 1841 1842 nButtonDown = 0; 1843 1844 if (nMouseStatus == SC_GM_IGNORE) 1845 { 1846 nMouseStatus = SC_GM_NONE; 1847 // Selection-Engine: Markieren abbrechen 1848 pViewData->GetView()->GetSelEngine()->Reset(); 1849 rMark.SetMarking(sal_False); 1850 if (pViewData->IsAnyFillMode()) 1851 { 1852 pViewData->GetView()->StopRefMode(); 1853 pViewData->ResetFillMode(); 1854 } 1855 StopMarking(); 1856 DrawEndAction(); // Markieren/Verschieben auf Drawing-Layer abbrechen 1857 ReleaseMouse(); 1858 return; 1859 } 1860 1861 if (nMouseStatus == SC_GM_FILTER) 1862 { 1863 if ( pFilterBox && pFilterBox->GetMode() == SC_FILTERBOX_FILTER ) 1864 { 1865 if (mpFilterButton.get()) 1866 { 1867 bool bFilterActive = IsAutoFilterActive( 1868 pFilterBox->GetCol(), pFilterBox->GetRow(), pViewData->GetTabNo() ); 1869 1870 mpFilterButton->setHasHiddenMember(bFilterActive); 1871 mpFilterButton->setPopupPressed(false); 1872 HideCursor(); 1873 mpFilterButton->draw(); 1874 ShowCursor(); 1875 } 1876 } 1877 nMouseStatus = SC_GM_NONE; 1878 ReleaseMouse(); 1879 return; // da muss nix mehr passieren 1880 } 1881 1882 ScModule* pScMod = SC_MOD(); 1883 if (pScMod->IsModalMode(pViewData->GetSfxDocShell())) 1884 return; 1885 1886 SfxBindings& rBindings = pViewData->GetBindings(); 1887 if (bEEMouse && pViewData->HasEditView( eWhich )) 1888 { 1889 EditView* pEditView; 1890 SCCOL nEditCol; 1891 SCROW nEditRow; 1892 pViewData->GetEditView( eWhich, pEditView, nEditCol, nEditRow ); 1893 pEditView->MouseButtonUp( rMEvt ); 1894 1895 if ( rMEvt.IsMiddle() && 1896 GetSettings().GetMouseSettings().GetMiddleButtonAction() == MOUSE_MIDDLE_PASTESELECTION ) 1897 { 1898 // EditView may have pasted from selection 1899 pScMod->InputChanged( pEditView ); 1900 } 1901 else 1902 pScMod->InputSelection( pEditView ); // parentheses etc. 1903 1904 pViewData->GetView()->InvalidateAttribs(); 1905 rBindings.Invalidate( SID_HYPERLINK_GETLINK ); 1906 bEEMouse = sal_False; 1907 return; 1908 } 1909 1910 if (bDPMouse) 1911 { 1912 DPMouseButtonUp( rMEvt ); // resets bDPMouse 1913 return; 1914 } 1915 1916 if (bRFMouse) 1917 { 1918 RFMouseMove( rMEvt, sal_True ); // Range wieder richtig herum 1919 bRFMouse = sal_False; 1920 SetPointer( Pointer( POINTER_ARROW ) ); 1921 ReleaseMouse(); 1922 return; 1923 } 1924 1925 if (nPagebreakMouse) 1926 { 1927 PagebreakMove( rMEvt, sal_True ); 1928 nPagebreakMouse = SC_PD_NONE; 1929 SetPointer( Pointer( POINTER_ARROW ) ); 1930 ReleaseMouse(); 1931 return; 1932 } 1933 1934 if (nMouseStatus == SC_GM_WATERUNDO) // Undo im Giesskannenmodus 1935 { 1936 ::svl::IUndoManager* pMgr = pViewData->GetDocShell()->GetUndoManager(); 1937 if ( pMgr->GetUndoActionCount() && pMgr->GetUndoActionId() == STR_UNDO_APPLYCELLSTYLE ) 1938 pMgr->Undo(); 1939 else 1940 Sound::Beep(); 1941 return; 1942 } 1943 1944 if (DrawMouseButtonUp(rMEvt)) // includes format paint brush handling for drawing objects 1945 { 1946 ScTabViewShell* pViewShell = pViewData->GetViewShell(); 1947 SfxBindings& rBindings=pViewShell->GetViewFrame()->GetBindings(); 1948 rBindings.Invalidate(SID_ATTR_TRANSFORM_WIDTH); 1949 rBindings.Invalidate(SID_ATTR_TRANSFORM_HEIGHT); 1950 rBindings.Invalidate(SID_ATTR_TRANSFORM_POS_X); 1951 rBindings.Invalidate(SID_ATTR_TRANSFORM_POS_Y); 1952 rBindings.Invalidate(SID_ATTR_TRANSFORM_ANGLE); 1953 rBindings.Invalidate(SID_ATTR_TRANSFORM_ROT_X); 1954 rBindings.Invalidate(SID_ATTR_TRANSFORM_ROT_Y); 1955 rBindings.Invalidate(SID_ATTR_TRANSFORM_AUTOWIDTH); 1956 rBindings.Invalidate(SID_ATTR_TRANSFORM_AUTOHEIGHT); 1957 return; 1958 } 1959 1960 rMark.SetMarking(sal_False); 1961 1962 SetPointer( Pointer( POINTER_ARROW ) ); 1963 1964 if (pViewData->IsFillMode() || 1965 ( pViewData->GetFillMode() == SC_FILL_MATRIX && rMEvt.IsMod1() )) 1966 { 1967 nScFillModeMouseModifier = rMEvt.GetModifier(); 1968 SCCOL nStartCol; 1969 SCROW nStartRow; 1970 SCCOL nEndCol; 1971 SCROW nEndRow; 1972 pViewData->GetFillData( nStartCol, nStartRow, nEndCol, nEndRow ); 1973 // DBG_ASSERT( nStartCol==pViewData->GetRefStartX() && nStartRow==pViewData->GetRefStartY(), 1974 // "Block wrong for AutoFill" ); 1975 ScRange aDelRange; 1976 sal_Bool bIsDel = pViewData->GetDelMark( aDelRange ); 1977 1978 ScViewFunc* pView = pViewData->GetView(); 1979 pView->StopRefMode(); 1980 pViewData->ResetFillMode(); 1981 pView->GetFunctionSet()->SetAnchorFlag( sal_False ); // #i5819# don't use AutoFill anchor flag for selection 1982 1983 if ( bIsDel ) 1984 { 1985 pView->MarkRange( aDelRange, sal_False ); 1986 pView->DeleteContents( IDF_CONTENTS ); 1987 SCTAB nTab = pViewData->GetTabNo(); 1988 ScRange aBlockRange( nStartCol, nStartRow, nTab, nEndCol, nEndRow, nTab ); 1989 if ( aBlockRange != aDelRange ) 1990 { 1991 if ( aDelRange.aStart.Row() == nStartRow ) 1992 aBlockRange.aEnd.SetCol( aDelRange.aStart.Col() - 1 ); 1993 else 1994 aBlockRange.aEnd.SetRow( aDelRange.aStart.Row() - 1 ); 1995 pView->MarkRange( aBlockRange, sal_False ); 1996 } 1997 } 1998 else 1999 pViewData->GetDispatcher().Execute( FID_FILL_AUTO, SFX_CALLMODE_SLOT | SFX_CALLMODE_RECORD ); 2000 } 2001 else if (pViewData->GetFillMode() == SC_FILL_MATRIX) 2002 { 2003 SCTAB nTab = pViewData->GetTabNo(); 2004 SCCOL nStartCol; 2005 SCROW nStartRow; 2006 SCCOL nEndCol; 2007 SCROW nEndRow; 2008 pViewData->GetFillData( nStartCol, nStartRow, nEndCol, nEndRow ); 2009 ScRange aBlockRange( nStartCol, nStartRow, nTab, nEndCol, nEndRow, nTab ); 2010 SCCOL nFillCol = pViewData->GetRefEndX(); 2011 SCROW nFillRow = pViewData->GetRefEndY(); 2012 ScAddress aEndPos( nFillCol, nFillRow, nTab ); 2013 2014 ScTabView* pView = pViewData->GetView(); 2015 pView->StopRefMode(); 2016 pViewData->ResetFillMode(); 2017 pView->GetFunctionSet()->SetAnchorFlag( sal_False ); 2018 2019 if ( aEndPos != aBlockRange.aEnd ) 2020 { 2021 pViewData->GetDocShell()->GetDocFunc().ResizeMatrix( aBlockRange, aEndPos, sal_False ); 2022 pViewData->GetView()->MarkRange( ScRange( aBlockRange.aStart, aEndPos ) ); 2023 } 2024 } 2025 else if (pViewData->IsAnyFillMode()) 2026 { 2027 // Embedded-Area has been changed 2028 ScTabView* pView = pViewData->GetView(); 2029 pView->StopRefMode(); 2030 pViewData->ResetFillMode(); 2031 pView->GetFunctionSet()->SetAnchorFlag( sal_False ); 2032 pViewData->GetDocShell()->UpdateOle(pViewData); 2033 } 2034 2035 sal_Bool bRefMode = pViewData->IsRefMode(); 2036 if (bRefMode) 2037 pScMod->EndReference(); 2038 2039 // Giesskannen-Modus (Gestalter) 2040 2041 if (pScMod->GetIsWaterCan()) 2042 { 2043 // Abfrage auf Undo schon oben 2044 2045 ScStyleSheetPool* pStylePool = (ScStyleSheetPool*) 2046 (pViewData->GetDocument()-> 2047 GetStyleSheetPool()); 2048 if ( pStylePool ) 2049 { 2050 SfxStyleSheet* pStyleSheet = (SfxStyleSheet*) 2051 pStylePool->GetActualStyleSheet(); 2052 2053 if ( pStyleSheet ) 2054 { 2055 SfxStyleFamily eFamily = pStyleSheet->GetFamily(); 2056 2057 switch ( eFamily ) 2058 { 2059 case SFX_STYLE_FAMILY_PARA: 2060 pViewData->GetView()->SetStyleSheetToMarked( pStyleSheet ); 2061 pViewData->GetView()->DoneBlockMode(); 2062 break; 2063 2064 case SFX_STYLE_FAMILY_PAGE: 2065 pViewData->GetDocument()->SetPageStyle( pViewData->GetTabNo(), 2066 pStyleSheet->GetName() ); 2067 2068 ScPrintFunc( pViewData->GetDocShell(), 2069 pViewData->GetViewShell()->GetPrinter(sal_True), 2070 pViewData->GetTabNo() ).UpdatePages(); 2071 2072 rBindings.Invalidate( SID_STATUS_PAGESTYLE ); 2073 break; 2074 2075 default: 2076 break; 2077 } 2078 } 2079 } 2080 } 2081 2082 ScDBFunc* pView = pViewData->GetView(); 2083 ScDocument* pBrushDoc = pView->GetBrushDocument(); 2084 if ( pBrushDoc ) 2085 { 2086 pView->PasteFromClip( IDF_ATTRIB, pBrushDoc ); 2087 if ( !pView->IsPaintBrushLocked() ) 2088 pView->ResetBrushDocument(); // invalidates pBrushDoc pointer 2089 } 2090 2091 // 2092 // double click (only left button) 2093 // 2094 2095 sal_Bool bDouble = ( rMEvt.GetClicks() == 2 && rMEvt.IsLeft() ); 2096 if ( bDouble && !bRefMode && nMouseStatus == SC_GM_DBLDOWN && !pScMod->IsRefDialogOpen() ) 2097 { 2098 // data pilot table 2099 Point aPos = rMEvt.GetPosPixel(); 2100 SCsCOL nPosX; 2101 SCsROW nPosY; 2102 SCTAB nTab = pViewData->GetTabNo(); 2103 pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY ); 2104 ScDPObject* pDPObj = pDoc->GetDPAtCursor( nPosX, nPosY, nTab ); 2105 if ( pDPObj && pDPObj->GetSaveData()->GetDrillDown() ) 2106 { 2107 ScAddress aCellPos( nPosX, nPosY, pViewData->GetTabNo() ); 2108 2109 // Check for header drill-down first. 2110 sheet::DataPilotTableHeaderData aData; 2111 pDPObj->GetHeaderPositionData(aCellPos, aData); 2112 2113 if ( ( aData.Flags & sheet::MemberResultFlags::HASMEMBER ) && 2114 ! ( aData.Flags & sheet::MemberResultFlags::SUBTOTAL ) ) 2115 { 2116 sal_uInt16 nDummy; 2117 if ( pView->HasSelectionForDrillDown( nDummy ) ) 2118 { 2119 // execute slot to show dialog 2120 pViewData->GetDispatcher().Execute( SID_OUTLINE_SHOW, SFX_CALLMODE_SLOT | SFX_CALLMODE_RECORD ); 2121 } 2122 else 2123 { 2124 // toggle single entry 2125 ScDPObject aNewObj( *pDPObj ); 2126 pDPObj->ToggleDetails( aData, &aNewObj ); 2127 ScDBDocFunc aFunc( *pViewData->GetDocShell() ); 2128 aFunc.DataPilotUpdate( pDPObj, &aNewObj, sal_True, sal_False ); 2129 pViewData->GetView()->CursorPosChanged(); // shells may be switched 2130 } 2131 } 2132 else 2133 { 2134 // Check if the data area is double-clicked. 2135 2136 Sequence<sheet::DataPilotFieldFilter> aFilters; 2137 if ( pDPObj->GetDataFieldPositionData(aCellPos, aFilters) ) 2138 pViewData->GetView()->ShowDataPilotSourceData( *pDPObj, aFilters ); 2139 else 2140 Sound::Beep(); // nothing to expand/collapse/show 2141 } 2142 2143 return; 2144 } 2145 2146 // Check for cell protection attribute. 2147 ScTableProtection* pProtect = pDoc->GetTabProtection( nTab ); 2148 bool bEditAllowed = true; 2149 if ( pProtect && pProtect->isProtected() ) 2150 { 2151 bool bCellProtected = pDoc->HasAttrib(nPosX, nPosY, nTab, nPosX, nPosY, nTab, HASATTR_PROTECTED); 2152 bool bSkipProtected = !pProtect->isOptionEnabled(ScTableProtection::SELECT_LOCKED_CELLS); 2153 bool bSkipUnprotected = !pProtect->isOptionEnabled(ScTableProtection::SELECT_UNLOCKED_CELLS); 2154 2155 if ( bSkipProtected && bSkipUnprotected ) 2156 bEditAllowed = false; 2157 else if ( (bCellProtected && bSkipProtected) || (!bCellProtected && bSkipUnprotected) ) 2158 bEditAllowed = false; 2159 } 2160 2161 if ( bEditAllowed ) 2162 { 2163 // edit cell contents 2164 pViewData->GetViewShell()->UpdateInputHandler(); 2165 pScMod->SetInputMode( SC_INPUT_TABLE ); 2166 if (pViewData->HasEditView(eWhich)) 2167 { 2168 // Text-Cursor gleich an die geklickte Stelle setzen 2169 EditView* pEditView = pViewData->GetEditView( eWhich ); 2170 MouseEvent aEditEvt( rMEvt.GetPosPixel(), 1, MOUSE_SYNTHETIC, MOUSE_LEFT, 0 ); 2171 pEditView->MouseButtonDown( aEditEvt ); 2172 pEditView->MouseButtonUp( aEditEvt ); 2173 } 2174 } 2175 return; 2176 } 2177 2178 // Links in edit cells 2179 2180 sal_Bool bAlt = rMEvt.IsMod2(); 2181 if ( !bAlt && !bRefMode && !bDouble && nMouseStatus == SC_GM_URLDOWN ) 2182 { 2183 // beim ButtonUp nur ausfuehren, wenn ButtonDown auch ueber einer URL war 2184 2185 String aName, aUrl, aTarget; 2186 if ( GetEditUrl( rMEvt.GetPosPixel(), &aName, &aUrl, &aTarget ) ) 2187 { 2188 nMouseStatus = SC_GM_NONE; // keinen Doppelklick anfangen 2189 ScGlobal::OpenURL( aUrl, aTarget ); 2190 2191 // fire worksheet_followhyperlink event 2192 uno::Reference< script::vba::XVBAEventProcessor > xVbaEvents = pDoc->GetVbaEventProcessor(); 2193 if( xVbaEvents.is() ) try 2194 { 2195 Point aPos = rMEvt.GetPosPixel(); 2196 SCsCOL nPosX; 2197 SCsROW nPosY; 2198 SCTAB nTab = pViewData->GetTabNo(); 2199 pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY ); 2200 ScBaseCell* pCell = NULL; 2201 if( lcl_GetHyperlinkCell( pDoc, nPosX, nPosY, nTab, pCell ) ) 2202 { 2203 ScAddress aCellPos( nPosX, nPosY, nTab ); 2204 uno::Reference< table::XCell > xCell( new ScCellObj( pViewData->GetDocShell(), aCellPos ) ); 2205 uno::Sequence< uno::Any > aArgs(1); 2206 aArgs[0] <<= xCell; 2207 xVbaEvents->processVbaEvent( script::vba::VBAEventId::WORKSHEET_FOLLOWHYPERLINK, aArgs ); 2208 } 2209 } 2210 catch( uno::Exception& ) 2211 { 2212 } 2213 2214 return; 2215 } 2216 } 2217 2218 // Gridwin - SelectionEngine 2219 2220 // SelMouseButtonDown is called only for left button, but SelMouseButtonUp would return 2221 // sal_True for any call, so IsLeft must be checked here, too. 2222 2223 if ( rMEvt.IsLeft() && pViewData->GetView()->GetSelEngine()->SelMouseButtonUp( rMEvt ) ) 2224 { 2225 // rMark.MarkToSimple(); 2226 pViewData->GetView()->UpdateAutoFillMark(); 2227 2228 SfxDispatcher* pDisp = pViewData->GetViewShell()->GetDispatcher(); 2229 sal_Bool bFormulaMode = pScMod->IsFormulaMode(); 2230 DBG_ASSERT( pDisp || bFormulaMode, "Cursor auf nicht aktiver View bewegen ?" ); 2231 2232 // #i14927# execute SID_CURRENTCELL (for macro recording) only if there is no 2233 // multiple selection, so the argument string completely describes the selection, 2234 // and executing the slot won't change the existing selection (executing the slot 2235 // here and from a recorded macro is treated equally) 2236 2237 if ( pDisp && !bFormulaMode && !rMark.IsMultiMarked() ) 2238 { 2239 String aAddr; // CurrentCell 2240 if( rMark.IsMarked() ) 2241 { 2242 // sal_Bool bKeep = rMark.IsMultiMarked(); //! wohin damit ??? 2243 2244 ScRange aScRange; 2245 rMark.GetMarkArea( aScRange ); 2246 aScRange.Format( aAddr, SCR_ABS ); 2247 if ( aScRange.aStart == aScRange.aEnd ) 2248 { 2249 // make sure there is a range selection string even for a single cell 2250 String aSingle = aAddr; 2251 aAddr.Append( (sal_Char) ':' ); 2252 aAddr.Append( aSingle ); 2253 } 2254 2255 //! SID_MARKAREA gibts nicht mehr ??? 2256 //! was passiert beim Markieren mit dem Cursor ??? 2257 } 2258 else // nur Cursor bewegen 2259 { 2260 ScAddress aScAddress( pViewData->GetCurX(), pViewData->GetCurY(), 0 ); 2261 aScAddress.Format( aAddr, SCA_ABS ); 2262 } 2263 2264 SfxStringItem aPosItem( SID_CURRENTCELL, aAddr ); 2265 pDisp->Execute( SID_CURRENTCELL, SFX_CALLMODE_SLOT | SFX_CALLMODE_RECORD, 2266 &aPosItem, (void*)0L ); 2267 2268 pViewData->GetView()->InvalidateAttribs(); 2269 } 2270 pViewData->GetViewShell()->SelectionChanged(); 2271 return; 2272 } 2273 } 2274 2275 void ScGridWindow::FakeButtonUp() 2276 { 2277 if ( nButtonDown ) 2278 { 2279 MouseEvent aEvent( aCurMousePos ); // nButtons = 0 -> ignore 2280 MouseButtonUp( aEvent ); 2281 } 2282 } 2283 2284 void __EXPORT ScGridWindow::MouseMove( const MouseEvent& rMEvt ) 2285 { 2286 aCurMousePos = rMEvt.GetPosPixel(); 2287 2288 if ( rMEvt.IsLeaveWindow() && pNoteMarker && !pNoteMarker->IsByKeyboard() ) 2289 HideNoteMarker(); 2290 2291 ScModule* pScMod = SC_MOD(); 2292 if (pScMod->IsModalMode(pViewData->GetSfxDocShell())) 2293 return; 2294 2295 // Ob aus dem Edit-Modus Drag&Drop gestartet wurde, bekommt man leider 2296 // nicht anders mit: 2297 2298 if (bEEMouse && nButtonDown && !rMEvt.GetButtons()) 2299 { 2300 bEEMouse = sal_False; 2301 nButtonDown = 0; 2302 nMouseStatus = SC_GM_NONE; 2303 return; 2304 } 2305 2306 if (nMouseStatus == SC_GM_IGNORE) 2307 return; 2308 2309 if (nMouseStatus == SC_GM_WATERUNDO) // Undo im Giesskannenmodus -> nur auf Up warten 2310 return; 2311 2312 if ( pViewData->GetViewShell()->IsAuditShell() ) // Detektiv-Füll-Modus 2313 { 2314 SetPointer( Pointer( POINTER_FILL ) ); 2315 return; 2316 } 2317 2318 if (nMouseStatus == SC_GM_FILTER && pFilterBox) 2319 { 2320 Point aRelPos = pFilterBox->ScreenToOutputPixel( OutputToScreenPixel( rMEvt.GetPosPixel() ) ); 2321 if ( Rectangle(Point(),pFilterBox->GetOutputSizePixel()).IsInside(aRelPos) ) 2322 { 2323 nButtonDown = 0; 2324 nMouseStatus = SC_GM_NONE; 2325 if ( pFilterBox->GetMode() == SC_FILTERBOX_FILTER ) 2326 { 2327 if (mpFilterButton.get()) 2328 { 2329 mpFilterButton->setHasHiddenMember(false); 2330 mpFilterButton->setPopupPressed(false); 2331 HideCursor(); 2332 mpFilterButton->draw(); 2333 ShowCursor(); 2334 } 2335 } 2336 ReleaseMouse(); 2337 pFilterBox->MouseButtonDown( MouseEvent( aRelPos, 1, MOUSE_SIMPLECLICK, MOUSE_LEFT ) ); 2338 return; 2339 } 2340 } 2341 2342 sal_Bool bFormulaMode = pScMod->IsFormulaMode(); // nächster Klick -> Referenz 2343 2344 if (bEEMouse && pViewData->HasEditView( eWhich )) 2345 { 2346 EditView* pEditView; 2347 SCCOL nEditCol; 2348 SCROW nEditRow; 2349 pViewData->GetEditView( eWhich, pEditView, nEditCol, nEditRow ); 2350 pEditView->MouseMove( rMEvt ); 2351 return; 2352 } 2353 2354 if (bDPMouse) 2355 { 2356 DPMouseMove( rMEvt ); 2357 return; 2358 } 2359 2360 if (bRFMouse) 2361 { 2362 RFMouseMove( rMEvt, sal_False ); 2363 return; 2364 } 2365 2366 if (nPagebreakMouse) 2367 { 2368 PagebreakMove( rMEvt, sal_False ); 2369 return; 2370 } 2371 2372 // anderen Mauszeiger anzeigen? 2373 2374 sal_Bool bEditMode = pViewData->HasEditView(eWhich); 2375 2376 //! Testen ob RefMode-Dragging !!! 2377 if ( bEditMode && (pViewData->GetRefTabNo() == pViewData->GetTabNo()) ) 2378 { 2379 Point aPos = rMEvt.GetPosPixel(); 2380 SCsCOL nPosX; 2381 SCsROW nPosY; 2382 pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY ); 2383 2384 EditView* pEditView; 2385 SCCOL nEditCol; 2386 SCROW nEditRow; 2387 pViewData->GetEditView( eWhich, pEditView, nEditCol, nEditRow ); 2388 SCCOL nEndCol = pViewData->GetEditEndCol(); 2389 SCROW nEndRow = pViewData->GetEditEndRow(); 2390 2391 if ( nPosX >= (SCsCOL) nEditCol && nPosX <= (SCsCOL) nEndCol && 2392 nPosY >= (SCsROW) nEditRow && nPosY <= (SCsROW) nEndRow ) 2393 { 2394 // Field can only be URL field 2395 sal_Bool bAlt = rMEvt.IsMod2(); 2396 if ( !bAlt && !nButtonDown && pEditView && pEditView->GetFieldUnderMousePointer() ) 2397 SetPointer( Pointer( POINTER_REFHAND ) ); 2398 else if ( pEditView && pEditView->GetEditEngine()->IsVertical() ) 2399 SetPointer( Pointer( POINTER_TEXT_VERTICAL ) ); 2400 else 2401 SetPointer( Pointer( POINTER_TEXT ) ); 2402 return; 2403 } 2404 } 2405 2406 sal_Bool bWater = SC_MOD()->GetIsWaterCan() || pViewData->GetView()->HasPaintBrush(); 2407 if (bWater) 2408 SetPointer( Pointer(POINTER_FILL) ); 2409 2410 if (!bWater) 2411 { 2412 sal_Bool bCross = sal_False; 2413 2414 // Range-Finder 2415 2416 sal_Bool bCorner; 2417 if ( HitRangeFinder( rMEvt.GetPosPixel(), bCorner ) ) 2418 { 2419 if (bCorner) 2420 SetPointer( Pointer( POINTER_CROSS ) ); 2421 else 2422 SetPointer( Pointer( POINTER_HAND ) ); 2423 bCross = sal_True; 2424 } 2425 2426 // Page-Break-Modus 2427 2428 sal_uInt16 nBreakType; 2429 if ( !nButtonDown && pViewData->IsPagebreakMode() && 2430 ( nBreakType = HitPageBreak( rMEvt.GetPosPixel() ) ) != 0 ) 2431 { 2432 PointerStyle eNew = POINTER_ARROW; 2433 switch ( nBreakType ) 2434 { 2435 case SC_PD_RANGE_L: 2436 case SC_PD_RANGE_R: 2437 case SC_PD_BREAK_H: 2438 eNew = POINTER_ESIZE; 2439 break; 2440 case SC_PD_RANGE_T: 2441 case SC_PD_RANGE_B: 2442 case SC_PD_BREAK_V: 2443 eNew = POINTER_SSIZE; 2444 break; 2445 case SC_PD_RANGE_TL: 2446 case SC_PD_RANGE_BR: 2447 eNew = POINTER_SESIZE; 2448 break; 2449 case SC_PD_RANGE_TR: 2450 case SC_PD_RANGE_BL: 2451 eNew = POINTER_NESIZE; 2452 break; 2453 } 2454 SetPointer( Pointer( eNew ) ); 2455 bCross = sal_True; 2456 } 2457 2458 // Fill-Cursor anzeigen ? 2459 2460 if ( !bFormulaMode && !nButtonDown ) 2461 if (TestMouse( rMEvt, sal_False )) 2462 bCross = sal_True; 2463 2464 if ( nButtonDown && pViewData->IsAnyFillMode() ) 2465 { 2466 SetPointer( Pointer( POINTER_CROSS ) ); 2467 bCross = sal_True; 2468 nScFillModeMouseModifier = rMEvt.GetModifier(); // ausgewertet bei AutoFill und Matrix 2469 } 2470 2471 if (!bCross) 2472 { 2473 sal_Bool bAlt = rMEvt.IsMod2(); 2474 2475 if (bEditMode) // Edit-Mode muss zuerst kommen! 2476 SetPointer( Pointer( POINTER_ARROW ) ); 2477 else if ( !bAlt && !nButtonDown && 2478 GetEditUrl(rMEvt.GetPosPixel()) ) 2479 SetPointer( Pointer( POINTER_REFHAND ) ); 2480 else if ( DrawMouseMove(rMEvt) ) // setzt Pointer um 2481 return; 2482 } 2483 } 2484 2485 if ( pViewData->GetView()->GetSelEngine()->SelMouseMove( rMEvt ) ) 2486 return; 2487 } 2488 2489 void lcl_InitMouseEvent( ::com::sun::star::awt::MouseEvent& rEvent, const MouseEvent& rEvt ) 2490 { 2491 rEvent.Modifiers = 0; 2492 if ( rEvt.IsShift() ) 2493 rEvent.Modifiers |= ::com::sun::star::awt::KeyModifier::SHIFT; 2494 if ( rEvt.IsMod1() ) 2495 rEvent.Modifiers |= ::com::sun::star::awt::KeyModifier::MOD1; 2496 if ( rEvt.IsMod2() ) 2497 rEvent.Modifiers |= ::com::sun::star::awt::KeyModifier::MOD2; 2498 if ( rEvt.IsMod3() ) 2499 rEvent.Modifiers |= ::com::sun::star::awt::KeyModifier::MOD3; 2500 2501 rEvent.Buttons = 0; 2502 if ( rEvt.IsLeft() ) 2503 rEvent.Buttons |= ::com::sun::star::awt::MouseButton::LEFT; 2504 if ( rEvt.IsRight() ) 2505 rEvent.Buttons |= ::com::sun::star::awt::MouseButton::RIGHT; 2506 if ( rEvt.IsMiddle() ) 2507 rEvent.Buttons |= ::com::sun::star::awt::MouseButton::MIDDLE; 2508 2509 rEvent.X = rEvt.GetPosPixel().X(); 2510 rEvent.Y = rEvt.GetPosPixel().Y(); 2511 rEvent.ClickCount = rEvt.GetClicks(); 2512 rEvent.PopupTrigger = sal_False; 2513 } 2514 2515 long ScGridWindow::PreNotify( NotifyEvent& rNEvt ) 2516 { 2517 bool bDone = false; 2518 sal_uInt16 nType = rNEvt.GetType(); 2519 if ( nType == EVENT_MOUSEBUTTONUP || nType == EVENT_MOUSEBUTTONDOWN ) 2520 { 2521 Window* pWindow = rNEvt.GetWindow(); 2522 if (pWindow == this && pViewData) 2523 { 2524 SfxViewFrame* pViewFrame = pViewData->GetViewShell()->GetViewFrame(); 2525 if (pViewFrame) 2526 { 2527 com::sun::star::uno::Reference<com::sun::star::frame::XController> xController = pViewFrame->GetFrame().GetController(); 2528 if (xController.is()) 2529 { 2530 ScTabViewObj* pImp = ScTabViewObj::getImplementation( xController ); 2531 if (pImp && pImp->IsMouseListening()) 2532 { 2533 ::com::sun::star::awt::MouseEvent aEvent; 2534 lcl_InitMouseEvent( aEvent, *rNEvt.GetMouseEvent() ); 2535 if ( rNEvt.GetWindow() ) 2536 aEvent.Source = rNEvt.GetWindow()->GetComponentInterface(); 2537 if ( nType == EVENT_MOUSEBUTTONDOWN) 2538 bDone = pImp->MousePressed( aEvent ); 2539 else 2540 bDone = pImp->MouseReleased( aEvent ); 2541 } 2542 } 2543 } 2544 } 2545 } 2546 if (bDone) // event consumed by a listener 2547 { 2548 if ( nType == EVENT_MOUSEBUTTONDOWN ) 2549 { 2550 const MouseEvent* pMouseEvent = rNEvt.GetMouseEvent(); 2551 if ( pMouseEvent->IsRight() && pMouseEvent->GetClicks() == 1 ) 2552 { 2553 // If a listener returned true for a right-click call, also prevent opening the context menu 2554 // (this works only if the context menu is opened on mouse-down) 2555 nMouseStatus = SC_GM_IGNORE; 2556 } 2557 } 2558 2559 return 1; 2560 } 2561 else 2562 return Window::PreNotify( rNEvt ); 2563 } 2564 2565 void ScGridWindow::Tracking( const TrackingEvent& rTEvt ) 2566 { 2567 // Weil die SelectionEngine kein Tracking kennt, die Events nur auf 2568 // die verschiedenen MouseHandler verteilen... 2569 2570 const MouseEvent& rMEvt = rTEvt.GetMouseEvent(); 2571 2572 if ( rTEvt.IsTrackingCanceled() ) // alles abbrechen... 2573 { 2574 if (!pViewData->GetView()->IsInActivatePart()) 2575 { 2576 if (bDPMouse) 2577 bDPMouse = sal_False; // gezeichnet wird per bDragRect 2578 if (bDragRect) 2579 { 2580 // pViewData->GetView()->DrawDragRect( nDragStartX, nDragStartY, nDragEndX, nDragEndY, eWhich ); 2581 bDragRect = sal_False; 2582 UpdateDragRectOverlay(); 2583 } 2584 if (bRFMouse) 2585 { 2586 RFMouseMove( rMEvt, sal_True ); // richtig abbrechen geht dabei nicht... 2587 bRFMouse = sal_False; 2588 } 2589 if (nPagebreakMouse) 2590 { 2591 // if (bPagebreakDrawn) 2592 // DrawDragRect( aPagebreakDrag.aStart.Col(), aPagebreakDrag.aStart.Row(), 2593 // aPagebreakDrag.aEnd.Col(), aPagebreakDrag.aEnd.Row(), sal_False ); 2594 bPagebreakDrawn = sal_False; 2595 UpdateDragRectOverlay(); 2596 nPagebreakMouse = SC_PD_NONE; 2597 } 2598 2599 SetPointer( Pointer( POINTER_ARROW ) ); 2600 StopMarking(); 2601 MouseButtonUp( rMEvt ); // mit Status SC_GM_IGNORE aus StopMarking 2602 2603 sal_Bool bRefMode = pViewData->IsRefMode(); 2604 if (bRefMode) 2605 SC_MOD()->EndReference(); // #63148# Dialog nicht verkleinert lassen 2606 } 2607 } 2608 else if ( rTEvt.IsTrackingEnded() ) 2609 { 2610 // MouseButtonUp immer mit passenden Buttons (z.B. wegen Testtool, #63148#) 2611 // Schliesslich behauptet der Tracking-Event ja, dass normal beendet und nicht 2612 // abgebrochen wurde. 2613 2614 MouseEvent aUpEvt( rMEvt.GetPosPixel(), rMEvt.GetClicks(), 2615 rMEvt.GetMode(), nButtonDown, rMEvt.GetModifier() ); 2616 MouseButtonUp( aUpEvt ); 2617 } 2618 else 2619 MouseMove( rMEvt ); 2620 } 2621 2622 void ScGridWindow::StartDrag( sal_Int8 /* nAction */, const Point& rPosPixel ) 2623 { 2624 if ( pFilterBox || nPagebreakMouse ) 2625 return; 2626 2627 HideNoteMarker(); 2628 2629 CommandEvent aDragEvent( rPosPixel, COMMAND_STARTDRAG, sal_True ); 2630 2631 if (bEEMouse && pViewData->HasEditView( eWhich )) 2632 { 2633 EditView* pEditView; 2634 SCCOL nEditCol; 2635 SCROW nEditRow; 2636 pViewData->GetEditView( eWhich, pEditView, nEditCol, nEditRow ); 2637 2638 // #63263# don't remove the edit view while switching views 2639 ScModule* pScMod = SC_MOD(); 2640 pScMod->SetInEditCommand( sal_True ); 2641 2642 pEditView->Command( aDragEvent ); 2643 2644 ScInputHandler* pHdl = pScMod->GetInputHdl(); 2645 if (pHdl) 2646 pHdl->DataChanged(); 2647 2648 pScMod->SetInEditCommand( sal_False ); 2649 if (!pViewData->IsActive()) // dropped to different view? 2650 { 2651 ScInputHandler* pViewHdl = pScMod->GetInputHdl( pViewData->GetViewShell() ); 2652 if ( pViewHdl && pViewData->HasEditView( eWhich ) ) 2653 { 2654 pViewHdl->CancelHandler(); 2655 ShowCursor(); // missing from KillEditView 2656 } 2657 } 2658 } 2659 else 2660 if ( !DrawCommand(aDragEvent) ) 2661 pViewData->GetView()->GetSelEngine()->Command( aDragEvent ); 2662 } 2663 2664 void lcl_SetTextCursorPos( ScViewData* pViewData, ScSplitPos eWhich, Window* pWin ) 2665 { 2666 SCCOL nCol = pViewData->GetCurX(); 2667 SCROW nRow = pViewData->GetCurY(); 2668 Rectangle aEditArea = pViewData->GetEditArea( eWhich, nCol, nRow, pWin, NULL, sal_True ); 2669 aEditArea.Right() = aEditArea.Left(); 2670 aEditArea = pWin->PixelToLogic( aEditArea ); 2671 pWin->SetCursorRect( &aEditArea ); 2672 } 2673 2674 void __EXPORT ScGridWindow::Command( const CommandEvent& rCEvt ) 2675 { 2676 // The command event is send to the window after a possible context 2677 // menu from an inplace client is closed. Now we have the chance to 2678 // deactivate the inplace client without any problem regarding parent 2679 // windows and code on the stack. 2680 // For more information, see #126086# and #128122# 2681 sal_uInt16 nCmd = rCEvt.GetCommand(); 2682 ScTabViewShell* pTabViewSh = pViewData->GetViewShell(); 2683 SfxInPlaceClient* pClient = pTabViewSh->GetIPClient(); 2684 if ( pClient && 2685 pClient->IsObjectInPlaceActive() && 2686 nCmd == COMMAND_CONTEXTMENU ) 2687 { 2688 pTabViewSh->DeactivateOle(); 2689 return; 2690 } 2691 2692 ScModule* pScMod = SC_MOD(); 2693 DBG_ASSERT( nCmd != COMMAND_STARTDRAG, "ScGridWindow::Command called with COMMAND_STARTDRAG" ); 2694 2695 if ( nCmd == COMMAND_STARTEXTTEXTINPUT || 2696 nCmd == COMMAND_ENDEXTTEXTINPUT || 2697 nCmd == COMMAND_EXTTEXTINPUT || 2698 nCmd == COMMAND_CURSORPOS ) 2699 { 2700 sal_Bool bEditView = pViewData->HasEditView( eWhich ); 2701 if (!bEditView) 2702 { 2703 // only if no cell editview is active, look at drawview 2704 SdrView* pSdrView = pViewData->GetView()->GetSdrView(); 2705 if ( pSdrView ) 2706 { 2707 OutlinerView* pOlView = pSdrView->GetTextEditOutlinerView(); 2708 if ( pOlView && pOlView->GetWindow() == this ) 2709 { 2710 pOlView->Command( rCEvt ); 2711 return; // done 2712 } 2713 } 2714 } 2715 2716 if ( nCmd == COMMAND_CURSORPOS && !bEditView ) 2717 { 2718 // #88458# CURSORPOS may be called without following text input, 2719 // to set the input method window position 2720 // -> input mode must not be started, 2721 // manually calculate text insert position if not in input mode 2722 2723 lcl_SetTextCursorPos( pViewData, eWhich, this ); 2724 return; 2725 } 2726 2727 ScInputHandler* pHdl = pScMod->GetInputHdl( pViewData->GetViewShell() ); 2728 if ( pHdl ) 2729 { 2730 pHdl->InputCommand( rCEvt, sal_True ); 2731 return; // done 2732 } 2733 2734 Window::Command( rCEvt ); 2735 return; 2736 } 2737 2738 if ( nCmd == COMMAND_VOICE ) 2739 { 2740 // Der Handler wird nur gerufen, wenn ein Text-Cursor aktiv ist, 2741 // also muss es eine EditView oder ein editiertes Zeichenobjekt geben 2742 2743 ScInputHandler* pHdl = pScMod->GetInputHdl( pViewData->GetViewShell() ); 2744 if ( pHdl && pViewData->HasEditView( eWhich ) ) 2745 { 2746 EditView* pEditView = pViewData->GetEditView( eWhich ); // ist dann nicht 0 2747 pHdl->DataChanging(); 2748 pEditView->Command( rCEvt ); 2749 pHdl->DataChanged(); 2750 return; // erledigt 2751 } 2752 SdrView* pSdrView = pViewData->GetView()->GetSdrView(); 2753 if ( pSdrView ) 2754 { 2755 OutlinerView* pOlView = pSdrView->GetTextEditOutlinerView(); 2756 if ( pOlView && pOlView->GetWindow() == this ) 2757 { 2758 pOlView->Command( rCEvt ); 2759 return; // erledigt 2760 } 2761 } 2762 Window::Command(rCEvt); // sonst soll sich die Basisklasse drum kümmern... 2763 return; 2764 } 2765 2766 if ( nCmd == COMMAND_PASTESELECTION ) 2767 { 2768 if ( bEEMouse ) 2769 { 2770 // EditEngine handles selection in MouseButtonUp - no action 2771 // needed in command handler 2772 } 2773 else 2774 { 2775 PasteSelection( rCEvt.GetMousePosPixel() ); 2776 } 2777 return; 2778 } 2779 2780 if ( nCmd == COMMAND_INPUTLANGUAGECHANGE ) 2781 { 2782 // #i55929# Font and font size state depends on input language if nothing is selected, 2783 // so the slots have to be invalidated when the input language is changed. 2784 2785 SfxBindings& rBindings = pViewData->GetBindings(); 2786 rBindings.Invalidate( SID_ATTR_CHAR_FONT ); 2787 rBindings.Invalidate( SID_ATTR_CHAR_FONTHEIGHT ); 2788 return; 2789 } 2790 2791 if ( nCmd == COMMAND_WHEEL || nCmd == COMMAND_STARTAUTOSCROLL || nCmd == COMMAND_AUTOSCROLL ) 2792 { 2793 sal_Bool bDone = pViewData->GetView()->ScrollCommand( rCEvt, eWhich ); 2794 if (!bDone) 2795 Window::Command(rCEvt); 2796 return; 2797 } 2798 // #i7560# FormulaMode check is below scrolling - scrolling is allowed during formula input 2799 sal_Bool bDisable = pScMod->IsFormulaMode() || 2800 pScMod->IsModalMode(pViewData->GetSfxDocShell()); 2801 if (bDisable) 2802 return; 2803 2804 if ( nCmd == COMMAND_CONTEXTMENU && !SC_MOD()->GetIsWaterCan() ) 2805 { 2806 sal_Bool bMouse = rCEvt.IsMouseEvent(); 2807 if ( bMouse && nMouseStatus == SC_GM_IGNORE ) 2808 return; 2809 2810 if (pViewData->IsAnyFillMode()) 2811 { 2812 pViewData->GetView()->StopRefMode(); 2813 pViewData->ResetFillMode(); 2814 } 2815 ReleaseMouse(); 2816 StopMarking(); 2817 2818 Point aPosPixel = rCEvt.GetMousePosPixel(); 2819 Point aMenuPos = aPosPixel; 2820 2821 if ( bMouse ) 2822 { 2823 SCsCOL nCellX = -1; 2824 SCsROW nCellY = -1; 2825 pViewData->GetPosFromPixel(aPosPixel.X(), aPosPixel.Y(), eWhich, nCellX, nCellY); 2826 ScDocument* pDoc = pViewData->GetDocument(); 2827 SCTAB nTab = pViewData->GetTabNo(); 2828 const ScTableProtection* pProtect = pDoc->GetTabProtection(nTab); 2829 bool bSelectAllowed = true; 2830 if ( pProtect && pProtect->isProtected() ) 2831 { 2832 // This sheet is protected. Check if a context menu is allowed on this cell. 2833 bool bCellProtected = pDoc->HasAttrib(nCellX, nCellY, nTab, nCellX, nCellY, nTab, HASATTR_PROTECTED); 2834 bool bSelProtected = pProtect->isOptionEnabled(ScTableProtection::SELECT_LOCKED_CELLS); 2835 bool bSelUnprotected = pProtect->isOptionEnabled(ScTableProtection::SELECT_UNLOCKED_CELLS); 2836 2837 if (bCellProtected) 2838 bSelectAllowed = bSelProtected; 2839 else 2840 bSelectAllowed = bSelUnprotected; 2841 } 2842 if (!bSelectAllowed) 2843 // Selecting this cell is not allowed, neither is context menu. 2844 return; 2845 2846 // #i18735# First select the item under the mouse pointer. 2847 // This can change the selection, and the view state (edit mode, etc). 2848 SelectForContextMenu( aPosPixel, nCellX, nCellY ); 2849 } 2850 2851 sal_Bool bDone = sal_False; 2852 sal_Bool bEdit = pViewData->HasEditView(eWhich); 2853 if ( !bEdit ) 2854 { 2855 // Edit-Zelle mit Spelling-Errors ? 2856 if ( bMouse && GetEditUrlOrError( sal_True, aPosPixel ) ) 2857 { 2858 // GetEditUrlOrError hat den Cursor schon bewegt 2859 2860 pScMod->SetInputMode( SC_INPUT_TABLE ); 2861 bEdit = pViewData->HasEditView(eWhich); // hat's geklappt ? 2862 2863 DBG_ASSERT( bEdit, "kann nicht in Edit-Modus schalten" ); 2864 } 2865 } 2866 if ( bEdit ) 2867 { 2868 EditView* pEditView = pViewData->GetEditView( eWhich ); // ist dann nicht 0 2869 2870 if ( !bMouse ) 2871 { 2872 Cursor* pCur = pEditView->GetCursor(); 2873 if ( pCur ) 2874 { 2875 Point aLogicPos = pCur->GetPos(); 2876 // use the position right of the cursor (spell popup is opened if 2877 // the cursor is before the word, but not if behind it) 2878 aLogicPos.X() += pCur->GetWidth(); 2879 aLogicPos.Y() += pCur->GetHeight() / 2; // center vertically 2880 aMenuPos = LogicToPixel( aLogicPos ); 2881 } 2882 } 2883 2884 // if edit mode was just started above, online spelling may be incomplete 2885 pEditView->GetEditEngine()->CompleteOnlineSpelling(); 2886 2887 // IsCursorAtWrongSpelledWord could be used for !bMouse 2888 // if there was a corresponding ExecuteSpellPopup call 2889 2890 if( pEditView->IsWrongSpelledWordAtPos( aMenuPos ) ) 2891 { 2892 // Wenn man unter OS/2 neben das Popupmenü klickt, kommt MouseButtonDown 2893 // vor dem Ende des Menue-Execute, darum muss SetModified vorher kommen 2894 // (Bug #40968#) 2895 ScInputHandler* pHdl = pScMod->GetInputHdl(); 2896 if (pHdl) 2897 pHdl->SetModified(); 2898 2899 Link aLink = LINK( this, ScGridWindow, PopupSpellingHdl ); 2900 pEditView->ExecuteSpellPopup( aMenuPos, &aLink ); 2901 2902 bDone = sal_True; 2903 } 2904 } 2905 else if ( !bMouse ) 2906 { 2907 // non-edit menu by keyboard -> use lower right of cell cursor position 2908 2909 SCCOL nCurX = pViewData->GetCurX(); 2910 SCROW nCurY = pViewData->GetCurY(); 2911 aMenuPos = pViewData->GetScrPos( nCurX, nCurY, eWhich, sal_True ); 2912 long nSizeXPix; 2913 long nSizeYPix; 2914 pViewData->GetMergeSizePixel( nCurX, nCurY, nSizeXPix, nSizeYPix ); 2915 aMenuPos.X() += nSizeXPix; 2916 aMenuPos.Y() += nSizeYPix; 2917 2918 if (pViewData) 2919 { 2920 ScTabViewShell* pViewSh = pViewData->GetViewShell(); 2921 if (pViewSh) 2922 { 2923 // Is a draw object selected? 2924 2925 SdrView* pDrawView = pViewSh->GetSdrView(); 2926 if (pDrawView && pDrawView->AreObjectsMarked()) 2927 { 2928 // #100442#; the conext menu should open in the middle of the selected objects 2929 Rectangle aSelectRect(LogicToPixel(pDrawView->GetAllMarkedBoundRect())); 2930 aMenuPos = aSelectRect.Center(); 2931 } 2932 } 2933 } 2934 } 2935 2936 if (!bDone) 2937 { 2938 SfxDispatcher::ExecutePopup( 0, this, &aMenuPos ); 2939 } 2940 } 2941 } 2942 2943 void ScGridWindow::SelectForContextMenu( const Point& rPosPixel, SCsCOL nCellX, SCsROW nCellY ) 2944 { 2945 // #i18735# if the click was outside of the current selection, 2946 // the cursor is moved or an object at the click position selected. 2947 // (see SwEditWin::SelectMenuPosition in Writer) 2948 2949 ScTabView* pView = pViewData->GetView(); 2950 ScDrawView* pDrawView = pView->GetScDrawView(); 2951 2952 // check cell edit mode 2953 2954 if ( pViewData->HasEditView(eWhich) ) 2955 { 2956 ScModule* pScMod = SC_MOD(); 2957 SCCOL nEditStartCol = pViewData->GetEditViewCol(); //! change to GetEditStartCol after calcrtl is integrated 2958 SCROW nEditStartRow = pViewData->GetEditViewRow(); 2959 SCCOL nEditEndCol = pViewData->GetEditEndCol(); 2960 SCROW nEditEndRow = pViewData->GetEditEndRow(); 2961 2962 if ( nCellX >= (SCsCOL) nEditStartCol && nCellX <= (SCsCOL) nEditEndCol && 2963 nCellY >= (SCsROW) nEditStartRow && nCellY <= (SCsROW) nEditEndRow ) 2964 { 2965 // handle selection within the EditView 2966 2967 EditView* pEditView = pViewData->GetEditView( eWhich ); // not NULL (HasEditView) 2968 EditEngine* pEditEngine = pEditView->GetEditEngine(); 2969 Rectangle aOutputArea = pEditView->GetOutputArea(); 2970 Rectangle aVisArea = pEditView->GetVisArea(); 2971 2972 Point aTextPos = PixelToLogic( rPosPixel ); 2973 if ( pEditEngine->IsVertical() ) // have to manually transform position 2974 { 2975 aTextPos -= aOutputArea.TopRight(); 2976 long nTemp = -aTextPos.X(); 2977 aTextPos.X() = aTextPos.Y(); 2978 aTextPos.Y() = nTemp; 2979 } 2980 else 2981 aTextPos -= aOutputArea.TopLeft(); 2982 aTextPos += aVisArea.TopLeft(); // position in the edit document 2983 2984 EPosition aDocPosition = pEditEngine->FindDocPosition(aTextPos); 2985 ESelection aCompare(aDocPosition.nPara, aDocPosition.nIndex); 2986 ESelection aSelection = pEditView->GetSelection(); 2987 aSelection.Adjust(); // needed for IsLess/IsGreater 2988 if ( aCompare.IsLess(aSelection) || aCompare.IsGreater(aSelection) ) 2989 { 2990 // clicked outside the selected text - deselect and move text cursor 2991 MouseEvent aEvent( rPosPixel ); 2992 pEditView->MouseButtonDown( aEvent ); 2993 pEditView->MouseButtonUp( aEvent ); 2994 pScMod->InputSelection( pEditView ); 2995 } 2996 2997 return; // clicked within the edit view - keep edit mode 2998 } 2999 else 3000 { 3001 // outside of the edit view - end edit mode, regardless of cell selection, then continue 3002 pScMod->InputEnterHandler(); 3003 } 3004 } 3005 3006 // check draw text edit mode 3007 3008 Point aLogicPos = PixelToLogic( rPosPixel ); // after cell edit mode is ended 3009 if ( pDrawView && pDrawView->GetTextEditObject() && pDrawView->GetTextEditOutlinerView() ) 3010 { 3011 OutlinerView* pOlView = pDrawView->GetTextEditOutlinerView(); 3012 Rectangle aOutputArea = pOlView->GetOutputArea(); 3013 if ( aOutputArea.IsInside( aLogicPos ) ) 3014 { 3015 // handle selection within the OutlinerView 3016 3017 Outliner* pOutliner = pOlView->GetOutliner(); 3018 const EditEngine& rEditEngine = pOutliner->GetEditEngine(); 3019 Rectangle aVisArea = pOlView->GetVisArea(); 3020 3021 Point aTextPos = aLogicPos; 3022 if ( pOutliner->IsVertical() ) // have to manually transform position 3023 { 3024 aTextPos -= aOutputArea.TopRight(); 3025 long nTemp = -aTextPos.X(); 3026 aTextPos.X() = aTextPos.Y(); 3027 aTextPos.Y() = nTemp; 3028 } 3029 else 3030 aTextPos -= aOutputArea.TopLeft(); 3031 aTextPos += aVisArea.TopLeft(); // position in the edit document 3032 3033 EPosition aDocPosition = rEditEngine.FindDocPosition(aTextPos); 3034 ESelection aCompare(aDocPosition.nPara, aDocPosition.nIndex); 3035 ESelection aSelection = pOlView->GetSelection(); 3036 aSelection.Adjust(); // needed for IsLess/IsGreater 3037 if ( aCompare.IsLess(aSelection) || aCompare.IsGreater(aSelection) ) 3038 { 3039 // clicked outside the selected text - deselect and move text cursor 3040 // use DrawView to allow extra handling there (none currently) 3041 MouseEvent aEvent( rPosPixel ); 3042 pDrawView->MouseButtonDown( aEvent, this ); 3043 pDrawView->MouseButtonUp( aEvent, this ); 3044 } 3045 3046 return; // clicked within the edit area - keep edit mode 3047 } 3048 else 3049 { 3050 // Outside of the edit area - end text edit mode, then continue. 3051 // DrawDeselectAll also ends text edit mode and updates the shells. 3052 // If the click was on the edited object, it will be selected again below. 3053 pView->DrawDeselectAll(); 3054 } 3055 } 3056 3057 // look for existing selection 3058 3059 sal_Bool bHitSelected = sal_False; 3060 if ( pDrawView && pDrawView->IsMarkedObjHit( aLogicPos ) ) 3061 { 3062 // clicked on selected object -> don't change anything 3063 bHitSelected = sal_True; 3064 } 3065 else if ( pViewData->GetMarkData().IsCellMarked(nCellX, nCellY) ) 3066 { 3067 // clicked on selected cell -> don't change anything 3068 bHitSelected = sal_True; 3069 } 3070 3071 // select drawing object or move cell cursor 3072 3073 if ( !bHitSelected ) 3074 { 3075 sal_Bool bWasDraw = ( pDrawView && pDrawView->AreObjectsMarked() ); 3076 sal_Bool bHitDraw = sal_False; 3077 if ( pDrawView ) 3078 { 3079 pDrawView->UnmarkAllObj(); 3080 // Unlock the Internal Layer in order to activate the context menu. 3081 // re-lock in ScDrawView::MarkListHasChanged() 3082 lcl_UnLockComment( pDrawView, pDrawView->GetSdrPageView(), pDrawView->GetModel(), aLogicPos ,pViewData); 3083 bHitDraw = pDrawView->MarkObj( aLogicPos ); 3084 // draw shell is activated in MarkListHasChanged 3085 } 3086 if ( !bHitDraw ) 3087 { 3088 pView->Unmark(); 3089 pView->SetCursor(nCellX, nCellY); 3090 if ( bWasDraw ) 3091 pViewData->GetViewShell()->SetDrawShell( sal_False ); // switch shells 3092 } 3093 } 3094 } 3095 3096 void __EXPORT ScGridWindow::KeyInput(const KeyEvent& rKEvt) 3097 { 3098 // #96965# Cursor control for ref input dialog 3099 if( SC_MOD()->IsRefDialogOpen() ) 3100 { 3101 const KeyCode& rKeyCode = rKEvt.GetKeyCode(); 3102 if( !rKeyCode.GetModifier() && (rKeyCode.GetCode() == KEY_F2) ) 3103 { 3104 SC_MOD()->EndReference(); 3105 } 3106 else if( pViewData->GetViewShell()->MoveCursorKeyInput( rKEvt ) ) 3107 { 3108 ScRange aRef( 3109 pViewData->GetRefStartX(), pViewData->GetRefStartY(), pViewData->GetRefStartZ(), 3110 pViewData->GetRefEndX(), pViewData->GetRefEndY(), pViewData->GetRefEndZ() ); 3111 SC_MOD()->SetReference( aRef, pViewData->GetDocument() ); 3112 } 3113 pViewData->GetViewShell()->SelectionChanged(); 3114 return ; 3115 } 3116 // wenn semi-Modeless-SfxChildWindow-Dialog oben, keine KeyInputs: 3117 else if( !pViewData->IsAnyFillMode() ) 3118 { 3119 // query for existing note marker before calling ViewShell's keyboard handling 3120 // which may remove the marker 3121 sal_Bool bHadKeyMarker = ( pNoteMarker && pNoteMarker->IsByKeyboard() ); 3122 ScTabViewShell* pViewSh = pViewData->GetViewShell(); 3123 3124 if (pViewData->GetDocShell()->GetProgress()) 3125 return; 3126 3127 if (DrawKeyInput(rKEvt)) 3128 { 3129 const KeyCode& rKeyCode = rKEvt.GetKeyCode(); 3130 if (rKeyCode.GetCode() == KEY_DOWN 3131 || rKeyCode.GetCode() == KEY_UP 3132 || rKeyCode.GetCode() == KEY_LEFT 3133 || rKeyCode.GetCode() == KEY_RIGHT) 3134 { 3135 ScTabViewShell* pViewShell = pViewData->GetViewShell(); 3136 SfxBindings& rBindings = pViewShell->GetViewFrame()->GetBindings(); 3137 rBindings.Invalidate(SID_ATTR_TRANSFORM_POS_X); 3138 rBindings.Invalidate(SID_ATTR_TRANSFORM_POS_Y); 3139 } 3140 return; 3141 } 3142 3143 if (!pViewData->GetView()->IsDrawSelMode() && !DrawHasMarkedObj()) // keine Eingaben im Zeichenmodus 3144 { //! DrawShell abfragen !!! 3145 if (pViewSh->TabKeyInput(rKEvt)) 3146 return; 3147 } 3148 else 3149 if (pViewSh->SfxViewShell::KeyInput(rKEvt)) // von SfxViewShell 3150 return; 3151 3152 KeyCode aCode = rKEvt.GetKeyCode(); 3153 if ( aCode.GetCode() == KEY_ESCAPE && aCode.GetModifier() == 0 ) 3154 { 3155 if ( bHadKeyMarker ) 3156 HideNoteMarker(); 3157 else 3158 pViewSh->Escape(); 3159 return; 3160 } 3161 if ( aCode.GetCode() == KEY_F1 && aCode.GetModifier() == KEY_MOD1 ) 3162 { 3163 // ctrl-F1 shows or hides the note or redlining info for the cursor position 3164 // (hard-coded because F1 can't be configured) 3165 3166 if ( bHadKeyMarker ) 3167 HideNoteMarker(); // hide when previously visible 3168 else 3169 ShowNoteMarker( pViewData->GetCurX(), pViewData->GetCurY(), sal_True ); 3170 return; 3171 } 3172 } 3173 3174 Window::KeyInput(rKEvt); 3175 } 3176 3177 void ScGridWindow::StopMarking() 3178 { 3179 DrawEndAction(); // Markieren/Verschieben auf Drawing-Layer abbrechen 3180 3181 if (nButtonDown) 3182 { 3183 pViewData->GetMarkData().SetMarking(sal_False); 3184 nMouseStatus = SC_GM_IGNORE; 3185 } 3186 } 3187 3188 void ScGridWindow::UpdateInputContext() 3189 { 3190 sal_Bool bReadOnly = pViewData->GetDocShell()->IsReadOnly(); 3191 sal_uLong nOptions = bReadOnly ? 0 : ( INPUTCONTEXT_TEXT | INPUTCONTEXT_EXTTEXTINPUT ); 3192 3193 // when font from InputContext is used, 3194 // it must be taken from the cursor position's cell attributes 3195 3196 InputContext aContext; 3197 aContext.SetOptions( nOptions ); 3198 SetInputContext( aContext ); 3199 } 3200 3201 //-------------------------------------------------------- 3202 3203 // sensitiver Bereich (Pixel) 3204 #define SCROLL_SENSITIVE 20 3205 3206 sal_Bool ScGridWindow::DropScroll( const Point& rMousePos ) 3207 { 3208 /* doch auch auf nicht aktiven Views... 3209 if ( !pViewData->IsActive() ) 3210 return sal_False; 3211 */ 3212 SCsCOL nDx = 0; 3213 SCsROW nDy = 0; 3214 Size aSize = GetOutputSizePixel(); 3215 3216 if (aSize.Width() > SCROLL_SENSITIVE * 3) 3217 { 3218 if ( rMousePos.X() < SCROLL_SENSITIVE && pViewData->GetPosX(WhichH(eWhich)) > 0 ) 3219 nDx = -1; 3220 if ( rMousePos.X() >= aSize.Width() - SCROLL_SENSITIVE 3221 && pViewData->GetPosX(WhichH(eWhich)) < MAXCOL ) 3222 nDx = 1; 3223 } 3224 if (aSize.Height() > SCROLL_SENSITIVE * 3) 3225 { 3226 if ( rMousePos.Y() < SCROLL_SENSITIVE && pViewData->GetPosY(WhichV(eWhich)) > 0 ) 3227 nDy = -1; 3228 if ( rMousePos.Y() >= aSize.Height() - SCROLL_SENSITIVE 3229 && pViewData->GetPosY(WhichV(eWhich)) < MAXROW ) 3230 nDy = 1; 3231 } 3232 3233 if ( nDx != 0 || nDy != 0 ) 3234 { 3235 // if (bDragRect) 3236 // pViewData->GetView()->DrawDragRect( nDragStartX, nDragStartY, nDragEndX, nDragEndY, eWhich ); 3237 3238 if ( nDx != 0 ) 3239 pViewData->GetView()->ScrollX( nDx, WhichH(eWhich) ); 3240 if ( nDy != 0 ) 3241 pViewData->GetView()->ScrollY( nDy, WhichV(eWhich) ); 3242 3243 // if (bDragRect) 3244 // pViewData->GetView()->DrawDragRect( nDragStartX, nDragStartY, nDragEndX, nDragEndY, eWhich ); 3245 } 3246 3247 return sal_False; 3248 } 3249 3250 sal_Bool lcl_TestScenarioRedliningDrop( ScDocument* pDoc, const ScRange& aDragRange) 3251 { 3252 // Testet, ob bei eingeschalteten RedLining, 3253 // bei einem Drop ein Scenario betroffen ist. 3254 3255 sal_Bool bReturn = sal_False; 3256 SCTAB nTab = aDragRange.aStart.Tab(); 3257 SCTAB nTabCount = pDoc->GetTableCount(); 3258 3259 if(pDoc->GetChangeTrack()!=NULL) 3260 { 3261 if( pDoc->IsScenario(nTab) && pDoc->HasScenarioRange(nTab, aDragRange)) 3262 { 3263 bReturn = sal_True; 3264 } 3265 else 3266 { 3267 for(SCTAB i=nTab+1; i<nTabCount && pDoc->IsScenario(i); i++) 3268 { 3269 if(pDoc->HasScenarioRange(i, aDragRange)) 3270 { 3271 bReturn = sal_True; 3272 break; 3273 } 3274 } 3275 } 3276 } 3277 return bReturn; 3278 } 3279 3280 ScRange lcl_MakeDropRange( SCCOL nPosX, SCROW nPosY, SCTAB nTab, const ScRange& rSource ) 3281 { 3282 SCCOL nCol1 = nPosX; 3283 SCCOL nCol2 = nCol1 + ( rSource.aEnd.Col() - rSource.aStart.Col() ); 3284 if ( nCol2 > MAXCOL ) 3285 { 3286 nCol1 -= nCol2 - MAXCOL; 3287 nCol2 = MAXCOL; 3288 } 3289 SCROW nRow1 = nPosY; 3290 SCROW nRow2 = nRow1 + ( rSource.aEnd.Row() - rSource.aStart.Row() ); 3291 if ( nRow2 > MAXROW ) 3292 { 3293 nRow1 -= nRow2 - MAXROW; 3294 nRow2 = MAXROW; 3295 } 3296 3297 return ScRange( nCol1, nRow1, nTab, nCol2, nRow2, nTab ); 3298 } 3299 3300 //-------------------------------------------------------- 3301 3302 extern sal_Bool bPasteIsDrop; // viewfun4 -> move to header 3303 extern sal_Bool bPasteIsMove; // viewfun7 -> move to header 3304 3305 //-------------------------------------------------------- 3306 3307 sal_Int8 ScGridWindow::AcceptPrivateDrop( const AcceptDropEvent& rEvt ) 3308 { 3309 if ( rEvt.mbLeaving ) 3310 { 3311 // if (bDragRect) 3312 // pViewData->GetView()->DrawDragRect( nDragStartX, nDragStartY, nDragEndX, nDragEndY, eWhich ); 3313 bDragRect = sal_False; 3314 UpdateDragRectOverlay(); 3315 return rEvt.mnAction; 3316 } 3317 3318 const ScDragData& rData = SC_MOD()->GetDragData(); 3319 if ( rData.pCellTransfer ) 3320 { 3321 // Don't move source that would include filtered rows. 3322 if ((rEvt.mnAction & DND_ACTION_MOVE) && rData.pCellTransfer->HasFilteredRows()) 3323 { 3324 if (bDragRect) 3325 { 3326 bDragRect = sal_False; 3327 UpdateDragRectOverlay(); 3328 } 3329 return DND_ACTION_NONE; 3330 } 3331 3332 Point aPos = rEvt.maPosPixel; 3333 3334 ScDocument* pSourceDoc = rData.pCellTransfer->GetSourceDocument(); 3335 ScDocument* pThisDoc = pViewData->GetDocument(); 3336 if (pSourceDoc == pThisDoc) 3337 { 3338 if ( pThisDoc->HasChartAtPoint(pViewData->GetTabNo(), PixelToLogic(aPos)) ) 3339 { 3340 if (bDragRect) // Rechteck löschen 3341 { 3342 // pViewData->GetView()->DrawDragRect( nDragStartX, nDragStartY, nDragEndX, nDragEndY, eWhich ); 3343 bDragRect = sal_False; 3344 UpdateDragRectOverlay(); 3345 } 3346 3347 //! highlight chart? (selection border?) 3348 3349 sal_Int8 nRet = rEvt.mnAction; 3350 //! if ( rEvt.GetAction() == DROP_LINK ) 3351 //! bOk = rEvt.SetAction( DROP_COPY ); // can't link onto chart 3352 return nRet; 3353 } 3354 } 3355 //! else 3356 //! if ( rEvt.GetAction() == DROP_MOVE ) 3357 //! rEvt.SetAction( DROP_COPY ); // different doc: default=COPY 3358 3359 if ( rData.pCellTransfer->GetDragSourceFlags() & SC_DROP_TABLE ) // whole sheet? 3360 { 3361 sal_Bool bOk = pThisDoc->IsDocEditable(); 3362 return bOk ? rEvt.mnAction : 0; // don't draw selection frame 3363 } 3364 3365 SCsCOL nPosX; 3366 SCsROW nPosY; 3367 pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY ); 3368 3369 ScRange aSourceRange = rData.pCellTransfer->GetRange(); 3370 SCCOL nSourceStartX = aSourceRange.aStart.Col(); 3371 SCROW nSourceStartY = aSourceRange.aStart.Row(); 3372 SCCOL nSourceEndX = aSourceRange.aEnd.Col(); 3373 SCROW nSourceEndY = aSourceRange.aEnd.Row(); 3374 SCCOL nSizeX = nSourceEndX - nSourceStartX + 1; 3375 SCROW nSizeY = nSourceEndY - nSourceStartY + 1; 3376 3377 if ( rEvt.mnAction != DND_ACTION_MOVE ) 3378 nSizeY = rData.pCellTransfer->GetNonFilteredRows(); // copy/link: no filtered rows 3379 3380 SCsCOL nNewDragX = nPosX - rData.pCellTransfer->GetDragHandleX(); 3381 if (nNewDragX<0) nNewDragX=0; 3382 if (nNewDragX+(nSizeX-1) > MAXCOL) 3383 nNewDragX = MAXCOL-(nSizeX-1); 3384 SCsROW nNewDragY = nPosY - rData.pCellTransfer->GetDragHandleY(); 3385 if (nNewDragY<0) nNewDragY=0; 3386 if (nNewDragY+(nSizeY-1) > MAXROW) 3387 nNewDragY = MAXROW-(nSizeY-1); 3388 3389 // don't break scenario ranges, don't drop on filtered 3390 SCTAB nTab = pViewData->GetTabNo(); 3391 ScRange aDropRange = lcl_MakeDropRange( nNewDragX, nNewDragY, nTab, aSourceRange ); 3392 if ( lcl_TestScenarioRedliningDrop( pThisDoc, aDropRange ) || 3393 lcl_TestScenarioRedliningDrop( pSourceDoc, aSourceRange ) || 3394 ScViewUtil::HasFiltered( aDropRange, pThisDoc) ) 3395 { 3396 if (bDragRect) 3397 { 3398 // pViewData->GetView()->DrawDragRect( nDragStartX, nDragStartY, nDragEndX, nDragEndY, eWhich ); 3399 bDragRect = sal_False; 3400 UpdateDragRectOverlay(); 3401 } 3402 return DND_ACTION_NONE; 3403 } 3404 3405 InsCellCmd eDragInsertMode = INS_NONE; 3406 Window::PointerState aState = GetPointerState(); 3407 3408 // check for datapilot item sorting 3409 ScDPObject* pDPObj = NULL; 3410 if ( pThisDoc == pSourceDoc && ( pDPObj = pThisDoc->GetDPAtCursor( nNewDragX, nNewDragY, nTab ) ) != NULL ) 3411 { 3412 // drop on DataPilot table: sort or nothing 3413 3414 bool bDPSort = false; 3415 if ( pThisDoc->GetDPAtCursor( nSourceStartX, nSourceStartY, aSourceRange.aStart.Tab() ) == pDPObj ) 3416 { 3417 sheet::DataPilotTableHeaderData aDestData; 3418 pDPObj->GetHeaderPositionData( ScAddress(nNewDragX, nNewDragY, nTab), aDestData ); 3419 bool bValid = ( aDestData.Dimension >= 0 ); // dropping onto a field 3420 3421 // look through the source range 3422 for (SCROW nRow = aSourceRange.aStart.Row(); bValid && nRow <= aSourceRange.aEnd.Row(); ++nRow ) 3423 for (SCCOL nCol = aSourceRange.aStart.Col(); bValid && nCol <= aSourceRange.aEnd.Col(); ++nCol ) 3424 { 3425 sheet::DataPilotTableHeaderData aSourceData; 3426 pDPObj->GetHeaderPositionData( ScAddress( nCol, nRow, aSourceRange.aStart.Tab() ), aSourceData ); 3427 if ( aSourceData.Dimension != aDestData.Dimension || !aSourceData.MemberName.getLength() ) 3428 bValid = false; // empty (subtotal) or different field 3429 } 3430 3431 if ( bValid ) 3432 { 3433 sal_Bool bIsDataLayout; 3434 String aDimName = pDPObj->GetDimName( aDestData.Dimension, bIsDataLayout ); 3435 const ScDPSaveDimension* pDim = pDPObj->GetSaveData()->GetExistingDimensionByName( aDimName ); 3436 if ( pDim ) 3437 { 3438 ScRange aOutRange = pDPObj->GetOutRange(); 3439 3440 sal_uInt16 nOrient = pDim->GetOrientation(); 3441 if ( nOrient == sheet::DataPilotFieldOrientation_COLUMN ) 3442 { 3443 eDragInsertMode = INS_CELLSRIGHT; 3444 nSizeY = aOutRange.aEnd.Row() - nNewDragY + 1; 3445 bDPSort = true; 3446 } 3447 else if ( nOrient == sheet::DataPilotFieldOrientation_ROW ) 3448 { 3449 eDragInsertMode = INS_CELLSDOWN; 3450 nSizeX = aOutRange.aEnd.Col() - nNewDragX + 1; 3451 bDPSort = true; 3452 } 3453 } 3454 } 3455 } 3456 3457 if ( !bDPSort ) 3458 { 3459 // no valid sorting in a DataPilot table -> disallow 3460 if ( bDragRect ) 3461 { 3462 bDragRect = sal_False; 3463 UpdateDragRectOverlay(); 3464 } 3465 return DND_ACTION_NONE; 3466 } 3467 } 3468 else if ( aState.mnState & KEY_MOD2 ) 3469 { 3470 if ( pThisDoc == pSourceDoc && nTab == aSourceRange.aStart.Tab() ) 3471 { 3472 long nDeltaX = labs( static_cast< long >( nNewDragX - nSourceStartX ) ); 3473 long nDeltaY = labs( static_cast< long >( nNewDragY - nSourceStartY ) ); 3474 if ( nDeltaX <= nDeltaY ) 3475 { 3476 eDragInsertMode = INS_CELLSDOWN; 3477 } 3478 else 3479 { 3480 eDragInsertMode = INS_CELLSRIGHT; 3481 } 3482 3483 if ( ( eDragInsertMode == INS_CELLSDOWN && nNewDragY <= nSourceEndY && 3484 ( nNewDragX + nSizeX - 1 ) >= nSourceStartX && nNewDragX <= nSourceEndX && 3485 ( nNewDragX != nSourceStartX || nNewDragY >= nSourceStartY ) ) || 3486 ( eDragInsertMode == INS_CELLSRIGHT && nNewDragX <= nSourceEndX && 3487 ( nNewDragY + nSizeY - 1 ) >= nSourceStartY && nNewDragY <= nSourceEndY && 3488 ( nNewDragY != nSourceStartY || nNewDragX >= nSourceStartX ) ) ) 3489 { 3490 if ( bDragRect ) 3491 { 3492 bDragRect = sal_False; 3493 UpdateDragRectOverlay(); 3494 } 3495 return DND_ACTION_NONE; 3496 } 3497 } 3498 else 3499 { 3500 if ( static_cast< long >( nSizeX ) >= static_cast< long >( nSizeY ) ) 3501 { 3502 eDragInsertMode = INS_CELLSDOWN; 3503 3504 } 3505 else 3506 { 3507 eDragInsertMode = INS_CELLSRIGHT; 3508 } 3509 } 3510 } 3511 3512 if ( nNewDragX != (SCsCOL) nDragStartX || nNewDragY != (SCsROW) nDragStartY || 3513 nDragStartX+nSizeX-1 != nDragEndX || nDragStartY+nSizeY-1 != nDragEndY || 3514 !bDragRect || eDragInsertMode != meDragInsertMode ) 3515 { 3516 // if (bDragRect) 3517 // pViewData->GetView()->DrawDragRect( nDragStartX, nDragStartY, nDragEndX, nDragEndY, eWhich ); 3518 3519 nDragStartX = nNewDragX; 3520 nDragStartY = nNewDragY; 3521 nDragEndX = nDragStartX+nSizeX-1; 3522 nDragEndY = nDragStartY+nSizeY-1; 3523 bDragRect = sal_True; 3524 meDragInsertMode = eDragInsertMode; 3525 3526 // pViewData->GetView()->DrawDragRect( nDragStartX, nDragStartY, nDragEndX, nDragEndY, eWhich ); 3527 3528 UpdateDragRectOverlay(); 3529 3530 // show target position as tip help 3531 #if 0 3532 if (Help::IsQuickHelpEnabled()) 3533 { 3534 ScRange aRange( nDragStartX, nDragStartY, nTab, nDragEndX, nDragEndY, nTab ); 3535 String aHelpStr; 3536 aRange.Format( aHelpStr, SCA_VALID ); // non-3D 3537 3538 Point aPos = Pointer::GetPosPixel(); 3539 sal_uInt16 nAlign = QUICKHELP_BOTTOM|QUICKHELP_RIGHT; 3540 Rectangle aRect( aPos, aPos ); 3541 Help::ShowQuickHelp(aRect, aHelpStr, nAlign); 3542 } 3543 #endif 3544 } 3545 } 3546 3547 return rEvt.mnAction; 3548 } 3549 3550 sal_Int8 ScGridWindow::AcceptDrop( const AcceptDropEvent& rEvt ) 3551 { 3552 const ScDragData& rData = SC_MOD()->GetDragData(); 3553 if ( rEvt.mbLeaving ) 3554 { 3555 DrawMarkDropObj( NULL ); 3556 if ( rData.pCellTransfer ) 3557 return AcceptPrivateDrop( rEvt ); // hide drop marker for internal D&D 3558 else 3559 return rEvt.mnAction; 3560 } 3561 3562 if ( pViewData->GetDocShell()->IsReadOnly() ) 3563 return DND_ACTION_NONE; 3564 3565 sal_Int8 nRet = DND_ACTION_NONE; 3566 3567 if (rData.pCellTransfer) 3568 { 3569 ScRange aSource = rData.pCellTransfer->GetRange(); 3570 if ( aSource.aStart.Col() != 0 || aSource.aEnd.Col() != MAXCOL || 3571 aSource.aStart.Row() != 0 || aSource.aEnd.Row() != MAXROW ) 3572 DropScroll( rEvt.maPosPixel ); 3573 3574 nRet = AcceptPrivateDrop( rEvt ); 3575 } 3576 else 3577 { 3578 if ( rData.aLinkDoc.Len() ) 3579 { 3580 String aThisName; 3581 ScDocShell* pDocSh = pViewData->GetDocShell(); 3582 if (pDocSh && pDocSh->HasName()) 3583 aThisName = pDocSh->GetMedium()->GetName(); 3584 3585 if ( rData.aLinkDoc != aThisName ) 3586 nRet = rEvt.mnAction; 3587 } 3588 else if (rData.aJumpTarget.Len()) 3589 { 3590 // internal bookmarks (from Navigator) 3591 // local jumps from an unnamed document are possible only within a document 3592 3593 if ( !rData.pJumpLocalDoc || rData.pJumpLocalDoc == pViewData->GetDocument() ) 3594 nRet = rEvt.mnAction; 3595 } 3596 else 3597 { 3598 sal_Int8 nMyAction = rEvt.mnAction; 3599 3600 // clear DND_ACTION_LINK when other actions are set. The usage below cannot handle 3601 // multiple set values 3602 if((nMyAction & DND_ACTION_LINK) && (nMyAction & (DND_ACTION_COPYMOVE))) 3603 { 3604 nMyAction &= ~DND_ACTION_LINK; 3605 } 3606 3607 if ( !rData.pDrawTransfer || 3608 !IsMyModel(rData.pDrawTransfer->GetDragSourceView()) ) // drawing within the document 3609 if ( rEvt.mbDefault && nMyAction == DND_ACTION_MOVE ) 3610 nMyAction = DND_ACTION_COPY; 3611 3612 ScDocument* pThisDoc = pViewData->GetDocument(); 3613 SdrObject* pHitObj = pThisDoc->GetObjectAtPoint( 3614 pViewData->GetTabNo(), PixelToLogic(rEvt.maPosPixel) ); 3615 if ( pHitObj && nMyAction == DND_ACTION_LINK ) // && !rData.pDrawTransfer ) 3616 { 3617 if ( IsDropFormatSupported(SOT_FORMATSTR_ID_SVXB) 3618 || IsDropFormatSupported(SOT_FORMAT_GDIMETAFILE) 3619 || IsDropFormatSupported(SOT_FORMATSTR_ID_PNG) 3620 || IsDropFormatSupported(SOT_FORMAT_BITMAP) ) 3621 { 3622 // graphic dragged onto drawing object 3623 DrawMarkDropObj( pHitObj ); 3624 nRet = nMyAction; 3625 } 3626 } 3627 if (!nRet) 3628 DrawMarkDropObj( NULL ); 3629 3630 if (!nRet) 3631 { 3632 switch ( nMyAction ) 3633 { 3634 case DND_ACTION_COPY: 3635 case DND_ACTION_MOVE: 3636 case DND_ACTION_COPYMOVE: 3637 { 3638 sal_Bool bMove = ( nMyAction == DND_ACTION_MOVE ); 3639 if ( IsDropFormatSupported( SOT_FORMATSTR_ID_EMBED_SOURCE ) || 3640 IsDropFormatSupported( SOT_FORMATSTR_ID_LINK_SOURCE ) || 3641 IsDropFormatSupported( SOT_FORMATSTR_ID_EMBED_SOURCE_OLE ) || 3642 IsDropFormatSupported( SOT_FORMATSTR_ID_LINK_SOURCE_OLE ) || 3643 IsDropFormatSupported( SOT_FORMATSTR_ID_EMBEDDED_OBJ_OLE ) || 3644 IsDropFormatSupported( SOT_FORMAT_STRING ) || 3645 IsDropFormatSupported( SOT_FORMATSTR_ID_SYLK ) || 3646 IsDropFormatSupported( SOT_FORMATSTR_ID_LINK ) || 3647 IsDropFormatSupported( SOT_FORMATSTR_ID_HTML ) || 3648 IsDropFormatSupported( SOT_FORMATSTR_ID_HTML_SIMPLE ) || 3649 IsDropFormatSupported( SOT_FORMATSTR_ID_DIF ) || 3650 IsDropFormatSupported( SOT_FORMATSTR_ID_DRAWING ) || 3651 IsDropFormatSupported( SOT_FORMATSTR_ID_SVXB ) || 3652 IsDropFormatSupported( SOT_FORMAT_RTF ) || 3653 IsDropFormatSupported( SOT_FORMAT_GDIMETAFILE ) || 3654 IsDropFormatSupported( SOT_FORMATSTR_ID_PNG ) || 3655 IsDropFormatSupported( SOT_FORMAT_BITMAP ) || 3656 IsDropFormatSupported( SOT_FORMATSTR_ID_SBA_DATAEXCHANGE ) || 3657 IsDropFormatSupported( SOT_FORMATSTR_ID_SBA_FIELDDATAEXCHANGE ) || 3658 ( !bMove && ( 3659 IsDropFormatSupported( SOT_FORMAT_FILE_LIST ) || 3660 IsDropFormatSupported( SOT_FORMAT_FILE ) || 3661 IsDropFormatSupported( SOT_FORMATSTR_ID_SOLK ) || 3662 IsDropFormatSupported( SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR ) || 3663 IsDropFormatSupported( SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK ) || 3664 IsDropFormatSupported( SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR ) ) ) ) 3665 { 3666 nRet = nMyAction; 3667 } 3668 } 3669 break; 3670 case DND_ACTION_LINK: 3671 if ( IsDropFormatSupported( SOT_FORMATSTR_ID_LINK_SOURCE ) || 3672 IsDropFormatSupported( SOT_FORMATSTR_ID_LINK_SOURCE_OLE ) || 3673 IsDropFormatSupported( SOT_FORMATSTR_ID_LINK ) || 3674 IsDropFormatSupported( SOT_FORMAT_FILE_LIST ) || 3675 IsDropFormatSupported( SOT_FORMAT_FILE ) || 3676 IsDropFormatSupported( SOT_FORMATSTR_ID_SOLK ) || 3677 IsDropFormatSupported( SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR ) || 3678 IsDropFormatSupported( SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK ) || 3679 IsDropFormatSupported( SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR ) ) 3680 { 3681 nRet = nMyAction; 3682 } 3683 break; 3684 } 3685 3686 if ( nRet ) 3687 { 3688 // Simple check for protection: It's not known here if the drop will result 3689 // in cells or drawing objects (some formats can be both) and how many cells 3690 // the result will be. But if IsFormatEditable for the drop cell position 3691 // is sal_False (ignores matrix formulas), nothing can be pasted, so the drop 3692 // can already be rejected here. 3693 3694 Point aPos = rEvt.maPosPixel; 3695 SCsCOL nPosX; 3696 SCsROW nPosY; 3697 pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY ); 3698 SCTAB nTab = pViewData->GetTabNo(); 3699 ScDocument* pDoc = pViewData->GetDocument(); 3700 3701 ScEditableTester aTester( pDoc, nTab, nPosX,nPosY, nPosX,nPosY ); 3702 if ( !aTester.IsFormatEditable() ) 3703 nRet = DND_ACTION_NONE; // forbidden 3704 } 3705 } 3706 } 3707 3708 // scroll only for accepted formats 3709 if (nRet) 3710 DropScroll( rEvt.maPosPixel ); 3711 } 3712 3713 return nRet; 3714 } 3715 3716 sal_uLong lcl_GetDropFormatId( const uno::Reference<datatransfer::XTransferable>& xTransfer, bool bPreferText = false ) 3717 { 3718 TransferableDataHelper aDataHelper( xTransfer ); 3719 3720 if ( !aDataHelper.HasFormat( SOT_FORMATSTR_ID_SBA_DATAEXCHANGE ) ) 3721 { 3722 // use bookmark formats if no sba is present 3723 3724 if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_SOLK ) ) 3725 return SOT_FORMATSTR_ID_SOLK; 3726 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR ) ) 3727 return SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR; 3728 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK ) ) 3729 return SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK; 3730 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR ) ) 3731 return SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR; 3732 } 3733 3734 sal_uLong nFormatId = 0; 3735 if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_DRAWING ) ) 3736 nFormatId = SOT_FORMATSTR_ID_DRAWING; 3737 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_SVXB ) ) 3738 nFormatId = SOT_FORMATSTR_ID_SVXB; 3739 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_EMBED_SOURCE ) ) 3740 { 3741 // If it's a Writer object, insert RTF instead of OLE 3742 3743 sal_Bool bDoRtf = sal_False; 3744 SotStorageStreamRef xStm; 3745 TransferableObjectDescriptor aObjDesc; 3746 if( aDataHelper.GetTransferableObjectDescriptor( SOT_FORMATSTR_ID_OBJECTDESCRIPTOR, aObjDesc ) && 3747 aDataHelper.GetSotStorageStream( SOT_FORMATSTR_ID_EMBED_SOURCE, xStm ) ) 3748 { 3749 SotStorageRef xStore( new SotStorage( *xStm ) ); 3750 bDoRtf = ( ( aObjDesc.maClassName == SvGlobalName( SO3_SW_CLASSID ) || 3751 aObjDesc.maClassName == SvGlobalName( SO3_SWWEB_CLASSID ) ) 3752 && aDataHelper.HasFormat( SOT_FORMAT_RTF ) ); 3753 } 3754 if ( bDoRtf ) 3755 nFormatId = FORMAT_RTF; 3756 else 3757 nFormatId = SOT_FORMATSTR_ID_EMBED_SOURCE; 3758 } 3759 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_LINK_SOURCE ) ) 3760 nFormatId = SOT_FORMATSTR_ID_LINK_SOURCE; 3761 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_SBA_DATAEXCHANGE ) ) 3762 nFormatId = SOT_FORMATSTR_ID_SBA_DATAEXCHANGE; 3763 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_SBA_FIELDDATAEXCHANGE ) ) 3764 nFormatId = SOT_FORMATSTR_ID_SBA_FIELDDATAEXCHANGE; 3765 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_BIFF_8 ) ) 3766 nFormatId = SOT_FORMATSTR_ID_BIFF_8; 3767 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_BIFF_5 ) ) 3768 nFormatId = SOT_FORMATSTR_ID_BIFF_5; 3769 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_EMBED_SOURCE_OLE ) ) 3770 nFormatId = SOT_FORMATSTR_ID_EMBED_SOURCE_OLE; 3771 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_EMBEDDED_OBJ_OLE ) ) 3772 nFormatId = SOT_FORMATSTR_ID_EMBEDDED_OBJ_OLE; 3773 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_LINK_SOURCE_OLE ) ) 3774 nFormatId = SOT_FORMATSTR_ID_LINK_SOURCE_OLE; 3775 else if ( aDataHelper.HasFormat( SOT_FORMAT_RTF ) ) 3776 nFormatId = SOT_FORMAT_RTF; 3777 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_HTML ) ) 3778 nFormatId = SOT_FORMATSTR_ID_HTML; 3779 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_HTML_SIMPLE ) ) 3780 nFormatId = SOT_FORMATSTR_ID_HTML_SIMPLE; 3781 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_SYLK ) ) 3782 nFormatId = SOT_FORMATSTR_ID_SYLK; 3783 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_LINK ) ) 3784 nFormatId = SOT_FORMATSTR_ID_LINK; 3785 else if ( bPreferText && aDataHelper.HasFormat( SOT_FORMAT_STRING ) ) // #i86734# the behaviour introduced in #i62773# is wrong when pasting 3786 nFormatId = SOT_FORMAT_STRING; 3787 else if ( aDataHelper.HasFormat( SOT_FORMAT_FILE_LIST ) ) 3788 nFormatId = SOT_FORMAT_FILE_LIST; 3789 else if ( aDataHelper.HasFormat( SOT_FORMAT_FILE ) ) // #i62773# FILE_LIST/FILE before STRING (Unix file managers) 3790 nFormatId = SOT_FORMAT_FILE; 3791 else if ( aDataHelper.HasFormat( SOT_FORMAT_STRING ) ) 3792 nFormatId = SOT_FORMAT_STRING; 3793 else if ( aDataHelper.HasFormat( SOT_FORMAT_GDIMETAFILE ) ) 3794 nFormatId = SOT_FORMAT_GDIMETAFILE; 3795 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_PNG ) ) 3796 nFormatId = SOT_FORMATSTR_ID_PNG; 3797 else if ( aDataHelper.HasFormat( SOT_FORMAT_BITMAP ) ) 3798 nFormatId = SOT_FORMAT_BITMAP; 3799 3800 return nFormatId; 3801 } 3802 3803 sal_uLong lcl_GetDropLinkId( const uno::Reference<datatransfer::XTransferable>& xTransfer ) 3804 { 3805 TransferableDataHelper aDataHelper( xTransfer ); 3806 3807 sal_uLong nFormatId = 0; 3808 if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_LINK_SOURCE ) ) 3809 nFormatId = SOT_FORMATSTR_ID_LINK_SOURCE; 3810 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_LINK_SOURCE_OLE ) ) 3811 nFormatId = SOT_FORMATSTR_ID_LINK_SOURCE_OLE; 3812 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_LINK ) ) 3813 nFormatId = SOT_FORMATSTR_ID_LINK; 3814 else if ( aDataHelper.HasFormat( SOT_FORMAT_FILE_LIST ) ) 3815 nFormatId = SOT_FORMAT_FILE_LIST; 3816 else if ( aDataHelper.HasFormat( SOT_FORMAT_FILE ) ) 3817 nFormatId = SOT_FORMAT_FILE; 3818 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_SOLK ) ) 3819 nFormatId = SOT_FORMATSTR_ID_SOLK; 3820 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR ) ) 3821 nFormatId = SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR; 3822 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK ) ) 3823 nFormatId = SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK; 3824 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR ) ) 3825 nFormatId = SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR; 3826 3827 return nFormatId; 3828 } 3829 3830 sal_Int8 ScGridWindow::ExecutePrivateDrop( const ExecuteDropEvent& rEvt ) 3831 { 3832 // hide drop marker 3833 // if (bDragRect) 3834 // pViewData->GetView()->DrawDragRect( nDragStartX, nDragStartY, nDragEndX, nDragEndY, eWhich ); 3835 bDragRect = sal_False; 3836 UpdateDragRectOverlay(); 3837 3838 ScModule* pScMod = SC_MOD(); 3839 const ScDragData& rData = pScMod->GetDragData(); 3840 3841 return DropTransferObj( rData.pCellTransfer, nDragStartX, nDragStartY, 3842 PixelToLogic(rEvt.maPosPixel), rEvt.mnAction ); 3843 } 3844 3845 sal_Int8 ScGridWindow::DropTransferObj( ScTransferObj* pTransObj, SCCOL nDestPosX, SCROW nDestPosY, 3846 const Point& rLogicPos, sal_Int8 nDndAction ) 3847 { 3848 if ( !pTransObj ) 3849 return 0; 3850 3851 ScDocument* pSourceDoc = pTransObj->GetSourceDocument(); 3852 ScDocShell* pDocSh = pViewData->GetDocShell(); 3853 ScDocument* pThisDoc = pViewData->GetDocument(); 3854 ScViewFunc* pView = pViewData->GetView(); 3855 SCTAB nThisTab = pViewData->GetTabNo(); 3856 sal_uInt16 nFlags = pTransObj->GetDragSourceFlags(); 3857 3858 sal_Bool bIsNavi = ( nFlags & SC_DROP_NAVIGATOR ) != 0; 3859 sal_Bool bIsMove = ( nDndAction == DND_ACTION_MOVE && !bIsNavi ); 3860 3861 // workaround for wrong nDndAction on Windows when pressing solely 3862 // the Alt key during drag and drop; 3863 // can be removed after #i79215# has been fixed 3864 if ( meDragInsertMode != INS_NONE ) 3865 { 3866 bIsMove = ( nDndAction & DND_ACTION_MOVE && !bIsNavi ); 3867 } 3868 3869 sal_Bool bIsLink = ( nDndAction == DND_ACTION_LINK ); 3870 3871 ScRange aSource = pTransObj->GetRange(); 3872 3873 // only use visible tab from source range - when dragging within one table, 3874 // all selected tables at the time of dropping are used (handled in MoveBlockTo) 3875 SCTAB nSourceTab = pTransObj->GetVisibleTab(); 3876 aSource.aStart.SetTab( nSourceTab ); 3877 aSource.aEnd.SetTab( nSourceTab ); 3878 3879 SCCOL nSizeX = aSource.aEnd.Col() - aSource.aStart.Col() + 1; 3880 SCROW nSizeY = (bIsMove ? (aSource.aEnd.Row() - aSource.aStart.Row() + 1) : 3881 pTransObj->GetNonFilteredRows()); // copy/link: no filtered rows 3882 ScRange aDest( nDestPosX, nDestPosY, nThisTab, 3883 nDestPosX + nSizeX - 1, nDestPosY + nSizeY - 1, nThisTab ); 3884 3885 /* NOTE: AcceptPrivateDrop() already checked for filtered conditions during 3886 * dragging and adapted drawing of the selection frame. We check here 3887 * (again) because this may actually also be called from PasteSelection(), 3888 * we would have to duplicate determination of flags and destination range 3889 * and would lose the context of the "filtered destination is OK" cases 3890 * below, which is already awkward enough as is. */ 3891 3892 // Don't move filtered source. 3893 bool bFiltered = (bIsMove && pTransObj->HasFilteredRows()); 3894 if (!bFiltered) 3895 { 3896 if (pSourceDoc != pThisDoc && ((nFlags & SC_DROP_TABLE) || 3897 (!bIsLink && meDragInsertMode == INS_NONE))) 3898 { 3899 // Nothing. Either entire sheet to be dropped, or the one case 3900 // where PasteFromClip() is to be called that handles a filtered 3901 // destination itself. Drag-copy from another document without 3902 // inserting cells. 3903 } 3904 else 3905 // Don't copy or move to filtered destination. 3906 bFiltered = ScViewUtil::HasFiltered( aDest, pThisDoc); 3907 } 3908 3909 sal_Bool bDone = sal_False; 3910 3911 if (!bFiltered && pSourceDoc == pThisDoc) 3912 { 3913 if ( nFlags & SC_DROP_TABLE ) // whole sheet? 3914 { 3915 if ( pThisDoc->IsDocEditable() ) 3916 { 3917 SCTAB nSrcTab = aSource.aStart.Tab(); 3918 pViewData->GetDocShell()->MoveTable( nSrcTab, nThisTab, !bIsMove, sal_True ); // with Undo 3919 pView->SetTabNo( nThisTab, sal_True ); 3920 bDone = sal_True; 3921 } 3922 } 3923 else // move/copy block 3924 { 3925 String aChartName; 3926 if (pThisDoc->HasChartAtPoint( nThisTab, rLogicPos, &aChartName )) 3927 { 3928 String aRangeName; 3929 aSource.Format( aRangeName, SCR_ABS_3D, pThisDoc ); 3930 SfxStringItem aNameItem( SID_CHART_NAME, aChartName ); 3931 SfxStringItem aRangeItem( SID_CHART_SOURCE, aRangeName ); 3932 sal_uInt16 nId = bIsMove ? SID_CHART_SOURCE : SID_CHART_ADDSOURCE; 3933 pViewData->GetDispatcher().Execute( nId, SFX_CALLMODE_ASYNCHRON | SFX_CALLMODE_RECORD, 3934 &aRangeItem, &aNameItem, (void*) NULL ); 3935 bDone = sal_True; 3936 } 3937 else if ( pThisDoc->GetDPAtCursor( nDestPosX, nDestPosY, nThisTab ) ) 3938 { 3939 // drop on DataPilot table: try to sort, fail if that isn't possible 3940 3941 ScAddress aDestPos( nDestPosX, nDestPosY, nThisTab ); 3942 if ( aDestPos != aSource.aStart ) 3943 bDone = pViewData->GetView()->DataPilotMove( aSource, aDestPos ); 3944 else 3945 bDone = sal_True; // same position: nothing 3946 } 3947 else if ( nDestPosX != aSource.aStart.Col() || nDestPosY != aSource.aStart.Row() || 3948 nSourceTab != nThisTab ) 3949 { 3950 String aUndo = ScGlobal::GetRscString( bIsMove ? STR_UNDO_MOVE : STR_UNDO_COPY ); 3951 pDocSh->GetUndoManager()->EnterListAction( aUndo, aUndo ); 3952 3953 bDone = sal_True; 3954 if ( meDragInsertMode != INS_NONE ) 3955 { 3956 // call with bApi = sal_True to avoid error messages in drop handler 3957 bDone = pDocSh->GetDocFunc().InsertCells( aDest, NULL, meDragInsertMode, sal_True /*bRecord*/, sal_True /*bApi*/, sal_True /*bPartOfPaste*/ ); 3958 if ( bDone ) 3959 { 3960 if ( nThisTab == nSourceTab ) 3961 { 3962 if ( meDragInsertMode == INS_CELLSDOWN && 3963 nDestPosX == aSource.aStart.Col() && nDestPosY < aSource.aStart.Row() ) 3964 { 3965 bDone = aSource.Move( 0, nSizeY, 0, pSourceDoc ); 3966 } 3967 else if ( meDragInsertMode == INS_CELLSRIGHT && 3968 nDestPosY == aSource.aStart.Row() && nDestPosX < aSource.aStart.Col() ) 3969 { 3970 bDone = aSource.Move( nSizeX, 0, 0, pSourceDoc ); 3971 } 3972 } 3973 pDocSh->UpdateOle( pViewData ); 3974 pView->CellContentChanged(); 3975 } 3976 } 3977 3978 if ( bDone ) 3979 { 3980 if ( bIsLink ) 3981 { 3982 // call with bApi = sal_True to avoid error messages in drop handler 3983 bDone = pView->LinkBlock( aSource, aDest.aStart, sal_True /*bApi*/ ); 3984 } 3985 else 3986 { 3987 // call with bApi = sal_True to avoid error messages in drop handler 3988 bDone = pView->MoveBlockTo( aSource, aDest.aStart, bIsMove, sal_True /*bRecord*/, sal_True /*bPaint*/, sal_True /*bApi*/ ); 3989 } 3990 } 3991 3992 if ( bDone && meDragInsertMode != INS_NONE && bIsMove && nThisTab == nSourceTab ) 3993 { 3994 DelCellCmd eCmd = DEL_NONE; 3995 if ( meDragInsertMode == INS_CELLSDOWN ) 3996 { 3997 eCmd = DEL_CELLSUP; 3998 } 3999 else if ( meDragInsertMode == INS_CELLSRIGHT ) 4000 { 4001 eCmd = DEL_CELLSLEFT; 4002 } 4003 4004 if ( ( eCmd == DEL_CELLSUP && nDestPosX == aSource.aStart.Col() ) || 4005 ( eCmd == DEL_CELLSLEFT && nDestPosY == aSource.aStart.Row() ) ) 4006 { 4007 // call with bApi = sal_True to avoid error messages in drop handler 4008 bDone = pDocSh->GetDocFunc().DeleteCells( aSource, NULL, eCmd, sal_True /*bRecord*/, sal_True /*bApi*/ ); 4009 if ( bDone ) 4010 { 4011 if ( eCmd == DEL_CELLSUP && nDestPosY > aSource.aEnd.Row() ) 4012 { 4013 bDone = aDest.Move( 0, -nSizeY, 0, pThisDoc ); 4014 } 4015 else if ( eCmd == DEL_CELLSLEFT && nDestPosX > aSource.aEnd.Col() ) 4016 { 4017 bDone = aDest.Move( -nSizeX, 0, 0, pThisDoc ); 4018 } 4019 pDocSh->UpdateOle( pViewData ); 4020 pView->CellContentChanged(); 4021 } 4022 } 4023 } 4024 4025 if ( bDone ) 4026 { 4027 pView->MarkRange( aDest, sal_False, sal_False ); 4028 pView->SetCursor( aDest.aEnd.Col(), aDest.aEnd.Row() ); 4029 } 4030 4031 pDocSh->GetUndoManager()->LeaveListAction(); 4032 4033 if (!bDone) 4034 Sound::Beep(); // instead of error message in drop handler 4035 } 4036 else 4037 bDone = sal_True; // nothing to do 4038 } 4039 4040 if (bDone) 4041 pTransObj->SetDragWasInternal(); // don't delete source in DragFinished 4042 } 4043 else if ( !bFiltered && pSourceDoc ) // between documents 4044 { 4045 if ( nFlags & SC_DROP_TABLE ) // copy/link sheets between documents 4046 { 4047 if ( pThisDoc->IsDocEditable() ) 4048 { 4049 ScDocShell* pSrcShell = pTransObj->GetSourceDocShell(); 4050 4051 SCTAB nTabs[MAXTABCOUNT]; 4052 4053 ScMarkData aMark = pTransObj->GetSourceMarkData(); 4054 SCTAB nTabCount = pSourceDoc->GetTableCount(); 4055 SCTAB nTabSelCount = 0; 4056 4057 for(SCTAB i=0; i<nTabCount; i++) 4058 { 4059 if(aMark.GetTableSelect(i)) 4060 { 4061 nTabs[nTabSelCount++]=i; 4062 for(SCTAB j=i+1;j<nTabCount;j++) 4063 { 4064 if((!pSourceDoc->IsVisible(j))&&(pSourceDoc->IsScenario(j))) 4065 { 4066 nTabs[nTabSelCount++]=j; 4067 i=j; 4068 } 4069 else break; 4070 } 4071 } 4072 } 4073 4074 pView->ImportTables( pSrcShell,nTabSelCount, nTabs, bIsLink, nThisTab ); 4075 bDone = sal_True; 4076 } 4077 } 4078 else if ( bIsLink ) 4079 { 4080 // as in PasteDDE 4081 // (external references might be used instead?) 4082 4083 SfxObjectShell* pSourceSh = pSourceDoc->GetDocumentShell(); 4084 DBG_ASSERT(pSourceSh, "drag document has no shell"); 4085 if (pSourceSh) 4086 { 4087 String aUndo = ScGlobal::GetRscString( STR_UNDO_COPY ); 4088 pDocSh->GetUndoManager()->EnterListAction( aUndo, aUndo ); 4089 4090 bDone = sal_True; 4091 if ( meDragInsertMode != INS_NONE ) 4092 { 4093 // call with bApi = sal_True to avoid error messages in drop handler 4094 bDone = pDocSh->GetDocFunc().InsertCells( aDest, NULL, meDragInsertMode, sal_True /*bRecord*/, sal_True /*bApi*/, sal_True /*bPartOfPaste*/ ); 4095 if ( bDone ) 4096 { 4097 pDocSh->UpdateOle( pViewData ); 4098 pView->CellContentChanged(); 4099 } 4100 } 4101 4102 if ( bDone ) 4103 { 4104 String aApp = Application::GetAppName(); 4105 String aTopic = pSourceSh->GetTitle( SFX_TITLE_FULLNAME ); 4106 String aItem; 4107 aSource.Format( aItem, SCA_VALID | SCA_TAB_3D, pSourceDoc ); 4108 4109 // TODO: we could define ocQuote for " 4110 const String aQuote( '"' ); 4111 const String& sSep = ScCompiler::GetNativeSymbol( ocSep); 4112 String aFormula( '=' ); 4113 aFormula += ScCompiler::GetNativeSymbol( ocDde); 4114 aFormula += ScCompiler::GetNativeSymbol( ocOpen); 4115 aFormula += aQuote; 4116 aFormula += aApp; 4117 aFormula += aQuote; 4118 aFormula += sSep; 4119 aFormula += aQuote; 4120 aFormula += aTopic; 4121 aFormula += aQuote; 4122 aFormula += sSep; 4123 aFormula += aQuote; 4124 aFormula += aItem; 4125 aFormula += aQuote; 4126 aFormula += ScCompiler::GetNativeSymbol( ocClose); 4127 4128 pView->DoneBlockMode(); 4129 pView->InitBlockMode( nDestPosX, nDestPosY, nThisTab ); 4130 pView->MarkCursor( nDestPosX + nSizeX - 1, 4131 nDestPosY + nSizeY - 1, nThisTab ); 4132 4133 pView->EnterMatrix( aFormula ); 4134 4135 pView->MarkRange( aDest, sal_False, sal_False ); 4136 pView->SetCursor( aDest.aEnd.Col(), aDest.aEnd.Row() ); 4137 } 4138 4139 pDocSh->GetUndoManager()->LeaveListAction(); 4140 } 4141 } 4142 else 4143 { 4144 //! HasSelectedBlockMatrixFragment without selected sheet? 4145 //! or don't start dragging on a part of a matrix 4146 4147 String aUndo = ScGlobal::GetRscString( bIsMove ? STR_UNDO_MOVE : STR_UNDO_COPY ); 4148 pDocSh->GetUndoManager()->EnterListAction( aUndo, aUndo ); 4149 4150 bDone = sal_True; 4151 if ( meDragInsertMode != INS_NONE ) 4152 { 4153 // call with bApi = sal_True to avoid error messages in drop handler 4154 bDone = pDocSh->GetDocFunc().InsertCells( aDest, NULL, meDragInsertMode, sal_True /*bRecord*/, sal_True /*bApi*/, sal_True /*bPartOfPaste*/ ); 4155 if ( bDone ) 4156 { 4157 pDocSh->UpdateOle( pViewData ); 4158 pView->CellContentChanged(); 4159 } 4160 } 4161 4162 if ( bDone ) 4163 { 4164 pView->Unmark(); // before SetCursor, so CheckSelectionTransfer isn't called with a selection 4165 pView->SetCursor( nDestPosX, nDestPosY ); 4166 bDone = pView->PasteFromClip( IDF_ALL, pTransObj->GetDocument() ); // clip-doc 4167 if ( bDone ) 4168 { 4169 pView->MarkRange( aDest, sal_False, sal_False ); 4170 pView->SetCursor( aDest.aEnd.Col(), aDest.aEnd.Row() ); 4171 } 4172 } 4173 4174 pDocSh->GetUndoManager()->LeaveListAction(); 4175 4176 // no longer call ResetMark here - the inserted block has been selected 4177 // and may have been copied to primary selection 4178 } 4179 } 4180 4181 sal_Int8 nRet = bDone ? nDndAction : DND_ACTION_NONE; 4182 return nRet; 4183 } 4184 4185 sal_Int8 ScGridWindow::ExecuteDrop( const ExecuteDropEvent& rEvt ) 4186 { 4187 DrawMarkDropObj( NULL ); // drawing layer 4188 4189 ScModule* pScMod = SC_MOD(); 4190 const ScDragData& rData = pScMod->GetDragData(); 4191 if (rData.pCellTransfer) 4192 return ExecutePrivateDrop( rEvt ); 4193 4194 Point aPos = rEvt.maPosPixel; 4195 4196 if ( rData.aLinkDoc.Len() ) 4197 { 4198 // try to insert a link 4199 4200 sal_Bool bOk = sal_True; 4201 String aThisName; 4202 ScDocShell* pDocSh = pViewData->GetDocShell(); 4203 if (pDocSh && pDocSh->HasName()) 4204 aThisName = pDocSh->GetMedium()->GetName(); 4205 4206 if ( rData.aLinkDoc == aThisName ) // error - no link within a document 4207 bOk = sal_False; 4208 else 4209 { 4210 ScViewFunc* pView = pViewData->GetView(); 4211 if ( rData.aLinkTable.Len() ) 4212 pView->InsertTableLink( rData.aLinkDoc, EMPTY_STRING, EMPTY_STRING, 4213 rData.aLinkTable ); 4214 else if ( rData.aLinkArea.Len() ) 4215 { 4216 SCsCOL nPosX; 4217 SCsROW nPosY; 4218 pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY ); 4219 pView->MoveCursorAbs( nPosX, nPosY, SC_FOLLOW_NONE, sal_False, sal_False ); 4220 4221 pView->InsertAreaLink( rData.aLinkDoc, EMPTY_STRING, EMPTY_STRING, 4222 rData.aLinkArea, 0 ); 4223 } 4224 else 4225 { 4226 DBG_ERROR("drop with link: no sheet nor area"); 4227 bOk = sal_False; 4228 } 4229 } 4230 4231 return bOk ? rEvt.mnAction : DND_ACTION_NONE; // don't try anything else 4232 } 4233 4234 Point aLogicPos = PixelToLogic(aPos); 4235 sal_Bool bIsLink = ( rEvt.mnAction == DND_ACTION_LINK ); 4236 4237 if (!bIsLink && rData.pDrawTransfer) 4238 { 4239 sal_uInt16 nFlags = rData.pDrawTransfer->GetDragSourceFlags(); 4240 4241 sal_Bool bIsNavi = ( nFlags & SC_DROP_NAVIGATOR ) != 0; 4242 sal_Bool bIsMove = ( rEvt.mnAction == DND_ACTION_MOVE && !bIsNavi ); 4243 4244 bPasteIsMove = bIsMove; 4245 4246 pViewData->GetView()->PasteDraw( aLogicPos, rData.pDrawTransfer->GetModel() ); 4247 4248 if (bPasteIsMove) 4249 rData.pDrawTransfer->SetDragWasInternal(); 4250 bPasteIsMove = sal_False; 4251 4252 return rEvt.mnAction; 4253 } 4254 4255 SCsCOL nPosX; 4256 SCsROW nPosY; 4257 pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY ); 4258 4259 if (rData.aJumpTarget.Len()) 4260 { 4261 // internal bookmark (from Navigator) 4262 // bookmark clipboard formats are in PasteScDataObject 4263 4264 if ( !rData.pJumpLocalDoc || rData.pJumpLocalDoc == pViewData->GetDocument() ) 4265 { 4266 pViewData->GetViewShell()->InsertBookmark( rData.aJumpText, rData.aJumpTarget, 4267 nPosX, nPosY ); 4268 return rEvt.mnAction; 4269 } 4270 } 4271 4272 ScDocument* pThisDoc = pViewData->GetDocument(); 4273 SdrObject* pHitObj = pThisDoc->GetObjectAtPoint( pViewData->GetTabNo(), PixelToLogic(aPos) ); 4274 if ( pHitObj && bIsLink ) 4275 { 4276 // dropped on drawing object 4277 // PasteOnDrawObjectLinked checks for valid formats 4278 if ( pViewData->GetView()->PasteOnDrawObjectLinked( rEvt.maDropEvent.Transferable, *pHitObj ) ) 4279 return rEvt.mnAction; 4280 } 4281 4282 sal_Bool bDone = sal_False; 4283 4284 sal_uLong nFormatId = bIsLink ? 4285 lcl_GetDropLinkId( rEvt.maDropEvent.Transferable ) : 4286 lcl_GetDropFormatId( rEvt.maDropEvent.Transferable ); 4287 if ( nFormatId ) 4288 { 4289 pScMod->SetInExecuteDrop( sal_True ); // #i28468# prevent error messages from PasteDataFormat 4290 bPasteIsDrop = sal_True; 4291 bDone = pViewData->GetView()->PasteDataFormat( 4292 nFormatId, rEvt.maDropEvent.Transferable, nPosX, nPosY, &aLogicPos, bIsLink ); 4293 bPasteIsDrop = sal_False; 4294 pScMod->SetInExecuteDrop( sal_False ); 4295 } 4296 4297 sal_Int8 nRet = bDone ? rEvt.mnAction : DND_ACTION_NONE; 4298 return nRet; 4299 } 4300 4301 //-------------------------------------------------------- 4302 4303 void ScGridWindow::PasteSelection( const Point& rPosPixel ) 4304 { 4305 Point aLogicPos = PixelToLogic( rPosPixel ); 4306 4307 SCsCOL nPosX; 4308 SCsROW nPosY; 4309 pViewData->GetPosFromPixel( rPosPixel.X(), rPosPixel.Y(), eWhich, nPosX, nPosY ); 4310 4311 ScSelectionTransferObj* pOwnSelection = SC_MOD()->GetSelectionTransfer(); 4312 if ( pOwnSelection ) 4313 { 4314 // within Calc 4315 4316 ScTransferObj* pCellTransfer = pOwnSelection->GetCellData(); 4317 if ( pCellTransfer ) 4318 { 4319 // keep a reference to the data in case the selection is changed during paste 4320 uno::Reference<datatransfer::XTransferable> xRef( pCellTransfer ); 4321 DropTransferObj( pCellTransfer, nPosX, nPosY, aLogicPos, DND_ACTION_COPY ); 4322 } 4323 else 4324 { 4325 ScDrawTransferObj* pDrawTransfer = pOwnSelection->GetDrawData(); 4326 if ( pDrawTransfer ) 4327 { 4328 // keep a reference to the data in case the selection is changed during paste 4329 uno::Reference<datatransfer::XTransferable> xRef( pDrawTransfer ); 4330 4331 // #96821# bSameDocClipboard argument for PasteDraw is needed 4332 // because only DragData is checked directly inside PasteDraw 4333 pViewData->GetView()->PasteDraw( aLogicPos, pDrawTransfer->GetModel(), sal_False, 4334 pDrawTransfer->GetSourceDocID() == pViewData->GetDocument()->GetDocumentID() ); 4335 } 4336 } 4337 } 4338 else 4339 { 4340 // get selection from system 4341 4342 TransferableDataHelper aDataHelper( TransferableDataHelper::CreateFromSelection( this ) ); 4343 uno::Reference<datatransfer::XTransferable> xTransferable = aDataHelper.GetTransferable(); 4344 if ( xTransferable.is() ) 4345 { 4346 sal_uLong nFormatId = lcl_GetDropFormatId( xTransferable, true ); 4347 if ( nFormatId ) 4348 { 4349 bPasteIsDrop = sal_True; 4350 pViewData->GetView()->PasteDataFormat( nFormatId, xTransferable, nPosX, nPosY, &aLogicPos ); 4351 bPasteIsDrop = sal_False; 4352 } 4353 } 4354 } 4355 } 4356 4357 //-------------------------------------------------------- 4358 4359 void ScGridWindow::UpdateEditViewPos() 4360 { 4361 if (pViewData->HasEditView(eWhich)) 4362 { 4363 EditView* pView; 4364 SCCOL nCol; 4365 SCROW nRow; 4366 pViewData->GetEditView( eWhich, pView, nCol, nRow ); 4367 SCCOL nEndCol = pViewData->GetEditEndCol(); 4368 SCROW nEndRow = pViewData->GetEditEndRow(); 4369 4370 // hide EditView? 4371 4372 sal_Bool bHide = ( nEndCol<pViewData->GetPosX(eHWhich) || nEndRow<pViewData->GetPosY(eVWhich) ); 4373 if ( SC_MOD()->IsFormulaMode() ) 4374 if ( pViewData->GetTabNo() != pViewData->GetRefTabNo() ) 4375 bHide = sal_True; 4376 4377 if (bHide) 4378 { 4379 Rectangle aRect = pView->GetOutputArea(); 4380 long nHeight = aRect.Bottom() - aRect.Top(); 4381 aRect.Top() = PixelToLogic(GetOutputSizePixel(), pViewData->GetLogicMode()). 4382 Height() * 2; 4383 aRect.Bottom() = aRect.Top() + nHeight; 4384 pView->SetOutputArea( aRect ); 4385 pView->HideCursor(); 4386 } 4387 else 4388 { 4389 // bForceToTop = sal_True for editing 4390 Rectangle aPixRect = pViewData->GetEditArea( eWhich, nCol, nRow, this, NULL, sal_True ); 4391 Point aScrPos = PixelToLogic( aPixRect.TopLeft(), pViewData->GetLogicMode() ); 4392 4393 Rectangle aRect = pView->GetOutputArea(); 4394 aRect.SetPos( aScrPos ); 4395 pView->SetOutputArea( aRect ); 4396 pView->ShowCursor(); 4397 } 4398 } 4399 } 4400 4401 void ScGridWindow::ScrollPixel( long nDifX, long nDifY ) 4402 { 4403 ClickExtern(); 4404 HideNoteMarker(); 4405 4406 bIsInScroll = sal_True; 4407 //sal_Bool bXor=DrawBeforeScroll(); 4408 4409 SetMapMode(MAP_PIXEL); 4410 Scroll( nDifX, nDifY, SCROLL_CHILDREN ); 4411 SetMapMode( GetDrawMapMode() ); // verschobenen MapMode erzeugen 4412 4413 UpdateEditViewPos(); 4414 4415 DrawAfterScroll(); //bXor); 4416 bIsInScroll = sal_False; 4417 } 4418 4419 // Formeln neu zeichnen ------------------------------------------------- 4420 4421 void ScGridWindow::UpdateFormulas() 4422 { 4423 if (pViewData->GetView()->IsMinimized()) 4424 return; 4425 4426 if ( nPaintCount ) 4427 { 4428 // nicht anfangen, verschachtelt zu painten 4429 // (dann würde zumindest der MapMode nicht mehr stimmen) 4430 4431 bNeedsRepaint = sal_True; // -> am Ende vom Paint nochmal Invalidate auf alles 4432 aRepaintPixel = Rectangle(); // alles 4433 return; 4434 } 4435 4436 SCCOL nX1 = pViewData->GetPosX( eHWhich ); 4437 SCROW nY1 = pViewData->GetPosY( eVWhich ); 4438 SCCOL nX2 = nX1 + pViewData->VisibleCellsX( eHWhich ); 4439 SCROW nY2 = nY1 + pViewData->VisibleCellsY( eVWhich ); 4440 4441 if (nX2 > MAXCOL) nX2 = MAXCOL; 4442 if (nY2 > MAXROW) nY2 = MAXROW; 4443 4444 // Draw( nX1, nY1, nX2, nY2, SC_UPDATE_CHANGED ); 4445 4446 // don't draw directly - instead use OutputData to find changed area and invalidate 4447 4448 SCROW nPosY = nY1; 4449 4450 ScDocShell* pDocSh = pViewData->GetDocShell(); 4451 ScDocument* pDoc = pDocSh->GetDocument(); 4452 SCTAB nTab = pViewData->GetTabNo(); 4453 4454 pDoc->ExtendHidden( nX1, nY1, nX2, nY2, nTab ); 4455 4456 Point aScrPos = pViewData->GetScrPos( nX1, nY1, eWhich ); 4457 long nMirrorWidth = GetSizePixel().Width(); 4458 sal_Bool bLayoutRTL = pDoc->IsLayoutRTL( nTab ); 4459 // unused variable long nLayoutSign = bLayoutRTL ? -1 : 1; 4460 if ( bLayoutRTL ) 4461 { 4462 long nEndPixel = pViewData->GetScrPos( nX2+1, nPosY, eWhich ).X(); 4463 nMirrorWidth = aScrPos.X() - nEndPixel; 4464 aScrPos.X() = nEndPixel + 1; 4465 } 4466 4467 long nScrX = aScrPos.X(); 4468 long nScrY = aScrPos.Y(); 4469 4470 double nPPTX = pViewData->GetPPTX(); 4471 double nPPTY = pViewData->GetPPTY(); 4472 4473 ScTableInfo aTabInfo; 4474 pDoc->FillInfo( aTabInfo, nX1, nY1, nX2, nY2, nTab, nPPTX, nPPTY, sal_False, sal_False ); 4475 4476 Fraction aZoomX = pViewData->GetZoomX(); 4477 Fraction aZoomY = pViewData->GetZoomY(); 4478 ScOutputData aOutputData( this, OUTTYPE_WINDOW, aTabInfo, pDoc, nTab, 4479 nScrX, nScrY, nX1, nY1, nX2, nY2, nPPTX, nPPTY, 4480 &aZoomX, &aZoomY ); 4481 aOutputData.SetMirrorWidth( nMirrorWidth ); 4482 4483 aOutputData.FindChanged(); 4484 4485 // #122149# do not use old GetChangedArea() which used polygon-based Regions, but use 4486 // the region-band based new version; anyways, only rectangles are added 4487 Region aChangedRegion( aOutputData.GetChangedAreaRegion() ); // logic (PixelToLogic) 4488 if(!aChangedRegion.IsEmpty()) 4489 { 4490 Invalidate(aChangedRegion); 4491 } 4492 4493 CheckNeedsRepaint(); // #i90362# used to be called via Draw() - still needed here 4494 } 4495 4496 void ScGridWindow::UpdateAutoFillMark(sal_Bool bMarked, const ScRange& rMarkRange) 4497 { 4498 if ( bMarked != bAutoMarkVisible || ( bMarked && rMarkRange.aEnd != aAutoMarkPos ) ) 4499 { 4500 HideCursor(); 4501 bAutoMarkVisible = bMarked; 4502 if ( bMarked ) 4503 aAutoMarkPos = rMarkRange.aEnd; 4504 ShowCursor(); 4505 4506 UpdateAutoFillOverlay(); 4507 } 4508 } 4509 4510 void ScGridWindow::UpdateListValPos( sal_Bool bVisible, const ScAddress& rPos ) 4511 { 4512 sal_Bool bOldButton = bListValButton; 4513 ScAddress aOldPos = aListValPos; 4514 4515 bListValButton = bVisible; 4516 aListValPos = rPos; 4517 4518 if ( bListValButton ) 4519 { 4520 if ( !bOldButton || aListValPos != aOldPos ) 4521 { 4522 // paint area of new button 4523 Invalidate( PixelToLogic( GetListValButtonRect( aListValPos ) ) ); 4524 } 4525 } 4526 if ( bOldButton ) 4527 { 4528 if ( !bListValButton || aListValPos != aOldPos ) 4529 { 4530 // paint area of old button 4531 Invalidate( PixelToLogic( GetListValButtonRect( aOldPos ) ) ); 4532 } 4533 } 4534 } 4535 4536 void ScGridWindow::HideCursor() 4537 { 4538 ++nCursorHideCount; 4539 if (nCursorHideCount==1) 4540 { 4541 DrawCursor(); 4542 DrawAutoFillMark(); 4543 } 4544 } 4545 4546 void ScGridWindow::ShowCursor() 4547 { 4548 if (nCursorHideCount==0) 4549 { 4550 DBG_ERROR("zuviel ShowCursor"); 4551 return; 4552 } 4553 4554 if (nCursorHideCount==1) 4555 { 4556 // #i57745# Draw the cursor before setting the variable, in case the 4557 // GetSizePixel call from drawing causes a repaint (resize handler is called) 4558 DrawAutoFillMark(); 4559 DrawCursor(); 4560 } 4561 4562 --nCursorHideCount; 4563 } 4564 4565 void __EXPORT ScGridWindow::GetFocus() 4566 { 4567 ScTabViewShell* pViewShell = pViewData->GetViewShell(); 4568 pViewShell->GotFocus(); 4569 pViewShell->SetFormShellAtTop( sal_False ); // focus in GridWindow -> FormShell no longer on top 4570 4571 if (pViewShell->HasAccessibilityObjects()) 4572 pViewShell->BroadcastAccessibility(ScAccGridWinFocusGotHint(eWhich, GetAccessible())); 4573 4574 if ( !SC_MOD()->IsFormulaMode() ) 4575 { 4576 pViewShell->UpdateInputHandler(); 4577 // StopMarking(); // falls Dialog (Fehler), weil dann kein ButtonUp 4578 // MO: nur wenn nicht im RefInput-Modus 4579 // -> GetFocus/MouseButtonDown-Reihenfolge 4580 // auf dem Mac 4581 } 4582 4583 Window::GetFocus(); 4584 } 4585 4586 void __EXPORT ScGridWindow::LoseFocus() 4587 { 4588 ScTabViewShell* pViewShell = pViewData->GetViewShell(); 4589 pViewShell->LostFocus(); 4590 4591 if (pViewShell->HasAccessibilityObjects()) 4592 pViewShell->BroadcastAccessibility(ScAccGridWinFocusLostHint(eWhich, GetAccessible())); 4593 4594 Window::LoseFocus(); 4595 } 4596 4597 Point ScGridWindow::GetMousePosPixel() const { return aCurMousePos; } 4598 4599 //------------------------------------------------------------------------ 4600 4601 sal_Bool ScGridWindow::HitRangeFinder( const Point& rMouse, sal_Bool& rCorner, 4602 sal_uInt16* pIndex, SCsCOL* pAddX, SCsROW* pAddY ) 4603 { 4604 sal_Bool bFound = sal_False; 4605 ScInputHandler* pHdl = SC_MOD()->GetInputHdl( pViewData->GetViewShell() ); 4606 if (pHdl) 4607 { 4608 ScRangeFindList* pRangeFinder = pHdl->GetRangeFindList(); 4609 if ( pRangeFinder && !pRangeFinder->IsHidden() && 4610 pRangeFinder->GetDocName() == pViewData->GetDocShell()->GetTitle() ) 4611 { 4612 ScDocument* pDoc = pViewData->GetDocument(); 4613 SCTAB nTab = pViewData->GetTabNo(); 4614 sal_Bool bLayoutRTL = pDoc->IsLayoutRTL( nTab ); 4615 long nLayoutSign = bLayoutRTL ? -1 : 1; 4616 4617 SCsCOL nPosX; 4618 SCsROW nPosY; 4619 pViewData->GetPosFromPixel( rMouse.X(), rMouse.Y(), eWhich, nPosX, nPosY ); 4620 // zusammengefasste (einzeln/Bereich) ??? 4621 ScAddress aAddr( nPosX, nPosY, nTab ); 4622 4623 // Point aNext = pViewData->GetScrPos( nPosX+1, nPosY+1, eWhich ); 4624 4625 Point aNext = pViewData->GetScrPos( nPosX, nPosY, eWhich, sal_True ); 4626 long nSizeXPix; 4627 long nSizeYPix; 4628 pViewData->GetMergeSizePixel( nPosX, nPosY, nSizeXPix, nSizeYPix ); 4629 aNext.X() += nSizeXPix * nLayoutSign; 4630 aNext.Y() += nSizeYPix; 4631 4632 sal_Bool bCornerHor; 4633 if ( bLayoutRTL ) 4634 bCornerHor = ( rMouse.X() >= aNext.X() && rMouse.X() <= aNext.X() + 8 ); 4635 else 4636 bCornerHor = ( rMouse.X() >= aNext.X() - 8 && rMouse.X() <= aNext.X() ); 4637 4638 sal_Bool bCellCorner = ( bCornerHor && 4639 rMouse.Y() >= aNext.Y() - 8 && rMouse.Y() <= aNext.Y() ); 4640 // corner is hit only if the mouse is within the cell 4641 4642 sal_uInt16 nCount = (sal_uInt16)pRangeFinder->Count(); 4643 for (sal_uInt16 i=nCount; i;) 4644 { 4645 // rückwärts suchen, damit der zuletzt gepaintete Rahmen gefunden wird 4646 --i; 4647 ScRangeFindData* pData = pRangeFinder->GetObject(i); 4648 if ( pData && pData->aRef.In(aAddr) ) 4649 { 4650 if (pIndex) *pIndex = i; 4651 if (pAddX) *pAddX = nPosX - pData->aRef.aStart.Col(); 4652 if (pAddY) *pAddY = nPosY - pData->aRef.aStart.Row(); 4653 bFound = sal_True; 4654 rCorner = ( bCellCorner && aAddr == pData->aRef.aEnd ); 4655 break; 4656 } 4657 } 4658 } 4659 } 4660 return bFound; 4661 } 4662 4663 #define SCE_TOP 1 4664 #define SCE_BOTTOM 2 4665 #define SCE_LEFT 4 4666 #define SCE_RIGHT 8 4667 #define SCE_ALL 15 4668 4669 void lcl_PaintOneRange( ScDocShell* pDocSh, const ScRange& rRange, sal_uInt16 nEdges ) 4670 { 4671 // der Range ist immer richtigherum 4672 4673 SCCOL nCol1 = rRange.aStart.Col(); 4674 SCROW nRow1 = rRange.aStart.Row(); 4675 SCTAB nTab1 = rRange.aStart.Tab(); 4676 SCCOL nCol2 = rRange.aEnd.Col(); 4677 SCROW nRow2 = rRange.aEnd.Row(); 4678 SCTAB nTab2 = rRange.aEnd.Tab(); 4679 sal_Bool bHiddenEdge = sal_False; 4680 SCROW nTmp; 4681 4682 ScDocument* pDoc = pDocSh->GetDocument(); 4683 while ( nCol1 > 0 && pDoc->ColHidden(nCol1, nTab1) ) 4684 { 4685 --nCol1; 4686 bHiddenEdge = sal_True; 4687 } 4688 while ( nCol2 < MAXCOL && pDoc->ColHidden(nCol2, nTab1) ) 4689 { 4690 ++nCol2; 4691 bHiddenEdge = sal_True; 4692 } 4693 nTmp = pDoc->FirstVisibleRow(0, nRow1, nTab1); 4694 if (!ValidRow(nTmp)) 4695 nTmp = 0; 4696 if (nTmp < nRow1) 4697 { 4698 nRow1 = nTmp; 4699 bHiddenEdge = sal_True; 4700 } 4701 nTmp = pDoc->FirstVisibleRow(nRow2, MAXROW, nTab1); 4702 if (!ValidRow(nTmp)) 4703 nTmp = MAXROW; 4704 if (nTmp > nRow2) 4705 { 4706 nRow2 = nTmp; 4707 bHiddenEdge = sal_True; 4708 } 4709 4710 if ( nCol2 > nCol1 + 1 && nRow2 > nRow1 + 1 && !bHiddenEdge ) 4711 { 4712 // nur an den Rändern entlang 4713 // (die Ecken werden evtl. zweimal getroffen) 4714 4715 if ( nEdges & SCE_TOP ) 4716 pDocSh->PostPaint( nCol1, nRow1, nTab1, nCol2, nRow1, nTab2, PAINT_MARKS ); 4717 if ( nEdges & SCE_LEFT ) 4718 pDocSh->PostPaint( nCol1, nRow1, nTab1, nCol1, nRow2, nTab2, PAINT_MARKS ); 4719 if ( nEdges & SCE_RIGHT ) 4720 pDocSh->PostPaint( nCol2, nRow1, nTab1, nCol2, nRow2, nTab2, PAINT_MARKS ); 4721 if ( nEdges & SCE_BOTTOM ) 4722 pDocSh->PostPaint( nCol1, nRow2, nTab1, nCol2, nRow2, nTab2, PAINT_MARKS ); 4723 } 4724 else // everything in one call 4725 pDocSh->PostPaint( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2, PAINT_MARKS ); 4726 } 4727 4728 void lcl_PaintRefChanged( ScDocShell* pDocSh, const ScRange& rOldUn, const ScRange& rNewUn ) 4729 { 4730 // Repaint für die Teile des Rahmens in Old, die bei New nicht mehr da sind 4731 4732 ScRange aOld = rOldUn; 4733 ScRange aNew = rNewUn; 4734 aOld.Justify(); 4735 aNew.Justify(); 4736 4737 if ( aOld.aStart == aOld.aEnd ) //! Tab ignorieren? 4738 pDocSh->GetDocument()->ExtendMerge(aOld); 4739 if ( aNew.aStart == aNew.aEnd ) //! Tab ignorieren? 4740 pDocSh->GetDocument()->ExtendMerge(aNew); 4741 4742 SCCOL nOldCol1 = aOld.aStart.Col(); 4743 SCROW nOldRow1 = aOld.aStart.Row(); 4744 SCCOL nOldCol2 = aOld.aEnd.Col(); 4745 SCROW nOldRow2 = aOld.aEnd.Row(); 4746 SCCOL nNewCol1 = aNew.aStart.Col(); 4747 SCROW nNewRow1 = aNew.aStart.Row(); 4748 SCCOL nNewCol2 = aNew.aEnd.Col(); 4749 SCROW nNewRow2 = aNew.aEnd.Row(); 4750 SCTAB nTab1 = aOld.aStart.Tab(); // Tab ändert sich nicht 4751 SCTAB nTab2 = aOld.aEnd.Tab(); 4752 4753 if ( nNewRow2 < nOldRow1 || nNewRow1 > nOldRow2 || 4754 nNewCol2 < nOldCol1 || nNewCol1 > nOldCol2 || 4755 ( nNewCol1 != nOldCol1 && nNewRow1 != nOldRow1 && 4756 nNewCol2 != nOldCol2 && nNewRow2 != nOldRow2 ) ) 4757 { 4758 // komplett weggeschoben oder alle Seiten verändert 4759 // (Abfrage <= statt < geht schief bei einzelnen Zeilen/Spalten) 4760 4761 lcl_PaintOneRange( pDocSh, aOld, SCE_ALL ); 4762 } 4763 else // alle vier Kanten einzeln testen 4764 { 4765 // oberer Teil 4766 if ( nNewRow1 < nOldRow1 ) // nur obere Linie löschen 4767 lcl_PaintOneRange( pDocSh, ScRange( 4768 nOldCol1, nOldRow1, nTab1, nOldCol2, nOldRow1, nTab2 ), SCE_ALL ); 4769 else if ( nNewRow1 > nOldRow1 ) // den Teil, der oben wegkommt 4770 lcl_PaintOneRange( pDocSh, ScRange( 4771 nOldCol1, nOldRow1, nTab1, nOldCol2, nNewRow1-1, nTab2 ), 4772 SCE_ALL &~ SCE_BOTTOM ); 4773 4774 // unterer Teil 4775 if ( nNewRow2 > nOldRow2 ) // nur untere Linie löschen 4776 lcl_PaintOneRange( pDocSh, ScRange( 4777 nOldCol1, nOldRow2, nTab1, nOldCol2, nOldRow2, nTab2 ), SCE_ALL ); 4778 else if ( nNewRow2 < nOldRow2 ) // den Teil, der unten wegkommt 4779 lcl_PaintOneRange( pDocSh, ScRange( 4780 nOldCol1, nNewRow2+1, nTab1, nOldCol2, nOldRow2, nTab2 ), 4781 SCE_ALL &~ SCE_TOP ); 4782 4783 // linker Teil 4784 if ( nNewCol1 < nOldCol1 ) // nur linke Linie löschen 4785 lcl_PaintOneRange( pDocSh, ScRange( 4786 nOldCol1, nOldRow1, nTab1, nOldCol1, nOldRow2, nTab2 ), SCE_ALL ); 4787 else if ( nNewCol1 > nOldCol1 ) // den Teil, der links wegkommt 4788 lcl_PaintOneRange( pDocSh, ScRange( 4789 nOldCol1, nOldRow1, nTab1, nNewCol1-1, nOldRow2, nTab2 ), 4790 SCE_ALL &~ SCE_RIGHT ); 4791 4792 // rechter Teil 4793 if ( nNewCol2 > nOldCol2 ) // nur rechte Linie löschen 4794 lcl_PaintOneRange( pDocSh, ScRange( 4795 nOldCol2, nOldRow1, nTab1, nOldCol2, nOldRow2, nTab2 ), SCE_ALL ); 4796 else if ( nNewCol2 < nOldCol2 ) // den Teil, der rechts wegkommt 4797 lcl_PaintOneRange( pDocSh, ScRange( 4798 nNewCol2+1, nOldRow1, nTab1, nOldCol2, nOldRow2, nTab2 ), 4799 SCE_ALL &~ SCE_LEFT ); 4800 } 4801 } 4802 4803 void ScGridWindow::RFMouseMove( const MouseEvent& rMEvt, sal_Bool bUp ) 4804 { 4805 ScInputHandler* pHdl = SC_MOD()->GetInputHdl( pViewData->GetViewShell() ); 4806 if (!pHdl) 4807 return; 4808 ScRangeFindList* pRangeFinder = pHdl->GetRangeFindList(); 4809 if (!pRangeFinder || nRFIndex >= pRangeFinder->Count()) 4810 return; 4811 ScRangeFindData* pData = pRangeFinder->GetObject( nRFIndex ); 4812 if (!pData) 4813 return; 4814 4815 // Mauszeiger 4816 4817 if (bRFSize) 4818 SetPointer( Pointer( POINTER_CROSS ) ); 4819 else 4820 SetPointer( Pointer( POINTER_HAND ) ); 4821 4822 // Scrolling 4823 4824 sal_Bool bTimer = sal_False; 4825 Point aPos = rMEvt.GetPosPixel(); 4826 SCsCOL nDx = 0; 4827 SCsROW nDy = 0; 4828 if ( aPos.X() < 0 ) nDx = -1; 4829 if ( aPos.Y() < 0 ) nDy = -1; 4830 Size aSize = GetOutputSizePixel(); 4831 if ( aPos.X() >= aSize.Width() ) 4832 nDx = 1; 4833 if ( aPos.Y() >= aSize.Height() ) 4834 nDy = 1; 4835 if ( nDx != 0 || nDy != 0 ) 4836 { 4837 if ( nDx != 0) pViewData->GetView()->ScrollX( nDx, WhichH(eWhich) ); 4838 if ( nDy != 0 ) pViewData->GetView()->ScrollY( nDy, WhichV(eWhich) ); 4839 bTimer = sal_True; 4840 } 4841 4842 // Umschalten bei Fixierung (damit Scrolling funktioniert) 4843 4844 if ( eWhich == pViewData->GetActivePart() ) //?? 4845 { 4846 if ( pViewData->GetHSplitMode() == SC_SPLIT_FIX ) 4847 if ( nDx > 0 ) 4848 { 4849 if ( eWhich == SC_SPLIT_TOPLEFT ) 4850 pViewData->GetView()->ActivatePart( SC_SPLIT_TOPRIGHT ); 4851 else if ( eWhich == SC_SPLIT_BOTTOMLEFT ) 4852 pViewData->GetView()->ActivatePart( SC_SPLIT_BOTTOMRIGHT ); 4853 } 4854 4855 if ( pViewData->GetVSplitMode() == SC_SPLIT_FIX ) 4856 if ( nDy > 0 ) 4857 { 4858 if ( eWhich == SC_SPLIT_TOPLEFT ) 4859 pViewData->GetView()->ActivatePart( SC_SPLIT_BOTTOMLEFT ); 4860 else if ( eWhich == SC_SPLIT_TOPRIGHT ) 4861 pViewData->GetView()->ActivatePart( SC_SPLIT_BOTTOMRIGHT ); 4862 } 4863 } 4864 4865 // Verschieben 4866 4867 SCsCOL nPosX; 4868 SCsROW nPosY; 4869 pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY ); 4870 4871 ScRange aOld = pData->aRef; 4872 ScRange aNew = aOld; 4873 if ( bRFSize ) 4874 { 4875 aNew.aEnd.SetCol((SCCOL)nPosX); 4876 aNew.aEnd.SetRow((SCROW)nPosY); 4877 } 4878 else 4879 { 4880 long nStartX = nPosX - nRFAddX; 4881 if ( nStartX < 0 ) nStartX = 0; 4882 long nStartY = nPosY - nRFAddY; 4883 if ( nStartY < 0 ) nStartY = 0; 4884 long nEndX = nStartX + aOld.aEnd.Col() - aOld.aStart.Col(); 4885 if ( nEndX > MAXCOL ) 4886 { 4887 nStartX -= ( nEndX - MAXROW ); 4888 nEndX = MAXCOL; 4889 } 4890 long nEndY = nStartY + aOld.aEnd.Row() - aOld.aStart.Row(); 4891 if ( nEndY > MAXROW ) 4892 { 4893 nStartY -= ( nEndY - MAXROW ); 4894 nEndY = MAXROW; 4895 } 4896 4897 aNew.aStart.SetCol((SCCOL)nStartX); 4898 aNew.aStart.SetRow((SCROW)nStartY); 4899 aNew.aEnd.SetCol((SCCOL)nEndX); 4900 aNew.aEnd.SetRow((SCROW)nEndY); 4901 } 4902 4903 if ( bUp ) 4904 aNew.Justify(); // beim ButtonUp wieder richtigherum 4905 4906 if ( aNew != aOld ) 4907 { 4908 pHdl->UpdateRange( nRFIndex, aNew ); 4909 4910 ScDocShell* pDocSh = pViewData->GetDocShell(); 4911 4912 // nur das neuzeichnen, was sich verändert hat... 4913 lcl_PaintRefChanged( pDocSh, aOld, aNew ); 4914 4915 // neuen Rahmen nur drüberzeichnen (synchron) 4916 pDocSh->Broadcast( ScIndexHint( SC_HINT_SHOWRANGEFINDER, nRFIndex ) ); 4917 4918 Update(); // was man bewegt, will man auch sofort sehen 4919 } 4920 4921 // Timer für Scrolling 4922 4923 if (bTimer) 4924 pViewData->GetView()->SetTimer( this, rMEvt ); // Event wiederholen 4925 else 4926 pViewData->GetView()->ResetTimer(); 4927 } 4928 4929 //------------------------------------------------------------------------ 4930 4931 sal_Bool ScGridWindow::GetEditUrl( const Point& rPos, 4932 String* pName, String* pUrl, String* pTarget ) 4933 { 4934 return GetEditUrlOrError( sal_False, rPos, pName, pUrl, pTarget ); 4935 } 4936 4937 sal_Bool ScGridWindow::GetEditUrlOrError( sal_Bool bSpellErr, const Point& rPos, 4938 String* pName, String* pUrl, String* pTarget ) 4939 { 4940 //! nPosX/Y mit übergeben? 4941 SCsCOL nPosX; 4942 SCsROW nPosY; 4943 pViewData->GetPosFromPixel( rPos.X(), rPos.Y(), eWhich, nPosX, nPosY ); 4944 4945 SCTAB nTab = pViewData->GetTabNo(); 4946 ScDocShell* pDocSh = pViewData->GetDocShell(); 4947 ScDocument* pDoc = pDocSh->GetDocument(); 4948 ScBaseCell* pCell = NULL; 4949 4950 sal_Bool bFound = lcl_GetHyperlinkCell( pDoc, nPosX, nPosY, nTab, pCell ); 4951 if( !bFound ) 4952 return sal_False; 4953 4954 ScHideTextCursor aHideCursor( pViewData, eWhich ); // before GetEditArea (MapMode is changed) 4955 4956 const ScPatternAttr* pPattern = pDoc->GetPattern( nPosX, nPosY, nTab ); 4957 // bForceToTop = sal_False, use the cell's real position 4958 Rectangle aEditRect = pViewData->GetEditArea( eWhich, nPosX, nPosY, this, pPattern, sal_False ); 4959 if (rPos.Y() < aEditRect.Top()) 4960 return sal_False; 4961 4962 // vertikal kann (noch) nicht angeklickt werden: 4963 4964 if (pPattern->GetCellOrientation() != SVX_ORIENTATION_STANDARD) 4965 return sal_False; 4966 4967 sal_Bool bBreak = ((SfxBoolItem&)pPattern->GetItem(ATTR_LINEBREAK)).GetValue() || 4968 ((SvxCellHorJustify)((const SvxHorJustifyItem&)pPattern-> 4969 GetItem( ATTR_HOR_JUSTIFY )).GetValue() == SVX_HOR_JUSTIFY_BLOCK); 4970 SvxCellHorJustify eHorJust = (SvxCellHorJustify)((SvxHorJustifyItem&)pPattern-> 4971 GetItem(ATTR_HOR_JUSTIFY)).GetValue(); 4972 4973 // EditEngine 4974 4975 ScFieldEditEngine aEngine( pDoc->GetEditPool() ); 4976 ScSizeDeviceProvider aProv(pDocSh); 4977 aEngine.SetRefDevice( aProv.GetDevice() ); 4978 aEngine.SetRefMapMode( MAP_100TH_MM ); 4979 SfxItemSet aDefault( aEngine.GetEmptyItemSet() ); 4980 pPattern->FillEditItemSet( &aDefault ); 4981 SvxAdjust eSvxAdjust = SVX_ADJUST_LEFT; 4982 switch (eHorJust) 4983 { 4984 case SVX_HOR_JUSTIFY_LEFT: 4985 case SVX_HOR_JUSTIFY_REPEAT: // nicht implementiert 4986 case SVX_HOR_JUSTIFY_STANDARD: // always Text if an EditCell type 4987 eSvxAdjust = SVX_ADJUST_LEFT; 4988 break; 4989 case SVX_HOR_JUSTIFY_RIGHT: 4990 eSvxAdjust = SVX_ADJUST_RIGHT; 4991 break; 4992 case SVX_HOR_JUSTIFY_CENTER: 4993 eSvxAdjust = SVX_ADJUST_CENTER; 4994 break; 4995 case SVX_HOR_JUSTIFY_BLOCK: 4996 eSvxAdjust = SVX_ADJUST_BLOCK; 4997 break; 4998 } 4999 aDefault.Put( SvxAdjustItem( eSvxAdjust, EE_PARA_JUST ) ); 5000 aEngine.SetDefaults( aDefault ); 5001 if (bSpellErr) 5002 aEngine.SetControlWord( aEngine.GetControlWord() | EE_CNTRL_ONLINESPELLING ); 5003 5004 MapMode aEditMode = pViewData->GetLogicMode(eWhich); // ohne Drawing-Skalierung 5005 Rectangle aLogicEdit = PixelToLogic( aEditRect, aEditMode ); 5006 long nThisColLogic = aLogicEdit.Right() - aLogicEdit.Left() + 1; 5007 Size aPaperSize = Size( 1000000, 1000000 ); 5008 if(pCell->GetCellType() == CELLTYPE_FORMULA) 5009 { 5010 long nSizeX = 0; 5011 long nSizeY = 0; 5012 pViewData->GetMergeSizePixel( nPosX, nPosY, nSizeX, nSizeY ); 5013 aPaperSize = Size(nSizeX, nSizeY ); 5014 aPaperSize = PixelToLogic(aPaperSize); 5015 } 5016 5017 if (bBreak) 5018 aPaperSize.Width() = nThisColLogic; 5019 aEngine.SetPaperSize( aPaperSize ); 5020 5021 ::std::auto_ptr< EditTextObject > pTextObj; 5022 const EditTextObject* pData; 5023 if(pCell->GetCellType() == CELLTYPE_EDIT) 5024 { 5025 ((ScEditCell*)pCell)->GetData(pData); 5026 if (pData) 5027 aEngine.SetText(*pData); 5028 } 5029 else // HyperLink Formula cell 5030 { 5031 pTextObj.reset((static_cast<ScFormulaCell*>(pCell))->CreateURLObject()); 5032 if (pTextObj.get()) 5033 aEngine.SetText(*pTextObj); 5034 } 5035 5036 long nStartX = aLogicEdit.Left(); 5037 5038 long nTextWidth = aEngine.CalcTextWidth(); 5039 long nTextHeight = aEngine.GetTextHeight(); 5040 if ( nTextWidth < nThisColLogic ) 5041 { 5042 if (eHorJust == SVX_HOR_JUSTIFY_RIGHT) 5043 nStartX += nThisColLogic - nTextWidth; 5044 else if (eHorJust == SVX_HOR_JUSTIFY_CENTER) 5045 nStartX += (nThisColLogic - nTextWidth) / 2; 5046 } 5047 5048 aLogicEdit.Left() = nStartX; 5049 if (!bBreak) 5050 aLogicEdit.Right() = nStartX + nTextWidth; 5051 5052 // There is one glitch when dealing with a hyperlink cell and 5053 // the cell content is NUMERIC. This defaults to right aligned and 5054 // we need to adjust accordingly. 5055 if(pCell->GetCellType() == CELLTYPE_FORMULA && 5056 static_cast<ScFormulaCell*>(pCell)->IsValue() && 5057 eHorJust == SVX_HOR_JUSTIFY_STANDARD) 5058 { 5059 aLogicEdit.Right() = aLogicEdit.Left() + nThisColLogic - 1; 5060 aLogicEdit.Left() = aLogicEdit.Right() - nTextWidth; 5061 } 5062 aLogicEdit.Bottom() = aLogicEdit.Top() + nTextHeight; 5063 5064 Point aLogicClick = PixelToLogic(rPos,aEditMode); 5065 if ( aLogicEdit.IsInside(aLogicClick) ) 5066 { 5067 // aEngine.SetUpdateMode(sal_False); 5068 EditView aTempView( &aEngine, this ); 5069 aTempView.SetOutputArea( aLogicEdit ); 5070 5071 sal_Bool bRet = sal_False; 5072 MapMode aOld = GetMapMode(); 5073 SetMapMode(aEditMode); // kein return mehr 5074 5075 if (bSpellErr) // Spelling-Fehler suchen 5076 { 5077 bRet = aTempView.IsWrongSpelledWordAtPos( rPos ); 5078 if ( bRet ) 5079 pViewData->GetView()->SetCursor( nPosX, nPosY ); // Cursor setzen 5080 } 5081 else // URL suchen 5082 { 5083 const SvxFieldItem* pFieldItem = aTempView.GetFieldUnderMousePointer(); 5084 5085 if (pFieldItem) 5086 { 5087 const SvxFieldData* pField = pFieldItem->GetField(); 5088 if ( pField && pField->ISA(SvxURLField) ) 5089 { 5090 if ( pName || pUrl || pTarget ) 5091 { 5092 const SvxURLField* pURLField = (const SvxURLField*)pField; 5093 if (pName) 5094 *pName = pURLField->GetRepresentation(); 5095 if (pUrl) 5096 *pUrl = pURLField->GetURL(); 5097 if (pTarget) 5098 *pTarget = pURLField->GetTargetFrame(); 5099 } 5100 bRet = sal_True; 5101 } 5102 } 5103 } 5104 5105 SetMapMode(aOld); 5106 5107 // text cursor is restored in ScHideTextCursor dtor 5108 5109 return bRet; 5110 } 5111 return sal_False; 5112 } 5113 5114 sal_Bool ScGridWindow::HasScenarioButton( const Point& rPosPixel, ScRange& rScenRange ) 5115 { 5116 ScDocument* pDoc = pViewData->GetDocument(); 5117 SCTAB nTab = pViewData->GetTabNo(); 5118 SCTAB nTabCount = pDoc->GetTableCount(); 5119 if ( nTab+1<nTabCount && pDoc->IsScenario(nTab+1) && !pDoc->IsScenario(nTab) ) 5120 { 5121 sal_Bool bLayoutRTL = pDoc->IsLayoutRTL( nTab ); 5122 5123 Size aButSize = pViewData->GetScenButSize(); 5124 long nBWidth = aButSize.Width(); 5125 if (!nBWidth) 5126 return sal_False; // noch kein Button gezeichnet -> da ist auch keiner 5127 long nBHeight = aButSize.Height(); 5128 long nHSpace = (long)( SC_SCENARIO_HSPACE * pViewData->GetPPTX() ); 5129 5130 //! Ranges an der Table cachen!!!! 5131 5132 ScMarkData aMarks; 5133 for (SCTAB i=nTab+1; i<nTabCount && pDoc->IsScenario(i); i++) 5134 pDoc->MarkScenario( i, nTab, aMarks, sal_False, SC_SCENARIO_SHOWFRAME ); 5135 ScRangeList aRanges; 5136 aMarks.FillRangeListWithMarks( &aRanges, sal_False ); 5137 5138 sal_uLong nRangeCount = aRanges.Count(); 5139 for (sal_uLong j=0; j<nRangeCount; j++) 5140 { 5141 ScRange aRange = *aRanges.GetObject(j); 5142 // Szenario-Rahmen immer dann auf zusammengefasste Zellen erweitern, wenn 5143 // dadurch keine neuen nicht-überdeckten Zellen mit umrandet werden 5144 pDoc->ExtendTotalMerge( aRange ); 5145 5146 sal_Bool bTextBelow = ( aRange.aStart.Row() == 0 ); 5147 5148 Point aButtonPos; 5149 if ( bTextBelow ) 5150 { 5151 aButtonPos = pViewData->GetScrPos( aRange.aEnd.Col()+1, aRange.aEnd.Row()+1, 5152 eWhich, sal_True ); 5153 } 5154 else 5155 { 5156 aButtonPos = pViewData->GetScrPos( aRange.aEnd.Col()+1, aRange.aStart.Row(), 5157 eWhich, sal_True ); 5158 aButtonPos.Y() -= nBHeight; 5159 } 5160 if ( bLayoutRTL ) 5161 aButtonPos.X() -= nHSpace - 1; 5162 else 5163 aButtonPos.X() -= nBWidth - nHSpace; // same for top or bottom 5164 5165 Rectangle aButRect( aButtonPos, Size(nBWidth,nBHeight) ); 5166 if ( aButRect.IsInside( rPosPixel ) ) 5167 { 5168 rScenRange = aRange; 5169 return sal_True; 5170 } 5171 } 5172 } 5173 5174 return sal_False; 5175 } 5176 5177 void ScGridWindow::UpdateVisibleRange() 5178 { 5179 // #163911# Update the visible range outside of paint (called when switching sheets). 5180 // Use the same logic here as in ScGridWindow::Draw. 5181 5182 SCCOL nPosX = pViewData->GetPosX( eHWhich ); 5183 SCROW nPosY = pViewData->GetPosY( eVWhich ); 5184 5185 SCCOL nXRight = nPosX + pViewData->VisibleCellsX(eHWhich); 5186 if (nXRight > MAXCOL) nXRight = MAXCOL; 5187 SCROW nYBottom = nPosY + pViewData->VisibleCellsY(eVWhich); 5188 if (nYBottom > MAXROW) nYBottom = MAXROW; 5189 5190 // Store the current visible range. 5191 maVisibleRange.mnCol1 = nPosX; 5192 maVisibleRange.mnCol2 = nXRight; 5193 maVisibleRange.mnRow1 = nPosY; 5194 maVisibleRange.mnRow2 = nYBottom; 5195 } 5196 5197 // #114409# 5198 void ScGridWindow::DrawLayerCreated() 5199 { 5200 SetMapMode( GetDrawMapMode() ); 5201 5202 // initially create overlay objects 5203 ImpCreateOverlayObjects(); 5204 } 5205 5206 // #114409# 5207 void ScGridWindow::CursorChanged() 5208 { 5209 // here the created OverlayObjects may be transformed in later versions. For 5210 // now, just re-create them 5211 5212 UpdateCursorOverlay(); 5213 } 5214 5215 // #114409# 5216 void ScGridWindow::ImpCreateOverlayObjects() 5217 { 5218 UpdateCursorOverlay(); 5219 UpdateSelectionOverlay(); 5220 UpdateAutoFillOverlay(); 5221 UpdateDragRectOverlay(); 5222 UpdateHeaderOverlay(); 5223 UpdateShrinkOverlay(); 5224 } 5225 5226 // #114409# 5227 void ScGridWindow::ImpDestroyOverlayObjects() 5228 { 5229 DeleteCursorOverlay(); 5230 DeleteSelectionOverlay(); 5231 DeleteAutoFillOverlay(); 5232 DeleteDragRectOverlay(); 5233 DeleteHeaderOverlay(); 5234 DeleteShrinkOverlay(); 5235 } 5236 5237 void ScGridWindow::UpdateAllOverlays() 5238 { 5239 // delete and re-allocate all overlay objects 5240 5241 ImpDestroyOverlayObjects(); 5242 ImpCreateOverlayObjects(); 5243 } 5244 5245 void ScGridWindow::DeleteCursorOverlay() 5246 { 5247 DELETEZ( mpOOCursors ); 5248 } 5249 5250 void ScGridWindow::UpdateCursorOverlay() 5251 { 5252 MapMode aDrawMode = GetDrawMapMode(); 5253 MapMode aOldMode = GetMapMode(); 5254 if ( aOldMode != aDrawMode ) 5255 SetMapMode( aDrawMode ); 5256 5257 // Existing OverlayObjects may be transformed in later versions. 5258 // For now, just re-create them. 5259 5260 DeleteCursorOverlay(); 5261 5262 std::vector<Rectangle> aPixelRects; 5263 5264 // determine the cursor rectangles in pixels (moved from ScGridWindow::DrawCursor) 5265 5266 SCTAB nTab = pViewData->GetTabNo(); 5267 SCCOL nX = pViewData->GetCurX(); 5268 SCROW nY = pViewData->GetCurY(); 5269 5270 if (!maVisibleRange.isInside(nX, nY)) 5271 return; 5272 5273 // don't show the cursor in overlapped cells 5274 5275 ScDocument* pDoc = pViewData->GetDocument(); 5276 const ScPatternAttr* pPattern = pDoc->GetPattern(nX,nY,nTab); 5277 const ScMergeFlagAttr& rMergeFlag = (const ScMergeFlagAttr&) pPattern->GetItem(ATTR_MERGE_FLAG); 5278 sal_Bool bOverlapped = rMergeFlag.IsOverlapped(); 5279 5280 // left or above of the screen? 5281 5282 sal_Bool bVis = ( nX>=pViewData->GetPosX(eHWhich) && nY>=pViewData->GetPosY(eVWhich) ); 5283 if (!bVis) 5284 { 5285 SCCOL nEndX = nX; 5286 SCROW nEndY = nY; 5287 const ScMergeAttr& rMerge = (const ScMergeAttr&) pPattern->GetItem(ATTR_MERGE); 5288 if (rMerge.GetColMerge() > 1) 5289 nEndX += rMerge.GetColMerge()-1; 5290 if (rMerge.GetRowMerge() > 1) 5291 nEndY += rMerge.GetRowMerge()-1; 5292 bVis = ( nEndX>=pViewData->GetPosX(eHWhich) && nEndY>=pViewData->GetPosY(eVWhich) ); 5293 } 5294 5295 if ( bVis && !bOverlapped && !pViewData->HasEditView(eWhich) && pViewData->IsActive() ) 5296 { 5297 Point aScrPos = pViewData->GetScrPos( nX, nY, eWhich, sal_True ); 5298 sal_Bool bLayoutRTL = pDoc->IsLayoutRTL( nTab ); 5299 5300 // completely right of/below the screen? 5301 // (test with logical start position in aScrPos) 5302 sal_Bool bMaybeVisible; 5303 if ( bLayoutRTL ) 5304 bMaybeVisible = ( aScrPos.X() >= -2 && aScrPos.Y() >= -2 ); 5305 else 5306 { 5307 Size aOutSize = GetOutputSizePixel(); 5308 bMaybeVisible = ( aScrPos.X() <= aOutSize.Width() + 2 && aScrPos.Y() <= aOutSize.Height() + 2 ); 5309 } 5310 if ( bMaybeVisible ) 5311 { 5312 long nSizeXPix; 5313 long nSizeYPix; 5314 pViewData->GetMergeSizePixel( nX, nY, nSizeXPix, nSizeYPix ); 5315 5316 if ( bLayoutRTL ) 5317 aScrPos.X() -= nSizeXPix - 2; // move instead of mirroring 5318 5319 sal_Bool bFix = ( pViewData->GetHSplitMode() == SC_SPLIT_FIX || 5320 pViewData->GetVSplitMode() == SC_SPLIT_FIX ); 5321 if ( pViewData->GetActivePart()==eWhich || bFix ) 5322 { 5323 aScrPos.X() -= 2; 5324 aScrPos.Y() -= 2; 5325 Rectangle aRect( aScrPos, Size( nSizeXPix + 3, nSizeYPix + 3 ) ); 5326 5327 aPixelRects.push_back(Rectangle( aRect.Left(), aRect.Top(), aRect.Left()+2, aRect.Bottom() )); 5328 aPixelRects.push_back(Rectangle( aRect.Right()-2, aRect.Top(), aRect.Right(), aRect.Bottom() )); 5329 aPixelRects.push_back(Rectangle( aRect.Left()+3, aRect.Top(), aRect.Right()-3, aRect.Top()+2 )); 5330 aPixelRects.push_back(Rectangle( aRect.Left()+3, aRect.Bottom()-2, aRect.Right()-3, aRect.Bottom() )); 5331 } 5332 else 5333 { 5334 Rectangle aRect( aScrPos, Size( nSizeXPix - 1, nSizeYPix - 1 ) ); 5335 aPixelRects.push_back( aRect ); 5336 } 5337 } 5338 } 5339 5340 if ( aPixelRects.size() ) 5341 { 5342 // #i70788# get the OverlayManager safely 5343 ::sdr::overlay::OverlayManager* pOverlayManager = getOverlayManager(); 5344 5345 if(pOverlayManager) 5346 { 5347 const Color aCursorColor( SC_MOD()->GetColorConfig().GetColorValue(svtools::FONTCOLOR).nColor ); 5348 std::vector< basegfx::B2DRange > aRanges; 5349 const basegfx::B2DHomMatrix aTransform(GetInverseViewTransformation()); 5350 5351 for(sal_uInt32 a(0); a < aPixelRects.size(); a++) 5352 { 5353 const Rectangle aRA(aPixelRects[a]); 5354 basegfx::B2DRange aRB(aRA.Left(), aRA.Top(), aRA.Right() + 1, aRA.Bottom() + 1); 5355 aRB.transform(aTransform); 5356 aRanges.push_back(aRB); 5357 } 5358 5359 sdr::overlay::OverlayObject* pOverlay = new sdr::overlay::OverlaySelection( 5360 sdr::overlay::OVERLAY_SOLID, 5361 aCursorColor, 5362 aRanges, 5363 false); 5364 5365 pOverlayManager->add(*pOverlay); 5366 mpOOCursors = new ::sdr::overlay::OverlayObjectList; 5367 mpOOCursors->append(*pOverlay); 5368 } 5369 } 5370 5371 if ( aOldMode != aDrawMode ) 5372 SetMapMode( aOldMode ); 5373 } 5374 5375 void ScGridWindow::DeleteSelectionOverlay() 5376 { 5377 DELETEZ( mpOOSelection ); 5378 } 5379 5380 void ScGridWindow::UpdateSelectionOverlay() 5381 { 5382 MapMode aDrawMode = GetDrawMapMode(); 5383 MapMode aOldMode = GetMapMode(); 5384 if ( aOldMode != aDrawMode ) 5385 SetMapMode( aDrawMode ); 5386 5387 DeleteSelectionOverlay(); 5388 std::vector<Rectangle> aPixelRects; 5389 GetSelectionRects( aPixelRects ); 5390 5391 if ( aPixelRects.size() && pViewData->IsActive() ) 5392 { 5393 // #i70788# get the OverlayManager safely 5394 ::sdr::overlay::OverlayManager* pOverlayManager = getOverlayManager(); 5395 5396 if(pOverlayManager) 5397 { 5398 std::vector< basegfx::B2DRange > aRanges; 5399 const basegfx::B2DHomMatrix aTransform(GetInverseViewTransformation()); 5400 5401 for(sal_uInt32 a(0); a < aPixelRects.size(); a++) 5402 { 5403 const Rectangle aRA(aPixelRects[a]); 5404 basegfx::B2DRange aRB(aRA.Left() - 1, aRA.Top() - 1, aRA.Right(), aRA.Bottom()); 5405 aRB.transform(aTransform); 5406 aRanges.push_back(aRB); 5407 } 5408 5409 // get the system's hilight color 5410 const SvtOptionsDrawinglayer aSvtOptionsDrawinglayer; 5411 const Color aHighlight(aSvtOptionsDrawinglayer.getHilightColor()); 5412 5413 sdr::overlay::OverlayObject* pOverlay = new sdr::overlay::OverlaySelection( 5414 sdr::overlay::OVERLAY_TRANSPARENT, 5415 aHighlight, 5416 aRanges, 5417 true); 5418 5419 pOverlayManager->add(*pOverlay); 5420 mpOOSelection = new ::sdr::overlay::OverlayObjectList; 5421 mpOOSelection->append(*pOverlay); 5422 } 5423 } 5424 5425 if ( aOldMode != aDrawMode ) 5426 SetMapMode( aOldMode ); 5427 } 5428 5429 void ScGridWindow::DeleteAutoFillOverlay() 5430 { 5431 DELETEZ( mpOOAutoFill ); 5432 mpAutoFillRect.reset(); 5433 } 5434 5435 void ScGridWindow::UpdateAutoFillOverlay() 5436 { 5437 MapMode aDrawMode = GetDrawMapMode(); 5438 MapMode aOldMode = GetMapMode(); 5439 if ( aOldMode != aDrawMode ) 5440 SetMapMode( aDrawMode ); 5441 5442 DeleteAutoFillOverlay(); 5443 5444 // get the AutoFill handle rectangle in pixels (moved from ScGridWindow::DrawAutoFillMark) 5445 5446 if ( bAutoMarkVisible && aAutoMarkPos.Tab() == pViewData->GetTabNo() && 5447 !pViewData->HasEditView(eWhich) && pViewData->IsActive() ) 5448 { 5449 SCCOL nX = aAutoMarkPos.Col(); 5450 SCROW nY = aAutoMarkPos.Row(); 5451 5452 if (!maVisibleRange.isInside(nX, nY)) 5453 // Autofill mark is not visible. Bail out. 5454 return; 5455 5456 SCTAB nTab = pViewData->GetTabNo(); 5457 ScDocument* pDoc = pViewData->GetDocument(); 5458 sal_Bool bLayoutRTL = pDoc->IsLayoutRTL( nTab ); 5459 5460 Point aFillPos = pViewData->GetScrPos( nX, nY, eWhich, sal_True ); 5461 long nSizeXPix; 5462 long nSizeYPix; 5463 pViewData->GetMergeSizePixel( nX, nY, nSizeXPix, nSizeYPix ); 5464 if ( bLayoutRTL ) 5465 aFillPos.X() -= nSizeXPix + 3; 5466 else 5467 aFillPos.X() += nSizeXPix - 2; 5468 5469 aFillPos.Y() += nSizeYPix; 5470 aFillPos.Y() -= 2; 5471 mpAutoFillRect.reset(new Rectangle(aFillPos, Size(6, 6))); 5472 5473 // #i70788# get the OverlayManager safely 5474 ::sdr::overlay::OverlayManager* pOverlayManager = getOverlayManager(); 5475 5476 if(pOverlayManager) 5477 { 5478 const Color aHandleColor( SC_MOD()->GetColorConfig().GetColorValue(svtools::FONTCOLOR).nColor ); 5479 std::vector< basegfx::B2DRange > aRanges; 5480 const basegfx::B2DHomMatrix aTransform(GetInverseViewTransformation()); 5481 basegfx::B2DRange aRB(mpAutoFillRect->Left(), mpAutoFillRect->Top(), mpAutoFillRect->Right() + 1, mpAutoFillRect->Bottom() + 1); 5482 5483 aRB.transform(aTransform); 5484 aRanges.push_back(aRB); 5485 5486 sdr::overlay::OverlayObject* pOverlay = new sdr::overlay::OverlaySelection( 5487 sdr::overlay::OVERLAY_SOLID, 5488 aHandleColor, 5489 aRanges, 5490 false); 5491 5492 pOverlayManager->add(*pOverlay); 5493 mpOOAutoFill = new ::sdr::overlay::OverlayObjectList; 5494 mpOOAutoFill->append(*pOverlay); 5495 } 5496 5497 if ( aOldMode != aDrawMode ) 5498 SetMapMode( aOldMode ); 5499 } 5500 } 5501 5502 void ScGridWindow::DeleteDragRectOverlay() 5503 { 5504 DELETEZ( mpOODragRect ); 5505 } 5506 5507 void ScGridWindow::UpdateDragRectOverlay() 5508 { 5509 MapMode aDrawMode = GetDrawMapMode(); 5510 MapMode aOldMode = GetMapMode(); 5511 if ( aOldMode != aDrawMode ) 5512 SetMapMode( aDrawMode ); 5513 5514 DeleteDragRectOverlay(); 5515 5516 // get the rectangles in pixels (moved from DrawDragRect) 5517 5518 if ( bDragRect || bPagebreakDrawn ) 5519 { 5520 std::vector<Rectangle> aPixelRects; 5521 5522 SCCOL nX1 = bDragRect ? nDragStartX : aPagebreakDrag.aStart.Col(); 5523 SCROW nY1 = bDragRect ? nDragStartY : aPagebreakDrag.aStart.Row(); 5524 SCCOL nX2 = bDragRect ? nDragEndX : aPagebreakDrag.aEnd.Col(); 5525 SCROW nY2 = bDragRect ? nDragEndY : aPagebreakDrag.aEnd.Row(); 5526 5527 SCTAB nTab = pViewData->GetTabNo(); 5528 5529 SCCOL nPosX = pViewData->GetPosX(WhichH(eWhich)); 5530 SCROW nPosY = pViewData->GetPosY(WhichV(eWhich)); 5531 if (nX1 < nPosX) nX1 = nPosX; 5532 if (nX2 < nPosX) nX2 = nPosX; 5533 if (nY1 < nPosY) nY1 = nPosY; 5534 if (nY2 < nPosY) nY2 = nPosY; 5535 5536 Point aScrPos( pViewData->GetScrPos( nX1, nY1, eWhich ) ); 5537 5538 long nSizeXPix=0; 5539 long nSizeYPix=0; 5540 ScDocument* pDoc = pViewData->GetDocument(); 5541 double nPPTX = pViewData->GetPPTX(); 5542 double nPPTY = pViewData->GetPPTY(); 5543 SCCOLROW i; 5544 5545 sal_Bool bLayoutRTL = pDoc->IsLayoutRTL( nTab ); 5546 long nLayoutSign = bLayoutRTL ? -1 : 1; 5547 5548 if (ValidCol(nX2) && nX2>=nX1) 5549 for (i=nX1; i<=nX2; i++) 5550 nSizeXPix += ScViewData::ToPixel( pDoc->GetColWidth( static_cast<SCCOL>(i), nTab ), nPPTX ); 5551 else 5552 { 5553 aScrPos.X() -= nLayoutSign; 5554 nSizeXPix += 2; 5555 } 5556 5557 if (ValidRow(nY2) && nY2>=nY1) 5558 for (i=nY1; i<=nY2; i++) 5559 nSizeYPix += ScViewData::ToPixel( pDoc->GetRowHeight( i, nTab ), nPPTY ); 5560 else 5561 { 5562 aScrPos.Y() -= 1; 5563 nSizeYPix += 2; 5564 } 5565 5566 aScrPos.X() -= 2 * nLayoutSign; 5567 aScrPos.Y() -= 2; 5568 // Rectangle aRect( aScrPos, Size( nSizeXPix + 3, nSizeYPix + 3 ) ); 5569 Rectangle aRect( aScrPos.X(), aScrPos.Y(), 5570 aScrPos.X() + ( nSizeXPix + 2 ) * nLayoutSign, aScrPos.Y() + nSizeYPix + 2 ); 5571 if ( bLayoutRTL ) 5572 { 5573 aRect.Left() = aRect.Right(); // end position is left 5574 aRect.Right() = aScrPos.X(); 5575 } 5576 5577 if ( meDragInsertMode == INS_CELLSDOWN ) 5578 { 5579 aPixelRects.push_back( Rectangle( aRect.Left()+1, aRect.Top()+3, aRect.Left()+1, aRect.Bottom()-2 ) ); 5580 aPixelRects.push_back( Rectangle( aRect.Right()-1, aRect.Top()+3, aRect.Right()-1, aRect.Bottom()-2 ) ); 5581 aPixelRects.push_back( Rectangle( aRect.Left()+1, aRect.Top(), aRect.Right()-1, aRect.Top()+2 ) ); 5582 aPixelRects.push_back( Rectangle( aRect.Left()+1, aRect.Bottom()-1, aRect.Right()-1, aRect.Bottom()-1 ) ); 5583 } 5584 else if ( meDragInsertMode == INS_CELLSRIGHT ) 5585 { 5586 aPixelRects.push_back( Rectangle( aRect.Left(), aRect.Top()+1, aRect.Left()+2, aRect.Bottom()-1 ) ); 5587 aPixelRects.push_back( Rectangle( aRect.Right()-1, aRect.Top()+1, aRect.Right()-1, aRect.Bottom()-1 ) ); 5588 aPixelRects.push_back( Rectangle( aRect.Left()+3, aRect.Top()+1, aRect.Right()-2, aRect.Top()+1 ) ); 5589 aPixelRects.push_back( Rectangle( aRect.Left()+3, aRect.Bottom()-1, aRect.Right()-2, aRect.Bottom()-1 ) ); 5590 } 5591 else 5592 { 5593 aPixelRects.push_back( Rectangle( aRect.Left(), aRect.Top(), aRect.Left()+2, aRect.Bottom() ) ); 5594 aPixelRects.push_back( Rectangle( aRect.Right()-2, aRect.Top(), aRect.Right(), aRect.Bottom() ) ); 5595 aPixelRects.push_back( Rectangle( aRect.Left()+3, aRect.Top(), aRect.Right()-3, aRect.Top()+2 ) ); 5596 aPixelRects.push_back( Rectangle( aRect.Left()+3, aRect.Bottom()-2, aRect.Right()-3, aRect.Bottom() ) ); 5597 } 5598 5599 // #i70788# get the OverlayManager safely 5600 ::sdr::overlay::OverlayManager* pOverlayManager = getOverlayManager(); 5601 5602 if(pOverlayManager) 5603 { 5604 // Color aHighlight = GetSettings().GetStyleSettings().GetHighlightColor(); 5605 std::vector< basegfx::B2DRange > aRanges; 5606 const basegfx::B2DHomMatrix aTransform(GetInverseViewTransformation()); 5607 5608 for(sal_uInt32 a(0); a < aPixelRects.size(); a++) 5609 { 5610 const Rectangle aRA(aPixelRects[a]); 5611 basegfx::B2DRange aRB(aRA.Left(), aRA.Top(), aRA.Right() + 1, aRA.Bottom() + 1); 5612 aRB.transform(aTransform); 5613 aRanges.push_back(aRB); 5614 } 5615 5616 sdr::overlay::OverlayObject* pOverlay = new sdr::overlay::OverlaySelection( 5617 sdr::overlay::OVERLAY_INVERT, 5618 Color(COL_BLACK), 5619 aRanges, 5620 false); 5621 5622 pOverlayManager->add(*pOverlay); 5623 mpOODragRect = new ::sdr::overlay::OverlayObjectList; 5624 mpOODragRect->append(*pOverlay); 5625 } 5626 } 5627 5628 if ( aOldMode != aDrawMode ) 5629 SetMapMode( aOldMode ); 5630 } 5631 5632 void ScGridWindow::DeleteHeaderOverlay() 5633 { 5634 DELETEZ( mpOOHeader ); 5635 } 5636 5637 void ScGridWindow::UpdateHeaderOverlay() 5638 { 5639 MapMode aDrawMode = GetDrawMapMode(); 5640 MapMode aOldMode = GetMapMode(); 5641 if ( aOldMode != aDrawMode ) 5642 SetMapMode( aDrawMode ); 5643 5644 DeleteHeaderOverlay(); 5645 5646 // Pixel rectangle is in aInvertRect 5647 if ( !aInvertRect.IsEmpty() ) 5648 { 5649 // #i70788# get the OverlayManager safely 5650 ::sdr::overlay::OverlayManager* pOverlayManager = getOverlayManager(); 5651 5652 if(pOverlayManager) 5653 { 5654 // Color aHighlight = GetSettings().GetStyleSettings().GetHighlightColor(); 5655 std::vector< basegfx::B2DRange > aRanges; 5656 const basegfx::B2DHomMatrix aTransform(GetInverseViewTransformation()); 5657 basegfx::B2DRange aRB(aInvertRect.Left(), aInvertRect.Top(), aInvertRect.Right() + 1, aInvertRect.Bottom() + 1); 5658 5659 aRB.transform(aTransform); 5660 aRanges.push_back(aRB); 5661 5662 sdr::overlay::OverlayObject* pOverlay = new sdr::overlay::OverlaySelection( 5663 sdr::overlay::OVERLAY_INVERT, 5664 Color(COL_BLACK), 5665 aRanges, 5666 false); 5667 5668 pOverlayManager->add(*pOverlay); 5669 mpOOHeader = new ::sdr::overlay::OverlayObjectList; 5670 mpOOHeader->append(*pOverlay); 5671 } 5672 } 5673 5674 if ( aOldMode != aDrawMode ) 5675 SetMapMode( aOldMode ); 5676 } 5677 5678 void ScGridWindow::DeleteShrinkOverlay() 5679 { 5680 DELETEZ( mpOOShrink ); 5681 } 5682 5683 void ScGridWindow::UpdateShrinkOverlay() 5684 { 5685 MapMode aDrawMode = GetDrawMapMode(); 5686 MapMode aOldMode = GetMapMode(); 5687 if ( aOldMode != aDrawMode ) 5688 SetMapMode( aDrawMode ); 5689 5690 DeleteShrinkOverlay(); 5691 5692 // get the rectangle in pixels 5693 5694 Rectangle aPixRect; 5695 ScRange aRange; 5696 SCTAB nTab = pViewData->GetTabNo(); 5697 if ( pViewData->IsRefMode() && nTab >= pViewData->GetRefStartZ() && nTab <= pViewData->GetRefEndZ() && 5698 pViewData->GetDelMark( aRange ) ) 5699 { 5700 //! limit to visible area 5701 if ( aRange.aStart.Col() <= aRange.aEnd.Col() && 5702 aRange.aStart.Row() <= aRange.aEnd.Row() ) 5703 { 5704 Point aStart = pViewData->GetScrPos( aRange.aStart.Col(), 5705 aRange.aStart.Row(), eWhich ); 5706 Point aEnd = pViewData->GetScrPos( aRange.aEnd.Col()+1, 5707 aRange.aEnd.Row()+1, eWhich ); 5708 aEnd.X() -= 1; 5709 aEnd.Y() -= 1; 5710 5711 aPixRect = Rectangle( aStart,aEnd ); 5712 } 5713 } 5714 5715 if ( !aPixRect.IsEmpty() ) 5716 { 5717 // #i70788# get the OverlayManager safely 5718 ::sdr::overlay::OverlayManager* pOverlayManager = getOverlayManager(); 5719 5720 if(pOverlayManager) 5721 { 5722 // Color aHighlight = GetSettings().GetStyleSettings().GetHighlightColor(); 5723 std::vector< basegfx::B2DRange > aRanges; 5724 const basegfx::B2DHomMatrix aTransform(GetInverseViewTransformation()); 5725 basegfx::B2DRange aRB(aPixRect.Left(), aPixRect.Top(), aPixRect.Right() + 1, aPixRect.Bottom() + 1); 5726 5727 aRB.transform(aTransform); 5728 aRanges.push_back(aRB); 5729 5730 sdr::overlay::OverlayObject* pOverlay = new sdr::overlay::OverlaySelection( 5731 sdr::overlay::OVERLAY_INVERT, 5732 Color(COL_BLACK), 5733 aRanges, 5734 false); 5735 5736 pOverlayManager->add(*pOverlay); 5737 mpOOShrink = new ::sdr::overlay::OverlayObjectList; 5738 mpOOShrink->append(*pOverlay); 5739 } 5740 } 5741 5742 if ( aOldMode != aDrawMode ) 5743 SetMapMode( aOldMode ); 5744 } 5745 5746 // #i70788# central method to get the OverlayManager safely 5747 ::sdr::overlay::OverlayManager* ScGridWindow::getOverlayManager() 5748 { 5749 SdrPageView* pPV = pViewData->GetView()->GetScDrawView()->GetSdrPageView(); 5750 5751 if(pPV) 5752 { 5753 SdrPageWindow* pPageWin = pPV->FindPageWindow( *this ); 5754 5755 if ( pPageWin ) 5756 { 5757 return (pPageWin->GetOverlayManager()); 5758 } 5759 } 5760 5761 return 0L; 5762 } 5763 5764 void ScGridWindow::flushOverlayManager() 5765 { 5766 // #i70788# get the OverlayManager safely 5767 ::sdr::overlay::OverlayManager* pOverlayManager = getOverlayManager(); 5768 5769 if(pOverlayManager) 5770 { 5771 pOverlayManager->flush(); 5772 } 5773 } 5774 5775 /* vim: set noet sw=4 ts=4: */ 5776