diff --git a/src/common/Stack.hxx b/src/common/Stack.hxx index f1ae48ae4..1bb10ceaa 100644 --- a/src/common/Stack.hxx +++ b/src/common/Stack.hxx @@ -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 diff --git a/src/emucore/EventHandler.cxx b/src/emucore/EventHandler.cxx index ed8721262..cb2c6873d 100644 --- a/src/emucore/EventHandler.cxx +++ b/src/emucore/EventHandler.cxx @@ -2181,6 +2181,7 @@ void EventHandler::setEventState(EventHandlerState state) break; case EventHandlerState::TIMEMACHINE: + myOSystem.timeMachine().requestResize(); myOverlay = &myOSystem.timeMachine(); enableTextEvents(true); break; diff --git a/src/gui/Dialog.cxx b/src/gui/Dialog.cxx index 93e632dd5..36b871bff 100644 --- a/src/gui/Dialog.cxx +++ b/src/gui/Dialog.cxx @@ -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; } } diff --git a/src/gui/Dialog.hxx b/src/gui/Dialog.hxx index 73804a0c6..5d29d90a4 100644 --- a/src/gui/Dialog.hxx +++ b/src/gui/Dialog.hxx @@ -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 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); diff --git a/src/gui/DialogContainer.cxx b/src/gui/DialogContainer.cxx index bbf17865f..f603c1fbd 100644 --- a/src/gui/DialogContainer.cxx +++ b/src/gui/DialogContainer.cxx @@ -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); } diff --git a/src/gui/DialogContainer.hxx b/src/gui/DialogContainer.hxx index 1e43e5c54..0d6b44f01 100644 --- a/src/gui/DialogContainer.hxx +++ b/src/gui/DialogContainer.hxx @@ -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(); diff --git a/src/gui/TimeMachine.cxx b/src/gui/TimeMachine.cxx index 75206039a..ec635d554 100644 --- a/src/gui/TimeMachine.cxx +++ b/src/gui/TimeMachine.cxx @@ -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); + } } diff --git a/src/gui/TimeMachine.hxx b/src/gui/TimeMachine.hxx index cde7e845c..c8f381bd9 100644 --- a/src/gui/TimeMachine.hxx +++ b/src/gui/TimeMachine.hxx @@ -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; diff --git a/src/gui/TimeMachineDialog.cxx b/src/gui/TimeMachineDialog.cxx index 281d46458..b0a2e172f 100644 --- a/src/gui/TimeMachineDialog.cxx +++ b/src/gui/TimeMachineDialog.cxx @@ -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)! diff --git a/src/gui/TimeMachineDialog.hxx b/src/gui/TimeMachineDialog.hxx index 30f2e7c8c..adeadfd8a 100644 --- a/src/gui/TimeMachineDialog.hxx +++ b/src/gui/TimeMachineDialog.hxx @@ -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: