2024-04-20 16:23:08 +00:00
|
|
|
/*
|
2024-06-15 18:12:48 +00:00
|
|
|
* Descent 3
|
2024-04-20 16:23:08 +00:00
|
|
|
* Copyright (C) 2024 Parallax Software
|
|
|
|
*
|
|
|
|
* 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/>.
|
|
|
|
|
2024-05-06 15:12:44 +00:00
|
|
|
--- HISTORICAL COMMENTS FOLLOW ---
|
|
|
|
|
2024-04-19 20:58:24 +00:00
|
|
|
* $Logfile: /DescentIII/Main/editor/GrListBox.cpp $
|
|
|
|
* $Revision: 1.1.1.1 $
|
|
|
|
* $Date: 2003-08-26 03:57:38 $
|
|
|
|
* $Author: kevinb $
|
|
|
|
*
|
|
|
|
* New graphical listbox
|
|
|
|
*
|
|
|
|
* $Log: not supported by cvs2svn $
|
2024-06-15 18:12:48 +00:00
|
|
|
*
|
2024-04-19 20:58:24 +00:00
|
|
|
* 8 6/10/98 1:57p Samir
|
|
|
|
* fixed some listbox problems.
|
2024-06-15 18:12:48 +00:00
|
|
|
*
|
2024-04-19 20:58:24 +00:00
|
|
|
* 7 6/10/98 12:18p Matt
|
|
|
|
* Added hack to fix bug until Samir can fix it for real.
|
2024-06-15 18:12:48 +00:00
|
|
|
*
|
2024-04-19 20:58:24 +00:00
|
|
|
* 6 2/10/98 3:16p Craig
|
|
|
|
* Samir
|
2024-06-15 18:12:48 +00:00
|
|
|
*
|
2024-04-19 20:58:24 +00:00
|
|
|
* 5 9/30/97 5:35p Samir
|
|
|
|
* Fixed hangup bug when masking out textures.
|
2024-06-15 18:12:48 +00:00
|
|
|
*
|
2024-04-19 20:58:24 +00:00
|
|
|
* 4 8/26/97 11:39a Samir
|
|
|
|
* Check editor_active to see whether editor graphics are active or not.
|
2024-06-15 18:12:48 +00:00
|
|
|
*
|
2024-04-19 20:58:24 +00:00
|
|
|
* 3 8/26/97 10:49a Samir
|
|
|
|
* Fixed some small bugs with the scroll bar.
|
2024-06-15 18:12:48 +00:00
|
|
|
*
|
2024-04-19 20:58:24 +00:00
|
|
|
* $NoKeywords: $
|
|
|
|
*/
|
|
|
|
|
|
|
|
// GrListBox.cpp : implementation file
|
|
|
|
//
|
|
|
|
|
|
|
|
#include "stdafx.h"
|
|
|
|
#include "editor.h"
|
|
|
|
#include "GrListBox.h"
|
|
|
|
|
|
|
|
#ifdef _DEBUG
|
|
|
|
#define new DEBUG_NEW
|
|
|
|
#undef THIS_FILE
|
|
|
|
static char THIS_FILE[] = __FILE__;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
// CGrListBox
|
|
|
|
|
2024-06-15 18:12:48 +00:00
|
|
|
CGrListBox::CGrListBox() {
|
|
|
|
items_max_row = 0;
|
|
|
|
items_per_row = 0;
|
|
|
|
m_ListLen = 0;
|
|
|
|
m_ListItem = 0;
|
|
|
|
m_SurfDimension = 0;
|
|
|
|
m_ItemSel = -1; // -1 because item number can be 0 and a valid item.
|
|
|
|
m_HitX = 0;
|
|
|
|
m_HitY = 0;
|
|
|
|
m_CheckHit = false;
|
|
|
|
m_IsItemSelInBox = false;
|
2024-04-19 20:58:24 +00:00
|
|
|
}
|
|
|
|
|
2024-06-15 18:12:48 +00:00
|
|
|
CGrListBox::~CGrListBox() {}
|
2024-04-19 20:58:24 +00:00
|
|
|
|
2024-06-15 18:12:48 +00:00
|
|
|
BOOL CGrListBox::Create(CWnd *parent_wnd, int id, const RECT &rect, int surf_dim, bool selbox) {
|
|
|
|
m_SurfDimension = surf_dim;
|
|
|
|
m_SelectionBox = selbox;
|
2024-04-19 20:58:24 +00:00
|
|
|
|
2024-06-15 18:12:48 +00:00
|
|
|
return CWnd::Create(NULL, "GrListBox", WS_CHILD | WS_VISIBLE | WS_VSCROLL, rect, parent_wnd, id);
|
2024-04-19 20:58:24 +00:00
|
|
|
}
|
|
|
|
|
2024-06-15 18:12:48 +00:00
|
|
|
void CGrListBox::SelectItem(int item) {
|
|
|
|
// don't do a damn thing if the item selected equals the requested selected item
|
|
|
|
if (item != m_ItemSel) {
|
|
|
|
m_ItemSel = item;
|
|
|
|
OnItemSelected(item);
|
|
|
|
ListBoxProc(false); // update list box data but don't draw yet.
|
|
|
|
|
|
|
|
// scroll window until item wanted is in view.
|
|
|
|
if (m_IsItemSelInBox == false) {
|
|
|
|
// SAMIR: fix this!!
|
|
|
|
int count = 0;
|
|
|
|
|
|
|
|
while (m_ListItem < m_ItemSel && (++count < 100))
|
|
|
|
if (RowDown(1, false))
|
|
|
|
break;
|
|
|
|
|
|
|
|
while (m_ListItem > m_ItemSel && (++count < 100))
|
|
|
|
if (RowUp(1, false))
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
CWnd::Invalidate();
|
|
|
|
}
|
2024-04-19 20:58:24 +00:00
|
|
|
}
|
|
|
|
|
2024-06-15 18:12:48 +00:00
|
|
|
void CGrListBox::SetItemFirst(int item) { m_ListItem = item; }
|
2024-04-19 20:58:24 +00:00
|
|
|
|
2024-06-15 18:12:48 +00:00
|
|
|
int CGrListBox::GetItemFirst() const { return m_ListItem; }
|
2024-04-19 20:58:24 +00:00
|
|
|
|
|
|
|
BEGIN_MESSAGE_MAP(CGrListBox, CWnd)
|
2024-06-15 18:12:48 +00:00
|
|
|
//{{AFX_MSG_MAP(CGrListBox)
|
|
|
|
ON_WM_LBUTTONDOWN()
|
|
|
|
ON_WM_PAINT()
|
|
|
|
ON_WM_VSCROLL()
|
|
|
|
//}}AFX_MSG_MAP
|
2024-04-19 20:58:24 +00:00
|
|
|
END_MESSAGE_MAP()
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
// CGrListBox message handlers
|
|
|
|
|
2024-06-15 18:12:48 +00:00
|
|
|
void CGrListBox::OnPaint() {
|
|
|
|
CPaintDC dc(this); // device context for painting
|
|
|
|
|
|
|
|
ListBoxProc(true);
|
2024-04-19 20:58:24 +00:00
|
|
|
}
|
|
|
|
|
2024-06-15 18:12:48 +00:00
|
|
|
void CGrListBox::OnLButtonDown(UINT nFlags, CPoint point) {
|
|
|
|
int old_sel;
|
2024-04-19 20:58:24 +00:00
|
|
|
|
2024-06-15 18:12:48 +00:00
|
|
|
m_CheckHit = true;
|
|
|
|
m_HitX = point.x;
|
|
|
|
m_HitY = point.y;
|
2024-04-19 20:58:24 +00:00
|
|
|
|
2024-06-15 18:12:48 +00:00
|
|
|
// should we have to redraw box if we haven't changed a selection?
|
|
|
|
old_sel = m_ItemSel;
|
|
|
|
ListBoxProc(false);
|
|
|
|
if (old_sel != m_ItemSel)
|
|
|
|
CWnd::Invalidate(FALSE);
|
2024-04-19 20:58:24 +00:00
|
|
|
|
2024-06-15 18:12:48 +00:00
|
|
|
CWnd::OnLButtonDown(nFlags, point);
|
2024-04-19 20:58:24 +00:00
|
|
|
}
|
|
|
|
|
2024-06-15 18:12:48 +00:00
|
|
|
void CGrListBox::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar *pScrollBar) {
|
|
|
|
|
|
|
|
SCROLLINFO si;
|
|
|
|
int cur_pos, new_pos;
|
|
|
|
|
|
|
|
GetScrollInfo(SB_VERT, &si, SIF_ALL);
|
|
|
|
cur_pos = m_ScrollPos;
|
|
|
|
|
|
|
|
switch (nSBCode) {
|
|
|
|
case SB_LINEDOWN:
|
|
|
|
new_pos = cur_pos + 1;
|
|
|
|
break;
|
|
|
|
case SB_LINEUP:
|
|
|
|
new_pos = cur_pos - 1;
|
|
|
|
break;
|
|
|
|
case SB_THUMBPOSITION:
|
|
|
|
new_pos = nPos;
|
|
|
|
break;
|
|
|
|
case SB_THUMBTRACK:
|
|
|
|
new_pos = nPos;
|
|
|
|
break;
|
|
|
|
case SB_PAGEDOWN:
|
|
|
|
new_pos = cur_pos + si.nPage;
|
|
|
|
break;
|
|
|
|
case SB_PAGEUP:
|
|
|
|
new_pos = cur_pos - si.nPage;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
new_pos = cur_pos;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (new_pos < 0)
|
|
|
|
new_pos = 0;
|
|
|
|
if (new_pos > (int)(si.nMax - si.nPage + 1))
|
|
|
|
new_pos = (int)(si.nMax - si.nPage + 1);
|
|
|
|
// if (new_pos == 0) RowUp((cur_pos-new_pos)+1); // list up until start of list. prevents missing items
|
|
|
|
if (new_pos != cur_pos) {
|
|
|
|
// ok, new_pos will be an index into the listbox, NOT the texture list.
|
|
|
|
// so we will get the number of texture rows we went up or down and change
|
|
|
|
// tex_start accordingly.
|
|
|
|
SCROLLINFO si;
|
|
|
|
|
|
|
|
// mprintf(0, "scroll new_pos = %d. original_pos = %d\n", new_pos, cur_pos);
|
|
|
|
if (new_pos < cur_pos)
|
|
|
|
RowUp(cur_pos - new_pos);
|
|
|
|
if (new_pos > cur_pos)
|
|
|
|
RowDown(new_pos - cur_pos);
|
|
|
|
|
|
|
|
cur_pos = new_pos;
|
|
|
|
|
|
|
|
si.cbSize = sizeof(si);
|
|
|
|
si.fMask = SIF_POS;
|
|
|
|
si.nPos = m_ScrollPos = cur_pos;
|
|
|
|
CWnd::SetScrollInfo(SB_VERT, &si);
|
|
|
|
}
|
|
|
|
|
|
|
|
CWnd::OnVScroll(nSBCode, nPos, pScrollBar);
|
2024-04-19 20:58:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
// internal functions
|
|
|
|
|
|
|
|
// these functions move the list pointer (m_ListItem) up or down a few rows.
|
2024-06-15 18:12:48 +00:00
|
|
|
bool CGrListBox::RowUp(int rows, bool draw) {
|
|
|
|
int old = m_ListItem;
|
|
|
|
int done = 0, count = 0;
|
|
|
|
bool retval = false;
|
|
|
|
|
|
|
|
while ((count < (items_per_row * rows)) && !done) {
|
|
|
|
int olditem;
|
|
|
|
|
|
|
|
if (m_ListItem == m_ItemSel)
|
|
|
|
retval = true;
|
|
|
|
|
|
|
|
olditem = m_ListItem;
|
|
|
|
m_ListItem = ListPrevItem(m_ListItem);
|
|
|
|
// mprintf(0, "m_ListItem = %d\n", m_ListItem);
|
|
|
|
if (m_ListItem > olditem) {
|
|
|
|
m_ListItem = olditem;
|
|
|
|
done = 1;
|
|
|
|
// mprintf(0, "m_ListItem = %d\n", m_ListItem);
|
|
|
|
} else if (old <= m_ListItem) {
|
|
|
|
m_ListItem = old;
|
|
|
|
done = 1;
|
|
|
|
} else
|
|
|
|
count++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (draw)
|
|
|
|
CWnd::Invalidate();
|
|
|
|
|
|
|
|
return retval;
|
2024-04-19 20:58:24 +00:00
|
|
|
}
|
|
|
|
|
2024-06-15 18:12:48 +00:00
|
|
|
bool CGrListBox::RowDown(int rows, bool draw) {
|
|
|
|
int old = m_ListItem;
|
|
|
|
int done = 0, count = 0;
|
|
|
|
bool retval = false;
|
2024-04-19 20:58:24 +00:00
|
|
|
|
2024-06-15 18:12:48 +00:00
|
|
|
while ((count < (items_per_row * rows)) && !done) {
|
|
|
|
if (m_ListItem == m_ItemSel)
|
|
|
|
retval = true;
|
2024-04-19 20:58:24 +00:00
|
|
|
|
2024-06-15 18:12:48 +00:00
|
|
|
m_ListItem = ListNextItem(m_ListItem);
|
2024-04-19 20:58:24 +00:00
|
|
|
|
2024-06-15 18:12:48 +00:00
|
|
|
if (old >= m_ListItem) {
|
|
|
|
m_ListItem = old;
|
|
|
|
done = 1;
|
|
|
|
} else
|
|
|
|
count++;
|
|
|
|
}
|
2024-04-19 20:58:24 +00:00
|
|
|
|
2024-06-15 18:12:48 +00:00
|
|
|
if (draw)
|
|
|
|
CWnd::Invalidate();
|
2024-04-19 20:58:24 +00:00
|
|
|
|
2024-06-15 18:12:48 +00:00
|
|
|
return retval;
|
2024-04-19 20:58:24 +00:00
|
|
|
}
|
|
|
|
|
2024-06-15 18:12:48 +00:00
|
|
|
int CGrListBox::CalcRowOfItem(int item) {
|
|
|
|
int curitem = 0, oldcuritem = 0;
|
|
|
|
int column = 0;
|
|
|
|
int row = 0;
|
|
|
|
|
|
|
|
do {
|
|
|
|
curitem = ListNextItem(curitem);
|
|
|
|
column++;
|
|
|
|
if (column == items_per_row) {
|
|
|
|
row++;
|
|
|
|
column = 0;
|
|
|
|
}
|
|
|
|
if (oldcuritem >= curitem)
|
|
|
|
return 0;
|
|
|
|
oldcuritem = curitem;
|
|
|
|
} while (curitem != item);
|
|
|
|
|
|
|
|
return row;
|
2024-04-19 20:58:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// draws all the items in the list, or don't draw. invoking DrawItem and uses the list management functions
|
2024-06-15 18:12:48 +00:00
|
|
|
void CGrListBox::ListBoxProc(bool do_draw) {
|
|
|
|
static bool in_listboxproc = false;
|
|
|
|
grHardwareSurface m_ItemSurf;
|
|
|
|
grHardwareSurface m_ItemSurfSel;
|
|
|
|
RECT box_rect;
|
|
|
|
int left, top, draw_x, draw_y;
|
|
|
|
int box_width, box_height;
|
|
|
|
int num_items, item;
|
|
|
|
|
|
|
|
// don't draw if editor is in background.
|
|
|
|
if (in_listboxproc)
|
|
|
|
return;
|
|
|
|
in_listboxproc = true;
|
|
|
|
if (!Editor_active)
|
|
|
|
do_draw = false;
|
|
|
|
|
|
|
|
// initialize graphic objects
|
|
|
|
CWnd::GetClientRect(&box_rect);
|
|
|
|
box_height = box_rect.bottom - box_rect.top;
|
|
|
|
box_width = box_rect.right - box_rect.left;
|
|
|
|
|
|
|
|
if (do_draw) {
|
|
|
|
Desktop_surf->attach_to_window((unsigned)CWnd::m_hWnd);
|
|
|
|
Desktop_surf->clear(0, 0, box_width, box_height);
|
|
|
|
m_ItemSurf.create(m_SurfDimension, m_SurfDimension, BPP_16);
|
|
|
|
m_ItemSurfSel.create(m_SurfDimension + 8, m_SurfDimension + 8, BPP_16);
|
|
|
|
}
|
|
|
|
|
|
|
|
// initialize list manager.
|
|
|
|
items_per_row = box_width / (m_SurfDimension + 8);
|
|
|
|
items_max_row = box_height / (m_SurfDimension + 8);
|
|
|
|
m_ListLen = this->ListEnumerate();
|
|
|
|
m_ListItem = (m_ListItem / items_per_row) * items_per_row; // align rows correctly
|
|
|
|
m_ListItem = this->ListFirstItem(m_ListItem);
|
|
|
|
|
|
|
|
// start drawing items in list box.
|
|
|
|
left = (box_width / 2) - (items_per_row * (m_SurfDimension + 8)) / 2;
|
|
|
|
top = (box_height / 2) - (items_max_row * (m_SurfDimension + 8)) / 2;
|
|
|
|
num_items = 0;
|
|
|
|
item = m_ListItem;
|
|
|
|
m_IsItemSelInBox = false; // this will turn true during the drawing loop
|
|
|
|
|
|
|
|
// drawing and item selection check all purpose loop
|
|
|
|
// if our start list function returned a -1, this means that there are no list items to draw!
|
|
|
|
// also stop if we've exceeded the number of items that can exist in the limited box of visible
|
|
|
|
// space.
|
|
|
|
while ((m_ListItem > -1) && (num_items < (items_per_row * items_max_row))) {
|
|
|
|
int previtem;
|
|
|
|
|
|
|
|
// draw at draw_x, draw_y. go to next item in list and check if we are at end of list.
|
|
|
|
draw_x = left + ((num_items % items_per_row) * (m_SurfDimension + 8));
|
|
|
|
draw_y = top + ((num_items / items_per_row) * (m_SurfDimension + 8));
|
|
|
|
|
|
|
|
previtem = item;
|
|
|
|
|
|
|
|
if (m_CheckHit)
|
|
|
|
if (m_HitX >= draw_x && m_HitX <= (draw_x + m_SurfDimension + 8) && m_HitY >= draw_y &&
|
|
|
|
m_HitY <= (draw_y + m_SurfDimension + 8)) {
|
|
|
|
m_ItemSel = item;
|
|
|
|
OnItemSelected(m_ItemSel);
|
|
|
|
m_CheckHit = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (m_ItemSel == item)
|
|
|
|
m_IsItemSelInBox = true;
|
|
|
|
|
|
|
|
if (do_draw) {
|
|
|
|
if (m_ItemSel == item) {
|
|
|
|
if (m_SelectionBox) {
|
|
|
|
grViewport vp(&m_ItemSurfSel);
|
|
|
|
vp.clear();
|
|
|
|
vp.lock();
|
|
|
|
vp.rect(GR_RGB(255, 0, 255), 0, 0, vp.width() - 1, vp.height() - 1);
|
|
|
|
vp.rect(GR_RGB(255, 0, 255), 1, 1, vp.width() - 2, vp.height() - 2);
|
|
|
|
vp.rect(GR_RGB(255, 0, 255), 2, 2, vp.width() - 3, vp.height() - 3);
|
|
|
|
vp.unlock();
|
|
|
|
Desktop_surf->blt(draw_x - 4, draw_y - 4, vp.get_parent());
|
|
|
|
this->DrawItem(draw_x, draw_y, &m_ItemSurf, item);
|
|
|
|
} else {
|
|
|
|
this->DrawItem(draw_x - 4, draw_y - 4, &m_ItemSurfSel, item);
|
|
|
|
}
|
|
|
|
} else
|
|
|
|
this->DrawItem(draw_x, draw_y, &m_ItemSurf, item);
|
|
|
|
}
|
|
|
|
|
|
|
|
item = this->ListNextItem(item);
|
|
|
|
|
|
|
|
// break if we hit end of list.
|
|
|
|
if (item <= previtem)
|
|
|
|
break;
|
|
|
|
|
|
|
|
num_items++;
|
|
|
|
}
|
|
|
|
|
|
|
|
// update the scroll bar
|
|
|
|
// free up any graphic resources initialized here.
|
|
|
|
if (do_draw) {
|
|
|
|
SCROLLINFO si;
|
|
|
|
|
|
|
|
si.cbSize = sizeof(si);
|
|
|
|
si.fMask = SIF_ALL;
|
|
|
|
si.nMin = 0;
|
|
|
|
si.nMax = (m_ListLen / items_per_row) + ((m_ListLen % items_per_row) ? 0 : -1);
|
|
|
|
si.nPos = m_ScrollPos = CalcRowOfItem(m_ListItem);
|
|
|
|
si.nPage = (si.nMax >= items_max_row) ? items_max_row : (si.nMax + 1);
|
|
|
|
CWnd::SetScrollInfo(SB_VERT, &si);
|
|
|
|
CWnd::ShowScrollBar(SB_VERT);
|
|
|
|
|
|
|
|
m_ItemSurfSel.free();
|
|
|
|
m_ItemSurf.free();
|
|
|
|
|
|
|
|
Desktop_surf->attach_to_window(NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
in_listboxproc = false;
|
2024-04-19 20:58:24 +00:00
|
|
|
}
|