Open Contacts list from accounts tab

embed
Manos Pitsidianakis 2019-02-26 17:50:47 +02:00
parent 00abea5bff
commit e285d1006b
Signed by: Manos Pitsidianakis
GPG Key ID: 73627C2F690DF710
23 changed files with 70 additions and 38 deletions

View File

@ -24,7 +24,7 @@ use fnv::FnvHashMap;
use std::ops::Deref;
type CardId = Uuid;
pub type CardId = Uuid;
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
pub struct AddressBook {

View File

@ -136,8 +136,8 @@ impl Entity {
&self.id
}
/// Pass events to child component.
pub fn rcv_event(&mut self, event: &UIEvent, context: &mut Context) -> bool {
self.component.process_event(&event, context)
pub fn rcv_event(&mut self, event: &mut UIEvent, context: &mut Context) -> bool {
self.component.process_event(event, context)
}
}
@ -146,7 +146,7 @@ impl Entity {
/// fields (eg self.dirty = false) and act upon that in their `draw` implementation.
pub trait Component: Display + Debug + Send {
fn draw(&mut self, grid: &mut CellBuffer, area: Area, context: &mut Context);
fn process_event(&mut self, event: &UIEvent, context: &mut Context) -> bool;
fn process_event(&mut self, event: &mut UIEvent, context: &mut Context) -> bool;
fn is_dirty(&self) -> bool {
true
}

View File

@ -123,7 +123,7 @@ impl Component for ContactManager {
context.dirty_areas.push_back(area);
}
fn process_event(&mut self, event: &UIEvent, context: &mut Context) -> bool {
fn process_event(&mut self, event: &mut UIEvent, context: &mut Context) -> bool {
if self.form.process_event(event, context) {
match self.form.buttons_result() {
None => {},

View File

@ -1,11 +1,13 @@
use super::*;
use melib::CardId;
const MAX_COLS: usize = 500;
#[derive(Debug, PartialEq)]
enum ViewMode {
List,
View(EntityId),
View(CardId),
}
#[derive(Debug)]
@ -16,7 +18,7 @@ pub struct ContactList {
length: usize,
content: CellBuffer,
id_positions: Vec<EntityId>,
id_positions: Vec<CardId>,
mode: ViewMode,
dirty: bool,
@ -51,6 +53,13 @@ impl ContactList {
}
}
pub fn for_account(pos: usize) -> Self {
ContactList {
account_pos: pos,
..Self::new()
}
}
fn initialize(&mut self, context: &mut Context) {
let account = &mut context.accounts[self.account_pos];
let book = &mut account.address_book;
@ -106,13 +115,23 @@ impl Component for ContactList {
self.cursor_pos = self.new_cursor_pos;
}
fn process_event(&mut self, event: &UIEvent, context: &mut Context) -> bool {
fn process_event(&mut self, event: &mut UIEvent, context: &mut Context) -> bool {
if let Some(ref mut v) = self.view {
if v.process_event(event, context) {
return true;
}
}
match event.event_type {
UIEventType::Input(Key::Char('c')) => {
let mut manager = ContactManager::default();
manager.account_pos = self.account_pos;
let entity = Entity::from(Box::new(manager));
self.mode = ViewMode::View(*entity.id());
self.view = Some(entity);
return true;
},
UIEventType::Input(Key::Char('e')) if self.length > 0 => {
let account = &mut context.accounts[self.account_pos];
let book = &mut account.address_book;

View File

@ -91,7 +91,7 @@ impl Component for Indexer {
context.dirty_areas.push_back(area);
}
fn process_event(&mut self, event: &UIEvent, _context: &mut Context) -> bool {
fn process_event(&mut self, event: &mut UIEvent, _context: &mut Context) -> bool {
if !self.entries[self.cursor[0]]
.index
.process_event(event, _context)

View File

@ -123,7 +123,7 @@ impl Component for Index {
return;
}
fn process_event(&mut self, event: &UIEvent, context: &mut Context) -> bool {
fn process_event(&mut self, event: &mut UIEvent, context: &mut Context) -> bool {
if self.content.process_event(event, context) {
return true;
}

View File

@ -257,7 +257,7 @@ impl Component for AccountMenu {
context.dirty_areas.push_back(area);
}
fn process_event(&mut self, event: &UIEvent, _context: &mut Context) -> bool {
fn process_event(&mut self, event: &mut UIEvent, _context: &mut Context) -> bool {
match event.event_type {
UIEventType::RefreshMailbox(c) => {
self.cursor = Some(c);

View File

@ -119,7 +119,7 @@ impl Component for AccountsPanel {
copy_area(grid, &self.content, area, ((0, 0), (width - 1, height - 1)));
context.dirty_areas.push_back(area);
}
fn process_event(&mut self, event: &UIEvent, context: &mut Context) -> bool {
fn process_event(&mut self, event: &mut UIEvent, context: &mut Context) -> bool {
match event.event_type {
UIEventType::Input(Key::Up) => {
self.cursor = self.cursor.saturating_sub(1);
@ -133,6 +133,13 @@ impl Component for AccountsPanel {
}
return true;
},
UIEventType::Input(Key::Char('\n')) => {
context.replies.push_back(UIEvent {
id: 0,
event_type: UIEventType::Action(Tab(TabOpen(Some(Box::new(ContactList::for_account(self.cursor)))
)))});
return true;
},
_ => {},
}

View File

@ -45,7 +45,7 @@ impl Component for ContactsPanel {
copy_area(grid, &self.content, area, ((0, 0), (width - 1, height - 1)));
context.dirty_areas.push_back(area);
}
fn process_event(&mut self, _event: &UIEvent, _context: &mut Context) -> bool {
fn process_event(&mut self, _event: &mut UIEvent, _context: &mut Context) -> bool {
false
}
fn is_dirty(&self) -> bool {

View File

@ -387,7 +387,7 @@ impl Component for Composer {
context.dirty_areas.push_back(area);
}
fn process_event(&mut self, event: &UIEvent, context: &mut Context) -> bool {
fn process_event(&mut self, event: &mut UIEvent, context: &mut Context) -> bool {
match (&mut self.mode, &mut self.reply_context) {
(ViewMode::Pager, _) => {
/* Cannot mutably borrow in pattern guard, pah! */

View File

@ -61,7 +61,7 @@ impl Component for Listing {
Listing::Threaded(l) => l.draw(grid, area, context),
}
}
fn process_event(&mut self, event: &UIEvent, context: &mut Context) -> bool {
fn process_event(&mut self, event: &mut UIEvent, context: &mut Context) -> bool {
if match self {
Listing::Plain(l) => l.process_event(event, context),
Listing::Compact(l) => l.process_event(event, context),

View File

@ -381,7 +381,7 @@ impl Component for CompactListing {
}
self.dirty = false;
}
fn process_event(&mut self, event: &UIEvent, context: &mut Context) -> bool {
fn process_event(&mut self, event: &mut UIEvent, context: &mut Context) -> bool {
if let Some(ref mut v) = self.view {
if v.process_event(event, context) {
return true;

View File

@ -417,7 +417,7 @@ impl Component for PlainListing {
self.dirty = false;
}
}
fn process_event(&mut self, event: &UIEvent, context: &mut Context) -> bool {
fn process_event(&mut self, event: &mut UIEvent, context: &mut Context) -> bool {
if let Some(ref mut v) = self.view {
if v.process_event(event, context) {
return true;

View File

@ -550,7 +550,7 @@ impl Component for ThreadListing {
self.dirty = false;
}
}
fn process_event(&mut self, event: &UIEvent, context: &mut Context) -> bool {
fn process_event(&mut self, event: &mut UIEvent, context: &mut Context) -> bool {
if let Some(ref mut v) = self.view {
if v.process_event(event, context) {
return true;

View File

@ -360,7 +360,7 @@ impl Component for MailView {
}
}
fn process_event(&mut self, event: &UIEvent, context: &mut Context) -> bool {
fn process_event(&mut self, event: &mut UIEvent, context: &mut Context) -> bool {
match self.mode {
ViewMode::Subview => {
if let Some(s) = self.subview.as_mut() {
@ -414,7 +414,7 @@ impl Component for MailView {
let envelope: &Envelope = &mailbox.collection[&self.coordinates.2];
let mut entries = Vec::new();
entries.push((envelope.from()[0].get_email().into_bytes(), format!("{}", envelope.from()[0])));
entries.push((String::from("foo@bar.de").into_bytes(), String::from("Johann de Vir <foo@bar.de>")));
entries.push((envelope.to()[0].get_email().into_bytes(), format!("{}", envelope.to()[0])));
self.mode = ViewMode::ContactSelector(Selector::new(entries, true));
self.dirty = true;
//context.accounts.context(self.coordinates.0).address_book.add_card(new_card);

View File

@ -315,7 +315,7 @@ impl Component for EnvelopeView {
}
}
fn process_event(&mut self, event: &UIEvent, context: &mut Context) -> bool {
fn process_event(&mut self, event: &mut UIEvent, context: &mut Context) -> bool {
if let Some(ref mut sub) = self.subview {
if sub.process_event(event, context) {
return true;

View File

@ -66,7 +66,7 @@ impl Component for HtmlView {
fn draw(&mut self, grid: &mut CellBuffer, area: Area, context: &mut Context) {
self.pager.draw(grid, area, context);
}
fn process_event(&mut self, event: &UIEvent, context: &mut Context) -> bool {
fn process_event(&mut self, event: &mut UIEvent, context: &mut Context) -> bool {
if self.pager.process_event(event, context) {
return true;
}

View File

@ -540,7 +540,7 @@ impl Component for ThreadView {
self.draw_horz(grid, area, context);
}
}
fn process_event(&mut self, event: &UIEvent, context: &mut Context) -> bool {
fn process_event(&mut self, event: &mut UIEvent, context: &mut Context) -> bool {
if self.mailview.process_event(event, context) {
return true;
}

View File

@ -39,7 +39,7 @@ impl fmt::Display for XDGNotifications {
impl Component for XDGNotifications {
fn draw(&mut self, _grid: &mut CellBuffer, _area: Area, _context: &mut Context) {}
fn process_event(&mut self, event: &UIEvent, _context: &mut Context) -> bool {
fn process_event(&mut self, event: &mut UIEvent, _context: &mut Context) -> bool {
if let UIEventType::Notification(ref title, ref body) = event.event_type {
notify_Notification::new()
.appname("meli")

View File

@ -88,7 +88,7 @@ impl Component for HSplit {
context,
);
}
fn process_event(&mut self, event: &UIEvent, context: &mut Context) -> bool {
fn process_event(&mut self, event: &mut UIEvent, context: &mut Context) -> bool {
self.top.rcv_event(event, context) || self.bottom.rcv_event(event, context)
}
fn is_dirty(&self) -> bool {
@ -175,7 +175,7 @@ impl Component for VSplit {
.component
.draw(grid, ((mid + 1, get_y(upper_left)), bottom_right), context);
}
fn process_event(&mut self, event: &UIEvent, context: &mut Context) -> bool {
fn process_event(&mut self, event: &mut UIEvent, context: &mut Context) -> bool {
(self.left.rcv_event(event, context) || self.right.rcv_event(event, context))
}
fn is_dirty(&self) -> bool {
@ -380,7 +380,7 @@ impl Component for Pager {
}
context.dirty_areas.push_back(area);
}
fn process_event(&mut self, event: &UIEvent, _context: &mut Context) -> bool {
fn process_event(&mut self, event: &mut UIEvent, context: &mut Context) -> bool {
match event.event_type {
UIEventType::Input(Key::Char('k')) => {
if self.cursor_pos > 0 {
@ -547,7 +547,7 @@ impl Component for StatusBar {
_ => {}
}
}
fn process_event(&mut self, event: &UIEvent, context: &mut Context) -> bool {
fn process_event(&mut self, event: &mut UIEvent, context: &mut Context) -> bool {
if self.container.rcv_event(event, context) {
return true;
}
@ -655,7 +655,7 @@ impl fmt::Display for TextBox {
impl Component for TextBox {
fn draw(&mut self, _grid: &mut CellBuffer, _area: Area, _context: &mut Context) {}
fn process_event(&mut self, _event: &UIEvent, _context: &mut Context) -> bool {
fn process_event(&mut self, _event: &mut UIEvent, _context: &mut Context) -> bool {
false
}
fn set_dirty(&mut self) {}
@ -708,7 +708,7 @@ impl Component for Progress {
fn draw(&mut self, _grid: &mut CellBuffer, _area: Area, _context: &mut Context) {
unimplemented!()
}
fn process_event(&mut self, _event: &UIEvent, _context: &mut Context) -> bool {
fn process_event(&mut self, _event: &mut UIEvent, _context: &mut Context) -> bool {
false
}
fn set_dirty(&mut self) {}
@ -792,7 +792,7 @@ impl Component for Tabbed {
self.children[self.cursor_pos].draw(grid, area, context);
}
}
fn process_event(&mut self, event: &UIEvent, context: &mut Context) -> bool {
fn process_event(&mut self, event: &mut UIEvent, context: &mut Context) -> bool {
match event.event_type {
UIEventType::Input(Key::Char('T')) => {
self.cursor_pos = (self.cursor_pos + 1) % self.children.len();
@ -811,6 +811,12 @@ impl Component for Tabbed {
self.children[self.cursor_pos].set_dirty();
return true;
}
UIEventType::Action(Tab(TabOpen(ref mut e))) if e.is_some() => {
self.add_component(e.take().unwrap());
self.cursor_pos = self.children.len() - 1;
self.children[self.cursor_pos].set_dirty();
return true;
}
UIEventType::Action(Tab(Close)) => {
let id = *self.children[self.cursor_pos].id();
self.children[self.cursor_pos].kill(id);
@ -874,7 +880,7 @@ impl Component for Selector {
);
context.dirty_areas.push_back(area);
}
fn process_event(&mut self, event: &UIEvent, context: &mut Context) -> bool {
fn process_event(&mut self, event: &mut UIEvent, context: &mut Context) -> bool {
let (width, height) = self.content.size();
match event.event_type {
UIEventType::Input(Key::Char(' ')) => {

View File

@ -120,7 +120,7 @@ impl Component for FormWidget {
self.dirty = false;
context.dirty_areas.push_back(area);
}
fn process_event(&mut self, event: &UIEvent, context: &mut Context) -> bool {
fn process_event(&mut self, event: &mut UIEvent, context: &mut Context) -> bool {
if self.focus == FormFocus::Buttons {
if self.buttons.process_event(event, context) {
return true;
@ -256,7 +256,7 @@ impl<T> Component for ButtonWidget<T> where T: std::fmt::Debug + Default + Send
len += cur_len + 3;
}
}
fn process_event(&mut self, event: &UIEvent, context: &mut Context) -> bool {
fn process_event(&mut self, event: &mut UIEvent, context: &mut Context) -> bool {
match event.event_type {
UIEventType::Input(Key::Char('\n')) => {
self.result = Some(self.buttons.remove(&self.layout[self.cursor]).unwrap_or_default());

View File

@ -24,7 +24,7 @@
*/
pub use melib::mailbox::{SortField, SortOrder};
use components::Entity;
use components::Component;
extern crate uuid;
use uuid::Uuid;
@ -38,7 +38,7 @@ pub enum ListingAction {
#[derive(Debug, )]
pub enum TabAction {
EntityOpen(Entity),
TabOpen(Option<Box<Component>>),
NewDraft,
Reply((usize, usize, usize), usize), // thread coordinates (account, mailbox, root_set idx) and message idx
Close,

View File

@ -453,7 +453,7 @@ impl State {
}
/// The application's main loop sends `UIEvents` to state via this method.
pub fn rcv_event(&mut self, event: UIEvent) {
pub fn rcv_event(&mut self, mut event: UIEvent) {
match event.event_type {
// Command type is handled only by State.
UIEventType::Command(cmd) => {
@ -483,7 +483,7 @@ impl State {
}
/* inform each entity */
for i in 0..self.entities.len() {
self.entities[i].rcv_event(&event, &mut self.context);
self.entities[i].rcv_event(&mut event, &mut self.context);
}
if !self.context.replies.is_empty() {