void CStatusLineCtrl::OnPaint(wxPaintEvent& event) { wxPaintDC dc(this); wxRect rect = GetRect(); int refresh = 0; if (!m_data.IsOk() || rect.GetWidth() != m_data.GetWidth() || rect.GetHeight() != m_data.GetHeight()) { delete m_mdc; m_data = wxBitmap(rect.GetWidth(), rect.GetHeight()); m_mdc = new wxMemoryDC(m_data); refresh = 15; } int elapsed_seconds = 0; wxTimeSpan elapsed; int left = -1; wxFileOffset rate; wxString bytes_and_rate; int bar_split = -1; int permill = -1; if (!m_pStatus) { if (!m_pPreviousStatusText || *m_pPreviousStatusText != m_statusText) { // Clear background m_mdc->SetFont(GetFont()); m_mdc->SetPen(GetBackgroundColour()); m_mdc->SetBrush(GetBackgroundColour()); m_mdc->SetTextForeground(GetForegroundColour()); m_mdc->DrawRectangle(0, 0, rect.GetWidth(), rect.GetHeight()); wxCoord h = (rect.GetHeight() - m_textHeight) / 2; m_mdc->DrawText(m_statusText, 50, h); delete m_pPreviousStatusText; m_pPreviousStatusText = new wxString(m_statusText); refresh = 0; } } else { if (m_pPreviousStatusText) { delete m_pPreviousStatusText; m_pPreviousStatusText = 0; refresh = 15; } if (m_pStatus->started.IsValid()) { elapsed = wxDateTime::Now().Subtract(m_pStatus->started); elapsed_seconds = elapsed.GetSeconds().GetLo(); // Assume GetHi is always 0 } if (elapsed_seconds != m_last_elapsed_seconds) { refresh |= 1; m_last_elapsed_seconds = elapsed_seconds; } if (COptions::Get()->GetOptionVal(OPTION_SPEED_DISPLAY)) rate = GetCurrentSpeed(); else rate = GetSpeed(elapsed_seconds); if (elapsed_seconds && rate > -1) { left = ((m_pStatus->totalSize - m_pStatus->startOffset) / rate) - elapsed_seconds; if (left < 0) left = 0; } if (m_last_left != left) { refresh |= 2; m_last_left = left; } const wxString bytestr = CSizeFormat::Format(m_pStatus->currentOffset, true, CSizeFormat::bytes, COptions::Get()->GetOptionVal(OPTION_SIZE_USETHOUSANDSEP) != 0, 0); if (elapsed_seconds && rate > -1) { if (rate > (1000*1000)) bytes_and_rate.Printf(_("%s (%d.%d MB/s)"), bytestr.c_str(), (int)(rate / 1000 / 1000), (int)((rate / 1000 / 100) % 10)); else if (rate > 1000) bytes_and_rate.Printf(_("%s (%d.%d KB/s)"), bytestr.c_str(), (int)(rate / 1000), (int)((rate / 100) % 10)); else bytes_and_rate.Printf(_("%s (%d B/s)"), bytestr.c_str(), (int)rate); } else bytes_and_rate.Printf(_("%s (? B/s)"), bytestr.c_str()); if (m_last_bytes_and_rate != bytes_and_rate) { refresh |= 8; m_last_bytes_and_rate = bytes_and_rate; } if (m_pStatus->totalSize > 0) { bar_split = wxLongLong(m_pStatus->currentOffset * (PROGRESSBAR_WIDTH - 2) / m_pStatus->totalSize).GetLo(); if (bar_split > (PROGRESSBAR_WIDTH - 2)) bar_split = PROGRESSBAR_WIDTH - 2; if (m_pStatus->currentOffset > m_pStatus->totalSize) permill = 1001; else permill = wxLongLong(m_pStatus->currentOffset * 1000 / m_pStatus->totalSize).GetLo(); } if (m_last_bar_split != bar_split || m_last_permill != permill) { refresh |= 4; m_last_bar_split = bar_split; m_last_permill = permill; } } if (refresh) { m_mdc->SetFont(GetFont()); m_mdc->SetPen(GetBackgroundColour()); m_mdc->SetBrush(GetBackgroundColour()); m_mdc->SetTextForeground(GetForegroundColour()); // Get character height so that we can center the text vertically. wxCoord h = (rect.GetHeight() - m_textHeight) / 2; if (refresh & 1) { m_mdc->DrawRectangle(0, 0, m_fieldOffsets[0], rect.GetHeight()); DrawRightAlignedText(*m_mdc, elapsed.Format(_("%H:%M:%S elapsed")), m_fieldOffsets[0], h); } if (refresh & 2) { m_mdc->DrawRectangle(m_fieldOffsets[0], 0, m_fieldOffsets[1] - m_fieldOffsets[0], rect.GetHeight()); if (left != -1) { wxTimeSpan timeLeft(0, 0, left); DrawRightAlignedText(*m_mdc, timeLeft.Format(_("%H:%M:%S left")), m_fieldOffsets[1], h); } else DrawRightAlignedText(*m_mdc, _("--:--:-- left"), m_fieldOffsets[1], h); } if (refresh & 8) { m_mdc->DrawRectangle(m_fieldOffsets[3], 0, rect.GetWidth() - m_fieldOffsets[3], rect.GetHeight()); m_mdc->DrawText(bytes_and_rate, m_fieldOffsets[3], h); } if (refresh & 4) { if (bar_split != -1) DrawProgressBar(*m_mdc, m_fieldOffsets[2], 1, rect.GetHeight() - 2, bar_split, permill); else m_mdc->DrawRectangle(m_fieldOffsets[2], 0, m_fieldOffsets[3] - m_fieldOffsets[2], rect.GetHeight()); } } dc.Blit(0, 0, rect.GetWidth(), rect.GetHeight(), m_mdc, 0, 0); }
void CStatusLineCtrl::OnPaint(wxPaintEvent&) { wxPaintDC dc(this); wxRect rect = GetRect(); int refresh = 0; if (!m_data.IsOk() || rect.GetWidth() != m_data.GetWidth() || rect.GetHeight() != m_data.GetHeight()) { m_mdc.reset(); m_data = wxBitmap(rect.GetWidth(), rect.GetHeight()); m_mdc = std::make_unique<wxMemoryDC>(m_data); // Use same layout direction as the DC which bitmap is drawn on. // This avoids problem with mirrored characters on RTL locales. m_mdc->SetLayoutDirection(dc.GetLayoutDirection()); refresh = 31; } fz::duration elapsed; int left = -1; wxFileOffset rate; wxString bytes_and_rate; int bar_split = -1; int permill = -1; if (status_.empty()) { if (m_previousStatusText != m_statusText) { // Clear background m_mdc->SetFont(GetFont()); m_mdc->SetPen(GetBackgroundColour()); m_mdc->SetBrush(GetBackgroundColour()); m_mdc->SetTextForeground(GetForegroundColour()); m_mdc->DrawRectangle(0, 0, rect.GetWidth(), rect.GetHeight()); wxCoord h = (rect.GetHeight() - m_textHeight) / 2; m_mdc->DrawText(m_statusText, 50, h); m_previousStatusText = m_statusText; refresh = 0; } } else { if (!m_previousStatusText.empty()) { m_previousStatusText.clear(); refresh = 31; } int elapsed_milli_seconds = 0; if (!status_.started.empty()) { elapsed = fz::datetime::now() - status_.started; elapsed_milli_seconds = static_cast<int>(elapsed.get_milliseconds()); // Assume it doesn't overflow } if (elapsed_milli_seconds / 1000 != m_last_elapsed_seconds) { refresh |= 1; m_last_elapsed_seconds = elapsed_milli_seconds / 1000; } if (COptions::Get()->GetOptionVal(OPTION_SPEED_DISPLAY)) rate = GetMomentarySpeed(); else rate = GetAverageSpeed(elapsed_milli_seconds); if (status_.totalSize > 0 && elapsed_milli_seconds >= 1000 && rate > 0) { wxFileOffset r = status_.totalSize - status_.currentOffset; left = r / rate + 1; if (r) ++left; if (left < 0) left = 0; } if (m_last_left != left) { refresh |= 2; m_last_left = left; } const wxString bytestr = CSizeFormat::Format(status_.currentOffset, true, CSizeFormat::bytes, COptions::Get()->GetOptionVal(OPTION_SIZE_USETHOUSANDSEP) != 0, 0); if (elapsed_milli_seconds >= 1000 && rate > -1) { CSizeFormat::_format format = static_cast<CSizeFormat::_format>(COptions::Get()->GetOptionVal(OPTION_SIZE_FORMAT)); if (format == CSizeFormat::bytes) format = CSizeFormat::iec; const wxString ratestr = CSizeFormat::Format(rate, true, format, COptions::Get()->GetOptionVal(OPTION_SIZE_USETHOUSANDSEP) != 0, COptions::Get()->GetOptionVal(OPTION_SIZE_DECIMALPLACES)); bytes_and_rate.Printf(_("%s (%s/s)"), bytestr, ratestr ); } else bytes_and_rate.Printf(_("%s (? B/s)"), bytestr); if (m_last_bytes_and_rate != bytes_and_rate) { refresh |= 8; m_last_bytes_and_rate = bytes_and_rate; } if (status_.totalSize > 0) { bar_split = static_cast<int>(status_.currentOffset * (PROGRESSBAR_WIDTH - 2) / status_.totalSize); if (bar_split > (PROGRESSBAR_WIDTH - 2)) bar_split = PROGRESSBAR_WIDTH - 2; if (status_.currentOffset > status_.totalSize) permill = 1001; else permill = static_cast<int>(status_.currentOffset * 1000 / status_.totalSize); } if (m_last_bar_split != bar_split || m_last_permill != permill) { refresh |= 4; m_last_bar_split = bar_split; m_last_permill = permill; } } if (refresh) { m_mdc->SetFont(GetFont()); m_mdc->SetPen(GetBackgroundColour()); m_mdc->SetBrush(GetBackgroundColour()); m_mdc->SetTextForeground(GetForegroundColour()); // Get character height so that we can center the text vertically. wxCoord h = (rect.GetHeight() - m_textHeight) / 2; if (refresh & 1) { m_mdc->DrawRectangle(0, 0, m_fieldOffsets[0], rect.GetHeight()); DrawRightAlignedText(*m_mdc, wxTimeSpan::Milliseconds(elapsed.get_milliseconds()).Format(_("%H:%M:%S elapsed")), m_fieldOffsets[0], h); } if (refresh & 2) { m_mdc->DrawRectangle(m_fieldOffsets[0], 0, m_fieldOffsets[1] - m_fieldOffsets[0], rect.GetHeight()); if (left != -1) { wxTimeSpan timeLeft(0, 0, left); DrawRightAlignedText(*m_mdc, timeLeft.Format(_("%H:%M:%S left")), m_fieldOffsets[1], h); } else DrawRightAlignedText(*m_mdc, _("--:--:-- left"), m_fieldOffsets[1], h); } if (refresh & 8) { m_mdc->DrawRectangle(m_fieldOffsets[3], 0, rect.GetWidth() - m_fieldOffsets[3], rect.GetHeight()); m_mdc->DrawText(bytes_and_rate, m_fieldOffsets[3], h); } if (refresh & 16) { m_mdc->DrawRectangle(m_fieldOffsets[1], 0, m_fieldOffsets[2] - m_fieldOffsets[1], rect.GetHeight()); } if (refresh & 4) { m_mdc->DrawRectangle(m_fieldOffsets[2], 0, m_fieldOffsets[3] - m_fieldOffsets[2], rect.GetHeight()); if (bar_split != -1) DrawProgressBar(*m_mdc, m_fieldOffsets[2], 1, rect.GetHeight() - 2, bar_split, permill); } } dc.Blit(0, 0, rect.GetWidth(), rect.GetHeight(), m_mdc.get(), 0, 0); }