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:}