mirror of https://github.com/stella-emu/stella.git
508 lines
17 KiB
C++
508 lines
17 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-2019 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.
|
|
//============================================================================
|
|
|
|
#include "bspf.hxx"
|
|
#include "BrowserDialog.hxx"
|
|
#include "Dialog.hxx"
|
|
#include "OSystem.hxx"
|
|
#include "FrameBuffer.hxx"
|
|
#include "FBSurface.hxx"
|
|
#include "ListWidget.hxx"
|
|
#include "PopUpWidget.hxx"
|
|
#include "ScrollBarWidget.hxx"
|
|
#include "EditTextWidget.hxx"
|
|
#include "Settings.hxx"
|
|
#include "TabWidget.hxx"
|
|
#include "Widget.hxx"
|
|
#include "Font.hxx"
|
|
#include "LauncherDialog.hxx"
|
|
#ifdef DEBUGGER_SUPPORT
|
|
#include "DebuggerDialog.hxx"
|
|
#endif
|
|
#include "UIDialog.hxx"
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
UIDialog::UIDialog(OSystem& osystem, DialogContainer& parent,
|
|
const GUI::Font& font, GuiObject* boss, int max_w, int max_h)
|
|
: Dialog(osystem, parent, font, "User interface settings"),
|
|
CommandSender(boss),
|
|
myFont(font),
|
|
myIsGlobal(boss != nullptr)
|
|
{
|
|
const GUI::Font& ifont = instance().frameBuffer().infoFont();
|
|
const int lineHeight = font.getLineHeight(),
|
|
fontWidth = font.getMaxCharWidth(),
|
|
fontHeight = font.getFontHeight(),
|
|
buttonHeight = font.getLineHeight() + 4;
|
|
|
|
const int VBORDER = 8;
|
|
const int HBORDER = 10;
|
|
const int INDENT = 16;
|
|
const int V_GAP = 4;
|
|
int xpos, ypos, tabID;
|
|
int lwidth, pwidth, bwidth;
|
|
WidgetArray wid;
|
|
VariantList items;
|
|
const Common::Size& ds = instance().frameBuffer().desktopSize();
|
|
|
|
// Set real dimensions
|
|
setSize(64 * fontWidth + HBORDER * 2, 11 * (lineHeight + V_GAP) + V_GAP * 9 + VBORDER + _th,
|
|
max_w, max_h);
|
|
|
|
// The tab widget
|
|
myTab = new TabWidget(this, font, 2, 4 + _th, _w - 2*2, _h - _th - buttonHeight - 20);
|
|
addTabWidget(myTab);
|
|
|
|
//////////////////////////////////////////////////////////
|
|
// 1) Misc. options
|
|
wid.clear();
|
|
tabID = myTab->addTab(" Look & Feel ");
|
|
lwidth = font.getStringWidth("Mouse wheel scroll ");
|
|
pwidth = font.getStringWidth("Right bottom");
|
|
xpos = HBORDER; ypos = VBORDER;
|
|
|
|
// UI Palette
|
|
ypos += 1;
|
|
items.clear();
|
|
VarList::push_back(items, "Standard", "standard");
|
|
VarList::push_back(items, "Classic", "classic");
|
|
VarList::push_back(items, "Light", "light");
|
|
myPalettePopup = new PopUpWidget(myTab, font, xpos, ypos, pwidth, lineHeight,
|
|
items, "Theme ", lwidth);
|
|
wid.push_back(myPalettePopup);
|
|
ypos += lineHeight + V_GAP;
|
|
|
|
// Dialog position
|
|
items.clear();
|
|
VarList::push_back(items, "Centered", 0);
|
|
VarList::push_back(items, "Left top", 1);
|
|
VarList::push_back(items, "Right top", 2);
|
|
VarList::push_back(items, "Right bottom", 3);
|
|
VarList::push_back(items, "Left bottom", 4);
|
|
myPositionPopup = new PopUpWidget(myTab, font, xpos, ypos, pwidth, lineHeight,
|
|
items, "Dialogs position ", lwidth);
|
|
wid.push_back(myPositionPopup);
|
|
ypos += lineHeight + V_GAP;
|
|
|
|
// Enable HiDPI mode
|
|
myHidpiWidget = new CheckboxWidget(myTab, font, xpos, ypos, "HiDPI mode (*)");
|
|
wid.push_back(myHidpiWidget);
|
|
ypos += lineHeight + V_GAP * 4;
|
|
|
|
// Delay between quick-selecting characters in ListWidget
|
|
int swidth = myPalettePopup->getWidth() - lwidth;
|
|
myListDelayPopup = new SliderWidget(myTab, font, xpos, ypos, swidth, lineHeight,
|
|
"List input delay ", 0, kListDelay,
|
|
font.getStringWidth("1 second"));
|
|
myListDelayPopup->setMinValue(0);
|
|
myListDelayPopup->setMaxValue(1000);
|
|
myListDelayPopup->setStepValue(50);
|
|
myListDelayPopup->setTickmarkInterval(5);
|
|
wid.push_back(myListDelayPopup);
|
|
ypos += lineHeight + V_GAP;
|
|
|
|
// Number of lines a mouse wheel will scroll
|
|
myWheelLinesPopup = new SliderWidget(myTab, font, xpos, ypos, swidth, lineHeight,
|
|
"Mouse wheel scroll ", 0, kMouseWheel,
|
|
font.getStringWidth("10 lines"));
|
|
myWheelLinesPopup->setMinValue(1);
|
|
myWheelLinesPopup->setMaxValue(10);
|
|
myWheelLinesPopup->setTickmarkInterval(3);
|
|
wid.push_back(myWheelLinesPopup);
|
|
|
|
// Add message concerning usage
|
|
ypos = myTab->getHeight() - 5 - fontHeight - ifont.getFontHeight() - 10;
|
|
lwidth = ifont.getStringWidth("(*) Change requires application restart");
|
|
new StaticTextWidget(myTab, ifont, xpos, ypos, std::min(lwidth, _w - 20), fontHeight,
|
|
"(*) Change requires application restart");
|
|
|
|
// Add items for tab 0
|
|
addToFocusList(wid, myTab, tabID);
|
|
|
|
//////////////////////////////////////////////////////////
|
|
// 2) Launcher options
|
|
wid.clear();
|
|
tabID = myTab->addTab(" Launcher ");
|
|
lwidth = font.getStringWidth("Launcher height ");
|
|
xpos = HBORDER; ypos = VBORDER;
|
|
|
|
// ROM path
|
|
bwidth = font.getStringWidth("ROM path" + ELLIPSIS) + 20 + 1;
|
|
ButtonWidget* romButton =
|
|
new ButtonWidget(myTab, font, xpos, ypos, bwidth, buttonHeight,
|
|
"ROM path" + ELLIPSIS, kChooseRomDirCmd);
|
|
wid.push_back(romButton);
|
|
xpos = romButton->getRight() + 8;
|
|
myRomPath = new EditTextWidget(myTab, font, xpos, ypos + 1,
|
|
_w - xpos - HBORDER - 2, lineHeight, "");
|
|
wid.push_back(myRomPath);
|
|
xpos = HBORDER;
|
|
ypos += lineHeight + V_GAP * 4;
|
|
|
|
// Launcher width and height
|
|
myLauncherWidthSlider = new SliderWidget(myTab, font, xpos, ypos, "Launcher width ",
|
|
lwidth, kLauncherSize, 6 * fontWidth, "px");
|
|
myLauncherWidthSlider->setMinValue(FBMinimum::Width);
|
|
myLauncherWidthSlider->setMaxValue(ds.w);
|
|
myLauncherWidthSlider->setStepValue(10);
|
|
// one tickmark every ~100 pixel
|
|
myLauncherWidthSlider->setTickmarkInterval((ds.w - FBMinimum::Width + 50) / 100);
|
|
wid.push_back(myLauncherWidthSlider);
|
|
ypos += lineHeight + V_GAP;
|
|
|
|
myLauncherHeightSlider = new SliderWidget(myTab, font, xpos, ypos, "Launcher height ",
|
|
lwidth, kLauncherSize, 6 * fontWidth, "px");
|
|
myLauncherHeightSlider->setMinValue(FBMinimum::Height);
|
|
myLauncherHeightSlider->setMaxValue(ds.h);
|
|
myLauncherHeightSlider->setStepValue(10);
|
|
// one tickmark every ~100 pixel
|
|
myLauncherHeightSlider->setTickmarkInterval((ds.h - FBMinimum::Height + 50) / 100);
|
|
wid.push_back(myLauncherHeightSlider);
|
|
ypos += lineHeight + V_GAP;
|
|
|
|
// Launcher font
|
|
pwidth = font.getStringWidth("2x (1000x720)");
|
|
items.clear();
|
|
VarList::push_back(items, "Small", "small");
|
|
VarList::push_back(items, "Medium", "medium");
|
|
VarList::push_back(items, "Large", "large");
|
|
myLauncherFontPopup =
|
|
new PopUpWidget(myTab, font, xpos, ypos + 1, pwidth, lineHeight, items,
|
|
"Launcher font ", lwidth);
|
|
wid.push_back(myLauncherFontPopup);
|
|
ypos += lineHeight + V_GAP * 4;
|
|
|
|
// ROM launcher info/snapshot viewer
|
|
items.clear();
|
|
VarList::push_back(items, "Off", "0");
|
|
VarList::push_back(items, "1x (640x480) ", "1");
|
|
VarList::push_back(items, "2x (1000x720)", "2");
|
|
myRomViewerPopup =
|
|
new PopUpWidget(myTab, font, xpos, ypos + 1, pwidth, lineHeight, items,
|
|
"ROM info viewer ", lwidth, kRomViewer);
|
|
wid.push_back(myRomViewerPopup);
|
|
ypos += lineHeight + V_GAP;
|
|
|
|
// Snapshot path (load files)
|
|
xpos = HBORDER + INDENT;
|
|
bwidth = font.getStringWidth("Image path" + ELLIPSIS) + 20 + 1;
|
|
myOpenBrowserButton = new ButtonWidget(myTab, font, xpos, ypos, bwidth, buttonHeight,
|
|
"Image path" + ELLIPSIS, kChooseSnapLoadDirCmd);
|
|
wid.push_back(myOpenBrowserButton);
|
|
//ypos += lineHeight + 4;
|
|
xpos = myOpenBrowserButton->getRight() + 8;
|
|
|
|
mySnapLoadPath = new EditTextWidget(myTab, font, xpos, ypos + 1,
|
|
_w - xpos - HBORDER - 2, lineHeight, "");
|
|
wid.push_back(mySnapLoadPath);
|
|
ypos += lineHeight + V_GAP * 4;
|
|
|
|
// Exit to Launcher
|
|
xpos = HBORDER;
|
|
myLauncherExitWidget = new CheckboxWidget(myTab, font, xpos + 1, ypos, "Always exit to Launcher");
|
|
wid.push_back(myLauncherExitWidget);
|
|
|
|
// Add message concerning usage
|
|
xpos = HBORDER;
|
|
ypos = myTab->getHeight() - 5 - fontHeight - ifont.getFontHeight() - 10;
|
|
lwidth = ifont.getStringWidth("(*) Changes require application restart");
|
|
new StaticTextWidget(myTab, ifont, xpos, ypos, std::min(lwidth, _w - 20), fontHeight,
|
|
"(*) Changes require application restart");
|
|
|
|
// Add items for tab 1
|
|
addToFocusList(wid, myTab, tabID);
|
|
|
|
// All ROM settings are disabled while in game mode
|
|
if(!myIsGlobal)
|
|
{
|
|
romButton->clearFlags(Widget::FLAG_ENABLED);
|
|
myRomPath->setEditable(false);
|
|
}
|
|
|
|
// Activate the first tab
|
|
myTab->setActiveTab(0);
|
|
|
|
// Add Defaults, OK and Cancel buttons
|
|
wid.clear();
|
|
addDefaultsOKCancelBGroup(wid, font);
|
|
addBGroupToFocusList(wid);
|
|
}
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
UIDialog::~UIDialog()
|
|
{
|
|
}
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
void UIDialog::loadConfig()
|
|
{
|
|
const Settings& settings = instance().settings();
|
|
|
|
// ROM path
|
|
myRomPath->setText(settings.getString("romdir"));
|
|
|
|
// Launcher size
|
|
const Common::Size& ls = settings.getSize("launcherres");
|
|
uInt32 w = ls.w, h = ls.h;
|
|
|
|
w = std::max(w, FBMinimum::Width);
|
|
h = std::max(h, FBMinimum::Height);
|
|
w = std::min(w, instance().frameBuffer().desktopSize().w);
|
|
h = std::min(h, instance().frameBuffer().desktopSize().h);
|
|
|
|
myLauncherWidthSlider->setValue(w);
|
|
myLauncherHeightSlider->setValue(h);
|
|
|
|
// Launcher font
|
|
const string& font = settings.getString("launcherfont");
|
|
myLauncherFontPopup->setSelected(font, "medium");
|
|
|
|
// ROM launcher info viewer
|
|
const string& viewer = settings.getString("romviewer");
|
|
myRomViewerPopup->setSelected(viewer, "0");
|
|
|
|
// ROM launcher info viewer image path
|
|
mySnapLoadPath->setText(settings.getString("snaploaddir"));
|
|
|
|
// Exit to launcher
|
|
bool exitlauncher = settings.getBool("exitlauncher");
|
|
myLauncherExitWidget->setState(exitlauncher);
|
|
|
|
// UI palette
|
|
const string& pal = settings.getString("uipalette");
|
|
myPalettePopup->setSelected(pal, "standard");
|
|
|
|
// Enable HiDPI mode
|
|
if (!instance().frameBuffer().hidpiAllowed())
|
|
{
|
|
myHidpiWidget->setState(false);
|
|
myHidpiWidget->setEnabled(false);
|
|
}
|
|
else
|
|
{
|
|
myHidpiWidget->setState(settings.getBool("hidpi"));
|
|
}
|
|
|
|
// Dialog position
|
|
myPositionPopup->setSelected(settings.getString("dialogpos"), "0");
|
|
|
|
// Listwidget quick delay
|
|
int delay = settings.getInt("listdelay");
|
|
myListDelayPopup->setValue(delay);
|
|
|
|
// Mouse wheel lines
|
|
int mw = settings.getInt("mwheel");
|
|
myWheelLinesPopup->setValue(mw);
|
|
|
|
handleRomViewer();
|
|
|
|
myTab->loadConfig();
|
|
}
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
void UIDialog::saveConfig()
|
|
{
|
|
Settings& settings = instance().settings();
|
|
|
|
// ROM path
|
|
settings.setValue("romdir", myRomPath->getText());
|
|
|
|
// Launcher size
|
|
settings.setValue("launcherres",
|
|
Common::Size(myLauncherWidthSlider->getValue(),
|
|
myLauncherHeightSlider->getValue()));
|
|
|
|
// Launcher font
|
|
settings.setValue("launcherfont",
|
|
myLauncherFontPopup->getSelectedTag().toString());
|
|
|
|
// ROM launcher info viewer
|
|
settings.setValue("romviewer",
|
|
myRomViewerPopup->getSelectedTag().toString());
|
|
|
|
// ROM launcher info viewer image path
|
|
settings.setValue("snaploaddir", mySnapLoadPath->getText());
|
|
|
|
// Exit to Launcher
|
|
settings.setValue("exitlauncher", myLauncherExitWidget->getState());
|
|
|
|
// UI palette
|
|
settings.setValue("uipalette",
|
|
myPalettePopup->getSelectedTag().toString());
|
|
instance().frameBuffer().setUIPalette();
|
|
|
|
// Enable HiDPI mode
|
|
settings.setValue("hidpi", myHidpiWidget->getState());
|
|
|
|
// Dialog position
|
|
settings.setValue("dialogpos", myPositionPopup->getSelectedTag().toString());
|
|
|
|
// Listwidget quick delay
|
|
settings.setValue("listdelay", myListDelayPopup->getValue());
|
|
ListWidget::setQuickSelectDelay(myListDelayPopup->getValue());
|
|
|
|
// Mouse wheel lines
|
|
settings.setValue("mwheel", myWheelLinesPopup->getValue());
|
|
ScrollBarWidget::setWheelLines(myWheelLinesPopup->getValue());
|
|
|
|
// Flush changes to disk and inform the OSystem
|
|
instance().saveConfig();
|
|
instance().setConfigPaths();
|
|
}
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
void UIDialog::setDefaults()
|
|
{
|
|
switch(myTab->getActiveTab())
|
|
{
|
|
case 0: // Misc. options
|
|
myPalettePopup->setSelected("standard");
|
|
myHidpiWidget->setState(false);
|
|
myPositionPopup->setSelected("0");
|
|
myListDelayPopup->setValue(300);
|
|
myWheelLinesPopup->setValue(4);
|
|
break;
|
|
case 1: // Launcher options
|
|
{
|
|
FilesystemNode node("~");
|
|
myRomPath->setText(node.getShortPath());
|
|
uInt32 w = std::min(instance().frameBuffer().desktopSize().w, 900u);
|
|
uInt32 h = std::min(instance().frameBuffer().desktopSize().h, 600u);
|
|
myLauncherWidthSlider->setValue(w);
|
|
myLauncherHeightSlider->setValue(h);
|
|
myLauncherFontPopup->setSelected("medium", "");
|
|
myRomViewerPopup->setSelected("1", "");
|
|
mySnapLoadPath->setText(instance().defaultLoadDir());
|
|
myLauncherExitWidget->setState(false);
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
void UIDialog::handleCommand(CommandSender* sender, int cmd, int data, int id)
|
|
{
|
|
switch(cmd)
|
|
{
|
|
case GuiObject::kOKCmd:
|
|
saveConfig();
|
|
close();
|
|
if(myIsGlobal) // Let the boss know romdir has changed
|
|
sendCommand(LauncherDialog::kRomDirChosenCmd, 0, 0);
|
|
break;
|
|
|
|
case GuiObject::kDefaultsCmd:
|
|
setDefaults();
|
|
break;
|
|
|
|
case kListDelay:
|
|
if(myListDelayPopup->getValue() == 0)
|
|
{
|
|
myListDelayPopup->setValueLabel("Off");
|
|
myListDelayPopup->setValueUnit("");
|
|
}
|
|
else if(myListDelayPopup->getValue() == 1000)
|
|
{
|
|
myListDelayPopup->setValueLabel("1");
|
|
myListDelayPopup->setValueUnit(" second");
|
|
}
|
|
else
|
|
{
|
|
myListDelayPopup->setValueUnit(" ms");
|
|
}
|
|
break;
|
|
case kMouseWheel:
|
|
if(myWheelLinesPopup->getValue() == 1)
|
|
myWheelLinesPopup->setValueUnit(" line");
|
|
else
|
|
myWheelLinesPopup->setValueUnit(" lines");
|
|
break;
|
|
|
|
case kChooseRomDirCmd:
|
|
// This dialog is resizable under certain conditions, so we need
|
|
// to re-create it as necessary
|
|
createBrowser("Select ROM directory");
|
|
myBrowser->show(myRomPath->getText(),
|
|
BrowserDialog::Directories, LauncherDialog::kRomDirChosenCmd);
|
|
break;
|
|
|
|
case LauncherDialog::kRomDirChosenCmd:
|
|
myRomPath->setText(myBrowser->getResult().getShortPath());
|
|
break;
|
|
|
|
case kLauncherSize:
|
|
case kRomViewer:
|
|
handleRomViewer();
|
|
break;
|
|
|
|
case kChooseSnapLoadDirCmd:
|
|
// This dialog is resizable under certain conditions, so we need
|
|
// to re-create it as necessary
|
|
createBrowser("Select snapshot load directory");
|
|
myBrowser->show(mySnapLoadPath->getText(),
|
|
BrowserDialog::Directories, kSnapLoadDirChosenCmd);
|
|
break;
|
|
|
|
case kSnapLoadDirChosenCmd:
|
|
mySnapLoadPath->setText(myBrowser->getResult().getShortPath());
|
|
break;
|
|
|
|
default:
|
|
Dialog::handleCommand(sender, cmd, data, 0);
|
|
break;
|
|
}
|
|
}
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
void UIDialog::handleRomViewer()
|
|
{
|
|
//string size = myRomViewerPopup->getSelectedName();
|
|
bool enable = myRomViewerPopup->getSelectedName() != "Off";
|
|
VariantList items;
|
|
|
|
myOpenBrowserButton->setEnabled(enable);
|
|
mySnapLoadPath->setEnabled(enable);
|
|
|
|
/*items.clear();
|
|
VarList::push_back(items, "Off", "0");
|
|
VarList::push_back(items, "1x (640x480) ", "1");
|
|
if(myLauncherWidthSlider->getValue() >= 1000 &&
|
|
myLauncherHeightSlider->getValue() >= 760)
|
|
{
|
|
VarList::push_back(items, "2x (1000x720)", "2");
|
|
}
|
|
myRomViewerPopup->addItems(items);
|
|
|
|
//myRomViewerPopup->setSelected("1x(640x480) ");*/
|
|
}
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
void UIDialog::createBrowser(const string& title)
|
|
{
|
|
uInt32 w = 0, h = 0;
|
|
getDynamicBounds(w, h);
|
|
|
|
// Create file browser dialog
|
|
if(!myBrowser || uInt32(myBrowser->getWidth()) != w ||
|
|
uInt32(myBrowser->getHeight()) != h)
|
|
myBrowser = make_unique<BrowserDialog>(this, myFont, w, h, title);
|
|
else
|
|
myBrowser->setTitle(title);
|
|
}
|