mirror of https://github.com/stella-emu/stella.git
First pass at fixing superfluous re-draws in the UI.
- This addresses issue 158, and reduces CPU usage to near 0% when no changes are happening - This returns the code to the same performance levels as version 3.x.
This commit is contained in:
parent
a20bb6e95d
commit
e691853f0e
|
@ -125,20 +125,13 @@ void FBSurfaceSDL2::translateCoords(Int32& x, Int32& y) const
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
bool FBSurfaceSDL2::render()
|
bool FBSurfaceSDL2::render()
|
||||||
{
|
{
|
||||||
if(mySurfaceIsDirty && myIsVisible)
|
if(myIsVisible)
|
||||||
{
|
{
|
||||||
//cerr << "src: x=" << mySrcR.x << ", y=" << mySrcR.y << ", w=" << mySrcR.w << ", h=" << mySrcR.h << endl;
|
|
||||||
//cerr << "dst: x=" << myDstR.x << ", y=" << myDstR.y << ", w=" << myDstR.w << ", h=" << myDstR.h << endl;
|
|
||||||
|
|
||||||
//cerr << "render()\n";
|
|
||||||
if(myTexAccess == SDL_TEXTUREACCESS_STREAMING)
|
if(myTexAccess == SDL_TEXTUREACCESS_STREAMING)
|
||||||
SDL_UpdateTexture(myTexture, &mySrcR, mySurface->pixels, mySurface->pitch);
|
SDL_UpdateTexture(myTexture, &mySrcR, mySurface->pixels, mySurface->pitch);
|
||||||
SDL_RenderCopy(myFB.myRenderer, myTexture, &mySrcR, &myDstR);
|
SDL_RenderCopy(myFB.myRenderer, myTexture, &mySrcR, &myDstR);
|
||||||
|
|
||||||
mySurfaceIsDirty = false;
|
return true;
|
||||||
|
|
||||||
// Let postFrameUpdate() know that a change has been made
|
|
||||||
return myFB.myDirtyFlag = true;
|
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,8 +32,7 @@
|
||||||
FrameBufferSDL2::FrameBufferSDL2(OSystem& osystem)
|
FrameBufferSDL2::FrameBufferSDL2(OSystem& osystem)
|
||||||
: FrameBuffer(osystem),
|
: FrameBuffer(osystem),
|
||||||
myWindow(nullptr),
|
myWindow(nullptr),
|
||||||
myRenderer(nullptr),
|
myRenderer(nullptr)
|
||||||
myDirtyFlag(true)
|
|
||||||
{
|
{
|
||||||
// Initialize SDL2 context
|
// Initialize SDL2 context
|
||||||
if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_JOYSTICK) < 0)
|
if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_JOYSTICK) < 0)
|
||||||
|
@ -275,7 +274,6 @@ string FrameBufferSDL2::about() const
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void FrameBufferSDL2::invalidate()
|
void FrameBufferSDL2::invalidate()
|
||||||
{
|
{
|
||||||
myDirtyFlag = true;
|
|
||||||
SDL_RenderClear(myRenderer);
|
SDL_RenderClear(myRenderer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -302,14 +300,10 @@ bool FrameBufferSDL2::fullScreen() const
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void FrameBufferSDL2::postFrameUpdate()
|
void FrameBufferSDL2::renderToScreen()
|
||||||
{
|
{
|
||||||
if(myDirtyFlag)
|
// Show all changes made to the renderer
|
||||||
{
|
SDL_RenderPresent(myRenderer);
|
||||||
// Now show all changes made to the renderer
|
|
||||||
SDL_RenderPresent(myRenderer);
|
|
||||||
myDirtyFlag = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -347,5 +341,5 @@ void FrameBufferSDL2::readPixels(uInt8* pixels, uInt32 pitch,
|
||||||
void FrameBufferSDL2::clear()
|
void FrameBufferSDL2::clear()
|
||||||
{
|
{
|
||||||
invalidate();
|
invalidate();
|
||||||
postFrameUpdate();
|
renderToScreen();
|
||||||
}
|
}
|
||||||
|
|
|
@ -164,9 +164,10 @@ class FrameBufferSDL2 : public FrameBuffer
|
||||||
string about() const override;
|
string about() const override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
This method is called after any drawing is done (per-frame).
|
This method must be called after all drawing is done, and indicates
|
||||||
|
that the buffers should be pushed to the physical screen.
|
||||||
*/
|
*/
|
||||||
void postFrameUpdate() override;
|
void renderToScreen() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// The SDL video buffer
|
// The SDL video buffer
|
||||||
|
@ -176,9 +177,6 @@ class FrameBufferSDL2 : public FrameBuffer
|
||||||
// Used by mapRGB (when palettes are created)
|
// Used by mapRGB (when palettes are created)
|
||||||
SDL_PixelFormat* myPixelFormat;
|
SDL_PixelFormat* myPixelFormat;
|
||||||
|
|
||||||
// Indicates that the renderer has been modified, and should be redrawn
|
|
||||||
bool myDirtyFlag;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Following constructors and assignment operators not supported
|
// Following constructors and assignment operators not supported
|
||||||
FrameBufferSDL2() = delete;
|
FrameBufferSDL2() = delete;
|
||||||
|
|
|
@ -793,7 +793,7 @@ void Debugger::unlockSystem()
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
bool Debugger::canExit() const
|
bool Debugger::canExit() const
|
||||||
{
|
{
|
||||||
return myDialogStack.top() == baseDialog();
|
return !myDialogStack.empty() && myDialogStack.top() == baseDialog();
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
|
|
@ -221,72 +221,84 @@ void DebuggerDialog::handleCommand(CommandSender* sender, int cmd,
|
||||||
void DebuggerDialog::doStep()
|
void DebuggerDialog::doStep()
|
||||||
{
|
{
|
||||||
instance().debugger().parser().run("step");
|
instance().debugger().parser().run("step");
|
||||||
|
setDirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void DebuggerDialog::doTrace()
|
void DebuggerDialog::doTrace()
|
||||||
{
|
{
|
||||||
instance().debugger().parser().run("trace");
|
instance().debugger().parser().run("trace");
|
||||||
|
setDirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void DebuggerDialog::doAdvance()
|
void DebuggerDialog::doAdvance()
|
||||||
{
|
{
|
||||||
instance().debugger().parser().run("frame #1");
|
instance().debugger().parser().run("frame #1");
|
||||||
|
setDirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void DebuggerDialog::doScanlineAdvance()
|
void DebuggerDialog::doScanlineAdvance()
|
||||||
{
|
{
|
||||||
instance().debugger().parser().run("scanline #1");
|
instance().debugger().parser().run("scanline #1");
|
||||||
|
setDirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void DebuggerDialog::doRewind()
|
void DebuggerDialog::doRewind()
|
||||||
{
|
{
|
||||||
instance().debugger().parser().run("rewind");
|
instance().debugger().parser().run("rewind");
|
||||||
|
setDirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void DebuggerDialog::doUnwind()
|
void DebuggerDialog::doUnwind()
|
||||||
{
|
{
|
||||||
instance().debugger().parser().run("unwind");
|
instance().debugger().parser().run("unwind");
|
||||||
|
setDirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void DebuggerDialog::doRewind10()
|
void DebuggerDialog::doRewind10()
|
||||||
{
|
{
|
||||||
instance().debugger().parser().run("rewind #10");
|
instance().debugger().parser().run("rewind #10");
|
||||||
|
setDirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void DebuggerDialog::doUnwind10()
|
void DebuggerDialog::doUnwind10()
|
||||||
{
|
{
|
||||||
instance().debugger().parser().run("unwind #10");
|
instance().debugger().parser().run("unwind #10");
|
||||||
|
setDirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void DebuggerDialog::doRewindAll()
|
void DebuggerDialog::doRewindAll()
|
||||||
{
|
{
|
||||||
instance().debugger().parser().run("rewind #1000");
|
instance().debugger().parser().run("rewind #1000");
|
||||||
|
setDirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void DebuggerDialog::doUnwindAll()
|
void DebuggerDialog::doUnwindAll()
|
||||||
{
|
{
|
||||||
instance().debugger().parser().run("unwind #1000");
|
instance().debugger().parser().run("unwind #1000");
|
||||||
|
setDirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void DebuggerDialog::doExitDebugger()
|
void DebuggerDialog::doExitDebugger()
|
||||||
{
|
{
|
||||||
instance().debugger().parser().run("run");
|
instance().debugger().parser().run("run");
|
||||||
|
setDirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void DebuggerDialog::doExitRom()
|
void DebuggerDialog::doExitRom()
|
||||||
{
|
{
|
||||||
instance().debugger().parser().run("exitrom");
|
instance().debugger().parser().run("exitrom");
|
||||||
|
setDirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
|
|
@ -130,8 +130,6 @@ class DebuggerDialog : public Dialog
|
||||||
ButtonWidget* myRewindButton;
|
ButtonWidget* myRewindButton;
|
||||||
ButtonWidget* myUnwindButton;
|
ButtonWidget* myUnwindButton;
|
||||||
|
|
||||||
//ButtonWidget* myOptionsButton;
|
|
||||||
|
|
||||||
unique_ptr<GUI::MessageBox> myFatalError;
|
unique_ptr<GUI::MessageBox> myFatalError;
|
||||||
unique_ptr<OptionsDialog> myOptions;
|
unique_ptr<OptionsDialog> myOptions;
|
||||||
|
|
||||||
|
|
|
@ -283,7 +283,8 @@ void EventHandler::handleSystemEvent(SystemEvent e, int, int)
|
||||||
switch(e)
|
switch(e)
|
||||||
{
|
{
|
||||||
case SystemEvent::WINDOW_EXPOSED:
|
case SystemEvent::WINDOW_EXPOSED:
|
||||||
myOSystem.frameBuffer().update();
|
case SystemEvent::WINDOW_RESIZED:
|
||||||
|
myOSystem.frameBuffer().update(true); // force full update
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SystemEvent::WINDOW_FOCUS_GAINED:
|
case SystemEvent::WINDOW_FOCUS_GAINED:
|
||||||
|
|
|
@ -219,12 +219,6 @@ class FBSurface
|
||||||
uInt32 color, TextAlign align = TextAlign::Left,
|
uInt32 color, TextAlign align = TextAlign::Left,
|
||||||
int deltax = 0, bool useEllipsis = true, uInt32 shadowColor = 0);
|
int deltax = 0, bool useEllipsis = true, uInt32 shadowColor = 0);
|
||||||
|
|
||||||
/**
|
|
||||||
This method should be called to indicate that the surface has been
|
|
||||||
modified, and should be redrawn at the next interval.
|
|
||||||
*/
|
|
||||||
virtual void setDirty() { }
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
// Note: The following methods are FBSurface-specific, and must be
|
// Note: The following methods are FBSurface-specific, and must be
|
||||||
// implemented in child classes.
|
// implemented in child classes.
|
||||||
|
@ -331,6 +325,13 @@ class FBSurface
|
||||||
|
|
||||||
static void setPalette(const uInt32* palette) { myPalette = palette; }
|
static void setPalette(const uInt32* palette) { myPalette = palette; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/**
|
||||||
|
This method must be called to indicate that the surface has been
|
||||||
|
modified, and should be redrawn at the next interval.
|
||||||
|
*/
|
||||||
|
virtual void setDirty() = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
static const uInt32* myPalette;
|
static const uInt32* myPalette;
|
||||||
uInt32* myPixels;
|
uInt32* myPixels;
|
||||||
|
|
|
@ -50,7 +50,8 @@ FrameBuffer::FrameBuffer(OSystem& osystem)
|
||||||
myLastScanlines(0),
|
myLastScanlines(0),
|
||||||
myGrabMouse(false),
|
myGrabMouse(false),
|
||||||
myCurrentModeList(nullptr)
|
myCurrentModeList(nullptr)
|
||||||
{}
|
{
|
||||||
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
FrameBuffer::~FrameBuffer()
|
FrameBuffer::~FrameBuffer()
|
||||||
|
@ -258,85 +259,116 @@ FBInitStatus FrameBuffer::createDisplay(const string& title,
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void FrameBuffer::update()
|
void FrameBuffer::update(bool force)
|
||||||
{
|
{
|
||||||
// Determine which mode we are in (from the EventHandler)
|
// Onscreen messages are a special case and require different handling than
|
||||||
// Take care of S_EMULATE mode here, otherwise let the GUI
|
// other objects; they aren't UI dialogs in the normal sense nor are they
|
||||||
// figure out what to draw
|
// TIA images, and they need to be rendered on top of everything
|
||||||
|
// The logic is split in two pieces:
|
||||||
|
// - at the top of ::update(), to determine whether underlying dialogs
|
||||||
|
// need to be force-redrawn
|
||||||
|
// - at the bottom of ::update(), to actually draw them (this must come
|
||||||
|
// last, since they are always drawn on top of everything else).
|
||||||
|
|
||||||
|
// Full rendering is required when messages are enabled
|
||||||
|
force |= myMsg.counter >= 0;
|
||||||
|
|
||||||
|
// Detect when a message has been turned off; one last redraw is required
|
||||||
|
// in this case, to draw over the area that the message occupied
|
||||||
|
if(myMsg.counter == 0)
|
||||||
|
myMsg.counter = -1;
|
||||||
|
|
||||||
invalidate();
|
|
||||||
switch(myOSystem.eventHandler().state())
|
switch(myOSystem.eventHandler().state())
|
||||||
{
|
{
|
||||||
|
case EventHandlerState::NONE:
|
||||||
case EventHandlerState::EMULATION:
|
case EventHandlerState::EMULATION:
|
||||||
// Do nothing; emulation mode is handled separately (see below)
|
// Do nothing; emulation mode is handled separately (see below)
|
||||||
break;
|
return;
|
||||||
|
|
||||||
case EventHandlerState::PAUSE:
|
case EventHandlerState::PAUSE:
|
||||||
{
|
{
|
||||||
myTIASurface->render();
|
|
||||||
|
|
||||||
// Show a pause message immediately and then every 7 seconds
|
// Show a pause message immediately and then every 7 seconds
|
||||||
if (myPausedCount-- <= 0)
|
if(myPausedCount-- <= 0)
|
||||||
{
|
{
|
||||||
myPausedCount = uInt32(7 * myOSystem.frameRate());
|
myPausedCount = uInt32(7 * myOSystem.frameRate());
|
||||||
showMessage("Paused", MessagePosition::MiddleCenter);
|
showMessage("Paused", MessagePosition::MiddleCenter);
|
||||||
}
|
}
|
||||||
|
if(force)
|
||||||
|
myTIASurface->render();
|
||||||
|
|
||||||
break; // EventHandlerState::PAUSE
|
break; // EventHandlerState::PAUSE
|
||||||
}
|
}
|
||||||
|
|
||||||
case EventHandlerState::OPTIONSMENU:
|
case EventHandlerState::OPTIONSMENU:
|
||||||
{
|
{
|
||||||
myTIASurface->render();
|
force |= myOSystem.menu().needsRedraw();
|
||||||
myOSystem.menu().draw(true);
|
if(force)
|
||||||
|
{
|
||||||
|
myTIASurface->render();
|
||||||
|
myOSystem.menu().draw(force);
|
||||||
|
}
|
||||||
break; // EventHandlerState::OPTIONSMENU
|
break; // EventHandlerState::OPTIONSMENU
|
||||||
}
|
}
|
||||||
|
|
||||||
case EventHandlerState::CMDMENU:
|
case EventHandlerState::CMDMENU:
|
||||||
{
|
{
|
||||||
myTIASurface->render();
|
force |= myOSystem.commandMenu().needsRedraw();
|
||||||
myOSystem.commandMenu().draw(true);
|
if(force)
|
||||||
|
{
|
||||||
|
myTIASurface->render();
|
||||||
|
myOSystem.commandMenu().draw(force);
|
||||||
|
}
|
||||||
break; // EventHandlerState::CMDMENU
|
break; // EventHandlerState::CMDMENU
|
||||||
}
|
}
|
||||||
|
|
||||||
case EventHandlerState::TIMEMACHINE:
|
case EventHandlerState::TIMEMACHINE:
|
||||||
{
|
{
|
||||||
myTIASurface->render();
|
force |= myOSystem.timeMachine().needsRedraw();
|
||||||
myOSystem.timeMachine().draw(true);
|
if(force)
|
||||||
|
{
|
||||||
|
myTIASurface->render();
|
||||||
|
myOSystem.timeMachine().draw(force);
|
||||||
|
}
|
||||||
break; // EventHandlerState::TIMEMACHINE
|
break; // EventHandlerState::TIMEMACHINE
|
||||||
}
|
}
|
||||||
|
|
||||||
case EventHandlerState::LAUNCHER:
|
case EventHandlerState::LAUNCHER:
|
||||||
{
|
{
|
||||||
myOSystem.launcher().draw(true);
|
force |= myOSystem.launcher().draw(force);
|
||||||
break; // EventHandlerState::LAUNCHER
|
break; // EventHandlerState::LAUNCHER
|
||||||
}
|
}
|
||||||
|
|
||||||
case EventHandlerState::DEBUGGER:
|
case EventHandlerState::DEBUGGER:
|
||||||
{
|
{
|
||||||
#ifdef DEBUGGER_SUPPORT
|
#ifdef DEBUGGER_SUPPORT
|
||||||
myOSystem.debugger().draw(true);
|
force |= myOSystem.debugger().draw(force);
|
||||||
#endif
|
#endif
|
||||||
break; // EventHandlerState::DEBUGGER
|
break; // EventHandlerState::DEBUGGER
|
||||||
}
|
}
|
||||||
|
|
||||||
case EventHandlerState::NONE:
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw any pending messages
|
// Draw any pending messages
|
||||||
|
// The logic here determines whether to draw the message
|
||||||
|
// If the message is to be disabled, logic inside the draw method
|
||||||
|
// indicates that, and then the code at the top of this method sees
|
||||||
|
// the change and redraws everything
|
||||||
if(myMsg.enabled)
|
if(myMsg.enabled)
|
||||||
drawMessage();
|
force |= drawMessage();
|
||||||
|
|
||||||
// Do any post-frame stuff
|
// Push buffers to screen only when necessary
|
||||||
postFrameUpdate();
|
if(force)
|
||||||
|
renderToScreen();
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void FrameBuffer::updateInEmulationMode()
|
void FrameBuffer::updateInEmulationMode()
|
||||||
{
|
{
|
||||||
// Determine which mode we are in (from the EventHandler)
|
// Update method that is specifically tailored to emulation mode
|
||||||
// Take care of S_EMULATE mode here, otherwise let the GUI
|
// Typically called from a thread, so it needs to be separate from
|
||||||
// figure out what to draw
|
// the normal update() method
|
||||||
|
//
|
||||||
|
// We don't worry about selective rendering here; the rendering
|
||||||
|
// always happens at the full framerate
|
||||||
|
|
||||||
myTIASurface->render();
|
myTIASurface->render();
|
||||||
|
|
||||||
|
@ -351,8 +383,8 @@ void FrameBuffer::updateInEmulationMode()
|
||||||
if(myMsg.enabled)
|
if(myMsg.enabled)
|
||||||
drawMessage();
|
drawMessage();
|
||||||
|
|
||||||
// Do any post-frame stuff
|
// Push buffers to screen
|
||||||
postFrameUpdate();
|
renderToScreen();
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -413,7 +445,6 @@ void FrameBuffer::drawFrameStats()
|
||||||
myStatsMsg.surface->drawString(font(), bsinfo, XPOS, YPOS + font().getFontHeight(),
|
myStatsMsg.surface->drawString(font(), bsinfo, XPOS, YPOS + font().getFontHeight(),
|
||||||
myStatsMsg.w, myStatsMsg.color, TextAlign::Left, 0, true, kBGColor);
|
myStatsMsg.w, myStatsMsg.color, TextAlign::Left, 0, true, kBGColor);
|
||||||
|
|
||||||
myStatsMsg.surface->setDirty();
|
|
||||||
myStatsMsg.surface->setDstPos(myImageRect.x() + 10, myImageRect.y() + 8);
|
myStatsMsg.surface->setDstPos(myImageRect.x() + 10, myImageRect.y() + 8);
|
||||||
myStatsMsg.surface->render();
|
myStatsMsg.surface->render();
|
||||||
}
|
}
|
||||||
|
@ -448,13 +479,26 @@ void FrameBuffer::enableMessages(bool enable)
|
||||||
// Erase old messages on the screen
|
// Erase old messages on the screen
|
||||||
myMsg.enabled = false;
|
myMsg.enabled = false;
|
||||||
myMsg.counter = 0;
|
myMsg.counter = 0;
|
||||||
update(); // Force update immediately
|
update(true); // Force update immediately
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
inline void FrameBuffer::drawMessage()
|
inline bool FrameBuffer::drawMessage()
|
||||||
{
|
{
|
||||||
|
// Either erase the entire message (when time is reached),
|
||||||
|
// or show again this frame
|
||||||
|
if(myMsg.counter == 0)
|
||||||
|
{
|
||||||
|
myMsg.enabled = false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if(myMsg.counter < 0)
|
||||||
|
{
|
||||||
|
myMsg.enabled = false;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Draw the bounded box and text
|
// Draw the bounded box and text
|
||||||
const GUI::Rect& dst = myMsg.surface->dstRect();
|
const GUI::Rect& dst = myMsg.surface->dstRect();
|
||||||
|
|
||||||
|
@ -511,16 +555,10 @@ inline void FrameBuffer::drawMessage()
|
||||||
myMsg.surface->frameRect(0, 0, myMsg.w, myMsg.h, kColor);
|
myMsg.surface->frameRect(0, 0, myMsg.w, myMsg.h, kColor);
|
||||||
myMsg.surface->drawString(font(), myMsg.text, 5, 4,
|
myMsg.surface->drawString(font(), myMsg.text, 5, 4,
|
||||||
myMsg.w, myMsg.color, TextAlign::Left);
|
myMsg.w, myMsg.color, TextAlign::Left);
|
||||||
|
myMsg.surface->render();
|
||||||
|
myMsg.counter--;
|
||||||
|
|
||||||
// Either erase the entire message (when time is reached),
|
return true;
|
||||||
// or show again this frame
|
|
||||||
if(myMsg.counter-- > 0)
|
|
||||||
{
|
|
||||||
myMsg.surface->setDirty();
|
|
||||||
myMsg.surface->render();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
myMsg.enabled = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -564,6 +602,8 @@ void FrameBuffer::resetSurfaces()
|
||||||
|
|
||||||
freeSurfaces();
|
freeSurfaces();
|
||||||
reloadSurfaces();
|
reloadSurfaces();
|
||||||
|
|
||||||
|
update(true); // force full update
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -589,6 +629,8 @@ void FrameBuffer::stateChanged(EventHandlerState state)
|
||||||
// Make sure any onscreen messages are removed
|
// Make sure any onscreen messages are removed
|
||||||
myMsg.enabled = false;
|
myMsg.enabled = false;
|
||||||
myMsg.counter = 0;
|
myMsg.counter = 0;
|
||||||
|
|
||||||
|
update(true); // force full update
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
|
|
@ -113,10 +113,9 @@ class FrameBuffer
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Updates the display, which depending on the current mode could mean
|
Updates the display, which depending on the current mode could mean
|
||||||
drawing the TIA, any pending menus, etc. Returns the numbers of CPU cycles
|
drawing the TIA, any pending menus, etc.
|
||||||
spent during emulation, or -1 if not applicable.
|
|
||||||
*/
|
*/
|
||||||
void update();
|
void update(bool force = false);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
There is a dedicated update method for emulation mode.
|
There is a dedicated update method for emulation mode.
|
||||||
|
@ -379,9 +378,10 @@ class FrameBuffer
|
||||||
virtual void setWindowIcon() = 0;
|
virtual void setWindowIcon() = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
This method is called after any drawing is done (per-frame).
|
This method must be called after all drawing is done, and indicates
|
||||||
|
that the buffers should be pushed to the physical screen.
|
||||||
*/
|
*/
|
||||||
virtual void postFrameUpdate() = 0;
|
virtual void renderToScreen() = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
This method is called to provide information about the FrameBuffer.
|
This method is called to provide information about the FrameBuffer.
|
||||||
|
@ -398,8 +398,10 @@ class FrameBuffer
|
||||||
private:
|
private:
|
||||||
/**
|
/**
|
||||||
Draw pending messages.
|
Draw pending messages.
|
||||||
|
|
||||||
|
@return Indicates whether any changes actually occurred.
|
||||||
*/
|
*/
|
||||||
void drawMessage();
|
bool drawMessage();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Frees and reloads all surfaces that the framebuffer knows about.
|
Frees and reloads all surfaces that the framebuffer knows about.
|
||||||
|
@ -521,7 +523,7 @@ class FrameBuffer
|
||||||
bool enabled;
|
bool enabled;
|
||||||
|
|
||||||
Message()
|
Message()
|
||||||
: counter(0), x(0), y(0), w(0), h(0), position(MessagePosition::BottomCenter),
|
: counter(-1), x(0), y(0), w(0), h(0), position(MessagePosition::BottomCenter),
|
||||||
color(0), enabled(false) { }
|
color(0), enabled(false) { }
|
||||||
};
|
};
|
||||||
Message myMsg;
|
Message myMsg;
|
||||||
|
|
|
@ -704,8 +704,8 @@ void OSystem::mainLoop()
|
||||||
// Dispatch emulation and render frame (if applicable)
|
// Dispatch emulation and render frame (if applicable)
|
||||||
timesliceSeconds = dispatchEmulation(emulationWorker);
|
timesliceSeconds = dispatchEmulation(emulationWorker);
|
||||||
else {
|
else {
|
||||||
// Render the GUI with 30 Hz in all other modes
|
// Render the GUI with 60 Hz in all other modes
|
||||||
timesliceSeconds = 1. / 30.;
|
timesliceSeconds = 1. / 60.;
|
||||||
myFrameBuffer->update();
|
myFrameBuffer->update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -206,7 +206,6 @@ uInt32 TIASurface::enableScanlines(int relative, int absolute)
|
||||||
attr.blendalpha = std::min(100u, attr.blendalpha);
|
attr.blendalpha = std::min(100u, attr.blendalpha);
|
||||||
|
|
||||||
mySLineSurface->applyAttributes();
|
mySLineSurface->applyAttributes();
|
||||||
mySLineSurface->setDirty();
|
|
||||||
|
|
||||||
return attr.blendalpha;
|
return attr.blendalpha;
|
||||||
}
|
}
|
||||||
|
@ -217,7 +216,6 @@ void TIASurface::enableScanlineInterpolation(bool enable)
|
||||||
FBSurface::Attributes& attr = mySLineSurface->attributes();
|
FBSurface::Attributes& attr = mySLineSurface->attributes();
|
||||||
attr.smoothing = enable;
|
attr.smoothing = enable;
|
||||||
mySLineSurface->applyAttributes();
|
mySLineSurface->applyAttributes();
|
||||||
mySLineSurface->setDirty();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -231,8 +229,6 @@ void TIASurface::enablePhosphor(bool enable, int blend)
|
||||||
myPhosphorPercent = blend / 100.0;
|
myPhosphorPercent = blend / 100.0;
|
||||||
myFilter = Filter(enable ? uInt8(myFilter) | 0x01 : uInt8(myFilter) & 0x10);
|
myFilter = Filter(enable ? uInt8(myFilter) | 0x01 : uInt8(myFilter) & 0x10);
|
||||||
|
|
||||||
myTiaSurface->setDirty();
|
|
||||||
mySLineSurface->setDirty();
|
|
||||||
memset(myRGBFramebuffer, 0, sizeof(myRGBFramebuffer));
|
memset(myRGBFramebuffer, 0, sizeof(myRGBFramebuffer));
|
||||||
|
|
||||||
// Precalculate the average colors for the 'phosphor' effect
|
// Precalculate the average colors for the 'phosphor' effect
|
||||||
|
@ -283,8 +279,6 @@ void TIASurface::enableNTSC(bool enable)
|
||||||
sl_attr.blendalpha = myOSystem.settings().getInt("tv.scanlines");
|
sl_attr.blendalpha = myOSystem.settings().getInt("tv.scanlines");
|
||||||
mySLineSurface->applyAttributes();
|
mySLineSurface->applyAttributes();
|
||||||
|
|
||||||
myTiaSurface->setDirty();
|
|
||||||
mySLineSurface->setDirty();
|
|
||||||
memset(myRGBFramebuffer, 0, sizeof(myRGBFramebuffer));
|
memset(myRGBFramebuffer, 0, sizeof(myRGBFramebuffer));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -379,15 +373,11 @@ void TIASurface::render()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw TIA image
|
// Draw TIA image
|
||||||
myTiaSurface->setDirty();
|
|
||||||
myTiaSurface->render();
|
myTiaSurface->render();
|
||||||
|
|
||||||
// Draw overlaying scanlines
|
// Draw overlaying scanlines
|
||||||
if(myScanlinesEnabled)
|
if(myScanlinesEnabled)
|
||||||
{
|
|
||||||
mySLineSurface->setDirty();
|
|
||||||
mySLineSurface->render();
|
mySLineSurface->render();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -424,14 +414,10 @@ void TIASurface::reRender()
|
||||||
if (myUsePhosphor)
|
if (myUsePhosphor)
|
||||||
{
|
{
|
||||||
// Draw TIA image
|
// Draw TIA image
|
||||||
myTiaSurface->setDirty();
|
|
||||||
myTiaSurface->render();
|
myTiaSurface->render();
|
||||||
|
|
||||||
// Draw overlaying scanlines
|
// Draw overlaying scanlines
|
||||||
if (myScanlinesEnabled)
|
if (myScanlinesEnabled)
|
||||||
{
|
|
||||||
mySLineSurface->setDirty();
|
|
||||||
mySLineSurface->render();
|
mySLineSurface->render();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -226,7 +226,7 @@ void AboutDialog::displayInfo()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Redraw entire dialog
|
// Redraw entire dialog
|
||||||
_dirty = true;
|
setDirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
|
|
@ -47,7 +47,7 @@ AudioDialog::AudioDialog(OSystem& osystem, DialogContainer& parent,
|
||||||
int xpos, ypos;
|
int xpos, ypos;
|
||||||
int lwidth = font.getStringWidth("Resampling quality "),
|
int lwidth = font.getStringWidth("Resampling quality "),
|
||||||
pwidth = font.getStringWidth("512 bytes");
|
pwidth = font.getStringWidth("512 bytes");
|
||||||
|
|
||||||
WidgetArray wid;
|
WidgetArray wid;
|
||||||
VariantList items;
|
VariantList items;
|
||||||
|
|
||||||
|
@ -186,7 +186,6 @@ void AudioDialog::updateSettingsWithPreset(AudioSettings& audioSettings)
|
||||||
myResamplingPopup->setSelected(static_cast<int>(audioSettings.resamplingQuality()));
|
myResamplingPopup->setSelected(static_cast<int>(audioSettings.resamplingQuality()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void AudioDialog::saveConfig()
|
void AudioDialog::saveConfig()
|
||||||
{
|
{
|
||||||
|
@ -235,8 +234,6 @@ void AudioDialog::setDefaults()
|
||||||
else updatePreset();
|
else updatePreset();
|
||||||
|
|
||||||
updateEnabledState();
|
updateEnabledState();
|
||||||
|
|
||||||
_dirty = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
|
|
@ -118,7 +118,7 @@ void ComboDialog::setDefaults()
|
||||||
for(int i = 0; i < 8; ++i)
|
for(int i = 0; i < 8; ++i)
|
||||||
myEvents[i]->setSelected("None", "-1");
|
myEvents[i]->setSelected("None", "-1");
|
||||||
|
|
||||||
_dirty = true;
|
setDirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
|
|
@ -546,45 +546,38 @@ void ContextMenu::drawDialog()
|
||||||
// by the ScummVM guys, so I'm not going to mess with it.
|
// by the ScummVM guys, so I'm not going to mess with it.
|
||||||
FBSurface& s = surface();
|
FBSurface& s = surface();
|
||||||
|
|
||||||
if(_dirty)
|
// Draw menu border and background
|
||||||
|
s.fillRect(_x+1, _y+1, _w-2, _h-2, kWidColor);
|
||||||
|
s.frameRect(_x, _y, _w, _h, kTextColor);
|
||||||
|
|
||||||
|
// Draw the entries, taking scroll buttons into account
|
||||||
|
int x = _x + 1, y = _y + 1, w = _w - 2;
|
||||||
|
|
||||||
|
// Show top scroll area
|
||||||
|
int offset = _selectedOffset;
|
||||||
|
if(_showScroll)
|
||||||
{
|
{
|
||||||
// Draw menu border and background
|
s.hLine(x, y+_rowHeight-1, w+2, kColor);
|
||||||
s.fillRect(_x+1, _y+1, _w-2, _h-2, kWidColor);
|
s.drawBitmap(up_arrow, ((_w-_x)>>1)-4, (_rowHeight>>1)+y-4, _scrollUpColor, 8);
|
||||||
s.frameRect(_x, _y, _w, _h, kTextColor);
|
y += _rowHeight;
|
||||||
|
offset--;
|
||||||
// Draw the entries, taking scroll buttons into account
|
|
||||||
int x = _x + 1, y = _y + 1, w = _w - 2;
|
|
||||||
|
|
||||||
// Show top scroll area
|
|
||||||
int offset = _selectedOffset;
|
|
||||||
if(_showScroll)
|
|
||||||
{
|
|
||||||
s.hLine(x, y+_rowHeight-1, w+2, kColor);
|
|
||||||
s.drawBitmap(up_arrow, ((_w-_x)>>1)-4, (_rowHeight>>1)+y-4, _scrollUpColor, 8);
|
|
||||||
y += _rowHeight;
|
|
||||||
offset--;
|
|
||||||
}
|
|
||||||
|
|
||||||
for(int i = _firstEntry, current = 0; i < _firstEntry + _numEntries; ++i, ++current)
|
|
||||||
{
|
|
||||||
bool hilite = offset == current;
|
|
||||||
if(hilite) s.fillRect(x, y, w, _rowHeight, kTextColorHi);
|
|
||||||
s.drawString(_font, _entries[i].first, x + 1, y + 2, w,
|
|
||||||
!hilite ? kTextColor : kTextColorInv);
|
|
||||||
y += _rowHeight;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Show bottom scroll area
|
|
||||||
if(_showScroll)
|
|
||||||
{
|
|
||||||
s.hLine(x, y, w+2, kColor);
|
|
||||||
s.drawBitmap(down_arrow, ((_w-_x)>>1)-4, (_rowHeight>>1)+y-4, _scrollDnColor, 8);
|
|
||||||
}
|
|
||||||
|
|
||||||
s.setDirty();
|
|
||||||
_dirty = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Commit surface changes to screen
|
for(int i = _firstEntry, current = 0; i < _firstEntry + _numEntries; ++i, ++current)
|
||||||
s.render();
|
{
|
||||||
|
bool hilite = offset == current;
|
||||||
|
if(hilite) s.fillRect(x, y, w, _rowHeight, kTextColorHi);
|
||||||
|
s.drawString(_font, _entries[i].first, x + 1, y + 2, w,
|
||||||
|
!hilite ? kTextColor : kTextColorInv);
|
||||||
|
y += _rowHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Show bottom scroll area
|
||||||
|
if(_showScroll)
|
||||||
|
{
|
||||||
|
s.hLine(x, y, w+2, kColor);
|
||||||
|
s.drawBitmap(down_arrow, ((_w-_x)>>1)-4, (_rowHeight>>1)+y-4, _scrollDnColor, 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
setDirty();
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,6 +64,7 @@ Dialog::Dialog(OSystem& instance, DialogContainer& parent, const GUI::Font& font
|
||||||
_flags(WIDGET_ENABLED | WIDGET_BORDER | WIDGET_CLEARBG)
|
_flags(WIDGET_ENABLED | WIDGET_BORDER | WIDGET_CLEARBG)
|
||||||
{
|
{
|
||||||
setTitle(title);
|
setTitle(title);
|
||||||
|
setDirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -86,7 +87,7 @@ Dialog::~Dialog()
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void Dialog::open(bool refresh)
|
void Dialog::open()
|
||||||
{
|
{
|
||||||
// Make sure we have a valid surface to draw into
|
// Make sure we have a valid surface to draw into
|
||||||
// Technically, this shouldn't be needed until drawDialog(), but some
|
// Technically, this shouldn't be needed until drawDialog(), but some
|
||||||
|
@ -103,10 +104,12 @@ void Dialog::open(bool refresh)
|
||||||
buildCurrentFocusList();
|
buildCurrentFocusList();
|
||||||
|
|
||||||
_visible = true;
|
_visible = true;
|
||||||
|
|
||||||
|
setDirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void Dialog::close(bool refresh)
|
void Dialog::close()
|
||||||
{
|
{
|
||||||
if (_mouseWidget)
|
if (_mouseWidget)
|
||||||
{
|
{
|
||||||
|
@ -119,6 +122,7 @@ void Dialog::close(bool refresh)
|
||||||
_visible = false;
|
_visible = false;
|
||||||
|
|
||||||
parent().removeDialog();
|
parent().removeDialog();
|
||||||
|
setDirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -131,6 +135,8 @@ void Dialog::setTitle(const string& title)
|
||||||
else
|
else
|
||||||
_th = _font.getLineHeight() + 4;
|
_th = _font.getLineHeight() + 4;
|
||||||
_h += _th;
|
_h += _th;
|
||||||
|
|
||||||
|
setDirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -144,6 +150,29 @@ void Dialog::center()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
bool Dialog::render()
|
||||||
|
{
|
||||||
|
if(!_dirty)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Draw this dialog
|
||||||
|
center();
|
||||||
|
drawDialog();
|
||||||
|
|
||||||
|
// Update dialog surface; also render any extra surfaces
|
||||||
|
// Extra surfaces must be rendered afterwards, so they are drawn on top
|
||||||
|
if(_surface->render())
|
||||||
|
{
|
||||||
|
mySurfaceStack.applyAll([](shared_ptr<FBSurface>& surface){
|
||||||
|
surface->render();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
_dirty = false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void Dialog::releaseFocus()
|
void Dialog::releaseFocus()
|
||||||
{
|
{
|
||||||
|
@ -291,6 +320,7 @@ void Dialog::addSurface(shared_ptr<FBSurface> surface)
|
||||||
mySurfaceStack.push(surface);
|
mySurfaceStack.push(surface);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int COUNT = 1;
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void Dialog::drawDialog()
|
void Dialog::drawDialog()
|
||||||
{
|
{
|
||||||
|
@ -299,63 +329,46 @@ void Dialog::drawDialog()
|
||||||
|
|
||||||
FBSurface& s = surface();
|
FBSurface& s = surface();
|
||||||
|
|
||||||
if(_dirty)
|
cerr << COUNT++ << " Dialog::drawDialog()\n";
|
||||||
|
// Dialog is still on top if e.g a ContextMenu is opened
|
||||||
|
bool onTop = parent().myDialogStack.top() == this
|
||||||
|
|| (parent().myDialogStack.get(parent().myDialogStack.size() - 2) == this
|
||||||
|
&& !parent().myDialogStack.top()->hasTitle());
|
||||||
|
|
||||||
|
if(_flags & WIDGET_CLEARBG)
|
||||||
{
|
{
|
||||||
// dialog is still on top if e.g a ContextMenu is opened
|
// cerr << "Dialog::drawDialog(): w = " << _w << ", h = " << _h << " @ " << &s << endl << endl;
|
||||||
bool onTop = parent().myDialogStack.top() == this
|
s.fillRect(_x, _y + _th, _w, _h - _th, onTop ? kDlgColor : kBGColorLo);
|
||||||
|| (parent().myDialogStack.get(parent().myDialogStack.size() - 2) == this
|
if(_th)
|
||||||
&& !parent().myDialogStack.top()->hasTitle());
|
|
||||||
|
|
||||||
if(_flags & WIDGET_CLEARBG)
|
|
||||||
{
|
{
|
||||||
// cerr << "Dialog::drawDialog(): w = " << _w << ", h = " << _h << " @ " << &s << endl << endl;
|
s.fillRect(_x, _y, _w, _th, onTop ? kColorTitleBar : kColorTitleBarLo);
|
||||||
s.fillRect(_x, _y + _th, _w, _h - _th, onTop ? kDlgColor : kBGColorLo);
|
s.drawString(_font, _title, _x + 10, _y + 2 + 1, _font.getStringWidth(_title),
|
||||||
if(_th)
|
onTop ? kColorTitleText : kColorTitleTextLo);
|
||||||
{
|
|
||||||
s.fillRect(_x, _y, _w, _th, onTop ? kColorTitleBar : kColorTitleBarLo);
|
|
||||||
s.drawString(_font, _title, _x + 10, _y + 2 + 1, _font.getStringWidth(_title),
|
|
||||||
onTop ? kColorTitleText : kColorTitleTextLo);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
}
|
||||||
s.invalidate();
|
else
|
||||||
if(_flags & WIDGET_BORDER)
|
s.invalidate();
|
||||||
s.frameRect(_x, _y, _w, _h, onTop ? kColor : kShadowColor);
|
if(_flags & WIDGET_BORDER)
|
||||||
|
s.frameRect(_x, _y, _w, _h, onTop ? kColor : kShadowColor);
|
||||||
|
|
||||||
// Make all child widget dirty
|
// Make all child widget dirty
|
||||||
Widget* w = _firstWidget;
|
Widget* w = _firstWidget;
|
||||||
Widget::setDirtyInChain(w);
|
Widget::setDirtyInChain(w);
|
||||||
|
|
||||||
// Draw all children
|
// Draw all children
|
||||||
w = _firstWidget;
|
w = _firstWidget;
|
||||||
while(w)
|
while(w)
|
||||||
{
|
{
|
||||||
w->draw();
|
w->draw();
|
||||||
w = w->_next;
|
w = w->_next;
|
||||||
}
|
|
||||||
|
|
||||||
// Draw outlines for focused widgets
|
|
||||||
// Don't change focus, since this will trigger lost and received
|
|
||||||
// focus events
|
|
||||||
if(_focusedWidget)
|
|
||||||
_focusedWidget = Widget::setFocusForChain(this, getFocusList(),
|
|
||||||
_focusedWidget, 0, false);
|
|
||||||
|
|
||||||
// Tell the surface(s) this area is dirty
|
|
||||||
s.setDirty();
|
|
||||||
|
|
||||||
_dirty = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Commit surface changes to screen; also render any extra surfaces
|
// Draw outlines for focused widgets
|
||||||
// Extra surfaces must be rendered afterwards, so they are drawn on top
|
// Don't change focus, since this will trigger lost and received
|
||||||
if(s.render())
|
// focus events
|
||||||
{
|
if(_focusedWidget)
|
||||||
mySurfaceStack.applyAll([](shared_ptr<FBSurface>& surface){
|
_focusedWidget = Widget::setFocusForChain(this, getFocusList(),
|
||||||
surface->setDirty();
|
_focusedWidget, 0, false);
|
||||||
surface->render();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
|
|
@ -51,8 +51,8 @@ class Dialog : public GuiObject
|
||||||
|
|
||||||
virtual ~Dialog();
|
virtual ~Dialog();
|
||||||
|
|
||||||
void open(bool refresh = true);
|
void open();
|
||||||
void close(bool refresh = true);
|
void close();
|
||||||
|
|
||||||
bool isVisible() const override { return _visible; }
|
bool isVisible() const override { return _visible; }
|
||||||
|
|
||||||
|
@ -62,6 +62,12 @@ class Dialog : public GuiObject
|
||||||
virtual void saveConfig() { }
|
virtual void saveConfig() { }
|
||||||
virtual void setDefaults() { }
|
virtual void setDefaults() { }
|
||||||
|
|
||||||
|
// A dialog being dirty indicates that its underlying surface needs to be
|
||||||
|
// redrawn and then re-rendered; this is taken care of in ::render()
|
||||||
|
void setDirty() override { _dirty = true; }
|
||||||
|
bool isDirty() const { return _dirty; }
|
||||||
|
bool render();
|
||||||
|
|
||||||
void addFocusWidget(Widget* w) override;
|
void addFocusWidget(Widget* w) override;
|
||||||
void addToFocusList(WidgetArray& list) override;
|
void addToFocusList(WidgetArray& list) override;
|
||||||
void addToFocusList(WidgetArray& list, TabWidget* w, int tabId);
|
void addToFocusList(WidgetArray& list, TabWidget* w, int tabId);
|
||||||
|
@ -190,6 +196,7 @@ class Dialog : public GuiObject
|
||||||
|
|
||||||
int _tabID;
|
int _tabID;
|
||||||
int _flags;
|
int _flags;
|
||||||
|
bool _dirty;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Following constructors and assignment operators not supported
|
// Following constructors and assignment operators not supported
|
||||||
|
|
|
@ -48,12 +48,12 @@ DialogContainer::~DialogContainer()
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void DialogContainer::updateTime(uInt64 time)
|
void DialogContainer::updateTime(uInt64 time)
|
||||||
{
|
{
|
||||||
// We only need millisecond precision
|
|
||||||
myTime = time / 1000;
|
|
||||||
|
|
||||||
if(myDialogStack.empty())
|
if(myDialogStack.empty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
// We only need millisecond precision
|
||||||
|
myTime = time / 1000;
|
||||||
|
|
||||||
// Check for pending continuous events and send them to the active dialog box
|
// Check for pending continuous events and send them to the active dialog box
|
||||||
Dialog* activeDialog = myDialogStack.top();
|
Dialog* activeDialog = myDialogStack.top();
|
||||||
|
|
||||||
|
@ -98,19 +98,31 @@ void DialogContainer::updateTime(uInt64 time)
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void DialogContainer::draw(bool full)
|
bool DialogContainer::draw(bool full)
|
||||||
{
|
{
|
||||||
// Draw all the dialogs on the stack when we want a full refresh
|
if(myDialogStack.empty())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Make the top dialog dirty if a full redraw is requested
|
||||||
if(full)
|
if(full)
|
||||||
{
|
myDialogStack.top()->setDirty();
|
||||||
myDialogStack.applyAll([](Dialog*& d){
|
|
||||||
d->center();
|
// If the top dialog is dirty, then all below it must be redrawn too
|
||||||
|
bool dirty = needsRedraw();
|
||||||
|
|
||||||
|
myDialogStack.applyAll([&](Dialog*& d){
|
||||||
|
if(dirty)
|
||||||
d->setDirty();
|
d->setDirty();
|
||||||
d->drawDialog();
|
full |= d->render();
|
||||||
});
|
});
|
||||||
}
|
|
||||||
else if(!myDialogStack.empty())
|
return full;
|
||||||
myDialogStack.top()->drawDialog();
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
bool DialogContainer::needsRedraw() const
|
||||||
|
{
|
||||||
|
return !myDialogStack.empty() ? myDialogStack.top()->isDirty() : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -121,14 +133,21 @@ void DialogContainer::addDialog(Dialog* d)
|
||||||
myOSystem.frameBuffer().showMessage(
|
myOSystem.frameBuffer().showMessage(
|
||||||
"Unable to show dialog box; FIX THE CODE");
|
"Unable to show dialog box; FIX THE CODE");
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
d->setDirty();
|
||||||
myDialogStack.push(d);
|
myDialogStack.push(d);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void DialogContainer::removeDialog()
|
void DialogContainer::removeDialog()
|
||||||
{
|
{
|
||||||
if(!myDialogStack.empty())
|
if(!myDialogStack.empty())
|
||||||
|
{
|
||||||
myDialogStack.pop();
|
myDialogStack.pop();
|
||||||
|
if(!myDialogStack.empty())
|
||||||
|
myDialogStack.top()->setDirty();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -136,9 +155,9 @@ void DialogContainer::reStack()
|
||||||
{
|
{
|
||||||
// Pop all items from the stack, and then add the base menu
|
// Pop all items from the stack, and then add the base menu
|
||||||
while(!myDialogStack.empty())
|
while(!myDialogStack.empty())
|
||||||
myDialogStack.top()->close(false); // don't force a refresh
|
myDialogStack.top()->close();
|
||||||
|
|
||||||
myBaseDialog->open(false); // don't force a refresh
|
myBaseDialog->open();
|
||||||
|
|
||||||
// Reset all continuous events
|
// Reset all continuous events
|
||||||
reset();
|
reset();
|
||||||
|
|
|
@ -121,8 +121,15 @@ class DialogContainer
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Draw the stack of menus (full indicates to redraw all items).
|
Draw the stack of menus (full indicates to redraw all items).
|
||||||
|
|
||||||
|
@return Answers whether any drawing actually occurred.
|
||||||
*/
|
*/
|
||||||
void draw(bool full = false);
|
bool draw(bool full = false);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Answers whether a full redraw is required.
|
||||||
|
*/
|
||||||
|
bool needsRedraw() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Reset dialog stack to the main configuration menu.
|
Reset dialog stack to the main configuration menu.
|
||||||
|
|
|
@ -274,8 +274,6 @@ void GlobalPropsDialog::setDefaults()
|
||||||
|
|
||||||
myHoldSelect->setState(false);
|
myHoldSelect->setState(false);
|
||||||
myHoldReset->setState(false);
|
myHoldReset->setState(false);
|
||||||
|
|
||||||
_dirty = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
|
|
@ -60,7 +60,6 @@ class GuiObject : public CommandReceiver
|
||||||
myParent(parent),
|
myParent(parent),
|
||||||
myDialog(dialog),
|
myDialog(dialog),
|
||||||
_x(x), _y(y), _w(w), _h(h),
|
_x(x), _y(y), _w(w), _h(h),
|
||||||
_dirty(false),
|
|
||||||
_firstWidget(nullptr) { }
|
_firstWidget(nullptr) { }
|
||||||
|
|
||||||
virtual ~GuiObject() = default;
|
virtual ~GuiObject() = default;
|
||||||
|
@ -69,8 +68,6 @@ class GuiObject : public CommandReceiver
|
||||||
DialogContainer& parent() const { return myParent; }
|
DialogContainer& parent() const { return myParent; }
|
||||||
Dialog& dialog() const { return myDialog; }
|
Dialog& dialog() const { return myDialog; }
|
||||||
|
|
||||||
void setDirty() { _dirty = true; }
|
|
||||||
|
|
||||||
virtual int getAbsX() const { return _x; }
|
virtual int getAbsX() const { return _x; }
|
||||||
virtual int getAbsY() const { return _y; }
|
virtual int getAbsY() const { return _y; }
|
||||||
virtual int getChildX() const { return getAbsX(); }
|
virtual int getChildX() const { return getAbsX(); }
|
||||||
|
@ -82,6 +79,7 @@ class GuiObject : public CommandReceiver
|
||||||
virtual void setHeight(int h) { _h = h; }
|
virtual void setHeight(int h) { _h = h; }
|
||||||
|
|
||||||
virtual bool isVisible() const = 0;
|
virtual bool isVisible() const = 0;
|
||||||
|
virtual void setDirty() = 0;
|
||||||
|
|
||||||
/** Add given widget(s) to the focus list */
|
/** Add given widget(s) to the focus list */
|
||||||
virtual void addFocusWidget(Widget* w) = 0;
|
virtual void addFocusWidget(Widget* w) = 0;
|
||||||
|
@ -107,7 +105,6 @@ class GuiObject : public CommandReceiver
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
int _x, _y, _w, _h;
|
int _x, _y, _w, _h;
|
||||||
bool _dirty;
|
|
||||||
|
|
||||||
Widget* _firstWidget;
|
Widget* _firstWidget;
|
||||||
WidgetArray _focusList;
|
WidgetArray _focusList;
|
||||||
|
|
|
@ -185,8 +185,6 @@ void HelpDialog::displayInfo()
|
||||||
myKey[i]->setLabel(myKeyStr[i]);
|
myKey[i]->setLabel(myKeyStr[i]);
|
||||||
myDesc[i]->setLabel(myDescStr[i]);
|
myDesc[i]->setLabel(myDescStr[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
_dirty = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
|
|
@ -399,8 +399,6 @@ void InputDialog::setDefaults()
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
_dirty = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
|
|
@ -178,8 +178,6 @@ void LauncherFilterDialog::saveConfig()
|
||||||
void LauncherFilterDialog::setDefaults()
|
void LauncherFilterDialog::setDefaults()
|
||||||
{
|
{
|
||||||
handleFileTypeChange("allroms");
|
handleFileTypeChange("allroms");
|
||||||
|
|
||||||
_dirty = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
|
|
@ -62,11 +62,10 @@ ListWidget::ListWidget(GuiObject* boss, const GUI::Font& font,
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void ListWidget::setSelected(int item)
|
void ListWidget::setSelected(int item)
|
||||||
{
|
{
|
||||||
|
setDirty();
|
||||||
|
|
||||||
if(item < 0 || item >= int(_list.size()))
|
if(item < 0 || item >= int(_list.size()))
|
||||||
{
|
|
||||||
setDirty(); // Simply redraw and exit
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
if(isEnabled())
|
if(isEnabled())
|
||||||
{
|
{
|
||||||
|
@ -180,6 +179,8 @@ void ListWidget::recalc()
|
||||||
|
|
||||||
// Reset to normal data entry
|
// Reset to normal data entry
|
||||||
abortEditMode();
|
abortEditMode();
|
||||||
|
|
||||||
|
setDirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
|
|
@ -279,8 +279,6 @@ void UIDialog::setDefaults()
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
_dirty = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
|
|
@ -551,8 +551,6 @@ void VideoDialog::setDefaults()
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_dirty = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -580,8 +578,6 @@ void VideoDialog::handleTVModeChange(NTSCFilter::Preset preset)
|
||||||
myTVScanLabel->setEnabled(scanenable);
|
myTVScanLabel->setEnabled(scanenable);
|
||||||
myTVScanIntense->setEnabled(scanenable);
|
myTVScanIntense->setEnabled(scanenable);
|
||||||
myTVScanInterpolate->setEnabled(scanenable);
|
myTVScanInterpolate->setEnabled(scanenable);
|
||||||
|
|
||||||
_dirty = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
|
|
@ -48,6 +48,8 @@ Widget::Widget(GuiObject* boss, const GUI::Font& font,
|
||||||
|
|
||||||
_fontWidth = _font.getMaxCharWidth();
|
_fontWidth = _font.getMaxCharWidth();
|
||||||
_fontHeight = _font.getLineHeight();
|
_fontHeight = _font.getLineHeight();
|
||||||
|
|
||||||
|
setDirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -59,14 +61,20 @@ Widget::~Widget()
|
||||||
_focusList.clear();
|
_focusList.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void Widget::setDirty()
|
||||||
|
{
|
||||||
|
// A widget being dirty indicates that its parent dialog is dirty
|
||||||
|
// So we inform the parent about it
|
||||||
|
_boss->dialog().setDirty();
|
||||||
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void Widget::draw()
|
void Widget::draw()
|
||||||
{
|
{
|
||||||
if(!_dirty || !isVisible() || !_boss->isVisible())
|
if(!isVisible() || !_boss->isVisible())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_dirty = false;
|
|
||||||
|
|
||||||
FBSurface& s = _boss->dialog().surface();
|
FBSurface& s = _boss->dialog().surface();
|
||||||
|
|
||||||
bool hasBorder = _flags & WIDGET_BORDER;
|
bool hasBorder = _flags & WIDGET_BORDER;
|
||||||
|
@ -119,9 +127,6 @@ void Widget::draw()
|
||||||
w->draw();
|
w->draw();
|
||||||
w = w->_next;
|
w = w->_next;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tell the framebuffer this area is dirty
|
|
||||||
s.setDirty();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -224,7 +229,6 @@ Widget* Widget::setFocusForChain(GuiObject* boss, WidgetArray& arr,
|
||||||
s.frameRect(x, y, w, h, kDlgColor);
|
s.frameRect(x, y, w, h, kDlgColor);
|
||||||
|
|
||||||
tmp->setDirty();
|
tmp->setDirty();
|
||||||
s.setDirty();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -278,7 +282,6 @@ Widget* Widget::setFocusForChain(GuiObject* boss, WidgetArray& arr,
|
||||||
s.frameRect(x, y, w, h, kWidFrameColor, FrameStyle::Dashed);
|
s.frameRect(x, y, w, h, kWidFrameColor, FrameStyle::Dashed);
|
||||||
|
|
||||||
tmp->setDirty();
|
tmp->setDirty();
|
||||||
s.setDirty();
|
|
||||||
|
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
|
@ -346,6 +349,8 @@ void StaticTextWidget::drawWidget(bool hilite)
|
||||||
FBSurface& s = _boss->dialog().surface();
|
FBSurface& s = _boss->dialog().surface();
|
||||||
s.drawString(_font, _label, _x, _y, _w,
|
s.drawString(_font, _label, _x, _y, _w,
|
||||||
isEnabled() ? _textcolor : uInt32(kColor), _align, 0, true, _shadowcolor);
|
isEnabled() ? _textcolor : uInt32(kColor), _align, 0, true, _shadowcolor);
|
||||||
|
|
||||||
|
_boss->dialog().setDirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -402,14 +407,12 @@ ButtonWidget::ButtonWidget(GuiObject* boss, const GUI::Font& font,
|
||||||
void ButtonWidget::handleMouseEntered()
|
void ButtonWidget::handleMouseEntered()
|
||||||
{
|
{
|
||||||
setFlags(WIDGET_HILITED);
|
setFlags(WIDGET_HILITED);
|
||||||
setDirty();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void ButtonWidget::handleMouseLeft()
|
void ButtonWidget::handleMouseLeft()
|
||||||
{
|
{
|
||||||
clearFlags(WIDGET_HILITED);
|
clearFlags(WIDGET_HILITED);
|
||||||
setDirty();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -446,6 +449,8 @@ void ButtonWidget::setBitmap(uInt32* bitmap, int bmw, int bmh)
|
||||||
_bmh = bmh;
|
_bmh = bmh;
|
||||||
_bmw = bmw;
|
_bmw = bmw;
|
||||||
_useBitmap = true;
|
_useBitmap = true;
|
||||||
|
|
||||||
|
setDirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -464,6 +469,8 @@ void ButtonWidget::drawWidget(bool hilite)
|
||||||
!isEnabled() ? /*hilite ? uInt32(kColor) :*/ uInt32(kBGColorLo) :
|
!isEnabled() ? /*hilite ? uInt32(kColor) :*/ uInt32(kBGColorLo) :
|
||||||
hilite ? _textcolorhi : _textcolor,
|
hilite ? _textcolorhi : _textcolor,
|
||||||
_bmw, _bmh);
|
_bmw, _bmh);
|
||||||
|
|
||||||
|
_boss->dialog().setDirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -584,6 +591,7 @@ void CheckboxWidget::setEditable(bool editable)
|
||||||
_bgcolor = kBGColorHi;
|
_bgcolor = kBGColorHi;
|
||||||
setFill(CheckboxWidget::Inactive);
|
setFill(CheckboxWidget::Inactive);
|
||||||
}
|
}
|
||||||
|
setDirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -604,6 +612,7 @@ void CheckboxWidget::setFill(FillType type)
|
||||||
_drawBox = false;
|
_drawBox = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
setDirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -634,6 +643,8 @@ void CheckboxWidget::drawWidget(bool hilite)
|
||||||
// Finally draw the label
|
// Finally draw the label
|
||||||
s.drawString(_font, _label, _x + 20, _y + _textY, _w,
|
s.drawString(_font, _label, _x + 20, _y + _textY, _w,
|
||||||
isEnabled() ? kTextColor : kColor);
|
isEnabled() ? kTextColor : kColor);
|
||||||
|
|
||||||
|
_boss->dialog().setDirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -697,18 +708,21 @@ void SliderWidget::setValue(int value)
|
||||||
void SliderWidget::setMinValue(int value)
|
void SliderWidget::setMinValue(int value)
|
||||||
{
|
{
|
||||||
_valueMin = value;
|
_valueMin = value;
|
||||||
|
setDirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void SliderWidget::setMaxValue(int value)
|
void SliderWidget::setMaxValue(int value)
|
||||||
{
|
{
|
||||||
_valueMax = value;
|
_valueMax = value;
|
||||||
|
setDirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void SliderWidget::setStepValue(int value)
|
void SliderWidget::setStepValue(int value)
|
||||||
{
|
{
|
||||||
_stepValue = value;
|
_stepValue = value;
|
||||||
|
setDirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -868,10 +882,12 @@ void SliderWidget::drawWidget(bool hilite)
|
||||||
if(_valueLabelWidth > 0)
|
if(_valueLabelWidth > 0)
|
||||||
s.drawString(_font, _valueLabel + _valueUnit, _x + _w - _valueLabelWidth, _y + 2,
|
s.drawString(_font, _valueLabel + _valueUnit, _x + _w - _valueLabelWidth, _y + 2,
|
||||||
_valueLabelWidth, isEnabled() ? kTextColor : kColor);
|
_valueLabelWidth, isEnabled() ? kTextColor : kColor);
|
||||||
|
|
||||||
|
_boss->dialog().setDirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
int SliderWidget::valueToPos(int value)
|
int SliderWidget::valueToPos(int value) const
|
||||||
{
|
{
|
||||||
if(value < _valueMin) value = _valueMin;
|
if(value < _valueMin) value = _valueMin;
|
||||||
else if(value > _valueMax) value = _valueMax;
|
else if(value > _valueMax) value = _valueMax;
|
||||||
|
@ -881,7 +897,7 @@ int SliderWidget::valueToPos(int value)
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
int SliderWidget::posToValue(int pos)
|
int SliderWidget::posToValue(int pos) const
|
||||||
{
|
{
|
||||||
int value = (pos) * (_valueMax - _valueMin) / (_w - _labelWidth - _valueLabelGap - _valueLabelWidth - 4) + _valueMin;
|
int value = (pos) * (_valueMax - _valueMin) / (_w - _labelWidth - _valueLabelGap - _valueLabelWidth - 4) + _valueMin;
|
||||||
|
|
||||||
|
|
|
@ -82,6 +82,7 @@ class Widget : public GuiObject
|
||||||
virtual bool handleJoyHat(int stick, int hat, JoyHat value) { return false; }
|
virtual bool handleJoyHat(int stick, int hat, JoyHat value) { return false; }
|
||||||
virtual bool handleEvent(Event::Type event) { return false; }
|
virtual bool handleEvent(Event::Type event) { return false; }
|
||||||
|
|
||||||
|
void setDirty() override;
|
||||||
void draw() override;
|
void draw() override;
|
||||||
void receivedFocus();
|
void receivedFocus();
|
||||||
void lostFocus();
|
void lostFocus();
|
||||||
|
@ -108,11 +109,11 @@ class Widget : public GuiObject
|
||||||
|
|
||||||
virtual const GUI::Font& font() const { return _font; }
|
virtual const GUI::Font& font() const { return _font; }
|
||||||
|
|
||||||
void setTextColor(uInt32 color) { _textcolor = color; }
|
void setTextColor(uInt32 color) { _textcolor = color; setDirty(); }
|
||||||
void setTextColorHi(uInt32 color) { _textcolorhi = color; }
|
void setTextColorHi(uInt32 color) { _textcolorhi = color; setDirty(); }
|
||||||
void setBGColor(uInt32 color) { _bgcolor = color; }
|
void setBGColor(uInt32 color) { _bgcolor = color; setDirty(); }
|
||||||
void setBGColorHi(uInt32 color) { _bgcolorhi = color; }
|
void setBGColorHi(uInt32 color) { _bgcolorhi = color; setDirty(); }
|
||||||
void setShadowColor(uInt32 color) { _shadowcolor = color; }
|
void setShadowColor(uInt32 color) { _shadowcolor = color; setDirty(); }
|
||||||
|
|
||||||
virtual void loadConfig() { }
|
virtual void loadConfig() { }
|
||||||
|
|
||||||
|
@ -187,7 +188,7 @@ class StaticTextWidget : public Widget
|
||||||
uInt32 shadowColor = 0);
|
uInt32 shadowColor = 0);
|
||||||
void setValue(int value);
|
void setValue(int value);
|
||||||
void setLabel(const string& label);
|
void setLabel(const string& label);
|
||||||
void setAlign(TextAlign align) { _align = align; }
|
void setAlign(TextAlign align) { _align = align; setDirty(); }
|
||||||
const string& getLabel() const { return _label; }
|
const string& getLabel() const { return _label; }
|
||||||
bool isEditable() const { return _editable; }
|
bool isEditable() const { return _editable; }
|
||||||
|
|
||||||
|
@ -341,8 +342,8 @@ class SliderWidget : public ButtonWidget
|
||||||
|
|
||||||
void drawWidget(bool hilite) override;
|
void drawWidget(bool hilite) override;
|
||||||
|
|
||||||
int valueToPos(int value);
|
int valueToPos(int value) const;
|
||||||
int posToValue(int pos);
|
int posToValue(int pos) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
int _value, _stepValue;
|
int _value, _stepValue;
|
||||||
|
|
Loading…
Reference in New Issue