union-minui/other/DinguxCommander/src/dialog.cpp
2023-04-15 10:36:01 +02:00

260 lines
6.9 KiB
C++

#include <iostream>
#include "dialog.h"
#include "sdlutils.h"
#include "resourceManager.h"
#include "def.h"
CDialog::CDialog(const std::string &p_title, const Sint16 p_x, const Sint16 p_y):
CWindow(),
m_nbTitle(false),
m_nbLabels(0),
m_nbOptions(0),
m_highlightedLine(0),
m_image(NULL),
m_cursor1(NULL),
m_cursor2(NULL),
m_x(p_x),
m_y(p_y),
m_cursorX(0),
m_cursorY(0),
m_font(CResourceManager::instance().getFont()),
m_font_sm(CResourceManager::instance().getSmallFont())
{
// Title
if (!p_title.empty())
{
m_nbTitle = true;
m_lines.push_back(p_title);
}
// Init clip
m_clip.x = 0;
m_clip.y = 0;
m_clip.w = 0;
m_clip.h = 0;
}
CDialog::~CDialog(void)
{
// Free surfaces
if (m_image != NULL)
{
SDL_FreeSurface(m_image);
m_image = NULL;
}
if (m_cursor1 != NULL)
{
SDL_FreeSurface(m_cursor1);
m_cursor1 = NULL;
}
if (m_cursor2 != NULL)
{
SDL_FreeSurface(m_cursor2);
m_cursor2 = NULL;
}
for (std::vector<SDL_Surface *>::iterator l_it = m_linesImg.begin(); l_it != m_linesImg.end(); ++l_it)
{
if (*l_it != NULL)
{
SDL_FreeSurface(*l_it);
*l_it = NULL;
}
}
}
void CDialog::addLabel(const std::string &p_label)
{
m_lines.push_back(p_label);
++m_nbLabels;
}
void CDialog::addOption(const std::string &p_option)
{
m_lines.push_back(p_option);
++m_nbOptions;
}
void CDialog::init(void)
{
// The width of the window depends on the width of the largest line
int l_width(0);
int l_cursorWidth(0);
SDL_Surface *l_surfaceTmp(NULL);
// Render every line
for (std::vector<std::string>::const_iterator l_it = m_lines.begin(); l_it != m_lines.end(); ++l_it)
{
// Render line
l_surfaceTmp = SDL_utils::renderText(m_font, *l_it, (m_nbTitle && l_it == m_lines.begin()) ? Globals::g_colorTextTitle : Globals::g_colorTextNormal);
if (l_surfaceTmp->w > l_width)
l_width = l_surfaceTmp->w;
m_linesImg.push_back(l_surfaceTmp);
}
// Cursor width
l_cursorWidth = l_width + 2 * DIALOG_MARGIN;
if (l_cursorWidth > SCREEN_WIDTH - 2 * DIALOG_BORDER)
l_cursorWidth = SCREEN_WIDTH - 2 * DIALOG_BORDER;
// Line clip
m_clip.h = m_linesImg.front()->h;
m_clip.w = l_cursorWidth - DIALOG_MARGIN - 1;
// Adjust image width
l_width = l_width + 2 * DIALOG_MARGIN + 2 * DIALOG_BORDER;
if (l_width > SCREEN_WIDTH)
l_width = SCREEN_WIDTH;
// Create dialog image
m_image = SDL_utils::createImage(l_width, m_linesImg.size() * LINE_HEIGHT + 2 * DIALOG_BORDER, SDL_MapRGB(Globals::g_screen->format, COLOR_BORDER));
{
SDL_Rect l_rect;
l_rect.x = DIALOG_BORDER;
l_rect.y = DIALOG_BORDER + m_nbTitle * LINE_HEIGHT;
l_rect.w = m_image->w - 2 * DIALOG_BORDER;
l_rect.h = m_image->h - 2 * DIALOG_BORDER - m_nbTitle * LINE_HEIGHT;
SDL_FillRect(m_image, &l_rect, SDL_MapRGB(m_image->format, COLOR_BG_1));
}
// Create cursor image
m_cursor1 = SDL_utils::createImage(l_cursorWidth, LINE_HEIGHT, SDL_MapRGB(Globals::g_screen->format, COLOR_CURSOR_1));
m_cursor2 = SDL_utils::createImage(l_cursorWidth, LINE_HEIGHT, SDL_MapRGB(Globals::g_screen->format, COLOR_CURSOR_2));
// Adjust dialog coordinates
if (!m_x)
m_x = (SCREEN_WIDTH - m_image->w) >> 1;
if (!m_y)
{
m_y = (SCREEN_HEIGHT - m_image->h) >> 1;
}
else
{
m_y = m_y - (m_image->h >> 1) + (LINE_HEIGHT >> 1);
if (m_y < Y_LIST)
m_y = Y_LIST;
if (m_y + m_image->h > Y_FOOTER + 1)
m_y = Y_FOOTER + 1 - m_image->h;
}
// Cursor coordinates
m_cursorX = m_x + DIALOG_BORDER;
m_cursorY = m_y + DIALOG_BORDER + (m_nbTitle + m_nbLabels) * LINE_HEIGHT;
}
void CDialog::render(const bool p_focus) const
{
INHIBIT(std::cout << "CDialog::render fullscreen: " << isFullScreen() << " focus: " << p_focus << std::endl;)
// Draw background
SDL_utils::applySurface(m_x, m_y, m_image, Globals::g_screen);
// Draw cursor
SDL_utils::applySurface(m_cursorX, m_cursorY + m_highlightedLine * LINE_HEIGHT, p_focus ? m_cursor1 : m_cursor2, Globals::g_screen);
// Draw lines text
Sint16 l_y(m_y + 4);
for (std::vector<SDL_Surface *>::const_iterator l_it = m_linesImg.begin(); l_it != m_linesImg.end(); ++l_it)
{
SDL_utils::applySurface(m_cursorX + DIALOG_MARGIN, (m_nbTitle && l_it == m_linesImg.begin()) ? l_y - 1 - Y_OFFSET : l_y - Y_OFFSET, *l_it, Globals::g_screen, &m_clip);
l_y += LINE_HEIGHT;
}
}
const bool CDialog::keyPress(const SDL_Event &p_event)
{
CWindow::keyPress(p_event);
bool l_ret(false);
switch (p_event.key.keysym.sym)
{
case MYKEY_PARENT:
m_retVal = -1;
l_ret = true;
break;
case MYKEY_UP:
l_ret = moveCursorUp(true);
break;
case MYKEY_DOWN:
l_ret = moveCursorDown(true);
break;
case MYKEY_PAGEUP:
if (m_highlightedLine)
{
m_highlightedLine = 0;
l_ret = true;
}
break;
case MYKEY_PAGEDOWN:
if (m_highlightedLine + 1 < m_nbOptions)
{
m_highlightedLine = m_nbOptions - 1;
l_ret = true;
}
break;
case MYKEY_OPEN:
m_retVal = m_highlightedLine + 1;
l_ret = true;
break;
default:
break;
}
return l_ret;
}
const bool CDialog::moveCursorUp(const bool p_loop)
{
bool l_ret(false);
if (m_highlightedLine)
{
--m_highlightedLine;
l_ret = true;
}
else if (p_loop && m_highlightedLine + 1 < m_nbOptions)
{
m_highlightedLine = m_nbOptions - 1;
l_ret = true;
}
return l_ret;
}
const bool CDialog::moveCursorDown(const bool p_loop)
{
bool l_ret(false);
if (m_highlightedLine + 1 < m_nbOptions)
{
++m_highlightedLine;
l_ret = true;
}
else if (p_loop && m_highlightedLine)
{
m_highlightedLine = 0;
l_ret = true;
}
return l_ret;
}
const bool CDialog::keyHold(void)
{
bool l_ret(false);
switch(m_lastPressed)
{
case MYKEY_UP:
if (tick(SDL_GetKeyState(NULL)[MYKEY_UP]))
l_ret = moveCursorUp(false);
break;
case MYKEY_DOWN:
if (tick(SDL_GetKeyState(NULL)[MYKEY_DOWN]))
l_ret = moveCursorDown(false);
break;
default:
break;
}
return l_ret;
}
const Sint16 &CDialog::getX(void) const
{
return m_x;
}
const Sint16 &CDialog::getY(void) const
{
return m_y;
}
const SDL_Surface * const CDialog::getImage(void) const
{
return m_image;
}
const unsigned int &CDialog::getHighlightedIndex(void) const
{
return m_highlightedLine;
}