mirror of https://github.com/stella-emu/stella.git
Added new rendering modes to FrameBufferSoft, which don't use dirty
rectangle merging. This makes the 'dirtyrects' option more relevant, since now if it's turned off, dirty rectangles are not merged, and the screen is updated with SDL_Flip() instead of SDL_UpdateRects(). This new functionality is very similar to how z26 works, but experiments on my Linux system show it to be twice as fast on average :) Dirty rectangle merging now defaults to off. I'm leaving it in, since it benefits people in some cases. Basically, non-dirty-rect support is optimal when many things are changing onscreen at once, at the cost of more constant and generally slightly higher CPU usage. Dirty-rect support is optimal at larger resolutions, where it's usually at least twice as fast as without, but is suboptimal at larger resolutions when lots of stuff is changing. At some point in the future, maybe Stella itself can automatically switch modes depending on which is faster at any point in time. Added "[..]" previous directory functionality to BrowserWidget, the same as already in the LauncherDialog. Thanks for Alex and Lou for the reminder. git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@1197 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
This commit is contained in:
parent
de4ee80062
commit
6608b99d8c
|
@ -273,6 +273,9 @@ paddle mode for those ROMs that don't use paddle zero by default.</li>
|
|||
the ROM properties to the internal defaults, deleting that ROMs properties
|
||||
from the external properties file.</li>
|
||||
|
||||
<li>Fixed bug whereby modified ROM properties weren't being reloaded when
|
||||
restarting a ROM.</li>
|
||||
|
||||
<li>Made 'phosphor' and 'phosphor blend' a ROM property, meaning it can be
|
||||
set per-ROM.</li>
|
||||
|
||||
|
|
|
@ -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: FrameBufferSoft.cxx,v 1.61 2006-12-08 16:48:56 stephena Exp $
|
||||
// $Id: FrameBufferSoft.cxx,v 1.62 2006-12-10 17:04:33 stephena Exp $
|
||||
//============================================================================
|
||||
|
||||
#include <SDL.h>
|
||||
|
@ -31,7 +31,8 @@
|
|||
FrameBufferSoft::FrameBufferSoft(OSystem* osystem)
|
||||
: FrameBuffer(osystem),
|
||||
myZoomLevel(1),
|
||||
myRenderType(kSoftZoom),
|
||||
myRenderType(kDirtyRect),
|
||||
myUseDirtyRects(true),
|
||||
myRectList(NULL),
|
||||
myOverlayRectList(NULL)
|
||||
{
|
||||
|
@ -114,18 +115,9 @@ bool FrameBufferSoft::createScreen()
|
|||
cerr << "ERROR: Unable to open SDL window: " << SDL_GetError() << endl;
|
||||
return false;
|
||||
}
|
||||
switch(myScreen->format->BitsPerPixel)
|
||||
{
|
||||
case 16:
|
||||
myPitch = myScreen->pitch/2;
|
||||
break;
|
||||
case 24:
|
||||
myPitch = myScreen->pitch;
|
||||
break;
|
||||
case 32:
|
||||
myPitch = myScreen->pitch/4;
|
||||
break;
|
||||
}
|
||||
|
||||
// Make sure drawMediaSource() knows which renderer to use
|
||||
stateChanged(myOSystem->eventHandler().state());
|
||||
|
||||
// Erase old rects, since they've probably been scaled for
|
||||
// a different sized screen
|
||||
|
@ -147,9 +139,9 @@ void FrameBufferSoft::drawMediaSource()
|
|||
uInt32 width = mediasrc.width();
|
||||
uInt32 height = mediasrc.height();
|
||||
|
||||
switch((int)myRenderType) // use switch/case, since we'll eventually have filters
|
||||
switch(myRenderType) // use switch/case, since we'll eventually have filters
|
||||
{
|
||||
case kSoftZoom:
|
||||
case kDirtyRect:
|
||||
{
|
||||
struct Rectangle
|
||||
{
|
||||
|
@ -289,7 +281,94 @@ void FrameBufferSoft::drawMediaSource()
|
|||
myRectList->add(&temp);
|
||||
SDL_FillRect(myScreen, &temp, myDefPalette[active.color]);
|
||||
}
|
||||
break; // case 0
|
||||
break; // kDirtyRect
|
||||
}
|
||||
|
||||
case kSoftZoom_16:
|
||||
{
|
||||
SDL_Rect temp;
|
||||
temp.x = temp.y = temp.w = temp.h = 0;
|
||||
myRectList->add(&temp);
|
||||
|
||||
uInt16* buffer = (uInt16*)myScreen->pixels;
|
||||
uInt32 bufofsY = 0;
|
||||
uInt32 screenofsY = 0;
|
||||
for(uInt32 y = 0; y < height; ++y)
|
||||
{
|
||||
uInt32 ystride = myZoomLevel;
|
||||
while(ystride--)
|
||||
{
|
||||
uInt32 pos = screenofsY;
|
||||
for(uInt32 x = 0; x < width; ++x)
|
||||
{
|
||||
const uInt32 bufofs = bufofsY + x;
|
||||
uInt32 xstride = myZoomLevel;
|
||||
|
||||
uInt8 v = currentFrame[bufofs];
|
||||
uInt8 w = previousFrame[bufofs];
|
||||
|
||||
if(v != w || theRedrawTIAIndicator)
|
||||
{
|
||||
while(xstride--)
|
||||
{
|
||||
buffer[pos++] = (uInt16) myDefPalette[v];
|
||||
buffer[pos++] = (uInt16) myDefPalette[v];
|
||||
}
|
||||
}
|
||||
else
|
||||
pos += xstride + xstride;
|
||||
}
|
||||
screenofsY += myPitch;
|
||||
}
|
||||
bufofsY += width;
|
||||
}
|
||||
break; // kSoftZoom_16
|
||||
}
|
||||
|
||||
case kSoftZoom_24:
|
||||
{
|
||||
break; // kSoftZoom_24
|
||||
}
|
||||
|
||||
case kSoftZoom_32:
|
||||
{
|
||||
SDL_Rect temp;
|
||||
temp.x = temp.y = temp.w = temp.h = 0;
|
||||
myRectList->add(&temp);
|
||||
|
||||
uInt32* buffer = (uInt32*)myScreen->pixels;
|
||||
uInt32 bufofsY = 0;
|
||||
uInt32 screenofsY = 0;
|
||||
for(uInt32 y = 0; y < height; ++y)
|
||||
{
|
||||
uInt32 ystride = myZoomLevel;
|
||||
while(ystride--)
|
||||
{
|
||||
uInt32 pos = screenofsY;
|
||||
for(uInt32 x = 0; x < width; ++x)
|
||||
{
|
||||
const uInt32 bufofs = bufofsY + x;
|
||||
uInt32 xstride = myZoomLevel;
|
||||
|
||||
uInt8 v = currentFrame[bufofs];
|
||||
uInt8 w = previousFrame[bufofs];
|
||||
|
||||
if(v != w || theRedrawTIAIndicator)
|
||||
{
|
||||
while(xstride--)
|
||||
{
|
||||
buffer[pos++] = (uInt32) myDefPalette[v];
|
||||
buffer[pos++] = (uInt32) myDefPalette[v];
|
||||
}
|
||||
}
|
||||
else
|
||||
pos += xstride + xstride;
|
||||
}
|
||||
screenofsY += myPitch;
|
||||
}
|
||||
bufofsY += width;
|
||||
}
|
||||
break; // kSoftZoom_32
|
||||
}
|
||||
|
||||
case kPhosphor_16:
|
||||
|
@ -304,13 +383,13 @@ void FrameBufferSoft::drawMediaSource()
|
|||
uInt16* buffer = (uInt16*)myScreen->pixels;
|
||||
uInt32 bufofsY = 0;
|
||||
uInt32 screenofsY = 0;
|
||||
for(uInt32 y = 0; y < height; ++y )
|
||||
for(uInt32 y = 0; y < height; ++y)
|
||||
{
|
||||
uInt32 ystride = myZoomLevel;
|
||||
while(ystride--)
|
||||
{
|
||||
uInt32 pos = screenofsY;
|
||||
for(uInt32 x = 0; x < width; ++x )
|
||||
for(uInt32 x = 0; x < width; ++x)
|
||||
{
|
||||
const uInt32 bufofs = bufofsY + x;
|
||||
uInt32 xstride = myZoomLevel;
|
||||
|
@ -343,13 +422,13 @@ void FrameBufferSoft::drawMediaSource()
|
|||
uInt8* buffer = (uInt8*)myScreen->pixels;
|
||||
uInt32 bufofsY = 0;
|
||||
uInt32 screenofsY = 0;
|
||||
for(uInt32 y = 0; y < height; ++y )
|
||||
for(uInt32 y = 0; y < height; ++y)
|
||||
{
|
||||
uInt32 ystride = myZoomLevel;
|
||||
while(ystride--)
|
||||
{
|
||||
uInt32 pos = screenofsY;
|
||||
for(uInt32 x = 0; x < width; ++x )
|
||||
for(uInt32 x = 0; x < width; ++x)
|
||||
{
|
||||
const uInt32 bufofs = bufofsY + x;
|
||||
uInt32 xstride = myZoomLevel;
|
||||
|
@ -397,13 +476,13 @@ void FrameBufferSoft::drawMediaSource()
|
|||
uInt32* buffer = (uInt32*)myScreen->pixels;
|
||||
uInt32 bufofsY = 0;
|
||||
uInt32 screenofsY = 0;
|
||||
for(uInt32 y = 0; y < height; ++y )
|
||||
for(uInt32 y = 0; y < height; ++y)
|
||||
{
|
||||
uInt32 ystride = myZoomLevel;
|
||||
while(ystride--)
|
||||
{
|
||||
uInt32 pos = screenofsY;
|
||||
for(uInt32 x = 0; x < width; ++x )
|
||||
for(uInt32 x = 0; x < width; ++x)
|
||||
{
|
||||
const uInt32 bufofs = bufofsY + x;
|
||||
uInt32 xstride = myZoomLevel;
|
||||
|
@ -646,29 +725,7 @@ void FrameBufferSoft::enablePhosphor(bool enable, int blend)
|
|||
myUsePhosphor = enable;
|
||||
myPhosphorBlend = blend;
|
||||
|
||||
if(myUsePhosphor)
|
||||
{
|
||||
switch(myScreen->format->BitsPerPixel)
|
||||
{
|
||||
case 16:
|
||||
myPitch = myScreen->pitch/2;
|
||||
myRenderType = kPhosphor_16;
|
||||
break;
|
||||
case 24:
|
||||
myPitch = myScreen->pitch;
|
||||
myRenderType = kPhosphor_24;
|
||||
break;
|
||||
case 32:
|
||||
myPitch = myScreen->pitch/4;
|
||||
myRenderType = kPhosphor_32;
|
||||
break;
|
||||
default:
|
||||
myRenderType = kSoftZoom; // What else should we do here?
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
myRenderType = kSoftZoom;
|
||||
stateChanged(myOSystem->eventHandler().state());
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -680,3 +737,60 @@ void FrameBufferSoft::cls()
|
|||
SDL_UpdateRect(myScreen, 0, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void FrameBufferSoft::stateChanged(EventHandler::State state)
|
||||
{
|
||||
if(!myScreen)
|
||||
return;
|
||||
|
||||
// When in a UI mode, always use dirty rects
|
||||
// Otherwise, check the 'dirtyrects' setting
|
||||
bool emulation = state == EventHandler::S_EMULATE;
|
||||
if(emulation)
|
||||
myUseDirtyRects = myOSystem->settings().getBool("dirtyrects");
|
||||
else
|
||||
myUseDirtyRects = true;
|
||||
|
||||
// Make sure drawMediaSource() knows which renderer to use
|
||||
// Testing for dirty rects takes priority over phosphor mode,
|
||||
// since phosphor mode only exists while emulating a ROM
|
||||
switch(myScreen->format->BitsPerPixel)
|
||||
{
|
||||
case 16:
|
||||
myPitch = myScreen->pitch/2;
|
||||
if(myUsePhosphor && emulation)
|
||||
myRenderType = kPhosphor_16;
|
||||
else if(myUseDirtyRects)
|
||||
myRenderType = kDirtyRect;
|
||||
else
|
||||
myRenderType = kSoftZoom_16;
|
||||
break;
|
||||
case 24:
|
||||
myPitch = myScreen->pitch;
|
||||
if(myUsePhosphor && emulation)
|
||||
myRenderType = kPhosphor_24;
|
||||
else if(myUseDirtyRects)
|
||||
myRenderType = kDirtyRect;
|
||||
else
|
||||
myRenderType = kSoftZoom_24;
|
||||
break;
|
||||
case 32:
|
||||
myPitch = myScreen->pitch/4;
|
||||
if(myUsePhosphor && emulation)
|
||||
myRenderType = kPhosphor_32;
|
||||
else if(myUseDirtyRects)
|
||||
myRenderType = kDirtyRect;
|
||||
else
|
||||
myRenderType = kSoftZoom_32;
|
||||
break;
|
||||
default:
|
||||
myRenderType = kDirtyRect; // What else should we do here?
|
||||
break;
|
||||
}
|
||||
|
||||
// Have the changes take effect
|
||||
myOSystem->eventHandler().refreshDisplay();
|
||||
|
||||
//cerr << "Render type: " << myRenderType << endl;
|
||||
}
|
||||
|
|
|
@ -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: FrameBufferSoft.hxx,v 1.39 2006-12-08 16:48:56 stephena Exp $
|
||||
// $Id: FrameBufferSoft.hxx,v 1.40 2006-12-10 17:04:34 stephena Exp $
|
||||
//============================================================================
|
||||
|
||||
#ifndef FRAMEBUFFER_SOFT_HXX
|
||||
|
@ -33,7 +33,7 @@ class RectList;
|
|||
This class implements an SDL software framebuffer.
|
||||
|
||||
@author Stephen Anthony
|
||||
@version $Id: FrameBufferSoft.hxx,v 1.39 2006-12-08 16:48:56 stephena Exp $
|
||||
@version $Id: FrameBufferSoft.hxx,v 1.40 2006-12-10 17:04:34 stephena Exp $
|
||||
*/
|
||||
class FrameBufferSoft : public FrameBuffer
|
||||
{
|
||||
|
@ -206,18 +206,29 @@ class FrameBufferSoft : public FrameBuffer
|
|||
*/
|
||||
virtual void cls();
|
||||
|
||||
/**
|
||||
Informs the Framebuffer of a change in EventHandler state.
|
||||
*/
|
||||
virtual void stateChanged(EventHandler::State state);
|
||||
|
||||
private:
|
||||
int myZoomLevel;
|
||||
int myPitch;
|
||||
|
||||
enum RenderType {
|
||||
kSoftZoom,
|
||||
kDirtyRect,
|
||||
kSoftZoom_16,
|
||||
kSoftZoom_24,
|
||||
kSoftZoom_32,
|
||||
kPhosphor_16,
|
||||
kPhosphor_24,
|
||||
kPhosphor_32
|
||||
};
|
||||
RenderType myRenderType;
|
||||
|
||||
// Use dirty updates (SDL_UpdateRects instead of SDL_UpdateRect)
|
||||
bool myUseDirtyRects;
|
||||
|
||||
// Used in the dirty update of the SDL surface
|
||||
RectList* myRectList;
|
||||
|
||||
|
|
|
@ -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: EventHandler.cxx,v 1.182 2006-12-09 00:25:19 stephena Exp $
|
||||
// $Id: EventHandler.cxx,v 1.183 2006-12-10 17:04:34 stephena Exp $
|
||||
//============================================================================
|
||||
|
||||
#include <sstream>
|
||||
|
@ -195,6 +195,7 @@ void EventHandler::refreshDisplay(bool forceUpdate)
|
|||
switch(myState)
|
||||
{
|
||||
case S_EMULATE:
|
||||
myOSystem->frameBuffer().cls();
|
||||
myOSystem->frameBuffer().refresh();
|
||||
break;
|
||||
|
||||
|
@ -2330,8 +2331,10 @@ void EventHandler::setEventState(State state)
|
|||
break;
|
||||
}
|
||||
|
||||
// Inform the OSystem about the new state
|
||||
// Inform various subsystems about the new state
|
||||
myOSystem->stateChanged(myState);
|
||||
if(&myOSystem->frameBuffer())
|
||||
myOSystem->frameBuffer().stateChanged(myState);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
|
|
@ -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: FrameBuffer.cxx,v 1.105 2006-12-08 16:49:25 stephena Exp $
|
||||
// $Id: FrameBuffer.cxx,v 1.106 2006-12-10 17:04:34 stephena Exp $
|
||||
//============================================================================
|
||||
|
||||
#include <sstream>
|
||||
|
@ -116,8 +116,6 @@ void FrameBuffer::initialize(const string& title, uInt32 width, uInt32 height,
|
|||
|
||||
// Erase any messages from a previous run
|
||||
myMessage.counter = 0;
|
||||
|
||||
myUseDirtyRects = myOSystem->settings().getBool("dirtyrects");
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
|
|
@ -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: FrameBuffer.hxx,v 1.77 2006-12-08 16:49:26 stephena Exp $
|
||||
// $Id: FrameBuffer.hxx,v 1.78 2006-12-10 17:04:34 stephena Exp $
|
||||
//============================================================================
|
||||
|
||||
#ifndef FRAMEBUFFER_HXX
|
||||
|
@ -24,6 +24,7 @@
|
|||
#include "bspf.hxx"
|
||||
#include "Array.hxx"
|
||||
#include "Event.hxx"
|
||||
#include "EventHandler.hxx"
|
||||
#include "MediaSrc.hxx"
|
||||
#include "Font.hxx"
|
||||
#include "GuiUtils.hxx"
|
||||
|
@ -96,7 +97,7 @@ struct Scaler {
|
|||
All GUI elements (ala ScummVM) are drawn here as well.
|
||||
|
||||
@author Stephen Anthony
|
||||
@version $Id: FrameBuffer.hxx,v 1.77 2006-12-08 16:49:26 stephena Exp $
|
||||
@version $Id: FrameBuffer.hxx,v 1.78 2006-12-10 17:04:34 stephena Exp $
|
||||
*/
|
||||
class FrameBuffer
|
||||
{
|
||||
|
@ -292,6 +293,11 @@ class FrameBuffer
|
|||
int color, TextAlignment align = kTextAlignLeft,
|
||||
int deltax = 0, bool useEllipsis = true);
|
||||
|
||||
/**
|
||||
Informs the Framebuffer of a change in EventHandler state.
|
||||
*/
|
||||
virtual void stateChanged(EventHandler::State state) { }
|
||||
|
||||
public:
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// The following methods are system-specific and must be implemented
|
||||
|
@ -485,9 +491,6 @@ class FrameBuffer
|
|||
// Indicates if the TIA area should be redrawn
|
||||
bool theRedrawTIAIndicator;
|
||||
|
||||
// Use dirty updates (SDL_UpdateRects instead of SDL_UpdateRect)
|
||||
bool myUseDirtyRects;
|
||||
|
||||
// Use phosphor effect (aka no flicker on 30Hz screens)
|
||||
bool myUsePhosphor;
|
||||
|
||||
|
|
|
@ -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: Settings.cxx,v 1.95 2006-12-09 00:25:20 stephena Exp $
|
||||
// $Id: Settings.cxx,v 1.96 2006-12-10 17:04:34 stephena Exp $
|
||||
//============================================================================
|
||||
|
||||
#include <cassert>
|
||||
|
@ -34,7 +34,7 @@ Settings::Settings(OSystem* osystem)
|
|||
|
||||
// Add options that are common to all versions of Stella
|
||||
setInternal("video", "soft");
|
||||
setInternal("dirtyrects", "true");
|
||||
setInternal("dirtyrects", "false"); // This only becomes useful at high resolutions
|
||||
|
||||
setInternal("gl_filter", "nearest");
|
||||
setInternal("gl_aspect", "2.0");
|
||||
|
|
|
@ -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: FrameBufferGP2X.cxx,v 1.10 2006-12-08 16:49:31 stephena Exp $
|
||||
// $Id: FrameBufferGP2X.cxx,v 1.11 2006-12-10 17:04:34 stephena Exp $
|
||||
//============================================================================
|
||||
|
||||
#include <SDL.h>
|
||||
|
@ -98,10 +98,10 @@ void FrameBufferGP2X::drawMediaSource()
|
|||
|
||||
if(!myUsePhosphor)
|
||||
{
|
||||
for(uInt32 y = 0; y < height; ++y )
|
||||
for(uInt32 y = 0; y < height; ++y)
|
||||
{
|
||||
uInt32 pos = screenofsY;
|
||||
for(uInt32 x = 0; x < width; ++x )
|
||||
for(uInt32 x = 0; x < width; ++x)
|
||||
{
|
||||
const uInt32 bufofs = bufofsY + x;
|
||||
uInt8 v = currentFrame[bufofs];
|
||||
|
@ -127,10 +127,10 @@ void FrameBufferGP2X::drawMediaSource()
|
|||
// so we don't care about theRedrawTIAIndicator
|
||||
myDirtyFlag = true;
|
||||
|
||||
for(uInt32 y = 0; y < height; ++y )
|
||||
for(uInt32 y = 0; y < height; ++y)
|
||||
{
|
||||
uInt32 pos = screenofsY;
|
||||
for(uInt32 x = 0; x < width; ++x )
|
||||
for(uInt32 x = 0; x < width; ++x)
|
||||
{
|
||||
const uInt32 bufofs = bufofsY + x;
|
||||
uInt8 v = currentFrame[bufofs];
|
||||
|
|
|
@ -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: BrowserDialog.cxx,v 1.22 2006-12-09 04:02:40 stephena Exp $
|
||||
// $Id: BrowserDialog.cxx,v 1.23 2006-12-10 17:04:34 stephena Exp $
|
||||
//
|
||||
// Based on code from ScummVM - Scumm Interpreter
|
||||
// Copyright (C) 2002-2004 The ScummVM project
|
||||
|
@ -26,6 +26,7 @@
|
|||
#include "FSNode.hxx"
|
||||
#include "GuiObject.hxx"
|
||||
#include "GuiUtils.hxx"
|
||||
#include "GameList.hxx"
|
||||
#include "BrowserDialog.hxx"
|
||||
|
||||
#include "bspf.hxx"
|
||||
|
@ -43,7 +44,8 @@ BrowserDialog::BrowserDialog(GuiObject* boss, const GUI::Font& font,
|
|||
: Dialog(boss->instance(), boss->parent(), x, y, w, h),
|
||||
CommandSender(boss),
|
||||
_fileList(NULL),
|
||||
_currentPath(NULL)
|
||||
_currentPath(NULL),
|
||||
_nodeList(NULL)
|
||||
{
|
||||
const int lineHeight = font.getLineHeight(),
|
||||
bwidth = font.getStringWidth("Cancel") + 20,
|
||||
|
@ -60,7 +62,7 @@ BrowserDialog::BrowserDialog(GuiObject* boss, const GUI::Font& font,
|
|||
ypos += lineHeight + 4;
|
||||
_currentPath = new StaticTextWidget(this, font, xpos, ypos,
|
||||
_w - 2 * xpos, lineHeight,
|
||||
"DUMMY", kTextAlignLeft);
|
||||
"", kTextAlignLeft);
|
||||
|
||||
// Add file list
|
||||
ypos += lineHeight;
|
||||
|
@ -99,6 +101,15 @@ BrowserDialog::BrowserDialog(GuiObject* boss, const GUI::Font& font,
|
|||
#endif
|
||||
|
||||
addFocusWidget(_fileList);
|
||||
|
||||
// Create a list of directory nodes
|
||||
_nodeList = new GameList();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
BrowserDialog::~BrowserDialog()
|
||||
{
|
||||
delete _nodeList;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -106,17 +117,65 @@ void BrowserDialog::setStartPath(const string& startpath)
|
|||
{
|
||||
// If no node has been set, or the last used one is now invalid,
|
||||
// go back to the root/default dir.
|
||||
_choice = FilesystemNode(startpath);
|
||||
_node = FilesystemNode(startpath);
|
||||
|
||||
if (_choice.isValid())
|
||||
_node = _choice;
|
||||
else if (!_node.isValid())
|
||||
if(!_node.isValid())
|
||||
_node = FilesystemNode();
|
||||
|
||||
// Alway refresh file list
|
||||
updateListing();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void BrowserDialog::updateListing()
|
||||
{
|
||||
if(!_node.isDirectory())
|
||||
return;
|
||||
|
||||
// Start with empty list
|
||||
_nodeList->clear();
|
||||
|
||||
// Update the path display
|
||||
_currentPath->setLabel(_node.path());
|
||||
|
||||
// Read in the data from the file system
|
||||
FSList content = _node.listDir();
|
||||
content.sort();
|
||||
|
||||
// Add '[..]' to indicate previous folder
|
||||
if(_node.hasParent())
|
||||
{
|
||||
const string& parent = _node.getParent().path();
|
||||
_nodeList->appendGame(" [..]", parent, "", true);
|
||||
}
|
||||
|
||||
// Now add the directory entries
|
||||
for(unsigned int idx = 0; idx < content.size(); idx++)
|
||||
{
|
||||
string name = content[idx].displayName();
|
||||
bool isDir = content[idx].isDirectory();
|
||||
if(isDir)
|
||||
name = " [" + name + "]";
|
||||
|
||||
_nodeList->appendGame(name, content[idx].path(), "", isDir);
|
||||
}
|
||||
|
||||
// Now fill the list widget with the contents of the GameList
|
||||
StringList l;
|
||||
for (int i = 0; i < (int) _nodeList->size(); ++i)
|
||||
l.push_back(_nodeList->name(i));
|
||||
|
||||
_fileList->setList(l);
|
||||
if(_fileList->getList().size() > 0)
|
||||
_fileList->setSelected(0);
|
||||
|
||||
// Only hilite the 'up' button if there's a parent directory
|
||||
_goUpButton->setEnabled(_node.hasParent());
|
||||
|
||||
// Finally, redraw
|
||||
setDirty(); draw();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void BrowserDialog::handleCommand(CommandSender* sender, int cmd,
|
||||
int data, int id)
|
||||
|
@ -124,23 +183,11 @@ void BrowserDialog::handleCommand(CommandSender* sender, int cmd,
|
|||
switch (cmd)
|
||||
{
|
||||
case kChooseCmd:
|
||||
{
|
||||
// If nothing is selected in the list widget, choose the current dir.
|
||||
// Else, choose the dir that is selected.
|
||||
int selection = _fileList->getSelected();
|
||||
if (selection >= 0 && selection < (int)_nodeContent.size())
|
||||
_choice = _nodeContent[selection];
|
||||
else
|
||||
_choice = _node;
|
||||
|
||||
// Send a signal to the calling class that a selection has been made
|
||||
// Since we aren't derived from a widget, we don't have a 'data' or 'id'
|
||||
if(_cmd)
|
||||
sendCommand(_cmd, 0, 0);
|
||||
|
||||
if(_cmd) sendCommand(_cmd, 0, 0);
|
||||
close();
|
||||
break;
|
||||
}
|
||||
|
||||
case kGoUpCmd:
|
||||
_node = _node.getParent();
|
||||
|
@ -149,47 +196,18 @@ void BrowserDialog::handleCommand(CommandSender* sender, int cmd,
|
|||
|
||||
case kListItemActivatedCmd:
|
||||
case kListItemDoubleClickedCmd:
|
||||
_node = _nodeContent[data];
|
||||
updateListing();
|
||||
{
|
||||
int item = _fileList->getSelected();
|
||||
if(item >= 0)
|
||||
{
|
||||
_node = _nodeList->path(item);
|
||||
updateListing();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
Dialog::handleCommand(sender, cmd, data, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void BrowserDialog::updateListing()
|
||||
{
|
||||
if(!_node.isDirectory())
|
||||
return;
|
||||
|
||||
// Update the path display
|
||||
_currentPath->setLabel(_node.path());
|
||||
|
||||
// Read in the data from the file system
|
||||
_nodeContent = _node.listDir();
|
||||
_nodeContent.sort();
|
||||
|
||||
// Populate the ListWidget
|
||||
StringList list;
|
||||
int size = _nodeContent.size();
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
if(_nodeContent[i].isDirectory())
|
||||
list.push_back(" [" + _nodeContent[i].displayName() + "]");
|
||||
else
|
||||
list.push_back(_nodeContent[i].displayName());
|
||||
}
|
||||
|
||||
_fileList->setList(list);
|
||||
if(size > 0)
|
||||
_fileList->setSelected(0);
|
||||
|
||||
// Only hilite the 'up' button if there's a parent directory
|
||||
_goUpButton->setEnabled(_node.hasParent());
|
||||
|
||||
// Finally, redraw
|
||||
setDirty(); draw();
|
||||
}
|
||||
|
|
|
@ -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: BrowserDialog.hxx,v 1.9 2006-12-08 16:49:32 stephena Exp $
|
||||
// $Id: BrowserDialog.hxx,v 1.10 2006-12-10 17:04:34 stephena Exp $
|
||||
//
|
||||
// Based on code from ScummVM - Scumm Interpreter
|
||||
// Copyright (C) 2002-2004 The ScummVM project
|
||||
|
@ -26,6 +26,7 @@ class GuiObject;
|
|||
class ButtonWidget;
|
||||
class StaticTextWidget;
|
||||
class StringListWidget;
|
||||
class GameList;
|
||||
|
||||
#include "Dialog.hxx"
|
||||
#include "Command.hxx"
|
||||
|
@ -38,7 +39,9 @@ class BrowserDialog : public Dialog, public CommandSender
|
|||
BrowserDialog(GuiObject* boss, const GUI::Font& font,
|
||||
int x, int y, int w, int h);
|
||||
|
||||
const FilesystemNode& getResult() { return _choice; }
|
||||
virtual ~BrowserDialog();
|
||||
|
||||
const FilesystemNode& getResult() { return _node; }
|
||||
|
||||
void setTitle(const string& title) { _title->setLabel(title); }
|
||||
void setEmitSignal(int cmd) { _cmd = cmd; }
|
||||
|
@ -48,23 +51,21 @@ class BrowserDialog : public Dialog, public CommandSender
|
|||
virtual void handleCommand(CommandSender* sender, int cmd, int data, int id);
|
||||
void updateListing();
|
||||
|
||||
protected:
|
||||
private:
|
||||
enum {
|
||||
kChooseCmd = 'CHOS',
|
||||
kGoUpCmd = 'GOUP'
|
||||
};
|
||||
|
||||
int _cmd;
|
||||
|
||||
StringListWidget* _fileList;
|
||||
StaticTextWidget* _currentPath;
|
||||
StaticTextWidget* _title;
|
||||
ButtonWidget* _goUpButton;
|
||||
|
||||
FilesystemNode _node;
|
||||
FSList _nodeContent;
|
||||
FilesystemNode _choice;
|
||||
|
||||
private:
|
||||
int _cmd;
|
||||
|
||||
enum {
|
||||
kChooseCmd = 'CHOS',
|
||||
kGoUpCmd = 'GOUP'
|
||||
};
|
||||
FilesystemNode _node;
|
||||
GameList* _nodeList;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue