870 lines
21 KiB
C++
870 lines
21 KiB
C++
/*
|
|
* This file is part of the Colobot: Gold Edition source code
|
|
* Copyright (C) 2001-2021, Daniel Roux, EPSITEC SA & TerranovaTeam
|
|
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
|
*
|
|
* This program 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 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program 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 this program. If not, see http://gnu.org/licenses
|
|
*/
|
|
|
|
|
|
#include "ui/controls/list.h"
|
|
|
|
#include "common/make_unique.h"
|
|
|
|
#include "graphics/core/device.h"
|
|
#include "graphics/core/renderers.h"
|
|
#include "graphics/engine/engine.h"
|
|
|
|
#include "math/func.h"
|
|
|
|
#include <cassert>
|
|
#include <cstring>
|
|
|
|
namespace Ui
|
|
{
|
|
|
|
const float MARGING = 4.0f;
|
|
|
|
|
|
// Object's constructor.
|
|
|
|
CList::CList()
|
|
: CControl(),
|
|
m_tabs(),
|
|
m_justifs()
|
|
{
|
|
for (int i = 0; i < 10; i++)
|
|
{
|
|
m_tabs[i] = 0.0f;
|
|
m_justifs[i] = Gfx::TEXT_ALIGN_LEFT;
|
|
}
|
|
|
|
m_expand = 0.0f;
|
|
m_totalLine = 0;
|
|
m_displayLine = 0;
|
|
m_selectLine = -1;
|
|
m_firstLine = 0;
|
|
m_bBlink = false;
|
|
m_bSelectCap = true;
|
|
m_blinkTime = 0.0f;
|
|
}
|
|
|
|
// Object's destructor.
|
|
|
|
CList::~CList()
|
|
{
|
|
}
|
|
|
|
|
|
// Creates a new list.
|
|
// if expand is less then zero, then the list would try to use expand's absolute value,
|
|
// and try to scale items to some size, so that dim of the list would not change after
|
|
// adjusting
|
|
|
|
bool CList::Create(const glm::vec2& pos, const glm::vec2& dim, int icon, EventType eventMsg, float expand)
|
|
{
|
|
m_expand = expand;
|
|
|
|
if (eventMsg == EVENT_NULL)
|
|
eventMsg = GetUniqueEventType();
|
|
|
|
CControl::Create(pos, dim, icon, eventMsg);
|
|
|
|
m_scroll = MakeUnique<CScroll>();
|
|
m_scroll->Create(pos, dim, 0, EVENT_NULL);
|
|
|
|
return MoveAdjust();
|
|
}
|
|
|
|
// Should never be called
|
|
bool CList::Create(const glm::vec2& pos, const glm::vec2& dim, int icon, EventType eventType)
|
|
{
|
|
assert(false);
|
|
return false;
|
|
}
|
|
|
|
|
|
// Adjusted after a change of dimensions.
|
|
|
|
bool CList::MoveAdjust()
|
|
{
|
|
glm::vec2 ipos, idim, ppos, ddim;
|
|
float marging, h;
|
|
|
|
for (auto& button : m_buttons)
|
|
button.reset();
|
|
|
|
if (m_icon == 0)
|
|
marging = MARGING;
|
|
else
|
|
marging = 0.0f;
|
|
|
|
ipos.x = m_pos.x + marging / 640.f;
|
|
ipos.y = m_pos.y + marging / 480.f;
|
|
idim.x = m_dim.x - marging * 2.0f / 640.f;
|
|
idim.y = m_dim.y - marging * 2.0f / 480.f;
|
|
|
|
//If m_expand is less then zero, then try to apply it's absolute value
|
|
h = m_engine->GetText()->GetHeight(m_fontType, m_fontSize) * ((m_expand < 0) ? -m_expand : m_expand);
|
|
m_displayLine = static_cast<int>(idim.y / h);
|
|
|
|
if (m_displayLine == 0)
|
|
return false;
|
|
if (m_displayLine > LISTMAXDISPLAY)
|
|
m_displayLine = LISTMAXDISPLAY;
|
|
|
|
// Stretch lines to fill whole area of a list, if needed
|
|
if (m_expand < 0 && (idim.y - (h * m_displayLine) < h))
|
|
{
|
|
h = idim.y / m_displayLine;
|
|
}
|
|
|
|
idim.y = h * m_displayLine; //Here cuts list size if height of shown elements is less then designed height
|
|
m_dim.y = idim.y + marging * 2.0f / 480.f;
|
|
|
|
ppos.x = ipos.x;
|
|
ppos.y = ipos.y + idim.y - h;
|
|
ddim.x = idim.x - SCROLL_WIDTH;
|
|
ddim.y = h;
|
|
for (int i = 0; i < m_displayLine; i++)
|
|
{
|
|
auto button = MakeUnique<CButton>();
|
|
button->Create(ppos, ddim, -1, EVENT_NULL);
|
|
button->SetTextAlign(Gfx::TEXT_ALIGN_LEFT);
|
|
button->SetState(STATE_SIMPLY);
|
|
button->SetFontType(m_fontType);
|
|
button->SetFontSize(m_fontSize);
|
|
ppos.y -= h;
|
|
|
|
m_buttons[i] = std::move(button);
|
|
}
|
|
|
|
if (m_scroll != nullptr)
|
|
{
|
|
ppos.x = ipos.x + idim.x - SCROLL_WIDTH;
|
|
ppos.y = ipos.y;
|
|
ddim.x = SCROLL_WIDTH;
|
|
ddim.y = idim.y;
|
|
m_scroll->SetPos(ppos);
|
|
m_scroll->SetDim(ddim);
|
|
}
|
|
|
|
UpdateScroll();
|
|
UpdateButton();
|
|
return true;
|
|
}
|
|
|
|
|
|
// Returns the message of a button.
|
|
|
|
EventType CList::GetEventMsgButton(int i)
|
|
{
|
|
if (i < 0 || i >= m_displayLine)
|
|
return EVENT_NULL;
|
|
if (m_buttons[i] == nullptr)
|
|
return EVENT_NULL;
|
|
return m_buttons[i]->GetEventType();
|
|
}
|
|
|
|
// Returns the message from the elevator.
|
|
|
|
EventType CList::GetEventMsgScroll()
|
|
{
|
|
if (m_scroll == nullptr)
|
|
return EVENT_NULL;
|
|
return m_scroll->GetEventType();
|
|
}
|
|
|
|
|
|
void CList::SetPos(const glm::vec2& pos)
|
|
{
|
|
CControl::SetPos(pos);
|
|
}
|
|
|
|
|
|
void CList::SetDim(const glm::vec2& dim)
|
|
{
|
|
m_dim = dim;
|
|
MoveAdjust();
|
|
CControl::SetDim(dim);
|
|
}
|
|
|
|
|
|
bool CList::SetState(int state, bool bState)
|
|
{
|
|
if (state & STATE_ENABLE)
|
|
{
|
|
for (int i = 0; i < m_displayLine; i++)
|
|
{
|
|
if (m_buttons[i] != nullptr)
|
|
m_buttons[i]->SetState(state, bState);
|
|
}
|
|
if (m_scroll != nullptr)
|
|
m_scroll->SetState(state, bState);
|
|
}
|
|
|
|
return CControl::SetState(state, bState);
|
|
}
|
|
|
|
|
|
bool CList::SetState(int state)
|
|
{
|
|
if (state & STATE_ENABLE)
|
|
{
|
|
for (int i = 0; i < m_displayLine; i++)
|
|
{
|
|
if (m_buttons[i] != nullptr)
|
|
m_buttons[i]->SetState(state);
|
|
}
|
|
if (m_scroll != nullptr)
|
|
m_scroll->SetState(state);
|
|
}
|
|
|
|
return CControl::SetState(state);
|
|
}
|
|
|
|
|
|
bool CList::ClearState(int state)
|
|
{
|
|
if (state & STATE_ENABLE)
|
|
{
|
|
for (int i = 0; i < m_displayLine; i++)
|
|
{
|
|
if (m_buttons[i] != nullptr)
|
|
m_buttons[i]->ClearState(state);
|
|
}
|
|
if (m_scroll != nullptr)
|
|
m_scroll->ClearState(state);
|
|
}
|
|
|
|
return CControl::ClearState(state);
|
|
}
|
|
|
|
|
|
// Management of an event.
|
|
|
|
bool CList::EventProcess(const Event &event)
|
|
{
|
|
if (m_bBlink && event.type == EVENT_FRAME)
|
|
{
|
|
int i = m_selectLine-m_firstLine;
|
|
|
|
if (i >= 0 && i < 4 && m_buttons[i] != nullptr)
|
|
{
|
|
m_blinkTime += event.rTime;
|
|
if (Math::Mod(m_blinkTime, 0.7f) < 0.3f)
|
|
{
|
|
m_buttons[i]->ClearState(STATE_ENABLE);
|
|
m_buttons[i]->ClearState(STATE_CHECK);
|
|
}
|
|
else
|
|
{
|
|
m_buttons[i]->SetState(STATE_ENABLE);
|
|
m_buttons[i]->SetState(STATE_CHECK);
|
|
}
|
|
}
|
|
}
|
|
|
|
if ((m_state & STATE_VISIBLE) == 0)
|
|
return true;
|
|
if ((m_state & STATE_ENABLE) == 0)
|
|
return true;
|
|
|
|
if (event.type == EVENT_MOUSE_WHEEL && Detect(event.mousePos))
|
|
{
|
|
auto data = event.GetData<MouseWheelEventData>();
|
|
m_firstLine -= data->y;
|
|
if (m_firstLine > m_totalLine - m_displayLine)
|
|
m_firstLine = m_totalLine - m_displayLine;
|
|
if (m_firstLine < 0)
|
|
m_firstLine = 0;
|
|
|
|
UpdateScroll();
|
|
UpdateButton();
|
|
return false;
|
|
}
|
|
|
|
CControl::EventProcess(event);
|
|
|
|
if (event.type == EVENT_MOUSE_MOVE || event.type == EVENT_MOUSE_BUTTON_DOWN || event.type == EVENT_MOUSE_BUTTON_UP)
|
|
{
|
|
if (Detect(event.mousePos))
|
|
{
|
|
m_engine->SetMouseType(Gfx::ENG_MOUSE_NORM);
|
|
for (int i = 0; i < m_displayLine; i++)
|
|
{
|
|
if (i + m_firstLine >= m_totalLine)
|
|
break;
|
|
if (m_buttons[i] != nullptr)
|
|
m_buttons[i]->EventProcess(event);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (m_bSelectCap)
|
|
{
|
|
for (int i = 0; i < m_displayLine; i++)
|
|
{
|
|
if (i + m_firstLine >= m_totalLine)
|
|
break;
|
|
|
|
if (m_buttons[i] != nullptr)
|
|
{
|
|
if (!m_buttons[i]->EventProcess(event))
|
|
return false;
|
|
|
|
if (event.type == m_buttons[i]->GetEventType())
|
|
{
|
|
SetSelect(m_firstLine + i);
|
|
|
|
m_event->AddEvent(Event(m_eventType)); // selected line changes
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (m_scroll != nullptr)
|
|
{
|
|
if (!m_scroll->EventProcess(event))
|
|
return false;
|
|
|
|
if (event.type == m_scroll->GetEventType())
|
|
{
|
|
MoveScroll();
|
|
UpdateButton();
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
// Draws the list.
|
|
|
|
void CList::Draw()
|
|
{
|
|
glm::vec2 uv1, uv2, corner, pos, dim, ppos, ddim;
|
|
float dp;
|
|
int i;
|
|
char text[100];
|
|
const char *pb, *pe;
|
|
|
|
if ((m_state & STATE_VISIBLE) == 0)
|
|
return;
|
|
|
|
if (m_state & STATE_SHADOW)
|
|
DrawShadow(m_pos, m_dim);
|
|
|
|
dp = 0.5f / 256.0f;
|
|
|
|
auto renderer = m_engine->GetDevice()->GetUIRenderer();
|
|
|
|
if (m_icon != -1)
|
|
{
|
|
dim = m_dim;
|
|
|
|
if (m_icon == 0)
|
|
{
|
|
auto texture = m_engine->LoadTexture("textures/interface/button2.png");
|
|
renderer->SetTexture(texture);
|
|
renderer->SetTransparency(Gfx::TransparencyMode::NONE);
|
|
|
|
uv1.x = 128.0f / 256.0f;
|
|
uv1.y = 64.0f / 256.0f; // u-v texture
|
|
uv2.x = 160.0f / 256.0f;
|
|
uv2.y = 96.0f / 256.0f;
|
|
}
|
|
else
|
|
{
|
|
auto texture = m_engine->LoadTexture("textures/interface/button2.png");
|
|
renderer->SetTexture(texture);
|
|
renderer->SetTransparency(Gfx::TransparencyMode::NONE);
|
|
|
|
uv1.x = 132.0f / 256.0f;
|
|
uv1.y = 68.0f / 256.0f; // u-v texture
|
|
uv2.x = 156.0f / 256.0f;
|
|
uv2.y = 92.0f / 256.0f;
|
|
|
|
if (m_buttons[0] != nullptr)
|
|
{
|
|
dim = m_buttons[0]->GetDim();
|
|
dim.y *= m_displayLine; // background sounds spot behind
|
|
}
|
|
}
|
|
|
|
uv1.x += dp;
|
|
uv1.y += dp;
|
|
uv2.x -= dp;
|
|
uv2.y -= dp;
|
|
|
|
corner.x = 10.0f / 640.0f;
|
|
corner.y = 10.0f / 480.0f;
|
|
DrawIcon(m_pos, dim, uv1, uv2, corner, 8.0f / 256.0f);
|
|
}
|
|
|
|
if ( m_totalLine < m_displayLine ) // no buttons to the bottom?
|
|
{
|
|
i = m_totalLine;
|
|
if (m_buttons[i] != nullptr)
|
|
{
|
|
pos = m_buttons[i]->GetPos();
|
|
dim = m_buttons[i]->GetDim();
|
|
pos.y += dim.y * 1.1f;
|
|
dim.y *= 0.4f;
|
|
pos.y -= dim.y;
|
|
|
|
auto texture = m_engine->LoadTexture("textures/interface/button2.png");
|
|
renderer->SetTexture(texture);
|
|
renderer->SetTransparency(Gfx::TransparencyMode::WHITE);
|
|
uv1.x = 120.0f / 256.0f;
|
|
uv1.y = 64.0f / 256.0f;
|
|
uv2.x = 128.0f / 256.0f;
|
|
uv2.y = 48.0f / 256.0f;
|
|
uv1.x += dp;
|
|
uv1.y -= dp;
|
|
uv2.x -= dp;
|
|
uv2.y += dp;
|
|
DrawIcon(pos, dim, uv1, uv2); // ch'tite shadow cute (?)
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < m_displayLine; i++)
|
|
{
|
|
if ( i + m_firstLine >= m_totalLine )
|
|
break;
|
|
|
|
if ( m_buttons[i] != nullptr )
|
|
{
|
|
if ( !m_bBlink && i + m_firstLine < m_totalLine )
|
|
m_buttons[i]->SetState(STATE_ENABLE, m_items[i+m_firstLine].enable && (m_state & STATE_ENABLE) );
|
|
|
|
m_buttons[i]->Draw(); // draws a box without text
|
|
|
|
// draws text in the box
|
|
pos = m_buttons[i]->GetPos();
|
|
dim = m_buttons[i]->GetDim();
|
|
if ( m_tabs[0] == 0.0f )
|
|
{
|
|
ppos.x = pos.x + dim.y * 0.5f;
|
|
ppos.y = pos.y + dim.y * 0.5f;
|
|
ppos.y -= m_engine->GetText()->GetHeight(m_fontType, m_fontSize) / 2.0f;
|
|
ddim.x = dim.x-dim.y;
|
|
DrawCase(m_items[i + m_firstLine].text.c_str(), ppos, ddim.x, Gfx::TEXT_ALIGN_LEFT);
|
|
}
|
|
else
|
|
{
|
|
ppos.x = pos.x + dim.y * 0.5f;
|
|
ppos.y = pos.y + dim.y * 0.5f;
|
|
ppos.y -= m_engine->GetText()->GetHeight(m_fontType, m_fontSize) / 2.0f;
|
|
pb = m_items[i + m_firstLine].text.c_str();
|
|
for (int j = 0; j < 10; j++)
|
|
{
|
|
pe = strchr(pb, '\t');
|
|
if ( pe == nullptr )
|
|
strcpy(text, pb);
|
|
else
|
|
{
|
|
strncpy(text, pb, pe - pb);
|
|
text[pe - pb] = 0;
|
|
}
|
|
DrawCase(text, ppos, m_tabs[j], m_justifs[j]);
|
|
|
|
if ( pe == nullptr )
|
|
break;
|
|
ppos.x += m_tabs[j];
|
|
pb = pe + 1;
|
|
}
|
|
}
|
|
|
|
if ( (m_state & STATE_EXTEND) && i < m_totalLine)
|
|
{
|
|
pos = m_buttons[i]->GetPos();
|
|
dim = m_buttons[i]->GetDim();
|
|
pos.x += dim.x - dim.y * 0.75f;
|
|
dim.x = dim.y * 0.75f;
|
|
pos.x += 2.0f / 640.0f;
|
|
pos.y += 2.0f / 480.0f;
|
|
dim.x -= 4.0f / 640.0f;
|
|
dim.y -= 4.0f / 480.0f;
|
|
|
|
if (m_items[i + m_firstLine].check)
|
|
{
|
|
auto texture = m_engine->LoadTexture("textures/interface/button1.png");
|
|
renderer->SetTexture(texture);
|
|
renderer->SetTransparency(Gfx::TransparencyMode::NONE);
|
|
uv1.x = 64.0f / 256.0f;
|
|
uv1.y = 0.0f / 256.0f;
|
|
uv2.x = 96.0f / 256.0f;
|
|
uv2.y = 32.0f / 256.0f;
|
|
uv1.x += dp;
|
|
uv1.y += dp;
|
|
uv2.x -= dp;
|
|
uv2.y -= dp;
|
|
DrawIcon(pos, dim, uv1, uv2); // square shape
|
|
|
|
renderer->SetTransparency(Gfx::TransparencyMode::WHITE);
|
|
uv1.x = 0.0f / 256.0f; // v
|
|
uv1.y = 64.0f / 256.0f;
|
|
uv2.x = 32.0f / 256.0f;
|
|
uv2.y = 96.0f / 256.0f;
|
|
uv1.x += dp;
|
|
uv1.y += dp;
|
|
uv2.x -= dp;
|
|
uv2.y -= dp;
|
|
DrawIcon(pos, dim, uv1, uv2); // draws v
|
|
}
|
|
else
|
|
{
|
|
auto texture = m_engine->LoadTexture("textures/interface/button1.png");
|
|
renderer->SetTexture(texture);
|
|
renderer->SetTransparency(Gfx::TransparencyMode::WHITE);
|
|
if ( i + m_firstLine == m_selectLine )
|
|
{
|
|
uv1.x =224.0f / 256.0f; // <
|
|
uv1.y =192.0f / 256.0f;
|
|
uv2.x =256.0f / 256.0f;
|
|
uv2.y =224.0f / 256.0f;
|
|
}
|
|
else
|
|
{
|
|
uv1.x = 96.0f / 256.0f; // x
|
|
uv1.y = 32.0f / 256.0f;
|
|
uv2.x =128.0f / 256.0f;
|
|
uv2.y = 64.0f / 256.0f;
|
|
}
|
|
uv1.x += dp;
|
|
uv1.y += dp;
|
|
uv2.x -= dp;
|
|
uv2.y -= dp;
|
|
DrawIcon(pos, dim, uv1, uv2); // draws x
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (m_scroll != nullptr)
|
|
m_scroll->Draw(); // draws the lift
|
|
}
|
|
|
|
// Displays text in a box.
|
|
|
|
void CList::DrawCase(const char* text, const glm::vec2& position, float width, Gfx::TextAlign justif)
|
|
{
|
|
glm::vec2 pos = position;
|
|
|
|
if (justif == Gfx::TEXT_ALIGN_CENTER)
|
|
pos.x += width / 2.0f;
|
|
else if (justif == Gfx::TEXT_ALIGN_RIGHT)
|
|
pos.x += width;
|
|
m_engine->GetText()->DrawText(std::string(text), m_fontType, m_fontSize, pos, width, justif, 0);
|
|
}
|
|
|
|
|
|
// Empty the list completely.
|
|
|
|
void CList::Flush()
|
|
{
|
|
m_totalLine = 0;
|
|
m_selectLine = -1;
|
|
m_firstLine = 0;
|
|
UpdateButton();
|
|
UpdateScroll();
|
|
}
|
|
|
|
|
|
// Specifies the total number of lines.
|
|
|
|
void CList::SetTotal(int i)
|
|
{
|
|
m_totalLine = i;
|
|
}
|
|
|
|
// Returns the total number of lines.
|
|
|
|
int CList::GetTotal()
|
|
{
|
|
return m_totalLine;
|
|
}
|
|
|
|
|
|
// Selects a line.
|
|
|
|
void CList::SetSelect(int i)
|
|
{
|
|
if ( m_bSelectCap )
|
|
m_selectLine = i;
|
|
else
|
|
{
|
|
m_firstLine = i;
|
|
UpdateScroll();
|
|
}
|
|
|
|
UpdateButton();
|
|
}
|
|
|
|
// Returns the selected line.
|
|
|
|
int CList::GetSelect()
|
|
{
|
|
if ( m_bSelectCap )
|
|
return m_selectLine;
|
|
else
|
|
return m_firstLine;
|
|
}
|
|
|
|
|
|
// Management of capability has a select box.
|
|
|
|
void CList::SetSelectCap(bool bEnable)
|
|
{
|
|
m_bSelectCap = bEnable;
|
|
}
|
|
|
|
bool CList::GetSelectCap()
|
|
{
|
|
return m_bSelectCap;
|
|
}
|
|
|
|
|
|
// Blink a line.
|
|
|
|
void CList::SetBlink(bool bEnable)
|
|
{
|
|
m_bBlink = bEnable;
|
|
m_blinkTime = 0.0f;
|
|
|
|
int i = m_selectLine - m_firstLine;
|
|
|
|
if (i >= 0 && i < 4 && m_buttons[i] != nullptr)
|
|
{
|
|
if ( !bEnable )
|
|
{
|
|
m_buttons[i]->SetState(STATE_CHECK);
|
|
m_buttons[i]->ClearState(STATE_ENABLE);
|
|
}
|
|
}
|
|
}
|
|
|
|
bool CList::GetBlink()
|
|
{
|
|
return m_bBlink;
|
|
}
|
|
|
|
|
|
// Specifies the text of a line.
|
|
|
|
void CList::SetItemName(int i, const std::string& name)
|
|
{
|
|
if ( i < 0 )
|
|
return;
|
|
|
|
if ( i >= m_totalLine )
|
|
m_totalLine = i+1; // expands the list
|
|
|
|
m_items.resize(m_totalLine);
|
|
if ( name.empty() )
|
|
m_items[i].text = " ";
|
|
else
|
|
m_items[i].text = name;
|
|
|
|
UpdateButton();
|
|
UpdateScroll();
|
|
}
|
|
|
|
// Returns the text of a line.
|
|
|
|
const std::string& CList::GetItemName(int i)
|
|
{
|
|
if ( i < 0 || i >= m_totalLine )
|
|
assert(false);
|
|
|
|
return m_items[i].text;
|
|
}
|
|
|
|
|
|
// Specifies the bit "check" for a box.
|
|
|
|
void CList::SetCheck(int i, bool bMode)
|
|
{
|
|
if ( i < 0 || i >= m_totalLine )
|
|
return;
|
|
|
|
m_items[i].check = bMode;
|
|
}
|
|
|
|
// Returns the bit "check" for a box.
|
|
|
|
bool CList::GetCheck(int i)
|
|
{
|
|
if ( i < 0 || i >= m_totalLine )
|
|
return false;
|
|
|
|
return m_items[i].check;
|
|
}
|
|
|
|
|
|
// Specifies the bit "enable" for a box.
|
|
|
|
void CList::SetEnable(int i, bool enable)
|
|
{
|
|
if ( i < 0 || i >= m_totalLine )
|
|
return;
|
|
|
|
m_items[i].enable = enable;
|
|
}
|
|
|
|
// Returns the bit "enable" for a box.
|
|
|
|
bool CList::GetEnable(int i)
|
|
{
|
|
if ( i < 0 || i >= m_totalLine )
|
|
return false;
|
|
|
|
return m_items[i].enable;
|
|
}
|
|
|
|
|
|
// Management of the position of the tabs.
|
|
|
|
void CList::SetTabs(int i, float pos, Gfx::TextAlign justif)
|
|
{
|
|
if ( i < 0 || i >= 10 )
|
|
return;
|
|
m_tabs[i] = pos;
|
|
m_justifs[i] = justif;
|
|
}
|
|
|
|
float CList::GetTabs(int i)
|
|
{
|
|
if ( i < 0 || i >= 10 )
|
|
return 0.0f;
|
|
return m_tabs[i];
|
|
}
|
|
|
|
|
|
// Moves the lift to see the list of the selected line.
|
|
|
|
void CList::ShowSelect(bool bFixed)
|
|
{
|
|
int sel;
|
|
|
|
if ( bFixed && m_selectLine >= m_firstLine && m_selectLine < m_firstLine+m_displayLine )
|
|
return; // all good
|
|
|
|
sel = m_selectLine;
|
|
|
|
// Down from 1/2 * h.
|
|
sel += m_displayLine / 2;
|
|
if ( sel > m_totalLine - 1 )
|
|
sel = m_totalLine - 1;
|
|
|
|
// Back to h-1.
|
|
sel -= m_displayLine - 1;
|
|
if ( sel < 0 )
|
|
sel = 0;
|
|
|
|
m_firstLine = sel;
|
|
|
|
UpdateButton();
|
|
UpdateScroll();
|
|
}
|
|
|
|
|
|
// Updates all button names.
|
|
|
|
void CList::UpdateButton()
|
|
{
|
|
int state, i, j;
|
|
|
|
state = CControl::GetState();
|
|
|
|
j = m_firstLine;
|
|
for (i = 0; i < m_displayLine; i++)
|
|
{
|
|
if (m_buttons[i] == nullptr)
|
|
continue;
|
|
|
|
m_buttons[i]->SetState(STATE_CHECK, (j == m_selectLine));
|
|
|
|
if ( j < m_totalLine )
|
|
{
|
|
//? m_buttons[i]->SetName(m_text[j]);
|
|
m_buttons[i]->SetName(" "); // blank button
|
|
m_buttons[i]->SetState(STATE_ENABLE, (state & STATE_ENABLE));
|
|
}
|
|
else
|
|
{
|
|
m_buttons[i]->SetName(" "); // blank button
|
|
m_buttons[i]->ClearState(STATE_ENABLE);
|
|
}
|
|
j ++;
|
|
}
|
|
}
|
|
|
|
// Updates the lift.
|
|
|
|
void CList::UpdateScroll()
|
|
{
|
|
float ratio, value, step;
|
|
|
|
if (m_scroll == nullptr)
|
|
return;
|
|
|
|
if (m_totalLine <= m_displayLine)
|
|
{
|
|
ratio = 1.0f;
|
|
value = 0.0f;
|
|
step = 0.0f;
|
|
}
|
|
else
|
|
{
|
|
ratio = static_cast<float>(m_displayLine) / m_totalLine;
|
|
if ( ratio > 1.0f ) ratio = 1.0f;
|
|
|
|
value = static_cast<float>(m_firstLine) / (m_totalLine - m_displayLine);
|
|
if ( value < 0.0f )
|
|
value = 0.0f;
|
|
if ( value > 1.0f )
|
|
value = 1.0f;
|
|
|
|
step = static_cast<float>(1.0f)/ (m_totalLine - m_displayLine);
|
|
if ( step < 0.0f )
|
|
step = 0.0f;
|
|
}
|
|
|
|
m_scroll->SetVisibleRatio(ratio);
|
|
m_scroll->SetVisibleValue(value);
|
|
m_scroll->SetArrowStep(step);
|
|
}
|
|
|
|
// Update when the lift is moving.
|
|
|
|
void CList::MoveScroll()
|
|
{
|
|
if (m_scroll == nullptr)
|
|
return;
|
|
|
|
int n = m_totalLine - m_displayLine;
|
|
float pos = m_scroll->GetVisibleValue();
|
|
pos += m_scroll->GetArrowStep() / 2.0f; // it's magic!
|
|
m_firstLine = static_cast<int>(pos * n);
|
|
if ( m_firstLine < 0 )
|
|
m_firstLine = 0;
|
|
if ( m_firstLine > n )
|
|
m_firstLine = n;
|
|
}
|
|
|
|
|
|
} // namespace Ui
|