Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 760 lines (656 sloc) 22.629 kB
f423d9c @CupNoodles First commit - copied from http://spokepov.cvs.sourceforge.net/viewvc…
CupNoodles authored
1 #include <wx/frame.h>
2 #include <wx/log.h>
3 #include <wx/debug.h>
4 #include <wx/event.h>
5 #include <wx/dcclient.h>
6 #include <wx/brush.h>
7 #include <wx/dcbuffer.h>
8 #include <wx/math.h>
9 #include <wx/wfstream.h>
10 #include <wx/datstrm.h>
11 #include <wx/image.h>
12 #include <wx/sizer.h>
13 #include <wx/stattext.h>
14 #include <wx/msgdlg.h>
d4acac8 @CupNoodles Added modifications by alendria here http://forums.adafruit.com/viewt…
CupNoodles authored
15 #include <wx/button.h>
f423d9c @CupNoodles First commit - copied from http://spokepov.cvs.sourceforge.net/viewvc…
CupNoodles authored
16 #include "wheelpanel.h"
17 #include "globals.h"
18
19 WheelPanel::WheelPanel(wxWindow *parent, wxPanel *ctl, int num_leds, int hub_size) :
20 wxPanel(parent) {
21
22 this->hubsize = hub_size;
23 this->num_leds = num_leds;
24
25 origimg = NULL;
26
27 controlpanel = ctl;
28
29 model = new bool *[ROWS_PER_WHEEL];
30 for (int i=0; i<ROWS_PER_WHEEL; i++) {
31 model[i] = new bool[30];
32 for (int j=0; j<30; j++)
33 model[i][j] = false;
34 }
35
36 savedname = wxString("");
37 controlsizer = new wxBoxSizer(wxHORIZONTAL);
38 controlpanel->SetSizer(controlsizer);
39 //controlsizer->SetSizeHints(this);
40 Read = new wxButton(controlpanel, BUTTON_ID_READ, "Read from SpokePOV");
41 Read->Hide();
42 Write = new wxButton(controlpanel, BUTTON_ID_WRITE, "Write to SpokePOV");
43 Write->Hide();
44 Verify = new wxButton(controlpanel, BUTTON_ID_VERIFY, "Verify SpokePOV")
45 ;
46 Verify->Hide();
47
48 Done = new wxButton(controlpanel, BUTTON_ID_DONE, "Done adjusting import image");
49 Done->Hide();
50 Donetext = new wxStaticText(controlpanel, wxID_ANY, "You can now resize (drag the corner boxes) or move (use the 'hand' tool) the image around, when you're done, click here: ");
51 Donetext->Hide();
52
53 controlsizer->Add(Read, 1, wxEXPAND|wxALL|wxALIGN_LEFT|wxFIXED_MINSIZE, 15);
54 controlsizer->Add(Write, 1, wxEXPAND|wxALL|wxFIXED_MINSIZE, 15);
55 controlsizer->Add(Verify, 1, wxEXPAND|wxALL|wxALIGN_RIGHT|wxFIXED_MINSIZE, 15);
56 controlsizer->Add(Donetext, 1, wxEXPAND|wxALL|wxALIGN_LEFT, 10);
57 controlsizer->Add(Done, 0, wxEXPAND|wxALL|wxALIGN_RIGHT|wxFIXED_MINSIZE, 10);
58
59 setupRWVcontrols();
60 }
61
62
63 void WheelPanel::setupRWVcontrols(void) {
64 wxSetCursor(*wxSTANDARD_CURSOR);
65
66 //controlsizer->Detach(Done);
67 Done->Hide();
68 //controlsizer->Detach(Donetext);
69 Donetext->Hide();
70
71 Read->Show();
72 Write->Show();
73 Verify->Show();
74
75 controlsizer->Layout();
76
77 drawstate = NONE;
78 Refresh();
79 }
80
81 void WheelPanel::setupImageControl(void) {
82 Read->Hide();
83 Write->Hide();
84 Verify->Hide();
85
86 Donetext->Show();
87 Done->Show();
88
89 controlsizer->Layout();
90 }
91
92 void WheelPanel::OnPaint(wxPaintEvent& event) {
93 wxBufferedPaintDC dc(this);
94 Draw(&dc);
95 }
96
97
98 bool WheelPanel::GetModel(unsigned char buff[]) {
99 int t;
100 for (int i=0; i<ROWS_PER_WHEEL; i++) {
101 for (int j = 0; j<4; j++) {
102 t = 0;
103 for (int k=0; k<8; k++) {
104 t <<= 1;
105 if (! model[i][j*8+k]) {
106 t |= 0x1;
107 }
108 }
109 buff[i*4+j] = t;
110 }
111 }
112 return true;
113 }
114
115
116 bool WheelPanel::SetModel(unsigned char buff[1024]) {
117 int row, led;
118 for (int i=0; i<1024; i++) {
119 row = i/4;
120 for (int j = 0; j<8; j++) {
121 led = (i%4)*8+j;
122 if (buff[i] & (1<<(7-j)))
123 model[row][led] = false;
124 else
125 model[row][led] = true;
126 }
127 }
128 Refresh();
129 return true;
130 }
131
132 bool WheelPanel::LoadModel(wxString name) {
133 wxInputStream *fis = new wxFileInputStream(name);
134 if (fis->IsOk()) {
135 wxDataInputStream *dis = new wxDataInputStream(*fis);
136 int len = dis->Read32();
137 if (len != 8) {
138 wxMessageBox("Not a valid SpokePOV file!", "Invalid file", wxICON_HAND|wxOK);
139 return false;
140 }
141 fis->SeekI(0);
142 dis = new wxDataInputStream(*fis);
143 if (dis->ReadString() != "SpokePOV") { // identifier
144 wxMessageBox("Not a valid SpokePOV file!", "Invalid file", wxICON_HAND|wxOK);
145 return false;
146 }
147 int maj=dis->Read8();
148 int min=dis->Read8();
149 if ((maj != 1) &&
150 (min != 2)) {
151 wxMessageBox(wxString::Format("Found a file with version \"%d.%d\" which is not supported!", maj, min), "Wrong version",wxICON_HAND|wxOK);
152 return false;
153 }
154
155 int leds = dis->Read8(); // basically the size
156 if (leds != num_leds) {
157 wxMessageBox(wxString::Format("This file has %d linear pixels (LEDs), while this SpokePOV only supports %d leds", leds, num_leds), "File mismatch", wxICON_HAND|wxOK );
158 return false;
159 }
160
161 int pix = dis->Read16();
162 if (pix != ROWS_PER_WHEEL) {
163 wxMessageBox(wxString::Format("This file has %d radial pixels, while this SpokePOV only supports %d pixels", pix, ROWS_PER_WHEEL), "File mismatch", wxICON_HAND|wxOK);
164 return false;
165 }
166
167 for (int led = 0; led < num_leds; led++) {
168 for (int row = 0; row < ROWS_PER_WHEEL; row++) {
169 //wxLogDebug("%d %d", led, row);
170 if (dis->Read8() == 0) {
171 model[row][led] = false;
172 } else {
173 model[row][led] = true;
174 }
175 }
176 }
177 if (origimg)
178 delete origimg;
179 origimg = NULL;
180 delete dis;
181 delete fis;
182 Refresh();
183 savedname = name;
184 return true;
185 }
186 delete fis;
187 return false;
188 }
189
190 bool WheelPanel::ImportBMP(wxString name) {
191 if (origimg)
192 delete origimg;
193 origimg = new wxImage();
194 if (! origimg->LoadFile(name))
195 return false;
196 wxLogDebug("%d %d", origimg->GetWidth(), origimg->GetHeight());
197 origimg->ConvertToMono(0,0,0);
198 currimgpos = wxPoint(0,0);
199 currimg = origimg->Copy();
200 Refresh();
201
202 setupImageControl();
203
204 drawstate = IMAGEFOLLOW;
205 return true;
206 }
207
208 bool WheelPanel::SaveModel(void) {
209 wxOutputStream *fos = new wxFileOutputStream(savedname);
210 if (fos->IsOk()) {
211 wxDataOutputStream *dos = new wxDataOutputStream(*fos);
212
213 dos->WriteString("SpokePOV"); // identifier
214
215 dos->Write8(1); // version 1.2
216 dos->Write8(2);
217
218 dos->Write8(30); // basically the size
219 dos->Write16(ROWS_PER_WHEEL);
220
221 for (int led = 0; led < num_leds; led++) {
222 for (int row = 0; row < ROWS_PER_WHEEL; row++) {
223 //wxLogDebug("%d %d", led, row);
224 if (model[row][led])
225 dos->Write8(0xff);
226 else
227 dos->Write8(0);
228 }
229 }
230 delete fos;
231 return true;
232 }
233 delete fos;
234 return false;
235 }
236
237 void WheelPanel::Draw(wxDC *dc) {
238 // wxLogDebug("draw");
239 wxSize size = GetClientSize();
240
241 // clear background
242 //wxLogDebug("size: %d %d", size.x, size.y);
243 dc->Clear();
244 dc->SetBrush(*wxWHITE_BRUSH);
245 dc->DrawRectangle(0, 0, size.x, size.y);
246
247 if ((drawstate == IMAGEFOLLOW) || (drawstate == IMAGEMOVE)
248 || (drawstate == IMAGERESIZE_SE) || (drawstate == IMAGERESIZE_NE)
249 || (drawstate == IMAGERESIZE_SW) || (drawstate == IMAGERESIZE_NW)
250 ) {
251 wxPoint p;
252 for (int row=0; row < ROWS_PER_WHEEL; row++) {
253 for (int led=0; led<num_leds; led++) {
254 p = getXYPointForLED(led, row);
255 p -= currimgpos;
256 //wxLogDebug("Led %d Row %d xy: (%d, %d)", led, row, p.x, p.y);
257 if ((p.x >= currimg.GetWidth()) || (p.x < 0) ||
258 (p.y >= currimg.GetHeight()) || (p.y < 0))
259 model[row][30-num_leds+led] = 0;
260 else {
261 if (currimg.GetRed(p.x, p.y) == 0) {
262 model[row][30-num_leds+led] = 0xFF;
263 } else {
264 model[row][30-num_leds+led] = 0;
265 }
266 }
267 }
268 }
269 }
270
271 // draw background image
272 if (origimg != NULL) {
273 dc->DrawBitmap(wxBitmap(currimg,1), currimgpos.x, currimgpos.y);
274 //wxLogDebug("Drawing at %d,%d", currimgpos.x, currimgpos.y);
275 if ((drawstate == IMAGEFOLLOW) || (drawstate == IMAGEMOVE)
276 || (drawstate == IMAGERESIZE_SE) || (drawstate == IMAGERESIZE_NE)
277 || (drawstate == IMAGERESIZE_SW) || (drawstate == IMAGERESIZE_NW)) {
278 // draw bounding box
279 wxSize imgsize = wxSize(currimg.GetWidth(), currimg.GetHeight());
280 wxSize tabsize = wxSize(TABSIZE,TABSIZE);
281 dc->SetPen(wxPen(*wxBLACK, 1, wxSHORT_DASH));
282 dc->SetBrush(*wxTRANSPARENT_BRUSH);
283 dc->DrawRectangle(currimgpos, imgsize);
284
285 // draw tabs
286 dc->SetPen(wxPen(*wxBLACK, 1, wxSOLID));
287 dc->SetBrush(*wxBLACK_BRUSH);
288 dc->DrawRectangle(currimgpos, tabsize);
289 dc->DrawRectangle(currimgpos+imgsize-tabsize, tabsize);
290 dc->DrawRectangle(currimgpos+wxSize(0, currimg.GetHeight()-TABSIZE), tabsize);
291 dc->DrawRectangle(currimgpos+wxSize(currimg.GetWidth()-TABSIZE, 0), tabsize);
292 }
293 }
294 // setup variables
295 wxPoint middle = wxPoint(size.x/2, size.y/2);
296 float dDiameter = (size.x < size.y) ? size.x : size.y;
297 dDiameter /= (num_leds + hubsize);
298
299 // draw rings
300 dc->SetPen(*wxGREY_PEN);
301 dc->SetBrush(*wxTRANSPARENT_BRUSH);
302 for (int i=0; i<num_leds+1; i++) {
303 float diam = dDiameter * (hubsize+i);
304 dc->DrawCircle(middle.x, middle.y, (int)(diam/2));
305 }
306
307 // draw spokes
308 float innerringD = dDiameter*hubsize;
309 float outerringD = dDiameter*(num_leds+hubsize);
310 for (int rad=0; rad<ROWS_PER_WHEEL; rad++) {
311 float x1 = innerringD/2.0 * sin(2*PI * rad / (float)ROWS_PER_WHEEL);
312 float x2 = outerringD/2.0 * sin(2*PI * rad / (float)ROWS_PER_WHEEL);
313 float y1 = innerringD/2.0 * cos(2*PI * rad / (float)ROWS_PER_WHEEL);
314 float y2 = outerringD/2.0 * cos(2*PI * rad / (float)ROWS_PER_WHEEL);
315 dc->DrawLine(middle.x+(int)x1, middle.y+(int)y1, middle.x+(int)x2, middle.y+(int)y2);
316 }
317
318 // draw model
319 wxPen *pen = new wxPen(*wxRED, (int)(dDiameter/2), wxSOLID);
320 pen->SetCap(wxCAP_BUTT);
321 dc->SetPen(*pen);
322 /*
323 float dAngle = 360.0/ROWS_PER_WHEEL;
324 for (int led = 0; led < num_leds; led++) {
325 for (int row = 0; row < ROWS_PER_WHEEL; row++) {
326 //wxLogDebug("%d %d", led, row);
327 if (model[row][30-num_leds+led]) {
328 float startangle = 90.0 - ((row+1)*360.0/ROWS_PER_WHEEL);
329 float diam = (led+.5+hubsize) * dDiameter;
330 dc->DrawEllipticArc(int(size.x/2 - (diam/2) + .5),
331 int(size.y/2 - (diam/2) + .5),
332 int(diam), int(diam),
333 startangle,startangle+dAngle);
334 }
335 }
336 }
337 */
338 for (int led = 0; led < num_leds; led++) {
339 int row = 0;
340 while (row < ROWS_PER_WHEEL) {
341 while ((row < ROWS_PER_WHEEL) &&
342 (model[row++][30-num_leds+led] == 0));
343
344 if (row == ROWS_PER_WHEEL)
345 continue;
346
347 // ok time to mark
348
349 int start = row-1;
350 while ((row < ROWS_PER_WHEEL) &&
351 (model[row++][30-num_leds+led] != 0));
352 int end = row-1;
353 float startangle = 90.0 - ((start)*360.0/(ROWS_PER_WHEEL-1));
354 float endangle = 90.0 - ((end)*360.0/(ROWS_PER_WHEEL-1));
355 float diam = (led+.5+hubsize) * dDiameter;
356 dc->DrawEllipticArc(int(size.x/2 - (diam/2) + .5),
357 int(size.y/2 - (diam/2) + .5),
358 int(diam), int(diam),
359 endangle, startangle);
360 //wxLogDebug("LED %d start %f end %f", led, startangle, endangle);
361 }
362 }
363 }
364
365 void WheelPanel::OnChar(wxKeyEvent &event) {
366 shiftdown = event.ShiftDown();
367 event.Skip();
368 }
369
370 void WheelPanel::OnLeftUp(wxMouseEvent &event) {
371 if (HasCapture())
372 ReleaseMouse();
373
374 switch (drawstate) {
375 case DRAWING:
376 case ERASING:
377 drawstate = NONE;
378 break;
379 case IMAGEFOLLOW:
380 break;
381 case IMAGEMOVE:
382 case IMAGERESIZE_SE:
383 case IMAGERESIZE_NE:
384 case IMAGERESIZE_SW:
385 case IMAGERESIZE_NW:
386 drawstate = IMAGEFOLLOW;
387 break;
388 }
389 }
390
391 void WheelPanel::OnLeftDown(wxMouseEvent &event) {
392 CaptureMouse();
393 SetFocus();
394
395 wxPoint pos = event.GetPosition();
396
397 switch (drawstate) {
398 case IMAGEFOLLOW: {
399 // in the square?
400 if (! origimg)
401 return;
402 if ((pos.x >= currimgpos.x+10) && (pos.x <= currimgpos.x+currimg.GetWidth()-10) &&
403 (pos.y >= currimgpos.y+10) && (pos.y <= currimgpos.y+currimg.GetHeight()-10)) {
404 // start dragging!
405 drawstate = IMAGEMOVE;
406 imagemovepos = pos;
407 origimgpos = currimgpos;
408 //wxLogDebug("dragging from (%d, %d)", pos.x, pos.y);
409 } else if ((pos.x > currimgpos.x+currimg.GetWidth()-10) &&
410 (pos.x < currimgpos.x+currimg.GetWidth()) &&
411 (pos.y > currimgpos.y+currimg.GetHeight()-10) &&
412 (pos.y < currimgpos.y+currimg.GetHeight())) {
413 // in the south east corner
414 wxLogDebug("Resizing SE");
415 drawstate = IMAGERESIZE_SE;
416 imageresizepos = pos;
417 lastsize = wxSize(currimg.GetWidth(), currimg.GetHeight());
418 } else if ((pos.x >= currimgpos.x) && (pos.x < currimgpos.x+10) &&
419 (pos.y >= currimgpos.y) && (pos.y < currimgpos.y+10)) {
420 // north west
421 wxLogDebug("Resizing NW");
422 drawstate = IMAGERESIZE_NW;
423 origimgpos = currimgpos;
424 imagemovepos = imageresizepos = pos;
425 lastsize = wxSize(currimg.GetWidth(), currimg.GetHeight());
426 } else if ((pos.x >= currimgpos.x+currimg.GetWidth()-10) &&
427 (pos.x < currimgpos.x+currimg.GetWidth()) &&
428 (pos.y >= currimgpos.y) && (pos.y < currimgpos.y+10)) {
429 // north east
430 wxLogDebug("Resizing NE");
431 drawstate = IMAGERESIZE_NE;
432 origimgpos = currimgpos;
433 imagemovepos = imageresizepos = pos;
434 lastsize = wxSize(currimg.GetWidth(), currimg.GetHeight());
435 } else if ((pos.x > currimgpos.x) && (pos.x < currimgpos.x+10) &&
436 (pos.y > currimgpos.y+currimg.GetHeight()-10) &&
437 (pos.y < currimgpos.y+currimg.GetHeight())) {
438 // south west
439 wxLogDebug("Resizing SW");
440 drawstate = IMAGERESIZE_SW;
441 origimgpos = currimgpos;
442 imagemovepos = imageresizepos = pos;
443 lastsize = wxSize(currimg.GetWidth(), currimg.GetHeight());
444 }
445 break;
446 }
447 case NONE:
448 {
449 // hand editing
450 wxPoint polarcoord = getLEDForXYPoint(pos.x, pos.y);
451 int lednum = polarcoord.x;
452 int rownum = polarcoord.y;
453
454 //wxLogDebug("%d %d", lednum, rownum);
455 if ((lednum < 0) || (lednum > num_leds) ||
456 (rownum < 0) || (rownum > ROWS_PER_WHEEL))
457 return;
458
459 if (model[rownum][lednum] == false) {
460 model[rownum][lednum] = true;
461 drawstate = DRAWING;
462 } else {
463 model[rownum][lednum] = false;
464 drawstate = ERASING;
465 }
466 Refresh();
467 break;
468 }
469 }
470 }
471
472
473 void WheelPanel::OnMotion(wxMouseEvent &event) {
474
475
476 switch (drawstate) {
477 case NONE: {
478 #if defined(W32_NATIVE)
479 wxPoint polarcoord = getLEDForXYPoint(event.GetPosition().x, event.GetPosition().y);
480 if ((polarcoord.x >= 0) && (polarcoord.x < num_leds)) {
481 wxSetCursor(wxCursor(wxCURSOR_PENCIL));
482 } else {
483 wxSetCursor(*wxSTANDARD_CURSOR);
484 }
485 #endif
486 return;
487 }
488 case IMAGEFOLLOW: {
489 // not dragging
490 wxPoint pos = event.GetPosition();
491 // in the square?
492 if (! origimg)
493 return;
494
495 if ((pos.x >= currimgpos.x+10) && (pos.x <= currimgpos.x+currimg.GetWidth()-10) &&
496 (pos.y >= currimgpos.y+10) && (pos.y <= currimgpos.y+currimg.GetHeight()-10)) {
497 // change the cursor to hand
498 this->SetCursor(wxCursor(wxCURSOR_HAND));
499 } else if ( ((pos.x >= currimgpos.x) && (pos.x < currimgpos.x+10) &&
500 (pos.y >= currimgpos.y) && (pos.y < currimgpos.y+10)) ||
501 ((pos.x > currimgpos.x+currimg.GetWidth()-10) &&
502 (pos.x < currimgpos.x+currimg.GetWidth()) &&
503 (pos.y > currimgpos.y+currimg.GetHeight()-10) &&
504 (pos.y < currimgpos.y+currimg.GetHeight())) ){
505 // north west or south east
506 this->SetCursor(wxCursor(wxCURSOR_SIZENWSE));
507 } else if ( ((pos.x >= currimgpos.x+currimg.GetWidth()-10) &&
508 (pos.x < currimgpos.x+currimg.GetWidth()) &&
509 (pos.y >= currimgpos.y) && (pos.y < currimgpos.y+10)) ||
510 ((pos.x > currimgpos.x) && (pos.x < currimgpos.x+10) &&
511 (pos.y > currimgpos.y+currimg.GetHeight()-10) &&
512 (pos.y < currimgpos.y+currimg.GetHeight())) )
513 {
514 // North east or South West
515 this->SetCursor(wxCursor(wxCURSOR_SIZENESW));
516 } else {
517 this->SetCursor(*wxSTANDARD_CURSOR);
518 }
519 break;
520 }
521 case IMAGEMOVE: {
522 // set the current image position to follow
523 //wxLogDebug(" to (%d, %d)", event.GetPosition().x, event.GetPosition().y);
524 wxPoint testpos = origimgpos + event.GetPosition() - imagemovepos;
525
526 // dont let them move it off the screen!
527 if ((testpos.x < 0) && (testpos.x+currimg.GetWidth() < TABSIZE))
528 break;
529 if ((testpos.x > GetSize().GetWidth()-TABSIZE) && (testpos.x+currimg.GetWidth() > GetSize().GetWidth()))
530 break;
531 if ((testpos.y < 0) && (testpos.y+currimg.GetHeight() < TABSIZE))
532 break;
533 if ((testpos.y > GetSize().GetHeight()-TABSIZE) && (testpos.y+currimg.GetHeight() > GetSize().GetHeight()))
534 break;
535
536 // ok
537 currimgpos = origimgpos + event.GetPosition() - imagemovepos;
538 //wxLogDebug("@(%d, %d)",currimgpos.x, currimgpos.y);
539 Refresh();
540 break;
541 }
542 case IMAGERESIZE_SE: {
543 wxSize newsize = lastsize + wxSize(event.GetPosition().x, event.GetPosition().y) -
544 wxSize(imageresizepos.x, imageresizepos.y);
545
546 // is shift held down?
547 if (shiftdown) {
548 if (newsize.x > newsize.y)
549 newsize.x = newsize.y;
550 else
551 newsize.y = newsize.x;
552 }
553
554 //wxLogDebug("New size (%d, %d)", newsize.GetWidth(), newsize.GetHeight());
555
556 if ((currimgpos.x < 0) && (currimgpos.x+newsize.GetWidth() < TABSIZE))
557 break;
558 if ((currimgpos.y < 0) && (currimgpos.y+newsize.GetHeight() < TABSIZE ))
559 break;
560
561 if ((newsize.GetWidth() <= 0) || (newsize.GetHeight() <= 0))
562 break;
563 currimg = origimg->Scale(newsize.GetWidth(), newsize.GetHeight());
564 Refresh();
565 break;
566 }
567 case IMAGERESIZE_NE: {
568 wxSize newsize = lastsize + wxSize(event.GetPosition().x, -event.GetPosition().y) -
569 wxSize(imageresizepos.x, -imageresizepos.y);
570
571 int curry = origimgpos.y + event.GetPosition().y - imagemovepos.y;
572
573 // is shift held down?
574 if (shiftdown) {
575 if (newsize.x > newsize.y) {
576 newsize.x = newsize.y;
577 }
578 else {
579 curry = origimgpos.y + event.GetPosition().y + (newsize.y-newsize.x) - imagemovepos.y;
580 newsize.y = newsize.x;
581 }
582 }
583 // wxLogDebug("New size (%d, %d)", newsize.GetWidth(), newsize.GetHeight());
584
585 // dont let them move it off screen
586 if ((curry+newsize.GetHeight() > this->GetSize().GetHeight()) &&
587 (curry+TABSIZE > this->GetSize().GetHeight()))
588 break;
589 if ((origimgpos.x < 0) && (origimgpos.x+newsize.GetWidth()-TABSIZE < 0))
590 break;
591 // dont allow negative sizes
592 if ((newsize.GetWidth() <= 0) || (newsize.GetHeight() <= 0))
593 break;
594 // OK!
595 currimg = origimg->Scale(newsize.GetWidth(), newsize.GetHeight());
596 currimgpos.y = curry;
597 Refresh();
598 break;
599 }
600 case IMAGERESIZE_NW: {
601 wxSize newsize = lastsize - wxSize(event.GetPosition().x, event.GetPosition().y) +
602 wxSize(imageresizepos.x, imageresizepos.y);
603
604 int curry = origimgpos.y + event.GetPosition().y - imagemovepos.y;
605 int currx = origimgpos.x + event.GetPosition().x - imagemovepos.x;
606
607 // is shift held down?
608 if (shiftdown) {
609 if (newsize.x > newsize.y) {
610 currx = origimgpos.x + event.GetPosition().x + (newsize.x - newsize.y) - imagemovepos.x;
611 newsize.x = newsize.y;
612 } else {
613 curry = origimgpos.y + event.GetPosition().y + (newsize.y-newsize.x) - imagemovepos.y;
614 newsize.y = newsize.x;
615 }
616 }
617 //wxLogDebug("New size (%d, %d)", newsize.GetWidth(), newsize.GetHeight());
618
619 if ((curry+newsize.GetHeight() > this->GetSize().GetHeight()) &&
620 (curry+TABSIZE > this->GetSize().GetHeight()))
621 break;
622 if ((currx+newsize.GetWidth() > this->GetSize().GetWidth()) &&
623 (currx+TABSIZE > this->GetSize().GetWidth()))
624 break;
625
626
627 if ((newsize.GetWidth() <= 0) || (newsize.GetHeight() <= 0))
628 break;
629 currimg = origimg->Scale(newsize.GetWidth(), newsize.GetHeight());
630 currimgpos.x = currx; currimgpos.y = curry;
631 Refresh();
632 break;
633 }
634 case IMAGERESIZE_SW: {
635 wxSize newsize = lastsize + wxSize(-event.GetPosition().x, event.GetPosition().y) -
636 wxSize(-imageresizepos.x, imageresizepos.y);
637
638 int currx = origimgpos.x + event.GetPosition().x - imagemovepos.x;
639
640 // is shift held down?
641 if (shiftdown) {
642 if (newsize.x > newsize.y) {
643 currx = origimgpos.x + event.GetPosition().x + (newsize.x - newsize.y) - imagemovepos.x;
644 newsize.x = newsize.y;
645 }
646 else
647 newsize.y = newsize.x;
648 }
649 // wxLogDebug("New size (%d, %d)", newsize.GetWidth(), newsize.GetHeight());
650
651 // dont let them resize beyond the window
652
653 if ((currx+newsize.GetWidth() > this->GetSize().GetWidth()) &&
654 (currx+TABSIZE > this->GetSize().GetWidth()))
655 break;
656 if ((origimgpos.y < 0) && (origimgpos.y+newsize.GetHeight()-TABSIZE < 0))
657 break;
658
659 // dont allow negative size
660 if ((newsize.GetWidth() <= 0) || (newsize.GetHeight() <= 0))
661 break;
662 currimg = origimg->Scale(newsize.GetWidth(), newsize.GetHeight());
663 currimgpos.x = currx;
664 Refresh();
665 break;
666 }
667
668 case DRAWING:
669 case ERASING: {
670 #if defined(W32_NATIVE)
671 wxSetCursor(wxCursor(wxCURSOR_PENCIL));
672 #endif
673 wxPoint polar = getLEDForXYPoint(event.GetPosition().x, event.GetPosition().y);
674
675 int rownum = polar.y;
676 int lednum = polar.x;
677
678 if ((lednum < 0) || (lednum >= num_leds) || (rownum < 0) || (rownum >= ROWS_PER_WHEEL))
679 return;
680
681 if ((drawstate == DRAWING) && !model[rownum][lednum]) {
682 model[rownum][lednum] = true;
683 Refresh();
684 } else if ((drawstate == ERASING) && model[rownum][lednum]) {
685 model[rownum][lednum] = false;
686 Refresh();
687 }
688 break;
689 }
690 }
691 }
692
693 void WheelPanel::OnEraseBackGround(wxEraseEvent& event) {};
694
695
696
697 wxPoint WheelPanel::getXYPointForLED(int led, int row) {
698 wxSize size = GetClientSize();
699 int width = size.x; int height = size.y;
700
701 float dDiameter = (size.x < size.y) ? size.x : size.y;
702 dDiameter /= (num_leds + hubsize);
703
704 float radius = (led + .5 + hubsize)*dDiameter/2;
705 float startangle = ((row+.5) * 360.0)/ROWS_PER_WHEEL;
706 float angle = startangle * PI/180.0;
707
708 return wxPoint( int(sin(angle)*radius+(width/2)),int((height/2)-cos(angle)*radius));
709 }
710
711
712 wxPoint WheelPanel::getLEDForXYPoint(int x, int y) {
713 wxSize size = GetClientSize();
714 int lednum, rownum;
715 int width = size.x; int height = size.y;
716
717 float dDiameter = (size.x < size.y) ? size.x : size.y;
718 dDiameter /= (num_leds + hubsize);
719
720 // find led num by finding distance from point to middle
721 lednum = int(sqrt(pow((width/2 - x), 2) + pow((height/2 - y), 2) ) / (dDiameter / 2) - hubsize);
722
723 //find row by calculating angle
724 x -= width/2;
725 y -= height/2;
726
727 float radius = sqrt(pow(x, 2) + pow(y, 2) );
728 float angle = asin(x/radius) * 180/PI;
729
730 angle = ((int)angle + 360) % 360;
731 if ((x > 0) && (y > 0))
732 angle = 180 - angle;
733 if ((x < 0) && (y > 0))
734 angle = 360 - angle + 180;
735
736 rownum = int(angle / 360 * ROWS_PER_WHEEL);
737
738 return wxPoint(lednum, rownum);
739 }
740
741 wxString WheelPanel::GetSavedFilename(void) {
742 return wxString(savedname);
743 }
744
745 void WheelPanel::SetSavedFilename(wxString name) {
746 savedname = wxString(name);
747 }
748
749 BEGIN_EVENT_TABLE (WheelPanel, wxPanel)
750 EVT_PAINT(WheelPanel::OnPaint)
751 EVT_ERASE_BACKGROUND(WheelPanel::OnEraseBackGround)
752 EVT_LEFT_DOWN(WheelPanel::OnLeftDown)
753 EVT_LEFT_UP(WheelPanel::OnLeftUp)
754 EVT_MOTION(WheelPanel::OnMotion)
755
756 EVT_KEY_UP(WheelPanel::OnChar)
757 EVT_KEY_DOWN(WheelPanel::OnChar)
758
759 END_EVENT_TABLE()
Something went wrong with that request. Please try again.