mirror of https://github.com/stella-emu/stella.git
703 lines
20 KiB
C++
703 lines
20 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-2021 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 "OSystem.hxx"
|
|
#include "Debugger.hxx"
|
|
#include "DiStella.hxx"
|
|
#include "Widget.hxx"
|
|
#include "Dialog.hxx"
|
|
#include "ToolTip.hxx"
|
|
#include "StellaKeys.hxx"
|
|
#include "FBSurface.hxx"
|
|
#include "Font.hxx"
|
|
#include "ScrollBarWidget.hxx"
|
|
#include "RomListSettings.hxx"
|
|
#include "RomListWidget.hxx"
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
RomListWidget::RomListWidget(GuiObject* boss, const GUI::Font& lfont,
|
|
const GUI::Font& nfont,
|
|
int x, int y, int w, int h)
|
|
: EditableWidget(boss, nfont, x, y, 16, 16)
|
|
{
|
|
_flags = Widget::FLAG_ENABLED | Widget::FLAG_CLEARBG | Widget::FLAG_RETAIN_FOCUS;
|
|
_bgcolor = kWidColor;
|
|
_bgcolorhi = kWidColor;
|
|
_textcolor = kTextColor;
|
|
_textcolorhi = kTextColor;
|
|
|
|
_editMode = false;
|
|
_dyText = -1; // fixes the vertical position of selected text
|
|
|
|
_cols = w / _fontWidth;
|
|
_rows = h / _lineHeight;
|
|
|
|
// Set real dimensions
|
|
_w = w - ScrollBarWidget::scrollBarWidth(_font);
|
|
_h = h + 2;
|
|
|
|
// Create scrollbar and attach to the list
|
|
myScrollBar = new ScrollBarWidget(boss, lfont, _x + _w, _y,
|
|
ScrollBarWidget::scrollBarWidth(_font), _h);
|
|
myScrollBar->setTarget(this);
|
|
|
|
// Add settings menu
|
|
myMenu = make_unique<RomListSettings>(this, lfont);
|
|
|
|
// Take advantage of a wide debugger window when possible
|
|
const int fontWidth = lfont.getMaxCharWidth(),
|
|
numchars = w / fontWidth;
|
|
|
|
_labelWidth = std::max(14, int(0.45 * (numchars - 8 - 8 - 9 - 2))) * fontWidth - 1;
|
|
_bytesWidth = 9 * fontWidth;
|
|
|
|
///////////////////////////////////////////////////////
|
|
// Add checkboxes
|
|
int ypos = _y + 2;
|
|
|
|
// rowheight is determined by largest item on a line,
|
|
// possibly meaning that number of rows will change
|
|
_lineHeight = std::max(_lineHeight, CheckboxWidget::boxSize(_font));
|
|
_rows = h / _lineHeight;
|
|
|
|
// Create a CheckboxWidget for each row in the list
|
|
for(int i = 0; i < _rows; ++i)
|
|
{
|
|
CheckboxWidget* t = new CheckboxWidget(boss, lfont, _x + 2, ypos, "",
|
|
CheckboxWidget::kCheckActionCmd);
|
|
t->setTarget(this);
|
|
t->setID(i);
|
|
t->setFill(CheckboxWidget::FillType::Circle);
|
|
t->setTextColor(kTextColorEm);
|
|
ypos += _lineHeight;
|
|
|
|
myCheckList.push_back(t);
|
|
}
|
|
|
|
// Add filtering
|
|
EditableWidget::TextFilter f = [&](char c)
|
|
{
|
|
switch(_base)
|
|
{
|
|
case Common::Base::Fmt::_16:
|
|
case Common::Base::Fmt::_16_1:
|
|
case Common::Base::Fmt::_16_2:
|
|
case Common::Base::Fmt::_16_4:
|
|
case Common::Base::Fmt::_16_8:
|
|
return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || c == ' ';
|
|
|
|
case Common::Base::Fmt::_2:
|
|
case Common::Base::Fmt::_2_8:
|
|
case Common::Base::Fmt::_2_16:
|
|
return c == '0' || c == '1' || c == ' ';
|
|
|
|
case Common::Base::Fmt::_10:
|
|
return (c >= '0' && c <= '9') || c == ' ';
|
|
|
|
case Common::Base::Fmt::_DEFAULT:
|
|
default: // TODO - properly handle all other cases
|
|
return false;
|
|
}
|
|
};
|
|
setTextFilter(f);
|
|
}
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
void RomListWidget::setList(const CartDebug::Disassembly& disasm)
|
|
{
|
|
myDisasm = &disasm;
|
|
|
|
// Enable all checkboxes
|
|
for(int i = 0; i < _rows; ++i)
|
|
myCheckList[i]->setFlags(Widget::FLAG_ENABLED);
|
|
|
|
// Then turn off any extras
|
|
if(int(myDisasm->list.size()) < _rows)
|
|
for(int i = int(myDisasm->list.size()); i < _rows; ++i)
|
|
myCheckList[i]->clearFlags(Widget::FLAG_ENABLED);
|
|
|
|
recalc();
|
|
}
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
void RomListWidget::setSelected(int item)
|
|
{
|
|
if(item < -1 || item >= int(myDisasm->list.size()))
|
|
return;
|
|
|
|
if(isEnabled())
|
|
{
|
|
if(_editMode)
|
|
abortEditMode();
|
|
|
|
_currentPos = _selectedItem = item;
|
|
scrollToSelected();
|
|
}
|
|
}
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
void RomListWidget::setHighlighted(int item)
|
|
{
|
|
if(item < -1 || item >= int(myDisasm->list.size()))
|
|
return;
|
|
|
|
if(isEnabled())
|
|
{
|
|
if(_editMode)
|
|
abortEditMode();
|
|
|
|
_highlightedItem = item;
|
|
|
|
// Only scroll the list if we're about to pass the page boundary
|
|
if (_highlightedItem < _currentPos)
|
|
{
|
|
_currentPos -= _rows;
|
|
if (_currentPos < 0)
|
|
_currentPos = 0;
|
|
}
|
|
else if(_highlightedItem == _currentPos + _rows)
|
|
_currentPos += _rows;
|
|
|
|
scrollToHighlighted();
|
|
}
|
|
}
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
int RomListWidget::findItem(int x, int y) const
|
|
{
|
|
return (y - 1) / _lineHeight + _currentPos;
|
|
}
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
void RomListWidget::recalc()
|
|
{
|
|
int size = int(myDisasm->list.size());
|
|
|
|
if (_currentPos >= size)
|
|
_currentPos = size - 1;
|
|
if (_currentPos < 0)
|
|
_currentPos = 0;
|
|
|
|
if(_selectedItem < 0 || _selectedItem >= size)
|
|
_selectedItem = 0;
|
|
|
|
_editMode = false;
|
|
|
|
myScrollBar->_numEntries = int(myDisasm->list.size());
|
|
myScrollBar->_entriesPerPage = _rows;
|
|
|
|
// Reset to normal data entry
|
|
abortEditMode();
|
|
|
|
setDirty();
|
|
}
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
void RomListWidget::scrollToCurrent(int item)
|
|
{
|
|
// Only do something if the current item is not in our view port
|
|
if (item < _currentPos)
|
|
{
|
|
// it's above our view
|
|
_currentPos = item;
|
|
}
|
|
else if (item >= _currentPos + _rows )
|
|
{
|
|
// it's below our view
|
|
_currentPos = item - _rows + 1;
|
|
}
|
|
|
|
int size = int(myDisasm->list.size());
|
|
if (_currentPos < 0 || _rows > size)
|
|
_currentPos = 0;
|
|
else if (_currentPos + _rows > size)
|
|
_currentPos = size - _rows;
|
|
|
|
myScrollBar->_currentPos = _currentPos;
|
|
myScrollBar->recalc();
|
|
|
|
setDirty();
|
|
}
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
void RomListWidget::handleMouseDown(int x, int y, MouseButton b, int clickCount)
|
|
{
|
|
if (!isEnabled())
|
|
return;
|
|
|
|
resetSelection();
|
|
// Grab right mouse button for context menu, left for selection/edit mode
|
|
if(b == MouseButton::RIGHT)
|
|
{
|
|
// Set selected and add menu at current x,y mouse location
|
|
_selectedItem = findItem(x, y);
|
|
scrollToSelected();
|
|
dialog().tooltip().hide();
|
|
myMenu->show(x + getAbsX(), y + getAbsY(),
|
|
dialog().surface().dstRect(), _selectedItem);
|
|
}
|
|
else
|
|
{
|
|
// First check whether the selection changed
|
|
int newSelectedItem;
|
|
newSelectedItem = findItem(x, y);
|
|
if (newSelectedItem > int(myDisasm->list.size()) - 1)
|
|
newSelectedItem = -1;
|
|
|
|
if (_selectedItem != newSelectedItem)
|
|
{
|
|
if (_editMode)
|
|
abortEditMode();
|
|
_selectedItem = newSelectedItem;
|
|
setDirty();
|
|
}
|
|
}
|
|
}
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
void RomListWidget::handleMouseUp(int x, int y, MouseButton b, int clickCount)
|
|
{
|
|
// If this was a double click and the mouse is still over the selected item,
|
|
// send the double click command
|
|
if (clickCount == 2 && (_selectedItem == findItem(x, y)))
|
|
{
|
|
// Start edit mode
|
|
if(isEditable() && !_editMode)
|
|
startEditMode();
|
|
}
|
|
}
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
void RomListWidget::handleMouseWheel(int x, int y, int direction)
|
|
{
|
|
myScrollBar->handleMouseWheel(x, y, direction);
|
|
}
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
bool RomListWidget::handleText(char text)
|
|
{
|
|
if(_editMode)
|
|
{
|
|
// Class EditableWidget handles all text editing related key presses for us
|
|
return EditableWidget::handleText(text);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
bool RomListWidget::handleKeyDown(StellaKey key, StellaMod mod)
|
|
{
|
|
// Ignore all Alt-mod keys
|
|
if(StellaModTest::isAlt(mod))
|
|
return false;
|
|
|
|
bool handled = true;
|
|
int oldSelectedItem = _selectedItem;
|
|
|
|
if (_editMode)
|
|
{
|
|
// Class EditableWidget handles all single-key presses for us
|
|
handled = EditableWidget::handleKeyDown(key, mod);
|
|
}
|
|
else
|
|
{
|
|
switch (key)
|
|
{
|
|
case KBDK_SPACE:
|
|
// Snap list back to currently highlighted line
|
|
if(_highlightedItem >= 0)
|
|
{
|
|
_currentPos = _highlightedItem;
|
|
scrollToHighlighted();
|
|
}
|
|
break;
|
|
|
|
default:
|
|
handled = false;
|
|
}
|
|
}
|
|
|
|
if (_selectedItem != oldSelectedItem)
|
|
{
|
|
myScrollBar->draw();
|
|
scrollToSelected();
|
|
}
|
|
|
|
_currentKeyDown = key;
|
|
return handled;
|
|
}
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
bool RomListWidget::handleKeyUp(StellaKey key, StellaMod mod)
|
|
{
|
|
if (key == _currentKeyDown)
|
|
_currentKeyDown = KBDK_UNKNOWN;
|
|
return true;
|
|
}
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
bool RomListWidget::handleEvent(Event::Type e)
|
|
{
|
|
if(!isEnabled() || _editMode)
|
|
return false;
|
|
|
|
bool handled = true;
|
|
int oldSelectedItem = _selectedItem;
|
|
|
|
switch(e)
|
|
{
|
|
case Event::UISelect:
|
|
if (_selectedItem >= 0)
|
|
{
|
|
if (isEditable())
|
|
startEditMode();
|
|
}
|
|
break;
|
|
|
|
case Event::UIUp:
|
|
if (_selectedItem > 0)
|
|
_selectedItem--;
|
|
break;
|
|
|
|
case Event::UIDown:
|
|
if (_selectedItem < int(myDisasm->list.size()) - 1)
|
|
_selectedItem++;
|
|
break;
|
|
|
|
case Event::UIPgUp:
|
|
_selectedItem -= _rows - 1;
|
|
if (_selectedItem < 0)
|
|
_selectedItem = 0;
|
|
break;
|
|
|
|
case Event::UIPgDown:
|
|
_selectedItem += _rows - 1;
|
|
if (_selectedItem >= int(myDisasm->list.size()))
|
|
_selectedItem = int(myDisasm->list.size()) - 1;
|
|
break;
|
|
|
|
case Event::UIHome:
|
|
_selectedItem = 0;
|
|
break;
|
|
|
|
case Event::UIEnd:
|
|
_selectedItem = int(myDisasm->list.size()) - 1;
|
|
break;
|
|
|
|
default:
|
|
handled = false;
|
|
}
|
|
|
|
if (_selectedItem != oldSelectedItem)
|
|
{
|
|
myScrollBar->draw();
|
|
scrollToSelected();
|
|
}
|
|
|
|
return handled;
|
|
}
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
void RomListWidget::handleCommand(CommandSender* sender, int cmd, int data, int id)
|
|
{
|
|
switch (cmd)
|
|
{
|
|
case CheckboxWidget::kCheckActionCmd:
|
|
// We let the parent class handle this
|
|
// Pass it as a kRLBreakpointChangedCmd command, since that's the intent
|
|
sendCommand(RomListWidget::kBPointChangedCmd, _currentPos+id, 0);
|
|
break;
|
|
|
|
case GuiObject::kSetPositionCmd:
|
|
if (_currentPos != data)
|
|
{
|
|
_currentPos = data;
|
|
setDirty();
|
|
}
|
|
break;
|
|
|
|
default:
|
|
// Let the parent class handle all other commands directly
|
|
sendCommand(cmd, data, id);
|
|
}
|
|
}
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
void RomListWidget::lostFocusWidget()
|
|
{
|
|
_editMode = false;
|
|
|
|
// Reset to normal data entry
|
|
abortEditMode();
|
|
}
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
Common::Point RomListWidget::getToolTipIndex(const Common::Point& pos) const
|
|
{
|
|
const Common::Rect& r = getEditRect();
|
|
const int col = (pos.x - r.x() - getAbsX()) / _font.getMaxCharWidth();
|
|
const int row = (pos.y - getAbsY()) / _lineHeight;
|
|
|
|
if(col < 0 || col >= 8
|
|
|| row < 0 || row + _currentPos >= int(myDisasm->list.size()))
|
|
return Common::Point(-1, -1);
|
|
else
|
|
return Common::Point(col, row + _currentPos);
|
|
}
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
string RomListWidget::getToolTip(const Common::Point& pos) const
|
|
{
|
|
const Common::Point& idx = getToolTipIndex(pos);
|
|
|
|
if(idx.y < 0)
|
|
return EmptyString;
|
|
|
|
const string bytes = myDisasm->list[idx.y].bytes;
|
|
|
|
if(static_cast<Int32>(bytes.length()) < idx.x + 1)
|
|
return EmptyString;
|
|
|
|
Int32 val;
|
|
if(bytes.length() == 8 && bytes[2] != ' ')
|
|
{
|
|
// Binary value
|
|
val = static_cast<Int32>(stol(bytes, nullptr, 2));
|
|
}
|
|
else
|
|
{
|
|
// 1..3 hex values
|
|
if(idx.x == 2)
|
|
// Skip gap after first byte
|
|
return EmptyString;
|
|
|
|
string valStr;
|
|
|
|
if(idx.x < 2 || bytes.length() < 8)
|
|
// 1 or 2 hex bytes, get one hex byte
|
|
valStr = bytes.substr((idx.x / 3) * 3, 2);
|
|
else
|
|
// 3 hex bytes, get two rightmost hex bytes
|
|
valStr = bytes.substr(6, 2) + bytes.substr(3, 2);
|
|
|
|
val = static_cast<Int32>(stol(valStr, nullptr, 16));
|
|
}
|
|
ostringstream buf;
|
|
|
|
buf << _toolTipText
|
|
<< "$" << Common::Base::toString(val, Common::Base::Fmt::_16)
|
|
<< " = #" << val;
|
|
if(val < 0x100)
|
|
{
|
|
if(val >= 0x80)
|
|
buf << '/' << -(0x100 - val);
|
|
buf << " = %" << Common::Base::toString(val, Common::Base::Fmt::_2);
|
|
}
|
|
|
|
return buf.str();
|
|
}
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
bool RomListWidget::changedToolTip(const Common::Point& oldPos,
|
|
const Common::Point& newPos) const
|
|
{
|
|
return getToolTipIndex(oldPos) != getToolTipIndex(newPos);
|
|
}
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
void RomListWidget::drawWidget(bool hilite)
|
|
{
|
|
FBSurface& s = _boss->dialog().surface();
|
|
const CartDebug::DisassemblyList& dlist = myDisasm->list;
|
|
int i, pos, xpos, ypos, len = int(dlist.size());
|
|
ColorId textColor = kTextColor;
|
|
|
|
const Common::Rect& r = getEditRect();
|
|
const Common::Rect& l = getLineRect();
|
|
|
|
// Draw a thin frame around the list and to separate columns
|
|
s.frameRect(_x, _y, _w + 1, _h, hilite ? kWidColorHi : kColor);
|
|
s.vLine(_x + CheckboxWidget::boxSize(_font) + 5, _y, _y + _h - 1, kColor);
|
|
|
|
// Draw the list items
|
|
int cycleCountW = _fontWidth * 8,
|
|
noTypeDisasmW = _w - l.x() - _labelWidth,
|
|
noCodeDisasmW = noTypeDisasmW - r.w(),
|
|
codeDisasmW = noCodeDisasmW - cycleCountW,
|
|
actualWidth = myDisasm->fieldwidth * _fontWidth;
|
|
if(actualWidth < codeDisasmW)
|
|
codeDisasmW = actualWidth;
|
|
|
|
xpos = _x + CheckboxWidget::boxSize(_font) + 10; ypos = _y + 2;
|
|
for(i = 0, pos = _currentPos; i < _rows && pos < len; i++, pos++, ypos += _lineHeight)
|
|
{
|
|
ColorId bytesColor = textColor;
|
|
|
|
// Mark checkboxes dirty for correct lines (takes scrolling into account)
|
|
myCheckList[i]->setState(instance().debugger().
|
|
checkBreakPoint(dlist[pos].address,
|
|
instance().debugger().cartDebug().getBank(dlist[pos].address)));
|
|
myCheckList[i]->setDirty();
|
|
// All checkboxes have to be redrawn because RomListWidget clears its whole area
|
|
// Also draw immediately, because chain order is not deterministic
|
|
myCheckList[i]->draw();
|
|
|
|
// Draw highlighted item in a frame
|
|
if(_highlightedItem == pos)
|
|
s.frameRect(_x + l.x() - 3, ypos - 1, _w - l.x(), _lineHeight, kWidColorHi);
|
|
|
|
// Draw the selected item inverted, on a highlighted background.
|
|
if(_selectedItem == pos && _hasFocus)
|
|
{
|
|
if(!_editMode)
|
|
{
|
|
s.fillRect(_x + r.x() - 3, ypos - 1, r.w(), _lineHeight, kTextColorHi);
|
|
bytesColor = kTextColorInv;
|
|
}
|
|
else
|
|
s.frameRect(_x + r.x() - 3, ypos - 1, r.w(), _lineHeight, kWidColorHi);
|
|
}
|
|
|
|
// Draw labels
|
|
s.drawString(_font, dlist[pos].label, xpos, ypos, _labelWidth,
|
|
dlist[pos].hllabel ? textColor : kColor);
|
|
|
|
// Bytes are only editable if they represent code, graphics, or accessible data
|
|
// Otherwise, the disassembly should get all remaining space
|
|
if(dlist[pos].type & (Device::CODE | Device::GFX | Device::PGFX |
|
|
Device::COL | Device::PCOL | Device::BCOL | Device::DATA))
|
|
{
|
|
if(dlist[pos].type == Device::CODE)
|
|
{
|
|
// Draw mnemonic
|
|
s.drawString(_font, dlist[pos].disasm.substr(0, 7), xpos + _labelWidth, ypos,
|
|
7 * _fontWidth, textColor);
|
|
// Draw operand
|
|
if(dlist[pos].disasm.length() > 8)
|
|
s.drawString(_font, dlist[pos].disasm.substr(8), xpos + _labelWidth + 7 * _fontWidth, ypos,
|
|
codeDisasmW - 7 * _fontWidth, textColor);
|
|
// Draw cycle count
|
|
s.drawString(_font, dlist[pos].ccount, xpos + _labelWidth + codeDisasmW, ypos,
|
|
cycleCountW, textColor);
|
|
}
|
|
else
|
|
{
|
|
// Draw disassembly only
|
|
s.drawString(_font, dlist[pos].disasm, xpos + _labelWidth, ypos,
|
|
noCodeDisasmW - 4, kTextColor);
|
|
}
|
|
|
|
// Draw separator
|
|
s.vLine(_x + r.x() - 7, ypos, ypos + _lineHeight - 1, kColor);
|
|
|
|
// Draw bytes
|
|
{
|
|
if(_selectedItem == pos && _editMode)
|
|
{
|
|
adjustOffset();
|
|
s.drawString(_font, editString(), _x + r.x(), ypos, r.w(), textColor,
|
|
TextAlign::Left, -_editScrollOffset, false);
|
|
|
|
drawCaretSelection();
|
|
}
|
|
else
|
|
{
|
|
s.drawString(_font, dlist[pos].bytes, _x + r.x(), ypos, r.w(), bytesColor);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Draw disassembly, giving it all remaining horizontal space
|
|
s.drawString(_font, dlist[pos].disasm, xpos + _labelWidth, ypos,
|
|
noTypeDisasmW, textColor);
|
|
}
|
|
}
|
|
}
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
Common::Rect RomListWidget::getLineRect() const
|
|
{
|
|
const int yoffset = std::max(0, (_selectedItem - _currentPos) * _lineHeight),
|
|
xoffset = CheckboxWidget::boxSize(_font) + 10;
|
|
|
|
return Common::Rect(2 + xoffset, 1 + yoffset,
|
|
_w - (xoffset - 15), _lineHeight + yoffset);
|
|
}
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
Common::Rect RomListWidget::getEditRect() const
|
|
{
|
|
const int yoffset = std::max(0, (_selectedItem - _currentPos) * _lineHeight);
|
|
|
|
return Common::Rect(2 + _w - _bytesWidth, 1 + yoffset + 1,
|
|
_w, _lineHeight + yoffset + 1);
|
|
}
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
void RomListWidget::startEditMode()
|
|
{
|
|
if (isEditable() && !_editMode && _selectedItem >= 0)
|
|
{
|
|
// Does this line represent an editable area?
|
|
if(myDisasm->list[_selectedItem].bytes == "")
|
|
return;
|
|
|
|
_editMode = true;
|
|
dialog().tooltip().hide();
|
|
switch(myDisasm->list[_selectedItem].type)
|
|
{
|
|
case Device::GFX:
|
|
case Device::PGFX:
|
|
_base = DiStella::settings.gfxFormat;
|
|
break;
|
|
default:
|
|
_base = Common::Base::format();
|
|
}
|
|
|
|
// Widget gets raw data while editing
|
|
EditableWidget::startEditMode();
|
|
setText(myDisasm->list[_selectedItem].bytes);
|
|
}
|
|
}
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
void RomListWidget::endEditMode()
|
|
{
|
|
if (!_editMode)
|
|
return;
|
|
|
|
// Send a message that editing finished with a return/enter key press
|
|
// The parent then calls getText() to get the newly entered data
|
|
_editMode = false;
|
|
sendCommand(RomListWidget::kRomChangedCmd, _selectedItem, static_cast<int>(_base));
|
|
|
|
// Reset to normal data entry
|
|
EditableWidget::endEditMode();
|
|
}
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
void RomListWidget::abortEditMode()
|
|
{
|
|
// Undo any changes made
|
|
_editMode = false;
|
|
|
|
// Reset to normal data entry
|
|
EditableWidget::abortEditMode();
|
|
}
|