8
8
// SS SS tt ee ll ll aa aa
9
9
// SSSS ttt eeeee llll llll aaaaa
11
// Copyright (c) 1995-2008 by Bradford W. Mott and the Stella team
11
// Copyright (c) 1995-2010 by Bradford W. Mott, Stephen Anthony
12
// and the Stella Team
13
// See the file "license" for information on usage and redistribution of
14
// See the file "License.txt" for information on usage and redistribution of
14
15
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
16
// $Id: RomListWidget.cxx,v 1.12 2008/05/11 21:18:34 stephena Exp $
17
// $Id: RomListWidget.cxx 2001 2010-04-10 21:37:23Z stephena $
18
19
// Based on code from ScummVM - Scumm Interpreter
19
20
// Copyright (C) 2002-2004 The ScummVM project
20
21
//============================================================================
22
23
#include "bspf.hxx"
24
#include "Debugger.hxx"
23
25
#include "ContextMenu.hxx"
27
#include "ScrollBarWidget.hxx"
24
28
#include "RomListWidget.hxx"
26
30
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
27
31
RomListWidget::RomListWidget(GuiObject* boss, const GUI::Font& font,
28
32
int x, int y, int w, int h)
29
: CheckListWidget(boss, font, x, y, w, h),
33
: EditableWidget(boss, font, x, y, 16, 16),
43
_flags = WIDGET_ENABLED | WIDGET_CLEARBG | WIDGET_RETAIN_FOCUS;
33
44
_type = kRomListWidget;
35
myMenu = new ContextMenu(this, font);
46
_bgcolorhi = kWidColor;
47
_textcolor = kTextColor;
48
_textcolorhi = kTextColor;
50
_cols = w / _fontWidth;
51
_rows = h / _fontHeight;
53
// Set real dimensions
54
_w = w - kScrollBarWidth;
57
// Create scrollbar and attach to the list
58
myScrollBar = new ScrollBarWidget(boss, font, _x + _w, _y, kScrollBarWidth, _h);
59
myScrollBar->setTarget(this);
38
63
// l.push_back("Add bookmark");
39
l.push_back("Save ROM");
40
l.push_back("Set PC");
64
l.push_back("Save ROM", "saverom");
65
l.push_back("Set PC", "setpc");
66
l.push_back("RunTo PC", "runtopc");
67
myMenu = new ContextMenu(this, font, l);
44
69
// Take advantage of a wide debugger window when possible
45
70
const int fontWidth = font.getMaxCharWidth(),
46
71
numchars = w / fontWidth;
48
myLabelWidth = BSPF_max(20, int(0.35 * (numchars - 12))) * fontWidth;
49
myBytesWidth = 12 * fontWidth;
73
_labelWidth = BSPF_max(16, int(0.35 * (numchars - 12))) * fontWidth;
74
_bytesWidth = 12 * fontWidth;
76
//////////////////////////////////////////////////////
80
// rowheight is determined by largest item on a line,
81
// possibly meaning that number of rows will change
82
_fontHeight = BSPF_max(_fontHeight, CheckboxWidget::boxSize());
83
_rows = h / _fontHeight;
85
// Create a CheckboxWidget for each row in the list
87
for(int i = 0; i < _rows; ++i)
89
t = new CheckboxWidget(boss, font, _x + 2, ypos, "", kCheckActionCmd);
94
t->setTextColor(kTextColorEm);
97
myCheckList.push_back(t);
52
101
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
58
107
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
59
void RomListWidget::setList(StringList& label, StringList& bytes, StringList& disasm,
65
CheckListWidget::setList(bytes, state);
108
void RomListWidget::setList(const CartDebug::DisassemblyList& list,
109
const PackedBitArray& state)
114
// Enable all checkboxes
115
for(int i = 0; i < _rows; ++i)
116
myCheckList[i]->setFlags(WIDGET_ENABLED);
118
// Then turn off any extras
119
if((int)myList->size() < _rows)
120
for(int i = myList->size(); i < _rows; ++i)
121
myCheckList[i]->clearFlags(WIDGET_ENABLED);
126
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
127
void RomListWidget::setHighlighted(int item)
129
if(item < -1 || item >= (int)myList->size())
137
_highlightedItem = item;
139
// Only scroll the list if we're about to pass the page boundary
141
_currentPos = _highlightedItem;
142
else if(_highlightedItem == _currentPos + _rows)
143
_currentPos += _rows;
145
scrollToHighlighted();
149
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
150
const string& RomListWidget::getEditString() const
152
if(_selectedItem < -1 || _selectedItem >= (int)myList->size())
158
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
159
int RomListWidget::findItem(int x, int y) const
161
return (y - 1) / _fontHeight + _currentPos;
164
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
165
void RomListWidget::recalc()
167
int size = myList->size();
169
if (_currentPos >= size)
170
_currentPos = size - 1;
174
if(_selectedItem < 0 || _selectedItem >= size)
179
myScrollBar->_numEntries = myList->size();
180
myScrollBar->_entriesPerPage = _rows;
182
// Reset to normal data entry
186
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
187
void RomListWidget::scrollToCurrent(int item)
189
// Only do something if the current item is not in our view port
190
if (item < _currentPos)
192
// it's above our view
195
else if (item >= _currentPos + _rows )
197
// it's below our view
198
_currentPos = item - _rows + 1;
201
if (_currentPos < 0 || _rows > (int)myList->size())
203
else if (_currentPos + _rows > (int)myList->size())
204
_currentPos = myList->size() - _rows;
206
myScrollBar->_currentPos = _currentPos;
207
myScrollBar->recalc();
68
212
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
69
213
void RomListWidget::handleMouseDown(int x, int y, int button, int clickCount)
71
// Grab right mouse button for context menu, send left to base class
218
// Grab right mouse button for context menu, left for selection/edit mode
74
myMenu->setPos(x + getAbsX(), y + getAbsY());
78
ListWidget::handleMouseDown(x, y, button, clickCount);
221
// Set selected and add menu at current x,y mouse location
222
_selectedItem = findItem(x, y);
224
myMenu->show(x + getAbsX(), y + getAbsY());
228
// First check whether the selection changed
230
newSelectedItem = findItem(x, y);
231
if (newSelectedItem > (int)myList->size() - 1)
232
newSelectedItem = -1;
234
if (_selectedItem != newSelectedItem)
238
_selectedItem = newSelectedItem;
244
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
245
void RomListWidget::handleMouseUp(int x, int y, int button, int clickCount)
247
// If this was a double click and the mouse is still over the selected item,
248
// send the double click command
249
if (clickCount == 2 && (_selectedItem == findItem(x, y)))
252
if(_editable && !_editMode)
257
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
258
void RomListWidget::handleMouseWheel(int x, int y, int direction)
260
myScrollBar->handleMouseWheel(x, y, direction);
263
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
264
bool RomListWidget::handleKeyDown(int ascii, int keycode, int modifiers)
266
// Ignore all Alt-mod keys
267
if(instance().eventHandler().kbdAlt(modifiers))
271
int oldSelectedItem = _selectedItem;
275
// Class EditableWidget handles all text editing related key presses for us
276
handled = EditableWidget::handleKeyDown(ascii, keycode, modifiers);
284
// Snap list back to currently highlighted line
285
if(_highlightedItem >= 0)
287
_currentPos = _highlightedItem;
288
scrollToHighlighted();
297
if (_selectedItem != oldSelectedItem)
303
_currentKeyDown = keycode;
307
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
308
bool RomListWidget::handleKeyUp(int ascii, int keycode, int modifiers)
310
if (keycode == _currentKeyDown)
81
315
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
82
316
bool RomListWidget::handleEvent(Event::Type e)
84
return ListWidget::handleEvent(e); // override CheckListWidget::handleEvent()
318
if(!isEnabled() || _editMode)
322
int oldSelectedItem = _selectedItem;
326
case Event::UISelect:
327
if (_selectedItem >= 0)
335
if (_selectedItem > 0)
340
if (_selectedItem < (int)myList->size() - 1)
345
_selectedItem -= _rows - 1;
346
if (_selectedItem < 0)
350
case Event::UIPgDown:
351
_selectedItem += _rows - 1;
352
if (_selectedItem >= (int)myList->size() )
353
_selectedItem = myList->size() - 1;
361
_selectedItem = myList->size() - 1;
368
if (_selectedItem != oldSelectedItem)
377
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
378
void RomListWidget::handleCommand(CommandSender* sender, int cmd, int data, int id)
382
case kCheckActionCmd:
383
// We let the parent class handle this
384
// Pass it as a kRLBreakpointChangedCmd command, since that's the intent
385
sendCommand(kRLBreakpointChangedCmd, myCheckList[id]->getState(), _currentPos+id);
388
case kSetPositionCmd:
389
if (_currentPos != (int)data)
398
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
399
void RomListWidget::lostFocusWidget()
403
// Reset to normal data entry
87
407
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
88
408
void RomListWidget::drawWidget(bool hilite)
90
410
//cerr << "RomListWidget::drawWidget\n";
91
FrameBuffer& fb = _boss->instance()->frameBuffer();
92
int i, pos, len = _list.size();
411
FBSurface& s = _boss->dialog().surface();
412
const CartDebug::DisassemblyList& dlist = *myList;
413
int i, pos, xpos, ypos, len = dlist.size();
96
416
// Draw a thin frame around the list and to separate columns
97
fb.hLine(_x, _y, _x + _w - 1, kColor);
98
fb.hLine(_x, _y + _h - 1, _x + _w - 1, kShadowColor);
99
fb.vLine(_x, _y, _y + _h - 1, kColor);
417
s.hLine(_x, _y, _x + _w - 1, kColor);
418
s.hLine(_x, _y + _h - 1, _x + _w - 1, kShadowColor);
419
s.vLine(_x, _y, _y + _h - 1, kColor);
101
fb.vLine(_x + CheckboxWidget::boxSize() + 5, _y, _y + _h - 1, kColor);
421
s.vLine(_x + CheckboxWidget::boxSize() + 5, _y, _y + _h - 1, kColor);
103
423
// Draw the list items
104
for (i = 0, pos = _currentPos; i < _rows && pos < len; i++, pos++)
424
const GUI::Rect& r = getEditRect();
425
const GUI::Rect& l = getLineRect();
426
int large_disasmw = _w - l.x() - _labelWidth,
427
small_disasmw = large_disasmw - r.width();
428
xpos = _x + CheckboxWidget::boxSize() + 10; ypos = _y + 2;
429
for (i = 0, pos = _currentPos; i < _rows && pos < len; i++, pos++, ypos += _fontHeight)
106
431
// Draw checkboxes for correct lines (takes scrolling into account)
107
_checkList[i]->setState(_stateList[pos]);
108
_checkList[i]->setDirty();
109
_checkList[i]->draw();
111
const int y = _y + 2 + _fontHeight * i;
113
GUI::Rect l = getLineRect();
114
GUI::Rect r = getEditRect();
432
myCheckList[i]->setState(myBPState->isSet(dlist[pos].address));
433
myCheckList[i]->setDirty();
434
myCheckList[i]->draw();
116
436
// Draw highlighted item in a frame
117
437
if (_highlightedItem == pos)
119
fb.frameRect(_x + l.left - 3, _y + 1 + _fontHeight * i,
120
_w - l.left, _fontHeight, kDbgColorHi);
439
s.frameRect(_x + l.x() - 3, _y + 1 + _fontHeight * i,
440
_w - l.x(), _fontHeight, kDbgColorHi);
123
443
// Draw the selected item inverted, on a highlighted background.
124
444
if (_selectedItem == pos && _hasFocus)
127
fb.fillRect(_x + r.left - 3, _y + 1 + _fontHeight * i,
128
r.width(), _fontHeight,
447
s.fillRect(_x + r.x() - 3, _y + 1 + _fontHeight * i,
448
r.width(), _fontHeight, kTextColorHi);
131
fb.frameRect(_x + r.left - 3, _y + 1 + _fontHeight * i,
132
r.width(), _fontHeight,
450
s.frameRect(_x + r.x() - 3, _y + 1 + _fontHeight * i,
451
r.width(), _fontHeight, kTextColorHi);
136
// Draw labels and actual disassembly
137
fb.drawString(_font, myLabel[pos], _x + r.left - myLabelWidth, y,
138
myLabelWidth, kTextColor);
140
fb.drawString(_font, myDisasm[pos], _x + r.right, y,
141
_w - r.right, kTextColor);
143
// Draw editable bytes
144
if (_selectedItem == pos && _editMode)
455
s.drawString(_font, dlist[pos].label, xpos, ypos, _labelWidth, kTextColor);
457
// Sometimes there aren't any bytes to display, in which case the disassembly
458
// should get all remaining space
459
if(dlist[pos].bytes != "")
146
buffer = _editString;
148
deltax = -_editScrollOffset;
150
fb.drawString(_font, buffer, _x + r.left, y, r.width(), kTextColor,
151
kTextAlignLeft, deltax, false);
462
s.drawString(_font, dlist[pos].disasm, xpos + _labelWidth, ypos,
463
small_disasmw, kTextColor);
467
if (_selectedItem == pos && _editMode)
470
deltax = -_editScrollOffset;
472
s.drawString(_font, _editString, _x + r.x(), ypos, r.width(), kTextColor,
473
kTextAlignLeft, deltax, false);
480
s.drawString(_font, dlist[pos].bytes, _x + r.x(), ypos, r.width(), kTextColor);
157
fb.drawString(_font, buffer, _x + r.left, y, r.width(), kTextColor);
486
// Draw disassembly, giving it all remaining horizontal space
487
s.drawString(_font, dlist[pos].disasm, xpos + _labelWidth, ypos,
488
large_disasmw, kTextColor);
161
// Only draw the caret while editing, and if it's in the current viewport
162
if(_editMode && (_selectedItem >= _scrollBar->_currentPos) &&
163
(_selectedItem < _scrollBar->_currentPos + _rows))
167
493
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -