2015-07-08 11:39:24 -04:00
/*
* Copyright ( C ) 2015 Jared Boone , ShareBrained Technology , Inc .
2016-07-29 23:27:28 -04:00
* Copyright ( C ) 2016 Furrtek
2015-07-08 11:39:24 -04:00
*
* This file is part of PortaPack .
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 2 , or ( at your option )
* any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program ; see the file COPYING . If not , write to
* the Free Software Foundation , Inc . , 51 Franklin Street ,
* Boston , MA 02110 - 1301 , USA .
*/
# include "ui_navigation.hpp"
2016-04-28 08:59:14 -04:00
2023-05-23 00:39:22 -04:00
// #include "modules.h"
2015-07-08 11:39:24 -04:00
2015-10-16 22:39:44 -04:00
# include "portapack.hpp"
2016-01-31 03:34:24 -05:00
# include "event_m0.hpp"
2016-08-23 02:45:33 -04:00
# include "bmp_splash.hpp"
# include "bmp_modal_warning.hpp"
2017-06-10 21:53:06 -04:00
# include "portapack_persistent_memory.hpp"
2023-04-23 15:48:45 -04:00
# include "portapack_shared_memory.hpp"
2015-07-08 11:39:24 -04:00
2020-08-08 17:06:53 -04:00
# include "ui_about_simple.hpp"
2017-07-14 05:02:21 -04:00
# include "ui_adsb_rx.hpp"
2017-10-14 11:30:49 -04:00
# include "ui_adsb_tx.hpp"
2017-08-29 04:42:04 -04:00
# include "ui_afsk_rx.hpp"
2021-03-07 17:05:23 -05:00
# include "ui_aprs_rx.hpp"
2020-04-20 00:50:03 -04:00
# include "ui_btle_rx.hpp"
2020-04-20 00:45:28 -04:00
# include "ui_nrf_rx.hpp"
2017-10-14 11:30:49 -04:00
# include "ui_aprs_tx.hpp"
2017-01-16 03:40:17 -05:00
# include "ui_bht_tx.hpp"
2017-04-07 01:20:24 -04:00
# include "ui_coasterp.hpp"
2020-04-21 08:22:09 -04:00
# include "ui_debug.hpp"
2016-12-09 12:21:47 -05:00
# include "ui_encoders.hpp"
2017-09-19 15:14:56 -04:00
# include "ui_fileman.hpp"
2023-06-07 11:33:32 -04:00
# include "ui_font_fixed_8x16.hpp"
2016-12-05 06:56:41 -05:00
# include "ui_freqman.hpp"
2016-12-09 12:21:47 -05:00
# include "ui_jammer.hpp"
2023-05-23 00:39:22 -04:00
// #include "ui_keyfob.hpp"
2016-12-09 12:21:47 -05:00
# include "ui_lcr.hpp"
2017-03-21 23:21:06 -04:00
# include "ui_mictx.hpp"
2016-12-09 12:21:47 -05:00
# include "ui_morse.hpp"
2023-05-23 00:39:22 -04:00
// #include "ui_numbers.hpp"
// #include "ui_nuoptix.hpp"
// #include "ui_playdead.hpp"
2017-02-07 12:48:17 -05:00
# include "ui_pocsag_tx.hpp"
2016-07-26 21:03:40 -04:00
# include "ui_rds.hpp"
2018-03-27 07:52:07 -04:00
# include "ui_remote.hpp"
2017-05-18 06:06:11 -04:00
# include "ui_scanner.hpp"
2018-03-27 07:52:07 -04:00
# include "ui_search.hpp"
2022-09-11 10:10:35 -04:00
# include "ui_recon.hpp"
2023-03-10 08:25:38 -05:00
# include "ui_level.hpp"
2017-10-14 11:30:49 -04:00
# include "ui_sd_wipe.hpp"
2018-05-16 04:45:13 -04:00
# include "ui_settings.hpp"
2017-10-14 11:30:49 -04:00
# include "ui_siggen.hpp"
# include "ui_sonde.hpp"
2017-03-22 14:21:31 -04:00
# include "ui_sstvtx.hpp"
2023-06-07 11:33:32 -04:00
# include "ui_styles.hpp"
2023-05-23 00:39:22 -04:00
// #include "ui_test.hpp"
2023-05-19 16:39:35 -04:00
# include "ui_text_editor.hpp"
2018-02-23 15:21:24 -05:00
# include "ui_tone_search.hpp"
2017-09-23 07:02:32 -04:00
# include "ui_touchtunes.hpp"
2022-04-03 19:38:06 -04:00
# include "ui_playlist.hpp"
2017-10-15 10:53:40 -04:00
# include "ui_view_wav.hpp"
2016-12-09 12:21:47 -05:00
# include "ui_whipcalc.hpp"
2023-03-28 08:39:00 -04:00
# include "ui_flash_utility.hpp"
2023-03-29 11:05:11 -04:00
# include "ui_sd_over_usb.hpp"
2023-05-14 17:09:43 -04:00
# include "ui_spectrum_painter.hpp"
2023-07-05 16:45:43 -04:00
# include "ui_ss_viewer.hpp"
2016-12-09 12:21:47 -05:00
2023-05-23 00:39:22 -04:00
// #include "acars_app.hpp"
2016-01-31 03:34:24 -05:00
# include "ais_app.hpp"
2018-06-10 05:15:43 -04:00
# include "analog_audio_app.hpp"
2020-04-20 00:50:24 -04:00
# include "analog_tv_app.hpp"
2018-06-10 05:15:43 -04:00
# include "capture_app.hpp"
2016-01-31 03:34:24 -05:00
# include "ert_app.hpp"
2019-02-06 12:34:53 -05:00
# include "lge_app.hpp"
2016-08-23 02:45:33 -04:00
# include "pocsag_app.hpp"
2017-01-10 14:45:40 -05:00
# include "replay_app.hpp"
2020-04-17 19:17:13 -04:00
# include "gps_sim_app.hpp"
2018-12-18 11:25:21 -05:00
# include "soundboard_app.hpp"
2018-06-10 05:15:43 -04:00
# include "tpms_app.hpp"
2016-01-31 03:34:24 -05:00
2016-02-16 14:09:00 -05:00
# include "core_control.hpp"
2020-10-21 12:21:34 -04:00
# include "ui_looking_glass_app.hpp"
2016-04-20 13:22:05 -04:00
# include "file.hpp"
2016-02-19 18:34:02 -05:00
# include "png_writer.hpp"
2015-07-08 11:39:24 -04:00
2018-01-07 18:13:08 -05:00
using portapack : : receiver_model ;
2018-02-22 02:04:19 -05:00
using portapack : : transmitter_model ;
2023-06-23 19:13:39 -04:00
namespace pmem = portapack : : persistent_memory ;
2018-01-07 18:13:08 -05:00
2015-07-08 11:39:24 -04:00
namespace ui {
2023-06-23 19:13:39 -04:00
/* StatusTray ************************************************************/
StatusTray : : StatusTray ( Point pos )
: View { { pos , { 0 , height } } } ,
pos_ ( pos ) {
set_focusable ( false ) ;
}
void StatusTray : : add ( Widget * child ) {
width_ + = child - > parent_rect ( ) . width ( ) ;
add_child ( child ) ;
}
void StatusTray : : update_layout ( ) {
// Widen the tray's parent rect.
auto rect = parent_rect ( ) ;
set_parent_rect ( { { rect . left ( ) - width_ , rect . top ( ) } , { rect . right ( ) + width_ , height } } ) ;
// Update the children.
auto x = 0 ;
for ( auto child : children ( ) ) {
auto size = child - > parent_rect ( ) . size ( ) ;
child - > set_parent_rect ( { { x , 0 } , size } ) ;
x + = size . width ( ) ;
}
set_dirty ( ) ;
}
void StatusTray : : clear ( ) {
// More efficient than 'remove_children'.
for ( auto child : children ( ) )
child - > set_parent ( nullptr ) ;
children_ . clear ( ) ;
width_ = 0 ;
set_parent_rect ( { pos_ , { width_ , height } } ) ;
set_dirty ( ) ;
}
void StatusTray : : paint ( Painter & ) {
}
2015-07-08 11:39:24 -04:00
/* SystemStatusView ******************************************************/
2018-01-07 22:47:37 -05:00
SystemStatusView : : SystemStatusView (
2023-05-18 16:16:05 -04:00
NavigationView & nav )
: nav_ ( nav ) {
add_children ( {
& backdrop ,
& button_back ,
& title ,
& button_title ,
2023-06-23 19:13:39 -04:00
& status_icons ,
2023-05-18 16:16:05 -04:00
} ) ;
2023-06-23 19:13:39 -04:00
if ( pmem : : should_use_sdcard_for_pmem ( ) ) {
pmem : : load_persistent_settings_from_file ( ) ;
2023-05-18 16:16:05 -04:00
}
button_back . id = - 1 ; // Special ID used by FocusManager
2023-06-07 11:33:32 -04:00
title . set_style ( & Styles : : bg_dark_grey ) ;
2023-05-18 16:16:05 -04:00
button_back . on_select = [ this ] ( ImageButton & ) {
2023-06-23 19:13:39 -04:00
if ( pmem : : should_use_sdcard_for_pmem ( ) ) {
pmem : : save_persistent_settings_to_file ( ) ;
2023-06-04 15:25:25 -04:00
}
2023-05-18 16:16:05 -04:00
if ( this - > on_back )
this - > on_back ( ) ;
} ;
button_title . on_select = [ this ] ( ImageButton & ) {
this - > on_title ( ) ;
} ;
button_converter . on_select = [ this ] ( ImageButton & ) {
this - > on_converter ( ) ;
} ;
2023-07-05 03:12:40 -04:00
toggle_speaker . on_change = [ this ] ( bool v ) {
pmem : : set_config_speaker_disable ( v ) ;
audio : : output : : update_audio_mute ( ) ;
refresh ( ) ;
2023-05-18 16:16:05 -04:00
} ;
2023-07-05 03:12:40 -04:00
toggle_mute . on_change = [ this ] ( bool v ) {
pmem : : set_config_audio_mute ( v ) ;
audio : : output : : update_audio_mute ( ) ;
refresh ( ) ;
2023-06-26 02:08:09 -04:00
} ;
2023-07-05 03:12:40 -04:00
toggle_stealth . on_change = [ this ] ( bool v ) {
pmem : : set_stealth_mode ( v ) ;
refresh ( ) ;
2023-05-18 16:16:05 -04:00
} ;
button_bias_tee . on_select = [ this ] ( ImageButton & ) {
this - > on_bias_tee ( ) ;
} ;
button_camera . on_select = [ this ] ( ImageButton & ) {
this - > on_camera ( ) ;
} ;
button_sleep . on_select = [ this ] ( ImageButton & ) {
DisplaySleepMessage message ;
EventDispatcher : : send_message ( message ) ;
} ;
button_clock_status . on_select = [ this ] ( ImageButton & ) {
this - > on_clk ( ) ;
} ;
2023-06-19 15:06:07 -04:00
2023-07-05 03:12:40 -04:00
// Initialize toggle buttons
toggle_speaker . set_value ( pmem : : config_speaker_disable ( ) ) ;
toggle_mute . set_value ( pmem : : config_audio_mute ( ) ) ;
toggle_stealth . set_value ( pmem : : stealth_mode ( ) ) ;
2023-08-20 05:13:04 -04:00
audio : : output : : stop ( ) ;
2023-06-19 15:06:07 -04:00
audio : : output : : update_audio_mute ( ) ;
2023-06-23 19:13:39 -04:00
refresh ( ) ;
2016-01-31 03:34:24 -05:00
}
2018-01-07 18:13:08 -05:00
void SystemStatusView : : refresh ( ) {
2023-06-23 19:13:39 -04:00
// NB: Order of insertion is the display order Left->Right.
// TODO: Might be better to support hide and only add once.
status_icons . clear ( ) ;
2023-06-27 22:34:25 -04:00
if ( ! pmem : : ui_hide_camera ( ) ) status_icons . add ( & button_camera ) ;
if ( ! pmem : : ui_hide_sleep ( ) ) status_icons . add ( & button_sleep ) ;
2023-07-05 03:12:40 -04:00
if ( ! pmem : : ui_hide_stealth ( ) ) status_icons . add ( & toggle_stealth ) ;
2023-06-27 22:34:25 -04:00
if ( ! pmem : : ui_hide_converter ( ) ) status_icons . add ( & button_converter ) ;
if ( ! pmem : : ui_hide_bias_tee ( ) ) status_icons . add ( & button_bias_tee ) ;
if ( ! pmem : : ui_hide_clock ( ) ) status_icons . add ( & button_clock_status ) ;
2023-07-05 03:12:40 -04:00
if ( ! pmem : : ui_hide_mute ( ) ) status_icons . add ( & toggle_mute ) ;
2023-06-26 02:08:09 -04:00
// Display "Disable speaker" icon only if AK4951 Codec which has separate speaker/headphone control
2023-07-05 03:12:40 -04:00
if ( audio : : speaker_disable_supported ( ) & & ! pmem : : ui_hide_speaker ( ) ) status_icons . add ( & toggle_speaker ) ;
2023-06-26 02:08:09 -04:00
2023-06-23 19:13:39 -04:00
if ( ! pmem : : ui_hide_sd_card ( ) ) status_icons . add ( & sd_card_status_view ) ;
status_icons . update_layout ( ) ;
// Clock status
bool external_clk = portapack : : clock_manager . get_reference ( ) . source = = ClockManager : : ReferenceSource : : External ;
button_clock_status . set_bitmap ( external_clk ? & bitmap_icon_clk_ext : & bitmap_icon_clk_int ) ;
2023-07-05 03:12:40 -04:00
button_clock_status . set_foreground ( pmem : : clkout_enabled ( ) ? Color : : green ( ) : Color : : light_grey ( ) ) ;
2023-06-23 19:13:39 -04:00
// Antenna DC Bias
2023-05-18 16:16:05 -04:00
if ( portapack : : get_antenna_bias ( ) ) {
button_bias_tee . set_bitmap ( & bitmap_icon_biast_on ) ;
2023-06-23 19:13:39 -04:00
button_bias_tee . set_foreground ( Color : : yellow ( ) ) ;
2023-05-18 16:16:05 -04:00
} else {
button_bias_tee . set_bitmap ( & bitmap_icon_biast_off ) ;
2023-06-23 19:13:39 -04:00
button_bias_tee . set_foreground ( Color : : light_grey ( ) ) ;
2023-05-18 16:16:05 -04:00
}
2023-06-23 19:13:39 -04:00
// Converter
2023-07-05 03:12:40 -04:00
button_converter . set_bitmap ( pmem : : config_updown_converter ( ) ? & bitmap_icon_downconvert : & bitmap_icon_upconvert ) ;
2023-06-23 19:13:39 -04:00
button_converter . set_foreground ( pmem : : config_converter ( ) ? Color : : red ( ) : Color : : light_grey ( ) ) ;
2023-05-18 16:16:05 -04:00
set_dirty ( ) ;
2018-01-07 18:13:08 -05:00
}
2016-02-07 13:33:15 -05:00
void SystemStatusView : : set_back_enabled ( bool new_value ) {
2023-05-18 16:16:05 -04:00
if ( new_value ) {
add_child ( & button_back ) ;
} else {
remove_child ( & button_back ) ;
}
2020-08-01 21:55:09 -04:00
}
void SystemStatusView : : set_title_image_enabled ( bool new_value ) {
2023-05-18 16:16:05 -04:00
if ( new_value ) {
add_child ( & button_title ) ;
} else {
remove_child ( & button_title ) ;
}
2016-01-31 03:34:24 -05:00
}
void SystemStatusView : : set_title ( const std : : string new_value ) {
2023-05-18 16:16:05 -04:00
if ( new_value . empty ( ) ) {
title . set ( default_title ) ;
} else {
2023-06-27 04:15:58 -04:00
// Limit length of title string to prevent partial characters if too many StatusView icons
2023-06-27 22:34:25 -04:00
size_t max_len = ( status_icons . parent_rect ( ) . left ( ) - title . parent_rect ( ) . left ( ) ) / 8 ;
2023-06-27 04:15:58 -04:00
title . set ( truncate ( new_value , max_len ) ) ;
2023-05-18 16:16:05 -04:00
}
2015-07-08 11:39:24 -04:00
}
2023-03-27 08:22:35 -04:00
void SystemStatusView : : on_converter ( ) {
2023-06-23 19:13:39 -04:00
pmem : : set_config_converter ( ! pmem : : config_converter ( ) ) ;
2023-06-11 14:47:13 -04:00
2023-06-17 17:15:21 -04:00
// Poke to update tuning
// NOTE: Code assumes here that a TX app isn't active, since RX & TX have diff tuning offsets
// (and there's only one tuner in the radio so can't update tuner for both).
2023-06-23 19:13:39 -04:00
// TODO: Maybe expose the 'enabled_' flag on models.
2023-06-11 14:47:13 -04:00
receiver_model . set_target_frequency ( receiver_model . target_frequency ( ) ) ;
2023-06-23 19:13:39 -04:00
refresh ( ) ;
2023-05-18 16:16:05 -04:00
}
2023-03-22 03:46:58 -04:00
2018-01-07 22:47:37 -05:00
void SystemStatusView : : on_bias_tee ( ) {
2023-05-24 00:22:30 -04:00
if ( ! portapack : : get_antenna_bias ( ) ) {
2023-06-23 19:13:39 -04:00
nav_ . display_modal ( " Bias voltage " ,
" Enable DC voltage on \n antenna connector? " ,
YESNO ,
[ this ] ( bool v ) {
if ( v ) {
portapack : : set_antenna_bias ( true ) ;
receiver_model . set_antenna_bias ( ) ;
transmitter_model . set_antenna_bias ( ) ;
refresh ( ) ;
}
} ) ;
2023-05-18 16:16:05 -04:00
} else {
portapack : : set_antenna_bias ( false ) ;
receiver_model . set_antenna_bias ( ) ;
transmitter_model . set_antenna_bias ( ) ;
2023-05-24 00:22:30 -04:00
// Ensure this is disabled. The models don't actually
// update the radio unless they are 'enabled_'.
radio : : set_antenna_bias ( false ) ;
2023-05-18 16:16:05 -04:00
refresh ( ) ;
}
2018-01-07 22:47:37 -05:00
}
2016-02-19 00:35:46 -05:00
void SystemStatusView : : on_camera ( ) {
2023-05-18 16:16:05 -04:00
ensure_directory ( " SCREENSHOTS " ) ;
auto path = next_filename_matching_pattern ( u " SCREENSHOTS/SCR_????.PNG " ) ;
2023-05-12 14:08:07 -04:00
2023-06-23 19:13:39 -04:00
if ( path . empty ( ) )
2023-05-18 16:16:05 -04:00
return ;
2016-04-20 13:22:05 -04:00
2023-05-18 16:16:05 -04:00
PNGWriter png ;
2023-06-23 19:13:39 -04:00
auto error = png . create ( path ) ;
if ( error )
2023-05-18 16:16:05 -04:00
return ;
2016-02-19 18:34:02 -05:00
2023-06-23 19:13:39 -04:00
for ( int i = 0 ; i < screen_height ; i + + ) {
std : : array < ColorRGB888 , screen_width > row ;
portapack : : display . read_pixels ( { 0 , i , screen_width , 1 } , row ) ;
2023-05-18 16:16:05 -04:00
png . write_scanline ( row ) ;
}
2016-02-19 00:35:46 -05:00
}
2020-09-16 07:27:56 -04:00
void SystemStatusView : : on_clk ( ) {
2023-06-23 19:13:39 -04:00
pmem : : set_clkout_enabled ( ! pmem : : clkout_enabled ( ) ) ;
portapack : : clock_manager . enable_clock_output ( pmem : : clkout_enabled ( ) ) ;
2023-05-18 16:16:05 -04:00
refresh ( ) ;
2020-09-16 07:27:56 -04:00
}
2020-08-01 21:55:09 -04:00
void SystemStatusView : : on_title ( ) {
2023-05-18 16:16:05 -04:00
if ( nav_ . is_top ( ) )
nav_ . push < AboutView > ( ) ;
else
nav_ . pop ( ) ;
2020-08-01 21:55:09 -04:00
}
2020-08-05 01:03:51 -04:00
/* Information View *****************************************************/
InformationView : : InformationView (
2023-05-18 16:16:05 -04:00
NavigationView & nav )
: nav_ ( nav ) {
static constexpr Style style_infobar {
. font = font : : fixed_8x16 ,
. background = { 33 , 33 , 33 } ,
. foreground = Color : : white ( ) ,
} ;
add_children ( { & backdrop ,
& version ,
& ltime } ) ;
version . set_style ( & style_infobar ) ;
2023-06-23 19:13:39 -04:00
ltime . set_hide_clock ( pmem : : hide_clock ( ) ) ;
2023-05-18 16:16:05 -04:00
ltime . set_style ( & style_infobar ) ;
ltime . set_seconds_enabled ( true ) ;
2023-06-23 19:13:39 -04:00
ltime . set_date_enabled ( pmem : : clock_with_date ( ) ) ;
2023-05-18 16:16:05 -04:00
set_dirty ( ) ;
2020-08-01 21:55:09 -04:00
}
2021-05-16 05:41:09 -04:00
void InformationView : : refresh ( ) {
2023-06-23 19:13:39 -04:00
ltime . set_hide_clock ( pmem : : hide_clock ( ) ) ;
2023-05-18 16:16:05 -04:00
ltime . set_seconds_enabled ( true ) ;
2023-06-23 19:13:39 -04:00
ltime . set_date_enabled ( pmem : : clock_with_date ( ) ) ;
2021-05-16 05:41:09 -04:00
}
2015-07-08 11:39:24 -04:00
/* Navigation ************************************************************/
2016-01-31 03:34:24 -05:00
bool NavigationView : : is_top ( ) const {
2023-05-18 16:16:05 -04:00
return view_stack . size ( ) = = 1 ;
2015-07-08 11:39:24 -04:00
}
2016-01-31 03:34:24 -05:00
View * NavigationView : : push_view ( std : : unique_ptr < View > new_view ) {
2023-05-18 16:16:05 -04:00
free_view ( ) ;
2016-01-31 03:34:24 -05:00
2023-05-18 16:16:05 -04:00
const auto p = new_view . get ( ) ;
2023-06-01 18:45:55 -04:00
view_stack . emplace_back ( ViewState { std : : move ( new_view ) , { } } ) ;
2016-01-31 03:34:24 -05:00
2023-05-18 16:16:05 -04:00
update_view ( ) ;
2016-01-31 03:34:24 -05:00
2023-05-18 16:16:05 -04:00
return p ;
2015-07-08 11:39:24 -04:00
}
void NavigationView : : pop ( ) {
2023-06-01 18:45:55 -04:00
pop ( true ) ;
2015-07-08 11:39:24 -04:00
}
2016-12-06 07:31:38 -05:00
void NavigationView : : pop_modal ( ) {
2023-06-01 18:45:55 -04:00
// Pop modal view + underlying app view.
// TODO: this shouldn't be necessary.
pop ( false ) ;
pop ( true ) ;
2016-12-06 07:31:38 -05:00
}
2016-05-17 13:15:34 -04:00
void NavigationView : : display_modal (
2023-05-18 16:16:05 -04:00
const std : : string & title ,
const std : : string & message ) {
display_modal ( title , message , INFO , nullptr ) ;
2016-12-06 07:31:38 -05:00
}
void NavigationView : : display_modal (
2023-05-18 16:16:05 -04:00
const std : : string & title ,
const std : : string & message ,
const modal_t type ,
const std : : function < void ( bool ) > on_choice ) {
/* If a modal view is already visible, don't display another */
if ( ! modal_view ) {
modal_view = push < ModalMessageView > ( title , message , type , on_choice ) ;
}
2016-05-17 12:33:16 -04:00
}
2023-06-01 18:45:55 -04:00
void NavigationView : : pop ( bool update ) {
if ( view ( ) = = modal_view ) {
modal_view = nullptr ;
}
// Can't pop last item from stack.
if ( view_stack . size ( ) > 1 ) {
auto on_pop = view_stack . back ( ) . on_pop ;
free_view ( ) ;
view_stack . pop_back ( ) ;
if ( update )
update_view ( ) ;
if ( on_pop ) on_pop ( ) ;
}
}
2016-01-31 03:34:24 -05:00
void NavigationView : : free_view ( ) {
2023-05-18 16:16:05 -04:00
remove_child ( view ( ) ) ;
2015-07-08 11:39:24 -04:00
}
2016-01-31 03:34:24 -05:00
void NavigationView : : update_view ( ) {
2023-06-01 18:45:55 -04:00
const auto new_view = view_stack . back ( ) . view . get ( ) ;
2023-05-18 16:16:05 -04:00
add_child ( new_view ) ;
new_view - > set_parent_rect ( { { 0 , 0 } , size ( ) } ) ;
2015-07-08 11:39:24 -04:00
2023-05-18 16:16:05 -04:00
focus ( ) ;
set_dirty ( ) ;
if ( on_view_changed ) {
on_view_changed ( * new_view ) ;
}
2016-01-31 03:34:24 -05:00
}
2015-07-08 11:39:24 -04:00
2016-01-31 03:34:24 -05:00
Widget * NavigationView : : view ( ) const {
2023-05-18 16:16:05 -04:00
return children_ . empty ( ) ? nullptr : children_ [ 0 ] ;
2015-07-08 11:39:24 -04:00
}
void NavigationView : : focus ( ) {
2023-05-18 16:16:05 -04:00
if ( view ( ) ) {
view ( ) - > focus ( ) ;
}
2015-07-08 11:39:24 -04:00
}
2023-06-01 18:45:55 -04:00
bool NavigationView : : set_on_pop ( std : : function < void ( ) > on_pop ) {
if ( view_stack . size ( ) < = 1 )
return false ;
auto & top = view_stack . back ( ) ;
if ( top . on_pop )
return false ;
top . on_pop = on_pop ;
return true ;
}
2017-05-25 16:36:30 -04:00
/* ReceiversMenuView *****************************************************/
2016-01-31 03:34:24 -05:00
2017-05-25 16:36:30 -04:00
ReceiversMenuView : : ReceiversMenuView ( NavigationView & nav ) {
2023-06-23 19:13:39 -04:00
if ( pmem : : show_gui_return_icon ( ) ) {
add_items ( { { " .. " , Color : : light_grey ( ) , & bitmap_icon_previous , [ & nav ] ( ) { nav . pop ( ) ; } } } ) ;
2023-05-18 16:16:05 -04:00
}
add_items ( {
2023-07-22 13:06:55 -04:00
{ " ADS-B " , Color : : green ( ) , & bitmap_icon_adsb , [ & nav ] ( ) { nav . push < ADSBRxView > ( ) ; } } ,
//{ "ACARS", Color::yellow(), &bitmap_icon_adsb, [&nav](){ nav.push<ACARSAppView>(); }},
2023-06-23 19:13:39 -04:00
{ " AIS Boats " , Color : : green ( ) , & bitmap_icon_ais , [ & nav ] ( ) { nav . push < AISAppView > ( ) ; } } ,
{ " AFSK " , Color : : yellow ( ) , & bitmap_icon_modem , [ & nav ] ( ) { nav . push < AFSKRxView > ( ) ; } } ,
{ " BTLE " , Color : : yellow ( ) , & bitmap_icon_btle , [ & nav ] ( ) { nav . push < BTLERxView > ( ) ; } } ,
{ " NRF " , Color : : yellow ( ) , & bitmap_icon_nrf , [ & nav ] ( ) { nav . push < NRFRxView > ( ) ; } } ,
{ " Audio " , Color : : green ( ) , & bitmap_icon_speaker , [ & nav ] ( ) { nav . push < AnalogAudioView > ( ) ; } } ,
{ " Analog TV " , Color : : yellow ( ) , & bitmap_icon_sstv , [ & nav ] ( ) { nav . push < AnalogTvView > ( ) ; } } ,
{ " ERT Meter " , Color : : green ( ) , & bitmap_icon_ert , [ & nav ] ( ) { nav . push < ERTAppView > ( ) ; } } ,
{ " POCSAG " , Color : : green ( ) , & bitmap_icon_pocsag , [ & nav ] ( ) { nav . push < POCSAGAppView > ( ) ; } } ,
{ " Radiosnde " , Color : : green ( ) , & bitmap_icon_sonde , [ & nav ] ( ) { nav . push < SondeView > ( ) ; } } ,
{ " TPMS Cars " , Color : : green ( ) , & bitmap_icon_tpms , [ & nav ] ( ) { nav . push < TPMSAppView > ( ) ; } } ,
{ " Recon " , Color : : green ( ) , & bitmap_icon_scanner , [ & nav ] ( ) { nav . push < ReconView > ( ) ; } } ,
{ " Level " , Color : : green ( ) , & bitmap_icon_options_radio , [ & nav ] ( ) { nav . push < LevelView > ( ) ; } } ,
{ " APRS " , Color : : green ( ) , & bitmap_icon_aprs , [ & nav ] ( ) { nav . push < APRSRXView > ( ) ; } }
2023-05-18 16:16:05 -04:00
/*
2023-06-23 19:13:39 -04:00
{ " DMR " , Color : : dark_grey ( ) , & bitmap_icon_dmr , [ & nav ] ( ) { nav . push < NotImplementedView > ( ) ; } } ,
{ " SIGFOX " , Color : : dark_grey ( ) , & bitmap_icon_fox , [ & nav ] ( ) { nav . push < NotImplementedView > ( ) ; } } , // SIGFRXView
{ " LoRa " , Color : : dark_grey ( ) , & bitmap_icon_lora , [ & nav ] ( ) { nav . push < NotImplementedView > ( ) ; } } ,
{ " SSTV " , Color : : dark_grey ( ) , & bitmap_icon_sstv , [ & nav ] ( ) { nav . push < NotImplementedView > ( ) ; } } ,
{ " TETRA " , Color : : dark_grey ( ) , & bitmap_icon_tetra , [ & nav ] ( ) { nav . push < NotImplementedView > ( ) ; } } , */
2023-05-18 16:16:05 -04:00
} ) ;
// set_highlighted(0); // Default selection is "Audio"
2016-11-30 01:41:55 -05:00
}
2017-05-25 16:36:30 -04:00
/* TransmittersMenuView **************************************************/
TransmittersMenuView : : TransmittersMenuView ( NavigationView & nav ) {
2023-06-23 19:13:39 -04:00
if ( pmem : : show_gui_return_icon ( ) ) {
add_items ( { { " .. " , Color : : light_grey ( ) , & bitmap_icon_previous , [ & nav ] ( ) { nav . pop ( ) ; } } } ) ;
2023-05-18 16:16:05 -04:00
}
add_items ( {
2023-06-25 13:48:51 -04:00
{ " ADS-B [S] " , ui : : Color : : green ( ) , & bitmap_icon_adsb , [ & nav ] ( ) { nav . push < ADSBTxView > ( ) ; } } ,
2023-05-18 16:16:05 -04:00
{ " APRS " , ui : : Color : : green ( ) , & bitmap_icon_aprs , [ & nav ] ( ) { nav . push < APRSTXView > ( ) ; } } ,
{ " BHT Xy/EP " , ui : : Color : : green ( ) , & bitmap_icon_bht , [ & nav ] ( ) { nav . push < BHTView > ( ) ; } } ,
2023-06-25 13:48:51 -04:00
{ " GPS Sim " , ui : : Color : : green ( ) , & bitmap_icon_gps_sim , [ & nav ] ( ) { nav . push < GpsSimAppView > ( ) ; } } ,
2023-05-18 16:16:05 -04:00
{ " Jammer " , ui : : Color : : green ( ) , & bitmap_icon_jammer , [ & nav ] ( ) { nav . push < JammerView > ( ) ; } } ,
//{ "Key fob", ui::Color::orange(), &bitmap_icon_keyfob, [&nav](){ nav.push<KeyfobView>(); } },
{ " LGE tool " , ui : : Color : : yellow ( ) , & bitmap_icon_lge , [ & nav ] ( ) { nav . push < LGEView > ( ) ; } } ,
{ " Morse " , ui : : Color : : green ( ) , & bitmap_icon_morse , [ & nav ] ( ) { nav . push < MorseView > ( ) ; } } ,
{ " BurgerPgr " , ui : : Color : : yellow ( ) , & bitmap_icon_burger , [ & nav ] ( ) { nav . push < CoasterPagerView > ( ) ; } } ,
//{ "Nuoptix DTMF", ui::Color::green(), &bitmap_icon_nuoptix, [&nav](){ nav.push<NuoptixView>(); } },
{ " OOK " , ui : : Color : : yellow ( ) , & bitmap_icon_remote , [ & nav ] ( ) { nav . push < EncodersView > ( ) ; } } ,
{ " POCSAG " , ui : : Color : : green ( ) , & bitmap_icon_pocsag , [ & nav ] ( ) { nav . push < POCSAGTXView > ( ) ; } } ,
{ " RDS " , ui : : Color : : green ( ) , & bitmap_icon_rds , [ & nav ] ( ) { nav . push < RDSView > ( ) ; } } ,
{ " Soundbrd " , ui : : Color : : green ( ) , & bitmap_icon_soundboard , [ & nav ] ( ) { nav . push < SoundBoardView > ( ) ; } } ,
{ " SSTV " , ui : : Color : : green ( ) , & bitmap_icon_sstv , [ & nav ] ( ) { nav . push < SSTVTXView > ( ) ; } } ,
{ " TEDI/LCR " , ui : : Color : : yellow ( ) , & bitmap_icon_lcr , [ & nav ] ( ) { nav . push < LCRView > ( ) ; } } ,
2023-06-25 13:48:51 -04:00
{ " TouchTune " , ui : : Color : : green ( ) , & bitmap_icon_touchtunes , [ & nav ] ( ) { nav . push < TouchTunesView > ( ) ; } } ,
2023-06-28 13:02:06 -04:00
//{"Playlist", ui::Color::green(), &bitmap_icon_scanner, [&nav]() { nav.push<PlaylistView>(); }},
2023-06-23 10:57:35 -04:00
{ " S.Painter " , ui : : Color : : orange ( ) , & bitmap_icon_paint , [ & nav ] ( ) { nav . push < SpectrumPainterView > ( ) ; } } ,
2023-05-18 16:16:05 -04:00
//{ "Remote", ui::Color::dark_grey(), &bitmap_icon_remote, [&nav](){ nav.push<RemoteView>(); } },
} ) ;
2016-01-31 03:34:24 -05:00
}
2017-05-25 16:36:30 -04:00
/* UtilitiesMenuView *****************************************************/
2016-12-06 07:31:38 -05:00
2017-05-25 16:36:30 -04:00
UtilitiesMenuView : : UtilitiesMenuView ( NavigationView & nav ) {
2023-06-23 19:13:39 -04:00
if ( pmem : : show_gui_return_icon ( ) ) {
add_items ( { { " .. " , Color : : light_grey ( ) , & bitmap_icon_previous , [ & nav ] ( ) { nav . pop ( ) ; } } } ) ;
2023-05-18 16:16:05 -04:00
}
add_items ( {
2023-06-23 19:13:39 -04:00
//{ "Test app", Color::dark_grey(), nullptr, [&nav](){ nav.push<TestView>(); } },
{ " Freq. manager " , Color : : green ( ) , & bitmap_icon_freqman , [ & nav ] ( ) { nav . push < FrequencyManagerView > ( ) ; } } ,
2023-06-25 13:48:51 -04:00
{ " File manager " , Color : : green ( ) , & bitmap_icon_dir , [ & nav ] ( ) { nav . push < FileManagerView > ( ) ; } } ,
2023-06-23 19:13:39 -04:00
{ " Notepad " , Color : : dark_cyan ( ) , & bitmap_icon_notepad , [ & nav ] ( ) { nav . push < TextEditorView > ( ) ; } } ,
{ " Signal gen " , Color : : green ( ) , & bitmap_icon_cwgen , [ & nav ] ( ) { nav . push < SigGenView > ( ) ; } } ,
//{ "Tone search", Color::dark_grey(), nullptr, [&nav](){ nav.push<ToneSearchView>(); } },
{ " Wav viewer " , Color : : yellow ( ) , & bitmap_icon_soundboard , [ & nav ] ( ) { nav . push < ViewWavView > ( ) ; } } ,
{ " Antenna length " , Color : : green ( ) , & bitmap_icon_tools_antenna , [ & nav ] ( ) { nav . push < WhipCalcView > ( ) ; } } ,
{ " Wipe SD card " , Color : : red ( ) , & bitmap_icon_tools_wipesd , [ & nav ] ( ) { nav . push < WipeSDView > ( ) ; } } ,
{ " Flash Utility " , Color : : red ( ) , & bitmap_icon_temperature , [ & nav ] ( ) { nav . push < FlashUtilityView > ( ) ; } } ,
2023-06-29 16:13:33 -04:00
{ " SD over USB " , Color : : yellow ( ) , & bitmap_icon_hackrf , [ & nav ] ( ) { nav . push < SdOverUsbView > ( ) ; } } ,
2023-05-18 16:16:05 -04:00
} ) ;
set_max_rows ( 2 ) ; // allow wider buttons
2016-12-06 07:31:38 -05:00
}
2017-05-25 16:36:30 -04:00
2015-07-08 11:39:24 -04:00
/* SystemMenuView ********************************************************/
2016-12-25 19:31:38 -05:00
void SystemMenuView : : hackrf_mode ( NavigationView & nav ) {
2023-05-18 16:16:05 -04:00
nav . push < ModalMessageView > ( " HackRF mode " , " This mode enables HackRF \n functionality. To return, \n press the reset button. \n \n Switch to HackRF mode? " , YESNO ,
[ this ] ( bool choice ) {
if ( choice ) {
EventDispatcher : : request_stop ( ) ;
}
} ) ;
2016-12-25 19:31:38 -05:00
}
2015-07-08 11:39:24 -04:00
SystemMenuView : : SystemMenuView ( NavigationView & nav ) {
2023-05-18 16:16:05 -04:00
add_items ( {
2023-06-23 19:13:39 -04:00
//{ "Play dead", Color::red(), &bitmap_icon_playdead, [&nav](){ nav.push<PlayDeadView>(); } },
{ " Receive " , Color : : cyan ( ) , & bitmap_icon_receivers , [ & nav ] ( ) { nav . push < ReceiversMenuView > ( ) ; } } ,
{ " Transmit " , Color : : cyan ( ) , & bitmap_icon_transmit , [ & nav ] ( ) { nav . push < TransmittersMenuView > ( ) ; } } ,
{ " Capture " , Color : : red ( ) , & bitmap_icon_capture , [ & nav ] ( ) { nav . push < CaptureAppView > ( ) ; } } ,
2023-06-28 13:02:06 -04:00
{ " Replay " , Color : : green ( ) , & bitmap_icon_replay , [ & nav ] ( ) { nav . push < PlaylistView > ( ) ; } } ,
2023-06-23 19:13:39 -04:00
{ " Search " , Color : : yellow ( ) , & bitmap_icon_search , [ & nav ] ( ) { nav . push < SearchView > ( ) ; } } ,
2023-06-25 13:48:51 -04:00
{ " Scanner " , Color : : green ( ) , & bitmap_icon_scanner , [ & nav ] ( ) { nav . push < ScannerView > ( ) ; } } ,
{ " Microphone " , Color : : green ( ) , & bitmap_icon_microphone , [ & nav ] ( ) { nav . push < MicTXView > ( ) ; } } ,
{ " Looking Glass " , Color : : green ( ) , & bitmap_icon_looking , [ & nav ] ( ) { nav . push < GlassView > ( ) ; } } ,
2023-06-23 19:13:39 -04:00
{ " Utilities " , Color : : cyan ( ) , & bitmap_icon_utilities , [ & nav ] ( ) { nav . push < UtilitiesMenuView > ( ) ; } } ,
{ " Settings " , Color : : cyan ( ) , & bitmap_icon_setup , [ & nav ] ( ) { nav . push < SettingsMenuView > ( ) ; } } ,
{ " Debug " , Color : : light_grey ( ) , & bitmap_icon_debug , [ & nav ] ( ) { nav . push < DebugMenuView > ( ) ; } } ,
{ " HackRF " , Color : : cyan ( ) , & bitmap_icon_hackrf , [ this , & nav ] ( ) { hackrf_mode ( nav ) ; } } ,
//{ "About", Color::cyan(), nullptr, [&nav](){ nav.push<AboutView>(); } }
2023-05-18 16:16:05 -04:00
} ) ;
set_max_rows ( 2 ) ; // allow wider buttons
set_arrow_enabled ( false ) ;
// set_highlighted(1); // Startup selection
2015-07-08 11:39:24 -04:00
}
/* SystemView ************************************************************/
SystemView : : SystemView (
2023-05-18 16:16:05 -04:00
Context & context ,
const Rect parent_rect )
: View { parent_rect } ,
context_ ( context ) {
2023-06-23 19:13:39 -04:00
set_style ( & Styles : : white ) ;
2023-05-18 16:16:05 -04:00
2023-06-23 19:13:39 -04:00
constexpr Dim status_view_height = 16 ;
constexpr Dim info_view_height = 16 ;
2023-05-18 16:16:05 -04:00
add_child ( & status_view ) ;
status_view . set_parent_rect ( { { 0 , 0 } ,
{ parent_rect . width ( ) , status_view_height } } ) ;
status_view . on_back = [ this ] ( ) {
this - > navigation_view . pop ( ) ;
} ;
add_child ( & navigation_view ) ;
navigation_view . set_parent_rect ( { { 0 , status_view_height } ,
2023-06-23 19:13:39 -04:00
{ parent_rect . width ( ) , static_cast < Dim > ( parent_rect . height ( ) - status_view_height ) } } ) ;
2023-05-18 16:16:05 -04:00
add_child ( & info_view ) ;
info_view . set_parent_rect ( { { 0 , 19 * 16 } ,
{ parent_rect . width ( ) , info_view_height } } ) ;
navigation_view . on_view_changed = [ this ] ( const View & new_view ) {
if ( ! this - > navigation_view . is_top ( ) ) {
remove_child ( & info_view ) ;
} else {
add_child ( & info_view ) ;
info_view . refresh ( ) ;
}
this - > status_view . set_back_enabled ( ! this - > navigation_view . is_top ( ) ) ;
this - > status_view . set_title_image_enabled ( this - > navigation_view . is_top ( ) ) ;
this - > status_view . set_title ( new_view . title ( ) ) ;
this - > status_view . set_dirty ( ) ;
} ;
2023-06-23 19:13:39 -04:00
// pmem::set_playdead_sequence(0x8D1);
2023-05-18 16:16:05 -04:00
// Initial view
2023-06-23 19:13:39 -04:00
/*if ((pmem::playing_dead() == 0x5920C1DF) || // Enable code
( pmem : : ui_config ( ) & 16 ) ) { // Login option
2023-05-18 16:16:05 -04:00
navigation_view . push < PlayDeadView > ( ) ;
} else { */
navigation_view . push < SystemMenuView > ( ) ;
2023-06-23 19:13:39 -04:00
if ( pmem : : config_splash ( ) ) {
2023-05-18 16:16:05 -04:00
navigation_view . push < BMPView > ( ) ;
}
status_view . set_back_enabled ( false ) ;
status_view . set_title_image_enabled ( true ) ;
status_view . set_dirty ( ) ;
// else
// navigation_view.push<SystemMenuView>();
//}
2015-07-08 11:39:24 -04:00
}
Context & SystemView : : context ( ) const {
2023-05-18 16:16:05 -04:00
return context_ ;
2015-07-08 11:39:24 -04:00
}
2023-04-23 10:21:33 -04:00
void SystemView : : toggle_overlay ( ) {
2023-06-28 13:04:16 -04:00
switch ( + + overlay_active ) {
case 1 :
this - > add_child ( & this - > overlay ) ;
this - > set_dirty ( ) ;
shared_memory . request_m4_performance_counter = 1 ;
shared_memory . m4_cpu_usage = 0 ;
shared_memory . m4_heap_usage = 0 ;
shared_memory . m4_stack_usage = 0 ;
break ;
case 2 :
this - > remove_child ( & this - > overlay ) ;
this - > add_child ( & this - > overlay2 ) ;
this - > set_dirty ( ) ;
shared_memory . request_m4_performance_counter = 0 ;
break ;
case 3 :
this - > remove_child ( & this - > overlay2 ) ;
this - > set_dirty ( ) ;
overlay_active = 0 ;
break ;
2023-05-18 16:16:05 -04:00
}
2023-04-23 10:21:33 -04:00
}
void SystemView : : paint_overlay ( ) {
2023-05-18 16:16:05 -04:00
static bool last_paint_state = false ;
if ( overlay_active ) {
// paint background only every other second
if ( ( ( ( chTimeNow ( ) > > 10 ) & 0x01 ) = = 0x01 ) = = last_paint_state )
return ;
2023-04-23 13:52:38 -04:00
2023-05-18 16:16:05 -04:00
last_paint_state = ! last_paint_state ;
2023-06-28 13:04:16 -04:00
if ( overlay_active = = 1 )
this - > overlay . set_dirty ( ) ;
else
this - > overlay2 . set_dirty ( ) ;
2023-05-18 16:16:05 -04:00
}
2023-04-23 10:21:33 -04:00
}
2016-02-05 11:40:14 -05:00
/* ***********************************************************************/
void BMPView : : focus ( ) {
2023-05-18 16:16:05 -04:00
button_done . focus ( ) ;
2016-02-05 11:40:14 -05:00
}
BMPView : : BMPView ( NavigationView & nav ) {
2023-05-18 16:16:05 -04:00
add_children ( { & button_done } ) ;
button_done . on_select = [ this , & nav ] ( Button & ) {
nav . pop ( ) ;
} ;
2016-02-05 11:40:14 -05:00
}
2016-12-09 12:21:47 -05:00
void BMPView : : paint ( Painter & ) {
2023-07-05 16:45:43 -04:00
if ( ! portapack : : display . drawBMP2 ( { 0 , 0 } , splash_dot_bmp ) )
2023-05-18 16:16:05 -04:00
portapack : : display . drawBMP ( { ( 240 - 230 ) / 2 , ( 320 - 50 ) / 2 - 10 } , splash_bmp , false ) ;
2016-02-05 11:40:14 -05:00
}
2015-07-08 11:39:24 -04:00
/* NotImplementedView ****************************************************/
2020-05-11 05:07:45 -04:00
/*NotImplementedView::NotImplementedView(NavigationView& nav) {
2023-05-18 16:16:05 -04:00
button_done . on_select = [ & nav ] ( Button & ) {
nav . pop ( ) ;
} ;
2015-07-08 11:39:24 -04:00
2023-05-18 16:16:05 -04:00
add_children ( {
& text_title ,
& button_done ,
} ) ;
2015-07-08 11:39:24 -04:00
}
void NotImplementedView : : focus ( ) {
2023-05-18 16:16:05 -04:00
button_done . focus ( ) ;
2020-05-11 05:07:45 -04:00
} */
2015-07-08 11:39:24 -04:00
2016-05-13 00:58:54 -04:00
/* ModalMessageView ******************************************************/
2016-12-09 12:21:47 -05:00
2016-05-17 13:15:34 -04:00
ModalMessageView : : ModalMessageView (
2023-05-18 16:16:05 -04:00
NavigationView & nav ,
const std : : string & title ,
const std : : string & message ,
const modal_t type ,
const std : : function < void ( bool ) > on_choice )
: title_ { title } ,
message_ { message } ,
type_ { type } ,
on_choice_ { on_choice } {
if ( type = = INFO ) {
add_child ( & button_ok ) ;
2023-05-19 16:39:35 -04:00
button_ok . on_select = [ this , & nav ] ( Button & ) {
if ( on_choice_ )
on_choice_ ( true ) ; // Assumes handler will pop.
else
nav . pop ( ) ;
2023-05-18 16:16:05 -04:00
} ;
} else if ( type = = YESNO ) {
add_children ( { & button_yes ,
& button_no } ) ;
button_yes . on_select = [ this , & nav ] ( Button & ) {
if ( on_choice_ ) on_choice_ ( true ) ;
nav . pop ( ) ;
} ;
button_no . on_select = [ this , & nav ] ( Button & ) {
if ( on_choice_ ) on_choice_ ( false ) ;
nav . pop ( ) ;
} ;
} else if ( type = = YESCANCEL ) {
add_children ( { & button_yes ,
& button_no } ) ;
button_yes . on_select = [ this , & nav ] ( Button & ) {
if ( on_choice_ ) on_choice_ ( true ) ;
nav . pop ( ) ;
} ;
button_no . on_select = [ this , & nav ] ( Button & ) {
// if (on_choice_) on_choice_(false);
nav . pop_modal ( ) ;
} ;
} else { // ABORT
add_child ( & button_ok ) ;
button_ok . on_select = [ this , & nav ] ( Button & ) {
if ( on_choice_ ) on_choice_ ( true ) ;
nav . pop_modal ( ) ;
} ;
}
2016-05-13 00:58:54 -04:00
}
2017-02-07 14:54:18 -05:00
void ModalMessageView : : paint ( Painter & painter ) {
2023-05-18 16:16:05 -04:00
size_t pos , i = 0 , start = 0 ;
portapack : : display . drawBMP ( { 100 , 48 } , modal_warning_bmp , false ) ;
// Terrible...
while ( ( pos = message_ . find ( " \n " , start ) ) ! = std : : string : : npos ) {
painter . draw_string (
{ 1 * 8 , ( Coord ) ( 120 + ( i * 16 ) ) } ,
style ( ) ,
message_ . substr ( start , pos - start ) ) ;
i + + ;
start = pos + 1 ;
}
painter . draw_string (
{ 1 * 8 , ( Coord ) ( 120 + ( i * 16 ) ) } ,
style ( ) ,
message_ . substr ( start , pos ) ) ;
2016-08-23 02:45:33 -04:00
}
2016-05-13 00:58:54 -04:00
void ModalMessageView : : focus ( ) {
2023-05-18 16:16:05 -04:00
if ( ( type_ = = YESNO ) | | ( type_ = = YESCANCEL ) ) {
button_yes . focus ( ) ;
} else {
button_ok . focus ( ) ;
}
2016-05-13 00:58:54 -04:00
}
2015-07-08 11:39:24 -04:00
} /* namespace ui */