xref: /trunk/main/swext/mediawiki/src/com/sun/star/wiki/MainThreadDialogExecutor.java (revision ae8858429a07d9f4eb86a1a1d12b3cd7da720293)
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 package com.sun.star.wiki;
25 
26 import com.sun.star.uno.Any;
27 import com.sun.star.awt.XDialog;
28 import com.sun.star.awt.XCallback;
29 import com.sun.star.awt.XRequestCallback;
30 import com.sun.star.lang.XMultiComponentFactory;
31 import com.sun.star.uno.UnoRuntime;
32 import com.sun.star.uno.XComponentContext;
33 import java.util.concurrent.Callable;
34 
35 public class MainThreadDialogExecutor implements XCallback
36 {
37     private Callable<Boolean> m_aTask;
38     private XDialog    m_xDialog;
39     private boolean    m_bResult = false;
40     private boolean    m_bCalled = false;
41     private boolean    m_bClose = false;
42 
43     /** Runs aTask on the main thread. Dialogs and message boxes must also be created there:
44         on macOS a window created on another thread gets no native window and its modal execute never returns. */
Run( XComponentContext xContext, Callable<Boolean> aTask )45     static public boolean Run( XComponentContext xContext, Callable<Boolean> aTask )
46     {
47         MainThreadDialogExecutor aExecutor = new MainThreadDialogExecutor( aTask );
48         return GetCallback( xContext, aExecutor );
49     }
50 
Execute( XComponentContext xContext, XDialog xDialog )51     static public boolean Execute( XComponentContext xContext, XDialog xDialog )
52     {
53         MainThreadDialogExecutor aExecutor = new MainThreadDialogExecutor( xDialog );
54         return GetCallback( xContext, aExecutor );
55     }
56 
Close( XComponentContext xContext, XDialog xDialog )57     static public boolean Close( XComponentContext xContext, XDialog xDialog )
58     {
59         MainThreadDialogExecutor aExecutor = new MainThreadDialogExecutor( xDialog, true );
60         return GetCallback( xContext, aExecutor );
61     }
62 
GetCallback( XComponentContext xContext, MainThreadDialogExecutor aExecutor )63     static private boolean GetCallback( XComponentContext xContext, MainThreadDialogExecutor aExecutor )
64     {
65         try
66         {
67             if ( aExecutor != null )
68             {
69                 String aThreadName = null;
70                 Thread aCurThread = Thread.currentThread();
71                 if ( aCurThread != null )
72                     aThreadName = aCurThread.getName();
73 
74                 if ( aThreadName != null && aThreadName.equals( "com.sun.star.thread.WikiEditorSendingThread" ) )
75                 {
76                     // the main thread should be accessed asynchronously
77                     XMultiComponentFactory xFactory = xContext.getServiceManager();
78                     if ( xFactory == null )
79                         throw new com.sun.star.uno.RuntimeException();
80 
81                     XRequestCallback xRequest = UnoRuntime.queryInterface(
82                         XRequestCallback.class,
83                         xFactory.createInstanceWithContext( "com.sun.star.awt.AsyncCallback", xContext ) );
84                     if ( xRequest != null )
85                     {
86                         xRequest.addCallback( aExecutor, Any.VOID );
87                         aExecutor.WaitForCall();
88                     }
89                 }
90                 else
91                 {
92                     // handle it as a main thread
93                     aExecutor.notify( Any.VOID );
94                 }
95             }
96         }
97         catch( Exception e )
98         {
99             e.printStackTrace();
100         }
101 
102         return aExecutor.GetResult();
103     }
104 
MainThreadDialogExecutor( Callable<Boolean> aTask )105     private MainThreadDialogExecutor( Callable<Boolean> aTask )
106     {
107         m_aTask = aTask;
108     }
109 
MainThreadDialogExecutor( XDialog xDialog )110     private MainThreadDialogExecutor( XDialog xDialog )
111     {
112         m_xDialog = xDialog;
113     }
114 
MainThreadDialogExecutor( XDialog xDialog, boolean bClose )115     private MainThreadDialogExecutor( XDialog xDialog, boolean bClose )
116     {
117         m_xDialog = xDialog;
118         m_bClose = true;
119         m_bCalled = true; // no waiting, asynchronous closing
120     }
121 
WaitForCall()122     private void WaitForCall()
123     {
124         boolean bInterrupted = false;
125         synchronized( this )
126         {
127             while( !m_bCalled )
128             {
129                 try
130                 {
131                     wait();
132                 }
133                 catch( InterruptedException e )
134                 {
135                     bInterrupted = true;
136                 }
137             }
138         }
139         if ( bInterrupted )
140             Thread.currentThread().interrupt();
141     }
142 
GetResult()143     private boolean GetResult()
144     {
145         return m_bResult;
146     }
147 
notify( Object aData )148     public void notify( Object aData )
149     {
150         try
151         {
152             CallInMainThread();
153         }
154         finally
155         {
156             synchronized( this )
157             {
158                 m_bCalled = true;
159                 notifyAll();
160             }
161         }
162     }
163 
CallInMainThread()164     private void CallInMainThread()
165     {
166         if ( m_aTask != null )
167         {
168             try
169             {
170                 m_bResult = m_aTask.call().booleanValue();
171             }
172             catch( Exception e )
173             {
174                 e.printStackTrace();
175             }
176         }
177         else if ( m_xDialog != null )
178         {
179             if ( !m_bClose )
180                 m_bResult = ( m_xDialog.execute() == 1 );
181             else
182             {
183                 try
184                 {
185                     m_xDialog.endExecute();
186                 }
187                 catch( Exception e )
188                 {
189                     e.printStackTrace();
190                 }
191                 m_bResult = true;
192             }
193         }
194     }
195 }
196