1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 #include "precompiled_reportdesign.hxx" 28 29 #include "Navigator.hxx" 30 31 #include "uistrings.hrc" 32 #include "ReportController.hxx" 33 #include "UITools.hxx" 34 #include "RptUndo.hxx" 35 #include "reportformula.hxx" 36 #include <com/sun/star/container/XContainerListener.hpp> 37 #include <com/sun/star/report/XReportDefinition.hpp> 38 #include <com/sun/star/report/XFixedText.hpp> 39 #include <com/sun/star/report/XFixedLine.hpp> 40 #include <com/sun/star/report/XFormattedField.hpp> 41 #include <com/sun/star/report/XImageControl.hpp> 42 #include <com/sun/star/report/XShape.hpp> 43 #include <svx/globlmn.hrc> 44 #include <svx/svxids.hrc> 45 #include "helpids.hrc" 46 #include "RptResId.hrc" 47 #include "rptui_slotid.hrc" 48 #include <tools/debug.hxx> 49 #include <comphelper/propmultiplex.hxx> 50 #include <comphelper/containermultiplexer.hxx> 51 #include <comphelper/types.hxx> 52 #include "cppuhelper/basemutex.hxx" 53 #include "comphelper/SelectionMultiplex.hxx" 54 #include <svtools/svtreebx.hxx> 55 #include <svl/solar.hrc> 56 #include "ReportVisitor.hxx" 57 #include "ModuleHelper.hxx" 58 #include <rtl/ref.hxx> 59 60 #include <boost/bind.hpp> 61 #include <memory> 62 #include <algorithm> 63 64 #define RID_SVXIMG_COLLAPSEDNODE (RID_FORMS_START + 2) 65 #define RID_SVXIMG_EXPANDEDNODE (RID_FORMS_START + 3) 66 #define DROP_ACTION_TIMER_INITIAL_TICKS 10 67 #define DROP_ACTION_TIMER_SCROLL_TICKS 3 68 #define DROP_ACTION_TIMER_TICK_BASE 10 69 70 namespace rptui 71 { 72 using namespace ::com::sun::star; 73 using namespace utl; 74 using namespace ::comphelper; 75 76 sal_uInt16 lcl_getImageId(const uno::Reference< report::XReportComponent>& _xElement) 77 { 78 sal_uInt16 nId = 0; 79 uno::Reference< report::XFixedLine> xFixedLine(_xElement,uno::UNO_QUERY); 80 if ( uno::Reference< report::XFixedText>(_xElement,uno::UNO_QUERY).is() ) 81 nId = SID_FM_FIXEDTEXT; 82 else if ( xFixedLine.is() ) 83 nId = xFixedLine->getOrientation() ? SID_INSERT_VFIXEDLINE : SID_INSERT_HFIXEDLINE; 84 else if ( uno::Reference< report::XFormattedField>(_xElement,uno::UNO_QUERY).is() ) 85 nId = SID_FM_EDIT; 86 else if ( uno::Reference< report::XImageControl>(_xElement,uno::UNO_QUERY).is() ) 87 nId = SID_FM_IMAGECONTROL; 88 else if ( uno::Reference< report::XShape>(_xElement,uno::UNO_QUERY).is() ) 89 nId = SID_DRAWTBX_CS_BASIC; 90 return nId; 91 } 92 // ----------------------------------------------------------------------------- 93 ::rtl::OUString lcl_getName(const uno::Reference< beans::XPropertySet>& _xElement) 94 { 95 OSL_ENSURE(_xElement.is(),"Found report element which is NULL!"); 96 ::rtl::OUString sTempName; 97 _xElement->getPropertyValue(PROPERTY_NAME) >>= sTempName; 98 ::rtl::OUStringBuffer sName = sTempName; 99 uno::Reference< report::XFixedText> xFixedText(_xElement,uno::UNO_QUERY); 100 uno::Reference< report::XReportControlModel> xReportModel(_xElement,uno::UNO_QUERY); 101 if ( xFixedText.is() ) 102 { 103 sName.append(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" : "))); 104 sName.append(xFixedText->getLabel()); 105 } 106 else if ( xReportModel.is() && _xElement->getPropertySetInfo()->hasPropertyByName(PROPERTY_DATAFIELD) ) 107 { 108 ReportFormula aFormula( xReportModel->getDataField() ); 109 if ( aFormula.isValid() ) 110 { 111 sName.append(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" : "))); 112 sName.append( aFormula.getUndecoratedContent() ); 113 } 114 } 115 return sName.makeStringAndClear(); 116 } 117 // ----------------------------------------------------------------------------- 118 119 class NavigatorTree : public ::cppu::BaseMutex 120 , public SvTreeListBox 121 , public reportdesign::ITraverseReport 122 , public comphelper::OSelectionChangeListener 123 , public ::comphelper::OPropertyChangeListener 124 { 125 class UserData; 126 friend class UserData; 127 class UserData : public ::cppu::BaseMutex 128 ,public ::comphelper::OPropertyChangeListener 129 ,public ::comphelper::OContainerListener 130 { 131 uno::Reference< uno::XInterface > m_xContent; 132 ::rtl::Reference< comphelper::OPropertyChangeMultiplexer> m_pListener; 133 ::rtl::Reference< comphelper::OContainerListenerAdapter> m_pContainerListener; 134 NavigatorTree* m_pTree; 135 public: 136 UserData(NavigatorTree* _pTree,const uno::Reference<uno::XInterface>& _xContent); 137 ~UserData(); 138 139 inline uno::Reference< uno::XInterface > getContent() const { return m_xContent; } 140 inline void setContent(const uno::Reference< uno::XInterface >& _xContent) { m_xContent = _xContent; } 141 protected: 142 // OPropertyChangeListener 143 virtual void _propertyChanged(const beans::PropertyChangeEvent& _rEvent) throw( uno::RuntimeException); 144 145 // OContainerListener 146 virtual void _elementInserted( const container::ContainerEvent& _rEvent ) throw(uno::RuntimeException); 147 virtual void _elementRemoved( const container::ContainerEvent& _Event ) throw(uno::RuntimeException); 148 virtual void _elementReplaced( const container::ContainerEvent& _rEvent ) throw(uno::RuntimeException); 149 virtual void _disposing(const lang::EventObject& _rSource) throw( uno::RuntimeException); 150 }; 151 152 enum DROP_ACTION { DA_SCROLLUP, DA_SCROLLDOWN, DA_EXPANDNODE }; 153 AutoTimer m_aDropActionTimer; 154 Timer m_aSynchronizeTimer; 155 ImageList m_aNavigatorImages; 156 ImageList m_aNavigatorImagesHC; 157 Point m_aTimerTriggered; // die Position, an der der DropTimer angeschaltet wurde 158 DROP_ACTION m_aDropActionType; 159 OReportController& m_rController; 160 SvLBoxEntry* m_pMasterReport; 161 SvLBoxEntry* m_pDragedEntry; 162 ::rtl::Reference< comphelper::OPropertyChangeMultiplexer> m_pReportListener; 163 ::rtl::Reference< comphelper::OSelectionChangeMultiplexer> m_pSelectionListener; 164 unsigned short m_nTimerCounter; 165 166 SvLBoxEntry* insertEntry(const ::rtl::OUString& _sName,SvLBoxEntry* _pParent,sal_uInt16 _nImageId,sal_uLong _nPosition,UserData* _pData); 167 void traverseSection(const uno::Reference< report::XSection>& _xSection,SvLBoxEntry* _pParent,sal_uInt16 _nImageId,sal_uLong _nPosition = LIST_APPEND); 168 void traverseFunctions(const uno::Reference< report::XFunctions>& _xFunctions,SvLBoxEntry* _pParent); 169 170 NavigatorTree(const NavigatorTree&); 171 void operator =(const NavigatorTree&); 172 protected: 173 virtual void Command( const CommandEvent& rEvt ); 174 // DragSourceHelper overridables 175 virtual void StartDrag( sal_Int8 nAction, const Point& rPosPixel ); 176 // DropTargetHelper overridables 177 virtual sal_Int8 AcceptDrop( const AcceptDropEvent& _rEvt ); 178 virtual sal_Int8 ExecuteDrop( const ExecuteDropEvent& _rEvt ); 179 180 // OSelectionChangeListener 181 virtual void _disposing(const lang::EventObject& _rSource) throw( uno::RuntimeException); 182 183 // OPropertyChangeListener 184 virtual void _propertyChanged(const beans::PropertyChangeEvent& _rEvent) throw( uno::RuntimeException); 185 186 // OContainerListener Helper 187 void _elementInserted( const container::ContainerEvent& _rEvent ); 188 void _elementRemoved( const container::ContainerEvent& _Event ); 189 void _elementReplaced( const container::ContainerEvent& _rEvent ); 190 191 public: 192 NavigatorTree(Window* pParent,OReportController& _rController ); 193 virtual ~NavigatorTree(); 194 195 DECL_LINK(OnEntrySelDesel, NavigatorTree*); 196 DECL_LINK( OnDropActionTimer, void* ); 197 198 virtual void _selectionChanged( const lang::EventObject& aEvent ) throw (uno::RuntimeException); 199 200 // ITraverseReport 201 virtual void traverseReport(const uno::Reference< report::XReportDefinition>& _xReport); 202 virtual void traverseReportFunctions(const uno::Reference< report::XFunctions>& _xFunctions); 203 virtual void traverseReportHeader(const uno::Reference< report::XSection>& _xSection); 204 virtual void traverseReportFooter(const uno::Reference< report::XSection>& _xSection); 205 virtual void traversePageHeader(const uno::Reference< report::XSection>& _xSection); 206 virtual void traversePageFooter(const uno::Reference< report::XSection>& _xSection); 207 208 virtual void traverseGroups(const uno::Reference< report::XGroups>& _xGroups); 209 virtual void traverseGroup(const uno::Reference< report::XGroup>& _xGroup); 210 virtual void traverseGroupFunctions(const uno::Reference< report::XFunctions>& _xFunctions); 211 virtual void traverseGroupHeader(const uno::Reference< report::XSection>& _xSection); 212 virtual void traverseGroupFooter(const uno::Reference< report::XSection>& _xSection); 213 214 virtual void traverseDetail(const uno::Reference< report::XSection>& _xSection); 215 216 SvLBoxEntry* find(const uno::Reference< uno::XInterface >& _xContent); 217 void removeEntry(SvLBoxEntry* _pEntry,bool _bRemove = true); 218 private: 219 using SvTreeListBox::ExecuteDrop; 220 }; 221 DBG_NAME(rpt_NavigatorTree) 222 // ----------------------------------------------------------------------------- 223 NavigatorTree::NavigatorTree( Window* pParent,OReportController& _rController ) 224 :SvTreeListBox( pParent, WB_TABSTOP| WB_HASBUTTONS|WB_HASLINES|WB_BORDER|WB_HSCROLL|WB_HASBUTTONSATROOT ) 225 ,comphelper::OSelectionChangeListener(m_aMutex) 226 ,OPropertyChangeListener(m_aMutex) 227 ,m_aTimerTriggered(-1,-1) 228 ,m_aDropActionType( DA_SCROLLUP ) 229 ,m_rController(_rController) 230 ,m_pMasterReport(NULL) 231 ,m_pDragedEntry(NULL) 232 ,m_nTimerCounter( DROP_ACTION_TIMER_INITIAL_TICKS ) 233 { 234 DBG_CTOR(rpt_NavigatorTree,NULL); 235 m_pReportListener = new OPropertyChangeMultiplexer(this,m_rController.getReportDefinition().get()); 236 m_pReportListener->addProperty(PROPERTY_PAGEHEADERON); 237 m_pReportListener->addProperty(PROPERTY_PAGEFOOTERON); 238 m_pReportListener->addProperty(PROPERTY_REPORTHEADERON); 239 m_pReportListener->addProperty(PROPERTY_REPORTFOOTERON); 240 241 m_pSelectionListener = new OSelectionChangeMultiplexer(this,&m_rController); 242 243 SetHelpId( HID_REPORT_NAVIGATOR_TREE ); 244 245 m_aNavigatorImages = ImageList( ModuleRes( RID_SVXIMGLIST_RPTEXPL ) ); 246 m_aNavigatorImagesHC = ImageList( ModuleRes( RID_SVXIMGLIST_RPTEXPL_HC ) ); 247 248 SetNodeBitmaps( 249 m_aNavigatorImages.GetImage( RID_SVXIMG_COLLAPSEDNODE ), 250 m_aNavigatorImages.GetImage( RID_SVXIMG_EXPANDEDNODE ), 251 BMP_COLOR_NORMAL 252 ); 253 SetNodeBitmaps( 254 m_aNavigatorImagesHC.GetImage( RID_SVXIMG_COLLAPSEDNODE ), 255 m_aNavigatorImagesHC.GetImage( RID_SVXIMG_EXPANDEDNODE ), 256 BMP_COLOR_HIGHCONTRAST 257 ); 258 259 SetDragDropMode(0xFFFF); 260 EnableInplaceEditing( sal_False ); 261 SetSelectionMode(MULTIPLE_SELECTION); 262 Clear(); 263 264 m_aDropActionTimer.SetTimeoutHdl(LINK(this, NavigatorTree, OnDropActionTimer)); 265 SetSelectHdl(LINK(this, NavigatorTree, OnEntrySelDesel)); 266 SetDeselectHdl(LINK(this, NavigatorTree, OnEntrySelDesel)); 267 } 268 // ----------------------------------------------------------------------------- 269 NavigatorTree::~NavigatorTree() 270 { 271 SvLBoxEntry* pCurrent = First(); 272 while ( pCurrent ) 273 { 274 delete static_cast<UserData*>(pCurrent->GetUserData()); 275 pCurrent = Next(pCurrent); 276 } 277 m_pReportListener->dispose(); 278 m_pSelectionListener->dispose(); 279 DBG_DTOR(rpt_NavigatorTree,NULL); 280 } 281 //------------------------------------------------------------------------------ 282 void NavigatorTree::Command( const CommandEvent& rEvt ) 283 { 284 sal_Bool bHandled = sal_False; 285 switch( rEvt.GetCommand() ) 286 { 287 case COMMAND_CONTEXTMENU: 288 { 289 // die Stelle, an der geklickt wurde 290 SvLBoxEntry* ptClickedOn = NULL; 291 ::Point aWhere; 292 if (rEvt.IsMouseEvent()) 293 { 294 aWhere = rEvt.GetMousePosPixel(); 295 ptClickedOn = GetEntry(aWhere); 296 if (ptClickedOn == NULL) 297 break; 298 if ( !IsSelected(ptClickedOn) ) 299 { 300 SelectAll(sal_False); 301 Select(ptClickedOn, sal_True); 302 SetCurEntry(ptClickedOn); 303 } 304 } 305 else 306 { 307 ptClickedOn = GetCurEntry(); 308 if ( !ptClickedOn ) 309 break; 310 aWhere = GetEntryPosition(ptClickedOn); 311 } 312 UserData* pData = static_cast<UserData*>(ptClickedOn->GetUserData()); 313 uno::Reference< report::XFunctionsSupplier> xSupplier(pData->getContent(),uno::UNO_QUERY); 314 uno::Reference< report::XFunctions> xFunctions(pData->getContent(),uno::UNO_QUERY); 315 uno::Reference< report::XGroup> xGroup(pData->getContent(),uno::UNO_QUERY); 316 sal_Bool bDeleteAllowed = m_rController.isEditable() && (xGroup.is() || 317 uno::Reference< report::XFunction>(pData->getContent(),uno::UNO_QUERY).is()); 318 PopupMenu aContextMenu( ModuleRes( RID_MENU_NAVIGATOR ) ); 319 320 sal_uInt16 nCount = aContextMenu.GetItemCount(); 321 for (sal_uInt16 i = 0; i < nCount; ++i) 322 { 323 if ( MENUITEM_SEPARATOR != aContextMenu.GetItemType(i)) 324 { 325 sal_uInt16 nId = aContextMenu.GetItemId(i); 326 327 aContextMenu.CheckItem(nId,m_rController.isCommandChecked(nId)); 328 sal_Bool bEnabled = m_rController.isCommandEnabled(nId); 329 if ( nId == SID_RPT_NEW_FUNCTION ) 330 aContextMenu.EnableItem(nId,m_rController.isEditable() && (xSupplier.is() || xFunctions.is()) ); 331 // special condition, check for function and group 332 else if ( nId == SID_DELETE ) 333 aContextMenu.EnableItem(SID_DELETE,bDeleteAllowed); 334 else 335 aContextMenu.EnableItem(nId,bEnabled); 336 } 337 } // for (sal_uInt16 i = 0; i < nCount; ++i) 338 sal_uInt16 nId = aContextMenu.Execute(this, aWhere); 339 if ( nId ) 340 { 341 uno::Sequence< beans::PropertyValue> aArgs; 342 if ( nId == SID_RPT_NEW_FUNCTION ) 343 { 344 aArgs.realloc(1); 345 aArgs[0].Value <<= (xFunctions.is() ? xFunctions : xSupplier->getFunctions()); 346 } 347 else if ( nId == SID_DELETE ) 348 { 349 if ( xGroup.is() ) 350 nId = SID_GROUP_REMOVE; 351 aArgs.realloc(1); 352 aArgs[0].Name = PROPERTY_GROUP; 353 aArgs[0].Value <<= pData->getContent(); 354 } 355 m_rController.executeUnChecked(nId,aArgs); 356 } 357 358 bHandled = sal_True; 359 } break; 360 } 361 362 if (!bHandled) 363 SvTreeListBox::Command( rEvt ); 364 } 365 // ----------------------------------------------------------------------------- 366 sal_Int8 NavigatorTree::AcceptDrop( const AcceptDropEvent& _rEvt ) 367 { 368 sal_Int8 nDropOption = DND_ACTION_NONE; 369 ::Point aDropPos = _rEvt.maPosPixel; 370 if (_rEvt.mbLeaving) 371 { 372 if (m_aDropActionTimer.IsActive()) 373 m_aDropActionTimer.Stop(); 374 } 375 else 376 { 377 bool bNeedTrigger = false; 378 // auf dem ersten Eintrag ? 379 if ((aDropPos.Y() >= 0) && (aDropPos.Y() < GetEntryHeight())) 380 { 381 m_aDropActionType = DA_SCROLLUP; 382 bNeedTrigger = true; 383 } 384 else if ((aDropPos.Y() < GetSizePixel().Height()) && (aDropPos.Y() >= GetSizePixel().Height() - GetEntryHeight())) 385 { 386 m_aDropActionType = DA_SCROLLDOWN; 387 bNeedTrigger = true; 388 } 389 else 390 { 391 SvLBoxEntry* pDropppedOn = GetEntry(aDropPos); 392 if (pDropppedOn && (GetChildCount(pDropppedOn) > 0) && !IsExpanded(pDropppedOn)) 393 { 394 m_aDropActionType = DA_EXPANDNODE; 395 bNeedTrigger = true; 396 } 397 } 398 399 if (bNeedTrigger && (m_aTimerTriggered != aDropPos)) 400 { 401 // neu anfangen zu zaehlen 402 m_nTimerCounter = DROP_ACTION_TIMER_INITIAL_TICKS; 403 // die Pos merken, da ich auch AcceptDrops bekomme, wenn sich die Maus gar nicht bewegt hat 404 m_aTimerTriggered = aDropPos; 405 // und den Timer los 406 if (!m_aDropActionTimer.IsActive()) // gibt es den Timer schon ? 407 { 408 m_aDropActionTimer.SetTimeout(DROP_ACTION_TIMER_TICK_BASE); 409 m_aDropActionTimer.Start(); 410 } 411 } 412 else if (!bNeedTrigger) 413 m_aDropActionTimer.Stop(); 414 } 415 416 return nDropOption; 417 } 418 // ------------------------------------------------------------------------- 419 sal_Int8 NavigatorTree::ExecuteDrop( const ExecuteDropEvent& /*_rEvt*/ ) 420 { 421 // _rEvt.mnAction; 422 return DND_ACTION_NONE; 423 } 424 // ------------------------------------------------------------------------- 425 void NavigatorTree::StartDrag( sal_Int8 /*_nAction*/, const Point& _rPosPixel ) 426 { 427 m_pDragedEntry = GetEntry(_rPosPixel); 428 if ( m_pDragedEntry ) 429 { 430 EndSelection(); 431 } 432 } 433 //------------------------------------------------------------------------ 434 IMPL_LINK( NavigatorTree, OnDropActionTimer, void*, EMPTYARG ) 435 { 436 if (--m_nTimerCounter > 0) 437 return 0L; 438 439 switch ( m_aDropActionType ) 440 { 441 case DA_EXPANDNODE: 442 { 443 SvLBoxEntry* pToExpand = GetEntry(m_aTimerTriggered); 444 if (pToExpand && (GetChildCount(pToExpand) > 0) && !IsExpanded(pToExpand)) 445 // tja, eigentlich muesste ich noch testen, ob die Node nicht schon expandiert ist, aber ich 446 // habe dazu weder in den Basisklassen noch im Model eine Methode gefunden ... 447 // aber ich denke, die BK sollte es auch so vertragen 448 Expand(pToExpand); 449 450 // nach dem Expand habe ich im Gegensatz zum Scrollen natuerlich nix mehr zu tun 451 m_aDropActionTimer.Stop(); 452 } 453 break; 454 455 case DA_SCROLLUP : 456 ScrollOutputArea( 1 ); 457 m_nTimerCounter = DROP_ACTION_TIMER_SCROLL_TICKS; 458 break; 459 460 case DA_SCROLLDOWN : 461 ScrollOutputArea( -1 ); 462 m_nTimerCounter = DROP_ACTION_TIMER_SCROLL_TICKS; 463 break; 464 465 } 466 467 return 0L; 468 } 469 470 // ----------------------------------------------------------------------------- 471 IMPL_LINK(NavigatorTree, OnEntrySelDesel, NavigatorTree*, /*pThis*/) 472 { 473 if ( !m_pSelectionListener->locked() ) 474 { 475 m_pSelectionListener->lock(); 476 SvLBoxEntry* pEntry = GetCurEntry(); 477 uno::Any aSelection; 478 if ( IsSelected(pEntry) ) 479 aSelection <<= static_cast<UserData*>(pEntry->GetUserData())->getContent(); 480 m_rController.select(aSelection); 481 m_pSelectionListener->unlock(); 482 } 483 484 return 0L; 485 } 486 // ----------------------------------------------------------------------------- 487 void NavigatorTree::_selectionChanged( const lang::EventObject& aEvent ) throw (uno::RuntimeException) 488 { 489 m_pSelectionListener->lock(); 490 uno::Reference< view::XSelectionSupplier> xSelectionSupplier(aEvent.Source,uno::UNO_QUERY); 491 uno::Any aSec = xSelectionSupplier->getSelection(); 492 uno::Sequence< uno::Reference< report::XReportComponent > > aSelection; 493 aSec >>= aSelection; 494 if ( !aSelection.getLength() ) 495 { 496 uno::Reference< uno::XInterface> xSelection(aSec,uno::UNO_QUERY); 497 SvLBoxEntry* pEntry = find(xSelection); 498 if ( pEntry && !IsSelected(pEntry) ) 499 { 500 Select(pEntry, sal_True); 501 SetCurEntry(pEntry); 502 } 503 else if ( !pEntry ) 504 SelectAll(sal_False,sal_False); 505 } 506 else 507 { 508 const uno::Reference< report::XReportComponent >* pIter = aSelection.getConstArray(); 509 const uno::Reference< report::XReportComponent >* pEnd = pIter + aSelection.getLength(); 510 for (; pIter != pEnd; ++pIter) 511 { 512 SvLBoxEntry* pEntry = find(*pIter); 513 if ( pEntry && !IsSelected(pEntry) ) 514 { 515 Select(pEntry, sal_True); 516 SetCurEntry(pEntry); 517 } 518 } 519 } 520 m_pSelectionListener->unlock(); 521 } 522 // ----------------------------------------------------------------------------- 523 SvLBoxEntry* NavigatorTree::insertEntry(const ::rtl::OUString& _sName,SvLBoxEntry* _pParent,sal_uInt16 _nImageId,sal_uLong _nPosition,UserData* _pData) 524 { 525 SvLBoxEntry* pEntry = NULL; 526 if ( _nImageId ) 527 { 528 const Image aImage( m_aNavigatorImages.GetImage( _nImageId ) ); 529 pEntry = InsertEntry(_sName,aImage,aImage,_pParent,sal_False,_nPosition,_pData); 530 if ( pEntry ) 531 { 532 const Image aImageHC( m_aNavigatorImagesHC.GetImage( _nImageId ) ); 533 SetExpandedEntryBmp( pEntry, aImageHC, BMP_COLOR_HIGHCONTRAST ); 534 SetCollapsedEntryBmp( pEntry, aImageHC, BMP_COLOR_HIGHCONTRAST ); 535 } 536 } 537 else 538 pEntry = InsertEntry(_sName,_pParent,sal_False,_nPosition,_pData); 539 return pEntry; 540 } 541 // ----------------------------------------------------------------------------- 542 void NavigatorTree::traverseSection(const uno::Reference< report::XSection>& _xSection,SvLBoxEntry* _pParent,sal_uInt16 _nImageId,sal_uLong _nPosition) 543 { 544 SvLBoxEntry* pSection = insertEntry(_xSection->getName(),_pParent,_nImageId,_nPosition,new UserData(this,_xSection)); 545 const sal_Int32 nCount = _xSection->getCount(); 546 for (sal_Int32 i = 0; i < nCount; ++i) 547 { 548 uno::Reference< report::XReportComponent> xElement(_xSection->getByIndex(i),uno::UNO_QUERY_THROW); 549 OSL_ENSURE(xElement.is(),"Found report element which is NULL!"); 550 insertEntry(lcl_getName(xElement.get()),pSection,lcl_getImageId(xElement),LIST_APPEND,new UserData(this,xElement)); 551 uno::Reference< report::XReportDefinition> xSubReport(xElement,uno::UNO_QUERY); 552 if ( xSubReport.is() ) 553 { 554 m_pMasterReport = find(_xSection->getReportDefinition()); 555 reportdesign::OReportVisitor aSubVisitor(this); 556 aSubVisitor.start(xSubReport); 557 } 558 } 559 } 560 // ----------------------------------------------------------------------------- 561 void NavigatorTree::traverseFunctions(const uno::Reference< report::XFunctions>& _xFunctions,SvLBoxEntry* _pParent) 562 { 563 SvLBoxEntry* pFunctions = insertEntry(String(ModuleRes(RID_STR_FUNCTIONS)),_pParent,SID_RPT_NEW_FUNCTION,LIST_APPEND,new UserData(this,_xFunctions)); 564 const sal_Int32 nCount = _xFunctions->getCount(); 565 for (sal_Int32 i = 0; i< nCount; ++i) 566 { 567 uno::Reference< report::XFunction> xElement(_xFunctions->getByIndex(i),uno::UNO_QUERY); 568 insertEntry(xElement->getName(),pFunctions,SID_RPT_NEW_FUNCTION,LIST_APPEND,new UserData(this,xElement)); 569 } 570 } 571 // ----------------------------------------------------------------------------- 572 SvLBoxEntry* NavigatorTree::find(const uno::Reference< uno::XInterface >& _xContent) 573 { 574 SvLBoxEntry* pRet = NULL; 575 if ( _xContent.is() ) 576 { 577 SvLBoxEntry* pCurrent = First(); 578 while ( pCurrent ) 579 { 580 UserData* pData = static_cast<UserData*>(pCurrent->GetUserData()); 581 OSL_ENSURE(pData,"No UserData set an entry!"); 582 if ( pData->getContent() == _xContent ) 583 { 584 pRet = pCurrent; 585 break; 586 } 587 pCurrent = Next(pCurrent); 588 } 589 } 590 return pRet; 591 } 592 // ----------------------------------------------------------------------------- 593 // ITraverseReport 594 // ----------------------------------------------------------------------------- 595 void NavigatorTree::traverseReport(const uno::Reference< report::XReportDefinition>& _xReport) 596 { 597 insertEntry(_xReport->getName(),m_pMasterReport,SID_SELECT_REPORT,LIST_APPEND,new UserData(this,_xReport)); 598 } 599 // ----------------------------------------------------------------------------- 600 void NavigatorTree::traverseReportFunctions(const uno::Reference< report::XFunctions>& _xFunctions) 601 { 602 SvLBoxEntry* pReport = find(_xFunctions->getParent()); 603 traverseFunctions(_xFunctions,pReport); 604 } 605 // ----------------------------------------------------------------------------- 606 void NavigatorTree::traverseReportHeader(const uno::Reference< report::XSection>& _xSection) 607 { 608 SvLBoxEntry* pReport = find(_xSection->getReportDefinition()); 609 traverseSection(_xSection,pReport,SID_REPORTHEADERFOOTER); 610 } 611 // ----------------------------------------------------------------------------- 612 void NavigatorTree::traverseReportFooter(const uno::Reference< report::XSection>& _xSection) 613 { 614 SvLBoxEntry* pReport = find(_xSection->getReportDefinition()); 615 traverseSection(_xSection,pReport,SID_REPORTHEADERFOOTER); 616 } 617 // ----------------------------------------------------------------------------- 618 void NavigatorTree::traversePageHeader(const uno::Reference< report::XSection>& _xSection) 619 { 620 SvLBoxEntry* pReport = find(_xSection->getReportDefinition()); 621 traverseSection(_xSection,pReport,SID_PAGEHEADERFOOTER); 622 } 623 // ----------------------------------------------------------------------------- 624 void NavigatorTree::traversePageFooter(const uno::Reference< report::XSection>& _xSection) 625 { 626 SvLBoxEntry* pReport = find(_xSection->getReportDefinition()); 627 traverseSection(_xSection,pReport,SID_PAGEHEADERFOOTER); 628 } 629 // ----------------------------------------------------------------------------- 630 void NavigatorTree::traverseGroups(const uno::Reference< report::XGroups>& _xGroups) 631 { 632 SvLBoxEntry* pReport = find(_xGroups->getReportDefinition()); 633 insertEntry(String(ModuleRes(RID_STR_GROUPS)),pReport,SID_SORTINGANDGROUPING,LIST_APPEND,new UserData(this,_xGroups)); 634 } 635 // ----------------------------------------------------------------------------- 636 void NavigatorTree::traverseGroup(const uno::Reference< report::XGroup>& _xGroup) 637 { 638 uno::Reference< report::XGroups> xGroups(_xGroup->getParent(),uno::UNO_QUERY); 639 SvLBoxEntry* pGroups = find(xGroups); 640 OSL_ENSURE(pGroups,"No Groups inserted so far. Why!"); 641 insertEntry(_xGroup->getExpression(),pGroups,SID_GROUP,rptui::getPositionInIndexAccess(xGroups.get(),_xGroup),new UserData(this,_xGroup)); 642 } 643 // ----------------------------------------------------------------------------- 644 void NavigatorTree::traverseGroupFunctions(const uno::Reference< report::XFunctions>& _xFunctions) 645 { 646 SvLBoxEntry* pGroup = find(_xFunctions->getParent()); 647 traverseFunctions(_xFunctions,pGroup); 648 } 649 // ----------------------------------------------------------------------------- 650 void NavigatorTree::traverseGroupHeader(const uno::Reference< report::XSection>& _xSection) 651 { 652 SvLBoxEntry* pGroup = find(_xSection->getGroup()); 653 OSL_ENSURE(pGroup,"No group found"); 654 traverseSection(_xSection,pGroup,SID_GROUPHEADER,1); 655 } 656 // ----------------------------------------------------------------------------- 657 void NavigatorTree::traverseGroupFooter(const uno::Reference< report::XSection>& _xSection) 658 { 659 SvLBoxEntry* pGroup = find(_xSection->getGroup()); 660 OSL_ENSURE(pGroup,"No group found"); 661 traverseSection(_xSection,pGroup,SID_GROUPFOOTER); 662 } 663 // ----------------------------------------------------------------------------- 664 void NavigatorTree::traverseDetail(const uno::Reference< report::XSection>& _xSection) 665 { 666 uno::Reference< report::XReportDefinition> xReport = _xSection->getReportDefinition(); 667 SvLBoxEntry* pParent = find(xReport); 668 traverseSection(_xSection,pParent,SID_ICON_DETAIL); 669 } 670 // ----------------------------------------------------------------------------- 671 void NavigatorTree::_propertyChanged(const beans::PropertyChangeEvent& _rEvent) throw( uno::RuntimeException) 672 { 673 uno::Reference< report::XReportDefinition> xReport(_rEvent.Source,uno::UNO_QUERY); 674 if ( xReport.is() ) 675 { 676 sal_Bool bEnabled = sal_False; 677 _rEvent.NewValue >>= bEnabled; 678 if ( bEnabled ) 679 { 680 SvLBoxEntry* pParent = find(xReport); 681 if ( _rEvent.PropertyName == PROPERTY_REPORTHEADERON ) 682 { 683 sal_uLong nPos = xReport->getReportHeaderOn() ? 2 : 1; 684 traverseSection(xReport->getReportHeader(),pParent,SID_REPORTHEADERFOOTER,nPos); 685 } 686 else if ( _rEvent.PropertyName == PROPERTY_PAGEHEADERON ) 687 { 688 traverseSection(xReport->getPageHeader(),pParent, SID_PAGEHEADERFOOTER,1); 689 } 690 else if ( _rEvent.PropertyName == PROPERTY_PAGEFOOTERON ) 691 traverseSection(xReport->getPageFooter(),pParent, SID_PAGEHEADERFOOTER); 692 else if ( _rEvent.PropertyName == PROPERTY_REPORTFOOTERON ) 693 { 694 sal_uLong nPos = xReport->getPageFooterOn() ? (GetLevelChildCount(pParent) - 1) : LIST_APPEND; 695 traverseSection(xReport->getReportFooter(),pParent,SID_REPORTHEADERFOOTER,nPos); 696 } 697 } 698 } 699 } 700 // ----------------------------------------------------------------------------- 701 void NavigatorTree::_elementInserted( const container::ContainerEvent& _rEvent ) 702 { 703 SvLBoxEntry* pEntry = find(_rEvent.Source); 704 uno::Reference<beans::XPropertySet> xProp(_rEvent.Element,uno::UNO_QUERY_THROW); 705 ::rtl::OUString sName; 706 uno::Reference< beans::XPropertySetInfo> xInfo = xProp->getPropertySetInfo(); 707 if ( xInfo.is() ) 708 { 709 if ( xInfo->hasPropertyByName(PROPERTY_NAME) ) 710 xProp->getPropertyValue(PROPERTY_NAME) >>= sName; 711 else if ( xInfo->hasPropertyByName(PROPERTY_EXPRESSION) ) 712 xProp->getPropertyValue(PROPERTY_EXPRESSION) >>= sName; 713 } 714 uno::Reference< report::XGroup> xGroup(xProp,uno::UNO_QUERY); 715 if ( xGroup.is() ) 716 { 717 reportdesign::OReportVisitor aSubVisitor(this); 718 aSubVisitor.start(xGroup); 719 } 720 else 721 { 722 uno::Reference< report::XReportComponent> xElement(xProp,uno::UNO_QUERY); 723 if ( xProp.is() ) 724 sName = lcl_getName(xProp); 725 insertEntry(sName,pEntry,(!xElement.is() ? sal_uInt16(SID_RPT_NEW_FUNCTION) : lcl_getImageId(xElement)),LIST_APPEND,new UserData(this,xProp)); 726 } 727 if ( !IsExpanded(pEntry) ) 728 Expand(pEntry); 729 } 730 // ----------------------------------------------------------------------------- 731 void NavigatorTree::_elementRemoved( const container::ContainerEvent& _rEvent ) 732 { 733 uno::Reference<beans::XPropertySet> xProp(_rEvent.Element,uno::UNO_QUERY); 734 SvLBoxEntry* pEntry = find(xProp); 735 OSL_ENSURE(pEntry,"NavigatorTree::_elementRemoved: No Entry found!"); 736 737 if ( pEntry ) 738 { 739 SvLBoxEntry* pParent = GetParent(pEntry); 740 removeEntry(pEntry); 741 PaintEntry(pParent); 742 } 743 } 744 // ----------------------------------------------------------------------------- 745 void NavigatorTree::_elementReplaced( const container::ContainerEvent& _rEvent ) 746 { 747 uno::Reference<beans::XPropertySet> xProp(_rEvent.ReplacedElement,uno::UNO_QUERY); 748 SvLBoxEntry* pEntry = find(xProp); 749 if ( pEntry ) 750 { 751 UserData* pData = static_cast<UserData*>(pEntry->GetUserData()); 752 xProp.set(_rEvent.Element,uno::UNO_QUERY); 753 pData->setContent(xProp); 754 ::rtl::OUString sName; 755 xProp->getPropertyValue(PROPERTY_NAME) >>= sName; 756 SetEntryText(pEntry,sName); 757 } 758 } 759 // ----------------------------------------------------------------------------- 760 void NavigatorTree::_disposing(const lang::EventObject& _rSource)throw( uno::RuntimeException) 761 { 762 removeEntry(find(_rSource.Source)); 763 } 764 // ----------------------------------------------------------------------------- 765 void NavigatorTree::removeEntry(SvLBoxEntry* _pEntry,bool _bRemove) 766 { 767 if ( _pEntry ) 768 { 769 SvLBoxEntry* pChild = FirstChild(_pEntry); 770 while( pChild ) 771 { 772 removeEntry(pChild,false); 773 pChild = NextSibling(pChild); 774 } 775 delete static_cast<UserData*>(_pEntry->GetUserData()); 776 if ( _bRemove ) 777 GetModel()->Remove(_pEntry); 778 } 779 } 780 DBG_NAME(rpt_NavigatorTree_UserData) 781 // ----------------------------------------------------------------------------- 782 NavigatorTree::UserData::UserData(NavigatorTree* _pTree,const uno::Reference<uno::XInterface>& _xContent) 783 : OPropertyChangeListener(m_aMutex) 784 , OContainerListener(m_aMutex) 785 , m_xContent(_xContent) 786 , m_pTree(_pTree) 787 { 788 DBG_CTOR(rpt_NavigatorTree_UserData,NULL); 789 uno::Reference<beans::XPropertySet> xProp(m_xContent,uno::UNO_QUERY); 790 if ( xProp.is() ) 791 { 792 uno::Reference< beans::XPropertySetInfo> xInfo = xProp->getPropertySetInfo(); 793 if ( xInfo.is() ) 794 { 795 m_pListener = new ::comphelper::OPropertyChangeMultiplexer(this,xProp); 796 if ( xInfo->hasPropertyByName(PROPERTY_NAME) ) 797 m_pListener->addProperty(PROPERTY_NAME); 798 else if ( xInfo->hasPropertyByName(PROPERTY_EXPRESSION) ) 799 m_pListener->addProperty(PROPERTY_EXPRESSION); 800 if ( xInfo->hasPropertyByName(PROPERTY_DATAFIELD) ) 801 m_pListener->addProperty(PROPERTY_DATAFIELD); 802 if ( xInfo->hasPropertyByName(PROPERTY_LABEL) ) 803 m_pListener->addProperty(PROPERTY_LABEL); 804 if ( xInfo->hasPropertyByName(PROPERTY_HEADERON) ) 805 m_pListener->addProperty(PROPERTY_HEADERON); 806 if ( xInfo->hasPropertyByName(PROPERTY_FOOTERON) ) 807 m_pListener->addProperty(PROPERTY_FOOTERON); 808 } 809 } 810 uno::Reference< container::XContainer> xContainer(m_xContent,uno::UNO_QUERY); 811 if ( xContainer.is() ) 812 { 813 m_pContainerListener = new ::comphelper::OContainerListenerAdapter(this,xContainer); 814 } 815 } 816 // ----------------------------------------------------------------------------- 817 NavigatorTree::UserData::~UserData() 818 { 819 DBG_DTOR(rpt_NavigatorTree_UserData,NULL); 820 if ( m_pContainerListener.is() ) 821 m_pContainerListener->dispose(); 822 if ( m_pListener.is() ) 823 m_pListener->dispose(); 824 } 825 // ----------------------------------------------------------------------------- 826 // OPropertyChangeListener 827 void NavigatorTree::UserData::_propertyChanged(const beans::PropertyChangeEvent& _rEvent) throw( uno::RuntimeException) 828 { 829 SvLBoxEntry* pEntry = m_pTree->find(_rEvent.Source); 830 OSL_ENSURE(pEntry,"No entry could be found! Why not!"); 831 const bool bFooterOn = (PROPERTY_FOOTERON == _rEvent.PropertyName); 832 try 833 { 834 if ( bFooterOn || PROPERTY_HEADERON == _rEvent.PropertyName ) 835 { 836 sal_Int32 nPos = 1; 837 uno::Reference< report::XGroup> xGroup(_rEvent.Source,uno::UNO_QUERY); 838 ::std::mem_fun_t< sal_Bool,OGroupHelper> pIsOn = ::std::mem_fun(&OGroupHelper::getHeaderOn); 839 ::std::mem_fun_t< uno::Reference<report::XSection> ,OGroupHelper> pMemFunSection = ::std::mem_fun(&OGroupHelper::getHeader); 840 if ( bFooterOn ) 841 { 842 pIsOn = ::std::mem_fun(&OGroupHelper::getFooterOn); 843 pMemFunSection = ::std::mem_fun(&OGroupHelper::getFooter); 844 nPos = m_pTree->GetChildCount(pEntry) - 1; 845 } 846 847 OGroupHelper aGroupHelper(xGroup); 848 if ( pIsOn(&aGroupHelper) ) 849 { 850 if ( bFooterOn ) 851 ++nPos; 852 m_pTree->traverseSection(pMemFunSection(&aGroupHelper),pEntry,bFooterOn ? SID_GROUPFOOTER : SID_GROUPHEADER,nPos); 853 } 854 //else 855 // m_pTree->removeEntry(m_pTree->GetEntry(pEntry,nPos)); 856 } 857 else if ( PROPERTY_EXPRESSION == _rEvent.PropertyName) 858 { 859 ::rtl::OUString sNewName; 860 _rEvent.NewValue >>= sNewName; 861 m_pTree->SetEntryText(pEntry,sNewName); 862 } 863 else if ( PROPERTY_DATAFIELD == _rEvent.PropertyName || PROPERTY_LABEL == _rEvent.PropertyName || PROPERTY_NAME == _rEvent.PropertyName ) 864 { 865 uno::Reference<beans::XPropertySet> xProp(_rEvent.Source,uno::UNO_QUERY); 866 m_pTree->SetEntryText(pEntry,lcl_getName(xProp)); 867 } 868 } 869 catch(uno::Exception) 870 {} 871 } 872 // ----------------------------------------------------------------------------- 873 void NavigatorTree::UserData::_elementInserted( const container::ContainerEvent& _rEvent ) throw(uno::RuntimeException) 874 { 875 m_pTree->_elementInserted( _rEvent ); 876 } 877 // ----------------------------------------------------------------------------- 878 void NavigatorTree::UserData::_elementRemoved( const container::ContainerEvent& _rEvent ) throw(uno::RuntimeException) 879 { 880 m_pTree->_elementRemoved( _rEvent ); 881 } 882 // ----------------------------------------------------------------------------- 883 void NavigatorTree::UserData::_elementReplaced( const container::ContainerEvent& _rEvent ) throw(uno::RuntimeException) 884 { 885 m_pTree->_elementReplaced( _rEvent ); 886 } 887 // ----------------------------------------------------------------------------- 888 void NavigatorTree::UserData::_disposing(const lang::EventObject& _rSource) throw( uno::RuntimeException) 889 { 890 m_pTree->_disposing( _rSource ); 891 } 892 // ----------------------------------------------------------------------------- 893 // class ONavigatorImpl 894 // ----------------------------------------------------------------------------- 895 class ONavigatorImpl 896 { 897 ONavigatorImpl(const ONavigatorImpl&); 898 void operator =(const ONavigatorImpl&); 899 public: 900 ONavigatorImpl(OReportController& _rController,ONavigator* _pParent); 901 virtual ~ONavigatorImpl(); 902 903 uno::Reference< report::XReportDefinition> m_xReport; 904 ::rptui::OReportController& m_rController; 905 ::std::auto_ptr<NavigatorTree> m_pNavigatorTree; 906 }; 907 908 ONavigatorImpl::ONavigatorImpl(OReportController& _rController,ONavigator* _pParent) 909 :m_xReport(_rController.getReportDefinition()) 910 ,m_rController(_rController) 911 ,m_pNavigatorTree(new NavigatorTree(_pParent,_rController)) 912 { 913 reportdesign::OReportVisitor aVisitor(m_pNavigatorTree.get()); 914 aVisitor.start(m_xReport); 915 m_pNavigatorTree->Expand(m_pNavigatorTree->find(m_xReport)); 916 lang::EventObject aEvent(m_rController); 917 m_pNavigatorTree->_selectionChanged(aEvent); 918 } 919 //------------------------------------------------------------------------ 920 ONavigatorImpl::~ONavigatorImpl() 921 { 922 } 923 // ----------------------------------------------------------------------------- 924 DBG_NAME( rpt_ONavigator ) 925 const long STD_WIN_SIZE_X = 210; 926 const long STD_WIN_SIZE_Y = 280; 927 const long LISTBOX_BORDER = 2; 928 //======================================================================== 929 // class ONavigator 930 //======================================================================== 931 ONavigator::ONavigator( Window* _pParent 932 ,OReportController& _rController) 933 : FloatingWindow( _pParent, ModuleRes(RID_NAVIGATOR) ) 934 { 935 DBG_CTOR( rpt_ONavigator,NULL); 936 937 m_pImpl.reset(new ONavigatorImpl(_rController,this)); 938 939 //Size aSpace = LogicToPixel( Size( 7, 120), MAP_APPFONT ); 940 //Size aOutSize(nMaxTextWidth + m_aHeader.GetSizePixel().Width() + 3*aSpace.Width(),aSpace.Height()); 941 //SetMinOutputSizePixel(aOutSize); 942 //SetOutputSizePixel(aOutSize); 943 FreeResource(); 944 m_pImpl->m_pNavigatorTree->Show(); 945 m_pImpl->m_pNavigatorTree->GrabFocus(); 946 SetSizePixel(Size(STD_WIN_SIZE_X,STD_WIN_SIZE_Y)); 947 Show(); 948 949 } 950 // ----------------------------------------------------------------------------- 951 952 //------------------------------------------------------------------------ 953 ONavigator::~ONavigator() 954 { 955 DBG_DTOR( rpt_ONavigator,NULL); 956 } 957 //------------------------------------------------------------------------------ 958 void ONavigator::Resize() 959 { 960 FloatingWindow::Resize(); 961 962 Point aPos(GetPosPixel()); 963 Size aSize( GetOutputSizePixel() ); 964 965 ////////////////////////////////////////////////////////////////////// 966 967 // Groesse der form::ListBox anpassen 968 Point aLBPos( LISTBOX_BORDER, LISTBOX_BORDER ); 969 Size aLBSize( aSize ); 970 aLBSize.Width() -= (2*LISTBOX_BORDER); 971 aLBSize.Height() -= (2*LISTBOX_BORDER); 972 973 m_pImpl->m_pNavigatorTree->SetPosSizePixel( aLBPos, aLBSize ); 974 } 975 // ----------------------------------------------------------------------------- 976 // ----------------------------------------------------------------------------- 977 void ONavigator::GetFocus() 978 { 979 Window::GetFocus(); 980 if ( m_pImpl->m_pNavigatorTree.get() ) 981 m_pImpl->m_pNavigatorTree->GrabFocus(); 982 } 983 // ============================================================================= 984 } // rptui 985 // ============================================================================= 986 987