]> git.saurik.com Git - wxWidgets.git/blob - utils/framelayout/src/newbmpbtn.cpp
vc makefile
[wxWidgets.git] / utils / framelayout / src / newbmpbtn.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: No names yet.
3 // Purpose: Contrib. demo
4 // Author: Aleksandras Gluchovas
5 // Modified by:
6 // Created: ??/09/98
7 // RCS-ID: $Id$
8 // Copyright: (c) Aleksandras Gluchovas
9 // Licence: wxWindows license
10 /////////////////////////////////////////////////////////////////////////////
11
12 #ifdef __GNUG__
13 #pragma implementation "newbmpbtn.cpp"
14 #pragma interface "newbmpbtn.cpp"
15 #endif
16
17 // For compilers that support precompilation, includes "wx/wx.h".
18 #include "wx/wxprec.h"
19
20 /*
21 #ifdef __BORLANDC__
22 #pragma hdrstop
23 #endif
24 */
25
26 #ifndef WX_PRECOMP
27 #include "wx/wx.h"
28 #endif
29
30 #include "newbmpbtn.h"
31 #include "wx/utils.h" // import wxMin,wxMax macros
32
33 ///////////// button-label rendering helpers //////////////////
34
35 static int* create_array( int width, int height, int fill = 0 )
36 {
37 int* array = new int[width*height];
38
39 int len = width*height;
40 for( int i = 0; i != len; ++i ) array[i] = fill;
41
42 return array;
43 }
44
45 #define GET_ELEM(array,x,y) (array[width*(y)+(x)])
46
47 #define MIN_COLOR_DIFF 10
48
49 #define IS_IN_ARRAY(x,y) ( (x) < width && (y) < height && (x) >= 0 && (y) >= 0 )
50
51 #define GET_RED(col) col & 0xFF
52 #define GET_GREEN(col) (col >> 8) & 0xFF
53 #define GET_BLUE(col) (col >> 16) & 0xFF
54
55 #define MAKE_INT_COLOR(red,green,blue) ( (red) | \
56 ( ( (green) << 8 ) & 0xFF00 ) | \
57 ( ( (blue) << 16) & 0xFF0000) \
58 )
59
60 #define IS_GREATER(col1,col2) ( ( (GET_RED(col1) ) > (GET_RED(col2) ) + MIN_COLOR_DIFF ) && \
61 ( (GET_GREEN(col1)) > (GET_GREEN(col2)) + MIN_COLOR_DIFF ) && \
62 ( (GET_BLUE(col1) ) > (GET_BLUE(col2) ) + MIN_COLOR_DIFF ) \
63 )
64
65 #define MASK_BG 0
66 #define MASK_DARK 1
67 #define MASK_LIGHT 2
68
69 // helper function, used internally
70
71 static void gray_out_pixmap( int* src, int* dest, int width, int height )
72 {
73 // assuming the pixels along the edges are of the background color
74 int bgCol = GET_ELEM(src,0,0);
75
76 int x = 0;
77 int y = 1;
78
79 do
80 {
81 int cur = GET_ELEM(src,x,y);
82
83 int r = GET_RED(cur);
84 int g = GET_GREEN(cur);
85 int b = GET_BLUE(cur);
86
87 if ( IS_IN_ARRAY(x-1,y-1) )
88 {
89 int upperElem = GET_ELEM(src,x-1,y-1);
90
91 // if the upper element is lighter than current
92 if ( IS_GREATER(upperElem,cur) )
93 {
94 GET_ELEM(dest,x,y) = MASK_DARK;
95 }
96 else
97 // if the current element is ligher than the upper
98 if ( IS_GREATER(cur,upperElem) )
99 {
100 GET_ELEM(dest,x,y) = MASK_LIGHT;
101 }
102 else
103 {
104 if ( GET_ELEM(dest,x-1,y-1) == MASK_LIGHT )
105
106 GET_ELEM(dest,x,y) = MASK_BG;
107
108 if ( GET_ELEM(dest,x-1,y-1 ) == MASK_DARK )
109
110 GET_ELEM(dest,x,y) = MASK_DARK;
111 else
112 GET_ELEM(dest,x,y) = MASK_BG;
113 }
114 }
115
116 // go zig-zag
117
118 if ( IS_IN_ARRAY(x+1,y-1) )
119 {
120 ++x;--y;
121 }
122 else
123 {
124 while( IS_IN_ARRAY(x-1,y+1) )
125 {
126 --x;++y;
127 }
128
129 if ( IS_IN_ARRAY(x,y+1) )
130 {
131 ++y; continue;
132 }
133 else
134 {
135 if ( IS_IN_ARRAY(x+1,y) )
136 {
137 ++x; continue;
138 }
139 else break;
140 }
141 }
142
143 } while(1);
144 }
145
146 // alg. for making the image look "grayed" (e.g. disabled button)
147 // NOTE:: used GetPixel(), which is Windows-Only!
148
149 void greay_out_image_on_dc( wxDC& dc, int width, int height )
150 {
151 // assuming the pixels along the edges are of the background color
152 wxColour bgCol;
153 dc.GetPixel( 0, 0, &bgCol );
154
155 wxPen darkPen ( wxColour(128,128,128),1, wxSOLID );
156 wxPen lightPen( wxColour(255,255,255),1, wxSOLID );
157 wxPen bgPen ( bgCol, 1, wxSOLID );
158
159 int* src = create_array( width, height, MASK_BG );
160 int* dest = create_array( width, height, MASK_BG );
161
162 int y = 0;
163 for( y = 0; y != height; ++y )
164
165 for( int x = 0; x != width; ++x )
166 {
167 wxColour col;
168 dc.GetPixel( x,y, &col );
169
170 int r = col.Red(),
171 g = col.Green(),
172 b = col.Blue();
173
174 int o = MAKE_INT_COLOR( r,g,b );
175
176 GET_ELEM(src,x,y) = MAKE_INT_COLOR( col.Red(), col.Green(), col.Blue() );
177 }
178
179 gray_out_pixmap( src, dest, width, height );
180
181 for( y = 0; y != height; ++y )
182
183 for( int x = 0; x != width; ++x )
184 {
185 int mask = GET_ELEM(dest,x,y);
186
187 switch (mask)
188 {
189 case MASK_BG : { dc.SetPen( bgPen );
190 dc.DrawPoint( x,y ); break;
191 }
192 case MASK_DARK : { dc.SetPen( darkPen );
193 dc.DrawPoint( x,y ); break;
194 }
195 case MASK_LIGHT : { dc.SetPen( lightPen );
196 dc.DrawPoint( x,y ); break;
197 }
198 default : break;
199 }
200 }
201
202 delete [] src;
203 delete [] dest;
204 }
205
206 ///////////////////////////////
207
208 /***** Impelementation for class wxNewBitmapButton *****/
209
210 IMPLEMENT_DYNAMIC_CLASS(wxNewBitmapButton, wxPanel)
211
212 BEGIN_EVENT_TABLE( wxNewBitmapButton, wxPanel )
213
214 EVT_LEFT_DOWN( wxNewBitmapButton::OnLButtonDown )
215 EVT_LEFT_UP ( wxNewBitmapButton::OnLButtonUp )
216 EVT_MOTION ( wxNewBitmapButton::OnMouseMove )
217
218 EVT_SIZE ( wxNewBitmapButton::OnSize )
219 EVT_PAINT( wxNewBitmapButton::OnPaint )
220
221 //EVT_KILL_FOCUS( wxNewBitmapButton::OnKillFocus )
222
223 EVT_ERASE_BACKGROUND( wxNewBitmapButton::OnEraseBackground )
224
225 END_EVENT_TABLE()
226
227 wxNewBitmapButton::wxNewBitmapButton( const wxBitmap& labelBitmap,
228 const wxString& labelText,
229 int alignText,
230 bool isFlat,
231 int firedEventType,
232 int marginX,
233 int marginY,
234 int textToLabelGap,
235 bool isSticky)
236 : mpDepressedImg( NULL ),
237 mpPressedImg ( NULL ),
238 mpDisabledImg ( NULL ),
239 mpFocusedImg ( NULL ),
240
241 mMarginX( marginX ),
242 mMarginY( marginY ),
243 mTextAlignment( alignText ),
244 mIsFlat( isFlat ),
245
246 mIsPressed ( FALSE ),
247 mDragStarted ( FALSE ),
248 mPrevPressedState( FALSE ),
249 mTextToLabelGap ( textToLabelGap ),
250
251 mBlackPen( wxColour( 0, 0, 0), 1, wxSOLID ),
252 mDarkPen ( wxColour(128,128,128), 1, wxSOLID ),
253 mGrayPen ( wxColour(192,192,192),
254 1, wxSOLID ),
255 mLightPen( wxColour(255,255,255), 1, wxSOLID ),
256
257 mFiredEventType( firedEventType ),
258 mIsSticky( isSticky ),
259 mIsCreated( FALSE ),
260 mSizeIsSet( FALSE ),
261
262 mHasFocusedBmp( FALSE ),
263 mIsInFocus( FALSE ),
264
265 mDepressedBmp( labelBitmap ),
266 mLabelText( labelText ),
267 mImageFileType( -1 )
268 {
269 }
270
271 wxNewBitmapButton::wxNewBitmapButton( const wxString& bitmapFileName,
272 const int bitmapFileType,
273 const wxString& labelText,
274 int alignText,
275 bool isFlat,
276 int firedEventType,
277 int marginX,
278 int marginY,
279 int textToLabelGap,
280 bool isSticky)
281
282 : mpDepressedImg( NULL ),
283 mpPressedImg ( NULL ),
284 mpDisabledImg ( NULL ),
285 mpFocusedImg ( NULL ),
286
287 mMarginX( 2 ),
288 mMarginY( 2 ),
289 mTextAlignment( alignText ),
290 mIsFlat( isFlat ),
291
292 mIsPressed ( FALSE ),
293 mDragStarted ( FALSE ),
294 mPrevPressedState( FALSE ),
295 mTextToLabelGap ( 2 ),
296
297 mBlackPen( wxColour( 0, 0, 0), 1, wxSOLID ),
298 mDarkPen ( wxColour(128,128,128), 1, wxSOLID ),
299 mGrayPen ( wxColour(192,192,192),
300 1, wxSOLID ),
301 mLightPen( wxColour(255,255,255), 1, wxSOLID ),
302
303 mFiredEventType( wxEVT_COMMAND_MENU_SELECTED ),
304 mIsSticky( FALSE ),
305 mIsCreated( FALSE ),
306 mSizeIsSet( FALSE ),
307
308 mHasFocusedBmp( FALSE ),
309 mIsInFocus( FALSE ),
310
311 mLabelText( labelText ),
312 mImageFileName( bitmapFileName ),
313 mImageFileType( bitmapFileType )
314 {
315 //mDepressedBmp.LoadFile( bitmapFileName, bitmapFileType );
316 }
317
318 wxNewBitmapButton::~wxNewBitmapButton(void)
319 {
320 DestroyLabels();
321 }
322
323 void wxNewBitmapButton::DrawShade( int outerLevel,
324 wxDC& dc,
325 wxPen& upperLeftSidePen,
326 wxPen& lowerRightSidePen )
327 {
328 wxBitmap* pBmp = GetStateLabel();
329
330 int x = mMarginX - (outerLevel + 1);
331 int y = mMarginY - (outerLevel + 1);
332
333 int height = pBmp->GetHeight() + (outerLevel + 1)*2 - 1;
334 int width = pBmp->GetWidth() + (outerLevel + 1)*2 - 1;
335
336 dc.SetPen( upperLeftSidePen );
337 dc.DrawLine( x,y, x + width, y );
338 dc.DrawLine( x,y, x, y + height );
339
340 dc.SetPen( lowerRightSidePen );
341 dc.DrawLine( x + width, y, x + width, y + height + 1 );
342 dc.DrawLine( x, y + height, x + width, y + height );
343 }
344
345 void wxNewBitmapButton::DestroyLabels()
346 {
347 if ( mpDepressedImg ) delete mpDepressedImg;
348 if ( mpPressedImg ) delete mpPressedImg;
349 if ( mpDisabledImg ) delete mpDisabledImg;
350 if ( mpFocusedImg ) delete mpFocusedImg;
351
352 mpDepressedImg = NULL;
353 mpPressedImg = NULL;
354 mpDisabledImg = NULL;
355 mpFocusedImg = NULL;
356 }
357
358 wxBitmap* wxNewBitmapButton::GetStateLabel()
359 {
360 if ( IsEnabled() )
361 {
362 if ( mIsPressed )
363 {
364 return mpPressedImg;
365 }
366 else
367 {
368 if ( mIsInFocus )
369 {
370 if ( mHasFocusedBmp )
371
372 return mpFocusedImg;
373 else
374 return mpDepressedImg;
375 }
376 else
377 return mpDepressedImg;
378 }
379 }
380 else
381 return mpDisabledImg;
382 }
383
384 void wxNewBitmapButton::RenderLabelImage( wxBitmap*& destBmp, wxBitmap* srcBmp,
385 bool isEnabled, bool isPressed )
386 {
387 if ( destBmp != 0 ) return;
388
389 // render lables on-demand
390
391 wxMemoryDC srcDc;
392 srcDc.SelectObject( *srcBmp );
393 wxFont fnt( 9, wxDECORATIVE , wxNORMAL, wxNORMAL );
394
395 bool hasText = ( mTextAlignment != NB_NO_TEXT ) &&
396 ( mLabelText.length() != 0 );
397
398 bool hasImage = (mTextAlignment != NB_NO_IMAGE);
399
400 wxSize destDim;
401 wxPoint txtPos;
402 wxPoint imgPos;
403
404 if ( hasText )
405 {
406 long txtWidth, txtHeight;
407
408 srcDc.SetFont( fnt );
409 srcDc.GetTextExtent( mLabelText, &txtWidth, &txtHeight );
410
411 if ( mTextAlignment == NB_ALIGN_TEXT_RIGHT )
412 {
413 destDim.x = srcBmp->GetWidth() + 2*mTextToLabelGap + txtWidth;
414
415 destDim.y =
416 wxMax( srcBmp->GetHeight(), txtHeight );
417
418 txtPos.x = srcBmp->GetWidth() + mTextToLabelGap;
419 txtPos.y = (destDim.y - txtHeight)/2;
420 imgPos.x = 0;
421 imgPos.y = (destDim.y - srcBmp->GetHeight())/2;
422 }
423 else
424 if ( mTextAlignment == NB_ALIGN_TEXT_BOTTOM )
425 {
426 destDim.x =
427 wxMax( srcBmp->GetWidth(), txtWidth );
428
429 destDim.y = srcBmp->GetHeight() + mTextToLabelGap + txtHeight;
430
431 txtPos.x = (destDim.x - txtWidth)/2;
432 txtPos.y = srcBmp->GetHeight() + mTextToLabelGap;
433 imgPos.x = (destDim.x - srcBmp->GetWidth())/2;
434 imgPos.y = 0;
435 }
436 else wxASSERT(0);// unsupported alignment type
437 }
438 else
439 {
440 imgPos.x = 0;
441 imgPos.y = 0;
442 destDim.x = srcBmp->GetWidth();
443 destDim.y = srcBmp->GetHeight();
444 }
445
446 destBmp = new wxBitmap( int(destDim.x), int(destDim.y) );
447
448 wxMemoryDC destDc;
449 destDc.SelectObject( *destBmp );
450
451 // FOR NOW:: hard-coded label background
452 wxBrush grayBrush( wxColour(192,192,192), wxSOLID );
453 wxPen nullPen( wxColour(0,0,0), 1, wxTRANSPARENT );
454
455 destDc.SetBrush( grayBrush );
456 destDc.SetPen( nullPen );
457
458 destDc.DrawRectangle( 0,0, destDim.x+1, destDim.y+1 );
459
460 if ( isPressed )
461 {
462 ++imgPos.x; ++imgPos.y;
463 ++txtPos.x; ++txtPos.y;
464 }
465
466 if ( hasImage )
467 {
468 destDc.Blit( imgPos.x, imgPos.y,
469 srcBmp->GetWidth()+1,
470 srcBmp->GetHeight()+1,
471 &srcDc, 0,0, wxCOPY );
472 }
473
474 if ( hasText )
475 {
476 wxWindow* pTopWnd = this;
477
478 do
479 {
480 wxWindow* pParent = pTopWnd->GetParent();
481
482 if ( pParent == 0 ) break;
483
484 pTopWnd = pParent;
485 } while(1);
486
487 destDc.SetFont( fnt );
488
489 // FOR NOW:: hard-coded text colors
490 destDc.SetTextForeground( wxColour( 0, 0, 0) );
491 destDc.SetTextBackground( wxColour(192,192,192) );
492
493 destDc.DrawText( mLabelText, txtPos.x, txtPos.y );
494 }
495
496 if ( !isEnabled )
497
498 greay_out_image_on_dc( destDc, destDim.x, destDim.y );
499
500 // adjust button size to fit the new dimensions of the label
501 if ( !mSizeIsSet && 0 )
502 {
503 mSizeIsSet = TRUE;
504 SetSize( -1,-1,
505 destBmp->GetWidth() + mMarginX*2,
506 destBmp->GetHeight() + mMarginY*2, 0
507 );
508 }
509 }
510
511 void wxNewBitmapButton::RenderLabelImages()
512 {
513 if ( !mIsCreated ) return;
514
515 if ( !IsEnabled() )
516 {
517 RenderLabelImage( mpDisabledImg, &mDepressedBmp, FALSE );
518 }
519 else
520
521 if ( mIsPressed )
522
523 RenderLabelImage( mpPressedImg, &mDepressedBmp, TRUE, TRUE );
524 else
525 {
526 if ( mIsInFocus )
527 {
528 if ( mHasFocusedBmp )
529
530 RenderLabelImage( mpFocusedImg, &mFocusedBmp, TRUE, FALSE );
531 else
532 RenderLabelImage( mpDepressedImg, &mDepressedBmp, TRUE, FALSE );
533 }
534 else
535 RenderLabelImage( mpDepressedImg, &mDepressedBmp, TRUE, FALSE );
536 }
537 }
538
539 void wxNewBitmapButton::DrawDecorations( wxDC& dc )
540 {
541 if ( mIsFlat )
542 {
543 DrawShade( 1, dc, mGrayPen, mGrayPen );
544
545 if ( mIsInFocus )
546 {
547 if ( mIsPressed )
548
549 DrawShade( 0, dc, mDarkPen, mLightPen );
550 else
551 DrawShade( 0, dc, mLightPen, mDarkPen );
552 }
553 else
554 DrawShade( 0, dc, mGrayPen, mGrayPen );
555 }
556 else
557 {
558 if ( mIsPressed )
559 {
560 DrawShade( 0, dc, mDarkPen, mGrayPen );
561 DrawShade( 1, dc, mBlackPen, mLightPen );
562 }
563 else
564 {
565 DrawShade( 0, dc, mGrayPen, mDarkPen );
566 DrawShade( 1, dc, mLightPen, mBlackPen );
567 }
568 }
569 }
570
571 void wxNewBitmapButton::SetLabel(const wxBitmap& labelBitmap,
572 const wxString& labelText )
573 {
574 DestroyLabels();
575
576 mLabelText = labelText;
577 mDepressedBmp = labelBitmap;
578
579 RenderLabelImages();
580 }
581
582 void wxNewBitmapButton::SetAlignments( int alignText,
583 int marginX,
584 int marginY,
585 int textToLabelGap)
586 {
587 DestroyLabels();
588
589 mMarginX = marginX;
590 mMarginY = marginY;
591 mTextAlignment = alignText;
592 mTextToLabelGap = textToLabelGap;
593
594 RenderLabelImages();
595 }
596
597 // event handlers
598
599 void wxNewBitmapButton::OnLButtonDown( wxMouseEvent& event )
600 {
601 mPrevPressedState = FALSE;
602 mDragStarted = TRUE;
603 mIsPressed = TRUE;
604 Refresh();
605
606 if ( !mIsInFocus )
607
608 CaptureMouse();
609 }
610
611 void wxNewBitmapButton::OnLButtonUp( wxMouseEvent& event )
612 {
613 if ( !mDragStarted ) return;
614
615 mDragStarted = FALSE;
616 mIsPressed = FALSE;
617 mIsInFocus = FALSE;
618 Refresh();
619
620 ReleaseMouse();
621
622 if ( IsInWindow( event.m_x, event.m_y ) )
623 {
624 // fire event, if mouse was released
625 // within the bounds of button
626 wxCommandEvent cmd( mFiredEventType, GetId() );
627 GetParent()->ProcessEvent( cmd );
628 }
629 }
630
631 bool wxNewBitmapButton::IsInWindow( int x, int y )
632 {
633 int width, height;
634 GetSize( &width, &height );
635
636 return ( x >= 0 && y >= 0 &&
637 x < width &&
638 y < height );
639 }
640
641 void wxNewBitmapButton::OnMouseMove( wxMouseEvent& event )
642 {
643 if ( !mIsInFocus && IsInWindow( event.m_x, event.m_y ) )
644 {
645 if ( !mDragStarted )
646 CaptureMouse();
647
648 mIsInFocus = TRUE;
649 }
650 else
651 if ( mIsInFocus && !IsInWindow( event.m_x, event.m_y ) )
652 {
653 mIsInFocus = FALSE;
654
655 if ( !mDragStarted )
656 ReleaseMouse();
657 }
658
659 if ( mDragStarted )
660 {
661 if ( IsInWindow( event.m_x, event.m_y ) )
662
663 mIsPressed = TRUE;
664 else
665 mIsPressed = FALSE;
666
667 if ( mIsPressed != mPrevPressedState )
668
669 Refresh();
670
671 mPrevPressedState = mIsPressed;
672 }
673
674 // FOR NOW::
675 Refresh();
676 }
677
678 void wxNewBitmapButton::OnSize( wxSizeEvent& event )
679 {
680 //Reshape();
681 }
682
683 void wxNewBitmapButton::Reshape( )
684 {
685 bool wasCreated = mIsCreated;
686 mIsCreated = TRUE;
687
688 if ( !wasCreated )
689 {
690 // in the case of loading button from stream, check if we
691 // have non-empty image-file name, load if possible
692
693 if ( mImageFileName != "" )
694 {
695 mDepressedBmp.LoadFile( mImageFileName, mImageFileType );
696
697 //wxMessageBox("Image Loaded!!!");
698 }
699
700 RenderLabelImages();
701
702 wxBitmap* pCurImg = GetStateLabel();
703
704 int w = pCurImg->GetWidth(),
705 h = pCurImg->GetHeight();
706
707 SetSize( 0,0, w + mMarginX*2, h + mMarginY*2 , 0 );
708 }
709 }
710
711 void wxNewBitmapButton::DrawLabel( wxDC& dc )
712 {
713 wxBitmap* pCurBmp = GetStateLabel();
714
715 if ( pCurBmp == NULL )
716 {
717 wxSizeEvent evt;
718 OnSize( evt ); // fake it up!
719
720 RenderLabelImages();
721 pCurBmp = GetStateLabel();
722 }
723
724 wxMemoryDC mdc;
725 mdc.SelectObject( *pCurBmp );
726
727 dc.Blit( mMarginX, mMarginY,
728 pCurBmp->GetWidth(),
729 pCurBmp->GetHeight(),
730 &mdc, 0,0, wxCOPY
731 );
732
733 mdc.SelectObject( wxNullBitmap );
734 }
735
736 void wxNewBitmapButton::OnPaint( wxPaintEvent& event )
737 {
738 wxPaintDC dc(this);
739
740 // first, make sure images for current state are prepared
741 RenderLabelImages();
742
743 DrawLabel( dc );
744
745 DrawDecorations( dc );
746 }
747
748 void wxNewBitmapButton::OnEraseBackground( wxEraseEvent& event )
749 {
750 // do nothing
751 }
752
753 void wxNewBitmapButton::OnKillFocus( wxFocusEvent& event )
754 {
755 // useless
756
757 wxMessageBox("kill-focus for button!");
758 }
759