bool
dlgTaskPointType(OrderedTask** task, const unsigned index)
{
  ordered_task = *task;
  active_index = index;

  point = &ordered_task->GetPoint(active_index);

  point_types.clear();
  ordered_task->GetFactory().GetValidTypes(index)
    .CopyTo(std::back_inserter(point_types));

  if (point_types.empty()) {
    assert(1);
    return false;
  }

  if (point_types.size() == 1)
    return SetPointType(point_types[0]);

  unsigned initial_index = 0;
  const auto b = point_types.begin(), e = point_types.end();
  auto i = std::find(b, e, get_point_type());
  if (i != e)
    initial_index = std::distance(b, i);

  FunctionListItemRenderer item_renderer(OnPointPaintListItem);

  int result = ListPicker(_("Task Point Type"),
                          point_types.size(), initial_index,
                          Layout::Scale(18),
                          item_renderer, false,
                          nullptr, TPTypeItemHelp);
  return result >= 0 && SetPointType(point_types[result]);
}
static bool
SetPointType(AbstractTaskFactory::LegalPointType type)
{
  bool apply = false;

  if (!point) {
    apply = true;
    // empty point, don't ask confirmation
  } else {
    if (type == get_point_type())
      // no change
      return true;

    if (MessageBoxX(_("Change point type?"), _("Task Point"),
                    MB_YESNO | MB_ICONQUESTION) == IDYES)
      apply = true;
  }

  if (apply) {
    AbstractTaskFactory &factory = ordered_task->GetFactory();

    if (point) {
      point = factory.CreateMutatedPoint(*point, type);
      if (point == NULL)
        return false;

      if (factory.Replace(*point, active_index, true))
        task_modified = true;
      delete point;
    } else {
      if (factory.IsValidFinishType(type) &&
          ordered_task->get_ordered_task_behaviour().is_closed)
        way_point = &(ordered_task->get_tp(0)->GetWaypoint());
      else
        way_point =
          dlgWaypointSelect(wf->GetMainWindow(),
                              ordered_task->TaskSize() > 0 ?
                              ordered_task->get_tp(ordered_task->
                                  TaskSize() - 1)->GetLocation() :
                              XCSoarInterface::Basic().location);
      if (!way_point)
        return false;

      point = factory.CreatePoint(type, *way_point);
      if (point == NULL)
        return false;

      if (factory.Append(*point, true))
        task_modified = true;

      delete point;
    }
    return true;
  }
  return false;
}
bool
dlgTaskPointType(SingleWindow &parent, OrderedTask** task, const unsigned index)
{
  ordered_task = *task;
  task_modified = false;
  active_index = index;

  point = ordered_task->get_tp(active_index);
  if (point)
    way_point = &point->GetWaypoint();
  else
    way_point = NULL;

  if (Layout::landscape)
    wf = LoadDialog(CallBackTable, parent, _T("IDR_XML_TASKPOINTTYPE_L"));
  else
    wf = LoadDialog(CallBackTable, parent, _T("IDR_XML_TASKPOINTTYPE"));

  if (!wf)
    return false;

  assert(wf != NULL);

  wPointTypes = (WndListFrame*)wf->FindByName(_T("frmPointTypes"));
  assert(wPointTypes != NULL);

  point_types = ordered_task->GetFactory().GetValidTypes(index);
  if (point_types.empty()) {
    assert(1);
    return false;
  }

  wPointTypes->SetActivateCallback(OnPointListEnter);
  wPointTypes->SetPaintItemCallback(OnPointPaintListItem);
  wPointTypes->SetCursorCallback(OnPointCursorCallback);
  wPointTypes->SetLength(point_types.size());

  if (point)
    for (unsigned i=0; i<point_types.size(); i++)
      if (point_types[i] == get_point_type())
        wPointTypes->SetCursorIndex(i); 

  RefreshView();

  if (point_types.size()==1)
    SetPointType(point_types[0]);
  else
    wf->ShowModal();

  delete wf;
  wf = NULL;

  return task_modified;
}
static void
OnPointPaintListItem(Canvas &canvas, const PixelRect rc,
                     unsigned DrawListIndex)
{
  assert(DrawListIndex < point_types.size());

  StaticString<120> buffer;

  const TCHAR* text = OrderedTaskPointName(point_types[DrawListIndex]);

  if (point && (point_types[DrawListIndex] == get_point_type()))
    buffer.Format(_T("*%s"), text);
  else
    buffer.Format(_T(" %s"), text);

  canvas.text(rc.left + Layout::FastScale(2),
              rc.top + Layout::FastScale(2), buffer);
}
/**
 * @return true if the task was modified
 */
static bool
SetPointType(TaskPointFactoryType type)
{
  if (type == get_point_type())
    // no change
    return false;

  AbstractTaskFactory &factory = ordered_task->GetFactory();
  bool task_modified = false;

  point = factory.CreateMutatedPoint(*point, type);
  if (point == nullptr)
    return false;

  if (factory.Replace(*point, active_index, true))
    task_modified = true;
  delete point;

  return task_modified;
}