// ****************************************************************************
// Copyright (C) 1998 by Dieter Windau
// All rights reserved
//
// gadgetex.cpp: implementation file
// Version: 1.6
// Date: 08.11.1998
// Author: Dieter Windau
//
// Freeware OWL classes that extents the dockable and gadget system
//
// You are free to use/modify this code but leave this header intact.
// May not be sold for profit.
//
// Tested with Borland C++ 5.02, OWL 5.02, OWL6 patch #3 and with Windows
// NT 4.0 SP3 but I think the class should work with Windows 95 too.
// This file is provided "as is" with no expressed or implied warranty.
// Use at your own risk.
//
// This package contains many classes and source that are based on other OWL
// developers work. Very special thanks to Alan Chambers, Christopher Kohlhoff,
// Jo Parrello, Mark Hatsell, Michael Mogensen and Yura Bidus
//
// Please send me bug reports, bug fixes, enhancements, requests, etc., and
// I'll try to keep this in next versions:
// EMail: dieter.windau@usa.net
// Web: http://members.aol.com/softengage/index.htm
//
// ****************************************************************************
#include <owlext\pch.h>
#pragma hdrstop
#include <owl/celarray.h>
#include <owl/uihelper.h>
#include <owl/tooltip.h>
#include <owl/rcntfile.h>
#include <owl/rcntfile.rh>
#include <owl/uimetric.h>
#include <owlext/util.h>
#include <owlext/harborex.h>
#include <owlext/dockingex.h>
#include <owlext/gadgetex.h>
#include <owlext/gadgctrl.h>
using namespace owl;
namespace OwlExt {
DIAG_DEFINE_GROUP(GadgetEx, 1, 0);
// ******************** TInvisibleGadgetEx ************************************
TInvisibleGadgetEx::TInvisibleGadgetEx()
:
TGadget(CM_INVISIBLEGADGET)
{
ShrinkWrapWidth = ShrinkWrapHeight = false;
SetEnabled(false);
SetVisible(true);
Bounds.right = Bounds.bottom = 22;
TRACEX(GadgetEx, 0, "TInvisibleGadgetEx constructed @" << (void*)this);
}
TInvisibleGadgetEx::~TInvisibleGadgetEx()
{
TRACEX(GadgetEx, 0, "TInvisibleGadgetEx destructed @" << (void*)this);
}
// ******************** TButtonGadgetEnablerEx *******************************
//
// Command enabler for my extended button gadgets
//
class TButtonGadgetEnablerEx : public TCommandEnabler {
public:
TButtonGadgetEnablerEx(TWindow::THandle hReceiver, TButtonGadgetEx* g)
:
TCommandEnabler(g->GetId(), hReceiver),
Gadget(g)
{
}
// Override TCommandEnabler virtuals
//
void Enable(bool);
void SetText(LPCTSTR);
void SetCheck(int);
protected:
TButtonGadgetEx* Gadget;
};
//
// Enable or disable the button gadget
//
void
TButtonGadgetEnablerEx::Enable(bool enable)
{
TCommandEnabler::Enable(enable);
Gadget->SetEnabled(enable);
}
//
// Handle the SetText request for a button gadget. Currently does nothing.
//
void
TButtonGadgetEnablerEx::SetText(LPCTSTR)
{
# pragma warn -ccc
# pragma warn -rch
CHECK(true);
# pragma warn .rch
# pragma warn .ccc
}
//
// Set the check-state for the button gadget
//
void
TButtonGadgetEnablerEx::SetCheck(int state)
{
// Call my SetButtonState
Gadget->SetButtonState(TButtonGadget::TState(state));
}
// ******************** TButtonGadgetEx ***************************************
TButtonGadgetEx::TButtonGadgetEx(TResId glyphResIdOrIndex,
int id,
TType type,
bool enabled, // initial state before cmd enabling
TState state,
bool sharedGlyph):
TButtonGadget(glyphResIdOrIndex, id, type, enabled, state, sharedGlyph)
{
MouseInGadget = false;
TRACEX(GadgetEx, 0, "TButtonGadgetEx constructed @" << (void*)this);
}
TButtonGadgetEx::~TButtonGadgetEx()
{
TRACEX(GadgetEx, 0, "TButtonGadgetEx destructed @" << (void*)this);
}
//
// Overwrite to call my BetterChecckExclusively() and my SyncronizeButtons()
// It is not a virtual function, but they are called from TButtonGadgetEnablerEx
//
void
TButtonGadgetEx::SetButtonState(TState newState)
{
if (newState != State) {
switch (Type)
{
case Exclusive:
if (newState == Down)
BetterCheckExclusively();
break;
case NonExclusive:
State = newState;
SyncronizeButtons(GetId(), newState);
break;
case SemiExclusive:
BetterCheckExclusively();
break;
case Command:
State = newState;
Invalidate(); // Call my not virtual Invalidate() function
Update();
break;
default: // TODO: RepeatCmd is not handled; handle or clarify.
WARN(true, _T("TButtonGadgetEx::SetButtonState: Switch doesn't handle Type: ") << Type);
break;
}
}
}
//
// Set resId of shown bitmap if Sharing is false or
// set glyphIndex of shown bitmap if Sharing is true
//
void
TButtonGadgetEx::SetResId(TResId glyphResIdOrIndex)
{
// The user can't set no bitmap
//
if (glyphResIdOrIndex == 0)
return;
delete CelArray;
if (ResId.IsString())
delete[] ResId.GetString();
// If we are sharing the glyph held by our window, then we won't need to load
// the resource
//
if (SharingGlyph) {
GlyphIndex = glyphResIdOrIndex.GetInt();
}
else {
ResId = glyphResIdOrIndex.IsString() ?
TResId(strnewdup(glyphResIdOrIndex)) : glyphResIdOrIndex;
}
CelArray = 0;
if (Window) {
BuildCelArray();
Invalidate(); // Call my not virtual Invalidate() function
Update();
}
}
//
// Reset the members to default values.
//
void TButtonGadgetEx::Reset()
{
TButtonGadgetDesc* bgd = TYPESAFE_DOWNCAST(
GadgetDescriptors->Find(GetId()), TButtonGadgetDesc);
if (bgd) {
SetResId(bgd->BmpResId);
}
}
//
// Returns true, if the members have the default values
//
bool TButtonGadgetEx::HasDefaultValues()
{
TButtonGadgetDesc* bgd = TYPESAFE_DOWNCAST(
GadgetDescriptors->Find(GetId()), TButtonGadgetDesc);
if (bgd && TResId(bgd->BmpResId) == ResId)
return true;
return false;
}
//
// Initiate a command enable for this button gadget
//
void
TButtonGadgetEx::CommandEnable()
{
PRECONDITION(Window);
TDockableControlBarEx* dcb = TYPESAFE_DOWNCAST(Window, TDockableControlBarEx);
if (dcb) {
THarborEx* harbor = TYPESAFE_DOWNCAST(dcb->GetHarbor(), THarborEx);
if (harbor && harbor->IsCustomizeMode()) {
SetEnabled(true);
return;
}
}
// Must send, not post here, since a ptr to a temp is passed
//
// This might be called during idle processing before the
// HWND has created. Therefore, confirm handle exists.
//
if (Window->GetHandle()) {
TButtonGadgetEnablerEx tempEnabler(*Window, this);
Window->HandleMessage(
WM_COMMAND_ENABLE,
0,
// Importand: !!! use my TButtonGadgetEnablerEx !!!
TParam2(&tempEnabler)
);
}
}
//
// Overwrite to erase the background for flat style
// It is not a virtual function, but they are called from the most important
// functions in TButtonGadgetEx
//
void
TButtonGadgetEx::Invalidate()
{
TDockableControlBarEx* dcb = TYPESAFE_DOWNCAST(Window, TDockableControlBarEx);
if (dcb) {
if(dcb->GetFlatStyle())
TGadget::Invalidate(true); // is flat style -> repaint gadget TWindow
else
TGadget::Invalidate(false);
}
}
//
// Make sure our style matches our state, then paint our gadget borders
//
void TButtonGadgetEx::CheckStyleAndState()
{
TDockableControlBarEx* dcb = TYPESAFE_DOWNCAST(Window, TDockableControlBarEx);
if (dcb) {
BorderStyle = None;
if (dcb->GetFlatStyle()) {
if (GetEnabled()) {
if (MouseInGadget)
BorderStyle = (Pressed || State == Down )? Recessed : Raised;
else if(State == Down)
BorderStyle = Recessed;
}
}
else
BorderStyle = (Pressed || State == Down) ? ButtonDn : ButtonUp;
}
}
//
// Perform all of the painting for this button gadget
//
void TButtonGadgetEx::Paint(TDC& dc)
{
TDockableControlBarEx* dcb = TYPESAFE_DOWNCAST(Window, TDockableControlBarEx);
if (dcb == 0) {
TButtonGadget::Paint(dc);
return;
}
else {
// Make sure our style matches our state, then paint our gadget borders
// This do the same as OWL60 paint source fragment
//
CheckStyleAndState();
PaintBorder(dc);
// Determine which CelArray to paint from: ours or our Window's
//
TCelArray& celArray = CelArray ? *CelArray : Window->GetCelArray();
// Get the inner rect to use as the button face
//
TRect faceRect;
GetInnerRect(faceRect);
// Calc the source rect from the celarray. The dest point of the glyph is
// relative to the face rect.
//
TRect srcRect(celArray.CelRect(GlyphIndex));
TPoint dstPt(BitmapOrigin - faceRect.TopLeft());
// Create a UI Face object for this button & let it paint the button face
//
TUIFace face(faceRect, celArray);
if (!GetEnabled()) {
face.Paint(dc, srcRect, dstPt, TUIFace::Disabled, false);
return;
}
else if (State == Indeterminate) { ///Y.B ??????????
face.Paint(dc, srcRect, dstPt, TUIFace::Indeterm, Pressed);
return;
}
else if (State == Down) {
if(dcb->GetFlatStyle()) {
face.Paint(dc, srcRect, MouseInGadget ? dstPt+TPoint(1,1) : dstPt,
MouseInGadget ? TUIFace::Normal : TUIFace::Down, Pressed);
return;
}
else if (!Pressed) {
face.Paint(dc, srcRect, dstPt, TUIFace::Down, false);
return;
}
}
face.Paint(dc, srcRect, dstPt, TUIFace::Normal, Pressed);
}
}
//
// Paint the border of the gadget based on the BorderStyle member
//
void
TButtonGadgetEx::PaintBorder(TDC& dc)
{
TButtonGadget::PaintBorder(dc);
}
//
// Mouse is entering this gadget. Called by gadget window if no other gadget
// has capture
//
void
TButtonGadgetEx::MouseEnter(uint modKeys, const TPoint& point)
{
//
// for flat ala IE 3.0 toolbar
//
TButtonGadget::MouseEnter(modKeys, point);
TDockableControlBarEx* dcb = TYPESAFE_DOWNCAST(Window, TDockableControlBarEx);
if (dcb) {
MouseInGadget = false;
THarborEx* harbor = TYPESAFE_DOWNCAST(dcb->GetHarbor(), THarborEx);
if (harbor && harbor->IsCustomizeMode() == false) {
MouseInGadget = true;
Invalidate(); // Call my not virtual Invalidate() function
}
}
}
//
// Overwrite to call my BetterChecckExclusively() and my SyncronizeButtons()
//
void
TButtonGadgetEx::Activate(const TPoint& pt)
{
switch (Type)
{
case Exclusive:
if (State != Down)
BetterCheckExclusively();
break;
case NonExclusive:
State = State == Up ? Down : Up;
SyncronizeButtons(GetId(), State);
break;
case SemiExclusive:
BetterCheckExclusively();
break;
default: // TODO: Command and RepeatCmd is not handled; handle or clarify.
WARN(true, _T("TButtonGadgetEx::Activate: Switch doesn't handle Type: ") << Type);
break;
}
// Unpress the button
//
CancelPressed(pt);
// Send the associated command for all enabled buttons except for exclusive
// buttons that are being poped up
//
if (!((Type == Exclusive || Type == SemiExclusive) && State != Down) &&
GetEnabled())
Window->PostMessage(WM_COMMAND, GetId());
}
//
// Syncronize the newState of a Exlusive, SemiExclusive and NonExclusive
// button gadget with id
//
void
TButtonGadgetEx::SyncronizeButtons(int id, TState newState)
{
if (Window) {
// Syncronize the descriptors for next "Customize"
//
TButtonGadgetDesc* desc = TYPESAFE_DOWNCAST(
GadgetDescriptors->Find(id), TButtonGadgetDesc);
if (desc && desc->ButtonGadgetType != Command)
desc->ButtonGadgetState = newState;
// Syncronize the real gadgets in all dockable toolbars
//
TDockableGadgetWindow* dockWin = TYPESAFE_DOWNCAST(Window,
TDockableGadgetWindow);
THarborEx* harbor = TYPESAFE_DOWNCAST(dockWin->GetHarbor(), THarborEx);
if (harbor) {
for (uint i=0; i<harbor->DCBData.GetItemsInContainer(); i++) {
TDockableControlBarEx* dcb = harbor->DCBData[i]->DCB;
if (dcb) {
for (TGadget* g=dcb->FirstGadget(); g; g=dcb->NextGadget(*g)) {
TButtonGadgetEx* bg = TYPESAFE_DOWNCAST(g, TButtonGadgetEx);
if (bg && bg->GetId() == id) {
bg->State = newState;
bg->Invalidate(); // Call my not virtual Invalidate() function
bg->Update();
}
}
}
}
}
}
}
//
// Similar to private OWL function CheckExclusively().
// Fix OWL bug with SemiExclusive button gadgets
// Syncronize the state of all buttons
//
void
TButtonGadgetEx::BetterCheckExclusively()
{
PRECONDITION(Window);
if (Window && (Type == Exclusive || Type == SemiExclusive)) {
if (Type == SemiExclusive)
State = (State == Up) ? Down : Up;
TButtonGadgetGroup* group = GadgetDescriptors->FindGroup(GetId());
if (group) {
for (uint i=0; i<group->Array.GetItemsInContainer(); i++) {
int id = group->Array[i];
if (id == GetId()) {
// change myself
//
if (Type == Exclusive)
SyncronizeButtons(id, Down);
else
SyncronizeButtons(id, State);
}
else {
// change the buttons in the group
//
if (!(Type == SemiExclusive && State == Up))
SyncronizeButtons(id, Up);
}
}
}
}
}
// ******************** TButtonTextGadgetEx ***********************************
TButtonTextGadgetEx::TButtonTextGadgetEx(
LPCTSTR commandText,
TDisplayType disptype,
TResId glyphResIdOrIndex, // see TButtonGadgetEx
int id, // see TButtonGadgetEx
TType type, // see TButtonGadgetEx
bool enabled, // see TButtonGadgetEx
TState state, // see TButtonGadgetEx
bool sharedGlyph): // see TButtonGadgetEx
TButtonGadgetEx(glyphResIdOrIndex, id, type, enabled, state, sharedGlyph)
{
if (commandText)
CommandText = commandText;
else
CommandText = _T("");
DispType = disptype;
// Be sure that the DisplayType is text if there is no bitmap
//
if (ResId == 0)
DispType = Text;
}
TButtonTextGadgetEx::~TButtonTextGadgetEx()
{
}
void TButtonTextGadgetEx::SetDisplayType(TDisplayType dispType)
{
if (dispType != DispType) {
// Be sure that the DisplayType is text if there is no bitmap
//
if (dispType != Text && ResId == 0)
return;
DispType = dispType;
if (Window) {
Window->Invalidate();
Window->GadgetChangedSize(*this);
}
}
}
void TButtonTextGadgetEx::SetCommandText(const owl::tstring& commandText)
{
CommandText = commandText;
if (Window)
Window->GadgetChangedSize(*this);
}
void TButtonTextGadgetEx::GetDesiredSize(TSize& size)
{
TButtonGadgetEx::GetDesiredSize(size);
if (DispType != Bitmap) {
if (Window && Window->GetHandle()) {
TRect textRect; // default constructor now set all members to 0
TClientDC dc(Window->GetHandle());
const TFont* font = &(Window->GetFont());
if (font)
dc.SelectObject(*font);
dc.DrawText(CommandText.c_str(), -1, textRect, DT_CALCRECT | DT_SINGLELINE);
if (font)
dc.RestoreFont();
TBorders borders = GetBorders();
textRect.right+=4;
textRect.bottom+=2;
if (DispType == Text)
size = textRect.Size()+TSize(borders.Left+borders.Right,
borders.Top+borders.Bottom);
else {
if (textRect.bottom > size.cy)
size.cy = textRect.bottom;
size.cx += textRect.Width();
}
}
}
}
void TButtonTextGadgetEx::SetBounds(const TRect& rect)
{
TButtonGadgetEx::SetBounds(rect);
BitmapOrigin.x = Borders.Left; // set the bitmap origin always to left
}
//
// Reset the members to default values.
//
void TButtonTextGadgetEx::Reset()
{
TButtonGadgetEx::Reset();
TButtonTextGadgetDesc* bgd = TYPESAFE_DOWNCAST(
GadgetDescriptors->Find(GetId()), TButtonTextGadgetDesc);
if (bgd) {
SetCommandText(bgd->Text);
SetDisplayType(bgd->DispType);
}
}
//
// Returns true, if the members have the default values
//
bool TButtonTextGadgetEx::HasDefaultValues()
{
if (TButtonGadgetEx::HasDefaultValues()) {
TButtonTextGadgetDesc* bgd = TYPESAFE_DOWNCAST(
GadgetDescriptors->Find(GetId()), TButtonTextGadgetDesc);
if (bgd && bgd->Text == CommandText && bgd->DispType == DispType)
return true;
}
return false;
}
void TButtonTextGadgetEx::Created()
{
TButtonGadgetEx::Created();
if (_tcslen(CommandText.c_str()) == 0)
TryToLoadCommandText();
}
//
// Perform all of the painting for this text button gadget
//
void TButtonTextGadgetEx::Paint(TDC& dc)
{
if (DispType == Bitmap) {
TButtonGadgetEx::Paint(dc);
}
else if (DispType == Text) {
TButtonGadgetEx::CheckStyleAndState();
TButtonGadgetEx::PaintBorder(dc);
PaintText(dc);
}
else {
TButtonGadgetEx::Paint(dc);
PaintText(dc);
}
}
//
// Perform all of the painting for this button gadget
//
void TButtonTextGadgetEx::PaintText(TDC& dc)
{
if (Window && DispType != Bitmap) {
const TFont* font = &(Window->GetFont());
if (font)
dc.SelectObject(*font);
TRect innerRect;
GetInnerRect(innerRect);
innerRect.left+=1;
if (DispType == BitmapText) {
TCelArray& celArray = CelArray ? *CelArray : Window->GetCelArray();
innerRect.left+=celArray.CelSize().cx;
}
if (DispType == Text) {
if (State == Down)
FillMaskRect(dc, innerRect);
else
dc.FillRect(innerRect, TBrush(TColor::Sys3dFace));
}
uint offset = (Pressed || State == Down) ? 1 : 0;
innerRect.Offset(offset, offset);
TColor oldtextcol;
int oldbkmode = dc.SetBkMode(TRANSPARENT);
if (GetEnabled() == false) {
innerRect.Offset(1,1);
oldtextcol = dc.SetTextColor(TColor::Sys3dHilight);
dc.DrawText(CommandText.c_str(), -1, innerRect, DT_SINGLELINE);
innerRect.Offset(-1,-1);
dc.SetTextColor(oldtextcol);
}
oldtextcol = dc.SetTextColor(GetEnabled() ?
TColor::SysBtnText : TColor::SysGrayText);
dc.DrawText(CommandText.c_str(), -1, innerRect, DT_SINGLELINE);
dc.SetTextColor(oldtextcol);
dc.SetBkMode(oldbkmode);
if (font)
dc.RestoreFont();
}
}
void TButtonTextGadgetEx::TryToLoadCommandText()
{
TCHAR str[255];
if (Window && Window->GetModule()) {
if (Window->GetModule()->LoadString(GetId(), str, sizeof(str)) > 0) {
TCHAR* ptr = _tcschr(str, _T('\n'));
if (ptr && ptr+1) {
TCHAR* ptr2 = _tcschr(str, _T('\t'));
if (ptr2 == 0)
ptr2 = _tcschr(str, _T('\a'));
if (ptr2)
*ptr2 = 0;
CommandText = owl::tstring(ptr+1);
// If we found the command text, then udpade the global descripton
//
if (_tcslen(CommandText.c_str()) > 0) {
TGadgetDesc* desc = GadgetDescriptors->Find(GetId());
if (desc) {
TButtonTextGadgetDesc* btgd = TYPESAFE_DOWNCAST(desc,
TButtonTextGadgetDesc);
if (btgd) {
btgd->Text = CommandText;
}
}
}
}
}
}
}
TDib* TButtonTextGadgetEx::GetGlyphDib()
{
PRECONDITION(Window);
if (ResId) {
TDib* glyph;
try {
glyph = new TDib(*Window->GetModule(), ResId);
}
catch (TXGdi& ) {
// Be sure that the DisplayType is text if there is no bitmap
//
ResId = 0;
DispType = Text;
return 0;
}
glyph->MapUIColors( TDib::MapFace | TDib::MapText | TDib::MapShadow |
TDib::MapHighlight );
return glyph;
}
return 0;
}
// ******************** TPopupButtonGadgetEx **********************************
const int ArrowWidth = 8;
TPopupButtonGadgetEx::TPopupButtonGadgetEx(
TPopupType popupType,
LPCTSTR commandText, // see TButtonTextGadget
TDisplayType disptype, // see TButtonTextGadget
TResId glyphResIdOrIndex, // see TButtonGadgetEx
int id, // see TButtonGadgetEx
TType type, // see TButtonGadgetEx
bool enabled, // see TButtonGadgetEx
TState state, // see TButtonGadgetEx
bool sharedGlyph): // see TButtonGadgetEx
TButtonTextGadgetEx(commandText, disptype, glyphResIdOrIndex, id, type, enabled,
state, sharedGlyph)
{
PopupType = popupType;
DownArrowPressed = false;
ButtonHasCapture = false;
}
void TPopupButtonGadgetEx::GetDesiredSize(TSize& size)
{
TButtonTextGadgetEx::GetDesiredSize(size);
if (PopupType != Normal)
size.cx += ArrowWidth;
}
// Start the PopupAction if the user click
// 1) into the button if PopupType != DownArrowAction
// 2) into the arrow if PopupType == DownArrowAction
// This function do nothing, overwrite them with functionallity
//
void TPopupButtonGadgetEx::PopupActionStart()
{
}
// This function must be called to show the button
// include the down arrow in normal state
//
void TPopupButtonGadgetEx::PopupActionEnd()
{
if (DownArrowPressed) {
DownArrowPressed = false;
Invalidate();
Update();
}
else {
TPoint p;
CancelPressed(p);
}
}
// Invoked by mouse-down & mouse enter events. sets member data "Pressed"
// to true and highlights the button
//
void TPopupButtonGadgetEx::BeginPressed(const TPoint& p)
{
PRECONDITION (Window);
if (PopupType != DownArrowAction) {
TButtonTextGadgetEx::BeginPressed(p);
Window->GadgetReleaseCapture(*this);
PopupActionStart();
}
else {
TRect DownArrowRect = Bounds;
DownArrowRect.Offset(-DownArrowRect.left, -DownArrowRect.top);
DownArrowRect.left = DownArrowRect.right - ArrowWidth;
if (ButtonHasCapture == false && DownArrowPressed == false &&
DownArrowRect.Contains(p)) {
Pressed = false;
DownArrowPressed = true;
Invalidate();
Update();
Window->GadgetReleaseCapture(*this);
PopupActionStart();
}
else {
TButtonTextGadgetEx::BeginPressed(p);
}
}
}
// Invoked by mouse exit events. sets member data "Pressed" to false and
// paints the button in its current state
//
void TPopupButtonGadgetEx::CancelPressed(const TPoint& p, bool)
{
if (Pressed)
TButtonTextGadgetEx::CancelPressed(p);
}
// Captures the mouse if "TrackMouse" is set.
//
void TPopupButtonGadgetEx::LButtonDown(uint modKeys, const TPoint& point)
{
TButtonTextGadgetEx::LButtonDown(modKeys, point);
if (Pressed)
ButtonHasCapture = true;
}
// Releases the mouse capture if "TrackMouse" is set.
//
void TPopupButtonGadgetEx::LButtonUp(uint modKeys, const TPoint& point)
{
TButtonTextGadgetEx::LButtonUp(modKeys, point);
ButtonHasCapture = false;
}
// 1. PaintButton
// 2. PaintSeparator
// 3. PaintDownArrow
//
void TPopupButtonGadgetEx::Paint(TDC& dc)
{
PaintButton(dc);
if (PopupType == DownArrowAction)
PaintSeparator(dc);
if (PopupType != Normal)
PaintDownArrow(dc);
}
// Paint the left button area
//
void TPopupButtonGadgetEx::PaintButton(TDC& dc)
{
PRECONDITION (Window);
TDockableControlBarEx* dcb = TYPESAFE_DOWNCAST(Window, TDockableControlBarEx);
if (dcb) {
if (Pressed && DownArrowPressed == false) {
if (PopupType == DownArrowAction)
Bounds.right -= (ArrowWidth+ (dcb->GetFlatStyle() ? 0 : 1));
TButtonTextGadgetEx::Paint(dc);
if (PopupType == DownArrowAction)
Bounds.right += (ArrowWidth+ (dcb->GetFlatStyle() ? 0 : 1));
}
else
TButtonTextGadgetEx::Paint(dc);
}
}
// Paint the separator between button and down arrow
//
void TPopupButtonGadgetEx::PaintSeparator(TDC& dc)
{
PRECONDITION (Window);
TDockableControlBarEx* dcb = TYPESAFE_DOWNCAST(Window, TDockableControlBarEx);
if (dcb) {
TRect innerRect;
GetInnerRect(innerRect);
TPoint dstPt(innerRect.right - (dcb->GetFlatStyle() ? 5 : 6),
innerRect.top + (innerRect.Height()-4)/2);
if (!(Pressed || DownArrowPressed)) {
if (GetEnabled()) {
if (dcb->GetFlatStyle()) {
if (MouseInGadget) {
TPen pen(TColor::Sys3dShadow);
dc.SelectObject(pen);
dc.MoveTo(dstPt.x-2, innerRect.top-2);
dc.LineTo(dstPt.x-2, innerRect.bottom+1);
dc.RestorePen();
TPen pen2(TColor::Sys3dHilight);
dc.SelectObject(pen2);
dc.MoveTo(dstPt.x-1, innerRect.top-1);
dc.LineTo(dstPt.x-1, innerRect.bottom+1);
dc.RestorePen();
}
}
else {
TPen pen(TColor::Sys3dShadow);
dc.SelectObject(pen);
dc.MoveTo(dstPt.x-2, innerRect.top-2);
dc.LineTo(dstPt.x-2, innerRect.bottom+1);
dc.RestorePen();
}
}
}
}
}
// Paint the down arrow
//
void TPopupButtonGadgetEx::PaintDownArrow(TDC& dc)
{
PRECONDITION (Window);
TDockableControlBarEx* dcb = TYPESAFE_DOWNCAST(Window, TDockableControlBarEx);
if (dcb) {
// Paint pressed border around down arrow
//
if (Pressed == false && DownArrowPressed) {
TRect boundsRect = TRect(0,0,Bounds.Width(), Bounds.Height());
boundsRect.left = boundsRect.right - (ArrowWidth+2);
if (dcb->GetFlatStyle()){
TUIBorder::DrawEdge(dc, boundsRect, TUIBorder::SunkenOuter,
TUIBorder::Rect);
}
else {
TUIBorder(boundsRect, (TUIBorder::TStyle)ButtonDn).Paint(dc);
}
}
TRect innerRect;
GetInnerRect(innerRect);
TPoint dstPt(innerRect.right - (dcb->GetFlatStyle() ? 5 : 6),
innerRect.top + (innerRect.Height()-4)/2);
// Paint down arrow
//
TColor col = TColor::SysBtnText;
if (!GetEnabled())
col = TColor::Sys3dShadow;
TPen pen3(col);
dc.SelectObject(pen3);
dc.MoveTo(dstPt.x, dstPt.y);
dc.LineTo(dstPt.x+5, dstPt.y);
dc.MoveTo(dstPt.x+1, dstPt.y+1);
dc.LineTo(dstPt.x+4, dstPt.y+1);
dc.SetPixel(dstPt.x+2, dstPt.y+2, col);
if (!GetEnabled()) {
dc.SetPixel(dstPt.x+2, dstPt.y+3, TColor::Sys3dHilight);
dc.SetPixel(dstPt.x+3, dstPt.y+2, TColor::Sys3dHilight);
dc.SetPixel(dstPt.x+4, dstPt.y+1, TColor::Sys3dHilight);
}
dc.RestorePen();
}
}
// ******************** TMenuButtonGadgetEx ***********************************
UINT TMenuButtonGadgetEx::Flags =
TPM_LEFTALIGN | TPM_LEFTBUTTON | TPM_RIGHTBUTTON;
TMenuButtonGadgetEx::TMenuButtonGadgetEx(
TPopupType popupType, // see TPopupButtonGadget
HMENU hmenu, // adress that points to a menu
TWindow* cmdTarget, // commando target window
LPCTSTR commandText, // see TButtonTextGadget
TDisplayType disptype, // see TButtonTextGadget
TResId glyphResIdOrIndex, // see TButtonGadgetEx
int id, // see TButtonGadgetEx
TType type, // see TButtonGadgetEx
bool enabled, // see TButtonGadgetEx
TState state, // see TButtonGadgetEx
bool sharedGlyph): // see TButtonGadgetEx
TPopupButtonGadgetEx(popupType, commandText, disptype, glyphResIdOrIndex, id,
type, enabled, state, sharedGlyph),
CmdTarget(cmdTarget)
{
hMenu = hmenu;
}
void TMenuButtonGadgetEx::PopupActionStart()
{
if (Window && Window->GetHandle() && CmdTarget && CmdTarget->GetHandle() &&
hMenu && IsMenu(hMenu)) {
TPoint tlp = Bounds.TopLeft();
TPoint brp = Bounds.BottomRight();
TRect winRect = Window->GetWindowRect();
tlp.Offset(winRect.left, winRect.top);
brp.Offset(winRect.left, winRect.top);
TPMPARAMS tpmParams;
tpmParams.cbSize = sizeof(TPMPARAMS);
tpmParams.rcExclude.top = tlp.y;
tpmParams.rcExclude.left = 0;
tpmParams.rcExclude.bottom = brp.y;
tpmParams.rcExclude.right = 32000;
::TrackPopupMenuEx(hMenu, Flags,
tlp.x, tlp.y, CmdTarget->GetHandle(), &tpmParams);
PopupActionEnd();
}
}
// ******************** TRecentFileButtonGadgetEx *****************************
TRecentFilesGadgetEx::TRecentFilesGadgetEx(
LPCTSTR commandText, // see TButtonTextGadget
TDisplayType disptype, // see TButtonTextGadget
TResId glyphResIdOrIndex, // see TButtonGadgetEx
int id, // see TButtonGadgetEx
TType type, // see TButtonGadgetEx
bool enabled, // see TButtonGadgetEx
TState state, // see TButtonGadgetEx
bool sharedGlyph): // see TButtonGadgetEx
TMenuButtonGadgetEx(DownArrowAction, 0, 0, commandText, disptype,
glyphResIdOrIndex, id, type, enabled, state, sharedGlyph)
{
}
void TRecentFilesGadgetEx::PopupActionStart()
{
if (Window && Window->GetHandle()) {
TApplication* app = Window->GetApplication();
if (app) {
CmdTarget = app->GetMainWindow();
TRecentFiles* rf = TYPESAFE_DOWNCAST(app, TRecentFiles);
if (rf) {
hMenu = ::CreatePopupMenu();
int count=0;
int id = CM_MRU_FIRST;
TCHAR menustr[_MAX_PATH+3];
TCHAR text[_MAX_PATH];
while (rf->GetMenuText(id, text, _MAX_PATH)) {
wsprintf(menustr, _T("&%d %s"), (count == 9) ? 0 : count+1, text);
::InsertMenu(hMenu, count, MF_BYPOSITION | MF_STRING, id, menustr);
id++;
count++;
}
if (count > 0)
TMenuButtonGadgetEx::PopupActionStart();
else
PopupActionEnd();
::DestroyMenu(hMenu);
}
}
}
}
// ******************** TColorButtonGadgetEx **********************************
TRect TColorButtonGadgetEx::DefaultFillRect = TRect(3,15,19,19);
TColorButtonGadgetEx::TColorButtonGadgetEx(
TPopupType popupType, // see TPopupButtonGadget
const TColorPickerData& data, // see TColorPicker
TColor startColorSel, // start color that is selected
TRect* fillRect, // rect that will be filled with color
TWindow* parentWindow, // parent window of picker
LPCTSTR commandText, // see TButtonTextGadget
TDisplayType disptype, // see TButtonTextGadget
TResId glyphResIdOrIndex, // see TButtonGadgetEx
int id, // see TButtonGadgetEx
TType type, // see TButtonGadgetEx
bool enabled, // see TButtonGadgetEx
TState state, // see TButtonGadgetEx
bool sharedGlyph): // see TButtonGadgetEx
TPopupButtonGadgetEx(popupType, commandText, disptype, glyphResIdOrIndex, id,
type, enabled, state, sharedGlyph),
ParentWindow(parentWindow),
Data (data)
{
CheckingMode = false;
ColorSel = startColorSel;
FillRect = fillRect;
ColorPickerWindow = new TColorPicker(ParentWindow, Data, ColorSel, id);
}
void TColorButtonGadgetEx::Created()
{
TPopupButtonGadgetEx::Created();
ColorPickerWindow->Create();
}
void TColorButtonGadgetEx::PopupActionStart()
{
if (ColorPickerWindow) {
TRect rect = GetBounds();
TPoint p2(rect.TopLeft());
Window->ClientToScreen(p2);
rect.right = p2.x + rect.Width();
rect.bottom = p2.y + rect.Height();
rect.left = p2.x;
rect.top = p2.y;
p2.y = rect.bottom;
// We tell the picker where the picker has to be displayed.
ColorPickerWindow->ShowPickerWindow(p2, rect);
CheckingMode = true;
}
}
// We check some events for this flat button gadget.
//
bool TColorButtonGadgetEx::IdleAction(long idleCount)
{
if (idleCount == 0 && ColorPickerWindow && CheckingMode) {
// Check if the current chosen color has changed. If it has changed,
// we update this flat button gadget and we tell the picker to notify
// the parent window.
//
TColor color = ColorPickerWindow->GetCurrentChosenColor();
if (color != ColorSel) {
ColorSel = color;
ColorPickerWindow->NotifyAtParent();
CheckingMode = false;
PopupActionEnd();
}
if (ColorPickerWindow->GetHandle() &&
ColorPickerWindow->IsWindowVisible() == false) {
CheckingMode = false;
PopupActionEnd();
}
}
return TPopupButtonGadgetEx::IdleAction(idleCount);
}
void TColorButtonGadgetEx::PaintButton(TDC& dc)
{
TPopupButtonGadgetEx::PaintButton(dc);
if (FillRect && GetEnabled()) {
// Copy only the RGB values for the color that will be draw
//
TColor col(ColorSel.Red(), ColorSel.Green(), ColorSel.Blue());
TRect rect = *FillRect;
if (col.GetValue() == TColor::Sys3dFace.GetValue())
rect.Inflate(-1,-1);
if (Pressed)
dc.FillRect(rect.OffsetBy(1,1), TBrush(col));
else
dc.FillRect(rect, TBrush(col));
}
}
void TColorButtonGadgetEx::Activate(const TPoint& pt)
{
TButtonGadget::Activate(pt);
// Send the registed color messege
//
if (!((Type == Exclusive || Type == SemiExclusive) && State != Down) &&
GetEnabled() && ColorPickerWindow && ColorPickerWindow->GetHandle())
ColorPickerWindow->NotifyAtParent();
}
// ******************** TControlGadgetEx **************************************
//
//
//
TControlGadgetEx::TControlGadgetEx(TWindow& control, TBorderStyle border):
// TGadget(control.Attr.Id, border)
TControlGadget(control, border)
{
IsCursorInControl = false;
// Control = &control;
// Control->ModifyStyle(0, WS_CLIPSIBLINGS); // Make sure relayout paints OK
// TRACEX(GadgetEx, 0, "TControlGadgetEx constructed @" << (void*)this);
}
TControlGadgetEx::~TControlGadgetEx()
{
// Don't delete the control here, because if the control is inside a window,
// the OWL framework delete the control and if not the control is deleted
// by TControlGadgetDesc
//
SetControl(0);
// Control->Destroy(0);
// delete Control;
// TRACEX(GadgetEx, 0, "TControlGadgetEx destructed @" << (void*)this);
}
//
// Virtual called after the window holding a gadget has been created
//
void
TControlGadgetEx::Created()
{
TControlGadget::Created();
// Try to load tooltip. This code is stolen from Jo Parrello's
// JPControlGadget class. Very special thanks
//
if (Control->GetHandle()) {
owl::tstring text = GetHintText(Control, GetId());
if (text.length()) {
TTooltip* tooltip = Window->GetTooltip();
if (tooltip && tooltip->GetHandle())
tooltip->UpdateTipText(TTooltip::TCtrlToolId{Window->GetHandle(), Control->GetHandle()}, text);
}
}
}
//
// Override the Inserted() virtual to take the oportunity to make sure that the
// control window has been created and shown
//
void
TControlGadgetEx::Inserted()
{
// TControlGadget::Inserted();
TRACEX(GadgetEx, 1, "TControlGadgetEx::Inserted @" << (void*)this);
Control->SetParent(Window);
if (Window->GetHandle()) {
if (Control->GetHandle() == 0)
Control->Create();
// Show the control
//
if (Control->IsWindowVisible() == false)
Control->ShowWindow(SW_SHOWNA);
}
// Say the TControlGadgetDesc, that the control is inserted in a window
//
TGadgetDesc* desc = GadgetDescriptors->Find(Control->GetId());
TControlGadgetDesc* cgdesc = TYPESAFE_DOWNCAST(desc, TControlGadgetDesc);
if (cgdesc) {
cgdesc->CountAdd();
}
}
//
// Override the Remove() virtual to take the oportunity to unparent the
// control window from the owning Window
//
void
TControlGadgetEx::Removed()
{
// TControlGadget::Removed();
TRACEX(GadgetEx, 1, "TControlGadgetEx::Removed @" << (void*)this);
// Hide the control
//
if (Control->IsWindowVisible() == true)
Control->ShowWindow(SW_HIDE);
Control->SetParent(0);
// Should we destroy the control at this point??
// Since it's no longer in the parent's child-list, there's a potential
// leak. However, the semantics of this function is 'Removed' - therefore
// one could be removing the control to be reinserted in another
// gadgetwindow.
// Unregister ourself with the tooltip window (if there's one)
//
if (Window && Window->GetHandle()) {
TTooltip* tooltip = Window->GetTooltip();
if (tooltip) {
CHECK(tooltip->GetHandle());
tooltip->DelTool(TTooltip::TCtrlToolId{Window->GetHandle(), Control->GetHandle()});
}
}
// Say the TControlGadgetDesc, that the control is removed from a window
//
TGadgetDesc* desc = GadgetDescriptors->Find(Control->GetId());
TControlGadgetDesc* cgdesc = TYPESAFE_DOWNCAST(desc, TControlGadgetDesc);
if (cgdesc) {
cgdesc->CountSub();
}
}
void
TControlGadgetEx::Paint(TDC& /*dc*/)
{
if (Control->GetHandle()) {
Control->Invalidate();
Control->UpdateWindow();
}
}
//
// Display tooltip and a message on status bar when you "enter" a TControlGadget
// This code is stolen from Jo Parrello's JPControlGadget class.
// Very special thanks
//
bool
TControlGadgetEx::IdleAction(long idleCount)
{
if (idleCount == 0) {
if (Window) {
TPoint crsPoint;
Window->GetCursorPos(crsPoint);
HWND hwnd = Window->WindowFromPoint(crsPoint);
if (hwnd) {
if ((hwnd != Control->GetHandle()) &&
(::GetParent(hwnd) != Control->GetHandle())) {
if (Window->GetHintMode() == TGadgetWindow::EnterHints) {
if (IsCursorInControl)
Window->SetHintCommand(-1);
IsCursorInControl = false;
}
}
else {
if (Window->GetHintMode() == TGadgetWindow::EnterHints) {
if (!IsCursorInControl)
Window->SetHintCommand(Control->GetId());
IsCursorInControl = true;
}
}
}
}
}
return false;
}
} // OwlExt namespace
//=====================================================================================
↑ V694 The condition (ptr + 1) is only false if there is pointer overflow which is undefined behavior anyway.
↑ V522 There might be dereferencing of a potential null pointer 'dockWin'.
↑ V547 Expression 'font' is always true.
↑ V547 Expression 'font' is always true.
↑ V547 Expression 'font' is always true.
↑ V547 Expression 'font' is always true.
↑ V560 A part of conditional expression is always true: ptr + 1.
↑ V805 Decreased performance. It is inefficient to identify an empty string by using 'strlen(str) == 0' construct. A more efficient way is to check: str[0] == '\0'.
↑ V805 Decreased performance. It is inefficient to identify an empty string by using 'strlen(str) > 0' construct. A more efficient way is to check: str[0] != '\0'.
↑ V806 Decreased performance. The expression of strlen(MyStr.c_str()) kind can be rewritten as MyStr.length().
↑ V806 Decreased performance. The expression of strlen(MyStr.c_str()) kind can be rewritten as MyStr.length().
↑ V818 It is more efficient to use an initialization list 'ColorSel(startColorSel)' rather than an assignment operator.
↑ V815 Decreased performance. Consider replacing the expression 'CommandText = ""' with 'CommandText.clear()'.
↑ V821 Decreased performance. The 'borders' variable can be constructed in a lower level scope.