diff --git a/Changes.txt b/Changes.txt index abb9c4ea8..bd6306930 100644 --- a/Changes.txt +++ b/Changes.txt @@ -19,6 +19,8 @@ * Fixed bug with aspect correction and fullscreen mode; snapshots from such a mode are now pixel-exact. + * Made serial port used for an AtariVox-USB adaptor editable. (TODO: Doc) + -Have fun! diff --git a/src/emucore/OSystem.cxx b/src/emucore/OSystem.cxx index d7cc5e602..39b83384d 100644 --- a/src/emucore/OSystem.cxx +++ b/src/emucore/OSystem.cxx @@ -186,11 +186,12 @@ bool OSystem::create() myPropSet->load(myPropertiesFile); // Detect serial port for AtariVox-USB - // If a previously set port is available, use it; + // If a previously set port is defined, use it; // otherwise use the first one found (if any) - StringList ports = MediaFactory::createSerialPort()->portNames(); - bool oldPortFound = BSPF::contains(ports, mySettings->getString("avoxport")); - if(!oldPortFound && ports.size() > 0) + const string& avoxport = mySettings->getString("avoxport"); + const StringList ports = MediaFactory::createSerialPort()->portNames(); + + if(avoxport.empty() && ports.size() > 0) mySettings->setValue("avoxport", ports[0]); return true; diff --git a/src/gui/GameInfoDialog.cxx b/src/gui/GameInfoDialog.cxx index 7e6e247f2..5a3c4b1b5 100644 --- a/src/gui/GameInfoDialog.cxx +++ b/src/gui/GameInfoDialog.cxx @@ -93,7 +93,7 @@ GameInfoDialog::GameInfoDialog( for(uInt32 i = 0; i < uInt32(Bankswitch::Type::NumSchemes); ++i) VarList::push_back(items, Bankswitch::BSList[i].desc, Bankswitch::BSList[i].name); myBSType = new PopUpWidget(myTab, font, t->getRight() + fontWidth, ypos, - pwidth, lineHeight, items, ""); + pwidth, lineHeight, items); wid.push_back(myBSType); ypos += lineHeight + VGAP; @@ -105,7 +105,7 @@ GameInfoDialog::GameInfoDialog( myStartBankLabel = new StaticTextWidget(myTab, font, HBORDER, ypos + 1, "Start bank (*) "); items.clear(); myStartBank = new PopUpWidget(myTab, font, myStartBankLabel->getRight(), ypos, - font.getStringWidth("AUTO"), lineHeight, items, "", 0, 0); + font.getStringWidth("AUTO"), lineHeight, items); wid.push_back(myStartBank); ypos += lineHeight + VGAP * 4; @@ -120,7 +120,7 @@ GameInfoDialog::GameInfoDialog( VarList::push_back(items, "PAL60", "PAL60"); VarList::push_back(items, "SECAM60", "SECAM60"); myFormat = new PopUpWidget(myTab, font, t->getRight(), ypos, - pwidth, lineHeight, items, "", 0, 0); + pwidth, lineHeight, items); wid.push_back(myFormat); myFormatDetected = new StaticTextWidget(myTab, ifont, myFormat->getRight() + fontWidth, ypos + 4, diff --git a/src/gui/InputDialog.cxx b/src/gui/InputDialog.cxx index cbb76e20c..e48a1fe61 100644 --- a/src/gui/InputDialog.cxx +++ b/src/gui/InputDialog.cxx @@ -224,10 +224,9 @@ void InputDialog::addDevicePortTab() ypos += lineHeight + VGAP * 3; lwidth = _font.getStringWidth("AtariVox serial port "); fwidth = _w - HBORDER * 2 - 2 - lwidth - PopUpWidget::dropDownWidth(_font); - VariantList items; - VarList::push_back(items, "None detected", ""); - myAVoxPort = new PopUpWidget(myTab, _font, HBORDER, ypos, fwidth, lineHeight, items, + myAVoxPort = new PopUpWidget(myTab, _font, HBORDER, ypos, fwidth, lineHeight, EmptyVarList, "AtariVox serial port ", lwidth, kCursorStateChanged); + myAVoxPort->setEditable(true); wid.push_back(myAVoxPort); // Add items for virtual device ports @@ -362,13 +361,16 @@ void InputDialog::loadConfig() // AtariVox serial port const string& avoxport = settings.getString("avoxport"); - StringList ports = MediaFactory::createSerialPort()->portNames(); - if(avoxport != EmptyString && !BSPF::contains(ports, avoxport)) - ports.push_back(avoxport); + const StringList ports = MediaFactory::createSerialPort()->portNames(); VariantList items; - VarList::push_back(items, "None detected", ""); + for(const auto& port: ports) - VarList::push_back(items, port, port); + VarList::push_back(items, port); + if(avoxport != EmptyString && !BSPF::contains(ports, avoxport)) + VarList::push_back(items, avoxport, avoxport); + if(items.size() == 0) + VarList::push_back(items, "None detected"); + myAVoxPort->addItems(items); myAVoxPort->setSelected(avoxport); @@ -451,7 +453,7 @@ void InputDialog::saveConfig() Controller::setAutoFireRate(rate); // AtariVox serial port - settings.setValue("avoxport", myAVoxPort->getSelectedTag().toString()); + settings.setValue("avoxport", myAVoxPort->getText()); // Allow all 4 joystick directions bool allowall4 = myAllowAll4->getState(); @@ -490,17 +492,11 @@ void InputDialog::setDefaults() break; case 2: // Devices & Ports - // Left & right ports - mySAPort->setState(false); - // Joystick deadzone myDeadzone->setValue(0); // Paddle speed (analog) myPaddleSpeed->setValue(20); - - // Paddle speed (digital) - myDPaddleSpeed->setValue(10); #if defined(RETRON77) myDejitterBase->setValue(2); myDejitterDiff->setValue(6); @@ -508,10 +504,12 @@ void InputDialog::setDefaults() myDejitterBase->setValue(0); myDejitterDiff->setValue(0); #endif + + // Paddle speed (digital) + myDPaddleSpeed->setValue(10); + // Autofire rate myAutoFireRate->setValue(0); - // AtariVox serial port - myAVoxPort->setSelectedMax(); // Allow all 4 joystick directions myAllowAll4->setState(false); @@ -519,6 +517,11 @@ void InputDialog::setDefaults() // Enable/disable modifier key-combos myModCombo->setState(true); + // Left & right ports + mySAPort->setState(false); + + // AtariVox serial port + myAVoxPort->setSelectedIndex(0); break; case 3: // Mouse diff --git a/src/gui/PopUpWidget.cxx b/src/gui/PopUpWidget.cxx index 3f4474fea..c41cfdc00 100644 --- a/src/gui/PopUpWidget.cxx +++ b/src/gui/PopUpWidget.cxx @@ -27,8 +27,7 @@ PopUpWidget::PopUpWidget(GuiObject* boss, const GUI::Font& font, int x, int y, int w, int h, const VariantList& list, const string& label, int labelWidth, int cmd) - : Widget(boss, font, x, y - 1, w, h + 2), - CommandSender(boss), + : EditableWidget(boss, font, x, y - 1, w, h + 2), _label(label), _labelWidth(labelWidth) { @@ -38,6 +37,8 @@ PopUpWidget::PopUpWidget(GuiObject* boss, const GUI::Font& font, _textcolor = kTextColor; _textcolorhi = kTextColor; // do not highlight the label + setEditable(false); + if(!_label.empty() && _labelWidth == 0) _labelWidth = _font.getStringWidth(_label); @@ -70,6 +71,7 @@ void PopUpWidget::addItems(const VariantList& items) void PopUpWidget::setSelected(const Variant& tag, const Variant& def) { myMenu->setSelected(tag, def); + setText(myMenu->getSelectedName()); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -77,6 +79,7 @@ void PopUpWidget::setSelectedIndex(int idx, bool changed) { _changed = changed; myMenu->setSelectedIndex(idx); + setText(myMenu->getSelectedName()); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -84,6 +87,7 @@ void PopUpWidget::setSelectedMax(bool changed) { _changed = changed; myMenu->setSelectedMax(); + setText(myMenu->getSelectedName()); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -113,11 +117,31 @@ const Variant& PopUpWidget::getSelectedTag() const // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void PopUpWidget::handleMouseDown(int x, int y, MouseButton b, int clickCount) { - if(isEnabled() && !myMenu->isVisible()) + if(!isEditable() || x > _w - dropDownWidth(_font)) { - // Add menu just underneath parent widget - myMenu->show(getAbsX() + _labelWidth, getAbsY() + getHeight(), - dialog().surface().dstRect(), myMenu->getSelected()); + if(isEnabled() && !myMenu->isVisible()) + { + // Add menu just underneath parent widget + myMenu->show(getAbsX() + _labelWidth, getAbsY() + getHeight(), + dialog().surface().dstRect(), myMenu->getSelected()); + } + } + else + { + x += _editScrollOffset - _labelWidth; + + int width = 0; + uInt32 i; + + for(i = 0; i < editString().size(); ++i) + { + width += _font.getCharWidth(editString()[i]); + if(width >= x) + break; + } + + if(setCaretPos(i)) + setDirty(); } } @@ -180,6 +204,7 @@ void PopUpWidget::handleCommand(CommandSender* sender, int cmd, int data, int id { // Intercept all events sent through the PromptWidget // They're likely from our ContextMenu, indicating a redraw is required + setText(myMenu->getSelectedName()); dialog().setDirty(); // Pass the cmd on to our parent @@ -246,23 +271,49 @@ void PopUpWidget::drawWidget(bool hilite) // Draw a thin frame around us. s.frameRect(x, _y, w, _h, isEnabled() && hilite ? kWidColorHi : kColor); - s.frameRect(x + w - (_arrowWidth * 2 - 2), _y + 1, (_arrowWidth * 2 - 3), _h - 2, - isEnabled() && hilite ? kWidColorHi : kBGColorLo); + if(isEnabled() && hilite) + s.frameRect(x + w - (_arrowWidth * 2 - 1), _y, (_arrowWidth * 2 - 1), _h, kWidColorHi); // Fill the background - s.fillRect(x + 1, _y + 1, w - (_arrowWidth * 2 - 1), _h - 2, - onTop ? _changed ? kDbgChangedColor : kWidColor : kDlgColor); - s.fillRect(x + w - (_arrowWidth * 2 - 3), _y + 2, (_arrowWidth * 2 - 5), _h - 4, - onTop ? isEnabled() && hilite ? kWidColor : kBGColorHi : kBGColorLo); + ColorId bgCol = isEditable() ? kWidColor : kDlgColor; + s.fillRect(x + 1, _y + 1, w - (_arrowWidth * 2 - 0), _h - 2, + onTop ? _changed ? kDbgChangedColor : bgCol : kDlgColor); + s.fillRect(x + w - (_arrowWidth * 2 - 2), _y + 1, (_arrowWidth * 2 - 3), _h - 2, + onTop ? isEnabled() && hilite ? kBtnColorHi : bgCol : kBGColorLo); // Draw an arrow pointing down at the right end to signal this is a dropdown/popup s.drawBitmap(_arrowImg, x + w - (_arrowWidth * 1.5 - 1), _y + myArrowsY + 1, !(isEnabled() && onTop) ? kColor : kTextColor, _arrowWidth, _arrowHeight); // Draw the selected entry, if any - const string& name = myMenu->getSelectedName(); + const string& name = editString(); + bool editable = isEditable(); + w -= dropDownWidth(_font); - TextAlign align = (_font.getStringWidth(name) > w) ? + TextAlign align = (_font.getStringWidth(name) > w && !editable) ? TextAlign::Right : TextAlign::Left; + adjustOffset(); s.drawString(_font, name, x + _textOfs, _y + myTextY, w, - !(isEnabled() && onTop) ? kColor : _changed ? kDbgChangedTextColor : kTextColor, align); + !(isEnabled() && onTop) ? kColor : _changed ? kDbgChangedTextColor : kTextColor, + align, editable ? -_editScrollOffset : 0, !editable); + + if(editable) + drawCaret(); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Common::Rect PopUpWidget::getEditRect() const +{ + return Common::Rect(_labelWidth + _textOfs, 1, _w - _textOfs - dropDownWidth(_font), _h); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void PopUpWidget::endEditMode() +{ + // Editing is always enabled +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void PopUpWidget::abortEditMode() +{ + // Editing is always enabled } diff --git a/src/gui/PopUpWidget.hxx b/src/gui/PopUpWidget.hxx index a3c122509..deb0af30c 100644 --- a/src/gui/PopUpWidget.hxx +++ b/src/gui/PopUpWidget.hxx @@ -24,7 +24,7 @@ class ContextMenu; #include "bspf.hxx" #include "Variant.hxx" #include "Command.hxx" -#include "Widget.hxx" +#include "EditableWidget.hxx" /** * Popup or dropdown widget which, when clicked, "pop up" a list of items and @@ -33,12 +33,12 @@ class ContextMenu; * Implementation wise, when the user selects an item, then a kPopUpItemSelectedCmd * is broadcast, with data being equal to the tag value of the selected entry. */ -class PopUpWidget : public Widget, public CommandSender +class PopUpWidget : public EditableWidget { public: PopUpWidget(GuiObject* boss, const GUI::Font& font, int x, int y, int w, int h, const VariantList& items, - const string& label, int labelWidth = 0, int cmd = 0); + const string& label = "", int labelWidth = 0, int cmd = 0); ~PopUpWidget() override = default; void setID(uInt32 id); @@ -78,6 +78,11 @@ class PopUpWidget : public Widget, public CommandSender void setArrow(); void drawWidget(bool hilite) override; + void endEditMode() override; + void abortEditMode() override; + + Common::Rect getEditRect() const override; + private: unique_ptr myMenu; int myArrowsY{0};