Kaydet (Commit) 9e5c3545 authored tarafından Caolán McNamara's avatar Caolán McNamara

create a HIG compliant MessageDialog and map to GtkMessageDialog

Change-Id: If86387619ff00a652ea418292fbb0026b867a431
üst 26bda9f4
......@@ -50,6 +50,13 @@ private:
//exist for the duration of the dialog
vcl::detail::ModuleMap m_aModuleMap;
//If the toplevel window has any properties which need to be set on it,
//but the toplevel is the owner of the builder, then its ctor
//has not been completed during the building, so properties for it
//are collected here and need to be set afterwards, e.g. during
//Show or Execute
stringmap m_aDeferredProperties;
struct PackingData
{
bool m_bVerticalOrient;
......@@ -65,10 +72,12 @@ private:
{
OString m_sID;
Window *m_pWindow;
short m_nResponseId;
PackingData m_aPackingData;
WinAndId(const OString &rId, Window *pWindow, bool bVertical)
: m_sID(rId)
, m_pWindow(pWindow)
, m_nResponseId(RET_CANCEL)
, m_aPackingData(bVertical)
{
}
......@@ -215,6 +224,7 @@ private:
ResHookProc m_pStringReplace;
Window *m_pParent;
bool m_bToplevelHasDeferredInit;
bool m_bToplevelHasDeferredProperties;
bool m_bToplevelParentFound;
ParserState *m_pParserState;
......@@ -266,14 +276,23 @@ public:
//sID may not exist
PopupMenu* get_menu(OString sID);
//given an sID return the response value for that widget
short get_response(const Window *pWindow) const;
OString get_by_window(const Window *pWindow) const;
void delete_by_window(const Window *pWindow);
//apply the properties of rProps to pWindow
static void set_properties(Window *pWindow, const stringmap &rProps);
//Convert _ gtk markup to ~ vcl markup
static OString convertMnemonicMarkup(const OString &rIn);
static OString extractCustomProperty(stringmap &rMap);
//see m_aDeferredProperties
void setDeferredProperties();
private:
Window *insertObject(Window *pParent, const OString &rClass, const OString &rID,
stringmap &rProps, stringmap &rPangoAttributes,
......@@ -322,12 +341,16 @@ private:
void handleAtkObject(xmlreader::XmlReader &reader, const OString &rID, Window *pWindow);
void handleActionWidget(xmlreader::XmlReader &reader);
PackingData get_window_packing_data(const Window *pWindow) const;
void set_window_packing_position(const Window *pWindow, sal_Int32 nPosition);
Window* prepareWidgetOwnScrolling(Window *pParent, WinBits &rWinStyle);
void cleanupWidgetOwnScrolling(Window *pScrollParent, Window *pWindow, stringmap &rMap);
void set_response(OString sID, short nResponse);
//Helpers to retrofit all the existing code to the builder
static void reorderWithinParent(Window &rWindow, sal_uInt16 nNewPosition);
};
......@@ -368,6 +391,12 @@ public:
{
return m_pUIBuilder->get_menu(sID);
}
void setDeferredProperties()
{
if (!m_pUIBuilder)
return;
m_pUIBuilder->setDeferredProperties();
}
};
/*
......
......@@ -12,7 +12,10 @@
#include <vcl/dllapi.h>
#include <vcl/button.hxx>
#include <vcl/dialog.hxx>
#include <vcl/fixed.hxx>
#include <vcl/scrbar.hxx>
#include <vcl/vclmedit.hxx>
#include <vcl/window.hxx>
#include <boost/multi_array.hpp>
#include <set>
......@@ -638,6 +641,29 @@ public:
bool set_property(const OString &rKey, const OString &rValue);
};
class VCL_DLLPUBLIC MessageDialog : public Dialog
{
private:
VclGrid* m_pGrid;
FixedImage* m_pImage;
VclMultiLineEdit* m_pPrimaryMessage;
VclMultiLineEdit* m_pSecondaryMessage;
OUString m_sPrimaryString;
OUString m_sSecondaryString;
DECL_DLLPRIVATE_LINK(ButtonHdl, Button *);
void setButtonHandlers();
public:
MessageDialog(Window* pParent, WinBits nStyle);
MessageDialog(Window* pParent, const OString& rID, const OUString& rUIXMLDescription);
virtual bool set_property(const OString &rKey, const OString &rValue);
virtual short Execute();
OUString get_primary_text() const;
OUString get_secondary_text() const;
void set_primary_text(const OUString &rPrimaryString);
void set_secondary_text(const OUString &rSecondaryString);
~MessageDialog();
};
VCL_DLLPUBLIC Size bestmaxFrameSizeForScreenSize(const Size &rScreenSize);
//Get first window of a pTopLevel window as
......
......@@ -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(),
......
......@@ -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;
......
......@@ -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;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment