Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2401 lines
64 KiB

  1. //===== Copyright (c) 1996-2005, Valve Corporation, All rights reserved. ======//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //===========================================================================//
  7. #include <assert.h>
  8. #include <math.h> // for ceil()
  9. #define PROTECTED_THINGS_DISABLE
  10. #include "tier1/utlstring.h"
  11. #include "vgui/Cursor.h"
  12. #include "vgui/MouseCode.h"
  13. #include "vgui/IBorder.h"
  14. #include "vgui/IInput.h"
  15. #include "vgui/ILocalize.h"
  16. #include "vgui/IPanel.h"
  17. #include "vgui/ISurface.h"
  18. #include "vgui/IScheme.h"
  19. #include "vgui/KeyCode.h"
  20. #include "vgui_controls/AnimationController.h"
  21. #include "vgui_controls/Controls.h"
  22. #include "vgui_controls/Frame.h"
  23. #include "vgui_controls/Button.h"
  24. #include "vgui_controls/Menu.h"
  25. #include "vgui_controls/MenuButton.h"
  26. #include "vgui_controls/TextImage.h"
  27. #include "keyvalues.h"
  28. #include <stdio.h>
  29. // memdbgon must be the last include file in a .cpp file!!!
  30. #include "tier0/memdbgon.h"
  31. using namespace vgui;
  32. static const int DEFAULT_SNAP_RANGE = 10; // number of pixels distance before the frame will snap to an edge
  33. static const int CAPTION_TITLE_BORDER = 7;
  34. static const int CAPTION_TITLE_BORDER_SMALL = 0;
  35. namespace
  36. {
  37. //-----------------------------------------------------------------------------
  38. // Purpose: Invisible panel to handle dragging/resizing frames
  39. //-----------------------------------------------------------------------------
  40. class GripPanel : public Panel
  41. {
  42. public:
  43. GripPanel(Frame *dragFrame, const char *name, int xdir, int ydir) : Panel(dragFrame, name)
  44. {
  45. _frame = dragFrame;
  46. _dragging = false;
  47. _dragMultX = xdir;
  48. _dragMultY = ydir;
  49. SetPaintEnabled(false);
  50. SetPaintBackgroundEnabled(false);
  51. SetPaintBorderEnabled(false);
  52. m_iSnapRange = DEFAULT_SNAP_RANGE;
  53. if (xdir == 1 && ydir == 1)
  54. {
  55. // bottom-right grip gets an image
  56. SetPaintEnabled(true);
  57. SetPaintBackgroundEnabled(true);
  58. }
  59. SetBlockDragChaining( true );
  60. SetKeyBoardInputEnabled( false );
  61. }
  62. // Purpose- handle window resizing
  63. // Input- dx, dy, the offet of the mouse pointer from where we started dragging
  64. virtual void moved(int dx, int dy)
  65. {
  66. if (!_frame->IsSizeable())
  67. return;
  68. // Start off with x, y at the coords of where we started to drag
  69. int newX = _dragOrgPos[0], newY =_dragOrgPos[1];
  70. // Start off with width and tall equal from window when we started to drag
  71. int newWide = _dragOrgSize[0], newTall = _dragOrgSize[1];
  72. // get window's minimum size
  73. int minWide, minTall;
  74. _frame->GetMinimumSize( minWide, minTall);
  75. // Handle width resizing
  76. newWide += (dx * _dragMultX);
  77. // Handle the position of the corner x position
  78. if (_dragMultX == -1)
  79. {
  80. // only move if we are not at the minimum
  81. // if we are at min we have to force the proper offset (dx)
  82. if (newWide < minWide)
  83. {
  84. dx=_dragOrgSize[0]-minWide;
  85. }
  86. newX += dx; // move window to its new position
  87. }
  88. // Handle height resizing
  89. newTall += (dy * _dragMultY);
  90. // Handle position of corner y position
  91. if (_dragMultY == -1)
  92. {
  93. if (newTall < minTall)
  94. {
  95. dy=_dragOrgSize[1]-minTall;
  96. }
  97. newY += dy;
  98. }
  99. if ( _frame->GetClipToParent() )
  100. {
  101. // If any coordinate is out of range, snap it back
  102. if ( newX < 0 )
  103. newX = 0;
  104. if ( newY < 0 )
  105. newY = 0;
  106. int sx, sy;
  107. surface()->GetScreenSize( sx, sy );
  108. int w, h;
  109. _frame->GetSize( w, h );
  110. if ( newX + w > sx )
  111. {
  112. newX = sx - w;
  113. }
  114. if ( newY + h > sy )
  115. {
  116. newY = sy - h;
  117. }
  118. }
  119. _frame->OnGripPanelMoved( newX, newY, newWide, newTall );
  120. _frame->InvalidateLayout();
  121. _frame->Repaint();
  122. }
  123. void OnCursorMoved(int x, int y)
  124. {
  125. if (!_dragging)
  126. return;
  127. if (!input()->IsMouseDown(MOUSE_LEFT))
  128. {
  129. // for some reason we're marked as dragging when the mouse is released
  130. // trigger a release
  131. OnMouseReleased(MOUSE_LEFT);
  132. return;
  133. }
  134. input()->GetCursorPos(x, y);
  135. int wx, wy, ww, wt;
  136. surface()->GetWorkspaceBounds(wx, wy, ww, wt);
  137. // Keep from dragging caption out of window
  138. x = clamp( x, wx, wx + ww - 1 );
  139. y = clamp( y, wy, wy + wt - 1 );
  140. moved((x - _dragStart[0]), ( y - _dragStart[1]));
  141. _frame->Repaint();
  142. }
  143. void OnMousePressed(MouseCode code)
  144. {
  145. if (code == MOUSE_LEFT)
  146. {
  147. _dragging=true;
  148. int x,y;
  149. input()->GetCursorPos(x,y);
  150. _dragStart[0]=x;
  151. _dragStart[1]=y;
  152. _frame->GetPos(_dragOrgPos[0],_dragOrgPos[1]);
  153. _frame->GetSize(_dragOrgSize[0],_dragOrgSize[1]);
  154. input()->SetMouseCapture(GetVPanel());
  155. // if a child doesn't have focus, get it for ourselves
  156. VPANEL focus = input()->GetFocus();
  157. if (!focus || !ipanel()->HasParent(focus, _frame->GetVPanel()))
  158. {
  159. _frame->RequestFocus();
  160. }
  161. _frame->Repaint();
  162. }
  163. else
  164. {
  165. GetParent()->OnMousePressed(code);
  166. }
  167. }
  168. void OnMouseDoublePressed(MouseCode code)
  169. {
  170. GetParent()->OnMouseDoublePressed(code);
  171. }
  172. void Paint()
  173. {
  174. // draw the grab handle in the bottom right of the frame
  175. surface()->DrawSetTextFont(_marlettFont);
  176. surface()->DrawSetTextPos(0, 0);
  177. // thin highlight lines
  178. surface()->DrawSetTextColor(GetFgColor());
  179. surface()->DrawUnicodeChar('p');
  180. }
  181. void PaintBackground()
  182. {
  183. // draw the grab handle in the bottom right of the frame
  184. surface()->DrawSetTextFont(_marlettFont);
  185. surface()->DrawSetTextPos(0, 0);
  186. // thick shadow lines
  187. surface()->DrawSetTextColor(GetBgColor());
  188. surface()->DrawUnicodeChar('o');
  189. }
  190. void OnMouseReleased(MouseCode code)
  191. {
  192. _dragging = false;
  193. input()->SetMouseCapture(NULL);
  194. _frame->OnGripPanelMoveFinished();
  195. }
  196. void OnMouseCaptureLost()
  197. {
  198. Panel::OnMouseCaptureLost();
  199. _dragging = false;
  200. _frame->OnGripPanelMoveFinished();
  201. }
  202. void ApplySchemeSettings(IScheme *pScheme)
  203. {
  204. Panel::ApplySchemeSettings(pScheme);
  205. bool isSmall = ((Frame *)GetParent())->IsSmallCaption();
  206. _marlettFont = pScheme->GetFont( isSmall ? "MarlettSmall" : "Marlett", IsProportional());
  207. SetFgColor(GetSchemeColor("FrameGrip.Color1", pScheme));
  208. SetBgColor(GetSchemeColor("FrameGrip.Color2", pScheme));
  209. const char *snapRange = pScheme->GetResourceString("Frame.AutoSnapRange");
  210. if (snapRange && *snapRange)
  211. {
  212. m_iSnapRange = atoi(snapRange);
  213. }
  214. }
  215. protected:
  216. Frame *_frame;
  217. int _dragMultX;
  218. int _dragMultY;
  219. bool _dragging;
  220. int _dragOrgPos[2];
  221. int _dragOrgSize[2];
  222. int _dragStart[2];
  223. int m_iSnapRange;
  224. HFont _marlettFont;
  225. };
  226. //-----------------------------------------------------------------------------
  227. // Purpose: Handles caption grip input for moving dialogs around
  228. //-----------------------------------------------------------------------------
  229. class CaptionGripPanel : public GripPanel
  230. {
  231. public:
  232. CaptionGripPanel(Frame* frame, const char *name) : GripPanel(frame, name, 0, 0)
  233. {
  234. }
  235. void moved(int dx, int dy)
  236. {
  237. if (!_frame->IsMoveable())
  238. return;
  239. int newX = _dragOrgPos[0] + dx;
  240. int newY = _dragOrgPos[1] + dy;
  241. if (m_iSnapRange)
  242. {
  243. // first check docking to desktop
  244. int wx, wy, ww, wt;
  245. surface()->GetWorkspaceBounds(wx, wy, ww, wt);
  246. getInsideSnapPosition(wx, wy, ww, wt, newX, newY);
  247. // now lets check all windows and see if we snap to those
  248. // root panel
  249. VPANEL root = surface()->GetEmbeddedPanel();
  250. // cycle through panels
  251. // look for panels that are visible and are popups that we can dock to
  252. for (int i = 0; i < ipanel()->GetChildCount(root); ++i)
  253. {
  254. VPANEL child = ipanel()->GetChild(root, i);
  255. tryToDock (child, newX, newY);
  256. }
  257. }
  258. if ( _frame->GetClipToParent() )
  259. {
  260. // If any coordinate is out of range, snap it back
  261. if ( newX < 0 )
  262. newX = 0;
  263. if ( newY < 0 )
  264. newY = 0;
  265. int sx, sy;
  266. surface()->GetScreenSize( sx, sy );
  267. int w, h;
  268. _frame->GetSize( w, h );
  269. if ( newX + w > sx )
  270. {
  271. newX = sx - w;
  272. }
  273. if ( newY + h > sy )
  274. {
  275. newY = sy - h;
  276. }
  277. }
  278. _frame->SetPos(newX, newY);
  279. }
  280. void tryToDock(VPANEL window, int &newX, int & newY)
  281. {
  282. // bail if child is this window
  283. if ( window == _frame->GetVPanel())
  284. return;
  285. int cx, cy, cw, ct;
  286. if ( (ipanel()->IsVisible(window)) && (ipanel()->IsPopup(window)) )
  287. {
  288. // position
  289. ipanel()->GetAbsPos(window, cx, cy);
  290. // dimensions
  291. ipanel()->GetSize(window, cw, ct);
  292. bool snapped = getOutsideSnapPosition (cx, cy, cw, ct, newX, newY);
  293. if (snapped)
  294. {
  295. // if we snapped, we're done with this path
  296. // dont try to snap to kids
  297. return;
  298. }
  299. }
  300. // check all children
  301. for (int i = 0; i < ipanel()->GetChildCount(window); ++i)
  302. {
  303. VPANEL child = ipanel()->GetChild(window, i);
  304. tryToDock(child, newX, newY);
  305. }
  306. }
  307. // Purpose: To calculate the windows new x,y position if it snaps
  308. // Will snap to the INSIDE of a window (eg desktop sides
  309. // Input: boundX boundY, position of candidate window we are seeing if we snap to
  310. // boundWide, boundTall, width and height of window we are seeing if we snap to
  311. // Output: snapToX, snapToY new coords for window, unchanged if we dont snap
  312. // Returns true if we snapped, false if we did not snap.
  313. bool getInsideSnapPosition(int boundX, int boundY, int boundWide, int boundTall,
  314. int &snapToX, int &snapToY)
  315. {
  316. int wide, tall;
  317. _frame->GetSize(wide, tall);
  318. Assert (wide > 0);
  319. Assert (tall > 0);
  320. bool snapped=false;
  321. if (abs(snapToX - boundX) < m_iSnapRange)
  322. {
  323. snapToX = boundX;
  324. snapped=true;
  325. }
  326. else if (abs((snapToX + wide) - (boundX + boundWide)) < m_iSnapRange)
  327. {
  328. snapToX = boundX + boundWide - wide;
  329. snapped=true;
  330. }
  331. if (abs(snapToY - boundY) < m_iSnapRange)
  332. {
  333. snapToY = boundY;
  334. snapped=true;
  335. }
  336. else if (abs((snapToY + tall) - (boundY + boundTall)) < m_iSnapRange)
  337. {
  338. snapToY = boundY + boundTall - tall;
  339. snapped=true;
  340. }
  341. return snapped;
  342. }
  343. // Purpose: To calculate the windows new x,y position if it snaps
  344. // Will snap to the OUTSIDE edges of a window (i.e. will stick peers together
  345. // Input: left, top, position of candidate window we are seeing if we snap to
  346. // boundWide, boundTall, width and height of window we are seeing if we snap to
  347. // Output: snapToX, snapToY new coords for window, unchanged if we dont snap
  348. // Returns true if we snapped, false if we did not snap.
  349. bool getOutsideSnapPosition(int left, int top, int boundWide, int boundTall,
  350. int &snapToX, int &snapToY)
  351. {
  352. Assert (boundWide >= 0);
  353. Assert (boundTall >= 0);
  354. bool snapped=false;
  355. int right=left+boundWide;
  356. int bottom=top+boundTall;
  357. int wide, tall;
  358. _frame->GetSize(wide, tall);
  359. Assert (wide > 0);
  360. Assert (tall > 0);
  361. // we now see if we are going to be able to snap to a window side, and not
  362. // just snap to the "open air"
  363. // want to make it so that if any part of the window can dock to the candidate, it will
  364. // is this window horizontally snappable to the candidate
  365. bool horizSnappable=(
  366. // top of window is in range
  367. ((snapToY > top) && (snapToY < bottom))
  368. // bottom of window is in range
  369. || ((snapToY+tall > top) && (snapToY+tall < bottom))
  370. // window is just plain bigger than the window we wanna dock to
  371. || ((snapToY < top) && (snapToY+tall > bottom)) );
  372. // is this window vertically snappable to the candidate
  373. bool vertSnappable= (
  374. // left of window is in range
  375. ((snapToX > left) && (snapToX < right))
  376. // right of window is in range
  377. || ((snapToX+wide > left) && (snapToX+wide < right))
  378. // window is just plain bigger than the window we wanna dock to
  379. || ((snapToX < left) && (snapToX+wide > right)) );
  380. // if neither, might as well bail
  381. if ( !(horizSnappable || vertSnappable) )
  382. return false;
  383. //if we're within the snap threshold then snap
  384. if ( (snapToX <= (right+m_iSnapRange)) &&
  385. (snapToX >= (right-m_iSnapRange)) )
  386. {
  387. if (horizSnappable)
  388. {
  389. //disallow "open air" snaps
  390. snapped=true;
  391. snapToX = right;
  392. }
  393. }
  394. else if ((snapToX + wide) >= (left-m_iSnapRange) &&
  395. (snapToX + wide) <= (left+m_iSnapRange))
  396. {
  397. if (horizSnappable)
  398. {
  399. snapped=true;
  400. snapToX = left-wide;
  401. }
  402. }
  403. if ( (snapToY <= (bottom+m_iSnapRange)) &&
  404. (snapToY >= (bottom-m_iSnapRange)) )
  405. {
  406. if (vertSnappable)
  407. {
  408. snapped=true;
  409. snapToY = bottom;
  410. }
  411. }
  412. else if ((snapToY + tall) <= (top+m_iSnapRange) &&
  413. (snapToY + tall) >= (top-m_iSnapRange))
  414. {
  415. if (vertSnappable)
  416. {
  417. snapped=true;
  418. snapToY = top-tall;
  419. }
  420. }
  421. return snapped;
  422. }
  423. };
  424. }
  425. namespace vgui
  426. {
  427. //-----------------------------------------------------------------------------
  428. // Purpose: overrides normal button drawing to use different colors & borders
  429. //-----------------------------------------------------------------------------
  430. class FrameButton : public Button
  431. {
  432. private:
  433. IBorder *_brightBorder, *_depressedBorder, *_disabledBorder;
  434. Color _enabledFgColor, _enabledBgColor;
  435. Color _disabledFgColor, _disabledBgColor;
  436. bool _disabledLook;
  437. public:
  438. static int GetButtonSide( Frame *pFrame )
  439. {
  440. if ( pFrame->IsSmallCaption() )
  441. {
  442. return 12;
  443. }
  444. return 18;
  445. }
  446. FrameButton(Panel *parent, const char *name, const char *text) : Button(parent, name, text)
  447. {
  448. SetSize( FrameButton::GetButtonSide( (Frame *)parent ), FrameButton::GetButtonSide( (Frame *)parent ) );
  449. _brightBorder = NULL;
  450. _depressedBorder = NULL;
  451. _disabledBorder = NULL;
  452. _disabledLook = true;
  453. SetContentAlignment(Label::a_northwest);
  454. SetTextInset(2, 1);
  455. SetBlockDragChaining( true );
  456. }
  457. virtual void ApplySchemeSettings(IScheme *pScheme)
  458. {
  459. Button::ApplySchemeSettings(pScheme);
  460. _enabledFgColor = GetSchemeColor("FrameTitleButton.FgColor", pScheme);
  461. _enabledBgColor = GetSchemeColor("FrameTitleButton.BgColor", pScheme);
  462. _disabledFgColor = GetSchemeColor("FrameTitleButton.DisabledFgColor", pScheme);
  463. _disabledBgColor = GetSchemeColor("FrameTitleButton.DisabledBgColor", pScheme);
  464. _brightBorder = pScheme->GetBorder("TitleButtonBorder");
  465. _depressedBorder = pScheme->GetBorder("TitleButtonDepressedBorder");
  466. _disabledBorder = pScheme->GetBorder("TitleButtonDisabledBorder");
  467. SetDisabledLook(_disabledLook);
  468. }
  469. virtual IBorder *GetBorder(bool depressed, bool armed, bool selected, bool keyfocus)
  470. {
  471. if (_disabledLook)
  472. {
  473. return _disabledBorder;
  474. }
  475. if (depressed)
  476. {
  477. return _depressedBorder;
  478. }
  479. return _brightBorder;
  480. }
  481. virtual void SetDisabledLook(bool state)
  482. {
  483. _disabledLook = state;
  484. if (!_disabledLook)
  485. {
  486. SetDefaultColor(_enabledFgColor, _enabledBgColor);
  487. SetArmedColor(_enabledFgColor, _enabledBgColor);
  488. SetDepressedColor(_enabledFgColor, _enabledBgColor);
  489. }
  490. else
  491. {
  492. // setup disabled colors
  493. SetDefaultColor(_disabledFgColor, _disabledBgColor);
  494. SetArmedColor(_disabledFgColor, _disabledBgColor);
  495. SetDepressedColor(_disabledFgColor, _disabledBgColor);
  496. }
  497. }
  498. virtual void PerformLayout()
  499. {
  500. Button::PerformLayout();
  501. Repaint();
  502. }
  503. // Don't request focus.
  504. // This will keep items in the listpanel selected.
  505. virtual void OnMousePressed(MouseCode code)
  506. {
  507. if (!IsEnabled())
  508. return;
  509. if (!IsMouseClickEnabled(code))
  510. return;
  511. if (IsUseCaptureMouseEnabled())
  512. {
  513. {
  514. SetSelected(true);
  515. Repaint();
  516. }
  517. // lock mouse input to going to this button
  518. input()->SetMouseCapture(GetVPanel());
  519. }
  520. }
  521. };
  522. //-----------------------------------------------------------------------------
  523. // Purpose: icon button
  524. //-----------------------------------------------------------------------------
  525. class FrameSystemButton : public MenuButton
  526. {
  527. DECLARE_CLASS_SIMPLE( FrameSystemButton, MenuButton );
  528. private:
  529. IImage *_enabled, *_disabled;
  530. Color _enCol, _disCol;
  531. bool _respond;
  532. CUtlString m_EnabledImage;
  533. CUtlString m_DisabledImage;
  534. public:
  535. FrameSystemButton(Panel *parent, const char *panelName) : MenuButton(parent, panelName, "")
  536. {
  537. _disabled = _enabled = NULL;
  538. _respond = true;
  539. SetEnabled(false);
  540. // This menu will open if we use the left or right mouse button
  541. SetMouseClickEnabled( MOUSE_RIGHT, true );
  542. SetBlockDragChaining( true );
  543. }
  544. void SetImages( const char *pEnabledImage, const char *pDisabledImage = NULL )
  545. {
  546. m_EnabledImage = pEnabledImage;
  547. m_DisabledImage = pDisabledImage ? pDisabledImage : pEnabledImage;
  548. }
  549. void GetImageSize( int &w, int &h )
  550. {
  551. w = h = 0;
  552. int tw = 0, th = 0;
  553. if ( _enabled )
  554. {
  555. _enabled->GetSize( w, h );
  556. }
  557. if ( _disabled )
  558. {
  559. _disabled->GetSize( tw, th );
  560. }
  561. if ( tw > w )
  562. {
  563. w = tw;
  564. }
  565. if ( th > h )
  566. {
  567. h = th;
  568. }
  569. }
  570. virtual void ApplySchemeSettings(IScheme *pScheme)
  571. {
  572. BaseClass::ApplySchemeSettings(pScheme);
  573. _enCol = GetSchemeColor("FrameSystemButton.FgColor", pScheme);
  574. _disCol = GetSchemeColor("FrameSystemButton.BgColor", pScheme);
  575. const char *pEnabledImage = m_EnabledImage.Length() ? m_EnabledImage.Get() :
  576. pScheme->GetResourceString( "FrameSystemButton.Icon" );
  577. const char *pDisabledImage = m_DisabledImage.Length() ? m_DisabledImage.Get() :
  578. pScheme->GetResourceString( "FrameSystemButton.DisabledIcon" );
  579. _enabled = scheme()->GetImage( pEnabledImage, false);
  580. _disabled = scheme()->GetImage( pDisabledImage, false);
  581. SetTextInset(0, 0);
  582. // get our iconic image
  583. SetEnabled(IsEnabled());
  584. }
  585. virtual IBorder *GetBorder(bool depressed, bool armed, bool selected, bool keyfocus)
  586. {
  587. return NULL;
  588. }
  589. virtual void SetEnabled(bool state)
  590. {
  591. Button::SetEnabled(state);
  592. if (IsEnabled())
  593. {
  594. if ( _enabled )
  595. {
  596. SetImageAtIndex(0, _enabled, 0);
  597. }
  598. SetBgColor(_enCol);
  599. SetDefaultColor(_enCol, _enCol);
  600. SetArmedColor(_enCol, _enCol);
  601. SetDepressedColor(_enCol, _enCol);
  602. }
  603. else
  604. {
  605. if ( _disabled )
  606. {
  607. SetImageAtIndex(0, _disabled, 0);
  608. }
  609. SetBgColor(_disCol);
  610. SetDefaultColor(_disCol, _disCol);
  611. SetArmedColor(_disCol, _disCol);
  612. SetDepressedColor(_disCol, _disCol);
  613. }
  614. }
  615. void SetResponsive(bool state)
  616. {
  617. _respond = state;
  618. }
  619. virtual void OnMousePressed(MouseCode code)
  620. {
  621. // button may look enabled but not be responsive
  622. if (!_respond)
  623. return;
  624. BaseClass::OnMousePressed(code);
  625. }
  626. virtual void OnMouseDoublePressed(MouseCode code)
  627. {
  628. // button may look enabled but not be responsive
  629. if (!_respond)
  630. return;
  631. // only close if left is double pressed
  632. if (code == MOUSE_LEFT)
  633. {
  634. // double click on the icon closes the window
  635. // But only if the menu contains a 'close' item
  636. vgui::Menu *pMenu = GetMenu();
  637. if ( pMenu && pMenu->FindChildByName("Close") )
  638. {
  639. PostMessage(GetVParent(), new KeyValues("CloseFrameButtonPressed"));
  640. }
  641. }
  642. }
  643. };
  644. } // namespace vgui
  645. //-----------------------------------------------------------------------------
  646. // Purpose: Constructor
  647. //-----------------------------------------------------------------------------
  648. Frame::Frame(Panel *parent, const char *panelName, bool showTaskbarIcon /*=true*/, bool bPopup /*=true*/ ) : EditablePanel(parent, panelName)
  649. {
  650. // frames start invisible, to avoid having window flicker in on taskbar
  651. SetVisible(false);
  652. if ( bPopup )
  653. {
  654. MakePopup(showTaskbarIcon);
  655. }
  656. m_hPreviousModal = 0;
  657. _title=0;
  658. _moveable=true;
  659. _sizeable=true;
  660. m_bHasFocus=false;
  661. _flashWindow=false;
  662. _drawTitleBar = true;
  663. m_bPreviouslyVisible = false;
  664. m_bFadingOut = false;
  665. m_bDisableFadeEffect = false;
  666. m_flTransitionEffectTime = 0.0f;
  667. m_flFocusTransitionEffectTime = 0.0f;
  668. m_bDeleteSelfOnClose = false;
  669. m_iClientInsetX = 5;
  670. m_iClientInsetY = 5;
  671. m_iClientInsetXOverridden = false;
  672. m_iTitleTextInsetX = 28;
  673. m_bClipToParent = false;
  674. m_bSmallCaption = false;
  675. m_bChainKeysToParent = false;
  676. m_bPrimed = false;
  677. m_hCustomTitleFont = INVALID_FONT;
  678. m_iTitleTextInsetXOverride = m_iTitleTextInsetYOverride = 0;
  679. SetTitle("#Frame_Untitled", parent ? false : true);
  680. // add ourselves to the build group
  681. SetBuildGroup(GetBuildGroup());
  682. SetMinimumSize(128,66);
  683. GetFocusNavGroup().SetFocusTopLevel(true);
  684. #if !defined( _GAMECONSOLE )
  685. _sysMenu = NULL;
  686. // add dragging grips
  687. _topGrip = new GripPanel(this, "frame_topGrip", 0, -1);
  688. _bottomGrip = new GripPanel(this, "frame_bottomGrip", 0, 1);
  689. _leftGrip = new GripPanel(this, "frame_leftGrip", -1, 0);
  690. _rightGrip = new GripPanel(this, "frame_rightGrip", 1, 0);
  691. _topLeftGrip = new GripPanel(this, "frame_tlGrip", -1, -1);
  692. _topRightGrip = new GripPanel(this, "frame_trGrip", 1, -1);
  693. _bottomLeftGrip = new GripPanel(this, "frame_blGrip", -1, 1);
  694. _bottomRightGrip = new GripPanel(this, "frame_brGrip", 1, 1);
  695. _captionGrip = new CaptionGripPanel(this, "frame_caption" );
  696. _captionGrip->SetCursor(dc_arrow);
  697. _minimizeButton = new FrameButton(this, "frame_minimize","0");
  698. _minimizeButton->AddActionSignalTarget(this);
  699. _minimizeButton->SetCommand(new KeyValues("Minimize"));
  700. _maximizeButton = new FrameButton(this, "frame_maximize", "1");
  701. //!! no maximize handler implemented yet, so leave maximize button disabled
  702. SetMaximizeButtonVisible(false);
  703. char str[] = { 0x6F, 0 };
  704. _minimizeToSysTrayButton = new FrameButton(this, "frame_mintosystray", str);
  705. _minimizeToSysTrayButton->SetCommand("MinimizeToSysTray");
  706. SetMinimizeToSysTrayButtonVisible(false);
  707. _closeButton = new FrameButton(this, "frame_close", "r");
  708. _closeButton->AddActionSignalTarget(this);
  709. _closeButton->SetCommand(new KeyValues("CloseFrameButtonPressed"));
  710. if (!surface()->SupportsFeature(ISurface::FRAME_MINIMIZE_MAXIMIZE))
  711. {
  712. SetMinimizeButtonVisible(false);
  713. SetMaximizeButtonVisible(false);
  714. }
  715. if (parent)
  716. {
  717. // vgui doesn't support subwindow minimization
  718. SetMinimizeButtonVisible(false);
  719. SetMaximizeButtonVisible(false);
  720. }
  721. _menuButton = new FrameSystemButton(this, "frame_menu");
  722. _menuButton->SetMenu(GetSysMenu());
  723. #endif
  724. SetupResizeCursors();
  725. REGISTER_COLOR_AS_OVERRIDABLE( m_InFocusBgColor, "infocus_bgcolor_override" );
  726. REGISTER_COLOR_AS_OVERRIDABLE( m_OutOfFocusBgColor, "outoffocus_bgcolor_override" );
  727. REGISTER_COLOR_AS_OVERRIDABLE( _titleBarBgColor, "titlebarbgcolor_override" );
  728. REGISTER_COLOR_AS_OVERRIDABLE( _titleBarDisabledBgColor, "titlebardisabledbgcolor_override" );
  729. REGISTER_COLOR_AS_OVERRIDABLE( _titleBarFgColor, "titlebarfgcolor_override" );
  730. REGISTER_COLOR_AS_OVERRIDABLE( _titleBarDisabledFgColor, "titlebardisabledfgcolor_override" );
  731. }
  732. //-----------------------------------------------------------------------------
  733. // Purpose: Destructor
  734. //-----------------------------------------------------------------------------
  735. Frame::~Frame()
  736. {
  737. if ( input()->GetAppModalSurface() == GetVPanel() )
  738. {
  739. vgui::input()->ReleaseAppModalSurface();
  740. if ( m_hPreviousModal != 0 )
  741. {
  742. vgui::input()->SetAppModalSurface( m_hPreviousModal );
  743. m_hPreviousModal = 0;
  744. }
  745. }
  746. // This is a textimage, so needs explicit deletion
  747. delete _title;
  748. }
  749. //-----------------------------------------------------------------------------
  750. // Purpose: Setup the grips on the edges of the panel to resize it.
  751. //-----------------------------------------------------------------------------
  752. void Frame::SetupResizeCursors()
  753. {
  754. #if !defined( _GAMECONSOLE )
  755. if (IsSizeable())
  756. {
  757. _topGrip->SetCursor(dc_sizens);
  758. _bottomGrip->SetCursor(dc_sizens);
  759. _leftGrip->SetCursor(dc_sizewe);
  760. _rightGrip->SetCursor(dc_sizewe);
  761. _topLeftGrip->SetCursor(dc_sizenwse);
  762. _topRightGrip->SetCursor(dc_sizenesw);
  763. _bottomLeftGrip->SetCursor(dc_sizenesw);
  764. _bottomRightGrip->SetCursor(dc_sizenwse);
  765. _bottomRightGrip->SetPaintEnabled(true);
  766. _bottomRightGrip->SetPaintBackgroundEnabled(true);
  767. }
  768. else
  769. {
  770. // not resizable, so just use the default cursor
  771. _topGrip->SetCursor(dc_arrow);
  772. _bottomGrip->SetCursor(dc_arrow);
  773. _leftGrip->SetCursor(dc_arrow);
  774. _rightGrip->SetCursor(dc_arrow);
  775. _topLeftGrip->SetCursor(dc_arrow);
  776. _topRightGrip->SetCursor(dc_arrow);
  777. _bottomLeftGrip->SetCursor(dc_arrow);
  778. _bottomRightGrip->SetCursor(dc_arrow);
  779. _bottomRightGrip->SetPaintEnabled(false);
  780. _bottomRightGrip->SetPaintBackgroundEnabled(false);
  781. }
  782. #endif
  783. }
  784. //-----------------------------------------------------------------------------
  785. // Purpose: Bring the frame to the front and requests focus, ensures it's not minimized
  786. //-----------------------------------------------------------------------------
  787. void Frame::Activate()
  788. {
  789. MoveToFront();
  790. if ( IsKeyBoardInputEnabled() )
  791. {
  792. RequestFocus();
  793. }
  794. SetVisible(true);
  795. SetEnabled(true);
  796. if (m_bFadingOut)
  797. {
  798. // we were fading out, make sure to fade back in
  799. m_bFadingOut = false;
  800. m_bPreviouslyVisible = false;
  801. }
  802. surface()->SetMinimized(GetVPanel(), false);
  803. }
  804. //-----------------------------------------------------------------------------
  805. // Sets up, cleans up modal dialogs
  806. //-----------------------------------------------------------------------------
  807. void Frame::DoModal( )
  808. {
  809. // move to the middle of the screen
  810. MoveToCenterOfScreen();
  811. InvalidateLayout();
  812. Activate();
  813. m_hPreviousModal = vgui::input()->GetAppModalSurface();
  814. vgui::input()->SetAppModalSurface( GetVPanel() );
  815. }
  816. //-----------------------------------------------------------------------------
  817. // Closes a modal dialog
  818. //-----------------------------------------------------------------------------
  819. void Frame::CloseModal()
  820. {
  821. vgui::input()->ReleaseAppModalSurface();
  822. if ( m_hPreviousModal != 0 )
  823. {
  824. vgui::input()->SetAppModalSurface( m_hPreviousModal );
  825. m_hPreviousModal = 0;
  826. }
  827. PostMessage( this, new KeyValues("Close") );
  828. }
  829. //-----------------------------------------------------------------------------
  830. // Purpose: activates the dialog
  831. // if dialog is not currently visible it starts it minimized and flashing in the taskbar
  832. //-----------------------------------------------------------------------------
  833. void Frame::ActivateMinimized()
  834. {
  835. if ( IsVisible() && !IsMinimized() || !surface()->SupportsFeature( ISurface::FRAME_MINIMIZE_MAXIMIZE ) )
  836. {
  837. Activate();
  838. }
  839. else
  840. {
  841. ipanel()->MoveToBack(GetVPanel());
  842. surface()->SetMinimized(GetVPanel(), true);
  843. SetVisible(true);
  844. SetEnabled(true);
  845. if (m_bFadingOut)
  846. {
  847. // we were fading out, make sure to fade back in
  848. m_bFadingOut = false;
  849. m_bPreviouslyVisible = false;
  850. }
  851. FlashWindow();
  852. }
  853. }
  854. //-----------------------------------------------------------------------------
  855. // Purpose: returns true if the dialog is currently minimized
  856. //-----------------------------------------------------------------------------
  857. bool Frame::IsMinimized()
  858. {
  859. return surface()->IsMinimized(GetVPanel());
  860. }
  861. //-----------------------------------------------------------------------------
  862. // Purpose: Center the dialog on the screen
  863. //-----------------------------------------------------------------------------
  864. void Frame::MoveToCenterOfScreen()
  865. {
  866. int wx, wy, ww, wt;
  867. surface()->GetWorkspaceBounds(wx, wy, ww, wt);
  868. SetPos((ww - GetWide()) / 2, (wt - GetTall()) / 2);
  869. }
  870. void Frame::LayoutProportional( FrameButton *bt )
  871. {
  872. float scale = 1.0;
  873. if( IsProportional() )
  874. {
  875. int screenW, screenH;
  876. surface()->GetScreenSize( screenW, screenH );
  877. int proW,proH;
  878. surface()->GetProportionalBase( proW, proH );
  879. scale = ( (float)( screenH ) / (float)( proH ) );
  880. }
  881. bt->SetSize( (int)( FrameButton::GetButtonSide( this ) * scale ), (int)( FrameButton::GetButtonSide( this ) * scale ) );
  882. bt->SetTextInset( (int)( ceil( 2 * scale ) ), (int) ( ceil(1 * scale ) ) );
  883. }
  884. //-----------------------------------------------------------------------------
  885. // Purpose: per-frame thinking, used for transition effects
  886. // only gets called if the Frame is visible
  887. //-----------------------------------------------------------------------------
  888. void Frame::OnThink()
  889. {
  890. BaseClass::OnThink();
  891. // check for transition effects
  892. if (IsVisible() && m_flTransitionEffectTime > 0 && ( !m_bDisableFadeEffect ))
  893. {
  894. if (m_bFadingOut)
  895. {
  896. // we're fading out, see if we're done so we can fully hide the window
  897. if (GetAlpha() < ( IsGameConsole() ? 64 : 1 ))
  898. {
  899. FinishClose();
  900. }
  901. }
  902. else if (!m_bPreviouslyVisible)
  903. {
  904. // need to fade-in
  905. m_bPreviouslyVisible = true;
  906. // fade in
  907. if (IsGameConsole())
  908. {
  909. SetAlpha(64);
  910. }
  911. else
  912. {
  913. SetAlpha(0);
  914. }
  915. GetAnimationController()->RunAnimationCommand(this, "alpha", 255.0f, 0.0f, m_flTransitionEffectTime, AnimationController::INTERPOLATOR_LINEAR);
  916. }
  917. }
  918. // check for focus changes
  919. bool hasFocus = false;
  920. if (input())
  921. {
  922. VPANEL focus = input()->GetFocus();
  923. if (focus && ipanel()->HasParent(focus, GetVPanel()))
  924. {
  925. if ( input()->GetAppModalSurface() == 0 ||
  926. input()->GetAppModalSurface() == GetVPanel() )
  927. {
  928. hasFocus = true;
  929. }
  930. }
  931. }
  932. if (hasFocus != m_bHasFocus)
  933. {
  934. // Because vgui focus is message based, and focus gets reset to NULL when a focused panel is deleted, we defer the flashing/transition
  935. // animation for an extra frame in case something is deleted, a message is sent, and then we become the focused panel again on the
  936. // next frame
  937. if ( !m_bPrimed )
  938. {
  939. m_bPrimed = true;
  940. return;
  941. }
  942. m_bPrimed = false;
  943. m_bHasFocus = hasFocus;
  944. OnFrameFocusChanged(m_bHasFocus);
  945. }
  946. else
  947. {
  948. m_bPrimed = false;
  949. }
  950. }
  951. //-----------------------------------------------------------------------------
  952. // Purpose: Called when the frame focus changes
  953. //-----------------------------------------------------------------------------
  954. void Frame::OnFrameFocusChanged(bool bHasFocus)
  955. {
  956. #if !defined( _GAMECONSOLE )
  957. // enable/disable the frame buttons
  958. _minimizeButton->SetDisabledLook(!bHasFocus);
  959. _maximizeButton->SetDisabledLook(!bHasFocus);
  960. _closeButton->SetDisabledLook(!bHasFocus);
  961. _minimizeToSysTrayButton->SetDisabledLook(!bHasFocus);
  962. _menuButton->SetEnabled(bHasFocus);
  963. _minimizeButton->InvalidateLayout();
  964. _maximizeButton->InvalidateLayout();
  965. _minimizeToSysTrayButton->InvalidateLayout();
  966. _closeButton->InvalidateLayout();
  967. _menuButton->InvalidateLayout();
  968. #endif
  969. if (bHasFocus)
  970. {
  971. _title->SetColor(_titleBarFgColor);
  972. }
  973. else
  974. {
  975. _title->SetColor(_titleBarDisabledFgColor);
  976. }
  977. // set our background color
  978. if (bHasFocus)
  979. {
  980. if (m_flFocusTransitionEffectTime && ( !m_bDisableFadeEffect ))
  981. {
  982. GetAnimationController()->RunAnimationCommand(this, "BgColor", m_InFocusBgColor, 0.0f, m_bDisableFadeEffect ? 0.0f : m_flTransitionEffectTime, AnimationController::INTERPOLATOR_LINEAR);
  983. }
  984. else
  985. {
  986. SetBgColor(m_InFocusBgColor);
  987. }
  988. }
  989. else
  990. {
  991. if (m_flFocusTransitionEffectTime && ( !m_bDisableFadeEffect ))
  992. {
  993. GetAnimationController()->RunAnimationCommand(this, "BgColor", m_OutOfFocusBgColor, 0.0f, m_bDisableFadeEffect ? 0.0f : m_flTransitionEffectTime, AnimationController::INTERPOLATOR_LINEAR);
  994. }
  995. else
  996. {
  997. SetBgColor(m_OutOfFocusBgColor);
  998. }
  999. }
  1000. // Stop flashing when we get focus
  1001. if (bHasFocus && _flashWindow)
  1002. {
  1003. FlashWindowStop();
  1004. }
  1005. }
  1006. int Frame::GetDraggerSize()
  1007. {
  1008. const int DRAGGER_SIZE = 5;
  1009. if ( m_bSmallCaption )
  1010. {
  1011. return 3;
  1012. }
  1013. return DRAGGER_SIZE;
  1014. }
  1015. int Frame::GetCornerSize()
  1016. {
  1017. const int CORNER_SIZE = 8;
  1018. if ( m_bSmallCaption )
  1019. {
  1020. return 6;
  1021. }
  1022. return CORNER_SIZE;
  1023. }
  1024. int Frame::GetBottomRightSize()
  1025. {
  1026. const int BOTTOMRIGHTSIZE = 18;
  1027. if ( m_bSmallCaption )
  1028. {
  1029. return 12;
  1030. }
  1031. return BOTTOMRIGHTSIZE;
  1032. }
  1033. int Frame::GetCaptionHeight()
  1034. {
  1035. const int CAPTIONHEIGHT = 23;
  1036. if ( m_bSmallCaption )
  1037. {
  1038. return 12;
  1039. }
  1040. return CAPTIONHEIGHT;
  1041. }
  1042. //-----------------------------------------------------------------------------
  1043. // Purpose: Recalculate the position of all items
  1044. //-----------------------------------------------------------------------------
  1045. void Frame::PerformLayout()
  1046. {
  1047. // chain back
  1048. BaseClass::PerformLayout();
  1049. // move everything into place
  1050. int wide, tall;
  1051. GetSize(wide, tall);
  1052. #if !defined( _GAMECONSOLE )
  1053. int DRAGGER_SIZE = GetDraggerSize();
  1054. int CORNER_SIZE = GetCornerSize();
  1055. int CORNER_SIZE2 = CORNER_SIZE * 2;
  1056. int BOTTOMRIGHTSIZE = GetBottomRightSize();
  1057. _topGrip->SetBounds(CORNER_SIZE, 0, wide - CORNER_SIZE2, DRAGGER_SIZE);
  1058. _leftGrip->SetBounds(0, CORNER_SIZE, DRAGGER_SIZE, tall - CORNER_SIZE2);
  1059. _topLeftGrip->SetBounds(0, 0, CORNER_SIZE, CORNER_SIZE);
  1060. _topRightGrip->SetBounds(wide - CORNER_SIZE, 0, CORNER_SIZE, CORNER_SIZE);
  1061. _bottomLeftGrip->SetBounds(0, tall - CORNER_SIZE, CORNER_SIZE, CORNER_SIZE);
  1062. // make the bottom-right grip larger
  1063. _bottomGrip->SetBounds(CORNER_SIZE, tall - DRAGGER_SIZE, wide - (CORNER_SIZE + BOTTOMRIGHTSIZE), DRAGGER_SIZE);
  1064. _rightGrip->SetBounds(wide - DRAGGER_SIZE, CORNER_SIZE, DRAGGER_SIZE, tall - (CORNER_SIZE + BOTTOMRIGHTSIZE));
  1065. _bottomRightGrip->SetBounds(wide - BOTTOMRIGHTSIZE, tall - BOTTOMRIGHTSIZE, BOTTOMRIGHTSIZE, BOTTOMRIGHTSIZE);
  1066. _captionGrip->SetSize(wide-10,GetCaptionHeight());
  1067. // Put the caption behind all of the grips, other buttons
  1068. _captionGrip->SetZPos( -1 );
  1069. _topGrip->MoveToFront();
  1070. _bottomGrip->MoveToFront();
  1071. _leftGrip->MoveToFront();
  1072. _rightGrip->MoveToFront();
  1073. _topLeftGrip->MoveToFront();
  1074. _topRightGrip->MoveToFront();
  1075. _bottomLeftGrip->MoveToFront();
  1076. _bottomRightGrip->MoveToFront();
  1077. _maximizeButton->MoveToFront();
  1078. _menuButton->MoveToFront();
  1079. _minimizeButton->MoveToFront();
  1080. _minimizeToSysTrayButton->MoveToFront();
  1081. _menuButton->SetBounds(5+2, 5+3, GetCaptionHeight()-5, GetCaptionHeight()-5);
  1082. #endif
  1083. float scale = 1;
  1084. if (IsProportional())
  1085. {
  1086. int screenW, screenH;
  1087. surface()->GetScreenSize( screenW, screenH );
  1088. int proW,proH;
  1089. surface()->GetProportionalBase( proW, proH );
  1090. scale = ( (float)( screenH ) / (float)( proH ) );
  1091. }
  1092. #if !defined( _GAMECONSOLE )
  1093. int offset_start = (int)( 20 * scale );
  1094. int offset = offset_start;
  1095. int top_border_offset = (int) ( ( 5+3 ) * scale );
  1096. if ( m_bSmallCaption )
  1097. {
  1098. top_border_offset = (int) ( ( 3 ) * scale );
  1099. }
  1100. int side_border_offset = (int) ( 5 * scale );
  1101. // push the buttons against the east side
  1102. if (_closeButton->IsVisible())
  1103. {
  1104. _closeButton->SetPos((wide-side_border_offset)-offset,top_border_offset);
  1105. offset += offset_start;
  1106. LayoutProportional( _closeButton );
  1107. _closeButton->SetZPos( 1 );
  1108. }
  1109. if (_minimizeToSysTrayButton->IsVisible())
  1110. {
  1111. _minimizeToSysTrayButton->SetPos((wide-side_border_offset)-offset,top_border_offset);
  1112. offset += offset_start;
  1113. LayoutProportional( _minimizeToSysTrayButton );
  1114. }
  1115. if (_maximizeButton->IsVisible())
  1116. {
  1117. _maximizeButton->SetPos((wide-side_border_offset)-offset,top_border_offset);
  1118. offset += offset_start;
  1119. LayoutProportional( _maximizeButton );
  1120. }
  1121. if (_minimizeButton->IsVisible())
  1122. {
  1123. _minimizeButton->SetPos((wide-side_border_offset)-offset,top_border_offset);
  1124. offset += offset_start;
  1125. LayoutProportional( _minimizeButton );
  1126. }
  1127. #endif
  1128. }
  1129. //-----------------------------------------------------------------------------
  1130. // Purpose: Set the text in the title bar.
  1131. //-----------------------------------------------------------------------------
  1132. void Frame::SetTitle(const char *title, bool surfaceTitle)
  1133. {
  1134. if (!_title)
  1135. {
  1136. _title = new TextImage( "" );
  1137. }
  1138. Assert(title);
  1139. _title->SetText(title);
  1140. // see if the combobox text has changed, and if so, post a message detailing the new text
  1141. const char *newTitle = title;
  1142. // check if the new text is a localized string, if so undo it
  1143. wchar_t unicodeText[128];
  1144. unicodeText[0] = 0;
  1145. if (*newTitle == '#')
  1146. {
  1147. // try lookup in localization tables
  1148. StringIndex_t unlocalizedTextSymbol = g_pVGuiLocalize->FindIndex(newTitle + 1);
  1149. if (unlocalizedTextSymbol != INVALID_STRING_INDEX)
  1150. {
  1151. // we have a new text value
  1152. wcsncpy( unicodeText, g_pVGuiLocalize->GetValueByIndex(unlocalizedTextSymbol), sizeof( unicodeText) / sizeof(wchar_t) );
  1153. }
  1154. }
  1155. else
  1156. {
  1157. g_pVGuiLocalize->ConvertANSIToUnicode( newTitle, unicodeText, sizeof(unicodeText) );
  1158. }
  1159. if (surfaceTitle)
  1160. {
  1161. surface()->SetTitle(GetVPanel(), unicodeText);
  1162. }
  1163. Repaint();
  1164. }
  1165. //-----------------------------------------------------------------------------
  1166. // Purpose: Sets the unicode text in the title bar
  1167. //-----------------------------------------------------------------------------
  1168. void Frame::SetTitle(const wchar_t *title, bool surfaceTitle)
  1169. {
  1170. if (!_title)
  1171. {
  1172. _title = new TextImage( "" );
  1173. }
  1174. _title->SetText(title);
  1175. if (surfaceTitle)
  1176. {
  1177. surface()->SetTitle(GetVPanel(), title);
  1178. }
  1179. Repaint();
  1180. }
  1181. //-----------------------------------------------------------------------------
  1182. // Purpose: Set the text in the title bar.
  1183. //-----------------------------------------------------------------------------
  1184. void Frame::InternalSetTitle(const char *title)
  1185. {
  1186. SetTitle(title, true);
  1187. }
  1188. //-----------------------------------------------------------------------------
  1189. // Purpose: Set the movability of the panel
  1190. //-----------------------------------------------------------------------------
  1191. void Frame::SetMoveable(bool state)
  1192. {
  1193. _moveable=state;
  1194. }
  1195. //-----------------------------------------------------------------------------
  1196. // Purpose: Set the resizability of the panel
  1197. //-----------------------------------------------------------------------------
  1198. void Frame::SetSizeable(bool state)
  1199. {
  1200. _sizeable=state;
  1201. SetupResizeCursors();
  1202. }
  1203. // When moving via caption, don't let any part of window go outside parent's bounds
  1204. void Frame::SetClipToParent( bool state )
  1205. {
  1206. m_bClipToParent = state;
  1207. }
  1208. bool Frame::GetClipToParent() const
  1209. {
  1210. return m_bClipToParent;
  1211. }
  1212. //-----------------------------------------------------------------------------
  1213. // Purpose: Check the movability of the panel
  1214. //-----------------------------------------------------------------------------
  1215. bool Frame::IsMoveable()
  1216. {
  1217. return _moveable;
  1218. }
  1219. //-----------------------------------------------------------------------------
  1220. // Purpose: Check the resizability of the panel
  1221. //-----------------------------------------------------------------------------
  1222. bool Frame::IsSizeable()
  1223. {
  1224. return _sizeable;
  1225. }
  1226. void Frame::GetSizerClientArea(int &x, int &y, int &wide, int &tall)
  1227. {
  1228. GetClientArea(x,y,wide,tall);
  1229. }
  1230. //-----------------------------------------------------------------------------
  1231. // Purpose: Get the size of the panel inside the frame edges.
  1232. //-----------------------------------------------------------------------------
  1233. void Frame::GetClientArea(int &x, int &y, int &wide, int &tall)
  1234. {
  1235. x = m_iClientInsetX;
  1236. y = 0;
  1237. GetSize(wide, tall);
  1238. if (_drawTitleBar)
  1239. {
  1240. int captionTall = surface()->GetFontTall(_title->GetFont());
  1241. int border = m_bSmallCaption ? CAPTION_TITLE_BORDER_SMALL : CAPTION_TITLE_BORDER;
  1242. int yinset = m_bSmallCaption ? 0 : m_iClientInsetY;
  1243. yinset += m_iTitleTextInsetYOverride;
  1244. y = yinset + captionTall + border + 1;
  1245. tall = (tall - yinset) - y;
  1246. }
  1247. if ( m_bSmallCaption )
  1248. {
  1249. tall -= 5;
  1250. }
  1251. wide = (wide - m_iClientInsetX) - x;
  1252. }
  1253. //
  1254. //-----------------------------------------------------------------------------
  1255. // Purpose: applies user configuration settings
  1256. //-----------------------------------------------------------------------------
  1257. void Frame::ApplyUserConfigSettings(KeyValues *userConfig)
  1258. {
  1259. // calculate defaults
  1260. int wx, wy, ww, wt;
  1261. vgui::surface()->GetWorkspaceBounds(wx, wy, ww, wt);
  1262. int x, y, wide, tall;
  1263. GetBounds(x, y, wide, tall);
  1264. bool bNoSettings = false;
  1265. if (_moveable)
  1266. {
  1267. // check to see if anything is set
  1268. if (!userConfig->FindKey("xpos", false))
  1269. {
  1270. bNoSettings = true;
  1271. }
  1272. // get the user config position
  1273. // default to where we're currently at
  1274. x = userConfig->GetInt("xpos", x);
  1275. y = userConfig->GetInt("ypos", y);
  1276. }
  1277. if (_sizeable)
  1278. {
  1279. wide = userConfig->GetInt("wide", wide);
  1280. tall = userConfig->GetInt("tall", tall);
  1281. // Make sure it's no larger than the workspace
  1282. if ( wide > ww )
  1283. {
  1284. wide = ww;
  1285. }
  1286. if ( tall > wt )
  1287. {
  1288. tall = wt;
  1289. }
  1290. }
  1291. // see if the dialog has a place on the screen it wants to start
  1292. if (bNoSettings && GetDefaultScreenPosition(x, y, wide, tall))
  1293. {
  1294. bNoSettings = false;
  1295. }
  1296. // make sure it conforms to the minimum size of the dialog
  1297. int minWide, minTall;
  1298. GetMinimumSize(minWide, minTall);
  1299. if (wide < minWide)
  1300. {
  1301. wide = minWide;
  1302. }
  1303. if (tall < minTall)
  1304. {
  1305. tall = minTall;
  1306. }
  1307. // make sure it's on the screen
  1308. if (x + wide > ww)
  1309. {
  1310. x = wx + ww - wide;
  1311. }
  1312. if (y + tall > wt)
  1313. {
  1314. y = wy + wt - tall;
  1315. }
  1316. if (x < wx)
  1317. {
  1318. x = wx;
  1319. }
  1320. if (y < wy)
  1321. {
  1322. y = wy;
  1323. }
  1324. SetBounds(x, y, wide, tall);
  1325. if (bNoSettings)
  1326. {
  1327. // since nothing was set, default our position to the middle of the screen
  1328. MoveToCenterOfScreen();
  1329. }
  1330. BaseClass::ApplyUserConfigSettings(userConfig);
  1331. }
  1332. //-----------------------------------------------------------------------------
  1333. // Purpose: returns user config settings for this control
  1334. //-----------------------------------------------------------------------------
  1335. void Frame::GetUserConfigSettings(KeyValues *userConfig)
  1336. {
  1337. if (_moveable)
  1338. {
  1339. int x, y;
  1340. GetPos(x, y);
  1341. userConfig->SetInt("xpos", x);
  1342. userConfig->SetInt("ypos", y);
  1343. }
  1344. if (_sizeable)
  1345. {
  1346. int w, t;
  1347. GetSize(w, t);
  1348. userConfig->SetInt("wide", w);
  1349. userConfig->SetInt("tall", t);
  1350. }
  1351. BaseClass::GetUserConfigSettings(userConfig);
  1352. }
  1353. //-----------------------------------------------------------------------------
  1354. // Purpose: optimization, return true if this control has any user config settings
  1355. //-----------------------------------------------------------------------------
  1356. bool Frame::HasUserConfigSettings()
  1357. {
  1358. return true;
  1359. }
  1360. //-----------------------------------------------------------------------------
  1361. // Purpose: gets the default position and size on the screen to appear the first time (defaults to centered)
  1362. //-----------------------------------------------------------------------------
  1363. bool Frame::GetDefaultScreenPosition(int &x, int &y, int &wide, int &tall)
  1364. {
  1365. return false;
  1366. }
  1367. //-----------------------------------------------------------------------------
  1368. // Purpose: draws title bar
  1369. //-----------------------------------------------------------------------------
  1370. void Frame::PaintBackground()
  1371. {
  1372. // take the panel with focus and check up tree for this panel
  1373. // if you find it, than some child of you has the focus, so
  1374. // you should be focused
  1375. Color titleColor = _titleBarDisabledBgColor;
  1376. if (m_bHasFocus)
  1377. {
  1378. titleColor = _titleBarBgColor;
  1379. }
  1380. BaseClass::PaintBackground();
  1381. if (_drawTitleBar)
  1382. {
  1383. int wide = GetWide();
  1384. int tall = surface()->GetFontTall(_title->GetFont());
  1385. // caption
  1386. surface()->DrawSetColor(titleColor);
  1387. int inset = m_bSmallCaption ? 3 : 5;
  1388. int captionHeight = m_bSmallCaption ? 14: 28;
  1389. surface()->DrawFilledRect(inset, inset, wide - inset, captionHeight );
  1390. if (_title)
  1391. {
  1392. int nTitleX = m_iTitleTextInsetXOverride ? m_iTitleTextInsetXOverride : m_iTitleTextInsetX;
  1393. int nTitleWidth = wide - 72;
  1394. #if !defined( _GAMECONSOLE )
  1395. if ( _menuButton && _menuButton->IsVisible() )
  1396. {
  1397. int mw, mh;
  1398. _menuButton->GetImageSize( mw, mh );
  1399. nTitleX += mw;
  1400. nTitleWidth -= mw;
  1401. }
  1402. #endif
  1403. int nTitleY;
  1404. if ( m_iTitleTextInsetYOverride )
  1405. {
  1406. nTitleY = m_iTitleTextInsetYOverride;
  1407. }
  1408. else
  1409. {
  1410. nTitleY = m_bSmallCaption ? 2 : 9;
  1411. }
  1412. _title->SetPos( nTitleX, nTitleY );
  1413. _title->SetSize( nTitleWidth, tall);
  1414. _title->Paint();
  1415. }
  1416. }
  1417. }
  1418. //-----------------------------------------------------------------------------
  1419. // Purpose:
  1420. //-----------------------------------------------------------------------------
  1421. void Frame::ApplySchemeSettings(IScheme *pScheme)
  1422. {
  1423. // always chain back
  1424. BaseClass::ApplySchemeSettings(pScheme);
  1425. SetOverridableColor( &_titleBarFgColor, GetSchemeColor("FrameTitleBar.TextColor", pScheme) );
  1426. SetOverridableColor( &_titleBarBgColor, GetSchemeColor("FrameTitleBar.BgColor", pScheme) );
  1427. SetOverridableColor( &_titleBarDisabledFgColor, GetSchemeColor("FrameTitleBar.DisabledTextColor", pScheme) );
  1428. SetOverridableColor( &_titleBarDisabledBgColor, GetSchemeColor("FrameTitleBar.DisabledBgColor", pScheme) );
  1429. const char *font = NULL;
  1430. if ( m_bSmallCaption )
  1431. {
  1432. font = pScheme->GetResourceString("FrameTitleBar.SmallFont");
  1433. }
  1434. else
  1435. {
  1436. font = pScheme->GetResourceString("FrameTitleBar.Font");
  1437. }
  1438. HFont titlefont;
  1439. if ( m_hCustomTitleFont )
  1440. {
  1441. titlefont = m_hCustomTitleFont;
  1442. }
  1443. else
  1444. {
  1445. titlefont = pScheme->GetFont((font && *font) ? font : "Default", IsProportional());
  1446. }
  1447. _title->SetFont( titlefont );
  1448. _title->ResizeImageToContent();
  1449. #if !defined( _GAMECONSOLE )
  1450. HFont marfont = (HFont)0;
  1451. if ( m_bSmallCaption )
  1452. {
  1453. marfont = pScheme->GetFont( "MarlettSmall", IsProportional() );
  1454. }
  1455. else
  1456. {
  1457. marfont = pScheme->GetFont( "Marlett", IsProportional() );
  1458. }
  1459. _minimizeButton->SetFont(marfont);
  1460. _maximizeButton->SetFont(marfont);
  1461. _minimizeToSysTrayButton->SetFont(marfont);
  1462. _closeButton->SetFont(marfont);
  1463. #endif
  1464. m_flTransitionEffectTime = atof(pScheme->GetResourceString("Frame.TransitionEffectTime"));
  1465. m_flFocusTransitionEffectTime = atof(pScheme->GetResourceString("Frame.FocusTransitionEffectTime"));
  1466. SetOverridableColor( &m_InFocusBgColor, pScheme->GetColor("Frame.BgColor", GetBgColor()) );
  1467. SetOverridableColor( &m_OutOfFocusBgColor, pScheme->GetColor("Frame.OutOfFocusBgColor", m_InFocusBgColor) );
  1468. const char *resourceString = pScheme->GetResourceString("Frame.ClientInsetX");
  1469. if ( resourceString )
  1470. {
  1471. m_iClientInsetX = atoi(resourceString);
  1472. }
  1473. resourceString = pScheme->GetResourceString("Frame.ClientInsetY");
  1474. if ( resourceString )
  1475. {
  1476. m_iClientInsetY = atoi(resourceString);
  1477. }
  1478. resourceString = pScheme->GetResourceString("Frame.TitleTextInsetX");
  1479. if ( resourceString )
  1480. {
  1481. m_iTitleTextInsetX = atoi(resourceString);
  1482. }
  1483. SetBgColor(m_InFocusBgColor);
  1484. SetBorder(pScheme->GetBorder("FrameBorder"));
  1485. OnFrameFocusChanged( m_bHasFocus );
  1486. }
  1487. // Disables the fade-in/out-effect even if configured in the scheme settings
  1488. void Frame::DisableFadeEffect( void )
  1489. {
  1490. m_flFocusTransitionEffectTime = 0.f;
  1491. m_flTransitionEffectTime = 0.f;
  1492. }
  1493. void Frame::SetFadeEffectDisableOverride( bool disabled )
  1494. {
  1495. m_bDisableFadeEffect = disabled;
  1496. }
  1497. //-----------------------------------------------------------------------------
  1498. // Purpose: Apply settings loaded from a resource file
  1499. //-----------------------------------------------------------------------------
  1500. void Frame::ApplySettings(KeyValues *inResourceData)
  1501. {
  1502. // Don't change the frame's visibility, remove that setting from the config data
  1503. inResourceData->SetInt("visible", -1);
  1504. BaseClass::ApplySettings(inResourceData);
  1505. if( !inResourceData->GetInt("settitlebarvisible", 1 ) ) // if "title" is "0" then don't draw the title bar
  1506. {
  1507. SetTitleBarVisible( false );
  1508. }
  1509. // set the title
  1510. const char *title = inResourceData->GetString("title", "");
  1511. if (title && *title)
  1512. {
  1513. SetTitle(title, true);
  1514. }
  1515. const char *titlefont = inResourceData->GetString("title_font", "");
  1516. if ( titlefont && titlefont[0] )
  1517. {
  1518. IScheme *pScheme = scheme()->GetIScheme( GetScheme() );
  1519. if ( pScheme )
  1520. {
  1521. m_hCustomTitleFont = pScheme->GetFont( titlefont );
  1522. }
  1523. }
  1524. KeyValues *pKV = inResourceData->FindKey( "clientinsetx_override", false );
  1525. if ( pKV )
  1526. {
  1527. m_iClientInsetX = pKV->GetInt();
  1528. m_iClientInsetXOverridden = true;
  1529. }
  1530. }
  1531. //-----------------------------------------------------------------------------
  1532. // Purpose: Apply settings loaded from a resource file
  1533. //-----------------------------------------------------------------------------
  1534. void Frame::GetSettings(KeyValues *outResourceData)
  1535. {
  1536. BaseClass::GetSettings(outResourceData);
  1537. outResourceData->SetInt("settitlebarvisible", _drawTitleBar );
  1538. if (_title)
  1539. {
  1540. char buf[256];
  1541. _title->GetUnlocalizedText( buf, 255 );
  1542. if (buf[0])
  1543. {
  1544. outResourceData->SetString("title", buf);
  1545. }
  1546. }
  1547. if ( m_iClientInsetXOverridden )
  1548. {
  1549. outResourceData->SetInt( "clientinsetx_override", m_iClientInsetX );
  1550. }
  1551. }
  1552. //-----------------------------------------------------------------------------
  1553. // Purpose: returns a description of the settings possible for a frame
  1554. //-----------------------------------------------------------------------------
  1555. const char *Frame::GetDescription()
  1556. {
  1557. static char buf[512];
  1558. Q_snprintf(buf, sizeof(buf), "%s, string title", BaseClass::GetDescription());
  1559. return buf;
  1560. }
  1561. //-----------------------------------------------------------------------------
  1562. // Purpose: Go invisible when a close message is recieved.
  1563. //-----------------------------------------------------------------------------
  1564. void Frame::OnClose()
  1565. {
  1566. // if we're modal, release that before we hide the window else the wrong window will get focus
  1567. if (input()->GetAppModalSurface() == GetVPanel())
  1568. {
  1569. input()->ReleaseAppModalSurface();
  1570. if ( m_hPreviousModal != 0 )
  1571. {
  1572. vgui::input()->SetAppModalSurface( m_hPreviousModal );
  1573. m_hPreviousModal = 0;
  1574. }
  1575. }
  1576. BaseClass::OnClose();
  1577. if (m_flTransitionEffectTime && !m_bDisableFadeEffect)
  1578. {
  1579. // begin the hide transition effect
  1580. GetAnimationController()->RunAnimationCommand(this, "alpha", 0.0f, 0.0f, m_flTransitionEffectTime, AnimationController::INTERPOLATOR_LINEAR);
  1581. m_bFadingOut = true;
  1582. // move us to the back of the draw order (so that fading out over the top of other dialogs doesn't look wierd)
  1583. surface()->MovePopupToBack(GetVPanel());
  1584. }
  1585. else
  1586. {
  1587. // hide us immediately
  1588. FinishClose();
  1589. }
  1590. }
  1591. //-----------------------------------------------------------------------------
  1592. // Purpose: Close button in frame pressed
  1593. //-----------------------------------------------------------------------------
  1594. void Frame::OnCloseFrameButtonPressed()
  1595. {
  1596. OnCommand("Close");
  1597. }
  1598. //-----------------------------------------------------------------------------
  1599. // Purpose: Command handling
  1600. //-----------------------------------------------------------------------------
  1601. void Frame::OnCommand(const char *command)
  1602. {
  1603. if (!stricmp(command, "Close"))
  1604. {
  1605. Close();
  1606. }
  1607. else if (!stricmp(command, "CloseModal"))
  1608. {
  1609. CloseModal();
  1610. }
  1611. else if (!stricmp(command, "Minimize"))
  1612. {
  1613. OnMinimize();
  1614. }
  1615. else if (!stricmp(command, "MinimizeToSysTray"))
  1616. {
  1617. OnMinimizeToSysTray();
  1618. }
  1619. else
  1620. {
  1621. BaseClass::OnCommand(command);
  1622. }
  1623. }
  1624. //-----------------------------------------------------------------------------
  1625. // Purpose: Get the system menu
  1626. //-----------------------------------------------------------------------------
  1627. Menu *Frame::GetSysMenu()
  1628. {
  1629. #if !defined( _GAMECONSOLE )
  1630. if (!_sysMenu)
  1631. {
  1632. _sysMenu = new Menu(this, NULL);
  1633. _sysMenu->SetVisible(false);
  1634. _sysMenu->AddActionSignalTarget(this);
  1635. _sysMenu->AddMenuItem("Minimize", "#SysMenu_Minimize", "Minimize", this);
  1636. _sysMenu->AddMenuItem("Maximize", "#SysMenu_Maximize", "Maximize", this);
  1637. _sysMenu->AddMenuItem("Close", "#SysMenu_Close", "Close", this);
  1638. // check for enabling/disabling menu items
  1639. // this might have to be done at other times as well.
  1640. Panel *menuItem = _sysMenu->FindChildByName("Minimize");
  1641. if (menuItem)
  1642. {
  1643. menuItem->SetEnabled(_minimizeButton->IsVisible());
  1644. }
  1645. menuItem = _sysMenu->FindChildByName("Maximize");
  1646. if (menuItem)
  1647. {
  1648. menuItem->SetEnabled(_maximizeButton->IsVisible());
  1649. }
  1650. menuItem = _sysMenu->FindChildByName("Close");
  1651. if (menuItem)
  1652. {
  1653. menuItem->SetEnabled(_closeButton->IsVisible());
  1654. }
  1655. }
  1656. return _sysMenu;
  1657. #else
  1658. return NULL;
  1659. #endif
  1660. }
  1661. //-----------------------------------------------------------------------------
  1662. // Purpose: Set the system menu
  1663. //-----------------------------------------------------------------------------
  1664. void Frame::SetSysMenu(Menu *menu)
  1665. {
  1666. #if !defined( _GAMECONSOLE )
  1667. if (menu == _sysMenu)
  1668. return;
  1669. _sysMenu->MarkForDeletion();
  1670. _sysMenu = menu;
  1671. _menuButton->SetMenu(_sysMenu);
  1672. #endif
  1673. }
  1674. //-----------------------------------------------------------------------------
  1675. // Set the system menu images
  1676. //-----------------------------------------------------------------------------
  1677. void Frame::SetImages( const char *pEnabledImage, const char *pDisabledImage )
  1678. {
  1679. #if !defined( _GAMECONSOLE )
  1680. _menuButton->SetImages( pEnabledImage, pDisabledImage );
  1681. #endif
  1682. }
  1683. //-----------------------------------------------------------------------------
  1684. // Purpose: Close the window
  1685. //-----------------------------------------------------------------------------
  1686. void Frame::Close()
  1687. {
  1688. OnClose();
  1689. }
  1690. //-----------------------------------------------------------------------------
  1691. // Purpose: Finishes closing the dialog
  1692. //-----------------------------------------------------------------------------
  1693. void Frame::FinishClose()
  1694. {
  1695. SetVisible(false);
  1696. m_bPreviouslyVisible = false;
  1697. m_bFadingOut = false;
  1698. OnFinishedClose();
  1699. if (m_bDeleteSelfOnClose)
  1700. {
  1701. // Must be last because if vgui is not running then this will call delete this!!!
  1702. MarkForDeletion();
  1703. }
  1704. }
  1705. //-----------------------------------------------------------------------------
  1706. // Purpose:
  1707. //-----------------------------------------------------------------------------
  1708. void Frame::OnFinishedClose()
  1709. {
  1710. }
  1711. //-----------------------------------------------------------------------------
  1712. // Purpose: Minimize the window on the taskbar.
  1713. //-----------------------------------------------------------------------------
  1714. void Frame::OnMinimize()
  1715. {
  1716. surface()->SetMinimized(GetVPanel(), true);
  1717. }
  1718. //-----------------------------------------------------------------------------
  1719. // Purpose: Does nothing by default
  1720. //-----------------------------------------------------------------------------
  1721. void Frame::OnMinimizeToSysTray()
  1722. {
  1723. }
  1724. //-----------------------------------------------------------------------------
  1725. // Purpose: Respond to mouse presses
  1726. //-----------------------------------------------------------------------------
  1727. void Frame::OnMousePressed(MouseCode code)
  1728. {
  1729. if (!IsBuildGroupEnabled())
  1730. {
  1731. // if a child doesn't have focus, get it for ourselves
  1732. VPANEL focus = input()->GetFocus();
  1733. if (!focus || !ipanel()->HasParent(focus, GetVPanel()))
  1734. {
  1735. RequestFocus();
  1736. }
  1737. }
  1738. BaseClass::OnMousePressed(code);
  1739. }
  1740. //-----------------------------------------------------------------------------
  1741. // Purpose: Toggle visibility of the system menu button
  1742. //-----------------------------------------------------------------------------
  1743. void Frame::SetMenuButtonVisible(bool state)
  1744. {
  1745. #if !defined( _GAMECONSOLE )
  1746. _menuButton->SetVisible(state);
  1747. #endif
  1748. }
  1749. //-----------------------------------------------------------------------------
  1750. // Purpose: Toggle respond of the system menu button
  1751. // it will look enabled or disabled in response to the title bar
  1752. // but may not activate.
  1753. //-----------------------------------------------------------------------------
  1754. void Frame::SetMenuButtonResponsive(bool state)
  1755. {
  1756. #if !defined( _GAMECONSOLE )
  1757. _menuButton->SetResponsive(state);
  1758. #endif
  1759. }
  1760. //-----------------------------------------------------------------------------
  1761. // Purpose: Toggle visibility of the minimize button
  1762. //-----------------------------------------------------------------------------
  1763. void Frame::SetMinimizeButtonVisible(bool state)
  1764. {
  1765. #if !defined( _GAMECONSOLE )
  1766. _minimizeButton->SetVisible(state);
  1767. #endif
  1768. }
  1769. //-----------------------------------------------------------------------------
  1770. // Purpose: Toggle visibility of the maximize button
  1771. //-----------------------------------------------------------------------------
  1772. void Frame::SetMaximizeButtonVisible(bool state)
  1773. {
  1774. #if !defined( _GAMECONSOLE )
  1775. _maximizeButton->SetVisible(state);
  1776. #endif
  1777. }
  1778. //-----------------------------------------------------------------------------
  1779. // Purpose: Toggles visibility of the minimize-to-systray icon (defaults to false)
  1780. //-----------------------------------------------------------------------------
  1781. void Frame::SetMinimizeToSysTrayButtonVisible(bool state)
  1782. {
  1783. #if !defined( _GAMECONSOLE )
  1784. _minimizeToSysTrayButton->SetVisible(state);
  1785. #endif
  1786. }
  1787. //-----------------------------------------------------------------------------
  1788. // Purpose: Toggle visibility of the close button
  1789. //-----------------------------------------------------------------------------
  1790. void Frame::SetCloseButtonVisible(bool state)
  1791. {
  1792. #if !defined( _GAMECONSOLE )
  1793. _closeButton->SetVisible(state);
  1794. #endif
  1795. }
  1796. //-----------------------------------------------------------------------------
  1797. // Purpose: soaks up any remaining messages
  1798. //-----------------------------------------------------------------------------
  1799. void Frame::OnKeyCodeReleased(KeyCode code)
  1800. {
  1801. }
  1802. //-----------------------------------------------------------------------------
  1803. // Purpose: soaks up any remaining messages
  1804. //-----------------------------------------------------------------------------
  1805. void Frame::OnKeyFocusTicked()
  1806. {
  1807. }
  1808. //-----------------------------------------------------------------------------
  1809. // Purpose: Toggles window flash state on a timer
  1810. //-----------------------------------------------------------------------------
  1811. void Frame::InternalFlashWindow()
  1812. {
  1813. if (_flashWindow)
  1814. {
  1815. // toggle icon flashing
  1816. _nextFlashState = true;
  1817. surface()->FlashWindow(GetVPanel(), _nextFlashState);
  1818. _nextFlashState = !_nextFlashState;
  1819. PostMessage(this, new KeyValues("FlashWindow"), 1.8f);
  1820. }
  1821. }
  1822. //-----------------------------------------------------------------------------
  1823. // Purpose: Adds the child to the focus nav group
  1824. //-----------------------------------------------------------------------------
  1825. void Frame::OnChildAdded(VPANEL child)
  1826. {
  1827. BaseClass::OnChildAdded(child);
  1828. }
  1829. //-----------------------------------------------------------------------------
  1830. // Purpose: Flash the window system tray button until the frame gets focus
  1831. //-----------------------------------------------------------------------------
  1832. void Frame::FlashWindow()
  1833. {
  1834. _flashWindow = true;
  1835. _nextFlashState = true;
  1836. InternalFlashWindow();
  1837. }
  1838. //-----------------------------------------------------------------------------
  1839. // Purpose: Stops any window flashing
  1840. //-----------------------------------------------------------------------------
  1841. void Frame::FlashWindowStop()
  1842. {
  1843. surface()->FlashWindow(GetVPanel(), false);
  1844. _flashWindow = false;
  1845. }
  1846. //-----------------------------------------------------------------------------
  1847. // Purpose: load the control settings - should be done after all the children are added to the dialog
  1848. //-----------------------------------------------------------------------------
  1849. void Frame::LoadControlSettings( const char *dialogResourceName, const char *pathID, KeyValues *pPreloadedKeyValues, KeyValues *pConditions )
  1850. {
  1851. BaseClass::LoadControlSettings( dialogResourceName, pathID, pPreloadedKeyValues, pConditions );
  1852. // set the focus on the default control
  1853. Panel *defaultFocus = GetFocusNavGroup().GetDefaultPanel();
  1854. if (defaultFocus)
  1855. {
  1856. defaultFocus->RequestFocus();
  1857. }
  1858. }
  1859. //-----------------------------------------------------------------------------
  1860. // Purpose: Checks for ctrl+shift+b hits to enter build mode
  1861. // Activates any hotkeys / default buttons
  1862. // Swallows any unhandled input
  1863. //-----------------------------------------------------------------------------
  1864. void Frame::OnKeyCodeTyped(KeyCode code)
  1865. {
  1866. bool shift = (input()->IsKeyDown(KEY_LSHIFT) || input()->IsKeyDown(KEY_RSHIFT));
  1867. bool ctrl = (input()->IsKeyDown(KEY_LCONTROL) || input()->IsKeyDown(KEY_RCONTROL));
  1868. bool alt = (input()->IsKeyDown(KEY_LALT) || input()->IsKeyDown(KEY_RALT));
  1869. if ( IsGameConsole() )
  1870. {
  1871. vgui::Panel *pMap = FindChildByName( "ControllerMap" );
  1872. if ( pMap && pMap->IsKeyBoardInputEnabled() )
  1873. {
  1874. pMap->OnKeyCodeTyped( code );
  1875. return;
  1876. }
  1877. }
  1878. if ( ctrl && shift && alt && code == KEY_B)
  1879. {
  1880. // enable build mode
  1881. ActivateBuildMode();
  1882. }
  1883. else if (ctrl && shift && alt && code == KEY_R)
  1884. {
  1885. // reload the scheme
  1886. VPANEL top = surface()->GetEmbeddedPanel();
  1887. if (top)
  1888. {
  1889. // reload the data file
  1890. scheme()->ReloadSchemes();
  1891. Panel *panel = ipanel()->GetPanel(top, GetModuleName());
  1892. if (panel)
  1893. {
  1894. // make the top-level panel reload it's scheme, it will chain down to all the child panels
  1895. panel->InvalidateLayout(false, true);
  1896. }
  1897. }
  1898. }
  1899. else if (alt && code == KEY_F4)
  1900. {
  1901. // user has hit the close
  1902. PostMessage(this, new KeyValues("CloseFrameButtonPressed"));
  1903. }
  1904. else if (code == KEY_ENTER)
  1905. {
  1906. // check for a default button
  1907. VPANEL panel = GetFocusNavGroup().GetCurrentDefaultButton();
  1908. if (panel && ipanel()->IsVisible( panel ) && ipanel()->IsEnabled( panel ))
  1909. {
  1910. // Activate the button
  1911. PostMessage(panel, new KeyValues("Hotkey"));
  1912. }
  1913. }
  1914. else if ( code == KEY_ESCAPE &&
  1915. surface()->SupportsFeature(ISurface::ESCAPE_KEY) &&
  1916. input()->GetAppModalSurface() == GetVPanel() )
  1917. {
  1918. // ESC cancels, unless we're in the engine - in the engine ESC flips between the UI and the game
  1919. CloseModal();
  1920. }
  1921. // Usually don't chain back as Frames are the end of the line for key presses, unless
  1922. // m_bChainKeysToParent is set
  1923. else if ( m_bChainKeysToParent )
  1924. {
  1925. BaseClass::OnKeyCodeTyped( code );
  1926. }
  1927. else
  1928. {
  1929. input()->OnKeyCodeUnhandled( (int)code );
  1930. }
  1931. }
  1932. //-----------------------------------------------------------------------------
  1933. // Purpose: If true, then OnKeyCodeTyped messages continue up past the Frame
  1934. // Input : state -
  1935. //-----------------------------------------------------------------------------
  1936. void Frame::SetChainKeysToParent( bool state )
  1937. {
  1938. m_bChainKeysToParent = state;
  1939. }
  1940. //-----------------------------------------------------------------------------
  1941. // Purpose: If true, then OnKeyCodeTyped messages continue up past the Frame
  1942. // Input : -
  1943. // Output : Returns true on success, false on failure.
  1944. //-----------------------------------------------------------------------------
  1945. bool Frame::CanChainKeysToParent() const
  1946. {
  1947. return m_bChainKeysToParent;
  1948. }
  1949. //-----------------------------------------------------------------------------
  1950. // Purpose: Checks for ctrl+shift+b hits to enter build mode
  1951. // Activates any hotkeys / default buttons
  1952. // Swallows any unhandled input
  1953. //-----------------------------------------------------------------------------
  1954. void Frame::OnKeyTyped(wchar_t unichar)
  1955. {
  1956. Panel *panel = GetFocusNavGroup().FindPanelByHotkey(unichar);
  1957. if (panel)
  1958. {
  1959. // tell the panel to Activate
  1960. PostMessage(panel, new KeyValues("Hotkey"));
  1961. }
  1962. }
  1963. //-----------------------------------------------------------------------------
  1964. // Purpose: sets all title bar controls
  1965. //-----------------------------------------------------------------------------
  1966. void Frame::SetTitleBarVisible( bool state )
  1967. {
  1968. _drawTitleBar = state;
  1969. SetMenuButtonVisible(state);
  1970. SetMinimizeButtonVisible(state);
  1971. SetMaximizeButtonVisible(state);
  1972. SetCloseButtonVisible(state);
  1973. }
  1974. //-----------------------------------------------------------------------------
  1975. // Purpose: sets the frame to delete itself on close
  1976. //-----------------------------------------------------------------------------
  1977. void Frame::SetDeleteSelfOnClose( bool state )
  1978. {
  1979. m_bDeleteSelfOnClose = state;
  1980. }
  1981. //-----------------------------------------------------------------------------
  1982. // Purpose: updates localized text
  1983. //-----------------------------------------------------------------------------
  1984. void Frame::OnDialogVariablesChanged( KeyValues *dialogVariables )
  1985. {
  1986. StringIndex_t index = _title->GetUnlocalizedTextSymbol();
  1987. if (index != INVALID_STRING_INDEX)
  1988. {
  1989. // reconstruct the string from the variables
  1990. wchar_t buf[1024];
  1991. g_pVGuiLocalize->ConstructString(buf, sizeof(buf), index, dialogVariables);
  1992. SetTitle(buf, true);
  1993. }
  1994. }
  1995. //-----------------------------------------------------------------------------
  1996. // Purpose: Handles staying on screen when the screen size changes
  1997. //-----------------------------------------------------------------------------
  1998. void Frame::OnScreenSizeChanged(int iOldWide, int iOldTall)
  1999. {
  2000. BaseClass::OnScreenSizeChanged(iOldWide, iOldTall);
  2001. if (IsProportional())
  2002. return;
  2003. // make sure we're completely on screen
  2004. int iNewWide, iNewTall;
  2005. surface()->GetScreenSize(iNewWide, iNewTall);
  2006. int x, y, wide, tall;
  2007. GetBounds(x, y, wide, tall);
  2008. // make sure the bottom-right corner is on the screen first
  2009. if (x + wide > iNewWide)
  2010. {
  2011. x = iNewWide - wide;
  2012. }
  2013. if (y + tall > iNewTall)
  2014. {
  2015. y = iNewTall - tall;
  2016. }
  2017. // make sure the top-left is visible
  2018. x = MAX( 0, x );
  2019. y = MAX( 0, y );
  2020. // apply
  2021. SetPos(x, y);
  2022. }
  2023. //-----------------------------------------------------------------------------
  2024. // Purpose: For supporting thin caption bars
  2025. // Input : state -
  2026. //-----------------------------------------------------------------------------
  2027. void Frame::SetSmallCaption( bool state )
  2028. {
  2029. m_bSmallCaption = state;
  2030. InvalidateLayout();
  2031. }
  2032. //-----------------------------------------------------------------------------
  2033. // Purpose:
  2034. // Input : -
  2035. // Output : Returns true on success, false on failure.
  2036. //-----------------------------------------------------------------------------
  2037. bool Frame::IsSmallCaption() const
  2038. {
  2039. return m_bSmallCaption;
  2040. }
  2041. //-----------------------------------------------------------------------------
  2042. // Purpose: Static method to place a frame under the cursor
  2043. //-----------------------------------------------------------------------------
  2044. void Frame::PlaceUnderCursor( )
  2045. {
  2046. // get cursor position, this is local to this text edit window
  2047. int cursorX, cursorY;
  2048. input()->GetCursorPos( cursorX, cursorY );
  2049. // relayout the menu immediately so that we know it's size
  2050. InvalidateLayout(true);
  2051. int w, h;
  2052. GetSize( w, h );
  2053. // work out where the cursor is and therefore the best place to put the frame
  2054. int sw, sh;
  2055. surface()->GetScreenSize( sw, sh );
  2056. // Try to center it first
  2057. int x, y;
  2058. x = cursorX - ( w / 2 );
  2059. y = cursorY - ( h / 2 );
  2060. // Clamp to various sides
  2061. if ( x + w > sw )
  2062. {
  2063. x = sw - w;
  2064. }
  2065. if ( y + h > sh )
  2066. {
  2067. y = sh - h;
  2068. }
  2069. if ( x < 0 )
  2070. {
  2071. x = 0;
  2072. }
  2073. if ( y < 0 )
  2074. {
  2075. y = 0;
  2076. }
  2077. SetPos( x, y );
  2078. }
  2079. void Frame::OnGripPanelMoved( int nNewX, int nNewY, int nNewW, int nNewH )
  2080. {
  2081. // set new position
  2082. SetBounds( nNewX, nNewY, nNewW, nNewH );
  2083. }