/**
 * This event handler is called when a key is pressed
 * @param key_code The key code of the pressed key
 * @return True if the event was handled, False otherwise
 */
static bool
FormKeyDown(gcc_unused WndForm &Sender, unsigned key_code)
{
  switch (key_code) {
  case VK_UP:
    if (!HasPointer())
      break;

    wdf->ZoomIn();
    return true;
  case VK_DOWN:
    if (!HasPointer())
      break;

    wdf->ZoomOut();
    return true;
  case VK_LEFT:
#ifdef GNAV
  case '6':
#endif
    wdf->PrevTarget();
    return true;
  case VK_RIGHT:
#ifdef GNAV
  case '7':
#endif
    wdf->NextTarget();
    return true;
  }

  return false;
}
Exemple #2
0
bool
FlarmTrafficControl::OnKeyDown(unsigned key_code)
{
  switch (key_code) {
  case KEY_UP:
    if (!HasPointer())
      break;

    ZoomIn();
    return true;

  case KEY_DOWN:
    if (!HasPointer())
      break;

    ZoomOut();
    return true;

#ifdef GNAV
  case '6':
    PrevTarget();
    return true;

  case '7':
    NextTarget();
    return true;
#endif
  }

  return FlarmTrafficWindow::OnKeyDown(key_code) ||
    InputEvents::processKey(key_code);
}
static const AbstractAirspace *
GetSelectedAirspace()
{
  return HasPointer() || focused_airspace == NULL
    ? selected_airspace
    : focused_airspace;
}
Exemple #4
0
bool
ButtonPanel::KeyPress(unsigned key_code)
{
  assert(key_code != 0);

  const unsigned n = buttons.size();
  for (unsigned i = 0; i < n; ++i) {
    if (keys[i] == key_code) {
      buttons[i]->Click();
      return true;
    }
  }

  if (selected_index >= 0 && !HasPointer()) {
    if (key_code == KEY_LEFT) {
      SelectPrevious();
      return true;
    } else if (key_code == KEY_RIGHT) {
      SelectNext();
      return true;
    } else if (key_code == KEY_RETURN) {
      auto &button = *buttons[selected_index];
      if (button.IsVisible() && button.IsEnabled())
        button.Click();
    }
  }

  return false;
}
Exemple #5
0
bool
ListControl::OnKeyCheck(unsigned key_code) const
{
  switch (key_code) {
  case KEY_RETURN:
    return CanActivateItem();

  case KEY_LEFT:
    if (!HasPointer())
      /* no wrap-around on Altair, as KEY_LEFT is usually used to
         switch to the previous dialog page */
      return true;

    return GetCursorIndex() > 0;

  case KEY_UP:
    if (!HasPointer() && IsShort())
      /* no page up/down behaviour in short lists on Altair; this
         rotation knob should move focus */
      return false;

    return GetCursorIndex() > 0;

  case KEY_RIGHT:
    if (!HasPointer())
      /* no wrap-around on Altair, as KEY_RIGHT is usually used to
         switch to the next dialog page */
      return true;

    return GetCursorIndex() + 1 < length;

  case KEY_DOWN:
    if (!HasPointer() && IsShort())
      /* no page up/down behaviour in short lists on Altair; this
         rotation knob should move focus */
      return false;

    return GetCursorIndex() + 1 < length;

  default:
    return false;
  }
}
void
AirspaceWarningListHandler::OnActivateItem(gcc_unused unsigned i)
{
  if (!HasPointer())
    /* on platforms without a pointing device (e.g. ALTAIR), allow
       "focusing" an airspace by pressing enter */
    focused_airspace = selected_airspace;
  else if (selected_airspace != NULL)
    dlgAirspaceDetails(*selected_airspace, airspace_warnings);
}
Exemple #7
0
void
Button::OnPaint(Canvas &canvas)
{
  assert(renderer != nullptr);

  const bool pressed = down;
  const bool focused = HasCursorKeys()
    ? HasFocus() || (selected && !HasPointer())
    : pressed;

  renderer->DrawButton(canvas, GetClientRect(),
                       IsEnabled(), focused, pressed);
}
Exemple #8
0
void
TabBarControl::PreviousPage()
{
  if (!pager.Previous(HasPointer()))
    /* failed to switch */
    return;

  if (tab_display != nullptr)
    tab_display->Invalidate();

  if (page_flipped_callback)
    page_flipped_callback();
}
Exemple #9
0
void
ScrollBar::SetSize(const PixelSize size)
{
  unsigned width;

  // if the device has a pointer (mouse/touchscreen/etc.)
  if (HasPointer())
    /* with a mouse, the scroll bar can be smaller */
    width = Layout::GetMinimumControlHeight();
  else
    // thin for ALTAIR b/c no touch screen
    width = Layout::SmallScale(12);

  // Update the coordinates of the scrollbar
  rc.left = size.cx - width;
  rc.top = 0;
  rc.right = size.cx;
  rc.bottom = size.cy;
}
Exemple #10
0
bool
dlgTextEntryShowModal(TCHAR *text, size_t width,
                      const TCHAR* caption, AllowedCharacters accb)
{
    switch (UIGlobals::GetDialogSettings().text_input_style) {
    case DialogSettings::TextInputStyle::Default:
    case DialogSettings::TextInputStyle::Keyboard:
        if (HasPointer())
            return dlgTextEntryKeyboardShowModal(text, width, caption, accb);
        else {
            dlgTextEntryHighscoreType(text, width, caption);
            return true;
        }

    case DialogSettings::TextInputStyle::HighScore:
        dlgTextEntryHighscoreType(text, width, caption);
        return true;
    }

    return false;
}
Exemple #11
0
bool
TextEntryDialog(TCHAR *text, size_t width,
                const TCHAR *caption, AllowedCharacters accb,
                bool default_shift_state)
{
  switch (UIGlobals::GetDialogSettings().text_input_style) {
  case DialogSettings::TextInputStyle::Default:
  case DialogSettings::TextInputStyle::Keyboard:
    if (HasPointer())
      return TouchTextEntry(text, width, caption, accb, default_shift_state);
    else {
      KnobTextEntry(text, width, caption);
      return true;
    }

  case DialogSettings::TextInputStyle::HighScore:
    KnobTextEntry(text, width, caption);
    return true;
  }

  return false;
}
bool
InterfaceConfigPanel::Save(bool &_changed, bool &_require_restart)
{
  UISettings &settings = CommonInterface::SetUISettings();
  bool changed = false, require_restart = false;;

#ifdef HAVE_BLANK
  changed |= SaveValue(AutoBlank, szProfileAutoBlank,
                       settings.display.enable_auto_blank);
#endif

  require_restart |= changed |= SaveValueFileReader(InputFile, szProfileInputFile);

#ifndef HAVE_NATIVE_GETTEXT
  WndProperty *wp = (WndProperty *)&GetControl(LanguageFile);
  if (wp != NULL) {
    DataFieldEnum &df = *(DataFieldEnum *)wp->GetDataField();

    TCHAR old_value[MAX_PATH];
    if (!Profile::GetPath(szProfileLanguageFile, old_value))
      old_value[0] = _T('\0');

    const TCHAR *old_base = BaseName(old_value);
    if (old_base == NULL)
      old_base = old_value;

    TCHAR buffer[MAX_PATH];
    const TCHAR *new_value, *new_base;

    switch (df.GetAsInteger()) {
    case 0:
      new_value = new_base = _T("auto");
      break;

    case 1:
      new_value = new_base = _T("none");
      break;

    default:
      _tcscpy(buffer, df.GetAsString());
      ContractLocalPath(buffer);
      new_value = buffer;
      new_base = BaseName(new_value);
      if (new_base == NULL)
        new_base = new_value;
      break;
    }

    if (_tcscmp(old_value, new_value) != 0 &&
        _tcscmp(old_base, new_base) != 0) {
      Profile::Set(szProfileLanguageFile, new_value);
      LanguageChanged = changed = true;
    }
  }
#endif

  require_restart |= changed |= SaveValueFileReader(StatusFile, szProfileStatusFile);

  unsigned menu_timeout = GetValueInteger(MenuTimeout) * 2;
  if (settings.menu_timeout != menu_timeout) {
    settings.menu_timeout = menu_timeout;
    Profile::Set(szProfileMenuTimeout, menu_timeout);
    changed = true;
  }

  if (HasPointer())
    changed |= SaveValueEnum(TextInput, szProfileAppTextInputStyle, settings.dialog.text_input_style);

#ifdef HAVE_VIBRATOR
  changed |= SaveValueEnum(HapticFeedback, szProfileHapticFeedback, settings.haptic_feedback);
#endif

  _changed |= changed;
  _require_restart |= require_restart;
  return true;
}
void
InterfaceConfigPanel::Prepare(ContainerWindow &parent, const PixelRect &rc)
{
  const UISettings &settings = CommonInterface::GetUISettings();

  RowFormWidget::Prepare(parent, rc);

  buttonFonts = ConfigPanel::GetExtraButton(1);
  assert(buttonFonts);

#ifdef HAVE_BLANK
  AddBoolean(_("Auto. blank"),
             _("This determines whether to blank the display after a long period of inactivity "
                 "when operating on internal battery power."),
             settings.display.enable_auto_blank);
#endif

  AddFileReader(_("Events"),
                _("The Input Events file defines the menu system and how XCSoar responds to "
                    "button presses and events from external devices."),
                szProfileInputFile, _T("*.xci\0"));
  SetExpertRow(InputFile);

#ifndef HAVE_NATIVE_GETTEXT
  WndProperty *wp;
  wp = AddEnum(_("Language"),
               _("The language options selects translations for English texts to other "
                   "languages. Select English for a native interface or Automatic to localise "
                   "XCSoar according to the system settings."));
  if (wp != NULL) {
    DataFieldEnum &df = *(DataFieldEnum *)wp->GetDataField();
    df.addEnumText(_("Automatic"));
    df.addEnumText(_("English"));

#ifdef HAVE_BUILTIN_LANGUAGES
    for (const struct builtin_language *l = language_table;
         l->resource != NULL; ++l)
      df.addEnumText(l->resource);
#endif

    LanguageFileVisitor lfv(df);
    VisitDataFiles(_T("*.mo"), lfv);

    df.Sort(2);

    TCHAR value[MAX_PATH];
    if (!Profile::GetPath(szProfileLanguageFile, value))
      value[0] = _T('\0');

    if (_tcscmp(value, _T("none")) == 0)
      df.Set(1);
    else if (!StringIsEmpty(value) && _tcscmp(value, _T("auto")) != 0) {
      const TCHAR *base = BaseName(value);
      if (base != NULL)
        df.SetAsString(base);
    }
    wp->RefreshDisplay();
  }
#endif /* !HAVE_NATIVE_GETTEXT */

  AddFileReader(_("Status message"),
                _("The status file can be used to define sounds to be played when certain "
                    "events occur, and how long various status messages will appear on screen."),
                szProfileStatusFile, _T("*.xcs\0"));
  SetExpertRow(StatusFile);

  AddTime(_("Menu timeout"),
          _("This determines how long menus will appear on screen if the user does not make any button "
            "presses or interacts with the computer."),
          1, 60, 1, settings.menu_timeout / 2);
  SetExpertRow(MenuTimeout);

  static gcc_constexpr_data StaticEnumChoice text_input_list[] = {
    { (unsigned)DialogSettings::TextInputStyle::Default, N_("Default") },
    { (unsigned)DialogSettings::TextInputStyle::Keyboard, N_("Keyboard") },
    { (unsigned)DialogSettings::TextInputStyle::HighScore,
      N_("HighScore Style") },
    { 0 }
  };

  AddEnum(_("Text input style"),
          _("Determines how the user is prompted for text input (filename, teamcode etc.)"),
          text_input_list, (unsigned)settings.dialog.text_input_style);
  SetExpertRow(TextInput);

  /* on-screen keyboard doesn't work without a pointing device
     (mouse or touch screen), hide the option on Altair */
  SetRowVisible(TextInput, HasPointer());

#ifdef HAVE_VIBRATOR
  static gcc_constexpr_data StaticEnumChoice haptic_feedback_list[] = {
    { (unsigned) UISettings::HapticFeedback::Default, N_("OS settings") },
    { (unsigned) UISettings::HapticFeedback::Off, N_("Off") },
    { (unsigned) UISettings::HapticFeedback::On, N_("On") },
    { 0 }
  };

  wp = AddEnum(_("Haptic feedback"),
               _("Determines if haptic feedback like vibration is used."),
               haptic_feedback_list, (unsigned)settings.haptic_feedback);
  SetExpertRow(HapticFeedback);
#endif /* HAVE_VIBRATOR */
}
Exemple #14
0
bool
ListControl::OnKeyDown(unsigned key_code)
{
  scroll_bar.DragEnd(this);

#ifndef _WIN32_WCE
  kinetic_timer.Cancel();
#endif

  switch (key_code) {
#ifdef GNAV
  // JMW added this to make data entry easier
  case KEY_APP4:
#endif
  case KEY_RETURN:
    if (CanActivateItem())
      ActivateItem();
    return true;

  case KEY_UP:
  case KEY_LEFT:
    if (!HasPointer() ^ (key_code == KEY_LEFT)) {
      // page up
      MoveCursor(-(int)items_visible);
      return true;
    } else {
      // previous item
      if (GetCursorIndex() <= 0)
        break;

      MoveCursor(-1);
      return true;
    }

  case KEY_DOWN:
  case KEY_RIGHT:
    if (!HasPointer() ^ (key_code == KEY_RIGHT)) {
      // page down
      MoveCursor(items_visible);
      return true;
    } else {
      // next item
      if (GetCursorIndex() +1 >= length)
        break;

      MoveCursor(1);
      return true;
    }

  case KEY_HOME:
    SetCursorIndex(0);
    return true;

  case KEY_END:
    if (length > 0) {
      SetCursorIndex(length - 1);
    }
    return true;

  case KEY_PRIOR:
    MoveCursor(-(int)items_visible);
    return true;

  case KEY_NEXT:
    MoveCursor(items_visible);
    return true;
  }
  return PaintWindow::OnKeyDown(key_code);
}
void
InterfaceConfigPanel::Prepare(ContainerWindow &parent, const PixelRect &rc)
{
  const UISettings &settings = CommonInterface::GetUISettings();

  RowFormWidget::Prepare(parent, rc);

  AddInteger(_("Text size"),
             nullptr,
             _T("%d %%"), _T("%d"), 75, 200, 5,
             settings.scale);

  AddFile(_("Events"),
          _("The Input Events file defines the menu system and how XCSoar responds to "
            "button presses and events from external devices."),
          ProfileKeys::InputFile, _T("*.xci\0"));
  SetExpertRow(InputFile);

#ifndef HAVE_NATIVE_GETTEXT
  WndProperty *wp;
  wp = AddEnum(_("Language"),
               _("The language options selects translations for English texts to other "
                   "languages. Select English for a native interface or Automatic to localise "
                   "XCSoar according to the system settings."));
  if (wp != nullptr) {
    DataFieldEnum &df = *(DataFieldEnum *)wp->GetDataField();
    df.addEnumText(_("Automatic"));
    df.addEnumText(_T("English"));

#ifdef HAVE_BUILTIN_LANGUAGES
    for (const BuiltinLanguage *l = language_table;
         l->resource != nullptr; ++l) {
      StaticString<100> display_string;
      display_string.Format(_T("%s (%s)"), l->name, l->resource);
      df.addEnumText(l->resource, display_string);
    }
#endif

    LanguageFileVisitor lfv(df);
    VisitDataFiles(_T("*.mo"), lfv);

    df.Sort(2);

    auto value_buffer = Profile::GetPath(ProfileKeys::LanguageFile);
    Path value = value_buffer;
    if (value.IsNull())
      value = Path(_T(""));

    if (value == Path(_T("none")))
      df.Set(1);
    else if (!value.IsEmpty() && value != Path(_T("auto"))) {
      const Path base = value.GetBase();
      if (base != nullptr)
        df.Set(base.c_str());
    }
    wp->RefreshDisplay();
  }
#endif /* !HAVE_NATIVE_GETTEXT */

  AddTime(_("Menu timeout"),
          _("This determines how long menus will appear on screen if the user does not make any button "
            "presses or interacts with the computer."),
          1, 60, 1, settings.menu_timeout / 2);
  SetExpertRow(MenuTimeout);

  static constexpr StaticEnumChoice text_input_list[] = {
    { (unsigned)DialogSettings::TextInputStyle::Default, N_("Default") },
    { (unsigned)DialogSettings::TextInputStyle::Keyboard, N_("Keyboard") },
    { (unsigned)DialogSettings::TextInputStyle::HighScore,
      N_("HighScore Style") },
    { 0 }
  };

  AddEnum(_("Text input style"),
          _("Determines how the user is prompted for text input (filename, teamcode etc.)"),
          text_input_list, (unsigned)settings.dialog.text_input_style);
  SetExpertRow(TextInput);

  /* on-screen keyboard doesn't work without a pointing device
     (mouse or touch screen) */
  SetRowVisible(TextInput, HasPointer());

#ifdef HAVE_VIBRATOR
  static constexpr StaticEnumChoice haptic_feedback_list[] = {
    { (unsigned)UISettings::HapticFeedback::DEFAULT, N_("OS settings") },
    { (unsigned)UISettings::HapticFeedback::OFF, N_("Off") },
    { (unsigned)UISettings::HapticFeedback::ON, N_("On") },
    { 0 }
  };

  wp = AddEnum(_("Haptic feedback"),
               _("Determines if haptic feedback like vibration is used."),
               haptic_feedback_list, (unsigned)settings.haptic_feedback);
  SetExpertRow(HapticFeedback);
#endif /* HAVE_VIBRATOR */
}
Exemple #16
0
bool
TabWidget::PreviousPage()
{
  return Previous(HasPointer());
}
Exemple #17
0
bool
TabWidget::NextPage()
{
  return Next(HasPointer());
}
void
AirspaceWarningMonitor::Check()
{
  const auto &calculated = CommonInterface::Calculated();

  if (widget == nullptr && calculated.airspace_warnings.latest == last)
    return;

  /* there's a new airspace warning */

  last = calculated.airspace_warnings.latest;

  auto *airspace_warnings = GetAirspaceWarnings();
  if (airspace_warnings == nullptr) {
    HideWidget();
    return;
  }

  if (!HasPointer()) {
    /* "classic" list-only view for devices without touch screen */

    if (dlgAirspaceWarningVisible())
      /* already visible */
      return;

    // un-blank the display, play a sound
    ResetUserIdle();
    PlayResource(_T("IDR_WAV_BEEPBWEEP"));

    // show airspace warnings dialog
    if (CommonInterface::GetUISettings().enable_airspace_warning_dialog)
      dlgAirspaceWarningsShowModal(*airspace_warnings, true);
    return;
  }

  const AbstractAirspace *airspace = nullptr;
  AirspaceWarning::State state;
  AirspaceInterceptSolution solution;

  {
    const ProtectedAirspaceWarningManager::Lease lease(*airspace_warnings);
    auto w = lease->begin();
    if (w != lease->end() && w->IsAckExpired()) {
      airspace = &w->GetAirspace();
      state = w->GetWarningState();
      solution = w->GetSolution();
    }
  }

  if (airspace == nullptr) {
    HideWidget();
    return;
  }

  if (CommonInterface::GetUISettings().enable_airspace_warning_dialog) {
    /* show airspace warning */
    if (widget != nullptr) {
      if (widget->Update(*airspace, state, solution))
        return;

      HideWidget();
    }

    widget = new AirspaceWarningWidget(*this, *airspace_warnings,
                                       *airspace, state, solution);
    PageActions::SetCustomBottom(widget);
  }

  // un-blank the display, play a sound
  ResetUserIdle();
  PlayResource(_T("IDR_WAV_BEEPBWEEP"));
}
bool
InterfaceConfigPanel::Save(bool &_changed)
{
  UISettings &settings = CommonInterface::SetUISettings();
  bool changed = false;;

  if (SaveValueEnum(UIScale, ProfileKeys::UIScale,
                    settings.scale))
    require_restart = changed = true;

  if (SaveValueFileReader(InputFile, ProfileKeys::InputFile))
    require_restart = changed = true;

#ifndef HAVE_NATIVE_GETTEXT
  WndProperty *wp = (WndProperty *)&GetControl(LanguageFile);
  if (wp != nullptr) {
    DataFieldEnum &df = *(DataFieldEnum *)wp->GetDataField();

    const auto old_value_buffer = Profile::GetPath(ProfileKeys::LanguageFile);
    Path old_value = old_value_buffer;
    if (old_value == nullptr)
      old_value = Path(_T(""));

    auto old_base = old_value.GetBase();
    if (old_base == nullptr)
      old_base = old_value;

    AllocatedPath buffer = nullptr;
    const TCHAR *new_value, *new_base;

    switch (df.GetValue()) {
    case 0:
      new_value = new_base = _T("auto");
      break;

    case 1:
      new_value = new_base = _T("none");
      break;

    default:
      new_value = df.GetAsString();
      buffer = ContractLocalPath(Path(new_value));
      if (!buffer.IsNull())
        new_value = buffer.c_str();
      new_base = Path(new_value).GetBase().c_str();
      if (new_base == nullptr)
        new_base = new_value;
      break;
    }

    if (old_value != Path(new_value) &&
        old_base != Path(new_base)) {
      Profile::Set(ProfileKeys::LanguageFile, new_value);
      LanguageChanged = changed = true;
    }
  }
#endif

  unsigned menu_timeout = GetValueInteger(MenuTimeout) * 2;
  if (settings.menu_timeout != menu_timeout) {
    settings.menu_timeout = menu_timeout;
    Profile::Set(ProfileKeys::MenuTimeout, menu_timeout);
    changed = true;
  }

  if (HasPointer())
    changed |= SaveValueEnum(TextInput, ProfileKeys::AppTextInputStyle, settings.dialog.text_input_style);

#ifdef HAVE_VIBRATOR
  changed |= SaveValueEnum(HapticFeedback, ProfileKeys::HapticFeedback, settings.haptic_feedback);
#endif

  _changed |= changed;
  return true;
}