Add a new GUI2 tooltip.

The placement of tooltip is controlled by the WML of the GUI engine. The
code is not used yet, only available with a proof-of-concept define named
DEBUG_TOOLTIP.
This commit is contained in:
Mark de Wever 2014-02-08 18:26:10 +01:00
parent 8ff55378cc
commit 5da495122a
7 changed files with 354 additions and 0 deletions

View file

@ -3,6 +3,7 @@ Version 1.11.9+dev:
* Updated translations:
* GUI2
* Added: FAI-function handling in GUI2 widgets.
* Added: A new tooltip window.
* Miscellaneous and bug fixes:
* Fixed: A compilation warning with DEBUG_WINDOW_LAYOUT_GRAPHS.

View file

@ -1,6 +1,11 @@
#textdomain wesnoth-lib
###
### Definition of the window used to show large tooltips.
### The placement algorithms used are described in the
### »Tooltip placement« section in the GUI2 design document.
###
### gui/dialogs/title_screen.cpp has test code, which is
### activated by defining the DEBUG_TOOLTIP macro.
###
[window]
@ -46,3 +51,188 @@
[/resolution]
[/window]
#define __GUI_WINDOW_HEIGHT
(
if(window_height = 0
# Determine the wanted maximum height. #
# The value should be high enough to avoid an #
# unable to place exception. #
, 100000
# Determine the height to use. #
, window_height)
)#enddef
#define __GUI_WINDOW_FUNCTIONS
def placement_method(m, w, s)
(
if((w.y > s.y) or ((w.x * 2) > s.x)
, 'V'
, if(m.y >= w.y
, if(m.x >= w.x, 'I', 'III')
, if(m.x >= w.x, 'II', 'IV')
)
)
);
def set_x(m, w, s)
(
[
switch(
placement_method(m, w, s)
, 'I' , m.x - w.x
, 'II' , m.x - w.x
, 'III' , 5
# extra offset to avoid being obscured by the mouse. #
, 'IV' , m.x + 15
, 'V' , 5
, #default# m.x
),
#
debug_print('placement_method, mouse ', m),
debug_print('window ', w),
debug_print('screen ', s),
debug_print('y margin', s.y - (m.y + w.y)),
debug_print('result ', placement_method(m, w, s)),
#
][0]
);
def set_y(m, w, s)
(
switch(
placement_method(m, w, s)
, 'I' , m.y - w.y
, 'II' , 5
, 'III' , m.y - w.y
, 'IV' , 5
, 'V' , 5
, #default# m.y - w.y
)
);
def get_maximum_width(w, s)
(
if(w.x = 0
# The default width upon the initial run. #
, 160
, if(w.y <= s.y
# If the window's height fits use that. #
, w.x
# Else use an increased width, which should reduce #
# the required height. #
, 2 * w.x))
);
def set_w(r, w, s)
(
switch(
r
, 'maximum', get_maximum_width(w, s)
, 'size', w.x
)
);
def reevaluate_best_size(w, s)
(
[
w.y > s.y,
#
debug_print('window ', w),
debug_print('screen ', s)
#
][0]
);
#enddef
#define __GUI_WINDOW_X
(
set_x(
loc(mouse_x, mouse_y)
, loc(window_width, window_height)
, loc(screen_width, screen_height))
)
#enddef
#define __GUI_WINDOW_Y
(
set_y(
loc(mouse_x, mouse_y)
, loc(window_width, window_height)
, loc(screen_width, screen_height))
)#enddef
#define __GUI_WINDOW_WIDTH
(
set_w(
size_request_mode
, loc(window_width, window_height)
, loc(screen_width, screen_height))
)#enddef
#define __GUI_WINDOW_REEVALUATE_BEST_SIZE
(
reevaluate_best_size(
loc(window_width, window_height)
, loc(screen_width, screen_height))
)#enddef
[window]
id = "tooltip"
description = "The tooltip popup window with large tooltips, eg in the main menu."
[resolution]
definition = "tooltip_large"
automatic_placement = "false"
functions = "{__GUI_WINDOW_FUNCTIONS}"
x = "{__GUI_WINDOW_X}"
y = "{__GUI_WINDOW_Y}"
width = "{__GUI_WINDOW_WIDTH}"
height = "{__GUI_WINDOW_HEIGHT}"
reevaluate_best_size = "{__GUI_WINDOW_REEVALUATE_BEST_SIZE}"
# TODO tooltips in this window make little sense.
# Have to think of a nice solution.
[tooltip]
id = "tooltip"
[/tooltip]
[helptip]
id = "tooltip"
[/helptip]
[grid]
[row]
[column]
[label]
id = "label"
definition = "default"
wrap = "true"
[/label]
[/column]
[/row]
[/grid]
[/resolution]
[/window]
#undef __GUI_WINDOW_REEVALUATE_BEST_SIZE
#undef __GUI_WINDOW_HEIGHT
#undef __GUI_WINDOW_WIDTH
#undef __GUI_WINDOW_Y
#undef __GUI_WINDOW_X
#undef __GUI_WINDOW_FUNCTIONS

View file

@ -21,6 +21,7 @@ if(ENABLE_DESIGN_DOCUMENTS)
gui2/introduction.tex
gui2/overall_design.tex
gui2/design_details.tex
gui2/design_details/tooltip_placement.tex
gui2/creating_widgets_and_dialogs.tex
gui2/files_for_the_widget.tex
gui2/files_for_the_window.tex

View file

@ -6,6 +6,10 @@
\usepackage{lmodern}
\usepackage[colorlinks]{hyperref}
\usepackage{enumerate}
\usepackage[section]{placeins}
\usepackage{tikz}
\usetikzlibrary{positioning,shapes.geometric}
\usepackage{verbatim}
\usepackage{gui2}

View file

@ -180,3 +180,4 @@ Subclasses of the tnotifier should add an notification function, so the notifier
can call all callbacks in the list. The notifier should take care of this
calling.
\input{gui2/design_details/tooltip_placement}

View file

@ -0,0 +1,116 @@
\section{Tooltip placement}
\label{sec:tooltip_placement}
The placement of the GUI2 tooltips are handled by the tooltip window. This
window needs to determine where it wants the tooltip to be placed, and
determine its optimal size.
\begin{description}
\item[\cref{sec:tooltip_placement:normal}]
Shows the how normal tooltips look in the game window.
\item[\cref{sec:tooltip_placement:large}]
Shows the how large tooltips look in the game window.
\item[\cref{sec:tooltip_placement:huge}]
Shows the how huge tooltips look in the game window.
\end{description}
\subsection{Normal}
\label{sec:tooltip_placement:normal}
This tooltip has a single line of text and the width of the tooltip is below or
equal to the wanted width of the tooltip. The wanted width of the tooltip is
determined by a size where the line-length of the text is pleasant to read.
Or the tooltip has either a end of line character, causing it to be spread
over several lines, or its text is too long for the wanted width, causing it to
be wrapped. The text's height will still fit on the screen.
\Cref{fig:tooltip_placement} gives a visual representation of the placement
algorithms used. The algorithms used are:
\begin{enumerate}[I.]
\item\label{sec:tooltip_placement:algorithm:I}
This is the preferred placement of the tooltip. The lower right corner of
the tooltip is attached to the top left of the mouse pointer.
\item\label{sec:tooltip_placement:algorithm:II}
This is used when the mouse \mbox{x-position} is greater than the width of
the tooltip window, but the mouse \mbox{y-position} is smaller than the
height of the tooltip window. The top of the tooltip is attached to the top
of the screen at the left side of the mouse pointer.
\item\label{sec:tooltip_placement:algorithm:III}
This is used when the mouse \mbox{x-position} is smaller than the width of
the tooltip window, but the mouse \mbox{x-position} is greater than the
height of the tooltip window. The left side of the tooltip is attached to
the left side of the screen at the top of the mouse pointer.
\item\label{sec:tooltip_placement:algorithm:IV}
This is used when the mouse \mbox{x-position} is smaller than the width of
the tooltip window, and the mouse \mbox{y-position} is smaller than the
height of the tooltip window. The top of the tooltip is attached to the top
of the screen at the right side of the mouse pointer.
\end{enumerate}
\begin{figure}[tbh]
\centering\begin{tikzpicture}[
x=0.0008\textwidth
, y=0.0008\textwidth
, pointer/.style={dart, draw=black, rotate=120, anchor=tip, fill=gray!60}
, shadow/.style={dart, draw=black!40, rotate=120, anchor=tip, fill=gray!15}
, tooltip/.style={draw=black, minimum width=100, minimum height=50}
]
\draw (0,0) rectangle (1200, 800);
% pointer size 55 x 75
\node[pointer] at (1135, 80) {};
\node[tooltip, anchor=south east] at (1135, 80) {Algorithm I};
\node[shadow] at (1135, 795) {};
\node[pointer] at (1135, 725) {};
\node[shadow] at (1135, 615) {};
\node[tooltip, anchor=north east] at (1135, 795) {Algorithm II};
\node[shadow] at (5, 80) {};
\node[pointer] at (155, 80) {};
\node[shadow] at (370, 80) {};
\node[tooltip, anchor=south west] at (5, 80) {Algorithm III};
\node[shadow] at (5, 795) {};
\node[pointer] at (5, 725) {};
\node[shadow] at (5, 615) {};
\node[tooltip, anchor=north west] at (70, 795) {Algorithm III};
\end{tikzpicture}
\caption{Overview of the tooltip placement.}
\label{fig:tooltip_placement}
\end{figure}
\subsection{Large}
\label{sec:tooltip_placement:large}
This tooltip needs so much space that its height no longer fits on the
screen. In this case the width will be increased. There is no guarantee the
tooltip will fit properly; the creator of the tooltip should consider
whether or not it contains too much information. Once the width is adjusted the
placement algorithm used it the same as for the normal tooltip, see
\cref{sec:tooltip_placement:normal}.
\subsection{Huge}
\label{sec:tooltip_placement:huge}
The tooltip will certainly not fit nicely on the screen and no attempt is
made to even try to do something sane. Instead it is placed in the top left
corner. Unless a very small screen resolution is used the creator of the
tooltip really needs to consider reducing the amount of text on the tooltip.
There is no guarantee the entire tooltip is visible.

View file

@ -26,6 +26,10 @@
#include "gui/auxiliary/tips.hpp"
#include "gui/dialogs/debug_clock.hpp"
#include "gui/dialogs/language_selection.hpp"
//#define DEBUG_TOOLTIP
#ifdef DEBUG_TOOLTIP
#include "gui/dialogs/tip.hpp"
#endif
#include "gui/widgets/button.hpp"
#include "gui/widgets/label.hpp"
#include "gui/widgets/multi_page.hpp"
@ -277,6 +281,37 @@ void ttitle_screen::post_build(CVideo& video, twindow& window)
, QUIT_GAME));
}
#ifdef DEBUG_TOOLTIP
static void debug_tooltip(
twindow& window
, bool& handled
, const tpoint& coordinate)
{
std::string message = "Hello world.";
/*
* This function is used to test the tooltip placement algorithms as
* described in the »Tooltip placement« section in the GUI2 design
* document.
*
* Use a 1024 x 768 screen size, set the maximum loop iteration to:
* - 0 to test with a normal tooltip placement.
* - 30 to test with a larger normal tooltip placement.
* - 60 to test with a huge tooltip placement.
* - 150 to test with a borderline to insanely huge tooltip placement.
* - 180 to test with an insanely huge tooltip placement.
*/
for(int i = 0; i < 0; ++i) {
message += " More greetings.";
}
gui2::tip::remove();
gui2::tip::show(window.video()
, "tooltip"
, message
, coordinate);
handled = true;
}
#endif
void ttitle_screen::pre_show(CVideo& video, twindow& window)
{
set_restore(false);
@ -284,6 +319,12 @@ void ttitle_screen::pre_show(CVideo& video, twindow& window)
window.set_enter_disabled(true);
window.set_escape_disabled(true);
#ifdef DEBUG_TOOLTIP
window.connect_signal<event::SDL_MOUSE_MOTION>(
boost::bind(debug_tooltip, boost::ref(window), _3, _5)
, event::tdispatcher::front_child);
#endif
/**** Set the version number ****/
if(tcontrol* control
= find_widget<tcontrol>(&window, "revision_number", false, false)) {