Add text fixes

master
darktohka 6 days ago
parent adc456b8f6
commit 202e2c160f

105
rust/Cargo.lock generated

@ -18,12 +18,6 @@ version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "366ffbaa4442f4684d91e2cd7c5ea7c4ed8add41959a31447066e279e432b618" checksum = "366ffbaa4442f4684d91e2cd7c5ea7c4ed8add41959a31447066e279e432b618"
[[package]]
name = "adler2"
version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa"
[[package]] [[package]]
name = "aes" name = "aes"
version = "0.8.4" version = "0.8.4"
@ -83,18 +77,6 @@ version = "3.20.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb" checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb"
[[package]]
name = "bytemuck"
version = "1.25.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c8efb64bd706a16a1bdde310ae86b351e4d21550d98d056f22f8a7f7a2183fec"
[[package]]
name = "byteorder-lite"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495"
[[package]] [[package]]
name = "bzip2" name = "bzip2"
version = "0.6.1" version = "0.6.1"
@ -163,7 +145,6 @@ name = "clean_flash_ui"
version = "34.0.0" version = "34.0.0"
dependencies = [ dependencies = [
"ab_glyph", "ab_glyph",
"image",
"minifb", "minifb",
"windows-sys", "windows-sys",
] ]
@ -264,31 +245,12 @@ version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be"
[[package]]
name = "fdeflate"
version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e6853b52649d4ac5c0bd02320cddc5ba956bdb407c4b75a2c6b75bf51500f8c"
dependencies = [
"simd-adler32",
]
[[package]] [[package]]
name = "find-msvc-tools" name = "find-msvc-tools"
version = "0.1.9" version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582"
[[package]]
name = "flate2"
version = "1.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "843fba2746e448b37e26a819579957415c8cef339bf08564fe8b7ddbd959573c"
dependencies = [
"crc32fast",
"miniz_oxide",
]
[[package]] [[package]]
name = "foldhash" name = "foldhash"
version = "0.1.5" version = "0.1.5"
@ -433,19 +395,6 @@ version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954"
[[package]]
name = "image"
version = "0.25.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "85ab80394333c02fe689eaf900ab500fbd0c2213da414687ebf995a65d5a6104"
dependencies = [
"bytemuck",
"byteorder-lite",
"moxcms",
"num-traits",
"png",
]
[[package]] [[package]]
name = "indexmap" name = "indexmap"
version = "2.13.0" version = "2.13.0"
@ -604,26 +553,6 @@ dependencies = [
"x11-dl", "x11-dl",
] ]
[[package]]
name = "miniz_oxide"
version = "0.8.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316"
dependencies = [
"adler2",
"simd-adler32",
]
[[package]]
name = "moxcms"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bb85c154ba489f01b25c0d36ae69a87e4a1c73a72631fc6c0eb6dde34a73e44b"
dependencies = [
"num-traits",
"pxfm",
]
[[package]] [[package]]
name = "nix" name = "nix"
version = "0.24.3" version = "0.24.3"
@ -636,15 +565,6 @@ dependencies = [
"memoffset", "memoffset",
] ]
[[package]]
name = "num-traits"
version = "0.2.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
dependencies = [
"autocfg",
]
[[package]] [[package]]
name = "once_cell" name = "once_cell"
version = "1.21.4" version = "1.21.4"
@ -689,19 +609,6 @@ version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6" checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6"
[[package]]
name = "png"
version = "0.18.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "60769b8b31b2a9f263dae2776c37b1b28ae246943cf719eb6946a1db05128a61"
dependencies = [
"bitflags 2.11.0",
"crc32fast",
"fdeflate",
"flate2",
"miniz_oxide",
]
[[package]] [[package]]
name = "ppmd-rust" name = "ppmd-rust"
version = "1.4.0" version = "1.4.0"
@ -727,12 +634,6 @@ dependencies = [
"unicode-ident", "unicode-ident",
] ]
[[package]]
name = "pxfm"
version = "0.1.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5a041e753da8b807c9255f28de81879c78c876392ff2469cde94799b2896b9d"
[[package]] [[package]]
name = "quote" name = "quote"
version = "1.0.45" version = "1.0.45"
@ -904,12 +805,6 @@ version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
[[package]]
name = "simd-adler32"
version = "0.3.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e320a6c5ad31d271ad523dcf3ad13e2767ad8b1cb8f047f75a8aeaf8da139da2"
[[package]] [[package]]
name = "slab" name = "slab"
version = "0.4.12" version = "0.4.12"

@ -10,7 +10,6 @@ members = [
[workspace.dependencies] [workspace.dependencies]
ab_glyph = "0.2" ab_glyph = "0.2"
sevenz-rust2 = { version = "0.20", default-feaures = false, features = ["compress", "util"] } sevenz-rust2 = { version = "0.20", default-feaures = false, features = ["compress", "util"] }
image = { version = "0.25", default-features = false, features = ["png"] }
minifb = "0.28" minifb = "0.28"
windows-sys = { version = "0.61", features = [ windows-sys = { version = "0.61", features = [
"Win32_Foundation", "Win32_Foundation",

@ -23,6 +23,8 @@ pub fn delete_file(path: &Path) {
} }
// Retry loop with ownership acquisition. // Retry loop with ownership acquisition.
#[cfg(windows)]
{
for _ in 0..10 { for _ in 0..10 {
if try_take_ownership_and_delete(path) { if try_take_ownership_and_delete(path) {
return; return;
@ -34,6 +36,7 @@ pub fn delete_file(path: &Path) {
kill_locking_processes(path); kill_locking_processes(path);
thread::sleep(Duration::from_millis(500)); thread::sleep(Duration::from_millis(500));
let _ = fs::remove_file(path); let _ = fs::remove_file(path);
}
} }
/// Recursively delete all files (optionally matching `filename`) under `base_dir`. /// Recursively delete all files (optionally matching `filename`) under `base_dir`.
@ -84,11 +87,14 @@ pub fn wipe_folder(path: &Path) {
// If folder is now empty, remove it. // If folder is now empty, remove it.
if is_dir_empty(path) { if is_dir_empty(path) {
if fs::remove_dir(path).is_err() { if fs::remove_dir(path).is_err() {
#[cfg(windows)]
{
kill_locking_processes(path); kill_locking_processes(path);
thread::sleep(Duration::from_millis(500)); thread::sleep(Duration::from_millis(500));
let _ = fs::remove_dir(path); let _ = fs::remove_dir(path);
} }
} }
}
} }
fn try_clear_readonly_and_delete(path: &Path) -> bool { fn try_clear_readonly_and_delete(path: &Path) -> bool {
@ -101,6 +107,7 @@ fn try_clear_readonly_and_delete(path: &Path) -> bool {
fs::remove_file(path).is_ok() fs::remove_file(path).is_ok()
} }
#[cfg(windows)]
fn try_take_ownership_and_delete(path: &Path) -> bool { fn try_take_ownership_and_delete(path: &Path) -> bool {
use windows_sys::Win32::Foundation::{CloseHandle, LocalFree}; use windows_sys::Win32::Foundation::{CloseHandle, LocalFree};
use windows_sys::Win32::Security::{ use windows_sys::Win32::Security::{
@ -191,6 +198,7 @@ fn try_take_ownership_and_delete(path: &Path) -> bool {
try_clear_readonly_and_delete(path) try_clear_readonly_and_delete(path)
} }
#[cfg(windows)]
fn kill_locking_processes(path: &Path) { fn kill_locking_processes(path: &Path) {
use windows_sys::Win32::Foundation::CloseHandle; use windows_sys::Win32::Foundation::CloseHandle;
use windows_sys::Win32::System::RestartManager::{ use windows_sys::Win32::System::RestartManager::{

@ -13,7 +13,7 @@ pub fn run_process(program: &str, args: &[&str]) -> ExitedProcess {
.stdout(Stdio::piped()) .stdout(Stdio::piped())
.stderr(Stdio::piped()); .stderr(Stdio::piped());
#[cfg(target_os = "windows")] #[cfg(windows)]
cmd.creation_flags(CREATE_NO_WINDOW); cmd.creation_flags(CREATE_NO_WINDOW);
let result = cmd.output(); let result = cmd.output();
@ -42,7 +42,7 @@ pub fn run_unmanaged_process(program: &str, args: &[&str]) {
.stdout(Stdio::null()) .stdout(Stdio::null())
.stderr(Stdio::null()); .stderr(Stdio::null());
#[cfg(target_os = "windows")] #[cfg(windows)]
cmd.creation_flags(CREATE_NO_WINDOW); cmd.creation_flags(CREATE_NO_WINDOW);
let _ = cmd.status(); let _ = cmd.status();

@ -109,6 +109,7 @@ impl SystemInfo {
result result
} }
#[cfg(windows)]
pub fn is_legacy_windows(&self) -> bool { pub fn is_legacy_windows(&self) -> bool {
// Windows version < 6.2 (before Windows 8). // Windows version < 6.2 (before Windows 8).
unsafe { unsafe {
@ -123,14 +124,21 @@ impl SystemInfo {
|| (info.dwMajorVersion == 6 && info.dwMinorVersion < 2) || (info.dwMajorVersion == 6 && info.dwMinorVersion < 2)
} }
} }
#[cfg(not(windows))]
pub fn is_legacy_windows(&self) -> bool {
false
}
} }
#[cfg(windows)]
extern "system" { extern "system" {
fn RtlGetVersion( fn RtlGetVersion(
lp_version_information: *mut windows_sys::Win32::System::SystemInformation::OSVERSIONINFOW, lp_version_information: *mut windows_sys::Win32::System::SystemInformation::OSVERSIONINFOW,
) -> i32; ) -> i32;
} }
#[cfg(windows)]
unsafe fn rtl_get_version( unsafe fn rtl_get_version(
info: &mut windows_sys::Win32::System::SystemInformation::OSVERSIONINFOW, info: &mut windows_sys::Win32::System::SystemInformation::OSVERSIONINFOW,
) { ) {

@ -307,6 +307,7 @@ pub fn uninstall(form: &dyn ProgressCallback) -> Result<(), InstallError> {
form.update_progress_label("Stopping Flash auto-updater task...", true); form.update_progress_label("Stopping Flash auto-updater task...", true);
delete_task("Adobe Flash Player Updater"); delete_task("Adobe Flash Player Updater");
delete_task("Adobe Flash Player Updater");
form.update_progress_label("Stopping Flash auto-updater service...", true); form.update_progress_label("Stopping Flash auto-updater service...", true);
delete_service("AdobeFlashPlayerUpdateSvc"); delete_service("AdobeFlashPlayerUpdateSvc");

@ -19,14 +19,12 @@ const PANEL_X: i32 = 90;
const PANEL_Y: i32 = 162; const PANEL_Y: i32 = 162;
const DISCLAIMER_TEXT: &str = "I am aware that Adobe Flash Player is no longer supported, nor provided by Adobe Inc.\n\ const DISCLAIMER_TEXT: &str = "I am aware that Adobe Flash Player is no longer supported, nor provided by Adobe Inc.\n\
Clean Flash Player is a third-party version of Flash Player built from the latest Flash Player\n\ Clean Flash Player is a third-party version of Flash Player built from the latest Flash Player version with adware removed.\n\n\
version with adware removed.\n\n\
Adobe is not required by any means to provide support for this version of Flash Player."; Adobe is not required by any means to provide support for this version of Flash Player.";
const COMPLETE_INSTALL_TEXT: &str = "Clean Flash Player has been successfully installed!\n\ const COMPLETE_INSTALL_TEXT: &str = "Clean Flash Player has been successfully installed!\n\
Don't forget, Flash Player is no longer compatible with new browsers.\n\n\ Don't forget, Flash Player is no longer compatible with new browsers.\n\n\
For browser recommendations and Flash Player updates,\n\ For browser recommendations and Flash Player updates, check out Clean Flash Player's website!";
check out Clean Flash Player's website!";
const COMPLETE_UNINSTALL_TEXT: &str = "\nAll versions of Flash Player have been successfully uninstalled.\n\n\ const COMPLETE_UNINSTALL_TEXT: &str = "\nAll versions of Flash Player have been successfully uninstalled.\n\n\
If you ever change your mind, check out Clean Flash Player's website!"; If you ever change your mind, check out Clean Flash Player's website!";
@ -116,6 +114,7 @@ impl InstallForm {
let lbl = |x: i32, y: i32, text: &str, size: f32| { let lbl = |x: i32, y: i32, text: &str, size: f32| {
let mut l = Label::new(s(x), s(y), text, sf(size)); let mut l = Label::new(s(x), s(y), text, sf(size));
l.line_spacing = sf(2.0); l.line_spacing = sf(2.0);
l.max_width = sf((WIDTH as i32 - x - 60) as f32);
l l
}; };
// Scaled button helper. // Scaled button helper.
@ -437,8 +436,7 @@ The following details could be useful. Press the Retry button to try again.",
self.before_install_label.text = format!( self.before_install_label.text = format!(
"You are about to install Clean Flash Player.\n\ "You are about to install Clean Flash Player.\n\
Please close any browser windows running Flash content before you continue.\n\n\ Please close any browser windows running Flash content before you continue.\n\n\
The installer will close all browser windows running Flash, uninstall previous versions of Flash Player and\n\ The installer will close all browser windows running Flash, uninstall previous versions of Flash Player and Flash Center, and install Flash for {}.",
Flash Center, and install Flash for {}.",
browser_str browser_str
); );
self.next_button.text = "INSTALL".into(); self.next_button.text = "INSTALL".into();
@ -446,8 +444,7 @@ Flash Center, and install Flash for {}.",
self.before_install_label.text = self.before_install_label.text =
"You are about to uninstall Clean Flash Player.\n\ "You are about to uninstall Clean Flash Player.\n\
Please close any browser windows running Flash content before you continue.\n\n\ Please close any browser windows running Flash content before you continue.\n\n\
The installer will completely remove all versions of Flash Player from this computer,\n\ The installer will completely remove all versions of Flash Player from this computer, including Clean Flash Player and older versions of Adobe Flash Player."
including Clean Flash Player and older versions of Adobe Flash Player."
.to_string(); .to_string();
self.next_button.text = "UNINSTALL".into(); self.next_button.text = "UNINSTALL".into();
} }
@ -502,10 +499,10 @@ including Clean Flash Player and older versions of Adobe Flash Player."
redirection::enable_redirection(redir); redirection::enable_redirection(redir);
let mut state = progress.lock().unwrap(); let mut state = progress.lock().unwrap();
state.done = true;
if let Err(e) = result { if let Err(e) = result {
state.error = Some(e.to_string()); state.error = Some(e.to_string());
} }
state.done = true;
}); });
} }
@ -609,6 +606,7 @@ including Clean Flash Player and older versions of Adobe Flash Player."
self.sf(11.0), self.sf(11.0),
FG_COLOR, FG_COLOR,
self.sf(1.0), self.sf(1.0),
self.sf((WIDTH as i32 - PANEL_X - 14) as f32),
); );
self.copy_error_button.draw(r, &self.fonts); self.copy_error_button.draw(r, &self.fonts);
} }

@ -188,6 +188,12 @@ fn install_from_archive(
Cursor::new(archive_bytes), Cursor::new(archive_bytes),
".", ".",
|entry, reader, _dest| { |entry, reader, _dest| {
// Skip directory entries — they have no file content.
if entry.is_directory() {
io::copy(reader, &mut io::sink()).map_err(sevenz_rust2::Error::from)?;
return Ok(true);
}
let entry_name = entry.name().to_string(); let entry_name = entry.name().to_string();
let parts: Vec<&str> = entry_name.split('/').collect(); let parts: Vec<&str> = entry_name.split('/').collect();
if parts.is_empty() { if parts.is_empty() {

@ -41,7 +41,10 @@ fn main() {
let mut renderer = Renderer::new(phys_w, phys_h); let mut renderer = Renderer::new(phys_w, phys_h);
let mut form = InstallForm::new(scale); let mut form = InstallForm::new(scale);
while window.is_open() && !window.is_key_down(Key::Escape) { while window.is_open() && !window.is_key_down(Key::Escape)
&& !(window.is_key_down(Key::F4)
&& (window.is_key_down(Key::LeftAlt) || window.is_key_down(Key::RightAlt)))
{
let (mx, my) = window let (mx, my) = window
.get_mouse_pos(MouseMode::Clamp) .get_mouse_pos(MouseMode::Clamp)
.unwrap_or((0.0, 0.0)); .unwrap_or((0.0, 0.0));

@ -79,7 +79,8 @@ impl FontManager {
} }
} }
/// Draw multiline text, splitting on '\n'. Returns total height drawn. /// Draw multiline text, splitting on '\n' and word-wrapping at `max_width`
/// (if > 0). Returns total height drawn.
pub fn draw_text_multiline( pub fn draw_text_multiline(
&self, &self,
renderer: &mut Renderer, renderer: &mut Renderer,
@ -89,18 +90,90 @@ impl FontManager {
size: f32, size: f32,
color: u32, color: u32,
line_spacing: f32, line_spacing: f32,
max_width: f32,
) -> f32 { ) -> f32 {
let scaled = self.regular.as_scaled(size); let scaled = self.regular.as_scaled(size);
let line_height = scaled.height() + line_spacing; let line_height = scaled.height() + line_spacing;
let mut cy = y as f32; let mut cy = y as f32;
for line in text.split('\n') { for line in text.split('\n') {
if max_width > 0.0 {
let wrapped = self.word_wrap(line, size, max_width);
for wl in &wrapped {
self.draw_text(renderer, x, cy as i32, wl, size, color);
cy += line_height;
}
} else {
self.draw_text(renderer, x, cy as i32, line, size, color); self.draw_text(renderer, x, cy as i32, line, size, color);
cy += line_height; cy += line_height;
} }
}
cy - y as f32 cy - y as f32
} }
/// Measure the total height of multiline text with word-wrapping.
pub fn measure_text_multiline(&self, text: &str, size: f32, line_spacing: f32, max_width: f32) -> (f32, f32) {
let scaled = self.regular.as_scaled(size);
let line_height = scaled.height() + line_spacing;
let mut total_lines = 0usize;
let mut overall_max_w: f32 = 0.0;
for line in text.split('\n') {
if max_width > 0.0 {
let wrapped = self.word_wrap(line, size, max_width);
for wl in &wrapped {
let (lw, _) = self.measure_text(wl, size);
if lw > overall_max_w {
overall_max_w = lw;
}
}
total_lines += wrapped.len();
} else {
let (lw, _) = self.measure_text(line, size);
if lw > overall_max_w {
overall_max_w = lw;
}
total_lines += 1;
}
}
(overall_max_w, line_height * total_lines as f32)
}
/// Word-wrap a single line to fit within `max_width` pixels.
fn word_wrap(&self, line: &str, size: f32, max_width: f32) -> Vec<String> {
if line.is_empty() {
return vec![String::new()];
}
let mut result = Vec::new();
let mut current = String::new();
let mut current_w: f32 = 0.0;
let space_w = self.measure_text(" ", size).0;
for word in line.split_whitespace() {
let (ww, _) = self.measure_text(word, size);
if current.is_empty() {
// First word on this line — always add even if too wide.
current = word.to_string();
current_w = ww;
} else if current_w + space_w + ww <= max_width {
current.push(' ');
current.push_str(word);
current_w += space_w + ww;
} else {
// Wrap.
result.push(current);
current = word.to_string();
current_w = ww;
}
}
result.push(current);
result
}
} }

@ -2,7 +2,7 @@ use super::Rect;
use crate::font::FontManager; use crate::font::FontManager;
use crate::renderer::Renderer; use crate::renderer::Renderer;
/// Simple static label for drawing text. /// Simple static label for drawing text with optional word-wrapping.
pub struct Label { pub struct Label {
pub rect: Rect, pub rect: Rect,
pub text: String, pub text: String,
@ -10,6 +10,8 @@ pub struct Label {
pub font_size: f32, pub font_size: f32,
pub line_spacing: f32, pub line_spacing: f32,
pub visible: bool, pub visible: bool,
/// If > 0, text is word-wrapped to this pixel width.
pub max_width: f32,
} }
impl Label { impl Label {
@ -21,6 +23,7 @@ impl Label {
font_size, font_size,
line_spacing: 2.0, line_spacing: 2.0,
visible: true, visible: true,
max_width: 0.0,
} }
} }
@ -36,6 +39,7 @@ impl Label {
self.font_size, self.font_size,
self.color, self.color,
self.line_spacing, self.line_spacing,
self.max_width,
); );
} }
@ -44,10 +48,13 @@ impl Label {
if !self.visible || !mouse_released { if !self.visible || !mouse_released {
return false; return false;
} }
let (tw, _th) = fonts.measure_text(&self.text, self.font_size); let (tw, th) = fonts.measure_text_multiline(
let lines = self.text.lines().count().max(1); &self.text,
let approx_h = (self.font_size * lines as f32 + 2.0 * lines as f32) as i32; self.font_size,
let r = Rect::new(self.rect.x, self.rect.y, tw as i32 + 5, approx_h); self.line_spacing,
self.max_width,
);
let r = Rect::new(self.rect.x, self.rect.y, tw as i32 + 5, th as i32);
r.contains(mx, my) r.contains(mx, my)
} }
} }

@ -35,7 +35,10 @@ fn main() {
let mut renderer = Renderer::new(phys_w, phys_h); let mut renderer = Renderer::new(phys_w, phys_h);
let mut form = UninstallForm::new(scale); let mut form = UninstallForm::new(scale);
while window.is_open() && !window.is_key_down(Key::Escape) { while window.is_open() && !window.is_key_down(Key::Escape)
&& !(window.is_key_down(Key::F4)
&& (window.is_key_down(Key::LeftAlt) || window.is_key_down(Key::RightAlt)))
{
let (mx, my) = window let (mx, my) = window
.get_mouse_pos(MouseMode::Clamp) .get_mouse_pos(MouseMode::Clamp)
.unwrap_or((0.0, 0.0)); .unwrap_or((0.0, 0.0));

@ -71,6 +71,7 @@ impl UninstallForm {
let lbl = |x: i32, y: i32, text: &str, size: f32| { let lbl = |x: i32, y: i32, text: &str, size: f32| {
let mut l = Label::new(s(x), s(y), text, sf(size)); let mut l = Label::new(s(x), s(y), text, sf(size));
l.line_spacing = sf(2.0); l.line_spacing = sf(2.0);
l.max_width = sf((WIDTH as i32 - x - 10) as f32);
l l
}; };
let btn = |x: i32, y: i32, w: i32, h: i32, text: &str| GradientButton { let btn = |x: i32, y: i32, w: i32, h: i32, text: &str| GradientButton {
@ -191,6 +192,7 @@ The following details could be useful. Press the Retry button to try again.",
self.sf(11.0), self.sf(11.0),
FG_COLOR, FG_COLOR,
self.sf(1.0), self.sf(1.0),
self.sf((WIDTH as i32 - PANEL_X - 14) as f32),
); );
self.copy_error_button.draw(renderer, &self.fonts); self.copy_error_button.draw(renderer, &self.fonts);
} }
@ -229,10 +231,10 @@ The following details could be useful. Press the Retry button to try again.",
redirection::enable_redirection(redir); redirection::enable_redirection(redir);
let mut state = progress.lock().unwrap(); let mut state = progress.lock().unwrap();
state.done = true;
if let Err(e) = result { if let Err(e) = result {
state.error = Some(e.to_string()); state.error = Some(e.to_string());
} }
state.done = true;
}); });
} }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 257 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 448 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Loading…
Cancel
Save