1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: Contrib. demo
4 // Author: Aleksandras Gluchovas
8 // Copyright: (c) Aleksandras Gluchovas
9 // Licence: wxWindows license
10 /////////////////////////////////////////////////////////////////////////////
13 #pragma implementation "newbmpbtn.cpp"
14 #pragma interface "newbmpbtn.cpp"
17 // For compilers that support precompilation, includes "wx/wx.h".
18 #include "wx/wxprec.h"
30 #include "newbmpbtn.h"
31 #include "wx/utils.h" // import wxMin,wxMax macros
33 ///////////// button-label rendering helpers //////////////////
35 static int* create_array( int width
, int height
, int fill
= 0 )
37 int* array
= new int[width
*height
];
39 int len
= width
*height
;
40 for( int i
= 0; i
!= len
; ++i
) array
[i
] = fill
;
45 #define GET_ELEM(array,x,y) (array[width*(y)+(x)])
47 #define MIN_COLOR_DIFF 10
49 #define IS_IN_ARRAY(x,y) ( (x) < width && (y) < height && (x) >= 0 && (y) >= 0 )
51 #define GET_RED(col) col & 0xFF
52 #define GET_GREEN(col) (col >> 8) & 0xFF
53 #define GET_BLUE(col) (col >> 16) & 0xFF
55 #define MAKE_INT_COLOR(red,green,blue) ( (red) | \
56 ( ( (green) << 8 ) & 0xFF00 ) | \
57 ( ( (blue) << 16) & 0xFF0000) \
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 ) \
69 // helper function, used internally
71 static void gray_out_pixmap( int* src
, int* dest
, int width
, int height
)
73 // assuming the pixels along the edges are of the background color
74 int bgCol
= GET_ELEM(src
,0,0);
81 int cur
= GET_ELEM(src
,x
,y
);
84 int g
= GET_GREEN(cur
);
85 int b
= GET_BLUE(cur
);
87 if ( IS_IN_ARRAY(x
-1,y
-1) )
89 int upperElem
= GET_ELEM(src
,x
-1,y
-1);
91 // if the upper element is lighter than current
92 if ( IS_GREATER(upperElem
,cur
) )
94 GET_ELEM(dest
,x
,y
) = MASK_DARK
;
97 // if the current element is ligher than the upper
98 if ( IS_GREATER(cur
,upperElem
) )
100 GET_ELEM(dest
,x
,y
) = MASK_LIGHT
;
104 if ( GET_ELEM(dest
,x
-1,y
-1) == MASK_LIGHT
)
106 GET_ELEM(dest
,x
,y
) = MASK_BG
;
108 if ( GET_ELEM(dest
,x
-1,y
-1 ) == MASK_DARK
)
110 GET_ELEM(dest
,x
,y
) = MASK_DARK
;
112 GET_ELEM(dest
,x
,y
) = MASK_BG
;
118 if ( IS_IN_ARRAY(x
+1,y
-1) )
124 while( IS_IN_ARRAY(x
-1,y
+1) )
129 if ( IS_IN_ARRAY(x
,y
+1) )
135 if ( IS_IN_ARRAY(x
+1,y
) )
146 // alg. for making the image look "grayed" (e.g. disabled button)
147 // NOTE:: used GetPixel(), which is Windows-Only!
149 void greay_out_image_on_dc( wxDC
& dc
, int width
, int height
)
151 // assuming the pixels along the edges are of the background color
153 dc
.GetPixel( 0, 0, &bgCol
);
155 wxPen
darkPen ( wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DSHADOW
),1, wxSOLID
);
156 wxPen
lightPen( wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DHIGHLIGHT
),1, wxSOLID
);
157 wxPen
bgPen ( bgCol
, 1, wxSOLID
);
159 int* src
= create_array( width
, height
, MASK_BG
);
160 int* dest
= create_array( width
, height
, MASK_BG
);
163 for( y
= 0; y
!= height
; ++y
)
165 for( int x
= 0; x
!= width
; ++x
)
168 dc
.GetPixel( x
,y
, &col
);
174 int o
= MAKE_INT_COLOR( r
,g
,b
);
176 GET_ELEM(src
,x
,y
) = MAKE_INT_COLOR( col
.Red(), col
.Green(), col
.Blue() );
179 gray_out_pixmap( src
, dest
, width
, height
);
181 for( y
= 0; y
!= height
; ++y
)
183 for( int x
= 0; x
!= width
; ++x
)
185 int mask
= GET_ELEM(dest
,x
,y
);
189 case MASK_BG
: { dc
.SetPen( bgPen
);
190 dc
.DrawPoint( x
,y
); break;
192 case MASK_DARK
: { dc
.SetPen( darkPen
);
193 dc
.DrawPoint( x
,y
); break;
195 case MASK_LIGHT
: { dc
.SetPen( lightPen
);
196 dc
.DrawPoint( x
,y
); break;
206 ///////////////////////////////
208 /***** Impelementation for class wxNewBitmapButton *****/
210 IMPLEMENT_DYNAMIC_CLASS(wxNewBitmapButton
, wxPanel
)
212 BEGIN_EVENT_TABLE( wxNewBitmapButton
, wxPanel
)
214 EVT_LEFT_DOWN( wxNewBitmapButton::OnLButtonDown
)
215 EVT_LEFT_UP ( wxNewBitmapButton::OnLButtonUp
)
216 EVT_MOTION ( wxNewBitmapButton::OnMouseMove
)
218 EVT_SIZE ( wxNewBitmapButton::OnSize
)
219 EVT_PAINT( wxNewBitmapButton::OnPaint
)
221 //EVT_KILL_FOCUS( wxNewBitmapButton::OnKillFocus )
223 EVT_ERASE_BACKGROUND( wxNewBitmapButton::OnEraseBackground
)
227 wxNewBitmapButton::wxNewBitmapButton( const wxBitmap
& labelBitmap
,
228 const wxString
& labelText
,
236 : mpDepressedImg( NULL
),
237 mpPressedImg ( NULL
),
238 mpDisabledImg ( NULL
),
239 mpFocusedImg ( NULL
),
243 mTextAlignment( alignText
),
246 mIsPressed ( FALSE
),
247 mDragStarted ( FALSE
),
248 mPrevPressedState( FALSE
),
249 mTextToLabelGap ( textToLabelGap
),
251 mBlackPen( wxColour( 0, 0, 0), 1, wxSOLID
),
252 mDarkPen ( wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DSHADOW
), 1, wxSOLID
),
253 mGrayPen ( wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DFACE
), 1, wxSOLID
),
254 mLightPen( wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DHIGHLIGHT
), 1, wxSOLID
),
256 mFiredEventType( firedEventType
),
257 mIsSticky( isSticky
),
261 mHasFocusedBmp( FALSE
),
264 mDepressedBmp( labelBitmap
),
265 mLabelText( labelText
),
270 wxNewBitmapButton::wxNewBitmapButton( const wxString
& bitmapFileName
,
271 const int bitmapFileType
,
272 const wxString
& labelText
,
281 : mpDepressedImg( NULL
),
282 mpPressedImg ( NULL
),
283 mpDisabledImg ( NULL
),
284 mpFocusedImg ( NULL
),
288 mTextAlignment( alignText
),
291 mIsPressed ( FALSE
),
292 mDragStarted ( FALSE
),
293 mPrevPressedState( FALSE
),
294 mTextToLabelGap ( 2 ),
296 mBlackPen( wxColour( 0, 0, 0), 1, wxSOLID
),
297 mDarkPen ( wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DSHADOW
), 1, wxSOLID
),
298 mGrayPen ( wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DFACE
), 1, wxSOLID
),
299 mLightPen( wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DHIGHLIGHT
), 1, wxSOLID
),
301 mFiredEventType( wxEVT_COMMAND_MENU_SELECTED
),
306 mHasFocusedBmp( FALSE
),
309 mLabelText( labelText
),
310 mImageFileName( bitmapFileName
),
311 mImageFileType( bitmapFileType
)
313 //mDepressedBmp.LoadFile( bitmapFileName, bitmapFileType );
316 wxNewBitmapButton::~wxNewBitmapButton(void)
321 void wxNewBitmapButton::DrawShade( int outerLevel
,
323 wxPen
& upperLeftSidePen
,
324 wxPen
& lowerRightSidePen
)
326 wxBitmap
* pBmp
= GetStateLabel();
328 int x
= mMarginX
- (outerLevel
+ 1);
329 int y
= mMarginY
- (outerLevel
+ 1);
331 int height
= pBmp
->GetHeight() + (outerLevel
+ 1)*2 - 1;
332 int width
= pBmp
->GetWidth() + (outerLevel
+ 1)*2 - 1;
334 dc
.SetPen( upperLeftSidePen
);
335 dc
.DrawLine( x
,y
, x
+ width
, y
);
336 dc
.DrawLine( x
,y
, x
, y
+ height
);
338 dc
.SetPen( lowerRightSidePen
);
339 dc
.DrawLine( x
+ width
, y
, x
+ width
, y
+ height
+ 1 );
340 dc
.DrawLine( x
, y
+ height
, x
+ width
, y
+ height
);
343 void wxNewBitmapButton::DestroyLabels()
345 if ( mpDepressedImg
) delete mpDepressedImg
;
346 if ( mpPressedImg
) delete mpPressedImg
;
347 if ( mpDisabledImg
) delete mpDisabledImg
;
348 if ( mpFocusedImg
) delete mpFocusedImg
;
350 mpDepressedImg
= NULL
;
352 mpDisabledImg
= NULL
;
356 wxBitmap
* wxNewBitmapButton::GetStateLabel()
368 if ( mHasFocusedBmp
)
372 return mpDepressedImg
;
375 return mpDepressedImg
;
379 return mpDisabledImg
;
382 void wxNewBitmapButton::RenderLabelImage( wxBitmap
*& destBmp
, wxBitmap
* srcBmp
,
383 bool isEnabled
, bool isPressed
)
385 if ( destBmp
!= 0 ) return;
387 // render lables on-demand
390 srcDc
.SelectObject( *srcBmp
);
392 bool hasText
= ( mTextAlignment
!= NB_NO_TEXT
) &&
393 ( mLabelText
.length() != 0 );
395 bool hasImage
= (mTextAlignment
!= NB_NO_IMAGE
);
403 long txtWidth
, txtHeight
;
405 srcDc
.SetFont( wxSystemSettings::GetSystemFont(wxSYS_DEFAULT_GUI_FONT
) );
406 srcDc
.GetTextExtent( mLabelText
, &txtWidth
, &txtHeight
);
408 if ( mTextAlignment
== NB_ALIGN_TEXT_RIGHT
)
410 destDim
.x
= srcBmp
->GetWidth() + 2*mTextToLabelGap
+ txtWidth
;
413 wxMax( srcBmp
->GetHeight(), txtHeight
);
415 txtPos
.x
= srcBmp
->GetWidth() + mTextToLabelGap
;
416 txtPos
.y
= (destDim
.y
- txtHeight
)/2;
418 imgPos
.y
= (destDim
.y
- srcBmp
->GetHeight())/2;
421 if ( mTextAlignment
== NB_ALIGN_TEXT_BOTTOM
)
424 wxMax( srcBmp
->GetWidth(), txtWidth
);
426 destDim
.y
= srcBmp
->GetHeight() + mTextToLabelGap
+ txtHeight
;
428 txtPos
.x
= (destDim
.x
- txtWidth
)/2;
429 txtPos
.y
= srcBmp
->GetHeight() + mTextToLabelGap
;
430 imgPos
.x
= (destDim
.x
- srcBmp
->GetWidth())/2;
433 else wxASSERT(0);// unsupported alignment type
439 destDim
.x
= srcBmp
->GetWidth();
440 destDim
.y
= srcBmp
->GetHeight();
443 destBmp
= new wxBitmap( int(destDim
.x
), int(destDim
.y
) );
446 destDc
.SelectObject( *destBmp
);
448 wxBrush
grayBrush( wxSystemSettings::GetSystemColour( wxSYS_COLOUR_3DFACE
), wxSOLID
);
449 wxPen
nullPen( wxColour(0,0,0), 1, wxTRANSPARENT
);
451 destDc
.SetBrush( grayBrush
);
452 destDc
.SetPen( nullPen
);
454 destDc
.DrawRectangle( 0,0, destDim
.x
+1, destDim
.y
+1 );
458 ++imgPos
.x
; ++imgPos
.y
;
459 ++txtPos
.x
; ++txtPos
.y
;
464 destDc
.Blit( imgPos
.x
, imgPos
.y
,
465 srcBmp
->GetWidth()+1,
466 srcBmp
->GetHeight()+1,
467 &srcDc
, 0,0, wxCOPY
,TRUE
);
472 wxWindow
* pTopWnd
= this;
476 wxWindow
* pParent
= pTopWnd
->GetParent();
478 if ( pParent
== 0 ) break;
483 destDc
.SetFont( wxSystemSettings::GetSystemFont( wxSYS_DEFAULT_GUI_FONT
) );
485 // Should be wxSYS_COLOUR_BTNTEXT, but gtk gives white?
486 destDc
.SetTextForeground( wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNTEXT
) );
487 destDc
.SetTextBackground( wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNFACE
) );
489 destDc
.DrawText( mLabelText
, txtPos
.x
, txtPos
.y
);
494 greay_out_image_on_dc( destDc
, destDim
.x
, destDim
.y
);
496 // adjust button size to fit the new dimensions of the label
497 if ( !mSizeIsSet
&& 0 )
501 destBmp
->GetWidth() + mMarginX
*2,
502 destBmp
->GetHeight() + mMarginY
*2, 0
507 void wxNewBitmapButton::RenderLabelImages()
509 if ( !mIsCreated
) return;
513 RenderLabelImage( mpDisabledImg
, &mDepressedBmp
, FALSE
);
519 RenderLabelImage( mpPressedImg
, &mDepressedBmp
, TRUE
, TRUE
);
524 if ( mHasFocusedBmp
)
526 RenderLabelImage( mpFocusedImg
, &mFocusedBmp
, TRUE
, FALSE
);
528 RenderLabelImage( mpDepressedImg
, &mDepressedBmp
, TRUE
, FALSE
);
531 RenderLabelImage( mpDepressedImg
, &mDepressedBmp
, TRUE
, FALSE
);
535 void wxNewBitmapButton::DrawDecorations( wxDC
& dc
)
539 DrawShade( 1, dc
, mGrayPen
, mGrayPen
);
545 DrawShade( 0, dc
, mDarkPen
, mLightPen
);
547 DrawShade( 0, dc
, mLightPen
, mDarkPen
);
550 DrawShade( 0, dc
, mGrayPen
, mGrayPen
);
556 DrawShade( 0, dc
, mDarkPen
, mGrayPen
);
557 DrawShade( 1, dc
, mBlackPen
, mLightPen
);
561 DrawShade( 0, dc
, mGrayPen
, mDarkPen
);
562 DrawShade( 1, dc
, mLightPen
, mBlackPen
);
567 void wxNewBitmapButton::SetLabel(const wxBitmap
& labelBitmap
,
568 const wxString
& labelText
)
572 mLabelText
= labelText
;
573 mDepressedBmp
= labelBitmap
;
578 void wxNewBitmapButton::SetAlignments( int alignText
,
587 mTextAlignment
= alignText
;
588 mTextToLabelGap
= textToLabelGap
;
595 void wxNewBitmapButton::OnLButtonDown( wxMouseEvent
& event
)
597 mPrevPressedState
= FALSE
;
607 void wxNewBitmapButton::OnLButtonUp( wxMouseEvent
& event
)
609 if ( !mDragStarted
) return;
611 mDragStarted
= FALSE
;
618 if ( IsInWindow( event
.m_x
, event
.m_y
) )
620 // fire event, if mouse was released
621 // within the bounds of button
622 wxCommandEvent
cmd( mFiredEventType
, GetId() );
623 GetParent()->ProcessEvent( cmd
);
627 bool wxNewBitmapButton::IsInWindow( int x
, int y
)
630 GetSize( &width
, &height
);
632 return ( x
>= 0 && y
>= 0 &&
637 void wxNewBitmapButton::OnMouseMove( wxMouseEvent
& event
)
639 if ( !mIsInFocus
&& IsInWindow( event
.m_x
, event
.m_y
) )
647 if ( mIsInFocus
&& !IsInWindow( event
.m_x
, event
.m_y
) )
657 if ( IsInWindow( event
.m_x
, event
.m_y
) )
663 if ( mIsPressed
!= mPrevPressedState
)
667 mPrevPressedState
= mIsPressed
;
674 void wxNewBitmapButton::OnSize( wxSizeEvent
& event
)
679 void wxNewBitmapButton::Reshape( )
681 bool wasCreated
= mIsCreated
;
686 // in the case of loading button from stream, check if we
687 // have non-empty image-file name, load if possible
689 if ( mImageFileName
!= "" )
691 mDepressedBmp
.LoadFile( mImageFileName
, mImageFileType
);
693 //wxMessageBox("Image Loaded!!!");
698 wxBitmap
* pCurImg
= GetStateLabel();
700 int w
= pCurImg
->GetWidth(),
701 h
= pCurImg
->GetHeight();
703 SetSize( 0,0, w
+ mMarginX
*2, h
+ mMarginY
*2 , 0 );
707 void wxNewBitmapButton::DrawLabel( wxDC
& dc
)
709 wxBitmap
* pCurBmp
= GetStateLabel();
711 if ( pCurBmp
== NULL
)
714 OnSize( evt
); // fake it up!
717 pCurBmp
= GetStateLabel();
721 mdc
.SelectObject( *pCurBmp
);
723 dc
.Blit( mMarginX
, mMarginY
,
725 pCurBmp
->GetHeight(),
729 mdc
.SelectObject( wxNullBitmap
);
732 void wxNewBitmapButton::OnPaint( wxPaintEvent
& event
)
736 // first, make sure images for current state are prepared
741 DrawDecorations( dc
);
744 void wxNewBitmapButton::OnEraseBackground( wxEraseEvent
& event
)
749 void wxNewBitmapButton::OnKillFocus( wxFocusEvent
& event
)
753 wxMessageBox("kill-focus for button!");