mirror of
https://github.com/Dummi26/musicdb.git
synced 2025-03-10 05:43:53 +01:00
fix mers, fix space not pausing in idle display
bug that is fixed now: if a textbox was focused on the main screen, and then the idle display opened, pressing spacebar would type a space character into that textbox (even though the box isnt visible), and would not trigger pause/resume. now, the textbox remains unchanged and the player will pause/resume.
This commit is contained in:
parent
0d261371b7
commit
f41bec1423
@ -12,12 +12,11 @@ directories = "5.0.1"
|
|||||||
regex = "1.9.3"
|
regex = "1.9.3"
|
||||||
speedy2d = { version = "1.12.0", optional = true }
|
speedy2d = { version = "1.12.0", optional = true }
|
||||||
toml = "0.7.6"
|
toml = "0.7.6"
|
||||||
# mers_lib = { version = "0.3.2", optional = true }
|
musicdb-mers = { version = "0.1.0", path = "../musicdb-mers", optional = true }
|
||||||
# musicdb-mers = { version = "0.1.0", path = "../musicdb-mers", optional = true }
|
|
||||||
uianimator = "0.1.1"
|
uianimator = "0.1.1"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["gui", "playback"]
|
default = ["gui", "playback", "merscfg"]
|
||||||
# gui:
|
# gui:
|
||||||
# enables the gui modes
|
# enables the gui modes
|
||||||
# merscfg:
|
# merscfg:
|
||||||
@ -27,6 +26,6 @@ default = ["gui", "playback"]
|
|||||||
# playback:
|
# playback:
|
||||||
# enables syncplayer modes, where the client mirrors the server's playback
|
# enables syncplayer modes, where the client mirrors the server's playback
|
||||||
gui = ["speedy2d"]
|
gui = ["speedy2d"]
|
||||||
# merscfg = ["mers_lib", "musicdb-mers", "speedy2d"]
|
merscfg = ["mers", "speedy2d"]
|
||||||
# mers = ["mers_lib", "musicdb-mers"]
|
mers = ["musicdb-mers"]
|
||||||
playback = ["musicdb-lib/playback"]
|
playback = ["musicdb-lib/playback"]
|
||||||
|
@ -299,7 +299,7 @@ pub struct Gui {
|
|||||||
pub size: UVec2,
|
pub size: UVec2,
|
||||||
pub mouse_pos: Vec2,
|
pub mouse_pos: Vec2,
|
||||||
pub font: Font,
|
pub font: Font,
|
||||||
pub keybinds: BTreeMap<KeyBinding, KeyActionId>,
|
pub keybinds: BTreeMap<KeyBinding, KeyActionRef>,
|
||||||
pub key_actions: KeyActions,
|
pub key_actions: KeyActions,
|
||||||
pub covers: Option<HashMap<CoverId, GuiServerImage>>,
|
pub covers: Option<HashMap<CoverId, GuiServerImage>>,
|
||||||
pub custom_images: Option<HashMap<String, GuiServerImage>>,
|
pub custom_images: Option<HashMap<String, GuiServerImage>>,
|
||||||
@ -351,11 +351,11 @@ impl Gui {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(Err(e)) => {
|
Ok(Err(e)) => {
|
||||||
eprintln!("Error loading merscfg:\n{e}");
|
eprintln!("Error loading merscfg:\n{}", e.display_term());
|
||||||
}
|
}
|
||||||
Ok(Ok(Err((m, e)))) => {
|
Ok(Ok(Err((m, e)))) => {
|
||||||
if let Some(e) = e {
|
if let Some(e) = e {
|
||||||
eprintln!("Error loading merscfg:\n{m}\n{e}");
|
eprintln!("Error loading merscfg:\n{m}\n{}", e.display_term());
|
||||||
} else {
|
} else {
|
||||||
eprintln!("Error loading merscfg:\n{m}");
|
eprintln!("Error loading merscfg:\n{m}");
|
||||||
}
|
}
|
||||||
@ -530,28 +530,39 @@ pub trait GuiElem {
|
|||||||
/// handles drawing.
|
/// handles drawing.
|
||||||
fn draw(&mut self, info: &mut DrawInfo, g: &mut Graphics2D) {}
|
fn draw(&mut self, info: &mut DrawInfo, g: &mut Graphics2D) {}
|
||||||
/// an event that is invoked whenever a mouse button is pressed on the element.
|
/// an event that is invoked whenever a mouse button is pressed on the element.
|
||||||
fn mouse_down(&mut self, button: MouseButton) -> Vec<GuiAction> {
|
fn mouse_down(&mut self, e: &mut EventInfo, button: MouseButton) -> Vec<GuiAction> {
|
||||||
Vec::with_capacity(0)
|
Vec::with_capacity(0)
|
||||||
}
|
}
|
||||||
/// an event that is invoked whenever a mouse button that was pressed on the element is released anywhere.
|
/// an event that is invoked whenever a mouse button that was pressed on the element is released anywhere.
|
||||||
fn mouse_up(&mut self, button: MouseButton) -> Vec<GuiAction> {
|
fn mouse_up(&mut self, e: &mut EventInfo, button: MouseButton) -> Vec<GuiAction> {
|
||||||
Vec::with_capacity(0)
|
Vec::with_capacity(0)
|
||||||
}
|
}
|
||||||
/// an event that is invoked after a mouse button was pressed and released on the same GUI element.
|
/// an event that is invoked after a mouse button was pressed and released on the same GUI element.
|
||||||
fn mouse_pressed(&mut self, button: MouseButton) -> Vec<GuiAction> {
|
fn mouse_pressed(&mut self, e: &mut EventInfo, button: MouseButton) -> Vec<GuiAction> {
|
||||||
Vec::with_capacity(0)
|
Vec::with_capacity(0)
|
||||||
}
|
}
|
||||||
fn mouse_wheel(&mut self, diff: f32) -> Vec<GuiAction> {
|
fn mouse_wheel(&mut self, e: &mut EventInfo, diff: f32) -> Vec<GuiAction> {
|
||||||
Vec::with_capacity(0)
|
Vec::with_capacity(0)
|
||||||
}
|
}
|
||||||
fn char_watch(&mut self, modifiers: ModifiersState, key: char) -> Vec<GuiAction> {
|
fn char_watch(
|
||||||
|
&mut self,
|
||||||
|
e: &mut EventInfo,
|
||||||
|
modifiers: ModifiersState,
|
||||||
|
key: char,
|
||||||
|
) -> Vec<GuiAction> {
|
||||||
Vec::with_capacity(0)
|
Vec::with_capacity(0)
|
||||||
}
|
}
|
||||||
fn char_focus(&mut self, modifiers: ModifiersState, key: char) -> Vec<GuiAction> {
|
fn char_focus(
|
||||||
|
&mut self,
|
||||||
|
e: &mut EventInfo,
|
||||||
|
modifiers: ModifiersState,
|
||||||
|
key: char,
|
||||||
|
) -> Vec<GuiAction> {
|
||||||
Vec::with_capacity(0)
|
Vec::with_capacity(0)
|
||||||
}
|
}
|
||||||
fn key_watch(
|
fn key_watch(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
e: &mut EventInfo,
|
||||||
modifiers: ModifiersState,
|
modifiers: ModifiersState,
|
||||||
down: bool,
|
down: bool,
|
||||||
key: Option<VirtualKeyCode>,
|
key: Option<VirtualKeyCode>,
|
||||||
@ -561,6 +572,7 @@ pub trait GuiElem {
|
|||||||
}
|
}
|
||||||
fn key_focus(
|
fn key_focus(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
e: &mut EventInfo,
|
||||||
modifiers: ModifiersState,
|
modifiers: ModifiersState,
|
||||||
down: bool,
|
down: bool,
|
||||||
key: Option<VirtualKeyCode>,
|
key: Option<VirtualKeyCode>,
|
||||||
@ -569,12 +581,24 @@ pub trait GuiElem {
|
|||||||
Vec::with_capacity(0)
|
Vec::with_capacity(0)
|
||||||
}
|
}
|
||||||
/// When something is dragged and released over this element
|
/// When something is dragged and released over this element
|
||||||
fn dragged(&mut self, dragged: Dragging) -> Vec<GuiAction> {
|
fn dragged(&mut self, e: &mut EventInfo, dragged: Dragging) -> Vec<GuiAction> {
|
||||||
Vec::with_capacity(0)
|
Vec::with_capacity(0)
|
||||||
}
|
}
|
||||||
fn updated_library(&mut self) {}
|
fn updated_library(&mut self) {}
|
||||||
fn updated_queue(&mut self) {}
|
fn updated_queue(&mut self) {}
|
||||||
}
|
}
|
||||||
|
pub struct EventInfo(bool);
|
||||||
|
impl EventInfo {
|
||||||
|
pub fn can_take(&self) -> bool {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
|
pub fn take(&mut self) -> bool {
|
||||||
|
std::mem::replace(&mut self.0, false)
|
||||||
|
}
|
||||||
|
fn new() -> Self {
|
||||||
|
Self(true)
|
||||||
|
}
|
||||||
|
}
|
||||||
impl<T: GuiElem + ?Sized> GuiElemInternal for T {}
|
impl<T: GuiElem + ?Sized> GuiElemInternal for T {}
|
||||||
pub(crate) trait GuiElemInternal: GuiElem {
|
pub(crate) trait GuiElemInternal: GuiElem {
|
||||||
fn _draw(&mut self, info: &mut DrawInfo, g: &mut Graphics2D) {
|
fn _draw(&mut self, info: &mut DrawInfo, g: &mut Graphics2D) {
|
||||||
@ -625,38 +649,49 @@ pub(crate) trait GuiElemInternal: GuiElem {
|
|||||||
self.config_mut().pixel_pos = std::mem::replace(&mut info.pos, ppos);
|
self.config_mut().pixel_pos = std::mem::replace(&mut info.pos, ppos);
|
||||||
}
|
}
|
||||||
/// recursively applies the function to all gui elements below and including this one
|
/// recursively applies the function to all gui elements below and including this one
|
||||||
fn _recursive_all(&mut self, f: &mut dyn FnMut(&mut dyn GuiElem)) {
|
fn _recursive_all(&mut self, allow_deactivated: bool, f: &mut dyn FnMut(&mut dyn GuiElem)) {
|
||||||
f(self.elem_mut());
|
if self.config().enabled || allow_deactivated {
|
||||||
for c in self.children() {
|
f(self.elem_mut());
|
||||||
c._recursive_all(f);
|
for c in self.children() {
|
||||||
|
c._recursive_all(allow_deactivated, f);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn _mouse_event(
|
fn _mouse_event(
|
||||||
&mut self,
|
&mut self,
|
||||||
condition: &mut dyn FnMut(&mut dyn GuiElem) -> Option<Vec<GuiAction>>,
|
e: &mut EventInfo,
|
||||||
|
allow_deactivated: bool,
|
||||||
|
condition: &mut dyn FnMut(&mut dyn GuiElem, &mut EventInfo) -> Option<Vec<GuiAction>>,
|
||||||
pos: Vec2,
|
pos: Vec2,
|
||||||
) -> Option<Vec<GuiAction>> {
|
) -> Option<Vec<GuiAction>> {
|
||||||
for c in &mut self.children() {
|
if self.config().enabled || allow_deactivated {
|
||||||
if c.config().enabled {
|
for c in &mut self.children() {
|
||||||
if c.config().pixel_pos.contains(pos) {
|
if c.config().enabled {
|
||||||
if let Some(v) = c._mouse_event(condition, pos) {
|
if c.config().pixel_pos.contains(pos) {
|
||||||
return Some(v);
|
if let Some(v) = c._mouse_event(e, allow_deactivated, condition, pos) {
|
||||||
|
return Some(v);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
condition(self.elem_mut(), e)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
}
|
}
|
||||||
condition(self.elem_mut())
|
|
||||||
}
|
}
|
||||||
fn _release_drag(
|
fn _release_drag(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
e: &mut EventInfo,
|
||||||
dragged: &mut Option<Dragging>,
|
dragged: &mut Option<Dragging>,
|
||||||
pos: Vec2,
|
pos: Vec2,
|
||||||
) -> Option<Vec<GuiAction>> {
|
) -> Option<Vec<GuiAction>> {
|
||||||
self._mouse_event(
|
self._mouse_event(
|
||||||
&mut |v| {
|
e,
|
||||||
|
false,
|
||||||
|
&mut |v, e| {
|
||||||
if v.config().drag_target {
|
if v.config().drag_target {
|
||||||
if let Some(d) = dragged.take() {
|
if let Some(d) = dragged.take() {
|
||||||
return Some(v.dragged(d));
|
return Some(v.dragged(e, d));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None
|
None
|
||||||
@ -666,13 +701,16 @@ pub(crate) trait GuiElemInternal: GuiElem {
|
|||||||
}
|
}
|
||||||
fn _mouse_button(
|
fn _mouse_button(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
e: &mut EventInfo,
|
||||||
button: MouseButton,
|
button: MouseButton,
|
||||||
down: bool,
|
down: bool,
|
||||||
pos: Vec2,
|
pos: Vec2,
|
||||||
) -> Option<Vec<GuiAction>> {
|
) -> Option<Vec<GuiAction>> {
|
||||||
if down {
|
if down {
|
||||||
self._mouse_event(
|
self._mouse_event(
|
||||||
&mut |v: &mut dyn GuiElem| {
|
e,
|
||||||
|
!down,
|
||||||
|
&mut |v: &mut dyn GuiElem, e| {
|
||||||
if v.config().mouse_events {
|
if v.config().mouse_events {
|
||||||
match button {
|
match button {
|
||||||
MouseButton::Left => {
|
MouseButton::Left => {
|
||||||
@ -689,7 +727,7 @@ pub(crate) trait GuiElemInternal: GuiElem {
|
|||||||
}
|
}
|
||||||
MouseButton::Other(_) => {}
|
MouseButton::Other(_) => {}
|
||||||
}
|
}
|
||||||
Some(v.mouse_down(button))
|
Some(v.mouse_down(e, button))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
@ -699,14 +737,16 @@ pub(crate) trait GuiElemInternal: GuiElem {
|
|||||||
} else {
|
} else {
|
||||||
let mut vec = vec![];
|
let mut vec = vec![];
|
||||||
if let Some(a) = self._mouse_event(
|
if let Some(a) = self._mouse_event(
|
||||||
&mut |v: &mut dyn GuiElem| {
|
e,
|
||||||
|
!down,
|
||||||
|
&mut |v: &mut dyn GuiElem, e| {
|
||||||
let down = v.config().mouse_down;
|
let down = v.config().mouse_down;
|
||||||
if v.config().mouse_events
|
if v.config().mouse_events
|
||||||
&& ((button == MouseButton::Left && down.0)
|
&& ((button == MouseButton::Left && down.0)
|
||||||
|| (button == MouseButton::Middle && down.1)
|
|| (button == MouseButton::Middle && down.1)
|
||||||
|| (button == MouseButton::Right && down.2))
|
|| (button == MouseButton::Right && down.2))
|
||||||
{
|
{
|
||||||
Some(v.mouse_pressed(button))
|
Some(v.mouse_pressed(e, button))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
@ -715,7 +755,7 @@ pub(crate) trait GuiElemInternal: GuiElem {
|
|||||||
) {
|
) {
|
||||||
vec.extend(a);
|
vec.extend(a);
|
||||||
};
|
};
|
||||||
self._recursive_all(&mut |v| {
|
self._recursive_all(!down, &mut |v| {
|
||||||
if v.config().mouse_events {
|
if v.config().mouse_events {
|
||||||
match button {
|
match button {
|
||||||
MouseButton::Left => {
|
MouseButton::Left => {
|
||||||
@ -732,17 +772,19 @@ pub(crate) trait GuiElemInternal: GuiElem {
|
|||||||
}
|
}
|
||||||
MouseButton::Other(_) => {}
|
MouseButton::Other(_) => {}
|
||||||
}
|
}
|
||||||
vec.extend(v.mouse_up(button));
|
vec.extend(v.mouse_up(e, button));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
Some(vec)
|
Some(vec)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn _mouse_wheel(&mut self, diff: f32, pos: Vec2) -> Option<Vec<GuiAction>> {
|
fn _mouse_wheel(&mut self, e: &mut EventInfo, diff: f32, pos: Vec2) -> Option<Vec<GuiAction>> {
|
||||||
self._mouse_event(
|
self._mouse_event(
|
||||||
&mut |v| {
|
e,
|
||||||
|
false,
|
||||||
|
&mut |v, e| {
|
||||||
if v.config().scroll_events {
|
if v.config().scroll_events {
|
||||||
Some(v.mouse_wheel(diff))
|
Some(v.mouse_wheel(e, diff))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
@ -752,29 +794,45 @@ pub(crate) trait GuiElemInternal: GuiElem {
|
|||||||
}
|
}
|
||||||
fn _keyboard_event(
|
fn _keyboard_event(
|
||||||
&mut self,
|
&mut self,
|
||||||
f_focus: &mut dyn FnMut(&mut dyn GuiElem, &mut Vec<GuiAction>),
|
e: &mut EventInfo,
|
||||||
f_watch: &mut dyn FnMut(&mut dyn GuiElem, &mut Vec<GuiAction>),
|
allow_deactivated: bool,
|
||||||
|
f_focus: &mut dyn FnMut(&mut dyn GuiElem, &mut EventInfo, &mut Vec<GuiAction>),
|
||||||
|
f_watch: &mut dyn FnMut(&mut dyn GuiElem, &mut EventInfo, &mut Vec<GuiAction>),
|
||||||
) -> Vec<GuiAction> {
|
) -> Vec<GuiAction> {
|
||||||
let mut o = vec![];
|
let mut o = vec![];
|
||||||
self._keyboard_event_inner(&mut Some(f_focus), f_watch, &mut o, true);
|
self._keyboard_event_inner_focus(e, allow_deactivated, f_focus, &mut o);
|
||||||
|
self._keyboard_event_inner_nofocus(e, allow_deactivated, f_watch, &mut o);
|
||||||
o
|
o
|
||||||
}
|
}
|
||||||
fn _keyboard_event_inner(
|
fn _keyboard_event_inner_nofocus(
|
||||||
&mut self,
|
&mut self,
|
||||||
f_focus: &mut Option<&mut dyn FnMut(&mut dyn GuiElem, &mut Vec<GuiAction>)>,
|
e: &mut EventInfo,
|
||||||
f_watch: &mut dyn FnMut(&mut dyn GuiElem, &mut Vec<GuiAction>),
|
allow_deactivated: bool,
|
||||||
|
f_watch: &mut dyn FnMut(&mut dyn GuiElem, &mut EventInfo, &mut Vec<GuiAction>),
|
||||||
events: &mut Vec<GuiAction>,
|
events: &mut Vec<GuiAction>,
|
||||||
focus: bool,
|
|
||||||
) {
|
) {
|
||||||
f_watch(self.elem_mut(), events);
|
if self.config().enabled || allow_deactivated {
|
||||||
let focus_index = self.config().keyboard_focus_index;
|
for child in self.children() {
|
||||||
for (i, child) in self.children().enumerate() {
|
child._keyboard_event_inner_nofocus(e, allow_deactivated, f_watch, events);
|
||||||
child._keyboard_event_inner(f_focus, f_watch, events, focus && i == focus_index);
|
}
|
||||||
|
f_watch(self.elem_mut(), e, events);
|
||||||
}
|
}
|
||||||
if focus {
|
}
|
||||||
// we have focus and no child has consumed f_focus
|
fn _keyboard_event_inner_focus(
|
||||||
if let Some(f) = f_focus.take() {
|
&mut self,
|
||||||
f(self.elem_mut(), events)
|
e: &mut EventInfo,
|
||||||
|
allow_deactivated: bool,
|
||||||
|
f_focus: &mut dyn FnMut(&mut dyn GuiElem, &mut EventInfo, &mut Vec<GuiAction>),
|
||||||
|
events: &mut Vec<GuiAction>,
|
||||||
|
) {
|
||||||
|
if e.can_take() && (self.config().enabled || allow_deactivated) {
|
||||||
|
let i = self.config().keyboard_focus_index;
|
||||||
|
if let Some(child) = self.children().nth(i) {
|
||||||
|
child._keyboard_event_inner_focus(e, allow_deactivated, f_focus, events);
|
||||||
|
}
|
||||||
|
if e.can_take() {
|
||||||
|
// we have focus and no child has taken the event
|
||||||
|
f_focus(self.elem_mut(), e, events);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -880,44 +938,56 @@ impl<T: GuiElemWrapper> GuiElem for T {
|
|||||||
fn draw(&mut self, info: &mut DrawInfo, g: &mut Graphics2D) {
|
fn draw(&mut self, info: &mut DrawInfo, g: &mut Graphics2D) {
|
||||||
self.as_elem_mut().draw(info, g)
|
self.as_elem_mut().draw(info, g)
|
||||||
}
|
}
|
||||||
fn mouse_down(&mut self, button: MouseButton) -> Vec<GuiAction> {
|
fn mouse_down(&mut self, e: &mut EventInfo, button: MouseButton) -> Vec<GuiAction> {
|
||||||
self.as_elem_mut().mouse_down(button)
|
self.as_elem_mut().mouse_down(e, button)
|
||||||
}
|
}
|
||||||
fn mouse_up(&mut self, button: MouseButton) -> Vec<GuiAction> {
|
fn mouse_up(&mut self, e: &mut EventInfo, button: MouseButton) -> Vec<GuiAction> {
|
||||||
self.as_elem_mut().mouse_up(button)
|
self.as_elem_mut().mouse_up(e, button)
|
||||||
}
|
}
|
||||||
fn mouse_pressed(&mut self, button: MouseButton) -> Vec<GuiAction> {
|
fn mouse_pressed(&mut self, e: &mut EventInfo, button: MouseButton) -> Vec<GuiAction> {
|
||||||
self.as_elem_mut().mouse_pressed(button)
|
self.as_elem_mut().mouse_pressed(e, button)
|
||||||
}
|
}
|
||||||
fn mouse_wheel(&mut self, diff: f32) -> Vec<GuiAction> {
|
fn mouse_wheel(&mut self, e: &mut EventInfo, diff: f32) -> Vec<GuiAction> {
|
||||||
self.as_elem_mut().mouse_wheel(diff)
|
self.as_elem_mut().mouse_wheel(e, diff)
|
||||||
}
|
}
|
||||||
fn char_watch(&mut self, modifiers: ModifiersState, key: char) -> Vec<GuiAction> {
|
fn char_watch(
|
||||||
self.as_elem_mut().char_watch(modifiers, key)
|
&mut self,
|
||||||
|
e: &mut EventInfo,
|
||||||
|
modifiers: ModifiersState,
|
||||||
|
key: char,
|
||||||
|
) -> Vec<GuiAction> {
|
||||||
|
self.as_elem_mut().char_watch(e, modifiers, key)
|
||||||
}
|
}
|
||||||
fn char_focus(&mut self, modifiers: ModifiersState, key: char) -> Vec<GuiAction> {
|
fn char_focus(
|
||||||
self.as_elem_mut().char_focus(modifiers, key)
|
&mut self,
|
||||||
|
e: &mut EventInfo,
|
||||||
|
modifiers: ModifiersState,
|
||||||
|
key: char,
|
||||||
|
) -> Vec<GuiAction> {
|
||||||
|
self.as_elem_mut().char_focus(e, modifiers, key)
|
||||||
}
|
}
|
||||||
fn key_watch(
|
fn key_watch(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
e: &mut EventInfo,
|
||||||
modifiers: ModifiersState,
|
modifiers: ModifiersState,
|
||||||
down: bool,
|
down: bool,
|
||||||
key: Option<VirtualKeyCode>,
|
key: Option<VirtualKeyCode>,
|
||||||
scan: KeyScancode,
|
scan: KeyScancode,
|
||||||
) -> Vec<GuiAction> {
|
) -> Vec<GuiAction> {
|
||||||
self.as_elem_mut().key_watch(modifiers, down, key, scan)
|
self.as_elem_mut().key_watch(e, modifiers, down, key, scan)
|
||||||
}
|
}
|
||||||
fn key_focus(
|
fn key_focus(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
e: &mut EventInfo,
|
||||||
modifiers: ModifiersState,
|
modifiers: ModifiersState,
|
||||||
down: bool,
|
down: bool,
|
||||||
key: Option<VirtualKeyCode>,
|
key: Option<VirtualKeyCode>,
|
||||||
scan: KeyScancode,
|
scan: KeyScancode,
|
||||||
) -> Vec<GuiAction> {
|
) -> Vec<GuiAction> {
|
||||||
self.as_elem_mut().key_focus(modifiers, down, key, scan)
|
self.as_elem_mut().key_focus(e, modifiers, down, key, scan)
|
||||||
}
|
}
|
||||||
fn dragged(&mut self, dragged: Dragging) -> Vec<GuiAction> {
|
fn dragged(&mut self, e: &mut EventInfo, dragged: Dragging) -> Vec<GuiAction> {
|
||||||
self.as_elem_mut().dragged(dragged)
|
self.as_elem_mut().dragged(e, dragged)
|
||||||
}
|
}
|
||||||
fn updated_library(&mut self) {
|
fn updated_library(&mut self) {
|
||||||
self.as_elem_mut().updated_library()
|
self.as_elem_mut().updated_library()
|
||||||
@ -1106,9 +1176,13 @@ impl Default for GuiElemCfg {
|
|||||||
pub enum GuiAction {
|
pub enum GuiAction {
|
||||||
OpenMain,
|
OpenMain,
|
||||||
/// Add a key action (and optionally bind it) and then call the given function
|
/// Add a key action (and optionally bind it) and then call the given function
|
||||||
AddKeybind(Option<KeyBinding>, KeyAction, Box<dyn FnOnce(KeyActionId)>),
|
AddKeybind(
|
||||||
|
Option<(KeyBinding, bool)>,
|
||||||
|
KeyAction,
|
||||||
|
Box<dyn FnOnce(KeyActionId)>,
|
||||||
|
),
|
||||||
/// Binds the action to the keybinding, or unbinds it entirely
|
/// Binds the action to the keybinding, or unbinds it entirely
|
||||||
SetKeybind(KeyActionId, Option<KeyBinding>),
|
SetKeybind(KeyActionId, Option<(KeyBinding, bool)>),
|
||||||
ForceIdle,
|
ForceIdle,
|
||||||
/// false -> prevent idling, true -> end idling even if already idle
|
/// false -> prevent idling, true -> end idling even if already idle
|
||||||
EndIdle(bool),
|
EndIdle(bool),
|
||||||
@ -1205,8 +1279,8 @@ impl Gui {
|
|||||||
}
|
}
|
||||||
GuiAction::AddKeybind(bind, action, func) => {
|
GuiAction::AddKeybind(bind, action, func) => {
|
||||||
let id = self.key_actions.add(action);
|
let id = self.key_actions.add(action);
|
||||||
if let Some(bind) = bind {
|
if let Some((bind, priority)) = bind {
|
||||||
self.keybinds.insert(bind, id);
|
self.keybinds.insert(bind, id.with_priority(priority));
|
||||||
}
|
}
|
||||||
func(id);
|
func(id);
|
||||||
}
|
}
|
||||||
@ -1226,8 +1300,8 @@ impl Gui {
|
|||||||
{
|
{
|
||||||
self.keybinds.remove(&b);
|
self.keybinds.remove(&b);
|
||||||
}
|
}
|
||||||
if let Some(bind) = bind {
|
if let Some((bind, priority)) = bind {
|
||||||
self.keybinds.insert(bind, action);
|
self.keybinds.insert(bind, action.with_priority(priority));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
GuiAction::SendToServer(cmd) => {
|
GuiAction::SendToServer(cmd) => {
|
||||||
@ -1283,7 +1357,7 @@ impl Gui {
|
|||||||
GuiAction::SetLineHeight(h) => {
|
GuiAction::SetLineHeight(h) => {
|
||||||
self.line_height = h;
|
self.line_height = h;
|
||||||
self.gui
|
self.gui
|
||||||
._recursive_all(&mut |e| e.config_mut().redraw = true);
|
._recursive_all(true, &mut |e| e.config_mut().redraw = true);
|
||||||
}
|
}
|
||||||
GuiAction::LoadCover(id) => {
|
GuiAction::LoadCover(id) => {
|
||||||
self.covers
|
self.covers
|
||||||
@ -1447,7 +1521,10 @@ impl WindowHandler<GuiEvent> for Gui {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn on_mouse_button_down(&mut self, helper: &mut WindowHelper<GuiEvent>, button: MouseButton) {
|
fn on_mouse_button_down(&mut self, helper: &mut WindowHelper<GuiEvent>, button: MouseButton) {
|
||||||
if let Some(a) = self.gui._mouse_button(button, true, self.mouse_pos.clone()) {
|
if let Some(a) =
|
||||||
|
self.gui
|
||||||
|
._mouse_button(&mut EventInfo::new(), button, true, self.mouse_pos.clone())
|
||||||
|
{
|
||||||
for a in a {
|
for a in a {
|
||||||
self.exec_gui_action(a)
|
self.exec_gui_action(a)
|
||||||
}
|
}
|
||||||
@ -1458,7 +1535,10 @@ impl WindowHandler<GuiEvent> for Gui {
|
|||||||
if self.dragging.is_some() {
|
if self.dragging.is_some() {
|
||||||
let (dr, _) = self.dragging.take().unwrap();
|
let (dr, _) = self.dragging.take().unwrap();
|
||||||
let mut opt = Some(dr);
|
let mut opt = Some(dr);
|
||||||
if let Some(a) = self.gui._release_drag(&mut opt, self.mouse_pos.clone()) {
|
if let Some(a) =
|
||||||
|
self.gui
|
||||||
|
._release_drag(&mut EventInfo::new(), &mut opt, self.mouse_pos.clone())
|
||||||
|
{
|
||||||
for a in a {
|
for a in a {
|
||||||
self.exec_gui_action(a)
|
self.exec_gui_action(a)
|
||||||
}
|
}
|
||||||
@ -1476,9 +1556,9 @@ impl WindowHandler<GuiEvent> for Gui {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let Some(a) = self
|
if let Some(a) =
|
||||||
.gui
|
self.gui
|
||||||
._mouse_button(button, false, self.mouse_pos.clone())
|
._mouse_button(&mut EventInfo::new(), button, false, self.mouse_pos.clone())
|
||||||
{
|
{
|
||||||
for a in a {
|
for a in a {
|
||||||
self.exec_gui_action(a)
|
self.exec_gui_action(a)
|
||||||
@ -1506,7 +1586,10 @@ impl WindowHandler<GuiEvent> for Gui {
|
|||||||
* self.last_height
|
* self.last_height
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
if let Some(a) = self.gui._mouse_wheel(dist, self.mouse_pos.clone()) {
|
if let Some(a) = self
|
||||||
|
.gui
|
||||||
|
._mouse_wheel(&mut EventInfo::new(), dist, self.mouse_pos.clone())
|
||||||
|
{
|
||||||
for a in a {
|
for a in a {
|
||||||
self.exec_gui_action(a)
|
self.exec_gui_action(a)
|
||||||
}
|
}
|
||||||
@ -1516,14 +1599,16 @@ impl WindowHandler<GuiEvent> for Gui {
|
|||||||
fn on_keyboard_char(&mut self, helper: &mut WindowHelper<GuiEvent>, unicode_codepoint: char) {
|
fn on_keyboard_char(&mut self, helper: &mut WindowHelper<GuiEvent>, unicode_codepoint: char) {
|
||||||
helper.request_redraw();
|
helper.request_redraw();
|
||||||
for a in self.gui._keyboard_event(
|
for a in self.gui._keyboard_event(
|
||||||
&mut |e, a| {
|
&mut EventInfo::new(),
|
||||||
if e.config().keyboard_events_focus {
|
false,
|
||||||
a.append(&mut e.char_focus(self.modifiers.clone(), unicode_codepoint));
|
&mut |g, e, a| {
|
||||||
|
if g.config().keyboard_events_focus {
|
||||||
|
a.append(&mut g.char_focus(e, self.modifiers.clone(), unicode_codepoint));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
&mut |e, a| {
|
&mut |g, e, a| {
|
||||||
if e.config().keyboard_events_watch {
|
if g.config().keyboard_events_watch {
|
||||||
a.append(&mut e.char_watch(self.modifiers.clone(), unicode_codepoint));
|
a.append(&mut g.char_watch(e, self.modifiers.clone(), unicode_codepoint));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
) {
|
) {
|
||||||
@ -1543,9 +1628,12 @@ impl WindowHandler<GuiEvent> for Gui {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
for a in self.gui._keyboard_event(
|
for a in self.gui._keyboard_event(
|
||||||
&mut |e, a| {
|
&mut EventInfo::new(),
|
||||||
if e.config().keyboard_events_focus {
|
false,
|
||||||
a.append(&mut e.key_focus(
|
&mut |g, e, a| {
|
||||||
|
if g.config().keyboard_events_focus {
|
||||||
|
a.append(&mut g.key_focus(
|
||||||
|
e,
|
||||||
self.modifiers.clone(),
|
self.modifiers.clone(),
|
||||||
true,
|
true,
|
||||||
virtual_key_code,
|
virtual_key_code,
|
||||||
@ -1553,9 +1641,10 @@ impl WindowHandler<GuiEvent> for Gui {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
&mut |e, a| {
|
&mut |g, e, a| {
|
||||||
if e.config().keyboard_events_watch {
|
if g.config().keyboard_events_watch {
|
||||||
a.append(&mut e.key_watch(
|
a.append(&mut g.key_watch(
|
||||||
|
e,
|
||||||
self.modifiers.clone(),
|
self.modifiers.clone(),
|
||||||
true,
|
true,
|
||||||
virtual_key_code,
|
virtual_key_code,
|
||||||
@ -1575,21 +1664,30 @@ impl WindowHandler<GuiEvent> for Gui {
|
|||||||
) {
|
) {
|
||||||
helper.request_redraw();
|
helper.request_redraw();
|
||||||
// handle keybinds unless settings are open, opening or closing
|
// handle keybinds unless settings are open, opening or closing
|
||||||
|
let mut e = EventInfo::new();
|
||||||
|
let mut post_action = None;
|
||||||
if self.gui.settings.0 == false && self.gui.settings.1.is_none() {
|
if self.gui.settings.0 == false && self.gui.settings.1.is_none() {
|
||||||
if let Some(key) = virtual_key_code {
|
if let Some(key) = virtual_key_code {
|
||||||
let keybind = KeyBinding::new(&self.modifiers, key);
|
let keybind = KeyBinding::new(&self.modifiers, key);
|
||||||
if let Some(action) = self.keybinds.get(&keybind) {
|
if let Some(action) = self.keybinds.get(&keybind) {
|
||||||
for a in self.key_actions.get(action).execute() {
|
if action.has_priority() {
|
||||||
self.exec_gui_action(a);
|
e.take();
|
||||||
|
for a in self.key_actions.get(&action.id()).execute() {
|
||||||
|
self.exec_gui_action(a);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
post_action = Some(action.id());
|
||||||
}
|
}
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for a in self.gui._keyboard_event(
|
for a in self.gui._keyboard_event(
|
||||||
&mut |e, a| {
|
&mut EventInfo::new(),
|
||||||
if e.config().keyboard_events_focus {
|
true,
|
||||||
a.append(&mut e.key_focus(
|
&mut |g, e, a| {
|
||||||
|
if g.config().keyboard_events_focus {
|
||||||
|
a.append(&mut g.key_focus(
|
||||||
|
e,
|
||||||
self.modifiers.clone(),
|
self.modifiers.clone(),
|
||||||
false,
|
false,
|
||||||
virtual_key_code,
|
virtual_key_code,
|
||||||
@ -1597,9 +1695,10 @@ impl WindowHandler<GuiEvent> for Gui {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
&mut |e, a| {
|
&mut |g, e, a| {
|
||||||
if e.config().keyboard_events_watch {
|
if g.config().keyboard_events_watch {
|
||||||
a.append(&mut e.key_watch(
|
a.append(&mut g.key_watch(
|
||||||
|
e,
|
||||||
self.modifiers.clone(),
|
self.modifiers.clone(),
|
||||||
false,
|
false,
|
||||||
virtual_key_code,
|
virtual_key_code,
|
||||||
@ -1610,6 +1709,13 @@ impl WindowHandler<GuiEvent> for Gui {
|
|||||||
) {
|
) {
|
||||||
self.exec_gui_action(a);
|
self.exec_gui_action(a);
|
||||||
}
|
}
|
||||||
|
if let Some(post_action) = post_action.take() {
|
||||||
|
if e.take() {
|
||||||
|
for a in self.key_actions.get(&post_action).execute() {
|
||||||
|
self.exec_gui_action(a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
fn on_keyboard_modifiers_changed(
|
fn on_keyboard_modifiers_changed(
|
||||||
&mut self,
|
&mut self,
|
||||||
@ -1636,7 +1742,7 @@ impl WindowHandler<GuiEvent> for Gui {
|
|||||||
} else {
|
} else {
|
||||||
eprintln!("WARN: Skipping call to merscfg's library_updated because gui_config is not available");
|
eprintln!("WARN: Skipping call to merscfg's library_updated because gui_config is not available");
|
||||||
}
|
}
|
||||||
self.gui._recursive_all(&mut |e| e.updated_library());
|
self.gui._recursive_all(true, &mut |e| e.updated_library());
|
||||||
helper.request_redraw();
|
helper.request_redraw();
|
||||||
}
|
}
|
||||||
GuiEvent::UpdatedQueue => {
|
GuiEvent::UpdatedQueue => {
|
||||||
@ -1647,7 +1753,7 @@ impl WindowHandler<GuiEvent> for Gui {
|
|||||||
} else {
|
} else {
|
||||||
eprintln!("WARN: Skipping call to merscfg's queue_updated because gui_config is not available");
|
eprintln!("WARN: Skipping call to merscfg's queue_updated because gui_config is not available");
|
||||||
}
|
}
|
||||||
self.gui._recursive_all(&mut |e| e.updated_queue());
|
self.gui._recursive_all(true, &mut |e| e.updated_queue());
|
||||||
helper.request_redraw();
|
helper.request_redraw();
|
||||||
}
|
}
|
||||||
GuiEvent::Exit => helper.terminate_loop(),
|
GuiEvent::Exit => helper.terminate_loop(),
|
||||||
@ -1660,7 +1766,7 @@ impl WindowHandler<GuiEvent> for Gui {
|
|||||||
fn on_resize(&mut self, _helper: &mut WindowHelper<GuiEvent>, size_pixels: UVec2) {
|
fn on_resize(&mut self, _helper: &mut WindowHelper<GuiEvent>, size_pixels: UVec2) {
|
||||||
self.size = size_pixels;
|
self.size = size_pixels;
|
||||||
self.gui
|
self.gui
|
||||||
._recursive_all(&mut |e| e.config_mut().redraw = true);
|
._recursive_all(true, &mut |e| e.config_mut().redraw = true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1807,10 +1913,29 @@ impl KeyAction {
|
|||||||
pub struct KeyActions(Vec<KeyAction>);
|
pub struct KeyActions(Vec<KeyAction>);
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
pub struct KeyActionId(usize);
|
pub struct KeyActionId(usize);
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
|
pub struct KeyActionRef(usize, bool);
|
||||||
impl KeyActionId {
|
impl KeyActionId {
|
||||||
pub fn get_index(&self) -> usize {
|
pub fn get_index(&self) -> usize {
|
||||||
self.0
|
self.0
|
||||||
}
|
}
|
||||||
|
pub fn with_priority(&self, priority: bool) -> KeyActionRef {
|
||||||
|
KeyActionRef(self.0, priority)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl KeyActionRef {
|
||||||
|
pub fn get_index(&self) -> usize {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
|
pub fn id(&self) -> KeyActionId {
|
||||||
|
KeyActionId(self.0)
|
||||||
|
}
|
||||||
|
pub fn has_priority(&self) -> bool {
|
||||||
|
self.1
|
||||||
|
}
|
||||||
|
pub fn set_priority(&mut self, priority: bool) {
|
||||||
|
self.1 = priority;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
impl KeyActions {
|
impl KeyActions {
|
||||||
pub fn add(&mut self, action: KeyAction) -> KeyActionId {
|
pub fn add(&mut self, action: KeyAction) -> KeyActionId {
|
||||||
|
@ -3,7 +3,7 @@ use std::{sync::Arc, time::Instant};
|
|||||||
use speedy2d::{color::Color, dimen::Vec2, shape::Rectangle, window::MouseButton};
|
use speedy2d::{color::Color, dimen::Vec2, shape::Rectangle, window::MouseButton};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
gui::{DrawInfo, GuiAction, GuiElem, GuiElemCfg, GuiElemChildren},
|
gui::{DrawInfo, EventInfo, GuiAction, GuiElem, GuiElemCfg, GuiElemChildren},
|
||||||
gui_text::Label,
|
gui_text::Label,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -291,20 +291,26 @@ impl<C: GuiElemChildren + 'static> GuiElem for ScrollBox<C> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn mouse_wheel(&mut self, diff: f32) -> Vec<crate::gui::GuiAction> {
|
fn mouse_wheel(&mut self, e: &mut EventInfo, diff: f32) -> Vec<crate::gui::GuiAction> {
|
||||||
self.scroll_target = (self.scroll_target
|
let nst = (self.scroll_target - self.size_unit.from_abs(diff as f32, self.last_height_px))
|
||||||
- self.size_unit.from_abs(diff as f32, self.last_height_px))
|
.max(0.0);
|
||||||
.max(0.0);
|
// only take the event if this would actually scroll, and only scroll if we can actually take the event
|
||||||
|
if nst != self.scroll_target && e.take() {
|
||||||
|
self.scroll_target = nst;
|
||||||
|
}
|
||||||
Vec::with_capacity(0)
|
Vec::with_capacity(0)
|
||||||
}
|
}
|
||||||
fn mouse_down(&mut self, button: MouseButton) -> Vec<GuiAction> {
|
fn mouse_down(&mut self, e: &mut EventInfo, button: MouseButton) -> Vec<GuiAction> {
|
||||||
if button == MouseButton::Left && self.mouse_in_scrollbar {
|
if button == MouseButton::Left && self.mouse_in_scrollbar && e.take() {
|
||||||
self.mouse_scrolling = true;
|
self.mouse_scrolling = true;
|
||||||
}
|
}
|
||||||
vec![]
|
vec![]
|
||||||
}
|
}
|
||||||
fn mouse_up(&mut self, button: MouseButton) -> Vec<GuiAction> {
|
fn mouse_up(&mut self, e: &mut EventInfo, button: MouseButton) -> Vec<GuiAction> {
|
||||||
if button == MouseButton::Left {
|
if button == MouseButton::Left {
|
||||||
|
if self.mouse_scrolling {
|
||||||
|
e.take();
|
||||||
|
}
|
||||||
self.mouse_scrolling = false;
|
self.mouse_scrolling = false;
|
||||||
}
|
}
|
||||||
vec![]
|
vec![]
|
||||||
@ -372,8 +378,8 @@ impl<C: GuiElemChildren + 'static> GuiElem for Button<C> {
|
|||||||
fn elem_mut(&mut self) -> &mut dyn GuiElem {
|
fn elem_mut(&mut self) -> &mut dyn GuiElem {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
fn mouse_pressed(&mut self, button: MouseButton) -> Vec<GuiAction> {
|
fn mouse_pressed(&mut self, e: &mut EventInfo, button: MouseButton) -> Vec<GuiAction> {
|
||||||
if button == MouseButton::Left {
|
if button == MouseButton::Left && e.take() {
|
||||||
(self.action.clone())(self)
|
(self.action.clone())(self)
|
||||||
} else {
|
} else {
|
||||||
vec![]
|
vec![]
|
||||||
@ -381,6 +387,7 @@ impl<C: GuiElemChildren + 'static> GuiElem for Button<C> {
|
|||||||
}
|
}
|
||||||
fn key_focus(
|
fn key_focus(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
e: &mut EventInfo,
|
||||||
_modifiers: speedy2d::window::ModifiersState,
|
_modifiers: speedy2d::window::ModifiersState,
|
||||||
down: bool,
|
down: bool,
|
||||||
key: Option<speedy2d::window::VirtualKeyCode>,
|
key: Option<speedy2d::window::VirtualKeyCode>,
|
||||||
@ -394,6 +401,7 @@ impl<C: GuiElemChildren + 'static> GuiElem for Button<C> {
|
|||||||
| speedy2d::window::VirtualKeyCode::NumpadEnter,
|
| speedy2d::window::VirtualKeyCode::NumpadEnter,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
&& e.take()
|
||||||
{
|
{
|
||||||
(self.action.clone())(self)
|
(self.action.clone())(self)
|
||||||
} else {
|
} else {
|
||||||
|
@ -27,7 +27,7 @@ use speedy2d::{
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
gui::{
|
gui::{
|
||||||
Dragging, DrawInfo, GuiAction, GuiConfig, GuiElem, GuiElemCfg, GuiElemChildren,
|
Dragging, DrawInfo, EventInfo, GuiAction, GuiConfig, GuiElem, GuiElemCfg, GuiElemChildren,
|
||||||
GuiElemWrapper,
|
GuiElemWrapper,
|
||||||
},
|
},
|
||||||
gui_anim::AnimationController,
|
gui_anim::AnimationController,
|
||||||
@ -598,21 +598,22 @@ impl GuiElem for LibraryBrowser {
|
|||||||
}
|
}
|
||||||
fn key_watch(
|
fn key_watch(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
e: &mut EventInfo,
|
||||||
modifiers: speedy2d::window::ModifiersState,
|
modifiers: speedy2d::window::ModifiersState,
|
||||||
down: bool,
|
down: bool,
|
||||||
key: Option<VirtualKeyCode>,
|
key: Option<VirtualKeyCode>,
|
||||||
_scan: speedy2d::window::KeyScancode,
|
_scan: speedy2d::window::KeyScancode,
|
||||||
) -> Vec<GuiAction> {
|
) -> Vec<GuiAction> {
|
||||||
if down && crate::gui::hotkey_deselect_all(&modifiers, key) {
|
if down && crate::gui::hotkey_deselect_all(&modifiers, key) && e.take() {
|
||||||
self.selected.clear();
|
self.selected.clear();
|
||||||
}
|
}
|
||||||
if down && crate::gui::hotkey_select_all(&modifiers, key) {
|
if down && crate::gui::hotkey_select_all(&modifiers, key) && e.take() {
|
||||||
self.selected_add_all();
|
self.selected_add_all();
|
||||||
}
|
}
|
||||||
if down && crate::gui::hotkey_select_albums(&modifiers, key) {
|
if down && crate::gui::hotkey_select_albums(&modifiers, key) && e.take() {
|
||||||
self.selected_add_albums();
|
self.selected_add_albums();
|
||||||
}
|
}
|
||||||
if down && crate::gui::hotkey_select_songs(&modifiers, key) {
|
if down && crate::gui::hotkey_select_songs(&modifiers, key) && e.take() {
|
||||||
self.selected_add_songs();
|
self.selected_add_songs();
|
||||||
}
|
}
|
||||||
vec![]
|
vec![]
|
||||||
@ -953,8 +954,8 @@ impl GuiElem for ListArtist {
|
|||||||
info.mouse_pos.y - info.pos.top_left().y,
|
info.mouse_pos.y - info.pos.top_left().y,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
fn mouse_down(&mut self, button: MouseButton) -> Vec<GuiAction> {
|
fn mouse_down(&mut self, e: &mut EventInfo, button: MouseButton) -> Vec<GuiAction> {
|
||||||
if button == MouseButton::Left {
|
if button == MouseButton::Left && e.take() {
|
||||||
self.mouse = true;
|
self.mouse = true;
|
||||||
if self.sel {
|
if self.sel {
|
||||||
vec![]
|
vec![]
|
||||||
@ -968,14 +969,16 @@ impl GuiElem for ListArtist {
|
|||||||
vec![]
|
vec![]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn mouse_up(&mut self, button: MouseButton) -> Vec<GuiAction> {
|
fn mouse_up(&mut self, e: &mut EventInfo, button: MouseButton) -> Vec<GuiAction> {
|
||||||
if self.mouse && button == MouseButton::Left {
|
if self.mouse && button == MouseButton::Left {
|
||||||
self.mouse = false;
|
self.mouse = false;
|
||||||
self.config.redraw = true;
|
self.config.redraw = true;
|
||||||
if !self.sel {
|
if e.take() {
|
||||||
self.selected.insert_artist(self.id);
|
if !self.sel {
|
||||||
} else {
|
self.selected.insert_artist(self.id);
|
||||||
self.selected.remove_artist(&self.id);
|
} else {
|
||||||
|
self.selected.remove_artist(&self.id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
vec![]
|
vec![]
|
||||||
@ -1097,8 +1100,8 @@ impl GuiElem for ListAlbum {
|
|||||||
info.mouse_pos.y - info.pos.top_left().y,
|
info.mouse_pos.y - info.pos.top_left().y,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
fn mouse_down(&mut self, button: MouseButton) -> Vec<GuiAction> {
|
fn mouse_down(&mut self, e: &mut EventInfo, button: MouseButton) -> Vec<GuiAction> {
|
||||||
if button == MouseButton::Left {
|
if button == MouseButton::Left && e.take() {
|
||||||
self.mouse = true;
|
self.mouse = true;
|
||||||
if self.sel {
|
if self.sel {
|
||||||
vec![]
|
vec![]
|
||||||
@ -1112,14 +1115,16 @@ impl GuiElem for ListAlbum {
|
|||||||
vec![]
|
vec![]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn mouse_up(&mut self, button: MouseButton) -> Vec<GuiAction> {
|
fn mouse_up(&mut self, e: &mut EventInfo, button: MouseButton) -> Vec<GuiAction> {
|
||||||
if self.mouse && button == MouseButton::Left {
|
if self.mouse && button == MouseButton::Left {
|
||||||
self.mouse = false;
|
self.mouse = false;
|
||||||
self.config.redraw = true;
|
self.config.redraw = true;
|
||||||
if !self.sel {
|
if e.take() {
|
||||||
self.selected.insert_album(self.id);
|
if !self.sel {
|
||||||
} else {
|
self.selected.insert_album(self.id);
|
||||||
self.selected.remove_album(&self.id);
|
} else {
|
||||||
|
self.selected.remove_album(&self.id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
vec![]
|
vec![]
|
||||||
@ -1238,8 +1243,8 @@ impl GuiElem for ListSong {
|
|||||||
info.mouse_pos.y - info.pos.top_left().y,
|
info.mouse_pos.y - info.pos.top_left().y,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
fn mouse_down(&mut self, button: MouseButton) -> Vec<GuiAction> {
|
fn mouse_down(&mut self, e: &mut EventInfo, button: MouseButton) -> Vec<GuiAction> {
|
||||||
if button == MouseButton::Left {
|
if button == MouseButton::Left && e.take() {
|
||||||
self.mouse = true;
|
self.mouse = true;
|
||||||
if self.sel {
|
if self.sel {
|
||||||
vec![]
|
vec![]
|
||||||
@ -1253,20 +1258,22 @@ impl GuiElem for ListSong {
|
|||||||
vec![]
|
vec![]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn mouse_up(&mut self, button: MouseButton) -> Vec<GuiAction> {
|
fn mouse_up(&mut self, e: &mut EventInfo, button: MouseButton) -> Vec<GuiAction> {
|
||||||
if self.mouse && button == MouseButton::Left {
|
if self.mouse && button == MouseButton::Left {
|
||||||
self.mouse = false;
|
self.mouse = false;
|
||||||
self.config.redraw = true;
|
self.config.redraw = true;
|
||||||
if !self.sel {
|
if e.take() {
|
||||||
self.selected.insert_song(self.id);
|
if !self.sel {
|
||||||
} else {
|
self.selected.insert_song(self.id);
|
||||||
self.selected.remove_song(&self.id);
|
} else {
|
||||||
|
self.selected.remove_song(&self.id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
vec![]
|
vec![]
|
||||||
}
|
}
|
||||||
fn mouse_pressed(&mut self, button: MouseButton) -> Vec<GuiAction> {
|
fn mouse_pressed(&mut self, e: &mut EventInfo, button: MouseButton) -> Vec<GuiAction> {
|
||||||
if button == MouseButton::Right {
|
if button == MouseButton::Right && e.take() {
|
||||||
let id = self.id;
|
let id = self.id;
|
||||||
vec![GuiAction::Build(Box::new(move |db| {
|
vec![GuiAction::Build(Box::new(move |db| {
|
||||||
if let Some(me) = db.songs().get(&id) {
|
if let Some(me) = db.songs().get(&id) {
|
||||||
|
@ -15,7 +15,7 @@ use speedy2d::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
gui::{Dragging, DrawInfo, GuiAction, GuiElem, GuiElemCfg},
|
gui::{Dragging, DrawInfo, EventInfo, GuiAction, GuiElem, GuiElemCfg},
|
||||||
gui_base::{Panel, ScrollBox},
|
gui_base::{Panel, ScrollBox},
|
||||||
gui_text::{self, AdvancedLabel, Label, TextField},
|
gui_text::{self, AdvancedLabel, Label, TextField},
|
||||||
};
|
};
|
||||||
@ -399,7 +399,8 @@ impl GuiElem for QueueEmptySpaceDragHandler {
|
|||||||
fn elem_mut(&mut self) -> &mut dyn GuiElem {
|
fn elem_mut(&mut self) -> &mut dyn GuiElem {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
fn dragged(&mut self, dragged: Dragging) -> Vec<GuiAction> {
|
fn dragged(&mut self, e: &mut EventInfo, dragged: Dragging) -> Vec<GuiAction> {
|
||||||
|
e.take();
|
||||||
dragged_add_to_queue(
|
dragged_add_to_queue(
|
||||||
dragged,
|
dragged,
|
||||||
(),
|
(),
|
||||||
@ -551,17 +552,17 @@ impl GuiElem for QueueSong {
|
|||||||
fn elem_mut(&mut self) -> &mut dyn GuiElem {
|
fn elem_mut(&mut self) -> &mut dyn GuiElem {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
fn mouse_down(&mut self, button: MouseButton) -> Vec<GuiAction> {
|
fn mouse_down(&mut self, e: &mut EventInfo, button: MouseButton) -> Vec<GuiAction> {
|
||||||
if button == MouseButton::Left {
|
if button == MouseButton::Left && e.take() {
|
||||||
self.mouse = true;
|
self.mouse = true;
|
||||||
self.copy_on_mouse_down = self.copy;
|
self.copy_on_mouse_down = self.copy;
|
||||||
}
|
}
|
||||||
vec![]
|
vec![]
|
||||||
}
|
}
|
||||||
fn mouse_up(&mut self, button: MouseButton) -> Vec<GuiAction> {
|
fn mouse_up(&mut self, e: &mut EventInfo, button: MouseButton) -> Vec<GuiAction> {
|
||||||
if self.mouse && button == MouseButton::Left {
|
if self.mouse && button == MouseButton::Left {
|
||||||
self.mouse = false;
|
self.mouse = false;
|
||||||
if !self.always_copy {
|
if e.take() && !self.always_copy {
|
||||||
vec![GuiAction::SendToServer(Command::QueueGoto(
|
vec![GuiAction::SendToServer(Command::QueueGoto(
|
||||||
self.path.clone(),
|
self.path.clone(),
|
||||||
))]
|
))]
|
||||||
@ -612,6 +613,7 @@ impl GuiElem for QueueSong {
|
|||||||
}
|
}
|
||||||
fn key_watch(
|
fn key_watch(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
_e: &mut EventInfo,
|
||||||
modifiers: ModifiersState,
|
modifiers: ModifiersState,
|
||||||
_down: bool,
|
_down: bool,
|
||||||
_key: Option<VirtualKeyCode>,
|
_key: Option<VirtualKeyCode>,
|
||||||
@ -620,8 +622,9 @@ impl GuiElem for QueueSong {
|
|||||||
self.copy = self.always_copy || modifiers.ctrl();
|
self.copy = self.always_copy || modifiers.ctrl();
|
||||||
vec![]
|
vec![]
|
||||||
}
|
}
|
||||||
fn dragged(&mut self, dragged: Dragging) -> Vec<GuiAction> {
|
fn dragged(&mut self, e: &mut EventInfo, dragged: Dragging) -> Vec<GuiAction> {
|
||||||
if !self.always_copy {
|
if !self.always_copy {
|
||||||
|
e.take();
|
||||||
let insert_below = self.insert_below;
|
let insert_below = self.insert_below;
|
||||||
dragged_add_to_queue(
|
dragged_add_to_queue(
|
||||||
dragged,
|
dragged,
|
||||||
@ -775,11 +778,11 @@ impl GuiElem for QueueFolder {
|
|||||||
self.copy_on_mouse_down,
|
self.copy_on_mouse_down,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
fn mouse_down(&mut self, button: MouseButton) -> Vec<GuiAction> {
|
fn mouse_down(&mut self, e: &mut EventInfo, button: MouseButton) -> Vec<GuiAction> {
|
||||||
if button == MouseButton::Left {
|
if button == MouseButton::Left && e.take() {
|
||||||
self.mouse = true;
|
self.mouse = true;
|
||||||
self.copy_on_mouse_down = self.copy;
|
self.copy_on_mouse_down = self.copy;
|
||||||
} else if button == MouseButton::Right {
|
} else if button == MouseButton::Right && e.take() {
|
||||||
// return vec![GuiAction::ContextMenu(Some(vec![Box::new(
|
// return vec![GuiAction::ContextMenu(Some(vec![Box::new(
|
||||||
// Panel::with_background(GuiElemCfg::default(), (), Color::DARK_GRAY),
|
// Panel::with_background(GuiElemCfg::default(), (), Color::DARK_GRAY),
|
||||||
// )]))];
|
// )]))];
|
||||||
@ -791,10 +794,10 @@ impl GuiElem for QueueFolder {
|
|||||||
}
|
}
|
||||||
vec![]
|
vec![]
|
||||||
}
|
}
|
||||||
fn mouse_up(&mut self, button: MouseButton) -> Vec<GuiAction> {
|
fn mouse_up(&mut self, e: &mut EventInfo, button: MouseButton) -> Vec<GuiAction> {
|
||||||
if self.mouse && button == MouseButton::Left {
|
if self.mouse && button == MouseButton::Left {
|
||||||
self.mouse = false;
|
self.mouse = false;
|
||||||
if !self.always_copy {
|
if e.take() && !self.always_copy {
|
||||||
vec![GuiAction::SendToServer(Command::QueueGoto(
|
vec![GuiAction::SendToServer(Command::QueueGoto(
|
||||||
self.path.clone(),
|
self.path.clone(),
|
||||||
))]
|
))]
|
||||||
@ -807,6 +810,7 @@ impl GuiElem for QueueFolder {
|
|||||||
}
|
}
|
||||||
fn key_watch(
|
fn key_watch(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
_e: &mut EventInfo,
|
||||||
modifiers: ModifiersState,
|
modifiers: ModifiersState,
|
||||||
_down: bool,
|
_down: bool,
|
||||||
_key: Option<VirtualKeyCode>,
|
_key: Option<VirtualKeyCode>,
|
||||||
@ -815,8 +819,9 @@ impl GuiElem for QueueFolder {
|
|||||||
self.copy = modifiers.ctrl();
|
self.copy = modifiers.ctrl();
|
||||||
vec![]
|
vec![]
|
||||||
}
|
}
|
||||||
fn dragged(&mut self, dragged: Dragging) -> Vec<GuiAction> {
|
fn dragged(&mut self, e: &mut EventInfo, dragged: Dragging) -> Vec<GuiAction> {
|
||||||
if !self.always_copy {
|
if !self.always_copy {
|
||||||
|
e.take();
|
||||||
if self.insert_into {
|
if self.insert_into {
|
||||||
dragged_add_to_queue(
|
dragged_add_to_queue(
|
||||||
dragged,
|
dragged,
|
||||||
@ -893,7 +898,8 @@ impl GuiElem for QueueIndentEnd {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn dragged(&mut self, dragged: Dragging) -> Vec<GuiAction> {
|
fn dragged(&mut self, e: &mut EventInfo, dragged: Dragging) -> Vec<GuiAction> {
|
||||||
|
e.take();
|
||||||
dragged_add_to_queue(
|
dragged_add_to_queue(
|
||||||
dragged,
|
dragged,
|
||||||
self.path_insert.clone(),
|
self.path_insert.clone(),
|
||||||
@ -987,8 +993,8 @@ impl GuiElem for QueueLoop {
|
|||||||
fn elem_mut(&mut self) -> &mut dyn GuiElem {
|
fn elem_mut(&mut self) -> &mut dyn GuiElem {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
fn mouse_wheel(&mut self, diff: f32) -> Vec<GuiAction> {
|
fn mouse_wheel(&mut self, e: &mut EventInfo, diff: f32) -> Vec<GuiAction> {
|
||||||
if self.always_copy {
|
if self.always_copy && e.take() {
|
||||||
if let QueueContent::Loop(total, _, _) = self.queue.content_mut() {
|
if let QueueContent::Loop(total, _, _) = self.queue.content_mut() {
|
||||||
if diff > 0.0 {
|
if diff > 0.0 {
|
||||||
*total += 1;
|
*total += 1;
|
||||||
@ -1020,17 +1026,17 @@ impl GuiElem for QueueLoop {
|
|||||||
self.copy_on_mouse_down,
|
self.copy_on_mouse_down,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
fn mouse_down(&mut self, button: MouseButton) -> Vec<GuiAction> {
|
fn mouse_down(&mut self, e: &mut EventInfo, button: MouseButton) -> Vec<GuiAction> {
|
||||||
if button == MouseButton::Left {
|
if button == MouseButton::Left && e.take() {
|
||||||
self.mouse = true;
|
self.mouse = true;
|
||||||
self.copy_on_mouse_down = self.copy;
|
self.copy_on_mouse_down = self.copy;
|
||||||
}
|
}
|
||||||
vec![]
|
vec![]
|
||||||
}
|
}
|
||||||
fn mouse_up(&mut self, button: MouseButton) -> Vec<GuiAction> {
|
fn mouse_up(&mut self, e: &mut EventInfo, button: MouseButton) -> Vec<GuiAction> {
|
||||||
if self.mouse && button == MouseButton::Left {
|
if self.mouse && button == MouseButton::Left {
|
||||||
self.mouse = false;
|
self.mouse = false;
|
||||||
if !self.always_copy {
|
if e.take() && !self.always_copy {
|
||||||
vec![GuiAction::SendToServer(Command::QueueGoto(
|
vec![GuiAction::SendToServer(Command::QueueGoto(
|
||||||
self.path.clone(),
|
self.path.clone(),
|
||||||
))]
|
))]
|
||||||
@ -1043,6 +1049,7 @@ impl GuiElem for QueueLoop {
|
|||||||
}
|
}
|
||||||
fn key_watch(
|
fn key_watch(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
_e: &mut EventInfo,
|
||||||
modifiers: ModifiersState,
|
modifiers: ModifiersState,
|
||||||
_down: bool,
|
_down: bool,
|
||||||
_key: Option<VirtualKeyCode>,
|
_key: Option<VirtualKeyCode>,
|
||||||
@ -1051,8 +1058,9 @@ impl GuiElem for QueueLoop {
|
|||||||
self.copy = modifiers.ctrl();
|
self.copy = modifiers.ctrl();
|
||||||
vec![]
|
vec![]
|
||||||
}
|
}
|
||||||
fn dragged(&mut self, dragged: Dragging) -> Vec<GuiAction> {
|
fn dragged(&mut self, e: &mut EventInfo, dragged: Dragging) -> Vec<GuiAction> {
|
||||||
if !self.always_copy {
|
if !self.always_copy {
|
||||||
|
e.take();
|
||||||
let mut p = self.path.clone();
|
let mut p = self.path.clone();
|
||||||
p.push(0);
|
p.push(0);
|
||||||
dragged_add_to_queue(
|
dragged_add_to_queue(
|
||||||
|
@ -9,8 +9,8 @@ use uianimator::{default_animator_f64_quadratic::DefaultAnimatorF64Quadratic, An
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
gui::{
|
gui::{
|
||||||
DrawInfo, GuiAction, GuiElem, GuiElemCfg, GuiElemChildren, KeyAction, KeyBinding,
|
DrawInfo, EventInfo, GuiAction, GuiElem, GuiElemCfg, GuiElemChildren, KeyAction,
|
||||||
SpecificGuiElem,
|
KeyBinding, SpecificGuiElem,
|
||||||
},
|
},
|
||||||
gui_base::{Button, Panel},
|
gui_base::{Button, Panel},
|
||||||
gui_edit_song::EditorForSongs,
|
gui_edit_song::EditorForSongs,
|
||||||
@ -97,7 +97,7 @@ impl GuiScreen {
|
|||||||
scroll_sensitivity_pages: f64,
|
scroll_sensitivity_pages: f64,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
config: config.w_keyboard_watch().w_mouse().w_keyboard_focus(),
|
config: config.w_keyboard_watch().w_mouse(),
|
||||||
c_notif_overlay,
|
c_notif_overlay,
|
||||||
c_status_bar: StatusBar::new(GuiElemCfg::at(Rectangle::from_tuples(
|
c_status_bar: StatusBar::new(GuiElemCfg::at(Rectangle::from_tuples(
|
||||||
(0.0, 0.9),
|
(0.0, 0.9),
|
||||||
@ -277,22 +277,48 @@ impl GuiElem for GuiScreen {
|
|||||||
}
|
}
|
||||||
fn key_watch(
|
fn key_watch(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
e: &mut EventInfo,
|
||||||
modifiers: speedy2d::window::ModifiersState,
|
modifiers: speedy2d::window::ModifiersState,
|
||||||
down: bool,
|
down: bool,
|
||||||
key: Option<speedy2d::window::VirtualKeyCode>,
|
key: Option<speedy2d::window::VirtualKeyCode>,
|
||||||
_scan: speedy2d::window::KeyScancode,
|
_scan: speedy2d::window::KeyScancode,
|
||||||
) -> Vec<GuiAction> {
|
) -> Vec<GuiAction> {
|
||||||
if down {
|
if down {
|
||||||
|
// don't `e.take()` here (it might cause keys the user wanted to type to go missing + it would break the next if statement)
|
||||||
self.not_idle();
|
self.not_idle();
|
||||||
}
|
}
|
||||||
if self.hotkey.triggered(modifiers, down, key) {
|
if self.hotkey.triggered(modifiers, down, key) && e.take() {
|
||||||
self.config.request_keyboard_focus = true;
|
self.config.request_keyboard_focus = true;
|
||||||
vec![GuiAction::ResetKeyboardFocus]
|
vec![GuiAction::ResetKeyboardFocus]
|
||||||
|
// } else if down && matches!(key, Some(VirtualKeyCode::Space)) && e.take() {
|
||||||
|
// MOVED TO CHAR_WATCH !!!
|
||||||
} else {
|
} else {
|
||||||
vec![]
|
vec![]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn mouse_down(&mut self, _button: speedy2d::window::MouseButton) -> Vec<GuiAction> {
|
fn char_watch(
|
||||||
|
&mut self,
|
||||||
|
e: &mut EventInfo,
|
||||||
|
modifiers: speedy2d::window::ModifiersState,
|
||||||
|
key: char,
|
||||||
|
) -> Vec<GuiAction> {
|
||||||
|
if key == ' ' && !(modifiers.ctrl() || modifiers.alt() || modifiers.logo()) && e.take() {
|
||||||
|
vec![GuiAction::Build(Box::new(|db| {
|
||||||
|
vec![GuiAction::SendToServer(if db.playing {
|
||||||
|
Command::Pause
|
||||||
|
} else {
|
||||||
|
Command::Resume
|
||||||
|
})]
|
||||||
|
}))]
|
||||||
|
} else {
|
||||||
|
vec![]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn mouse_down(
|
||||||
|
&mut self,
|
||||||
|
_e: &mut EventInfo,
|
||||||
|
_button: speedy2d::window::MouseButton,
|
||||||
|
) -> Vec<GuiAction> {
|
||||||
self.not_idle();
|
self.not_idle();
|
||||||
vec![]
|
vec![]
|
||||||
}
|
}
|
||||||
@ -300,7 +326,7 @@ impl GuiElem for GuiScreen {
|
|||||||
if self.config.init {
|
if self.config.init {
|
||||||
info.actions.extend([
|
info.actions.extend([
|
||||||
GuiAction::AddKeybind(
|
GuiAction::AddKeybind(
|
||||||
Some(KeyBinding::ctrl(VirtualKeyCode::Q)),
|
Some((KeyBinding::ctrl(VirtualKeyCode::Q), true)),
|
||||||
KeyAction {
|
KeyAction {
|
||||||
category: "General".to_owned(),
|
category: "General".to_owned(),
|
||||||
title: "Quit".to_owned(),
|
title: "Quit".to_owned(),
|
||||||
@ -311,7 +337,7 @@ impl GuiElem for GuiScreen {
|
|||||||
Box::new(|_| {}),
|
Box::new(|_| {}),
|
||||||
),
|
),
|
||||||
GuiAction::AddKeybind(
|
GuiAction::AddKeybind(
|
||||||
Some(KeyBinding::ctrl(VirtualKeyCode::I)),
|
Some((KeyBinding::ctrl(VirtualKeyCode::I), true)),
|
||||||
KeyAction {
|
KeyAction {
|
||||||
category: "General".to_owned(),
|
category: "General".to_owned(),
|
||||||
title: "Idle".to_owned(),
|
title: "Idle".to_owned(),
|
||||||
@ -322,7 +348,7 @@ impl GuiElem for GuiScreen {
|
|||||||
Box::new(|_| {}),
|
Box::new(|_| {}),
|
||||||
),
|
),
|
||||||
GuiAction::AddKeybind(
|
GuiAction::AddKeybind(
|
||||||
Some(KeyBinding::ctrl(VirtualKeyCode::F)),
|
Some((KeyBinding::ctrl(VirtualKeyCode::F), true)),
|
||||||
KeyAction {
|
KeyAction {
|
||||||
category: "Library".to_owned(),
|
category: "Library".to_owned(),
|
||||||
title: "Search songs".to_owned(),
|
title: "Search songs".to_owned(),
|
||||||
@ -414,28 +440,4 @@ impl GuiElem for GuiScreen {
|
|||||||
self.idle_timeout = self.c_settings.get_timeout_val();
|
self.idle_timeout = self.c_settings.get_timeout_val();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn key_focus(
|
|
||||||
&mut self,
|
|
||||||
_modifiers: speedy2d::window::ModifiersState,
|
|
||||||
down: bool,
|
|
||||||
key: Option<speedy2d::window::VirtualKeyCode>,
|
|
||||||
_scan: speedy2d::window::KeyScancode,
|
|
||||||
) -> Vec<GuiAction> {
|
|
||||||
if down && matches!(key, Some(VirtualKeyCode::Space)) {
|
|
||||||
vec![GuiAction::Build(Box::new(|db| {
|
|
||||||
vec![GuiAction::SendToServer(if db.playing {
|
|
||||||
Command::Pause
|
|
||||||
} else {
|
|
||||||
Command::Resume
|
|
||||||
})]
|
|
||||||
}))]
|
|
||||||
} else if down && matches!(key, Some(VirtualKeyCode::F8)) {
|
|
||||||
vec![GuiAction::SendToServer(Command::ErrorInfo(
|
|
||||||
"".to_owned(),
|
|
||||||
"tEsT".to_owned(),
|
|
||||||
))]
|
|
||||||
} else {
|
|
||||||
vec![]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -11,8 +11,8 @@ use speedy2d::{
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
gui::{
|
gui::{
|
||||||
DrawInfo, GuiAction, GuiElem, GuiElemCfg, GuiElemChildren, KeyAction, KeyActionId,
|
DrawInfo, EventInfo, GuiAction, GuiElem, GuiElemCfg, GuiElemChildren, KeyAction,
|
||||||
KeyBinding,
|
KeyActionId, KeyBinding,
|
||||||
},
|
},
|
||||||
gui_base::{Button, Panel, ScrollBox, Slider},
|
gui_base::{Button, Panel, ScrollBox, Slider},
|
||||||
gui_text::{AdvancedContent, AdvancedLabel, Content, Label},
|
gui_text::{AdvancedContent, AdvancedLabel, Content, Label},
|
||||||
@ -139,8 +139,8 @@ impl KeybindInput {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl GuiElem for KeybindInput {
|
impl GuiElem for KeybindInput {
|
||||||
fn mouse_pressed(&mut self, button: MouseButton) -> Vec<GuiAction> {
|
fn mouse_pressed(&mut self, e: &mut EventInfo, button: MouseButton) -> Vec<GuiAction> {
|
||||||
if let MouseButton::Left = button {
|
if MouseButton::Left == button && e.take() {
|
||||||
if !self.has_keyboard_focus {
|
if !self.has_keyboard_focus {
|
||||||
self.changing = true;
|
self.changing = true;
|
||||||
self.config.request_keyboard_focus = true;
|
self.config.request_keyboard_focus = true;
|
||||||
@ -154,6 +154,7 @@ impl GuiElem for KeybindInput {
|
|||||||
}
|
}
|
||||||
fn key_focus(
|
fn key_focus(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
e: &mut EventInfo,
|
||||||
modifiers: ModifiersState,
|
modifiers: ModifiersState,
|
||||||
down: bool,
|
down: bool,
|
||||||
key: Option<VirtualKeyCode>,
|
key: Option<VirtualKeyCode>,
|
||||||
@ -171,13 +172,14 @@ impl GuiElem for KeybindInput {
|
|||||||
| VirtualKeyCode::RAlt
|
| VirtualKeyCode::RAlt
|
||||||
| VirtualKeyCode::LWin
|
| VirtualKeyCode::LWin
|
||||||
| VirtualKeyCode::RWin
|
| VirtualKeyCode::RWin
|
||||||
) {
|
) && e.take()
|
||||||
|
{
|
||||||
self.changing = false;
|
self.changing = false;
|
||||||
let bind = KeyBinding::new(&modifiers, key);
|
let bind = KeyBinding::new(&modifiers, key);
|
||||||
self.keybinds_should_be_updated
|
self.keybinds_should_be_updated
|
||||||
.store(true, std::sync::atomic::Ordering::Relaxed);
|
.store(true, std::sync::atomic::Ordering::Relaxed);
|
||||||
vec![
|
vec![
|
||||||
GuiAction::SetKeybind(self.id, Some(bind)),
|
GuiAction::SetKeybind(self.id, Some((bind, true))),
|
||||||
GuiAction::ResetKeyboardFocus,
|
GuiAction::ResetKeyboardFocus,
|
||||||
]
|
]
|
||||||
} else {
|
} else {
|
||||||
|
@ -10,7 +10,7 @@ use speedy2d::{
|
|||||||
window::{ModifiersState, MouseButton},
|
window::{ModifiersState, MouseButton},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::gui::{GuiAction, GuiElem, GuiElemCfg, GuiServerImage};
|
use crate::gui::{EventInfo, GuiAction, GuiElem, GuiElemCfg, GuiServerImage};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
||||||
@ -224,12 +224,24 @@ impl GuiElem for TextField {
|
|||||||
g.draw_line(info.pos.top_left(), info.pos.bottom_left(), t, c);
|
g.draw_line(info.pos.top_left(), info.pos.bottom_left(), t, c);
|
||||||
g.draw_line(info.pos.top_right(), info.pos.bottom_right(), t, c);
|
g.draw_line(info.pos.top_right(), info.pos.bottom_right(), t, c);
|
||||||
}
|
}
|
||||||
fn mouse_pressed(&mut self, _button: MouseButton) -> Vec<GuiAction> {
|
fn mouse_pressed(&mut self, e: &mut EventInfo, _button: MouseButton) -> Vec<GuiAction> {
|
||||||
self.config.request_keyboard_focus = true;
|
if e.take() {
|
||||||
vec![GuiAction::ResetKeyboardFocus]
|
self.config.request_keyboard_focus = true;
|
||||||
|
vec![GuiAction::ResetKeyboardFocus]
|
||||||
|
} else {
|
||||||
|
vec![]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
fn char_focus(&mut self, modifiers: ModifiersState, key: char) -> Vec<GuiAction> {
|
fn char_focus(
|
||||||
if !(modifiers.ctrl() || modifiers.alt() || modifiers.logo()) && !key.is_control() {
|
&mut self,
|
||||||
|
e: &mut EventInfo,
|
||||||
|
modifiers: ModifiersState,
|
||||||
|
key: char,
|
||||||
|
) -> Vec<GuiAction> {
|
||||||
|
if !(modifiers.ctrl() || modifiers.alt() || modifiers.logo())
|
||||||
|
&& !key.is_control()
|
||||||
|
&& e.take()
|
||||||
|
{
|
||||||
let content = &mut self.c_input.content;
|
let content = &mut self.c_input.content;
|
||||||
let was_empty = content.get_text().is_empty();
|
let was_empty = content.get_text().is_empty();
|
||||||
content.text().push(key);
|
content.text().push(key);
|
||||||
@ -249,6 +261,7 @@ impl GuiElem for TextField {
|
|||||||
}
|
}
|
||||||
fn key_focus(
|
fn key_focus(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
e: &mut EventInfo,
|
||||||
modifiers: ModifiersState,
|
modifiers: ModifiersState,
|
||||||
down: bool,
|
down: bool,
|
||||||
key: Option<speedy2d::window::VirtualKeyCode>,
|
key: Option<speedy2d::window::VirtualKeyCode>,
|
||||||
@ -257,6 +270,7 @@ impl GuiElem for TextField {
|
|||||||
if down
|
if down
|
||||||
&& !(modifiers.alt() || modifiers.logo())
|
&& !(modifiers.alt() || modifiers.logo())
|
||||||
&& key == Some(speedy2d::window::VirtualKeyCode::Backspace)
|
&& key == Some(speedy2d::window::VirtualKeyCode::Backspace)
|
||||||
|
&& e.take()
|
||||||
{
|
{
|
||||||
let content = &mut self.c_input.content;
|
let content = &mut self.c_input.content;
|
||||||
if !content.get_text().is_empty() {
|
if !content.get_text().is_empty() {
|
||||||
|
@ -264,24 +264,35 @@ fn main() {
|
|||||||
}
|
}
|
||||||
#[cfg(feature = "mers")]
|
#[cfg(feature = "mers")]
|
||||||
Mode::RunMers { path } => {
|
Mode::RunMers { path } => {
|
||||||
let mut src = mers_lib::prelude_compile::Source::new_from_file(path).unwrap();
|
let mut src =
|
||||||
|
musicdb_mers::mers_lib::prelude_compile::Source::new_from_file(path).unwrap();
|
||||||
let srca = Arc::new(src.clone());
|
let srca = Arc::new(src.clone());
|
||||||
let con = Mutex::new(con);
|
let con = Mutex::new(con);
|
||||||
let (mut i1, mut i2, mut i3) = musicdb_mers::add(
|
let (mut i1, mut i2, mut i3) = musicdb_mers::add(
|
||||||
mers_lib::prelude_compile::Config::new().bundle_std(),
|
musicdb_mers::mers_lib::prelude_compile::Config::new().bundle_std(),
|
||||||
&database,
|
&database,
|
||||||
&Arc::new(move |cmd: Command| cmd.to_bytes(&mut *con.lock().unwrap()).unwrap()),
|
&Arc::new(move |cmd: Command| cmd.to_bytes(&mut *con.lock().unwrap()).unwrap()),
|
||||||
&mers_after_db_updated_action,
|
&mers_after_db_updated_action,
|
||||||
)
|
)
|
||||||
.infos();
|
.infos();
|
||||||
let program = mers_lib::prelude_compile::parse(&mut src, &srca)
|
let program = match musicdb_mers::mers_lib::prelude_compile::parse(&mut src, &srca) {
|
||||||
.unwrap()
|
Ok(p) => p,
|
||||||
.compile(&mut i1, mers_lib::prelude_compile::CompInfo::default())
|
Err(e) => {
|
||||||
.unwrap();
|
eprintln!("{}", e.display_term());
|
||||||
|
std::process::exit(60);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let program = match program.compile(&mut i1, Default::default()) {
|
||||||
|
Ok(p) => p,
|
||||||
|
Err(e) => {
|
||||||
|
eprintln!("{}", e.display_term());
|
||||||
|
std::process::exit(60);
|
||||||
|
}
|
||||||
|
};
|
||||||
match program.check(&mut i3, None) {
|
match program.check(&mut i3, None) {
|
||||||
Ok(_) => {}
|
Ok(_) => {}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
eprintln!("{e}");
|
eprintln!("{}", e.display_term());
|
||||||
std::process::exit(60);
|
std::process::exit(60);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -293,7 +304,9 @@ fn main() {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
program.run(&mut i2);
|
if let Err(e) = program.run(&mut i2) {
|
||||||
|
eprintln!("{}", e.display_term());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,12 +8,11 @@ use std::{
|
|||||||
time::Duration,
|
time::Duration,
|
||||||
};
|
};
|
||||||
|
|
||||||
use mers_lib::{
|
|
||||||
data::{Data, MersType, Type},
|
|
||||||
errors::CheckError,
|
|
||||||
prelude_compile::CompInfo,
|
|
||||||
};
|
|
||||||
use musicdb_lib::{data::database::Database, server::Command};
|
use musicdb_lib::{data::database::Database, server::Command};
|
||||||
|
use musicdb_mers::mers_lib::{
|
||||||
|
data::{Data, Type},
|
||||||
|
errors::CheckError,
|
||||||
|
};
|
||||||
use speedy2d::{color::Color, dimen::Vec2, shape::Rectangle, window::UserEventSender};
|
use speedy2d::{color::Color, dimen::Vec2, shape::Rectangle, window::UserEventSender};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
@ -24,17 +23,17 @@ use crate::{
|
|||||||
textcfg::TextBuilder,
|
textcfg::TextBuilder,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct OptFunc(pub Option<mers_lib::data::function::Function>);
|
pub struct OptFunc(pub Option<musicdb_mers::mers_lib::data::function::Function>);
|
||||||
impl OptFunc {
|
impl OptFunc {
|
||||||
pub fn none() -> Self {
|
pub fn none() -> Self {
|
||||||
Self(None)
|
Self(None)
|
||||||
}
|
}
|
||||||
pub fn some(func: mers_lib::data::function::Function) -> Self {
|
pub fn some(func: musicdb_mers::mers_lib::data::function::Function) -> Self {
|
||||||
Self(Some(func))
|
Self(Some(func))
|
||||||
}
|
}
|
||||||
fn run(&self) {
|
fn run(&self) {
|
||||||
if let Some(func) = &self.0 {
|
if let Some(func) = &self.0 {
|
||||||
func.run(Data::empty_tuple());
|
func.run_immut(Data::empty_tuple());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -71,7 +70,6 @@ pub struct MersCfg {
|
|||||||
pub func_library_updated: OptFunc,
|
pub func_library_updated: OptFunc,
|
||||||
pub func_queue_updated: OptFunc,
|
pub func_queue_updated: OptFunc,
|
||||||
// - - globals that aren't functions - -
|
// - - globals that aren't functions - -
|
||||||
pub var_is_playing: Arc<RwLock<Data>>,
|
|
||||||
pub var_is_idle: Arc<RwLock<Data>>,
|
pub var_is_idle: Arc<RwLock<Data>>,
|
||||||
pub var_window_size_in_pixels: Arc<RwLock<Data>>,
|
pub var_window_size_in_pixels: Arc<RwLock<Data>>,
|
||||||
pub var_idle_screen_cover_aspect_ratio: Arc<RwLock<Data>>,
|
pub var_idle_screen_cover_aspect_ratio: Arc<RwLock<Data>>,
|
||||||
@ -104,16 +102,17 @@ impl MersCfg {
|
|||||||
func_library_updated: OptFunc::none(),
|
func_library_updated: OptFunc::none(),
|
||||||
func_queue_updated: OptFunc::none(),
|
func_queue_updated: OptFunc::none(),
|
||||||
|
|
||||||
var_is_playing: Arc::new(RwLock::new(Data::new(mers_lib::data::bool::Bool(false)))),
|
var_is_idle: Arc::new(RwLock::new(Data::new(
|
||||||
var_is_idle: Arc::new(RwLock::new(Data::new(mers_lib::data::bool::Bool(false)))),
|
musicdb_mers::mers_lib::data::bool::Bool(false),
|
||||||
|
))),
|
||||||
var_window_size_in_pixels: Arc::new(RwLock::new(Data::new(
|
var_window_size_in_pixels: Arc::new(RwLock::new(Data::new(
|
||||||
mers_lib::data::tuple::Tuple(vec![
|
musicdb_mers::mers_lib::data::tuple::Tuple(vec![
|
||||||
Data::new(mers_lib::data::int::Int(0)),
|
Data::new(musicdb_mers::mers_lib::data::int::Int(0)),
|
||||||
Data::new(mers_lib::data::int::Int(0)),
|
Data::new(musicdb_mers::mers_lib::data::int::Int(0)),
|
||||||
]),
|
]),
|
||||||
))),
|
))),
|
||||||
var_idle_screen_cover_aspect_ratio: Arc::new(RwLock::new(Data::new(
|
var_idle_screen_cover_aspect_ratio: Arc::new(RwLock::new(Data::new(
|
||||||
mers_lib::data::float::Float(0.0),
|
musicdb_mers::mers_lib::data::float::Float(0.0),
|
||||||
))),
|
))),
|
||||||
|
|
||||||
channel_gui_actions: std::sync::mpsc::channel(),
|
channel_gui_actions: std::sync::mpsc::channel(),
|
||||||
@ -133,36 +132,31 @@ impl MersCfg {
|
|||||||
}
|
}
|
||||||
fn custom_globals(
|
fn custom_globals(
|
||||||
&self,
|
&self,
|
||||||
cfg: mers_lib::prelude_extend_config::Config,
|
cfg: musicdb_mers::mers_lib::prelude_extend_config::Config,
|
||||||
db: &Arc<Mutex<Database>>,
|
db: &Arc<Mutex<Database>>,
|
||||||
event_sender: Arc<UserEventSender<GuiEvent>>,
|
event_sender: Arc<UserEventSender<GuiEvent>>,
|
||||||
notif_sender: Sender<
|
notif_sender: Sender<
|
||||||
Box<dyn FnOnce(&NotifOverlay) -> (Box<dyn GuiElem>, NotifInfo) + Send>,
|
Box<dyn FnOnce(&NotifOverlay) -> (Box<dyn GuiElem>, NotifInfo) + Send>,
|
||||||
>,
|
>,
|
||||||
after_db_cmd: &Arc<Mutex<Option<Box<dyn FnMut(Command) + Send + Sync + 'static>>>>,
|
after_db_cmd: &Arc<Mutex<Option<Box<dyn FnMut(Command) + Send + Sync + 'static>>>>,
|
||||||
) -> mers_lib::prelude_extend_config::Config {
|
) -> musicdb_mers::mers_lib::prelude_extend_config::Config {
|
||||||
let cmd_es = event_sender.clone();
|
let cmd_es = event_sender.clone();
|
||||||
let cmd_ga = self.channel_gui_actions.0.clone();
|
let cmd_ga = self.channel_gui_actions.0.clone();
|
||||||
musicdb_mers::add(cfg, db, &Arc::new(move |cmd| {
|
musicdb_mers::add(cfg, db, &Arc::new(move |cmd| {
|
||||||
cmd_ga.send(cmd).unwrap();
|
cmd_ga.send(cmd).unwrap();
|
||||||
cmd_es.send_event(GuiEvent::RefreshMers).unwrap();
|
cmd_es.send_event(GuiEvent::RefreshMers).unwrap();
|
||||||
}), after_db_cmd)
|
}), after_db_cmd)
|
||||||
.add_var_arc(
|
.add_var_from_arc(
|
||||||
"is_playing".to_owned(),
|
|
||||||
Arc::clone(&self.var_is_playing),
|
|
||||||
self.var_is_playing.read().unwrap().get().as_type(),
|
|
||||||
)
|
|
||||||
.add_var_arc(
|
|
||||||
"is_idle".to_owned(),
|
"is_idle".to_owned(),
|
||||||
Arc::clone(&self.var_is_idle),
|
Arc::clone(&self.var_is_idle),
|
||||||
self.var_is_idle.read().unwrap().get().as_type(),
|
self.var_is_idle.read().unwrap().get().as_type(),
|
||||||
)
|
)
|
||||||
.add_var_arc(
|
.add_var_from_arc(
|
||||||
"window_size_in_pixels".to_owned(),
|
"window_size_in_pixels".to_owned(),
|
||||||
Arc::clone(&self.var_window_size_in_pixels),
|
Arc::clone(&self.var_window_size_in_pixels),
|
||||||
self.var_window_size_in_pixels.read().unwrap().get().as_type(),
|
self.var_window_size_in_pixels.read().unwrap().get().as_type(),
|
||||||
)
|
)
|
||||||
.add_var_arc(
|
.add_var_from_arc(
|
||||||
"idle_screen_cover_aspect_ratio".to_owned(),
|
"idle_screen_cover_aspect_ratio".to_owned(),
|
||||||
Arc::clone(&self.var_idle_screen_cover_aspect_ratio),
|
Arc::clone(&self.var_idle_screen_cover_aspect_ratio),
|
||||||
self.var_idle_screen_cover_aspect_ratio.read().unwrap().get().as_type(),
|
self.var_idle_screen_cover_aspect_ratio.read().unwrap().get().as_type(),
|
||||||
@ -170,155 +164,135 @@ impl MersCfg {
|
|||||||
.add_var("playback_resume".to_owned(),{
|
.add_var("playback_resume".to_owned(),{
|
||||||
let es = event_sender.clone();
|
let es = event_sender.clone();
|
||||||
let v = Arc::clone(&self.updated_playing_status);
|
let v = Arc::clone(&self.updated_playing_status);
|
||||||
Data::new(mers_lib::data::function::Function {
|
musicdb_mers::mers_lib::data::function::Function::new_generic(
|
||||||
info: Arc::new(mers_lib::info::Info::neverused()),
|
|a| {
|
||||||
info_check: Arc::new(Mutex::new(mers_lib::info::Info::neverused())),
|
|
||||||
out: Arc::new(|a, _| {
|
|
||||||
if a.is_zero_tuple() {
|
if a.is_zero_tuple() {
|
||||||
Ok(Type::empty_tuple())
|
Ok(Type::empty_tuple())
|
||||||
} else {
|
} else {
|
||||||
Err(format!("Can't call `playback_resume` with argument of type `{a}` (must be `()`).").into())
|
Err(format!("Can't call `playback_resume` with argument of type `{a}` (must be `()`).").into())
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
run: Arc::new(move |_, _| {
|
move |_, _| {
|
||||||
v.store(1, std::sync::atomic::Ordering::Relaxed);
|
v.store(1, std::sync::atomic::Ordering::Relaxed);
|
||||||
es.send_event(GuiEvent::Refresh).unwrap();
|
es.send_event(GuiEvent::Refresh).unwrap();
|
||||||
Data::empty_tuple()
|
Ok(Data::empty_tuple())
|
||||||
}),
|
},
|
||||||
inner_statements: None,
|
)
|
||||||
})
|
|
||||||
})
|
})
|
||||||
.add_var("playback_pause".to_owned(),{
|
.add_var("playback_pause".to_owned(),{
|
||||||
let es = event_sender.clone();
|
let es = event_sender.clone();
|
||||||
let v = Arc::clone(&self.updated_playing_status);
|
let v = Arc::clone(&self.updated_playing_status);
|
||||||
Data::new(mers_lib::data::function::Function {
|
musicdb_mers::mers_lib::data::function::Function::new_generic(
|
||||||
info: Arc::new(mers_lib::info::Info::neverused()),
|
|a| {
|
||||||
info_check: Arc::new(Mutex::new(mers_lib::info::Info::neverused())),
|
|
||||||
out: Arc::new(|a, _| {
|
|
||||||
if a.is_zero_tuple() {
|
if a.is_zero_tuple() {
|
||||||
Ok(Type::empty_tuple())
|
Ok(Type::empty_tuple())
|
||||||
} else {
|
} else {
|
||||||
Err(format!("Can't call `playback_pause` with argument of type `{a}` (must be `()`).").into())
|
Err(format!("Can't call `playback_pause` with argument of type `{a}` (must be `()`).").into())
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
run: Arc::new(move |_, _| {
|
move |_, _| {
|
||||||
v.store(2, std::sync::atomic::Ordering::Relaxed);
|
v.store(2, std::sync::atomic::Ordering::Relaxed);
|
||||||
es.send_event(GuiEvent::Refresh).unwrap();
|
es.send_event(GuiEvent::Refresh).unwrap();
|
||||||
Data::empty_tuple()
|
Ok(Data::empty_tuple())
|
||||||
}),
|
},
|
||||||
inner_statements: None,
|
)
|
||||||
})
|
|
||||||
})
|
})
|
||||||
.add_var("playback_stop".to_owned(),{
|
.add_var("playback_stop".to_owned(),{
|
||||||
let es = event_sender.clone();
|
let es = event_sender.clone();
|
||||||
let v = Arc::clone(&self.updated_playing_status);
|
let v = Arc::clone(&self.updated_playing_status);
|
||||||
Data::new(mers_lib::data::function::Function {
|
musicdb_mers::mers_lib::data::function::Function::new_generic(
|
||||||
info: Arc::new(mers_lib::info::Info::neverused()),
|
|a| {
|
||||||
info_check: Arc::new(Mutex::new(mers_lib::info::Info::neverused())),
|
|
||||||
out: Arc::new(|a, _| {
|
|
||||||
if a.is_zero_tuple() {
|
if a.is_zero_tuple() {
|
||||||
Ok(Type::empty_tuple())
|
Ok(Type::empty_tuple())
|
||||||
} else {
|
} else {
|
||||||
Err(format!("Can't call `playback_stop` with argument of type `{a}` (must be `()`).").into())
|
Err(format!("Can't call `playback_stop` with argument of type `{a}` (must be `()`).").into())
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
run: Arc::new(move |_, _| {
|
move |_, _| {
|
||||||
v.store(3, std::sync::atomic::Ordering::Relaxed);
|
v.store(3, std::sync::atomic::Ordering::Relaxed);
|
||||||
es.send_event(GuiEvent::Refresh).unwrap();
|
es.send_event(GuiEvent::Refresh).unwrap();
|
||||||
Data::empty_tuple()
|
Ok(Data::empty_tuple())
|
||||||
}),
|
},
|
||||||
inner_statements: None,
|
)
|
||||||
})
|
|
||||||
})
|
})
|
||||||
.add_var("idle_start".to_owned(),{
|
.add_var("idle_start".to_owned(),{
|
||||||
let es = event_sender.clone();
|
let es = event_sender.clone();
|
||||||
let v = Arc::clone(&self.updated_idle_status);
|
let v = Arc::clone(&self.updated_idle_status);
|
||||||
Data::new(mers_lib::data::function::Function {
|
musicdb_mers::mers_lib::data::function::Function::new_generic(
|
||||||
info: Arc::new(mers_lib::info::Info::neverused()),
|
|a| {
|
||||||
info_check: Arc::new(Mutex::new(mers_lib::info::Info::neverused())),
|
|
||||||
out: Arc::new(|a, _| {
|
|
||||||
if a.is_zero_tuple() {
|
if a.is_zero_tuple() {
|
||||||
Ok(Type::empty_tuple())
|
Ok(Type::empty_tuple())
|
||||||
} else {
|
} else {
|
||||||
Err(format!("Can't call `idle_start` with argument of type `{a}` (must be `()`).").into())
|
Err(format!("Can't call `idle_start` with argument of type `{a}` (must be `()`).").into())
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
run: Arc::new(move |_, _| {
|
move |_, _| {
|
||||||
v.store(1, std::sync::atomic::Ordering::Relaxed);
|
v.store(1, std::sync::atomic::Ordering::Relaxed);
|
||||||
es.send_event(GuiEvent::Refresh).unwrap();
|
es.send_event(GuiEvent::Refresh).unwrap();
|
||||||
Data::empty_tuple()
|
Ok(Data::empty_tuple())
|
||||||
}),
|
},
|
||||||
inner_statements: None,
|
)
|
||||||
})
|
|
||||||
})
|
})
|
||||||
.add_var("idle_stop".to_owned(),{
|
.add_var("idle_stop".to_owned(),{
|
||||||
let es = event_sender.clone();
|
let es = event_sender.clone();
|
||||||
let v = Arc::clone(&self.updated_idle_status);
|
let v = Arc::clone(&self.updated_idle_status);
|
||||||
Data::new(mers_lib::data::function::Function {
|
musicdb_mers::mers_lib::data::function::Function::new_generic(
|
||||||
info: Arc::new(mers_lib::info::Info::neverused()),
|
|a| {
|
||||||
info_check: Arc::new(Mutex::new(mers_lib::info::Info::neverused())),
|
|
||||||
out: Arc::new(|a, _| {
|
|
||||||
if a.is_zero_tuple() {
|
if a.is_zero_tuple() {
|
||||||
Ok(Type::empty_tuple())
|
Ok(Type::empty_tuple())
|
||||||
} else {
|
} else {
|
||||||
Err(format!("Can't call `idle_stop` with argument of type `{a}` (must be `()`).").into())
|
Err(format!("Can't call `idle_stop` with argument of type `{a}` (must be `()`).").into())
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
run: Arc::new(move |_, _| {
|
move |_, _| {
|
||||||
v.store(2, std::sync::atomic::Ordering::Relaxed);
|
v.store(2, std::sync::atomic::Ordering::Relaxed);
|
||||||
es.send_event(GuiEvent::Refresh).unwrap();
|
es.send_event(GuiEvent::Refresh).unwrap();
|
||||||
Data::empty_tuple()
|
Ok(Data::empty_tuple())
|
||||||
}),
|
},
|
||||||
inner_statements: None,
|
)
|
||||||
})
|
|
||||||
})
|
})
|
||||||
.add_var("idle_prevent".to_owned(),{
|
.add_var("idle_prevent".to_owned(),{
|
||||||
let es = event_sender.clone();
|
let es = event_sender.clone();
|
||||||
let v = Arc::clone(&self.updated_idle_status);
|
let v = Arc::clone(&self.updated_idle_status);
|
||||||
Data::new(mers_lib::data::function::Function {
|
musicdb_mers::mers_lib::data::function::Function::new_generic(
|
||||||
info: Arc::new(mers_lib::info::Info::neverused()),
|
|a | {
|
||||||
info_check: Arc::new(Mutex::new(mers_lib::info::Info::neverused())),
|
|
||||||
out: Arc::new(|a, _| {
|
|
||||||
if a.is_zero_tuple() {
|
if a.is_zero_tuple() {
|
||||||
Ok(Type::empty_tuple())
|
Ok(Type::empty_tuple())
|
||||||
} else {
|
} else {
|
||||||
Err(format!("Can't call `idle_prevent` with argument of type `{a}` (must be `()`).").into())
|
Err(format!("Can't call `idle_prevent` with argument of type `{a}` (must be `()`).").into())
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
run: Arc::new(move |_, _| {
|
move |_, _| {
|
||||||
v.store(3, std::sync::atomic::Ordering::Relaxed);
|
v.store(3, std::sync::atomic::Ordering::Relaxed);
|
||||||
es.send_event(GuiEvent::Refresh).unwrap();
|
es.send_event(GuiEvent::Refresh).unwrap();
|
||||||
Data::empty_tuple()
|
Ok(Data::empty_tuple())
|
||||||
}),
|
},
|
||||||
inner_statements: None,
|
)
|
||||||
})
|
|
||||||
})
|
})
|
||||||
.add_var("send_notification".to_owned(),{
|
.add_var("send_notification".to_owned(),{
|
||||||
let es = event_sender.clone();
|
let es = event_sender.clone();
|
||||||
Data::new(mers_lib::data::function::Function {
|
musicdb_mers::mers_lib::data::function::Function::new_generic(
|
||||||
info: Arc::new(mers_lib::info::Info::neverused()),
|
|a| {
|
||||||
info_check: Arc::new(Mutex::new(mers_lib::info::Info::neverused())),
|
if a.is_included_in_single(&musicdb_mers::mers_lib::data::tuple::TupleT(vec![
|
||||||
out: Arc::new(|a, _| {
|
musicdb_mers::mers_lib::data::Type::new(musicdb_mers::mers_lib::data::string::StringT),
|
||||||
if a.is_included_in(&mers_lib::data::tuple::TupleT(vec![
|
musicdb_mers::mers_lib::data::Type::new(musicdb_mers::mers_lib::data::string::StringT),
|
||||||
mers_lib::data::Type::new(mers_lib::data::string::StringT),
|
musicdb_mers::mers_lib::data::Type::newm(vec![
|
||||||
mers_lib::data::Type::new(mers_lib::data::string::StringT),
|
Arc::new(musicdb_mers::mers_lib::data::int::IntT),
|
||||||
mers_lib::data::Type::newm(vec![
|
Arc::new(musicdb_mers::mers_lib::data::float::FloatT)
|
||||||
Arc::new(mers_lib::data::int::IntT),
|
|
||||||
Arc::new(mers_lib::data::float::FloatT)
|
|
||||||
]),
|
]),
|
||||||
])) {
|
])) {
|
||||||
Ok(Type::empty_tuple())
|
Ok(Type::empty_tuple())
|
||||||
} else {
|
} else {
|
||||||
Err(format!("Can't call `send_notification` with argument of type `{a}` (must be `String`).").into())
|
Err(format!("Can't call `send_notification` with argument of type `{a}` (must be `String`).").into())
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
run: Arc::new(move |a, _| {
|
move |a, _| {
|
||||||
let a = a.get();
|
let a = a.get();
|
||||||
let t = &a.as_any().downcast_ref::<mers_lib::data::tuple::Tuple>().unwrap().0;
|
let t = &a.as_any().downcast_ref::<musicdb_mers::mers_lib::data::tuple::Tuple>().unwrap().0;
|
||||||
let title = t[0].get().as_any().downcast_ref::<mers_lib::data::string::String>().unwrap().0.clone();
|
let title = t[0].get().as_any().downcast_ref::<musicdb_mers::mers_lib::data::string::String>().unwrap().0.clone();
|
||||||
let text = t[1].get().as_any().downcast_ref::<mers_lib::data::string::String>().unwrap().0.clone();
|
let text = t[1].get().as_any().downcast_ref::<musicdb_mers::mers_lib::data::string::String>().unwrap().0.clone();
|
||||||
let t = t[2].get();
|
let t = t[2].get();
|
||||||
let duration = t.as_any().downcast_ref::<mers_lib::data::int::Int>().map(|s| Duration::from_secs(s.0.max(0) as _)).unwrap_or_else(|| Duration::from_secs_f64(t.as_any().downcast_ref::<mers_lib::data::float::Float>().unwrap().0));
|
let duration = t.as_any().downcast_ref::<musicdb_mers::mers_lib::data::int::Int>().map(|s| Duration::from_secs(s.0.max(0) as _)).unwrap_or_else(|| Duration::from_secs_f64(t.as_any().downcast_ref::<musicdb_mers::mers_lib::data::float::Float>().unwrap().0));
|
||||||
notif_sender
|
notif_sender
|
||||||
.send(Box::new(move |_| {
|
.send(Box::new(move |_| {
|
||||||
(
|
(
|
||||||
@ -353,77 +327,70 @@ impl MersCfg {
|
|||||||
}))
|
}))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
es.send_event(GuiEvent::Refresh).unwrap();
|
es.send_event(GuiEvent::Refresh).unwrap();
|
||||||
Data::empty_tuple()
|
Ok(Data::empty_tuple())
|
||||||
}),
|
},
|
||||||
inner_statements: None,
|
)
|
||||||
})
|
|
||||||
})
|
})
|
||||||
.add_var("set_idle_screen_cover_pos".to_owned(),{
|
.add_var("set_idle_screen_cover_pos".to_owned(),{
|
||||||
let es = event_sender.clone();
|
let es = event_sender.clone();
|
||||||
let update = Arc::clone(&self.updated_idle_screen_cover_pos);
|
let update = Arc::clone(&self.updated_idle_screen_cover_pos);
|
||||||
Data::new(mers_lib::data::function::Function {
|
musicdb_mers::mers_lib::data::function::Function::new_generic(
|
||||||
info: Arc::new(mers_lib::info::Info::neverused()),
|
|a| {
|
||||||
info_check: Arc::new(Mutex::new(mers_lib::info::Info::neverused())),
|
if a.is_included_in(&musicdb_mers::mers_lib::data::Type::newm(vec![
|
||||||
out: Arc::new(|a, _| {
|
Arc::new(musicdb_mers::mers_lib::data::tuple::TupleT(vec![])),
|
||||||
if a.is_included_in(&mers_lib::data::Type::newm(vec![
|
Arc::new(musicdb_mers::mers_lib::data::tuple::TupleT(vec![
|
||||||
Arc::new(mers_lib::data::tuple::TupleT(vec![])),
|
musicdb_mers::mers_lib::data::Type::new(musicdb_mers::mers_lib::data::float::FloatT),
|
||||||
Arc::new(mers_lib::data::tuple::TupleT(vec![
|
musicdb_mers::mers_lib::data::Type::new(musicdb_mers::mers_lib::data::float::FloatT),
|
||||||
mers_lib::data::Type::new(mers_lib::data::float::FloatT),
|
musicdb_mers::mers_lib::data::Type::new(musicdb_mers::mers_lib::data::float::FloatT),
|
||||||
mers_lib::data::Type::new(mers_lib::data::float::FloatT),
|
musicdb_mers::mers_lib::data::Type::new(musicdb_mers::mers_lib::data::float::FloatT),
|
||||||
mers_lib::data::Type::new(mers_lib::data::float::FloatT),
|
|
||||||
mers_lib::data::Type::new(mers_lib::data::float::FloatT),
|
|
||||||
]))
|
]))
|
||||||
])) {
|
])) {
|
||||||
Ok(Type::empty_tuple())
|
Ok(Type::empty_tuple())
|
||||||
} else {
|
} else {
|
||||||
Err(format!("Can't call `set_idle_screen_cover_pos` with argument of type `{a}` (must be `()` or `(Float, Float, Float, Float)`).").into())
|
Err(format!("Can't call `set_idle_screen_cover_pos` with argument of type `{a}` (must be `()` or `(Float, Float, Float, Float)`).").into())
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
run: Arc::new(move |a, _| {
|
move |a, _| {
|
||||||
let a = a.get();
|
let a = a.get();
|
||||||
let mut vals = a.as_any().downcast_ref::<mers_lib::data::tuple::Tuple>().unwrap().0.iter().map(|v| v.get().as_any().downcast_ref::<mers_lib::data::float::Float>().unwrap().0);
|
let mut vals = a.as_any().downcast_ref::<musicdb_mers::mers_lib::data::tuple::Tuple>().unwrap().0.iter().map(|v| v.get().as_any().downcast_ref::<musicdb_mers::mers_lib::data::float::Float>().unwrap().0);
|
||||||
update.update(
|
update.update(
|
||||||
if vals.len() >= 4 {
|
if vals.len() >= 4 {
|
||||||
Some(Rectangle::from_tuples((vals.next().unwrap() as _, vals.next().unwrap() as _), (vals.next().unwrap() as _, vals.next().unwrap() as _)))
|
Some(Rectangle::from_tuples((vals.next().unwrap() as _, vals.next().unwrap() as _), (vals.next().unwrap() as _, vals.next().unwrap() as _)))
|
||||||
} else { None });
|
} else { None });
|
||||||
es.send_event(GuiEvent::Refresh).unwrap();
|
es.send_event(GuiEvent::Refresh).unwrap();
|
||||||
Data::empty_tuple()
|
Ok(Data::empty_tuple())
|
||||||
}),
|
},
|
||||||
inner_statements: None,
|
)
|
||||||
})
|
|
||||||
}).add_var("set_idle_screen_artist_image_pos".to_owned(),{
|
}).add_var("set_idle_screen_artist_image_pos".to_owned(),{
|
||||||
let es = event_sender.clone();
|
let es = event_sender.clone();
|
||||||
let update = Arc::clone(&self.updated_idle_screen_artist_image_pos);
|
let update = Arc::clone(&self.updated_idle_screen_artist_image_pos);
|
||||||
Data::new(mers_lib::data::function::Function {
|
musicdb_mers::mers_lib::data::function::Function::new_generic(
|
||||||
info: Arc::new(mers_lib::info::Info::neverused()),
|
|a| {
|
||||||
info_check: Arc::new(Mutex::new(mers_lib::info::Info::neverused())),
|
if a.is_included_in(&musicdb_mers::mers_lib::data::Type::newm(vec![
|
||||||
out: Arc::new(|a, _| {
|
Arc::new(musicdb_mers::mers_lib::data::tuple::TupleT(vec![])),
|
||||||
if a.is_included_in(&mers_lib::data::Type::newm(vec![
|
Arc::new(musicdb_mers::mers_lib::data::tuple::TupleT(vec![
|
||||||
Arc::new(mers_lib::data::tuple::TupleT(vec![])),
|
musicdb_mers::mers_lib::data::Type::new(musicdb_mers::mers_lib::data::float::FloatT),
|
||||||
Arc::new(mers_lib::data::tuple::TupleT(vec![
|
musicdb_mers::mers_lib::data::Type::new(musicdb_mers::mers_lib::data::float::FloatT),
|
||||||
mers_lib::data::Type::new(mers_lib::data::float::FloatT),
|
musicdb_mers::mers_lib::data::Type::new(musicdb_mers::mers_lib::data::float::FloatT),
|
||||||
mers_lib::data::Type::new(mers_lib::data::float::FloatT),
|
musicdb_mers::mers_lib::data::Type::new(musicdb_mers::mers_lib::data::float::FloatT),
|
||||||
mers_lib::data::Type::new(mers_lib::data::float::FloatT),
|
|
||||||
mers_lib::data::Type::new(mers_lib::data::float::FloatT),
|
|
||||||
]))
|
]))
|
||||||
])) {
|
])) {
|
||||||
Ok(Type::empty_tuple())
|
Ok(Type::empty_tuple())
|
||||||
} else {
|
} else {
|
||||||
Err(format!("Can't call `set_idle_screen_artist_image_pos` with argument of type `{a}` (must be `()` or `(Float, Float, Float, Float)`).").into())
|
Err(format!("Can't call `set_idle_screen_artist_image_pos` with argument of type `{a}` (must be `()` or `(Float, Float, Float, Float)`).").into())
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
run: Arc::new(move |a, _| {
|
move |a, _| {
|
||||||
let a = a.get();
|
let a = a.get();
|
||||||
let mut vals = a.as_any().downcast_ref::<mers_lib::data::tuple::Tuple>().unwrap().0.iter().map(|v| v.get().as_any().downcast_ref::<mers_lib::data::float::Float>().unwrap().0);
|
let mut vals = a.as_any().downcast_ref::<musicdb_mers::mers_lib::data::tuple::Tuple>().unwrap().0.iter().map(|v| v.get().as_any().downcast_ref::<musicdb_mers::mers_lib::data::float::Float>().unwrap().0);
|
||||||
update.update(
|
update.update(
|
||||||
if vals.len() >= 4 {
|
if vals.len() >= 4 {
|
||||||
Some(Rectangle::from_tuples((vals.next().unwrap() as _, vals.next().unwrap() as _), (vals.next().unwrap() as _, vals.next().unwrap() as _)))
|
Some(Rectangle::from_tuples((vals.next().unwrap() as _, vals.next().unwrap() as _), (vals.next().unwrap() as _, vals.next().unwrap() as _)))
|
||||||
} else { None });
|
} else { None });
|
||||||
es.send_event(GuiEvent::Refresh).unwrap();
|
es.send_event(GuiEvent::Refresh).unwrap();
|
||||||
Data::empty_tuple()
|
Ok(Data::empty_tuple())
|
||||||
}),
|
},
|
||||||
inner_statements: None,
|
)
|
||||||
})
|
|
||||||
})
|
})
|
||||||
.add_var("set_idle_screen_top_text_pos".to_owned(), gen_set_pos_func("set_idle_screen_top_text_pos", Arc::clone(&event_sender), Arc::clone(&self.updated_idle_screen_top_text_pos)))
|
.add_var("set_idle_screen_top_text_pos".to_owned(), gen_set_pos_func("set_idle_screen_top_text_pos", Arc::clone(&event_sender), Arc::clone(&self.updated_idle_screen_top_text_pos)))
|
||||||
.add_var("set_idle_screen_side_text_1_pos".to_owned(), gen_set_pos_func("set_idle_screen_side_text_1_pos", Arc::clone(&event_sender), Arc::clone(&self.updated_idle_screen_side_text_1_pos)))
|
.add_var("set_idle_screen_side_text_1_pos".to_owned(), gen_set_pos_func("set_idle_screen_side_text_1_pos", Arc::clone(&event_sender), Arc::clone(&self.updated_idle_screen_side_text_1_pos)))
|
||||||
@ -433,153 +400,142 @@ impl MersCfg {
|
|||||||
.add_var("set_statusbar_text_format".to_owned(),{
|
.add_var("set_statusbar_text_format".to_owned(),{
|
||||||
let es = event_sender.clone();
|
let es = event_sender.clone();
|
||||||
let update = Arc::clone(&self.updated_statusbar_text_format);
|
let update = Arc::clone(&self.updated_statusbar_text_format);
|
||||||
Data::new(mers_lib::data::function::Function {
|
musicdb_mers::mers_lib::data::function::Function::new_generic(
|
||||||
info: Arc::new(mers_lib::info::Info::neverused()),
|
|a| {
|
||||||
info_check: Arc::new(Mutex::new(mers_lib::info::Info::neverused())),
|
if a.is_included_in_single(&musicdb_mers::mers_lib::data::string::StringT) {
|
||||||
out: Arc::new(|a, _| {
|
|
||||||
if a.is_included_in(&mers_lib::data::string::StringT) {
|
|
||||||
Ok(Type::newm(vec![
|
Ok(Type::newm(vec![
|
||||||
Arc::new(mers_lib::data::tuple::TupleT(vec![])),
|
Arc::new(musicdb_mers::mers_lib::data::tuple::TupleT(vec![])),
|
||||||
Arc::new(mers_lib::data::string::StringT),
|
Arc::new(musicdb_mers::mers_lib::data::string::StringT),
|
||||||
]))
|
]))
|
||||||
} else {
|
} else {
|
||||||
Err(format!("Can't call `set_statusbar_text_format` with argument of type `{a}` (must be `String`).").into())
|
Err(format!("Can't call `set_statusbar_text_format` with argument of type `{a}` (must be `String`).").into())
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
run: Arc::new(move |a, _| {
|
move |a, _| {
|
||||||
let a = a.get();
|
let a = a.get();
|
||||||
let o = match a.as_any().downcast_ref::<mers_lib::data::string::String>().unwrap().0.parse() {
|
let o = match a.as_any().downcast_ref::<musicdb_mers::mers_lib::data::string::String>().unwrap().0.parse() {
|
||||||
Ok(v) => {
|
Ok(v) => {
|
||||||
update.update(v);
|
update.update(v);
|
||||||
Data::empty_tuple()
|
Data::empty_tuple()
|
||||||
}
|
}
|
||||||
Err(e) => mers_lib::data::Data::new(mers_lib::data::string::String(e.to_string())),
|
Err(e) => musicdb_mers::mers_lib::data::Data::new(musicdb_mers::mers_lib::data::string::String(e.to_string())),
|
||||||
};
|
};
|
||||||
es.send_event(GuiEvent::Refresh).unwrap();
|
es.send_event(GuiEvent::Refresh).unwrap();
|
||||||
o
|
Ok(o)
|
||||||
}),
|
},
|
||||||
inner_statements: None,
|
)
|
||||||
})
|
|
||||||
})
|
})
|
||||||
.add_var("set_idle_screen_top_text_format".to_owned(),{
|
.add_var("set_idle_screen_top_text_format".to_owned(),{
|
||||||
let es = event_sender.clone();
|
let es = event_sender.clone();
|
||||||
let update = Arc::clone(&self.updated_idle_screen_top_text_format);
|
let update = Arc::clone(&self.updated_idle_screen_top_text_format);
|
||||||
Data::new(mers_lib::data::function::Function {
|
musicdb_mers::mers_lib::data::function::Function::new_generic(
|
||||||
info: Arc::new(mers_lib::info::Info::neverused()),
|
|a| {
|
||||||
info_check: Arc::new(Mutex::new(mers_lib::info::Info::neverused())),
|
if a.is_included_in_single(&musicdb_mers::mers_lib::data::string::StringT) {
|
||||||
out: Arc::new(|a, _| {
|
|
||||||
if a.is_included_in(&mers_lib::data::string::StringT) {
|
|
||||||
Ok(Type::newm(vec![
|
Ok(Type::newm(vec![
|
||||||
Arc::new(mers_lib::data::tuple::TupleT(vec![])),
|
Arc::new(musicdb_mers::mers_lib::data::tuple::TupleT(vec![])),
|
||||||
Arc::new(mers_lib::data::string::StringT),
|
Arc::new(musicdb_mers::mers_lib::data::string::StringT),
|
||||||
]))
|
]))
|
||||||
} else {
|
} else {
|
||||||
Err(format!("Can't call `set_idle_screen_top_text_format` with argument of type `{a}` (must be `String`).").into())
|
Err(format!("Can't call `set_idle_screen_top_text_format` with argument of type `{a}` (must be `String`).").into())
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
run: Arc::new(move |a, _| {
|
move |a, _| {
|
||||||
let a = a.get();
|
let a = a.get();
|
||||||
let o = match a.as_any().downcast_ref::<mers_lib::data::string::String>().unwrap().0.parse() {
|
let o = match a.as_any().downcast_ref::<musicdb_mers::mers_lib::data::string::String>().unwrap().0.parse() {
|
||||||
Ok(v) => {
|
Ok(v) => {
|
||||||
update.update(v);
|
update.update(v);
|
||||||
Data::empty_tuple()
|
Data::empty_tuple()
|
||||||
}
|
}
|
||||||
Err(e) => mers_lib::data::Data::new(mers_lib::data::string::String(e.to_string())),
|
Err(e) => musicdb_mers::mers_lib::data::Data::new(musicdb_mers::mers_lib::data::string::String(e.to_string())),
|
||||||
};
|
};
|
||||||
es.send_event(GuiEvent::Refresh).unwrap();
|
es.send_event(GuiEvent::Refresh).unwrap();
|
||||||
o
|
Ok(o)
|
||||||
}),
|
},
|
||||||
inner_statements: None,
|
)
|
||||||
})
|
|
||||||
}).add_var("set_idle_screen_side_text_1_format".to_owned(),{
|
}).add_var("set_idle_screen_side_text_1_format".to_owned(),{
|
||||||
let es = event_sender.clone();
|
let es = event_sender.clone();
|
||||||
let update = Arc::clone(&self.updated_idle_screen_side_text_1_format);
|
let update = Arc::clone(&self.updated_idle_screen_side_text_1_format);
|
||||||
Data::new(mers_lib::data::function::Function {
|
musicdb_mers::mers_lib::data::function::Function::new_generic(
|
||||||
info: Arc::new(mers_lib::info::Info::neverused()),
|
|a| {
|
||||||
info_check: Arc::new(Mutex::new(mers_lib::info::Info::neverused())),
|
if a.is_included_in_single(&musicdb_mers::mers_lib::data::string::StringT) {
|
||||||
out: Arc::new(|a, _| {
|
|
||||||
if a.is_included_in(&mers_lib::data::string::StringT) {
|
|
||||||
Ok(Type::newm(vec![
|
Ok(Type::newm(vec![
|
||||||
Arc::new(mers_lib::data::tuple::TupleT(vec![])),
|
Arc::new(musicdb_mers::mers_lib::data::tuple::TupleT(vec![])),
|
||||||
Arc::new(mers_lib::data::string::StringT),
|
Arc::new(musicdb_mers::mers_lib::data::string::StringT),
|
||||||
]))
|
]))
|
||||||
} else {
|
} else {
|
||||||
Err(format!("Can't call `set_idle_screen_side_text_1_format` with argument of type `{a}` (must be `String`).").into())
|
Err(format!("Can't call `set_idle_screen_side_text_1_format` with argument of type `{a}` (must be `String`).").into())
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
run: Arc::new(move |a, _| {
|
move |a, _| {
|
||||||
let a = a.get();
|
let a = a.get();
|
||||||
let o = match a.as_any().downcast_ref::<mers_lib::data::string::String>().unwrap().0.parse() {
|
let o = match a.as_any().downcast_ref::<musicdb_mers::mers_lib::data::string::String>().unwrap().0.parse() {
|
||||||
Ok(v) => {
|
Ok(v) => {
|
||||||
update.update(v);
|
update.update(v);
|
||||||
Data::empty_tuple()
|
Data::empty_tuple()
|
||||||
}
|
}
|
||||||
Err(e) => mers_lib::data::Data::new(mers_lib::data::string::String(e.to_string())),
|
Err(e) => musicdb_mers::mers_lib::data::Data::new(musicdb_mers::mers_lib::data::string::String(e.to_string())),
|
||||||
};
|
};
|
||||||
es.send_event(GuiEvent::Refresh).unwrap();
|
es.send_event(GuiEvent::Refresh).unwrap();
|
||||||
o
|
Ok(o)
|
||||||
}),
|
},
|
||||||
inner_statements: None,
|
)
|
||||||
})
|
|
||||||
}).add_var("set_idle_screen_side_text_2_format".to_owned(),{
|
}).add_var("set_idle_screen_side_text_2_format".to_owned(),{
|
||||||
let es = event_sender.clone();
|
let es = event_sender.clone();
|
||||||
let update = Arc::clone(&self.updated_idle_screen_side_text_2_format);
|
let update = Arc::clone(&self.updated_idle_screen_side_text_2_format);
|
||||||
Data::new(mers_lib::data::function::Function {
|
musicdb_mers::mers_lib::data::function::Function::new_generic(
|
||||||
info: Arc::new(mers_lib::info::Info::neverused()),
|
|a| {
|
||||||
info_check: Arc::new(Mutex::new(mers_lib::info::Info::neverused())),
|
if a.is_included_in_single(&musicdb_mers::mers_lib::data::string::StringT) {
|
||||||
out: Arc::new(|a, _| {
|
|
||||||
if a.is_included_in(&mers_lib::data::string::StringT) {
|
|
||||||
Ok(Type::newm(vec![
|
Ok(Type::newm(vec![
|
||||||
Arc::new(mers_lib::data::tuple::TupleT(vec![])),
|
Arc::new(musicdb_mers::mers_lib::data::tuple::TupleT(vec![])),
|
||||||
Arc::new(mers_lib::data::string::StringT),
|
Arc::new(musicdb_mers::mers_lib::data::string::StringT),
|
||||||
]))
|
]))
|
||||||
} else {
|
} else {
|
||||||
Err(format!("Can't call `set_idle_screen_side_text_2_format` with argument of type `{a}` (must be `String`).").into())
|
Err(format!("Can't call `set_idle_screen_side_text_2_format` with argument of type `{a}` (must be `String`).").into())
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
run: Arc::new(move |a, _| {
|
move |a, _| {
|
||||||
let a = a.get();
|
let a = a.get();
|
||||||
let o = match a.as_any().downcast_ref::<mers_lib::data::string::String>().unwrap().0.parse() {
|
let o = match a.as_any().downcast_ref::<musicdb_mers::mers_lib::data::string::String>().unwrap().0.parse() {
|
||||||
Ok(v) => {
|
Ok(v) => {
|
||||||
update.update(v);
|
update.update(v);
|
||||||
Data::empty_tuple()
|
Data::empty_tuple()
|
||||||
}
|
}
|
||||||
Err(e) => mers_lib::data::Data::new(mers_lib::data::string::String(e.to_string())),
|
Err(e) => musicdb_mers::mers_lib::data::Data::new(musicdb_mers::mers_lib::data::string::String(e.to_string())),
|
||||||
};
|
};
|
||||||
es.send_event(GuiEvent::Refresh).unwrap();
|
es.send_event(GuiEvent::Refresh).unwrap();
|
||||||
o
|
Ok(o)
|
||||||
}),
|
},
|
||||||
inner_statements: None,
|
)
|
||||||
})
|
|
||||||
})
|
})
|
||||||
// .add_type("Song".to_owned(), Ok(Arc::new(mers_lib::data::object::ObjectT(vec![
|
// .add_type("Song".to_owned(), Ok(Arc::new(musicdb_mers::mers_lib::data::object::ObjectT(vec![
|
||||||
// ("id".to_owned(), Type::new(mers_lib::data::int::IntT)),
|
// ("id".to_owned(), Type::new(musicdb_mers::mers_lib::data::int::IntT)),
|
||||||
// ("title".to_owned(), Type::new(mers_lib::data::string::StringT)),
|
// ("title".to_owned(), Type::new(musicdb_mers::mers_lib::data::string::StringT)),
|
||||||
// ("album".to_owned(), Type::new(mers_lib::data::string::StringT)),
|
// ("album".to_owned(), Type::new(musicdb_mers::mers_lib::data::string::StringT)),
|
||||||
// ("artist".to_owned(), Type::new(mers_lib::data::string::StringT)),
|
// ("artist".to_owned(), Type::new(musicdb_mers::mers_lib::data::string::StringT)),
|
||||||
// ]))))
|
// ]))))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn run(gui_cfg: &mut GuiConfig, gui: &mut Gui, run: impl FnOnce(&Self) -> &OptFunc) {
|
pub fn run(gui_cfg: &mut GuiConfig, gui: &mut Gui, run: impl FnOnce(&Self) -> &OptFunc) {
|
||||||
{
|
// prepare vars
|
||||||
let mut db = gui_cfg.merscfg.database.lock().unwrap();
|
|
||||||
let db = &mut db;
|
|
||||||
// prepare vars
|
|
||||||
*gui_cfg.merscfg.var_is_playing.write().unwrap() =
|
|
||||||
mers_lib::data::Data::new(mers_lib::data::bool::Bool(db.playing));
|
|
||||||
}
|
|
||||||
*gui_cfg.merscfg.var_window_size_in_pixels.write().unwrap() =
|
*gui_cfg.merscfg.var_window_size_in_pixels.write().unwrap() =
|
||||||
mers_lib::data::Data::new(mers_lib::data::tuple::Tuple(vec![
|
musicdb_mers::mers_lib::data::Data::new(musicdb_mers::mers_lib::data::tuple::Tuple(
|
||||||
mers_lib::data::Data::new(mers_lib::data::int::Int(gui.size.x as _)),
|
vec![
|
||||||
mers_lib::data::Data::new(mers_lib::data::int::Int(gui.size.y as _)),
|
musicdb_mers::mers_lib::data::Data::new(
|
||||||
]));
|
musicdb_mers::mers_lib::data::int::Int(gui.size.x as _),
|
||||||
|
),
|
||||||
|
musicdb_mers::mers_lib::data::Data::new(
|
||||||
|
musicdb_mers::mers_lib::data::int::Int(gui.size.y as _),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
));
|
||||||
*gui_cfg
|
*gui_cfg
|
||||||
.merscfg
|
.merscfg
|
||||||
.var_idle_screen_cover_aspect_ratio
|
.var_idle_screen_cover_aspect_ratio
|
||||||
.write()
|
.write()
|
||||||
.unwrap() = mers_lib::data::Data::new(mers_lib::data::float::Float(
|
.unwrap() =
|
||||||
gui.gui.c_idle_display.cover_aspect_ratio.value as _,
|
musicdb_mers::mers_lib::data::Data::new(musicdb_mers::mers_lib::data::float::Float(
|
||||||
));
|
gui.gui.c_idle_display.cover_aspect_ratio.value as _,
|
||||||
|
));
|
||||||
|
|
||||||
// run
|
// run
|
||||||
run(&gui_cfg.merscfg).run();
|
run(&gui_cfg.merscfg).run();
|
||||||
@ -707,12 +663,14 @@ impl MersCfg {
|
|||||||
>,
|
>,
|
||||||
after_db_cmd: &Arc<Mutex<Option<Box<dyn FnMut(Command) + Send + Sync + 'static>>>>,
|
after_db_cmd: &Arc<Mutex<Option<Box<dyn FnMut(Command) + Send + Sync + 'static>>>>,
|
||||||
) -> std::io::Result<Result<Result<(), (String, Option<CheckError>)>, CheckError>> {
|
) -> std::io::Result<Result<Result<(), (String, Option<CheckError>)>, CheckError>> {
|
||||||
let src = mers_lib::prelude_compile::Source::new_from_file(self.source_file.clone())?;
|
let src = musicdb_mers::mers_lib::prelude_compile::Source::new_from_file(
|
||||||
|
self.source_file.clone(),
|
||||||
|
)?;
|
||||||
Ok(self.load2(src, event_sender, notif_sender, after_db_cmd))
|
Ok(self.load2(src, event_sender, notif_sender, after_db_cmd))
|
||||||
}
|
}
|
||||||
fn load2(
|
fn load2(
|
||||||
&mut self,
|
&mut self,
|
||||||
mut src: mers_lib::prelude_compile::Source,
|
mut src: musicdb_mers::mers_lib::prelude_compile::Source,
|
||||||
event_sender: Arc<UserEventSender<GuiEvent>>,
|
event_sender: Arc<UserEventSender<GuiEvent>>,
|
||||||
notif_sender: Sender<
|
notif_sender: Sender<
|
||||||
Box<dyn FnOnce(&NotifOverlay) -> (Box<dyn GuiElem>, NotifInfo) + Send>,
|
Box<dyn FnOnce(&NotifOverlay) -> (Box<dyn GuiElem>, NotifInfo) + Send>,
|
||||||
@ -722,24 +680,27 @@ impl MersCfg {
|
|||||||
let srca = Arc::new(src.clone());
|
let srca = Arc::new(src.clone());
|
||||||
let (mut i1, mut i2, mut i3) = self
|
let (mut i1, mut i2, mut i3) = self
|
||||||
.custom_globals(
|
.custom_globals(
|
||||||
mers_lib::prelude_extend_config::Config::new().bundle_std(),
|
musicdb_mers::mers_lib::prelude_extend_config::Config::new().bundle_std(),
|
||||||
&self.database,
|
&self.database,
|
||||||
event_sender,
|
event_sender,
|
||||||
notif_sender,
|
notif_sender,
|
||||||
after_db_cmd,
|
after_db_cmd,
|
||||||
)
|
)
|
||||||
.infos();
|
.infos();
|
||||||
let compiled = mers_lib::prelude_compile::parse(&mut src, &srca)?
|
let compiled = musicdb_mers::mers_lib::prelude_compile::parse(&mut src, &srca)?
|
||||||
.compile(&mut i1, CompInfo::default())?;
|
.compile(&mut i1, Default::default())?;
|
||||||
let _ = compiled.check(&mut i3, None)?;
|
let _ = compiled.check(&mut i3, None)?;
|
||||||
let out = compiled.run(&mut i2);
|
let out = compiled.run(&mut i2)?;
|
||||||
Ok(self.load3(out))
|
Ok(self.load3(out))
|
||||||
}
|
}
|
||||||
fn load3(&mut self, out: mers_lib::data::Data) -> Result<(), (String, Option<CheckError>)> {
|
fn load3(
|
||||||
|
&mut self,
|
||||||
|
out: musicdb_mers::mers_lib::data::Data,
|
||||||
|
) -> Result<(), (String, Option<CheckError>)> {
|
||||||
if let Some(obj) = out
|
if let Some(obj) = out
|
||||||
.get()
|
.get()
|
||||||
.as_any()
|
.as_any()
|
||||||
.downcast_ref::<mers_lib::data::object::Object>()
|
.downcast_ref::<musicdb_mers::mers_lib::data::object::Object>()
|
||||||
{
|
{
|
||||||
for (name, val) in obj.0.iter() {
|
for (name, val) in obj.0.iter() {
|
||||||
let name = name.as_str();
|
let name = name.as_str();
|
||||||
@ -759,7 +720,7 @@ impl MersCfg {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return Err((format!("mers config file must return an object!"), None));
|
return Err((String::from("mers config file must return an object! (optional) fields of the object: `before_draw`, `library_updated`, `queue_updated`."), None));
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -767,12 +728,12 @@ impl MersCfg {
|
|||||||
|
|
||||||
fn check_handler(
|
fn check_handler(
|
||||||
name: &str,
|
name: &str,
|
||||||
val: &mers_lib::data::Data,
|
val: &musicdb_mers::mers_lib::data::Data,
|
||||||
) -> Result<mers_lib::data::function::Function, (String, Option<CheckError>)> {
|
) -> Result<musicdb_mers::mers_lib::data::function::Function, (String, Option<CheckError>)> {
|
||||||
if let Some(func) = val
|
if let Some(func) = val
|
||||||
.get()
|
.get()
|
||||||
.as_any()
|
.as_any()
|
||||||
.downcast_ref::<mers_lib::data::function::Function>()
|
.downcast_ref::<musicdb_mers::mers_lib::data::function::Function>()
|
||||||
{
|
{
|
||||||
match func.check(&Type::empty_tuple()) {
|
match func.check(&Type::empty_tuple()) {
|
||||||
Ok(_) => Ok(func.clone()),
|
Ok(_) => Ok(func.clone()),
|
||||||
@ -787,36 +748,42 @@ fn gen_set_pos_func(
|
|||||||
name: &'static str,
|
name: &'static str,
|
||||||
es: Arc<UserEventSender<GuiEvent>>,
|
es: Arc<UserEventSender<GuiEvent>>,
|
||||||
update: Arc<Updatable<Rectangle>>,
|
update: Arc<Updatable<Rectangle>>,
|
||||||
) -> Data {
|
) -> musicdb_mers::mers_lib::data::function::Function {
|
||||||
Data::new(mers_lib::data::function::Function {
|
musicdb_mers::mers_lib::data::function::Function::new_generic(
|
||||||
info: Arc::new(mers_lib::info::Info::neverused()),
|
move |a| {
|
||||||
info_check: Arc::new(Mutex::new(mers_lib::info::Info::neverused())),
|
if a.is_included_in(&musicdb_mers::mers_lib::data::Type::newm(vec![Arc::new(
|
||||||
out: Arc::new(move |a, _| {
|
musicdb_mers::mers_lib::data::tuple::TupleT(vec![
|
||||||
if a.is_included_in(&mers_lib::data::Type::newm(vec![Arc::new(
|
musicdb_mers::mers_lib::data::Type::new(
|
||||||
mers_lib::data::tuple::TupleT(vec![
|
musicdb_mers::mers_lib::data::float::FloatT,
|
||||||
mers_lib::data::Type::new(mers_lib::data::float::FloatT),
|
),
|
||||||
mers_lib::data::Type::new(mers_lib::data::float::FloatT),
|
musicdb_mers::mers_lib::data::Type::new(
|
||||||
mers_lib::data::Type::new(mers_lib::data::float::FloatT),
|
musicdb_mers::mers_lib::data::float::FloatT,
|
||||||
mers_lib::data::Type::new(mers_lib::data::float::FloatT),
|
),
|
||||||
|
musicdb_mers::mers_lib::data::Type::new(
|
||||||
|
musicdb_mers::mers_lib::data::float::FloatT,
|
||||||
|
),
|
||||||
|
musicdb_mers::mers_lib::data::Type::new(
|
||||||
|
musicdb_mers::mers_lib::data::float::FloatT,
|
||||||
|
),
|
||||||
]),
|
]),
|
||||||
)])) {
|
)])) {
|
||||||
Ok(Type::empty_tuple())
|
Ok(Type::empty_tuple())
|
||||||
} else {
|
} else {
|
||||||
Err(format!("Can't call `{name}` with argument of type `{a}` (must be `(Float, Float, Float, Float)`).").into())
|
Err(format!("Can't call `{name}` with argument of type `{a}` (must be `(Float, Float, Float, Float)`).").into())
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
run: Arc::new(move |a, _| {
|
move |a, _| {
|
||||||
let a = a.get();
|
let a = a.get();
|
||||||
let mut vals = a
|
let mut vals = a
|
||||||
.as_any()
|
.as_any()
|
||||||
.downcast_ref::<mers_lib::data::tuple::Tuple>()
|
.downcast_ref::<musicdb_mers::mers_lib::data::tuple::Tuple>()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.0
|
.0
|
||||||
.iter()
|
.iter()
|
||||||
.map(|v| {
|
.map(|v| {
|
||||||
v.get()
|
v.get()
|
||||||
.as_any()
|
.as_any()
|
||||||
.downcast_ref::<mers_lib::data::float::Float>()
|
.downcast_ref::<musicdb_mers::mers_lib::data::float::Float>()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.0
|
.0
|
||||||
});
|
});
|
||||||
@ -825,10 +792,9 @@ fn gen_set_pos_func(
|
|||||||
(vals.next().unwrap() as _, vals.next().unwrap() as _),
|
(vals.next().unwrap() as _, vals.next().unwrap() as _),
|
||||||
));
|
));
|
||||||
es.send_event(GuiEvent::Refresh).unwrap();
|
es.send_event(GuiEvent::Refresh).unwrap();
|
||||||
Data::empty_tuple()
|
Ok(Data::empty_tuple())
|
||||||
}),
|
},
|
||||||
inner_statements: None,
|
)
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Updatable<T> {
|
pub struct Updatable<T> {
|
||||||
|
@ -6,5 +6,5 @@ edition = "2021"
|
|||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
mers_lib = { version = "0.9.1", features = ["ecolor-term"] }
|
||||||
musicdb-lib = { version = "0.1.0", path = "../musicdb-lib" }
|
musicdb-lib = { version = "0.1.0", path = "../musicdb-lib" }
|
||||||
mers_lib = "0.3.4"
|
|
||||||
|
@ -3,9 +3,10 @@ use std::{
|
|||||||
sync::{Arc, Mutex, RwLock},
|
sync::{Arc, Mutex, RwLock},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub use mers_lib;
|
||||||
|
|
||||||
use mers_lib::{
|
use mers_lib::{
|
||||||
data::{self, function::Function, Data, MersData, MersType, Type},
|
data::{self, function::Function, Data, MersData, MersType, Type},
|
||||||
info::Info,
|
|
||||||
prelude_extend_config::Config,
|
prelude_extend_config::Config,
|
||||||
};
|
};
|
||||||
use musicdb_lib::{
|
use musicdb_lib::{
|
||||||
@ -25,17 +26,6 @@ pub fn add(
|
|||||||
cmd: &Arc<impl Fn(Command) + Sync + Send + 'static>,
|
cmd: &Arc<impl Fn(Command) + Sync + Send + 'static>,
|
||||||
after_db_cmd: &Arc<Mutex<Option<Box<dyn FnMut(Command) + Send + Sync + 'static>>>>,
|
after_db_cmd: &Arc<Mutex<Option<Box<dyn FnMut(Command) + Send + Sync + 'static>>>>,
|
||||||
) -> Config {
|
) -> Config {
|
||||||
macro_rules! func {
|
|
||||||
($out:expr, $run:expr) => {
|
|
||||||
Data::new(data::function::Function {
|
|
||||||
info: Arc::new(Info::neverused()),
|
|
||||||
info_check: Arc::new(Mutex::new(Info::neverused())),
|
|
||||||
out: Arc::new($out),
|
|
||||||
run: Arc::new($run),
|
|
||||||
inner_statements: None,
|
|
||||||
})
|
|
||||||
};
|
|
||||||
}
|
|
||||||
/// handle commands received from server (for handler functions)
|
/// handle commands received from server (for handler functions)
|
||||||
/// `T` can be used to return generated data to avoid calculating something twice if one event may call multiple handlers.
|
/// `T` can be used to return generated data to avoid calculating something twice if one event may call multiple handlers.
|
||||||
fn handle<T>(
|
fn handle<T>(
|
||||||
@ -50,7 +40,7 @@ pub fn add(
|
|||||||
.downcast_ref::<Function>()
|
.downcast_ref::<Function>()
|
||||||
{
|
{
|
||||||
let (data, t) = gen();
|
let (data, t) = gen();
|
||||||
Some((t, func.run(data)))
|
Some((t, func.run_immut(data).ok()?))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
@ -143,7 +133,7 @@ pub fn add(
|
|||||||
// MusicDb type
|
// MusicDb type
|
||||||
cfg = cfg
|
cfg = cfg
|
||||||
.with_list()
|
.with_list()
|
||||||
.add_type(MusicDbIdT.to_string(), Ok(Arc::new(MusicDbIdT)));
|
.add_type(MusicDbIdT.to_string(), Ok(Arc::new(Type::new(MusicDbIdT))));
|
||||||
// handler setters
|
// handler setters
|
||||||
for (name, handler, in_type) in [
|
for (name, handler, in_type) in [
|
||||||
("resume", handler_resume, Type::empty_tuple()),
|
("resume", handler_resume, Type::empty_tuple()),
|
||||||
@ -166,15 +156,13 @@ pub fn add(
|
|||||||
] {
|
] {
|
||||||
cfg = cfg.add_var(
|
cfg = cfg.add_var(
|
||||||
format!("handle_event_{name}"),
|
format!("handle_event_{name}"),
|
||||||
func!(
|
Function::new_generic(
|
||||||
move |a, _| {
|
move |a| {
|
||||||
if a.types.iter().all(|a| {
|
if a.types.iter().all(|a| {
|
||||||
Type::newm(vec![Arc::clone(a)]).is_zero_tuple()
|
Type::newm(vec![Arc::clone(a)]).is_zero_tuple()
|
||||||
|| a.as_any()
|
|| a.as_any()
|
||||||
.downcast_ref::<data::function::FunctionT>()
|
.downcast_ref::<data::function::FunctionT>()
|
||||||
.is_some_and(|a| {
|
.is_some_and(|a| a.o(&in_type).is_ok_and(|opt| opt.is_zero_tuple()))
|
||||||
(a.0)(&in_type).is_ok_and(|opt| opt.is_zero_tuple())
|
|
||||||
})
|
|
||||||
}) {
|
}) {
|
||||||
Ok(Type::empty_tuple())
|
Ok(Type::empty_tuple())
|
||||||
} else {
|
} else {
|
||||||
@ -183,17 +171,17 @@ pub fn add(
|
|||||||
},
|
},
|
||||||
move |a, _| {
|
move |a, _| {
|
||||||
*handler.write().unwrap() = a;
|
*handler.write().unwrap() = a;
|
||||||
Data::empty_tuple()
|
Ok(Data::empty_tuple())
|
||||||
}
|
},
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
// actions
|
// actions
|
||||||
cfg.add_var(
|
cfg.add_var(
|
||||||
"send_server_notification".to_owned(),
|
"send_server_notification".to_owned(),
|
||||||
func!(
|
Function::new_generic(
|
||||||
|a, _| {
|
|a| {
|
||||||
if a.is_included_in(&data::string::StringT) {
|
if a.is_included_in_single(&data::string::StringT) {
|
||||||
Ok(Type::empty_tuple())
|
Ok(Type::empty_tuple())
|
||||||
} else {
|
} else {
|
||||||
Err(format!("Function argument must be `String`.").into())
|
Err(format!("Function argument must be `String`.").into())
|
||||||
@ -211,15 +199,15 @@ pub fn add(
|
|||||||
.0
|
.0
|
||||||
.clone(),
|
.clone(),
|
||||||
));
|
));
|
||||||
Data::empty_tuple()
|
Ok(Data::empty_tuple())
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
.add_var(
|
.add_var(
|
||||||
"resume".to_owned(),
|
"resume".to_owned(),
|
||||||
func!(
|
Function::new_generic(
|
||||||
|a, _| {
|
|a| {
|
||||||
if a.is_included_in(&Type::empty_tuple()) {
|
if a.is_included_in(&Type::empty_tuple()) {
|
||||||
Ok(Type::empty_tuple())
|
Ok(Type::empty_tuple())
|
||||||
} else {
|
} else {
|
||||||
@ -230,15 +218,15 @@ pub fn add(
|
|||||||
let cmd = Arc::clone(cmd);
|
let cmd = Arc::clone(cmd);
|
||||||
move |_, _| {
|
move |_, _| {
|
||||||
cmd(Command::Resume);
|
cmd(Command::Resume);
|
||||||
Data::empty_tuple()
|
Ok(Data::empty_tuple())
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
.add_var(
|
.add_var(
|
||||||
"pause".to_owned(),
|
"pause".to_owned(),
|
||||||
func!(
|
Function::new_generic(
|
||||||
|a, _| {
|
|a| {
|
||||||
if a.is_included_in(&Type::empty_tuple()) {
|
if a.is_included_in(&Type::empty_tuple()) {
|
||||||
Ok(Type::empty_tuple())
|
Ok(Type::empty_tuple())
|
||||||
} else {
|
} else {
|
||||||
@ -249,15 +237,15 @@ pub fn add(
|
|||||||
let cmd = Arc::clone(cmd);
|
let cmd = Arc::clone(cmd);
|
||||||
move |_, _| {
|
move |_, _| {
|
||||||
cmd(Command::Pause);
|
cmd(Command::Pause);
|
||||||
Data::empty_tuple()
|
Ok(Data::empty_tuple())
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
.add_var(
|
.add_var(
|
||||||
"stop_playback".to_owned(),
|
"stop".to_owned(),
|
||||||
func!(
|
Function::new_generic(
|
||||||
|a, _| {
|
|a| {
|
||||||
if a.is_included_in(&Type::empty_tuple()) {
|
if a.is_included_in(&Type::empty_tuple()) {
|
||||||
Ok(Type::empty_tuple())
|
Ok(Type::empty_tuple())
|
||||||
} else {
|
} else {
|
||||||
@ -268,15 +256,15 @@ pub fn add(
|
|||||||
let cmd = Arc::clone(cmd);
|
let cmd = Arc::clone(cmd);
|
||||||
move |_, _| {
|
move |_, _| {
|
||||||
cmd(Command::Stop);
|
cmd(Command::Stop);
|
||||||
Data::empty_tuple()
|
Ok(Data::empty_tuple())
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
.add_var(
|
.add_var(
|
||||||
"next_song".to_owned(),
|
"next_song".to_owned(),
|
||||||
func!(
|
Function::new_generic(
|
||||||
|a, _| {
|
|a| {
|
||||||
if a.is_included_in(&Type::empty_tuple()) {
|
if a.is_included_in(&Type::empty_tuple()) {
|
||||||
Ok(Type::empty_tuple())
|
Ok(Type::empty_tuple())
|
||||||
} else {
|
} else {
|
||||||
@ -287,31 +275,31 @@ pub fn add(
|
|||||||
let cmd = Arc::clone(cmd);
|
let cmd = Arc::clone(cmd);
|
||||||
move |_, _| {
|
move |_, _| {
|
||||||
cmd(Command::NextSong);
|
cmd(Command::NextSong);
|
||||||
Data::empty_tuple()
|
Ok(Data::empty_tuple())
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
.add_var(
|
.add_var(
|
||||||
"get_playing".to_owned(),
|
"get_playing".to_owned(),
|
||||||
func!(
|
Function::new_generic(
|
||||||
|a, _| {
|
|a| {
|
||||||
if a.is_included_in(&Type::empty_tuple()) {
|
if a.is_included_in(&Type::empty_tuple()) {
|
||||||
Ok(Type::new(data::bool::BoolT))
|
Ok(data::bool::bool_type())
|
||||||
} else {
|
} else {
|
||||||
Err(format!("Function argument must be `()`.").into())
|
Err(format!("Function argument must be `()`.").into())
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
let db = Arc::clone(db);
|
let db = Arc::clone(db);
|
||||||
move |_, _| Data::new(data::bool::Bool(db.lock().unwrap().playing))
|
move |_, _| Ok(Data::new(data::bool::Bool(db.lock().unwrap().playing)))
|
||||||
}
|
},
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
.add_var(
|
.add_var(
|
||||||
"queue_get_current_song".to_owned(),
|
"queue_get_current_song".to_owned(),
|
||||||
func!(
|
Function::new_generic(
|
||||||
|a, _| {
|
|a| {
|
||||||
if a.is_included_in(&Type::empty_tuple()) {
|
if a.is_included_in(&Type::empty_tuple()) {
|
||||||
Ok(Type::newm(vec![
|
Ok(Type::newm(vec![
|
||||||
Arc::new(MusicDbIdT),
|
Arc::new(MusicDbIdT),
|
||||||
@ -323,17 +311,19 @@ pub fn add(
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
let db = Arc::clone(db);
|
let db = Arc::clone(db);
|
||||||
move |_, _| match db.lock().unwrap().queue.get_current_song() {
|
move |_, _| {
|
||||||
Some(id) => Data::new(MusicDbId(*id)),
|
Ok(match db.lock().unwrap().queue.get_current_song() {
|
||||||
None => Data::empty_tuple(),
|
Some(id) => Data::new(MusicDbId(*id)),
|
||||||
|
None => Data::empty_tuple(),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
.add_var(
|
.add_var(
|
||||||
"queue_get_next_song".to_owned(),
|
"queue_get_next_song".to_owned(),
|
||||||
func!(
|
Function::new_generic(
|
||||||
|a, _| {
|
|a| {
|
||||||
if a.is_included_in(&Type::empty_tuple()) {
|
if a.is_included_in(&Type::empty_tuple()) {
|
||||||
Ok(Type::newm(vec![
|
Ok(Type::newm(vec![
|
||||||
Arc::new(MusicDbIdT),
|
Arc::new(MusicDbIdT),
|
||||||
@ -345,21 +335,23 @@ pub fn add(
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
let db = Arc::clone(db);
|
let db = Arc::clone(db);
|
||||||
move |_, _| match db.lock().unwrap().queue.get_next_song() {
|
move |_, _| {
|
||||||
Some(id) => Data::new(MusicDbId(*id)),
|
Ok(match db.lock().unwrap().queue.get_next_song() {
|
||||||
None => Data::empty_tuple(),
|
Some(id) => Data::new(MusicDbId(*id)),
|
||||||
|
None => Data::empty_tuple(),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
.add_var(
|
.add_var(
|
||||||
"queue_get_elem".to_owned(),
|
"queue_get_elem".to_owned(),
|
||||||
func!(
|
Function::new_generic(
|
||||||
|a, _| {
|
|a| {
|
||||||
if a.is_included_in(&mers_lib::program::configs::with_list::ListT(Type::new(
|
if a.is_included_in_single(&mers_lib::program::configs::with_list::ListT(
|
||||||
data::int::IntT,
|
Type::new(data::int::IntT),
|
||||||
))) {
|
)) {
|
||||||
Ok(gen_queue_elem_type())
|
Ok(gen_queue_elem_type_or_empty_tuple())
|
||||||
} else {
|
} else {
|
||||||
Err(format!("Function argument must be `List<Int>`.").into())
|
Err(format!("Function argument must be `List<Int>`.").into())
|
||||||
}
|
}
|
||||||
@ -368,22 +360,24 @@ pub fn add(
|
|||||||
let db = Arc::clone(db);
|
let db = Arc::clone(db);
|
||||||
move |a, _| {
|
move |a, _| {
|
||||||
let a = int_list_to_usize_vec(&a);
|
let a = int_list_to_usize_vec(&a);
|
||||||
if let Some(elem) = db.lock().unwrap().queue.get_item_at_index(&a, 0) {
|
Ok(
|
||||||
gen_queue_elem(elem)
|
if let Some(elem) = db.lock().unwrap().queue.get_item_at_index(&a, 0) {
|
||||||
} else {
|
gen_queue_elem(elem)
|
||||||
Data::empty_tuple()
|
} else {
|
||||||
}
|
Data::empty_tuple()
|
||||||
|
},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
.add_var(
|
.add_var(
|
||||||
"queue_goto".to_owned(),
|
"queue_goto".to_owned(),
|
||||||
func!(
|
Function::new_generic(
|
||||||
|a, _| {
|
|a| {
|
||||||
if a.is_included_in(&mers_lib::program::configs::with_list::ListT(Type::new(
|
if a.is_included_in_single(&mers_lib::program::configs::with_list::ListT(
|
||||||
data::int::IntT,
|
Type::new(data::int::IntT),
|
||||||
))) {
|
)) {
|
||||||
Ok(Type::empty_tuple())
|
Ok(Type::empty_tuple())
|
||||||
} else {
|
} else {
|
||||||
Err(format!("Function argument must be `List<Int>`.").into())
|
Err(format!("Function argument must be `List<Int>`.").into())
|
||||||
@ -393,15 +387,15 @@ pub fn add(
|
|||||||
let cmd = Arc::clone(cmd);
|
let cmd = Arc::clone(cmd);
|
||||||
move |a, _| {
|
move |a, _| {
|
||||||
cmd(Command::QueueGoto(int_list_to_usize_vec(&a)));
|
cmd(Command::QueueGoto(int_list_to_usize_vec(&a)));
|
||||||
Data::empty_tuple()
|
Ok(Data::empty_tuple())
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
.add_var(
|
.add_var(
|
||||||
"queue_clear".to_owned(),
|
"queue_clear".to_owned(),
|
||||||
func!(
|
Function::new_generic(
|
||||||
|a, _| {
|
|a| {
|
||||||
if a.is_included_in(&Type::empty_tuple()) {
|
if a.is_included_in(&Type::empty_tuple()) {
|
||||||
Ok(Type::empty_tuple())
|
Ok(Type::empty_tuple())
|
||||||
} else {
|
} else {
|
||||||
@ -415,133 +409,134 @@ pub fn add(
|
|||||||
vec![],
|
vec![],
|
||||||
QueueContent::Folder(QueueFolder::default()).into(),
|
QueueContent::Folder(QueueFolder::default()).into(),
|
||||||
));
|
));
|
||||||
Data::empty_tuple()
|
Ok(Data::empty_tuple())
|
||||||
}
|
|
||||||
}
|
|
||||||
),
|
|
||||||
)
|
|
||||||
.add_var(
|
|
||||||
"queue_add_song".to_owned(),
|
|
||||||
func!(
|
|
||||||
|a, _| {
|
|
||||||
if a.is_included_in(&data::tuple::TupleT(vec![
|
|
||||||
Type::new(mers_lib::program::configs::with_list::ListT(Type::new(
|
|
||||||
data::int::IntT,
|
|
||||||
))),
|
|
||||||
Type::new(MusicDbIdT),
|
|
||||||
])) {
|
|
||||||
Ok(Type::empty_tuple())
|
|
||||||
} else {
|
|
||||||
Err(format!("Function argument must be `(List<Int>, MusicDbId)`.").into())
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
|
||||||
let cmd = Arc::clone(cmd);
|
|
||||||
move |a, _| {
|
|
||||||
let a = a.get();
|
|
||||||
let a = &a.as_any().downcast_ref::<data::tuple::Tuple>().unwrap().0;
|
|
||||||
let path = int_list_to_usize_vec(&a[0]);
|
|
||||||
let song_id = a[1].get().as_any().downcast_ref::<MusicDbId>().unwrap().0;
|
|
||||||
cmd(Command::QueueAdd(
|
|
||||||
path,
|
|
||||||
vec![QueueContent::Song(song_id).into()],
|
|
||||||
));
|
|
||||||
Data::empty_tuple()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
),
|
|
||||||
)
|
|
||||||
.add_var(
|
|
||||||
"queue_add_loop".to_owned(),
|
|
||||||
func!(
|
|
||||||
|a, _| {
|
|
||||||
if a.is_included_in(&data::tuple::TupleT(vec![
|
|
||||||
Type::new(mers_lib::program::configs::with_list::ListT(Type::new(
|
|
||||||
data::int::IntT,
|
|
||||||
))),
|
|
||||||
Type::new(data::int::IntT),
|
|
||||||
])) {
|
|
||||||
Ok(Type::empty_tuple())
|
|
||||||
} else {
|
|
||||||
Err(format!("Function argument must be `(List<Int>, Int)`.").into())
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
let cmd = Arc::clone(cmd);
|
|
||||||
move |a, _| {
|
|
||||||
let a = a.get();
|
|
||||||
let a = &a.as_any().downcast_ref::<data::tuple::Tuple>().unwrap().0;
|
|
||||||
let path = int_list_to_usize_vec(&a[0]);
|
|
||||||
let repeat_count = a[1]
|
|
||||||
.get()
|
|
||||||
.as_any()
|
|
||||||
.downcast_ref::<data::int::Int>()
|
|
||||||
.unwrap()
|
|
||||||
.0;
|
|
||||||
cmd(Command::QueueAdd(
|
|
||||||
path,
|
|
||||||
vec![QueueContent::Loop(
|
|
||||||
repeat_count.max(0) as _,
|
|
||||||
0,
|
|
||||||
Box::new(QueueContent::Folder(QueueFolder::default()).into()),
|
|
||||||
)
|
|
||||||
.into()],
|
|
||||||
));
|
|
||||||
Data::empty_tuple()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
),
|
|
||||||
)
|
|
||||||
.add_var(
|
|
||||||
"queue_add_folder".to_owned(),
|
|
||||||
func!(
|
|
||||||
|a, _| {
|
|
||||||
if a.is_included_in(&data::tuple::TupleT(vec![
|
|
||||||
Type::new(mers_lib::program::configs::with_list::ListT(Type::new(
|
|
||||||
data::int::IntT,
|
|
||||||
))),
|
|
||||||
Type::new(data::string::StringT),
|
|
||||||
])) {
|
|
||||||
Ok(Type::empty_tuple())
|
|
||||||
} else {
|
|
||||||
Err(format!("Function argument must be `(List<Int>, String)`.").into())
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
let cmd = Arc::clone(cmd);
|
|
||||||
move |a, _| {
|
|
||||||
let a = a.get();
|
|
||||||
let a = &a.as_any().downcast_ref::<data::tuple::Tuple>().unwrap().0;
|
|
||||||
let path = int_list_to_usize_vec(&a[0]);
|
|
||||||
let name = a[1]
|
|
||||||
.get()
|
|
||||||
.as_any()
|
|
||||||
.downcast_ref::<data::string::String>()
|
|
||||||
.unwrap()
|
|
||||||
.0
|
|
||||||
.clone();
|
|
||||||
cmd(Command::QueueAdd(
|
|
||||||
path,
|
|
||||||
vec![QueueContent::Folder(QueueFolder {
|
|
||||||
index: 0,
|
|
||||||
content: vec![],
|
|
||||||
name,
|
|
||||||
order: None,
|
|
||||||
})
|
|
||||||
.into()],
|
|
||||||
));
|
|
||||||
Data::empty_tuple()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
// TODO: `queue_add`, which takes any queue element as defined in `gen_queue_elem_type`
|
||||||
|
// .add_var(
|
||||||
|
// "queue_add_song".to_owned(),
|
||||||
|
// Function::new_generic(
|
||||||
|
// |a| {
|
||||||
|
// if a.is_included_in_single(&data::tuple::TupleT(vec![
|
||||||
|
// Type::new(mers_lib::program::configs::with_list::ListT(Type::new(
|
||||||
|
// data::int::IntT,
|
||||||
|
// ))),
|
||||||
|
// Type::new(MusicDbIdT),
|
||||||
|
// ])) {
|
||||||
|
// Ok(Type::empty_tuple())
|
||||||
|
// } else {
|
||||||
|
// Err(format!("Function argument must be `(List<Int>, MusicDbId)`.").into())
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// let cmd = Arc::clone(cmd);
|
||||||
|
// move |a, _| {
|
||||||
|
// let a = a.get();
|
||||||
|
// let a = &a.as_any().downcast_ref::<data::tuple::Tuple>().unwrap().0;
|
||||||
|
// let path = int_list_to_usize_vec(&a[0]);
|
||||||
|
// let song_id = a[1].get().as_any().downcast_ref::<MusicDbId>().unwrap().0;
|
||||||
|
// cmd(Command::QueueAdd(
|
||||||
|
// path,
|
||||||
|
// vec![QueueContent::Song(song_id).into()],
|
||||||
|
// ));
|
||||||
|
// Ok(Data::empty_tuple())
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
// ),
|
||||||
|
// )
|
||||||
|
// .add_var(
|
||||||
|
// "queue_add_loop".to_owned(),
|
||||||
|
// Function::new_generic(
|
||||||
|
// |a| {
|
||||||
|
// if a.is_included_in_single(&data::tuple::TupleT(vec![
|
||||||
|
// Type::new(mers_lib::program::configs::with_list::ListT(Type::new(
|
||||||
|
// data::int::IntT,
|
||||||
|
// ))),
|
||||||
|
// Type::new(data::int::IntT),
|
||||||
|
// ])) {
|
||||||
|
// Ok(Type::empty_tuple())
|
||||||
|
// } else {
|
||||||
|
// Err(format!("Function argument must be `(List<Int>, Int)`.").into())
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// let cmd = Arc::clone(cmd);
|
||||||
|
// move |a, _| {
|
||||||
|
// let a = a.get();
|
||||||
|
// let a = &a.as_any().downcast_ref::<data::tuple::Tuple>().unwrap().0;
|
||||||
|
// let path = int_list_to_usize_vec(&a[0]);
|
||||||
|
// let repeat_count = a[1]
|
||||||
|
// .get()
|
||||||
|
// .as_any()
|
||||||
|
// .downcast_ref::<data::int::Int>()
|
||||||
|
// .unwrap()
|
||||||
|
// .0;
|
||||||
|
// cmd(Command::QueueAdd(
|
||||||
|
// path,
|
||||||
|
// vec![QueueContent::Loop(
|
||||||
|
// repeat_count.max(0) as _,
|
||||||
|
// 0,
|
||||||
|
// Box::new(QueueContent::Folder(QueueFolder::default()).into()),
|
||||||
|
// )
|
||||||
|
// .into()],
|
||||||
|
// ));
|
||||||
|
// Ok(Data::empty_tuple())
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
// ),
|
||||||
|
// )
|
||||||
|
// .add_var(
|
||||||
|
// "queue_add_folder".to_owned(),
|
||||||
|
// Function::new_generic(
|
||||||
|
// |a| {
|
||||||
|
// if a.is_included_in_single(&data::tuple::TupleT(vec![
|
||||||
|
// Type::new(mers_lib::program::configs::with_list::ListT(Type::new(
|
||||||
|
// data::int::IntT,
|
||||||
|
// ))),
|
||||||
|
// Type::new(data::string::StringT),
|
||||||
|
// ])) {
|
||||||
|
// Ok(Type::empty_tuple())
|
||||||
|
// } else {
|
||||||
|
// Err(format!("Function argument must be `(List<Int>, String)`.").into())
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// let cmd = Arc::clone(cmd);
|
||||||
|
// move |a, _| {
|
||||||
|
// let a = a.get();
|
||||||
|
// let a = &a.as_any().downcast_ref::<data::tuple::Tuple>().unwrap().0;
|
||||||
|
// let path = int_list_to_usize_vec(&a[0]);
|
||||||
|
// let name = a[1]
|
||||||
|
// .get()
|
||||||
|
// .as_any()
|
||||||
|
// .downcast_ref::<data::string::String>()
|
||||||
|
// .unwrap()
|
||||||
|
// .0
|
||||||
|
// .clone();
|
||||||
|
// cmd(Command::QueueAdd(
|
||||||
|
// path,
|
||||||
|
// vec![QueueContent::Folder(QueueFolder {
|
||||||
|
// index: 0,
|
||||||
|
// content: vec![],
|
||||||
|
// name,
|
||||||
|
// order: None,
|
||||||
|
// })
|
||||||
|
// .into()],
|
||||||
|
// ));
|
||||||
|
// Ok(Data::empty_tuple())
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
// ),
|
||||||
|
// )
|
||||||
.add_var(
|
.add_var(
|
||||||
"all_songs".to_owned(),
|
"all_songs".to_owned(),
|
||||||
func!(
|
Function::new_generic(
|
||||||
|a, _| {
|
|a| {
|
||||||
if a.is_zero_tuple() {
|
if a.is_zero_tuple() {
|
||||||
Ok(Type::new(mers_lib::program::configs::with_list::ListT(
|
Ok(Type::new(mers_lib::program::configs::with_list::ListT(
|
||||||
gen_song_type(),
|
Type::new(gen_song_type()),
|
||||||
)))
|
)))
|
||||||
} else {
|
} else {
|
||||||
Err(format!("Function argument must be `()`.").into())
|
Err(format!("Function argument must be `()`.").into())
|
||||||
@ -550,23 +545,23 @@ pub fn add(
|
|||||||
{
|
{
|
||||||
let db = Arc::clone(db);
|
let db = Arc::clone(db);
|
||||||
move |_, _| {
|
move |_, _| {
|
||||||
Data::new(mers_lib::program::configs::with_list::List(
|
Ok(Data::new(mers_lib::program::configs::with_list::List(
|
||||||
db.lock()
|
db.lock()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.songs()
|
.songs()
|
||||||
.values()
|
.values()
|
||||||
.map(|s| Arc::new(RwLock::new(gen_song(s))))
|
.map(|s| Arc::new(RwLock::new(gen_song(s))))
|
||||||
.collect(),
|
.collect(),
|
||||||
))
|
)))
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
.add_var(
|
.add_var(
|
||||||
"get_song".to_owned(),
|
"get_song".to_owned(),
|
||||||
func!(
|
Function::new_generic(
|
||||||
|a, _| {
|
|a| {
|
||||||
if a.is_included_in(&MusicDbIdT) {
|
if a.is_included_in_single(&MusicDbIdT) {
|
||||||
Ok(Type::newm(vec![
|
Ok(Type::newm(vec![
|
||||||
Arc::new(gen_song_type()),
|
Arc::new(gen_song_type()),
|
||||||
Arc::new(data::tuple::TupleT(vec![])),
|
Arc::new(data::tuple::TupleT(vec![])),
|
||||||
@ -579,19 +574,19 @@ pub fn add(
|
|||||||
let db = Arc::clone(db);
|
let db = Arc::clone(db);
|
||||||
move |a, _| {
|
move |a, _| {
|
||||||
let id = a.get().as_any().downcast_ref::<MusicDbId>().unwrap().0;
|
let id = a.get().as_any().downcast_ref::<MusicDbId>().unwrap().0;
|
||||||
match db.lock().unwrap().get_song(&id) {
|
Ok(match db.lock().unwrap().get_song(&id) {
|
||||||
Some(song) => gen_song(song),
|
Some(song) => gen_song(song),
|
||||||
None => Data::empty_tuple(),
|
None => Data::empty_tuple(),
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
.add_var(
|
.add_var(
|
||||||
"get_album".to_owned(),
|
"get_album".to_owned(),
|
||||||
func!(
|
Function::new_generic(
|
||||||
|a, _| {
|
|a| {
|
||||||
if a.is_included_in(&MusicDbIdT) {
|
if a.is_included_in_single(&MusicDbIdT) {
|
||||||
Ok(Type::newm(vec![
|
Ok(Type::newm(vec![
|
||||||
Arc::new(gen_album_type()),
|
Arc::new(gen_album_type()),
|
||||||
Arc::new(data::tuple::TupleT(vec![])),
|
Arc::new(data::tuple::TupleT(vec![])),
|
||||||
@ -604,19 +599,19 @@ pub fn add(
|
|||||||
let db = Arc::clone(db);
|
let db = Arc::clone(db);
|
||||||
move |a, _| {
|
move |a, _| {
|
||||||
let id = a.get().as_any().downcast_ref::<MusicDbId>().unwrap().0;
|
let id = a.get().as_any().downcast_ref::<MusicDbId>().unwrap().0;
|
||||||
match db.lock().unwrap().albums().get(&id) {
|
Ok(match db.lock().unwrap().albums().get(&id) {
|
||||||
Some(album) => gen_album(album),
|
Some(album) => gen_album(album),
|
||||||
None => Data::empty_tuple(),
|
None => Data::empty_tuple(),
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
.add_var(
|
.add_var(
|
||||||
"get_artist".to_owned(),
|
"get_artist".to_owned(),
|
||||||
func!(
|
Function::new_generic(
|
||||||
|a, _| {
|
|a| {
|
||||||
if a.is_included_in(&MusicDbIdT) {
|
if a.is_included_in_single(&MusicDbIdT) {
|
||||||
Ok(Type::newm(vec![
|
Ok(Type::newm(vec![
|
||||||
Arc::new(gen_artist_type()),
|
Arc::new(gen_artist_type()),
|
||||||
Arc::new(data::tuple::TupleT(vec![])),
|
Arc::new(data::tuple::TupleT(vec![])),
|
||||||
@ -629,19 +624,19 @@ pub fn add(
|
|||||||
let db = Arc::clone(db);
|
let db = Arc::clone(db);
|
||||||
move |a, _| {
|
move |a, _| {
|
||||||
let id = a.get().as_any().downcast_ref::<MusicDbId>().unwrap().0;
|
let id = a.get().as_any().downcast_ref::<MusicDbId>().unwrap().0;
|
||||||
match db.lock().unwrap().artists().get(&id) {
|
Ok(match db.lock().unwrap().artists().get(&id) {
|
||||||
Some(artist) => gen_artist(artist),
|
Some(artist) => gen_artist(artist),
|
||||||
None => Data::empty_tuple(),
|
None => Data::empty_tuple(),
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
.add_var(
|
.add_var(
|
||||||
"get_song_tags".to_owned(),
|
"get_song_tags".to_owned(),
|
||||||
func!(
|
Function::new_generic(
|
||||||
|a, _| {
|
|a| {
|
||||||
if a.is_included_in(&MusicDbIdT) {
|
if a.is_included_in_single(&MusicDbIdT) {
|
||||||
Ok(Type::newm(vec![
|
Ok(Type::newm(vec![
|
||||||
Arc::new(mers_lib::program::configs::with_list::ListT(Type::new(
|
Arc::new(mers_lib::program::configs::with_list::ListT(Type::new(
|
||||||
data::string::StringT,
|
data::string::StringT,
|
||||||
@ -656,7 +651,7 @@ pub fn add(
|
|||||||
let db = Arc::clone(db);
|
let db = Arc::clone(db);
|
||||||
move |a, _| {
|
move |a, _| {
|
||||||
let id = a.get().as_any().downcast_ref::<MusicDbId>().unwrap().0;
|
let id = a.get().as_any().downcast_ref::<MusicDbId>().unwrap().0;
|
||||||
match db.lock().unwrap().get_song(&id) {
|
Ok(match db.lock().unwrap().get_song(&id) {
|
||||||
Some(song) => Data::new(mers_lib::program::configs::with_list::List(
|
Some(song) => Data::new(mers_lib::program::configs::with_list::List(
|
||||||
song.general
|
song.general
|
||||||
.tags
|
.tags
|
||||||
@ -669,16 +664,16 @@ pub fn add(
|
|||||||
.collect(),
|
.collect(),
|
||||||
)),
|
)),
|
||||||
None => Data::empty_tuple(),
|
None => Data::empty_tuple(),
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
.add_var(
|
.add_var(
|
||||||
"get_album_tags".to_owned(),
|
"get_album_tags".to_owned(),
|
||||||
func!(
|
Function::new_generic(
|
||||||
|a, _| {
|
|a| {
|
||||||
if a.is_included_in(&MusicDbIdT) {
|
if a.is_included_in_single(&MusicDbIdT) {
|
||||||
Ok(Type::newm(vec![
|
Ok(Type::newm(vec![
|
||||||
Arc::new(mers_lib::program::configs::with_list::ListT(Type::new(
|
Arc::new(mers_lib::program::configs::with_list::ListT(Type::new(
|
||||||
data::string::StringT,
|
data::string::StringT,
|
||||||
@ -693,7 +688,7 @@ pub fn add(
|
|||||||
let db = Arc::clone(db);
|
let db = Arc::clone(db);
|
||||||
move |a, _| {
|
move |a, _| {
|
||||||
let id = a.get().as_any().downcast_ref::<MusicDbId>().unwrap().0;
|
let id = a.get().as_any().downcast_ref::<MusicDbId>().unwrap().0;
|
||||||
match db.lock().unwrap().albums().get(&id) {
|
Ok(match db.lock().unwrap().albums().get(&id) {
|
||||||
Some(album) => Data::new(mers_lib::program::configs::with_list::List(
|
Some(album) => Data::new(mers_lib::program::configs::with_list::List(
|
||||||
album
|
album
|
||||||
.general
|
.general
|
||||||
@ -707,16 +702,16 @@ pub fn add(
|
|||||||
.collect(),
|
.collect(),
|
||||||
)),
|
)),
|
||||||
None => Data::empty_tuple(),
|
None => Data::empty_tuple(),
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
.add_var(
|
.add_var(
|
||||||
"get_artist_tags".to_owned(),
|
"get_artist_tags".to_owned(),
|
||||||
func!(
|
Function::new_generic(
|
||||||
|a, _| {
|
|a| {
|
||||||
if a.is_included_in(&MusicDbIdT) {
|
if a.is_included_in_single(&MusicDbIdT) {
|
||||||
Ok(Type::newm(vec![
|
Ok(Type::newm(vec![
|
||||||
Arc::new(mers_lib::program::configs::with_list::ListT(Type::new(
|
Arc::new(mers_lib::program::configs::with_list::ListT(Type::new(
|
||||||
data::string::StringT,
|
data::string::StringT,
|
||||||
@ -731,7 +726,7 @@ pub fn add(
|
|||||||
let db = Arc::clone(db);
|
let db = Arc::clone(db);
|
||||||
move |a, _| {
|
move |a, _| {
|
||||||
let id = a.get().as_any().downcast_ref::<MusicDbId>().unwrap().0;
|
let id = a.get().as_any().downcast_ref::<MusicDbId>().unwrap().0;
|
||||||
match db.lock().unwrap().artists().get(&id) {
|
Ok(match db.lock().unwrap().artists().get(&id) {
|
||||||
Some(artist) => Data::new(mers_lib::program::configs::with_list::List(
|
Some(artist) => Data::new(mers_lib::program::configs::with_list::List(
|
||||||
artist
|
artist
|
||||||
.general
|
.general
|
||||||
@ -745,15 +740,15 @@ pub fn add(
|
|||||||
.collect(),
|
.collect(),
|
||||||
)),
|
)),
|
||||||
None => Data::empty_tuple(),
|
None => Data::empty_tuple(),
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn gen_song_type() -> Type {
|
fn gen_song_type() -> data::object::ObjectT {
|
||||||
Type::new(data::object::ObjectT(vec![
|
data::object::ObjectT(vec![
|
||||||
("id".to_owned(), Type::new(MusicDbIdT)),
|
("id".to_owned(), Type::new(MusicDbIdT)),
|
||||||
("title".to_owned(), Type::new(data::string::StringT)),
|
("title".to_owned(), Type::new(data::string::StringT)),
|
||||||
(
|
(
|
||||||
@ -771,7 +766,7 @@ fn gen_song_type() -> Type {
|
|||||||
Arc::new(data::tuple::TupleT(vec![])),
|
Arc::new(data::tuple::TupleT(vec![])),
|
||||||
]),
|
]),
|
||||||
),
|
),
|
||||||
]))
|
])
|
||||||
}
|
}
|
||||||
fn gen_song(song: &Song) -> Data {
|
fn gen_song(song: &Song) -> Data {
|
||||||
Data::new(data::object::Object(vec![
|
Data::new(data::object::Object(vec![
|
||||||
@ -799,8 +794,8 @@ fn gen_song(song: &Song) -> Data {
|
|||||||
),
|
),
|
||||||
]))
|
]))
|
||||||
}
|
}
|
||||||
fn gen_album_type() -> Type {
|
fn gen_album_type() -> data::object::ObjectT {
|
||||||
Type::new(data::object::ObjectT(vec![
|
data::object::ObjectT(vec![
|
||||||
("id".to_owned(), Type::new(MusicDbIdT)),
|
("id".to_owned(), Type::new(MusicDbIdT)),
|
||||||
("name".to_owned(), Type::new(data::string::StringT)),
|
("name".to_owned(), Type::new(data::string::StringT)),
|
||||||
("artist".to_owned(), Type::new(MusicDbIdT)),
|
("artist".to_owned(), Type::new(MusicDbIdT)),
|
||||||
@ -817,7 +812,7 @@ fn gen_album_type() -> Type {
|
|||||||
MusicDbIdT,
|
MusicDbIdT,
|
||||||
))),
|
))),
|
||||||
),
|
),
|
||||||
]))
|
])
|
||||||
}
|
}
|
||||||
fn gen_album(album: &Album) -> Data {
|
fn gen_album(album: &Album) -> Data {
|
||||||
Data::new(data::object::Object(vec![
|
Data::new(data::object::Object(vec![
|
||||||
@ -847,8 +842,8 @@ fn gen_album(album: &Album) -> Data {
|
|||||||
),
|
),
|
||||||
]))
|
]))
|
||||||
}
|
}
|
||||||
fn gen_artist_type() -> Type {
|
fn gen_artist_type() -> data::object::ObjectT {
|
||||||
Type::new(data::object::ObjectT(vec![
|
data::object::ObjectT(vec![
|
||||||
("id".to_owned(), Type::new(MusicDbIdT)),
|
("id".to_owned(), Type::new(MusicDbIdT)),
|
||||||
("name".to_owned(), Type::new(data::string::StringT)),
|
("name".to_owned(), Type::new(data::string::StringT)),
|
||||||
(
|
(
|
||||||
@ -870,7 +865,7 @@ fn gen_artist_type() -> Type {
|
|||||||
MusicDbIdT,
|
MusicDbIdT,
|
||||||
))),
|
))),
|
||||||
),
|
),
|
||||||
]))
|
])
|
||||||
}
|
}
|
||||||
fn gen_artist(artist: &Artist) -> Data {
|
fn gen_artist(artist: &Artist) -> Data {
|
||||||
Data::new(data::object::Object(vec![
|
Data::new(data::object::Object(vec![
|
||||||
@ -910,15 +905,15 @@ fn gen_artist(artist: &Artist) -> Data {
|
|||||||
]))
|
]))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn gen_queue_elem_type() -> Type {
|
fn gen_queue_elem_type_or_empty_tuple() -> Type {
|
||||||
Type::newm(vec![
|
Type::newm(vec![
|
||||||
Arc::new(data::tuple::TupleT(vec![])),
|
Arc::new(data::tuple::TupleT(vec![])),
|
||||||
Arc::new(data::object::ObjectT(vec![
|
Arc::new(data::object::ObjectT(vec![
|
||||||
("enabled".to_owned(), Type::new(data::bool::BoolT)),
|
("enabled".to_owned(), data::bool::bool_type()),
|
||||||
("song".to_owned(), Type::new(MusicDbIdT)),
|
("song".to_owned(), Type::new(MusicDbIdT)),
|
||||||
])),
|
])),
|
||||||
Arc::new(data::object::ObjectT(vec![
|
Arc::new(data::object::ObjectT(vec![
|
||||||
("enabled".to_owned(), Type::new(data::bool::BoolT)),
|
("enabled".to_owned(), data::bool::bool_type()),
|
||||||
(
|
(
|
||||||
"loop".to_owned(),
|
"loop".to_owned(),
|
||||||
Type::new(data::object::ObjectT(vec![
|
Type::new(data::object::ObjectT(vec![
|
||||||
@ -928,11 +923,11 @@ fn gen_queue_elem_type() -> Type {
|
|||||||
),
|
),
|
||||||
])),
|
])),
|
||||||
Arc::new(data::object::ObjectT(vec![
|
Arc::new(data::object::ObjectT(vec![
|
||||||
("enabled".to_owned(), Type::new(data::bool::BoolT)),
|
("enabled".to_owned(), data::bool::bool_type()),
|
||||||
("random".to_owned(), Type::empty_tuple()),
|
("random".to_owned(), Type::empty_tuple()),
|
||||||
])),
|
])),
|
||||||
Arc::new(data::object::ObjectT(vec![
|
Arc::new(data::object::ObjectT(vec![
|
||||||
("enabled".to_owned(), Type::new(data::bool::BoolT)),
|
("enabled".to_owned(), data::bool::bool_type()),
|
||||||
(
|
(
|
||||||
"folder".to_owned(),
|
"folder".to_owned(),
|
||||||
Type::new(data::object::ObjectT(vec![
|
Type::new(data::object::ObjectT(vec![
|
||||||
@ -943,7 +938,7 @@ fn gen_queue_elem_type() -> Type {
|
|||||||
),
|
),
|
||||||
])),
|
])),
|
||||||
Arc::new(data::object::ObjectT(vec![
|
Arc::new(data::object::ObjectT(vec![
|
||||||
("enabled".to_owned(), Type::new(data::bool::BoolT)),
|
("enabled".to_owned(), data::bool::bool_type()),
|
||||||
("shuffle".to_owned(), Type::empty_tuple()),
|
("shuffle".to_owned(), Type::empty_tuple()),
|
||||||
])),
|
])),
|
||||||
])
|
])
|
||||||
@ -1038,7 +1033,7 @@ impl MersType for MusicDbIdT {
|
|||||||
fn is_same_type_as(&self, other: &dyn MersType) -> bool {
|
fn is_same_type_as(&self, other: &dyn MersType) -> bool {
|
||||||
other.as_any().is::<Self>()
|
other.as_any().is::<Self>()
|
||||||
}
|
}
|
||||||
fn is_included_in_single(&self, target: &dyn MersType) -> bool {
|
fn is_included_in(&self, target: &dyn MersType) -> bool {
|
||||||
target.as_any().is::<Self>()
|
target.as_any().is::<Self>()
|
||||||
}
|
}
|
||||||
fn subtypes(&self, acc: &mut Type) {
|
fn subtypes(&self, acc: &mut Type) {
|
||||||
|
Loading…
Reference in New Issue
Block a user