package Common.Passes; import Common.Utils.Utils_; import Common.Utils.Stopwatch; import Common.Utils.TextLog; import Common.Visual.UI_; import Common.MainModule_; import _VisualDVM.Passes.PassCode; import Common.Visual.Windows.PassForm; import _VisualDVM.Current; import _VisualDVM.Global; import _VisualDVM.Visual.Controls.PassButton; import _VisualDVM.Visual.Controls.PassControl; import _VisualDVM.Visual.Menus.StablePassMenuItem; import _VisualDVM.Visual.UI; import javax.swing.*; import java.awt.event.ActionEvent; import java.util.Stack; import java.util.Vector; import java.util.concurrent.Semaphore; public class Pass { public int callsCount = 0; //число вызовов прохода за текущий сеанс визуализатора. public T target; //главный аргумент. public PassState state = PassState.Inactive; //текущее состояние прохода. public Semaphore animation_sem; //-------------- public Vector controls = new Vector<>(); public TextLog Log; //внутренний журнал прохода. protected boolean interrupt; protected SwingWorker dispatcher = null; private PassForm form = null; protected JMenuItem menuItem = null; private JButton button = null; private JButton tabButton = null; private Exception last_error; //последнее пойманное исключение выполнения. //->> public Throwable getCauseRec(Throwable ex) { Throwable cause = ex.getCause(); return (cause == null) ? ex : getCauseRec(cause); } // //https://www.delftstack.com/ru/howto/java/java-resize-image/ public String getIconPath() { return null; } public Icon getTabIcon() { return Utils_.getTabIcon(getIconPath()); } public AbstractAction getControlAction() { return new AbstractAction() { @Override public void actionPerformed(ActionEvent e) { UpdateStatsIfNeed(); Do(); } }; } public String getButtonText() { return getDescription(); } public JMenuItem createMenuItem() { if (menuItem == null) menuItem = new StablePassMenuItem(this); return menuItem; } public JButton createButton() { if (button == null) button = new PassButton(this); return button; } public JButton createTabButton() { if (tabButton == null) tabButton = new PassButton(this, true); return tabButton; } public void setControlsEnabled(boolean flag) { for (PassControl control : controls) control.setEnabled(flag); } public void setControlsVisible(boolean flag) { for (PassControl control : controls) control.setVisible(flag); } public void setControlsToolTipText(String text) { for (PassControl control : controls) control.setToolTipText(text); } protected void FocusResult() { } public boolean hasStats() { return false; } public void UpdateStatsIfNeed() { if (hasStats()) { try { MainModule_.object.getDb().passStats.IncPassStat(getName()); } catch (Exception ex) { Utils_.MainLog.PrintException(ex); } UI.fastAccessMenuBar.Refresh(); //todo все бары в мейн модуль. или уи.мейн модуль } } public boolean isDone() { return state.equals(PassState.Done); } public void setDone() { state=PassState.Done; } public String getName(){return getClass().getSimpleName();} public String getDescription() { return MainModule_.object.getPassDescription(getName()); } public String getStartDescription() { return getDescription(); } protected void FocusBeforeStart() { //отображение вкладок. } //- //объединение старых методов InitArgs и CanStart. зачастую семантика у них пересекалась. protected boolean canStart(Object... args) throws Exception { return true; } //- protected void body() throws Exception { } protected boolean validate() { return true; } //- protected void performCanNotStart() throws Exception { } protected void showCanNotStart() throws Exception { } protected void performPreparation() throws Exception { } protected void showPreparation() throws Exception { } protected void performFinish() throws Exception { } protected void showFinish() throws Exception { } protected void performDone() throws Exception { } protected void showDone() throws Exception { } protected void performFail() throws Exception { } protected void showFail() throws Exception { } //- private void PerformCanNotStart() throws Exception { performCanNotStart(); if (UI_.isActive()) showCanNotStart(); } protected void PerformPreparation() throws Exception { performPreparation(); if (UI_.isActive()) showPreparation(); } private void PerformFinish() throws Exception { performFinish(); //- if (UI_.isActive()) showFinish(); } private void PerformDone() throws Exception { performDone(); //- if (UI_.isActive()) showDone(); } private void PerformFail() throws Exception { performFail(); //- if (UI_.isActive()) showFail(); } //------ protected PassCode necessary() { return null; } protected boolean resetsNecessary() { return false; } public void Reset() { if (state == PassState.Done) state = PassState.Inactive; } //------ protected void createStack_r(Stack ToDo, Vector ToPrint) { ToDo.push(this); if (needsConfirmations() // если UI нет, сюда он не дойдет. ) { ToPrint.add(this.getStartDescription()); } if (necessary() != null) { Pass next = MainModule_.object.getPass(necessary()); if (resetsNecessary() || !next.isDone()) next.createStack_r(ToDo, ToPrint); } } //todo обращение к пропертиес как то пофиксить public boolean Do(Object... args) { Stack ToDo = new Stack<>(); Vector ToPrint = new Vector<>(); createStack_r(ToDo, ToPrint); if (Global.properties.ConfirmPassesStart && !ToPrint.isEmpty() && !UI_.Question("Выполнить проход(ы):\n" + String.join("\n", ToPrint)) ) return false; while (ToDo.size() > 1) { if (!ToDo.pop().start()) return false; } if (start(args)) { if (Global.properties.FocusPassesResult) FocusResult(); //- if (Global.properties.ShowPassesDone && !ToPrint.isEmpty() ) { UI_.Info("Проход(ы)\n\n" + String.join("\n", ToPrint) + "\nуспешно выполнен(ы)!"); } //- return true; } return false; } //- // protected boolean needsAnimation() { return false; } public void Interrupt() throws Exception { UI_.Info("Проход " + Utils_.Brackets(getDescription()) + " не разрешено прерывать."); } public boolean needsConfirmations() { return false; } // //- protected void CheckException(Exception ex) { if (ex instanceof PassException) { Log.Writeln_(ex.getMessage()); } else Utils_.MainLog.PrintException(ex); } public boolean start(Object... args) { //-------------------------------> interrupt = false; callsCount++; Stopwatch timer = new Stopwatch(); state = PassState.Inactive; last_error = null; target = null; Log = new TextLog(); if (!getDescription().isEmpty()) Utils_.MainLog.Print(getDescription() + " стартует.."); timer.Start(); //-------------------------------> try { if (UI_.isActive()) FocusBeforeStart(); if (canStart(args)) { PerformPreparation(); if (UI_.isActive() && needsAnimation()) { animation_sem = new Semaphore(1); animation_sem.acquire(); //--- form = null; MainModule_.object.set(Current.PassForm, null); System.gc(); //-- MainModule_.object.set(Current.PassForm, form = new PassForm(this)); dispatcher = new SwingWorker() { @Override protected Object doInBackground() { // UI.Print(DebugPrintLevel.Passes, "фоновое выполнение началось"); try { body(); } catch (Exception ex) { last_error = ex; } // UI.Print(DebugPrintLevel.Passes, "Ожидание активации окна анимации "); //ждем пока окно откроется и освободит его. try { animation_sem.acquire(); } catch (InterruptedException e) { Utils_.MainLog.PrintException(e); } //и уничтожаем его. // UI.Print(DebugPrintLevel.Passes, "Окно анимации активировано."); form.dispose(); form = null; // UI.Print(DebugPrintLevel.Passes, "Окно анимации закрыто."); animation_sem.release(); return null; } @Override protected void done() { //тут ничего не анализируем. события - отдельный поток. тут это не нужно } }; dispatcher.execute(); form.ShowDialog(); // UI.Print(DebugPrintLevel.Passes, "фоновое выполнение закончено, обработка резульатов"); if (last_error != null) { state = PassState.Crushed; CheckException(last_error); } // UI.Print(DebugPrintLevel.Passes, "OK"); dispatcher = null; } else { //исключения во время выполнения возможны в штатном режиме. try { body(); } catch (Exception ex) { state = PassState.Crushed;//упал при выполнении. CheckException(ex); } } PerformFinish(); if ((state != PassState.Crushed) && validate()) { state = PassState.Done; PerformDone(); } else { state = PassState.Failed; PerformFail(); } } else { state = PassState.CantStart; PerformCanNotStart(); } } catch (Exception ex) { state = PassState.ExternalCrushed; Utils_.MainLog.PrintException(ex); } //-------------------------------> timer.Stop(); if (!getDescription().isEmpty()) { Utils_.MainLog.Print( getDescription() + " окончен за " + timer.Print() + " состояние " + Utils_.Brackets(state.getDescription()) ); if (!Log.isEmpty() && UI_.isActive()) UI_.Error( "проход " + Utils_.Brackets(getDescription()) + "\n" + state.getDescription() + "\n\n" + Log.toString()); } //-------------------------------> return isDone(); } //-- public void ShowSapforMessage(String message) { if (UI_.isActive() && form != null) { String[] data = message.split(":"); switch (data[0]) { case "message_1": form.fields.Label1.setText((data.length > 1) ? data[1] : ""); break; case "message_2": form.fields.Label2.setText((data.length > 1) ? data[1] : ""); break; case "progress": form.fields.ProgressBar.setValue((data.length > 1) ? Integer.parseInt(data[1]) : 0); break; } } else System.out.println(Utils_.Brackets(message)); } public void ShowMessage1(String message) { if (form != null) form.fields.Label1.setText((message.length() > 1) ? message : ""); else System.out.println(Utils_.Brackets(message)); } public void ShowMessage2(String message) { if (form != null) form.fields.Label2.setText((message.isEmpty() ? "" : message)); else System.out.println(Utils_.Brackets(message)); } public void ShowProgress(int total, int current, boolean auto) { if (form != null) { form.lTitle.setText(getDescription() + " " + (current + 1) + "/" + total); if (auto) { double dp = ((double) current / total) * 100; int p = (int) dp; form.fields.ProgressBar.setValue(p); } } } public void ShowProgress2(int total, int current, String comment) { if (form != null) { form.fields.Label2.setText(comment + " " + current + "/" + total); double dp = ((double) current / total) * 100; int p = (int) dp; form.fields.ProgressBar.setValue(p); } } public void ShowProgressTextOnly(int total, int current, String comment) { if (form != null) form.lTitle.setText(form.lTitle.getText() + " : " + comment + " " + current + "/" + total); } }