|
|
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//===========================================================================//
#include <assert.h>
#include <math.h> // for ceil()
#define PROTECTED_THINGS_DISABLE
#include "tier1/utlstring.h"
#include "vgui/Cursor.h"
#include "vgui/MouseCode.h"
#include "vgui/IBorder.h"
#include "vgui/IInput.h"
#include "vgui/ILocalize.h"
#include "vgui/IPanel.h"
#include "vgui/ISurface.h"
#include "vgui/IScheme.h"
#include "vgui/KeyCode.h"
#include "vgui_controls/AnimationController.h"
#include "vgui_controls/Controls.h"
#include "vgui_controls/Frame.h"
#include "vgui_controls/Button.h"
#include "vgui_controls/Menu.h"
#include "vgui_controls/MenuButton.h"
#include "vgui_controls/TextImage.h"
#include "KeyValues.h"
#include <stdio.h>
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
using namespace vgui;
static const int DEFAULT_SNAP_RANGE = 10; // number of pixels distance before the frame will snap to an edge
static const int CAPTION_TITLE_BORDER = 7; static const int CAPTION_TITLE_BORDER_SMALL = 0;
namespace { //-----------------------------------------------------------------------------
// Purpose: Invisible panel to handle dragging/resizing frames
//-----------------------------------------------------------------------------
class GripPanel : public Panel { public: GripPanel(Frame *dragFrame, const char *name, int xdir, int ydir) : Panel(dragFrame, name) { _frame = dragFrame; _dragging = false; _dragMultX = xdir; _dragMultY = ydir; SetPaintEnabled(false); SetPaintBackgroundEnabled(false); SetPaintBorderEnabled(false); m_iSnapRange = DEFAULT_SNAP_RANGE;
if (xdir == 1 && ydir == 1) { // bottom-right grip gets an image
SetPaintEnabled(true); SetPaintBackgroundEnabled(true); }
SetBlockDragChaining( true ); } // Purpose- handle window resizing
// Input- dx, dy, the offet of the mouse pointer from where we started dragging
virtual void moved(int dx, int dy) { if (!_frame->IsSizeable()) return; // Start off with x, y at the coords of where we started to drag
int newX = _dragOrgPos[0], newY =_dragOrgPos[1]; // Start off with width and tall equal from window when we started to drag
int newWide = _dragOrgSize[0], newTall = _dragOrgSize[1]; // get window's minimum size
int minWide, minTall; _frame->GetMinimumSize( minWide, minTall); // Handle width resizing
newWide += (dx * _dragMultX); // Handle the position of the corner x position
if (_dragMultX == -1) { // only move if we are not at the minimum
// if we are at min we have to force the proper offset (dx)
if (newWide < minWide) { dx=_dragOrgSize[0]-minWide; } newX += dx; // move window to its new position
} // Handle height resizing
newTall += (dy * _dragMultY); // Handle position of corner y position
if (_dragMultY == -1) { if (newTall < minTall) { dy=_dragOrgSize[1]-minTall; } newY += dy; } if ( _frame->GetClipToParent() ) { // If any coordinate is out of range, snap it back
if ( newX < 0 ) newX = 0; if ( newY < 0 ) newY = 0; int sx, sy; surface()->GetScreenSize( sx, sy );
int w, h; _frame->GetSize( w, h ); if ( newX + w > sx ) { newX = sx - w; } if ( newY + h > sy ) { newY = sy - h; } }
// set new position
_frame->SetPos(newX, newY); // set the new size
// if window is below min size it will automatically pop to min size
_frame->SetSize(newWide, newTall); _frame->InvalidateLayout(); _frame->Repaint(); } void OnCursorMoved(int x, int y) { if (!_dragging) return;
if (!input()->IsMouseDown(MOUSE_LEFT)) { // for some reason we're marked as dragging when the mouse is released
// trigger a release
OnMouseReleased(MOUSE_LEFT); return; }
input()->GetCursorPos(x, y); moved((x - _dragStart[0]), ( y - _dragStart[1])); _frame->Repaint(); } void OnMousePressed(MouseCode code) { if (code == MOUSE_LEFT) { _dragging=true; int x,y; input()->GetCursorPos(x,y); _dragStart[0]=x; _dragStart[1]=y; _frame->GetPos(_dragOrgPos[0],_dragOrgPos[1]); _frame->GetSize(_dragOrgSize[0],_dragOrgSize[1]); input()->SetMouseCapture(GetVPanel()); // if a child doesn't have focus, get it for ourselves
VPANEL focus = input()->GetFocus(); if (!focus || !ipanel()->HasParent(focus, _frame->GetVPanel())) { _frame->RequestFocus(); } _frame->Repaint(); } else { GetParent()->OnMousePressed(code); } }
void OnMouseDoublePressed(MouseCode code) { GetParent()->OnMouseDoublePressed(code); }
void Paint() { // draw the grab handle in the bottom right of the frame
surface()->DrawSetTextFont(_marlettFont); surface()->DrawSetTextPos(0, 0); // thin highlight lines
surface()->DrawSetTextColor(GetFgColor()); surface()->DrawUnicodeChar('p'); }
void PaintBackground() { // draw the grab handle in the bottom right of the frame
surface()->DrawSetTextFont(_marlettFont); surface()->DrawSetTextPos(0, 0); // thick shadow lines
surface()->DrawSetTextColor(GetBgColor()); surface()->DrawUnicodeChar('o'); } void OnMouseReleased(MouseCode code) { _dragging = false; input()->SetMouseCapture(NULL); }
void OnMouseCaptureLost() { Panel::OnMouseCaptureLost(); _dragging = false; }
void ApplySchemeSettings(IScheme *pScheme) { Panel::ApplySchemeSettings(pScheme); bool isSmall = ((Frame *)GetParent())->IsSmallCaption();
_marlettFont = pScheme->GetFont( isSmall ? "MarlettSmall" : "Marlett", IsProportional()); SetFgColor(GetSchemeColor("FrameGrip.Color1", pScheme)); SetBgColor(GetSchemeColor("FrameGrip.Color2", pScheme));
const char *snapRange = pScheme->GetResourceString("Frame.AutoSnapRange"); if (snapRange && *snapRange) { m_iSnapRange = atoi(snapRange); } } protected: Frame *_frame; int _dragMultX; int _dragMultY; bool _dragging; int _dragOrgPos[2]; int _dragOrgSize[2]; int _dragStart[2]; int m_iSnapRange; HFont _marlettFont; }; //-----------------------------------------------------------------------------
// Purpose: Handles caption grip input for moving dialogs around
//-----------------------------------------------------------------------------
class CaptionGripPanel : public GripPanel { public: CaptionGripPanel(Frame* frame, const char *name) : GripPanel(frame, name, 0, 0) { } void moved(int dx, int dy) { if (!_frame->IsMoveable()) return;
int newX = _dragOrgPos[0] + dx; int newY = _dragOrgPos[1] + dy;
if (m_iSnapRange) { // first check docking to desktop
int wx, wy, ww, wt; surface()->GetWorkspaceBounds(wx, wy, ww, wt); getInsideSnapPosition(wx, wy, ww, wt, newX, newY);
// now lets check all windows and see if we snap to those
// root panel
VPANEL root = surface()->GetEmbeddedPanel(); // cycle through panels
// look for panels that are visible and are popups that we can dock to
for (int i = 0; i < ipanel()->GetChildCount(root); ++i) { VPANEL child = ipanel()->GetChild(root, i); tryToDock (child, newX, newY); } }
if ( _frame->GetClipToParent() ) { // If any coordinate is out of range, snap it back
if ( newX < 0 ) newX = 0; if ( newY < 0 ) newY = 0; int sx, sy; surface()->GetScreenSize( sx, sy );
int w, h; _frame->GetSize( w, h ); if ( newX + w > sx ) { newX = sx - w; } if ( newY + h > sy ) { newY = sy - h; } }
_frame->SetPos(newX, newY);
} void tryToDock(VPANEL window, int &newX, int & newY) { // bail if child is this window
if ( window == _frame->GetVPanel()) return; int cx, cy, cw, ct; if ( (ipanel()->IsVisible(window)) && (ipanel()->IsPopup(window)) ) { // position
ipanel()->GetAbsPos(window, cx, cy); // dimensions
ipanel()->GetSize(window, cw, ct); bool snapped = getOutsideSnapPosition (cx, cy, cw, ct, newX, newY); if (snapped) { // if we snapped, we're done with this path
// dont try to snap to kids
return; } }
// check all children
for (int i = 0; i < ipanel()->GetChildCount(window); ++i) { VPANEL child = ipanel()->GetChild(window, i); tryToDock(child, newX, newY); }
}
// Purpose: To calculate the windows new x,y position if it snaps
// Will snap to the INSIDE of a window (eg desktop sides
// Input: boundX boundY, position of candidate window we are seeing if we snap to
// boundWide, boundTall, width and height of window we are seeing if we snap to
// Output: snapToX, snapToY new coords for window, unchanged if we dont snap
// Returns true if we snapped, false if we did not snap.
bool getInsideSnapPosition(int boundX, int boundY, int boundWide, int boundTall, int &snapToX, int &snapToY) { int wide, tall; _frame->GetSize(wide, tall); Assert (wide > 0); Assert (tall > 0); bool snapped=false; if (abs(snapToX - boundX) < m_iSnapRange) { snapToX = boundX; snapped=true; } else if (abs((snapToX + wide) - (boundX + boundWide)) < m_iSnapRange) { snapToX = boundX + boundWide - wide; snapped=true; }
if (abs(snapToY - boundY) < m_iSnapRange) { snapToY = boundY; snapped=true; } else if (abs((snapToY + tall) - (boundY + boundTall)) < m_iSnapRange) { snapToY = boundY + boundTall - tall; snapped=true; } return snapped; }
// Purpose: To calculate the windows new x,y position if it snaps
// Will snap to the OUTSIDE edges of a window (i.e. will stick peers together
// Input: left, top, position of candidate window we are seeing if we snap to
// boundWide, boundTall, width and height of window we are seeing if we snap to
// Output: snapToX, snapToY new coords for window, unchanged if we dont snap
// Returns true if we snapped, false if we did not snap.
bool getOutsideSnapPosition(int left, int top, int boundWide, int boundTall, int &snapToX, int &snapToY) { Assert (boundWide >= 0); Assert (boundTall >= 0); bool snapped=false; int right=left+boundWide; int bottom=top+boundTall;
int wide, tall; _frame->GetSize(wide, tall); Assert (wide > 0); Assert (tall > 0);
// we now see if we are going to be able to snap to a window side, and not
// just snap to the "open air"
// want to make it so that if any part of the window can dock to the candidate, it will
// is this window horizontally snappable to the candidate
bool horizSnappable=( // top of window is in range
((snapToY > top) && (snapToY < bottom)) // bottom of window is in range
|| ((snapToY+tall > top) && (snapToY+tall < bottom)) // window is just plain bigger than the window we wanna dock to
|| ((snapToY < top) && (snapToY+tall > bottom)) ); // is this window vertically snappable to the candidate
bool vertSnappable= ( // left of window is in range
((snapToX > left) && (snapToX < right)) // right of window is in range
|| ((snapToX+wide > left) && (snapToX+wide < right)) // window is just plain bigger than the window we wanna dock to
|| ((snapToX < left) && (snapToX+wide > right)) ); // if neither, might as well bail
if ( !(horizSnappable || vertSnappable) ) return false;
//if we're within the snap threshold then snap
if ( (snapToX <= (right+m_iSnapRange)) && (snapToX >= (right-m_iSnapRange)) ) { if (horizSnappable) { //disallow "open air" snaps
snapped=true; snapToX = right; } } else if ((snapToX + wide) >= (left-m_iSnapRange) && (snapToX + wide) <= (left+m_iSnapRange)) { if (horizSnappable) { snapped=true; snapToX = left-wide; } } if ( (snapToY <= (bottom+m_iSnapRange)) && (snapToY >= (bottom-m_iSnapRange)) ) { if (vertSnappable) { snapped=true; snapToY = bottom; } } else if ((snapToY + tall) <= (top+m_iSnapRange) && (snapToY + tall) >= (top-m_iSnapRange)) { if (vertSnappable) { snapped=true; snapToY = top-tall; } } return snapped; } }; }
namespace vgui { //-----------------------------------------------------------------------------
// Purpose: overrides normal button drawing to use different colors & borders
//-----------------------------------------------------------------------------
class FrameButton : public Button { private: IBorder *_brightBorder, *_depressedBorder, *_disabledBorder; Color _enabledFgColor, _enabledBgColor; Color _disabledFgColor, _disabledBgColor; bool _disabledLook; public: static int GetButtonSide( Frame *pFrame ) { if ( pFrame->IsSmallCaption() ) { return 12; }
return 18; } FrameButton(Panel *parent, const char *name, const char *text) : Button(parent, name, text) { SetSize( FrameButton::GetButtonSide( (Frame *)parent ), FrameButton::GetButtonSide( (Frame *)parent ) ); _brightBorder = NULL; _depressedBorder = NULL; _disabledBorder = NULL; _disabledLook = true; SetContentAlignment(Label::a_northwest); SetTextInset(2, 1); SetBlockDragChaining( true ); } virtual void ApplySchemeSettings(IScheme *pScheme) { Button::ApplySchemeSettings(pScheme); _enabledFgColor = GetSchemeColor("FrameTitleButton.FgColor", pScheme); _enabledBgColor = GetSchemeColor("FrameTitleButton.BgColor", pScheme);
_disabledFgColor = GetSchemeColor("FrameTitleButton.DisabledFgColor", pScheme); _disabledBgColor = GetSchemeColor("FrameTitleButton.DisabledBgColor", pScheme); _brightBorder = pScheme->GetBorder("TitleButtonBorder"); _depressedBorder = pScheme->GetBorder("TitleButtonDepressedBorder"); _disabledBorder = pScheme->GetBorder("TitleButtonDisabledBorder"); SetDisabledLook(_disabledLook); } virtual IBorder *GetBorder(bool depressed, bool armed, bool selected, bool keyfocus) { if (_disabledLook) { return _disabledBorder; } if (depressed) { return _depressedBorder; } return _brightBorder; } virtual void SetDisabledLook(bool state) { _disabledLook = state; if (!_disabledLook) { SetDefaultColor(_enabledFgColor, _enabledBgColor); SetArmedColor(_enabledFgColor, _enabledBgColor); SetDepressedColor(_enabledFgColor, _enabledBgColor); } else { // setup disabled colors
SetDefaultColor(_disabledFgColor, _disabledBgColor); SetArmedColor(_disabledFgColor, _disabledBgColor); SetDepressedColor(_disabledFgColor, _disabledBgColor); } }
virtual void PerformLayout() { Button::PerformLayout(); Repaint(); } // Don't request focus.
// This will keep items in the listpanel selected.
virtual void OnMousePressed(MouseCode code) { if (!IsEnabled()) return; if (!IsMouseClickEnabled(code)) return; if (IsUseCaptureMouseEnabled()) { { SetSelected(true); Repaint(); } // lock mouse input to going to this button
input()->SetMouseCapture(GetVPanel()); } } };
//-----------------------------------------------------------------------------
// Purpose: icon button
//-----------------------------------------------------------------------------
class FrameSystemButton : public MenuButton { DECLARE_CLASS_SIMPLE( FrameSystemButton, MenuButton );
private: IImage *_enabled, *_disabled; Color _enCol, _disCol; bool _respond; CUtlString m_EnabledImage; CUtlString m_DisabledImage; public: FrameSystemButton(Panel *parent, const char *panelName) : MenuButton(parent, panelName, "") { _disabled = _enabled = NULL; _respond = true; SetEnabled(false); // This menu will open if we use the left or right mouse button
SetMouseClickEnabled( MOUSE_RIGHT, true ); SetBlockDragChaining( true ); } void SetImages( const char *pEnabledImage, const char *pDisabledImage = NULL ) { m_EnabledImage = pEnabledImage; m_DisabledImage = pDisabledImage ? pDisabledImage : pEnabledImage; }
void GetImageSize( int &w, int &h ) { w = h = 0;
int tw = 0, th = 0; if ( _enabled ) { _enabled->GetSize( w, h ); } if ( _disabled ) { _disabled->GetSize( tw, th ); } if ( tw > w ) { w = tw; } if ( th > h ) { h = th; } }
virtual void ApplySchemeSettings(IScheme *pScheme) { BaseClass::ApplySchemeSettings(pScheme);
_enCol = GetSchemeColor("FrameSystemButton.FgColor", pScheme); _disCol = GetSchemeColor("FrameSystemButton.BgColor", pScheme); const char *pEnabledImage = m_EnabledImage.Length() ? m_EnabledImage.Get() : pScheme->GetResourceString( "FrameSystemButton.Icon" ); const char *pDisabledImage = m_DisabledImage.Length() ? m_DisabledImage.Get() : pScheme->GetResourceString( "FrameSystemButton.DisabledIcon" ); _enabled = scheme()->GetImage( pEnabledImage, false); _disabled = scheme()->GetImage( pDisabledImage, false);
SetTextInset(0, 0); // get our iconic image
SetEnabled(IsEnabled()); } virtual IBorder *GetBorder(bool depressed, bool armed, bool selected, bool keyfocus) { return NULL; }
virtual void SetEnabled(bool state) { Button::SetEnabled(state); if (IsEnabled()) { if ( _enabled ) { SetImageAtIndex(0, _enabled, 0); } SetBgColor(_enCol); SetDefaultColor(_enCol, _enCol); SetArmedColor(_enCol, _enCol); SetDepressedColor(_enCol, _enCol); } else { if ( _disabled ) { SetImageAtIndex(0, _disabled, 0); } SetBgColor(_disCol); SetDefaultColor(_disCol, _disCol); SetArmedColor(_disCol, _disCol); SetDepressedColor(_disCol, _disCol); } } void SetResponsive(bool state) { _respond = state; }
virtual void OnMousePressed(MouseCode code) { // button may look enabled but not be responsive
if (!_respond) return;
BaseClass::OnMousePressed(code); }
virtual void OnMouseDoublePressed(MouseCode code) { // button may look enabled but not be responsive
if (!_respond) return;
// only close if left is double pressed
if (code == MOUSE_LEFT) { // double click on the icon closes the window
// But only if the menu contains a 'close' item
vgui::Menu *pMenu = GetMenu(); if ( pMenu && pMenu->FindChildByName("Close") ) { PostMessage(GetVParent(), new KeyValues("CloseFrameButtonPressed")); } } }
};
} // namespace vgui
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
Frame::Frame(Panel *parent, const char *panelName, bool showTaskbarIcon /*=true*/, bool bPopup /*=true*/ ) : EditablePanel(parent, panelName) { // frames start invisible, to avoid having window flicker in on taskbar
SetVisible(false); if ( bPopup ) { MakePopup(showTaskbarIcon); }
m_hPreviousModal = 0;
_title=null; _moveable=true; _sizeable=true; m_bHasFocus=false; _flashWindow=false; _drawTitleBar = true; m_bPreviouslyVisible = false; m_bFadingOut = false; m_bDisableFadeEffect = false; m_flTransitionEffectTime = 0.0f; m_flFocusTransitionEffectTime = 0.0f; m_bDeleteSelfOnClose = false; m_iClientInsetX = 5; m_iClientInsetY = 5; m_iClientInsetXOverridden = false; m_iTitleTextInsetX = 28; m_bClipToParent = false; m_bSmallCaption = false; m_bChainKeysToParent = false; m_bPrimed = false; m_hCustomTitleFont = INVALID_FONT;
SetTitle("#Frame_Untitled", parent ? false : true); // add ourselves to the build group
SetBuildGroup(GetBuildGroup()); SetMinimumSize(128,66); GetFocusNavGroup().SetFocusTopLevel(true); #if !defined( _X360 )
_sysMenu = NULL;
// add dragging grips
_topGrip = new GripPanel(this, "frame_topGrip", 0, -1); _bottomGrip = new GripPanel(this, "frame_bottomGrip", 0, 1); _leftGrip = new GripPanel(this, "frame_leftGrip", -1, 0); _rightGrip = new GripPanel(this, "frame_rightGrip", 1, 0); _topLeftGrip = new GripPanel(this, "frame_tlGrip", -1, -1); _topRightGrip = new GripPanel(this, "frame_trGrip", 1, -1); _bottomLeftGrip = new GripPanel(this, "frame_blGrip", -1, 1); _bottomRightGrip = new GripPanel(this, "frame_brGrip", 1, 1); _captionGrip = new CaptionGripPanel(this, "frame_caption" ); _captionGrip->SetCursor(dc_arrow);
_minimizeButton = new FrameButton(this, "frame_minimize","0"); _minimizeButton->AddActionSignalTarget(this); _minimizeButton->SetCommand(new KeyValues("Minimize")); _maximizeButton = new FrameButton(this, "frame_maximize", "1"); //!! no maximize handler implemented yet, so leave maximize button disabled
SetMaximizeButtonVisible(false);
char str[] = { 0x6F, 0 }; _minimizeToSysTrayButton = new FrameButton(this, "frame_mintosystray", str); _minimizeToSysTrayButton->SetCommand("MinimizeToSysTray"); SetMinimizeToSysTrayButtonVisible(false); _closeButton = new FrameButton(this, "frame_close", "r"); _closeButton->AddActionSignalTarget(this); _closeButton->SetCommand(new KeyValues("CloseFrameButtonPressed")); if (!surface()->SupportsFeature(ISurface::FRAME_MINIMIZE_MAXIMIZE)) { SetMinimizeButtonVisible(false); SetMaximizeButtonVisible(false); }
if (parent) { // vgui doesn't support subwindow minimization
SetMinimizeButtonVisible(false); SetMaximizeButtonVisible(false); }
_menuButton = new FrameSystemButton(this, "frame_menu"); _menuButton->SetMenu(GetSysMenu()); #endif
SetupResizeCursors();
REGISTER_COLOR_AS_OVERRIDABLE( m_InFocusBgColor, "infocus_bgcolor_override" ); REGISTER_COLOR_AS_OVERRIDABLE( m_OutOfFocusBgColor, "outoffocus_bgcolor_override" ); REGISTER_COLOR_AS_OVERRIDABLE( _titleBarBgColor, "titlebarbgcolor_override" ); REGISTER_COLOR_AS_OVERRIDABLE( _titleBarDisabledBgColor, "titlebardisabledbgcolor_override" ); REGISTER_COLOR_AS_OVERRIDABLE( _titleBarFgColor, "titlebarfgcolor_override" ); REGISTER_COLOR_AS_OVERRIDABLE( _titleBarDisabledFgColor, "titlebardisabledfgcolor_override" ); }
//-----------------------------------------------------------------------------
// Purpose: Destructor
//-----------------------------------------------------------------------------
Frame::~Frame() { if ( input()->GetAppModalSurface() == GetVPanel() ) { vgui::input()->ReleaseAppModalSurface(); if ( m_hPreviousModal != 0 ) { vgui::input()->SetAppModalSurface( m_hPreviousModal ); m_hPreviousModal = 0; } }
#if !defined( _X360 )
delete _topGrip; delete _bottomGrip; delete _leftGrip; delete _rightGrip; delete _topLeftGrip; delete _topRightGrip; delete _bottomLeftGrip; delete _bottomRightGrip; delete _captionGrip; delete _minimizeButton; delete _maximizeButton; delete _closeButton; delete _menuButton; delete _minimizeToSysTrayButton; #endif
delete _title; }
//-----------------------------------------------------------------------------
// Purpose: Setup the grips on the edges of the panel to resize it.
//-----------------------------------------------------------------------------
void Frame::SetupResizeCursors() { #if !defined( _X360 )
if (IsSizeable()) { _topGrip->SetCursor(dc_sizens); _bottomGrip->SetCursor(dc_sizens); _leftGrip->SetCursor(dc_sizewe); _rightGrip->SetCursor(dc_sizewe); _topLeftGrip->SetCursor(dc_sizenwse); _topRightGrip->SetCursor(dc_sizenesw); _bottomLeftGrip->SetCursor(dc_sizenesw); _bottomRightGrip->SetCursor(dc_sizenwse);
_bottomRightGrip->SetPaintEnabled(true); _bottomRightGrip->SetPaintBackgroundEnabled(true); } else { // not resizable, so just use the default cursor
_topGrip->SetCursor(dc_arrow); _bottomGrip->SetCursor(dc_arrow); _leftGrip->SetCursor(dc_arrow); _rightGrip->SetCursor(dc_arrow); _topLeftGrip->SetCursor(dc_arrow); _topRightGrip->SetCursor(dc_arrow); _bottomLeftGrip->SetCursor(dc_arrow); _bottomRightGrip->SetCursor(dc_arrow);
_bottomRightGrip->SetPaintEnabled(false); _bottomRightGrip->SetPaintBackgroundEnabled(false); } #endif
}
//-----------------------------------------------------------------------------
// Purpose: Bring the frame to the front and requests focus, ensures it's not minimized
//-----------------------------------------------------------------------------
void Frame::Activate() { MoveToFront(); if ( IsKeyBoardInputEnabled() ) { RequestFocus(); } SetVisible(true); SetEnabled(true); if (m_bFadingOut) { // we were fading out, make sure to fade back in
m_bFadingOut = false; m_bPreviouslyVisible = false; }
surface()->SetMinimized(GetVPanel(), false); }
//-----------------------------------------------------------------------------
// Sets up, cleans up modal dialogs
//-----------------------------------------------------------------------------
void Frame::DoModal( ) { // move to the middle of the screen
MoveToCenterOfScreen(); InvalidateLayout(); Activate(); m_hPreviousModal = vgui::input()->GetAppModalSurface(); vgui::input()->SetAppModalSurface( GetVPanel() ); }
//-----------------------------------------------------------------------------
// Closes a modal dialog
//-----------------------------------------------------------------------------
void Frame::CloseModal() { vgui::input()->ReleaseAppModalSurface(); if ( m_hPreviousModal != 0 ) { vgui::input()->SetAppModalSurface( m_hPreviousModal ); m_hPreviousModal = 0; } PostMessage( this, new KeyValues("Close") ); }
//-----------------------------------------------------------------------------
// Purpose: activates the dialog
// if dialog is not currently visible it starts it minimized and flashing in the taskbar
//-----------------------------------------------------------------------------
void Frame::ActivateMinimized() { if ( ( IsVisible() && !IsMinimized() ) || !surface()->SupportsFeature( ISurface::FRAME_MINIMIZE_MAXIMIZE ) ) { Activate(); } else { ipanel()->MoveToBack(GetVPanel()); surface()->SetMinimized(GetVPanel(), true); SetVisible(true); SetEnabled(true); if (m_bFadingOut) { // we were fading out, make sure to fade back in
m_bFadingOut = false; m_bPreviouslyVisible = false; } FlashWindow(); } }
//-----------------------------------------------------------------------------
// Purpose: returns true if the dialog is currently minimized
//-----------------------------------------------------------------------------
bool Frame::IsMinimized() { return surface()->IsMinimized(GetVPanel()); }
//-----------------------------------------------------------------------------
// Purpose: Center the dialog on the screen
//-----------------------------------------------------------------------------
void Frame::MoveToCenterOfScreen() { int wx, wy, ww, wt; surface()->GetWorkspaceBounds(wx, wy, ww, wt); SetPos((ww - GetWide()) / 2, (wt - GetTall()) / 2); }
void Frame::LayoutProportional( FrameButton *bt ) { float scale = 1.0;
if( IsProportional() ) { int screenW, screenH; surface()->GetScreenSize( screenW, screenH );
int proW,proH; surface()->GetProportionalBase( proW, proH );
scale = ( (float)( screenH ) / (float)( proH ) ); }
bt->SetSize( (int)( FrameButton::GetButtonSide( this ) * scale ), (int)( FrameButton::GetButtonSide( this ) * scale ) ); bt->SetTextInset( (int)( ceil( 2 * scale ) ), (int) ( ceil(1 * scale ) ) ); }
//-----------------------------------------------------------------------------
// Purpose: per-frame thinking, used for transition effects
// only gets called if the Frame is visible
//-----------------------------------------------------------------------------
void Frame::OnThink() { BaseClass::OnThink();
// check for transition effects
if (IsVisible() && m_flTransitionEffectTime > 0 && ( !m_bDisableFadeEffect )) { if (m_bFadingOut) { // we're fading out, see if we're done so we can fully hide the window
if (GetAlpha() < ( IsX360() ? 64 : 1 )) { FinishClose(); } } else if (!m_bPreviouslyVisible) { // need to fade-in
m_bPreviouslyVisible = true; // fade in
if (IsX360()) { SetAlpha(64); } else { SetAlpha(0); } GetAnimationController()->RunAnimationCommand(this, "alpha", 255.0f, 0.0f, m_flTransitionEffectTime, AnimationController::INTERPOLATOR_LINEAR); } }
// check for focus changes
bool hasFocus = false;
if (input()) { VPANEL focus = input()->GetFocus(); if (focus && ipanel()->HasParent(focus, GetVPanel())) { if ( input()->GetAppModalSurface() == 0 || input()->GetAppModalSurface() == GetVPanel() ) { hasFocus = true; } } } if (hasFocus != m_bHasFocus) { // Because vgui focus is message based, and focus gets reset to NULL when a focused panel is deleted, we defer the flashing/transition
// animation for an extra frame in case something is deleted, a message is sent, and then we become the focused panel again on the
// next frame
if ( !m_bPrimed ) { m_bPrimed = true; return; } m_bPrimed = false; m_bHasFocus = hasFocus; OnFrameFocusChanged(m_bHasFocus); } else { m_bPrimed = false; } }
//-----------------------------------------------------------------------------
// Purpose: Called when the frame focus changes
//-----------------------------------------------------------------------------
void Frame::OnFrameFocusChanged(bool bHasFocus) { #if !defined( _X360 )
// enable/disable the frame buttons
_minimizeButton->SetDisabledLook(!bHasFocus); _maximizeButton->SetDisabledLook(!bHasFocus); _closeButton->SetDisabledLook(!bHasFocus); _minimizeToSysTrayButton->SetDisabledLook(!bHasFocus); _menuButton->SetEnabled(bHasFocus); _minimizeButton->InvalidateLayout(); _maximizeButton->InvalidateLayout(); _minimizeToSysTrayButton->InvalidateLayout(); _closeButton->InvalidateLayout(); _menuButton->InvalidateLayout(); #endif
if (bHasFocus) { _title->SetColor(_titleBarFgColor); } else { _title->SetColor(_titleBarDisabledFgColor); }
// set our background color
if (bHasFocus) { if (m_flFocusTransitionEffectTime && ( !m_bDisableFadeEffect )) { GetAnimationController()->RunAnimationCommand(this, "BgColor", m_InFocusBgColor, 0.0f, m_bDisableFadeEffect ? 0.0f : m_flTransitionEffectTime, AnimationController::INTERPOLATOR_LINEAR); } else { SetBgColor(m_InFocusBgColor); } } else { if (m_flFocusTransitionEffectTime && ( !m_bDisableFadeEffect )) { GetAnimationController()->RunAnimationCommand(this, "BgColor", m_OutOfFocusBgColor, 0.0f, m_bDisableFadeEffect ? 0.0f : m_flTransitionEffectTime, AnimationController::INTERPOLATOR_LINEAR); } else { SetBgColor(m_OutOfFocusBgColor); } }
// Stop flashing when we get focus
if (bHasFocus && _flashWindow) { FlashWindowStop(); } }
int Frame::GetDraggerSize() { const int DRAGGER_SIZE = 5; if ( m_bSmallCaption ) { return 3; } return DRAGGER_SIZE; }
int Frame::GetCornerSize() { const int CORNER_SIZE = 8; if ( m_bSmallCaption ) { return 6; } return CORNER_SIZE; }
int Frame::GetBottomRightSize() { const int BOTTOMRIGHTSIZE = 18; if ( m_bSmallCaption ) { return 12; } return BOTTOMRIGHTSIZE; }
int Frame::GetCaptionHeight() { const int CAPTIONHEIGHT = 23; if ( m_bSmallCaption ) { return 12; } return CAPTIONHEIGHT; }
//-----------------------------------------------------------------------------
// Purpose: Recalculate the position of all items
//-----------------------------------------------------------------------------
void Frame::PerformLayout() { // chain back
BaseClass::PerformLayout(); // move everything into place
int wide, tall; GetSize(wide, tall); #if !defined( _X360 )
int DRAGGER_SIZE = GetDraggerSize(); int CORNER_SIZE = GetCornerSize(); int CORNER_SIZE2 = CORNER_SIZE * 2; int BOTTOMRIGHTSIZE = GetBottomRightSize();
_topGrip->SetBounds(CORNER_SIZE, 0, wide - CORNER_SIZE2, DRAGGER_SIZE); _leftGrip->SetBounds(0, CORNER_SIZE, DRAGGER_SIZE, tall - CORNER_SIZE2); _topLeftGrip->SetBounds(0, 0, CORNER_SIZE, CORNER_SIZE); _topRightGrip->SetBounds(wide - CORNER_SIZE, 0, CORNER_SIZE, CORNER_SIZE); _bottomLeftGrip->SetBounds(0, tall - CORNER_SIZE, CORNER_SIZE, CORNER_SIZE);
// make the bottom-right grip larger
_bottomGrip->SetBounds(CORNER_SIZE, tall - DRAGGER_SIZE, wide - (CORNER_SIZE + BOTTOMRIGHTSIZE), DRAGGER_SIZE); _rightGrip->SetBounds(wide - DRAGGER_SIZE, CORNER_SIZE, DRAGGER_SIZE, tall - (CORNER_SIZE + BOTTOMRIGHTSIZE));
_bottomRightGrip->SetBounds(wide - BOTTOMRIGHTSIZE, tall - BOTTOMRIGHTSIZE, BOTTOMRIGHTSIZE, BOTTOMRIGHTSIZE); _captionGrip->SetSize(wide-10,GetCaptionHeight()); _topGrip->MoveToFront(); _bottomGrip->MoveToFront(); _leftGrip->MoveToFront(); _rightGrip->MoveToFront(); _topLeftGrip->MoveToFront(); _topRightGrip->MoveToFront(); _bottomLeftGrip->MoveToFront(); _bottomRightGrip->MoveToFront(); _maximizeButton->MoveToFront(); _menuButton->MoveToFront(); _minimizeButton->MoveToFront(); _minimizeToSysTrayButton->MoveToFront(); _menuButton->SetBounds(5+2, 5+3, GetCaptionHeight()-5, GetCaptionHeight()-5); #endif
float scale = 1; if (IsProportional()) { int screenW, screenH; surface()->GetScreenSize( screenW, screenH );
int proW,proH; surface()->GetProportionalBase( proW, proH );
scale = ( (float)( screenH ) / (float)( proH ) ); } #if !defined( _X360 )
int offset_start = (int)( 20 * scale ); int offset = offset_start;
int top_border_offset = (int) ( ( 5+3 ) * scale ); if ( m_bSmallCaption ) { top_border_offset = (int) ( ( 3 ) * scale ); }
int side_border_offset = (int) ( 5 * scale ); // push the buttons against the east side
if (_closeButton->IsVisible()) { _closeButton->SetPos((wide-side_border_offset)-offset,top_border_offset); offset += offset_start; LayoutProportional( _closeButton );
} if (_minimizeToSysTrayButton->IsVisible()) { _minimizeToSysTrayButton->SetPos((wide-side_border_offset)-offset,top_border_offset); offset += offset_start; LayoutProportional( _minimizeToSysTrayButton ); } if (_maximizeButton->IsVisible()) { _maximizeButton->SetPos((wide-side_border_offset)-offset,top_border_offset); offset += offset_start; LayoutProportional( _maximizeButton ); } if (_minimizeButton->IsVisible()) { _minimizeButton->SetPos((wide-side_border_offset)-offset,top_border_offset); offset += offset_start; LayoutProportional( _minimizeButton ); } #endif
}
//-----------------------------------------------------------------------------
// Purpose: Set the text in the title bar.
//-----------------------------------------------------------------------------
void Frame::SetTitle(const char *title, bool surfaceTitle) { if (!_title) { _title = new TextImage( "" ); }
Assert(title); _title->SetText(title);
// see if the combobox text has changed, and if so, post a message detailing the new text
const char *newTitle = title;
// check if the new text is a localized string, if so undo it
wchar_t unicodeText[128]; unicodeText[0] = 0; if (*newTitle == '#') { // try lookup in localization tables
StringIndex_t unlocalizedTextSymbol = g_pVGuiLocalize->FindIndex(newTitle + 1); if (unlocalizedTextSymbol != INVALID_LOCALIZE_STRING_INDEX) { // we have a new text value
wcsncpy( unicodeText, g_pVGuiLocalize->GetValueByIndex(unlocalizedTextSymbol), sizeof( unicodeText) / sizeof(wchar_t) ); } } else { g_pVGuiLocalize->ConvertANSIToUnicode( newTitle, unicodeText, sizeof(unicodeText) ); }
if (surfaceTitle) { surface()->SetTitle(GetVPanel(), unicodeText); } Repaint(); }
//-----------------------------------------------------------------------------
// Purpose: Sets the unicode text in the title bar
//-----------------------------------------------------------------------------
void Frame::SetTitle(const wchar_t *title, bool surfaceTitle) { if (!_title) { _title = new TextImage( "" ); } _title->SetText(title); if (surfaceTitle) { surface()->SetTitle(GetVPanel(), title); } Repaint(); }
//-----------------------------------------------------------------------------
// Purpose: Set the text in the title bar.
//-----------------------------------------------------------------------------
void Frame::InternalSetTitle(const char *title) { SetTitle(title, true); }
//-----------------------------------------------------------------------------
// Purpose: Set the movability of the panel
//-----------------------------------------------------------------------------
void Frame::SetMoveable(bool state) { _moveable=state; }
//-----------------------------------------------------------------------------
// Purpose: Set the resizability of the panel
//-----------------------------------------------------------------------------
void Frame::SetSizeable(bool state) { _sizeable=state; SetupResizeCursors(); }
// When moving via caption, don't let any part of window go outside parent's bounds
void Frame::SetClipToParent( bool state ) { m_bClipToParent = state; }
bool Frame::GetClipToParent() const { return m_bClipToParent; }
//-----------------------------------------------------------------------------
// Purpose: Check the movability of the panel
//-----------------------------------------------------------------------------
bool Frame::IsMoveable() { return _moveable; }
//-----------------------------------------------------------------------------
// Purpose: Check the resizability of the panel
//-----------------------------------------------------------------------------
bool Frame::IsSizeable() { return _sizeable; }
//-----------------------------------------------------------------------------
// Purpose: Get the size of the panel inside the frame edges.
//-----------------------------------------------------------------------------
void Frame::GetClientArea(int &x, int &y, int &wide, int &tall) { x = m_iClientInsetX;
GetSize(wide, tall);
if (_drawTitleBar) { int captionTall = surface()->GetFontTall(_title->GetFont());
int border = m_bSmallCaption ? CAPTION_TITLE_BORDER_SMALL : CAPTION_TITLE_BORDER; int yinset = m_bSmallCaption ? 0 : m_iClientInsetY;
yinset += m_iTitleTextInsetYOverride;
y = yinset + captionTall + border + 1; tall = (tall - yinset) - y; } if ( m_bSmallCaption ) { tall -= 5; }
wide = (wide - m_iClientInsetX) - x; }
//
//-----------------------------------------------------------------------------
// Purpose: applies user configuration settings
//-----------------------------------------------------------------------------
void Frame::ApplyUserConfigSettings(KeyValues *userConfig) { // calculate defaults
int wx, wy, ww, wt; vgui::surface()->GetWorkspaceBounds(wx, wy, ww, wt);
int x, y, wide, tall; GetBounds(x, y, wide, tall); bool bNoSettings = false; if (_moveable) { // check to see if anything is set
if (!userConfig->FindKey("xpos", false)) { bNoSettings = true; }
// get the user config position
// default to where we're currently at
x = userConfig->GetInt("xpos", x); y = userConfig->GetInt("ypos", y); } if (_sizeable) { wide = userConfig->GetInt("wide", wide); tall = userConfig->GetInt("tall", tall);
// Make sure it's no larger than the workspace
if ( wide > ww ) { wide = ww; } if ( tall > wt ) { tall = wt; } }
// see if the dialog has a place on the screen it wants to start
if (bNoSettings && GetDefaultScreenPosition(x, y, wide, tall)) { bNoSettings = false; }
// make sure it conforms to the minimum size of the dialog
int minWide, minTall; GetMinimumSize(minWide, minTall); if (wide < minWide) { wide = minWide; } if (tall < minTall) { tall = minTall; }
// make sure it's on the screen
if (x + wide > ww) { x = wx + ww - wide; } if (y + tall > wt) { y = wy + wt - tall; }
if (x < wx) { x = wx; } if (y < wy) { y = wy; }
SetBounds(x, y, wide, tall);
if (bNoSettings) { // since nothing was set, default our position to the middle of the screen
MoveToCenterOfScreen(); }
BaseClass::ApplyUserConfigSettings(userConfig); }
//-----------------------------------------------------------------------------
// Purpose: returns user config settings for this control
//-----------------------------------------------------------------------------
void Frame::GetUserConfigSettings(KeyValues *userConfig) { if (_moveable) { int x, y; GetPos(x, y); userConfig->SetInt("xpos", x); userConfig->SetInt("ypos", y); } if (_sizeable) { int w, t; GetSize(w, t); userConfig->SetInt("wide", w); userConfig->SetInt("tall", t); }
BaseClass::GetUserConfigSettings(userConfig); }
//-----------------------------------------------------------------------------
// Purpose: optimization, return true if this control has any user config settings
//-----------------------------------------------------------------------------
bool Frame::HasUserConfigSettings() { return true; }
//-----------------------------------------------------------------------------
// Purpose: gets the default position and size on the screen to appear the first time (defaults to centered)
//-----------------------------------------------------------------------------
bool Frame::GetDefaultScreenPosition(int &x, int &y, int &wide, int &tall) { return false; }
//-----------------------------------------------------------------------------
// Purpose: draws title bar
//-----------------------------------------------------------------------------
void Frame::PaintBackground() { // take the panel with focus and check up tree for this panel
// if you find it, than some child of you has the focus, so
// you should be focused
Color titleColor = _titleBarDisabledBgColor; if (m_bHasFocus) { titleColor = _titleBarBgColor; }
BaseClass::PaintBackground();
if (_drawTitleBar) { int wide = GetWide(); int tall = surface()->GetFontTall(_title->GetFont());
// caption
surface()->DrawSetColor(titleColor); int inset = m_bSmallCaption ? 3 : 5; int captionHeight = m_bSmallCaption ? 14: 28;
surface()->DrawFilledRect(inset, inset, wide - inset, captionHeight ); if (_title) { int nTitleX = m_iTitleTextInsetXOverride ? m_iTitleTextInsetXOverride : m_iTitleTextInsetX; int nTitleWidth = wide - 72; #if !defined( _X360 )
if ( _menuButton && _menuButton->IsVisible() ) { int mw, mh; _menuButton->GetImageSize( mw, mh ); nTitleX += mw; nTitleWidth -= mw; } #endif
int nTitleY; if ( m_iTitleTextInsetYOverride ) { nTitleY = m_iTitleTextInsetYOverride; } else { nTitleY = m_bSmallCaption ? 2 : 9; } _title->SetPos( nTitleX, nTitleY ); _title->SetSize( nTitleWidth, tall); _title->Paint(); } } }
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void Frame::ApplySchemeSettings(IScheme *pScheme) { // always chain back
BaseClass::ApplySchemeSettings(pScheme); SetOverridableColor( &_titleBarFgColor, GetSchemeColor("FrameTitleBar.TextColor", pScheme) ); SetOverridableColor( &_titleBarBgColor, GetSchemeColor("FrameTitleBar.BgColor", pScheme) ); SetOverridableColor( &_titleBarDisabledFgColor, GetSchemeColor("FrameTitleBar.DisabledTextColor", pScheme) ); SetOverridableColor( &_titleBarDisabledBgColor, GetSchemeColor("FrameTitleBar.DisabledBgColor", pScheme) );
const char *font = NULL; if ( m_bSmallCaption ) { font = pScheme->GetResourceString("FrameTitleBar.SmallFont"); } else { font = pScheme->GetResourceString("FrameTitleBar.Font"); }
HFont titlefont; if ( m_hCustomTitleFont ) { titlefont = m_hCustomTitleFont; } else { titlefont = pScheme->GetFont((font && *font) ? font : "Default", IsProportional()); }
_title->SetFont( titlefont ); _title->ResizeImageToContent();
#if !defined( _X360 )
HFont marfont = (HFont)0; if ( m_bSmallCaption ) { marfont = pScheme->GetFont( "MarlettSmall", IsProportional() ); } else { marfont = pScheme->GetFont( "Marlett", IsProportional() ); }
_minimizeButton->SetFont(marfont); _maximizeButton->SetFont(marfont); _minimizeToSysTrayButton->SetFont(marfont); _closeButton->SetFont(marfont); #endif
m_flTransitionEffectTime = atof(pScheme->GetResourceString("Frame.TransitionEffectTime")); m_flFocusTransitionEffectTime = atof(pScheme->GetResourceString("Frame.FocusTransitionEffectTime"));
SetOverridableColor( &m_InFocusBgColor, pScheme->GetColor("Frame.BgColor", GetBgColor()) ); SetOverridableColor( &m_OutOfFocusBgColor, pScheme->GetColor("Frame.OutOfFocusBgColor", m_InFocusBgColor) );
const char *resourceString = pScheme->GetResourceString("Frame.ClientInsetX"); if ( resourceString ) { m_iClientInsetX = atoi(resourceString); } resourceString = pScheme->GetResourceString("Frame.ClientInsetY"); if ( resourceString ) { m_iClientInsetY = atoi(resourceString); } resourceString = pScheme->GetResourceString("Frame.TitleTextInsetX"); if ( resourceString ) { m_iTitleTextInsetX = atoi(resourceString); }
SetBgColor(m_InFocusBgColor); SetBorder(pScheme->GetBorder("FrameBorder"));
OnFrameFocusChanged( m_bHasFocus ); }
// Disables the fade-in/out-effect even if configured in the scheme settings
void Frame::DisableFadeEffect( void ) { m_flFocusTransitionEffectTime = 0.f; m_flTransitionEffectTime = 0.f; }
void Frame::SetFadeEffectDisableOverride( bool disabled ) { m_bDisableFadeEffect = disabled; }
//-----------------------------------------------------------------------------
// Purpose: Apply settings loaded from a resource file
//-----------------------------------------------------------------------------
void Frame::ApplySettings(KeyValues *inResourceData) { // Don't change the frame's visibility, remove that setting from the config data
inResourceData->SetInt("visible", -1); BaseClass::ApplySettings(inResourceData);
SetCloseButtonVisible( inResourceData->GetBool( "setclosebuttonvisible", true ) );
if( !inResourceData->GetInt("settitlebarvisible", 1 ) ) // if "title" is "0" then don't draw the title bar
{ SetTitleBarVisible( false ); } // set the title
const char *title = inResourceData->GetString("title", ""); if (title && *title) { SetTitle(title, true); }
const char *titlefont = inResourceData->GetString("title_font", ""); if ( titlefont && titlefont[0] ) { IScheme *pScheme = scheme()->GetIScheme( GetScheme() ); if ( pScheme ) { m_hCustomTitleFont = pScheme->GetFont( titlefont ); } }
KeyValues *pKV = inResourceData->FindKey( "clientinsetx_override", false ); if ( pKV ) { m_iClientInsetX = pKV->GetInt(); m_iClientInsetXOverridden = true; } }
//-----------------------------------------------------------------------------
// Purpose: Apply settings loaded from a resource file
//-----------------------------------------------------------------------------
void Frame::GetSettings(KeyValues *outResourceData) { BaseClass::GetSettings(outResourceData); outResourceData->SetInt("settitlebarvisible", _drawTitleBar );
if (_title) { char buf[256]; _title->GetUnlocalizedText( buf, 255 ); if (buf[0]) { outResourceData->SetString("title", buf); } }
if ( m_iClientInsetXOverridden ) { outResourceData->SetInt( "clientinsetx_override", m_iClientInsetX ); } }
//-----------------------------------------------------------------------------
// Purpose: returns a description of the settings possible for a frame
//-----------------------------------------------------------------------------
const char *Frame::GetDescription() { static char buf[512]; Q_snprintf(buf, sizeof(buf), "%s, string title", BaseClass::GetDescription()); return buf; }
//-----------------------------------------------------------------------------
// Purpose: Go invisible when a close message is recieved.
//-----------------------------------------------------------------------------
void Frame::OnClose() { // if we're modal, release that before we hide the window else the wrong window will get focus
if (input()->GetAppModalSurface() == GetVPanel()) { input()->ReleaseAppModalSurface(); if ( m_hPreviousModal != 0 ) { vgui::input()->SetAppModalSurface( m_hPreviousModal ); m_hPreviousModal = 0; } } BaseClass::OnClose();
if (m_flTransitionEffectTime && !m_bDisableFadeEffect) { // begin the hide transition effect
GetAnimationController()->RunAnimationCommand(this, "alpha", 0.0f, 0.0f, m_flTransitionEffectTime, AnimationController::INTERPOLATOR_LINEAR); m_bFadingOut = true; // move us to the back of the draw order (so that fading out over the top of other dialogs doesn't look wierd)
surface()->MovePopupToBack(GetVPanel()); } else { // hide us immediately
FinishClose(); } }
//-----------------------------------------------------------------------------
// Purpose: Close button in frame pressed
//-----------------------------------------------------------------------------
void Frame::OnCloseFrameButtonPressed() { OnCommand("Close"); }
//-----------------------------------------------------------------------------
// Purpose: Command handling
//-----------------------------------------------------------------------------
void Frame::OnCommand(const char *command) { if (!stricmp(command, "Close")) { Close(); } else if (!stricmp(command, "CloseModal")) { CloseModal(); } else if (!stricmp(command, "Minimize")) { OnMinimize(); } else if (!stricmp(command, "MinimizeToSysTray")) { OnMinimizeToSysTray(); } else { BaseClass::OnCommand(command); } }
//-----------------------------------------------------------------------------
// Purpose: Get the system menu
//-----------------------------------------------------------------------------
Menu *Frame::GetSysMenu() { #if !defined( _X360 )
if (!_sysMenu) { _sysMenu = new Menu(this, NULL); _sysMenu->SetVisible(false); _sysMenu->AddActionSignalTarget(this);
_sysMenu->AddMenuItem("Minimize", "#SysMenu_Minimize", "Minimize", this); _sysMenu->AddMenuItem("Maximize", "#SysMenu_Maximize", "Maximize", this); _sysMenu->AddMenuItem("Close", "#SysMenu_Close", "Close", this);
// check for enabling/disabling menu items
// this might have to be done at other times as well.
Panel *menuItem = _sysMenu->FindChildByName("Minimize"); if (menuItem) { menuItem->SetEnabled(_minimizeButton->IsVisible()); } menuItem = _sysMenu->FindChildByName("Maximize"); if (menuItem) { menuItem->SetEnabled(_maximizeButton->IsVisible()); } menuItem = _sysMenu->FindChildByName("Close"); if (menuItem) { menuItem->SetEnabled(_closeButton->IsVisible()); } } return _sysMenu; #else
return NULL; #endif
}
//-----------------------------------------------------------------------------
// Purpose: Set the system menu
//-----------------------------------------------------------------------------
void Frame::SetSysMenu(Menu *menu) { #if !defined( _X360 )
if (menu == _sysMenu) return; _sysMenu->MarkForDeletion(); _sysMenu = menu;
_menuButton->SetMenu(_sysMenu); #endif
}
//-----------------------------------------------------------------------------
// Set the system menu images
//-----------------------------------------------------------------------------
void Frame::SetImages( const char *pEnabledImage, const char *pDisabledImage ) { #if !defined( _X360 )
_menuButton->SetImages( pEnabledImage, pDisabledImage ); #endif
}
//-----------------------------------------------------------------------------
// Purpose: Close the window
//-----------------------------------------------------------------------------
void Frame::Close() { OnClose(); }
//-----------------------------------------------------------------------------
// Purpose: Finishes closing the dialog
//-----------------------------------------------------------------------------
void Frame::FinishClose() { SetVisible(false); m_bPreviouslyVisible = false; m_bFadingOut = false;
OnFinishedClose(); if (m_bDeleteSelfOnClose) { // Must be last because if vgui is not running then this will call delete this!!!
MarkForDeletion(); } }
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void Frame::OnFinishedClose() { }
//-----------------------------------------------------------------------------
// Purpose: Minimize the window on the taskbar.
//-----------------------------------------------------------------------------
void Frame::OnMinimize() { surface()->SetMinimized(GetVPanel(), true); }
//-----------------------------------------------------------------------------
// Purpose: Does nothing by default
//-----------------------------------------------------------------------------
void Frame::OnMinimizeToSysTray() { }
//-----------------------------------------------------------------------------
// Purpose: Respond to mouse presses
//-----------------------------------------------------------------------------
void Frame::OnMousePressed(MouseCode code) { if (!IsBuildGroupEnabled()) { // if a child doesn't have focus, get it for ourselves
VPANEL focus = input()->GetFocus(); if (!focus || !ipanel()->HasParent(focus, GetVPanel())) { RequestFocus(); } } BaseClass::OnMousePressed(code); }
//-----------------------------------------------------------------------------
// Purpose: Toggle visibility of the system menu button
//-----------------------------------------------------------------------------
void Frame::SetMenuButtonVisible(bool state) { #if !defined( _X360 )
_menuButton->SetVisible(state); #endif
}
//-----------------------------------------------------------------------------
// Purpose: Toggle respond of the system menu button
// it will look enabled or disabled in response to the title bar
// but may not activate.
//-----------------------------------------------------------------------------
void Frame::SetMenuButtonResponsive(bool state) { #if !defined( _X360 )
_menuButton->SetResponsive(state); #endif
}
//-----------------------------------------------------------------------------
// Purpose: Toggle visibility of the minimize button
//-----------------------------------------------------------------------------
void Frame::SetMinimizeButtonVisible(bool state) { #if !defined( _X360 )
_minimizeButton->SetVisible(state); #endif
}
//-----------------------------------------------------------------------------
// Purpose: Toggle visibility of the maximize button
//-----------------------------------------------------------------------------
void Frame::SetMaximizeButtonVisible(bool state) { #if !defined( _X360 )
_maximizeButton->SetVisible(state); #endif
}
//-----------------------------------------------------------------------------
// Purpose: Toggles visibility of the minimize-to-systray icon (defaults to false)
//-----------------------------------------------------------------------------
void Frame::SetMinimizeToSysTrayButtonVisible(bool state) { #if !defined( _X360 )
_minimizeToSysTrayButton->SetVisible(state); #endif
}
//-----------------------------------------------------------------------------
// Purpose: Toggle visibility of the close button
//-----------------------------------------------------------------------------
void Frame::SetCloseButtonVisible(bool state) { #if !defined( _X360 )
_closeButton->SetVisible(state); #endif
}
//-----------------------------------------------------------------------------
// Purpose: soaks up any remaining messages
//-----------------------------------------------------------------------------
void Frame::OnKeyCodeReleased(KeyCode code) { }
//-----------------------------------------------------------------------------
// Purpose: soaks up any remaining messages
//-----------------------------------------------------------------------------
void Frame::OnKeyFocusTicked() { }
//-----------------------------------------------------------------------------
// Purpose: Toggles window flash state on a timer
//-----------------------------------------------------------------------------
void Frame::InternalFlashWindow() { if (_flashWindow) { // toggle icon flashing
_nextFlashState = true; surface()->FlashWindow(GetVPanel(), _nextFlashState); _nextFlashState = !_nextFlashState; PostMessage(this, new KeyValues("FlashWindow"), 1.8f); } }
//-----------------------------------------------------------------------------
// Purpose: Adds the child to the focus nav group
//-----------------------------------------------------------------------------
void Frame::OnChildAdded(VPANEL child) { BaseClass::OnChildAdded(child); }
//-----------------------------------------------------------------------------
// Purpose: Flash the window system tray button until the frame gets focus
//-----------------------------------------------------------------------------
void Frame::FlashWindow() { _flashWindow = true; _nextFlashState = true; InternalFlashWindow(); }
//-----------------------------------------------------------------------------
// Purpose: Stops any window flashing
//-----------------------------------------------------------------------------
void Frame::FlashWindowStop() { surface()->FlashWindow(GetVPanel(), false); _flashWindow = false; }
//-----------------------------------------------------------------------------
// Purpose: load the control settings - should be done after all the children are added to the dialog
//-----------------------------------------------------------------------------
void Frame::LoadControlSettings( const char *dialogResourceName, const char *pathID, KeyValues *pPreloadedKeyValues, KeyValues *pConditions ) { BaseClass::LoadControlSettings( dialogResourceName, pathID, pPreloadedKeyValues, pConditions );
// set the focus on the default control
Panel *defaultFocus = GetFocusNavGroup().GetDefaultPanel(); if (defaultFocus) { defaultFocus->RequestFocus(); } }
//-----------------------------------------------------------------------------
// Purpose: Checks for ctrl+shift+b hits to enter build mode
// Activates any hotkeys / default buttons
// Swallows any unhandled input
//-----------------------------------------------------------------------------
void Frame::OnKeyCodeTyped(KeyCode code) { bool shift = (input()->IsKeyDown(KEY_LSHIFT) || input()->IsKeyDown(KEY_RSHIFT)); bool ctrl = (input()->IsKeyDown(KEY_LCONTROL) || input()->IsKeyDown(KEY_RCONTROL)); bool alt = (input()->IsKeyDown(KEY_LALT) || input()->IsKeyDown(KEY_RALT)); if ( IsX360() ) { vgui::Panel *pMap = FindChildByName( "ControllerMap" ); if ( pMap && pMap->IsKeyBoardInputEnabled() ) { pMap->OnKeyCodeTyped( code ); return; } }
if ( ctrl && shift && alt && code == KEY_B) { // enable build mode
ActivateBuildMode(); } else if (ctrl && shift && alt && code == KEY_R) { // reload the scheme
VPANEL top = surface()->GetEmbeddedPanel(); if (top) { // reload the data file
scheme()->ReloadSchemes();
Panel *panel = ipanel()->GetPanel(top, GetModuleName()); if (panel) { // make the top-level panel reload it's scheme, it will chain down to all the child panels
panel->InvalidateLayout(false, true); } } } else if (alt && code == KEY_F4) { // user has hit the close
PostMessage(this, new KeyValues("CloseFrameButtonPressed")); } else if (code == KEY_ENTER) { // check for a default button
VPANEL panel = GetFocusNavGroup().GetCurrentDefaultButton(); if (panel && ipanel()->IsVisible( panel ) && ipanel()->IsEnabled( panel )) { // Activate the button
PostMessage(panel, new KeyValues("Hotkey")); } } else if ( code == KEY_ESCAPE && surface()->SupportsFeature(ISurface::ESCAPE_KEY) && input()->GetAppModalSurface() == GetVPanel() ) { // ESC cancels, unless we're in the engine - in the engine ESC flips between the UI and the game
CloseModal(); } // Usually don't chain back as Frames are the end of the line for key presses, unless
// m_bChainKeysToParent is set
else if ( m_bChainKeysToParent ) { BaseClass::OnKeyCodeTyped( code ); } else { input()->OnKeyCodeUnhandled( (int)code ); } }
//-----------------------------------------------------------------------------
// Purpose: If true, then OnKeyCodeTyped messages continue up past the Frame
// Input : state -
//-----------------------------------------------------------------------------
void Frame::SetChainKeysToParent( bool state ) { m_bChainKeysToParent = state; }
//-----------------------------------------------------------------------------
// Purpose: If true, then OnKeyCodeTyped messages continue up past the Frame
// Input : -
// Output : Returns true on success, false on failure.
//-----------------------------------------------------------------------------
bool Frame::CanChainKeysToParent() const { return m_bChainKeysToParent; }
//-----------------------------------------------------------------------------
// Purpose: Checks for ctrl+shift+b hits to enter build mode
// Activates any hotkeys / default buttons
// Swallows any unhandled input
//-----------------------------------------------------------------------------
void Frame::OnKeyTyped(wchar_t unichar) { Panel *panel = GetFocusNavGroup().FindPanelByHotkey(unichar); if (panel) { // tell the panel to Activate
PostMessage(panel, new KeyValues("Hotkey")); } }
//-----------------------------------------------------------------------------
// Purpose: sets all title bar controls
//-----------------------------------------------------------------------------
void Frame::SetTitleBarVisible( bool state ) { _drawTitleBar = state; SetMenuButtonVisible(state); SetMinimizeButtonVisible(state); SetMaximizeButtonVisible(state); SetCloseButtonVisible(state); }
//-----------------------------------------------------------------------------
// Purpose: sets the frame to delete itself on close
//-----------------------------------------------------------------------------
void Frame::SetDeleteSelfOnClose( bool state ) { m_bDeleteSelfOnClose = state; }
//-----------------------------------------------------------------------------
// Purpose: updates localized text
//-----------------------------------------------------------------------------
void Frame::OnDialogVariablesChanged( KeyValues *dialogVariables ) { StringIndex_t index = _title->GetUnlocalizedTextSymbol(); if (index != INVALID_LOCALIZE_STRING_INDEX) { // reconstruct the string from the variables
wchar_t buf[1024]; g_pVGuiLocalize->ConstructString(buf, sizeof(buf), index, dialogVariables); SetTitle(buf, true); } }
//-----------------------------------------------------------------------------
// Purpose: Handles staying on screen when the screen size changes
//-----------------------------------------------------------------------------
void Frame::OnScreenSizeChanged(int iOldWide, int iOldTall) { BaseClass::OnScreenSizeChanged(iOldWide, iOldTall);
if (IsProportional()) return;
// make sure we're completely on screen
int iNewWide, iNewTall; surface()->GetScreenSize(iNewWide, iNewTall);
int x, y, wide, tall; GetBounds(x, y, wide, tall);
// make sure the bottom-right corner is on the screen first
if (x + wide > iNewWide) { x = iNewWide - wide; } if (y + tall > iNewTall) { y = iNewTall - tall; }
// make sure the top-left is visible
x = max( 0, x ); y = max( 0, y );
// apply
SetPos(x, y); }
//-----------------------------------------------------------------------------
// Purpose: For supporting thin caption bars
// Input : state -
//-----------------------------------------------------------------------------
void Frame::SetSmallCaption( bool state ) { m_bSmallCaption = state; InvalidateLayout(); }
//-----------------------------------------------------------------------------
// Purpose:
// Input : -
// Output : Returns true on success, false on failure.
//-----------------------------------------------------------------------------
bool Frame::IsSmallCaption() const { return m_bSmallCaption; }
//-----------------------------------------------------------------------------
// Purpose: Static method to place a frame under the cursor
//-----------------------------------------------------------------------------
void Frame::PlaceUnderCursor( ) { // get cursor position, this is local to this text edit window
int cursorX, cursorY; input()->GetCursorPos( cursorX, cursorY );
// relayout the menu immediately so that we know it's size
InvalidateLayout(true); int w, h; GetSize( w, h );
// work out where the cursor is and therefore the best place to put the frame
int sw, sh; surface()->GetScreenSize( sw, sh );
// Try to center it first
int x, y; x = cursorX - ( w / 2 ); y = cursorY - ( h / 2 );
// Clamp to various sides
if ( x + w > sw ) { x = sw - w; } if ( y + h > sh ) { y = sh - h; } if ( x < 0 ) { x = 0; } if ( y < 0 ) { y = 0; }
SetPos( x, y ); }
|