/////////////////////////////////////////////////////////////////////////////
-// Name: dcclient.cpp
+// Name: src/os2/dcclient.cpp
// Purpose: wxClientDC class
// Author: David Webster
// Modified by:
// For compilers that support precompilation, includes "wx.h".
#include "wx/wxprec.h"
-#include "wx/string.h"
-#include "wx/log.h"
-#include "wx/window.h"
+#include "wx/dcclient.h"
+#include "wx/os2/dcclient.h"
-#include "wx/os2/private.h"
+#ifndef WX_PRECOMP
+ #include "wx/string.h"
+ #include "wx/log.h"
+ #include "wx/app.h"
+ #include "wx/window.h"
+#endif
-#include "wx/dcclient.h"
+#include "wx/os2/private.h"
// ----------------------------------------------------------------------------
// array/list types
struct WXDLLEXPORT wxPaintDCInfo
{
wxPaintDCInfo( wxWindow* pWin
- ,wxDC* pDC
+ ,wxPaintDCImpl* pDC
)
{
m_hWnd = pWin->GetHWND();
WX_DEFINE_OBJARRAY(wxArrayDCInfo);
-// ----------------------------------------------------------------------------
-// macros
-// ----------------------------------------------------------------------------
-
- IMPLEMENT_DYNAMIC_CLASS(wxWindowDC, wxDC)
- IMPLEMENT_DYNAMIC_CLASS(wxClientDC, wxWindowDC)
- IMPLEMENT_DYNAMIC_CLASS(wxPaintDC, wxWindowDC)
-
// ----------------------------------------------------------------------------
// global variables
// ----------------------------------------------------------------------------
static RECT g_paintStruct;
-#ifdef __WXDEBUG__
+#ifdef wxHAS_PAINT_DEBUG
// a global variable which we check to verify that wxPaintDC are only
// created in resopnse to WM_PAINT message - doing this from elsewhere is a
- // common programming error among wxWindows programmers and might lead to
+ // common programming error among wxWidgets programmers and might lead to
// very subtle and difficult to debug refresh/repaint bugs.
int g_isPainting = 0;
-#endif // __WXDEBUG__
+#endif // wxHAS_PAINT_DEBUG
// ===========================================================================
// implementation
// ===========================================================================
// ----------------------------------------------------------------------------
-// wxWindowDC
+// wxWindowDCImpl
// ----------------------------------------------------------------------------
-wxWindowDC::wxWindowDC()
+IMPLEMENT_ABSTRACT_CLASS(wxWindowDCImpl, wxPMDCImpl)
+
+wxWindowDCImpl::wxWindowDCImpl( wxDC *owner ) :
+ wxPMDCImpl( owner )
{
- m_pCanvas = NULL;
+ m_PageSize.cx = m_PageSize.cy = 0;
}
-wxWindowDC::wxWindowDC(
- wxWindow* pTheCanvas
-)
+wxWindowDCImpl::wxWindowDCImpl( wxDC *owner, wxWindow* pTheCanvas) :
+ wxPMDCImpl( owner )
{
ERRORID vError;
wxString sError;
+ int nWidth, nHeight;
m_pCanvas = pTheCanvas;
+ DoGetSize(&nWidth, &nHeight);
+ m_PageSize.cx = nWidth;
+ m_PageSize.cy = nHeight;
m_hDC = (WXHDC) ::WinOpenWindowDC(GetWinHwnd(pTheCanvas) );
- m_nDCCount++;
+
//
// default under PM is that Window and Client DC's are the same
// so we offer a separate Presentation Space to use for the
// entire window. Otherwise, calling BeginPaint will just create
// chached-micro client presentation space
//
- m_hPS = GpiCreatePS( m_hab
- ,m_hDC
- ,&m_PageSize
- ,PU_PELS | GPIF_LONG | GPIA_ASSOC
- );
+ m_hPS = ::GpiCreatePS( vHabmain
+ ,m_hDC
+ ,&m_PageSize
+ ,PU_PELS | GPIF_LONG | GPIA_ASSOC
+ );
+ if (!m_hPS)
+ {
+ vError = ::WinGetLastError(vHabmain);
+ sError = wxPMErrorToStr(vError);
+ wxLogError(wxT("Unable to create presentation space. Error: %s\n"), sError.c_str());
+ }
::GpiAssociate(m_hPS, NULLHANDLE);
::GpiAssociate(m_hPS, m_hDC);
- // Set the wxWindows color table
+
+ //
+ // Set the wxWidgets color table
+ //
if (!::GpiCreateLogColorTable( m_hPS
,0L
,LCOLF_CONSECRGB
{
vError = ::WinGetLastError(vHabmain);
sError = wxPMErrorToStr(vError);
- wxLogError("Unable to set current color table. Error: %s\n", sError);
+ wxLogError(wxT("Unable to set current color table (3). Error: %s\n"), sError.c_str());
}
::GpiCreateLogColorTable( m_hPS
,0L
,0L
,NULL
);
- SetBackground(wxBrush(m_pCanvas->GetBackgroundColour(), wxSOLID));
::WinQueryWindowRect( GetWinHwnd(m_pCanvas)
,&m_vRclPaint
);
-}
+ InitDC();
+} // end of wxWindowDCImpl::wxWindowDCImpl
-wxWindowDC::~wxWindowDC()
+void wxWindowDCImpl::InitDC()
{
- if (m_pCanvas && m_hDC)
- {
- SelectOldObjects(m_hDC);
- //
- // In PM one does not explicitly close or release an open WindowDC
- // They automatically close with the window, unless explicitly detached
- // but we need to destroy our PS
- //
- if(m_hPS)
- {
- ::GpiAssociate(m_hPS, NULLHANDLE);
- ::GpiDestroyPS(m_hPS);
- }
- m_hPS = NULLHANDLE;
- m_hDC = NULLHANDLE;
- }
- m_nDCCount--;
-}
+ //
+ // The background mode is only used for text background and is set in
+ // DrawText() to OPAQUE as required, otherwise always TRANSPARENT,
+ //
+ ::GpiSetBackMix(GetHPS(), BM_LEAVEALONE);
+
+ //
+ // Default bg colour is pne of the window
+ //
+ SetBackground(wxBrush(m_pCanvas->GetBackgroundColour(), wxSOLID));
+
+ m_pen.SetColour(*wxBLACK);
+ m_brush.SetColour(*wxWHITE);
+ // since we are a window dc we need to grab the palette from the window
+#if wxUSE_PALETTE
+ InitializePalette();
+#endif
+ wxFont* pFont = new wxFont( 10, wxMODERN, wxNORMAL, wxBOLD );
+ SetFont(*pFont);
+ delete pFont;
+ //
+ // OS/2 default vertical character alignment needs to match the other OS's
+ //
+ ::GpiSetTextAlignment((HPS)GetHPS(), TA_NORMAL_HORIZ, TA_BOTTOM);
+
+} // end of wxWindowDCImpl::InitDC
+
+void wxWindowDCImpl::DoGetSize(
+ int* pnWidth
+, int* pnHeight
+) const
+{
+ wxCHECK_RET( m_pCanvas, wxT("wxWindowDC without a window?") );
+ m_pCanvas->GetSize( pnWidth
+ ,pnHeight
+ );
+} // end of wxWindowDCImpl::DoGetSize
// ----------------------------------------------------------------------------
// wxClientDC
// ----------------------------------------------------------------------------
-wxClientDC::wxClientDC()
+IMPLEMENT_ABSTRACT_CLASS(wxClientDCImpl, wxWindowDCImpl)
+
+wxClientDCImpl::wxClientDCImpl( wxDC *owner ) :
+ wxWindowDCImpl( owner )
{
m_pCanvas = NULL;
}
-wxClientDC::wxClientDC(
- wxWindow* pTheCanvas
-)
+wxClientDCImpl::wxClientDCImpl( wxDC *owner, wxWindow *pTheCanvas) :
+ wxWindowDCImpl( owner )
{
SIZEL vSizl = { 0,0};
ERRORID vError;
//
// default under PM is that Window and Client DC's are the same
//
+
m_hDC = (WXHDC) ::WinOpenWindowDC(GetWinHwnd(pTheCanvas));
+ printf("Got WindowDC %X for window handle %X\n", m_hDC, pTheCanvas);
+
m_hPS = ::GpiCreatePS( wxGetInstance()
,m_hDC
,&vSizl
,PU_PELS | GPIF_LONG | GPIA_ASSOC
);
+ ::GpiAssociate(m_hPS, NULLHANDLE);
+ ::GpiAssociate(m_hPS, m_hDC);
- // Set the wxWindows color table
+ printf("Got m_hPS %X\n", m_hPS);
+ // Set the wxWidgets color table
if (!::GpiCreateLogColorTable( m_hPS
,0L
,LCOLF_CONSECRGB
{
vError = ::WinGetLastError(vHabmain);
sError = wxPMErrorToStr(vError);
- wxLogError("Unable to set current color table. Error: %s\n", sError);
+ wxLogError(wxT("Unable to set current color table (4). Error: %s\n"), sError.c_str());
}
::GpiCreateLogColorTable( m_hPS
,0L
,NULL
);
//
- // Default mode is BM_LEAVEALONE so we make no call Set the mix
- //
- SetBackground(wxBrush( m_pCanvas->GetBackgroundColour()
- ,wxSOLID
- )
- );
- //
// Set the DC/PS rectangle
//
::WinQueryWindowRect( GetWinHwnd(m_pCanvas)
,&m_vRclPaint
);
-} // end of wxClientDC::wxClientDC
+ InitDC();
+} // end of wxClientDCImpl::wxClientDCImpl
-wxClientDC::~wxClientDC()
+void wxClientDCImpl::InitDC()
{
- if ( m_pCanvas && GetHdc() )
- {
- SelectOldObjects(m_hDC);
+ wxWindowDCImpl::InitDC();
- //
- // We don't explicitly release Device contexts in PM and
- // the cached micro PS is already gone
- //
- m_hDC = 0;
+ // in wxUniv build we must manually do some DC adjustments usually
+ // performed by Windows for us
+#ifdef __WXUNIVERSAL__
+ wxPoint ptOrigin = m_pCanvas->GetClientAreaOrigin();
+ if ( ptOrigin.x || ptOrigin.y )
+ {
+ // no need to shift DC origin if shift is null
+ SetDeviceOrigin(ptOrigin.x, ptOrigin.y);
}
-} // end of wxClientDC::~wxClientDC
+
+ // clip the DC to avoid overwriting the non client area
+ SetClippingRegion(wxPoint(0, 0), m_pCanvas->GetClientSize());
+#endif // __WXUNIVERSAL__
+} // end of wxClientDCImpl::InitDC
+
+wxClientDCImpl::~wxClientDCImpl()
+{
+} // end of wxClientDCImpl::~wxClientDCImpl
+
+void wxClientDCImpl::DoGetSize(
+ int* pnWidth
+, int* pnHeight
+) const
+{
+ wxCHECK_RET( m_pCanvas, wxT("wxWindowDC without a window?") );
+ m_pCanvas->GetClientSize( pnWidth
+ ,pnHeight
+ );
+} // end of wxClientDCImpl::DoGetSize
// ----------------------------------------------------------------------------
// wxPaintDC
// ----------------------------------------------------------------------------
-// VZ: initial implementation (by JACS) only remembered the last wxPaintDC
-// created and tried to reuse - this was supposed to take care of a
-// situation when a derived class OnPaint() calls base class OnPaint()
-// because in this case ::BeginPaint() shouldn't be called second time.
-//
-// I'm not sure how useful this is, however we must remember the HWND
-// associated with the last HDC as well - otherwise we may (and will!) try
-// to reuse the HDC for another HWND which is a nice recipe for disaster.
-//
-// So we store a list of windows for which we already have the DC and not
-// just one single hDC. This seems to work, but I'm really not sure about
-// the usefullness of the whole idea - IMHO it's much better to not call
-// base class OnPaint() at all, or, if we really want to allow it, add a
-// "wxPaintDC *" parameter to wxPaintEvent which should be used if it's
-// !NULL instead of creating a new DC.
-
-wxArrayDCInfo wxPaintDC::ms_cache;
-
-wxPaintDC::wxPaintDC()
+IMPLEMENT_ABSTRACT_CLASS(wxPaintDCImpl, wxWindowDCImpl)
+
+wxArrayDCInfo wxPaintDCImpl::ms_cache;
+
+wxPaintDCImpl::wxPaintDCImpl( wxDC *owner ) :
+ wxClientDCImpl( owner )
{
m_pCanvas = NULL;
m_hDC = 0;
}
-wxPaintDC::wxPaintDC(
- wxWindow* pCanvas
-)
+wxPaintDCImpl::wxPaintDCImpl( wxDC *owner, wxWindow *pCanvas) :
+ wxClientDCImpl( owner )
{
wxCHECK_RET(pCanvas, wxT("NULL canvas in wxPaintDC ctor"));
- RECTL vRect;
-#ifdef __WXDEBUG__
+#ifdef wxHAS_PAINT_DEBUG
if (g_isPainting <= 0)
{
wxFAIL_MSG( wxT("wxPaintDC may be created only in EVT_PAINT handler!") );
return;
}
-#endif // __WXDEBUG__
+#endif // wxHAS_PAINT_DEBUG
m_pCanvas = pCanvas;
{
HPS hPS;
+ m_hDC = ::WinOpenWindowDC(GetWinHwnd(m_pCanvas));
hPS = ::WinBeginPaint( GetWinHwnd(m_pCanvas)
,NULLHANDLE
,&g_paintStruct
);
if(hPS)
{
- POINTL vPoint[2];
- LONG lControl;
- LONG lColor;
-
+ ::GpiAssociate(hPS, m_hDC);
m_hOldPS = m_hPS;
m_hPS = hPS;
::GpiCreateLogColorTable( m_hPS
);
}
- m_bIsPaintTime = TRUE;
- m_hDC = (WXHDC) -1; // to satisfy those anonizmous efforts
+ m_bIsPaintTime = true;
ms_cache.Add(new wxPaintDCInfo(m_pCanvas, this));
}
- SetBackground(wxBrush(m_pCanvas->GetBackgroundColour(), wxSOLID));
-}
+ InitDC();
+} // end of wxPaintDCImpl::wxPaintDCImpl
-wxPaintDC::~wxPaintDC()
+wxPaintDCImpl::~wxPaintDCImpl()
{
if ( m_hDC )
{
{
::WinEndPaint(m_hPS);
m_hPS = m_hOldPS;
- m_bIsPaintTime = FALSE;
- ms_cache.Remove(nIndex);
+ m_bIsPaintTime = false;
+ ms_cache.RemoveAt(nIndex);
}
//else: cached DC entry is still in use
}
}
-wxPaintDCInfo* wxPaintDC::FindInCache(
+wxPaintDCInfo* wxPaintDCImpl::FindInCache(
size_t* pIndex
) const
{
}
}
return pInfo;
-} // end of wxPaintDC::FindInCache
+} // end of wxPaintDCImpl::FindInCache
+// find the entry for this DC in the cache (keyed by the window)
+WXHDC wxPaintDCImpl::FindDCInCache(
+ wxWindow* pWin
+)
+{
+ wxPaintDCInfo* pInfo = NULL;
+ size_t nCache = ms_cache.GetCount();
+
+ for (size_t n = 0; n < nCache; n++)
+ {
+ pInfo = &ms_cache[n];
+ if (pInfo->m_hWnd == pWin->GetHWND())
+ {
+ return pInfo->m_hDC;
+ }
+ }
+ return 0;
+} // end of wxPaintDCImpl::FindInCache