@@ -141,8 +141,13 @@ impl App { |
| 141 | 141 | // Create UI widgets (positioned in controls area) |
| 142 | 142 | let controls_y = (WINDOW_HEIGHT - 100) as i32; |
| 143 | 143 | |
| 144 | | - // Profile dropdown on the left |
| 145 | | - let mut dropdown_profiles = Dropdown::new(10, controls_y + 60, 150, 32); |
| 144 | + // Buttons on the left |
| 145 | + let btn_apply = Button::new(10, controls_y + 60, 70, 32, "Apply"); |
| 146 | + let btn_revert = Button::new(90, controls_y + 60, 70, 32, "Revert"); |
| 147 | + let btn_save = Button::new(170, controls_y + 60, 60, 32, "Save"); |
| 148 | + |
| 149 | + // Profile dropdown and Save As on the right |
| 150 | + let mut dropdown_profiles = Dropdown::new(WINDOW_WIDTH as i32 - 260, controls_y + 60, 150, 32); |
| 146 | 151 | let profile_names: Vec<String> = config.profiles.keys().cloned().collect(); |
| 147 | 152 | let current_profile = config.general.default_profile.clone(); |
| 148 | 153 | if profile_names.is_empty() { |
@@ -151,11 +156,6 @@ impl App { |
| 151 | 156 | dropdown_profiles.set_items(profile_names); |
| 152 | 157 | } |
| 153 | 158 | dropdown_profiles.set_selected_by_name(¤t_profile); |
| 154 | | - |
| 155 | | - // Buttons on the right |
| 156 | | - let btn_apply = Button::new(WINDOW_WIDTH as i32 - 370, controls_y + 60, 80, 32, "Apply"); |
| 157 | | - let btn_revert = Button::new(WINDOW_WIDTH as i32 - 280, controls_y + 60, 80, 32, "Revert"); |
| 158 | | - let btn_save = Button::new(WINDOW_WIDTH as i32 - 190, controls_y + 60, 80, 32, "Save"); |
| 159 | 159 | let btn_save_as = Button::new(WINDOW_WIDTH as i32 - 100, controls_y + 60, 90, 32, "Save As"); |
| 160 | 160 | |
| 161 | 161 | Ok(Self { |
@@ -327,10 +327,10 @@ impl App { |
| 327 | 327 | return EventResult::Redraw; |
| 328 | 328 | } |
| 329 | 329 | if self.btn_save_as.handle_event(event) { |
| 330 | | - // Show save-as input |
| 330 | + // Show save-as input (appears above the dropdown) |
| 331 | 331 | let size = self.renderer.size(); |
| 332 | 332 | let controls_y = size.height.saturating_sub(100) as i32; |
| 333 | | - let mut input = TextInput::new(180, controls_y + 60, 150, 32); |
| 333 | + let mut input = TextInput::new(size.width as i32 - 260, controls_y + 25, 150, 32); |
| 334 | 334 | input.set_placeholder("Profile name"); |
| 335 | 335 | input.set_active(true); |
| 336 | 336 | self.save_as_input = Some(input); |
@@ -688,15 +688,19 @@ impl App { |
| 688 | 688 | |
| 689 | 689 | // Reposition widgets |
| 690 | 690 | let controls_y = size.height.saturating_sub(100) as i32; |
| 691 | | - self.dropdown_profiles.set_position(10, controls_y + 60); |
| 692 | | - self.btn_apply.set_position(size.width as i32 - 370, controls_y + 60); |
| 693 | | - self.btn_revert.set_position(size.width as i32 - 280, controls_y + 60); |
| 694 | | - self.btn_save.set_position(size.width as i32 - 190, controls_y + 60); |
| 691 | + |
| 692 | + // Buttons on the left |
| 693 | + self.btn_apply.set_position(10, controls_y + 60); |
| 694 | + self.btn_revert.set_position(90, controls_y + 60); |
| 695 | + self.btn_save.set_position(170, controls_y + 60); |
| 696 | + |
| 697 | + // Dropdown and Save As on the right |
| 698 | + self.dropdown_profiles.set_position(size.width as i32 - 260, controls_y + 60); |
| 695 | 699 | self.btn_save_as.set_position(size.width as i32 - 100, controls_y + 60); |
| 696 | 700 | |
| 697 | | - // Reposition save-as input if active |
| 701 | + // Reposition save-as input if active (next to dropdown) |
| 698 | 702 | if let Some(ref mut input) = self.save_as_input { |
| 699 | | - input.set_position(180, controls_y + 60); |
| 703 | + input.set_position(size.width as i32 - 260, controls_y + 25); |
| 700 | 704 | } |
| 701 | 705 | } |
| 702 | 706 | |
@@ -741,7 +745,7 @@ impl App { |
| 741 | 745 | self.theme.item_description, |
| 742 | 746 | )?; |
| 743 | 747 | |
| 744 | | - // Status message (show for 3 seconds) |
| 748 | + // Status message (show for 3 seconds) - after the left buttons |
| 745 | 749 | if let Some((ref msg, instant)) = self.status_message { |
| 746 | 750 | if instant.elapsed().as_secs() < 3 { |
| 747 | 751 | let color = if msg.contains("error") || msg.contains("Failed") { |
@@ -750,28 +754,34 @@ impl App { |
| 750 | 754 | Color::new(0.4, 0.8, 0.4, 1.0) // Green |
| 751 | 755 | }; |
| 752 | 756 | self.renderer |
| 753 | | - .text_default(msg, 10.0, (controls_y + 60) as f64, color)?; |
| 757 | + .text_default(msg, 250.0, (controls_y + 70) as f64, color)?; |
| 754 | 758 | } |
| 755 | 759 | } |
| 756 | 760 | |
| 757 | | - // Dirty indicator (above buttons) |
| 761 | + // Profile label and dirty indicator (above dropdown on right) |
| 758 | 762 | if self.monitor_view.is_dirty() { |
| 763 | + // Show "Profile: * unsaved" when dirty |
| 764 | + self.renderer.text_default( |
| 765 | + "Profile:", |
| 766 | + (size.width - 260) as f64, |
| 767 | + (controls_y + 45) as f64, |
| 768 | + self.theme.item_description, |
| 769 | + )?; |
| 759 | 770 | self.renderer.text_default( |
| 760 | 771 | "* unsaved", |
| 761 | | - (size.width - 370) as f64, |
| 772 | + (size.width - 200) as f64, |
| 762 | 773 | (controls_y + 45) as f64, |
| 763 | 774 | Color::new(1.0, 0.7, 0.3, 1.0), // Orange |
| 764 | 775 | )?; |
| 776 | + } else { |
| 777 | + self.renderer.text_default( |
| 778 | + "Profile:", |
| 779 | + (size.width - 260) as f64, |
| 780 | + (controls_y + 45) as f64, |
| 781 | + self.theme.item_description, |
| 782 | + )?; |
| 765 | 783 | } |
| 766 | 784 | |
| 767 | | - // Profile label |
| 768 | | - self.renderer.text_default( |
| 769 | | - "Profile:", |
| 770 | | - 10.0, |
| 771 | | - (controls_y + 45) as f64, |
| 772 | | - self.theme.item_description, |
| 773 | | - )?; |
| 774 | | - |
| 775 | 785 | // Render dropdown |
| 776 | 786 | self.dropdown_profiles.render(&self.renderer, &self.theme)?; |
| 777 | 787 | |