Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 760 lines (656 sloc) 22.629 kb
f423d9c Daigo Kawasaki First commit - copied from http://spokepov.cvs.sourceforge.net/viewvc/sp...
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 Daigo Kawasaki Added modifications by alendria here http://forums.adafruit.com/viewtopi...
CupNoodles authored
15 #include <wx/button.h>
f423d9c Daigo Kawasaki First commit - copied from http://spokepov.cvs.sourceforge.net/viewvc/sp...
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.