Commit 1afafa6b authored by Guillaume Sabbagh's avatar Guillaume Sabbagh
Browse files
parents d589263b d0d45491
......@@ -131,7 +131,6 @@ class Model:
"""
def exporterGraphviz(self, uids):
data=self.getObject(uids)
with ThreadPoolExecutor(max_workers=len(data)) as executor:
for index, row in data.iterrows():
obj=row["object"]
......@@ -153,8 +152,7 @@ class Description:
return self._str
def generer(self):
mo=ModelObjects.get(self._obj)
if mo==ModelObjects.GC:
if issubclass(type(self._obj), Categorie):
return self._genererDescriptionCategorie()
else:
return str(self._obj)
......@@ -165,15 +163,15 @@ class Description:
`limite_fleches` est le nombre maximal de flèches entre deux objets qu'on s'autorise à afficher.
"""
descr=""
if self._obj.nom:
descr+=self._obj.nom
# objets
descr+=" {"
print(self)
for o in self._obj.objets:
descr+=str(o)+","
descr=descr[:-1]+"}"
if(len(self._obj.objets)>0):
descr=descr[:-1]+"}"
else:
descr+="}"
# flesches
fleches_elem = set(self._obj[self._obj.objets,self._obj.objets])
......@@ -211,11 +209,18 @@ class Description:
if WARNING_LIMITE_FLECHES_ATTEINTE:
print("Warning : limite fleches entre "+str(source)+" et "+str(cible)+" atteinte.")
break
descr+=" flèches: "
descr+=" {"
flag=False
for f in fleches_non_elementaires:
descr+=f
descr+=f+","
flag=True
for f in fleches_elementaires:
descr+=f
descr+=f+","
flag=True
if flag:
descr=descr[:-1]+"}"
else:
descr+="}"
return descr
......
......@@ -4,20 +4,35 @@
class Parameters():
"""
///////////////////// TK
"""
# Frames
FRAME_BD=2
# Section frame
SECTION_COLOR = "#649BB4"
SECTION_RELIEF="groove"
SECTION_FONT_SIZE = 10
SECTION_FONT_WEIGHT = 'bold'
SECTION_FONT_UNDERLINE= 0
FRAME_BD=2
# Inform frame
INFORM_BG='#C0C0C0'
INFORM_FG='black'
# Export frame
ExportAsDialog_BG='white'
HIGHLIGHTCOLOR_BUTTON="#649BB4"
"""
///////////////////// NetworkX
"""
# Graph
NODE_COLOR='#000000'
EDGE_ELEMENTARY_COLOR='#000000'
EDGE_NO_ELEMENTARY_COLOR='#0033FF'
parameters=Parameters()
......@@ -3,9 +3,9 @@
from tkinter import Tk, YES, BOTH
from tko.TkOglWin import TkOglWin
from ogl.TkOglWin import TkOglWin
from oglWrap.ogl_hdr import GL_BLEND, GL_COLOR_BUFFER_BIT, GL_DEPTH_BUFFER_BIT, GL_DEPTH_TEST, \
from ogl.oglWrap.ogl_hdr import GL_BLEND, GL_COLOR_BUFFER_BIT, GL_DEPTH_BUFFER_BIT, GL_DEPTH_TEST, \
GL_MODELVIEW, GL_ONE_MINUS_SRC_ALPHA, GL_PROJECTION, GL_QUADS, GL_RENDERER, \
GL_SRC_ALPHA, GL_VENDOR, GL_VERSION, \
glBegin, glClear, glBlendFunc, glClearColor, \
......
/* in MainWindow */
from ogl.AppOgl import AppOgl
_glFrame=None
...
def _initFrames(self):
...
# OGL frame
self._glFrame=Frame(self._frame)
self._glFrame.grid(row=0, column=0, sticky="nesw")
self.initGLApp()
...
def initGLApp(self):
self._glApp=AppOgl(self._glFrame, width=320, height=200)
self._glApp.pack(expand = YES, fill=BOTH)
\ No newline at end of file
......@@ -10,14 +10,14 @@ from tkinter import Frame
import sys
if sys.platform.startswith('win32'):
from oglWrap.win32_gdi import PFD_DRAW_TO_WINDOW, PFD_SUPPORT_OPENGL, PFD_DOUBLEBUFFER, PFD_TYPE_RGBA, \
from ogl.oglWrap.win32_gdi import PFD_DRAW_TO_WINDOW, PFD_SUPPORT_OPENGL, PFD_DOUBLEBUFFER, PFD_TYPE_RGBA, \
PixelFormatDescriptor, get_dc, choose_pixel_format, set_pixel_format, \
get_pixel_format, swap_buffers
from oglWrap.ogl_hdr import wglCreateContext, wglMakeCurrent
from ogl.oglWrap.ogl_hdr import wglCreateContext, wglMakeCurrent
elif sys.platform.startswith('linux'):
from oglWrap.x11_gdi import X11_None, x_open_display
from oglWrap.ogl_hdr import PGLint, GLX_RGBA, GLX_DEPTH_SIZE, GLX_DOUBLEBUFFER, GL_TRUE, \
from ogl.oglWrap.x11_gdi import X11_None, x_open_display
from ogl.oglWrap.ogl_hdr import PGLint, GLX_RGBA, GLX_DEPTH_SIZE, GLX_DOUBLEBUFFER, GL_TRUE, \
GLX_BLUE_SIZE, GLX_GREEN_SIZE, GLX_RED_SIZE, \
glXChooseVisual, glXCreateContext, glXMakeCurrent, glXSwapBuffers
......
"""entry point for Tkinter Window with OpenGL]
"""
from itertools import product
from tkinter import TOP, X, YES, BOTH, \
Frame, Label
from Categorie import Categorie
from tk.Factory import *
from Parameters import parameters
import matplotlib.pyplot as plt
import matplotlib
matplotlib.use("TkAgg")
from matplotlib.figure import Figure
from matplotlib.backends.backend_tkagg import (FigureCanvasTkAgg, NavigationToolbar2Tk)
import networkx as nx
class PlotFrame(Frame):
_controller=None
_plot=None
_canvas=None
def __init__(self, parent, controller, *args, **kwargs):
assert controller
Frame.__init__(self, parent, *args, **kwargs)
self._controller=controller
self.columnconfigure(0, weight=1, minsize=200)
self.rowconfigure(0, minsize=20)
self.rowconfigure(1, weight=1, minsize=100)
self._initFrame()
def _initFrame(self):
factory.buildSectionLabel(self,"Visualisation NetworkX").grid(row=0, column=0, sticky="nwe")
G = nx.fast_gnp_random_graph(n=10, p=0.5,directed=True)
# draw
f = Figure(figsize=(5,5), dpi=100)
self._plot=f.add_subplot(111)
self._plot.cla()
nx.draw_networkx(G, ax=self._plot, pos=nx.random_layout(G), node_color='r', edge_color='b')
self._canvas = FigureCanvasTkAgg(f, master=self)
self._canvas.draw()
toolbar = NavigationToolbar2Tk(self._canvas, self, pack_toolbar=False)
toolbar.update()
toolbar.grid(row=2, column=0, sticky="nswe")
self._canvas.get_tk_widget().grid(row=1, column=0, sticky="nswe")
def setGraph(self, graph:nx.Graph):
self._plot.cla()
if callable(getattr(graph,"check_planarity",None)) and graph.check_planarity()[0]:
nx.draw_networkx(graph, ax=self._plot, pos=nx.planar_layout(graph))
else:
nx.draw_networkx(graph, ax=self._plot, pos=nx.random_layout(graph))
self._canvas.draw()
class GraphGenerator:
"""
Static
Construit le nx.Graph associé à un objet par la fonction 'give(object)'
"""
def give(obj) -> nx.Graph:
if issubclass(type(obj), Categorie):
return GraphGenerator._genererGrapheCategorie(obj)
else:
print(f"Impossible de générer le graphe de l'objet: {obj}")
"""
GENERATEURS PAR CLASSE
"""
def _genererGrapheCategorie(cat,
afficher_identites:bool = True,
complet:bool = True,
limite_fleches:int = 30)-> nx.Graph:
"""
@param complet: - si True affiche toutes les flèches;
- si False affiche seulement les flèches élémentaires.
@param limite_fleches: nombre maximal de flèches entre deux objets.
"""
G = nx.MultiDiGraph()
G.add_nodes_from(cat.objets, color=parameters.NODE_COLOR)
#pos = nx.spring_layout(G)
# flesches
fleches_elem = set(cat[cat.objets,cat.objets])
if complet:
func = lambda x,y : cat({x},{y})
else:
func = lambda x,y : cat[{x},{y}]
for source,cible in product(cat.objets,repeat=2):
nb_fleches = 0
for fleche in func(source,cible):
if afficher_identites or not fleche.is_identite:
if fleche.source not in cat.objets:
raise Exception("Source d'une fleche pas dans les objets de la categorie.")
if fleche.cible not in cat.objets:
raise Exception("Source d'une fleche pas dans les objets de la categorie.")
if len({obj for obj in cat.objets if obj == fleche.source}) > 1:
raise Exception("Plus d'un objet de la catégorie est source de la fleche.")
if len({obj for obj in cat.objets if obj == fleche.cible}) > 1:
raise Exception("Plus d'un objet de la catégorie est cible de la fleche.")
#permet d'avoir toujours un objet de la catégorie comme source
source = {obj for obj in cat.objets if obj == fleche.source}.pop()
#permet d'avoir toujours un objet de la catégorie comme cible
cible = {obj for obj in cat.objets if obj == fleche.cible}.pop()
# descriptions
if fleche in fleches_elem:
G.add_edge(str(source),str(cible),
color=parameters.EDGE_ELEMENTARY_COLOR,
label=str(fleche))
else:
G.add_edge(str(source),str(cible),
color=parameters.EDGE_NO_ELEMENTARY_COLOR,
label=str(fleche))
nb_fleches += 1
if nb_fleches > limite_fleches:
if WARNING_LIMITE_FLECHES_ATTEINTE:
print("Warning : limite fleches entre "+str(source)+" et "+str(cible)+" atteinte.")
break
return G
\ No newline at end of file
......@@ -4,9 +4,9 @@ from tkinter import TOP, YES, BOTH, X, \
filedialog, messagebox
from Parameters import parameters
from tko.AppOgl import AppOgl
from tk.OutilsFrame import OutilsFrame
from tk.ObjetsFrame import ObjetsFrame
from plot.PlotFrame import PlotFrame
class MainWindow:
......@@ -16,9 +16,10 @@ class MainWindow:
def getRoot(self): return self._root
_frame=None
_glFrame=None
_plotFrame=None
_outFrame=None
_objFrame=None
def getPlotFrame(self): return self._plotFrame
_glApp=None
_menu=None
......@@ -46,11 +47,6 @@ class MainWindow:
self._root.config(bg = "#787878")
def _initFrames(self):
# main frame
#test
#b=Button(self._root, text="test", command=lambda:self._controller.test(self._root))
#b.pack(fill=X)
# Frame
self._frame = Frame(self._root)
self._frame.pack(expand=YES, fill=BOTH)
......@@ -59,24 +55,19 @@ class MainWindow:
self._frame.columnconfigure(2, weight=2, minsize=200)
self._frame.rowconfigure(0, weight=1, minsize=300)
# OGL frame
self._glFrame=Frame(self._frame)
self._glFrame.grid(row=0, column=0, sticky="nesw")
self.initGLApp()
# Plot frame
self._plotFrame=PlotFrame(self._frame, self._controller)
self._plotFrame.grid(row=0, column=0, sticky="nesw")
# Outils frame
self._outFrame = OutilsFrame(self._frame, self._controller)
self._outFrame.grid(row=0, column=1, sticky="nesw")
# Objets frame
self._objFrame = ObjetsFrame(self._frame, self._controller)
self._objFrame = ObjetsFrame(self._frame, self._controller, self)
self._objFrame.grid(row=0, column=2, sticky="nesw")
def initGLApp(self):
self._glApp=AppOgl(self._glFrame, width=320, height=200)
self._glApp.pack(expand = YES, fill=BOTH)
def _initMenu(self):
self._menu=Menu()
......@@ -137,7 +128,31 @@ class MainWindow:
uids=self._objFrame.getSelectedObjects()
self._controller.getModel().exporterGraphviz(uids)
def exportObjectsGraphviz(self, uids):
print(f"ddz{uids}")
self._controller.getModel().exporterGraphviz(uids)
"""
EXPORTS DIALOG CLASS
"""
class ExportAsDialog(Toplevel):
_registered=None
......
......@@ -3,7 +3,7 @@
"""
from pandas import DataFrame
from tkinter import TOP, X, NO, W, Y, YES, BOTH, RIGHT, VERTICAL, \
Frame, Label
Frame, Label, Menu
from tkinter.ttk import Treeview, Style, Scrollbar
from ModelCallable import ModelCallable
......@@ -12,23 +12,30 @@ from Model import Description
from tk.InformFrame import InformFrame
from tk.Factory import *
from plot.PlotFrame import GraphGenerator
class ObjetsFrame(Frame, ModelCallable):
_controller=None
_mainWindow=None
_tree=None
_scrollbarY=None
_informFrame=None
_popupMenu=None
_popupObjectIid=None
_folders={}
def __init__(self, parent, controller, *args, **kwargs):
assert controller
def __init__(self, parent, controller, mainWindow, *args, **kwargs):
assert controller and mainWindow
Frame.__init__(self, parent, *args, **kwargs)
self._controller=controller
self._controller.getModel().registerModelCallable(self)
self._mainWindow=mainWindow
self.columnconfigure(0, weight=1, minsize=100)
self.columnconfigure(1, minsize=16)#default value of scrollbar width
......@@ -54,7 +61,7 @@ class ObjetsFrame(Frame, ModelCallable):
self._tree["columns"]=("class","description")
self._tree.column("#0", width=100, minwidth=15, stretch=False)
self._tree.column("class", width=50, stretch=False)
self._tree.column("class", width=15, stretch=False)
self._tree.column("description", width=200, minwidth=80, stretch=True)
self._tree.heading("#0",text="UID",anchor=W)
......@@ -64,9 +71,19 @@ class ObjetsFrame(Frame, ModelCallable):
self._tree.bind("<<TreeviewSelect>>", self.objectSelection)
self._tree.bind("<Delete>", self.objectSelection)
# popup tree menu
self._popupMenu = Menu(self._tree, tearoff=0)
self._popupMenu.add_command(label="NetworkX",
command=self.toNetworkX)
self._popupMenu.add_command(label="Graphviz",
command=self.toGraphviz)
self._tree.bind("<Button-3>", self.popup) # Button-2 on Aqua
# INFORM
self._informFrame=InformFrame(self)
self._informFrame.grid(row=2, columnspan = 2, column=0, sticky="nesw")
"""
GETTERS
"""
......@@ -132,7 +149,7 @@ class ObjetsFrame(Frame, ModelCallable):
"""
BIND FUNCTIONS
BIND FUNCTIONS/MENU FUNCTIONS
"""
def objectSelection(self, event):
curItems = self._tree.selection()
......@@ -147,7 +164,30 @@ class ObjetsFrame(Frame, ModelCallable):
self._informFrame.setText(text)
def objectDelete(self, event):
print(self._tree.focus())
pass
def popup(self, event):
try:
iid = self._tree.identify_row(event.y)
if iid:
self._popupMenu.tk_popup(event.x_root, event.y_root, 0)
if self._tree.parent(iid):
self._popupObjectIid=int(iid)
else:
pass
finally:
self._popupMenu.grab_release()
def toNetworkX(self):
if self._popupObjectIid is not None:
self._mainWindow.getPlotFrame().setGraph(GraphGenerator.give(self._controller.getModel().getObject(self._popupObjectIid)['object']))
self._popupObjectIid=None
def toGraphviz(self):
if self._popupObjectIid is not None:
self._mainWindow.exportObjectsGraphviz([self._popupObjectIid])
self._popupObjectIid=None
......
......@@ -27,3 +27,5 @@ class OutilsFrame(Frame):
NOFrame=NewObjectFrame(self, self._controller.getModel())
NOFrame.grid(row=1, column=0, sticky="nwe")
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment