Added wxNonOwnedWindow::SetShape(wxGraphicsPath).
TODO: Document. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@69462 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
		@@ -39,7 +39,6 @@ class WXDLLIMPEXP_FWD_CORE wxToolBar;
 | 
			
		||||
#define wxFRAME_NO_TASKBAR      0x0002  // No taskbar button (MSW only)
 | 
			
		||||
#define wxFRAME_TOOL_WINDOW     0x0004  // No taskbar button, no system menu
 | 
			
		||||
#define wxFRAME_FLOAT_ON_PARENT 0x0008  // Always above its parent
 | 
			
		||||
#define wxFRAME_SHAPED          0x0010  // Create a window that is able to be shaped
 | 
			
		||||
 | 
			
		||||
// ----------------------------------------------------------------------------
 | 
			
		||||
// wxFrame is a top-level window with optional menubar, statusbar and toolbar
 | 
			
		||||
 
 | 
			
		||||
@@ -11,6 +11,8 @@
 | 
			
		||||
#ifndef _WX_GTK_NONOWNEDWND_H_
 | 
			
		||||
#define _WX_GTK_NONOWNEDWND_H_
 | 
			
		||||
 | 
			
		||||
class wxNonOwnedWindowShapeImpl;
 | 
			
		||||
 | 
			
		||||
// ----------------------------------------------------------------------------
 | 
			
		||||
// wxNonOwnedWindow contains code common to wx{Popup,TopLevel}Window in wxGTK.
 | 
			
		||||
// ----------------------------------------------------------------------------
 | 
			
		||||
@@ -18,16 +20,23 @@
 | 
			
		||||
class WXDLLIMPEXP_CORE wxNonOwnedWindow : public wxNonOwnedWindowBase
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
    wxNonOwnedWindow() { }
 | 
			
		||||
 | 
			
		||||
    virtual bool SetShape(const wxRegion& region);
 | 
			
		||||
    wxNonOwnedWindow() { m_shapeImpl = NULL; }
 | 
			
		||||
    virtual ~wxNonOwnedWindow();
 | 
			
		||||
 | 
			
		||||
    // Overridden to actually set the shape when the window becomes realized.
 | 
			
		||||
    virtual void GTKHandleRealized();
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
    virtual bool DoClearShape();
 | 
			
		||||
    virtual bool DoSetRegionShape(const wxRegion& region);
 | 
			
		||||
#if wxUSE_GRAPHICS_CONTEXT
 | 
			
		||||
    virtual bool DoSetPathShape(const wxGraphicsPath& path);
 | 
			
		||||
#endif // wxUSE_GRAPHICS_CONTEXT
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    // If valid, defines the custom shape of the window.
 | 
			
		||||
    wxRegion m_shape;
 | 
			
		||||
    // If non-NULL, contains information about custom window shape.
 | 
			
		||||
    wxNonOwnedWindowShapeImpl* m_shapeImpl;
 | 
			
		||||
 | 
			
		||||
    wxDECLARE_NO_COPY_CLASS(wxNonOwnedWindow);
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
@@ -11,6 +11,8 @@
 | 
			
		||||
#ifndef _WX_MSW_NONOWNEDWND_H_
 | 
			
		||||
#define _WX_MSW_NONOWNEDWND_H_
 | 
			
		||||
 | 
			
		||||
class wxNonOwnedWindowShapeImpl;
 | 
			
		||||
 | 
			
		||||
// ----------------------------------------------------------------------------
 | 
			
		||||
// wxNonOwnedWindow
 | 
			
		||||
// ----------------------------------------------------------------------------
 | 
			
		||||
@@ -18,7 +20,20 @@
 | 
			
		||||
class WXDLLIMPEXP_CORE wxNonOwnedWindow : public wxNonOwnedWindowBase
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
    virtual bool SetShape(const wxRegion& region);
 | 
			
		||||
    wxNonOwnedWindow();
 | 
			
		||||
    virtual ~wxNonOwnedWindow();
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
    virtual bool DoClearShape();
 | 
			
		||||
    virtual bool DoSetRegionShape(const wxRegion& region);
 | 
			
		||||
#if wxUSE_GRAPHICS_CONTEXT
 | 
			
		||||
    virtual bool DoSetPathShape(const wxGraphicsPath& path);
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    wxNonOwnedWindowShapeImpl* m_shapeImpl;
 | 
			
		||||
#endif // wxUSE_GRAPHICS_CONTEXT
 | 
			
		||||
 | 
			
		||||
    wxDECLARE_NO_COPY_CLASS(wxNonOwnedWindow);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif // _WX_MSW_NONOWNEDWND_H_
 | 
			
		||||
 
 | 
			
		||||
@@ -14,6 +14,11 @@
 | 
			
		||||
 | 
			
		||||
#include "wx/window.h"
 | 
			
		||||
 | 
			
		||||
// Styles that can be used with any wxNonOwnedWindow:
 | 
			
		||||
#define wxFRAME_SHAPED          0x0010  // Create a window that is able to be shaped
 | 
			
		||||
 | 
			
		||||
class WXDLLIMPEXP_FWD_CORE wxGraphicsPath;
 | 
			
		||||
 | 
			
		||||
// ----------------------------------------------------------------------------
 | 
			
		||||
// wxNonOwnedWindow: a window that is not a child window of another one.
 | 
			
		||||
// ----------------------------------------------------------------------------
 | 
			
		||||
@@ -24,8 +29,52 @@ public:
 | 
			
		||||
    // Set the shape of the window to the given region.
 | 
			
		||||
    // Returns true if the platform supports this feature (and the
 | 
			
		||||
    // operation is successful.)
 | 
			
		||||
    virtual bool SetShape(const wxRegion& WXUNUSED(region)) { return false; }
 | 
			
		||||
    bool SetShape(const wxRegion& region)
 | 
			
		||||
    {
 | 
			
		||||
        // This style is in fact only needed by wxOSX/Carbon so once we don't
 | 
			
		||||
        // use this port any more, we could get rid of this requirement, but
 | 
			
		||||
        // for now you must specify wxFRAME_SHAPED for SetShape() to work on
 | 
			
		||||
        // all platforms.
 | 
			
		||||
        wxCHECK_MSG
 | 
			
		||||
        (
 | 
			
		||||
            HasFlag(wxFRAME_SHAPED), false,
 | 
			
		||||
            wxS("Shaped windows must be created with the wxFRAME_SHAPED style.")
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        return region.IsEmpty() ? DoClearShape() : DoSetRegionShape(region);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
#if wxUSE_GRAPHICS_CONTEXT
 | 
			
		||||
    // Set the shape using the specified path.
 | 
			
		||||
    bool SetShape(const wxGraphicsPath& path)
 | 
			
		||||
    {
 | 
			
		||||
        wxCHECK_MSG
 | 
			
		||||
        (
 | 
			
		||||
            HasFlag(wxFRAME_SHAPED), false,
 | 
			
		||||
            wxS("Shaped windows must be created with the wxFRAME_SHAPED style.")
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        return DoSetPathShape(path);
 | 
			
		||||
    }
 | 
			
		||||
#endif // wxUSE_GRAPHICS_CONTEXT
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
    virtual bool DoClearShape()
 | 
			
		||||
    {
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    virtual bool DoSetRegionShape(const wxRegion& WXUNUSED(region))
 | 
			
		||||
    {
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
#if wxUSE_GRAPHICS_CONTEXT
 | 
			
		||||
    virtual bool DoSetPathShape(const wxGraphicsPath& WXUNUSED(path))
 | 
			
		||||
    {
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
#endif // wxUSE_GRAPHICS_CONTEXT
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#if defined(__WXDFB__)
 | 
			
		||||
 
 | 
			
		||||
@@ -14,6 +14,8 @@
 | 
			
		||||
 | 
			
		||||
#include "wx/window.h"
 | 
			
		||||
 | 
			
		||||
#include "wx/graphics.h"
 | 
			
		||||
 | 
			
		||||
#if wxUSE_SYSTEM_OPTIONS
 | 
			
		||||
    #define wxMAC_WINDOW_PLAIN_TRANSITION wxT("mac.window-plain-transition")
 | 
			
		||||
#endif
 | 
			
		||||
@@ -82,6 +84,10 @@ public:
 | 
			
		||||
    virtual bool SetShape(const wxRegion& region);
 | 
			
		||||
    const wxRegion& GetShape() const { return m_shape; }
 | 
			
		||||
 | 
			
		||||
#if wxUSE_GRAPHICS_CONTEXT
 | 
			
		||||
    const wxGraphicsPath& GetShapePath() { return m_shapePath; }
 | 
			
		||||
#endif // wxUSE_GRAPHICS_CONTEXT
 | 
			
		||||
 | 
			
		||||
    // activation hooks only necessary for MDI Implementation
 | 
			
		||||
    static void MacDelayedDeactivation(long timestamp);
 | 
			
		||||
    virtual void MacActivate( long timestamp , bool inIsActivating ) ;
 | 
			
		||||
@@ -125,6 +131,12 @@ protected:
 | 
			
		||||
                                   wxShowEffect effect,
 | 
			
		||||
                                   unsigned timeout);
 | 
			
		||||
 | 
			
		||||
    virtual bool DoClearShape();
 | 
			
		||||
    virtual bool DoSetRegionShape(const wxRegion& region);
 | 
			
		||||
#if wxUSE_GRAPHICS_CONTEXT
 | 
			
		||||
    virtual bool DoSetPathShape(const wxGraphicsPath& path);
 | 
			
		||||
#endif // wxUSE_GRAPHICS_CONTEXT
 | 
			
		||||
 | 
			
		||||
    virtual void WillBeDestroyed();
 | 
			
		||||
 | 
			
		||||
    wxNonOwnedWindowImpl* m_nowpeer ;
 | 
			
		||||
@@ -135,6 +147,9 @@ protected:
 | 
			
		||||
 | 
			
		||||
private :
 | 
			
		||||
    wxRegion m_shape;
 | 
			
		||||
#if wxUSE_GRAPHICS_CONTEXT
 | 
			
		||||
    wxGraphicsPath m_shapePath;
 | 
			
		||||
#endif // wxUSE_GRAPHICS_CONTEXT
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// list of all frames and modeless dialogs
 | 
			
		||||
 
 | 
			
		||||
@@ -24,7 +24,6 @@
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifndef WX_PRECOMP
 | 
			
		||||
    #include "wx/frame.h"           // Just for wxFRAME_SHAPED.
 | 
			
		||||
    #include "wx/nonownedwnd.h"
 | 
			
		||||
    #include "wx/region.h"
 | 
			
		||||
#endif // WX_PRECOMP
 | 
			
		||||
@@ -33,61 +32,275 @@
 | 
			
		||||
 | 
			
		||||
#include <gdk/gdk.h>
 | 
			
		||||
 | 
			
		||||
namespace
 | 
			
		||||
{
 | 
			
		||||
#include "wx/graphics.h"
 | 
			
		||||
 | 
			
		||||
// helper
 | 
			
		||||
bool do_shape_combine_region(GdkWindow* window, const wxRegion& region)
 | 
			
		||||
// ----------------------------------------------------------------------------
 | 
			
		||||
// wxNonOwnedWindowShapeImpl: base class for region and path-based classes.
 | 
			
		||||
// ----------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
// This class provides behaviour common to both region and path-based
 | 
			
		||||
// implementations and defines SetShape() method and virtual dtor that can be
 | 
			
		||||
// called by wxNonOwnedWindow when it's realized leaving just the
 | 
			
		||||
// implementation of DoSetShape() to the derived classes.
 | 
			
		||||
class wxNonOwnedWindowShapeImpl : public wxEvtHandler
 | 
			
		||||
{
 | 
			
		||||
    if (window)
 | 
			
		||||
public:
 | 
			
		||||
    wxNonOwnedWindowShapeImpl(wxWindow* win) : m_win(win)
 | 
			
		||||
    {
 | 
			
		||||
        if (region.IsEmpty())
 | 
			
		||||
        {
 | 
			
		||||
            gdk_window_shape_combine_mask(window, NULL, 0, 0);
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            gdk_window_shape_combine_region(window, region.GetRegion(), 0, 0);
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} // anonymous namespace
 | 
			
		||||
    virtual ~wxNonOwnedWindowShapeImpl() { }
 | 
			
		||||
 | 
			
		||||
    bool SetShape()
 | 
			
		||||
    {
 | 
			
		||||
        if ( m_win->m_wxwindow )
 | 
			
		||||
            SetShapeIfNonNull(gtk_widget_get_window(m_win->m_wxwindow));
 | 
			
		||||
 | 
			
		||||
        return SetShapeIfNonNull(gtk_widget_get_window(m_win->m_widget));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Must be overridden to indicate if the data object must stay around or if
 | 
			
		||||
    // it can be deleted once SetShape() was called.
 | 
			
		||||
    virtual bool CanBeDeleted() const = 0;
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
    wxWindow* const m_win;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    // SetShape to the given GDK window by calling DoSetShape() if it's non-NULL.
 | 
			
		||||
    bool SetShapeIfNonNull(GdkWindow* window)
 | 
			
		||||
    {
 | 
			
		||||
        return window && DoSetShape(window);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // SetShape the shape to the given GDK window which can be either the window
 | 
			
		||||
    // of m_widget or m_wxwindow of the wxWindow we're used with.
 | 
			
		||||
    virtual bool DoSetShape(GdkWindow* window) = 0;
 | 
			
		||||
 | 
			
		||||
    wxDECLARE_NO_COPY_CLASS(wxNonOwnedWindowShapeImpl);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// Version not using any custom shape.
 | 
			
		||||
class wxNonOwnedWindowShapeImplNone : public wxNonOwnedWindowShapeImpl
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
    wxNonOwnedWindowShapeImplNone(wxWindow* win) :
 | 
			
		||||
        wxNonOwnedWindowShapeImpl(win)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    virtual bool CanBeDeleted() const { return true; }
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    virtual bool DoSetShape(GdkWindow* window)
 | 
			
		||||
    {
 | 
			
		||||
        gdk_window_shape_combine_mask(window, NULL, 0, 0);
 | 
			
		||||
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// Version using simple wxRegion.
 | 
			
		||||
class wxNonOwnedWindowShapeImplRegion : public wxNonOwnedWindowShapeImpl
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
    wxNonOwnedWindowShapeImplRegion(wxWindow* win, const wxRegion& region) :
 | 
			
		||||
        wxNonOwnedWindowShapeImpl(win),
 | 
			
		||||
        m_region(region)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    virtual bool CanBeDeleted() const { return true; }
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    virtual bool DoSetShape(GdkWindow* window)
 | 
			
		||||
    {
 | 
			
		||||
        gdk_window_shape_combine_region(window, m_region.GetRegion(), 0, 0);
 | 
			
		||||
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    wxRegion m_region;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#if wxUSE_GRAPHICS_CONTEXT
 | 
			
		||||
 | 
			
		||||
// Version using more complex wxGraphicsPath.
 | 
			
		||||
class wxNonOwnedWindowShapeImplPath : public wxNonOwnedWindowShapeImpl
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
    wxNonOwnedWindowShapeImplPath(wxWindow* win, const wxGraphicsPath& path) :
 | 
			
		||||
        wxNonOwnedWindowShapeImpl(win),
 | 
			
		||||
        m_path(path),
 | 
			
		||||
        m_mask(CreateShapeBitmap(path), *wxBLACK)
 | 
			
		||||
    {
 | 
			
		||||
 | 
			
		||||
        m_win->Connect
 | 
			
		||||
               (
 | 
			
		||||
                wxEVT_PAINT,
 | 
			
		||||
                wxPaintEventHandler(wxNonOwnedWindowShapeImplPath::OnPaint),
 | 
			
		||||
                NULL,
 | 
			
		||||
                this
 | 
			
		||||
               );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    virtual ~wxNonOwnedWindowShapeImplPath()
 | 
			
		||||
    {
 | 
			
		||||
        m_win->Disconnect
 | 
			
		||||
               (
 | 
			
		||||
                wxEVT_PAINT,
 | 
			
		||||
                wxPaintEventHandler(wxNonOwnedWindowShapeImplPath::OnPaint),
 | 
			
		||||
                NULL,
 | 
			
		||||
                this
 | 
			
		||||
               );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Currently we always return false from here, if drawing the border
 | 
			
		||||
    // becomes optional, we could return true if we don't need to draw it.
 | 
			
		||||
    virtual bool CanBeDeleted() const { return false; }
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    wxBitmap CreateShapeBitmap(const wxGraphicsPath& path)
 | 
			
		||||
    {
 | 
			
		||||
        // Draw the path on a bitmap to get the mask we need.
 | 
			
		||||
        //
 | 
			
		||||
        // Notice that using monochrome bitmap here doesn't work because of an
 | 
			
		||||
        // apparent wxGraphicsContext bug in wxGTK, so use a bitmap of screen
 | 
			
		||||
        // depth even if this is wasteful.
 | 
			
		||||
        wxBitmap bmp(m_win->GetSize());
 | 
			
		||||
 | 
			
		||||
        wxMemoryDC dc(bmp);
 | 
			
		||||
 | 
			
		||||
        dc.SetBackground(*wxBLACK);
 | 
			
		||||
        dc.Clear();
 | 
			
		||||
 | 
			
		||||
        wxScopedPtr<wxGraphicsContext> context(wxGraphicsContext::Create(dc));
 | 
			
		||||
        context->SetBrush(*wxWHITE);
 | 
			
		||||
        context->FillPath(path);
 | 
			
		||||
 | 
			
		||||
        return bmp;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    virtual bool DoSetShape(GdkWindow *window)
 | 
			
		||||
    {
 | 
			
		||||
        GdkBitmap* bitmap = m_mask.GetBitmap();
 | 
			
		||||
        if ( !bitmap )
 | 
			
		||||
            return false;
 | 
			
		||||
 | 
			
		||||
        gdk_window_shape_combine_mask(window, bitmap, 0, 0);
 | 
			
		||||
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Draw a shaped window border.
 | 
			
		||||
    void OnPaint(wxPaintEvent& event)
 | 
			
		||||
    {
 | 
			
		||||
        event.Skip();
 | 
			
		||||
 | 
			
		||||
        wxPaintDC dc(m_win);
 | 
			
		||||
        wxScopedPtr<wxGraphicsContext> context(wxGraphicsContext::Create(dc));
 | 
			
		||||
        context->SetPen(wxPen(*wxLIGHT_GREY, 2));
 | 
			
		||||
        context->StrokePath(m_path);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    wxGraphicsPath m_path;
 | 
			
		||||
    wxMask m_mask;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif // wxUSE_GRAPHICS_CONTEXT
 | 
			
		||||
 | 
			
		||||
// ============================================================================
 | 
			
		||||
// wxNonOwnedWindow implementation
 | 
			
		||||
// ============================================================================
 | 
			
		||||
 | 
			
		||||
wxNonOwnedWindow::~wxNonOwnedWindow()
 | 
			
		||||
{
 | 
			
		||||
    delete m_shapeImpl;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void wxNonOwnedWindow::GTKHandleRealized()
 | 
			
		||||
{
 | 
			
		||||
    wxNonOwnedWindowBase::GTKHandleRealized();
 | 
			
		||||
 | 
			
		||||
    if (HasFlag(wxFRAME_SHAPED))
 | 
			
		||||
        SetShape(m_shape);
 | 
			
		||||
    if ( m_shapeImpl )
 | 
			
		||||
    {
 | 
			
		||||
        m_shapeImpl->SetShape();
 | 
			
		||||
 | 
			
		||||
        // We can destroy wxNonOwnedWindowShapeImplRegion immediately but need
 | 
			
		||||
        // to keep wxNonOwnedWindowShapeImplPath around as it draws the border
 | 
			
		||||
        // on every repaint.
 | 
			
		||||
        if ( m_shapeImpl->CanBeDeleted() )
 | 
			
		||||
        {
 | 
			
		||||
            delete m_shapeImpl;
 | 
			
		||||
            m_shapeImpl = NULL;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool wxNonOwnedWindow::SetShape(const wxRegion& region)
 | 
			
		||||
bool wxNonOwnedWindow::DoClearShape()
 | 
			
		||||
{
 | 
			
		||||
    wxCHECK_MSG( HasFlag(wxFRAME_SHAPED), false,
 | 
			
		||||
                 wxT("Shaped windows must be created with the wxFRAME_SHAPED style."));
 | 
			
		||||
    if ( !m_shapeImpl )
 | 
			
		||||
    {
 | 
			
		||||
        // Nothing to do, we don't have any custom shape.
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if ( gtk_widget_get_realized(m_widget) )
 | 
			
		||||
    {
 | 
			
		||||
        if ( m_wxwindow )
 | 
			
		||||
            do_shape_combine_region(gtk_widget_get_window(m_wxwindow), region);
 | 
			
		||||
 | 
			
		||||
        return do_shape_combine_region(gtk_widget_get_window(m_widget), region);
 | 
			
		||||
        // Reset the existing shape immediately.
 | 
			
		||||
        wxNonOwnedWindowShapeImplNone data(this);
 | 
			
		||||
        data.SetShape();
 | 
			
		||||
    }
 | 
			
		||||
    else // not realized yet
 | 
			
		||||
    {
 | 
			
		||||
        // store the shape to set, it will be really set once we're realized
 | 
			
		||||
        m_shape = region;
 | 
			
		||||
    //else: just do nothing, deleting m_shapeImpl is enough to ensure that we
 | 
			
		||||
    // don't set the custom shape later when we're realized.
 | 
			
		||||
 | 
			
		||||
        // we don't know if we're going to succeed or fail, be optimistic by
 | 
			
		||||
        // default
 | 
			
		||||
    delete m_shapeImpl;
 | 
			
		||||
    m_shapeImpl = NULL;
 | 
			
		||||
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool wxNonOwnedWindow::DoSetRegionShape(const wxRegion& region)
 | 
			
		||||
{
 | 
			
		||||
    // In any case get rid of the old data.
 | 
			
		||||
    delete m_shapeImpl;
 | 
			
		||||
    m_shapeImpl = NULL;
 | 
			
		||||
 | 
			
		||||
    if ( gtk_widget_get_realized(m_widget) )
 | 
			
		||||
    {
 | 
			
		||||
        // We can avoid an unnecessary heap allocation and just set the shape
 | 
			
		||||
        // immediately.
 | 
			
		||||
        wxNonOwnedWindowShapeImplRegion data(this, region);
 | 
			
		||||
        return data.SetShape();
 | 
			
		||||
    }
 | 
			
		||||
    else // Create an object that will set shape when we're realized.
 | 
			
		||||
    {
 | 
			
		||||
        m_shapeImpl = new wxNonOwnedWindowShapeImplRegion(this, region);
 | 
			
		||||
 | 
			
		||||
        // In general we don't know whether we are going to succeed or not, so
 | 
			
		||||
        // be optimistic.
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if wxUSE_GRAPHICS_CONTEXT
 | 
			
		||||
 | 
			
		||||
bool wxNonOwnedWindow::DoSetPathShape(const wxGraphicsPath& path)
 | 
			
		||||
{
 | 
			
		||||
    // The logic here is simpler than above because we always create
 | 
			
		||||
    // wxNonOwnedWindowShapeImplPath on the heap as we must keep it around,
 | 
			
		||||
    // even if we're already realized
 | 
			
		||||
 | 
			
		||||
    delete m_shapeImpl;
 | 
			
		||||
    m_shapeImpl = new wxNonOwnedWindowShapeImplPath(this, path);
 | 
			
		||||
 | 
			
		||||
    if ( gtk_widget_get_realized(m_widget) )
 | 
			
		||||
    {
 | 
			
		||||
        return m_shapeImpl->SetShape();
 | 
			
		||||
    }
 | 
			
		||||
    //else: will be done later from GTKHandleRealized().
 | 
			
		||||
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif // wxUSE_GRAPHICS_CONTEXT
 | 
			
		||||
 
 | 
			
		||||
@@ -34,27 +34,27 @@
 | 
			
		||||
 | 
			
		||||
#include "wx/nonownedwnd.h"
 | 
			
		||||
 | 
			
		||||
#include "wx/msw/wrapgdip.h"
 | 
			
		||||
#include "wx/graphics.h"
 | 
			
		||||
#include "wx/scopedptr.h"
 | 
			
		||||
 | 
			
		||||
// ============================================================================
 | 
			
		||||
// wxNonOwnedWindow implementation
 | 
			
		||||
// ============================================================================
 | 
			
		||||
 | 
			
		||||
bool wxNonOwnedWindow::SetShape(const wxRegion& region)
 | 
			
		||||
bool wxNonOwnedWindow::DoClearShape()
 | 
			
		||||
{
 | 
			
		||||
    wxCHECK_MSG( HasFlag(wxFRAME_SHAPED), false,
 | 
			
		||||
                 wxT("Shaped windows must be created with the wxFRAME_SHAPED style."));
 | 
			
		||||
 | 
			
		||||
    // The empty region signifies that the shape should be removed from the
 | 
			
		||||
    // window.
 | 
			
		||||
    if ( region.IsEmpty() )
 | 
			
		||||
    if (::SetWindowRgn(GetHwnd(), NULL, TRUE) == 0)
 | 
			
		||||
    {
 | 
			
		||||
        if (::SetWindowRgn(GetHwnd(), NULL, TRUE) == 0)
 | 
			
		||||
        {
 | 
			
		||||
            wxLogLastError(wxT("SetWindowRgn"));
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
        return true;
 | 
			
		||||
        wxLogLastError(wxT("SetWindowRgn"));
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool wxNonOwnedWindow::DoSetRegionShape(const wxRegion& region)
 | 
			
		||||
{
 | 
			
		||||
    // Windows takes ownership of the region, so
 | 
			
		||||
    // we'll have to make a copy of the region to give to it.
 | 
			
		||||
    DWORD noBytes = ::GetRegionData(GetHrgnOf(region), 0, NULL);
 | 
			
		||||
@@ -77,4 +77,104 @@ bool wxNonOwnedWindow::SetShape(const wxRegion& region)
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if wxUSE_GRAPHICS_CONTEXT
 | 
			
		||||
 | 
			
		||||
#include "wx/msw/wrapgdip.h"
 | 
			
		||||
 | 
			
		||||
// This class contains data used only when SetPath(wxGraphicsPath) is called.
 | 
			
		||||
//
 | 
			
		||||
// Notice that it derives from wxEvtHandler solely to allow Connect()-ing its
 | 
			
		||||
// OnPaint() method to the window, we could get rid of this inheritance once
 | 
			
		||||
// Bind() can be used in wx sources.
 | 
			
		||||
class wxNonOwnedWindowShapeImpl : public wxEvtHandler
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
    wxNonOwnedWindowShapeImpl(wxNonOwnedWindow* win, const wxGraphicsPath& path) :
 | 
			
		||||
        m_win(win),
 | 
			
		||||
        m_path(path)
 | 
			
		||||
    {
 | 
			
		||||
        // Create the region corresponding to this path and set it as windows
 | 
			
		||||
        // shape.
 | 
			
		||||
        wxScopedPtr<wxGraphicsContext> context(wxGraphicsContext::Create(win));
 | 
			
		||||
        Region gr(static_cast<GraphicsPath*>(m_path.GetNativePath()));
 | 
			
		||||
        win->SetShape(
 | 
			
		||||
            wxRegion(
 | 
			
		||||
                gr.GetHRGN(static_cast<Graphics*>(context->GetNativeContext()))
 | 
			
		||||
            )
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        // Connect to the paint event to draw the border.
 | 
			
		||||
        //
 | 
			
		||||
        // TODO: Do this only optionally?
 | 
			
		||||
        m_win->Connect
 | 
			
		||||
               (
 | 
			
		||||
                wxEVT_PAINT,
 | 
			
		||||
                wxPaintEventHandler(wxNonOwnedWindowShapeImpl::OnPaint),
 | 
			
		||||
                NULL,
 | 
			
		||||
                this
 | 
			
		||||
               );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    virtual ~wxNonOwnedWindowShapeImpl()
 | 
			
		||||
    {
 | 
			
		||||
        m_win->Disconnect
 | 
			
		||||
               (
 | 
			
		||||
                wxEVT_PAINT,
 | 
			
		||||
                wxPaintEventHandler(wxNonOwnedWindowShapeImpl::OnPaint),
 | 
			
		||||
                NULL,
 | 
			
		||||
                this
 | 
			
		||||
               );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    void OnPaint(wxPaintEvent& event)
 | 
			
		||||
    {
 | 
			
		||||
        event.Skip();
 | 
			
		||||
 | 
			
		||||
        wxPaintDC dc(m_win);
 | 
			
		||||
        wxScopedPtr<wxGraphicsContext> context(wxGraphicsContext::Create(dc));
 | 
			
		||||
        context->SetPen(wxPen(*wxLIGHT_GREY, 2));
 | 
			
		||||
        context->StrokePath(m_path);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    wxNonOwnedWindow* const m_win;
 | 
			
		||||
    wxGraphicsPath m_path;
 | 
			
		||||
 | 
			
		||||
    wxDECLARE_NO_COPY_CLASS(wxNonOwnedWindowShapeImpl);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
wxNonOwnedWindow::wxNonOwnedWindow()
 | 
			
		||||
{
 | 
			
		||||
    m_shapeImpl = NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
wxNonOwnedWindow::~wxNonOwnedWindow()
 | 
			
		||||
{
 | 
			
		||||
    delete m_shapeImpl;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool wxNonOwnedWindow::DoSetPathShape(const wxGraphicsPath& path)
 | 
			
		||||
{
 | 
			
		||||
    delete m_shapeImpl;
 | 
			
		||||
    m_shapeImpl = new wxNonOwnedWindowShapeImpl(this, path);
 | 
			
		||||
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#else // !wxUSE_GRAPHICS_CONTEXT
 | 
			
		||||
 | 
			
		||||
// Trivial ctor and dtor as we don't have anything to do when wxGraphicsContext
 | 
			
		||||
// is not used but still define them here to avoid adding even more #if checks
 | 
			
		||||
// to the header, it it doesn't do any harm even though it's not needed.
 | 
			
		||||
wxNonOwnedWindow::wxNonOwnedWindow()
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
wxNonOwnedWindow::~wxNonOwnedWindow()
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif // wxUSE_GRAPHICS_CONTEXT/!wxUSE_GRAPHICS_CONTEXT
 | 
			
		||||
 | 
			
		||||
#endif // !__WXWINCE__
 | 
			
		||||
 
 | 
			
		||||
@@ -1288,6 +1288,19 @@ void wxWidgetCocoaImpl::drawRect(void* rect, WXWidget slf, void *WXUNUSED(_cmd))
 | 
			
		||||
            dc.SetDeviceClippingRegion(clearRgn);
 | 
			
		||||
            dc.Clear();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
#if wxUSE_GRAPHICS_CONTEXT
 | 
			
		||||
        // If the window shape is defined by a path, stroke the path to show
 | 
			
		||||
        // the window border.
 | 
			
		||||
        const wxGraphicsPath& path = tlwParent->GetShapePath();
 | 
			
		||||
        if ( !path.IsNull() )
 | 
			
		||||
        {
 | 
			
		||||
            CGContextSetLineWidth(context, 1);
 | 
			
		||||
            CGContextSetStrokeColorWithColor(context, wxLIGHT_GREY->GetCGColor());
 | 
			
		||||
            CGContextAddPath(context, (CGPathRef) path.GetNativePath());
 | 
			
		||||
            CGContextStrokePath(context);
 | 
			
		||||
        }
 | 
			
		||||
#endif // wxUSE_GRAPHICS_CONTEXT
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    wxpeer->MacPaintChildrenBorders();
 | 
			
		||||
 
 | 
			
		||||
@@ -497,25 +497,49 @@ WXWindow wxNonOwnedWindow::GetWXWindow() const
 | 
			
		||||
// Shape implementation
 | 
			
		||||
// ---------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
bool wxNonOwnedWindow::SetShape(const wxRegion& region)
 | 
			
		||||
bool wxNonOwnedWindow::DoClearShape()
 | 
			
		||||
{
 | 
			
		||||
    wxCHECK_MSG( HasFlag(wxFRAME_SHAPED), false,
 | 
			
		||||
                 wxT("Shaped windows must be created with the wxFRAME_SHAPED style."));
 | 
			
		||||
    m_shape.Clear();
 | 
			
		||||
 | 
			
		||||
    m_shape = region;
 | 
			
		||||
 | 
			
		||||
    // The empty region signifies that the shape
 | 
			
		||||
    // should be removed from the window.
 | 
			
		||||
    if ( region.IsEmpty() )
 | 
			
		||||
    {
 | 
			
		||||
        wxSize sz = GetClientSize();
 | 
			
		||||
        wxRegion rgn(0, 0, sz.x, sz.y);
 | 
			
		||||
        if ( rgn.IsEmpty() )
 | 
			
		||||
            return false ;
 | 
			
		||||
        else
 | 
			
		||||
            return SetShape(rgn);
 | 
			
		||||
    }
 | 
			
		||||
    wxSize sz = GetClientSize();
 | 
			
		||||
    wxRegion region(0, 0, sz.x, sz.y);
 | 
			
		||||
 | 
			
		||||
    return m_nowpeer->SetShape(region);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool wxNonOwnedWindow::DoSetRegionShape(const wxRegion& region)
 | 
			
		||||
{
 | 
			
		||||
    m_shape = region;
 | 
			
		||||
 | 
			
		||||
    return m_nowpeer->SetShape(region);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if wxUSE_GRAPHICS_CONTEXT
 | 
			
		||||
 | 
			
		||||
#include "wx/scopedptr.h"
 | 
			
		||||
 | 
			
		||||
bool wxNonOwnedWindow::DoSetPathShape(const wxGraphicsPath& path)
 | 
			
		||||
{
 | 
			
		||||
    m_shapePath = path;
 | 
			
		||||
 | 
			
		||||
    // Convert the path to wxRegion by rendering the path on a window-sized
 | 
			
		||||
    // bitmap, creating a mask from it and finally creating the region from
 | 
			
		||||
    // this mask.
 | 
			
		||||
    wxBitmap bmp(GetSize());
 | 
			
		||||
 | 
			
		||||
    {
 | 
			
		||||
        wxMemoryDC dc(bmp);
 | 
			
		||||
        dc.SetBackground(*wxBLACK);
 | 
			
		||||
        dc.Clear();
 | 
			
		||||
 | 
			
		||||
        wxScopedPtr<wxGraphicsContext> context(wxGraphicsContext::Create(dc));
 | 
			
		||||
        context->SetBrush(*wxWHITE);
 | 
			
		||||
        context->FillPath(m_shapePath);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bmp.SetMask(new wxMask(bmp, *wxBLACK));
 | 
			
		||||
 | 
			
		||||
    return DoSetRegionShape(wxRegion(bmp));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif // wxUSE_GRAPHICS_CONTEXT
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user