From 5a387537bb9f57d99b211379509694bdf8da4e90 Mon Sep 17 00:00:00 2001 From: Blake Harnden <32446120+bharnden@users.noreply.github.com> Date: Wed, 4 Dec 2019 13:40:35 -0800 Subject: [PATCH] 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 --- coretk/coretk/coreclient.py | 37 ++++++++++++++----- coretk/coretk/data/xmls/sample1.xml | 2 +- coretk/coretk/dialogs/canvasbackground.py | 23 +++--------- coretk/coretk/dialogs/mobilityplayer.py | 44 ++++++++++++++++++++--- coretk/coretk/graph.py | 24 +++++++++++-- 5 files changed, 94 insertions(+), 36 deletions(-) diff --git a/coretk/coretk/coreclient.py b/coretk/coretk/coreclient.py index fec00a73..ef617ac0 100644 --- a/coretk/coretk/coreclient.py +++ b/coretk/coretk/coreclient.py @@ -1,12 +1,14 @@ """ Incorporate grpc into python tkinter GUI """ +import json import logging import os import time 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.interface import InterfaceManager from coretk.nodeutils import NodeDraw, NodeUtils @@ -141,6 +143,8 @@ class CoreClient: logging.warning("unknown session event: %s", session_event) elif event.HasField("node_event"): self.handle_node_event(event.node_event) + elif event.HasField("config_event"): + logging.info("config event: %s", event) else: logging.info("unhandled event: %s", event) @@ -164,7 +168,7 @@ class CoreClient: x = event.node.position.x y = event.node.position.y canvas_node = self.canvas_nodes[node_id] - canvas_node.move(x, y) + canvas_node.move(x, y, update=False) def handle_throughputs(self, event): interface_throughputs = event.interface_throughputs @@ -189,7 +193,6 @@ class CoreClient: # get session data response = self.client.get_session(self.session_id) - logging.info("joining session(%s): %s", self.session_id, response) session = response.session self.state = session.state self.client.events(self.session_id, self.handle_events) @@ -235,9 +238,6 @@ class CoreClient: node_id = int(_id / 1000) 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 for node in session.nodes: self.created_nodes.add(node.id) @@ -262,6 +262,13 @@ class CoreClient: self.file_configs[node.id][service] = {} 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(): self.app.toolbar.runtime_frame.tkraise() else: @@ -271,6 +278,18 @@ class CoreClient: def is_runtime(self): 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): """ Create a new session @@ -372,9 +391,9 @@ class CoreClient: # display mobility players for node_id, config in self.mobility_configs.items(): canvas_node = self.canvas_nodes[node_id] - dialog = MobilityPlayerDialog(self.app, self.app, canvas_node, config) - dialog.show() - self.mobility_players[node_id] = dialog + mobility_player = MobilityPlayer(self.app, self.app, canvas_node, config) + mobility_player.show() + self.mobility_players[node_id] = mobility_player def stop_session(self, session_id=None): if not session_id: diff --git a/coretk/coretk/data/xmls/sample1.xml b/coretk/coretk/data/xmls/sample1.xml index 8bda5b8c..7c8ccf72 100644 --- a/coretk/coretk/data/xmls/sample1.xml +++ b/coretk/coretk/data/xmls/sample1.xml @@ -269,7 +269,7 @@ router ospf6 - + diff --git a/coretk/coretk/dialogs/canvasbackground.py b/coretk/coretk/dialogs/canvasbackground.py index 84b0bdb6..844b5595 100644 --- a/coretk/coretk/dialogs/canvasbackground.py +++ b/coretk/coretk/dialogs/canvasbackground.py @@ -5,14 +5,11 @@ import logging import tkinter as tk from tkinter import filedialog, ttk -from PIL import Image - from coretk.appconfig import BACKGROUNDS_PATH from coretk.dialogs.dialog import Dialog from coretk.images import Images PADX = 5 -ABOVE_WALLPAPER = ["edge", "linkinfo", "wireless", "antenna", "nodename", "node"] class CanvasBackgroundDialog(Dialog): @@ -178,23 +175,11 @@ class CanvasBackgroundDialog(Dialog): filename = self.filename.get() if not filename: - self.canvas.delete(self.canvas.wallpaper_id) - 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) + filename = None + try: + self.canvas.set_wallpaper(filename) except FileNotFoundError: 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() diff --git a/coretk/coretk/dialogs/mobilityplayer.py b/coretk/coretk/dialogs/mobilityplayer.py index 65b16058..136e6179 100644 --- a/coretk/coretk/dialogs/mobilityplayer.py +++ b/coretk/coretk/dialogs/mobilityplayer.py @@ -1,7 +1,7 @@ import tkinter as tk 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.images import ImageEnum, Images @@ -9,6 +9,42 @@ PAD = 5 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): def __init__(self, master, app, canvas_node, config): super().__init__( @@ -88,19 +124,19 @@ class MobilityPlayerDialog(Dialog): self.set_play() session_id = self.app.core.session_id 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): self.set_pause() session_id = self.app.core.session_id 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): self.set_stop() session_id = self.app.core.session_id self.app.core.client.mobility_action( - session_id, self.node.id, core_pb2.MobilityAction.STOP + session_id, self.node.id, MobilityAction.STOP ) diff --git a/coretk/coretk/graph.py b/coretk/coretk/graph.py index 7389be52..7ef341a3 100644 --- a/coretk/coretk/graph.py +++ b/coretk/coretk/graph.py @@ -3,7 +3,7 @@ import logging import tkinter as tk from tkinter import font -from PIL import ImageTk +from PIL import Image, ImageTk from core.api.grpc import core_pb2 from core.api.grpc.core_pb2 import NodeType @@ -21,6 +21,7 @@ from coretk.nodeutils import NodeUtils from coretk.shape import Shape NODE_TEXT_OFFSET = 5 +ABOVE_WALLPAPER = ["edge", "linkinfo", "wireless", "antenna", "nodename", "node"] class GraphMode(enum.Enum): @@ -583,6 +584,21 @@ class CanvasGraph(tk.Canvas): else: 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): return self.mode == GraphMode.SELECT @@ -696,7 +712,7 @@ class CanvasNode: self.canvas.itemconfig(self.id, image=self.image) 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_y = self.core_node.position.y x_offset = x - old_x @@ -720,7 +736,7 @@ class CanvasNode: self.canvas.coords(edge.id, x, y, x2, y2) else: 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)) def on_enter(self, event): @@ -784,6 +800,8 @@ class CanvasNode: def show_mobility_player(self): self.canvas.context = None + mobility_player = self.app.core.mobility_players[self.core_node.id] + mobility_player.show() def show_emane_config(self): self.canvas.context = None