diff options
author | Caolán McNamara <caolanm@redhat.com> | 2013-01-11 10:08:20 +0000 |
---|---|---|
committer | Caolán McNamara <caolanm@redhat.com> | 2013-01-11 19:42:51 +0000 |
commit | a84663a612053389703472dbd7aac4a4b9e7df7b (patch) | |
tree | 38c437c0b9268a6ed4a598a51c5c5b735012e9f1 /vcl | |
parent | d19eab221f168aed12249ffc8a36a9f1aca5a94e (diff) |
create VclSizeGroup analog of GtkSizeGroup
Change-Id: I01015184223960a5bdfb895fedc79e982a408082
Diffstat (limited to 'vcl')
-rw-r--r-- | vcl/inc/vcl/builder.hxx | 15 | ||||
-rw-r--r-- | vcl/inc/vcl/layout.hxx | 52 | ||||
-rw-r--r-- | vcl/inc/vcl/window.hxx | 13 | ||||
-rw-r--r-- | vcl/inc/window.h | 2 | ||||
-rw-r--r-- | vcl/source/window/builder.cxx | 80 | ||||
-rw-r--r-- | vcl/source/window/layout.cxx | 58 | ||||
-rw-r--r-- | vcl/source/window/window.cxx | 7 | ||||
-rw-r--r-- | vcl/source/window/window2.cxx | 141 |
8 files changed, 333 insertions, 35 deletions
diff --git a/vcl/inc/vcl/builder.hxx b/vcl/inc/vcl/builder.hxx index cba973846ac1..09426676da1e 100644 --- a/vcl/inc/vcl/builder.hxx +++ b/vcl/inc/vcl/builder.hxx @@ -128,6 +128,17 @@ private: typedef std::map<OString, stockinfo> StockMap; + struct SizeGroup + { + OString m_sID; + std::vector<OString> m_aWidgets; + stringmap m_aProperties; + SizeGroup(const OString &rId) + : m_sID(rId) + { + } + }; + struct ParserState { std::vector<RadioButtonGroupMap> m_aGroupMaps; @@ -150,6 +161,8 @@ private: Translations m_aTranslations; std::map<Window*, Window*> m_aRedundantParentWidgets; + + std::vector<SizeGroup> m_aSizeGroups; }; void loadTranslations(const com::sun::star::lang::Locale &rLocale, const OUString &rUri); @@ -247,6 +260,8 @@ private: void handleMenu(xmlreader::XmlReader &reader, const OString &rID); std::vector<OString> handleItems(xmlreader::XmlReader &reader, const OString &rID); + void handleSizeGroup(xmlreader::XmlReader &reader, const OString &rID); + PackingData get_window_packing_data(const Window *pWindow) const; void set_window_packing_position(const Window *pWindow, sal_Int32 nPosition); diff --git a/vcl/inc/vcl/layout.hxx b/vcl/inc/vcl/layout.hxx index 9beee36e76f7..5173687c603e 100644 --- a/vcl/inc/vcl/layout.hxx +++ b/vcl/inc/vcl/layout.hxx @@ -15,6 +15,7 @@ #include <vcl/scrbar.hxx> #include <vcl/window.hxx> #include <boost/multi_array.hpp> +#include <set> class VCL_DLLPUBLIC VclContainer : public Window { @@ -573,6 +574,57 @@ public: virtual void Command(const CommandEvent& rCEvt); }; +enum VclSizeGroupMode +{ + VCL_SIZE_GROUP_NONE, + VCL_SIZE_GROUP_HORIZONTAL, + VCL_SIZE_GROUP_VERTICAL, + VCL_SIZE_GROUP_BOTH +}; + +class VCL_DLLPUBLIC VclSizeGroup +{ +private: + std::set<Window*> m_aWindows; + bool m_bIgnoreHidden; + VclSizeGroupMode m_eMode; + + void trigger_queue_resize(); +public: + VclSizeGroup() + : m_bIgnoreHidden(false) + , m_eMode(VCL_SIZE_GROUP_HORIZONTAL) + { + } + void insert(Window *pWindow) + { + m_aWindows.insert(pWindow); + } + void erase(Window *pWindow) + { + m_aWindows.erase(pWindow); + } + const std::set<Window*>& get_widgets() const + { + return m_aWindows; + } + std::set<Window*>& get_widgets() + { + return m_aWindows; + } + void set_ignore_hidden(bool bIgnoreHidden); + bool get_ignore_hidden() const + { + return m_bIgnoreHidden; + } + void set_mode(VclSizeGroupMode eMode); + VclSizeGroupMode get_mode() const + { + return m_eMode; + } + bool set_property(const OString &rKey, const OString &rValue); +}; + // retro-fitting utilities // //Get a Size which is large enough to contain all children with diff --git a/vcl/inc/vcl/window.hxx b/vcl/inc/vcl/window.hxx index cebab25117db..f0ceb9a3e1b8 100644 --- a/vcl/inc/vcl/window.hxx +++ b/vcl/inc/vcl/window.hxx @@ -334,6 +334,7 @@ const char* ImplDbgCheckWindow( const void* pObj ); class Dialog; class WindowImpl; class VclBuilder; +class VclSizeGroup; struct WindowResHeader { @@ -575,9 +576,6 @@ protected: void CallEventListeners( sal_uLong nEvent, void* pData = NULL ); void FireVclEvent( VclSimpleEvent* pEvent ); - sal_Int32 get_height_request() const; - sal_Int32 get_width_request() const; - // FIXME: this is a hack to workaround missing layout functionality SAL_DLLPRIVATE void ImplAdjustNWFSizes(); public: @@ -1086,6 +1084,7 @@ public: * @see get_preferred_size, set_width_request */ void set_height_request(sal_Int32 nHeightRequest); + sal_Int32 get_height_request() const; /* * Sets the "height-request" property @@ -1096,6 +1095,7 @@ public: * @see get_preferred_size, set_height_request */ void set_width_request(sal_Int32 nWidthRequest); + sal_Int32 get_width_request() const; /* * Retrieves the preferred size of a widget taking @@ -1221,6 +1221,13 @@ public: bool set_font_attribute(const rtl::OString &rKey, const rtl::OString &rValue); /* + * Adds this widget to the xGroup VclSizeGroup + * + */ + void add_to_size_group(boost::shared_ptr< VclSizeGroup > xGroup); + void remove_from_all_size_groups(); + + /* * Move this widget to be the nNewPosition'd child of its parent */ void reorderWithinParent(sal_uInt16 nNewPosition); diff --git a/vcl/inc/window.h b/vcl/inc/window.h index dbedd3b78871..1785be28007f 100644 --- a/vcl/inc/window.h +++ b/vcl/inc/window.h @@ -44,6 +44,7 @@ struct ImplDelData; struct ImplAccessibleInfos; class Window; +class VclSizeGroup; class VirtualDevice; class Cursor; class ImplDevFontList; @@ -283,6 +284,7 @@ public: InputContext maInputContext; ::com::sun::star::uno::Reference< ::com::sun::star::awt::XWindowPeer > mxWindowPeer; ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > mxAccessible; + ::boost::shared_ptr< VclSizeGroup > m_xSizeGroup; ImplAccessibleInfos* mpAccessibleInfos; VCLXWindow* mpVCLXWindow; Region maWinRegion; // region to 'shape' the VCL window (frame coordinates) diff --git a/vcl/source/window/builder.cxx b/vcl/source/window/builder.cxx index e9e427ec113c..7b78faccf423 100644 --- a/vcl/source/window/builder.cxx +++ b/vcl/source/window/builder.cxx @@ -215,6 +215,28 @@ VclBuilder::VclBuilder(Window *pParent, OUString sUIDir, OUString sUIFile, OStri mungeScrollAdjustment(*pTarget, *pAdjustment); } + //Set size-groups when all widgets have been imported + for (std::vector<SizeGroup>::iterator aI = m_pParserState->m_aSizeGroups.begin(), + aEnd = m_pParserState->m_aSizeGroups.end(); aI != aEnd; ++aI) + { + boost::shared_ptr< VclSizeGroup > xGroup(new VclSizeGroup); + + 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<OString>::iterator aW = aI->m_aWidgets.begin(), + aEndW = aI->m_aWidgets.end(); aW != aEndW; ++aW) + { + Window* pWindow = get<Window>(aW->getStr()); + pWindow->add_to_size_group(xGroup); + } + } + //Set button images when everything has been imported std::set<OString> aImagesToBeRemoved; for (std::vector<ButtonImageWidgetMap>::iterator aI = m_pParserState->m_aButtonImageWidgetMaps.begin(), @@ -1660,6 +1682,59 @@ void VclBuilder::handleMenuObject(PopupMenu *pParent, xmlreader::XmlReader &read insertMenuObject(pParent, sClass, sID, aProperties, aAccelerators); } +void VclBuilder::handleSizeGroup(xmlreader::XmlReader &reader, const OString &rID) +{ + m_pParserState->m_aSizeGroups.push_back(SizeGroup(rID)); + SizeGroup &rSizeGroup = m_pParserState->m_aSizeGroups.back(); + + int nLevel = 1; + + while(1) + { + xmlreader::Span name; + int nsId; + + xmlreader::XmlReader::Result res = reader.nextItem( + xmlreader::XmlReader::TEXT_NONE, &name, &nsId); + + if (res == xmlreader::XmlReader::RESULT_DONE) + break; + + if (res == xmlreader::XmlReader::RESULT_BEGIN) + { + ++nLevel; + if (name.equals(RTL_CONSTASCII_STRINGPARAM("widget"))) + { + while (reader.nextAttribute(&nsId, &name)) + { + if (name.equals(RTL_CONSTASCII_STRINGPARAM("name"))) + { + name = reader.getAttributeValue(false); + OString sWidget = OString(name.begin, name.length); + sal_Int32 nDelim = sWidget.indexOf(':'); + if (nDelim != -1) + sWidget = sWidget.copy(0, nDelim); + rSizeGroup.m_aWidgets.push_back(sWidget); + } + } + } + else + { + if (name.equals(RTL_CONSTASCII_STRINGPARAM("property"))) + collectProperty(reader, rID, rSizeGroup.m_aProperties); + } + } + + if (res == xmlreader::XmlReader::RESULT_END) + { + --nLevel; + } + + if (!nLevel) + break; + } +} + OString VclBuilder::convertMnemonicMarkup(const OString &rIn) { OStringBuffer aRet(rIn); @@ -1793,6 +1868,11 @@ Window* VclBuilder::handleObject(Window *pParent, xmlreader::XmlReader &reader) handleMenu(reader, sID); return NULL; } + else if (sClass == "GtkSizeGroup") + { + handleSizeGroup(reader, sID); + return NULL; + } int nLevel = 1; diff --git a/vcl/source/window/layout.cxx b/vcl/source/window/layout.cxx index 5c0d7fdae1ad..f021fb82565b 100644 --- a/vcl/source/window/layout.cxx +++ b/vcl/source/window/layout.cxx @@ -1378,6 +1378,64 @@ void VclEventBox::Command(const CommandEvent&) //discard events by default to block them reaching children } +void VclSizeGroup::trigger_queue_resize() +{ + //sufficient to trigger one widget to trigger all of them + if (!m_aWindows.empty()) + { + Window *pWindow = *m_aWindows.begin(); + pWindow->queue_resize(); + } +} + +void VclSizeGroup::set_ignore_hidden(bool bIgnoreHidden) +{ + if (bIgnoreHidden != m_bIgnoreHidden) + { + m_bIgnoreHidden = bIgnoreHidden; + trigger_queue_resize(); + } +} + +void VclSizeGroup::set_mode(VclSizeGroupMode eMode) +{ + if (eMode != m_eMode) + { + m_eMode = eMode; + trigger_queue_resize(); + } + +} + +bool VclSizeGroup::set_property(const OString &rKey, const OString &rValue) +{ + if (rKey == "ignore-hidden") + set_ignore_hidden(toBool(rValue)); + else if (rKey == "mode") + { + VclSizeGroupMode eMode = VCL_SIZE_GROUP_HORIZONTAL; + if (rValue.equalsL(RTL_CONSTASCII_STRINGPARAM("none"))) + eMode = VCL_SIZE_GROUP_NONE; + else if (rValue.equalsL(RTL_CONSTASCII_STRINGPARAM("horizontal"))) + eMode = VCL_SIZE_GROUP_HORIZONTAL; + else if (rValue.equalsL(RTL_CONSTASCII_STRINGPARAM("vertical"))) + eMode = VCL_SIZE_GROUP_VERTICAL; + else if (rValue.equalsL(RTL_CONSTASCII_STRINGPARAM("both"))) + eMode = VCL_SIZE_GROUP_BOTH; + else + { + SAL_WARN("vcl.layout", "unknown size group mode" << rValue.getStr()); + } + set_mode(eMode); + } + else + { + SAL_INFO("vcl.layout", "unhandled property: " << rKey.getStr()); + return false; + } + return true; +} + Size getLegacyBestSizeForChildren(const Window &rWindow) { Rectangle aBounds; diff --git a/vcl/source/window/window.cxx b/vcl/source/window/window.cxx index f4f6f3deda86..a7a4b649da76 100644 --- a/vcl/source/window/window.cxx +++ b/vcl/source/window/window.cxx @@ -4481,13 +4481,16 @@ Window::~Window() } } + // remove from size-group if necessary + remove_from_all_size_groups(); + // hide window in order to trigger the Paint-Handling Hide(); // announce the window is to be destroyed { - NotifyEvent aNEvt( EVENT_DESTROY, this ); - Notify( aNEvt ); + NotifyEvent aNEvt( EVENT_DESTROY, this ); + Notify( aNEvt ); } // EndExtTextInputMode diff --git a/vcl/source/window/window2.cxx b/vcl/source/window/window2.cxx index d7db958ffb98..7c7f910c4294 100644 --- a/vcl/source/window/window2.cxx +++ b/vcl/source/window/window2.cxx @@ -1735,33 +1735,60 @@ void Window::SetOutputSizePixel( const Size& rNewSize ) //When a widget wants to renegotiate layout, get toplevel parent dialog and call //resize on it. Mark all intermediate containers (or container-alike) widgets //as dirty for the size remains unchanged, but layout changed circumstances -void Window::queue_resize() +namespace { - bool bSomeoneCares = false; + bool queue_ungrouped_resize(Window *pOrigWindow) + { + bool bSomeoneCares = false; - Dialog *pDialog = NULL; + Dialog *pDialog = NULL; - Window *pWindow = this; + Window *pWindow = pOrigWindow; - while( pWindow ) - { - if (isContainerWindow(*pWindow)) - { - VclContainer *pContainer = static_cast<VclContainer*>(pWindow); - pContainer->markLayoutDirty(); - bSomeoneCares = true; - } - else if (pWindow->GetType() == WINDOW_TABCONTROL) + while (pWindow) { - TabControl *pTabControl = static_cast<TabControl*>(pWindow); - pTabControl->markLayoutDirty(); + if (isContainerWindow(*pWindow)) + { + VclContainer *pContainer = static_cast<VclContainer*>(pWindow); + pContainer->markLayoutDirty(); + bSomeoneCares = true; + } + else if (pWindow->GetType() == WINDOW_TABCONTROL) + { + TabControl *pTabControl = static_cast<TabControl*>(pWindow); + pTabControl->markLayoutDirty(); + bSomeoneCares = true; + } + else if (pWindow->IsDialog()) + { + pDialog = dynamic_cast<Dialog*>(pWindow); + break; + } + pWindow = pWindow->GetParent(); } - else if (pWindow->IsDialog()) + + if (pDialog && pDialog != pOrigWindow) + pDialog->queue_layout(); + return bSomeoneCares; + } +} + +void Window::queue_resize() +{ + bool bSomeoneCares = queue_ungrouped_resize(this); + + WindowImpl *pWindowImpl = mpWindowImpl->mpBorderWindow ? mpWindowImpl->mpBorderWindow->mpWindowImpl : mpWindowImpl; + if (pWindowImpl->m_xSizeGroup && pWindowImpl->m_xSizeGroup->get_mode() != VCL_SIZE_GROUP_NONE) + { + std::set<Window*> &rWindows = pWindowImpl->m_xSizeGroup->get_widgets(); + for (std::set<Window*>::iterator aI = rWindows.begin(), + aEnd = rWindows.end(); aI != aEnd; ++aI) { - pDialog = dynamic_cast<Dialog*>(pWindow); - break; + Window *pOther = *aI; + if (pOther == this) + continue; + queue_ungrouped_resize(pOther); } - pWindow = pWindow->GetParent(); } if (bSomeoneCares) @@ -1772,10 +1799,6 @@ void Window::queue_resize() if (pBorderWindow) pBorderWindow->Resize(); } - - if (!pDialog || pDialog == this) - return; - pDialog->queue_layout(); } namespace @@ -1988,17 +2011,52 @@ void Window::set_width_request(sal_Int32 nWidthRequest) } } +namespace +{ + Size get_ungrouped_preferred_size(const Window &rWindow) + { + Size aRet(rWindow.get_width_request(), rWindow.get_height_request()); + if (aRet.Width() == -1 || aRet.Height() == -1) + { + Size aOptimal = rWindow.GetOptimalSize(WINDOWSIZE_PREFERRED); + if (aRet.Width() == -1) + aRet.Width() = aOptimal.Width(); + if (aRet.Height() == -1) + aRet.Height() = aOptimal.Height(); + } + return aRet; + } +} + Size Window::get_preferred_size() const { - Size aRet(get_width_request(), get_height_request()); - if (aRet.Width() == -1 || aRet.Height() == -1) + Size aRet(get_ungrouped_preferred_size(*this)); + + WindowImpl *pWindowImpl = mpWindowImpl->mpBorderWindow ? mpWindowImpl->mpBorderWindow->mpWindowImpl : mpWindowImpl; + if (pWindowImpl->m_xSizeGroup) { - Size aOptimal = GetOptimalSize(WINDOWSIZE_PREFERRED); - if (aRet.Width() == -1) - aRet.Width() = aOptimal.Width(); - if (aRet.Height() == -1) - aRet.Height() = aOptimal.Height(); + const VclSizeGroupMode eMode = pWindowImpl->m_xSizeGroup->get_mode(); + if (eMode != VCL_SIZE_GROUP_NONE) + { + const bool bIgnoreInHidden = pWindowImpl->m_xSizeGroup->get_ignore_hidden(); + const std::set<Window*> &rWindows = pWindowImpl->m_xSizeGroup->get_widgets(); + for (std::set<Window*>::const_iterator aI = rWindows.begin(), + aEnd = rWindows.end(); aI != aEnd; ++aI) + { + const Window *pOther = *aI; + if (pOther == this) + continue; + if (bIgnoreInHidden && !pOther->IsVisible()) + continue; + Size aOtherSize = get_ungrouped_preferred_size(*pOther); + if (eMode == VCL_SIZE_GROUP_BOTH || eMode == VCL_SIZE_GROUP_HORIZONTAL) + aRet.Width() = std::max(aRet.Width(), aOtherSize.Width()); + if (eMode == VCL_SIZE_GROUP_BOTH || eMode == VCL_SIZE_GROUP_VERTICAL) + aRet.Height() = std::max(aRet.Height(), aOtherSize.Height()); + } + } } + return aRet; } @@ -2230,4 +2288,27 @@ void Window::set_secondary(bool bSecondary) pWindowImpl->mbSecondary = bSecondary; } +void Window::add_to_size_group(boost::shared_ptr< VclSizeGroup > xGroup) +{ + WindowImpl *pWindowImpl = mpWindowImpl->mpBorderWindow ? mpWindowImpl->mpBorderWindow->mpWindowImpl : mpWindowImpl; + //To-Do, multiple groups + pWindowImpl->m_xSizeGroup = xGroup; + pWindowImpl->m_xSizeGroup->insert(this); + if (VCL_SIZE_GROUP_NONE != pWindowImpl->m_xSizeGroup->get_mode()) + queue_resize(); +} + +void Window::remove_from_all_size_groups() +{ + WindowImpl *pWindowImpl = mpWindowImpl->mpBorderWindow ? mpWindowImpl->mpBorderWindow->mpWindowImpl : mpWindowImpl; + //To-Do, multiple groups + if (pWindowImpl->m_xSizeGroup) + { + if (VCL_SIZE_GROUP_NONE != pWindowImpl->m_xSizeGroup->get_mode()) + queue_resize(); + pWindowImpl->m_xSizeGroup->erase(this); + pWindowImpl->m_xSizeGroup.reset(); + } +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |