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 23 24 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_sc.hxx" 26 27 #include "scitems.hxx" 28 29 #include <memory> //auto_ptr 30 #include <editeng/adjitem.hxx> 31 #include <svx/algitem.hxx> 32 #include <svx/dbexch.hrc> 33 #include <editeng/editview.hxx> 34 #include <editeng/editstat.hxx> 35 #include <editeng/flditem.hxx> 36 #include <svx/svdetc.hxx> 37 #include <editeng/editobj.hxx> 38 #include <sfx2/dispatch.hxx> 39 #include <sfx2/viewfrm.hxx> 40 #include <sfx2/docfile.hxx> 41 #include <svl/stritem.hxx> 42 #include <svtools/svlbox.hxx> 43 #include <svtools/svtabbx.hxx> 44 #include <svl/urlbmk.hxx> 45 #include <tools/urlobj.hxx> 46 #include <vcl/cursor.hxx> 47 #include <vcl/sound.hxx> 48 #include <vcl/graph.hxx> 49 #include <vcl/hatch.hxx> 50 #include <sot/formats.hxx> 51 #include <sot/clsids.hxx> 52 53 #include <svx/svdview.hxx> // fuer Command-Handler (COMMAND_INSERTTEXT) 54 #include <editeng/outliner.hxx> // fuer Command-Handler (COMMAND_INSERTTEXT) 55 #include <svx/svditer.hxx> 56 #include <svx/svdocapt.hxx> 57 #include <svx/svdpagv.hxx> 58 59 #include <com/sun/star/sheet/DataPilotFieldFilter.hpp> 60 #include <com/sun/star/sheet/DataPilotFieldOrientation.hpp> 61 #include <com/sun/star/sheet/DataPilotTableHeaderData.hpp> 62 #include <com/sun/star/sheet/DataPilotTableResultData.hpp> 63 #include <com/sun/star/sheet/DataPilotTablePositionData.hpp> 64 #include <com/sun/star/sheet/DataPilotTablePositionType.hpp> 65 #include <com/sun/star/sheet/MemberResultFlags.hpp> 66 #include <com/sun/star/awt/KeyModifier.hpp> 67 #include <com/sun/star/awt/MouseButton.hpp> 68 #include <com/sun/star/script/vba/VBAEventId.hpp> 69 #include <com/sun/star/script/vba/XVBAEventProcessor.hpp> 70 71 #include "gridwin.hxx" 72 #include "tabvwsh.hxx" 73 #include "docsh.hxx" 74 #include "viewdata.hxx" 75 #include "tabview.hxx" 76 #include "select.hxx" 77 #include "scmod.hxx" 78 #include "document.hxx" 79 #include "attrib.hxx" 80 #include "dbcolect.hxx" 81 #include "stlpool.hxx" 82 #include "printfun.hxx" 83 #include "cbutton.hxx" 84 #include "sc.hrc" 85 #include "globstr.hrc" 86 #include "editutil.hxx" 87 #include "scresid.hxx" 88 #include "inputhdl.hxx" 89 #include "uiitems.hxx" // Filter-Dialog - auslagern !!! 90 #include "filtdlg.hxx" 91 #include "impex.hxx" // Sylk-ID fuer CB 92 #include "cell.hxx" // fuer Edit-Felder 93 #include "patattr.hxx" 94 #include "notemark.hxx" 95 #include "rfindlst.hxx" 96 #include "docpool.hxx" 97 #include "output.hxx" 98 #include "docfunc.hxx" 99 #include "dbdocfun.hxx" 100 #include "dpobject.hxx" 101 #include "dpoutput.hxx" 102 #include "transobj.hxx" 103 #include "drwtrans.hxx" 104 #include "seltrans.hxx" 105 #include "sizedev.hxx" 106 #include "AccessibilityHints.hxx" 107 #include "dpsave.hxx" 108 #include "viewuno.hxx" 109 #include "compiler.hxx" 110 #include "editable.hxx" 111 #include "fillinfo.hxx" 112 #include "scitems.hxx" 113 #include "userdat.hxx" 114 #include "drwlayer.hxx" 115 #include "attrib.hxx" 116 #include "validat.hxx" 117 #include "tabprotection.hxx" 118 #include "postit.hxx" 119 #include "dpcontrol.hxx" 120 #include "cellsuno.hxx" 121 122 #include "drawview.hxx" 123 #include <svx/sdrpagewindow.hxx> 124 #include <svx/sdr/overlay/overlaymanager.hxx> 125 #include <vcl/svapp.hxx> 126 #include <svx/sdr/overlay/overlayselection.hxx> 127 128 using namespace com::sun::star; 129 using ::com::sun::star::uno::Sequence; 130 using ::com::sun::star::uno::Any; 131 132 const sal_uInt8 SC_NESTEDBUTTON_NONE = 0; 133 const sal_uInt8 SC_NESTEDBUTTON_DOWN = 1; 134 const sal_uInt8 SC_NESTEDBUTTON_UP = 2; 135 136 #define SC_AUTOFILTER_ALL 0 137 #define SC_AUTOFILTER_TOP10 1 138 #define SC_AUTOFILTER_CUSTOM 2 139 140 // Modi fuer 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(); // auswaehlen 265 nDone = 1; 266 } 267 else if ( nKey == KEY_ESCAPE ) 268 { 269 pGridWin->ClickExtern(); // loescht 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, enthaelt 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 noetig fuer 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: falsche 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 auswaehlen 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 //! Texthoehe 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 spaeter 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 Groesse feststeht 795 796 // Listbox fuellen 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; // fuer Rand 820 if ( nMaxText > 300 ) 821 nMaxText = 300; // auch nicht uebertreiben (Pixel) 822 823 if (nMaxText > nSizeX) // Groesse auf benoetigte Groesse 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 naechste 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 spaeter 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 }; 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 Groesse an Fenster anpassen 1023 //! vorher Abfrage, ob die Eintraege 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 Eintraege 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 naechste 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 Eintraege 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 ) // loeschen 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 1315 { 1316 rNewEntry.eOp = SC_EQUAL; 1317 *rNewEntry.pStr = aValue; 1318 } 1319 if (nQueryPos > 0) 1320 rNewEntry.eConnect = SC_AND; 1321 } 1322 else 1323 { 1324 if (bFound) 1325 aParam.DeleteQuery(nQueryPos); 1326 } 1327 1328 // #100597# end edit mode - like in ScCellShell::ExecuteDB 1329 if ( pViewData->HasEditView( pViewData->GetActivePart() ) ) 1330 { 1331 SC_MOD()->InputEnterHandler(); 1332 pViewData->GetViewShell()->UpdateInputHandler(); 1333 } 1334 1335 pViewData->GetView()->Query( aParam, NULL, sal_True ); 1336 pDBData->SetQueryParam( aParam ); // speichern 1337 } 1338 else // "Zuviele Bedingungen" 1339 pViewData->GetView()->ErrorMessage( STR_FILTER_TOOMANY ); 1340 } 1341 } 1342 else 1343 { 1344 DBG_ERROR("Wo ist der Datenbankbereich?"); 1345 } 1346 } 1347 1348 void ScGridWindow::SetPointer( const Pointer& rPointer ) 1349 { 1350 nCurrentPointer = 0; 1351 Window::SetPointer( rPointer ); 1352 } 1353 1354 void ScGridWindow::MoveMouseStatus( ScGridWindow& rDestWin ) 1355 { 1356 if (nButtonDown) 1357 { 1358 rDestWin.nButtonDown = nButtonDown; 1359 rDestWin.nMouseStatus = nMouseStatus; 1360 } 1361 1362 if (bRFMouse) 1363 { 1364 rDestWin.bRFMouse = bRFMouse; 1365 rDestWin.bRFSize = bRFSize; 1366 rDestWin.nRFIndex = nRFIndex; 1367 rDestWin.nRFAddX = nRFAddX; 1368 rDestWin.nRFAddY = nRFAddY; 1369 bRFMouse = sal_False; 1370 } 1371 1372 if (nPagebreakMouse) 1373 { 1374 rDestWin.nPagebreakMouse = nPagebreakMouse; 1375 rDestWin.nPagebreakBreak = nPagebreakBreak; 1376 rDestWin.nPagebreakPrev = nPagebreakPrev; 1377 rDestWin.aPagebreakSource = aPagebreakSource; 1378 rDestWin.aPagebreakDrag = aPagebreakDrag; 1379 nPagebreakMouse = SC_PD_NONE; 1380 } 1381 } 1382 1383 sal_Bool ScGridWindow::TestMouse( const MouseEvent& rMEvt, sal_Bool bAction ) 1384 { 1385 // MouseEvent buttons must only be checked if bAction==TRUE 1386 // to allow changing the mouse pointer in MouseMove, 1387 // but not start AutoFill with right button (#74229#). 1388 // with bAction==sal_True, SetFillMode / SetDragMode is called 1389 1390 if ( bAction && !rMEvt.IsLeft() ) 1391 return sal_False; 1392 1393 sal_Bool bNewPointer = sal_False; 1394 1395 SfxInPlaceClient* pClient = pViewData->GetViewShell()->GetIPClient(); 1396 sal_Bool bOleActive = ( pClient && pClient->IsObjectInPlaceActive() ); 1397 1398 if ( pViewData->IsActive() && !bOleActive ) 1399 { 1400 ScDocument* pDoc = pViewData->GetDocument(); 1401 SCTAB nTab = pViewData->GetTabNo(); 1402 sal_Bool bLayoutRTL = pDoc->IsLayoutRTL( nTab ); 1403 1404 // Auto-Fill 1405 1406 ScRange aMarkRange; 1407 if (pViewData->GetSimpleArea( aMarkRange ) == SC_MARK_SIMPLE) 1408 { 1409 if (aMarkRange.aStart.Tab() == pViewData->GetTabNo() && mpAutoFillRect) 1410 { 1411 Point aMousePos = rMEvt.GetPosPixel(); 1412 if (mpAutoFillRect->IsInside(aMousePos)) 1413 { 1414 SetPointer( Pointer( POINTER_CROSS ) ); //! dickeres Kreuz ? 1415 if (bAction) 1416 { 1417 SCCOL nX = aMarkRange.aEnd.Col(); 1418 SCROW nY = aMarkRange.aEnd.Row(); 1419 1420 if ( lcl_IsEditableMatrix( pViewData->GetDocument(), aMarkRange ) ) 1421 pViewData->SetDragMode( 1422 aMarkRange.aStart.Col(), aMarkRange.aStart.Row(), nX, nY, SC_FILL_MATRIX ); 1423 else 1424 pViewData->SetFillMode( 1425 aMarkRange.aStart.Col(), aMarkRange.aStart.Row(), nX, nY ); 1426 1427 // #108266# The simple selection must also be recognized when dragging, 1428 // where the Marking flag is set and MarkToSimple won't work anymore. 1429 pViewData->GetMarkData().MarkToSimple(); 1430 } 1431 bNewPointer = sal_True; 1432 } 1433 } 1434 } 1435 1436 // Embedded-Rechteck 1437 1438 if (pDoc->IsEmbedded()) 1439 { 1440 ScRange aRange; 1441 pDoc->GetEmbedded( aRange ); 1442 if ( pViewData->GetTabNo() == aRange.aStart.Tab() ) 1443 { 1444 Point aStartPos = pViewData->GetScrPos( aRange.aStart.Col(), aRange.aStart.Row(), eWhich ); 1445 Point aEndPos = pViewData->GetScrPos( aRange.aEnd.Col()+1, aRange.aEnd.Row()+1, eWhich ); 1446 Point aMousePos = rMEvt.GetPosPixel(); 1447 if ( bLayoutRTL ) 1448 { 1449 aStartPos.X() += 2; 1450 aEndPos.X() += 2; 1451 } 1452 sal_Bool bTop = ( aMousePos.X() >= aStartPos.X()-3 && aMousePos.X() <= aStartPos.X()+1 && 1453 aMousePos.Y() >= aStartPos.Y()-3 && aMousePos.Y() <= aStartPos.Y()+1 ); 1454 sal_Bool bBottom = ( aMousePos.X() >= aEndPos.X()-3 && aMousePos.X() <= aEndPos.X()+1 && 1455 aMousePos.Y() >= aEndPos.Y()-3 && aMousePos.Y() <= aEndPos.Y()+1 ); 1456 if ( bTop || bBottom ) 1457 { 1458 SetPointer( Pointer( POINTER_CROSS ) ); 1459 if (bAction) 1460 { 1461 sal_uInt8 nMode = bTop ? SC_FILL_EMBED_LT : SC_FILL_EMBED_RB; 1462 pViewData->SetDragMode( 1463 aRange.aStart.Col(), aRange.aStart.Row(), 1464 aRange.aEnd.Col(), aRange.aEnd.Row(), nMode ); 1465 } 1466 bNewPointer = sal_True; 1467 } 1468 } 1469 } 1470 } 1471 1472 if (!bNewPointer && bAction) 1473 { 1474 // SetPointer( POINTER_ARROW ); // in Fu... 1475 pViewData->ResetFillMode(); 1476 } 1477 1478 return bNewPointer; 1479 } 1480 1481 void __EXPORT ScGridWindow::MouseButtonDown( const MouseEvent& rMEvt ) 1482 { 1483 nNestedButtonState = SC_NESTEDBUTTON_DOWN; 1484 1485 HandleMouseButtonDown( rMEvt ); 1486 1487 if ( nNestedButtonState == SC_NESTEDBUTTON_UP ) 1488 { 1489 // #i41690# If an object is deactivated from MouseButtonDown, it might reschedule, 1490 // so MouseButtonUp comes before the MouseButtonDown call is finished. In this case, 1491 // simulate another MouseButtonUp call, so the selection state is consistent. 1492 1493 nButtonDown = rMEvt.GetButtons(); 1494 FakeButtonUp(); 1495 1496 if ( IsTracking() ) 1497 EndTracking(); // normally done in VCL as part of MouseButtonUp handling 1498 } 1499 nNestedButtonState = SC_NESTEDBUTTON_NONE; 1500 } 1501 1502 void ScGridWindow::HandleMouseButtonDown( const MouseEvent& rMEvt ) 1503 { 1504 // We have to check if a context menu is shown and we have an UI 1505 // active inplace client. In that case we have to ignore the event. 1506 // Otherwise we would crash (context menu has been 1507 // opened by inplace client and we would deactivate the inplace client, 1508 // the contex menu is closed by VCL asynchronously which in the end 1509 // would work on deleted objects or the context menu has no parent anymore) 1510 // See #126086# and #128122# 1511 SfxViewShell* pViewSh = pViewData->GetViewShell(); 1512 SfxInPlaceClient* pClient = pViewSh->GetIPClient(); 1513 if ( pClient && 1514 pClient->IsObjectInPlaceActive() && 1515 PopupMenu::IsInExecute() ) 1516 return; 1517 1518 aCurMousePos = rMEvt.GetPosPixel(); 1519 1520 // Filter-Popup beendet sich mit eigenem Mausklick, nicht erst beim Klick 1521 // in das GridWindow, darum ist die folgende Abfrage nicht mehr noetig: 1522 #if 0 1523 // merken, dass FilterBox geloescht wird, damit sichergestellt 1524 // ist, dass in diesem Handler nicht an gleicher Stelle wieder 1525 // eine neue geoeffnet wird. 1526 sal_Bool bWasFilterBox = ( pFilterBox != NULL && 1527 ((Window*)pFilterBox)->IsVisible() && 1528 !pFilterBox->IsDataSelect() ); 1529 SCCOL nOldColFBox = bWasFilterBox ? pFilterBox->GetCol() : 0; 1530 SCROW nOldRowFBox = bWasFilterBox ? pFilterBox->GetRow() : 0; 1531 #endif 1532 1533 ClickExtern(); // loescht FilterBox, wenn vorhanden 1534 1535 HideNoteMarker(); // Notiz-Anzeige 1536 1537 bEEMouse = sal_False; 1538 1539 ScModule* pScMod = SC_MOD(); 1540 if (pScMod->IsModalMode(pViewData->GetSfxDocShell())) 1541 { 1542 Sound::Beep(); 1543 return; 1544 } 1545 1546 pScActiveViewShell = pViewData->GetViewShell(); // falls auf Link geklickt wird 1547 nScClickMouseModifier = rMEvt.GetModifier(); // um Control-Klick immer zu erkennen 1548 1549 sal_Bool bDetective = pViewData->GetViewShell()->IsAuditShell(); 1550 sal_Bool bRefMode = pViewData->IsRefMode(); // Referenz angefangen 1551 sal_Bool bFormulaMode = pScMod->IsFormulaMode(); // naechster Klick -> Referenz 1552 sal_Bool bEditMode = pViewData->HasEditView(eWhich); // auch bei Mode==SC_INPUT_TYPE 1553 sal_Bool bDouble = (rMEvt.GetClicks() == 2); 1554 1555 // DeactivateIP passiert nur noch bei MarkListHasChanged 1556 1557 // im GrabFocus Aufruf kann eine Fehlermeldung hochkommen 1558 // (z.B. beim Umbenennen von Tabellen per Tab-Reiter) 1559 1560 if ( !nButtonDown || !bDouble ) // single (first) click is always valid 1561 nButtonDown = rMEvt.GetButtons(); // set nButtonDown first, so StopMarking works 1562 1563 // pViewData->GetViewShell()->GetViewFrame()->GetWindow().GrabFocus(); 1564 if ( ( bEditMode && pViewData->GetActivePart() == eWhich ) || !bFormulaMode ) 1565 GrabFocus(); 1566 1567 // #i31846# need to cancel a double click if the first click has set the "ignore" state, 1568 // but a single (first) click is always valid 1569 if ( nMouseStatus == SC_GM_IGNORE && bDouble ) 1570 { 1571 nButtonDown = 0; 1572 nMouseStatus = SC_GM_NONE; 1573 return; 1574 } 1575 1576 if ( bDetective ) // Detektiv-Fuell-Modus 1577 { 1578 if ( rMEvt.IsLeft() && !rMEvt.GetModifier() ) 1579 { 1580 Point aPos = rMEvt.GetPosPixel(); 1581 SCsCOL nPosX; 1582 SCsROW nPosY; 1583 pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY ); 1584 1585 SfxInt16Item aPosXItem( SID_RANGE_COL, nPosX ); 1586 SfxInt32Item aPosYItem( SID_RANGE_ROW, nPosY ); 1587 pViewData->GetDispatcher().Execute( SID_FILL_SELECT, SFX_CALLMODE_SLOT | SFX_CALLMODE_RECORD, 1588 &aPosXItem, &aPosYItem, (void*)0L ); 1589 1590 } 1591 nButtonDown = 0; 1592 nMouseStatus = SC_GM_NONE; 1593 return; 1594 } 1595 1596 if (!bDouble) 1597 nMouseStatus = SC_GM_NONE; 1598 1599 if (!bFormulaMode) 1600 { 1601 if ( pViewData->GetActivePart() != eWhich ) 1602 pViewData->GetView()->ActivatePart( eWhich ); 1603 } 1604 else 1605 { 1606 ScViewSelectionEngine* pSelEng = pViewData->GetView()->GetSelEngine(); 1607 pSelEng->SetWindow(this); 1608 pSelEng->SetWhich(eWhich); 1609 pSelEng->SetVisibleArea( Rectangle(Point(), GetOutputSizePixel()) ); 1610 } 1611 1612 if (bEditMode && (pViewData->GetRefTabNo() == pViewData->GetTabNo())) 1613 { 1614 Point aPos = rMEvt.GetPosPixel(); 1615 SCsCOL nPosX; 1616 SCsROW nPosY; 1617 pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY ); 1618 1619 EditView* pEditView; 1620 SCCOL nEditCol; 1621 SCROW nEditRow; 1622 pViewData->GetEditView( eWhich, pEditView, nEditCol, nEditRow ); 1623 SCCOL nEndCol = pViewData->GetEditEndCol(); 1624 SCROW nEndRow = pViewData->GetEditEndRow(); 1625 1626 if ( nPosX >= (SCsCOL) nEditCol && nPosX <= (SCsCOL) nEndCol && 1627 nPosY >= (SCsROW) nEditRow && nPosY <= (SCsROW) nEndRow ) 1628 { 1629 // #53966# beim Klick in die Tabellen-EditView immer den Focus umsetzen 1630 if (bFormulaMode) // sonst ist es oben schon passiert 1631 GrabFocus(); 1632 1633 pScMod->SetInputMode( SC_INPUT_TABLE ); 1634 bEEMouse = sal_True; 1635 bEditMode = pEditView->MouseButtonDown( rMEvt ); 1636 return; 1637 } 1638 } 1639 1640 if (pScMod->GetIsWaterCan()) 1641 { 1642 //! was is mit'm Mac ??? 1643 if ( rMEvt.GetModifier() + rMEvt.GetButtons() == MOUSE_RIGHT ) 1644 { 1645 nMouseStatus = SC_GM_WATERUNDO; 1646 return; 1647 } 1648 } 1649 1650 // Reihenfolge passend zum angezeigten Cursor: 1651 // RangeFinder, AutoFill, PageBreak, Drawing 1652 1653 if ( HitRangeFinder( rMEvt.GetPosPixel(), bRFSize, &nRFIndex, &nRFAddX, &nRFAddY ) ) 1654 { 1655 bRFMouse = sal_True; // die anderen Variablen sind oben initialisiert 1656 1657 if ( pViewData->GetActivePart() != eWhich ) 1658 pViewData->GetView()->ActivatePart( eWhich ); //! schon oben immer ??? 1659 1660 // CaptureMouse(); 1661 StartTracking(); 1662 return; 1663 } 1664 1665 sal_Bool bCrossPointer = TestMouse( rMEvt, sal_True ); 1666 if ( bCrossPointer ) 1667 { 1668 if ( bDouble ) 1669 pViewData->GetView()->FillCrossDblClick(); 1670 else 1671 pScMod->InputEnterHandler(); // Autofill etc. 1672 } 1673 1674 if ( !bCrossPointer ) 1675 { 1676 nPagebreakMouse = HitPageBreak( rMEvt.GetPosPixel(), &aPagebreakSource, 1677 &nPagebreakBreak, &nPagebreakPrev ); 1678 if (nPagebreakMouse) 1679 { 1680 bPagebreakDrawn = sal_False; 1681 // CaptureMouse(); 1682 StartTracking(); 1683 PagebreakMove( rMEvt, sal_False ); 1684 return; 1685 } 1686 } 1687 1688 if (!bFormulaMode && !bEditMode && rMEvt.IsLeft()) 1689 { 1690 if ( !bCrossPointer && DrawMouseButtonDown(rMEvt) ) 1691 { 1692 //if (DrawHasMarkedObj()) 1693 // pViewData->GetViewShell()->SetDrawShellOrSub(); // Draw-Objekt selektiert 1694 return; 1695 } 1696 1697 pViewData->GetViewShell()->SetDrawShell( sal_False ); // kein Draw-Objekt selektiert 1698 1699 // TestMouse schon oben passiert 1700 } 1701 1702 Point aPos = rMEvt.GetPosPixel(); 1703 SCsCOL nPosX; 1704 SCsROW nPosY; 1705 pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY ); 1706 SCTAB nTab = pViewData->GetTabNo(); 1707 ScDocument* pDoc = pViewData->GetDocument(); 1708 1709 1710 // 1711 // AutoFilter buttons 1712 // 1713 1714 if ( !bDouble && !bFormulaMode && rMEvt.IsLeft() ) 1715 { 1716 SCsCOL nRealPosX; 1717 SCsROW nRealPosY; 1718 pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nRealPosX, nRealPosY, false );//the real row/col 1719 ScMergeFlagAttr* pRealPosAttr = (ScMergeFlagAttr*) 1720 pDoc->GetAttr( nRealPosX, nRealPosY, nTab, ATTR_MERGE_FLAG ); 1721 ScMergeFlagAttr* pAttr = (ScMergeFlagAttr*) 1722 pDoc->GetAttr( nPosX, nPosY, nTab, ATTR_MERGE_FLAG ); 1723 if( pRealPosAttr->HasAutoFilter() ) 1724 { 1725 SC_MOD()->InputEnterHandler(); 1726 if (DoAutoFilterButton( nRealPosX, nRealPosY, rMEvt)) 1727 return; 1728 } 1729 if( pAttr->HasAutoFilter() ) 1730 { 1731 SC_MOD()->InputEnterHandler(); //Add for i85305 1732 if (DoAutoFilterButton( nPosX, nPosY, rMEvt)) 1733 return; 1734 } 1735 if (pAttr->HasButton()) 1736 { 1737 DoPushButton( nPosX, nPosY, rMEvt ); // setzt evtl. bPivotMouse / bDPMouse 1738 return; 1739 } 1740 1741 // List Validity drop-down button 1742 1743 if ( bListValButton ) 1744 { 1745 Rectangle aButtonRect = GetListValButtonRect( aListValPos ); 1746 if ( aButtonRect.IsInside( aPos ) ) 1747 { 1748 DoAutoFilterMenue( aListValPos.Col(), aListValPos.Row(), sal_True ); 1749 1750 nMouseStatus = SC_GM_FILTER; // not set in DoAutoFilterMenue for bDataSelect 1751 CaptureMouse(); 1752 return; 1753 } 1754 } 1755 } 1756 1757 // 1758 // scenario selection 1759 // 1760 1761 ScRange aScenRange; 1762 if ( rMEvt.IsLeft() && HasScenarioButton( aPos, aScenRange ) ) 1763 { 1764 DoScenarioMenue( aScenRange ); 1765 return; 1766 } 1767 1768 // 1769 // Doppelklick angefangen ? 1770 // 1771 1772 // StopMarking kann aus DrawMouseButtonDown gerufen werden 1773 1774 if ( nMouseStatus != SC_GM_IGNORE && !bRefMode ) 1775 { 1776 if ( bDouble && !bCrossPointer ) 1777 { 1778 if (nMouseStatus == SC_GM_TABDOWN) 1779 nMouseStatus = SC_GM_DBLDOWN; 1780 } 1781 else 1782 nMouseStatus = SC_GM_TABDOWN; 1783 } 1784 1785 // 1786 // Links in Edit-Zellen 1787 // 1788 1789 sal_Bool bAlt = rMEvt.IsMod2(); 1790 if ( !bAlt && rMEvt.IsLeft() && 1791 GetEditUrl(rMEvt.GetPosPixel()) ) // Klick auf Link: Cursor nicht bewegen 1792 { 1793 SetPointer( Pointer( POINTER_REFHAND ) ); 1794 nMouseStatus = SC_GM_URLDOWN; // auch nur dann beim ButtonUp ausfuehren 1795 return; 1796 } 1797 1798 // 1799 // Gridwin - SelectionEngine 1800 // 1801 1802 if ( rMEvt.IsLeft() ) 1803 { 1804 ScViewSelectionEngine* pSelEng = pViewData->GetView()->GetSelEngine(); 1805 pSelEng->SetWindow(this); 1806 pSelEng->SetWhich(eWhich); 1807 pSelEng->SetVisibleArea( Rectangle(Point(), GetOutputSizePixel()) ); 1808 1809 // SelMouseButtonDown an der View setzt noch das bMoveIsShift Flag 1810 if ( pViewData->GetView()->SelMouseButtonDown( rMEvt ) ) 1811 { 1812 if (IsMouseCaptured()) 1813 { 1814 // Tracking statt CaptureMouse, damit sauber abgebrochen werden kann 1815 //! Irgendwann sollte die SelectionEngine selber StartTracking rufen!?! 1816 ReleaseMouse(); 1817 StartTracking(); 1818 } 1819 pViewData->GetMarkData().SetMarking(sal_True); 1820 return; 1821 } 1822 } 1823 } 1824 1825 void __EXPORT ScGridWindow::MouseButtonUp( const MouseEvent& rMEvt ) 1826 { 1827 aCurMousePos = rMEvt.GetPosPixel(); 1828 ScDocument* pDoc = pViewData->GetDocument(); 1829 ScMarkData& rMark = pViewData->GetMarkData(); 1830 1831 // #i41690# detect a MouseButtonUp call from within MouseButtonDown 1832 // (possible through Reschedule from storing an OLE object that is deselected) 1833 1834 if ( nNestedButtonState == SC_NESTEDBUTTON_DOWN ) 1835 nNestedButtonState = SC_NESTEDBUTTON_UP; 1836 1837 if (nButtonDown != rMEvt.GetButtons()) 1838 nMouseStatus = SC_GM_IGNORE; // reset und return 1839 1840 nButtonDown = 0; 1841 1842 if (nMouseStatus == SC_GM_IGNORE) 1843 { 1844 nMouseStatus = SC_GM_NONE; 1845 // Selection-Engine: Markieren abbrechen 1846 pViewData->GetView()->GetSelEngine()->Reset(); 1847 rMark.SetMarking(sal_False); 1848 if (pViewData->IsAnyFillMode()) 1849 { 1850 pViewData->GetView()->StopRefMode(); 1851 pViewData->ResetFillMode(); 1852 } 1853 StopMarking(); 1854 DrawEndAction(); // Markieren/Verschieben auf Drawing-Layer abbrechen 1855 ReleaseMouse(); 1856 return; 1857 } 1858 1859 if (nMouseStatus == SC_GM_FILTER) 1860 { 1861 if ( pFilterBox && pFilterBox->GetMode() == SC_FILTERBOX_FILTER ) 1862 { 1863 if (mpFilterButton.get()) 1864 { 1865 bool bFilterActive = IsAutoFilterActive( 1866 pFilterBox->GetCol(), pFilterBox->GetRow(), pViewData->GetTabNo() ); 1867 1868 mpFilterButton->setHasHiddenMember(bFilterActive); 1869 mpFilterButton->setPopupPressed(false); 1870 HideCursor(); 1871 mpFilterButton->draw(); 1872 ShowCursor(); 1873 } 1874 } 1875 nMouseStatus = SC_GM_NONE; 1876 ReleaseMouse(); 1877 return; // da muss nix mehr passieren 1878 } 1879 1880 ScModule* pScMod = SC_MOD(); 1881 if (pScMod->IsModalMode(pViewData->GetSfxDocShell())) 1882 return; 1883 1884 SfxBindings& rBindings = pViewData->GetBindings(); 1885 if (bEEMouse && pViewData->HasEditView( eWhich )) 1886 { 1887 EditView* pEditView; 1888 SCCOL nEditCol; 1889 SCROW nEditRow; 1890 pViewData->GetEditView( eWhich, pEditView, nEditCol, nEditRow ); 1891 pEditView->MouseButtonUp( rMEvt ); 1892 1893 if ( rMEvt.IsMiddle() && 1894 GetSettings().GetMouseSettings().GetMiddleButtonAction() == MOUSE_MIDDLE_PASTESELECTION ) 1895 { 1896 // EditView may have pasted from selection 1897 pScMod->InputChanged( pEditView ); 1898 } 1899 else 1900 pScMod->InputSelection( pEditView ); // parentheses etc. 1901 1902 pViewData->GetView()->InvalidateAttribs(); 1903 rBindings.Invalidate( SID_HYPERLINK_GETLINK ); 1904 bEEMouse = sal_False; 1905 return; 1906 } 1907 1908 if (bDPMouse) 1909 { 1910 DPMouseButtonUp( rMEvt ); // resets bDPMouse 1911 return; 1912 } 1913 1914 if (bRFMouse) 1915 { 1916 RFMouseMove( rMEvt, sal_True ); // Range wieder richtigherum 1917 bRFMouse = sal_False; 1918 SetPointer( Pointer( POINTER_ARROW ) ); 1919 ReleaseMouse(); 1920 return; 1921 } 1922 1923 if (nPagebreakMouse) 1924 { 1925 PagebreakMove( rMEvt, sal_True ); 1926 nPagebreakMouse = SC_PD_NONE; 1927 SetPointer( Pointer( POINTER_ARROW ) ); 1928 ReleaseMouse(); 1929 return; 1930 } 1931 1932 if (nMouseStatus == SC_GM_WATERUNDO) // Undo im Giesskannenmodus 1933 { 1934 ::svl::IUndoManager* pMgr = pViewData->GetDocShell()->GetUndoManager(); 1935 if ( pMgr->GetUndoActionCount() && pMgr->GetUndoActionId() == STR_UNDO_APPLYCELLSTYLE ) 1936 pMgr->Undo(); 1937 else 1938 Sound::Beep(); 1939 return; 1940 } 1941 1942 if (DrawMouseButtonUp(rMEvt)) // includes format paint brush handling for drawing objects 1943 { 1944 ScTabViewShell* pViewShell = pViewData->GetViewShell(); 1945 SfxBindings& rBindings=pViewShell->GetViewFrame()->GetBindings(); 1946 rBindings.Invalidate(SID_ATTR_TRANSFORM_WIDTH); 1947 rBindings.Invalidate(SID_ATTR_TRANSFORM_HEIGHT); 1948 rBindings.Invalidate(SID_ATTR_TRANSFORM_POS_X); 1949 rBindings.Invalidate(SID_ATTR_TRANSFORM_POS_Y); 1950 rBindings.Invalidate(SID_ATTR_TRANSFORM_ANGLE); 1951 rBindings.Invalidate(SID_ATTR_TRANSFORM_ROT_X); 1952 rBindings.Invalidate(SID_ATTR_TRANSFORM_ROT_Y); 1953 rBindings.Invalidate(SID_ATTR_TRANSFORM_AUTOWIDTH); 1954 rBindings.Invalidate(SID_ATTR_TRANSFORM_AUTOHEIGHT); 1955 return; 1956 } 1957 1958 rMark.SetMarking(sal_False); 1959 1960 SetPointer( Pointer( POINTER_ARROW ) ); 1961 1962 if (pViewData->IsFillMode() || 1963 ( pViewData->GetFillMode() == SC_FILL_MATRIX && rMEvt.IsMod1() )) 1964 { 1965 nScFillModeMouseModifier = rMEvt.GetModifier(); 1966 SCCOL nStartCol; 1967 SCROW nStartRow; 1968 SCCOL nEndCol; 1969 SCROW nEndRow; 1970 pViewData->GetFillData( nStartCol, nStartRow, nEndCol, nEndRow ); 1971 // DBG_ASSERT( nStartCol==pViewData->GetRefStartX() && nStartRow==pViewData->GetRefStartY(), 1972 // "Block falsch fuer AutoFill" ); 1973 ScRange aDelRange; 1974 sal_Bool bIsDel = pViewData->GetDelMark( aDelRange ); 1975 1976 ScViewFunc* pView = pViewData->GetView(); 1977 pView->StopRefMode(); 1978 pViewData->ResetFillMode(); 1979 pView->GetFunctionSet()->SetAnchorFlag( sal_False ); // #i5819# don't use AutoFill anchor flag for selection 1980 1981 if ( bIsDel ) 1982 { 1983 pView->MarkRange( aDelRange, sal_False ); 1984 pView->DeleteContents( IDF_CONTENTS ); 1985 SCTAB nTab = pViewData->GetTabNo(); 1986 ScRange aBlockRange( nStartCol, nStartRow, nTab, nEndCol, nEndRow, nTab ); 1987 if ( aBlockRange != aDelRange ) 1988 { 1989 if ( aDelRange.aStart.Row() == nStartRow ) 1990 aBlockRange.aEnd.SetCol( aDelRange.aStart.Col() - 1 ); 1991 else 1992 aBlockRange.aEnd.SetRow( aDelRange.aStart.Row() - 1 ); 1993 pView->MarkRange( aBlockRange, sal_False ); 1994 } 1995 } 1996 else 1997 pViewData->GetDispatcher().Execute( FID_FILL_AUTO, SFX_CALLMODE_SLOT | SFX_CALLMODE_RECORD ); 1998 } 1999 else if (pViewData->GetFillMode() == SC_FILL_MATRIX) 2000 { 2001 SCTAB nTab = pViewData->GetTabNo(); 2002 SCCOL nStartCol; 2003 SCROW nStartRow; 2004 SCCOL nEndCol; 2005 SCROW nEndRow; 2006 pViewData->GetFillData( nStartCol, nStartRow, nEndCol, nEndRow ); 2007 ScRange aBlockRange( nStartCol, nStartRow, nTab, nEndCol, nEndRow, nTab ); 2008 SCCOL nFillCol = pViewData->GetRefEndX(); 2009 SCROW nFillRow = pViewData->GetRefEndY(); 2010 ScAddress aEndPos( nFillCol, nFillRow, nTab ); 2011 2012 ScTabView* pView = pViewData->GetView(); 2013 pView->StopRefMode(); 2014 pViewData->ResetFillMode(); 2015 pView->GetFunctionSet()->SetAnchorFlag( sal_False ); 2016 2017 if ( aEndPos != aBlockRange.aEnd ) 2018 { 2019 pViewData->GetDocShell()->GetDocFunc().ResizeMatrix( aBlockRange, aEndPos, sal_False ); 2020 pViewData->GetView()->MarkRange( ScRange( aBlockRange.aStart, aEndPos ) ); 2021 } 2022 } 2023 else if (pViewData->IsAnyFillMode()) 2024 { 2025 // Embedded-Area has been changed 2026 ScTabView* pView = pViewData->GetView(); 2027 pView->StopRefMode(); 2028 pViewData->ResetFillMode(); 2029 pView->GetFunctionSet()->SetAnchorFlag( sal_False ); 2030 pViewData->GetDocShell()->UpdateOle(pViewData); 2031 } 2032 2033 sal_Bool bRefMode = pViewData->IsRefMode(); 2034 if (bRefMode) 2035 pScMod->EndReference(); 2036 2037 // 2038 // Giesskannen-Modus (Gestalter) 2039 // 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 // 2179 // Links in edit cells 2180 // 2181 2182 sal_Bool bAlt = rMEvt.IsMod2(); 2183 if ( !bAlt && !bRefMode && !bDouble && nMouseStatus == SC_GM_URLDOWN ) 2184 { 2185 // beim ButtonUp nur ausfuehren, wenn ButtonDown auch ueber einer URL war 2186 2187 String aName, aUrl, aTarget; 2188 if ( GetEditUrl( rMEvt.GetPosPixel(), &aName, &aUrl, &aTarget ) ) 2189 { 2190 nMouseStatus = SC_GM_NONE; // keinen Doppelklick anfangen 2191 ScGlobal::OpenURL( aUrl, aTarget ); 2192 2193 // fire worksheet_followhyperlink event 2194 uno::Reference< script::vba::XVBAEventProcessor > xVbaEvents = pDoc->GetVbaEventProcessor(); 2195 if( xVbaEvents.is() ) try 2196 { 2197 Point aPos = rMEvt.GetPosPixel(); 2198 SCsCOL nPosX; 2199 SCsROW nPosY; 2200 SCTAB nTab = pViewData->GetTabNo(); 2201 pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY ); 2202 ScBaseCell* pCell = NULL; 2203 if( lcl_GetHyperlinkCell( pDoc, nPosX, nPosY, nTab, pCell ) ) 2204 { 2205 ScAddress aCellPos( nPosX, nPosY, nTab ); 2206 uno::Reference< table::XCell > xCell( new ScCellObj( pViewData->GetDocShell(), aCellPos ) ); 2207 uno::Sequence< uno::Any > aArgs(1); 2208 aArgs[0] <<= xCell; 2209 xVbaEvents->processVbaEvent( script::vba::VBAEventId::WORKSHEET_FOLLOWHYPERLINK, aArgs ); 2210 } 2211 } 2212 catch( uno::Exception& ) 2213 { 2214 } 2215 2216 return; 2217 } 2218 } 2219 2220 // 2221 // Gridwin - SelectionEngine 2222 // 2223 2224 // SelMouseButtonDown is called only for left button, but SelMouseButtonUp would return 2225 // sal_True for any call, so IsLeft must be checked here, too. 2226 2227 if ( rMEvt.IsLeft() && pViewData->GetView()->GetSelEngine()->SelMouseButtonUp( rMEvt ) ) 2228 { 2229 // rMark.MarkToSimple(); 2230 pViewData->GetView()->UpdateAutoFillMark(); 2231 2232 SfxDispatcher* pDisp = pViewData->GetViewShell()->GetDispatcher(); 2233 sal_Bool bFormulaMode = pScMod->IsFormulaMode(); 2234 DBG_ASSERT( pDisp || bFormulaMode, "Cursor auf nicht aktiver View bewegen ?" ); 2235 2236 // #i14927# execute SID_CURRENTCELL (for macro recording) only if there is no 2237 // multiple selection, so the argument string completely describes the selection, 2238 // and executing the slot won't change the existing selection (executing the slot 2239 // here and from a recorded macro is treated equally) 2240 2241 if ( pDisp && !bFormulaMode && !rMark.IsMultiMarked() ) 2242 { 2243 String aAddr; // CurrentCell 2244 if( rMark.IsMarked() ) 2245 { 2246 // sal_Bool bKeep = rMark.IsMultiMarked(); //! wohin damit ??? 2247 2248 ScRange aScRange; 2249 rMark.GetMarkArea( aScRange ); 2250 aScRange.Format( aAddr, SCR_ABS ); 2251 if ( aScRange.aStart == aScRange.aEnd ) 2252 { 2253 // make sure there is a range selection string even for a single cell 2254 String aSingle = aAddr; 2255 aAddr.Append( (sal_Char) ':' ); 2256 aAddr.Append( aSingle ); 2257 } 2258 2259 //! SID_MARKAREA gibts nicht mehr ??? 2260 //! was passiert beim Markieren mit dem Cursor ??? 2261 } 2262 else // nur Cursor bewegen 2263 { 2264 ScAddress aScAddress( pViewData->GetCurX(), pViewData->GetCurY(), 0 ); 2265 aScAddress.Format( aAddr, SCA_ABS ); 2266 } 2267 2268 SfxStringItem aPosItem( SID_CURRENTCELL, aAddr ); 2269 pDisp->Execute( SID_CURRENTCELL, SFX_CALLMODE_SLOT | SFX_CALLMODE_RECORD, 2270 &aPosItem, (void*)0L ); 2271 2272 pViewData->GetView()->InvalidateAttribs(); 2273 } 2274 pViewData->GetViewShell()->SelectionChanged(); 2275 return; 2276 } 2277 } 2278 2279 void ScGridWindow::FakeButtonUp() 2280 { 2281 if ( nButtonDown ) 2282 { 2283 MouseEvent aEvent( aCurMousePos ); // nButtons = 0 -> ignore 2284 MouseButtonUp( aEvent ); 2285 } 2286 } 2287 2288 void __EXPORT ScGridWindow::MouseMove( const MouseEvent& rMEvt ) 2289 { 2290 aCurMousePos = rMEvt.GetPosPixel(); 2291 2292 if ( rMEvt.IsLeaveWindow() && pNoteMarker && !pNoteMarker->IsByKeyboard() ) 2293 HideNoteMarker(); 2294 2295 ScModule* pScMod = SC_MOD(); 2296 if (pScMod->IsModalMode(pViewData->GetSfxDocShell())) 2297 return; 2298 2299 // Ob aus dem Edit-Modus Drag&Drop gestartet wurde, bekommt man leider 2300 // nicht anders mit: 2301 2302 if (bEEMouse && nButtonDown && !rMEvt.GetButtons()) 2303 { 2304 bEEMouse = sal_False; 2305 nButtonDown = 0; 2306 nMouseStatus = SC_GM_NONE; 2307 return; 2308 } 2309 2310 if (nMouseStatus == SC_GM_IGNORE) 2311 return; 2312 2313 if (nMouseStatus == SC_GM_WATERUNDO) // Undo im Giesskannenmodus -> nur auf Up warten 2314 return; 2315 2316 if ( pViewData->GetViewShell()->IsAuditShell() ) // Detektiv-Fuell-Modus 2317 { 2318 SetPointer( Pointer( POINTER_FILL ) ); 2319 return; 2320 } 2321 2322 if (nMouseStatus == SC_GM_FILTER && pFilterBox) 2323 { 2324 Point aRelPos = pFilterBox->ScreenToOutputPixel( OutputToScreenPixel( rMEvt.GetPosPixel() ) ); 2325 if ( Rectangle(Point(),pFilterBox->GetOutputSizePixel()).IsInside(aRelPos) ) 2326 { 2327 nButtonDown = 0; 2328 nMouseStatus = SC_GM_NONE; 2329 if ( pFilterBox->GetMode() == SC_FILTERBOX_FILTER ) 2330 { 2331 if (mpFilterButton.get()) 2332 { 2333 mpFilterButton->setHasHiddenMember(false); 2334 mpFilterButton->setPopupPressed(false); 2335 HideCursor(); 2336 mpFilterButton->draw(); 2337 ShowCursor(); 2338 } 2339 } 2340 ReleaseMouse(); 2341 pFilterBox->MouseButtonDown( MouseEvent( aRelPos, 1, MOUSE_SIMPLECLICK, MOUSE_LEFT ) ); 2342 return; 2343 } 2344 } 2345 2346 sal_Bool bFormulaMode = pScMod->IsFormulaMode(); // naechster Klick -> Referenz 2347 2348 if (bEEMouse && pViewData->HasEditView( eWhich )) 2349 { 2350 EditView* pEditView; 2351 SCCOL nEditCol; 2352 SCROW nEditRow; 2353 pViewData->GetEditView( eWhich, pEditView, nEditCol, nEditRow ); 2354 pEditView->MouseMove( rMEvt ); 2355 return; 2356 } 2357 2358 if (bDPMouse) 2359 { 2360 DPMouseMove( rMEvt ); 2361 return; 2362 } 2363 2364 if (bRFMouse) 2365 { 2366 RFMouseMove( rMEvt, sal_False ); 2367 return; 2368 } 2369 2370 if (nPagebreakMouse) 2371 { 2372 PagebreakMove( rMEvt, sal_False ); 2373 return; 2374 } 2375 2376 // anderen Mauszeiger anzeigen? 2377 2378 sal_Bool bEditMode = pViewData->HasEditView(eWhich); 2379 2380 //! Testen ob RefMode-Dragging !!! 2381 if ( bEditMode && (pViewData->GetRefTabNo() == pViewData->GetTabNo()) ) 2382 { 2383 Point aPos = rMEvt.GetPosPixel(); 2384 SCsCOL nPosX; 2385 SCsROW nPosY; 2386 pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY ); 2387 2388 EditView* pEditView; 2389 SCCOL nEditCol; 2390 SCROW nEditRow; 2391 pViewData->GetEditView( eWhich, pEditView, nEditCol, nEditRow ); 2392 SCCOL nEndCol = pViewData->GetEditEndCol(); 2393 SCROW nEndRow = pViewData->GetEditEndRow(); 2394 2395 if ( nPosX >= (SCsCOL) nEditCol && nPosX <= (SCsCOL) nEndCol && 2396 nPosY >= (SCsROW) nEditRow && nPosY <= (SCsROW) nEndRow ) 2397 { 2398 // Field can only be URL field 2399 sal_Bool bAlt = rMEvt.IsMod2(); 2400 if ( !bAlt && !nButtonDown && pEditView && pEditView->GetFieldUnderMousePointer() ) 2401 SetPointer( Pointer( POINTER_REFHAND ) ); 2402 else if ( pEditView && pEditView->GetEditEngine()->IsVertical() ) 2403 SetPointer( Pointer( POINTER_TEXT_VERTICAL ) ); 2404 else 2405 SetPointer( Pointer( POINTER_TEXT ) ); 2406 return; 2407 } 2408 } 2409 2410 sal_Bool bWater = SC_MOD()->GetIsWaterCan() || pViewData->GetView()->HasPaintBrush(); 2411 if (bWater) 2412 SetPointer( Pointer(POINTER_FILL) ); 2413 2414 if (!bWater) 2415 { 2416 sal_Bool bCross = sal_False; 2417 2418 // Range-Finder 2419 2420 sal_Bool bCorner; 2421 if ( HitRangeFinder( rMEvt.GetPosPixel(), bCorner ) ) 2422 { 2423 if (bCorner) 2424 SetPointer( Pointer( POINTER_CROSS ) ); 2425 else 2426 SetPointer( Pointer( POINTER_HAND ) ); 2427 bCross = sal_True; 2428 } 2429 2430 // Page-Break-Modus 2431 2432 sal_uInt16 nBreakType; 2433 if ( !nButtonDown && pViewData->IsPagebreakMode() && 2434 ( nBreakType = HitPageBreak( rMEvt.GetPosPixel() ) ) != 0 ) 2435 { 2436 PointerStyle eNew = POINTER_ARROW; 2437 switch ( nBreakType ) 2438 { 2439 case SC_PD_RANGE_L: 2440 case SC_PD_RANGE_R: 2441 case SC_PD_BREAK_H: 2442 eNew = POINTER_ESIZE; 2443 break; 2444 case SC_PD_RANGE_T: 2445 case SC_PD_RANGE_B: 2446 case SC_PD_BREAK_V: 2447 eNew = POINTER_SSIZE; 2448 break; 2449 case SC_PD_RANGE_TL: 2450 case SC_PD_RANGE_BR: 2451 eNew = POINTER_SESIZE; 2452 break; 2453 case SC_PD_RANGE_TR: 2454 case SC_PD_RANGE_BL: 2455 eNew = POINTER_NESIZE; 2456 break; 2457 } 2458 SetPointer( Pointer( eNew ) ); 2459 bCross = sal_True; 2460 } 2461 2462 // Fill-Cursor anzeigen ? 2463 2464 if ( !bFormulaMode && !nButtonDown ) 2465 if (TestMouse( rMEvt, sal_False )) 2466 bCross = sal_True; 2467 2468 if ( nButtonDown && pViewData->IsAnyFillMode() ) 2469 { 2470 SetPointer( Pointer( POINTER_CROSS ) ); 2471 bCross = sal_True; 2472 nScFillModeMouseModifier = rMEvt.GetModifier(); // ausgewertet bei AutoFill und Matrix 2473 } 2474 2475 if (!bCross) 2476 { 2477 sal_Bool bAlt = rMEvt.IsMod2(); 2478 2479 if (bEditMode) // Edit-Mode muss zuerst kommen! 2480 SetPointer( Pointer( POINTER_ARROW ) ); 2481 else if ( !bAlt && !nButtonDown && 2482 GetEditUrl(rMEvt.GetPosPixel()) ) 2483 SetPointer( Pointer( POINTER_REFHAND ) ); 2484 else if ( DrawMouseMove(rMEvt) ) // setzt Pointer um 2485 return; 2486 } 2487 } 2488 2489 if ( pViewData->GetView()->GetSelEngine()->SelMouseMove( rMEvt ) ) 2490 return; 2491 } 2492 2493 void lcl_InitMouseEvent( ::com::sun::star::awt::MouseEvent& rEvent, const MouseEvent& rEvt ) 2494 { 2495 rEvent.Modifiers = 0; 2496 if ( rEvt.IsShift() ) 2497 rEvent.Modifiers |= ::com::sun::star::awt::KeyModifier::SHIFT; 2498 if ( rEvt.IsMod1() ) 2499 rEvent.Modifiers |= ::com::sun::star::awt::KeyModifier::MOD1; 2500 if ( rEvt.IsMod2() ) 2501 rEvent.Modifiers |= ::com::sun::star::awt::KeyModifier::MOD2; 2502 if ( rEvt.IsMod3() ) 2503 rEvent.Modifiers |= ::com::sun::star::awt::KeyModifier::MOD3; 2504 2505 rEvent.Buttons = 0; 2506 if ( rEvt.IsLeft() ) 2507 rEvent.Buttons |= ::com::sun::star::awt::MouseButton::LEFT; 2508 if ( rEvt.IsRight() ) 2509 rEvent.Buttons |= ::com::sun::star::awt::MouseButton::RIGHT; 2510 if ( rEvt.IsMiddle() ) 2511 rEvent.Buttons |= ::com::sun::star::awt::MouseButton::MIDDLE; 2512 2513 rEvent.X = rEvt.GetPosPixel().X(); 2514 rEvent.Y = rEvt.GetPosPixel().Y(); 2515 rEvent.ClickCount = rEvt.GetClicks(); 2516 rEvent.PopupTrigger = sal_False; 2517 } 2518 2519 long ScGridWindow::PreNotify( NotifyEvent& rNEvt ) 2520 { 2521 bool bDone = false; 2522 sal_uInt16 nType = rNEvt.GetType(); 2523 if ( nType == EVENT_MOUSEBUTTONUP || nType == EVENT_MOUSEBUTTONDOWN ) 2524 { 2525 Window* pWindow = rNEvt.GetWindow(); 2526 if (pWindow == this && pViewData) 2527 { 2528 SfxViewFrame* pViewFrame = pViewData->GetViewShell()->GetViewFrame(); 2529 if (pViewFrame) 2530 { 2531 com::sun::star::uno::Reference<com::sun::star::frame::XController> xController = pViewFrame->GetFrame().GetController(); 2532 if (xController.is()) 2533 { 2534 ScTabViewObj* pImp = ScTabViewObj::getImplementation( xController ); 2535 if (pImp && pImp->IsMouseListening()) 2536 { 2537 ::com::sun::star::awt::MouseEvent aEvent; 2538 lcl_InitMouseEvent( aEvent, *rNEvt.GetMouseEvent() ); 2539 if ( rNEvt.GetWindow() ) 2540 aEvent.Source = rNEvt.GetWindow()->GetComponentInterface(); 2541 if ( nType == EVENT_MOUSEBUTTONDOWN) 2542 bDone = pImp->MousePressed( aEvent ); 2543 else 2544 bDone = pImp->MouseReleased( aEvent ); 2545 } 2546 } 2547 } 2548 } 2549 } 2550 if (bDone) // event consumed by a listener 2551 { 2552 if ( nType == EVENT_MOUSEBUTTONDOWN ) 2553 { 2554 const MouseEvent* pMouseEvent = rNEvt.GetMouseEvent(); 2555 if ( pMouseEvent->IsRight() && pMouseEvent->GetClicks() == 1 ) 2556 { 2557 // If a listener returned true for a right-click call, also prevent opening the context menu 2558 // (this works only if the context menu is opened on mouse-down) 2559 nMouseStatus = SC_GM_IGNORE; 2560 } 2561 } 2562 2563 return 1; 2564 } 2565 else 2566 return Window::PreNotify( rNEvt ); 2567 } 2568 2569 void ScGridWindow::Tracking( const TrackingEvent& rTEvt ) 2570 { 2571 // Weil die SelectionEngine kein Tracking kennt, die Events nur auf 2572 // die verschiedenen MouseHandler verteilen... 2573 2574 const MouseEvent& rMEvt = rTEvt.GetMouseEvent(); 2575 2576 if ( rTEvt.IsTrackingCanceled() ) // alles abbrechen... 2577 { 2578 if (!pViewData->GetView()->IsInActivatePart()) 2579 { 2580 if (bDPMouse) 2581 bDPMouse = sal_False; // gezeichnet wird per bDragRect 2582 if (bDragRect) 2583 { 2584 // pViewData->GetView()->DrawDragRect( nDragStartX, nDragStartY, nDragEndX, nDragEndY, eWhich ); 2585 bDragRect = sal_False; 2586 UpdateDragRectOverlay(); 2587 } 2588 if (bRFMouse) 2589 { 2590 RFMouseMove( rMEvt, sal_True ); // richtig abbrechen geht dabei nicht... 2591 bRFMouse = sal_False; 2592 } 2593 if (nPagebreakMouse) 2594 { 2595 // if (bPagebreakDrawn) 2596 // DrawDragRect( aPagebreakDrag.aStart.Col(), aPagebreakDrag.aStart.Row(), 2597 // aPagebreakDrag.aEnd.Col(), aPagebreakDrag.aEnd.Row(), sal_False ); 2598 bPagebreakDrawn = sal_False; 2599 UpdateDragRectOverlay(); 2600 nPagebreakMouse = SC_PD_NONE; 2601 } 2602 2603 SetPointer( Pointer( POINTER_ARROW ) ); 2604 StopMarking(); 2605 MouseButtonUp( rMEvt ); // mit Status SC_GM_IGNORE aus StopMarking 2606 2607 sal_Bool bRefMode = pViewData->IsRefMode(); 2608 if (bRefMode) 2609 SC_MOD()->EndReference(); // #63148# Dialog nicht verkleinert lassen 2610 } 2611 } 2612 else if ( rTEvt.IsTrackingEnded() ) 2613 { 2614 // MouseButtonUp immer mit passenden Buttons (z.B. wegen Testtool, #63148#) 2615 // Schliesslich behauptet der Tracking-Event ja, dass normal beendet und nicht 2616 // abgebrochen wurde. 2617 2618 MouseEvent aUpEvt( rMEvt.GetPosPixel(), rMEvt.GetClicks(), 2619 rMEvt.GetMode(), nButtonDown, rMEvt.GetModifier() ); 2620 MouseButtonUp( aUpEvt ); 2621 } 2622 else 2623 MouseMove( rMEvt ); 2624 } 2625 2626 void ScGridWindow::StartDrag( sal_Int8 /* nAction */, const Point& rPosPixel ) 2627 { 2628 if ( pFilterBox || nPagebreakMouse ) 2629 return; 2630 2631 HideNoteMarker(); 2632 2633 CommandEvent aDragEvent( rPosPixel, COMMAND_STARTDRAG, sal_True ); 2634 2635 if (bEEMouse && pViewData->HasEditView( eWhich )) 2636 { 2637 EditView* pEditView; 2638 SCCOL nEditCol; 2639 SCROW nEditRow; 2640 pViewData->GetEditView( eWhich, pEditView, nEditCol, nEditRow ); 2641 2642 // #63263# don't remove the edit view while switching views 2643 ScModule* pScMod = SC_MOD(); 2644 pScMod->SetInEditCommand( sal_True ); 2645 2646 pEditView->Command( aDragEvent ); 2647 2648 ScInputHandler* pHdl = pScMod->GetInputHdl(); 2649 if (pHdl) 2650 pHdl->DataChanged(); 2651 2652 pScMod->SetInEditCommand( sal_False ); 2653 if (!pViewData->IsActive()) // dropped to different view? 2654 { 2655 ScInputHandler* pViewHdl = pScMod->GetInputHdl( pViewData->GetViewShell() ); 2656 if ( pViewHdl && pViewData->HasEditView( eWhich ) ) 2657 { 2658 pViewHdl->CancelHandler(); 2659 ShowCursor(); // missing from KillEditView 2660 } 2661 } 2662 } 2663 else 2664 if ( !DrawCommand(aDragEvent) ) 2665 pViewData->GetView()->GetSelEngine()->Command( aDragEvent ); 2666 } 2667 2668 void lcl_SetTextCursorPos( ScViewData* pViewData, ScSplitPos eWhich, Window* pWin ) 2669 { 2670 SCCOL nCol = pViewData->GetCurX(); 2671 SCROW nRow = pViewData->GetCurY(); 2672 Rectangle aEditArea = pViewData->GetEditArea( eWhich, nCol, nRow, pWin, NULL, sal_True ); 2673 aEditArea.Right() = aEditArea.Left(); 2674 aEditArea = pWin->PixelToLogic( aEditArea ); 2675 pWin->SetCursorRect( &aEditArea ); 2676 } 2677 2678 void __EXPORT ScGridWindow::Command( const CommandEvent& rCEvt ) 2679 { 2680 // The command event is send to the window after a possible context 2681 // menu from an inplace client is closed. Now we have the chance to 2682 // deactivate the inplace client without any problem regarding parent 2683 // windows and code on the stack. 2684 // For more information, see #126086# and #128122# 2685 sal_uInt16 nCmd = rCEvt.GetCommand(); 2686 ScTabViewShell* pTabViewSh = pViewData->GetViewShell(); 2687 SfxInPlaceClient* pClient = pTabViewSh->GetIPClient(); 2688 if ( pClient && 2689 pClient->IsObjectInPlaceActive() && 2690 nCmd == COMMAND_CONTEXTMENU ) 2691 { 2692 pTabViewSh->DeactivateOle(); 2693 return; 2694 } 2695 2696 ScModule* pScMod = SC_MOD(); 2697 DBG_ASSERT( nCmd != COMMAND_STARTDRAG, "ScGridWindow::Command called with COMMAND_STARTDRAG" ); 2698 2699 if ( nCmd == COMMAND_STARTEXTTEXTINPUT || 2700 nCmd == COMMAND_ENDEXTTEXTINPUT || 2701 nCmd == COMMAND_EXTTEXTINPUT || 2702 nCmd == COMMAND_CURSORPOS ) 2703 { 2704 sal_Bool bEditView = pViewData->HasEditView( eWhich ); 2705 if (!bEditView) 2706 { 2707 // only if no cell editview is active, look at drawview 2708 SdrView* pSdrView = pViewData->GetView()->GetSdrView(); 2709 if ( pSdrView ) 2710 { 2711 OutlinerView* pOlView = pSdrView->GetTextEditOutlinerView(); 2712 if ( pOlView && pOlView->GetWindow() == this ) 2713 { 2714 pOlView->Command( rCEvt ); 2715 return; // done 2716 } 2717 } 2718 } 2719 2720 if ( nCmd == COMMAND_CURSORPOS && !bEditView ) 2721 { 2722 // #88458# CURSORPOS may be called without following text input, 2723 // to set the input method window position 2724 // -> input mode must not be started, 2725 // manually calculate text insert position if not in input mode 2726 2727 lcl_SetTextCursorPos( pViewData, eWhich, this ); 2728 return; 2729 } 2730 2731 ScInputHandler* pHdl = pScMod->GetInputHdl( pViewData->GetViewShell() ); 2732 if ( pHdl ) 2733 { 2734 pHdl->InputCommand( rCEvt, sal_True ); 2735 return; // done 2736 } 2737 2738 Window::Command( rCEvt ); 2739 return; 2740 } 2741 2742 if ( nCmd == COMMAND_VOICE ) 2743 { 2744 // Der Handler wird nur gerufen, wenn ein Text-Cursor aktiv ist, 2745 // also muss es eine EditView oder ein editiertes Zeichenobjekt geben 2746 2747 ScInputHandler* pHdl = pScMod->GetInputHdl( pViewData->GetViewShell() ); 2748 if ( pHdl && pViewData->HasEditView( eWhich ) ) 2749 { 2750 EditView* pEditView = pViewData->GetEditView( eWhich ); // ist dann nicht 0 2751 pHdl->DataChanging(); 2752 pEditView->Command( rCEvt ); 2753 pHdl->DataChanged(); 2754 return; // erledigt 2755 } 2756 SdrView* pSdrView = pViewData->GetView()->GetSdrView(); 2757 if ( pSdrView ) 2758 { 2759 OutlinerView* pOlView = pSdrView->GetTextEditOutlinerView(); 2760 if ( pOlView && pOlView->GetWindow() == this ) 2761 { 2762 pOlView->Command( rCEvt ); 2763 return; // erledigt 2764 } 2765 } 2766 Window::Command(rCEvt); // sonst soll sich die Basisklasse drum kuemmern... 2767 return; 2768 } 2769 2770 if ( nCmd == COMMAND_PASTESELECTION ) 2771 { 2772 if ( bEEMouse ) 2773 { 2774 // EditEngine handles selection in MouseButtonUp - no action 2775 // needed in command handler 2776 } 2777 else 2778 { 2779 PasteSelection( rCEvt.GetMousePosPixel() ); 2780 } 2781 return; 2782 } 2783 2784 if ( nCmd == COMMAND_INPUTLANGUAGECHANGE ) 2785 { 2786 // #i55929# Font and font size state depends on input language if nothing is selected, 2787 // so the slots have to be invalidated when the input language is changed. 2788 2789 SfxBindings& rBindings = pViewData->GetBindings(); 2790 rBindings.Invalidate( SID_ATTR_CHAR_FONT ); 2791 rBindings.Invalidate( SID_ATTR_CHAR_FONTHEIGHT ); 2792 return; 2793 } 2794 2795 if ( nCmd == COMMAND_WHEEL || nCmd == COMMAND_STARTAUTOSCROLL || nCmd == COMMAND_AUTOSCROLL ) 2796 { 2797 sal_Bool bDone = pViewData->GetView()->ScrollCommand( rCEvt, eWhich ); 2798 if (!bDone) 2799 Window::Command(rCEvt); 2800 return; 2801 } 2802 // #i7560# FormulaMode check is below scrolling - scrolling is allowed during formula input 2803 sal_Bool bDisable = pScMod->IsFormulaMode() || 2804 pScMod->IsModalMode(pViewData->GetSfxDocShell()); 2805 if (bDisable) 2806 return; 2807 2808 if ( nCmd == COMMAND_CONTEXTMENU && !SC_MOD()->GetIsWaterCan() ) 2809 { 2810 sal_Bool bMouse = rCEvt.IsMouseEvent(); 2811 if ( bMouse && nMouseStatus == SC_GM_IGNORE ) 2812 return; 2813 2814 if (pViewData->IsAnyFillMode()) 2815 { 2816 pViewData->GetView()->StopRefMode(); 2817 pViewData->ResetFillMode(); 2818 } 2819 ReleaseMouse(); 2820 StopMarking(); 2821 2822 Point aPosPixel = rCEvt.GetMousePosPixel(); 2823 Point aMenuPos = aPosPixel; 2824 2825 if ( bMouse ) 2826 { 2827 SCsCOL nCellX = -1; 2828 SCsROW nCellY = -1; 2829 pViewData->GetPosFromPixel(aPosPixel.X(), aPosPixel.Y(), eWhich, nCellX, nCellY); 2830 ScDocument* pDoc = pViewData->GetDocument(); 2831 SCTAB nTab = pViewData->GetTabNo(); 2832 const ScTableProtection* pProtect = pDoc->GetTabProtection(nTab); 2833 bool bSelectAllowed = true; 2834 if ( pProtect && pProtect->isProtected() ) 2835 { 2836 // This sheet is protected. Check if a context menu is allowed on this cell. 2837 bool bCellProtected = pDoc->HasAttrib(nCellX, nCellY, nTab, nCellX, nCellY, nTab, HASATTR_PROTECTED); 2838 bool bSelProtected = pProtect->isOptionEnabled(ScTableProtection::SELECT_LOCKED_CELLS); 2839 bool bSelUnprotected = pProtect->isOptionEnabled(ScTableProtection::SELECT_UNLOCKED_CELLS); 2840 2841 if (bCellProtected) 2842 bSelectAllowed = bSelProtected; 2843 else 2844 bSelectAllowed = bSelUnprotected; 2845 } 2846 if (!bSelectAllowed) 2847 // Selecting this cell is not allowed, neither is context menu. 2848 return; 2849 2850 // #i18735# First select the item under the mouse pointer. 2851 // This can change the selection, and the view state (edit mode, etc). 2852 SelectForContextMenu( aPosPixel, nCellX, nCellY ); 2853 } 2854 2855 sal_Bool bDone = sal_False; 2856 sal_Bool bEdit = pViewData->HasEditView(eWhich); 2857 if ( !bEdit ) 2858 { 2859 // Edit-Zelle mit Spelling-Errors ? 2860 if ( bMouse && GetEditUrlOrError( sal_True, aPosPixel ) ) 2861 { 2862 // GetEditUrlOrError hat den Cursor schon bewegt 2863 2864 pScMod->SetInputMode( SC_INPUT_TABLE ); 2865 bEdit = pViewData->HasEditView(eWhich); // hat's geklappt ? 2866 2867 DBG_ASSERT( bEdit, "kann nicht in Edit-Modus schalten" ); 2868 } 2869 } 2870 if ( bEdit ) 2871 { 2872 EditView* pEditView = pViewData->GetEditView( eWhich ); // ist dann nicht 0 2873 2874 if ( !bMouse ) 2875 { 2876 Cursor* pCur = pEditView->GetCursor(); 2877 if ( pCur ) 2878 { 2879 Point aLogicPos = pCur->GetPos(); 2880 // use the position right of the cursor (spell popup is opened if 2881 // the cursor is before the word, but not if behind it) 2882 aLogicPos.X() += pCur->GetWidth(); 2883 aLogicPos.Y() += pCur->GetHeight() / 2; // center vertically 2884 aMenuPos = LogicToPixel( aLogicPos ); 2885 } 2886 } 2887 2888 // if edit mode was just started above, online spelling may be incomplete 2889 pEditView->GetEditEngine()->CompleteOnlineSpelling(); 2890 2891 // IsCursorAtWrongSpelledWord could be used for !bMouse 2892 // if there was a corresponding ExecuteSpellPopup call 2893 2894 if( pEditView->IsWrongSpelledWordAtPos( aMenuPos ) ) 2895 { 2896 // Wenn man unter OS/2 neben das Popupmenue klickt, kommt MouseButtonDown 2897 // vor dem Ende des Menue-Execute, darum muss SetModified vorher kommen 2898 // (Bug #40968#) 2899 ScInputHandler* pHdl = pScMod->GetInputHdl(); 2900 if (pHdl) 2901 pHdl->SetModified(); 2902 2903 Link aLink = LINK( this, ScGridWindow, PopupSpellingHdl ); 2904 pEditView->ExecuteSpellPopup( aMenuPos, &aLink ); 2905 2906 bDone = sal_True; 2907 } 2908 } 2909 else if ( !bMouse ) 2910 { 2911 // non-edit menu by keyboard -> use lower right of cell cursor position 2912 2913 SCCOL nCurX = pViewData->GetCurX(); 2914 SCROW nCurY = pViewData->GetCurY(); 2915 aMenuPos = pViewData->GetScrPos( nCurX, nCurY, eWhich, sal_True ); 2916 long nSizeXPix; 2917 long nSizeYPix; 2918 pViewData->GetMergeSizePixel( nCurX, nCurY, nSizeXPix, nSizeYPix ); 2919 aMenuPos.X() += nSizeXPix; 2920 aMenuPos.Y() += nSizeYPix; 2921 2922 if (pViewData) 2923 { 2924 ScTabViewShell* pViewSh = pViewData->GetViewShell(); 2925 if (pViewSh) 2926 { 2927 // Is a draw object selected? 2928 2929 SdrView* pDrawView = pViewSh->GetSdrView(); 2930 if (pDrawView && pDrawView->AreObjectsMarked()) 2931 { 2932 // #100442#; the conext menu should open in the middle of the selected objects 2933 Rectangle aSelectRect(LogicToPixel(pDrawView->GetAllMarkedBoundRect())); 2934 aMenuPos = aSelectRect.Center(); 2935 } 2936 } 2937 } 2938 } 2939 2940 if (!bDone) 2941 { 2942 SfxDispatcher::ExecutePopup( 0, this, &aMenuPos ); 2943 } 2944 } 2945 } 2946 2947 void ScGridWindow::SelectForContextMenu( const Point& rPosPixel, SCsCOL nCellX, SCsROW nCellY ) 2948 { 2949 // #i18735# if the click was outside of the current selection, 2950 // the cursor is moved or an object at the click position selected. 2951 // (see SwEditWin::SelectMenuPosition in Writer) 2952 2953 ScTabView* pView = pViewData->GetView(); 2954 ScDrawView* pDrawView = pView->GetScDrawView(); 2955 2956 // check cell edit mode 2957 2958 if ( pViewData->HasEditView(eWhich) ) 2959 { 2960 ScModule* pScMod = SC_MOD(); 2961 SCCOL nEditStartCol = pViewData->GetEditViewCol(); //! change to GetEditStartCol after calcrtl is integrated 2962 SCROW nEditStartRow = pViewData->GetEditViewRow(); 2963 SCCOL nEditEndCol = pViewData->GetEditEndCol(); 2964 SCROW nEditEndRow = pViewData->GetEditEndRow(); 2965 2966 if ( nCellX >= (SCsCOL) nEditStartCol && nCellX <= (SCsCOL) nEditEndCol && 2967 nCellY >= (SCsROW) nEditStartRow && nCellY <= (SCsROW) nEditEndRow ) 2968 { 2969 // handle selection within the EditView 2970 2971 EditView* pEditView = pViewData->GetEditView( eWhich ); // not NULL (HasEditView) 2972 EditEngine* pEditEngine = pEditView->GetEditEngine(); 2973 Rectangle aOutputArea = pEditView->GetOutputArea(); 2974 Rectangle aVisArea = pEditView->GetVisArea(); 2975 2976 Point aTextPos = PixelToLogic( rPosPixel ); 2977 if ( pEditEngine->IsVertical() ) // have to manually transform position 2978 { 2979 aTextPos -= aOutputArea.TopRight(); 2980 long nTemp = -aTextPos.X(); 2981 aTextPos.X() = aTextPos.Y(); 2982 aTextPos.Y() = nTemp; 2983 } 2984 else 2985 aTextPos -= aOutputArea.TopLeft(); 2986 aTextPos += aVisArea.TopLeft(); // position in the edit document 2987 2988 EPosition aDocPosition = pEditEngine->FindDocPosition(aTextPos); 2989 ESelection aCompare(aDocPosition.nPara, aDocPosition.nIndex); 2990 ESelection aSelection = pEditView->GetSelection(); 2991 aSelection.Adjust(); // needed for IsLess/IsGreater 2992 if ( aCompare.IsLess(aSelection) || aCompare.IsGreater(aSelection) ) 2993 { 2994 // clicked outside the selected text - deselect and move text cursor 2995 MouseEvent aEvent( rPosPixel ); 2996 pEditView->MouseButtonDown( aEvent ); 2997 pEditView->MouseButtonUp( aEvent ); 2998 pScMod->InputSelection( pEditView ); 2999 } 3000 3001 return; // clicked within the edit view - keep edit mode 3002 } 3003 else 3004 { 3005 // outside of the edit view - end edit mode, regardless of cell selection, then continue 3006 pScMod->InputEnterHandler(); 3007 } 3008 } 3009 3010 // check draw text edit mode 3011 3012 Point aLogicPos = PixelToLogic( rPosPixel ); // after cell edit mode is ended 3013 if ( pDrawView && pDrawView->GetTextEditObject() && pDrawView->GetTextEditOutlinerView() ) 3014 { 3015 OutlinerView* pOlView = pDrawView->GetTextEditOutlinerView(); 3016 Rectangle aOutputArea = pOlView->GetOutputArea(); 3017 if ( aOutputArea.IsInside( aLogicPos ) ) 3018 { 3019 // handle selection within the OutlinerView 3020 3021 Outliner* pOutliner = pOlView->GetOutliner(); 3022 const EditEngine& rEditEngine = pOutliner->GetEditEngine(); 3023 Rectangle aVisArea = pOlView->GetVisArea(); 3024 3025 Point aTextPos = aLogicPos; 3026 if ( pOutliner->IsVertical() ) // have to manually transform position 3027 { 3028 aTextPos -= aOutputArea.TopRight(); 3029 long nTemp = -aTextPos.X(); 3030 aTextPos.X() = aTextPos.Y(); 3031 aTextPos.Y() = nTemp; 3032 } 3033 else 3034 aTextPos -= aOutputArea.TopLeft(); 3035 aTextPos += aVisArea.TopLeft(); // position in the edit document 3036 3037 EPosition aDocPosition = rEditEngine.FindDocPosition(aTextPos); 3038 ESelection aCompare(aDocPosition.nPara, aDocPosition.nIndex); 3039 ESelection aSelection = pOlView->GetSelection(); 3040 aSelection.Adjust(); // needed for IsLess/IsGreater 3041 if ( aCompare.IsLess(aSelection) || aCompare.IsGreater(aSelection) ) 3042 { 3043 // clicked outside the selected text - deselect and move text cursor 3044 // use DrawView to allow extra handling there (none currently) 3045 MouseEvent aEvent( rPosPixel ); 3046 pDrawView->MouseButtonDown( aEvent, this ); 3047 pDrawView->MouseButtonUp( aEvent, this ); 3048 } 3049 3050 return; // clicked within the edit area - keep edit mode 3051 } 3052 else 3053 { 3054 // Outside of the edit area - end text edit mode, then continue. 3055 // DrawDeselectAll also ends text edit mode and updates the shells. 3056 // If the click was on the edited object, it will be selected again below. 3057 pView->DrawDeselectAll(); 3058 } 3059 } 3060 3061 // look for existing selection 3062 3063 sal_Bool bHitSelected = sal_False; 3064 if ( pDrawView && pDrawView->IsMarkedObjHit( aLogicPos ) ) 3065 { 3066 // clicked on selected object -> don't change anything 3067 bHitSelected = sal_True; 3068 } 3069 else if ( pViewData->GetMarkData().IsCellMarked(nCellX, nCellY) ) 3070 { 3071 // clicked on selected cell -> don't change anything 3072 bHitSelected = sal_True; 3073 } 3074 3075 // select drawing object or move cell cursor 3076 3077 if ( !bHitSelected ) 3078 { 3079 sal_Bool bWasDraw = ( pDrawView && pDrawView->AreObjectsMarked() ); 3080 sal_Bool bHitDraw = sal_False; 3081 if ( pDrawView ) 3082 { 3083 pDrawView->UnmarkAllObj(); 3084 // Unlock the Internal Layer in order to activate the context menu. 3085 // re-lock in ScDrawView::MarkListHasChanged() 3086 lcl_UnLockComment( pDrawView, pDrawView->GetSdrPageView(), pDrawView->GetModel(), aLogicPos ,pViewData); 3087 bHitDraw = pDrawView->MarkObj( aLogicPos ); 3088 // draw shell is activated in MarkListHasChanged 3089 } 3090 if ( !bHitDraw ) 3091 { 3092 pView->Unmark(); 3093 pView->SetCursor(nCellX, nCellY); 3094 if ( bWasDraw ) 3095 pViewData->GetViewShell()->SetDrawShell( sal_False ); // switch shells 3096 } 3097 } 3098 } 3099 3100 void __EXPORT ScGridWindow::KeyInput(const KeyEvent& rKEvt) 3101 { 3102 // #96965# Cursor control for ref input dialog 3103 if( SC_MOD()->IsRefDialogOpen() ) 3104 { 3105 const KeyCode& rKeyCode = rKEvt.GetKeyCode(); 3106 if( !rKeyCode.GetModifier() && (rKeyCode.GetCode() == KEY_F2) ) 3107 { 3108 SC_MOD()->EndReference(); 3109 //return; 3110 } 3111 else if( pViewData->GetViewShell()->MoveCursorKeyInput( rKEvt ) ) 3112 { 3113 ScRange aRef( 3114 pViewData->GetRefStartX(), pViewData->GetRefStartY(), pViewData->GetRefStartZ(), 3115 pViewData->GetRefEndX(), pViewData->GetRefEndY(), pViewData->GetRefEndZ() ); 3116 SC_MOD()->SetReference( aRef, pViewData->GetDocument() ); 3117 //return; 3118 } 3119 pViewData->GetViewShell()->SelectionChanged(); 3120 return ; 3121 } 3122 // wenn semi-Modeless-SfxChildWindow-Dialog oben, keine KeyInputs: 3123 else if( !pViewData->IsAnyFillMode() ) 3124 { 3125 // query for existing note marker before calling ViewShell's keyboard handling 3126 // which may remove the marker 3127 sal_Bool bHadKeyMarker = ( pNoteMarker && pNoteMarker->IsByKeyboard() ); 3128 ScTabViewShell* pViewSh = pViewData->GetViewShell(); 3129 3130 if (pViewData->GetDocShell()->GetProgress()) 3131 return; 3132 3133 if (DrawKeyInput(rKEvt)) 3134 { 3135 const KeyCode& rKeyCode = rKEvt.GetKeyCode(); 3136 if (rKeyCode.GetCode() == KEY_DOWN 3137 || rKeyCode.GetCode() == KEY_UP 3138 || rKeyCode.GetCode() == KEY_LEFT 3139 || rKeyCode.GetCode() == KEY_RIGHT) 3140 { 3141 ScTabViewShell* pViewShell = pViewData->GetViewShell(); 3142 SfxBindings& rBindings = pViewShell->GetViewFrame()->GetBindings(); 3143 rBindings.Invalidate(SID_ATTR_TRANSFORM_POS_X); 3144 rBindings.Invalidate(SID_ATTR_TRANSFORM_POS_Y); 3145 } 3146 return; 3147 } 3148 3149 if (!pViewData->GetView()->IsDrawSelMode() && !DrawHasMarkedObj()) // keine Eingaben im Zeichenmodus 3150 { //! DrawShell abfragen !!! 3151 if (pViewSh->TabKeyInput(rKEvt)) 3152 return; 3153 } 3154 else 3155 if (pViewSh->SfxViewShell::KeyInput(rKEvt)) // von SfxViewShell 3156 return; 3157 3158 KeyCode aCode = rKEvt.GetKeyCode(); 3159 if ( aCode.GetCode() == KEY_ESCAPE && aCode.GetModifier() == 0 ) 3160 { 3161 if ( bHadKeyMarker ) 3162 HideNoteMarker(); 3163 else 3164 pViewSh->Escape(); 3165 return; 3166 } 3167 if ( aCode.GetCode() == KEY_F1 && aCode.GetModifier() == KEY_MOD1 ) 3168 { 3169 // ctrl-F1 shows or hides the note or redlining info for the cursor position 3170 // (hard-coded because F1 can't be configured) 3171 3172 if ( bHadKeyMarker ) 3173 HideNoteMarker(); // hide when previously visible 3174 else 3175 ShowNoteMarker( pViewData->GetCurX(), pViewData->GetCurY(), sal_True ); 3176 return; 3177 } 3178 } 3179 3180 Window::KeyInput(rKEvt); 3181 } 3182 3183 void ScGridWindow::StopMarking() 3184 { 3185 DrawEndAction(); // Markieren/Verschieben auf Drawing-Layer abbrechen 3186 3187 if (nButtonDown) 3188 { 3189 pViewData->GetMarkData().SetMarking(sal_False); 3190 nMouseStatus = SC_GM_IGNORE; 3191 } 3192 } 3193 3194 void ScGridWindow::UpdateInputContext() 3195 { 3196 sal_Bool bReadOnly = pViewData->GetDocShell()->IsReadOnly(); 3197 sal_uLong nOptions = bReadOnly ? 0 : ( INPUTCONTEXT_TEXT | INPUTCONTEXT_EXTTEXTINPUT ); 3198 3199 // when font from InputContext is used, 3200 // it must be taken from the cursor position's cell attributes 3201 3202 InputContext aContext; 3203 aContext.SetOptions( nOptions ); 3204 SetInputContext( aContext ); 3205 } 3206 3207 //-------------------------------------------------------- 3208 3209 // sensitiver Bereich (Pixel) 3210 #define SCROLL_SENSITIVE 20 3211 3212 sal_Bool ScGridWindow::DropScroll( const Point& rMousePos ) 3213 { 3214 /* doch auch auf nicht aktiven Views... 3215 if ( !pViewData->IsActive() ) 3216 return sal_False; 3217 */ 3218 SCsCOL nDx = 0; 3219 SCsROW nDy = 0; 3220 Size aSize = GetOutputSizePixel(); 3221 3222 if (aSize.Width() > SCROLL_SENSITIVE * 3) 3223 { 3224 if ( rMousePos.X() < SCROLL_SENSITIVE && pViewData->GetPosX(WhichH(eWhich)) > 0 ) 3225 nDx = -1; 3226 if ( rMousePos.X() >= aSize.Width() - SCROLL_SENSITIVE 3227 && pViewData->GetPosX(WhichH(eWhich)) < MAXCOL ) 3228 nDx = 1; 3229 } 3230 if (aSize.Height() > SCROLL_SENSITIVE * 3) 3231 { 3232 if ( rMousePos.Y() < SCROLL_SENSITIVE && pViewData->GetPosY(WhichV(eWhich)) > 0 ) 3233 nDy = -1; 3234 if ( rMousePos.Y() >= aSize.Height() - SCROLL_SENSITIVE 3235 && pViewData->GetPosY(WhichV(eWhich)) < MAXROW ) 3236 nDy = 1; 3237 } 3238 3239 if ( nDx != 0 || nDy != 0 ) 3240 { 3241 // if (bDragRect) 3242 // pViewData->GetView()->DrawDragRect( nDragStartX, nDragStartY, nDragEndX, nDragEndY, eWhich ); 3243 3244 if ( nDx != 0 ) 3245 pViewData->GetView()->ScrollX( nDx, WhichH(eWhich) ); 3246 if ( nDy != 0 ) 3247 pViewData->GetView()->ScrollY( nDy, WhichV(eWhich) ); 3248 3249 // if (bDragRect) 3250 // pViewData->GetView()->DrawDragRect( nDragStartX, nDragStartY, nDragEndX, nDragEndY, eWhich ); 3251 } 3252 3253 return sal_False; 3254 } 3255 3256 sal_Bool lcl_TestScenarioRedliningDrop( ScDocument* pDoc, const ScRange& aDragRange) 3257 { 3258 // Testet, ob bei eingeschalteten RedLining, 3259 // bei einem Drop ein Scenario betroffen ist. 3260 3261 sal_Bool bReturn = sal_False; 3262 SCTAB nTab = aDragRange.aStart.Tab(); 3263 SCTAB nTabCount = pDoc->GetTableCount(); 3264 3265 if(pDoc->GetChangeTrack()!=NULL) 3266 { 3267 if( pDoc->IsScenario(nTab) && pDoc->HasScenarioRange(nTab, aDragRange)) 3268 { 3269 bReturn = sal_True; 3270 } 3271 else 3272 { 3273 for(SCTAB i=nTab+1; i<nTabCount && pDoc->IsScenario(i); i++) 3274 { 3275 if(pDoc->HasScenarioRange(i, aDragRange)) 3276 { 3277 bReturn = sal_True; 3278 break; 3279 } 3280 } 3281 } 3282 } 3283 return bReturn; 3284 } 3285 3286 ScRange lcl_MakeDropRange( SCCOL nPosX, SCROW nPosY, SCTAB nTab, const ScRange& rSource ) 3287 { 3288 SCCOL nCol1 = nPosX; 3289 SCCOL nCol2 = nCol1 + ( rSource.aEnd.Col() - rSource.aStart.Col() ); 3290 if ( nCol2 > MAXCOL ) 3291 { 3292 nCol1 -= nCol2 - MAXCOL; 3293 nCol2 = MAXCOL; 3294 } 3295 SCROW nRow1 = nPosY; 3296 SCROW nRow2 = nRow1 + ( rSource.aEnd.Row() - rSource.aStart.Row() ); 3297 if ( nRow2 > MAXROW ) 3298 { 3299 nRow1 -= nRow2 - MAXROW; 3300 nRow2 = MAXROW; 3301 } 3302 3303 return ScRange( nCol1, nRow1, nTab, nCol2, nRow2, nTab ); 3304 } 3305 3306 //-------------------------------------------------------- 3307 3308 extern sal_Bool bPasteIsDrop; // viewfun4 -> move to header 3309 extern sal_Bool bPasteIsMove; // viewfun7 -> move to header 3310 3311 //-------------------------------------------------------- 3312 3313 sal_Int8 ScGridWindow::AcceptPrivateDrop( const AcceptDropEvent& rEvt ) 3314 { 3315 if ( rEvt.mbLeaving ) 3316 { 3317 // if (bDragRect) 3318 // pViewData->GetView()->DrawDragRect( nDragStartX, nDragStartY, nDragEndX, nDragEndY, eWhich ); 3319 bDragRect = sal_False; 3320 UpdateDragRectOverlay(); 3321 return rEvt.mnAction; 3322 } 3323 3324 const ScDragData& rData = SC_MOD()->GetDragData(); 3325 if ( rData.pCellTransfer ) 3326 { 3327 // Don't move source that would include filtered rows. 3328 if ((rEvt.mnAction & DND_ACTION_MOVE) && rData.pCellTransfer->HasFilteredRows()) 3329 { 3330 if (bDragRect) 3331 { 3332 bDragRect = sal_False; 3333 UpdateDragRectOverlay(); 3334 } 3335 return DND_ACTION_NONE; 3336 } 3337 3338 Point aPos = rEvt.maPosPixel; 3339 3340 ScDocument* pSourceDoc = rData.pCellTransfer->GetSourceDocument(); 3341 ScDocument* pThisDoc = pViewData->GetDocument(); 3342 if (pSourceDoc == pThisDoc) 3343 { 3344 if ( pThisDoc->HasChartAtPoint(pViewData->GetTabNo(), PixelToLogic(aPos)) ) 3345 { 3346 if (bDragRect) // Rechteck loeschen 3347 { 3348 // pViewData->GetView()->DrawDragRect( nDragStartX, nDragStartY, nDragEndX, nDragEndY, eWhich ); 3349 bDragRect = sal_False; 3350 UpdateDragRectOverlay(); 3351 } 3352 3353 //! highlight chart? (selection border?) 3354 3355 sal_Int8 nRet = rEvt.mnAction; 3356 //! if ( rEvt.GetAction() == DROP_LINK ) 3357 //! bOk = rEvt.SetAction( DROP_COPY ); // can't link onto chart 3358 return nRet; 3359 } 3360 } 3361 //! else 3362 //! if ( rEvt.GetAction() == DROP_MOVE ) 3363 //! rEvt.SetAction( DROP_COPY ); // different doc: default=COPY 3364 3365 3366 if ( rData.pCellTransfer->GetDragSourceFlags() & SC_DROP_TABLE ) // whole sheet? 3367 { 3368 sal_Bool bOk = pThisDoc->IsDocEditable(); 3369 return bOk ? rEvt.mnAction : 0; // don't draw selection frame 3370 } 3371 3372 SCsCOL nPosX; 3373 SCsROW nPosY; 3374 pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY ); 3375 3376 ScRange aSourceRange = rData.pCellTransfer->GetRange(); 3377 SCCOL nSourceStartX = aSourceRange.aStart.Col(); 3378 SCROW nSourceStartY = aSourceRange.aStart.Row(); 3379 SCCOL nSourceEndX = aSourceRange.aEnd.Col(); 3380 SCROW nSourceEndY = aSourceRange.aEnd.Row(); 3381 SCCOL nSizeX = nSourceEndX - nSourceStartX + 1; 3382 SCROW nSizeY = nSourceEndY - nSourceStartY + 1; 3383 3384 if ( rEvt.mnAction != DND_ACTION_MOVE ) 3385 nSizeY = rData.pCellTransfer->GetNonFilteredRows(); // copy/link: no filtered rows 3386 3387 SCsCOL nNewDragX = nPosX - rData.pCellTransfer->GetDragHandleX(); 3388 if (nNewDragX<0) nNewDragX=0; 3389 if (nNewDragX+(nSizeX-1) > MAXCOL) 3390 nNewDragX = MAXCOL-(nSizeX-1); 3391 SCsROW nNewDragY = nPosY - rData.pCellTransfer->GetDragHandleY(); 3392 if (nNewDragY<0) nNewDragY=0; 3393 if (nNewDragY+(nSizeY-1) > MAXROW) 3394 nNewDragY = MAXROW-(nSizeY-1); 3395 3396 // don't break scenario ranges, don't drop on filtered 3397 SCTAB nTab = pViewData->GetTabNo(); 3398 ScRange aDropRange = lcl_MakeDropRange( nNewDragX, nNewDragY, nTab, aSourceRange ); 3399 if ( lcl_TestScenarioRedliningDrop( pThisDoc, aDropRange ) || 3400 lcl_TestScenarioRedliningDrop( pSourceDoc, aSourceRange ) || 3401 ScViewUtil::HasFiltered( aDropRange, pThisDoc) ) 3402 { 3403 if (bDragRect) 3404 { 3405 // pViewData->GetView()->DrawDragRect( nDragStartX, nDragStartY, nDragEndX, nDragEndY, eWhich ); 3406 bDragRect = sal_False; 3407 UpdateDragRectOverlay(); 3408 } 3409 return DND_ACTION_NONE; 3410 } 3411 3412 InsCellCmd eDragInsertMode = INS_NONE; 3413 Window::PointerState aState = GetPointerState(); 3414 3415 // check for datapilot item sorting 3416 ScDPObject* pDPObj = NULL; 3417 if ( pThisDoc == pSourceDoc && ( pDPObj = pThisDoc->GetDPAtCursor( nNewDragX, nNewDragY, nTab ) ) != NULL ) 3418 { 3419 // drop on DataPilot table: sort or nothing 3420 3421 bool bDPSort = false; 3422 if ( pThisDoc->GetDPAtCursor( nSourceStartX, nSourceStartY, aSourceRange.aStart.Tab() ) == pDPObj ) 3423 { 3424 sheet::DataPilotTableHeaderData aDestData; 3425 pDPObj->GetHeaderPositionData( ScAddress(nNewDragX, nNewDragY, nTab), aDestData ); 3426 bool bValid = ( aDestData.Dimension >= 0 ); // dropping onto a field 3427 3428 // look through the source range 3429 for (SCROW nRow = aSourceRange.aStart.Row(); bValid && nRow <= aSourceRange.aEnd.Row(); ++nRow ) 3430 for (SCCOL nCol = aSourceRange.aStart.Col(); bValid && nCol <= aSourceRange.aEnd.Col(); ++nCol ) 3431 { 3432 sheet::DataPilotTableHeaderData aSourceData; 3433 pDPObj->GetHeaderPositionData( ScAddress( nCol, nRow, aSourceRange.aStart.Tab() ), aSourceData ); 3434 if ( aSourceData.Dimension != aDestData.Dimension || !aSourceData.MemberName.getLength() ) 3435 bValid = false; // empty (subtotal) or different field 3436 } 3437 3438 if ( bValid ) 3439 { 3440 sal_Bool bIsDataLayout; 3441 String aDimName = pDPObj->GetDimName( aDestData.Dimension, bIsDataLayout ); 3442 const ScDPSaveDimension* pDim = pDPObj->GetSaveData()->GetExistingDimensionByName( aDimName ); 3443 if ( pDim ) 3444 { 3445 ScRange aOutRange = pDPObj->GetOutRange(); 3446 3447 sal_uInt16 nOrient = pDim->GetOrientation(); 3448 if ( nOrient == sheet::DataPilotFieldOrientation_COLUMN ) 3449 { 3450 eDragInsertMode = INS_CELLSRIGHT; 3451 nSizeY = aOutRange.aEnd.Row() - nNewDragY + 1; 3452 bDPSort = true; 3453 } 3454 else if ( nOrient == sheet::DataPilotFieldOrientation_ROW ) 3455 { 3456 eDragInsertMode = INS_CELLSDOWN; 3457 nSizeX = aOutRange.aEnd.Col() - nNewDragX + 1; 3458 bDPSort = true; 3459 } 3460 } 3461 } 3462 } 3463 3464 if ( !bDPSort ) 3465 { 3466 // no valid sorting in a DataPilot table -> disallow 3467 if ( bDragRect ) 3468 { 3469 bDragRect = sal_False; 3470 UpdateDragRectOverlay(); 3471 } 3472 return DND_ACTION_NONE; 3473 } 3474 } 3475 else if ( aState.mnState & KEY_MOD2 ) 3476 { 3477 if ( pThisDoc == pSourceDoc && nTab == aSourceRange.aStart.Tab() ) 3478 { 3479 long nDeltaX = labs( static_cast< long >( nNewDragX - nSourceStartX ) ); 3480 long nDeltaY = labs( static_cast< long >( nNewDragY - nSourceStartY ) ); 3481 if ( nDeltaX <= nDeltaY ) 3482 { 3483 eDragInsertMode = INS_CELLSDOWN; 3484 } 3485 else 3486 { 3487 eDragInsertMode = INS_CELLSRIGHT; 3488 } 3489 3490 if ( ( eDragInsertMode == INS_CELLSDOWN && nNewDragY <= nSourceEndY && 3491 ( nNewDragX + nSizeX - 1 ) >= nSourceStartX && nNewDragX <= nSourceEndX && 3492 ( nNewDragX != nSourceStartX || nNewDragY >= nSourceStartY ) ) || 3493 ( eDragInsertMode == INS_CELLSRIGHT && nNewDragX <= nSourceEndX && 3494 ( nNewDragY + nSizeY - 1 ) >= nSourceStartY && nNewDragY <= nSourceEndY && 3495 ( nNewDragY != nSourceStartY || nNewDragX >= nSourceStartX ) ) ) 3496 { 3497 if ( bDragRect ) 3498 { 3499 bDragRect = sal_False; 3500 UpdateDragRectOverlay(); 3501 } 3502 return DND_ACTION_NONE; 3503 } 3504 } 3505 else 3506 { 3507 if ( static_cast< long >( nSizeX ) >= static_cast< long >( nSizeY ) ) 3508 { 3509 eDragInsertMode = INS_CELLSDOWN; 3510 3511 } 3512 else 3513 { 3514 eDragInsertMode = INS_CELLSRIGHT; 3515 } 3516 } 3517 } 3518 3519 if ( nNewDragX != (SCsCOL) nDragStartX || nNewDragY != (SCsROW) nDragStartY || 3520 nDragStartX+nSizeX-1 != nDragEndX || nDragStartY+nSizeY-1 != nDragEndY || 3521 !bDragRect || eDragInsertMode != meDragInsertMode ) 3522 { 3523 // if (bDragRect) 3524 // pViewData->GetView()->DrawDragRect( nDragStartX, nDragStartY, nDragEndX, nDragEndY, eWhich ); 3525 3526 nDragStartX = nNewDragX; 3527 nDragStartY = nNewDragY; 3528 nDragEndX = nDragStartX+nSizeX-1; 3529 nDragEndY = nDragStartY+nSizeY-1; 3530 bDragRect = sal_True; 3531 meDragInsertMode = eDragInsertMode; 3532 3533 // pViewData->GetView()->DrawDragRect( nDragStartX, nDragStartY, nDragEndX, nDragEndY, eWhich ); 3534 3535 UpdateDragRectOverlay(); 3536 3537 // show target position as tip help 3538 #if 0 3539 if (Help::IsQuickHelpEnabled()) 3540 { 3541 ScRange aRange( nDragStartX, nDragStartY, nTab, nDragEndX, nDragEndY, nTab ); 3542 String aHelpStr; 3543 aRange.Format( aHelpStr, SCA_VALID ); // non-3D 3544 3545 Point aPos = Pointer::GetPosPixel(); 3546 sal_uInt16 nAlign = QUICKHELP_BOTTOM|QUICKHELP_RIGHT; 3547 Rectangle aRect( aPos, aPos ); 3548 Help::ShowQuickHelp(aRect, aHelpStr, nAlign); 3549 } 3550 #endif 3551 } 3552 } 3553 3554 return rEvt.mnAction; 3555 } 3556 3557 sal_Int8 ScGridWindow::AcceptDrop( const AcceptDropEvent& rEvt ) 3558 { 3559 const ScDragData& rData = SC_MOD()->GetDragData(); 3560 if ( rEvt.mbLeaving ) 3561 { 3562 DrawMarkDropObj( NULL ); 3563 if ( rData.pCellTransfer ) 3564 return AcceptPrivateDrop( rEvt ); // hide drop marker for internal D&D 3565 else 3566 return rEvt.mnAction; 3567 } 3568 3569 if ( pViewData->GetDocShell()->IsReadOnly() ) 3570 return DND_ACTION_NONE; 3571 3572 3573 sal_Int8 nRet = DND_ACTION_NONE; 3574 3575 if (rData.pCellTransfer) 3576 { 3577 ScRange aSource = rData.pCellTransfer->GetRange(); 3578 if ( aSource.aStart.Col() != 0 || aSource.aEnd.Col() != MAXCOL || 3579 aSource.aStart.Row() != 0 || aSource.aEnd.Row() != MAXROW ) 3580 DropScroll( rEvt.maPosPixel ); 3581 3582 nRet = AcceptPrivateDrop( rEvt ); 3583 } 3584 else 3585 { 3586 if ( rData.aLinkDoc.Len() ) 3587 { 3588 String aThisName; 3589 ScDocShell* pDocSh = pViewData->GetDocShell(); 3590 if (pDocSh && pDocSh->HasName()) 3591 aThisName = pDocSh->GetMedium()->GetName(); 3592 3593 if ( rData.aLinkDoc != aThisName ) 3594 nRet = rEvt.mnAction; 3595 } 3596 else if (rData.aJumpTarget.Len()) 3597 { 3598 // internal bookmarks (from Navigator) 3599 // local jumps from an unnamed document are possible only within a document 3600 3601 if ( !rData.pJumpLocalDoc || rData.pJumpLocalDoc == pViewData->GetDocument() ) 3602 nRet = rEvt.mnAction; 3603 } 3604 else 3605 { 3606 sal_Int8 nMyAction = rEvt.mnAction; 3607 3608 // clear DND_ACTION_LINK when other actions are set. The usage below cannot handle 3609 // multiple set values 3610 if((nMyAction & DND_ACTION_LINK) && (nMyAction & (DND_ACTION_COPYMOVE))) 3611 { 3612 nMyAction &= ~DND_ACTION_LINK; 3613 } 3614 3615 if ( !rData.pDrawTransfer || 3616 !IsMyModel(rData.pDrawTransfer->GetDragSourceView()) ) // drawing within the document 3617 if ( rEvt.mbDefault && nMyAction == DND_ACTION_MOVE ) 3618 nMyAction = DND_ACTION_COPY; 3619 3620 ScDocument* pThisDoc = pViewData->GetDocument(); 3621 SdrObject* pHitObj = pThisDoc->GetObjectAtPoint( 3622 pViewData->GetTabNo(), PixelToLogic(rEvt.maPosPixel) ); 3623 if ( pHitObj && nMyAction == DND_ACTION_LINK ) // && !rData.pDrawTransfer ) 3624 { 3625 if ( IsDropFormatSupported(SOT_FORMATSTR_ID_SVXB) 3626 || IsDropFormatSupported(SOT_FORMAT_GDIMETAFILE) 3627 || IsDropFormatSupported(SOT_FORMAT_BITMAP) ) 3628 { 3629 // graphic dragged onto drawing object 3630 DrawMarkDropObj( pHitObj ); 3631 nRet = nMyAction; 3632 } 3633 } 3634 if (!nRet) 3635 DrawMarkDropObj( NULL ); 3636 3637 if (!nRet) 3638 { 3639 switch ( nMyAction ) 3640 { 3641 case DND_ACTION_COPY: 3642 case DND_ACTION_MOVE: 3643 case DND_ACTION_COPYMOVE: 3644 { 3645 sal_Bool bMove = ( nMyAction == DND_ACTION_MOVE ); 3646 if ( IsDropFormatSupported( SOT_FORMATSTR_ID_EMBED_SOURCE ) || 3647 IsDropFormatSupported( SOT_FORMATSTR_ID_LINK_SOURCE ) || 3648 IsDropFormatSupported( SOT_FORMATSTR_ID_EMBED_SOURCE_OLE ) || 3649 IsDropFormatSupported( SOT_FORMATSTR_ID_LINK_SOURCE_OLE ) || 3650 IsDropFormatSupported( SOT_FORMATSTR_ID_EMBEDDED_OBJ_OLE ) || 3651 IsDropFormatSupported( SOT_FORMAT_STRING ) || 3652 IsDropFormatSupported( SOT_FORMATSTR_ID_SYLK ) || 3653 IsDropFormatSupported( SOT_FORMATSTR_ID_LINK ) || 3654 IsDropFormatSupported( SOT_FORMATSTR_ID_HTML ) || 3655 IsDropFormatSupported( SOT_FORMATSTR_ID_HTML_SIMPLE ) || 3656 IsDropFormatSupported( SOT_FORMATSTR_ID_DIF ) || 3657 IsDropFormatSupported( SOT_FORMATSTR_ID_DRAWING ) || 3658 IsDropFormatSupported( SOT_FORMATSTR_ID_SVXB ) || 3659 IsDropFormatSupported( SOT_FORMAT_RTF ) || 3660 IsDropFormatSupported( SOT_FORMAT_GDIMETAFILE ) || 3661 IsDropFormatSupported( SOT_FORMAT_BITMAP ) || 3662 IsDropFormatSupported( SOT_FORMATSTR_ID_SBA_DATAEXCHANGE ) || 3663 IsDropFormatSupported( SOT_FORMATSTR_ID_SBA_FIELDDATAEXCHANGE ) || 3664 ( !bMove && ( 3665 IsDropFormatSupported( SOT_FORMAT_FILE_LIST ) || 3666 IsDropFormatSupported( SOT_FORMAT_FILE ) || 3667 IsDropFormatSupported( SOT_FORMATSTR_ID_SOLK ) || 3668 IsDropFormatSupported( SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR ) || 3669 IsDropFormatSupported( SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK ) || 3670 IsDropFormatSupported( SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR ) ) ) ) 3671 { 3672 nRet = nMyAction; 3673 } 3674 } 3675 break; 3676 case DND_ACTION_LINK: 3677 if ( IsDropFormatSupported( SOT_FORMATSTR_ID_LINK_SOURCE ) || 3678 IsDropFormatSupported( SOT_FORMATSTR_ID_LINK_SOURCE_OLE ) || 3679 IsDropFormatSupported( SOT_FORMATSTR_ID_LINK ) || 3680 IsDropFormatSupported( SOT_FORMAT_FILE_LIST ) || 3681 IsDropFormatSupported( SOT_FORMAT_FILE ) || 3682 IsDropFormatSupported( SOT_FORMATSTR_ID_SOLK ) || 3683 IsDropFormatSupported( SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR ) || 3684 IsDropFormatSupported( SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK ) || 3685 IsDropFormatSupported( SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR ) ) 3686 { 3687 nRet = nMyAction; 3688 } 3689 break; 3690 } 3691 3692 if ( nRet ) 3693 { 3694 // Simple check for protection: It's not known here if the drop will result 3695 // in cells or drawing objects (some formats can be both) and how many cells 3696 // the result will be. But if IsFormatEditable for the drop cell position 3697 // is sal_False (ignores matrix formulas), nothing can be pasted, so the drop 3698 // can already be rejected here. 3699 3700 Point aPos = rEvt.maPosPixel; 3701 SCsCOL nPosX; 3702 SCsROW nPosY; 3703 pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY ); 3704 SCTAB nTab = pViewData->GetTabNo(); 3705 ScDocument* pDoc = pViewData->GetDocument(); 3706 3707 ScEditableTester aTester( pDoc, nTab, nPosX,nPosY, nPosX,nPosY ); 3708 if ( !aTester.IsFormatEditable() ) 3709 nRet = DND_ACTION_NONE; // forbidden 3710 } 3711 } 3712 } 3713 3714 // scroll only for accepted formats 3715 if (nRet) 3716 DropScroll( rEvt.maPosPixel ); 3717 } 3718 3719 return nRet; 3720 } 3721 3722 sal_uLong lcl_GetDropFormatId( const uno::Reference<datatransfer::XTransferable>& xTransfer, bool bPreferText = false ) 3723 { 3724 TransferableDataHelper aDataHelper( xTransfer ); 3725 3726 if ( !aDataHelper.HasFormat( SOT_FORMATSTR_ID_SBA_DATAEXCHANGE ) ) 3727 { 3728 // use bookmark formats if no sba is present 3729 3730 if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_SOLK ) ) 3731 return SOT_FORMATSTR_ID_SOLK; 3732 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR ) ) 3733 return SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR; 3734 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK ) ) 3735 return SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK; 3736 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR ) ) 3737 return SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR; 3738 } 3739 3740 sal_uLong nFormatId = 0; 3741 if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_DRAWING ) ) 3742 nFormatId = SOT_FORMATSTR_ID_DRAWING; 3743 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_SVXB ) ) 3744 nFormatId = SOT_FORMATSTR_ID_SVXB; 3745 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_EMBED_SOURCE ) ) 3746 { 3747 // If it's a Writer object, insert RTF instead of OLE 3748 3749 sal_Bool bDoRtf = sal_False; 3750 SotStorageStreamRef xStm; 3751 TransferableObjectDescriptor aObjDesc; 3752 if( aDataHelper.GetTransferableObjectDescriptor( SOT_FORMATSTR_ID_OBJECTDESCRIPTOR, aObjDesc ) && 3753 aDataHelper.GetSotStorageStream( SOT_FORMATSTR_ID_EMBED_SOURCE, xStm ) ) 3754 { 3755 SotStorageRef xStore( new SotStorage( *xStm ) ); 3756 bDoRtf = ( ( aObjDesc.maClassName == SvGlobalName( SO3_SW_CLASSID ) || 3757 aObjDesc.maClassName == SvGlobalName( SO3_SWWEB_CLASSID ) ) 3758 && aDataHelper.HasFormat( SOT_FORMAT_RTF ) ); 3759 } 3760 if ( bDoRtf ) 3761 nFormatId = FORMAT_RTF; 3762 else 3763 nFormatId = SOT_FORMATSTR_ID_EMBED_SOURCE; 3764 } 3765 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_LINK_SOURCE ) ) 3766 nFormatId = SOT_FORMATSTR_ID_LINK_SOURCE; 3767 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_SBA_DATAEXCHANGE ) ) 3768 nFormatId = SOT_FORMATSTR_ID_SBA_DATAEXCHANGE; 3769 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_SBA_FIELDDATAEXCHANGE ) ) 3770 nFormatId = SOT_FORMATSTR_ID_SBA_FIELDDATAEXCHANGE; 3771 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_BIFF_8 ) ) 3772 nFormatId = SOT_FORMATSTR_ID_BIFF_8; 3773 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_BIFF_5 ) ) 3774 nFormatId = SOT_FORMATSTR_ID_BIFF_5; 3775 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_EMBED_SOURCE_OLE ) ) 3776 nFormatId = SOT_FORMATSTR_ID_EMBED_SOURCE_OLE; 3777 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_EMBEDDED_OBJ_OLE ) ) 3778 nFormatId = SOT_FORMATSTR_ID_EMBEDDED_OBJ_OLE; 3779 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_LINK_SOURCE_OLE ) ) 3780 nFormatId = SOT_FORMATSTR_ID_LINK_SOURCE_OLE; 3781 else if ( aDataHelper.HasFormat( SOT_FORMAT_RTF ) ) 3782 nFormatId = SOT_FORMAT_RTF; 3783 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_HTML ) ) 3784 nFormatId = SOT_FORMATSTR_ID_HTML; 3785 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_HTML_SIMPLE ) ) 3786 nFormatId = SOT_FORMATSTR_ID_HTML_SIMPLE; 3787 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_SYLK ) ) 3788 nFormatId = SOT_FORMATSTR_ID_SYLK; 3789 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_LINK ) ) 3790 nFormatId = SOT_FORMATSTR_ID_LINK; 3791 else if ( bPreferText && aDataHelper.HasFormat( SOT_FORMAT_STRING ) ) // #i86734# the behaviour introduced in #i62773# is wrong when pasting 3792 nFormatId = SOT_FORMAT_STRING; 3793 else if ( aDataHelper.HasFormat( SOT_FORMAT_FILE_LIST ) ) 3794 nFormatId = SOT_FORMAT_FILE_LIST; 3795 else if ( aDataHelper.HasFormat( SOT_FORMAT_FILE ) ) // #i62773# FILE_LIST/FILE before STRING (Unix file managers) 3796 nFormatId = SOT_FORMAT_FILE; 3797 else if ( aDataHelper.HasFormat( SOT_FORMAT_STRING ) ) 3798 nFormatId = SOT_FORMAT_STRING; 3799 else if ( aDataHelper.HasFormat( SOT_FORMAT_GDIMETAFILE ) ) 3800 nFormatId = SOT_FORMAT_GDIMETAFILE; 3801 else if ( aDataHelper.HasFormat( SOT_FORMAT_BITMAP ) ) 3802 nFormatId = SOT_FORMAT_BITMAP; 3803 3804 return nFormatId; 3805 } 3806 3807 sal_uLong lcl_GetDropLinkId( const uno::Reference<datatransfer::XTransferable>& xTransfer ) 3808 { 3809 TransferableDataHelper aDataHelper( xTransfer ); 3810 3811 sal_uLong nFormatId = 0; 3812 if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_LINK_SOURCE ) ) 3813 nFormatId = SOT_FORMATSTR_ID_LINK_SOURCE; 3814 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_LINK_SOURCE_OLE ) ) 3815 nFormatId = SOT_FORMATSTR_ID_LINK_SOURCE_OLE; 3816 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_LINK ) ) 3817 nFormatId = SOT_FORMATSTR_ID_LINK; 3818 else if ( aDataHelper.HasFormat( SOT_FORMAT_FILE_LIST ) ) 3819 nFormatId = SOT_FORMAT_FILE_LIST; 3820 else if ( aDataHelper.HasFormat( SOT_FORMAT_FILE ) ) 3821 nFormatId = SOT_FORMAT_FILE; 3822 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_SOLK ) ) 3823 nFormatId = SOT_FORMATSTR_ID_SOLK; 3824 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR ) ) 3825 nFormatId = SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR; 3826 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK ) ) 3827 nFormatId = SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK; 3828 else if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR ) ) 3829 nFormatId = SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR; 3830 3831 return nFormatId; 3832 } 3833 3834 3835 sal_Int8 ScGridWindow::ExecutePrivateDrop( const ExecuteDropEvent& rEvt ) 3836 { 3837 // hide drop marker 3838 // if (bDragRect) 3839 // pViewData->GetView()->DrawDragRect( nDragStartX, nDragStartY, nDragEndX, nDragEndY, eWhich ); 3840 bDragRect = sal_False; 3841 UpdateDragRectOverlay(); 3842 3843 ScModule* pScMod = SC_MOD(); 3844 const ScDragData& rData = pScMod->GetDragData(); 3845 3846 return DropTransferObj( rData.pCellTransfer, nDragStartX, nDragStartY, 3847 PixelToLogic(rEvt.maPosPixel), rEvt.mnAction ); 3848 } 3849 3850 sal_Int8 ScGridWindow::DropTransferObj( ScTransferObj* pTransObj, SCCOL nDestPosX, SCROW nDestPosY, 3851 const Point& rLogicPos, sal_Int8 nDndAction ) 3852 { 3853 if ( !pTransObj ) 3854 return 0; 3855 3856 ScDocument* pSourceDoc = pTransObj->GetSourceDocument(); 3857 ScDocShell* pDocSh = pViewData->GetDocShell(); 3858 ScDocument* pThisDoc = pViewData->GetDocument(); 3859 ScViewFunc* pView = pViewData->GetView(); 3860 SCTAB nThisTab = pViewData->GetTabNo(); 3861 sal_uInt16 nFlags = pTransObj->GetDragSourceFlags(); 3862 3863 sal_Bool bIsNavi = ( nFlags & SC_DROP_NAVIGATOR ) != 0; 3864 sal_Bool bIsMove = ( nDndAction == DND_ACTION_MOVE && !bIsNavi ); 3865 3866 // workaround for wrong nDndAction on Windows when pressing solely 3867 // the Alt key during drag and drop; 3868 // can be removed after #i79215# has been fixed 3869 if ( meDragInsertMode != INS_NONE ) 3870 { 3871 bIsMove = ( nDndAction & DND_ACTION_MOVE && !bIsNavi ); 3872 } 3873 3874 sal_Bool bIsLink = ( nDndAction == DND_ACTION_LINK ); 3875 3876 ScRange aSource = pTransObj->GetRange(); 3877 3878 // only use visible tab from source range - when dragging within one table, 3879 // all selected tables at the time of dropping are used (handled in MoveBlockTo) 3880 SCTAB nSourceTab = pTransObj->GetVisibleTab(); 3881 aSource.aStart.SetTab( nSourceTab ); 3882 aSource.aEnd.SetTab( nSourceTab ); 3883 3884 SCCOL nSizeX = aSource.aEnd.Col() - aSource.aStart.Col() + 1; 3885 SCROW nSizeY = (bIsMove ? (aSource.aEnd.Row() - aSource.aStart.Row() + 1) : 3886 pTransObj->GetNonFilteredRows()); // copy/link: no filtered rows 3887 ScRange aDest( nDestPosX, nDestPosY, nThisTab, 3888 nDestPosX + nSizeX - 1, nDestPosY + nSizeY - 1, nThisTab ); 3889 3890 3891 /* NOTE: AcceptPrivateDrop() already checked for filtered conditions during 3892 * dragging and adapted drawing of the selection frame. We check here 3893 * (again) because this may actually also be called from PasteSelection(), 3894 * we would have to duplicate determination of flags and destination range 3895 * and would lose the context of the "filtered destination is OK" cases 3896 * below, which is already awkward enough as is. */ 3897 3898 // Don't move filtered source. 3899 bool bFiltered = (bIsMove && pTransObj->HasFilteredRows()); 3900 if (!bFiltered) 3901 { 3902 if (pSourceDoc != pThisDoc && ((nFlags & SC_DROP_TABLE) || 3903 (!bIsLink && meDragInsertMode == INS_NONE))) 3904 { 3905 // Nothing. Either entire sheet to be dropped, or the one case 3906 // where PasteFromClip() is to be called that handles a filtered 3907 // destination itself. Drag-copy from another document without 3908 // inserting cells. 3909 } 3910 else 3911 // Don't copy or move to filtered destination. 3912 bFiltered = ScViewUtil::HasFiltered( aDest, pThisDoc); 3913 } 3914 3915 sal_Bool bDone = sal_False; 3916 3917 if (!bFiltered && pSourceDoc == pThisDoc) 3918 { 3919 if ( nFlags & SC_DROP_TABLE ) // whole sheet? 3920 { 3921 if ( pThisDoc->IsDocEditable() ) 3922 { 3923 SCTAB nSrcTab = aSource.aStart.Tab(); 3924 pViewData->GetDocShell()->MoveTable( nSrcTab, nThisTab, !bIsMove, sal_True ); // with Undo 3925 pView->SetTabNo( nThisTab, sal_True ); 3926 bDone = sal_True; 3927 } 3928 } 3929 else // move/copy block 3930 { 3931 String aChartName; 3932 if (pThisDoc->HasChartAtPoint( nThisTab, rLogicPos, &aChartName )) 3933 { 3934 String aRangeName; 3935 aSource.Format( aRangeName, SCR_ABS_3D, pThisDoc ); 3936 SfxStringItem aNameItem( SID_CHART_NAME, aChartName ); 3937 SfxStringItem aRangeItem( SID_CHART_SOURCE, aRangeName ); 3938 sal_uInt16 nId = bIsMove ? SID_CHART_SOURCE : SID_CHART_ADDSOURCE; 3939 pViewData->GetDispatcher().Execute( nId, SFX_CALLMODE_ASYNCHRON | SFX_CALLMODE_RECORD, 3940 &aRangeItem, &aNameItem, (void*) NULL ); 3941 bDone = sal_True; 3942 } 3943 else if ( pThisDoc->GetDPAtCursor( nDestPosX, nDestPosY, nThisTab ) ) 3944 { 3945 // drop on DataPilot table: try to sort, fail if that isn't possible 3946 3947 ScAddress aDestPos( nDestPosX, nDestPosY, nThisTab ); 3948 if ( aDestPos != aSource.aStart ) 3949 bDone = pViewData->GetView()->DataPilotMove( aSource, aDestPos ); 3950 else 3951 bDone = sal_True; // same position: nothing 3952 } 3953 else if ( nDestPosX != aSource.aStart.Col() || nDestPosY != aSource.aStart.Row() || 3954 nSourceTab != nThisTab ) 3955 { 3956 String aUndo = ScGlobal::GetRscString( bIsMove ? STR_UNDO_MOVE : STR_UNDO_COPY ); 3957 pDocSh->GetUndoManager()->EnterListAction( aUndo, aUndo ); 3958 3959 bDone = sal_True; 3960 if ( meDragInsertMode != INS_NONE ) 3961 { 3962 // call with bApi = sal_True to avoid error messages in drop handler 3963 bDone = pDocSh->GetDocFunc().InsertCells( aDest, NULL, meDragInsertMode, sal_True /*bRecord*/, sal_True /*bApi*/, sal_True /*bPartOfPaste*/ ); 3964 if ( bDone ) 3965 { 3966 if ( nThisTab == nSourceTab ) 3967 { 3968 if ( meDragInsertMode == INS_CELLSDOWN && 3969 nDestPosX == aSource.aStart.Col() && nDestPosY < aSource.aStart.Row() ) 3970 { 3971 bDone = aSource.Move( 0, nSizeY, 0, pSourceDoc ); 3972 } 3973 else if ( meDragInsertMode == INS_CELLSRIGHT && 3974 nDestPosY == aSource.aStart.Row() && nDestPosX < aSource.aStart.Col() ) 3975 { 3976 bDone = aSource.Move( nSizeX, 0, 0, pSourceDoc ); 3977 } 3978 } 3979 pDocSh->UpdateOle( pViewData ); 3980 pView->CellContentChanged(); 3981 } 3982 } 3983 3984 if ( bDone ) 3985 { 3986 if ( bIsLink ) 3987 { 3988 // call with bApi = sal_True to avoid error messages in drop handler 3989 bDone = pView->LinkBlock( aSource, aDest.aStart, sal_True /*bApi*/ ); 3990 } 3991 else 3992 { 3993 // call with bApi = sal_True to avoid error messages in drop handler 3994 bDone = pView->MoveBlockTo( aSource, aDest.aStart, bIsMove, sal_True /*bRecord*/, sal_True /*bPaint*/, sal_True /*bApi*/ ); 3995 } 3996 } 3997 3998 if ( bDone && meDragInsertMode != INS_NONE && bIsMove && nThisTab == nSourceTab ) 3999 { 4000 DelCellCmd eCmd = DEL_NONE; 4001 if ( meDragInsertMode == INS_CELLSDOWN ) 4002 { 4003 eCmd = DEL_CELLSUP; 4004 } 4005 else if ( meDragInsertMode == INS_CELLSRIGHT ) 4006 { 4007 eCmd = DEL_CELLSLEFT; 4008 } 4009 4010 if ( ( eCmd == DEL_CELLSUP && nDestPosX == aSource.aStart.Col() ) || 4011 ( eCmd == DEL_CELLSLEFT && nDestPosY == aSource.aStart.Row() ) ) 4012 { 4013 // call with bApi = sal_True to avoid error messages in drop handler 4014 bDone = pDocSh->GetDocFunc().DeleteCells( aSource, NULL, eCmd, sal_True /*bRecord*/, sal_True /*bApi*/ ); 4015 if ( bDone ) 4016 { 4017 if ( eCmd == DEL_CELLSUP && nDestPosY > aSource.aEnd.Row() ) 4018 { 4019 bDone = aDest.Move( 0, -nSizeY, 0, pThisDoc ); 4020 } 4021 else if ( eCmd == DEL_CELLSLEFT && nDestPosX > aSource.aEnd.Col() ) 4022 { 4023 bDone = aDest.Move( -nSizeX, 0, 0, pThisDoc ); 4024 } 4025 pDocSh->UpdateOle( pViewData ); 4026 pView->CellContentChanged(); 4027 } 4028 } 4029 } 4030 4031 if ( bDone ) 4032 { 4033 pView->MarkRange( aDest, sal_False, sal_False ); 4034 pView->SetCursor( aDest.aEnd.Col(), aDest.aEnd.Row() ); 4035 } 4036 4037 pDocSh->GetUndoManager()->LeaveListAction(); 4038 4039 if (!bDone) 4040 Sound::Beep(); // instead of error message in drop handler 4041 } 4042 else 4043 bDone = sal_True; // nothing to do 4044 } 4045 4046 if (bDone) 4047 pTransObj->SetDragWasInternal(); // don't delete source in DragFinished 4048 } 4049 else if ( !bFiltered && pSourceDoc ) // between documents 4050 { 4051 if ( nFlags & SC_DROP_TABLE ) // copy/link sheets between documents 4052 { 4053 if ( pThisDoc->IsDocEditable() ) 4054 { 4055 ScDocShell* pSrcShell = pTransObj->GetSourceDocShell(); 4056 4057 SCTAB nTabs[MAXTABCOUNT]; 4058 4059 ScMarkData aMark = pTransObj->GetSourceMarkData(); 4060 SCTAB nTabCount = pSourceDoc->GetTableCount(); 4061 SCTAB nTabSelCount = 0; 4062 4063 for(SCTAB i=0; i<nTabCount; i++) 4064 { 4065 if(aMark.GetTableSelect(i)) 4066 { 4067 nTabs[nTabSelCount++]=i; 4068 for(SCTAB j=i+1;j<nTabCount;j++) 4069 { 4070 if((!pSourceDoc->IsVisible(j))&&(pSourceDoc->IsScenario(j))) 4071 { 4072 nTabs[nTabSelCount++]=j; 4073 i=j; 4074 } 4075 else break; 4076 } 4077 } 4078 } 4079 4080 pView->ImportTables( pSrcShell,nTabSelCount, nTabs, bIsLink, nThisTab ); 4081 bDone = sal_True; 4082 } 4083 } 4084 else if ( bIsLink ) 4085 { 4086 // as in PasteDDE 4087 // (external references might be used instead?) 4088 4089 SfxObjectShell* pSourceSh = pSourceDoc->GetDocumentShell(); 4090 DBG_ASSERT(pSourceSh, "drag document has no shell"); 4091 if (pSourceSh) 4092 { 4093 String aUndo = ScGlobal::GetRscString( STR_UNDO_COPY ); 4094 pDocSh->GetUndoManager()->EnterListAction( aUndo, aUndo ); 4095 4096 bDone = sal_True; 4097 if ( meDragInsertMode != INS_NONE ) 4098 { 4099 // call with bApi = sal_True to avoid error messages in drop handler 4100 bDone = pDocSh->GetDocFunc().InsertCells( aDest, NULL, meDragInsertMode, sal_True /*bRecord*/, sal_True /*bApi*/, sal_True /*bPartOfPaste*/ ); 4101 if ( bDone ) 4102 { 4103 pDocSh->UpdateOle( pViewData ); 4104 pView->CellContentChanged(); 4105 } 4106 } 4107 4108 if ( bDone ) 4109 { 4110 String aApp = Application::GetAppName(); 4111 String aTopic = pSourceSh->GetTitle( SFX_TITLE_FULLNAME ); 4112 String aItem; 4113 aSource.Format( aItem, SCA_VALID | SCA_TAB_3D, pSourceDoc ); 4114 4115 // TODO: we could define ocQuote for " 4116 const String aQuote( '"' ); 4117 const String& sSep = ScCompiler::GetNativeSymbol( ocSep); 4118 String aFormula( '=' ); 4119 aFormula += ScCompiler::GetNativeSymbol( ocDde); 4120 aFormula += ScCompiler::GetNativeSymbol( ocOpen); 4121 aFormula += aQuote; 4122 aFormula += aApp; 4123 aFormula += aQuote; 4124 aFormula += sSep; 4125 aFormula += aQuote; 4126 aFormula += aTopic; 4127 aFormula += aQuote; 4128 aFormula += sSep; 4129 aFormula += aQuote; 4130 aFormula += aItem; 4131 aFormula += aQuote; 4132 aFormula += ScCompiler::GetNativeSymbol( ocClose); 4133 4134 pView->DoneBlockMode(); 4135 pView->InitBlockMode( nDestPosX, nDestPosY, nThisTab ); 4136 pView->MarkCursor( nDestPosX + nSizeX - 1, 4137 nDestPosY + nSizeY - 1, nThisTab ); 4138 4139 pView->EnterMatrix( aFormula ); 4140 4141 pView->MarkRange( aDest, sal_False, sal_False ); 4142 pView->SetCursor( aDest.aEnd.Col(), aDest.aEnd.Row() ); 4143 } 4144 4145 pDocSh->GetUndoManager()->LeaveListAction(); 4146 } 4147 } 4148 else 4149 { 4150 //! HasSelectedBlockMatrixFragment without selected sheet? 4151 //! or don't start dragging on a part of a matrix 4152 4153 String aUndo = ScGlobal::GetRscString( bIsMove ? STR_UNDO_MOVE : STR_UNDO_COPY ); 4154 pDocSh->GetUndoManager()->EnterListAction( aUndo, aUndo ); 4155 4156 bDone = sal_True; 4157 if ( meDragInsertMode != INS_NONE ) 4158 { 4159 // call with bApi = sal_True to avoid error messages in drop handler 4160 bDone = pDocSh->GetDocFunc().InsertCells( aDest, NULL, meDragInsertMode, sal_True /*bRecord*/, sal_True /*bApi*/, sal_True /*bPartOfPaste*/ ); 4161 if ( bDone ) 4162 { 4163 pDocSh->UpdateOle( pViewData ); 4164 pView->CellContentChanged(); 4165 } 4166 } 4167 4168 if ( bDone ) 4169 { 4170 pView->Unmark(); // before SetCursor, so CheckSelectionTransfer isn't called with a selection 4171 pView->SetCursor( nDestPosX, nDestPosY ); 4172 bDone = pView->PasteFromClip( IDF_ALL, pTransObj->GetDocument() ); // clip-doc 4173 if ( bDone ) 4174 { 4175 pView->MarkRange( aDest, sal_False, sal_False ); 4176 pView->SetCursor( aDest.aEnd.Col(), aDest.aEnd.Row() ); 4177 } 4178 } 4179 4180 pDocSh->GetUndoManager()->LeaveListAction(); 4181 4182 // no longer call ResetMark here - the inserted block has been selected 4183 // and may have been copied to primary selection 4184 } 4185 } 4186 4187 sal_Int8 nRet = bDone ? nDndAction : DND_ACTION_NONE; 4188 return nRet; 4189 } 4190 4191 sal_Int8 ScGridWindow::ExecuteDrop( const ExecuteDropEvent& rEvt ) 4192 { 4193 DrawMarkDropObj( NULL ); // drawing layer 4194 4195 ScModule* pScMod = SC_MOD(); 4196 const ScDragData& rData = pScMod->GetDragData(); 4197 if (rData.pCellTransfer) 4198 return ExecutePrivateDrop( rEvt ); 4199 4200 Point aPos = rEvt.maPosPixel; 4201 4202 if ( rData.aLinkDoc.Len() ) 4203 { 4204 // try to insert a link 4205 4206 sal_Bool bOk = sal_True; 4207 String aThisName; 4208 ScDocShell* pDocSh = pViewData->GetDocShell(); 4209 if (pDocSh && pDocSh->HasName()) 4210 aThisName = pDocSh->GetMedium()->GetName(); 4211 4212 if ( rData.aLinkDoc == aThisName ) // error - no link within a document 4213 bOk = sal_False; 4214 else 4215 { 4216 ScViewFunc* pView = pViewData->GetView(); 4217 if ( rData.aLinkTable.Len() ) 4218 pView->InsertTableLink( rData.aLinkDoc, EMPTY_STRING, EMPTY_STRING, 4219 rData.aLinkTable ); 4220 else if ( rData.aLinkArea.Len() ) 4221 { 4222 SCsCOL nPosX; 4223 SCsROW nPosY; 4224 pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY ); 4225 pView->MoveCursorAbs( nPosX, nPosY, SC_FOLLOW_NONE, sal_False, sal_False ); 4226 4227 pView->InsertAreaLink( rData.aLinkDoc, EMPTY_STRING, EMPTY_STRING, 4228 rData.aLinkArea, 0 ); 4229 } 4230 else 4231 { 4232 DBG_ERROR("drop with link: no sheet nor area"); 4233 bOk = sal_False; 4234 } 4235 } 4236 4237 return bOk ? rEvt.mnAction : DND_ACTION_NONE; // don't try anything else 4238 } 4239 4240 Point aLogicPos = PixelToLogic(aPos); 4241 sal_Bool bIsLink = ( rEvt.mnAction == DND_ACTION_LINK ); 4242 4243 if (!bIsLink && rData.pDrawTransfer) 4244 { 4245 sal_uInt16 nFlags = rData.pDrawTransfer->GetDragSourceFlags(); 4246 4247 sal_Bool bIsNavi = ( nFlags & SC_DROP_NAVIGATOR ) != 0; 4248 sal_Bool bIsMove = ( rEvt.mnAction == DND_ACTION_MOVE && !bIsNavi ); 4249 4250 bPasteIsMove = bIsMove; 4251 4252 pViewData->GetView()->PasteDraw( aLogicPos, rData.pDrawTransfer->GetModel() ); 4253 4254 if (bPasteIsMove) 4255 rData.pDrawTransfer->SetDragWasInternal(); 4256 bPasteIsMove = sal_False; 4257 4258 return rEvt.mnAction; 4259 } 4260 4261 4262 SCsCOL nPosX; 4263 SCsROW nPosY; 4264 pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY ); 4265 4266 if (rData.aJumpTarget.Len()) 4267 { 4268 // internal bookmark (from Navigator) 4269 // bookmark clipboard formats are in PasteScDataObject 4270 4271 if ( !rData.pJumpLocalDoc || rData.pJumpLocalDoc == pViewData->GetDocument() ) 4272 { 4273 pViewData->GetViewShell()->InsertBookmark( rData.aJumpText, rData.aJumpTarget, 4274 nPosX, nPosY ); 4275 return rEvt.mnAction; 4276 } 4277 } 4278 4279 ScDocument* pThisDoc = pViewData->GetDocument(); 4280 SdrObject* pHitObj = pThisDoc->GetObjectAtPoint( pViewData->GetTabNo(), PixelToLogic(aPos) ); 4281 if ( pHitObj && bIsLink ) 4282 { 4283 // dropped on drawing object 4284 // PasteOnDrawObject checks for valid formats 4285 if ( pViewData->GetView()->PasteOnDrawObject( rEvt.maDropEvent.Transferable, pHitObj, sal_True ) ) 4286 return rEvt.mnAction; 4287 } 4288 4289 sal_Bool bDone = sal_False; 4290 4291 sal_uLong nFormatId = bIsLink ? 4292 lcl_GetDropLinkId( rEvt.maDropEvent.Transferable ) : 4293 lcl_GetDropFormatId( rEvt.maDropEvent.Transferable ); 4294 if ( nFormatId ) 4295 { 4296 pScMod->SetInExecuteDrop( sal_True ); // #i28468# prevent error messages from PasteDataFormat 4297 bPasteIsDrop = sal_True; 4298 bDone = pViewData->GetView()->PasteDataFormat( 4299 nFormatId, rEvt.maDropEvent.Transferable, nPosX, nPosY, &aLogicPos, bIsLink ); 4300 bPasteIsDrop = sal_False; 4301 pScMod->SetInExecuteDrop( sal_False ); 4302 } 4303 4304 sal_Int8 nRet = bDone ? rEvt.mnAction : DND_ACTION_NONE; 4305 return nRet; 4306 } 4307 4308 //-------------------------------------------------------- 4309 4310 void ScGridWindow::PasteSelection( const Point& rPosPixel ) 4311 { 4312 Point aLogicPos = PixelToLogic( rPosPixel ); 4313 4314 SCsCOL nPosX; 4315 SCsROW nPosY; 4316 pViewData->GetPosFromPixel( rPosPixel.X(), rPosPixel.Y(), eWhich, nPosX, nPosY ); 4317 4318 ScSelectionTransferObj* pOwnSelection = SC_MOD()->GetSelectionTransfer(); 4319 if ( pOwnSelection ) 4320 { 4321 // within Calc 4322 4323 ScTransferObj* pCellTransfer = pOwnSelection->GetCellData(); 4324 if ( pCellTransfer ) 4325 { 4326 // keep a reference to the data in case the selection is changed during paste 4327 uno::Reference<datatransfer::XTransferable> xRef( pCellTransfer ); 4328 DropTransferObj( pCellTransfer, nPosX, nPosY, aLogicPos, DND_ACTION_COPY ); 4329 } 4330 else 4331 { 4332 ScDrawTransferObj* pDrawTransfer = pOwnSelection->GetDrawData(); 4333 if ( pDrawTransfer ) 4334 { 4335 // keep a reference to the data in case the selection is changed during paste 4336 uno::Reference<datatransfer::XTransferable> xRef( pDrawTransfer ); 4337 4338 // #96821# bSameDocClipboard argument for PasteDraw is needed 4339 // because only DragData is checked directly inside PasteDraw 4340 pViewData->GetView()->PasteDraw( aLogicPos, pDrawTransfer->GetModel(), sal_False, 4341 pDrawTransfer->GetSourceDocID() == pViewData->GetDocument()->GetDocumentID() ); 4342 } 4343 } 4344 } 4345 else 4346 { 4347 // get selection from system 4348 4349 TransferableDataHelper aDataHelper( TransferableDataHelper::CreateFromSelection( this ) ); 4350 uno::Reference<datatransfer::XTransferable> xTransferable = aDataHelper.GetTransferable(); 4351 if ( xTransferable.is() ) 4352 { 4353 sal_uLong nFormatId = lcl_GetDropFormatId( xTransferable, true ); 4354 if ( nFormatId ) 4355 { 4356 bPasteIsDrop = sal_True; 4357 pViewData->GetView()->PasteDataFormat( nFormatId, xTransferable, nPosX, nPosY, &aLogicPos ); 4358 bPasteIsDrop = sal_False; 4359 } 4360 } 4361 } 4362 } 4363 4364 //-------------------------------------------------------- 4365 4366 void ScGridWindow::UpdateEditViewPos() 4367 { 4368 if (pViewData->HasEditView(eWhich)) 4369 { 4370 EditView* pView; 4371 SCCOL nCol; 4372 SCROW nRow; 4373 pViewData->GetEditView( eWhich, pView, nCol, nRow ); 4374 SCCOL nEndCol = pViewData->GetEditEndCol(); 4375 SCROW nEndRow = pViewData->GetEditEndRow(); 4376 4377 // hide EditView? 4378 4379 sal_Bool bHide = ( nEndCol<pViewData->GetPosX(eHWhich) || nEndRow<pViewData->GetPosY(eVWhich) ); 4380 if ( SC_MOD()->IsFormulaMode() ) 4381 if ( pViewData->GetTabNo() != pViewData->GetRefTabNo() ) 4382 bHide = sal_True; 4383 4384 if (bHide) 4385 { 4386 Rectangle aRect = pView->GetOutputArea(); 4387 long nHeight = aRect.Bottom() - aRect.Top(); 4388 aRect.Top() = PixelToLogic(GetOutputSizePixel(), pViewData->GetLogicMode()). 4389 Height() * 2; 4390 aRect.Bottom() = aRect.Top() + nHeight; 4391 pView->SetOutputArea( aRect ); 4392 pView->HideCursor(); 4393 } 4394 else 4395 { 4396 // bForceToTop = sal_True for editing 4397 Rectangle aPixRect = pViewData->GetEditArea( eWhich, nCol, nRow, this, NULL, sal_True ); 4398 Point aScrPos = PixelToLogic( aPixRect.TopLeft(), pViewData->GetLogicMode() ); 4399 4400 Rectangle aRect = pView->GetOutputArea(); 4401 aRect.SetPos( aScrPos ); 4402 pView->SetOutputArea( aRect ); 4403 pView->ShowCursor(); 4404 } 4405 } 4406 } 4407 4408 void ScGridWindow::ScrollPixel( long nDifX, long nDifY ) 4409 { 4410 ClickExtern(); 4411 HideNoteMarker(); 4412 4413 bIsInScroll = sal_True; 4414 //sal_Bool bXor=DrawBeforeScroll(); 4415 4416 SetMapMode(MAP_PIXEL); 4417 Scroll( nDifX, nDifY, SCROLL_CHILDREN ); 4418 SetMapMode( GetDrawMapMode() ); // verschobenen MapMode erzeugen 4419 4420 UpdateEditViewPos(); 4421 4422 DrawAfterScroll(); //bXor); 4423 bIsInScroll = sal_False; 4424 } 4425 4426 // Formeln neu zeichnen ------------------------------------------------- 4427 4428 void ScGridWindow::UpdateFormulas() 4429 { 4430 if (pViewData->GetView()->IsMinimized()) 4431 return; 4432 4433 if ( nPaintCount ) 4434 { 4435 // nicht anfangen, verschachtelt zu painten 4436 // (dann wuerde zumindest der MapMode nicht mehr stimmen) 4437 4438 bNeedsRepaint = sal_True; // -> am Ende vom Paint nochmal Invalidate auf alles 4439 aRepaintPixel = Rectangle(); // alles 4440 return; 4441 } 4442 4443 SCCOL nX1 = pViewData->GetPosX( eHWhich ); 4444 SCROW nY1 = pViewData->GetPosY( eVWhich ); 4445 SCCOL nX2 = nX1 + pViewData->VisibleCellsX( eHWhich ); 4446 SCROW nY2 = nY1 + pViewData->VisibleCellsY( eVWhich ); 4447 4448 if (nX2 > MAXCOL) nX2 = MAXCOL; 4449 if (nY2 > MAXROW) nY2 = MAXROW; 4450 4451 // Draw( nX1, nY1, nX2, nY2, SC_UPDATE_CHANGED ); 4452 4453 // don't draw directly - instead use OutputData to find changed area and invalidate 4454 4455 SCROW nPosY = nY1; 4456 4457 ScDocShell* pDocSh = pViewData->GetDocShell(); 4458 ScDocument* pDoc = pDocSh->GetDocument(); 4459 SCTAB nTab = pViewData->GetTabNo(); 4460 4461 pDoc->ExtendHidden( nX1, nY1, nX2, nY2, nTab ); 4462 4463 Point aScrPos = pViewData->GetScrPos( nX1, nY1, eWhich ); 4464 long nMirrorWidth = GetSizePixel().Width(); 4465 sal_Bool bLayoutRTL = pDoc->IsLayoutRTL( nTab ); 4466 // unused variable long nLayoutSign = bLayoutRTL ? -1 : 1; 4467 if ( bLayoutRTL ) 4468 { 4469 long nEndPixel = pViewData->GetScrPos( nX2+1, nPosY, eWhich ).X(); 4470 nMirrorWidth = aScrPos.X() - nEndPixel; 4471 aScrPos.X() = nEndPixel + 1; 4472 } 4473 4474 long nScrX = aScrPos.X(); 4475 long nScrY = aScrPos.Y(); 4476 4477 double nPPTX = pViewData->GetPPTX(); 4478 double nPPTY = pViewData->GetPPTY(); 4479 4480 ScTableInfo aTabInfo; 4481 pDoc->FillInfo( aTabInfo, nX1, nY1, nX2, nY2, nTab, nPPTX, nPPTY, sal_False, sal_False ); 4482 4483 Fraction aZoomX = pViewData->GetZoomX(); 4484 Fraction aZoomY = pViewData->GetZoomY(); 4485 ScOutputData aOutputData( this, OUTTYPE_WINDOW, aTabInfo, pDoc, nTab, 4486 nScrX, nScrY, nX1, nY1, nX2, nY2, nPPTX, nPPTY, 4487 &aZoomX, &aZoomY ); 4488 aOutputData.SetMirrorWidth( nMirrorWidth ); 4489 4490 aOutputData.FindChanged(); 4491 4492 // #122149# do not use old GetChangedArea() which used polygon-based Regions, but use 4493 // the region-band based new version; anyways, only rectangles are added 4494 Region aChangedRegion( aOutputData.GetChangedAreaRegion() ); // logic (PixelToLogic) 4495 if(!aChangedRegion.IsEmpty()) 4496 { 4497 Invalidate(aChangedRegion); 4498 } 4499 4500 CheckNeedsRepaint(); // #i90362# used to be called via Draw() - still needed here 4501 } 4502 4503 void ScGridWindow::UpdateAutoFillMark(sal_Bool bMarked, const ScRange& rMarkRange) 4504 { 4505 if ( bMarked != bAutoMarkVisible || ( bMarked && rMarkRange.aEnd != aAutoMarkPos ) ) 4506 { 4507 HideCursor(); 4508 bAutoMarkVisible = bMarked; 4509 if ( bMarked ) 4510 aAutoMarkPos = rMarkRange.aEnd; 4511 ShowCursor(); 4512 4513 UpdateAutoFillOverlay(); 4514 } 4515 } 4516 4517 void ScGridWindow::UpdateListValPos( sal_Bool bVisible, const ScAddress& rPos ) 4518 { 4519 sal_Bool bOldButton = bListValButton; 4520 ScAddress aOldPos = aListValPos; 4521 4522 bListValButton = bVisible; 4523 aListValPos = rPos; 4524 4525 if ( bListValButton ) 4526 { 4527 if ( !bOldButton || aListValPos != aOldPos ) 4528 { 4529 // paint area of new button 4530 Invalidate( PixelToLogic( GetListValButtonRect( aListValPos ) ) ); 4531 } 4532 } 4533 if ( bOldButton ) 4534 { 4535 if ( !bListValButton || aListValPos != aOldPos ) 4536 { 4537 // paint area of old button 4538 Invalidate( PixelToLogic( GetListValButtonRect( aOldPos ) ) ); 4539 } 4540 } 4541 } 4542 4543 void ScGridWindow::HideCursor() 4544 { 4545 ++nCursorHideCount; 4546 if (nCursorHideCount==1) 4547 { 4548 DrawCursor(); 4549 DrawAutoFillMark(); 4550 } 4551 } 4552 4553 void ScGridWindow::ShowCursor() 4554 { 4555 if (nCursorHideCount==0) 4556 { 4557 DBG_ERROR("zuviel ShowCursor"); 4558 return; 4559 } 4560 4561 if (nCursorHideCount==1) 4562 { 4563 // #i57745# Draw the cursor before setting the variable, in case the 4564 // GetSizePixel call from drawing causes a repaint (resize handler is called) 4565 DrawAutoFillMark(); 4566 DrawCursor(); 4567 } 4568 4569 --nCursorHideCount; 4570 } 4571 4572 void __EXPORT ScGridWindow::GetFocus() 4573 { 4574 ScTabViewShell* pViewShell = pViewData->GetViewShell(); 4575 pViewShell->GotFocus(); 4576 pViewShell->SetFormShellAtTop( sal_False ); // focus in GridWindow -> FormShell no longer on top 4577 4578 if (pViewShell->HasAccessibilityObjects()) 4579 pViewShell->BroadcastAccessibility(ScAccGridWinFocusGotHint(eWhich, GetAccessible())); 4580 4581 4582 if ( !SC_MOD()->IsFormulaMode() ) 4583 { 4584 pViewShell->UpdateInputHandler(); 4585 // StopMarking(); // falls Dialog (Fehler), weil dann kein ButtonUp 4586 // MO: nur wenn nicht im RefInput-Modus 4587 // -> GetFocus/MouseButtonDown-Reihenfolge 4588 // auf dem Mac 4589 } 4590 4591 Window::GetFocus(); 4592 } 4593 4594 void __EXPORT ScGridWindow::LoseFocus() 4595 { 4596 ScTabViewShell* pViewShell = pViewData->GetViewShell(); 4597 pViewShell->LostFocus(); 4598 4599 if (pViewShell->HasAccessibilityObjects()) 4600 pViewShell->BroadcastAccessibility(ScAccGridWinFocusLostHint(eWhich, GetAccessible())); 4601 4602 Window::LoseFocus(); 4603 } 4604 4605 Point ScGridWindow::GetMousePosPixel() const { return aCurMousePos; } 4606 4607 //------------------------------------------------------------------------ 4608 4609 sal_Bool ScGridWindow::HitRangeFinder( const Point& rMouse, sal_Bool& rCorner, 4610 sal_uInt16* pIndex, SCsCOL* pAddX, SCsROW* pAddY ) 4611 { 4612 sal_Bool bFound = sal_False; 4613 ScInputHandler* pHdl = SC_MOD()->GetInputHdl( pViewData->GetViewShell() ); 4614 if (pHdl) 4615 { 4616 ScRangeFindList* pRangeFinder = pHdl->GetRangeFindList(); 4617 if ( pRangeFinder && !pRangeFinder->IsHidden() && 4618 pRangeFinder->GetDocName() == pViewData->GetDocShell()->GetTitle() ) 4619 { 4620 ScDocument* pDoc = pViewData->GetDocument(); 4621 SCTAB nTab = pViewData->GetTabNo(); 4622 sal_Bool bLayoutRTL = pDoc->IsLayoutRTL( nTab ); 4623 long nLayoutSign = bLayoutRTL ? -1 : 1; 4624 4625 SCsCOL nPosX; 4626 SCsROW nPosY; 4627 pViewData->GetPosFromPixel( rMouse.X(), rMouse.Y(), eWhich, nPosX, nPosY ); 4628 // zusammengefasste (einzeln/Bereich) ??? 4629 ScAddress aAddr( nPosX, nPosY, nTab ); 4630 4631 // Point aNext = pViewData->GetScrPos( nPosX+1, nPosY+1, eWhich ); 4632 4633 Point aNext = pViewData->GetScrPos( nPosX, nPosY, eWhich, sal_True ); 4634 long nSizeXPix; 4635 long nSizeYPix; 4636 pViewData->GetMergeSizePixel( nPosX, nPosY, nSizeXPix, nSizeYPix ); 4637 aNext.X() += nSizeXPix * nLayoutSign; 4638 aNext.Y() += nSizeYPix; 4639 4640 sal_Bool bCornerHor; 4641 if ( bLayoutRTL ) 4642 bCornerHor = ( rMouse.X() >= aNext.X() && rMouse.X() <= aNext.X() + 8 ); 4643 else 4644 bCornerHor = ( rMouse.X() >= aNext.X() - 8 && rMouse.X() <= aNext.X() ); 4645 4646 sal_Bool bCellCorner = ( bCornerHor && 4647 rMouse.Y() >= aNext.Y() - 8 && rMouse.Y() <= aNext.Y() ); 4648 // corner is hit only if the mouse is within the cell 4649 4650 sal_uInt16 nCount = (sal_uInt16)pRangeFinder->Count(); 4651 for (sal_uInt16 i=nCount; i;) 4652 { 4653 // rueckwaerts suchen, damit der zuletzt gepaintete Rahmen gefunden wird 4654 --i; 4655 ScRangeFindData* pData = pRangeFinder->GetObject(i); 4656 if ( pData && pData->aRef.In(aAddr) ) 4657 { 4658 if (pIndex) *pIndex = i; 4659 if (pAddX) *pAddX = nPosX - pData->aRef.aStart.Col(); 4660 if (pAddY) *pAddY = nPosY - pData->aRef.aStart.Row(); 4661 bFound = sal_True; 4662 rCorner = ( bCellCorner && aAddr == pData->aRef.aEnd ); 4663 break; 4664 } 4665 } 4666 } 4667 } 4668 return bFound; 4669 } 4670 4671 #define SCE_TOP 1 4672 #define SCE_BOTTOM 2 4673 #define SCE_LEFT 4 4674 #define SCE_RIGHT 8 4675 #define SCE_ALL 15 4676 4677 void lcl_PaintOneRange( ScDocShell* pDocSh, const ScRange& rRange, sal_uInt16 nEdges ) 4678 { 4679 // der Range ist immer richtigherum 4680 4681 SCCOL nCol1 = rRange.aStart.Col(); 4682 SCROW nRow1 = rRange.aStart.Row(); 4683 SCTAB nTab1 = rRange.aStart.Tab(); 4684 SCCOL nCol2 = rRange.aEnd.Col(); 4685 SCROW nRow2 = rRange.aEnd.Row(); 4686 SCTAB nTab2 = rRange.aEnd.Tab(); 4687 sal_Bool bHiddenEdge = sal_False; 4688 SCROW nTmp; 4689 4690 ScDocument* pDoc = pDocSh->GetDocument(); 4691 while ( nCol1 > 0 && pDoc->ColHidden(nCol1, nTab1) ) 4692 { 4693 --nCol1; 4694 bHiddenEdge = sal_True; 4695 } 4696 while ( nCol2 < MAXCOL && pDoc->ColHidden(nCol2, nTab1) ) 4697 { 4698 ++nCol2; 4699 bHiddenEdge = sal_True; 4700 } 4701 nTmp = pDoc->FirstVisibleRow(0, nRow1, nTab1); 4702 if (!ValidRow(nTmp)) 4703 nTmp = 0; 4704 if (nTmp < nRow1) 4705 { 4706 nRow1 = nTmp; 4707 bHiddenEdge = sal_True; 4708 } 4709 nTmp = pDoc->FirstVisibleRow(nRow2, MAXROW, nTab1); 4710 if (!ValidRow(nTmp)) 4711 nTmp = MAXROW; 4712 if (nTmp > nRow2) 4713 { 4714 nRow2 = nTmp; 4715 bHiddenEdge = sal_True; 4716 } 4717 4718 if ( nCol2 > nCol1 + 1 && nRow2 > nRow1 + 1 && !bHiddenEdge ) 4719 { 4720 // nur an den Raendern entlang 4721 // (die Ecken werden evtl. zweimal getroffen) 4722 4723 if ( nEdges & SCE_TOP ) 4724 pDocSh->PostPaint( nCol1, nRow1, nTab1, nCol2, nRow1, nTab2, PAINT_MARKS ); 4725 if ( nEdges & SCE_LEFT ) 4726 pDocSh->PostPaint( nCol1, nRow1, nTab1, nCol1, nRow2, nTab2, PAINT_MARKS ); 4727 if ( nEdges & SCE_RIGHT ) 4728 pDocSh->PostPaint( nCol2, nRow1, nTab1, nCol2, nRow2, nTab2, PAINT_MARKS ); 4729 if ( nEdges & SCE_BOTTOM ) 4730 pDocSh->PostPaint( nCol1, nRow2, nTab1, nCol2, nRow2, nTab2, PAINT_MARKS ); 4731 } 4732 else // everything in one call 4733 pDocSh->PostPaint( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2, PAINT_MARKS ); 4734 } 4735 4736 void lcl_PaintRefChanged( ScDocShell* pDocSh, const ScRange& rOldUn, const ScRange& rNewUn ) 4737 { 4738 // Repaint fuer die Teile des Rahmens in Old, die bei New nicht mehr da sind 4739 4740 ScRange aOld = rOldUn; 4741 ScRange aNew = rNewUn; 4742 aOld.Justify(); 4743 aNew.Justify(); 4744 4745 if ( aOld.aStart == aOld.aEnd ) //! Tab ignorieren? 4746 pDocSh->GetDocument()->ExtendMerge(aOld); 4747 if ( aNew.aStart == aNew.aEnd ) //! Tab ignorieren? 4748 pDocSh->GetDocument()->ExtendMerge(aNew); 4749 4750 SCCOL nOldCol1 = aOld.aStart.Col(); 4751 SCROW nOldRow1 = aOld.aStart.Row(); 4752 SCCOL nOldCol2 = aOld.aEnd.Col(); 4753 SCROW nOldRow2 = aOld.aEnd.Row(); 4754 SCCOL nNewCol1 = aNew.aStart.Col(); 4755 SCROW nNewRow1 = aNew.aStart.Row(); 4756 SCCOL nNewCol2 = aNew.aEnd.Col(); 4757 SCROW nNewRow2 = aNew.aEnd.Row(); 4758 SCTAB nTab1 = aOld.aStart.Tab(); // Tab aendert sich nicht 4759 SCTAB nTab2 = aOld.aEnd.Tab(); 4760 4761 if ( nNewRow2 < nOldRow1 || nNewRow1 > nOldRow2 || 4762 nNewCol2 < nOldCol1 || nNewCol1 > nOldCol2 || 4763 ( nNewCol1 != nOldCol1 && nNewRow1 != nOldRow1 && 4764 nNewCol2 != nOldCol2 && nNewRow2 != nOldRow2 ) ) 4765 { 4766 // komplett weggeschoben oder alle Seiten veraendert 4767 // (Abfrage <= statt < geht schief bei einzelnen Zeilen/Spalten) 4768 4769 lcl_PaintOneRange( pDocSh, aOld, SCE_ALL ); 4770 } 4771 else // alle vier Kanten einzeln testen 4772 { 4773 // oberer Teil 4774 if ( nNewRow1 < nOldRow1 ) // nur obere Linie loeschen 4775 lcl_PaintOneRange( pDocSh, ScRange( 4776 nOldCol1, nOldRow1, nTab1, nOldCol2, nOldRow1, nTab2 ), SCE_ALL ); 4777 else if ( nNewRow1 > nOldRow1 ) // den Teil, der oben wegkommt 4778 lcl_PaintOneRange( pDocSh, ScRange( 4779 nOldCol1, nOldRow1, nTab1, nOldCol2, nNewRow1-1, nTab2 ), 4780 SCE_ALL &~ SCE_BOTTOM ); 4781 4782 // unterer Teil 4783 if ( nNewRow2 > nOldRow2 ) // nur untere Linie loeschen 4784 lcl_PaintOneRange( pDocSh, ScRange( 4785 nOldCol1, nOldRow2, nTab1, nOldCol2, nOldRow2, nTab2 ), SCE_ALL ); 4786 else if ( nNewRow2 < nOldRow2 ) // den Teil, der unten wegkommt 4787 lcl_PaintOneRange( pDocSh, ScRange( 4788 nOldCol1, nNewRow2+1, nTab1, nOldCol2, nOldRow2, nTab2 ), 4789 SCE_ALL &~ SCE_TOP ); 4790 4791 // linker Teil 4792 if ( nNewCol1 < nOldCol1 ) // nur linke Linie loeschen 4793 lcl_PaintOneRange( pDocSh, ScRange( 4794 nOldCol1, nOldRow1, nTab1, nOldCol1, nOldRow2, nTab2 ), SCE_ALL ); 4795 else if ( nNewCol1 > nOldCol1 ) // den Teil, der links wegkommt 4796 lcl_PaintOneRange( pDocSh, ScRange( 4797 nOldCol1, nOldRow1, nTab1, nNewCol1-1, nOldRow2, nTab2 ), 4798 SCE_ALL &~ SCE_RIGHT ); 4799 4800 // rechter Teil 4801 if ( nNewCol2 > nOldCol2 ) // nur rechte Linie loeschen 4802 lcl_PaintOneRange( pDocSh, ScRange( 4803 nOldCol2, nOldRow1, nTab1, nOldCol2, nOldRow2, nTab2 ), SCE_ALL ); 4804 else if ( nNewCol2 < nOldCol2 ) // den Teil, der rechts wegkommt 4805 lcl_PaintOneRange( pDocSh, ScRange( 4806 nNewCol2+1, nOldRow1, nTab1, nOldCol2, nOldRow2, nTab2 ), 4807 SCE_ALL &~ SCE_LEFT ); 4808 } 4809 } 4810 4811 void ScGridWindow::RFMouseMove( const MouseEvent& rMEvt, sal_Bool bUp ) 4812 { 4813 ScInputHandler* pHdl = SC_MOD()->GetInputHdl( pViewData->GetViewShell() ); 4814 if (!pHdl) 4815 return; 4816 ScRangeFindList* pRangeFinder = pHdl->GetRangeFindList(); 4817 if (!pRangeFinder || nRFIndex >= pRangeFinder->Count()) 4818 return; 4819 ScRangeFindData* pData = pRangeFinder->GetObject( nRFIndex ); 4820 if (!pData) 4821 return; 4822 4823 // Mauszeiger 4824 4825 if (bRFSize) 4826 SetPointer( Pointer( POINTER_CROSS ) ); 4827 else 4828 SetPointer( Pointer( POINTER_HAND ) ); 4829 4830 // Scrolling 4831 4832 sal_Bool bTimer = sal_False; 4833 Point aPos = rMEvt.GetPosPixel(); 4834 SCsCOL nDx = 0; 4835 SCsROW nDy = 0; 4836 if ( aPos.X() < 0 ) nDx = -1; 4837 if ( aPos.Y() < 0 ) nDy = -1; 4838 Size aSize = GetOutputSizePixel(); 4839 if ( aPos.X() >= aSize.Width() ) 4840 nDx = 1; 4841 if ( aPos.Y() >= aSize.Height() ) 4842 nDy = 1; 4843 if ( nDx != 0 || nDy != 0 ) 4844 { 4845 if ( nDx != 0) pViewData->GetView()->ScrollX( nDx, WhichH(eWhich) ); 4846 if ( nDy != 0 ) pViewData->GetView()->ScrollY( nDy, WhichV(eWhich) ); 4847 bTimer = sal_True; 4848 } 4849 4850 // Umschalten bei Fixierung (damit Scrolling funktioniert) 4851 4852 if ( eWhich == pViewData->GetActivePart() ) //?? 4853 { 4854 if ( pViewData->GetHSplitMode() == SC_SPLIT_FIX ) 4855 if ( nDx > 0 ) 4856 { 4857 if ( eWhich == SC_SPLIT_TOPLEFT ) 4858 pViewData->GetView()->ActivatePart( SC_SPLIT_TOPRIGHT ); 4859 else if ( eWhich == SC_SPLIT_BOTTOMLEFT ) 4860 pViewData->GetView()->ActivatePart( SC_SPLIT_BOTTOMRIGHT ); 4861 } 4862 4863 if ( pViewData->GetVSplitMode() == SC_SPLIT_FIX ) 4864 if ( nDy > 0 ) 4865 { 4866 if ( eWhich == SC_SPLIT_TOPLEFT ) 4867 pViewData->GetView()->ActivatePart( SC_SPLIT_BOTTOMLEFT ); 4868 else if ( eWhich == SC_SPLIT_TOPRIGHT ) 4869 pViewData->GetView()->ActivatePart( SC_SPLIT_BOTTOMRIGHT ); 4870 } 4871 } 4872 4873 // Verschieben 4874 4875 SCsCOL nPosX; 4876 SCsROW nPosY; 4877 pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY ); 4878 4879 ScRange aOld = pData->aRef; 4880 ScRange aNew = aOld; 4881 if ( bRFSize ) 4882 { 4883 aNew.aEnd.SetCol((SCCOL)nPosX); 4884 aNew.aEnd.SetRow((SCROW)nPosY); 4885 } 4886 else 4887 { 4888 long nStartX = nPosX - nRFAddX; 4889 if ( nStartX < 0 ) nStartX = 0; 4890 long nStartY = nPosY - nRFAddY; 4891 if ( nStartY < 0 ) nStartY = 0; 4892 long nEndX = nStartX + aOld.aEnd.Col() - aOld.aStart.Col(); 4893 if ( nEndX > MAXCOL ) 4894 { 4895 nStartX -= ( nEndX - MAXROW ); 4896 nEndX = MAXCOL; 4897 } 4898 long nEndY = nStartY + aOld.aEnd.Row() - aOld.aStart.Row(); 4899 if ( nEndY > MAXROW ) 4900 { 4901 nStartY -= ( nEndY - MAXROW ); 4902 nEndY = MAXROW; 4903 } 4904 4905 aNew.aStart.SetCol((SCCOL)nStartX); 4906 aNew.aStart.SetRow((SCROW)nStartY); 4907 aNew.aEnd.SetCol((SCCOL)nEndX); 4908 aNew.aEnd.SetRow((SCROW)nEndY); 4909 } 4910 4911 if ( bUp ) 4912 aNew.Justify(); // beim ButtonUp wieder richtigherum 4913 4914 if ( aNew != aOld ) 4915 { 4916 pHdl->UpdateRange( nRFIndex, aNew ); 4917 4918 ScDocShell* pDocSh = pViewData->GetDocShell(); 4919 4920 // nur das neuzeichnen, was sich veraendert hat... 4921 lcl_PaintRefChanged( pDocSh, aOld, aNew ); 4922 4923 // neuen Rahmen nur drueberzeichnen (synchron) 4924 pDocSh->Broadcast( ScIndexHint( SC_HINT_SHOWRANGEFINDER, nRFIndex ) ); 4925 4926 Update(); // was man bewegt, will man auch sofort sehen 4927 } 4928 4929 // Timer fuer Scrolling 4930 4931 if (bTimer) 4932 pViewData->GetView()->SetTimer( this, rMEvt ); // Event wiederholen 4933 else 4934 pViewData->GetView()->ResetTimer(); 4935 } 4936 4937 //------------------------------------------------------------------------ 4938 4939 sal_Bool ScGridWindow::GetEditUrl( const Point& rPos, 4940 String* pName, String* pUrl, String* pTarget ) 4941 { 4942 return GetEditUrlOrError( sal_False, rPos, pName, pUrl, pTarget ); 4943 } 4944 4945 sal_Bool ScGridWindow::GetEditUrlOrError( sal_Bool bSpellErr, const Point& rPos, 4946 String* pName, String* pUrl, String* pTarget ) 4947 { 4948 //! nPosX/Y mit uebergeben? 4949 SCsCOL nPosX; 4950 SCsROW nPosY; 4951 pViewData->GetPosFromPixel( rPos.X(), rPos.Y(), eWhich, nPosX, nPosY ); 4952 4953 SCTAB nTab = pViewData->GetTabNo(); 4954 ScDocShell* pDocSh = pViewData->GetDocShell(); 4955 ScDocument* pDoc = pDocSh->GetDocument(); 4956 ScBaseCell* pCell = NULL; 4957 4958 sal_Bool bFound = lcl_GetHyperlinkCell( pDoc, nPosX, nPosY, nTab, pCell ); 4959 if( !bFound ) 4960 return sal_False; 4961 4962 ScHideTextCursor aHideCursor( pViewData, eWhich ); // before GetEditArea (MapMode is changed) 4963 4964 const ScPatternAttr* pPattern = pDoc->GetPattern( nPosX, nPosY, nTab ); 4965 // bForceToTop = sal_False, use the cell's real position 4966 Rectangle aEditRect = pViewData->GetEditArea( eWhich, nPosX, nPosY, this, pPattern, sal_False ); 4967 if (rPos.Y() < aEditRect.Top()) 4968 return sal_False; 4969 4970 // vertikal kann (noch) nicht angeklickt werden: 4971 4972 if (pPattern->GetCellOrientation() != SVX_ORIENTATION_STANDARD) 4973 return sal_False; 4974 4975 sal_Bool bBreak = ((SfxBoolItem&)pPattern->GetItem(ATTR_LINEBREAK)).GetValue() || 4976 ((SvxCellHorJustify)((const SvxHorJustifyItem&)pPattern-> 4977 GetItem( ATTR_HOR_JUSTIFY )).GetValue() == SVX_HOR_JUSTIFY_BLOCK); 4978 SvxCellHorJustify eHorJust = (SvxCellHorJustify)((SvxHorJustifyItem&)pPattern-> 4979 GetItem(ATTR_HOR_JUSTIFY)).GetValue(); 4980 4981 // EditEngine 4982 4983 ScFieldEditEngine aEngine( pDoc->GetEditPool() ); 4984 ScSizeDeviceProvider aProv(pDocSh); 4985 aEngine.SetRefDevice( aProv.GetDevice() ); 4986 aEngine.SetRefMapMode( MAP_100TH_MM ); 4987 SfxItemSet aDefault( aEngine.GetEmptyItemSet() ); 4988 pPattern->FillEditItemSet( &aDefault ); 4989 SvxAdjust eSvxAdjust = SVX_ADJUST_LEFT; 4990 switch (eHorJust) 4991 { 4992 case SVX_HOR_JUSTIFY_LEFT: 4993 case SVX_HOR_JUSTIFY_REPEAT: // nicht implementiert 4994 case SVX_HOR_JUSTIFY_STANDARD: // always Text if an EditCell type 4995 eSvxAdjust = SVX_ADJUST_LEFT; 4996 break; 4997 case SVX_HOR_JUSTIFY_RIGHT: 4998 eSvxAdjust = SVX_ADJUST_RIGHT; 4999 break; 5000 case SVX_HOR_JUSTIFY_CENTER: 5001 eSvxAdjust = SVX_ADJUST_CENTER; 5002 break; 5003 case SVX_HOR_JUSTIFY_BLOCK: 5004 eSvxAdjust = SVX_ADJUST_BLOCK; 5005 break; 5006 } 5007 aDefault.Put( SvxAdjustItem( eSvxAdjust, EE_PARA_JUST ) ); 5008 aEngine.SetDefaults( aDefault ); 5009 if (bSpellErr) 5010 aEngine.SetControlWord( aEngine.GetControlWord() | EE_CNTRL_ONLINESPELLING ); 5011 5012 MapMode aEditMode = pViewData->GetLogicMode(eWhich); // ohne Drawing-Skalierung 5013 Rectangle aLogicEdit = PixelToLogic( aEditRect, aEditMode ); 5014 long nThisColLogic = aLogicEdit.Right() - aLogicEdit.Left() + 1; 5015 Size aPaperSize = Size( 1000000, 1000000 ); 5016 if(pCell->GetCellType() == CELLTYPE_FORMULA) 5017 { 5018 long nSizeX = 0; 5019 long nSizeY = 0; 5020 pViewData->GetMergeSizePixel( nPosX, nPosY, nSizeX, nSizeY ); 5021 aPaperSize = Size(nSizeX, nSizeY ); 5022 aPaperSize = PixelToLogic(aPaperSize); 5023 } 5024 5025 if (bBreak) 5026 aPaperSize.Width() = nThisColLogic; 5027 aEngine.SetPaperSize( aPaperSize ); 5028 5029 ::std::auto_ptr< EditTextObject > pTextObj; 5030 const EditTextObject* pData; 5031 if(pCell->GetCellType() == CELLTYPE_EDIT) 5032 { 5033 ((ScEditCell*)pCell)->GetData(pData); 5034 if (pData) 5035 aEngine.SetText(*pData); 5036 } 5037 else // HyperLink Formula cell 5038 { 5039 pTextObj.reset((static_cast<ScFormulaCell*>(pCell))->CreateURLObject()); 5040 if (pTextObj.get()) 5041 aEngine.SetText(*pTextObj); 5042 } 5043 5044 long nStartX = aLogicEdit.Left(); 5045 5046 long nTextWidth = aEngine.CalcTextWidth(); 5047 long nTextHeight = aEngine.GetTextHeight(); 5048 if ( nTextWidth < nThisColLogic ) 5049 { 5050 if (eHorJust == SVX_HOR_JUSTIFY_RIGHT) 5051 nStartX += nThisColLogic - nTextWidth; 5052 else if (eHorJust == SVX_HOR_JUSTIFY_CENTER) 5053 nStartX += (nThisColLogic - nTextWidth) / 2; 5054 } 5055 5056 aLogicEdit.Left() = nStartX; 5057 if (!bBreak) 5058 aLogicEdit.Right() = nStartX + nTextWidth; 5059 5060 // There is one glitch when dealing with a hyperlink cell and 5061 // the cell content is NUMERIC. This defaults to right aligned and 5062 // we need to adjust accordingly. 5063 if(pCell->GetCellType() == CELLTYPE_FORMULA && 5064 static_cast<ScFormulaCell*>(pCell)->IsValue() && 5065 eHorJust == SVX_HOR_JUSTIFY_STANDARD) 5066 { 5067 aLogicEdit.Right() = aLogicEdit.Left() + nThisColLogic - 1; 5068 aLogicEdit.Left() = aLogicEdit.Right() - nTextWidth; 5069 } 5070 aLogicEdit.Bottom() = aLogicEdit.Top() + nTextHeight; 5071 5072 5073 Point aLogicClick = PixelToLogic(rPos,aEditMode); 5074 if ( aLogicEdit.IsInside(aLogicClick) ) 5075 { 5076 // aEngine.SetUpdateMode(sal_False); 5077 EditView aTempView( &aEngine, this ); 5078 aTempView.SetOutputArea( aLogicEdit ); 5079 5080 sal_Bool bRet = sal_False; 5081 MapMode aOld = GetMapMode(); 5082 SetMapMode(aEditMode); // kein return mehr 5083 5084 if (bSpellErr) // Spelling-Fehler suchen 5085 { 5086 bRet = aTempView.IsWrongSpelledWordAtPos( rPos ); 5087 if ( bRet ) 5088 pViewData->GetView()->SetCursor( nPosX, nPosY ); // Cursor setzen 5089 } 5090 else // URL suchen 5091 { 5092 const SvxFieldItem* pFieldItem = aTempView.GetFieldUnderMousePointer(); 5093 5094 if (pFieldItem) 5095 { 5096 const SvxFieldData* pField = pFieldItem->GetField(); 5097 if ( pField && pField->ISA(SvxURLField) ) 5098 { 5099 if ( pName || pUrl || pTarget ) 5100 { 5101 const SvxURLField* pURLField = (const SvxURLField*)pField; 5102 if (pName) 5103 *pName = pURLField->GetRepresentation(); 5104 if (pUrl) 5105 *pUrl = pURLField->GetURL(); 5106 if (pTarget) 5107 *pTarget = pURLField->GetTargetFrame(); 5108 } 5109 bRet = sal_True; 5110 } 5111 } 5112 } 5113 5114 SetMapMode(aOld); 5115 5116 // text cursor is restored in ScHideTextCursor dtor 5117 5118 return bRet; 5119 } 5120 return sal_False; 5121 } 5122 5123 sal_Bool ScGridWindow::HasScenarioButton( const Point& rPosPixel, ScRange& rScenRange ) 5124 { 5125 ScDocument* pDoc = pViewData->GetDocument(); 5126 SCTAB nTab = pViewData->GetTabNo(); 5127 SCTAB nTabCount = pDoc->GetTableCount(); 5128 if ( nTab+1<nTabCount && pDoc->IsScenario(nTab+1) && !pDoc->IsScenario(nTab) ) 5129 { 5130 sal_Bool bLayoutRTL = pDoc->IsLayoutRTL( nTab ); 5131 5132 Size aButSize = pViewData->GetScenButSize(); 5133 long nBWidth = aButSize.Width(); 5134 if (!nBWidth) 5135 return sal_False; // noch kein Button gezeichnet -> da ist auch keiner 5136 long nBHeight = aButSize.Height(); 5137 long nHSpace = (long)( SC_SCENARIO_HSPACE * pViewData->GetPPTX() ); 5138 5139 //! Ranges an der Table cachen!!!! 5140 5141 ScMarkData aMarks; 5142 for (SCTAB i=nTab+1; i<nTabCount && pDoc->IsScenario(i); i++) 5143 pDoc->MarkScenario( i, nTab, aMarks, sal_False, SC_SCENARIO_SHOWFRAME ); 5144 ScRangeList aRanges; 5145 aMarks.FillRangeListWithMarks( &aRanges, sal_False ); 5146 5147 5148 sal_uLong nRangeCount = aRanges.Count(); 5149 for (sal_uLong j=0; j<nRangeCount; j++) 5150 { 5151 ScRange aRange = *aRanges.GetObject(j); 5152 // Szenario-Rahmen immer dann auf zusammengefasste Zellen erweitern, wenn 5153 // dadurch keine neuen nicht-ueberdeckten Zellen mit umrandet werden 5154 pDoc->ExtendTotalMerge( aRange ); 5155 5156 sal_Bool bTextBelow = ( aRange.aStart.Row() == 0 ); 5157 5158 Point aButtonPos; 5159 if ( bTextBelow ) 5160 { 5161 aButtonPos = pViewData->GetScrPos( aRange.aEnd.Col()+1, aRange.aEnd.Row()+1, 5162 eWhich, sal_True ); 5163 } 5164 else 5165 { 5166 aButtonPos = pViewData->GetScrPos( aRange.aEnd.Col()+1, aRange.aStart.Row(), 5167 eWhich, sal_True ); 5168 aButtonPos.Y() -= nBHeight; 5169 } 5170 if ( bLayoutRTL ) 5171 aButtonPos.X() -= nHSpace - 1; 5172 else 5173 aButtonPos.X() -= nBWidth - nHSpace; // same for top or bottom 5174 5175 Rectangle aButRect( aButtonPos, Size(nBWidth,nBHeight) ); 5176 if ( aButRect.IsInside( rPosPixel ) ) 5177 { 5178 rScenRange = aRange; 5179 return sal_True; 5180 } 5181 } 5182 } 5183 5184 return sal_False; 5185 } 5186 5187 void ScGridWindow::UpdateVisibleRange() 5188 { 5189 // #163911# Update the visible range outside of paint (called when switching sheets). 5190 // Use the same logic here as in ScGridWindow::Draw. 5191 5192 SCCOL nPosX = pViewData->GetPosX( eHWhich ); 5193 SCROW nPosY = pViewData->GetPosY( eVWhich ); 5194 5195 SCCOL nXRight = nPosX + pViewData->VisibleCellsX(eHWhich); 5196 if (nXRight > MAXCOL) nXRight = MAXCOL; 5197 SCROW nYBottom = nPosY + pViewData->VisibleCellsY(eVWhich); 5198 if (nYBottom > MAXROW) nYBottom = MAXROW; 5199 5200 // Store the current visible range. 5201 maVisibleRange.mnCol1 = nPosX; 5202 maVisibleRange.mnCol2 = nXRight; 5203 maVisibleRange.mnRow1 = nPosY; 5204 maVisibleRange.mnRow2 = nYBottom; 5205 } 5206 5207 // #114409# 5208 void ScGridWindow::DrawLayerCreated() 5209 { 5210 SetMapMode( GetDrawMapMode() ); 5211 5212 // initially create overlay objects 5213 ImpCreateOverlayObjects(); 5214 } 5215 5216 // #114409# 5217 void ScGridWindow::CursorChanged() 5218 { 5219 // here the created OverlayObjects may be transformed in later versions. For 5220 // now, just re-create them 5221 5222 UpdateCursorOverlay(); 5223 } 5224 5225 // #114409# 5226 void ScGridWindow::ImpCreateOverlayObjects() 5227 { 5228 UpdateCursorOverlay(); 5229 UpdateSelectionOverlay(); 5230 UpdateAutoFillOverlay(); 5231 UpdateDragRectOverlay(); 5232 UpdateHeaderOverlay(); 5233 UpdateShrinkOverlay(); 5234 } 5235 5236 // #114409# 5237 void ScGridWindow::ImpDestroyOverlayObjects() 5238 { 5239 DeleteCursorOverlay(); 5240 DeleteSelectionOverlay(); 5241 DeleteAutoFillOverlay(); 5242 DeleteDragRectOverlay(); 5243 DeleteHeaderOverlay(); 5244 DeleteShrinkOverlay(); 5245 } 5246 5247 void ScGridWindow::UpdateAllOverlays() 5248 { 5249 // delete and re-allocate all overlay objects 5250 5251 ImpDestroyOverlayObjects(); 5252 ImpCreateOverlayObjects(); 5253 } 5254 5255 void ScGridWindow::DeleteCursorOverlay() 5256 { 5257 DELETEZ( mpOOCursors ); 5258 } 5259 5260 void ScGridWindow::UpdateCursorOverlay() 5261 { 5262 MapMode aDrawMode = GetDrawMapMode(); 5263 MapMode aOldMode = GetMapMode(); 5264 if ( aOldMode != aDrawMode ) 5265 SetMapMode( aDrawMode ); 5266 5267 // Existing OverlayObjects may be transformed in later versions. 5268 // For now, just re-create them. 5269 5270 DeleteCursorOverlay(); 5271 5272 std::vector<Rectangle> aPixelRects; 5273 5274 // 5275 // determine the cursor rectangles in pixels (moved from ScGridWindow::DrawCursor) 5276 // 5277 5278 SCTAB nTab = pViewData->GetTabNo(); 5279 SCCOL nX = pViewData->GetCurX(); 5280 SCROW nY = pViewData->GetCurY(); 5281 5282 if (!maVisibleRange.isInside(nX, nY)) 5283 return; 5284 5285 // don't show the cursor in overlapped cells 5286 5287 ScDocument* pDoc = pViewData->GetDocument(); 5288 const ScPatternAttr* pPattern = pDoc->GetPattern(nX,nY,nTab); 5289 const ScMergeFlagAttr& rMergeFlag = (const ScMergeFlagAttr&) pPattern->GetItem(ATTR_MERGE_FLAG); 5290 sal_Bool bOverlapped = rMergeFlag.IsOverlapped(); 5291 5292 // left or above of the screen? 5293 5294 sal_Bool bVis = ( nX>=pViewData->GetPosX(eHWhich) && nY>=pViewData->GetPosY(eVWhich) ); 5295 if (!bVis) 5296 { 5297 SCCOL nEndX = nX; 5298 SCROW nEndY = nY; 5299 const ScMergeAttr& rMerge = (const ScMergeAttr&) pPattern->GetItem(ATTR_MERGE); 5300 if (rMerge.GetColMerge() > 1) 5301 nEndX += rMerge.GetColMerge()-1; 5302 if (rMerge.GetRowMerge() > 1) 5303 nEndY += rMerge.GetRowMerge()-1; 5304 bVis = ( nEndX>=pViewData->GetPosX(eHWhich) && nEndY>=pViewData->GetPosY(eVWhich) ); 5305 } 5306 5307 if ( bVis && !bOverlapped && !pViewData->HasEditView(eWhich) && pViewData->IsActive() ) 5308 { 5309 Point aScrPos = pViewData->GetScrPos( nX, nY, eWhich, sal_True ); 5310 sal_Bool bLayoutRTL = pDoc->IsLayoutRTL( nTab ); 5311 5312 // completely right of/below the screen? 5313 // (test with logical start position in aScrPos) 5314 sal_Bool bMaybeVisible; 5315 if ( bLayoutRTL ) 5316 bMaybeVisible = ( aScrPos.X() >= -2 && aScrPos.Y() >= -2 ); 5317 else 5318 { 5319 Size aOutSize = GetOutputSizePixel(); 5320 bMaybeVisible = ( aScrPos.X() <= aOutSize.Width() + 2 && aScrPos.Y() <= aOutSize.Height() + 2 ); 5321 } 5322 if ( bMaybeVisible ) 5323 { 5324 long nSizeXPix; 5325 long nSizeYPix; 5326 pViewData->GetMergeSizePixel( nX, nY, nSizeXPix, nSizeYPix ); 5327 5328 if ( bLayoutRTL ) 5329 aScrPos.X() -= nSizeXPix - 2; // move instead of mirroring 5330 5331 sal_Bool bFix = ( pViewData->GetHSplitMode() == SC_SPLIT_FIX || 5332 pViewData->GetVSplitMode() == SC_SPLIT_FIX ); 5333 if ( pViewData->GetActivePart()==eWhich || bFix ) 5334 { 5335 aScrPos.X() -= 2; 5336 aScrPos.Y() -= 2; 5337 Rectangle aRect( aScrPos, Size( nSizeXPix + 3, nSizeYPix + 3 ) ); 5338 5339 aPixelRects.push_back(Rectangle( aRect.Left(), aRect.Top(), aRect.Left()+2, aRect.Bottom() )); 5340 aPixelRects.push_back(Rectangle( aRect.Right()-2, aRect.Top(), aRect.Right(), aRect.Bottom() )); 5341 aPixelRects.push_back(Rectangle( aRect.Left()+3, aRect.Top(), aRect.Right()-3, aRect.Top()+2 )); 5342 aPixelRects.push_back(Rectangle( aRect.Left()+3, aRect.Bottom()-2, aRect.Right()-3, aRect.Bottom() )); 5343 } 5344 else 5345 { 5346 Rectangle aRect( aScrPos, Size( nSizeXPix - 1, nSizeYPix - 1 ) ); 5347 aPixelRects.push_back( aRect ); 5348 } 5349 } 5350 } 5351 5352 if ( aPixelRects.size() ) 5353 { 5354 // #i70788# get the OverlayManager safely 5355 ::sdr::overlay::OverlayManager* pOverlayManager = getOverlayManager(); 5356 5357 if(pOverlayManager) 5358 { 5359 const Color aCursorColor( SC_MOD()->GetColorConfig().GetColorValue(svtools::FONTCOLOR).nColor ); 5360 std::vector< basegfx::B2DRange > aRanges; 5361 const basegfx::B2DHomMatrix aTransform(GetInverseViewTransformation()); 5362 5363 for(sal_uInt32 a(0); a < aPixelRects.size(); a++) 5364 { 5365 const Rectangle aRA(aPixelRects[a]); 5366 basegfx::B2DRange aRB(aRA.Left(), aRA.Top(), aRA.Right() + 1, aRA.Bottom() + 1); 5367 aRB.transform(aTransform); 5368 aRanges.push_back(aRB); 5369 } 5370 5371 sdr::overlay::OverlayObject* pOverlay = new sdr::overlay::OverlaySelection( 5372 sdr::overlay::OVERLAY_SOLID, 5373 aCursorColor, 5374 aRanges, 5375 false); 5376 5377 pOverlayManager->add(*pOverlay); 5378 mpOOCursors = new ::sdr::overlay::OverlayObjectList; 5379 mpOOCursors->append(*pOverlay); 5380 } 5381 } 5382 5383 if ( aOldMode != aDrawMode ) 5384 SetMapMode( aOldMode ); 5385 } 5386 5387 void ScGridWindow::DeleteSelectionOverlay() 5388 { 5389 DELETEZ( mpOOSelection ); 5390 } 5391 5392 void ScGridWindow::UpdateSelectionOverlay() 5393 { 5394 MapMode aDrawMode = GetDrawMapMode(); 5395 MapMode aOldMode = GetMapMode(); 5396 if ( aOldMode != aDrawMode ) 5397 SetMapMode( aDrawMode ); 5398 5399 DeleteSelectionOverlay(); 5400 std::vector<Rectangle> aPixelRects; 5401 GetSelectionRects( aPixelRects ); 5402 5403 if ( aPixelRects.size() && pViewData->IsActive() ) 5404 { 5405 // #i70788# get the OverlayManager safely 5406 ::sdr::overlay::OverlayManager* pOverlayManager = getOverlayManager(); 5407 5408 if(pOverlayManager) 5409 { 5410 std::vector< basegfx::B2DRange > aRanges; 5411 const basegfx::B2DHomMatrix aTransform(GetInverseViewTransformation()); 5412 5413 for(sal_uInt32 a(0); a < aPixelRects.size(); a++) 5414 { 5415 const Rectangle aRA(aPixelRects[a]); 5416 basegfx::B2DRange aRB(aRA.Left() - 1, aRA.Top() - 1, aRA.Right(), aRA.Bottom()); 5417 aRB.transform(aTransform); 5418 aRanges.push_back(aRB); 5419 } 5420 5421 // get the system's hilight color 5422 const SvtOptionsDrawinglayer aSvtOptionsDrawinglayer; 5423 const Color aHighlight(aSvtOptionsDrawinglayer.getHilightColor()); 5424 5425 sdr::overlay::OverlayObject* pOverlay = new sdr::overlay::OverlaySelection( 5426 sdr::overlay::OVERLAY_TRANSPARENT, 5427 aHighlight, 5428 aRanges, 5429 true); 5430 5431 pOverlayManager->add(*pOverlay); 5432 mpOOSelection = new ::sdr::overlay::OverlayObjectList; 5433 mpOOSelection->append(*pOverlay); 5434 } 5435 } 5436 5437 if ( aOldMode != aDrawMode ) 5438 SetMapMode( aOldMode ); 5439 } 5440 5441 void ScGridWindow::DeleteAutoFillOverlay() 5442 { 5443 DELETEZ( mpOOAutoFill ); 5444 mpAutoFillRect.reset(); 5445 } 5446 5447 void ScGridWindow::UpdateAutoFillOverlay() 5448 { 5449 MapMode aDrawMode = GetDrawMapMode(); 5450 MapMode aOldMode = GetMapMode(); 5451 if ( aOldMode != aDrawMode ) 5452 SetMapMode( aDrawMode ); 5453 5454 DeleteAutoFillOverlay(); 5455 5456 // 5457 // get the AutoFill handle rectangle in pixels (moved from ScGridWindow::DrawAutoFillMark) 5458 // 5459 5460 if ( bAutoMarkVisible && aAutoMarkPos.Tab() == pViewData->GetTabNo() && 5461 !pViewData->HasEditView(eWhich) && pViewData->IsActive() ) 5462 { 5463 SCCOL nX = aAutoMarkPos.Col(); 5464 SCROW nY = aAutoMarkPos.Row(); 5465 5466 if (!maVisibleRange.isInside(nX, nY)) 5467 // Autofill mark is not visible. Bail out. 5468 return; 5469 5470 SCTAB nTab = pViewData->GetTabNo(); 5471 ScDocument* pDoc = pViewData->GetDocument(); 5472 sal_Bool bLayoutRTL = pDoc->IsLayoutRTL( nTab ); 5473 5474 Point aFillPos = pViewData->GetScrPos( nX, nY, eWhich, sal_True ); 5475 long nSizeXPix; 5476 long nSizeYPix; 5477 pViewData->GetMergeSizePixel( nX, nY, nSizeXPix, nSizeYPix ); 5478 if ( bLayoutRTL ) 5479 aFillPos.X() -= nSizeXPix + 3; 5480 else 5481 aFillPos.X() += nSizeXPix - 2; 5482 5483 aFillPos.Y() += nSizeYPix; 5484 aFillPos.Y() -= 2; 5485 mpAutoFillRect.reset(new Rectangle(aFillPos, Size(6, 6))); 5486 5487 // #i70788# get the OverlayManager safely 5488 ::sdr::overlay::OverlayManager* pOverlayManager = getOverlayManager(); 5489 5490 if(pOverlayManager) 5491 { 5492 const Color aHandleColor( SC_MOD()->GetColorConfig().GetColorValue(svtools::FONTCOLOR).nColor ); 5493 std::vector< basegfx::B2DRange > aRanges; 5494 const basegfx::B2DHomMatrix aTransform(GetInverseViewTransformation()); 5495 basegfx::B2DRange aRB(mpAutoFillRect->Left(), mpAutoFillRect->Top(), mpAutoFillRect->Right() + 1, mpAutoFillRect->Bottom() + 1); 5496 5497 aRB.transform(aTransform); 5498 aRanges.push_back(aRB); 5499 5500 sdr::overlay::OverlayObject* pOverlay = new sdr::overlay::OverlaySelection( 5501 sdr::overlay::OVERLAY_SOLID, 5502 aHandleColor, 5503 aRanges, 5504 false); 5505 5506 pOverlayManager->add(*pOverlay); 5507 mpOOAutoFill = new ::sdr::overlay::OverlayObjectList; 5508 mpOOAutoFill->append(*pOverlay); 5509 } 5510 5511 if ( aOldMode != aDrawMode ) 5512 SetMapMode( aOldMode ); 5513 } 5514 } 5515 5516 void ScGridWindow::DeleteDragRectOverlay() 5517 { 5518 DELETEZ( mpOODragRect ); 5519 } 5520 5521 void ScGridWindow::UpdateDragRectOverlay() 5522 { 5523 MapMode aDrawMode = GetDrawMapMode(); 5524 MapMode aOldMode = GetMapMode(); 5525 if ( aOldMode != aDrawMode ) 5526 SetMapMode( aDrawMode ); 5527 5528 DeleteDragRectOverlay(); 5529 5530 // 5531 // get the rectangles in pixels (moved from DrawDragRect) 5532 // 5533 5534 if ( bDragRect || bPagebreakDrawn ) 5535 { 5536 std::vector<Rectangle> aPixelRects; 5537 5538 SCCOL nX1 = bDragRect ? nDragStartX : aPagebreakDrag.aStart.Col(); 5539 SCROW nY1 = bDragRect ? nDragStartY : aPagebreakDrag.aStart.Row(); 5540 SCCOL nX2 = bDragRect ? nDragEndX : aPagebreakDrag.aEnd.Col(); 5541 SCROW nY2 = bDragRect ? nDragEndY : aPagebreakDrag.aEnd.Row(); 5542 5543 SCTAB nTab = pViewData->GetTabNo(); 5544 5545 SCCOL nPosX = pViewData->GetPosX(WhichH(eWhich)); 5546 SCROW nPosY = pViewData->GetPosY(WhichV(eWhich)); 5547 if (nX1 < nPosX) nX1 = nPosX; 5548 if (nX2 < nPosX) nX2 = nPosX; 5549 if (nY1 < nPosY) nY1 = nPosY; 5550 if (nY2 < nPosY) nY2 = nPosY; 5551 5552 Point aScrPos( pViewData->GetScrPos( nX1, nY1, eWhich ) ); 5553 5554 long nSizeXPix=0; 5555 long nSizeYPix=0; 5556 ScDocument* pDoc = pViewData->GetDocument(); 5557 double nPPTX = pViewData->GetPPTX(); 5558 double nPPTY = pViewData->GetPPTY(); 5559 SCCOLROW i; 5560 5561 sal_Bool bLayoutRTL = pDoc->IsLayoutRTL( nTab ); 5562 long nLayoutSign = bLayoutRTL ? -1 : 1; 5563 5564 if (ValidCol(nX2) && nX2>=nX1) 5565 for (i=nX1; i<=nX2; i++) 5566 nSizeXPix += ScViewData::ToPixel( pDoc->GetColWidth( static_cast<SCCOL>(i), nTab ), nPPTX ); 5567 else 5568 { 5569 aScrPos.X() -= nLayoutSign; 5570 nSizeXPix += 2; 5571 } 5572 5573 if (ValidRow(nY2) && nY2>=nY1) 5574 for (i=nY1; i<=nY2; i++) 5575 nSizeYPix += ScViewData::ToPixel( pDoc->GetRowHeight( i, nTab ), nPPTY ); 5576 else 5577 { 5578 aScrPos.Y() -= 1; 5579 nSizeYPix += 2; 5580 } 5581 5582 aScrPos.X() -= 2 * nLayoutSign; 5583 aScrPos.Y() -= 2; 5584 // Rectangle aRect( aScrPos, Size( nSizeXPix + 3, nSizeYPix + 3 ) ); 5585 Rectangle aRect( aScrPos.X(), aScrPos.Y(), 5586 aScrPos.X() + ( nSizeXPix + 2 ) * nLayoutSign, aScrPos.Y() + nSizeYPix + 2 ); 5587 if ( bLayoutRTL ) 5588 { 5589 aRect.Left() = aRect.Right(); // end position is left 5590 aRect.Right() = aScrPos.X(); 5591 } 5592 5593 if ( meDragInsertMode == INS_CELLSDOWN ) 5594 { 5595 aPixelRects.push_back( Rectangle( aRect.Left()+1, aRect.Top()+3, aRect.Left()+1, aRect.Bottom()-2 ) ); 5596 aPixelRects.push_back( Rectangle( aRect.Right()-1, aRect.Top()+3, aRect.Right()-1, aRect.Bottom()-2 ) ); 5597 aPixelRects.push_back( Rectangle( aRect.Left()+1, aRect.Top(), aRect.Right()-1, aRect.Top()+2 ) ); 5598 aPixelRects.push_back( Rectangle( aRect.Left()+1, aRect.Bottom()-1, aRect.Right()-1, aRect.Bottom()-1 ) ); 5599 } 5600 else if ( meDragInsertMode == INS_CELLSRIGHT ) 5601 { 5602 aPixelRects.push_back( Rectangle( aRect.Left(), aRect.Top()+1, aRect.Left()+2, aRect.Bottom()-1 ) ); 5603 aPixelRects.push_back( Rectangle( aRect.Right()-1, aRect.Top()+1, aRect.Right()-1, aRect.Bottom()-1 ) ); 5604 aPixelRects.push_back( Rectangle( aRect.Left()+3, aRect.Top()+1, aRect.Right()-2, aRect.Top()+1 ) ); 5605 aPixelRects.push_back( Rectangle( aRect.Left()+3, aRect.Bottom()-1, aRect.Right()-2, aRect.Bottom()-1 ) ); 5606 } 5607 else 5608 { 5609 aPixelRects.push_back( Rectangle( aRect.Left(), aRect.Top(), aRect.Left()+2, aRect.Bottom() ) ); 5610 aPixelRects.push_back( Rectangle( aRect.Right()-2, aRect.Top(), aRect.Right(), aRect.Bottom() ) ); 5611 aPixelRects.push_back( Rectangle( aRect.Left()+3, aRect.Top(), aRect.Right()-3, aRect.Top()+2 ) ); 5612 aPixelRects.push_back( Rectangle( aRect.Left()+3, aRect.Bottom()-2, aRect.Right()-3, aRect.Bottom() ) ); 5613 } 5614 5615 // #i70788# get the OverlayManager safely 5616 ::sdr::overlay::OverlayManager* pOverlayManager = getOverlayManager(); 5617 5618 if(pOverlayManager) 5619 { 5620 // Color aHighlight = GetSettings().GetStyleSettings().GetHighlightColor(); 5621 std::vector< basegfx::B2DRange > aRanges; 5622 const basegfx::B2DHomMatrix aTransform(GetInverseViewTransformation()); 5623 5624 for(sal_uInt32 a(0); a < aPixelRects.size(); a++) 5625 { 5626 const Rectangle aRA(aPixelRects[a]); 5627 basegfx::B2DRange aRB(aRA.Left(), aRA.Top(), aRA.Right() + 1, aRA.Bottom() + 1); 5628 aRB.transform(aTransform); 5629 aRanges.push_back(aRB); 5630 } 5631 5632 sdr::overlay::OverlayObject* pOverlay = new sdr::overlay::OverlaySelection( 5633 sdr::overlay::OVERLAY_INVERT, 5634 Color(COL_BLACK), 5635 aRanges, 5636 false); 5637 5638 pOverlayManager->add(*pOverlay); 5639 mpOODragRect = new ::sdr::overlay::OverlayObjectList; 5640 mpOODragRect->append(*pOverlay); 5641 } 5642 } 5643 5644 if ( aOldMode != aDrawMode ) 5645 SetMapMode( aOldMode ); 5646 } 5647 5648 void ScGridWindow::DeleteHeaderOverlay() 5649 { 5650 DELETEZ( mpOOHeader ); 5651 } 5652 5653 void ScGridWindow::UpdateHeaderOverlay() 5654 { 5655 MapMode aDrawMode = GetDrawMapMode(); 5656 MapMode aOldMode = GetMapMode(); 5657 if ( aOldMode != aDrawMode ) 5658 SetMapMode( aDrawMode ); 5659 5660 DeleteHeaderOverlay(); 5661 5662 // Pixel rectangle is in aInvertRect 5663 if ( !aInvertRect.IsEmpty() ) 5664 { 5665 // #i70788# get the OverlayManager safely 5666 ::sdr::overlay::OverlayManager* pOverlayManager = getOverlayManager(); 5667 5668 if(pOverlayManager) 5669 { 5670 // Color aHighlight = GetSettings().GetStyleSettings().GetHighlightColor(); 5671 std::vector< basegfx::B2DRange > aRanges; 5672 const basegfx::B2DHomMatrix aTransform(GetInverseViewTransformation()); 5673 basegfx::B2DRange aRB(aInvertRect.Left(), aInvertRect.Top(), aInvertRect.Right() + 1, aInvertRect.Bottom() + 1); 5674 5675 aRB.transform(aTransform); 5676 aRanges.push_back(aRB); 5677 5678 sdr::overlay::OverlayObject* pOverlay = new sdr::overlay::OverlaySelection( 5679 sdr::overlay::OVERLAY_INVERT, 5680 Color(COL_BLACK), 5681 aRanges, 5682 false); 5683 5684 pOverlayManager->add(*pOverlay); 5685 mpOOHeader = new ::sdr::overlay::OverlayObjectList; 5686 mpOOHeader->append(*pOverlay); 5687 } 5688 } 5689 5690 if ( aOldMode != aDrawMode ) 5691 SetMapMode( aOldMode ); 5692 } 5693 5694 void ScGridWindow::DeleteShrinkOverlay() 5695 { 5696 DELETEZ( mpOOShrink ); 5697 } 5698 5699 void ScGridWindow::UpdateShrinkOverlay() 5700 { 5701 MapMode aDrawMode = GetDrawMapMode(); 5702 MapMode aOldMode = GetMapMode(); 5703 if ( aOldMode != aDrawMode ) 5704 SetMapMode( aDrawMode ); 5705 5706 DeleteShrinkOverlay(); 5707 5708 // 5709 // get the rectangle in pixels 5710 // 5711 5712 Rectangle aPixRect; 5713 ScRange aRange; 5714 SCTAB nTab = pViewData->GetTabNo(); 5715 if ( pViewData->IsRefMode() && nTab >= pViewData->GetRefStartZ() && nTab <= pViewData->GetRefEndZ() && 5716 pViewData->GetDelMark( aRange ) ) 5717 { 5718 //! limit to visible area 5719 if ( aRange.aStart.Col() <= aRange.aEnd.Col() && 5720 aRange.aStart.Row() <= aRange.aEnd.Row() ) 5721 { 5722 Point aStart = pViewData->GetScrPos( aRange.aStart.Col(), 5723 aRange.aStart.Row(), eWhich ); 5724 Point aEnd = pViewData->GetScrPos( aRange.aEnd.Col()+1, 5725 aRange.aEnd.Row()+1, eWhich ); 5726 aEnd.X() -= 1; 5727 aEnd.Y() -= 1; 5728 5729 aPixRect = Rectangle( aStart,aEnd ); 5730 } 5731 } 5732 5733 if ( !aPixRect.IsEmpty() ) 5734 { 5735 // #i70788# get the OverlayManager safely 5736 ::sdr::overlay::OverlayManager* pOverlayManager = getOverlayManager(); 5737 5738 if(pOverlayManager) 5739 { 5740 // Color aHighlight = GetSettings().GetStyleSettings().GetHighlightColor(); 5741 std::vector< basegfx::B2DRange > aRanges; 5742 const basegfx::B2DHomMatrix aTransform(GetInverseViewTransformation()); 5743 basegfx::B2DRange aRB(aPixRect.Left(), aPixRect.Top(), aPixRect.Right() + 1, aPixRect.Bottom() + 1); 5744 5745 aRB.transform(aTransform); 5746 aRanges.push_back(aRB); 5747 5748 sdr::overlay::OverlayObject* pOverlay = new sdr::overlay::OverlaySelection( 5749 sdr::overlay::OVERLAY_INVERT, 5750 Color(COL_BLACK), 5751 aRanges, 5752 false); 5753 5754 pOverlayManager->add(*pOverlay); 5755 mpOOShrink = new ::sdr::overlay::OverlayObjectList; 5756 mpOOShrink->append(*pOverlay); 5757 } 5758 } 5759 5760 if ( aOldMode != aDrawMode ) 5761 SetMapMode( aOldMode ); 5762 } 5763 5764 // #i70788# central method to get the OverlayManager safely 5765 ::sdr::overlay::OverlayManager* ScGridWindow::getOverlayManager() 5766 { 5767 SdrPageView* pPV = pViewData->GetView()->GetScDrawView()->GetSdrPageView(); 5768 5769 if(pPV) 5770 { 5771 SdrPageWindow* pPageWin = pPV->FindPageWindow( *this ); 5772 5773 if ( pPageWin ) 5774 { 5775 return (pPageWin->GetOverlayManager()); 5776 } 5777 } 5778 5779 return 0L; 5780 } 5781 5782 void ScGridWindow::flushOverlayManager() 5783 { 5784 // #i70788# get the OverlayManager safely 5785 ::sdr::overlay::OverlayManager* pOverlayManager = getOverlayManager(); 5786 5787 if(pOverlayManager) 5788 { 5789 pOverlayManager->flush(); 5790 } 5791 } 5792 5793 // --------------------------------------------------------------------------- 5794 // eof 5795