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

Commit

Permalink
Modify list view api to support custom entry (#1722)
Browse files Browse the repository at this point in the history
Also fixed issue with not-masked selected entry in visualization chooser.
  • Loading branch information
farmaazon authored Jul 22, 2021
1 parent 3031f4a commit b398ad9
Show file tree
Hide file tree
Showing 11 changed files with 546 additions and 440 deletions.
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

0 comments on commit b398ad9

Please sign in to comment.