updates clean up setting wallpaper for graph canvas, updates to read metadata for canvas to display wallpaper from loaded xml file, update to allow reopening mobility player from node context

This commit is contained in:
Blake Harnden 2019-12-04 13:40:35 -08:00
parent 41a9b88189
commit 5a387537bb
5 changed files with 94 additions and 36 deletions

View file

@ -1,12 +1,14 @@
""" """
Incorporate grpc into python tkinter GUI Incorporate grpc into python tkinter GUI
""" """
import json
import logging import logging
import os import os
import time import time
from core.api.grpc import client, core_pb2 from core.api.grpc import client, core_pb2
from coretk.dialogs.mobilityplayer import MobilityPlayerDialog from coretk import appconfig
from coretk.dialogs.mobilityplayer import MobilityPlayer
from coretk.dialogs.sessions import SessionsDialog from coretk.dialogs.sessions import SessionsDialog
from coretk.interface import InterfaceManager from coretk.interface import InterfaceManager
from coretk.nodeutils import NodeDraw, NodeUtils from coretk.nodeutils import NodeDraw, NodeUtils
@ -141,6 +143,8 @@ class CoreClient:
logging.warning("unknown session event: %s", session_event) logging.warning("unknown session event: %s", session_event)
elif event.HasField("node_event"): elif event.HasField("node_event"):
self.handle_node_event(event.node_event) self.handle_node_event(event.node_event)
elif event.HasField("config_event"):
logging.info("config event: %s", event)
else: else:
logging.info("unhandled event: %s", event) logging.info("unhandled event: %s", event)
@ -164,7 +168,7 @@ class CoreClient:
x = event.node.position.x x = event.node.position.x
y = event.node.position.y y = event.node.position.y
canvas_node = self.canvas_nodes[node_id] canvas_node = self.canvas_nodes[node_id]
canvas_node.move(x, y) canvas_node.move(x, y, update=False)
def handle_throughputs(self, event): def handle_throughputs(self, event):
interface_throughputs = event.interface_throughputs interface_throughputs = event.interface_throughputs
@ -189,7 +193,6 @@ class CoreClient:
# get session data # get session data
response = self.client.get_session(self.session_id) response = self.client.get_session(self.session_id)
logging.info("joining session(%s): %s", self.session_id, response)
session = response.session session = response.session
self.state = session.state self.state = session.state
self.client.events(self.session_id, self.handle_events) self.client.events(self.session_id, self.handle_events)
@ -235,9 +238,6 @@ class CoreClient:
node_id = int(_id / 1000) node_id = int(_id / 1000)
self.set_emane_model_config(node_id, config.model, config.config, interface) self.set_emane_model_config(node_id, config.model, config.config, interface)
# draw session
self.app.canvas.reset_and_redraw(session)
# get node service config and file config # get node service config and file config
for node in session.nodes: for node in session.nodes:
self.created_nodes.add(node.id) self.created_nodes.add(node.id)
@ -262,6 +262,13 @@ class CoreClient:
self.file_configs[node.id][service] = {} self.file_configs[node.id][service] = {}
self.file_configs[node.id][service][file] = response.data self.file_configs[node.id][service][file] = response.data
# draw session
self.app.canvas.reset_and_redraw(session)
# get metadata
response = self.client.get_session_metadata(self.session_id)
self.parse_metadata(response.config)
if self.is_runtime(): if self.is_runtime():
self.app.toolbar.runtime_frame.tkraise() self.app.toolbar.runtime_frame.tkraise()
else: else:
@ -271,6 +278,18 @@ class CoreClient:
def is_runtime(self): def is_runtime(self):
return self.state == core_pb2.SessionState.RUNTIME return self.state == core_pb2.SessionState.RUNTIME
def parse_metadata(self, config):
# canvas settings
canvas_config = config.get("canvas")
if canvas_config:
logging.info("canvas metadata: %s", canvas_config)
canvas_config = json.loads(canvas_config)
wallpaper_style = canvas_config["wallpaper-style"]
self.app.canvas.scale_option.set(wallpaper_style)
wallpaper = canvas_config["wallpaper"]
wallpaper = str(appconfig.BACKGROUNDS_PATH.joinpath(wallpaper))
self.app.canvas.set_wallpaper(wallpaper)
def create_new_session(self): def create_new_session(self):
""" """
Create a new session Create a new session
@ -372,9 +391,9 @@ class CoreClient:
# display mobility players # display mobility players
for node_id, config in self.mobility_configs.items(): for node_id, config in self.mobility_configs.items():
canvas_node = self.canvas_nodes[node_id] canvas_node = self.canvas_nodes[node_id]
dialog = MobilityPlayerDialog(self.app, self.app, canvas_node, config) mobility_player = MobilityPlayer(self.app, self.app, canvas_node, config)
dialog.show() mobility_player.show()
self.mobility_players[node_id] = dialog self.mobility_players[node_id] = mobility_player
def stop_session(self, session_id=None): def stop_session(self, session_id=None):
if not session_id: if not session_id:

View file

@ -269,7 +269,7 @@ router ospf6
<configuration name="annotation a0" value="{iconcoords {612.0 492.0}} {type text} {label {wireless network}} {labelcolor black} {fontfamily {Arial}} {fontsize {12}} {effects {bold}} {canvas c1}"/> <configuration name="annotation a0" value="{iconcoords {612.0 492.0}} {type text} {label {wireless network}} {labelcolor black} {fontfamily {Arial}} {fontsize {12}} {effects {bold}} {canvas c1}"/>
<configuration name="annotation a1" value="{iconcoords {142.0 112.0 393.0 291.0}} {type rectangle} {label {}} {labelcolor black} {fontfamily {Arial}} {fontsize {12}} {color #ebebde} {width 1} {border #ffffff} {rad 25} {canvas c1}"/> <configuration name="annotation a1" value="{iconcoords {142.0 112.0 393.0 291.0}} {type rectangle} {label {}} {labelcolor black} {fontfamily {Arial}} {fontsize {12}} {color #ebebde} {width 1} {border #ffffff} {rad 25} {canvas c1}"/>
<configuration name="annotation a2" value="{iconcoords {492.0 384.0}} {type text} {label {gateway}} {labelcolor black} {fontfamily {Arial}} {fontsize {12}} {effects {bold}} {canvas c1}"/> <configuration name="annotation a2" value="{iconcoords {492.0 384.0}} {type text} {label {gateway}} {labelcolor black} {fontfamily {Arial}} {fontsize {12}} {effects {bold}} {canvas c1}"/>
<configuration name="canvas c1" value="{name {Canvas1}} {wallpaper-style {upperleft}} {wallpaper {sample1-bg.gif}}"/> <configuration name="canvas" value='{"name": "Canvas1", "wallpaper-style": 1, "wallpaper": "sample1-bg.gif"}'/>
<configuration name="global_options" value="interface_names=no ip_addresses=yes ipv6_addresses=no node_labels=yes link_labels=yes show_api=no background_images=no annotations=yes grid=no traffic_start=0"/> <configuration name="global_options" value="interface_names=no ip_addresses=yes ipv6_addresses=no node_labels=yes link_labels=yes show_api=no background_images=no annotations=yes grid=no traffic_start=0"/>
</session_metadata> </session_metadata>
<default_services> <default_services>

View file

@ -5,14 +5,11 @@ import logging
import tkinter as tk import tkinter as tk
from tkinter import filedialog, ttk from tkinter import filedialog, ttk
from PIL import Image
from coretk.appconfig import BACKGROUNDS_PATH from coretk.appconfig import BACKGROUNDS_PATH
from coretk.dialogs.dialog import Dialog from coretk.dialogs.dialog import Dialog
from coretk.images import Images from coretk.images import Images
PADX = 5 PADX = 5
ABOVE_WALLPAPER = ["edge", "linkinfo", "wireless", "antenna", "nodename", "node"]
class CanvasBackgroundDialog(Dialog): class CanvasBackgroundDialog(Dialog):
@ -178,23 +175,11 @@ class CanvasBackgroundDialog(Dialog):
filename = self.filename.get() filename = self.filename.get()
if not filename: if not filename:
self.canvas.delete(self.canvas.wallpaper_id) filename = None
self.canvas.wallpaper = None
self.canvas.wallpaper_file = None
self.destroy()
return
try:
img = Image.open(filename)
self.canvas.wallpaper = img
self.canvas.wallpaper_file = filename
self.canvas.redraw()
for component in ABOVE_WALLPAPER:
self.canvas.tag_raise(component)
try:
self.canvas.set_wallpaper(filename)
except FileNotFoundError: except FileNotFoundError:
logging.error("invalid background: %s", filename) logging.error("invalid background: %s", filename)
if self.canvas.wallpaper_id:
self.canvas.delete(self.canvas.wallpaper_id)
self.canvas.wallpaper_id = None
self.canvas.wallpaper_file = None
self.destroy() self.destroy()

View file

@ -1,7 +1,7 @@
import tkinter as tk import tkinter as tk
from tkinter import ttk from tkinter import ttk
from core.api.grpc import core_pb2 from core.api.grpc.core_pb2 import MobilityAction
from coretk.dialogs.dialog import Dialog from coretk.dialogs.dialog import Dialog
from coretk.images import ImageEnum, Images from coretk.images import ImageEnum, Images
@ -9,6 +9,42 @@ PAD = 5
ICON_SIZE = 16 ICON_SIZE = 16
class MobilityPlayer:
def __init__(self, master, app, canvas_node, config):
self.master = master
self.app = app
self.canvas_node = canvas_node
self.config = config
self.dialog = None
self.state = None
def show(self):
if self.dialog:
self.dialog.destroy()
self.dialog = MobilityPlayerDialog(
self.master, self.app, self.canvas_node, self.config
)
if self.state == MobilityAction.START:
self.set_play()
elif self.state == MobilityAction.PAUSE:
self.set_pause()
else:
self.set_stop()
self.dialog.show()
def set_play(self):
self.dialog.set_play()
self.state = MobilityAction.START
def set_pause(self):
self.dialog.set_pause()
self.state = MobilityAction.PAUSE
def set_stop(self):
self.dialog.set_stop()
self.state = MobilityAction.STOP
class MobilityPlayerDialog(Dialog): class MobilityPlayerDialog(Dialog):
def __init__(self, master, app, canvas_node, config): def __init__(self, master, app, canvas_node, config):
super().__init__( super().__init__(
@ -88,19 +124,19 @@ class MobilityPlayerDialog(Dialog):
self.set_play() self.set_play()
session_id = self.app.core.session_id session_id = self.app.core.session_id
self.app.core.client.mobility_action( self.app.core.client.mobility_action(
session_id, self.node.id, core_pb2.MobilityAction.START session_id, self.node.id, MobilityAction.START
) )
def click_pause(self): def click_pause(self):
self.set_pause() self.set_pause()
session_id = self.app.core.session_id session_id = self.app.core.session_id
self.app.core.client.mobility_action( self.app.core.client.mobility_action(
session_id, self.node.id, core_pb2.MobilityAction.PAUSE session_id, self.node.id, MobilityAction.PAUSE
) )
def click_stop(self): def click_stop(self):
self.set_stop() self.set_stop()
session_id = self.app.core.session_id session_id = self.app.core.session_id
self.app.core.client.mobility_action( self.app.core.client.mobility_action(
session_id, self.node.id, core_pb2.MobilityAction.STOP session_id, self.node.id, MobilityAction.STOP
) )

View file

@ -3,7 +3,7 @@ import logging
import tkinter as tk import tkinter as tk
from tkinter import font from tkinter import font
from PIL import ImageTk from PIL import Image, ImageTk
from core.api.grpc import core_pb2 from core.api.grpc import core_pb2
from core.api.grpc.core_pb2 import NodeType from core.api.grpc.core_pb2 import NodeType
@ -21,6 +21,7 @@ from coretk.nodeutils import NodeUtils
from coretk.shape import Shape from coretk.shape import Shape
NODE_TEXT_OFFSET = 5 NODE_TEXT_OFFSET = 5
ABOVE_WALLPAPER = ["edge", "linkinfo", "wireless", "antenna", "nodename", "node"]
class GraphMode(enum.Enum): class GraphMode(enum.Enum):
@ -583,6 +584,21 @@ class CanvasGraph(tk.Canvas):
else: else:
self.itemconfig("gridline", state=tk.HIDDEN) self.itemconfig("gridline", state=tk.HIDDEN)
def set_wallpaper(self, filename):
logging.info("setting wallpaper: %s", filename)
if filename is not None:
img = Image.open(filename)
self.wallpaper = img
self.wallpaper_file = filename
self.redraw()
for component in ABOVE_WALLPAPER:
self.tag_raise(component)
else:
if self.wallpaper_id is not None:
self.delete(self.wallpaper_id)
self.wallpaper = None
self.wallpaper_file = None
def is_selection_mode(self): def is_selection_mode(self):
return self.mode == GraphMode.SELECT return self.mode == GraphMode.SELECT
@ -696,7 +712,7 @@ class CanvasNode:
self.canvas.itemconfig(self.id, image=self.image) self.canvas.itemconfig(self.id, image=self.image)
self.canvas.itemconfig(self.text_id, text=self.core_node.name) self.canvas.itemconfig(self.text_id, text=self.core_node.name)
def move(self, x, y): def move(self, x, y, update=True):
old_x = self.core_node.position.x old_x = self.core_node.position.x
old_y = self.core_node.position.y old_y = self.core_node.position.y
x_offset = x - old_x x_offset = x - old_x
@ -720,7 +736,7 @@ class CanvasNode:
self.canvas.coords(edge.id, x, y, x2, y2) self.canvas.coords(edge.id, x, y, x2, y2)
else: else:
self.canvas.coords(edge.id, x1, y1, x, y) self.canvas.coords(edge.id, x1, y1, x, y)
if self.app.core.is_runtime(): if self.app.core.is_runtime() and update:
self.app.core.edit_node(self.core_node.id, int(x), int(y)) self.app.core.edit_node(self.core_node.id, int(x), int(y))
def on_enter(self, event): def on_enter(self, event):
@ -784,6 +800,8 @@ class CanvasNode:
def show_mobility_player(self): def show_mobility_player(self):
self.canvas.context = None self.canvas.context = None
mobility_player = self.app.core.mobility_players[self.core_node.id]
mobility_player.show()
def show_emane_config(self): def show_emane_config(self):
self.canvas.context = None self.canvas.context = None