1use rmux_proto::{PaneTarget, SessionName};
2
3pub use rmux_proto::PaneId;
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq)]
7pub struct PaneGeometry {
8 x: u16,
9 y: u16,
10 cols: u16,
11 rows: u16,
12}
13
14impl PaneGeometry {
15 #[must_use]
17 pub const fn new(x: u16, y: u16, cols: u16, rows: u16) -> Self {
18 Self { x, y, cols, rows }
19 }
20
21 #[must_use]
23 pub const fn x(&self) -> u16 {
24 self.x
25 }
26
27 #[must_use]
29 pub const fn y(&self) -> u16 {
30 self.y
31 }
32
33 #[must_use]
35 pub const fn cols(&self) -> u16 {
36 self.cols
37 }
38
39 #[must_use]
41 pub const fn rows(&self) -> u16 {
42 self.rows
43 }
44}
45
46#[derive(Debug, Clone, PartialEq, Eq)]
48pub struct Pane {
49 id: PaneId,
50 index: u32,
51 geometry: PaneGeometry,
52 active_point: u64,
53}
54
55impl Pane {
56 #[must_use]
58 pub const fn id(&self) -> PaneId {
59 self.id
60 }
61
62 #[must_use]
64 pub const fn index(&self) -> u32 {
65 self.index
66 }
67
68 #[must_use]
70 pub const fn geometry(&self) -> PaneGeometry {
71 self.geometry
72 }
73
74 pub(crate) const fn active_point(&self) -> u64 {
75 self.active_point
76 }
77
78 #[must_use]
80 pub fn target(&self, session_name: &SessionName) -> PaneTarget {
81 PaneTarget::new(session_name.clone(), self.index)
82 }
83
84 #[cfg_attr(not(test), allow(dead_code))]
85 pub(crate) const fn new(index: u32, geometry: PaneGeometry) -> Self {
86 Self::new_with_id(PaneId::new(index), index, geometry)
87 }
88
89 pub(crate) const fn new_with_id(id: PaneId, index: u32, geometry: PaneGeometry) -> Self {
90 Self {
91 id,
92 index,
93 geometry,
94 active_point: 0,
95 }
96 }
97
98 pub(crate) fn set_geometry(&mut self, geometry: PaneGeometry) {
99 self.geometry = geometry;
100 }
101
102 pub(crate) fn set_index(&mut self, index: u32) {
103 self.index = index;
104 }
105
106 pub(crate) fn set_active_point(&mut self, active_point: u64) {
107 self.active_point = active_point;
108 }
109}
110
111#[cfg(test)]
112mod tests {
113 use super::{Pane, PaneGeometry, PaneId};
114 use rmux_proto::SessionName;
115
116 #[test]
117 fn geometry_accessors_match_constructor_values() {
118 let geometry = PaneGeometry::new(4, 7, 80, 24);
119
120 assert_eq!(geometry.x(), 4);
121 assert_eq!(geometry.y(), 7);
122 assert_eq!(geometry.cols(), 80);
123 assert_eq!(geometry.rows(), 24);
124 }
125
126 #[test]
127 fn pane_target_uses_session_name_and_index() {
128 let pane = Pane::new(3, PaneGeometry::new(0, 0, 10, 5));
129 let session_name = SessionName::new("alpha").expect("valid session name");
130
131 assert_eq!(pane.target(&session_name).to_string(), "alpha:0.3");
132 }
133
134 #[test]
135 fn pane_id_is_stable_and_independent_from_display_index() {
136 let pane = Pane::new_with_id(PaneId::new(9), 3, PaneGeometry::new(0, 0, 10, 5));
137
138 assert_eq!(pane.id(), PaneId::new(9));
139 assert_eq!(pane.index(), 3);
140 }
141
142 #[test]
143 fn set_geometry_replaces_the_existing_rectangle() {
144 let mut pane = Pane::new(0, PaneGeometry::new(0, 0, 10, 5));
145 let replacement = PaneGeometry::new(12, 1, 34, 50);
146
147 pane.set_geometry(replacement);
148
149 assert_eq!(pane.geometry(), replacement);
150 }
151}