From f56bb35301836e56582a575a75864392a0177875 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20P=2E=20Tjern=C3=B8?= Date: Mon, 2 Dec 2013 19:31:46 -0800 Subject: Fix line endings. WHAMMY. --- mp/src/vgui2/vgui_controls/Frame.cpp | 4792 +++++++++++++++++----------------- 1 file changed, 2396 insertions(+), 2396 deletions(-) (limited to 'mp/src/vgui2/vgui_controls/Frame.cpp') diff --git a/mp/src/vgui2/vgui_controls/Frame.cpp b/mp/src/vgui2/vgui_controls/Frame.cpp index 3d4718ad..35b5d761 100644 --- a/mp/src/vgui2/vgui_controls/Frame.cpp +++ b/mp/src/vgui2/vgui_controls/Frame.cpp @@ -1,2396 +1,2396 @@ -//========= Copyright Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//===========================================================================// - -#include -#include // 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 - -// 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 ); -} +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//===========================================================================// + +#include +#include // 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 + +// 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 ); +} -- cgit v1.2.3