forked from pisilinux-rs/yali-rs
Bölümleme tablosu boyut sütunu düzeltmeleri ve disk seçimi UI iyileştirmeleri
- Manuel bölümleme tablosunda boyut sütununun görünmemesi sorunu çözüldü - Disk başlığı kırmızı renk ve kutucuk simge sorunları düzeltildi (c_accent yerine c_text, Unicode ok karakteri) - Disk seçimi için ComboBox bileşeni eklendi (eski Grid tabanlı sistem yerine) - Tablo header hizalamaları düzeltildi (sol/sağ/ortalanmış sütunlar) - Font yüklemesi iyileştirildi (monospace font desteği ve emoji fallback mekanizması) - LVM LV boyut kontrolü sembolik boyutlar için düzeltildi - Disk bölüm numarası formatlama fonksiyonu eklendi (nvme0n1p1 vs sda1 mantığı) Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
+179
-115
@@ -505,11 +505,11 @@ impl PartitionStep {
|
|||||||
// arka plan
|
// arka plan
|
||||||
egui::Frame::none()
|
egui::Frame::none()
|
||||||
.fill(if selected {
|
.fill(if selected {
|
||||||
egui::Color32::from_rgba_unmultiplied(237, 237, 224, 1)
|
egui::Color32::from_rgba_unmultiplied(237, 237, 224, 255)
|
||||||
} else if response.hovered() {
|
} else if response.hovered() {
|
||||||
egui::Color32::from_rgba_unmultiplied(60, 60, 80, 180)
|
egui::Color32::from_rgba_unmultiplied(60, 60, 80, 180)
|
||||||
} else {
|
} else {
|
||||||
egui::Color32::from_rgba_unmultiplied(237, 237, 224, 1)
|
egui::Color32::from_rgba_unmultiplied(237, 237, 224, 40)
|
||||||
})
|
})
|
||||||
.stroke(egui::Stroke::new(
|
.stroke(egui::Stroke::new(
|
||||||
if selected { 2.0_f32 } else { 1.0_f32 },
|
if selected { 2.0_f32 } else { 1.0_f32 },
|
||||||
@@ -593,26 +593,25 @@ impl PartitionStep {
|
|||||||
let mut satirlar = Vec::new();
|
let mut satirlar = Vec::new();
|
||||||
if plan.efi_mb > 0 {
|
if plan.efi_mb > 0 {
|
||||||
satirlar.push(Satir {
|
satirlar.push(Satir {
|
||||||
part: format!("{}1 (EFI)", plan.disk),
|
part: format!("{} (EFI)", format_partition_device(&plan.disk, 1)),
|
||||||
fs: "FAT32",
|
fs: "FAT32",
|
||||||
size: format!("{} MB", plan.efi_mb),
|
size: format!("{} MB", plan.efi_mb),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
let swap_part = if plan.efi_mb > 0 { 2 } else { 1 };
|
let swap_part = if plan.efi_mb > 0 { 2 } else { 1 };
|
||||||
satirlar.push(Satir {
|
satirlar.push(Satir {
|
||||||
part: format!("{}{} (swap)", plan.disk, swap_part),
|
part: format!("{} (swap)", format_partition_device(&plan.disk, swap_part)),
|
||||||
fs: "swap",
|
fs: "swap",
|
||||||
size: format!("{} MB", plan.swap_mb),
|
size: format!("{} MB", plan.swap_mb),
|
||||||
});
|
});
|
||||||
let root_part = swap_part + 1;
|
let root_part = swap_part + 1;
|
||||||
satirlar.push(Satir {
|
satirlar.push(Satir {
|
||||||
part: format!("{}{}{}", plan.disk, root_part, t!("plan_root_suffix")),
|
part: format!("{}{}", format_partition_device(&plan.disk, root_part), t!("plan_root_suffix")),
|
||||||
fs: "ext4",
|
fs: "ext4",
|
||||||
size: format!("{:.1} GB", plan.root_mb as f64 / 1024.0),
|
size: format!("{:.1} GB", plan.root_mb as f64 / 1024.0),
|
||||||
});
|
});
|
||||||
|
|
||||||
egui::Frame::none()
|
egui::Frame::none()
|
||||||
.stroke(egui::Stroke::new(1.0_f32, crate::ui::theme::c_border()))
|
|
||||||
.rounding(egui::Rounding::same(6.0))
|
.rounding(egui::Rounding::same(6.0))
|
||||||
.show(ui, |ui| {
|
.show(ui, |ui| {
|
||||||
let tam = ui.available_width();
|
let tam = ui.available_width();
|
||||||
@@ -716,97 +715,124 @@ impl PartitionStep {
|
|||||||
|
|
||||||
impl PartitionStep {
|
impl PartitionStep {
|
||||||
fn show_manual_mode(&mut self, ui: &mut egui::Ui, state: &mut GlobalState) {
|
fn show_manual_mode(&mut self, ui: &mut egui::Ui, state: &mut GlobalState) {
|
||||||
let kart_genislik = 180.0;
|
// let kart_genislik = 180.0;
|
||||||
let kart_yukseklik = 160.0;
|
// let kart_yukseklik = 160.0;
|
||||||
|
|
||||||
// ── Disk seçimi (hedef disk) ────────────────────────────
|
|
||||||
ui.group(|ui| {
|
ui.group(|ui| {
|
||||||
ui.label(t!("select_disk_label"));
|
ui.label(egui::RichText::new("Kurulum Yapılacak Diski Seçin:").strong());
|
||||||
ui.add_space(8.0);
|
ui.add_space(6.0);
|
||||||
let disks = state.available_disks.clone();
|
|
||||||
|
|
||||||
egui::Grid::new("manual_disk_grid")
|
// Seçili disk için etiket
|
||||||
.min_col_width(kart_genislik + 12.0)
|
let selected_label = state.selected_disk.as_ref()
|
||||||
.spacing([12.0, 12.0])
|
.and_then(|disk_name| state.available_disks.iter().find(|d| d.name == *disk_name))
|
||||||
.show(ui, |ui| {
|
.map(|disk| format!("{} - {} ({:.1} GB)", disk.name, disk.model, disk.size_bytes as f64 / 1_073_741_824.0))
|
||||||
for (i, disk) in disks.iter().enumerate() {
|
.unwrap_or_else(|| "Disk Seçin".to_string());
|
||||||
let selected = state.selected_disk.as_deref() == Some(&disk.name);
|
|
||||||
|
|
||||||
let (rect, response) = ui.allocate_exact_size(
|
// ComboBox Oluşturma
|
||||||
egui::vec2(kart_genislik, kart_yukseklik),
|
egui::ComboBox::from_id_source("disk_selection_combobox")
|
||||||
egui::Sense::click(),
|
.selected_text(selected_label)
|
||||||
);
|
.width(ui.available_width() - 20.0) // Genişliği panele yay
|
||||||
let child_ui = &mut ui.child_ui(rect, egui::Layout::top_down(egui::Align::Center));
|
.show_ui(ui, |ui| {
|
||||||
|
for disk in &state.available_disks {
|
||||||
|
let label = format!("{} - {} ({:.1} GB)", disk.name, disk.model, disk.size_bytes as f64 / 1_073_741_824.0);
|
||||||
|
|
||||||
egui::Frame::none()
|
if ui.selectable_value(&mut state.selected_disk, Some(disk.name.clone()), label).changed() {
|
||||||
.fill(if selected {
|
// Disk değiştiğinde tetiklenecek işlemler (örn: disk bölümlerini yeniden okuma)
|
||||||
egui::Color32::from_rgba_unmultiplied(237, 237, 224, 1)
|
println!("Seçilen Disk Değişti: {}", disk.name);
|
||||||
} else if response.hovered() {
|
|
||||||
egui::Color32::from_rgba_unmultiplied(60, 60, 80, 180)
|
|
||||||
} else {
|
|
||||||
egui::Color32::from_rgba_unmultiplied(237, 237, 224, 1)
|
|
||||||
})
|
|
||||||
.stroke(egui::Stroke::new(
|
|
||||||
if selected { 2.0_f32 } else { 1.0_f32 },
|
|
||||||
if selected { crate::ui::theme::c_accent() } else { crate::ui::theme::c_border() },
|
|
||||||
))
|
|
||||||
.rounding(egui::Rounding::same(8.0))
|
|
||||||
.inner_margin(egui::Margin::same(8.0))
|
|
||||||
.show(child_ui, |ui| {
|
|
||||||
ui.set_min_size(egui::vec2(kart_genislik - 16.0, kart_yukseklik - 16.0));
|
|
||||||
ui.add_space(8.0);
|
|
||||||
ui.add(
|
|
||||||
egui::Image::new(egui::include_image!("../../assets/disk.png"))
|
|
||||||
.max_width(64.0)
|
|
||||||
.max_height(64.0)
|
|
||||||
.rounding(egui::Rounding::same(6.0)),
|
|
||||||
);
|
|
||||||
ui.add_space(6.0);
|
|
||||||
let marka = if disk.vendor.is_empty() {
|
|
||||||
&disk.model
|
|
||||||
} else {
|
|
||||||
&disk.vendor
|
|
||||||
};
|
|
||||||
|
|
||||||
ui.label(
|
|
||||||
egui::RichText::new(marka)
|
|
||||||
.size(11.0)
|
|
||||||
.color(crate::ui::theme::c_text_dim()),
|
|
||||||
);
|
|
||||||
|
|
||||||
ui.label(
|
|
||||||
egui::RichText::new(format!("{} GB", disk.size_gb))
|
|
||||||
.size(14.0)
|
|
||||||
.strong()
|
|
||||||
.color(crate::ui::theme::c_text()),
|
|
||||||
);
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
if response.clicked() {
|
|
||||||
// Aktif diski değiştir; ancak diğer disklerde yapılmış
|
|
||||||
// bölüm tanımlarını KORU. Seçilen diskin mevcut
|
|
||||||
// bölümlerini listeye ekle (aynı cihaz zaten tanımlıysa
|
|
||||||
// kullanıcının tanımı kazanır).
|
|
||||||
state.selected_disk = Some(disk.name.clone());
|
|
||||||
let fresh = read_existing_partitions(&disk.name);
|
|
||||||
for f in fresh {
|
|
||||||
let known = state.custom_partitions.iter()
|
|
||||||
.any(|p| p.device == f.device || p.orig_device == f.orig_device);
|
|
||||||
if !known {
|
|
||||||
state.custom_partitions.push(f);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
self.manual.error = None;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (i + 1) % 3 == 0 {
|
|
||||||
ui.end_row();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// // ── Disk seçimi (hedef disk) ────────────────────────────
|
||||||
|
// ui.group(|ui| {
|
||||||
|
// ui.label(t!("select_disk_label"));
|
||||||
|
// ui.add_space(8.0);
|
||||||
|
// let disks = state.available_disks.clone();
|
||||||
|
|
||||||
|
// egui::Grid::new("manual_disk_grid")
|
||||||
|
// .min_col_width(kart_genislik + 12.0)
|
||||||
|
// .spacing([12.0, 12.0])
|
||||||
|
// .show(ui, |ui| {
|
||||||
|
// for (i, disk) in disks.iter().enumerate() {
|
||||||
|
// let selected = state.selected_disk.as_deref() == Some(&disk.name);
|
||||||
|
|
||||||
|
// let (rect, response) = ui.allocate_exact_size(
|
||||||
|
// egui::vec2(kart_genislik, kart_yukseklik),
|
||||||
|
// egui::Sense::click(),
|
||||||
|
// );
|
||||||
|
// let child_ui = &mut ui.child_ui(rect, egui::Layout::top_down(egui::Align::Center));
|
||||||
|
|
||||||
|
// egui::Frame::none()
|
||||||
|
// .fill(if selected {
|
||||||
|
// egui::Color32::from_rgba_unmultiplied(237, 237, 224, 255)
|
||||||
|
// } else if response.hovered() {
|
||||||
|
// egui::Color32::from_rgba_unmultiplied(60, 60, 80, 180)
|
||||||
|
// } else {
|
||||||
|
// egui::Color32::from_rgba_unmultiplied(237, 237, 224, 40)
|
||||||
|
// })
|
||||||
|
// .stroke(egui::Stroke::new(
|
||||||
|
// if selected { 2.0_f32 } else { 1.0_f32 },
|
||||||
|
// if selected { crate::ui::theme::c_accent() } else { crate::ui::theme::c_border() },
|
||||||
|
// ))
|
||||||
|
// .rounding(egui::Rounding::same(8.0))
|
||||||
|
// .inner_margin(egui::Margin::same(8.0))
|
||||||
|
// .show(child_ui, |ui| {
|
||||||
|
// ui.set_min_size(egui::vec2(kart_genislik - 16.0, kart_yukseklik - 16.0));
|
||||||
|
// ui.add_space(8.0);
|
||||||
|
// ui.add(
|
||||||
|
// egui::Image::new(egui::include_image!("../../assets/disk.png"))
|
||||||
|
// .max_width(64.0)
|
||||||
|
// .max_height(64.0)
|
||||||
|
// .rounding(egui::Rounding::same(6.0)),
|
||||||
|
// );
|
||||||
|
// ui.add_space(6.0);
|
||||||
|
// let marka = if disk.vendor.is_empty() {
|
||||||
|
// &disk.model
|
||||||
|
// } else {
|
||||||
|
// &disk.vendor
|
||||||
|
// };
|
||||||
|
|
||||||
|
// ui.label(
|
||||||
|
// egui::RichText::new(marka)
|
||||||
|
// .size(11.0)
|
||||||
|
// .color(crate::ui::theme::c_text_dim()),
|
||||||
|
// );
|
||||||
|
|
||||||
|
// ui.label(
|
||||||
|
// egui::RichText::new(format!("{} GB", disk.size_gb))
|
||||||
|
// .size(14.0)
|
||||||
|
// .strong()
|
||||||
|
// .color(crate::ui::theme::c_text()),
|
||||||
|
// );
|
||||||
|
|
||||||
|
// });
|
||||||
|
|
||||||
|
// if response.clicked() {
|
||||||
|
// // Aktif diski değiştir; ancak diğer disklerde yapılmış
|
||||||
|
// // bölüm tanımlarını KORU. Seçilen diskin mevcut
|
||||||
|
// // bölümlerini listeye ekle (aynı cihaz zaten tanımlıysa
|
||||||
|
// // kullanıcının tanımı kazanır).
|
||||||
|
// state.selected_disk = Some(disk.name.clone());
|
||||||
|
// let fresh = read_existing_partitions(&disk.name);
|
||||||
|
// for f in fresh {
|
||||||
|
// let known = state.custom_partitions.iter()
|
||||||
|
// .any(|p| p.device == f.device || p.orig_device == f.orig_device);
|
||||||
|
// if !known {
|
||||||
|
// state.custom_partitions.push(f);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// self.manual.error = None;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if (i + 1) % 3 == 0 {
|
||||||
|
// ui.end_row();
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
// });
|
||||||
|
|
||||||
ui.add_space(8.0);
|
ui.add_space(8.0);
|
||||||
|
|
||||||
let disk = match &state.selected_disk {
|
let disk = match &state.selected_disk {
|
||||||
@@ -822,8 +848,6 @@ impl PartitionStep {
|
|||||||
ui.label(egui::RichText::new(t!("mp_plan_title")).strong().color(crate::ui::theme::c_text()));
|
ui.label(egui::RichText::new(t!("mp_plan_title")).strong().color(crate::ui::theme::c_text()));
|
||||||
ui.add_space(6.0);
|
ui.add_space(6.0);
|
||||||
|
|
||||||
let delete_idx: Option<usize> = None;
|
|
||||||
|
|
||||||
let col_widths = [0.25, 0.12, 0.16, 0.24, 0.23];
|
let col_widths = [0.25, 0.12, 0.16, 0.24, 0.23];
|
||||||
let tam_genislik = ui.available_width();
|
let tam_genislik = ui.available_width();
|
||||||
let _border_stroke = egui::Stroke::new(1.0_f32, crate::ui::theme::c_border());
|
let _border_stroke = egui::Stroke::new(1.0_f32, crate::ui::theme::c_border());
|
||||||
@@ -917,12 +941,12 @@ impl PartitionStep {
|
|||||||
egui::pos2(hdr_rect.left() + 10.0, hdr_rect.center().y),
|
egui::pos2(hdr_rect.left() + 10.0, hdr_rect.center().y),
|
||||||
egui::Align2::LEFT_CENTER,
|
egui::Align2::LEFT_CENTER,
|
||||||
if is_active_disk {
|
if is_active_disk {
|
||||||
format!("\u{EA6B} {} ({})", disk_name, disk_total_str)
|
format!("\u{EA6B} {} ( {} )", disk_name, disk_total_str)
|
||||||
} else {
|
} else {
|
||||||
format!("{} ({})", disk_name, disk_total_str)
|
format!("{} ({})", disk_name, disk_total_str)
|
||||||
},
|
},
|
||||||
egui::FontId::proportional(12.5),
|
egui::FontId::proportional(12.5),
|
||||||
crate::ui::theme::c_accent(),
|
crate::ui::theme::select_disk_label(),
|
||||||
);
|
);
|
||||||
|
|
||||||
// Bu diskin kendi sütun başlıkları
|
// Bu diskin kendi sütun başlıkları
|
||||||
@@ -1029,13 +1053,25 @@ impl PartitionStep {
|
|||||||
egui::pos2(x + 8.0, row_rect.top() + 4.0),
|
egui::pos2(x + 8.0, row_rect.top() + 4.0),
|
||||||
egui::vec2(cell_w - 16.0, 26.0),
|
egui::vec2(cell_w - 16.0, 26.0),
|
||||||
);
|
);
|
||||||
painter.text(
|
// Tablo okunabilirliği: metin sütunları sola, sayı (Boyut)
|
||||||
text_rect.center(),
|
// sağa yaslı; aygıt adı monospace (/dev/sdb1 vs sdb10 ayrımı).
|
||||||
egui::Align2::CENTER_CENTER,
|
let (anchor, font) = match j {
|
||||||
*text,
|
0 => (egui::Align2::LEFT_CENTER, egui::FontId::monospace(12.5)),
|
||||||
egui::FontId::proportional(13.0),
|
1 => (egui::Align2::RIGHT_CENTER, egui::FontId::monospace(12.5)),
|
||||||
text_color,
|
_ => (egui::Align2::LEFT_CENTER, egui::FontId::proportional(13.0)),
|
||||||
);
|
};
|
||||||
|
// Hizalama noktası anchor'a göre seçilir: LEFT_CENTER için hücrenin
|
||||||
|
// SOL kenarı, RIGHT_CENTER için SAĞ kenarı. Her ikisinde de rect.center()
|
||||||
|
// kullanmak metnin hücre ORTASINDAN başlamasına yol açıyordu; uzun
|
||||||
|
// aygıt adlarında (örn. "/dev/nvme0n1p1") bu, metnin yarısının bir
|
||||||
|
// sonraki sütuna taşıp üstüne binmesine (görsel olarak karakterlerin
|
||||||
|
// kayıp/örtülü görünmesine) sebep oluyordu.
|
||||||
|
let anchor_pos = match anchor {
|
||||||
|
egui::Align2::LEFT_CENTER => text_rect.left_center(),
|
||||||
|
egui::Align2::RIGHT_CENTER => text_rect.right_center(),
|
||||||
|
_ => text_rect.center(),
|
||||||
|
};
|
||||||
|
painter.text(anchor_pos, anchor, *text, font, text_color);
|
||||||
x += cell_w;
|
x += cell_w;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1065,7 +1101,7 @@ impl PartitionStep {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if vis_idx < total_rows - 1 {
|
if vis_idx < total_rows - 1 {
|
||||||
ui.separator();
|
//ui.separator();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1087,9 +1123,6 @@ impl PartitionStep {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Silme onayı
|
// Silme onayı
|
||||||
if let Some(idx) = delete_idx {
|
|
||||||
self.manual.delete_idx = Some(idx);
|
|
||||||
}
|
|
||||||
if let Some(idx) = self.manual.delete_idx {
|
if let Some(idx) = self.manual.delete_idx {
|
||||||
let dev = state.custom_partitions.get(idx)
|
let dev = state.custom_partitions.get(idx)
|
||||||
.map(|p| p.device.clone())
|
.map(|p| p.device.clone())
|
||||||
@@ -1168,7 +1201,6 @@ impl PartitionStep {
|
|||||||
self.manual.add_mountpoint = match next_num {
|
self.manual.add_mountpoint = match next_num {
|
||||||
1 if self.is_uefi => "/boot/efi".to_string(),
|
1 if self.is_uefi => "/boot/efi".to_string(),
|
||||||
1 => "/".to_string(),
|
1 => "/".to_string(),
|
||||||
2 if self.is_uefi => "swap".to_string(),
|
|
||||||
2 => "swap".to_string(),
|
2 => "swap".to_string(),
|
||||||
3 => "/".to_string(),
|
3 => "/".to_string(),
|
||||||
_ => String::new(),
|
_ => String::new(),
|
||||||
@@ -1781,7 +1813,13 @@ impl PartitionStep {
|
|||||||
.filter(|lv| lv.vg_name == vg.name)
|
.filter(|lv| lv.vg_name == vg.name)
|
||||||
.map(|lv| lv.size_mb)
|
.map(|lv| lv.size_mb)
|
||||||
.sum();
|
.sum();
|
||||||
if current_sum + size_mb > vg.size_mb && size_mb > 0 {
|
let overflows = if size_mb == 0 {
|
||||||
|
// "Kalan alan" (sembolik): VG'de hiç boş yer kalmamışsa hata.
|
||||||
|
current_sum >= vg.size_mb
|
||||||
|
} else {
|
||||||
|
current_sum + size_mb > vg.size_mb
|
||||||
|
};
|
||||||
|
if overflows {
|
||||||
self.manual.error = Some(t!("lvm_lv_error_size").to_string());
|
self.manual.error = Some(t!("lvm_lv_error_size").to_string());
|
||||||
} else {
|
} else {
|
||||||
state.logical_volumes.push(crate::installer::LogicalVolume {
|
state.logical_volumes.push(crate::installer::LogicalVolume {
|
||||||
@@ -1839,7 +1877,7 @@ impl PartitionStep {
|
|||||||
/// Bölüm tablosunun sütun başlıklarını çizer.
|
/// Bölüm tablosunun sütun başlıklarını çizer.
|
||||||
/// Her disk grubu kendi başlık satırıyla ayrı bir "tablo" görünümü verir.
|
/// Her disk grubu kendi başlık satırıyla ayrı bir "tablo" görünümü verir.
|
||||||
fn draw_partition_table_header(ui: &mut egui::Ui, tam_genislik: f32, col_widths: [f32; 5]) {
|
fn draw_partition_table_header(ui: &mut egui::Ui, tam_genislik: f32, col_widths: [f32; 5]) {
|
||||||
let header_color = egui::Color32::from_rgb(33, 37, 41);
|
let header_color = egui::Color32::from_rgb(0, 0, 0);
|
||||||
let header_text = egui::Color32::WHITE;
|
let header_text = egui::Color32::WHITE;
|
||||||
let headers: [String; 5] = [
|
let headers: [String; 5] = [
|
||||||
t!("mp_device").to_string(),
|
t!("mp_device").to_string(),
|
||||||
@@ -1851,19 +1889,33 @@ fn draw_partition_table_header(ui: &mut egui::Ui, tam_genislik: f32, col_widths:
|
|||||||
ui.horizontal(|ui| {
|
ui.horizontal(|ui| {
|
||||||
ui.set_height(30.0);
|
ui.set_height(30.0);
|
||||||
ui.spacing_mut().item_spacing.x = 0.0;
|
ui.spacing_mut().item_spacing.x = 0.0;
|
||||||
|
// Başlık hizası içerikle aynı: Aygıt/Dosya Sistemi/Bağlama sola,
|
||||||
|
// Boyut sağa, Biçim ortalanmış.
|
||||||
|
let header_aligns = [
|
||||||
|
egui::Align2::LEFT_CENTER,
|
||||||
|
egui::Align2::RIGHT_CENTER,
|
||||||
|
egui::Align2::LEFT_CENTER,
|
||||||
|
egui::Align2::LEFT_CENTER,
|
||||||
|
egui::Align2::CENTER_CENTER,
|
||||||
|
];
|
||||||
for (j, h) in headers.into_iter().enumerate() {
|
for (j, h) in headers.into_iter().enumerate() {
|
||||||
let (rect, _) = ui.allocate_exact_size(
|
let (rect, _) = ui.allocate_exact_size(
|
||||||
egui::vec2(tam_genislik * col_widths[j], 30.0),
|
egui::vec2(tam_genislik * col_widths[j], 30.0),
|
||||||
egui::Sense::hover(),
|
egui::Sense::hover(),
|
||||||
);
|
);
|
||||||
let child_ui = &mut ui.child_ui(rect, egui::Layout::top_down(egui::Align::Center));
|
let painter = ui.painter();
|
||||||
egui::Frame::none()
|
// İçerikle aynı 8px iç boşluk
|
||||||
.fill(header_color)
|
let inner = rect.shrink2(egui::vec2(8.0, 0.0));
|
||||||
.stroke(egui::Stroke::new(1.0_f32, header_color))
|
painter.rect_filled(rect, egui::Rounding::ZERO, header_color);
|
||||||
.inner_margin(egui::Margin::symmetric(8.0, 4.0))
|
// Hizalama noktası anchor'a göre seçilir (bkz. satır çiziminde aynı düzeltme):
|
||||||
.show(child_ui, |ui| {
|
// rect.center() her anchor için kullanılırsa LEFT_CENTER/RIGHT_CENTER
|
||||||
ui.label(egui::RichText::new(h).strong().color(header_text).size(13.0));
|
// başlıklar hücre ortasından başlar/biter, uzun başlıklarda taşma olur.
|
||||||
});
|
let anchor_pos = match header_aligns[j] {
|
||||||
|
egui::Align2::LEFT_CENTER => inner.left_center(),
|
||||||
|
egui::Align2::RIGHT_CENTER => inner.right_center(),
|
||||||
|
_ => inner.center(),
|
||||||
|
};
|
||||||
|
painter.text(anchor_pos, header_aligns[j], h, egui::FontId::proportional(13.0), header_text);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -2064,6 +2116,18 @@ fn partition_bar(ui: &mut egui::Ui, plan: &PartitionPlan) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Disk adına bölüm numarasını doğru ekle: `sda`+1 → `sda1`, ama
|
||||||
|
/// `nvme0n1`/`mmcblk0`/`loop0` gibi rakamla biten aygıtlarda araya
|
||||||
|
/// `p` konur → `nvme0n1p1`, `mmcblk0p1`. (bkz. `device_to_disk` — aynı
|
||||||
|
/// kuralın tersini uygular.)
|
||||||
|
fn format_partition_device(disk: &str, num: u64) -> String {
|
||||||
|
if disk.chars().last().map(|c| c.is_ascii_digit()).unwrap_or(false) {
|
||||||
|
format!("{}p{}", disk, num)
|
||||||
|
} else {
|
||||||
|
format!("{}{}", disk, num)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Sayıyı nokta ile binlik ayraçlı formata çevirir (örn. 7000000 → 7.000.000).
|
/// Sayıyı nokta ile binlik ayraçlı formata çevirir (örn. 7000000 → 7.000.000).
|
||||||
fn format_number_thousands(n: u64) -> String {
|
fn format_number_thousands(n: u64) -> String {
|
||||||
let s = n.to_string();
|
let s = n.to_string();
|
||||||
|
|||||||
+128
-12
@@ -52,6 +52,7 @@ pub fn c_sidebar_text() -> Color32 { color_from_hex(SIDEBAR_TEXT.load(Ordering::
|
|||||||
pub fn c_footer_bg() -> Color32 { color_from_hex(BG_FOOTER.load(Ordering::Relaxed)) }
|
pub fn c_footer_bg() -> Color32 { color_from_hex(BG_FOOTER.load(Ordering::Relaxed)) }
|
||||||
pub fn c_root_bg() -> Color32 { color_from_hex(BG_ROOT.load(Ordering::Relaxed)) }
|
pub fn c_root_bg() -> Color32 { color_from_hex(BG_ROOT.load(Ordering::Relaxed)) }
|
||||||
pub fn c_keyboard_bg() -> Color32 { color_from_hex(KEYBOARD_BG.load(Ordering::Relaxed)) }
|
pub fn c_keyboard_bg() -> Color32 { color_from_hex(KEYBOARD_BG.load(Ordering::Relaxed)) }
|
||||||
|
pub fn select_disk_label() -> Color32 { color_from_hex(0xFFFFFF) }
|
||||||
|
|
||||||
pub fn set_theme_mode(is_dark: bool) {
|
pub fn set_theme_mode(is_dark: bool) {
|
||||||
if is_dark {
|
if is_dark {
|
||||||
@@ -108,10 +109,85 @@ pub fn apply(ctx: &egui::Context, is_dark: bool) {
|
|||||||
ctx.set_visuals(build_visuals(is_dark));
|
ctx.set_visuals(build_visuals(is_dark));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// fn setup_fonts(ctx: &egui::Context) {
|
||||||
|
// let mut fonts = egui::FontDefinitions::default();
|
||||||
|
|
||||||
|
// // 1. ADIM: Sadece Metin (Text) Fontunu Bul ve Yükle
|
||||||
|
// let text_font_paths = [
|
||||||
|
// "/usr/share/fonts/TTF/OpenSans-Regular.ttf",
|
||||||
|
// "/usr/share/fonts/noto/NotoSans-Regular.ttf",
|
||||||
|
// "/usr/share/fonts/exo-1/Exo-Regular.otf",
|
||||||
|
// "/usr/share/fonts/exo-1/Exo2-Medium.ttf",
|
||||||
|
// "/usr/share/fonts/exo-1/Exo-Medium.otf",
|
||||||
|
// ];
|
||||||
|
|
||||||
|
// for path in text_font_paths {
|
||||||
|
// if let Ok(data) = std::fs::read(path) {
|
||||||
|
// fonts.font_data.insert(
|
||||||
|
// "system_text_font".to_owned(),
|
||||||
|
// egui::FontData::from_owned(data),
|
||||||
|
// );
|
||||||
|
|
||||||
|
// // Metin fontunu en başa (0. indeks) koyuyoruz ki varsayılan olarak bu kullanılsın
|
||||||
|
// fonts
|
||||||
|
// .families
|
||||||
|
// .entry(egui::FontFamily::Proportional)
|
||||||
|
// .or_default()
|
||||||
|
// .insert(0, "system_text_font".to_owned());
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // 2. ADIM: Renkli Emoji Fontunu Ara ve "Fallback" (Yedek) Olarak Sona Ekle
|
||||||
|
// // ISO ortamlarında Noto Color Emoji genellikle bu yollardan birinde olur
|
||||||
|
// let emoji_font_paths = [
|
||||||
|
// "/usr/share/fonts/noto/NotoColorEmoji.ttf",
|
||||||
|
// ];
|
||||||
|
|
||||||
|
// for path in emoji_font_paths {
|
||||||
|
// if let Ok(data) = std::fs::read(path) {
|
||||||
|
// fonts.font_data.insert(
|
||||||
|
// "system_emoji_font".to_owned(),
|
||||||
|
// egui::FontData::from_owned(data),
|
||||||
|
// );
|
||||||
|
|
||||||
|
// // ÖNEMLİ: Emojiyi listenin SONUNA (push ile) ekliyoruz.
|
||||||
|
// // Böylece egui normal harfleri sistem fontuyla yazacak,
|
||||||
|
// // harf sistem fontunda yoksa (yani emojiyse) gidip bu fonttan alacak.
|
||||||
|
// fonts
|
||||||
|
// .families
|
||||||
|
// .entry(egui::FontFamily::Proportional)
|
||||||
|
// .or_default()
|
||||||
|
// .push("system_emoji_font".to_owned());
|
||||||
|
|
||||||
|
// fonts
|
||||||
|
// .families
|
||||||
|
// .entry(egui::FontFamily::Monospace)
|
||||||
|
// .or_default()
|
||||||
|
// .insert(0, "system_emoji_font".to_owned());
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // 3. ADIM: Remixicon ikon fontunu projeye göm (PUA bölgesindeki karakterler için fallback)
|
||||||
|
// let remixicon_data = include_bytes!("../../assets/remixicon.ttf");
|
||||||
|
// fonts.font_data.insert(
|
||||||
|
// "remixicon".to_owned(),
|
||||||
|
// egui::FontData::from_owned(remixicon_data.to_vec()),
|
||||||
|
// );
|
||||||
|
// fonts
|
||||||
|
// .families
|
||||||
|
// .entry(egui::FontFamily::Proportional)
|
||||||
|
// .or_default()
|
||||||
|
// .push("remixicon".to_owned());
|
||||||
|
|
||||||
|
// ctx.set_fonts(fonts);
|
||||||
|
// }
|
||||||
|
|
||||||
fn setup_fonts(ctx: &egui::Context) {
|
fn setup_fonts(ctx: &egui::Context) {
|
||||||
let mut fonts = egui::FontDefinitions::default();
|
let mut fonts = egui::FontDefinitions::default();
|
||||||
|
|
||||||
// 1. ADIM: Sadece Metin (Text) Fontunu Bul ve Yükle
|
// 1. ADIM: Metin ve Monospace için Sistem Fontu Yükleme
|
||||||
let text_font_paths = [
|
let text_font_paths = [
|
||||||
"/usr/share/fonts/TTF/OpenSans-Regular.ttf",
|
"/usr/share/fonts/TTF/OpenSans-Regular.ttf",
|
||||||
"/usr/share/fonts/noto/NotoSans-Regular.ttf",
|
"/usr/share/fonts/noto/NotoSans-Regular.ttf",
|
||||||
@@ -120,25 +196,59 @@ fn setup_fonts(ctx: &egui::Context) {
|
|||||||
"/usr/share/fonts/exo-1/Exo-Medium.otf",
|
"/usr/share/fonts/exo-1/Exo-Medium.otf",
|
||||||
];
|
];
|
||||||
|
|
||||||
|
let mut _text_font_loaded = false;
|
||||||
|
|
||||||
for path in text_font_paths {
|
for path in text_font_paths {
|
||||||
if let Ok(data) = std::fs::read(path) {
|
if let Ok(data) = std::fs::read(path) {
|
||||||
fonts.font_data.insert(
|
fonts.font_data.insert(
|
||||||
"system_text_font".to_owned(),
|
"system_text_font".to_owned(),
|
||||||
egui::FontData::from_owned(data),
|
egui::FontData::from_owned(data).into(), // Sürüme göre .into() veya std::sync::Arc::new(...)
|
||||||
);
|
);
|
||||||
|
|
||||||
// Metin fontunu en başa (0. indeks) koyuyoruz ki varsayılan olarak bu kullanılsın
|
// Proportional (Orantılı) fontun başına ekle
|
||||||
fonts
|
fonts
|
||||||
.families
|
.families
|
||||||
.entry(egui::FontFamily::Proportional)
|
.entry(egui::FontFamily::Proportional)
|
||||||
.or_default()
|
.or_default()
|
||||||
.insert(0, "system_text_font".to_owned());
|
.insert(0, "system_text_font".to_owned());
|
||||||
|
|
||||||
|
// Monospace için de bu fontu varsayılan olarak ekle (özel bir monospace bulunamadıysa)
|
||||||
|
fonts
|
||||||
|
.families
|
||||||
|
.entry(egui::FontFamily::Monospace)
|
||||||
|
.or_default()
|
||||||
|
.insert(0, "system_text_font".to_owned());
|
||||||
|
|
||||||
|
_text_font_loaded = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. ADIM: Renkli Emoji Fontunu Ara ve "Fallback" (Yedek) Olarak Sona Ekle
|
// Ek Güvence: Özel bir Monospace fontu varsa öncelikli olarak onu ara
|
||||||
// ISO ortamlarında Noto Color Emoji genellikle bu yollardan birinde olur
|
let mono_font_paths = [
|
||||||
|
"/usr/share/fonts/TTF/Hack-Regular.ttf",
|
||||||
|
"/usr/share/fonts/TTF/DejaVuSansMono.ttf",
|
||||||
|
"/usr/share/fonts/noto/NotoSansMono-Regular.ttf",
|
||||||
|
];
|
||||||
|
|
||||||
|
for path in mono_font_paths {
|
||||||
|
if let Ok(data) = std::fs::read(path) {
|
||||||
|
fonts.font_data.insert(
|
||||||
|
"system_mono_font".to_owned(),
|
||||||
|
egui::FontData::from_owned(data).into(),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Monospace ailesinin 0. indeksine yerleştir
|
||||||
|
fonts
|
||||||
|
.families
|
||||||
|
.entry(egui::FontFamily::Monospace)
|
||||||
|
.or_default()
|
||||||
|
.insert(0, "system_mono_font".to_owned());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. ADIM: Color Emoji Fontunu Yedek (Fallback) Olarak EKLE
|
||||||
let emoji_font_paths = [
|
let emoji_font_paths = [
|
||||||
"/usr/share/fonts/noto/NotoColorEmoji.ttf",
|
"/usr/share/fonts/noto/NotoColorEmoji.ttf",
|
||||||
];
|
];
|
||||||
@@ -147,12 +257,10 @@ fn setup_fonts(ctx: &egui::Context) {
|
|||||||
if let Ok(data) = std::fs::read(path) {
|
if let Ok(data) = std::fs::read(path) {
|
||||||
fonts.font_data.insert(
|
fonts.font_data.insert(
|
||||||
"system_emoji_font".to_owned(),
|
"system_emoji_font".to_owned(),
|
||||||
egui::FontData::from_owned(data),
|
egui::FontData::from_owned(data).into(),
|
||||||
);
|
);
|
||||||
|
|
||||||
// ÖNEMLİ: Emojiyi listenin SONUNA (push ile) ekliyoruz.
|
// Her iki aileye de SONA (push) ekle, böylece metinler bozulmaz
|
||||||
// Böylece egui normal harfleri sistem fontuyla yazacak,
|
|
||||||
// harf sistem fontunda yoksa (yani emojiyse) gidip bu fonttan alacak.
|
|
||||||
fonts
|
fonts
|
||||||
.families
|
.families
|
||||||
.entry(egui::FontFamily::Proportional)
|
.entry(egui::FontFamily::Proportional)
|
||||||
@@ -163,23 +271,30 @@ fn setup_fonts(ctx: &egui::Context) {
|
|||||||
.families
|
.families
|
||||||
.entry(egui::FontFamily::Monospace)
|
.entry(egui::FontFamily::Monospace)
|
||||||
.or_default()
|
.or_default()
|
||||||
.insert(0, "system_emoji_font".to_owned());
|
.push("system_emoji_font".to_owned()); // insert(0, ...) yerine push yapıldı!
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. ADIM: Remixicon ikon fontunu projeye göm (PUA bölgesindeki karakterler için fallback)
|
// 3. ADIM: Remixicon İkon Fontunu Göm (PUA)
|
||||||
let remixicon_data = include_bytes!("../../assets/remixicon.ttf");
|
let remixicon_data = include_bytes!("../../assets/remixicon.ttf");
|
||||||
fonts.font_data.insert(
|
fonts.font_data.insert(
|
||||||
"remixicon".to_owned(),
|
"remixicon".to_owned(),
|
||||||
egui::FontData::from_owned(remixicon_data.to_vec()),
|
egui::FontData::from_owned(remixicon_data.to_vec()).into(),
|
||||||
);
|
);
|
||||||
|
|
||||||
fonts
|
fonts
|
||||||
.families
|
.families
|
||||||
.entry(egui::FontFamily::Proportional)
|
.entry(egui::FontFamily::Proportional)
|
||||||
.or_default()
|
.or_default()
|
||||||
.push("remixicon".to_owned());
|
.push("remixicon".to_owned());
|
||||||
|
|
||||||
|
fonts
|
||||||
|
.families
|
||||||
|
.entry(egui::FontFamily::Monospace)
|
||||||
|
.or_default()
|
||||||
|
.push("remixicon".to_owned());
|
||||||
|
|
||||||
ctx.set_fonts(fonts);
|
ctx.set_fonts(fonts);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -250,6 +365,7 @@ fn build_style() -> egui::Style {
|
|||||||
style.spacing.indent = 16.0;
|
style.spacing.indent = 16.0;
|
||||||
style.spacing.scroll.bar_width = 14.0;
|
style.spacing.scroll.bar_width = 14.0;
|
||||||
|
|
||||||
|
|
||||||
// Metin boyutları
|
// Metin boyutları
|
||||||
style.text_styles = [
|
style.text_styles = [
|
||||||
(egui::TextStyle::Small, FontId::proportional(11.0)),
|
(egui::TextStyle::Small, FontId::proportional(11.0)),
|
||||||
|
|||||||
Reference in New Issue
Block a user