ui: remove Entity
parent
b993375fa0
commit
106744c7ca
22
src/bin.rs
22
src/bin.rs
|
@ -62,32 +62,30 @@ fn main() {
|
|||
let worker_receiver = state.worker_receiver();
|
||||
|
||||
/* Register some reasonably useful interfaces */
|
||||
let menu = Entity::from(Box::new(AccountMenu::new(&state.context.accounts)));
|
||||
let menu = Box::new(AccountMenu::new(&state.context.accounts));
|
||||
let listing = listing::Listing::from(IndexStyle::Compact);
|
||||
let b = Entity::from(Box::new(listing));
|
||||
let tabs = Box::new(Tabbed::new(vec![
|
||||
let b = Box::new(listing);
|
||||
let window = Box::new(Tabbed::new(vec![
|
||||
Box::new(VSplit::new(menu, b, 90, false)),
|
||||
Box::new(AccountsPanel::new(&state.context)),
|
||||
Box::new(ContactList::default()),
|
||||
]));
|
||||
let window = Entity::from(tabs);
|
||||
|
||||
let status_bar = Entity::from(Box::new(StatusBar::new(window)));
|
||||
state.register_entity(status_bar);
|
||||
let status_bar = Box::new(StatusBar::new(window));
|
||||
state.register_component(status_bar);
|
||||
|
||||
let xdg_notifications =
|
||||
Entity::from(Box::new(ui::components::notifications::XDGNotifications {}));
|
||||
state.register_entity(xdg_notifications);
|
||||
state.register_entity(Entity::from(Box::new(
|
||||
let xdg_notifications = Box::new(ui::components::notifications::XDGNotifications {});
|
||||
state.register_component(xdg_notifications);
|
||||
state.register_component(Box::new(
|
||||
ui::components::notifications::NotificationFilter {},
|
||||
)));
|
||||
));
|
||||
|
||||
/* Keep track of the input mode. See ui::UIMode for details */
|
||||
'main: loop {
|
||||
state.render();
|
||||
|
||||
'inner: loop {
|
||||
/* Check if any entities have sent reply events to State. */
|
||||
/* Check if any components have sent reply events to State. */
|
||||
let events: Vec<UIEvent> = state.context.replies();
|
||||
for e in events {
|
||||
state.rcv_event(e);
|
||||
|
|
|
@ -76,69 +76,7 @@ const _DOUBLE_DOWN_AND_LEFT: char = '╗';
|
|||
const _DOUBLE_UP_AND_LEFT: char = '╝';
|
||||
const _DOUBLE_UP_AND_RIGHT: char = '╚';
|
||||
|
||||
type EntityId = Uuid;
|
||||
|
||||
/// `Entity` is a container for Components.
|
||||
#[derive(Debug)]
|
||||
pub struct Entity {
|
||||
id: EntityId,
|
||||
pub component: Box<Component>, // more than one?
|
||||
}
|
||||
|
||||
impl From<Box<Component>> for Entity {
|
||||
fn from(mut kind: Box<Component>) -> Entity {
|
||||
let id = Uuid::new_v4();
|
||||
kind.set_id(id);
|
||||
Entity {
|
||||
id,
|
||||
component: kind,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<C: 'static> From<Box<C>> for Entity
|
||||
where
|
||||
C: Component,
|
||||
{
|
||||
fn from(mut kind: Box<C>) -> Entity {
|
||||
let id = Uuid::new_v4();
|
||||
kind.set_id(id);
|
||||
Entity {
|
||||
id,
|
||||
component: kind,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Entity {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
Display::fmt(&self.component, f)
|
||||
}
|
||||
}
|
||||
|
||||
impl DerefMut for Entity {
|
||||
fn deref_mut(&mut self) -> &mut Box<Component> {
|
||||
&mut self.component
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for Entity {
|
||||
type Target = Box<Component>;
|
||||
|
||||
fn deref(&self) -> &Box<Component> {
|
||||
&self.component
|
||||
}
|
||||
}
|
||||
|
||||
impl Entity {
|
||||
pub fn id(&self) -> &EntityId {
|
||||
&self.id
|
||||
}
|
||||
/// Pass events to child component.
|
||||
pub fn rcv_event(&mut self, event: &mut UIEvent, context: &mut Context) -> bool {
|
||||
self.component.process_event(event, context)
|
||||
}
|
||||
}
|
||||
type ComponentId = Uuid;
|
||||
|
||||
pub type ShortcutMap = FnvHashMap<&'static str, Key>;
|
||||
|
||||
|
@ -155,8 +93,9 @@ pub trait Component: Display + Debug + Send {
|
|||
true
|
||||
}
|
||||
fn set_dirty(&mut self);
|
||||
fn kill(&mut self, _id: EntityId) {}
|
||||
fn set_id(&mut self, _id: EntityId) {}
|
||||
fn kill(&mut self, _id: ComponentId) {}
|
||||
fn set_id(&mut self, _id: ComponentId) {}
|
||||
fn id(&self) -> ComponentId;
|
||||
|
||||
fn get_shortcuts(&self, _context: &Context) -> ShortcutMap {
|
||||
Default::default()
|
||||
|
|
|
@ -36,7 +36,7 @@ enum ViewMode {
|
|||
|
||||
#[derive(Debug)]
|
||||
pub struct ContactManager {
|
||||
id: Uuid,
|
||||
id: ComponentId,
|
||||
pub card: Card,
|
||||
mode: ViewMode,
|
||||
form: FormWidget,
|
||||
|
@ -169,13 +169,13 @@ impl Component for ContactManager {
|
|||
});
|
||||
context.replies.push_back(UIEvent {
|
||||
id: 0,
|
||||
event_type: UIEventType::EntityKill(self.id),
|
||||
event_type: UIEventType::ComponentKill(self.id),
|
||||
});
|
||||
}
|
||||
Some(false) => {
|
||||
context.replies.push_back(UIEvent {
|
||||
id: 0,
|
||||
event_type: UIEventType::EntityKill(self.id),
|
||||
event_type: UIEventType::ComponentKill(self.id),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -186,7 +186,7 @@ impl Component for ContactManager {
|
|||
UIEventType::Input(Key::Char('\n')) => {
|
||||
context.replies.push_back(UIEvent {
|
||||
id: 0,
|
||||
event_type: UIEventType::EntityKill(self.id),
|
||||
event_type: UIEventType::ComponentKill(self.id),
|
||||
});
|
||||
return true;
|
||||
},
|
||||
|
@ -206,7 +206,10 @@ impl Component for ContactManager {
|
|||
self.form.set_dirty();
|
||||
}
|
||||
|
||||
fn set_id(&mut self, uuid: Uuid) {
|
||||
self.id = uuid;
|
||||
fn id(&self) -> ComponentId {
|
||||
self.id
|
||||
}
|
||||
fn set_id(&mut self, id: ComponentId) {
|
||||
self.id = id;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,7 +23,8 @@ pub struct ContactList {
|
|||
|
||||
mode: ViewMode,
|
||||
dirty: bool,
|
||||
view: Option<Entity>,
|
||||
view: Option<Box<Component>>,
|
||||
id: ComponentId,
|
||||
}
|
||||
|
||||
impl Default for ContactList {
|
||||
|
@ -51,6 +52,7 @@ impl ContactList {
|
|||
content,
|
||||
dirty: true,
|
||||
view: None,
|
||||
id: ComponentId::default(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -234,10 +236,10 @@ impl Component for ContactList {
|
|||
UIEventType::Input(ref key) if *key == shortcuts["create_contact"] => {
|
||||
let mut manager = ContactManager::default();
|
||||
manager.account_pos = self.account_pos;
|
||||
let entity = Entity::from(Box::new(manager));
|
||||
let component = Box::new(manager);
|
||||
|
||||
self.mode = ViewMode::View(*entity.id());
|
||||
self.view = Some(entity);
|
||||
self.mode = ViewMode::View(component.id());
|
||||
self.view = Some(component);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -249,10 +251,10 @@ impl Component for ContactList {
|
|||
let mut manager = ContactManager::default();
|
||||
manager.card = card;
|
||||
manager.account_pos = self.account_pos;
|
||||
let entity = Entity::from(Box::new(manager));
|
||||
let component = Box::new(manager);
|
||||
|
||||
self.mode = ViewMode::View(*entity.id());
|
||||
self.view = Some(entity);
|
||||
self.mode = ViewMode::View(component.id());
|
||||
self.view = Some(component);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -261,9 +263,9 @@ impl Component for ContactList {
|
|||
let mut manager = ContactManager::default();
|
||||
manager.card = card;
|
||||
manager.account_pos = self.account_pos;
|
||||
let entity = Entity::from(Box::new(manager));
|
||||
self.mode = ViewMode::View(*entity.id());
|
||||
self.view = Some(entity);
|
||||
let component = Box::new(manager);
|
||||
self.mode = ViewMode::View(component.id());
|
||||
self.view = Some(component);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -277,7 +279,7 @@ impl Component for ContactList {
|
|||
self.new_cursor_pos += 1;
|
||||
return true;
|
||||
}
|
||||
UIEventType::EntityKill(ref kill_id) if self.mode == ViewMode::View(*kill_id) => {
|
||||
UIEventType::ComponentKill(ref kill_id) if self.mode == ViewMode::View(*kill_id) => {
|
||||
self.mode = ViewMode::List;
|
||||
self.view.take();
|
||||
self.set_dirty();
|
||||
|
@ -315,4 +317,11 @@ impl Component for ContactList {
|
|||
|
||||
map
|
||||
}
|
||||
|
||||
fn id(&self) -> ComponentId {
|
||||
self.id
|
||||
}
|
||||
fn set_id(&mut self, id: ComponentId) {
|
||||
self.id = id;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,6 +38,7 @@ pub struct Indexer {
|
|||
entries: Vec<MenuEntry>,
|
||||
dirty: bool,
|
||||
cursor: Vec<usize>,
|
||||
id: ComponentId,
|
||||
}
|
||||
|
||||
impl fmt::Display for Indexer {
|
||||
|
@ -53,6 +54,7 @@ impl Default for Indexer {
|
|||
entries: Vec::with_capacity(8),
|
||||
dirty: true,
|
||||
cursor: Vec::with_capacity(8),
|
||||
id: ComponentId::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -125,4 +127,11 @@ impl Component for Indexer {
|
|||
fn set_dirty(&mut self) {
|
||||
self.dirty = true;
|
||||
}
|
||||
|
||||
fn id(&self) -> ComponentId {
|
||||
self.id
|
||||
}
|
||||
fn set_id(&mut self, id: ComponentId) {
|
||||
self.id = id;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,6 +34,7 @@ pub struct Index {
|
|||
state: IndexState,
|
||||
|
||||
content: Box<IndexContent>,
|
||||
id: ComponentId,
|
||||
}
|
||||
|
||||
impl Index {
|
||||
|
@ -169,6 +170,13 @@ impl Component for Index {
|
|||
fn set_dirty(&mut self) {
|
||||
self.dirty = true;
|
||||
}
|
||||
|
||||
fn id(&self) -> ComponentId {
|
||||
self.id
|
||||
}
|
||||
fn set_id(&mut self, id: ComponentId) {
|
||||
self.id = id;
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Index {
|
||||
|
|
|
@ -48,6 +48,7 @@ pub struct AccountMenu {
|
|||
dirty: bool,
|
||||
visible: bool,
|
||||
cursor: Option<(usize, usize)>,
|
||||
id: ComponentId,
|
||||
}
|
||||
|
||||
impl fmt::Display for AccountMenu {
|
||||
|
@ -72,6 +73,7 @@ impl AccountMenu {
|
|||
visible: true,
|
||||
dirty: true,
|
||||
cursor: None,
|
||||
id: ComponentId::default(),
|
||||
}
|
||||
}
|
||||
/*
|
||||
|
@ -301,4 +303,11 @@ impl Component for AccountMenu {
|
|||
.cloned()
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn id(&self) -> ComponentId {
|
||||
self.id
|
||||
}
|
||||
fn set_id(&mut self, id: ComponentId) {
|
||||
self.id = id;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,6 +27,7 @@ pub struct AccountsPanel {
|
|||
cursor: usize,
|
||||
content: CellBuffer,
|
||||
dirty: bool,
|
||||
id: ComponentId,
|
||||
}
|
||||
|
||||
impl fmt::Display for AccountsPanel {
|
||||
|
@ -84,6 +85,13 @@ impl Component for AccountsPanel {
|
|||
fn set_dirty(&mut self) {
|
||||
self.dirty = true;
|
||||
}
|
||||
|
||||
fn id(&self) -> ComponentId {
|
||||
self.id
|
||||
}
|
||||
fn set_id(&mut self, id: ComponentId) {
|
||||
self.id = id;
|
||||
}
|
||||
}
|
||||
|
||||
impl AccountsPanel {
|
||||
|
@ -94,6 +102,7 @@ impl AccountsPanel {
|
|||
cursor: 0,
|
||||
content,
|
||||
dirty: true,
|
||||
id: ComponentId::default(),
|
||||
}
|
||||
}
|
||||
fn initialize(&mut self, context: &Context) {
|
||||
|
|
|
@ -45,6 +45,7 @@ pub struct Composer {
|
|||
mode: ViewMode,
|
||||
dirty: bool,
|
||||
initialized: bool,
|
||||
id: ComponentId,
|
||||
}
|
||||
|
||||
impl Default for Composer {
|
||||
|
@ -62,6 +63,7 @@ impl Default for Composer {
|
|||
mode: ViewMode::Edit,
|
||||
dirty: true,
|
||||
initialized: false,
|
||||
id: ComponentId::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -688,6 +690,13 @@ impl Component for Composer {
|
|||
|
||||
map
|
||||
}
|
||||
|
||||
fn id(&self) -> ComponentId {
|
||||
self.id
|
||||
}
|
||||
fn set_id(&mut self, id: ComponentId) {
|
||||
self.id = id;
|
||||
}
|
||||
}
|
||||
|
||||
fn get_display_name(context: &Context, idx: usize) -> String {
|
||||
|
|
|
@ -163,6 +163,21 @@ impl Component for Listing {
|
|||
Listing::Threaded(l) => l.get_shortcuts(context),
|
||||
}
|
||||
}
|
||||
|
||||
fn id(&self) -> ComponentId {
|
||||
match self {
|
||||
Listing::Compact(l) => l.id(),
|
||||
Listing::Plain(l) => l.id(),
|
||||
Listing::Threaded(l) => l.id(),
|
||||
}
|
||||
}
|
||||
fn set_id(&mut self, id: ComponentId) {
|
||||
match self {
|
||||
Listing::Compact(l) => l.set_id(id),
|
||||
Listing::Plain(l) => l.set_id(id),
|
||||
Listing::Threaded(l) => l.set_id(id),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<IndexStyle> for Listing {
|
||||
|
|
|
@ -43,6 +43,7 @@ struct MailboxView {
|
|||
view: ThreadView,
|
||||
|
||||
movement: Option<PageMovement>,
|
||||
id: ComponentId,
|
||||
}
|
||||
|
||||
impl fmt::Display for MailboxView {
|
||||
|
@ -87,6 +88,7 @@ impl MailboxView {
|
|||
view: ThreadView::default(),
|
||||
|
||||
movement: None,
|
||||
id: ComponentId::default(),
|
||||
}
|
||||
}
|
||||
/// Fill the `self.content` `CellBuffer` with the contents of the account folder the user has
|
||||
|
@ -587,6 +589,13 @@ impl Component for MailboxView {
|
|||
|
||||
map
|
||||
}
|
||||
|
||||
fn id(&self) -> ComponentId {
|
||||
self.id
|
||||
}
|
||||
fn set_id(&mut self, id: ComponentId) {
|
||||
self.id = id;
|
||||
}
|
||||
}
|
||||
|
||||
/// A list of all mail (`Envelope`s) in a `Mailbox`. On `\n` it opens the `Envelope` content in a
|
||||
|
@ -597,6 +606,7 @@ pub struct CompactListing {
|
|||
cursor: usize,
|
||||
dirty: bool,
|
||||
populated: bool,
|
||||
id: ComponentId,
|
||||
}
|
||||
|
||||
impl ListingTrait for CompactListing {
|
||||
|
@ -627,6 +637,7 @@ impl CompactListing {
|
|||
cursor: 0,
|
||||
dirty: true,
|
||||
populated: false,
|
||||
id: ComponentId::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -762,4 +773,11 @@ impl Component for CompactListing {
|
|||
|
||||
map
|
||||
}
|
||||
|
||||
fn id(&self) -> ComponentId {
|
||||
self.id
|
||||
}
|
||||
fn set_id(&mut self, id: ComponentId) {
|
||||
self.id = id;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,6 +41,7 @@ pub struct PlainListing {
|
|||
/// If `self.view` exists or not.
|
||||
unfocused: bool,
|
||||
view: Option<MailView>,
|
||||
id: ComponentId,
|
||||
}
|
||||
|
||||
impl ListingTrait for PlainListing {
|
||||
|
@ -89,6 +90,7 @@ impl PlainListing {
|
|||
dirty: true,
|
||||
unfocused: false,
|
||||
view: None,
|
||||
id: ComponentId::default(),
|
||||
}
|
||||
}
|
||||
/// Fill the `self.content` `CellBuffer` with the contents of the account folder the user has
|
||||
|
@ -561,4 +563,11 @@ impl Component for PlainListing {
|
|||
};
|
||||
self.dirty = true;
|
||||
}
|
||||
|
||||
fn id(&self) -> ComponentId {
|
||||
self.id
|
||||
}
|
||||
fn set_id(&mut self, id: ComponentId) {
|
||||
self.id = id;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -44,6 +44,7 @@ pub struct ThreadListing {
|
|||
unfocused: bool,
|
||||
initialised: bool,
|
||||
view: Option<MailView>,
|
||||
id: ComponentId,
|
||||
}
|
||||
|
||||
impl ListingTrait for ThreadListing {
|
||||
|
@ -86,6 +87,7 @@ impl ThreadListing {
|
|||
unfocused: false,
|
||||
view: None,
|
||||
initialised: false,
|
||||
id: ComponentId::default(),
|
||||
}
|
||||
}
|
||||
/// Fill the `self.content` `CellBuffer` with the contents of the account folder the user has
|
||||
|
@ -729,4 +731,11 @@ impl Component for ThreadListing {
|
|||
.map(|p| p.get_shortcuts(context))
|
||||
.unwrap_or_default()
|
||||
}
|
||||
|
||||
fn id(&self) -> ComponentId {
|
||||
self.id
|
||||
}
|
||||
fn set_id(&mut self, id: ComponentId) {
|
||||
self.id = id;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -69,6 +69,7 @@ pub struct MailView {
|
|||
mode: ViewMode,
|
||||
|
||||
cmd_buf: String,
|
||||
id: ComponentId,
|
||||
}
|
||||
|
||||
impl fmt::Display for MailView {
|
||||
|
@ -112,6 +113,7 @@ impl MailView {
|
|||
mode: ViewMode::Normal,
|
||||
|
||||
cmd_buf: String::with_capacity(4),
|
||||
id: ComponentId::default(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -723,4 +725,11 @@ impl Component for MailView {
|
|||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
fn id(&self) -> ComponentId {
|
||||
self.id
|
||||
}
|
||||
fn set_id(&mut self, id: ComponentId) {
|
||||
self.id = id;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -55,6 +55,7 @@ pub struct EnvelopeView {
|
|||
|
||||
account_pos: usize,
|
||||
cmd_buf: String,
|
||||
id: ComponentId,
|
||||
}
|
||||
|
||||
impl fmt::Display for EnvelopeView {
|
||||
|
@ -79,6 +80,7 @@ impl EnvelopeView {
|
|||
wrapper,
|
||||
account_pos,
|
||||
cmd_buf: String::with_capacity(4),
|
||||
id: ComponentId::default(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -545,4 +547,11 @@ impl Component for EnvelopeView {
|
|||
fn set_dirty(&mut self) {
|
||||
self.dirty = true;
|
||||
}
|
||||
|
||||
fn id(&self) -> ComponentId {
|
||||
self.id
|
||||
}
|
||||
fn set_id(&mut self, id: ComponentId) {
|
||||
self.id = id;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,10 +27,12 @@ use std::process::{Command, Stdio};
|
|||
pub struct HtmlView {
|
||||
pager: Pager,
|
||||
bytes: Vec<u8>,
|
||||
id: ComponentId,
|
||||
}
|
||||
|
||||
impl HtmlView {
|
||||
pub fn new(bytes: Vec<u8>, context: &mut Context, account_pos: usize) -> Self {
|
||||
let id = ComponentId::default();
|
||||
let settings = context.accounts[account_pos].runtime_settings.conf();
|
||||
if let Some(filter_invocation) = settings.html_filter() {
|
||||
let parts = split_command!(filter_invocation);
|
||||
|
@ -57,7 +59,7 @@ impl HtmlView {
|
|||
None,
|
||||
None,
|
||||
);
|
||||
HtmlView { pager, bytes }
|
||||
HtmlView { pager, bytes, id }
|
||||
} else {
|
||||
let mut html_filter = command_obj.unwrap();
|
||||
html_filter
|
||||
|
@ -75,7 +77,7 @@ impl HtmlView {
|
|||
));
|
||||
|
||||
let pager = Pager::from_string(display_text, None, None, None);
|
||||
HtmlView { pager, bytes }
|
||||
HtmlView { pager, bytes, id }
|
||||
}
|
||||
} else {
|
||||
if let Ok(mut html_filter) = Command::new("w3m")
|
||||
|
@ -98,7 +100,7 @@ impl HtmlView {
|
|||
));
|
||||
|
||||
let pager = Pager::from_string(display_text, None, None, None);
|
||||
HtmlView { pager, bytes }
|
||||
HtmlView { pager, bytes, id }
|
||||
} else {
|
||||
context.replies.push_back(UIEvent {
|
||||
id: 0,
|
||||
|
@ -115,7 +117,7 @@ impl HtmlView {
|
|||
None,
|
||||
None,
|
||||
);
|
||||
HtmlView { pager, bytes }
|
||||
HtmlView { pager, bytes, id }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -168,4 +170,11 @@ impl Component for HtmlView {
|
|||
fn set_dirty(&mut self) {
|
||||
self.pager.set_dirty();
|
||||
}
|
||||
|
||||
fn id(&self) -> ComponentId {
|
||||
self.id
|
||||
}
|
||||
fn set_id(&mut self, id: ComponentId) {
|
||||
self.id = id;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -51,6 +51,7 @@ pub struct ThreadView {
|
|||
dirty: bool,
|
||||
content: CellBuffer,
|
||||
initiated: bool,
|
||||
id: ComponentId,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
@ -985,4 +986,11 @@ impl Component for ThreadView {
|
|||
|
||||
map
|
||||
}
|
||||
|
||||
fn id(&self) -> ComponentId {
|
||||
self.id
|
||||
}
|
||||
fn set_id(&mut self, id: ComponentId) {
|
||||
self.id = id;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -54,6 +54,11 @@ impl Component for XDGNotifications {
|
|||
false
|
||||
}
|
||||
fn set_dirty(&mut self) {}
|
||||
|
||||
fn id(&self) -> ComponentId {
|
||||
ComponentId::nil()
|
||||
}
|
||||
fn set_id(&mut self, _id: ComponentId) {}
|
||||
}
|
||||
|
||||
fn escape_str(s: &str) -> String {
|
||||
|
@ -133,5 +138,9 @@ impl Component for NotificationFilter {
|
|||
}
|
||||
false
|
||||
}
|
||||
fn id(&self) -> ComponentId {
|
||||
ComponentId::nil()
|
||||
}
|
||||
fn set_dirty(&mut self) {}
|
||||
fn set_id(&mut self, _id: ComponentId) {}
|
||||
}
|
||||
|
|
|
@ -30,10 +30,11 @@ pub use self::widgets::*;
|
|||
/// A horizontally split in half container.
|
||||
#[derive(Debug)]
|
||||
pub struct HSplit {
|
||||
top: Entity,
|
||||
bottom: Entity,
|
||||
top: Box<Component>,
|
||||
bottom: Box<Component>,
|
||||
show_divider: bool,
|
||||
ratio: usize, // bottom/whole height * 100
|
||||
id: ComponentId,
|
||||
}
|
||||
|
||||
impl fmt::Display for HSplit {
|
||||
|
@ -44,12 +45,18 @@ impl fmt::Display for HSplit {
|
|||
}
|
||||
|
||||
impl HSplit {
|
||||
pub fn new(top: Entity, bottom: Entity, ratio: usize, show_divider: bool) -> Self {
|
||||
pub fn new(
|
||||
top: Box<Component>,
|
||||
bottom: Box<Component>,
|
||||
ratio: usize,
|
||||
show_divider: bool,
|
||||
) -> Self {
|
||||
HSplit {
|
||||
top,
|
||||
bottom,
|
||||
show_divider,
|
||||
ratio,
|
||||
id: ComponentId::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -62,8 +69,8 @@ impl Component for HSplit {
|
|||
let upper_left = upper_left!(area);
|
||||
let bottom_right = bottom_right!(area);
|
||||
let total_rows = get_y(bottom_right) - get_y(upper_left);
|
||||
let bottom_entity_height = (self.ratio * total_rows) / 100;
|
||||
let mid = get_y(upper_left) + total_rows - bottom_entity_height;
|
||||
let bottom_component_height = (self.ratio * total_rows) / 100;
|
||||
let mid = get_y(upper_left) + total_rows - bottom_component_height;
|
||||
|
||||
if self.show_divider {
|
||||
for i in get_x(upper_left)..=get_x(bottom_right) {
|
||||
|
@ -74,7 +81,7 @@ impl Component for HSplit {
|
|||
.push_back(((get_x(upper_left), mid), (get_x(bottom_right), mid)));
|
||||
}
|
||||
|
||||
self.top.component.draw(
|
||||
self.top.draw(
|
||||
grid,
|
||||
(
|
||||
upper_left,
|
||||
|
@ -82,23 +89,23 @@ impl Component for HSplit {
|
|||
),
|
||||
context,
|
||||
);
|
||||
self.bottom.component.draw(
|
||||
self.bottom.draw(
|
||||
grid,
|
||||
((get_x(upper_left), get_y(upper_left) + mid), bottom_right),
|
||||
context,
|
||||
);
|
||||
}
|
||||
fn process_event(&mut self, event: &mut UIEvent, context: &mut Context) -> bool {
|
||||
self.top.rcv_event(event, context) || self.bottom.rcv_event(event, context)
|
||||
self.top.process_event(event, context) || self.bottom.process_event(event, context)
|
||||
}
|
||||
|
||||
fn is_dirty(&self) -> bool {
|
||||
self.top.component.is_dirty() || self.bottom.component.is_dirty()
|
||||
self.top.is_dirty() || self.bottom.is_dirty()
|
||||
}
|
||||
|
||||
fn set_dirty(&mut self) {
|
||||
self.top.component.set_dirty();
|
||||
self.bottom.component.set_dirty();
|
||||
self.top.set_dirty();
|
||||
self.bottom.set_dirty();
|
||||
}
|
||||
|
||||
fn get_shortcuts(&self, context: &Context) -> ShortcutMap {
|
||||
|
@ -106,34 +113,48 @@ impl Component for HSplit {
|
|||
top_map.extend(self.bottom.get_shortcuts(context).into_iter());
|
||||
top_map
|
||||
}
|
||||
|
||||
fn id(&self) -> ComponentId {
|
||||
self.id
|
||||
}
|
||||
fn set_id(&mut self, id: ComponentId) {
|
||||
self.id = id;
|
||||
}
|
||||
}
|
||||
|
||||
/// A vertically split in half container.
|
||||
#[derive(Debug)]
|
||||
pub struct VSplit {
|
||||
left: Entity,
|
||||
right: Entity,
|
||||
left: Box<Component>,
|
||||
right: Box<Component>,
|
||||
show_divider: bool,
|
||||
prev_visibility: (bool, bool),
|
||||
/// This is the width of the right container to the entire width.
|
||||
ratio: usize, // right/(container width) * 100
|
||||
id: ComponentId,
|
||||
}
|
||||
|
||||
impl fmt::Display for VSplit {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
// TODO display focused entity
|
||||
// TODO display focused component
|
||||
Display::fmt(&self.right, f)
|
||||
}
|
||||
}
|
||||
|
||||
impl VSplit {
|
||||
pub fn new(left: Entity, right: Entity, ratio: usize, show_divider: bool) -> Self {
|
||||
pub fn new(
|
||||
left: Box<Component>,
|
||||
right: Box<Component>,
|
||||
ratio: usize,
|
||||
show_divider: bool,
|
||||
) -> Self {
|
||||
VSplit {
|
||||
left,
|
||||
right,
|
||||
show_divider,
|
||||
prev_visibility: (true, true),
|
||||
ratio,
|
||||
id: ComponentId::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -151,7 +172,7 @@ impl Component for VSplit {
|
|||
self.set_dirty();
|
||||
self.prev_visibility = visibility;
|
||||
}
|
||||
let right_entity_width = match visibility {
|
||||
let right_component_width = match visibility {
|
||||
(true, true) => (self.ratio * total_cols) / 100,
|
||||
(false, true) => total_cols,
|
||||
(true, false) => 0,
|
||||
|
@ -161,7 +182,7 @@ impl Component for VSplit {
|
|||
}
|
||||
};
|
||||
|
||||
let mid = get_x(bottom_right) - right_entity_width;
|
||||
let mid = get_x(bottom_right) - right_component_width;
|
||||
|
||||
if get_y(upper_left) > 1 {
|
||||
let c = grid
|
||||
|
@ -193,12 +214,12 @@ impl Component for VSplit {
|
|||
.push_back(((mid, get_y(upper_left)), (mid, get_y(bottom_right))));
|
||||
}
|
||||
|
||||
if right_entity_width == total_cols {
|
||||
self.right.component.draw(grid, area, context);
|
||||
} else if right_entity_width == 0 {
|
||||
self.left.component.draw(grid, area, context);
|
||||
if right_component_width == total_cols {
|
||||
self.right.draw(grid, area, context);
|
||||
} else if right_component_width == 0 {
|
||||
self.left.draw(grid, area, context);
|
||||
} else {
|
||||
self.left.component.draw(
|
||||
self.left.draw(
|
||||
grid,
|
||||
(
|
||||
upper_left,
|
||||
|
@ -210,22 +231,21 @@ impl Component for VSplit {
|
|||
context,
|
||||
);
|
||||
self.right
|
||||
.component
|
||||
.draw(grid, (set_x(upper_left, mid + 1), bottom_right), context);
|
||||
}
|
||||
}
|
||||
|
||||
fn process_event(&mut self, event: &mut UIEvent, context: &mut Context) -> bool {
|
||||
(self.left.rcv_event(event, context) || self.right.rcv_event(event, context))
|
||||
(self.left.process_event(event, context) || self.right.process_event(event, context))
|
||||
}
|
||||
|
||||
fn is_dirty(&self) -> bool {
|
||||
self.left.component.is_dirty() || self.right.component.is_dirty()
|
||||
self.left.is_dirty() || self.right.is_dirty()
|
||||
}
|
||||
|
||||
fn set_dirty(&mut self) {
|
||||
self.left.component.set_dirty();
|
||||
self.right.component.set_dirty();
|
||||
self.left.set_dirty();
|
||||
self.right.set_dirty();
|
||||
}
|
||||
|
||||
fn get_shortcuts(&self, context: &Context) -> ShortcutMap {
|
||||
|
@ -233,6 +253,13 @@ impl Component for VSplit {
|
|||
right_map.extend(self.left.get_shortcuts(context).into_iter());
|
||||
right_map
|
||||
}
|
||||
|
||||
fn id(&self) -> ComponentId {
|
||||
self.id
|
||||
}
|
||||
fn set_id(&mut self, id: ComponentId) {
|
||||
self.id = id;
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
@ -254,6 +281,7 @@ pub struct Pager {
|
|||
dirty: bool,
|
||||
content: CellBuffer,
|
||||
movement: Option<PageMovement>,
|
||||
id: ComponentId,
|
||||
}
|
||||
|
||||
impl fmt::Display for Pager {
|
||||
|
@ -524,12 +552,19 @@ impl Component for Pager {
|
|||
|
||||
map
|
||||
}
|
||||
|
||||
fn id(&self) -> ComponentId {
|
||||
self.id
|
||||
}
|
||||
fn set_id(&mut self, id: ComponentId) {
|
||||
self.id = id;
|
||||
}
|
||||
}
|
||||
|
||||
/// Status bar.
|
||||
#[derive(Debug)]
|
||||
pub struct StatusBar {
|
||||
container: Entity,
|
||||
container: Box<Component>,
|
||||
status: String,
|
||||
notifications: VecDeque<String>,
|
||||
ex_buffer: String,
|
||||
|
@ -537,6 +572,7 @@ pub struct StatusBar {
|
|||
mode: UIMode,
|
||||
height: usize,
|
||||
dirty: bool,
|
||||
id: ComponentId,
|
||||
}
|
||||
|
||||
impl fmt::Display for StatusBar {
|
||||
|
@ -547,7 +583,7 @@ impl fmt::Display for StatusBar {
|
|||
}
|
||||
|
||||
impl StatusBar {
|
||||
pub fn new(container: Entity) -> Self {
|
||||
pub fn new(container: Box<Component>) -> Self {
|
||||
StatusBar {
|
||||
container,
|
||||
status: String::with_capacity(256),
|
||||
|
@ -557,6 +593,7 @@ impl StatusBar {
|
|||
dirty: true,
|
||||
mode: UIMode::Normal,
|
||||
height: 1,
|
||||
id: ComponentId::default(),
|
||||
}
|
||||
}
|
||||
fn draw_status_bar(&mut self, grid: &mut CellBuffer, area: Area, context: &mut Context) {
|
||||
|
@ -615,7 +652,7 @@ impl Component for StatusBar {
|
|||
}
|
||||
let height = self.height;
|
||||
|
||||
self.container.component.draw(
|
||||
self.container.draw(
|
||||
grid,
|
||||
(
|
||||
upper_left,
|
||||
|
@ -649,7 +686,7 @@ impl Component for StatusBar {
|
|||
}
|
||||
}
|
||||
fn process_event(&mut self, event: &mut UIEvent, context: &mut Context) -> bool {
|
||||
if self.container.rcv_event(event, context) {
|
||||
if self.container.process_event(event, context) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -728,7 +765,7 @@ impl Component for StatusBar {
|
|||
false
|
||||
}
|
||||
fn is_dirty(&self) -> bool {
|
||||
self.dirty || self.container.component.is_dirty()
|
||||
self.dirty || self.container.is_dirty()
|
||||
}
|
||||
fn set_dirty(&mut self) {
|
||||
self.dirty = true;
|
||||
|
@ -737,40 +774,21 @@ impl Component for StatusBar {
|
|||
fn get_shortcuts(&self, context: &Context) -> ShortcutMap {
|
||||
self.container.get_shortcuts(context)
|
||||
}
|
||||
}
|
||||
|
||||
// A box with a text content.
|
||||
#[derive(Debug)]
|
||||
pub struct TextBox {
|
||||
_content: String,
|
||||
}
|
||||
|
||||
impl TextBox {
|
||||
pub fn new(s: String) -> Self {
|
||||
TextBox { _content: s }
|
||||
fn id(&self) -> ComponentId {
|
||||
self.id
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for TextBox {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
// TODO display info
|
||||
write!(f, "text box")
|
||||
fn set_id(&mut self, id: ComponentId) {
|
||||
self.id = id;
|
||||
}
|
||||
}
|
||||
|
||||
impl Component for TextBox {
|
||||
fn draw(&mut self, _grid: &mut CellBuffer, _area: Area, _context: &mut Context) {}
|
||||
fn process_event(&mut self, _event: &mut UIEvent, _context: &mut Context) -> bool {
|
||||
false
|
||||
}
|
||||
fn set_dirty(&mut self) {}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Progress {
|
||||
description: String,
|
||||
total_work: usize,
|
||||
finished: usize,
|
||||
id: ComponentId,
|
||||
}
|
||||
|
||||
impl Progress {
|
||||
|
@ -779,6 +797,7 @@ impl Progress {
|
|||
description: s,
|
||||
total_work,
|
||||
finished: 0,
|
||||
id: ComponentId::default(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -817,17 +836,25 @@ impl Component for Progress {
|
|||
false
|
||||
}
|
||||
fn set_dirty(&mut self) {}
|
||||
|
||||
fn id(&self) -> ComponentId {
|
||||
self.id
|
||||
}
|
||||
fn set_id(&mut self, id: ComponentId) {
|
||||
self.id = id;
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Tabbed {
|
||||
pinned: usize,
|
||||
children: Vec<Entity>,
|
||||
children: Vec<Box<Component>>,
|
||||
cursor_pos: usize,
|
||||
|
||||
show_shortcuts: bool,
|
||||
|
||||
dirty: bool,
|
||||
id: ComponentId,
|
||||
}
|
||||
|
||||
impl Tabbed {
|
||||
|
@ -835,10 +862,11 @@ impl Tabbed {
|
|||
let pinned = children.len();
|
||||
Tabbed {
|
||||
pinned,
|
||||
children: children.into_iter().map(Entity::from).collect(),
|
||||
children,
|
||||
cursor_pos: 0,
|
||||
show_shortcuts: false,
|
||||
dirty: true,
|
||||
id: ComponentId::default(),
|
||||
}
|
||||
}
|
||||
fn draw_tabs(&mut self, grid: &mut CellBuffer, area: Area, context: &mut Context) {
|
||||
|
@ -895,7 +923,7 @@ impl Tabbed {
|
|||
context.dirty_areas.push_back(area);
|
||||
}
|
||||
pub fn add_component(&mut self, new: Box<Component>) {
|
||||
self.children.push(Entity::from(new));
|
||||
self.children.push(new);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1027,7 +1055,7 @@ impl Component for Tabbed {
|
|||
if self.pinned > self.cursor_pos {
|
||||
return true;
|
||||
}
|
||||
let id = *self.children[self.cursor_pos].id();
|
||||
let id = self.children[self.cursor_pos].id();
|
||||
self.children[self.cursor_pos].kill(id);
|
||||
self.set_dirty();
|
||||
return true;
|
||||
|
@ -1036,14 +1064,14 @@ impl Component for Tabbed {
|
|||
if self.pinned > self.cursor_pos {
|
||||
return true;
|
||||
}
|
||||
if let Some(c_idx) = self.children.iter().position(|x| x.id() == id) {
|
||||
if let Some(c_idx) = self.children.iter().position(|x| x.id() == *id) {
|
||||
self.children.remove(c_idx);
|
||||
self.cursor_pos = self.cursor_pos.saturating_sub(1);
|
||||
self.set_dirty();
|
||||
return true;
|
||||
} else {
|
||||
eprintln!(
|
||||
"DEBUG: Child entity with id {:?} not found.\nList: {:?}",
|
||||
"DEBUG: Child component with id {:?} not found.\nList: {:?}",
|
||||
id, self.children
|
||||
);
|
||||
}
|
||||
|
@ -1059,6 +1087,13 @@ impl Component for Tabbed {
|
|||
self.dirty = true;
|
||||
self.children[self.cursor_pos].set_dirty();
|
||||
}
|
||||
|
||||
fn id(&self) -> ComponentId {
|
||||
self.id
|
||||
}
|
||||
fn set_id(&mut self, id: ComponentId) {
|
||||
self.id = id;
|
||||
}
|
||||
}
|
||||
|
||||
type EntryIdentifier = Vec<u8>;
|
||||
|
@ -1074,6 +1109,7 @@ pub struct Selector {
|
|||
cursor: usize,
|
||||
|
||||
dirty: bool,
|
||||
id: ComponentId,
|
||||
}
|
||||
|
||||
impl fmt::Display for Selector {
|
||||
|
@ -1136,6 +1172,13 @@ impl Component for Selector {
|
|||
fn set_dirty(&mut self) {
|
||||
self.dirty = true;
|
||||
}
|
||||
|
||||
fn id(&self) -> ComponentId {
|
||||
self.id
|
||||
}
|
||||
fn set_id(&mut self, id: ComponentId) {
|
||||
self.id = id;
|
||||
}
|
||||
}
|
||||
|
||||
impl Selector {
|
||||
|
@ -1170,6 +1213,7 @@ impl Selector {
|
|||
content,
|
||||
cursor: 0,
|
||||
dirty: true,
|
||||
id: ComponentId::default(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -187,6 +187,11 @@ impl Component for Field {
|
|||
true
|
||||
}
|
||||
fn set_dirty(&mut self) {}
|
||||
|
||||
fn id(&self) -> ComponentId {
|
||||
ComponentId::nil()
|
||||
}
|
||||
fn set_id(&mut self, _id: ComponentId) {}
|
||||
}
|
||||
|
||||
impl fmt::Display for Field {
|
||||
|
@ -206,6 +211,7 @@ pub struct FormWidget {
|
|||
focus: FormFocus,
|
||||
hide_buttons: bool,
|
||||
dirty: bool,
|
||||
id: ComponentId,
|
||||
}
|
||||
|
||||
impl fmt::Display for FormWidget {
|
||||
|
@ -441,6 +447,13 @@ impl Component for FormWidget {
|
|||
fn set_dirty(&mut self) {
|
||||
self.dirty = true;
|
||||
}
|
||||
|
||||
fn id(&self) -> ComponentId {
|
||||
self.id
|
||||
}
|
||||
fn set_id(&mut self, id: ComponentId) {
|
||||
self.id = id;
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
|
@ -453,6 +466,7 @@ where
|
|||
|
||||
result: Option<T>,
|
||||
cursor: usize,
|
||||
id: ComponentId,
|
||||
}
|
||||
|
||||
impl<T> fmt::Display for ButtonWidget<T>
|
||||
|
@ -474,6 +488,7 @@ where
|
|||
buttons: vec![init_val].into_iter().collect(),
|
||||
result: None,
|
||||
cursor: 0,
|
||||
id: ComponentId::default(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -542,6 +557,13 @@ where
|
|||
true
|
||||
}
|
||||
fn set_dirty(&mut self) {}
|
||||
|
||||
fn id(&self) -> ComponentId {
|
||||
self.id
|
||||
}
|
||||
fn set_id(&mut self, id: ComponentId) {
|
||||
self.id = id;
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
|
@ -551,6 +573,7 @@ pub struct AutoComplete {
|
|||
cursor: usize,
|
||||
|
||||
dirty: bool,
|
||||
id: ComponentId,
|
||||
}
|
||||
|
||||
impl fmt::Display for AutoComplete {
|
||||
|
@ -595,6 +618,13 @@ impl Component for AutoComplete {
|
|||
fn set_dirty(&mut self) {
|
||||
self.dirty = true;
|
||||
}
|
||||
|
||||
fn id(&self) -> ComponentId {
|
||||
self.id
|
||||
}
|
||||
fn set_id(&mut self, id: ComponentId) {
|
||||
self.id = id;
|
||||
}
|
||||
}
|
||||
|
||||
impl AutoComplete {
|
||||
|
@ -604,6 +634,7 @@ impl AutoComplete {
|
|||
content: CellBuffer::default(),
|
||||
cursor: 0,
|
||||
dirty: true,
|
||||
id: ComponentId::default(),
|
||||
};
|
||||
ret.set_suggestions(entries);
|
||||
ret
|
||||
|
|
|
@ -21,9 +21,9 @@
|
|||
|
||||
/*! The application's state.
|
||||
|
||||
The UI crate has an Entity-Component-System design. The System part, is also the application's state, so they're both merged in the `State` struct.
|
||||
The UI crate has an Box<Component>-Component-System design. The System part, is also the application's state, so they're both merged in the `State` struct.
|
||||
|
||||
`State` owns all the Entities of the UI, which are currently plain Containers for `Component`s. In the application's main event loop, input is handed to the state in the form of `UIEvent` objects which traverse the entity graph. Components decide to handle each input or not.
|
||||
`State` owns all the Components of the UI. In the application's main event loop, input is handed to the state in the form of `UIEvent` objects which traverse the component graph. Components decide to handle each input or not.
|
||||
|
||||
Input is received in the main loop from threads which listen on the stdin for user input, observe folders for file changes etc. The relevant struct is `ThreadEvent`.
|
||||
*/
|
||||
|
@ -115,7 +115,7 @@ impl Context {
|
|||
}
|
||||
}
|
||||
|
||||
/// A State object to manage and own components and entities of the UI. `State` is responsible for
|
||||
/// A State object to manage and own components and components of the UI. `State` is responsible for
|
||||
/// managing the terminal and interfacing with `melib`
|
||||
pub struct State {
|
||||
cols: usize,
|
||||
|
@ -125,7 +125,7 @@ pub struct State {
|
|||
stdout: Option<StateStdout>,
|
||||
child: Option<ForkType>,
|
||||
pub mode: UIMode,
|
||||
entities: Vec<Entity>,
|
||||
components: Vec<Box<Component>>,
|
||||
pub context: Context,
|
||||
threads: FnvHashMap<thread::ThreadId, (chan::Sender<bool>, thread::JoinHandle<()>)>,
|
||||
work_controller: WorkController,
|
||||
|
@ -199,7 +199,7 @@ impl State {
|
|||
stdout: Some(stdout),
|
||||
child: None,
|
||||
mode: UIMode::Normal,
|
||||
entities: Vec::with_capacity(1),
|
||||
components: Vec::with_capacity(1),
|
||||
|
||||
context: Context {
|
||||
accounts,
|
||||
|
@ -376,8 +376,8 @@ impl State {
|
|||
|
||||
/// Force a redraw for all dirty components.
|
||||
pub fn redraw(&mut self) {
|
||||
for i in 0..self.entities.len() {
|
||||
self.draw_entity(i);
|
||||
for i in 0..self.components.len() {
|
||||
self.draw_component(i);
|
||||
}
|
||||
let areas: Vec<Area> = self.context.dirty_areas.drain(0..).collect();
|
||||
/* draw each dirty area */
|
||||
|
@ -433,30 +433,30 @@ impl State {
|
|||
pub fn render(&mut self) {
|
||||
self.update_size();
|
||||
|
||||
/* draw each entity */
|
||||
for i in 0..self.entities.len() {
|
||||
self.draw_entity(i);
|
||||
/* draw each component */
|
||||
for i in 0..self.components.len() {
|
||||
self.draw_component(i);
|
||||
}
|
||||
let cols = self.cols;
|
||||
let rows = self.rows;
|
||||
|
||||
self.draw_area(((0, 0), (cols - 1, rows - 1)));
|
||||
}
|
||||
pub fn draw_entity(&mut self, idx: usize) {
|
||||
let entity = &mut self.entities[idx];
|
||||
pub fn draw_component(&mut self, idx: usize) {
|
||||
let component = &mut self.components[idx];
|
||||
let upper_left = (0, 0);
|
||||
let bottom_right = (self.cols - 1, self.rows - 1);
|
||||
|
||||
if entity.component.is_dirty() {
|
||||
entity.component.draw(
|
||||
if component.is_dirty() {
|
||||
component.draw(
|
||||
&mut self.grid,
|
||||
(upper_left, bottom_right),
|
||||
&mut self.context,
|
||||
);
|
||||
}
|
||||
}
|
||||
pub fn register_entity(&mut self, entity: Entity) {
|
||||
self.entities.push(entity);
|
||||
pub fn register_component(&mut self, component: Box<Component>) {
|
||||
self.components.push(component);
|
||||
}
|
||||
/// Convert user commands to actions/method calls.
|
||||
fn parse_command(&mut self, cmd: &str) {
|
||||
|
@ -499,9 +499,9 @@ impl State {
|
|||
}
|
||||
_ => {}
|
||||
}
|
||||
/* inform each entity */
|
||||
for i in 0..self.entities.len() {
|
||||
self.entities[i].rcv_event(&mut event, &mut self.context);
|
||||
/* inform each component */
|
||||
for i in 0..self.components.len() {
|
||||
self.components[i].process_event(&mut event, &mut self.context);
|
||||
}
|
||||
|
||||
if !self.context.replies.is_empty() {
|
||||
|
|
|
@ -84,7 +84,7 @@ pub enum UIEventType {
|
|||
Action(Action),
|
||||
StatusEvent(StatusEvent),
|
||||
MailboxUpdate((usize, usize)), // (account_idx, mailbox_idx)
|
||||
EntityKill(Uuid),
|
||||
ComponentKill(Uuid),
|
||||
StartupCheck(FolderHash),
|
||||
RefreshEvent(Box<RefreshEvent>),
|
||||
EnvelopeUpdate(EnvelopeHash),
|
||||
|
|
Loading…
Reference in New Issue