void wxVScrolledWindow::RefreshLines(size_t from, size_t to) { wxASSERT_MSG( from <= to, _T("RefreshLines(): empty range") ); // clump the range to just the visible lines -- it is useless to refresh // the other ones if ( from < GetVisibleBegin() ) from = GetVisibleBegin(); if ( to >= GetVisibleEnd() ) to = GetVisibleEnd(); else to++; // calculate the rect occupied by these lines on screen wxRect rect; rect.width = GetClientSize().x; for ( size_t nBefore = GetVisibleBegin(); nBefore < from; nBefore++ ) { rect.y += OnGetLineHeight(nBefore); } for ( size_t nBetween = from; nBetween < to; nBetween++ ) { rect.height += OnGetLineHeight(nBetween); } // do refresh it RefreshRect(rect); }
bool wxVScrolledWindow::ScrollToLine(size_t line) { if ( !m_lineMax ) { // we're empty, code below doesn't make sense in this case return false; } // determine the real first line to scroll to: we shouldn't scroll beyond // the end size_t lineFirstLast = FindFirstFromBottom(m_lineMax - 1, true); if ( line > lineFirstLast ) line = lineFirstLast; // anything to do? if ( line == m_lineFirst ) { // no return false; } // remember the currently shown lines for the refresh code below size_t lineFirstOld = GetVisibleBegin(), lineLastOld = GetVisibleEnd(); m_lineFirst = line; // the size of scrollbar thumb could have changed UpdateScrollbar(); // finally refresh the display -- but only redraw as few lines as possible // to avoid flicker if ( GetChildren().empty() && (GetVisibleBegin() >= lineLastOld || GetVisibleEnd() <= lineFirstOld ) ) { // the simplest case: we don't have any old lines left, just redraw // everything Refresh(); } else // overlap between the lines we showed before and should show now { // Avoid scrolling visible parts of the screen on Mac #ifdef __WXMAC__ if (!IsShownOnScreen()) Refresh(); else #endif ScrollWindow(0, GetLinesHeight(GetVisibleBegin(), lineFirstOld)); } return true; }
wxPoint wxHtmlListBox::GetRootCellCoords(size_t n) const { wxPoint pos(CELL_BORDER, CELL_BORDER); pos += GetMargins(); pos.y += GetRowsHeight(GetVisibleBegin(), n); return pos; }
bool wxVScrolledWindow::ScrollPages(int pages) { bool didSomething = false; while ( pages ) { int line; if ( pages > 0 ) { line = GetVisibleEnd(); if ( line ) line--; pages--; } else // pages < 0 { line = FindFirstFromBottom(GetVisibleBegin()); pages++; } didSomething = ScrollToLine(line); } return didSomething; }
void wxVListBoxComboPopup::OnMouseMove(wxMouseEvent& event) { event.Skip(); // Move selection to cursor if it is inside the popup int y = event.GetPosition().y; int fromBottom = GetClientSize().y - y; // Since in any case we need to find out if the last item is only // partially visible, we might just as well replicate the HitTest // loop here. const size_t lineMax = GetVisibleEnd(); for ( size_t line = GetVisibleBegin(); line < lineMax; line++ ) { y -= OnGetRowHeight(line); if ( y < 0 ) { // Only change selection if item is fully visible if ( (y + fromBottom) >= 0 ) { wxVListBox::SetSelection((int)line); return; } } } }
wxPoint ContentBoxCtrol::GetRootCellCoords(size_t n) const { wxPoint pos(CELL_BORDER, CELL_BORDER); pos += GetMargins(); //pos.y += GetRowHeight(GetVisibleRowsBegin(), n); pos.y += GetRowsHeight(GetVisibleBegin(), n); return pos; }
void wxVListBox::RefreshSelected() { // only refresh those items which are currently visible and selected: for ( size_t n = GetVisibleBegin(), end = GetVisibleEnd(); n < end; n++ ) { if ( IsSelected(n) ) RefreshRow(n); } }
// hit testing int wxSymbolListCtrl::HitTest(const wxPoint& pt) { wxCoord lineHeight = OnGetRowHeight(0); int atLine = GetVisibleBegin() + (pt.y/lineHeight); int symbol = (atLine*m_symbolsPerLine) + (pt.x/(m_cellSize.x+1)); if (symbol >= m_minSymbolValue && symbol <= m_maxSymbolValue) return symbol; return -1; }
int wxVScrolledWindow::HitTest(wxCoord WXUNUSED(x), wxCoord y) const { const size_t lineMax = GetVisibleEnd(); for ( size_t line = GetVisibleBegin(); line < lineMax; line++ ) { y -= OnGetLineHeight(line); if ( y < 0 ) return line; } return wxNOT_FOUND; }
void wxVListBox::OnPaint(wxPaintEvent& WXUNUSED(event)) { wxSize clientSize = GetClientSize(); wxAutoBufferedPaintDC dc(this); // the update rectangle wxRect rectUpdate = GetUpdateClientRect(); // fill it with background colour dc.SetBackground(GetBackgroundColour()); dc.Clear(); // the bounding rectangle of the current line wxRect rectRow; rectRow.width = clientSize.x; // iterate over all visible lines const size_t lineMax = GetVisibleEnd(); for ( size_t line = GetVisibleBegin(); line < lineMax; line++ ) { const wxCoord hRow = OnGetRowHeight(line); rectRow.height = hRow; // and draw the ones which intersect the update rect if ( rectRow.Intersects(rectUpdate) ) { // don't allow drawing outside of the lines rectangle wxDCClipper clip(dc, rectRow); wxRect rect = rectRow; OnDrawBackground(dc, rect, line); OnDrawSeparator(dc, rect, line); rect.Deflate(m_ptMargins.x, m_ptMargins.y); OnDrawItem(dc, rect, line); } else // no intersection { if ( rectRow.GetTop() > rectUpdate.GetBottom() ) { // we are already below the update rect, no need to continue // further break; } //else: the next line may intersect the update rect } rectRow.y += hRow; } }
// // Handle the wxEVT_LEFT_DOWN event // void KeyView::OnLeftDown(wxMouseEvent & event) { // Only check if for tree view if (mViewType != ViewByTree) { // Allow further processing (important for focus handling) event.Skip(); return; } // Get the mouse position when the button was pressed wxPoint pos = event.GetPosition(); // And see if it was on a line within the view int line = HitTest(pos); // It was on a line if (line != wxNOT_FOUND) { KeyNode *node = mLines[line]; // Toggle the open state if this is a parent node if (node->isparent) { // Toggle state node->isopen = !node->isopen; // Don't want the view to scroll vertically, so remember the current // top line. size_t topline = GetVisibleBegin(); // Refresh the view now that the number of lines have changed RefreshLines(); // Reset the original top line ScrollToLine(topline); // And make sure current line is still selected SelectNode(LineToIndex(line)); } } // Allow further processing (important for focus handling) event.Skip(); }
bool wxVListBox::DoSetCurrent(int current) { wxASSERT_MSG( current == wxNOT_FOUND || (current >= 0 && (size_t)current < GetItemCount()), wxT("wxVListBox::DoSetCurrent(): invalid item index") ); if ( current == m_current ) { // nothing to do return false; } if ( m_current != wxNOT_FOUND ) RefreshRow(m_current); m_current = current; if ( m_current != wxNOT_FOUND ) { // if the line is not visible at all, we scroll it into view but we // don't need to refresh it -- it will be redrawn anyhow if ( !IsVisible(m_current) ) { ScrollToRow(m_current); } else // line is at least partly visible { // it is, indeed, only partly visible, so scroll it into view to // make it entirely visible // BUT scrolling down when m_current is first visible makes it // completely hidden, so that is even worse while ( (size_t)m_current + 1 == GetVisibleRowsEnd() && (size_t)m_current != GetVisibleRowsBegin() && ScrollToRow(GetVisibleBegin() + 1) ) ; // but in any case refresh it as even if it was only partly visible // before we need to redraw it entirely as its background changed RefreshRow(m_current); } } return true; }
bool wxSymbolListCtrl::DoSetCurrent(int current) { wxASSERT_MSG( current == wxNOT_FOUND || (current >= m_minSymbolValue && current <= m_maxSymbolValue), wxT("wxSymbolListCtrl::DoSetCurrent(): invalid symbol value") ); if ( current == m_current ) { // nothing to do return false; } if ( m_current != wxNOT_FOUND ) RefreshRow(SymbolValueToLineNumber(m_current)); m_current = current; if ( m_current != wxNOT_FOUND ) { int lineNo = SymbolValueToLineNumber(m_current); // if the line is not visible at all, we scroll it into view but we // don't need to refresh it -- it will be redrawn anyhow if ( !IsVisible(lineNo) ) { ScrollToRow(lineNo); } else // line is at least partly visible { // it is, indeed, only partly visible, so scroll it into view to // make it entirely visible while ( (unsigned)lineNo + 1 == GetVisibleEnd() && ScrollToRow(GetVisibleBegin() + 1) ) ; // but in any case refresh it as even if it was only partly visible // before we need to redraw it entirely as its background changed RefreshRow(lineNo); } } return true; }
void wxVScrolledWindow::RefreshLine(size_t line) { // is this line visible? if ( !IsVisible(line) ) { // no, it is useless to do anything return; } // calculate the rect occupied by this line on screen wxRect rect; rect.width = GetClientSize().x; rect.height = OnGetLineHeight(line); for ( size_t n = GetVisibleBegin(); n < line; n++ ) { rect.y += OnGetLineHeight(n); } // do refresh it RefreshRect(rect); }
bool ContentBoxCtrol::DoSetCurrent(int current) { wxASSERT_MSG( current == wxNOT_FOUND || (current >= 0 && (size_t)current < GetItemCount()), "ContentBoxCtrol::DoSetCurrent(): invalid item index" ); if ( current == m_current ) { // nothing to do return false; } if ( m_current != wxNOT_FOUND ) wxVScrolledWindow::RefreshRow(m_current); m_current = current; if ( m_current != wxNOT_FOUND ) { // if the line is not visible at all, we scroll it into view but we // don't need to refresh it -- it will be redrawn anyhow if ( !IsVisible(m_current) ) { ScrollToRow(m_current); } else // line is at least partly visible { // it is, indeed, only partly visible, so scroll it into view to // make it entirely visible while ( (size_t)m_current == GetVisibleRowsEnd() && ScrollToRow(GetVisibleBegin()+1) ) ; // but in any case refresh it as even if it was only partly visible // before we need to redraw it entirely as its background changed wxVScrolledWindow::RefreshRow(m_current); } } return true; }
wxRect wxVListBox::GetItemRect(size_t n) const { wxRect itemrect; // check that this item is visible const size_t lineMax = GetVisibleEnd(); if ( n >= lineMax ) return itemrect; size_t line = GetVisibleBegin(); if ( n < line ) return itemrect; while ( line <= n ) { itemrect.y += itemrect.height; itemrect.height = OnGetRowHeight(line); line++; } itemrect.width = GetClientSize().x; return itemrect; }
void wxSymbolListCtrl::OnPaint(wxPaintEvent& WXUNUSED(event)) { // If size is larger, recalculate double buffer bitmap wxSize clientSize = GetClientSize(); if ( !m_doubleBuffer || clientSize.x > m_doubleBuffer->GetWidth() || clientSize.y > m_doubleBuffer->GetHeight() ) { delete m_doubleBuffer; m_doubleBuffer = new wxBitmap(clientSize.x+25,clientSize.y+25); } wxBufferedPaintDC dc(this,*m_doubleBuffer); // the update rectangle wxRect rectUpdate = GetUpdateClientRect(); // fill it with background colour dc.SetBackground(GetBackgroundColour()); dc.Clear(); // set the font to be displayed dc.SetFont(GetFont()); // the bounding rectangle of the current line wxRect rectRow; rectRow.width = clientSize.x; dc.SetPen(wxPen(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT))); dc.SetTextForeground(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT)); dc.SetBackgroundMode(wxBRUSHSTYLE_TRANSPARENT); // iterate over all visible lines const size_t lineMax = GetVisibleEnd(); for ( size_t line = GetVisibleBegin(); line < lineMax; line++ ) { const wxCoord hRow = OnGetRowHeight(line); rectRow.height = hRow; // and draw the ones which intersect the update rect if ( rectRow.Intersects(rectUpdate) ) { // don't allow drawing outside of the lines rectangle wxDCClipper clip(dc, rectRow); wxRect rect = rectRow; rect.Deflate(m_ptMargins.x, m_ptMargins.y); OnDrawItem(dc, rect, line); } else // no intersection { if ( rectRow.GetTop() > rectUpdate.GetBottom() ) { // we are already below the update rect, no need to continue // further break; } //else: the next line may intersect the update rect } rectRow.y += hRow; } }
// // Handle the wxEVT_KEY_DOWN event // void KeyView::OnKeyDown(wxKeyEvent & event) { int line = GetSelection(); int keycode = event.GetKeyCode(); switch (keycode) { // The LEFT key moves selection to parent or collapses selected // node if it is expanded. case WXK_LEFT: { // Nothing selected...nothing to do if (line == wxNOT_FOUND) { // Allow further processing event.Skip(); break; } KeyNode *node = mLines[line]; // Collapse the node if it is open if (node->isopen) { // No longer open node->isopen = false; // Don't want the view to scroll vertically, so remember the current // top line. size_t topline = GetVisibleBegin(); // Refresh the view now that the number of lines have changed RefreshLines(); // Reset the original top line ScrollToLine(topline); // And make sure current line is still selected SelectNode(LineToIndex(line)); } else { // Move selection to the parent of this node for (int i = line - 1; i >= 0; i--) { // Found the parent if (mLines[i]->depth < node->depth) { // So select it SelectNode(LineToIndex(i)); break; } } } // Further processing of the event is not wanted // (we didn't call event.Skip() } break; // The RIGHT key moves the selection to the first child or expands // the node if it is a parent. case WXK_RIGHT: { // Nothing selected...nothing to do if (line == wxNOT_FOUND) { // Allow further processing event.Skip(); break; } KeyNode *node = mLines[line]; // Only want parent nodes if (node->isparent) { // It is open so move select to first child if (node->isopen) { // But only if there is one if (line < (int) mLines.GetCount() - 1) { SelectNode(LineToIndex(line + 1)); } } else { // Node is now open node->isopen = true; // Don't want the view to scroll vertically, so remember the current // top line. size_t topline = GetVisibleBegin(); // Refresh the view now that the number of lines have changed RefreshLines(); // Reset the original top line ScrollToLine(topline); // And make sure current line is still selected SelectNode(LineToIndex(line)); } } // Further processing of the event is not wanted // (we didn't call event.Skip() } break; // Move selection to next node whose 1st character matches // the keycode default: { int cnt = (int) mLines.GetCount(); bool found = false; // Search the entire list if not is currently selected if (line == wxNOT_FOUND) { line = cnt; } else { // Search from the node following the current one for (int i = line + 1; i < cnt; i++) { wxString label; // Get the string to search based on view type if (mViewType == ViewByTree) { label = GetLabel(LineToIndex(i)); } else if (mViewType == ViewByName) { label = GetFullLabel(LineToIndex(i)); } else if (mViewType == ViewByKey) { label = GetKey(LineToIndex(i)); } // Move selection if they match if (label.Left(1).IsSameAs(keycode, false)) { SelectNode(LineToIndex(i)); found = true; break; } } } // A match wasn't found if (!found) { // So scan from the start of the list to the current node for (int i = 0; i < line; i++) { wxString label; // Get the string to search based on view type if (mViewType == ViewByTree) { label = GetLabel(LineToIndex(i)); } else if (mViewType == ViewByName) { label = GetFullLabel(LineToIndex(i)); } else if (mViewType == ViewByKey) { label = GetKey(LineToIndex(i)); } // Move selection if they match if (label.Left(1).IsSameAs(keycode, false)) { SelectNode(LineToIndex(i)); found = true; break; } } } // A node wasn't found so allow further processing if (!found) { event.Skip(); } // Otherwise, further processing of the event is not wanted // (we didn't call event.Skip() } } }
void wxVListBox::OnKeyDown(wxKeyEvent& event) { // flags for DoHandleItemClick() int flags = ItemClick_Kbd; int current; switch ( event.GetKeyCode() ) { case WXK_HOME: case WXK_NUMPAD_HOME: current = 0; break; case WXK_END: case WXK_NUMPAD_END: current = GetRowCount() - 1; break; case WXK_DOWN: case WXK_NUMPAD_DOWN: if ( m_current == (int)GetRowCount() - 1 ) return; current = m_current + 1; break; case WXK_UP: case WXK_NUMPAD_UP: if ( m_current == wxNOT_FOUND ) current = GetRowCount() - 1; else if ( m_current != 0 ) current = m_current - 1; else // m_current == 0 return; break; case WXK_PAGEDOWN: case WXK_NUMPAD_PAGEDOWN: PageDown(); current = GetVisibleBegin(); break; case WXK_PAGEUP: case WXK_NUMPAD_PAGEUP: if ( m_current == (int)GetVisibleBegin() ) { PageUp(); } current = GetVisibleBegin(); break; case WXK_SPACE: // hack: pressing space should work like a mouse click rather than // like a keyboard arrow press, so trick DoHandleItemClick() in // thinking we were clicked flags &= ~ItemClick_Kbd; current = m_current; break; #ifdef __WXMSW__ case WXK_TAB: // Since we are using wxWANTS_CHARS we need to send navigation // events for the tabs on MSW HandleAsNavigationKey(event); // fall through to default #endif default: event.Skip(); current = 0; // just to silent the stupid compiler warnings wxUnusedVar(current); return; } if ( event.ShiftDown() ) flags |= ItemClick_Shift; if ( event.ControlDown() ) flags |= ItemClick_Ctrl; DoHandleItemClick(current, flags); }