pub struct Point {
pub x: f64,
pub y: f64,
}
Expand description
A 2D point.
This type represents a point in 2D space. It has the same layout as Vec2
, but
its meaning is different: Vec2
represents a change in location (for example velocity).
In general, kurbo
overloads math operators where it makes sense, for example implementing
Affine * Point
as the point under the affine transformation. However Point + Point
and
f64 * Point
are not implemented, because the operations do not make geometric sense. If you
need to apply these operations, then 1) check what you’re doing makes geometric sense, then 2)
use Point::to_vec2
to convert the point to a Vec2
.
Fields§
§x: f64
The x coordinate.
y: f64
The y coordinate.
Implementations§
Source§impl Point
impl Point
Sourcepub const fn new(x: f64, y: f64) -> Point
pub const fn new(x: f64, y: f64) -> Point
Create a new Point
with the provided x
and y
coordinates.
Examples found in repository?
More examples
120 fn layout(
121 &mut self,
122 ctx: &mut druid::LayoutCtx,
123 bc: &druid::BoxConstraints,
124 data: &AppState,
125 env: &druid::Env,
126 ) -> druid::Size {
127 let mut interactable_area = Region::EMPTY;
128 let smaller_bc = BoxConstraints::new(
129 Size::new(0.0, 0.0),
130 Size::new(bc.max().width - 100.0, bc.max().height - 100.0),
131 );
132 let full_bc = BoxConstraints::new(Size::new(0.0, 0.0), bc.max());
133 let _label_size = self.info_label.layout(ctx, &smaller_bc, data, env);
134 let controls_size = self.controls.layout(ctx, &full_bc, data, env);
135
136 let text_origin_point = Point::new(50.0, 50.0 + controls_size.height);
137 self.info_label.set_origin(ctx, text_origin_point);
138 let controls_origin_point = Point::new(EXAMPLE_BORDER_SIZE, EXAMPLE_BORDER_SIZE);
139 self.controls.set_origin(ctx, controls_origin_point);
140
141 // Add side rects to clarify the dimensions of the window.
142 let left_rect = Rect::new(0.0, 0.0, EXAMPLE_BORDER_SIZE, bc.max().height);
143 let right_rect = Rect::new(
144 bc.max().width - EXAMPLE_BORDER_SIZE,
145 0.0,
146 bc.max().width,
147 bc.max().height,
148 );
149 let bottom_rect = Rect::new(
150 0.0,
151 bc.max().height - EXAMPLE_BORDER_SIZE,
152 bc.max().width,
153 bc.max().height,
154 );
155 interactable_area.add_rect(left_rect);
156 interactable_area.add_rect(right_rect);
157 interactable_area.add_rect(bottom_rect);
158 interactable_area.add_rect(self.info_label.layout_rect());
159 interactable_area.add_rect(self.controls.layout_rect());
160
161 if data.limit_input_region {
162 ctx.window().set_input_region(Some(interactable_area));
163 } else {
164 ctx.window().set_input_region(None);
165 }
166
167 bc.max()
168 }
Sourcepub const fn to_vec2(self) -> Vec2
pub const fn to_vec2(self) -> Vec2
Convert this point into a Vec2
.
Examples found in repository?
99 fn event(&mut self, child: &mut W, ctx: &mut EventCtx, event: &Event, data: &mut T, env: &Env) {
100 let wait_duration = Duration::from_millis(500);
101 let resched_dur = Duration::from_millis(50);
102 let cursor_size = Size::new(15., 15.);
103 let now = Instant::now();
104 let new_state = match &self.state {
105 TooltipState::Fresh => match event {
106 Event::MouseMove(me) if ctx.is_hot() => Some(TooltipState::Waiting {
107 last_move: now,
108 timer_expire: now + wait_duration,
109 token: ctx.request_timer(wait_duration),
110 position_in_window_coordinates: me.window_pos,
111 }),
112 _ => None,
113 },
114 TooltipState::Waiting {
115 last_move,
116 timer_expire,
117 token,
118 position_in_window_coordinates,
119 } => match event {
120 Event::MouseMove(me) if ctx.is_hot() => {
121 let (cur_token, cur_expire) = if *timer_expire - now < resched_dur {
122 (ctx.request_timer(wait_duration), now + wait_duration)
123 } else {
124 (*token, *timer_expire)
125 };
126 Some(TooltipState::Waiting {
127 last_move: now,
128 timer_expire: cur_expire,
129 token: cur_token,
130 position_in_window_coordinates: me.window_pos,
131 })
132 }
133 Event::Timer(tok) if tok == token => {
134 let deadline = *last_move + wait_duration;
135 ctx.set_handled();
136 if deadline > now {
137 let wait_for = deadline - now;
138 tracing::info!("Waiting another {:?}", wait_for);
139 Some(TooltipState::Waiting {
140 last_move: *last_move,
141 timer_expire: deadline,
142 token: ctx.request_timer(wait_for),
143 position_in_window_coordinates: *position_in_window_coordinates,
144 })
145 } else {
146 let tooltip_position_in_window_coordinates =
147 (position_in_window_coordinates.to_vec2() + cursor_size.to_vec2())
148 .to_point();
149 let win_id = ctx.new_sub_window(
150 WindowConfig::default()
151 .show_titlebar(false)
152 .window_size_policy(WindowSizePolicy::Content)
153 .set_level(WindowLevel::Tooltip(ctx.window().clone()))
154 .set_position(tooltip_position_in_window_coordinates),
155 Label::<()>::new(self.tip.clone()),
156 (),
157 env.clone(),
158 );
159 Some(TooltipState::Showing(win_id))
160 }
161 }
162 _ => None,
163 },
164 TooltipState::Showing(win_id) => {
165 match event {
166 Event::MouseMove(me) if !ctx.is_hot() => {
167 // TODO another timer on leaving
168 tracing::info!("Sending close window for {:?}", win_id);
169 ctx.submit_command(CLOSE_WINDOW.to(*win_id));
170 Some(TooltipState::Waiting {
171 last_move: now,
172 timer_expire: now + wait_duration,
173 token: ctx.request_timer(wait_duration),
174 position_in_window_coordinates: me.window_pos,
175 })
176 }
177 _ => None,
178 }
179 }
180 };
181
182 if let Some(state) = new_state {
183 self.state = state;
184 }
185
186 if !ctx.is_handled() {
187 child.event(ctx, event, data, env);
188 }
189 }
190
191 fn lifecycle(
192 &mut self,
193 child: &mut W,
194 ctx: &mut LifeCycleCtx,
195 event: &LifeCycle,
196 data: &T,
197 env: &Env,
198 ) {
199 if let LifeCycle::HotChanged(false) = event {
200 if let TooltipState::Showing(win_id) = self.state {
201 ctx.submit_command(CLOSE_WINDOW.to(win_id));
202 }
203 self.state = TooltipState::Fresh;
204 }
205 child.lifecycle(ctx, event, data, env)
206 }
207}
208
209struct DragWindowController {
210 init_pos: Option<Point>,
211 //dragging: bool
212}
213
214impl DragWindowController {
215 pub fn new() -> Self {
216 DragWindowController { init_pos: None }
217 }
218}
219
220impl<T, W: Widget<T>> Controller<T, W> for DragWindowController {
221 fn event(&mut self, child: &mut W, ctx: &mut EventCtx, event: &Event, data: &mut T, env: &Env) {
222 match event {
223 Event::MouseDown(me) if me.buttons.has_left() => {
224 ctx.set_active(true);
225 self.init_pos = Some(me.window_pos)
226 }
227 Event::MouseMove(me) if ctx.is_active() && me.buttons.has_left() => {
228 if let Some(init_pos) = self.init_pos {
229 let within_window_change = me.window_pos.to_vec2() - init_pos.to_vec2();
230 let old_pos = ctx.window().get_position();
231 let new_pos = old_pos + within_window_change;
232 tracing::info!(
233 "Drag {:?} ",
234 (
235 init_pos,
236 me.window_pos,
237 within_window_change,
238 old_pos,
239 new_pos
240 )
241 );
242 ctx.window().set_position(new_pos)
243 }
244 }
245 Event::MouseUp(_me) if ctx.is_active() => {
246 self.init_pos = None;
247 ctx.set_active(false)
248 }
249 _ => (),
250 }
251 child.event(ctx, event, data, env)
252 }
253}
254
255struct ScreenThing;
256
257impl Widget<()> for ScreenThing {
258 fn event(&mut self, _ctx: &mut EventCtx, _event: &Event, _data: &mut (), _env: &Env) {}
259
260 fn lifecycle(&mut self, _ctx: &mut LifeCycleCtx, _event: &LifeCycle, _data: &(), _env: &Env) {}
261
262 fn update(&mut self, _ctx: &mut UpdateCtx, _old_data: &(), _data: &(), _env: &Env) {}
263
264 fn layout(
265 &mut self,
266 _ctx: &mut LayoutCtx,
267 bc: &BoxConstraints,
268 _data: &(),
269 _env: &Env,
270 ) -> Size {
271 bc.constrain(Size::new(800.0, 600.0))
272 }
273
274 fn paint(&mut self, ctx: &mut PaintCtx, _data: &(), env: &Env) {
275 let sz = ctx.size();
276
277 let monitors = Screen::get_monitors();
278 let all = monitors
279 .iter()
280 .map(|x| x.virtual_rect())
281 .fold(Rect::ZERO, |s, r| r.union(s));
282 if all.width() > 0. && all.height() > 0. {
283 let trans = Affine::scale(f64::min(sz.width / all.width(), sz.height / all.height()))
284 * Affine::translate(all.origin().to_vec2()).inverse();
285 let font = env.get(theme::UI_FONT).family;
286
287 for (i, mon) in monitors.iter().enumerate() {
288 let vr = mon.virtual_rect();
289 let tr = trans.transform_rect_bbox(vr);
290 ctx.stroke(tr, &Color::WHITE, 1.0);
291
292 if let Ok(tl) = ctx
293 .text()
294 .new_text_layout(format!(
295 "{}:{}x{}@{},{}",
296 i,
297 vr.width(),
298 vr.height(),
299 vr.x0,
300 vr.y0
301 ))
302 .max_width(tr.width() - 5.)
303 .font(font.clone(), env.get(theme::TEXT_SIZE_NORMAL))
304 .text_color(Color::WHITE)
305 .build()
306 {
307 ctx.draw_text(&tl, tr.center() - tl.size().to_vec2() * 0.5);
308 }
309 }
310 }
311 }
Sourcepub fn distance_squared(self, other: Point) -> f64
pub fn distance_squared(self, other: Point) -> f64
Squared Euclidean distance.
Sourcepub fn round(self) -> Point
pub fn round(self) -> Point
Returns a new Point
,
with x
and y
rounded to the nearest integer.
§Examples
use kurbo::Point;
let a = Point::new(3.3, 3.6).round();
let b = Point::new(3.0, -3.1).round();
assert_eq!(a.x, 3.0);
assert_eq!(a.y, 4.0);
assert_eq!(b.x, 3.0);
assert_eq!(b.y, -3.0);
Sourcepub fn ceil(self) -> Point
pub fn ceil(self) -> Point
Returns a new Point
,
with x
and y
rounded up to the nearest integer,
unless they are already an integer.
§Examples
use kurbo::Point;
let a = Point::new(3.3, 3.6).ceil();
let b = Point::new(3.0, -3.1).ceil();
assert_eq!(a.x, 4.0);
assert_eq!(a.y, 4.0);
assert_eq!(b.x, 3.0);
assert_eq!(b.y, -3.0);
Sourcepub fn floor(self) -> Point
pub fn floor(self) -> Point
Returns a new Point
,
with x
and y
rounded down to the nearest integer,
unless they are already an integer.
§Examples
use kurbo::Point;
let a = Point::new(3.3, 3.6).floor();
let b = Point::new(3.0, -3.1).floor();
assert_eq!(a.x, 3.0);
assert_eq!(a.y, 3.0);
assert_eq!(b.x, 3.0);
assert_eq!(b.y, -4.0);
Sourcepub fn expand(self) -> Point
pub fn expand(self) -> Point
Returns a new Point
,
with x
and y
rounded away from zero to the nearest integer,
unless they are already an integer.
§Examples
use kurbo::Point;
let a = Point::new(3.3, 3.6).expand();
let b = Point::new(3.0, -3.1).expand();
assert_eq!(a.x, 4.0);
assert_eq!(a.y, 4.0);
assert_eq!(b.x, 3.0);
assert_eq!(b.y, -4.0);
Sourcepub fn trunc(self) -> Point
pub fn trunc(self) -> Point
Returns a new Point
,
with x
and y
rounded towards zero to the nearest integer,
unless they are already an integer.
§Examples
use kurbo::Point;
let a = Point::new(3.3, 3.6).trunc();
let b = Point::new(3.0, -3.1).trunc();
assert_eq!(a.x, 3.0);
assert_eq!(a.y, 3.0);
assert_eq!(b.x, 3.0);
assert_eq!(b.y, -3.0);
Trait Implementations§
Source§impl AddAssign<Vec2> for Point
impl AddAssign<Vec2> for Point
Source§fn add_assign(&mut self, other: Vec2)
fn add_assign(&mut self, other: Vec2)
+=
operation. Read moreSource§impl Mul<Point> for TranslateScale
impl Mul<Point> for TranslateScale
Source§impl Scalable for Point
impl Scalable for Point
Source§impl SubAssign<Vec2> for Point
impl SubAssign<Vec2> for Point
Source§fn sub_assign(&mut self, other: Vec2)
fn sub_assign(&mut self, other: Vec2)
-=
operation. Read moreSource§impl ValueType for Point
impl ValueType for Point
Source§fn try_from_value(value: &Value) -> Result<Self, ValueTypeError>
fn try_from_value(value: &Value) -> Result<Self, ValueTypeError>
Value
into this type.