Add support for transparent hint windows under GTK

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@40237 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Alex Bligh 2006-07-22 17:30:28 +00:00
parent 24e35cf87b
commit 7a5b04a65e
3 changed files with 130 additions and 7 deletions

View File

@ -44,6 +44,10 @@ enum wxFrameManagerOption
wxAUI_MGR_TRANSPARENT_DRAG = 1 << 2,
wxAUI_MGR_TRANSPARENT_HINT = 1 << 3,
wxAUI_MGR_TRANSPARENT_HINT_FADE = 1 << 4,
// The venetian blind effect is ONLY used when the wxAUI_MGR_TRANSPARENT_HINT has been used, but
// at runtime we determine we cannot use transparency (because, for instance, the OS does not support it).
// setting this flag drops back in such circumstances (only) to the behaviour without wxAUI_MGR_TRANSPARENT_HINT
wxAUI_MGR_DISABLE_VENETIAN_BLINDS = 1 << 5,
wxAUI_MGR_DEFAULT = wxAUI_MGR_ALLOW_FLOATING |
wxAUI_MGR_TRANSPARENT_HINT |
@ -540,6 +544,7 @@ protected:
wxFrame* m_hint_wnd; // transparent hint window, if supported by platform
wxTimer m_hint_fadetimer; // transparent fade timer
wxByte m_hint_fadeamt; // transparent fade amount
wxByte m_hint_fademax; // maximum value of hint fade
#ifndef SWIG
DECLARE_EVENT_TABLE()

View File

@ -913,12 +913,12 @@ void MyFrame::OnManagerFlag(wxCommandEvent& event)
{
unsigned int flag = 0;
#if !defined(__WXMSW__) && !defined(__WXMAC__)
#if !defined(__WXMSW__) && !defined(__WXMAC__) && !defined(__WXGTK__)
if (event.GetId() == ID_TransparentDrag ||
event.GetId() == ID_TransparentHint ||
event.GetId() == ID_TransparentHintFade)
{
wxMessageBox(wxT("This option is presently only available on wxMSW and wxMac"));
wxMessageBox(wxT("This option is presently only available on wxGTK, wxMSW and wxMac"));
return;
}
#endif

View File

@ -64,6 +64,107 @@ DEFINE_EVENT_TYPE(wxEVT_AUI_RENDER)
IMPLEMENT_DYNAMIC_CLASS(wxFrameManagerEvent, wxEvent)
class wxPseudoTransparentFrame : public wxFrame
{
public:
wxPseudoTransparentFrame(wxWindow* parent = NULL,
wxWindowID id = -1,
const wxString& title = wxT(""),
const wxPoint& pos = wxDefaultPosition,
const wxSize& size = wxDefaultSize,
long style = wxDEFAULT_FRAME_STYLE,
const wxString &name = wxT("frame"))
: wxFrame(parent, id, title, pos, size, style | wxFRAME_SHAPED, name)
{
SetBackgroundStyle(wxBG_STYLE_CUSTOM);
m_Amount=0;
m_MaxWidth=0;
m_MaxHeight=0;
#ifdef __WXGTK__
m_CanSetShape = false; // have to wait for window create event on GTK
#else
m_CanSetShape = true;
#endif
SetTransparent(0);
}
virtual bool SetTransparent(wxByte alpha)
{
if (m_CanSetShape)
{
int w=100; // some defaults
int h=100;
GetClientSize(&w, &h);
if ((alpha != m_Amount) || (m_MaxWidth<w) | (m_MaxHeight<h))
{
// Make the region at least double the height and width so we don't have
// to rebuild if the size changes.
m_MaxWidth=w*2;
m_MaxHeight=h*2;
m_Amount = alpha;
m_Region.Clear();
// m_Region.Union(0, 0, 1, m_MaxWidth);
if (m_Amount)
{
for (int y=0; y<m_MaxHeight; y++)
{
// Reverse the order of the bottom 4 bits
int j=((y&8)?1:0)|((y&4)?2:0)|((y&2)?4:0)|((y&1)?8:0);
if ((j*16+8)<m_Amount)
m_Region.Union(0, y, m_MaxWidth, 1);
}
}
SetShape(m_Region);
Refresh();
}
}
return true;
}
void OnPaint(wxPaintEvent & event)
{
wxPaintDC dc(this);
dc.SetBrush(wxSystemSettings::GetColour(wxSYS_COLOUR_ACTIVECAPTION));
dc.SetPen(*wxTRANSPARENT_PEN);
wxRegionIterator upd(GetUpdateRegion()); // get the update rect list
while (upd)
{
wxRect rect(upd.GetRect());
dc.DrawRectangle(rect.x, rect.y, rect.width, rect.height);
upd++;
}
}
#ifdef __WXGTK__
void OnWindowCreate(wxWindowCreateEvent& WXUNUSED(event)) {m_CanSetShape=true; SetTransparent(0);}
#endif
private:
int m_Amount;
int m_MaxWidth;
int m_MaxHeight;
bool m_CanSetShape;
wxRegion m_Region;
DECLARE_DYNAMIC_CLASS(wxPseudoTransparentFrame);
DECLARE_EVENT_TABLE();
};
IMPLEMENT_DYNAMIC_CLASS( wxPseudoTransparentFrame, wxFrame )
BEGIN_EVENT_TABLE(wxPseudoTransparentFrame, wxFrame)
EVT_PAINT(wxPseudoTransparentFrame::OnPaint)
#ifdef __WXGTK__
EVT_WINDOW_CREATE(wxPseudoTransparentFrame::OnWindowCreate)
#endif
END_EVENT_TABLE()
// -- static utility functions --
@ -496,7 +597,7 @@ void wxFrameManager::SetManagedWindow(wxWindow* frame)
#endif
// Make a window to use for a transparent hint
#if defined(__WXMSW__)
#if defined(__WXMSW__) || defined(__WXGTK__)
m_hint_wnd = new wxFrame(m_frame, -1, wxEmptyString, wxDefaultPosition, wxSize(1,1),
wxFRAME_TOOL_WINDOW |
wxFRAME_FLOAT_ON_PARENT |
@ -523,11 +624,23 @@ void wxFrameManager::SetManagedWindow(wxWindow* frame)
p->SetBackgroundColour(*wxBLUE);
#endif
m_hint_fademax=50;
if (m_hint_wnd && !m_hint_wnd->CanSetTransparent())
{
m_hint_wnd->Close();
m_hint_wnd->Destroy();
m_hint_wnd = NULL;
// If we can convert it to a PseudoTransparent window, do so
m_hint_wnd = new wxPseudoTransparentFrame (m_frame, -1, wxEmptyString, wxDefaultPosition, wxSize(1,1),
wxFRAME_TOOL_WINDOW |
wxFRAME_FLOAT_ON_PARENT |
wxFRAME_NO_TASKBAR |
wxNO_BORDER);
m_hint_fademax = 128;
}
}
@ -2462,25 +2575,29 @@ bool wxFrameManager::DoDrop(wxDockInfoArray& docks,
void wxFrameManager::OnHintFadeTimer(wxTimerEvent& WXUNUSED(event))
{
if (!m_hint_wnd || m_hint_fadeamt >= 50)
if (!m_hint_wnd || m_hint_fadeamt >= m_hint_fademax)
{
m_hint_fadetimer.Stop();
return;
}
m_hint_fadeamt += 5;
m_hint_fadeamt += 4;
m_hint_wnd->SetTransparent(m_hint_fadeamt);
}
void wxFrameManager::ShowHint(const wxRect& rect)
{
if ((m_flags & wxAUI_MGR_TRANSPARENT_HINT) != 0 && m_hint_wnd)
if ((m_flags & wxAUI_MGR_TRANSPARENT_HINT) != 0
&& m_hint_wnd
// Finally, don't use a venetian blind effect if it's been specifically disabled
&& !((m_hint_wnd->IsKindOf(CLASSINFO(wxPseudoTransparentFrame))) && (m_flags & wxAUI_MGR_DISABLE_VENETIAN_BLINDS))
)
{
if (m_last_hint == rect)
return;
m_last_hint = rect;
wxByte initial_fade = 50;
wxByte initial_fade = m_hint_fademax;
if (m_flags & wxAUI_MGR_TRANSPARENT_HINT_FADE)
initial_fade = 0;
@ -2565,6 +2682,7 @@ void wxFrameManager::HideHint()
// hides a transparent window hint, if there is one
if (m_hint_wnd)
{
m_hint_wnd->Show(false);
m_hint_wnd->SetTransparent(0);
m_hint_fadetimer.Stop();
m_last_hint = wxRect();