use std::{fmt, mem, ptr};
use std::default::Default;
use qualia::{SurfaceId, Area, Position, Size};
type Link = Option<Frame>;
struct Edges {
prev: Link,
next: Link,
first: Link,
last: Link,
}
impl Default for Edges {
fn default() -> Self {
Edges {
prev: None,
next: None,
first: None,
last: None,
}
}
}
struct Node {
matter: Link,
space: Edges,
time: Edges,
}
impl Default for Node {
fn default() -> Self {
Node {
matter: None,
space: Edges::default(),
time: Edges::default(),
}
}
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum Geometry {
Vertical,
Horizontal,
Stacked,
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum Mobility {
Floating,
Anchored,
Docked,
}
impl Mobility {
pub fn is_floating(&self) -> bool {
*self == Mobility::Floating
}
pub fn is_anchored(&self) -> bool {
*self == Mobility::Anchored
}
pub fn is_docked(&self) -> bool {
*self == Mobility::Docked
}
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum Mode {
Root,
Display{id: i32},
Workspace{is_active: bool},
Container,
Leaf,
}
impl Mode {
pub fn is_display(&self) -> bool {
if let Mode::Display{id: _} = *self {
true
} else {
false
}
}
pub fn is_workspace(&self) -> bool {
if let Mode::Workspace{is_active: _} = *self {
true
} else {
false
}
}
pub fn is_leaf(&self) -> bool {
*self == Mode::Leaf
}
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum Side {
Before,
On,
After,
}
pub struct Parameters {
pub sid: SurfaceId,
pub geometry: Geometry,
pub mobility: Mobility,
pub mode: Mode,
pub pos: Position,
pub size: Size,
pub title: String,
}
impl Parameters {
pub fn new_root() -> Self {
Parameters {
sid: SurfaceId::invalid(),
geometry: Geometry::Stacked,
mobility: Mobility::Floating,
mode: Mode::Root,
pos: Position::default(),
size: Size::default(),
title: "root".to_owned(),
}
}
pub fn new_display(id: i32, area: Area, title: String) -> Self {
Parameters {
sid: SurfaceId::invalid(),
geometry: Geometry::Stacked,
mobility: Mobility::Floating,
mode: Mode::Display{id: id},
pos: area.pos,
size: area.size,
title: title,
}
}
pub fn new_workspace(title: String, geometry: Geometry, active: bool) -> Self {
Parameters {
sid: SurfaceId::invalid(),
geometry: geometry,
mobility: Mobility::Anchored,
mode: Mode::Workspace{is_active: active},
pos: Position::default(),
size: Size::default(),
title: title,
}
}
pub fn new_container(geometry: Geometry) -> Self {
Parameters {
sid: SurfaceId::invalid(),
geometry: geometry,
mobility: Mobility::Anchored,
mode: Mode::Container,
pos: Position::default(),
size: Size::default(),
title: "".to_owned(),
}
}
pub fn new_leaf(sid: SurfaceId, geometry: Geometry) -> Self {
Parameters {
sid: sid,
geometry: geometry,
mobility: Mobility::Anchored,
mode: Mode::Leaf,
pos: Position::default(),
size: Size::default(),
title: "".to_owned(),
}
}
}
pub struct InnerFrame {
params: Parameters,
node: Node,
}
#[derive(Clone)]
pub struct Frame {
inner: *mut InnerFrame,
}
impl Frame {
pub fn new(sid: SurfaceId,
geometry: Geometry,
mobility: Mobility,
mode: Mode,
pos: Position,
size: Size,
title: String)
-> Self {
Self::allocate(InnerFrame {
params: Parameters {
sid: sid,
geometry: geometry,
mobility: mobility,
mode: mode,
pos: pos,
size: size,
title: title,
},
node: Node::default(),
})
}
pub fn new_root() -> Self {
Self::allocate(InnerFrame {
params: Parameters::new_root(),
node: Node::default(),
})
}
pub fn new_display(id: i32, area: Area, title: String) -> Self {
Self::allocate(InnerFrame {
params: Parameters::new_display(id, area, title),
node: Node::default(),
})
}
pub fn new_workspace(title: String, geometry: Geometry, active: bool) -> Self {
Self::allocate(InnerFrame {
params: Parameters::new_workspace(title, geometry, active),
node: Node::default(),
})
}
pub fn new_container(geometry: Geometry) -> Self {
Self::allocate(InnerFrame {
params: Parameters::new_container(geometry),
node: Node::default(),
})
}
pub fn new_leaf(sid: SurfaceId, geometry: Geometry) -> Self {
Self::allocate(InnerFrame {
params: Parameters::new_leaf(sid, geometry),
node: Node::default(),
})
}
pub fn destroy(&self) {
for f in self.time_iter() {
f.destroy();
}
self.deallocate();
}
}
impl Frame {
pub fn time_iter(&self) -> FrameTimeIterator {
FrameTimeIterator { frame: self.get_first_time() }
}
pub fn time_rev_iter(&self) -> FrameTimeReveresedIterator {
FrameTimeReveresedIterator { frame: self.get_last_time() }
}
pub fn space_iter(&self) -> FrameSpaceIterator {
FrameSpaceIterator { frame: self.get_first_space() }
}
pub fn space_rev_iter(&self) -> FrameSpaceReveresedIterator {
FrameSpaceReveresedIterator { frame: self.get_last_space() }
}
}
impl Frame {
#[inline]
pub fn get_sid(&self) -> SurfaceId {
unsafe { (*self.inner).params.sid }
}
#[inline]
pub fn get_mode(&self) -> Mode {
unsafe { (*self.inner).params.mode }
}
#[inline]
pub fn get_geometry(&self) -> Geometry {
unsafe { (*self.inner).params.geometry }
}
#[inline]
pub fn get_mobility(&self) -> Mobility {
unsafe { (*self.inner).params.mobility }
}
#[inline]
pub fn get_position(&self) -> Position {
unsafe { (*self.inner).params.pos.clone() }
}
#[inline]
pub fn get_size(&self) -> Size {
unsafe { (*self.inner).params.size.clone() }
}
#[inline]
pub fn get_area(&self) -> Area {
Area::new(self.get_position(), self.get_size())
}
pub fn get_title(&self) -> String {
unsafe { (*self.inner).params.title.clone() }
}
pub fn is_top(&self) -> bool {
let mode = self.get_mode();
let mobility = self.get_mobility();
(mobility == Mobility::Docked) || ((mode != Mode::Container) && (mode != Mode::Leaf))
}
pub fn is_reanchorizable(&self) -> bool {
!self.is_top()
}
pub fn is_reorientable(&self) -> bool {
(!self.is_top()) || (self.get_mode().is_workspace())
}
pub fn make_active(&self, active: bool) {
if self.get_mode().is_workspace() {
unsafe {
(*self.inner).params.mode = Mode::Workspace{is_active: active};
}
}
}
}
impl Frame {
#[inline]
pub fn set_plumbing_sid(&mut self, sid: SurfaceId) {
unsafe {
(*self.inner).params.sid = sid;
}
}
#[inline]
pub fn set_plumbing_position(&mut self, pos: Position) {
unsafe {
(*self.inner).params.pos = pos;
}
}
#[inline]
pub fn set_plumbing_size(&mut self, size: Size) {
unsafe {
(*self.inner).params.size = size;
}
}
#[inline]
pub fn set_plumbing_geometry(&mut self, geometry: Geometry) {
unsafe {
(*self.inner).params.geometry = geometry;
}
}
#[inline]
pub fn set_plumbing_mobility(&mut self, mobility: Mobility) {
unsafe {
(*self.inner).params.mobility = mobility;
}
}
#[inline]
pub fn set_plumbing_mode(&mut self, mode: Mode) {
unsafe {
(*self.inner).params.mode = mode;
}
}
#[inline]
pub fn set_plumbing_position_and_size(&mut self, pos: Position, size: Size) {
unsafe {
(*self.inner).params.pos = pos;
}
unsafe {
(*self.inner).params.size = size;
}
}
}
impl Frame {
#[inline]
pub fn has_parent(&self) -> bool {
unsafe { (*self.inner).node.matter.is_some() }
}
#[inline]
pub fn has_children(&self) -> bool {
unsafe { (*self.inner).node.time.last.is_some() }
}
#[inline]
pub fn get_parent(&self) -> Option<Frame> {
unsafe { (*self.inner).node.matter.clone() }
}
#[inline]
pub fn get_first_time(&self) -> Option<Frame> {
unsafe { (*self.inner).node.time.first.clone() }
}
#[inline]
pub fn get_last_time(&self) -> Option<Frame> {
unsafe { (*self.inner).node.time.last.clone() }
}
#[inline]
pub fn get_prev_time(&self) -> Option<Frame> {
unsafe { (*self.inner).node.time.prev.clone() }
}
#[inline]
pub fn get_next_time(&self) -> Option<Frame> {
unsafe { (*self.inner).node.time.next.clone() }
}
#[inline]
pub fn get_first_space(&self) -> Option<Frame> {
unsafe { (*self.inner).node.space.first.clone() }
}
#[inline]
pub fn get_last_space(&self) -> Option<Frame> {
unsafe { (*self.inner).node.space.last.clone() }
}
#[inline]
pub fn get_prev_space(&self) -> Option<Frame> {
unsafe { (*self.inner).node.space.prev.clone() }
}
#[inline]
pub fn get_next_space(&self) -> Option<Frame> {
unsafe { (*self.inner).node.space.next.clone() }
}
}
impl Frame {
pub fn prepend(&mut self, frame: &mut Frame) {
self.append_time(frame);
self.prepend_space(frame);
frame.set_matter(self);
}
pub fn append(&mut self, frame: &mut Frame) {
self.append_time(frame);
self.append_space(frame);
frame.set_matter(self);
}
pub fn prejoin(&mut self, frame: &mut Frame) {
if let Some(ref mut parent) = self.get_parent() {
parent.append_time(frame);
if let Some(ref mut prev) = self.get_prev_space() {
prev.join_space(frame);
frame.join_space(self);
} else {
parent.prepend_space(frame);
}
frame.set_matter(parent);
}
}
pub fn adjoin(&mut self, frame: &mut Frame) {
if let Some(ref mut parent) = self.get_parent() {
parent.append_time(frame);
if let Some(ref mut next) = self.get_next_space() {
self.join_space(frame);
frame.join_space(next);
} else {
parent.append_space(frame);
}
frame.set_matter(parent);
}
}
pub fn pop(&mut self) {
if let Some(ref mut parent) = self.get_parent() {
self.unjoin_time();
parent.prepend_time(self);
}
}
pub fn remove(&mut self) {
if self.has_parent() {
self.unjoin_time();
self.unjoin_space();
self.reset_matter();
}
}
}
impl Frame {
#[inline]
fn set_matter(&mut self, frame: &Frame) {
unsafe {
(*self.inner).node.matter = Some(frame.clone());
}
}
#[inline]
fn reset_matter(&mut self) {
unsafe {
(*self.inner).node.matter = None;
}
}
#[inline]
fn prepend_time(&mut self, frame: &mut Frame) {
unsafe {
if let Some(ref mut first_time) = (*self.inner).node.time.first {
(*first_time.inner).node.time.prev = Some(frame.clone());
(*frame.inner).node.time.next = Some(first_time.clone());
} else {
(*self.inner).node.time.last = Some(frame.clone());
}
(*self.inner).node.time.first = Some(frame.clone());
}
}
#[inline]
fn append_time(&mut self, frame: &mut Frame) {
unsafe {
if let Some(ref mut last_time) = (*self.inner).node.time.last {
(*last_time.inner).node.time.next = Some(frame.clone());
(*frame.inner).node.time.prev = Some(last_time.clone());
} else {
(*self.inner).node.time.first = Some(frame.clone());
}
(*self.inner).node.time.last = Some(frame.clone());
}
}
#[inline]
fn prepend_space(&mut self, frame: &mut Frame) {
unsafe {
if let Some(ref mut first_space) = (*self.inner).node.space.first {
frame.join_space(first_space);
} else {
(*self.inner).node.space.last = Some(frame.clone());
}
(*self.inner).node.space.first = Some(frame.clone());
}
}
#[inline]
fn append_space(&mut self, frame: &mut Frame) {
unsafe {
if let Some(ref mut last_space) = (*self.inner).node.space.last {
last_space.join_space(frame);
} else {
(*self.inner).node.space.first = Some(frame.clone());
}
(*self.inner).node.space.last = Some(frame.clone());
}
}
#[inline]
fn join_space(&mut self, frame: &mut Frame) {
unsafe {
(*self.inner).node.space.next = Some(frame.clone());
(*frame.inner).node.space.prev = Some(self.clone());
}
}
#[inline]
fn unjoin_time(&mut self) {
unsafe {
if let Some(ref mut next_time) = (*self.inner).node.time.next {
(*next_time.inner).node.time.prev = (*self.inner).node.time.prev.clone();
} else if let Some(ref mut matter) = (*self.inner).node.matter {
(*matter.inner).node.time.last = (*self.inner).node.time.prev.clone();
}
if let Some(ref mut prev_time) = (*self.inner).node.time.prev {
(*prev_time.inner).node.time.next = (*self.inner).node.time.next.clone();
} else if let Some(ref mut matter) = (*self.inner).node.matter {
(*matter.inner).node.time.first = (*self.inner).node.time.next.clone();
}
(*self.inner).node.time.prev = None;
(*self.inner).node.time.next = None;
}
}
#[inline]
fn unjoin_space(&mut self) {
unsafe {
if let Some(ref mut next_space) = (*self.inner).node.space.next {
(*next_space.inner).node.space.prev = (*self.inner).node.space.prev.clone();
} else if let Some(ref mut matter) = (*self.inner).node.matter {
(*matter.inner).node.space.last = (*self.inner).node.space.prev.clone();
}
if let Some(ref mut prev_space) = (*self.inner).node.space.prev {
(*prev_space.inner).node.space.next = (*self.inner).node.space.next.clone();
} else if let Some(ref mut matter) = (*self.inner).node.matter {
(*matter.inner).node.space.first = (*self.inner).node.space.next.clone();
}
(*self.inner).node.space.prev = None;
(*self.inner).node.space.next = None;
}
}
}
impl Frame {
fn allocate(inner: InnerFrame) -> Self {
let ptr = {
let mut v = Vec::with_capacity(mem::size_of::<InnerFrame>());
let ptr = v.as_mut_ptr();
mem::forget(v);
ptr
} as *mut _;
unsafe {
ptr::write(ptr, inner);
}
Frame { inner: ptr }
}
fn deallocate(&self) {
let ptr = self.inner as *mut _;
unsafe {
mem::drop(Vec::from_raw_parts(ptr, 0, mem::size_of::<InnerFrame>()));
}
}
}
impl Frame {
#[inline]
pub fn equals_exact(&self, other: &Frame) -> bool {
self.inner == other.inner
}
pub fn count_children(&self) -> usize {
let mut result = 0;
for _ in self.time_iter() {
result += 1
}
result
}
pub fn count_anchored_children(&self) -> usize {
let mut result = 0;
for child in self.time_iter() {
if child.get_mobility().is_anchored() {
result += 1
}
}
result
}
pub fn calculate_global_position(&self) -> Position {
if let Some(parent) = self.get_parent() {
self.get_position() + parent.calculate_global_position()
} else {
Position::default()
}
}
}
impl fmt::Debug for Frame {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let pos = self.get_position();
let size = self.get_size();
write!(f,
"Frame {{ sid: {:?}, '{}', {:?}, {:?}, {:?}, {}x{}+{}+{} }}",
self.get_sid(),
self.get_title(),
self.get_mode(),
self.get_geometry(),
self.get_mobility(),
size.width,
size.height,
pos.x,
pos.y)
}
}
pub struct FrameTimeIterator {
frame: Link,
}
impl Iterator for FrameTimeIterator {
type Item = Frame;
fn next(&mut self) -> Option<Frame> {
let result = self.frame.clone();
self.frame = if let Some(ref mut frame) = self.frame {
frame.get_next_time()
} else {
None
};
result
}
}
pub struct FrameTimeReveresedIterator {
frame: Link,
}
impl Iterator for FrameTimeReveresedIterator {
type Item = Frame;
fn next(&mut self) -> Option<Frame> {
let result = self.frame.clone();
self.frame = if let Some(ref mut frame) = self.frame {
frame.get_prev_time()
} else {
None
};
result
}
}
pub struct FrameSpaceIterator {
frame: Link,
}
impl Iterator for FrameSpaceIterator {
type Item = Frame;
fn next(&mut self) -> Option<Frame> {
let result = self.frame.clone();
self.frame = if let Some(ref mut frame) = self.frame {
frame.get_next_space()
} else {
None
};
result
}
}
pub struct FrameSpaceReveresedIterator {
frame: Link,
}
impl Iterator for FrameSpaceReveresedIterator {
type Item = Frame;
fn next(&mut self) -> Option<Frame> {
let result = self.frame.clone();
self.frame = if let Some(ref mut frame) = self.frame {
frame.get_prev_space()
} else {
None
};
result
}
}