# -*- coding: utf-8 -*-
# pylint: disable=bare-except
# pylint: disable=too-many-branches
# pylint: disable=too-many-lines
# pylint: disable=too-many-statements
# pylint: disable=invalid-name
# pylint: disable=line-too-long

"""
Copyright (c) 2019-2026 Tomasz Łuczak, TeaM-TL

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

nice GUI for ImageMagick command common used (by me)
"""
# standard modules
import datetime
import gettext
import logging
import os
import platform
import sys
import tempfile
import time

from tkinter import (
    PhotoImage,
    Canvas,
    Label,
    filedialog,
    StringVar,
    IntVar,
    TclError,
    TkVersion,
)

from PIL import ImageGrab

import darkdetect

import ttkbootstrap as ttk
from ttkbootstrap.widgets.scrolled import ScrolledText, ScrolledFrame
from ttkbootstrap.dialogs.colorchooser import ColorChooserDialog
from ttkbootstrap.dialogs import Messagebox
from ttkbootstrap.constants import (
    N,
    S,
    W,
    E,
    X,
    BOTH,
    LEFT,
    RIGHT,
    TOP,
    BOTTOM,
    END,
    DISABLED,
    NORMAL,
    HORIZONTAL,
)

# my modules
import check_new_version
import convert
import convert_pillow
import convert_common
import common
import ini_read
import ini_save
import magick
import version
import gui
import gui_bindings
import gui_tooltips

try:
    from wand.version import VERSION

    IMAGEMAGICK_WAND_VERSION = "Wand " + VERSION
    PILLOW = 0
except:
    IMAGEMAGICK_WAND_VERSION = "Wand - missing"
    PILLOW = 1

if PILLOW == 0:
    try:
        from wand.version import MAGICK_VERSION

        IMAGEMAGICK_WAND_VERSION += ", IM " + MAGICK_VERSION.split(" ")[1]
    except:
        IMAGEMAGICK_WAND_VERSION += ", IM - missing"
        PILLOW = 1

# logger = logging.getLogger(__name__)
logging.basicConfig(
    filename=os.path.join(os.path.expanduser("~"), ".fotokilof.log"),
    encoding="utf-8",
    filemode="a",
    format="%(asctime)s.%(msecs)03d :%(levelname)s: %(message)s",
    datefmt="%Y-%m-%d %H:%M:%S",
    level=logging.DEBUG,
)
# Start logging
start_time = time.time()
logging.info("Start: %s", start_time)
logging.info(IMAGEMAGICK_WAND_VERSION)

if platform.system() == "Windows":
    OS = "Windows"
elif platform.system() == "Darwin":
    OS = "MACOS"
else:
    OS = "UNIX"

# set locale for Windows
if OS == "Windows":
    import locale

    if os.getenv("LANG") is None:
        os.environ["LANG"] = locale.getlocale()[0]

localedir = os.path.join(os.path.abspath(os.path.dirname(__file__)), "locale")
if not os.path.isdir(localedir):
    localedir = os.path.join(os.getcwd(), "locale")
logging.debug("Locale directory: %s", localedir)

translate = gettext.translation("fotokilof", localedir, fallback=True)
gettext.install("fotokilof", localedir)
_ = translate.gettext

###################
# CONSTANTS
if OS == "Windows":
    PREVIEW_ORIG = 400  # preview original
    PREVIEW_NEW = 400  # preview result
    PREVIEW_COMPOSE = 400  # preview compose
    PREVIEW_LOGO = 80  # preview logo
else:
    PREVIEW_ORIG = 450
    PREVIEW_NEW = 450
    PREVIEW_COMPOSE = 450  # preview compose
    PREVIEW_LOGO = 100

preview_size_list = (
    300,
    350,
    400,
    450,
    500,
    550,
    600,
    650,
    700,
    800,
    900,
    1000,
    1200,
    1400,
    1600,
    1800,
    1920,
    "none",
)
###################


def change_ttk_theme(event):
    """Press F2 to change ttkbootstrap theme"""

    if style.theme.name == "litera":
        new = "darkly"
    else:
        new = "litera"
    style.theme_use(new)


def print_command(cmd):
    """print command in custom window"""
    t_custom.insert(END, cmd + " ")


def convert_custom_clear():
    """clear custom widget"""
    t_custom.delete(1.0, END)


def preview_orig_clear():
    """clear every preview if doesn't choose file"""
    logging.debug("clear preview")
    c_preview_orig_pi.delete("all")
    # if no original, new preview should be clear too
    preview_new_clear()


def preview_compose_clear():
    """clear preview compose if doesn't choose file"""
    logging.debug("clear preview")
    c_compose_preview_pi.delete("all")
    l_compose_preview.configure(text="")


def preview_new_clear():
    """clear every preview if doesn't choose file"""
    logging.debug("clear preview")
    c_preview_new_pi.delete("all")


def preview_new_refresh(event):
    """callback after selection of size preview"""
    # to define file_out
    if path_to_file_out(resized.get()) is not None:
        if os.path.isfile(path_to_file_out(resized.get())):
            preview_new(path_to_file_out(resized.get()))
        else:
            preview_new_clear()
    else:
        preview_new_clear()


def preview_new(file_out):
    """generate result preview"""
    if co_preview_selector_new.get() == "none" or co_preview_selector_new.get() == "":
        preview_new_clear()
    else:
        preview_picture = convert_common.preview(
            file_out, int(co_preview_selector_new.get()), PILLOW
        )
        try:
            pi_preview_new.configure(file=preview_picture["filename"])
        except TclError as error_detail:
            logging.error("preview_new: %s", error_detail)

        c_preview_new_pi.delete("all")
        c_preview_new_pi.configure(
            width=preview_picture["preview_width"],
            height=preview_picture["preview_height"],
        )
        c_preview_new_pi.create_image(0, 0, image=pi_preview_new, anchor="nw")
        l_preview_new.configure(
            text=preview_picture["width"]
            + "x"
            + preview_picture["height"]
            + " - "
            + preview_picture["size"]
        )

        gui.copy_to_clipboard(file_out)


def preview_orig_button():
    """original preview"""
    # global file_in_path
    convert_common.display_image(file_in_path.get(), PILLOW)


def preview_new_button(event=None):
    """preview new picture"""
    # to define file_out
    try:
        filename = path_to_file_out(resized.get())
        if os.path.isfile(filename):
            convert_common.display_image(filename, PILLOW)
    except:
        logging.warning("No result picture to preview")


def compose_preview_button():
    """preview picture for compose"""
    try:
        convert_common.display_image(img_compose_file.get(), PILLOW)
    except:
        logging.warning("No compose picture to preview")


def extension_from_file():
    """set extension in ComboBox same as opened file"""
    extension = os.path.splitext(file_in_path.get())[1].lower()
    try:
        co_apply_type.current(
            common.file_extension_patterns_output(PILLOW).index(extension)
        )
    except:
        logging.warning("extension_from_file: wrong extension")
        co_apply_type.current(
            common.file_extension_patterns_output(PILLOW).index(".jpg")
        )


def path_to_file_out(resize):
    """create filename of out file"""
    if resize:
        subdir = common.resize_subdir(
            img_resize.get(),
            common.empty(e1_resize_x.get()),
            common.empty(e1_resize_y.get()),
            common.empty(e2_resize.get()),
        )
        workdir = os.path.join(work_dir.get(), subdir[0])
        resized.set(1)
    else:
        workdir = work_dir.get()
        resized.set(0)

    filename = convert.out_full_filename(
        file_in_path.get(), workdir, co_apply_type.get()
    )
    return filename


def apply_all_button():
    """all option together, processing one file or whole directory"""
    if os.path.isfile(file_in_path.get()):
        progress_files.set(_("Processing"))
        root.update_idletasks()

        # single file or whole directory
        i = 0
        if file_dir_selector.get() == 0:
            files_list = [file_in_path.get()]
        else:
            dirname = os.path.dirname(file_in_path.get())
            files_list_short = common.list_of_images(dirname, OS, PILLOW)
            files_list = []
            for filename_short in files_list_short:
                files_list.append(os.path.join(dirname, filename_short))

        file_list_len = len(files_list)
        for file_in in files_list:
            if img_compose_on.get():
                # compose
                clone = convert_common.make_clone(file_in, PILLOW)
                if clone is not None:
                    clone = convert_common.compose(
                        clone,
                        img_compose_file.get(),
                        img_compose_right.get(),
                        img_compose_autoresize.get(),
                        img_compose_color.get(),
                        img_compose_gravity.get(),
                        PILLOW,
                    )
                    subdir = work_dir.get()
            elif img_custom_on.get() and not PILLOW:
                cmd = t_custom.get("1.0", "end-1c")
                subdir = work_dir.get()
            else:
                # other conversions
                clone = convert_common.make_clone(
                    file_in, PILLOW, img_vignette_color.get()
                )
                if img_crop_on.get():
                    clone = convert_common.crop(
                        file_in,
                        clone,
                        img_crop.get(),
                        img_crop_gravity.get(),
                        convert_crop_entries(),
                        PILLOW,
                    )
                if img_mirror_on.get():
                    clone = convert_common.mirror(
                        clone, img_mirror_flip.get(), img_mirror_flop.get(), PILLOW
                    )
                if img_bw_on.get():
                    clone = convert_common.bw(
                        clone, img_bw.get(), e_bw_sepia.get(), PILLOW
                    )
                if img_contrast_on.get():
                    clone = convert_common.contrast(
                        clone,
                        img_contrast.get(),
                        co_contrast_selection.get(),
                        e1_contrast.get(),
                        e2_contrast.get(),
                        PILLOW,
                    )
                if img_normalize_on.get():
                    clone = convert_common.normalize(
                        clone, img_normalize.get(), co_normalize_channel.get(), PILLOW
                    )
                if img_vignette_on.get():
                    convert_common.vignette(
                        clone,
                        e_vignette_dx.get(),
                        e_vignette_dy.get(),
                        e_vignette_radius.get(),
                        e_vignette_sigma.get(),
                        PILLOW,
                    )
                if img_rotate_on.get():
                    clone = convert_common.rotate(
                        clone,
                        img_rotate.get(),
                        img_rotate_color.get(),
                        e_rotate_own.get(),
                        PILLOW,
                    )
                if img_border_on.get():
                    clone = convert_common.border(
                        clone,
                        img_border_color.get(),
                        e_border_we.get(),
                        e_border_ns.get(),
                        PILLOW,
                    )
                if img_resize_on.get():
                    #  subdir for results if resize
                    subdir_command = common.resize_subdir(
                        img_resize.get(),
                        common.empty(e1_resize_x.get()),
                        common.empty(e1_resize_y.get()),
                        common.empty(e2_resize.get()),
                    )
                    subdir = os.path.join(work_dir.get(), subdir_command[0])
                    clone = convert_common.resize(clone, subdir_command[1], PILLOW)
                    resized.set(1)
                else:
                    resized.set(0)
                    # standard subdir for result picture
                    subdir = work_dir.get()
                if img_text_on.get():
                    clone = convert_common.text(
                        clone, convert_text_collection_data(), PILLOW
                    )
                if img_logo_on.get():
                    coordinates = (
                        common.empty(e_logo_dx.get()),
                        common.empty(e_logo_dy.get()),
                        common.empty(e_logo_width.get()),
                        common.empty(e_logo_height.get()),
                        img_logo_gravity.get(),
                    )
                    height = clone.height
                    width = clone.width
                    convert_common.pip(
                        clone, file_logo_path.get(), coordinates, width, height, PILLOW
                    )
            file_out = convert.out_full_filename(file_in, subdir, co_apply_type.get())
            if img_custom_on.get() and not PILLOW:
                magick.magick(cmd, file_in, file_out, OS)
            else:
                convert_common.save_close_clone(
                    clone, file_out, img_exif_on.get(), PILLOW
                )
            preview_new(file_out)
            # progressbar
            i = i + 1
            progress_files.set(str(i) + " " + _("of") + " " + str(file_list_len))
            progressbar_var.set(i / file_list_len * 100)
            progress_var.set(i)
            root.update_idletasks()

        # file_in_path.set(file_in)
        preview_orig()

        progress_var.set(0)
        progress_files.set(_("done"))
        progressbar_var.set(0)
        root.update_idletasks()
        # work_sub_dir.set("")  # reset subdir name for next processing
    else:
        logging.debug("No file selected")


def convert_button_common(operation_func, color=None):
    """common part for other convert_*_button functions"""
    progress_files.set(_("Processing"))
    root.update_idletasks()
    clone = convert_common.make_clone(file_in_path.get(), PILLOW, color)
    if clone is None:
        progress_files.set(_("No image to process"))
        return

    clone = operation_func(clone)

    file_out = path_to_file_out(0)
    convert_common.save_close_clone(clone, file_out, img_exif_on.get(), PILLOW)
    preview_new(file_out)

    progress_files.set(_("done"))
    progressbar_var.set(0)
    root.update_idletasks()


def convert_custom_button():
    """execute custom command"""
    progress_files.set(_("Processing"))
    root.update_idletasks()
    out_file = convert.out_full_filename(
        file_in_path.get(), work_dir.get(), co_apply_type.get()
    )
    cmd = t_custom.get("1.0", "end-1c")
    result = magick.magick(cmd, file_in_path.get(), out_file, OS)
    if result == "OK":
        preview_new(out_file)
    progress_files.set(_("done"))


def convert_contrast_button():
    """contrast button"""

    def contrast_operation(clone):
        return convert_common.contrast(
            clone,
            img_contrast.get(),
            co_contrast_selection.get(),
            e1_contrast.get(),
            e2_contrast.get(),
            PILLOW,
        )

    convert_button_common(contrast_operation)


def convert_bw_button():
    """black-white or sepia button"""

    def bw_operation(clone):
        return convert_common.bw(clone, img_bw.get(), e_bw_sepia.get(), PILLOW)

    convert_button_common(bw_operation)


def convert_normalize_button():
    """normalize button"""

    def normalize_operation(clone):
        return convert_common.normalize(
            clone, img_normalize.get(), co_normalize_channel.get(), PILLOW
        )

    convert_button_common(normalize_operation)


def convert_rotate_button():
    """Rotate button"""

    def rotate_operation(clone):
        return convert_common.rotate(
            clone, img_rotate.get(), img_rotate_color.get(), e_rotate_own.get(), PILLOW
        )

    convert_button_common(rotate_operation)


def convert_mirror_button():
    """Mirror button"""

    def mirror_operation(clone):
        return convert_common.mirror(
            clone, img_mirror_flip.get(), img_mirror_flop.get(), PILLOW
        )

    convert_button_common(mirror_operation)


def convert_resize_button():
    """Resize button"""
    progress_files.set(_("Processing"))
    root.update_idletasks()

    resize_command = common.resize_subdir(
        img_resize.get(),
        common.empty(e1_resize_x.get()),
        common.empty(e1_resize_y.get()),
        common.empty(e2_resize.get()),
    )
    file_out = path_to_file_out(1)
    clone = convert_common.make_clone(file_in_path.get(), PILLOW)
    if clone is not None:
        clone = convert_common.resize(clone, resize_command[1], PILLOW)
        convert_common.save_close_clone(clone, file_out, img_exif_on.get(), PILLOW)
        preview_new(file_out)
    progress_files.set(_("done"))


def convert_border_button():
    """Border button"""

    def border_operation(clone):
        return convert_common.border(
            clone, img_border_color.get(), e_border_we.get(), e_border_ns.get(), PILLOW
        )

    convert_button_common(border_operation)


def convert_vignette_button():
    """Vignette button"""

    def vignette_operation(clone):
        return convert_common.vignette(
            clone,
            e_vignette_dx.get(),
            e_vignette_dy.get(),
            e_vignette_radius.get(),
            e_vignette_sigma.get(),
            PILLOW,
        )

    convert_button_common(vignette_operation, img_vignette_color.get())


def convert_compose_button():
    """Compose button"""

    def compose_operation(clone):
        return convert_common.compose(
            clone,
            img_compose_file.get(),
            img_compose_right.get(),
            img_compose_autoresize.get(),
            img_compose_color.get(),
            img_compose_gravity.get(),
            PILLOW,
        )

    convert_button_common(compose_operation)


def crop_read():
    """Read size of picture and load into crop widget"""
    if file_in_path.get() is not None:
        if os.path.isfile(file_in_path.get()):
            image_size_xy = convert_common.get_image_size(file_in_path.get(), PILLOW)
            if image_size_xy != (0, 0):
                width = image_size_xy[0]
                height = image_size_xy[1]
                e1_crop_1.delete(0, "end")
                e1_crop_1.insert(0, "0")
                e2_crop_1.delete(0, "end")
                e2_crop_1.insert(0, "0")
                e3_crop_1.delete(0, "end")
                e3_crop_1.insert(0, width)
                e4_crop_1.delete(0, "end")
                e4_crop_1.insert(0, height)
                e1_crop_2.delete(0, "end")
                e1_crop_2.insert(0, "0")
                e2_crop_2.delete(0, "end")
                e2_crop_2.insert(0, "0")
                e3_crop_2.delete(0, "end")
                e3_crop_2.insert(0, width)
                e4_crop_2.delete(0, "end")
                e4_crop_2.insert(0, height)
                e1_crop_3.delete(0, "end")
                e1_crop_3.insert(0, "0")
                e2_crop_3.delete(0, "end")
                e2_crop_3.insert(0, "0")
                e3_crop_3.delete(0, "end")
                e3_crop_3.insert(0, width)
                e4_crop_3.delete(0, "end")
                e4_crop_3.insert(0, height)
                img_crop_gravity.set("C")


def convert_crop_entries():
    """dictionary with values for convert_crop function"""
    dict_return = {}
    dict_return["one_x1"] = common.empty(e1_crop_1.get())
    dict_return["one_y1"] = common.empty(e2_crop_1.get())
    dict_return["one_x2"] = common.empty(e3_crop_1.get())
    dict_return["one_y2"] = common.empty(e4_crop_1.get())
    dict_return["two_x1"] = common.empty(e1_crop_2.get())
    dict_return["two_y1"] = common.empty(e2_crop_2.get())
    dict_return["two_width"] = common.empty(e3_crop_2.get())
    dict_return["two_height"] = common.empty(e4_crop_2.get())
    dict_return["three_dx"] = common.empty(e1_crop_3.get())
    dict_return["three_dy"] = common.empty(e2_crop_3.get())
    dict_return["three_width"] = common.empty(e3_crop_3.get())
    dict_return["three_height"] = common.empty(e4_crop_3.get())
    return dict_return


def convert_crop_button():
    """Crop button"""

    def crop_operation(clone):
        return convert_common.crop(
            file_in_path.get(),
            clone,
            img_crop.get(),
            img_crop_gravity.get(),
            convert_crop_entries(),
            PILLOW,
        )

    convert_button_common(crop_operation)


def convert_text_collection_data():
    """collect text data for conversion"""
    return (
        "dummy",
        img_text_inout.get(),
        e_text_angle.get(),
        img_text_rotate.get(),
        img_text_color.get(),
        img_text_font.get(),
        e_text_size.get(),
        img_text_gravity_onoff.get(),
        img_text_gravity.get(),
        img_text_box.get(),
        img_text_box_color.get(),
        e_text_x.get(),
        e_text_y.get(),
        e_text.get(),
        img_text_arrow.get(),
    )


def convert_text_button():
    """add text"""

    def text_operation(clone):
        return convert_common.text(clone, convert_text_collection_data(), PILLOW)

    convert_button_common(text_operation)


def fonts():
    """preparing font names for ImageMagick or Pillow and load into listbox"""
    result = convert_common.fonts_list(PILLOW)
    co_text_font["values"] = result
    return result


def font_selected(event):
    """callback via bind for font selection"""
    img_text_font.set(co_text_font.get())


def compose_autoresize():
    """If autoresize is on, turn off next row with options"""
    if img_compose_autoresize.get():
        frame_compose_autoresize.grid_remove()
    else:
        frame_compose_autoresize.grid()
        compose_autoresize_gravity()


def compose_autoresize_gravity():
    """Select N, C, S or W, C, E gravity for compose"""
    if img_compose_right.get():
        rb_compose_W.grid_remove()
        rb_compose_E.grid_remove()
        rb_compose_N.grid()
        rb_compose_S.grid()
    else:
        rb_compose_N.grid_remove()
        rb_compose_S.grid_remove()
        rb_compose_W.grid()
        rb_compose_E.grid()


def convert_logo_button():
    """Logo button"""
    progress_files.set(_("Processing"))
    root.update_idletasks()
    coordinates = (
        common.empty(e_logo_dx.get()),
        common.empty(e_logo_dy.get()),
        common.empty(e_logo_width.get()),
        common.empty(e_logo_height.get()),
        img_logo_gravity.get(),
    )
    clone = convert_common.make_clone(file_in_path.get(), PILLOW)
    if clone is not None:
        convert_common.pip(
            clone, file_logo_path.get(), coordinates, clone.width, clone.height, PILLOW
        )
        convert_common.save_close_clone(
            clone, path_to_file_out(0), img_exif_on.get(), PILLOW
        )
        preview_new(path_to_file_out(0))
    progress_files.set(_("done"))


def open_file_compose():
    """open file to append and compose"""
    filename = open_file_dialog(
        os.path.dirname(img_compose_file.get()), _("Select picture for composing")
    )
    img_compose_file.set(filename)
    if os.path.isfile(img_compose_file.get()):
        preview_compose()
    else:
        preview_compose_clear()


def open_file_logo():
    """open logo file for inserting"""
    filename = open_file_dialog(
        os.path.dirname(file_logo_path.get()), _("Select logo picture for inserting")
    )

    file_logo_path.set(filename)

    if os.path.isfile(file_logo_path.get()):
        preview_logo()
    else:
        preview_logo_clear()


def open_file():
    """open image for processing"""

    dirname = os.path.dirname(file_in_path.get())
    filename = open_file_dialog(dirname, _("Select picture for processing"))
    open_file_common(dirname, filename)


def open_file_common(cwd, filename):
    """common function for: open, first, last, next, prev"""
    if filename is not None:
        file_in_path.set(common.spacja(os.path.join(cwd, filename)))
        root.title(window_title + file_in_path.get())
        image_size = convert_common.get_image_size(file_in_path.get(), PILLOW)
        if image_size != (0, 0):
            file_in_width.set(image_size[0])
            file_in_height.set(image_size[1])
            preview_orig()
            extension_from_file()
            preview_new_refresh("none")
        else:
            preview_orig_clear()


def open_file_dialog(dir_initial, title):
    """open file dialog function for image and logo"""
    all_image_types = common.file_extension_patterns(PILLOW)
    filetypes = (
        (_("All graphics files"), all_image_types),
        (_("JPG files"), ".JPG .JPEG .jpg jpeg"),
        (_("PNG files"), ".PNG .png"),
        (_("TIFF files"), ".TIF .TIFF .tif .tiff"),
    )
    if not PILLOW:
        filetypes += (
            (_("WEBP files"), ".WEBP .webp"),
            (_("HEIC files"), ".HEIC .heic"),
            (_("HEIF files"), ".HEIC .heif"),
        )
    filetypes += ((_("ALL types"), "*"),)
    # Wand doesn't like SVG: (_("SVG files"), ".SVG .svg"),
    filename = None
    filename = filedialog.askopenfilename(
        initialdir=dir_initial, filetypes=filetypes, title=title
    )
    return filename


def open_file_with_action(action):
    """
    Open file according action: 'first', 'last', 'next', 'previous'.
    common for function open_file_(first| last| next| previous)
    """
    current_path = file_in_path.get()
    if not current_path or not os.path.isfile(current_path):
        return
    dir_name = os.path.dirname(current_path)
    file_list = common.list_of_images(dir_name, OS, PILLOW)
    current_file = os.path.basename(current_path)
    filename = common.file_from_list_of_images(file_list, current_file, action)
    open_file_common(dir_name, filename)


def open_file_last_key(event):
    """call open_file_last from bind"""
    open_file_last()


def open_file_next_key(event):
    """call open_file_next from bind"""
    open_file_next()


def open_file_first_key(event):
    """call open_file_first from bind"""
    open_file_first()


def open_file_prev_key(event):
    """call open_file_prev from bind"""
    open_file_prev()


def open_file_last():
    """Open last file"""
    open_file_with_action("last")


def open_file_next():
    """Open next file"""
    open_file_with_action("next")


def open_file_first():
    """Open first file"""
    open_file_with_action("first")


def open_file_prev():
    """Open previous file"""
    open_file_with_action("previous")


def open_screenshot():
    """Make screenshot"""
    now = datetime.datetime.now()
    today = now.strftime("%F")
    today_dir = os.path.join(tempfile.gettempdir(), today)
    if not os.path.isdir(today_dir):
        try:
            os.mkdir(today_dir)
        except:
            logging.error("Error in open_screenshot, make today directory")

    filename = now.strftime("%F_%H-%M-%S_%f") + ".png"
    out_file = os.path.normpath(os.path.join(today_dir, filename))
    do_it = 1
    try:
        screenshot = ImageGrab.grabclipboard()
    except:
        if OS == "UNIX":
            message = _(
                "Sorry, nothing in clipboard\nOr xclip (X11) or wl-clipboard (Wayland) is not installed\n Install xclip or wl-clipboard and try again!"
            )
            Messagebox.show_error(message, title=_("Missing package"))
    try:
        screenshot.save(out_file, "PNG")
    except:
        logging.error("open_screenshot(), error save from clipboards")
        do_it = 0
    if do_it:
        open_file_common(today_dir, filename)


def ask_color(initial):
    """Use color widget ColorChooserDialog from ttkbootstrap"""
    color_dialog = ColorChooserDialog(initialcolor=initial)
    color_dialog.show()
    colors = color_dialog.result
    if colors:
        result = colors.hex
    else:
        result = None
    return result


def color_choose_rotate():
    """color selection for rotate"""
    color = ask_color(img_rotate_color.get())
    if color is not None:
        img_rotate_color.set(color)
        l_rotate_color.configure(bg=color)


def color_choose_border():
    """Border color selection"""
    color = ask_color(img_border_color.get())
    if color is not None:
        img_border_color.set(color)
        l_border_color.configure(bg=color)


def color_choose_vignette():
    """color selection for rotate"""
    color = ask_color(img_vignette_color.get())
    if color is not None:
        img_vignette_color.set(color)
        l_vignette_color.configure(bg=color)


def color_choose_box():
    """Background color selection"""
    color = ask_color(img_text_color.get())
    if color is not None:
        img_text_box_color.set(color)
        l_text_color.configure(bg=img_text_box_color.get())


def color_choose():
    """Color selection"""
    color = ask_color(img_text_color.get())
    if color is not None:
        img_text_color.set(color)
        l_text_color.configure(fg=img_text_color.get())


def color_choose_compose():
    """color selection for compose"""
    color = ask_color(img_compose_color.get())
    if color is not None:
        img_compose_color.set(color)
        l_compose_color.configure(bg=color)


def ini_read_wraper():
    """Read config INI file"""
    # main
    ini_entries = ini_read.main(FILE_INI, preview_size_list)
    file_in_path.set(ini_entries["file_in_path"])
    file_dir_selector.set(ini_entries["file_dir_selector"])
    work_dir.set(ini_entries["work_dir"])
    img_exif_on.set(ini_entries["img_exif_on"])
    co_preview_selector_orig.current(
        preview_size_list.index(ini_entries["preview_orig"])
    )
    co_preview_selector_new.current(preview_size_list.index(ini_entries["preview_new"]))
    log_level.set(ini_entries["log_level"])
    match log_level.get():
        case "E":
            logging.getLogger().setLevel(logging.ERROR)
        case "W":
            logging.getLogger().setLevel(logging.WARNING)
        case "I":
            logging.getLogger().setLevel(logging.INFO)
        case _:
            logging.getLogger().setLevel(logging.DEBUG)
    img_custom_on.set(ini_entries["img_custom_on"])
    check_version.set(ini_entries["check_version"])
    # resize
    ini_entries = ini_read.resize(FILE_INI)
    img_resize_on.set(ini_entries["img_resize_on"])
    img_resize.set(ini_entries["img_resize"])
    e1_resize_x.delete(0, "end")
    e1_resize_x.insert(0, ini_entries["resize_size_pixel_x"])
    e1_resize_y.delete(0, "end")
    e1_resize_y.insert(0, ini_entries["resize_size_pixel_y"])
    e2_resize.delete(0, "end")
    e2_resize.insert(0, ini_entries["resize_size_percent"])
    # text
    ini_entries = ini_read.text(FILE_INI, img_text_font_dict, OS)
    img_text_on.set(ini_entries["img_text_on"])
    img_text_inout.set(ini_entries["img_text_inout"])
    img_text_font.set(ini_entries["text_font"])
    img_text_color.set(ini_entries["text_color"])
    img_text_gravity.set(ini_entries["img_text_gravity"])
    img_text_gravity_onoff.set(ini_entries["img_text_gravity_onoff"])
    img_text_box.set(ini_entries["text_box"])
    img_text_box_color.set(ini_entries["text_box_color"])
    img_text_arrow.set(ini_entries["text_arrow"])
    l_text_color.configure(fg=img_text_color.get(), bg=img_text_box_color.get())
    img_text_rotate.set(ini_entries["text_rotate"])
    e_text.delete(0, "end")
    e_text.insert(0, ini_entries["text_text"])
    e_text_size.delete(0, "end")
    e_text_size.insert(0, ini_entries["text_size"])
    e_text_x.delete(0, "end")
    e_text_x.insert(0, ini_entries["text_x"])
    e_text_y.delete(0, "end")
    e_text_y.insert(0, ini_entries["text_y"])
    e_text_angle.delete(0, "end")
    e_text_angle.insert(0, ini_entries["text_rotate_own"])
    # rotate
    ini_entries = ini_read.rotate(FILE_INI)
    img_rotate_on.set(ini_entries["img_rotate_on"])
    img_rotate.set(ini_entries["img_rotate"])
    e_rotate_own.delete(0, "end")
    e_rotate_own.insert(0, ini_entries["img_rotate_own"])
    img_rotate_color.set(ini_entries["img_rotate_color"])
    l_rotate_color.configure(bg=img_rotate_color.get())
    # crop
    ini_entries = ini_read.crop(FILE_INI)
    img_crop_on.set(ini_entries["img_crop_on"])
    img_crop.set(ini_entries["img_crop"])
    img_crop_gravity.set(ini_entries["img_crop_gravity"])
    e1_crop_1.delete(0, "end")
    e1_crop_1.insert(0, ini_entries["crop_1_x1"])
    e2_crop_1.delete(0, "end")
    e2_crop_1.insert(0, ini_entries["crop_1_y1"])
    e3_crop_1.delete(0, "end")
    e3_crop_1.insert(0, ini_entries["crop_1_x2"])
    e4_crop_1.delete(0, "end")
    e4_crop_1.insert(0, ini_entries["crop_1_y2"])
    e1_crop_2.delete(0, "end")
    e1_crop_2.insert(0, ini_entries["crop_2_x1"])
    e2_crop_2.delete(0, "end")
    e2_crop_2.insert(0, ini_entries["crop_2_y1"])
    e3_crop_2.delete(0, "end")
    e3_crop_2.insert(0, ini_entries["crop_2_width"])
    e4_crop_2.delete(0, "end")
    e4_crop_2.insert(0, ini_entries["crop_2_height"])
    e1_crop_3.delete(0, "end")
    e1_crop_3.insert(0, ini_entries["crop_3_dx"])
    e2_crop_3.delete(0, "end")
    e2_crop_3.insert(0, ini_entries["crop_3_dy"])
    e3_crop_3.delete(0, "end")
    e3_crop_3.insert(0, ini_entries["crop_3_width"])
    e4_crop_3.delete(0, "end")
    e4_crop_3.insert(0, ini_entries["crop_3_height"])
    # border
    ini_entries = ini_read.border(FILE_INI)
    img_border_on.set(ini_entries["img_border_on"])
    img_border_color.set(ini_entries["img_border_color"])
    l_border_color.configure(bg=img_border_color.get())
    e_border_ns.delete(0, "end")
    e_border_ns.insert(0, ini_entries["img_border_size_x"])
    e_border_we.delete(0, "end")
    e_border_we.insert(0, ini_entries["img_border_size_y"])
    # vignette
    ini_entries = ini_read.vignette(FILE_INI)
    img_vignette_on.set(ini_entries["on"])
    img_vignette_color.set(ini_entries["color"])
    l_vignette_color.configure(bg=img_vignette_color.get())
    e_vignette_dx.delete(0, "end")
    e_vignette_dx.insert(0, ini_entries["dx"])
    e_vignette_dy.delete(0, "end")
    e_vignette_dy.insert(0, ini_entries["dy"])
    e_vignette_radius.delete(0, "end")
    e_vignette_radius.insert(0, ini_entries["radius"])
    e_vignette_sigma.delete(0, "end")
    e_vignette_sigma.insert(0, ini_entries["sigma"])
    # color
    ini_entries = ini_read.colors(FILE_INI)
    img_bw_on.set(ini_entries["color_on"])
    img_bw.set(ini_entries["black_white"])
    e_bw_sepia.delete(0, "end")
    e_bw_sepia.insert(0, ini_entries["sepia"])
    # normalize
    ini_entries = ini_read.normalize(FILE_INI, normalize_channels)
    img_normalize_on.set(ini_entries["normalize_on"])
    img_normalize.set(ini_entries["normalize"])
    co_normalize_channel.current(normalize_channels.index(ini_entries["channel"]))
    # contrast
    ini_entries = ini_read.contrast(FILE_INI, contrast_selection)
    img_contrast_on.set(ini_entries["contrast_on"])
    img_contrast.set(ini_entries["contrast"])
    co_contrast_selection.current(
        contrast_selection.index(ini_entries["contrast_selection"])
    )
    e1_contrast.delete(0, "end")
    e1_contrast.insert(0, ini_entries["contrast_stretch_1"])
    e2_contrast.delete(0, "end")
    e2_contrast.insert(0, ini_entries["contrast_stretch_2"])
    # logo
    ini_entries = ini_read.logo(FILE_INI)
    img_logo_on.set(ini_entries["img_logo_on"])
    file_logo_path.set(ini_entries["logo_logo"])
    img_logo_gravity.set(ini_entries["img_logo_gravity"])
    e_logo_width.delete(0, "end")
    e_logo_width.insert(0, ini_entries["logo_width"])
    e_logo_height.delete(0, "end")
    e_logo_height.insert(0, ini_entries["logo_height"])
    e_logo_dx.delete(0, "end")
    e_logo_dx.insert(0, ini_entries["logo_dx"])
    e_logo_dy.delete(0, "end")
    e_logo_dy.insert(0, ini_entries["logo_dy"])
    # mirror
    ini_entries = ini_read.mirror(FILE_INI)
    img_mirror_on.set(ini_entries["img_mirror_on"])
    img_mirror_flip.set(ini_entries["img_mirror_flip"])
    img_mirror_flop.set(ini_entries["img_mirror_flop"])
    # compose
    ini_entries = ini_read.compose(FILE_INI, preview_size_list)
    img_compose_on.set(ini_entries["compose_on"])
    img_compose_file.set(ini_entries["compose_filename"])
    img_compose_right.set(ini_entries["compose_right"])
    img_compose_autoresize.set(ini_entries["compose_autoresize"])
    img_compose_color.set(ini_entries["compose_color"])
    img_compose_gravity.set(ini_entries["compose_gravity"])
    co_compose_preview_selector.current(preview_size_list.index(ini_entries["preview"]))


def ini_save_wraper():
    """Write variables into config file INI"""
    # main
    config = {
        "section": "Main",
        "path": file_in_path.get(),
        "work_dir": work_dir.get(),
        "file_dir": file_dir_selector.get(),
        "exif": img_exif_on.get(),
        "custom_on": img_custom_on.get(),
        "preview_orig": co_preview_selector_orig.get(),
        "preview_new": co_preview_selector_new.get(),
        "log_level": log_level.get(),
        "check_version": check_version.get(),
    }
    # resize
    resize = {
        "section": "Resize",
        "on": img_resize_on.get(),
        "resize": img_resize.get(),
        "size_pixel_x": e1_resize_x.get(),
        "size_pixel_y": e1_resize_y.get(),
        "size_percent": e2_resize.get(),
    }
    # text
    text = {
        "section": "Text",
        "on": img_text_on.get(),
        "inout": img_text_inout.get(),
        "text": e_text.get(),
        "gravity": img_text_gravity.get(),
        "gravity_onoff": img_text_gravity_onoff.get(),
        "font": img_text_font.get(),
        "size": e_text_size.get(),
        "color": img_text_color.get(),
        "box": img_text_box.get(),
        "box_color": img_text_box_color.get(),
        "x": e_text_x.get(),
        "y": e_text_y.get(),
        "text_rotate": img_text_rotate.get(),
        "text_rotate_own": e_text_angle.get(),
        "text_arrow": img_text_arrow.get(),
    }
    # rotate
    rotate = {
        "section": "Rotate",
        "on": img_rotate_on.get(),
        "rotate": img_rotate.get(),
        "own": e_rotate_own.get(),
        "color": img_rotate_color.get(),
    }
    # crop
    crop = {
        "section": "Crop",
        "on": img_crop_on.get(),
        "crop": img_crop.get(),
        "1_x1": e1_crop_1.get(),
        "1_y1": e2_crop_1.get(),
        "1_x2": e3_crop_1.get(),
        "1_y2": e4_crop_1.get(),
        "2_x1": e1_crop_2.get(),
        "2_y1": e2_crop_2.get(),
        "2_width": e3_crop_2.get(),
        "2_height": e4_crop_2.get(),
        "3_dx": e1_crop_3.get(),
        "3_dy": e2_crop_3.get(),
        "3_width": e3_crop_3.get(),
        "3_height": e4_crop_3.get(),
        "gravity": img_crop_gravity.get(),
    }
    # border
    border = {
        "section": "Border",
        "on": img_border_on.get(),
        "color": img_border_color.get(),
        "size_x": e_border_ns.get(),
        "size_y": e_border_we.get(),
    }
    # color
    color = {
        "section": "Color",
        "on": img_bw_on.get(),
        "black-white": img_bw.get(),
        "sepia": e_bw_sepia.get(),
    }
    # normalize
    normalize = {
        "section": "Normalize",
        "on": img_normalize_on.get(),
        "normalize": img_normalize.get(),
        "channel": co_normalize_channel.get(),
    }
    # contrast
    contrast = {
        "section": "Contrast",
        "on": img_contrast_on.get(),
        "contrast": img_contrast.get(),
        "selection": co_contrast_selection.get(),
        "contrast_stretch_1": e1_contrast.get(),
        "contrast_stretch_2": e2_contrast.get(),
    }
    # mirror
    mirror = {
        "section": "Mirror",
        "on": img_mirror_on.get(),
        "flip": img_mirror_flip.get(),
        "flop": img_mirror_flop.get(),
    }
    # vignette
    vignette = {
        "section": "Vignette",
        "on": img_vignette_on.get(),
        "dx": e_vignette_dx.get(),
        "dy": e_vignette_dy.get(),
        "radius": e_vignette_radius.get(),
        "sigma": e_vignette_sigma.get(),
        "color": img_vignette_color.get(),
    }
    # logo
    logo = {
        "section": "Logo",
        "on": img_logo_on.get(),
        "logo": file_logo_path.get(),
        "gravity": img_logo_gravity.get(),
        "width": e_logo_width.get(),
        "height": e_logo_height.get(),
        "dx": e_logo_dx.get(),
        "dy": e_logo_dy.get(),
    }
    # compose
    compose = {
        "section": "Compose",
        "on": img_compose_on.get(),
        "filename": img_compose_file.get(),
        "right": img_compose_right.get(),
        "autoresize": img_compose_autoresize.get(),
        "color": img_compose_color.get(),
        "gravity": img_compose_gravity.get(),
        "preview": co_compose_preview_selector.get(),
    }

    ini_save_data = (
        FILE_INI,
        config,
        resize,
        text,
        rotate,
        crop,
        border,
        color,
        normalize,
        contrast,
        mirror,
        vignette,
        logo,
        compose,
    )
    ini_save.save(ini_save_data)


def help_info(event):
    """okno info"""
    # global PWD
    license_file = os.path.join(os.path.dirname(PWD), "LICENSE")
    try:
        with open(license_file, "r", encoding="utf8") as license_fh:
            message = ""
            for line in license_fh:
                message = message + line
    except:
        logging.warning(
            "help_info: error during loading license file: %s", license_file
        )
        message = (
            "Copyright "
            + version.__copyright__
            + " "
            + version.__author__
            + " under MIT license"
        )
    Messagebox.show_info(message, title=_("License"))


def close_program():
    """close program window"""
    logging.debug("closed")
    root.quit()
    root.destroy()
    sys.exit()


def mouse_crop_nw(event):
    """Left-Upper corner"""
    x_preview = event.x
    y_preview = event.y

    xy_max = common.mouse_crop_calculation(
        file_in_width.get(), file_in_height.get(), int(co_preview_selector_orig.get())
    )
    width = int(x_preview * xy_max["x_orig"] / xy_max["x_max"])
    height = int(y_preview * xy_max["y_orig"] / xy_max["y_max"])

    if img_crop_on.get() == 1:
        if img_crop.get() == 1:
            e1_crop_1.delete(0, "end")
            e1_crop_1.insert(0, width)
            e2_crop_1.delete(0, "end")
            e2_crop_1.insert(0, height)
        elif img_crop.get() == 2:
            e1_crop_2.delete(0, "end")
            e1_crop_2.insert(0, width)
            e2_crop_2.delete(0, "end")
            e2_crop_2.insert(0, height)
        preview_orig()

    if img_text_on.get() and not img_text_gravity_onoff.get():
        e_text_x.delete(0, "end")
        e_text_x.insert(0, width)
        e_text_y.delete(0, "end")
        e_text_y.insert(0, height)


def mouse_crop_se(event):
    """Right-Lower corner"""
    if img_crop_on.get() == 1:
        x_preview = event.x
        y_preview = event.y
        xy_max = common.mouse_crop_calculation(
            file_in_width.get(),
            file_in_height.get(),
            int(co_preview_selector_orig.get()),
        )
        width = int(x_preview * xy_max["x_orig"] / xy_max["x_max"])
        height = int(y_preview * xy_max["y_orig"] / xy_max["y_max"])
        e3_crop_1.delete(0, "end")
        e3_crop_1.insert(0, width)
        e4_crop_1.delete(0, "end")
        e4_crop_1.insert(0, height)

        preview_orig()


def preview_orig_refresh(event):
    """callback after selection of size preview"""
    preview_orig()


def preview_orig():
    """
    generation preview of original picture
    and add crop rectangle
    """
    if co_preview_selector_orig.get() != "none":
        if os.path.isfile(file_in_path.get()):
            if img_crop_on.get() == 1:
                # draw crop rectangle on preview
                xy_max = common.mouse_crop_calculation(
                    file_in_width.get(),
                    file_in_height.get(),
                    int(co_preview_selector_orig.get()),
                )
                match img_crop.get():
                    case 1:
                        x0 = common.empty(e1_crop_1.get())
                        y0 = common.empty(e2_crop_1.get())
                        x1 = common.empty(e3_crop_1.get())
                        y1 = common.empty(e4_crop_1.get())
                    case 2:
                        x0 = common.empty(e1_crop_2.get())
                        y0 = common.empty(e2_crop_2.get())
                        x1 = x0 + common.empty(e3_crop_2.get())
                        y1 = y0 + common.empty(e4_crop_2.get())
                    case 3:
                        coord_for_crop = (
                            common.empty(e1_crop_3.get()),
                            common.empty(e2_crop_3.get()),
                            common.empty(e3_crop_3.get()),
                            common.empty(e4_crop_3.get()),
                            img_crop_gravity.get(),
                        )
                        coord = common.crop_gravity(
                            coord_for_crop, xy_max["x_orig"], xy_max["y_orig"]
                        )
                        x0 = coord[0]
                        y0 = coord[1]
                        x1 = coord[2]
                        y1 = coord[3]
                if (xy_max["x_orig"] > 0) and (xy_max["y_orig"] > 0):
                    ratio_x = xy_max["x_max"] / xy_max["x_orig"]
                    ratio_y = xy_max["y_max"] / xy_max["y_orig"]
                else:
                    ratio_x = 1
                    ratio_y = 1
                x0 = int(x0 * ratio_x)
                y0 = int(y0 * ratio_y)
                x1 = int(x1 * ratio_x)
                y1 = int(y1 * ratio_y)

                crop_rectangle = (x0, y0, x1, y1)
            else:
                crop_rectangle = ""

            preview_picture = convert_common.preview(
                file_in_path.get(),
                int(co_preview_selector_orig.get()),
                PILLOW,
                crop_rectangle,
            )

            try:
                pi_preview_orig.configure(file=preview_picture["filename"])
            except TclError as error_detail:
                logging.error("preview_orig: %s", error_detail)

            c_preview_orig_pi.delete("all")
            c_preview_orig_pi.configure(
                width=preview_picture["preview_width"],
                height=preview_picture["preview_height"],
            )
            c_preview_orig_pi.create_image(0, 0, image=pi_preview_orig, anchor="nw")

            try:
                l_preview_orig.configure(
                    text=preview_picture["width"]
                    + "x"
                    + preview_picture["height"]
                    + " - "
                    + preview_picture["size"]
                )
            except:
                logging.error("preview_orig: Cannot load image size")
        else:
            preview_orig_clear()
    progress_files.set(_("Ready"))


def preview_logo():
    """generating logo preview"""
    if os.path.isfile(file_logo_path.get()):
        l_logo_filename.configure(text=os.path.basename(file_logo_path.get()))
        preview_picture = convert_common.preview(
            file_logo_path.get(), PREVIEW_LOGO, PILLOW
        )

        try:
            pi_logo_preview.configure(file=preview_picture["filename"])
        except TclError as error_detail:
            logging.error("preview_logo: %s", error_detail)

        l_logo_preview.configure(
            text=preview_picture["width"] + "x" + preview_picture["height"]
        )
    else:
        logging.error("Preview_logo: Cannot load file")


def preview_logo_clear():
    """clear if no logo picture is selected"""
    l_logo_filename.configure(text=_("No file selected"))
    pi_logo_preview.configure(file="")
    l_logo_preview.configure(text="")


def preview_compose():
    """generating compose preview"""
    if os.path.isfile(img_compose_file.get()):
        # l_compose_preview.configure(text=os.path.basename(img_compose_file.get()))
        preview_picture = convert_common.preview(
            img_compose_file.get(), int(co_compose_preview_selector.get()), PILLOW
        )

        try:
            pi_compose_preview.configure(file=preview_picture["filename"])
        except TclError as error_detail:
            logging.error("preview_compose: %s", error_detail)

        c_compose_preview_pi.delete("all")
        c_compose_preview_pi.configure(
            width=preview_picture["preview_width"],
            height=preview_picture["preview_height"],
        )
        c_compose_preview_pi.create_image(0, 0, image=pi_compose_preview, anchor="nw")
        l_compose_preview.configure(
            text=preview_picture["width"] + "x" + preview_picture["height"]
        )
    else:
        logging.error("Preview_compose: Cannot load compose file")


def preview_compose_refresh(event):
    """callback after selection of size preview"""
    # to define file_out
    preview_compose()


def tools_set_event(event):
    """tool set for event"""
    tools_set(1)


def tools_set_on():
    """tool set for event"""
    tools_set(1)


def tools_set_off():
    """tool set for event"""
    tools_set(0)


def tools_set(preview_on):
    """selection tools for showing"""
    l_info_when_no_tool.grid()

    if img_compose_on.get():
        frame_crop.grid_remove()
        frame_mirror.grid_remove()
        frame_bw.grid_remove()
        frame_contrast.grid_remove()
        frame_normalize.grid_remove()
        frame_vignette.grid_remove()
        frame_border.grid_remove()
        frame_rotate.grid_remove()
        frame_resize.grid_remove()
        frame_text.grid_remove()
        frame_logo.grid_remove()
        frame_custom.grid_remove()
        l_info_when_no_tool.grid_remove()
        frame_compose.grid()
    else:
        frame_compose.grid_remove()
        if img_crop_on.get():
            frame_crop.grid()
            crop_tool_hide_show()
            l_info_when_no_tool.grid_remove()
        else:
            frame_crop.grid_remove()

        if img_mirror_on.get():
            frame_mirror.grid(row=1, column=1, sticky=(W, N, S), padx=5)
            l_info_when_no_tool.grid_remove()
        else:
            frame_mirror.grid_remove()

        if img_bw_on.get() == 0:
            frame_bw.grid_remove()
        else:
            frame_bw.grid(row=1, column=1, sticky=W, padx=5)
            l_info_when_no_tool.grid_remove()

        if img_contrast_on.get() == 0:
            frame_contrast.grid_remove()
        else:
            frame_contrast.grid(row=1, column=2, sticky=W, padx=5)
            l_info_when_no_tool.grid_remove()

        if img_normalize_on.get() == 0:
            frame_normalize.grid_remove()
        else:
            frame_normalize.grid(row=1, column=2, sticky=W, padx=5)
            l_info_when_no_tool.grid_remove()

        if img_vignette_on.get() == 0:
            frame_vignette.grid_remove()
        else:
            frame_vignette.grid(row=1, column=2, sticky=W, padx=5)
            l_info_when_no_tool.grid_remove()

        if img_border_on.get() == 0:
            frame_border.grid_remove()
        else:
            frame_border.grid(row=1, column=1, sticky=W, padx=5)
            l_info_when_no_tool.grid_remove()

        if img_rotate_on.get() == 0:
            frame_rotate.grid_remove()
        else:
            frame_rotate.grid()
            l_info_when_no_tool.grid_remove()

        if img_resize_on.get() == 0:
            frame_resize.grid_remove()
        else:
            frame_resize.grid()
            l_info_when_no_tool.grid_remove()

        if img_text_on.get() == 0:
            frame_text.grid_remove()
        else:
            frame_text.grid()
            l_info_when_no_tool.grid_remove()

        if img_logo_on.get():
            frame_logo.grid()
            l_info_when_no_tool.grid_remove()
        else:
            frame_logo.grid_remove()

        if img_custom_on.get():
            frame_custom.grid()
            l_info_when_no_tool.grid_remove()
        else:
            frame_custom.grid_remove()

        if (img_bw_on.get() == 0) and (img_contrast_on.get() == 0):
            frame_bw_contrast.grid_remove()
        else:
            frame_bw_contrast.grid()

        if (img_border_on.get() == 0) and (img_normalize_on.get() == 0):
            frame_border_normalize.grid_remove()
        else:
            frame_border_normalize.grid()

        if (img_mirror_on.get() == 0) and (img_vignette_on.get() == 0):
            frame_mirror_vignette.grid_remove()
        else:
            frame_mirror_vignette.grid()

    if preview_on:
        preview_orig()


def crop_tool_hide_show():
    """hide not necessary things, or show if the are needed"""
    match img_crop.get():
        case 1:
            f_clickL_crop.grid()
            f_clickR_crop.grid()
            e1_crop_2.grid_remove()
            e2_crop_2.grid_remove()
            e3_crop_2.grid_remove()
            e4_crop_2.grid_remove()
            e1_crop_3.grid_remove()
            e2_crop_3.grid_remove()
            e3_crop_3.grid_remove()
            e4_crop_3.grid_remove()
            frame_crop_gravity.grid_remove()
        case 2:
            f_clickL_crop.grid_remove()
            f_clickR_crop.grid_remove()
            e1_crop_2.grid()
            e2_crop_2.grid()
            e3_crop_2.grid()
            e4_crop_2.grid()
            e1_crop_3.grid_remove()
            e2_crop_3.grid_remove()
            e3_crop_3.grid_remove()
            e4_crop_3.grid_remove()
            frame_crop_gravity.grid_remove()
        case 3:
            f_clickL_crop.grid_remove()
            f_clickR_crop.grid_remove()
            e1_crop_2.grid_remove()
            e2_crop_2.grid_remove()
            e3_crop_2.grid_remove()
            e4_crop_2.grid_remove()
            e1_crop_3.grid()
            e2_crop_3.grid()
            e3_crop_3.grid()
            e4_crop_3.grid()
            frame_crop_gravity.grid()
    preview_orig()


def text_tool_hide_show():
    """hide not necessary things, or show if the are needed"""
    if img_text_inout.get():
        # Outside
        l_text_xy_x.grid_remove()
        l_text_xy_y.grid_remove()
        e_text_x.grid_remove()
        e_text_y.grid_remove()
        rb_text_NW.grid_remove()
        rb_text_N.grid_remove()
        rb_text_NE.grid_remove()
        rb_text_W.grid()
        rb_text_C.grid()
        rb_text_E.grid()
        rb_text_SW.grid_remove()
        rb_text_S.grid_remove()
        rb_text_SE.grid_remove()
        cb_text_gravity.grid_remove()
        cb_text_arrow.grid_remove()
        frame_text_rotate.grid_remove()
    else:
        # Inside
        l_text_xy_x.grid()
        l_text_xy_y.grid()
        e_text_x.grid()
        e_text_y.grid()
        cb_text_gravity.grid()
        cb_text_arrow.grid()
        if img_text_gravity_onoff.get():
            # Gravity on
            rb_text_NW.grid()
            rb_text_N.grid()
            rb_text_NE.grid()
            rb_text_W.grid()
            rb_text_C.grid()
            rb_text_E.grid()
            rb_text_SW.grid()
            rb_text_S.grid()
            rb_text_SE.grid()
            l_text_xy_x.configure(text=_("dx"))
            l_text_xy_y.configure(text=_("dy"))
        else:
            # Gravity off
            rb_text_NW.grid_remove()
            rb_text_N.grid_remove()
            rb_text_NE.grid_remove()
            rb_text_W.grid_remove()
            rb_text_C.grid_remove()
            rb_text_E.grid_remove()
            rb_text_SW.grid_remove()
            rb_text_S.grid_remove()
            rb_text_SE.grid_remove()
            l_text_xy_x.configure(text=_("x"))
            l_text_xy_y.configure(text=_("y"))
        frame_text_rotate.grid()


###############################################################################
# GUI main window
###############################################################################
logging.info("GUI: %ss", str(time.time() - start_time))
title_begin = (
    version.__author__ + " : " + version.__appname__ + " " + version.__version__ + " | "
)
root = ttk.Window(resizable=(1, 1), title=title_begin)
ttk.Sizegrip()
style = ttk.Style()
# hidden file
# https://code.activestate.com/lists/python-tkinter-discuss/3723/
try:
    # call a dummy dialog with an impossible option to initialize the file
    # dialog without really getting a dialog window; this will throw a
    # TclError, so we need a try...except :
    try:
        root.tk.call("tk_getOpenFile", "-foobarbaz")
    except TclError:
        pass
    # now set the magic variables accordingly
    root.tk.call("set", "::tk::dialog::file::showHiddenBtn", "1")
    root.tk.call("set", "::tk::dialog::file::showHiddenVar", "0")
except:
    pass

##########################
# global variables
FILE_INI = os.path.join(os.path.expanduser("~"), ".fotokilof.ini")
PWD = os.getcwd()
log_level = StringVar()  # E(rror), W(arning), M(essage)
check_version = IntVar()  # allow to check new version
work_dir = StringVar()  # default: "FotoKilof"
work_sub_dir = StringVar()  # subdir for resized pictures
work_sub_dir.set("")  # default none
file_dir_selector = IntVar()
file_in_path = StringVar()  # fullpath original picture
file_in_width = IntVar()  # width original picture
file_in_height = IntVar()  # height original picture
file_in_size = IntVar()  # size original picture (bytes)
img_logo_on = IntVar()  # Logo
file_logo_path = StringVar()  # fullpath logo file
img_logo_gravity = StringVar()
img_resize_on = IntVar()  # Resize
img_resize = IntVar()  # (1, 2, 3, 4, 5)
resized = IntVar()  # for proper display
img_text_on = IntVar()  # Text
img_text_gravity = StringVar()
img_text_gravity_onoff = IntVar()
img_text_font = StringVar()
img_text_font_dict = {}  # dict with available fonts, from fonts()
img_text_color = StringVar()
img_text_box = IntVar()
img_text_box_color = StringVar()
img_text_inout = IntVar()  # Text inside or outside picture
img_text_rotate = IntVar()
img_text_arrow = IntVar()
img_rotate_on = IntVar()  # Rotate
img_rotate = IntVar()
img_rotate_own = IntVar()
img_rotate_color = StringVar()
img_crop_on = IntVar()  # Crop
img_crop = IntVar()  # (1, 2, 3)
img_crop_gravity = StringVar()
img_border_on = IntVar()  # Border
img_border_color = StringVar()
img_normalize_on = IntVar()  # Normalize
img_normalize = IntVar()  # (1,2,3)
normalize_channels = (
    "None",
    "Red",
    "Green",
    "Blue",
    "Alpha",
    "Gray",
    "Cyan",
    "Magenta",
    "Yellow",
    "Black",
    "Opacity",
    "Index",
    "RGB",
    "RGBA",
    "CMYK",
    "CMYKA",
)
img_bw_on = IntVar()  # Black-white
img_bw = IntVar()
img_contrast_on = IntVar()  # Contrast
img_contrast = IntVar()  # (1, 2)
img_mirror_on = IntVar()  # Mirror
img_mirror_flip = IntVar()  # (0, 1)
img_mirror_flop = IntVar()  # (0, 1)
contrast_selection = ("+5", "+4", "+3", "+2", "+1", "-1", "-2", "-3", "-4", "-5")
img_custom_on = IntVar()  # Custom
img_exif_on = IntVar()
img_vignette_on = IntVar()
img_vignette_color = StringVar()
img_compose_on = IntVar()  # Compose
img_compose_file = StringVar()  # fullpath file for compose
img_compose_right = IntVar()
img_compose_autoresize = IntVar()
img_compose_color = StringVar()
img_compose_gravity = StringVar()
progress_var = IntVar()  # progressbar
progressbar_var = IntVar()
progress_files = StringVar()

######################################################################
# Tabs
######################################################################
main_menu = ttk.Frame()
main_tools = ttk.Frame()
main_paned = ttk.Panedwindow(orient=HORIZONTAL, bootstyle="default")
main_progress = ttk.Frame()

main_menu.pack(side=TOP, expand=0, fill=BOTH)
main_tools.pack(side=TOP, expand=0, fill=BOTH)
main_progress.pack(side=BOTTOM, expand=0, fill=X, anchor=S)
main_paned.pack(side=BOTTOM, expand=1, fill=BOTH)


validation = main_paned.register(gui.only_numbers)  # Entry validation
validationint = main_paned.register(gui.only_integer)  # Entry validation integer value
####################################################################
progressbar = ttk.Progressbar(
    main_progress,
    orient=HORIZONTAL,
    bootstyle="info",
    mode="determinate",
    variable=progressbar_var,
    maximum=100,
)
progressbar.pack(side=BOTTOM, padx=0, pady=0, fill=X, expand=0, anchor=S)
####################################################################
# main_menu row
####################################################################
###########################
# Picture selection
###########################
frame_file_select = ttk.Labelframe(main_menu, text=_("Image"))

frame_file_select.grid(row=1, column=1, sticky=(N, W, E, S), padx=5, pady=5)

b_file_select = ttk.Button(
    frame_file_select, text=_("File selection"), command=open_file, bootstyle="info"
)

b_file_select_screenshot = ttk.Button(
    frame_file_select, text=_("Clipboard"), command=open_screenshot, bootstyle="info"
)

b_file_select_first = ttk.Button(
    frame_file_select,
    text=_("First"),
    bootstyle="info-outline",
    command=open_file_first,
)
b_file_select_prev = ttk.Button(
    frame_file_select,
    text=_("Previous"),
    bootstyle="info-outline",
    command=open_file_prev,
)
b_file_select_next = ttk.Button(
    frame_file_select, text=_("Next"), bootstyle="info-outline", command=open_file_next
)
b_file_select_last = ttk.Button(
    frame_file_select, text=_("Last"), bootstyle="info-outline", command=open_file_last
)

b_file_select.grid(column=1, row=1, padx=5, pady=5, sticky=W)
#
b_file_select_screenshot.grid(column=2, row=1, padx=10, pady=5, sticky=W)
#
b_file_select_first.grid(column=5, row=1, padx=5, pady=5, sticky=W)
b_file_select_prev.grid(column=6, row=1, padx=5, pady=5, sticky=W)
b_file_select_next.grid(column=7, row=1, padx=5, pady=5, sticky=W)
b_file_select_last.grid(column=8, row=1, padx=5, pady=5, sticky=W)

##########################
# Execute all
##########################
frame_apply = ttk.Labelframe(main_menu, text=_("Execute all"))
frame_apply.grid(row=1, column=2, sticky=(N, W, E, S), padx=5, pady=5)

rb_apply_dir = ttk.Radiobutton(
    frame_apply,
    text=_("Folder"),
    bootstyle="info",
    variable=file_dir_selector,
    value="1",
)
rb_apply_file = ttk.Radiobutton(
    frame_apply, text=_("File"), bootstyle="info", variable=file_dir_selector, value="0"
)
co_apply_type = ttk.Combobox(
    frame_apply, width=4, values=common.file_extension_patterns_output(PILLOW)
)
co_apply_type.configure(state="readonly")
co_apply_type.current(common.file_extension_patterns_output(PILLOW).index(".jpg"))
b_apply_run = ttk.Button(
    frame_apply, text=_("Execute all"), bootstyle="info", command=apply_all_button
)

b_apply_run.pack(side=LEFT, padx=5, pady=5, anchor=W)
rb_apply_dir.pack(side=LEFT, pady=5, anchor=W)
rb_apply_file.pack(side=LEFT, padx=5, pady=5, anchor=W)

co_apply_type.pack(side=LEFT, padx=5, pady=1, anchor=W)

l_pb = ttk.Label(frame_apply, textvariable=progress_files, width=15)
l_pb.pack(side=LEFT, padx=5, pady=2, anchor=W)

###########################
# Buttons
###########################
frame_save = ttk.Labelframe(main_menu, text=_("Settings"))
frame_save.grid(row=1, column=3, sticky=(N, W, E, S), padx=5, pady=5)

b_last_save = ttk.Button(
    frame_save, text=_("Save"), bootstyle="info-outline", command=ini_save_wraper
)
b_last_read = ttk.Button(
    frame_save, text=_("Load"), bootstyle="info-outline", command=ini_read_wraper
)

b_last_save.pack(padx=5, pady=1, anchor=W, side=LEFT)
b_last_read.pack(padx=5, pady=1, anchor=W, side=LEFT)

####################################################################
# main_tools row
####################################################################
frame_tools_selection = ttk.Frame(main_paned)

############################
# Tools selection
############################
frame_tools_set = ttk.Labelframe(main_tools, text=_("Tools"))
frame_tools_set.grid(row=1, column=1, padx=5, pady=2, sticky=(W, E))

cb_resize = ttk.Checkbutton(
    frame_tools_set,
    text=_("Scaling/Resize"),
    bootstyle="info",
    variable=img_resize_on,
    offvalue="0",
    onvalue="1",
    command=tools_set_off,
)
cb_crop = ttk.Checkbutton(
    frame_tools_set,
    text=_("Crop"),
    bootstyle="info",
    variable=img_crop_on,
    offvalue="0",
    onvalue="1",
    command=tools_set_on,
)
cb_text = ttk.Checkbutton(
    frame_tools_set,
    text=_("Text"),
    bootstyle="info",
    variable=img_text_on,
    onvalue="1",
    offvalue="0",
    command=tools_set_off,
)
cb_rotate = ttk.Checkbutton(
    frame_tools_set,
    text=_("Rotate"),
    bootstyle="info",
    variable=img_rotate_on,
    offvalue="0",
    onvalue="1",
    command=tools_set_off,
)
cb_border = ttk.Checkbutton(
    frame_tools_set,
    text=_("Border"),
    bootstyle="info",
    variable=img_border_on,
    offvalue="0",
    onvalue="1",
    command=tools_set_off,
)
cb_bw = ttk.Checkbutton(
    frame_tools_set,
    text=_("Black&white"),
    bootstyle="info",
    variable=img_bw_on,
    offvalue="0",
    command=tools_set_off,
)
cb_normalize = ttk.Checkbutton(
    frame_tools_set,
    text=_("Colors normalize"),
    bootstyle="info",
    variable=img_normalize_on,
    offvalue="0",
    onvalue="1",
    command=tools_set_off,
)
cb_contrast = ttk.Checkbutton(
    frame_tools_set,
    text=_("Contrast"),
    bootstyle="info",
    variable=img_contrast_on,
    offvalue="0",
    onvalue="1",
    command=tools_set_off,
)
cb_mirror = ttk.Checkbutton(
    frame_tools_set,
    text=_("Mirror"),
    bootstyle="info",
    variable=img_mirror_on,
    offvalue="0",
    onvalue="1",
    command=tools_set_off,
)
cb_logo = ttk.Checkbutton(
    frame_tools_set,
    text=_("Logo"),
    bootstyle="info",
    variable=img_logo_on,
    offvalue="0",
    onvalue="1",
    command=tools_set_off,
)
cb_custom = ttk.Checkbutton(
    frame_tools_set,
    text=_("Custom"),
    bootstyle="info",
    variable=img_custom_on,
    offvalue=0,
    onvalue=1,
    command=tools_set_off,
)
cb_vignette = ttk.Checkbutton(
    frame_tools_set,
    text=_("Vignette"),
    bootstyle="info",
    variable=img_vignette_on,
    offvalue="0",
    onvalue="1",
    command=tools_set_off,
)
cb_exif = ttk.Checkbutton(
    frame_tools_set,
    text=_("EXIF"),
    bootstyle="info",
    variable=img_exif_on,
    offvalue="0",
    onvalue="1",
    command=tools_set_off,
)
cb_compose = ttk.Checkbutton(
    frame_tools_set,
    text=_("Compose"),
    bootstyle="info",
    variable=img_compose_on,
    offvalue="0",
    onvalue="1",
    command=tools_set_off,
)

cb_crop.pack(padx=5, pady=5, anchor=W, side=LEFT)
cb_mirror.pack(padx=5, pady=5, anchor=W, side=LEFT)
cb_bw.pack(padx=5, pady=5, anchor=W, side=LEFT)
cb_contrast.pack(padx=5, pady=5, anchor=W, side=LEFT)
cb_normalize.pack(padx=5, pady=5, anchor=W, side=LEFT)
if not PILLOW:
    cb_vignette.pack(padx=5, pady=5, anchor=W, side=LEFT)
cb_border.pack(padx=5, pady=5, anchor=W, side=LEFT)
cb_rotate.pack(padx=5, pady=5, anchor=W, side=LEFT)
cb_resize.pack(padx=5, pady=5, anchor=W, side=LEFT)
cb_text.pack(padx=5, pady=5, anchor=W, side=LEFT)
cb_logo.pack(padx=5, pady=5, anchor=W, side=LEFT)
if not PILLOW:
    cb_custom.pack(padx=5, pady=5, anchor=W, side=LEFT)
    cb_exif.pack(padx=5, pady=5, anchor=W, side=LEFT)
cb_compose.pack(padx=5, pady=5, anchor=W, side=LEFT)

####################################################################
# main row
####################################################################
#####################################################
# First column
#####################################################
frame_first_col = ScrolledFrame(autohide=True)

###########################
# Label if no any tool selected
l_info_when_no_tool = ttk.Label(
    frame_first_col,
    text=_(
        "Open file for processing\nSelect tools for conversion\nExecute conversion or perform all conversion in one run"
    ),
)

###########################
# Resize
###########################
frame_resize = ttk.Labelframe(frame_first_col, text=_("Scale/Resize"))
###
frame_resize_row1 = ttk.Frame(frame_resize)
rb_resize_3 = ttk.Radiobutton(
    frame_resize_row1, text="FullHD (1920x1080)", variable=img_resize, value="3"
)
rb_resize_4 = ttk.Radiobutton(
    frame_resize_row1, text="2K (2048×1556)", variable=img_resize, value="4"
)
rb_resize_5 = ttk.Radiobutton(
    frame_resize_row1, text="4K (4096×3112)", variable=img_resize, value="5"
)
frame_resize_row2 = ttk.Frame(frame_resize)
rb_resize_1 = ttk.Radiobutton(
    frame_resize_row2, text=_("Max"), variable=img_resize, value="1"
)
l_resize_x = ttk.Label(frame_resize_row2, text="X")
e1_resize_x = ttk.Entry(
    frame_resize_row2, width=4, validate="key", validatecommand=(validation, "%S")
)
l_resize_y = ttk.Label(frame_resize_row2, text="Y")
e1_resize_y = ttk.Entry(
    frame_resize_row2, width=4, validate="key", validatecommand=(validation, "%S")
)
rb_resize_2 = ttk.Radiobutton(
    frame_resize_row2, text=_("Percent"), variable=img_resize, value="2"
)
e2_resize = ttk.Entry(
    frame_resize_row2, width=3, validate="key", validatecommand=(validation, "%S")
)
b_resize_run = ttk.Button(
    frame_resize_row2, text=_("Execute"), command=convert_resize_button
)

rb_resize_3.pack(side=LEFT, padx=5)
rb_resize_4.pack(side=LEFT, padx=5)
rb_resize_5.pack(side=LEFT, padx=5)
rb_resize_1.pack(side=LEFT, padx=5)
l_resize_x.pack(side=LEFT, padx=5)
e1_resize_x.pack(side=LEFT, padx=0)
l_resize_y.pack(side=LEFT, padx=5)
e1_resize_y.pack(side=LEFT, padx=0)
rb_resize_2.pack(side=LEFT, padx=5)
e2_resize.pack(side=LEFT, padx=0)
b_resize_run.pack(side=LEFT, padx=25, pady=5)

frame_resize_row1.pack(side=TOP, fill=X, expand=1)
frame_resize_row2.pack(side=TOP, fill=X, expand=1)

############################
# crop
############################
frame_crop = ttk.Labelframe(frame_first_col, text=_("Crop"))
frame_crop.grid(row=3, column=1, columnspan=2, sticky=(N, W, E, S), padx=5, pady=1)
###
rb1_crop = ttk.Radiobutton(
    frame_crop,
    variable=img_crop,
    value="1",
    text=_("Coordinates (x1, y1) and (x2, y2)"),
    command=crop_tool_hide_show,
)
f_clickL_crop = ttk.Frame(frame_crop)
l_clickL_crop = ttk.Label(f_clickL_crop, text=_("Left Upper\ncorner\nClick left"))
e1_crop_1 = ttk.Entry(
    f_clickL_crop, width=4, validate="key", validatecommand=(validation, "%S")
)
e2_crop_1 = ttk.Entry(
    f_clickL_crop, width=4, validate="key", validatecommand=(validation, "%S")
)
f_clickR_crop = ttk.Frame(frame_crop)
l_clickR_crop = ttk.Label(f_clickR_crop, text=_("Right Lower\ncorner\nClick right"))
e3_crop_1 = ttk.Entry(
    f_clickR_crop, width=4, validate="key", validatecommand=(validation, "%S")
)
e4_crop_1 = ttk.Entry(
    f_clickR_crop, width=4, validate="key", validatecommand=(validation, "%S")
)

rb2_crop = ttk.Radiobutton(
    frame_crop,
    variable=img_crop,
    value="2",
    text=_("Origin (x1,y1) and dimensions (X, Y)"),
    command=crop_tool_hide_show,
)
e1_crop_2 = ttk.Entry(
    frame_crop, width=4, validate="key", validatecommand=(validation, "%S")
)
e2_crop_2 = ttk.Entry(
    frame_crop, width=4, validate="key", validatecommand=(validation, "%S")
)
e3_crop_2 = ttk.Entry(
    frame_crop, width=4, validate="key", validatecommand=(validation, "%S")
)
e4_crop_2 = ttk.Entry(
    frame_crop, width=4, validate="key", validatecommand=(validation, "%S")
)

rb3_crop = ttk.Radiobutton(
    frame_crop,
    variable=img_crop,
    value="3",
    text=_("Offset (dx,dy), dimensions (X, Y)\nand gravity"),
    command=crop_tool_hide_show,
)
e1_crop_3 = ttk.Entry(
    frame_crop, width=4, validate="key", validatecommand=(validation, "%S")
)
e2_crop_3 = ttk.Entry(
    frame_crop, width=4, validate="key", validatecommand=(validation, "%S")
)
e3_crop_3 = ttk.Entry(
    frame_crop, width=4, validate="key", validatecommand=(validation, "%S")
)
e4_crop_3 = ttk.Entry(
    frame_crop, width=4, validate="key", validatecommand=(validation, "%S")
)

frame_crop_gravity = ttk.Frame(frame_crop)
rb_crop_NW = ttk.Radiobutton(
    frame_crop_gravity,
    text="NW",
    variable=img_crop_gravity,
    value="NW",
    command=preview_orig,
)
rb_crop_N = ttk.Radiobutton(
    frame_crop_gravity,
    text="N",
    variable=img_crop_gravity,
    value="N",
    command=preview_orig,
)
rb_crop_NE = ttk.Radiobutton(
    frame_crop_gravity,
    text="NE",
    variable=img_crop_gravity,
    value="NE",
    command=preview_orig,
)
rb_crop_W = ttk.Radiobutton(
    frame_crop_gravity,
    text="W",
    variable=img_crop_gravity,
    value="W",
    command=preview_orig,
)
rb_crop_C = ttk.Radiobutton(
    frame_crop_gravity,
    text=_("Center"),
    variable=img_crop_gravity,
    value="C",
    command=preview_orig,
)
rb_crop_E = ttk.Radiobutton(
    frame_crop_gravity,
    text="E",
    variable=img_crop_gravity,
    value="E",
    command=preview_orig,
)
rb_crop_SW = ttk.Radiobutton(
    frame_crop_gravity,
    text="SW",
    variable=img_crop_gravity,
    value="SW",
    command=preview_orig,
)
rb_crop_S = ttk.Radiobutton(
    frame_crop_gravity,
    text="S",
    variable=img_crop_gravity,
    value="S",
    command=preview_orig,
)
rb_crop_SE = ttk.Radiobutton(
    frame_crop_gravity,
    text="SE",
    variable=img_crop_gravity,
    value="SE",
    command=preview_orig,
)
frame_crop_buttons = ttk.Frame(frame_crop)

b_crop_show = ttk.Button(
    frame_crop_buttons, text=_("Preview"), command=preview_orig, bootstyle="outline"
)
b_crop_read = ttk.Button(
    frame_crop_buttons, text=_("From image"), command=crop_read, bootstyle="outline"
)
b_crop_run = ttk.Button(frame_crop, text=_("Execute"), command=convert_crop_button)

rb1_crop.grid(row=2, column=1, sticky=W, padx=5, pady=5)
f_clickL_crop.grid(row=1, column=2, rowspan=4, columnspan=2, padx=5, sticky=N)
f_clickR_crop.grid(row=1, column=4, rowspan=4, columnspan=2, padx=5, sticky=N)
e1_crop_1.grid(row=1, column=1, sticky=W, padx=5, pady=5)
e2_crop_1.grid(row=1, column=2, sticky=W, padx=5, pady=5)
e3_crop_1.grid(row=1, column=1, sticky=W, padx=5, pady=5)
e4_crop_1.grid(row=1, column=2, sticky=W, padx=5, pady=5)
l_clickL_crop.grid(row=2, column=1, columnspan=2, sticky=(W, E))
l_clickR_crop.grid(row=2, column=1, columnspan=2, sticky=(W, E))
rb2_crop.grid(row=3, column=1, sticky=W, padx=5, pady=5)
e1_crop_2.grid(row=3, column=2, sticky=W, padx=10, pady=5)
e2_crop_2.grid(row=3, column=3, sticky=W, padx=5, pady=5)
e3_crop_2.grid(row=3, column=4, sticky=W, padx=5, pady=5)
e4_crop_2.grid(row=3, column=5, sticky=W, padx=5, pady=5)
rb3_crop.grid(row=4, column=1, sticky=W, padx=5, pady=1)
e1_crop_3.grid(row=4, column=2, sticky=W, padx=10, pady=1)
e2_crop_3.grid(row=4, column=3, sticky=W, padx=5, pady=1)
e3_crop_3.grid(row=4, column=4, sticky=W, padx=5, pady=1)
e4_crop_3.grid(row=4, column=5, sticky=W, padx=5, pady=1)
frame_crop_gravity.grid(row=2, column=2, rowspan=2, padx=5, columnspan=4, sticky=E)
rb_crop_NW.grid(row=1, column=1, sticky=W, padx=3, pady=1)
rb_crop_N.grid(row=1, column=2, padx=3, pady=1)
rb_crop_NE.grid(row=1, column=3, sticky=W, padx=3, pady=1)
rb_crop_W.grid(row=2, column=1, sticky=W, padx=3, pady=1)
rb_crop_C.grid(row=2, column=2, sticky=W, padx=3, pady=1)
rb_crop_E.grid(row=2, column=3, sticky=W, padx=3, pady=1)
rb_crop_SW.grid(row=3, column=1, sticky=W, padx=3, pady=1)
rb_crop_S.grid(row=3, column=2, padx=3, pady=1)
rb_crop_SE.grid(row=3, column=3, sticky=W, padx=3, pady=1)
frame_crop_buttons.grid(row=5, column=1, sticky=(W, E))
b_crop_read.grid(row=1, column=1, sticky=W, padx=15, pady=5)
b_crop_show.grid(row=1, column=2, sticky=W, padx=5, pady=5)
b_crop_run.grid(row=5, column=4, columnspan=2, sticky=W, padx=5, pady=5)

###########################
# Tekst
###########################
frame_text = ttk.Labelframe(frame_first_col, text=_("Add text"))
###
e_text = ttk.Entry(frame_text, width=55)
# frame_text_text.grid(row=1, column=1, columnspan=5, sticky=(W, E))
e_text.grid(row=1, column=1, columnspan=5, sticky=W, padx=5)

###
rb_text_in = ttk.Radiobutton(
    frame_text,
    text=_("Inside"),
    variable=img_text_inout,
    value="0",
    command=text_tool_hide_show,
)
rb_text_out = ttk.Radiobutton(
    frame_text,
    text=_("Outside"),
    variable=img_text_inout,
    value="1",
    command=text_tool_hide_show,
)
cb_text_box = ttk.Checkbutton(
    frame_text, text=_("Background"), variable=img_text_box, onvalue="1", offvalue="0"
)
cb_text_arrow = ttk.Checkbutton(
    frame_text, text=_("Arrow"), variable=img_text_arrow, onvalue="1", offvalue="0"
)
cb_text_gravity = ttk.Checkbutton(
    frame_text,
    text=_("Gravity"),
    variable=img_text_gravity_onoff,
    onvalue="1",
    offvalue="0",
    command=text_tool_hide_show,
)
# l_text_xy_l = ttk.Label(frame_text, text=_("Offset"))
l_text_xy_x = ttk.Label(frame_text, text=_("dx"))
l_text_xy_y = ttk.Label(frame_text, text=_("dy"))
e_text_x = ttk.Entry(
    frame_text, width=4, validate="key", validatecommand=(validation, "%S")
)
e_text_y = ttk.Entry(
    frame_text, width=4, validate="key", validatecommand=(validation, "%S")
)

rb_text_out.grid(row=2, column=1, sticky=W, padx=5, pady=1)
rb_text_in.grid(row=3, column=1, sticky=W, padx=5, pady=1)
if not PILLOW:
    cb_text_box.grid(row=4, column=1, sticky=W, padx=5, pady=1)
cb_text_arrow.grid(row=4, column=2, sticky=W, padx=5, pady=1)
cb_text_gravity.grid(row=2, column=3, columnspan=2, sticky=W, pady=1)

l_text_xy_x.grid(row=3, column=3, sticky=W, padx=5, pady=1)
l_text_xy_y.grid(row=3, column=4, sticky=W, padx=5, pady=1)
e_text_x.grid(row=4, column=3, sticky=(W, N), padx=5, pady=1)
e_text_y.grid(row=4, column=4, sticky=(W, N), padx=5, pady=1)

###
frame_text_gravity = ttk.Frame(frame_text)
rb_text_NW = ttk.Radiobutton(
    frame_text_gravity, text="NW", variable=img_text_gravity, value="NW"
)
rb_text_N = ttk.Radiobutton(
    frame_text_gravity, text="N", variable=img_text_gravity, value="N"
)
rb_text_NE = ttk.Radiobutton(
    frame_text_gravity, text="NE", variable=img_text_gravity, value="NE"
)
rb_text_W = ttk.Radiobutton(
    frame_text_gravity, text="W", variable=img_text_gravity, value="W"
)
rb_text_C = ttk.Radiobutton(
    frame_text_gravity, text=_("Center"), variable=img_text_gravity, value="C"
)
rb_text_E = ttk.Radiobutton(
    frame_text_gravity, text="E", variable=img_text_gravity, value="E"
)
rb_text_SW = ttk.Radiobutton(
    frame_text_gravity, text="SW", variable=img_text_gravity, value="SW"
)
rb_text_S = ttk.Radiobutton(
    frame_text_gravity, text="S", variable=img_text_gravity, value="S"
)
rb_text_SE = ttk.Radiobutton(
    frame_text_gravity, text="SE", variable=img_text_gravity, value="SE"
)
frame_text_gravity.grid(row=2, column=2, rowspan=3, padx=25, pady=2, sticky=(W, N))
rb_text_NW.grid(row=1, column=1, sticky=W, padx=3, pady=1)
rb_text_N.grid(row=1, column=2, padx=3, pady=1)
rb_text_NE.grid(row=1, column=3, sticky=W, padx=3, pady=1)
rb_text_W.grid(row=2, column=1, sticky=W, padx=3, pady=1)
rb_text_C.grid(row=2, column=2, padx=3, pady=1)
rb_text_E.grid(row=2, column=3, sticky=W, padx=3, pady=1)
rb_text_SW.grid(row=3, column=1, padx=3, sticky=W, pady=1)
rb_text_S.grid(row=3, column=2, padx=3, pady=1)
rb_text_SE.grid(row=3, column=3, sticky=W, padx=3, pady=1)

###
co_text_font = ttk.Combobox(frame_text, width=30, textvariable=img_text_font)
co_text_font.configure(state="readonly")
e_text_size = ttk.Entry(
    frame_text, width=3, validate="key", validatecommand=(validation, "%S")
)
l_text_color = Label(frame_text, text=_("Color test"))
b_text_color = ttk.Button(
    frame_text, text=_("Font"), command=color_choose, bootstyle="outline"
)
l_text_heght = ttk.Label(frame_text, text=_("Height"))
b_text_box_color = ttk.Button(
    frame_text, text=_("Background"), command=color_choose_box, bootstyle="outline"
)
b_text_run = ttk.Button(frame_text, text=_("Execute"), command=convert_text_button)

l_text_color.grid(row=2, column=5, sticky=(W, E), padx=5, pady=1)
b_text_color.grid(row=3, column=5, sticky=(W, E), padx=5, pady=1)
b_text_box_color.grid(row=4, column=5, sticky=(W, E), padx=5, pady=1)
co_text_font.grid(row=5, column=1, columnspan=2, sticky=(W, E), padx=5)
l_text_heght.grid(row=5, column=3, sticky=W, padx=5)
e_text_size.grid(row=5, column=4, sticky=W, padx=5)
b_text_run.grid(row=5, column=5, sticky=(E), padx=5, pady=1)

frame_text_rotate = ttk.Frame(frame_text)
rb_text_rotate_0 = ttk.Radiobutton(
    frame_text_rotate, text="0", variable=img_text_rotate, value="0"
)
rb_text_rotate_90 = ttk.Radiobutton(
    frame_text_rotate, text="90", variable=img_text_rotate, value="90"
)
rb_text_rotate_180 = ttk.Radiobutton(
    frame_text_rotate, text="180", variable=img_text_rotate, value="180"
)
rb_text_rotate_270 = ttk.Radiobutton(
    frame_text_rotate, text="270", variable=img_text_rotate, value="270"
)
rb_text_rotate_own = ttk.Radiobutton(
    frame_text_rotate, text=_("Custom"), variable=img_text_rotate, value="-1"
)
e_text_angle = ttk.Entry(
    frame_text_rotate, width=3, validate="key", validatecommand=(validation, "%S")
)
if not PILLOW:
    rb_text_rotate_0.grid(row=1, column=1, sticky=(N, W, E, S), padx=5, pady=5)
    rb_text_rotate_90.grid(row=1, column=2, sticky=(N, W, E, S), padx=5, pady=5)
    rb_text_rotate_180.grid(row=1, column=3, sticky=(N, W, E, S), padx=5, pady=5)
    rb_text_rotate_270.grid(row=1, column=4, sticky=(N, W, E, S), padx=5, pady=5)
    rb_text_rotate_own.grid(row=1, column=5, sticky=(N, W, E, S), padx=5, pady=5)
    e_text_angle.grid(row=1, column=6, sticky=(N, W, E, S), padx=5, pady=5)
    frame_text_rotate.grid(row=6, column=1, columnspan=6, sticky=W, padx=5)

###########################
# Rotate
###########################
frame_rotate = ttk.Labelframe(frame_first_col, text=_("Rotate"))
###
rb_rotate_90 = ttk.Radiobutton(frame_rotate, text="90", variable=img_rotate, value="90")
rb_rotate_180 = ttk.Radiobutton(
    frame_rotate, text="180", variable=img_rotate, value="180"
)
rb_rotate_270 = ttk.Radiobutton(
    frame_rotate, text="270", variable=img_rotate, value="270"
)
rb_rotate_own = ttk.Radiobutton(
    frame_rotate, text=_("Custom"), variable=img_rotate, value="0"
)
e_rotate_own = ttk.Entry(
    frame_rotate, width=3, validate="key", validatecommand=(validation, "%S")
)
l_rotate_color = Label(frame_rotate, text=_("  "))
b_rotate_color = ttk.Button(
    frame_rotate, text=_("Color"), command=color_choose_rotate, bootstyle="outline"
)
b_rotate_run = ttk.Button(
    frame_rotate, text=_("Execute"), command=convert_rotate_button
)

rb_rotate_90.pack(side=LEFT, padx=5, pady=5)
rb_rotate_180.pack(side=LEFT, padx=5, pady=5)
rb_rotate_270.pack(side=LEFT, padx=5, pady=5)
rb_rotate_own.pack(side=LEFT, padx=5, pady=5)
e_rotate_own.pack(side=LEFT, padx=5, pady=5)
l_rotate_color.pack(side=LEFT, pady=5)
b_rotate_color.pack(side=LEFT, padx=5, pady=5)
b_rotate_run.pack(side=LEFT, padx=5, pady=5)

###########################
# frames for two widgets
###########################
frame_mirror_vignette = ttk.Frame(frame_first_col)
frame_bw_contrast = ttk.Frame(frame_first_col)
frame_border_normalize = ttk.Frame(frame_first_col)

###########################
# Border
###########################
frame_border = ttk.Labelframe(frame_border_normalize, text=_("Border"))
###
l_border_color = Label(frame_border, text=_("  "))
l_border_we = ttk.Label(frame_border, text="WE")
e_border_we = ttk.Entry(
    frame_border, width=3, validate="key", validatecommand=(validation, "%S")
)
l_border_ns = ttk.Label(frame_border, text="NS")
e_border_ns = ttk.Entry(
    frame_border, width=3, validate="key", validatecommand=(validation, "%S")
)
b_border_color = ttk.Button(
    frame_border, text=_("Color"), command=color_choose_border, bootstyle="outline"
)
b_border_run = ttk.Button(
    frame_border, text=_("Execute"), command=convert_border_button
)

l_border_we.grid(row=1, column=1, padx=5, pady=0)
e_border_we.grid(row=1, column=2, padx=5, pady=0)
l_border_ns.grid(row=2, column=1, padx=5, pady=5)
e_border_ns.grid(row=2, column=2, padx=5, pady=5)
l_border_color.grid(row=1, column=3)
b_border_color.grid(row=1, column=5, padx=5, pady=0)
b_border_run.grid(row=2, column=5, padx=5, pady=5, sticky=E)

############################
# Black-white
############################
frame_bw = ttk.Labelframe(frame_bw_contrast, text=_("Black-white"))
###
rb1_bw = ttk.Radiobutton(frame_bw, text=_("Black-white"), variable=img_bw, value="1")
rb2_bw = ttk.Radiobutton(frame_bw, text=_("Sepia"), variable=img_bw, value="2")
e_bw_sepia = ttk.Entry(
    frame_bw, width=3, validate="key", validatecommand=(validation, "%S")
)
l_bw_sepia = ttk.Label(frame_bw, text="%")
b_bw_run = ttk.Button(frame_bw, text=_("Execute"), command=convert_bw_button)

if not PILLOW:
    rb2_bw.grid(row=1, column=1, padx=5, pady=5, sticky=W)
    e_bw_sepia.grid(row=1, column=2, padx=5, pady=5, sticky=E)
    l_bw_sepia.grid(row=1, column=3, padx=5, pady=5, sticky=W)
rb1_bw.grid(row=2, column=1, padx=5, pady=0, sticky=W)
b_bw_run.grid(row=2, column=2, columnspan=2, padx=5, pady=5, sticky=E)

########################
# Contrast
#########################
frame_contrast = ttk.Labelframe(frame_bw_contrast, text=_("Contrast"))
###
rb1_contrast = ttk.Radiobutton(
    frame_contrast, text=_("Stretch"), variable=img_contrast, value="1"
)
rb2_contrast = ttk.Radiobutton(
    frame_contrast, text=_("Contrast"), variable=img_contrast, value="2"
)
co_contrast_selection = ttk.Combobox(frame_contrast, width=3, values=contrast_selection)
co_contrast_selection.configure(state="readonly")

e1_contrast = ttk.Entry(frame_contrast, width=4)
e2_contrast = ttk.Entry(frame_contrast, width=4)
l1_contrast = ttk.Label(frame_contrast, text=_("Black"))
l2_contrast = ttk.Label(frame_contrast, text=_("White"))
b_contrast_run = ttk.Button(
    frame_contrast, text=_("Execute"), command=convert_contrast_button
)

rb1_contrast.grid(row=1, column=1, padx=5, pady=5, sticky=W)
l1_contrast.grid(row=1, column=2, padx=5, pady=5, sticky=E)
e1_contrast.grid(row=1, column=3, padx=5, pady=5, sticky=E)
l2_contrast.grid(row=1, column=4, padx=5, pady=5, sticky=W)
e2_contrast.grid(row=1, column=5, padx=5, pady=5, sticky=W)
if not PILLOW:
    rb2_contrast.grid(row=2, column=1, padx=5, pady=5, sticky=W)
    co_contrast_selection.grid(row=2, column=2, padx=5, pady=5, sticky=W)
b_contrast_run.grid(row=2, column=3, padx=5, pady=5, columnspan=3, sticky=E)

############################
# Color normalize
############################
frame_normalize = ttk.Labelframe(frame_border_normalize, text=_("Color normalize"))
###
rb1_normalize = ttk.Radiobutton(
    frame_normalize, text=_("Normalize"), variable=img_normalize, value="1"
)
rb2_normalize = ttk.Radiobutton(
    frame_normalize, text=_("AutoLevel"), variable=img_normalize, value="2"
)
l_normalize_channel = ttk.Label(frame_normalize, text=_("Channel:"))
co_normalize_channel = ttk.Combobox(frame_normalize, width=7, values=normalize_channels)
co_normalize_channel.configure(state="readonly")
b_normalize_run = ttk.Button(
    frame_normalize, text=_("Execute"), command=convert_normalize_button
)

rb1_normalize.grid(row=1, column=1, padx=5, pady=0, sticky=W)
if not PILLOW:
    l_normalize_channel.grid(row=1, column=2, padx=5, pady=4, sticky=E)
    co_normalize_channel.grid(row=1, column=3, padx=5, pady=4, sticky=E)
rb2_normalize.grid(row=2, column=1, padx=5, pady=4, sticky=W)
b_normalize_run.grid(row=2, column=2, columnspan=2, padx=5, pady=4, sticky=E)

###########################
# Mirror
###########################
frame_mirror = ttk.Labelframe(frame_mirror_vignette, text=_("Mirror"))

cb_mirror_flip = ttk.Checkbutton(
    frame_mirror, text="NS", variable=img_mirror_flip, offvalue="0", onvalue="1"
)
cb_mirror_flop = ttk.Checkbutton(
    frame_mirror, text="WE", variable=img_mirror_flop, offvalue="0", onvalue="1"
)
b_mirror_run = ttk.Button(
    frame_mirror, text=_("Execute"), command=convert_mirror_button
)

cb_mirror_flip.grid(row=1, column=1, sticky=(N, W, E, S), padx=5, pady=5)
cb_mirror_flop.grid(row=1, column=2, sticky=(N, W, E, S), padx=5, pady=5)
b_mirror_run.grid(row=1, column=5, sticky=E, padx=5, pady=5)

###########################
# vignette
###########################
frame_vignette = ttk.Labelframe(frame_mirror_vignette, text=_("Vignette"))
###
l_vignette_radius = ttk.Label(frame_vignette, text=_("Radius"))
e_vignette_radius = ttk.Entry(
    frame_vignette, width=3, validate="key", validatecommand=(validation, "%S")
)
l_vignette_sigma = ttk.Label(frame_vignette, text=_("Sigma"))
e_vignette_sigma = ttk.Entry(
    frame_vignette, width=3, validate="key", validatecommand=(validation, "%S")
)
l_vignette_dx = ttk.Label(frame_vignette, text=_("dx"))
e_vignette_dx = ttk.Entry(
    frame_vignette, width=3, validate="key", validatecommand=(validationint, "%S")
)
l_vignette_dy = ttk.Label(frame_vignette, text=_("dy"))
e_vignette_dy = ttk.Entry(
    frame_vignette, width=3, validate="key", validatecommand=(validationint, "%S")
)
l_vignette_color = Label(frame_vignette, text=_("  "))
b_vignette_color = ttk.Button(
    frame_vignette, text=_("Color"), command=color_choose_vignette, bootstyle="outline"
)
b_vignette_run = ttk.Button(
    frame_vignette, text=_("Execute"), command=convert_vignette_button
)
l_vignette_radius.grid(row=1, column=1, padx=5, pady=0)
e_vignette_radius.grid(row=1, column=2, padx=5, pady=0)
l_vignette_sigma.grid(row=2, column=1, padx=5, pady=5)
e_vignette_sigma.grid(row=2, column=2, padx=5, pady=5)
l_vignette_dx.grid(row=1, column=3, padx=5, pady=0)
e_vignette_dx.grid(row=1, column=4, padx=5, pady=0)
l_vignette_dy.grid(row=2, column=3, padx=5, pady=5)
e_vignette_dy.grid(row=2, column=4, padx=5, pady=5)
l_vignette_color.grid(row=1, column=5)
b_vignette_color.grid(row=1, column=6, padx=5, pady=0)
b_vignette_run.grid(row=2, column=6, padx=5, pady=5)

###########################
# Logo
###########################
frame_logo = ttk.Labelframe(frame_first_col, text=_("Logo"))

b_logo_select = ttk.Button(
    frame_logo, text=_("File selection"), command=open_file_logo, bootstyle="outline"
)

b_logo_run = ttk.Button(frame_logo, text=_("Execute"), command=convert_logo_button)
l_logo_filename = ttk.Label(frame_logo, width=25)

b_logo_select.grid(row=1, column=1, padx=5, pady=5)
l_logo_filename.grid(row=1, column=2, padx=5, pady=5, sticky=W)
b_logo_run.grid(row=1, column=3, padx=5, pady=5, sticky=E)

###
frame_logo_xy = ttk.Frame(frame_logo)
l_logo_XxY = ttk.Label(frame_logo_xy, text=_("Width\nHeight"))
l_logo_dxdy = ttk.Label(frame_logo_xy, text=_("Offset\n(dx,dy)"))
e_logo_width = ttk.Entry(
    frame_logo_xy, width=4, validate="key", validatecommand=(validation, "%S")
)
e_logo_height = ttk.Entry(
    frame_logo_xy, width=4, validate="key", validatecommand=(validation, "%S")
)
e_logo_dx = ttk.Entry(
    frame_logo_xy, width=4, validate="key", validatecommand=(validation, "%S")
)
e_logo_dy = ttk.Entry(
    frame_logo_xy, width=4, validate="key", validatecommand=(validation, "%S")
)

frame_logo_xy.grid(row=2, column=2, padx=5, pady=5)
l_logo_XxY.grid(row=1, column=1, sticky=W, padx=5)
e_logo_width.grid(row=2, column=1, sticky=W, padx=5)
e_logo_height.grid(row=3, column=1, sticky=W, padx=5)
l_logo_dxdy.grid(row=1, column=2, sticky=W, padx=5)
e_logo_dx.grid(row=2, column=2, sticky=W, padx=5)
e_logo_dy.grid(row=3, column=2, sticky=W, padx=5)

###
frame_logo_gravity = ttk.Frame(frame_logo)
rb_logo_NW = ttk.Radiobutton(
    frame_logo_gravity, text="NW", variable=img_logo_gravity, value="NW"
)
rb_logo_N = ttk.Radiobutton(
    frame_logo_gravity, text="N", variable=img_logo_gravity, value="N"
)
rb_logo_NE = ttk.Radiobutton(
    frame_logo_gravity, text="NE", variable=img_logo_gravity, value="NE"
)
rb_logo_W = ttk.Radiobutton(
    frame_logo_gravity, text="W", variable=img_logo_gravity, value="W"
)
rb_logo_C = ttk.Radiobutton(
    frame_logo_gravity, text=_("Center"), variable=img_logo_gravity, value="C"
)
rb_logo_E = ttk.Radiobutton(
    frame_logo_gravity, text="E", variable=img_logo_gravity, value="E"
)
rb_logo_SW = ttk.Radiobutton(
    frame_logo_gravity, text="SW", variable=img_logo_gravity, value="SW"
)
rb_logo_S = ttk.Radiobutton(
    frame_logo_gravity, text="S", variable=img_logo_gravity, value="S"
)
rb_logo_SE = ttk.Radiobutton(
    frame_logo_gravity, text="SE", variable=img_logo_gravity, value="SE"
)
frame_logo_gravity.grid(row=2, column=3, padx=5, pady=5, sticky=(S, E))

rb_logo_NW.grid(row=1, column=1, sticky=W, padx=3, pady=2)
rb_logo_N.grid(row=1, column=2, padx=3, pady=2)
rb_logo_NE.grid(row=1, column=3, sticky=W, padx=3, pady=2)
rb_logo_W.grid(row=2, column=1, sticky=W, padx=3, pady=2)
rb_logo_C.grid(row=2, column=2, padx=3, pady=2)
rb_logo_E.grid(row=2, column=3, sticky=W, padx=3, pady=2)
rb_logo_SW.grid(row=3, column=1, sticky=W, padx=3, pady=2)
rb_logo_S.grid(row=3, column=2, padx=3, pady=2)
rb_logo_SE.grid(row=3, column=3, sticky=W, padx=3, pady=2)

###
frame_logo_preview = ttk.Frame(frame_logo)
frame_logo_preview.grid(row=2, column=1)
pi_logo_preview = PhotoImage()
l_logo_preview_pi = ttk.Label(frame_logo_preview, image=pi_logo_preview)
l_logo_preview = ttk.Label(frame_logo_preview)
l_logo_preview_pi.grid(row=2, column=1, padx=5, pady=1)
l_logo_preview.grid(row=1, column=1, padx=5, pady=1)

############################
# Custom command
############################
frame_custom = ttk.Labelframe(frame_first_col, text=_("Custom command"))

b_custom_clear = ttk.Button(
    frame_custom, text=_("Clear"), bootstyle="warning", command=convert_custom_clear
)
b_custom_run = ttk.Button(
    frame_custom, text=_("Execute"), command=convert_custom_button
)

t_custom = ScrolledText(
    frame_custom, state=NORMAL, height=5, width=45, wrap="word", undo=True
)

t_custom.pack(expand=1, fill=BOTH, padx=5, pady=5)
b_custom_run.pack(side=RIGHT, padx=5, pady=5)
b_custom_clear.pack(side=RIGHT, padx=5, pady=5)

###########################
# Compose
###########################
frame_compose = ttk.Labelframe(frame_first_col, text=_("Compose"))

# ## Main
frame_compose_main = ttk.Frame(frame_compose)
b_compose_select = ttk.Button(
    frame_compose_main,
    text=_("File selection"),
    command=open_file_compose,
    bootstyle="outline",
)
rb_compose_bottom = ttk.Radiobutton(
    frame_compose_main,
    text=_("Bottom"),
    variable=img_compose_right,
    value="0",
    command=compose_autoresize_gravity,
)
rb_compose_right = ttk.Radiobutton(
    frame_compose_main,
    text=_("Right"),
    variable=img_compose_right,
    value="1",
    command=compose_autoresize_gravity,
)
cb_compose_autoresize = ttk.Checkbutton(
    frame_compose_main,
    text=_("Autoresize"),
    variable=img_compose_autoresize,
    onvalue="1",
    offvalue="0",
    command=compose_autoresize,
)

b_compose_run = ttk.Button(
    frame_compose_main, text=_("Execute"), command=convert_compose_button
)

b_compose_select.pack(padx=5, pady=5, anchor=W, side=LEFT)
rb_compose_bottom.pack(padx=5, pady=5, anchor=W, side=LEFT)
rb_compose_right.pack(padx=5, pady=5, anchor=W, side=LEFT)
cb_compose_autoresize.pack(padx=5, pady=5, anchor=W, side=LEFT)
b_compose_run.pack(padx=5, pady=5, anchor=W, side=LEFT)

frame_compose_main.grid(row=1, padx=5, pady=5, sticky=W)

# ## Autoresize
frame_compose_autoresize = ttk.Frame(frame_compose)

b_compose_color = ttk.Button(
    frame_compose_autoresize,
    text=_("Color"),
    bootstyle="outline",
    command=color_choose_compose,
)
l_compose_color = Label(frame_compose_autoresize, text=_("  "))
rb_compose_N = ttk.Radiobutton(
    frame_compose_autoresize, text=_("Top"), variable=img_compose_gravity, value="N"
)
rb_compose_W = ttk.Radiobutton(
    frame_compose_autoresize, text=_("Left"), variable=img_compose_gravity, value="W"
)
rb_compose_C = ttk.Radiobutton(
    frame_compose_autoresize, text=_("Center"), variable=img_compose_gravity, value="C"
)
rb_compose_E = ttk.Radiobutton(
    frame_compose_autoresize, text=_("Right"), variable=img_compose_gravity, value="E"
)
rb_compose_S = ttk.Radiobutton(
    frame_compose_autoresize, text=_("Bottom"), variable=img_compose_gravity, value="S"
)

b_compose_color.grid(padx=5, pady=5, row=1, column=1)
l_compose_color.grid(padx=5, pady=5, row=1, column=2)
rb_compose_N.grid(padx=5, pady=5, row=1, column=3)
rb_compose_W.grid(padx=5, pady=5, row=1, column=3)
rb_compose_C.grid(padx=5, pady=5, row=1, column=4)
rb_compose_E.grid(padx=5, pady=5, row=1, column=5)
rb_compose_S.grid(padx=5, pady=5, row=1, column=5)

frame_compose_autoresize.grid(row=2, padx=5, pady=5, sticky=W)

# ## Preview
frame_compose_preview = ttk.Frame(frame_compose)
frame_compose_preview.grid(row=3, padx=5, pady=5, sticky=W)

###
b_compose_preview_run = ttk.Button(
    frame_compose_preview,
    text=_("Preview"),
    bootstyle="secondary",
    command=compose_preview_button,
)
l_compose_preview = ttk.Label(frame_compose_preview)
co_compose_preview_selector = ttk.Combobox(
    frame_compose_preview, width=4, bootstyle="secondary", values=preview_size_list
)
co_compose_preview_selector.configure(state="readonly")
pi_compose_preview = PhotoImage()
c_compose_preview_pi = Canvas(frame_compose_preview)
c_compose_preview_pi.create_image(0, 0, image=pi_compose_preview, anchor="ne")

c_compose_preview_pi.pack(side=BOTTOM, anchor=W)
b_compose_preview_run.pack(side=LEFT, padx=5, pady=5)
l_compose_preview.pack(side=LEFT, padx=5, pady=5)
co_compose_preview_selector.pack(side=LEFT, padx=5, pady=1)

############################
# Pack frames
############################
frame_first_col.pack(fill=BOTH, expand=1)

l_info_when_no_tool.grid(row=1, column=1, padx=5, pady=5)
frame_crop.grid(row=2, column=1, sticky=(N, W, S), padx=5, pady=1)
frame_mirror_vignette.grid(row=3, column=1, sticky=(N, W, S), padx=0, pady=1)
frame_bw_contrast.grid(row=4, column=1, sticky=(N, W, S), padx=0, pady=1)
frame_border_normalize.grid(row=5, column=1, sticky=(N, W, S), padx=0, pady=1)
frame_rotate.grid(row=7, column=1, sticky=(N, W, S), padx=5, pady=1)
frame_resize.grid(row=8, column=1, sticky=(N, W, S), padx=5, pady=5)
frame_text.grid(row=9, column=1, sticky=(N, W, S), padx=5, pady=1)
frame_logo.grid(row=10, column=1, sticky=(N, W, S), padx=5, pady=1)
frame_custom.grid(row=11, column=1, sticky=(N, W, S), padx=5, pady=1)
frame_compose.grid(row=12, column=1, sticky=(N, W, S), padx=5, pady=1)

#####################################################
# Second column
#####################################################
frame_second_col = ttk.Frame()

############################
# Original preview
############################
frame_preview_orig = ttk.Labelframe(frame_second_col, text=_("Original"))
frame_preview_orig.grid(row=1, column=1, sticky=(N, W, E, S), padx=5, pady=5)
###
b_preview_orig_run = ttk.Button(
    frame_preview_orig,
    text=_("Preview"),
    bootstyle="secondary",
    command=preview_orig_button,
)
l_preview_orig = ttk.Label(frame_preview_orig)
co_preview_selector_orig = ttk.Combobox(
    frame_preview_orig, width=4, bootstyle="secondary", values=preview_size_list
)
co_preview_selector_orig.configure(state="readonly")
pi_preview_orig = PhotoImage()
c_preview_orig_pi = Canvas(frame_preview_orig)
c_preview_orig_pi.create_image(0, 0, image=pi_preview_orig, anchor="ne")

c_preview_orig_pi.pack(side=BOTTOM, anchor=W)
b_preview_orig_run.pack(side=LEFT, padx=5, pady=5)
l_preview_orig.pack(side=LEFT, padx=5, pady=5)
co_preview_selector_orig.pack(side=LEFT, padx=5, pady=1)

#####################################################
# Third column
#####################################################
frame_third_col = ttk.Frame()

##########################
# Result preview
###########################
frame_preview_new = ttk.Labelframe(frame_third_col, text=_("Result"))

frame_preview_new.grid(row=1, column=1, sticky=(N, W, E, S), padx=5, pady=5)
###
b_preview_new_run = ttk.Button(
    frame_preview_new,
    text=_("Preview"),
    bootstyle="secondary",
    command=preview_new_button,
)
l_preview_new = ttk.Label(frame_preview_new)
co_preview_selector_new = ttk.Combobox(
    frame_preview_new, width=4, bootstyle="secondary", values=preview_size_list
)
co_preview_selector_new.configure(state="readonly")
pi_preview_new = PhotoImage()
c_preview_new_pi = Canvas(frame_preview_new)
c_preview_orig_pi.create_image(0, 0, image=pi_preview_orig, anchor="ne")

c_preview_new_pi.pack(side=BOTTOM, anchor=W)
b_preview_new_run.pack(side=LEFT, padx=5, pady=5)
l_preview_new.pack(side=LEFT, padx=5, pady=5)
co_preview_selector_new.pack(side=LEFT, padx=5, pady=1)

###############################################################################
# Add Frames into Panedwindow
###############################################################################
main_paned.add(frame_first_col.container)
main_paned.add(frame_second_col)
main_paned.add(frame_third_col)

###############################################################################
# bind
###############################################################################
# binding commands to widgets
root_actions = {
    "help_info": help_info,
    "change_theme": change_ttk_theme,
    "open_file_prev_key": open_file_prev_key,
    "open_file_next_key": open_file_next_key,
    "open_file_first_key": open_file_first_key,
    "open_file_last_key": open_file_last_key,
    "close_program": close_program,
}
panel_widgets = {
    "c_preview_orig_pi": c_preview_orig_pi,
    "c_preview_new_pi": c_preview_new_pi,
    "co_preview_selector_orig": co_preview_selector_orig,
    "co_preview_selector_new": co_preview_selector_new,
    "co_compose_preview_selector": co_compose_preview_selector,
    "co_text_font": co_text_font,
}
widget_actions = {
    "mouse_crop_nw": mouse_crop_nw,
    "mouse_crop_se": mouse_crop_se,
    "preview_new_button": preview_new_button,
    "preview_orig_refresh": preview_orig_refresh,
    "preview_new_refresh": preview_new_refresh,
    "preview_compose_refresh": preview_compose_refresh,
    "font_selected": font_selected,
}

gui_bindings.setup_root_bindings(root, root_actions)
gui_bindings.setup_widget_bindings(panel_widgets, widget_actions, OS)

###############################################################################
# toolTips
###############################################################################
widgets = {
    "b_file_select_screenshot": b_file_select_screenshot,
    "b_file_select_first": b_file_select_first,
    "b_file_select_prev": b_file_select_prev,
    "b_file_select_next": b_file_select_next,
    "b_file_select_last": b_file_select_last,
    "rb_apply_dir": rb_apply_dir,
    "rb_apply_file": rb_apply_file,
    "co_apply_type": co_apply_type,
    "b_apply_run": b_apply_run,
    "b_last_save": b_last_save,
    "b_last_read": b_last_read,
    "cb_resize": cb_resize,
    "cb_crop": cb_crop,
    "cb_text": cb_text,
    "cb_rotate": cb_rotate,
    "cb_border": cb_border,
    "cb_bw": cb_bw,
    "cb_contrast": cb_contrast,
    "cb_normalize": cb_normalize,
    "cb_mirror": cb_mirror,
    "cb_vignette": cb_vignette,
    "cb_logo": cb_logo,
    "cb_custom": cb_custom,
    "cb_exif": cb_exif,
    "b_preview_orig_run": b_preview_orig_run,
    "co_preview_selector_orig": co_preview_selector_orig,
    "b_preview_new_run": b_preview_new_run,
    "co_preview_selector_new": co_preview_selector_new,
    "b_resize_run": b_resize_run,
    "rb1_crop": rb1_crop,
    "rb2_crop": rb2_crop,
    "rb3_crop": rb3_crop,
    "e1_crop_1": e1_crop_1,
    "e2_crop_1": e2_crop_1,
    "e3_crop_1": e3_crop_1,
    "e4_crop_1": e4_crop_1,
    "e1_crop_2": e1_crop_2,
    "e2_crop_2": e2_crop_2,
    "e3_crop_2": e3_crop_2,
    "e4_crop_2": e4_crop_2,
    "e1_crop_3": e1_crop_3,
    "e2_crop_3": e2_crop_3,
    "e3_crop_3": e3_crop_3,
    "e4_crop_3": e4_crop_3,
    "b_crop_read": b_crop_read,
    "b_crop_show": b_crop_show,
    "frame_crop_gravity": frame_crop_gravity,
    "b_crop_run": b_crop_run,
    "e_text": e_text,
    "e_text_size": e_text_size,
    "e_text_angle": e_text_angle,
    "co_text_font": co_text_font,
    "rb_text_in": rb_text_in,
    "rb_text_out": rb_text_out,
    "cb_text_gravity": cb_text_gravity,
    "frame_text_gravity": frame_text_gravity,
    "cb_text_box": cb_text_box,
    "cb_text_arrow": cb_text_arrow,
    "e_text_x": e_text_x,
    "e_text_y": e_text_y,
    "l_text_color": l_text_color,
    "b_text_color": b_text_color,
    "b_text_box_color": b_text_box_color,
    "b_text_run": b_text_run,
    "rb_rotate_own": rb_rotate_own,
    "e_rotate_own": e_rotate_own,
    "l_rotate_color": l_rotate_color,
    "b_rotate_color": b_rotate_color,
    "b_rotate_run": b_rotate_run,
    "e2_resize": e2_resize,
    "e_border_ns": e_border_ns,
    "e_border_we": e_border_we,
    "l_border_color": l_border_color,
    "b_border_color": b_border_color,
    "b_border_run": b_border_run,
    "rb1_bw": rb1_bw,
    "rb2_bw": rb2_bw,
    "e_bw_sepia": e_bw_sepia,
    "b_bw_run": b_bw_run,
    "e1_contrast": e1_contrast,
    "e2_contrast": e2_contrast,
    "rb1_contrast": rb1_contrast,
    "rb2_contrast": rb2_contrast,
    "co_contrast_selection": co_contrast_selection,
    "b_contrast_run": b_contrast_run,
    "rb1_normalize": rb1_normalize,
    "co_normalize_channel": co_normalize_channel,
    "rb2_normalize": rb2_normalize,
    "b_normalize_run": b_normalize_run,
    "cb_mirror_flip": cb_mirror_flip,
    "cb_mirror_flop": cb_mirror_flop,
    "b_mirror_run": b_mirror_run,
    "e_vignette_radius": e_vignette_radius,
    "e_vignette_sigma": e_vignette_sigma,
    "e_vignette_dx": e_vignette_dx,
    "e_vignette_dy": e_vignette_dy,
    "l_vignette_color": l_vignette_color,
    "b_vignette_color": b_vignette_color,
    "b_vignette_run": b_vignette_run,
    "b_logo_select": b_logo_select,
    "e_logo_width": e_logo_width,
    "e_logo_height": e_logo_height,
    "e_logo_dx": e_logo_dx,
    "e_logo_dy": e_logo_dy,
    "frame_logo_gravity": frame_logo_gravity,
    "b_logo_run": b_logo_run,
    "b_compose_select": b_compose_select,
    "rb_compose_bottom": rb_compose_bottom,
    "rb_compose_right": rb_compose_right,
    "cb_compose_autoresize": cb_compose_autoresize,
    "l_compose_color": l_compose_color,
    "b_compose_color": b_compose_color,
    "rb_compose_N": rb_compose_N,
    "rb_compose_W": rb_compose_W,
    "rb_compose_C": rb_compose_C,
    "rb_compose_E": rb_compose_E,
    "rb_compose_S": rb_compose_S,
    "b_compose_run": b_compose_run,
}
gui_tooltips.init_tooltips(widgets)

logging.debug("End GUI: %ss", str(time.time() - start_time))
##########################################
# Run functions
#

Python_version = (
    "Py "
    + platform.python_version()
    + ", Tk "
    + str(TkVersion)
    + ", PIL "
    + convert_pillow.version()
)
window_title = title_begin + IMAGEMAGICK_WAND_VERSION + ", " + Python_version + " | "
root.title(window_title)
img_text_font_dict = fonts()  # Reading available fonts
ini_read_wraper()  # Loading settings from config file
l_border_color.configure(bg=img_border_color.get())
l_compose_color.configure(bg=img_compose_color.get())

if darkdetect.isDark():
    style.theme_use("darkly")
elif darkdetect.isLight():
    style.theme_use("litera")

if PILLOW:
    # disable processing buttons
    img_logo_on.set(0)
    img_custom_on.set(0)
    cb_custom.configure(state=DISABLED)
    img_vignette_on.set(0)
    cb_vignette.configure(state=DISABLED)
    img_exif_on.set(0)
    cb_exif.configure(state=DISABLED)

tools_set(0)
text_tool_hide_show()
progress_files.set(_("Ready"))
compose_autoresize()
if os.path.isfile(file_in_path.get()):
    open_file_common("", file_in_path.get())
if img_logo_on.get() == 1:
    if os.path.isfile(file_logo_path.get()):
        # Load preview logo
        preview_logo()


if check_version.get():
    if check_new_version.check_version(version.__version__)[0]:
        Messagebox.show_warning(
            "New version of FotoKilof is available.\nCurrent: "
            + version.__version__
            + ", New: "
            + check_new_version.check_version(version.__version__)[1]
            + "\nRun command:\npython3 -m pip install --upgrade fotokilof",
            title=_("New version of FotoKilof is available"),
        )

logging.info("End start: %ss", str(time.time() - start_time))
root.mainloop()

# EOF
