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 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_framework.hxx"
30 
31 //_______________________________________________
32 // my own includes
33 
34 #include <dispatch/windowcommanddispatch.hxx>
35 #include <threadhelp/readguard.hxx>
36 #include <threadhelp/writeguard.hxx>
37 #include <targets.h>
38 #include <services.h>
39 
40 //_______________________________________________
41 // interface includes
42 
43 #include <com/sun/star/frame/XDispatchProvider.hpp>
44 #include <com/sun/star/frame/XDispatch.hpp>
45 #include <com/sun/star/util/XURLTransformer.hpp>
46 
47 //_______________________________________________
48 // includes of other projects
49 
50 #include <vcl/window.hxx>
51 #include <vcl/svapp.hxx>
52 #include <vcl/cmdevt.hxx>
53 #include <vos/mutex.hxx>
54 #include <toolkit/helper/vclunohelper.hxx>
55 #include <rtl/logfile.hxx>
56 
57 //_______________________________________________
58 // namespace
59 
60 namespace framework{
61 
62 namespace css = ::com::sun::star;
63 
64 //_______________________________________________
65 // declarations
66 
67 const ::rtl::OUString WindowCommandDispatch::COMMAND_PREFERENCES = ::rtl::OUString::createFromAscii(".uno:OptionsTreeDialog");
68 const ::rtl::OUString WindowCommandDispatch::COMMAND_ABOUTBOX    = ::rtl::OUString::createFromAscii(".uno:About");
69 
70 //-----------------------------------------------
71 WindowCommandDispatch::WindowCommandDispatch(const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR ,
72                          const css::uno::Reference< css::frame::XFrame >&              xFrame)
73     : ThreadHelpBase(                            )
74     , m_xSMGR       (xSMGR                       )
75     , m_xFrame      (xFrame                      )
76     , m_xWindow     (xFrame->getContainerWindow())
77 {
78     impl_startListening();
79 }
80 
81 //-----------------------------------------------
82 WindowCommandDispatch::~WindowCommandDispatch()
83 {
84     m_xSMGR.clear();
85 }
86 
87 //-----------------------------------------------
88 void SAL_CALL WindowCommandDispatch::disposing(const css::lang::EventObject& /*aSource*/)
89     throw (css::uno::RuntimeException)
90 {
91     // We hold our window weak ... so there is no need to clear it's reference here.
92     // The window and we will die by ref count automatically.
93 }
94 
95 //-----------------------------------------------
96 void WindowCommandDispatch::impl_startListening()
97 {
98     // SYNCHRONIZED ->
99     ReadGuard aReadLock(m_aLock);
100     css::uno::Reference< css::awt::XWindow > xWindow( m_xWindow.get(), css::uno::UNO_QUERY );
101     aReadLock.unlock();
102     // <- SYNCHRONIZED
103 
104     if ( ! xWindow.is())
105         return;
106 
107     // SYNCHRONIZED ->
108     ::vos::OClearableGuard aSolarLock(Application::GetSolarMutex());
109 
110     Window* pWindow = VCLUnoHelper::GetWindow(xWindow);
111     if ( ! pWindow)
112         return;
113 
114     pWindow->AddEventListener( LINK(this, WindowCommandDispatch, impl_notifyCommand) );
115 
116     aSolarLock.clear();
117     // <- SYNCHRONIZED
118 }
119 
120 //-----------------------------------------------
121 IMPL_LINK(WindowCommandDispatch, impl_notifyCommand, void*, pParam)
122 {
123     if ( ! pParam)
124         return 0L;
125 
126     const VclWindowEvent* pEvent = (VclWindowEvent*)pParam;
127     if (pEvent->GetId() != VCLEVENT_WINDOW_COMMAND)
128         return 0L;
129 
130     const CommandEvent* pCommand = (CommandEvent*)pEvent->GetData();
131     if (pCommand->GetCommand() != COMMAND_SHOWDIALOG)
132         return 0L;
133 
134     const CommandDialogData* pData = pCommand->GetDialogData();
135     if ( ! pData)
136         return 0L;
137 
138     const int nCommand = pData->GetDialogId();
139           ::rtl::OUString sCommand;
140 
141     switch (nCommand)
142     {
143         case SHOWDIALOG_ID_PREFERENCES :
144                 sCommand = WindowCommandDispatch::COMMAND_PREFERENCES;
145                 break;
146 
147         case SHOWDIALOG_ID_ABOUT :
148                 sCommand = WindowCommandDispatch::COMMAND_ABOUTBOX;
149                 break;
150 
151         default :
152                 return 0L;
153     }
154 
155     impl_dispatchCommand(sCommand);
156 
157     return 0L;
158 }
159 
160 //-----------------------------------------------
161 void WindowCommandDispatch::impl_dispatchCommand(const ::rtl::OUString& sCommand)
162 {
163     // ignore all errors here. It's clicking a menu entry only ...
164     // The user will try it again, in case nothing happens .-)
165     try
166     {
167         // SYNCHRONIZED ->
168         ReadGuard aReadLock(m_aLock);
169         css::uno::Reference< css::frame::XDispatchProvider >   xProvider(m_xFrame.get(), css::uno::UNO_QUERY_THROW);
170         css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR    = m_xSMGR;
171         aReadLock.unlock();
172         // <- SYNCHRONIZED
173 
174         // check provider ... we know it's weak reference only
175         if ( ! xProvider.is())
176             return;
177 
178         css::uno::Reference< css::util::XURLTransformer > xParser(xSMGR->createInstance(SERVICENAME_URLTRANSFORMER), css::uno::UNO_QUERY_THROW);
179         css::util::URL aCommand;
180         aCommand.Complete = sCommand;
181         xParser->parseStrict(aCommand);
182 
183         css::uno::Reference< css::frame::XDispatch > xDispatch = xProvider->queryDispatch(aCommand, SPECIALTARGET_SELF, 0);
184         if (xDispatch.is())
185             xDispatch->dispatch(aCommand, css::uno::Sequence< css::beans::PropertyValue >());
186     }
187     catch(const css::uno::Exception&)
188     {}
189 }
190 
191 } // namespace framework
192