summaryrefslogtreecommitdiff
path: root/vcl
diff options
context:
space:
mode:
authorCaolán McNamara <caolanm@redhat.com>2013-04-30 20:44:06 +0100
committerCaolán McNamara <caolanm@redhat.com>2013-05-01 14:42:05 +0100
commit9e5c35454d07f880a2cb52d9a808633b908bb859 (patch)
treeb436edac62601268ffa16841720faf857c859c9e /vcl
parent26bda9f4a82c9b1956a10e3dc52a99bc2f850ada (diff)
create a HIG compliant MessageDialog and map to GtkMessageDialog
Change-Id: If86387619ff00a652ea418292fbb0026b867a431
Diffstat (limited to 'vcl')
-rw-r--r--vcl/source/window/builder.cxx105
-rw-r--r--vcl/source/window/dialog.cxx3
-rw-r--r--vcl/source/window/layout.cxx176
3 files changed, 275 insertions, 9 deletions
diff --git a/vcl/source/window/builder.cxx b/vcl/source/window/builder.cxx
index a879eb3c887d..2f3b364a89a1 100644
--- a/vcl/source/window/builder.cxx
+++ b/vcl/source/window/builder.cxx
@@ -144,6 +144,7 @@ VclBuilder::VclBuilder(Window *pParent, OUString sUIDir, OUString sUIFile, OStri
, m_pParserState(new ParserState)
{
m_bToplevelHasDeferredInit = (pParent && pParent->IsDialog()) ? ((Dialog*)pParent)->isDeferredInit() : false;
+ m_bToplevelHasDeferredProperties = m_bToplevelHasDeferredInit;
sal_Int32 nIdx = m_sHelpRoot.lastIndexOf('.');
if (nIdx != -1)
@@ -944,6 +945,13 @@ Window *VclBuilder::makeObject(Window *pParent, const OString &name, const OStri
nBits |= WB_SIZEABLE;
pWindow = new Dialog(pParent, nBits);
}
+ else if (name == "GtkMessageDialog")
+ {
+ WinBits nBits = WB_MOVEABLE|WB_3DLOOK|WB_CLOSEABLE;
+ if (extractResizable(rMap))
+ nBits |= WB_SIZEABLE;
+ pWindow = new MessageDialog(pParent, nBits);
+ }
else if (name == "GtkBox")
{
bVertical = extractOrientation(rMap);
@@ -1256,6 +1264,27 @@ namespace
}
}
+//Any properties from .ui load we couldn't set because of potential virtual methods
+//during ctor are applied here
+void VclBuilder::setDeferredProperties()
+{
+ if (!m_bToplevelHasDeferredProperties)
+ return;
+ set_properties(m_pParent, m_aDeferredProperties);
+ m_aDeferredProperties.clear();
+ m_bToplevelHasDeferredProperties = false;
+}
+
+void VclBuilder::set_properties(Window *pWindow, const stringmap &rProps)
+{
+ for (stringmap::const_iterator aI = rProps.begin(), aEnd = rProps.end(); aI != aEnd; ++aI)
+ {
+ const OString &rKey = aI->first;
+ const OString &rValue = aI->second;
+ pWindow->set_property(rKey, rValue);
+ }
+}
+
Window *VclBuilder::insertObject(Window *pParent, const OString &rClass,
const OString &rID, stringmap &rProps, stringmap &rPango,
stringmap &rAtk,
@@ -1294,12 +1323,10 @@ Window *VclBuilder::insertObject(Window *pParent, const OString &rClass,
if (pCurrentChild)
{
- for (stringmap::iterator aI = rProps.begin(), aEnd = rProps.end(); aI != aEnd; ++aI)
- {
- const OString &rKey = aI->first;
- const OString &rValue = aI->second;
- pCurrentChild->set_property(rKey, rValue);
- }
+ if (pCurrentChild == m_pParent && m_bToplevelHasDeferredProperties)
+ m_aDeferredProperties = rProps;
+ else
+ set_properties(pCurrentChild, rProps);
for (stringmap::iterator aI = rPango.begin(), aEnd = rPango.end(); aI != aEnd; ++aI)
{
@@ -1529,15 +1556,19 @@ void VclBuilder::handleChild(Window *pParent, xmlreader::XmlReader &reader)
if (VclFrame *pFrameParent = dynamic_cast<VclFrame*>(pParent))
pFrameParent->designate_label(pCurrentChild);
}
- if (sInternalChild.equals("vbox"))
+ if (sInternalChild.equals("vbox") || sInternalChild.equals("messagedialog-vbox"))
{
if (Dialog *pBoxParent = dynamic_cast<Dialog*>(pParent))
pBoxParent->set_content_area(static_cast<VclBox*>(pCurrentChild));
}
- else if (sInternalChild.equals("action_area"))
+ else if (sInternalChild.equals("action_area") || sInternalChild.equals("messagedialog-action_area"))
{
- if (Dialog *pBoxParent = dynamic_cast<Dialog*>(pParent))
+ Window *pContentArea = pCurrentChild->GetParent();
+ assert(pContentArea && pContentArea->GetType() == WINDOW_CONTAINER);
+ if (Dialog *pBoxParent = dynamic_cast<Dialog*>(pContentArea ? pContentArea->GetParent() : NULL))
+ {
pBoxParent->set_action_area(static_cast<VclButtonBox*>(pCurrentChild));
+ }
}
//To-Do make reorder a virtual in Window, move this foo
@@ -2222,6 +2253,8 @@ Window* VclBuilder::handleObject(Window *pParent, xmlreader::XmlReader &reader)
collectPangoAttribute(reader, aPangoAttributes);
else if (name.equals("relation"))
collectAtkAttribute(reader, aAtkAttributes);
+ else if (name.equals("action-widget"))
+ handleActionWidget(reader);
}
}
@@ -2424,6 +2457,28 @@ void VclBuilder::collectProperty(xmlreader::XmlReader &reader, const OString &rI
}
}
+void VclBuilder::handleActionWidget(xmlreader::XmlReader &reader)
+{
+ xmlreader::Span name;
+ int nsId;
+
+ OString sResponse;
+
+ while (reader.nextAttribute(&nsId, &name))
+ {
+ if (name.equals("response"))
+ {
+ name = reader.getAttributeValue(false);
+ sResponse = OString(name.begin, name.length);
+ }
+ }
+
+ reader.nextItem(xmlreader::XmlReader::TEXT_RAW, &name, &nsId);
+ OString sID = OString(name.begin, name.length);
+ set_response(sID, sResponse.toInt32());
+}
+
+
void VclBuilder::collectAccelerator(xmlreader::XmlReader &reader, stringmap &rMap)
{
xmlreader::Span name;
@@ -2482,6 +2537,38 @@ PopupMenu *VclBuilder::get_menu(OString sID)
return NULL;
}
+short VclBuilder::get_response(const Window *pWindow) const
+{
+ for (std::vector<WinAndId>::const_iterator aI = m_aChildren.begin(),
+ aEnd = m_aChildren.end(); aI != aEnd; ++aI)
+ {
+ if (aI->m_pWindow == pWindow)
+ {
+ return aI->m_nResponseId;
+ }
+ }
+
+ //how did we not find sID ?
+ assert(false);
+ return RET_CANCEL;
+}
+
+void VclBuilder::set_response(OString sID, short nResponse)
+{
+ for (std::vector<WinAndId>::iterator aI = m_aChildren.begin(),
+ aEnd = m_aChildren.end(); aI != aEnd; ++aI)
+ {
+ if (aI->m_sID.equals(sID))
+ {
+ aI->m_nResponseId = nResponse;
+ return;
+ }
+ }
+
+ //how did we not find sID ?
+ assert(false);
+}
+
void VclBuilder::delete_by_name(OString sID)
{
for (std::vector<WinAndId>::iterator aI = m_aChildren.begin(),
diff --git a/vcl/source/window/dialog.cxx b/vcl/source/window/dialog.cxx
index c37588a74fde..4ea01eb635e5 100644
--- a/vcl/source/window/dialog.cxx
+++ b/vcl/source/window/dialog.cxx
@@ -711,6 +711,7 @@ void Dialog::StateChanged( StateChangedType nType )
if (isLayoutEnabled())
{
mbIsCalculatingInitialLayoutSize = true;
+ setDeferredProperties();
setOptimalLayoutSize();
mbIsCalculatingInitialLayoutSize = false;
}
@@ -900,6 +901,8 @@ void Dialog::ImplEndExecuteModal()
short Dialog::Execute()
{
+ setDeferredProperties();
+
if ( !ImplStartExecuteModal() )
return 0;
diff --git a/vcl/source/window/layout.cxx b/vcl/source/window/layout.cxx
index 27bb34dec24d..84351e2709da 100644
--- a/vcl/source/window/layout.cxx
+++ b/vcl/source/window/layout.cxx
@@ -10,6 +10,7 @@
#include <com/sun/star/accessibility/AccessibleRole.hpp>
#include <vcl/dialog.hxx>
#include <vcl/layout.hxx>
+#include <vcl/msgbox.hxx>
#include "window.h"
VclContainer::VclContainer(Window *pParent, WinBits nStyle)
@@ -1565,6 +1566,181 @@ bool VclSizeGroup::set_property(const OString &rKey, const OString &rValue)
return true;
}
+MessageDialog::MessageDialog(Window* pParent, WinBits nStyle)
+ : Dialog(pParent, nStyle)
+ , m_pGrid(NULL)
+ , m_pImage(NULL)
+ , m_pPrimaryMessage(NULL)
+ , m_pSecondaryMessage(NULL)
+{
+ SetType(WINDOW_MESSBOX);
+}
+
+MessageDialog::MessageDialog(Window* pParent, const OString& rID, const OUString& rUIXMLDescription)
+ : Dialog(pParent, rID, rUIXMLDescription, WINDOW_MESSBOX)
+ , m_pGrid(NULL)
+ , m_pImage(NULL)
+ , m_pPrimaryMessage(NULL)
+ , m_pSecondaryMessage(NULL)
+{
+}
+
+MessageDialog::~MessageDialog()
+{
+ delete m_pSecondaryMessage;
+ delete m_pPrimaryMessage;
+ delete m_pImage;
+ delete m_pGrid;
+}
+
+IMPL_LINK(MessageDialog, ButtonHdl, Button *, pButton)
+{
+ //for now insist that we have a builder, we can relax that in
+ //the future if we need it
+ assert(m_pUIBuilder);
+ EndDialog(m_pUIBuilder->get_response(pButton));
+ return 0;
+}
+
+void MessageDialog::setButtonHandlers()
+{
+ SAL_WARN_IF(!m_pUIBuilder, "vcl.layout", "MessageDialog non-ui load button responses not implemented yet");
+ if (!m_pUIBuilder)
+ return;
+ VclButtonBox *pButtonBox = get_action_area();
+ assert(pButtonBox);
+ for (Window* pChild = pButtonBox->GetWindow(WINDOW_FIRSTCHILD); pChild;
+ pChild = pChild->GetWindow(WINDOW_NEXT))
+ {
+ switch (pChild->GetType())
+ {
+ case WINDOW_PUSHBUTTON:
+ {
+ PushButton* pButton = (PushButton*)pChild;
+ pButton->SetClickHdl(LINK(this, MessageDialog, ButtonHdl));
+ break;
+ }
+ //for now at least, insist that the response ids match
+ //the default actions for those widgets, and leave
+ //their default handlers in place
+ case WINDOW_OKBUTTON:
+ assert(m_pUIBuilder->get_response(pChild) == RET_OK);
+ break;
+ case WINDOW_CANCELBUTTON:
+ assert(m_pUIBuilder->get_response(pChild) == RET_CANCEL);
+ break;
+ case WINDOW_HELPBUTTON:
+ assert(m_pUIBuilder->get_response(pChild) == RET_HELP);
+ break;
+ default:
+ SAL_WARN("vcl.layout", "The type of widget " <<
+ pChild->GetHelpId() << " is currently not handled");
+ break;
+ }
+ //The default is to stick the focus into the first widget
+ //that accepts it, and if that happens and its a button
+ //then that becomes the new default button, so explicitly
+ //put the focus into the default button
+ if (pChild->GetStyle() & WB_DEFBUTTON)
+ pChild->GrabFocus();
+ }
+}
+
+short MessageDialog::Execute()
+{
+ setDeferredProperties();
+
+ if (!m_pGrid)
+ {
+ VclContainer *pContainer = get_content_area();
+ assert(pContainer);
+
+ m_pGrid = new VclGrid(pContainer);
+ m_pGrid->set_column_spacing(12);
+
+ m_pImage = new FixedImage(m_pGrid, WB_CENTER | WB_VCENTER | WB_3DLOOK);
+ m_pImage->SetImage(WarningBox::GetStandardImage());
+ m_pImage->set_grid_left_attach(0);
+ m_pImage->set_grid_top_attach(0);
+ m_pImage->set_valign(VCL_ALIGN_START);
+ m_pImage->Show();
+
+ WinBits nWinStyle = WB_LEFT | WB_VCENTER | WB_WORDBREAK | WB_NOLABEL | WB_NOTABSTOP;
+
+ m_pPrimaryMessage = new VclMultiLineEdit(m_pGrid, nWinStyle);
+ m_pPrimaryMessage->SetPaintTransparent(true);
+ m_pPrimaryMessage->EnableCursor(false);
+ Font aFont = GetSettings().GetStyleSettings().GetLabelFont();
+ aFont.SetSize( Size( 0, aFont.GetSize().Height() * 1.2 ) );
+ aFont.SetWeight(WEIGHT_BOLD);
+ m_pPrimaryMessage->SetControlFont(aFont);
+ m_pPrimaryMessage->set_grid_left_attach(1);
+ m_pPrimaryMessage->set_grid_top_attach(0);
+ m_pPrimaryMessage->set_hexpand(true);
+ m_pPrimaryMessage->SetText(m_sPrimaryString);
+ m_pPrimaryMessage->Show(!m_sPrimaryString.isEmpty());
+
+ m_pSecondaryMessage = new VclMultiLineEdit(m_pGrid, nWinStyle);
+ m_pSecondaryMessage->SetPaintTransparent(true);
+ m_pSecondaryMessage->EnableCursor(false);
+ m_pSecondaryMessage->set_grid_left_attach(1);
+ m_pSecondaryMessage->set_grid_top_attach(1);
+ m_pSecondaryMessage->set_hexpand(true);
+ m_pSecondaryMessage->SetText(m_sSecondaryString);
+ m_pSecondaryMessage->Show(!m_sSecondaryString.isEmpty());
+
+ m_pGrid->Show();
+
+ setButtonHandlers();
+ }
+ return Dialog::Execute();
+}
+
+OUString MessageDialog::get_primary_text() const
+{
+ const_cast<MessageDialog*>(this)->setDeferredProperties();
+
+ return m_sPrimaryString;
+}
+
+OUString MessageDialog::get_secondary_text() const
+{
+ const_cast<MessageDialog*>(this)->setDeferredProperties();
+
+ return m_sSecondaryString;
+}
+
+bool MessageDialog::set_property(const OString &rKey, const OString &rValue)
+{
+ if (rKey == "text")
+ set_primary_text(OStringToOUString(rValue, RTL_TEXTENCODING_UTF8));
+ else if (rKey == "secondary-text")
+ set_secondary_text(OStringToOUString(rValue, RTL_TEXTENCODING_UTF8));
+ else
+ return Dialog::set_property(rKey, rValue);
+ return true;
+}
+
+void MessageDialog::set_primary_text(const OUString &rPrimaryString)
+{
+ m_sPrimaryString = rPrimaryString;
+ if (m_pPrimaryMessage)
+ {
+ m_pPrimaryMessage->SetText(m_sPrimaryString);
+ m_pPrimaryMessage->Show(!m_sPrimaryString.isEmpty());
+ }
+}
+
+void MessageDialog::set_secondary_text(const OUString &rSecondaryString)
+{
+ m_sSecondaryString = rSecondaryString;
+ if (m_pSecondaryMessage)
+ {
+ m_pSecondaryMessage->SetText(OUString("\n") + m_sSecondaryString);
+ m_pSecondaryMessage->Show(!m_sSecondaryString.isEmpty());
+ }
+}
+
Size getLegacyBestSizeForChildren(const Window &rWindow)
{
Rectangle aBounds;