email-client

A gtk4 Email Client
git clone git://archive.git.mtrnord.blog/erooster-mail/email-client.git
Log | Files | Refs | LICENSE

folder_view.rs (5287B)


      1 use gtk::{prelude::*, Align};
      2 use relm4::{factory::FactoryVecDeque, prelude::*};
      3 
      4 pub struct MailboxesView {
      5     mailboxes: FactoryVecDeque<Mailbox>,
      6 }
      7 
      8 pub struct MailboxesInit {
      9     pub mailboxes: Vec<MailboxInit>,
     10 }
     11 
     12 #[derive(Debug)]
     13 pub enum MailboxesMsg {
     14     AddMailbox(MailboxInit),
     15     // TODO: Is this the correct type?
     16     RemoveMailbox(MailboxInit),
     17 }
     18 
     19 #[relm4::component(pub)]
     20 impl SimpleComponent for MailboxesView {
     21     type Init = MailboxesInit;
     22     type Input = MailboxesMsg;
     23     type Output = ();
     24 
     25     view! {
     26         gtk::ScrolledWindow {
     27             set_propagate_natural_width: true,
     28             set_hscrollbar_policy: gtk::PolicyType::Never,
     29 
     30             #[local_ref]
     31             mailbox_list_box -> gtk::Box {}
     32         }
     33     }
     34 
     35     fn init(
     36         init: Self::Init,
     37         root: &Self::Root,
     38         sender: ComponentSender<Self>,
     39     ) -> ComponentParts<Self> {
     40         let mut model = MailboxesView {
     41             mailboxes: FactoryVecDeque::new(gtk::Box::default(), sender.input_sender()),
     42         };
     43 
     44         for mailbox in init.mailboxes {
     45             model.mailboxes.guard().push_back(mailbox);
     46         }
     47         let mailbox_list_box = model.mailboxes.widget();
     48         let widgets = view_output!();
     49 
     50         ComponentParts { model, widgets }
     51     }
     52 
     53     fn update(&mut self, msg: MailboxesMsg, _sender: ComponentSender<Self>) {
     54         match msg {
     55             MailboxesMsg::AddMailbox(mailbox) => self.mailboxes.guard().push_back(mailbox),
     56             MailboxesMsg::RemoveMailbox(mailbox) => todo!(),
     57         };
     58     }
     59 }
     60 
     61 struct Mailbox {
     62     icon_name: String,
     63     mailbox_name: String,
     64     folders: FactoryVecDeque<Folder>,
     65 }
     66 
     67 #[derive(Debug)]
     68 enum MailboxInput {
     69     SetIconName(String),
     70     SetName(String),
     71 }
     72 
     73 #[derive(Debug)]
     74 pub struct MailboxInit {
     75     pub icon_name: String,
     76     pub mailbox_name: String,
     77     pub folders: Vec<FolderInit>,
     78 }
     79 
     80 #[relm4::factory]
     81 impl FactoryComponent for Mailbox {
     82     type Init = MailboxInit;
     83     type Input = MailboxInput;
     84     type Output = ();
     85     type CommandOutput = ();
     86     type ParentInput = MailboxesMsg;
     87     type ParentWidget = gtk::Box;
     88 
     89     view! {
     90         root = gtk::Expander {
     91             set_expanded: true,
     92             set_halign: Align::Fill,
     93             set_hexpand: true,
     94             #[wrap(Some)]
     95             set_label_widget = &gtk::Box {
     96                 gtk::Image {
     97                     set_margin_end: 8,
     98                     #[watch]
     99                     set_from_icon_name: Some(&self.icon_name)
    100                 },
    101                 gtk::Label {
    102                     #[watch]
    103                     set_label: &self.mailbox_name,
    104                 }
    105             },
    106 
    107             #[wrap(Some)]
    108             set_child = self.folders.widget(),
    109         }
    110     }
    111 
    112     fn init_model(value: Self::Init, _index: &DynamicIndex, sender: FactorySender<Self>) -> Self {
    113         let box_parent = gtk::ListBox::default();
    114         box_parent.set_halign(Align::Fill);
    115         let mut model = Self {
    116             icon_name: value.icon_name,
    117             mailbox_name: value.mailbox_name,
    118             folders: FactoryVecDeque::new(box_parent, sender.input_sender()),
    119         };
    120 
    121         for folder in value.folders {
    122             model.folders.guard().push_back(folder);
    123         }
    124 
    125         model
    126     }
    127 
    128     fn update(&mut self, msg: Self::Input, _sender: FactorySender<Self>) {
    129         match msg {
    130             MailboxInput::SetIconName(icon_name) => {
    131                 self.icon_name = icon_name;
    132             }
    133             MailboxInput::SetName(mailbox_name) => {
    134                 self.mailbox_name = mailbox_name;
    135             } // TODO: Add and Remove Folders
    136         }
    137     }
    138 }
    139 
    140 struct Folder {
    141     icon_name: String,
    142     folder_name: String,
    143     pub depth: i32,
    144 }
    145 
    146 #[derive(Debug)]
    147 enum FolderInput {
    148     SetIconName(String),
    149     SetName(String),
    150 }
    151 
    152 #[derive(Debug)]
    153 pub struct FolderInit {
    154     pub icon_name: String,
    155     pub folder_name: String,
    156     pub depth: i32,
    157 }
    158 
    159 #[relm4::factory]
    160 impl FactoryComponent for Folder {
    161     type Init = FolderInit;
    162     type Input = FolderInput;
    163     type Output = ();
    164     type CommandOutput = ();
    165     type ParentInput = MailboxInput;
    166     type ParentWidget = gtk::ListBox;
    167 
    168     view! {
    169         root = gtk::ListBoxRow {
    170             set_halign: Align::Fill,
    171 
    172             gtk::Box {
    173                 set_margin_start: 40_i32*self.depth,
    174                 set_halign: Align::Fill,
    175                 gtk::Image {
    176                     set_margin_end: 8,
    177                     #[watch]
    178                     set_from_icon_name: Some(&self.icon_name)
    179                 },
    180                 gtk::Label {
    181                     #[watch]
    182                     set_label: &self.folder_name,
    183                 }
    184             }
    185         }
    186     }
    187 
    188     fn init_model(value: Self::Init, _index: &DynamicIndex, _sender: FactorySender<Self>) -> Self {
    189         Self {
    190             depth: value.depth,
    191             icon_name: value.icon_name,
    192             folder_name: value.folder_name,
    193         }
    194     }
    195 
    196     fn update(&mut self, msg: Self::Input, _sender: FactorySender<Self>) {
    197         match msg {
    198             FolderInput::SetIconName(icon_name) => {
    199                 self.icon_name = icon_name;
    200             }
    201             FolderInput::SetName(folder_name) => {
    202                 self.folder_name = folder_name;
    203             }
    204         }
    205     }
    206 }