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 
28 #include <stdio.h>
29 #include <wchar.h>
30 
31 #include <cppuhelper/bootstrap.hxx>
32 
33 #include <osl/file.hxx>
34 #include <osl/process.h>
35 
36 #include <com/sun/star/bridge/XUnoUrlResolver.hpp>
37 #include <com/sun/star/frame/XComponentLoader.hpp>
38 #include <com/sun/star/beans/XPropertySet.hpp>
39 #include <com/sun/star/awt/tree/XMutableTreeDataModel.hpp>
40 #include <com/sun/star/awt/tree/XTreeControl.hpp>
41 #include <com/sun/star/awt/tree/XTreeExpansionListener.hpp>
42 #include <com/sun/star/awt/tree/XTreeEditListener.hpp>
43 #include <com/sun/star/awt/XDialog.hpp>
44 #include <com/sun/star/awt/XControlModel.hpp>
45 #include <com/sun/star/container/XNameContainer.hpp>
46 #include <com/sun/star/awt/XControl.hpp>
47 #include <com/sun/star/awt/XControlContainer.hpp>
48 #include <com/sun/star/view/SelectionType.hpp>
49 
50 #include <tools/urlobj.hxx>
51 #include <vcl/image.hxx>
52 #include <vcl/graph.hxx>
53 
54 #include <cppuhelper/implbase2.hxx>
55 
56 #include <string.h>
57 #include <rtl/ref.hxx>
58 
59 #include "imagemgr.hxx"
60 
61 using rtl::OUString;
62 using namespace com::sun::star::uno;
63 using namespace com::sun::star::lang;
64 using namespace com::sun::star::beans;
65 using namespace com::sun::star::bridge;
66 using namespace com::sun::star::frame;
67 using namespace com::sun::star::registry;
68 using namespace com::sun::star::awt;
69 using namespace com::sun::star::awt::tree;
70 using namespace com::sun::star::container;
71 using namespace com::sun::star::view;
72 using namespace com::sun::star::util;
73 
74 class DirectoryTree : public ::cppu::WeakImplHelper2< XTreeExpansionListener, XTreeEditListener >
75 {
76 public:
77 	DirectoryTree( const Reference< XComponentContext >& xComponentContext );
78 	virtual ~DirectoryTree();
79 
80 	void fillNode( const Reference< XMutableTreeNode >& xNode );
81 	void display( const OUString& rURL );
82 
83 	// XTreeExpansionListener
84     virtual void SAL_CALL requestChildNodes( const TreeExpansionEvent& Event ) throw (RuntimeException);
85     virtual void SAL_CALL treeExpanding( const TreeExpansionEvent& Event ) throw (ExpandVetoException, RuntimeException);
86     virtual void SAL_CALL treeCollapsing( const TreeExpansionEvent& Event ) throw (ExpandVetoException, RuntimeException);
87     virtual void SAL_CALL treeExpanded( const TreeExpansionEvent& Event ) throw (RuntimeException);
88     virtual void SAL_CALL treeCollapsed( const TreeExpansionEvent& Event ) throw (RuntimeException);
89 
90 	// XTreeEditListener
91     virtual void SAL_CALL nodeEditing( const Reference< XTreeNode >& Node ) throw (VetoException, RuntimeException);
92     virtual void SAL_CALL nodeEdited( const Reference< XTreeNode >& Node, const OUString& NewText ) throw (RuntimeException);
93 
94 	// XEventListener
95     virtual void SAL_CALL disposing( const ::com::sun::star::lang::EventObject& Source ) throw (RuntimeException);
96 
97 	Reference< XMultiComponentFactory > mxMultiComponentFactoryServer;
98 	Reference< XComponentContext > mxComponentContext;
99 	Reference< XTreeControl > mxTreeControl;
100 	Reference< XMutableTreeDataModel > mxTreeDataModel;
101 };
102 
103 DirectoryTree::DirectoryTree( const Reference< XComponentContext >& xComponentContext )
104 : mxComponentContext( xComponentContext )
105 , mxMultiComponentFactoryServer( xComponentContext->getServiceManager() )
106 {
107 }
108 
109 DirectoryTree::~DirectoryTree()
110 {
111 }
112 
113 void DirectoryTree::display( const OUString& rURL )
114 {
115 	// some property names for later use
116 	const OUString sPositionX( RTL_CONSTASCII_USTRINGPARAM( "PositionX" ) );
117 	const OUString sPositionY( RTL_CONSTASCII_USTRINGPARAM( "PositionY" ) );
118 	const OUString sWidth( RTL_CONSTASCII_USTRINGPARAM( "Width" ) );
119 	const OUString sHeight( RTL_CONSTASCII_USTRINGPARAM( "Height" ) );
120 	const OUString sDataModel( RTL_CONSTASCII_USTRINGPARAM( "DataModel" ) );
121 	const OUString sSelectionType( RTL_CONSTASCII_USTRINGPARAM( "SelectionType" ) );
122 	const OUString sShowsRootHandles( RTL_CONSTASCII_USTRINGPARAM( "ShowsRootHandles" ) );
123 	const OUString sShowsHandles( RTL_CONSTASCII_USTRINGPARAM( "ShowsHandles" ) );
124 	const OUString sRootDisplayed( RTL_CONSTASCII_USTRINGPARAM( "RootDisplayed" ) );
125 	const OUString sEditable( RTL_CONSTASCII_USTRINGPARAM( "Editable" ) );
126 	const OUString sTitle( RTL_CONSTASCII_USTRINGPARAM( "Title" ) );
127 	const OUString sRowHeight( RTL_CONSTASCII_USTRINGPARAM( "RowHeight" ) );
128 
129 	// first create a data model for our tree control
130 	mxTreeDataModel = Reference< XMutableTreeDataModel >(
131 		mxMultiComponentFactoryServer->createInstanceWithContext(
132 	        OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.awt.tree.MutableTreeDataModel" ) ),
133 		    mxComponentContext ), UNO_QUERY_THROW );
134 
135 	// now fill it with some sample data
136 	Reference< XMutableTreeNode > xNode( mxTreeDataModel->createNode( Any( rURL ), false ), UNO_QUERY_THROW );
137 	xNode->setDataValue( Any( rURL ) );
138 	xNode->setExpandedGraphicURL( OUString( RTL_CONSTASCII_USTRINGPARAM( "private:graphicrepository/sd/res/triangle_down.png" ) ) );
139 	xNode->setCollapsedGraphicURL( OUString( RTL_CONSTASCII_USTRINGPARAM( "private:graphicrepository/sd/res/triangle_right.png" ) ) );
140 
141 	fillNode( xNode );
142 	mxTreeDataModel->setRoot( xNode );
143 
144 	// now create the dialog
145 	Reference< XControlModel > xDialogModel(
146 		mxMultiComponentFactoryServer->createInstanceWithContext(
147 	        OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.awt.UnoControlDialogModel" ) ),
148 		    mxComponentContext ), UNO_QUERY_THROW );
149 
150 	Reference< XPropertySet > xDialogPropertySet( xDialogModel, UNO_QUERY_THROW );
151 	xDialogPropertySet->setPropertyValue( sPositionX,	Any( sal_Int32(50) ) );
152 	xDialogPropertySet->setPropertyValue( sPositionY,	Any( sal_Int32(50) ) );
153 	xDialogPropertySet->setPropertyValue( sWidth,		Any( sal_Int32(256) ) );
154 	xDialogPropertySet->setPropertyValue( sHeight,		Any( sal_Int32(256) ) );
155 	xDialogPropertySet->setPropertyValue( sTitle,		Any( OUString( RTL_CONSTASCII_USTRINGPARAM( "Tree Control Test" ) ) ) );
156 
157 	Reference< XMultiServiceFactory > xDialogMSF( xDialogModel, UNO_QUERY_THROW );
158 
159 	// now create our tree control
160 	Reference< XControlModel > xTreeControlModel(
161 		xDialogMSF->createInstance(
162 	        OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.awt.tree.TreeControlModel" ) ) ),
163 		    UNO_QUERY_THROW );
164 
165 	Reference< XPropertySet > XTreeControlModelSet( xTreeControlModel, UNO_QUERY_THROW );
166 
167 	XTreeControlModelSet->setPropertyValue( sSelectionType,	Any( SelectionType_NONE ) );
168 	XTreeControlModelSet->setPropertyValue( sPositionX,		Any( sal_Int32(3) ) );
169 	XTreeControlModelSet->setPropertyValue( sPositionY,		Any( sal_Int32(3) ) );
170 	XTreeControlModelSet->setPropertyValue( sWidth,			Any( sal_Int32(253) ) );
171 	XTreeControlModelSet->setPropertyValue( sHeight,		Any( sal_Int32(253) ) );
172 	XTreeControlModelSet->setPropertyValue( sDataModel,		Any( mxTreeDataModel ) );
173 	XTreeControlModelSet->setPropertyValue( sShowsRootHandles,Any( sal_False ) );
174 	XTreeControlModelSet->setPropertyValue( sShowsHandles,	Any( sal_False ) );
175 	XTreeControlModelSet->setPropertyValue( sRootDisplayed,	Any( sal_True ) );
176 	XTreeControlModelSet->setPropertyValue( sEditable,		Any( sal_True ) );
177 //	XTreeControlModelSet->setPropertyValue( sRowHeight,		Any( sal_Int32( 12 ) ) );
178 
179 	Reference< XNameContainer > xDialogModelContainer( xDialogModel, UNO_QUERY_THROW );
180 
181 	const OUString sTreeControlName( RTL_CONSTASCII_USTRINGPARAM( "tree" ) );
182 
183 	xDialogModelContainer->insertByName( sTreeControlName, Any( xTreeControlModel ) );
184 
185 	// now create the peers
186 	Reference< XControl > xDialogControl(
187 		mxMultiComponentFactoryServer->createInstanceWithContext(
188 	        OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.awt.UnoControlDialog" ) ),
189 		    mxComponentContext ), UNO_QUERY_THROW );
190 
191 	xDialogControl->setModel( xDialogModel );
192 
193 	Reference< XToolkit > xToolkit(
194 		mxMultiComponentFactoryServer->createInstanceWithContext(
195 	        OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.awt.Toolkit" ) ),
196 		    mxComponentContext ), UNO_QUERY_THROW );
197 	xDialogControl->createPeer( xToolkit, 0 );
198 
199 	// get the peers of the sub controls from the dialog peer container
200 	Reference< XControlContainer > xDialogContainer( xDialogControl, UNO_QUERY_THROW );
201 	mxTreeControl = Reference< XTreeControl >( xDialogContainer->getControl( sTreeControlName ), UNO_QUERY_THROW );
202 
203 	Reference< XTreeExpansionListener > xListener( static_cast<XWeak*>(this), UNO_QUERY_THROW );
204 	mxTreeControl->addTreeExpansionListener( xListener );
205 	Reference< XDialog > xDialog( xDialogControl, UNO_QUERY_THROW );
206 	xDialog->execute();
207 }
208 
209 void DirectoryTree::fillNode( const Reference< XMutableTreeNode >& xNode )
210 {
211 	if( xNode->getChildCount() == 0 )
212 	{
213 		OUString sParentPath;
214 		xNode->getDataValue() >>= sParentPath;
215 
216 		osl::Directory aDirectory( sParentPath );
217 		if( aDirectory.open() == osl::Directory::E_None )
218 		{
219 			osl::DirectoryItem aItem;
220 			osl::FileStatus fs( FileStatusMask_Type | FileStatusMask_FileURL);
221 			while( aDirectory.getNextItem( aItem, 0xffffffff ) == osl::Directory::E_None )
222 			{
223 				if (aItem.getFileStatus(fs) == osl::FileBase::E_None)
224 				{
225 					bool bDirectory = fs.getFileType() == osl::FileStatus::Directory;
226 					Reference< XMutableTreeNode > xChildNode( mxTreeDataModel->createNode( Any( fs.getFileName() ), bDirectory ), UNO_QUERY_THROW );
227 					xChildNode->setDataValue( Any( fs.getFileURL() ) );
228 					if( bDirectory )
229 					{
230 						xChildNode->setExpandedGraphicURL( OUString( RTL_CONSTASCII_USTRINGPARAM( "private:graphicrepository/sd/res/triangle_down.png" ) ) );
231 						xChildNode->setCollapsedGraphicURL( OUString( RTL_CONSTASCII_USTRINGPARAM( "private:graphicrepository/sd/res/triangle_right.png" ) ) );
232 					}
233 					else
234 					{
235 						xChildNode->setNodeGraphicURL( OUString( RTL_CONSTASCII_USTRINGPARAM("private:graphicrepository/sw/imglst/nc20010.png") ) );
236 					}
237 					xNode->appendChild( xChildNode );
238 				}
239 			}
240 		}
241 	}
242 }
243 
244 // XTreeExpansionListener
245 void SAL_CALL DirectoryTree::requestChildNodes( const TreeExpansionEvent& rEvent ) throw (RuntimeException)
246 {
247 	if( rEvent.Node.is() && rEvent.Node->hasChildsOnDemand() )
248 	{
249 		Reference< XMutableTreeNode > xNode( rEvent.Node, UNO_QUERY );
250 		if( xNode.is() )
251 		{
252 			fillNode( xNode );
253 			xNode->setHasChildsOnDemand( sal_False );
254 		}
255 	}
256 }
257 
258 void SAL_CALL DirectoryTree::treeExpanding( const TreeExpansionEvent& /*rEvent*/ ) throw (ExpandVetoException, RuntimeException)
259 {
260 }
261 
262 void SAL_CALL DirectoryTree::treeCollapsing( const TreeExpansionEvent&  ) throw (ExpandVetoException, RuntimeException)
263 {
264 }
265 
266 void SAL_CALL DirectoryTree::treeExpanded( const TreeExpansionEvent&  ) throw (RuntimeException)
267 {
268 }
269 
270 void SAL_CALL DirectoryTree::treeCollapsed( const TreeExpansionEvent& /*rEvent*/ ) throw (RuntimeException)
271 {
272 /*
273 	if( rEvent.Node != mxTreeDataModel->getRoot() )
274 	{
275 		Reference< XMutableTreeNode > xNode( rEvent.Node, UNO_QUERY );
276 		if( xNode.is() )
277 		{
278 			while( xNode->getChildCount() )
279 				xNode->removeChildByIndex(0);
280 			xNode->setHasChildsOnDemand( sal_True );
281 		}
282 	}
283 */
284 }
285 
286 // XTreeEditListener
287 void SAL_CALL DirectoryTree::nodeEditing( const Reference< XTreeNode >&  ) throw (VetoException, RuntimeException)
288 {
289 }
290 
291 void SAL_CALL DirectoryTree::nodeEdited( const Reference< XTreeNode >& , const OUString&  ) throw (RuntimeException)
292 {
293 }
294 
295 // XEventListener
296 void SAL_CALL DirectoryTree::disposing( const ::com::sun::star::lang::EventObject&  ) throw (RuntimeException)
297 {
298 }
299 
300 //============================================================================
301 int SAL_CALL main( int argc, char **argv )
302 {
303     OUString sConnectionString(RTL_CONSTASCII_USTRINGPARAM("uno:socket,host=localhost,port=5678;urp;StarOffice.ServiceManager"));
304 
305 	if (argc < 2)
306 	{
307 		printf("using: treetest <directory> [<uno_connection_url>]\n\n"
308 #ifdef WNT
309 				"example: treetest  \"c:\" \"uno:socket,host=localhost,port=5678;urp;StarOffice.ServiceManager\"\n");
310 #else
311 				"example: treetest  \"/etc\" \"uno:socket,host=localhost,port=5678;urp;StarOffice.ServiceManager\"\n");
312 #endif
313 		exit(1);
314 	}
315  	if (argc == 3)
316 	{
317 		sConnectionString = OUString::createFromAscii(argv[2]);
318 	}
319 
320 	// Creates a simple registry service instance.
321     Reference< XSimpleRegistry > xSimpleRegistry(::cppu::createSimpleRegistry() );
322 
323     // Connects the registry to a persistent data source represented by an URL.
324     xSimpleRegistry->open(
325 		OUString( RTL_CONSTASCII_USTRINGPARAM("treetest.rdb") ), sal_True, sal_False );
326 
327     /* Bootstraps an initial component context with service manager upon a given
328        registry. This includes insertion of initial services:
329        - (registry) service manager, shared lib loader,
330        - simple registry, nested registry,
331        - implementation registration
332        - registry typedescription provider, typedescription manager (also
333          installs it into cppu core)
334     */
335     Reference< XComponentContext > xComponentContext(
336         ::cppu::bootstrap_InitialComponentContext( xSimpleRegistry ) );
337 
338     /* Gets the service manager instance to be used (or null). This method has
339        been added for convenience, because the service manager is a often used
340        object.
341     */
342 	Reference< XMultiComponentFactory > xMultiComponentFactoryClient(
343 		xComponentContext->getServiceManager() );
344 
345     /* Creates an instance of a component which supports the services specified
346        by the factory.
347     */
348     Reference< XInterface > xInterface =
349         xMultiComponentFactoryClient->createInstanceWithContext(
350             OUString::createFromAscii( "com.sun.star.bridge.UnoUrlResolver" ),
351             xComponentContext );
352 
353     Reference< XUnoUrlResolver > resolver( xInterface, UNO_QUERY );
354 
355     // Resolves the component context from the office, on the uno URL given by argv[1].
356     try
357     {
358         xInterface = Reference< XInterface >(
359             resolver->resolve( sConnectionString ), UNO_QUERY );
360     }
361     catch ( Exception& e )
362     {
363 		printf("Error: cannot establish a connection using '%s':\n       %s\n",
364                OUStringToOString(sConnectionString, RTL_TEXTENCODING_ASCII_US).getStr(),
365                OUStringToOString(e.Message, RTL_TEXTENCODING_ASCII_US).getStr());
366 		exit(1);
367     }
368 
369     // gets the server component context as property of the office component factory
370     Reference< XPropertySet > xPropSet( xInterface, UNO_QUERY );
371     xPropSet->getPropertyValue( OUString::createFromAscii("DefaultContext") ) >>= xComponentContext;
372 
373     // gets the service manager from the office
374     Reference< XMultiComponentFactory > xMultiComponentFactoryServer(
375         xComponentContext->getServiceManager() );
376 
377 	try
378 	{
379 		OUString ustrFileURL;
380 		osl::FileBase::getFileURLFromSystemPath( OUString::createFromAscii(argv[1]), ustrFileURL );
381 
382 		rtl::Reference< DirectoryTree >(
383 			new DirectoryTree( xComponentContext ) )->display(ustrFileURL);
384 	}
385 	catch( Exception& e )
386 	{
387 		printf("Error: exception caught during test:\n       %s\n",
388                OUStringToOString(e.Message, RTL_TEXTENCODING_ASCII_US).getStr());
389 		exit(1);
390 	}
391 
392 	// dispose the local service manager
393     Reference< XComponent >::query( xMultiComponentFactoryClient )->dispose();
394 
395     return 0;
396 }
397