[Add] Gui Tooltips.

[Clean] Cleaned up GUI::Screen.
This commit is contained in:
Rtch90 2018-04-14 19:30:27 +01:00
parent b32409dfb1
commit fecd2866f5
24 changed files with 381 additions and 82 deletions

View File

@ -6,13 +6,13 @@ noinst_LIBRARIES = libgui.a
include_HEADERS = body.h frame.h generic_system_view.h glfreetype.h gui_button.h gui_container.h gui_events.h gui_fixed.h \ include_HEADERS = body.h frame.h generic_system_view.h glfreetype.h gui_button.h gui_container.h gui_events.h gui_fixed.h \
gui.h gui_image_button.h gui_image.h gui_image_radio_button.h gui_label.h gui_multi_state_image_button.h gui_radio_button.h \ gui.h gui_image_button.h gui_image.h gui_image_radio_button.h gui_label.h gui_multi_state_image_button.h gui_radio_button.h \
gui_radio_group.h gui_screen.h gui_toggle_button.h gui_widget.h libs.h matrix4x4.h mtrand.h l3d.h \ gui_radio_group.h gui_screen.h gui_toggle_button.h gui_widget.h gui_tooltip.h libs.h matrix4x4.h mtrand.h l3d.h \
planet.h player.h dynamic_body.h sector.h sector_view.h ship_cpanel.h ship.h space.h star.h star_system.h system_info_view.h \ planet.h player.h dynamic_body.h sector.h sector_view.h ship_cpanel.h ship.h space.h star.h star_system.h system_info_view.h \
system_view.h vector3.h view.h world_view.h date.h space_station.h space_station_view.h model_body.h gui_iselectable.h \ system_view.h vector3.h view.h world_view.h date.h space_station.h space_station_view.h model_body.h gui_iselectable.h \
ship_type.h object.h info_view.h model_coll_mesh_data.h object_viewer_view.h fixed.h custom_starsystems.h gameconsts.h \ ship_type.h object.h info_view.h model_coll_mesh_data.h object_viewer_view.h fixed.h custom_starsystems.h gameconsts.h \
aabb.h serializer.h sfx.h aabb.h serializer.h sfx.h
libgui_a_SOURCES = gui_button.cpp gui.cpp gui_fixed.cpp gui_screen.cpp gui_label.cpp gui_toggle_button.cpp gui_radio_button.cpp \ libgui_a_SOURCES = gui_button.cpp gui.cpp gui_fixed.cpp gui_screen.cpp gui_label.cpp gui_tooltip.cpp gui_toggle_button.cpp gui_radio_button.cpp \
gui_radio_group.cpp gui_image_button.cpp gui_image.cpp gui_image_radio_button.cpp gui_multi_state_image_button.cpp gui_widget.cpp \ gui_radio_group.cpp gui_image_button.cpp gui_image.cpp gui_image_radio_button.cpp gui_multi_state_image_button.cpp gui_widget.cpp \
gui_container.cpp gui_container.cpp

View File

@ -283,6 +283,22 @@ void FontFace::RenderGlyph(int chr) {
glDrawElements(GL_TRIANGLES, glyph->numidx, GL_UNSIGNED_SHORT, glyph->iarray); glDrawElements(GL_TRIANGLES, glyph->numidx, GL_UNSIGNED_SHORT, glyph->iarray);
} }
void FontFace::MeasureString(const char* str, float& w, float& h) {
w = 0;
h = GetHeight();
float line_width = 0;
for(unsigned int i = 0; i < strlen(str); i++) {
if(str[i] == '\n') {
if(line_width > w) w = line_width;
line_width = 0;
h += GetHeight();
} else {
line_width += m_glyphs[str[i]].advx;
}
}
if(line_width > w) w = line_width;
}
void FontFace::RenderString(const char* str) { void FontFace::RenderString(const char* str) {
glPushMatrix(); glPushMatrix();
for(unsigned int i = 0; i < strlen(str); i++) { for(unsigned int i = 0; i < strlen(str); i++) {

View File

@ -8,6 +8,7 @@ public:
void RenderGlyph(int chr); void RenderGlyph(int chr);
void RenderString(const char* str); void RenderString(const char* str);
void RenderMarkup(const char* str); void RenderMarkup(const char* str);
void MeasureString(const char* str, float& w, float& h);
/* Of Ms. */ /* Of Ms. */
float GetHeight(void) { return m_height; } float GetHeight(void) { return m_height; }

View File

@ -3,6 +3,7 @@
namespace Gui { namespace Gui {
namespace RawEvents { namespace RawEvents {
sigc::signal<void, SDL_MouseMotionEvent*> onMouseMotion;
sigc::signal<void, SDL_MouseButtonEvent*> onMouseDown; sigc::signal<void, SDL_MouseButtonEvent*> onMouseDown;
sigc::signal<void, SDL_MouseButtonEvent*> onMouseUp; sigc::signal<void, SDL_MouseButtonEvent*> onMouseUp;
sigc::signal<void, SDL_KeyboardEvent*> onKeyDown; sigc::signal<void, SDL_KeyboardEvent*> onKeyDown;
@ -31,10 +32,53 @@ void HandleSDLEvent(SDL_Event* event) {
case SDL_KEYUP: case SDL_KEYUP:
RawEvents::onKeyUp.emit(&event->key); RawEvents::onKeyUp.emit(&event->key);
break; break;
case SDL_MOUSEMOTION:
Screen::OnMouseMotion(&event->motion);
RawEvents::onMouseMotion.emit(&event->motion);
break;
}
}
struct TimerSignal {
Uint32 goTime;
sigc::signal<void>* sig;
};
static std::list<TimerSignal> g_timeSignals;
void AddTimer(Uint32 ms, sigc::signal<void>* s) {
TimerSignal _s;
_s.goTime = SDL_GetTicks() + ms;
_s.sig = s;
g_timeSignals.push_back(_s);
}
void RemoveTimer(sigc::signal<void>* s) {
for(std::list<TimerSignal>::iterator i = g_timeSignals.begin();
i!= g_timeSignals.end();) {
if((*i).sig == s)
i = g_timeSignals.erase(i);
else ++i;
}
}
static void ExpireTimers(Uint32 t) {
for(std::list<TimerSignal>::iterator i = g_timeSignals.begin();
i != g_timeSignals.end();) {
if(t >= (*i).goTime)
i = g_timeSignals.erase(i);
else ++i;
} }
} }
void Draw(void) { void Draw(void) {
Uint32 t = SDL_GetTicks();
/* Let's abuse it like an update() function also.. */
for(std::list<TimerSignal>::iterator i = g_timeSignals.begin(); i != g_timeSignals.end(); ++i) {
if(t >= (*i).goTime)(*i).sig->emit();
}
ExpireTimers(t);
Screen::Draw(); Screen::Draw();
} }

View File

@ -9,6 +9,8 @@
void HandleSDLEvent(SDL_Event* event); void HandleSDLEvent(SDL_Event* event);
void Draw(void); void Draw(void);
void AddTimer(Uint32 ms, sigc::signal<void>* s);
void RemoveTimer(sigc::signal<void>* s);
void Init(int screen_width, int screen_height, int ui_width, int ui_height); void Init(int screen_width, int screen_height, int ui_width, int ui_height);
} }
@ -35,5 +37,6 @@ namespace Gui {
#include "gui_radio_group.h" #include "gui_radio_group.h"
#include "gui_fixed.h" #include "gui_fixed.h"
#include "gui_label.h" #include "gui_label.h"
#include "gui_tooltip.h"
#include "gui_screen.h" #include "gui_screen.h"

View File

@ -7,7 +7,7 @@ namespace Gui {
Button::Button(void) { Button::Button(void) {
m_isPressed = false; m_isPressed = false;
m_eventMask = EVENT_MOUSEDOWN | EVENT_MOUSEUP; m_eventMask = EVENT_MOUSEDOWN | EVENT_MOUSEUP | EVENT_MOUSEMOTION;
SetSize(BUTTON_SIZE, BUTTON_SIZE); SetSize(BUTTON_SIZE, BUTTON_SIZE);
} }

View File

@ -3,6 +3,38 @@
namespace Gui { namespace Gui {
bool Container::OnMouseMotion(MouseMotionEvent* e) {
float x = e->x;
float y = e->y;
for(std::list<widget_pos>::iterator i = m_children.begin(); i != m_children.end(); ++i) {
float pos[2],size[2];
if(!(*i).w->IsVisible()) {
if((*i).w->IsMouseOver() == true)
(*i).w->OnMouseLeave();
continue;
}
int evmask = (*i).w->GetEventMask();
if(!(evmask & Widget::EVENT_MOUSEMOTION)) continue;
(*i).w->GetPosition(pos);
(*i).w->GetSize(size);
if((x >= pos[0]) && (x < pos[0]+size[0]) &&
(y >= pos[1]) && (y < pos[1]+size[1])) {
e->x = x-pos[0];
e->y = y-pos[1];
if((*i).w->IsMouseOver() == false) {
(*i).w->OnMouseEnter();
}
bool alive = (*i).w->OnMouseMotion(e);
if(!alive) return false;
} else {
if((*i).w->IsMouseOver() == true)
(*i).w->OnMouseLeave();
}
}
return true;
}
bool Container::HandleMouseEvent(MouseButtonEvent* e) { bool Container::HandleMouseEvent(MouseButtonEvent* e) {
float x = e->x; float x = e->x;

View File

@ -9,6 +9,7 @@ namespace Gui {
public: public:
bool OnMouseDown(MouseButtonEvent* e); bool OnMouseDown(MouseButtonEvent* e);
bool OnMouseUp(MouseButtonEvent* e); bool OnMouseUp(MouseButtonEvent* e);
bool OnMouseMotion(MouseMotionEvent* e);
void DeleteAllChildren(void); void DeleteAllChildren(void);
virtual void Draw(void); virtual void Draw(void);
virtual void ShowAll(void); virtual void ShowAll(void);

View File

@ -6,5 +6,9 @@ namespace Gui {
float x, y; /* Widget coords. */ float x, y; /* Widget coords. */
float screenX, screenY; /* Screen coords. */ float screenX, screenY; /* Screen coords. */
}; };
struct MouseMotionEvent {
float x, y; /* Widget coords. */
float screenX, screenY; /* Screen coords. */
};
} }

View File

@ -7,7 +7,7 @@ Fixed::Fixed(float w, float h) {
SetSize(w, h); SetSize(w, h);
memcpy(m_bgcol, Color::bg, 3*sizeof(float)); memcpy(m_bgcol, Color::bg, 3*sizeof(float));
m_w = w; m_h = h; m_w = w; m_h = h;
m_transparent = false; m_transparent = true;
m_eventMask = EVENT_ALL; m_eventMask = EVENT_ALL;
} }

View File

@ -12,12 +12,20 @@ Label::Label(std::string& text) {
m_color[0] = m_color[1] = m_color[2] = 1.0f; m_color[0] = m_color[1] = m_color[2] = 1.0f;
} }
void Label::RecalcSize(void) {
float w, h;
Screen::MeasureString(m_text, w, h);
SetSize(w,h);
}
void Label::SetText(const char* text) { void Label::SetText(const char* text) {
m_text = text; m_text = text;
RecalcSize();
} }
void Label::SetText(std::string& text) { void Label::SetText(std::string& text) {
m_text = text; m_text = text;
RecalcSize();
} }
void Label::Draw(void) { void Label::Draw(void) {
@ -26,9 +34,8 @@ void Label::Draw(void) {
} }
void Label::GetSizeRequested(float size[2]) { void Label::GetSizeRequested(float size[2]) {
#pragma message("Not setting size correctly.") RecalcSize();
size[0] = 70; GetSize(size);
size[1] = 10;
} }
void Label::SetColor(float r, float g, float b) { void Label::SetColor(float r, float g, float b) {

View File

@ -14,6 +14,7 @@ namespace Gui {
void SetText(std::string& text); void SetText(std::string& text);
void SetColor(float r, float g, float b); void SetColor(float r, float g, float b);
private: private:
void RecalcSize(void);
std::string m_text; std::string m_text;
float m_color[3]; float m_color[3];
}; };

View File

@ -18,11 +18,13 @@ MultiStateImageButton::~MultiStateImageButton(void) {
void MultiStateImageButton::StateNext(void) { void MultiStateImageButton::StateNext(void) {
m_curState++; m_curState++;
if(m_curState >= (signed)m_states.size()) m_curState = 0; if(m_curState >= (signed)m_states.size()) m_curState = 0;
UpdateOverriddenTooltip();
} }
void MultiStateImageButton::StatePrev(void) { void MultiStateImageButton::StatePrev(void) {
m_curState--; m_curState--;
if(m_curState < 0) m_curState = (signed)m_states.size()-1; if(m_curState < 0) m_curState = (signed)m_states.size()-1;
UpdateOverriddenTooltip();
} }
void MultiStateImageButton::OnActivate(void) { void MultiStateImageButton::OnActivate(void) {
@ -49,14 +51,23 @@ void MultiStateImageButton::Draw(void) {
} }
void MultiStateImageButton::AddState(int state, const char* filename) { void MultiStateImageButton::AddState(int state, const char* filename) {
AddState(state, filename, "");
}
void MultiStateImageButton::AddState(int state, const char* filename, std::string tooltip) {
State s; State s;
s.state = state; s.state = state;
s.image = new Image(filename); s.image = new Image(filename);
s.tooltip = tooltip;
m_states.push_back(s); m_states.push_back(s);
float size[2]; float size[2];
s.image->GetSizeRequested(size); s.image->GetSizeRequested(size);
SetSize(size[0], size[1]); SetSize(size[0], size[1]);
} }
std::string MultiStateImageButton::GetOverrideTooltip(void) {
return m_states[m_curState].tooltip;
}
} }

View File

@ -12,16 +12,20 @@ namespace Gui {
virtual ~MultiStateImageButton(void); virtual ~MultiStateImageButton(void);
virtual void GetSizeRequested(float size[2]); virtual void GetSizeRequested(float size[2]);
void AddState(int state, const char* filename); void AddState(int state, const char* filename);
void AddState(int state, const char* filename, std::string tooltip);
int GetState(void) { return m_states[m_curState].state; } int GetState(void) { return m_states[m_curState].state; }
void StateNext(void); void StateNext(void);
void StatePrev(void); void StatePrev(void);
virtual void OnActivate(void); virtual void OnActivate(void);
sigc::signal<void, MultiStateImageButton*> onClick; sigc::signal<void, MultiStateImageButton*> onClick;
virtual void SetSelected(bool state); virtual void SetSelected(bool state);
protected:
virtual std::string GetOverrideTooltip(void);
private: private:
struct State { struct State {
int state; int state;
Image* image; Image* image;
std::string tooltip;
}; };
std::vector<State> m_states; std::vector<State> m_states;
int m_curState; int m_curState;

View File

@ -11,11 +11,11 @@ int Screen::realWidth;
int Screen::realHeight; int Screen::realHeight;
float Screen::invRealWidth; float Screen::invRealWidth;
float Screen::invRealHeight; float Screen::invRealHeight;
std::list<Widget*> Screen::widgets;
std::list<Widget*> Screen::kbshortcut_widgets; std::list<Widget*> Screen::kbshortcut_widgets;
float Screen::font_xsize; float Screen::font_xsize;
float Screen::font_ysize; float Screen::font_ysize;
std::vector<Screen::LabelPos> Screen::labelPositions; std::vector<Screen::LabelPos> Screen::labelPositions;
Gui::Fixed* Screen::baseContainer;
void Screen::Init(int real_width, int real_height, int ui_width, int ui_height) { void Screen::Init(int real_width, int real_height, int ui_width, int ui_height) {
Screen::width = ui_width; Screen::width = ui_width;
@ -28,6 +28,8 @@ void Screen::Init(int real_width, int real_height, int ui_width, int ui_height)
Screen::font = new FontFace("font.ttf"); Screen::font = new FontFace("font.ttf");
Screen::font_xsize = 16*0.8; Screen::font_xsize = 16*0.8;
Screen::font_ysize = 16; Screen::font_ysize = 16;
Screen::baseContainer = new Gui::Fixed(Screen::width, Screen::height);
Screen::baseContainer->SetPosition(0,0);
} }
GLint Screen::Project(GLdouble objX, GLdouble objY, GLdouble objZ, const GLdouble* model, GLint Screen::Project(GLdouble objX, GLdouble objY, GLdouble objZ, const GLdouble* model,
@ -46,7 +48,6 @@ void Screen::EnterOrtho(void) {
glMatrixMode(GL_PROJECTION); glMatrixMode(GL_PROJECTION);
glPushMatrix(); glPushMatrix();
glLoadIdentity(); glLoadIdentity();
//glOrtho(9, 320, 0, 200, -1, 1);
glOrtho(0, width, 0, height, -1, 1); glOrtho(0, width, 0, height, -1, 1);
glMatrixMode(GL_MODELVIEW); glMatrixMode(GL_MODELVIEW);
glPushMatrix(); glPushMatrix();
@ -67,65 +68,43 @@ void Screen::Draw(void) {
labelPositions.clear(); labelPositions.clear();
EnterOrtho(); EnterOrtho();
for(std::list<Widget*>::iterator i = Screen::widgets.begin(); i != Screen::widgets.end(); ++i) { baseContainer->Draw();
if(!(*i)->IsVisible()) continue;
glPushMatrix();
float pos[2];
(*i)->GetPosition(pos);
glTranslatef(pos[0], pos[1], 0);
(*i)->Draw();
glPopMatrix();
}
LeaveOrtho(); LeaveOrtho();
} }
void Screen::AddBaseWidget(Widget* w, int x, int y) { void Screen::AddBaseWidget(Widget* w, int x, int y) {
w->SetPosition(x, y); baseContainer->Add(w, x, y);
Screen::widgets.push_back(w);
} }
void Screen::RemoveBaseWidget(Widget* w) { void Screen::RemoveBaseWidget(Widget* w) {
Screen::widgets.remove(w); baseContainer->Remove(w);
}
void Screen::SDLEventCoordToScreenCoord(int sdlev_x, int sdlev_y, float* x, float* y) {
*y = height-(sdlev_y*height*invRealHeight);
*x = sdlev_x*width*invRealWidth;
}
void Screen::OnMouseMotion(SDL_MouseMotionEvent* e) {
MouseMotionEvent ev;
float x, y;
Screen::SDLEventCoordToScreenCoord(e->x, e->y, &x, &y);
ev.screenX = ev.x = x;
ev.screenY = ev.y = y;
baseContainer->OnMouseMotion(&ev);
} }
void Screen::OnClick(SDL_MouseButtonEvent* e) { void Screen::OnClick(SDL_MouseButtonEvent* e) {
MouseButtonEvent ev; MouseButtonEvent ev;
float x = e->x; float x, y;
float y = e->y; Screen::SDLEventCoordToScreenCoord(e->x, e->y, &x, &y);
y = height-(y*height*invRealHeight);
x = x*width*invRealWidth;
ev.button = e->button; ev.button = e->button;
ev.isdown = (e->type == SDL_MOUSEBUTTONDOWN); ev.isdown = (e->type == SDL_MOUSEBUTTONDOWN);
ev.x = x; ev.screenX = ev.x = x;
ev.y = y; ev.screenY = ev.y = y;
ev.screenX = x;
ev.screenY = y;
OnClickTestLabels(ev); OnClickTestLabels(ev);
for(std::list<Widget*>::iterator i = Screen::widgets.begin(); i != Screen::widgets.end(); ++i) { if(ev.isdown) baseContainer->OnMouseDown(&ev);
float size[2], pos[2]; else baseContainer->OnMouseUp(&ev);
if(!(*i)->IsVisible()) continue;
int evmask = (*i)->GetEventMask();
if(ev.isdown) {
if(!(evmask & Widget::EVENT_MOUSEDOWN)) continue;
} else {
if(!(evmask & Widget::EVENT_MOUSEUP)) continue;
}
(*i)->GetPosition(pos);
(*i)->GetSize(size);
if((x >= pos[0]) && (x < pos[0]+size[0]) &&
(y >= pos[1]) && (y < pos[1]+size[1])) {
ev.x = x-pos[0];
ev.y = y-pos[1];
if(ev.isdown) {
(*i)->OnMouseDown(&ev);
} else {
(*i)->OnMouseUp(&ev);
}
}
}
} }
void Screen::OnClickTestLabels(const Gui::MouseButtonEvent& ev) { void Screen::OnClickTestLabels(const Gui::MouseButtonEvent& ev) {
@ -147,6 +126,12 @@ void Screen::OnKeyDown(const SDL_keysym* sym) {
} }
} }
void Screen::MeasureString(const std::string& s, float& w, float& h) {
font->MeasureString(s.c_str(), w, h);
w *= Screen::font_xsize;
h *= Screen::font_ysize;
}
void Screen::RenderString(const std::string& s) { void Screen::RenderString(const std::string& s) {
glPushMatrix(); glPushMatrix();
glScalef(Screen::font_xsize, Screen::font_ysize, 1); glScalef(Screen::font_xsize, Screen::font_ysize, 1);

View File

@ -11,9 +11,11 @@ namespace Gui {
static void Draw(void); static void Draw(void);
static void AddBaseWidget(Widget* w, int x, int y); static void AddBaseWidget(Widget* w, int x, int y);
static void RemoveBaseWidget(Widget* w); static void RemoveBaseWidget(Widget* w);
static void OnMouseMotion(SDL_MouseMotionEvent* e);
static void OnClick(SDL_MouseButtonEvent* e); static void OnClick(SDL_MouseButtonEvent* e);
static void OnKeyDown(const SDL_keysym* sym); static void OnKeyDown(const SDL_keysym* sym);
static void RenderString(const std::string& s); static void RenderString(const std::string& s);
static void MeasureString(const std::string& s, float& w, float& h);
static void RenderMarkup(const std::string& s); static void RenderMarkup(const std::string& s);
static void PutClickableLabel(const std::string& s, float x, float y, static void PutClickableLabel(const std::string& s, float x, float y,
sigc::slot<void, const Gui::MouseButtonEvent*> slot); sigc::slot<void, const Gui::MouseButtonEvent*> slot);
@ -37,16 +39,18 @@ namespace Gui {
static void OnClickTestLabels(const Gui::MouseButtonEvent& ev); static void OnClickTestLabels(const Gui::MouseButtonEvent& ev);
static bool CanPutLabel(float x, float y); static bool CanPutLabel(float x, float y);
static void AddShortcutWidget(Widget* w); static void AddShortcutWidget(Widget* w);
static void SDLEventCoordToScreenCoord(int sdlev_x, int sdlev_y, float* x, float* y);
static bool init; static bool init;
static int width, height; static int width, height;
static int realWidth, realHeight; static int realWidth, realHeight;
static float invRealWidth, invRealHeight; static float invRealWidth, invRealHeight;
static std::list<Widget*> widgets;
static std::list<Widget*> kbshortcut_widgets; static std::list<Widget*> kbshortcut_widgets;
static std::list<Widget*> mouseHoveredWidgets;
static FontFace* font; static FontFace* font;
static float font_xsize; static float font_xsize;
static float font_ysize; static float font_ysize;
static Gui::Fixed* baseContainer;
}; };
} }

71
src/gui_tooltip.cpp Normal file
View File

@ -0,0 +1,71 @@
#include "gui.h"
namespace Gui {
#define TOOLTIP_PADDING 5
#define FADE_TIME_MS 500
ToolTip::ToolTip(const char* text) {
SetText(text);
m_createdTime = SDL_GetTicks();
}
void ToolTip::CalcSize(void) {
float w, h;
Screen::MeasureString(m_text, w, h);
w += 2*TOOLTIP_PADDING;
h += 2*TOOLTIP_PADDING;
SetSize(w, h);
}
ToolTip::ToolTip(std::string& text) {
SetText(text);
m_createdTime = SDL_GetTicks();
}
void ToolTip::SetText(const char* text) {
m_text = text;
CalcSize();
}
void ToolTip::SetText(std::string& text) {
m_text = text;
CalcSize();
}
void ToolTip::Draw(void) {
float size[2];
int age = SDL_GetTicks() - m_createdTime;
float alpha = age/(float)FADE_TIME_MS; alpha = MIN(alpha, 0.75);
glEnable(GL_BLEND);
GetSize(size);
glColor4f(.2, .2, .6, alpha);
glBegin(GL_QUADS);
glVertex2f(size[0], 0);
glVertex2f(size[0], size[1]);
glVertex2f(0, size[1]);
glVertex2f(0, 0);
glEnd();
glColor4f(.0, .0, .8, alpha);
glBegin(GL_LINE_LOOP);
glVertex2f(size[0], 0);
glVertex2f(size[0], size[1]);
glVertex2f(0, size[1]);
glVertex2f(0, 0);
glEnd();
glPushMatrix();
glTranslatef(TOOLTIP_PADDING, TOOLTIP_PADDING, 0);
glColor4f(1, 1, 1, alpha);
Screen::RenderMarkup(m_text);
glPopMatrix();
glDisable(GL_BLEND);
}
void ToolTip::GetSizeRequested(float size[2]) {
#pragma message("Not setting size correctly.")
size[0] = 70;
size[1] = 10;
}
}

21
src/gui_tooltip.h Normal file
View File

@ -0,0 +1,21 @@
#pragma once
#include <string>
#include "gui_widget.h"
namespace Gui {
class ToolTip : public Widget {
public:
ToolTip(const char* text);
ToolTip(std::string& text);
virtual void Draw(void);
virtual ~ToolTip(void) {}
virtual void GetSizeRequested(float size[2]);
void SetText(const char* text);
void SetText(std::string& text);
private:
void CalcSize(void);
std::string m_text;
Uint32 m_createdTime;
};
}

View File

@ -3,8 +3,12 @@
namespace Gui { namespace Gui {
Widget::Widget(void) { Widget::Widget(void) {
m_parent = 0;
m_visible = false; m_visible = false;
m_mouseOver = false;
m_eventMask = EVENT_NONE; m_eventMask = EVENT_NONE;
m_tooltipWidget = 0;
m_tooltipTimerSignal.connect(sigc::mem_fun(this, &Widget::OnToolTip));
} }
void Widget::SetShortcut(SDLKey key, SDLMod mod) { void Widget::SetShortcut(SDLKey key, SDLMod mod) {
@ -20,5 +24,71 @@ void Widget::OnPreShortcut(const SDL_keysym* sym) {
} }
} }
void Widget::GetAbsolutePosition(float pos[2]) {
GetPosition(pos);
const Container* parent = GetParent();
while(parent) {
pos[0] += parent->m_size.x;
pos[1] += parent->m_size.y;
parent = parent->GetParent();
}
}
void Widget::OnMouseEnter(void) {
m_mouseOver = true;
Gui::AddTimer(1000, &m_tooltipTimerSignal);
}
void Widget::OnMouseLeave(void) {
m_mouseOver = false;
if(m_tooltipWidget) {
Screen::RemoveBaseWidget(m_tooltipWidget);
m_tooltipWidget = 0;
}
Gui::RemoveTimer(&m_tooltipTimerSignal);
}
void Widget::UpdateOverriddenTooltip(void) {
if(m_tooltipWidget) {
std::string text = GetOverrideTooltip();
m_tooltipWidget->SetText(text);
}
}
void Widget::OnToolTip(void) {
if(!m_tooltipWidget) {
std::string text = GetOverrideTooltip();
if(text == "") text = m_tooltip;
if(text == "") return;
float pos[2];
GetAbsolutePosition(pos);
m_tooltipWidget = new ToolTip(text);
if(m_tooltipWidget->m_size.w + pos[0] > Screen::GetWidth())
pos[0] = Screen::GetWidth() - m_tooltipWidget->m_size.w;
if(m_tooltipWidget->m_size.h + pos[1] > Screen::GetHeight())
pos[1] = Screen::GetHeight() - m_tooltipWidget->m_size.h;
Screen::AddBaseWidget(m_tooltipWidget, pos[0], pos[1]);
m_tooltipWidget->Show();
}
}
void Widget::Hide(void) {
m_visible = false;
if(m_tooltipWidget) {
Screen::RemoveBaseWidget(m_tooltipWidget);
delete m_tooltipWidget;
m_tooltipWidget = 0;
}
}
Widget::~Widget(void) {
if(m_tooltipWidget) {
Screen::RemoveBaseWidget(m_tooltipWidget);
delete m_tooltipWidget;
}
}
} }

View File

@ -3,27 +3,35 @@
namespace Gui { namespace Gui {
class Container; class Container;
class ToolTip;
class Widget { class Widget {
public: public:
Widget(void); Widget(void);
virtual void Draw(void) = 0; virtual void Draw(void) = 0;
virtual ~Widget(void) {} virtual ~Widget(void);
virtual void GetSizeRequested(float size[2]) = 0; virtual void GetSizeRequested(float size[2]) = 0;
void GetPosition(float pos[2]) { pos[0] = m_size.x; pos[1] = m_size.y; } void GetPosition(float pos[2]) const { pos[0] = m_size.x; pos[1] = m_size.y; }
void GetAbsolutePosition(float pos[2]);
void SetPosition(float x, float y) { m_size.x = x; m_size.y = y; } void SetPosition(float x, float y) { m_size.x = x; m_size.y = y; }
void GetSize(float size[2]) { size[0] = m_size.w; size[1] = m_size.h; } void GetSize(float size[2]) { size[0] = m_size.w; size[1] = m_size.h; }
void SetSize(float w, float h) { m_size.w = w; m_size.h = h; }; void SetSize(float w, float h) { m_size.w = w; m_size.h = h; };
void SetShortcut(SDLKey key, SDLMod mod); void SetShortcut(SDLKey key, SDLMod mod);
virtual void Show(void) { m_visible = true; } virtual void Show(void) { m_visible = true; }
virtual void Hide(void) { m_visible = false; } virtual void Hide(void);
bool IsVisible(void) { return m_visible; } bool IsVisible(void) { return m_visible; }
Container* GetParent(void) { return m_parent; } Container* GetParent(void) const { return m_parent; }
void SetParent(Container* p) { m_parent = p; } void SetParent(Container* p) { m_parent = p; }
void SetToolTip(std::string s) { m_tooltip = s; }
const std::string& GetToolTip(void) const { return m_tooltip; }
/* Event handlers should return false to stop propagating event. */ /* Event handlers should return false to stop propagating event. */
virtual bool OnMouseDown(MouseButtonEvent* e) { return false; } virtual bool OnMouseDown(MouseButtonEvent* e) { return false; }
virtual bool OnMouseUp(MouseButtonEvent* e) { return false; } virtual bool OnMouseUp(MouseButtonEvent* e) { return false; }
virtual bool OnMouseMotion(MouseMotionEvent* e) { return true; }
virtual void OnActivate(void) { } virtual void OnActivate(void) { }
virtual void OnMouseEnter(void);
virtual void OnMouseLeave(void);
bool IsMouseOver(void) { return m_mouseOver; }
/* Only to be called by Screen::OnKeyDown. */ /* Only to be called by Screen::OnKeyDown. */
void OnPreShortcut(const SDL_keysym* sym); void OnPreShortcut(const SDL_keysym* sym);
enum EventMask { enum EventMask {
@ -32,6 +40,7 @@ namespace Gui {
EVENT_KEYUP = 1<<1, EVENT_KEYUP = 1<<1,
EVENT_MOUSEDOWN = 1<<2, EVENT_MOUSEDOWN = 1<<2,
EVENT_MOUSEUP = 1<<3, EVENT_MOUSEUP = 1<<3,
EVENT_MOUSEMOTION = 1<<4, /* Needed for OnMouseEnter, Leave, IsMOuseOver. */
EVENT_ALL = 0xffffffff EVENT_ALL = 0xffffffff
}; };
unsigned int GetEventMask(void) { return m_eventMask; } unsigned int GetEventMask(void) { return m_eventMask; }
@ -41,12 +50,20 @@ namespace Gui {
SDLKey sym; SDLKey sym;
SDLMod mod; SDLMod mod;
} m_shortcut; } m_shortcut;
virtual std::string GetOverrideTooltip(void) { return ""; }
void UpdateOverriddenTooltip(void);
private: private:
struct { struct {
float x,y,w,h; float x,y,w,h;
} m_size; } m_size;
bool m_visible; bool m_visible;
bool m_mouseOver;
Container* m_parent; Container* m_parent;
std::string m_tooltip;
sigc::signal<void> m_tooltipTimerSignal;
ToolTip* m_tooltipWidget;
void OnToolTip();
}; };
} }

View File

@ -21,14 +21,17 @@ SectorView::SectorView(void) : GenericSystemView() {
Gui::ImageButton* ib = new Gui::ImageButton("icons/sectorview_f6_systeminfo.png"); Gui::ImageButton* ib = new Gui::ImageButton("icons/sectorview_f6_systeminfo.png");
ib->onClick.connect(sigc::mem_fun(this, &SectorView::OnClickSystemInfo)); ib->onClick.connect(sigc::mem_fun(this, &SectorView::OnClickSystemInfo));
ib->SetShortcut(SDLK_F5, KMOD_NONE); ib->SetShortcut(SDLK_F5, KMOD_NONE);
ib->SetToolTip("Star system information.");
m_rightButtonBar->Add(ib, 2, 2); m_rightButtonBar->Add(ib, 2, 2);
m_zoomInButton = new Gui::ImageButton("icons/zoom_in_f7.png"); m_zoomInButton = new Gui::ImageButton("icons/zoom_in_f7.png");
m_zoomInButton->SetShortcut(SDLK_F6, KMOD_NONE); m_zoomInButton->SetShortcut(SDLK_F6, KMOD_NONE);
m_zoomInButton->SetToolTip("Zoom in.");
m_rightButtonBar->Add(m_zoomInButton, 34, 2); m_rightButtonBar->Add(m_zoomInButton, 34, 2);
m_zoomOutButton = new Gui::ImageButton("icons/zoom_out_f8.png"); m_zoomOutButton = new Gui::ImageButton("icons/zoom_out_f8.png");
m_zoomOutButton->SetShortcut(SDLK_F7, KMOD_NONE); m_zoomOutButton->SetShortcut(SDLK_F7, KMOD_NONE);
m_zoomOutButton->SetToolTip("Zoom out.");
m_rightButtonBar->Add(m_zoomOutButton, 66, 2); m_rightButtonBar->Add(m_zoomOutButton, 66, 2);
m_gluDiskDlist = glGenLists(1); m_gluDiskDlist = glGenLists(1);

View File

@ -50,9 +50,9 @@ ShipCpanel::ShipCpanel(void) : Gui::Fixed(640, 64) {
Gui::MultiStateImageButton* cam_button = new Gui::MultiStateImageButton(); Gui::MultiStateImageButton* cam_button = new Gui::MultiStateImageButton();
g->Add(cam_button); g->Add(cam_button);
cam_button->SetSelected(true); cam_button->SetSelected(true);
cam_button->AddState(WorldView::CAM_FRONT, "icons/cam_front.png"); cam_button->AddState(WorldView::CAM_FRONT, "icons/cam_front.png", "Front view");
cam_button->AddState(WorldView::CAM_REAR, "icons/cam_rear.png"); cam_button->AddState(WorldView::CAM_REAR, "icons/cam_rear.png", "Read view");
cam_button->AddState(WorldView::CAM_EXTERNAL, "icons/cam_external.png"); cam_button->AddState(WorldView::CAM_EXTERNAL, "icons/cam_external.png", "External view");
cam_button->SetShortcut(SDLK_F1, KMOD_NONE); cam_button->SetShortcut(SDLK_F1, KMOD_NONE);
cam_button->onClick.connect(sigc::mem_fun(this, &ShipCpanel::OnChangeCamView)); cam_button->onClick.connect(sigc::mem_fun(this, &ShipCpanel::OnChangeCamView));
Add(cam_button, 2, 2); Add(cam_button, 2, 2);
@ -61,8 +61,8 @@ ShipCpanel::ShipCpanel(void) : Gui::Fixed(640, 64) {
g->Add(map_button); g->Add(map_button);
map_button->SetSelected(false); map_button->SetSelected(false);
map_button->SetShortcut(SDLK_F2, KMOD_NONE); map_button->SetShortcut(SDLK_F2, KMOD_NONE);
map_button->AddState(L3D::MAP_SECTOR, "icons/cpan_f2_map.png"); map_button->AddState(L3D::MAP_SECTOR, "icons/cpan_f2_map.png", "Galaxy sector map");
map_button->AddState(L3D::MAP_SYSTEM, "icons/cpan_f2_normal.png"); map_button->AddState(L3D::MAP_SYSTEM, "icons/cpan_f2_normal.png", "Star system view");
map_button->onClick.connect(sigc::mem_fun(this, &ShipCpanel::OnChangeMapView)); map_button->onClick.connect(sigc::mem_fun(this, &ShipCpanel::OnChangeMapView));
Add(map_button, 34, 2); Add(map_button, 34, 2);
@ -70,7 +70,7 @@ ShipCpanel::ShipCpanel(void) : Gui::Fixed(640, 64) {
g->Add(info_button); g->Add(info_button);
info_button->SetSelected(false); info_button->SetSelected(false);
info_button->SetShortcut(SDLK_F3, KMOD_NONE); info_button->SetShortcut(SDLK_F3, KMOD_NONE);
info_button->AddState(0, "icons/cpan_f3_shipinfo.png"); info_button->AddState(0, "icons/cpan_f3_shipinfo.png", "Ship information.");
info_button->onClick.connect(sigc::mem_fun(this, &ShipCpanel::OnChangeInfoView)); info_button->onClick.connect(sigc::mem_fun(this, &ShipCpanel::OnChangeInfoView));
Add(info_button, 66, 2); Add(info_button, 66, 2);
@ -78,7 +78,7 @@ ShipCpanel::ShipCpanel(void) : Gui::Fixed(640, 64) {
g->Add(comms_button); g->Add(comms_button);
comms_button->SetSelected(false); comms_button->SetSelected(false);
comms_button->SetShortcut(SDLK_F4, KMOD_NONE); comms_button->SetShortcut(SDLK_F4, KMOD_NONE);
comms_button->AddState(0, "icons/comms_f4.png"); comms_button->AddState(0, "icons/comms_f4.png", "Comms.");
comms_button->onClick.connect(sigc::mem_fun(this, &ShipCpanel::OnClickComms)); comms_button->onClick.connect(sigc::mem_fun(this, &ShipCpanel::OnClickComms));
Add(comms_button, 98, 2); Add(comms_button, 98, 2);

View File

@ -13,10 +13,12 @@ SystemView::SystemView(void): View() {
m_zoomInButton = new Gui::ImageButton("icons/zoom_in_f7.png"); m_zoomInButton = new Gui::ImageButton("icons/zoom_in_f7.png");
m_zoomInButton->SetShortcut(SDLK_F6, KMOD_NONE); m_zoomInButton->SetShortcut(SDLK_F6, KMOD_NONE);
m_zoomInButton->SetToolTip("Zoom in.");
m_rightButtonBar->Add(m_zoomInButton, 34, 2); m_rightButtonBar->Add(m_zoomInButton, 34, 2);
m_zoomOutButton = new Gui::ImageButton("icons/zoom_out_f8.png"); m_zoomOutButton = new Gui::ImageButton("icons/zoom_out_f8.png");
m_zoomOutButton->SetShortcut(SDLK_F7, KMOD_NONE); m_zoomOutButton->SetShortcut(SDLK_F7, KMOD_NONE);
m_zoomOutButton->SetToolTip("Zoom out.");
m_rightButtonBar->Add(m_zoomOutButton, 66, 2); m_rightButtonBar->Add(m_zoomOutButton, 66, 2);
Gui::ImageButton* b = new Gui::ImageButton("icons/sysview_accel_r3.png", Gui::ImageButton* b = new Gui::ImageButton("icons/sysview_accel_r3.png",

View File

@ -27,25 +27,27 @@ WorldView::WorldView(void): View() {
Gui::MultiStateImageButton* wheels_button = new Gui::MultiStateImageButton(); Gui::MultiStateImageButton* wheels_button = new Gui::MultiStateImageButton();
wheels_button->SetShortcut(SDLK_F6, KMOD_NONE); wheels_button->SetShortcut(SDLK_F6, KMOD_NONE);
wheels_button->AddState(0, "icons/wheels_up.png"); wheels_button->AddState(0, "icons/wheels_up.png", "Wheels up.");
wheels_button->AddState(1, "icons/wheels_down.png"); wheels_button->AddState(1, "icons/wheels_down.png", "Wheels down.");
wheels_button->onClick.connect(sigc::mem_fun(this, &WorldView::OnChangeWheelsState)); wheels_button->onClick.connect(sigc::mem_fun(this, &WorldView::OnChangeWheelsState));
m_rightButtonBar->Add(wheels_button, 34, 2); m_rightButtonBar->Add(wheels_button, 34, 2);
Gui::MultiStateImageButton* labels_button = new Gui::MultiStateImageButton(); Gui::MultiStateImageButton* labels_button = new Gui::MultiStateImageButton();
labels_button->SetShortcut(SDLK_8, KMOD_NONE); labels_button->SetShortcut(SDLK_8, KMOD_NONE);
labels_button->AddState(1, "icons/labels_on.png"); labels_button->AddState(1, "icons/labels_on.png", "Object labels on.");
labels_button->AddState(0, "icons/labels_off.png"); labels_button->AddState(0, "icons/labels_off.png", "Object labels off.");
labels_button->onClick.connect(sigc::mem_fun(this, &WorldView::OnChangeLabelsState)); labels_button->onClick.connect(sigc::mem_fun(this, &WorldView::OnChangeLabelsState));
m_rightButtonBar->Add(labels_button, 98, 2); m_rightButtonBar->Add(labels_button, 98, 2);
m_hyperspaceButton = new Gui::ImageButton("icons/hyperspace_f8.png"); m_hyperspaceButton = new Gui::ImageButton("icons/hyperspace_f8.png");
m_hyperspaceButton->SetShortcut(SDLK_F7, KMOD_NONE); m_hyperspaceButton->SetShortcut(SDLK_F7, KMOD_NONE);
m_hyperspaceButton->SetToolTip("Hyperspace Jump.");
m_hyperspaceButton->onClick.connect(sigc::mem_fun(this, &WorldView::OnClickHyperspace)); m_hyperspaceButton->onClick.connect(sigc::mem_fun(this, &WorldView::OnClickHyperspace));
m_rightButtonBar->Add(m_hyperspaceButton, 66, 2); m_rightButtonBar->Add(m_hyperspaceButton, 66, 2);
launchButton = new Gui::ImageButton("icons/blastoff.png"); launchButton = new Gui::ImageButton("icons/blastoff.png");
launchButton->SetShortcut(SDLK_F5, KMOD_NONE); launchButton->SetShortcut(SDLK_F5, KMOD_NONE);
launchButton->SetToolTip("Takeoff");
launchButton->onClick.connect(sigc::mem_fun(this, &WorldView::OnClickBlastoff)); launchButton->onClick.connect(sigc::mem_fun(this, &WorldView::OnClickBlastoff));
m_rightButtonBar->Add(launchButton, 2, 2); m_rightButtonBar->Add(launchButton, 2, 2);