/* -*- 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/.
*/
std::unique_ptr<weld::TreeIter> xEntry(rTreeView.make_iterator(&rIter)); if (!rTreeView.get_iter_first(*xEntry))
xEntry.reset();
while (xEntry && rTreeView.iter_compare(*xEntry, rIter) != 0)
{ if (!rTreeView.iter_next(*xEntry))
xEntry.reset();
nAbsPos++;
}
return nAbsPos;
}
bool IsEntryVisible(const weld::TreeView& rTreeView, const weld::TreeIter& rIter)
{ // short circuit for the common case if (rTreeView.get_iter_depth(rIter) == 0) returntrue;
std::unique_ptr<weld::TreeIter> xEntry(rTreeView.make_iterator(&rIter)); bool bRetVal = false; do
{ if (rTreeView.get_iter_depth(*xEntry) == 0)
{
bRetVal = true; break;
}
} while (rTreeView.iter_parent(*xEntry) && rTreeView.get_row_expanded(*xEntry)); return bRetVal;
}
}
const std::locale& BuilderBase::getResLocale() const
{
assert(m_pParserState && "parser state no more valid"); return m_pParserState->m_aResLocale;
}
const std::vector<BuilderBase::SizeGroup>& BuilderBase::getSizeGroups() const
{
assert(m_pParserState && "parser state no more valid"); return m_pParserState->m_aSizeGroups;
}
const std::vector<BuilderBase::MnemonicWidgetMap>& BuilderBase::getMnemonicWidgetMaps() const {
assert(m_pParserState && "parser state no more valid"); return m_pParserState->m_aMnemonicWidgetMaps;
}
const std::vector<BuilderBase::RadioButtonGroupMap>& BuilderBase::getRadioButtonGroupMaps() const {
assert(m_pParserState && "parser state no more valid"); return m_pParserState->m_aRadioButtonGroupMaps;
}
//Set a11y relations and role when everything has been imported for (autoconst& elemAtk : m_pVclParserState->m_aAtkInfo)
{
vcl::Window *pSource = elemAtk.first; const stringmap &rMap = elemAtk.second;
for (autoconst& [ rType, rParam ] : rMap)
{ if (rType == "role")
{
sal_Int16 role = BuilderUtils::getRoleFromName(rParam); if (role != css::accessibility::AccessibleRole::UNKNOWN)
pSource->SetAccessibleRole(role);
} else
{
vcl::Window *pTarget = get(rParam);
SAL_WARN_IF(!pTarget, "vcl", "missing parameter of a11y relation: " << rParam); if (!pTarget) continue; if (rType == "labelled-by")
pSource->SetAccessibleRelationLabeledBy(pTarget); elseif (rType == "label-for")
pSource->SetAccessibleRelationLabelFor(pTarget); else
{
SAL_WARN("vcl.builder", "unhandled a11y relation :" << rType);
}
}
}
}
#ifndef NDEBUG
o3tl::sorted_vector<OUString> models; #endif //Set ComboBox models when everything has been imported for (autoconst& elem : m_pVclParserState->m_aModelMaps)
{
assert(models.insert(elem.m_sValue).second && "a liststore or treestore is used in duplicate widgets");
vcl::Window* pTarget = get(elem.m_sID);
ListBox *pListBoxTarget = dynamic_cast<ListBox*>(pTarget);
ComboBox *pComboBoxTarget = dynamic_cast<ComboBox*>(pTarget);
SvTabListBox *pTreeBoxTarget = dynamic_cast<SvTabListBox*>(pTarget); // pStore may be empty const ListStore *pStore = get_model_by_name(elem.m_sValue);
SAL_WARN_IF(!pListBoxTarget && !pComboBoxTarget && !pTreeBoxTarget && !dynamic_cast<IconView*>(pTarget), "vcl", "missing elements of combobox"); if (pListBoxTarget && pStore)
mungeModel(*pListBoxTarget, *pStore, elem.m_nActiveId); elseif (pComboBoxTarget && pStore)
mungeModel(*pComboBoxTarget, *pStore, elem.m_nActiveId); elseif (pTreeBoxTarget && pStore)
mungeModel(*pTreeBoxTarget, *pStore, elem.m_nActiveId);
}
//Set TextView buffers when everything has been imported for (autoconst& elem : m_pVclParserState->m_aTextBufferMaps)
{
VclMultiLineEdit *pTarget = get<VclMultiLineEdit>(elem.m_sID); const TextBuffer *pBuffer = get_buffer_by_name(elem.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 (autoconst& elem : m_pVclParserState->m_aNumericFormatterAdjustmentMaps)
{
NumericFormatter *pTarget = dynamic_cast<NumericFormatter*>(get(elem.m_sID)); const Adjustment *pAdjustment = get_adjustment_by_name(elem.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 (autoconst& elem : m_pVclParserState->m_aFormattedFormatterAdjustmentMaps)
{
FormattedField *pTarget = dynamic_cast<FormattedField*>(get(elem.m_sID)); const Adjustment *pAdjustment = get_adjustment_by_name(elem.m_sValue);
SAL_WARN_IF(!pTarget, "vcl", "missing FormattedField element of spinbutton/adjustment");
SAL_WARN_IF(!pAdjustment, "vcl", "missing Adjustment element of spinbutton/adjustment"); if (pTarget && pAdjustment)
mungeAdjustment(*pTarget, *pAdjustment);
}
//Set ScrollBar adjustments when everything has been imported for (autoconst& elem : m_pVclParserState->m_aScrollAdjustmentMaps)
{
ScrollBar *pTarget = get<ScrollBar>(elem.m_sID); const Adjustment *pAdjustment = get_adjustment_by_name(elem.m_sValue);
SAL_WARN_IF(!pTarget || !pAdjustment, "vcl", "missing elements of scrollbar/adjustment"); if (pTarget && pAdjustment)
mungeAdjustment(*pTarget, *pAdjustment);
}
//Set Scale(Slider) adjustments for (autoconst& elem : m_pVclParserState->m_aSliderAdjustmentMaps)
{
Slider* pTarget = dynamic_cast<Slider*>(get(elem.m_sID)); const Adjustment* pAdjustment = get_adjustment_by_name(elem.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 (autoconst& sizeGroup : getSizeGroups())
{
std::shared_ptr<VclSizeGroup> xGroup(std::make_shared<VclSizeGroup>());
for (autoconst& [ rKey, rValue ] : sizeGroup.m_aProperties)
xGroup->set_property(rKey, rValue);
FixedImage *pImage = get<FixedImage>(elem.m_sValue);
SAL_WARN_IF(!pTarget || !pImage, "vcl", "missing elements of button/image/stock"); if (!pTarget || !pImage) continue;
aImagesToBeRemoved.insert(elem.m_sValue);
if (!elem.m_bRadio)
{ const Image& rImage = pImage->GetImage();
SymbolType eSymbol = mapStockToSymbol(rImage.GetStock()); if (eSymbol != SymbolType::IMAGE && eSymbol != SymbolType::DONTKNOW)
{
pTargetButton->SetSymbol(eSymbol); //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
pTargetButton->SetStyle(pTargetButton->GetStyle() | WB_SMALLSTYLE);
} else
{
pTargetButton->SetModeImage(rImage); if (pImage->GetStyle() & WB_SMALLSTYLE)
{
Size aSz(rImage.GetSizePixel());
aSz.AdjustWidth(6);
aSz.AdjustHeight(6); if (pTargetButton->get_width_request() == -1)
pTargetButton->set_width_request(aSz.Width()); if (pTargetButton->get_height_request() == -1)
pTargetButton->set_height_request(aSz.Height());
}
}
} else
pTargetRadio->SetModeRadioImage(pImage->GetImage());
auto aFind = m_pVclParserState->m_aImageSizeMap.find(elem.m_sValue); if (aFind != m_pVclParserState->m_aImageSizeMap.end())
{ switch (aFind->second)
{ case 1:
pTarget->SetSmallSymbol(); break; case 2:
assert(pImage->GetStyle() & WB_SMALLSTYLE);
pTarget->SetStyle(pTarget->GetStyle() | WB_SMALLSTYLE); break; case 3:
pTarget->SetStyle(pTarget->GetStyle() | WB_SMALLSTYLE); // large toolbar, make bigger than normal (4)
pTarget->set_width_request(pTarget->GetOptimalSize().Width() * 1.5);
pTarget->set_height_request(pTarget->GetOptimalSize().Height() * 1.5); break; case 4: break; default:
SAL_WARN("vcl.builder", "unsupported image size " << aFind->second); break;
}
m_pVclParserState->m_aImageSizeMap.erase(aFind);
}
}
//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 (autoconst& elem : aImagesToBeRemoved)
{
delete_by_name(elem);
}
//Set button menus when everything has been imported for (autoconst& elem : m_pVclParserState->m_aButtonMenuMaps)
{
MenuButton *pTarget = get<MenuButton>(elem.m_sID);
PopupMenu *pMenu = get_menu(elem.m_sValue);
SAL_WARN_IF(!pTarget || !pMenu, "vcl", "missing elements of button/menu"); if (!pTarget || !pMenu) continue;
pTarget->SetPopupMenu(pMenu, true);
}
//Remove ScrollWindow parent widgets whose children in vcl implement scrolling //internally. for (autoconst& elem : m_pVclParserState->m_aRedundantParentWidgets)
{
delete_by_window(elem.first);
}
//fdo#67378 merge the label into the disclosure button for (autoconst& elem : m_pVclParserState->m_aExpanderWidgets)
{
vcl::Window *pChild = elem->get_child();
vcl::Window* pLabel = elem->GetWindow(GetWindowType::LastChild); if (pLabel && pLabel != pChild && pLabel->GetType() == WindowType::FIXEDTEXT)
{
FixedText *pLabelWidget = static_cast<FixedText*>(pLabel);
elem->set_label(pLabelWidget->GetText()); if (pLabelWidget->IsControlFont())
elem->get_label_widget()->SetControlFont(pLabelWidget->GetControlFont());
delete_by_window(pLabel);
}
}
// create message dialog message area now for (autoconst& elem : m_pVclParserState->m_aMessageDialogs)
elem->create_message_area();
//drop maps, etc. that we don't need again
resetParserState();
SAL_WARN_IF(!m_sID.isEmpty() && (!m_bToplevelParentFound && !get_by_name(m_sID)), "vcl.builder", "Requested top level widget \"" << m_sID << "\" not found in " << sUIFile);
#ifdefined SAL_LOG_WARN if (m_bToplevelParentFound && m_pParent->IsDialog())
{ int nButtons = 0; bool bHasDefButton = false; for (autoconst& child : m_aChildren)
{ if (isButtonType(child.m_pWindow->GetType()))
{
++nButtons; if (child.m_pWindow->GetStyle() & WB_DEFBUTTON)
{
bHasDefButton = true; break;
}
}
}
SAL_WARN_IF(nButtons && !bHasDefButton, "vcl.builder", "No default button defined in " << sUIFile);
} #endif
constbool bHideHelp = comphelper::LibreOfficeKit::isActive() &&
officecfg::Office::Common::Help::HelpRootURL::get().isEmpty(); if (bHideHelp)
{ if (vcl::Window *pHelpButton = get(u"help"))
pHelpButton->Hide();
}
}
VclBuilder::~VclBuilder()
{
disposeBuilder();
}
void VclBuilder::disposeBuilder()
{ for (std::vector<WinAndId>::reverse_iterator aI = m_aChildren.rbegin(),
aEnd = m_aChildren.rend(); aI != aEnd; ++aI)
{
aI->m_pWindow.disposeAndClear();
}
m_aChildren.clear();
for (std::vector<MenuAndId>::reverse_iterator aI = m_aMenus.rbegin(),
aEnd = m_aMenus.rend(); aI != aEnd; ++aI)
{
aI->m_pMenu.disposeAndClear();
}
m_aMenus.clear();
m_pParent.reset();
}
vcl::Window* VclBuilder::prepareWidgetOwnScrolling(vcl::Window *pParent, WinBits &rWinStyle)
{ //For Widgets that manage their own scrolling, if one appears as a child of //a scrolling window shoehorn that scrolling settings to this widget and //return the real parent to use if (pParent && pParent->GetType() == WindowType::SCROLLWINDOW)
{
WinBits nScrollBits = pParent->GetStyle();
nScrollBits &= (WB_AUTOHSCROLL|WB_HSCROLL|WB_AUTOVSCROLL|WB_VSCROLL);
rWinStyle |= nScrollBits; if (static_cast<VclScrolledWindow*>(pParent)->HasVisibleBorder())
rWinStyle |= WB_BORDER;
pParent = pParent->GetParent();
}
// This branch is mainly for building for WASM, and especially for // Collabora Online in the browser, where code from core and Collabora // Online is compiled to WASM and linked into a single WASM binary. // (Not for Allotropia's Qt-based LibreOffice in the browser.)
// When building core for WASM it doesn't use the same // solenv/bin/native-code.py thing as the mobile apps, even if in both // cases everything is linked statically. So there is no generated // native-code.h, and we can't use lo_get_custom_widget_func() from // that. So cheat and duplicate the code from an existing generated // native-code.h. It's just a handful of lines anyway.
#ifndef DISABLE_DYNLOADING const OUString sModule = OUString::Concat(SAL_DLLPREFIX)
+ name.subView(0, nDelim)
+ SAL_DLLEXTENSION;
ModuleMap::iterator aI = g_aModuleMap.find(sModule); if (aI == g_aModuleMap.end())
{
std::shared_ptr<NoAutoUnloadModule> pModule; #if ENABLE_MERGELIBS if (!g_pMergedLib->is())
g_pMergedLib->loadRelative(&thisModule, SVLIBRARY("merged")); if ((pFunction = reinterpret_cast<VclBuilder::customMakeWidget>(
g_pMergedLib->getFunctionSymbol(sFunction))))
pModule = g_pMergedLib; #endif if (!pFunction)
{
pModule = std::make_shared<NoAutoUnloadModule>(); bool ok = pModule->loadRelative(&thisModule, sModule); if (!ok)
{ #ifdef LINUX // in the case of preloading, we don't have eg. the // libcuilo.so, but still need to dlsym the symbols - // which are already in-process if (comphelper::LibreOfficeKit::isActive())
{
pFunction = reinterpret_cast<VclBuilder::customMakeWidget>(dlsym(RTLD_DEFAULT, OUStringToOString(sFunction, RTL_TEXTENCODING_UTF8).getStr()));
ok = !!pFunction;
assert(ok && "couldn't even directly dlsym the sFunction (available via preload)");
} #endif
assert(ok && "bad module name in .ui");
} else
{
pFunction = reinterpret_cast<VclBuilder::customMakeWidget>(
pModule->getFunctionSymbol(sFunction));
}
}
g_aModuleMap.insert(std::make_pair(sModule, pModule));
} else
pFunction = reinterpret_cast<VclBuilder::customMakeWidget>(
aI->second->getFunctionSymbol(sFunction)); #elif !HAVE_FEATURE_DESKTOP || (defined EMSCRIPTEN && !ENABLE_QT5) // This ifdef branch is mainly for building for either the // Android or iOS apps, or the Collabora Online as WASM thing.
pFunction = lo_get_custom_widget_func(sFunction.toUtf8().getStr());
SAL_WARN_IF(!pFunction, "vcl.builder", "Could not find " << sFunction);
assert(pFunction); #else
pFunction = reinterpret_cast<VclBuilder::customMakeWidget>(
osl_getFunctionSymbol((oslModule)RTLD_DEFAULT, sFunction.pData)); #endif
} return pFunction;
}
}
if (pParent && (pParent->GetType() == WindowType::TABCONTROL ||
pParent->GetType() == WindowType::VERTICALTABCONTROL))
{ bool bTopLevel(name == "GtkDialog" || name == "GtkMessageDialog" ||
name == "GtkWindow" || name == "GtkPopover" || name == "GtkAssistant"); if (!bTopLevel)
{ if (pParent->GetType() == WindowType::TABCONTROL)
{ //We have to add a page //make default pageid == position
TabControl *pTabControl = static_cast<TabControl*>(pParent);
sal_uInt16 nNewPageCount = pTabControl->GetPageCount()+1;
sal_uInt16 nNewPageId = nNewPageCount;
pTabControl->InsertPage(nNewPageId, OUString());
pTabControl->SetCurPageId(nNewPageId);
SAL_WARN_IF(bIsPlaceHolder, "vcl.builder", "we should have no placeholders for tabpages"); if (!bIsPlaceHolder)
{
VclPtrInstance<TabPage> pPage(pTabControl);
pPage->Show();
//Make up a name for it
OUString sTabPageId = get_by_window(pParent) + "-page" +
OUString::number(nNewPageCount);
m_aChildren.emplace_back(sTabPageId, pPage, false);
pPage->SetHelpId(getHelpRoot() + sTabPageId);
pParent = pPage;
pTabControl->SetTabPage(nNewPageId, pPage);
}
} else
{
VerticalTabControl *pTabControl = static_cast<VerticalTabControl*>(pParent);
SAL_WARN_IF(bIsPlaceHolder, "vcl.builder", "we should have no placeholders for tabpages"); if (!bIsPlaceHolder)
pParent = pTabControl->GetPageParent();
}
}
}
if (bIsPlaceHolder || name == "GtkTreeSelection") return nullptr;
extractButtonImage(id, rMap, name == "GtkRadioButton");
VclPtr<vcl::Window> xWindow; if (name == "GtkDialog" || name == "GtkAssistant")
{ // WB_ALLOWMENUBAR because we don't know in advance if we will encounter // a menubar, and menubars need a BorderWindow in the toplevel, and // such border windows need to be in created during the dialog ctor
WinBits nBits = WB_MOVEABLE|WB_3DLOOK|WB_ALLOWMENUBAR; if (extractResizable(rMap))
nBits |= WB_SIZEABLE; if (extractCloseable(rMap))
nBits |= WB_CLOSEABLE;
Dialog::InitFlag eInit = !pParent ? Dialog::InitFlag::NoParent : Dialog::InitFlag::Default; if (name == "GtkAssistant")
xWindow = VclPtr<vcl::RoadmapWizard>::Create(pParent, nBits, eInit); else
xWindow = VclPtr<Dialog>::Create(pParent, nBits, eInit); #if HAVE_FEATURE_DESKTOP if (!extractModal(rMap))
xWindow->SetType(WindowType::MODELESSDIALOG); #endif
} elseif (name == "GtkMessageDialog")
{
WinBits nBits = WB_MOVEABLE|WB_3DLOOK|WB_CLOSEABLE; if (extractResizable(rMap))
nBits |= WB_SIZEABLE;
VclPtr<MessageDialog> xDialog(VclPtr<MessageDialog>::Create(pParent, nBits));
m_pVclParserState->m_aMessageDialogs.push_back(xDialog);
xWindow = xDialog; #ifdefined _WIN32
xWindow->set_border_width(3); #else
xWindow->set_border_width(12); #endif
} elseif (name == "GtkBox" || name == "GtkStatusbar")
{
bVertical = hasOrientationVertical(rMap); if (bVertical)
xWindow = VclPtr<VclVBox>::Create(pParent); else
xWindow = VclPtr<VclHBox>::Create(pParent);
if (extractEntry(rMap))
{
VclPtrInstance<ComboBox> xComboBox(pParent, nBits);
xComboBox->EnableAutoSize(true);
xWindow = xComboBox;
} else
{
VclPtrInstance<ListBox> xListBox(pParent, nBits|WB_SIMPLEMODE);
xListBox->EnableAutoSize(true);
xWindow = xListBox;
}
} elseif (name == "VclOptionalBox" || name == "sfxlo-OptionalBox")
{ // tdf#135495 fallback sfxlo-OptionalBox to VclOptionalBox as a stopgap
xWindow = VclPtr<OptionalBox>::Create(pParent);
} elseif (name == "svtlo-ManagedMenuButton")
{ // like tdf#135495 keep the name svtlo-ManagedMenuButton even though it's a misnomer // and is not dlsymed from the svt library
xWindow = VclPtr<ManagedMenuButton>::Create(pParent, WB_CLIPCHILDREN|WB_CENTER|WB_VCENTER|WB_FLATBUTTON);
OUString sMenu = BuilderUtils::extractCustomProperty(rMap); if (!sMenu.isEmpty())
m_pVclParserState->m_aButtonMenuMaps.emplace_back(id, sMenu);
setupFromActionName(static_cast<Button*>(xWindow.get()), rMap, m_xFrame);
} elseif (name == "sfxlo-PriorityMergedHBox")
{ // like tdf#135495 above, keep the sfxlo-PriorityMergedHBox even though its not in sfx anymore
xWindow = VclPtr<PriorityMergedHBox>::Create(pParent);
} elseif (name == "sfxlo-PriorityHBox")
{ // like tdf#135495 above, keep the sfxlo-PriorityMergedHBox even though its not in sfx anymore
xWindow = VclPtr<PriorityHBox>::Create(pParent);
} elseif (name == "sfxlo-DropdownBox")
{ // like tdf#135495 above, keep the sfxlo-PriorityMergedHBox even though its not in sfx anymore
xWindow = VclPtr<DropdownBox>::Create(pParent);
} elseif (name == "sfxlo-ContextVBox")
{ // like tdf#135495 above, keep the sfxlo-PriorityMergedHBox even though its not in sfx anymore
xWindow = VclPtr<ContextVBox>::Create(pParent);
} elseif (name == "GtkIconView")
{
assert(rMap.contains(u"model"_ustr) && "GtkIconView must have a model");
//window we want to apply the packing props for this GtkIconView to
VclPtr<vcl::Window> xWindowForPackingProps;
extractModel(id, rMap);
WinBits nWinStyle = WB_CLIPCHILDREN|WB_LEFT|WB_VCENTER|WB_3DLOOK; //IconView manages its own scrolling,
vcl::Window *pRealParent = prepareWidgetOwnScrolling(pParent, nWinStyle);
VclPtr<IconView> xBox = VclPtr<IconView>::Create(pRealParent, nWinStyle);
xWindowForPackingProps = xBox;
if (pRealParent != pParent)
cleanupWidgetOwnScrolling(pParent, xWindowForPackingProps, rMap);
} elseif (name == "GtkTreeView")
{ if (!isLegacy())
{
assert(rMap.contains(u"model"_ustr) && "GtkTreeView must have a model");
}
//window we want to apply the packing props for this GtkTreeView to
VclPtr<vcl::Window> xWindowForPackingProps; //To-Do //a) make SvHeaderTabListBox/SvTabListBox the default target for GtkTreeView //b) remove the non-drop down mode of ListBox and convert // everything over to SvHeaderTabListBox/SvTabListBox
extractModel(id, rMap);
WinBits nWinStyle = WB_CLIPCHILDREN|WB_LEFT|WB_VCENTER|WB_3DLOOK; if (isLegacy())
{
OUString sBorder = BuilderUtils::extractCustomProperty(rMap); if (!sBorder.isEmpty())
nWinStyle |= WB_BORDER;
} else
{
nWinStyle |= WB_HASBUTTONS | WB_HASBUTTONSATROOT;
} //ListBox/SvHeaderTabListBox manages its own scrolling,
vcl::Window *pRealParent = prepareWidgetOwnScrolling(pParent, nWinStyle); if (isLegacy())
{
xWindow = VclPtr<ListBox>::Create(pRealParent, nWinStyle | WB_SIMPLEMODE);
xWindowForPackingProps = xWindow;
} else
{
VclPtr<SvTabListBox> xBox; bool bHeadersVisible = extractHeadersVisible(rMap); if (bHeadersVisible)
{
VclPtr<VclVBox> xContainer = VclPtr<VclVBox>::Create(pRealParent);
OUString containerid(id + "-container");
xContainer->SetHelpId(getHelpRoot() + containerid);
m_aChildren.emplace_back(containerid, xContainer, true);
VclPtrInstance<HeaderBar> xHeader(xContainer, WB_BUTTONSTYLE | WB_BORDER | WB_TABSTOP | WB_3DLOOK);
xHeader->set_width_request(0); // let the headerbar width not affect the size request
OUString headerid(id + "-header");
xHeader->SetHelpId(getHelpRoot() + headerid);
m_aChildren.emplace_back(headerid, xHeader, true);
VclPtr<SvHeaderTabListBox> xHeaderBox = VclPtr<SvHeaderTabListBox>::Create(xContainer, nWinStyle, xHeader);
xContainer->set_expand(true);
xHeader->Show();
xContainer->Show();
xBox = xHeaderBox;
xWindowForPackingProps = xContainer;
} else
{
xBox = VclPtr<LclTabListBox>::Create(pRealParent, nWinStyle);
xWindowForPackingProps = xBox;
}
xWindow = xBox;
xBox->SetNoAutoCurEntry(true);
xBox->SetQuickSearch(true);
xBox->SetSpaceBetweenEntries(3);
xBox->SetEntryHeight(16);
xBox->SetHighlightRange(); // select over the whole width
} if (pRealParent != pParent)
cleanupWidgetOwnScrolling(pParent, xWindowForPackingProps, rMap);
} elseif (name == "GtkTreeViewColumn")
{ if (!isLegacy())
{
SvHeaderTabListBox* pTreeView = dynamic_cast<SvHeaderTabListBox*>(pParent); if (HeaderBar* pHeaderBar = pTreeView ? pTreeView->GetHeaderBar() : nullptr)
{
HeaderBarItemBits nBits = HeaderBarItemBits::LEFTIMAGE; if (extractClickable(rMap))
nBits |= HeaderBarItemBits::CLICKABLE; if (extractSortIndicator(rMap))
nBits |= HeaderBarItemBits::DOWNARROW; float fAlign = extractAlignment(rMap); if (fAlign == 0.0)
nBits |= HeaderBarItemBits::LEFT;
--> --------------------
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.