From 08e49b63c162f16cb35262cd48da324c779c1a1c Mon Sep 17 00:00:00 2001
From: Clement Tsang <34804052+ClementTsang@users.noreply.github.com>
Date: Sun, 16 Aug 2020 01:25:59 -0700
Subject: [PATCH] refactor: Revert tui upgrade to 0.10

Reverts tui upgrade, there are some bugs and issues - namely, issues with rendering text.
We can revert this commit when those bugs are dealt with (should be fine after 0.10.1, tested building from the repo).
---
 Cargo.lock                               |   6 +-
 Cargo.toml                               |   2 +-
 src/canvas.rs                            |  73 +++++----
 src/canvas/canvas_colours.rs             |   2 +-
 src/canvas/dialogs/dd_dialog.rs          | 149 ++++++++++--------
 src/canvas/dialogs/help_dialog.rs        |  36 +++--
 src/canvas/widgets/basic_table_arrows.rs |  15 +-
 src/canvas/widgets/battery_display.rs    | 128 +++++++++++----
 src/canvas/widgets/cpu_basic.rs          |  22 +--
 src/canvas/widgets/cpu_graph.rs          |  47 ++++--
 src/canvas/widgets/disk_table.rs         |  46 ++++--
 src/canvas/widgets/mem_basic.rs          |  13 +-
 src/canvas/widgets/mem_graph.rs          |  50 +++---
 src/canvas/widgets/network_basic.rs      |  28 ++--
 src/canvas/widgets/network_graph.rs      |  55 ++++---
 src/canvas/widgets/process_table.rs      |  80 +++++-----
 src/canvas/widgets/temp_table.rs         |  30 ++--
 src/constants.rs                         | 188 +++++++++++------------
 18 files changed, 546 insertions(+), 424 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index a89748a1..7d2b4099 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1345,13 +1345,15 @@ checksum = "a7f741b240f1a48843f9b8e0444fb55fb2a4ff67293b50a9179dfd5ea67f8d41"
 
 [[package]]
 name = "tui"
-version = "0.10.0"
+version = "0.9.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a977b0bb2e2033a6fef950f218f13622c3c34e59754b704ce3492dedab1dfe95"
+checksum = "9533d39bef0ae8f510e8a99d78702e68d1bbf0b98a78ec9740509d287010ae1e"
 dependencies = [
  "bitflags",
  "cassowary",
  "crossterm",
+ "either",
+ "itertools",
  "unicode-segmentation",
  "unicode-width",
 ]
diff --git a/Cargo.toml b/Cargo.toml
index 1b225266..282d1e6e 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -39,7 +39,7 @@ serde = {version = "1.0", features = ["derive"] }
 unicode-segmentation = "1.6.0"
 unicode-width = "0.1.7"
 # tui = {version = "0.10.0", features = ["crossterm"], default-features = false, git = "https://github.com/fdehau/tui-rs.git"}
-tui = {version = "0.10.0", features = ["crossterm"], default-features = false }
+tui = {version = "0.9.5", features = ["crossterm"], default-features = false }
 
 # For debugging only...
 fern = "0.6.0"
diff --git a/src/canvas.rs b/src/canvas.rs
index 8ff9c31b..563651b8 100644
--- a/src/canvas.rs
+++ b/src/canvas.rs
@@ -4,7 +4,7 @@ use std::collections::HashMap;
 use tui::{
     backend::Backend,
     layout::{Constraint, Direction, Layout, Rect},
-    text::{Span, Spans},
+    widgets::Text,
     Frame, Terminal,
 };
 
@@ -55,7 +55,7 @@ pub struct Painter {
     pub colours: CanvasColours,
     height: u16,
     width: u16,
-    styled_help_text: Vec<Spans<'static>>,
+    styled_help_text: Vec<Text<'static>>,
     is_mac_os: bool,
     row_constraints: Vec<Constraint>,
     col_constraints: Vec<Vec<Constraint>>,
@@ -163,27 +163,28 @@ impl Painter {
                 styled_help_spans.extend(
                     section
                         .iter()
-                        .map(|&text| Span::styled(text, self.colours.text_style))
+                        .map(|&text| Text::styled(text, self.colours.text_style))
                         .collect::<Vec<_>>(),
                 );
             } else {
                 // Not required check but it runs only a few times... so whatever ig, prevents me from
                 // being dumb and leaving a help text section only one line long.
                 if section.len() > 1 {
-                    styled_help_spans.push(Span::from(""));
+                    styled_help_spans.push(Text::raw("\n\n"));
                     styled_help_spans
-                        .push(Span::styled(section[0], self.colours.table_header_style));
+                        .push(Text::styled(section[0], self.colours.table_header_style));
                     styled_help_spans.extend(
                         section[1..]
                             .iter()
-                            .map(|&text| Span::styled(text, self.colours.text_style))
+                            .map(|&text| Text::styled(text, self.colours.text_style))
                             .collect::<Vec<_>>(),
                     );
                 }
             }
         });
 
-        self.styled_help_text = styled_help_spans.into_iter().map(Spans::from).collect();
+        // self.styled_help_text = styled_help_spans.into_iter().map(Spans::from).collect();
+        self.styled_help_text = styled_help_spans;
     }
 
     pub fn draw_data<B: Backend>(
@@ -251,36 +252,44 @@ impl Painter {
 
                 let dd_text = self.get_dd_spans(app_state);
 
-                let (text_width, text_height) = if let Some(dd_text) = &dd_text {
-                    let width = if f.size().width < 100 {
+                let (text_width, text_height) = (
+                    if f.size().width < 100 {
                         f.size().width * 90 / 100
                     } else {
-                        let min_possible_width = (f.size().width * 50 / 100) as usize;
-                        let mut width = dd_text.width();
+                        f.size().width * 50 / 100
+                    },
+                    7,
+                );
+                // let (text_width, text_height) = if let Some(dd_text) = &dd_text {
+                //     let width = if f.size().width < 100 {
+                //         f.size().width * 90 / 100
+                //     } else {
+                //         let min_possible_width = (f.size().width * 50 / 100) as usize;
+                //         let mut width = dd_text.width();
 
-                        // This should theoretically never allow width to be 0... we can be safe and do an extra check though.
-                        while width > (f.size().width as usize) && width / 2 > min_possible_width {
-                            width /= 2;
-                        }
+                //         // This should theoretically never allow width to be 0... we can be safe and do an extra check though.
+                //         while width > (f.size().width as usize) && width / 2 > min_possible_width {
+                //             width /= 2;
+                //         }
 
-                        std::cmp::max(width, min_possible_width) as u16
-                    };
+                //         std::cmp::max(width, min_possible_width) as u16
+                //     };
 
-                    (
-                        width,
-                        (dd_text.height() + 2 + (dd_text.width() / width as usize)) as u16,
-                    )
-                } else {
-                    // AFAIK this shouldn't happen, unless something went wrong...
-                    (
-                        if f.size().width < 100 {
-                            f.size().width * 90 / 100
-                        } else {
-                            f.size().width * 50 / 100
-                        },
-                        7,
-                    )
-                };
+                //     (
+                //         width,
+                //         (dd_text.height() + 2 + (dd_text.width() / width as usize)) as u16,
+                //     )
+                // } else {
+                //     // AFAIK this shouldn't happen, unless something went wrong...
+                //     (
+                //         if f.size().width < 100 {
+                //             f.size().width * 90 / 100
+                //         } else {
+                //             f.size().width * 50 / 100
+                //         },
+                //         7,
+                //     )
+                // };
 
                 let vertical_bordering = f.size().height.saturating_sub(text_height) / 2;
                 let vertical_dialog_chunk = Layout::default()
diff --git a/src/canvas/canvas_colours.rs b/src/canvas/canvas_colours.rs
index 5d0e6584..d7724568 100644
--- a/src/canvas/canvas_colours.rs
+++ b/src/canvas/canvas_colours.rs
@@ -85,7 +85,7 @@ impl CanvasColours {
     }
 
     pub fn set_table_header_colour(&mut self, colour: &str) -> error::Result<()> {
-        self.table_header_style = get_style_from_config(colour)?.add_modifier(Modifier::BOLD);
+        self.table_header_style = get_style_from_config(colour)?.modifier(Modifier::BOLD);
         Ok(())
     }
 
diff --git a/src/canvas/dialogs/dd_dialog.rs b/src/canvas/dialogs/dd_dialog.rs
index 18f89d68..8b3f342c 100644
--- a/src/canvas/dialogs/dd_dialog.rs
+++ b/src/canvas/dialogs/dd_dialog.rs
@@ -2,8 +2,7 @@ use tui::{
     backend::Backend,
     layout::{Alignment, Rect},
     terminal::Frame,
-    text::{Span, Spans, Text},
-    widgets::{Block, Borders, Paragraph, Wrap},
+    widgets::{Block, Borders, Paragraph, Text},
 };
 
 use crate::{app::App, canvas::Painter};
@@ -12,61 +11,58 @@ const DD_BASE: &str = " Confirm Kill Process ── Esc to close ";
 const DD_ERROR_BASE: &str = " Error ── Esc to close ";
 
 pub trait KillDialog {
-    fn get_dd_spans(&self, app_state: &App) -> Option<Text<'_>>;
+    fn get_dd_spans(&self, app_state: &App) -> Option<Vec<Text<'_>>>;
 
     fn draw_dd_dialog<B: Backend>(
-        &self, f: &mut Frame<'_, B>, dd_text: Option<Text<'_>>, app_state: &App, draw_loc: Rect,
+        &self, f: &mut Frame<'_, B>, dd_text: Option<Vec<Text<'_>>>, app_state: &App,
+        draw_loc: Rect,
     ) -> bool;
 }
 
 impl KillDialog for Painter {
-    fn get_dd_spans(&self, app_state: &App) -> Option<Text<'_>> {
+    fn get_dd_spans(&self, app_state: &App) -> Option<Vec<Text<'_>>> {
         if let Some(dd_err) = &app_state.dd_err {
-            return Some(Text::from(Spans::from(format!(
-                "Failure to properly kill the process - {}",
-                dd_err
-            ))));
+            return Some(vec![
+                Text::raw("\n"),
+                Text::raw(format!("Failure to properly kill the process - {}", dd_err)),
+            ]);
         } else if let Some(to_kill_processes) = app_state.get_to_delete_processes() {
             if let Some(first_pid) = to_kill_processes.1.first() {
-                return Some(Text::from(vec![
-                    Spans::from(vec![]),
-                    Spans::from(vec![
-                        if app_state.is_grouped(app_state.current_widget.widget_id) {
-                            if to_kill_processes.1.len() != 1 {
-                                Span::from(format!(
-                                    "Kill {} processes with the name \"{}\"?",
-                                    to_kill_processes.1.len(),
-                                    to_kill_processes.0
-                                ))
-                            } else {
-                                Span::from(format!(
-                                    "Kill 1 process with the name \"{}\"?",
-                                    to_kill_processes.0
-                                ))
-                            }
-                        } else {
-                            Span::from(format!(
-                                "Kill process \"{}\" with PID {}?",
-                                to_kill_processes.0, first_pid
+                return Some(vec![
+                    Text::raw("\n"),
+                    if app_state.is_grouped(app_state.current_widget.widget_id) {
+                        if to_kill_processes.1.len() != 1 {
+                            Text::raw(format!(
+                                "Kill {} processes with the name \"{}\"?",
+                                to_kill_processes.1.len(),
+                                to_kill_processes.0
                             ))
-                        },
-                    ]),
-                    Spans::from(vec![]),
-                    Spans::from(vec![
-                        if app_state.delete_dialog_state.is_on_yes {
-                            Span::styled("Yes", self.colours.currently_selected_text_style)
                         } else {
-                            Span::from("Yes")
-                        },
-                        Span::from("                 "),
-                        if app_state.delete_dialog_state.is_on_yes {
-                            Span::from("No")
-                        } else {
-                            Span::styled("No", self.colours.currently_selected_text_style)
-                        },
-                    ]),
-                    Spans::from(vec![]),
-                ]));
+                            Text::raw(format!(
+                                "Kill 1 process with the name \"{}\"?",
+                                to_kill_processes.0
+                            ))
+                        }
+                    } else {
+                        Text::raw(format!(
+                            "Kill process \"{}\" with PID {}?",
+                            to_kill_processes.0, first_pid
+                        ))
+                    },
+                    Text::raw("\n\n"),
+                    if app_state.delete_dialog_state.is_on_yes {
+                        Text::styled("Yes", self.colours.currently_selected_text_style)
+                    } else {
+                        Text::raw("Yes")
+                    },
+                    Text::raw("                 "),
+                    if app_state.delete_dialog_state.is_on_yes {
+                        Text::raw("No")
+                    } else {
+                        Text::styled("No", self.colours.currently_selected_text_style)
+                    },
+                    Text::raw("\n"),
+                ]);
             }
         }
 
@@ -74,44 +70,63 @@ impl KillDialog for Painter {
     }
 
     fn draw_dd_dialog<B: Backend>(
-        &self, f: &mut Frame<'_, B>, dd_text: Option<Text<'_>>, app_state: &App, draw_loc: Rect,
+        &self, f: &mut Frame<'_, B>, dd_text: Option<Vec<Text<'_>>>, app_state: &App,
+        draw_loc: Rect,
     ) -> bool {
         if let Some(dd_text) = dd_text {
+            // let dd_title = if app_state.dd_err.is_some() {
+            //     Text::styled(
+            //         format!(
+            //             " Error ─{}─ Esc to close ",
+            //             "─".repeat(
+            //                 usize::from(draw_loc.width)
+            //                     .saturating_sub(DD_ERROR_BASE.chars().count() + 2)
+            //             )
+            //         ),
+            //         self.colours.border_style,
+            //     )
+            // } else {
+            //     Text::styled(
+            //         format!(
+            //             " Confirm Kill Process ─{}─ Esc to close ",
+            //             "─".repeat(
+            //                 usize::from(draw_loc.width).saturating_sub(DD_BASE.chars().count() + 2)
+            //             )
+            //         ),
+            //         self.colours.border_style,
+            //     )
+            // };
+
             let dd_title = if app_state.dd_err.is_some() {
-                Span::styled(
-                    format!(
-                        " Error ─{}─ Esc to close ",
-                        "─".repeat(
-                            usize::from(draw_loc.width)
-                                .saturating_sub(DD_ERROR_BASE.chars().count() + 2)
-                        )
-                    ),
-                    self.colours.border_style,
+                format!(
+                    " Error ─{}─ Esc to close ",
+                    "─".repeat(
+                        usize::from(draw_loc.width)
+                            .saturating_sub(DD_ERROR_BASE.chars().count() + 2)
+                    )
                 )
             } else {
-                Span::styled(
-                    format!(
-                        " Confirm Kill Process ─{}─ Esc to close ",
-                        "─".repeat(
-                            usize::from(draw_loc.width).saturating_sub(DD_BASE.chars().count() + 2)
-                        )
-                    ),
-                    self.colours.border_style,
+                format!(
+                    " Confirm Kill Process ─{}─ Esc to close ",
+                    "─".repeat(
+                        usize::from(draw_loc.width).saturating_sub(DD_BASE.chars().count() + 2)
+                    )
                 )
             };
 
             f.render_widget(
-                Paragraph::new(dd_text)
+                Paragraph::new(dd_text.iter())
                     .block(
                         Block::default()
-                            .title(dd_title)
+                            .title(&dd_title)
+                            .title_style(self.colours.border_style)
                             .style(self.colours.border_style)
                             .borders(Borders::ALL)
                             .border_style(self.colours.border_style),
                     )
                     .style(self.colours.text_style)
                     .alignment(Alignment::Center)
-                    .wrap(Wrap { trim: true }),
+                    .wrap(true),
                 draw_loc,
             );
 
diff --git a/src/canvas/dialogs/help_dialog.rs b/src/canvas/dialogs/help_dialog.rs
index 138622ce..8ef4d010 100644
--- a/src/canvas/dialogs/help_dialog.rs
+++ b/src/canvas/dialogs/help_dialog.rs
@@ -4,8 +4,7 @@ use tui::{
     backend::Backend,
     layout::{Alignment, Rect},
     terminal::Frame,
-    text::Span,
-    widgets::{Block, Borders, Paragraph, Wrap},
+    widgets::{Block, Borders, Paragraph},
 };
 
 use crate::{app::App, canvas::Painter, constants};
@@ -22,14 +21,19 @@ impl HelpDialog for Painter {
     fn draw_help_dialog<B: Backend>(
         &self, f: &mut Frame<'_, B>, app_state: &mut App, draw_loc: Rect,
     ) {
-        let help_title = Span::styled(
-            format!(
-                " Help ─{}─ Esc to close ",
-                "─".repeat(
-                    usize::from(draw_loc.width).saturating_sub(HELP_BASE.chars().count() + 2)
-                )
-            ),
-            self.colours.border_style,
+        // let help_title = Text::styled(
+        //     format!(
+        //         " Help ─{}─ Esc to close ",
+        //         "─".repeat(
+        //             usize::from(draw_loc.width).saturating_sub(HELP_BASE.chars().count() + 2)
+        //         )
+        //     ),
+        //     self.colours.border_style,
+        // );
+
+        let help_title = format!(
+            " Help ─{}─ Esc to close ",
+            "─".repeat(usize::from(draw_loc.width).saturating_sub(HELP_BASE.chars().count() + 2))
         );
 
         if app_state.is_force_redraw {
@@ -95,24 +99,24 @@ impl HelpDialog for Painter {
         }
 
         f.render_widget(
-            Paragraph::new(self.styled_help_text.clone())
+            Paragraph::new(self.styled_help_text.iter())
                 .block(
                     Block::default()
-                        .title(help_title)
+                        .title(&help_title)
+                        .title_style(self.colours.border_style)
                         .style(self.colours.border_style)
                         .borders(Borders::ALL)
                         .border_style(self.colours.border_style),
                 )
                 .style(self.colours.text_style)
                 .alignment(Alignment::Left)
-                .wrap(Wrap { trim: true })
-                .scroll((
+                .wrap(true)
+                .scroll(
                     app_state
                         .help_dialog_state
                         .scroll_state
                         .current_scroll_index,
-                    0,
-                )),
+                ),
             draw_loc,
         );
     }
diff --git a/src/canvas/widgets/basic_table_arrows.rs b/src/canvas/widgets/basic_table_arrows.rs
index 18beab83..591f71c6 100644
--- a/src/canvas/widgets/basic_table_arrows.rs
+++ b/src/canvas/widgets/basic_table_arrows.rs
@@ -10,8 +10,7 @@ use tui::{
     backend::Backend,
     layout::{Constraint, Layout, Rect},
     terminal::Frame,
-    text::{Span, Spans},
-    widgets::{Block, Paragraph},
+    widgets::{Block, Paragraph, Text},
 };
 
 pub trait BasicTableArrows {
@@ -98,12 +97,10 @@ impl BasicTableArrows for Painter {
             usize::from(draw_loc.width).saturating_sub(6 + left_name.len() + right_name.len());
 
         let arrow_text = vec![
-            Spans::from(Span::from(String::default())),
-            Spans::from(vec![
-                Span::styled(format!("◄ {}", left_name), self.colours.text_style),
-                Span::from(" ".repeat(num_spaces)),
-                Span::styled(format!("{} ►", right_name), self.colours.text_style),
-            ]),
+            Text::raw("\n"),
+            Text::styled(format!("◄ {}", left_name), self.colours.text_style),
+            Text::raw(" ".repeat(num_spaces)),
+            Text::styled(format!("{} ►", right_name), self.colours.text_style),
         ];
 
         let margined_draw_loc = Layout::default()
@@ -112,7 +109,7 @@ impl BasicTableArrows for Painter {
             .split(draw_loc);
 
         f.render_widget(
-            Paragraph::new(arrow_text).block(Block::default()),
+            Paragraph::new(arrow_text.iter()).block(Block::default()),
             margined_draw_loc[0],
         );
     }
diff --git a/src/canvas/widgets/battery_display.rs b/src/canvas/widgets/battery_display.rs
index d716b53e..7c3b7896 100644
--- a/src/canvas/widgets/battery_display.rs
+++ b/src/canvas/widgets/battery_display.rs
@@ -8,8 +8,7 @@ use tui::{
     backend::Backend,
     layout::{Constraint, Rect},
     terminal::Frame,
-    text::{Span, Spans},
-    widgets::{Block, Borders, Paragraph, Row, Table, Tabs},
+    widgets::{Block, Borders, Paragraph, Row, Table, Tabs, Text},
 };
 
 pub trait BatteryDisplayWidget {
@@ -34,25 +33,45 @@ impl BatteryDisplayWidget for Painter {
                 self.colours.border_style
             };
 
+            // let title = if app_state.is_expanded {
+            //     const TITLE_BASE: &str = " Battery ── Esc to go back ";
+            //     Span::styled(
+            //         format!(
+            //             " Battery ─{}─ Esc to go back ",
+            //             "─".repeat(
+            //                 usize::from(draw_loc.width)
+            //                     .saturating_sub(TITLE_BASE.chars().count() + 2)
+            //             )
+            //         ),
+            //         border_and_title_style,
+            //     )
+            // } else {
+            //     Span::styled(" Battery ".to_string(), self.colours.widget_title_style)
+            // };
+
             let title = if app_state.is_expanded {
                 const TITLE_BASE: &str = " Battery ── Esc to go back ";
-                Span::styled(
-                    format!(
-                        " Battery ─{}─ Esc to go back ",
-                        "─".repeat(
-                            usize::from(draw_loc.width)
-                                .saturating_sub(TITLE_BASE.chars().count() + 2)
-                        )
-                    ),
-                    border_and_title_style,
+
+                format!(
+                    " Battery ─{}─ Esc to go back ",
+                    "─".repeat(
+                        usize::from(draw_loc.width).saturating_sub(TITLE_BASE.chars().count() + 2)
+                    )
                 )
             } else {
-                Span::styled(" Battery ".to_string(), self.colours.widget_title_style)
+                " Battery ".to_string()
+            };
+
+            let title_style = if app_state.is_expanded {
+                border_and_title_style
+            } else {
+                self.colours.widget_title_style
             };
 
             let battery_block = if draw_border {
                 Block::default()
-                    .title(title)
+                    .title(&title)
+                    .title_style(title_style)
                     .borders(Borders::ALL)
                     .border_style(border_and_title_style)
             } else if is_on_widget {
@@ -63,22 +82,32 @@ impl BatteryDisplayWidget for Painter {
                 Block::default().borders(Borders::NONE)
             };
 
-            f.render_widget(
-                Tabs::new(
-                    (app_state
-                        .canvas_data
-                        .battery_data
-                        .iter()
-                        .map(|battery| Spans::from(battery.battery_name.clone())))
-                    .collect::<Vec<_>>(),
-                )
-                .block(battery_block.clone())
-                .divider(tui::symbols::line::VERTICAL)
-                .style(self.colours.text_style)
-                .highlight_style(self.colours.currently_selected_text_style)
-                .select(battery_widget_state.currently_selected_battery_index),
-                draw_loc,
-            );
+            // f.render_widget(
+            //     // Tabs::new(
+            //     //     (app_state
+            //     //         .canvas_data
+            //     //         .battery_data
+            //     //         .iter()
+            //     //         .map(|battery| Spans::from(battery.battery_name.clone())))
+            //     //     .collect::<Vec<_>>(),
+            //     // )
+            //     Tabs::default()
+            //         .titles(
+            //             app_state
+            //                 .canvas_data
+            //                 .battery_data
+            //                 .iter()
+            //                 .map(|battery| &battery.battery_name)
+            //                 .collect::<Vec<_>>()
+            //                 .as_ref(),
+            //         )
+            //         .block(battery_block)
+            //         .divider(tui::symbols::line::VERTICAL)
+            //         .style(self.colours.text_style)
+            //         .highlight_style(self.colours.currently_selected_text_style)
+            //         .select(battery_widget_state.currently_selected_battery_index),
+            //     draw_loc,
+            // );
 
             if let Some(battery_details) = app_state
                 .canvas_data
@@ -134,21 +163,52 @@ impl BatteryDisplayWidget for Painter {
                 // Draw
                 f.render_widget(
                     Table::new([""].iter(), battery_rows)
-                        .block(battery_block.clone())
+                        .block(battery_block)
                         .header_style(self.colours.table_header_style)
                         .widths([Constraint::Percentage(50), Constraint::Percentage(50)].as_ref()),
                     draw_loc,
                 );
             } else {
                 f.render_widget(
-                    Paragraph::new(Spans::from(Span::styled(
-                        "No data found for this battery",
-                        self.colours.text_style,
-                    )))
+                    Paragraph::new(
+                        [Text::styled(
+                            "No data found for this battery",
+                            self.colours.text_style,
+                        )]
+                        .iter(),
+                    )
                     .block(battery_block),
                     draw_loc,
                 );
             }
+
+            // Has to be placed AFTER for tui 0.9, place BEFORE for 0.10.
+            f.render_widget(
+                // Tabs::new(
+                //     (app_state
+                //         .canvas_data
+                //         .battery_data
+                //         .iter()
+                //         .map(|battery| Spans::from(battery.battery_name.clone())))
+                //     .collect::<Vec<_>>(),
+                // )
+                Tabs::default()
+                    .titles(
+                        app_state
+                            .canvas_data
+                            .battery_data
+                            .iter()
+                            .map(|battery| &battery.battery_name)
+                            .collect::<Vec<_>>()
+                            .as_ref(),
+                    )
+                    .block(battery_block)
+                    .divider(tui::symbols::line::VERTICAL)
+                    .style(self.colours.text_style)
+                    .highlight_style(self.colours.currently_selected_text_style)
+                    .select(battery_widget_state.currently_selected_battery_index),
+                draw_loc,
+            );
         }
     }
 }
diff --git a/src/canvas/widgets/cpu_basic.rs b/src/canvas/widgets/cpu_basic.rs
index c8db2f33..4683a677 100644
--- a/src/canvas/widgets/cpu_basic.rs
+++ b/src/canvas/widgets/cpu_basic.rs
@@ -11,8 +11,7 @@ use tui::{
     backend::Backend,
     layout::{Constraint, Direction, Layout, Rect},
     terminal::Frame,
-    text::{Span, Spans},
-    widgets::{Block, Paragraph},
+    widgets::{Block, Paragraph, Text},
 };
 
 pub trait CpuBasicWidget {
@@ -77,10 +76,10 @@ impl CpuBasicWidget for Painter {
 
                     let num_bars = calculate_basic_use_bars(use_percentage, bar_length);
                     format!(
-                        "{:3}[{}{}{:3.0}%]",
+                        "{:3}[{}{}{:3.0}%]\n",
                         if app_state.app_config_fields.show_average_cpu {
                             if cpu_index == 0 {
-                                " AVG".to_string()
+                                "AVG".to_string()
                             } else {
                                 (cpu_index - 1).to_string()
                             }
@@ -109,11 +108,16 @@ impl CpuBasicWidget for Painter {
                     let end_index = min(start_index + how_many_cpus, num_cpus);
                     let cpu_column = (start_index..end_index)
                         .map(|cpu_index| {
-                            Spans::from(Span {
-                                content: (&cpu_bars[cpu_index]).into(),
-                                style: self.colours.cpu_colour_styles
+                            // Spans::from(Span {
+                            //     content: (&cpu_bars[cpu_index]).into(),
+                            //     style: self.colours.cpu_colour_styles
+                            //         [cpu_index % self.colours.cpu_colour_styles.len()],
+                            // })
+                            Text::styled(
+                                &cpu_bars[cpu_index],
+                                self.colours.cpu_colour_styles
                                     [cpu_index % self.colours.cpu_colour_styles.len()],
-                            })
+                            )
                         })
                         .collect::<Vec<_>>();
 
@@ -126,7 +130,7 @@ impl CpuBasicWidget for Painter {
                         .split(*chunk);
 
                     f.render_widget(
-                        Paragraph::new(cpu_column).block(Block::default()),
+                        Paragraph::new(cpu_column.iter()).block(Block::default()),
                         margined_loc[0],
                     );
                 }
diff --git a/src/canvas/widgets/cpu_graph.rs b/src/canvas/widgets/cpu_graph.rs
index a01b7f5f..f31eb1f2 100644
--- a/src/canvas/widgets/cpu_graph.rs
+++ b/src/canvas/widgets/cpu_graph.rs
@@ -17,7 +17,6 @@ use tui::{
     layout::{Constraint, Direction, Layout, Rect},
     symbols::Marker,
     terminal::Frame,
-    text::Span,
     widgets::{Axis, Block, Borders, Chart, Dataset, Row, Table},
 };
 
@@ -104,12 +103,17 @@ impl CpuGraphWidget for Painter {
         if let Some(cpu_widget_state) = app_state.cpu_state.widget_states.get_mut(&widget_id) {
             let cpu_data: &mut [ConvertedCpuData] = &mut app_state.canvas_data.cpu_data;
 
-            let display_time_labels = vec![
-                Span::styled(
-                    format!("{}s", cpu_widget_state.current_display_time / 1000),
-                    self.colours.graph_style,
-                ),
-                Span::styled("0s".to_string(), self.colours.graph_style),
+            // let display_time_labels = vec![
+            //     Text::styled(
+            //         format!("{}s", cpu_widget_state.current_display_time / 1000),
+            //         self.colours.graph_style,
+            //     ),
+            //     Text::styled("0s".to_string(), self.colours.graph_style),
+            // ];
+
+            let display_time_labels = [
+                format!("{}s", cpu_widget_state.current_display_time / 1000),
+                "0s".to_string(),
             ];
 
             let x_axis = if app_state.app_config_fields.hide_time
@@ -124,7 +128,8 @@ impl CpuGraphWidget for Painter {
                     Axis::default()
                         .bounds([-(cpu_widget_state.current_display_time as f64), 0.0])
                         .style(self.colours.graph_style)
-                        .labels(display_time_labels)
+                        .labels(&display_time_labels)
+                        .labels_style(self.colours.graph_style)
                 } else {
                     cpu_widget_state.autohide_timer = None;
                     Axis::default().bounds([-(cpu_widget_state.current_display_time as f64), 0.0])
@@ -135,17 +140,16 @@ impl CpuGraphWidget for Painter {
                 Axis::default()
                     .bounds([-(cpu_widget_state.current_display_time as f64), 0.0])
                     .style(self.colours.graph_style)
-                    .labels(display_time_labels)
+                    .labels(&display_time_labels)
+                    .labels_style(self.colours.graph_style)
             };
 
             // Note this is offset as otherwise the 0 value is not drawn!
             let y_axis = Axis::default()
                 .style(self.colours.graph_style)
                 .bounds([-0.5, 100.5])
-                .labels(vec![
-                    Span::styled("0%", self.colours.graph_style),
-                    Span::styled("100%", self.colours.graph_style),
-                ]);
+                .labels_style(self.colours.graph_style)
+                .labels(&["0%", "100%"]);
 
             let use_dot = app_state.app_config_fields.use_dot;
             let show_avg_cpu = app_state.app_config_fields.show_average_cpu;
@@ -199,17 +203,26 @@ impl CpuGraphWidget for Painter {
                 self.colours.border_style
             };
 
-            let title = if app_state.is_expanded {
-                Span::styled(" CPU ".to_string(), border_style)
+            // let title = if app_state.is_expanded {
+            //     Span::styled(" CPU ".to_string(), border_style)
+            // } else {
+            //     Span::styled(" CPU ".to_string(), self.colours.widget_title_style)
+            // };
+            let title = " CPU ";
+            let title_style = if app_state.is_expanded {
+                border_style
             } else {
-                Span::styled(" CPU ".to_string(), self.colours.widget_title_style)
+                self.colours.widget_title_style
             };
 
             f.render_widget(
-                Chart::new(dataset_vector)
+                // Chart::new(dataset_vector)
+                Chart::default()
+                    .datasets(&dataset_vector)
                     .block(
                         Block::default()
                             .title(title)
+                            .title_style(title_style)
                             .borders(Borders::ALL)
                             .border_style(border_style),
                     )
diff --git a/src/canvas/widgets/disk_table.rs b/src/canvas/widgets/disk_table.rs
index 5b31314e..191e6b66 100644
--- a/src/canvas/widgets/disk_table.rs
+++ b/src/canvas/widgets/disk_table.rs
@@ -4,7 +4,6 @@ use tui::{
     backend::Backend,
     layout::{Constraint, Direction, Layout, Rect},
     terminal::Frame,
-    text::Span,
     widgets::{Block, Borders, Row, Table},
 };
 
@@ -77,27 +76,48 @@ impl DiskTableWidget for Painter {
                 (self.colours.border_style, self.colours.text_style)
             };
 
+            // let title = if app_state.is_expanded {
+            //     const TITLE_BASE: &str = " Disk ── Esc to go back ";
+            //     Span::styled(
+            //         format!(
+            //             " Disk ─{}─ Esc to go back ",
+            //             "─".repeat(
+            //                 usize::from(draw_loc.width)
+            //                     .saturating_sub(TITLE_BASE.chars().count() + 2)
+            //             )
+            //         ),
+            //         border_and_title_style,
+            //     )
+            // } else if app_state.app_config_fields.use_basic_mode {
+            //     Span::from(String::new())
+            // } else {
+            //     Span::styled(" Disk ".to_string(), self.colours.widget_title_style)
+            // };
+
             let title = if app_state.is_expanded {
                 const TITLE_BASE: &str = " Disk ── Esc to go back ";
-                Span::styled(
-                    format!(
-                        " Disk ─{}─ Esc to go back ",
-                        "─".repeat(
-                            usize::from(draw_loc.width)
-                                .saturating_sub(TITLE_BASE.chars().count() + 2)
-                        )
-                    ),
-                    border_and_title_style,
+                format!(
+                    " Disk ─{}─ Esc to go back ",
+                    "─".repeat(
+                        usize::from(draw_loc.width).saturating_sub(TITLE_BASE.chars().count() + 2)
+                    )
                 )
             } else if app_state.app_config_fields.use_basic_mode {
-                Span::from(String::new())
+                String::new()
             } else {
-                Span::styled(" Disk ".to_string(), self.colours.widget_title_style)
+                " Disk ".to_string()
+            };
+
+            let title_style = if app_state.is_expanded {
+                border_and_title_style
+            } else {
+                self.colours.widget_title_style
             };
 
             let disk_block = if draw_border {
                 Block::default()
-                    .title(title)
+                    .title(&title)
+                    .title_style(title_style)
                     .borders(Borders::ALL)
                     .border_style(border_and_title_style)
             } else if is_on_widget {
diff --git a/src/canvas/widgets/mem_basic.rs b/src/canvas/widgets/mem_basic.rs
index 43003e86..c4498316 100644
--- a/src/canvas/widgets/mem_basic.rs
+++ b/src/canvas/widgets/mem_basic.rs
@@ -8,8 +8,7 @@ use tui::{
     backend::Backend,
     layout::{Constraint, Layout, Rect},
     terminal::Frame,
-    text::{Span, Spans},
-    widgets::{Block, Paragraph},
+    widgets::{Block, Paragraph, Text},
 };
 
 pub trait MemBasicWidget {
@@ -54,7 +53,7 @@ impl MemBasicWidget for Painter {
         let num_bars_ram = calculate_basic_use_bars(ram_use_percentage, bar_length);
         let num_bars_swap = calculate_basic_use_bars(swap_use_percentage, bar_length);
         let mem_label = format!(
-            "RAM[{}{}{:3.0}%]",
+            "RAM[{}{}{:3.0}%]\n",
             "|".repeat(num_bars_ram),
             " ".repeat(bar_length - num_bars_ram),
             ram_use_percentage.round(),
@@ -66,13 +65,13 @@ impl MemBasicWidget for Painter {
             swap_use_percentage.round(),
         );
 
-        let mem_text = vec![
-            Spans::from(Span::styled(mem_label, self.colours.ram_style)),
-            Spans::from(Span::styled(swap_label, self.colours.swap_style)),
+        let mem_text = [
+            Text::styled(mem_label, self.colours.ram_style),
+            Text::styled(swap_label, self.colours.swap_style),
         ];
 
         f.render_widget(
-            Paragraph::new(mem_text).block(Block::default()),
+            Paragraph::new(mem_text.iter()).block(Block::default()),
             margined_loc[0],
         );
     }
diff --git a/src/canvas/widgets/mem_graph.rs b/src/canvas/widgets/mem_graph.rs
index 24717dab..ba38b6bd 100644
--- a/src/canvas/widgets/mem_graph.rs
+++ b/src/canvas/widgets/mem_graph.rs
@@ -5,7 +5,6 @@ use tui::{
     layout::{Constraint, Rect},
     symbols::Marker,
     terminal::Frame,
-    text::Span,
     widgets::{Axis, Block, Borders, Chart, Dataset},
 };
 
@@ -23,12 +22,9 @@ impl MemGraphWidget for Painter {
             let mem_data: &[(f64, f64)] = &app_state.canvas_data.mem_data;
             let swap_data: &[(f64, f64)] = &app_state.canvas_data.swap_data;
 
-            let display_time_labels = vec![
-                Span::styled(
-                    format!("{}s", mem_widget_state.current_display_time / 1000),
-                    self.colours.graph_style,
-                ),
-                Span::styled("0s".to_string(), self.colours.graph_style),
+            let display_time_labels = [
+                format!("{}s", mem_widget_state.current_display_time / 1000),
+                "0s".to_string(),
             ];
             let x_axis = if app_state.app_config_fields.hide_time
                 || (app_state.app_config_fields.autohide_time
@@ -42,7 +38,8 @@ impl MemGraphWidget for Painter {
                     Axis::default()
                         .bounds([-(mem_widget_state.current_display_time as f64), 0.0])
                         .style(self.colours.graph_style)
-                        .labels(display_time_labels)
+                        .labels(&display_time_labels)
+                        .labels_style(self.colours.graph_style)
                 } else {
                     mem_widget_state.autohide_timer = None;
                     Axis::default().bounds([-(mem_widget_state.current_display_time as f64), 0.0])
@@ -53,17 +50,16 @@ impl MemGraphWidget for Painter {
                 Axis::default()
                     .bounds([-(mem_widget_state.current_display_time as f64), 0.0])
                     .style(self.colours.graph_style)
-                    .labels(display_time_labels)
+                    .labels(&display_time_labels)
+                    .labels_style(self.colours.graph_style)
             };
 
             // Offset as the zero value isn't drawn otherwise...
             let y_axis = Axis::default()
                 .style(self.colours.graph_style)
                 .bounds([-0.5, 100.5])
-                .labels(vec![
-                    Span::styled("0%", self.colours.graph_style),
-                    Span::styled("100%", self.colours.graph_style),
-                ]);
+                .labels(&["0%", "100%"])
+                .labels_style(self.colours.graph_style);
 
             let mut mem_canvas_vec: Vec<Dataset<'_>> = vec![];
 
@@ -95,25 +91,29 @@ impl MemGraphWidget for Painter {
 
             let title = if app_state.is_expanded {
                 const TITLE_BASE: &str = " Memory ── Esc to go back ";
-                Span::styled(
-                    format!(
-                        " Memory ─{}─ Esc to go back ",
-                        "─".repeat(
-                            usize::from(draw_loc.width)
-                                .saturating_sub(TITLE_BASE.chars().count() + 2)
-                        )
-                    ),
-                    self.colours.highlighted_border_style,
+                format!(
+                    " Memory ─{}─ Esc to go back ",
+                    "─".repeat(
+                        usize::from(draw_loc.width).saturating_sub(TITLE_BASE.chars().count() + 2)
+                    )
                 )
             } else {
-                Span::styled(" Memory ".to_string(), self.colours.widget_title_style)
+                " Memory ".to_string()
+            };
+            let title_style = if app_state.is_expanded {
+                self.colours.highlighted_border_style
+            } else {
+                self.colours.widget_title_style
             };
 
             f.render_widget(
-                Chart::new(mem_canvas_vec)
+                // Chart::new(mem_canvas_vec)
+                Chart::default()
+                    .datasets(&mem_canvas_vec)
                     .block(
                         Block::default()
-                            .title(title)
+                            .title(&title)
+                            .title_style(title_style)
                             .borders(Borders::ALL)
                             .border_style(if app_state.current_widget.widget_id == widget_id {
                                 self.colours.highlighted_border_style
diff --git a/src/canvas/widgets/network_basic.rs b/src/canvas/widgets/network_basic.rs
index 891d8a1f..2d8c6340 100644
--- a/src/canvas/widgets/network_basic.rs
+++ b/src/canvas/widgets/network_basic.rs
@@ -4,8 +4,7 @@ use tui::{
     backend::Backend,
     layout::{Constraint, Direction, Layout, Rect},
     terminal::Frame,
-    text::{Span, Spans},
-    widgets::{Block, Paragraph},
+    widgets::{Block, Paragraph, Text},
 };
 
 pub trait NetworkBasicWidget {
@@ -44,25 +43,28 @@ impl NetworkBasicWidget for Painter {
             );
         }
 
-        let rx_label = format!("RX: {}", &app_state.canvas_data.rx_display);
+        let rx_label = format!("RX: {}\n", &app_state.canvas_data.rx_display);
         let tx_label = format!("TX: {}", &app_state.canvas_data.tx_display);
-        let total_rx_label = format!("Total RX: {}", &app_state.canvas_data.total_rx_display);
+        let total_rx_label = format!("Total RX: {}\n", &app_state.canvas_data.total_rx_display);
         let total_tx_label = format!("Total TX: {}", &app_state.canvas_data.total_tx_display);
 
-        let net_text = vec![
-            Spans::from(Span::styled(rx_label, self.colours.rx_style)),
-            Spans::from(Span::styled(tx_label, self.colours.tx_style)),
+        let net_text = [
+            Text::styled(rx_label, self.colours.rx_style),
+            Text::styled(tx_label, self.colours.tx_style),
         ];
 
-        let total_net_text = vec![
-            Spans::from(Span::styled(total_rx_label, self.colours.total_rx_style)),
-            Spans::from(Span::styled(total_tx_label, self.colours.total_tx_style)),
+        let total_net_text = [
+            Text::styled(total_rx_label, self.colours.total_rx_style),
+            Text::styled(total_tx_label, self.colours.total_tx_style),
         ];
 
-        f.render_widget(Paragraph::new(net_text).block(Block::default()), net_loc[0]);
-
         f.render_widget(
-            Paragraph::new(total_net_text).block(Block::default()),
+            Paragraph::new(net_text.iter()).block(Block::default()),
+            net_loc[0],
+        );
+
+        f.render_widget(
+            Paragraph::new(total_net_text.iter()).block(Block::default()),
             total_loc[0],
         );
     }
diff --git a/src/canvas/widgets/network_graph.rs b/src/canvas/widgets/network_graph.rs
index 27a464d8..b981c15f 100644
--- a/src/canvas/widgets/network_graph.rs
+++ b/src/canvas/widgets/network_graph.rs
@@ -12,7 +12,6 @@ use tui::{
     layout::{Constraint, Direction, Layout, Rect},
     symbols::Marker,
     terminal::Frame,
-    text::Span,
     widgets::{Axis, Block, Borders, Chart, Dataset, Row, Table},
 };
 
@@ -72,12 +71,9 @@ impl NetworkGraphWidget for Painter {
             let network_data_rx: &[(f64, f64)] = &app_state.canvas_data.network_data_rx;
             let network_data_tx: &[(f64, f64)] = &app_state.canvas_data.network_data_tx;
 
-            let display_time_labels = vec![
-                Span::styled(
-                    format!("{}s", network_widget_state.current_display_time / 1000),
-                    self.colours.graph_style,
-                ),
-                Span::styled("0s".to_string(), self.colours.graph_style),
+            let display_time_labels = [
+                format!("{}s", network_widget_state.current_display_time / 1000),
+                "0s".to_string(),
             ];
             let x_axis = if app_state.app_config_fields.hide_time
                 || (app_state.app_config_fields.autohide_time
@@ -91,7 +87,8 @@ impl NetworkGraphWidget for Painter {
                     Axis::default()
                         .bounds([-(network_widget_state.current_display_time as f64), 0.0])
                         .style(self.colours.graph_style)
-                        .labels(display_time_labels)
+                        .labels(&display_time_labels)
+                        .labels_style(self.colours.graph_style)
                 } else {
                     network_widget_state.autohide_timer = None;
                     Axis::default()
@@ -103,35 +100,33 @@ impl NetworkGraphWidget for Painter {
                 Axis::default()
                     .bounds([-(network_widget_state.current_display_time as f64), 0.0])
                     .style(self.colours.graph_style)
-                    .labels(display_time_labels)
+                    .labels(&display_time_labels)
+                    .labels_style(self.colours.graph_style)
             };
 
             // 0 is offset.
-            let y_axis_labels = vec![
-                Span::styled("0B", self.colours.graph_style),
-                Span::styled("1KiB", self.colours.graph_style),
-                Span::styled("1MiB", self.colours.graph_style),
-                Span::styled("1GiB", self.colours.graph_style),
-            ];
+            let y_axis_labels = ["0B", "1KiB", "1MiB", "1GiB"];
             let y_axis = Axis::default()
                 .style(self.colours.graph_style)
                 .bounds([-0.5, 30_f64])
-                .labels(y_axis_labels);
+                .labels(&y_axis_labels)
+                .labels_style(self.colours.graph_style);
 
             let title = if app_state.is_expanded {
                 const TITLE_BASE: &str = " Network ── Esc to go back ";
-                Span::styled(
-                    format!(
-                        " Network ─{}─ Esc to go back ",
-                        "─".repeat(
-                            usize::from(draw_loc.width)
-                                .saturating_sub(TITLE_BASE.chars().count() + 2)
-                        )
-                    ),
-                    self.colours.highlighted_border_style,
+                format!(
+                    " Network ─{}─ Esc to go back ",
+                    "─".repeat(
+                        usize::from(draw_loc.width).saturating_sub(TITLE_BASE.chars().count() + 2)
+                    )
                 )
             } else {
-                Span::styled(" Network ".to_string(), self.colours.widget_title_style)
+                " Network ".to_string()
+            };
+            let title_style = if app_state.is_expanded {
+                self.colours.highlighted_border_style
+            } else {
+                self.colours.widget_title_style
             };
 
             let legend_constraints = if hide_legend {
@@ -142,7 +137,6 @@ impl NetworkGraphWidget for Painter {
 
             let dataset = if app_state.app_config_fields.use_old_network_legend && !hide_legend {
                 let mut ret_val = vec![];
-
                 ret_val.push(
                     Dataset::default()
                         .name(format!("RX: {:7}", app_state.canvas_data.rx_display))
@@ -220,10 +214,13 @@ impl NetworkGraphWidget for Painter {
             };
 
             f.render_widget(
-                Chart::new(dataset)
+                // Chart::new(dataset)
+                Chart::default()
+                    .datasets(&dataset)
                     .block(
                         Block::default()
-                            .title(title)
+                            .title(&title)
+                            .title_style(title_style)
                             .borders(Borders::ALL)
                             .border_style(if app_state.current_widget.widget_id == widget_id {
                                 self.colours.highlighted_border_style
diff --git a/src/canvas/widgets/process_table.rs b/src/canvas/widgets/process_table.rs
index 54f0a5ad..dea0d642 100644
--- a/src/canvas/widgets/process_table.rs
+++ b/src/canvas/widgets/process_table.rs
@@ -13,8 +13,7 @@ use tui::{
     backend::Backend,
     layout::{Alignment, Constraint, Direction, Layout, Rect},
     terminal::Frame,
-    text::{Span, Spans},
-    widgets::{Block, Borders, Paragraph, Row, Table},
+    widgets::{Block, Borders, Paragraph, Row, Table, Text},
 };
 
 use unicode_segmentation::{GraphemeIndices, UnicodeSegmentation};
@@ -225,26 +224,30 @@ impl ProcessTableWidget for Painter {
                         && !proc_widget_state.is_sort_open
                     {
                         const TITLE_BASE: &str = " Processes ── Esc to go back ";
-                        Span::styled(
-                            format!(
-                                " Processes ─{}─ Esc to go back ",
-                                "─".repeat(
-                                    usize::from(draw_loc.width)
-                                        .saturating_sub(TITLE_BASE.chars().count() + 2)
-                                )
-                            ),
-                            border_and_title_style,
+                        format!(
+                            " Processes ─{}─ Esc to go back ",
+                            "─".repeat(
+                                usize::from(draw_loc.width)
+                                    .saturating_sub(TITLE_BASE.chars().count() + 2)
+                            )
                         )
                     } else {
-                        Span::styled(" Processes ".to_string(), self.colours.widget_title_style)
+                        " Processes ".to_string()
                     }
                 } else {
-                    Span::from(String::default())
+                    String::default()
+                };
+
+                let title_style = if app_state.is_expanded {
+                    border_and_title_style
+                } else {
+                    self.colours.widget_title_style
                 };
 
                 let process_block = if draw_border {
                     Block::default()
-                        .title(title)
+                        .title(&title)
+                        .title_style(title_style)
                         .borders(Borders::ALL)
                         .border_style(border_and_title_style)
                 } else if is_on_widget {
@@ -291,7 +294,7 @@ impl ProcessTableWidget for Painter {
             is_on_widget: bool, grapheme_indices: GraphemeIndices<'a>, start_position: usize,
             cursor_position: usize, query: &str, currently_selected_text_style: tui::style::Style,
             text_style: tui::style::Style,
-        ) -> Vec<Span<'a>> {
+        ) -> Vec<Text<'a>> {
             let mut current_grapheme_posn = 0;
 
             if is_on_widget {
@@ -303,9 +306,9 @@ impl ProcessTableWidget for Painter {
                             None
                         } else {
                             let styled = if grapheme.0 == cursor_position {
-                                Span::styled(grapheme.1, currently_selected_text_style)
+                                Text::styled(grapheme.1, currently_selected_text_style)
                             } else {
-                                Span::styled(grapheme.1, text_style)
+                                Text::styled(grapheme.1, text_style)
                             };
                             Some(styled)
                         }
@@ -313,7 +316,7 @@ impl ProcessTableWidget for Painter {
                     .collect::<Vec<_>>();
 
                 if cursor_position >= query.len() {
-                    res.push(Span::styled(" ", currently_selected_text_style))
+                    res.push(Text::styled(" ", currently_selected_text_style))
                 }
 
                 res
@@ -327,7 +330,7 @@ impl ProcessTableWidget for Painter {
                         if current_grapheme_posn <= start_position {
                             None
                         } else {
-                            let styled = Span::styled(grapheme.1, text_style);
+                            let styled = Text::styled(grapheme.1, text_style);
                             Some(styled)
                         }
                     })
@@ -373,8 +376,8 @@ impl ProcessTableWidget for Painter {
                 self.colours.text_style,
             );
 
-            let mut search_text = vec![Spans::from({
-                let mut search_vec = vec![Span::styled(
+            let mut search_text = {
+                let mut search_vec = vec![Text::styled(
                     search_title,
                     if is_on_widget {
                         self.colours.table_header_style
@@ -384,7 +387,7 @@ impl ProcessTableWidget for Painter {
                 )];
                 search_vec.extend(query_with_cursor);
                 search_vec
-            })];
+            };
 
             // Text options shamelessly stolen from VS Code.
             let case_style = if !proc_widget_state.process_search_state.is_ignoring_case {
@@ -411,24 +414,25 @@ impl ProcessTableWidget for Painter {
                 self.colours.text_style
             };
 
-            let option_text = Spans::from(vec![
-                Span::styled(
+            let option_text = vec![
+                Text::raw("\n"),
+                Text::styled(
                     format!("Case({})", if self.is_mac_os { "F1" } else { "Alt+C" }),
                     case_style,
                 ),
-                Span::from("  "),
-                Span::styled(
+                Text::raw("  "),
+                Text::styled(
                     format!("Whole({})", if self.is_mac_os { "F2" } else { "Alt+W" }),
                     whole_word_style,
                 ),
-                Span::from("  "),
-                Span::styled(
+                Text::raw("  "),
+                Text::styled(
                     format!("Regex({})", if self.is_mac_os { "F3" } else { "Alt+R" }),
                     regex_style,
                 ),
-            ]);
+            ];
 
-            search_text.push(Spans::from(Span::styled(
+            search_text.push(Text::styled(
                 if let Some(err) = &proc_widget_state
                     .process_search_state
                     .search_state
@@ -439,8 +443,8 @@ impl ProcessTableWidget for Painter {
                     ""
                 },
                 self.colours.invalid_query_style,
-            )));
-            search_text.push(option_text);
+            ));
+            search_text.extend(option_text);
 
             let current_border_style = if proc_widget_state
                 .process_search_state
@@ -459,17 +463,15 @@ impl ProcessTableWidget for Painter {
 
                 let repeat_num =
                     usize::from(draw_loc.width).saturating_sub(TITLE_BASE.chars().count() + 2);
-                Span::styled(
-                    format!("{} Esc to close ", "─".repeat(repeat_num)),
-                    current_border_style,
-                )
+                format!("{} Esc to close ", "─".repeat(repeat_num))
             } else {
-                Span::from(String::new())
+                String::new()
             };
 
             let process_search_block = if draw_border {
                 Block::default()
-                    .title(title)
+                    .title(&title)
+                    .title_style(current_border_style)
                     .borders(Borders::ALL)
                     .border_style(current_border_style)
             } else if is_on_widget {
@@ -487,7 +489,7 @@ impl ProcessTableWidget for Painter {
                 .split(draw_loc);
 
             f.render_widget(
-                Paragraph::new(search_text)
+                Paragraph::new(search_text.iter())
                     .block(process_search_block)
                     .style(self.colours.text_style)
                     .alignment(Alignment::Left),
diff --git a/src/canvas/widgets/temp_table.rs b/src/canvas/widgets/temp_table.rs
index 0b5bd42f..23822b68 100644
--- a/src/canvas/widgets/temp_table.rs
+++ b/src/canvas/widgets/temp_table.rs
@@ -5,7 +5,6 @@ use tui::{
     backend::Backend,
     layout::{Constraint, Direction, Layout, Rect},
     terminal::Frame,
-    text::Span,
     widgets::{Block, Borders, Row, Table},
 };
 
@@ -79,28 +78,27 @@ impl TempTableWidget for Painter {
 
             let title = if app_state.is_expanded {
                 const TITLE_BASE: &str = " Temperatures ── Esc to go back ";
-                Span::styled(
-                    format!(
-                        " Temperatures ─{}─ Esc to go back ",
-                        "─".repeat(
-                            usize::from(draw_loc.width)
-                                .saturating_sub(TITLE_BASE.chars().count() + 2)
-                        )
-                    ),
-                    border_and_title_style,
+                format!(
+                    " Temperatures ─{}─ Esc to go back ",
+                    "─".repeat(
+                        usize::from(draw_loc.width).saturating_sub(TITLE_BASE.chars().count() + 2)
+                    )
                 )
             } else if app_state.app_config_fields.use_basic_mode {
-                Span::from(String::new())
+                String::new()
             } else {
-                Span::styled(
-                    " Temperatures ".to_string(),
-                    self.colours.widget_title_style,
-                )
+                " Temperatures ".to_string()
+            };
+            let title_style = if app_state.is_expanded {
+                border_and_title_style
+            } else {
+                self.colours.widget_title_style
             };
 
             let temp_block = if draw_border {
                 Block::default()
-                    .title(title)
+                    .title(&title)
+                    .title_style(title_style)
                     .borders(Borders::ALL)
                     .border_style(border_and_title_style)
             } else if is_on_widget {
diff --git a/src/constants.rs b/src/constants.rs
index 572a6e5b..c2483aed 100644
--- a/src/constants.rs
+++ b/src/constants.rs
@@ -43,126 +43,126 @@ lazy_static! {
 
 // Help text
 pub const HELP_CONTENTS_TEXT: [&str; 7] = [
-    "Press the corresponding numbers to jump to the section, or scroll:",
-    "1 - General",
-    "2 - CPU widget",
-    "3 - Process widget",
-    "4 - Process search widget",
-    "5 - Process sort widget",
+    "Press the corresponding numbers to jump to the section, or scroll:\n",
+    "1 - General\n",
+    "2 - CPU widget\n",
+    "3 - Process widget\n",
+    "4 - Process search widget\n",
+    "5 - Process sort widget\n",
     "6 - Battery widget",
 ];
 
 pub const GENERAL_HELP_TEXT: [&str; 29] = [
-    "1 - General",
-    "q, Ctrl-c      Quit",
-    "Esc            Close dialog windows, search, widgets, or exit expanded mode",
-    "Ctrl-r         Reset display and any collected data",
-    "f              Freeze/unfreeze updating with new data",
-    "Ctrl-Left,     ",
-    "Shift-Left,    Move widget selection left",
-    "H, A           ",
-    "Ctrl-Right,    ",
-    "Shift-Right,   Move widget selection right",
-    "L, D           ",
-    "Ctrl-Up,       ",
-    "Shift-Up,      Move widget selection up",
-    "K, W           ",
-    "Ctrl-Down,     ",
-    "Shift-Down,    Move widget selection down",
-    "J, S           ",
-    "Left, h        Move left within widget",
-    "Down, j        Move down within widget",
-    "Up, k          Move up within widget",
-    "Right, l       Move right within widget",
-    "?              Open help menu",
-    "gg             Jump to the first entry",
-    "G              Jump to the last entry",
-    "e              Expand the currently selected widget",
-    "+              Zoom in on chart (decrease time range)",
-    "-              Zoom out on chart (increase time range)",
-    "=              Reset zoom",
+    "1 - General\n",
+    "q, Ctrl-c      Quit\n",
+    "Esc            Close dialog windows, search, widgets, or exit expanded mode\n",
+    "Ctrl-r         Reset display and any collected data\n",
+    "f              Freeze/unfreeze updating with new data\n",
+    "Ctrl-Left,     \n",
+    "Shift-Left,    Move widget selection left\n",
+    "H, A           \n",
+    "Ctrl-Right,    \n",
+    "Shift-Right,   Move widget selection right\n",
+    "L, D           \n",
+    "Ctrl-Up,       \n",
+    "Shift-Up,      Move widget selection up\n",
+    "K, W           \n",
+    "Ctrl-Down,     \n",
+    "Shift-Down,    Move widget selection down\n",
+    "J, S           \n",
+    "Left, h        Move left within widget\n",
+    "Down, j        Move down within widget\n",
+    "Up, k          Move up within widget\n",
+    "Right, l       Move right within widget\n",
+    "?              Open help menu\n",
+    "gg             Jump to the first entry\n",
+    "G              Jump to the last entry\n",
+    "e              Expand the currently selected widget\n",
+    "+              Zoom in on chart (decrease time range)\n",
+    "-              Zoom out on chart (increase time range)\n",
+    "=              Reset zoom\n",
     "Mouse scroll   Scroll through the tables or zoom in/out of charts by scrolling up/down",
 ];
 
 pub const CPU_HELP_TEXT: [&str; 2] = [
-    "2 - CPU widget",
+    "2 - CPU widget\n",
     "Mouse scroll   Scrolling over an CPU core/average shows only that entry on the chart",
 ];
 
 // TODO [Help]: Search in help?
 // TODO [Help]: Move to using tables for easier formatting?
 pub const PROCESS_HELP_TEXT: [&str; 11] = [
-    "3 - Process widget",
-    "dd             Kill the selected process",
-    "c              Sort by CPU usage, press again to reverse sorting order",
-    "m              Sort by memory usage, press again to reverse sorting order",
-    "p              Sort by PID name, press again to reverse sorting order",
-    "n              Sort by process name, press again to reverse sorting order",
-    "Tab            Group/un-group processes with the same name",
-    "Ctrl-f, /      Open process search widget",
-    "P              Toggle between showing the full path or just the process name",
-    "s, F6          Open process sort widget",
+    "3 - Process widget\n",
+    "dd             Kill the selected process\n",
+    "c              Sort by CPU usage, press again to reverse sorting order\n",
+    "m              Sort by memory usage, press again to reverse sorting order\n",
+    "p              Sort by PID name, press again to reverse sorting order\n",
+    "n              Sort by process name, press again to reverse sorting order\n",
+    "Tab            Group/un-group processes with the same name\n",
+    "Ctrl-f, /      Open process search widget\n",
+    "P              Toggle between showing the full path or just the process name\n",
+    "s, F6          Open process sort widget\n",
     "I              Invert current sort",
 ];
 
 pub const SEARCH_HELP_TEXT: [&str; 43] = [
-    "4 - Process search widget",
-    "Tab            Toggle between searching for PID and name",
-    "Esc            Close the search widget (retains the filter)",
-    "Ctrl-a         Skip to the start of the search query",
-    "Ctrl-e         Skip to the end of the search query",
-    "Ctrl-u         Clear the current search query",
-    "Backspace      Delete the character behind the cursor",
-    "Delete         Delete the character at the cursor",
-    "Alt-c/F1       Toggle matching case",
-    "Alt-w/F2       Toggle matching the entire word",
-    "Alt-r/F3       Toggle using regex",
-    "Left, Alt-h    Move cursor left",
-    "Right, Alt-l   Move cursor right",
-    "",
-    "Search keywords:",
-    "pid            ex: pid 825",
-    "cpu            ex: cpu > 4.2",
-    "mem            ex: mem < 4.2",
-    "read           ex: read >= 1 b",
-    "write          ex: write <= 1 tb",
-    "tread          ex: tread = 1",
-    "twrite         ex: twrite = 1",
-    "",
-    "Comparison operators:",
-    "=              ex: cpu = 1",
-    ">              ex: cpu > 1",
-    "<              ex: cpu < 1",
-    ">=             ex: cpu >= 1",
-    "<=             ex: cpu <= 1",
-    "",
-    "Logical operators:",
-    "and/&&/<Space> ex: btm and cpu > 1 and mem > 1",
-    "or/||          ex: btm or firefox",
-    "",
-    "Supported units:",
-    "B              ex: read > 1 b",
-    "KB             ex: read > 1 kb",
-    "MB             ex: read > 1 mb",
-    "TB             ex: read > 1 tb",
-    "KiB            ex: read > 1 kib",
-    "MiB            ex: read > 1 mib",
-    "GiB            ex: read > 1 gib",
+    "4 - Process search widget\n",
+    "Tab            Toggle between searching for PID and name\n",
+    "Esc            Close the search widget (retains the filter)\n",
+    "Ctrl-a         Skip to the start of the search query\n",
+    "Ctrl-e         Skip to the end of the search query\n",
+    "Ctrl-u         Clear the current search query\n",
+    "Backspace      Delete the character behind the cursor\n",
+    "Delete         Delete the character at the cursor\n",
+    "Alt-c/F1       Toggle matching case\n",
+    "Alt-w/F2       Toggle matching the entire word\n",
+    "Alt-r/F3       Toggle using regex\n",
+    "Left, Alt-h    Move cursor left\n",
+    "Right, Alt-l   Move cursor right\n",
+    "\n",
+    "Search keywords:\n",
+    "pid            ex: pid 825\n",
+    "cpu            ex: cpu > 4.2\n",
+    "mem            ex: mem < 4.2\n",
+    "read           ex: read >= 1 b\n",
+    "write          ex: write <= 1 tb\n",
+    "tread          ex: tread = 1\n",
+    "twrite         ex: twrite = 1\n",
+    "\n",
+    "Comparison operators:\n",
+    "=              ex: cpu = 1\n",
+    ">              ex: cpu > 1\n",
+    "<              ex: cpu < 1\n",
+    ">=             ex: cpu >= 1\n",
+    "<=             ex: cpu <= 1\n",
+    "\n",
+    "Logical operators:\n",
+    "and/&&/<Space> ex: btm and cpu > 1 and mem > 1\n",
+    "or/||          ex: btm or firefox\n",
+    "\n",
+    "Supported units:\n",
+    "B              ex: read > 1 b\n",
+    "KB             ex: read > 1 kb\n",
+    "MB             ex: read > 1 mb\n",
+    "TB             ex: read > 1 tb\n",
+    "KiB            ex: read > 1 kib\n",
+    "MiB            ex: read > 1 mib\n",
+    "GiB            ex: read > 1 gib\n",
     "TiB            ex: read > 1 tib",
 ];
 
 pub const SORT_HELP_TEXT: [&str; 6] = [
-    "5 - Sort widget",
-    "Down, 'j'      Scroll down in list",
-    "Up, 'k'        Scroll up in list",
-    "Mouse scroll   Scroll through sort widget",
-    "Esc            Close the sort widget",
+    "5 - Sort widget\n",
+    "Down, 'j'      Scroll down in list\n",
+    "Up, 'k'        Scroll up in list\n",
+    "Mouse scroll   Scroll through sort widget\n",
+    "Esc            Close the sort widget\n",
     "Enter          Sort by current selected column",
 ];
 
 pub const BATTERY_HELP_TEXT: [&str; 3] = [
-    "6 - Battery widget",
-    "Left           Go to previous battery",
+    "6 - Battery widget\n",
+    "Left           Go to previous battery\n",
     "Right          Go to next battery",
 ];