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
// Copyright 2018 The xi-editor Authors.
//
// 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 at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//! Widget trait and common widgets.
use std::any::Any;
pub use druid_win_shell::window::MouseButton;
use {BoxConstraints, Geometry, LayoutResult};
use {HandlerCtx, Id, LayoutCtx, PaintCtx};
mod button;
pub use widget::button::{Button, Label};
mod event_forwarder;
pub use widget::event_forwarder::EventForwarder;
mod flex;
pub use widget::flex::{Column, Flex, Row};
mod key_listener;
pub use widget::key_listener::KeyListener;
mod null;
pub(crate) use widget::null::NullWidget;
mod padding;
pub use widget::padding::Padding;
/// The trait implemented by all widgets.
pub trait Widget {
/// Paint the widget's appearance into the paint context.
///
/// The implementer is responsible for translating the coordinates as
/// specified in the geometry.
#[allow(unused)]
fn paint(&mut self, paint_ctx: &mut PaintCtx, geom: &Geometry) {}
/// Participate in the layout protocol.
///
/// `size` is the size of the child previously requested by a RequestChild return.
///
/// The default implementation is suitable for widgets with a single child, and
/// just forwards the layout unmodified.
fn layout(&mut self, bc: &BoxConstraints, children: &[Id], size: Option<(f32, f32)>,
ctx: &mut LayoutCtx) -> LayoutResult
{
if let Some(size) = size {
// Maybe this is not necessary, rely on default value.
ctx.position_child(children[0], (0.0, 0.0));
LayoutResult::Size(size)
} else {
LayoutResult::RequestChild(children[0], *bc)
}
}
/// Sent to the widget on mouse event.
///
/// Mouse events are propagated in a post-order traversal of the widget tree,
/// culled by geometry. Propagation stops as soon as the event is handled.
#[allow(unused)]
fn mouse(&mut self, event: &MouseEvent, ctx: &mut HandlerCtx) -> bool { false }
/// Sent to the active or hot widget on mouse move events.
// TODO: should mods be plumbed here?
#[allow(unused)]
fn mouse_moved(&mut self, x: f32, y: f32, ctx: &mut HandlerCtx) {}
/// Sent to the widget when its "hot" status changes.
#[allow(unused)]
fn on_hot_changed(&mut self, hot: bool, ctx: &mut HandlerCtx) {}
/// An "escape hatch" of sorts for accessing widget state beyond the widget
/// methods. Returns true if it is handled.
#[allow(unused)]
fn poke(&mut self, payload: &mut Any, ctx: &mut HandlerCtx) -> bool { false }
/// Sent to the widget on key event.
///
/// Key events are only sent to the focused widget.
///
/// Note that keys that are interpreted as characters are sent twice, first
/// as a `Vkey`, then as a `Char`.
///
/// This is a fairly thin wrapper over WM messages. Keyboard input will be
/// changing quite a bit when IME is implemented.
///
/// Returns true if the event is handled.
#[allow(unused)]
fn key(&mut self, event: &KeyEvent, ctx: &mut HandlerCtx) -> bool { false }
/// Called at the beginning of a new animation frame.
///
/// The `interval` argument is the time in nanoseconds between frames, for
/// the purpose of computing animations. When framerate is steady, it should
/// be exactly the reciprocal of the refresh rate of the monitor. If we are
/// skipping frames, its cumulative sum should approximately track the
/// passage of wall clock time and otherwise should be chosen to optimize
/// for smoothness of animations.
///
/// The ideal heuristic for computing this interval is a deep topic, ideally
/// the subject of a blog post when I figure it out.
///
/// On the first frame when transitioning from idle to animating, `interval`
/// will be 0. (This logic is presently per-window but might change to
/// per-widget to make it more consistent).
///
/// This method should call `invalidate` on the context if the visual display
/// updates. In the current implementation, that's not very useful, but it
/// will become much more so when there's fine grained invalidation.
///
/// The method can also call `request_anim_frame` to keep the animation running.
#[allow(unused)]
fn anim_frame(&mut self, interval: u64, ctx: &mut HandlerCtx) {}
/// Called when a child widget is removed.
#[allow(unused)]
fn on_child_removed(&mut self, child: Id) {}
}
pub struct MouseEvent {
/// X coordinate in px units, relative to top left of widget.
pub x: f32,
/// Y coordinate in px units, relative to top left of widget.
pub y: f32,
/// The modifiers, which have the same interpretation as the raw WM message.
///
/// TODO: rationalize this with mouse mods.
pub mods: u32,
/// Which mouse button was pressed.
pub which: MouseButton,
/// Count of multiple clicks, is 0 for mouse up event.
pub count: u32,
}
#[derive(Clone)]
pub struct KeyEvent {
pub key: KeyVariant,
/// The modifiers, a combinations of `M_ALT`, `M_CTRL`, `M_SHIFT`.
pub mods: u32,
}
#[derive(Clone)]
pub enum KeyVariant {
/// A virtual-key code, same as WM_KEYDOWN message.
Vkey(i32),
/// A Unicode character.
Char(char),
}