#ifndef __WX_COCOA_DC_H__
#define __WX_COCOA_DC_H__
+class WXDLLEXPORT wxDC;
+WX_DECLARE_LIST(wxDC, wxCocoaDCStack);
+
//=========================================================================
// wxDC
//=========================================================================
{
DECLARE_DYNAMIC_CLASS(wxDC)
DECLARE_NO_COPY_CLASS(wxDC)
+//-------------------------------------------------------------------------
+// Initialization
+//-------------------------------------------------------------------------
public:
wxDC();
~wxDC();
+//-------------------------------------------------------------------------
+// wxCocoa specifics
+//-------------------------------------------------------------------------
+public:
static void CocoaInitializeTextSystem();
static void CocoaShutdownTextSystem();
- static wxDC *sm_focusedDC;
static WX_NSTextStorage sm_cocoaNSTextStorage;
static WX_NSLayoutManager sm_cocoaNSLayoutManager;
static WX_NSTextContainer sm_cocoaNSTextContainer;
-
+protected:
+// DC stack
+ static wxCocoaDCStack sm_cocoaDCStack;
+ virtual bool CocoaLockFocus();
+ virtual bool CocoaUnlockFocus();
+ bool CocoaUnwindStackAndTakeFocus();
+ inline bool CocoaTakeFocus()
+ {
+ wxCocoaDCStack::Node *node = sm_cocoaDCStack.GetFirst();
+ if(node && (node->GetData() == this))
+ return true;
+ return CocoaUnwindStackAndTakeFocus();
+ }
+ void CocoaUnwindStackAndLoseFocus();
+// DC flipping/transformation
+ void CocoaApplyTransformations();
+ float m_cocoaHeight;
+ bool m_cocoaFlipped;
+//-------------------------------------------------------------------------
+// Implementation
+//-------------------------------------------------------------------------
+public:
// implement base class pure virtuals
// ----------------------------------
virtual void DoDrawPolygon(int n, wxPoint points[],
wxCoord xoffset, wxCoord yoffset,
int fillStyle = wxODDEVEN_RULE);
-
};
#endif // __WX_COCOA_DC_H__
// Create a DC corresponding to a window
wxClientDC(wxWindow *win);
~wxClientDC(void);
+protected:
+// DC stack
+ virtual bool CocoaLockFocus();
+ virtual bool CocoaUnlockFocus();
};
class wxPaintDC: public wxWindowDC
// Create a DC corresponding to a window
wxPaintDC(wxWindow *win);
~wxPaintDC(void);
+protected:
+// DC stack
+ virtual bool CocoaLockFocus();
+ virtual bool CocoaUnlockFocus();
};
#endif // __WX_COCOA_DCCLIENT_H__
~wxMemoryDC(void);
virtual void SelectObject(const wxBitmap& bitmap);
virtual void DoGetSize(int *width, int *height) const;
+// DC stack
+ virtual bool CocoaLockFocus();
+ virtual bool CocoaUnlockFocus();
};
#endif // __WX_COCOA_DCMEMORY_H__
#import <AppKit/NSTypeSetter.h>
#import <AppKit/NSImage.h>
+#include <wx/listimpl.cpp>
+WX_DEFINE_LIST(wxCocoaDCStack);
+
IMPLEMENT_ABSTRACT_CLASS(wxDC, wxObject)
-wxDC *wxDC::sm_focusedDC = NULL;
WX_NSTextStorage wxDC::sm_cocoaNSTextStorage = nil;
WX_NSLayoutManager wxDC::sm_cocoaNSLayoutManager = nil;
WX_NSTextContainer wxDC::sm_cocoaNSTextContainer = nil;
+wxCocoaDCStack wxDC::sm_cocoaDCStack;
void wxDC::CocoaInitializeTextSystem()
{
[sm_cocoaNSTextStorage release]; sm_cocoaNSTextStorage = nil;
}
+void wxDC::CocoaUnwindStackAndLoseFocus()
+{
+ wxCocoaDCStack::Node *ourNode=sm_cocoaDCStack.Find(this);
+ if(ourNode)
+ {
+ wxCocoaDCStack::Node *node=sm_cocoaDCStack.GetFirst();
+ for(;node!=ourNode; node=sm_cocoaDCStack.GetFirst())
+ {
+ wxDC *dc = node->GetData();
+ wxASSERT(dc);
+ wxASSERT(dc!=this);
+ if(!dc->CocoaUnlockFocus())
+ {
+ wxFAIL_MSG("Unable to unlock focus on higher-level DC!");
+ }
+ sm_cocoaDCStack.DeleteNode(node);
+ }
+ wxASSERT(node==ourNode);
+ wxASSERT(ourNode->GetData() == this);
+ ourNode->GetData()->CocoaUnlockFocus();
+ sm_cocoaDCStack.DeleteNode(ourNode);
+ }
+}
+
+bool wxDC::CocoaUnwindStackAndTakeFocus()
+{
+ wxCocoaDCStack::Node *node=sm_cocoaDCStack.GetFirst();
+ for(;node;node = sm_cocoaDCStack.GetFirst())
+ {
+ wxDC *dc = node->GetData();
+ wxASSERT(dc);
+ // If we're on the stack, then it's unwound enough and we have focus
+ if(dc==this)
+ return true;
+ // If unable to unlockFocus (e.g. wxPaintDC) stop here
+ if(!dc->CocoaUnlockFocus())
+ break;
+ sm_cocoaDCStack.DeleteNode(node);
+ }
+ return CocoaLockFocus();
+}
+
wxDC::wxDC(void)
{
+ m_cocoaFlipped = false;
+ m_cocoaHeight = 0.0;
}
wxDC::~wxDC(void)
{
}
+bool wxDC::CocoaLockFocus()
+{
+ return false;
+}
+
+bool wxDC::CocoaUnlockFocus()
+{
+ return false;
+}
+
+void wxDC::CocoaApplyTransformations()
+{
+ // This transform flips the graphics since wxDC uses top-left origin
+ if(!m_cocoaFlipped)
+ {
+ // The transform is auto released
+ NSAffineTransform *transform = [NSAffineTransform transform];
+ /* x' = 1x + 0y + 0
+ y' = 0x + -1y + window's height
+ */
+ NSAffineTransformStruct matrix = {
+ 1, 0
+ , 0, -1
+ , 0, m_cocoaHeight
+ };
+ [transform setTransformStruct: matrix];
+ // Apply the transform
+ [transform concat];
+ }
+ // TODO: Apply scaling transformation
+}
+
void wxDC::DoDrawRectangle(wxCoord x, wxCoord y, wxCoord width, wxCoord height)
{
+ if(!CocoaTakeFocus()) return;
NSBezierPath *bezpath = [NSBezierPath bezierPathWithRect:NSMakeRect(x,y,width,height)];
[m_textForegroundColour.GetNSColor() set];
[bezpath stroke];
void wxDC::DoDrawLine(wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2)
{
+ if(!CocoaTakeFocus()) return;
NSBezierPath *bezpath = [NSBezierPath bezierPath];
[bezpath moveToPoint:NSMakePoint(x1,y1)];
[bezpath lineToPoint:NSMakePoint(x2,y2)];
void wxDC::DoDrawText(const wxString& text, wxCoord x, wxCoord y)
{
+ if(!CocoaTakeFocus()) return;
wxASSERT_MSG(sm_cocoaNSTextStorage && sm_cocoaNSLayoutManager && sm_cocoaNSTextContainer, "Text system has not been initialized. BAD PROGRAMMER!");
NSAttributedString *attributedString = [[NSAttributedString alloc]
initWithString:[NSString stringWithCString:text.c_str()]];
void wxDC::DoDrawBitmap(const wxBitmap &bmp, wxCoord x, wxCoord y, bool useMask)
{
+ if(!CocoaTakeFocus()) return;
if(!bmp.Ok())
return;
#include "wx/dcclient.h"
#include "wx/window.h"
+#include "wx/log.h"
#import <AppKit/NSView.h>
#import <AppKit/NSAffineTransform.h>
#import <AppKit/NSColor.h>
#import <AppKit/NSGraphicsContext.h>
#import <AppKit/NSBezierPath.h>
+#import <AppKit/NSWindow.h>
/*
* wxWindowDC
wxClientDC::~wxClientDC(void)
{
+ CocoaUnwindStackAndLoseFocus();
};
+bool wxClientDC::CocoaLockFocus()
+{
+ wxLogDebug("Locking focus on wxClientDC=%p, NSView=%p",this, m_window->GetNSView());
+ if([m_window->GetNSView() lockFocusIfCanDraw])
+ {
+ sm_cocoaDCStack.Insert(this);
+ m_cocoaFlipped = [m_window->GetNSView() isFlipped];
+ m_cocoaHeight = [m_window->GetNSView() bounds].size.height;
+ CocoaApplyTransformations();
+ return true;
+ }
+ wxLogDebug("focus lock failed!");
+ return false;
+}
+
+bool wxClientDC::CocoaUnlockFocus()
+{
+ wxLogDebug("Unlocking focus on wxClientDC=%p, NSView=%p",this, m_window->GetNSView());
+ [[m_window->GetNSView() window] flushWindow];
+ [m_window->GetNSView() unlockFocus];
+ return true;
+}
+
/*
* wxPaintDC
*/
{
m_window = window;
wxASSERT_MSG([NSView focusView]==window->GetNSView(), "PaintDC's NSView does not have focus. Please use wxPaintDC only as the first DC created in a paint handler");
- // This transform flips the graphics since wxDC uses top-left origin
- if(![window->GetNSView() isFlipped])
- {
- // The transform is auto released
- NSAffineTransform *transform = [NSAffineTransform transform];
- /* x' = 1x + 0y + 0
- y' = 0x + -1y + window's height
- */
- NSAffineTransformStruct matrix = {
- 1, 0
- , 0, -1
- , 0, [window->GetNSView() bounds].size.height
- };
- [transform setTransformStruct: matrix];
- // Apply the transform
- [transform concat];
- }
- // TODO: Apply scaling transformation
+ sm_cocoaDCStack.Insert(this);
+ m_cocoaFlipped = [window->GetNSView() isFlipped];
+ m_cocoaHeight = [window->GetNSView() bounds].size.height;
+ CocoaApplyTransformations();
};
wxPaintDC::~wxPaintDC(void)
{
+ CocoaUnwindStackAndLoseFocus();
};
+bool wxPaintDC::CocoaLockFocus()
+{
+ wxFAIL_MSG("wxPaintDC cannot be asked to lock focus!");
+ return false;
+}
+
+bool wxPaintDC::CocoaUnlockFocus()
+{
+ // wxPaintDC focus can never be unlocked.
+ return false;
+}
+
{
}
+bool wxMemoryDC::CocoaLockFocus()
+{
+ return false;
+}
+
+bool wxMemoryDC::CocoaUnlockFocus()
+{
+ return false;
+}
+
void wxMemoryDC::SelectObject( const wxBitmap& bitmap )
{
}