1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: Contrib. demo
4 // Author: Aleksandras Gluchovas
8 // Copyright: (c) Aleksandras Gluchovas
9 // Licence: wxWindows license
10 /////////////////////////////////////////////////////////////////////////////
13 #pragma implementation "newbmpbtn.h"
16 // For compilers that support precompilation, includes "wx/wx.h".
17 #include "wx/wxprec.h"
27 #include "wx/fl/newbmpbtn.h"
28 #include "wx/utils.h" // import wxMin,wxMax macros
30 ///////////// button-label rendering helpers //////////////////
32 static int* create_array( int width
, int height
, int fill
= 0 )
34 int* array
= new int[width
*height
];
36 int len
= width
*height
;
37 for( int i
= 0; i
!= len
; ++i
) array
[i
] = fill
;
42 #define GET_ELEM(array,x,y) (array[width*(y)+(x)])
44 #define MIN_COLOR_DIFF 10
46 #define IS_IN_ARRAY(x,y) ( (x) < width && (y) < height && (x) >= 0 && (y) >= 0 )
48 #define GET_RED(col) col & 0xFF
49 #define GET_GREEN(col) (col >> 8) & 0xFF
50 #define GET_BLUE(col) (col >> 16) & 0xFF
52 #define MAKE_INT_COLOR(red,green,blue) ( (red) | \
53 ( ( (green) << 8 ) & 0xFF00 ) | \
54 ( ( (blue) << 16) & 0xFF0000) \
57 #define IS_GREATER(col1,col2) ( ( (GET_RED(col1) ) > (GET_RED(col2) ) + MIN_COLOR_DIFF ) && \
58 ( (GET_GREEN(col1)) > (GET_GREEN(col2)) + MIN_COLOR_DIFF ) && \
59 ( (GET_BLUE(col1) ) > (GET_BLUE(col2) ) + MIN_COLOR_DIFF ) \
66 // helper function, used internally
68 static void gray_out_pixmap( int* src
, int* dest
, int width
, int height
)
70 // assuming the pixels along the edges are of the background color
77 int cur
= GET_ELEM(src
,x
,y
);
80 if ( IS_IN_ARRAY(x
-1,y
-1) )
82 int upperElem
= GET_ELEM(src
,x
-1,y
-1);
84 // if the upper element is lighter than current
85 if ( IS_GREATER(upperElem
,cur
) )
87 GET_ELEM(dest
,x
,y
) = MASK_DARK
;
90 // if the current element is ligher than the upper
91 if ( IS_GREATER(cur
,upperElem
) )
93 GET_ELEM(dest
,x
,y
) = MASK_LIGHT
;
97 if ( GET_ELEM(dest
,x
-1,y
-1) == MASK_LIGHT
)
99 GET_ELEM(dest
,x
,y
) = MASK_BG
;
101 if ( GET_ELEM(dest
,x
-1,y
-1 ) == MASK_DARK
)
103 GET_ELEM(dest
,x
,y
) = MASK_DARK
;
105 GET_ELEM(dest
,x
,y
) = MASK_BG
;
111 if ( IS_IN_ARRAY(x
+1,y
-1) )
117 while( IS_IN_ARRAY(x
-1,y
+1) )
122 if ( IS_IN_ARRAY(x
,y
+1) )
128 if ( IS_IN_ARRAY(x
+1,y
) )
139 // alg. for making the image look "grayed" (e.g. disabled button)
140 // NOTE:: used GetPixel(), which is Windows-Only!
142 void gray_out_image_on_dc( wxDC
& dc
, int width
, int height
)
144 // assuming the pixels along the edges are of the background color
146 dc
.GetPixel( 0, 0, &bgCol
);
148 wxPen
darkPen ( wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DSHADOW
),1, wxSOLID
);
149 wxPen
lightPen( wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DHIGHLIGHT
),1, wxSOLID
);
150 wxPen
bgPen ( bgCol
, 1, wxSOLID
);
152 int* src
= create_array( width
, height
, MASK_BG
);
153 int* dest
= create_array( width
, height
, MASK_BG
);
156 for( y
= 0; y
!= height
; ++y
)
158 for( int x
= 0; x
!= width
; ++x
)
161 dc
.GetPixel( x
,y
, &col
);
164 GET_ELEM(src
,x
,y
) = MAKE_INT_COLOR( col
.Red(), col
.Green(), col
.Blue() );
167 gray_out_pixmap( src
, dest
, width
, height
);
169 for( y
= 0; y
!= height
; ++y
)
171 for( int x
= 0; x
!= width
; ++x
)
173 int mask
= GET_ELEM(dest
,x
,y
);
177 case MASK_BG
: { dc
.SetPen( bgPen
);
178 dc
.DrawPoint( x
,y
); break;
180 case MASK_DARK
: { dc
.SetPen( darkPen
);
181 dc
.DrawPoint( x
,y
); break;
183 case MASK_LIGHT
: { dc
.SetPen( lightPen
);
184 dc
.DrawPoint( x
,y
); break;
194 ///////////////////////////////
196 /***** Impelementation for class wxNewBitmapButton *****/
198 IMPLEMENT_DYNAMIC_CLASS(wxNewBitmapButton
, wxPanel
)
200 BEGIN_EVENT_TABLE( wxNewBitmapButton
, wxPanel
)
202 EVT_LEFT_DOWN( wxNewBitmapButton::OnLButtonDown
)
203 EVT_LEFT_UP ( wxNewBitmapButton::OnLButtonUp
)
204 EVT_MOTION ( wxNewBitmapButton::OnMouseMove
)
206 EVT_SIZE ( wxNewBitmapButton::OnSize
)
207 EVT_PAINT( wxNewBitmapButton::OnPaint
)
209 //EVT_KILL_FOCUS( wxNewBitmapButton::OnKillFocus )
211 EVT_ERASE_BACKGROUND( wxNewBitmapButton::OnEraseBackground
)
215 wxNewBitmapButton::wxNewBitmapButton( const wxBitmap
& labelBitmap
,
216 const wxString
& labelText
,
224 : mTextToLabelGap ( textToLabelGap
),
227 mTextAlignment( alignText
),
228 mIsSticky( isSticky
),
230 mLabelText( labelText
),
231 mImageFileType( wxBITMAP_TYPE_INVALID
),
232 mDepressedBmp( labelBitmap
),
234 mpDepressedImg( NULL
),
235 mpPressedImg ( NULL
),
236 mpDisabledImg ( NULL
),
237 mpFocusedImg ( NULL
),
240 mDragStarted ( FALSE
),
241 mIsPressed ( FALSE
),
243 mPrevPressedState( FALSE
),
244 mPrevInFocusState( FALSE
),
245 mHasFocusedBmp( FALSE
),
246 mFiredEventType( firedEventType
),
248 mBlackPen( wxColour( 0, 0, 0), 1, wxSOLID
),
249 mDarkPen ( wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DSHADOW
), 1, wxSOLID
),
250 mGrayPen ( wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DFACE
), 1, wxSOLID
),
251 mLightPen( wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DHIGHLIGHT
), 1, wxSOLID
),
259 wxNewBitmapButton::wxNewBitmapButton( const wxString
& bitmapFileName
,
260 const wxBitmapType bitmapFileType
,
261 const wxString
& labelText
,
270 : mTextToLabelGap ( 2 ),
273 mTextAlignment( alignText
),
276 mLabelText( labelText
),
277 mImageFileName( bitmapFileName
),
278 mImageFileType( bitmapFileType
),
280 mpDepressedImg( NULL
),
281 mpPressedImg ( NULL
),
282 mpDisabledImg ( NULL
),
283 mpFocusedImg ( NULL
),
285 mDragStarted ( FALSE
),
286 mIsPressed ( FALSE
),
287 mIsInFocus ( FALSE
),
288 mPrevPressedState( FALSE
),
289 mPrevInFocusState( FALSE
),
290 mHasFocusedBmp( FALSE
),
291 mFiredEventType( wxEVT_COMMAND_MENU_SELECTED
),
293 mBlackPen( wxColour( 0, 0, 0), 1, wxSOLID
),
294 mDarkPen ( wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DSHADOW
), 1, wxSOLID
),
295 mGrayPen ( wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DFACE
), 1, wxSOLID
),
296 mLightPen( wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DHIGHLIGHT
), 1, wxSOLID
),
304 wxNewBitmapButton::~wxNewBitmapButton(void)
309 void wxNewBitmapButton::DrawShade( int outerLevel
,
311 wxPen
& upperLeftSidePen
,
312 wxPen
& lowerRightSidePen
)
314 wxBitmap
* pBmp
= GetStateLabel();
316 int x
= mMarginX
- (outerLevel
+ 1);
317 int y
= mMarginY
- (outerLevel
+ 1);
319 int height
= pBmp
->GetHeight() + (outerLevel
+ 1)*2 - 1;
320 int width
= pBmp
->GetWidth() + (outerLevel
+ 1)*2 - 1;
322 dc
.SetPen( upperLeftSidePen
);
323 dc
.DrawLine( x
,y
, x
+ width
, y
);
324 dc
.DrawLine( x
,y
, x
, y
+ height
);
326 dc
.SetPen( lowerRightSidePen
);
327 dc
.DrawLine( x
+ width
, y
, x
+ width
, y
+ height
+ 1 );
328 dc
.DrawLine( x
, y
+ height
, x
+ width
, y
+ height
);
331 void wxNewBitmapButton::DestroyLabels()
333 if ( mpDepressedImg
) delete mpDepressedImg
;
334 if ( mpPressedImg
) delete mpPressedImg
;
335 if ( mpDisabledImg
) delete mpDisabledImg
;
336 if ( mpFocusedImg
) delete mpFocusedImg
;
338 mpDepressedImg
= NULL
;
340 mpDisabledImg
= NULL
;
344 wxBitmap
* wxNewBitmapButton::GetStateLabel()
356 if ( mHasFocusedBmp
)
360 return mpDepressedImg
;
363 return mpDepressedImg
;
367 return mpDisabledImg
;
370 static const unsigned char _gDisableImage
[] = { 0x55,0xAA,0x55,0xAA,
375 void wxNewBitmapButton::RenderLabelImage( wxBitmap
*& destBmp
, wxBitmap
* srcBmp
,
376 bool isEnabled
, bool isPressed
)
378 if ( destBmp
!= 0 ) return;
380 // render lables on-demand
383 srcDc
.SelectObject( *srcBmp
);
385 bool hasText
= ( mTextAlignment
!= NB_NO_TEXT
) &&
386 ( mLabelText
.length() != 0 );
388 bool hasImage
= (mTextAlignment
!= NB_NO_IMAGE
);
396 long txtWidth
, txtHeight
;
398 srcDc
.SetFont( wxSystemSettings::GetSystemFont(wxSYS_DEFAULT_GUI_FONT
) );
399 srcDc
.GetTextExtent( mLabelText
, &txtWidth
, &txtHeight
);
401 if ( mTextAlignment
== NB_ALIGN_TEXT_RIGHT
)
403 destDim
.x
= srcBmp
->GetWidth() + 2*mTextToLabelGap
+ txtWidth
;
406 wxMax( srcBmp
->GetHeight(), txtHeight
);
408 txtPos
.x
= srcBmp
->GetWidth() + mTextToLabelGap
;
409 txtPos
.y
= (destDim
.y
- txtHeight
)/2;
411 imgPos
.y
= (destDim
.y
- srcBmp
->GetHeight())/2;
414 if ( mTextAlignment
== NB_ALIGN_TEXT_BOTTOM
)
417 wxMax( srcBmp
->GetWidth(), txtWidth
);
419 destDim
.y
= srcBmp
->GetHeight() + mTextToLabelGap
+ txtHeight
;
421 txtPos
.x
= (destDim
.x
- txtWidth
)/2;
422 txtPos
.y
= srcBmp
->GetHeight() + mTextToLabelGap
;
423 imgPos
.x
= (destDim
.x
- srcBmp
->GetWidth())/2;
428 int avoidCompilerWarning
= 0;
429 wxASSERT(avoidCompilerWarning
);// unsupported alignment type
436 destDim
.x
= srcBmp
->GetWidth();
437 destDim
.y
= srcBmp
->GetHeight();
440 destBmp
= new wxBitmap( int(destDim
.x
), int(destDim
.y
) );
443 destDc
.SelectObject( *destBmp
);
445 wxBrush
grayBrush( wxSystemSettings::GetSystemColour( wxSYS_COLOUR_3DFACE
), wxSOLID
);
446 wxPen
nullPen( wxColour(0,0,0), 1, wxTRANSPARENT
);
448 destDc
.SetBrush( grayBrush
);
449 destDc
.SetPen( nullPen
);
451 destDc
.DrawRectangle( 0,0, destDim
.x
+1, destDim
.y
+1 );
455 ++imgPos
.x
; ++imgPos
.y
;
456 ++txtPos
.x
; ++txtPos
.y
;
462 destDc
.Blit( imgPos
.x
, imgPos
.y
,
463 srcBmp
->GetWidth()+1,
464 srcBmp
->GetHeight()+1,
465 &srcDc
, 0,0, wxCOPY
,TRUE
);
470 wxWindow
* pTopWnd
= this;
474 wxWindow
* pParent
= pTopWnd
->GetParent();
482 destDc
.SetFont( wxSystemSettings::GetSystemFont( wxSYS_DEFAULT_GUI_FONT
) );
486 destDc
.SetTextForeground( wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNTEXT
) );
490 destDc
.SetTextForeground( wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DSHADOW
) );
492 destDc
.SetTextBackground( wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNFACE
) );
494 destDc
.DrawText( mLabelText
, txtPos
.x
, txtPos
.y
);
498 destDc
.SetBrush( grayBrush
);
499 destDc
.SetPen( nullPen
);
501 destDc
.DrawRectangle( 0,0, destDim
.x
+1, destDim
.y
+1 );
505 ++imgPos
.x
; ++imgPos
.y
;
506 ++txtPos
.x
; ++txtPos
.y
;
512 destDc
.Blit( imgPos
.x
, imgPos
.y
,
513 srcBmp
->GetWidth()+1,
514 srcBmp
->GetHeight()+1,
515 &srcDc
, 0,0, wxCOPY
,TRUE
);
520 wxWindow
* pTopWnd
= this;
524 wxWindow
* pParent
= pTopWnd
->GetParent();
532 destDc
.SetFont( wxSystemSettings::GetSystemFont( wxSYS_DEFAULT_GUI_FONT
) );
536 destDc
.SetTextForeground( wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNTEXT
) );
540 destDc
.SetTextForeground( wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DSHADOW
) );
542 destDc
.SetTextBackground( wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNFACE
) );
544 destDc
.DrawText( mLabelText
, txtPos
.x
, txtPos
.y
);
549 #ifdef __WXMSW__ // This is currently MSW specific
550 gray_out_image_on_dc( destDc
, destDim
.x
, destDim
.y
);
552 wxBrush
checkerBrush( wxBitmap( (const char*)_gDisableImage
,8,8) );
553 checkerBrush
.SetColour( wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE
) );
554 destDc
.SetBrush( checkerBrush
);
555 destDc
.DrawRectangle( imgPos
.x
, imgPos
.y
, srcBmp
->GetWidth()+1, srcBmp
->GetHeight()+1);
558 // adjust button size to fit the new dimensions of the label
559 if ( !mSizeIsSet
&& 0 )
563 destBmp
->GetWidth() + mMarginX
*2,
564 destBmp
->GetHeight() + mMarginY
*2, 0
568 void wxNewBitmapButton::RenderAllLabelImages()
572 RenderLabelImage( mpDisabledImg
, &mDepressedBmp
, FALSE
);
573 RenderLabelImage( mpPressedImg
, &mDepressedBmp
, TRUE
, TRUE
);
574 RenderLabelImage( mpDepressedImg
, &mDepressedBmp
, TRUE
, FALSE
);
575 if ( mHasFocusedBmp
)
577 RenderLabelImage( mpFocusedImg
, &mFocusedBmp
, TRUE
, FALSE
);
582 void wxNewBitmapButton::RenderLabelImages()
589 RenderLabelImage( mpDisabledImg
, &mDepressedBmp
, FALSE
);
595 RenderLabelImage( mpPressedImg
, &mDepressedBmp
, TRUE
, TRUE
);
600 if ( mHasFocusedBmp
)
601 RenderLabelImage( mpFocusedImg
, &mFocusedBmp
, TRUE
, FALSE
);
603 RenderLabelImage( mpDepressedImg
, &mDepressedBmp
, TRUE
, FALSE
);
606 RenderLabelImage( mpDepressedImg
, &mDepressedBmp
, TRUE
, FALSE
);
610 void wxNewBitmapButton::DrawDecorations( wxDC
& dc
)
614 DrawShade( 1, dc
, mGrayPen
, mGrayPen
);
619 DrawShade( 0, dc
, mDarkPen
, mLightPen
);
621 DrawShade( 0, dc
, mLightPen
, mDarkPen
);
624 DrawShade( 0, dc
, mGrayPen
, mGrayPen
);
630 DrawShade( 0, dc
, mDarkPen
, mGrayPen
);
631 DrawShade( 1, dc
, mBlackPen
, mLightPen
);
635 DrawShade( 0, dc
, mGrayPen
, mDarkPen
);
636 DrawShade( 1, dc
, mLightPen
, mBlackPen
);
641 void wxNewBitmapButton::SetLabel(const wxBitmap
& labelBitmap
,
642 const wxString
& labelText
)
646 mLabelText
= labelText
;
647 mDepressedBmp
= labelBitmap
;
649 //RenderLabelImages();
650 RenderAllLabelImages();
653 void wxNewBitmapButton::SetAlignments( int alignText
,
662 mTextAlignment
= alignText
;
663 mTextToLabelGap
= textToLabelGap
;
665 //RenderLabelImages();
666 RenderAllLabelImages();
671 void wxNewBitmapButton::OnLButtonDown( wxMouseEvent
& event
)
673 mPrevPressedState
= FALSE
;
682 void wxNewBitmapButton::OnLButtonUp( wxMouseEvent
& event
)
687 mDragStarted
= FALSE
;
694 if ( IsInWindow( event
.m_x
, event
.m_y
) )
696 // fire event, if mouse was released
697 // within the bounds of button
698 wxCommandEvent
cmd( mFiredEventType
, GetId() );
699 GetParent()->ProcessEvent( cmd
);
703 bool wxNewBitmapButton::IsInWindow( int x
, int y
)
706 GetSize( &width
, &height
);
708 return ( x
>= 0 && y
>= 0 &&
713 void wxNewBitmapButton::OnMouseMove( wxMouseEvent
& event
)
715 mPrevPressedState
=mIsPressed
;
716 mPrevInFocusState
=mIsInFocus
;
717 if ( !mIsInFocus
&& IsInWindow( event
.m_x
, event
.m_y
) )
725 if ( mIsInFocus
&& !IsInWindow( event
.m_x
, event
.m_y
) )
735 if ( IsInWindow( event
.m_x
, event
.m_y
) )
742 if ((mIsPressed
!= mPrevPressedState
) ||
743 (mIsInFocus
!=mPrevInFocusState
))
749 void wxNewBitmapButton::OnSize( wxSizeEvent
& event
)
754 void wxNewBitmapButton::Reshape( )
757 bool wasCreated
= mIsCreated
;
762 // in the case of loading button from stream, check if we
763 // have non-empty image-file name, load if possible
765 if ( mImageFileName
!= "" )
767 mDepressedBmp
.LoadFile( mImageFileName
, mImageFileType
);
769 //wxMessageBox("Image Loaded!!!");
772 //RenderLabelImages();
773 RenderAllLabelImages();
775 wxBitmap
* pCurImg
= GetStateLabel();
777 int w
= pCurImg
->GetWidth(),
778 h
= pCurImg
->GetHeight();
780 SetSize( 0,0, w
+ mMarginX
*2, h
+ mMarginY
*2 , 0 );
784 void wxNewBitmapButton::DrawLabel( wxDC
& dc
)
786 wxBitmap
* pCurBmp
= GetStateLabel();
788 if ( pCurBmp
== NULL
)
791 OnSize( evt
); // fake it up!
793 //RenderLabelImages();
794 pCurBmp
= GetStateLabel();
798 mdc
.SelectObject( *pCurBmp
);
800 dc
.Blit( mMarginX
, mMarginY
,
802 pCurBmp
->GetHeight(),
806 mdc
.SelectObject( wxNullBitmap
);
809 void wxNewBitmapButton::OnPaint( wxPaintEvent
& event
)
813 // first, make sure images for current state are prepared
814 //RenderLabelImages();
818 DrawDecorations( dc
);
821 void wxNewBitmapButton::OnEraseBackground( wxEraseEvent
& event
)
826 void wxNewBitmapButton::OnKillFocus( wxFocusEvent
& event
)
830 wxMessageBox("kill-focus for button!");