merge the formfield patch from ooo-build
[ooovba.git] / svtools / source / misc / acceleratorexecute.cxx
blob21d7f1b47e435ed15b1150d183dd313abd441591
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: acceleratorexecute.cxx,v $
10 * $Revision: 1.14.90.1 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_svtools.hxx"
33 #include "acceleratorexecute.hxx"
35 //===============================================
36 // includes
38 #ifndef __COM_SUN_STAR_FRAME_XMODULEMANAGER_HPP_
39 #include <com/sun/star/frame/XModuleManager.hpp>
40 #endif
42 #ifndef __COM_SUN_STAR_FRAME_XDESKTOP_HPP_
43 #include <com/sun/star/frame/XDesktop.hpp>
44 #endif
46 #ifndef __COM_SUN_STAR_UI_XUICONFIGURATIONMANAGER_HPP_
47 #include <com/sun/star/ui/XUIConfigurationManager.hpp>
48 #endif
50 #ifndef __COM_SUN_STAR_UI_XMODULEUICONFIGURATIONMANAGERSUPPLIER_HPP_
51 #include <com/sun/star/ui/XModuleUIConfigurationManagerSupplier.hpp>
52 #endif
54 #ifndef __COM_SUN_STAR_UI_XUICONFIGURATIONMANAGERSUPPLIER_HPP_
55 #include <com/sun/star/ui/XUIConfigurationManagerSupplier.hpp>
56 #endif
58 #ifndef __COM_SUN_STAR_AWT_XTOPWINDOW_HPP_
59 #include <com/sun/star/awt/XTopWindow.hpp>
60 #endif
62 #ifndef __COM_SUN_STAR_AWT_KEYMODIFIER_HPP_
63 #include <com/sun/star/awt/KeyModifier.hpp>
64 #endif
66 #ifndef __COM_SUN_STAR_UNO_SEQUENCE_HXX_
67 #include <com/sun/star/uno/Sequence.hxx>
68 #endif
70 #ifndef __COM_SUN_STAR_BEANS_PROPERTYVALUE_HPP_
71 #include <com/sun/star/beans/PropertyValue.hpp>
72 #endif
74 #ifndef __COM_SUN_STAR_LANG_DISPOSEDEXCEPTION_HPP_
75 #include <com/sun/star/lang/DisposedException.hpp>
76 #endif
77 #include <toolkit/helper/vclunohelper.hxx>
79 #include <vcl/window.hxx>
80 #include <vcl/svapp.hxx>
81 #include <vos/mutex.hxx>
83 //===============================================
84 // namespace
86 namespace css = ::com::sun::star;
88 namespace svt
91 //===============================================
92 // definitions
94 //-----------------------------------------------
95 class SVT_DLLPRIVATE AsyncAccelExec
97 public:
99 //---------------------------------------
100 /** creates a new instance of this class, which can be used
101 one times only!
103 This instance can be forced to execute it's internal set request
104 asynchronous. After that it deletes itself !
106 static AsyncAccelExec* createOnShotInstance(const css::uno::Reference< css::frame::XDispatch >& xDispatch,
107 const css::util::URL& aURL );
109 void execAsync();
111 private:
113 //---------------------------------------
114 /** @short allow creation of instances of this class
115 by using our factory only!
117 SVT_DLLPRIVATE AsyncAccelExec(const css::uno::Reference< css::frame::XDispatch >& xDispatch,
118 const css::util::URL& aURL );
120 DECL_DLLPRIVATE_LINK(impl_ts_asyncCallback, void*);
122 private:
124 ::vcl::EventPoster m_aAsyncCallback;
125 css::uno::Reference< css::frame::XDispatch > m_xDispatch;
126 css::util::URL m_aURL;
129 //-----------------------------------------------
130 AcceleratorExecute::AcceleratorExecute()
131 : TMutexInit ( )
132 , m_aAsyncCallback(LINK(this, AcceleratorExecute, impl_ts_asyncCallback))
136 //-----------------------------------------------
137 AcceleratorExecute::AcceleratorExecute(const AcceleratorExecute&)
138 : TMutexInit ( )
139 , m_aAsyncCallback(LINK(this, AcceleratorExecute, impl_ts_asyncCallback))
141 // copy construction sint supported in real ...
142 // but we need this ctor to init our async callback ...
145 //-----------------------------------------------
146 AcceleratorExecute::~AcceleratorExecute()
148 // does nothing real
151 //-----------------------------------------------
152 AcceleratorExecute* AcceleratorExecute::createAcceleratorHelper()
154 AcceleratorExecute* pNew = new AcceleratorExecute();
155 return pNew;
158 //-----------------------------------------------
159 void AcceleratorExecute::init(const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR,
160 const css::uno::Reference< css::frame::XFrame >& xEnv )
162 // SAFE -> ----------------------------------
163 ::osl::ResettableMutexGuard aLock(m_aLock);
165 // take over the uno service manager
166 m_xSMGR = xSMGR;
168 // specify our internal dispatch provider
169 // frame or desktop?! => document or global config.
170 sal_Bool bDesktopIsUsed = sal_False;
171 m_xDispatcher = css::uno::Reference< css::frame::XDispatchProvider >(xEnv, css::uno::UNO_QUERY);
172 if (!m_xDispatcher.is())
174 aLock.clear();
175 // <- SAFE ------------------------------
177 css::uno::Reference< css::frame::XDispatchProvider > xDispatcher(
178 xSMGR->createInstance(::rtl::OUString::createFromAscii("com.sun.star.frame.Desktop")),
179 css::uno::UNO_QUERY_THROW);
181 // SAFE -> ------------------------------
182 aLock.reset();
184 m_xDispatcher = xDispatcher;
185 bDesktopIsUsed = sal_True;
188 aLock.clear();
189 // <- SAFE ----------------------------------
191 // open all needed configuration objects
192 css::uno::Reference< css::ui::XAcceleratorConfiguration > xGlobalCfg;
193 css::uno::Reference< css::ui::XAcceleratorConfiguration > xModuleCfg;
194 css::uno::Reference< css::ui::XAcceleratorConfiguration > xDocCfg ;
196 // global cfg
197 xGlobalCfg = AcceleratorExecute::st_openGlobalConfig(xSMGR);
198 if (!bDesktopIsUsed)
200 // module cfg
201 xModuleCfg = AcceleratorExecute::st_openModuleConfig(xSMGR, xEnv);
203 // doc cfg
204 css::uno::Reference< css::frame::XController > xController;
205 css::uno::Reference< css::frame::XModel > xModel;
206 xController = xEnv->getController();
207 if (xController.is())
208 xModel = xController->getModel();
209 if (xModel.is())
210 xDocCfg = AcceleratorExecute::st_openDocConfig(xModel);
213 // SAFE -> ------------------------------
214 aLock.reset();
216 m_xGlobalCfg = xGlobalCfg;
217 m_xModuleCfg = xModuleCfg;
218 m_xDocCfg = xDocCfg ;
220 aLock.clear();
221 // <- SAFE ----------------------------------
224 //-----------------------------------------------
225 sal_Bool AcceleratorExecute::execute(const KeyCode& aVCLKey)
227 css::awt::KeyEvent aAWTKey = AcceleratorExecute::st_VCLKey2AWTKey(aVCLKey);
228 return execute(aAWTKey);
231 //-----------------------------------------------
232 sal_Bool AcceleratorExecute::execute(const css::awt::KeyEvent& aAWTKey)
234 ::rtl::OUString sCommand = impl_ts_findCommand(aAWTKey);
236 // No Command found? Do nothing! User isnt interested on any error handling .-)
237 if (!sCommand.getLength())
238 return sal_False;
240 // SAFE -> ----------------------------------
241 ::osl::ResettableMutexGuard aLock(m_aLock);
243 css::uno::Reference< css::frame::XDispatchProvider > xProvider = m_xDispatcher;
245 aLock.clear();
246 // <- SAFE ----------------------------------
248 // convert command in URL structure
249 css::uno::Reference< css::util::XURLTransformer > xParser = impl_ts_getURLParser();
250 css::util::URL aURL;
251 aURL.Complete = sCommand;
252 xParser->parseStrict(aURL);
254 // ask for dispatch object
255 css::uno::Reference< css::frame::XDispatch > xDispatch = xProvider->queryDispatch(aURL, ::rtl::OUString(), 0);
256 sal_Bool bRet = xDispatch.is();
257 if ( bRet )
259 // Note: Such instance can be used one times only and destroy itself afterwards .-)
260 AsyncAccelExec* pExec = AsyncAccelExec::createOnShotInstance(xDispatch, aURL);
261 pExec->execAsync();
264 return bRet;
267 //-----------------------------------------------
268 css::awt::KeyEvent AcceleratorExecute::st_VCLKey2AWTKey(const KeyCode& aVCLKey)
270 css::awt::KeyEvent aAWTKey;
271 aAWTKey.Modifiers = 0;
272 aAWTKey.KeyCode = (sal_Int16)aVCLKey.GetCode();
274 if (aVCLKey.IsShift())
275 aAWTKey.Modifiers |= css::awt::KeyModifier::SHIFT;
276 if (aVCLKey.IsMod1())
277 aAWTKey.Modifiers |= css::awt::KeyModifier::MOD1;
278 if (aVCLKey.IsMod2())
279 aAWTKey.Modifiers |= css::awt::KeyModifier::MOD2;
280 if (aVCLKey.IsMod3())
281 aAWTKey.Modifiers |= css::awt::KeyModifier::MOD3;
282 return aAWTKey;
285 //-----------------------------------------------
286 KeyCode AcceleratorExecute::st_AWTKey2VCLKey(const css::awt::KeyEvent& aAWTKey)
288 sal_Bool bShift = ((aAWTKey.Modifiers & css::awt::KeyModifier::SHIFT) == css::awt::KeyModifier::SHIFT );
289 sal_Bool bMod1 = ((aAWTKey.Modifiers & css::awt::KeyModifier::MOD1 ) == css::awt::KeyModifier::MOD1 );
290 sal_Bool bMod2 = ((aAWTKey.Modifiers & css::awt::KeyModifier::MOD2 ) == css::awt::KeyModifier::MOD2 );
291 sal_Bool bMod3 = ((aAWTKey.Modifiers & css::awt::KeyModifier::MOD3 ) == css::awt::KeyModifier::MOD3 );
292 USHORT nKey = (USHORT)aAWTKey.KeyCode;
294 return KeyCode(nKey, bShift, bMod1, bMod2, bMod3);
296 //-----------------------------------------------
297 ::rtl::OUString AcceleratorExecute::findCommand(const css::awt::KeyEvent& aKey)
299 return impl_ts_findCommand(aKey);
301 //-----------------------------------------------
302 ::rtl::OUString AcceleratorExecute::impl_ts_findCommand(const css::awt::KeyEvent& aKey)
304 // SAFE -> ----------------------------------
305 ::osl::ResettableMutexGuard aLock(m_aLock);
307 css::uno::Reference< css::ui::XAcceleratorConfiguration > xGlobalCfg = m_xGlobalCfg;
308 css::uno::Reference< css::ui::XAcceleratorConfiguration > xModuleCfg = m_xModuleCfg;
309 css::uno::Reference< css::ui::XAcceleratorConfiguration > xDocCfg = m_xDocCfg ;
311 aLock.clear();
312 // <- SAFE ----------------------------------
314 ::rtl::OUString sCommand;
318 if (xDocCfg.is())
319 sCommand = xDocCfg->getCommandByKeyEvent(aKey);
320 if (sCommand.getLength())
321 return sCommand;
323 catch(const css::container::NoSuchElementException&)
328 if (xModuleCfg.is())
329 sCommand = xModuleCfg->getCommandByKeyEvent(aKey);
330 if (sCommand.getLength())
331 return sCommand;
333 catch(const css::container::NoSuchElementException&)
338 if (xGlobalCfg.is())
339 sCommand = xGlobalCfg->getCommandByKeyEvent(aKey);
340 if (sCommand.getLength())
341 return sCommand;
343 catch(const css::container::NoSuchElementException&)
346 // fall back to functional key codes
347 if( aKey.Modifiers == 0 )
349 switch( aKey.KeyCode )
351 case com::sun::star::awt::Key::DELETE_TO_BEGIN_OF_LINE:
352 return rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".uno:DelToStartOfLine" ) );
354 case com::sun::star::awt::Key::DELETE_TO_END_OF_LINE:
355 return rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".uno:DelToEndOfLine" ) );
357 case com::sun::star::awt::Key::DELETE_TO_BEGIN_OF_PARAGRAPH:
358 return rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".uno:DelToStartOfPara" ) );
360 case com::sun::star::awt::Key::DELETE_TO_END_OF_PARAGRAPH:
361 return rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".uno:DelToEndOfPara" ) );
363 case com::sun::star::awt::Key::DELETE_WORD_BACKWARD:
364 return rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".uno:DelToStartOfWord" ) );
366 case com::sun::star::awt::Key::DELETE_WORD_FORWARD:
367 return rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".uno:DelToEndOfWord" ) );
369 case com::sun::star::awt::Key::INSERT_LINEBREAK:
370 return rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".uno:InsertLinebreak" ) );
372 case com::sun::star::awt::Key::INSERT_PARAGRAPH:
373 return rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".uno:InsertPara" ) );
375 case com::sun::star::awt::Key::MOVE_WORD_BACKWARD:
376 return rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".uno:GoToPrevWord" ) );
378 case com::sun::star::awt::Key::MOVE_WORD_FORWARD:
379 return rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".uno:GoToNextWord" ) );
381 case com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_LINE:
382 return rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".uno:GoToStartOfLine" ) );
384 case com::sun::star::awt::Key::MOVE_TO_END_OF_LINE:
385 return rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".uno:GoToEndOfLine" ) );
387 case com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_PARAGRAPH:
388 return rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".uno:GoToStartOfPara" ) );
390 case com::sun::star::awt::Key::MOVE_TO_END_OF_PARAGRAPH:
391 return rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".uno:GoToEndOfPara" ) );
393 case com::sun::star::awt::Key::MOVE_TO_BEGIN_OF_DOCUMENT:
394 return rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".uno:GoToStartOfDoc" ) );
396 case com::sun::star::awt::Key::MOVE_TO_END_OF_DOCUMENT:
397 return rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".uno:GoToEndOfDoc" ) );
399 case com::sun::star::awt::Key::SELECT_BACKWARD:
400 return rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".uno:CharLeftSel" ) );
402 case com::sun::star::awt::Key::SELECT_FORWARD:
403 return rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".uno:CharRightSel" ) );
405 case com::sun::star::awt::Key::SELECT_WORD_BACKWARD:
406 return rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".uno:WordLeftSel" ) );
408 case com::sun::star::awt::Key::SELECT_WORD_FORWARD:
409 return rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".uno:WordRightSel" ) );
411 case com::sun::star::awt::Key::SELECT_WORD:
412 return rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".uno:SelectWord" ) );
414 case com::sun::star::awt::Key::SELECT_LINE:
415 return rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "" ) );
417 case com::sun::star::awt::Key::SELECT_PARAGRAPH:
418 return rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".uno:SelectText" ) );
420 case com::sun::star::awt::Key::SELECT_TO_BEGIN_OF_LINE:
421 return rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".uno:StartOfLineSel" ) );
423 case com::sun::star::awt::Key::SELECT_TO_END_OF_LINE:
424 return rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".uno:EndOfLineSel" ) );
426 case com::sun::star::awt::Key::SELECT_TO_BEGIN_OF_PARAGRAPH:
427 return rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".uno:StartOfParaSel" ) );
429 case com::sun::star::awt::Key::SELECT_TO_END_OF_PARAGRAPH:
430 return rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".uno:EndOfParaSel" ) );
432 case com::sun::star::awt::Key::SELECT_TO_BEGIN_OF_DOCUMENT:
433 return rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".uno:StartOfDocumentSel" ) );
435 case com::sun::star::awt::Key::SELECT_TO_END_OF_DOCUMENT:
436 return rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".uno:EndOfDocumentSel" ) );
438 case com::sun::star::awt::Key::SELECT_ALL:
439 return rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".uno:SelectAll" ) );
440 default:
441 break;
445 return ::rtl::OUString();
448 //-----------------------------------------------
449 css::uno::Reference< css::ui::XAcceleratorConfiguration > AcceleratorExecute::st_openGlobalConfig(const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR)
451 css::uno::Reference< css::ui::XAcceleratorConfiguration > xAccCfg(
452 xSMGR->createInstance(::rtl::OUString::createFromAscii("com.sun.star.ui.GlobalAcceleratorConfiguration")),
453 css::uno::UNO_QUERY_THROW);
454 return xAccCfg;
457 //-----------------------------------------------
458 css::uno::Reference< css::ui::XAcceleratorConfiguration > AcceleratorExecute::st_openModuleConfig(const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR ,
459 const css::uno::Reference< css::frame::XFrame >& xFrame)
461 css::uno::Reference< css::frame::XModuleManager > xModuleDetection(
462 xSMGR->createInstance(::rtl::OUString::createFromAscii("com.sun.star.frame.ModuleManager")),
463 css::uno::UNO_QUERY_THROW);
465 ::rtl::OUString sModule;
468 sModule = xModuleDetection->identify(xFrame);
470 catch(const css::uno::RuntimeException&rEx)
471 { (void) rEx; throw; }
472 catch(const css::uno::Exception&)
473 { return css::uno::Reference< css::ui::XAcceleratorConfiguration >(); }
475 css::uno::Reference< css::ui::XModuleUIConfigurationManagerSupplier > xUISupplier(
476 xSMGR->createInstance(::rtl::OUString::createFromAscii("com.sun.star.ui.ModuleUIConfigurationManagerSupplier")),
477 css::uno::UNO_QUERY_THROW);
479 css::uno::Reference< css::ui::XAcceleratorConfiguration > xAccCfg;
482 css::uno::Reference< css::ui::XUIConfigurationManager > xUIManager = xUISupplier->getUIConfigurationManager(sModule);
483 xAccCfg = css::uno::Reference< css::ui::XAcceleratorConfiguration >(xUIManager->getShortCutManager(), css::uno::UNO_QUERY_THROW);
485 catch(const css::container::NoSuchElementException&)
487 return xAccCfg;
490 //-----------------------------------------------
491 css::uno::Reference< css::ui::XAcceleratorConfiguration > AcceleratorExecute::st_openDocConfig(const css::uno::Reference< css::frame::XModel >& xModel)
493 css::uno::Reference< css::ui::XAcceleratorConfiguration > xAccCfg;
494 css::uno::Reference< css::ui::XUIConfigurationManagerSupplier > xUISupplier(xModel, css::uno::UNO_QUERY);
495 if (xUISupplier.is())
497 css::uno::Reference< css::ui::XUIConfigurationManager > xUIManager = xUISupplier->getUIConfigurationManager();
498 xAccCfg.set(xUIManager->getShortCutManager(), css::uno::UNO_QUERY_THROW);
500 return xAccCfg;
503 //-----------------------------------------------
504 css::uno::Reference< css::util::XURLTransformer > AcceleratorExecute::impl_ts_getURLParser()
506 // SAFE -> ----------------------------------
507 ::osl::ResettableMutexGuard aLock(m_aLock);
509 if (m_xURLParser.is())
510 return m_xURLParser;
511 css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR;
513 aLock.clear();
514 // <- SAFE ----------------------------------
516 css::uno::Reference< css::util::XURLTransformer > xParser(
517 xSMGR->createInstance(::rtl::OUString::createFromAscii("com.sun.star.util.URLTransformer")),
518 css::uno::UNO_QUERY_THROW);
520 // SAFE -> ----------------------------------
521 aLock.reset();
522 m_xURLParser = xParser;
523 aLock.clear();
524 // <- SAFE ----------------------------------
526 return xParser;
529 //-----------------------------------------------
530 IMPL_LINK(AcceleratorExecute, impl_ts_asyncCallback, void*, EMPTYARG)
532 // replaced by AsyncAccelExec!
533 return 0;
536 //-----------------------------------------------
537 AsyncAccelExec::AsyncAccelExec(const css::uno::Reference< css::frame::XDispatch >& xDispatch,
538 const css::util::URL& aURL )
539 : m_aAsyncCallback(LINK(this, AsyncAccelExec, impl_ts_asyncCallback))
540 , m_xDispatch (xDispatch )
541 , m_aURL (aURL )
545 //-----------------------------------------------
546 AsyncAccelExec* AsyncAccelExec::createOnShotInstance(const css::uno::Reference< css::frame::XDispatch >& xDispatch,
547 const css::util::URL& aURL )
549 AsyncAccelExec* pExec = new AsyncAccelExec(xDispatch, aURL);
550 return pExec;
553 //-----------------------------------------------
554 void AsyncAccelExec::execAsync()
556 m_aAsyncCallback.Post(0);
559 //-----------------------------------------------
560 IMPL_LINK(AsyncAccelExec, impl_ts_asyncCallback, void*,)
562 if (! m_xDispatch.is())
563 return 0;
567 m_xDispatch->dispatch(m_aURL, css::uno::Sequence< css::beans::PropertyValue >());
569 catch(const css::lang::DisposedException&)
571 catch(const css::uno::RuntimeException& )
572 { throw; }
573 catch(const css::uno::Exception&)
576 delete this;
578 return 0;
581 } // namespace svt