Files
VisualSapfor/src/ProjectData/SapforData/Functions/UI/Graph/FunctionsGraphUI.java

264 lines
14 KiB
Java
Raw Normal View History

2023-09-17 22:13:42 +03:00
package ProjectData.SapforData.Functions.UI.Graph;
import Common_old.Current;
import Common_old.UI.UI;
import Common_old.Utils.Utils;
2023-09-17 22:13:42 +03:00
import ProjectData.SapforData.Functions.FuncCoordinates;
import ProjectData.SapforData.Functions.FuncInfo;
import ProjectData.SapforData.Functions.FunctionType;
import Visual_DVM_2021.Passes.All.SPF_GetGraphFunctionPositions;
import Visual_DVM_2021.Passes.PassCode_2021;
import Visual_DVM_2021.Passes.Pass_2021;
2023-09-17 22:13:42 +03:00
import com.mxgraph.model.mxCell;
import com.mxgraph.model.mxGeometry;
import com.mxgraph.swing.mxGraphComponent;
import com.mxgraph.util.mxConstants;
import com.mxgraph.util.mxEvent;
import com.mxgraph.util.mxEventObject;
import com.mxgraph.util.mxRectangle;
import com.mxgraph.view.mxGraph;
import com.mxgraph.view.mxStylesheet;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.Hashtable;
import java.util.LinkedHashMap;
import static com.mxgraph.util.mxConstants.SHAPE_DOUBLE_ELLIPSE;
import static com.mxgraph.util.mxConstants.SHAPE_ELLIPSE;
public class FunctionsGraphUI extends mxGraph {
//--
public final static Timer ffTimer = new Timer(1000, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
Pass_2021.passes.get(PassCode_2021.SPF_GetGraphFunctionPositions).Do();
}
});
//---
private static final int default_width = 80;
private static final int default_height = 30;
//форма узлов?
// https://progi.pro/kak-sdelat-parallelogrammnuyu-vershinu-v-jgraphx-13032580
//мануал
//https://jgraph.github.io/mxgraph/docs/manual_javavis.html
//https://jgraph.github.io/mxgraph/java/docs/com/mxgraph/swing/mxGraphComponent.html
//общий манул
//https://jgraph.github.io/mxgraph/docs/manual_javavis.html#1.3
//манул п кликам?
//https://github.com/jgraph/mxgraph/blob/master/java/examples/com/mxgraph/examples/swing/ClickHandler.java
//все образцы
//https://github.com/jgraph/mxgraph/tree/master/java/examples/com/mxgraph/examples/swing
//https://github.com/jgraph/jgraphx/blob/master/src/com/mxgraph/util/mxConstants.java
//про размеры
//https://stackoverflow.com/questions/51619879/mxgraph-how-to-automatically-resize-mxcell-to-content-width-if-it-exceeds-the
//---------------------
//координаты вершин графа
// public LinkedHashMap<String, Pair<Double, Double>> vertexCoordinates = new LinkedHashMap<>();
protected GraphInfo graph = null; //инфа о вершинах и ребрах.
public FunctionsGraphUI(GraphInfo graph_in) {
graph = graph_in;
//настройки графа
setGridEnabled(true);
//setAllowNegativeCoordinates(false);
setAllowDanglingEdges(false); //запрет на висячие ребра.
setCellsEditable(false); //запрет на редактирование клеток
setCellsResizable(false); //запрет изменения размера клеток
setKeepEdgesInBackground(true); // ребра на задний план. очень важно.
setDropEnabled(false);
setAutoSizeCells(true);
setConnectableEdges(false);
setCellsCloneable(false);
//--------------------
mxStylesheet stylesheet = getStylesheet();
Hashtable<String, Object> style = new Hashtable<String, Object>();
style.put(mxConstants.STYLE_SHAPE, SHAPE_ELLIPSE);
style.put(mxConstants.STYLE_FONTCOLOR, "black");
style.put(mxConstants.STYLE_FILLCOLOR, "yellow");
style.put(mxConstants.STYLE_FONTSIZE, "16");
style.put(mxConstants.STYLE_FONTSTYLE, mxConstants.FONT_BOLD);
stylesheet.putCellStyle(FunctionType.Default.toString(), style);
//------------------------------------------
style = new Hashtable<String, Object>();
style.put(mxConstants.STYLE_SHAPE, SHAPE_ELLIPSE);
style.put(mxConstants.STYLE_FONTCOLOR, "black");
style.put(mxConstants.STYLE_FILLCOLOR, "lightgreen");
style.put(mxConstants.STYLE_FONTSIZE, "16");
style.put(mxConstants.STYLE_FONTSTYLE, mxConstants.FONT_BOLD);
stylesheet.putCellStyle(FunctionType.Main.toString(), style);
//------------------------------------------
style = new Hashtable<String, Object>();
style.put(mxConstants.STYLE_SHAPE, SHAPE_ELLIPSE);
style.put(mxConstants.STYLE_FONTCOLOR, "black");
style.put(mxConstants.STYLE_FILLCOLOR, "lightgray");
style.put(mxConstants.STYLE_FONTSIZE, "16");
style.put(mxConstants.STYLE_FONTSTYLE, mxConstants.FONT_BOLD);
// style.put(mxConstants.STYLE_STROKECOLOR, "lawngreen"); это и есть границы.
// style.put(mxConstants.STYLE_STROKEWIDTH, 5);
stylesheet.putCellStyle(FunctionType.Standard.toString(), style);
//------------------------------------------
style = new Hashtable<String, Object>();
style.put(mxConstants.STYLE_SHAPE, SHAPE_ELLIPSE);
style.put(mxConstants.STYLE_FONTCOLOR, "white");
style.put(mxConstants.STYLE_FILLCOLOR, "darkred");
style.put(mxConstants.STYLE_FONTSIZE, "16");
style.put(mxConstants.STYLE_FONTSTYLE, mxConstants.FONT_BOLD);
stylesheet.putCellStyle(FunctionType.NotFound.toString(), style);
//------------------------------------------
style = new Hashtable<String, Object>();
style.put(mxConstants.STYLE_SHAPE, SHAPE_DOUBLE_ELLIPSE);
style.put(mxConstants.STYLE_FONTCOLOR, "black");
style.put(mxConstants.STYLE_FILLCOLOR, "lightblue");
style.put(mxConstants.STYLE_FONTSIZE, "16");
style.put(mxConstants.STYLE_FONTSTYLE, mxConstants.FONT_BOLD);
// style.put(mxConstants.STYLE_STROKECOLOR, "lawngreen"); это и есть границы.
// style.put(mxConstants.STYLE_STROKEWIDTH, 5);
stylesheet.putCellStyle("current", style);
}
//---
// еще один туториал?
// https://www.47.gbmse.ru/resources/utility/mxgraph/docs/tutorial.html
//
//https://github.com/jgraph/mxgraph/tree/master/java/examples/com/mxgraph/examples/swing
//https://jgraph.github.io/mxgraph/java/docs/com/mxgraph/swing/mxGraphComponent.html
//https://www.47.gbmse.ru/resources/utility/mxgraph/docs/tutorial.html#3.2
public mxGraphComponent Draw() {
FuncInfo funcInfo = null;
//установить координаты вершин.
SetCoordinates(); //пустышка.
Object parent = getDefaultParent();
getModel().beginUpdate();
//непосредственное добавление графики
//------------------------------------
//размеры
//https://stackoverflow.com/questions/51619879/mxgraph-how-to-automatically-resize-mxcell-to-content-width-if-it-exceeds-the
// UI.Info("++");
LinkedHashMap<String, Object> mxVertexes = new LinkedHashMap<>();
for (String name : graph.vertexCoordinates.keySet()) {
funcInfo = Current.getProject().allFunctions.get(name);
String vertexType = funcInfo.type.toString();
if (SPF_GetGraphFunctionPositions.showByCurrentFunction) {
FuncInfo current_fi = (FuncInfo) Current.get(Current.Function);
if ((current_fi != null) && (funcInfo.funcName.equals(current_fi.funcName))) {
vertexType = "current";
}
}
mxVertexes.put(name,
insertVertex(parent,
name, //идентификатор вершины. должен быть уникальным.
name, //объект не стоит делать. какие то мутки при перетаскивании объектов.
//строки-ключа уже достаточно
//координаты вершины
graph.vertexCoordinates.get(name).getKey(),
graph.vertexCoordinates.get(name).getValue(),
default_width, default_height,
vertexType
));
}
for (String name : graph.vertexMap.keySet()) {
mxCell cell = (mxCell) mxVertexes.get(name);
mxRectangle preferred = getPreferredSizeForCell(cell);
mxGeometry current = cell.getGeometry();
current.setWidth((preferred.getWidth() > default_width) ? preferred.getWidth() : default_width);
//updateCellSize(cell, true); это если просто везде выставить авторазмер.
//тут же нам нужно применить его только в случае если ширина меньше чем надо.
for (String neigbor : graph.vertexMap.get(name)) {
insertEdge(parent, null,
//надпись над ребром.
"",
//вершина 1
mxVertexes.get(name),
//вершина 2
mxVertexes.get(neigbor));
}
}
//------------------------------------
//https://java.hotexamples.com/examples/com.mxgraph.view/mxGraph/setAutoSizeCells/java-mxgraph-setautosizecells-method-examples.html
groupCells();
getModel().endUpdate();
//------------------------------------
//обертка графа контролом
mxGraphComponent graphComponent = new mxGraphComponent(this);
graphComponent.setZoomFactor(1.10);
//--
// https://programtalk.com/java-more-examples/com.mxgraph.util.mxEvent.UP/
addListener(mxEvent.CELLS_MOVED, new mxIEventListener() {
@Override
public void invoke(Object o, mxEventObject mxEventObject) {
//Сохранение координат графа при сдвиге узла
if (mxEventObject.getProperties().containsKey("cells")) {
Object[] cells = (Object[]) mxEventObject.getProperties().get("cells");
for (Object cell_ : cells) {
if (cell_ instanceof mxCell) {
mxCell cell = (mxCell) cell_;
if (cell.isVertex()) {
String funcName = (String) cell.getValue();
FuncCoordinates coords = null;
// UI.Info(cell.getGeometry().getPoint().toString());
Point point = cell.getGeometry().getPoint();
try {
if (Current.getProject().db.funcCoordinates.containsKey(funcName)) {
coords = Current.getProject().db.funcCoordinates.get(funcName);
coords.name = funcName;
coords.X = point.getX();
coords.Y = point.getY();
Current.getProject().db.Update(coords);
} else {
coords = new FuncCoordinates();
coords.name = funcName;
coords.X = point.getX();
coords.Y = point.getY();
Current.getProject().db.Insert(coords);
}
} catch (Exception ignored) {
}
}
}
}
}
}
});
graphComponent.getGraphControl().setComponentPopupMenu(new FunctionsGraphMenu());
//обработка клика мышом.
graphComponent.getGraphControl().addMouseListener(new MouseAdapter() {
public void mouseReleased(MouseEvent e) {
Object cell = graphComponent.getCellAt(e.getX(), e.getY());
if (cell != null) {
mxCell mx_cell = (mxCell) cell;
if (mx_cell.isVertex()) {
String func_name = (String) mx_cell.getValue();
FuncInfo fi = Current.getProject().allFunctions.get(func_name);
switch (e.getClickCount()) {
case 1:
Current.set(Current.SelectedFunction, fi);
break;
case 2:
switch (fi.type) {
case Default:
case Main:
fi.Show(true);
break;
case Standard:
case NotFound:
UI.Info("процедура " + Utils.Brackets(func_name) + " " + fi.type.getDescription());
break;
}
break;
}
}
}
}
});
graphComponent.getViewport().setBackground(Color.WHITE);
return graphComponent;
}
//по умолчанию ничего не меняем.
public void SetCoordinates() {
}
public void SaveCoords() {
}
}