Changeset View
Standalone View
source/gui/COList.cpp
/* Copyright (C) 2017 Wildfire Games. | /* Copyright (C) 2019 Wildfire Games. | ||||
elexis: 9 | |||||
* This file is part of 0 A.D. | * This file is part of 0 A.D. | ||||
* | * | ||||
* 0 A.D. is free software: you can redistribute it and/or modify | * 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 | * it under the terms of the GNU General Public License as published by | ||||
* the Free Software Foundation, either version 2 of the License, or | * the Free Software Foundation, either version 2 of the License, or | ||||
* (at your option) any later version. | * (at your option) any later version. | ||||
* | * | ||||
* 0 A.D. is distributed in the hope that it will be useful, | * 0 A.D. is distributed in the hope that it will be useful, | ||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||||
* GNU General Public License for more details. | * GNU General Public License for more details. | ||||
* | * | ||||
* You should have received a copy of the GNU General Public License | * 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/>. | * along with 0 A.D. If not, see <http://www.gnu.org/licenses/>. | ||||
*/ | */ | ||||
#include "precompiled.h" | #include "precompiled.h" | ||||
#include "COList.h" | #include "COList.h" | ||||
#include "i18n/L10n.h" | #include "i18n/L10n.h" | ||||
#include "ps/CLogger.h" | #include "ps/CLogger.h" | ||||
#include "soundmanager/ISoundManager.h" | #include "soundmanager/ISoundManager.h" | ||||
const float SORT_SPRITE_DIM = 16.0f; | |||||
Not Done Inline ActionsIs auto-resizing the column header to the content dimensions really important? elexis: Is auto-resizing the column header to the content dimensions really important?
If so, it would… | |||||
Not Done Inline ActionsI didn't get what do you mean. Auto-resizing is important, because we can have long column names. We can't process images and texts equally yet because they have different infrastructures. The sprite size is fixed, because we don't have methods to get a real sprite size, because it could be drawn with different sizes. vladislavbelov: I didn't get what do you mean.
Auto-resizing is important, because we can have long column… | |||||
Not Done Inline Actions
Pixels?
m_Size The sprite (not the imagefile) has a size property which should be used. Maybe doesn't have to be in this commit and this commit does it cleaner than what was here before. elexis: > We can't process images and texts equally yet because they have different infrastructures. | |||||
Not Done Inline Actions
No, we layout texts and images separately. We can't insert images into a text directly. By together layout I mean layout like in HTML or inside our XML. We have the hardcoded layout in our GUI elements.
Nope, CGUISprite has it, but we have only CGUISpriteInstance. vladislavbelov: > Pixels?
No, we layout texts and images separately. We can't insert images into a text… | |||||
Not Done Inline Actions
Not necessary to do so either. The code can remain the same, just the hardcoding can be replaced with the user-specified size. Even relative sizes shouldn't be a problem because m_CachedActualSize is known.
and m_Sprites stores the CGUISprite that the CGUISpriteInstance refers to, which could be exposed through a getter for instance. elexis: > We can't insert images into a text directly
Not necessary to do so either. The code can… | |||||
Not Done Inline ActionsCGUISprite isn't the one sprite, but the set. So we need to duplicate logic here then. Or somehow unify it. vladislavbelov: `CGUISprite` isn't the one sprite, but the set. So we need to duplicate logic here then. Or… | |||||
Not Done Inline ActionsSo the COList code also breaks the definition of a sprite in the way that a sprite consists of N images, not only one? elexis: So the COList code also breaks the definition of a sprite in the way that a sprite consists of… | |||||
Not Done Inline Actions
No, COList uses fixed size, so no problem here. vladislavbelov: > So the COList code also breaks the definition of a sprite in the way that a sprite consists… | |||||
Not Done Inline ActionsTo the confusion and disappointment of the user who had configured a different size or position. elexis: To the confusion and disappointment of the user who had configured a different size or position. | |||||
Not Done Inline Actions
(Also one can, for example setup_resources.xml. But those have variable size too) elexis: > We can't insert images into a text directly
(Also one can, for example `setup_resources.xml`. | |||||
const CPos COLUMN_SHIFT = CPos(0, 4); | |||||
COList::COList() : CList() | COList::COList() : CList() | ||||
{ | { | ||||
AddSetting(GUIST_CGUISpriteInstance, "sprite_heading"); | AddSetting(GUIST_CGUISpriteInstance, "sprite_heading"); | ||||
AddSetting(GUIST_float, "heading_height"); | |||||
AddSetting(GUIST_bool, "sortable"); // The actual sorting is done in JS for more versatility | AddSetting(GUIST_bool, "sortable"); // The actual sorting is done in JS for more versatility | ||||
AddSetting(GUIST_CStr, "selected_column"); | AddSetting(GUIST_CStr, "selected_column"); | ||||
AddSetting(GUIST_int, "selected_column_order"); | AddSetting(GUIST_int, "selected_column_order"); | ||||
AddSetting(GUIST_CGUISpriteInstance, "sprite_asc"); // Show the order of sorting | AddSetting(GUIST_CGUISpriteInstance, "sprite_asc"); // Show the order of sorting | ||||
AddSetting(GUIST_CGUISpriteInstance, "sprite_desc"); | AddSetting(GUIST_CGUISpriteInstance, "sprite_desc"); | ||||
AddSetting(GUIST_CGUISpriteInstance, "sprite_not_sorted"); | AddSetting(GUIST_CGUISpriteInstance, "sprite_not_sorted"); | ||||
} | } | ||||
Show All 18 Lines | void COList::SetupText() | ||||
if (GUI<CStrW>::GetSetting(this, "font", font) != PSRETURN_OK || font.empty()) | if (GUI<CStrW>::GetSetting(this, "font", font) != PSRETURN_OK || font.empty()) | ||||
// Use the default if none is specified | // Use the default if none is specified | ||||
// TODO Gee: (2004-08-14) Don't define standard like this. Do it with the default style. | // TODO Gee: (2004-08-14) Don't define standard like this. Do it with the default style. | ||||
font = L"default"; | font = L"default"; | ||||
bool scrollbar; | bool scrollbar; | ||||
GUI<bool>::GetSetting(this, "scrollbar", scrollbar); | GUI<bool>::GetSetting(this, "scrollbar", scrollbar); | ||||
float width = GetListRect().GetWidth(); | m_TotalAvailableColumnWidth = GetListRect().GetWidth(); | ||||
// remove scrollbar if applicable | // remove scrollbar if applicable | ||||
if (scrollbar && GetScrollBar(0).GetStyle()) | if (scrollbar && GetScrollBar(0).GetStyle()) | ||||
width -= GetScrollBar(0).GetStyle()->m_Width; | m_TotalAvailableColumnWidth -= GetScrollBar(0).GetStyle()->m_Width; | ||||
m_TotalAvailableColumnWidth = width; | |||||
float buffer_zone = 0.f; | float buffer_zone = 0.f; | ||||
GUI<float>::GetSetting(this, "buffer_zone", buffer_zone); | GUI<float>::GetSetting(this, "buffer_zone", buffer_zone); | ||||
Done Inline Actionsconst auto& column then. vladislavbelov: `const auto& column` then. | |||||
for (COListColumn column : m_Columns) | m_HeadingHeight = SORT_SPRITE_DIM; // At least the size of the sorting sprite | ||||
for (const COListColumn& column : m_Columns) | |||||
{ | { | ||||
float width = column.m_Width; | |||||
if (column.m_Width > 0 && column.m_Width < 1) | |||||
width *= m_TotalAvailableColumnWidth; | |||||
Done Inline ActionsThere I guess. Stan: There I guess. | |||||
SGUIText* text = new SGUIText(); | SGUIText* text = new SGUIText(); | ||||
CGUIString gui_string; | CGUIString gui_string; | ||||
gui_string.SetValue(column.m_Heading); | gui_string.SetValue(column.m_Heading); | ||||
*text = GetGUI()->GenerateText(gui_string, font, width, buffer_zone, this); | *text = GetGUI()->GenerateText(gui_string, font, width, buffer_zone, this); | ||||
AddText(text); | AddText(text); | ||||
Done Inline ActionsAlso sprites should be accounted here. The sprites size is hardcoded currently. vladislavbelov: Also sprites should be accounted here. The sprites size is hardcoded currently. | |||||
Done Inline ActionsThe sprite is accounted for, as we start m_HeadingHeight at 16. The sprite is always going to be at most 16x16px, because it gets clipped to 16x16 in the DrawSprite function on line 432: GetGUI()->DrawSprite(*sprite, cell_id, bz + 0.1f, CRect(leftTopCorner + CPos(width - 16, 0), leftTopCorner + CPos(width, 16))); gentz: The sprite is accounted for, as we start `m_HeadingHeight` at 16.
The sprite is always going… | |||||
Done Inline ActionsYeah, I meant to move the size up to use a common constant instead of the duplication. vladislavbelov: Yeah, I meant to move the size up to use a common constant instead of the duplication. | |||||
m_HeadingHeight = std::max(m_HeadingHeight, text->m_Size.cy + COLUMN_SHIFT.y); | |||||
Not Done Inline ActionsWe forgot about the hardcoded shift for the column name CPos(0, 4). vladislavbelov: We forgot about the hardcoded shift for the column name `CPos(0, 4)`. | |||||
} | } | ||||
// Generate texts | // Generate texts | ||||
float buffered_y = 0.f; | float buffered_y = 0.f; | ||||
for (size_t i = 0; i < pList->m_Items.size(); ++i) | for (size_t i = 0; i < pList->m_Items.size(); ++i) | ||||
{ | { | ||||
m_ItemsYPositions[i] = buffered_y; | m_ItemsYPositions[i] = buffered_y; | ||||
float shift = 0.0f; | float shift = 0.0f; | ||||
Done Inline ActionsThe same value as below, so it'd be better to calculate before the if. vladislavbelov: The same value as below, so it'd be better to calculate before the `if`. | |||||
for (size_t c = 0; c < m_Columns.size(); ++c) | for (const COListColumn& column : m_Columns) | ||||
{ | { | ||||
float width = column.m_Width; | |||||
if (column.m_Width > 0 && column.m_Width < 1) | |||||
width *= m_TotalAvailableColumnWidth; | |||||
Done Inline ActionsHere also Stan: Here also | |||||
CGUIList* pList_c; | CGUIList* pList_c; | ||||
GUI<CGUIList>::GetSettingPointer(this, "list_" + m_Columns[c].m_Id, pList_c); | GUI<CGUIList>::GetSettingPointer(this, "list_" + column.m_Id, pList_c); | ||||
SGUIText* text = new SGUIText(); | SGUIText* text = new SGUIText(); | ||||
if (!pList_c->m_Items[i].GetOriginalString().empty()) | if (!pList_c->m_Items[i].GetOriginalString().empty()) | ||||
*text = GetGUI()->GenerateText(pList_c->m_Items[i], font, width, buffer_zone, this); | *text = GetGUI()->GenerateText(pList_c->m_Items[i], font, width, buffer_zone, this); | ||||
else | else | ||||
{ | { | ||||
// Minimum height of a space character of the current font size | // Minimum height of a space character of the current font size | ||||
CGUIString align_string; | CGUIString align_string; | ||||
align_string.SetValue(L" "); | align_string.SetValue(L" "); | ||||
Show All 17 Lines | if (scrollbar) | ||||
GetScrollBar(0).SetY(rect.top); | GetScrollBar(0).SetY(rect.top); | ||||
GetScrollBar(0).SetZ(GetBufferedZ()); | GetScrollBar(0).SetZ(GetBufferedZ()); | ||||
GetScrollBar(0).SetLength(rect.bottom - rect.top); | GetScrollBar(0).SetLength(rect.bottom - rect.top); | ||||
} | } | ||||
} | } | ||||
CRect COList::GetListRect() const | CRect COList::GetListRect() const | ||||
{ | { | ||||
float headingHeight; | return m_CachedActualSize + CRect(0, m_HeadingHeight, 0, 0); | ||||
GUI<float>::GetSetting(this, "heading_height", headingHeight); | |||||
return m_CachedActualSize + CRect(0, headingHeight, 0, 0); | |||||
} | } | ||||
void COList::HandleMessage(SGUIMessage& Message) | void COList::HandleMessage(SGUIMessage& Message) | ||||
{ | { | ||||
CList::HandleMessage(Message); | CList::HandleMessage(Message); | ||||
switch (Message.type) | switch (Message.type) | ||||
{ | { | ||||
// If somebody clicks on the column heading | // If somebody clicks on the column heading | ||||
case GUIM_MOUSE_PRESS_LEFT: | case GUIM_MOUSE_PRESS_LEFT: | ||||
{ | { | ||||
bool sortable; | bool sortable; | ||||
GUI<bool>::GetSetting(this, "sortable", sortable); | GUI<bool>::GetSetting(this, "sortable", sortable); | ||||
if (!sortable) | if (!sortable) | ||||
return; | return; | ||||
CPos mouse = GetMousePos(); | CPos mouse = GetMousePos(); | ||||
if (!m_CachedActualSize.PointInside(mouse)) | if (!m_CachedActualSize.PointInside(mouse)) | ||||
return; | return; | ||||
CStr selectedColumn; | CStr selectedColumn; | ||||
GUI<CStr>::GetSetting(this, "selected_column", selectedColumn); | GUI<CStr>::GetSetting(this, "selected_column", selectedColumn); | ||||
int selectedColumnOrder; | int selectedColumnOrder; | ||||
GUI<int>::GetSetting(this, "selected_column_order", selectedColumnOrder); | GUI<int>::GetSetting(this, "selected_column_order", selectedColumnOrder); | ||||
float headingHeight; | |||||
GUI<float>::GetSetting(this, "heading_height", headingHeight); | |||||
float xpos = 0; | float xpos = 0; | ||||
for (COListColumn column : m_Columns) | for (const COListColumn& column : m_Columns) | ||||
{ | { | ||||
bool hidden = false; | bool hidden = false; | ||||
GUI<bool>::GetSetting(this, "hidden_" + column.m_Id, hidden); | GUI<bool>::GetSetting(this, "hidden_" + column.m_Id, hidden); | ||||
if (hidden) | if (hidden) | ||||
continue; | continue; | ||||
float width = column.m_Width; | float width = column.m_Width; | ||||
// Check if it's a decimal value, and if so, assume relative positioning. | // Check if it's a decimal value, and if so, assume relative positioning. | ||||
if (column.m_Width < 1 && column.m_Width > 0) | if (column.m_Width < 1 && column.m_Width > 0) | ||||
width *= m_TotalAvailableColumnWidth; | width *= m_TotalAvailableColumnWidth; | ||||
CPos leftTopCorner = m_CachedActualSize.TopLeft() + CPos(xpos, 0); | CPos leftTopCorner = m_CachedActualSize.TopLeft() + CPos(xpos, 0); | ||||
if (mouse.x >= leftTopCorner.x && | if (mouse.x >= leftTopCorner.x && | ||||
mouse.x < leftTopCorner.x + width && | mouse.x < leftTopCorner.x + width && | ||||
mouse.y < leftTopCorner.y + headingHeight) | mouse.y < leftTopCorner.y + m_HeadingHeight) | ||||
{ | { | ||||
if (column.m_Id != selectedColumn) | if (column.m_Id != selectedColumn) | ||||
{ | { | ||||
selectedColumnOrder = 1; | selectedColumnOrder = 1; | ||||
selectedColumn = column.m_Id; | selectedColumn = column.m_Id; | ||||
} | } | ||||
else | else | ||||
selectedColumnOrder = -selectedColumnOrder; | selectedColumnOrder = -selectedColumnOrder; | ||||
▲ Show 20 Lines • Show All 183 Lines • ▼ Show 20 Lines | if (rect_sel.top <= rect.bottom && | ||||
rect_sel.left = GetScrollBar(0).GetOuterRect().right; | rect_sel.left = GetScrollBar(0).GetOuterRect().right; | ||||
} | } | ||||
// Draw item selection | // Draw item selection | ||||
GetGUI()->DrawSprite(*sprite_selectarea, cell_id, bz+0.05f, rect_sel); | GetGUI()->DrawSprite(*sprite_selectarea, cell_id, bz+0.05f, rect_sel); | ||||
} | } | ||||
} | } | ||||
float headingHeight; | |||||
GUI<float>::GetSetting(this, "heading_height", headingHeight); | |||||
// Draw line above column header | // Draw line above column header | ||||
CGUISpriteInstance* sprite_heading = NULL; | CGUISpriteInstance* sprite_heading = NULL; | ||||
GUI<CGUISpriteInstance>::GetSettingPointer(this, "sprite_heading", sprite_heading); | GUI<CGUISpriteInstance>::GetSettingPointer(this, "sprite_heading", sprite_heading); | ||||
CRect rect_head(m_CachedActualSize.left, m_CachedActualSize.top, m_CachedActualSize.right, | CRect rect_head(m_CachedActualSize.left, m_CachedActualSize.top, m_CachedActualSize.right, | ||||
m_CachedActualSize.top + headingHeight); | m_CachedActualSize.top + m_HeadingHeight); | ||||
GetGUI()->DrawSprite(*sprite_heading, cell_id, bz, rect_head); | GetGUI()->DrawSprite(*sprite_heading, cell_id, bz, rect_head); | ||||
// Draw column headers | // Draw column headers | ||||
bool sortable; | bool sortable; | ||||
GUI<bool>::GetSetting(this, "sortable", sortable); | GUI<bool>::GetSetting(this, "sortable", sortable); | ||||
CStr selectedColumn; | CStr selectedColumn; | ||||
GUI<CStr>::GetSetting(this, "selected_column", selectedColumn); | GUI<CStr>::GetSetting(this, "selected_column", selectedColumn); | ||||
Show All 31 Lines | if (sortable) | ||||
if (selectedColumnOrder != -1) | if (selectedColumnOrder != -1) | ||||
GUI<CGUISpriteInstance>::GetSettingPointer(this, "sprite_asc", sprite); | GUI<CGUISpriteInstance>::GetSettingPointer(this, "sprite_asc", sprite); | ||||
else | else | ||||
GUI<CGUISpriteInstance>::GetSettingPointer(this, "sprite_desc", sprite); | GUI<CGUISpriteInstance>::GetSettingPointer(this, "sprite_desc", sprite); | ||||
} | } | ||||
else | else | ||||
GUI<CGUISpriteInstance>::GetSettingPointer(this, "sprite_not_sorted", sprite); | GUI<CGUISpriteInstance>::GetSettingPointer(this, "sprite_not_sorted", sprite); | ||||
GetGUI()->DrawSprite(*sprite, cell_id, bz + 0.1f, CRect(leftTopCorner + CPos(width - 16, 0), leftTopCorner + CPos(width, 16))); | GetGUI()->DrawSprite(*sprite, cell_id, bz + 0.1f, CRect(leftTopCorner + CPos(width - SORT_SPRITE_DIM, 0), leftTopCorner + CPos(width, SORT_SPRITE_DIM))); | ||||
Done Inline ActionsSo another 16 should be replaced here too. vladislavbelov: So another `16` should be replaced here too. | |||||
Done Inline ActionsThat other 16 is for the width. gentz: That other 16 is for the width. | |||||
Done Inline ActionsYes, but I said above, the sprite is square, so 16 is both width and height currently. So it should be defined as one constant. vladislavbelov: Yes, but I said above, the sprite is square, so `16` is both width and height currently. So it… | |||||
} | } | ||||
// Draw column header text | // Draw column header text | ||||
DrawText(col, color, leftTopCorner + CPos(0, 4), bz + 0.1f, rect_head); | DrawText(col, color, leftTopCorner + COLUMN_SHIFT, bz + 0.1f, rect_head); | ||||
xpos += width; | xpos += width; | ||||
} | } | ||||
// Draw list items for each column | // Draw list items for each column | ||||
const size_t objectsCount = m_Columns.size(); | const size_t objectsCount = m_Columns.size(); | ||||
for (size_t i = 0; i < pList->m_Items.size(); ++i) | for (size_t i = 0; i < pList->m_Items.size(); ++i) | ||||
{ | { | ||||
if (m_ItemsYPositions[i+1] - scroll < 0 || | if (m_ItemsYPositions[i+1] - scroll < 0 || | ||||
▲ Show 20 Lines • Show All 47 Lines • Show Last 20 Lines |
9