stella/src/gui/CheckListWidget.cxx

197 lines
6.1 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 "Dialog.hxx"
#include "FBSurface.hxx"
#include "ScrollBarWidget.hxx"
#include "CheckListWidget.hxx"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CheckListWidget::CheckListWidget(GuiObject* boss, const GUI::Font& font,
int x, int y, int w, int h)
: ListWidget(boss, font, x, y, w, h)
{
int ypos = _y + 2;
// rowheight is determined by largest item on a line,
// possibly meaning that number of rows will change
_fontHeight = std::max(_fontHeight, CheckboxWidget::boxSize());
_rows = h / _fontHeight;
// Create a CheckboxWidget for each row in the list
for(int i = 0; i < _rows; ++i)
{
CheckboxWidget* t = new CheckboxWidget(boss, font, _x + 2, ypos, "",
CheckboxWidget::kCheckActionCmd);
t->setTextColor(kTextColor);
t->setTarget(this);
t->setID(i);
ypos += _fontHeight;
_checkList.push_back(t);
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CheckListWidget::handleMouseEntered()
{
setFlags(Widget::FLAG_HILITED);
setDirty();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CheckListWidget::handleMouseLeft()
{
clearFlags(Widget::FLAG_HILITED);
setDirty();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CheckListWidget::setList(const StringList& list, const BoolArray& state)
{
_list = list;
_stateList = state;
assert(_list.size() == _stateList.size());
// Enable all checkboxes
for(int i = 0; i < _rows; ++i)
_checkList[i]->setFlags(Widget::FLAG_ENABLED);
// Then turn off any extras
if(int(_stateList.size()) < _rows)
for(int i = int(_stateList.size()); i < _rows; ++i)
_checkList[i]->clearFlags(Widget::FLAG_ENABLED);
ListWidget::recalc();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CheckListWidget::setLine(int line, const string& str, const bool& state)
{
if(line >= int(_list.size()))
return;
_list[line] = str;
_stateList[line] = state;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CheckListWidget::drawWidget(bool hilite)
{
//cerr << "CheckListWidget::drawWidget\n";
FBSurface& s = _boss->dialog().surface();
bool onTop = _boss->dialog().isOnTop();
int i, pos, len = int(_list.size());
// Draw a thin frame around the list and to separate columns
s.frameRect(_x, _y, _w, _h, hilite ? kWidColorHi : kColor);
s.vLine(_x + CheckboxWidget::boxSize() + 5, _y, _y + _h - 1, kColor);
// Draw the list items
for (i = 0, pos = _currentPos; i < _rows && pos < len; i++, pos++)
{
// Draw checkboxes for correct lines (takes scrolling into account)
_checkList[i]->setState(_stateList[pos]);
_checkList[i]->setDirty();
_checkList[i]->draw();
const int y = _y + 2 + _fontHeight * i + 2;
ColorId textColor = kTextColor;
Common::Rect r(getEditRect());
// Draw the selected item inverted, on a highlighted background.
if (_selectedItem == pos)
{
if(_hasFocus && !_editMode)
{
s.fillRect(_x + r.x() - 3, _y + 1 + _fontHeight * i,
_w - r.x(), _fontHeight, kTextColorHi);
textColor = kTextColorInv;
}
else
s.frameRect(_x + r.x() - 3, _y + 1 + _fontHeight * i,
_w - r.x(), _fontHeight, onTop ? kTextColorHi : kColor);
}
if (_selectedItem == pos && _editMode)
{
adjustOffset();
s.drawString(_font, editString(), _x + r.x(), y, r.w(), onTop ? kTextColor : kColor,
TextAlign::Left, -_editScrollOffset, false);
}
else
s.drawString(_font, _list[pos], _x + r.x(), y, r.w(),
onTop ? textColor : kColor);
}
// Only draw the caret while editing, and if it's in the current viewport
if(_editMode && (_selectedItem >= _scrollBar->_currentPos) &&
(_selectedItem < _scrollBar->_currentPos + _rows))
drawCaret();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Common::Rect CheckListWidget::getEditRect() const
{
const int yoffset = (_selectedItem - _currentPos) * _fontHeight,
xoffset = CheckboxWidget::boxSize() + 10;
return Common::Rect(2 + xoffset, 1 + yoffset,
_w - (xoffset - 15), _fontHeight + yoffset);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool CheckListWidget::getState(int line)
{
if(line >= 0 && line < int(_stateList.size()))
return _stateList[line];
else
return false;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool CheckListWidget::handleEvent(Event::Type e)
{
if(e == Event::UISelect)
{
// Simulate a mouse button click
_checkList[ListWidget::getSelected()]->handleMouseUp(0, 0, MouseButton::LEFT, 0);
return true;
}
else
return ListWidget::handleEvent(e);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CheckListWidget::handleCommand(CommandSender* sender, int cmd,
int data, int id)
{
if(cmd == CheckboxWidget::kCheckActionCmd)
{
// Figure out which line has been checked
int line = _currentPos + id;
_stateList[line] = bool(data);
// Let the boss know about it
sendCommand(CheckListWidget::kListItemChecked, line, _id);
}
else
ListWidget::handleCommand(sender, cmd, data, id);
}