2019-01-24 21:00:31 +01:00
|
|
|
/* Copyright (C) 2019 Wildfire Games.
|
2014-06-05 16:33:44 +02:00
|
|
|
* This file is part of 0 A.D.
|
|
|
|
*
|
|
|
|
* 0 A.D. 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.
|
|
|
|
*
|
|
|
|
* 0 A.D. 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 0 A.D. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
2015-08-21 19:08:41 +02:00
|
|
|
|
2013-11-07 21:07:24 +01:00
|
|
|
#include "precompiled.h"
|
2015-08-21 19:08:41 +02:00
|
|
|
|
2013-11-07 21:07:24 +01:00
|
|
|
#include "COList.h"
|
|
|
|
|
2019-09-18 22:51:45 +02:00
|
|
|
#include "gui/CGUI.h"
|
2019-07-26 20:57:28 +02:00
|
|
|
#include "gui/CGUIColor.h"
|
2019-09-20 15:11:18 +02:00
|
|
|
#include "gui/CGUIList.h"
|
|
|
|
#include "gui/IGUIScrollBar.h"
|
2015-08-21 19:08:41 +02:00
|
|
|
#include "i18n/L10n.h"
|
2013-11-07 21:07:24 +01:00
|
|
|
#include "ps/CLogger.h"
|
|
|
|
|
2019-01-24 21:00:31 +01:00
|
|
|
const float SORT_SPRITE_DIM = 16.0f;
|
|
|
|
const CPos COLUMN_SHIFT = CPos(0, 4);
|
|
|
|
|
2019-08-21 12:12:33 +02:00
|
|
|
COList::COList(CGUI& pGUI)
|
2019-08-01 22:20:24 +02:00
|
|
|
: CList(pGUI), IGUIObject(pGUI)
|
2013-11-07 21:07:24 +01:00
|
|
|
{
|
2019-08-04 04:20:08 +02:00
|
|
|
AddSetting<CGUISpriteInstance>("sprite_heading");
|
|
|
|
AddSetting<bool>("sortable"); // The actual sorting is done in JS for more versatility
|
|
|
|
AddSetting<CStr>("selected_column");
|
Move static GUI<>::SetSetting operating on IGUIObject to a member IGUIObject::SetSetting.
Remove PSERROR codes from SetSetting (let std::map throw an out_of_range
if a caller wants to Set a setting that doesn't exist without having
checked with SettingExists, equal to GetSetting from 92b6cdfeab).
That also simplifies std::function SetSettingWrap construct from
0a7d0ecdde to void IGUIObject::SettingChanged.
Don't trigger debug_warn or exceptions in GUITooltip::ShowTooltip if the
XML author specified wrong tooltip input, and dodge another
dynamic_cast.
Rename existing IGUIObject::SetSetting to
IGUIObject::SetSettingFromString and comment that it is purposed for
parsing XML files.
Remove SetSetting default value, so that authors are made aware
explicitly of the need to decide the function broadcasting a message,
refs d87057b1c0, 719f2d7967, ...
Change const bool& SkipMessage to const bool SendMessage, so that a
positive value relates to a positive action.
Clean AddSettings whitespace and integer types.
Differential Revision: https://code.wildfiregames.com/D2231
Tested on: gcc 9.1.0, clang 8.0.1, Jenkins
Comments By: Philip on IRC on 2010-07-24 on GUIUtil being ugly, in case
that one counts
This was SVN commit r22796.
2019-08-28 13:21:11 +02:00
|
|
|
AddSetting<i32>("selected_column_order");
|
2019-08-04 04:20:08 +02:00
|
|
|
AddSetting<CGUISpriteInstance>("sprite_asc"); // Show the order of sorting
|
|
|
|
AddSetting<CGUISpriteInstance>("sprite_desc");
|
|
|
|
AddSetting<CGUISpriteInstance>("sprite_not_sorted");
|
2013-11-07 21:07:24 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void COList::SetupText()
|
|
|
|
{
|
2019-08-26 14:25:07 +02:00
|
|
|
const CGUIList& pList = GetSetting<CGUIList>("list");
|
2019-08-19 12:32:29 +02:00
|
|
|
m_ItemsYPositions.resize(pList.m_Items.size() + 1);
|
2013-11-07 21:07:24 +01:00
|
|
|
|
|
|
|
// Delete all generated texts. Some could probably be saved,
|
|
|
|
// but this is easier, and this function will never be called
|
|
|
|
// continuously, or even often, so it'll probably be okay.
|
|
|
|
m_GeneratedTexts.clear();
|
|
|
|
|
2019-08-26 14:25:07 +02:00
|
|
|
const CStrW& font = GetSetting<CStrW>("font");
|
|
|
|
const bool scrollbar = GetSetting<bool>("scrollbar");
|
2013-11-07 21:07:24 +01:00
|
|
|
|
2019-01-24 21:00:31 +01:00
|
|
|
m_TotalAvailableColumnWidth = GetListRect().GetWidth();
|
2013-11-07 21:07:24 +01:00
|
|
|
// remove scrollbar if applicable
|
|
|
|
if (scrollbar && GetScrollBar(0).GetStyle())
|
2019-01-24 21:00:31 +01:00
|
|
|
m_TotalAvailableColumnWidth -= GetScrollBar(0).GetStyle()->m_Width;
|
2013-11-07 21:07:24 +01:00
|
|
|
|
2019-08-26 14:25:07 +02:00
|
|
|
const float buffer_zone = GetSetting<float>("buffer_zone");
|
2013-11-07 21:07:24 +01:00
|
|
|
|
2019-01-24 21:00:31 +01:00
|
|
|
m_HeadingHeight = SORT_SPRITE_DIM; // At least the size of the sorting sprite
|
|
|
|
|
|
|
|
for (const COListColumn& column : m_Columns)
|
2013-11-07 21:07:24 +01:00
|
|
|
{
|
2019-01-24 21:00:31 +01:00
|
|
|
float width = column.m_Width;
|
|
|
|
if (column.m_Width > 0 && column.m_Width < 1)
|
|
|
|
width *= m_TotalAvailableColumnWidth;
|
|
|
|
|
2013-11-07 21:07:24 +01:00
|
|
|
CGUIString gui_string;
|
2016-08-31 21:29:48 +02:00
|
|
|
gui_string.SetValue(column.m_Heading);
|
Move CGUI::GenerateText to CGUIText constructor, CGUI::DrawText to CGUIText::Draw, SGenerateTextImage from CGUI to CGUIText.
Makes GUI text construction 30x faster for empty strings, otherwise less
than 1% faster.
Split the constructor into smaller helper functions to reduce nesting
and improve readability.
Change m_GeneratedTexts from pointer to reference, so that one doesn't
have to keep track to delete it correctly in several places, without
having to resort to copy or move assignments but constructing in place.
Mark CGUIText as NONCOPYABLE and MOVABLE which is already implicitly the
case due to the CGUISpriteInstance members, refs 0a7d0ecdde/D2133,
D2163/3028551b91.
Differential Revision: https://code.wildfiregames.com/D2168
Prepared by the GUIText.h file split in 838889ab12 / D2167.
Comments By: Vladislav
Tested on: gcc 9, clang 8, VS2015, Jenkins
Inlining tested using: clang -Rpass=inline and gcc -Winline
This was SVN commit r22679.
2019-08-17 03:32:11 +02:00
|
|
|
|
|
|
|
const CGUIText& text = AddText(gui_string, font, width, buffer_zone, this);
|
|
|
|
m_HeadingHeight = std::max(m_HeadingHeight, text.GetSize().cy + COLUMN_SHIFT.y);
|
2016-01-18 20:23:14 +01:00
|
|
|
}
|
|
|
|
|
2013-11-07 21:07:24 +01:00
|
|
|
// Generate texts
|
|
|
|
float buffered_y = 0.f;
|
|
|
|
|
2019-08-19 12:32:29 +02:00
|
|
|
for (size_t i = 0; i < pList.m_Items.size(); ++i)
|
2013-11-07 21:07:24 +01:00
|
|
|
{
|
|
|
|
m_ItemsYPositions[i] = buffered_y;
|
2017-03-17 02:10:49 +01:00
|
|
|
float shift = 0.0f;
|
2019-01-24 21:00:31 +01:00
|
|
|
for (const COListColumn& column : m_Columns)
|
2013-11-07 21:07:24 +01:00
|
|
|
{
|
2019-01-24 21:00:31 +01:00
|
|
|
float width = column.m_Width;
|
|
|
|
if (column.m_Width > 0 && column.m_Width < 1)
|
|
|
|
width *= m_TotalAvailableColumnWidth;
|
|
|
|
|
2019-08-26 14:25:07 +02:00
|
|
|
CGUIList& pList_c = GetSetting<CGUIList>("list_" + column.m_Id);
|
Move CGUI::GenerateText to CGUIText constructor, CGUI::DrawText to CGUIText::Draw, SGenerateTextImage from CGUI to CGUIText.
Makes GUI text construction 30x faster for empty strings, otherwise less
than 1% faster.
Split the constructor into smaller helper functions to reduce nesting
and improve readability.
Change m_GeneratedTexts from pointer to reference, so that one doesn't
have to keep track to delete it correctly in several places, without
having to resort to copy or move assignments but constructing in place.
Mark CGUIText as NONCOPYABLE and MOVABLE which is already implicitly the
case due to the CGUISpriteInstance members, refs 0a7d0ecdde/D2133,
D2163/3028551b91.
Differential Revision: https://code.wildfiregames.com/D2168
Prepared by the GUIText.h file split in 838889ab12 / D2167.
Comments By: Vladislav
Tested on: gcc 9, clang 8, VS2015, Jenkins
Inlining tested using: clang -Rpass=inline and gcc -Winline
This was SVN commit r22679.
2019-08-17 03:32:11 +02:00
|
|
|
CGUIText* text;
|
2019-08-19 12:32:29 +02:00
|
|
|
if (!pList_c.m_Items[i].GetOriginalString().empty())
|
|
|
|
text = &AddText(pList_c.m_Items[i], font, width, buffer_zone, this);
|
2017-03-17 02:10:49 +01:00
|
|
|
else
|
|
|
|
{
|
|
|
|
// Minimum height of a space character of the current font size
|
|
|
|
CGUIString align_string;
|
|
|
|
align_string.SetValue(L" ");
|
Move CGUI::GenerateText to CGUIText constructor, CGUI::DrawText to CGUIText::Draw, SGenerateTextImage from CGUI to CGUIText.
Makes GUI text construction 30x faster for empty strings, otherwise less
than 1% faster.
Split the constructor into smaller helper functions to reduce nesting
and improve readability.
Change m_GeneratedTexts from pointer to reference, so that one doesn't
have to keep track to delete it correctly in several places, without
having to resort to copy or move assignments but constructing in place.
Mark CGUIText as NONCOPYABLE and MOVABLE which is already implicitly the
case due to the CGUISpriteInstance members, refs 0a7d0ecdde/D2133,
D2163/3028551b91.
Differential Revision: https://code.wildfiregames.com/D2168
Prepared by the GUIText.h file split in 838889ab12 / D2167.
Comments By: Vladislav
Tested on: gcc 9, clang 8, VS2015, Jenkins
Inlining tested using: clang -Rpass=inline and gcc -Winline
This was SVN commit r22679.
2019-08-17 03:32:11 +02:00
|
|
|
text = &AddText(align_string, font, width, buffer_zone, this);
|
2017-03-17 02:10:49 +01:00
|
|
|
}
|
Move CGUI::GenerateText to CGUIText constructor, CGUI::DrawText to CGUIText::Draw, SGenerateTextImage from CGUI to CGUIText.
Makes GUI text construction 30x faster for empty strings, otherwise less
than 1% faster.
Split the constructor into smaller helper functions to reduce nesting
and improve readability.
Change m_GeneratedTexts from pointer to reference, so that one doesn't
have to keep track to delete it correctly in several places, without
having to resort to copy or move assignments but constructing in place.
Mark CGUIText as NONCOPYABLE and MOVABLE which is already implicitly the
case due to the CGUISpriteInstance members, refs 0a7d0ecdde/D2133,
D2163/3028551b91.
Differential Revision: https://code.wildfiregames.com/D2168
Prepared by the GUIText.h file split in 838889ab12 / D2167.
Comments By: Vladislav
Tested on: gcc 9, clang 8, VS2015, Jenkins
Inlining tested using: clang -Rpass=inline and gcc -Winline
This was SVN commit r22679.
2019-08-17 03:32:11 +02:00
|
|
|
shift = std::max(shift, text->GetSize().cy);
|
2013-11-07 21:07:24 +01:00
|
|
|
}
|
2017-03-17 02:10:49 +01:00
|
|
|
buffered_y += shift;
|
2013-11-07 21:07:24 +01:00
|
|
|
}
|
|
|
|
|
2019-08-19 12:32:29 +02:00
|
|
|
m_ItemsYPositions[pList.m_Items.size()] = buffered_y;
|
2013-11-07 21:07:24 +01:00
|
|
|
|
|
|
|
if (scrollbar)
|
|
|
|
{
|
2016-08-31 21:29:48 +02:00
|
|
|
CRect rect = GetListRect();
|
2015-08-21 19:08:41 +02:00
|
|
|
GetScrollBar(0).SetScrollRange(m_ItemsYPositions.back());
|
2016-08-31 21:29:48 +02:00
|
|
|
GetScrollBar(0).SetScrollSpace(rect.GetHeight());
|
2013-11-07 21:07:24 +01:00
|
|
|
|
2015-08-21 19:08:41 +02:00
|
|
|
GetScrollBar(0).SetX(rect.right);
|
|
|
|
GetScrollBar(0).SetY(rect.top);
|
|
|
|
GetScrollBar(0).SetZ(GetBufferedZ());
|
|
|
|
GetScrollBar(0).SetLength(rect.bottom - rect.top);
|
2013-11-07 21:07:24 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
CRect COList::GetListRect() const
|
|
|
|
{
|
2019-01-24 21:00:31 +01:00
|
|
|
return m_CachedActualSize + CRect(0, m_HeadingHeight, 0, 0);
|
2013-11-07 21:07:24 +01:00
|
|
|
}
|
|
|
|
|
2015-08-21 19:08:41 +02:00
|
|
|
void COList::HandleMessage(SGUIMessage& Message)
|
2013-11-07 21:07:24 +01:00
|
|
|
{
|
|
|
|
CList::HandleMessage(Message);
|
2015-06-17 11:10:50 +02:00
|
|
|
|
|
|
|
switch (Message.type)
|
|
|
|
{
|
|
|
|
// If somebody clicks on the column heading
|
|
|
|
case GUIM_MOUSE_PRESS_LEFT:
|
|
|
|
{
|
2019-08-26 14:25:07 +02:00
|
|
|
if (!GetSetting<bool>("sortable"))
|
2015-06-17 11:10:50 +02:00
|
|
|
return;
|
|
|
|
|
2019-08-21 12:12:33 +02:00
|
|
|
const CPos& mouse = m_pGUI.GetMousePos();
|
2015-06-17 11:10:50 +02:00
|
|
|
if (!m_CachedActualSize.PointInside(mouse))
|
|
|
|
return;
|
2015-08-21 19:08:41 +02:00
|
|
|
|
2019-08-23 16:43:10 +02:00
|
|
|
// Copies, so that these settings are only modfied via SetSettings later.
|
2019-08-26 14:25:07 +02:00
|
|
|
CStr selectedColumn = GetSetting<CStr>("selected_column");
|
|
|
|
int selectedColumnOrder = GetSetting<i32>("selected_column_order");
|
2016-08-31 21:29:48 +02:00
|
|
|
|
2015-06-17 11:10:50 +02:00
|
|
|
float xpos = 0;
|
2019-01-24 21:00:31 +01:00
|
|
|
for (const COListColumn& column : m_Columns)
|
2015-06-17 11:10:50 +02:00
|
|
|
{
|
2019-08-26 14:25:07 +02:00
|
|
|
if (GetSetting<bool>("hidden_" + column.m_Id))
|
2017-03-28 02:25:17 +02:00
|
|
|
continue;
|
|
|
|
|
2016-08-31 21:29:48 +02:00
|
|
|
float width = column.m_Width;
|
2015-06-17 11:10:50 +02:00
|
|
|
// Check if it's a decimal value, and if so, assume relative positioning.
|
2016-08-31 21:29:48 +02:00
|
|
|
if (column.m_Width < 1 && column.m_Width > 0)
|
|
|
|
width *= m_TotalAvailableColumnWidth;
|
2015-09-02 19:55:02 +02:00
|
|
|
CPos leftTopCorner = m_CachedActualSize.TopLeft() + CPos(xpos, 0);
|
2015-06-17 11:10:50 +02:00
|
|
|
if (mouse.x >= leftTopCorner.x &&
|
|
|
|
mouse.x < leftTopCorner.x + width &&
|
2019-01-24 21:00:31 +01:00
|
|
|
mouse.y < leftTopCorner.y + m_HeadingHeight)
|
2015-06-17 11:10:50 +02:00
|
|
|
{
|
2016-08-31 21:29:48 +02:00
|
|
|
if (column.m_Id != selectedColumn)
|
2015-06-17 11:10:50 +02:00
|
|
|
{
|
2016-08-31 21:29:48 +02:00
|
|
|
selectedColumnOrder = 1;
|
|
|
|
selectedColumn = column.m_Id;
|
2015-06-17 11:10:50 +02:00
|
|
|
}
|
|
|
|
else
|
2016-08-31 21:29:48 +02:00
|
|
|
selectedColumnOrder = -selectedColumnOrder;
|
2019-08-23 16:43:10 +02:00
|
|
|
|
Move static GUI<>::SetSetting operating on IGUIObject to a member IGUIObject::SetSetting.
Remove PSERROR codes from SetSetting (let std::map throw an out_of_range
if a caller wants to Set a setting that doesn't exist without having
checked with SettingExists, equal to GetSetting from 92b6cdfeab).
That also simplifies std::function SetSettingWrap construct from
0a7d0ecdde to void IGUIObject::SettingChanged.
Don't trigger debug_warn or exceptions in GUITooltip::ShowTooltip if the
XML author specified wrong tooltip input, and dodge another
dynamic_cast.
Rename existing IGUIObject::SetSetting to
IGUIObject::SetSettingFromString and comment that it is purposed for
parsing XML files.
Remove SetSetting default value, so that authors are made aware
explicitly of the need to decide the function broadcasting a message,
refs d87057b1c0, 719f2d7967, ...
Change const bool& SkipMessage to const bool SendMessage, so that a
positive value relates to a positive action.
Clean AddSettings whitespace and integer types.
Differential Revision: https://code.wildfiregames.com/D2231
Tested on: gcc 9.1.0, clang 8.0.1, Jenkins
Comments By: Philip on IRC on 2010-07-24 on GUIUtil being ugly, in case
that one counts
This was SVN commit r22796.
2019-08-28 13:21:11 +02:00
|
|
|
SetSetting<CStr>("selected_column", selectedColumn, true);
|
|
|
|
SetSetting<i32>("selected_column_order", selectedColumnOrder, true);
|
2015-06-17 11:10:50 +02:00
|
|
|
|
2019-08-23 16:43:10 +02:00
|
|
|
ScriptEvent("selectioncolumnchange");
|
2019-08-23 00:34:12 +02:00
|
|
|
PlaySound("sound_selected");
|
2015-06-17 11:10:50 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
xpos += width;
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
return;
|
|
|
|
}
|
2013-11-07 21:07:24 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
bool COList::HandleAdditionalChildren(const XMBElement& child, CXeromyces* pFile)
|
|
|
|
{
|
2014-04-20 22:03:57 +02:00
|
|
|
#define ELMT(x) int elmt_##x = pFile->GetElementID(#x)
|
|
|
|
#define ATTR(x) int attr_##x = pFile->GetAttributeID(#x)
|
|
|
|
ELMT(item);
|
2016-08-31 21:29:48 +02:00
|
|
|
ELMT(column);
|
2014-04-20 22:03:57 +02:00
|
|
|
ELMT(translatableAttribute);
|
|
|
|
ATTR(id);
|
2014-05-01 00:33:08 +02:00
|
|
|
ATTR(context);
|
2013-11-07 21:07:24 +01:00
|
|
|
|
|
|
|
if (child.GetNodeName() == elmt_item)
|
|
|
|
{
|
|
|
|
AddItem(child.GetText().FromUTF8(), child.GetText().FromUTF8());
|
|
|
|
return true;
|
|
|
|
}
|
2016-08-31 21:29:48 +02:00
|
|
|
else if (child.GetNodeName() == elmt_column)
|
2013-11-07 21:07:24 +01:00
|
|
|
{
|
2016-08-31 21:29:48 +02:00
|
|
|
COListColumn column;
|
2017-03-28 02:25:17 +02:00
|
|
|
bool hidden = false;
|
2013-11-07 21:07:24 +01:00
|
|
|
|
2015-06-01 02:29:35 +02:00
|
|
|
for (XMBAttribute attr : child.GetAttributes())
|
2013-11-07 21:07:24 +01:00
|
|
|
{
|
2015-08-21 19:08:41 +02:00
|
|
|
CStr attr_name(pFile->GetAttributeString(attr.Name));
|
|
|
|
CStr attr_value(attr.Value);
|
2013-11-07 21:07:24 +01:00
|
|
|
|
|
|
|
if (attr_name == "color")
|
|
|
|
{
|
2019-08-29 11:07:29 +02:00
|
|
|
if (!CGUI::ParseString<CGUIColor>(&m_pGUI, attr_value.FromUTF8(), column.m_TextColor))
|
2015-01-22 21:36:24 +01:00
|
|
|
LOGERROR("GUI: Error parsing '%s' (\"%s\")", attr_name.c_str(), attr_value.c_str());
|
2013-11-07 21:07:24 +01:00
|
|
|
}
|
|
|
|
else if (attr_name == "id")
|
|
|
|
{
|
2016-08-31 21:29:48 +02:00
|
|
|
column.m_Id = attr_value;
|
2013-11-07 21:07:24 +01:00
|
|
|
}
|
2017-03-28 02:25:17 +02:00
|
|
|
else if (attr_name == "hidden")
|
|
|
|
{
|
2019-08-29 11:07:29 +02:00
|
|
|
if (!CGUI::ParseString<bool>(&m_pGUI, attr_value.FromUTF8(), hidden))
|
2017-03-28 02:25:17 +02:00
|
|
|
LOGERROR("GUI: Error parsing '%s' (\"%s\")", attr_name.c_str(), attr_value.c_str());
|
|
|
|
}
|
2013-11-07 21:07:24 +01:00
|
|
|
else if (attr_name == "width")
|
|
|
|
{
|
|
|
|
float width;
|
2019-08-29 11:07:29 +02:00
|
|
|
if (!CGUI::ParseString<float>(&m_pGUI, attr_value.FromUTF8(), width))
|
2015-01-22 21:36:24 +01:00
|
|
|
LOGERROR("GUI: Error parsing '%s' (\"%s\")", attr_name.c_str(), attr_value.c_str());
|
2013-11-07 21:07:24 +01:00
|
|
|
else
|
|
|
|
{
|
|
|
|
// Check if it's a relative value, and save as decimal if so.
|
|
|
|
if (attr_value.find("%") != std::string::npos)
|
|
|
|
width = width / 100.f;
|
2016-08-31 21:29:48 +02:00
|
|
|
column.m_Width = width;
|
2013-11-07 21:07:24 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (attr_name == "heading")
|
|
|
|
{
|
2016-08-31 21:29:48 +02:00
|
|
|
column.m_Heading = attr_value.FromUTF8();
|
2013-11-07 21:07:24 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-06-01 02:29:35 +02:00
|
|
|
for (XMBElement grandchild : child.GetChildNodes())
|
2014-04-20 22:03:57 +02:00
|
|
|
{
|
2015-08-21 19:08:41 +02:00
|
|
|
if (grandchild.GetNodeName() != elmt_translatableAttribute)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
CStr attributeName(grandchild.GetAttributes().GetNamedItem(attr_id));
|
2016-08-31 21:29:48 +02:00
|
|
|
// only the heading is translatable for list column
|
2015-08-21 19:08:41 +02:00
|
|
|
if (attributeName.empty() || attributeName != "heading")
|
2014-04-20 22:03:57 +02:00
|
|
|
{
|
2016-08-31 21:29:48 +02:00
|
|
|
LOGERROR("GUI: translatable attribute in olist column that isn't a heading. (object: %s)", this->GetPresentableName().c_str());
|
2015-08-21 19:08:41 +02:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
CStr value(grandchild.GetText());
|
|
|
|
if (value.empty())
|
|
|
|
continue;
|
|
|
|
|
|
|
|
CStr context(grandchild.GetAttributes().GetNamedItem(attr_context)); // Read the context if any.
|
|
|
|
if (!context.empty())
|
|
|
|
{
|
|
|
|
CStr translatedValue(g_L10n.TranslateWithContext(context, value));
|
2016-08-31 21:29:48 +02:00
|
|
|
column.m_Heading = translatedValue.FromUTF8();
|
2015-08-21 19:08:41 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
CStr translatedValue(g_L10n.Translate(value));
|
2016-08-31 21:29:48 +02:00
|
|
|
column.m_Heading = translatedValue.FromUTF8();
|
2014-04-20 22:03:57 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-08-04 04:20:08 +02:00
|
|
|
AddSetting<CGUIList>("list_" + column.m_Id);
|
|
|
|
AddSetting<bool>("hidden_" + column.m_Id);
|
Move static GUI<>::SetSetting operating on IGUIObject to a member IGUIObject::SetSetting.
Remove PSERROR codes from SetSetting (let std::map throw an out_of_range
if a caller wants to Set a setting that doesn't exist without having
checked with SettingExists, equal to GetSetting from 92b6cdfeab).
That also simplifies std::function SetSettingWrap construct from
0a7d0ecdde to void IGUIObject::SettingChanged.
Don't trigger debug_warn or exceptions in GUITooltip::ShowTooltip if the
XML author specified wrong tooltip input, and dodge another
dynamic_cast.
Rename existing IGUIObject::SetSetting to
IGUIObject::SetSettingFromString and comment that it is purposed for
parsing XML files.
Remove SetSetting default value, so that authors are made aware
explicitly of the need to decide the function broadcasting a message,
refs d87057b1c0, 719f2d7967, ...
Change const bool& SkipMessage to const bool SendMessage, so that a
positive value relates to a positive action.
Clean AddSettings whitespace and integer types.
Differential Revision: https://code.wildfiregames.com/D2231
Tested on: gcc 9.1.0, clang 8.0.1, Jenkins
Comments By: Philip on IRC on 2010-07-24 on GUIUtil being ugly, in case
that one counts
This was SVN commit r22796.
2019-08-28 13:21:11 +02:00
|
|
|
SetSetting<bool>("hidden_" + column.m_Id, hidden, true);
|
2017-03-28 02:25:17 +02:00
|
|
|
|
Use NONCOPYABLE for most GUI classes and structs to have the compiler indicate unintended copies, refs 3028551b91 / D2163.
That is CChartData, CGUIList, CGUISeries, COListColumn, GUITooltip,
SGUIMessage, SSpriteCall, STextCall, SFeedback, IGUISetting,
CGUISetting, GUI, IGUIObject, IGUIScrollBar.
Drop copying GetSetting and SetSetting template functions for CGUIList,
CGUISeries, CClientArea, CGUIString.
Stop copying COListColumn.
Drop copying GUI<CClientArea>::GetSetting call in
IGUIObject::UpdateCachedSize() and four copying
GUI<CGUIString>::GetSetting calls in SetupText() functions.
Delete unused GUIRenderer IGLState class from 849f50a500 obsolete since
1f5b8f1c9a.
Differential Revision: https://code.wildfiregames.com/D2164
This was SVN commit r22638.
2019-08-10 02:04:17 +02:00
|
|
|
m_Columns.emplace_back(std::move(column));
|
|
|
|
|
2013-11-07 21:07:24 +01:00
|
|
|
SetupText();
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
Use NONCOPYABLE for most GUI classes and structs to have the compiler indicate unintended copies, refs 3028551b91 / D2163.
That is CChartData, CGUIList, CGUISeries, COListColumn, GUITooltip,
SGUIMessage, SSpriteCall, STextCall, SFeedback, IGUISetting,
CGUISetting, GUI, IGUIObject, IGUIScrollBar.
Drop copying GetSetting and SetSetting template functions for CGUIList,
CGUISeries, CClientArea, CGUIString.
Stop copying COListColumn.
Drop copying GUI<CClientArea>::GetSetting call in
IGUIObject::UpdateCachedSize() and four copying
GUI<CGUIString>::GetSetting calls in SetupText() functions.
Delete unused GUIRenderer IGLState class from 849f50a500 obsolete since
1f5b8f1c9a.
Differential Revision: https://code.wildfiregames.com/D2164
This was SVN commit r22638.
2019-08-10 02:04:17 +02:00
|
|
|
|
|
|
|
return false;
|
2013-11-07 21:07:24 +01:00
|
|
|
}
|
|
|
|
|
2015-08-21 19:08:41 +02:00
|
|
|
void COList::DrawList(const int& selected, const CStr& _sprite, const CStr& _sprite_selected, const CStr& _textcolor)
|
2013-11-07 21:07:24 +01:00
|
|
|
{
|
2019-08-23 16:43:10 +02:00
|
|
|
const float bz = GetBufferedZ();
|
2019-08-26 14:25:07 +02:00
|
|
|
const bool scrollbar = GetSetting<bool>("scrollbar");
|
2013-11-07 21:07:24 +01:00
|
|
|
|
|
|
|
if (scrollbar)
|
|
|
|
IGUIScrollBarOwner::Draw();
|
|
|
|
|
2015-08-21 19:08:41 +02:00
|
|
|
CRect rect = GetListRect();
|
2013-11-07 21:07:24 +01:00
|
|
|
|
2019-08-26 14:25:07 +02:00
|
|
|
CGUISpriteInstance& sprite = GetSetting<CGUISpriteInstance>(_sprite);
|
|
|
|
CGUISpriteInstance& sprite_selectarea = GetSetting<CGUISpriteInstance>(_sprite_selected);
|
2019-08-19 12:32:29 +02:00
|
|
|
|
2019-08-26 14:25:07 +02:00
|
|
|
const int cell_id = GetSetting<i32>("cell_id");
|
2013-11-07 21:07:24 +01:00
|
|
|
|
2019-08-21 12:12:33 +02:00
|
|
|
m_pGUI.DrawSprite(sprite, cell_id, bz, rect);
|
2013-11-07 21:07:24 +01:00
|
|
|
|
2015-08-21 19:08:41 +02:00
|
|
|
float scroll = 0.f;
|
|
|
|
if (scrollbar)
|
|
|
|
scroll = GetScrollBar(0).GetPos();
|
2013-11-07 21:07:24 +01:00
|
|
|
|
2015-09-02 19:55:02 +02:00
|
|
|
// Draw item selection
|
2015-08-21 19:08:41 +02:00
|
|
|
if (selected != -1)
|
|
|
|
{
|
|
|
|
ENSURE(selected >= 0 && selected+1 < (int)m_ItemsYPositions.size());
|
2013-11-07 21:07:24 +01:00
|
|
|
|
2015-08-21 19:08:41 +02:00
|
|
|
// Get rectangle of selection:
|
|
|
|
CRect rect_sel(rect.left, rect.top + m_ItemsYPositions[selected] - scroll,
|
|
|
|
rect.right, rect.top + m_ItemsYPositions[selected+1] - scroll);
|
2013-11-07 21:07:24 +01:00
|
|
|
|
2015-08-21 19:08:41 +02:00
|
|
|
if (rect_sel.top <= rect.bottom &&
|
|
|
|
rect_sel.bottom >= rect.top)
|
|
|
|
{
|
|
|
|
if (rect_sel.bottom > rect.bottom)
|
|
|
|
rect_sel.bottom = rect.bottom;
|
|
|
|
if (rect_sel.top < rect.top)
|
|
|
|
rect_sel.top = rect.top;
|
2013-11-07 21:07:24 +01:00
|
|
|
|
2015-08-21 19:08:41 +02:00
|
|
|
if (scrollbar)
|
|
|
|
{
|
|
|
|
// Remove any overlapping area of the scrollbar.
|
|
|
|
if (rect_sel.right > GetScrollBar(0).GetOuterRect().left &&
|
|
|
|
rect_sel.right <= GetScrollBar(0).GetOuterRect().right)
|
|
|
|
rect_sel.right = GetScrollBar(0).GetOuterRect().left;
|
|
|
|
|
|
|
|
if (rect_sel.left >= GetScrollBar(0).GetOuterRect().left &&
|
|
|
|
rect_sel.left < GetScrollBar(0).GetOuterRect().right)
|
|
|
|
rect_sel.left = GetScrollBar(0).GetOuterRect().right;
|
2013-11-07 21:07:24 +01:00
|
|
|
}
|
2015-08-21 19:08:41 +02:00
|
|
|
|
2015-09-02 19:55:02 +02:00
|
|
|
// Draw item selection
|
2019-08-21 12:12:33 +02:00
|
|
|
m_pGUI.DrawSprite(sprite_selectarea, cell_id, bz+0.05f, rect_sel);
|
2013-11-07 21:07:24 +01:00
|
|
|
}
|
2015-08-21 19:08:41 +02:00
|
|
|
}
|
2013-11-07 21:07:24 +01:00
|
|
|
|
2015-09-02 19:55:02 +02:00
|
|
|
// Draw line above column header
|
2019-08-26 14:25:07 +02:00
|
|
|
CGUISpriteInstance& sprite_heading = GetSetting<CGUISpriteInstance>("sprite_heading");
|
2015-08-21 19:08:41 +02:00
|
|
|
CRect rect_head(m_CachedActualSize.left, m_CachedActualSize.top, m_CachedActualSize.right,
|
2019-01-24 21:00:31 +01:00
|
|
|
m_CachedActualSize.top + m_HeadingHeight);
|
2019-08-21 12:12:33 +02:00
|
|
|
m_pGUI.DrawSprite(sprite_heading, cell_id, bz, rect_head);
|
2015-06-17 11:10:50 +02:00
|
|
|
|
2016-09-04 00:22:11 +02:00
|
|
|
// Draw column headers
|
2019-08-26 14:25:07 +02:00
|
|
|
const bool sortable = GetSetting<bool>("sortable");
|
|
|
|
const CStr& selectedColumn = GetSetting<CStr>("selected_column");
|
|
|
|
const int selectedColumnOrder = GetSetting<i32>("selected_column_order");
|
|
|
|
const CGUIColor& color = GetSetting<CGUIColor>(_textcolor);
|
2016-09-04 00:22:11 +02:00
|
|
|
|
2015-08-21 19:08:41 +02:00
|
|
|
float xpos = 0;
|
2016-08-31 21:29:48 +02:00
|
|
|
for (size_t col = 0; col < m_Columns.size(); ++col)
|
2015-08-21 19:08:41 +02:00
|
|
|
{
|
2019-08-26 14:25:07 +02:00
|
|
|
if (GetSetting<bool>("hidden_" + m_Columns[col].m_Id))
|
2017-03-28 02:25:17 +02:00
|
|
|
continue;
|
|
|
|
|
2015-08-21 19:08:41 +02:00
|
|
|
// Check if it's a decimal value, and if so, assume relative positioning.
|
2016-08-31 21:29:48 +02:00
|
|
|
float width = m_Columns[col].m_Width;
|
|
|
|
if (m_Columns[col].m_Width < 1 && m_Columns[col].m_Width > 0)
|
|
|
|
width *= m_TotalAvailableColumnWidth;
|
2015-08-21 19:08:41 +02:00
|
|
|
|
|
|
|
CPos leftTopCorner = m_CachedActualSize.TopLeft() + CPos(xpos, 0);
|
2015-09-02 19:55:02 +02:00
|
|
|
|
|
|
|
// Draw sort arrows in colum header
|
2016-09-04 00:22:11 +02:00
|
|
|
if (sortable)
|
|
|
|
{
|
2019-08-19 12:32:29 +02:00
|
|
|
CStr spriteName;
|
2016-09-04 00:22:11 +02:00
|
|
|
if (selectedColumn == m_Columns[col].m_Id)
|
|
|
|
{
|
|
|
|
if (selectedColumnOrder == 0)
|
|
|
|
LOGERROR("selected_column_order must not be 0");
|
|
|
|
|
|
|
|
if (selectedColumnOrder != -1)
|
2019-08-19 12:32:29 +02:00
|
|
|
spriteName = "sprite_asc";
|
2016-09-04 00:22:11 +02:00
|
|
|
else
|
2019-08-19 12:32:29 +02:00
|
|
|
spriteName = "sprite_desc";
|
2016-09-04 00:22:11 +02:00
|
|
|
}
|
|
|
|
else
|
2019-08-19 12:32:29 +02:00
|
|
|
spriteName = "sprite_not_sorted";
|
2016-09-04 00:22:11 +02:00
|
|
|
|
2019-08-26 14:25:07 +02:00
|
|
|
CGUISpriteInstance& sprite = GetSetting<CGUISpriteInstance>(spriteName);
|
2019-08-21 12:12:33 +02:00
|
|
|
m_pGUI.DrawSprite(sprite, cell_id, bz + 0.1f, CRect(leftTopCorner + CPos(width - SORT_SPRITE_DIM, 0), leftTopCorner + CPos(width, SORT_SPRITE_DIM)));
|
2016-09-04 00:22:11 +02:00
|
|
|
}
|
2013-11-07 21:07:24 +01:00
|
|
|
|
2015-09-02 19:55:02 +02:00
|
|
|
// Draw column header text
|
2019-01-24 21:00:31 +01:00
|
|
|
DrawText(col, color, leftTopCorner + COLUMN_SHIFT, bz + 0.1f, rect_head);
|
2015-08-21 19:08:41 +02:00
|
|
|
xpos += width;
|
|
|
|
}
|
2013-11-07 21:07:24 +01:00
|
|
|
|
2015-09-02 19:55:02 +02:00
|
|
|
// Draw list items for each column
|
2019-08-26 14:25:07 +02:00
|
|
|
const CGUIList& pList = GetSetting<CGUIList>("list");
|
2016-08-31 21:29:48 +02:00
|
|
|
const size_t objectsCount = m_Columns.size();
|
2019-08-19 12:32:29 +02:00
|
|
|
for (size_t i = 0; i < pList.m_Items.size(); ++i)
|
2015-08-21 19:08:41 +02:00
|
|
|
{
|
|
|
|
if (m_ItemsYPositions[i+1] - scroll < 0 ||
|
|
|
|
m_ItemsYPositions[i] - scroll > rect.GetHeight())
|
|
|
|
continue;
|
2015-07-30 03:33:48 +02:00
|
|
|
|
2015-08-21 19:08:41 +02:00
|
|
|
const float rowHeight = m_ItemsYPositions[i+1] - m_ItemsYPositions[i];
|
2013-11-07 21:07:24 +01:00
|
|
|
|
2015-08-21 19:08:41 +02:00
|
|
|
// Clipping area (we'll have to substract the scrollbar)
|
|
|
|
CRect cliparea = GetListRect();
|
2013-11-07 21:07:24 +01:00
|
|
|
|
2015-08-21 19:08:41 +02:00
|
|
|
if (scrollbar)
|
|
|
|
{
|
|
|
|
if (cliparea.right > GetScrollBar(0).GetOuterRect().left &&
|
|
|
|
cliparea.right <= GetScrollBar(0).GetOuterRect().right)
|
|
|
|
cliparea.right = GetScrollBar(0).GetOuterRect().left;
|
2013-11-07 21:07:24 +01:00
|
|
|
|
2015-08-21 19:08:41 +02:00
|
|
|
if (cliparea.left >= GetScrollBar(0).GetOuterRect().left &&
|
|
|
|
cliparea.left < GetScrollBar(0).GetOuterRect().right)
|
|
|
|
cliparea.left = GetScrollBar(0).GetOuterRect().right;
|
|
|
|
}
|
2015-07-30 03:33:48 +02:00
|
|
|
|
2015-09-02 19:55:02 +02:00
|
|
|
// Draw all items for that column
|
2015-08-21 19:08:41 +02:00
|
|
|
xpos = 0;
|
2016-08-31 21:29:48 +02:00
|
|
|
for (size_t col = 0; col < objectsCount; ++col)
|
2015-08-21 19:08:41 +02:00
|
|
|
{
|
2019-08-26 14:25:07 +02:00
|
|
|
if (GetSetting<bool>("hidden_" + m_Columns[col].m_Id))
|
2017-03-28 02:25:17 +02:00
|
|
|
continue;
|
|
|
|
|
2015-08-21 19:08:41 +02:00
|
|
|
// Determine text position and width
|
|
|
|
const CPos textPos = rect.TopLeft() + CPos(xpos, -scroll + m_ItemsYPositions[i]);
|
2015-07-30 03:33:48 +02:00
|
|
|
|
2016-08-31 21:29:48 +02:00
|
|
|
float width = m_Columns[col].m_Width;
|
2015-08-21 19:08:41 +02:00
|
|
|
// Check if it's a decimal value, and if so, assume relative positioning.
|
2016-08-31 21:29:48 +02:00
|
|
|
if (m_Columns[col].m_Width < 1 && m_Columns[col].m_Width > 0)
|
|
|
|
width *= m_TotalAvailableColumnWidth;
|
2015-07-30 03:33:48 +02:00
|
|
|
|
2015-08-21 19:08:41 +02:00
|
|
|
// Clip text to the column (to prevent drawing text into the neighboring column)
|
|
|
|
CRect cliparea2 = cliparea;
|
|
|
|
cliparea2.right = std::min(cliparea2.right, textPos.x + width);
|
|
|
|
cliparea2.bottom = std::min(cliparea2.bottom, textPos.y + rowHeight);
|
|
|
|
|
2015-09-02 19:55:02 +02:00
|
|
|
// Draw list item
|
2016-08-31 21:29:48 +02:00
|
|
|
DrawText(objectsCount * (i +/*Heading*/1) + col, m_Columns[col].m_TextColor, textPos, bz + 0.1f, cliparea2);
|
2015-08-21 19:08:41 +02:00
|
|
|
xpos += width;
|
2013-11-07 21:07:24 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|