/* -*- 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/. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef DISABLE_DYNLOADING #include #endif namespace { sal_uInt16 mapStockToImageResource(const OString& sType) { sal_uInt16 nRet = 0; if (sType == "gtk-index") nRet = SV_RESID_BITMAP_INDEX; else if (sType == "gtk-refresh") nRet = SV_RESID_BITMAP_REFRESH; return nRet; } SymbolType mapStockToSymbol(const OString& sType) { SymbolType eRet = SymbolType::DONTKNOW; if (sType == "gtk-media-next") eRet = SymbolType::NEXT; else if (sType == "gtk-media-previous") eRet = SymbolType::PREV; else if (sType == "gtk-media-play") eRet = SymbolType::PLAY; else if (sType == "gtk-media-stop") eRet = SymbolType::STOP; else if (sType == "gtk-goto-first") eRet = SymbolType::FIRST; else if (sType == "gtk-goto-last") eRet = SymbolType::LAST; else if (sType == "gtk-go-back") eRet = SymbolType::ARROW_LEFT; else if (sType == "gtk-go-forward") eRet = SymbolType::ARROW_RIGHT; else if (sType == "gtk-go-up") eRet = SymbolType::ARROW_UP; else if (sType == "gtk-go-down") eRet = SymbolType::ARROW_DOWN; else if (sType == "gtk-missing-image") eRet = SymbolType::IMAGE; else if (sType == "gtk-help") eRet = SymbolType::HELP; else if (sType == "gtk-close") eRet = SymbolType::CLOSE; else if (mapStockToImageResource(sType)) eRet = SymbolType::IMAGE; return eRet; } } void VclBuilder::loadTranslations(const LanguageTag &rLanguageTag, const OUString& rUri) { /* FIXME-BCP47: support language tags with * LanguageTag::getFallbackStrings() ? */ for (int i = rLanguageTag.getCountry().isEmpty() ? 1 : 0; i < 2; ++i) { OUStringBuffer aTransBuf; sal_Int32 nLastSlash = rUri.lastIndexOf('/'); if (nLastSlash != -1) aTransBuf.append(rUri.copy(0, nLastSlash)); else { aTransBuf.append('.'); nLastSlash = 0; } aTransBuf.append("/res/"); OUString sLang(rLanguageTag.getLanguage()); switch (i) { case 0: sLang = sLang + "-" + rLanguageTag.getCountry(); break; default: break; } aTransBuf.append(sLang); aTransBuf.append(".zip"); sal_Int32 nEndName = rUri.lastIndexOf('.'); if (nEndName == -1) nEndName = rUri.getLength(); OUString sZippedFile(rUri.copy(nLastSlash + 1, nEndName - nLastSlash - 1) + "/" + sLang + ".ui"); try { css::uno::Reference xNameAccess = css::packages::zip::ZipFileAccess::createWithURL( comphelper::getProcessComponentContext(), aTransBuf.makeStringAndClear()); if (!xNameAccess.is()) continue; css::uno::Reference xInputStream(xNameAccess->getByName(sZippedFile), css::uno::UNO_QUERY); if (!xInputStream.is()) continue; OStringBuffer sStr; for (;;) { sal_Int32 const size = 2048; css::uno::Sequence< sal_Int8 > data(size); sal_Int32 n = xInputStream->readBytes(data, size); sStr.append(reinterpret_cast(data.getConstArray()), n); if (n < size) break; } xmlreader::XmlReader reader(sStr.getStr(), sStr.getLength()); handleTranslations(reader); break; } catch (const css::uno::Exception &) { } } } #if defined SAL_LOG_WARN namespace { bool isButtonType(WindowType nType) { return nType == WINDOW_PUSHBUTTON || nType == WINDOW_OKBUTTON || nType == WINDOW_CANCELBUTTON || nType == WINDOW_HELPBUTTON || nType == WINDOW_IMAGEBUTTON || nType == WINDOW_MENUBUTTON || nType == WINDOW_MOREBUTTON || nType == WINDOW_SPINBUTTON; } } #endif VclBuilder::VclBuilder(vcl::Window *pParent, const OUString& sUIDir, const OUString& sUIFile, const OString& sID, const css::uno::Reference& rFrame) : m_sID(sID) , m_sHelpRoot(OUStringToOString(sUIFile, RTL_TEXTENCODING_UTF8)) , m_pStringReplace(ResMgr::GetReadStringHook()) , m_pParent(pParent) , m_bToplevelParentFound(false) , m_pParserState(new ParserState) , m_xFrame(rFrame) { m_bToplevelHasDeferredInit = pParent && ((pParent->IsSystemWindow() && static_cast(pParent)->isDeferredInit()) || (pParent->IsDockingWindow() && static_cast(pParent)->isDeferredInit())); m_bToplevelHasDeferredProperties = m_bToplevelHasDeferredInit; sal_Int32 nIdx = m_sHelpRoot.lastIndexOf('.'); if (nIdx != -1) m_sHelpRoot = m_sHelpRoot.copy(0, nIdx); m_sHelpRoot = m_sHelpRoot + OString('/'); OUString sUri = sUIDir + sUIFile; const LanguageTag& rLanguageTag = Application::GetSettings().GetUILanguageTag(); bool bEN_US = (rLanguageTag.getBcp47() == "en-US"); if (!bEN_US) loadTranslations(rLanguageTag, sUri); try { xmlreader::XmlReader reader(sUri); handleChild(pParent, reader); } catch (const css::uno::Exception &rExcept) { SAL_WARN("vcl.layout", "Unable to read .ui file: " << rExcept.Message); throw; } //Set Mnemonic widgets when everything has been imported for (std::vector::iterator aI = m_pParserState->m_aMnemonicWidgetMaps.begin(), aEnd = m_pParserState->m_aMnemonicWidgetMaps.end(); aI != aEnd; ++aI) { FixedText *pOne = get(aI->m_sID); vcl::Window *pOther = get(aI->m_sValue); SAL_WARN_IF(!pOne || !pOther, "vcl", "missing either source " << aI->m_sID << " or target " << aI->m_sValue << " member of Mnemonic Widget Mapping"); if (pOne && pOther) pOne->set_mnemonic_widget(pOther); } //Set a11y relations when everything has been imported for (AtkMap::iterator aI = m_pParserState->m_aAtkInfo.begin(), aEnd = m_pParserState->m_aAtkInfo.end(); aI != aEnd; ++aI) { vcl::Window *pSource = aI->first; const stringmap &rMap = aI->second; for (stringmap::const_iterator aP = rMap.begin(), aEndP = rMap.end(); aP != aEndP; ++aP) { const OString &rTarget = aP->second; vcl::Window *pTarget = get(rTarget); SAL_WARN_IF(!pTarget, "vcl", "missing member of a11y relation: " << rTarget.getStr()); if (!pTarget) continue; const OString &rType = aP->first; if (rType == "labelled-by") pSource->SetAccessibleRelationLabeledBy(pTarget); else if (rType == "label-for") pSource->SetAccessibleRelationLabelFor(pTarget); else if (rType == "member-of") pSource->SetAccessibleRelationMemberOf(pTarget); else { SAL_INFO("vcl.layout", "unhandled a11y relation :" << rType.getStr()); } } } //Set radiobutton groups when everything has been imported for (std::vector::iterator aI = m_pParserState->m_aGroupMaps.begin(), aEnd = m_pParserState->m_aGroupMaps.end(); aI != aEnd; ++aI) { RadioButton *pOne = get(aI->m_sID); RadioButton *pOther = get(aI->m_sValue); SAL_WARN_IF(!pOne || !pOther, "vcl", "missing member of radiobutton group"); if (pOne && pOther) pOne->group(*pOther); } //Set ComboBox models when everything has been imported for (std::vector::iterator aI = m_pParserState->m_aModelMaps.begin(), aEnd = m_pParserState->m_aModelMaps.end(); aI != aEnd; ++aI) { ListBox *pTarget = get(aI->m_sID); const ListStore *pStore = get_model_by_name(aI->m_sValue); SAL_WARN_IF(!pTarget || !pStore, "vcl", "missing elements of combobox/liststore"); if (pTarget && pStore) mungeModel(*pTarget, *pStore, aI->m_nActiveId); } //Set TextView buffers when everything has been imported for (std::vector::iterator aI = m_pParserState->m_aTextBufferMaps.begin(), aEnd = m_pParserState->m_aTextBufferMaps.end(); aI != aEnd; ++aI) { VclMultiLineEdit *pTarget = get(aI->m_sID); const TextBuffer *pBuffer = get_buffer_by_name(aI->m_sValue); SAL_WARN_IF(!pTarget || !pBuffer, "vcl", "missing elements of textview/textbuffer"); if (pTarget && pBuffer) mungeTextBuffer(*pTarget, *pBuffer); } //Set SpinButton adjustments when everything has been imported for (std::vector::iterator aI = m_pParserState->m_aNumericFormatterAdjustmentMaps.begin(), aEnd = m_pParserState->m_aNumericFormatterAdjustmentMaps.end(); aI != aEnd; ++aI) { NumericFormatter *pTarget = dynamic_cast(get(aI->m_sID)); const Adjustment *pAdjustment = get_adjustment_by_name(aI->m_sValue); SAL_WARN_IF(!pTarget, "vcl", "missing NumericFormatter element of spinbutton/adjustment"); SAL_WARN_IF(!pAdjustment, "vcl", "missing Adjustment element of spinbutton/adjustment"); if (pTarget && pAdjustment) mungeAdjustment(*pTarget, *pAdjustment); } for (std::vector::iterator aI = m_pParserState->m_aTimeFormatterAdjustmentMaps.begin(), aEnd = m_pParserState->m_aTimeFormatterAdjustmentMaps.end(); aI != aEnd; ++aI) { TimeField *pTarget = dynamic_cast(get(aI->m_sID)); const Adjustment *pAdjustment = get_adjustment_by_name(aI->m_sValue); SAL_WARN_IF(!pTarget || !pAdjustment, "vcl", "missing elements of spinbutton/adjustment"); if (pTarget && pAdjustment) mungeAdjustment(*pTarget, *pAdjustment); } for (std::vector::iterator aI = m_pParserState->m_aDateFormatterAdjustmentMaps.begin(), aEnd = m_pParserState->m_aDateFormatterAdjustmentMaps.end(); aI != aEnd; ++aI) { DateField *pTarget = dynamic_cast(get(aI->m_sID)); const Adjustment *pAdjustment = get_adjustment_by_name(aI->m_sValue); SAL_WARN_IF(!pTarget || !pAdjustment, "vcl", "missing elements of spinbutton/adjustment"); if (pTarget && pAdjustment) mungeAdjustment(*pTarget, *pAdjustment); } //Set ScrollBar adjustments when everything has been imported for (std::vector::iterator aI = m_pParserState->m_aScrollAdjustmentMaps.begin(), aEnd = m_pParserState->m_aScrollAdjustmentMaps.end(); aI != aEnd; ++aI) { ScrollBar *pTarget = get(aI->m_sID); const Adjustment *pAdjustment = get_adjustment_by_name(aI->m_sValue); SAL_WARN_IF(!pTarget || !pAdjustment, "vcl", "missing elements of scrollbar/adjustment"); if (pTarget && pAdjustment) mungeAdjustment(*pTarget, *pAdjustment); } //Set Scale(Slider) adjustments std::vector::iterator aIterator; for (aIterator = m_pParserState->m_aSliderAdjustmentMaps.begin(); aIterator != m_pParserState->m_aSliderAdjustmentMaps.end(); ++aIterator) { Slider* pTarget = dynamic_cast(get(aIterator->m_sID)); const Adjustment* pAdjustment = get_adjustment_by_name(aIterator->m_sValue); SAL_WARN_IF(!pTarget || !pAdjustment, "vcl", "missing elements of scale(slider)/adjustment"); if (pTarget && pAdjustment) { mungeAdjustment(*pTarget, *pAdjustment); } } //Set size-groups when all widgets have been imported for (std::vector::iterator aI = m_pParserState->m_aSizeGroups.begin(), aEnd = m_pParserState->m_aSizeGroups.end(); aI != aEnd; ++aI) { std::shared_ptr xGroup(std::make_shared()); for (stringmap::iterator aP = aI->m_aProperties.begin(), aEndP = aI->m_aProperties.end(); aP != aEndP; ++aP) { const OString &rKey = aP->first; const OString &rValue = aP->second; xGroup->set_property(rKey, rValue); } for (std::vector::iterator aW = aI->m_aWidgets.begin(), aEndW = aI->m_aWidgets.end(); aW != aEndW; ++aW) { vcl::Window* pWindow = get(aW->getStr()); pWindow->add_to_size_group(xGroup); } } //Set button images when everything has been imported std::set aImagesToBeRemoved; for (std::vector::iterator aI = m_pParserState->m_aButtonImageWidgetMaps.begin(), aEnd = m_pParserState->m_aButtonImageWidgetMaps.end(); aI != aEnd; ++aI) { PushButton *pTargetButton = nullptr; RadioButton *pTargetRadio = nullptr; Button *pTarget = nullptr; if (!aI->m_bRadio) { pTargetButton = get(aI->m_sID); pTarget = pTargetButton; } else { pTargetRadio = get(aI->m_sID); pTarget = pTargetRadio; } FixedImage *pImage = get(aI->m_sValue); SAL_WARN_IF(!pTarget || !pImage, "vcl", "missing elements of button/image/stock"); if (!pTarget || !pImage) continue; aImagesToBeRemoved.insert(aI->m_sValue); VclBuilder::StockMap::iterator aFind = m_pParserState->m_aStockMap.find(aI->m_sValue); if (aFind == m_pParserState->m_aStockMap.end()) { if (!aI->m_bRadio) pTargetButton->SetModeImage(pImage->GetImage()); else pTargetRadio->SetModeRadioImage(pImage->GetImage()); } else { const stockinfo &rImageInfo = aFind->second; SymbolType eType = mapStockToSymbol(rImageInfo.m_sStock); SAL_WARN_IF(eType == SymbolType::DONTKNOW, "vcl", "missing stock image element for button"); if (eType == SymbolType::DONTKNOW) continue; if (!aI->m_bRadio) { pTargetButton->SetSymbol(eType); //fdo#76457 keep symbol images small e.g. tools->customize->menu //but images the right size. Really the PushButton::CalcMinimumSize //and PushButton::ImplDrawPushButton are the better place to handle //this, but its such a train-wreck if (eType != SymbolType::IMAGE) pTargetButton->SetStyle(pTargetButton->GetStyle() | WB_SMALLSTYLE); } else SAL_WARN_IF(eType != SymbolType::IMAGE, "vcl.layout", "inimplemented symbol type for radiobuttons"); if (eType == SymbolType::IMAGE) { Bitmap aBitmap(VclResId(mapStockToImageResource(rImageInfo.m_sStock))); Image const aImage(aBitmap); if (!aI->m_bRadio) pTargetButton->SetModeImage(aImage); else pTargetRadio->SetModeRadioImage(aImage); } switch (rImageInfo.m_nSize) { case 1: pTarget->SetSmallSymbol(); break; case 4: break; default: SAL_WARN("vcl.layout", "unsupported image size " << rImageInfo.m_nSize); break; } } } //There may be duplicate use of an Image, so we used a set to collect and //now we can remove them from the tree after their final munge for (std::set::iterator aI = aImagesToBeRemoved.begin(), aEnd = aImagesToBeRemoved.end(); aI != aEnd; ++aI) { delete_by_name(*aI); } //Set button menus when everything has been imported for (std::vector::iterator aI = m_pParserState->m_aButtonMenuMaps.begin(), aEnd = m_pParserState->m_aButtonMenuMaps.end(); aI != aEnd; ++aI) { MenuButton *pTarget = get(aI->m_sID); PopupMenu *pMenu = get_menu(aI->m_sValue); SAL_WARN_IF(!pTarget || !pMenu, "vcl", "missing elements of button/menu"); if (!pTarget || !pMenu) continue; pTarget->SetPopupMenu(pMenu); } //Remove ScrollWindow parent widgets whose children in vcl implement scrolling //internally. for (auto aI = m_pParserState->m_aRedundantParentWidgets.begin(), aEnd = m_pParserState->m_aRedundantParentWidgets.end(); aI != aEnd; ++aI) { delete_by_window(aI->first); } //fdo#67378 merge the label into the disclosure button for (auto aI = m_pParserState->m_aExpanderWidgets.begin(), aEnd = m_pParserState->m_aExpanderWidgets.end(); aI != aEnd; ++aI) { VclExpander *pOne = *aI; vcl::Window *pChild = pOne->get_child(); vcl::Window* pLabel = pOne->GetWindow(GetWindowType::LastChild); if (pLabel && pLabel != pChild && pLabel->GetType() == WINDOW_FIXEDTEXT) { FixedText *pLabelWidget = static_cast(pLabel); pOne->set_label(pLabelWidget->GetText()); delete_by_window(pLabel); } } //drop maps, etc. that we don't need again m_pParserState.reset(); SAL_WARN_IF(!m_sID.isEmpty() && (!m_bToplevelParentFound && !get_by_name(m_sID)), "vcl.layout", "Requested top level widget \"" << m_sID.getStr() << "\" not found in " << sUIFile); #if defined SAL_LOG_WARN if (m_bToplevelParentFound && m_pParent->IsDialog()) { int nButtons = 0; bool bHasDefButton = false; for (std::vector::iterator aI = m_aChildren.begin(), aEnd = m_aChildren.end(); aI != aEnd; ++aI) { if (isButtonType(aI->m_pWindow->GetType())) { ++nButtons; if (aI->m_pWindow->GetStyle() & WB_DEFBUTTON) { bHasDefButton = true; break; } } } SAL_WARN_IF(nButtons && !bHasDefButton, "vcl.layout", "No default button defined in " << sUIFile); } #endif } VclBuilder::~VclBuilder() { disposeBuilder(); } void VclBuilder::disposeBuilder() { for (std::vector::reverse_iterator aI = m_aChildren.rbegin(), aEnd = m_aChildren.rend(); aI != aEnd; ++aI) { aI->m_pWindow.disposeAndClear(); } m_aChildren.clear(); for (std::vector::reverse_iterator aI = m_aMenus.rbegin(), aEnd = m_aMenus.rend(); aI != aEnd; ++aI) { delete aI->m_pMenu; } m_aMenus.clear(); m_pParent.clear(); } void VclBuilder::handleTranslations(xmlreader::XmlReader &reader) { xmlreader::Span name; int nsId; OString sID, sProperty; while(true) { xmlreader::XmlReader::Result res = reader.nextItem( xmlreader::XmlReader::TEXT_RAW, &name, &nsId); if (res == xmlreader::XmlReader::RESULT_BEGIN) { if (name.equals("e")) { while (reader.nextAttribute(&nsId, &name)) { if (name.equals("g")) { name = reader.getAttributeValue(false); sID = OString(name.begin, name.length); sal_Int32 nDelim = sID.indexOf(':'); if (nDelim != -1) sID = sID.copy(nDelim); } else if (name.equals("i")) { name = reader.getAttributeValue(false); sProperty = OString(name.begin, name.length); } } } } if (res == xmlreader::XmlReader::RESULT_TEXT && !sID.isEmpty()) { OString sTranslation(name.begin, name.length); m_pParserState->m_aTranslations[sID][sProperty] = sTranslation; } if (res == xmlreader::XmlReader::RESULT_END) sID.clear(); if (res == xmlreader::XmlReader::RESULT_DONE) break; } } OString VclBuilder::extractCustomProperty(VclBuilder::stringmap &rMap) { OString sCustomProperty; VclBuilder::stringmap::iterator aFind = rMap.find(OString("customproperty")); if (aFind != rMap.end()) { sCustomProperty = aFind->second; rMap.erase(aFind); } return sCustomProperty; } namespace { bool extractDrawValue(VclBuilder::stringmap& rMap) { bool bDrawValue = true; VclBuilder::stringmap::iterator aFind = rMap.find(OString("draw_value")); if (aFind != rMap.end()) { bDrawValue = toBool(aFind->second); rMap.erase(aFind); } return bDrawValue; } OString extractValuePos(VclBuilder::stringmap& rMap) { OString sRet("top"); VclBuilder::stringmap::iterator aFind = rMap.find(OString("value_pos")); if (aFind != rMap.end()) { sRet = aFind->second; rMap.erase(aFind); } return sRet; } OString extractTypeHint(VclBuilder::stringmap &rMap) { OString sRet("normal"); VclBuilder::stringmap::iterator aFind = rMap.find(OString("type-hint")); if (aFind != rMap.end()) { sRet = aFind->second; rMap.erase(aFind); } return sRet; } bool extractResizable(VclBuilder::stringmap &rMap) { bool bResizable = true; VclBuilder::stringmap::iterator aFind = rMap.find(OString("resizable")); if (aFind != rMap.end()) { bResizable = toBool(aFind->second); rMap.erase(aFind); } return bResizable; } bool extractDecorated(VclBuilder::stringmap &rMap) { bool bDecorated = true; VclBuilder::stringmap::iterator aFind = rMap.find(OString("decorated")); if (aFind != rMap.end()) { bDecorated = toBool(aFind->second); rMap.erase(aFind); } return bDecorated; } bool extractCloseable(VclBuilder::stringmap &rMap) { bool bCloseable = true; VclBuilder::stringmap::iterator aFind = rMap.find(OString("deletable")); if (aFind != rMap.end()) { bCloseable = toBool(aFind->second); rMap.erase(aFind); } return bCloseable; } bool extractEntry(VclBuilder::stringmap &rMap) { bool bHasEntry = false; VclBuilder::stringmap::iterator aFind = rMap.find(OString("has-entry")); if (aFind != rMap.end()) { bHasEntry = toBool(aFind->second); rMap.erase(aFind); } return bHasEntry; } bool extractOrientation(VclBuilder::stringmap &rMap) { bool bVertical = false; VclBuilder::stringmap::iterator aFind = rMap.find(OString("orientation")); if (aFind != rMap.end()) { bVertical = aFind->second.equalsIgnoreAsciiCase("vertical"); rMap.erase(aFind); } return bVertical; } bool extractInconsistent(VclBuilder::stringmap &rMap) { bool bInconsistent = false; VclBuilder::stringmap::iterator aFind = rMap.find(OString("inconsistent")); if (aFind != rMap.end()) { bInconsistent = toBool(aFind->second); rMap.erase(aFind); } return bInconsistent; } OString extractIconName(VclBuilder::stringmap &rMap) { OString sIconName; VclBuilder::stringmap::iterator aFind = rMap.find(OString("icon-name")); if (aFind != rMap.end()) { sIconName = aFind->second; rMap.erase(aFind); } return sIconName; } OUString getStockText(const OString &rType) { if (rType == "gtk-ok") return (VclResId(SV_BUTTONTEXT_OK).toString()); else if (rType == "gtk-cancel") return (VclResId(SV_BUTTONTEXT_CANCEL).toString()); else if (rType == "gtk-help") return (VclResId(SV_BUTTONTEXT_HELP).toString()); else if (rType == "gtk-close") return (VclResId(SV_BUTTONTEXT_CLOSE).toString()); else if (rType == "gtk-revert-to-saved") return (VclResId(SV_BUTTONTEXT_RESET).toString()); else if (rType == "gtk-add") return (VclResId(SV_BUTTONTEXT_ADD).toString()); else if (rType == "gtk-delete") return (VclResId(SV_BUTTONTEXT_DELETE).toString()); else if (rType == "gtk-remove") return (VclResId(SV_BUTTONTEXT_REMOVE).toString()); else if (rType == "gtk-new") return (VclResId(SV_BUTTONTEXT_NEW).toString()); else if (rType == "gtk-edit") return (VclResId(SV_BUTTONTEXT_EDIT).toString()); else if (rType == "gtk-apply") return (VclResId(SV_BUTTONTEXT_APPLY).toString()); else if (rType == "gtk-save") return (VclResId(SV_BUTTONTEXT_SAVE).toString()); else if (rType == "gtk-open") return (VclResId(SV_BUTTONTEXT_OPEN).toString()); else if (rType == "gtk-undo") return (VclResId(SV_BUTTONTEXT_UNDO).toString()); else if (rType == "gtk-paste") return (VclResId(SV_BUTTONTEXT_PASTE).toString()); else if (rType == "gtk-media-next") return (VclResId(SV_BUTTONTEXT_NEXT).toString()); else if (rType == "gtk-go-up") return (VclResId(SV_BUTTONTEXT_GO_UP).toString()); else if (rType == "gtk-go-down") return (VclResId(SV_BUTTONTEXT_GO_DOWN).toString()); else if (rType == "gtk-clear") return (VclResId(SV_BUTTONTEXT_CLEAR).toString()); else if (rType == "gtk-media-play") return (VclResId(SV_BUTTONTEXT_PLAY).toString()); else if (rType == "gtk-find") return (VclResId(SV_BUTTONTEXT_FIND).toString()); else if (rType == "gtk-stop") return (VclResId(SV_BUTTONTEXT_STOP).toString()); else if (rType == "gtk-connect") return (VclResId(SV_BUTTONTEXT_CONNECT).toString()); else if (rType == "gtk-yes") return (VclResId(SV_BUTTONTEXT_YES).toString()); else if (rType == "gtk-no") return (VclResId(SV_BUTTONTEXT_NO).toString()); SAL_WARN("vcl.layout", "unknown stock type: " << rType.getStr()); return OUString(); } bool extractStock(VclBuilder::stringmap &rMap) { bool bIsStock = false; VclBuilder::stringmap::iterator aFind = rMap.find(OString("use-stock")); if (aFind != rMap.end()) { bIsStock = toBool(aFind->second); rMap.erase(aFind); } return bIsStock; } WinBits extractRelief(VclBuilder::stringmap &rMap) { WinBits nBits = WB_3DLOOK; VclBuilder::stringmap::iterator aFind = rMap.find(OString("relief")); if (aFind != rMap.end()) { if (aFind->second == "half") nBits = WB_FLATBUTTON | WB_BEVELBUTTON; else if (aFind->second == "none") nBits = WB_FLATBUTTON; rMap.erase(aFind); } return nBits; } OString extractLabel(VclBuilder::stringmap &rMap) { OString sType; VclBuilder::stringmap::iterator aFind = rMap.find(OString("label")); if (aFind != rMap.end()) { sType = aFind->second; rMap.erase(aFind); } return sType; } OString extractActionName(VclBuilder::stringmap &rMap) { OString sActionName; VclBuilder::stringmap::iterator aFind = rMap.find(OString("action-name")); if (aFind != rMap.end()) { sActionName = aFind->second; rMap.erase(aFind); } return sActionName; } bool extractVisible(VclBuilder::stringmap &rMap) { VclBuilder::stringmap::iterator aFind = rMap.find(OString("visible")); if (aFind != rMap.end()) { return toBool(aFind->second); } return false; } Size extractSizeRequest(VclBuilder::stringmap &rMap) { OString sWidthRequest("0"); OString sHeightRequest("0"); VclBuilder::stringmap::iterator aFind = rMap.find(OString("width-request")); if (aFind != rMap.end()) { sWidthRequest = aFind->second; rMap.erase(aFind); } aFind = rMap.find(OString("height-request")); if (aFind != rMap.end()) { sHeightRequest = aFind->second; rMap.erase(aFind); } return Size(sWidthRequest.toInt32(), sHeightRequest.toInt32()); } OString extractTooltipText(VclBuilder::stringmap &rMap) { OString sTooltipText; VclBuilder::stringmap::iterator aFind = rMap.find(OString("tooltip-text")); if (aFind == rMap.end()) aFind = rMap.find(OString("tooltip-markup")); if (aFind != rMap.end()) { sTooltipText = aFind->second; rMap.erase(aFind); } return sTooltipText; } void setupFromActionName(Button *pButton, VclBuilder::stringmap &rMap, const css::uno::Reference& rFrame) { if (!rFrame.is()) return; OUString aCommand(OStringToOUString(extractActionName(rMap), RTL_TEXTENCODING_UTF8)); if (aCommand.isEmpty()) return; OUString aLabel(vcl::CommandInfoProvider::Instance().GetLabelForCommand(aCommand, rFrame)); if (!aLabel.isEmpty()) pButton->SetText(aLabel); OUString aTooltip(vcl::CommandInfoProvider::Instance().GetTooltipForCommand(aCommand, rFrame)); if (!aTooltip.isEmpty()) pButton->SetQuickHelpText(aTooltip); Image aImage(vcl::CommandInfoProvider::Instance().GetImageForCommand(aCommand, /*bLarge=*/ false, rFrame)); pButton->SetModeImage(aImage); pButton->SetCommandHandler(aCommand); } VclPtr