mirror of https://github.com/wayvr-org/wayvr.git
editbox keyboard input, scrollbars fix (scissoring broken atm), clippy
This commit is contained in:
parent
841241a7e6
commit
2ddb419676
|
|
@ -93,19 +93,18 @@
|
|||
position="absolute" width="100%" height="100%"
|
||||
gradient="radial" color="#44BBFF11" color2="#00000000" />
|
||||
|
||||
<div
|
||||
id="content"
|
||||
flex_direction="column"
|
||||
overflow_x="scroll"
|
||||
overflow_y="scroll"
|
||||
padding="16"
|
||||
gap="8"
|
||||
width="100%"
|
||||
min_height="100%"
|
||||
>
|
||||
<!-- filled-in at runtime -->
|
||||
<div overflow_x="scroll" overflow_y="scroll" width="100%" height="100%">
|
||||
<div
|
||||
id="content"
|
||||
flex_direction="column"
|
||||
padding="16"
|
||||
gap="8"
|
||||
width="100%"
|
||||
height="100%"
|
||||
>
|
||||
<!-- filled-in at runtime -->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div position="absolute" id="popup_manager" width="100%" height="100%" />
|
||||
</rectangle>
|
||||
<!-- BOTTOM PANEL -->
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<layout>
|
||||
<elements>
|
||||
<div id="running_games_list_parent" align_self="center" />
|
||||
<div id="game_list_parent" align_items="center" flex_direction="column" gap="8" overflow_y="scroll" />
|
||||
<div id="game_list_parent" align_items="center" flex_direction="column" gap="8" />
|
||||
</elements>
|
||||
</layout>
|
||||
|
|
@ -50,7 +50,6 @@ enum CompositorMode {
|
|||
enum Task {
|
||||
SetCompositor(CompositorMode),
|
||||
SetRes(ResMode),
|
||||
SetPos(PosMode), // TODO?
|
||||
SetOrientation(OrientationMode),
|
||||
SetAutoStart(bool),
|
||||
Launch,
|
||||
|
|
@ -295,7 +294,6 @@ impl View {
|
|||
match task {
|
||||
Task::SetCompositor(mode) => self.compositor_mode = mode,
|
||||
Task::SetRes(mode) => self.res_mode = mode,
|
||||
Task::SetPos(mode) => self.pos_mode = mode,
|
||||
Task::SetOrientation(mode) => self.orientation_mode = mode,
|
||||
Task::SetAutoStart(auto_start) => self.auto_start = auto_start,
|
||||
Task::Launch => self.action_launch(interface, data),
|
||||
|
|
|
|||
|
|
@ -66,8 +66,9 @@
|
|||
</rectangle>
|
||||
<rectangle macro="rect">
|
||||
<label text="Editbox test" />
|
||||
<EditBox text="Initial text. Test, abcdef." />
|
||||
<EditBox />
|
||||
<EditBox text="Initial text. Test, abcdef." width="400" />
|
||||
|
||||
<EditBox margin_left="42" margin_top="42" margin_bottom="40" width="200" />
|
||||
</rectangle>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,25 +1,25 @@
|
|||
use glam::{vec2, Vec2};
|
||||
use std::sync::Arc;
|
||||
use testbed::{testbed_any::TestbedAny, Testbed};
|
||||
use glam::{Vec2, vec2};
|
||||
use std::{rc::Rc, sync::Arc};
|
||||
use testbed::{Testbed, testbed_any::TestbedAny};
|
||||
use tracing_subscriber::EnvFilter;
|
||||
use tracing_subscriber::filter::LevelFilter;
|
||||
use tracing_subscriber::layer::SubscriberExt;
|
||||
use tracing_subscriber::util::SubscriberInitExt;
|
||||
use tracing_subscriber::EnvFilter;
|
||||
use vulkan::init_window;
|
||||
use vulkano::{
|
||||
Validated, VulkanError,
|
||||
command_buffer::CommandBufferUsage,
|
||||
format::Format,
|
||||
image::{view::ImageView, ImageUsage},
|
||||
image::{ImageUsage, view::ImageView},
|
||||
swapchain::{
|
||||
acquire_next_image, ColorSpace, CompositeAlpha, PresentMode, Surface, SurfaceInfo, Swapchain,
|
||||
SwapchainCreateInfo, SwapchainPresentInfo,
|
||||
ColorSpace, CompositeAlpha, PresentMode, Surface, SurfaceInfo, Swapchain, SwapchainCreateInfo,
|
||||
SwapchainPresentInfo, acquire_next_image,
|
||||
},
|
||||
sync::GpuFuture,
|
||||
Validated, VulkanError,
|
||||
};
|
||||
use wgui::{
|
||||
event::{MouseButtonIndex, MouseDownEvent, MouseMotionEvent, MouseUpEvent, MouseWheelEvent},
|
||||
gfx::{cmd::WGfxClearMode, WGfx},
|
||||
event::{MouseButtonEvent, MouseButtonIndex, MouseMotionEvent, MouseWheelEvent},
|
||||
gfx::{WGfx, cmd::WGfxClearMode},
|
||||
renderer_vk::{self},
|
||||
};
|
||||
use winit::{
|
||||
|
|
@ -32,7 +32,7 @@ use wlx_common::{audio, timestep::Timestep};
|
|||
use crate::{
|
||||
rate_limiter::RateLimiter,
|
||||
testbed::{
|
||||
testbed_dashboard::TestbedDashboard, testbed_generic::TestbedGeneric, TestbedUpdateParams,
|
||||
TestbedUpdateParams, testbed_dashboard::TestbedDashboard, testbed_generic::TestbedGeneric,
|
||||
},
|
||||
};
|
||||
|
||||
|
|
@ -174,7 +174,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||
testbed
|
||||
.layout()
|
||||
.push_event(
|
||||
&wgui::event::Event::MouseDown(MouseDownEvent {
|
||||
&wgui::event::Event::MouseDown(MouseButtonEvent {
|
||||
pos: mouse / scale,
|
||||
index: MouseButtonIndex::Left,
|
||||
device: 0,
|
||||
|
|
@ -187,7 +187,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||
testbed
|
||||
.layout()
|
||||
.push_event(
|
||||
&wgui::event::Event::MouseUp(MouseUpEvent {
|
||||
&wgui::event::Event::MouseUp(MouseButtonEvent {
|
||||
pos: mouse / scale,
|
||||
index: MouseButtonIndex::Left,
|
||||
device: 0,
|
||||
|
|
@ -221,33 +221,46 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||
..
|
||||
} => {
|
||||
if event.state == ElementState::Pressed {
|
||||
if event.physical_key == PhysicalKey::Code(KeyCode::F10) {
|
||||
debug_draw_enabled = !debug_draw_enabled;
|
||||
if debug_draw_enabled {
|
||||
log::info!(
|
||||
"Debug draw enabled\n\tAqua: widget boundary\n\tMagenta: Scissoring (separate render pass)"
|
||||
);
|
||||
if !event.repeat {
|
||||
if event.physical_key == PhysicalKey::Code(KeyCode::F10) {
|
||||
debug_draw_enabled = !debug_draw_enabled;
|
||||
if debug_draw_enabled {
|
||||
log::info!(
|
||||
"Debug draw enabled\n\tAqua: widget boundary\n\tMagenta: Scissoring (separate render pass)"
|
||||
);
|
||||
}
|
||||
testbed.layout().mark_redraw();
|
||||
}
|
||||
|
||||
if event.physical_key == PhysicalKey::Code(KeyCode::F11) {
|
||||
testbed.layout().print_tree();
|
||||
}
|
||||
|
||||
if event.physical_key == PhysicalKey::Code(KeyCode::Equal) {
|
||||
scale *= 1.25;
|
||||
render_context
|
||||
.update_viewport(&mut shared_context, swapchain_size, scale)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
if event.physical_key == PhysicalKey::Code(KeyCode::Minus) {
|
||||
scale *= 0.75;
|
||||
render_context
|
||||
.update_viewport(&mut shared_context, swapchain_size, scale)
|
||||
.unwrap();
|
||||
}
|
||||
testbed.layout().mark_redraw();
|
||||
}
|
||||
|
||||
if event.physical_key == PhysicalKey::Code(KeyCode::F11) {
|
||||
testbed.layout().print_tree();
|
||||
}
|
||||
|
||||
if event.physical_key == PhysicalKey::Code(KeyCode::Equal) {
|
||||
scale *= 1.25;
|
||||
render_context
|
||||
.update_viewport(&mut shared_context, swapchain_size, scale)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
if event.physical_key == PhysicalKey::Code(KeyCode::Minus) {
|
||||
scale *= 0.75;
|
||||
render_context
|
||||
.update_viewport(&mut shared_context, swapchain_size, scale)
|
||||
.unwrap();
|
||||
}
|
||||
testbed
|
||||
.layout()
|
||||
.push_event(
|
||||
&wgui::event::Event::TextInput(wgui::event::TextInputEvent {
|
||||
text: event.text.map(|text| Rc::from(text.as_str())),
|
||||
}),
|
||||
&mut (),
|
||||
&mut (),
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
Event::WindowEvent {
|
||||
|
|
|
|||
|
|
@ -14,8 +14,8 @@ use wgui::{
|
|||
drawing,
|
||||
event::{
|
||||
CallbackDataCommon, Event as WguiEvent, EventAlterables, EventCallback, EventListenerID,
|
||||
EventListenerKind, InternalStateChangeEvent, MouseButtonIndex, MouseDownEvent,
|
||||
MouseLeaveEvent, MouseMotionEvent, MouseUpEvent, MouseWheelEvent,
|
||||
EventListenerKind, InternalStateChangeEvent, MouseButtonEvent, MouseButtonIndex,
|
||||
MouseLeaveEvent, MouseMotionEvent, MouseWheelEvent,
|
||||
},
|
||||
gfx::cmd::WGfxClearMode,
|
||||
i18n::Translation,
|
||||
|
|
@ -416,13 +416,13 @@ impl<S: 'static> OverlayBackend for GuiPanel<S> {
|
|||
};
|
||||
|
||||
let e = if pressed {
|
||||
WguiEvent::MouseDown(MouseDownEvent {
|
||||
WguiEvent::MouseDown(MouseButtonEvent {
|
||||
pos: hit.uv * self.layout.content_size,
|
||||
index,
|
||||
device: hit.pointer,
|
||||
})
|
||||
} else {
|
||||
WguiEvent::MouseUp(MouseUpEvent {
|
||||
WguiEvent::MouseUp(MouseButtonEvent {
|
||||
pos: hit.uv * self.layout.content_size,
|
||||
index,
|
||||
device: hit.pointer,
|
||||
|
|
|
|||
|
|
@ -8,8 +8,8 @@ use wayvr_ipc::{
|
|||
};
|
||||
use wgui::{
|
||||
event::{
|
||||
Event as WguiEvent, MouseButtonIndex, MouseDownEvent, MouseLeaveEvent, MouseMotionEvent,
|
||||
MouseUpEvent, MouseWheelEvent,
|
||||
Event as WguiEvent, MouseButtonEvent, MouseButtonIndex, MouseLeaveEvent, MouseMotionEvent,
|
||||
MouseWheelEvent,
|
||||
},
|
||||
gfx::cmd::WGfxClearMode,
|
||||
renderer_vk::context::Context as WguiContext,
|
||||
|
|
@ -247,13 +247,13 @@ impl OverlayBackend for DashFrontend {
|
|||
};
|
||||
|
||||
let e = if pressed {
|
||||
WguiEvent::MouseDown(MouseDownEvent {
|
||||
WguiEvent::MouseDown(MouseButtonEvent {
|
||||
pos: hit.uv * self.inner.layout.content_size,
|
||||
index,
|
||||
device: hit.pointer,
|
||||
})
|
||||
} else {
|
||||
WguiEvent::MouseUp(MouseUpEvent {
|
||||
WguiEvent::MouseUp(MouseButtonEvent {
|
||||
pos: hit.uv * self.inner.layout.content_size,
|
||||
index,
|
||||
device: hit.pointer,
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ use regex::Regex;
|
|||
use slotmap::{SlotMap, new_key_type};
|
||||
use wgui::{
|
||||
drawing,
|
||||
event::{InternalStateChangeEvent, MouseButton, MouseButtonIndex},
|
||||
event::{InternalStateChangeEvent, MouseButtonEvent, MouseButtonIndex},
|
||||
};
|
||||
use wlx_common::windowing::{OverlayWindowState, Positioning};
|
||||
use wlx_common::{
|
||||
|
|
@ -390,7 +390,7 @@ fn handle_press(
|
|||
app: &mut AppState,
|
||||
key: &KeyState,
|
||||
keyboard: &mut KeyboardState,
|
||||
button: MouseButton,
|
||||
button: MouseButtonEvent,
|
||||
) {
|
||||
match &key.button_state {
|
||||
KeyButtonData::Key { vk, pressed } => {
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
## [Built-in components](#components)
|
||||
|
||||
[Button](#button-component), [Slider](#slider-component), [CheckBox](#checkbox-component), [Tabs](#tabs-component) ([Tab](#tab-component))
|
||||
[Button](#button-component), [Slider](#slider-component), [CheckBox](#checkbox-component), [Tabs](#tabs-component) ([Tab](#tab-component)), [EditBox](#editbox-component)
|
||||
|
||||
## [Examples](#examples)
|
||||
|
||||
|
|
@ -408,6 +408,20 @@ _Image path (see [sprite](#sprite-widget)) for src descriptions_
|
|||
|
||||
---
|
||||
|
||||
## EditBox component
|
||||
|
||||
### `<EditBox>`
|
||||
|
||||
### A single-line text input field.
|
||||
|
||||
#### Parameters
|
||||
|
||||
`text`: **string**
|
||||
|
||||
_Initial text content_
|
||||
|
||||
---
|
||||
|
||||
# Examples
|
||||
|
||||
## Simple layout
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ use crate::{
|
|||
animation::{Animation, AnimationEasing},
|
||||
components::{Component, ComponentBase, ComponentTrait, FocusChangeData, RefreshData},
|
||||
drawing::{self, Color},
|
||||
event::{self, CallbackDataCommon, EventListenerCollection, EventListenerKind, StyleSetRequest},
|
||||
event::{self, CallbackDataCommon, CallbackMetadata, EventListenerCollection, EventListenerKind, StyleSetRequest},
|
||||
i18n::Translation,
|
||||
layout::{WidgetID, WidgetPair},
|
||||
renderer_vk::text::{TextShadow, TextStyle},
|
||||
|
|
@ -41,8 +41,9 @@ struct State {
|
|||
#[allow(clippy::struct_field_names)]
|
||||
struct Data {
|
||||
#[allow(dead_code)]
|
||||
id_rect_container: WidgetID, // Rectangle
|
||||
id_rect_bottom: WidgetID, // Rectangle
|
||||
id_rect_container: WidgetID,
|
||||
id_rect_bottom: WidgetID,
|
||||
id_rect_cursor: WidgetID,
|
||||
id_label: WidgetID,
|
||||
}
|
||||
|
||||
|
|
@ -76,15 +77,15 @@ fn anim_bottom_rect(
|
|||
common.alterables.set_style(
|
||||
data.widget_id,
|
||||
StyleSetRequest::Size(taffy::Size {
|
||||
width: percent(0.9.lerp(1.0, pos_bidir)),
|
||||
height: length(2.0 + pos_bidir * 2.0),
|
||||
width: percent(0.95.lerp(1.0, pos_bidir)),
|
||||
height: length(1.0 + pos_bidir),
|
||||
}),
|
||||
);
|
||||
|
||||
common.alterables.set_style(
|
||||
data.widget_id,
|
||||
StyleSetRequest::Margin(taffy::Rect {
|
||||
bottom: length(0.0),
|
||||
bottom: length(pos_bidir),
|
||||
left: auto(),
|
||||
right: auto(),
|
||||
top: auto(),
|
||||
|
|
@ -105,7 +106,7 @@ fn refresh_all(common: &mut CallbackDataCommon, data: &Data, state: &mut State)
|
|||
drop(defaults);
|
||||
|
||||
let (rect_color, border_color) = if state.focused {
|
||||
(editbox_color.add_rgb(0.1), editbox_color.add_rgb(0.75))
|
||||
(editbox_color.add_rgb(0.15), editbox_color.add_rgb(0.15 + 0.25))
|
||||
} else if state.hovered {
|
||||
(editbox_color.add_rgb(0.1), editbox_color.add_rgb(0.1 + 0.15))
|
||||
} else {
|
||||
|
|
@ -122,6 +123,16 @@ fn refresh_all(common: &mut CallbackDataCommon, data: &Data, state: &mut State)
|
|||
state.focused_prev = state.focused;
|
||||
}
|
||||
|
||||
// Cursor
|
||||
common.alterables.set_style(
|
||||
data.id_rect_cursor,
|
||||
StyleSetRequest::Display(if state.focused {
|
||||
taffy::Display::Flex
|
||||
} else {
|
||||
taffy::Display::None
|
||||
}),
|
||||
);
|
||||
|
||||
state.first_refresh = false;
|
||||
|
||||
Some(())
|
||||
|
|
@ -149,13 +160,22 @@ impl ComponentTrait for ComponentEditBox {
|
|||
}
|
||||
}
|
||||
|
||||
impl ComponentEditBox {
|
||||
pub fn set_text(&self, common: &mut CallbackDataCommon, text: Translation) {
|
||||
let Some(mut label) = common.state.widgets.get_as::<WidgetLabel>(self.data.id_label) else {
|
||||
return;
|
||||
};
|
||||
fn update_text(common: &mut CallbackDataCommon, state: &mut State, data: &Data, text: String) {
|
||||
let Some(mut label) = common.state.widgets.get_as::<WidgetLabel>(data.id_label) else {
|
||||
return;
|
||||
};
|
||||
|
||||
label.set_text(common, text);
|
||||
label.set_text(common, Translation::from_raw_text(&text));
|
||||
|
||||
common.alterables.refresh_component_once(&state.self_ref);
|
||||
|
||||
state.text = text;
|
||||
}
|
||||
|
||||
impl ComponentEditBox {
|
||||
pub fn set_text(&self, common: &mut CallbackDataCommon, text: &str) {
|
||||
let mut state = self.state.borrow_mut();
|
||||
update_text(common, &mut state, &self.data, String::from(text));
|
||||
}
|
||||
|
||||
pub fn get_text(&self) -> Ref<'_, String> {
|
||||
|
|
@ -163,6 +183,50 @@ impl ComponentEditBox {
|
|||
}
|
||||
}
|
||||
|
||||
fn register_event_text_input(
|
||||
state: Rc<RefCell<State>>,
|
||||
data: Rc<Data>,
|
||||
listeners: &mut EventListenerCollection,
|
||||
) -> event::EventListenerID {
|
||||
listeners.register(
|
||||
EventListenerKind::TextInput,
|
||||
Box::new(move |common, evt, (), ()| {
|
||||
let mut state = state.borrow_mut();
|
||||
if !state.focused {
|
||||
return Ok(EventResult::Pass);
|
||||
}
|
||||
|
||||
let CallbackMetadata::TextInput(input) = &evt.metadata else {
|
||||
unreachable!();
|
||||
};
|
||||
|
||||
let Some(input_text) = &input.text else {
|
||||
return Ok(EventResult::Pass); // nothing to do
|
||||
};
|
||||
|
||||
let Some(ch) = input_text.chars().next() else {
|
||||
return Ok(EventResult::Pass); // ???
|
||||
};
|
||||
|
||||
let mut new_text = std::mem::take(&mut state.text);
|
||||
|
||||
if ch == '\x08' {
|
||||
// Backspace
|
||||
new_text.pop();
|
||||
} else {
|
||||
let printable = !input_text.chars().any(char::is_control);
|
||||
if printable {
|
||||
new_text.push_str(input_text);
|
||||
}
|
||||
}
|
||||
|
||||
update_text(common, &mut state, &data, new_text);
|
||||
|
||||
Ok(EventResult::Consumed)
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
||||
fn register_event_mouse_enter(
|
||||
state: Rc<RefCell<State>>,
|
||||
listeners: &mut EventListenerCollection,
|
||||
|
|
@ -217,6 +281,7 @@ pub fn construct(
|
|||
) -> anyhow::Result<(WidgetPair, Rc<ComponentEditBox>)> {
|
||||
let globals = ess.layout.state.globals.clone();
|
||||
let defaults = globals.defaults();
|
||||
let text_color = defaults.text_color;
|
||||
drop(defaults);
|
||||
|
||||
if params.style.size.width.is_auto() {
|
||||
|
|
@ -232,7 +297,7 @@ pub fn construct(
|
|||
params.style.position = taffy::Position::Relative;
|
||||
params.style.overflow = taffy::Point {
|
||||
x: taffy::Overflow::Scroll,
|
||||
y: taffy::Overflow::Scroll,
|
||||
y: taffy::Overflow::Visible,
|
||||
};
|
||||
params.style.min_size = params.style.max_size;
|
||||
|
||||
|
|
@ -296,13 +361,34 @@ pub fn construct(
|
|||
},
|
||||
},
|
||||
),
|
||||
Default::default(),
|
||||
taffy::Style {
|
||||
position: taffy::Position::Relative,
|
||||
..Default::default()
|
||||
},
|
||||
)?;
|
||||
|
||||
let (rect_cursor, _) = ess.layout.add_child(
|
||||
label_parent.id,
|
||||
WidgetRectangle::create(WidgetRectangleParams {
|
||||
color: text_color.with_alpha(0.75),
|
||||
..Default::default()
|
||||
}),
|
||||
taffy::Style {
|
||||
align_self: Some(taffy::AlignSelf::Center),
|
||||
justify_self: Some(taffy::JustifySelf::End),
|
||||
min_size: taffy::Size {
|
||||
width: length(2.0),
|
||||
height: length(16.0),
|
||||
},
|
||||
..Default::default()
|
||||
},
|
||||
)?;
|
||||
|
||||
let data = Rc::new(Data {
|
||||
id_rect_container: id_container,
|
||||
id_label: label.id,
|
||||
id_rect_bottom: rect_bottom.id,
|
||||
id_rect_cursor: rect_cursor.id,
|
||||
});
|
||||
|
||||
let state = Rc::new(RefCell::new(State {
|
||||
|
|
@ -322,6 +408,7 @@ pub fn construct(
|
|||
register_event_mouse_enter(state.clone(), &mut root_state.event_listeners),
|
||||
register_event_mouse_leave(state.clone(), &mut root_state.event_listeners),
|
||||
register_event_mouse_press(state.clone(), &mut root_state.event_listeners),
|
||||
register_event_text_input(state.clone(), data.clone(), &mut root_state.event_listeners),
|
||||
]
|
||||
},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -19,10 +19,6 @@ use crate::{
|
|||
|
||||
use super::{layout::Layout, widget::DrawState};
|
||||
|
||||
pub struct ImageHandle {
|
||||
// to be implemented, will contain pixel data (RGB or RGBA) loaded via "ImageBank" or something by the gui
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone, Copy, PartialEq)]
|
||||
pub struct Boundary {
|
||||
pub pos: Vec2,
|
||||
|
|
@ -254,14 +250,19 @@ pub fn has_overflow_clip(style: &taffy::Style) -> bool {
|
|||
style.overflow.x != taffy::Overflow::Visible || style.overflow.y != taffy::Overflow::Visible
|
||||
}
|
||||
|
||||
fn primitive_debug_rect(boundary: &Boundary, transform: &Mat4, color: drawing::Color) -> drawing::RenderPrimitive {
|
||||
fn primitive_debug_rect(
|
||||
boundary: &Boundary,
|
||||
transform: &Mat4,
|
||||
color: drawing::Color,
|
||||
border: f32,
|
||||
) -> drawing::RenderPrimitive {
|
||||
drawing::RenderPrimitive::Rectangle(
|
||||
PrimitiveExtent {
|
||||
boundary: *boundary,
|
||||
transform: *transform,
|
||||
},
|
||||
Rectangle {
|
||||
border: 1.0,
|
||||
border,
|
||||
border_color: color,
|
||||
color: Color::new(0.0, 0.0, 0.0, 0.0),
|
||||
..Default::default()
|
||||
|
|
@ -277,12 +278,16 @@ pub fn push_transform_stack(
|
|||
) {
|
||||
let raw_dim = Vec2::new(l.size.width, l.size.height);
|
||||
let visual_dim = raw_dim + scroll_shift;
|
||||
let content_dim = Vec2::new(l.content_box_width(), l.content_box_height());
|
||||
let content_rel_pos = Vec2::new(l.content_box_x(), l.content_box_y());
|
||||
|
||||
transform_stack.push(stack::Transform {
|
||||
rel_pos: Vec2::new(l.location.x, l.location.y) - scroll_shift,
|
||||
transform: widget_state.data.transform,
|
||||
raw_dim,
|
||||
visual_dim,
|
||||
content_dim,
|
||||
content_rel_pos,
|
||||
abs_pos: Default::default(),
|
||||
transform_rel: Default::default(),
|
||||
});
|
||||
|
|
@ -368,11 +373,11 @@ fn draw_widget(
|
|||
&boundary,
|
||||
&state.transform_stack.get().transform,
|
||||
Color::new(0.0, 1.0, 1.0, 0.5),
|
||||
1.0,
|
||||
));
|
||||
}
|
||||
|
||||
let starting_scissor_set_count = internal.scissor_set_count;
|
||||
|
||||
let scissor_result = push_scissor_stack(state.transform_stack, state.scissor_stack, scroll_shift, &info, style);
|
||||
|
||||
if scissor_result == PushScissorStackResult::VisibleAndClip {
|
||||
|
|
@ -383,6 +388,7 @@ fn draw_widget(
|
|||
&boundary_relative,
|
||||
&state.transform_stack.get().transform,
|
||||
Color::new(1.0, 0.0, 1.0, 1.0),
|
||||
3.0,
|
||||
));
|
||||
}
|
||||
state
|
||||
|
|
@ -412,12 +418,12 @@ fn draw_widget(
|
|||
.push(drawing::RenderPrimitive::ScissorSet(*state.scissor_stack.get()));
|
||||
}
|
||||
|
||||
state.transform_stack.pop();
|
||||
|
||||
if let Some(info) = &info {
|
||||
widget_state.draw_scrollbars(state, &draw_params, info);
|
||||
}
|
||||
|
||||
state.transform_stack.pop();
|
||||
|
||||
if wants_redraw {
|
||||
state.alterables.mark_redraw();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ use std::{
|
|||
any::{Any, TypeId},
|
||||
cell::{Ref, RefMut},
|
||||
collections::HashSet,
|
||||
rc::Weak,
|
||||
rc::{Rc, Weak},
|
||||
};
|
||||
|
||||
use glam::Vec2;
|
||||
|
|
@ -10,7 +10,7 @@ use slotmap::{DenseSlotMap, new_key_type};
|
|||
|
||||
use crate::{
|
||||
animation::{self, Animation},
|
||||
components::{Component, ComponentTrait, ComponentWeak},
|
||||
components::{ComponentTrait, ComponentWeak},
|
||||
globals,
|
||||
i18n::I18n,
|
||||
layout::{LayoutDispatchFunc, LayoutState, LayoutTask, WidgetID},
|
||||
|
|
@ -27,7 +27,7 @@ pub enum MouseButtonIndex {
|
|||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct MouseButton {
|
||||
pub struct MouseButtonEvent {
|
||||
pub index: MouseButtonIndex,
|
||||
pub pos: Vec2,
|
||||
pub device: usize,
|
||||
|
|
@ -39,12 +39,6 @@ pub struct MousePosition {
|
|||
pub device: usize,
|
||||
}
|
||||
|
||||
pub struct MouseDownEvent {
|
||||
pub pos: Vec2,
|
||||
pub index: MouseButtonIndex,
|
||||
pub device: usize,
|
||||
}
|
||||
|
||||
pub struct MouseLeaveEvent {
|
||||
pub device: usize,
|
||||
}
|
||||
|
|
@ -54,29 +48,29 @@ pub struct MouseMotionEvent {
|
|||
pub device: usize,
|
||||
}
|
||||
|
||||
pub struct MouseUpEvent {
|
||||
pub pos: Vec2,
|
||||
pub index: MouseButtonIndex,
|
||||
pub device: usize,
|
||||
}
|
||||
|
||||
pub struct MouseWheelEvent {
|
||||
pub pos: Vec2, /* mouse position */
|
||||
pub delta: Vec2, /* wheel delta */
|
||||
pub device: usize,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct TextInputEvent {
|
||||
pub text: Option<Rc<str>>,
|
||||
}
|
||||
|
||||
pub struct InternalStateChangeEvent {
|
||||
pub metadata: usize,
|
||||
}
|
||||
|
||||
pub enum Event {
|
||||
InternalStateChange(InternalStateChangeEvent),
|
||||
MouseDown(MouseDownEvent),
|
||||
MouseDown(MouseButtonEvent),
|
||||
MouseLeave(MouseLeaveEvent),
|
||||
MouseMotion(MouseMotionEvent),
|
||||
MouseUp(MouseUpEvent),
|
||||
MouseUp(MouseButtonEvent),
|
||||
MouseWheel(MouseWheelEvent),
|
||||
TextInput(TextInputEvent),
|
||||
}
|
||||
|
||||
impl Event {
|
||||
|
|
@ -203,8 +197,9 @@ pub struct CallbackData<'a> {
|
|||
|
||||
pub enum CallbackMetadata {
|
||||
None,
|
||||
MouseButton(MouseButton),
|
||||
MouseButton(MouseButtonEvent),
|
||||
MousePosition(MousePosition),
|
||||
TextInput(TextInputEvent),
|
||||
Custom(usize),
|
||||
}
|
||||
|
||||
|
|
@ -213,9 +208,10 @@ impl CallbackMetadata {
|
|||
|
||||
pub const fn get_mouse_pos_absolute(&self) -> Option<Vec2> {
|
||||
match *self {
|
||||
Self::MouseButton(b) => Some(b.pos),
|
||||
Self::MousePosition(b) => Some(b.pos),
|
||||
Self::Custom(_) | Self::None => None,
|
||||
CallbackMetadata::MouseButton(b) => Some(b.pos),
|
||||
CallbackMetadata::MousePosition(b) => Some(b.pos),
|
||||
CallbackMetadata::Custom(_) | CallbackMetadata::None => None,
|
||||
CallbackMetadata::TextInput(_) => None,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -232,6 +228,7 @@ pub enum EventListenerKind {
|
|||
MouseEnter,
|
||||
MouseMotion,
|
||||
MouseLeave,
|
||||
TextInput,
|
||||
InternalStateChange,
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -39,6 +39,11 @@ impl<T: StackItem<T>, const STACK_MAX: usize> GenericStack<T, STACK_MAX> {
|
|||
pub const fn get(&self) -> &T {
|
||||
&self.stack[(self.top - 1) as usize]
|
||||
}
|
||||
|
||||
pub const fn parent(&self) -> &T {
|
||||
debug_assert!(self.top >= 2);
|
||||
&self.stack[(self.top - 2) as usize]
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: StackItem<T>, const STACK_MAX: usize> Default for GenericStack<T, STACK_MAX> {
|
||||
|
|
@ -54,9 +59,11 @@ impl<T: StackItem<T>, const STACK_MAX: usize> Default for GenericStack<T, STACK_
|
|||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct Transform {
|
||||
pub rel_pos: Vec2,
|
||||
pub visual_dim: Vec2, // for convenience
|
||||
pub raw_dim: Vec2, // for convenience
|
||||
pub abs_pos: Vec2, // for convenience, will be set after pushing
|
||||
pub visual_dim: Vec2,
|
||||
pub raw_dim: Vec2,
|
||||
pub content_rel_pos: Vec2,
|
||||
pub content_dim: Vec2,
|
||||
pub abs_pos: Vec2, // for convenience, will be set after pushing
|
||||
pub transform: glam::Mat4,
|
||||
pub transform_rel: glam::Mat4,
|
||||
}
|
||||
|
|
@ -68,6 +75,8 @@ impl Default for Transform {
|
|||
rel_pos: Default::default(),
|
||||
visual_dim: Default::default(),
|
||||
raw_dim: Default::default(),
|
||||
content_dim: Default::default(),
|
||||
content_rel_pos: Default::default(),
|
||||
transform: Mat4::IDENTITY,
|
||||
transform_rel: Default::default(),
|
||||
}
|
||||
|
|
|
|||
|
|
@ -311,6 +311,8 @@ impl WidgetState {
|
|||
}
|
||||
|
||||
pub fn get_scroll_shift_smooth(&self, info: &ScrollbarInfo, l: &taffy::Layout, timestep_alpha: f32) -> (Vec2, bool) {
|
||||
//return (self.get_scroll_shift_raw(info, l), false);
|
||||
|
||||
let currently_animating = self.data.scrolling_cur != self.data.scrolling_cur_prev;
|
||||
|
||||
let scrolling = self
|
||||
|
|
@ -368,7 +370,8 @@ impl WidgetState {
|
|||
return;
|
||||
}
|
||||
|
||||
let transform = state.transform_stack.get();
|
||||
let transform_widget = state.transform_stack.get();
|
||||
let transform_parent = state.transform_stack.parent();
|
||||
|
||||
let thickness = 6.0;
|
||||
let margin = 6.0;
|
||||
|
|
@ -385,12 +388,15 @@ impl WidgetState {
|
|||
PrimitiveExtent {
|
||||
boundary: drawing::Boundary::from_pos_size(
|
||||
Vec2::new(
|
||||
transform.rel_pos.x + transform.raw_dim.x * (1.0 - info.handle_size.x) * self.data.scrolling_cur.x,
|
||||
transform.rel_pos.y + transform.raw_dim.y - thickness - margin,
|
||||
// X
|
||||
transform_widget.content_rel_pos.x
|
||||
+ transform_parent.raw_dim.x * (1.0 - info.handle_size.x) * self.data.scrolling_cur.x,
|
||||
// Y
|
||||
transform_widget.content_rel_pos.y + transform_widget.raw_dim.y - thickness - margin,
|
||||
),
|
||||
Vec2::new(transform.raw_dim.x * info.handle_size.x, thickness),
|
||||
Vec2::new(transform_widget.raw_dim.x * info.handle_size.x, thickness),
|
||||
),
|
||||
transform: transform.transform,
|
||||
transform: transform_parent.transform,
|
||||
},
|
||||
rect_params,
|
||||
));
|
||||
|
|
@ -402,12 +408,15 @@ impl WidgetState {
|
|||
PrimitiveExtent {
|
||||
boundary: drawing::Boundary::from_pos_size(
|
||||
Vec2::new(
|
||||
transform.rel_pos.x + transform.raw_dim.x - thickness - margin,
|
||||
transform.rel_pos.y + transform.raw_dim.y * (1.0 - info.handle_size.y) * self.data.scrolling_cur.y,
|
||||
// X
|
||||
transform_widget.content_rel_pos.x + transform_widget.raw_dim.x - thickness - margin,
|
||||
// Y
|
||||
transform_widget.content_rel_pos.y
|
||||
+ transform_parent.raw_dim.y * (1.0 - info.handle_size.y) * self.data.scrolling_cur.y,
|
||||
),
|
||||
Vec2::new(thickness, transform.raw_dim.y * info.handle_size.y),
|
||||
Vec2::new(thickness, transform_widget.raw_dim.y * info.handle_size.y),
|
||||
),
|
||||
transform: transform.transform,
|
||||
transform: transform_parent.transform,
|
||||
},
|
||||
rect_params,
|
||||
));
|
||||
|
|
@ -489,16 +498,19 @@ impl WidgetState {
|
|||
let mut res: Option<InvokeListenersResult> = None;
|
||||
|
||||
match &event {
|
||||
Event::TextInput(e) => {
|
||||
res = Some(self.invoke_listeners(
|
||||
&mut invoke_data,
|
||||
EventListenerKind::TextInput,
|
||||
CallbackMetadata::TextInput(e.clone()),
|
||||
)?);
|
||||
}
|
||||
Event::MouseDown(e) => {
|
||||
if hovered && self.data.set_device_pressed(e.device, true) {
|
||||
res = Some(self.invoke_listeners(
|
||||
&mut invoke_data,
|
||||
EventListenerKind::MousePress,
|
||||
CallbackMetadata::MouseButton(event::MouseButton {
|
||||
index: e.index,
|
||||
pos: e.pos,
|
||||
device: e.device,
|
||||
}),
|
||||
CallbackMetadata::MouseButton(*e),
|
||||
)?);
|
||||
}
|
||||
}
|
||||
|
|
@ -507,11 +519,7 @@ impl WidgetState {
|
|||
res = Some(self.invoke_listeners(
|
||||
&mut invoke_data,
|
||||
EventListenerKind::MouseRelease,
|
||||
CallbackMetadata::MouseButton(event::MouseButton {
|
||||
index: e.index,
|
||||
pos: e.pos,
|
||||
device: e.device,
|
||||
}),
|
||||
CallbackMetadata::MouseButton(*e),
|
||||
)?);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue