1
0
forked from 0ad/0ad

# GUI bug fixes.

Align rendered shapes to pixels, to avoid fuzzy textures and subpixel
gaps at unlucky screen sizes.
Reposition dropdown scrollbars correctly after dynamic size changes.
Fix mouse-drag selection of text in input controls.
Draw input selection background as a nicer size.
Support tooltips on lists.
Support 'enabled' on lists.
Fix crash when switching GUI pages in tick hander.

This was SVN commit r7649.
This commit is contained in:
Ykkrosh 2010-06-30 21:20:08 +00:00
parent 545979040b
commit e88391e5d8
6 changed files with 78 additions and 81 deletions

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2009 Wildfire Games.
/* Copyright (C) 2010 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -59,9 +59,9 @@ CDropDown::~CDropDown()
void CDropDown::SetupText()
{
CList::SetupText();
SetupListRect();
CList::SetupText();
}
void CDropDown::HandleMessage(const SGUIMessage &Message)
@ -71,36 +71,23 @@ void CDropDown::HandleMessage(const SGUIMessage &Message)
switch (Message.type)
{
case GUIM_SETTINGS_UPDATED:
bool scrollbar;
GUI<bool>::GetSetting(this, "scrollbar", scrollbar);
// Update scroll-bar
// TODO Gee: (2004-09-01) Is this really updated each time it should?
if (scrollbar &&
(Message.value == CStr("dropdown_size")/* ||
Message.value == CStr("")*/))
{
CRect rect = GetListRect();
GetScrollBar(0).SetX( rect.right );
GetScrollBar(0).SetY( rect.top );
GetScrollBar(0).SetZ( GetBufferedZ() );
GetScrollBar(0).SetLength( rect.bottom - rect.top );
}
{
// Update cached list rect
if (Message.value == CStr("size") ||
Message.value == CStr("absolute") ||
Message.value == CStr("dropdown_size") ||
Message.value == CStr("dropdown_buffer") ||
Message.value == CStr("scrollbar_style") ||
Message.value == CStr("button_width"))
if (Message.value == "size" ||
Message.value == "absolute" ||
Message.value == "dropdown_size" ||
Message.value == "dropdown_buffer" ||
Message.value == "scrollbar_style" ||
Message.value == "button_width")
{
SetupListRect();
}
break;
}
case GUIM_MOUSE_MOTION:{
case GUIM_MOUSE_MOTION:
{
if (m_Open)
{
CPos mouse = GetMousePos();
@ -141,22 +128,30 @@ void CDropDown::HandleMessage(const SGUIMessage &Message)
}
}
}break;
break;
}
case GUIM_MOUSE_LEAVE:{
case GUIM_MOUSE_LEAVE:
{
GUI<int>::GetSetting(this, "selected", m_ElementHighlight);
}break;
break;
}
// We can't inherent this routine from CList, because we need to include
// a mouse click to open the dropdown, also the coordinates are changed.
// We can't inherent this routine from CList, because we need to include
// a mouse click to open the dropdown, also the coordinates are changed.
case GUIM_MOUSE_PRESS_LEFT:
{
bool enabled;
GUI<bool>::GetSetting(this, "enabled", enabled);
if (!enabled)
break;
if (!m_Open)
{
m_Open = true;
GetScrollBar(0).SetPos(0.f);
GetScrollBar(0).SetZ( GetBufferedZ() );
GetScrollBar(0).SetZ(GetBufferedZ());
GUI<int>::GetSetting(this, "selected", m_ElementHighlight);
return; // overshadow
}
@ -168,7 +163,7 @@ void CDropDown::HandleMessage(const SGUIMessage &Message)
if (m_CachedActualSize.PointInside(mouse))
{
m_Open = false;
GetScrollBar(0).SetZ( GetBufferedZ() );
GetScrollBar(0).SetZ(GetBufferedZ());
return; // overshadow
}
@ -177,13 +172,14 @@ void CDropDown::HandleMessage(const SGUIMessage &Message)
mouse.y >= GetListRect().top)
{
m_Open = false;
GetScrollBar(0).SetZ( GetBufferedZ() );
GetScrollBar(0).SetZ(GetBufferedZ());
}
}
} break;
break;
}
case GUIM_LOST_FOCUS:
m_Open=false;
m_Open = false;
break;
case GUIM_LOAD:

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2009 Wildfire Games.
/* Copyright (C) 2010 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -456,9 +456,11 @@ InReaction CInput::ManuallyHandleEvent(const SDL_Event_* ev)
}
break;
}
return IN_HANDLED;
}
return IN_HANDLED;
return IN_PASS;
}
void CInput::HandleMessage(const SGUIMessage &Message)
@ -766,7 +768,7 @@ void CInput::Draw()
// If we have a selecting box (i.e. when you have selected letters, not just when
// the pointer is between two letters) we need to process all letters once
// before we do it the second time and render allt he text. We can't do it
// before we do it the second time and render all the text. We can't do it
// in the same loop because text will have been drawn, so it will disappear when
// drawn behind the text that has already been drawn. Confusing, well it's necessary
// (I think).
@ -851,9 +853,9 @@ void CInput::Draw()
if (multiline)
{
rect = CRect(m_CachedActualSize.left+box_x+buffer_zone,
m_CachedActualSize.top+buffered_y,
m_CachedActualSize.top+buffered_y+(h-ls)/2,
m_CachedActualSize.left+x_pointer+buffer_zone,
m_CachedActualSize.top+buffered_y+ls);
m_CachedActualSize.top+buffered_y+(h+ls)/2);
if (rect.bottom < m_CachedActualSize.top)
continue;
@ -867,9 +869,9 @@ void CInput::Draw()
else // if one-line
{
rect = CRect(m_CachedActualSize.left+box_x+buffer_zone-m_HorizontalScroll,
m_CachedActualSize.top+buffered_y,
m_CachedActualSize.top+buffered_y+(h-ls)/2,
m_CachedActualSize.left+x_pointer+buffer_zone-m_HorizontalScroll,
m_CachedActualSize.top+buffered_y+ls);
m_CachedActualSize.top+buffered_y+(h+ls)/2);
if (rect.left < m_CachedActualSize.left)
rect.left = m_CachedActualSize.left;

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2009 Wildfire Games.
/* Copyright (C) 2010 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -47,8 +47,8 @@ CList::CList()
AddSetting(GUIST_CColor, "textcolor");
AddSetting(GUIST_CColor, "textcolor_selected");
AddSetting(GUIST_int, "selected"); // Index selected. -1 is none.
//AddSetting(GUIST_CStr, "tooltip");
//AddSetting(GUIST_CStr, "tooltip_style");
AddSetting(GUIST_CStr, "tooltip");
AddSetting(GUIST_CStr, "tooltip_style");
AddSetting(GUIST_CGUIList, "list");
GUI<bool>::SetSetting(this, "scrollbar", false);
@ -75,8 +75,6 @@ void CList::SetupText()
CGUIList *pList;
GUI<CGUIList>::GetSettingPointer(this, "list", pList);
//LOG(CLogger::Error, LOG_CATEGORY, L"SetupText() %hs", GetPresentableName().c_str());
//debug_assert(m_GeneratedTexts.size()>=1);
m_ItemsYPositions.resize( pList->m_Items.size()+1 );
@ -137,6 +135,12 @@ void CList::SetupText()
{
GetScrollBar(0).SetScrollRange( m_ItemsYPositions.back() );
GetScrollBar(0).SetScrollSpace( GetListRect().GetHeight() );
CRect rect = GetListRect();
GetScrollBar(0).SetX( rect.right );
GetScrollBar(0).SetY( rect.top );
GetScrollBar(0).SetZ( GetBufferedZ() );
GetScrollBar(0).SetLength( rect.bottom - rect.top );
}
}
@ -151,20 +155,6 @@ void CList::HandleMessage(const SGUIMessage &Message)
bool scrollbar;
GUI<bool>::GetSetting(this, "scrollbar", scrollbar);
// Update scroll-bar
// TODO Gee: (2004-09-01) Is this really updated each time it should?
if (scrollbar &&
(Message.value == CStr("size") ||
Message.value == CStr("z") ||
Message.value == CStr("absolute")))
{
CRect rect = GetListRect();
GetScrollBar(0).SetX( rect.right );
GetScrollBar(0).SetY( rect.top );
GetScrollBar(0).SetZ( GetBufferedZ() );
GetScrollBar(0).SetLength( rect.bottom - rect.top );
}
if (Message.value == "list")
{
SetupText();
@ -179,13 +169,13 @@ void CList::HandleMessage(const SGUIMessage &Message)
ScriptEvent("selectionchange");
}
if (Message.value == CStr("scrollbar"))
if (Message.value == "scrollbar")
{
SetupText();
}
// Update scrollbar
if (Message.value == CStr("scrollbar_style"))
if (Message.value == "scrollbar_style")
{
CStr scrollbar_style;
GUI<CStr>::GetSetting(this, Message.value, scrollbar_style);
@ -199,6 +189,11 @@ void CList::HandleMessage(const SGUIMessage &Message)
case GUIM_MOUSE_PRESS_LEFT:
{
bool enabled;
GUI<bool>::GetSetting(this, "enabled", enabled);
if (!enabled)
break;
bool scrollbar;
CGUIList *pList;
GUI<bool>::GetSetting(this, "scrollbar", scrollbar);
@ -248,12 +243,6 @@ void CList::HandleMessage(const SGUIMessage &Message)
case GUIM_LOAD:
{
CRect rect = GetListRect();
GetScrollBar(0).SetX( rect.right );
GetScrollBar(0).SetY( rect.top );
GetScrollBar(0).SetZ( GetBufferedZ() );
GetScrollBar(0).SetLength( rect.bottom - rect.top );
CStr scrollbar_style;
GUI<CStr>::GetSetting(this, "scrollbar_style", scrollbar_style);
GetScrollBar(0).SetScrollBarStyle( scrollbar_style );
@ -302,7 +291,7 @@ InReaction CList::ManuallyHandleEvent(const SDL_Event_* ev)
break;
default: // Do nothing
break;
return IN_PASS;
}
return IN_HANDLED;

View File

@ -252,7 +252,10 @@ void CGUIManager::SendEventToAll(const CStr& eventName)
void CGUIManager::TickObjects()
{
for (PageStackType::iterator it = m_PageStack.begin(); it != m_PageStack.end(); ++it)
// Save an immutable copy so iterators aren't invalidated by tick handlers
PageStackType pageStack = m_PageStack;
for (PageStackType::iterator it = pageStack.begin(); it != pageStack.end(); ++it)
it->gui->TickObjects();
}

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2009 Wildfire Games.
/* Copyright (C) 2010 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -409,6 +409,11 @@ void GUIRenderer::UpdateDrawCallCache(DrawCalls &Calls, const CStr& SpriteName,
}
Call.m_Vertices = ObjectSize;
// Round the vertex coordinates to integers, to avoid ugly filtering artifacts
Call.m_Vertices.left = (int)(Call.m_Vertices.left + 0.5f);
Call.m_Vertices.right = (int)(Call.m_Vertices.right + 0.5f);
Call.m_Vertices.top = (int)(Call.m_Vertices.top + 0.5f);
Call.m_Vertices.bottom = (int)(Call.m_Vertices.bottom + 0.5f);
if (! cit->m_TextureName.empty())
{
@ -609,10 +614,10 @@ void GUIRenderer::Draw(DrawCalls &Calls)
{
glColor4fv(cit->m_BorderColor.FloatArray());
glBegin(GL_LINE_LOOP);
glVertex3f(cit->m_Vertices.left, cit->m_Vertices.top, cit->m_DeltaZ);
glVertex3f(cit->m_Vertices.right, cit->m_Vertices.top, cit->m_DeltaZ);
glVertex3f(cit->m_Vertices.right, cit->m_Vertices.bottom, cit->m_DeltaZ);
glVertex3f(cit->m_Vertices.left, cit->m_Vertices.bottom, cit->m_DeltaZ);
glVertex3f(cit->m_Vertices.left + 0.5f, cit->m_Vertices.top + 0.5f, cit->m_DeltaZ);
glVertex3f(cit->m_Vertices.right - 0.5f, cit->m_Vertices.top + 0.5f, cit->m_DeltaZ);
glVertex3f(cit->m_Vertices.right - 0.5f, cit->m_Vertices.bottom - 0.5f, cit->m_DeltaZ);
glVertex3f(cit->m_Vertices.left + 0.5f, cit->m_Vertices.bottom - 0.5f, cit->m_DeltaZ);
glEnd();
}
}

View File

@ -149,7 +149,7 @@ void IGUIObject::AddToPointersMap(map_pObjects &ObjectMap)
}
if (ObjectMap.count(m_Name) > 0)
{
throw PSERROR_GUI_NameAmbiguity();
throw PSERROR_GUI_NameAmbiguity(m_Name.c_str());
}
else
{
@ -449,9 +449,11 @@ void IGUIObject::RegisterScriptHandler(const CStr& Action, const CStr& Code, CGU
JSFunction* func = JS_CompileFunction(g_ScriptingHost.getContext(), pGUI->m_ScriptObject,
buf, paramCount, paramNames, Code.c_str(), Code.length(), CodeName, 0);
debug_assert(func); // TODO: Handle errors
if (func)
SetScriptHandler(Action, JS_GetFunctionObject(func));
if (!func)
return; // JS will report an error message
SetScriptHandler(Action, JS_GetFunctionObject(func));
}
void IGUIObject::SetScriptHandler(const CStr& Action, JSObject* Function)