From c1580f6ace288a68a3523b4a706f6dccae3309d0 Mon Sep 17 00:00:00 2001
From: punix <polunga40@unity-mail.de>
Date: Sun, 15 Jun 2025 15:37:27 +0200
Subject: [PATCH] import LxTools with try except  and add images in readme

---
 Changelog    |   8 +-
 README.md    |  11 ++-
 logviewer.py |   1 -
 message.py   | 222 ++++++++++++++++++++-------------------------------
 4 files changed, 102 insertions(+), 140 deletions(-)

diff --git a/Changelog b/Changelog
index 0488a9d..e976829 100644
--- a/Changelog
+++ b/Changelog
@@ -4,7 +4,13 @@ Changelog for shared_libs
 
  - add Info Window for user in delete logfile
    bevore delete logfile.
- 
+
+  ### Added
+15-06-2025
+
+ - Update MessageDialog Class description
+ - import LxTools with try exception.
+
   ### Added
 14-06-2025
 
diff --git a/README.md b/README.md
index 24b594c..efead32 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,12 @@
 # shared_libs
 
-Module Project for apps by git.ilunix.de
\ No newline at end of file
+Module Project for apps by git.ilunix.de
+Examples with a Theme from Projekt Wire-Py 
+
+# Screenshots
+[![info_example.png](https://fb.ilunix.de/api/public/dl/KtaTPMMq=true)](https://fb.ilunix.de/share/KtaTPMMq)
+[![error_example.png](https://fb.ilunix.de/api/public/dl/cRO_ksrM=true)](https://fb.ilunix.de/share/cRO_ksrM)
+[![warning_example.png](https://fb.ilunix.de/api/public/dl/1JEdSJcI=true)](https://fb.ilunix.de/share/1JEdSJcI)
+[![question_light_example.png](https://fb.ilunix.de/api/public/dl/XxNey7y7=true)](https://fb.ilunix.de/share/1XxNey7y7)
+[![question_dark_example.png](https://fb.ilunix.de/api/public/dl/4HCxiNwB=true)](https://fb.ilunix.de/share/4HCxiNwB)
+[![example_with_own_title_and_icon.png](https://fb.ilunix.de/api/public/dl/uui8b1xx=true)](https://fb.ilunix.de/share/uui8b1xx)
\ No newline at end of file
diff --git a/logviewer.py b/logviewer.py
index bf4944c..d5b9cae 100755
--- a/logviewer.py
+++ b/logviewer.py
@@ -17,7 +17,6 @@ from shared_libs.common_tools import (
 )
 import sys
 from file_and_dir_ensure import prepare_app_environment
-import webbrowser
 
 
 class LogViewer(tk.Tk):
diff --git a/message.py b/message.py
index d52f931..f79714c 100644
--- a/message.py
+++ b/message.py
@@ -2,155 +2,104 @@ import os
 from typing import List, Optional, Dict
 import tkinter as tk
 from tkinter import ttk
-from shared_libs.common_tools import LxTools
 
-"""
-####################################################
-Attention! MessageDialog returns different values.
-From 3 buttons with Cancel, Cancel and the Close (x) 
-None returns. otherwise always False.
-####################################################
-Usage Examples
-1. Basic Info Dialog
-from tkinter import Tk
-
-root = Tk()
-dialog = MessageDialog(
-    message_type="info",
-    text="This is an information message.",
-    buttons=["OK"],
-    master=root,
-)
-result = dialog.show()
-print("User clicked OK:", result)
-
------------------------------------------------------
-My Favorite Example,
-for simply information message:
-
-MessageDialog(text="This is an information message.")
-result = MessageDialog(text="This is an information message.").show()
------------------------------------------------------
-Explanation: if you need the return value e.g. in the vaiable result, 
-you need to add .show(). otherwise only if no root.mainloop z.b is used to test the window.
-#####################################################
-
-2. Error Dialog with Custom Icon and Command
-def on_cancel():
-    print("User canceled the operation.")
-
-root = Tk()
-result = MessageDialog(
-    message_type="error",
-    text="An error occurred during processing.",
-    buttons=["Retry", "Cancel"],
-    commands=[None, on_cancel],
-    icon="/path/to/custom/error_icon.png",
-    title="Critical Error"
-).show()
-
-print("User clicked Retry:", result)
-
------------------------------------------------------
-My Favorite Example,
-for simply Error message:
-
-MessageDialog(
-    "error",
-    text="An error occurred during processing.",
-).show()
-
-#####################################################
-
-3. Confirmation Dialog with Yes/No Buttons
-def on_confirm():
-    print("User confirmed the action.")
-
-root = Tk()
-dialog = MessageDialog(
-    message_type="ask",
-    text="Are you sure you want to proceed?",
-    buttons=["Yes", "No"],
-    commands=[on_confirm, None], # Either use comando or work with the values True and False
-)
-result = dialog.show()
-print("User confirmed:", result)
------------------------------------------------------
-
-My Favorite Example,
-for simply Question message:
-
-dialog = MessageDialog(
-        "ask",
-        text="Are you sure you want to proceed?",
-        buttons=["Yes", "No"]
-    ).show()
-#####################################################
-
-4. Warning Dialog with Custom Title
-
-root = Tk()
-dialog = MessageDialog(
-    message_type="warning",
-    text="This action cannot be undone.",
-    buttons=["Proceed", "Cancel"],
-    title="Warning: Irreversible Action"
-)
-result = dialog.show()
-print("User proceeded:", result)
------------------------------------------------------
-And a special example for a "open link" button:
-Be careful not to forget to import it into the script in which this dialog is used!!!
-import webbrowser
-from functools import partial
-
-dialog = MessageDialog(
-    "ask",
-    text="Are you sure you want to proceed?",
-    buttons=["Yes", "Go to Exapmle"],
-    commands=[
-        None,  # Default on "OK"
-        partial(webbrowser.open, "https://exapmle.com"),
-    ],
-    icon="/pathh/to/custom/icon.png",
-    title="Example",
-).show()
-
-
-In all dialogues, a font can also be specified as a tuple. With font=("ubuntu", 11)
-and wraplength=300, the text is automatically wrapped.
-"""
+try:
+    from manager import LxTools
+except (ModuleNotFoundError, NameError):
+    from shared_libs.common_tools import LxTools
 
 
 class MessageDialog:
     """
-    A customizable message dialog window using tkinter.
+    A customizable message dialog window using tkinter for user interaction.
 
     This class creates modal dialogs for displaying information, warnings, errors,
-    or questions to the user. It supports multiple button configurations and custom
-    icons. The dialog is centered on the screen and handles user interactions.
+    or questions to the user. It supports multiple button configurations, custom
+    icons, keyboard navigation, and command binding. The dialog is centered on the
+    screen and handles user interactions with focus management and accessibility.
 
     Attributes:
         message_type (str): Type of message ("info", "error", "warning", "ask").
-        text (str): Main message content.
+        text (str): Main message content to display.
         buttons (List[str]): List of button labels (e.g., ["OK", "Cancel"]).
-        result (bool): True if the user clicked a positive button (like "Yes" or "OK"), else False.
-        icons: Dictionary mapping message types to tkinter.PhotoImage objects.
+        result (bool or None):
+            - True for positive actions (Yes, OK)
+            - False for negative actions (No, Cancel)
+            - None if "Cancel" was clicked with ≥3 buttons
+        icons: Dictionary mapping message types to tkinter.PhotoImage objects
 
     Parameters:
-        message_type: Type of message dialog (default: "info").
-        text: Message content to display.
-        buttons: List of button labels (default: ["OK"]).
-        master: Parent tkinter window (optional).
-        commands: List of callables for each button (default: [None]).
-        icon: Custom icon path (overrides default icons if provided).
-        title: Window title (default: derived from message_type).
+        message_type: Type of message dialog (default: "info")
+        text: Message content to display
+        buttons: List of button labels (default: ["OK"])
+        master: Parent tkinter window (optional)
+        commands: List of callables for each button (default: [None])
+        icon: Custom icon path (overrides default icons if provided)
+        title: Window title (default: derived from message_type)
+        font: Font tuple for text styling
+        wraplength: Text wrapping width in pixels
 
     Methods:
         _get_title(): Returns the default window title based on message type.
         _load_icons(): Loads icons from system paths or fallback locations.
         _on_button_click(button_text): Sets result and closes the dialog.
-        show(): Displays the dialog and waits for user response (returns self.result).
+        show(): Displays the dialog and waits for user response.
+
+    Example Usage:
+
+    1. Basic Info Dialog:
+    >>> MessageDialog(
+    ...     text="This is an information message.")
+    >>> result = dialog.show()
+    >>> print("User clicked OK:", result)
+
+    Notes:
+        My Favorite Example,
+        for simply information message:
+
+    >>> MessageDialog(text="This is an information message.")
+    >>> result = MessageDialog(text="This is an information message.").show()
+
+    Example Usage:
+
+    2. Error Dialog with Custom Command:
+    >>> def on_retry():
+    ...     print("User selected Retry")
+
+    >>> dialog = MessageDialog(
+    ...     message_type="error",
+    ...     text="An error occurred during processing.",
+    ...     buttons=["Retry", "Cancel"],
+    ...     commands=[on_retry, None],
+    ...     title="Critical Error"
+    ... )
+    >>> result = dialog.show()
+    >>> print("User selected Retry:", result)
+
+    Example Usage:
+
+    3. And a special example for a "open link" button:
+    Be careful not to forget to import it into the script in which
+    this dialog is used!!! import webbrowser from functools import partial
+
+    >>> MessageDialog(
+    ...     "info"
+    ...     text="This is an information message.",
+    ...     buttons=["Yes", "Go to Exapmle"],
+    ...     commands=[
+    ...         None,  # Default on "OK"
+    ...         partial(webbrowser.open, "https://exapmle.com"),
+    ...    ],
+    ...     icon="/pathh/to/custom/icon.png",
+    ...     title="Example",
+    ... )
+
+    Notes:
+        - Returns None if "Cancel" was clicked with ≥3 buttons
+        - Supports keyboard navigation (Left/Right arrows and Enter)
+        - Dialog automatically centers on screen
+        - Result is False for window close (X) with 2 buttons
+        - Font and wraplength parameters enable text styling
     """
 
     DEFAULT_ICON_PATH = "/usr/share/icons/lx-icons"
@@ -191,7 +140,7 @@ class MessageDialog:
 
         # Layout
         frame = ttk.Frame(self.window)
-        frame.pack(expand=True, fill="both")
+        frame.pack(expand=True, fill="both", padx=15, pady=8)
 
         # Grid-Configuration
         frame.grid_rowconfigure(0, weight=1)
@@ -218,13 +167,12 @@ class MessageDialog:
             row=0,
             column=1,
             padx=(10, 20),
-            pady=(8, 20),
             sticky="nsew",
         )
 
         # Create button frame
         self.button_frame = ttk.Frame(frame)
-        self.button_frame.grid(row=1, columnspan=2, pady=(15, 10))
+        self.button_frame.grid(row=1, columnspan=2, pady=(8, 10))
 
         for i, btn_text in enumerate(buttons):
             if commands and len(commands) > i and commands[i] is not None:
@@ -243,7 +191,7 @@ class MessageDialog:
                 )
 
             padx_value = 50 if self.icon is not None and len(buttons) == 2 else 10
-            btn.pack(side="left" if i == 0 else "right", padx=padx_value, pady=15)
+            btn.pack(side="left" if i == 0 else "right", padx=padx_value, pady=5)
             btn.focus_set() if i == 0 else None  # Set focus on first button
             self.buttons_widgets.append(btn)
 
@@ -309,12 +257,12 @@ class MessageDialog:
                     if os.path.exists(icon_paths[key]):
                         self.icons[key] = tk.PhotoImage(file=icon_paths[key])
                     else:
-                        self.icons[key] = tk.PhotoImage(file=fallback_paths[key])
+                        if os.path.exists(fallback_paths[key]):
+                            self.icons[key] = tk.PhotoImage(file=fallback_paths[key])
             except Exception as e:
                 print(f"Error on load Icon '{[key]}': {e}")
                 self.icons[key] = tk.PhotoImage()
                 print(f"⚠️ No Icon found for '{key}'. Use standard Tkinter icon.")
-
         return self.icons
 
     def _get_icon_path(self) -> str:
-- 
2.49.1