1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License in the LICENSE-APACHE file or at:
//     https://www.apache.org/licenses/LICENSE-2.0

//! Widgets

#[cfg(not(feature = "layout"))] mod layout_extern;

#[cfg(feature = "cassowary")]
#[macro_use] mod layout_cw;

mod class;
mod data;

#[cfg(not(feature = "layout"))]
pub use self::layout_extern::{Layout, ChildLayout, GridPos};
#[cfg(feature = "cassowary")]
pub use self::layout_cw::{Layout};

pub use self::data::*;
pub use self::class::Class;
use crate::toolkit::TkData;

/// Common widget behaviour
pub trait Core {
    /// Get the widget's number
    fn number(&self) -> u32;
    
    /// Set the widget's number
    /// 
    /// This should only be called during widget enumeration. It will panic if
    /// the number has already been set (to anything other than 0).
    fn set_number(&mut self, number: u32);
    
    /// Get the toolkit data associated with this widget
    fn tkd(&self) -> TkData;
    
    /// Set the toolkit data associated with this widget
    /// 
    /// This will panic if the toolkit data is not null.
    fn set_tkd(&mut self, tkd: TkData);
    
    /// Get the widget's region, relative to its parent.
    fn rect(&self) -> &Rect;
    
    /// Get mutable access to the widget's region
    fn rect_mut(&mut self) -> &mut Rect;
}

/// Common widget data
/// 
/// Widgets should normally implement `Core` by use of an embedded field
/// of this type (i.e. composition). The `kas::derive` macro may be used
/// to write the actual implementation:
/// 
/// ```notest
/// # // test fails: kas_impl uses the wrong prefix for crate?
/// extern crate kas;
/// 
/// #[kas::kas_impl(Core(core))]
/// struct MyWidget {
///     core: kas::widget::CoreData,
///     // more fields here
/// }
/// 
/// 
/// # fn main() {}
/// ```
#[derive(Clone, Default, Debug)]
pub struct CoreData {
    number: u32,
    tkd: TkData,
    rect: Rect,
}

impl Core for CoreData {
    #[inline]
    fn number(&self) -> u32 {
        self.number
    }
    
    #[inline]
    fn set_number(&mut self, number: u32) {
        if self.number != 0 {
            panic!("widget number has been set twice");
        }
        self.number = number;
    }
    
    #[inline]
    fn tkd(&self) -> TkData {
        self.tkd.clone()
    }
    
    #[inline]
    fn set_tkd(&mut self, tkd: TkData) {
        if !self.tkd.is_null() && !tkd.is_null() {
            panic!("widget's toolkit data has been set twice");
        }
        self.tkd = tkd;
    }
    
    #[inline]
    fn rect(&self) -> &Rect {
        &self.rect
    }
    
    #[inline]
    fn rect_mut(&mut self) -> &mut Rect {
        &mut self.rect
    }
}

/// A widget encapsulates code for event handling and/or drawing some feature
/// of a sub-region of a window.
/// 
/// Functionality common to all widgets is provided by the `Core` trait.
pub trait Widget: Layout {
    /// Get the widget's classification.
    fn class(&self) -> Class;
    
    /// Get the widget's label, if any.
    /// TODO: keep?
    fn label(&self) -> Option<&str>;
    
    /// Get whether this input field is editable.
    /// TODO: this should not be here, but we don't yet have downcast support!
    fn is_editable(&self) -> bool {
        false
    }
    
    /// Get the number of child widgets
    fn len(&self) -> usize;
    
    /// Get a reference to a child widget by index, or `None` if the index is
    /// out of bounds.
    /// 
    /// For convenience, `Index<usize>` is implemented via this method.
    /// 
    /// Required: `index < self.len()`.
    fn get(&self, index: usize) -> Option<&Widget>;
    
    /// Mutable variant of get
    fn get_mut(&mut self, index: usize) -> Option<&mut Widget>;
    
    /// Set the number for self and each child. Returns own number + 1.
    fn enumerate(&mut self, mut n: u32) -> u32 {
        for i in 0..self.len() {
            self.get_mut(i).map(|w| n = w.enumerate(n));
        }
        self.set_number(n);
        n + 1
    }
}

pub struct ChildIter<'a, W: 'a + Widget + ?Sized> {
    w: &'a W,
    i: ::std::ops::Range<usize>,
}

impl<'a, W: 'a + Widget + ?Sized> ChildIter<'a, W> {
    pub fn new(widget: &'a W) -> Self {
        ChildIter { w: widget, i: (0..widget.len()).into_iter() }
    }
}

impl<'a, W: 'a + Widget + ?Sized> Iterator for ChildIter<'a, W> {
    type Item = &'a Widget;
    fn next(&mut self) -> Option<Self::Item> {
        self.i.next().and_then(|i| self.w.get(i))
    }
}
/*
pub struct ChildIterMut<'a, W: 'static + Widget + ?Sized> {
    w: &'a mut W,
    i: ::std::ops::Range<usize>,
}

impl<'a, W: 'static + Widget + ?Sized> ChildIterMut<'a, W> {
    fn new(widget: &'a mut W) -> Self {
        let len = widget.len();
        ChildIterMut { w: widget, i: (0..len).into_iter() }
    }
    
    fn next<'b: 'a>(&'b mut self) -> Option<&'b mut Widget> {
        // TODO: resolve lifetime error (streaming iterator)
        self.i.next().and_then(|i| self.w.get_mut(i)).map(|w| &*w)
    }
}
*/