Commit 1a82add6 authored by stephena's avatar stephena
Browse files

Added the ability to sort (in alphabetical order) by Name, Manufacturer

or Rarity columns in the game listview.  The currently selected sort column
is also saved, and then used when StellaX starts again.

The current width of columns is also saved, and reused when StellaX starts
again.

Still TODO is get the titlebar close button to 'hook' into the
MainDlg::Quit() method, so that it works the same way as pressing
the 'Exit' button or pressing 'Alt-F4'.  Right now, pressing the close
button in the titlebar bypasses the Quit() method, and AFAICT also
the freeing of any memory.  This bug seems to have been present in StellaX
since the beginning.


git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@304 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
parent eda90151
......@@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: SettingsWin32.cxx,v 1.8 2004-07-05 00:53:48 stephena Exp $
// $Id: SettingsWin32.cxx,v 1.9 2004-07-11 22:04:21 stephena Exp $
//============================================================================
#include <sstream>
......@@ -62,6 +62,13 @@ SettingsWin32::SettingsWin32()
#ifdef SNAPSHOT_SUPPORT
set("ssdir", ".\\");
#endif
// These settings are for the StellaX frontend
// If you don't use StellaX, the following settings are ignored
set("sortcol", "0");
set("namecolwidth", "0");
set("manufacturercolwidth", "0");
set("raritycolwidth", "0");
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
......
......@@ -2,199 +2,148 @@
// StellaX
// Jeff Miller 05/01/2000
//
#include "pch.hxx"
#include "HeaderCtrl.hxx"
CHeaderCtrl::CHeaderCtrl(
) : \
m_nSortCol(0),
m_fSortAsc(TRUE)
CHeaderCtrl::CHeaderCtrl()
: m_nSortCol(0),
m_fSortAsc(TRUE)
{
}
LRESULT CHeaderCtrl::WndProc(
HWND hWnd,
UINT msg,
WPARAM wParam,
LPARAM lParam,
BOOL& rfHandled
)
LRESULT CHeaderCtrl::WndProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, BOOL& rfHandled )
{
switch ( msg )
{
case WM_DRAWITEM:
rfHandled = TRUE;
OnDrawItem(hWnd, (UINT)wParam, (LPDRAWITEMSTRUCT)lParam);
return TRUE;
}
switch ( msg )
{
case WM_DRAWITEM:
rfHandled = TRUE;
OnDrawItem(hWnd, (UINT)wParam, (LPDRAWITEMSTRUCT)lParam);
return TRUE;
}
return 0;
return 0;
}
void CHeaderCtrl::SetSortCol(
int nCol,
BOOL bAsc
)
void CHeaderCtrl::SetSortCol( int nCol, BOOL bAsc )
{
m_nSortCol = nCol;
m_fSortAsc = bAsc;
// change this item to owner draw
m_nSortCol = nCol;
m_fSortAsc = bAsc;
HWND hwndHeader = ::GetDlgItem( *this, 0 );
HDITEM hdi;
hdi.mask = HDI_FORMAT;
Header_GetItem(hwndHeader, nCol, &hdi);
hdi.fmt |= HDF_OWNERDRAW;
Header_SetItem(hwndHeader, nCol, &hdi);
// repaint the header
::InvalidateRect(hwndHeader, NULL, TRUE);
// change this item to owner draw
HWND hwndHeader = ::GetDlgItem( *this, 0 );
HDITEM hdi;
hdi.mask = HDI_FORMAT;
Header_GetItem(hwndHeader, nCol, &hdi);
hdi.fmt |= HDF_OWNERDRAW;
Header_SetItem(hwndHeader, nCol, &hdi);
// repaint the header
InvalidateRect(hwndHeader, NULL, TRUE);
}
void CHeaderCtrl::OnDrawItem(
HWND hwnd,
UINT idCtl,
LPDRAWITEMSTRUCT lpdis
)
void CHeaderCtrl::OnDrawItem( HWND hwnd, UINT idCtl, LPDRAWITEMSTRUCT lpdis )
{
UNUSED_ALWAYS( idCtl );
UNUSED_ALWAYS( idCtl );
HDC hdc = lpdis->hDC;
RECT rcLabel;
HDC hdc = lpdis->hDC;
CopyRect( &rcLabel, &(lpdis->rcItem) );
/* save the DC */
int nSavedDC = ::SaveDC( hdc );
/* set clip region to column */
HRGN hrgn = ::CreateRectRgnIndirect( &rcLabel );
SelectObject( hdc, hrgn );
DeleteObject( hrgn );
/* draw the background */
FillRect( hdc, &rcLabel, ::GetSysColorBrush(COLOR_3DFACE) );
/* offset the label */
SIZE size;
GetTextExtentPoint32( hdc, _T(" "), 1, &size );
int nOffset = size.cx * 2;
/* get the column text and format */
TCHAR tszText[255 + 1];
HDITEM hdi;
hdi.mask = HDI_TEXT | HDI_FORMAT;
hdi.pszText = tszText;
hdi.cchTextMax = 255;
Header_GetItem( GetDlgItem(hwnd, 0), lpdis->itemID, &hdi );
/* determine format for drawing label */
UINT uFormat = DT_SINGLELINE | DT_NOPREFIX | DT_NOCLIP | DT_VCENTER | DT_END_ELLIPSIS;
/* determine justification */
if (hdi.fmt & HDF_CENTER)
uFormat |= DT_CENTER;
else if (hdi.fmt & HDF_RIGHT)
uFormat |= DT_RIGHT;
else
uFormat |= DT_LEFT;
/* adjust the rect if selected */
if (lpdis->itemState & ODS_SELECTED)
{
rcLabel.left++;
rcLabel.top += 2;
rcLabel.right++;
}
/* adjust rect for sort arrow */
if ( lpdis->itemID == m_nSortCol )
rcLabel.right -= (3 * nOffset);
RECT rcLabel;
::CopyRect( &rcLabel, &(lpdis->rcItem) );
/* save the DC */
int nSavedDC = ::SaveDC( hdc );
/* set clip region to column */
HRGN hrgn = ::CreateRectRgnIndirect( &rcLabel );
SelectObject( hdc, hrgn );
DeleteObject( hrgn );
/* draw the background */
::FillRect( hdc, &rcLabel, ::GetSysColorBrush(COLOR_3DFACE) );
/* offset the label */
SIZE size;
::GetTextExtentPoint32( hdc, _T(" "), 1, &size );
int nOffset = size.cx * 2;
/* get the column text and format */
TCHAR tszText[255 + 1];
HDITEM hdi;
hdi.mask = HDI_TEXT | HDI_FORMAT;
hdi.pszText = tszText;
hdi.cchTextMax = 255;
Header_GetItem( GetDlgItem(hwnd, 0), lpdis->itemID, &hdi );
/* determine format for drawing label */
UINT uFormat = DT_SINGLELINE | DT_NOPREFIX | DT_NOCLIP |
DT_VCENTER | DT_END_ELLIPSIS;
/* determine justification */
if (hdi.fmt & HDF_CENTER)
{
uFormat |= DT_CENTER;
}
else if (hdi.fmt & HDF_RIGHT)
{
uFormat |= DT_RIGHT;
}
else
{
uFormat |= DT_LEFT;
}
/* adjust the rect if selected */
if (lpdis->itemState & ODS_SELECTED)
{
rcLabel.left++;
rcLabel.top += 2;
rcLabel.right++;
}
/* adjust rect for sort arrow */
if ( lpdis->itemID == m_nSortCol )
{
rcLabel.right -= (3 * nOffset);
}
rcLabel.left += nOffset;
rcLabel.right -= nOffset;
/* draw label */
if ( rcLabel.left < rcLabel.right )
{
::DrawText(hdc, tszText, -1, &rcLabel, uFormat );
}
/* draw the arrow */
if ( lpdis->itemID == m_nSortCol )
{
RECT rcIcon;
HPEN hpenLight, hpenShadow, hpenOld;
rcLabel.left += nOffset;
rcLabel.right -= nOffset;
/* draw label */
if ( rcLabel.left < rcLabel.right )
DrawText(hdc, tszText, -1, &rcLabel, uFormat );
/* draw the arrow */
if ( lpdis->itemID == m_nSortCol )
{
RECT rcIcon;
HPEN hpenLight, hpenShadow, hpenOld;
::CopyRect( &rcIcon, &(lpdis->rcItem) );
CopyRect( &rcIcon, &(lpdis->rcItem) );
hpenLight = ::CreatePen( PS_SOLID, 1, GetSysColor(COLOR_3DHILIGHT) );
hpenShadow = ::CreatePen( PS_SOLID, 1, GetSysColor(COLOR_3DSHADOW) );
hpenOld = (HPEN)::SelectObject( hdc, hpenLight );
hpenLight = ::CreatePen( PS_SOLID, 1, GetSysColor(COLOR_3DHILIGHT) );
hpenShadow = ::CreatePen( PS_SOLID, 1, GetSysColor(COLOR_3DSHADOW) );
hpenOld = (HPEN)::SelectObject( hdc, hpenLight );
if (m_fSortAsc)
{
/* draw triangle pointing up */
::MoveToEx( hdc, rcIcon.right - 2 * nOffset, nOffset - 1, NULL );
::LineTo( hdc, rcIcon.right - 3 * nOffset / 2,
rcIcon.bottom - nOffset );
::LineTo( hdc, rcIcon.right - 5 * nOffset / 2 - 2,
rcIcon.bottom - nOffset );
::MoveToEx( hdc, rcIcon.right - 5 * nOffset / 2 - 1,
rcIcon.bottom - nOffset, NULL );
::SelectObject( hdc, hpenShadow );
::LineTo( hdc, rcIcon.right - 2 * nOffset, nOffset - 2 );
}
else
{
/* draw triangle pointing down */
if (m_fSortAsc)
{
/* draw triangle pointing up */
MoveToEx( hdc, rcIcon.right - 2 * nOffset, nOffset - 1, NULL );
LineTo( hdc, rcIcon.right - 3 * nOffset / 2, rcIcon.bottom - nOffset );
LineTo( hdc, rcIcon.right - 5 * nOffset / 2 - 2, rcIcon.bottom - nOffset );
MoveToEx( hdc, rcIcon.right - 5 * nOffset / 2 - 1, rcIcon.bottom - nOffset, NULL );
::MoveToEx( hdc, rcIcon.right - 3 * nOffset / 2, nOffset - 1,
NULL );
::LineTo( hdc, rcIcon.right - 2 * nOffset - 1,
rcIcon.bottom - nOffset );
::LineTo( hdc, rcIcon.right - 2 * nOffset - 1,
rcIcon.bottom - nOffset );
::MoveToEx( hdc, rcIcon.right - 2 * nOffset - 1,
rcIcon.bottom - nOffset, NULL );
SelectObject( hdc, hpenShadow );
LineTo( hdc, rcIcon.right - 2 * nOffset, nOffset - 2 );
}
else
{
/* draw triangle pointing down */
MoveToEx( hdc, rcIcon.right - 3 * nOffset / 2, nOffset - 1, NULL );
LineTo( hdc, rcIcon.right - 2 * nOffset - 1, rcIcon.bottom - nOffset );
LineTo( hdc, rcIcon.right - 2 * nOffset - 1, rcIcon.bottom - nOffset );
MoveToEx( hdc, rcIcon.right - 2 * nOffset - 1, rcIcon.bottom - nOffset, NULL );
::SelectObject( hdc, hpenShadow );
::LineTo( hdc, rcIcon.right - 5 * nOffset / 2 - 1,
nOffset - 1 );
::LineTo( hdc, rcIcon.right - 3 * nOffset / 2,
nOffset - 1 );
}
SelectObject( hdc, hpenShadow );
LineTo( hdc, rcIcon.right - 5 * nOffset / 2 - 1, nOffset - 1 );
LineTo( hdc, rcIcon.right - 3 * nOffset / 2, nOffset - 1 );
}
::SelectObject( hdc, hpenOld );
::DeleteObject( hpenShadow );
::DeleteObject( hpenLight );
}
SelectObject( hdc, hpenOld );
DeleteObject( hpenShadow );
DeleteObject( hpenLight );
}
::RestoreDC( hdc, nSavedDC );
RestoreDC( hdc, nSavedDC );
}
......@@ -4,51 +4,39 @@
//
#ifndef HDRCTL_H
#define HDRCTL_H
#pragma once
#include "Wnd.hxx"
class CHeaderCtrl : public CWnd
{
public:
public:
CHeaderCtrl();
CHeaderCtrl();
void SetSortCol(int col, BOOL fAscending);
int GetSortCol(void) const;
BOOL GetSortAsc(void) const;
void SetSortCol(int nCol, BOOL fAscending);
int GetSortCol(void) const;
BOOL GetSortAsc(void) const;
protected:
LRESULT WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam, BOOL& rfHandled);
protected:
private:
void OnDrawItem(HWND hwnd, UINT idCtl, LPDRAWITEMSTRUCT lpdis);
LRESULT WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam,
BOOL& rfHandled);
private:
void OnDrawItem(HWND hwnd, UINT idCtl, LPDRAWITEMSTRUCT lpdis);
UINT m_nSortCol;
BOOL m_fSortAsc;
CHeaderCtrl( const CHeaderCtrl& ); // no implementation
void operator=( const CHeaderCtrl& ); // no implementation
UINT m_nSortCol;
BOOL m_fSortAsc;
CHeaderCtrl( const CHeaderCtrl& ); // no implementation
void operator=( const CHeaderCtrl& ); // no implementation
};
inline int CHeaderCtrl::GetSortCol
(
void
) const
inline int CHeaderCtrl::GetSortCol( void ) const
{
return m_nSortCol;
return m_nSortCol;
}
inline BOOL CHeaderCtrl::GetSortAsc
(
void
) const
inline BOOL CHeaderCtrl::GetSortAsc( void ) const
{
return m_fSortAsc;
return m_fSortAsc;
}
#endif
......@@ -14,7 +14,7 @@
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: MainDlg.cxx,v 1.4 2004-07-10 22:25:58 stephena Exp $
// $Id: MainDlg.cxx,v 1.5 2004-07-11 22:04:22 stephena Exp $
//============================================================================
#include "pch.hxx"
......@@ -35,14 +35,21 @@
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
MainDlg::MainDlg( CGlobalData& rGlobalData, HINSTANCE hInstance )
: myGlobalData(rGlobalData),
m_hInstance(hInstance)
myHInstance(hInstance)
{
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
MainDlg::~MainDlg( void )
{
// Just to be safe, make sure we don't have a memory leak
ListView_Clear();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
int MainDlg::DoModal( HWND hwndParent )
{
return DialogBoxParam( m_hInstance,
return DialogBoxParam( myHInstance,
MAKEINTRESOURCE(IDD),
hwndParent,
StaticDialogFunc,
......@@ -138,7 +145,7 @@ MainDlg::DialogFunc( UINT uMsg, WPARAM wParam, LPARAM lParam )
case WM_SYSCOMMAND:
// Allow Alt-F4 to close the window
if ( wParam == SC_CLOSE )
::EndDialog( myHwnd, IDCANCEL );
Quit(myHwnd);
break;
}
......@@ -154,7 +161,7 @@ BOOL MainDlg::OnInitDialog( void )
HWND hwnd = *this;
// Set dialog icon
HICON hicon = ::LoadIcon(m_hInstance, MAKEINTRESOURCE(IDI_APP));
HICON hicon = ::LoadIcon(myHInstance, MAKEINTRESOURCE(IDI_APP));
::SendMessage( hwnd, WM_SETICON, ICON_BIG, (LPARAM)hicon );
::SendMessage( hwnd, WM_SETICON, ICON_SMALL, (LPARAM)hicon );
......@@ -199,16 +206,24 @@ BOOL MainDlg::OnInitDialog( void )
int columnHeader[] = { IDS_NAME, IDS_MANUFACTURER, IDS_RARITY };
// Set the column widths
LONG lTotalWidth = rc.right-rc.left - GetSystemMetrics(SM_CXVSCROLL);
int columnWidth[3];
columnWidth[0] = (int) (0.58 * lTotalWidth);
columnWidth[1] = (int) (0.25 * lTotalWidth);
columnWidth[2] = lTotalWidth - columnWidth[0] - columnWidth[1];
columnWidth[0] = myGlobalData.settings().getInt("namecolwidth");
columnWidth[1] = myGlobalData.settings().getInt("manufacturercolwidth");
columnWidth[2] = myGlobalData.settings().getInt("raritycolwidth");
// Make sure there are sane values for the column widths
if (columnWidth[0] <= 0 || columnWidth[1] <= 0 || columnWidth[2] <= 0)
{
LONG lTotalWidth = rc.right-rc.left - GetSystemMetrics(SM_CXVSCROLL);
columnWidth[0] = (int) (0.58 * lTotalWidth);
columnWidth[1] = (int) (0.25 * lTotalWidth);
columnWidth[2] = lTotalWidth - columnWidth[0] - columnWidth[1];
}
// Set up the column headings
for (int i = 0; i < sizeof(columnHeader)/sizeof(int); ++i)
for (int i = 0; i < 3; ++i)
{
LoadString( m_hInstance, columnHeader[i], psz, nMaxString );
LoadString( myHInstance, columnHeader[i], psz, nMaxString );
LV_COLUMN lvc;
lvc.mask = LVCF_FMT | LVCF_TEXT | LVCF_WIDTH;
......@@ -222,7 +237,7 @@ BOOL MainDlg::OnInitDialog( void )
UpdateRomList();
// Set default button
::SendMessage( hwnd, DM_SETDEFID, IDC_PLAY, 0 );
SendMessage( hwnd, DM_SETDEFID, IDC_PLAY, 0 );
// return FALSE if SetFocus is called
return TRUE;
......@@ -247,7 +262,7 @@ BOOL MainDlg::OnCommand( int id, HWND hwndCtl, UINT codeNotify )
ASSERT( nItem != -1 );
if ( nItem == -1 )
{
MessageBox( m_hInstance, hwnd, IDS_NO_ITEM_SELECTED );
MessageBox( myHInstance, hwnd, IDS_NO_ITEM_SELECTED );
return TRUE;
}
......@@ -262,8 +277,7 @@ BOOL MainDlg::OnCommand( int id, HWND hwndCtl, UINT codeNotify )
break; // case IDC_PLAY
case IDC_EXIT:
ListView_Clear();
EndDialog( hwnd, IDCANCEL );
Quit(hwnd);
return TRUE;
break; // case IDC_EXIT
......@@ -295,7 +309,7 @@ BOOL MainDlg::OnCommand( int id, HWND hwndCtl, UINT codeNotify )
case IDC_RELOAD:
{
LoadRomListFromDisk();
ListView_SortByColumn( myHwndList, myGlobalData.settings().getInt("sortcol") );
return TRUE;
break; // case IDC_RELOAD
}
......@@ -315,13 +329,13 @@ BOOL MainDlg::OnNotify( int idCtrl, LPNMHDR pnmh )
OnItemChanged( (LPNMLISTVIEW)pnmh );
return TRUE;
// case LVN_COLUMNCLICK:
// OnColumnClick( (LPNMLISTVIEW)pnmh );
// return TRUE;
case LVN_COLUMNCLICK:
OnColumnClick( (LPNMLISTVIEW)pnmh );
return TRUE;
case NM_DBLCLK:
// send out an ok click to play
::SendDlgItemMessage( *this, IDC_PLAY, BM_CLICK, 0, 0 );
SendDlgItemMessage( *this, IDC_PLAY, BM_CLICK, 0, 0 );
return TRUE;
}
......@@ -356,6 +370,12 @@ void MainDlg::OnItemChanged( LPNMLISTVIEW pnmv )
EnableWindow( GetDlgItem( hwnd, IDC_PLAY ), TRUE );
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void MainDlg::OnColumnClick( LPNMLISTVIEW pnmv )
{
ListView_SortByColumn( pnmv->hdr.hwndFrom, pnmv->iSubItem );
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
static void ScreenToClient( HWND hwnd, LPRECT lpRect )
{
......@@ -393,7 +413,7 @@ BOOL MainDlg::OnEraseBkgnd( HDC hdc )
HDC hdcMem = CreateCompatibleDC(hdc);
HBITMAP hbmpTile = LoadBitmap( m_hInstance, MAKEINTRESOURCE(IDB_TILE) );
HBITMAP hbmpTile = LoadBitmap( myHInstance, MAKEINTRESOURCE(IDB_TILE) );
BITMAP bm;
GetObject(hbmpTile, sizeof(bm), &bm);
......@@ -436,6 +456,31 @@ HBRUSH MainDlg::OnCtlColorStatic( HDC hdcStatic, HWND hwndStatic )
return (HBRUSH)GetStockObject(NULL_BRUSH);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void MainDlg::Quit( HWND hwnd )
{
// OK, reload the settings to make sure we have the most current ones
myGlobalData.settings().loadConfig();
// Save the current sort column
int sortcol = myHeader.GetSortCol();
myGlobalData.settings().setInt("sortcol", sortcol);
// Save the column widths
myGlobalData.settings().setInt("namecolwidth",
ListView_GetColWidth( hwnd, 0 ));
myGlobalData.settings().setInt("manufacturercolwidth",
ListView_GetColWidth( hwnd, 1 ));
myGlobalData.settings().setInt("raritycolwidth",
ListView_GetColWidth( hwnd, 2 ));
// Now, save the settings
myGlobalData.settings().saveConfig();
ListView_Clear();
EndDialog( hwnd, IDCANCEL );
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void MainDlg::UpdateRomList( void )
{
......@@ -447,22 +492,13 @@ void MainDlg::UpdateRomList( void )
// if items added, select first item and enable play button
int nCount = ListView_GetItemCount( myHwndList );
if (nCount != 0)
{
myHeader.SetSortCol( 0, TRUE );
// ListView_SortItems( myHwndList, ListViewCompareFunc, (LPARAM)this );
ListView_SetItemState( myHwndList, 0, LVIS_SELECTED | LVIS_FOCUSED,
LVIS_SELECTED | LVIS_FOCUSED );
}
else
{
::EnableWindow(::GetDlgItem( *this, IDC_PLAY),