Esempio n. 1
0
static void
LoadChecklist()
{
  nLists = 0;

  free(ChecklistText[0]);
  ChecklistText[0] = NULL;

  free(ChecklistTitle[0]);
  ChecklistTitle[0] = NULL;

  TLineReader *reader = OpenDataTextFile(_T(XCSCHKLIST));
  if (reader == NULL) {
    addChecklist(_("No checklist loaded"), _("Create xcsoar-checklist.txt"));
    return;
  }

  StaticString<MAXDETAILS> Details;
  TCHAR Name[100];
  bool inDetails = false;
  int i;

  Details.clear();
  Name[0] = 0;

  TCHAR *TempString;
  while ((TempString = reader->ReadLine()) != NULL) {
    // Look for start
    if (TempString[0] == '[') {
      if (inDetails) {
        addChecklist(Name, Details);
        Details.clear();
        Name[0] = 0;
      }

      // extract name
      for (i = 1; i < MAXTITLE; i++) {
        if (TempString[i] == ']')
          break;

        Name[i - 1] = TempString[i];
      }
      Name[i - 1] = 0;

      inDetails = true;
    } else {
      // append text to details string
      Details.append(TempString);
      Details.Append(_T('\n'));
    }
  }

  delete reader;

  if (inDetails) {
    addChecklist(Name, Details);
  }
}
Esempio n. 2
0
bool
PopupMessage::Message::AppendTo(StaticString<2000> &buffer, unsigned now)
{
  if (IsUnknown())
    // ignore unknown messages
    return false;

  if (texpiry < now) {
    texpiry = tstart - 1;
    // reset expiry so we don't refresh
    return false;
  }

  if (!buffer.empty())
    buffer.append(_T("\r\n"));
  buffer.append(text);
  return true;
}
Esempio n. 3
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. 4
0
void
DeviceListWidget::OnPaintItem(Canvas &canvas, const PixelRect rc, unsigned idx)
{
  assert(idx < NUMDEV);

  const DeviceConfig &config =
    CommonInterface::SetSystemSettings().devices[idx];
  const Flags flags(*items[idx]);

  const UPixelScalar margin = Layout::GetTextPadding();

  TCHAR port_name_buffer[128];
  const TCHAR *port_name =
    config.GetPortName(port_name_buffer, ARRAY_SIZE(port_name_buffer));

  StaticString<256> text(_T("A: "));
  text[0u] += idx;

  if (config.UsesDriver()) {
    const TCHAR *driver_name = FindDriverDisplayName(config.driver_name);

    text.AppendFormat(_("%s on %s"), driver_name, port_name);
  } else {
    text.append(port_name);
  }

  canvas.Select(*look.list.font);
  canvas.DrawText(rc.left + margin, rc.top + margin, text);

  /* show a list of features that are available in the second row */

  StaticString<256> buffer;
  const TCHAR *status;
  if (flags.alive) {
    if (flags.location) {
      buffer = _("GPS fix");
    } else if (flags.gps) {
      /* device sends GPGGA, but no valid location */
      buffer = _("Bad GPS");
    } else {
      buffer = _("Connected");
    }

    if (flags.baro) {
      buffer.append(_T("; "));
      buffer.append(_("Baro"));
    }

    if (flags.airspeed) {
      buffer.append(_T("; "));
      buffer.append(_("Airspeed"));
    }

    if (flags.vario) {
      buffer.append(_T("; "));
      buffer.append(_("Vario"));
    }

    if (flags.traffic)
      buffer.append(_T("; FLARM"));

    if (flags.debug) {
      buffer.append(_T("; "));
      buffer.append(_("Debug"));
    }

    status = buffer;
  } else if (config.IsDisabled()) {
    status = _("Disabled");
  } else if (is_simulator() || !config.IsAvailable()) {
    status = _("N/A");
  } else if (flags.open) {
    buffer = _("No data");

    if (flags.debug) {
      buffer.append(_T("; "));
      buffer.append(_("Debug"));
    }

    status = buffer;
#ifdef ANDROID
  } else if ((config.port_type == DeviceConfig::PortType::RFCOMM ||
              config.port_type == DeviceConfig::PortType::RFCOMM_SERVER) &&
             !BluetoothHelper::isEnabled(Java::GetEnv())) {
    status = _("Bluetooth is disabled");
#endif
  } else if (flags.duplicate) {
    status = _("Duplicate");
  } else if (flags.error) {
    status = _("Error");
  } else {
    status = _("Not connected");
  }

  canvas.Select(look.small_font);
  canvas.DrawText(rc.left + margin, rc.top + 2 * margin + font_height,
                  status);
}
Esempio n. 5
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. 6
0
void
DeviceListWidget::OnPaintItem(Canvas &canvas, const PixelRect rc, unsigned idx)
{
  assert(idx < NUMDEV);

  const DeviceConfig &config =
    CommonInterface::SetSystemSettings().devices[idx];
  const Flags flags(*items[idx]);

  const UPixelScalar margin = Layout::Scale(2);

  TCHAR port_name_buffer[128];
  const TCHAR *port_name =
    config.GetPortName(port_name_buffer, ARRAY_SIZE(port_name_buffer));

  StaticString<256> text(_T("A: "));
  text[0u] += idx;

  if (config.UsesDriver()) {
    const TCHAR *driver_name = FindDriverDisplayName(config.driver_name);

    text.AppendFormat(_("%s on %s"), driver_name, port_name);
  } else {
    text.append(port_name);
  }

  canvas.text(rc.left + margin, rc.top + margin, text);

  /* show a list of features that are available in the second row */

  StaticString<256> buffer;
  const TCHAR *status;
  if (flags.alive) {
    if (flags.location) {
      buffer = _("GPS fix");
    } else if (flags.gps) {
      /* device sends GPGGA, but no valid location */
      buffer = _("Bad GPS");
    } else {
      buffer = _("Connected");
    }

    if (flags.baro) {
      buffer.append(_T("; "));
      buffer.append(_("Baro"));
    }

    if (flags.airspeed) {
      buffer.append(_T("; "));
      buffer.append(_("Airspeed"));
    }

    if (flags.vario) {
      buffer.append(_T("; "));
      buffer.append(_("Vario"));
    }

    if (flags.traffic)
      buffer.append(_T("; FLARM"));

    status = buffer;
  } else if (config.IsDisabled()) {
    status = _("Disabled");
  } else if (is_simulator() || !config.IsAvailable()) {
    status = _("N/A");
  } else if (flags.open) {
    status = _("No data");
  } else {
    status = _("Not connected");
  }

  canvas.text(rc.left + margin, rc.top + 2 * margin + font_height,
              status);
}
Esempio n. 7
0
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());
  }

}
Esempio n. 8
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. 9
0
static void
PaintListItem(Canvas &canvas, const PixelRect rc, unsigned index)
{
  assert(array[index].IsDefined());

  const FlarmId id = array[index];

  const DialogLook &look = UIGlobals::GetDialogLook();
  const Font &name_font = *look.list.font;
  const Font &small_font = *look.small_font;

  canvas.SetTextColor(COLOR_BLACK);

  TCHAR tmp_id[10];
  id.Format(tmp_id);

  const FlarmRecord *record = FlarmNet::FindRecordById(id);
  const TCHAR *callsign = FlarmDetails::LookupCallsign(id);

  canvas.Select(name_font);

  StaticString<256> tmp;
  if (record != NULL)
    tmp.Format(_T("%s - %s - %s"), callsign, record->registration, tmp_id);
  else if (callsign != NULL)
    tmp.Format(_T("%s - %s"), callsign, tmp_id);
  else
    tmp.Format(_T("%s"), tmp_id);

  canvas.text_clipped(rc.left + Layout::FastScale(2),
                      rc.top + Layout::FastScale(2), rc, tmp);

  canvas.Select(small_font);

  tmp.clear();
  if (record != NULL) {
    if (!StringIsEmpty(record->pilot))
      tmp = record->pilot;

    if (!StringIsEmpty(record->plane_type)) {
      if (!tmp.empty())
        tmp.append(_T(" - "));

      tmp.append(record->plane_type);
    }

    if (!StringIsEmpty(record->airfield)) {
      if (!tmp.empty())
        tmp.append(_T(" - "));

      tmp.append(record->airfield);
    }
  }

  if (tmp.empty())
    tmp = _("No further information");

  canvas.text_clipped(rc.left + Layout::FastScale(2),
                      rc.top + name_font.GetHeight() + Layout::FastScale(4),
                      rc, tmp);
}