Add files via upload

This commit is contained in:
Akash Bora
2025-08-09 15:47:34 +05:30
committed by GitHub
parent d99908cd76
commit 08fb701a44
16 changed files with 466 additions and 34 deletions

View File

@@ -2,11 +2,9 @@
CTkRangeSlider CTkRangeSlider
Range slider for customtkinter Range slider for customtkinter
Author: Akash Bora Author: Akash Bora
Version: 0.2 Version: 0.3
""" """
from __future__ import annotations
import math import math
import tkinter import tkinter
import sys import sys
@@ -23,12 +21,90 @@ class CustomDrawEngine:
It is tailored towards the range slider. It is tailored towards the range slider.
""" """
preferred_drawing_method: str = "font_shapes" # 'polygon_shapes', 'font_shapes', 'circle_shapes' # Use circle_shapes on macOS to avoid rectangular slider heads, font_shapes elsewhere
preferred_drawing_method: str = "circle_shapes" if sys.platform == "darwin" else "font_shapes"
def __init__(self, canvas: CTkCanvas): def __init__(self, canvas: CTkCanvas):
self._canvas = canvas self._canvas = canvas
def _DrawEngine__draw_rounded_rect_with_border_font_shapes(self, width: int, height: int, corner_radius: int, border_width: int, inner_corner_radius: int, def __calc_optimal_corner_radius(self, user_corner_radius: Union[float, int]) -> Union[float, int]:
# optimize for drawing with polygon shapes
if self.preferred_drawing_method == "polygon_shapes":
if sys.platform == "darwin":
return user_corner_radius
else:
return round(user_corner_radius)
# optimize for drawing with antialiased font shapes
elif self.preferred_drawing_method == "font_shapes":
return round(user_corner_radius)
# optimize for drawing with circles and rects
elif self.preferred_drawing_method == "circle_shapes":
user_corner_radius = 0.5 * round(user_corner_radius / 0.5) # round to 0.5 steps
# make sure the value is always with .5 at the end for smoother corners
if user_corner_radius == 0:
return 0
elif user_corner_radius % 1 == 0:
return user_corner_radius + 0.5
else:
return user_corner_radius
def __draw_rounded_rect_with_border_polygon_shapes(self, width: int, height: int, corner_radius: int, border_width: int, inner_corner_radius: int) -> bool:
requires_recoloring = False
# create border button parts (only if border exists)
if border_width > 0:
if not self._canvas.find_withtag("border_parts"):
self._canvas.create_polygon((0, 0, 0, 0), tags=("border_line_1", "border_parts"))
requires_recoloring = True
self._canvas.coords("border_line_1",
(corner_radius,
corner_radius,
width - corner_radius,
corner_radius,
width - corner_radius,
height - corner_radius,
corner_radius,
height - corner_radius))
self._canvas.itemconfig("border_line_1",
joinstyle=tkinter.ROUND,
width=corner_radius * 2)
else:
self._canvas.delete("border_parts")
# create inner button parts
if not self._canvas.find_withtag("inner_parts"):
self._canvas.create_polygon((0, 0, 0, 0), tags=("inner_line_1", "inner_parts"), joinstyle=tkinter.ROUND)
requires_recoloring = True
if corner_radius <= border_width:
bottom_right_shift = -1 # weird canvas rendering inaccuracy that has to be corrected in some cases
else:
bottom_right_shift = 0
self._canvas.coords("inner_line_1",
border_width + inner_corner_radius,
border_width + inner_corner_radius,
width - (border_width + inner_corner_radius) + bottom_right_shift,
border_width + inner_corner_radius,
width - (border_width + inner_corner_radius) + bottom_right_shift,
height - (border_width + inner_corner_radius) + bottom_right_shift,
border_width + inner_corner_radius,
height - (border_width + inner_corner_radius) + bottom_right_shift)
self._canvas.itemconfig("inner_line_1",
width=inner_corner_radius * 2)
if requires_recoloring: # new parts were added -> manage z-order
self._canvas.tag_lower("inner_parts")
self._canvas.tag_lower("border_parts")
return requires_recoloring
def __draw_rounded_rect_with_border_font_shapes(self, width: int, height: int, corner_radius: int, border_width: int, inner_corner_radius: int,
exclude_parts: tuple) -> bool: exclude_parts: tuple) -> bool:
requires_recoloring = False requires_recoloring = False
@@ -165,7 +241,257 @@ class CustomDrawEngine:
self._canvas.tag_lower("border_parts") self._canvas.tag_lower("border_parts")
return requires_recoloring return requires_recoloring
def __draw_rounded_rect_with_border_circle_shapes(self, width: int, height: int, corner_radius: int, border_width: int, inner_corner_radius: int) -> bool:
requires_recoloring = False
# create border parts (only if border exists)
if border_width > 0:
if corner_radius > 0:
# create canvas border corner parts if not already created
if not self._canvas.find_withtag("border_oval_1"):
self._canvas.create_oval(0, 0, 0, 0, tags=("border_oval_1", "border_parts"), width=0)
self._canvas.create_oval(0, 0, 0, 0, tags=("border_oval_2", "border_parts"), width=0)
self._canvas.create_oval(0, 0, 0, 0, tags=("border_oval_3", "border_parts"), width=0)
self._canvas.create_oval(0, 0, 0, 0, tags=("border_oval_4", "border_parts"), width=0)
requires_recoloring = True
# set positions of border corner parts
self._canvas.coords("border_oval_1", 0, 0, 2 * corner_radius, 2 * corner_radius)
self._canvas.coords("border_oval_2", width - 2 * corner_radius, 0, width, 2 * corner_radius)
self._canvas.coords("border_oval_3", width - 2 * corner_radius, height - 2 * corner_radius, width, height)
self._canvas.coords("border_oval_4", 0, height - 2 * corner_radius, 2 * corner_radius, height)
# create canvas border rectangle parts
if not self._canvas.find_withtag("border_rectangle_1"):
self._canvas.create_rectangle(0, 0, 0, 0, tags=("border_rectangle_1", "border_parts"), width=0)
self._canvas.create_rectangle(0, 0, 0, 0, tags=("border_rectangle_2", "border_parts"), width=0)
requires_recoloring = True
# set positions of border rectangle parts
self._canvas.coords("border_rectangle_1", corner_radius, 0, width - corner_radius, height)
self._canvas.coords("border_rectangle_2", 0, corner_radius, width, height - corner_radius)
else:
self._canvas.delete("border_parts")
# create inner parts
if not self._canvas.find_withtag("inner_rectangle_1"):
self._canvas.create_rectangle(0, 0, 0, 0, tags=("inner_rectangle_1", "inner_parts"), width=0)
requires_recoloring = True
if inner_corner_radius > 0:
if not self._canvas.find_withtag("inner_oval_1"):
self._canvas.create_oval(0, 0, 0, 0, tags=("inner_oval_1", "inner_parts"), width=0)
self._canvas.create_oval(0, 0, 0, 0, tags=("inner_oval_2", "inner_parts"), width=0)
self._canvas.create_oval(0, 0, 0, 0, tags=("inner_oval_3", "inner_parts"), width=0)
self._canvas.create_oval(0, 0, 0, 0, tags=("inner_oval_4", "inner_parts"), width=0)
requires_recoloring = True
# set positions of inner corner parts
self._canvas.coords("inner_oval_1", border_width, border_width, border_width + 2 * inner_corner_radius, border_width + 2 * inner_corner_radius)
self._canvas.coords("inner_oval_2", width - border_width - 2 * inner_corner_radius, border_width, width - border_width, border_width + 2 * inner_corner_radius)
self._canvas.coords("inner_oval_3", width - border_width - 2 * inner_corner_radius, height - border_width - 2 * inner_corner_radius, width - border_width, height - border_width)
self._canvas.coords("inner_oval_4", border_width, height - border_width - 2 * inner_corner_radius, border_width + 2 * inner_corner_radius, height - border_width)
else:
self._canvas.delete("inner_oval_1", "inner_oval_2", "inner_oval_3", "inner_oval_4")
# set position of inner rectangle part
self._canvas.coords("inner_rectangle_1", border_width + inner_corner_radius, border_width, width - border_width - inner_corner_radius, height - border_width)
if requires_recoloring:
self._canvas.tag_lower("inner_parts")
self._canvas.tag_lower("border_parts")
return requires_recoloring
def __draw_rounded_progress_bar_with_border_polygon_shapes(self, width: int, height: int, corner_radius: int, border_width: int, inner_corner_radius: int,
progress_value_1: float, progress_value_2: float, orientation: str) -> bool:
requires_recoloring = self.__draw_rounded_rect_with_border_polygon_shapes(width, height, corner_radius, border_width, inner_corner_radius)
if corner_radius <= border_width:
bottom_right_shift = 0 # weird canvas rendering inaccuracy that has to be corrected in some cases
else:
bottom_right_shift = 0
# create progress parts
if not self._canvas.find_withtag("progress_parts"):
self._canvas.create_polygon((0, 0, 0, 0), tags=("progress_line_1", "progress_parts"), joinstyle=tkinter.ROUND)
self._canvas.tag_raise("progress_parts", "inner_parts")
requires_recoloring = True
if orientation == "w":
self._canvas.coords("progress_line_1",
border_width + inner_corner_radius + (width - 2 * border_width - 2 * inner_corner_radius) * progress_value_1,
border_width + inner_corner_radius,
border_width + inner_corner_radius + (width - 2 * border_width - 2 * inner_corner_radius) * progress_value_2,
border_width + inner_corner_radius,
border_width + inner_corner_radius + (width - 2 * border_width - 2 * inner_corner_radius) * progress_value_2,
height - (border_width + inner_corner_radius) + bottom_right_shift,
border_width + inner_corner_radius + (width - 2 * border_width - 2 * inner_corner_radius) * progress_value_1,
height - (border_width + inner_corner_radius) + bottom_right_shift)
elif orientation == "s":
self._canvas.coords("progress_line_1",
border_width + inner_corner_radius,
border_width + inner_corner_radius + (height - 2 * border_width - 2 * inner_corner_radius) * (1 - progress_value_2),
width - (border_width + inner_corner_radius),
border_width + inner_corner_radius + (height - 2 * border_width - 2 * inner_corner_radius) * (1 - progress_value_2),
width - (border_width + inner_corner_radius),
border_width + inner_corner_radius + (height - 2 * border_width - 2 * inner_corner_radius) * (1 - progress_value_1),
border_width + inner_corner_radius,
border_width + inner_corner_radius + (height - 2 * border_width - 2 * inner_corner_radius) * (1 - progress_value_1))
self._canvas.itemconfig("progress_line_1", width=inner_corner_radius * 2)
return requires_recoloring
def __draw_rounded_progress_bar_with_border_font_shapes(self, width: int, height: int, corner_radius: int, border_width: int, inner_corner_radius: int,
progress_value_1: float, progress_value_2: float, orientation: str) -> bool:
requires_recoloring, requires_recoloring_2 = False, False
if inner_corner_radius > 0:
# create canvas border corner parts if not already created
if not self._canvas.find_withtag("progress_oval_1_a"):
self._canvas.create_aa_circle(0, 0, 0, tags=("progress_oval_1_a", "progress_corner_part", "progress_parts"), anchor=tkinter.CENTER)
self._canvas.create_aa_circle(0, 0, 0, tags=("progress_oval_1_b", "progress_corner_part", "progress_parts"), anchor=tkinter.CENTER, angle=180)
self._canvas.create_aa_circle(0, 0, 0, tags=("progress_oval_2_a", "progress_corner_part", "progress_parts"), anchor=tkinter.CENTER)
self._canvas.create_aa_circle(0, 0, 0, tags=("progress_oval_2_b", "progress_corner_part", "progress_parts"), anchor=tkinter.CENTER, angle=180)
requires_recoloring = True
if not self._canvas.find_withtag("progress_oval_3_a") and round(inner_corner_radius) * 2 < height - 2 * border_width:
self._canvas.create_aa_circle(0, 0, 0, tags=("progress_oval_3_a", "progress_corner_part", "progress_parts"), anchor=tkinter.CENTER)
self._canvas.create_aa_circle(0, 0, 0, tags=("progress_oval_3_b", "progress_corner_part", "progress_parts"), anchor=tkinter.CENTER, angle=180)
self._canvas.create_aa_circle(0, 0, 0, tags=("progress_oval_4_a", "progress_corner_part", "progress_parts"), anchor=tkinter.CENTER)
self._canvas.create_aa_circle(0, 0, 0, tags=("progress_oval_4_b", "progress_corner_part", "progress_parts"), anchor=tkinter.CENTER, angle=180)
requires_recoloring = True
elif self._canvas.find_withtag("progress_oval_3_a") and not round( inner_corner_radius) * 2 < height - 2 * border_width:
self._canvas.delete("progress_oval_3_a", "progress_oval_3_b", "progress_oval_4_a", "progress_oval_4_b")
if not self._canvas.find_withtag("progress_rectangle_1"):
self._canvas.create_rectangle(0, 0, 0, 0, tags=("progress_rectangle_1", "progress_rectangle_part", "progress_parts"), width=0)
requires_recoloring = True
if not self._canvas.find_withtag("progress_rectangle_2") and inner_corner_radius * 2 < height - (border_width * 2):
self._canvas.create_rectangle(0, 0, 0, 0, tags=("progress_rectangle_2", "progress_rectangle_part", "progress_parts"), width=0)
requires_recoloring = True
elif self._canvas.find_withtag("progress_rectangle_2") and not inner_corner_radius * 2 < height - (border_width * 2):
self._canvas.delete("progress_rectangle_2")
# horizontal orientation from the bottom
if orientation == "w":
requires_recoloring_2 = self.__draw_rounded_rect_with_border_font_shapes(width, height, corner_radius, border_width, inner_corner_radius,
())
# set positions of progress corner parts
self._canvas.coords("progress_oval_1_a", border_width + inner_corner_radius + (width - 2 * border_width - 2 * inner_corner_radius) * progress_value_1,
border_width + inner_corner_radius, inner_corner_radius)
self._canvas.coords("progress_oval_1_b", border_width + inner_corner_radius + (width - 2 * border_width - 2 * inner_corner_radius) * progress_value_1,
border_width + inner_corner_radius, inner_corner_radius)
self._canvas.coords("progress_oval_2_a", border_width + inner_corner_radius + (width - 2 * border_width - 2 * inner_corner_radius) * progress_value_2,
border_width + inner_corner_radius, inner_corner_radius)
self._canvas.coords("progress_oval_2_b", border_width + inner_corner_radius + (width - 2 * border_width - 2 * inner_corner_radius) * progress_value_2,
border_width + inner_corner_radius, inner_corner_radius)
self._canvas.coords("progress_oval_3_a", border_width + inner_corner_radius + (width - 2 * border_width - 2 * inner_corner_radius) * progress_value_2,
height - border_width - inner_corner_radius, inner_corner_radius)
self._canvas.coords("progress_oval_3_b", border_width + inner_corner_radius + (width - 2 * border_width - 2 * inner_corner_radius) * progress_value_2,
height - border_width - inner_corner_radius, inner_corner_radius)
self._canvas.coords("progress_oval_4_a", border_width + inner_corner_radius + (width - 2 * border_width - 2 * inner_corner_radius) * progress_value_1,
height - border_width - inner_corner_radius, inner_corner_radius)
self._canvas.coords("progress_oval_4_b", border_width + inner_corner_radius + (width - 2 * border_width - 2 * inner_corner_radius) * progress_value_1,
height - border_width - inner_corner_radius, inner_corner_radius)
# set positions of progress rect parts
self._canvas.coords("progress_rectangle_1",
border_width + inner_corner_radius + (width - 2 * border_width - 2 * inner_corner_radius) * progress_value_1,
border_width,
border_width + inner_corner_radius + (width - 2 * border_width - 2 * inner_corner_radius) * progress_value_2,
height - border_width)
self._canvas.coords("progress_rectangle_2",
border_width + 2 * inner_corner_radius + (width - 2 * inner_corner_radius - 2 * border_width) * progress_value_1,
border_width + inner_corner_radius,
border_width + 2 * inner_corner_radius + (width - 2 * inner_corner_radius - 2 * border_width) * progress_value_2,
height - inner_corner_radius - border_width)
# vertical orientation from the bottom
if orientation == "s":
requires_recoloring_2 = self.__draw_rounded_rect_with_border_font_shapes(width, height, corner_radius, border_width, inner_corner_radius,
())
# set positions of progress corner parts
self._canvas.coords("progress_oval_1_a", border_width + inner_corner_radius,
border_width + inner_corner_radius + (height - 2 * border_width - 2 * inner_corner_radius) * (1 - progress_value_2), inner_corner_radius)
self._canvas.coords("progress_oval_1_b", border_width + inner_corner_radius,
border_width + inner_corner_radius + (height - 2 * border_width - 2 * inner_corner_radius) * (1 - progress_value_2), inner_corner_radius)
self._canvas.coords("progress_oval_2_a", width - border_width - inner_corner_radius,
border_width + inner_corner_radius + (height - 2 * border_width - 2 * inner_corner_radius) * (1 - progress_value_2), inner_corner_radius)
self._canvas.coords("progress_oval_2_b", width - border_width - inner_corner_radius,
border_width + inner_corner_radius + (height - 2 * border_width - 2 * inner_corner_radius) * (1 - progress_value_2), inner_corner_radius)
self._canvas.coords("progress_oval_3_a", width - border_width - inner_corner_radius,
border_width + inner_corner_radius + (height - 2 * border_width - 2 * inner_corner_radius) * (1 - progress_value_1), inner_corner_radius)
self._canvas.coords("progress_oval_3_b", width - border_width - inner_corner_radius,
border_width + inner_corner_radius + (height - 2 * border_width - 2 * inner_corner_radius) * (1 - progress_value_1), inner_corner_radius)
self._canvas.coords("progress_oval_4_a", border_width + inner_corner_radius,
border_width + inner_corner_radius + (height - 2 * border_width - 2 * inner_corner_radius) * (1 - progress_value_1), inner_corner_radius)
self._canvas.coords("progress_oval_4_b", border_width + inner_corner_radius,
border_width + inner_corner_radius + (height - 2 * border_width - 2 * inner_corner_radius) * (1 - progress_value_1), inner_corner_radius)
# set positions of progress rect parts
self._canvas.coords("progress_rectangle_1",
border_width + inner_corner_radius,
border_width + (height - 2 * border_width - 2 * inner_corner_radius) * (1 - progress_value_2),
width - border_width - inner_corner_radius,
border_width + (height - 2 * border_width - 2 * inner_corner_radius) * (1 - progress_value_1))
self._canvas.coords("progress_rectangle_2",
border_width,
border_width + inner_corner_radius + (height - 2 * border_width - 2 * inner_corner_radius) * (1 - progress_value_2),
width - border_width,
border_width + inner_corner_radius + (height - 2 * border_width - 2 * inner_corner_radius) * (1 - progress_value_1))
return requires_recoloring or requires_recoloring_2
def __draw_rounded_progress_bar_with_border_circle_shapes(self, width: int, height: int, corner_radius: int, border_width: int, inner_corner_radius: int,
progress_value_1: float, progress_value_2: float, orientation: str) -> bool:
requires_recoloring = self.__draw_rounded_rect_with_border_circle_shapes(width, height, corner_radius, border_width, inner_corner_radius)
# create progress parts
if not self._canvas.find_withtag("progress_rectangle_1"):
self._canvas.create_rectangle(0, 0, 0, 0, tags=("progress_rectangle_1", "progress_parts"), width=0)
requires_recoloring = True
if orientation == "w":
x1 = border_width + inner_corner_radius + (width - 2 * border_width - 2 * inner_corner_radius) * progress_value_1
x2 = border_width + inner_corner_radius + (width - 2 * border_width - 2 * inner_corner_radius) * progress_value_2
self._canvas.coords("progress_rectangle_1", x1, border_width, x2, height - border_width)
elif orientation == "s":
y1 = border_width + inner_corner_radius + (height - 2 * border_width - 2 * inner_corner_radius) * (1 - progress_value_2)
y2 = border_width + inner_corner_radius + (height - 2 * border_width - 2 * inner_corner_radius) * (1 - progress_value_1)
self._canvas.coords("progress_rectangle_1", border_width, y1, width - border_width, y2)
if inner_corner_radius > 0:
if not self._canvas.find_withtag("progress_oval_1"):
self._canvas.create_oval(0, 0, 0, 0, tags=("progress_oval_1", "progress_parts"), width=0)
self._canvas.create_oval(0, 0, 0, 0, tags=("progress_oval_2", "progress_parts"), width=0)
self._canvas.create_oval(0, 0, 0, 0, tags=("progress_oval_3", "progress_parts"), width=0)
self._canvas.create_oval(0, 0, 0, 0, tags=("progress_oval_4", "progress_parts"), width=0)
requires_recoloring = True
if orientation == "w":
self._canvas.coords("progress_oval_1", x1 - inner_corner_radius, border_width, x1 + inner_corner_radius, border_width + 2 * inner_corner_radius)
self._canvas.coords("progress_oval_2", x2 - inner_corner_radius, border_width, x2 + inner_corner_radius, border_width + 2 * inner_corner_radius)
self._canvas.coords("progress_oval_3", x2 - inner_corner_radius, height - border_width - 2 * inner_corner_radius, x2 + inner_corner_radius, height - border_width)
self._canvas.coords("progress_oval_4", x1 - inner_corner_radius, height - border_width - 2 * inner_corner_radius, x1 + inner_corner_radius, height - border_width)
elif orientation == "s":
self._canvas.coords("progress_oval_1", border_width, y1 - inner_corner_radius, border_width + 2 * inner_corner_radius, y1 + inner_corner_radius)
self._canvas.coords("progress_oval_2", width - border_width - 2 * inner_corner_radius, y1 - inner_corner_radius, width - border_width, y1 + inner_corner_radius)
self._canvas.coords("progress_oval_3", width - border_width - 2 * inner_corner_radius, y2 - inner_corner_radius, width - border_width, y2 + inner_corner_radius)
self._canvas.coords("progress_oval_4", border_width, y2 - inner_corner_radius, border_width + 2 * inner_corner_radius, y2 + inner_corner_radius)
else:
self._canvas.delete("progress_oval_1", "progress_oval_2", "progress_oval_3", "progress_oval_4")
return requires_recoloring
def draw_rounded_slider_with_border_and_2_button(self, width: Union[float, int], height: Union[float, int], corner_radius: Union[float, int], def draw_rounded_slider_with_border_and_2_button(self, width: Union[float, int], height: Union[float, int], corner_radius: Union[float, int],
border_width: Union[float, int], button_length: Union[float, int], button_corner_radius: Union[float, int], border_width: Union[float, int], button_length: Union[float, int], button_corner_radius: Union[float, int],
slider_value: float, slider_2_value: float, orientation: str) -> bool: slider_value: float, slider_2_value: float, orientation: str) -> bool:
@@ -182,25 +508,28 @@ class CustomDrawEngine:
button_length = round(button_length) button_length = round(button_length)
border_width = round(border_width) border_width = round(border_width)
button_corner_radius = round(button_corner_radius) button_corner_radius = round(button_corner_radius)
corner_radius = DrawEngine._DrawEngine__calc_optimal_corner_radius(self, corner_radius) # optimize corner_radius for different drawing methods (different rounding) corner_radius = self.__calc_optimal_corner_radius(corner_radius) # optimize corner_radius for different drawing methods (different rounding)
if corner_radius >= border_width: if corner_radius >= border_width:
inner_corner_radius = corner_radius - border_width inner_corner_radius = corner_radius - border_width
else: else:
inner_corner_radius = 0 inner_corner_radius = 0
if self.preferred_drawing_method == "polygon_shapes" or self.preferred_drawing_method == "circle_shapes": if self.preferred_drawing_method == "polygon_shapes":
return self.__draw_rounded_slider_with_border_and_2_button_polygon_shapes(width, height, corner_radius, border_width, inner_corner_radius, return self.__draw_rounded_slider_with_border_and_2_button_polygon_shapes(width, height, corner_radius, border_width, inner_corner_radius,
button_length, button_corner_radius, slider_value, slider_2_value, orientation) button_length, button_corner_radius, slider_value, slider_2_value, orientation)
elif self.preferred_drawing_method == "font_shapes": elif self.preferred_drawing_method == "font_shapes":
return self.__draw_rounded_slider_with_border_and_2_button_font_shapes(width, height, corner_radius, border_width, inner_corner_radius, return self.__draw_rounded_slider_with_border_and_2_button_font_shapes(width, height, corner_radius, border_width, inner_corner_radius,
button_length, button_corner_radius, slider_value, slider_2_value, orientation) button_length, button_corner_radius, slider_value, slider_2_value, orientation)
elif self.preferred_drawing_method == "circle_shapes":
return self.__draw_rounded_slider_with_border_and_2_button_circle_shapes(width, height, corner_radius, border_width, inner_corner_radius,
button_length, button_corner_radius, slider_value, slider_2_value, orientation)
def __draw_rounded_slider_with_border_and_2_button_polygon_shapes(self, width: int, height: int, corner_radius: int, border_width: int, inner_corner_radius: int, def __draw_rounded_slider_with_border_and_2_button_polygon_shapes(self, width: int, height: int, corner_radius: int, border_width: int, inner_corner_radius: int,
button_length: int, button_corner_radius: int, slider_value: float, slider_2_value: float, orientation: str) -> bool: button_length: int, button_corner_radius: int, slider_value: float, slider_2_value: float, orientation: str) -> bool:
# draw normal progressbar # draw normal progressbar
requires_recoloring = DrawEngine._DrawEngine__draw_rounded_progress_bar_with_border_polygon_shapes(self, width, height, corner_radius, border_width, inner_corner_radius, requires_recoloring = self.__draw_rounded_progress_bar_with_border_polygon_shapes(width, height, corner_radius, border_width, inner_corner_radius,
slider_value, slider_2_value, orientation) slider_value, slider_2_value, orientation)
# create slider button part # create slider button part
@@ -258,8 +587,7 @@ class CustomDrawEngine:
button_length: int, button_corner_radius: int, slider_value: float, slider_2_value: float, orientation: str) -> bool: button_length: int, button_corner_radius: int, slider_value: float, slider_2_value: float, orientation: str) -> bool:
# draw normal progressbar # draw normal progressbar
requires_recoloring = DrawEngine._DrawEngine__draw_rounded_progress_bar_with_border_font_shapes(self, width, height, corner_radius, border_width, requires_recoloring = self.__draw_rounded_progress_bar_with_border_font_shapes(width, height, corner_radius, border_width, inner_corner_radius, slider_value, slider_2_value, orientation)
inner_corner_radius, slider_value, slider_2_value, orientation)
# create 4 circles (if not needed, then less) # create 4 circles (if not needed, then less)
if not self._canvas.find_withtag("slider_oval_1_a"): if not self._canvas.find_withtag("slider_oval_1_a"):
@@ -285,14 +613,14 @@ class CustomDrawEngine:
self._canvas.create_aa_circle(0, 0, 0, tags=("slider_oval_3_a", "slider_corner_part", "slider_parts", "slider_0_parts"), anchor=tkinter.CENTER) self._canvas.create_aa_circle(0, 0, 0, tags=("slider_oval_3_a", "slider_corner_part", "slider_parts", "slider_0_parts"), anchor=tkinter.CENTER)
self._canvas.create_aa_circle(0, 0, 0, tags=("slider_oval_3_b", "slider_corner_part", "slider_parts", "slider_0_parts"), anchor=tkinter.CENTER, angle=180) self._canvas.create_aa_circle(0, 0, 0, tags=("slider_oval_3_b", "slider_corner_part", "slider_parts", "slider_0_parts"), anchor=tkinter.CENTER, angle=180)
requires_recoloring = True requires_recoloring = True
elif self._canvas.find_withtag("border_oval_3_a") and not (button_length > 0 and height > 2 * button_corner_radius): elif self._canvas.find_withtag("slider_oval_3_a") and not (button_length > 0 and height > 2 * button_corner_radius):
self._canvas.delete("slider_oval_3_a", "slider_oval_3_b") self._canvas.delete("slider_oval_3_a", "slider_oval_3_b")
# create the 2 rectangles (if needed) # create the 2 rectangles (if needed)
if not self._canvas.find_withtag("slider_rectangle_1") and button_length > 0: if not self._canvas.find_withtag("slider_rectangle_1") and button_length > 0:
self._canvas.create_rectangle(0, 0, 0, 0, tags=("slider_rectangle_1", "slider_rectangle_part", "slider_parts", "slider_0_parts"), width=0) self._canvas.create_rectangle(0, 0, 0, 0, tags=("slider_rectangle_1", "slider_rectangle_part", "slider_parts", "slider_0_parts"), width=0)
requires_recoloring = True requires_recoloring = True
elif self._canvas.find_withtag("slider_rectangle_1") and not button_length > 0: elif self._canvas.find_withtag("slider елдер_1") and not button_length > 0:
self._canvas.delete("slider_rectangle_1") self._canvas.delete("slider_rectangle_1")
if not self._canvas.find_withtag("slider_rectangle_2") and height > 2 * button_corner_radius: if not self._canvas.find_withtag("slider_rectangle_2") and height > 2 * button_corner_radius:
@@ -338,7 +666,7 @@ class CustomDrawEngine:
button_corner_radius, slider_y_position - (button_length / 2) - button_corner_radius, button_corner_radius, slider_y_position - (button_length / 2) - button_corner_radius,
width - button_corner_radius, slider_y_position + (button_length / 2) + button_corner_radius) width - button_corner_radius, slider_y_position + (button_length / 2) + button_corner_radius)
######## second button ########## # second button
# create 4 circles (if not needed, then less) # create 4 circles (if not needed, then less)
if not self._canvas.find_withtag("slider_oval_2_1_a"): if not self._canvas.find_withtag("slider_oval_2_1_a"):
self._canvas.create_aa_circle(0, 0, 0, tags=("slider_oval_2_1_a", "slider_corner_part", "slider_parts", "slider_1_parts"), anchor=tkinter.CENTER) self._canvas.create_aa_circle(0, 0, 0, tags=("slider_oval_2_1_a", "slider_corner_part", "slider_parts", "slider_1_parts"), anchor=tkinter.CENTER)
@@ -363,7 +691,7 @@ class CustomDrawEngine:
self._canvas.create_aa_circle(0, 0, 0, tags=("slider_oval_2_3_a", "slider_corner_part", "slider_parts", "slider_1_parts"), anchor=tkinter.CENTER) self._canvas.create_aa_circle(0, 0, 0, tags=("slider_oval_2_3_a", "slider_corner_part", "slider_parts", "slider_1_parts"), anchor=tkinter.CENTER)
self._canvas.create_aa_circle(0, 0, 0, tags=("slider_oval_2_3_b", "slider_corner_part", "slider_parts", "slider_1_parts"), anchor=tkinter.CENTER, angle=180) self._canvas.create_aa_circle(0, 0, 0, tags=("slider_oval_2_3_b", "slider_corner_part", "slider_parts", "slider_1_parts"), anchor=tkinter.CENTER, angle=180)
requires_recoloring = True requires_recoloring = True
elif self._canvas.find_withtag("border_oval_2_3_a") and not (button_length > 0 and height > 2 * button_corner_radius): elif self._canvas.find_withtag("slider_oval_2_3_a") and not (button_length > 0 and height > 2 * button_corner_radius):
self._canvas.delete("slider_oval_2_3_a", "slider_oval_2_3_b") self._canvas.delete("slider_oval_2_3_a", "slider_oval_2_3_b")
# create the 2 rectangles (if needed) # create the 2 rectangles (if needed)
@@ -421,6 +749,67 @@ class CustomDrawEngine:
return requires_recoloring return requires_recoloring
def __draw_rounded_slider_with_border_and_2_button_circle_shapes(self, width: int, height: int, corner_radius: int, border_width: int, inner_corner_radius: int,
button_length: int, button_corner_radius: int, slider_value: float, slider_2_value: float, orientation: str) -> bool:
requires_recoloring = self.__draw_rounded_progress_bar_with_border_circle_shapes(width, height, corner_radius, border_width, inner_corner_radius, slider_value, slider_2_value, orientation)
# create slider button parts
if not self._canvas.find_withtag("slider_0_parts"):
self._canvas.create_oval(0, 0, 0, 0, tags=("slider_oval_1", "slider_parts", "slider_0_parts"), width=0)
self._canvas.create_oval(0, 0, 0, 0, tags=("slider_oval_2", "slider_parts", "slider_0_parts"), width=0)
self._canvas.create_oval(0, 0, 0, 0, tags=("slider_oval_3", "slider_parts", "slider_0_parts"), width=0)
self._canvas.create_oval(0, 0, 0, 0, tags=("slider_oval_4", "slider_parts", "slider_0_parts"), width=0)
self._canvas.create_rectangle(0, 0, 0, 0, tags=("slider_rectangle_1", "slider_parts", "slider_0_parts"), width=0)
self._canvas.create_rectangle(0, 0, 0, 0, tags=("slider_rectangle_2", "slider_parts", "slider_0_parts"), width=0)
requires_recoloring = True
if not self._canvas.find_withtag("slider_1_parts"):
self._canvas.create_oval(0, 0, 0, 0, tags=("slider_oval_2_1", "slider_parts", "slider_1_parts"), width=0)
self._canvas.create_oval(0, 0, 0, 0, tags=("slider_oval_2_2", "slider_parts", "slider_1_parts"), width=0)
self._canvas.create_oval(0, 0, 0, 0, tags=("slider_oval_2_3", "slider_parts", "slider_1_parts"), width=0)
self._canvas.create_oval(0, 0, 0, 0, tags=("slider_oval_2_4", "slider_parts", "slider_1_parts"), width=0)
self._canvas.create_rectangle(0, 0, 0, 0, tags=("slider_rectangle_2_1", "slider_parts", "slider_1_parts"), width=0)
self._canvas.create_rectangle(0, 0, 0, 0, tags=("slider_rectangle_2_2", "slider_parts", "slider_1_parts"), width=0)
requires_recoloring = True
if orientation == "w":
slider_x_position = corner_radius + (button_length / 2) + (width - 2 * corner_radius - button_length) * slider_value
self._canvas.coords("slider_oval_1", slider_x_position - button_length / 2 - button_corner_radius, 0, slider_x_position - button_length / 2 + button_corner_radius, 2 * button_corner_radius)
self._canvas.coords("slider_oval_2", slider_x_position + button_length / 2 - button_corner_radius, 0, slider_x_position + button_length / 2 + button_corner_radius, 2 * button_corner_radius)
self._canvas.coords("slider_oval_3", slider_x_position + button_length / 2 - button_corner_radius, height - 2 * button_corner_radius, slider_x_position + button_length / 2 + button_corner_radius, height)
self._canvas.coords("slider_oval_4", slider_x_position - button_length / 2 - button_corner_radius, height - 2 * button_corner_radius, slider_x_position - button_length / 2 + button_corner_radius, height)
self._canvas.coords("slider_rectangle_1", slider_x_position - button_length / 2, 0, slider_x_position + button_length / 2, height)
self._canvas.coords("slider_rectangle_2", slider_x_position - button_length / 2 - button_corner_radius, button_corner_radius, slider_x_position + button_length / 2 + button_corner_radius, height - button_corner_radius)
slider_x_position = corner_radius + (button_length / 2) + (width - 2 * corner_radius - button_length) * slider_2_value
self._canvas.coords("slider_oval_2_1", slider_x_position - button_length / 2 - button_corner_radius, 0, slider_x_position - button_length / 2 + button_corner_radius, 2 * button_corner_radius)
self._canvas.coords("slider_oval_2_2", slider_x_position + button_length / 2 - button_corner_radius, 0, slider_x_position + button_length / 2 + button_corner_radius, 2 * button_corner_radius)
self._canvas.coords("slider_oval_2_3", slider_x_position + button_length / 2 - button_corner_radius, height - 2 * button_corner_radius, slider_x_position + button_length / 2 + button_corner_radius, height)
self._canvas.coords("slider_oval_2_4", slider_x_position - button_length / 2 - button_corner_radius, height - 2 * button_corner_radius, slider_x_position - button_length / 2 + button_corner_radius, height)
self._canvas.coords("slider_rectangle_2_1", slider_x_position - button_length / 2, 0, slider_x_position + button_length / 2, height)
self._canvas.coords("slider_rectangle_2_2", slider_x_position - button_length / 2 - button_corner_radius, button_corner_radius, slider_x_position + button_length / 2 + button_corner_radius, height - button_corner_radius)
elif orientation == "s":
slider_y_position = corner_radius + (button_length / 2) + (height - 2 * corner_radius - button_length) * (1 - slider_value)
self._canvas.coords("slider_oval_1", 0, slider_y_position - button_length / 2 - button_corner_radius, 2 * button_corner_radius, slider_y_position - button_length / 2 + button_corner_radius)
self._canvas.coords("slider_oval_2", 0, slider_y_position + button_length / 2 - button_corner_radius, 2 * button_corner_radius, slider_y_position + button_length / 2 + button_corner_radius)
self._canvas.coords("slider_oval_3", width - 2 * button_corner_radius, slider_y_position + button_length / 2 - button_corner_radius, width, slider_y_position + button_length / 2 + button_corner_radius)
self._canvas.coords("slider_oval_4", width - 2 * button_corner_radius, slider_y_position - button_length / 2 - button_corner_radius, width, slider_y_position - button_length / 2 + button_corner_radius)
self._canvas.coords("slider_rectangle_1", 0, slider_y_position - button_length / 2, width, slider_y_position + button_length / 2)
self._canvas.coords("slider_rectangle_2", button_corner_radius, slider_y_position - button_length / 2 - button_corner_radius, width - button_corner_radius, slider_y_position + button_length / 2 + button_corner_radius)
slider_y_position = corner_radius + (button_length / 2) + (height - 2 * corner_radius - button_length) * (1 - slider_2_value)
self._canvas.coords("slider_oval_2_1", 0, slider_y_position - button_length / 2 - button_corner_radius, 2 * button_corner_radius, slider_y_position - button_length / 2 + button_corner_radius)
self._canvas.coords("slider_oval_2_2", 0, slider_y_position + button_length / 2 - button_corner_radius, 2 * button_corner_radius, slider_y_position + button_length / 2 + button_corner_radius)
self._canvas.coords("slider_oval_2_3", width - 2 * button_corner_radius, slider_y_position + button_length / 2 - button_corner_radius, width, slider_y_position + button_length / 2 + button_corner_radius)
self._canvas.coords("slider_oval_2_4", width - 2 * button_corner_radius, slider_y_position - button_length / 2 - button_corner_radius, width, slider_y_position - button_length / 2 + button_corner_radius)
self._canvas.coords("slider_rectangle_2_1", 0, slider_y_position - button_length / 2, width, slider_y_position + button_length / 2)
self._canvas.coords("slider_rectangle_2_2", button_corner_radius, slider_y_position - button_length / 2 - button_corner_radius, width - button_corner_radius, slider_y_position + button_length / 2 + button_corner_radius)
if requires_recoloring:
self._canvas.tag_raise("slider_parts")
return requires_recoloring
class CTkRangeSlider(CTkBaseClass): class CTkRangeSlider(CTkBaseClass):
""" """
Range slider with rounded corners, border, number of steps, variable support, vertical orientation. Range slider with rounded corners, border, number of steps, variable support, vertical orientation.

View File

@@ -1,4 +1,4 @@
// dd_ring_buffer.js // buffer.js
// works kinda like an audio delay // works kinda like an audio delay
// stacks the previous n frames into a buffer // stacks the previous n frames into a buffer

View File

@@ -1,4 +1,4 @@
// dd_delay.js // delay.js
// works kinda like an audio delay // works kinda like an audio delay
// stacks the previous n frames into a buffer // stacks the previous n frames into a buffer

View File

@@ -1,4 +1,4 @@
// dd_RandomDamage(invertRandomN).js // invertReverse.js
// invert x and y component of mv for random number of frames if threshold met for frame // invert x and y component of mv for random number of frames if threshold met for frame
let threshold = 95; let threshold = 95;

View File

@@ -1,4 +1,4 @@
// dd_mirror_X.js // mirror_X.js
// clean buffer : // clean buffer :
var buffer = [ ]; var buffer = [ ];

View File

@@ -1,4 +1,4 @@
// dd_MultiplySlowest_50.js // noise.js
// Multiply slowest moving mv's // Multiply slowest moving mv's
var LARGEST = 0; var LARGEST = 0;
var SOME_PERCENTAGE = 0.5; var SOME_PERCENTAGE = 0.5;

View File

@@ -1,4 +1,4 @@
// dd_sheer.js // sheer.js
var ZOOM = -20; var ZOOM = -20;

View File

@@ -1,5 +1,5 @@
// dd_RandomDamage(antiGrav).js // shift.js
// anitgravityify if threshold met for frame // anitgravitify if threshold met for frame
let threshold = 98; let threshold = 98;
// global variable holding forward motion vectors from previous frames // global variable holding forward motion vectors from previous frames

View File

@@ -1,4 +1,4 @@
// dd_zero.js // sink.js
// only mess frames if mv > movement_threshold // only mess frames if mv > movement_threshold
var movement_threshold = 3; var movement_threshold = 3;
function glitch_frame(frame) function glitch_frame(frame)

View File

@@ -1,4 +1,4 @@
// dd_slam_zoom_in.js // slam_zoom.js
var ZOOM = 20; var ZOOM = 20;

View File

@@ -1,4 +1,4 @@
// dd_RandomDamage(progZoom).js // slice.js
// progressive Zoom x and y components of mv if threshold met for frame // progressive Zoom x and y components of mv if threshold met for frame
let threshold = 95; let threshold = 95;

View File

@@ -1,4 +1,4 @@
// dd_RandomDamage(stopXY).js // stop.js
// stop x and y component of mv for n framesif threshold met for frame // stop x and y component of mv for n framesif threshold met for frame
let threshold = 95; let threshold = 95;

View File

@@ -1,4 +1,4 @@
// dd_zoom_in.js // zoom.js
var ZOOM = 20; var ZOOM = 20;

View File

@@ -1,10 +1,10 @@
""" """
DATAMOSHER PRO Py version 2.3 DATAMOSHER PRO Py version 2.4
Author: Akash Bora (Akascape) Author: Akash Bora (Akascape)
License: MIT | Copyright (c) 2024 Akash Bora License: MIT | Copyright (c) 2025 Akash Bora
""" """
currentversion = 2.3 currentversion = 2.4
#Import installed modules #Import installed modules
import tkinter import tkinter
@@ -744,6 +744,14 @@ dynamic()
keepframe.select() keepframe.select()
param = "" param = ""
def open_file(sfile):
if sys.platform.startswith('darwin'): # macOS
subprocess.call(('open', sfile))
elif os.name == 'nt': # Windows
os.startfile(sfile)
elif os.name == 'posix': # Linux
subprocess.call(('xdg-open', sfile))
#autosave video name #autosave video name
def savename(): def savename():
global sfile global sfile
@@ -885,10 +893,10 @@ def do_the_mosh():
if os.path.exists(sfile): if os.path.exists(sfile):
res = messagebox.showinfo("Exported!", "File exported successfully, \nFile Location: " +str(sfile)) res = messagebox.showinfo("Exported!", "File exported successfully, \nFile Location: " +str(sfile))
ProcessLabel.configure(text="Last used: "+last_used) ProcessLabel.configure(text="Last used: "+last_used)
try: os.startfile(sfile) try: open_file(sfile)
except: pass except: pass
else: else:
messagebox.showerror("Oops!", "Something went wrong! \nPlease recheck the settings and try again.") messagebox.showerror("Oops!", "Something went wrong! \nPlease recheck the settings and try again.\nView error logs for more information.")
ProcessLabel.configure(text='Recheck the settings and try again!') ProcessLabel.configure(text='Recheck the settings and try again!')
button_open.configure(state=tkinter.NORMAL) button_open.configure(state=tkinter.NORMAL)
@@ -904,6 +912,8 @@ button_mosh = customtkinter.CTkButton(master=frame_right, height=30,width=110,co
text="MOSH", command=Threadthis) text="MOSH", command=Threadthis)
button_mosh.pack(padx=(0,10), pady=10, fill="x", side="right") button_mosh.pack(padx=(0,10), pady=10, fill="x", side="right")
root.after(100, root.focus_force)
root.mainloop() root.mainloop()
#--------------------------------------------------------------------# #--------------------------------------------------------------------#

View File

@@ -20,6 +20,27 @@ except ImportError:
DIRPATH = os.path.dirname(os.path.realpath(__file__)) DIRPATH = os.path.dirname(os.path.realpath(__file__))
#Set executable permissions for macOS
def set_mac_permissions():
if sys.platform.startswith("darwin"):
print("Setting executable permissions for macOS...")
ffgac = os.path.join(DIRPATH,"FFglitch","ffgac")
ffedit = os.path.join(DIRPATH,"FFglitch","ffedit")
try:
if os.path.exists(ffgac):
os.chmod(ffgac, 0o755)
print("Permissions set for ffgac")
except Exception as e:
print(f"Failed to set permissions for ffgac: {e} \nPlease go to System Settings -> Security & Privacy -> scroll down and give permission to the ffgac file")
try:
if os.path.exists(ffedit):
os.chmod(ffedit, 0o755)
print("Permissions set for ffedit")
except Exception as e:
print(f"Failed to set permissions for ffedit: {e} \nPlease go to System Settings -> Security & Privacy -> scroll down and give permission to the ffedit file")
#Checking the required folders #Checking the required folders
folders = ["Assets","FFglitch","DatamoshLib","pymosh"] folders = ["Assets","FFglitch","DatamoshLib","pymosh"]
missingfolder=[] missingfolder=[]
@@ -69,6 +90,8 @@ else:
#Check FFglitch Status #Check FFglitch Status
def checkffglitch(): def checkffglitch():
print("Checking FFglitch:") print("Checking FFglitch:")
# Set permissions for macOS before running
set_mac_permissions()
print("Running ffgac...") print("Running ffgac...")
ffgac = os.path.join(DIRPATH,"FFglitch","ffgac") ffgac = os.path.join(DIRPATH,"FFglitch","ffgac")
ffedit = os.path.join(DIRPATH,"FFglitch","ffedit") ffedit = os.path.join(DIRPATH,"FFglitch","ffedit")
@@ -130,6 +153,8 @@ else:
if os.path.exists(os.path.join("FFglitch","ffgac")) or os.path.exists(os.path.join("FFglitch","ffgac.exe")): if os.path.exists(os.path.join("FFglitch","ffgac")) or os.path.exists(os.path.join("FFglitch","ffgac.exe")):
os.remove(os.path.join("FFglitch","ffglitch.zip")) os.remove(os.path.join("FFglitch","ffglitch.zip"))
time.sleep(1) time.sleep(1)
# Set permissions after extraction for macOS
set_mac_permissions()
checkffglitch() checkffglitch()
print("FFglitch setup complete!") print("FFglitch setup complete!")
except: except:
@@ -138,6 +163,7 @@ else:
print("ffglitch modes cannot run without ffgac and ffedit packages, download them manually and paste them inside the FFglitch folder.") print("ffglitch modes cannot run without ffgac and ffedit packages, download them manually and paste them inside the FFglitch folder.")
#Everything done! #Everything done!
time.sleep(1)
print("Setup Complete!") print("Setup Complete!")
time.sleep(5) time.sleep(5)
sys.exit() sys.exit()

View File

@@ -0,0 +1,7 @@
imageio
imageio-ffmpeg
numpy
customtkinter
pillow
requests
packaging