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 "precompiled_sd.hxx"
29 
30 #include "ChildWindowPane.hxx"
31 
32 #include "PaneDockingWindow.hxx"
33 #include "ViewShellBase.hxx"
34 #include "ViewShellManager.hxx"
35 #include "framework/FrameworkHelper.hxx"
36 #include <toolkit/helper/vclunohelper.hxx>
37 #include <vcl/svapp.hxx>
38 
39 using namespace ::com::sun::star;
40 using namespace ::com::sun::star::uno;
41 using namespace ::com::sun::star::drawing::framework;
42 
43 namespace sd { namespace framework {
44 
45 
46 ChildWindowPane::ChildWindowPane (
47     const Reference<XResourceId>& rxPaneId,
48     sal_uInt16 nChildWindowId,
49     ViewShellBase& rViewShellBase,
50     ::std::auto_ptr<SfxShell> pShell)
51     : ChildWindowPaneInterfaceBase(rxPaneId,(::Window*)NULL),
52       mnChildWindowId(nChildWindowId),
53       mrViewShellBase(rViewShellBase),
54       mpShell(pShell),
55       mbHasBeenActivated(false)
56 {
57     mrViewShellBase.GetViewShellManager()->ActivateShell(mpShell.get());
58 
59     SfxViewFrame* pViewFrame = mrViewShellBase.GetViewFrame();
60     if (pViewFrame != NULL)
61     {
62         if (mrViewShellBase.IsActive())
63         {
64             if (pViewFrame->KnowsChildWindow(mnChildWindowId))
65             {
66                 if (pViewFrame->HasChildWindow(mnChildWindowId))
67                 {
68                     // The ViewShellBase has already been activated.  Make
69                     // the child window visible as soon as possible.
70                     pViewFrame->SetChildWindow(mnChildWindowId, sal_True);
71                     OSL_TRACE("ChildWindowPane:activating now");
72                 }
73                 else
74                 {
75                     // The window is created asynchronously.  Rely on the
76                     // ConfigurationUpdater to try another update, and with
77                     // that another request for this window, in a short
78                     // time.
79                     OSL_TRACE("ChildWindowPane:activated asynchronously");
80                 }
81             }
82             else
83             {
84                 OSL_TRACE("ChildWindowPane:not known");
85             }
86         }
87         else
88         {
89             // The ViewShellBase has not yet been activated.  Hide the
90             // window and wait a little before it is made visible.  See
91             // comments in the GetWindow() method for an explanation.
92             pViewFrame->SetChildWindow(mnChildWindowId, sal_False);
93             OSL_TRACE("ChildWindowPane:base not active");
94         }
95     }
96 }
97 
98 
99 
100 
101 ChildWindowPane::~ChildWindowPane (void) throw()
102 {
103 }
104 
105 
106 
107 
108 void ChildWindowPane::Hide (void)
109 {
110     SfxViewFrame* pViewFrame = mrViewShellBase.GetViewFrame();
111     if (pViewFrame != NULL)
112         if (pViewFrame->KnowsChildWindow(mnChildWindowId))
113             if (pViewFrame->HasChildWindow(mnChildWindowId))
114                 pViewFrame->SetChildWindow(mnChildWindowId, sal_False);
115 
116     // Release the window because when the child window is shown again it
117     // may use a different window.
118     mxWindow = NULL;
119 }
120 
121 
122 
123 
124 void SAL_CALL ChildWindowPane::disposing (void)
125 {
126     ::osl::MutexGuard aGuard (maMutex);
127 
128     mrViewShellBase.GetViewShellManager()->DeactivateShell(mpShell.get());
129     mpShell.reset();
130 
131     if (mxWindow.is())
132     {
133         mxWindow->removeEventListener(this);
134     }
135 
136     Pane::disposing();
137 }
138 
139 
140 
141 
142 ::Window* ChildWindowPane::GetWindow (void)
143 {
144     do
145     {
146         if (mxWindow.is())
147             // Window already exists => nothing to do.
148             break;
149 
150         // When the window is not yet present then obtain it only when the
151         // shell has already been activated.  The activation is not
152         // necessary for the code to work properly but is used to optimize
153         // the layouting and displaying of the window.  When it is made
154         // visible to early then some layouting seems to be made twice or at
155         // an inconvenient time and the overall process of initializing the
156         // Impress takes longer.
157         if ( ! mbHasBeenActivated && mpShell.get()!=NULL && ! mpShell->IsActive())
158             break;
159 
160         mbHasBeenActivated = true;
161         SfxViewFrame* pViewFrame = mrViewShellBase.GetViewFrame();
162         if (pViewFrame == NULL)
163             break;
164         // The view frame has to know the child window.  This can be the
165         // case, when for example the document is in read-only mode:  the
166         // task pane is then not available.
167         if ( ! pViewFrame->KnowsChildWindow(mnChildWindowId))
168             break;
169 
170         pViewFrame->SetChildWindow(mnChildWindowId, sal_True);
171         SfxChildWindow* pChildWindow = pViewFrame->GetChildWindow(mnChildWindowId);
172         if (pChildWindow == NULL)
173             if (pViewFrame->HasChildWindow(mnChildWindowId))
174             {
175                 // The child window is not yet visible.  Ask the view frame
176                 // to show it and try again to get access to the child
177                 // window.
178                 pViewFrame->ShowChildWindow(mnChildWindowId, sal_True);
179                 pChildWindow = pViewFrame->GetChildWindow(mnChildWindowId);
180             }
181 
182         // When the child window is still not visible then we have to try later.
183         if (pChildWindow == NULL)
184             break;
185 
186         // From the child window get the docking window and from that the
187         // content window that is the container for the actual content.
188         PaneDockingWindow* pDockingWindow = dynamic_cast<PaneDockingWindow*>(
189             pChildWindow->GetWindow());
190         if (pDockingWindow == NULL)
191             break;
192 
193         // At last, we have access to the window and its UNO wrapper.
194         mpWindow = &pDockingWindow->GetContentWindow();
195         mxWindow = VCLUnoHelper::GetInterface(mpWindow);
196 
197         // Register as window listener to be informed when the child window
198         // is hidden.
199         if (mxWindow.is())
200             mxWindow->addEventListener(this);
201     }
202     while (false);
203 
204     return mpWindow;
205 }
206 
207 
208 
209 
210 Reference<awt::XWindow> SAL_CALL ChildWindowPane::getWindow (void)
211     throw (RuntimeException)
212 {
213     if (mpWindow == NULL || ! mxWindow.is())
214         GetWindow();
215     return Pane::getWindow();
216 }
217 
218 
219 
220 IMPLEMENT_FORWARD_XINTERFACE2(
221     ChildWindowPane,
222     ChildWindowPaneInterfaceBase,
223     Pane);
224 IMPLEMENT_FORWARD_XTYPEPROVIDER2(
225     ChildWindowPane,
226     ChildWindowPaneInterfaceBase,
227     Pane);
228 
229 
230 
231 
232 //----- XEventListener --------------------------------------------------------
233 
234 void SAL_CALL ChildWindowPane::disposing (const lang::EventObject& rEvent)
235     throw (RuntimeException)
236 {
237     ThrowIfDisposed();
238 
239     if (rEvent.Source == mxWindow)
240     {
241         // The window is gone but the pane remains alive.  The next call to
242         // GetWindow() may create the window anew.
243         mxWindow = NULL;
244         mpWindow = NULL;
245     }
246 }
247 
248 
249 
250 
251 } } // end of namespace sd::framework
252