Ereigniszustellung und Hostgrenzen korrigieren und Change archivieren

This commit is contained in:
2026-09-05 19:15:31 +02:00
parent 57d6386a5a
commit 644a86212f
39 changed files with 2013 additions and 271 deletions

View File

@@ -1777,6 +1777,49 @@ impl FormsModel {
}
}
fn timer_enabled(&self, key: ObjectKey) -> bool {
self.instance(key)
.is_ok_and(|obj| obj.description.class == ObjectClass::Timer)
&& self.boolean(key, "ENABLED")
&& self.integer(key, "INTERVAL").unwrap_or(0) > 0
&& self
.root_form(key)
.is_some_and(|form| self.is_visible(form))
}
/// Zeitbedarf für Timer und gedrückt gehaltene Spin-Schaltflächen.
pub fn next_deadline(&self) -> Option<u64> {
if self.menu_is_open() || (!self.has_visible_forms() && self.spin_repeat.is_none()) {
return None;
}
let timers = self
.keys()
.into_iter()
.filter(|key| self.timer_enabled(*key))
.map(|key| {
self.timer_last
.get(&key)
.copied()
.unwrap_or(0)
.saturating_add(self.integer(key, "INTERVAL").unwrap() as u64)
});
let spin = self.spin_repeat.and_then(|(key, _)| {
let interval = self.integer(key, "INTERVAL").unwrap_or(250).max(0) as u64;
(interval > 0).then(|| {
self.spin_last
.map_or(0, |last| last.saturating_add(interval))
})
});
timers.chain(spin).min()
}
pub fn mouse_needs_time(&self, event: MausEreignis) -> bool {
self.active_form.is_some()
&& !self.menu_is_open()
&& event.art == MausArt::Loslassen
&& self.pressed.is_some()
}
pub fn timers(&mut self, now_ms: u64) {
if !self.menu_path.is_empty() {
return;
@@ -1784,15 +1827,7 @@ impl FormsModel {
let mut due: Vec<_> = self
.keys()
.into_iter()
.filter(|key| {
self.instance(*key)
.is_ok_and(|obj| obj.description.class == ObjectClass::Timer)
&& self.boolean(*key, "ENABLED")
&& self.integer(*key, "INTERVAL").unwrap_or(0) > 0
&& self
.root_form(*key)
.is_some_and(|form| self.is_visible(form))
})
.filter(|key| self.timer_enabled(*key))
.collect();
due.sort_by_key(|key| {
self.instance(*key)
@@ -2395,13 +2430,16 @@ fn dialog_event(
model: &mut FormsModel,
screen: &mut TextScreen,
host: &mut dyn Host,
queued: &mut VecDeque<Ereignis>,
queued: &mut VecDeque<tb_runtime::builtins::Eingabe>,
plain_access_key: bool,
) -> Option<FormEvent> {
loop {
model.render(screen);
host.present(screen);
let event = queued.pop_front().or_else(|| host.next_event(true))?;
let event = queued
.pop_front()
.map(|e| e.ereignis)
.or_else(|| host.next_event(true))?;
match event {
Ereignis::Taste(key, shift) => {
let shift = if plain_access_key && key.chars().count() == 1 {
@@ -2412,14 +2450,19 @@ fn dialog_event(
model.handle_key(&key, shift);
}
Ereignis::Maus(event) => {
model.handle_mouse_at(event, host.jetzt_ms());
let now = if model.mouse_needs_time(event) {
host.jetzt_ms()
} else {
0
};
model.handle_mouse_at(event, now);
}
Ereignis::Groesse { cols, rows } => {
screen.resize(cols, rows);
model.resize(cols, rows);
}
event @ (Ereignis::Abbruch | Ereignis::Ende | Ereignis::Signal(_)) => {
queued.push_front(event);
queued.push_front(event.into());
return None;
}
}
@@ -2435,7 +2478,7 @@ fn dialog_event(
pub fn msgbox_dialog(
screen: &mut TextScreen,
host: &mut dyn Host,
queued: &mut VecDeque<Ereignis>,
queued: &mut VecDeque<tb_runtime::builtins::Eingabe>,
text: &str,
kind: i32,
title: &str,
@@ -2549,7 +2592,7 @@ pub fn msgbox_dialog(
pub fn inputbox_dialog(
screen: &mut TextScreen,
host: &mut dyn Host,
queued: &mut VecDeque<Ereignis>,
queued: &mut VecDeque<tb_runtime::builtins::Eingabe>,
prompt: &str,
title: &str,
initial: &str,