|
@@ -12,12 +12,24 @@ use std::sync::Arc;
|
|
|
use std::iter;
|
|
|
use std::slice;
|
|
|
|
|
|
+struct WidgetState {
|
|
|
+ widget: Box<Widget>,
|
|
|
+ position: u16,
|
|
|
+ width: u16
|
|
|
+}
|
|
|
+
|
|
|
+impl WidgetState {
|
|
|
+ fn contains(&self, x: u16) -> bool {
|
|
|
+ x >= self.position && x < self.position + self.width
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
pub struct Panel {
|
|
|
pub conn: Arc<x11::Connection>,
|
|
|
pub window: xcb::Window,
|
|
|
pub width: u16,
|
|
|
- left_widgets: Vec<Box<Widget>>,
|
|
|
- right_widgets: Vec<Box<Widget>>,
|
|
|
+ left_widgets: Vec<WidgetState>,
|
|
|
+ right_widgets: Vec<WidgetState>,
|
|
|
fonts: Rc<font::FontLoader>,
|
|
|
picture: xcb::render::Picture,
|
|
|
finishing: bool
|
|
@@ -62,7 +74,7 @@ impl Panel {
|
|
|
xcb::COPY_FROM_PARENT,
|
|
|
&[
|
|
|
(xcb::CW_BACK_PIXEL, 0xFF000000),
|
|
|
- (xcb::CW_EVENT_MASK, xcb::EVENT_MASK_EXPOSURE | xcb::EVENT_MASK_PROPERTY_CHANGE | xcb::EVENT_MASK_STRUCTURE_NOTIFY)
|
|
|
+ (xcb::CW_EVENT_MASK, xcb::EVENT_MASK_EXPOSURE | xcb::EVENT_MASK_PROPERTY_CHANGE | xcb::EVENT_MASK_STRUCTURE_NOTIFY | xcb::EVENT_MASK_BUTTON_PRESS)
|
|
|
]
|
|
|
);
|
|
|
self.set_property(
|
|
@@ -77,8 +89,8 @@ impl Panel {
|
|
|
(xcb::render::CP_POLY_MODE, xcb::render::POLY_MODE_IMPRECISE)
|
|
|
]);
|
|
|
self.conn.flush();
|
|
|
- for widget in self.widgets_iter() {
|
|
|
- widget.init();
|
|
|
+ for state in self.widgets_iter() {
|
|
|
+ state.widget.init();
|
|
|
}
|
|
|
self.conn.flush();
|
|
|
}
|
|
@@ -87,7 +99,7 @@ impl Panel {
|
|
|
widget::DrawContext::new(self.conn.clone_connection(), self.window, self.picture, self.fonts.clone())
|
|
|
}
|
|
|
|
|
|
- pub fn widgets_iter(&mut self) -> iter::Chain<slice::IterMut<Box<Widget>>, slice::IterMut<Box<Widget>>>{
|
|
|
+ fn widgets_iter(&mut self) -> iter::Chain<slice::IterMut<WidgetState>, slice::IterMut<WidgetState>>{
|
|
|
self.left_widgets.iter_mut().chain(self.right_widgets.iter_mut())
|
|
|
}
|
|
|
|
|
@@ -107,8 +119,8 @@ impl Panel {
|
|
|
let finishing = self.finishing;
|
|
|
let mut should_exit = false;
|
|
|
if !finishing {
|
|
|
- for widget in self.widgets_iter() {
|
|
|
- should_exit |= widget.handle_event(&event);
|
|
|
+ for state in self.widgets_iter() {
|
|
|
+ should_exit |= state.widget.handle_event(&event);
|
|
|
}
|
|
|
}
|
|
|
match event {
|
|
@@ -116,6 +128,17 @@ impl Panel {
|
|
|
if event.response_type() == xcb::EXPOSE {
|
|
|
self.relayout();
|
|
|
};
|
|
|
+ if event.response_type() == xcb::BUTTON_PRESS {
|
|
|
+ let event: &xcb::ButtonPressEvent = unsafe { xcb::cast_event(&event) };
|
|
|
+ let x = event.root_x() as u16;
|
|
|
+ for state in self.widgets_iter() {
|
|
|
+ if state.contains(x) {
|
|
|
+ let offset_x = x - state.position;
|
|
|
+ let event = widget::Message::MousePress(offset_x);
|
|
|
+ state.widget.handle_event(&event);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ };
|
|
|
if finishing && event.response_type() == xcb::DESTROY_NOTIFY {
|
|
|
let event: &xcb::DestroyNotifyEvent = unsafe { xcb::cast_event(&event) };
|
|
|
if event.window() == self.window {
|
|
@@ -135,11 +158,19 @@ impl Panel {
|
|
|
}
|
|
|
|
|
|
pub fn add_left_widget(&mut self, widget: Box<Widget>) {
|
|
|
- self.left_widgets.push(widget);
|
|
|
+ self.left_widgets.push(WidgetState{
|
|
|
+ widget: widget,
|
|
|
+ position: 0,
|
|
|
+ width: 0
|
|
|
+ });
|
|
|
}
|
|
|
|
|
|
pub fn add_right_widget(&mut self, widget: Box<Widget>) {
|
|
|
- self.right_widgets.push(widget);
|
|
|
+ self.right_widgets.push(WidgetState{
|
|
|
+ widget: widget,
|
|
|
+ position: 0,
|
|
|
+ width: 0
|
|
|
+ });
|
|
|
}
|
|
|
|
|
|
pub fn relayout(&mut self) {
|
|
@@ -151,23 +182,32 @@ impl Panel {
|
|
|
color,
|
|
|
&[xcb::Rectangle::new(0, 0, self.width, 20)]
|
|
|
);
|
|
|
+
|
|
|
+ // measure
|
|
|
let mut left_pos = 0;
|
|
|
- for widget in self.left_widgets.iter_mut() {
|
|
|
- widget.render(left_pos);
|
|
|
- left_pos += widget.width();
|
|
|
+ for state in self.left_widgets.iter_mut() {
|
|
|
+ state.position = left_pos;
|
|
|
+ state.width = state.widget.width();
|
|
|
+ left_pos += state.width;
|
|
|
}
|
|
|
let mut right_pos = self.width;
|
|
|
- for widget in self.right_widgets.iter_mut() {
|
|
|
- right_pos -= widget.width();
|
|
|
- widget.render(right_pos);
|
|
|
+ for state in self.right_widgets.iter_mut() {
|
|
|
+ state.width = state.widget.width();
|
|
|
+ right_pos -= state.width;
|
|
|
+ state.position = right_pos;
|
|
|
+ }
|
|
|
+
|
|
|
+ // render
|
|
|
+ for state in self.widgets_iter() {
|
|
|
+ state.widget.render(state.position);
|
|
|
}
|
|
|
self.conn.flush();
|
|
|
}
|
|
|
|
|
|
pub fn finish(&mut self) {
|
|
|
self.finishing = true;
|
|
|
- for widget in self.widgets_iter() {
|
|
|
- widget.finish();
|
|
|
+ for state in self.widgets_iter() {
|
|
|
+ state.widget.finish();
|
|
|
}
|
|
|
xcb::destroy_window(&self.conn, self.window);
|
|
|
self.conn.flush();
|