diff options
author | Caolán McNamara <caolanm@redhat.com> | 2012-08-23 11:54:40 +0100 |
---|---|---|
committer | Caolán McNamara <caolanm@redhat.com> | 2012-09-28 08:48:37 +0100 |
commit | 13dde575a9e03f1d1fbfbb40514c142a6e2f2909 (patch) | |
tree | 2d43fe5b64b9bc9836ad1dbee335ac803507c2d7 | |
parent | fcdf78fc9f0165ba42415d9a703aefc6da4a3b37 (diff) |
Implement a VclExpander equivalent of GtkExpander
Change-Id: I539d8d313a35509cf603f18e5f074eab331f2480
-rw-r--r-- | vcl/inc/vcl/button.hxx | 1 | ||||
-rw-r--r-- | vcl/inc/vcl/dialog.hxx | 1 | ||||
-rw-r--r-- | vcl/inc/vcl/layout.hxx | 29 | ||||
-rw-r--r-- | vcl/qa/cppunit/builder/demo.ui | 114 | ||||
-rw-r--r-- | vcl/source/control/button.cxx | 5 | ||||
-rw-r--r-- | vcl/source/window/builder.cxx | 2 | ||||
-rw-r--r-- | vcl/source/window/dialog.cxx | 59 | ||||
-rw-r--r-- | vcl/source/window/layout.cxx | 131 |
8 files changed, 310 insertions, 32 deletions
diff --git a/vcl/inc/vcl/button.hxx b/vcl/inc/vcl/button.hxx index a4b1a76ad4b3..6ea504ea8093 100644 --- a/vcl/inc/vcl/button.hxx +++ b/vcl/inc/vcl/button.hxx @@ -571,6 +571,7 @@ class VCL_DLLPUBLIC DisclosureButton : public CheckBox protected: SAL_DLLPRIVATE virtual void ImplDrawCheckBoxState(); public: + DisclosureButton( Window* pParent, WinBits nStyle = 0 ); DisclosureButton( Window* pParent, const ResId& rResId ); virtual void KeyInput( const KeyEvent& rKEvt ); diff --git a/vcl/inc/vcl/dialog.hxx b/vcl/inc/vcl/dialog.hxx index bc5e712e40ee..70a43c3a6c2d 100644 --- a/vcl/inc/vcl/dialog.hxx +++ b/vcl/inc/vcl/dialog.hxx @@ -100,6 +100,7 @@ public: virtual Size GetOptimalSize(WindowSizeType eType) const; virtual void Resize(); bool isLayoutEnabled() const; + void setInitialLayoutSize(); virtual bool set_property(const rtl::OString &rKey, const rtl::OString &rValue); void set_border_width(int nBorderWidth) diff --git a/vcl/inc/vcl/layout.hxx b/vcl/inc/vcl/layout.hxx index ca6d50f83eef..42071ce4f4cd 100644 --- a/vcl/inc/vcl/layout.hxx +++ b/vcl/inc/vcl/layout.hxx @@ -29,6 +29,7 @@ #define _VCLLAYOUT_HXX #include <vcl/dllapi.h> +#include <vcl/button.hxx> #include <vcl/window.hxx> #include <boost/multi_array.hpp> @@ -377,8 +378,8 @@ class VCL_DLLPUBLIC VclBin : public VclContainer { public: VclBin(Window *pParent) : VclContainer(pParent) {} - Window *get_child(); - const Window *get_child() const; + virtual Window *get_child(); + virtual const Window *get_child() const; virtual Size calculateRequisition() const; virtual void setAllocation(const Size &rAllocation); }; @@ -422,6 +423,30 @@ private: float m_fYScale; }; +class VCL_DLLPUBLIC VclExpander : public VclBin +{ +public: + VclExpander(Window *pParent) + : VclBin(pParent) + , m_bResizeTopLevel(true) + , m_aDisclosureButton(this) + { + m_aDisclosureButton.SetToggleHdl(LINK(this, VclExpander, ClickHdl)); + m_aDisclosureButton.Show(); + } + virtual Window *get_child(); + virtual const Window *get_child() const; + virtual bool set_property(const rtl::OString &rKey, const rtl::OString &rValue); +protected: + virtual Size calculateRequisition() const; + virtual void setAllocation(const Size &rAllocation); +private: + bool m_bResizeTopLevel; + DisclosureButton m_aDisclosureButton; + DECL_DLLPRIVATE_LINK(ClickHdl, DisclosureButton* pBtn); +}; + + /* * @return true if rValue is "True", "true", "1", etc. */ diff --git a/vcl/qa/cppunit/builder/demo.ui b/vcl/qa/cppunit/builder/demo.ui index 776173e77c7f..b83fd65d5622 100644 --- a/vcl/qa/cppunit/builder/demo.ui +++ b/vcl/qa/cppunit/builder/demo.ui @@ -1880,6 +1880,120 @@ <property name="tab_fill">False</property> </packing> </child> + <child> + <object class="GtkExpander" id="expander1"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="resize_toplevel">True</property> + <child> + <object class="GtkGrid" id="grid5"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="row_spacing">200</property> + <property name="column_spacing">400</property> + <child> + <object class="GtkLabel" id="label34"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes">label</property> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">0</property> + <property name="width">1</property> + <property name="height">1</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="label35"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes">label</property> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">1</property> + <property name="width">1</property> + <property name="height">1</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="label36"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes">label</property> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">2</property> + <property name="width">1</property> + <property name="height">1</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="label37"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes">label</property> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">0</property> + <property name="width">1</property> + <property name="height">1</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="label38"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes">label</property> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">1</property> + <property name="width">1</property> + <property name="height">1</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="label39"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes">label</property> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">2</property> + <property name="width">1</property> + <property name="height">1</property> + </packing> + </child> + </object> + </child> + <child type="label"> + <object class="GtkLabel" id="label40"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes">Details</property> + </object> + </child> + </object> + <packing> + <property name="position">6</property> + </packing> + </child> + <child type="tab"> + <object class="GtkLabel" id="label33"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes">page 7</property> + </object> + <packing> + <property name="position">6</property> + <property name="tab_fill">False</property> + </packing> + </child> </object> <packing> <property name="expand">True</property> diff --git a/vcl/source/control/button.cxx b/vcl/source/control/button.cxx index 0b8b0f419a88..3fa3b9571ee9 100644 --- a/vcl/source/control/button.cxx +++ b/vcl/source/control/button.cxx @@ -4169,6 +4169,11 @@ TriStateBox::~TriStateBox() // ======================================================================= +DisclosureButton::DisclosureButton( Window* pParent, WinBits nStyle ) : + CheckBox( pParent, nStyle ) +{ +} + DisclosureButton::DisclosureButton( Window* pParent, const ResId& rResId ) : CheckBox( pParent, rResId.SetRT( RSC_CHECKBOX ) ) { diff --git a/vcl/source/window/builder.cxx b/vcl/source/window/builder.cxx index 2fa0f6f34e8e..7b42362d2687 100644 --- a/vcl/source/window/builder.cxx +++ b/vcl/source/window/builder.cxx @@ -390,6 +390,8 @@ Window *VclBuilder::makeObject(Window *pParent, const rtl::OString &name, const pWindow = new VclGrid(pParent); else if (name.equalsL(RTL_CONSTASCII_STRINGPARAM("GtkFrame"))) pWindow = new VclFrame(pParent); + else if (name.equalsL(RTL_CONSTASCII_STRINGPARAM("GtkExpander"))) + pWindow = new VclExpander(pParent); else if (name.equalsL(RTL_CONSTASCII_STRINGPARAM("GtkAlignment"))) pWindow = new VclAlignment(pParent); else if (name.equalsL(RTL_CONSTASCII_STRINGPARAM("GtkButton"))) diff --git a/vcl/source/window/dialog.cxx b/vcl/source/window/dialog.cxx index 5666b02fbd48..422ddce7fbea 100644 --- a/vcl/source/window/dialog.cxx +++ b/vcl/source/window/dialog.cxx @@ -649,43 +649,46 @@ long Dialog::Notify( NotifyEvent& rNEvt ) return nRet; } -// ----------------------------------------------------------------------- - -void Dialog::StateChanged( StateChangedType nType ) +void Dialog::setInitialLayoutSize() { - SystemWindow::StateChanged( nType ); + maLayoutTimer.Stop(); - if ( nType == STATE_CHANGE_INITSHOW ) + //resize dialog to fit requisition on initial show + VclBox *pBox = static_cast<VclBox*>(GetWindow(WINDOW_FIRSTCHILD)); + + const DialogStyle& rDialogStyle = + GetSettings().GetStyleSettings().GetDialogStyle(); + pBox->set_border_width(rDialogStyle.content_area_border); + pBox->set_spacing(rDialogStyle.content_area_spacing); + + VclButtonBox *pActionArea = getActionArea(this); + if (pActionArea) { - if (isLayoutEnabled()) - { - maLayoutTimer.Stop(); + pActionArea->set_border_width(rDialogStyle.action_area_border); + pActionArea->set_spacing(rDialogStyle.button_spacing); + } - //resize dialog to fit requisition on initial show - VclBox *pBox = static_cast<VclBox*>(GetWindow(WINDOW_FIRSTCHILD)); + Size aSize = get_preferred_size(); - const DialogStyle& rDialogStyle = - GetSettings().GetStyleSettings().GetDialogStyle(); - pBox->set_border_width(rDialogStyle.content_area_border); - pBox->set_spacing(rDialogStyle.content_area_spacing); + Size aMax = GetOptimalSize(WINDOWSIZE_MAXIMUM); + aSize.Width() = std::min(aMax.Width(), aSize.Width()); + aSize.Height() = std::min(aMax.Height(), aSize.Height()); - VclButtonBox *pActionArea = getActionArea(this); - if (pActionArea) - { - pActionArea->set_border_width(rDialogStyle.action_area_border); - pActionArea->set_spacing(rDialogStyle.button_spacing); - } + SetMinOutputSizePixel(aSize); + SetSizePixel(aSize); + setPosSizeOnContainee(aSize, *pBox); +} - Size aSize = get_preferred_size(); +// ----------------------------------------------------------------------- - Size aMax = GetOptimalSize(WINDOWSIZE_MAXIMUM); - aSize.Width() = std::min(aMax.Width(), aSize.Width()); - aSize.Height() = std::min(aMax.Height(), aSize.Height()); +void Dialog::StateChanged( StateChangedType nType ) +{ + SystemWindow::StateChanged( nType ); - SetMinOutputSizePixel(aSize); - SetSizePixel(aSize); - setPosSizeOnContainee(aSize, *pBox); - } + if ( nType == STATE_CHANGE_INITSHOW ) + { + if (isLayoutEnabled()) + setInitialLayoutSize(); if ( GetSettings().GetStyleSettings().GetAutoMnemonic() ) ImplWindowAutoMnemonic( this ); diff --git a/vcl/source/window/layout.cxx b/vcl/source/window/layout.cxx index 1bc223335746..67b4af8f5b1a 100644 --- a/vcl/source/window/layout.cxx +++ b/vcl/source/window/layout.cxx @@ -26,6 +26,7 @@ * instead of those above. */ +#include <vcl/dialog.hxx> #include <vcl/layout.hxx> #include "window.h" @@ -865,8 +866,6 @@ Size VclAlignment::calculateRequisition() const void VclAlignment::setAllocation(const Size &rAllocation) { - //SetBackground( Color(0x00, 0x00, 0xFF) ); - Window *pChild = get_child(); if (!pChild || !pChild->IsVisible()) return; @@ -903,6 +902,134 @@ bool VclAlignment::set_property(const rtl::OString &rKey, const rtl::OString &rV return true; } +const Window *VclExpander::get_child() const +{ + const WindowImpl* pWindowImpl = ImplGetWindowImpl(); + + assert(pWindowImpl->mpFirstChild == &m_aDisclosureButton); + + return pWindowImpl->mpFirstChild->GetWindow(WINDOW_NEXT); +} + +Window *VclExpander::get_child() +{ + return const_cast<Window*>(const_cast<const VclExpander*>(this)->get_child()); +} + +Size VclExpander::calculateRequisition() const +{ + Size aRet(0, 0); + + WindowImpl* pWindowImpl = ImplGetWindowImpl(); + + const Window *pChild = get_child(); + const Window *pLabel = pChild != pWindowImpl->mpLastChild ? pWindowImpl->mpLastChild : NULL; + + if (pChild && pChild->IsVisible() && m_aDisclosureButton.IsChecked()) + aRet = pChild->GetOptimalSize(WINDOWSIZE_PREFERRED); + + Size aExpanderSize = m_aDisclosureButton.GetOptimalSize(WINDOWSIZE_PREFERRED); + + if (pLabel && pLabel->IsVisible()) + { + Size aLabelSize = pLabel->GetOptimalSize(WINDOWSIZE_PREFERRED); + aExpanderSize.Height() = std::max(aExpanderSize.Height(), aLabelSize.Height()); + aExpanderSize.Width() += aLabelSize.Width(); + } + + aRet.Height() += aExpanderSize.Height(); + aRet.Width() = std::max(aExpanderSize.Width(), aRet.Width()); + + const FrameStyle &rFrameStyle = + GetSettings().GetStyleSettings().GetFrameStyle(); + aRet.Width() += rFrameStyle.left + rFrameStyle.right; + aRet.Height() += rFrameStyle.top + rFrameStyle.bottom; + + return aRet; +} + +void VclExpander::setAllocation(const Size &rAllocation) +{ + const FrameStyle &rFrameStyle = + GetSettings().GetStyleSettings().GetFrameStyle(); + Size aAllocation(rAllocation.Width() - rFrameStyle.left - rFrameStyle.right, + rAllocation.Height() - rFrameStyle.top - rFrameStyle.bottom); + Point aChildPos(rFrameStyle.left, rFrameStyle.top); + + WindowImpl* pWindowImpl = ImplGetWindowImpl(); + + //The label widget is the last (of two) children + Window *pChild = get_child(); + Window *pLabel = pChild != pWindowImpl->mpLastChild ? pWindowImpl->mpLastChild : NULL; + + Size aButtonSize = m_aDisclosureButton.GetOptimalSize(WINDOWSIZE_PREFERRED); + Size aLabelSize; + Size aExpanderSize = aButtonSize; + if (pLabel && pLabel->IsVisible()) + { + aLabelSize = pLabel->GetOptimalSize(WINDOWSIZE_PREFERRED); + aExpanderSize.Height() = std::max(aExpanderSize.Height(), aLabelSize.Height()); + aExpanderSize.Width() += aLabelSize.Width(); + } + + aExpanderSize.Height() = std::min(aExpanderSize.Height(), aAllocation.Height()); + aExpanderSize.Width() = std::min(aExpanderSize.Width(), aAllocation.Width()); + + aButtonSize.Height() = std::min(aButtonSize.Height(), aExpanderSize.Height()); + aButtonSize.Width() = std::min(aButtonSize.Width(), aExpanderSize.Width()); + + long nExtraExpanderHeight = aExpanderSize.Height() - aButtonSize.Height(); + Point aButtonPos(aChildPos.X(), aChildPos.Y() + nExtraExpanderHeight/2); + setPosSizePixel(m_aDisclosureButton, aButtonPos, aButtonSize); + + if (pLabel && pLabel->IsVisible()) + { + aLabelSize.Height() = std::min(aLabelSize.Height(), aExpanderSize.Height()); + aLabelSize.Width() = std::min(aLabelSize.Width(), + aExpanderSize.Width() - aButtonSize.Width()); + + long nExtraLabelHeight = aExpanderSize.Height() - aLabelSize.Height(); + Point aLabelPos(aChildPos.X() + aButtonSize.Width(), aChildPos.Y() + nExtraLabelHeight/2); + setPosSizePixel(*pLabel, aLabelPos, aLabelSize); + } + + aAllocation.Height() -= aExpanderSize.Height(); + aChildPos.Y() += aExpanderSize.Height(); + + if (pChild && pChild->IsVisible()) + { + if (!m_aDisclosureButton.IsChecked()) + aAllocation = Size(); + setPosSizePixel(*pChild, aChildPos, aAllocation); + } +} + +bool VclExpander::set_property(const rtl::OString &rKey, const rtl::OString &rValue) +{ + if (rKey.equalsL(RTL_CONSTASCII_STRINGPARAM("expanded"))) + m_aDisclosureButton.Check(toBool(rValue)); + else if (rKey.equalsL(RTL_CONSTASCII_STRINGPARAM("resize-toplevel"))) + m_bResizeTopLevel = toBool(rValue); + else + return VclBin::set_property(rKey, rValue); + return true; +} + +IMPL_LINK( VclExpander, ClickHdl, DisclosureButton*, pBtn ) +{ + Window *pChild = get_child(); + if (pChild) + { + pChild->Show(pBtn->IsChecked()); + Dialog* pResizeDialog = m_bResizeTopLevel ? GetParentDialog() : NULL; + if (pResizeDialog) + pResizeDialog->setInitialLayoutSize(); + else + queue_resize(); + } + return 0; +} + Size getLegacyBestSizeForChildren(const Window &rWindow) { Rectangle aBounds; |