Untitled

 avatar
unknown
plain_text
3 months ago
5.7 kB
6
Indexable
class LidAlertScreen(ctk.CTkToplevel):
    def __init__(self, parent, reed_switch, main_root, on_close=None):
        super().__init__(parent)
        self.on_close = on_close
        self.reed_switch = reed_switch
        self.main_root = main_root
        self._destroyed = False
        self._destroy_lock = threading.Lock()
        self._monitor_thread = None
        
        # Retrieve current settings from main root
        self.language = getattr(self.main_root, 'LANGUAGE', 'EN')
        self.dark_mode = getattr(self.main_root, 'DARK_MODE', False)
        
        # Set up the UI
        self._setup_ui()
        
        # Start monitoring in a controlled way
        self._start_monitoring()

    def _setup_ui(self):
        """Set up all UI elements"""
        # Configure colors based on dark mode
        bg_color = '#1c1c1e' if self.dark_mode else '#f5f5f7'
        border_color = '#2c2c2e' if self.dark_mode else '#e5e5e7'
        text_color = 'white' if self.dark_mode else 'black'
        
        # Configure window
        self.configure(fg_color=bg_color)
        self.overrideredirect(True)
        self.geometry(f"{self.winfo_screenwidth()}x{self.winfo_screenheight()}+0+0")
        self.protocol("WM_DELETE_WINDOW", lambda: None)
        self.attributes('-topmost', True)
        
        # Create main container with padding
        self.container = ctk.CTkFrame(self, fg_color=bg_color, corner_radius=0)
        self.container.pack(fill='both', expand=True, padx=30, pady=30)

        # Add border frame
        self.border_frame = ctk.CTkFrame(
            self.container,
            fg_color=border_color,
            corner_radius=10
        )
        self.border_frame.pack(fill='both', expand=True, padx=10, pady=10)

        # Create alert box with pastel red background
        pastel_red = "#FFB3B3"
        self.alert_box = ctk.CTkFrame(
            self.border_frame,
            fg_color=pastel_red,
            corner_radius=8
        )
        self.alert_box.pack(fill='both', expand=True, padx=5, pady=5)

        # Add warning message
        message_text = TRANSLATIONS[self.language].get(
            'lid_open_warning',
            "WARNING: Lid is open!\nPlease close the lid to continue."
        )
        self.message_label = ctk.CTkLabel(
            self.alert_box,
            text=message_text,
            font=('Dongle', 36),
            text_color='#000000'
        )
        self.message_label.place(relx=0.5, rely=0.35, anchor='center')

        # Add warning icon
        try:
            icon_image = ctk.CTkImage(
                light_image=Image.open("icons/circle-alert-b.png"),
                dark_image=Image.open("icons/circle-alert-b.png"),
                size=(55, 55)
            )
            self.icon_label = ctk.CTkLabel(
                self.alert_box,
                image=icon_image,
                text=""
            )
        except Exception as e:
            print(f"Error loading warning icon: {e}")
            self.icon_label = ctk.CTkLabel(
                self.alert_box,
                text="⚠",
                font=('Dongle', 48)
            )
        self.icon_label.place(relx=0.5, rely=0.55, anchor='center')

    def _start_monitoring(self):
        """Start monitoring thread with proper control"""
        if not self._destroyed:
            self._monitor_thread = threading.Thread(target=self.monitor_lid, daemon=True)
            self._monitor_thread.start()

    def handle_lid_closed(self):
        """Synchronized lid closed handler"""
        with self._destroy_lock:
            if not self._destroyed:
                self._destroyed = True
                # Schedule destruction on main thread with a small delay
                self.after(100, self._safe_destroy)
                if self.on_close:
                    self.after(0, self.on_close)

    def _safe_destroy(self):
        """Safe destruction with proper thread handling"""
        try:
            with self._destroy_lock:
                if not self._destroyed:
                    return
                
            if self._monitor_thread and self._monitor_thread.is_alive():
                self._monitor_thread.join(timeout=0.1)
                
            self.destroy()
        except tkinter.TclError:
            pass
        except Exception as e:
            print(f"Safe destroy error: {e}")

    def monitor_lid(self):
        """Thread-safe lid monitoring"""
        while True:
            try:
                with self._destroy_lock:
                    if self._destroyed:
                        break
                    
                try:
                    if self.reed_switch.is_pressed:
                        self.after(0, self.handle_lid_closed)
                        break
                except Exception:
                    # Reed switch might be closed, exit gracefully
                    break
                    
                time.sleep(0.1)
            except RuntimeError:
                # Handle interpreter shutdown
                break
            except Exception as e:
                print(f"Monitor error: {e}")
                break

    def cleanup(self):
        """Enhanced cleanup with thread synchronization"""
        with self._destroy_lock:
            if self._destroyed:
                return
            self._destroyed = True
        
        try:
            self.after(100, self._safe_destroy)
        except Exception as e:
            print(f"Cleanup error: {e}")
Editor is loading...
Leave a Comment