mirror of https://github.com/stella-emu/stella.git
248 lines
8.8 KiB
C++
248 lines
8.8 KiB
C++
//============================================================================
|
|
//
|
|
// SSSS tt lll lll
|
|
// SS SS tt ll ll
|
|
// SS tttttt eeee ll ll aaaa
|
|
// SSSS tt ee ee ll ll aa
|
|
// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
|
|
// SS SS tt ee ll ll aa aa
|
|
// SSSS ttt eeeee llll llll aaaaa
|
|
//
|
|
// Copyright (c) 1995-2020 by Bradford W. Mott, Stephen Anthony
|
|
// and the Stella Team
|
|
//
|
|
// See the file "License.txt" for information on usage and redistribution of
|
|
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
|
//
|
|
// Based on code from ScummVM - Scumm Interpreter
|
|
// Copyright (C) 2002-2004 The ScummVM project
|
|
//============================================================================
|
|
|
|
#ifndef DIALOG_HXX
|
|
#define DIALOG_HXX
|
|
|
|
class FBSurface;
|
|
class OSystem;
|
|
class DialogContainer;
|
|
class TabWidget;
|
|
class CommandSender;
|
|
|
|
#include "Stack.hxx"
|
|
#include "Widget.hxx"
|
|
#include "GuiObject.hxx"
|
|
#include "StellaKeys.hxx"
|
|
#include "EventHandlerConstants.hxx"
|
|
#include "bspf.hxx"
|
|
|
|
/**
|
|
This is the base class for all dialog boxes.
|
|
|
|
@author Stephen Anthony
|
|
*/
|
|
class Dialog : public GuiObject
|
|
{
|
|
friend class DialogContainer;
|
|
|
|
public:
|
|
Dialog(OSystem& instance, DialogContainer& parent,
|
|
int x = 0, int y = 0, int w = 0, int h = 0);
|
|
Dialog(OSystem& instance, DialogContainer& parent, const GUI::Font& font,
|
|
const string& title = "", int x = 0, int y = 0, int w = 0, int h = 0);
|
|
~Dialog() override;
|
|
|
|
void open();
|
|
void close();
|
|
|
|
bool isVisible() const override { return _visible; }
|
|
bool isOnTop() const { return _onTop; }
|
|
|
|
virtual void center();
|
|
virtual void drawDialog();
|
|
virtual void loadConfig() { }
|
|
virtual void saveConfig() { }
|
|
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;
|
|
bool isDirty() override; // TODO: remove
|
|
bool isChainDirty() const override;
|
|
void redraw();
|
|
void render();
|
|
|
|
void addFocusWidget(Widget* w) override;
|
|
void addToFocusList(WidgetArray& list) override;
|
|
void addToFocusList(WidgetArray& list, TabWidget* w, int tabId);
|
|
void addBGroupToFocusList(WidgetArray& list) { _buttonGroup = list; }
|
|
void addTabWidget(TabWidget* w);
|
|
void addDefaultWidget(Widget* w) { _defaultWidget = w; }
|
|
void addOKWidget(Widget* w) { _okWidget = w; }
|
|
void addCancelWidget(Widget* w) { _cancelWidget = w; }
|
|
void setFocus(Widget* w);
|
|
|
|
/** 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.
|
|
*/
|
|
void addSurface(const shared_ptr<FBSurface>& surface);
|
|
|
|
void setTitle(const string& title);
|
|
bool hasTitle() { return !_title.empty(); }
|
|
|
|
/**
|
|
Determine the maximum width/height of a dialog based on the minimum
|
|
allowable bounds, also taking into account the current window size.
|
|
Currently scales the width/height to 95% of allowable area when possible.
|
|
|
|
NOTE: This method is meant to be used for dynamic, resizeable dialogs.
|
|
That is, those that can change size during a program run, and
|
|
*have* to take the current window size into account.
|
|
|
|
@param w The resulting width to use for the dialog
|
|
@param h The resulting height to use for the dialog
|
|
|
|
@return True if the dialog fits in the current window (scaled to 90%)
|
|
False if the dialog is smaller than the current window, and
|
|
has to be scaled down
|
|
*/
|
|
bool getDynamicBounds(uInt32& w, uInt32& h) const;
|
|
|
|
/**
|
|
Checks if the dialogs fits into the actual sizes.
|
|
|
|
@param w The resulting width to use for the dialog
|
|
@param h The resulting height to use for the dialog
|
|
|
|
@return True if the dialog should be resized
|
|
*/
|
|
bool shouldResize(uInt32& w, uInt32& h) const;
|
|
|
|
protected:
|
|
void draw() override { }
|
|
void releaseFocus() override;
|
|
|
|
virtual void handleText(char text);
|
|
virtual void handleKeyDown(StellaKey key, StellaMod modifiers, bool repeated = false);
|
|
virtual void handleKeyUp(StellaKey key, StellaMod modifiers);
|
|
virtual void handleMouseDown(int x, int y, MouseButton b, int clickCount);
|
|
virtual void handleMouseUp(int x, int y, MouseButton b, int clickCount);
|
|
virtual void handleMouseWheel(int x, int y, int direction);
|
|
virtual void handleMouseMoved(int x, int y);
|
|
virtual bool handleMouseClicks(int x, int y, MouseButton b);
|
|
virtual void handleJoyDown(int stick, int button, bool longPress = false);
|
|
virtual void handleJoyUp(int stick, int button);
|
|
virtual void handleJoyAxis(int stick, JoyAxis axis, JoyDir adir, int button = JOY_CTRL_NONE);
|
|
virtual bool handleJoyHat(int stick, int hat, JoyHatDir hdir, int button = JOY_CTRL_NONE);
|
|
void handleCommand(CommandSender* sender, int cmd, int data, int id) override;
|
|
virtual Event::Type getJoyAxisEvent(int stick, JoyAxis axis, JoyDir adir, int button);
|
|
|
|
Widget* findWidget(int x, int y) const; // Find the widget at pos x,y if any
|
|
|
|
|
|
void addOKBGroup(WidgetArray& wid, const GUI::Font& font,
|
|
const string& okText = "OK",
|
|
int buttonWidth = 0);
|
|
|
|
void addOKCancelBGroup(WidgetArray& wid, const GUI::Font& font,
|
|
const string& okText = "OK",
|
|
const string& cancelText = "Cancel",
|
|
bool focusOKButton = true,
|
|
int buttonWidth = 0);
|
|
|
|
void addDefaultsOKCancelBGroup(WidgetArray& wid, const GUI::Font& font,
|
|
const string& okText = "OK",
|
|
const string& cancelText = "Cancel",
|
|
const string& defaultsText = "Defaults",
|
|
bool focusOKButton = true);
|
|
|
|
// NOTE: This method, and the three above it, are due to be refactored at some
|
|
// point, since the parameter list is kind of getting ridiculous
|
|
void addDefaultsExtraOKCancelBGroup(WidgetArray& wid, const GUI::Font& font,
|
|
const string& extraText, int extraCmd,
|
|
const string& okText = "OK",
|
|
const string& cancelText = "Cancel",
|
|
const string& defaultsText = "Defaults",
|
|
bool focusOKButton = true);
|
|
|
|
void processCancelWithoutWidget(bool state = true) { _processCancel = state; }
|
|
virtual void processCancel() { close(); }
|
|
|
|
/** Define the size (allowed) for the dialog. */
|
|
void setSize(uInt32 w, uInt32 h, uInt32 max_w, uInt32 max_h);
|
|
void positionAt(uInt32 pos);
|
|
|
|
virtual bool repeatEnabled() { return true; }
|
|
|
|
private:
|
|
void buildCurrentFocusList(int tabID = -1);
|
|
bool handleNavEvent(Event::Type e, bool repeated = false);
|
|
void getTabIdForWidget(Widget* w);
|
|
bool cycleTab(int direction);
|
|
|
|
protected:
|
|
const GUI::Font& _font;
|
|
|
|
Widget* _mouseWidget{nullptr};
|
|
Widget* _focusedWidget{nullptr};
|
|
Widget* _dragWidget{nullptr};
|
|
Widget* _defaultWidget{nullptr};
|
|
Widget* _okWidget{nullptr};
|
|
Widget* _cancelWidget{nullptr};
|
|
|
|
bool _visible{false};
|
|
bool _onTop{true};
|
|
bool _processCancel{false};
|
|
string _title;
|
|
int _th{0};
|
|
int _layer{0};
|
|
|
|
Common::FixedStack<shared_ptr<FBSurface>> mySurfaceStack;
|
|
|
|
private:
|
|
struct Focus {
|
|
Widget* widget{nullptr};
|
|
WidgetArray list;
|
|
|
|
explicit Focus(Widget* w = nullptr) : widget(w) { }
|
|
};
|
|
using FocusList = vector<Focus>;
|
|
|
|
struct TabFocus {
|
|
TabWidget* widget{nullptr};
|
|
FocusList focus;
|
|
uInt32 currentTab{0};
|
|
|
|
explicit TabFocus(TabWidget* w = nullptr) : widget(w) { }
|
|
|
|
void appendFocusList(WidgetArray& list);
|
|
void saveCurrentFocus(Widget* w);
|
|
Widget* getNewFocus();
|
|
};
|
|
using TabFocusList = vector<TabFocus>;
|
|
|
|
Focus _myFocus; // focus for base dialog
|
|
TabFocusList _myTabList; // focus for each tab (if any)
|
|
|
|
WidgetArray _buttonGroup;
|
|
shared_ptr<FBSurface> _surface;
|
|
|
|
int _tabID{0};
|
|
uInt32 _max_w{0}; // maximum wanted width
|
|
uInt32 _max_h{0}; // maximum wanted height
|
|
|
|
private:
|
|
// Following constructors and assignment operators not supported
|
|
Dialog() = delete;
|
|
Dialog(const Dialog&) = delete;
|
|
Dialog(Dialog&&) = delete;
|
|
Dialog& operator=(const Dialog&) = delete;
|
|
Dialog& operator=(Dialog&&) = delete;
|
|
};
|
|
|
|
#endif
|