diff options
author | Norbert Preining <norbert@preining.info> | 2019-09-02 13:46:59 +0900 |
---|---|---|
committer | Norbert Preining <norbert@preining.info> | 2019-09-02 13:46:59 +0900 |
commit | e0c6872cf40896c7be36b11dcc744620f10adf1d (patch) | |
tree | 60335e10d2f4354b0674ec22d7b53f0f8abee672 /support/dktools/DkWxBufferedControl.cpt |
Initial commit
Diffstat (limited to 'support/dktools/DkWxBufferedControl.cpt')
-rw-r--r-- | support/dktools/DkWxBufferedControl.cpt | 431 |
1 files changed, 431 insertions, 0 deletions
diff --git a/support/dktools/DkWxBufferedControl.cpt b/support/dktools/DkWxBufferedControl.cpt new file mode 100644 index 0000000000..3b78151c5b --- /dev/null +++ b/support/dktools/DkWxBufferedControl.cpt @@ -0,0 +1,431 @@ +%% options + +copyright owner = Dirk Krause +copyright year = 2013-xxxx +license = bsd + +%% header + +#include <dk3all.h> + +#include <wx/wxprec.h> +#ifdef __BORLANDC__ +#pragma hdrstop +#endif +#ifndef WX_PRECOMP +#include <wx/wx.h> +#endif + +/** This is a base class for triple-buffered views. + Like double-buffering we write the windows contents + to an image and finally transfer the entire image + to the device context. + Additionally we keep the image between the paint events + and rebuild the image only if necessary (data to show + has changed). + + When the frame containing your view becomes invisible + (frame iconized or hidden) you should use the releaseBuffer() + method to decrease the memory footprint of the program. + + In your derived class, call the DkWxBufferedControl constructors from + the constructors. + From Create() call DkWxBufferedControl::Create(). + + You should also use DECLARE_DYNAMIC_CLASS() and + IMPLEMENT_DYNAMIC_CLASS(). +*/ +class DkWxBufferedControl : public wxControl +{ + private: + + /** Avoid simultaneous access from multiple threads. + */ + wxMutex mxProtectData; + + /** Bitmap for buffered drawing operations. + */ + wxBitmap *pBitmap; + + /** Flag: Must redraw. + */ + bool bMustDraw; + + /** Bitmap width, window width. + */ + int iWidth; + + /** Bitmap height, window height. + */ + int iHeight; + + /** For RTTI. + */ + DECLARE_DYNAMIC_CLASS(DkWxBufferedControl) + + /** Event table. + */ + DECLARE_EVENT_TABLE() + + protected: + + static wxChar const DkWxBufferedControlName[]; + + /** Internal method to paint. + This method saves some DC attributes and restores them + before returning. + @param pdc Device context to draw to. + @param event Paint event to process. + @param buffered Flag: Operating on a memory DC. + @param clWidth Client area width. + @param clHeight Client area height. + */ + void InternalPaint( + wxDC & pdc, + wxPaintEvent & event, + bool buffered, + int clWidth, + int clHeight + ); + + public: + + /** Default constructor. + */ + DkWxBufferedControl(); + + /** Constructor. + @param pParent Parent window. + @param wid Window ID + @param pos Window position. + @param size Window size. + @param style Window style. + @param validator Validator for control. + @param name Window type name. + */ + DkWxBufferedControl( + wxWindow *pParent, + wxWindowID wid = wxID_ANY, + const wxPoint & pos = wxDefaultPosition, + const wxSize & size = wxDefaultSize, + long style = 0L, + const wxValidator & validator = wxDefaultValidator, + wxChar const *name = DkWxBufferedControlName + ); + + /** Create after using the default constructor. + @param pParent Parent window. + @param wid Window ID + @param pos Window position. + @param size Window size. + @param style Window style. + @param validator Validator for control. + @param name Window type name. + */ + bool + Create( + wxWindow *pParent, + wxWindowID wid = wxID_ANY, + const wxPoint & pos = wxDefaultPosition, + const wxSize & size = wxDefaultSize, + long style = 0L, + const wxValidator & validator = wxDefaultValidator, + const wxChar *name = DkWxBufferedControlName + ); + + /** Destructor. + */ + ~DkWxBufferedControl(); + + /** Indicate that data has changed so on next + paint we must rebuild the bitmap. + @param flag: Flag to turn bMustDraw on or off. + */ + void + SetMustUpdate(bool flag = true); + + /** Release bitmap buffer. This function should be called + when the frame or dialog containing this view is iconized + or hidden. + */ + void + releaseBuffer(void); + + /** Handler for erase background event. + @param event Event to process. + */ + void + OnErase(wxEraseEvent & event); + + /** Handler for paint event. + @param event Event to process. + */ + void + OnPaint(wxPaintEvent & event); + + /** Overwrite this method to do the real drawing. + @param pdc Device context to draw to. + Normally a memory dc, but may be a direct + dc in special situations (failed to allocate + bitmap). + @param event Paint event to process. + @param buffered Flag: Operating on a memory DC. + @param clWidth Client area width. + @param clHeight Client area height. + */ + virtual + void PaintOperation( + wxDC & pdc, + wxPaintEvent & event, + bool buffered, + int clWidth, + int clHeight + ); + +}; + +%% module + + + +#include "DkWxBufferedControl.h" + + +$!trace-include + + + +wxChar const DkWxBufferedControl::DkWxBufferedControlName[] = { + wxT("DkWxBufferedControl") +}; + + +IMPLEMENT_DYNAMIC_CLASS(DkWxBufferedControl, wxControl) + +BEGIN_EVENT_TABLE(DkWxBufferedControl,wxControl) + EVT_ERASE_BACKGROUND(DkWxBufferedControl::OnErase) + EVT_PAINT(DkWxBufferedControl::OnPaint) +END_EVENT_TABLE() + + + +DkWxBufferedControl::DkWxBufferedControl() +{ + $? "+ DkWxBufferedControl::DkWxBufferedControl" + pBitmap = NULL; + iWidth = -1; + iHeight = -1; + bMustDraw = true; + SetBackgroundStyle(wxBG_STYLE_CUSTOM); + $? "- DkWxBufferedControl::DkWxBufferedControl" +} + + + +bool +DkWxBufferedControl::Create( + wxWindow *pParent, + wxWindowID wid, + const wxPoint & pos, + const wxSize & size, + long style, + const wxValidator & validator, + wxChar const *name +) +{ + bool back; + back = wxControl::Create( + pParent, wid, pos, size, style, validator, wxString(name) + ); + pBitmap = NULL; + iWidth = -1; + iHeight = -1; + bMustDraw = true; + SetBackgroundStyle(wxBG_STYLE_CUSTOM); + return back; +} + + + +DkWxBufferedControl::DkWxBufferedControl( + wxWindow *pParent, + wxWindowID wid, + const wxPoint & pos, + const wxSize & size, + long style, + const wxValidator & validator, + wxChar const *name +) +: wxControl( + pParent, + wid, + pos, + size, + style, + validator, + wxString(name) +) +{ + $? "+ DkWxBufferedControl::DkWxBufferedControl" + pBitmap = NULL; + iWidth = -1; + iHeight = -1; + bMustDraw = true; + SetBackgroundStyle(wxBG_STYLE_CUSTOM); + $? "- DkWxBufferedControl::DkWxBufferedControl" +} + + + +DkWxBufferedControl::~DkWxBufferedControl() +{ + $? "+ DkWxBufferedControl::~DkWxBufferedControl" + { + wxMutexLocker lock(mxProtectData); + if(NULL != pBitmap) { $? ". delete bitmap buffer (destructor)" + delete(pBitmap); + pBitmap = NULL; + } + iWidth = -1; + iHeight = -1; + bMustDraw = false; + } + $? "- DkWxBufferedControl::~DkWxBufferedControl" +} + + + +void +DkWxBufferedControl::OnErase(wxEraseEvent & event) +{ + $? "+ DkWxBufferedControl::OnErase" + /* Do nothing here. */ + $? "- DkWxBufferedControl::OnErase" +} + + + +void +DkWxBufferedControl::OnPaint(wxPaintEvent & event) +{ + bool mustdraw = false; + bool done = false; + int w = 0; + int h = 0; + $? "+ DkWxBufferedControl::OnPaint" + wxPaintDC paintDC(this); + { + wxMutexLocker lock(mxProtectData); +#if VERSION_BEFORE_20150821 + w = iWidth; + h = iHeight; +#endif + wxSize sz = GetClientSize(); + if(NULL != pBitmap) { + if((iWidth != sz.x) || (iHeight != sz.y)) { + delete(pBitmap); $? ". delete bitmap buffer (size)" + pBitmap = NULL; + mustdraw = true; $? ". bitmap size mismatch" + } + } + w = iWidth = sz.x; h = iHeight = sz.y; + if(NULL == pBitmap) { $? ". allocate bitmap buffer" + pBitmap = new wxBitmap(iWidth, iHeight); + mustdraw = true; $? ". new bitmap PTR=%d", TR_IPTR(pBitmap) + } + if(NULL != pBitmap) { $? ". have bitmap" + if(false == mustdraw) { + if(bMustDraw) { $? ". must redraw, requested" + mustdraw = true; + } + } + if(mustdraw) { $? ". must redraw, use bitmap" + wxMemoryDC memDC; + memDC.SelectObject(*pBitmap); + InternalPaint(memDC, event, true, w, h); + memDC.SelectObject(wxNullBitmap); + bMustDraw = false; $? ". result saved in bitmap" + } else { $? ". simply use existing bitmap" + } + paintDC.DrawBitmap(*pBitmap, 0, 0, false); + done = true; + } + } + if(!(done)) { $? ". paint unbuffered" + InternalPaint(paintDC, event, false, w, h); + } $? "- DkWxBufferedControl::OnPaint" +} + + + +void +DkWxBufferedControl::PaintOperation( + wxDC & pdc, + wxPaintEvent & event, + bool buffered, + int clWidth, + int clHeight +) +{ + /* The default implementation intentionally does nothing. */ +} + + + +void +DkWxBufferedControl::InternalPaint( + wxDC & pdc, + wxPaintEvent & event, + bool buffered, + int clWidth, + int clHeight +) +{ + wxBrush const br = pdc.GetBrush(); + wxBrush const bg = pdc.GetBackground(); + wxFont const fn = pdc.GetFont(); + wxPen const pn = pdc.GetPen(); + wxColour const tbg = pdc.GetTextBackground(); + wxColour const tfg = pdc.GetTextForeground(); + int bgm = pdc.GetBackgroundMode(); + $? "+ DkWxBufferedControl::InternalPaint" + PaintOperation(pdc, event, buffered, clWidth, clHeight); + + pdc.SetBackgroundMode(bgm); + pdc.SetTextForeground(tfg); + pdc.SetTextBackground(tbg); + pdc.SetPen(pn); + pdc.SetFont(fn); + pdc.SetBackground(bg); + pdc.SetBrush(br); + $? "- DkWxBufferedControl::InternalPaint" +} + + + +void +DkWxBufferedControl::SetMustUpdate(bool flag) +{ + $? "+ DkWxBufferedControl::SetMustUpdate" + { + wxMutexLocker lock(mxProtectData); + bMustDraw = flag; + } + $? "- DkWxBufferedControl::SetMustUpdate" +} + + + +void +DkWxBufferedControl::releaseBuffer(void) +{ + $? "+ DkWxBufferedControl::releaseBuffer" + { + wxMutexLocker lock(mxProtectData); + if(pBitmap) { $? ". delete bitmap buffer (explicit release)" + delete(pBitmap); + pBitmap = NULL; + } + } $? "- DkWxBufferedControl::releaseBuffer" +} + |