#include "textlist.h" #include "tw/colors.h" #include "tw/event.h" #include "tw/scrollbar.h" #include "tw/keycodes.h" #include #include #include using namespace std; using namespace TwConsts; namespace { const int rowHeight = 20; // 15 }; //============================================================================== class TTextList::Data { public: Data(TWidget *w) : m_w(w), m_selAction(0), m_dblClickAction(0), m_scrollbar(new TScrollbar(w)), m_yoffset(0) { } ~Data() { if (m_selAction) delete m_selAction; if (m_dblClickAction) delete m_dblClickAction; std::map::iterator it = m_items.begin(); for (; it != m_items.end(); ++it) delete it->second; } int posToItem(const TPoint &p); void updateScrollBarStatus() { if (!m_scrollbar) return; unsigned int ly = m_w->getLy(); if ((m_items.size() * rowHeight) > ly) { m_scrollbar->setValue(m_yoffset, 0, (m_items.size() + 1) * rowHeight - ly, ly); m_scrollbar->show(); //m_scrollbar->setValue(m_yoffset,0, yrange-ly, ly); } else { m_yoffset = 0; m_scrollbar->hide(); //m_scrollbar->setValue(0,0, 0, 0); } m_scrollbar->invalidate(); } TWidget *m_w; std::map m_items; vector m_selectedItems; TGenericTextListAction *m_selAction; TGenericTextListAction *m_dblClickAction; TScrollbar *m_scrollbar; int m_yoffset; }; //------------------------------------------------------------------------------ int TTextList::Data::posToItem(const TPoint &p) { /* TDimension d = getSize(); int i = getItemCount()-1; 10 + for(int y=10; y=0; y+=rowHeight, --i) */ int y = m_w->getSize().ly - p.y + m_yoffset; int item = y / rowHeight; return item; } //============================================================================== TTextListItem::TTextListItem(const string &id, const string &caption) : m_id(id), m_caption(caption) { } //============================================================================== TTextList::TTextList(TWidget *parent, string name) : TWidget(parent, name), m_data(0) { m_data = new Data(this); m_data->m_scrollbar->setAction(new TScrollbarAction(this, &TTextList::scrollTo)); } //------------------------------------------------------------------------------ TTextList::~TTextList() { delete m_data; } //------------------------------------------------------------------------------ void TTextList::addItem(TTextListItem *item) { std::map::iterator it = m_data->m_items.find(item->getId()); if (it == m_data->m_items.end()) { m_data->m_items.insert(make_pair(item->getId(), item)); m_data->updateScrollBarStatus(); } } //------------------------------------------------------------------------------ void TTextList::removeItem(const string &itemId) { std::map::iterator it = m_data->m_items.find(itemId); if (it != m_data->m_items.end()) { m_data->m_items.erase(it); m_data->updateScrollBarStatus(); } } //------------------------------------------------------------------------------ void TTextList::clearAll() { m_data->m_items.clear(); m_data->m_selectedItems.clear(); invalidate(); m_data->updateScrollBarStatus(); } //------------------------------------------------------------------------------ int TTextList::getItemCount() const { return m_data->m_items.size(); } //------------------------------------------------------------------------------ TTextListItem *TTextList::getItem(int i) const { if (i >= 0 && i < (int)m_data->m_items.size()) { std::map::iterator it = m_data->m_items.begin(); advance(it, i); return it->second; } return 0; } //------------------------------------------------------------------------------ int TTextList::itemToIndex(const string &itemId) { std::map::iterator it = m_data->m_items.find(itemId); if (it == m_data->m_items.end()) return -1; else return distance(m_data->m_items.begin(), it); } //------------------------------------------------------------------------------ int TTextList::getSelectedItemCount() const { return m_data->m_selectedItems.size(); } //------------------------------------------------------------------------------ TTextListItem *TTextList::getSelectedItem(int i) const { if (i < 0 || (int)m_data->m_selectedItems.size() <= i) return 0; string itemId = m_data->m_selectedItems[i]; std::map::iterator it = m_data->m_items.find(itemId); if (it != m_data->m_items.end()) return it->second; else return 0; } //------------------------------------------------------------------------------ string TTextList::getSelectedItemId(int i) const { if ((int)m_data->m_selectedItems.size() <= i) return ""; assert(i >= 0 && i < (int)m_data->m_selectedItems.size()); return m_data->m_selectedItems[i]; } //------------------------------------------------------------------------------ void TTextList::select(int i, bool on) { assert(i >= 0 && i < (int)m_data->m_items.size()); std::map::iterator it = m_data->m_items.begin(); advance(it, i); string id = it->first; vector::iterator it2 = find(m_data->m_selectedItems.begin(), m_data->m_selectedItems.end(), id); if (on) { if (it2 == m_data->m_selectedItems.end()) m_data->m_selectedItems.push_back(id); } else { if (it2 != m_data->m_selectedItems.end()) m_data->m_selectedItems.erase(it2); } if (m_data->m_selAction) m_data->m_selAction->sendCommand(i); invalidate(); } //------------------------------------------------------------------------------ void TTextList::select(const string &itemId, bool on) { std::map::iterator it = m_data->m_items.find(itemId); if (it != m_data->m_items.end()) { int i = distance(m_data->m_items.begin(), it); select(i, on); } } //------------------------------------------------------------------------------ void TTextList::unselectAll() { m_data->m_selectedItems.clear(); invalidate(); } //------------------------------------------------------------------------------ bool TTextList::isSelected(int i) const { assert(i >= 0 && i < (int)m_data->m_items.size()); std::map::iterator it = m_data->m_items.begin(); advance(it, i); string id = it->first; vector::iterator it2 = find(m_data->m_selectedItems.begin(), m_data->m_selectedItems.end(), id); return it2 != m_data->m_selectedItems.end(); } //------------------------------------------------------------------------------ bool TTextList::isSelected(const string &item) const { assert(false); return false; } //------------------------------------------------------------------------------ void TTextList::scrollTo(int y) { y = (y / rowHeight) * rowHeight; if (m_data->m_yoffset == y) return; m_data->m_yoffset = y; m_data->updateScrollBarStatus(); invalidate(); } //------------------------------------------------------------------------------ void TTextList::draw() { drawRect(TRect(TPoint(0, 0), getSize())); TDimension d = getSize(); int y = d.ly - 1 - rowHeight; for (int i = m_data->m_yoffset / rowHeight; i < getItemCount() && y >= 0; ++i, y -= rowHeight) { if (isSelected(i)) { setColor(Blue, 2); fillRect(2, y - 2, getSize().lx - 1 - 2, y + rowHeight - 1 - 2); } setColor(Black); drawText(TPoint(10, y), getItem(i)->getCaption()); } } //------------------------------------------------------------------------------ void TTextList::setSelAction(TGenericTextListAction *action) { if (m_data->m_selAction) delete m_data->m_selAction; m_data->m_selAction = action; } //------------------------------------------------------------------------------ void TTextList::setDblClickAction(TGenericTextListAction *action) { if (m_data->m_dblClickAction) delete m_data->m_dblClickAction; m_data->m_dblClickAction = action; } //------------------------------------------------------------------------------ void TTextList::configureNotify(const TDimension &d) { m_data->m_scrollbar->setGeometry(d.lx - 20, 1, d.lx - 2, d.ly - 2); m_data->updateScrollBarStatus(); } //------------------------------------------------------------------------------ void TTextList::leftButtonDown(const TMouseEvent &e) { int i = m_data->posToItem(e.m_pos); if (i >= 0 && i < (int)m_data->m_items.size()) { if (!e.isShiftPressed()) unselectAll(); select(i, !isSelected(i)); } } //------------------------------------------------------------------------------ void TTextList::leftButtonDoubleClick(const TMouseEvent &e) { int i = m_data->posToItem(e.m_pos); if (i >= 0 && i < (int)m_data->m_items.size()) { if (m_data->m_dblClickAction) m_data->m_dblClickAction->sendCommand(i); } } //------------------------------------------------------------------------------ void TTextList::keyDown(int key, unsigned long mod, const TPoint &pos) { if ((key == TK_UpArrow) || (key == TK_DownArrow)) { int lastSelected = -1; for (int i = 0; i < getItemCount(); ++i) if (isSelected(i)) lastSelected = i; if (lastSelected == -1) return; int newSelected = (key == TK_UpArrow) ? lastSelected - 1 : lastSelected + 1; if (newSelected >= 0 && newSelected < (int)m_data->m_items.size()) { // if (!e.isShiftPressed()) unselectAll(); select(newSelected, !isSelected(newSelected)); } } else TWidget::keyDown(key, mod, pos); }