warzone2100/lib/widget/tip.cpp

200 lines
5.3 KiB
C++

/*
This file is part of Warzone 2100.
Copyright (C) 1999-2004 Eidos Interactive
Copyright (C) 2005-2013 Warzone 2100 Project
Warzone 2100 is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
Warzone 2100 is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Warzone 2100; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/** @file
* The tool tip display system.
*/
#include "lib/framework/frame.h"
#include "lib/framework/wzapp.h"
#include "lib/framework/frameint.h"
#include "widget.h"
#include "widgint.h"
#include "tip.h"
// FIXME Direct iVis implementation include!
#include "lib/ivis_opengl/pieblitfunc.h"
#include <QtCore/QStringList>
/* Time delay before showing the tool tip */
#define TIP_PAUSE 200
/* How long to display the tool tip */
#define TIP_TIME 4000
/* Size of border around tip text */
#define TIP_HGAP 6
#define TIP_VGAP 3
/* The tool tip state */
static enum _tip_state
{
TIP_NONE, // No tip, and no button hilited
TIP_WAIT, // A button is hilited, but not yet ready to show the tip
TIP_ACTIVE, // A tip is being displayed
} tipState;
static SDWORD startTime; // When the tip was created
static SDWORD mx, my; // Last mouse coords
static SDWORD wx, wy, ww, wh; // Position and size of button to place tip by
static SDWORD tx, ty, tw, th; // Position and size of the tip box
static SDWORD fx, fy; // Position of the text
static int lineHeight;
static QStringList pTip; // Tip text
static WIDGET *psWidget; // The button the tip is for
static enum iV_fonts FontID = font_regular; // ID for the Ivis Font.
static PIELIGHT TipColour;
/* Initialise the tool tip module */
void tipInitialise(void)
{
tipState = TIP_NONE;
TipColour = WZCOL_WHITE;
}
// Set the global toop tip text colour.
void widgSetTipColour(PIELIGHT colour)
{
TipColour = colour;
}
/*
* Setup a tool tip.
* The tip module will then wait until the correct points to
* display and then remove the tool tip.
* i.e. The tip will not be displayed immediately.
* Calling this while another tip is being displayed will restart
* the tip system.
* psSource is the widget that started the tip.
* x,y,width,height - specify the position of the button to place the
* tip by.
*/
void tipStart(WIDGET *psSource, QString pNewTip, iV_fonts NewFontID, int x, int y, int width, int height)
{
ASSERT(psSource != NULL, "Invalid widget pointer");
tipState = TIP_WAIT;
startTime = wzGetTicks();
mx = mouseX();
my = mouseY();
wx = x; wy = y;
ww = width; wh = height;
pTip = pNewTip.split('\n');
psWidget = psSource;
FontID = NewFontID;
}
/* Stop a tool tip (e.g. if the hilite is lost on a button).
* psSource should be the same as the widget that started the tip.
*/
void tipStop(WIDGET *psSource)
{
ASSERT(psSource != NULL,
"tipStop: Invalid widget pointer");
if (tipState != TIP_NONE && psSource == psWidget)
{
tipState = TIP_NONE;
}
}
/* Update and possibly display the tip */
void tipDisplay()
{
SDWORD newMX, newMY;
SDWORD currTime;
SDWORD fw, topGap;
switch (tipState)
{
case TIP_WAIT:
/* See if the tip has to be shown */
newMX = mouseX();
newMY = mouseY();
currTime = wzGetTicks();
if (newMX == mx &&
newMY == my &&
(currTime - startTime > TIP_PAUSE))
{
/* Activate the tip */
tipState = TIP_ACTIVE;
/* Calculate the size of the tip box */
topGap = TIP_VGAP;
iV_SetFont(FontID);
lineHeight = iV_GetTextLineSize();
fw = 0;
for (int n = 0; n < pTip.size(); ++n)
{
fw = std::max<int>(fw, iV_GetTextWidth(pTip[n].toUtf8().constData()));
}
tw = fw + TIP_HGAP * 2;
th = topGap * 2 + lineHeight*pTip.size() + iV_GetTextBelowBase();
/* Position the tip box */
tx = clip(wx + ww/2, 0, screenWidth - tw - 1);
ty = std::max(wy + wh + TIP_VGAP, 0);
if (ty + th >= (int)screenHeight)
{
/* Position the tip above the button */
ty = wy - th - TIP_VGAP;
}
/* Position the text */
fx = tx + TIP_HGAP;
fy = ty + (th - lineHeight*pTip.size()) / 2 - iV_GetTextAboveBase();
/* Note the time */
startTime = wzGetTicks();
}
else if (newMX != mx ||
newMY != my ||
mousePressed(MOUSE_LMB))
{
mx = newMX;
my = newMY;
startTime = currTime;
}
break;
case TIP_ACTIVE:
/* Draw the tool tip */
pie_BoxFill(tx, ty, tx + tw, ty + th, WZCOL_FORM_TIP_BACKGROUND);
iV_Line(tx + 1, ty + th - 2, tx + 1, ty + 1, WZCOL_FORM_DARK);
iV_Line(tx + 2, ty + 1, tx + tw - 2, ty + 1, WZCOL_FORM_DARK);
iV_Line(tx, ty + th, tx + tw, ty + th, WZCOL_FORM_DARK);
iV_Line(tx + tw, ty + th - 1, tx + tw, ty, WZCOL_FORM_DARK);
iV_Box(tx, ty, tx + tw - 1, ty + th - 1, WZCOL_FORM_LIGHT);
iV_SetFont(FontID);
iV_SetTextColour(TipColour);
for (int n = 0; n < pTip.size(); ++n)
{
iV_DrawText(pTip[n].toUtf8().constData(), fx, fy + lineHeight*n);
}
break;
default:
break;
}
}