1
1
import logging
2
2
import math
3
3
import tkinter as tk
4
- from tkinter import PhotoImage , font , ttk
4
+ from tkinter import PhotoImage , font , messagebox , ttk
5
5
from tkinter .ttk import Progressbar
6
6
from typing import Any , Dict , Optional , Type
7
7
8
8
import grpc
9
9
10
- from core .gui import appconfig , themes
10
+ from core .gui import appconfig , images
11
+ from core .gui import nodeutils as nutils
12
+ from core .gui import themes
11
13
from core .gui .appconfig import GuiConfig
12
14
from core .gui .coreclient import CoreClient
13
15
from core .gui .dialogs .error import ErrorDialog
14
16
from core .gui .frames .base import InfoFrameBase
15
17
from core .gui .frames .default import DefaultInfoFrame
16
- from core .gui .graph .graph import CanvasGraph
17
- from core .gui .images import ImageEnum , Images
18
+ from core .gui .graph .manager import CanvasManager
19
+ from core .gui .images import ImageEnum
18
20
from core .gui .menubar import Menubar
19
- from core .gui .nodeutils import NodeUtils
20
21
from core .gui .statusbar import StatusBar
21
22
from core .gui .themes import PADY
22
23
from core .gui .toolbar import Toolbar
@@ -29,13 +30,13 @@ class Application(ttk.Frame):
29
30
def __init__ (self , proxy : bool , session_id : int = None ) -> None :
30
31
super ().__init__ ()
31
32
# load node icons
32
- NodeUtils .setup ()
33
+ nutils .setup ()
33
34
34
35
# widgets
35
36
self .menubar : Optional [Menubar ] = None
36
37
self .toolbar : Optional [Toolbar ] = None
37
38
self .right_frame : Optional [ttk .Frame ] = None
38
- self .canvas : Optional [CanvasGraph ] = None
39
+ self .manager : Optional [CanvasManager ] = None
39
40
self .statusbar : Optional [StatusBar ] = None
40
41
self .progress : Optional [Progressbar ] = None
41
42
self .infobar : Optional [ttk .Frame ] = None
@@ -77,7 +78,7 @@ def setup_app(self) -> None:
77
78
self .master .title ("CORE" )
78
79
self .center ()
79
80
self .master .protocol ("WM_DELETE_WINDOW" , self .on_closing )
80
- image = Images . get (ImageEnum .CORE , 16 )
81
+ image = images . from_enum (ImageEnum .CORE , width = images . DIALOG_SIZE )
81
82
self .master .tk .call ("wm" , "iconphoto" , self .master ._w , image )
82
83
self .master .option_add ("*tearOff" , tk .FALSE )
83
84
self .setup_file_dialogs ()
@@ -136,20 +137,8 @@ def draw_infobar(self) -> None:
136
137
label .grid (sticky = tk .EW , pady = PADY )
137
138
138
139
def draw_canvas (self ) -> None :
139
- canvas_frame = ttk .Frame (self .right_frame )
140
- canvas_frame .rowconfigure (0 , weight = 1 )
141
- canvas_frame .columnconfigure (0 , weight = 1 )
142
- canvas_frame .grid (row = 0 , column = 0 , sticky = tk .NSEW , pady = 1 )
143
- self .canvas = CanvasGraph (canvas_frame , self , self .core )
144
- self .canvas .grid (sticky = tk .NSEW )
145
- scroll_y = ttk .Scrollbar (canvas_frame , command = self .canvas .yview )
146
- scroll_y .grid (row = 0 , column = 1 , sticky = tk .NS )
147
- scroll_x = ttk .Scrollbar (
148
- canvas_frame , orient = tk .HORIZONTAL , command = self .canvas .xview
149
- )
150
- scroll_x .grid (row = 1 , column = 0 , sticky = tk .EW )
151
- self .canvas .configure (xscrollcommand = scroll_x .set )
152
- self .canvas .configure (yscrollcommand = scroll_y .set )
140
+ self .manager = CanvasManager (self .right_frame , self , self .core )
141
+ self .manager .notebook .grid (sticky = tk .NSEW )
153
142
154
143
def draw_status (self ) -> None :
155
144
self .statusbar = StatusBar (self .right_frame , self )
@@ -179,17 +168,30 @@ def show_info(self) -> None:
179
168
def hide_info (self ) -> None :
180
169
self .infobar .grid_forget ()
181
170
182
- def show_grpc_exception (self , title : str , e : grpc .RpcError ) -> None :
171
+ def show_grpc_exception (
172
+ self , message : str , e : grpc .RpcError , blocking : bool = False
173
+ ) -> None :
183
174
logging .exception ("app grpc exception" , exc_info = e )
184
- message = e .details ()
185
- self .show_error (title , message )
175
+ dialog = ErrorDialog (self , "GRPC Exception" , message , e .details ())
176
+ if blocking :
177
+ dialog .show ()
178
+ else :
179
+ self .after (0 , lambda : dialog .show ())
186
180
187
- def show_exception (self , title : str , e : Exception ) -> None :
181
+ def show_exception (self , message : str , e : Exception ) -> None :
188
182
logging .exception ("app exception" , exc_info = e )
189
- self .show_error (title , str (e ))
183
+ self .after (
184
+ 0 , lambda : ErrorDialog (self , "App Exception" , message , str (e )).show ()
185
+ )
190
186
191
- def show_error (self , title : str , message : str ) -> None :
192
- self .after (0 , lambda : ErrorDialog (self , title , message ).show ())
187
+ def show_exception_data (self , title : str , message : str , details : str ) -> None :
188
+ self .after (0 , lambda : ErrorDialog (self , title , message , details ).show ())
189
+
190
+ def show_error (self , title : str , message : str , blocking : bool = False ) -> None :
191
+ if blocking :
192
+ messagebox .showerror (title , message , parent = self )
193
+ else :
194
+ self .after (0 , lambda : messagebox .showerror (title , message , parent = self ))
193
195
194
196
def on_closing (self ) -> None :
195
197
if self .toolbar .picker :
@@ -201,15 +203,17 @@ def save_config(self) -> None:
201
203
202
204
def joined_session_update (self ) -> None :
203
205
if self .core .is_runtime ():
206
+ self .menubar .set_state (is_runtime = True )
204
207
self .toolbar .set_runtime ()
205
208
else :
209
+ self .menubar .set_state (is_runtime = False )
206
210
self .toolbar .set_design ()
207
211
208
- def get_icon (self , image_enum : ImageEnum , width : int ) -> PhotoImage :
209
- return Images . get (image_enum , int ( width * self .app_scale ) )
212
+ def get_enum_icon (self , image_enum : ImageEnum , * , width : int ) -> PhotoImage :
213
+ return images . from_enum (image_enum , width = width , scale = self .app_scale )
210
214
211
- def get_custom_icon (self , image_file : str , width : int ) -> PhotoImage :
212
- return Images . get_custom ( image_file , int ( width * self .app_scale ) )
215
+ def get_file_icon (self , file_path : str , * , width : int ) -> PhotoImage :
216
+ return images . from_file ( file_path , width = width , scale = self .app_scale )
213
217
214
218
def close (self ) -> None :
215
219
self .master .destroy ()
0 commit comments