xref: /AOO41X/main/cui/source/customize/selector.cxx (revision 2ee96f1cdb99d49425d866b1ec4c5567f37285e6)
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_cui.hxx"
26 #include <vcl/help.hxx>
27 #include <vcl/msgbox.hxx>
28 #include <vcl/metric.hxx>
29 #include "selector.hxx"
30 #include <dialmgr.hxx>
31 #include "selector.hrc"
32 #include <svx/fmresids.hrc> // for RID_SVXIMG_...
33 #include <svx/dialmgr.hxx>  // for RID_SVXIMG_...
34 #include <cuires.hrc>
35 #include <sfx2/app.hxx>
36 #include <sfx2/msg.hxx>
37 #include <sfx2/msgpool.hxx>
38 #include <sfx2/minfitem.hxx>
39 #include <sfx2/objsh.hxx>
40 #include <sfx2/dispatch.hxx>
41 
42 #include <comphelper/documentinfo.hxx>
43 #include <comphelper/processfactory.hxx>
44 #include <comphelper/componentcontext.hxx>
45 
46 #include <com/sun/star/beans/XPropertySet.hpp>
47 #include <com/sun/star/script/provider/XScriptProviderSupplier.hpp>
48 #include <com/sun/star/script/provider/XScriptProvider.hpp>
49 #include <com/sun/star/script/browse/XBrowseNode.hpp>
50 #include <com/sun/star/script/browse/BrowseNodeTypes.hpp>
51 #include <com/sun/star/script/browse/XBrowseNodeFactory.hpp>
52 #include <com/sun/star/script/browse/BrowseNodeFactoryViewTypes.hpp>
53 #include <com/sun/star/frame/XModuleManager.hpp>
54 #include <com/sun/star/frame/XDesktop.hpp>
55 #include <com/sun/star/container/XEnumerationAccess.hpp>
56 #include <com/sun/star/container/XEnumeration.hpp>
57 #include <com/sun/star/document/XEmbeddedScripts.hpp>
58 #include <com/sun/star/document/XScriptInvocationContext.hpp>
59 #include <com/sun/star/frame/XDispatchInformationProvider.hpp>
60 #include <com/sun/star/frame/DispatchInformation.hpp>
61 #include <com/sun/star/container/XChild.hpp>
62 
63 using ::rtl::OUString;
64 using namespace ::com::sun::star;
65 using namespace ::com::sun::star::uno;
66 using namespace ::com::sun::star::script;
67 using namespace ::com::sun::star::frame;
68 using namespace ::com::sun::star::document;
69 using namespace ::com::sun::star::container;
70 
71 #define _SVSTDARR_STRINGSDTOR
72 #include <svl/svstdarr.hxx>
73 #include <svtools/imagemgr.hxx>
74 #include <tools/urlobj.hxx>
75 #include <tools/diagnose_ex.h>
76 
77 SV_IMPL_PTRARR(SvxGroupInfoArr_Impl, SvxGroupInfoPtr);
78 
79 /*
80  * The implementations of SvxConfigFunctionListBox_Impl and
81  * SvxConfigGroupListBox_Impl are copied from sfx2/source/dialog/cfg.cxx
82  */
SvxConfigFunctionListBox_Impl(Window * pParent,const ResId & rResId)83 SvxConfigFunctionListBox_Impl::SvxConfigFunctionListBox_Impl( Window* pParent, const ResId& rResId)
84     : SvTreeListBox( pParent, rResId )
85     , pCurEntry( 0 )
86     , m_pDraggingEntry( 0 )
87 {
88     SetStyle( GetStyle() | WB_CLIPCHILDREN | WB_HSCROLL | WB_SORT );
89     GetModel()->SetSortMode( SortAscending );
90 
91     // Timer f"ur die BallonHelp
92     aTimer.SetTimeout( 200 );
93     aTimer.SetTimeoutHdl(
94         LINK( this, SvxConfigFunctionListBox_Impl, TimerHdl ) );
95 }
96 
~SvxConfigFunctionListBox_Impl()97 SvxConfigFunctionListBox_Impl::~SvxConfigFunctionListBox_Impl()
98 {
99     ClearAll();
100 }
101 
GetLastSelectedEntry()102 SvLBoxEntry* SvxConfigFunctionListBox_Impl::GetLastSelectedEntry()
103 {
104     if ( m_pDraggingEntry != NULL )
105     {
106         return m_pDraggingEntry;
107     }
108     else
109     {
110         return FirstSelected();
111     }
112 }
113 
MouseMove(const MouseEvent & rMEvt)114 void SvxConfigFunctionListBox_Impl::MouseMove( const MouseEvent& rMEvt )
115 {
116     Point aMousePos = rMEvt.GetPosPixel();
117     pCurEntry = GetCurEntry();
118 
119     if ( pCurEntry && GetEntry( aMousePos ) == pCurEntry )
120         aTimer.Start();
121     else
122     {
123         Help::ShowBalloon( this, aMousePos, String() );
124         aTimer.Stop();
125     }
126 }
127 
128 
IMPL_LINK(SvxConfigFunctionListBox_Impl,TimerHdl,Timer *,EMPTYARG)129 IMPL_LINK( SvxConfigFunctionListBox_Impl, TimerHdl, Timer*, EMPTYARG)
130 {
131     aTimer.Stop();
132     Point aMousePos = GetPointerPosPixel();
133     SvLBoxEntry *pEntry = GetCurEntry();
134     if ( pEntry && GetEntry( aMousePos ) == pEntry && pCurEntry == pEntry )
135         Help::ShowBalloon( this, OutputToScreenPixel( aMousePos ), GetHelpText( pEntry ) );
136     return 0L;
137 }
138 
ClearAll()139 void SvxConfigFunctionListBox_Impl::ClearAll()
140 {
141     sal_uInt16 nCount = aArr.Count();
142     for ( sal_uInt16 i=0; i<nCount; i++ )
143     {
144         SvxGroupInfo_Impl *pData = aArr[i];
145         delete pData;
146     }
147 
148     aArr.Remove( 0, nCount );
149     Clear();
150 }
151 
GetHelpText(SvLBoxEntry * pEntry)152 String SvxConfigFunctionListBox_Impl::GetHelpText( SvLBoxEntry *pEntry )
153 {
154     // Information zum selektierten Entry aus den Userdaten holen
155     SvxGroupInfo_Impl *pInfo =
156         pEntry ? (SvxGroupInfo_Impl*) pEntry->GetUserData(): 0;
157 
158     if ( pInfo )
159     {
160         if ( pInfo->nKind == SVX_CFGFUNCTION_SLOT )
161         {
162             OUString aCmdURL( pInfo->sURL );
163 
164             OUString aHelpText = Application::GetHelp()->GetHelpText( aCmdURL, this );
165 
166             return aHelpText;
167         }
168         else if ( pInfo->nKind == SVX_CFGFUNCTION_SCRIPT )
169         {
170             return pInfo->sHelpText;
171         }
172     }
173 
174     return String();
175 }
176 
FunctionSelected()177 void SvxConfigFunctionListBox_Impl::FunctionSelected()
178 {
179     Help::ShowBalloon( this, Point(), String() );
180 }
181 
182 // drag and drop support
NotifyStartDrag(TransferDataContainer &,SvLBoxEntry * pEntry)183 DragDropMode SvxConfigFunctionListBox_Impl::NotifyStartDrag(
184     TransferDataContainer& /*aTransferDataContainer*/, SvLBoxEntry* pEntry )
185 {
186     m_pDraggingEntry = pEntry;
187     return GetDragDropMode();
188 }
189 
DragFinished(sal_Int8)190 void SvxConfigFunctionListBox_Impl::DragFinished( sal_Int8 /*nDropAction*/ )
191 {
192     m_pDraggingEntry = NULL;
193 }
194 
195 sal_Int8
AcceptDrop(const AcceptDropEvent &)196 SvxConfigFunctionListBox_Impl::AcceptDrop( const AcceptDropEvent& /*rEvt*/ )
197 {
198     return DND_ACTION_NONE;
199 }
200 
SvxConfigGroupListBox_Impl(Window * pParent,const ResId & rResId,bool _bShowSlots,const Reference<frame::XFrame> & xFrame)201 SvxConfigGroupListBox_Impl::SvxConfigGroupListBox_Impl(
202     Window* pParent, const ResId& rResId,
203     bool _bShowSlots, const Reference< frame::XFrame >& xFrame )
204         : SvTreeListBox( pParent, rResId )
205         , m_bShowSlots( _bShowSlots ),
206     m_hdImage(ResId(IMG_HARDDISK,*rResId.GetResMgr())),
207     m_hdImage_hc(ResId(IMG_HARDDISK_HC,*rResId.GetResMgr())),
208     m_libImage(ResId(IMG_LIB,*rResId.GetResMgr())),
209     m_libImage_hc(ResId(IMG_LIB_HC,*rResId.GetResMgr())),
210     m_macImage(ResId(IMG_MACRO,*rResId.GetResMgr())),
211     m_macImage_hc(ResId(IMG_MACRO_HC,*rResId.GetResMgr())),
212     m_docImage(ResId(IMG_DOC,*rResId.GetResMgr())),
213     m_docImage_hc(ResId(IMG_DOC_HC,*rResId.GetResMgr())),
214     m_sMyMacros(String(ResId(STR_MYMACROS,*rResId.GetResMgr()))),
215     m_sProdMacros(String(ResId(STR_PRODMACROS,*rResId.GetResMgr())))
216 {
217     FreeResource();
218 
219     if ( xFrame != NULL )
220     {
221         m_xFrame.set( xFrame );
222     }
223 
224     SetStyle( GetStyle() | WB_CLIPCHILDREN | WB_HSCROLL | WB_HASBUTTONS | WB_HASLINES | WB_HASLINESATROOT | WB_HASBUTTONSATROOT );
225 
226     ImageList aNavigatorImages( SVX_RES( RID_SVXIMGLIST_FMEXPL ) );
227 
228     SetNodeBitmaps(
229         aNavigatorImages.GetImage( RID_SVXIMG_COLLAPSEDNODE ),
230         aNavigatorImages.GetImage( RID_SVXIMG_EXPANDEDNODE ),
231         BMP_COLOR_NORMAL );
232 
233     SetNodeBitmaps(
234         aNavigatorImages.GetImage( RID_SVXIMG_COLLAPSEDNODE ),
235         aNavigatorImages.GetImage( RID_SVXIMG_EXPANDEDNODE ),
236         BMP_COLOR_HIGHCONTRAST );
237 }
238 
239 
~SvxConfigGroupListBox_Impl()240 SvxConfigGroupListBox_Impl::~SvxConfigGroupListBox_Impl()
241 {
242     ClearAll();
243 }
244 
ClearAll()245 void SvxConfigGroupListBox_Impl::ClearAll()
246 {
247     sal_uInt16 nCount = aArr.Count();
248     for ( sal_uInt16 i=0; i<nCount; i++ )
249     {
250         SvxGroupInfo_Impl *pData = aArr[i];
251         delete pData;
252     }
253 
254     aArr.Remove( 0, nCount );
255     Clear();
256 }
257 
258 //-----------------------------------------------
259 namespace
260 {
261     //...........................................
262     /** examines a component whether it supports XEmbeddedScripts, or provides access to such a
263         component by implementing XScriptInvocationContext.
264         @return
265             the model which supports the embedded scripts, or <NULL/> if it cannot find such a
266             model
267     */
lcl_getDocumentWithScripts_throw(const Reference<XInterface> & _rxComponent)268     static Reference< XModel > lcl_getDocumentWithScripts_throw( const Reference< XInterface >& _rxComponent )
269     {
270         Reference< XEmbeddedScripts > xScripts( _rxComponent, UNO_QUERY );
271         if ( !xScripts.is() )
272         {
273             Reference< XScriptInvocationContext > xContext( _rxComponent, UNO_QUERY );
274             if ( xContext.is() )
275                 xScripts.set( xContext->getScriptContainer(), UNO_QUERY );
276         }
277 
278         return Reference< XModel >( xScripts, UNO_QUERY );
279     }
280 
281     //...........................................
lcl_getScriptableDocument_nothrow(const Reference<XFrame> & _rxFrame)282     static Reference< XModel > lcl_getScriptableDocument_nothrow( const Reference< XFrame >& _rxFrame )
283     {
284         Reference< XModel > xDocument;
285 
286         // examine our associated frame
287         try
288         {
289             OSL_ENSURE( _rxFrame.is(), "lcl_getScriptableDocument_nothrow: you need to pass a frame to this dialog/tab page!" );
290             if ( _rxFrame.is() )
291             {
292                 // first try the model in the frame
293                 Reference< XController > xController( _rxFrame->getController(), UNO_SET_THROW );
294                 xDocument = lcl_getDocumentWithScripts_throw( xController->getModel() );
295 
296                 if ( !xDocument.is() )
297                 {
298                     // if there is no suitable document in the frame, try the controller
299                     xDocument = lcl_getDocumentWithScripts_throw( _rxFrame->getController() );
300                 }
301             }
302         }
303         catch( const Exception& )
304         {
305             DBG_UNHANDLED_EXCEPTION();
306         }
307 
308         return xDocument;
309     }
310 }
311 
fillScriptList(const Reference<browse::XBrowseNode> & _rxRootNode,SvLBoxEntry * _pParentEntry,bool _bCheapChildsOnDemand)312 void SvxConfigGroupListBox_Impl::fillScriptList( const Reference< browse::XBrowseNode >& _rxRootNode, SvLBoxEntry* _pParentEntry, bool _bCheapChildsOnDemand )
313 {
314     OSL_PRECOND( _rxRootNode.is(), "SvxConfigGroupListBox_Impl::fillScriptList: invalid root node!" );
315     if ( !_rxRootNode.is() )
316         return;
317 
318     try
319     {
320         if ( _rxRootNode->hasChildNodes() )
321         {
322             Sequence< Reference< browse::XBrowseNode > > children =
323                 _rxRootNode->getChildNodes();
324 
325             sal_Bool bIsRootNode = _rxRootNode->getName().equalsAscii("Root");
326 
327             /* To mimic current starbasic behaviour we
328             need to make sure that only the current document
329             is displayed in the config tree. Tests below
330             set the bDisplay flag to sal_False if the current
331             node is a first level child of the Root and is NOT
332             either the current document, user or share */
333             OUString sCurrentDocTitle;
334             Reference< XModel > xWorkingDocument = lcl_getScriptableDocument_nothrow( m_xFrame );
335             if ( xWorkingDocument.is() )
336             {
337                 sCurrentDocTitle = ::comphelper::DocumentInfo::getDocumentTitle( xWorkingDocument );
338             }
339 
340             for ( long n = 0; n < children.getLength(); n++ )
341             {
342                 Reference< browse::XBrowseNode >& theChild = children[n];
343                 //#139111# some crash reports show that it might be unset
344                 if ( !theChild.is() )
345                     continue;
346                 ::rtl::OUString sUIName = theChild->getName();
347                 sal_Bool bDisplay = sal_True;
348 
349                 if  (   bIsRootNode
350                     ||  ( m_bShowSlots && _pParentEntry && ( GetModel()->GetDepth( _pParentEntry ) == 0 ) )
351                         // if we show slots (as in the customize dialog)
352                         // then the user & share are added at depth=1
353                     )
354                 {
355                     if ( sUIName.equalsAscii( "user" ) )
356                     {
357                         sUIName = m_sMyMacros;
358                         bIsRootNode = sal_True;
359                     }
360                     else if ( sUIName.equalsAscii( "share" ) )
361                     {
362                         sUIName = m_sProdMacros;
363                         bIsRootNode = sal_True;
364                     }
365                     else if ( !sUIName.equals( sCurrentDocTitle ) )
366                     {
367                         bDisplay = sal_False;
368                     }
369                 }
370 
371                 if ( !bDisplay )
372                     continue;
373 
374                 if ( children[n]->getType() == browse::BrowseNodeTypes::SCRIPT )
375                     continue;
376 
377                 SvLBoxEntry* pNewEntry = InsertEntry( sUIName, _pParentEntry );
378 
379                 ::comphelper::ComponentContext aContext( ::comphelper::getProcessServiceFactory() );
380                 Image aImage = GetImage( theChild, aContext.getUNOContext(), bIsRootNode, BMP_COLOR_NORMAL );
381                 SetExpandedEntryBmp( pNewEntry, aImage, BMP_COLOR_NORMAL );
382                 SetCollapsedEntryBmp( pNewEntry, aImage, BMP_COLOR_NORMAL );
383 
384                 aImage = GetImage( theChild, aContext.getUNOContext(), bIsRootNode, BMP_COLOR_HIGHCONTRAST );
385                 SetExpandedEntryBmp( pNewEntry, aImage, BMP_COLOR_HIGHCONTRAST );
386                 SetCollapsedEntryBmp( pNewEntry, aImage, BMP_COLOR_HIGHCONTRAST );
387 
388                 SvxGroupInfo_Impl* pInfo =
389                     new SvxGroupInfo_Impl( SVX_CFGGROUP_SCRIPTCONTAINER, 0, theChild );
390                 pNewEntry->SetUserData( pInfo );
391                 aArr.Insert( pInfo, aArr.Count() );
392 
393                 if ( _bCheapChildsOnDemand )
394                 {
395                     /* i30923 - Would be nice if there was a better
396                     * way to determine if a basic lib had children
397                     * without having to ask for them (which forces
398                     * the library to be loaded */
399                     pNewEntry->EnableChildsOnDemand( sal_True );
400                 }
401                 else
402                 {
403                     // if there are granchildren we're interested in, display the '+' before
404                     // the entry, but do not yet expand
405                     Sequence< Reference< browse::XBrowseNode > > grandchildren =
406                         children[n]->getChildNodes();
407 
408                     for ( sal_Int32 m = 0; m < grandchildren.getLength(); m++ )
409                     {
410                         if ( grandchildren[m]->getType() == browse::BrowseNodeTypes::CONTAINER )
411                         {
412                             pNewEntry->EnableChildsOnDemand( sal_True );
413                             break;
414                         }
415                     }
416                 }
417             }
418         }
419     }
420     catch (const Exception&)
421     {
422         DBG_UNHANDLED_EXCEPTION();
423     }
424 }
425 
Init()426 void SvxConfigGroupListBox_Impl::Init()
427 {
428     SetUpdateMode(sal_False);
429     ClearAll();
430 
431     Reference< XComponentContext > xContext;
432     Reference < beans::XPropertySet > xProps(
433         ::comphelper::getProcessServiceFactory(), UNO_QUERY_THROW );
434 
435     xContext.set( xProps->getPropertyValue(
436         rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DefaultContext" ))),
437         UNO_QUERY );
438 
439     // are we showing builtin commands?
440     if ( m_bShowSlots && xContext.is() && m_xFrame.is() )
441     {
442         Reference< lang::XMultiComponentFactory > xMCF =
443             xContext->getServiceManager();
444 
445         Reference< frame::XDispatchInformationProvider > xDIP(
446             m_xFrame, UNO_QUERY );
447 
448         Reference< ::com::sun::star::frame::XModuleManager >
449             xModuleManager( xMCF->createInstanceWithContext(
450                 OUString::createFromAscii(
451                     "com.sun.star.frame.ModuleManager" ),
452                 xContext ),
453             UNO_QUERY );
454 
455         OUString aModuleId;
456         try{
457             aModuleId = xModuleManager->identify( m_xFrame );
458         }catch(const uno::Exception&)
459             { aModuleId = ::rtl::OUString(); }
460 
461         Reference< container::XNameAccess > xNameAccess(
462             xMCF->createInstanceWithContext(
463                 OUString::createFromAscii(
464                     "com.sun.star.frame.UICommandDescription" ),
465                 xContext ),
466             UNO_QUERY );
467 
468         if ( xNameAccess.is() )
469         {
470             xNameAccess->getByName( aModuleId ) >>= m_xModuleCommands;
471         }
472 
473         Reference< container::XNameAccess > xAllCategories(
474             xMCF->createInstanceWithContext(
475                 OUString::createFromAscii(
476                     "com.sun.star.ui.UICategoryDescription" ),
477                 xContext ),
478             UNO_QUERY );
479 
480         Reference< container::XNameAccess > xModuleCategories;
481         if ( xAllCategories.is() )
482         {
483             if ( aModuleId.getLength() != 0 )
484             {
485                 try
486                 {
487                     xModuleCategories = Reference< container::XNameAccess >(
488                         xAllCategories->getByName( aModuleId ), UNO_QUERY );
489                 }
490                 catch ( container::NoSuchElementException& )
491                 {
492                 }
493             }
494 
495             if ( !xModuleCategories.is() )
496             {
497                 xModuleCategories = xAllCategories;
498             }
499         }
500 
501         if ( xModuleCategories.is() )
502         {
503             Sequence< sal_Int16 > gids =
504                 xDIP->getSupportedCommandGroups();
505 
506             for ( sal_Int32 i = 0; i < gids.getLength(); i++ )
507             {
508                 Sequence< frame::DispatchInformation > commands;
509                 try
510                 {
511                     commands =
512                         xDIP->getConfigurableDispatchInformation( gids[i] );
513                 }
514                 catch ( container::NoSuchElementException& )
515                 {
516                     continue;
517                 }
518 
519                 if ( commands.getLength() == 0 )
520                 {
521                     continue;
522                 }
523 
524                 sal_Int32 gid = gids[i];
525                 OUString idx = OUString::valueOf( gid );
526                 OUString group = idx;
527                 try
528                 {
529                     xModuleCategories->getByName( idx ) >>= group;
530                 }
531                 catch ( container::NoSuchElementException& )
532                 {
533                 }
534 
535                 SvLBoxEntry *pEntry = InsertEntry( group, NULL );
536 
537                 SvxGroupInfo_Impl *pInfo =
538                     new SvxGroupInfo_Impl( SVX_CFGGROUP_FUNCTION, gids[i] );
539                 aArr.Insert( pInfo, aArr.Count() );
540 
541                 pEntry->SetUserData( pInfo );
542             }
543         }
544     }
545 
546     if ( xContext.is() )
547     {
548         // Add Scripting Framework entries
549         Reference< browse::XBrowseNode > rootNode;
550         Reference< XComponentContext> xCtx;
551 
552         try
553         {
554             Reference < beans::XPropertySet > _xProps(
555                 ::comphelper::getProcessServiceFactory(), UNO_QUERY_THROW );
556             xCtx.set( _xProps->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DefaultContext" ))), UNO_QUERY_THROW );
557             Reference< browse::XBrowseNodeFactory > xFac( xCtx->getValueByName(
558                 OUString::createFromAscii( "/singletons/com.sun.star.script.browse.theBrowseNodeFactory") ), UNO_QUERY_THROW );
559             rootNode.set( xFac->createView( browse::BrowseNodeFactoryViewTypes::MACROSELECTOR ) );
560         }
561         catch( const Exception& )
562         {
563             DBG_UNHANDLED_EXCEPTION();
564         }
565 
566         if ( rootNode.is() )
567         {
568             if ( m_bShowSlots )
569             {
570                 SvxGroupInfo_Impl *pInfo =
571                     new SvxGroupInfo_Impl( SVX_CFGGROUP_SCRIPTCONTAINER, 0, rootNode );
572 
573                 String aTitle =
574                     String( CUI_RES( STR_SELECTOR_MACROS ) );
575 
576                 SvLBoxEntry *pNewEntry = InsertEntry( aTitle, NULL );
577                 pNewEntry->SetUserData( pInfo );
578                 pNewEntry->EnableChildsOnDemand( sal_True );
579                 aArr.Insert( pInfo, aArr.Count() );
580             }
581             else
582             {
583                 fillScriptList( rootNode, NULL, false );
584             }
585         }
586     }
587     MakeVisible( GetEntry( 0,0 ) );
588     SetUpdateMode( sal_True );
589 }
590 
GetImage(Reference<browse::XBrowseNode> node,Reference<XComponentContext> xCtx,bool bIsRootNode,bool bHighContrast)591 Image SvxConfigGroupListBox_Impl::GetImage( Reference< browse::XBrowseNode > node, Reference< XComponentContext > xCtx, bool bIsRootNode, bool bHighContrast )
592 {
593     Image aImage;
594     if ( bIsRootNode )
595     {
596         if ( node->getName().equalsAscii( "user" ) || node->getName().equalsAscii( "share" ) )
597         {
598             if( bHighContrast == BMP_COLOR_NORMAL )
599                 aImage = m_hdImage;
600             else
601                 aImage = m_hdImage_hc;
602         }
603         else
604         {
605             OUString factoryURL;
606             OUString nodeName = node->getName();
607             Reference<XInterface> xDocumentModel = getDocumentModel(xCtx, nodeName );
608             if ( xDocumentModel.is() )
609             {
610                 Reference< ::com::sun::star::frame::XModuleManager >
611                     xModuleManager(
612                         xCtx->getServiceManager()
613                             ->createInstanceWithContext(
614                                 OUString::createFromAscii("com.sun.star.frame.ModuleManager"),
615                                 xCtx ),
616                             UNO_QUERY_THROW );
617                 Reference<container::XNameAccess> xModuleConfig(
618                     xModuleManager, UNO_QUERY_THROW );
619                 // get the long name of the document:
620                 OUString appModule( xModuleManager->identify(
621                                     xDocumentModel ) );
622                 Sequence<beans::PropertyValue> moduleDescr;
623                 Any aAny = xModuleConfig->getByName(appModule);
624                 if( sal_True != ( aAny >>= moduleDescr ) )
625                 {
626                     throw RuntimeException(OUString::createFromAscii("SFTreeListBox::Init: failed to get PropertyValue"), Reference< XInterface >());
627                 }
628                 beans::PropertyValue const * pmoduleDescr =
629                     moduleDescr.getConstArray();
630                 for ( sal_Int32 pos = moduleDescr.getLength(); pos--; )
631                 {
632                     if (pmoduleDescr[ pos ].Name.equalsAsciiL(
633                             RTL_CONSTASCII_STRINGPARAM(
634                                 "ooSetupFactoryEmptyDocumentURL") ))
635                     {
636                         pmoduleDescr[ pos ].Value >>= factoryURL;
637                         break;
638                     }
639                 }
640             }
641             if( factoryURL.getLength() > 0 )
642             {
643                 if( bHighContrast == BMP_COLOR_NORMAL )
644                     aImage = SvFileInformationManager::GetFileImage(
645                         INetURLObject(factoryURL), false,
646                         BMP_COLOR_NORMAL );
647                 else
648                     aImage = SvFileInformationManager::GetFileImage(
649                         INetURLObject(factoryURL), false,
650                         BMP_COLOR_HIGHCONTRAST );
651             }
652             else
653             {
654                 if( bHighContrast == BMP_COLOR_NORMAL )
655                     aImage = m_docImage;
656                 else
657                     aImage = m_docImage_hc;
658             }
659         }
660     }
661     else
662     {
663         if( node->getType() == browse::BrowseNodeTypes::SCRIPT )
664         {
665             if( bHighContrast == BMP_COLOR_NORMAL )
666                 aImage = m_macImage;
667             else
668                 aImage = m_macImage_hc;
669         }
670         else
671         {
672             if( bHighContrast == BMP_COLOR_NORMAL )
673                 aImage = m_libImage;
674             else
675                 aImage = m_libImage_hc;
676         }
677     }
678     return aImage;
679 }
680 
681 Reference< XInterface  >
getDocumentModel(Reference<XComponentContext> & xCtx,OUString & docName)682 SvxConfigGroupListBox_Impl::getDocumentModel(
683     Reference< XComponentContext >& xCtx, OUString& docName )
684 {
685     Reference< XInterface > xModel;
686     Reference< lang::XMultiComponentFactory > mcf =
687             xCtx->getServiceManager();
688     Reference< frame::XDesktop > desktop (
689         mcf->createInstanceWithContext(
690             OUString::createFromAscii("com.sun.star.frame.Desktop"),                 xCtx ),
691             UNO_QUERY );
692 
693     Reference< container::XEnumerationAccess > componentsAccess =
694         desktop->getComponents();
695     Reference< container::XEnumeration > components =
696         componentsAccess->createEnumeration();
697     while (components->hasMoreElements())
698     {
699         Reference< frame::XModel > model(
700             components->nextElement(), UNO_QUERY );
701         if ( model.is() )
702         {
703             OUString sTdocUrl = ::comphelper::DocumentInfo::getDocumentTitle( model );
704             if( sTdocUrl.equals( docName ) )
705             {
706                 xModel = model;
707                 break;
708             }
709         }
710     }
711     return xModel;
712 }
713 
GroupSelected()714 void SvxConfigGroupListBox_Impl::GroupSelected()
715 {
716     SvLBoxEntry *pEntry = FirstSelected();
717     SvxGroupInfo_Impl *pInfo = (SvxGroupInfo_Impl*) pEntry->GetUserData();
718     pFunctionListBox->SetUpdateMode(sal_False);
719     pFunctionListBox->ClearAll();
720     if ( pInfo->nKind != SVX_CFGGROUP_FUNCTION &&
721              pInfo->nKind != SVX_CFGGROUP_SCRIPTCONTAINER )
722     {
723         pFunctionListBox->SetUpdateMode(sal_True);
724         return;
725     }
726 
727     switch ( pInfo->nKind )
728     {
729         case SVX_CFGGROUP_FUNCTION :
730         {
731             SvLBoxEntry *_pEntry = FirstSelected();
732             if ( _pEntry != NULL )
733             {
734                 SvxGroupInfo_Impl *_pInfo =
735                     (SvxGroupInfo_Impl*) _pEntry->GetUserData();
736 
737                 Reference< frame::XDispatchInformationProvider > xDIP(
738                     m_xFrame, UNO_QUERY );
739 
740                 Sequence< frame::DispatchInformation > commands;
741                 try
742                 {
743                     commands = xDIP->getConfigurableDispatchInformation(
744                         _pInfo->nOrd );
745                 }
746                 catch ( container::NoSuchElementException& )
747                 {
748                 }
749 
750                 for ( sal_Int32 i = 0; i < commands.getLength(); i++ )
751                 {
752                     if ( commands[i].Command.getLength() == 0 )
753                     {
754                         continue;
755                     }
756 
757                     Image aImage;
758 
759                     OUString aCmdURL( commands[i].Command );
760 
761                     if ( m_pImageProvider )
762                     {
763                         aImage = m_pImageProvider->GetImage( aCmdURL );
764                     }
765 
766                     OUString aLabel;
767                     try
768                     {
769                         Any a = m_xModuleCommands->getByName( aCmdURL );
770                         Sequence< beans::PropertyValue > aPropSeq;
771 
772                         if ( a >>= aPropSeq )
773                         {
774                             for ( sal_Int32 k = 0; k < aPropSeq.getLength(); k++ )
775                             {
776                                 if ( aPropSeq[k].Name.equalsAscii( "Name" ) )
777                                 {
778                                     aPropSeq[k].Value >>= aLabel;
779                                     break;
780                                 }
781                             }
782                         }
783                     }
784                     catch ( container::NoSuchElementException& )
785                     {
786                     }
787 
788                     if ( aLabel.getLength() == 0 )
789                     {
790                         aLabel = commands[i].Command;
791                     }
792 
793                     SvLBoxEntry* pFuncEntry = NULL;
794                     if ( !!aImage )
795                     {
796                         pFuncEntry = pFunctionListBox->InsertEntry(
797                             aLabel, aImage, aImage );
798                     }
799                     else
800                     {
801                         pFuncEntry = pFunctionListBox->InsertEntry(
802                             aLabel, NULL );
803                     }
804 
805                     SvxGroupInfo_Impl *_pGroupInfo = new SvxGroupInfo_Impl(
806                         SVX_CFGFUNCTION_SLOT, 123, aCmdURL, ::rtl::OUString() );
807 
808                     pFunctionListBox->aArr.Insert(
809                         _pGroupInfo, pFunctionListBox->aArr.Count() );
810 
811                     pFuncEntry->SetUserData( _pGroupInfo );
812                 }
813             }
814             break;
815         }
816 
817         case SVX_CFGGROUP_SCRIPTCONTAINER:
818         {
819             Reference< browse::XBrowseNode > rootNode( pInfo->xBrowseNode );
820 
821             try {
822                 if ( rootNode->hasChildNodes() )
823                 {
824                     Sequence< Reference< browse::XBrowseNode > > children =
825                         rootNode->getChildNodes();
826 
827                     for ( long n = 0; n < children.getLength(); n++ )
828                     {
829                         if (!children[n].is())
830                             continue;
831                         if (children[n]->getType() == browse::BrowseNodeTypes::SCRIPT)
832                         {
833                             OUString uri;
834                             OUString description;
835 
836                             Reference < beans::XPropertySet >xPropSet( children[n], UNO_QUERY );
837                             if (!xPropSet.is())
838                             {
839                                 continue;
840                             }
841 
842                             Any value =
843                                 xPropSet->getPropertyValue( String::CreateFromAscii( "URI" ) );
844                             value >>= uri;
845 
846                             try
847                             {
848                                 value = xPropSet->getPropertyValue(
849                                     String::CreateFromAscii( "Description" ) );
850                                 value >>= description;
851                             }
852                             catch (Exception &) {
853                                 // do nothing, the description will be empty
854                             }
855 
856                             SvxGroupInfo_Impl* _pGroupInfo =
857                                 new SvxGroupInfo_Impl(
858                                     SVX_CFGFUNCTION_SCRIPT, 123, uri, description );
859 
860                             Image aImage = GetImage( children[n], Reference< XComponentContext >(), sal_False, BMP_COLOR_NORMAL );
861                             SvLBoxEntry* pNewEntry =
862                                 pFunctionListBox->InsertEntry( children[n]->getName(), NULL );
863                             pFunctionListBox->SetExpandedEntryBmp(pNewEntry, aImage, BMP_COLOR_NORMAL);
864                             pFunctionListBox->SetCollapsedEntryBmp(pNewEntry, aImage, BMP_COLOR_NORMAL);
865                             aImage = GetImage( children[n], Reference< XComponentContext >(), sal_False, BMP_COLOR_HIGHCONTRAST );
866                             pFunctionListBox->SetExpandedEntryBmp(pNewEntry, aImage, BMP_COLOR_HIGHCONTRAST);
867                             pFunctionListBox->SetCollapsedEntryBmp(pNewEntry, aImage, BMP_COLOR_HIGHCONTRAST);
868 
869                             pNewEntry->SetUserData( _pGroupInfo );
870 
871                             pFunctionListBox->aArr.Insert(
872                                 _pGroupInfo, pFunctionListBox->aArr.Count() );
873 
874                         }
875                     }
876                 }
877             }
878             catch (const Exception&)
879             {
880                 DBG_UNHANDLED_EXCEPTION();
881             }
882             break;
883         }
884 
885         default:
886         {
887             return;
888         }
889     }
890 
891     if ( pFunctionListBox->GetEntryCount() )
892         pFunctionListBox->Select( pFunctionListBox->GetEntry( 0, 0 ) );
893 
894     pFunctionListBox->SetUpdateMode(sal_True);
895 }
896 
Expand(SvLBoxEntry * pParent)897 sal_Bool SvxConfigGroupListBox_Impl::Expand( SvLBoxEntry* pParent )
898 {
899     sal_Bool bRet = SvTreeListBox::Expand( pParent );
900     if ( bRet )
901     {
902         // Wieviele Entries k"onnen angezeigt werden ?
903         sal_uLong nEntries = GetOutputSizePixel().Height() / GetEntryHeight();
904 
905         // Wieviele Kinder sollen angezeigt werden ?
906         sal_uLong nChildCount = GetVisibleChildCount( pParent );
907 
908         // Passen alle Kinder und der parent gleichzeitig in die View ?
909         if ( nChildCount+1 > nEntries )
910         {
911             // Wenn nicht, wenigstens parent ganz nach oben schieben
912             MakeVisible( pParent, sal_True );
913         }
914         else
915         {
916             // An welcher relativen ViewPosition steht der aufzuklappende parent
917             SvLBoxEntry *pEntry = GetFirstEntryInView();
918             sal_uLong nParentPos = 0;
919             while ( pEntry && pEntry != pParent )
920             {
921                 nParentPos++;
922                 pEntry = GetNextEntryInView( pEntry );
923             }
924 
925             // Ist unter dem parent noch genug Platz f"ur alle Kinder ?
926             if ( nParentPos + nChildCount + 1 > nEntries )
927                 ScrollOutputArea( (short)( nEntries - ( nParentPos + nChildCount + 1 ) ) );
928         }
929     }
930 
931     return bRet;
932 }
933 
RequestingChilds(SvLBoxEntry * pEntry)934 void SvxConfigGroupListBox_Impl::RequestingChilds( SvLBoxEntry *pEntry )
935 {
936     SvxGroupInfo_Impl *pInfo = (SvxGroupInfo_Impl*) pEntry->GetUserData();
937     pInfo->bWasOpened = sal_True;
938     switch ( pInfo->nKind )
939     {
940         case SVX_CFGGROUP_SCRIPTCONTAINER:
941         {
942             if ( !GetChildCount( pEntry ) )
943             {
944                 Reference< browse::XBrowseNode > rootNode( pInfo->xBrowseNode ) ;
945                 fillScriptList( rootNode, pEntry, true /* i30923 */ );
946             }
947             break;
948         }
949 
950         default:
951             DBG_ERROR( "Falscher Gruppentyp!" );
952             break;
953     }
954 }
955 
956 /*
957  * Implementation of SvxScriptSelectorDialog
958  *
959  * This dialog is used for selecting Slot API commands
960  * and Scripting Framework Scripts.
961  */
962 
SvxScriptSelectorDialog(Window * pParent,sal_Bool bShowSlots,const Reference<frame::XFrame> & xFrame)963 SvxScriptSelectorDialog::SvxScriptSelectorDialog(
964   Window* pParent, sal_Bool bShowSlots, const Reference< frame::XFrame >& xFrame )
965     :
966     ModelessDialog( pParent, CUI_RES( RID_DLG_SCRIPTSELECTOR ) ),
967     aDialogDescription( this, CUI_RES( TXT_SELECTOR_DIALOG_DESCRIPTION ) ),
968     aGroupText( this, CUI_RES( TXT_SELECTOR_CATEGORIES ) ),
969     aCategories( this, CUI_RES( BOX_SELECTOR_CATEGORIES ), bShowSlots, xFrame ),
970     aFunctionText( this, CUI_RES( TXT_SELECTOR_COMMANDS ) ),
971     aCommands( this, CUI_RES( BOX_SELECTOR_COMMANDS ) ),
972     aOKButton( this, CUI_RES( BTN_SELECTOR_OK ) ),
973     aCancelButton( this, CUI_RES( BTN_SELECTOR_CANCEL ) ),
974     aHelpButton( this, CUI_RES( BTN_SELECTOR_HELP ) ),
975     aDescription( this, CUI_RES( GRP_SELECTOR_DESCRIPTION ) ),
976     aDescriptionText( this, CUI_RES( TXT_SELECTOR_DESCRIPTION ) ),
977     m_bShowSlots( bShowSlots )
978 {
979 
980     ResMgr& rMgr = CUI_MGR();
981 
982     // If we are showing Slot API commands update labels in the UI, and
983     // enable drag'n'drop
984     if ( m_bShowSlots )
985     {
986         aGroupText.SetText( String( ResId( STR_SELECTOR_CATEGORIES, rMgr ) ) );
987         aOKButton.SetText( String( ResId( STR_SELECTOR_ADD, rMgr ) ) );
988         aCancelButton.SetText( String( ResId( STR_SELECTOR_CLOSE, rMgr ) ) );
989         aFunctionText.SetText( String( ResId( STR_SELECTOR_COMMANDS, rMgr ) ) );
990         SetDialogDescription(
991             String( ResId( STR_SELECTOR_ADD_COMMANDS_DESCRIPTION, rMgr ) ) );
992         SetText( String( ResId( STR_SELECTOR_ADD_COMMANDS, rMgr ) ) );
993 
994         aCommands.SetDragDropMode( SV_DRAGDROP_APP_COPY );
995     }
996 
997     ResizeControls();
998 
999     aCategories.SetFunctionListBox( &aCommands );
1000     aCategories.Init();
1001     // aCategories.Select( aCategories.GetEntry( 0, 0 ) );
1002 
1003     aCategories.SetSelectHdl(
1004             LINK( this, SvxScriptSelectorDialog, SelectHdl ) );
1005     aCommands.SetSelectHdl( LINK( this, SvxScriptSelectorDialog, SelectHdl ) );
1006     aCommands.SetDoubleClickHdl( LINK( this, SvxScriptSelectorDialog, FunctionDoubleClickHdl ) );
1007 
1008     aOKButton.SetClickHdl( LINK( this, SvxScriptSelectorDialog, ClickHdl ) );
1009     aCancelButton.SetClickHdl( LINK( this, SvxScriptSelectorDialog, ClickHdl ) );
1010 
1011     UpdateUI();
1012     FreeResource();
1013 }
1014 
ResizeControls()1015 void SvxScriptSelectorDialog::ResizeControls()
1016 {
1017     Point p, newp;
1018     Size s, news;
1019     long gap;
1020 
1021     sal_uInt16 style = TEXT_DRAW_MULTILINE | TEXT_DRAW_TOP |
1022                    TEXT_DRAW_LEFT | TEXT_DRAW_WORDBREAK;
1023 
1024     // get dimensions of dialog instructions control
1025     p = aDialogDescription.GetPosPixel();
1026     s = aDialogDescription.GetSizePixel();
1027 
1028     // get dimensions occupied by text in the control
1029     Rectangle rect =
1030         GetTextRect( Rectangle( p, s ), aDialogDescription.GetText(), style );
1031     news = rect.GetSize();
1032 
1033     // the gap is the difference between the control height and its text height
1034     gap = s.Height() - news.Height();
1035 
1036     // resize the dialog instructions control
1037     news = Size( s.Width(), s.Height() - gap );
1038     aDialogDescription.SetSizePixel( news );
1039 
1040     // resize other controls to fill the gap
1041     p = aGroupText.GetPosPixel();
1042     newp = Point( p.X(), p.Y() - gap );
1043     aGroupText.SetPosPixel( newp );
1044 
1045     p = aCategories.GetPosPixel();
1046     newp = Point( p.X(), p.Y() - gap );
1047     aCategories.SetPosPixel( newp );
1048     s = aCategories.GetSizePixel();
1049     news = Size( s.Width(), s.Height() + gap );
1050     aCategories.SetSizePixel( news );
1051 
1052     p = aFunctionText.GetPosPixel();
1053     newp = Point( p.X(), p.Y() - gap );
1054     aFunctionText.SetPosPixel( newp );
1055 
1056     p = aCommands.GetPosPixel();
1057     newp = Point( p.X(), p.Y() - gap );
1058     aCommands.SetPosPixel( newp );
1059     s = aCommands.GetSizePixel();
1060     news = Size( s.Width(), s.Height() + gap );
1061     aCommands.SetSizePixel( news );
1062 
1063     p = aOKButton.GetPosPixel();
1064     newp = Point( p.X(), p.Y() - gap );
1065     aOKButton.SetPosPixel( newp );
1066 
1067     p = aCancelButton.GetPosPixel();
1068     newp = Point( p.X(), p.Y() - gap );
1069     aCancelButton.SetPosPixel( newp );
1070 
1071     p = aHelpButton.GetPosPixel();
1072     newp = Point( p.X(), p.Y() - gap );
1073     aHelpButton.SetPosPixel( newp );
1074 }
1075 
~SvxScriptSelectorDialog()1076 SvxScriptSelectorDialog::~SvxScriptSelectorDialog()
1077 {
1078 }
1079 
IMPL_LINK(SvxScriptSelectorDialog,SelectHdl,Control *,pCtrl)1080 IMPL_LINK( SvxScriptSelectorDialog, SelectHdl, Control*, pCtrl )
1081 {
1082     if ( pCtrl == &aCategories )
1083     {
1084         aCategories.GroupSelected();
1085     }
1086     else if ( pCtrl == &aCommands )
1087     {
1088         aCommands.FunctionSelected();
1089     }
1090     UpdateUI();
1091     return 0;
1092 }
1093 
IMPL_LINK(SvxScriptSelectorDialog,FunctionDoubleClickHdl,Control *,pCtrl)1094 IMPL_LINK( SvxScriptSelectorDialog, FunctionDoubleClickHdl, Control*, pCtrl )
1095 {
1096     (void)pCtrl;
1097     if ( aOKButton.IsEnabled() )
1098         return ClickHdl( &aOKButton );
1099     return 0;
1100 }
1101 
1102 // Check if command is selected and enable the OK button accordingly
1103 // Grab the help text for this id if available and update the description field
1104 void
UpdateUI()1105 SvxScriptSelectorDialog::UpdateUI()
1106 {
1107     OUString url = GetScriptURL();
1108     if ( url != NULL && url.getLength() != 0 )
1109     {
1110         String rMessage =
1111             aCommands.GetHelpText( aCommands.FirstSelected() );
1112         aDescriptionText.SetText( rMessage );
1113 
1114         aOKButton.Enable( sal_True );
1115     }
1116     else
1117     {
1118         aDescriptionText.SetText( String() );
1119         aOKButton.Enable( sal_False );
1120     }
1121 }
1122 
IMPL_LINK(SvxScriptSelectorDialog,ClickHdl,Button *,pButton)1123 IMPL_LINK( SvxScriptSelectorDialog, ClickHdl, Button *, pButton )
1124 {
1125     if ( pButton == &aCancelButton )
1126     {
1127         // If we are displaying Slot API commands then the dialog is being
1128         // run from Tools/Configure and we should not close it, just hide it
1129         if ( m_bShowSlots == sal_False )
1130         {
1131             EndDialog( RET_CANCEL );
1132         }
1133         else
1134         {
1135             Hide();
1136         }
1137     }
1138     else if ( pButton == &aOKButton )
1139     {
1140         GetAddHdl().Call( this );
1141 
1142         // If we are displaying Slot API commands then this the dialog is being
1143         // run from Tools/Configure and we should not close it
1144         if ( m_bShowSlots == sal_False )
1145         {
1146             EndDialog( RET_OK );
1147         }
1148         else
1149         {
1150             // Select the next entry in the list if possible
1151             SvLBoxEntry* current = aCommands.FirstSelected();
1152             SvLBoxEntry* next = aCommands.NextSibling( current );
1153 
1154             if ( next != NULL )
1155             {
1156                 aCommands.Select( next );
1157             }
1158         }
1159     }
1160 
1161     return 0;
1162 }
1163 
1164 void
SetRunLabel()1165 SvxScriptSelectorDialog::SetRunLabel()
1166 {
1167     aOKButton.SetText( String( CUI_RES( STR_SELECTOR_RUN ) ) );
1168 }
1169 
1170 void
SetDialogDescription(const String & rDescription)1171 SvxScriptSelectorDialog::SetDialogDescription( const String& rDescription )
1172 {
1173     aDialogDescription.SetText( rDescription );
1174 }
1175 
1176 String
GetScriptURL() const1177 SvxScriptSelectorDialog::GetScriptURL() const
1178 {
1179     OUString result;
1180 
1181     SvLBoxEntry *pEntry = const_cast< SvxScriptSelectorDialog* >( this )->aCommands.GetLastSelectedEntry();
1182     if ( pEntry )
1183     {
1184         SvxGroupInfo_Impl *pData = (SvxGroupInfo_Impl*) pEntry->GetUserData();
1185         if  (   ( pData->nKind == SVX_CFGFUNCTION_SLOT )
1186             ||  ( pData->nKind == SVX_CFGFUNCTION_SCRIPT )
1187             )
1188         {
1189             result = pData->sURL;
1190         }
1191     }
1192 
1193     return result;
1194 }
1195 
1196 String
GetSelectedDisplayName()1197 SvxScriptSelectorDialog::GetSelectedDisplayName()
1198 {
1199     return aCommands.GetEntryText( aCommands.GetLastSelectedEntry() );
1200 }
1201 
1202 String
GetSelectedHelpText()1203 SvxScriptSelectorDialog::GetSelectedHelpText()
1204 {
1205     return aCommands.GetHelpText( aCommands.GetLastSelectedEntry() );
1206 }
1207