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