Esempio n. 1
0
void
PageListWidget::OnPaintItem(Canvas &canvas, const PixelRect rc, unsigned idx)
{
  const InfoBoxSettings &info_box_settings =
    CommonInterface::GetUISettings().info_boxes;

  assert(idx < PageSettings::MAX_PAGES);
  const auto &value = settings.pages[idx];

  StaticString<64> buffer;

  switch (value.main) {
  case PageLayout::Main::MAP:
    buffer = _("Map");
    break;

  case PageLayout::Main::FLARM_RADAR:
    buffer = _("FLARM radar");
    break;

  case PageLayout::Main::THERMAL_ASSISTANT:
    buffer = _("Thermal assistant");
    break;

  case PageLayout::Main::HORIZON:
    buffer = _("Horizon");
    break;

  case PageLayout::Main::MAX:
    gcc_unreachable();
  }

  if (value.infobox_config.enabled) {
    buffer.AppendFormat(_T(", %s"), _("InfoBoxes"));

    if (!value.infobox_config.auto_switch &&
        value.infobox_config.panel < InfoBoxSettings::MAX_PANELS)
      buffer.AppendFormat(_T(" (%s)"),
                          gettext(info_box_settings.panels[value.infobox_config.panel].name));
    else
      buffer.AppendFormat(_T(" (%s)"), _("Auto"));
  }

  switch (value.bottom) {
  case PageLayout::Bottom::NOTHING:
  case PageLayout::Bottom::CUSTOM:
    break;

  case PageLayout::Bottom::CROSS_SECTION:
    buffer.AppendFormat(_T(", %s"), _("Cross section"));
    break;

  case PageLayout::Bottom::MAX:
    gcc_unreachable();
  }

  canvas.DrawText(rc.left + Layout::GetTextPadding(),
                  rc.top + Layout::GetTextPadding(),
                  buffer);
}
static void
UpdateCaption(const TCHAR *waypoint_name, int8_t file_num)
{
    StaticString<256> buffer;
    buffer.Format(_T("%s: %s"), _("Waypoint"), waypoint_name);

    if (file_num > 0) {
        const TCHAR *key;
        switch (file_num) {
        case 1:
            key = szProfileWaypointFile;
            break;
        case 2:
            key = szProfileAdditionalWaypointFile;
            break;
        case 3:
            key = szProfileWatchedWaypointFile;
            break;
        }

        const TCHAR *filename = Profile::GetPathBase(key);
        if (filename != NULL)
            buffer.AppendFormat(_T(" (%s)"), filename);
    }

    wf->SetCaption(buffer);
}
Esempio n. 3
0
static void
UpdateCaption(WndForm *form, const Waypoint *waypoint)
{
  StaticString<256> buffer;
  buffer.Format(_T("%s: %s"), _("Waypoint"), waypoint->name.c_str());

  const char *key = nullptr;
  switch (waypoint->file_num) {
  case 1:
    key = ProfileKeys::WaypointFile;
    break;
  case 2:
    key = ProfileKeys::AdditionalWaypointFile;
    break;
  case 3:
    key = ProfileKeys::WatchedWaypointFile;
    break;
  }

  if (key != nullptr) {
    const TCHAR *filename = Profile::GetPathBase(key);
    if (filename != nullptr)
      buffer.AppendFormat(_T(" (%s)"), filename);
  }

  form->SetCaption(buffer);
}
Esempio n. 4
0
void
MapItemListRenderer::Draw(Canvas &canvas, const PixelRect rc,
                          const MarkerMapItem &item,
                          const DialogLook &dialog_look,
                          const MarkerLook &look)
{
  const PixelScalar line_height = rc.bottom - rc.top;

  const Marker &marker = item.marker;

  const RasterPoint pt(rc.left + line_height / 2,
                       rc.top + line_height / 2);

  look.icon.Draw(canvas, pt);

  const Font &name_font = *dialog_look.list.font_bold;
  const Font &small_font = *dialog_look.small_font;

  PixelScalar left = rc.left + line_height + Layout::FastScale(2);

  StaticString<256> buffer;
  buffer.Format(_T("%s #%d"), _("Marker"), item.id + 1);
  canvas.Select(name_font);
  canvas.DrawClippedText(left, rc.top + Layout::FastScale(2), rc, buffer);

  TCHAR time_buffer[32], timespan_buffer[32];
  FormatSignedTimeHHMM(time_buffer, TimeLocal(marker.time.GetSecondOfDay()));
  FormatTimespanSmart(timespan_buffer, BrokenDateTime::NowUTC() - marker.time);
  buffer.Format(_("dropped %s ago"), timespan_buffer);
  buffer.AppendFormat(_T(" (%s)"), time_buffer);
  canvas.Select(small_font);
  canvas.DrawClippedText(left,
                         rc.top + name_font.GetHeight() + Layout::FastScale(4),
                         rc, buffer);
}
Esempio n. 5
0
const tstring 
AirspaceAltitude::GetAsTextUnits(const bool concise) const
{
  StaticString<64> buffer;

  switch (type) {
  case AGL:
    if (!positive(altitude_above_terrain))
      buffer = _T("GND");
    else
      buffer.Format(_T("%d %s AGL"),
                    iround(Units::ToUserAltitude(altitude_above_terrain)),
                    Units::GetAltitudeName());
    break;
  case FL:
    buffer.Format(_T("FL%d"), (int)flight_level);
    break;
  case MSL:
    buffer.Format(_T("%d %s"), iround(Units::ToUserAltitude(altitude)),
                  Units::GetAltitudeName());
    break;
  case UNDEFINED:
  default:
    buffer.clear();
    break;
  }

  if (!concise && type != MSL && positive(altitude))
    buffer.AppendFormat(_T(" %d %s"), iround(Units::ToUserAltitude(altitude)),
                        Units::GetAltitudeName());

  return tstring(buffer);
}
Esempio n. 6
0
void
MapItemListRenderer::Draw(Canvas &canvas, const PixelRect rc,
                          const ThermalMapItem &item,
                          const DialogLook &dialog_look,
                          const MapLook &look)
{
  const PixelScalar line_height = rc.bottom - rc.top;

  const ThermalSource &thermal = item.thermal;

  RasterPoint pt = { PixelScalar(rc.left + line_height / 2),
                     PixelScalar(rc.top + line_height / 2) };

  look.thermal_source_icon.Draw(canvas, pt);

  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, _("Thermal"));

  StaticString<256> buffer;
  TCHAR lift_buffer[32], time_buffer[32], timespan_buffer[32];
  FormatUserVerticalSpeed(thermal.lift_rate, lift_buffer, 32);
  FormatSignedTimeHHMM(time_buffer, TimeLocal((int)thermal.time));

  int timespan = BrokenDateTime::NowUTC().GetSecondOfDay() - (int)thermal.time;
  if (timespan < 0)
    timespan += 24 * 60 * 60;

  FormatTimespanSmart(timespan_buffer, timespan);

  buffer.Format(_T("%s: %s"), _("Avg. lift"), lift_buffer);
  buffer.append(_T(" - "));
  buffer.AppendFormat(_("left %s ago"), timespan_buffer);
  buffer.AppendFormat(_T(" (%s)"), time_buffer);
  canvas.Select(small_font);
  canvas.text_clipped(left,
                      rc.top + name_font.GetHeight() + Layout::FastScale(4),
                      rc, buffer);
}
Esempio n. 7
0
static void
UpdateCaption(WndForm *form, const Waypoint *waypoint)
{
  StaticString<256> buffer;
  buffer.Format(_T("%s: %s"), _("Waypoint"), waypoint->name.c_str());

  const char *key = nullptr;
  const TCHAR *name = nullptr;

  switch (waypoint->origin) {
  case WaypointOrigin::NONE:
    break;

  case WaypointOrigin::USER:
    name = _T("user.cup");
    break;

  case WaypointOrigin::PRIMARY:
    key = ProfileKeys::WaypointFile;
    break;

  case WaypointOrigin::ADDITIONAL:
    key = ProfileKeys::AdditionalWaypointFile;
    break;

  case WaypointOrigin::WATCHED:
    key = ProfileKeys::WatchedWaypointFile;
    break;

  case WaypointOrigin::MAP:
    key = ProfileKeys::MapFile;
    break;
  }

  if (key != nullptr) {
    const auto filename = Profile::map.GetPathBase(key);
    if (!filename.IsNull())
      buffer.AppendFormat(_T(" (%s)"), filename.c_str());
  } else if (name != nullptr)
    buffer.AppendFormat(_T(" (%s)"), name);

  form->SetCaption(buffer);
}
Esempio n. 8
0
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);
}
Esempio n. 9
0
static void
AddSpiralWaypoints(Waypoints &waypoints,
                   const GeoPoint &center = GeoPoint(Angle::Degrees(51.4),
                                                     Angle::Degrees(7.85)),
                   Angle angle_start = Angle::Degrees(0),
                   Angle angle_step = Angle::Degrees(15),
                   fixed distance_start = fixed(0),
                   fixed distance_step = fixed(1000),
                   fixed distance_max = fixed(150000))
{
  assert(positive(distance_step));

  for (unsigned i = 0;; ++i) {
    GeoVector vector;
    vector.distance = distance_start + distance_step * i;
    if (vector.distance > distance_max)
      break;

    vector.bearing = angle_start + angle_step * i;

    Waypoint waypoint;
    waypoint.location = vector.EndPoint(center);
    waypoint.original_id = i;
    waypoint.elevation = fixed(i * 10 - 500);

    StaticString<256> buffer;

    if (i % 7 == 0) {
      buffer = _T("Airfield");
      waypoint.type = Waypoint::Type::AIRFIELD;
    } else if (i % 3 == 0) {
      buffer = _T("Field");
      waypoint.type = Waypoint::Type::OUTLANDING;
    } else
      buffer = _T("Waypoint");

    buffer.AppendFormat(_T(" #%d"), i + 1);
    waypoint.name = buffer;

    waypoints.Append(std::move(waypoint));
  }

  waypoints.Optimise();
}
Esempio n. 10
0
void
NOAAListRenderer::Draw(Canvas &canvas, const PixelRect rc,
                       const NOAAStore::Item &station,
                       const TwoTextRowsRenderer &row_renderer)
{
  StaticString<256> title;
  title = station.GetCodeT();
  if (station.parsed_metar_available &&
      station.parsed_metar.name_available)
    title.AppendFormat(_T(": %s"), station.parsed_metar.name.c_str());

  row_renderer.DrawFirstRow(canvas, rc, title);

  const TCHAR *tmp;
  if (!station.metar_available)
    tmp = _("No METAR available");
  else
    tmp = station.metar.content.c_str();

  row_renderer.DrawSecondRow(canvas, rc, tmp);
}
Esempio n. 11
0
static void
Update()
{
  tstring metar_taf = _T("");

  NOAAFormatter::Format(*station_iterator, metar_taf);
  WndProperty* wp = (WndProperty*)wf->FindByName(_T("DetailsText"));
  wp->SetText(metar_taf.c_str());

  StaticString<100> caption;
  caption.Format(_T("%s: "), _("METAR and TAF"));

  ParsedMETAR parsed;
  if (!station_iterator->GetParsedMETAR(parsed) ||
      !parsed.name_available)
    caption += station_iterator->GetCodeT();
  else
    caption.AppendFormat(_T("%s (%s)"), parsed.name.c_str(),
                         station_iterator->GetCodeT());

  wf->SetCaption(caption);
}
Esempio n. 12
0
void
NOAADetailsWidget::Update()
{
  tstring metar_taf = _T("");

  NOAAFormatter::Format(*station_iterator, metar_taf);

  SetText(metar_taf.c_str());

  StaticString<100> caption;
  caption.Format(_T("%s: "), _("METAR and TAF"));

  if (!station_iterator->parsed_metar_available ||
      !station_iterator->parsed_metar.name_available)
    caption += station_iterator->GetCodeT();
  else
    caption.AppendFormat(_T("%s (%s)"),
                         station_iterator->parsed_metar.name.c_str(),
                         station_iterator->GetCodeT());

  dialog.SetCaption(caption);
}
Esempio n. 13
0
  void Visit(const TCHAR *path, const TCHAR *filename) {
    // Create a TaskFile instance to determine how many
    // tasks are inside of this task file
    TaskFile* task_file = TaskFile::Create(path);
    if (task_file == NULL)
      return;

    // Get base name of the task file
    const TCHAR* base_name = BaseName(path);

    // Count the tasks in the task file
    unsigned count = task_file->Count();
    // For each task in the task file
    for (unsigned i = 0; i < count; i++) {
      // Copy base name of the file into task name
      StaticString<256> name;
      name = (base_name != NULL) ? base_name : path;

      // If the task file holds more than one task
      if (count > 1) {
        if (i < task_file->namesuffixes.size() &&
            task_file->namesuffixes[i]) {

          name += _T(": ");
          name += task_file->namesuffixes[i];

        } else {
          // .. append " - Task #[n]" suffix to the task name
          name.AppendFormat(_T(": %s #%2d"), _("Task"), i + 1);
        }
      }

      // Add the task to the TaskStore
      store.push_back(TaskStore::Item(path, name.empty() ? path : name, i));
    }

    // Remove temporary TaskFile instance
    delete task_file;
  }
void
GlueMapWindow::DrawMapScale(Canvas &canvas, const PixelRect &rc,
                            const MapWindowProjection &projection) const
{
  RenderMapScale(canvas, projection, rc, look.overlay);

  if (!projection.IsValid())
    return;

  StaticString<80> buffer;

  buffer.clear();

  if (GetMapSettings().auto_zoom_enabled)
    buffer = _T("AUTO ");

  switch (follow_mode) {
  case FOLLOW_SELF:
    break;

  case FOLLOW_PAN:
    buffer += _T("PAN ");
    break;
  }

  const UIState &ui_state = GetUIState();
  if (ui_state.auxiliary_enabled) {
    buffer += ui_state.panel_name;
    buffer += _T(" ");
  }

  if (Basic().gps.replay)
    buffer += _T("REPLAY ");
  else if (Basic().gps.simulator) {
    buffer += _("Simulator");
    buffer += _T(" ");
  }

  if (GetComputerSettings().polar.ballast_timer_active)
    buffer.AppendFormat(
        _T("BALLAST %d LITERS "),
        (int)GetComputerSettings().polar.glide_polar_task.GetBallastLitres());

  if (rasp_renderer != nullptr) {
    const TCHAR *label = rasp_renderer->GetLabel();
    if (label != nullptr)
      buffer += gettext(label);
  }

  if (!buffer.empty()) {

    const Font &font = *look.overlay.overlay_font;
    canvas.Select(font);
    const unsigned height = font.GetCapitalHeight()
        + Layout::GetTextPadding();
    int y = rc.bottom - height;

    TextInBoxMode mode;
    mode.vertical_position = TextInBoxMode::VerticalPosition::ABOVE;
    mode.shape = LabelShape::OUTLINED;

    TextInBox(canvas, buffer, 0, y, mode, rc, nullptr);
  }
}
Esempio n. 15
0
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;
}
Esempio n. 16
0
void
MapItemListRenderer::Draw(Canvas &canvas, const PixelRect rc,
                          const ArrivalAltitudeMapItem &item,
                          const DialogLook &dialog_look,
                          const FinalGlideBarLook &look)
{
  const UPixelScalar line_height = rc.bottom - rc.top;

  bool elevation_available =
      !RasterBuffer::IsSpecial((short)item.elevation);

  bool reach_relevant = item.reach.IsReachRelevant();

  RoughAltitude arrival_altitude =
    item.reach.terrain_valid == ReachResult::Validity::VALID
    ? item.reach.terrain
    : item.reach.direct;
  if (elevation_available)
    arrival_altitude -= item.elevation;

  bool reachable =
    item.reach.terrain_valid != ReachResult::Validity::UNREACHABLE &&
    arrival_altitude.IsPositive();

  // Draw final glide arrow icon

  RasterPoint pt = { (PixelScalar)(rc.left + line_height / 2),
                     (PixelScalar)(rc.top + line_height / 2) };

  RasterPoint arrow[] = {
      { -7, -3 }, { 0, 4 }, { 7, -3 }
  };

  Angle arrow_angle = reachable ? Angle::HalfCircle() : Angle::Zero();
  PolygonRotateShift(arrow, ARRAY_SIZE(arrow), pt.x, pt.y, arrow_angle, 100);

  if (reachable) {
    canvas.Select(look.brush_above);
    canvas.Select(look.pen_above);
  } else {
    canvas.Select(look.brush_below);
    canvas.Select(look.pen_below);
  }
  canvas.DrawPolygon(arrow, ARRAY_SIZE(arrow));


  const Font &name_font = *dialog_look.list.font_bold;
  const Font &small_font = *dialog_look.small_font;

  PixelScalar left = rc.left + line_height + Layout::FastScale(2);


  // Format title row

  TCHAR altitude_buffer[32];
  StaticString<256> buffer;
  buffer.clear();

  if (elevation_available) {
    RoughAltitude relative_arrival_altitude =
      item.reach.direct - item.elevation;

    FormatRelativeUserAltitude(fixed((short)relative_arrival_altitude),
                               altitude_buffer, ARRAY_SIZE(altitude_buffer));

    buffer.AppendFormat(_T("%s %s, "), altitude_buffer, _("AGL"));
  }

  FormatUserAltitude(fixed(item.reach.direct),
                     altitude_buffer, ARRAY_SIZE(altitude_buffer));

  buffer.AppendFormat(_T("%s %s"), altitude_buffer, _("MSL"));

  // Draw title row

  canvas.Select(name_font);
  canvas.DrawClippedText(left, rc.top + Layout::FastScale(2), rc, buffer);

  // Format comment row

  if (reach_relevant) {
    buffer.Format(_T("%s: "), _("around terrain"));

    if (elevation_available) {
      RoughAltitude relative_arrival_altitude =
          item.reach.terrain - item.elevation;

      FormatRelativeUserAltitude(fixed((short)relative_arrival_altitude),
                                 altitude_buffer, ARRAY_SIZE(altitude_buffer));

     buffer.AppendFormat(_T("%s %s, "), altitude_buffer, _("AGL"));
    }

    FormatUserAltitude(fixed(item.reach.terrain),
                       altitude_buffer, ARRAY_SIZE(altitude_buffer));

    buffer.AppendFormat(_T("%s %s, "), altitude_buffer, _("MSL"));
  } else if (elevation_available &&
             (int)item.reach.direct >= (int)item.elevation &&
             item.reach.terrain_valid == ReachResult::Validity::UNREACHABLE) {
    buffer.UnsafeFormat(_T("%s "), _("Unreachable due to terrain."));
  } else {
    buffer.clear();
  }

  buffer += _("Arrival altitude incl. safety height");

  // Draw comment row

  canvas.Select(small_font);
  canvas.DrawClippedText(left,
                         rc.top + name_font.GetHeight() + Layout::FastScale(4),
                         rc, buffer);
}
Esempio n. 17
0
void
GlueMapWindow::DrawMapScale(Canvas &canvas, const PixelRect &rc,
                            const MapWindowProjection &projection) const
{
  StaticString<80> buffer;

  fixed map_width = projection.GetScreenWidthMeters();

  canvas.Select(Fonts::map_bold);
  FormatUserMapScale(map_width, buffer.buffer(), true);
  PixelSize text_size = canvas.CalcTextSize(buffer);

  const PixelScalar text_padding_x = Layout::Scale(2);
  const PixelScalar height = Fonts::map_bold.GetCapitalHeight() + Layout::Scale(2);

  PixelScalar x = 0;
  look.map_scale_left_icon.Draw(canvas, 0, rc.bottom - height);

  x += look.map_scale_left_icon.GetSize().cx;
  canvas.DrawFilledRectangle(x, rc.bottom - height,
                             x + 2 * text_padding_x + text_size.cx,
                             rc.bottom, COLOR_WHITE);

  canvas.SetBackgroundTransparent();
  canvas.SetTextColor(COLOR_BLACK);
  x += text_padding_x;
  canvas.text(x, rc.bottom - Fonts::map_bold.GetAscentHeight() - Layout::Scale(1),
              buffer);

  x += text_padding_x + text_size.cx;
  look.map_scale_right_icon.Draw(canvas, x, rc.bottom - height);

  buffer.clear();
  if (GetMapSettings().auto_zoom_enabled)
    buffer = _T("AUTO ");

  switch (follow_mode) {
  case FOLLOW_SELF:
    break;

  case FOLLOW_PAN:
    buffer += _T("PAN ");
    break;
  }

  const UIState &ui_state = GetUIState();
  if (ui_state.auxiliary_enabled) {
    buffer += ui_state.panel_name;
    buffer += _T(" ");
  }

  if (Basic().gps.replay)
    buffer += _T("REPLAY ");
  else if (Basic().gps.simulator) {
    buffer += _("Simulator");
    buffer += _T(" ");
  }

  if (GetComputerSettings().polar.ballast_timer_active)
    buffer.AppendFormat(
        _T("BALLAST %d LITERS "),
        (int)GetComputerSettings().polar.glide_polar_task.GetBallastLitres());

  if (weather != NULL && weather->GetParameter() > 0) {
    const TCHAR *label = weather->ItemLabel(weather->GetParameter());
    if (label != NULL)
      buffer += label;
  }

  if (!buffer.empty()) {
    int y = rc.bottom - height;

    canvas.Select(Fonts::title);
    canvas.SetBackgroundOpaque();
    canvas.SetBackgroundColor(COLOR_WHITE);

    canvas.text(0, y - canvas.CalcTextSize(buffer).cy, buffer);
  }
}
Esempio n. 18
0
static void
Draw(Canvas &canvas, PixelRect rc,
     const ArrivalAltitudeMapItem &item,
     const TwoTextRowsRenderer &row_renderer,
     const FinalGlideBarLook &look)
{
  const unsigned line_height = rc.GetHeight();

  bool reach_relevant = item.reach.IsReachRelevant();

  int arrival_altitude =
    item.reach.terrain_valid == ReachResult::Validity::VALID
    ? item.reach.terrain
    : item.reach.direct;
  if (item.HasElevation())
    arrival_altitude -= item.elevation;

  bool reachable =
    item.reach.terrain_valid != ReachResult::Validity::UNREACHABLE &&
    arrival_altitude >= 0;

  // Draw final glide arrow icon

  const PixelPoint pt(rc.left + line_height / 2, rc.top + line_height / 2);

  BulkPixelPoint arrow[] = {
      { -7, -3 }, { 0, 4 }, { 7, -3 }
  };

  Angle arrow_angle = reachable ? Angle::HalfCircle() : Angle::Zero();
  PolygonRotateShift(arrow, ARRAY_SIZE(arrow), pt, arrow_angle);

  if (reachable) {
    canvas.Select(look.brush_above);
    canvas.Select(look.pen_above);
  } else {
    canvas.Select(look.brush_below);
    canvas.Select(look.pen_below);
  }
  canvas.DrawPolygon(arrow, ARRAY_SIZE(arrow));

  const unsigned text_padding = Layout::GetTextPadding();
  rc.left += line_height + text_padding;

  // Format title row

  TCHAR altitude_buffer[32];
  StaticString<256> buffer;
  buffer.clear();

  if (item.HasElevation()) {
    int relative_arrival_altitude =
      item.reach.direct - item.elevation;

    FormatRelativeUserAltitude(relative_arrival_altitude,
                               altitude_buffer, ARRAY_SIZE(altitude_buffer));

    buffer.AppendFormat(_T("%s %s, "), altitude_buffer, _("AGL"));
  }

  buffer.AppendFormat(_T("%s %s"),
                      FormatUserAltitude(item.reach.direct).c_str(),
                      _("MSL"));

  // Draw title row

  row_renderer.DrawFirstRow(canvas, rc, buffer);

  // Format comment row

  if (reach_relevant) {
    buffer.Format(_T("%s: "), _("around terrain"));

    if (item.HasElevation()) {
      int relative_arrival_altitude =
          item.reach.terrain - item.elevation;

      FormatRelativeUserAltitude(relative_arrival_altitude,
                                 altitude_buffer, ARRAY_SIZE(altitude_buffer));

     buffer.AppendFormat(_T("%s %s, "), altitude_buffer, _("AGL"));
    }

    buffer.AppendFormat(_T("%s %s, "),
                        FormatUserAltitude(item.reach.terrain).c_str(),
                        _("MSL"));
  } else if (item.HasElevation() &&
             item.reach.direct >= item.elevation &&
             item.reach.terrain_valid == ReachResult::Validity::UNREACHABLE) {
    buffer.UnsafeFormat(_T("%s "), _("Unreachable due to terrain."));
  } else {
    buffer.clear();
  }

  buffer += _("Arrival altitude incl. safety height");

  // Draw comment row

  row_renderer.DrawSecondRow(canvas, rc, buffer);
}
Esempio n. 19
0
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
  }
}
Esempio n. 20
0
void
GlueMapWindow::DrawMapScale(Canvas &canvas, const PixelRect &rc,
                            const MapWindowProjection &projection) const
{
  if (!projection.IsValid())
    return;

  StaticString<80> buffer;

  fixed map_width = projection.GetScreenWidthMeters();

  const Font &font = *look.overlay_font;
  canvas.Select(font);
  FormatUserMapScale(map_width, buffer.buffer(), true);
  PixelSize text_size = canvas.CalcTextSize(buffer);

  const PixelScalar text_padding_x = Layout::GetTextPadding();
  const PixelScalar height = font.GetCapitalHeight()
    + Layout::GetTextPadding();

  PixelScalar x = 0;
  look.map_scale_left_icon.Draw(canvas, 0, rc.bottom - height);

  x += look.map_scale_left_icon.GetSize().cx;
  canvas.DrawFilledRectangle(x, rc.bottom - height,
                             x + 2 * text_padding_x + text_size.cx,
                             rc.bottom, COLOR_WHITE);

  canvas.SetBackgroundTransparent();
  canvas.SetTextColor(COLOR_BLACK);
  x += text_padding_x;
  canvas.DrawText(x,
                  rc.bottom - font.GetAscentHeight() - Layout::Scale(1),
                  buffer);

  x += text_padding_x + text_size.cx;
  look.map_scale_right_icon.Draw(canvas, x, rc.bottom - height);

  buffer.clear();
  if (GetMapSettings().auto_zoom_enabled)
    buffer = _T("AUTO ");

  switch (follow_mode) {
  case FOLLOW_SELF:
    break;

  case FOLLOW_PAN:
    buffer += _T("PAN ");
    break;
  }

  const UIState &ui_state = GetUIState();
  if (ui_state.auxiliary_enabled) {
    buffer += ui_state.panel_name;
    buffer += _T(" ");
  }

  if (Basic().gps.replay)
    buffer += _T("REPLAY ");
  else if (Basic().gps.simulator) {
    buffer += _("Simulator");
    buffer += _T(" ");
  }

  if (GetComputerSettings().polar.ballast_timer_active)
    buffer.AppendFormat(
        _T("BALLAST %d LITERS "),
        (int)GetComputerSettings().polar.glide_polar_task.GetBallastLitres());

  if (weather != nullptr && weather->GetParameter() > 0) {
    const TCHAR *label = weather->ItemLabel(weather->GetParameter());
    if (label != nullptr)
      buffer += label;
  }

  if (!buffer.empty()) {
    int y = rc.bottom - height;

    TextInBoxMode mode;
    mode.vertical_position = TextInBoxMode::VerticalPosition::ABOVE;
    mode.shape = LabelShape::OUTLINED;

    TextInBox(canvas, buffer, 0, y, mode, rc, nullptr);
  }
}