summaryrefslogtreecommitdiffstats
path: root/vcl/source/control/PriorityHBox.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'vcl/source/control/PriorityHBox.cxx')
-rw-r--r--vcl/source/control/PriorityHBox.cxx197
1 files changed, 197 insertions, 0 deletions
diff --git a/vcl/source/control/PriorityHBox.cxx b/vcl/source/control/PriorityHBox.cxx
new file mode 100644
index 000000000..c893cc833
--- /dev/null
+++ b/vcl/source/control/PriorityHBox.cxx
@@ -0,0 +1,197 @@
+/* -*- 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 .
+ */
+
+#include <vcl/layout.hxx>
+#include <PriorityHBox.hxx>
+#include <comphelper/lok.hxx>
+
+namespace
+{
+bool lcl_comparePriority(const vcl::IPrioritable* a, const vcl::IPrioritable* b)
+{
+ return a->GetPriority() < b->GetPriority();
+}
+}
+
+PriorityHBox::PriorityHBox(vcl::Window* pParent)
+ : VclHBox(pParent)
+ , m_bInitialized(false)
+{
+}
+
+PriorityHBox::~PriorityHBox() { disposeOnce(); }
+
+void PriorityHBox::Initialize()
+{
+ m_bInitialized = true;
+
+ GetChildrenWithPriorities();
+ SetSizeFromParent();
+}
+
+int PriorityHBox::GetHiddenCount() const
+{
+ int nCount = 0;
+
+ for (auto pWindow : m_aSortedChildren)
+ if (pWindow->IsHidden())
+ nCount++;
+
+ return nCount;
+}
+
+void PriorityHBox::SetSizeFromParent()
+{
+ vcl::Window* pParent = GetParent();
+ if (pParent)
+ {
+ Size aParentSize = pParent->GetSizePixel();
+ SetSizePixel(Size(aParentSize.getWidth(), aParentSize.getHeight()));
+ }
+}
+
+Size PriorityHBox::calculateRequisition() const
+{
+ if (!m_bInitialized)
+ {
+ return VclHBox::calculateRequisition();
+ }
+
+ sal_uInt16 nVisibleChildren = 0;
+
+ Size aSize;
+ for (vcl::Window* pChild = GetWindow(GetWindowType::FirstChild); pChild;
+ pChild = pChild->GetWindow(GetWindowType::Next))
+ {
+ if (!pChild->IsVisible())
+ continue;
+ ++nVisibleChildren;
+ Size aChildSize = getLayoutRequisition(*pChild);
+
+ bool bAlwaysExpanded = true;
+
+ vcl::IPrioritable* pPrioritable = dynamic_cast<vcl::IPrioritable*>(pChild);
+ if (pPrioritable && pPrioritable->GetPriority() != VCL_PRIORITY_DEFAULT)
+ bAlwaysExpanded = false;
+
+ if (bAlwaysExpanded)
+ {
+ tools::Long nPrimaryDimension = getPrimaryDimension(aChildSize);
+ nPrimaryDimension += pChild->get_padding() * 2;
+ setPrimaryDimension(aChildSize, nPrimaryDimension);
+ }
+ else
+ setPrimaryDimension(aChildSize, 0);
+
+ accumulateMaxes(aChildSize, aSize);
+ }
+
+ return finalizeMaxes(aSize, nVisibleChildren);
+}
+
+void PriorityHBox::Resize()
+{
+ if (!m_bInitialized)
+ Initialize();
+
+ if (!m_bInitialized || comphelper::LibreOfficeKit::isActive())
+ {
+ return VclHBox::Resize();
+ }
+
+ tools::Long nWidth = GetSizePixel().Width();
+ tools::Long nCurrentWidth = VclHBox::calculateRequisition().getWidth();
+
+ // Hide lower priority controls
+ for (vcl::IPrioritable* pPrioritable : m_aSortedChildren)
+ {
+ if (nCurrentWidth <= nWidth)
+ break;
+
+ vcl::Window* pWindow = dynamic_cast<vcl::Window*>(pPrioritable);
+
+ if (pWindow && pWindow->GetParent() == this)
+ {
+ nCurrentWidth -= pWindow->GetOutputSizePixel().Width() + get_spacing();
+ pWindow->Show();
+ pPrioritable->HideContent();
+ nCurrentWidth += pWindow->GetOutputSizePixel().Width() + get_spacing();
+ }
+ }
+
+ auto pChildR = m_aSortedChildren.rbegin();
+ // Show higher priority controls if we already have enough space
+ while (pChildR != m_aSortedChildren.rend())
+ {
+ vcl::Window* pWindow = dynamic_cast<vcl::Window*>(*pChildR);
+ vcl::IPrioritable* pPrioritable = *pChildR;
+
+ if (pWindow->GetParent() != this)
+ {
+ pChildR++;
+ continue;
+ }
+
+ if (pWindow)
+ {
+ nCurrentWidth -= pWindow->GetOutputSizePixel().Width() + get_spacing();
+ pWindow->Show();
+ pPrioritable->ShowContent();
+ nCurrentWidth += getLayoutRequisition(*pWindow).Width() + get_spacing();
+
+ if (nCurrentWidth > nWidth)
+ {
+ pPrioritable->HideContent();
+ break;
+ }
+ }
+
+ pChildR++;
+ }
+
+ VclHBox::Resize();
+}
+
+void PriorityHBox::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect)
+{
+ if (!m_bInitialized)
+ Initialize();
+
+ VclHBox::Paint(rRenderContext, rRect);
+}
+
+void PriorityHBox::GetChildrenWithPriorities()
+{
+ for (sal_uInt16 i = 0; i < GetChildCount(); ++i)
+ {
+ vcl::Window* pChild = GetChild(i);
+
+ // Add only containers which have explicitly assigned priority.
+ vcl::IPrioritable* pPrioritable = dynamic_cast<vcl::IPrioritable*>(pChild);
+ if (pPrioritable && pPrioritable->GetPriority() != VCL_PRIORITY_DEFAULT)
+ m_aSortedChildren.push_back(pPrioritable);
+ }
+
+ if (m_aSortedChildren.empty())
+ m_bInitialized = false;
+
+ std::sort(m_aSortedChildren.begin(), m_aSortedChildren.end(), lcl_comparePriority);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */