mirror of
https://github.com/sxyazi/yazi.git
synced 2026-07-21 23:01:05 +00:00
feat: drag-resize panes with mouse (#3890)
Co-authored-by: Lingxuan Ye <yelingxuan@xiaomi.com> Co-authored-by: sxyazi <sxyazi@gmail.com>
This commit is contained in:
parent
4a2e5addcd
commit
a2996908de
25 changed files with 182 additions and 71 deletions
|
|
@ -17,6 +17,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/):
|
||||||
- Custom tab name ([#3666])
|
- Custom tab name ([#3666])
|
||||||
- New `--in` for `search` action to set search directory ([#3696])
|
- New `--in` for `search` action to set search directory ([#3696])
|
||||||
- Hover cursor over the new file after copying/cutting/linking/hardlinking/extracting ([#3846], [#3854])
|
- Hover cursor over the new file after copying/cutting/linking/hardlinking/extracting ([#3846], [#3854])
|
||||||
|
- Drag-resize panes with mouse ([#3890])
|
||||||
- Multi-file spotter ([#3733])
|
- Multi-file spotter ([#3733])
|
||||||
- New `app:theme` action that hot-reload user themes/flavors ([#3906])
|
- New `app:theme` action that hot-reload user themes/flavors ([#3906])
|
||||||
- Dynamic open/opener Lua API ([#3901])
|
- Dynamic open/opener Lua API ([#3901])
|
||||||
|
|
@ -1703,6 +1704,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/):
|
||||||
[#3846]: https://github.com/sxyazi/yazi/pull/3846
|
[#3846]: https://github.com/sxyazi/yazi/pull/3846
|
||||||
[#3854]: https://github.com/sxyazi/yazi/pull/3854
|
[#3854]: https://github.com/sxyazi/yazi/pull/3854
|
||||||
[#3862]: https://github.com/sxyazi/yazi/pull/3862
|
[#3862]: https://github.com/sxyazi/yazi/pull/3862
|
||||||
|
[#3890]: https://github.com/sxyazi/yazi/pull/3890
|
||||||
[#3891]: https://github.com/sxyazi/yazi/pull/3891
|
[#3891]: https://github.com/sxyazi/yazi/pull/3891
|
||||||
[#3894]: https://github.com/sxyazi/yazi/pull/3894
|
[#3894]: https://github.com/sxyazi/yazi/pull/3894
|
||||||
[#3901]: https://github.com/sxyazi/yazi/pull/3901
|
[#3901]: https://github.com/sxyazi/yazi/pull/3901
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,6 @@ use mlua::{ObjectLike, Table};
|
||||||
use tracing::error;
|
use tracing::error;
|
||||||
use yazi_actor::lives::Lives;
|
use yazi_actor::lives::Lives;
|
||||||
use yazi_binding::runtime_scope;
|
use yazi_binding::runtime_scope;
|
||||||
use yazi_config::YAZI;
|
|
||||||
use yazi_macro::succ;
|
use yazi_macro::succ;
|
||||||
use yazi_parser::app::MouseForm;
|
use yazi_parser::app::MouseForm;
|
||||||
use yazi_plugin::LUA;
|
use yazi_plugin::LUA;
|
||||||
|
|
@ -30,10 +29,6 @@ impl Actor for Mouse {
|
||||||
LUA.globals().raw_get::<Table>("Root")?.call_method::<Table>("new", area)
|
LUA.globals().raw_get::<Table>("Root")?.call_method::<Table>("new", area)
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
if matches!(event.kind, MouseEventKind::Down(_) if YAZI.mgr.mouse_events.get().draggable()) {
|
|
||||||
root.raw_set("_drag_start", event)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
match event.kind {
|
match event.kind {
|
||||||
MouseEventKind::Down(_) => root.call_method("click", (event, false))?,
|
MouseEventKind::Down(_) => root.call_method("click", (event, false))?,
|
||||||
MouseEventKind::Up(_) => root.call_method("click", (event, true))?,
|
MouseEventKind::Up(_) => root.call_method("click", (event, true))?,
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
use std::ops::{Add, AddAssign, Deref};
|
use std::ops::{Add, AddAssign, Deref};
|
||||||
|
|
||||||
use mlua::{FromLua, IntoLua, Lua, MetaMethod, Table, UserData, Value};
|
use mlua::{FromLua, IntoLua, Lua, MetaMethod, Table, UserData, UserDataFields, Value};
|
||||||
|
|
||||||
#[derive(Clone, Copy, Default, FromLua)]
|
#[derive(Clone, Copy, Default, FromLua)]
|
||||||
pub struct Pad(ratatui::widgets::Padding);
|
pub struct Pad(ratatui::widgets::Padding);
|
||||||
|
|
@ -52,7 +52,7 @@ impl Pad {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl UserData for Pad {
|
impl UserData for Pad {
|
||||||
fn add_fields<F: mlua::UserDataFields<Self>>(fields: &mut F) {
|
fn add_fields<F: UserDataFields<Self>>(fields: &mut F) {
|
||||||
fields.add_field_method_get("left", |_, me| Ok(me.left));
|
fields.add_field_method_get("left", |_, me| Ok(me.left));
|
||||||
fields.add_field_method_get("right", |_, me| Ok(me.right));
|
fields.add_field_method_get("right", |_, me| Ok(me.right));
|
||||||
fields.add_field_method_get("top", |_, me| Ok(me.top));
|
fields.add_field_method_get("top", |_, me| Ok(me.top));
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
use std::{ops::Deref, str::FromStr};
|
use std::{ops::Deref, str::FromStr};
|
||||||
|
|
||||||
use mlua::{AnyUserData, ExternalError, ExternalResult, FromLua, IntoLua, Lua, MetaMethod, Table, UserData, UserDataMethods, Value};
|
use mlua::{AnyUserData, ExternalError, ExternalResult, FromLua, IntoLua, Lua, MetaMethod, Table, UserData, UserDataFields, UserDataMethods, Value};
|
||||||
use yazi_shim::strum::IntoStr;
|
use yazi_shim::strum::IntoStr;
|
||||||
|
|
||||||
use super::Pad;
|
use super::Pad;
|
||||||
|
|
@ -81,7 +81,7 @@ impl Pos {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl UserData for Pos {
|
impl UserData for Pos {
|
||||||
fn add_fields<F: mlua::UserDataFields<Self>>(fields: &mut F) {
|
fn add_fields<F: UserDataFields<Self>>(fields: &mut F) {
|
||||||
// TODO: cache
|
// TODO: cache
|
||||||
fields.add_field_method_get("1", |_, me| Ok(me.origin.into_str()));
|
fields.add_field_method_get("1", |_, me| Ok(me.origin.into_str()));
|
||||||
fields.add_field_method_get("x", |_, me| Ok(me.offset.x));
|
fields.add_field_method_get("x", |_, me| Ok(me.offset.x));
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
|
|
||||||
use mlua::{FromLua, IntoLua, Lua, MetaMethod, Table, UserData, UserDataMethods, Value};
|
use mlua::{FromLua, IntoLua, Lua, MetaMethod, Table, UserData, UserDataFields, UserDataMethods, Value};
|
||||||
|
|
||||||
use super::Pad;
|
use super::Pad;
|
||||||
|
|
||||||
|
|
@ -48,10 +48,19 @@ impl Rect {
|
||||||
r.height = r.height.saturating_sub(pad.top + pad.bottom);
|
r.height = r.height.saturating_sub(pad.top + pad.bottom);
|
||||||
Self(r)
|
Self(r)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn patch(self, t: Table) -> mlua::Result<Self> {
|
||||||
|
Ok(Self(ratatui::layout::Rect {
|
||||||
|
x: t.raw_get::<Option<_>>("x")?.unwrap_or(self.x),
|
||||||
|
y: t.raw_get::<Option<_>>("y")?.unwrap_or(self.y),
|
||||||
|
width: t.raw_get::<Option<_>>("w")?.unwrap_or(self.width),
|
||||||
|
height: t.raw_get::<Option<_>>("h")?.unwrap_or(self.height),
|
||||||
|
}))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl UserData for Rect {
|
impl UserData for Rect {
|
||||||
fn add_fields<F: mlua::UserDataFields<Self>>(fields: &mut F) {
|
fn add_fields<F: UserDataFields<Self>>(fields: &mut F) {
|
||||||
fields.add_field_method_get("x", |_, me| Ok(me.x));
|
fields.add_field_method_get("x", |_, me| Ok(me.x));
|
||||||
fields.add_field_method_get("y", |_, me| Ok(me.y));
|
fields.add_field_method_get("y", |_, me| Ok(me.y));
|
||||||
fields.add_field_method_get("w", |_, me| Ok(me.width));
|
fields.add_field_method_get("w", |_, me| Ok(me.width));
|
||||||
|
|
@ -71,5 +80,7 @@ impl UserData for Rect {
|
||||||
fn add_methods<M: UserDataMethods<Self>>(methods: &mut M) {
|
fn add_methods<M: UserDataMethods<Self>>(methods: &mut M) {
|
||||||
methods.add_method("pad", |_, me, pad: Pad| Ok(me.pad(pad)));
|
methods.add_method("pad", |_, me, pad: Pad| Ok(me.pad(pad)));
|
||||||
methods.add_method("contains", |_, me, Self(rect)| Ok(me.contains(rect.into())));
|
methods.add_method("contains", |_, me, Self(rect)| Ok(me.contains(rect.into())));
|
||||||
|
|
||||||
|
methods.add_meta_method(MetaMethod::Call, |_, me, t: Table| me.patch(t));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
|
|
||||||
use mlua::{ExternalError, ExternalResult, FromLua, Lua, UserData, Value};
|
use mlua::{ExternalError, ExternalResult, FromLua, Lua, UserData, UserDataFields, Value};
|
||||||
|
|
||||||
#[derive(Clone, Copy, Default)]
|
#[derive(Clone, Copy, Default)]
|
||||||
pub struct Id(pub yazi_shared::Id);
|
pub struct Id(pub yazi_shared::Id);
|
||||||
|
|
@ -22,7 +22,7 @@ impl FromLua for Id {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl UserData for Id {
|
impl UserData for Id {
|
||||||
fn add_fields<F: mlua::UserDataFields<Self>>(fields: &mut F) {
|
fn add_fields<F: UserDataFields<Self>>(fields: &mut F) {
|
||||||
fields.add_field_method_get("value", |_, me| Ok(me.0.get()));
|
fields.add_field_method_get("value", |_, me| Ok(me.0.get()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
|
|
||||||
use mlua::{MetaMethod, UserData, UserDataMethods};
|
use mlua::{MetaMethod, UserData, UserDataFields, UserDataMethods};
|
||||||
|
|
||||||
pub struct ImageInfo(yazi_adapter::ImageInfo);
|
pub struct ImageInfo(yazi_adapter::ImageInfo);
|
||||||
|
|
||||||
|
|
@ -15,7 +15,7 @@ impl From<yazi_adapter::ImageInfo> for ImageInfo {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl UserData for ImageInfo {
|
impl UserData for ImageInfo {
|
||||||
fn add_fields<F: mlua::UserDataFields<Self>>(fields: &mut F) {
|
fn add_fields<F: UserDataFields<Self>>(fields: &mut F) {
|
||||||
fields.add_field_method_get("w", |_, me| Ok(me.width));
|
fields.add_field_method_get("w", |_, me| Ok(me.width));
|
||||||
fields.add_field_method_get("h", |_, me| Ok(me.height));
|
fields.add_field_method_get("h", |_, me| Ok(me.height));
|
||||||
fields.add_field_method_get("ori", |_, me| Ok(me.orientation.map(|o| o.to_exif())));
|
fields.add_field_method_get("ori", |_, me| Ok(me.orientation.map(|o| o.to_exif())));
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
use std::mem;
|
use std::mem;
|
||||||
|
|
||||||
use mlua::{UserData, Value};
|
use mlua::{UserData, UserDataFields, Value};
|
||||||
|
|
||||||
use super::Status;
|
use super::Status;
|
||||||
use crate::{cached_field, cached_field_mut};
|
use crate::{cached_field, cached_field_mut};
|
||||||
|
|
@ -20,7 +20,7 @@ impl Output {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl UserData for Output {
|
impl UserData for Output {
|
||||||
fn add_fields<F: mlua::UserDataFields<Self>>(fields: &mut F) {
|
fn add_fields<F: UserDataFields<Self>>(fields: &mut F) {
|
||||||
cached_field!(fields, status, |_, me| Ok(Status::new(me.inner.status)));
|
cached_field!(fields, status, |_, me| Ok(Status::new(me.inner.status)));
|
||||||
cached_field_mut!(fields, stdout, |lua, me| {
|
cached_field_mut!(fields, stdout, |lua, me| {
|
||||||
lua.create_external_string(mem::take(&mut me.inner.stdout))
|
lua.create_external_string(mem::take(&mut me.inner.stdout))
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
use mlua::UserData;
|
use mlua::{UserData, UserDataFields};
|
||||||
|
|
||||||
pub struct Status {
|
pub struct Status {
|
||||||
inner: std::process::ExitStatus,
|
inner: std::process::ExitStatus,
|
||||||
|
|
@ -9,7 +9,7 @@ impl Status {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl UserData for Status {
|
impl UserData for Status {
|
||||||
fn add_fields<F: mlua::UserDataFields<Self>>(fields: &mut F) {
|
fn add_fields<F: UserDataFields<Self>>(fields: &mut F) {
|
||||||
fields.add_field_method_get("success", |_, me| Ok(me.inner.success()));
|
fields.add_field_method_get("success", |_, me| Ok(me.inner.success()));
|
||||||
fields.add_field_method_get("code", |_, me| Ok(me.inner.code()));
|
fields.add_field_method_get("code", |_, me| Ok(me.inner.code()));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ linemode = "none"
|
||||||
show_hidden = false
|
show_hidden = false
|
||||||
show_symlink = true
|
show_symlink = true
|
||||||
scrolloff = 5
|
scrolloff = 5
|
||||||
mouse_events = [ "click", "scroll" ]
|
mouse_events = [ "click", "scroll", "drag" ]
|
||||||
|
|
||||||
[preview]
|
[preview]
|
||||||
wrap = "no"
|
wrap = "no"
|
||||||
|
|
|
||||||
|
|
@ -15,10 +15,6 @@ bitflags! {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MouseEvents {
|
|
||||||
pub const fn draggable(self) -> bool { self.contains(Self::DRAG) }
|
|
||||||
}
|
|
||||||
|
|
||||||
impl TryFrom<Vec<String>> for MouseEvents {
|
impl TryFrom<Vec<String>> for MouseEvents {
|
||||||
type Error = anyhow::Error;
|
type Error = anyhow::Error;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,10 @@ end
|
||||||
|
|
||||||
-- Mouse events
|
-- Mouse events
|
||||||
function Current:click(event, up)
|
function Current:click(event, up)
|
||||||
|
if up or event.is_middle then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
local y = event.y - self._area.y + 1
|
local y = event.y - self._area.y + 1
|
||||||
if self._folder.window[y] then
|
if self._folder.window[y] then
|
||||||
Entity:new(self._folder.window[y]):click(event, up)
|
Entity:new(self._folder.window[y]):click(event, up)
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ function Marker:redraw()
|
||||||
|
|
||||||
local y = math.min(self._area.y + last[1], self._area.y + self._area.h) - 1
|
local y = math.min(self._area.y + last[1], self._area.y + self._area.h) - 1
|
||||||
local rect = ui.Rect {
|
local rect = ui.Rect {
|
||||||
x = math.max(0, self._area.x - 1),
|
x = self._area.x,
|
||||||
y = y,
|
y = y,
|
||||||
w = 1,
|
w = 1,
|
||||||
h = math.min(1 + last[2] - last[1], self._area.y + self._area.h - y),
|
h = math.min(1 + last[2] - last[1], self._area.y + self._area.h - y),
|
||||||
|
|
|
||||||
33
yazi-plugin/preset/components/markers.lua
Normal file
33
yazi-plugin/preset/components/markers.lua
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
Markers = {
|
||||||
|
_id = "markers",
|
||||||
|
}
|
||||||
|
|
||||||
|
function Markers:new(chunks, tab)
|
||||||
|
local me = setmetatable({ _chunks = chunks, _tab = tab }, { __index = self })
|
||||||
|
me:build()
|
||||||
|
return me
|
||||||
|
end
|
||||||
|
|
||||||
|
function Markers:build()
|
||||||
|
self._children = {
|
||||||
|
Marker:new(self._chunks[1], self._tab.parent),
|
||||||
|
Marker:new(self._chunks[2], self._tab.current),
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
function Markers:reflow() return {} end
|
||||||
|
|
||||||
|
function Markers:redraw()
|
||||||
|
local elements = {}
|
||||||
|
for _, child in ipairs(self._children) do
|
||||||
|
elements = ya.list_merge(elements, ui.redraw(child))
|
||||||
|
end
|
||||||
|
return elements
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Mouse events
|
||||||
|
function Markers:click(event, up) end
|
||||||
|
|
||||||
|
function Markers:scroll(event, step) end
|
||||||
|
|
||||||
|
function Markers:touch(event, step) end
|
||||||
|
|
@ -34,6 +34,10 @@ end
|
||||||
|
|
||||||
-- Mouse events
|
-- Mouse events
|
||||||
function Parent:click(event, up)
|
function Parent:click(event, up)
|
||||||
|
if up or event.is_middle then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
local y = event.y - self._area.y + 1
|
local y = event.y - self._area.y + 1
|
||||||
local window = self._folder and self._folder.window or {}
|
local window = self._folder and self._folder.window or {}
|
||||||
if window[y] then
|
if window[y] then
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,10 @@ function Preview:redraw() return {} end
|
||||||
|
|
||||||
-- Mouse events
|
-- Mouse events
|
||||||
function Preview:click(event, up)
|
function Preview:click(event, up)
|
||||||
|
if up or event.is_middle then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
local y = event.y - self._area.y + 1
|
local y = event.y - self._area.y + 1
|
||||||
local window = self._folder and self._folder.window or {}
|
local window = self._folder and self._folder.window or {}
|
||||||
if window[y] then
|
if window[y] then
|
||||||
|
|
|
||||||
|
|
@ -1,32 +1,19 @@
|
||||||
Rail = {
|
Rail = {}
|
||||||
_id = "rail",
|
|
||||||
}
|
|
||||||
|
|
||||||
function Rail:new(chunks, tab)
|
function Rail:new(id, area, chunks)
|
||||||
local me = setmetatable({ _chunks = chunks, _tab = tab }, { __index = self })
|
return setmetatable({
|
||||||
me:build()
|
_id = id,
|
||||||
return me
|
_area = area,
|
||||||
|
_chunks = chunks,
|
||||||
|
}, { __index = self })
|
||||||
end
|
end
|
||||||
|
|
||||||
function Rail:build()
|
function Rail:reflow() return { self } end
|
||||||
self._base = {
|
|
||||||
ui.Bar(ui.Edge.RIGHT):area(self._chunks[1]):symbol(th.mgr.border_symbol):style(th.mgr.border_style),
|
|
||||||
ui.Bar(ui.Edge.LEFT):area(self._chunks[3]):symbol(th.mgr.border_symbol):style(th.mgr.border_style),
|
|
||||||
}
|
|
||||||
self._children = {
|
|
||||||
Marker:new(self._chunks[1], self._tab.parent),
|
|
||||||
Marker:new(self._chunks[2], self._tab.current),
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
function Rail:reflow() return {} end
|
|
||||||
|
|
||||||
function Rail:redraw()
|
function Rail:redraw()
|
||||||
local elements = self._base or {}
|
return {
|
||||||
for _, child in ipairs(self._children) do
|
ui.Bar(ui.Edge.LEFT):area(self._area):symbol(th.mgr.border_symbol):style(th.mgr.border_style),
|
||||||
elements = ya.list_merge(elements, ui.redraw(child))
|
}
|
||||||
end
|
|
||||||
return elements
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Mouse events
|
-- Mouse events
|
||||||
|
|
@ -35,3 +22,24 @@ function Rail:click(event, up) end
|
||||||
function Rail:scroll(event, step) end
|
function Rail:scroll(event, step) end
|
||||||
|
|
||||||
function Rail:touch(event, step) end
|
function Rail:touch(event, step) end
|
||||||
|
|
||||||
|
function Rail:drag(event)
|
||||||
|
local c, x, parent, current, preview = self._chunks, 0, 0, 0, 0
|
||||||
|
if self._id == "rail-left" then
|
||||||
|
x = math.min(event.x, c[2].right - 2)
|
||||||
|
parent = math.max(1, x - c[1].x)
|
||||||
|
current = math.max(1, c[1].w + c[2].w - parent)
|
||||||
|
preview = math.max(1, c[3].w)
|
||||||
|
else
|
||||||
|
x = math.max(event.x, c[2].x + 2)
|
||||||
|
preview = math.max(1, c[3].right - x)
|
||||||
|
current = math.max(1, c[2].w + c[3].w - preview)
|
||||||
|
parent = math.max(1, c[1].w)
|
||||||
|
end
|
||||||
|
|
||||||
|
local r = rt.mgr.ratio
|
||||||
|
if r.parent ~= parent or r.current ~= current or r.preview ~= preview then
|
||||||
|
rt.mgr.ratio = { parent, current, preview }
|
||||||
|
ui.render()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
|
||||||
44
yazi-plugin/preset/components/rails.lua
Normal file
44
yazi-plugin/preset/components/rails.lua
Normal file
|
|
@ -0,0 +1,44 @@
|
||||||
|
Rails = {
|
||||||
|
_id = "rails",
|
||||||
|
}
|
||||||
|
|
||||||
|
function Rails:new(chunks, tab)
|
||||||
|
local me = setmetatable({ _chunks = chunks, _tab = tab }, { __index = self })
|
||||||
|
me:build()
|
||||||
|
return me
|
||||||
|
end
|
||||||
|
|
||||||
|
function Rails:build()
|
||||||
|
local c, children = self._chunks, {}
|
||||||
|
if c[1].w > 0 then
|
||||||
|
children[#children + 1] = Rail:new("rail-left", c[2] { w = math.min(1, c[2].w) }, c)
|
||||||
|
end
|
||||||
|
if c[3].w > 0 then
|
||||||
|
children[#children + 1] =
|
||||||
|
Rail:new("rail-right", c[2] { x = math.max(0, c[2].right - 1), w = math.min(1, c[2].w) }, c)
|
||||||
|
end
|
||||||
|
self._children = children
|
||||||
|
end
|
||||||
|
|
||||||
|
function Rails:reflow()
|
||||||
|
local components = {}
|
||||||
|
for _, child in ipairs(self._children) do
|
||||||
|
components = ya.list_merge(components, child:reflow())
|
||||||
|
end
|
||||||
|
return components
|
||||||
|
end
|
||||||
|
|
||||||
|
function Rails:redraw()
|
||||||
|
local elements = {}
|
||||||
|
for _, child in ipairs(self._children) do
|
||||||
|
elements = ya.list_merge(elements, ui.redraw(child))
|
||||||
|
end
|
||||||
|
return elements
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Mouse events
|
||||||
|
function Rails:click(event, up) end
|
||||||
|
|
||||||
|
function Rails:scroll(event, step) end
|
||||||
|
|
||||||
|
function Rails:touch(event, step) end
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
Root = {
|
Root = {
|
||||||
_id = "root",
|
_id = "root",
|
||||||
_drag_start = ui.Rect {},
|
_dragging = nil,
|
||||||
}
|
}
|
||||||
|
|
||||||
function Root:new(area)
|
function Root:new(area)
|
||||||
|
|
@ -50,11 +50,12 @@ end
|
||||||
|
|
||||||
-- Mouse events
|
-- Mouse events
|
||||||
function Root:click(event, up)
|
function Root:click(event, up)
|
||||||
if tostring(cx.layer) ~= "mgr" then
|
local c = Root._dragging or ya.child_at(ui.Rect { x = event.x, y = event.y }, self:reflow())
|
||||||
return
|
Root._dragging = not up and c or nil
|
||||||
|
|
||||||
|
if tostring(cx.layer) == "mgr" then
|
||||||
|
return c and c:click(event, up)
|
||||||
end
|
end
|
||||||
local c = ya.child_at(ui.Rect { x = event.x, y = event.y }, self:reflow())
|
|
||||||
return c and c:click(event, up)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function Root:scroll(event, step)
|
function Root:scroll(event, step)
|
||||||
|
|
@ -75,4 +76,11 @@ end
|
||||||
|
|
||||||
function Root:move(event) end
|
function Root:move(event) end
|
||||||
|
|
||||||
function Root:drag(event) end
|
function Root:drag(event)
|
||||||
|
if tostring(cx.layer) ~= "mgr" then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local c = Root._dragging
|
||||||
|
return c and c.drag and c:drag(event)
|
||||||
|
end
|
||||||
|
|
|
||||||
|
|
@ -23,11 +23,13 @@ end
|
||||||
|
|
||||||
function Tab:build()
|
function Tab:build()
|
||||||
local c = self._chunks
|
local c = self._chunks
|
||||||
|
local p = c[2].w > 0 and 0 or 1
|
||||||
self._children = {
|
self._children = {
|
||||||
Parent:new(c[1]:pad(ui.Pad.x(1)), self._tab),
|
Parent:new(c[1]:pad(ui.Pad(0, p, 0, 1)), self._tab),
|
||||||
Current:new(c[2]:pad(ui.Pad(0, c[3].w > 0 and 0 or 1, 0, c[1].w > 0 and 0 or 1)), self._tab),
|
Current:new(c[2]:pad(ui.Pad.x(1)), self._tab),
|
||||||
Preview:new(c[3]:pad(ui.Pad.x(1)), self._tab),
|
Preview:new(c[3]:pad(ui.Pad(0, 1, 0, p)), self._tab),
|
||||||
Rail:new(c, self._tab),
|
Rails:new(c, self._tab),
|
||||||
|
Markers:new(c, self._tab),
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -29,12 +29,7 @@ function Tasks:redraw()
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
|
|
||||||
elements[#elements + 1] = ui.Line({ self:icon(snap), snap.title }):area(ui.Rect {
|
elements[#elements + 1] = ui.Line({ self:icon(snap), snap.title }):area(self._area { y = y, h = 1 })
|
||||||
x = self._area.x,
|
|
||||||
y = y,
|
|
||||||
w = self._area.w,
|
|
||||||
h = 1,
|
|
||||||
})
|
|
||||||
|
|
||||||
if i == cx.tasks.cursor + 1 then
|
if i == cx.tasks.cursor + 1 then
|
||||||
elements[#elements] = elements[#elements]:style(th.tasks.hovered)
|
elements[#elements] = elements[#elements]:style(th.tasks.hovered)
|
||||||
|
|
@ -107,14 +102,14 @@ function Tasks:progress_redraw(snap, y)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
ui.Gauge()
|
ui.Gauge()
|
||||||
:area(ui.Rect { x = self._chunks[1].x, y = y, w = self._chunks[1].w, h = 1 })
|
:area(self._chunks[1] { y = y, h = 1 })
|
||||||
:percent(snap.percent)
|
:percent(snap.percent)
|
||||||
:label(ui.Span(label):style(th.status.progress_label))
|
:label(ui.Span(label):style(th.status.progress_label))
|
||||||
:gauge_style(style),
|
:gauge_style(style),
|
||||||
|
|
||||||
ui.Line(string.format("%d/%d", snap.prog.success_files, snap.prog.total_files))
|
ui.Line(string.format("%d/%d", snap.prog.success_files, snap.prog.total_files))
|
||||||
:fg("gray")
|
:fg("gray")
|
||||||
:area(ui.Rect { x = self._chunks[2].x, y = y, w = self._chunks[2].w, h = 1 })
|
:area(self._chunks[2] { y = y, h = 1 })
|
||||||
:align(ui.Align.RIGHT),
|
:align(ui.Align.RIGHT),
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -127,7 +122,7 @@ function Tasks:progress_redraw(snap, y)
|
||||||
text = "Failed, press Enter to view log…"
|
text = "Failed, press Enter to view log…"
|
||||||
end
|
end
|
||||||
return {
|
return {
|
||||||
ui.Line(text):fg("gray"):area(ui.Rect { x = self._chunks[1].x, y = y, w = self._chunks[1].w, h = 1 }),
|
ui.Line(text):fg("gray"):area(self._chunks[1] { y = y, h = 1 }),
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -30,10 +30,11 @@ function M:peek(job)
|
||||||
left[#left]:truncate { max = max, ellipsis = entity:ellipsis(max) }
|
left[#left]:truncate { max = max, ellipsis = entity:ellipsis(max) }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local marker_area = job.area { x = math.max(0, job.area.x - 1) }
|
||||||
ya.preview_widget(job, {
|
ya.preview_widget(job, {
|
||||||
ui.List(left):area(job.area),
|
ui.List(left):area(job.area),
|
||||||
ui.Text(right):area(job.area):align(ui.Align.RIGHT),
|
ui.Text(right):area(job.area):align(ui.Align.RIGHT),
|
||||||
table.unpack(Marker:new(job.area, folder):redraw()),
|
table.unpack(Marker:new(marker_area, folder):redraw()),
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -47,11 +47,13 @@ fn stage_1(lua: &Lua) -> Result<()> {
|
||||||
lua.load(preset!("components/linemode")).set_name("linemode.lua").exec()?;
|
lua.load(preset!("components/linemode")).set_name("linemode.lua").exec()?;
|
||||||
|
|
||||||
lua.load(preset!("components/marker")).set_name("marker.lua").exec()?;
|
lua.load(preset!("components/marker")).set_name("marker.lua").exec()?;
|
||||||
|
lua.load(preset!("components/markers")).set_name("markers.lua").exec()?;
|
||||||
lua.load(preset!("components/modal")).set_name("modal.lua").exec()?;
|
lua.load(preset!("components/modal")).set_name("modal.lua").exec()?;
|
||||||
lua.load(preset!("components/parent")).set_name("parent.lua").exec()?;
|
lua.load(preset!("components/parent")).set_name("parent.lua").exec()?;
|
||||||
lua.load(preset!("components/preview")).set_name("preview.lua").exec()?;
|
lua.load(preset!("components/preview")).set_name("preview.lua").exec()?;
|
||||||
lua.load(preset!("components/progress")).set_name("progress.lua").exec()?;
|
lua.load(preset!("components/progress")).set_name("progress.lua").exec()?;
|
||||||
lua.load(preset!("components/rail")).set_name("rail.lua").exec()?;
|
lua.load(preset!("components/rail")).set_name("rail.lua").exec()?;
|
||||||
|
lua.load(preset!("components/rails")).set_name("rails.lua").exec()?;
|
||||||
lua.load(preset!("components/root")).set_name("root.lua").exec()?;
|
lua.load(preset!("components/root")).set_name("root.lua").exec()?;
|
||||||
lua.load(preset!("components/status")).set_name("status.lua").exec()?;
|
lua.load(preset!("components/status")).set_name("status.lua").exec()?;
|
||||||
lua.load(preset!("components/tab")).set_name("tab.lua").exec()?;
|
lua.load(preset!("components/tab")).set_name("tab.lua").exec()?;
|
||||||
|
|
|
||||||
|
|
@ -60,11 +60,13 @@ impl Default for Loader {
|
||||||
("header".to_owned(), [][..].into()),
|
("header".to_owned(), [][..].into()),
|
||||||
("linemode".to_owned(), [][..].into()),
|
("linemode".to_owned(), [][..].into()),
|
||||||
("marker".to_owned(), [][..].into()),
|
("marker".to_owned(), [][..].into()),
|
||||||
|
("markers".to_owned(), [][..].into()),
|
||||||
("modal".to_owned(), [][..].into()),
|
("modal".to_owned(), [][..].into()),
|
||||||
("parent".to_owned(), [][..].into()),
|
("parent".to_owned(), [][..].into()),
|
||||||
("preview".to_owned(), [][..].into()),
|
("preview".to_owned(), [][..].into()),
|
||||||
("progress".to_owned(), [][..].into()),
|
("progress".to_owned(), [][..].into()),
|
||||||
("rail".to_owned(), [][..].into()),
|
("rail".to_owned(), [][..].into()),
|
||||||
|
("rails".to_owned(), [][..].into()),
|
||||||
("root".to_owned(), [][..].into()),
|
("root".to_owned(), [][..].into()),
|
||||||
("status".to_owned(), [][..].into()),
|
("status".to_owned(), [][..].into()),
|
||||||
("tab".to_owned(), [][..].into()),
|
("tab".to_owned(), [][..].into()),
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@ impl Widget for Clear {
|
||||||
}
|
}
|
||||||
|
|
||||||
const fn is_overlapping(a: Rect, b: Rect) -> bool {
|
const fn is_overlapping(a: Rect, b: Rect) -> bool {
|
||||||
a.x < b.x + b.width && a.x + a.width > b.x && a.y < b.y + b.height && a.y + a.height > b.y
|
a.x < b.right() && a.right() > b.x && a.y < b.y + b.height && a.y + a.height > b.y
|
||||||
}
|
}
|
||||||
|
|
||||||
fn overlap(a: Rect, b: Rect) -> Option<Rect> {
|
fn overlap(a: Rect, b: Rect) -> Option<Rect> {
|
||||||
|
|
@ -40,7 +40,7 @@ fn overlap(a: Rect, b: Rect) -> Option<Rect> {
|
||||||
|
|
||||||
let x = a.x.max(b.x);
|
let x = a.x.max(b.x);
|
||||||
let y = a.y.max(b.y);
|
let y = a.y.max(b.y);
|
||||||
let width = (a.x + a.width).min(b.x + b.width) - x;
|
let width = a.right().min(b.right()) - x;
|
||||||
let height = (a.y + a.height).min(b.y + b.height) - y;
|
let height = (a.y + a.height).min(b.y + b.height) - y;
|
||||||
Some(Rect { x, y, width, height })
|
Some(Rect { x, y, width, height })
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue