void WaypointListRenderer::Draw(Canvas &canvas, const PixelRect rc, const Waypoint &waypoint, const GeoVector *vector, const DialogLook &dialog_look, const WaypointLook &look, const WaypointRendererSettings &settings) { const PixelScalar line_height = rc.bottom - rc.top; const Font &name_font = *dialog_look.list.font; const Font &small_font = *dialog_look.small_font; Buffer buffer; // Y-Coordinate of the second row PixelScalar top2 = rc.top + name_font.GetHeight() + Layout::FastScale(4); // Use small font for details canvas.Select(small_font); // Draw leg distance UPixelScalar leg_info_width = 0; if (vector) { FormatUserDistanceSmart(vector->distance, buffer.buffer(), true); UPixelScalar width = leg_info_width = canvas.CalcTextWidth(buffer.c_str()); canvas.text(rc.right - Layout::FastScale(2) - width, rc.top + Layout::FastScale(2) + (name_font.GetHeight() - small_font.GetHeight()) / 2, buffer.c_str()); // Draw leg bearing FormatBearing(buffer.buffer(), buffer.MAX_SIZE, vector->bearing); width = canvas.CalcTextWidth(buffer.c_str()); canvas.text(rc.right - Layout::FastScale(2) - width, top2, buffer.c_str()); if (width > leg_info_width) leg_info_width = width; leg_info_width += Layout::FastScale(2); } // Draw details line FormatWaypointDetails(buffer, waypoint); PixelScalar left = rc.left + line_height + Layout::FastScale(2); canvas.text_clipped(left, top2, rc.right - leg_info_width - left, buffer.c_str()); // Draw waypoint name canvas.Select(name_font); canvas.text_clipped(left, rc.top + Layout::FastScale(2), rc.right - leg_info_width - left, waypoint.name.c_str()); // Draw icon RasterPoint pt = { (PixelScalar)(rc.left + line_height / 2), (PixelScalar)(rc.top + line_height / 2) }; WaypointIconRenderer wir(settings, look, canvas); wir.Draw(waypoint, pt); }
static void DrawBanner(Canvas &canvas, PixelRect &rc) { const unsigned padding = 2; const Bitmap logo(IDB_LOGO); const unsigned banner_height = logo.GetHeight(); /* draw the XCSoar logo */ int x = rc.left + padding; canvas.Copy(x, rc.top + padding, logo.GetWidth(), logo.GetHeight(), logo, 0, 0); x += logo.GetWidth() + 8; canvas.Select(bold_font); canvas.SetTextColor(COLOR_BLACK); canvas.SetBackgroundTransparent(); /* draw the XCSoar banner text with a larger font */ Font large_font; large_font.LoadFile("/opt/xcsoar/share/fonts/VeraBd.ttf", 40); canvas.Select(large_font); const unsigned name_y = rc.top + (banner_height - large_font.GetHeight()) / 2; const TCHAR *const name1 = _T("XC"); canvas.DrawText(x, name_y, name1); x += canvas.CalcTextWidth(name1); const TCHAR *const name2 = _T("Soar"); canvas.SetTextColor(COLOR_GRAY); canvas.DrawText(x, name_y, name2); canvas.SetTextColor(COLOR_BLACK); x += canvas.CalcTextWidth(name2) + 30; /* some more text */ const TCHAR *const website = _T("www.xcsoar.org"); canvas.Select(normal_font); canvas.DrawText(x, rc.top + (banner_height - normal_font.GetHeight()) / 2, website); const TCHAR *const comment = _T("powered off"); canvas.DrawText(rc.right - canvas.CalcTextWidth(comment) - padding, rc.top + padding, comment); rc.top += banner_height + 8; }
void WifiListWidget::OnPaintItem(Canvas &canvas, const PixelRect rc, unsigned idx) { const DialogLook &look = UIGlobals::GetDialogLook(); const auto &info = networks[idx]; const unsigned padding = Layout::GetTextPadding(); const unsigned x1 = rc.left + padding; const unsigned y1 = rc.top + padding; const unsigned y2 = y1 + look.text_font->GetHeight() + padding; static char wifi_security[][20] = { "WPA", "WEP", "Open", }; canvas.Select(*look.text_font); canvas.DrawText(x1, y1, info.ssid); canvas.Select(*look.small_font); canvas.DrawText(x1, y2, info.bssid); const TCHAR *state = nullptr; StaticString<40> state_buffer; /* found the currently connected wifi network? */ if (StringIsEqual(info.bssid, status.bssid)) { state = _("Connected"); /* look up ip address for eth0 */ const auto addr = IPv4Address::GetDeviceAddress("eth0"); if (addr.IsDefined()) { /* valid address? */ StaticString<40> addr_str; if (addr.ToString(addr_str.buffer(), addr_str.MAX_SIZE) != nullptr) { state_buffer.Format(_T("%s (%s)"), state, addr_str.c_str()); state = state_buffer; } } } else if (info.id >= 0) state = info.signal_level >= 0 ? _("Saved and visible") : _("Saved, but not visible"); else if (info.signal_level >= 0) state = _("Visible"); if (state != nullptr) { unsigned width = canvas.CalcTextWidth(state); canvas.DrawText(rc.right - padding - width, y1, state); } if (info.signal_level >= 0) { StaticString<20> text; text.UnsafeFormat(_T("%s %u"), wifi_security[info.security], info.signal_level); unsigned width = canvas.CalcTextWidth(text); canvas.DrawText(rc.right - padding - width, y2, text); } }
static void OnAirspacePaintListItem(Canvas &canvas, const PixelRect rc, unsigned i) { assert(i < AIRSPACECLASSCOUNT); const AirspaceComputerSettings &computer = CommonInterface::GetComputerSettings().airspace; const AirspaceRendererSettings &renderer = CommonInterface::GetMapSettings().airspace; const AirspaceLook &look = CommonInterface::main_window.GetLook().map.airspace; PixelScalar w0 = rc.right - rc.left - Layout::FastScale(4); PixelScalar w1 = canvas.CalcTextWidth(_("Warn")) + Layout::FastScale(10); PixelScalar w2 = canvas.CalcTextWidth(_("Display")) + Layout::FastScale(10); PixelScalar x0 = w0 - w1 - w2; if (color_mode) { canvas.SelectWhitePen(); #ifndef HAVE_HATCHED_BRUSH canvas.Select(look.solid_brushes[i]); #else #ifdef HAVE_ALPHA_BLEND if (renderer.transparency && AlphaBlendAvailable()) { canvas.Select(look.solid_brushes[i]); } else { #endif canvas.SetTextColor(renderer.classes[i].color); canvas.SetBackgroundColor(Color(0xFF, 0xFF, 0xFF)); canvas.Select(look.brushes[renderer.classes[i].brush]); #ifdef HAVE_ALPHA_BLEND } #endif #endif canvas.Rectangle(rc.left + x0, rc.top + Layout::FastScale(2), rc.right - Layout::FastScale(2), rc.bottom - Layout::FastScale(2)); } else { if (computer.warnings.class_warnings[i]) canvas.text(rc.left + w0 - w1 - w2, rc.top + Layout::FastScale(2), _("Warn")); if (renderer.classes[i].display) canvas.text(rc.left + w0 - w2, rc.top + Layout::FastScale(2), _("Display")); } canvas.text_clipped(rc.left + Layout::FastScale(2), rc.top + Layout::FastScale(2), x0 - Layout::FastScale(10), AirspaceFormatter::GetClass((AirspaceClass)i)); }
void AirspaceSettingsListWidget::OnPaintItem(Canvas &canvas, const PixelRect rc, unsigned i) { assert(i < AIRSPACECLASSCOUNT); const AirspaceComputerSettings &computer = CommonInterface::GetComputerSettings().airspace; const AirspaceRendererSettings &renderer = CommonInterface::GetMapSettings().airspace; const AirspaceLook &look = CommonInterface::main_window->GetLook().map.airspace; PixelScalar w0 = rc.right - rc.left - Layout::FastScale(4); PixelScalar w1 = canvas.CalcTextWidth(_("Warn")) + Layout::FastScale(10); PixelScalar w2 = canvas.CalcTextWidth(_("Display")) + Layout::FastScale(10); PixelScalar x0 = w0 - w1 - w2; const unsigned padding = Layout::GetTextPadding(); if (color_mode) { if (AirspacePreviewRenderer::PrepareFill( canvas, (AirspaceClass)i, look, renderer)) { canvas.Rectangle(rc.left + x0, rc.top + padding, rc.right - padding, rc.bottom - padding); AirspacePreviewRenderer::UnprepareFill(canvas); } if (AirspacePreviewRenderer::PrepareOutline( canvas, (AirspaceClass)i, look, renderer)) { canvas.Rectangle(rc.left + x0, rc.top + padding, rc.right - padding, rc.bottom - padding); } } else { if (computer.warnings.class_warnings[i]) canvas.DrawText(rc.left + w0 - w1 - w2, rc.top + padding, _("Warn")); if (renderer.classes[i].display) canvas.DrawText(rc.left + w0 - w2, rc.top + padding, _("Display")); } canvas.DrawClippedText(rc.left + padding, rc.top + padding, x0 - Layout::FastScale(10), AirspaceFormatter::GetClass((AirspaceClass)i)); }
void OptionStartsWidget::OnPaintItem(Canvas &canvas, const PixelRect rc, unsigned DrawListIndex) { assert(DrawListIndex <= task.GetOptionalStartPointCount() + (RealStartExists ? 2 : 1)); assert(GetList().GetLength() == task.GetOptionalStartPointCount() + (RealStartExists ? 2 : 1)); const unsigned padding = Layout::GetTextPadding(); const unsigned index_optional_starts = DrawListIndex - (RealStartExists ? 1 : 0); if (DrawListIndex == GetList().GetLength() - 1) { canvas.DrawText(rc.left + padding, rc.top + padding, _("(Add Alternate Start)")); } else { RasterPoint pt(rc.left + padding, rc.top + padding); const OrderedTaskPoint *tp; if (DrawListIndex == 0 && RealStartExists) { tp = &task.GetPoint(0); canvas.DrawText(pt.x, pt.y, _T("*")); pt.x += canvas.CalcTextWidth(_T("*")); } else tp = &task.GetOptionalStartPoint(index_optional_starts); assert(tp != nullptr); canvas.DrawText(pt.x, pt.y, tp->GetWaypoint().name.c_str()); } }
static void OnPaintListItem(Canvas &canvas, const PixelRect rc, unsigned i) { if (AirspaceSelectInfo.empty()) { assert(i == 0); canvas.text(rc.left + Layout::FastScale(2), rc.top + Layout::FastScale(2), _("No Match!")); return; } assert(i < AirspaceSelectInfo.size()); const AbstractAirspace &airspace = *AirspaceSelectInfo[i].airspace; int w0, w1, w2, w3, x1, x2, x3; w0 = rc.right - rc.left - Layout::FastScale(4); w1 = canvas.CalcTextWidth(_T("XXX")); w2 = canvas.CalcTextWidth(_T(" 000km")); w3 = canvas.CalcTextWidth(_T(" 000")_T(DEG)); x1 = w0-w1-w2-w3; canvas.text_clipped(rc.left + Layout::FastScale(2), rc.top + Layout::FastScale(2), x1 - Layout::FastScale(5), airspace.GetNameText().c_str()); // left justified canvas.text(rc.left + x1, rc.top + Layout::FastScale(2), airspace.GetTypeText(true)); StaticString<12> sTmp; // right justified after airspace type sTmp.Format(_T("%d%s"), (int)AirspaceSelectInfo[i].Distance, Units::GetDistanceName()); x2 = w0 - w3 - canvas.CalcTextWidth(sTmp); canvas.text(rc.left + x2, rc.top + Layout::FastScale(2), sTmp); // right justified after distance FormatBearing(sTmp.buffer(), sTmp.MAX_SIZE, AirspaceSelectInfo[i].Direction); x3 = w0 - canvas.CalcTextWidth(sTmp); canvas.text(rc.left + x3, rc.top + Layout::FastScale(2), sTmp); }
void AirspaceListRenderer::Draw(Canvas &canvas, const PixelRect rc, const AbstractAirspace &airspace, const TCHAR *comment, const DialogLook &dialog_look, const AirspaceLook &look, const AirspaceRendererSettings &renderer_settings) { const PixelScalar line_height = rc.bottom - rc.top; const Font &name_font = *dialog_look.list.font; const Font &small_font = *dialog_look.small_font; PixelScalar left = rc.left + line_height + Layout::FastScale(2); canvas.Select(name_font); canvas.text_clipped(left, rc.top + Layout::FastScale(2), rc, airspace.GetName()); canvas.Select(small_font); canvas.text_clipped(left, rc.top + name_font.GetHeight() + Layout::FastScale(4), rc, comment); tstring top = AirspaceFormatter::GetTopShort(airspace); PixelScalar altitude_width = canvas.CalcTextWidth(top.c_str()); canvas.text_clipped(rc.right - altitude_width - Layout::FastScale(4), rc.top + name_font.GetHeight() - small_font.GetHeight() + Layout::FastScale(2), rc, top.c_str()); tstring base = AirspaceFormatter::GetBaseShort(airspace); altitude_width = canvas.CalcTextWidth(base.c_str()); canvas.text_clipped(rc.right - altitude_width - Layout::FastScale(4), rc.top + name_font.GetHeight() + Layout::FastScale(4), rc, base.c_str()); RasterPoint pt = { PixelScalar(rc.left + line_height / 2), PixelScalar(rc.top + line_height / 2) }; PixelScalar radius = std::min(PixelScalar(line_height / 2 - Layout::FastScale(4)), Layout::FastScale(10)); AirspacePreviewRenderer::Draw(canvas, airspace, pt, radius, renderer_settings, look); }
void MapItemListRenderer::Draw(Canvas &canvas, const PixelRect rc, const AirspaceMapItem &item, const DialogLook &dialog_look, const AirspaceLook &look, const AirspaceRendererSettings &renderer_settings) { const PixelScalar line_height = rc.bottom - rc.top; const AbstractAirspace &airspace = *item.airspace; RasterPoint pt = { PixelScalar(rc.left + line_height / 2), PixelScalar(rc.top + line_height / 2) }; PixelScalar radius = std::min(PixelScalar(line_height / 2 - Layout::FastScale(4)), Layout::FastScale(10)); AirspacePreviewRenderer::Draw(canvas, airspace, pt, radius, renderer_settings, look); const Font &name_font = *dialog_look.list.font; const Font &small_font = *dialog_look.small_font; canvas.SetTextColor(COLOR_BLACK); PixelScalar left = rc.left + line_height + Layout::FastScale(2); canvas.Select(name_font); canvas.text_clipped(left, rc.top + Layout::FastScale(2), rc, airspace.GetName()); canvas.Select(small_font); canvas.text_clipped(left, rc.top + name_font.GetHeight() + Layout::FastScale(4), rc, airspace.GetTypeText(false)); PixelScalar altitude_width = canvas.CalcTextWidth(airspace.GetTopText(true).c_str()); canvas.text_clipped(rc.right - altitude_width - Layout::FastScale(4), rc.top + name_font.GetHeight() - small_font.GetHeight() + Layout::FastScale(2), rc, airspace.GetTopText(true).c_str()); altitude_width = canvas.CalcTextWidth(airspace.GetBaseText(true).c_str()); canvas.text_clipped(rc.right - altitude_width - Layout::FastScale(4), rc.top + name_font.GetHeight() + Layout::FastScale(4), rc, airspace.GetBaseText(true).c_str()); }
void ManagedFileListWidget::OnPaintItem(Canvas &canvas, const PixelRect rc, unsigned i) { const FileItem &file = items[i]; const unsigned margin = Layout::GetTextPadding(); canvas.Select(row_renderer.GetFirstFont()); row_renderer.DrawFirstRow(canvas, rc, file.name.c_str()); canvas.Select(row_renderer.GetSecondFont()); if (file.downloading) { StaticString<64> text; if (file.download_status.position < 0) { text = _("Queued"); } else if (file.download_status.size > 0) { text.Format(_T("%s (%u%%)"), _("Downloading"), unsigned(file.download_status.position * 100 / file.download_status.size)); } else { TCHAR size[32]; FormatByteSize(size, ARRAY_SIZE(size), file.download_status.position); text.Format(_T("%s (%s)"), _("Downloading"), size); } const unsigned width = canvas.CalcTextWidth(text); canvas.DrawText(rc.right - width - margin, rc.top + row_renderer.GetFirstY(), text); } else if (file.failed) { const TCHAR *text = _("Error"); const unsigned width = canvas.CalcTextWidth(text); canvas.DrawText(rc.right - width - margin, rc.top + row_renderer.GetFirstY(), text); } row_renderer.DrawSecondRow(canvas, rc, file.size.c_str()); canvas.DrawText((rc.left + rc.right) / 2, rc.top + row_renderer.GetSecondY(), file.last_modified.c_str()); }
void ManagedFileListWidget::OnPaintItem(Canvas &canvas, const PixelRect rc, unsigned i) { const FileItem &file = items[i]; const UPixelScalar margin = Layout::GetTextPadding(); canvas.DrawText(rc.left + margin, rc.top + margin, file.name.c_str()); if (file.downloading) { StaticString<64> text; if (file.download_status.position < 0) { text = _("Queued"); } else if (file.download_status.size > 0) { text.Format(_T("%s (%u%%)"), _("Downloading"), unsigned(file.download_status.position * 100 / file.download_status.size)); } else { TCHAR size[32]; FormatByteSize(size, ARRAY_SIZE(size), file.download_status.position); text.Format(_T("%s (%s)"), _("Downloading"), size); } UPixelScalar width = canvas.CalcTextWidth(text); canvas.DrawText(rc.right - width - margin, rc.top + margin, text); } else if (file.failed) { const TCHAR *text = _("Error"); UPixelScalar width = canvas.CalcTextWidth(text); canvas.DrawText(rc.right - width - margin, rc.top + margin, text); } canvas.DrawText(rc.left + margin, rc.top + 2 * margin + font_height, file.size.c_str()); canvas.DrawText((rc.left + rc.right) / 2, rc.top + 2 * margin + font_height, file.last_modified.c_str()); }
/** * Draw right-aligned text. */ static void DrawTextRight(Canvas &canvas, int x, int y, const TCHAR *text) { unsigned width = canvas.CalcTextWidth(text); canvas.DrawText(x - width, y, text); }
void TrafficListWidget::OnPaintItem(Canvas &canvas, const PixelRect rc, unsigned index) { assert(index < items.size()); Item &item = items[index]; assert(item.IsFlarm() #ifdef HAVE_SKYLINES_TRACKING_HANDLER || item.IsSkyLines() #endif ); item.AutoLoad(); const FlarmNetRecord *record = item.record; const TCHAR *callsign = item.callsign; const DialogLook &look = UIGlobals::GetDialogLook(); const Font &name_font = *look.list.font_bold; const Font &small_font = *look.small_font; const unsigned text_padding = Layout::GetTextPadding(); const unsigned frame_padding = text_padding / 2; TCHAR tmp_id[10]; item.id.Format(tmp_id); canvas.Select(name_font); StaticString<256> tmp; if (item.IsFlarm()) { if (record != NULL) tmp.Format(_T("%s - %s - %s"), callsign, record->registration.c_str(), tmp_id); else if (callsign != NULL) tmp.Format(_T("%s - %s"), callsign, tmp_id); else tmp.Format(_T("%s"), tmp_id); #ifdef HAVE_SKYLINES_TRACKING_HANDLER } else if (item.IsSkyLines()) { tmp.UnsafeFormat(_T("SkyLines %u"), item.skylines_id); #endif } else { tmp = _T("?"); } const int name_x = rc.left + text_padding, name_y = rc.top + text_padding; if (item.color != FlarmColor::NONE) { const TrafficLook &traffic_look = UIGlobals::GetLook().traffic; switch (item.color) { case FlarmColor::NONE: case FlarmColor::COUNT: gcc_unreachable(); case FlarmColor::GREEN: canvas.Select(traffic_look.team_pen_green); break; case FlarmColor::BLUE: canvas.Select(traffic_look.team_pen_blue); break; case FlarmColor::YELLOW: canvas.Select(traffic_look.team_pen_yellow); break; case FlarmColor::MAGENTA: canvas.Select(traffic_look.team_pen_magenta); break; } canvas.SelectHollowBrush(); const PixelSize size = canvas.CalcTextSize(tmp); canvas.Rectangle(name_x - frame_padding, name_y - frame_padding, name_x + size.cx + frame_padding, name_y + size.cy + frame_padding); } canvas.DrawText(name_x, name_y, tmp); if (record != NULL) { tmp.clear(); if (!record->pilot.empty()) tmp = record->pilot.c_str(); if (!record->plane_type.empty()) { if (!tmp.empty()) tmp.append(_T(" - ")); tmp.append(record->plane_type); } if (!record->airfield.empty()) { if (!tmp.empty()) tmp.append(_T(" - ")); tmp.append(record->airfield); } if (!tmp.empty()) { canvas.Select(small_font); canvas.DrawText(rc.left + text_padding, rc.bottom - small_font.GetHeight() - text_padding, tmp); } } /* draw bearing and distance on the right */ if (item.vector.IsValid()) { FormatUserDistanceSmart(item.vector.distance, tmp.buffer(), true); unsigned width = canvas.CalcTextWidth(tmp.c_str()); canvas.DrawText(rc.right - text_padding - width, name_y + (name_font.GetHeight() - small_font.GetHeight()) / 2, tmp.c_str()); // Draw leg bearing FormatBearing(tmp.buffer(), tmp.MAX_SIZE, item.vector.bearing); width = canvas.CalcTextWidth(tmp.c_str()); canvas.DrawText(rc.right - text_padding - width, rc.bottom - small_font.GetHeight() - text_padding, tmp.c_str()); } }
void TaskEditPanel::OnPaintItem(Canvas &canvas, const PixelRect rc, unsigned DrawListIndex) { assert(DrawListIndex <= ordered_task->TaskSize()); const PixelScalar line_height = rc.bottom - rc.top; TCHAR buffer[120]; const Font &name_font = *dialog.GetLook().list.font_bold; const Font &small_font = *dialog.GetLook().small_font; // Draw "Add turnpoint" label if (DrawListIndex == ordered_task->TaskSize()) { canvas.Select(name_font); canvas.SetTextColor(COLOR_BLACK); _stprintf(buffer, _T(" (%s)"), _("Add Turnpoint")); canvas.DrawText(rc.left + line_height + Layout::FastScale(2), rc.top + line_height / 2 - name_font.GetHeight() / 2, buffer); return; } const OrderedTaskPoint &tp = ordered_task->GetTaskPoint(DrawListIndex); GeoVector leg = tp.GetNominalLegVector(); bool show_leg_info = leg.distance > fixed(0.01); // Draw icon const RasterPoint pt(rc.left + line_height / 2, rc.top + line_height / 2); PixelScalar radius = std::min(PixelScalar(line_height / 2 - Layout::FastScale(4)), Layout::FastScale(10)); OZPreviewRenderer::Draw(canvas, tp.GetObservationZone(), pt, radius, task_look, CommonInterface::GetMapSettings().airspace, airspace_look); // Y-Coordinate of the second row PixelScalar top2 = rc.top + name_font.GetHeight() + Layout::FastScale(4); // Use small font for details canvas.Select(small_font); canvas.SetTextColor(COLOR_BLACK); UPixelScalar leg_info_width = 0; if (show_leg_info) { // Draw leg distance FormatUserDistanceSmart(leg.distance, buffer, true); UPixelScalar width = leg_info_width = canvas.CalcTextWidth(buffer); canvas.DrawText(rc.right - Layout::FastScale(2) - width, rc.top + Layout::FastScale(2) + (name_font.GetHeight() - small_font.GetHeight()) / 2, buffer); // Draw leg bearing FormatBearing(buffer, ARRAY_SIZE(buffer), leg.bearing); width = canvas.CalcTextWidth(buffer); canvas.DrawText(rc.right - Layout::FastScale(2) - width, top2, buffer); if (width > leg_info_width) leg_info_width = width; leg_info_width += Layout::FastScale(2); } // Draw details line PixelScalar left = rc.left + line_height + Layout::FastScale(2); OrderedTaskPointRadiusLabel(tp.GetObservationZone(), buffer); if (!StringIsEmpty(buffer)) canvas.DrawClippedText(left, top2, rc.right - leg_info_width - left, buffer); // Draw turnpoint name canvas.Select(name_font); OrderedTaskPointLabel(tp.GetType(), tp.GetWaypoint().name.c_str(), DrawListIndex, buffer); canvas.DrawClippedText(left, rc.top + Layout::FastScale(2), rc.right - leg_info_width - left, buffer); }
void TaskEditPanel::OnPaintItem(Canvas &canvas, const PixelRect rc, unsigned DrawListIndex) { assert(DrawListIndex <= ordered_task->TaskSize()); const unsigned padding = Layout::GetTextPadding(); const unsigned line_height = rc.bottom - rc.top; TCHAR buffer[120]; // Draw "Add turnpoint" label if (DrawListIndex == ordered_task->TaskSize()) { row_renderer.DrawFirstRow(canvas, rc, _("Add Turnpoint")); return; } const OrderedTaskPoint &tp = ordered_task->GetTaskPoint(DrawListIndex); GeoVector leg = tp.GetNominalLegVector(); bool show_leg_info = leg.distance > fixed(0.01); PixelRect text_rc = rc; text_rc.left += line_height + padding; if (show_leg_info) { // Use small font for details canvas.Select(row_renderer.GetSecondFont()); // Draw leg distance FormatUserDistanceSmart(leg.distance, buffer, true); unsigned width = canvas.CalcTextWidth(buffer); const int x1 = rc.right - padding - width; canvas.DrawText(x1, rc.top + row_renderer.GetFirstY(), buffer); // Draw leg bearing FormatBearing(buffer, ARRAY_SIZE(buffer), leg.bearing); width = canvas.CalcTextWidth(buffer); const int x2 = rc.right - padding - width; canvas.DrawText(x2, rc.top + row_renderer.GetSecondY(), buffer); text_rc.right = std::min(x1, x2) - padding; } // Draw details line OrderedTaskPointRadiusLabel(tp.GetObservationZone(), buffer); if (!StringIsEmpty(buffer)) row_renderer.DrawSecondRow(canvas, text_rc, buffer); // Draw turnpoint name OrderedTaskPointLabel(tp.GetType(), tp.GetWaypoint().name.c_str(), DrawListIndex, buffer); row_renderer.DrawFirstRow(canvas, text_rc, buffer); // Draw icon const RasterPoint pt(rc.left + line_height / 2, rc.top + line_height / 2); const unsigned radius = line_height / 2 - padding; OZPreviewRenderer::Draw(canvas, tp.GetObservationZone(), pt, radius, task_look, CommonInterface::GetMapSettings().airspace, airspace_look); }
void DigitEntry::OnPaint(Canvas &canvas) { assert(cursor < length); const bool focused = HasCursorKeys() && HasFocus(); if (HaveClipping()) canvas.Clear(look.background_color); canvas.Select(look.text_font); canvas.SetBackgroundOpaque(); const unsigned text_height = look.text_font.GetHeight(); const int y = (top + bottom - text_height) / 2; PixelRect rc; rc.top = top; rc.bottom = bottom; TCHAR buffer[4]; for (unsigned i = 0; i < length; ++i) { const Column &c = columns[i]; rc.left = c.left; rc.right = c.right; if (focused && i == cursor) { canvas.SetTextColor(look.list.focused.text_color); canvas.SetBackgroundColor(look.list.focused.background_color); } else if (c.IsEditable()) { canvas.SetTextColor(look.list.text_color); canvas.SetBackgroundColor(look.list.background_color); } else { canvas.SetTextColor(look.list.text_color); canvas.SetBackgroundColor(look.background_color); } const TCHAR *text = buffer; buffer[1] = _T('\0'); switch (c.type) { case Column::Type::DIGIT: case Column::Type::DIGIT6: assert(c.value < 10); buffer[0] = _T('0') + c.value; break; case Column::Type::HOUR: assert(c.value < 24); _stprintf(buffer, _T("%02u"), c.value); break; case Column::Type::DIGIT36: assert(c.value < 36); _stprintf(buffer, _T("%02u"), c.value); break; case Column::Type::DIGIT19: assert(c.value < 19); _stprintf(buffer, _T("%02u"), c.value); break; case Column::Type::SIGN: buffer[0] = c.IsNegative() ? _T('-') : _T('+'); break; case Column::Type::DECIMAL_POINT: buffer[0] = _T('.'); break; case Column::Type::COLON: buffer[0] = _T(':'); break; case Column::Type::NORTH_SOUTH: buffer[0] = c.IsNegative() ? _T('S') : _T('N'); break; case Column::Type::EAST_WEST: buffer[0] = c.IsNegative() ? _T('W') : _T('E'); break; case Column::Type::DEGREES: text = _T("°"); break; case Column::Type::APOSTROPHE: text = _T("'"); break; case Column::Type::QUOTE: text = _T("\""); break; case Column::Type::UNIT: // TODO: render unit symbol? text = Units::unit_descriptors[c.value].name; break; } if (c.IsEditable() && !valid) buffer[0] = _T('\0'); const int x = (c.left + c.right - canvas.CalcTextWidth(text)) / 2; canvas.DrawOpaqueText(x, y, rc, text); } canvas.SetBackgroundTransparent(); canvas.SetTextColor(look.text_color); unsigned control_height = Layout::GetMaximumControlHeight(); PixelRect plus_rc(0, top - control_height, 0, top); PixelRect minus_rc(0, bottom, 0, bottom + control_height); for (unsigned i = 0; i < length; ++i) { const Column &c = columns[i]; if (!c.IsEditable()) continue; plus_rc.left = minus_rc.left = c.left; plus_rc.right = minus_rc.right = c.right; button_renderer.DrawButton(canvas, plus_rc, false, false); button_renderer.DrawButton(canvas, minus_rc, false, false); canvas.SelectNullPen(); canvas.Select(look.button.standard.foreground_brush); SymbolRenderer::DrawArrow(canvas, plus_rc, SymbolRenderer::UP); SymbolRenderer::DrawArrow(canvas, minus_rc, SymbolRenderer::DOWN); } }
void AirspaceWarningListHandler::OnPaintItem(Canvas &canvas, const PixelRect paint_rc, unsigned i) { TCHAR buffer[128]; // This constant defines the margin that should be respected // for renderring within the paint_rc area. const int padding = 2; if (i == 0 && warning_list.empty()) { /* the warnings were emptied between the opening of the dialog and this refresh, so only need to display "No Warnings" for top item, otherwise exit immediately */ canvas.DrawText(paint_rc.left + Layout::Scale(padding), paint_rc.top + Layout::Scale(padding), _("No Warnings")); return; } assert(i < warning_list.size()); const WarningItem &warning = warning_list[i]; const AbstractAirspace &airspace = *warning.airspace; const AirspaceInterceptSolution &solution = warning.solution; const UPixelScalar text_height = 12, text_top = 1; // word "inside" is used as the etalon, because it is longer than "near" and // currently (9.4.2011) there is no other possibility for the status text. const int status_width = canvas.CalcTextWidth(_T("inside")); // "1888" is used in order to have enough space for 4-digit heights with "AGL" const int altitude_width = canvas.CalcTextWidth(_T("1888 m AGL")); // Dynamic columns scaling - "name" column is flexible, altitude and state // columns are fixed-width. const PixelScalar left0 = Layout::FastScale(padding), left2 = paint_rc.right - Layout::FastScale(padding) - (status_width + 2 * Layout::FastScale(padding)), left1 = left2 - Layout::FastScale(padding) - altitude_width; PixelRect rc_text_clip = paint_rc; rc_text_clip.right = left1 - Layout::FastScale(padding); if (!warning.ack_expired) canvas.SetTextColor(COLOR_GRAY); { // name, altitude info _sntprintf(buffer, 21, _T("%s %s"), airspace.GetName(), AirspaceFormatter::GetClass(airspace)); canvas.DrawClippedText(paint_rc.left + left0, paint_rc.top + Layout::Scale(text_top), rc_text_clip, buffer); AirspaceFormatter::FormatAltitudeShort(buffer, airspace.GetTop()); canvas.DrawText(paint_rc.left + left1, paint_rc.top + Layout::Scale(text_top), buffer); AirspaceFormatter::FormatAltitudeShort(buffer, airspace.GetBase()); canvas.DrawText(paint_rc.left + left1, paint_rc.top + Layout::Scale(text_top + text_height), buffer); } if (warning.state != AirspaceWarning::WARNING_INSIDE && warning.state > AirspaceWarning::WARNING_CLEAR && solution.IsValid()) { _stprintf(buffer, _T("%d secs"), (int)solution.elapsed_time); if (positive(solution.distance)) _stprintf(buffer + _tcslen(buffer), _T(" dist %d m"), (int)solution.distance); else { /* the airspace is right above or below us - show the vertical distance */ _tcscat(buffer, _T(" vertical ")); fixed delta = solution.altitude - CommonInterface::Basic().nav_altitude; FormatRelativeUserAltitude(delta, buffer + _tcslen(buffer), true); } canvas.DrawClippedText(paint_rc.left + left0, paint_rc.top + Layout::Scale(text_top + text_height), rc_text_clip, buffer); } /* draw the warning state indicator */ Color state_color; const TCHAR *state_text; if (warning.state == AirspaceWarning::WARNING_INSIDE) { state_color = warning.ack_expired ? inside_color : inside_ack_color; state_text = _T("inside"); } else if (warning.state > AirspaceWarning::WARNING_CLEAR) { state_color = warning.ack_expired ? near_color : near_ack_color; state_text = _T("near"); } else { state_color = COLOR_WHITE; state_text = NULL; } const PixelSize state_text_size = canvas.CalcTextSize(state_text != NULL ? state_text : _T("W")); if (state_color != COLOR_WHITE) { /* colored background */ PixelRect rc; rc.left = paint_rc.left + left2; rc.top = paint_rc.top + Layout::FastScale(padding); rc.right = paint_rc.right - Layout::FastScale(padding); rc.bottom = paint_rc.bottom - Layout::FastScale(padding); canvas.DrawFilledRectangle(rc, state_color); /* on this background we just painted, we must use black color for the state text; our caller might have selected a different color, override it here */ canvas.SetTextColor(COLOR_BLACK); } if (state_text != NULL) { // -- status text will be centered inside its table cell: canvas.DrawText(paint_rc.left + left2 + Layout::FastScale(padding) + (status_width / 2) - (canvas.CalcTextWidth(state_text) / 2), (paint_rc.bottom + paint_rc.top - state_text_size.cy) / 2, state_text); } }