Team Fortress 2 Source Code as on 22/4/2020
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.

2396 lines
64 KiB

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