use std::fmt::Debug;
use r3bl_rs_utils_core::*;
use crate::*;
#[derive(Debug)]
pub enum DialogEngineApplyResponse {
UpdateEditorBuffer(EditorBuffer),
DialogChoice(DialogChoice),
SelectScrollResultsPanel,
Noop,
}
pub struct DialogEngineApi;
impl DialogEngineApi {
pub async fn render_engine<S, A>(
args: DialogEngineArgs<'_, S, A>,
) -> CommonResult<RenderPipeline>
where
S: HasDialogBuffers + Default + Clone + PartialEq + Debug + Sync + Send,
A: Debug + Default + Clone + Sync + Send,
{
let mode = args.dialog_engine.dialog_options.mode;
let overlay_flex_box: PartialFlexBox = {
match &args.dialog_engine.maybe_flex_box {
Some((saved_size, saved_mode, saved_box))
if saved_size == args.window_size && saved_mode == &mode =>
{
*saved_box
}
_ => {
let it = internal_impl::make_flex_box_for_dialog(
&args.self_id,
&args.dialog_engine.dialog_options,
args.window_size,
args.dialog_engine.maybe_surface_bounds,
)?;
args.dialog_engine.maybe_flex_box.replace((
*args.window_size,
mode,
it,
));
it
}
}
};
let (origin_pos, bounds_size) =
overlay_flex_box.get_style_adjusted_position_and_size();
let pipeline = {
let mut it = render_pipeline!();
it.push(
ZOrder::Glass,
internal_impl::render_border(
&origin_pos,
&bounds_size,
args.dialog_engine,
),
);
it.push(
ZOrder::Glass,
internal_impl::render_title(
&origin_pos,
&bounds_size,
&args.dialog_buffer.title,
args.dialog_engine,
),
);
if matches!(
args.dialog_engine.dialog_options.mode,
DialogEngineMode::ModalAutocomplete
) {
let results_panel_ops = internal_impl::render_results_panel(
&origin_pos,
&bounds_size,
args.dialog_engine,
args.self_id,
args.state,
)?;
if !results_panel_ops.is_empty() {
it.push(ZOrder::Glass, results_panel_ops);
}
}
it += internal_impl::render_editor(&origin_pos, &bounds_size, args).await?;
it
};
Ok(pipeline)
}
pub async fn apply_event<S, A>(
args: DialogEngineArgs<'_, S, A>,
input_event: &InputEvent,
) -> CommonResult<DialogEngineApplyResponse>
where
S: HasDialogBuffers + Default + Clone + PartialEq + Debug + Sync + Send,
A: Debug + Default + Clone + Sync + Send,
{
let DialogEngineArgs {
self_id,
component_registry,
shared_store,
shared_global_data,
state,
dialog_buffer,
dialog_engine,
..
} = args;
if let Some(choice) = internal_impl::try_handle_dialog_choice(
input_event,
dialog_buffer,
dialog_engine,
) {
dialog_engine.reset();
return Ok(DialogEngineApplyResponse::DialogChoice(choice));
}
if let EventPropagation::ConsumedRender =
internal_impl::try_handle_up_down(input_event, dialog_buffer, dialog_engine)
{
return Ok(DialogEngineApplyResponse::SelectScrollResultsPanel);
}
let editor_engine_args = EditorEngineArgs {
component_registry,
shared_global_data,
self_id,
editor_buffer: &dialog_buffer.editor_buffer,
editor_engine: &mut dialog_engine.editor_engine,
shared_store,
state,
};
if let EditorEngineApplyEventResult::Applied(new_editor_buffer) =
EditorEngineApi::apply_event(editor_engine_args, input_event).await?
{
return Ok(DialogEngineApplyResponse::UpdateEditorBuffer(
new_editor_buffer,
));
}
Ok(DialogEngineApplyResponse::Noop)
}
}
#[repr(u16)]
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum DisplayConstants {
DialogComponentBorderWidthPercent = 90,
SimpleModalRowCount = 4,
EmptyLine = 1,
DefaultResultsPanelRowCount = 5,
}
mod internal_impl {
use super::*;
pub fn make_flex_box_for_dialog(
dialog_id: &FlexBoxId,
dialog_options: &DialogEngineConfigOptions,
window_size: &Size,
maybe_surface_bounds: Option<SurfaceBounds>,
) -> CommonResult<PartialFlexBox> {
let surface_size = if let Some(surface_bounds) = maybe_surface_bounds {
surface_bounds.box_size
} else {
*window_size
};
let surface_origin_pos = if let Some(surface_bounds) = maybe_surface_bounds {
surface_bounds.origin_pos
} else {
position!(col_index: 0, row_index: 0)
};
if window_size.col_count < ch!(MinSize::Col as u8)
|| window_size.row_count < ch!(MinSize::Row as u8)
{
return CommonError::new(
CommonErrorType::DisplaySizeTooSmall,
&format!(
"Window size is too small. Min size is {} cols x {} rows",
MinSize::Col as u8,
MinSize::Row as u8
),
);
}
let (origin_pos, bounds_size) = match dialog_options.mode {
DialogEngineMode::ModalSimple => {
let simple_dialog_size = {
let col_count = {
let percent = percent!(
DisplayConstants::DialogComponentBorderWidthPercent as u16
)?;
percent.calc_percentage(surface_size.col_count)
};
let row_count = ch!(DisplayConstants::SimpleModalRowCount as u16);
let size = size! { col_count: col_count, row_count: row_count };
assert!(size.row_count < ch!(MinSize::Row as u8));
size
};
let origin_pos = {
let origin_col =
surface_size.col_count / 2 - simple_dialog_size.col_count / 2;
let origin_row =
surface_size.row_count / 2 - simple_dialog_size.row_count / 2;
let mut it = position!(col_index: origin_col, row_index: origin_row);
it += surface_origin_pos;
it
};
(origin_pos, simple_dialog_size)
}
DialogEngineMode::ModalAutocomplete => {
let autocomplete_dialog_size = {
let row_count = ch!(DisplayConstants::SimpleModalRowCount as u16)
+ ch!(DisplayConstants::EmptyLine as u16)
+ dialog_options.result_panel_display_row_count;
let col_count = {
let percent = percent!(
DisplayConstants::DialogComponentBorderWidthPercent as u16
)?;
percent.calc_percentage(surface_size.col_count)
};
let size = size!(col_count: col_count, row_count: row_count);
assert!(size.row_count < ch!(MinSize::Row as u8));
size
};
let origin_pos = {
let origin_col = surface_size.col_count / 2
- autocomplete_dialog_size.col_count / 2;
let origin_row = surface_size.row_count / 2
- autocomplete_dialog_size.row_count / 2;
let mut it = position!(col_index: origin_col, row_index: origin_row);
it += surface_origin_pos;
it
};
(origin_pos, autocomplete_dialog_size)
}
};
throws_with_return!({
PartialFlexBox {
id: *dialog_id,
style_adjusted_origin_pos: origin_pos,
style_adjusted_bounds_size: bounds_size,
maybe_computed_style: None,
}
})
}
pub async fn render_editor<S, A>(
origin_pos: &Position,
bounds_size: &Size,
args: DialogEngineArgs<'_, S, A>,
) -> CommonResult<RenderPipeline>
where
S: Debug + Default + Clone + PartialEq + Sync + Send,
A: Debug + Default + Clone + Sync + Send,
{
let maybe_style = args.dialog_engine.dialog_options.maybe_style_editor;
let flex_box: FlexBox = PartialFlexBox {
id: args.self_id,
style_adjusted_origin_pos: position! {col_index: origin_pos.col_index + 1, row_index: origin_pos.row_index + 2},
style_adjusted_bounds_size: size! {col_count: bounds_size.col_count - 2, row_count: 1},
maybe_computed_style: maybe_style,
}
.into();
let editor_engine_args = EditorEngineArgs {
component_registry: args.component_registry,
shared_global_data: args.shared_global_data,
self_id: args.self_id,
editor_buffer: &args.dialog_buffer.editor_buffer,
editor_engine: &mut args.dialog_engine.editor_engine,
shared_store: args.shared_store,
state: args.state,
};
let mut pipeline =
EditorEngineApi::render_engine(editor_engine_args, &flex_box).await?;
pipeline.hoist(ZOrder::Normal, ZOrder::Glass);
if args.dialog_buffer.editor_buffer.is_empty()
|| args.dialog_buffer.editor_buffer.get_as_string() == ""
{
let mut ops = render_ops!();
let msg = "Press <Esc> to close, or <Enter> to accept".to_string();
ops.push(RenderOp::ResetColor);
ops.push(RenderOp::MoveCursorPositionAbs(
flex_box.style_adjusted_origin_pos,
));
ops.push(RenderOp::PaintTextWithAttributes(
msg,
Some(if let Some(style) = maybe_style {
Style { dim: true, ..style }
} else {
Style {
dim: true,
..Default::default()
}
}),
));
pipeline.push(ZOrder::Glass, ops);
};
Ok(pipeline)
}
pub fn render_results_panel<S>(
origin_pos: &Position,
bounds_size: &Size,
dialog_engine: &DialogEngine,
self_id: FlexBoxId,
state: &S,
) -> CommonResult<RenderOps>
where
S: HasDialogBuffers + Default + Clone + PartialEq + Debug + Sync + Send,
{
let mut it = render_ops!();
if let Some(dialog_buffer) = state.get_dialog_buffer(self_id) {
if let Some(results) = dialog_buffer.maybe_results.as_ref() {
if !results.is_empty() {
paint_results(
&mut it,
origin_pos,
bounds_size,
results,
dialog_engine,
);
};
}
};
return Ok(it);
pub fn paint_results(
ops: &mut RenderOps,
origin_pos: &Position,
bounds_size: &Size,
results: &[String],
dialog_engine: &DialogEngine,
) {
let col_start_index = ch!(1);
let row_start_index =
ch!(DisplayConstants::SimpleModalRowCount as u16) - ch!(1);
let mut rel_insertion_pos =
position!(col_index: col_start_index, row_index: row_start_index);
let scroll_offset_row_index = dialog_engine.scroll_offset_row_index;
let selected_row_index = dialog_engine.selected_row_index;
for (row_index, item) in results.iter().enumerate() {
let row_index = ch!(row_index);
if row_index < scroll_offset_row_index {
continue;
}
rel_insertion_pos.add_row(1);
let text = UnicodeString::from(item.as_str());
let max_display_col_count = bounds_size.col_count - 2;
let clipped_text = if text.display_width > max_display_col_count {
let snip_len = ch!(2);
let postfix_len = ch!(5);
let lhs_start_index = ch!(0);
let lhs_end_index = max_display_col_count - postfix_len - snip_len;
let lhs = text.clip_to_width(lhs_start_index, lhs_end_index);
let rhs_start_index = text.display_width - postfix_len;
let rhs_end_index = text.display_width;
let rhs = text.clip_to_width(rhs_start_index, rhs_end_index);
format!("{lhs}..{rhs}")
} else {
text.string
};
let max_display_row_count =
dialog_engine.dialog_options.result_panel_display_row_count +
scroll_offset_row_index;
if row_index >= max_display_row_count {
break;
}
ops.push(RenderOp::ResetColor);
ops.push(RenderOp::MoveCursorPositionRelTo(
*origin_pos,
rel_insertion_pos,
));
match selected_row_index.eq(&row_index) {
true => {
let my_selected_style = match dialog_engine
.dialog_options
.maybe_style_results_panel
{
Some(style) => Style {
underline: true,
..style
},
_ => Style {
underline: true,
..Default::default()
},
}
.into();
ops.push(RenderOp::ApplyColors(my_selected_style));
ops.push(RenderOp::PaintTextWithAttributes(
clipped_text,
my_selected_style,
));
}
false => {
ops.push(RenderOp::ApplyColors(
dialog_engine.dialog_options.maybe_style_results_panel,
));
ops.push(RenderOp::PaintTextWithAttributes(
clipped_text,
dialog_engine.dialog_options.maybe_style_results_panel,
));
}
}
}
}
}
pub fn render_title(
origin_pos: &Position,
bounds_size: &Size,
title: &str,
dialog_engine: &mut DialogEngine,
) -> RenderOps {
let mut ops = render_ops!();
let row_pos = position!(col_index: origin_pos.col_index + 1, row_index: origin_pos.row_index + 1);
let title_us = UnicodeString::from(title);
let text_content = title_us.truncate_to_fit_size(size! {
col_count: bounds_size.col_count - 2, row_count: bounds_size.row_count
});
ops.push(RenderOp::ResetColor);
ops.push(RenderOp::MoveCursorPositionAbs(row_pos));
ops.push(RenderOp::ApplyColors(
dialog_engine.dialog_options.maybe_style_title,
));
lolcat_from_style(
&mut ops,
&mut dialog_engine.color_wheel,
&dialog_engine.dialog_options.maybe_style_title,
text_content,
);
ops
}
fn lolcat_from_style(
ops: &mut RenderOps,
color_wheel: &mut ColorWheel,
maybe_style: &Option<Style>,
text: &str,
) {
if let Some(style) = maybe_style {
if style.lolcat {
color_wheel
.colorize_into_styled_texts(
&UnicodeString::from(text),
GradientGenerationPolicy::ReuseExistingGradientAndResetIndex,
TextColorizationPolicy::ColorEachCharacter(*maybe_style),
)
.render_into(ops);
return;
}
}
ops.push(RenderOp::PaintTextWithAttributes(text.into(), *maybe_style));
}
pub fn render_border(
origin_pos: &Position,
bounds_size: &Size,
dialog_engine: &mut DialogEngine,
) -> RenderOps {
let mut ops = render_ops!();
let inner_spaces = SPACER.repeat(ch!(@to_usize bounds_size.col_count - 2));
let maybe_style = dialog_engine.dialog_options.maybe_style_border;
for row_idx in 0..*bounds_size.row_count {
let row_pos = position!(col_index: origin_pos.col_index, row_index: origin_pos.row_index + row_idx);
let is_first_line = row_idx == 0;
let is_last_line = row_idx == (*bounds_size.row_count - 1);
ops.push(RenderOp::ResetColor);
ops.push(RenderOp::MoveCursorPositionAbs(row_pos));
ops.push(RenderOp::ApplyColors(maybe_style));
match (is_first_line, is_last_line) {
(true, false) => {
let text_content = format!(
"{}{}{}",
BorderGlyphCharacter::TopLeft.as_ref(),
BorderGlyphCharacter::Horizontal
.as_ref()
.repeat(ch!(@to_usize bounds_size.col_count - 2)),
BorderGlyphCharacter::TopRight.as_ref()
);
lolcat_from_style(
&mut ops,
&mut dialog_engine.color_wheel,
&maybe_style,
&text_content,
);
}
(false, false) => {
let text_content = format!(
"{}{}{}",
BorderGlyphCharacter::Vertical.as_ref(),
inner_spaces,
BorderGlyphCharacter::Vertical.as_ref()
);
lolcat_from_style(
&mut ops,
&mut dialog_engine.color_wheel,
&maybe_style,
&text_content,
);
}
(false, true) => {
let text_content = format!(
"{}{}{}",
BorderGlyphCharacter::BottomLeft.as_ref(),
BorderGlyphCharacter::Horizontal
.as_ref()
.repeat(ch!(@to_usize bounds_size.col_count - 2)),
BorderGlyphCharacter::BottomRight.as_ref(),
);
lolcat_from_style(
&mut ops,
&mut dialog_engine.color_wheel,
&maybe_style,
&text_content,
);
}
_ => {}
};
match dialog_engine.dialog_options.mode {
DialogEngineMode::ModalSimple => {}
DialogEngineMode::ModalAutocomplete => {
let inner_line = BorderGlyphCharacter::Horizontal
.as_ref()
.repeat(ch!(@to_usize bounds_size.col_count - 2))
.to_string();
let text_content = format!(
"{}{}{}",
BorderGlyphCharacter::LineUpDownRight.as_ref(),
inner_line,
BorderGlyphCharacter::LineUpDownLeft.as_ref()
);
let col_start_index = ch!(0);
let row_start_index =
ch!(DisplayConstants::SimpleModalRowCount as u16) - ch!(1);
let rel_insertion_pos =
position!(col_index: col_start_index, row_index: row_start_index);
ops.push(RenderOp::ResetColor);
ops.push(RenderOp::MoveCursorPositionRelTo(
*origin_pos,
rel_insertion_pos,
));
lolcat_from_style(
&mut ops,
&mut dialog_engine.color_wheel,
&maybe_style,
&text_content,
);
}
}
}
ops
}
pub fn try_handle_dialog_choice(
input_event: &InputEvent,
dialog_buffer: &DialogBuffer,
dialog_engine: &DialogEngine,
) -> Option<DialogChoice> {
match DialogEvent::from(input_event) {
DialogEvent::EnterPressed => match dialog_engine.dialog_options.mode {
DialogEngineMode::ModalSimple => {
let text = dialog_buffer.editor_buffer.get_as_string();
return Some(DialogChoice::Yes(text));
}
DialogEngineMode::ModalAutocomplete => {
let selected_index = ch!(@to_usize dialog_engine.selected_row_index);
if let Some(results) = &dialog_buffer.maybe_results {
if let Some(selected_result) = results.get(selected_index) {
return Some(DialogChoice::Yes(selected_result.clone()));
}
}
return Some(DialogChoice::No);
}
},
DialogEvent::EscPressed => {
return Some(DialogChoice::No);
}
_ => {}
}
None
}
pub fn try_handle_up_down(
input_event: &InputEvent,
dialog_buffer: &DialogBuffer,
dialog_engine: &mut DialogEngine,
) -> EventPropagation {
if input_event.matches(&[InputEvent::Keyboard(KeyPress::Plain {
key: Key::SpecialKey(SpecialKey::Up),
})]) {
if dialog_engine.selected_row_index > ch!(0) {
dialog_engine.selected_row_index -= 1;
}
if dialog_engine.selected_row_index < dialog_engine.scroll_offset_row_index {
dialog_engine.scroll_offset_row_index -= 1;
}
return EventPropagation::ConsumedRender;
}
if input_event.matches(&[InputEvent::Keyboard(KeyPress::Plain {
key: Key::SpecialKey(SpecialKey::Down),
})]) {
let max_abs_row_index = dialog_buffer.get_results_count() - ch!(1);
let results_panel_viewport_height_row_count =
dialog_engine.dialog_options.result_panel_display_row_count;
if dialog_engine.selected_row_index < max_abs_row_index {
dialog_engine.selected_row_index += 1;
}
if dialog_engine.selected_row_index
>= dialog_engine.scroll_offset_row_index
+ results_panel_viewport_height_row_count
{
dialog_engine.scroll_offset_row_index += 1;
}
return EventPropagation::ConsumedRender;
}
EventPropagation::Propagate
}
}
#[cfg(test)]
mod test_dialog_engine_api_render_engine {
use r3bl_rs_utils_core::*;
use super::*;
use crate::test_dialog::mock_real_objects_for_dialog;
#[tokio::test]
async fn render_engine() {
let self_id: FlexBoxId = FlexBoxId::from(0);
let window_size = &size!( col_count: 70, row_count: 15 );
let dialog_buffer = &mut DialogBuffer::new_empty();
let dialog_engine = &mut mock_real_objects_for_dialog::make_dialog_engine();
let shared_store = &mock_real_objects_for_dialog::create_store();
let shared_global_data =
&test_editor::mock_real_objects_for_editor::make_shared_global_data(
(*window_size).into(),
);
let component_registry =
&mut test_editor::mock_real_objects_for_editor::make_component_registry();
let state = &shared_store.read().await.state.clone();
let args = DialogEngineArgs {
shared_global_data,
shared_store,
state,
component_registry,
window_size,
self_id,
dialog_buffer,
dialog_engine,
};
let pipeline = dbg!(DialogEngineApi::render_engine(args).await.unwrap());
assert_eq2!(pipeline.len(), 1);
let render_ops = pipeline.get(&ZOrder::Glass).unwrap();
assert!(!render_ops.is_empty());
}
}
#[cfg(test)]
mod test_dialog_api_make_flex_box_for_dialog {
use std::error::Error;
use r3bl_rs_utils_core::*;
use crate::{dialog_engine_api::internal_impl, *};
#[test]
fn make_flex_box_for_dialog_simple_display_size_too_small() {
let surface = Surface::default();
let window_size = Size::default();
let dialog_id: FlexBoxId = FlexBoxId::from(0);
let result_flex_box = dbg!(internal_impl::make_flex_box_for_dialog(
&dialog_id,
&DialogEngineConfigOptions {
mode: DialogEngineMode::ModalSimple,
..Default::default()
},
&window_size,
Some(SurfaceBounds::from(&surface)),
));
let my_err: Box<dyn Error + Send + Sync> = result_flex_box.err().unwrap();
assert_eq2!(my_err.is::<CommonError>(), true);
let result = matches!(
my_err.downcast_ref::<CommonError>(),
Some(CommonError {
err_type: CommonErrorType::DisplaySizeTooSmall,
err_msg: _,
})
);
assert_eq2!(result, true);
}
#[test]
fn make_flex_box_for_dialog_autocomplete_display_size_too_small() {
let surface = Surface::default();
let window_size = Size::default();
let dialog_id: FlexBoxId = FlexBoxId::from(0);
let result_flex_box = dbg!(internal_impl::make_flex_box_for_dialog(
&dialog_id,
&DialogEngineConfigOptions {
mode: DialogEngineMode::ModalAutocomplete,
..Default::default()
},
&window_size,
Some(SurfaceBounds::from(&surface)),
));
let my_err: Box<dyn Error + Send + Sync> = result_flex_box.err().unwrap();
assert_eq2!(my_err.is::<CommonError>(), true);
let result = matches!(
my_err.downcast_ref::<CommonError>(),
Some(CommonError {
err_type: CommonErrorType::DisplaySizeTooSmall,
err_msg: _,
})
);
assert_eq2!(result, true);
}
#[test]
fn make_flex_box_for_dialog_simple() {
let surface = Surface {
origin_pos: position! { col_index: 2, row_index: 2 },
box_size: size!( col_count: 65, row_count: 10 ),
..Default::default()
};
let window_size = size!( col_count: 70, row_count: 15 );
let self_id: FlexBoxId = FlexBoxId::from(0);
let result_flex_box = dbg!(internal_impl::make_flex_box_for_dialog(
&self_id,
&DialogEngineConfigOptions {
mode: DialogEngineMode::ModalSimple,
..Default::default()
},
&window_size,
Some(SurfaceBounds::from(&surface)),
));
assert_eq2!(result_flex_box.is_ok(), true);
let flex_box = result_flex_box.unwrap();
assert_eq2!(flex_box.id, self_id);
assert_eq2!(
flex_box.style_adjusted_bounds_size,
size!( col_count: 58, row_count: 4 )
);
assert_eq2!(
flex_box.style_adjusted_origin_pos,
position!( col_index: 5, row_index: 5 )
);
}
#[test]
fn make_flex_box_for_dialog_autocomplete() {
let surface = Surface {
origin_pos: position! { col_index: 2, row_index: 2 },
box_size: size!( col_count: 65, row_count: 10 ),
..Default::default()
};
let window_size = size!( col_count: 70, row_count: 15 );
let self_id: FlexBoxId = FlexBoxId::from(0);
let result_flex_box = dbg!(internal_impl::make_flex_box_for_dialog(
&self_id,
&DialogEngineConfigOptions {
mode: DialogEngineMode::ModalAutocomplete,
..Default::default()
},
&window_size,
Some(SurfaceBounds::from(&surface)),
));
assert_eq2!(result_flex_box.is_ok(), true);
let flex_box = result_flex_box.unwrap();
assert_eq2!(flex_box.id, self_id);
assert_eq2!(
flex_box.style_adjusted_bounds_size,
size!( col_count: 58, row_count: 10 )
);
assert_eq2!(
flex_box.style_adjusted_origin_pos,
position!( col_index: 5, row_index: 2 )
);
}
}
#[cfg(test)]
mod test_dialog_engine_api_apply_event {
use r3bl_rs_utils_core::*;
use super::*;
use crate::test_dialog::mock_real_objects_for_dialog;
#[tokio::test]
async fn apply_event_esc() {
let self_id: FlexBoxId = FlexBoxId::from(0);
let window_size = &size!( col_count: 70, row_count: 15 );
let dialog_buffer = &mut DialogBuffer::new_empty();
let dialog_engine = &mut mock_real_objects_for_dialog::make_dialog_engine();
let shared_store = &mock_real_objects_for_dialog::create_store();
let shared_global_data =
&test_editor::mock_real_objects_for_editor::make_shared_global_data(
(*window_size).into(),
);
let component_registry =
&mut test_editor::mock_real_objects_for_editor::make_component_registry();
let state = &shared_store.read().await.state.clone();
let args = DialogEngineArgs {
shared_global_data,
shared_store,
state,
component_registry,
window_size,
self_id,
dialog_buffer,
dialog_engine,
};
let input_event = InputEvent::Keyboard(keypress!(@special SpecialKey::Esc));
let response = dbg!(DialogEngineApi::apply_event(args, &input_event)
.await
.unwrap());
assert!(matches!(
response,
DialogEngineApplyResponse::DialogChoice(DialogChoice::No)
));
}
#[tokio::test]
async fn apply_event_enter() {
let self_id: FlexBoxId = FlexBoxId::from(0);
let window_size = &size!( col_count: 70, row_count: 15 );
let dialog_buffer = &mut DialogBuffer::new_empty();
let dialog_engine = &mut mock_real_objects_for_dialog::make_dialog_engine();
let shared_store = &mock_real_objects_for_dialog::create_store();
let shared_global_data =
&test_editor::mock_real_objects_for_editor::make_shared_global_data(
(*window_size).into(),
);
let component_registry =
&mut test_editor::mock_real_objects_for_editor::make_component_registry();
let state = &shared_store.read().await.state.clone();
let args = DialogEngineArgs {
shared_global_data,
shared_store,
state,
component_registry,
window_size,
self_id,
dialog_buffer,
dialog_engine,
};
let input_event = InputEvent::Keyboard(keypress!(@special SpecialKey::Enter));
let response = dbg!(DialogEngineApi::apply_event(args, &input_event)
.await
.unwrap());
if let DialogEngineApplyResponse::DialogChoice(DialogChoice::Yes(value)) =
&response
{
assert_eq2!(value, "");
}
assert!(matches!(
response,
DialogEngineApplyResponse::DialogChoice(DialogChoice::Yes(_))
));
}
#[tokio::test]
async fn apply_event_other_key() {
let self_id: FlexBoxId = FlexBoxId::from(0);
let window_size = &size!( col_count: 70, row_count: 15 );
let dialog_buffer = &mut DialogBuffer::new_empty();
let dialog_engine = &mut mock_real_objects_for_dialog::make_dialog_engine();
let shared_store = &mock_real_objects_for_dialog::create_store();
let shared_global_data =
&test_editor::mock_real_objects_for_editor::make_shared_global_data(
(*window_size).into(),
);
let component_registry =
&mut test_editor::mock_real_objects_for_editor::make_component_registry();
let state = &shared_store.read().await.state.clone();
let args = DialogEngineArgs {
shared_global_data,
shared_store,
state,
component_registry,
window_size,
self_id,
dialog_buffer,
dialog_engine,
};
let input_event = InputEvent::Keyboard(keypress!(@char 'a'));
let response = dbg!(DialogEngineApi::apply_event(args, &input_event)
.await
.unwrap());
if let DialogEngineApplyResponse::UpdateEditorBuffer(editor_buffer) = &response {
assert_eq2!(editor_buffer.get_as_string(), "a");
}
}
}