pygui: update to allow custom nodes to use icons from any directory
This commit is contained in:
parent
93813358b5
commit
2387812a76
8 changed files with 36 additions and 40 deletions
|
@ -196,11 +196,11 @@ class Application(ttk.Frame):
|
||||||
self.menubar.set_state(is_runtime=False)
|
self.menubar.set_state(is_runtime=False)
|
||||||
self.toolbar.set_design()
|
self.toolbar.set_design()
|
||||||
|
|
||||||
def get_icon(self, image_enum: ImageEnum, *, width: int) -> PhotoImage:
|
def get_enum_icon(self, image_enum: ImageEnum, *, width: int) -> PhotoImage:
|
||||||
return images.from_enum(image_enum, width=width, scale=self.app_scale)
|
return images.from_enum(image_enum, width=width, scale=self.app_scale)
|
||||||
|
|
||||||
def get_custom_icon(self, image_file: str, *, width: int) -> PhotoImage:
|
def get_file_icon(self, file_path: str, *, width: int) -> PhotoImage:
|
||||||
return images.from_name(image_file, width=width, scale=self.app_scale)
|
return images.from_file(file_path, width=width, scale=self.app_scale)
|
||||||
|
|
||||||
def close(self) -> None:
|
def close(self) -> None:
|
||||||
self.master.destroy()
|
self.master.destroy()
|
||||||
|
|
|
@ -216,7 +216,7 @@ class CustomNodesDialog(Dialog):
|
||||||
def click_create(self) -> None:
|
def click_create(self) -> None:
|
||||||
name = self.name.get()
|
name = self.name.get()
|
||||||
if name not in self.app.core.custom_nodes:
|
if name not in self.app.core.custom_nodes:
|
||||||
image_file = Path(self.image_file).stem
|
image_file = str(Path(self.image_file).absolute())
|
||||||
custom_node = CustomNode(name, image_file, list(self.services))
|
custom_node = CustomNode(name, image_file, list(self.services))
|
||||||
node_draw = NodeDraw.from_custom(custom_node)
|
node_draw = NodeDraw.from_custom(custom_node)
|
||||||
logging.info(
|
logging.info(
|
||||||
|
@ -236,7 +236,7 @@ class CustomNodesDialog(Dialog):
|
||||||
self.selected = name
|
self.selected = name
|
||||||
node_draw = self.app.core.custom_nodes.pop(previous_name)
|
node_draw = self.app.core.custom_nodes.pop(previous_name)
|
||||||
node_draw.model = name
|
node_draw.model = name
|
||||||
node_draw.image_file = Path(self.image_file).stem
|
node_draw.image_file = str(Path(self.image_file).absolute())
|
||||||
node_draw.image = self.image
|
node_draw.image = self.image
|
||||||
node_draw.services = self.services
|
node_draw.services = self.services
|
||||||
logging.debug(
|
logging.debug(
|
||||||
|
|
|
@ -84,17 +84,17 @@ class MobilityPlayerDialog(Dialog):
|
||||||
for i in range(3):
|
for i in range(3):
|
||||||
frame.columnconfigure(i, weight=1)
|
frame.columnconfigure(i, weight=1)
|
||||||
|
|
||||||
image = self.app.get_icon(ImageEnum.START, width=ICON_SIZE)
|
image = self.app.get_enum_icon(ImageEnum.START, width=ICON_SIZE)
|
||||||
self.play_button = ttk.Button(frame, image=image, command=self.click_play)
|
self.play_button = ttk.Button(frame, image=image, command=self.click_play)
|
||||||
self.play_button.image = image
|
self.play_button.image = image
|
||||||
self.play_button.grid(row=0, column=0, sticky=tk.EW, padx=PADX)
|
self.play_button.grid(row=0, column=0, sticky=tk.EW, padx=PADX)
|
||||||
|
|
||||||
image = self.app.get_icon(ImageEnum.PAUSE, width=ICON_SIZE)
|
image = self.app.get_enum_icon(ImageEnum.PAUSE, width=ICON_SIZE)
|
||||||
self.pause_button = ttk.Button(frame, image=image, command=self.click_pause)
|
self.pause_button = ttk.Button(frame, image=image, command=self.click_pause)
|
||||||
self.pause_button.image = image
|
self.pause_button.image = image
|
||||||
self.pause_button.grid(row=0, column=1, sticky=tk.EW, padx=PADX)
|
self.pause_button.grid(row=0, column=1, sticky=tk.EW, padx=PADX)
|
||||||
|
|
||||||
image = self.app.get_icon(ImageEnum.STOP, width=ICON_SIZE)
|
image = self.app.get_enum_icon(ImageEnum.STOP, width=ICON_SIZE)
|
||||||
self.stop_button = ttk.Button(frame, image=image, command=self.click_stop)
|
self.stop_button = ttk.Button(frame, image=image, command=self.click_stop)
|
||||||
self.stop_button.image = image
|
self.stop_button.image = image
|
||||||
self.stop_button.grid(row=0, column=2, sticky=tk.EW, padx=PADX)
|
self.stop_button.grid(row=0, column=2, sticky=tk.EW, padx=PADX)
|
||||||
|
|
|
@ -48,10 +48,10 @@ class ServiceConfigDialog(Dialog):
|
||||||
self.directory_entry: Optional[ttk.Entry] = None
|
self.directory_entry: Optional[ttk.Entry] = None
|
||||||
self.default_directories: List[str] = []
|
self.default_directories: List[str] = []
|
||||||
self.temp_directories: List[str] = []
|
self.temp_directories: List[str] = []
|
||||||
self.documentnew_img: PhotoImage = self.app.get_icon(
|
self.documentnew_img: PhotoImage = self.app.get_enum_icon(
|
||||||
ImageEnum.DOCUMENTNEW, width=ICON_SIZE
|
ImageEnum.DOCUMENTNEW, width=ICON_SIZE
|
||||||
)
|
)
|
||||||
self.editdelete_img: PhotoImage = self.app.get_icon(
|
self.editdelete_img: PhotoImage = self.app.get_enum_icon(
|
||||||
ImageEnum.EDITDELETE, width=ICON_SIZE
|
ImageEnum.EDITDELETE, width=ICON_SIZE
|
||||||
)
|
)
|
||||||
self.notebook: Optional[ttk.Notebook] = None
|
self.notebook: Optional[ttk.Notebook] = None
|
||||||
|
|
|
@ -95,7 +95,7 @@ class CanvasNode:
|
||||||
def add_antenna(self) -> None:
|
def add_antenna(self) -> None:
|
||||||
x, y = self.position()
|
x, y = self.position()
|
||||||
offset = len(self.antennas) * 8 * self.app.app_scale
|
offset = len(self.antennas) * 8 * self.app.app_scale
|
||||||
img = self.app.get_icon(ImageEnum.ANTENNA, width=images.ANTENNA_SIZE)
|
img = self.app.get_enum_icon(ImageEnum.ANTENNA, width=images.ANTENNA_SIZE)
|
||||||
antenna_id = self.canvas.create_image(
|
antenna_id = self.canvas.create_image(
|
||||||
x - 16 + offset,
|
x - 16 + offset,
|
||||||
y - int(23 * self.app.app_scale),
|
y - int(23 * self.app.app_scale),
|
||||||
|
@ -389,7 +389,7 @@ class CanvasNode:
|
||||||
def scale_antennas(self) -> None:
|
def scale_antennas(self) -> None:
|
||||||
for i in range(len(self.antennas)):
|
for i in range(len(self.antennas)):
|
||||||
antenna_id = self.antennas[i]
|
antenna_id = self.antennas[i]
|
||||||
image = self.app.get_icon(ImageEnum.ANTENNA, width=images.ANTENNA_SIZE)
|
image = self.app.get_enum_icon(ImageEnum.ANTENNA, width=images.ANTENNA_SIZE)
|
||||||
self.canvas.itemconfig(antenna_id, image=image)
|
self.canvas.itemconfig(antenna_id, image=image)
|
||||||
self.antenna_images[antenna_id] = image
|
self.antenna_images[antenna_id] = image
|
||||||
node_x, node_y = self.canvas.coords(self.id)
|
node_x, node_y = self.canvas.coords(self.id)
|
||||||
|
@ -492,7 +492,7 @@ class ShadowNode:
|
||||||
self.node: "CanvasNode" = node
|
self.node: "CanvasNode" = node
|
||||||
self.id: Optional[int] = None
|
self.id: Optional[int] = None
|
||||||
self.text_id: Optional[int] = None
|
self.text_id: Optional[int] = None
|
||||||
self.image: PhotoImage = self.app.get_icon(
|
self.image: PhotoImage = self.app.get_enum_icon(
|
||||||
ImageEnum.SHADOW, width=images.NODE_SIZE
|
ImageEnum.SHADOW, width=images.NODE_SIZE
|
||||||
)
|
)
|
||||||
self.draw()
|
self.draw()
|
||||||
|
|
|
@ -17,7 +17,11 @@ IMAGES: Dict[str, str] = {}
|
||||||
|
|
||||||
def load_all() -> None:
|
def load_all() -> None:
|
||||||
for image in LOCAL_ICONS_PATH.glob("*"):
|
for image in LOCAL_ICONS_PATH.glob("*"):
|
||||||
|
try:
|
||||||
|
ImageEnum(image.stem)
|
||||||
IMAGES[image.stem] = str(image)
|
IMAGES[image.stem] = str(image)
|
||||||
|
except ValueError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
def from_file(
|
def from_file(
|
||||||
|
@ -39,13 +43,6 @@ def from_enum(
|
||||||
return from_file(file_path, width=width, height=height, scale=scale)
|
return from_file(file_path, width=width, height=height, scale=scale)
|
||||||
|
|
||||||
|
|
||||||
def from_name(
|
|
||||||
name: str, *, width: int, height: int = None, scale: float = 1.0
|
|
||||||
) -> PhotoImage:
|
|
||||||
file_path = IMAGES[name]
|
|
||||||
return from_file(file_path, width=width, height=height, scale=scale)
|
|
||||||
|
|
||||||
|
|
||||||
class ImageEnum(Enum):
|
class ImageEnum(Enum):
|
||||||
SWITCH = "lanswitch"
|
SWITCH = "lanswitch"
|
||||||
CORE = "core-icon"
|
CORE = "core-icon"
|
||||||
|
|
|
@ -113,22 +113,21 @@ def _get_custom_file(config: GuiConfig, name: str) -> Optional[str]:
|
||||||
def get_icon(node: Node, app: "Application") -> PhotoImage:
|
def get_icon(node: Node, app: "Application") -> PhotoImage:
|
||||||
scale = app.app_scale
|
scale = app.app_scale
|
||||||
image = None
|
image = None
|
||||||
# node has defined a custom icon
|
# node icon was overriden with a specific value
|
||||||
if node.icon:
|
if node.icon:
|
||||||
try:
|
try:
|
||||||
image = images.from_file(node.icon, width=images.NODE_SIZE, scale=scale)
|
image = images.from_file(node.icon, width=images.NODE_SIZE, scale=scale)
|
||||||
except OSError:
|
except OSError:
|
||||||
logging.error("invalid icon: %s", node.icon)
|
logging.error("invalid icon: %s", node.icon)
|
||||||
else:
|
# custom node
|
||||||
# attempt to find default type/model image
|
elif is_custom(node):
|
||||||
image = images.from_node(node, scale=scale)
|
|
||||||
# attempt to find custom image file
|
|
||||||
if not image:
|
|
||||||
image_file = _get_custom_file(app.guiconfig, node.model)
|
image_file = _get_custom_file(app.guiconfig, node.model)
|
||||||
|
logging.info("custom node file: %s", image_file)
|
||||||
if image_file:
|
if image_file:
|
||||||
image = images.from_name(
|
image = images.from_file(image_file, width=images.NODE_SIZE, scale=scale)
|
||||||
image_file, width=images.NODE_SIZE, scale=scale
|
# built in node
|
||||||
)
|
else:
|
||||||
|
image = images.from_node(node, scale=scale)
|
||||||
# default image, if everything above fails
|
# default image, if everything above fails
|
||||||
if not image:
|
if not image:
|
||||||
image = images.from_enum(
|
image = images.from_enum(
|
||||||
|
@ -171,7 +170,7 @@ class NodeDraw:
|
||||||
node_draw = NodeDraw()
|
node_draw = NodeDraw()
|
||||||
node_draw.custom = True
|
node_draw.custom = True
|
||||||
node_draw.image_file = custom_node.image
|
node_draw.image_file = custom_node.image
|
||||||
node_draw.image = images.from_name(custom_node.image, width=images.NODE_SIZE)
|
node_draw.image = images.from_file(custom_node.image, width=images.NODE_SIZE)
|
||||||
node_draw.node_type = NodeType.DEFAULT
|
node_draw.node_type = NodeType.DEFAULT
|
||||||
node_draw.services = custom_node.services
|
node_draw.services = custom_node.services
|
||||||
node_draw.label = custom_node.name
|
node_draw.label = custom_node.name
|
||||||
|
|
|
@ -58,11 +58,11 @@ class PickerFrame(ttk.Frame):
|
||||||
image_file: str = None,
|
image_file: str = None,
|
||||||
) -> None:
|
) -> None:
|
||||||
if image_enum:
|
if image_enum:
|
||||||
bar_image = self.app.get_icon(image_enum, width=TOOLBAR_SIZE)
|
bar_image = self.app.get_enum_icon(image_enum, width=TOOLBAR_SIZE)
|
||||||
image = self.app.get_icon(image_enum, width=PICKER_SIZE)
|
image = self.app.get_enum_icon(image_enum, width=PICKER_SIZE)
|
||||||
else:
|
else:
|
||||||
bar_image = self.app.get_custom_icon(image_file, width=TOOLBAR_SIZE)
|
bar_image = self.app.get_file_icon(image_file, width=TOOLBAR_SIZE)
|
||||||
image = self.app.get_custom_icon(image_file, width=PICKER_SIZE)
|
image = self.app.get_file_icon(image_file, width=PICKER_SIZE)
|
||||||
button = ttk.Button(
|
button = ttk.Button(
|
||||||
self, image=image, text=label, compound=tk.TOP, style=Styles.picker_button
|
self, image=image, text=label, compound=tk.TOP, style=Styles.picker_button
|
||||||
)
|
)
|
||||||
|
@ -93,7 +93,7 @@ class ButtonBar(ttk.Frame):
|
||||||
def create_button(
|
def create_button(
|
||||||
self, image_enum: ImageEnum, func: Callable, tooltip: str, radio: bool = False
|
self, image_enum: ImageEnum, func: Callable, tooltip: str, radio: bool = False
|
||||||
) -> ttk.Button:
|
) -> ttk.Button:
|
||||||
image = self.app.get_icon(image_enum, width=TOOLBAR_SIZE)
|
image = self.app.get_enum_icon(image_enum, width=TOOLBAR_SIZE)
|
||||||
button = ttk.Button(self, image=image, command=func)
|
button = ttk.Button(self, image=image, command=func)
|
||||||
button.image = image
|
button.image = image
|
||||||
button.grid(sticky=tk.EW)
|
button.grid(sticky=tk.EW)
|
||||||
|
@ -122,7 +122,7 @@ class MarkerFrame(ttk.Frame):
|
||||||
def draw(self) -> None:
|
def draw(self) -> None:
|
||||||
self.columnconfigure(0, weight=1)
|
self.columnconfigure(0, weight=1)
|
||||||
|
|
||||||
image = self.app.get_icon(ImageEnum.DELETE, width=16)
|
image = self.app.get_enum_icon(ImageEnum.DELETE, width=16)
|
||||||
button = ttk.Button(self, image=image, width=2, command=self.click_clear)
|
button = ttk.Button(self, image=image, width=2, command=self.click_clear)
|
||||||
button.image = image
|
button.image = image
|
||||||
button.grid(sticky=tk.EW, pady=self.PAD)
|
button.grid(sticky=tk.EW, pady=self.PAD)
|
||||||
|
@ -384,7 +384,7 @@ class Toolbar(ttk.Frame):
|
||||||
self.picker.show()
|
self.picker.show()
|
||||||
|
|
||||||
def create_observe_button(self) -> None:
|
def create_observe_button(self) -> None:
|
||||||
image = self.app.get_icon(ImageEnum.OBSERVE, width=TOOLBAR_SIZE)
|
image = self.app.get_enum_icon(ImageEnum.OBSERVE, width=TOOLBAR_SIZE)
|
||||||
menu_button = ttk.Menubutton(
|
menu_button = ttk.Menubutton(
|
||||||
self.runtime_frame, image=image, direction=tk.RIGHT
|
self.runtime_frame, image=image, direction=tk.RIGHT
|
||||||
)
|
)
|
||||||
|
@ -446,9 +446,9 @@ class Toolbar(ttk.Frame):
|
||||||
) -> None:
|
) -> None:
|
||||||
image = None
|
image = None
|
||||||
if image_enum:
|
if image_enum:
|
||||||
image = self.app.get_icon(image_enum, width=TOOLBAR_SIZE)
|
image = self.app.get_enum_icon(image_enum, width=TOOLBAR_SIZE)
|
||||||
elif image_file:
|
elif image_file:
|
||||||
image = self.app.get_custom_icon(image_file, width=TOOLBAR_SIZE)
|
image = self.app.get_file_icon(image_file, width=TOOLBAR_SIZE)
|
||||||
if image:
|
if image:
|
||||||
button.config(image=image)
|
button.config(image=image)
|
||||||
button.image = image
|
button.image = image
|
||||||
|
|
Loading…
Add table
Reference in a new issue