forked from pisilinux-rs/yali-rs
feat: dropdown full-width click, gradient bg, pointing-hand cursor
This commit is contained in:
+24
-10
@@ -114,21 +114,35 @@ pub fn language_selector_ui(ui: &mut eframe::egui::Ui, state: &mut crate::instal
|
||||
let item_height = 28.0;
|
||||
|
||||
// Eleman kutularını sarmalayarak tam genişlikte tıklanabilir yapıyoruz
|
||||
ui.add_sized([available_width, item_height], |ui: &mut egui::Ui| {
|
||||
let (rect, item_resp) = ui.allocate_exact_size(
|
||||
egui::vec2(available_width, item_height),
|
||||
egui::Sense::click(),
|
||||
);
|
||||
{
|
||||
use egui::epaint::Mesh;
|
||||
let top = egui::Color32::from_rgb(249, 249, 249);
|
||||
let bot = egui::Color32::from_rgb(233, 233, 233);
|
||||
let mut mesh = Mesh::default();
|
||||
let idx = mesh.vertices.len() as u32;
|
||||
mesh.vertices.push(egui::epaint::Vertex { pos: egui::pos2(rect.left(), rect.top()), uv: egui::pos2(0.0, 0.0), color: top });
|
||||
mesh.vertices.push(egui::epaint::Vertex { pos: egui::pos2(rect.right(), rect.top()), uv: egui::pos2(0.0, 0.0), color: top });
|
||||
mesh.vertices.push(egui::epaint::Vertex { pos: egui::pos2(rect.right(), rect.bottom()), uv: egui::pos2(0.0, 0.0), color: bot });
|
||||
mesh.vertices.push(egui::epaint::Vertex { pos: egui::pos2(rect.left(), rect.bottom()), uv: egui::pos2(0.0, 0.0), color: bot });
|
||||
mesh.indices.extend_from_slice(&[idx, idx + 1, idx + 2, idx + 2, idx + 3, idx]);
|
||||
ui.painter().add(egui::Shape::mesh(mesh));
|
||||
}
|
||||
ui.put(rect, |ui: &mut egui::Ui| {
|
||||
ui.horizontal(|ui| {
|
||||
ui.add_space(6.0); // İç sol boşluk
|
||||
ui.add_space(6.0);
|
||||
ui.add(eframe::egui::Image::new(image_source.clone()).max_width(18.0));
|
||||
ui.add_space(4.0);
|
||||
|
||||
let mut current_lang = state.language.clone();
|
||||
let resp = ui.selectable_value(&mut current_lang, code.to_string(), *label);
|
||||
|
||||
if resp.clicked() {
|
||||
state.language = code.to_string();
|
||||
}
|
||||
resp
|
||||
ui.label(*label);
|
||||
}).response
|
||||
});
|
||||
if item_resp.clicked() {
|
||||
state.language = code.to_string();
|
||||
}
|
||||
item_resp.on_hover_cursor(egui::CursorIcon::PointingHand);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
+8
-9
@@ -471,18 +471,18 @@ impl InstallerStep for WelcomeStep {
|
||||
// Rescue mode butonu
|
||||
ui.add_space(10.0);
|
||||
|
||||
ui.allocate_ui(
|
||||
egui::vec2(ui.available_width(), 30.0), // Genişlik tam, Yükseklik sadece 24px
|
||||
|ui| {
|
||||
// Şimdi dikeyde ortalayarak soldan sağa diziyoruz
|
||||
ui.with_layout(egui::Layout::left_to_right(egui::Align::Center), |ui| {
|
||||
egui::Frame::none()
|
||||
.rounding(egui::Rounding::same(6.0))
|
||||
.inner_margin(egui::Margin::symmetric(8.0, 4.0))
|
||||
.show(ui, |ui| {
|
||||
ui.horizontal(|ui| {
|
||||
let rescue_available = detect_existing_linux();
|
||||
if rescue_available {
|
||||
if theme::secondary_button(ui, &t!("rescue_button")).clicked() {
|
||||
if theme::light_gray_btn(ui, &t!("rescue_button")).clicked() {
|
||||
state.rescue_mode = true;
|
||||
}
|
||||
|
||||
if theme::secondary_button(ui, &t!("recheck")).clicked() {
|
||||
if theme::light_gray_btn(ui, &t!("recheck")).clicked() {
|
||||
self.checked = false;
|
||||
self.on_enter(state);
|
||||
}
|
||||
@@ -494,8 +494,7 @@ impl InstallerStep for WelcomeStep {
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,138 @@
|
||||
use eframe::egui::{self, Color32, FontId, Rounding, Stroke, Vec2};
|
||||
|
||||
fn lerp_color(a: Color32, b: Color32, t: f32) -> Color32 {
|
||||
Color32::from_rgba_premultiplied(
|
||||
(a.r() as f32 + (b.r() as f32 - a.r() as f32) * t) as u8,
|
||||
(a.g() as f32 + (b.g() as f32 - a.g() as f32) * t) as u8,
|
||||
(a.b() as f32 + (b.b() as f32 - a.b() as f32) * t) as u8,
|
||||
(a.a() as f32 + (b.a() as f32 - a.a() as f32) * t) as u8,
|
||||
)
|
||||
}
|
||||
|
||||
fn gradient_button(ui: &mut egui::Ui, text: &str, top_color: Color32, bottom_color: Color32, text_color: Color32, hover_top: Color32, hover_bottom: Color32, border_color: Color32) -> egui::Response {
|
||||
let rounding = Rounding::same(6.0);
|
||||
let min_size = Vec2::new(100.0, 32.0);
|
||||
let padding = Vec2::new(12.0, 6.0);
|
||||
|
||||
let font_id = ui.style().text_styles.get(&egui::TextStyle::Button)
|
||||
.cloned().unwrap_or(FontId::proportional(14.0));
|
||||
let galley = ui.painter().layout_no_wrap(
|
||||
text.to_string(),
|
||||
font_id,
|
||||
text_color,
|
||||
);
|
||||
|
||||
let size = Vec2::new(
|
||||
min_size.x.max(galley.size().x + 2.0 * padding.x),
|
||||
min_size.y.max(galley.size().y + 2.0 * padding.y),
|
||||
);
|
||||
|
||||
let (rect, response) = ui.allocate_exact_size(size, egui::Sense::click());
|
||||
|
||||
let n_strips = 16;
|
||||
for i in 0..n_strips {
|
||||
let t = i as f32 / n_strips as f32;
|
||||
let t2 = (i + 1) as f32 / n_strips as f32;
|
||||
let c = lerp_color(top_color, bottom_color, (t + t2) * 0.5);
|
||||
let y0 = rect.top() + rect.height() * t;
|
||||
let y1 = rect.top() + rect.height() * t2;
|
||||
let strip_rect = egui::Rect::from_min_max(
|
||||
egui::pos2(rect.left(), y0),
|
||||
egui::pos2(rect.right(), y1),
|
||||
);
|
||||
ui.painter().rect(strip_rect, Rounding::ZERO, c, Stroke::NONE);
|
||||
}
|
||||
|
||||
if response.hovered() {
|
||||
for i in 0..n_strips {
|
||||
let t = i as f32 / n_strips as f32;
|
||||
let t2 = (i + 1) as f32 / n_strips as f32;
|
||||
let c = lerp_color(hover_top, hover_bottom, (t + t2) * 0.5);
|
||||
let y0 = rect.top() + rect.height() * t;
|
||||
let y1 = rect.top() + rect.height() * t2;
|
||||
let strip_rect = egui::Rect::from_min_max(
|
||||
egui::pos2(rect.left(), y0),
|
||||
egui::pos2(rect.right(), y1),
|
||||
);
|
||||
ui.painter().rect(strip_rect, Rounding::ZERO, c, Stroke::NONE);
|
||||
}
|
||||
}
|
||||
|
||||
ui.painter().rect(rect, rounding, Color32::TRANSPARENT, Stroke::new(1.0, border_color));
|
||||
|
||||
ui.painter().galley(
|
||||
egui::pos2(rect.center().x - galley.size().x / 2.0, rect.center().y - galley.size().y / 2.0),
|
||||
galley,
|
||||
text_color,
|
||||
);
|
||||
|
||||
if let Some(cursor) = ui.visuals().interact_cursor {
|
||||
if response.hovered() {
|
||||
ui.ctx().set_cursor_icon(cursor);
|
||||
}
|
||||
}
|
||||
|
||||
response
|
||||
}
|
||||
|
||||
pub fn primary_button(ui: &mut egui::Ui, text: &str) -> egui::Response {
|
||||
gradient_button(ui, text,
|
||||
Color32::from_rgb(50, 130, 255),
|
||||
Color32::from_rgb(13, 110, 253),
|
||||
Color32::WHITE,
|
||||
Color32::from_rgb(70, 150, 255),
|
||||
Color32::from_rgb(30, 130, 255),
|
||||
Color32::from_rgb(13, 110, 253))
|
||||
}
|
||||
|
||||
pub fn secondary_button(ui: &mut egui::Ui, text: &str) -> egui::Response {
|
||||
gradient_button(ui, text,
|
||||
Color32::from_rgb(130, 140, 150),
|
||||
Color32::from_rgb(100, 110, 120),
|
||||
Color32::from_rgb(158, 158, 175),
|
||||
Color32::from_rgb(150, 160, 170),
|
||||
Color32::from_rgb(120, 130, 140),
|
||||
Color32::from_rgb(100, 110, 120))
|
||||
}
|
||||
|
||||
pub fn danger_button(ui: &mut egui::Ui, text: &str) -> egui::Response {
|
||||
gradient_button(ui, text,
|
||||
Color32::from_rgb(240, 83, 99),
|
||||
Color32::from_rgb(200, 40, 60),
|
||||
Color32::WHITE,
|
||||
Color32::from_rgb(255, 100, 120),
|
||||
Color32::from_rgb(220, 60, 80),
|
||||
Color32::from_rgb(200, 40, 60))
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn white_grd_btn(ui: &mut egui::Ui, text: &str) -> egui::Response {
|
||||
gradient_button(ui, text,
|
||||
Color32::from_rgb(255, 255, 255),
|
||||
Color32::from_rgb(246, 246, 246),
|
||||
Color32::from_rgb(102, 102, 102),
|
||||
Color32::from_rgb(246, 246, 246),
|
||||
Color32::from_rgb(255, 255, 255),
|
||||
Color32::from_rgb(177, 177, 177))
|
||||
}
|
||||
#[allow(dead_code)]
|
||||
pub fn btn_dark_blue(ui: &mut egui::Ui, text: &str) -> egui::Response {
|
||||
gradient_button(ui, text,
|
||||
Color32::from_rgb(99, 184, 238),
|
||||
Color32::from_rgb(70, 140, 207),
|
||||
Color32::WHITE,
|
||||
Color32::from_rgb(70, 140, 207),
|
||||
Color32::from_rgb(99, 184, 238),
|
||||
Color32::from_rgb(56, 102, 163))
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn light_gray_btn(ui: &mut egui::Ui, text: &str) -> egui::Response {
|
||||
gradient_button(ui, text,
|
||||
Color32::from_rgb(249, 249, 249), // üst: #f9f9f9
|
||||
Color32::from_rgb(233, 233, 233), // alt: #e9e9e9
|
||||
Color32::from_rgb(102, 102, 102), // metin: #666666
|
||||
Color32::from_rgb(233, 233, 233), // hover üst (ters)
|
||||
Color32::from_rgb(249, 249, 249), // hover alt (ters)
|
||||
Color32::from_rgb(227, 195, 227)) // border: #e3c7e3
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
pub mod theme;
|
||||
pub mod buttons;
|
||||
pub mod slideshow;
|
||||
pub mod error_screen;
|
||||
|
||||
|
||||
+5
-85
@@ -15,6 +15,8 @@ use std::sync::atomic::{AtomicU32, Ordering};
|
||||
static BG_DARK: AtomicU32 = AtomicU32::new(0x121214);
|
||||
static BG_PANEL: AtomicU32 = AtomicU32::new(0x1A1A1E);
|
||||
static BG_WIDGET: AtomicU32 = AtomicU32::new(0x242428);
|
||||
|
||||
|
||||
static BORDER: AtomicU32 = AtomicU32::new(0x323238);
|
||||
static TEXT: AtomicU32 = AtomicU32::new(0xF3F3F5);
|
||||
static TEXT_DIM: AtomicU32 = AtomicU32::new(0x9E9EAF);
|
||||
@@ -284,96 +286,14 @@ fn build_style() -> egui::Style {
|
||||
]
|
||||
.into();
|
||||
|
||||
style.visuals.interact_cursor = Some(egui::CursorIcon::PointingHand);
|
||||
|
||||
style
|
||||
}
|
||||
|
||||
// ─── Yardımcı widget'lar ─────────────────────────────────────────
|
||||
|
||||
fn lerp_color(a: Color32, b: Color32, t: f32) -> Color32 {
|
||||
Color32::from_rgba_premultiplied(
|
||||
(a.r() as f32 + (b.r() as f32 - a.r() as f32) * t) as u8,
|
||||
(a.g() as f32 + (b.g() as f32 - a.g() as f32) * t) as u8,
|
||||
(a.b() as f32 + (b.b() as f32 - a.b() as f32) * t) as u8,
|
||||
(a.a() as f32 + (b.a() as f32 - a.a() as f32) * t) as u8,
|
||||
)
|
||||
}
|
||||
|
||||
fn gradient_button(ui: &mut egui::Ui, text: &str, top_color: Color32, bottom_color: Color32, text_color: Color32) -> egui::Response {
|
||||
let rounding = Rounding::same(6.0);
|
||||
let min_size = Vec2::new(100.0, 32.0);
|
||||
let padding = Vec2::new(12.0, 6.0);
|
||||
|
||||
let font_id = ui.style().text_styles.get(&egui::TextStyle::Button)
|
||||
.cloned().unwrap_or(FontId::proportional(14.0));
|
||||
let galley = ui.painter().layout_no_wrap(
|
||||
text.to_string(),
|
||||
font_id,
|
||||
text_color,
|
||||
);
|
||||
|
||||
let size = Vec2::new(
|
||||
min_size.x.max(galley.size().x + 2.0 * padding.x),
|
||||
min_size.y.max(galley.size().y + 2.0 * padding.y),
|
||||
);
|
||||
|
||||
let (rect, response) = ui.allocate_exact_size(size, egui::Sense::click());
|
||||
|
||||
// Gradient arka plan (16 yatay şerit)
|
||||
let n_strips = 16;
|
||||
for i in 0..n_strips {
|
||||
let t = i as f32 / n_strips as f32;
|
||||
let t2 = (i + 1) as f32 / n_strips as f32;
|
||||
let c = lerp_color(top_color, bottom_color, (t + t2) * 0.5);
|
||||
let y0 = rect.top() + rect.height() * t;
|
||||
let y1 = rect.top() + rect.height() * t2;
|
||||
let strip_rect = egui::Rect::from_min_max(
|
||||
egui::pos2(rect.left(), y0),
|
||||
egui::pos2(rect.right(), y1),
|
||||
);
|
||||
ui.painter().rect(strip_rect, Rounding::ZERO, c, Stroke::NONE);
|
||||
}
|
||||
|
||||
// Yuvarlak köşe efekti için border
|
||||
ui.painter().rect(rect, rounding, Color32::TRANSPARENT, Stroke::new(1.0, bottom_color));
|
||||
|
||||
// Hover efekti
|
||||
if response.hovered() {
|
||||
ui.painter().rect(rect, rounding, Color32::WHITE.linear_multiply(0.10), Stroke::NONE);
|
||||
}
|
||||
|
||||
// Metin
|
||||
ui.painter().galley(
|
||||
egui::pos2(rect.center().x - galley.size().x / 2.0, rect.center().y - galley.size().y / 2.0),
|
||||
galley,
|
||||
text_color,
|
||||
);
|
||||
|
||||
response
|
||||
}
|
||||
|
||||
/// Ana eylem butonu (mavi gradient).
|
||||
pub fn primary_button(ui: &mut egui::Ui, text: &str) -> egui::Response {
|
||||
gradient_button(ui, text,
|
||||
Color32::from_rgb(50, 130, 255), // üst: açık mavi
|
||||
Color32::from_rgb(13, 110, 253), // alt: koyu mavi
|
||||
Color32::WHITE)
|
||||
}
|
||||
|
||||
/// İkincil buton (gri gradient).
|
||||
pub fn secondary_button(ui: &mut egui::Ui, text: &str) -> egui::Response {
|
||||
gradient_button(ui, text,
|
||||
Color32::from_rgb(130, 140, 150), // üst: açık gri
|
||||
Color32::from_rgb(100, 110, 120), // alt: koyu gri
|
||||
c_text_dim())
|
||||
}
|
||||
|
||||
/// İptal/Danger butonu (kırmızı gradient).
|
||||
pub fn danger_button(ui: &mut egui::Ui, text: &str) -> egui::Response {
|
||||
gradient_button(ui, text,
|
||||
Color32::from_rgb(240, 83, 99), // üst: açık kırmızı
|
||||
Color32::from_rgb(200, 40, 60), // alt: koyu kırmızı
|
||||
Color32::WHITE)
|
||||
}
|
||||
pub use super::buttons::*;
|
||||
|
||||
/// Bölüm başlığı — büyük, açık renkli, alt çizgisiz.
|
||||
pub fn section_heading(ui: &mut egui::Ui, text: &str) {
|
||||
|
||||
Reference in New Issue
Block a user