[Add] Gui Tooltips.
[Clean] Cleaned up GUI::Screen.
This commit is contained in:
		
							parent
							
								
									b32409dfb1
								
							
						
					
					
						commit
						fecd2866f5
					
				| @ -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 \
 | ||||
| 		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 \
 | ||||
| 		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 \
 | ||||
| 		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_container.cpp | ||||
| 
 | ||||
|  | ||||
| @ -283,6 +283,22 @@ void FontFace::RenderGlyph(int chr) { | ||||
|   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) { | ||||
|   glPushMatrix(); | ||||
|     for(unsigned int i = 0; i < strlen(str); i++) { | ||||
|  | ||||
| @ -8,6 +8,7 @@ public: | ||||
|   void RenderGlyph(int chr); | ||||
|   void RenderString(const char* str); | ||||
|   void RenderMarkup(const char* str); | ||||
|   void MeasureString(const char* str, float& w, float& h); | ||||
| 
 | ||||
|   /* Of Ms. */ | ||||
|   float GetHeight(void) { return m_height; } | ||||
|  | ||||
							
								
								
									
										44
									
								
								src/gui.cpp
									
									
									
									
									
								
							
							
						
						
									
										44
									
								
								src/gui.cpp
									
									
									
									
									
								
							| @ -3,6 +3,7 @@ | ||||
| 
 | ||||
| namespace Gui { | ||||
| namespace RawEvents { | ||||
|   sigc::signal<void, SDL_MouseMotionEvent*> onMouseMotion; | ||||
|   sigc::signal<void, SDL_MouseButtonEvent*> onMouseDown; | ||||
|   sigc::signal<void, SDL_MouseButtonEvent*> onMouseUp; | ||||
|   sigc::signal<void, SDL_KeyboardEvent*>    onKeyDown; | ||||
| @ -31,10 +32,53 @@ void HandleSDLEvent(SDL_Event* event) { | ||||
|   case SDL_KEYUP: | ||||
|     RawEvents::onKeyUp.emit(&event->key); | ||||
|     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) { | ||||
|   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(); | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -9,6 +9,8 @@ | ||||
| 
 | ||||
|   void HandleSDLEvent(SDL_Event* event); | ||||
|   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); | ||||
|  } | ||||
| 
 | ||||
| @ -35,5 +37,6 @@ namespace Gui { | ||||
| #include "gui_radio_group.h" | ||||
| #include "gui_fixed.h" | ||||
| #include "gui_label.h" | ||||
| #include "gui_tooltip.h" | ||||
| #include "gui_screen.h" | ||||
| 
 | ||||
|  | ||||
| @ -7,7 +7,7 @@ namespace Gui { | ||||
| 
 | ||||
| Button::Button(void) { | ||||
|   m_isPressed = false; | ||||
|   m_eventMask = EVENT_MOUSEDOWN | EVENT_MOUSEUP; | ||||
|   m_eventMask = EVENT_MOUSEDOWN | EVENT_MOUSEUP | EVENT_MOUSEMOTION; | ||||
|   SetSize(BUTTON_SIZE, BUTTON_SIZE); | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -3,6 +3,38 @@ | ||||
| 
 | ||||
| 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) { | ||||
|   float x = e->x; | ||||
|  | ||||
| @ -9,6 +9,7 @@ namespace Gui { | ||||
|   public: | ||||
|     bool OnMouseDown(MouseButtonEvent* e); | ||||
|     bool OnMouseUp(MouseButtonEvent* e); | ||||
|     bool OnMouseMotion(MouseMotionEvent* e); | ||||
|     void DeleteAllChildren(void); | ||||
|     virtual void Draw(void); | ||||
|     virtual void ShowAll(void); | ||||
|  | ||||
| @ -3,7 +3,11 @@ namespace Gui { | ||||
|   struct MouseButtonEvent { | ||||
|     Uint8 isdown; | ||||
|     Uint8 button; | ||||
|     float x, y; /* Widget coords. */ | ||||
|     float x, y;             /* Widget coords. */ | ||||
|     float screenX, screenY; /* Screen coords. */ | ||||
|   }; | ||||
|   struct MouseMotionEvent { | ||||
|     float x, y;             /* Widget coords. */ | ||||
|     float screenX, screenY; /* Screen coords. */ | ||||
|   }; | ||||
| } | ||||
|  | ||||
| @ -7,7 +7,7 @@ Fixed::Fixed(float w, float h) { | ||||
|   SetSize(w, h); | ||||
|   memcpy(m_bgcol, Color::bg, 3*sizeof(float)); | ||||
|   m_w = w; m_h = h; | ||||
|   m_transparent = false; | ||||
|   m_transparent = true; | ||||
|   m_eventMask = EVENT_ALL; | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -12,12 +12,20 @@ Label::Label(std::string& text) { | ||||
|   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) { | ||||
|   m_text = text; | ||||
|   RecalcSize(); | ||||
| } | ||||
| 
 | ||||
| void Label::SetText(std::string& text) { | ||||
|   m_text = text; | ||||
|   RecalcSize(); | ||||
| } | ||||
| 
 | ||||
| void Label::Draw(void) { | ||||
| @ -26,9 +34,8 @@ void Label::Draw(void) { | ||||
| } | ||||
| 
 | ||||
| void Label::GetSizeRequested(float size[2]) { | ||||
| #pragma message("Not setting size correctly.") | ||||
|   size[0] = 70; | ||||
|   size[1] = 10; | ||||
|   RecalcSize(); | ||||
|   GetSize(size); | ||||
| } | ||||
| 
 | ||||
| void Label::SetColor(float r, float g, float b) { | ||||
|  | ||||
| @ -14,6 +14,7 @@ namespace Gui { | ||||
|     void SetText(std::string& text); | ||||
|     void SetColor(float r, float g, float b); | ||||
|   private: | ||||
|     void RecalcSize(void); | ||||
|     std::string m_text; | ||||
|     float m_color[3]; | ||||
|   }; | ||||
|  | ||||
| @ -18,11 +18,13 @@ MultiStateImageButton::~MultiStateImageButton(void) { | ||||
| void MultiStateImageButton::StateNext(void) { | ||||
|   m_curState++; | ||||
|   if(m_curState >= (signed)m_states.size()) m_curState = 0; | ||||
|   UpdateOverriddenTooltip(); | ||||
| } | ||||
| 
 | ||||
| void MultiStateImageButton::StatePrev(void) { | ||||
|   m_curState--; | ||||
|   if(m_curState < 0) m_curState = (signed)m_states.size()-1; | ||||
|   UpdateOverriddenTooltip(); | ||||
| } | ||||
| 
 | ||||
| void MultiStateImageButton::OnActivate(void) { | ||||
| @ -49,14 +51,23 @@ void MultiStateImageButton::Draw(void) { | ||||
| } | ||||
| 
 | ||||
| void MultiStateImageButton::AddState(int state, const char* filename) { | ||||
|   AddState(state, filename, ""); | ||||
| } | ||||
| 
 | ||||
| void MultiStateImageButton::AddState(int state, const char* filename, std::string tooltip) { | ||||
|   State s; | ||||
|   s.state = state; | ||||
|   s.image = new Image(filename); | ||||
|   s.tooltip = tooltip; | ||||
|   m_states.push_back(s); | ||||
|   float size[2]; | ||||
|   s.image->GetSizeRequested(size); | ||||
|   SetSize(size[0], size[1]); | ||||
| } | ||||
| 
 | ||||
| std::string MultiStateImageButton::GetOverrideTooltip(void) { | ||||
|   return m_states[m_curState].tooltip; | ||||
| } | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -12,16 +12,20 @@ namespace Gui { | ||||
|     virtual ~MultiStateImageButton(void); | ||||
|     virtual void GetSizeRequested(float size[2]); | ||||
|     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; } | ||||
|     void StateNext(void); | ||||
|     void StatePrev(void); | ||||
|     virtual void OnActivate(void); | ||||
|     sigc::signal<void, MultiStateImageButton*> onClick; | ||||
|     virtual void SetSelected(bool state); | ||||
|   protected: | ||||
|     virtual std::string GetOverrideTooltip(void); | ||||
|   private: | ||||
|     struct State { | ||||
|       int state; | ||||
|       Image* image; | ||||
|       std::string tooltip; | ||||
|     }; | ||||
|     std::vector<State> m_states; | ||||
|     int m_curState; | ||||
|  | ||||
| @ -11,11 +11,11 @@ int Screen::realWidth; | ||||
| int Screen::realHeight; | ||||
| float Screen::invRealWidth; | ||||
| float Screen::invRealHeight; | ||||
| std::list<Widget*> Screen::widgets; | ||||
| std::list<Widget*> Screen::kbshortcut_widgets; | ||||
| float Screen::font_xsize; | ||||
| float Screen::font_ysize; | ||||
| 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) { | ||||
|   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_xsize    = 16*0.8; | ||||
|   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, | ||||
| @ -46,7 +48,6 @@ void Screen::EnterOrtho(void) { | ||||
|   glMatrixMode(GL_PROJECTION); | ||||
|   glPushMatrix(); | ||||
|   glLoadIdentity(); | ||||
|   //glOrtho(9, 320, 0, 200, -1, 1);
 | ||||
|   glOrtho(0, width, 0, height, -1, 1); | ||||
|   glMatrixMode(GL_MODELVIEW); | ||||
|   glPushMatrix(); | ||||
| @ -67,65 +68,43 @@ void Screen::Draw(void) { | ||||
|   labelPositions.clear(); | ||||
|   EnterOrtho(); | ||||
| 
 | ||||
|   for(std::list<Widget*>::iterator i = Screen::widgets.begin(); i != Screen::widgets.end(); ++i) { | ||||
|     if(!(*i)->IsVisible()) continue; | ||||
|     glPushMatrix(); | ||||
|     float pos[2]; | ||||
|     (*i)->GetPosition(pos); | ||||
|     glTranslatef(pos[0], pos[1], 0); | ||||
|     (*i)->Draw(); | ||||
|     glPopMatrix(); | ||||
|   } | ||||
|   baseContainer->Draw(); | ||||
|   LeaveOrtho(); | ||||
| } | ||||
| 
 | ||||
| void Screen::AddBaseWidget(Widget* w, int x, int y) { | ||||
|   w->SetPosition(x, y); | ||||
|   Screen::widgets.push_back(w); | ||||
|   baseContainer->Add(w, x, y); | ||||
| } | ||||
| 
 | ||||
| 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) { | ||||
|   MouseButtonEvent ev; | ||||
|   float x = e->x; | ||||
|   float y = e->y; | ||||
|   y = height-(y*height*invRealHeight); | ||||
|   x = x*width*invRealWidth; | ||||
|   float x, y; | ||||
|   Screen::SDLEventCoordToScreenCoord(e->x, e->y, &x, &y); | ||||
|   ev.button = e->button; | ||||
|   ev.isdown = (e->type == SDL_MOUSEBUTTONDOWN); | ||||
|   ev.x = x; | ||||
|   ev.y = y; | ||||
|   ev.screenX = x; | ||||
|   ev.screenY = y; | ||||
|   ev.screenX = ev.x = x; | ||||
|   ev.screenY = ev.y = y; | ||||
|   OnClickTestLabels(ev); | ||||
|   for(std::list<Widget*>::iterator i = Screen::widgets.begin(); i != Screen::widgets.end(); ++i) { | ||||
|     float size[2], pos[2]; | ||||
|     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); | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|   if(ev.isdown) baseContainer->OnMouseDown(&ev); | ||||
|   else baseContainer->OnMouseUp(&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) { | ||||
|   glPushMatrix(); | ||||
|   glScalef(Screen::font_xsize, Screen::font_ysize, 1); | ||||
|  | ||||
| @ -11,9 +11,11 @@ namespace Gui { | ||||
|     static void Draw(void); | ||||
|     static void AddBaseWidget(Widget* w, int x, int y); | ||||
|     static void RemoveBaseWidget(Widget* w); | ||||
|     static void OnMouseMotion(SDL_MouseMotionEvent* e); | ||||
|     static void OnClick(SDL_MouseButtonEvent* e); | ||||
|     static void OnKeyDown(const SDL_keysym* sym); | ||||
|     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 PutClickableLabel(const std::string& s, float x, float y, | ||||
|                                   sigc::slot<void, const Gui::MouseButtonEvent*> slot); | ||||
| @ -37,16 +39,18 @@ namespace Gui { | ||||
|     static void OnClickTestLabels(const Gui::MouseButtonEvent& ev); | ||||
|     static bool CanPutLabel(float x, float y); | ||||
|     static void AddShortcutWidget(Widget* w); | ||||
|     static void SDLEventCoordToScreenCoord(int sdlev_x, int sdlev_y, float* x, float* y); | ||||
| 
 | ||||
|     static bool init; | ||||
|     static int width, height; | ||||
|     static int realWidth, realHeight; | ||||
|     static float invRealWidth, invRealHeight; | ||||
|     static std::list<Widget*> widgets; | ||||
|     static std::list<Widget*> kbshortcut_widgets; | ||||
|     static std::list<Widget*> mouseHoveredWidgets; | ||||
|     static FontFace* font; | ||||
|     static float font_xsize; | ||||
|     static float font_ysize; | ||||
|     static Gui::Fixed* baseContainer; | ||||
|   }; | ||||
| } | ||||
| 
 | ||||
|  | ||||
							
								
								
									
										71
									
								
								src/gui_tooltip.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										71
									
								
								src/gui_tooltip.cpp
									
									
									
									
									
										Normal 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
									
								
							
							
						
						
									
										21
									
								
								src/gui_tooltip.h
									
									
									
									
									
										Normal 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; | ||||
|   }; | ||||
| } | ||||
| 
 | ||||
| @ -3,8 +3,12 @@ | ||||
| namespace Gui { | ||||
| 
 | ||||
| Widget::Widget(void) { | ||||
|   m_visible   = false; | ||||
|   m_eventMask = EVENT_NONE; | ||||
|   m_parent        = 0; | ||||
|   m_visible       = false; | ||||
|   m_mouseOver     = false; | ||||
|   m_eventMask     = EVENT_NONE; | ||||
|   m_tooltipWidget = 0; | ||||
|   m_tooltipTimerSignal.connect(sigc::mem_fun(this, &Widget::OnToolTip)); | ||||
| } | ||||
| 
 | ||||
| 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; | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -3,36 +3,45 @@ | ||||
| 
 | ||||
| namespace Gui { | ||||
|   class Container; | ||||
|   class ToolTip; | ||||
|   class Widget { | ||||
|   public: | ||||
|     Widget(void); | ||||
|     virtual void Draw(void) = 0; | ||||
|     virtual ~Widget(void) {} | ||||
|     virtual ~Widget(void); | ||||
|     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 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 SetShortcut(SDLKey key, SDLMod mod); | ||||
|     virtual void Show(void)             { m_visible = true; } | ||||
|     virtual void Hide(void)             { m_visible = false; } | ||||
|     virtual void Hide(void); | ||||
|     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 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. */ | ||||
|     virtual bool OnMouseDown(MouseButtonEvent* e) { return false; } | ||||
|     virtual bool OnMouseUp(MouseButtonEvent* e)   { return false; } | ||||
|     virtual void OnActivate(void)                 {} | ||||
|     virtual bool OnMouseDown(MouseButtonEvent* e)   { return false; } | ||||
|     virtual bool OnMouseUp(MouseButtonEvent* e)     { return false; } | ||||
|     virtual bool OnMouseMotion(MouseMotionEvent* e) { return true; } | ||||
|     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. */ | ||||
|     void OnPreShortcut(const SDL_keysym* sym); | ||||
|     enum EventMask { | ||||
|       EVENT_NONE      = 0, | ||||
|       EVENT_KEYDOWN   = 1<<0, | ||||
|       EVENT_KEYUP     = 1<<1, | ||||
|       EVENT_MOUSEDOWN = 1<<2, | ||||
|       EVENT_MOUSEUP   = 1<<3, | ||||
|       EVENT_ALL       = 0xffffffff | ||||
|       EVENT_NONE        = 0, | ||||
|       EVENT_KEYDOWN     = 1<<0, | ||||
|       EVENT_KEYUP       = 1<<1, | ||||
|       EVENT_MOUSEDOWN   = 1<<2, | ||||
|       EVENT_MOUSEUP     = 1<<3, | ||||
|       EVENT_MOUSEMOTION = 1<<4, /* Needed for OnMouseEnter, Leave, IsMOuseOver. */ | ||||
|       EVENT_ALL         = 0xffffffff | ||||
|     }; | ||||
|     unsigned int GetEventMask(void)   { return m_eventMask; } | ||||
|   protected: | ||||
| @ -41,12 +50,20 @@ namespace Gui { | ||||
|       SDLKey sym; | ||||
|       SDLMod mod; | ||||
|     } m_shortcut; | ||||
| 
 | ||||
|     virtual std::string GetOverrideTooltip(void) { return ""; } | ||||
|     void UpdateOverriddenTooltip(void); | ||||
|   private: | ||||
|     struct { | ||||
|       float x,y,w,h; | ||||
|     } m_size; | ||||
|     bool m_visible; | ||||
|     bool m_mouseOver; | ||||
|     Container* m_parent; | ||||
|     std::string m_tooltip; | ||||
|     sigc::signal<void> m_tooltipTimerSignal; | ||||
|     ToolTip* m_tooltipWidget; | ||||
|     void OnToolTip(); | ||||
|   }; | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -21,14 +21,17 @@ SectorView::SectorView(void) : GenericSystemView() { | ||||
|   Gui::ImageButton* ib = new Gui::ImageButton("icons/sectorview_f6_systeminfo.png"); | ||||
|   ib->onClick.connect(sigc::mem_fun(this, &SectorView::OnClickSystemInfo)); | ||||
|   ib->SetShortcut(SDLK_F5, KMOD_NONE); | ||||
|   ib->SetToolTip("Star system information."); | ||||
|   m_rightButtonBar->Add(ib, 2, 2); | ||||
| 
 | ||||
|   m_zoomInButton = new Gui::ImageButton("icons/zoom_in_f7.png"); | ||||
|   m_zoomInButton->SetShortcut(SDLK_F6, KMOD_NONE); | ||||
|   m_zoomInButton->SetToolTip("Zoom in."); | ||||
|   m_rightButtonBar->Add(m_zoomInButton, 34, 2); | ||||
| 
 | ||||
|   m_zoomOutButton = new Gui::ImageButton("icons/zoom_out_f8.png"); | ||||
|   m_zoomOutButton->SetShortcut(SDLK_F7, KMOD_NONE); | ||||
|   m_zoomOutButton->SetToolTip("Zoom out."); | ||||
|   m_rightButtonBar->Add(m_zoomOutButton, 66, 2); | ||||
| 
 | ||||
|   m_gluDiskDlist = glGenLists(1); | ||||
|  | ||||
| @ -50,9 +50,9 @@ ShipCpanel::ShipCpanel(void) : Gui::Fixed(640, 64) { | ||||
|   Gui::MultiStateImageButton* cam_button = new Gui::MultiStateImageButton(); | ||||
|   g->Add(cam_button); | ||||
|   cam_button->SetSelected(true); | ||||
|   cam_button->AddState(WorldView::CAM_FRONT,     "icons/cam_front.png"); | ||||
|   cam_button->AddState(WorldView::CAM_REAR,     "icons/cam_rear.png"); | ||||
|   cam_button->AddState(WorldView::CAM_EXTERNAL, "icons/cam_external.png"); | ||||
|   cam_button->AddState(WorldView::CAM_FRONT,     "icons/cam_front.png", "Front view"); | ||||
|   cam_button->AddState(WorldView::CAM_REAR,     "icons/cam_rear.png", "Read view"); | ||||
|   cam_button->AddState(WorldView::CAM_EXTERNAL, "icons/cam_external.png", "External view"); | ||||
|   cam_button->SetShortcut(SDLK_F1, KMOD_NONE); | ||||
|   cam_button->onClick.connect(sigc::mem_fun(this, &ShipCpanel::OnChangeCamView)); | ||||
|   Add(cam_button, 2, 2); | ||||
| @ -61,8 +61,8 @@ ShipCpanel::ShipCpanel(void) : Gui::Fixed(640, 64) { | ||||
|   g->Add(map_button); | ||||
|   map_button->SetSelected(false); | ||||
|   map_button->SetShortcut(SDLK_F2, KMOD_NONE); | ||||
|   map_button->AddState(L3D::MAP_SECTOR, "icons/cpan_f2_map.png"); | ||||
|   map_button->AddState(L3D::MAP_SYSTEM, "icons/cpan_f2_normal.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", "Star system view"); | ||||
|   map_button->onClick.connect(sigc::mem_fun(this, &ShipCpanel::OnChangeMapView)); | ||||
|   Add(map_button, 34, 2); | ||||
| 
 | ||||
| @ -70,7 +70,7 @@ ShipCpanel::ShipCpanel(void) : Gui::Fixed(640, 64) { | ||||
|   g->Add(info_button); | ||||
|   info_button->SetSelected(false); | ||||
|   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)); | ||||
|   Add(info_button, 66, 2); | ||||
| 
 | ||||
| @ -78,7 +78,7 @@ ShipCpanel::ShipCpanel(void) : Gui::Fixed(640, 64) { | ||||
|   g->Add(comms_button); | ||||
|   comms_button->SetSelected(false); | ||||
|   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)); | ||||
|   Add(comms_button, 98, 2); | ||||
| 
 | ||||
|  | ||||
| @ -13,10 +13,12 @@ SystemView::SystemView(void): View() { | ||||
| 
 | ||||
|   m_zoomInButton = new Gui::ImageButton("icons/zoom_in_f7.png"); | ||||
|   m_zoomInButton->SetShortcut(SDLK_F6, KMOD_NONE); | ||||
|   m_zoomInButton->SetToolTip("Zoom in."); | ||||
|   m_rightButtonBar->Add(m_zoomInButton, 34, 2); | ||||
| 
 | ||||
|   m_zoomOutButton = new Gui::ImageButton("icons/zoom_out_f8.png"); | ||||
|   m_zoomOutButton->SetShortcut(SDLK_F7, KMOD_NONE); | ||||
|   m_zoomOutButton->SetToolTip("Zoom out."); | ||||
|   m_rightButtonBar->Add(m_zoomOutButton, 66, 2); | ||||
| 
 | ||||
|   Gui::ImageButton* b = new Gui::ImageButton("icons/sysview_accel_r3.png", | ||||
|  | ||||
| @ -27,25 +27,27 @@ WorldView::WorldView(void): View() { | ||||
|    | ||||
|   Gui::MultiStateImageButton* wheels_button = new Gui::MultiStateImageButton(); | ||||
|   wheels_button->SetShortcut(SDLK_F6, KMOD_NONE); | ||||
|   wheels_button->AddState(0, "icons/wheels_up.png"); | ||||
|   wheels_button->AddState(1, "icons/wheels_down.png"); | ||||
|   wheels_button->AddState(0, "icons/wheels_up.png", "Wheels up."); | ||||
|   wheels_button->AddState(1, "icons/wheels_down.png", "Wheels down."); | ||||
|   wheels_button->onClick.connect(sigc::mem_fun(this, &WorldView::OnChangeWheelsState)); | ||||
|   m_rightButtonBar->Add(wheels_button, 34, 2); | ||||
| 
 | ||||
|   Gui::MultiStateImageButton* labels_button = new Gui::MultiStateImageButton(); | ||||
|   labels_button->SetShortcut(SDLK_8, KMOD_NONE); | ||||
|   labels_button->AddState(1, "icons/labels_on.png"); | ||||
|   labels_button->AddState(0, "icons/labels_off.png"); | ||||
|   labels_button->AddState(1, "icons/labels_on.png", "Object labels on."); | ||||
|   labels_button->AddState(0, "icons/labels_off.png", "Object labels off."); | ||||
|   labels_button->onClick.connect(sigc::mem_fun(this, &WorldView::OnChangeLabelsState)); | ||||
|   m_rightButtonBar->Add(labels_button, 98, 2); | ||||
| 
 | ||||
|   m_hyperspaceButton = new Gui::ImageButton("icons/hyperspace_f8.png"); | ||||
|   m_hyperspaceButton->SetShortcut(SDLK_F7, KMOD_NONE); | ||||
|   m_hyperspaceButton->SetToolTip("Hyperspace Jump."); | ||||
|   m_hyperspaceButton->onClick.connect(sigc::mem_fun(this, &WorldView::OnClickHyperspace)); | ||||
|   m_rightButtonBar->Add(m_hyperspaceButton, 66, 2); | ||||
| 
 | ||||
|   launchButton = new Gui::ImageButton("icons/blastoff.png"); | ||||
|   launchButton->SetShortcut(SDLK_F5, KMOD_NONE); | ||||
|   launchButton->SetToolTip("Takeoff"); | ||||
|   launchButton->onClick.connect(sigc::mem_fun(this, &WorldView::OnClickBlastoff)); | ||||
|   m_rightButtonBar->Add(launchButton, 2, 2); | ||||
| 
 | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 Rtch90
						Rtch90