]> Shamusworld >> Repos - architektonas/blob - src/circle.cpp
In the middle of refactoring objects for loading/saving.
[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
28 Circle::~Circle()
29 {
30 }
31
32
33 /*virtual*/ void Circle::Draw(Painter * painter)
34 {
35         if (state == OSSelected || hitCircle || hitCenter)
36                 painter->SetPen(QPen(Qt::red, 2.0, Qt::DotLine));
37         else
38                 painter->SetPen(QPen(Qt::black, 1.0, Qt::SolidLine));
39
40         // Hatch/Fill...
41 //      QBrush brush(Qt::DiagCrossPattern);
42 //      brush.setColor(QColor(255, 255, 0));
43 //      painter->SetBrush(brush);
44         painter->SetBrush(QBrush(Qt::NoBrush));
45
46         // Draw the object...
47         painter->DrawEllipse(position, radius, radius);
48
49         // & draw handles (if needed)
50         if (state == OSSelected || hitCenter)
51                 painter->DrawHandle(position);
52
53         if (state == OSSelected && draggingEdge && objectWasDragged)
54                 painter->DrawHandle(dragPoint);
55 }
56
57
58 /*virtual*/ Vector Circle::Center(void)
59 {
60         return position;
61 }
62
63
64 /*virtual*/ bool Circle::Collided(Vector point)
65 {
66         // We can assume this, since this is a mouse down event here.
67         objectWasDragged = false;
68         HitTest(point);
69
70         draggingCenter = hitCenter;
71         draggingEdge = hitCircle;
72
73         if (hitCenter || hitCircle)
74         {
75                 dragPoint = point;
76                 oldState = state;
77                 state = OSSelected;
78                 return true;
79         }
80
81         // We didn't hit anything, so deselect this object and report failure to hit
82         state = OSInactive;
83         return false;
84 }
85
86
87 /*virtual*/ void Circle::PointerMoved(Vector point)
88 {
89         // Hit test tells us what we hit (if anything) through boolean variables. It
90         // also tells us whether or not the state changed.
91         needUpdate = HitTest(point);
92         objectWasDragged = (draggingEdge | draggingCenter);
93
94         if (draggingEdge)
95                 radius = Vector::Magnitude(point, position);
96         else if (draggingCenter)
97                 position = point;
98
99         // Save this point so the rendering code knows where to draw the handle...
100         dragPoint = point;
101 }
102
103
104 /*virtual*/ void Circle::PointerReleased(void)
105 {
106         // Mouse went up, so our dragging is done (if any *was* done, that is)
107         draggingEdge = draggingCenter = false;
108         hitCenter = hitCircle = false;
109
110         // If the object was dragged, then revert to the old state.
111         // Otherwise, we were probably just clicked, and want to stay in the selected state.
112         if (objectWasDragged)
113                 state = oldState;
114 }
115
116
117 bool Circle::HitTest(Point point)
118 {
119         SaveState();
120         hitCenter = hitCircle = false;
121         double length = Vector::Magnitude(position, point);
122 //printf("Circle::length = %lf, radius = %lf\n", length, radius);
123 //How to translate this into pixels from Document space???
124 //Maybe we need to pass a scaling factor in here from the caller? That would make sense, as
125 //the caller knows about the zoom factor and all that good kinda crap
126 /*
127 Document passes in the correct Cartesian coordinates being pointed to by the mouse.
128 So all we have to be concerned with is properly scaling our hot zones/handle sizes,
129 since we generally *don't* want those to scale with the zoom level. ;-)
130 */
131         if (length < 8.0)
132                 hitCenter = true;
133         else if ((length < (radius + 2.0)) && (length > (radius - 2.0)))
134                 hitCircle = true;
135
136         return StateChanged();
137 }
138
139
140 void Circle::SaveState(void)
141 {
142         oldHitCenter = hitCenter;
143         oldHitCircle = hitCircle;
144 }
145
146
147 bool Circle::StateChanged(void)
148 {
149         if ((hitCenter != oldHitCenter) || (hitCircle != oldHitCircle))
150                 return true;
151
152         return false;
153 }
154
155
156 /*virtual*/ void Circle::Enumerate(FILE * file)
157 {
158         fprintf(file, "CIRCLE (%lf,%lf) %lf\n", position.x, position.y, radius);
159 }
160