📄 transitionarrow.c
字号:
//////////////////////////////////////////////////////////////////////////////////// This file is part of Toolkit for Conceptual Modeling (TCM).// (c) copyright 1996, Vrije Universiteit Amsterdam.// Author: Frank Dehne (frank@cs.vu.nl).//// TCM is free software; you can redistribute it and/or modify// it under the terms of the GNU General Public License as published by// the Free Software Foundation; either version 2 of the License, or // (at your option) any later version.//// TCM is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the// GNU General Public License for more details.//// You should have received a copy of the GNU General Public License// along with TCM; if not, write to the Free Software// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA// 02111-1307, USA.////////////////////////////////////////////////////////////////////////////////#include "grafport.h"#include "inputfile.h"#include "outputfile.h"#include <math.h>#include <stdlib.h>#include "transition.h"#include "transitionarrow.h"#include "diagramviewer.h" const int TransitionArrow::HLINELEN = 20;const int TransitionArrow::HLINEXOFFSET = 4;const int TransitionArrow::HLINEYOFFSET = 2;const int TransitionArrow::HLINEDIST = 10;TransitionArrow::TransitionArrow(ShapeView *v, Grafport *g, GShape *node1, GShape *node2, List<Point *> *aline, bool Curved): Line(v, g, node1, node2, aline, Curved) { event = new TextShape(v, g, this); event->SetAlignment(TextAlign::LEFT); event->SetDescription("Event"); actions = new List<TextShape *>; separator = RIGHT; CalcPosition(); SetEnd2(LineEnd::FILLED_ARROW);}TransitionArrow::TransitionArrow(ShapeView *v, Grafport *g, GShape *node1, GShape *node2, bool Curved): Line(v, g, node1, node2, Curved) { event = new TextShape(v, g, this); event->SetAlignment(TextAlign::LEFT); event->SetDescription("Event"); actions = new List<TextShape *>; separator = RIGHT; SetEnd2(LineEnd::FILLED_ARROW);}TransitionArrow::TransitionArrow(const TransitionArrow &aline): Line(aline) { hlineFrom = aline.hlineFrom; hlineTo = aline.hlineTo; anchorPoint = aline.anchorPoint; separator = aline.separator; event = new TextShape(*(TextShape *)(aline.event)); event->SetParent(this); actions = new List<TextShape *>; for (aline.actions->first(); !aline.actions->done(); aline.actions->next()) { TextShape *a = aline.actions->cur(); TextShape *b = new TextShape (*a); b->SetParent(this); actions->add(b); }}TransitionArrow::~TransitionArrow() { delete event; actions->clear(); delete actions;}void TransitionArrow::DrawShape() { Line::DrawShape(); event->Draw(); SetDrawAttributes(); GetGrafport()->DrawLine(hlineFrom.x, hlineFrom.y, hlineTo.x, hlineTo.y); for (actions->first(); !actions->done(); actions->next()) actions->cur()->Draw();}void TransitionArrow::UpdateAnchor(const Point *p, const Point *t) { Point pt = anchorPoint; if (IsCurved()) { pt.y += p->y; pt.x += p->x; } else if (separator == LEFT || separator == RIGHT) { // find segment where the anchor point is located. // (void) GetLine(pt.x, pt.y); pt.y += p->y; // shift left <-> RIGHT ? Point dp = *t + *p; if (dp.x < anchorPoint.x) separator = LEFT; else separator = RIGHT; } else { pt.x += p->x; // shift up <-> down ? Point dp = *t + *p; if (dp.y < anchorPoint.y) separator = UP; else separator = DOWN; } Undraw(); if (IsCurved()) anchorPoint = pt; else if (separator == LEFT || separator == RIGHT) { int cx, cy; // make anchorpoint a point on the line. (void) ContainsPtLine(pt.x, pt.y, (*GetLine())[GetLineNumber()-1], (*GetLine())[GetLineNumber()], cx, cy); anchorPoint = Point(cx, cy); } else anchorPoint = pt; CalcHLinePart(); Draw();}void TransitionArrow::CalcPosition() { Line::CalcPosition(); anchorPoint = *GetPosition(); CalcSeparator(); CalcHLinePart();}void TransitionArrow::CalcHLinePart() { CalcPositionHLine(); CalcPositionEvent(); CalcPositionActions();}void TransitionArrow::CalcSeparator() { double alpha; if (GetWidth() != 0) alpha = atan((double)GetHeight()/(double)GetWidth()); else alpha = 2*atan(1); // estimation. // if (fabs(alpha) > 0.5*atan(1)) { if (fabs(alpha) > atan(1)) { if (separator == UP || separator == DOWN) separator = RIGHT; } else { if (separator == LEFT || separator == RIGHT) separator = UP; }}void TransitionArrow::CalcPositionHLine() { int d1 = HLineLength(); if (separator == RIGHT) { // attach right to line. hlineFrom = anchorPoint; hlineTo = Point(hlineFrom.x + d1, hlineFrom.y); } else if (separator == LEFT) { // attach left to line. hlineTo = anchorPoint; hlineFrom = Point(hlineTo.x - d1, hlineTo.y); } else { // put above/below the line. double alpha = atan((double)GetHeight()/(double)GetWidth()); if (separator == UP) { int d2 = (int)(cos(alpha)*max(HLINEDIST, HLINEYOFFSET+actions->count()*GetName()->GetFontHeight())); d2 += HLINEYOFFSET; hlineFrom = Point(anchorPoint.x - d1/2, anchorPoint.y - d2); hlineTo = Point(anchorPoint.x + d1/2, anchorPoint.y - d2); } else { // separator == DOWN int textHeight = max(GetName()->GetFontHeight(), event->GetStringHeight()); int d2 = (int)(cos(alpha)*max(HLINEDIST,HLINEYOFFSET+ textHeight)); d2 += HLINEYOFFSET; hlineFrom = Point(anchorPoint.x - d1/2, anchorPoint.y + d2); hlineTo = Point(anchorPoint.x + d1/2, anchorPoint.y + d2); } } hlineFrom = Point(max(3,hlineFrom.x), max(3,hlineFrom.y)); hlineTo = Point(max(3,hlineTo.x), max(3,hlineTo.y)); }void TransitionArrow::CalcPositionEvent() { Point pt; const string *s = event->GetString(); if (*s != "") { pt.x = hlineFrom.x + event->GetStringWidth()/2; pt.y = hlineFrom.y - event->GetStringHeight()/2; pt.y -= 2*HLINEYOFFSET; } else { pt.x = (hlineFrom.x + hlineTo.x)/2; pt.y = hlineFrom.y - event->GetFontHeight()/2; } pt.x += HLINEXOFFSET; event->SetPosition(&pt);}void TransitionArrow::CalcPositionActions() { Point pt; int w, h; int textHeight = GetName()->GetFontHeight(); pt = hlineFrom; pt.y += HLINEYOFFSET + textHeight/2; for (actions->first(); !actions->done(); actions->next()) { w = actions->cur()->GetStringWidth(); h = actions->cur()->GetStringHeight(); pt.x = hlineFrom.x + w/2 + HLINEXOFFSET; actions->cur()->SetPosition(&pt); pt.y += textHeight; }}void TransitionArrow::UpdateEvent(const string *c) { if (IsVisible()) Undraw(); event->SetString(c); CalcHLinePart(); if (IsVisible()) Draw();}void TransitionArrow::UpdateAction(const string *s, unsigned n, bool update) { if (IsVisible()) Undraw(); SetAction(s, n, update); CalcHLinePart(); if (IsVisible()) Draw();}void TransitionArrow::SetSelect(bool set) { Line::SetSelect(set);}bool TransitionArrow::ContainsPt(int x, int y) { if (Line::ContainsPt(x,y)) return True; else return HitHLine(x, y);}bool TransitionArrow::HitHLine(int x, int y) { // point near horizontal line ? int textHeight = GetName()->GetFontHeight(); return (x >= hlineFrom.x && x <= hlineTo.x && y >= hlineFrom.y - textHeight && y <= hlineFrom.y + textHeight);}int TransitionArrow::HLineLength() { int max = HLINELEN; int n = event->GetStringWidth()+HLINEXOFFSET; if (n > max) max = n; for (actions->first(); !actions->done(); actions->next()) { n = actions->cur()->GetStringWidth()+HLINEXOFFSET; if (n > max) max = n; } return max;}bool TransitionArrow::InTextArea(int x, int y) { if (Line::InTextArea(x,y)) return True; else if (event->ContainsPt(x, y)) return True; for (actions->first(); !actions->done(); actions->next()) { if (actions->cur()->ContainsPt(x, y)) return True; } return False;}TextShape *TransitionArrow::HitTextShape(int x, int y) { if (event->ContainsPt(x, y)) return event; for (actions->first(); !actions->done(); actions->next()) { if (actions->cur()->ContainsPt(x, y)) return actions->cur(); } return 0;}TextShape *TransitionArrow::ChooseTextShape(int x, int y) { // This is the winner of the "clumsiest function award". int textHeight = GetName()->GetFontHeight(); // hit event string. if (event->ContainsPt(x, y)) return event; // hit action string. if (actions->first()) { // action text shapes can overlap // make sure that you choose the right one. do { int pt_y = actions->cur()->GetTopMost(); pt_y += textHeight; if (actions->cur()->ContainsPt(x,y) && y <= pt_y) { // return the action. TextShape *t = actions->cur(); return t; } // pt_y += textHeight; } while (actions->next()); if (actions->last()) { if (actions->cur()->ContainsPt(x,y)) return actions->cur(); } } // hit hline part ? if (HitHLine(x, y)) { if (y <= hlineFrom.y) { // above line -> return event. Point pt = *event->GetPosition();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -