summaryrefslogtreecommitdiffstats
path: root/src/ui/list.cpp
diff options
context:
space:
mode:
authorPiotr Dziwinski <piotrdz@gmail.com>2012-06-26 22:23:05 +0200
committerPiotr Dziwinski <piotrdz@gmail.com>2012-06-26 22:23:05 +0200
commitebed57aa22b772211387a5561f995eee8f5faed1 (patch)
tree9a0b08371df54c125957e63c7ecff81c001d4eaf /src/ui/list.cpp
parentfc5389d18816799ba2698914384cd099ba8a7a6c (diff)
downloadcolobot-ebed57aa22b772211387a5561f995eee8f5faed1.tar.gz
colobot-ebed57aa22b772211387a5561f995eee8f5faed1.tar.bz2
colobot-ebed57aa22b772211387a5561f995eee8f5faed1.zip
Whitespace and language change
- changed tabs to spaces and DOS line endings to Unix (except in CBot and metafile) - changed language to English - fixed #include <d3d.h> in d3dengine.h
Diffstat (limited to 'src/ui/list.cpp')
-rw-r--r--src/ui/list.cpp1736
1 files changed, 868 insertions, 868 deletions
diff --git a/src/ui/list.cpp b/src/ui/list.cpp
index fd137eb..75c740d 100644
--- a/src/ui/list.cpp
+++ b/src/ui/list.cpp
@@ -1,868 +1,868 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * 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://www.gnu.org/licenses/.
-
-// list.cpp
-
-
-#include <windows.h>
-#include <stdio.h>
-#include <d3d.h>
-
-#include "common/struct.h"
-#include "old/d3dengine.h"
-#include "old/math3d.h"
-#include "common/event.h"
-#include "common/misc.h"
-#include "common/iman.h"
-#include "ui/button.h"
-#include "ui/scroll.h"
-#include "old/text.h"
-#include "ui/list.h"
-
-
-
-const float MARGING = 4.0f;
-
-
-
-// Object's constructor.
-
-CList::CList(CInstanceManager* iMan) : CControl(iMan)
-{
- int i;
-
- for ( i=0 ; i<LISTMAXDISPLAY ; i++ )
- {
- m_button[i] = 0;
- }
- m_scroll = 0;
-
- for ( i=0 ; i<LISTMAXTOTAL ; i++ )
- {
- m_text[i][0] = 0;
- m_check[i] = false;
- m_enable[i] = true;
- }
-
- for ( i=0 ; i<10 ; i++ )
- {
- m_tabs[i] = 0.0f;
- m_justifs[i] = 1;
- }
-
- 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()
-{
- int i;
-
- for ( i=0 ; i<LISTMAXDISPLAY ; i++ )
- {
- delete m_button[i];
- }
- delete m_scroll;
-}
-
-
-// Creates a new list.
-
-bool CList::Create(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg,
- float expand)
-{
- m_expand = expand;
-
- if ( eventMsg == EVENT_NULL ) eventMsg = GetUniqueEventMsg();
- CControl::Create(pos, dim, icon, eventMsg);
-
- m_scroll = new CScroll(m_iMan);
- m_scroll->Create(pos, dim, 0, EVENT_NULL);
- m_eventScroll = m_scroll->RetEventMsg();
-
- return MoveAdjust();
-}
-
-// Adjusted after a change of dimensions.
-
-bool CList::MoveAdjust()
-{
- Math::Point ipos, idim, ppos, ddim;
- float marging, h;
- int i;
-
- for ( i=0 ; i<LISTMAXDISPLAY ; i++ )
- {
- delete m_button[i];
- m_button[i] = 0;
- }
-
- 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;
-
- h = m_engine->RetText()->RetHeight(m_fontSize, m_fontType)*m_expand;
-
- m_displayLine = (int)(idim.y/h);
- if ( m_displayLine == 0 ) return false;
- if ( m_displayLine > LISTMAXDISPLAY ) m_displayLine = LISTMAXDISPLAY;
- idim.y = h*m_displayLine;
- 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 ( i=0 ; i<m_displayLine ; i++ )
- {
- m_button[i] = new CButton(m_iMan);
- m_button[i]->Create(ppos, ddim, -1, EVENT_NULL);
- m_button[i]->SetJustif(1);
- m_button[i]->SetState(STATE_SIMPLY);
- m_button[i]->SetFontType(m_fontType);
- m_button[i]->SetFontSize(m_fontSize);
- ppos.y -= h;
-
- m_eventButton[i] = m_button[i]->RetEventMsg();
- }
-
- if ( m_scroll != 0 )
- {
- 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.
-
-EventMsg CList::RetEventMsgButton(int i)
-{
- if ( i < 0 || i >= m_displayLine ) return EVENT_NULL;
- if ( m_button[i] == 0 ) return EVENT_NULL;
- return m_button[i]->RetEventMsg();
-}
-
-// Returns the message from the elevator.
-
-EventMsg CList::RetEventMsgScroll()
-{
- if ( m_scroll == 0 ) return EVENT_NULL;
- return m_scroll->RetEventMsg();
-}
-
-
-void CList::SetPos(Math::Point pos)
-{
- CControl::SetPos(pos);
-}
-
-void CList::SetDim(Math::Point dim)
-{
- m_dim = dim;
- MoveAdjust();
- CControl::SetDim(dim);
-}
-
-
-bool CList::SetState(int state, bool bState)
-{
- int i;
-
- if ( state & STATE_ENABLE )
- {
- for ( i=0 ; i<m_displayLine ; i++ )
- {
- if ( m_button[i] != 0 ) m_button[i]->SetState(state, bState);
- }
- if ( m_scroll != 0 ) m_scroll->SetState(state, bState);
- }
-
- return CControl::SetState(state, bState);
-}
-
-bool CList::SetState(int state)
-{
- int i;
-
- if ( state & STATE_ENABLE )
- {
- for ( i=0 ; i<m_displayLine ; i++ )
- {
- if ( m_button[i] != 0 ) m_button[i]->SetState(state);
- }
- if ( m_scroll != 0 ) m_scroll->SetState(state);
- }
-
- return CControl::SetState(state);
-}
-
-bool CList::ClearState(int state)
-{
- int i;
-
- if ( state & STATE_ENABLE )
- {
- for ( i=0 ; i<m_displayLine ; i++ )
- {
- if ( m_button[i] != 0 ) m_button[i]->ClearState(state);
- }
- if ( m_scroll != 0 ) m_scroll->ClearState(state);
- }
-
- return CControl::ClearState(state);
-}
-
-
-// Management of an event.
-
-bool CList::EventProcess(const Event &event)
-{
- int i;
-
- if ( m_bBlink && // blinks?
- event.event == EVENT_FRAME )
- {
- i = m_selectLine-m_firstLine;
-
- if ( i >= 0 && i < 4 &&
- m_button[i] != 0 )
- {
- m_blinkTime += event.rTime;
- if ( Math::Mod(m_blinkTime, 0.7f) < 0.3f )
- {
- m_button[i]->ClearState(STATE_ENABLE);
- m_button[i]->ClearState(STATE_CHECK);
- }
- else
- {
- m_button[i]->SetState(STATE_ENABLE);
- m_button[i]->SetState(STATE_CHECK);
- }
- }
- }
-
- if ( (m_state & STATE_VISIBLE) == 0 ) return true;
- if ( (m_state & STATE_ENABLE) == 0 ) return true;
-
- if ( event.event == EVENT_KEYDOWN &&
- event.param == VK_WHEELUP &&
- Detect(event.pos) )
- {
- if ( m_firstLine > 0 ) m_firstLine --;
- UpdateScroll();
- UpdateButton();
- return true;
- }
- if ( event.event == EVENT_KEYDOWN &&
- event.param == VK_WHEELDOWN &&
- Detect(event.pos) )
- {
- if ( m_firstLine < m_totalLine-m_displayLine ) m_firstLine ++;
- UpdateScroll();
- UpdateButton();
- return true;
- }
-
- CControl::EventProcess(event);
-
- if ( event.event == EVENT_MOUSEMOVE && Detect(event.pos) )
- {
- m_engine->SetMouseType(D3DMOUSENORM);
- for ( i=0 ; i<m_displayLine ; i++ )
- {
- if ( i+m_firstLine >= m_totalLine ) break;
- if ( m_button[i] != 0 )
- {
- m_button[i]->EventProcess(event);
- }
- }
- }
-
- if ( m_bSelectCap )
- {
- for ( i=0 ; i<m_displayLine ; i++ )
- {
- if ( i+m_firstLine >= m_totalLine ) break;
- if ( m_button[i] != 0 )
- {
- if ( !m_button[i]->EventProcess(event) ) return false;
-
- if ( event.event == m_eventButton[i] )
- {
- SetSelect(m_firstLine+i);
-
- Event newEvent = event;
- newEvent.event = m_eventMsg;
- m_event->AddEvent(newEvent); // selected line changes
- }
- }
- }
- }
-
- if ( m_scroll != 0 )
- {
- if ( !m_scroll->EventProcess(event) ) return false;
-
- if ( event.event == m_eventScroll )
- {
- MoveScroll();
- UpdateButton();
- }
- }
-
- return true;
-}
-
-
-// Draws the list.
-
-void CList::Draw()
-{
- Math::Point uv1, uv2, corner, pos, dim, ppos, ddim;
- float dp;
- int i, j;
- char text[100];
- 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;
-
- if ( m_icon != -1 )
- {
- dim = m_dim;
-
- if ( m_icon == 0 )
- {
- m_engine->SetTexture("button2.tga");
- m_engine->SetState(D3DSTATENORMAL);
-
- 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
- {
- m_engine->SetTexture("button2.tga");
- m_engine->SetState(D3DSTATENORMAL);
-
- 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_button[0] != 0 )
- {
- dim = m_button[0]->RetDim();
- 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_button[i] != 0 )
- {
- pos = m_button[i]->RetPos();
- dim = m_button[i]->RetDim();
- pos.y += dim.y*1.1f;
- dim.y *= 0.4f;
- pos.y -= dim.y;
-
- m_engine->SetTexture("button2.tga");
- m_engine->SetState(D3DSTATETTw);
- 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_button[i] != 0 )
- {
- if ( !m_bBlink && i+m_firstLine < m_totalLine )
- {
- m_button[i]->SetState(STATE_ENABLE, m_enable[i+m_firstLine] && (m_state & STATE_ENABLE) );
- }
- m_button[i]->Draw(); // draws a box without text
-
- // draws text in the box
- pos = m_button[i]->RetPos();
- dim = m_button[i]->RetDim();
- 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->RetText()->RetHeight(m_fontSize, m_fontType)/2.0f;
- ddim.x = dim.x-dim.y;
- DrawCase(m_text[i+m_firstLine], ppos, ddim.x, 1);
- }
- else
- {
- ppos.x = pos.x+dim.y*0.5f;
- ppos.y = pos.y+dim.y*0.5f;
- ppos.y -= m_engine->RetText()->RetHeight(m_fontSize, m_fontType)/2.0f;
- pb = m_text[i+m_firstLine];
- for ( j=0 ; j<10 ; j++ )
- {
- pe = strchr(pb, '\t');
- if ( pe == 0 )
- {
- strcpy(text, pb);
- }
- else
- {
- strncpy(text, pb, pe-pb);
- text[pe-pb] = 0;
- }
- DrawCase(text, ppos, m_tabs[j], m_justifs[j]);
-
- if ( pe == 0 ) break;
- ppos.x += m_tabs[j];
- pb = pe+1;
- }
- }
-
- if ( (m_state & STATE_EXTEND) && i < m_totalLine )
- {
- pos = m_button[i]->RetPos();
- dim = m_button[i]->RetDim();
- 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_check[i+m_firstLine] )
- {
- m_engine->SetTexture("button1.tga");
- m_engine->SetState(D3DSTATENORMAL);
- 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
-
- m_engine->SetState(D3DSTATETTw);
- 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
- {
- m_engine->SetTexture("button1.tga");
- m_engine->SetState(D3DSTATETTw);
- 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 != 0 )
- {
- m_scroll->Draw(); // draws the lift
- }
-}
-
-// Displays text in a box.
-
-void CList::DrawCase(char *text, Math::Point pos, float width, int justif)
-{
- if ( justif == 1 )
- {
- m_engine->RetText()->DrawText(text, pos, width, 1, m_fontSize, m_fontStretch, m_fontType, 0);
- }
- else if ( justif == 0 )
- {
- pos.x += width/2.0f;
- m_engine->RetText()->DrawText(text, pos, width, 0, m_fontSize, m_fontStretch, m_fontType, 0);
- }
- else
- {
- pos.x += width;
- m_engine->RetText()->DrawText(text, pos, width, -1, m_fontSize, m_fontStretch, m_fontType, 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::RetTotal()
-{
- 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::RetSelect()
-{
- 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::RetSelectCap()
-{
- return m_bSelectCap;
-}
-
-
-// Blink a line.
-
-void CList::SetBlink(bool bEnable)
-{
- int i;
-
- m_bBlink = bEnable;
- m_blinkTime = 0.0f;
-
- i = m_selectLine-m_firstLine;
-
- if ( i >= 0 && i < 4 &&
- m_button[i] != 0 )
- {
- if ( !bEnable )
- {
- m_button[i]->SetState(STATE_CHECK);
- m_button[i]->ClearState(STATE_ENABLE);
- }
- }
-}
-
-bool CList::RetBlink()
-{
- return m_bBlink;
-}
-
-
-// Specifies the text of a line.
-
-void CList::SetName(int i, char* name)
-{
- if ( i < 0 || i >= LISTMAXTOTAL ) return;
-
- if ( i >= m_totalLine )
- {
- m_totalLine = i+1; // expands the list
- }
-
- if ( name[0] == 0 )
- {
- strcpy(m_text[i], " ");
- }
- else
- {
- strcpy(m_text[i], name);
- }
- UpdateButton();
- UpdateScroll();
-}
-
-// Returns the text of a line.
-
-char* CList::RetName(int i)
-{
- if ( i < 0 || i >= m_totalLine ) return 0;
-
- return m_text[i];
-}
-
-
-// Specifies the bit "check" for a box.
-
-void CList::SetCheck(int i, bool bMode)
-{
- if ( i < 0 || i >= m_totalLine ) return;
-
- m_check[i] = bMode;
-}
-
-// Returns the bit "check" for a box.
-
-bool CList::RetCheck(int i)
-{
- if ( i < 0 || i >= m_totalLine ) return false;
-
- return m_check[i];
-}
-
-
-// Specifies the bit "enable" for a box.
-
-void CList::SetEnable(int i, bool bMode)
-{
- if ( i < 0 || i >= m_totalLine ) return;
-
- m_enable[i] = bMode;
-}
-
-// Returns the bit "enable" for a box.
-
-bool CList::RetEnable(int i)
-{
- if ( i < 0 || i >= m_totalLine ) return false;
-
- return m_enable[i];
-}
-
-
-// Management of the position of the tabs.
-
-void CList::SetTabs(int i, float pos, int justif)
-{
- if ( i < 0 || i >= 10 ) return;
- m_tabs[i] = pos;
- m_justifs[i] = justif;
-}
-
-float CList::RetTabs(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::RetState();
-
- j = m_firstLine;
- for ( i=0 ; i<m_displayLine ; i++ )
- {
- if ( m_button[i] == 0 ) continue;
-
- m_button[i]->SetState(STATE_CHECK, (j == m_selectLine));
-
- if ( j < m_totalLine )
- {
-//? m_button[i]->SetName(m_text[j]);
- m_button[i]->SetName(" "); // blank button
- m_button[i]->SetState(STATE_ENABLE, (state & STATE_ENABLE));
- }
- else
- {
- m_button[i]->SetName(" "); // blank button
- m_button[i]->ClearState(STATE_ENABLE);
- }
- j ++;
- }
-}
-
-// Updates the lift.
-
-void CList::UpdateScroll()
-{
- float ratio, value, step;
-
- if ( m_scroll == 0 ) return;
-
- if ( m_totalLine <= m_displayLine )
- {
- ratio = 1.0f;
- value = 0.0f;
- step = 0.0f;
- }
- else
- {
- ratio = (float)m_displayLine/m_totalLine;
- if ( ratio > 1.0f ) ratio = 1.0f;
-
- value = (float)m_firstLine/(m_totalLine-m_displayLine);
- if ( value < 0.0f ) value = 0.0f;
- if ( value > 1.0f ) value = 1.0f;
-
- step = (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()
-{
- float pos;
- int n;
-
- if ( m_scroll == 0 ) return;
-
- n = m_totalLine-m_displayLine;
- pos = m_scroll->RetVisibleValue();
- pos += m_scroll->RetArrowStep()/2.0f; // it's magic!
- m_firstLine = (int)(pos*n);
- if ( m_firstLine < 0 ) m_firstLine = 0;
- if ( m_firstLine > n ) m_firstLine = n;
-}
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * 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://www.gnu.org/licenses/.
+
+// list.cpp
+
+
+#include <windows.h>
+#include <stdio.h>
+#include <d3d.h>
+
+#include "common/struct.h"
+#include "old/d3dengine.h"
+#include "old/math3d.h"
+#include "common/event.h"
+#include "common/misc.h"
+#include "common/iman.h"
+#include "ui/button.h"
+#include "ui/scroll.h"
+#include "old/text.h"
+#include "ui/list.h"
+
+
+
+const float MARGING = 4.0f;
+
+
+
+// Object's constructor.
+
+CList::CList(CInstanceManager* iMan) : CControl(iMan)
+{
+ int i;
+
+ for ( i=0 ; i<LISTMAXDISPLAY ; i++ )
+ {
+ m_button[i] = 0;
+ }
+ m_scroll = 0;
+
+ for ( i=0 ; i<LISTMAXTOTAL ; i++ )
+ {
+ m_text[i][0] = 0;
+ m_check[i] = false;
+ m_enable[i] = true;
+ }
+
+ for ( i=0 ; i<10 ; i++ )
+ {
+ m_tabs[i] = 0.0f;
+ m_justifs[i] = 1;
+ }
+
+ 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()
+{
+ int i;
+
+ for ( i=0 ; i<LISTMAXDISPLAY ; i++ )
+ {
+ delete m_button[i];
+ }
+ delete m_scroll;
+}
+
+
+// Creates a new list.
+
+bool CList::Create(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg,
+ float expand)
+{
+ m_expand = expand;
+
+ if ( eventMsg == EVENT_NULL ) eventMsg = GetUniqueEventMsg();
+ CControl::Create(pos, dim, icon, eventMsg);
+
+ m_scroll = new CScroll(m_iMan);
+ m_scroll->Create(pos, dim, 0, EVENT_NULL);
+ m_eventScroll = m_scroll->RetEventMsg();
+
+ return MoveAdjust();
+}
+
+// Adjusted after a change of dimensions.
+
+bool CList::MoveAdjust()
+{
+ Math::Point ipos, idim, ppos, ddim;
+ float marging, h;
+ int i;
+
+ for ( i=0 ; i<LISTMAXDISPLAY ; i++ )
+ {
+ delete m_button[i];
+ m_button[i] = 0;
+ }
+
+ 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;
+
+ h = m_engine->RetText()->RetHeight(m_fontSize, m_fontType)*m_expand;
+
+ m_displayLine = (int)(idim.y/h);
+ if ( m_displayLine == 0 ) return false;
+ if ( m_displayLine > LISTMAXDISPLAY ) m_displayLine = LISTMAXDISPLAY;
+ idim.y = h*m_displayLine;
+ 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 ( i=0 ; i<m_displayLine ; i++ )
+ {
+ m_button[i] = new CButton(m_iMan);
+ m_button[i]->Create(ppos, ddim, -1, EVENT_NULL);
+ m_button[i]->SetJustif(1);
+ m_button[i]->SetState(STATE_SIMPLY);
+ m_button[i]->SetFontType(m_fontType);
+ m_button[i]->SetFontSize(m_fontSize);
+ ppos.y -= h;
+
+ m_eventButton[i] = m_button[i]->RetEventMsg();
+ }
+
+ if ( m_scroll != 0 )
+ {
+ 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.
+
+EventMsg CList::RetEventMsgButton(int i)
+{
+ if ( i < 0 || i >= m_displayLine ) return EVENT_NULL;
+ if ( m_button[i] == 0 ) return EVENT_NULL;
+ return m_button[i]->RetEventMsg();
+}
+
+// Returns the message from the elevator.
+
+EventMsg CList::RetEventMsgScroll()
+{
+ if ( m_scroll == 0 ) return EVENT_NULL;
+ return m_scroll->RetEventMsg();
+}
+
+
+void CList::SetPos(Math::Point pos)
+{
+ CControl::SetPos(pos);
+}
+
+void CList::SetDim(Math::Point dim)
+{
+ m_dim = dim;
+ MoveAdjust();
+ CControl::SetDim(dim);
+}
+
+
+bool CList::SetState(int state, bool bState)
+{
+ int i;
+
+ if ( state & STATE_ENABLE )
+ {
+ for ( i=0 ; i<m_displayLine ; i++ )
+ {
+ if ( m_button[i] != 0 ) m_button[i]->SetState(state, bState);
+ }
+ if ( m_scroll != 0 ) m_scroll->SetState(state, bState);
+ }
+
+ return CControl::SetState(state, bState);
+}
+
+bool CList::SetState(int state)
+{
+ int i;
+
+ if ( state & STATE_ENABLE )
+ {
+ for ( i=0 ; i<m_displayLine ; i++ )
+ {
+ if ( m_button[i] != 0 ) m_button[i]->SetState(state);
+ }
+ if ( m_scroll != 0 ) m_scroll->SetState(state);
+ }
+
+ return CControl::SetState(state);
+}
+
+bool CList::ClearState(int state)
+{
+ int i;
+
+ if ( state & STATE_ENABLE )
+ {
+ for ( i=0 ; i<m_displayLine ; i++ )
+ {
+ if ( m_button[i] != 0 ) m_button[i]->ClearState(state);
+ }
+ if ( m_scroll != 0 ) m_scroll->ClearState(state);
+ }
+
+ return CControl::ClearState(state);
+}
+
+
+// Management of an event.
+
+bool CList::EventProcess(const Event &event)
+{
+ int i;
+
+ if ( m_bBlink && // blinks?
+ event.event == EVENT_FRAME )
+ {
+ i = m_selectLine-m_firstLine;
+
+ if ( i >= 0 && i < 4 &&
+ m_button[i] != 0 )
+ {
+ m_blinkTime += event.rTime;
+ if ( Math::Mod(m_blinkTime, 0.7f) < 0.3f )
+ {
+ m_button[i]->ClearState(STATE_ENABLE);
+ m_button[i]->ClearState(STATE_CHECK);
+ }
+ else
+ {
+ m_button[i]->SetState(STATE_ENABLE);
+ m_button[i]->SetState(STATE_CHECK);
+ }
+ }
+ }
+
+ if ( (m_state & STATE_VISIBLE) == 0 ) return true;
+ if ( (m_state & STATE_ENABLE) == 0 ) return true;
+
+ if ( event.event == EVENT_KEYDOWN &&
+ event.param == VK_WHEELUP &&
+ Detect(event.pos) )
+ {
+ if ( m_firstLine > 0 ) m_firstLine --;
+ UpdateScroll();
+ UpdateButton();
+ return true;
+ }
+ if ( event.event == EVENT_KEYDOWN &&
+ event.param == VK_WHEELDOWN &&
+ Detect(event.pos) )
+ {
+ if ( m_firstLine < m_totalLine-m_displayLine ) m_firstLine ++;
+ UpdateScroll();
+ UpdateButton();
+ return true;
+ }
+
+ CControl::EventProcess(event);
+
+ if ( event.event == EVENT_MOUSEMOVE && Detect(event.pos) )
+ {
+ m_engine->SetMouseType(D3DMOUSENORM);
+ for ( i=0 ; i<m_displayLine ; i++ )
+ {
+ if ( i+m_firstLine >= m_totalLine ) break;
+ if ( m_button[i] != 0 )
+ {
+ m_button[i]->EventProcess(event);
+ }
+ }
+ }
+
+ if ( m_bSelectCap )
+ {
+ for ( i=0 ; i<m_displayLine ; i++ )
+ {
+ if ( i+m_firstLine >= m_totalLine ) break;
+ if ( m_button[i] != 0 )
+ {
+ if ( !m_button[i]->EventProcess(event) ) return false;
+
+ if ( event.event == m_eventButton[i] )
+ {
+ SetSelect(m_firstLine+i);
+
+ Event newEvent = event;
+ newEvent.event = m_eventMsg;
+ m_event->AddEvent(newEvent); // selected line changes
+ }
+ }
+ }
+ }
+
+ if ( m_scroll != 0 )
+ {
+ if ( !m_scroll->EventProcess(event) ) return false;
+
+ if ( event.event == m_eventScroll )
+ {
+ MoveScroll();
+ UpdateButton();
+ }
+ }
+
+ return true;
+}
+
+
+// Draws the list.
+
+void CList::Draw()
+{
+ Math::Point uv1, uv2, corner, pos, dim, ppos, ddim;
+ float dp;
+ int i, j;
+ char text[100];
+ 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;
+
+ if ( m_icon != -1 )
+ {
+ dim = m_dim;
+
+ if ( m_icon == 0 )
+ {
+ m_engine->SetTexture("button2.tga");
+ m_engine->SetState(D3DSTATENORMAL);
+
+ 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
+ {
+ m_engine->SetTexture("button2.tga");
+ m_engine->SetState(D3DSTATENORMAL);
+
+ 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_button[0] != 0 )
+ {
+ dim = m_button[0]->RetDim();
+ 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_button[i] != 0 )
+ {
+ pos = m_button[i]->RetPos();
+ dim = m_button[i]->RetDim();
+ pos.y += dim.y*1.1f;
+ dim.y *= 0.4f;
+ pos.y -= dim.y;
+
+ m_engine->SetTexture("button2.tga");
+ m_engine->SetState(D3DSTATETTw);
+ 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_button[i] != 0 )
+ {
+ if ( !m_bBlink && i+m_firstLine < m_totalLine )
+ {
+ m_button[i]->SetState(STATE_ENABLE, m_enable[i+m_firstLine] && (m_state & STATE_ENABLE) );
+ }
+ m_button[i]->Draw(); // draws a box without text
+
+ // draws text in the box
+ pos = m_button[i]->RetPos();
+ dim = m_button[i]->RetDim();
+ 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->RetText()->RetHeight(m_fontSize, m_fontType)/2.0f;
+ ddim.x = dim.x-dim.y;
+ DrawCase(m_text[i+m_firstLine], ppos, ddim.x, 1);
+ }
+ else
+ {
+ ppos.x = pos.x+dim.y*0.5f;
+ ppos.y = pos.y+dim.y*0.5f;
+ ppos.y -= m_engine->RetText()->RetHeight(m_fontSize, m_fontType)/2.0f;
+ pb = m_text[i+m_firstLine];
+ for ( j=0 ; j<10 ; j++ )
+ {
+ pe = strchr(pb, '\t');
+ if ( pe == 0 )
+ {
+ strcpy(text, pb);
+ }
+ else
+ {
+ strncpy(text, pb, pe-pb);
+ text[pe-pb] = 0;
+ }
+ DrawCase(text, ppos, m_tabs[j], m_justifs[j]);
+
+ if ( pe == 0 ) break;
+ ppos.x += m_tabs[j];
+ pb = pe+1;
+ }
+ }
+
+ if ( (m_state & STATE_EXTEND) && i < m_totalLine )
+ {
+ pos = m_button[i]->RetPos();
+ dim = m_button[i]->RetDim();
+ 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_check[i+m_firstLine] )
+ {
+ m_engine->SetTexture("button1.tga");
+ m_engine->SetState(D3DSTATENORMAL);
+ 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
+
+ m_engine->SetState(D3DSTATETTw);
+ 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
+ {
+ m_engine->SetTexture("button1.tga");
+ m_engine->SetState(D3DSTATETTw);
+ 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 != 0 )
+ {
+ m_scroll->Draw(); // draws the lift
+ }
+}
+
+// Displays text in a box.
+
+void CList::DrawCase(char *text, Math::Point pos, float width, int justif)
+{
+ if ( justif == 1 )
+ {
+ m_engine->RetText()->DrawText(text, pos, width, 1, m_fontSize, m_fontStretch, m_fontType, 0);
+ }
+ else if ( justif == 0 )
+ {
+ pos.x += width/2.0f;
+ m_engine->RetText()->DrawText(text, pos, width, 0, m_fontSize, m_fontStretch, m_fontType, 0);
+ }
+ else
+ {
+ pos.x += width;
+ m_engine->RetText()->DrawText(text, pos, width, -1, m_fontSize, m_fontStretch, m_fontType, 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::RetTotal()
+{
+ 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::RetSelect()
+{
+ 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::RetSelectCap()
+{
+ return m_bSelectCap;
+}
+
+
+// Blink a line.
+
+void CList::SetBlink(bool bEnable)
+{
+ int i;
+
+ m_bBlink = bEnable;
+ m_blinkTime = 0.0f;
+
+ i = m_selectLine-m_firstLine;
+
+ if ( i >= 0 && i < 4 &&
+ m_button[i] != 0 )
+ {
+ if ( !bEnable )
+ {
+ m_button[i]->SetState(STATE_CHECK);
+ m_button[i]->ClearState(STATE_ENABLE);
+ }
+ }
+}
+
+bool CList::RetBlink()
+{
+ return m_bBlink;
+}
+
+
+// Specifies the text of a line.
+
+void CList::SetName(int i, char* name)
+{
+ if ( i < 0 || i >= LISTMAXTOTAL ) return;
+
+ if ( i >= m_totalLine )
+ {
+ m_totalLine = i+1; // expands the list
+ }
+
+ if ( name[0] == 0 )
+ {
+ strcpy(m_text[i], " ");
+ }
+ else
+ {
+ strcpy(m_text[i], name);
+ }
+ UpdateButton();
+ UpdateScroll();
+}
+
+// Returns the text of a line.
+
+char* CList::RetName(int i)
+{
+ if ( i < 0 || i >= m_totalLine ) return 0;
+
+ return m_text[i];
+}
+
+
+// Specifies the bit "check" for a box.
+
+void CList::SetCheck(int i, bool bMode)
+{
+ if ( i < 0 || i >= m_totalLine ) return;
+
+ m_check[i] = bMode;
+}
+
+// Returns the bit "check" for a box.
+
+bool CList::RetCheck(int i)
+{
+ if ( i < 0 || i >= m_totalLine ) return false;
+
+ return m_check[i];
+}
+
+
+// Specifies the bit "enable" for a box.
+
+void CList::SetEnable(int i, bool bMode)
+{
+ if ( i < 0 || i >= m_totalLine ) return;
+
+ m_enable[i] = bMode;
+}
+
+// Returns the bit "enable" for a box.
+
+bool CList::RetEnable(int i)
+{
+ if ( i < 0 || i >= m_totalLine ) return false;
+
+ return m_enable[i];
+}
+
+
+// Management of the position of the tabs.
+
+void CList::SetTabs(int i, float pos, int justif)
+{
+ if ( i < 0 || i >= 10 ) return;
+ m_tabs[i] = pos;
+ m_justifs[i] = justif;
+}
+
+float CList::RetTabs(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::RetState();
+
+ j = m_firstLine;
+ for ( i=0 ; i<m_displayLine ; i++ )
+ {
+ if ( m_button[i] == 0 ) continue;
+
+ m_button[i]->SetState(STATE_CHECK, (j == m_selectLine));
+
+ if ( j < m_totalLine )
+ {
+//? m_button[i]->SetName(m_text[j]);
+ m_button[i]->SetName(" "); // blank button
+ m_button[i]->SetState(STATE_ENABLE, (state & STATE_ENABLE));
+ }
+ else
+ {
+ m_button[i]->SetName(" "); // blank button
+ m_button[i]->ClearState(STATE_ENABLE);
+ }
+ j ++;
+ }
+}
+
+// Updates the lift.
+
+void CList::UpdateScroll()
+{
+ float ratio, value, step;
+
+ if ( m_scroll == 0 ) return;
+
+ if ( m_totalLine <= m_displayLine )
+ {
+ ratio = 1.0f;
+ value = 0.0f;
+ step = 0.0f;
+ }
+ else
+ {
+ ratio = (float)m_displayLine/m_totalLine;
+ if ( ratio > 1.0f ) ratio = 1.0f;
+
+ value = (float)m_firstLine/(m_totalLine-m_displayLine);
+ if ( value < 0.0f ) value = 0.0f;
+ if ( value > 1.0f ) value = 1.0f;
+
+ step = (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()
+{
+ float pos;
+ int n;
+
+ if ( m_scroll == 0 ) return;
+
+ n = m_totalLine-m_displayLine;
+ pos = m_scroll->RetVisibleValue();
+ pos += m_scroll->RetArrowStep()/2.0f; // it's magic!
+ m_firstLine = (int)(pos*n);
+ if ( m_firstLine < 0 ) m_firstLine = 0;
+ if ( m_firstLine > n ) m_firstLine = n;
+}
+
+