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