diff options
Diffstat (limited to '')
-rw-r--r-- | include/svl/ondemand.hxx | 288 |
1 files changed, 288 insertions, 0 deletions
diff --git a/include/svl/ondemand.hxx b/include/svl/ondemand.hxx new file mode 100644 index 000000000..5ce944a96 --- /dev/null +++ b/include/svl/ondemand.hxx @@ -0,0 +1,288 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_SVL_ONDEMAND_HXX +#define INCLUDED_SVL_ONDEMAND_HXX + +#include <memory> +#include <unotools/syslocale.hxx> +#include <i18nlangtag/lang.h> +#include <unotools/localedatawrapper.hxx> +#include <unotools/calendarwrapper.hxx> +#include <unotools/transliterationwrapper.hxx> +#include <unotools/nativenumberwrapper.hxx> +#include <com/sun/star/uno/Reference.hxx> +#include <i18nutil/transliteration.hxx> + +/* + On demand instantiation and initialization of several i18n wrappers, + helping the number formatter to not perform worse than it already does. + */ + +/** @short + Switch between LANGUAGE_SYSTEM and LANGUAGE_ENGLISH_US and any other + LocaleDataWrapper. + SvNumberformatter uses it upon switching locales. + + @descr + Avoids reloading and analysing of locale data again and again. + + @ATTENTION + If the default ctor is used the init() method MUST be called before + accessing any locale data. The passed parameters Locale and LanguageType + must match each other. + */ + +class OnDemandLocaleDataWrapper +{ + css::uno::Reference< css::uno::XComponentContext > m_xContext; + SvtSysLocale aSysLocale; + LanguageType eCurrentLanguage; + LanguageType eLastAnyLanguage; + const LocaleDataWrapper* pSystem; + std::unique_ptr<const LocaleDataWrapper> pEnglish; + std::unique_ptr< LocaleDataWrapper> pAny; + const LocaleDataWrapper* pCurrent; + bool bInitialized; + +public: + OnDemandLocaleDataWrapper() + : eLastAnyLanguage( LANGUAGE_DONTKNOW ) + , bInitialized(false) + { + pCurrent = pSystem = aSysLocale.GetLocaleDataPtr(); + eCurrentLanguage = LANGUAGE_SYSTEM; + } + + bool isInitialized() const { return bInitialized; } + + void init( + const css::uno::Reference< css::uno::XComponentContext >& rxContext, + const LanguageTag& rLanguageTag + ) + { + m_xContext = rxContext; + changeLocale( rLanguageTag ); + bInitialized = true; + } + + void changeLocale( const LanguageTag& rLanguageTag ) + { + LanguageType eLang = rLanguageTag.getLanguageType( false); + if ( eLang == LANGUAGE_SYSTEM ) + pCurrent = pSystem; + else if ( eLang == LANGUAGE_ENGLISH_US ) + { + if ( !pEnglish ) + pEnglish.reset( new LocaleDataWrapper( m_xContext, rLanguageTag ) ); + pCurrent = pEnglish.get(); + } + else + { + if ( !pAny ) + { + pAny.reset( new LocaleDataWrapper( m_xContext, rLanguageTag ) ); + eLastAnyLanguage = eLang; + } + else if ( eLastAnyLanguage != eLang ) + { + pAny->setLanguageTag( rLanguageTag ); + eLastAnyLanguage = eLang; + } + pCurrent = pAny.get(); + } + eCurrentLanguage = eLang; + } + + LanguageType getCurrentLanguage() const + { return eCurrentLanguage; } + + const LocaleDataWrapper* get() const { return pCurrent; } + const LocaleDataWrapper* operator->() const { return get(); } + const LocaleDataWrapper& operator*() const { return *pCurrent; } +}; + +/** Load a calendar only if it's needed. Keep calendar for "en-US" locale + separately, as there can be alternation between locale dependent and + locale independent formats. + SvNumberformatter uses it upon switching locales. + + @ATTENTION If the default ctor is used the init() method MUST be called + before accessing the calendar. + */ +class OnDemandCalendarWrapper +{ + css::uno::Reference< css::uno::XComponentContext > m_xContext; + css::lang::Locale aEnglishLocale; + css::lang::Locale aLocale; + mutable css::lang::Locale aLastAnyLocale; + mutable std::unique_ptr<CalendarWrapper> pEnglishPtr; + mutable std::unique_ptr<CalendarWrapper> pAnyPtr; + +public: + OnDemandCalendarWrapper() + { + LanguageTag aEnglishLanguageTag(LANGUAGE_ENGLISH_US); + aEnglishLocale = aEnglishLanguageTag.getLocale(); + aLastAnyLocale = aEnglishLocale; + } + + void init( + const css::uno::Reference< css::uno::XComponentContext >& rxContext, + const css::lang::Locale& rLocale + ) + { + m_xContext = rxContext; + changeLocale( rLocale ); + pEnglishPtr.reset(); + pAnyPtr.reset(); + } + + void changeLocale( const css::lang::Locale& rLocale ) + { + aLocale = rLocale; + } + + CalendarWrapper* get() const + { + CalendarWrapper* pPtr; + if ( aLocale == aEnglishLocale ) + { + if (!pEnglishPtr) + { + pEnglishPtr.reset( new CalendarWrapper( m_xContext )); + pEnglishPtr->loadDefaultCalendar( aEnglishLocale ); + } + pPtr = pEnglishPtr.get(); + } + else + { + if ( !pAnyPtr ) + { + pAnyPtr.reset(new CalendarWrapper( m_xContext )); + pAnyPtr->loadDefaultCalendar(aLocale); + aLastAnyLocale = aLocale; + } + else if ( aLocale != aLastAnyLocale ) + { + pAnyPtr->loadDefaultCalendar( aLocale ); + aLastAnyLocale = aLocale; + } + pPtr = pAnyPtr.get(); + } + return pPtr; + } + +}; + +/** Load a transliteration only if it's needed. + SvNumberformatter uses it upon switching locales. + @ATTENTION If the default ctor is used the init() method MUST be called + before accessing the transliteration. + */ +class OnDemandTransliterationWrapper +{ + css::uno::Reference< css::uno::XComponentContext > m_xContext; + LanguageType eLanguage; + TransliterationFlags nType; + mutable std::unique_ptr<::utl::TransliterationWrapper> + pPtr; + mutable bool bValid; + bool bInitialized; + +public: + OnDemandTransliterationWrapper() + : eLanguage( LANGUAGE_SYSTEM ) + , nType(TransliterationFlags::NONE) + , bValid(false) + , bInitialized(false) + {} + + bool isInitialized() const { return bInitialized; } + + void init( + const css::uno::Reference< css::uno::XComponentContext >& rxContext, + LanguageType eLang + ) + { + m_xContext = rxContext; + nType = TransliterationFlags::IGNORE_CASE; + changeLocale( eLang ); + pPtr.reset(); + bInitialized = true; + } + + void changeLocale( LanguageType eLang ) + { + bValid = false; + eLanguage = eLang; + } + + const ::utl::TransliterationWrapper* get() const + { + if ( !bValid ) + { + if ( !pPtr ) + pPtr.reset( new ::utl::TransliterationWrapper( m_xContext, nType ) ); + pPtr->loadModuleIfNeeded( eLanguage ); + bValid = true; + } + return pPtr.get(); + } + + const ::utl::TransliterationWrapper* operator->() const { return get(); } +}; + +/** Load a native number service wrapper only if it's needed. + SvNumberformatter uses it. + + @ATTENTION + If the default ctor is used the init() method MUST be called + before accessing the native number supplier. + */ +class OnDemandNativeNumberWrapper +{ + css::uno::Reference< css::uno::XComponentContext > m_xContext; + mutable std::unique_ptr<NativeNumberWrapper> + pPtr; + +public: + OnDemandNativeNumberWrapper() + {} + + void init( + const css::uno::Reference< css::uno::XComponentContext >& rxContext + ) + { + m_xContext = rxContext; + pPtr.reset(); + } + + NativeNumberWrapper* get() const + { + if ( !pPtr ) + pPtr.reset(new NativeNumberWrapper( m_xContext )); + return pPtr.get(); + } + +}; + +#endif // INCLUDED_SVL_ONDEMAND_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |