mirror of
https://github.com/TomSchimansky/CustomTkinter.git
synced 2023-08-10 21:13:13 +03:00
completed scaling
This commit is contained in:
@ -2,10 +2,10 @@ import tkinter
|
||||
import tkinter.ttk as ttk
|
||||
import copy
|
||||
import re
|
||||
import math
|
||||
from typing import Callable, Union, TypedDict
|
||||
|
||||
from .ctk_tk import CTk
|
||||
from .ctk_toplevel import CTkToplevel
|
||||
from ..windows.ctk_tk import CTk
|
||||
from ..windows.ctk_toplevel import CTkToplevel
|
||||
from ..appearance_mode_tracker import AppearanceModeTracker
|
||||
from ..scaling_tracker import ScalingTracker
|
||||
from ..theme_manager import CTkThemeManager
|
||||
@ -16,12 +16,23 @@ class CTkBaseClass(tkinter.Frame):
|
||||
super().__init__(*args, width=width, height=height, **kwargs) # set desired size of underlying tkinter.Frame
|
||||
|
||||
self.bg_color = self.detect_color_of_master() if bg_color is None else bg_color
|
||||
self.width = width # width and height in pixel, represent current size of the widget (not the desired size by init)
|
||||
self.height = height # width and height are independent of the scale
|
||||
|
||||
self.current_width = width # current_width and current_height in pixel, represent current size of the widget (not the desired size by init)
|
||||
self.current_height = height # current_width and current_height are independent of the scale
|
||||
self.desired_width = width
|
||||
self.desired_height = height
|
||||
|
||||
# add set_scaling method to callback list of ScalingTracker for automatic scaling changes
|
||||
ScalingTracker.add_widget(self.set_scaling, self)
|
||||
self.scaling = ScalingTracker.get_widget_scaling(self)
|
||||
self.widget_scaling = ScalingTracker.get_widget_scaling(self)
|
||||
self.spacing_scaling = ScalingTracker.get_spacing_scaling(self)
|
||||
|
||||
# save latest geometry function and kwargs
|
||||
class GeometryCallDict(TypedDict):
|
||||
function: Callable
|
||||
kwargs: dict
|
||||
|
||||
self.last_geometry_manager_call: Union[GeometryCallDict, None] = None
|
||||
|
||||
# add set_appearance_mode method to callback list of AppearanceModeTracker for appearance mode changes
|
||||
AppearanceModeTracker.add(self.set_appearance_mode, self)
|
||||
@ -54,6 +65,39 @@ class CTkBaseClass(tkinter.Frame):
|
||||
AppearanceModeTracker.remove(self.set_appearance_mode)
|
||||
super().destroy()
|
||||
|
||||
def place(self, **kwargs):
|
||||
self.last_geometry_manager_call = {"function": super().place, "kwargs": kwargs}
|
||||
super().place(**self.apply_argument_scaling(kwargs))
|
||||
|
||||
def pack(self, **kwargs):
|
||||
self.last_geometry_manager_call = {"function": super().pack, "kwargs": kwargs}
|
||||
super().pack(**self.apply_argument_scaling(kwargs))
|
||||
|
||||
def grid(self, **kwargs):
|
||||
self.last_geometry_manager_call = {"function": super().grid, "kwargs": kwargs}
|
||||
super().grid(**self.apply_argument_scaling(kwargs))
|
||||
|
||||
def apply_argument_scaling(self, kwargs: dict) -> dict:
|
||||
scaled_kwargs = copy.copy(kwargs)
|
||||
|
||||
if "pady" in scaled_kwargs:
|
||||
if isinstance(scaled_kwargs["pady"], (int, float, str)):
|
||||
scaled_kwargs["pady"] = self.apply_spacing_scaling(scaled_kwargs["pady"])
|
||||
elif isinstance(scaled_kwargs["pady"], tuple):
|
||||
scaled_kwargs["pady"] = tuple([self.apply_spacing_scaling(v) for v in scaled_kwargs["pady"]])
|
||||
if "padx" in kwargs:
|
||||
if isinstance(scaled_kwargs["padx"], (int, float, str)):
|
||||
scaled_kwargs["padx"] = self.apply_spacing_scaling(scaled_kwargs["padx"])
|
||||
elif isinstance(scaled_kwargs["padx"], tuple):
|
||||
scaled_kwargs["padx"] = tuple([self.apply_spacing_scaling(v) for v in scaled_kwargs["padx"]])
|
||||
|
||||
if "x" in scaled_kwargs:
|
||||
scaled_kwargs["x"] = self.apply_spacing_scaling(scaled_kwargs["x"])
|
||||
if "y" in scaled_kwargs:
|
||||
scaled_kwargs["y"] = self.apply_spacing_scaling(scaled_kwargs["y"])
|
||||
|
||||
return scaled_kwargs
|
||||
|
||||
def config(self, *args, **kwargs):
|
||||
self.configure(*args, **kwargs)
|
||||
|
||||
@ -77,9 +121,9 @@ class CTkBaseClass(tkinter.Frame):
|
||||
|
||||
def update_dimensions_event(self, event):
|
||||
# only redraw if dimensions changed (for performance)
|
||||
if self.width != math.floor(event.width * self.scaling) or self.height != math.floor(event.height * self.scaling):
|
||||
self.width = event.width / self.scaling # adjust current size according to new size given by event
|
||||
self.height = event.height / self.scaling # width and height are independent of the scale
|
||||
if self.current_width != round(event.width / self.widget_scaling) or self.current_height != round(event.height / self.widget_scaling):
|
||||
self.current_width = round(event.width / self.widget_scaling) # adjust current size according to new size given by event
|
||||
self.current_height = round(event.height / self.widget_scaling) # current_width and current_height are independent of the scale
|
||||
|
||||
self.draw(no_color_updates=True) # faster drawing without color changes
|
||||
|
||||
@ -115,28 +159,44 @@ class CTkBaseClass(tkinter.Frame):
|
||||
|
||||
self.draw()
|
||||
|
||||
def set_scaling(self, new_scaling):
|
||||
self.scaling = new_scaling
|
||||
def set_scaling(self, new_widget_scaling, new_spacing_scaling, new_window_scaling):
|
||||
self.widget_scaling = new_widget_scaling
|
||||
self.spacing_scaling = new_spacing_scaling
|
||||
|
||||
super().configure(width=self.width * self.scaling, height=self.height * self.scaling)
|
||||
super().configure(width=self.apply_widget_scaling(self.desired_width), height=self.apply_widget_scaling(self.desired_height))
|
||||
|
||||
if self.last_geometry_manager_call is not None:
|
||||
self.last_geometry_manager_call["function"](**self.apply_argument_scaling(self.last_geometry_manager_call["kwargs"]))
|
||||
|
||||
def apply_widget_scaling(self, value):
|
||||
if isinstance(value, (int, float)):
|
||||
return value * self.widget_scaling
|
||||
else:
|
||||
return value
|
||||
|
||||
def apply_spacing_scaling(self, value):
|
||||
if isinstance(value, (int, float)):
|
||||
return value * self.spacing_scaling
|
||||
else:
|
||||
return value
|
||||
|
||||
def apply_font_scaling(self, font):
|
||||
if type(font) == tuple or type(font) == list:
|
||||
font_list = list(font)
|
||||
for i in range(len(font_list)):
|
||||
if (type(font_list[i]) == int or type(font_list[i]) == float) and font_list[i] < 0:
|
||||
font_list[i] = int(font_list[i] * self.scaling)
|
||||
font_list[i] = int(font_list[i] * self.widget_scaling)
|
||||
return tuple(font_list)
|
||||
|
||||
elif type(font) == str:
|
||||
for negative_number in re.findall(r" -\d* ", font):
|
||||
font = font.replace(negative_number, f" {int(int(negative_number) * self.scaling)} ")
|
||||
font = font.replace(negative_number, f" {int(int(negative_number) * self.widget_scaling)} ")
|
||||
return font
|
||||
|
||||
elif isinstance(font, tkinter.font.Font):
|
||||
new_font_object = copy.copy(font)
|
||||
if font.cget("size") < 0:
|
||||
new_font_object.config(size=int(font.cget("size") * self.scaling))
|
||||
new_font_object.config(size=int(font.cget("size") * self.widget_scaling))
|
||||
return new_font_object
|
||||
|
||||
else:
|
||||
|
Reference in New Issue
Block a user