Add wxSTCPopupWindow for wxSTC

The wxSTCPopupWindow is intended to serve as a popup window for showing
call tips and popup lists with wxSTC. This class is designed to show its
content and respond to mouse clicks, but it should never take focus from
its parent wxSTC. It is built with customizations for wxMSW, wxCocoa,
and wxGTK+ to function in that way.
This commit is contained in:
New Pagodi
2019-03-11 13:27:35 -05:00
parent 79e16c78bc
commit 75656067ae
2 changed files with 290 additions and 0 deletions

View File

@@ -32,6 +32,7 @@
#include "wx/tokenzr.h" #include "wx/tokenzr.h"
#include "wx/dynlib.h" #include "wx/dynlib.h"
#include "wx/scopedarray.h" #include "wx/scopedarray.h"
#include "wx/toplevel.h"
#ifdef wxHAS_RAW_BITMAP #ifdef wxHAS_RAW_BITMAP
#include "wx/rawbmp.h" #include "wx/rawbmp.h"
@@ -55,6 +56,12 @@
#include "wx/dcscreen.h" #include "wx/dcscreen.h"
#endif #endif
#if defined(__WXGTK__) && wxSTC_POPUP_IS_FRAME
#include "wx/gtk/private/wrapgtk.h"
#elif defined(__WXMSW__)
#include "wx/msw/wrapwin.h"
#endif
Point Point::FromLong(long lpoint) { Point Point::FromLong(long lpoint) {
return Point(lpoint & 0xFFFF, lpoint >> 16); return Point(lpoint & 0xFFFF, lpoint >> 16);
} }
@@ -1983,6 +1990,206 @@ PRectangle Window::GetMonitorRect(Point pt) {
return PRectangleFromwxRect(dpy.GetGeometry()); return PRectangleFromwxRect(dpy.GetGeometry());
} }
//----------------------------------------------------------------------
// wxSTCPopupBase and wxSTCPopupWindow
#ifdef __WXOSX_COCOA__
wxSTCPopupBase::wxSTCPopupBase(wxWindow* parent):wxNonOwnedWindow()
{
}
wxSTCPopupBase::~wxSTCPopupBase()
{
}
#elif wxUSE_POPUPWIN
wxSTCPopupBase::wxSTCPopupBase(wxWindow* parent)
:wxPopupWindow(parent, wxPU_CONTAINS_CONTROLS)
{
}
#ifdef __WXGTK__
wxSTCPopupBase::~wxSTCPopupBase()
{
wxRect rect = GetRect();
GetParent()->ScreenToClient(&(rect.x), &(rect.y));
GetParent()->Refresh(false, &rect);
}
#elif defined(__WXMSW__)
// Do not activate the window when it is shown.
bool wxSTCPopupBase::Show(bool show)
{
if ( !wxWindowBase::Show(show) )
return false;
if ( show )
{
HWND hWnd = reinterpret_cast<HWND>(GetHandle());
::ShowWindow(hWnd, SW_SHOWNA );
::SetWindowPos(hWnd, HWND_NOTOPMOST, 0, 0, 0, 0,
SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
}
else
wxPopupWindow::Show(false);
return true;
}
// Do not activate in response to mouse clicks on this window.
bool wxSTCPopupBase::MSWHandleMessage(WXLRESULT *res, WXUINT msg,
WXWPARAM wParam, WXLPARAM lParam)
{
if ( msg == WM_MOUSEACTIVATE )
{
*res = MA_NOACTIVATE;
return true;
}
else
return wxPopupWindow::MSWHandleMessage(res, msg, wParam,lParam);
}
#endif // __WXGTK__
#else
wxSTCPopupBase::wxSTCPopupBase(wxWindow* parent):wxFrame()
{
// Make sure the frame is initially hidden. However, GTK+ will hide the
// frame initially and doesn't like trying to hide it before it's
// created, so don't do it there.
#if !defined(__WXGTK__)
Hide();
#endif
wxFrame::Create(parent, wxID_ANY, wxEmptyString,
wxDefaultPosition, wxDefaultSize,
wxFRAME_FLOAT_ON_PARENT | wxBORDER_NONE);
#if defined(__WXGTK__)
gtk_window_set_accept_focus(GTK_WINDOW(this->GetHandle()), FALSE);
#endif
}
#ifdef __WXMSW__
// Use ShowWithoutActivating instead of show.
bool wxSTCPopupBase::Show(bool show)
{
if ( show )
{
if ( IsShown() )
return false;
else
{
ShowWithoutActivating();
return true;
}
}
else
return wxFrame::Show(false);
}
// Do not activate in response to mouse clicks on this window.
bool wxSTCPopupBase::MSWHandleMessage(WXLRESULT *res, WXUINT msg,
WXWPARAM wParam, WXLPARAM lParam)
{
if ( msg == WM_MOUSEACTIVATE )
{
*res = MA_NOACTIVATE;
return true;
}
else
return wxFrame::MSWHandleMessage(res, msg, wParam, lParam);
}
#elif !wxSTC_POPUP_IS_CUSTOM
void wxSTCPopupBase::ActivateParent()
{
// Although we're a frame, we always want the parent to be active,
// so raise it whenever we get shown, focused, etc.
wxTopLevelWindow *frame = wxDynamicCast(
wxGetTopLevelParent(GetParent()), wxTopLevelWindow);
if (frame)
frame->Raise();
}
bool wxSTCPopupBase::Show(bool show)
{
bool rv = wxFrame::Show(show);
if (rv && show)
ActivateParent();
#ifdef __WXMAC__
GetParent()->Refresh(false);
#endif
}
#endif
#endif // __WXOSX_COCOA__
wxSTCPopupWindow::wxSTCPopupWindow(wxWindow* parent):wxSTCPopupBase(parent)
{
#if !wxSTC_POPUP_IS_CUSTOM
Bind(wxEVT_SET_FOCUS, &wxSTCPopupWindow::OnFocus, this);
#endif
}
bool wxSTCPopupWindow::Destroy()
{
#if defined(__WXMAC__) && wxSTC_POPUP_IS_FRAME && !wxSTC_POPUP_IS_CUSTOM
// The bottom edge of this window is not getting properly
// refreshed upon deletion, so help it out...
wxWindow* p = GetParent();
wxRect r(GetPosition(), GetSize());
r.SetHeight(r.GetHeight()+1);
p->Refresh(false, &r);
#endif
if ( !wxPendingDelete.Member(this) )
wxPendingDelete.Append(this);
return true;
}
bool wxSTCPopupWindow::AcceptsFocus() const
{
return false;
}
void wxSTCPopupWindow::DoSetSize(int x, int y, int width, int height, int flags)
{
// convert coords to screen coords since we're a top-level window
if (x != wxDefaultCoord)
GetParent()->ClientToScreen(&x, NULL);
if (y != wxDefaultCoord)
GetParent()->ClientToScreen(NULL, &y);
wxSTCPopupBase::DoSetSize(x, y, width, height, flags);
}
#if !wxSTC_POPUP_IS_CUSTOM
void wxSTCPopupWindow::OnFocus(wxFocusEvent& event)
{
#if wxSTC_POPUP_IS_FRAME
ActivateParent();
#endif
GetParent()->SetFocus();
event.Skip();
}
#endif // !wxSTC_POPUP_IS_CUSTOM
//---------------------------------------------------------------------- //----------------------------------------------------------------------
// Helper classes for ListBox // Helper classes for ListBox

View File

@@ -54,6 +54,89 @@ public:
virtual void SetList(const char* list, char separator, char typesep) wxOVERRIDE; virtual void SetList(const char* list, char separator, char typesep) wxOVERRIDE;
}; };
//----------------------------------------------------------------------
// wxSTCPopupWindow
#if defined(__WXOSX_COCOA__) || defined(__WXMSW__) || defined(__WXGTK__)
#define wxSTC_POPUP_IS_CUSTOM 1
#else
#define wxSTC_POPUP_IS_CUSTOM 0
#endif
// Define the base class used for wxSTCPopupWindow.
#ifdef __WXOSX_COCOA__
#include "wx/nonownedwnd.h"
#define wxSTC_POPUP_IS_FRAME 0
class wxSTCPopupBase:public wxNonOwnedWindow
{
public:
wxSTCPopupBase(wxWindow*);
virtual ~wxSTCPopupBase();
};
#elif wxUSE_POPUPWIN
#include "wx/popupwin.h"
#define wxSTC_POPUP_IS_FRAME 0
class wxSTCPopupBase:public wxPopupWindow
{
public:
wxSTCPopupBase(wxWindow*);
#ifdef __WXGTK__
virtual ~wxSTCPopupBase();
#elif defined(__WXMSW__)
virtual bool Show(bool show=true) wxOVERRIDE;
virtual bool MSWHandleMessage(WXLRESULT *result, WXUINT message,
WXWPARAM wParam, WXLPARAM lParam)
wxOVERRIDE;
#endif
};
#else
#include "wx/frame.h"
#define wxSTC_POPUP_IS_FRAME 1
class wxSTCPopupBase:public wxFrame
{
public:
wxSTCPopupBase(wxWindow*);
#ifdef __WXMSW__
virtual bool Show(bool show=true) wxOVERRIDE;
virtual bool MSWHandleMessage(WXLRESULT *result, WXUINT message,
WXWPARAM wParam, WXLPARAM lParam)
wxOVERRIDE;
#elif !wxSTC_POPUP_IS_CUSTOM
virtual bool Show(bool show=true) wxOVERRIDE;
void ActivateParent();
#endif
};
#endif // __WXOSX_COCOA__
class wxSTCPopupWindow:public wxSTCPopupBase
{
public:
wxSTCPopupWindow(wxWindow*);
virtual bool Destroy() wxOVERRIDE;
virtual bool AcceptsFocus() const wxOVERRIDE;
protected:
virtual void DoSetSize(int x, int y, int width, int height,
int sizeFlags = wxSIZE_AUTO) wxOVERRIDE;
#if !wxSTC_POPUP_IS_CUSTOM
void OnFocus(wxFocusEvent& event);
#endif
};
//----------------------------------------------------------------------
// SurfaceData
class SurfaceData class SurfaceData
{ {
public: public: