1
2 /*
3 * This file is part of a wxSmith plugin for Code::Blocks Studio
4 * Copyright (C) 2007 Bartlomiej Swiecki
5 *
6 * wxSmith is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * wxSmith and this file is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with wxSmith; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
19 *
20 * Ron Collins
21 * rcoll@theriver.com
22 * 4-Feb-2010
23 *
24 */
25
26 #include "wxSpeedButton.h"
27
28
29 // ==========================================================================
30 // wxSpeedButton
31 // ==========================================================================
32 IMPLEMENT_DYNAMIC_CLASS( wxSpeedButton, wxControl )
33
34 BEGIN_EVENT_TABLE(wxSpeedButton,wxControl)
35 EVT_MOUSE_EVENTS ( wxSpeedButton::OnMouseEvents )
36 EVT_PAINT ( wxSpeedButton::OnPaint )
37 EVT_SIZE ( wxSpeedButton::OnSize )
38 EVT_SET_FOCUS ( wxSpeedButton::OnSetFocus )
39 EVT_KILL_FOCUS ( wxSpeedButton::OnKillFocus )
40 EVT_CHAR ( wxSpeedButton::OnKey )
41 END_EVENT_TABLE()
42
43
44 //------------------------------------------------------------------------------
45 // book-keeping data for a series of speed-buttons
46
47 static int sbgCount = 0; // number of speed-buttons created
48 static wxArrayPtrVoid sbgArray; // list of defined buttones
49
50 //------------------------------------------------------------------------------
51
~wxSpeedButton()52 wxSpeedButton::~wxSpeedButton() {
53 int n;
54
55 // release the mouse
56
57 // if (HasCapture()) ReleaseMouse();
58
59 // erase entry in master array
60
61 n = sbgArray.Index((void *) this);
62 if (n != wxNOT_FOUND) sbgArray.RemoveAt(n);
63
64 }
65
66 //------------------------------------------------------------------------------
67 // the basic contructor
68
wxSpeedButton(wxWindow * inParent,wxWindowID inID,const wxString & inLabel,const wxBitmap & inGlyph,int inGlyphCount,int inMargin,int inGroupIndex,bool inAllowAllUp,const wxPoint & inPos,const wxSize & inSize,long inStyle,const wxValidator & inVal,const wxString & inName)69 wxSpeedButton::wxSpeedButton( wxWindow *inParent, // parent window
70 wxWindowID inID, // id of this button
71 const wxString &inLabel, // button text
72 const wxBitmap &inGlyph, // bitmaps displayed on button
73 int inGlyphCount, // number of images in inGlyph
74 int inMargin, // area around image and tex
75 int inGroupIndex, // ident of a group of buttons
76 bool inAllowAllUp, // allow all buttons up
77 const wxPoint &inPos, // button position
78 const wxSize &inSize, // button size
79 long inStyle, // border styles
80 const wxValidator &inVal, // validator
81 const wxString &inName) { // name of button
82
83 Create( inParent, inID,
84 inLabel,
85 inGlyph, inGlyphCount, inMargin,
86 inGroupIndex, inAllowAllUp,
87 inPos, inSize, inStyle, inVal, inName);
88 }
89
90 //------------------------------------------------------------------------------
91 // a constructor that creates a bitmap from a filename
92
wxSpeedButton(wxWindow * inParent,wxWindowID inID,const wxString & inLabel,const wxString & inGlyphFile,int inGlyphCount,int inMargin,int inGroupIndex,bool inAllowAllUp,const wxPoint & inPos,const wxSize & inSize,long inStyle,const wxValidator & inVal,const wxString & inName)93 wxSpeedButton::wxSpeedButton( wxWindow *inParent, // parent window
94 wxWindowID inID, // id of this button
95 const wxString &inLabel, // button text
96 const wxString &inGlyphFile, // bitmaps displayed on button
97 int inGlyphCount, // number of images in inGlyph
98 int inMargin, // area around image and tex
99 int inGroupIndex, // ident of a group of buttons
100 bool inAllowAllUp, // allow all buttons up
101 const wxPoint &inPos, // button position
102 const wxSize &inSize, // button size
103 long inStyle, // border styles
104 const wxValidator &inVal, // validator
105 const wxString &inName) { // name of button
106 wxBitmap bmp(inGlyphFile, wxBITMAP_TYPE_ANY );
107
108 Create( inParent, inID,
109 inLabel,
110 bmp, inGlyphCount, inMargin,
111 inGroupIndex, inAllowAllUp,
112 inPos, inSize, inStyle, inVal, inName);
113 }
114
115
116
117 //------------------------------------------------------------------------------
118
Create(wxWindow * inParent,wxWindowID inID,const wxString & inLabel,const wxBitmap & inGlyph,int inGlyphCount,int inMargin,int inGroupIndex,bool inAllowAllUp,const wxPoint & inPos,const wxSize & inSize,long inStyle,const wxValidator & inVal,const wxString & inName)119 bool wxSpeedButton::Create( wxWindow *inParent, // parent window
120 wxWindowID inID, // id of this button
121 const wxString &inLabel, // button text
122 const wxBitmap &inGlyph, // bitmaps displayed on button
123 int inGlyphCount, // number of images in inGlyph
124 int inMargin, // area around image and tex
125 int inGroupIndex, // ident of a group of buttons
126 bool inAllowAllUp, // allow all buttons up
127 const wxPoint &inPos, // button position
128 const wxSize &inSize, // button size
129 long inStyle, // border styles
130 const wxValidator &inVal, // validator
131 const wxString &inName) { // name of button
132
133 int n;
134 wxString name;
135 wxPoint pos;
136 wxSize size;
137 wxString s;
138
139 // make sure we can load images
140
141 wxInitAllImageHandlers();
142
143 // one more button
144
145 sbgCount += 1;
146
147 // make a default name
148
149 name = inName;
150 name.Trim(true);
151 name.Trim(false);
152 if (name.Len() == 0) name.Printf(_T("SpeedButton-%d"), sbgCount);
153
154 // the position
155
156 pos = inPos;
157 if (pos.x < 0) pos.x = 0;
158 if (pos.y < 0) pos.y = 0;
159
160 // the size - default size is 72 x 24
161
162 size = inSize;
163 size.SetDefaults(wxSize(72, 24));
164
165 // fix the alignment -- default to BU_LEFT
166 // clear border styles and make sure we clip children
167
168 n = inStyle;
169 n = n & (~ wxBORDER_MASK);
170 n = n | wxBORDER_NONE;
171 n = n | wxCLIP_CHILDREN;
172
173 if (((n & wxBU_LEFT) == 0) &&
174 ((n & wxBU_TOP) == 0) &&
175 ((n & wxBU_RIGHT) == 0) &&
176 ((n & wxBU_BOTTOM) == 0))
177 n = n | wxBU_LEFT;
178
179 // make the control, make sure we clip children
180
181 if (! wxControl::Create(inParent, inID, pos, size, n, inVal, name)) return false;
182
183 // basic stuff for any control
184
185 wxControl::SetLabel(inLabel);
186 wxControl::SetBackgroundColour(inParent->GetBackgroundColour());
187 wxControl::SetForegroundColour(inParent->GetForegroundColour());
188 wxControl::SetFont(inParent->GetFont());
189
190 // extract bitmaps
191
192 SplitGlyphs(inGlyph, inGlyphCount);
193
194 // the blank space around images and text
195
196 mMargin = inMargin;
197 if (mMargin < 0) mMargin = 0;
198
199 // ID for a group of buttons
200
201 mGroupIndex = inGroupIndex;
202 mAllowAllUp = inAllowAllUp;
203
204 // no button down yet
205
206 mMouseDown = false;
207 mMouseOver = false;
208 mButtonDown = false;
209 mButtonFocused = false;
210
211 // the is a small chance that CalcLayout could be called recursively
212
213 mCalcBusy = false;
214
215 // keep track of our parent, and the top-most parent
216
217 mParent = GetParent();
218 mTopParent = mParent;
219 while ((mTopParent != NULL) && (! mTopParent->IsKindOf(CLASSINFO(wxTopLevelWindow))))
220 mTopParent = mTopParent->GetParent();
221
222 // no user data yet
223
224 mUserData = 0;
225
226 // add this button to the master list
227
228 sbgArray.Add((void *) this);
229
230 // draw it
231
232 Refresh(false);
233
234 // done
235
236 return true;
237 }
238
239 //------------------------------------------------------------------------------
240 // given an input bitmap, make 3 glyphs from it:
241 // the input bitmap may be empty (no glyphs),
242 // with 1 image, make UP glyph, DOWN glyph, DISABLED glyph
243 // with 2 images, the first image is UP and DOWN glyphs, the 2nd image is DISABLED glyph
244 // with 3 images, each image is a glyph
245
SplitGlyphs(const wxBitmap & inBitmap,int inCount)246 void wxSpeedButton::SplitGlyphs(const wxBitmap &inBitmap, int inCount) {
247 int n;
248 int bw,bh;
249 int sw,sh;
250 wxRect rr;
251 wxImage img;
252 wxBitmap *bmp;
253
254 // no images yet
255
256 mGlyphUp = wxNullBitmap;
257 mGlyphDown = wxNullBitmap;
258 mGlyphDisabled = wxNullBitmap;
259
260 // if no bitmap, then we are done
261
262 if (! inBitmap.Ok()) return;
263
264 // size of the bitmap
265
266 bw = inBitmap.GetWidth();
267 bh = inBitmap.GetHeight();
268 if ((bw <= 0) || (bh <= 0)) return;
269
270 // determine the number of images in the source bitmap
271 // if inCount > 0, then that is the count specified by the user
272 // else, count number of square sub-images
273
274 if (inCount > 0) n = inCount;
275 else if (bw >= bh) n = (int) bw / bh;
276 else n = (int) bh / bw;
277
278 // extract sub-images, either vertically or horizontally
279
280 if (n == 1) {
281 mGlyphUp = inBitmap;
282 mGlyphDown = inBitmap;
283
284 img = inBitmap.ConvertToImage();
285 img = img.ConvertToGreyscale();
286 bmp = new wxBitmap(img);
287 mGlyphDisabled = *bmp;
288 }
289 else if ((n == 2) && (bw >= bh)) {
290 sw = (int) bw / n;
291 sh = bh;
292
293 rr.SetX(0);
294 rr.SetY(0);
295 rr.SetWidth(sw);
296 rr.SetHeight(sh);
297 mGlyphUp = inBitmap.GetSubBitmap(rr);
298 mGlyphDown = inBitmap.GetSubBitmap(rr);
299 rr.SetX(sw);
300 mGlyphDisabled = inBitmap.GetSubBitmap(rr);
301 }
302 else if ((n == 2) && (bh > bw)) {
303 sw = bw;
304 sh = (int) bh / n;
305
306 rr.SetX(0);
307 rr.SetY(0);
308 rr.SetWidth(sw);
309 rr.SetHeight(sh);
310 mGlyphUp = inBitmap.GetSubBitmap(rr);
311 mGlyphDown = inBitmap.GetSubBitmap(rr);
312 rr.SetY(sh);
313 mGlyphDisabled = inBitmap.GetSubBitmap(rr);
314 }
315 else if ((n >= 3) && (bw >= bh)) {
316 sw = (int) bw / n;
317 sh = bh;
318
319 rr.SetX(0);
320 rr.SetY(0);
321 rr.SetWidth(sw);
322 rr.SetHeight(sh);
323 mGlyphUp = inBitmap.GetSubBitmap(rr);
324 rr.SetX(sw);
325 mGlyphDown = inBitmap.GetSubBitmap(rr);
326 rr.SetX(sw+sw);
327 mGlyphDisabled = inBitmap.GetSubBitmap(rr);
328 }
329 else { // (n >= 3) && (bh > bw)
330 sw = bw;
331 sh = (int) bh / n;
332
333 rr.SetX(0);
334 rr.SetY(0);
335 rr.SetWidth(sw);
336 rr.SetHeight(sh);
337 mGlyphUp = inBitmap.GetSubBitmap(rr);
338 rr.SetY(sh);
339 mGlyphDown = inBitmap.GetSubBitmap(rr);
340 rr.SetY(sh+sh);;
341 mGlyphDisabled = inBitmap.GetSubBitmap(rr);
342 };
343
344 // make them all transparent
345
346 MakeTransparent(mGlyphUp);
347 MakeTransparent(mGlyphDown);
348 MakeTransparent(mGlyphDisabled);
349 }
350
351 //------------------------------------------------------------------------------
352 // make sure a bitmap has a transparency mask
353
MakeTransparent(wxBitmap & inBitmap)354 void wxSpeedButton::MakeTransparent(wxBitmap &inBitmap) {
355 int h;
356 int r,g,b;
357 wxImage img;
358 wxBitmap *bmp;
359
360 // not a good image?
361
362 if (! inBitmap.IsOk()) return;
363
364 // already have a mask?
365
366 img = inBitmap.ConvertToImage();
367 if (img.HasMask()) return;
368
369 // get the colors of the lower-left corner of the image
370
371 h = img.GetHeight();
372 r = img.GetRed(0, h-1);
373 b = img.GetBlue(0, h-1);
374 g = img.GetGreen(0, h-1);
375
376 // make a mask from those colors
377
378 img.SetMaskColour(r, g, b);
379
380 // store it back in the bitmap
381
382 bmp = new wxBitmap(img);
383 inBitmap = *bmp;
384 }
385
386 //------------------------------------------------------------------------------
387
GetGlyphSize(wxBitmap & inGlyph,int & outWidth,int & outHeight)388 void wxSpeedButton::GetGlyphSize(wxBitmap &inGlyph, int &outWidth, int &outHeight) {
389
390 if (inGlyph.Ok()) {
391 outWidth = inGlyph.GetWidth();
392 outHeight = inGlyph.GetHeight();
393 }
394 else {
395 outWidth = 0;
396 outHeight = 0;
397 };
398
399 }
400
401 //------------------------------------------------------------------------------
402 // calc best size for button,
403 // fills in mGlyphSize, mLabelSize, mBestSize
404
DoGetBestSize(void)405 wxSize wxSpeedButton::DoGetBestSize(void) {
406 int i,n;
407 int w,h;
408 int bn;
409 int bw, bh;
410 int gw, gh;
411 int lw, lh;
412
413 // max size of the bitmaps
414
415 bw = 0;
416 bh = 0;
417 GetGlyphSize(mGlyphUp, gw, gh);
418 if (gw > bw) bw = gw;
419 if (gh > bh) bh = gh;
420 GetGlyphSize(mGlyphDown, gw, gh);
421 if (gw > bw) bw = gw;
422 if (gh > bh) bh = gh;
423 GetGlyphSize(mGlyphDisabled, gw, gh);
424 if (gw > bw) bw = gw;
425 if (gh > bh) bh = gh;
426
427 mGlyphSize.Set(bw, bh);
428
429 // max size of the t n = inStyle | wxCLIP_CHILDREN;ext label
430
431 lw = 0;
432 lh = 0;
433 if (! GetLabel().IsEmpty()) GetTextExtent(GetLabel(), &lw, &lh);
434
435 mLabelSize.Set(lw, lh);
436
437 // border size is a magiv number, imperically determined using the
438 // wxNativeRenderer to draw the button
439
440 bn = 2;
441
442 // best size depends upon the alignment
443
444 i = GetWindowStyleFlag();
445
446 if (((i & wxBU_LEFT) != 0) || ((i & wxBU_RIGHT) != 0)) {
447 w = bn + mMargin + bw + mMargin + lw + mMargin + bn;
448 n = (bh > lh) ? bh : lh;
449 h = bn + mMargin + n + mMargin + bn;
450 }
451 else if (((i & wxBU_TOP) != 0) || ((i & wxBU_BOTTOM) != 0)) {
452 n = (bw > lw) ? bw : lw;
453 w = bn + mMargin + n + mMargin + bn;
454 h = bn + mMargin + bh + mMargin + lh + mMargin + bn;
455 }
456 else { // assume BU_LEFT
457 w = bn + mMargin + bw + mMargin + lw + mMargin + bn;
458 n = (bh > lh) ? bh : lh;
459 h = bn + mMargin + n + mMargin + bn;
460 };
461
462 mBestSize.Set(w, h);
463
464 // done
465
466 return mBestSize;
467 }
468
469 //------------------------------------------------------------------------------
470 // calculate the position of the bitmap and the label
471 // fills in mGlyphPos, mLabelPos, mCurrentSize
472
CalcLayout(bool inRefresh)473 void wxSpeedButton::CalcLayout(bool inRefresh) {
474 int i;
475 int bn;
476 int w, h;
477 bool gz, lz;
478 int gx, gy;
479 int lx, ly;
480
481 // no recursive calls
482
483 if (mCalcBusy) return;
484 mCalcBusy = true;
485
486 // current size of the button
487
488 GetSize(&w,&h);
489 mCurrentSize.Set(w, h);
490
491 // get sizes of bitmaps and labels, alignment and margin
492
493 DoGetBestSize();
494
495 // glyph or label not used?
496
497 gz = (mGlyphSize.GetWidth() == 0) || (mGlyphSize.GetHeight() == 0);
498 lz = (mLabelSize.GetWidth() == 0) || (mLabelSize.GetHeight() == 0);
499
500 // border size is a magiv number, imperically determined using the
501 // wxNativeRenderer to draw the button
502
503 bn = 2;
504
505 // position depends on alignment
506
507 i = GetWindowStyleFlag();
508
509 if (gz && lz) { // no glyph, no label
510 gx = 0;
511 gy = 0;
512 lx = 0;
513 ly = 0;
514 }
515 else if (gz) { // no glyph, only label
516 gx = 0;
517 gy = 0;
518 lx = (mCurrentSize.GetWidth() - mLabelSize.GetWidth()) / 2;
519 ly = (mCurrentSize.GetHeight() - mLabelSize.GetHeight()) / 2;
520 }
521 else if (lz) { // no label, glyph only
522 gx = (mCurrentSize.GetWidth() - mGlyphSize.GetWidth()) / 2;
523 gy = (mCurrentSize.GetHeight() - mGlyphSize.GetHeight()) / 2;
524 lx = 0;
525 ly = 0;
526 }
527 else if ((i & wxBU_LEFT) != 0) {
528 gx = bn + mMargin;
529 lx = gx + mGlyphSize.GetWidth() + mMargin;
530 gy = (mCurrentSize.GetHeight() - mGlyphSize.GetHeight()) / 2;
531 ly = (mCurrentSize.GetHeight() - mLabelSize.GetHeight()) / 2;
532 }
533 else if ((i & wxBU_RIGHT) != 0) {
534 gx = mCurrentSize.GetWidth() - (mGlyphSize.GetWidth() + mMargin + bn);
535 lx = gx - (mLabelSize.GetWidth() + mMargin);
536 gy = (mCurrentSize.GetHeight() - mGlyphSize.GetHeight()) / 2;
537 ly = (mCurrentSize.GetHeight() - mLabelSize.GetHeight()) / 2;
538 }
539 else if ((i & wxBU_TOP) != 0) {
540 gx = (mCurrentSize.GetWidth() - mGlyphSize.GetWidth()) / 2;
541 lx = (mCurrentSize.GetWidth() - mLabelSize.GetWidth()) / 2;
542 gy = bn + mMargin;
543 ly = gy + mMargin + mGlyphSize.GetHeight();
544 }
545 else if ((i & wxBU_BOTTOM) != 0) {
546 gx = (mCurrentSize.GetWidth() - mGlyphSize.GetWidth()) / 2;
547 lx = (mCurrentSize.GetWidth() - mLabelSize.GetWidth()) / 2;
548 gy = mCurrentSize.GetHeight() - (bn + mMargin + mGlyphSize.GetHeight());
549 ly = gy - (mLabelSize.GetHeight() + mMargin);
550 }
551 else { // unknown
552 gx = 0;
553 gy = 0;
554 lx = 0;
555 ly = 0;
556 };
557
558 // save the positions
559
560 mGlyphPos.x = gx;
561 mGlyphPos.y = gy;
562 mLabelPos.x = lx;
563 mLabelPos.y = ly;
564
565 // redraw button?
566
567 if (inRefresh) Refresh(false);
568
569 // allow another call
570
571 mCalcBusy = false;
572 }
573
574
575
576
577
578 //------------------------------------------------------------------------------
579
SetLabel(wxString & inLabel)580 void wxSpeedButton::SetLabel(wxString &inLabel) {
581 wxControl::SetLabel(inLabel);
582 Refresh(false);
583 }
584
585 //------------------------------------------------------------------------------
586
SetGlyphUp(wxBitmap & inBitmap)587 void wxSpeedButton::SetGlyphUp(wxBitmap &inBitmap) {
588
589 mGlyphUp = inBitmap;
590 Refresh(false);
591 }
592
GetGlyphUp(void)593 wxBitmap &wxSpeedButton::GetGlyphUp(void) {
594
595 return mGlyphUp;
596 }
597
598 //------------------------------------------------------------------------------
599
SetGlyphDown(wxBitmap & inBitmap)600 void wxSpeedButton::SetGlyphDown(wxBitmap &inBitmap) {
601
602 mGlyphDown = inBitmap;
603 Refresh(false);
604 }
605
GetGlyphDown(void)606 wxBitmap &wxSpeedButton::GetGlyphDown(void) {
607
608 return mGlyphDown;
609 }
610
611 //------------------------------------------------------------------------------
612
SetGlyphDisabled(wxBitmap & inBitmap)613 void wxSpeedButton::SetGlyphDisabled(wxBitmap &inBitmap) {
614
615 mGlyphDisabled = inBitmap;
616 Refresh(false);
617 }
618
GetGlyphDisabled(void)619 wxBitmap &wxSpeedButton::GetGlyphDisabled(void) {
620
621 return mGlyphDisabled;
622 }
623
624
625
626
627 //------------------------------------------------------------------------------
628
SetAlign(int inAlign)629 void wxSpeedButton::SetAlign(int inAlign) {
630 int i,n;
631
632 // make sure a valid alignment
633
634 n = inAlign;
635 if ((n != wxBU_LEFT) && (n != wxBU_TOP) &&(n != wxBU_RIGHT) &&(n != wxBU_BOTTOM)) n = wxBU_LEFT;
636
637 // get current style
638
639 i = GetWindowStyleFlag();
640
641 // remove old alignment, and border info
642
643 i = i & (~ wxBORDER_MASK);
644 i = i & (~ wxBU_ALIGN_MASK);
645
646 // put in alignment and no-border
647
648 i = i | wxBORDER_NONE;
649 i = i | n;
650 i = i | wxCLIP_CHILDREN;
651
652 // save new style
653
654 SetWindowStyleFlag(i);
655 Refresh(false);
656 }
657
GetAlign(void)658 int wxSpeedButton::GetAlign(void) {
659 int i;
660
661 i = GetWindowStyleFlag();
662 i = i & wxBU_ALIGN_MASK;
663
664 return i;
665 }
666
667 //------------------------------------------------------------------------------
668
SetMargin(int inMargin)669 void wxSpeedButton::SetMargin(int inMargin) {
670
671 mMargin = inMargin;
672 Refresh(false);
673 }
674
GetMargin(void)675 int wxSpeedButton::GetMargin(void) {
676
677 return mMargin;
678 }
679
680 //------------------------------------------------------------------------------
681
SetGroupIndex(bool inIndex)682 void wxSpeedButton::SetGroupIndex(bool inIndex) {
683
684 mGroupIndex = inIndex;
685 Refresh(false);
686 }
687
GetGroupIndex(void)688 int wxSpeedButton::GetGroupIndex(void) {
689
690 return mGroupIndex;
691 }
692
693
694
695 //------------------------------------------------------------------------------
696
SetDown(bool inDown)697 void wxSpeedButton::SetDown(bool inDown) {
698
699 // a simple button never goes DOWN, it always reports as UP
700
701 if (mGroupIndex == 0) {
702 mButtonDown = false;
703 }
704
705 // a sime toggle button goes UP and DOWN
706
707 else if (mGroupIndex == -1) {
708 mButtonDown = inDown;
709 }
710
711 // a group toggle button, grouped by immediate parent
712
713 else if (mGroupIndex == -2) {
714 SetAllUp(this);
715 if ((! inDown) && (mAllowAllUp)) mButtonDown = false;
716 else mButtonDown = true;
717 }
718
719 // all else is a group toggle button, grouped by index and top-level parent
720
721 else {
722 SetAllUp(this);
723 if ((! inDown) && (mAllowAllUp)) mButtonDown = false;
724 else mButtonDown = true;
725 };
726
727 // done
728
729 Refresh(false);
730 }
731
GetDown(void)732 bool wxSpeedButton::GetDown(void) {
733
734 return mButtonDown;
735 }
736
SetAllUp(wxSpeedButton * inButton)737 void wxSpeedButton::SetAllUp(wxSpeedButton *inButton) {
738 int i,n;
739 wxSpeedButton *b;
740
741 // no button?
742
743 if (inButton == NULL) return;
744
745 // simple button
746
747 if (inButton->mGroupIndex == 0) {
748 inButton->mButtonDown = false;
749 inButton->Refresh(false);
750 }
751
752 // toggle button
753
754 else if (inButton->mGroupIndex == -1) {
755 inButton->mButtonDown = false;
756 inButton->Refresh(false);
757 }
758
759 // group button, grouped by immediate parent
760
761 else if (inButton->mGroupIndex == -2) {
762 n = sbgArray.GetCount();
763 for(i=0; i<n; i++) {
764 b = (wxSpeedButton *) sbgArray.Item(i);
765 if (b->mParent == inButton->mParent) {
766 b->mButtonDown = false;
767 b->Refresh(false);
768 };
769 };
770 }
771
772 // all else is a group toggle button, grouped by index and top-level parent
773
774 else {
775 n = sbgArray.GetCount();
776 for(i=0; i<n; i++) {
777 b = (wxSpeedButton *) sbgArray.Item(i);
778 if ((b->mGroupIndex == inButton->mGroupIndex) && (b->mTopParent == inButton->mTopParent)) {
779 b->mButtonDown = false;
780 b->Refresh(false);
781 };
782 };
783 };
784
785
786 }
787
SetValue(bool inDown)788 void wxSpeedButton::SetValue(bool inDown) {
789
790 SetDown(inDown);
791 }
792
GetValue(void)793 bool wxSpeedButton::GetValue(void) {
794
795 return GetDown();
796 }
797
798 //------------------------------------------------------------------------------
799
SetAllowAllUp(bool inAllUp)800 void wxSpeedButton::SetAllowAllUp(bool inAllUp) {
801
802 mAllowAllUp = inAllUp;
803 Refresh(false);
804 }
805
GetAllowAllUp(void)806 bool wxSpeedButton::GetAllowAllUp(void) {
807
808 return mAllowAllUp;
809 }
810
811 //------------------------------------------------------------------------------
812
SetUserData(long inData)813 void wxSpeedButton::SetUserData(long inData) {
814
815 mUserData = inData;
816 }
817
GetUserData(void)818 long wxSpeedButton::GetUserData(void) {
819
820 return mUserData;
821 }
822
823
824
825
826
827
828 //------------------------------------------------------------------------------
829
830 // sequence of events in GTK is up, dclick, up.
831
OnMouseEvents(wxMouseEvent & event)832 void wxSpeedButton::OnMouseEvents(wxMouseEvent& event) {
833 wxWindow *win;
834
835 // our underlying window
836
837 win = (wxWindow *) this;
838
839 // any mouse button down
840
841 if (event.LeftDown() || event.RightDown()) {
842 if (!HasCapture()) CaptureMouse();
843 mMouseDown = true;
844 mButtonFocused = true;
845 win->SetFocus();
846 Redraw();
847 }
848
849 // any mouse button up
850 // this is where we send a click event
851
852 else if (event.LeftUp() || event.RightUp()) {
853 if (HasCapture()) ReleaseMouse();
854 mMouseDown = false;
855 mButtonFocused = true;
856 win->SetFocus();
857 SetDown(! mButtonDown);
858 SendEvent(event.LeftUp());
859 Redraw();
860 }
861
862 // mouse over
863
864 else if (event.Entering()) {
865 mMouseOver = true;
866 Redraw();
867 }
868 else if (event.Leaving()) {
869 mMouseOver = false;
870 Redraw();
871 };
872 }
873
874 //------------------------------------------------------------------------------
875 // cake a mouse click
876
DoClick(bool inLeft)877 void wxSpeedButton::DoClick(bool inLeft) {
878
879 SetDown(! mButtonDown);
880 SendEvent(inLeft);
881 Refresh(false);
882 }
883
884
885 //------------------------------------------------------------------------------
886 // send a command click-event for the left or right buttons
887
SendEvent(bool inLeft)888 void wxSpeedButton::SendEvent(bool inLeft) {
889 int n;
890 long now;
891 wxCommandEvent event;
892
893 // set command type and window ID of caller
894
895 if (inLeft) event.SetEventType(wxEVT_COMMAND_LEFT_CLICK);
896 else event.SetEventType(wxEVT_COMMAND_RIGHT_CLICK);
897
898 event.SetId(GetId());
899
900 // save pointer to this object
901
902 event.SetEventObject(this);
903
904 // if LEFT, the int is 1, else 0
905
906 n = inLeft ? 1 : 0;
907 event.SetInt(n);
908
909 // and the time
910
911 now = (long) wxDateTime::GetTimeNow();
912 event.SetTimestamp(now);
913
914 // send it
915
916 GetEventHandler()->ProcessEvent(event);
917 }
918
919
920 //------------------------------------------------------------------------------
921
OnPaint(wxPaintEvent & event)922 void wxSpeedButton::OnPaint(wxPaintEvent& event)
923 {
924 wxPaintDC dc(this);
925 Paint(dc);
926 event.Skip();
927 }
928
929 //------------------------------------------------------------------------------
930
Redraw()931 void wxSpeedButton::Redraw()
932 {
933 wxClientDC dc(this);
934 Paint(dc);
935 }
936
937 //------------------------------------------------------------------------------
938 // drawing up, down, flat
939 // optional hot, transparent
940
Paint(wxDC & dc)941 void wxSpeedButton::Paint( wxDC &dc ) {
942 int n;
943 int w,h;
944 wxColour cf; // foreground color
945 wxColour cb; // background color
946 wxColour cg; // gray text
947 wxColour cy; // yellow
948 wxBrush bb; // background brush
949 wxPen pp; // line-drawing pen
950 wxBitmap bmp;
951 wxString s;
952 wxRect rr;
953
954 // get size and layout
955
956 if (! mCalcBusy) CalcLayout(false);
957
958 w = mCurrentSize.GetWidth();
959 h = mCurrentSize.GetHeight();
960
961 // get colors
962
963 cf = GetForegroundColour();
964 cb = GetBackgroundColour();
965 cg = wxSystemSettings::GetColour(wxSYS_COLOUR_GRAYTEXT );
966 cy = wxTheColourDatabase->Find(_("YELLOW"));
967
968 // use wxWidgets to draw the basic button
969
970 rr.SetX(0);
971 rr.SetY(0);
972 rr.SetWidth(w);
973 rr.SetHeight(h);
974
975 n = 0;
976 if (mMouseDown || mButtonDown) n = n | wxCONTROL_PRESSED;
977 if (mButtonFocused) n = n | wxCONTROL_ISDEFAULT;
978
979 wxRendererNative::Get().DrawPushButton(this, dc, rr, n);
980
981 // track mouse movements with mMouseOver using a dotted yellow line
982
983 pp = *wxBLACK_PEN;
984 pp.SetColour(cy);
985 // pp.SetStyle(wxDOT);
986 dc.SetPen(pp);
987 if (mMouseOver) {
988 n = 2;
989 dc.DrawLine( n, n, w-n, n);
990 dc.DrawLine(w-n, n, w-n, h-n);
991 dc.DrawLine(w-n, h-n, n, h-n);
992 dc.DrawLine( n, h-n, n, n);
993 };
994
995 // select the bitmap to draw
996
997 if (! IsEnabled()) bmp = mGlyphDisabled;
998 else if (mMouseDown || mButtonDown) bmp = mGlyphDown;
999 else bmp = mGlyphUp;
1000
1001 if (bmp.IsOk()) dc.DrawBitmap(bmp, mGlyphPos.x, mGlyphPos.y, true );
1002
1003 // the text label
1004
1005 s = GetLabelText();
1006 if (! s.IsEmpty()) {
1007 dc.SetFont(GetFont());
1008 dc.SetBackgroundMode(wxTRANSPARENT);
1009 if (! IsEnabled()) dc.SetTextForeground(cg);
1010 else dc.SetTextForeground(cf);
1011 dc.DrawText(s, mLabelPos.x, mLabelPos.y);
1012 };
1013 }
1014
1015 //------------------------------------------------------------------------------
1016
OnSize(wxSizeEvent & event)1017 void wxSpeedButton::OnSize( wxSizeEvent &event )
1018 {
1019 Refresh(false);
1020 event.Skip();
1021 }
1022
1023
1024
1025 //------------------------------------------------------------------------------
1026
OnSetFocus(wxFocusEvent & event)1027 void wxSpeedButton::OnSetFocus(wxFocusEvent& event) {
1028
1029 mButtonFocused = true;
1030 Redraw();
1031 event.Skip();
1032 }
1033
1034 //------------------------------------------------------------------------------
1035
OnKillFocus(wxFocusEvent & event)1036 void wxSpeedButton::OnKillFocus(wxFocusEvent& event) {
1037
1038 mButtonFocused = false;
1039 Redraw();
1040 event.Skip();
1041 }
1042
1043 //------------------------------------------------------------------------------
1044
OnKey(wxKeyEvent & event)1045 void wxSpeedButton::OnKey(wxKeyEvent& event) {
1046 int n;
1047 wxString s;
1048
1049 n = event.GetKeyCode();
1050 if ((n == '\n') || ( n == '\r') || (n == ' ')) {
1051 mButtonFocused = true;
1052 SetDown(! mButtonDown);
1053 SendEvent(true);
1054 Redraw();
1055 //Refresh(false);
1056 };
1057
1058 event.Skip();
1059 }
1060
1061
1062
1063
1064
1065
1066
1067
1068