Skip to content

Commit

Permalink
simplify code by splitting left and right buttons
Browse files Browse the repository at this point in the history
  • Loading branch information
Ilya Malyavin committed Jun 3, 2023
1 parent c79dc0b commit ddafd1b
Showing 1 changed file with 98 additions and 111 deletions.
209 changes: 98 additions & 111 deletions src/buttons.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,24 +12,21 @@ const BUTTON_SPACING: f32 = 13.;

#[derive(Debug)]
pub(crate) struct Buttons {
// Sorted by index vec of buttons.
// Indicies from left and right sides are mixed
buttons: Vec<ButtonBox>,
// Sorted by index vec of buttons for left/right sides
buttons_left: Vec<Button>,
buttons_right: Vec<Button>,
layout_config: Option<(String, String)>,
}

// Wraps button and defines its layout
#[derive(Debug, Clone)]
pub struct ButtonBox {
index: u32,
side: Side,
button: Button,
}
type ButtonLayout = (Vec<Button>, Vec<Button>);

impl Default for Buttons {
fn default() -> Self {
let (buttons_left, buttons_right) = Buttons::get_default_buttons_layout();

Self {
buttons: Buttons::get_default_buttons_layout(),
buttons_left,
buttons_right,
layout_config: None,
}
}
Expand All @@ -40,8 +37,9 @@ impl Buttons {
let mut instance = Self::default();

match Buttons::parse_button_layout(config_string.clone()) {
Some(buttons) => {
instance.buttons = buttons;
Some((buttons_left, buttons_right)) => {
instance.buttons_left = buttons_left;
instance.buttons_right = buttons_right;
instance.layout_config = config_string;
}
_ => (),
Expand All @@ -55,33 +53,34 @@ impl Buttons {
let mut left_x = BUTTON_MARGIN;
let mut right_x = width as f32 - BUTTON_MARGIN;

for button_box in &mut self.buttons {
if button_box.side == Side::Left {
button_box.button.offset = left_x;
for button in &mut self.buttons_left {
button.offset = left_x;

// Add the button size plus spacing
left_x += BUTTON_SIZE + BUTTON_SPACING;
}

// Add the button size plus spacing
left_x += BUTTON_SIZE + BUTTON_SPACING;
} else {
// Subtract the button size.
right_x -= BUTTON_SIZE;
for button in &mut self.buttons_right {
// Subtract the button size.
right_x -= BUTTON_SIZE;

// Update it
button_box.button.offset = right_x;
// Update it
button.offset = right_x;

// Subtract spacing for the next button.
right_x -= BUTTON_SPACING;
}
// Subtract spacing for the next button.
right_x -= BUTTON_SPACING;
}
}

/// Find the coordinate of the button.
pub fn find_button(&self, x: f64, y: f64) -> Location {
let x = x as f32;
let y = y as f32;
let buttons = self.buttons_left.iter().chain(self.buttons_right.iter());

for button_box in self.buttons.iter() {
if button_box.button.contains(x, y) {
return Location::Button(button_box.button.kind);
for button in buttons {
if button.contains(x, y) {
return Location::Button(button.kind);
}
}

Expand All @@ -96,35 +95,32 @@ impl Buttons {
}

pub fn update_buttons(&mut self, supports_maximize: bool, supports_minimize: bool) {
self.buttons = Buttons::parse_button_layout(self.layout_config.clone())
.unwrap_or_else(Buttons::get_default_buttons_layout)
.into_iter()
.filter(|button_box| match button_box.button.kind {
ButtonKind::Close => true,
ButtonKind::Maximize => supports_maximize,
ButtonKind::Minimize => supports_minimize,
})
.collect::<Vec<ButtonBox>>();
let is_supported = |button: &Button| match button.kind {
ButtonKind::Close => true,
ButtonKind::Maximize => supports_maximize,
ButtonKind::Minimize => supports_minimize,
};

let (buttons_left, buttons_right) =
Buttons::parse_button_layout(self.layout_config.clone())
.unwrap_or_else(Buttons::get_default_buttons_layout);

self.buttons_left = buttons_left.into_iter().filter(is_supported).collect();
self.buttons_right = buttons_right.into_iter().filter(is_supported).collect();
}

pub fn right_buttons_start_x(&self) -> Option<f32> {
for button_box in self.buttons.iter().rev() {
if button_box.side == Side::Right {
return Some(button_box.button.x());
}
match self.buttons_right.last() {
Some(button) => Some(button.x()),
None => None,
}

None
}

pub fn left_buttons_end_x(&self) -> Option<f32> {
for button_box in self.buttons.iter().rev() {
if button_box.side == Side::Left {
return Some(button_box.button.end_x());
}
match self.buttons_left.last() {
Some(button) => Some(button.end_x()),
None => None,
}

None
}

pub fn draw(
Expand All @@ -140,86 +136,77 @@ impl Buttons {
) {
let left_buttons_right_limit =
self.right_buttons_start_x().unwrap_or(end_x).min(end_x) - BUTTON_SPACING;
let buttons_left = self.buttons_left.iter().map(|x| (x, Side::Left));
let buttons_right = self.buttons_right.iter().map(|x| (x, Side::Right));

for (button, side) in buttons_left.chain(buttons_right) {
let is_visible = button.x() > start_x && button.end_x() < end_x
// If we have buttons from both sides and they overlap, prefer the right side
&& (side == Side::Right || button.end_x() < left_buttons_right_limit);

let visible_buttons = self
.buttons
.iter()
// Buttons should be within a viewport
.filter(|x| x.button.x() > start_x && x.button.end_x() < end_x)
// If we have buttons from both sides and they overlap, prefer the right side
.filter(|x| x.side == Side::Right || x.button.end_x() < left_buttons_right_limit);

for button_box in visible_buttons {
button_box
.button
.draw(scale, colors, mouse_location, pixmap, resizable, state);
if is_visible {
button.draw(scale, colors, mouse_location, pixmap, resizable, state);
}
}
}

fn parse_button_layout(sides: Option<(String, String)>) -> Option<Vec<ButtonBox>> {
fn parse_button_layout(sides: Option<(String, String)>) -> Option<ButtonLayout> {
if sides.is_none() {
return None;
}

let (left_side, right_side) = sides.unwrap();

let mut buttons: Vec<ButtonBox> = vec![];
let buttons_left = Buttons::parse_button_layout_side(left_side, Side::Left);
let buttons_right = Buttons::parse_button_layout_side(right_side, Side::Right);

for (side, config) in [(Side::Left, left_side), (Side::Right, right_side)] {
let mut index: u32 = 0;

for button in config.split(",").take(3) {
let button_kind = match button {
"close" => Some(ButtonKind::Close),
"maximize" => Some(ButtonKind::Maximize),
"minimize" => Some(ButtonKind::Minimize),
_ => None,
};

if button_kind.is_none() {
warn!("Found unkown button type, ignoring");
continue;
}
let kind = button_kind.unwrap();

buttons.push(ButtonBox {
index,
side,
button: Button::new(kind),
});
index += 1;
}
}

if buttons.len() == 0 {
if buttons_left.len() == 0 && buttons_right.len() == 0 {
warn!("No valid buttons found in configuration");
return None;
}

// sort buttons in place
buttons.sort_unstable_by_key(|button| button.index);
Some((buttons_left, buttons_right))
}

fn parse_button_layout_side(config: String, side: Side) -> Vec<Button> {
let mut buttons: Vec<Button> = vec![];

for button in config.split(",").take(3) {
let button_kind = match button {
"close" => Some(ButtonKind::Close),
"maximize" => Some(ButtonKind::Maximize),
"minimize" => Some(ButtonKind::Minimize),
_ => None,
};

if button_kind.is_none() {
warn!("Found unknown button type, ignoring");
continue;
}
let kind = button_kind.unwrap();
buttons.push(Button::new(kind));
}

// For right side, we need to revert the order
let buttons = if side == Side::Right {
buttons.into_iter().rev().collect()
} else {
buttons
};

Some(buttons)
buttons
}

fn get_default_buttons_layout() -> Vec<ButtonBox> {
vec![
ButtonBox {
side: Side::Right,
index: 0,
button: Button::new(ButtonKind::Close),
},
ButtonBox {
side: Side::Right,
index: 1,
button: Button::new(ButtonKind::Maximize),
},
ButtonBox {
side: Side::Right,
index: 2,
button: Button::new(ButtonKind::Minimize),
},
]
fn get_default_buttons_layout() -> ButtonLayout {
(
vec![],
vec![
Button::new(ButtonKind::Close),
Button::new(ButtonKind::Maximize),
Button::new(ButtonKind::Minimize),
],
)
}
}

Expand Down

0 comments on commit ddafd1b

Please sign in to comment.