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