1:/*
   2: * Programmins graphical user interfaces
   3: * Example: DiagramView.cpp
   4: * Jarkko Leponiemi 2003
   5: */
   6:
   7:#include "DiagramView.h"
   8:#include "Observable.h"
   9:
  10:DiagramView::DiagramView(Diagram *diagram)
  11:{
  12:  this->diagram = diagram;
  13:  this->diagram->AddObserver(this);
  14:  mode = 'S';
  15:  moving = NULL;
  16:}
  17:
  18:DiagramView::~DiagramView()
  19:{
  20:  this->diagram = NULL;
  21:}
  22:
  23:void DiagramView::Update(Observable *o, int type, void *args)
  24:{
  25:  InvalidateWindow();
  26:  UpdateWindow();
  27:  
  28:}
  29:
  30:void DiagramView::OnPaint(HDC hdc)
  31:{
  32:  const ConnectorList &clist = diagram->GetConnectors();
  33:  for (ConnectorList::const_iterator i = clist.begin(); i != clist.end(); ++i) {
  34:    Connector *c = *i;
  35:    Node *n1 = c->GetNode1();
  36:    Node *n2 = c->GetNode2();
  37:    ::MoveToEx(hdc, n1->GetX(), n1->GetY(), NULL);
  38:    ::LineTo(hdc, n2->GetX(), n2->GetY());
  39:  }
  40:  const NodeList &nlist = diagram->GetNodes();
  41:  RECT r;
  42:  for (NodeList::const_iterator j = nlist.begin(); j != nlist.end(); ++j) {
  43:    Node *n = *j;
  44:    GetNodeRect(hdc, n, &r);
  45:    ::Rectangle(hdc, r.left, r.top, r.right, r.bottom);
  46:    ::DrawText(hdc, n->GetTitle().c_str(), n->GetTitle().length(), &r, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
  47:  }
  48:}
  49:
  50:void DiagramView::OnKeyStroke(int vkey)
  51:{
  52:  if (vkey == 'S' || vkey == 'N' || vkey == 'C')
  53:    this->mode = vkey;
  54:}
  55:
  56:void DiagramView::OnMouse(UINT message, int x, int y, long modifiers)
  57:{
  58:  HDC hdc = ::GetDC(hWnd);
  59:  switch (message) {
  60:  case WM_LBUTTONDOWN:
  61:    if (mode == 'N') {
  62:      string title = "Untitled";
  63:      diagram->CreateNode(title, x, y);
  64:    } else {
  65:      ::SetCapture(hWnd);
  66:      moving = FindNodeInPoint(hdc, x, y);
  67:      if (moving != NULL && mode == 'S') {
  68:        ox = moving->GetX() - x;
  69:        oy = moving->GetY() - y;
  70:      } else if (moving != NULL && mode == 'C') {
  71:        ox = x;
  72:        oy = y;
  73:        DrawTempConnector(hdc);
  74:      }
  75:    }
  76:    break;
  77:  case WM_MOUSEMOVE:
  78:    if (moving != NULL) {
  79:      if (mode == 'S') {
  80:        diagram->MoveNode(moving, x + ox, y + oy);
  81:      } else if (mode == 'C') {
  82:        DrawTempConnector(hdc);
  83:        ox = x;
  84:        oy = y;
  85:        DrawTempConnector(hdc);
  86:      }
  87:    }
  88:    break;
  89:  case WM_LBUTTONUP:
  90:    ::ReleaseCapture();
  91:    if (moving != NULL && mode == 'C') {
  92:      DrawTempConnector(hdc);
  93:      Node *n = FindNodeInPoint(hdc, x, y);
  94:      if (n != NULL) {
  95:        diagram->CreateConnector(moving, n);
  96:      }
  97:    }
  98:    moving = NULL;
  99:  }
 100:  ::ReleaseDC(hWnd, hdc);
 101:}
 102:
 103:void DiagramView::GetNodeRect(HDC hdc, Node *n, RECT *r)
 104:{
 105:  ::SetRect(r, 0, 0, 0, 0);
 106:  ::DrawText(hdc, n->GetTitle().c_str(), n->GetTitle().length(), r, DT_SINGLELINE | DT_CENTER | DT_VCENTER | DT_CALCRECT);
 107:  int x = n->GetX(), y = n->GetY();
 108:  ::SetRect(r, x - r->right / 2 - 5, y - r->bottom / 2 - 5,
 109:    x + r->right / 2 + 5, y + r->bottom + 5);
 110:}
 111:
 112:Node *DiagramView::FindNodeInPoint(HDC hdc, int x, int y)
 113:{
 114:  Node *n = NULL;
 115:  RECT r;
 116:  POINT pt = {x, y};
 117:  const NodeList &nlist = diagram->GetNodes();
 118:  for (NodeList::const_iterator i = nlist.begin(); i != nlist.end(); ++i) {
 119:    Node *tmp = *i;
 120:    GetNodeRect(hdc, tmp, &r);
 121:    if (::PtInRect(&r, pt)) n = tmp;
 122:  }
 123:  return n;
 124:}
 125:
 126:void DiagramView::DrawTempConnector(HDC hdc)
 127:{
 128:  ::SetROP2(hdc, R2_NOT);
 129:  MoveToEx(hdc, moving->GetX(), moving->GetY(), NULL);
 130:  LineTo(hdc, ox, oy);
 131:}