summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--compilerplugins/clang/constantparam.numbers.results4
-rw-r--r--include/sfx2/infobar.hxx57
-rw-r--r--include/sfx2/objsh.hxx4
-rw-r--r--include/sfx2/sfxbasecontroller.hxx4
-rw-r--r--include/sfx2/viewfrm.hxx12
-rw-r--r--include/vcl/weldutils.hxx29
-rw-r--r--sc/source/ui/docshell/docsh4.cxx10
-rw-r--r--sc/source/ui/inc/docsh.hxx2
-rw-r--r--sfx2/UIConfig_sfx.mk2
-rw-r--r--sfx2/source/dialog/infobar.cxx380
-rw-r--r--sfx2/source/doc/objserv.cxx10
-rw-r--r--sfx2/source/view/sfxbasecontroller.cxx17
-rw-r--r--sfx2/source/view/viewfrm.cxx56
-rw-r--r--sfx2/uiconfig/ui/extrabutton.ui24
-rw-r--r--sfx2/uiconfig/ui/infobar.ui187
-rw-r--r--solenv/sanitizers/ui/sfx.suppr1
-rw-r--r--vcl/source/app/weldutils.cxx58
17 files changed, 584 insertions, 273 deletions
diff --git a/compilerplugins/clang/constantparam.numbers.results b/compilerplugins/clang/constantparam.numbers.results
index 0a808e5f2924..add43943e088 100644
--- a/compilerplugins/clang/constantparam.numbers.results
+++ b/compilerplugins/clang/constantparam.numbers.results
@@ -806,10 +806,6 @@ include/sfx2/frame.hxx:192
void SfxUnoFrameItem::SfxUnoFrameItem(unsigned short,const class com::sun::star::uno::Reference<class com::sun::star::frame::XFrame> &)
unsigned short nWhich
6516
-include/sfx2/infobar.hxx:111
- class VclPtr<class SfxInfoBarWindow> SfxInfoBarContainerWindow::appendInfoBar(const class rtl::OUString &,const class rtl::OUString &,const class rtl::OUString &,enum InfobarType,long,_Bool)
- long nMessageStyle
- 278528
include/sfx2/linkmgr.hxx:63
_Bool sfx2::LinkManager::InsertLink(class sfx2::SvBaseLink *,enum sfx2::SvBaseLinkObjectType,enum SfxLinkUpdateMode,const class rtl::OUString *)
enum SfxLinkUpdateMode nUpdateType
diff --git a/include/sfx2/infobar.hxx b/include/sfx2/infobar.hxx
index 40a1b1ff9fbf..a03c833b957d 100644
--- a/include/sfx2/infobar.hxx
+++ b/include/sfx2/infobar.hxx
@@ -15,11 +15,7 @@
#include <sfx2/childwin.hxx>
#include <sfx2/dllapi.h>
-
-class FixedImage;
-class FixedText;
-class Button;
-class PushButton;
+#include <vcl/InterimItemWindow.hxx>
// These must match the values in offapi/com/sun/star/frame/InfobarType.idl
enum class InfobarType
@@ -57,44 +53,59 @@ public:
void Update();
};
+class ExtraButton;
+
/** Class representing a single InfoBar to be added in a SfxInfoBarContainerWindow.
*/
-class SFX2_DLLPUBLIC SfxInfoBarWindow final : public vcl::Window
+class SFX2_DLLPUBLIC SfxInfoBarWindow final : public InterimItemWindow
{
private:
OUString m_sId;
InfobarType m_eType;
- VclPtr<FixedImage> m_pImage;
- VclPtr<FixedText> m_pPrimaryMessage;
- VclPtr<FixedText> m_pSecondaryMessage;
- VclPtr<Button> m_pCloseBtn;
- std::vector<VclPtr<PushButton>> m_aActionBtns;
+ Size m_aSize;
+ Size m_aMessageSize;
+ Size m_aOrigMessageSize;
+ bool m_bLayingOut;
+ std::unique_ptr<weld::Image> m_xImage;
+ std::unique_ptr<weld::Label> m_xPrimaryMessage;
+ std::unique_ptr<weld::TextView> m_xSecondaryMessage;
+ std::unique_ptr<weld::Container> m_xButtonBox;
+ std::unique_ptr<weld::Toolbar> m_xCloseBtn;
+ std::vector<std::unique_ptr<ExtraButton>> m_aActionBtns;
+
+ DECL_LINK(SizeAllocHdl, const Size&, void);
void SetForeAndBackgroundColors(InfobarType eType);
+ void SetCloseButtonImage();
public:
SfxInfoBarWindow(vcl::Window* parent, const OUString& sId, const OUString& sPrimaryMessage,
const OUString& sSecondaryMessage, InfobarType InfobarType,
- WinBits nMessageStyle, bool bShowCloseButton);
+ bool bShowCloseButton);
+ Size DoLayout();
+ virtual void Layout() override;
virtual ~SfxInfoBarWindow() override;
virtual void dispose() override;
const OUString& getId() const { return m_sId; }
- virtual void Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle&) override;
- virtual void Resize() override;
void Update(const OUString& sPrimaryMessage, const OUString& sSecondaryMessage,
InfobarType eType);
basegfx::BColor m_aBackgroundColor;
basegfx::BColor m_aForegroundColor;
/** Add button to Infobar.
- * Infobar takes ownership of the button so the button is
- * destroyed when the infobar gets destroyed.
- */
- void addButton(PushButton* pButton);
+ * Infobar takes ownership of the button so the button is
+ * destroyed when the infobar gets destroyed.
+ *
+ * The optional "pCommand" is used by extensions, via XInfobarProvider, to
+ * dispatch pCommand on click.
+ */
+ weld::Button& addButton(const OUString* pCommand = nullptr);
+
+ void SetCommandHandler(weld::Button& rBtn, const OUString& aCommand);
private:
- DECL_LINK(CloseHandler, Button*, void);
+ DECL_LINK(CloseHandler, const OString&, void);
};
class SfxInfoBarContainerWindow final : public vcl::Window
@@ -102,6 +113,10 @@ class SfxInfoBarContainerWindow final : public vcl::Window
private:
SfxInfoBarContainerChild* m_pChildWin;
std::vector<VclPtr<SfxInfoBarWindow>> m_pInfoBars;
+ Idle m_aLayoutIdle;
+ bool m_bResizing;
+
+ DECL_LINK(DoUpdateLayout, Timer*, void);
public:
SfxInfoBarContainerWindow(SfxInfoBarContainerChild* pChildWin);
@@ -110,12 +125,14 @@ public:
VclPtr<SfxInfoBarWindow> appendInfoBar(const OUString& sId, const OUString& sPrimaryMessage,
const OUString& sSecondaryMessage, InfobarType ibType,
- WinBits nMessageStyle, bool bShowCloseButton);
+ bool bShowCloseButton);
VclPtr<SfxInfoBarWindow> getInfoBar(const OUString& sId);
bool hasInfoBarWithID(const OUString& sId);
void removeInfoBar(VclPtr<SfxInfoBarWindow> const& pInfoBar);
static bool isInfobarEnabled(const OUString& sId);
+ void TriggerUpdateLayout();
+
virtual void Resize() override;
};
diff --git a/include/sfx2/objsh.hxx b/include/sfx2/objsh.hxx
index 8da1f2bb7f82..e60139348c26 100644
--- a/include/sfx2/objsh.hxx
+++ b/include/sfx2/objsh.hxx
@@ -41,6 +41,7 @@
#include <functional>
#include <sfx2/AccessibilityIssue.hxx>
+namespace weld {class Button; }
class SbxValue;
class SbxArray;
class BasicManager;
@@ -58,7 +59,6 @@ class GDIMetaFile;
class INetURLObject;
class IndexBitSet;
class JobSetup;
-class Button;
class OutputDevice;
class Color;
class Fraction;
@@ -368,7 +368,7 @@ public:
const OUString& aComment);
SignatureState GetScriptingSignatureState();
void SignScriptingContent(weld::Window* pDialogParent);
- DECL_LINK(SignDocumentHandler, Button*, void);
+ DECL_LINK(SignDocumentHandler, weld::Button&, void);
virtual std::shared_ptr<SfxDocumentInfoDialog> CreateDocumentInfoDialog(weld::Window* pParent, const SfxItemSet& rItemSet);
diff --git a/include/sfx2/sfxbasecontroller.hxx b/include/sfx2/sfxbasecontroller.hxx
index 7fd536a14ef7..2adae2ec6cdc 100644
--- a/include/sfx2/sfxbasecontroller.hxx
+++ b/include/sfx2/sfxbasecontroller.hxx
@@ -50,10 +50,10 @@ namespace com::sun::star::frame { struct DispatchDescriptor; }
namespace com::sun::star::ui { class XContextMenuInterceptor; }
namespace com::sun::star::ui { class XSidebarProvider; }
namespace com::sun::star::util { struct URL; }
+namespace weld { class Button; }
struct IMPL_SfxBaseController_DataContainer ; // impl. struct to hold member of class SfxBaseController
-class Button;
class NotifyEvent;
class SfxViewFrame;
class SfxViewShell;
@@ -207,7 +207,7 @@ private:
SAL_DLLPRIVATE SfxViewFrame& GetViewFrame_Impl() const;
SAL_DLLPRIVATE void ShowInfoBars( );
- DECL_LINK( CheckOutHandler, Button*, void );
+ DECL_LINK( CheckOutHandler, weld::Button&, void );
std::unique_ptr<IMPL_SfxBaseController_DataContainer> m_pData ;
diff --git a/include/sfx2/viewfrm.hxx b/include/sfx2/viewfrm.hxx
index 07d1360c57c7..aedd362f8781 100644
--- a/include/sfx2/viewfrm.hxx
+++ b/include/sfx2/viewfrm.hxx
@@ -30,7 +30,7 @@
#include <svl/poolitem.hxx>
#include <vcl/svapp.hxx>
-class Button;
+namespace weld { class Button; }
class SvBorder;
class SfxDispatcher;
class SfxBindings;
@@ -59,11 +59,11 @@ private:
protected:
virtual void Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) override;
- DECL_LINK(GetInvolvedHandler, Button*, void);
- DECL_LINK(DonationHandler, Button*, void);
- DECL_LINK(WhatsNewHandler, Button*, void);
- DECL_LINK(SwitchReadOnlyHandler, Button*, void);
- DECL_LINK(SignDocumentHandler, Button*, void);
+ DECL_LINK(GetInvolvedHandler, weld::Button&, void);
+ DECL_LINK(DonationHandler, weld::Button&, void);
+ DECL_LINK(WhatsNewHandler, weld::Button&, void);
+ DECL_LINK(SwitchReadOnlyHandler, weld::Button&, void);
+ DECL_LINK(SignDocumentHandler, weld::Button&, void);
SAL_DLLPRIVATE void KillDispatcher_Impl();
virtual ~SfxViewFrame() override;
diff --git a/include/vcl/weldutils.hxx b/include/vcl/weldutils.hxx
index 7eb4334e0156..7d22a456119e 100644
--- a/include/vcl/weldutils.hxx
+++ b/include/vcl/weldutils.hxx
@@ -11,6 +11,9 @@
#define INCLUDED_VCL_WELDUTILS_HXX
#include <com/sun/star/awt/XWindow.hpp>
+#include <com/sun/star/frame/XDispatch.hpp>
+#include <com/sun/star/frame/XFrame.hpp>
+#include <com/sun/star/frame/XStatusListener.hpp>
#include <com/sun/star/uno/Reference.hxx>
#include <comphelper/interfacecontainer2.hxx>
#include <cppuhelper/compbase.hxx>
@@ -156,6 +159,32 @@ public:
}
};
+class VCL_DLLPUBLIC WidgetStatusListener final
+ : public cppu::WeakImplHelper<css::frame::XStatusListener>
+{
+public:
+ WidgetStatusListener(weld::Widget* widget, const OUString& rCommand);
+
+private:
+ weld::Widget* mWidget; /** The widget on which actions are performed */
+
+ /** Dispatcher. Need to keep a reference to it as long as this StatusListener exists. */
+ css::uno::Reference<css::frame::XDispatch> mxDispatch;
+ css::util::URL maCommandURL;
+ css::uno::Reference<css::frame::XFrame> mxFrame;
+
+public:
+ void SAL_CALL statusChanged(const css::frame::FeatureStateEvent& rEvent) override;
+
+ void SAL_CALL disposing(const css::lang::EventObject& /*Source*/) override;
+
+ const css::uno::Reference<css::frame::XFrame>& getFrame() { return mxFrame; }
+
+ void startListening();
+
+ void dispose();
+};
+
class VCL_DLLPUBLIC EntryFormatter : public Formatter
{
public:
diff --git a/sc/source/ui/docshell/docsh4.cxx b/sc/source/ui/docshell/docsh4.cxx
index ecce1c5da91f..a63a8b49619b 100644
--- a/sc/source/ui/docshell/docsh4.cxx
+++ b/sc/source/ui/docshell/docsh4.cxx
@@ -135,7 +135,7 @@ void ScDocShell::ReloadAllLinks()
m_aDocument.UpdateAreaLinks();
}
-IMPL_LINK_NOARG( ScDocShell, ReloadAllLinksHdl, Button*, void )
+IMPL_LINK_NOARG( ScDocShell, ReloadAllLinksHdl, weld::Button&, void )
{
ReloadAllLinks();
@@ -500,11 +500,9 @@ void ScDocShell::Execute( SfxRequest& rReq )
auto pInfoBar = pViewFrame->AppendInfoBar("enablecontent", "", ScResId(STR_RELOAD_TABLES), InfobarType::WARNING);
if (pInfoBar)
{
- VclPtrInstance<PushButton> xBtn(&pViewFrame->GetWindow());
- xBtn->SetText(ScResId(STR_ENABLE_CONTENT));
- xBtn->SetSizePixel(xBtn->GetOptimalSize());
- xBtn->SetClickHdl(LINK(this, ScDocShell, ReloadAllLinksHdl));
- pInfoBar->addButton(xBtn);
+ weld::Button& rBtn = pInfoBar->addButton();
+ rBtn.set_label(ScResId(STR_ENABLE_CONTENT));
+ rBtn.connect_clicked(LINK(this, ScDocShell, ReloadAllLinksHdl));
}
}
rReq.Done();
diff --git a/sc/source/ui/inc/docsh.hxx b/sc/source/ui/inc/docsh.hxx
index e23067503bae..8a7fc31c1364 100644
--- a/sc/source/ui/inc/docsh.hxx
+++ b/sc/source/ui/inc/docsh.hxx
@@ -337,7 +337,7 @@ public:
void UnlockDocument();
DECL_LINK( DialogClosedHdl, sfx2::FileDialogHelper*, void );
- DECL_LINK( ReloadAllLinksHdl, Button*, void );
+ DECL_LINK( ReloadAllLinksHdl, weld::Button&, void );
virtual SfxStyleSheetBasePool* GetStyleSheetPool() override;
diff --git a/sfx2/UIConfig_sfx.mk b/sfx2/UIConfig_sfx.mk
index 5e79a8399cbf..5bb91d7ac6f6 100644
--- a/sfx2/UIConfig_sfx.mk
+++ b/sfx2/UIConfig_sfx.mk
@@ -30,6 +30,7 @@ $(eval $(call gb_UIConfig_add_uifiles,sfx,\
sfx2/uiconfig/ui/editdocumentdialog \
sfx2/uiconfig/ui/editdurationdialog \
sfx2/uiconfig/ui/emojicontrol \
+ sfx2/uiconfig/ui/extrabutton \
sfx2/uiconfig/ui/errorfindemaildialog \
sfx2/uiconfig/ui/floatingrecord \
sfx2/uiconfig/ui/helpbookmarkpage \
@@ -39,6 +40,7 @@ $(eval $(call gb_UIConfig_add_uifiles,sfx,\
sfx2/uiconfig/ui/helpmanual \
sfx2/uiconfig/ui/helpsearchpage \
sfx2/uiconfig/ui/helpwindow \
+ sfx2/uiconfig/ui/infobar \
sfx2/uiconfig/ui/inputdialog \
sfx2/uiconfig/ui/licensedialog \
sfx2/uiconfig/ui/linefragment \
diff --git a/sfx2/source/dialog/infobar.cxx b/sfx2/source/dialog/infobar.cxx
index fd64691ffa99..580bd6685801 100644
--- a/sfx2/source/dialog/infobar.cxx
+++ b/sfx2/source/dialog/infobar.cxx
@@ -8,6 +8,7 @@
*/
#include <basegfx/polygon/b2dpolygon.hxx>
+#include <comphelper/dispatchcommand.hxx>
#include <drawinglayer/primitive2d/polygonprimitive2d.hxx>
#include <drawinglayer/primitive2d/PolyPolygonColorPrimitive2D.hxx>
#include <drawinglayer/primitive2d/PolyPolygonStrokePrimitive2D.hxx>
@@ -21,11 +22,13 @@
#include <sfx2/objface.hxx>
#include <sfx2/sfxsids.hrc>
#include <sfx2/viewfrm.hxx>
-#include <vcl/button.hxx>
-#include <vcl/fixed.hxx>
#include <vcl/decoview.hxx>
+#include <vcl/image.hxx>
#include <vcl/settings.hxx>
#include <vcl/svapp.hxx>
+#include <vcl/virdev.hxx>
+#include <vcl/weldutils.hxx>
+#include <bitmaps.hlst>
using namespace std;
using namespace drawinglayer::geometry;
@@ -37,8 +40,6 @@ using namespace css::frame;
namespace
{
-const long INFO_BAR_BASE_HEIGHT = 40;
-
void GetInfoBarColors(InfobarType ibType, BColor& rBackgroundColor, BColor& rForegroundColor,
BColor& rMessageColor)
{
@@ -79,54 +80,39 @@ OUString GetInfoBarIconName(InfobarType ibType)
switch (ibType)
{
case InfobarType::INFO:
- aRet = "vcl/res/infobox.svg";
+ aRet = "vcl/res/infobox.png";
break;
case InfobarType::SUCCESS:
- aRet = "vcl/res/successbox.svg";
+ aRet = "vcl/res/successbox.png";
break;
case InfobarType::WARNING:
- aRet = "vcl/res/warningbox.svg";
+ aRet = "vcl/res/warningbox.png";
break;
case InfobarType::DANGER:
- aRet = "vcl/res/errorbox.svg";
+ aRet = "vcl/res/errorbox.png";
break;
}
return aRet;
}
-class SfxCloseButton : public PushButton
-{
- basegfx::BColor m_aBackgroundColor;
- basegfx::BColor m_aForegroundColor;
-
-public:
- explicit SfxCloseButton(vcl::Window* pParent)
- : PushButton(pParent, 0)
- {
- basegfx::BColor aMessageColor;
- GetInfoBarColors(InfobarType::WARNING, m_aBackgroundColor, m_aForegroundColor,
- aMessageColor);
- }
+} // anonymous namespace
- virtual void Paint(vcl::RenderContext& rRenderContext,
- const ::tools::Rectangle& rRect) override;
+void SfxInfoBarWindow::SetCloseButtonImage()
+{
+ Size aSize = Image(StockImage::Yes, CLOSEDOC).GetSizePixel();
+ aSize = Size(aSize.Width() * 1.5, aSize.Height() * 1.5);
- void setBackgroundColor(const basegfx::BColor& rColor);
- void setForegroundColor(const basegfx::BColor& rColor);
-};
+ VclPtr<VirtualDevice> xDevice(m_xCloseBtn->create_virtual_device());
+ xDevice->SetOutputSizePixel(aSize);
-void SfxCloseButton::Paint(vcl::RenderContext& rRenderContext, const ::tools::Rectangle&)
-{
Point aBtnPos(0, 0);
- if (GetButtonState() & DrawButtonFlags::Pressed)
- aBtnPos.Move(Size(1, 1));
const ViewInformation2D aNewViewInfos;
const unique_ptr<BaseProcessor2D> pProcessor(
- createBaseProcessor2DFromOutputDevice(rRenderContext, aNewViewInfos));
+ createBaseProcessor2DFromOutputDevice(*xDevice, aNewViewInfos));
- const ::tools::Rectangle aRect(aBtnPos, PixelToLogic(GetSizePixel()));
+ const ::tools::Rectangle aRect(aBtnPos, xDevice->PixelToLogic(aSize));
drawinglayer::primitive2d::Primitive2DContainer aSeq(2);
@@ -138,12 +124,8 @@ void SfxCloseButton::Paint(vcl::RenderContext& rRenderContext, const ::tools::Re
aPolygon.append(B2DPoint(aRect.Left(), aRect.Bottom()));
aPolygon.setClosed(true);
- Color aBackgroundColor(m_aBackgroundColor);
- if (IsMouseOver() || HasFocus())
- aBackgroundColor.ApplyTintOrShade(-2000);
-
PolyPolygonColorPrimitive2D* pBack
- = new PolyPolygonColorPrimitive2D(B2DPolyPolygon(aPolygon), aBackgroundColor.getBColor());
+ = new PolyPolygonColorPrimitive2D(B2DPolyPolygon(aPolygon), m_aBackgroundColor);
aSeq[0] = pBack;
LineAttribute aLineAttribute(m_aForegroundColor, 2.0);
@@ -167,187 +149,186 @@ void SfxCloseButton::Paint(vcl::RenderContext& rRenderContext, const ::tools::Re
aSeq[1] = pCross;
pProcessor->process(aSeq);
+
+ m_xCloseBtn->set_item_image("close", xDevice);
}
-void SfxCloseButton::setBackgroundColor(const basegfx::BColor& rColor)
+class ExtraButton
{
- m_aBackgroundColor = rColor;
-}
+private:
+ std::unique_ptr<weld::Builder> m_xBuilder;
+ std::unique_ptr<weld::Container> m_xContainer;
+ std::unique_ptr<weld::Button> m_xButton;
+ /** StatusListener. Updates the button as the slot state changes */
+ rtl::Reference<weld::WidgetStatusListener> m_xStatusListener;
+ OUString m_aCommand;
+
+ DECL_LINK(CommandHdl, weld::Button&, void);
+
+public:
+ ExtraButton(weld::Container* pContainer, const OUString* pCommand)
+ : m_xBuilder(Application::CreateBuilder(pContainer, "sfx/ui/extrabutton.ui"))
+ , m_xContainer(m_xBuilder->weld_container("ExtraButton"))
+ , m_xButton(m_xBuilder->weld_button("button"))
+ {
+ if (pCommand)
+ {
+ m_aCommand = *pCommand;
+ m_xButton->connect_clicked(LINK(this, ExtraButton, CommandHdl));
+ m_xStatusListener.set(new weld::WidgetStatusListener(m_xButton.get(), m_aCommand));
+ m_xStatusListener->startListening();
+ }
+ }
+
+ ~ExtraButton()
+ {
+ if (m_xStatusListener.is())
+ m_xStatusListener->dispose();
+ }
+
+ weld::Button& get_widget() { return *m_xButton; }
+};
-void SfxCloseButton::setForegroundColor(const basegfx::BColor& rColor)
+IMPL_LINK_NOARG(ExtraButton, CommandHdl, weld::Button&, void)
{
- m_aForegroundColor = rColor;
+ comphelper::dispatchCommand(m_aCommand, css::uno::Sequence<css::beans::PropertyValue>());
}
-} // anonymous namespace
-
SfxInfoBarWindow::SfxInfoBarWindow(vcl::Window* pParent, const OUString& sId,
const OUString& sPrimaryMessage,
const OUString& sSecondaryMessage, InfobarType ibType,
- WinBits nMessageStyle, bool bShowCloseButton)
- : Window(pParent, WB_DIALOGCONTROL)
+ bool bShowCloseButton)
+ : InterimItemWindow(pParent, "sfx/ui/infobar.ui", "InfoBar")
, m_sId(sId)
, m_eType(ibType)
- , m_pImage(VclPtr<FixedImage>::Create(this, nMessageStyle))
- , m_pPrimaryMessage(VclPtr<FixedText>::Create(this, nMessageStyle | WB_WORDBREAK))
- , m_pSecondaryMessage(VclPtr<FixedText>::Create(this, nMessageStyle | WB_WORDBREAK))
- , m_pCloseBtn(VclPtr<SfxCloseButton>::Create(this))
+ , m_bLayingOut(false)
+ , m_xImage(m_xBuilder->weld_image("image"))
+ , m_xPrimaryMessage(m_xBuilder->weld_label("primary"))
+ , m_xSecondaryMessage(m_xBuilder->weld_text_view("secondary"))
+ , m_xButtonBox(m_xBuilder->weld_container("buttonbox"))
+ , m_xCloseBtn(m_xBuilder->weld_toolbar("closebar"))
, m_aActionBtns()
{
- m_pCloseBtn->SetStyle(WB_DEFBUTTON | WB_TABSTOP);
- SetForeAndBackgroundColors(m_eType);
- float fScaleFactor = GetDPIScaleFactor();
- long nWidth = pParent->GetSizePixel().getWidth();
- SetPosSizePixel(Point(0, 0), Size(nWidth, INFO_BAR_BASE_HEIGHT * fScaleFactor));
+ SetStyle(GetStyle() | WB_DIALOGCONTROL);
- m_pImage->SetImage(Image(StockImage::Yes, GetInfoBarIconName(ibType)));
- m_pImage->SetPaintTransparent(true);
- m_pImage->Show();
+ InitControlBase(m_xCloseBtn.get());
+
+ m_xImage->set_from_icon_name(GetInfoBarIconName(ibType));
+ m_xSecondaryMessage->set_margin_top(m_xImage->get_preferred_size().Height() / 4);
- vcl::Font aFont(m_pPrimaryMessage->GetControlFont());
- aFont.SetWeight(WEIGHT_BOLD);
- m_pPrimaryMessage->SetControlFont(aFont);
if (!sPrimaryMessage.isEmpty())
{
- m_pPrimaryMessage->SetText(sPrimaryMessage);
- m_pPrimaryMessage->Show();
+ m_xPrimaryMessage->set_label(sPrimaryMessage);
+ m_xPrimaryMessage->show();
}
- m_pSecondaryMessage->SetText(sSecondaryMessage);
- m_pSecondaryMessage->Show();
+ m_xSecondaryMessage->set_text(sSecondaryMessage);
+ m_aOrigMessageSize = m_xSecondaryMessage->get_preferred_size();
+ m_aMessageSize = m_aOrigMessageSize;
+ m_xSecondaryMessage->connect_size_allocate(LINK(this, SfxInfoBarWindow, SizeAllocHdl));
if (bShowCloseButton)
{
- m_pCloseBtn->SetClickHdl(LINK(this, SfxInfoBarWindow, CloseHandler));
- m_pCloseBtn->Show();
+ m_xCloseBtn->connect_clicked(LINK(this, SfxInfoBarWindow, CloseHandler));
+ m_xCloseBtn->show();
}
EnableChildTransparentMode();
- Resize();
-}
+ SetForeAndBackgroundColors(m_eType);
+
+ auto nWidth = pParent->GetSizePixel().getWidth();
+ auto nHeight = get_preferred_size().Height();
+ SetSizePixel(Size(nWidth, nHeight + 2));
-void SfxInfoBarWindow::addButton(PushButton* pButton)
-{
- pButton->SetParent(this);
- pButton->Show();
- m_aActionBtns.emplace_back(pButton);
Resize();
}
-SfxInfoBarWindow::~SfxInfoBarWindow() { disposeOnce(); }
-
-void SfxInfoBarWindow::SetForeAndBackgroundColors(InfobarType eType)
+IMPL_LINK(SfxInfoBarWindow, SizeAllocHdl, const Size&, rSize, void)
{
- basegfx::BColor aMessageColor;
- GetInfoBarColors(eType, m_aBackgroundColor, m_aForegroundColor, aMessageColor);
-
- static_cast<SfxCloseButton*>(m_pCloseBtn.get())->setBackgroundColor(m_aBackgroundColor);
- static_cast<SfxCloseButton*>(m_pCloseBtn.get())->setForegroundColor(m_aForegroundColor);
- m_pPrimaryMessage->SetControlForeground(Color(aMessageColor));
- m_pSecondaryMessage->SetControlForeground(Color(aMessageColor));
+ if (m_aMessageSize != rSize)
+ {
+ m_aMessageSize = rSize;
+ static_cast<SfxInfoBarContainerWindow*>(GetParent())->TriggerUpdateLayout();
+ }
}
-void SfxInfoBarWindow::dispose()
+Size SfxInfoBarWindow::DoLayout()
{
- for (auto& rxBtn : m_aActionBtns)
- rxBtn.disposeAndClear();
-
- m_pImage.disposeAndClear();
- m_pPrimaryMessage.disposeAndClear();
- m_pSecondaryMessage.disposeAndClear();
- m_pCloseBtn.disposeAndClear();
- m_aActionBtns.clear();
- vcl::Window::dispose();
+ Size aGivenSize(GetSizePixel());
+
+ // disconnect SizeAllocHdl because we don't care about the size change
+ // during layout
+ m_xSecondaryMessage->connect_size_allocate(Link<const Size&, void>());
+
+ // blow away size cache in case m_aMessageSize.Width() is already the width request
+ // and we would get the cached preferred size instead of the recalc we want to force
+ m_xSecondaryMessage->set_size_request(-1, -1);
+ // make the width we were detected as set to by SizeAllocHdl as our desired width
+ m_xSecondaryMessage->set_size_request(m_aMessageSize.Width(), -1);
+ // get our preferred size with that message width
+ Size aSizeForWidth(aGivenSize.Width(), m_xContainer->get_preferred_size().Height());
+ // restore the message preferred size so we can freely resize, and get a new
+ // m_aMessageSize and repeat the process if we do
+ m_xSecondaryMessage->set_size_request(m_aOrigMessageSize.Width(), -1);
+
+ // connect SizeAllocHdl so changes outside of this layout will trigger a new layout
+ m_xSecondaryMessage->connect_size_allocate(LINK(this, SfxInfoBarWindow, SizeAllocHdl));
+
+ return aSizeForWidth;
}
-void SfxInfoBarWindow::Paint(vcl::RenderContext& rRenderContext,
- const ::tools::Rectangle& rPaintRect)
+void SfxInfoBarWindow::Layout()
{
- const ViewInformation2D aNewViewInfos;
- const unique_ptr<BaseProcessor2D> pProcessor(
- createBaseProcessor2DFromOutputDevice(rRenderContext, aNewViewInfos));
+ if (m_bLayingOut)
+ return;
+ m_bLayingOut = true;
- const ::tools::Rectangle aRect(Point(0, 0), PixelToLogic(GetSizePixel()));
+ InterimItemWindow::Layout();
- drawinglayer::primitive2d::Primitive2DContainer aSeq(2);
-
- // Light background
- B2DPolygon aPolygon;
- aPolygon.append(B2DPoint(aRect.Left(), aRect.Top()));
- aPolygon.append(B2DPoint(aRect.Right(), aRect.Top()));
- aPolygon.append(B2DPoint(aRect.Right(), aRect.Bottom()));
- aPolygon.append(B2DPoint(aRect.Left(), aRect.Bottom()));
- aPolygon.setClosed(true);
-
- PolyPolygonColorPrimitive2D* pBack
- = new PolyPolygonColorPrimitive2D(B2DPolyPolygon(aPolygon), m_aBackgroundColor);
- aSeq[0] = pBack;
-
- LineAttribute aLineAttribute(m_aForegroundColor, 1.0);
-
- // Bottom dark line
- B2DPolygon aPolygonBottom;
- aPolygonBottom.append(B2DPoint(aRect.Left(), aRect.Bottom()));
- aPolygonBottom.append(B2DPoint(aRect.Right(), aRect.Bottom()));
-
- PolygonStrokePrimitive2D* pLineBottom
- = new PolygonStrokePrimitive2D(aPolygonBottom, aLineAttribute);
-
- aSeq[1] = pLineBottom;
-
- pProcessor->process(aSeq);
-
- Window::Paint(rRenderContext, rPaintRect);
+ m_bLayingOut = false;
}
-void SfxInfoBarWindow::Resize()
+weld::Button& SfxInfoBarWindow::addButton(const OUString* pCommand)
{
- float fScaleFactor = GetDPIScaleFactor();
+ m_aActionBtns.emplace_back(std::make_unique<ExtraButton>(m_xButtonBox.get(), pCommand));
- long nWidth = GetSizePixel().getWidth();
- m_pCloseBtn->SetPosSizePixel(Point(nWidth - 25 * fScaleFactor, 15 * fScaleFactor),
- Size(10 * fScaleFactor, 10 * fScaleFactor));
-
- // Reparent the buttons and place them on the right of the bar
- long nX = m_pCloseBtn->GetPosPixel().getX() - 15 * fScaleFactor;
- long nButtonGap = 5 * fScaleFactor;
-
- for (auto const& actionBtn : m_aActionBtns)
- {
- long nButtonWidth = actionBtn->GetSizePixel().getWidth();
- nX -= nButtonWidth;
- actionBtn->SetPosSizePixel(Point(nX, 5 * fScaleFactor),
- Size(nButtonWidth, 30 * fScaleFactor));
- nX -= nButtonGap;
- }
+ return m_aActionBtns.back()->get_widget();
+}
- Point aPrimaryMessagePosition(32 * fScaleFactor + 10 * fScaleFactor, 10 * fScaleFactor);
- Point aSecondaryMessagePosition(aPrimaryMessagePosition);
- Size aMessageSize(nX - 35 * fScaleFactor, 20 * fScaleFactor);
- Size aPrimaryTextSize = m_pPrimaryMessage->CalcMinimumSize(aMessageSize.getWidth());
- Size aSecondaryTextSize = m_pSecondaryMessage->CalcMinimumSize(aMessageSize.getWidth()
- - aPrimaryTextSize.getWidth());
- if (!m_pPrimaryMessage->GetText().isEmpty())
- aSecondaryMessagePosition.AdjustX(aPrimaryTextSize.getWidth() + 6 * fScaleFactor);
+SfxInfoBarWindow::~SfxInfoBarWindow() { disposeOnce(); }
- long aMinimumHeight = std::max(m_pPrimaryMessage->CalcMinimumSize().getHeight(),
- m_pSecondaryMessage->CalcMinimumSize().getHeight());
+void SfxInfoBarWindow::SetForeAndBackgroundColors(InfobarType eType)
+{
+ basegfx::BColor aMessageColor;
+ GetInfoBarColors(eType, m_aBackgroundColor, m_aForegroundColor, aMessageColor);
- long aExtraHeight = aSecondaryTextSize.getHeight() - aMinimumHeight;
+ m_xPrimaryMessage->set_font_color(Color(aMessageColor));
+ m_xSecondaryMessage->set_font_color(Color(aMessageColor));
- // The message won't be legible and the window will get too high
- if (aMessageSize.getWidth() < 30)
+ Color aBackgroundColor(m_aBackgroundColor);
+ m_xPrimaryMessage->set_background(aBackgroundColor);
+ m_xSecondaryMessage->set_background(aBackgroundColor);
+ m_xContainer->set_background(aBackgroundColor);
+ if (m_xCloseBtn->get_visible())
{
- aExtraHeight = 0;
+ m_xCloseBtn->set_background(aBackgroundColor);
+ SetCloseButtonImage();
}
+}
- m_pPrimaryMessage->SetPosSizePixel(aPrimaryMessagePosition, aPrimaryTextSize);
- m_pSecondaryMessage->SetPosSizePixel(aSecondaryMessagePosition, aSecondaryTextSize);
- m_pImage->SetPosSizePixel(Point(4, 4), Size(32 * fScaleFactor, 32 * fScaleFactor));
+void SfxInfoBarWindow::dispose()
+{
+ for (auto& rxBtn : m_aActionBtns)
+ rxBtn.reset();
- SetPosSizePixel(GetPosPixel(), Size(nWidth, INFO_BAR_BASE_HEIGHT * fScaleFactor
- + aExtraHeight * fScaleFactor));
+ m_xImage.reset();
+ m_xPrimaryMessage.reset();
+ m_xSecondaryMessage.reset();
+ m_xButtonBox.reset();
+ m_xCloseBtn.reset();
+ m_aActionBtns.clear();
+ InterimItemWindow::dispose();
}
void SfxInfoBarWindow::Update(const OUString& sPrimaryMessage, const OUString& sSecondaryMessage,
@@ -357,16 +338,16 @@ void SfxInfoBarWindow::Update(const OUString& sPrimaryMessage, const OUString& s
{
m_eType = eType;
SetForeAndBackgroundColors(m_eType);
- m_pImage->SetImage(Image(StockImage::Yes, GetInfoBarIconName(eType)));
+ m_xImage->set_from_icon_name(GetInfoBarIconName(eType));
}
- m_pPrimaryMessage->SetText(sPrimaryMessage);
- m_pSecondaryMessage->SetText(sSecondaryMessage);
+ m_xPrimaryMessage->set_label(sPrimaryMessage);
+ m_xSecondaryMessage->set_text(sSecondaryMessage);
Resize();
Invalidate();
}
-IMPL_LINK_NOARG(SfxInfoBarWindow, CloseHandler, Button*, void)
+IMPL_LINK_NOARG(SfxInfoBarWindow, CloseHandler, const OString&, void)
{
static_cast<SfxInfoBarContainerWindow*>(GetParent())->removeInfoBar(this);
}
@@ -375,9 +356,15 @@ SfxInfoBarContainerWindow::SfxInfoBarContainerWindow(SfxInfoBarContainerChild* p
: Window(pChildWin->GetParent(), WB_DIALOGCONTROL)
, m_pChildWin(pChildWin)
, m_pInfoBars()
+ , m_bResizing(false)
{
+ m_aLayoutIdle.SetPriority(TaskPriority::HIGHEST);
+ m_aLayoutIdle.SetInvokeHandler(LINK(this, SfxInfoBarContainerWindow, DoUpdateLayout));
+ m_aLayoutIdle.SetDebugName("SfxInfoBarContainerWindow m_aLayoutIdle");
}
+IMPL_LINK_NOARG(SfxInfoBarContainerWindow, DoUpdateLayout, Timer*, void) { m_pChildWin->Update(); }
+
SfxInfoBarContainerWindow::~SfxInfoBarContainerWindow() { disposeOnce(); }
void SfxInfoBarContainerWindow::dispose()
@@ -388,16 +375,17 @@ void SfxInfoBarContainerWindow::dispose()
Window::dispose();
}
-VclPtr<SfxInfoBarWindow>
-SfxInfoBarContainerWindow::appendInfoBar(const OUString& sId, const OUString& sPrimaryMessage,
- const OUString& sSecondaryMessage, InfobarType ibType,
- WinBits nMessageStyle, bool bShowCloseButton)
+VclPtr<SfxInfoBarWindow> SfxInfoBarContainerWindow::appendInfoBar(const OUString& sId,
+ const OUString& sPrimaryMessage,
+ const OUString& sSecondaryMessage,
+ InfobarType ibType,
+ bool bShowCloseButton)
{
if (!isInfobarEnabled(sId))
return nullptr;
auto pInfoBar = VclPtr<SfxInfoBarWindow>::Create(this, sId, sPrimaryMessage, sSecondaryMessage,
- ibType, nMessageStyle, bShowCloseButton);
+ ibType, bShowCloseButton);
basegfx::BColor aBackgroundColor;
basegfx::BColor aForegroundColor;
@@ -436,8 +424,6 @@ void SfxInfoBarContainerWindow::removeInfoBar(VclPtr<SfxInfoBarWindow> const& pI
m_pInfoBars.erase(it);
}
- Resize();
-
m_pChildWin->Update();
}
@@ -457,25 +443,46 @@ bool SfxInfoBarContainerWindow::isInfobarEnabled(const OUString& sId)
return true;
}
+// This triggers the SfxFrame to re-layout its childwindows
+void SfxInfoBarContainerWindow::TriggerUpdateLayout() { m_aLayoutIdle.Start(); }
+
void SfxInfoBarContainerWindow::Resize()
{
- long nWidth = GetSizePixel().getWidth();
+ if (m_bResizing)
+ return;
+ m_bResizing = true;
+ const Size& rOrigSize = GetSizePixel();
+ auto nOrigWidth = rOrigSize.getWidth();
+ auto nOrigHeight = rOrigSize.getHeight();
+
long nHeight = 0;
for (auto& rxInfoBar : m_pInfoBars)
{
- Size aSize = rxInfoBar->GetSizePixel();
- aSize.setWidth(nWidth);
+ Size aOrigSize = rxInfoBar->GetSizePixel();
+ Size aSize(nOrigWidth, aOrigSize.Height());
+
Point aPos(0, nHeight);
+ // stage 1: provisionally size the infobar,
+ rxInfoBar->SetPosSizePixel(aPos, aSize);
+
+ // stage 2: perhaps allow height to stretch to fit
+ // the stage 1 width
+ aSize = rxInfoBar->DoLayout();
rxInfoBar->SetPosSizePixel(aPos, aSize);
- rxInfoBar->Resize();
rxInfoBar->Show();
// Stretch to fit the infobar(s)
nHeight += aSize.getHeight();
}
- SetSizePixel(Size(nWidth, nHeight));
+ if (nOrigHeight != nHeight)
+ {
+ SetSizePixel(Size(nOrigWidth, nHeight));
+ TriggerUpdateLayout();
+ }
+
+ m_bResizing = false;
}
SFX_IMPL_POS_CHILDWINDOW_WITHID(SfxInfoBarContainerChild, SID_INFOBAR, SFX_OBJECTBAR_OBJECT);
@@ -502,6 +509,15 @@ SfxChildWinInfo SfxInfoBarContainerChild::GetInfo() const
void SfxInfoBarContainerChild::Update()
{
+ // Layout to current width, this may change the height
+ if (vcl::Window* pChild = GetWindow())
+ {
+ Size aSize(pChild->GetSizePixel());
+ pChild->Resize();
+ if (aSize == pChild->GetSizePixel())
+ return;
+ }
+
// Refresh the frame to take the infobars container height change into account
const sal_uInt16 nId = GetChildWindowId();
SfxViewFrame* pVFrame = m_pBindings->GetDispatcher()->GetFrame();
diff --git a/sfx2/source/doc/objserv.cxx b/sfx2/source/doc/objserv.cxx
index 8ab9ea898e9a..47c25433ee51 100644
--- a/sfx2/source/doc/objserv.cxx
+++ b/sfx2/source/doc/objserv.cxx
@@ -1434,11 +1434,9 @@ void SfxObjectShell::GetState_Impl(SfxItemSet &rSet)
auto pInfoBar = pFrame->AppendInfoBar("signature", "", sMessage, aInfobarType);
if (pInfoBar == nullptr || pInfoBar->IsDisposed())
return;
- VclPtrInstance<PushButton> xBtn(&(pFrame->GetWindow()));
- xBtn->SetText(SfxResId(STR_SIGNATURE_SHOW));
- xBtn->SetSizePixel(xBtn->GetOptimalSize());
- xBtn->SetClickHdl(LINK(this, SfxObjectShell, SignDocumentHandler));
- pInfoBar->addButton(xBtn);
+ weld::Button& rBtn = pInfoBar->addButton();
+ rBtn.set_label(SfxResId(STR_SIGNATURE_SHOW));
+ rBtn.connect_clicked(LINK(this, SfxObjectShell, SignDocumentHandler));
}
}
else // info bar exists already
@@ -1475,7 +1473,7 @@ void SfxObjectShell::GetState_Impl(SfxItemSet &rSet)
}
}
-IMPL_LINK_NOARG(SfxObjectShell, SignDocumentHandler, Button*, void)
+IMPL_LINK_NOARG(SfxObjectShell, SignDocumentHandler, weld::Button&, void)
{
GetDispatcher()->Execute(SID_SIGNATURE);
}
diff --git a/sfx2/source/view/sfxbasecontroller.cxx b/sfx2/source/view/sfxbasecontroller.cxx
index a4706277e869..8f4ba77305db 100644
--- a/sfx2/source/view/sfxbasecontroller.cxx
+++ b/sfx2/source/view/sfxbasecontroller.cxx
@@ -1398,15 +1398,13 @@ void SfxBaseController::ShowInfoBars( )
InfobarType::WARNING);
if (pInfoBar)
{
- VclPtrInstance<PushButton> xBtn(&pViewFrame->GetWindow());
- xBtn->SetText(SfxResId(STR_CHECKOUT));
- xBtn->SetSizePixel(xBtn->GetOptimalSize());
- xBtn->SetClickHdl(LINK(this, SfxBaseController, CheckOutHandler));
- pInfoBar->addButton(xBtn);
+ weld::Button &rBtn = pInfoBar->addButton();
+ rBtn.set_label(SfxResId(STR_CHECKOUT));
+ rBtn.connect_clicked(LINK(this, SfxBaseController, CheckOutHandler));
}
}
-IMPL_LINK_NOARG ( SfxBaseController, CheckOutHandler, Button*, void )
+IMPL_LINK_NOARG ( SfxBaseController, CheckOutHandler, weld::Button&, void )
{
if ( m_pData->m_pViewShell )
m_pData->m_pViewShell->GetObjectShell()->CheckOut( );
@@ -1498,11 +1496,8 @@ void SAL_CALL SfxBaseController::appendInfobar(const OUString& sId, const OUStri
{
if (actionButton.First.isEmpty() || actionButton.Second.isEmpty())
continue;
- VclPtrInstance<PushButton> xBtn(&pViewFrame->GetWindow());
- xBtn->SetText(actionButton.First);
- xBtn->SetSizePixel(xBtn->GetOptimalSize());
- xBtn->SetCommandHandler(actionButton.Second);
- pInfoBar->addButton(xBtn);
+ weld::Button& rBtn = pInfoBar->addButton(&actionButton.Second);
+ rBtn.set_label(actionButton.First);
}
}
diff --git a/sfx2/source/view/viewfrm.cxx b/sfx2/source/view/viewfrm.cxx
index 9e4b4b280c59..ccb39350f223 100644
--- a/sfx2/source/view/viewfrm.cxx
+++ b/sfx2/source/view/viewfrm.cxx
@@ -1258,19 +1258,17 @@ void SfxViewFrame::AppendReadOnlyInfobar()
{
// SID_SIGNPDF opened a read-write PDF
// read-only for signing purposes.
- VclPtrInstance<PushButton> xSignButton(&GetWindow());
+ weld::Button& rSignButton = pInfoBar->addButton();
if (bSignWithCert)
{
- xSignButton->SetText(SfxResId(STR_READONLY_FINISH_SIGN));
+ rSignButton.set_label(SfxResId(STR_READONLY_FINISH_SIGN));
}
else
{
- xSignButton->SetText(SfxResId(STR_READONLY_SIGN));
+ rSignButton.set_label(SfxResId(STR_READONLY_SIGN));
}
- xSignButton->SetSizePixel(xSignButton->GetOptimalSize());
- xSignButton->SetClickHdl(LINK(this, SfxViewFrame, SignDocumentHandler));
- pInfoBar->addButton(xSignButton);
+ rSignButton.connect_clicked(LINK(this, SfxViewFrame, SignDocumentHandler));
}
bool showEditDocumentButton = true;
@@ -1279,11 +1277,9 @@ void SfxViewFrame::AppendReadOnlyInfobar()
if (showEditDocumentButton)
{
- VclPtrInstance<PushButton> xBtn(&GetWindow());
- xBtn->SetText(SfxResId(STR_READONLY_EDIT));
- xBtn->SetSizePixel(xBtn->GetOptimalSize());
- xBtn->SetClickHdl(LINK(this, SfxViewFrame, SwitchReadOnlyHandler));
- pInfoBar->addButton(xBtn);
+ weld::Button& rBtn = pInfoBar->addButton();
+ rBtn.set_label(SfxResId(STR_READONLY_EDIT));
+ rBtn.connect_clicked(LINK(this, SfxViewFrame, SwitchReadOnlyHandler));
}
}
@@ -1341,11 +1337,9 @@ void SfxViewFrame::Notify( SfxBroadcaster& /*rBC*/, const SfxHint& rHint )
VclPtr<SfxInfoBarWindow> pInfoBar = AppendInfoBar("whatsnew", "", SfxResId(STR_WHATSNEW_TEXT), InfobarType::INFO);
if (pInfoBar)
{
- VclPtrInstance<PushButton> xWhatsNewButton(&GetWindow());
- xWhatsNewButton->SetText(SfxResId(STR_WHATSNEW_BUTTON));
- xWhatsNewButton->SetSizePixel(xWhatsNewButton->GetOptimalSize());
- xWhatsNewButton->SetClickHdl(LINK(this, SfxViewFrame, WhatsNewHandler));
- pInfoBar->addButton(xWhatsNewButton);
+ weld::Button& rWhatsNewButton = pInfoBar->addButton();
+ rWhatsNewButton.set_label(SfxResId(STR_WHATSNEW_BUTTON));
+ rWhatsNewButton.connect_clicked(LINK(this, SfxViewFrame, WhatsNewHandler));
//update lastversion
std::shared_ptr<comphelper::ConfigurationChanges> batch(comphelper::ConfigurationChanges::create());
@@ -1384,11 +1378,9 @@ void SfxViewFrame::Notify( SfxBroadcaster& /*rBC*/, const SfxHint& rHint )
if (pInfoBar)
{
- VclPtrInstance<PushButton> xGetInvolvedButton(&GetWindow());
- xGetInvolvedButton->SetText(SfxResId(STR_GET_INVOLVED_BUTTON));
- xGetInvolvedButton->SetSizePixel(xGetInvolvedButton->GetOptimalSize());
- xGetInvolvedButton->SetClickHdl(LINK(this, SfxViewFrame, GetInvolvedHandler));
- pInfoBar->addButton(xGetInvolvedButton);
+ weld::Button& rGetInvolvedButton = pInfoBar->addButton();
+ rGetInvolvedButton.set_label(SfxResId(STR_GET_INVOLVED_BUTTON));
+ rGetInvolvedButton.connect_clicked(LINK(this, SfxViewFrame, GetInvolvedHandler));
}
}
@@ -1413,11 +1405,9 @@ void SfxViewFrame::Notify( SfxBroadcaster& /*rBC*/, const SfxHint& rHint )
VclPtr<SfxInfoBarWindow> pInfoBar = AppendInfoBar("donate", "", SfxResId(STR_DONATE_TEXT), InfobarType::INFO);
if (pInfoBar)
{
- VclPtrInstance<PushButton> xDonateButton(&GetWindow());
- xDonateButton->SetText(SfxResId(STR_DONATE_BUTTON));
- xDonateButton->SetSizePixel(xDonateButton->GetOptimalSize());
- xDonateButton->SetClickHdl(LINK(this, SfxViewFrame, DonationHandler));
- pInfoBar->addButton(xDonateButton);
+ weld::Button& rDonateButton = pInfoBar->addButton();
+ rDonateButton.set_label(SfxResId(STR_DONATE_BUTTON));
+ rDonateButton.connect_clicked(LINK(this, SfxViewFrame, DonationHandler));
}
}
@@ -1546,33 +1536,33 @@ void SfxViewFrame::Notify( SfxBroadcaster& /*rBC*/, const SfxHint& rHint )
}
}
-IMPL_LINK_NOARG(SfxViewFrame, WhatsNewHandler, Button*, void)
+IMPL_LINK_NOARG(SfxViewFrame, WhatsNewHandler, weld::Button&, void)
{
GetDispatcher()->Execute(SID_WHATSNEW);
}
-IMPL_LINK_NOARG(SfxViewFrame, GetInvolvedHandler, Button*, void)
+IMPL_LINK_NOARG(SfxViewFrame, GetInvolvedHandler, weld::Button&, void)
{
GetDispatcher()->Execute(SID_GETINVOLVED);
}
-IMPL_LINK_NOARG(SfxViewFrame, DonationHandler, Button*, void)
+IMPL_LINK_NOARG(SfxViewFrame, DonationHandler, weld::Button&, void)
{
GetDispatcher()->Execute(SID_DONATION);
}
-IMPL_LINK(SfxViewFrame, SwitchReadOnlyHandler, Button*, pButton, void)
+IMPL_LINK(SfxViewFrame, SwitchReadOnlyHandler, weld::Button&, rButton, void)
{
if (m_xObjSh.is() && m_xObjSh->IsSignPDF())
{
- SfxEditDocumentDialog aDialog(pButton->GetFrameWeld());
+ SfxEditDocumentDialog aDialog(&rButton);
if (aDialog.run() != RET_OK)
return;
}
GetDispatcher()->Execute(SID_EDITDOC);
}
-IMPL_LINK_NOARG(SfxViewFrame, SignDocumentHandler, Button*, void)
+IMPL_LINK_NOARG(SfxViewFrame, SignDocumentHandler, weld::Button&, void)
{
GetDispatcher()->Execute(SID_SIGNATURE);
}
@@ -3340,7 +3330,7 @@ VclPtr<SfxInfoBarWindow> SfxViewFrame::AppendInfoBar(const OUString& sId,
SfxInfoBarContainerWindow* pInfoBarContainer = static_cast<SfxInfoBarContainerWindow*>(pChild->GetWindow());
auto pInfoBar = pInfoBarContainer->appendInfoBar(sId, sPrimaryMessage, sSecondaryMessage,
- aInfobarType, WB_LEFT | WB_VCENTER, bShowCloseButton);
+ aInfobarType, bShowCloseButton);
ShowChildWindow(SfxInfoBarContainerChild::GetChildWindowId());
return pInfoBar;
}
diff --git a/sfx2/uiconfig/ui/extrabutton.ui b/sfx2/uiconfig/ui/extrabutton.ui
new file mode 100644
index 000000000000..69619f5d4ed0
--- /dev/null
+++ b/sfx2/uiconfig/ui/extrabutton.ui
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.36.0 -->
+<interface domain="svt">
+ <requires lib="gtk+" version="3.18"/>
+ <object class="GtkBox" id="ExtraButton">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkButton" id="button">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="receives_default">True</property>
+ <property name="always_show_image">True</property>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+</interface>
diff --git a/sfx2/uiconfig/ui/infobar.ui b/sfx2/uiconfig/ui/infobar.ui
new file mode 100644
index 000000000000..73fcd6b1122a
--- /dev/null
+++ b/sfx2/uiconfig/ui/infobar.ui
@@ -0,0 +1,187 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.36.0 -->
+<interface domain="svt">
+ <requires lib="gtk+" version="3.18"/>
+ <object class="GtkBox" id="InfoBar">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkScrolledWindow">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="hscrollbar_policy">never</property>
+ <property name="vscrollbar_policy">never</property>
+ <property name="shadow_type">in</property>
+ <child>
+ <object class="GtkViewport">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkGrid">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="border_width">2</property>
+ <property name="column_spacing">6</property>
+ <child>
+ <object class="GtkBox" id="right">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="valign">start</property>
+ <property name="spacing">3</property>
+ <child>
+ <object class="GtkBox" id="buttonbox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="valign">center</property>
+ <property name="spacing">6</property>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToolbar" id="closebar">
+ <property name="can_focus">False</property>
+ <property name="no_show_all">True</property>
+ <property name="valign">center</property>
+ <property name="toolbar_style">icons</property>
+ <property name="show_arrow">False</property>
+ <property name="icon_size">1</property>
+ <child>
+ <object class="GtkToolButton" id="close">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="tooltip_text" translatable="yes" context="infobar|close|tooltip_text">Close Infobar</property>
+ <property name="icon_name">sfx2/res/closedoc.png</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="homogeneous">True</property>
+ </packing>
+ </child>
+ <style>
+ <class name="small-button"/>
+ </style>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">2</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="left">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="valign">start</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkImage" id="image">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="valign">center</property>
+ <property name="stock">gtk-missing-image</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="primary">
+ <property name="can_focus">False</property>
+ <property name="no_show_all">True</property>
+ <property name="valign">center</property>
+ <property name="vexpand">True</property>
+ <property name="label">label</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="primary-atkobject">
+ <property name="AtkObject::accessible-role">static</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkScrolledWindow">
+ <property name="width_request">60</property>
+ <property name="height_request">6</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="hscrollbar_policy">never</property>
+ <property name="vscrollbar_policy">never</property>
+ <child>
+ <object class="GtkTextView" id="secondary">
+ <property name="width_request">60</property>
+ <property name="height_request">6</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="editable">False</property>
+ <property name="wrap_mode">word-char</property>
+ <property name="cursor_visible">False</property>
+ <property name="accepts_tab">False</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ <object class="GtkSizeGroup" id="sizegroup1">
+ <property name="mode">vertical</property>
+ <widgets>
+ <widget name="right"/>
+ <widget name="left"/>
+ </widgets>
+ </object>
+</interface>
diff --git a/solenv/sanitizers/ui/sfx.suppr b/solenv/sanitizers/ui/sfx.suppr
index b34b687c0128..4edcdb02a842 100644
--- a/solenv/sanitizers/ui/sfx.suppr
+++ b/solenv/sanitizers/ui/sfx.suppr
@@ -22,6 +22,7 @@ sfx2/uiconfig/ui/documentinfopage.ui://GtkLabel[@id='showtype'] orphan-label
sfx2/uiconfig/ui/documentinfopage.ui://GtkLabel[@id='showtemplate'] orphan-label
sfx2/uiconfig/ui/documentinfopage.ui://GtkImage[@id='icon'] no-labelled-by
sfx2/uiconfig/ui/documentinfopage.ui://GtkLabel[@id='nameed'] orphan-label
+sfx2/uiconfig/ui/extrabutton.ui://GtkButton[@id='button'] button-no-label
sfx2/uiconfig/ui/helpindexpage.ui://GtkEntry[@id='termentry'] no-labelled-by
sfx2/uiconfig/ui/helpwindow.ui://GtkCheckButton[@id='checkbutton'] button-no-label
sfx2/uiconfig/ui/helpwindow.ui://GtkToolButton[@id='index'] button-no-label
diff --git a/vcl/source/app/weldutils.cxx b/vcl/source/app/weldutils.cxx
index ee074df63d93..237645076330 100644
--- a/vcl/source/app/weldutils.cxx
+++ b/vcl/source/app/weldutils.cxx
@@ -7,6 +7,9 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
+#include <com/sun/star/util/URLTransformer.hpp>
+#include <com/sun/star/frame/Desktop.hpp>
+#include <comphelper/processfactory.hxx>
#include <svl/zforlist.hxx>
#include <svl/zformat.hxx>
#include <vcl/builderpage.hxx>
@@ -488,6 +491,61 @@ int GetMinimumEditHeight()
std::unique_ptr<weld::Entry> xEntry(xBuilder->weld_entry("name_entry"));
return xEntry->get_preferred_size().Height();
}
+
+WidgetStatusListener::WidgetStatusListener(weld::Widget* widget, const OUString& aCommand)
+ : mWidget(widget)
+{
+ css::uno::Reference<css::uno::XComponentContext> xContext
+ = ::comphelper::getProcessComponentContext();
+ css::uno::Reference<css::frame::XDesktop2> xDesktop = css::frame::Desktop::create(xContext);
+
+ css::uno::Reference<css::frame::XFrame> xFrame(xDesktop->getActiveFrame());
+ if (!xFrame.is())
+ xFrame = xDesktop;
+
+ mxFrame = xFrame;
+
+ maCommandURL.Complete = aCommand;
+ css::uno::Reference<css::util::XURLTransformer> xParser
+ = css::util::URLTransformer::create(xContext);
+ xParser->parseStrict(maCommandURL);
+}
+
+void WidgetStatusListener::startListening()
+{
+ if (mxDispatch.is())
+ mxDispatch->removeStatusListener(this, maCommandURL);
+
+ css::uno::Reference<css::frame::XDispatchProvider> xDispatchProvider(mxFrame,
+ css::uno::UNO_QUERY);
+ if (!xDispatchProvider.is())
+ return;
+
+ mxDispatch = xDispatchProvider->queryDispatch(maCommandURL, "", 0);
+ if (mxDispatch.is())
+ mxDispatch->addStatusListener(this, maCommandURL);
+}
+
+void WidgetStatusListener::statusChanged(const css::frame::FeatureStateEvent& rEvent)
+{
+ mWidget->set_sensitive(rEvent.IsEnabled);
+}
+
+void WidgetStatusListener::disposing(const css::lang::EventObject& /*Source*/)
+{
+ mxDispatch.clear();
+}
+
+void WidgetStatusListener::dispose()
+{
+ if (mxDispatch.is())
+ {
+ mxDispatch->removeStatusListener(this, maCommandURL);
+ mxDispatch.clear();
+ }
+ mxFrame.clear();
+ mWidget = nullptr;
+}
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */