Checkpoint, MenuHandle can open one
This commit is contained in:
parent
d782426491
commit
267e07472d
3 changed files with 136 additions and 8 deletions
|
@ -1,8 +1,8 @@
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
point, AnyElement, BorrowWindow, Bounds, Element, LayoutId, ParentComponent, Pixels, Point,
|
point, AnyElement, BorrowWindow, Bounds, Component, Element, LayoutId, ParentComponent, Pixels,
|
||||||
Size, Style,
|
Point, Size, Style,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct OverlayState {
|
pub struct OverlayState {
|
||||||
|
@ -48,6 +48,12 @@ impl<V: 'static> ParentComponent<V> for Overlay<V> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<V: 'static> Component<V> for Overlay<V> {
|
||||||
|
fn render(self) -> AnyElement<V> {
|
||||||
|
AnyElement::new(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<V: 'static> Element<V> for Overlay<V> {
|
impl<V: 'static> Element<V> for Overlay<V> {
|
||||||
type ElementState = OverlayState;
|
type ElementState = OverlayState;
|
||||||
|
|
||||||
|
|
|
@ -574,6 +574,7 @@ impl<'a> WindowContext<'a> {
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
/// Add a node to the layout tree for the current frame. Takes the `Style` of the element for which
|
/// Add a node to the layout tree for the current frame. Takes the `Style` of the element for which
|
||||||
/// layout is being requested, along with the layout ids of any children. This method is called during
|
/// layout is being requested, along with the layout ids of any children. This method is called during
|
||||||
/// calls to the `Element::layout` trait method and enables any element to participate in layout.
|
/// calls to the `Element::layout` trait method and enables any element to participate in layout.
|
||||||
|
|
|
@ -1,13 +1,16 @@
|
||||||
use crate::{status_bar::StatusItemView, Axis, Workspace};
|
use crate::{status_bar::StatusItemView, Axis, Workspace};
|
||||||
use gpui::{
|
use gpui::{
|
||||||
div, px, Action, AnyView, AppContext, Component, Div, Entity, EntityId, EventEmitter,
|
div, overlay, point, px, Action, AnyElement, AnyView, AppContext, Component, DispatchPhase,
|
||||||
FocusHandle, FocusableView, ParentComponent, Render, SharedString, Styled, Subscription, View,
|
Div, Element, ElementId, Entity, EntityId, EventEmitter, FocusHandle, FocusableView,
|
||||||
ViewContext, WeakView, WindowContext,
|
InteractiveComponent, LayoutId, MouseButton, MouseDownEvent, ParentComponent, Pixels, Point,
|
||||||
|
Render, SharedString, Style, Styled, Subscription, View, ViewContext, VisualContext, WeakView,
|
||||||
|
WindowContext,
|
||||||
};
|
};
|
||||||
use schemars::JsonSchema;
|
use schemars::JsonSchema;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::sync::Arc;
|
use smallvec::SmallVec;
|
||||||
use ui::{h_stack, IconButton, InteractionState, Tooltip};
|
use std::{cell::RefCell, rc::Rc, sync::Arc};
|
||||||
|
use ui::{h_stack, IconButton, InteractionState, Label, Tooltip};
|
||||||
|
|
||||||
pub enum PanelEvent {
|
pub enum PanelEvent {
|
||||||
ChangePosition,
|
ChangePosition,
|
||||||
|
@ -656,6 +659,118 @@ impl PanelButtons {
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
pub struct MenuHandle<V: 'static> {
|
||||||
|
id: ElementId,
|
||||||
|
children: SmallVec<[AnyElement<V>; 2]>,
|
||||||
|
builder: Rc<dyn Fn(&mut V, &mut ViewContext<V>) -> AnyView + 'static>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<V: 'static> ParentComponent<V> for MenuHandle<V> {
|
||||||
|
fn children_mut(&mut self) -> &mut SmallVec<[AnyElement<V>; 2]> {
|
||||||
|
&mut self.children
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<V: 'static> MenuHandle<V> {
|
||||||
|
fn new(
|
||||||
|
id: impl Into<ElementId>,
|
||||||
|
builder: impl Fn(&mut V, &mut ViewContext<V>) -> AnyView + 'static,
|
||||||
|
) -> Self {
|
||||||
|
Self {
|
||||||
|
id: id.into(),
|
||||||
|
children: SmallVec::new(),
|
||||||
|
builder: Rc::new(builder),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct MenuState<V> {
|
||||||
|
open: Rc<RefCell<bool>>,
|
||||||
|
menu: Option<AnyElement<V>>,
|
||||||
|
}
|
||||||
|
// Here be dragons
|
||||||
|
impl<V: 'static> Element<V> for MenuHandle<V> {
|
||||||
|
type ElementState = MenuState<V>;
|
||||||
|
|
||||||
|
fn element_id(&self) -> Option<gpui::ElementId> {
|
||||||
|
Some(self.id.clone())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn layout(
|
||||||
|
&mut self,
|
||||||
|
view_state: &mut V,
|
||||||
|
element_state: Option<Self::ElementState>,
|
||||||
|
cx: &mut crate::ViewContext<V>,
|
||||||
|
) -> (gpui::LayoutId, Self::ElementState) {
|
||||||
|
let mut child_layout_ids = self
|
||||||
|
.children
|
||||||
|
.iter_mut()
|
||||||
|
.map(|child| child.layout(view_state, cx))
|
||||||
|
.collect::<SmallVec<[LayoutId; 2]>>();
|
||||||
|
|
||||||
|
let open = if let Some(element_state) = element_state {
|
||||||
|
element_state.open
|
||||||
|
} else {
|
||||||
|
Rc::new(RefCell::new(false))
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut menu = None;
|
||||||
|
if *open.borrow() {
|
||||||
|
let mut view = (self.builder)(view_state, cx).render();
|
||||||
|
child_layout_ids.push(view.layout(view_state, cx));
|
||||||
|
menu.replace(view);
|
||||||
|
}
|
||||||
|
let layout_id = cx.request_layout(&gpui::Style::default(), child_layout_ids.into_iter());
|
||||||
|
|
||||||
|
(layout_id, MenuState { open, menu })
|
||||||
|
}
|
||||||
|
|
||||||
|
fn paint(
|
||||||
|
&mut self,
|
||||||
|
bounds: crate::Bounds<gpui::Pixels>,
|
||||||
|
view_state: &mut V,
|
||||||
|
element_state: &mut Self::ElementState,
|
||||||
|
cx: &mut crate::ViewContext<V>,
|
||||||
|
) {
|
||||||
|
for child in &mut self.children {
|
||||||
|
child.paint(view_state, cx);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(mut menu) = element_state.menu.as_mut() {
|
||||||
|
menu.paint(view_state, cx);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let open = element_state.open.clone();
|
||||||
|
cx.on_mouse_event(move |view_state, event: &MouseDownEvent, phase, cx| {
|
||||||
|
dbg!(&event, &phase);
|
||||||
|
if phase == DispatchPhase::Bubble
|
||||||
|
&& event.button == MouseButton::Right
|
||||||
|
&& bounds.contains_point(&event.position)
|
||||||
|
{
|
||||||
|
*open.borrow_mut() = true;
|
||||||
|
cx.notify();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<V: 'static> Component<V> for MenuHandle<V> {
|
||||||
|
fn render(self) -> AnyElement<V> {
|
||||||
|
AnyElement::new(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct TestMenu {}
|
||||||
|
impl Render for TestMenu {
|
||||||
|
type Element = Div<Self>;
|
||||||
|
|
||||||
|
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
||||||
|
div().child("0MG!")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// here be kittens
|
||||||
impl Render for PanelButtons {
|
impl Render for PanelButtons {
|
||||||
type Element = Div<Self>;
|
type Element = Div<Self>;
|
||||||
|
|
||||||
|
@ -689,7 +804,13 @@ impl Render for PanelButtons {
|
||||||
.tooltip(move |_, cx| Tooltip::for_action(name, &*action, cx))
|
.tooltip(move |_, cx| Tooltip::for_action(name, &*action, cx))
|
||||||
};
|
};
|
||||||
|
|
||||||
Some(button)
|
Some(
|
||||||
|
MenuHandle::new(
|
||||||
|
SharedString::from(format!("{} tooltip", name)),
|
||||||
|
move |_, cx| Tooltip::text("HELLOOOOOOOOOOOOOO", cx),
|
||||||
|
)
|
||||||
|
.child(button),
|
||||||
|
)
|
||||||
});
|
});
|
||||||
|
|
||||||
h_stack().children(buttons)
|
h_stack().children(buttons)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue