1
0
mirror of https://github.com/blupi-games/planetblupi synced 2024-12-30 10:15:36 +01:00
planetblupi/src/button.cxx
2017-10-18 07:04:35 +02:00

435 lines
8.1 KiB
C++

/*
* This file is part of the planetblupi source code
* Copyright (C) 1997, Daniel Roux & EPSITEC SA
* Copyright (C) 2017, Mathieu Schroeter
* http://epsitec.ch; http://www.blupi.org; http://github.com/blupi-games
*
* 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 <stdio.h>
#include <stdlib.h>
#include "button.h"
#include "decor.h"
#include "def.h"
#include "event.h"
#include "gettext.h"
#include "misc.h"
#include "pixmap.h"
#include "sound.h"
CButton::CButton ()
{
m_type = 0;
m_bEnable = true;
m_bHide = false;
m_state = 0;
m_mouseState = 0;
m_nbMenu = 0;
m_nbToolTips = 0;
m_selMenu = 0;
m_bMouseDown = false;
m_message = static_cast<Uint32> (-1);
m_pPixmap = nullptr;
m_pDecor = nullptr;
m_pSound = nullptr;
m_toolTips = nullptr;
}
CButton::~CButton ()
{
}
// Crée un nouveau bouton.
bool
CButton::Create (
CPixmap * pPixmap, CSound * pSound, Point pos, Sint32 type, Sint32 * pMenu,
Sint32 nbMenu, const char ** pToolTips, Sint32 region, Uint32 message)
{
Point iconDim;
Sint32 i, icon;
static Sint32 ttypes[] = {
DIMBUTTONX, DIMBUTTONY, // button00.bmp
};
if (type < 0 || type > 0)
return false;
iconDim.x = ttypes[type * 2 + 0];
iconDim.y = ttypes[type * 2 + 1];
m_pPixmap = pPixmap;
m_pSound = pSound;
m_type = type;
m_bEnable = true;
m_bHide = false;
m_message = message;
m_pos = pos;
m_dim = iconDim;
m_nbMenu = nbMenu;
m_selMenu = 0;
m_state = 0;
m_mouseState = 0;
m_bMouseDown = false;
m_nbToolTips = 0;
while (pToolTips[m_nbToolTips])
++m_nbToolTips;
for (i = 0; i < nbMenu; i++)
{
icon = pMenu[i];
if (region == 1) // palmiers ?
{
if (icon == 0)
icon = 90; // sol normal
if (icon == 1)
icon = 91; // sol inflammable
if (icon == 2)
icon = 92; // sol inculte
if (icon == 7)
icon = 9; // plante
if (icon == 8)
icon = 10; // arbre
}
if (region == 2) // hiver ?
{
if (icon == 0)
icon = 96; // sol normal
if (icon == 1)
icon = 97; // sol inflammable
if (icon == 2)
icon = 98; // sol inculte
if (icon == 8)
icon = 99; // arbre
}
if (region == 3) // sapin ?
{
if (icon == 0)
icon = 102; // sol normal
if (icon == 1)
icon = 103; // sol inflammable
if (icon == 2)
icon = 104; // sol inculte
if (icon == 8)
icon = 105; // arbre
}
m_iconMenu[i] = icon;
}
m_toolTips = pToolTips;
return true;
}
// Dessine un bouton dans son état.
void
CButton::Draw ()
{
Sint32 i;
Point pos;
Rect rect;
if (m_bHide) // bouton caché ?
{
rect.left = m_pos.x;
rect.right = m_pos.x + m_dim.x;
rect.top = m_pos.y;
rect.bottom = m_pos.y + m_dim.y;
m_pPixmap->DrawPart (-1, CHBACK, m_pos, rect); // dessine le fond
return;
}
if (m_bEnable) // bouton actif ?
m_pPixmap->DrawIcon (-1, CHBUTTON + m_type, m_mouseState, m_pos);
else
m_pPixmap->DrawIcon (-1, CHBUTTON + m_type, 4, m_pos);
if (m_nbMenu == 0)
return;
pos = m_pos;
if (m_nbMenu > 0)
{
m_pPixmap->DrawIcon (-1, CHBUTTON + m_type, m_iconMenu[m_selMenu] + 6, pos);
}
if (m_nbMenu == 1 || !m_bEnable || !m_bMouseDown)
return;
pos = m_pos;
pos.x += m_dim.x + 2;
for (i = 0; i < m_nbMenu; i++)
{
m_pPixmap->DrawIcon (-1, CHBUTTON + m_type, i == m_selMenu ? 1 : 0, pos);
m_pPixmap->DrawIcon (-1, CHBUTTON + m_type, m_iconMenu[i] + 6, pos);
pos.x += m_dim.x - 1;
}
}
Sint32
CButton::GetState ()
{
return m_state;
}
void
CButton::SetState (Sint32 state)
{
m_state = state;
m_mouseState = state;
}
Sint32
CButton::GetMenu ()
{
return m_selMenu;
}
void
CButton::SetMenu (Sint32 menu)
{
m_selMenu = menu;
}
bool
CButton::GetEnable ()
{
return m_bEnable;
}
void
CButton::SetEnable (bool bEnable)
{
m_bEnable = bEnable;
}
bool
CButton::GetHide ()
{
return m_bHide;
}
void
CButton::SetHide (bool bHide)
{
m_bHide = bHide;
}
// Traitement d'un événement.
bool
CButton::TreatEvent (const SDL_Event & event)
{
Point pos;
if (m_bHide || !m_bEnable)
return false;
// pos = ConvLongToPos(lParam);
switch (event.type)
{
case SDL_MOUSEBUTTONDOWN:
if (
event.button.button != SDL_BUTTON_LEFT &&
event.button.button != SDL_BUTTON_RIGHT)
break;
pos.x = event.button.x;
pos.y = event.button.y;
if (MouseDown (pos))
return true;
break;
case SDL_MOUSEMOTION:
pos.x = event.motion.x;
pos.y = event.motion.y;
if (MouseMove (pos))
return true;
break;
case SDL_MOUSEBUTTONUP:
if (
event.button.button != SDL_BUTTON_LEFT &&
event.button.button != SDL_BUTTON_RIGHT)
break;
pos.x = event.button.x;
pos.y = event.button.y;
if (MouseUp (pos))
return false; // (*)
break;
}
return false;
}
// (*) Tous les boutons doivent recevoir l'événement BUTTONUP !
// Indique si la souris est sur ce bouton.
bool
CButton::MouseOnButton (Point pos)
{
return Detect (pos);
}
// Retourne le tooltips pour un bouton, en fonction
// de la position de la souris.
const char *
CButton::GetToolTips (Point pos)
{
Sint32 width = m_dim.x;
Sint32 rank;
if (m_bHide || !m_bEnable)
return nullptr;
if (m_nbMenu > 1 && m_bMouseDown) // sous-menu déroulé ?
width += 2 + (m_dim.x - 1) * m_nbMenu;
if (
pos.x < m_pos.x || pos.x > m_pos.x + width || pos.y < m_pos.y ||
pos.y > m_pos.y + m_dim.y)
return nullptr;
rank = (pos.x - (m_pos.x + 2 + 1)) / (m_dim.x - 1);
if (rank < 0)
rank = 0;
if (rank > m_nbToolTips)
return nullptr;
if (m_nbMenu > 1)
{
if (m_bMouseDown && rank > 0)
rank--;
else
rank = m_selMenu;
}
return gettext (m_toolTips[rank]);
}
// Détecte si la souris est dans le bouton.
bool
CButton::Detect (Point pos)
{
Sint32 width = m_dim.x;
if (m_bHide || !m_bEnable)
return false;
if (m_nbMenu > 1 && m_bMouseDown) // sous-menu déroulé ?
width += 2 + (m_dim.x - 1) * m_nbMenu;
if (
pos.x < m_pos.x || pos.x > m_pos.x + width || pos.y < m_pos.y ||
pos.y > m_pos.y + m_dim.y)
return false;
return true;
}
// Bouton de la souris pressé.
bool
CButton::MouseDown (Point pos)
{
if (!Detect (pos))
return false;
m_mouseState = 1;
m_bMouseDown = true;
CEvent::PushUserEvent (EV_UPDATE);
m_pSound->PlayImage (SOUND_CLICK, pos);
return true;
}
// Souris déplacés.
bool
CButton::MouseMove (Point pos)
{
bool bDetect;
Sint32 iState, iMenu;
iState = m_mouseState;
iMenu = m_selMenu;
bDetect = Detect (pos);
if (m_bMouseDown)
{
if (bDetect)
m_mouseState = 1; // pressé
else
m_mouseState = m_state;
}
else
{
if (bDetect)
m_mouseState = m_state + 2; // survollé
else
m_mouseState = m_state;
}
if (
m_nbMenu > 1 && m_bMouseDown &&
pos.x > m_pos.x + m_dim.x + 2) // dans sous-menu ?
{
m_selMenu = (pos.x - (m_pos.x + m_dim.x + 2)) / (m_dim.x - 1);
if (m_selMenu >= m_nbMenu)
m_selMenu = m_nbMenu - 1;
}
if (iState != m_mouseState || iMenu != m_selMenu)
CEvent::PushUserEvent (EV_UPDATE);
return m_bMouseDown;
}
// Bouton de la souris relâché.
bool
CButton::MouseUp (Point pos)
{
bool bDetect;
bDetect = Detect (pos);
m_mouseState = m_state;
m_bMouseDown = false;
if (!bDetect)
return false;
if (m_message != static_cast<Uint32> (-1))
CEvent::PushUserEvent (m_message);
return true;
}