]> Shamusworld >> Repos - architektonas/blob - src/circle.cpp
Added Architektonas drawing file loading/saving infrastructure.
[architektonas] / src / circle.cpp
1 // circle.cpp: Circle object
2 //
3 // Part of the Architektonas Project
4 // (C) 2011 Underground Software
5 // See the README and GPLv3 files for licensing and warranty information
6 //
7 // JLH = James Hammons <jlhamm@acm.org>
8 //
9 // WHO  WHEN        WHAT
10 // ---  ----------  ------------------------------------------------------------
11 // JLH  03/28/2011  Created this file
12 // JLH  09/26/2011  Added hover effects
13 // JLH  09/26/2011  Major cleanup of this class
14 //
15
16 #include "circle.h"
17
18 #include <QtGui>
19 #include "painter.h"
20
21
22 Circle::Circle(Vector p1, double r, Object * p/*= NULL*/): Object(p1, p), radius(r),
23         draggingEdge(false), draggingCenter(false), hitCenter(false), hitCircle(false)
24 {
25 }
26
27 Circle::~Circle()
28 {
29 }
30
31 /*virtual*/ void Circle::Draw(Painter * painter)
32 {
33         if (state == OSSelected || hitCircle || hitCenter)
34                 painter->SetPen(QPen(Qt::red, 2.0, Qt::DotLine));
35         else
36                 painter->SetPen(QPen(Qt::black, 1.0, Qt::SolidLine));
37
38         // Hatch/Fill...
39 //      QBrush brush(Qt::DiagCrossPattern);
40 //      brush.setColor(QColor(255, 255, 0));
41 //      painter->SetBrush(brush);
42         painter->SetBrush(QBrush(Qt::NoBrush));
43
44         // Draw the object...
45         painter->DrawEllipse(position, radius, radius);
46
47         // & draw handles (if needed)
48         if (state == OSSelected || hitCenter)
49                 painter->DrawHandle(position);
50
51         if (state == OSSelected && draggingEdge && objectWasDragged)
52                 painter->DrawHandle(dragPoint);
53 }
54
55 /*virtual*/ Vector Circle::Center(void)
56 {
57         return position;
58 }
59
60 /*virtual*/ bool Circle::Collided(Vector point)
61 {
62         // We can assume this, since this is a mouse down event here.
63         objectWasDragged = false;
64         HitTest(point);
65
66         draggingCenter = hitCenter;
67         draggingEdge = hitCircle;
68
69         if (hitCenter || hitCircle)
70         {
71                 dragPoint = point;
72                 oldState = state;
73                 state = OSSelected;
74                 return true;
75         }
76
77         // We didn't hit anything, so deselect this object and report failure to hit
78         state = OSInactive;
79         return false;
80 }
81
82 /*virtual*/ void Circle::PointerMoved(Vector point)
83 {
84         // Hit test tells us what we hit (if anything) through boolean variables. It
85         // also tells us whether or not the state changed.
86         needUpdate = HitTest(point);
87         objectWasDragged = (draggingEdge | draggingCenter);
88
89         if (draggingEdge)
90                 radius = Vector::Magnitude(point, position);
91         else if (draggingCenter)
92                 position = point;
93
94         // Save this point so the rendering code knows where to draw the handle...
95         dragPoint = point;
96 }
97
98 /*virtual*/ void Circle::PointerReleased(void)
99 {
100         // Mouse went up, so our dragging is done (if any *was* done, that is)
101         draggingEdge = draggingCenter = false;
102         hitCenter = hitCircle = false;
103
104         // If the object was dragged, then revert to the old state.
105         // Otherwise, we were probably just clicked, and want to stay in the selected state.
106         if (objectWasDragged)
107                 state = oldState;
108 }
109
110 bool Circle::HitTest(Point point)
111 {
112         SaveState();
113         hitCenter = hitCircle = false;
114         double length = Vector::Magnitude(position, point);
115 //printf("Circle::length = %lf, radius = %lf\n", length, radius);
116 //How to translate this into pixels from Document space???
117 //Maybe we need to pass a scaling factor in here from the caller? That would make sense, as
118 //the caller knows about the zoom factor and all that good kinda crap
119 /*
120 Document passes in the correct Cartesian coordinates being pointed to by the mouse.
121 So all we have to be concerned with is properly scaling our hot zones/handle sizes,
122 since we generally *don't* want those to scale with the zoom level. ;-)
123 */
124         if (length < 8.0)
125                 hitCenter = true;
126         else if ((length < (radius + 2.0)) && (length > (radius - 2.0)))
127                 hitCircle = true;
128
129         return StateChanged();
130 }
131
132 void Circle::SaveState(void)
133 {
134         oldHitCenter = hitCenter;
135         oldHitCircle = hitCircle;
136 }
137
138 bool Circle::StateChanged(void)
139 {
140         if ((hitCenter != oldHitCenter) || (hitCircle != oldHitCircle))
141                 return true;
142
143         return false;
144 }