LibreOffice Module reportdesign (master)  1
propbrw.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  * Licensed to the Apache Software Foundation (ASF) under one or more
12  * contributor license agreements. See the NOTICE file distributed
13  * with this work for additional information regarding copyright
14  * ownership. The ASF licenses this file to you under the Apache
15  * License, Version 2.0 (the "License"); you may not use this file
16  * except in compliance with the License. You may obtain a copy of
17  * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 #include <memory>
20 #include <propbrw.hxx>
21 #include <RptObject.hxx>
22 #include <ReportController.hxx>
24 #include <strings.hrc>
25 #include <rptui_slotid.hrc>
26 #include <tools/diagnose_ex.h>
27 #include <com/sun/star/awt/XLayoutConstrains.hpp>
28 #include <com/sun/star/beans/PropertyValue.hpp>
29 #include <com/sun/star/frame/Frame.hpp>
30 #include <com/sun/star/inspection/ObjectInspector.hpp>
31 #include <com/sun/star/inspection/DefaultHelpProvider.hpp>
32 #include <com/sun/star/lang/XServiceInfo.hpp>
33 #include <com/sun/star/report/inspection/DefaultComponentInspectorModel.hpp>
34 #include <vcl/stdtext.hxx>
35 #include <vcl/weld.hxx>
36 #include <svx/svditer.hxx>
37 
40 #include <comphelper/types.hxx>
41 #include <comphelper/sequence.hxx>
42 #include <core_resource.hxx>
43 #include <SectionView.hxx>
44 #include <ReportSection.hxx>
45 #include <strings.hxx>
46 #include <DesignView.hxx>
47 #include <ViewsWindow.hxx>
48 #include <UITools.hxx>
49 #include <unotools/confignode.hxx>
50 
51 namespace rptui
52 {
53 #define STD_WIN_SIZE_X 300
54 #define STD_WIN_SIZE_Y 350
55 
56 using namespace ::com::sun::star;
57 using namespace uno;
58 using namespace lang;
59 using namespace frame;
60 using namespace beans;
61 using namespace container;
62 using namespace ::comphelper;
63 
64 
65 namespace
66 {
67  bool lcl_shouldEnableHelpSection( const Reference< XComponentContext >& _rxContext )
68  {
69  ::utl::OConfigurationTreeRoot aConfiguration(
71  _rxContext, "/org.openoffice.Office.ReportDesign/PropertyBrowser/" ) );
72 
73  bool bEnabled = false;
74  OSL_VERIFY( aConfiguration.getNodeValue( "DirectHelp" ) >>= bEnabled );
75  return bEnabled;
76  }
77 }
78 
79 
80 // PropBrw
81 
82 
83 PropBrw::PropBrw(const Reference< XComponentContext >& _xORB, vcl::Window* pParent, ODesignView* _pDesignView)
85  , m_xContentArea(VclPtr<VclVBox>::Create(this))
86  , m_xORB(_xORB)
87  , m_pDesignView(_pDesignView)
88  , m_pView( nullptr )
89  , m_bInitialStateChange(true)
90 {
91 
92  Size aPropWinSize(STD_WIN_SIZE_X,STD_WIN_SIZE_Y);
93  SetOutputSizePixel(aPropWinSize);
94 
95  // turn off WB_CLIPCHILDREN otherwise the bg won't extend "under"
96  // transparent children of the widget
97  m_xContentArea->SetControlBackground(m_xContentArea->GetSettings().GetStyleSettings().GetWindowColor());
98  m_xContentArea->SetBackground(m_xContentArea->GetControlBackground());
99  m_xContentArea->SetStyle(m_xContentArea->GetStyle() & ~WB_CLIPCHILDREN);
100  m_xContentArea->Show();
101 
102  try
103  {
104  // create a frame wrapper for myself
105  m_xMeAsFrame = Frame::create( m_xORB );
106  m_xMeAsFrame->initialize(VCLUnoHelper::GetInterface(m_xContentArea));
107  m_xMeAsFrame->setName("report property browser"); // change name!
108  }
109  catch (Exception&)
110  {
111  DBG_UNHANDLED_EXCEPTION("reportdesign");
112  OSL_FAIL("PropBrw::PropBrw: could not create/initialize my frame!");
113  m_xMeAsFrame.clear();
114  }
115 
116  if (m_xMeAsFrame.is())
117  {
118  try
119  {
120  ::cppu::ContextEntry_Init aHandlerContextInfo[] =
121  {
122  ::cppu::ContextEntry_Init( "ContextDocument", makeAny( m_pDesignView->getController().getModel() )),
123  ::cppu::ContextEntry_Init( "DialogParentWindow", makeAny( VCLUnoHelper::GetInterface ( this ) )),
124  ::cppu::ContextEntry_Init( "ActiveConnection", makeAny( m_pDesignView->getController().getConnection() ) ),
125  };
126  m_xInspectorContext.set(
127  ::cppu::createComponentContext( aHandlerContextInfo, SAL_N_ELEMENTS( aHandlerContextInfo ),
128  m_xORB ) );
129  // create a property browser controller
130  bool bEnableHelpSection = lcl_shouldEnableHelpSection( m_xORB );
131  Reference< inspection::XObjectInspectorModel> xInspectorModel( bEnableHelpSection
132  ? report::inspection::DefaultComponentInspectorModel::createWithHelpSection( m_xInspectorContext, 3, 8 )
133  : report::inspection::DefaultComponentInspectorModel::createDefault( m_xInspectorContext ) );
134 
135  m_xBrowserController = inspection::ObjectInspector::createWithModel(m_xInspectorContext, xInspectorModel);
136  if ( !m_xBrowserController.is() )
137  {
138  ShowServiceNotAvailableError(pParent ? pParent->GetFrameWeld() : nullptr, u"com.sun.star.inspection.ObjectInspector", true);
139  }
140  else
141  {
142  m_xBrowserController->attachFrame( Reference<XFrame>(m_xMeAsFrame, UNO_QUERY_THROW));
143  if ( bEnableHelpSection )
144  {
145  uno::Reference< inspection::XObjectInspector > xInspector( m_xBrowserController, uno::UNO_SET_THROW );
146  uno::Reference< inspection::XObjectInspectorUI > xInspectorUI( xInspector->getInspectorUI() );
147  inspection::DefaultHelpProvider::create( m_xInspectorContext, xInspectorUI );
148  }
149  }
150  }
151  catch (Exception&)
152  {
153  DBG_UNHANDLED_EXCEPTION("reportdesign");
154  OSL_FAIL("PropBrw::PropBrw: could not create/initialize the browser controller!");
155  try
156  {
157  ::comphelper::disposeComponent(m_xBrowserController);
158  }
159  catch(Exception&) { }
160  m_xBrowserController.clear();
161  }
162  }
163 
164  VclContainer::setLayoutAllocation(*m_xContentArea, Point(0, 0), aPropWinSize);
165  m_xContentArea->Show();
166 
168 }
169 
170 
171 PropBrw::~PropBrw()
172 {
173  disposeOnce();
174 }
175 
176 void PropBrw::dispose()
177 {
178  if (m_xBrowserController.is())
179  implDetachController();
180 
181  try
182  {
183  uno::Reference<container::XNameContainer> xName(m_xInspectorContext,uno::UNO_QUERY);
184  if ( xName.is() )
185  {
186  const OUString pProps[] = { OUString( "ContextDocument" )
187  , OUString( "DialogParentWindow" )
188  , OUString( "ActiveConnection" )};
189  for (const auto & i : pProps)
190  xName->removeByName(i);
191  }
192  }
193  catch(Exception&)
194  {}
195 
197  m_pDesignView.clear();
198  m_xContentArea.disposeAndClear();
200 }
201 
202 void PropBrw::setCurrentPage(const OUString& _sLastActivePage)
203 {
204  m_sLastActivePage = _sLastActivePage;
205 }
206 
207 
208 void PropBrw::implDetachController()
209 {
210  m_sLastActivePage = getCurrentPage();
211  implSetNewObject( );
212 
213  if ( m_xMeAsFrame.is() )
214  m_xMeAsFrame->setComponent( nullptr, nullptr );
215 
216  if ( m_xBrowserController.is() )
217  m_xBrowserController->attachFrame( nullptr );
218 
219  m_xMeAsFrame.clear();
220  m_xBrowserController.clear();
221 }
222 
223 OUString PropBrw::getCurrentPage() const
224 {
225  OUString sCurrentPage;
226  try
227  {
228  if ( m_xBrowserController.is() )
229  {
230  OSL_VERIFY( m_xBrowserController->getViewData() >>= sCurrentPage );
231  }
232 
233  if ( sCurrentPage.isEmpty() )
234  sCurrentPage = m_sLastActivePage;
235  }
236  catch( const Exception& )
237  {
238  TOOLS_WARN_EXCEPTION( "reportdesign", "PropBrw::getCurrentPage: caught an exception while retrieving the current page!" );
239  }
240  return sCurrentPage;
241 }
242 
243 bool PropBrw::Close()
244 {
245  m_xLastSection.clear();
246  // suspend the controller (it is allowed to veto)
247  if ( m_xMeAsFrame.is() )
248  {
249  try
250  {
251  Reference< XController > xController( m_xMeAsFrame->getController() );
252  if ( xController.is() && !xController->suspend( true ) )
253  return false;
254  }
255  catch( const Exception& )
256  {
257  TOOLS_WARN_EXCEPTION( "reportdesign", "FmPropBrw::Close: caught an exception while asking the controller!" );
258  }
259  }
260  implDetachController();
261 
262  m_pDesignView->getController().executeUnChecked(SID_PROPERTYBROWSER_LAST_PAGE,uno::Sequence< beans::PropertyValue>());
263 
264  return true;
265 }
266 
267 uno::Sequence< Reference<uno::XInterface> > PropBrw::CreateCompPropSet(const SdrMarkList& _rMarkList)
268 {
269  const size_t nMarkCount = _rMarkList.GetMarkCount();
270  ::std::vector< uno::Reference< uno::XInterface> > aSets;
271  aSets.reserve(nMarkCount);
272 
273  for(size_t i=0; i<nMarkCount; ++i)
274  {
275  SdrObject* pCurrent = _rMarkList.GetMark(i)->GetMarkedSdrObj();
276 
277  ::std::unique_ptr<SdrObjListIter> pGroupIterator;
278  if (pCurrent->IsGroupObject())
279  {
280  pGroupIterator.reset(new SdrObjListIter(pCurrent->GetSubList()));
281  pCurrent = pGroupIterator->IsMore() ? pGroupIterator->Next() : nullptr;
282  }
283 
284  while (pCurrent)
285  {
286  OObjectBase* pObj = dynamic_cast<OObjectBase*>(pCurrent);
287  if ( pObj )
288  aSets.push_back(CreateComponentPair(pObj));
289 
290  // next element
291  pCurrent = pGroupIterator && pGroupIterator->IsMore() ? pGroupIterator->Next() : nullptr;
292  }
293  }
294  return uno::Sequence< Reference<uno::XInterface> >(aSets.data(), aSets.size());
295 }
296 
297 void PropBrw::implSetNewObject( const uno::Sequence< Reference<uno::XInterface> >& _aObjects )
298 {
299  if ( m_xBrowserController.is() )
300  {
301  try
302  {
303  m_xBrowserController->inspect(uno::Sequence< Reference<uno::XInterface> >());
304  m_xBrowserController->inspect(_aObjects);
305  }
306  catch( const Exception& )
307  {
308  TOOLS_WARN_EXCEPTION( "reportdesign", "FmPropBrw::StateChanged: caught an exception while setting the initial page!" );
309  }
310  }
311  SetText( GetHeadlineName(_aObjects) );
312 }
313 
314 
315 OUString PropBrw::GetHeadlineName( const uno::Sequence< Reference<uno::XInterface> >& _aObjects )
316 {
317  OUString aName;
318  if ( !_aObjects.hasElements() )
319  {
320  aName = RptResId(RID_STR_BRWTITLE_NO_PROPERTIES);
321  }
322  else if ( _aObjects.getLength() == 1 ) // single selection
323  {
324  aName = RptResId(RID_STR_BRWTITLE_PROPERTIES);
325 
326  uno::Reference< container::XNameContainer > xNameCont(_aObjects[0],uno::UNO_QUERY);
327  Reference< lang::XServiceInfo > xServiceInfo( xNameCont->getByName("ReportComponent"), UNO_QUERY );
328  if ( xServiceInfo.is() )
329  {
330  TranslateId pResId;
331  if ( xServiceInfo->supportsService( SERVICE_FIXEDTEXT ) )
332  {
333  pResId = RID_STR_PROPTITLE_FIXEDTEXT;
334  }
335  else if ( xServiceInfo->supportsService( SERVICE_IMAGECONTROL ) )
336  {
337  pResId = RID_STR_PROPTITLE_IMAGECONTROL;
338  }
339  else if ( xServiceInfo->supportsService( SERVICE_FORMATTEDFIELD ) )
340  {
341  pResId = RID_STR_PROPTITLE_FORMATTED;
342  }
343  else if ( xServiceInfo->supportsService( SERVICE_SHAPE ) )
344  {
345  pResId = RID_STR_PROPTITLE_SHAPE;
346  }
347  else if ( xServiceInfo->supportsService( SERVICE_REPORTDEFINITION ) )
348  {
349  pResId = RID_STR_PROPTITLE_REPORT;
350  }
351  else if ( xServiceInfo->supportsService( SERVICE_SECTION ) )
352  {
353  pResId = RID_STR_PROPTITLE_SECTION;
354  }
355  else if ( xServiceInfo->supportsService( SERVICE_FUNCTION ) )
356  {
357  pResId = RID_STR_PROPTITLE_FUNCTION;
358  }
359  else if ( xServiceInfo->supportsService( SERVICE_GROUP ) )
360  {
361  pResId = RID_STR_PROPTITLE_GROUP;
362  }
363  else if ( xServiceInfo->supportsService( SERVICE_FIXEDLINE ) )
364  {
365  pResId = RID_STR_PROPTITLE_FIXEDLINE;
366  }
367  else
368  {
369  OSL_FAIL("Unknown service name!");
371  return aName;
372  }
373 
374  aName += RptResId(pResId);
375  }
376  }
377  else // multiselection
378  {
379  aName = RptResId(RID_STR_BRWTITLE_PROPERTIES)
380  + RptResId(RID_STR_BRWTITLE_MULTISELECT);
381  }
382 
383  return aName;
384 }
385 
386 uno::Reference< uno::XInterface> PropBrw::CreateComponentPair(OObjectBase* _pObj)
387 {
388  _pObj->initializeOle();
389  return CreateComponentPair(_pObj->getAwtComponent(),_pObj->getReportComponent());
390 }
391 
392 uno::Reference< uno::XInterface> PropBrw::CreateComponentPair(const uno::Reference< uno::XInterface>& _xFormComponent
393  ,const uno::Reference< uno::XInterface>& _xReportComponent)
394 {
395  uno::Reference< container::XNameContainer > xNameCont = ::comphelper::NameContainer_createInstance(cppu::UnoType<XInterface>::get());
396  xNameCont->insertByName("FormComponent",uno::makeAny(_xFormComponent));
397  xNameCont->insertByName("ReportComponent",uno::makeAny(_xReportComponent));
398  xNameCont->insertByName("RowSet",uno::makeAny(uno::Reference< uno::XInterface>(m_pDesignView->getController().getRowSet())));
399 
400  return xNameCont;
401 }
402 
403 ::Size PropBrw::getMinimumSize() const
404 {
405  ::Size aSize;
406  Reference< awt::XLayoutConstrains > xLayoutConstrains( m_xBrowserController, UNO_QUERY );
407  if( xLayoutConstrains.is() )
408  {
409  awt::Size aMinSize = xLayoutConstrains->getMinimumSize();
410  aMinSize.Height += 4;
411  aMinSize.Width += 4;
412  aSize.setHeight( aMinSize.Height );
413  aSize.setWidth( aMinSize.Width );
414  }
415  return aSize;
416 }
417 
418 void PropBrw::Update( OSectionView* pNewView )
419 {
420  try
421  {
422  if ( m_pView )
423  {
424  EndListening( *(m_pView->GetModel()) );
425  m_pView = nullptr;
426  }
427 
428  // set focus on initialization
429  if ( m_bInitialStateChange )
430  {
431  // if we're just newly created, we want to have the focus
432  PostUserEvent( LINK( this, PropBrw, OnAsyncGetFocus ), nullptr, true );
433  m_bInitialStateChange = false;
434  // and additionally, we want to show the page which was active during
435  // our previous incarnation
436  if ( !m_sLastActivePage.isEmpty() && m_xBrowserController.is() )
437  {
438  try
439  {
440  m_xBrowserController->restoreViewData( makeAny( m_sLastActivePage ) );
441  }
442  catch( const Exception& )
443  {
444  TOOLS_WARN_EXCEPTION( "reportdesign", "FmPropBrw::StateChanged: caught an exception while setting the initial page!" );
445  }
446  }
447  }
448 
449  if ( !pNewView )
450  return;
451  else
452  m_pView = pNewView;
453 
454  uno::Sequence< Reference<uno::XInterface> > aMarkedObjects;
455  OViewsWindow* pViews = m_pView->getReportSection()->getSectionWindow()->getViewsWindow();
456  const sal_uInt16 nSectionCount = pViews->getSectionCount();
457  for (sal_uInt16 i = 0; i < nSectionCount; ++i)
458  {
459  OSectionWindow* pSectionWindow = pViews->getSectionWindow(i);
460  if ( pSectionWindow )
461  {
462  const SdrMarkList& rMarkList = pSectionWindow->getReportSection().getSectionView().GetMarkedObjectList();
463  aMarkedObjects = ::comphelper::concatSequences(aMarkedObjects,CreateCompPropSet( rMarkList ));
464  }
465  }
466 
467  if ( aMarkedObjects.hasElements() ) // multiple selection
468  {
469  m_xLastSection.clear();
470  implSetNewObject( aMarkedObjects );
471  }
472  else if ( m_xLastSection != m_pView->getReportSection()->getSection() )
473  {
474  uno::Reference< uno::XInterface> xTemp(m_pView->getReportSection()->getSection());
475  m_xLastSection = xTemp;
476  uno::Reference< container::XNameContainer > xNameCont = ::comphelper::NameContainer_createInstance(cppu::UnoType<XInterface>::get() );
477  xNameCont->insertByName("ReportComponent",uno::makeAny(xTemp));
478  xTemp = xNameCont;
479 
480  implSetNewObject( uno::Sequence< uno::Reference< uno::XInterface> >(&xTemp,1) );
481  }
482 
483  StartListening( *(m_pView->GetModel()) );
484  }
485  catch ( Exception& )
486  {
487  TOOLS_WARN_EXCEPTION( "reportdesign", "PropBrw::Update" );
488  }
489 }
490 
491 void PropBrw::Update( const uno::Reference< uno::XInterface>& _xReportComponent)
492 {
493  if ( m_xLastSection == _xReportComponent )
494  return;
495 
496  m_xLastSection = _xReportComponent;
497  try
498  {
499  if ( m_pView )
500  {
501  EndListening( *(m_pView->GetModel()) );
502  m_pView = nullptr;
503  }
504 
505  uno::Reference< uno::XInterface> xTemp(CreateComponentPair(_xReportComponent,_xReportComponent));
506  implSetNewObject( uno::Sequence< uno::Reference< uno::XInterface> >(&xTemp,1) );
507  }
508  catch ( Exception& )
509  {
510  TOOLS_WARN_EXCEPTION( "reportdesign", "PropBrw::Update: Exception occurred!" );
511  }
512 }
513 
514 IMPL_LINK_NOARG( PropBrw, OnAsyncGetFocus, void*, void )
515 {
516  m_xContentArea->GrabFocus();
517 }
518 
519 void PropBrw::LoseFocus()
520 {
522  if (m_pDesignView)
523  m_pDesignView->getController().InvalidateAll();
524 }
525 
526 }
527 
528 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
#define SERVICE_FUNCTION
Definition: strings.hxx:26
static void setLayoutAllocation(vcl::Window &rWindow, const Point &rPos, const Size &rSize)
size_t GetMarkCount() const
Reference< XComponentContext > SAL_CALL createComponentContext(ContextEntry_Init const *pEntries, sal_Int32 nEntries, Reference< XComponentContext > const &xDelegate)
void setWidth(tools::Long nWidth)
#define SERVICE_IMAGECONTROL
Definition: strings.hxx:24
void notifySystemWindow(vcl::Window const *pWindow, vcl::Window *pToRegister, const ::comphelper::mem_fun1_t< TaskPaneList, vcl::Window * > &rMemFunc)
notifySystemWindow adds or remove the given window _pToRegister at the Systemwindow found when search...
Definition: UITools.cxx:857
void Create(SwFormatVertOrient &rItem, SvStream &rStrm, sal_uInt16 nVersionAbusedAsSize)
OSectionWindow * getSectionWindow(const sal_uInt16 _nPos) const
return the section at the given position
virtual void initializeOle()
Definition: RptObject.hxx:101
#define STD_WIN_SIZE_X
Definition: propbrw.cxx:53
SdrMark * GetMark(size_t nNum) const
#define SERVICE_GROUP
Definition: strings.hxx:31
virtual SdrObjList * GetSubList() const
const css::uno::Reference< css::report::XReportComponent > & getReportComponent() const
Definition: RptObject.hxx:105
static OConfigurationTreeRoot createWithComponentContext(const css::uno::Reference< css::uno::XComponentContext > &_rxContext, const OUString &_rPath, sal_Int32 _nDepth=-1, CREATION_MODE _eMode=CM_UPDATABLE)
weld::Window * GetFrameWeld() const
sal_Int64 WinBits
Reference< XController > xController
#define SAL_N_ELEMENTS(arr)
#define STD_WIN_SIZE_Y
Definition: propbrw.cxx:54
OReportSection & getReportSection()
SdrObject * GetMarkedSdrObj() const
#define SERVICE_FIXEDLINE
Definition: strings.hxx:29
#define DBG_UNHANDLED_EXCEPTION(...)
virtual void dispose() override
#define SERVICE_FORMATTEDFIELD
Definition: strings.hxx:23
#define TOOLS_WARN_EXCEPTION(area, stream)
OUString RptResId(TranslateId aId)
int i
#define SERVICE_SECTION
Definition: strings.hxx:30
css::uno::Any getNodeValue(const OUString &_rPath) const noexcept
const SdrMarkList & GetMarkedObjectList() const
float u
#define RID_STR_CLASS_FORMATTEDFIELD
Definition: strings.hxx:18
bool IsGroupObject() const
virtual css::uno::Reference< css::beans::XPropertySet > getAwtComponent()
Definition: RptObject.cxx:339
OViewsWindow * getViewsWindow()
virtual void LoseFocus()
IMPL_LINK_NOARG(PropBrw, OnAsyncGetFocus, void *, void)
Definition: propbrw.cxx:514
WinBits const WB_3DLOOK
WinBits const WB_SIZEABLE
PropBrw(PropBrw const &)=delete
#define SERVICE_REPORTDEFINITION
Definition: strings.hxx:27
OUString aName
mem_fun1_t< Tp, Arg > mem_fun(void(Tp::*f)(Arg))
void RemoveWindow(vcl::Window *pWindow)
void setHeight(tools::Long nHeight)
void AddWindow(vcl::Window *pWindow)
WinBits const WB_STDMODELESS
void ShowServiceNotAvailableError(weld::Widget *pParent, std::u16string_view rServiceName, bool bError)
static css::uno::Reference< css::awt::XWindow > GetInterface(vcl::Window *pWindow)
WinBits const WB_CLIPCHILDREN
#define SERVICE_SHAPE
Definition: strings.hxx:28
#define SERVICE_FIXEDTEXT
Definition: strings.hxx:22
sal_uInt16 getSectionCount() const
OSectionView & getSectionView() const
css::uno::Any SAL_CALL makeAny(const SharedUNOComponent< INTERFACE, COMPONENT > &value)