1//************************************ bs::framework - Copyright 2018 Marko Pintera **************************************//
2//*********** Licensed under the MIT license. See LICENSE.md for full terms. This notice is not to be removed. ***********//
3#include "GUI/BsGUITooltip.h"
4#include "GUI/BsGUIPanel.h"
5#include "Renderer/BsCamera.h"
6#include "RenderAPI/BsViewport.h"
7#include "GUI/BsGUILayoutY.h"
8#include "GUI/BsGUILayoutX.h"
9#include "GUI/BsGUITexture.h"
10#include "GUI/BsGUILabel.h"
11#include "GUI/BsGUIHelper.h"
12#include "GUI/BsGUISkin.h"
13#include "Resources/BsBuiltinResources.h"
14#include "GUI/BsDropDownAreaPlacement.h"
15
16using namespace std::placeholders;
17
18namespace bs
19{
20 const UINT32 GUITooltip::TOOLTIP_WIDTH = 200;
21 const UINT32 GUITooltip::CURSOR_SIZE = 16;
22
23 String GUITooltip::getFrameStyleName()
24 {
25 return "TooltipFrame";
26 }
27
28 GUITooltip::GUITooltip(const HSceneObject& parent, const GUIWidget& overlaidWidget, const Vector2I& position,
29 const String& text)
30 :CGUIWidget(parent, overlaidWidget.getCamera())
31 {
32 setDepth(0); // Needs to be in front of everything
33 setSkin(overlaidWidget.getSkinResource());
34
35 SPtr<Camera> camera = overlaidWidget.getCamera();
36 SPtr<Viewport> viewport = camera->getViewport();
37
38 Rect2I availableBounds = viewport->getPixelArea();
39
40 const GUISkin& skin = getSkin();
41 const GUIElementStyle* multiLineLabelStyle = skin.getStyle(BuiltinResources::MultiLineLabelStyle);
42 const GUIElementStyle* backgroundStyle = skin.getStyle(getFrameStyleName());
43
44 Vector2I size(TOOLTIP_WIDTH, 25);
45 if (multiLineLabelStyle != nullptr)
46 {
47 GUIDimensions dimensions = GUIDimensions::create(GUIOptions(GUIOption::fixedWidth(TOOLTIP_WIDTH)));
48 size = GUIHelper::calcOptimalContentsSize(text, *multiLineLabelStyle, dimensions);
49 }
50
51 INT32 contentOffsetX = 0;
52 INT32 contentOffsetY = 0;
53 if(backgroundStyle != nullptr)
54 {
55 size.x += backgroundStyle->margins.left + backgroundStyle->margins.right;
56 size.y += backgroundStyle->margins.top + backgroundStyle->margins.bottom;
57
58 contentOffsetX = backgroundStyle->margins.left;
59 contentOffsetY = backgroundStyle->margins.top;
60 }
61
62 // Content area
63 GUIPanel* contentPanel = getPanel()->addNewElement<GUIPanel>();
64 contentPanel->setWidth((UINT32)size.x);
65 contentPanel->setHeight((UINT32)size.y);
66 contentPanel->setDepthRange(-1);
67
68 // Background frame
69 GUIPanel* backgroundPanel = getPanel()->addNewElement<GUIPanel>();
70 backgroundPanel->setWidth((UINT32)size.x);
71 backgroundPanel->setHeight((UINT32)size.y);
72 backgroundPanel->setDepthRange(0);
73
74 GUILayout* backgroundLayout = backgroundPanel->addNewElement<GUILayoutX>();
75
76 GUITexture* backgroundFrame = GUITexture::create(TextureScaleMode::StretchToFit, getFrameStyleName());
77 backgroundLayout->addElement(backgroundFrame);
78
79 GUILayout* contentLayout = contentPanel->addNewElement<GUILayoutY>();
80 contentLayout->addNewElement<GUILabel>(HString(text),
81 GUIOptions(GUIOption::fixedWidth(TOOLTIP_WIDTH), GUIOption::flexibleHeight()),
82 BuiltinResources::MultiLineLabelStyle);
83
84 Rect2I positionBounds;
85 positionBounds.x = position.x;
86 positionBounds.y = position.y;
87 positionBounds.width = CURSOR_SIZE;
88 positionBounds.height = CURSOR_SIZE;
89
90 DropDownAreaPlacement::HorzDir horzDir;
91 DropDownAreaPlacement::VertDir vertDir;
92 DropDownAreaPlacement placement = DropDownAreaPlacement::aroundBounds(positionBounds);
93 Rect2I placementBounds = placement.getOptimalBounds((UINT32)size.x, (UINT32)size.y, availableBounds, horzDir, vertDir);
94
95 backgroundPanel->setPosition(placementBounds.x, placementBounds.y);
96 contentPanel->setPosition(placementBounds.x + contentOffsetX, placementBounds.y + contentOffsetY);
97 }
98}