]> Shamusworld >> Repos - architektonas/blob - src/trimaction.cpp
40ae9fe9b61388848f795d81e85c8053022733c4
[architektonas] / src / trimaction.cpp
1 // TrimAction.cpp: Action class for mirroring selected objects
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  08/27/2011  Created this file
12 //
13
14 #include "trimaction.h"
15 #include "applicationwindow.h"
16 #include "container.h"
17 #include "drawingview.h"
18 #include "geometry.h"
19 #include "line.h"
20 #include "mathconstants.h"
21 #include "painter.h"
22
23
24 enum { FIRST_POINT, NEXT_POINT };
25
26
27 TrimAction::TrimAction(): state(FIRST_POINT), t(0), u(1.0),
28         doc(&(ApplicationWindow::drawing->document))
29 //, line(NULL),
30 //      shiftWasPressedOnNextPoint(false), ctrlWasPressed(false),
31 //      mirror(new Container(Vector()))
32 {
33 //      ApplicationWindow::drawing->document.CopySelectedContentsTo(mirror);
34 //      mirror->Save();
35 }
36
37
38 TrimAction::~TrimAction()
39 {
40 }
41
42
43 /*virtual*/ void TrimAction::Draw(Painter * painter)
44 {
45         Object * obj = doc->lastObjectHovered;
46
47         if (obj == NULL)
48                 return;
49
50         // This assumes a Line, but it might not be!
51         painter->SetPen(QPen(Qt::black, 2.0, Qt::DotLine));
52         Vector v(((Line *)obj)->position, ((Line *)obj)->endpoint);
53         Point p1 = ((Line *)obj)->position + (v * t);
54         Point p2 = ((Line *)obj)->position + (v * u);
55         painter->DrawLine(p1, p2);
56 #if 0
57         if (state == FIRST_POINT)
58         {
59                 painter->DrawHandle(p1);
60         }
61         else
62         {
63                 Vector reflectedP2 = -(p2 - p1);
64                 Point newP2 = p1 + reflectedP2;
65                 painter->DrawLine(newP2, p2);
66                 painter->DrawHandle(p1);
67
68                 double absAngle = (Vector(p2 - p1).Angle()) * RADIANS_TO_DEGREES;
69
70                 // Keep the angle between 0 and 180 degrees
71                 if (absAngle > 180.0)
72                         absAngle -= 180.0;
73
74                 QString text = QChar(0x2221) + QObject::tr(": %1");
75                 text = text.arg(absAngle);
76
77                 if (ctrlWasPressed)
78                         text += " (Copy)";
79
80                 painter->DrawInformativeText(text);
81
82                 // Draw the mirror only if there's been a line to mirror around
83                 if (p1 != p2)
84                         mirror->Draw(painter);
85         }
86 #endif
87 }
88
89
90 /*virtual*/ void TrimAction::MouseDown(Vector point)
91 {
92 // this is not accurate enough. need to use the actual intersection point, not
93 // just the parameter(s).
94         Object * toTrim = doc->lastObjectHovered;
95
96         if (toTrim == NULL)
97                 return;
98
99 //it would be nice to do it like this, but if we bisect the object, we have to
100 //create an extra one...
101 //      toTrim->Trim(t, u);
102
103         Vector v(((Line *)toTrim)->position, ((Line *)toTrim)->endpoint);
104
105         // Check to see which case we have...
106         // We're trimming point #1...
107         if (t == 0)
108         {
109                 ((Line *)toTrim)->position = ((Line *)toTrim)->position + (v * u);
110 //              u = 1.0;
111         }
112         else if (u == 1.0)
113         {
114                 ((Line *)toTrim)->endpoint = ((Line *)toTrim)->position + (v * t);
115 //              t = 0;
116         }
117         else
118         {
119                 Point p1 = ((Line *)toTrim)->position + (v * t);
120                 Point p2 = ((Line *)toTrim)->position + (v * u);
121                 Point p3 = ((Line *)toTrim)->endpoint;
122                 ((Line *)toTrim)->endpoint = p1;
123                 Line * line = new Line(p2, p3);
124                 emit ObjectReady(line);
125 //              t = 0, u = 1.0;
126         }
127
128         doc->lastObjectHovered = NULL;
129 }
130
131
132 /*virtual*/ void TrimAction::MouseMoved(Vector point)
133 {
134 #if 0
135         if (state == FIRST_POINT)
136                 p1 = point;
137 //      else
138 //      {
139 //              p2 = point;
140 //              mirror->Restore();
141 //              mirror->Mirror(p1, p2);
142 //      }
143 #endif
144 //      Container & doc = ApplicationWindow::drawing->document;
145 //      int items = doc.ItemsSelected();
146         Object * toTrim = doc->lastObjectHovered;
147 //      double closestPt1 = 0, closestPt2 = 1.0;
148         t = 0, u = 1.0;
149
150         if (toTrim == NULL)
151                 return;
152
153         if (toTrim->type != OTLine)
154                 return;
155
156         double pointHoveredT = Geometry::ParameterOfLineAndPoint(((Line *)toTrim)->position, ((Line *)toTrim)->endpoint, point);
157
158         std::vector<Object *>::iterator i;
159
160         for(i=doc->objects.begin(); i!=doc->objects.end(); i++)
161         {
162                 // Can't trim against yourself... :-P
163                 if (*i == toTrim)
164                         continue;
165
166                 Object * trimAgainst = *i;
167                 double t1;//, u1;
168
169                 if ((toTrim->type != OTLine) || (trimAgainst->type != OTLine))
170                         continue;
171
172                 int intersects = Geometry::Intersects((Line *)toTrim, (Line *)trimAgainst, &t1);//, &u1);
173
174                 if (intersects)
175                 {
176                         // Now what? We don't know which side to trim!
177                         // ... now we do, we know which side of the Line we're on!
178                         if ((t1 > t) && (t1 < pointHoveredT))
179                                 t = t1;
180
181                         if ((t1 < u) && (t1 > pointHoveredT))
182                                 u = t1;
183                 }
184         }
185 }
186
187
188 /*virtual*/ void TrimAction::MouseReleased(void)
189 {
190 #if 0
191         if (state == FIRST_POINT)
192         {
193                 p2 = p1;
194                 state = NEXT_POINT;
195         }
196         else if (state == NEXT_POINT)
197         {
198                 if (!ctrlWasPressed)
199                 {
200                         state = FIRST_POINT;
201                         ApplicationWindow::drawing->document.MirrorSelected(p1, p2);
202
203                         mirror->Clear();
204                         ApplicationWindow::drawing->document.CopySelectedContentsTo(mirror);
205                         mirror->Save();
206                 }
207                 else
208                 {
209                         mirror->CopyContentsTo(&(ApplicationWindow::drawing->document));
210                 }
211         }
212 #endif
213 }
214
215
216 /*virtual*/ void TrimAction::KeyDown(int key)
217 {
218 #if 0
219         if ((key == Qt::Key_Shift) && (state == NEXT_POINT))
220         {
221                 shiftWasPressedOnNextPoint = true;
222                 p1Save = p1;
223                 p1 = p2;
224                 state = FIRST_POINT;
225                 emit NeedRefresh();
226         }
227         else if (key == Qt::Key_Control)
228         {
229                 ctrlWasPressed = true;
230                 emit NeedRefresh();
231         }
232 #endif
233         if ((t == 0) && (u == 1.0))
234                 return;
235
236         t = 0, u = 1.0;
237 }
238
239
240 /*virtual*/ void TrimAction::KeyReleased(int key)
241 {
242 #if 0
243         if ((key == Qt::Key_Shift) && shiftWasPressedOnNextPoint)
244         {
245                 shiftWasPressedOnNextPoint = false;
246                 p2 = p1;
247                 p1 = p1Save;
248                 state = NEXT_POINT;
249                 emit NeedRefresh();
250         }
251         else if (key == Qt::Key_Control)
252         {
253                 ctrlWasPressed = false;
254                 emit NeedRefresh();
255         }
256 #endif
257 }
258