Initial (incomplete) tooltip code
This was SVN commit r1540.
This commit is contained in:
parent
6486de894d
commit
659a9ea57a
@ -134,6 +134,23 @@
|
||||
cell-id CDATA #IMPLIED
|
||||
>
|
||||
|
||||
<!--
|
||||
<tooltip>
|
||||
-->
|
||||
<!ATTLIST tooltip
|
||||
name CDATA #REQUIRED
|
||||
sprite CDATA #REQUIRED
|
||||
|
||||
anchor CDATA #IMPLIED
|
||||
buffer-zone CDATA #IMPLIED
|
||||
font CDATA #IMPLIED
|
||||
maxwidth CDATA #IMPLIED
|
||||
pos CDATA #IMPLIED
|
||||
textcolor CDATA #IMPLIED
|
||||
time CDATA #IMPLIED
|
||||
>
|
||||
|
||||
|
||||
<!--
|
||||
<sprites>
|
||||
-->
|
||||
|
@ -31,6 +31,8 @@ CButton::CButton()
|
||||
AddSetting(GUIST_CColor, "textcolor-over");
|
||||
AddSetting(GUIST_CColor, "textcolor-pressed");
|
||||
AddSetting(GUIST_CColor, "textcolor-disabled");
|
||||
AddSetting(GUIST_CStr, "tooltip");
|
||||
AddSetting(GUIST_CStr, "tooltip-style");
|
||||
|
||||
// Add text
|
||||
AddText(new SGUIText());
|
||||
|
@ -37,15 +37,17 @@ CCheckBox::CCheckBox()
|
||||
*/
|
||||
AddSetting(GUIST_CGUIString, "caption");
|
||||
AddSetting(GUIST_bool, "checked");
|
||||
AddSetting(GUIST_CGUISpriteInstance,"sprite");
|
||||
AddSetting(GUIST_CGUISpriteInstance,"sprite-over");
|
||||
AddSetting(GUIST_CGUISpriteInstance,"sprite-pressed");
|
||||
AddSetting(GUIST_CGUISpriteInstance,"sprite-disabled");
|
||||
AddSetting(GUIST_CGUISpriteInstance,"sprite2");
|
||||
AddSetting(GUIST_CGUISpriteInstance,"sprite2-over");
|
||||
AddSetting(GUIST_CGUISpriteInstance,"sprite2-pressed");
|
||||
AddSetting(GUIST_CGUISpriteInstance,"sprite2-disabled");
|
||||
AddSetting(GUIST_CGUISpriteInstance, "sprite");
|
||||
AddSetting(GUIST_CGUISpriteInstance, "sprite-over");
|
||||
AddSetting(GUIST_CGUISpriteInstance, "sprite-pressed");
|
||||
AddSetting(GUIST_CGUISpriteInstance, "sprite-disabled");
|
||||
AddSetting(GUIST_CGUISpriteInstance, "sprite2");
|
||||
AddSetting(GUIST_CGUISpriteInstance, "sprite2-over");
|
||||
AddSetting(GUIST_CGUISpriteInstance, "sprite2-pressed");
|
||||
AddSetting(GUIST_CGUISpriteInstance, "sprite2-disabled");
|
||||
AddSetting(GUIST_int, "square-side");
|
||||
AddSetting(GUIST_CStr, "tooltip");
|
||||
AddSetting(GUIST_CStr, "tooltip-style");
|
||||
|
||||
// Add text
|
||||
AddText(new SGUIText());
|
||||
|
@ -22,6 +22,7 @@ gee@pyro.nu
|
||||
#include "CRadioButton.h"
|
||||
#include "CInput.h"
|
||||
#include "CProgressBar.h"
|
||||
#include "CTooltip.h"
|
||||
#include "MiniMap.h"
|
||||
|
||||
#include "ps/Xeromyces.h"
|
||||
@ -183,8 +184,9 @@ int CGUI::HandleEvent(const SDL_Event* ev)
|
||||
else
|
||||
if (ev->type == SDL_MOUSEBUTTONUP)
|
||||
{
|
||||
if (ev->button.button == SDL_BUTTON_LEFT)
|
||||
switch (ev->button.button)
|
||||
{
|
||||
case SDL_BUTTON_LEFT:
|
||||
if (pNearest)
|
||||
{
|
||||
pNearest->HandleMessage(SGUIMessage(GUIM_MOUSE_RELEASE_LEFT));
|
||||
@ -192,6 +194,7 @@ int CGUI::HandleEvent(const SDL_Event* ev)
|
||||
|
||||
ret = EV_HANDLED;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// Reset all states on all visible objects
|
||||
@ -249,6 +252,16 @@ void CGUI::TickObjects()
|
||||
CStr action = "tick";
|
||||
GUI<CStr>::RecurseObject(0, m_BaseObject,
|
||||
&IGUIObject::ScriptEvent, action);
|
||||
|
||||
// Also update tooltips:
|
||||
|
||||
// TODO: Efficiency
|
||||
IGUIObject* pNearest = NULL;
|
||||
GUI<IGUIObject*>::RecurseObject(GUIRR_HIDDEN | GUIRR_GHOST, m_BaseObject,
|
||||
&IGUIObject::ChooseMouseOverAndClosest,
|
||||
pNearest);
|
||||
|
||||
m_Tooltip.Update(pNearest, m_MousePos, this);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
@ -667,8 +680,8 @@ SGUIText CGUI::GenerateText(const CGUIString &string,
|
||||
// this won't be exact because we're assuming the line_height
|
||||
// will be as our preliminary calculation said. But that may change,
|
||||
// although we'd have to add a couple of more loops to try straightening
|
||||
// this problem out, and it is very unlikely to happen noticably if one
|
||||
// stuctures his text in a stylistically pure fashion. Even if not, it
|
||||
// this problem out, and it is very unlikely to happen noticeably if one
|
||||
// structures his text in a stylistically pure fashion. Even if not, it
|
||||
// is still quite unlikely it will happen.
|
||||
// Loop through left and right side, from and to.
|
||||
for (int j=0; j<2; ++j)
|
||||
@ -832,7 +845,7 @@ void CGUI::DrawText(SGUIText &Text, const CColor &DefaultColor,
|
||||
const CPos &pos, const float &z)
|
||||
{
|
||||
// TODO Gee: All these really necessary? Some
|
||||
// are deafults and if you changed them
|
||||
// are defaults and if you changed them
|
||||
// the opposite value at the end of the functions,
|
||||
// some things won't be drawn correctly.
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
@ -1054,7 +1067,15 @@ void CGUI::Xeromyces_ReadRootSetup(XMBElement Element, CXeromyces* pFile)
|
||||
{
|
||||
Xeromyces_ReadIcon(child, pFile);
|
||||
}
|
||||
// No need for else, we're using DTD.
|
||||
else
|
||||
if (name == "tooltip")
|
||||
{
|
||||
Xeromyces_ReadTooltip(child, pFile);
|
||||
}
|
||||
else
|
||||
{
|
||||
debug_warn("Invalid data - DTD shouldn't allow this");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1105,8 +1126,8 @@ void CGUI::Xeromyces_ReadObject(XMBElement Element, CXeromyces* pFile, IGUIObjec
|
||||
//
|
||||
CStr argStyle (attributes.getNamedItem(attr_style));
|
||||
|
||||
if (m_Styles.count(CStr("default")) == 1)
|
||||
object->LoadStyle(*this, CStr("default"));
|
||||
if (m_Styles.count("default") == 1)
|
||||
object->LoadStyle(*this, "default");
|
||||
|
||||
if (argStyle.Length())
|
||||
{
|
||||
@ -1134,7 +1155,7 @@ void CGUI::Xeromyces_ReadObject(XMBElement Element, CXeromyces* pFile, IGUIObjec
|
||||
XMBAttribute attr = attributes.item(i);
|
||||
|
||||
// If value is "null", then it is equivalent as never being entered
|
||||
if ((CStr)attr.Value == (CStr)"null")
|
||||
if ((CStr)attr.Value == "null")
|
||||
continue;
|
||||
|
||||
// Ignore "type" and "style", we've already checked it
|
||||
@ -1156,47 +1177,6 @@ void CGUI::Xeromyces_ReadObject(XMBElement Element, CXeromyces* pFile, IGUIObjec
|
||||
if (attr.Name == attr_z)
|
||||
ManuallySetZ = true;
|
||||
|
||||
|
||||
/* TODO: Reimplement this inside GUIRenderer.cpp
|
||||
|
||||
// Generate "stretched:filename" sprites.
|
||||
//
|
||||
// Check whether it's actually one of the many sprite... parameters.
|
||||
if (pFile->getAttributeString(attr.Name).substr(0, 6) == "sprite")
|
||||
{
|
||||
// Check whether it's a special stretched one
|
||||
CStr SpriteName (attr.Value);
|
||||
if (SpriteName.substr(0, 10) == "stretched:" &&
|
||||
m_Sprites.find(SpriteName) == m_Sprites.end() )
|
||||
{
|
||||
|
||||
CStr TexFilename ("art/textures/ui/");
|
||||
TexFilename += SpriteName.substr(10);
|
||||
|
||||
Handle tex = tex_load(TexFilename);
|
||||
if (tex <= 0)
|
||||
{
|
||||
LOG(ERROR, LOG_CATEGORY, "Error opening texture '%s': %lld", TexFilename.c_str(), tex);
|
||||
}
|
||||
else
|
||||
{
|
||||
CGUISprite sprite;
|
||||
SGUIImage image;
|
||||
|
||||
CStr DefaultSize ("0 0 100% 100%");
|
||||
image.m_TextureSize = CClientArea(DefaultSize);
|
||||
image.m_Size = CClientArea(DefaultSize);
|
||||
|
||||
image.m_TextureName = TexFilename;
|
||||
image.m_Texture = tex;
|
||||
tex_upload(tex);
|
||||
|
||||
sprite.AddImage(image);
|
||||
m_Sprites[SpriteName] = sprite;
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
// Try setting the value
|
||||
if (object->SetSetting(pFile->getAttributeString(attr.Name), (CStr)attr.Value) != PS_OK)
|
||||
{
|
||||
@ -1214,8 +1194,8 @@ void CGUI::Xeromyces_ReadObject(XMBElement Element, CXeromyces* pFile, IGUIObjec
|
||||
}
|
||||
|
||||
// Attempt to register the hotkey tag, if one was provided
|
||||
if( hotkeyTag.Length() )
|
||||
hotkeyRegisterGUIObject( object->GetName(), hotkeyTag );
|
||||
if (hotkeyTag.Length())
|
||||
hotkeyRegisterGUIObject(object->GetName(), hotkeyTag);
|
||||
|
||||
CStrW caption (Element.getText());
|
||||
if (caption.Length())
|
||||
@ -1376,6 +1356,9 @@ void CGUI::Xeromyces_ReadSprite(XMBElement Element, CXeromyces* pFile)
|
||||
// Get name, we know it exists because of DTD requirements
|
||||
name = Element.getAttributes().getNamedItem( pFile->getAttributeID("name") );
|
||||
|
||||
if (m_Sprites.find(name) != m_Sprites.end())
|
||||
LOG(WARNING, LOG_CATEGORY, "Sprite name '%s' used more than once; first definition will be discarded", (const char*)name);
|
||||
|
||||
//
|
||||
// Read Children (the images)
|
||||
//
|
||||
@ -1404,7 +1387,7 @@ void CGUI::Xeromyces_ReadSprite(XMBElement Element, CXeromyces* pFile)
|
||||
}
|
||||
else
|
||||
{
|
||||
debug_warn("Oops"); // DTD shouldn't allow this
|
||||
debug_warn("Invalid data - DTD shouldn't allow this");
|
||||
}
|
||||
}
|
||||
|
||||
@ -1521,7 +1504,7 @@ void CGUI::Xeromyces_ReadImage(XMBElement Element, CXeromyces* pFile, CGUISprite
|
||||
}
|
||||
else
|
||||
{
|
||||
debug_warn("Oops"); // DTD shouldn't allow this
|
||||
debug_warn("Invalid data - DTD shouldn't allow this");
|
||||
}
|
||||
}
|
||||
|
||||
@ -1539,7 +1522,7 @@ void CGUI::Xeromyces_ReadImage(XMBElement Element, CXeromyces* pFile, CGUISprite
|
||||
}
|
||||
else
|
||||
{
|
||||
debug_warn("Oops"); // DTD shouldn't allow this
|
||||
debug_warn("Invalid data - DTD shouldn't allow this");
|
||||
}
|
||||
}
|
||||
|
||||
@ -1581,7 +1564,7 @@ void CGUI::Xeromyces_ReadEffects(XMBElement Element, CXeromyces* pFile, SGUIImag
|
||||
BOOL("grayscale", Greyscale)
|
||||
|
||||
{
|
||||
debug_warn("Oops"); // DTD shouldn't allow this
|
||||
debug_warn("Invalid data - DTD shouldn't allow this");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1746,9 +1729,36 @@ void CGUI::Xeromyces_ReadIcon(XMBElement Element, CXeromyces* pFile)
|
||||
}
|
||||
else
|
||||
{
|
||||
debug_warn("Oops"); // DTD shouldn't allow this
|
||||
debug_warn("Invalid data - DTD shouldn't allow this");
|
||||
}
|
||||
}
|
||||
|
||||
m_Icons[name] = icon;
|
||||
}
|
||||
|
||||
void CGUI::Xeromyces_ReadTooltip(XMBElement Element, CXeromyces* pFile)
|
||||
{
|
||||
IGUIObject* object = new CTooltip;
|
||||
|
||||
object->SetName(CStr("__internal(") + CStr(m_InternalNameNumber) + CStr(")"));
|
||||
++m_InternalNameNumber;
|
||||
|
||||
XMBAttributeList attributes = Element.getAttributes();
|
||||
for (int i=0; i<attributes.Count; ++i)
|
||||
{
|
||||
XMBAttribute attr = attributes.item(i);
|
||||
CStr attr_name (pFile->getAttributeString(attr.Name));
|
||||
CStr attr_value (attr.Value);
|
||||
|
||||
if (attr_name == "name")
|
||||
{
|
||||
object->SetName(attr_value);
|
||||
}
|
||||
else
|
||||
{
|
||||
object->SetSetting(attr_name, attr_value);
|
||||
}
|
||||
}
|
||||
|
||||
AddObject(object);
|
||||
}
|
||||
|
@ -25,6 +25,7 @@ ERROR_TYPE(GUI, JSOpenFailed);
|
||||
//--------------------------------------------------------
|
||||
#include "GUI.h"
|
||||
|
||||
#include "GUITooltip.h"
|
||||
#include "Singleton.h"
|
||||
#include "input.h" // JW: grr, classes suck in this case :P
|
||||
|
||||
@ -476,6 +477,8 @@ private:
|
||||
*/
|
||||
void Xeromyces_ReadIcon(XMBElement Element, CXeromyces* pFile);
|
||||
|
||||
void Xeromyces_ReadTooltip(XMBElement Element, CXeromyces* pFile);
|
||||
|
||||
//@}
|
||||
|
||||
private:
|
||||
@ -511,6 +514,8 @@ private:
|
||||
// TODO Gee: Used?
|
||||
int16_t m_Errors;
|
||||
|
||||
GUITooltip m_Tooltip;
|
||||
|
||||
//@}
|
||||
//--------------------------------------------------------
|
||||
/** @name Objects */
|
||||
|
@ -19,6 +19,8 @@ CImage::CImage()
|
||||
{
|
||||
AddSetting(GUIST_CGUISpriteInstance, "sprite");
|
||||
AddSetting(GUIST_int, "cell-id");
|
||||
AddSetting(GUIST_CStr, "tooltip");
|
||||
AddSetting(GUIST_CStr, "tooltip-style");
|
||||
}
|
||||
|
||||
CImage::~CImage()
|
||||
|
@ -33,6 +33,8 @@ CInput::CInput() : m_iBufferPos(0)
|
||||
AddSetting(GUIST_CGUISpriteInstance, "sprite");
|
||||
AddSetting(GUIST_int, "cell-id");
|
||||
AddSetting(GUIST_CColor, "textcolor");
|
||||
AddSetting(GUIST_CStr, "tooltip");
|
||||
AddSetting(GUIST_CStr, "tooltip-style");
|
||||
// TODO Gee: (2004-08-14)
|
||||
// Add a setting for buffer zone
|
||||
//AddSetting(GUIST_int, "
|
||||
|
@ -20,6 +20,8 @@ CProgressBar::CProgressBar()
|
||||
AddSetting(GUIST_CGUISpriteInstance, "sprite-background");
|
||||
AddSetting(GUIST_CGUISpriteInstance, "sprite-bar");
|
||||
AddSetting(GUIST_float, "caption"); // aka value from 0 to 100
|
||||
AddSetting(GUIST_CStr, "tooltip");
|
||||
AddSetting(GUIST_CStr, "tooltip-style");
|
||||
}
|
||||
|
||||
CProgressBar::~CProgressBar()
|
||||
|
@ -28,6 +28,8 @@ CText::CText()
|
||||
AddSetting(GUIST_CGUISpriteInstance, "sprite");
|
||||
AddSetting(GUIST_int, "cell-id");
|
||||
AddSetting(GUIST_CColor, "textcolor");
|
||||
AddSetting(GUIST_CStr, "tooltip");
|
||||
AddSetting(GUIST_CStr, "tooltip-style");
|
||||
// TODO Gee: (2004-08-14)
|
||||
// Add a setting for buffer zone
|
||||
//AddSetting(GUIST_int, "
|
||||
@ -56,8 +58,6 @@ void CText::SetupText()
|
||||
|
||||
assert(m_GeneratedTexts.size()>=1);
|
||||
|
||||
CColor color;
|
||||
|
||||
CStr font;
|
||||
if (GUI<CStr>::GetSetting(this, "font", font) != PS_OK || font.Length()==0)
|
||||
// Use the default if none is specified
|
||||
@ -66,7 +66,6 @@ void CText::SetupText()
|
||||
|
||||
CGUIString caption;
|
||||
bool scrollbar;
|
||||
GUI<CColor>::GetSetting(this, "textcolor", color);
|
||||
GUI<CGUIString>::GetSetting(this, "caption", caption);
|
||||
GUI<bool>::GetSetting(this, "scrollbar", scrollbar);
|
||||
|
||||
|
140
source/gui/CTooltip.cpp
Normal file
140
source/gui/CTooltip.cpp
Normal file
@ -0,0 +1,140 @@
|
||||
#include "precompiled.h"
|
||||
|
||||
#include "CTooltip.h"
|
||||
#include "CGUI.h"
|
||||
|
||||
CTooltip::CTooltip()
|
||||
{
|
||||
AddSetting(GUIST_float, "buffer-zone");
|
||||
AddSetting(GUIST_CGUIString, "caption");
|
||||
AddSetting(GUIST_CStr, "font");
|
||||
AddSetting(GUIST_CGUISpriteInstance, "sprite");
|
||||
AddSetting(GUIST_float, "time");
|
||||
AddSetting(GUIST_CColor, "textcolor");
|
||||
AddSetting(GUIST_int, "maxwidth");
|
||||
AddSetting(GUIST_CPos, "pos");
|
||||
AddSetting(GUIST_EVAlign, "anchor");
|
||||
|
||||
AddSetting(GUIST_CPos, "_mousepos");
|
||||
|
||||
GUI<float>::SetSetting(this, "time", 0.5f);
|
||||
GUI<EVAlign>::SetSetting(this, "anchor", EVAlign_Bottom);
|
||||
|
||||
// Set up a blank piece of text, to be replaced with a more
|
||||
// interesting message later
|
||||
AddText(new SGUIText());
|
||||
}
|
||||
|
||||
CTooltip::~CTooltip()
|
||||
{
|
||||
}
|
||||
|
||||
void CTooltip::SetupText()
|
||||
{
|
||||
if (!GetGUI())
|
||||
return;
|
||||
|
||||
assert(m_GeneratedTexts.size()==1);
|
||||
|
||||
CStr font;
|
||||
if (GUI<CStr>::GetSetting(this, "font", font) != PS_OK || font.Length()==0)
|
||||
font = "default";
|
||||
|
||||
float buffer_zone=0.f;
|
||||
GUI<float>::GetSetting(this, "buffer-zone", buffer_zone);
|
||||
|
||||
CGUIString caption;
|
||||
GUI<CGUIString>::GetSetting(this, "caption", caption);
|
||||
|
||||
float max_width = 500.f; // TODO: max-width setting
|
||||
|
||||
*m_GeneratedTexts[0] = GetGUI()->GenerateText(caption, font, max_width, buffer_zone, this);
|
||||
|
||||
CPos mousepos, pos;
|
||||
EVAlign anchor;
|
||||
GUI<CPos>::GetSetting(this, "_mousepos", mousepos);
|
||||
GUI<CPos>::GetSetting(this, "pos", pos);
|
||||
GUI<EVAlign>::GetSetting(this, "anchor", anchor);
|
||||
|
||||
// Position the tooltip relative to the mouse
|
||||
|
||||
CClientArea size;
|
||||
size.pixel.left = mousepos.x + pos.x;
|
||||
size.pixel.right = size.pixel.left + m_GeneratedTexts[0]->m_Size.cx;
|
||||
switch (anchor)
|
||||
{
|
||||
case EVAlign_Top:
|
||||
size.pixel.top = mousepos.y + pos.y;
|
||||
size.pixel.bottom = size.pixel.top + m_GeneratedTexts[0]->m_Size.cy;
|
||||
break;
|
||||
case EVAlign_Bottom:
|
||||
size.pixel.bottom = mousepos.y + pos.y;
|
||||
size.pixel.top = size.pixel.bottom - m_GeneratedTexts[0]->m_Size.cy;
|
||||
break;
|
||||
case EVAlign_Center:
|
||||
size.pixel.top = mousepos.y + pos.y - m_GeneratedTexts[0]->m_Size.cy/2.f;
|
||||
size.pixel.bottom = size.pixel.top + m_GeneratedTexts[0]->m_Size.cy;
|
||||
break;
|
||||
default:
|
||||
debug_warn("Invalid EVAlign!");
|
||||
}
|
||||
|
||||
// Adjust it if it's falling off the screen
|
||||
|
||||
extern int g_xres, g_yres;
|
||||
float screenw = (float)g_xres, screenh = (float)g_yres;
|
||||
|
||||
if (size.pixel.top < 0.f)
|
||||
size.pixel.bottom -= size.pixel.top, size.pixel.top = 0.f;
|
||||
else if (size.pixel.bottom > screenh)
|
||||
size.pixel.top -= (size.pixel.bottom-screenh), size.pixel.bottom = screenh;
|
||||
else if (size.pixel.left < 0.f)
|
||||
size.pixel.right -= size.pixel.left, size.pixel.left = 0.f;
|
||||
else if (size.pixel.right > screenw)
|
||||
size.pixel.left -= (size.pixel.right-screenw), size.pixel.right = screenw;
|
||||
|
||||
GUI<CClientArea>::SetSetting(this, "size", size);
|
||||
UpdateCachedSize();
|
||||
}
|
||||
|
||||
void CTooltip::HandleMessage(const SGUIMessage &Message)
|
||||
{
|
||||
switch (Message.type)
|
||||
{
|
||||
case GUIM_SETTINGS_UPDATED:
|
||||
// Don't update the text when the size changes, because the size is
|
||||
// changed whenever the text is updated ( => infinite recursion)
|
||||
if (/*Message.value == "size" ||*/ Message.value == "caption" ||
|
||||
Message.value == "font" || Message.value == "buffer-zone")
|
||||
{
|
||||
SetupText();
|
||||
}
|
||||
break;
|
||||
|
||||
case GUIM_LOAD:
|
||||
SetupText();
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void CTooltip::Draw()
|
||||
{
|
||||
float z = 900.f; // TODO: Find a nicer way of putting the tooltip on top of everything else
|
||||
|
||||
if (GetGUI())
|
||||
{
|
||||
CGUISpriteInstance *sprite;
|
||||
GUI<CGUISpriteInstance>::GetSettingPointer(this, "sprite", sprite);
|
||||
|
||||
GetGUI()->DrawSprite(*sprite, 0, z, m_CachedActualSize);
|
||||
|
||||
CColor color;
|
||||
GUI<CColor>::GetSetting(this, "textcolor", color);
|
||||
|
||||
// Draw text
|
||||
IGUITextOwner::Draw(0, color, m_CachedActualSize.TopLeft(), z+0.1f);
|
||||
}
|
||||
}
|
31
source/gui/CTooltip.h
Normal file
31
source/gui/CTooltip.h
Normal file
@ -0,0 +1,31 @@
|
||||
/*
|
||||
GUI Object - Tooltip
|
||||
|
||||
--Overview--
|
||||
|
||||
Mostly like CText, but intended for dynamic tooltips
|
||||
|
||||
*/
|
||||
|
||||
#ifndef CTooltip_H
|
||||
#define CTooltip_H
|
||||
|
||||
#include "IGUITextOwner.h"
|
||||
|
||||
class CTooltip : public IGUITextOwner
|
||||
{
|
||||
GUI_OBJECT(CTooltip)
|
||||
|
||||
public:
|
||||
CTooltip();
|
||||
virtual ~CTooltip();
|
||||
|
||||
protected:
|
||||
void SetupText();
|
||||
|
||||
virtual void HandleMessage(const SGUIMessage &Message);
|
||||
|
||||
virtual void Draw();
|
||||
};
|
||||
|
||||
#endif
|
209
source/gui/GUITooltip.cpp
Normal file
209
source/gui/GUITooltip.cpp
Normal file
@ -0,0 +1,209 @@
|
||||
#include "precompiled.h"
|
||||
|
||||
#include "GUITooltip.h"
|
||||
#include "lib/timer.h"
|
||||
#include "IGUIObject.h"
|
||||
#include "CGUI.h"
|
||||
|
||||
#include "ps/CLogger.h"
|
||||
|
||||
/*
|
||||
Tooltips:
|
||||
When holding the mouse stationary over an object for some amount of time,
|
||||
the tooltip is displayed. If the mouse moves off that object, the tooltip
|
||||
disappears. If the mouse re-enters an object within a short time, the new
|
||||
tooltip is displayed immediately. (This lets you run the mouse across a
|
||||
series of buttons, without waiting ages for the text to pop up every time.)
|
||||
|
||||
See Visual Studio's toolbar buttons for an example.
|
||||
|
||||
|
||||
Implemented as a state machine:
|
||||
|
||||
(where "*" lines are checked constantly, and "<" lines are handled
|
||||
on entry to that state)
|
||||
|
||||
IN MOTION
|
||||
* If the mouse stops, check whether it should have a tooltip and move to
|
||||
'STATIONARY, NO TOOLTIP' or 'STATIONARY, TOOLIP'
|
||||
|
||||
STATIONARY, NO TOOLTIP
|
||||
* If the mouse moves, switch to 'IN MOTION'
|
||||
|
||||
STATIONARY, TOOLTIP
|
||||
< Set target time = now + tooltip time
|
||||
* If the mouse moves, switch to 'IN MOTION'
|
||||
* If now > target time, switch to 'SHOWING'
|
||||
|
||||
SHOWING
|
||||
< Start displaying the tooltip
|
||||
* If the mouse leaves the object, check whether it has a tooltip
|
||||
and switch to 'SHOWING' or 'COOLING'
|
||||
|
||||
COOLING (since I can't think of a better name)
|
||||
< Stop displaying the tooltip
|
||||
< Set target time = now + cooldown time
|
||||
* If the mouse has moved and is over a tooltipped object, switch to 'SHOWING'
|
||||
* If now > target time, switch to 'STATIONARY, NO TOOLTIP'
|
||||
*/
|
||||
|
||||
enum
|
||||
{
|
||||
ST_IN_MOTION,
|
||||
ST_STATIONARY_NO_TOOLTIP,
|
||||
ST_STATIONARY_TOOLTIP,
|
||||
ST_SHOWING,
|
||||
ST_COOLING
|
||||
};
|
||||
|
||||
GUITooltip::GUITooltip()
|
||||
: m_State(ST_IN_MOTION), m_PreviousObject(NULL), m_PreviousTooltipName(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
const double CooldownTime = 0.25; // TODO: Don't hard-code this value
|
||||
|
||||
static bool GetTooltip(IGUIObject* obj, CStr* &style)
|
||||
{
|
||||
if (obj && obj->SettingExists("tooltip-style"))
|
||||
{
|
||||
// Use GetSettingPointer to avoid unnecessary string-copying.
|
||||
// (The tooltip code is only run once per frame, but efficiency
|
||||
// would be nice anyway.)
|
||||
if (GUI<CStr>::GetSettingPointer(obj, "tooltip-style", style) == PS_OK
|
||||
&& style->Length())
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Urgh - this is only a method because it needs to access HandleMessage (which
|
||||
// is 'protected'), so it needs to be friendable (and so not a static function)
|
||||
void GUITooltip::ShowTooltip(IGUIObject* obj, CPos pos, CStr& style, CGUI* gui)
|
||||
{
|
||||
IGUIObject* tooltipobj = gui->FindObjectByName(style);
|
||||
if (! tooltipobj)
|
||||
{
|
||||
LOG_ONCE(ERROR, "gui", "Cannot find tooltip object named '%s'", (const char*)style);
|
||||
return;
|
||||
}
|
||||
GUI<bool>::SetSetting(tooltipobj, "hidden", false);
|
||||
|
||||
assert(obj);
|
||||
|
||||
// These shouldn't fail:
|
||||
|
||||
CStr text;
|
||||
if (GUI<CStr>::GetSetting(obj, "tooltip", text) != PS_OK)
|
||||
debug_warn("Failed to retrieve tooltip text");
|
||||
|
||||
if (tooltipobj->SetSetting("caption", text) != PS_OK)
|
||||
debug_warn("Failed to set tooltip caption");
|
||||
|
||||
if (GUI<CPos>::SetSetting(tooltipobj, "_mousepos", pos) != PS_OK)
|
||||
debug_warn("Failed to set tooltip mouse position");
|
||||
|
||||
tooltipobj->HandleMessage(SGUIMessage(GUIM_SETTINGS_UPDATED, "caption"));
|
||||
}
|
||||
|
||||
static void HideTooltip(CStr& style, CGUI* gui)
|
||||
{
|
||||
IGUIObject* tooltipobj = gui->FindObjectByName(style);
|
||||
if (! tooltipobj)
|
||||
{
|
||||
LOG_ONCE(ERROR, "gui", "Cannot find tooltip object named '%s'", (const char*)style);
|
||||
return;
|
||||
}
|
||||
GUI<bool>::SetSetting(tooltipobj, "hidden", true);
|
||||
}
|
||||
|
||||
void GUITooltip::Update(IGUIObject* Nearest, CPos MousePos, CGUI* GUI)
|
||||
{
|
||||
double now = get_time();
|
||||
|
||||
CStr* style = NULL;
|
||||
|
||||
int nextstate = -1;
|
||||
|
||||
switch (m_State)
|
||||
{
|
||||
case ST_IN_MOTION:
|
||||
if (MousePos == m_PreviousMousePos)
|
||||
{
|
||||
if (GetTooltip(Nearest, style))
|
||||
nextstate = ST_STATIONARY_TOOLTIP;
|
||||
else
|
||||
nextstate = ST_STATIONARY_NO_TOOLTIP;
|
||||
}
|
||||
break;
|
||||
|
||||
case ST_STATIONARY_NO_TOOLTIP:
|
||||
if (MousePos != m_PreviousMousePos)
|
||||
nextstate = ST_IN_MOTION;
|
||||
break;
|
||||
|
||||
case ST_STATIONARY_TOOLTIP:
|
||||
if (MousePos != m_PreviousMousePos)
|
||||
nextstate = ST_IN_MOTION;
|
||||
else if (now >= m_Time)
|
||||
{
|
||||
// Make sure the tooltip still exists
|
||||
if (GetTooltip(Nearest, style))
|
||||
nextstate = ST_SHOWING;
|
||||
else
|
||||
{
|
||||
// Failed to retrieve style - the object has probably been
|
||||
// altered, so just restart the process
|
||||
nextstate = ST_IN_MOTION;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case ST_SHOWING:
|
||||
if (Nearest != m_PreviousObject)
|
||||
{
|
||||
if (GetTooltip(Nearest, style))
|
||||
nextstate = ST_SHOWING;
|
||||
else
|
||||
nextstate = ST_COOLING;
|
||||
}
|
||||
break;
|
||||
|
||||
case ST_COOLING:
|
||||
if (now >= m_Time)
|
||||
nextstate = ST_IN_MOTION;
|
||||
else if (Nearest != m_PreviousObject && GetTooltip(Nearest, style))
|
||||
nextstate = ST_SHOWING;
|
||||
break;
|
||||
}
|
||||
|
||||
if (nextstate != -1)
|
||||
{
|
||||
switch (nextstate)
|
||||
{
|
||||
case ST_STATIONARY_TOOLTIP:
|
||||
m_Time = now + 0.5/* TODO: tooltip time */;
|
||||
break;
|
||||
|
||||
case ST_SHOWING:
|
||||
// show tooltip
|
||||
ShowTooltip(Nearest, MousePos, *style, GUI);
|
||||
m_PreviousTooltipName = *style;
|
||||
break;
|
||||
|
||||
case ST_COOLING:
|
||||
// hide the tooltip
|
||||
HideTooltip(m_PreviousTooltipName, GUI);
|
||||
m_Time = now + CooldownTime;
|
||||
break;
|
||||
}
|
||||
|
||||
m_State = nextstate;
|
||||
}
|
||||
|
||||
|
||||
m_PreviousMousePos = MousePos;
|
||||
m_PreviousObject = Nearest;
|
||||
|
||||
}
|
27
source/gui/GUITooltip.h
Normal file
27
source/gui/GUITooltip.h
Normal file
@ -0,0 +1,27 @@
|
||||
#ifndef GUITooltip_H
|
||||
#define GUITooltip_H
|
||||
|
||||
class IGUIObject;
|
||||
class CGUI;
|
||||
class CStr;
|
||||
|
||||
#include "Overlay.h"
|
||||
|
||||
class GUITooltip
|
||||
{
|
||||
public:
|
||||
GUITooltip();
|
||||
void Update(IGUIObject* Nearest, CPos MousePos, CGUI* GUI);
|
||||
|
||||
private:
|
||||
void ShowTooltip(IGUIObject* obj, CPos pos, CStr& style, CGUI* gui);
|
||||
|
||||
int m_State;
|
||||
|
||||
IGUIObject* m_PreviousObject;
|
||||
CStr m_PreviousTooltipName;
|
||||
CPos m_PreviousMousePos;
|
||||
double m_Time;
|
||||
};
|
||||
|
||||
#endif // GUITooltip_H
|
@ -299,6 +299,8 @@ void CGUIString::SetValue(const CStrW& str)
|
||||
|
||||
// Setup parser
|
||||
// TODO Gee: (2004-08-16) Create and store this parser object somewhere to save loading time.
|
||||
// TODO PT: Extended CParserCache so that the above is possible (since it currently only
|
||||
// likes one-task parsers)
|
||||
CParser Parser;
|
||||
// I've added the option of an additional parameter. Only used for icons when writing this.
|
||||
Parser.InputTaskType("start", "$ident[_=_$value_[$ident_=_$value_]]");
|
||||
|
@ -132,7 +132,7 @@ struct SGUIText
|
||||
* List of sprites, or "icons" that should be rendered
|
||||
* along with the text.
|
||||
*/
|
||||
std::list<SSpriteCall> m_SpriteCalls; // list for consistant mem addresses
|
||||
std::list<SSpriteCall> m_SpriteCalls; // list for consistent mem addresses
|
||||
// so that we can point to elements.
|
||||
|
||||
/**
|
||||
@ -145,7 +145,7 @@ struct SGUIText
|
||||
/**
|
||||
* @author Gustav Larsson
|
||||
*
|
||||
* String class, substitue for CStr, but that parses
|
||||
* String class, substitute for CStr, but that parses
|
||||
* the tags and builds up a list of all text that will
|
||||
* be different when outputted.
|
||||
*
|
||||
@ -287,7 +287,7 @@ public:
|
||||
* @param Feedback contains all info that is generated.
|
||||
* @param DefaultFont Default Font
|
||||
* @param from From character n,
|
||||
* @param to to chacter n.
|
||||
* @param to to character n.
|
||||
* @param FirstLine Whether this is the first line of text, to calculate its height correctly
|
||||
*
|
||||
* pObject Only for Error outputting, optional! If NULL
|
||||
|
@ -1,14 +1,68 @@
|
||||
// This file is used by all bits of GUI code that need to repeat some code
|
||||
// for a variety of types (to avoid duplicating the list of types). Just do
|
||||
// #define TYPE(T) your_code_involving_T;
|
||||
// #include "GUItypes.h"
|
||||
// #undef TYPE
|
||||
//
|
||||
// If you want to exclude a particular type, define e.g. GUITYPE_IGNORE_CStr
|
||||
#if 0
|
||||
=pod /* (These C++ comments in Perl code are to please my syntax highlighter)
|
||||
|
||||
// File generated by:
|
||||
// perl -e"print qq{#ifndef GUITYPE_IGNORE_$_\nTYPE($_)\n#endif\n} for qw(bool int float CColor CClientArea CGUIString CGUISpriteInstance CStr CStrW EAlign EVAlign)"
|
||||
|
||||
This file is used by all bits of GUI code that need to repeat some code
|
||||
for a variety of types (to avoid repeating the list of types in half a dozen
|
||||
places, and to make it much easier to add a new type). Just do
|
||||
#define TYPE(T) your_code_involving_T;
|
||||
#include "GUItypes.h"
|
||||
#undef TYPE
|
||||
to handle every possible type.
|
||||
|
||||
If you want to exclude a particular type, define e.g. GUITYPE_IGNORE_CStr
|
||||
|
||||
To alter this file, adjust the types in the indented list below, then run
|
||||
"perl GUITypes.h" to regenerate it. (Or if you want to do it manually, make
|
||||
sure you update the four mentions of each typename in this file.)
|
||||
|
||||
|
||||
=cut */
|
||||
|
||||
my @types = qw(
|
||||
|
||||
|
||||
bool
|
||||
int
|
||||
float
|
||||
CColor
|
||||
CClientArea
|
||||
CGUIString
|
||||
CGUISpriteInstance
|
||||
CStr
|
||||
CStrW
|
||||
EAlign
|
||||
EVAlign
|
||||
CPos
|
||||
|
||||
|
||||
);
|
||||
|
||||
#// Extract everything from this file, above the /********/ line
|
||||
open IN, $0 or die "Error opening $0: $!";
|
||||
my $out = '';
|
||||
while (<IN>)
|
||||
{
|
||||
last if $_ eq "/********/\n";
|
||||
$out .= $_;
|
||||
}
|
||||
$out .= "/********/\n";
|
||||
$out .= "#ifndef GUITYPE_IGNORE_$_\nTYPE($_)\n#endif\n" for @types;
|
||||
|
||||
#// and some minor hacks to make autocompleting things happier:
|
||||
$out .= "#ifdef PLEASE_DO_NOT_DEFINE_THIS\n// See IGUIObject.h for 'enum EGUISettingType'\nenum {" . (join ',', map "GUIST_$_", @types) . "};\n#endif";
|
||||
|
||||
#// Overwrite the current program with the newly-generated contents
|
||||
close IN;
|
||||
open OUT, ">$0" or die "Error opening >$0: $!"; #// TODO: Find whether it's safe for a program to overwrite itself. (It seems to work, at least on Windows)
|
||||
print OUT $out;
|
||||
close OUT;
|
||||
|
||||
__END__
|
||||
#endif
|
||||
|
||||
|
||||
/********/
|
||||
#ifndef GUITYPE_IGNORE_bool
|
||||
TYPE(bool)
|
||||
#endif
|
||||
@ -42,3 +96,10 @@ TYPE(EAlign)
|
||||
#ifndef GUITYPE_IGNORE_EVAlign
|
||||
TYPE(EVAlign)
|
||||
#endif
|
||||
#ifndef GUITYPE_IGNORE_CPos
|
||||
TYPE(CPos)
|
||||
#endif
|
||||
#ifdef PLEASE_DO_NOT_DEFINE_THIS
|
||||
// See IGUIObject.h for 'enum EGUISettingType'
|
||||
enum {GUIST_bool,GUIST_int,GUIST_float,GUIST_CColor,GUIST_CClientArea,GUIST_CGUIString,GUIST_CGUISpriteInstance,GUIST_CStr,GUIST_CStrW,GUIST_EAlign,GUIST_EVAlign,GUIST_CPos};
|
||||
#endif
|
@ -147,6 +147,19 @@ bool __ParseString<CSize>(const CStr& Value, CSize &Output)
|
||||
return true;
|
||||
}
|
||||
|
||||
template <>
|
||||
bool __ParseString<CPos>(const CStr& Value, CPos &Output)
|
||||
{
|
||||
CSize temp;
|
||||
if (__ParseString<CSize>(Value, temp))
|
||||
{
|
||||
Output = CPos(temp);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
template <>
|
||||
bool __ParseString<EAlign>(const CStr &Value, EAlign &Output)
|
||||
{
|
||||
|
@ -31,7 +31,8 @@ gee@pyro.nu
|
||||
//--------------------------------------------------------
|
||||
// Includes / Compiler directives
|
||||
//--------------------------------------------------------
|
||||
#include "GUI.h"
|
||||
#include "GUIbase.h"
|
||||
#include "GUItext.h"
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "input.h" // just for EV_PASS
|
||||
@ -70,20 +71,12 @@ struct JSObject;
|
||||
* For use of later macros, all names should be GUIST_ followed
|
||||
* by the code name (case sensitive!).
|
||||
*/
|
||||
#define TYPE(T) GUIST_##T,
|
||||
enum EGUISettingType
|
||||
{
|
||||
GUIST_bool,
|
||||
GUIST_int,
|
||||
GUIST_float,
|
||||
GUIST_CColor,
|
||||
GUIST_CClientArea,
|
||||
GUIST_CGUIString,
|
||||
GUIST_CStr,
|
||||
GUIST_CStrW,
|
||||
GUIST_CGUISpriteInstance,
|
||||
GUIST_EAlign,
|
||||
GUIST_EVAlign
|
||||
#include "GUItypes.h"
|
||||
};
|
||||
#undef TYPE
|
||||
|
||||
/**
|
||||
* @author Gustav Larsson
|
||||
@ -135,6 +128,7 @@ class IGUIObject
|
||||
friend class CGUI;
|
||||
friend class CInternalCGUIAccessorBase;
|
||||
friend class IGUIScrollBar;
|
||||
friend class GUITooltip;
|
||||
|
||||
// Allow getProperty to access things like GetParent()
|
||||
friend JSBool JSI_IGUIObject::getProperty(JSContext* cx, JSObject* obj, jsval id, jsval* vp);
|
||||
@ -502,7 +496,7 @@ protected:
|
||||
/**
|
||||
* Settings pool, all an object's settings are located here
|
||||
* If a derived object has got more settings that the base
|
||||
* settings, it's becasue they have a new version of the
|
||||
* settings, it's because they have a new version of the
|
||||
* function SetupSettings().
|
||||
*
|
||||
* @see SetupSettings()
|
||||
|
@ -41,10 +41,12 @@ void IGUITextOwner::HandleMessage(const SGUIMessage &Message)
|
||||
// these. Although that is not certain, but one will have to manually
|
||||
// change it and disregard this function.
|
||||
// TODO Gee: (2004-09-07) Make sure this is all options that can affect the text.
|
||||
if (Message.value == CStr("size") || Message.value == CStr("z") ||
|
||||
Message.value == CStr("absolute") || Message.value == CStr("caption") ||
|
||||
Message.value == CStr("font") || Message.value == CStr("textcolor") ||
|
||||
Message.value == CStr("buffer-zone"))
|
||||
// Also TODO: If several things are changing (e.g. when loading the file),
|
||||
// only call SetupText once (probably just before it's drawn)
|
||||
if (Message.value == "size" || Message.value == "z" ||
|
||||
Message.value == "absolute" || Message.value == "caption" ||
|
||||
Message.value == "font" || Message.value == "textcolor" ||
|
||||
Message.value == "buffer-zone")
|
||||
{
|
||||
SetupText();
|
||||
}
|
||||
|
@ -32,6 +32,8 @@ CMiniMap::CMiniMap()
|
||||
m_UnitManager(0)
|
||||
{
|
||||
AddSetting(GUIST_CColor, "fov-wedge-color");
|
||||
AddSetting(GUIST_CStr, "tooltip");
|
||||
AddSetting(GUIST_CStr, "tooltip-style");
|
||||
}
|
||||
|
||||
CMiniMap::~CMiniMap()
|
||||
@ -189,12 +191,12 @@ void CMiniMap::Destroy()
|
||||
/*
|
||||
* Calefaction
|
||||
* TODO: Speed this up. There has to be some mathematical way to make
|
||||
* this more effecient. This works for now.
|
||||
* this more efficient. This works for now.
|
||||
*/
|
||||
CVector2D CMiniMap::GetMapSpaceCoords(CVector3D worldPos)
|
||||
{
|
||||
u32 x = (u32)(worldPos.X / CELL_SIZE);
|
||||
// Entities Z coordinate is really it's longitutinale coordinate on the terrain
|
||||
// Entity's Z coordinate is really its longitudinal coordinate on the terrain
|
||||
u32 y = (u32)(worldPos.Z / CELL_SIZE);
|
||||
|
||||
// Calculate map space scale
|
||||
|
@ -5,6 +5,9 @@
|
||||
#include "JSInterface_IGUIObject.h"
|
||||
#include "JSInterface_GUITypes.h"
|
||||
|
||||
#include "gui/IGUIObject.h"
|
||||
#include "gui/CGUI.h"
|
||||
|
||||
#include "ps/StringConvert.h"
|
||||
|
||||
JSClass JSI_IGUIObject::JSI_class = {
|
||||
|
@ -1,7 +1,6 @@
|
||||
// $Id$
|
||||
|
||||
#include "scripting/ScriptingHost.h"
|
||||
#include "gui/GUI.h"
|
||||
|
||||
#ifndef JSI_IGUIOBJECT_INCLUDED
|
||||
#define JSI_IGUIOBJECT_INCLUDED
|
||||
|
@ -36,7 +36,10 @@ I18n::StringBuffer::operator Str()
|
||||
}
|
||||
|
||||
if (String.VarCount == 0)
|
||||
if (String.Parts.size())
|
||||
return String.Parts[0]->ToString(Locale, Variables).str();
|
||||
else
|
||||
return Str();
|
||||
|
||||
Str ret;
|
||||
|
||||
|
@ -231,6 +231,10 @@ CPos::CPos() : x(0.f), y(0.f)
|
||||
{
|
||||
}
|
||||
|
||||
CPos::CPos(const CSize& s) : x(s.cx), y(s.cy)
|
||||
{
|
||||
}
|
||||
|
||||
CPos::CPos(const float &_x, const float &_y) : x(_x), y(_y)
|
||||
{
|
||||
}
|
||||
|
@ -147,6 +147,7 @@ class CPos
|
||||
{
|
||||
public:
|
||||
CPos();
|
||||
CPos(const CSize &pos);
|
||||
CPos(const float &_x, const float &_y);
|
||||
|
||||
// Operators
|
||||
|
@ -15,6 +15,8 @@
|
||||
#include "Network/Server.h"
|
||||
#include "Network/Client.h"
|
||||
|
||||
#include "gui/CGUI.h"
|
||||
|
||||
#include "ps/i18n.h"
|
||||
|
||||
#include "scripting/JSInterface_Entity.h"
|
||||
|
Loading…
Reference in New Issue
Block a user