/** * 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; }
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; }
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; }
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); }
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); }
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(); }
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; }
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; }
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 */ }
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 */ }
bool TabWidget::PreviousPage() { return Previous(HasPointer()); }
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; }