Skip to content
Snippets Groups Projects
Unverified Commit eadba6fc authored by sam's avatar sam Committed by GitHub
Browse files

Placeholders (#74)


* first draft

* refine placeholder logic

bug: inputting and deleting a char on a widget quickly (i think at cursor blink speed) hold the input visually for that blink duration.

needs testing: placeholder specific attrs

* fix conflict with #73

* update placeholder attrs

* small fixes

* fix cursor showing on empty readonly widgets

---------

Co-authored-by: default avatarStaffEngineer <velo.app1@gmail.com>
parent 454758d4
No related branches found
No related tags found
No related merge requests found
......@@ -18,6 +18,7 @@ fn setup(mut commands: Commands) {
Attrs::new().color(bevy_color_to_cosmic(Color::GREEN)),
)),
max_lines: CosmicMaxLines(1),
placeholder_setter: PlaceholderText(CosmicText::OneStyle("Place held :)".into())),
..default()
});
......
......@@ -47,6 +47,10 @@ fn setup(mut commands: Commands, windows: Query<&Window, With<PrimaryWindow>>) {
max_lines: CosmicMaxLines(1),
text_setter: CosmicText::OneStyle("BANANA IS THE CODEWORD!".into()),
mode: CosmicMode::Wrap,
placeholder_setter: PlaceholderText(CosmicText::OneStyle("Placeholder".into())),
placeholder_attrs: PlaceholderAttrs(AttrsOwned::new(
Attrs::new().color(CosmicColor::rgb(88, 88, 88)),
)),
})
.id();
......
......@@ -4,6 +4,8 @@ use bevy_cosmic_edit::*;
fn create_editable_widget(commands: &mut Commands, scale_factor: f32, text: String) -> Entity {
let attrs =
AttrsOwned::new(Attrs::new().color(bevy_color_to_cosmic(Color::hex("4d4d4d").unwrap())));
let placeholder_attrs =
AttrsOwned::new(Attrs::new().color(bevy_color_to_cosmic(Color::hex("#e6e6e6").unwrap())));
commands
.spawn(CosmicEditUiBundle {
border_color: Color::hex("#ededed").unwrap().into(),
......@@ -25,6 +27,8 @@ fn create_editable_widget(commands: &mut Commands, scale_factor: f32, text: Stri
text_setter: CosmicText::OneStyle(text),
text_position: CosmicTextPosition::Left { padding: 20 },
mode: CosmicMode::InfiniteLine,
placeholder_setter: PlaceholderText(CosmicText::OneStyle("Type something...".into())),
placeholder_attrs: PlaceholderAttrs(placeholder_attrs.clone()),
..default()
})
.id()
......
......@@ -190,6 +190,20 @@ pub struct CosmicMaxChars(pub usize);
#[derive(Component, Default)]
pub struct FillColor(pub Color);
#[derive(Component)]
pub struct Placeholder(pub CosmicEditor);
#[derive(Component, Default)]
pub struct PlaceholderText(pub CosmicText);
#[derive(Component)]
pub struct PlaceholderAttrs(pub AttrsOwned);
impl Default for PlaceholderAttrs {
fn default() -> Self {
Self(AttrsOwned::new(Attrs::new()))
}
}
#[derive(Bundle)]
pub struct CosmicEditUiBundle {
// Bevy UI bits
......@@ -245,6 +259,9 @@ pub struct CosmicEditUiBundle {
pub text_setter: CosmicText,
/// Text input mode
pub mode: CosmicMode,
/// Setting this will update the placeholder text
pub placeholder_setter: PlaceholderText,
pub placeholder_attrs: PlaceholderAttrs,
}
impl Default for CosmicEditUiBundle {
......@@ -272,6 +289,8 @@ impl Default for CosmicEditUiBundle {
text_setter: Default::default(),
mode: Default::default(),
background_color: BackgroundColor(Color::WHITE),
placeholder_setter: Default::default(),
placeholder_attrs: Default::default(),
}
}
}
......@@ -387,36 +406,43 @@ impl Plugin for CosmicEditPlugin {
fn build(&self, app: &mut App) {
let font_system = create_cosmic_font_system(self.font_config.clone());
app.add_systems(First, (cosmic_editor_builder, on_scale_factor_change))
.add_systems(PreUpdate, update_buffer_text)
.add_systems(
Update,
(
input_kb,
input_mouse,
blink_cursor,
freeze_cursor_blink,
hide_inactive_or_readonly_cursor,
clear_inactive_selection,
),
)
.add_systems(
PostUpdate,
(cosmic_edit_redraw_buffer_ui, cosmic_edit_redraw_buffer)
.after(TransformSystem::TransformPropagate),
)
.init_resource::<Focus>()
.insert_resource(CursorBlinkTimer(Timer::from_seconds(
0.53,
TimerMode::Repeating,
)))
.insert_resource(CursorVisibility(true))
.insert_resource(SwashCacheState {
swash_cache: SwashCache::new(),
})
.insert_resource(CosmicFontSystem(font_system))
.insert_resource(ClickTimer(Timer::from_seconds(0.5, TimerMode::Once)))
.add_event::<CosmicTextChanged>();
app.add_systems(
First,
(
cosmic_editor_builder,
placeholder_builder,
on_scale_factor_change,
),
)
.add_systems(PreUpdate, (update_buffer_text, update_placeholder_text))
.add_systems(
Update,
(
input_kb,
input_mouse,
blink_cursor,
freeze_cursor_blink,
hide_inactive_or_readonly_cursor,
clear_inactive_selection,
),
)
.add_systems(
PostUpdate,
(cosmic_edit_redraw_buffer_ui, cosmic_edit_redraw_buffer)
.after(TransformSystem::TransformPropagate),
)
.init_resource::<Focus>()
.insert_resource(CursorBlinkTimer(Timer::from_seconds(
0.53,
TimerMode::Repeating,
)))
.insert_resource(CursorVisibility(true))
.insert_resource(SwashCacheState {
swash_cache: SwashCache::new(),
})
.insert_resource(CosmicFontSystem(font_system))
.insert_resource(ClickTimer(Timer::from_seconds(0.5, TimerMode::Once)))
.add_event::<CosmicTextChanged>();
match self.change_cursor {
CursorConfig::Default => {
......@@ -479,6 +505,23 @@ fn cosmic_editor_builder(
}
}
fn placeholder_builder(
mut added_editors: Query<(Entity, &CosmicMetrics), Added<PlaceholderText>>,
mut font_system: ResMut<CosmicFontSystem>,
mut commands: Commands,
) {
for (entity, metrics) in added_editors.iter_mut() {
let buffer = Buffer::new(
&mut font_system.0,
Metrics::new(metrics.font_size, metrics.line_height).scale(metrics.scale_factor),
);
let editor = CosmicEditor(Editor::new(buffer));
commands.entity(entity).insert(Placeholder(editor));
}
}
fn create_cosmic_font_system(cosmic_font_config: CosmicFontConfig) -> FontSystem {
let locale = sys_locale::get_locale().unwrap_or_else(|| String::from("en-US"));
let mut db = cosmic_text::fontdb::Database::new();
......@@ -572,6 +615,21 @@ fn update_buffer_text(
}
}
/// Updates editor buffer when text component changes
fn update_placeholder_text(
mut editor_q: Query<
(&mut Placeholder, &mut PlaceholderText, &PlaceholderAttrs),
Changed<PlaceholderText>,
>,
mut font_system: ResMut<CosmicFontSystem>,
) {
for (mut editor, text, attrs) in editor_q.iter_mut() {
editor
.0
.set_text(text.0.to_owned(), attrs.0.clone(), &mut font_system.0);
}
}
fn trim_text(text: CosmicText, max_chars: usize, max_lines: usize) -> CosmicText {
if max_chars == 0 && max_lines == 0 {
// no limits, no work to do
......@@ -722,30 +780,41 @@ fn blink_cursor(
time: Res<Time>,
active_editor: ResMut<Focus>,
mut cosmic_editor_q: Query<&mut CosmicEditor, Without<ReadOnly>>,
mut placeholder_editor_q: Query<&mut Placeholder, Without<ReadOnly>>,
) {
if let Some(e) = active_editor.0 {
if let Ok(mut editor) = cosmic_editor_q.get_mut(e) {
timer.0.tick(time.delta());
if !timer.0.just_finished() && !active_editor.is_changed() {
return;
}
visibility.0 = !visibility.0;
timer.0.tick(time.delta());
if !timer.0.just_finished() && !active_editor.is_changed() {
return;
}
visibility.0 = !visibility.0;
// always start cursor visible on focus
if active_editor.is_changed() {
visibility.0 = true;
timer.0.set_elapsed(Duration::ZERO);
}
// always start cursor visible on focus
if active_editor.is_changed() {
visibility.0 = true;
timer.0.set_elapsed(Duration::ZERO);
}
let mut cursor = editor.0.cursor();
let new_color = if visibility.0 {
None
} else {
Some(cosmic_text::Color::rgba(0, 0, 0, 0))
};
let new_color = if visibility.0 {
None
} else {
Some(cosmic_text::Color::rgba(0, 0, 0, 0))
};
if let Ok(mut editor) = cosmic_editor_q.get_mut(e) {
let editor = &mut editor.0;
let mut cursor = editor.cursor();
cursor.color = new_color;
editor.0.set_cursor(cursor);
editor.0.buffer_mut().set_redraw(true);
editor.set_cursor(cursor);
editor.buffer_mut().set_redraw(true);
}
if let Ok(mut placeholder) = placeholder_editor_q.get_mut(e) {
let placeholder = &mut placeholder.0 .0;
let mut cursor_p = placeholder.cursor();
cursor_p.color = new_color;
placeholder.set_cursor(cursor_p);
placeholder.buffer_mut().set_redraw(true);
}
}
}
......@@ -784,6 +853,7 @@ fn freeze_cursor_blink(
fn hide_inactive_or_readonly_cursor(
mut cosmic_editor_q_readonly: Query<&mut CosmicEditor, With<ReadOnly>>,
mut cosmic_editor_q_placeholder: Query<(Entity, &mut Placeholder, Option<&ReadOnly>)>,
mut cosmic_editor_q_editable: Query<(Entity, &mut CosmicEditor), Without<ReadOnly>>,
active_editor: Res<Focus>,
) {
......@@ -798,6 +868,16 @@ fn hide_inactive_or_readonly_cursor(
return;
}
for (e, mut editor, readonly_opt) in &mut cosmic_editor_q_placeholder.iter_mut() {
if e != active_editor.0.unwrap() || readonly_opt.is_some() {
let editor = &mut editor.0;
let mut cursor = editor.0.cursor();
cursor.color = Some(cosmic_text::Color::rgba(0, 0, 0, 0));
editor.0.set_cursor(cursor);
editor.0.buffer_mut().set_redraw(true);
}
}
for (e, mut editor) in &mut cosmic_editor_q_editable.iter_mut() {
if e != active_editor.0.unwrap() {
let mut cursor = editor.0.cursor();
......@@ -829,6 +909,7 @@ fn cosmic_edit_redraw_buffer_ui(
mut swash_cache_state: ResMut<SwashCacheState>,
mut cosmic_edit_query: Query<(
&mut CosmicEditor,
Option<&mut Placeholder>,
&CosmicAttrs,
&CosmicBackground,
&FillColor,
......@@ -846,6 +927,7 @@ fn cosmic_edit_redraw_buffer_ui(
for (
mut editor,
mut placeholder_opt,
attrs,
background_image,
fill_color,
......@@ -857,8 +939,20 @@ fn cosmic_edit_redraw_buffer_ui(
mode,
) in &mut cosmic_edit_query.iter_mut()
{
editor.0.shape_as_needed(&mut font_system.0);
if !editor.0.buffer().redraw() {
let editor = if editor.get_text().is_empty() && placeholder_opt.is_some() {
let placeholder = &mut placeholder_opt.as_mut().unwrap().0 .0;
let mut cursor = placeholder.cursor();
cursor.index = 0;
placeholder.set_cursor(cursor);
placeholder.buffer_mut().set_redraw(true);
*x_offset = XOffset(None);
placeholder
} else {
&mut editor.0
};
editor.shape_as_needed(&mut font_system.0);
if !editor.buffer().redraw() {
continue;
}
......@@ -879,12 +973,11 @@ fn cosmic_edit_redraw_buffer_ui(
CosmicMode::Wrap => (widget_width - padding_x, widget_height),
};
editor
.0
.buffer_mut()
.set_size(&mut font_system.0, buffer_width, buffer_height);
if mode == &CosmicMode::AutoHeight {
let text_size = get_text_size(editor.0.buffer());
let text_size = get_text_size(editor.buffer());
let text_height = (text_size.1 + 30.) / primary_window.scale_factor() as f32;
if text_height > height {
height = text_height.ceil();
......@@ -897,7 +990,7 @@ fn cosmic_edit_redraw_buffer_ui(
&mut x_offset,
&mut images,
&mut swash_cache_state,
&mut editor.0,
editor,
attrs,
background_image.0.clone(),
fill_color.0,
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment