Skip to content
This repository has been archived by the owner on Dec 28, 2021. It is now read-only.

Modify list view api to support custom entry #1722

Merged
merged 4 commits into from
Jul 22, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 7 additions & 26 deletions src/rust/ensogl/example/src/list_view.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ use crate::prelude::*;
use ensogl_core::system::web;
use ensogl_core::application::Application;
use ensogl_core::display::object::ObjectOps;
use ensogl_core::display::shape::*;
use ensogl_core::data::color;
use ensogl_text_msdf_sys::run_once_initialized;
use ensogl_gui_components::list_view;
use logger::TraceLogger as Logger;
Expand Down Expand Up @@ -40,19 +38,6 @@ pub fn entry_point_list_view() {
// === Mock Entries ===
// ====================

mod icon {
use super::*;
ensogl_core::define_shape_system! {
(style:Style,id:f32) {
let width = list_view::entry::ICON_SIZE.px();
let height = list_view::entry::ICON_SIZE.px();
let color : Var<color::Rgba> = "rgba(input_id/16.0,0.0,0.0,1.0)".into();
Rect((&width,&height)).fill(color).into()
}
}
}


#[derive(Clone,Debug)]
struct MockEntries {
logger : Logger,
Expand All @@ -68,20 +53,16 @@ impl MockEntries {
}
}

impl list_view::entry::ModelProvider for MockEntries {
impl list_view::entry::ModelProvider<list_view::entry::GlyphHighlightedLabel> for MockEntries {
fn entry_count(&self) -> usize { self.entries_count }

fn get(&self, id:usize) -> Option<list_view::entry::Model> {
fn get(&self, id:usize) -> Option<list_view::entry::GlyphHighlightedLabelModel> {
if id >= self.entries_count {
None
} else {
use list_view::entry::ICON_SIZE;
let icon = icon::View::new(&self.logger);
icon.size.set(Vector2(ICON_SIZE,ICON_SIZE));
icon.id.set(id as f32);
let model = list_view::entry::Model::new(iformat!("Entry {id}")).with_icon(icon);
if id == 10 { Some(model.highlight(std::iter::once((Bytes(1)..Bytes(3)).into()))) }
else { Some(model) }
let label = iformat!("Entry {id}");
let highlighted = if id == 10 { vec![(Bytes(1)..Bytes(3)).into()] } else { vec![] };
Some(list_view::entry::GlyphHighlightedLabelModel {label,highlighted})
}
}
}
Expand All @@ -97,8 +78,8 @@ fn init(app:&Application) {
theme::builtin::light::register(&app);
theme::builtin::light::enable(&app);

let list_view = app.new_view::<list_view::ListView>();
let provider = list_view::entry::AnyModelProvider::from(MockEntries::new(app,1000));
let list_view = app.new_view::<list_view::ListView<list_view::entry::GlyphHighlightedLabel>>();
let provider = list_view::entry::AnyModelProvider::new(MockEntries::new(app,1000));
list_view.frp.resize(Vector2(100.0,160.0));
list_view.frp.set_entries(provider);
app.display.add_child(&list_view);
Expand Down
20 changes: 12 additions & 8 deletions src/rust/ensogl/lib/components/src/drop_down_menu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ pub mod chooser_hover_area {

ensogl_core::define_endpoints! {
Input {
set_entries (list_view::entry::AnyModelProvider),
set_entries (list_view::entry::AnyModelProvider<Entry>),
set_icon_size (Vector2),
set_icon_padding (Vector2),
hide_selection_menu (),
Expand All @@ -96,6 +96,9 @@ ensogl_core::define_endpoints! {
// === Model ===
// =============

/// A type of Entry used in DropDownMenu's ListView.
pub type Entry = list_view::entry::Label;

#[derive(Clone,Debug)]
struct Model {
logger : Logger,
Expand All @@ -106,10 +109,10 @@ struct Model {
icon_overlay : chooser_hover_area::View,

label : text::Area,
selection_menu : list_view::ListView,
selection_menu : list_view::ListView<Entry>,

// `SingleMaskedProvider` allows us to hide the selected element.
content : RefCell<Option<list_view::entry::SingleMaskedProvider>>,
content : RefCell<Option<list_view::entry::SingleMaskedProvider<Entry>>>,
}

impl Model {
Expand Down Expand Up @@ -152,7 +155,8 @@ impl Model {
self.selection_menu.unset_parent()
}

fn get_content_item(&self, id:Option<list_view::entry::Id>) -> Option<list_view::entry::Model> {
fn get_content_item
(&self, id:Option<list_view::entry::Id>) -> Option<<Entry as list_view::entry::Entry>::Model> {
self.content.borrow().as_ref()?.get(id?)
}

Expand Down Expand Up @@ -215,9 +219,9 @@ impl DropDownMenu {
// === Input Processing ===

eval frp.input.set_entries ([model](entries) {
let entries:list_view::entry::SingleMaskedProvider = entries.clone_ref().into();
let entries:list_view::entry::SingleMaskedProvider<Entry> = entries.clone_ref().into();
model.content.set(entries.clone());
let entries:list_view::entry::AnyModelProvider = entries.into();
let entries = list_view::entry::AnyModelProvider::<Entry>::new(entries);
model.selection_menu.frp.set_entries.emit(entries);
});

Expand Down Expand Up @@ -311,12 +315,12 @@ impl DropDownMenu {
// clear the mask.
content.clear_mask();
if let Some(item) = model.get_content_item(Some(*entry_id)) {
model.set_label(&item.label)
model.set_label(&item)
};
// Remove selected item from menu list
content.set_mask(*entry_id);
// Update menu content.
let entries:list_view::entry::AnyModelProvider = content.clone().into();
let entries = list_view::entry::AnyModelProvider::<Entry>::new(content.clone());
model.selection_menu.frp.set_entries.emit(entries);
};
};
Expand Down
61 changes: 32 additions & 29 deletions src/rust/ensogl/lib/components/src/list_view.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ const SHAPE_PADDING:f32 = 5.0;
mod selection {
use super::*;

pub const CORNER_RADIUS_PX:f32 = entry::LABEL_SIZE;
pub const CORNER_RADIUS_PX:f32 = 12.0;

ensogl_core::define_shape_system! {
(style:Style) {
Expand Down Expand Up @@ -95,16 +95,17 @@ struct View {

/// The Model of Select Component.
#[derive(Clone,CloneRef,Debug)]
struct Model {
struct Model<E:entry::Entry> {
app : Application,
entries : entry::List,
entries : entry::List<E>,
selection : selection::View,
background : background::View,
scrolled_area : display::object::Instance,
display_object : display::object::Instance,
}

impl Model {
impl<E:entry::Entry> Model<E> {

fn new(app:&Application) -> Self {
let app = app.clone_ref();
let logger = Logger::new("SelectionContainer");
Expand Down Expand Up @@ -141,7 +142,7 @@ impl Model {
self.entries.update_entries(visible_entries);
}

fn set_entries(&self, provider:entry::AnyModelProvider, view:&View) {
fn set_entries(&self, provider:entry::AnyModelProvider<E>, view:&View) {
let visible_entries = Self::visible_entries(view,provider.entry_count());
self.entries.update_entries_new_provider(provider,visible_entries);
}
Expand All @@ -151,10 +152,10 @@ impl Model {
0..0
} else {
let entry_at_y_saturating = |y:f32| {
match entry::List::entry_at_y_position(y,entry_count) {
entry::IdAtYPosition::AboveFirst => 0,
entry::IdAtYPosition::UnderLast => entry_count - 1,
entry::IdAtYPosition::Entry(id) => id,
match entry::List::<E>::entry_at_y_position(y,entry_count) {
entry::list::IdAtYPosition::AboveFirst => 0,
entry::list::IdAtYPosition::UnderLast => entry_count - 1,
entry::list::IdAtYPosition::Entry(id) => id,
}
};
let first = entry_at_y_saturating(*position_y);
Expand Down Expand Up @@ -191,6 +192,7 @@ impl Model {
// ===========

ensogl_core::define_endpoints! {
<E>
Input {
/// Move selection one position up.
move_selection_up(),
Expand All @@ -211,7 +213,7 @@ ensogl_core::define_endpoints! {

resize (Vector2<f32>),
scroll_jump (f32),
set_entries (entry::AnyModelProvider),
set_entries (entry::AnyModelProvider<E>),
select_entry (entry::Id),
chose_entry (entry::Id),
}
Expand All @@ -226,27 +228,28 @@ ensogl_core::define_endpoints! {



// ========================
// === Select Component ===
// ========================
// ==========================
// === ListView Component ===
// ==========================

/// Select Component.
/// ListView Component.
///
/// Select is a displayed list of entries with possibility of selecting one and "chosing" by
/// clicking or pressing enter.
/// This is a displayed list of entries (of any type `E`) with possibility of selecting one and
/// "choosing" by clicking or pressing enter. The basic entry types are defined in [`entry`] module.
#[allow(missing_docs)]
#[derive(Clone,CloneRef,Debug)]
pub struct ListView {
model : Model,
pub frp : Frp,
pub struct ListView<E:entry::Entry> {
model : Model<E>,
pub frp : Frp<E>,
}

impl Deref for ListView {
type Target = Frp;
impl<E:entry::Entry> Deref for ListView<E> {
type Target = Frp<E>;
fn deref(&self) -> &Self::Target { &self.frp }
}

impl ListView {
impl<E:entry::Entry> ListView<E>
where E::Model : Default {
/// Constructor.
pub fn new(app:&Application) -> Self {
let frp = Frp::new();
Expand Down Expand Up @@ -279,7 +282,7 @@ impl ListView {
scene.screen_to_object_space(&model.scrolled_area,*pos).y
}));
mouse_pointed_entry <- mouse_y_in_scroll.map(f!([model](y)
entry::List::entry_at_y_position(*y,model.entries.entry_count()).entry()
entry::List::<E>::entry_at_y_position(*y,model.entries.entry_count()).entry()
));


Expand Down Expand Up @@ -336,7 +339,7 @@ impl ListView {
// === Selection Size and Position ===

target_selection_y <- frp.selected_entry.map(|id|
id.map_or(0.0,entry::List::position_y_of_entry)
id.map_or(0.0,entry::List::<E>::position_y_of_entry)
);
target_selection_height <- frp.selected_entry.map(f!([](id)
if id.is_some() {entry::HEIGHT} else {0.0}
Expand All @@ -361,7 +364,7 @@ impl ListView {
// === Scrolling ===

selection_top_after_move_up <- selected_entry_after_move_up.map(|id|
id.map(|id| entry::List::y_range_of_entry(id).end)
id.map(|id| entry::List::<E>::y_range_of_entry(id).end)
);
min_scroll_after_move_up <- selection_top_after_move_up.map(|top|
top.unwrap_or(MAX_SCROLL)
Expand All @@ -370,7 +373,7 @@ impl ListView {
current.max(*min)
);
selection_bottom_after_move_down <- selected_entry_after_move_down.map(|id|
id.map(|id| entry::List::y_range_of_entry(id).start)
id.map(|id| entry::List::<E>::y_range_of_entry(id).start)
);
max_scroll_after_move_down <- selection_bottom_after_move_down.map2(&frp.size,
|y,size| y.map_or(MAX_SCROLL, |y| y + size.y)
Expand Down Expand Up @@ -420,15 +423,15 @@ impl ListView {
}
}

impl display::Object for ListView {
impl<E:entry::Entry> display::Object for ListView<E> {
fn display_object(&self) -> &display::object::Instance { &self.model.display_object }
}

impl application::command::FrpNetworkProvider for ListView {
impl<E:entry::Entry> application::command::FrpNetworkProvider for ListView<E> {
fn network(&self) -> &frp::Network { &self.frp.network }
}

impl application::View for ListView {
impl<E:entry::Entry> application::View for ListView<E> {
fn label() -> &'static str { "ListView" }
fn new(app:&Application) -> Self { ListView::new(app) }
fn app(&self) -> &Application { &self.model.app }
Expand Down
Loading