summaryrefslogtreecommitdiff
path: root/vcl
diff options
context:
space:
mode:
authorCaolán McNamara <caolanm@redhat.com>2013-01-11 10:08:20 +0000
committerCaolán McNamara <caolanm@redhat.com>2013-01-11 19:42:51 +0000
commita84663a612053389703472dbd7aac4a4b9e7df7b (patch)
tree38c437c0b9268a6ed4a598a51c5c5b735012e9f1 /vcl
parentd19eab221f168aed12249ffc8a36a9f1aca5a94e (diff)
create VclSizeGroup analog of GtkSizeGroup
Change-Id: I01015184223960a5bdfb895fedc79e982a408082
Diffstat (limited to 'vcl')
-rw-r--r--vcl/inc/vcl/builder.hxx15
-rw-r--r--vcl/inc/vcl/layout.hxx52
-rw-r--r--vcl/inc/vcl/window.hxx13
-rw-r--r--vcl/inc/window.h2
-rw-r--r--vcl/source/window/builder.cxx80
-rw-r--r--vcl/source/window/layout.cxx58
-rw-r--r--vcl/source/window/window.cxx7
-rw-r--r--vcl/source/window/window2.cxx141
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: */