Time Machine dialog now resizes correctly:

- in 2x mode, it takes up the maximum amount of space
- in larger modes, it takes up the same relative amount of space: ~80% width
This commit is contained in:
Stephen Anthony 2018-02-03 17:27:52 -03:30
parent f4db8e4816
commit 6c5bddcdf8
10 changed files with 88 additions and 19 deletions

View File

@ -48,6 +48,15 @@ class FixedStack
T pop() { return std::move(_stack[--_size]); }
uInt32 size() const { return _size; }
void replace(const T& oldItem, const T& newItem) {
for(uInt32 i = 0; i < _size; ++i) {
if(_stack[i] == oldItem) {
_stack[i] = newItem;
return;
}
}
}
// Apply the given function to every item in the stack
// We do it this way so the stack API can be preserved,
// and no access to individual elements is allowed outside

View File

@ -2181,6 +2181,7 @@ void EventHandler::setEventState(EventHandlerState state)
break;
case EventHandlerState::TIMEMACHINE:
myOSystem.timeMachine().requestResize();
myOverlay = &myOSystem.timeMachine();
enableTextEvents(true);
break;

View File

@ -27,6 +27,8 @@
#include "Dialog.hxx"
#include "Widget.hxx"
#include "TabWidget.hxx"
#include "Settings.hxx"
#include "Console.hxx"
#include "Vec.hxx"
/*
@ -728,16 +730,25 @@ Widget* Dialog::TabFocus::getNewFocus()
bool Dialog::getResizableBounds(uInt32& w, uInt32& h) const
{
const GUI::Rect& r = instance().frameBuffer().imageRect();
double scaleFactor = 0.8;
if(instance().hasConsole())
{
bool ntsc = instance().console().about().InitialFrameRate == "60";
uInt32 aspect = instance().settings().getInt(ntsc ?"tia.aspectn" : "tia.aspectp");
scaleFactor = aspect / 100.0;
}
if(r.width() <= FrameBuffer::kFBMinW || r.height() <= FrameBuffer::kFBMinH)
{
w = uInt32(0.8 * FrameBuffer::kTIAMinW) * 2;
w = uInt32(scaleFactor * FrameBuffer::kTIAMinW) * 2;
h = FrameBuffer::kTIAMinH * 2;
return false;
}
else
{
w = std::max(uInt32(0.8 * r.width()), uInt32(FrameBuffer::kFBMinW));
h = std::max(uInt32(0.8 * r.height()), uInt32(FrameBuffer::kFBMinH));
w = std::max(uInt32(scaleFactor * r.width()), uInt32(FrameBuffer::kFBMinW));
h = std::max(uInt32(scaleFactor * r.height()), uInt32(FrameBuffer::kFBMinH));
return true;
}
}

View File

@ -72,10 +72,11 @@ class Dialog : public GuiObject
/** Returns the base surface associated with this dialog. */
FBSurface& surface() const { return *_surface; }
/** Adds a surface to this dialog, which is rendered on top of the
base surface whenever the base surface is re-rendered. Since
the surface render() call will always occur in such a case, the
surface should call setVisible() to enable/disable its output.
/**
Adds a surface to this dialog, which is rendered on top of the
base surface whenever the base surface is re-rendered. Since
the surface render() call will always occur in such a case, the
surface should call setVisible() to enable/disable its output.
*/
void addSurface(shared_ptr<FBSurface> surface);
@ -83,6 +84,12 @@ class Dialog : public GuiObject
void clearFlags(int flags) { _flags &= ~flags; setDirty(); }
int getFlags() const { return _flags; }
/**
Determine the maximum bounds based on the given width and height.
Returns whether or not a large font can be used within these bounds.
*/
bool getResizableBounds(uInt32& w, uInt32& h) const;
protected:
virtual void draw() override { }
void releaseFocus() override;
@ -110,11 +117,6 @@ class Dialog : public GuiObject
void processCancelWithoutWidget(bool state) { _processCancel = state; }
/** Determine the maximum bounds based on the given width and height
Returns whether or not a large font can be used within these bounds.
*/
bool getResizableBounds(uInt32& w, uInt32& h) const;
private:
void buildCurrentFocusList(int tabID = -1);
bool handleNavEvent(Event::Type e);

View File

@ -119,7 +119,7 @@ void DialogContainer::addDialog(Dialog* d)
const GUI::Rect& r = myOSystem.frameBuffer().imageRect();
if(uInt32(d->getWidth()) > r.width() || uInt32(d->getHeight()) > r.height())
myOSystem.frameBuffer().showMessage(
"Unable to show dialog box; resize current window");
"Unable to show dialog box; FIX THE CODE");
else
myDialogStack.push(d);
}

View File

@ -134,6 +134,14 @@ class DialogContainer
*/
const Dialog* baseDialog() const { return myBaseDialog; }
/**
Inform the container that it should resize according to the current
screen dimensions. We make this virtual, since the container may or
may not choose to do a resize, and even if it does, *how* it does it
is determined by the specific container.
*/
virtual void requestResize() { }
private:
void reset();

View File

@ -22,8 +22,37 @@
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
TimeMachine::TimeMachine(OSystem& osystem)
: DialogContainer(osystem)
: DialogContainer(osystem),
myWidth(FrameBuffer::kFBMinW)
{
myBaseDialog = new TimeMachineDialog(myOSystem, *this,
FrameBuffer::kFBMinW, FrameBuffer::kFBMinH);
myBaseDialog = new TimeMachineDialog(myOSystem, *this, myWidth);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void TimeMachine::requestResize()
{
uInt32 w, h;
myBaseDialog->getResizableBounds(w, h);
// If dialog is too large for given area, we need to resize it
// Otherwise, make it 80% of the allowable width
int newWidth = myWidth;
if(w < FrameBuffer::kFBMinW)
newWidth = w;
else if(myBaseDialog->getWidth() != 0.8 * w)
newWidth = 0.8 * w;
// Only re-create when absolutely necessary
if(myWidth != newWidth)
{
myWidth = newWidth;
Dialog* oldPtr = myBaseDialog;
delete myBaseDialog;
myBaseDialog = new TimeMachineDialog(myOSystem, *this, myWidth);
Dialog* newPtr = myBaseDialog;
// Update the container stack; it may contain a reference to the old pointer
if(oldPtr != newPtr)
myDialogStack.replace(oldPtr, newPtr);
}
}

View File

@ -33,6 +33,15 @@ class TimeMachine : public DialogContainer
TimeMachine(OSystem& osystem);
virtual ~TimeMachine() = default;
/**
This dialog has an adjustable size. We need to make sure the
dialog can fit within the given bounds.
*/
void requestResize() override;
private:
int myWidth;
private:
// Following constructors and assignment operators not supported
TimeMachine() = delete;

View File

@ -36,7 +36,7 @@ using Common::Base;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
TimeMachineDialog::TimeMachineDialog(OSystem& osystem, DialogContainer& parent,
int max_w, int max_h)
int width)
: Dialog(osystem, parent)
{
const int BUTTON_W = 16, BUTTON_H = 14;
@ -136,7 +136,7 @@ TimeMachineDialog::TimeMachineDialog(OSystem& osystem, DialogContainer& parent,
int xpos, ypos;
// Set real dimensions
_w = 20 * (buttonWidth + BUTTON_GAP) + 20;
_w = width; // Parent determines our width (based on window size)
_h = V_BORDER * 2 + rowHeight + buttonHeight + 2;
this->clearFlags(WIDGET_CLEARBG); // does only work combined with blending (0..100)!

View File

@ -28,7 +28,7 @@ class TimeLineWidget;
class TimeMachineDialog : public Dialog
{
public:
TimeMachineDialog(OSystem& osystem, DialogContainer& parent, int max_w, int max_h);
TimeMachineDialog(OSystem& osystem, DialogContainer& parent, int width);
virtual ~TimeMachineDialog() = default;
private: