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 28 29 // INCLUDE --------------------------------------------------------------- 30 31 #include "scitems.hxx" 32 #include <vcl/msgbox.hxx> 33 #include <vcl/sound.hxx> 34 35 #include "gridwin.hxx" 36 #include "tabvwsh.hxx" 37 #include "docsh.hxx" 38 #include "viewdata.hxx" 39 #include "pivot.hxx" 40 //CHINA001 #include "pfiltdlg.hxx" 41 #include "uiitems.hxx" 42 #include "scresid.hxx" 43 #include "sc.hrc" 44 #include "globstr.hrc" 45 #include "pagedata.hxx" 46 #include "dpobject.hxx" 47 #include "dpsave.hxx" 48 #include "dpoutput.hxx" // ScDPPositionData 49 #include "dpshttab.hxx" 50 #include "dbdocfun.hxx" 51 #include "dpcontrol.hxx" 52 #include "dpcontrol.hrc" 53 #include "strload.hxx" 54 #include "userlist.hxx" 55 56 #include <com/sun/star/sheet/DataPilotFieldOrientation.hpp> 57 #include "scabstdlg.hxx" //CHINA001 58 59 #include <vector> 60 #include <hash_map> 61 62 using namespace com::sun::star; 63 using ::com::sun::star::sheet::DataPilotFieldOrientation; 64 using ::std::vector; 65 using ::std::auto_ptr; 66 using ::std::hash_map; 67 using ::rtl::OUString; 68 using ::rtl::OUStringHash; 69 70 // STATIC DATA ----------------------------------------------------------- 71 72 // ----------------------------------------------------------------------- 73 74 DataPilotFieldOrientation ScGridWindow::GetDPFieldOrientation( SCCOL nCol, SCROW nRow ) const 75 { 76 using namespace ::com::sun::star::sheet; 77 78 ScDocument* pDoc = pViewData->GetDocument(); 79 SCTAB nTab = pViewData->GetTabNo(); 80 ScDPObject* pDPObj = pDoc->GetDPAtCursor(nCol, nRow, nTab); 81 if (!pDPObj) 82 return DataPilotFieldOrientation_HIDDEN; 83 84 sal_uInt16 nOrient = DataPilotFieldOrientation_HIDDEN; 85 86 // Check for page field first. 87 if (nCol > 0) 88 { 89 // look for the dimension header left of the drop-down arrow 90 long nField = pDPObj->GetHeaderDim( ScAddress( nCol-1, nRow, nTab ), nOrient ); 91 if ( nField >= 0 && nOrient == DataPilotFieldOrientation_PAGE ) 92 { 93 sal_Bool bIsDataLayout = sal_False; 94 String aFieldName = pDPObj->GetDimName( nField, bIsDataLayout ); 95 if ( aFieldName.Len() && !bIsDataLayout ) 96 return DataPilotFieldOrientation_PAGE; 97 } 98 } 99 100 nOrient = sheet::DataPilotFieldOrientation_HIDDEN; 101 102 // Now, check for row/column field. 103 long nField = pDPObj->GetHeaderDim(ScAddress(nCol, nRow, nTab), nOrient); 104 if (nField >= 0 && (nOrient == DataPilotFieldOrientation_COLUMN || nOrient == DataPilotFieldOrientation_ROW) ) 105 { 106 sal_Bool bIsDataLayout = sal_False; 107 String aFieldName = pDPObj->GetDimName(nField, bIsDataLayout); 108 if (aFieldName.Len() && !bIsDataLayout) 109 return static_cast<DataPilotFieldOrientation>(nOrient); 110 } 111 112 return DataPilotFieldOrientation_HIDDEN; 113 } 114 115 // private method for mouse button handling 116 sal_Bool ScGridWindow::DoPageFieldSelection( SCCOL nCol, SCROW nRow ) 117 { 118 if (GetDPFieldOrientation( nCol, nRow ) == sheet::DataPilotFieldOrientation_PAGE) 119 { 120 LaunchPageFieldMenu( nCol, nRow ); 121 return sal_True; 122 } 123 return sal_False; 124 } 125 126 bool ScGridWindow::DoAutoFilterButton( SCCOL nCol, SCROW nRow, const MouseEvent& rMEvt ) 127 { 128 ScDocument* pDoc = pViewData->GetDocument(); 129 SCTAB nTab = pViewData->GetTabNo(); 130 Point aScrPos = pViewData->GetScrPos(nCol, nRow, eWhich); 131 Point aDiffPix = rMEvt.GetPosPixel(); 132 133 aDiffPix -= aScrPos; 134 sal_Bool bLayoutRTL = pDoc->IsLayoutRTL( nTab ); 135 if ( bLayoutRTL ) 136 aDiffPix.X() = -aDiffPix.X(); 137 138 long nSizeX, nSizeY; 139 pViewData->GetMergeSizePixel( nCol, nRow, nSizeX, nSizeY ); 140 // The button height should not use the merged cell height, should still use single row height 141 nSizeY = pViewData->ToPixel(pDoc->GetRowHeight(nRow, nTab), pViewData->GetPPTY()); 142 Size aScrSize(nSizeX-1, nSizeY-1); 143 144 // Check if the mouse cursor is clicking on the popup arrow box. 145 mpFilterButton.reset(new ScDPFieldButton(this, &GetSettings().GetStyleSettings(), &pViewData->GetZoomX(), &pViewData->GetZoomY(), pDoc)); 146 mpFilterButton->setBoundingBox(aScrPos, aScrSize, bLayoutRTL); 147 mpFilterButton->setPopupLeft(bLayoutRTL); // #i114944# AutoFilter button is left-aligned in RTL 148 Point aPopupPos; 149 Size aPopupSize; 150 mpFilterButton->getPopupBoundingBox(aPopupPos, aPopupSize); 151 Rectangle aRec(aPopupPos, aPopupSize); 152 if (aRec.IsInside(rMEvt.GetPosPixel())) 153 { 154 if ( DoPageFieldSelection( nCol, nRow ) ) 155 return true; 156 157 bool bFilterActive = IsAutoFilterActive(nCol, nRow, nTab); 158 mpFilterButton->setHasHiddenMember(bFilterActive); 159 mpFilterButton->setDrawBaseButton(false); 160 mpFilterButton->setDrawPopupButton(true); 161 mpFilterButton->setPopupPressed(true); 162 HideCursor(); 163 mpFilterButton->draw(); 164 ShowCursor(); 165 DoAutoFilterMenue(nCol, nRow, false); 166 return true; 167 } 168 169 return false; 170 } 171 172 void ScGridWindow::DoPushButton( SCCOL nCol, SCROW nRow, const MouseEvent& rMEvt ) 173 { 174 ScDocument* pDoc = pViewData->GetDocument(); 175 SCTAB nTab = pViewData->GetTabNo(); 176 177 ScDPObject* pDPObj = pDoc->GetDPAtCursor(nCol, nRow, nTab); 178 179 if (pDPObj) 180 { 181 sal_uInt16 nOrient = sheet::DataPilotFieldOrientation_HIDDEN; 182 ScAddress aPos( nCol, nRow, nTab ); 183 long nField = pDPObj->GetHeaderDim( aPos, nOrient ); 184 if ( nField >= 0 ) 185 { 186 bDPMouse = sal_True; 187 nDPField = nField; 188 pDragDPObj = pDPObj; 189 190 if (DPTestFieldPopupArrow(rMEvt, aPos, pDPObj)) 191 { 192 // field name pop up menu has been launched. Don't activate 193 // field move. 194 bDPMouse = false; 195 return; 196 } 197 198 DPTestMouse( rMEvt, sal_True ); 199 StartTracking(); 200 } 201 else if ( pDPObj->IsFilterButton(aPos) ) 202 { 203 ReleaseMouse(); // may have been captured in ButtonDown 204 205 ScQueryParam aQueryParam; 206 SCTAB nSrcTab = 0; 207 const ScSheetSourceDesc* pDesc = pDPObj->GetSheetDesc(); 208 DBG_ASSERT(pDesc, "no sheet source for filter button"); 209 if (pDesc) 210 { 211 aQueryParam = pDesc->aQueryParam; 212 nSrcTab = pDesc->aSourceRange.aStart.Tab(); 213 } 214 215 SfxItemSet aArgSet( pViewData->GetViewShell()->GetPool(), 216 SCITEM_QUERYDATA, SCITEM_QUERYDATA ); 217 aArgSet.Put( ScQueryItem( SCITEM_QUERYDATA, pViewData, &aQueryParam ) ); 218 219 //CHINA001 ScPivotFilterDlg* pDlg = new ScPivotFilterDlg( 220 //CHINA001 pViewData->GetViewShell()->GetDialogParent(), 221 //CHINA001 aArgSet, nSrcTab ); 222 ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create(); 223 DBG_ASSERT(pFact, "ScAbstractFactory create fail!");//CHINA001 224 225 AbstractScPivotFilterDlg* pDlg = pFact->CreateScPivotFilterDlg( pViewData->GetViewShell()->GetDialogParent(), 226 aArgSet, nSrcTab, 227 RID_SCDLG_PIVOTFILTER); 228 DBG_ASSERT(pDlg, "Dialog create fail!");//CHINA001 229 if ( pDlg->Execute() == RET_OK ) 230 { 231 ScSheetSourceDesc aNewDesc; 232 if (pDesc) 233 aNewDesc = *pDesc; 234 235 const ScQueryItem& rQueryItem = pDlg->GetOutputItem(); 236 aNewDesc.aQueryParam = rQueryItem.GetQueryData(); 237 238 ScDPObject aNewObj( *pDPObj ); 239 aNewObj.SetSheetDesc( aNewDesc ); 240 ScDBDocFunc aFunc( *pViewData->GetDocShell() ); 241 aFunc.DataPilotUpdate( pDPObj, &aNewObj, sal_True, sal_False ); 242 pViewData->GetView()->CursorPosChanged(); // shells may be switched 243 } 244 delete pDlg; 245 } 246 else 247 Sound::Beep(); 248 } 249 else 250 { 251 DBG_ERROR("Da is ja garnix"); 252 } 253 } 254 255 // ----------------------------------------------------------------------- 256 // 257 // Data Pilot interaction 258 // 259 260 void ScGridWindow::DPTestMouse( const MouseEvent& rMEvt, sal_Bool bMove ) 261 { 262 DBG_ASSERT(pDragDPObj, "pDragDPObj missing"); 263 264 // scroll window if at edges 265 //! move this to separate method 266 267 sal_Bool bTimer = sal_False; 268 Point aPixel = rMEvt.GetPosPixel(); 269 270 SCsCOL nDx = 0; 271 SCsROW nDy = 0; 272 if ( aPixel.X() < 0 ) 273 nDx = -1; 274 if ( aPixel.Y() < 0 ) 275 nDy = -1; 276 Size aSize = GetOutputSizePixel(); 277 if ( aPixel.X() >= aSize.Width() ) 278 nDx = 1; 279 if ( aPixel.Y() >= aSize.Height() ) 280 nDy = 1; 281 if ( nDx != 0 || nDy != 0 ) 282 { 283 UpdateDragRect( sal_False, Rectangle() ); 284 285 if ( nDx != 0) 286 pViewData->GetView()->ScrollX( nDx, WhichH(eWhich) ); 287 if ( nDy != 0 ) 288 pViewData->GetView()->ScrollY( nDy, WhichV(eWhich) ); 289 290 bTimer = sal_True; 291 } 292 293 // --- 294 295 SCsCOL nPosX; 296 SCsROW nPosY; 297 pViewData->GetPosFromPixel( aPixel.X(), aPixel.Y(), eWhich, nPosX, nPosY ); 298 sal_Bool bMouseLeft; 299 sal_Bool bMouseTop; 300 pViewData->GetMouseQuadrant( aPixel, eWhich, nPosX, nPosY, bMouseLeft, bMouseTop ); 301 302 ScAddress aPos( nPosX, nPosY, pViewData->GetTabNo() ); 303 304 Rectangle aPosRect; 305 sal_uInt16 nOrient; 306 long nDimPos; 307 sal_Bool bHasRange = pDragDPObj->GetHeaderDrag( aPos, bMouseLeft, bMouseTop, nDPField, 308 aPosRect, nOrient, nDimPos ); 309 UpdateDragRect( bHasRange && bMove, aPosRect ); 310 311 sal_Bool bIsDataLayout; 312 sal_Int32 nDimFlags = 0; 313 String aDimName = pDragDPObj->GetDimName( nDPField, bIsDataLayout, &nDimFlags ); 314 bool bAllowed = !bHasRange || ScDPObject::IsOrientationAllowed( nOrient, nDimFlags ); 315 316 if (bMove) // set mouse pointer 317 { 318 PointerStyle ePointer = POINTER_PIVOT_DELETE; 319 if ( !bAllowed ) 320 ePointer = POINTER_NOTALLOWED; 321 else if ( bHasRange ) 322 switch (nOrient) 323 { 324 case sheet::DataPilotFieldOrientation_COLUMN: ePointer = POINTER_PIVOT_COL; break; 325 case sheet::DataPilotFieldOrientation_ROW: ePointer = POINTER_PIVOT_ROW; break; 326 case sheet::DataPilotFieldOrientation_PAGE: 327 case sheet::DataPilotFieldOrientation_DATA: ePointer = POINTER_PIVOT_FIELD; break; 328 } 329 SetPointer( ePointer ); 330 } 331 else // execute change 332 { 333 if (!bHasRange) 334 nOrient = sheet::DataPilotFieldOrientation_HIDDEN; 335 336 if ( bIsDataLayout && ( nOrient != sheet::DataPilotFieldOrientation_COLUMN && 337 nOrient != sheet::DataPilotFieldOrientation_ROW ) ) 338 { 339 // removing data layout is not allowed 340 pViewData->GetView()->ErrorMessage(STR_PIVOT_MOVENOTALLOWED); 341 } 342 else if ( bAllowed ) 343 { 344 ScDPSaveData aSaveData( *pDragDPObj->GetSaveData() ); 345 346 ScDPSaveDimension* pDim; 347 if ( bIsDataLayout ) 348 pDim = aSaveData.GetDataLayoutDimension(); 349 else 350 pDim = aSaveData.GetDimensionByName(aDimName); 351 pDim->SetOrientation( nOrient ); 352 aSaveData.SetPosition( pDim, nDimPos ); 353 354 //! docfunc method with ScDPSaveData as argument? 355 356 ScDPObject aNewObj( *pDragDPObj ); 357 aNewObj.SetSaveData( aSaveData ); 358 ScDBDocFunc aFunc( *pViewData->GetDocShell() ); 359 // when dragging fields, allow re-positioning (bAllowMove) 360 aFunc.DataPilotUpdate( pDragDPObj, &aNewObj, sal_True, sal_False, sal_True ); 361 pViewData->GetView()->CursorPosChanged(); // shells may be switched 362 } 363 } 364 365 if (bTimer && bMove) 366 pViewData->GetView()->SetTimer( this, rMEvt ); // repeat event 367 else 368 pViewData->GetView()->ResetTimer(); 369 } 370 371 bool ScGridWindow::DPTestFieldPopupArrow(const MouseEvent& rMEvt, const ScAddress& rPos, ScDPObject* pDPObj) 372 { 373 sal_Bool bLayoutRTL = pViewData->GetDocument()->IsLayoutRTL( pViewData->GetTabNo() ); 374 375 // Get the geometry of the cell. 376 Point aScrPos = pViewData->GetScrPos(rPos.Col(), rPos.Row(), eWhich); 377 long nSizeX, nSizeY; 378 pViewData->GetMergeSizePixel(rPos.Col(), rPos.Row(), nSizeX, nSizeY); 379 Size aScrSize(nSizeX-1, nSizeY-1); 380 381 // Check if the mouse cursor is clicking on the popup arrow box. 382 ScDPFieldButton aBtn(this, &GetSettings().GetStyleSettings()); 383 aBtn.setBoundingBox(aScrPos, aScrSize, bLayoutRTL); 384 aBtn.setPopupLeft(false); // DataPilot popup is always right-aligned for now 385 Point aPopupPos; 386 Size aPopupSize; 387 aBtn.getPopupBoundingBox(aPopupPos, aPopupSize); 388 Rectangle aRec(aPopupPos, aPopupSize); 389 if (aRec.IsInside(rMEvt.GetPosPixel())) 390 { 391 // Mouse cursor inside the popup arrow box. Launch the field menu. 392 DPLaunchFieldPopupMenu(OutputToScreenPixel(aScrPos), aScrSize, rPos, pDPObj); 393 return true; 394 } 395 396 return false; 397 } 398 399 namespace { 400 401 struct DPFieldPopupData : public ScDPFieldPopupWindow::ExtendedData 402 { 403 ScPivotParam maDPParam; 404 ScDPObject* mpDPObj; 405 long mnDim; 406 }; 407 408 class DPFieldPopupOKAction : public ScMenuFloatingWindow::Action 409 { 410 public: 411 explicit DPFieldPopupOKAction(ScGridWindow* p) : 412 mpGridWindow(p) {} 413 414 virtual void execute() 415 { 416 mpGridWindow->UpdateDPFromFieldPopupMenu(); 417 } 418 private: 419 ScGridWindow* mpGridWindow; 420 }; 421 422 class PopupSortAction : public ScMenuFloatingWindow::Action 423 { 424 public: 425 enum SortType { ASCENDING, DESCENDING, CUSTOM }; 426 427 explicit PopupSortAction(const ScAddress& rPos, SortType eType, sal_uInt16 nUserListIndex, ScTabViewShell* pViewShell) : 428 maPos(rPos), meType(eType), mnUserListIndex(nUserListIndex), mpViewShell(pViewShell) {} 429 430 virtual void execute() 431 { 432 switch (meType) 433 { 434 case ASCENDING: 435 mpViewShell->DataPilotSort(maPos, true); 436 break; 437 case DESCENDING: 438 mpViewShell->DataPilotSort(maPos, false); 439 break; 440 case CUSTOM: 441 mpViewShell->DataPilotSort(maPos, true, &mnUserListIndex); 442 break; 443 default: 444 ; 445 } 446 } 447 448 private: 449 ScAddress maPos; 450 SortType meType; 451 sal_uInt16 mnUserListIndex; 452 ScTabViewShell* mpViewShell; 453 }; 454 455 } 456 457 bool lcl_GetLabelIndex( size_t& rLabelIndex, long nDimension, const ScDPLabelDataVector& rLabelArray ) 458 { 459 size_t n = rLabelArray.size(); 460 for (size_t i = 0; i < n; ++i) 461 if (static_cast<long>(rLabelArray[i].mnCol) == nDimension) 462 { 463 rLabelIndex = i; 464 return true; 465 } 466 return false; 467 } 468 469 void ScGridWindow::DPLaunchFieldPopupMenu( 470 const Point& rScrPos, const Size& rScrSize, const ScAddress& rPos, ScDPObject* pDPObj) 471 { 472 // We need to get the list of field members. 473 auto_ptr<DPFieldPopupData> pDPData(new DPFieldPopupData); 474 pDPObj->FillLabelData(pDPData->maDPParam); 475 pDPData->mpDPObj = pDPObj; 476 477 sal_uInt16 nOrient; 478 pDPData->mnDim = pDPObj->GetHeaderDim(rPos, nOrient); 479 480 // #i116457# FillLabelData skips empty column names, so mnDim can't be used directly as index into maLabelArray. 481 size_t nLabelIndex = 0; 482 if (!lcl_GetLabelIndex( nLabelIndex, pDPData->mnDim, pDPData->maDPParam.maLabelArray )) 483 return; 484 485 const ScDPLabelData& rLabelData = pDPData->maDPParam.maLabelArray[nLabelIndex]; 486 487 mpDPFieldPopup.reset(new ScDPFieldPopupWindow(this, pViewData->GetDocument())); 488 mpDPFieldPopup->setName(OUString::createFromAscii("Pivot table field member popup")); 489 mpDPFieldPopup->setExtendedData(pDPData.release()); 490 mpDPFieldPopup->setOKAction(new DPFieldPopupOKAction(this)); 491 { 492 // Populate field members. 493 size_t n = rLabelData.maMembers.size(); 494 mpDPFieldPopup->setMemberSize(n); 495 for (size_t i = 0; i < n; ++i) 496 { 497 const ScDPLabelData::Member& rMem = rLabelData.maMembers[i]; 498 mpDPFieldPopup->addMember(rMem.getDisplayName(), rMem.mbVisible); 499 } 500 mpDPFieldPopup->initMembers(); 501 } 502 503 vector<OUString> aUserSortNames; 504 ScUserList* pUserList = ScGlobal::GetUserList(); 505 if (pUserList) 506 { 507 sal_uInt16 n = pUserList->GetCount(); 508 aUserSortNames.reserve(n); 509 for (sal_uInt16 i = 0; i < n; ++i) 510 { 511 ScUserListData* pData = static_cast<ScUserListData*>((*pUserList)[i]); 512 aUserSortNames.push_back(pData->GetString()); 513 } 514 } 515 516 // Populate the menus. 517 ScTabViewShell* pViewShell = pViewData->GetViewShell(); 518 mpDPFieldPopup->addMenuItem( 519 ScRscStrLoader(RID_POPUP_FILTER, STR_MENU_SORT_ASC).GetString(), true, 520 new PopupSortAction(rPos, PopupSortAction::ASCENDING, 0, pViewShell)); 521 mpDPFieldPopup->addMenuItem( 522 ScRscStrLoader(RID_POPUP_FILTER, STR_MENU_SORT_DESC).GetString(), true, 523 new PopupSortAction(rPos, PopupSortAction::DESCENDING, 0, pViewShell)); 524 ScMenuFloatingWindow* pSubMenu = mpDPFieldPopup->addSubMenuItem( 525 ScRscStrLoader(RID_POPUP_FILTER, STR_MENU_SORT_CUSTOM).GetString(), !aUserSortNames.empty()); 526 527 if (pSubMenu && !aUserSortNames.empty()) 528 { 529 size_t n = aUserSortNames.size(); 530 for (size_t i = 0; i < n; ++i) 531 { 532 pSubMenu->addMenuItem( 533 aUserSortNames[i], true, 534 new PopupSortAction(rPos, PopupSortAction::CUSTOM, static_cast<sal_uInt16>(i), pViewShell)); 535 } 536 } 537 538 sal_Bool bLayoutRTL = pViewData->GetDocument()->IsLayoutRTL( pViewData->GetTabNo() ); 539 540 Rectangle aCellRect(rScrPos, rScrSize); 541 const Size& rPopupSize = mpDPFieldPopup->getWindowSize(); 542 if (bLayoutRTL) 543 { 544 // RTL: rScrPos is logical-left (visual right) position, always right-align with that 545 aCellRect.SetPos(Point(rScrPos.X() - rPopupSize.Width() + 1, rScrPos.Y())); 546 } 547 else if (rScrSize.getWidth() > rPopupSize.getWidth()) 548 { 549 // If the cell width is larger than the popup window width, launch it 550 // right-aligned with the cell. 551 long nXOffset = rScrSize.getWidth() - rPopupSize.getWidth(); 552 aCellRect.SetPos(Point(rScrPos.X() + nXOffset, rScrPos.Y())); 553 } 554 mpDPFieldPopup->SetPopupModeEndHdl( LINK(this, ScGridWindow, PopupModeEndHdl) ); 555 mpDPFieldPopup->StartPopupMode(aCellRect, (FLOATWIN_POPUPMODE_DOWN | FLOATWIN_POPUPMODE_GRABFOCUS)); 556 } 557 558 void ScGridWindow::UpdateDPFromFieldPopupMenu() 559 { 560 typedef hash_map<OUString, OUString, OUStringHash> MemNameMapType; 561 typedef hash_map<OUString, bool, OUStringHash> MemVisibilityType; 562 563 if (!mpDPFieldPopup.get()) 564 return; 565 566 DPFieldPopupData* pDPData = static_cast<DPFieldPopupData*>(mpDPFieldPopup->getExtendedData()); 567 if (!pDPData) 568 return; 569 570 ScDPObject* pDPObj = pDPData->mpDPObj; 571 ScDPObject aNewDPObj(*pDPObj); 572 aNewDPObj.BuildAllDimensionMembers(); 573 ScDPSaveData* pSaveData = aNewDPObj.GetSaveData(); 574 575 sal_Bool bIsDataLayout; 576 String aDimName = pDPObj->GetDimName(pDPData->mnDim, bIsDataLayout); 577 ScDPSaveDimension* pDim = pSaveData->GetDimensionByName(aDimName); 578 if (!pDim) 579 return; 580 581 size_t nLabelIndex = 0; 582 lcl_GetLabelIndex( nLabelIndex, pDPData->mnDim, pDPData->maDPParam.maLabelArray ); 583 584 // Build a map of layout names to original names. 585 const ScDPLabelData& rLabelData = pDPData->maDPParam.maLabelArray[nLabelIndex]; 586 MemNameMapType aMemNameMap; 587 for (vector<ScDPLabelData::Member>::const_iterator itr = rLabelData.maMembers.begin(), itrEnd = rLabelData.maMembers.end(); 588 itr != itrEnd; ++itr) 589 aMemNameMap.insert(MemNameMapType::value_type(itr->maLayoutName, itr->maName)); 590 591 // The raw result may contain a mixture of layout names and original names. 592 MemVisibilityType aRawResult; 593 mpDPFieldPopup->getResult(aRawResult); 594 595 MemVisibilityType aResult; 596 for (MemVisibilityType::const_iterator itr = aRawResult.begin(), itrEnd = aRawResult.end(); itr != itrEnd; ++itr) 597 { 598 MemNameMapType::const_iterator itrNameMap = aMemNameMap.find(itr->first); 599 if (itrNameMap == aMemNameMap.end()) 600 // This is an original member name. Use it as-is. 601 aResult.insert(MemVisibilityType::value_type(itr->first, itr->second)); 602 else 603 { 604 // This is a layout name. Get the original member name and use it. 605 aResult.insert(MemVisibilityType::value_type(itrNameMap->second, itr->second)); 606 } 607 } 608 pDim->UpdateMemberVisibility(aResult); 609 610 ScDBDocFunc aFunc(*pViewData->GetDocShell()); 611 aFunc.DataPilotUpdate(pDPObj, &aNewDPObj, true, false); 612 } 613 614 void ScGridWindow::DPMouseMove( const MouseEvent& rMEvt ) 615 { 616 DPTestMouse( rMEvt, sal_True ); 617 } 618 619 void ScGridWindow::DPMouseButtonUp( const MouseEvent& rMEvt ) 620 { 621 bDPMouse = sal_False; 622 ReleaseMouse(); 623 624 DPTestMouse( rMEvt, sal_False ); 625 SetPointer( Pointer( POINTER_ARROW ) ); 626 } 627 628 // ----------------------------------------------------------------------- 629 630 void ScGridWindow::UpdateDragRect( sal_Bool bShowRange, const Rectangle& rPosRect ) 631 { 632 SCCOL nStartX = ( rPosRect.Left() >= 0 ) ? static_cast<SCCOL>(rPosRect.Left()) : SCCOL_MAX; 633 SCROW nStartY = ( rPosRect.Top() >= 0 ) ? static_cast<SCROW>(rPosRect.Top()) : SCROW_MAX; 634 SCCOL nEndX = ( rPosRect.Right() >= 0 ) ? static_cast<SCCOL>(rPosRect.Right()) : SCCOL_MAX; 635 SCROW nEndY = ( rPosRect.Bottom() >= 0 ) ? static_cast<SCROW>(rPosRect.Bottom()) : SCROW_MAX; 636 637 if ( bShowRange == bDragRect && nDragStartX == nStartX && nDragEndX == nEndX && 638 nDragStartY == nStartY && nDragEndY == nEndY ) 639 { 640 return; // everything unchanged 641 } 642 643 // if ( bDragRect ) 644 // DrawDragRect( nDragStartX, nDragStartY, nDragEndX, nDragEndY, sal_False ); 645 if ( bShowRange ) 646 { 647 nDragStartX = nStartX; 648 nDragStartY = nStartY; 649 nDragEndX = nEndX; 650 nDragEndY = nEndY; 651 bDragRect = sal_True; 652 // DrawDragRect( nDragStartX, nDragStartY, nDragEndX, nDragEndY, sal_False ); 653 } 654 else 655 bDragRect = sal_False; 656 657 UpdateDragRectOverlay(); 658 } 659 660 // ----------------------------------------------------------------------- 661 662 // Page-Break-Modus 663 664 sal_uInt16 ScGridWindow::HitPageBreak( const Point& rMouse, ScRange* pSource, 665 SCCOLROW* pBreak, SCCOLROW* pPrev ) 666 { 667 sal_uInt16 nFound = SC_PD_NONE; // 0 668 ScRange aSource; 669 SCCOLROW nBreak = 0; 670 SCCOLROW nPrev = 0; 671 672 ScPageBreakData* pPageData = pViewData->GetView()->GetPageBreakData(); 673 if ( pPageData ) 674 { 675 sal_Bool bHori = sal_False; 676 sal_Bool bVert = sal_False; 677 SCCOL nHitX = 0; 678 SCROW nHitY = 0; 679 680 long nMouseX = rMouse.X(); 681 long nMouseY = rMouse.Y(); 682 SCsCOL nPosX; 683 SCsROW nPosY; 684 pViewData->GetPosFromPixel( nMouseX, nMouseY, eWhich, nPosX, nPosY ); 685 Point aTL = pViewData->GetScrPos( nPosX, nPosY, eWhich ); 686 Point aBR = pViewData->GetScrPos( nPosX+1, nPosY+1, eWhich ); 687 688 // Horizontal mehr Toleranz als vertikal, weil mehr Platz ist 689 if ( nMouseX <= aTL.X() + 4 ) 690 { 691 bHori = sal_True; 692 nHitX = nPosX; 693 } 694 else if ( nMouseX >= aBR.X() - 6 ) 695 { 696 bHori = sal_True; 697 nHitX = nPosX+1; // linker Rand der naechsten Zelle 698 } 699 if ( nMouseY <= aTL.Y() + 2 ) 700 { 701 bVert = sal_True; 702 nHitY = nPosY; 703 } 704 else if ( nMouseY >= aBR.Y() - 4 ) 705 { 706 bVert = sal_True; 707 nHitY = nPosY+1; // oberer Rand der naechsten Zelle 708 } 709 710 if ( bHori || bVert ) 711 { 712 sal_uInt16 nCount = sal::static_int_cast<sal_uInt16>( pPageData->GetCount() ); 713 for (sal_uInt16 nPos=0; nPos<nCount && !nFound; nPos++) 714 { 715 ScPrintRangeData& rData = pPageData->GetData(nPos); 716 ScRange aRange = rData.GetPrintRange(); 717 sal_Bool bLHit = ( bHori && nHitX == aRange.aStart.Col() ); 718 sal_Bool bRHit = ( bHori && nHitX == aRange.aEnd.Col() + 1 ); 719 sal_Bool bTHit = ( bVert && nHitY == aRange.aStart.Row() ); 720 sal_Bool bBHit = ( bVert && nHitY == aRange.aEnd.Row() + 1 ); 721 sal_Bool bInsideH = ( nPosX >= aRange.aStart.Col() && nPosX <= aRange.aEnd.Col() ); 722 sal_Bool bInsideV = ( nPosY >= aRange.aStart.Row() && nPosY <= aRange.aEnd.Row() ); 723 724 if ( bLHit ) 725 { 726 if ( bTHit ) 727 nFound = SC_PD_RANGE_TL; 728 else if ( bBHit ) 729 nFound = SC_PD_RANGE_BL; 730 else if ( bInsideV ) 731 nFound = SC_PD_RANGE_L; 732 } 733 else if ( bRHit ) 734 { 735 if ( bTHit ) 736 nFound = SC_PD_RANGE_TR; 737 else if ( bBHit ) 738 nFound = SC_PD_RANGE_BR; 739 else if ( bInsideV ) 740 nFound = SC_PD_RANGE_R; 741 } 742 else if ( bTHit && bInsideH ) 743 nFound = SC_PD_RANGE_T; 744 else if ( bBHit && bInsideH ) 745 nFound = SC_PD_RANGE_B; 746 if (nFound) 747 aSource = aRange; 748 749 // Umbrueche 750 751 if ( bVert && bInsideH && !nFound ) 752 { 753 size_t nRowCount = rData.GetPagesY(); 754 const SCROW* pRowEnd = rData.GetPageEndY(); 755 for (size_t nRowPos=0; nRowPos+1<nRowCount; nRowPos++) 756 if ( pRowEnd[nRowPos]+1 == nHitY ) 757 { 758 nFound = SC_PD_BREAK_V; 759 aSource = aRange; 760 nBreak = nHitY; 761 if ( nRowPos ) 762 nPrev = pRowEnd[nRowPos-1]+1; 763 else 764 nPrev = aRange.aStart.Row(); 765 } 766 } 767 if ( bHori && bInsideV && !nFound ) 768 { 769 size_t nColCount = rData.GetPagesX(); 770 const SCCOL* pColEnd = rData.GetPageEndX(); 771 for (size_t nColPos=0; nColPos+1<nColCount; nColPos++) 772 if ( pColEnd[nColPos]+1 == nHitX ) 773 { 774 nFound = SC_PD_BREAK_H; 775 aSource = aRange; 776 nBreak = nHitX; 777 if ( nColPos ) 778 nPrev = pColEnd[nColPos-1]+1; 779 else 780 nPrev = aRange.aStart.Col(); 781 } 782 } 783 } 784 } 785 } 786 787 if (pSource) 788 *pSource = aSource; // Druckbereich 789 if (pBreak) 790 *pBreak = nBreak; // X/Y Position des verchobenen Seitenumbruchs 791 if (pPrev) 792 *pPrev = nPrev; // X/Y Anfang der Seite, die am Umbruch zuende ist 793 return nFound; 794 } 795 796 void ScGridWindow::PagebreakMove( const MouseEvent& rMEvt, sal_Bool bUp ) 797 { 798 //! Scrolling und Umschalten mit RFMouseMove zusammenfassen ! 799 //! (Weginvertieren vor dem Scrolling ist anders) 800 801 // Scrolling 802 803 sal_Bool bTimer = sal_False; 804 Point aPos = rMEvt.GetPosPixel(); 805 SCsCOL nDx = 0; 806 SCsROW nDy = 0; 807 if ( aPos.X() < 0 ) nDx = -1; 808 if ( aPos.Y() < 0 ) nDy = -1; 809 Size aSize = GetOutputSizePixel(); 810 if ( aPos.X() >= aSize.Width() ) 811 nDx = 1; 812 if ( aPos.Y() >= aSize.Height() ) 813 nDy = 1; 814 if ( nDx != 0 || nDy != 0 ) 815 { 816 if ( bPagebreakDrawn ) // weginvertieren 817 { 818 // DrawDragRect( aPagebreakDrag.aStart.Col(), aPagebreakDrag.aStart.Row(), 819 // aPagebreakDrag.aEnd.Col(), aPagebreakDrag.aEnd.Row(), sal_False ); 820 bPagebreakDrawn = sal_False; 821 UpdateDragRectOverlay(); 822 } 823 824 if ( nDx != 0 ) pViewData->GetView()->ScrollX( nDx, WhichH(eWhich) ); 825 if ( nDy != 0 ) pViewData->GetView()->ScrollY( nDy, WhichV(eWhich) ); 826 bTimer = sal_True; 827 } 828 829 // Umschalten bei Fixierung (damit Scrolling funktioniert) 830 831 if ( eWhich == pViewData->GetActivePart() ) //?? 832 { 833 if ( pViewData->GetHSplitMode() == SC_SPLIT_FIX ) 834 if ( nDx > 0 ) 835 { 836 if ( eWhich == SC_SPLIT_TOPLEFT ) 837 pViewData->GetView()->ActivatePart( SC_SPLIT_TOPRIGHT ); 838 else if ( eWhich == SC_SPLIT_BOTTOMLEFT ) 839 pViewData->GetView()->ActivatePart( SC_SPLIT_BOTTOMRIGHT ); 840 } 841 842 if ( pViewData->GetVSplitMode() == SC_SPLIT_FIX ) 843 if ( nDy > 0 ) 844 { 845 if ( eWhich == SC_SPLIT_TOPLEFT ) 846 pViewData->GetView()->ActivatePart( SC_SPLIT_BOTTOMLEFT ); 847 else if ( eWhich == SC_SPLIT_TOPRIGHT ) 848 pViewData->GetView()->ActivatePart( SC_SPLIT_BOTTOMRIGHT ); 849 } 850 } 851 852 // ab hier neu 853 854 // gesucht wird eine Position zwischen den Zellen (vor nPosX / nPosY) 855 SCsCOL nPosX; 856 SCsROW nPosY; 857 pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY ); 858 sal_Bool bLeft, bTop; 859 pViewData->GetMouseQuadrant( aPos, eWhich, nPosX, nPosY, bLeft, bTop ); 860 if ( !bLeft ) ++nPosX; 861 if ( !bTop ) ++nPosY; 862 863 sal_Bool bBreak = ( nPagebreakMouse == SC_PD_BREAK_H || nPagebreakMouse == SC_PD_BREAK_V ); 864 sal_Bool bHide = sal_False; 865 sal_Bool bToEnd = sal_False; 866 ScRange aDrawRange = aPagebreakSource; 867 if ( bBreak ) 868 { 869 if ( nPagebreakMouse == SC_PD_BREAK_H ) 870 { 871 if ( nPosX > aPagebreakSource.aStart.Col() && 872 nPosX <= aPagebreakSource.aEnd.Col() + 1 ) // ans Ende ist auch erlaubt 873 { 874 bToEnd = ( nPosX == aPagebreakSource.aEnd.Col() + 1 ); 875 aDrawRange.aStart.SetCol( nPosX ); 876 aDrawRange.aEnd.SetCol( nPosX - 1 ); 877 } 878 else 879 bHide = sal_True; 880 } 881 else 882 { 883 if ( nPosY > aPagebreakSource.aStart.Row() && 884 nPosY <= aPagebreakSource.aEnd.Row() + 1 ) // ans Ende ist auch erlaubt 885 { 886 bToEnd = ( nPosY == aPagebreakSource.aEnd.Row() + 1 ); 887 aDrawRange.aStart.SetRow( nPosY ); 888 aDrawRange.aEnd.SetRow( nPosY - 1 ); 889 } 890 else 891 bHide = sal_True; 892 } 893 } 894 else 895 { 896 if ( nPagebreakMouse & SC_PD_RANGE_L ) 897 aDrawRange.aStart.SetCol( nPosX ); 898 if ( nPagebreakMouse & SC_PD_RANGE_T ) 899 aDrawRange.aStart.SetRow( nPosY ); 900 if ( nPagebreakMouse & SC_PD_RANGE_R ) 901 { 902 if ( nPosX > 0 ) 903 aDrawRange.aEnd.SetCol( nPosX-1 ); 904 else 905 bHide = sal_True; 906 } 907 if ( nPagebreakMouse & SC_PD_RANGE_B ) 908 { 909 if ( nPosY > 0 ) 910 aDrawRange.aEnd.SetRow( nPosY-1 ); 911 else 912 bHide = sal_True; 913 } 914 if ( aDrawRange.aStart.Col() > aDrawRange.aEnd.Col() || 915 aDrawRange.aStart.Row() > aDrawRange.aEnd.Row() ) 916 bHide = sal_True; 917 } 918 919 if ( !bPagebreakDrawn || bUp || aDrawRange != aPagebreakDrag ) 920 { 921 // zeichnen... 922 923 if ( bPagebreakDrawn ) 924 { 925 // weginvertieren 926 // DrawDragRect( aPagebreakDrag.aStart.Col(), aPagebreakDrag.aStart.Row(), 927 // aPagebreakDrag.aEnd.Col(), aPagebreakDrag.aEnd.Row(), sal_False ); 928 bPagebreakDrawn = sal_False; 929 } 930 aPagebreakDrag = aDrawRange; 931 if ( !bUp && !bHide ) 932 { 933 // hininvertieren 934 // DrawDragRect( aPagebreakDrag.aStart.Col(), aPagebreakDrag.aStart.Row(), 935 // aPagebreakDrag.aEnd.Col(), aPagebreakDrag.aEnd.Row(), sal_False ); 936 bPagebreakDrawn = sal_True; 937 } 938 UpdateDragRectOverlay(); 939 } 940 941 // bei ButtonUp die Aenderung ausfuehren 942 943 if ( bUp ) 944 { 945 ScViewFunc* pViewFunc = pViewData->GetView(); 946 ScDocShell* pDocSh = pViewData->GetDocShell(); 947 ScDocument* pDoc = pDocSh->GetDocument(); 948 SCTAB nTab = pViewData->GetTabNo(); 949 sal_Bool bUndo (pDoc->IsUndoEnabled()); 950 951 if ( bBreak ) 952 { 953 sal_Bool bColumn = ( nPagebreakMouse == SC_PD_BREAK_H ); 954 SCCOLROW nNew = bColumn ? static_cast<SCCOLROW>(nPosX) : static_cast<SCCOLROW>(nPosY); 955 if ( nNew != nPagebreakBreak ) 956 { 957 if (bUndo) 958 { 959 String aUndo = ScGlobal::GetRscString( STR_UNDO_DRAG_BREAK ); 960 pDocSh->GetUndoManager()->EnterListAction( aUndo, aUndo ); 961 } 962 963 sal_Bool bGrow = !bHide && nNew > nPagebreakBreak; 964 if ( bColumn ) 965 { 966 if (pDoc->HasColBreak(static_cast<SCCOL>(nPagebreakBreak), nTab) & BREAK_MANUAL) 967 { 968 ScAddress aOldAddr( static_cast<SCCOL>(nPagebreakBreak), nPosY, nTab ); 969 pViewFunc->DeletePageBreak( sal_True, sal_True, &aOldAddr, sal_False ); 970 } 971 if ( !bHide && !bToEnd ) // am Ende nicht 972 { 973 ScAddress aNewAddr( static_cast<SCCOL>(nNew), nPosY, nTab ); 974 pViewFunc->InsertPageBreak( sal_True, sal_True, &aNewAddr, sal_False ); 975 } 976 if ( bGrow ) 977 { 978 // vorigen Break auf hart, und Skalierung aendern 979 bool bManualBreak = (pDoc->HasColBreak(static_cast<SCCOL>(nPagebreakPrev), nTab) & BREAK_MANUAL); 980 if ( static_cast<SCCOL>(nPagebreakPrev) > aPagebreakSource.aStart.Col() && !bManualBreak ) 981 { 982 ScAddress aPrev( static_cast<SCCOL>(nPagebreakPrev), nPosY, nTab ); 983 pViewFunc->InsertPageBreak( sal_True, sal_True, &aPrev, sal_False ); 984 } 985 986 if (!pDocSh->AdjustPrintZoom( ScRange( 987 static_cast<SCCOL>(nPagebreakPrev),0,nTab, static_cast<SCCOL>(nNew-1),0,nTab ) )) 988 bGrow = sal_False; 989 } 990 } 991 else 992 { 993 if (pDoc->HasRowBreak(nPagebreakBreak, nTab) & BREAK_MANUAL) 994 { 995 ScAddress aOldAddr( nPosX, nPagebreakBreak, nTab ); 996 pViewFunc->DeletePageBreak( sal_False, sal_True, &aOldAddr, sal_False ); 997 } 998 if ( !bHide && !bToEnd ) // am Ende nicht 999 { 1000 ScAddress aNewAddr( nPosX, nNew, nTab ); 1001 pViewFunc->InsertPageBreak( sal_False, sal_True, &aNewAddr, sal_False ); 1002 } 1003 if ( bGrow ) 1004 { 1005 // vorigen Break auf hart, und Skalierung aendern 1006 bool bManualBreak = (pDoc->HasRowBreak(nPagebreakPrev, nTab) & BREAK_MANUAL); 1007 if ( nPagebreakPrev > aPagebreakSource.aStart.Row() && !bManualBreak ) 1008 { 1009 ScAddress aPrev( nPosX, nPagebreakPrev, nTab ); 1010 pViewFunc->InsertPageBreak( sal_False, sal_True, &aPrev, sal_False ); 1011 } 1012 1013 if (!pDocSh->AdjustPrintZoom( ScRange( 1014 0,nPagebreakPrev,nTab, 0,nNew-1,nTab ) )) 1015 bGrow = sal_False; 1016 } 1017 } 1018 1019 if (bUndo) 1020 { 1021 pDocSh->GetUndoManager()->LeaveListAction(); 1022 } 1023 1024 if (!bGrow) // sonst in AdjustPrintZoom schon passiert 1025 { 1026 pViewFunc->UpdatePageBreakData( sal_True ); 1027 pDocSh->SetDocumentModified(); 1028 } 1029 } 1030 } 1031 else if ( bHide || aPagebreakDrag != aPagebreakSource ) 1032 { 1033 // Druckbereich setzen 1034 1035 String aNewRanges; 1036 sal_uInt16 nOldCount = pDoc->GetPrintRangeCount( nTab ); 1037 if ( nOldCount ) 1038 { 1039 for (sal_uInt16 nPos=0; nPos<nOldCount; nPos++) 1040 { 1041 const ScRange* pOld = pDoc->GetPrintRange( nTab, nPos ); 1042 if ( pOld ) 1043 { 1044 String aTemp; 1045 if ( *pOld != aPagebreakSource ) 1046 pOld->Format( aTemp, SCA_VALID ); 1047 else if ( !bHide ) 1048 aPagebreakDrag.Format( aTemp, SCA_VALID ); 1049 if (aTemp.Len()) 1050 { 1051 if ( aNewRanges.Len() ) 1052 aNewRanges += ';'; 1053 aNewRanges += aTemp; 1054 } 1055 } 1056 } 1057 } 1058 else if (!bHide) 1059 aPagebreakDrag.Format( aNewRanges, SCA_VALID ); 1060 1061 pViewFunc->SetPrintRanges( pDoc->IsPrintEntireSheet( nTab ), &aNewRanges, NULL, NULL, sal_False ); 1062 } 1063 } 1064 1065 // Timer fuer Scrolling 1066 1067 if (bTimer && !bUp) 1068 pViewData->GetView()->SetTimer( this, rMEvt ); // Event wiederholen 1069 else 1070 pViewData->GetView()->ResetTimer(); 1071 } 1072 1073 1074 1075 1076