//buttonx.cpp
#include <owl/pch.h>
#include <stdio.h>
#include "source/buttonx.h"
#include <math.h>
DEFINE_RESPONSE_TABLE1(TButtonEx, TGlyphDib)
EV_WM_EXITMENULOOP,
EV_WM_MOUSEMOVE,
EV_WM_LBUTTONUP,
EV_WM_LBUTTONDOWN,
EV_WM_KEYDOWN,
EV_WM_KEYUP,
END_RESPONSE_TABLE;
TButtonEx::TButtonEx(TWindow* parent, int id, constcharfar*
text,
int X, int Y, int W, int H, bool isDefault,
TModule* module)
: TGlyphDib(parent, id, text,X,Y,W,H, isDefault,module)
{
BX_InitVars();
}
TButtonEx::TButtonEx(TWindow* parent, int resourceId,
TModule* module)
:TGlyphDib(parent, resourceId, module)
{
BX_InitVars();
}
TButtonEx::~TButtonEx()
{
}
void TButtonEx::BX_InitVars()
{
BX_ColorText=TColor::SysBtnText;
BX_ColorTextNegative=TColor::SysBtnText;
BX_ColorBk=TColor::Sys3dFace;
BX_ColorBkNegative=TColor::Sys3dFace;
BX_GadgetBorder=true;
BX_ThinBorder=false;
BX_Focus=false;
BX_FlatAlways=false;
BX_Flat=false;
BX_TextOnGlyph=false;
BX_Menu=0;
MouseIsIn=false;
WasPushed=false;
}
void TButtonEx::BX_SetCursor(int id)
{
SetCursor(GetModule(),id);
}
void TButtonEx::BX_SetMenu(int id)
{
BX_Menu=id;
}
void TButtonEx::PaintFace(TDC& dc, TRect& rect)
{
// Fill the background with
the face color
TColor bkcolor=(MouseIsIn||IsSet(biPushed))?BX_ColorBkNegative:BX_ColorBk;
TBrush brush(bkcolor);
dc.FillRect(rect, brush);
// Grab the glyph and it's
size
TDib* glyph = 0;
// Pointer to glyph
TRect glyphRect(0, 0,
0,
0);
// Size of glyph
if (IsSet(biShowGlyph))
{
glyph = dibOf(gtUp);
if( ButtonDisabled() )
glyph = dibOf(gtDisabled);
else if( ButtonFocus() )
glyph = dibOf(gtFocus);
else if( ButtonDown() )
glyph = dibOf(gtDown);
else if( ButtonNegative()
) glyph = dibOf(gtNegative);
CHECK(glyph && glyph->IsGDIObject());
glyphRect.Set(0,
0,
glyph->Width(), glyph->Height());
}
// Grab some information about
the text/caption
int len = 0;
// Length of Caption
TRect textRect(0, 0,
0,
0);
// Size of text
TAPointer<char> text;
// Pointer to caption dynamic buffer
TPointer<TFont> tmpFnt;
// Object wrapping font handle
TColor textColor;
// Color used for button's text
if (IsSet(biShowText))
{
len = GetWindowTextLength();
if (len)
{
if (!BtnFontOf())
//useless checks!
{
HFONT hFont =
HFONT(::SendMessage(::GetParent(*this), WM_GETFONT,0,
0));
if (!hFont)
hFont
= HFONT(GetStockObject(TSystem::Has3dUI() ? ANSI_VAR_FONT :SYSTEM_FONT));
if (hFont)
tmpFnt
=
new TFont(hFont);
}
if (BtnFontOf())
{
CHECK(BtnFont->IsGDIObject());
dc.SelectObject(*BtnFontOf());
}
else if (tmpFnt)
{
CHECK(((TFont&)tmpFnt).IsGDIObject());
dc.SelectObject((TFont&)tmpFnt);
}
text = new char[len+1];
GetWindowText(text, len+1);
textRect.Set(0,
0,
rect.Width() - glyphRect.Width(), SHRT_MAX);
if (IsSet(biDisabled))
{
textColor = TColor::SysGrayText;
if ((textColor
== TColor::Sys3dFace.GetValue()) ||
(textColor == TColor::SysBtnText.GetValue())) {
textColor
= TColor::Sys3dShadow;
}
}
else
{
if (MouseIsIn
|| IsSet(biPushed) )
textColor
= BX_ColorTextNegative;
else
textColor
= BX_ColorText;
}
TColor oldColor = dc.SetTextColor(textColor);
dc.DrawText(text, len, textRect,
DT_WORDBREAK|DT_CALCRECT);
dc.SetTextColor(oldColor);
}
}
// If we have text and/or
glyph, lay them out and paint them
if (!textRect.IsNull() || !glyphRect.IsNull())
{
if( (!textRect.IsNull()) & (BX_TextOnGlyph)
)
{
int x1=(rect.Width()-glyphRect.Width())/2;
int x2=(rect.Height()-glyphRect.Height())/2;
glyphRect=TRect(TPoint( x1,x2
), glyphRect.Size() );
int dy=(rect.Height()-dc.GetTextExtent(text,
strlen(text)).cy)/2;
textRect.Set(rect.left,rect.top+dy,rect.right,rect.bottom-dy);
}
else
{
LayoutTextGlyph(rect, textRect,
glyphRect);
}
// Offset things
to the lower right if we're in down
if (IsSet(biPushed)) {
////changed
if (!glyphRect.IsNull()
&& ((glyph == dibOf(gtDown))|(glyph == dibOf(gtNegative) )) )
glyphRect.Offset(1,
1);
if (!textRect.IsNull())
textRect.Offset(1,
1);
}
// Paint the components
of the button
if (!glyphRect.IsNull()) {
PRECONDITION(glyph &&
glyph->IsGDIObject());
if(IsSet(biDisabled))
{
TBitmap
bitmap(*glyph, &TPalette((HPALETTE)::GetStockObject(DEFAULT_PALETTE)));
TUIFace uiFace(glyphRect,
bitmap);
uiFace.Paint(dc,
TPoint(0,
0),
IsSet(biDisabled)?TUIFace::Disabled:TUIFace::Normal, IsSet(biPushed));
}
else
{
dc.SetDIBitsToDevice(glyphRect,TPoint(0,0),*glyph);
}
}
if (!textRect.IsNull()) {
int mode = dc.SetBkMode(TRANSPARENT);
TColor oldColor = dc.SetTextColor(textColor);
if(BX_TextOnGlyph)
dc.DrawText(text,
len, textRect, DT_CENTER|DT_WORDBREAK);
else
dc.DrawText(text,
len, textRect, DT_WORDBREAK);
if(IsSet(biDisabled))
{
dc.SetTextColor(TColor::Sys3dHilight);
if(BX_TextOnGlyph)
dc.DrawText(text,
len, textRect.OffsetBy(1,1),
DT_CENTER|DT_WORDBREAK);
else
dc.DrawText(text,
len, textRect.OffsetBy(1,1),
DT_WORDBREAK);
}
dc.SetTextColor(oldColor);
dc.SetBkMode(mode);
}
}
// Paint the focus rect [if
necessary]
if (IsSet(biFocus))
PaintFocusRect(dc, rect);
// Restore font
if (len && (BtnFontOf() || tmpFnt))
dc.RestoreFont();
}
void TButtonEx::PaintFrame(TDC& dc, TRect&
rect)
{
if(BX_FlatAlways)
return; //no border
if(BX_Flat & !MouseIsIn) return;
//no
border - unless mouse is in
//I don't remmember what the hell
I did here
if(BX_ThinBorder)
{
if(IsSet(biPushed))
::DrawEdge(dc, (LPRECT)&rect,
BDR_SUNKENOUTER,BF_ADJUST|BF_RECT);
else
::DrawEdge(dc, (LPRECT)&rect,
BDR_RAISEDINNER,BF_ADJUST|BF_RECT);
}
else if(BX_GadgetBorder)
{
if(IsSet(biPushed))
::DrawEdge(dc, (LPRECT)&rect,
EDGE_SUNKEN ,BF_ADJUST|BF_RECT);
else
{
::DrawEdge(dc, (LPRECT)&rect,
BDR_RAISEDINNER ,BF_ADJUST|BF_RECT);
::DrawEdge(dc, (LPRECT)&rect,
BDR_RAISEDOUTER ,BF_ADJUST|BF_BOTTOM|BF_BOTTOMRIGHT);
}
}
else
{
TUIBorder::TStyle style;
style=(IsSet(biPushed) ? TUIBorder::ButtonDn
: TUIBorder::WndRaised );
TUIBorder uiBorder(rect,style,BX_ThinBorder?TUIBorder::Soft:0);
uiBorder.Paint(dc);
rect = uiBorder.GetClientRect();
}
}
void TButtonEx::PaintFocusRect(TDC& dc, const
TRect& faceRect)
{
if(!BX_Focus) return;
TGlyphDib::PaintFocusRect(dc, faceRect);
}
void TButtonEx::MouseEnter()
{
if(MouseIsIn) return;
SetCapture();
MouseIsIn=true;
Invalidate(true);
}
void TButtonEx::MouseLeave()
{
WasPushed=false;
if (GetCapture() == *this) ReleaseCapture();
if(!MouseIsIn) return;
MouseIsIn=false;
if(IsSet(biPushed))
SendMessage(BM_SETSTATE, false);
Invalidate(true);
}
void TButtonEx::EvMouseMove(uint modKeys, TPoint&
point)
{
//sometimes the user pushes
the button, then drags it outside
//then comes back in. If
this sort of none-sense is in progress
//then let the parent class
deal with it.
if(WasPushed)
{
TGlyphDib::EvMouseMove(modKeys, point);
return;
}
bool hit=(GetClientRect().Contains(point));
if(hit) MouseEnter();
else MouseLeave();
}
void TButtonEx::EvLButtonDown(uint msg, TPoint&
point)
{
TGlyphDib::EvLButtonDown(msg, point);
SetCapture();
MouseIsIn=true;
WasPushed=true;
}
void TButtonEx::EvLButtonUp(uint, TPoint& point)
{
if( IsSet(biPushed) & (GetCapture()==*this)
){
ReleaseCapture();
if(!BX_Menu)//
if there is no menu push the button back up
SendMessage(BM_SETSTATE, false);
TRect rect;
GetClientRect(rect);
if (rect.Contains(point))
SendNotificationEx();
}
WasPushed=false;
MouseLeave();
}
//helper function - if true, then
PaintFace should use gtNegative
bool TButtonEx::ButtonNegative()
{
return( (!IsSet(biPushed)) && dibOf(gtNegative)
&& MouseIsIn );
}
//helper function - if true, then
PaintFace should use gtDown
bool TButtonEx::ButtonDown()
{
return (IsSet(biPushed) && dibOf(gtDown));
}
//helper function - if true, then
PaintFace should use gtDisabled
bool TButtonEx::ButtonDisabled()
{
return (IsSet(biDisabled) && dibOf(gtDisabled));
}
//helper function - if true, then
PaintFace should use gtFocus
bool TButtonEx::ButtonFocus()
{
return((IsSet(biFocus)) && dibOf(gtFocus));
}
void TButtonEx::MapColors(TDib* dib, TGlyphType type)
{
// dib->MapUIColors(TDib::MapFace|TDib::MapText|TDib::MapShadow|TDib::MapHighlight);
// Normally the above statement
would be enough to map the colors;
// but in this case background
color may be different
// so you have to map LtGray
to the actual background color
dib->MapColor(TColor::Black, TColor::SysBtnText);
dib->MapColor(TColor::Gray, TColor::Sys3dShadow);
dib->MapColor(TColor::White, TColor::Sys3dHilight);
//If we are setting up the
negative image, map light gray to
//BX_ColorBkNegative. This
color may be different than
//BX_ColorBk
if((type==gtNegative)|(type==gtDown))
dib->MapColor(TColor::LtGray, BX_ColorBkNegative);
//map LtGray to the current
background color
else
dib->MapColor(TColor::LtGray, BX_ColorBk);
}
void TButtonEx::SendNotificationEx()
{
if(BX_Menu)
{
TPopupMenu popup;
popup = TPopupMenu(GetModule()->LoadMenu(BX_Menu),
AutoDelete);
popup.TrackPopupMenu(TPM_LEFTALIGN | TPM_LEFTBUTTON|TPM_RIGHTBUTTON,GetWindowRect().BottomLeft(),0,Parent->HWindow);
MouseLeave();
SendMessage(BM_SETSTATE, false);
}
else
TGlyphDib::SendNotificationEx();
if (!IsSet(biFocus))
SetFocus();
}
void TButtonEx::EvExitMenuLoop(bool)
{
WasPushed=false;
ReleaseCapture();
MouseIsIn=false;
SendMessage(BM_SETSTATE, false);
Invalidate(true);
}
void TButtonEx::EvKeyUp(uint key, uint repeatCount,
uint flags)
{
if(!BX_Focus) return;
TGlyphDib::EvKeyUp(key, repeatCount, flags);
}
void TButtonEx::EvKeyDown(uint key, uint repeatCount,
uint flags)
{
if(!BX_Focus) return;
TGlyphDib::EvKeyDown(key, repeatCount, flags);
}
void TButtonEx::PaintButton(TDC& dc)
{
TGlyphDib::PaintButton(dc);
}