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); }
void TaskStatusPanel::Refresh() { if (protected_task_manager == NULL) return; const DerivedInfo &calculated = CommonInterface::Calculated(); const TaskStats &task_stats = calculated.ordered_task_stats; TCHAR Temp[80]; SetRowVisible(TaskTime, task_stats.has_targets); if (task_stats.has_targets) { FormatSignedTimeHHMM(Temp, (int)protected_task_manager->GetOrderedTaskSettings().aat_min_time); SetText(TaskTime, Temp); } int ete_time(task_stats.GetEstimatedTotalTime()); FormatSignedTimeHHMM(Temp, ete_time); SetText(ETETime, Temp); FormatSignedTimeHHMM(Temp, (int)task_stats.total.time_remaining_now); SetText(RemainingTime, Temp); if (task_stats.total.planned.IsDefined()) { FormatUserDistanceSmart(task_stats.total.planned.GetDistance(), Temp, ARRAY_SIZE(Temp)); SetText(TaskDistance, Temp); } else SetText(TaskDistance, _T("")); if (task_stats.total.remaining.IsDefined()) { FormatUserDistanceSmart(task_stats.total.remaining.GetDistance(), Temp, ARRAY_SIZE(Temp)); SetText(RemainingDistance, Temp); } if (task_stats.total.planned.IsDefined()) { FormatUserTaskSpeed(task_stats.total.planned.GetSpeed(), Temp, ARRAY_SIZE(Temp)); SetText(EstimatedSpeed, Temp); } else SetText(EstimatedSpeed, _T("")); if (task_stats.total.travelled.IsDefined()) { FormatUserTaskSpeed(task_stats.total.travelled.GetSpeed(), Temp, ARRAY_SIZE(Temp)); SetText(AverageSpeed, Temp); } else SetText(AverageSpeed, _T("")); }
void TeamCodeWidget::Update(const MoreData &basic, const DerivedInfo &calculated) { const TeamInfo &teamcode_info = calculated; const TeamCodeSettings &settings = CommonInterface::GetComputerSettings().team_code; SetText(RELATIVE_BEARING, teamcode_info.teammate_available && basic.track_available ? FormatAngleDelta(teamcode_info.teammate_vector.bearing - basic.track).c_str() : _T("---")); if (teamcode_info.teammate_available) { SetText(BEARING, FormatBearing(teamcode_info.teammate_vector.bearing).c_str()); SetText(RANGE, FormatUserDistanceSmart(teamcode_info.teammate_vector.distance)); } SetText(OWN_CODE, teamcode_info.own_teammate_code.GetCode()); SetText(MATE_CODE, settings.team_code.GetCode()); SetText(FLARM_LOCK, settings.team_flarm_id.IsDefined() ? settings.team_flarm_callsign.c_str() : _T("")); }
void InfoBoxData::SetValueFromDistance(fixed new_value) { Unit distance_unit = FormatUserDistanceSmart(new_value, value.buffer(), false); SetValueUnit(distance_unit); }
void FlightStatusPanel::Refresh() { const NMEAInfo &basic = CommonInterface::Basic(); const DerivedInfo &calculated = CommonInterface::Calculated(); if (basic.location_available) SetText(Location, FormatGeoPoint(basic.location)); else ClearText(Location); if (basic.gps_altitude_available) SetText(Altitude, FormatUserAltitude(basic.gps_altitude)); else ClearText(Altitude); SetText(MaxHeightGain, FormatUserAltitude(calculated.max_height_gain)); if (nearest_waypoint) { GeoVector vec(basic.location, nearest_waypoint->location); SetText(Near, nearest_waypoint->name.c_str()); SetText(Bearing, FormatBearing(vec.bearing).c_str()); SetText(Distance, FormatUserDistanceSmart(vec.distance)); } else { SetText(Near, _T("-")); SetText(Bearing, _T("-")); SetText(Distance, _T("-")); } }
gcc_const static inline StringBuffer<TCHAR, 32> FormatUserDistanceSmart(double value) { StringBuffer<TCHAR, 32> buffer; FormatUserDistanceSmart(value, buffer.data()); return 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) { // Draw leg distance FormatUserDistanceSmart(leg.distance, buffer, true); const int x1 = row_renderer.DrawRightFirstRow(canvas, rc, buffer); // Draw leg bearing FormatBearing(buffer, ARRAY_SIZE(buffer), leg.bearing); const int x2 = row_renderer.DrawRightSecondRow(canvas, rc, buffer); text_rc.right = std::min(x1, x2); } // 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); }
static void DisplayParsedMETAR(const NOAAStore::Item &station) { if (!station.parsed_metar_available) { printf("METAR parsing failed!\n");; return; } const ParsedMETAR &parsed = station.parsed_metar; printf("Parsed Data:\n"); if (parsed.name_available) _tprintf(_T("Name: %s\n"), parsed.name.c_str()); if (parsed.location_available) { TCHAR buffer[256]; FormatGeoPoint(parsed.location, buffer, ARRAY_SIZE(buffer), CoordinateFormat::DDMMSS); _tprintf(_T("Location: %s\n"), buffer); } if (parsed.qnh_available) { TCHAR buffer[256]; FormatUserPressure(parsed.qnh, buffer, ARRAY_SIZE(buffer)); _tprintf(_T("QNH: %s\n"), buffer); } if (parsed.wind_available) { TCHAR buffer[256]; FormatUserWindSpeed(parsed.wind.norm, buffer, ARRAY_SIZE(buffer)); _tprintf(_T("Wind: %.0f" DEG " %s\n"), (double)parsed.wind.bearing.Degrees(), buffer); } if (parsed.temperatures_available) { TCHAR buffer[256]; FormatUserTemperature(parsed.temperature, buffer, ARRAY_SIZE(buffer)); _tprintf(_T("Temperature: %s\n"), buffer); FormatUserTemperature(parsed.dew_point, buffer, ARRAY_SIZE(buffer)); _tprintf(_T("Dew point: %s\n"), buffer); } if (parsed.visibility_available) { TCHAR buffer[256]; if (parsed.visibility >= 9999) _tcscpy(buffer, _T("unlimited")); else { fixed visibility(parsed.visibility); FormatUserDistanceSmart(visibility, buffer, ARRAY_SIZE(buffer)); } _tprintf(_T("Visibility: %s\n"), buffer); } printf("\n"); }
void WaypointListRenderer::Draw(Canvas &canvas, const PixelRect rc, const Waypoint &waypoint, fixed distance, fixed arrival_altitude, 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; // 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 distance and arrival altitude StaticString<256> buffer; TCHAR dist[20], alt[20], radio[20]; FormatUserDistanceSmart(distance, dist, true); FormatRelativeUserAltitude(arrival_altitude, alt, true); buffer.Format(_T("%s: %s - %s: %s"), _("Distance"), dist, _("Arrival Alt"), alt); if (waypoint.radio_frequency.IsDefined()) { waypoint.radio_frequency.Format(radio, ARRAY_SIZE(radio)); buffer.AppendFormat(_T(" - %s MHz"), radio); } UPixelScalar left = rc.left + line_height + Layout::FastScale(2); canvas.text_clipped(left, top2, rc, buffer); // Draw waypoint name canvas.Select(name_font); canvas.text_clipped(left, rc.top + Layout::FastScale(2), rc, waypoint.name.c_str()); // Draw icon RasterPoint pt = { PixelScalar(rc.left + line_height / 2), PixelScalar(rc.top + line_height / 2) }; WaypointIconRenderer::Reachability reachable = positive(arrival_altitude) ? WaypointIconRenderer::ReachableTerrain : WaypointIconRenderer::Unreachable; WaypointIconRenderer wir(settings, look, canvas); wir.Draw(waypoint, pt, reachable); }
/** * Paints the radar circle on the given canvas * @param canvas The canvas to paint on */ void FlarmTrafficWindow::PaintRadarBackground(Canvas &canvas) const { canvas.SelectHollowBrush(); canvas.Select(look.radar_pen); canvas.SetTextColor(look.radar_color); // Paint circles canvas.circle(radar_mid.x, radar_mid.y, radius); canvas.circle(radar_mid.x, radar_mid.y, radius / 2); PaintRadarPlane(canvas); if (small) return; // Paint zoom strings canvas.Select(look.label_font); canvas.SetBackgroundOpaque(); canvas.SetBackgroundColor(look.background_color); TCHAR distance_string[10]; FormatUserDistanceSmart(distance, distance_string, ARRAY_SIZE(distance_string)); PixelSize s = canvas.CalcTextSize(distance_string); canvas.text(radar_mid.x - s.cx / 2, radar_mid.y + radius - s.cy * 0.75, distance_string); FormatUserDistanceSmart(distance / 2, distance_string, ARRAY_SIZE(distance_string)); s = canvas.CalcTextSize(distance_string); canvas.text(radar_mid.x - s.cx / 2, radar_mid.y + radius / 2 - s.cy * 0.75, distance_string); canvas.SetBackgroundTransparent(); PaintNorth(canvas); }
/** * Updates all the dialogs fields, that are changing frequently. * e.g. climb speed, distance, height */ void FlarmTrafficDetailsWidget::UpdateChanging(const MoreData &basic) { TCHAR tmp[40]; const TCHAR *value; const FlarmTraffic* target = basic.flarm.traffic.FindTraffic(target_id); bool target_ok = target && target->IsDefined(); // Fill distance/direction field if (target_ok) { FormatUserDistanceSmart(target->distance, tmp, 20, fixed(1000)); TCHAR *p = tmp + _tcslen(tmp); *p++ = _T(' '); FormatAngleDelta(p, 20, target->Bearing() - basic.track); value = tmp; } else value = _T("--"); SetText(DISTANCE, value); // Fill altitude field if (target_ok) { TCHAR *p = tmp; if (target->altitude_available) { FormatUserAltitude(target->altitude, p, 20); p += _tcslen(p); *p++ = _T(' '); } Angle dir = Angle::FromXY(target->distance, target->relative_altitude); FormatVerticalAngleDelta(p, 20, dir); value = tmp; } else value = _T("--"); SetText(ALTITUDE, value); // Fill climb speed field if (target_ok && target->climb_rate_avg30s_available) { FormatUserVerticalSpeed(target->climb_rate_avg30s, tmp, 20); value = tmp; } else value = _T("--"); SetText(VARIO, value); }
/** * Updates all the dialogs fields, that are changing frequently. * e.g. climb speed, distance, height */ static void UpdateChanging() { TCHAR tmp[20]; const FlarmTraffic* target = XCSoarInterface::Basic().flarm.traffic.FindTraffic(target_id); bool target_ok = target && target->IsDefined(); // Fill distance field if (target_ok) FormatUserDistanceSmart(target->distance, tmp, 20, fixed(1000)); else _tcscpy(tmp, _T("--")); SetFormValue(*wf, _T("prpDistance"), tmp); // Fill horizontal direction field if (target_ok) FormatAngleDelta(tmp, ARRAY_SIZE(tmp), target->Bearing() - CommonInterface::Basic().track); else _tcscpy(tmp, _T("--")); SetFormValue(*wf, _T("prpDirectionH"), tmp); // Fill altitude field if (target_ok && target->altitude_available) FormatUserAltitude(target->altitude, tmp, 20); else _tcscpy(tmp, _T("--")); SetFormValue(*wf, _T("prpAltitude"), tmp); // Fill vertical direction field if (target_ok) { Angle dir = Angle::Radians((fixed)atan2(target->relative_altitude, target->distance)).AsDelta(); FormatVerticalAngleDelta(tmp, ARRAY_SIZE(tmp), dir); } else _tcscpy(tmp, _T("--")); SetFormValue(*wf, _T("prpDirectionV"), tmp); // Fill climb speed field if (target_ok && target->climb_rate_avg30s_available) FormatUserVerticalSpeed(target->climb_rate_avg30s, tmp, 20); else _tcscpy(tmp, _T("--")); SetFormValue(*wf, _T("prpVSpeed"), tmp); }
void AirspaceListRenderer::Draw(Canvas &canvas, const PixelRect rc, const AbstractAirspace &airspace, const GeoVector &vector, const DialogLook &dialog_look, const AirspaceLook &look, const AirspaceRendererSettings &renderer_settings) { StaticString<256> comment(AirspaceFormatter::GetClass(airspace)); TCHAR dist[20], bearing[20]; FormatUserDistanceSmart(vector.distance, dist, true); FormatBearing(bearing, ARRAY_SIZE(bearing), vector.bearing); comment.AppendFormat(_T(" - %s - %s"), dist, bearing); Draw(canvas, rc, airspace, comment, dialog_look, look, renderer_settings); }
void FlightStatusPanel::Refresh() { const NMEAInfo &basic = CommonInterface::Basic(); const DerivedInfo &calculated = CommonInterface::Calculated(); StaticString<32> buffer; if (basic.location_available) { FormatGeoPoint(basic.location, buffer.buffer(), buffer.MAX_SIZE); SetText(Location, buffer); } else SetText(Location, _T("")); if (basic.gps_altitude_available) { FormatUserAltitude(basic.gps_altitude, buffer.buffer(), buffer.MAX_SIZE); SetText(Altitude, buffer); } else SetText(Altitude, _T("")); FormatUserAltitude(calculated.max_height_gain, buffer.buffer(), buffer.MAX_SIZE); SetText(MaxHeightGain, buffer); if (nearest_waypoint) { GeoVector vec(basic.location, nearest_waypoint->location); SetText(Near, nearest_waypoint->name.c_str()); FormatBearing(buffer.buffer(), buffer.MAX_SIZE, vec.bearing, _T("")); SetText(Bearing, buffer); FormatUserDistanceSmart(vec.distance, buffer.buffer(), buffer.MAX_SIZE); SetText(Distance, buffer); } else { SetText(Near, _T("-")); SetText(Bearing, _T("-")); SetText(Distance, _T("-")); } }
void FlarmTrafficControl::PaintDistance(Canvas &canvas, PixelRect rc, fixed distance) const { // Format distance TCHAR buffer[20]; Unit unit = FormatUserDistanceSmart(distance, buffer, false, fixed(1000)); // Calculate unit size canvas.Select(look.info_units_font); const unsigned unit_width = UnitSymbolRenderer::GetSize(canvas, unit).cx; const unsigned unit_height = UnitSymbolRenderer::GetAscentHeight(look.info_units_font, unit); const unsigned space_width = unit_width / 3; // Calculate value size canvas.Select(look.info_values_font); const unsigned value_height = look.info_values_font.GetAscentHeight(); const unsigned value_width = canvas.CalcTextSize(buffer).cx; // Calculate positions const unsigned max_height = std::max(unit_height, value_height); // Paint value canvas.DrawText(rc.left, rc.bottom - value_height, buffer); // Paint unit canvas.Select(look.info_units_font); UnitSymbolRenderer::Draw(canvas, RasterPoint(rc.left + value_width + space_width, rc.bottom - unit_height), unit, look.unit_fraction_pen); // Paint label canvas.Select(look.info_labels_font); canvas.DrawText(rc.left, rc.bottom - max_height - look.info_labels_font.GetHeight(), _("Distance")); }
void MapItemListRenderer::Draw(Canvas &canvas, const PixelRect rc, const LocationMapItem &item, const DialogLook &dialog_look) { const Font &name_font = *dialog_look.list.font_bold; const Font &small_font = *dialog_look.small_font; PixelScalar left = rc.left + Layout::FastScale(2); TCHAR info_buffer[256], distance_buffer[32], direction_buffer[32]; if (item.vector.IsValid()) { FormatUserDistanceSmart(item.vector.distance, distance_buffer, 32); FormatBearing(direction_buffer, ARRAY_SIZE(direction_buffer), item.vector.bearing); _stprintf(info_buffer, _T("%s: %s, %s: %s"), _("Distance"), distance_buffer, _("Direction"), direction_buffer); } else { _stprintf(info_buffer, _T("%s: %s, %s: %s"), _("Distance"), _T("???"), _("Direction"), _T("???")); } canvas.Select(name_font); canvas.DrawClippedText(left, rc.top + Layout::FastScale(2), rc, info_buffer); TCHAR elevation_buffer[32]; if (!RasterBuffer::IsSpecial(item.elevation)) { FormatUserAltitude(fixed(item.elevation), elevation_buffer, 32); _stprintf(info_buffer, _T("%s: %s"), _("Elevation"), elevation_buffer); } else { _stprintf(info_buffer, _T("%s: %s"), _("Elevation"), _T("???")); } canvas.Select(small_font); canvas.DrawClippedText(left, rc.top + name_font.GetHeight() + Layout::FastScale(4), rc, info_buffer); }
static void Draw(Canvas &canvas, const PixelRect rc, const LocationMapItem &item, const TwoTextRowsRenderer &row_renderer) { TCHAR info_buffer[256]; if (item.vector.IsValid()) StringFormatUnsafe(info_buffer, _T("%s: %s, %s: %s"), _("Distance"), FormatUserDistanceSmart(item.vector.distance).c_str(), _("Direction"), FormatBearing(item.vector.bearing).c_str()); else StringFormatUnsafe(info_buffer, _T("%s: %s, %s: %s"), _("Distance"), _T("???"), _("Direction"), _T("???")); row_renderer.DrawFirstRow(canvas, rc, info_buffer); StringFormatUnsafe(info_buffer, _T("%s: %s"), _("Elevation"), item.HasElevation() ? FormatUserAltitude(item.elevation).c_str() : _T("???")); row_renderer.DrawSecondRow(canvas, rc, info_buffer); }
static bool FormatDecodedMETARLine(const TCHAR *line, unsigned length, const ParsedMETAR &parsed, tstring &output) { const TCHAR *end = line + length; const TCHAR *colon = (const TCHAR *)memchr(line, _T(':'), length); if (!colon) return false; unsigned title_length = colon - line; if (title_length == 0) return false; const TCHAR *value = colon + 1; while (*value == _T(' ')) value++; unsigned value_length = end - value; if (CheckTitle(line, title_length, _T("Wind"))) { StaticString<256> buffer; if (!parsed.wind_available) { buffer.Format(_T("%s: "), _("Wind")); buffer.append(value, value_length); } else { TCHAR wind_speed_buffer[16]; FormatUserWindSpeed(parsed.wind.norm, wind_speed_buffer, ARRAY_SIZE(wind_speed_buffer)); buffer.Format(_T("%s: %.0f" DEG " %s"), _("Wind"), (double)parsed.wind.bearing.Degrees(), wind_speed_buffer); } output += buffer; output += '\n'; return true; } if (CheckTitle(line, title_length, _T("Temperature"))) { StaticString<256> buffer; if (!parsed.temperatures_available) { buffer.Format(_T("%s: "), _("Temperature")); buffer.append(value, value_length); } else { TCHAR temperature_buffer[16]; FormatUserTemperature(parsed.temperature, temperature_buffer, ARRAY_SIZE(temperature_buffer)); buffer.Format(_T("%s: %s"), _("Temperature"), temperature_buffer); } output += buffer; output += '\n'; return true; } if (CheckTitle(line, title_length, _T("Dew Point"))) { StaticString<256> buffer; if (!parsed.temperatures_available) { buffer.Format(_T("%s: "), _("Dew Point")); buffer.append(value, value_length); } else { TCHAR temperature_buffer[16]; FormatUserTemperature(parsed.dew_point, temperature_buffer, ARRAY_SIZE(temperature_buffer)); buffer.Format(_T("%s: %s"), _("Dew Point"), temperature_buffer); } output += buffer; output += '\n'; return true; } if (CheckTitle(line, title_length, _T("Pressure (altimeter)"))) { StaticString<256> buffer; if (!parsed.qnh_available) { buffer.Format(_T("%s: "), _("Pressure")); buffer.append(value, value_length); } else { TCHAR qnh_buffer[16]; FormatUserPressure(parsed.qnh, qnh_buffer, ARRAY_SIZE(qnh_buffer)); buffer.Format(_T("%s: %s"), _("Pressure"), qnh_buffer); } output += buffer; output += '\n'; return true; } if (CheckTitle(line, title_length, _T("Visibility"))) { StaticString<256> buffer; buffer.Format(_T("%s: "), _("Visibility")); if (!parsed.qnh_available) { buffer.append(value, value_length); } else { TCHAR vis_buffer[32]; if (parsed.visibility >= 9999) { FormatUserDistanceSmart(fixed(10000), vis_buffer, ARRAY_SIZE(vis_buffer)); buffer.AppendFormat(_("more than %s"), vis_buffer); } else { FormatUserDistanceSmart(fixed(parsed.visibility), vis_buffer, ARRAY_SIZE(vis_buffer)); buffer += vis_buffer; } } output += buffer; output += '\n'; return true; } if (CheckTitle(line, title_length, _T("Sky conditions"))) { StaticString<256> buffer; buffer.Format(_T("%s: "), _("Sky Conditions")); StaticString<64> _value; _value.set(value, value_length); buffer += gettext(_value); output += buffer; output += '\n'; return true; } if (CheckTitle(line, title_length, _T("Weather"))) { StaticString<256> buffer; buffer.Format(_T("%s: "), _("Weather")); StaticString<64> _value; _value.set(value, value_length); buffer += gettext(_value); output += buffer; output += '\n'; return true; } StaticString<64> title; title.set(line, title_length); StaticString<256> buffer; buffer.Format(_T("%s: "), gettext(title.c_str())); buffer.append(value, value_length); output += buffer; output += '\n'; return true; }
void WaypointInfoWidget::Prepare(ContainerWindow &parent, const PixelRect &rc) { RowFormWidget::Prepare(parent, rc); const MoreData &basic = CommonInterface::Basic(); const DerivedInfo &calculated = CommonInterface::Calculated(); const ComputerSettings &settings = CommonInterface::GetComputerSettings(); StaticString<64> buffer; if (!waypoint.comment.empty()) AddMultiLine(waypoint.comment.c_str()); if (waypoint.radio_frequency.IsDefined() && waypoint.radio_frequency.Format(buffer.buffer(), buffer.MAX_SIZE) != NULL) { buffer += _T(" MHz"); AddReadOnly(_("Radio frequency"), NULL, buffer); } if (waypoint.runway.IsDirectionDefined()) buffer.UnsafeFormat(_T("%02u"), waypoint.runway.GetDirectionName()); else buffer.clear(); if (waypoint.runway.IsLengthDefined()) { if (!buffer.empty()) buffer += _T("; "); TCHAR length_buffer[16]; FormatSmallUserDistance(length_buffer, fixed(waypoint.runway.GetLength())); buffer += length_buffer; } if (!buffer.empty()) AddReadOnly(_("Runway"), NULL, buffer); if (FormatGeoPoint(waypoint.location, buffer.buffer(), buffer.MAX_SIZE) != NULL) AddReadOnly(_("Location"), NULL, buffer); FormatUserAltitude(waypoint.elevation, buffer.buffer(), buffer.MAX_SIZE); AddReadOnly(_("Elevation"), NULL, buffer); if (basic.time_available) { const SunEphemeris::Result sun = SunEphemeris::CalcSunTimes(waypoint.location, basic.date_time_utc, fixed(GetUTCOffset()) / 3600); const unsigned sunrisehours = (int)sun.time_of_sunrise; const unsigned sunrisemins = (int)((sun.time_of_sunrise - fixed(sunrisehours)) * 60); const unsigned sunset_hour = (int)sun.time_of_sunset; const unsigned sunset_minute = (int)((sun.time_of_sunset - fixed(sunset_hour)) * 60); buffer.UnsafeFormat(_T("%02u:%02u - %02u:%02u"), sunrisehours, sunrisemins, sunset_hour, sunset_minute); AddReadOnly(_("Daylight time"), NULL, buffer); } if (basic.location_available) { const GeoVector vector = basic.location.DistanceBearing(waypoint.location); TCHAR distance_buffer[32]; FormatUserDistanceSmart(vector.distance, distance_buffer, ARRAY_SIZE(distance_buffer)); FormatBearing(buffer.buffer(), buffer.MAX_SIZE, vector.bearing, distance_buffer); AddReadOnly(_("Bearing and Distance"), NULL, buffer); } if (basic.location_available && basic.NavAltitudeAvailable() && settings.polar.glide_polar_task.IsValid()) { const GlideState glide_state(basic.location.DistanceBearing(waypoint.location), waypoint.elevation + settings.task.safety_height_arrival, basic.nav_altitude, calculated.GetWindOrZero()); GlidePolar gp0 = settings.polar.glide_polar_task; gp0.SetMC(fixed(0)); AddGlideResult(_("Alt. diff. MC 0"), MacCready::Solve(settings.task.glide, gp0, glide_state)); AddGlideResult(_("Alt. diff. MC safety"), MacCready::Solve(settings.task.glide, calculated.glide_polar_safety, glide_state)); AddGlideResult(_("Alt. diff. MC current"), MacCready::Solve(settings.task.glide, settings.polar.glide_polar_task, glide_state)); } }
void InfoBoxData::SetCommentFromDistance(fixed new_value) { FormatUserDistanceSmart(new_value, comment.buffer()); }
void TaskStatusPanel::Refresh() { if (protected_task_manager == nullptr) return; const DerivedInfo &calculated = CommonInterface::Calculated(); const TaskStats &task_stats = calculated.ordered_task_stats; SetRowVisible(TaskTime, task_stats.has_targets); if (task_stats.has_targets) SetText(TaskTime, FormatSignedTimeHHMM((int)protected_task_manager->GetOrderedTaskSettings().aat_min_time)); SetText(ETETime, FormatSignedTimeHHMM((int)task_stats.GetEstimatedTotalTime())); SetText(RemainingTime, FormatSignedTimeHHMM((int)task_stats.total.time_remaining_now)); if (task_stats.total.planned.IsDefined()) SetText(TaskDistance, FormatUserDistanceSmart(task_stats.total.planned.GetDistance())); else ClearText(TaskDistance); if (task_stats.total.remaining.IsDefined()) SetText(RemainingDistance, FormatUserDistanceSmart(task_stats.total.remaining.GetDistance())); if (task_stats.total.planned.IsDefined()) SetText(EstimatedSpeed, FormatUserTaskSpeed(task_stats.total.planned.GetSpeed())); else ClearText(EstimatedSpeed); if (task_stats.total.travelled.IsDefined()) SetText(AverageSpeed, FormatUserTaskSpeed(task_stats.total.travelled.GetSpeed())); else ClearText(AverageSpeed); LoadValue(MC, CommonInterface::GetComputerSettings().polar.glide_polar_task.GetMC(), UnitGroup::VERTICAL_SPEED); if (task_stats.total.planned.IsDefined()) { auto rMax = task_stats.distance_max; auto rMin = task_stats.distance_min; if (rMin < rMax) { auto range = 2 * (task_stats.total.planned.GetDistance() - rMin) / (rMax - rMin) - 1; LoadValue(RANGE, range * 100); } else ClearValue(RANGE); } else ClearValue(RANGE); if (task_stats.total.remaining_effective.IsDefined()) LoadValue(SPEED_REMAINING, task_stats.total.remaining_effective.GetSpeed(), UnitGroup::TASK_SPEED); else ClearValue(SPEED_REMAINING); LoadValue(EFFECTIVE_MC, task_stats.effective_mc, UnitGroup::VERTICAL_SPEED); if (task_stats.total.travelled.IsDefined()) LoadValue(SPEED_ACHIEVED, task_stats.total.travelled.GetSpeed(), UnitGroup::TASK_SPEED); else ClearValue(SPEED_ACHIEVED); LoadValue(CRUISE_EFFICIENCY, task_stats.cruise_efficiency * 100); }
/** * Paints the basic info for the selected target on the given canvas * @param canvas The canvas to paint on */ void FlarmTrafficControl2::PaintTrafficInfo(Canvas &canvas) const { // Don't paint numbers if no plane selected if (selection == -1 && !WarningMode()) return; // Shortcut to the selected traffic FlarmTraffic traffic = data.list[WarningMode() ? warning : selection]; assert(traffic.IsDefined()); // Temporary string TCHAR tmp[20]; // Temporary string size PixelSize sz; PixelRect rc; rc.left = padding; rc.top = padding; rc.right = canvas.get_width() - padding; rc.bottom = canvas.get_height() - padding; // Set the text color and background switch (traffic.alarm_level) { case FlarmTraffic::AlarmType::LOW: case FlarmTraffic::AlarmType::INFO_ALERT: canvas.SetTextColor(look.warning_color); break; case FlarmTraffic::AlarmType::IMPORTANT: case FlarmTraffic::AlarmType::URGENT: canvas.SetTextColor(look.alarm_color); break; case FlarmTraffic::AlarmType::NONE: canvas.SetTextColor(look.default_color); break; } canvas.SetBackgroundTransparent(); // Climb Rate if (!WarningMode() && traffic.climb_rate_avg30s_available) { FormatUserVerticalSpeed(traffic.climb_rate_avg30s, tmp, 20); canvas.Select(look.info_values_font); sz = canvas.CalcTextSize(tmp); canvas.text(rc.right - sz.cx, rc.top + look.info_labels_font.GetHeight(), tmp); canvas.Select(look.info_labels_font); sz = canvas.CalcTextSize(_("Vario")); canvas.text(rc.right - sz.cx, rc.top, _("Vario")); } // Distance FormatUserDistanceSmart(traffic.distance, tmp, 20, fixed(1000)); canvas.Select(look.info_values_font); sz = canvas.CalcTextSize(tmp); canvas.text(rc.left, rc.bottom - sz.cy, tmp); canvas.Select(look.info_labels_font); canvas.text(rc.left, rc.bottom - look.info_values_font.GetHeight() - look.info_labels_font.GetHeight(), _("Distance")); // Relative Height FormatRelativeUserAltitude(traffic.relative_altitude, tmp, 20); canvas.Select(look.info_values_font); sz = canvas.CalcTextSize(tmp); canvas.text(rc.right - sz.cx, rc.bottom - sz.cy, tmp); canvas.Select(look.info_labels_font); sz = canvas.CalcTextSize(_("Rel. Alt.")); canvas.text(rc.right - sz.cx, rc.bottom - look.info_values_font.GetHeight() - look.info_labels_font.GetHeight(), _("Rel. Alt.")); // ID / Name unsigned font_size; if (traffic.HasName()) { canvas.Select(look.call_sign_font); font_size = look.call_sign_font.GetHeight(); if (!traffic.HasAlarm()) canvas.SetTextColor(look.selection_color); _tcscpy(tmp, traffic.name); } else { font_size = look.info_labels_font.GetHeight(); traffic.id.Format(tmp); } if (!WarningMode()) { // Team color dot FlarmFriends::Color team_color = FlarmFriends::GetFriendColor(traffic.id); // If no color found but target is teammate if (team_color == FlarmFriends::Color::NONE && settings.team_flarm_tracking && traffic.id == settings.team_flarm_id) // .. use yellow color team_color = FlarmFriends::Color::GREEN; // If team color found -> draw a colored circle around the target if (team_color != FlarmFriends::Color::NONE) { switch (team_color) { case FlarmFriends::Color::GREEN: canvas.Select(look.team_brush_green); break; case FlarmFriends::Color::BLUE: canvas.Select(look.team_brush_blue); break; case FlarmFriends::Color::YELLOW: canvas.Select(look.team_brush_green); break; case FlarmFriends::Color::MAGENTA: canvas.Select(look.team_brush_magenta); break; default: break; } canvas.SelectNullPen(); canvas.DrawCircle(rc.left + Layout::FastScale(7), rc.top + (font_size / 2), Layout::FastScale(7)); rc.left += Layout::FastScale(16); } } canvas.text(rc.left, rc.top, tmp); }
void TrafficListWidget::OnPaintItem(Canvas &canvas, 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 != nullptr) tmp.Format(_T("%s - %s - %s"), callsign, record->registration.c_str(), tmp_id); else if (callsign != nullptr) tmp.Format(_T("%s - %s"), callsign, tmp_id); else tmp.Format(_T("%s"), tmp_id); #ifdef HAVE_SKYLINES_TRACKING_HANDLER } else if (item.IsSkyLines()) { if (!item.name.empty()) tmp = item.name.c_str(); else tmp.UnsafeFormat(_T("SkyLines %u"), item.skylines_id); #endif } else { tmp = _T("?"); } 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(rc.left + row_renderer.GetX() - frame_padding, rc.top + row_renderer.GetFirstY() - frame_padding, rc.left + row_renderer.GetX() + size.cx + frame_padding, rc.top + row_renderer.GetFirstY() + size.cy + frame_padding); } row_renderer.DrawFirstRow(canvas, rc, tmp); canvas.Select(small_font); /* draw bearing and distance on the right */ if (item.vector.IsValid()) { row_renderer.DrawRightFirstRow(canvas, rc, FormatUserDistanceSmart(item.vector.distance).c_str()); // Draw leg bearing rc.right = row_renderer.DrawRightSecondRow(canvas, rc, FormatBearing(item.vector.bearing).c_str()); } if (record != nullptr) { 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()) row_renderer.DrawSecondRow(canvas, rc, tmp); #ifdef HAVE_SKYLINES_TRACKING_HANDLER } else if (item.IsSkyLines()) { if (CommonInterface::Basic().time_available) { tmp.UnsafeFormat(_("%u minutes ago"), SinceInMinutes(CommonInterface::Basic().time, item.time_of_day_ms)); } else tmp.clear(); if (!item.near_name.empty()) tmp.AppendFormat(_T(" near %s (%s)"), item.near_name.c_str(), FormatUserDistanceSmart(item.near_distance).c_str()); if (!tmp.empty()) tmp.append(_T("; ")); tmp.append(FormatUserAltitude(item.altitude)); if (!tmp.empty()) row_renderer.DrawSecondRow(canvas, rc, tmp); #endif } }
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 WaypointInfoWidget::Prepare(ContainerWindow &parent, const PixelRect &rc) { RowFormWidget::Prepare(parent, rc); const MoreData &basic = CommonInterface::Basic(); const DerivedInfo &calculated = CommonInterface::Calculated(); const ComputerSettings &settings = CommonInterface::GetComputerSettings(); StaticString<64> buffer; if (!waypoint.comment.empty()) AddMultiLine(waypoint.comment.c_str()); if (waypoint.radio_frequency.IsDefined() && waypoint.radio_frequency.Format(buffer.buffer(), buffer.MAX_SIZE) != nullptr) { buffer += _T(" MHz"); AddReadOnly(_("Radio frequency"), nullptr, buffer); } if (waypoint.runway.IsDirectionDefined()) buffer.UnsafeFormat(_T("%02u"), waypoint.runway.GetDirectionName()); else buffer.clear(); if (waypoint.runway.IsLengthDefined()) { if (!buffer.empty()) buffer += _T("; "); TCHAR length_buffer[16]; FormatSmallUserDistance(length_buffer, fixed(waypoint.runway.GetLength())); buffer += length_buffer; } if (!buffer.empty()) AddReadOnly(_("Runway"), nullptr, buffer); if (FormatGeoPoint(waypoint.location, buffer.buffer(), buffer.MAX_SIZE) != nullptr) AddReadOnly(_("Location"), nullptr, buffer); FormatUserAltitude(waypoint.elevation, buffer.buffer(), buffer.MAX_SIZE); AddReadOnly(_("Elevation"), nullptr, buffer); if (basic.time_available && basic.date_time_utc.IsDatePlausible()) { const SunEphemeris::Result sun = SunEphemeris::CalcSunTimes(waypoint.location, basic.date_time_utc, settings.utc_offset); const BrokenTime sunrise = BreakHourOfDay(sun.time_of_sunrise); const BrokenTime sunset = BreakHourOfDay(sun.time_of_sunset); buffer.UnsafeFormat(_T("%02u:%02u - %02u:%02u"), sunrise.hour, sunrise.minute, sunset.hour, sunset.minute); AddReadOnly(_("Daylight time"), nullptr, buffer); } if (basic.location_available) { const GeoVector vector = basic.location.DistanceBearing(waypoint.location); TCHAR distance_buffer[32]; FormatUserDistanceSmart(vector.distance, distance_buffer, ARRAY_SIZE(distance_buffer)); FormatBearing(buffer.buffer(), buffer.MAX_SIZE, vector.bearing, distance_buffer); AddReadOnly(_("Bearing and Distance"), nullptr, buffer); } if (basic.location_available && basic.NavAltitudeAvailable() && settings.polar.glide_polar_task.IsValid()) { const GlideState glide_state(basic.location.DistanceBearing(waypoint.location), waypoint.elevation + settings.task.safety_height_arrival, basic.nav_altitude, calculated.GetWindOrZero()); GlidePolar gp0 = settings.polar.glide_polar_task; gp0.SetMC(fixed(0)); AddGlideResult(_("Alt. diff. MC 0"), MacCready::Solve(settings.task.glide, gp0, glide_state)); AddGlideResult(_("Alt. diff. MC safety"), MacCready::Solve(settings.task.glide, calculated.glide_polar_safety, glide_state)); AddGlideResult(_("Alt. diff. MC current"), MacCready::Solve(settings.task.glide, settings.polar.glide_polar_task, glide_state)); } if (basic.location_available && basic.NavAltitudeAvailable()) { const TaskBehaviour &task_behaviour = CommonInterface::GetComputerSettings().task; const fixed safety_height = task_behaviour.safety_height_arrival; const fixed target_altitude = waypoint.elevation + safety_height; const fixed delta_h = basic.nav_altitude - target_altitude; if (positive(delta_h)) { const fixed distance = basic.location.Distance(waypoint.location); const fixed gr = distance / delta_h; if (GradientValid(gr)) { buffer.UnsafeFormat(_T("%.1f"), (double)gr); AddReadOnly(_("Required glide ratio"), nullptr, buffer); } } } }