WIP: buildout mouse interactions
This commit is contained in:
parent
61fe3c093d
commit
c8f4eb9d34
4 changed files with 224 additions and 136 deletions
57
src/app.rs
57
src/app.rs
|
|
@ -10,7 +10,7 @@ use cosmic::{
|
|||
futures::{self, SinkExt},
|
||||
keyboard::{Event as KeyEvent, Key, Modifiers},
|
||||
subscription::{self, Subscription},
|
||||
window, Event, Length, Point,
|
||||
window, Event, Length,
|
||||
},
|
||||
style,
|
||||
widget::{self, segmented_button},
|
||||
|
|
@ -29,7 +29,7 @@ use crate::{
|
|||
config::{AppTheme, Config, IconSizes, TabConfig, CONFIG_VERSION},
|
||||
fl, home_dir,
|
||||
key_bind::{key_binds, KeyBind},
|
||||
menu, mouse_area,
|
||||
menu,
|
||||
operation::Operation,
|
||||
tab::{self, ItemMetadata, Location, Tab},
|
||||
};
|
||||
|
|
@ -126,7 +126,6 @@ pub enum Message {
|
|||
TabClose(Option<segmented_button::Entity>),
|
||||
TabConfig(TabConfig),
|
||||
TabContextAction(segmented_button::Entity, Action),
|
||||
TabContextMenu(segmented_button::Entity, Option<Point>),
|
||||
TabMessage(Option<segmented_button::Entity>, tab::Message),
|
||||
TabNew,
|
||||
TabRescan(segmented_button::Entity, Vec<tab::Item>),
|
||||
|
|
@ -862,20 +861,14 @@ impl Application for App {
|
|||
_ => {}
|
||||
}
|
||||
}
|
||||
Message::TabContextMenu(entity, position_opt) => {
|
||||
match self.tab_model.data_mut::<Tab>(entity) {
|
||||
Some(tab) => {
|
||||
// Update context menu position
|
||||
tab.context_menu = position_opt;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
// Disable side context page
|
||||
self.core.window.show_context = false;
|
||||
}
|
||||
Message::TabMessage(entity_opt, tab_message) => {
|
||||
let entity = entity_opt.unwrap_or_else(|| self.tab_model.active());
|
||||
|
||||
if let tab::Message::ContextMenu(_point_opt) = tab_message {
|
||||
// Disable side context page
|
||||
self.core.window.show_context = false;
|
||||
}
|
||||
|
||||
let mut update_opt = None;
|
||||
match self.tab_model.data_mut::<Tab>(entity) {
|
||||
Some(tab) => {
|
||||
|
|
@ -981,38 +974,10 @@ impl Application for App {
|
|||
let entity = self.tab_model.active();
|
||||
match self.tab_model.data::<Tab>(entity) {
|
||||
Some(tab) => {
|
||||
let mut mouse_area = mouse_area::MouseArea::new(
|
||||
tab.view(self.core())
|
||||
.map(move |message| Message::TabMessage(Some(entity), message)),
|
||||
)
|
||||
.on_press(move |_point_opt| {
|
||||
Message::TabMessage(Some(entity), tab::Message::Click(None))
|
||||
})
|
||||
.on_back_press(move |_point_opt| {
|
||||
Message::TabMessage(None, tab::Message::GoPrevious)
|
||||
})
|
||||
.on_forward_press(move |_point_opt| {
|
||||
Message::TabMessage(None, tab::Message::GoNext)
|
||||
});
|
||||
if tab.context_menu.is_some() {
|
||||
mouse_area = mouse_area
|
||||
.on_right_press(move |_point_opt| Message::TabContextMenu(entity, None));
|
||||
} else {
|
||||
mouse_area = mouse_area.on_right_press(move |point_opt| {
|
||||
Message::TabContextMenu(entity, point_opt)
|
||||
});
|
||||
}
|
||||
let mut popover = widget::popover(mouse_area, menu::context_menu(entity, &tab));
|
||||
match tab.context_menu {
|
||||
Some(point) => {
|
||||
let rounded = Point::new(point.x.round(), point.y.round());
|
||||
popover = popover.position(rounded);
|
||||
}
|
||||
None => {
|
||||
popover = popover.show_popup(false);
|
||||
}
|
||||
}
|
||||
tab_column = tab_column.push(popover);
|
||||
let tab_view = tab
|
||||
.view(self.core())
|
||||
.map(move |message| Message::TabMessage(Some(entity), message));
|
||||
tab_column = tab_column.push(tab_view);
|
||||
}
|
||||
None => {
|
||||
//TODO
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ use cosmic::{
|
|||
widget::{
|
||||
self,
|
||||
menu::{ItemHeight, ItemWidth, MenuBar, MenuTree},
|
||||
segmented_button,
|
||||
},
|
||||
Element,
|
||||
};
|
||||
|
|
@ -17,7 +16,7 @@ use crate::{
|
|||
app::{Action, Message},
|
||||
fl,
|
||||
key_bind::KeyBind,
|
||||
tab::{Location, Tab},
|
||||
tab::{self, Location, Tab},
|
||||
};
|
||||
|
||||
macro_rules! menu_button {
|
||||
|
|
@ -35,10 +34,10 @@ macro_rules! menu_button {
|
|||
);
|
||||
}
|
||||
|
||||
pub fn context_menu<'a>(entity: segmented_button::Entity, tab: &Tab) -> Element<'a, Message> {
|
||||
pub fn context_menu<'a>(tab: &Tab) -> Element<'a, tab::Message> {
|
||||
//TODO: show key bindings in context menu?
|
||||
let menu_action = |label, action| {
|
||||
menu_button!(widget::text(label)).on_press(Message::TabContextAction(entity, action))
|
||||
menu_button!(widget::text(label)).on_press(tab::Message::ContextAction(action))
|
||||
};
|
||||
|
||||
let selected = tab
|
||||
|
|
|
|||
|
|
@ -1,16 +1,22 @@
|
|||
//! A container for capturing mouse events.
|
||||
|
||||
use cosmic::iced_core::{
|
||||
event::{self, Event},
|
||||
layout, mouse, overlay, renderer, touch,
|
||||
widget::{tree, Operation, OperationOutputWrapper, Tree},
|
||||
Size, {Clipboard, Element, Layout, Length, Point, Rectangle, Shell, Widget},
|
||||
use cosmic::{
|
||||
iced_core::{
|
||||
border::Border,
|
||||
event::{self, Event},
|
||||
layout, mouse, overlay,
|
||||
renderer::{self, Quad, Renderer as _},
|
||||
touch,
|
||||
widget::{tree, Operation, OperationOutputWrapper, Tree},
|
||||
Clipboard, Color, Layout, Length, Point, Rectangle, Shell, Size, Widget,
|
||||
},
|
||||
Element, Renderer, Theme,
|
||||
};
|
||||
|
||||
/// Emit messages on mouse events.
|
||||
#[allow(missing_debug_implementations)]
|
||||
pub struct MouseArea<'a, Message, Theme, Renderer> {
|
||||
content: Element<'a, Message, Theme, Renderer>,
|
||||
pub struct MouseArea<'a, Message> {
|
||||
content: Element<'a, Message>,
|
||||
on_drag: Option<Box<dyn Fn(Option<Point>) -> Message + 'a>>,
|
||||
on_press: Option<Box<dyn Fn(Option<Point>) -> Message + 'a>>,
|
||||
on_release: Option<Box<dyn Fn(Option<Point>) -> Message + 'a>>,
|
||||
|
|
@ -23,9 +29,10 @@ pub struct MouseArea<'a, Message, Theme, Renderer> {
|
|||
on_back_release: Option<Box<dyn Fn(Option<Point>) -> Message + 'a>>,
|
||||
on_forward_press: Option<Box<dyn Fn(Option<Point>) -> Message + 'a>>,
|
||||
on_forward_release: Option<Box<dyn Fn(Option<Point>) -> Message + 'a>>,
|
||||
show_drag_box: bool,
|
||||
}
|
||||
|
||||
impl<'a, Message, Theme, Renderer> MouseArea<'a, Message, Theme, Renderer> {
|
||||
impl<'a, Message> MouseArea<'a, Message> {
|
||||
/// The message to emit when a drag is initiated.
|
||||
#[must_use]
|
||||
pub fn on_drag(mut self, message: impl Fn(Option<Point>) -> Message + 'a) -> Self {
|
||||
|
|
@ -112,6 +119,12 @@ impl<'a, Message, Theme, Renderer> MouseArea<'a, Message, Theme, Renderer> {
|
|||
self.on_forward_release = Some(Box::new(message));
|
||||
self
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn show_drag_box(mut self, show_drag_box: bool) -> Self {
|
||||
self.show_drag_box = show_drag_box;
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
/// Local state of the [`MouseArea`].
|
||||
|
|
@ -121,9 +134,9 @@ struct State {
|
|||
drag_initiated: Option<Point>,
|
||||
}
|
||||
|
||||
impl<'a, Message, Theme, Renderer> MouseArea<'a, Message, Theme, Renderer> {
|
||||
impl<'a, Message> MouseArea<'a, Message> {
|
||||
/// Creates a [`MouseArea`] with the given content.
|
||||
pub fn new(content: impl Into<Element<'a, Message, Theme, Renderer>>) -> Self {
|
||||
pub fn new(content: impl Into<Element<'a, Message>>) -> Self {
|
||||
MouseArea {
|
||||
content: content.into(),
|
||||
on_drag: None,
|
||||
|
|
@ -138,14 +151,13 @@ impl<'a, Message, Theme, Renderer> MouseArea<'a, Message, Theme, Renderer> {
|
|||
on_back_release: None,
|
||||
on_forward_press: None,
|
||||
on_forward_release: None,
|
||||
show_drag_box: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, Message, Theme, Renderer> Widget<Message, Theme, Renderer>
|
||||
for MouseArea<'a, Message, Theme, Renderer>
|
||||
impl<'a, Message> Widget<Message, Theme, Renderer> for MouseArea<'a, Message>
|
||||
where
|
||||
Renderer: renderer::Renderer,
|
||||
Message: Clone,
|
||||
{
|
||||
fn tag(&self) -> tree::Tag {
|
||||
|
|
@ -261,6 +273,38 @@ where
|
|||
cursor,
|
||||
viewport,
|
||||
);
|
||||
|
||||
if self.show_drag_box {
|
||||
let state = tree.state.downcast_ref::<State>();
|
||||
if let Some(a) = state.drag_initiated {
|
||||
if let Some(b) = cursor.position() {
|
||||
let min_x = a.x.min(b.x);
|
||||
let max_x = a.x.max(b.x);
|
||||
let min_y = a.y.min(b.y);
|
||||
let max_y = a.y.max(b.y);
|
||||
let bounds = Rectangle::new(
|
||||
Point::new(min_x, min_y),
|
||||
Size::new(max_x - min_x, max_y - min_y),
|
||||
);
|
||||
let cosmic = theme.cosmic();
|
||||
let mut bg_color = cosmic.accent_color();
|
||||
//TODO: get correct alpha
|
||||
bg_color.alpha = 0.2;
|
||||
renderer.fill_quad(
|
||||
Quad {
|
||||
bounds,
|
||||
border: Border {
|
||||
color: cosmic.accent_color().into(),
|
||||
width: 1.0,
|
||||
radius: cosmic.radius_xs().into(),
|
||||
},
|
||||
..Default::default()
|
||||
},
|
||||
Color::from(bg_color),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn overlay<'b>(
|
||||
|
|
@ -275,50 +319,47 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, Message, Theme, Renderer> From<MouseArea<'a, Message, Theme, Renderer>>
|
||||
for Element<'a, Message, Theme, Renderer>
|
||||
impl<'a, Message> From<MouseArea<'a, Message>> for Element<'a, Message>
|
||||
where
|
||||
Message: 'a + Clone,
|
||||
Renderer: 'a + renderer::Renderer,
|
||||
Theme: 'a,
|
||||
{
|
||||
fn from(
|
||||
area: MouseArea<'a, Message, Theme, Renderer>,
|
||||
) -> Element<'a, Message, Theme, Renderer> {
|
||||
fn from(area: MouseArea<'a, Message>) -> Element<'a, Message> {
|
||||
Element::new(area)
|
||||
}
|
||||
}
|
||||
|
||||
/// Processes the given [`Event`] and updates the [`State`] of an [`MouseArea`]
|
||||
/// accordingly.
|
||||
fn update<Message: Clone, Theme, Renderer>(
|
||||
widget: &mut MouseArea<'_, Message, Theme, Renderer>,
|
||||
fn update<Message: Clone>(
|
||||
widget: &mut MouseArea<'_, Message>,
|
||||
event: &Event,
|
||||
layout: Layout<'_>,
|
||||
cursor: mouse::Cursor,
|
||||
shell: &mut Shell<'_, Message>,
|
||||
state: &mut State,
|
||||
) -> event::Status {
|
||||
if !cursor.is_over(layout.bounds()) {
|
||||
if state.drag_initiated.is_none() && !cursor.is_over(layout.bounds()) {
|
||||
return event::Status::Ignored;
|
||||
}
|
||||
|
||||
if let Some(message) = widget.on_press.as_ref() {
|
||||
if let Event::Mouse(mouse::Event::ButtonPressed(mouse::Button::Left))
|
||||
| Event::Touch(touch::Event::FingerPressed { .. }) = event
|
||||
{
|
||||
state.drag_initiated = cursor.position();
|
||||
if let Event::Mouse(mouse::Event::ButtonPressed(mouse::Button::Left))
|
||||
| Event::Touch(touch::Event::FingerPressed { .. }) = event
|
||||
{
|
||||
state.drag_initiated = cursor.position();
|
||||
if let Some(message) = widget.on_press.as_ref() {
|
||||
shell.publish(message(cursor.position_in(layout.bounds())));
|
||||
|
||||
return event::Status::Captured;
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(message) = widget.on_release.as_ref() {
|
||||
if let Event::Mouse(mouse::Event::ButtonReleased(mouse::Button::Left))
|
||||
| Event::Touch(touch::Event::FingerLifted { .. }) = event
|
||||
{
|
||||
state.drag_initiated = None;
|
||||
if let Event::Mouse(mouse::Event::ButtonReleased(mouse::Button::Left))
|
||||
| Event::Touch(touch::Event::FingerLifted { .. }) = event
|
||||
{
|
||||
state.drag_initiated = None;
|
||||
if let Some(message) = widget.on_release.as_ref() {
|
||||
shell.publish(message(cursor.position_in(layout.bounds())));
|
||||
|
||||
return event::Status::Captured;
|
||||
|
|
@ -397,16 +438,9 @@ fn update<Message: Clone, Theme, Renderer>(
|
|||
}
|
||||
}
|
||||
|
||||
if state.drag_initiated.is_none() && widget.on_drag.is_some() {
|
||||
if let Event::Mouse(mouse::Event::ButtonPressed(mouse::Button::Left))
|
||||
| Event::Touch(touch::Event::FingerPressed { .. }) = event
|
||||
{
|
||||
state.drag_initiated = cursor.position();
|
||||
}
|
||||
} else if let Some((message, drag_source)) = widget.on_drag.as_ref().zip(state.drag_initiated) {
|
||||
if let Some((message, drag_source)) = widget.on_drag.as_ref().zip(state.drag_initiated) {
|
||||
if let Some(position) = cursor.position() {
|
||||
if position.distance(drag_source) > 1.0 {
|
||||
state.drag_initiated = None;
|
||||
shell.publish(message(cursor.position_in(layout.bounds())));
|
||||
|
||||
return event::Status::Captured;
|
||||
|
|
|
|||
184
src/tab.rs
184
src/tab.rs
|
|
@ -7,11 +7,13 @@ use cosmic::{
|
|||
keyboard::Modifiers,
|
||||
subscription::{self, Subscription},
|
||||
//TODO: export in cosmic::widget
|
||||
widget::horizontal_rule,
|
||||
widget::{horizontal_rule, scrollable::Viewport},
|
||||
Alignment,
|
||||
ContentFit,
|
||||
Length,
|
||||
Point,
|
||||
Rectangle,
|
||||
Size,
|
||||
},
|
||||
theme, widget, Element,
|
||||
};
|
||||
|
|
@ -28,10 +30,12 @@ use std::{
|
|||
};
|
||||
|
||||
use crate::{
|
||||
app::Action,
|
||||
config::{IconSizes, TabConfig},
|
||||
dialog::DialogKind,
|
||||
fl,
|
||||
fl, menu,
|
||||
mime_icon::mime_icon,
|
||||
mouse_area,
|
||||
};
|
||||
|
||||
const DOUBLE_CLICK_DURATION: Duration = Duration::from_millis(500);
|
||||
|
|
@ -390,12 +394,16 @@ impl Location {
|
|||
pub enum Message {
|
||||
Click(Option<usize>),
|
||||
Config(TabConfig),
|
||||
ContextAction(Action),
|
||||
ContextMenu(Option<Point>),
|
||||
Drag(Option<Point>),
|
||||
EditLocation(Option<Location>),
|
||||
GoNext,
|
||||
GoPrevious,
|
||||
Location(Location),
|
||||
LocationUp,
|
||||
RightClick(usize),
|
||||
Scroll(Viewport),
|
||||
Thumbnail(PathBuf, Result<image::RgbaImage, ()>),
|
||||
ToggleShowHidden,
|
||||
View(View),
|
||||
|
|
@ -542,6 +550,8 @@ pub struct Tab {
|
|||
pub items_opt: Option<Vec<Item>>,
|
||||
pub view: View,
|
||||
pub dialog: Option<DialogKind>,
|
||||
pub drag_opt: Option<Point>,
|
||||
pub scroll_opt: Option<Viewport>,
|
||||
pub edit_location: Option<Location>,
|
||||
pub history_i: usize,
|
||||
pub history: Vec<Location>,
|
||||
|
|
@ -555,8 +565,10 @@ impl Tab {
|
|||
location,
|
||||
context_menu: None,
|
||||
items_opt: None,
|
||||
view: View::List,
|
||||
view: View::Grid,
|
||||
dialog: None,
|
||||
drag_opt: None,
|
||||
scroll_opt: None,
|
||||
edit_location: None,
|
||||
history_i: 0,
|
||||
history,
|
||||
|
|
@ -576,6 +588,23 @@ impl Tab {
|
|||
}
|
||||
}
|
||||
|
||||
fn select_by_drag(&mut self, rect: Rectangle) {
|
||||
let items = match &mut self.items_opt {
|
||||
Some(some) => some,
|
||||
None => return,
|
||||
};
|
||||
|
||||
println!("{:?}", rect);
|
||||
let (row, col) = match self.view {
|
||||
View::Grid => (0, 0),
|
||||
View::List => (0, 0),
|
||||
};
|
||||
for (i, item) in items.iter_mut().enumerate() {
|
||||
item.selected = false;
|
||||
//TODO
|
||||
}
|
||||
}
|
||||
|
||||
pub fn update(&mut self, message: Message, modifiers: Modifiers) -> bool {
|
||||
let mut cd = None;
|
||||
let mut history_i_opt = None;
|
||||
|
|
@ -629,6 +658,43 @@ impl Tab {
|
|||
Message::Config(config) => {
|
||||
self.config = config;
|
||||
}
|
||||
Message::ContextAction(action) => {
|
||||
// Close context menu
|
||||
self.context_menu = None;
|
||||
|
||||
// TODO: run actions message
|
||||
println!("TODO {:?}", action);
|
||||
}
|
||||
Message::ContextMenu(point_opt) => {
|
||||
self.context_menu = point_opt;
|
||||
}
|
||||
Message::Drag(point_opt) => match point_opt {
|
||||
Some(point) => {
|
||||
let drag = match self.drag_opt {
|
||||
Some(some) => some,
|
||||
None => {
|
||||
self.drag_opt = Some(point);
|
||||
point
|
||||
}
|
||||
};
|
||||
let min_x = drag.x.min(point.x);
|
||||
let max_x = drag.x.max(point.x);
|
||||
let min_y = drag.y.min(point.y);
|
||||
let max_y = drag.y.max(point.y);
|
||||
let offset_y = self
|
||||
.scroll_opt
|
||||
.map(|x| x.absolute_offset().y)
|
||||
.unwrap_or_default();
|
||||
let rect = Rectangle::new(
|
||||
Point::new(min_x, min_y + offset_y),
|
||||
Size::new(max_x - min_x, max_y - min_y),
|
||||
);
|
||||
self.select_by_drag(rect);
|
||||
}
|
||||
None => {
|
||||
self.drag_opt = None;
|
||||
}
|
||||
},
|
||||
Message::EditLocation(edit_location) => {
|
||||
self.edit_location = edit_location;
|
||||
}
|
||||
|
|
@ -679,6 +745,9 @@ impl Tab {
|
|||
}
|
||||
}
|
||||
}
|
||||
Message::Scroll(viewport) => {
|
||||
self.scroll_opt = Some(viewport);
|
||||
}
|
||||
Message::Thumbnail(path, thumbnail_res) => {
|
||||
if let Some(ref mut items) = self.items_opt {
|
||||
for item in items.iter_mut() {
|
||||
|
|
@ -875,30 +944,27 @@ impl Tab {
|
|||
pub fn empty_view(&self, has_hidden: bool, core: &Core) -> Element<Message> {
|
||||
let cosmic_theme::Spacing { space_xxs, .. } = core.system_theme().cosmic().spacing;
|
||||
|
||||
widget::column::with_children(vec![
|
||||
self.location_view(core),
|
||||
widget::container(
|
||||
widget::column::with_children(vec![
|
||||
widget::icon::from_name("folder-symbolic")
|
||||
.size(64)
|
||||
.icon()
|
||||
.into(),
|
||||
widget::text(if has_hidden {
|
||||
fl!("empty-folder-hidden")
|
||||
} else {
|
||||
fl!("empty-folder")
|
||||
})
|
||||
widget::column::with_children(vec![widget::container(
|
||||
widget::column::with_children(vec![
|
||||
widget::icon::from_name("folder-symbolic")
|
||||
.size(64)
|
||||
.icon()
|
||||
.into(),
|
||||
])
|
||||
.align_items(Alignment::Center)
|
||||
.spacing(space_xxs),
|
||||
)
|
||||
.align_x(Horizontal::Center)
|
||||
.align_y(Vertical::Center)
|
||||
.width(Length::Fill)
|
||||
.height(Length::Fill)
|
||||
.into(),
|
||||
])
|
||||
widget::text(if has_hidden {
|
||||
fl!("empty-folder-hidden")
|
||||
} else {
|
||||
fl!("empty-folder")
|
||||
})
|
||||
.into(),
|
||||
])
|
||||
.align_items(Alignment::Center)
|
||||
.spacing(space_xxs),
|
||||
)
|
||||
.align_x(Horizontal::Center)
|
||||
.align_y(Vertical::Center)
|
||||
.width(Length::Fill)
|
||||
.height(Length::Fill)
|
||||
.into()])
|
||||
.into()
|
||||
}
|
||||
|
||||
|
|
@ -936,13 +1002,14 @@ impl Tab {
|
|||
.height(item_height)
|
||||
.width(item_width),
|
||||
)
|
||||
.padding(0)
|
||||
.style(button_style(item.selected))
|
||||
.on_press(Message::Click(Some(i)));
|
||||
if self.context_menu.is_some() {
|
||||
children.push(button.into());
|
||||
} else {
|
||||
children.push(
|
||||
crate::mouse_area::MouseArea::new(button)
|
||||
mouse_area::MouseArea::new(button)
|
||||
.on_right_press_no_capture(move |_point_opt| Message::RightClick(i))
|
||||
.into(),
|
||||
);
|
||||
|
|
@ -954,13 +1021,10 @@ impl Tab {
|
|||
return self.empty_view(hidden > 0, core);
|
||||
}
|
||||
}
|
||||
widget::column::with_children(vec![
|
||||
self.location_view(core),
|
||||
widget::scrollable(widget::flex_row(children))
|
||||
.width(Length::Fill)
|
||||
.into(),
|
||||
])
|
||||
.into()
|
||||
widget::scrollable(widget::flex_row(children))
|
||||
.on_scroll(Message::Scroll)
|
||||
.width(Length::Fill)
|
||||
.into()
|
||||
}
|
||||
|
||||
pub fn list_view(&self, core: &Core) -> Element<Message> {
|
||||
|
|
@ -1060,7 +1124,7 @@ impl Tab {
|
|||
children.push(button.into());
|
||||
} else {
|
||||
children.push(
|
||||
crate::mouse_area::MouseArea::new(button)
|
||||
mouse_area::MouseArea::new(button)
|
||||
.on_right_press_no_capture(move |_point_opt| Message::RightClick(i))
|
||||
.into(),
|
||||
);
|
||||
|
|
@ -1073,24 +1137,50 @@ impl Tab {
|
|||
}
|
||||
}
|
||||
|
||||
widget::column::with_children(vec![
|
||||
self.location_view(core).into(),
|
||||
widget::scrollable(
|
||||
widget::column::with_children(children)
|
||||
// Hack to make room for scroll bar
|
||||
.padding([0, space_xxs, 0, 0]),
|
||||
)
|
||||
.width(Length::Fill)
|
||||
.into(),
|
||||
])
|
||||
widget::scrollable(
|
||||
widget::column::with_children(children)
|
||||
// Hack to make room for scroll bar
|
||||
.padding([0, space_xxs, 0, 0]),
|
||||
)
|
||||
.on_scroll(Message::Scroll)
|
||||
.width(Length::Fill)
|
||||
.into()
|
||||
}
|
||||
|
||||
pub fn view(&self, core: &Core) -> Element<Message> {
|
||||
widget::container(match self.view {
|
||||
let location_view = self.location_view(core);
|
||||
let item_view = match self.view {
|
||||
View::Grid => self.grid_view(core),
|
||||
View::List => self.list_view(core),
|
||||
})
|
||||
};
|
||||
let mut mouse_area =
|
||||
mouse_area::MouseArea::new(widget::container(item_view).height(Length::Fill))
|
||||
.on_drag(move |point_opt| Message::Drag(point_opt))
|
||||
.on_press(move |_point_opt| Message::Click(None))
|
||||
.on_release(move |point_opt| Message::Drag(None))
|
||||
.on_back_press(move |_point_opt| Message::GoPrevious)
|
||||
.on_forward_press(move |_point_opt| Message::GoNext)
|
||||
.show_drag_box(true);
|
||||
if self.context_menu.is_some() {
|
||||
mouse_area = mouse_area.on_right_press(move |_point_opt| Message::ContextMenu(None));
|
||||
} else {
|
||||
mouse_area =
|
||||
mouse_area.on_right_press(move |point_opt| Message::ContextMenu(point_opt));
|
||||
}
|
||||
let mut popover = widget::popover(mouse_area, menu::context_menu(&self));
|
||||
match self.context_menu {
|
||||
Some(point) => {
|
||||
let rounded = Point::new(point.x.round(), point.y.round());
|
||||
popover = popover.position(rounded);
|
||||
}
|
||||
None => {
|
||||
popover = popover.show_popup(false);
|
||||
}
|
||||
}
|
||||
widget::container(widget::column::with_children(vec![
|
||||
location_view,
|
||||
popover.into(),
|
||||
]))
|
||||
.height(Length::Fill)
|
||||
.width(Length::Fill)
|
||||
.into()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue