// DrawItView.cpp : implementation of the CDrawItView class
//
#include "stdafx.h"
#pragma warning (disable:4786)
#include "DrawIt.h"
#include "DrawItDoc.h"
#include "DrawItView.h"
#include <algorithm>
#include <math.h>
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CDrawItView
IMPLEMENT_DYNCREATE(CDrawItView, CView)
BEGIN_MESSAGE_MAP(CDrawItView, CView)
//{{AFX_MSG_MAP(CDrawItView)
ON_WM_LBUTTONDOWN()
ON_WM_LBUTTONUP()
ON_WM_MOUSEMOVE()
ON_COMMAND(ID_EDIT_ABUSE, OnEditAbuse)
ON_COMMAND(ID_EDIT_ABUSE2, OnEditAbuse2)
ON_COMMAND_RANGE(ID_INSERT_LINE, ID_INSERT_ELLIPSE, OnInsertCommand)
ON_UPDATE_COMMAND_UI_RANGE(ID_INSERT_LINE, ID_INSERT_ELLIPSE, OnUpdateInsertCommand)
//}}AFX_MSG_MAP
// Standard printing commands
ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview)
ON_COMMAND(ID_VIEW_DRAWOBJECTS, OnViewDrawobjects)
ON_UPDATE_COMMAND_UI(ID_VIEW_DRAWOBJECTS, OnUpdateViewDrawobjects)
// ON_UPDATE_COMMAND_UI(ID_EDIT_UNDO, OnUpdateEditUndo)
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CDrawItView construction/destruction
CDrawItView::CDrawItView()
: m_spec(0)
, m_bDrawItems(true), m_openMouseTransaction(0)
{
// TODO: add construction code here
}
CDrawItView::~CDrawItView()
{
}
BOOL CDrawItView::PreCreateWindow(CREATESTRUCT& cs)
{
// TODO: Modify the Window class or styles here by modifying
// the CREATESTRUCT cs
return CView::PreCreateWindow(cs);
}
/////////////////////////////////////////////////////////////////////////////
// Helpers
class ViewApi : public DrawItAPI
{
public:
ViewApi(CDrawItDoc::Points& p, CDrawItDoc::ObjectRecord* r) : points(p), rec(r)
{
InitData();
}
virtual ~ViewApi() {}
CDrawItDoc::Points& points;
CDrawItDoc::ObjectRecord* rec;
DRAWDATA data;
// internal use
void ChangeRecord(CDrawItDoc::ObjectRecord* r)
{
rec = r;
InitData();
}
void InitData()
{
data.count_data = rec ? rec->second.size() : 0;
data.data = rec ? &rec->second[0] : 0;
}
// api methods
virtual unsigned long AddPoint(const POINT* where)
{
unsigned long id = points.size() + 1;
while (points.find(id) != points.end()) id = rand() % ((unsigned long)-1);
points[id] = *where;
InitData();
return id;
}
virtual void SetPoint(unsigned long id, const POINT* where)
{
points[id] = *where;
}
virtual const POINT* GetPoint(unsigned long id)
{
if (points.find(id) == points.end()) return NULL;
return &points[id];
}
virtual void RemovePoint(unsigned long id)
{
CDrawItDoc::Points::iterator i = points.find(id);
if (i == points.end()) return;
points.erase(i);
}
virtual unsigned long AddData(unsigned long d)
{
rec->second.push_back(d);
InitData();
return rec->second.size() - 1;
}
virtual void SetData(unsigned long id, unsigned long d)
{
rec->second[id] = d;
}
virtual void ResizeData(unsigned int count)
{
rec->second.resize(count);
}
};
struct DrawHelper
{
DrawHelper(HDC dc, CDrawItDoc::Points& pts)
: api(pts, NULL), hdc(dc)
{
}
void operator()(CDrawItDoc::Objects::value_type& rec)
{
const CDrawItDoc::TypeCode& c = rec.second.first;
const CDrawItDoc::ObjectData& d = rec.second.second;
api.ChangeRecord(&rec.second);
data.count_data = d.size();
data.data = data.count_data ? const_cast<unsigned long*>(&d[0]) : 0;
(*g_drawFunctions[c].draw)(&api, hdc, &data);
}
ViewApi api;
HDC hdc;
DRAWDATA data;
};
/////////////////////////////////////////////////////////////////////////////
// CDrawItView drawing and input
void CDrawItView::OnDraw(CDC* pDC)
{
if (!m_bDrawItems) return;
CDrawItDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
if (pDC->IsPrinting()) {
XFORM xform; ZeroMemory(&xform, sizeof(xform));
xform.eDx = xform.eDy = 0.0;
xform.eM11 = xform.eM22 = 5.0;
xform.eM12 = xform.eM21 = 0.0;
::SetGraphicsMode(pDC->m_hDC, GM_ADVANCED);
::SetWorldTransform(pDC->m_hDC, &xform);
}
if (pDoc->data->m_objects.size() > 0) {
DrawHelper helper(pDC->GetSafeHdc(), pDoc->data->m_points);
std::for_each(pDoc->data->m_objects.begin(), pDoc->data->m_objects.end(), helper);
}
}
/////////////////////////////////////////////////////////////////////////////
// CDrawItView printing
BOOL CDrawItView::OnPreparePrinting(CPrintInfo* pInfo)
{
// default preparation
return DoPreparePrinting(pInfo);
}
void CDrawItView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
// TODO: add extra initialization before printing
}
void CDrawItView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
// TODO: add cleanup after printing
}
/////////////////////////////////////////////////////////////////////////////
// CDrawItView diagnostics
#ifdef _DEBUG
void CDrawItView::AssertValid() const
{
CView::AssertValid();
}
void CDrawItView::Dump(CDumpContext& dc) const
{
CView::Dump(dc);
}
CDrawItDoc* CDrawItView::GetDocument() // non-debug version is inline
{
ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CDrawItDoc)));
return (CDrawItDoc*)m_pDocument;
}
#endif //_DEBUG
/////////////////////////////////////////////////////////////////////////////
// CDrawItView message handlers
void CDrawItView::OnLButtonDown(UINT nFlags, CPoint point)
{
Mm::SPACEID sid = GetDocument()->sid;
if (Mm::GetOpenTransactionId(sid) == 0) {
Mm::OpenTransaction(sid);
m_openMouseTransaction = Mm::GetOpenTransactionId(sid);
}
CDrawItDoc::Objects& objects = GetDocument()->data->m_objects;
CDrawItDoc::Points& points = GetDocument()->data->m_points;
unsigned long id = objects.size() + 1;
while (objects.find(id) != objects.end()) id = rand() % ((unsigned long)-1);
objects[id] = CDrawItDoc::ObjectRecord();
CDrawItDoc::ObjectRecord& r = objects[id];
r.first = m_spec;
ViewApi api(points, &r);
(*g_drawFunctions[r.first].create)(&api, &point, &api.data);
m_idCreating = id;
Invalidate();
CView::OnLButtonDown(nFlags, point);
}
void CDrawItView::OnLButtonUp(UINT nFlags, CPoint point)
{
Mm::SPACEID sid = GetDocument()->sid;
if (m_idCreating != 0 && Mm::GetOpenTransactionId(sid) != 0) {
CDrawItDoc::Objects& objects = GetDocument()->data->m_objects;
CDrawItDoc::Points& points = GetDocument()->data->m_points;
CDrawItDoc::ObjectRecord& r = objects[m_idCreating];
ViewApi api(points, &r);
(*g_drawFunctions[r.first].complete)(&api, &api.data);
}
m_idCreating = 0;
if (m_openMouseTransaction != 0 && Mm::GetOpenTransactionId(sid) == m_openMouseTransaction) {
Mm::CommitTransaction(sid);
}
m_openMouseTransaction = 0;
Invalidate();
CView::OnLButtonUp(nFlags, point);
}
void CDrawItView::OnMouseMove(UINT nFlags, CPoint point)
{
Mm::SPACEID sid = GetDocument()->sid;
if (Mm::GetOpenTransactionId(sid) != 0 && (nFlags & MK_LBUTTON) && m_idCreating != 0) {
CDrawItDoc::Objects& objects = GetDocument()->data->m_objects;
CDrawItDoc::Points& points = GetDocument()->data->m_points;
CDrawItDoc::ObjectRecord& r = objects[m_idCreating];
ViewApi api(points, &r);
(*g_drawFunctions[r.first].create)(&api, &point, &api.data);
Invalidate();
}
CView::OnMouseMove(nFlags, point);
}
void CDrawItView::OnEditAbuse()
{
Mm::SPACEID sid = GetDocument()->sid;
CDrawItDoc::Objects& objects = GetDocument()->data->m_objects;
CDrawItDoc::Points& points = GetDocument()->data->m_points;
for (unsigned int i = 0; i < 1000; ++i)
{
Mm::AutoTransaction txn(sid);
POINT p1, p2;
p1.x = rand() % 1000;
p1.y = rand() % 1000;
p2.x = p1.x + rand() % 100;
p2.y = p1.y + rand() % 100;
unsigned long id = objects.size() + 1;
while (objects.find(id) != objects.end()) id = rand() % ((unsigned long)-1);
objects[id] = CDrawItDoc::ObjectRecord();
CDrawItDoc::ObjectRecord& r = objects[id];
r.first = (rand() % 5);
ViewApi api(points, &r);
(*g_drawFunctions[r.first].create)(&api, &p1, &api.data);
(*g_drawFunctions[r.first].create)(&api, &p2, &api.data);
(*g_drawFunctions[r.first].complete)(&api, &api.data);
}
Invalidate();
}
void CDrawItView::OnEditAbuse2()
{
Mm::SPACEID sid = GetDocument()->sid;
CDrawItDoc::Objects& objects = GetDocument()->data->m_objects;
CDrawItDoc::Points& points = GetDocument()->data->m_points;
Mm::AutoTransaction txn(sid);
CDrawItDoc::ObjectRecord rec;
for (unsigned int i = 0; i < 1000; ++i)
{
POINT p1, p2;
p1.x = rand() % 1000;
p1.y = rand() % 1000;
p2.x = p1.x + rand() % 100;
p2.y = p1.y + rand() % 100;
unsigned long id = objects.size() + 1;
while (objects.find(id) != objects.end())
id = rand() % ((unsigned long)-1);
objects[id] = CDrawItDoc::ObjectRecord();
CDrawItDoc::ObjectRecord& r = objects[id];
r.first = (rand() % 5);
ViewApi api(GetDocument()->data->m_points, &r);
(*g_drawFunctions[r.first].create)(&api, &p1, &api.data);
(*g_drawFunctions[r.first].create)(&api, &p2, &api.data);
(*g_drawFunctions[r.first].complete)(&api, &api.data);
}
Invalidate();
}
void CDrawItView::OnInsertCommand(UINT id)
{
const CDrawItDoc::TypeCode spec = (CDrawItDoc::TypeCode)(id - ID_INSERT_LINE);
m_spec = spec;
}
void CDrawItView::OnUpdateInsertCommand(CCmdUI* pCmdUI)
{
Mm::SPACEID sid = GetDocument()->sid;
const CDrawItDoc::TypeCode spec = (CDrawItDoc::TypeCode)(pCmdUI->m_nID - ID_INSERT_LINE);
pCmdUI->Enable(TRUE);
pCmdUI->SetCheck(spec == m_spec ? TRUE : FALSE);
CString msg;
msg.Format("%d points, %d shapes : %d bytes free in %d chunks",
GetDocument()->data->m_points.size(),
GetDocument()->data->m_objects.size(),
Mm::FreeSpace(sid), Mm::FreeCount(sid));
GetParentFrame()->SetMessageText(msg);
}
void CDrawItView::OnViewDrawobjects()
{
m_bDrawItems = !m_bDrawItems;
Invalidate();
}
void CDrawItView::OnUpdateViewDrawobjects(CCmdUI *pCmdUI)
{
pCmdUI->SetCheck(m_bDrawItems ? 1 : 0);
}