Fix formatting

This commit is contained in:
Drakulix 2017-04-26 20:10:22 +02:00
parent 4c5e2be11e
commit f7d3b3dee3
5 changed files with 186 additions and 111 deletions

View File

@ -4,9 +4,12 @@
use backend::{SeatInternal, TouchSlotInternal}; use backend::{SeatInternal, TouchSlotInternal};
use backend::graphics::GraphicsBackend; use backend::graphics::GraphicsBackend;
use backend::graphics::opengl::{Api, OpenglGraphicsBackend, PixelFormat, SwapBuffersError}; use backend::graphics::opengl::{Api, OpenglGraphicsBackend, PixelFormat, SwapBuffersError};
use backend::input::{Axis, AxisSource, InputBackend, InputHandler, KeyState, MouseButton, MouseButtonState, use backend::input::{Axis, AxisSource, Event as BackendEvent, InputBackend, InputHandler, KeyState,
Seat, SeatCapabilities, TouchSlot, Event as BackendEvent, KeyboardKeyEvent, PointerAxisEvent, PointerButtonEvent, PointerMotionAbsoluteEvent, TouchDownEvent, TouchUpEvent, TouchMotionEvent, TouchCancelEvent}; KeyboardKeyEvent, MouseButton, MouseButtonState, PointerAxisEvent, PointerButtonEvent,
use glutin::{Api as GlutinApi, MouseButton as GlutinMouseButton, PixelFormat as GlutinPixelFormat, MouseCursor}; PointerMotionAbsoluteEvent, Seat, SeatCapabilities, TouchCancelEvent, TouchDownEvent,
TouchMotionEvent, TouchSlot, TouchUpEvent};
use glutin::{Api as GlutinApi, MouseButton as GlutinMouseButton, MouseCursor,
PixelFormat as GlutinPixelFormat};
use glutin::{ContextError, CreationError, ElementState, Event, GlContext, HeadlessContext, use glutin::{ContextError, CreationError, ElementState, Event, GlContext, HeadlessContext,
HeadlessRendererBuilder, MouseScrollDelta, Touch, TouchPhase, Window, WindowBuilder}; HeadlessRendererBuilder, MouseScrollDelta, Touch, TouchPhase, Window, WindowBuilder};
use nix::c_void; use nix::c_void;
@ -85,7 +88,7 @@ impl GraphicsBackend for GlutinHeadlessRenderer {
type CursorFormat = (); type CursorFormat = ();
fn set_cursor_position(&mut self, _x: u32, _y: u32) -> Result<(), ()> { fn set_cursor_position(&mut self, _x: u32, _y: u32) -> Result<(), ()> {
//FIXME: Maybe save position? Is it of any use? // FIXME: Maybe save position? Is it of any use?
Ok(()) Ok(())
} }
@ -290,11 +293,21 @@ impl PointerMotionAbsoluteEvent for GlutinMouseMovedEvent {
} }
fn x_transformed(&self, width: u32) -> u32 { fn x_transformed(&self, width: u32) -> u32 {
cmp::min(self.x * width as i32 / self.window.get_inner_size_points().unwrap_or((width, 0)).0 as i32, 0) as u32 cmp::min(self.x * width as i32 /
self.window
.get_inner_size_points()
.unwrap_or((width, 0))
.0 as i32,
0) as u32
} }
fn y_transformed(&self, height: u32) -> u32 { fn y_transformed(&self, height: u32) -> u32 {
cmp::min(self.y * height as i32 / self.window.get_inner_size_points().unwrap_or((0, height)).1 as i32, 0) as u32 cmp::min(self.y * height as i32 /
self.window
.get_inner_size_points()
.unwrap_or((0, height))
.1 as i32,
0) as u32
} }
} }
@ -326,8 +339,10 @@ impl PointerAxisEvent for GlutinMouseWheelEvent {
fn amount(&self) -> f64 { fn amount(&self) -> f64 {
match (self.axis, self.delta) { match (self.axis, self.delta) {
(Axis::Horizontal, MouseScrollDelta::LineDelta(x, _)) | (Axis::Horizontal, MouseScrollDelta::PixelDelta(x, _)) => x as f64, (Axis::Horizontal, MouseScrollDelta::LineDelta(x, _)) |
(Axis::Vertical, MouseScrollDelta::LineDelta(_, y)) | (Axis::Vertical, MouseScrollDelta::PixelDelta(_, y)) => y as f64, (Axis::Horizontal, MouseScrollDelta::PixelDelta(x, _)) => x as f64,
(Axis::Vertical, MouseScrollDelta::LineDelta(_, y)) |
(Axis::Vertical, MouseScrollDelta::PixelDelta(_, y)) => y as f64,
} }
} }
} }
@ -385,11 +400,21 @@ impl TouchDownEvent for GlutinTouchStartedEvent {
} }
fn x_transformed(&self, width: u32) -> u32 { fn x_transformed(&self, width: u32) -> u32 {
cmp::min(self.location.0 as i32 * width as i32 / self.window.get_inner_size_points().unwrap_or((width, 0)).0 as i32, 0) as u32 cmp::min(self.location.0 as i32 * width as i32 /
self.window
.get_inner_size_points()
.unwrap_or((width, 0))
.0 as i32,
0) as u32
} }
fn y_transformed(&self, height: u32) -> u32 { fn y_transformed(&self, height: u32) -> u32 {
cmp::min(self.location.1 as i32 * height as i32 / self.window.get_inner_size_points().unwrap_or((0, height)).1 as i32, 0) as u32 cmp::min(self.location.1 as i32 * height as i32 /
self.window
.get_inner_size_points()
.unwrap_or((0, height))
.1 as i32,
0) as u32
} }
} }
@ -422,11 +447,19 @@ impl TouchMotionEvent for GlutinTouchMovedEvent {
} }
fn x_transformed(&self, width: u32) -> u32 { fn x_transformed(&self, width: u32) -> u32 {
self.location.0 as u32 * width / self.window.get_inner_size_points().unwrap_or((width, 0)).0 self.location.0 as u32 * width /
self.window
.get_inner_size_points()
.unwrap_or((width, 0))
.0
} }
fn y_transformed(&self, height: u32) -> u32 { fn y_transformed(&self, height: u32) -> u32 {
self.location.1 as u32 * height / self.window.get_inner_size_points().unwrap_or((0, height)).1 self.location.1 as u32 * height /
self.window
.get_inner_size_points()
.unwrap_or((0, height))
.1
} }
} }
@ -526,7 +559,9 @@ impl InputBackend for GlutinInputBackend {
Event::KeyboardInput(state, key_code, _) => { Event::KeyboardInput(state, key_code, _) => {
match state { match state {
ElementState::Pressed => self.key_counter += 1, ElementState::Pressed => self.key_counter += 1,
ElementState::Released => self.key_counter = self.key_counter.checked_sub(1).unwrap_or(0), ElementState::Released => {
self.key_counter = self.key_counter.checked_sub(1).unwrap_or(0)
}
}; };
handler.on_keyboard_key(&self.seat, handler.on_keyboard_key(&self.seat,
GlutinKeyboardInputEvent { GlutinKeyboardInputEvent {
@ -537,21 +572,23 @@ impl InputBackend for GlutinInputBackend {
}) })
} }
Event::MouseMoved(x, y) => { Event::MouseMoved(x, y) => {
handler.on_pointer_move_absolute(&self.seat, GlutinMouseMovedEvent { handler.on_pointer_move_absolute(&self.seat,
window: self.window.clone(), GlutinMouseMovedEvent {
time: self.time_counter, window: self.window.clone(),
x: x, time: self.time_counter,
y: y, x: x,
}) y: y,
})
} }
Event::MouseWheel(delta, _) => { Event::MouseWheel(delta, _) => {
let event = GlutinMouseWheelEvent { let event = GlutinMouseWheelEvent {
axis: Axis::Horizontal, axis: Axis::Horizontal,
time: self.time_counter, time: self.time_counter,
delta: delta, delta: delta,
}; };
match delta { match delta {
MouseScrollDelta::LineDelta(x, y) | MouseScrollDelta::PixelDelta(x, y) => { MouseScrollDelta::LineDelta(x, y) |
MouseScrollDelta::PixelDelta(x, y) => {
if x != 0.0 { if x != 0.0 {
handler.on_pointer_axis(&self.seat, event.clone()); handler.on_pointer_axis(&self.seat, event.clone());
} }
@ -562,11 +599,12 @@ impl InputBackend for GlutinInputBackend {
} }
} }
Event::MouseInput(state, button) => { Event::MouseInput(state, button) => {
handler.on_pointer_button(&self.seat, GlutinMouseInputEvent { handler.on_pointer_button(&self.seat,
time: self.time_counter, GlutinMouseInputEvent {
button: button, time: self.time_counter,
state: state, button: button,
}) state: state,
})
} }
Event::Touch(Touch { Event::Touch(Touch {
phase: TouchPhase::Started, phase: TouchPhase::Started,
@ -574,12 +612,12 @@ impl InputBackend for GlutinInputBackend {
id, id,
}) => { }) => {
handler.on_touch_down(&self.seat, handler.on_touch_down(&self.seat,
GlutinTouchStartedEvent { GlutinTouchStartedEvent {
window: self.window.clone(), window: self.window.clone(),
time: self.time_counter, time: self.time_counter,
location: (x, y), location: (x, y),
id: id, id: id,
}) })
} }
Event::Touch(Touch { Event::Touch(Touch {
phase: TouchPhase::Moved, phase: TouchPhase::Moved,
@ -587,12 +625,12 @@ impl InputBackend for GlutinInputBackend {
id, id,
}) => { }) => {
handler.on_touch_motion(&self.seat, handler.on_touch_motion(&self.seat,
GlutinTouchMovedEvent { GlutinTouchMovedEvent {
window: self.window.clone(), window: self.window.clone(),
time: self.time_counter, time: self.time_counter,
location: (x, y), location: (x, y),
id: id, id: id,
}) })
} }
Event::Touch(Touch { Event::Touch(Touch {
phase: TouchPhase::Ended, phase: TouchPhase::Ended,
@ -600,17 +638,17 @@ impl InputBackend for GlutinInputBackend {
id, id,
}) => { }) => {
handler.on_touch_motion(&self.seat, handler.on_touch_motion(&self.seat,
GlutinTouchMovedEvent { GlutinTouchMovedEvent {
window: self.window.clone(), window: self.window.clone(),
time: self.time_counter, time: self.time_counter,
location: (x, y), location: (x, y),
id: id, id: id,
}); });
handler.on_touch_up(&self.seat, handler.on_touch_up(&self.seat,
GlutinTouchEndedEvent { GlutinTouchEndedEvent {
time: self.time_counter, time: self.time_counter,
id: id, id: id,
}); });
} }
Event::Touch(Touch { Event::Touch(Touch {
phase: TouchPhase::Cancelled, phase: TouchPhase::Cancelled,
@ -618,10 +656,10 @@ impl InputBackend for GlutinInputBackend {
.. ..
}) => { }) => {
handler.on_touch_cancel(&self.seat, handler.on_touch_cancel(&self.seat,
GlutinTouchCancelledEvent { GlutinTouchCancelledEvent {
time: self.time_counter, time: self.time_counter,
id: id, id: id,
}) })
} }
Event::Closed => return Err(GlutinInputError::WindowClosed), Event::Closed => return Err(GlutinInputError::WindowClosed),
_ => {} _ => {}

View File

@ -1,8 +1,8 @@
//! Common traits and types for opengl rendering on graphics backends //! Common traits and types for opengl rendering on graphics backends
use nix::c_void;
use super::GraphicsBackend; use super::GraphicsBackend;
use nix::c_void;
/// Error that can happen when swapping buffers. /// Error that can happen when swapping buffers.
#[derive(Debug, Clone)] #[derive(Debug, Clone)]

View File

@ -1,9 +1,9 @@
//! Common traits and types used for software rendering on graphics backends //! Common traits and types used for software rendering on graphics backends
use std::error::Error;
use wayland_server::protocol::wl_shm::Format;
use super::GraphicsBackend; use super::GraphicsBackend;
use std::error::Error;
use wayland_server::protocol::wl_shm::Format;
/// Trait that describes objects providing a software rendering implementation /// Trait that describes objects providing a software rendering implementation
pub trait CpuGraphicsBackend<E: Error>: GraphicsBackend { pub trait CpuGraphicsBackend<E: Error>: GraphicsBackend {

View File

@ -48,7 +48,9 @@ impl ::std::cmp::PartialEq for Seat {
} }
impl ::std::hash::Hash for Seat { impl ::std::hash::Hash for Seat {
fn hash<H>(&self, state: &mut H) where H: ::std::hash::Hasher { fn hash<H>(&self, state: &mut H)
where H: ::std::hash::Hasher
{
self.id.hash(state); self.id.hash(state);
} }
} }

View File

@ -4,10 +4,10 @@ use backend::{SeatInternal, TouchSlotInternal};
use backend::input as backend; use backend::input as backend;
use input as libinput; use input as libinput;
use input::event; use input::event;
use std::io::Error as IoError;
use std::collections::hash_map::{DefaultHasher, Entry, HashMap}; use std::collections::hash_map::{DefaultHasher, Entry, HashMap};
use std::hash::{Hash, Hasher}; use std::hash::{Hash, Hasher};
use std::io::Error as IoError;
use std::rc::Rc; use std::rc::Rc;
/// Libinput based `InputBackend`. /// Libinput based `InputBackend`.
@ -48,12 +48,12 @@ impl backend::Event for event::keyboard::KeyboardKeyEvent {
impl backend::KeyboardKeyEvent for event::keyboard::KeyboardKeyEvent { impl backend::KeyboardKeyEvent for event::keyboard::KeyboardKeyEvent {
fn key_code(&self) -> u32 { fn key_code(&self) -> u32 {
use ::input::event::keyboard::KeyboardEventTrait; use input::event::keyboard::KeyboardEventTrait;
self.key() self.key()
} }
fn state(&self) -> backend::KeyState { fn state(&self) -> backend::KeyState {
use ::input::event::keyboard::KeyboardEventTrait; use input::event::keyboard::KeyboardEventTrait;
self.key_state().into() self.key_state().into()
} }
@ -70,7 +70,7 @@ pub struct PointerAxisEvent {
impl<'a> backend::Event for PointerAxisEvent { impl<'a> backend::Event for PointerAxisEvent {
fn time(&self) -> u32 { fn time(&self) -> u32 {
use ::input::event::pointer::PointerEventTrait; use input::event::pointer::PointerEventTrait;
self.event.time() self.event.time()
} }
} }
@ -86,10 +86,10 @@ impl<'a> backend::PointerAxisEvent for PointerAxisEvent {
fn amount(&self) -> f64 { fn amount(&self) -> f64 {
match self.source() { match self.source() {
backend::AxisSource::Finger | backend::AxisSource::Continuous => backend::AxisSource::Finger |
self.event.axis_value(self.axis), backend::AxisSource::Continuous => self.event.axis_value(self.axis),
backend::AxisSource::Wheel | backend::AxisSource::WheelTilt => backend::AxisSource::Wheel |
self.event.axis_value_discrete(self.axis).unwrap(), backend::AxisSource::WheelTilt => self.event.axis_value_discrete(self.axis).unwrap(),
} }
} }
} }
@ -324,18 +324,19 @@ impl backend::InputBackend for LibinputInputBackend {
trace!(self.logger, "Calling on_seat_changed with {:?}", old_seat); trace!(self.logger, "Calling on_seat_changed with {:?}", old_seat);
handler.on_seat_changed(&old_seat); handler.on_seat_changed(&old_seat);
} }
}, }
Entry::Vacant(seat_entry) => { Entry::Vacant(seat_entry) => {
let mut hasher = DefaultHasher::default(); let mut hasher = DefaultHasher::default();
seat_entry.key().hash(&mut hasher); seat_entry.key().hash(&mut hasher);
let seat = seat_entry.insert(backend::Seat::new(hasher.finish(), new_caps)); let seat = seat_entry.insert(backend::Seat::new(hasher.finish(),
new_caps));
if let Some(ref mut handler) = self.handler { if let Some(ref mut handler) = self.handler {
trace!(self.logger, "Calling on_seat_created with {:?}", seat); trace!(self.logger, "Calling on_seat_created with {:?}", seat);
handler.on_seat_created(&seat); handler.on_seat_created(&seat);
} }
} }
} }
}, }
DeviceEvent::Removed(device_removed_event) => { DeviceEvent::Removed(device_removed_event) => {
let removed = device_removed_event.device(); let removed = device_removed_event.device();
@ -347,9 +348,21 @@ impl backend::InputBackend for LibinputInputBackend {
// update capabilities, so they appear correctly on `on_seat_changed` and `on_seat_destroyed`. // update capabilities, so they appear correctly on `on_seat_changed` and `on_seat_destroyed`.
if let Some(seat) = self.seats.get_mut(&device_seat) { if let Some(seat) = self.seats.get_mut(&device_seat) {
let caps = seat.capabilities_mut(); let caps = seat.capabilities_mut();
caps.pointer = self.devices.iter().filter(|x| x.seat() == device_seat).any(|x| x.has_capability(libinput::DeviceCapability::Pointer)); caps.pointer =
caps.keyboard = self.devices.iter().filter(|x| x.seat() == device_seat).any(|x| x.has_capability(libinput::DeviceCapability::Keyboard)); self.devices
caps.touch = self.devices.iter().filter(|x| x.seat() == device_seat).any(|x| x.has_capability(libinput::DeviceCapability::Touch)); .iter()
.filter(|x| x.seat() == device_seat)
.any(|x| x.has_capability(libinput::DeviceCapability::Pointer));
caps.keyboard =
self.devices
.iter()
.filter(|x| x.seat() == device_seat)
.any(|x| x.has_capability(libinput::DeviceCapability::Keyboard));
caps.touch =
self.devices
.iter()
.filter(|x| x.seat() == device_seat)
.any(|x| x.has_capability(libinput::DeviceCapability::Touch));
} else { } else {
panic!("Seat changed that was never created") panic!("Seat changed that was never created")
} }
@ -373,95 +386,117 @@ impl backend::InputBackend for LibinputInputBackend {
handler.on_seat_changed(&seat); handler.on_seat_changed(&seat);
} }
} }
}, }
} }
if let Some(ref mut handler) = self.handler { if let Some(ref mut handler) = self.handler {
handler.on_input_config_changed(&mut self.devices); handler.on_input_config_changed(&mut self.devices);
} }
}, }
libinput::Event::Touch(touch_event) => { libinput::Event::Touch(touch_event) => {
use ::input::event::touch::*; use input::event::touch::*;
if let Some(ref mut handler) = self.handler { if let Some(ref mut handler) = self.handler {
let device_seat = touch_event.device().seat(); let device_seat = touch_event.device().seat();
let seat = &self.seats.get(&device_seat).expect("Recieved key event of non existing Seat"); let seat = &self.seats
.get(&device_seat)
.expect("Recieved key event of non existing Seat");
match touch_event { match touch_event {
TouchEvent::Down(down_event) => { TouchEvent::Down(down_event) => {
trace!(self.logger, "Calling on_touch_down with {:?}", down_event); trace!(self.logger, "Calling on_touch_down with {:?}", down_event);
handler.on_touch_down(seat, down_event) handler.on_touch_down(seat, down_event)
}, }
TouchEvent::Motion(motion_event) => { TouchEvent::Motion(motion_event) => {
trace!(self.logger, "Calling on_touch_motion with {:?}", motion_event); trace!(self.logger,
"Calling on_touch_motion with {:?}",
motion_event);
handler.on_touch_motion(seat, motion_event) handler.on_touch_motion(seat, motion_event)
}, }
TouchEvent::Up(up_event) => { TouchEvent::Up(up_event) => {
trace!(self.logger, "Calling on_touch_up with {:?}", up_event); trace!(self.logger, "Calling on_touch_up with {:?}", up_event);
handler.on_touch_up(seat, up_event) handler.on_touch_up(seat, up_event)
}, }
TouchEvent::Cancel(cancel_event) => { TouchEvent::Cancel(cancel_event) => {
trace!(self.logger, "Calling on_touch_cancel with {:?}", cancel_event); trace!(self.logger,
"Calling on_touch_cancel with {:?}",
cancel_event);
handler.on_touch_cancel(seat, cancel_event) handler.on_touch_cancel(seat, cancel_event)
}, }
TouchEvent::Frame(frame_event) => { TouchEvent::Frame(frame_event) => {
trace!(self.logger, "Calling on_touch_frame with {:?}", frame_event); trace!(self.logger, "Calling on_touch_frame with {:?}", frame_event);
handler.on_touch_frame(seat, frame_event) handler.on_touch_frame(seat, frame_event)
}, }
} }
} }
}, }
libinput::Event::Keyboard(keyboard_event) => { libinput::Event::Keyboard(keyboard_event) => {
use ::input::event::keyboard::*; use input::event::keyboard::*;
match keyboard_event { match keyboard_event {
KeyboardEvent::Key(key_event) => { KeyboardEvent::Key(key_event) => {
if let Some(ref mut handler) = self.handler { if let Some(ref mut handler) = self.handler {
let device_seat = key_event.device().seat(); let device_seat = key_event.device().seat();
let seat = &self.seats.get(&device_seat).expect("Recieved key event of non existing Seat"); let seat = &self.seats
.get(&device_seat)
.expect("Recieved key event of non existing Seat");
trace!(self.logger, "Calling on_keyboard_key with {:?}", key_event); trace!(self.logger, "Calling on_keyboard_key with {:?}", key_event);
handler.on_keyboard_key(seat, key_event); handler.on_keyboard_key(seat, key_event);
} }
} }
} }
}, }
libinput::Event::Pointer(pointer_event) => { libinput::Event::Pointer(pointer_event) => {
use ::input::event::pointer::*; use input::event::pointer::*;
if let Some(ref mut handler) = self.handler { if let Some(ref mut handler) = self.handler {
let device_seat = pointer_event.device().seat(); let device_seat = pointer_event.device().seat();
let seat = &self.seats.get(&device_seat).expect("Recieved key event of non existing Seat"); let seat = &self.seats
.get(&device_seat)
.expect("Recieved key event of non existing Seat");
match pointer_event { match pointer_event {
PointerEvent::Motion(motion_event) => { PointerEvent::Motion(motion_event) => {
trace!(self.logger, "Calling on_pointer_move with {:?}", motion_event); trace!(self.logger,
"Calling on_pointer_move with {:?}",
motion_event);
handler.on_pointer_move(seat, motion_event); handler.on_pointer_move(seat, motion_event);
}, }
PointerEvent::MotionAbsolute(motion_abs_event) => { PointerEvent::MotionAbsolute(motion_abs_event) => {
trace!(self.logger, "Calling on_pointer_move_absolute with {:?}", motion_abs_event); trace!(self.logger,
"Calling on_pointer_move_absolute with {:?}",
motion_abs_event);
handler.on_pointer_move_absolute(seat, motion_abs_event); handler.on_pointer_move_absolute(seat, motion_abs_event);
}, }
PointerEvent::Axis(axis_event) => { PointerEvent::Axis(axis_event) => {
let rc_axis_event = Rc::new(axis_event); let rc_axis_event = Rc::new(axis_event);
if rc_axis_event.has_axis(Axis::Vertical) { if rc_axis_event.has_axis(Axis::Vertical) {
trace!(self.logger, "Calling on_pointer_axis for Axis::Vertical with {:?}", *rc_axis_event); trace!(self.logger,
handler.on_pointer_axis(seat, self::PointerAxisEvent { "Calling on_pointer_axis for Axis::Vertical with {:?}",
axis: Axis::Vertical, *rc_axis_event);
event: rc_axis_event.clone() handler.on_pointer_axis(seat,
}); self::PointerAxisEvent {
axis: Axis::Vertical,
event: rc_axis_event.clone(),
});
} }
if rc_axis_event.has_axis(Axis::Horizontal) { if rc_axis_event.has_axis(Axis::Horizontal) {
trace!(self.logger, "Calling on_pointer_axis for Axis::Horizontal with {:?}", *rc_axis_event); trace!(self.logger,
handler.on_pointer_axis(seat, self::PointerAxisEvent { "Calling on_pointer_axis for Axis::Horizontal with {:?}",
axis: Axis::Horizontal, *rc_axis_event);
event: rc_axis_event.clone() handler.on_pointer_axis(seat,
}); self::PointerAxisEvent {
axis: Axis::Horizontal,
event: rc_axis_event.clone(),
});
} }
}, }
PointerEvent::Button(button_event) => { PointerEvent::Button(button_event) => {
trace!(self.logger, "Calling on_pointer_button with {:?}", button_event); trace!(self.logger,
"Calling on_pointer_button with {:?}",
button_event);
handler.on_pointer_button(seat, button_event); handler.on_pointer_button(seat, button_event);
} }
} }
} }
}, }
_ => {}, //FIXME: What to do with the rest. _ => {} //FIXME: What to do with the rest.
} }
}; }
Ok(()) Ok(())
} }
} }