weld impress TabBarControl

Change-Id: Ia596830595289005a1c7e811ae4f446dc745f50c
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/104699
Tested-by: Jenkins
Reviewed-by: Caolán McNamara <caolanm@redhat.com>
This commit is contained in:
Caolán McNamara
2020-10-29 15:02:34 +01:00
parent 716c9ec53e
commit e00fd78e6e
4 changed files with 154 additions and 80 deletions
+1
View File
@@ -156,6 +156,7 @@ $(eval $(call gb_UIConfig_add_uifiles,modules/simpress,\
sd/uiconfig/simpress/ui/slidecontextmenu \
sd/uiconfig/simpress/ui/slidedesigndialog \
sd/uiconfig/simpress/ui/slidetransitionspanel \
sd/uiconfig/simpress/ui/tabviewbar \
sd/uiconfig/simpress/ui/tabledesignpanel \
sd/uiconfig/simpress/ui/templatedialog \
))
+25 -6
View File
@@ -25,8 +25,8 @@
#include <com/sun/star/drawing/framework/XToolBar.hpp>
#include <com/sun/star/drawing/framework/XConfigurationChangeListener.hpp>
#include <com/sun/star/lang/XUnoTunnel.hpp>
#include <vcl/tabctrl.hxx>
#include <cppuhelper/compbase.hxx>
#include <vcl/InterimItemWindow.hxx>
#include "MutexOwner.hxx"
#include <vector>
@@ -39,10 +39,28 @@ namespace vcl { class Window; }
namespace sd {
class ViewShellBase;
class ViewTabBar;
}
namespace sd {
class TabBarControl : public InterimItemWindow
{
public:
TabBarControl(vcl::Window* pParentWindow, const ::rtl::Reference<ViewTabBar>& rpViewTabBar);
virtual void dispose() override;
virtual ~TabBarControl() override;
weld::Notebook& GetNotebook() { return *mxTabControl; }
int GetAllocatedWidth() const { return mnAllocatedWidth; }
private:
std::unique_ptr<weld::Notebook> mxTabControl;
::rtl::Reference<ViewTabBar> mpViewTabBar;
int mnAllocatedWidth;
DECL_LINK(ActivatePageHdl, const OString&, void);
DECL_LINK(NotebookSizeAllocHdl, const Size&, void);
};
typedef ::cppu::WeakComponentImplHelper <
css::drawing::framework::XToolBar,
css::drawing::framework::XTabBar,
@@ -64,9 +82,9 @@ public:
virtual void SAL_CALL disposing() override;
const VclPtr< ::TabControl>& GetTabControl() const { return mpTabControl;}
const VclPtr<TabBarControl>& GetTabControl() const { return mpTabControl; }
bool ActivatePage();
bool ActivatePage(size_t nIndex);
//----- drawing::framework::XConfigurationChangeListener ------------------
@@ -125,6 +143,8 @@ public:
*/
int GetHeight() const;
void UpdateActiveButton();
void AddTabBarButton (
const css::drawing::framework::TabBarButton& rButton,
const css::drawing::framework::TabBarButton& rAnchor);
@@ -138,16 +158,15 @@ public:
GetTabBarButtons();
private:
VclPtr< ::TabControl> mpTabControl;
VclPtr<TabBarControl> mpTabControl;
css::uno::Reference<css::frame::XController> mxController;
css::uno::Reference<css::drawing::framework::XConfigurationController> mxConfigurationController;
typedef ::std::vector<css::drawing::framework::TabBarButton> TabBarButtonList;
TabBarButtonList maTabBarButtons;
VclPtr<TabPage> mpTabPage;
css::uno::Reference<css::drawing::framework::XResourceId> mxViewTabBarId;
ViewShellBase* mpViewShellBase;
int mnNoteBookWidthPadding;
void UpdateActiveButton();
void AddTabBarButton (
const css::drawing::framework::TabBarButton& rButton,
sal_Int32 nPosition);
+82 -74
View File
@@ -25,9 +25,8 @@
#include <DrawController.hxx>
#include <Client.hxx>
#include <vcl/svapp.hxx>
#include <vcl/tabpage.hxx>
#include <vcl/settings.hxx>
#include <vcl/svapp.hxx>
#include <sfx2/viewfrm.hxx>
#include <com/sun/star/drawing/framework/ResourceId.hpp>
@@ -54,16 +53,6 @@ bool IsEqual (const TabBarButton& rButton1, const TabBarButton& rButton2)
|| rButton1.ButtonLabel == rButton2.ButtonLabel);
}
class TabBarControl : public ::TabControl
{
public:
TabBarControl (vcl::Window* pParentWindow, const ::rtl::Reference<ViewTabBar>& rpViewTabBar);
virtual void Paint (vcl::RenderContext& rRenderContext, const ::tools::Rectangle& rRect) override;
virtual void ActivatePage() override;
private:
::rtl::Reference<ViewTabBar> mpViewTabBar;
};
} // end of anonymous namespace
ViewTabBar::ViewTabBar (
@@ -73,18 +62,10 @@ ViewTabBar::ViewTabBar (
mpTabControl(VclPtr<TabBarControl>::Create(GetAnchorWindow(rxViewTabBarId,rxController), this)),
mxController(rxController),
maTabBarButtons(),
mpTabPage(nullptr),
mxViewTabBarId(rxViewTabBarId),
mpViewShellBase(nullptr)
mpViewShellBase(nullptr),
mnNoteBookWidthPadding(0)
{
// Set one new tab page for all tab entries. We need it only to
// determine the height of the tab bar.
mpTabPage.reset(VclPtr<TabPage>::Create(mpTabControl.get()));
mpTabPage->Hide();
// add some space before the tabitems
mpTabControl->SetItemsOffset(Point(5, 3));
// Tunnel through the controller and use the ViewShellBase to obtain the
// view frame.
try
@@ -152,10 +133,6 @@ void ViewTabBar::disposing()
{
const SolarMutexGuard aSolarGuard;
// Set all references to the one tab page to NULL and delete the page.
for (sal_uInt16 nIndex=0; nIndex<mpTabControl->GetPageCount(); ++nIndex)
mpTabControl->SetTabPage(nIndex, nullptr);
mpTabPage.disposeAndClear();
mpTabControl.disposeAndClear();
}
@@ -319,7 +296,7 @@ sal_Int64 SAL_CALL ViewTabBar::getSomething (const Sequence<sal_Int8>& rId)
return nResult;
}
bool ViewTabBar::ActivatePage()
bool ViewTabBar::ActivatePage(size_t nIndex)
{
try
{
@@ -346,7 +323,6 @@ bool ViewTabBar::ActivatePage()
pIPClient = dynamic_cast<Client*>(mpViewShellBase->GetIPClient());
if (pIPClient==nullptr || ! pIPClient->IsObjectInPlaceActive())
{
sal_uInt16 nIndex (mpTabControl->GetCurPageId() - 1);
if (nIndex < maTabBarButtons.size())
{
xConfigurationController->requestResourceActivation(
@@ -356,13 +332,6 @@ bool ViewTabBar::ActivatePage()
return true;
}
else
{
// When we run into this else branch then we have an active OLE
// object. We ignore the request to switch views. Additionally
// we put the active tab back to the one for the current view.
UpdateActiveButton();
}
}
catch (const RuntimeException&)
{
@@ -378,16 +347,31 @@ int ViewTabBar::GetHeight() const
if (!maTabBarButtons.empty())
{
TabPage* pActivePage (mpTabControl->GetTabPage(
mpTabControl->GetCurPageId()));
if (pActivePage!=nullptr && mpTabControl->IsReallyVisible())
nHeight = pActivePage->GetPosPixel().Y();
if (mpTabControl->IsReallyVisible())
{
weld::Notebook& rNotebook = mpTabControl->GetNotebook();
int nAllocatedWidth = mpTabControl->GetAllocatedWidth();
int nPageWidth = nAllocatedWidth - mnNoteBookWidthPadding;
// set each page width-request to the size it takes to fit the notebook allocation
for (int nIndex = 1, nPageCount = rNotebook.get_n_pages(); nIndex <= nPageCount; ++nIndex)
{
OString sIdent(OString::number(nIndex));
weld::Container* pContainer = rNotebook.get_page(sIdent);
pContainer->set_size_request(nPageWidth, -1);
}
// get the height-for-width for this allocation
nHeight = mpTabControl->get_preferred_size().Height();
}
if (nHeight <= 0)
{
// Using a default when the real height can not be determined.
// To get correct height this method should be called when the
// control is visible.
nHeight = 21;
}
}
return nHeight;
@@ -430,13 +414,11 @@ void ViewTabBar::AddTabBarButton (
const css::drawing::framework::TabBarButton& rButton,
sal_Int32 nPosition)
{
if (nPosition>=0
&& nPosition<=mpTabControl->GetPageCount())
if (nPosition >= 0 &&
nPosition <= mpTabControl->GetNotebook().get_n_pages())
{
sal_uInt16 nIndex (static_cast<sal_uInt16>(nPosition));
// Insert the button into our local array.
maTabBarButtons.insert(maTabBarButtons.begin()+nIndex, rButton);
maTabBarButtons.insert(maTabBarButtons.begin() + nPosition, rButton);
UpdateTabBarButtons();
UpdateActiveButton();
}
@@ -501,8 +483,7 @@ void ViewTabBar::UpdateActiveButton()
{
if (maTabBarButtons[nIndex].ResourceId->compareTo(xViewId) == 0)
{
mpTabControl->SetCurPageId(nIndex+1);
mpTabControl->::TabControl::ActivatePage();
mpTabControl->GetNotebook().set_current_page(nIndex);
break;
}
}
@@ -510,27 +491,42 @@ void ViewTabBar::UpdateActiveButton()
void ViewTabBar::UpdateTabBarButtons()
{
sal_uInt16 nPageCount (mpTabControl->GetPageCount());
sal_uInt16 nIndex = 1;
int nMaxPageWidthReq(0);
weld::Notebook& rNotebook = mpTabControl->GetNotebook();
int nPageCount(rNotebook.get_n_pages());
int nIndex = 1;
for (const auto& rTab : maTabBarButtons)
{
OString sIdent(OString::number(nIndex));
// Create a new tab when there are not enough.
if (nPageCount < nIndex)
mpTabControl->InsertPage(nIndex, rTab.ButtonLabel);
rNotebook.append_page(sIdent, rTab.ButtonLabel);
else
{
// Update the tab.
rNotebook.set_tab_label_text(sIdent, rTab.ButtonLabel);
}
// Update the tab.
mpTabControl->SetPageText(nIndex, rTab.ButtonLabel);
mpTabControl->SetHelpText(nIndex, rTab.HelpText);
mpTabControl->SetTabPage(nIndex, mpTabPage.get());
// Set a fairly arbitrary initial width request for the pages so we can
// measure what extra width the notebook itself uses
weld::Container* pContainer = rNotebook.get_page(sIdent);
int nTextWidth = pContainer->get_pixel_size(rTab.ButtonLabel).Width();
pContainer->set_size_request(nTextWidth, -1);
nMaxPageWidthReq = std::max(nMaxPageWidthReq, nTextWidth);
++nIndex;
}
// Delete tabs that are no longer used.
for (; nIndex<=nPageCount; ++nIndex)
mpTabControl->RemovePage(nIndex);
rNotebook.remove_page(OString::number(nIndex));
mpTabPage->Hide();
int nWidthReq = rNotebook.get_preferred_size().Width();
// The excess width over the page request that the notebook uses we will
// use this later to help measure the best height-for-width given the
// eventual allocatated width of the notebook
mnNoteBookWidthPadding = nWidthReq - nMaxPageWidthReq;
}
//===== TabBarControl =========================================================
@@ -538,36 +534,48 @@ void ViewTabBar::UpdateTabBarButtons()
TabBarControl::TabBarControl (
vcl::Window* pParentWindow,
const ::rtl::Reference<ViewTabBar>& rpViewTabBar)
: ::TabControl(pParentWindow),
mpViewTabBar(rpViewTabBar)
: InterimItemWindow(pParentWindow, "modules/simpress/ui/tabviewbar.ui", "TabViewBar")
, mxTabControl(m_xBuilder->weld_notebook("tabcontrol"))
, mpViewTabBar(rpViewTabBar)
, mnAllocatedWidth(0)
{
}
void TabBarControl::Paint (vcl::RenderContext& rRenderContext, const ::tools::Rectangle& rRect)
{
Color aOriginalFillColor(rRenderContext.GetFillColor());
Color aOriginalLineColor(rRenderContext.GetLineColor());
// Because the actual window background is transparent--to avoid
// flickering due to multiple background paintings by this and by child
// windows--we have to paint the background for this control explicitly:
// the actual control is not painted over its whole bounding box.
rRenderContext.SetFillColor(rRenderContext.GetSettings().GetStyleSettings().GetDialogColor());
rRenderContext.SetLineColor();
rRenderContext.DrawRect(rRect);
SetPaintTransparent(false);
SetBackground(Application::GetSettings().GetStyleSettings().GetDialogColor());
::TabControl::Paint(rRenderContext, rRect);
InitControlBase(mxTabControl.get());
rRenderContext.SetFillColor(aOriginalFillColor);
rRenderContext.SetLineColor(aOriginalLineColor);
mxTabControl->connect_enter_page(LINK(this, TabBarControl, ActivatePageHdl));
mxTabControl->connect_size_allocate(LINK(this, TabBarControl, NotebookSizeAllocHdl));
}
void TabBarControl::ActivatePage()
void TabBarControl::dispose()
{
if (mpViewTabBar->ActivatePage())
mxTabControl.reset();
InterimItemWindow::dispose();
}
TabBarControl::~TabBarControl()
{
disposeOnce();
}
IMPL_LINK(TabBarControl, NotebookSizeAllocHdl, const Size&, rSize, void)
{
mnAllocatedWidth = rSize.Width();
}
IMPL_LINK(TabBarControl, ActivatePageHdl, const OString&, rPage, void)
{
if (!mpViewTabBar->ActivatePage(mxTabControl->get_page_index(rPage)))
{
// Call the parent so that the correct tab is highlighted.
this->::TabControl::ActivatePage();
// When we run into this else branch then we have an active OLE
// object. We ignore the request to switch views. Additionally
// we put the active tab back to the one for the current view.
mpViewTabBar->UpdateActiveButton();
}
}
+46
View File
@@ -0,0 +1,46 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.36.0 -->
<interface domain="sd">
<requires lib="gtk+" version="3.20"/>
<object class="GtkBox" id="TabViewBar">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkNotebook" id="tabcontrol">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="margin_left">5</property>
<property name="margin_top">3</property>
<property name="hexpand">True</property>
<property name="vexpand">True</property>
<property name="scrollable">True</property>
<property name="enable_popup">True</property>
<child>
<object class="GtkGrid">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<placeholder/>
</child>
</object>
</child>
<child type="tab">
<object class="GtkLabel" id="1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label">placeholder</property>
</object>
<packing>
<property name="tab_fill">False</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
</object>
</interface>