package _VisualDVM.Visual.Windows; import Common.CommonConstants; import Common.Database.Objects.DBObject; import Common.Passes.Pass; import Common.Utils.Utils_; import Common.Visual.Controls.ShortLabel; import Common.Visual.Menus.VisualiserMenuBar; import Common.Visual.UI; import _VisualDVM.ProjectData.Files.UI.Editor.SPFEditor; import _VisualDVM.Utils; import _VisualDVM.Visual.Editor.BaseEditor; import javafx.util.Pair; import org.fife.ui.rsyntaxtextarea.RSyntaxTextAreaHighlighter; import org.fife.ui.rtextarea.RTextScrollPane; import javax.swing.*; import java.util.LinkedHashMap; import java.util.Vector; public abstract class ComparisonForm { public Class t; //класс объектов. //-->> public Vector lines = new Vector<>(); //строки с учетом/неучетом пробелов. для сравнения public Vector visible_lines = new Vector<>(); //строки с нетронутыми пробелами. для отображения //подсветка. public LinkedHashMap> colors = new LinkedHashMap<>(); public RSyntaxTextAreaHighlighter slave_highlighter = null; //погонщик рабов protected JToolBar tools; protected JLabel lObjectName; protected JButton bApplyObject; protected JButton bClose; //-->> protected T object = null; //-->> protected BaseEditor Body; //-->> ComparisonForm this_ = null; //? ComparisonForm slave = null; ComparisonForm master = null; //-->> private JPanel content; private JPanel editorPanel; private JButton bPrevious; private JButton bNext; private JButton bCompare; private RTextScrollPane Scroll; //----- private boolean events_on = false;//относится только к мастеру, отвечает за скроллы. private int current_diff_line = -1; //--->> // protected Object ownScrollModel = null; //---<< public ComparisonForm(Class t_in, ComparisonForm slave_in) { //- Body = new BaseEditor(); Scroll = new RTextScrollPane(Body); editorPanel.add(Scroll); // ownScrollModel = Scroll.getVerticalScrollBar().getModel(); //- t = t_in; this_ = this; slave = slave_in; bPrevious.setVisible(isMaster()); bNext.setVisible(isMaster()); Scroll.setLineNumbersEnabled(true); bApplyObject.addActionListener(e -> { ApplyObject(); }); //--->>> Body.setWhitespaceVisible(true); Body.setEditable(false); if (isMaster()) { // slave.Scroll.getVerticalScrollBar().setModel(Scroll.getVerticalScrollBar().getModel()); slave_highlighter = (RSyntaxTextAreaHighlighter) slave.Body.getHighlighter(); //бяк быть не должно при условии что строк одинаковое количество. а это должно выполняться. Body.addCaretListener(e -> { if (events_on && isReady() && slave.isReady()) { try { int master_lineNum = Body.getCaretLineNumber(); slave.Body.setCaretPosition(slave.Body.getLineStartOffset(master_lineNum)); } catch (Exception ex) { Utils_.MainLog.PrintException(ex); } } }); // slave.master = this; bPrevious.addActionListener(e -> { if (current_diff_line != CommonConstants.Nan) { if (current_diff_line > 0) current_diff_line--; else current_diff_line = colors.size() - 1; ShowCurrentDiff(); } }); bNext.addActionListener(e -> { if (current_diff_line != CommonConstants.Nan) { if (current_diff_line < colors.size() - 1) current_diff_line++; else current_diff_line = 0; ShowCurrentDiff(); } }); bCompare.addActionListener(e -> { DoComparePass(isReady() && slave.isReady()); }); } else { //рабу сравнивать не положено. bCompare.setVisible(false); } //--->>> bClose.addActionListener(e -> { onClose(); }); } public JPanel getContent() { return content; } //--->> public boolean isMaster() { return slave != null; } public boolean isSlave() { return master != null; } //--->> //неперегружаемые методы protected void RemoveObject() { object = null; removeObject(); showNoObject(); ClearText(); } public abstract Object getDefaultCurrentObject(); public void ApplyObject() { if (getDefaultCurrentObject() != null) ApplyObject(getDefaultCurrentObject()); else UI.Info("Текущий объект для сравнения не назначен!"); } public void ApplyObject(Object object_in) { RemoveObject(); object = (T) object_in; applyObject(); showObject(); } private void ShowCurrentDiff() { Body.gotoLine_(colors.get(current_diff_line).getKey()); } private void getLines() { lines.clear(); visible_lines.clear(); //-- Pair, Vector> p = Utils.getFortranLines(getText()); lines = p.getKey(); visible_lines = p.getValue(); } protected void ClearText() { events_on = false; Body.setText("объект не назначен"); } //предполагаем что оба объекта есть и мы можем получить с них текст. protected void Compare() throws Exception { events_on = false; current_diff_line = CommonConstants.Nan; colors.clear(); //----------------------------------------------------------------------------------------------- Body.setText(""); slave.Body.setText(""); int d = 0; getLines(); slave.getLines(); //-------------------------------------------------------------------- Vector t1 = new Vector<>(); Vector t2 = new Vector<>(); //------ int old_j = 0; int j = 0; for (int i = 0; i < lines.size(); ++i) { if (Utils.Contains(slave.lines, lines.get(i), old_j)) { for (int k = old_j; k < slave.lines.size(); ++k) { j = k; if (Utils.CompareLines(lines.get(i), slave.lines.get(k))) { j++; t1.add(visible_lines.get(i)); t2.add(slave.visible_lines.get(k)); break; } else { t1.add("+"); t2.add("+ " + slave.visible_lines.get(k)); colors.put(d, new Pair(t2.size() - 1, true)); ++d; } } old_j = j; } else { //строки гарантированно нет. t1.add("- " + visible_lines.get(i)); t2.add("- " + visible_lines.get(i)); colors.put(d, new Pair(t2.size() - 1, false)); ++d; } } //теперь граничное условие. если первый файл кончился а второй нет, его остаток это добавление. for (int i = j; i < slave.lines.size(); ++i) { t1.add("+"); t2.add("+ " + slave.visible_lines.get(i)); colors.put(d, new Pair(t2.size() - 1, true)); ++d; } ///---------------- Body.setText(String.join("\n", t1)); slave.Body.setText(String.join("\n", t2)); Body.setCaretPosition(0); slave.Body.setCaretPosition(0); //теперь покрас. for (Integer diff_num : colors.keySet()) { slave_highlighter.addHighlight( slave.Body.getLineStartOffset(colors.get(diff_num).getKey()), slave.Body.getLineEndOffset(colors.get(diff_num).getKey()), colors.get(diff_num).getValue() ? SPFEditor.GreenTextPainter : SPFEditor.RedTextPainter ); } if (colors.size() > 0) current_diff_line = 0; events_on = true; } public void Show() throws Exception { events_on = false; current_diff_line = CommonConstants.Nan; colors.clear(); //---------------------------------------------------------------------------------------------- Body.setText(""); slave.Body.setText(""); int d = 0; getLines(); slave.getLines(); //-------------------------------------------------------------------- Vector t1 = new Vector<>(); Vector t2 = new Vector<>(); //------ t1.addAll(visible_lines); t2.addAll(slave.visible_lines); //просто выясняем кто из них длиннее, и короткий дополняем пустыми строками.] int delta = Math.abs(t1.size() - t2.size()); if (lines.size() > slave.lines.size()) { Utils.addEmptyLines(t2, delta); } else if (lines.size() < slave.lines.size()) { Utils.addEmptyLines(t1, delta); } ///---------------- Body.setText(String.join("\n", t1)); slave.Body.setText(String.join("\n", t2)); Body.setCaretPosition(0); slave.Body.setCaretPosition(0); events_on = true; } //Перегружаемые методы. //--->> protected void showNoObject() { lObjectName.setText("?"); lObjectName.setToolTipText("Объект не назначен."); } protected void showObject() { if (object instanceof DBObject) { DBObject dbObject = (DBObject) object; lObjectName.setText(dbObject.toString()); lObjectName.setToolTipText(dbObject.toString()); } } protected void removeObject() { } protected void applyObject() { } protected abstract String getText(); protected boolean fortranWrapsOn() { return false; } //-->> private void createUIComponents() { // TODO: place custom component creation code here lObjectName = new ShortLabel(40); tools = new VisualiserMenuBar(); } //для сравнения по кнопке. public boolean isReady() { return object != null; } public void onClose() { RemoveObject(); } public void DoComparePass(boolean startCondition) { Pass pass = new Pass() { @Override public String getDescription() { return "Сравнение"; } @Override protected boolean needsAnimation() { return true; } @Override public boolean needsConfirmations() { return false; } @Override protected boolean canStart(Object... args) throws Exception { return startCondition; } @Override protected void body() throws Exception { Compare(); } }; pass.Do(); } public void DoShowPass(boolean startCondition) { Pass pass = new Pass() { @Override public String getDescription() { return "Отображение"; } @Override protected boolean needsAnimation() { return false; } @Override public boolean needsConfirmations() { return false; } @Override protected boolean canStart(Object... args) throws Exception { return startCondition; } @Override protected void body() throws Exception { Show(); } }; pass.Do(); } }