summaryrefslogtreecommitdiff
path: root/support/dktools/DkWxBufferedControl.cpt
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
committerNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
commite0c6872cf40896c7be36b11dcc744620f10adf1d (patch)
tree60335e10d2f4354b0674ec22d7b53f0f8abee672 /support/dktools/DkWxBufferedControl.cpt
Initial commit
Diffstat (limited to 'support/dktools/DkWxBufferedControl.cpt')
-rw-r--r--support/dktools/DkWxBufferedControl.cpt431
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"
+}
+