compactrs 2025.12.25

High-performance native Windows file compressor using WOF (Windows Overlay Filter)
#![allow(unsafe_op_in_unsafe_fn)]

//! HeaderPanel component - manages the header area with top-right buttons.
//!
//! This component contains the Settings, About, and Console buttons
//! positioned in the top-right corner of the main window.

use crate::types::*;

use super::base::Component;
use crate::ui::builder::ControlBuilder;
use crate::ui::controls::apply_button_theme;
use crate::ui::layout::{layout_horizontal, LayoutItem, SizePolicy};

const ICON_SETTINGS: &[u16] = &[0xE713, 0]; // Settings
const ICON_KEYBOARD: &[u16] = &[0xE765, 0]; // Keyboard
const ICON_ABOUT: &[u16] = &[0xE946, 0];    // Info
const ICON_CONSOLE: &[u16] = &[0xE756, 0];  // CommandPrompt
const ICON_WATCHER: &[u16] = &[0xE9D2, 0];  // Clock/Alarm

/// Configuration for HeaderPanel control IDs.
pub struct HeaderPanelIds {
    pub btn_settings: u16,
    pub btn_about: u16,
    pub btn_shortcuts: u16,
    pub btn_console: u16,
    pub btn_watcher: u16,
}

/// HeaderPanel component containing the top-right action buttons.
///
/// # Layout
/// Buttons are positioned in the top-right corner:
/// [>_] [?] [⚙]
/// Console, About, Settings (right to left)
pub struct HeaderPanel {
    hwnd_settings: HWND,
    hwnd_about: HWND,
    hwnd_shortcuts: HWND,
    hwnd_console: HWND,
    hwnd_watcher: HWND,
    ids: HeaderPanelIds,
}

impl HeaderPanel {
    /// Creates a new HeaderPanel with uninitialized handles.
    ///
    /// Call `create()` to actually create the Win32 controls.
    pub fn new(ids: HeaderPanelIds) -> Self {
        Self {
            hwnd_settings: std::ptr::null_mut(),
            hwnd_about: std::ptr::null_mut(),
            hwnd_shortcuts: std::ptr::null_mut(),
            hwnd_console: std::ptr::null_mut(),
            hwnd_watcher: std::ptr::null_mut(),
            ids,
        }
    }

    /// Returns the Settings button HWND.
    #[inline]
    pub fn settings_hwnd(&self) -> HWND {
        self.hwnd_settings
    }

    /// Returns the About button HWND.
    #[inline]
    pub fn about_hwnd(&self) -> HWND {
        self.hwnd_about
    }

    /// Returns the Shortcuts button HWND.
    #[inline]
    pub fn shortcuts_hwnd(&self) -> HWND {
        self.hwnd_shortcuts
    }

    /// Returns the Console button HWND.
    #[inline]
    pub fn console_hwnd(&self) -> HWND {
        self.hwnd_console
    }

    /// Returns the Watcher button HWND.
    #[inline]
    pub fn watcher_hwnd(&self) -> HWND {
        self.hwnd_watcher
    }

    /// Sets the font for all child controls.
    ///
    /// # Arguments
    /// * `hfont` - The font handle to apply
    ///
    /// # Safety
    /// Calls Win32 SendMessageW API.
    pub unsafe fn set_font(&self, hfont: HFONT) {
        let _ = hfont;
        // Do NOT apply app font to these buttons as they use specific Icon Font.
    }
}

impl Component for HeaderPanel {
    unsafe fn create(&mut self, parent: HWND) -> Result<(), String> {
        unsafe {
            let _module = GetModuleHandleW(std::ptr::null());

            let is_dark = crate::ui::theme::is_system_dark_mode();
            let icon_font = crate::ui::theme::get_icon_font();

            // Initial positions (will be updated in on_resize)
            // These are just placeholders - real positions set in on_resize
            self.hwnd_settings = ControlBuilder::new(parent, self.ids.btn_settings)
                .text_w(ICON_SETTINGS)
                .pos(0, 0).size(30, 25).dark_mode(is_dark)
                .font(icon_font)
                .build();

            self.hwnd_about = ControlBuilder::new(parent, self.ids.btn_about)
                .text_w(ICON_ABOUT)
                .pos(0, 0).size(30, 25).dark_mode(is_dark)
                .font(icon_font)
                .build();

            self.hwnd_shortcuts = ControlBuilder::new(parent, self.ids.btn_shortcuts)
                .text_w(ICON_KEYBOARD)
                .pos(0, 0).size(30, 25).dark_mode(is_dark)
                .font(icon_font)
                .build();

            self.hwnd_console = ControlBuilder::new(parent, self.ids.btn_console)
                .text_w(ICON_CONSOLE)
                .pos(0, 0).size(30, 25).dark_mode(is_dark)
                .font(icon_font)
                .build();

            self.hwnd_watcher = ControlBuilder::new(parent, self.ids.btn_watcher)
                .text_w(ICON_WATCHER)
                .pos(0, 0).size(30, 25).dark_mode(is_dark)
                .font(icon_font)
                .build();

            Ok(())
        }
    }

    fn hwnd(&self) -> Option<HWND> {
        // This component doesn't have a single "main" HWND
        None
    }

    unsafe fn on_resize(&mut self, parent_rect: &RECT) {
        unsafe {
             // Parent rect provides everything needed.
            
            let padding = 10;
            // Header height is 25? Based on button size (30x25).
            // Let's rely on layout implementation.
            
            // Visual Order (Right -> Left): Settings, About, Shortcuts, Console, Watcher.
            // layout_horizontal is Left -> Right.
            // So: [Spacer] [Watcher] [Console] [Shortcuts] [About] [Settings]
            
            // Current manual code:
            // Settings: right - pad - btn
            // About: right - pad - btn - 35 (so 5px gap)
            
            // Layout Items:
            // Spacer: Flex(1.0)
            // Watcher: Fixed(30)
            // Console: Fixed(30)
            // Shortcuts: Fixed(30)
            // About: Fixed(30)
            // Settings: Fixed(30)
            
            // Gap should be 5.
            
            let items = [
                LayoutItem { hwnd: std::ptr::null_mut(), policy: SizePolicy::Flex(1.0) },
                LayoutItem { hwnd: self.hwnd_watcher, policy: SizePolicy::Fixed(30) },
                LayoutItem { hwnd: self.hwnd_console, policy: SizePolicy::Fixed(30) },
                LayoutItem { hwnd: self.hwnd_shortcuts, policy: SizePolicy::Fixed(30) },
                LayoutItem { hwnd: self.hwnd_about, policy: SizePolicy::Fixed(30) },
                LayoutItem { hwnd: self.hwnd_settings, policy: SizePolicy::Fixed(30) },
            ];
            
            // The existing code uses a `header_height` of 25.
            // layout_horizontal stretches items to fill height (height - padding*2).
            // If parent_rect height is large (e.g. whole window?), we shouldn't pass entire parent_rect.
            // HeaderPanel creates buttons with size(30, 25).
            // Let's assume we want a fixed height strip at the top.
            // Previous code used `header_height = 25` and `padding = 10`.
            // So top y = padding = 10. height = 25.
            
            let rect_h = 25 + (padding * 2); 
            let layout_rect = RECT {
                left: parent_rect.left,
                top: parent_rect.top, // Relative or Absolute? 
                // parent_rect comes from window.rs
                // In window.rs, HeaderPanel is created.
                // window.rs calls `header_panel.on_resize(&client_rect)`.
                // client_rect usually starts at (0,0).
                
                right: parent_rect.right,
                bottom: parent_rect.top + rect_h,
            };
            
            layout_horizontal(&layout_rect, &items, padding, 5);
        }
    }

    unsafe fn on_theme_change(&mut self, is_dark: bool) {
        unsafe {
            apply_button_theme(self.hwnd_settings, is_dark);
            apply_button_theme(self.hwnd_about, is_dark);
            apply_button_theme(self.hwnd_shortcuts, is_dark);
            apply_button_theme(self.hwnd_console, is_dark);
            apply_button_theme(self.hwnd_watcher, is_dark);
        }
    }
}