Перенос.
This commit is contained in:
495
src/Common/Current.java
Normal file
495
src/Common/Current.java
Normal file
@@ -0,0 +1,495 @@
|
||||
package Common;
|
||||
import Common.Database.iDBObject;
|
||||
import Common.UI.Themes.VisualiserTheme;
|
||||
import Common.Utils.TextLog;
|
||||
import GlobalData.Account.Account;
|
||||
import GlobalData.Compiler.Compiler;
|
||||
import GlobalData.Machine.Machine;
|
||||
import GlobalData.Makefile.Makefile;
|
||||
import GlobalData.Module.Module;
|
||||
import GlobalData.RemoteFile.RemoteFile;
|
||||
import GlobalData.RemoteSapfor.RemoteSapfor;
|
||||
import GlobalData.RunConfiguration.RunConfiguration;
|
||||
import GlobalData.Tasks.CompilationTask.CompilationTask;
|
||||
import GlobalData.Tasks.RunTask.RunTask;
|
||||
import GlobalData.User.User;
|
||||
import ProjectData.Files.DBProjectFile;
|
||||
import ProjectData.Project.db_project_info;
|
||||
import ProjectData.SapforData.Functions.FuncInfo;
|
||||
import ProjectData.SapforData.Regions.ParallelRegion;
|
||||
import Repository.BugReport.BugReport;
|
||||
import Repository.Subscribes.Subscriber;
|
||||
import TestingSystem.Configuration.Configuration;
|
||||
import TestingSystem.Sapfor.SapforConfiguration.SapforConfiguration;
|
||||
import TestingSystem.Sapfor.SapforTask.SapforTask_2023;
|
||||
import TestingSystem.Sapfor.SapforTasksPackage.SapforTasksPackage_2023;
|
||||
import TestingSystem.Tasks.TestCompilationTask;
|
||||
import TestingSystem.Tasks.TestRunTask;
|
||||
import TestingSystem.TasksPackage.TasksPackage;
|
||||
import TestingSystem.Test.Test;
|
||||
import Visual_DVM_2021.Passes.UI.PassForm;
|
||||
|
||||
import javax.swing.tree.DefaultMutableTreeNode;
|
||||
import java.io.File;
|
||||
import java.util.LinkedHashMap;
|
||||
public enum Current {
|
||||
Undefined,
|
||||
//--
|
||||
SapforEtalonTaskResult,//самый левый пакет
|
||||
SapforTaskResult,
|
||||
//--
|
||||
ComponentServerBackup,
|
||||
Subscriber,
|
||||
Theme,
|
||||
FileGraphElement,
|
||||
InlineGraphElement,
|
||||
InlineGraphElement2,
|
||||
IncludeGraphElement,
|
||||
Component,
|
||||
Project,
|
||||
File,
|
||||
Root,
|
||||
Version,
|
||||
BugReport,
|
||||
Account,
|
||||
DBArray,
|
||||
ProjectArray,
|
||||
ParallelRegionInfo,
|
||||
ParallelVariant,
|
||||
Machine,
|
||||
User,
|
||||
Compiler,
|
||||
Makefile,
|
||||
Module,
|
||||
RunConfiguration,
|
||||
EnvironmentValue,
|
||||
CompilationTask,
|
||||
RunTask,
|
||||
ProjectNode, //узел в дереве проекта. нужен для отображения добавленных файлов
|
||||
SelectedDirectory,
|
||||
SelectedFile,
|
||||
//текущий выбранный удаленный файл
|
||||
RemoteFile,
|
||||
PassForm, //текущее окно анимации. нужно для сообщений сапфора по сокету.
|
||||
RunStsRecord,
|
||||
//только для того, чтобы закодировать таблицу.
|
||||
Array,
|
||||
ParallelRegion,
|
||||
Dimensions,
|
||||
//----------
|
||||
Warnings,
|
||||
Errors,
|
||||
Notes,
|
||||
Recommendations,
|
||||
//-
|
||||
Sapfor,
|
||||
//-
|
||||
Scenario,
|
||||
ScenarioCommand,
|
||||
//-
|
||||
Configuration,
|
||||
Group,
|
||||
//-
|
||||
DVMParameterValue,
|
||||
Test,
|
||||
Function,
|
||||
SelectedFunction,
|
||||
//-
|
||||
Credentials,
|
||||
TestCompilationTask,
|
||||
TestRunTask,
|
||||
TasksPackage,
|
||||
//-
|
||||
DialogWindow,
|
||||
//-
|
||||
SapforTasksPackage,
|
||||
PackageVersion,
|
||||
RemoteSapfor,
|
||||
SapforConfiguration,
|
||||
SapforConfigurationCommand,
|
||||
SapforTask,
|
||||
SapforProfile,
|
||||
SapforProfileSetting,
|
||||
//--
|
||||
ProjectView;
|
||||
//-
|
||||
//---
|
||||
private static final LinkedHashMap<Current, Object> objects = new LinkedHashMap<>();
|
||||
public static Mode mode;
|
||||
public static boolean hasUI() {
|
||||
return Current.mode.equals(Current.Mode.Normal);
|
||||
}
|
||||
public static boolean HasProject() {
|
||||
return get(Project) != null;
|
||||
}
|
||||
public static boolean HasFile() {
|
||||
return get(File) != null;
|
||||
}
|
||||
public static boolean HasSelectedFile() {
|
||||
return get(SelectedFile) != null;
|
||||
}
|
||||
public static boolean HasAccount() {
|
||||
return get(Account) != null;
|
||||
}
|
||||
public static boolean HasMachine() {
|
||||
return get(Machine) != null;
|
||||
}
|
||||
public static boolean HasUser() {
|
||||
return get(User) != null;
|
||||
}
|
||||
public static boolean HasCompiler() {
|
||||
return get(Compiler) != null;
|
||||
}
|
||||
public static boolean HasRemoteFile() {
|
||||
return get(RemoteFile) != null;
|
||||
}
|
||||
public static boolean HasMakefile() {
|
||||
return get(Makefile) != null;
|
||||
}
|
||||
public static boolean HasRunConfiguration() {
|
||||
return get(RunConfiguration) != null;
|
||||
}
|
||||
public static boolean HasCompilationTask() {
|
||||
return get(CompilationTask) != null;
|
||||
}
|
||||
public static boolean HasRunTask() {
|
||||
return get(RunTask) != null;
|
||||
}
|
||||
public static boolean HasPassForm() {
|
||||
return get(PassForm) != null;
|
||||
}
|
||||
public static boolean HasProjectView() {
|
||||
return get(ProjectView) != null;
|
||||
}
|
||||
//для быстрого доступа на чтение. слишком много на нем завязано.
|
||||
public static db_project_info getProject() {
|
||||
return (db_project_info) get(Project);
|
||||
}
|
||||
public static DBProjectFile getFile() {
|
||||
return (DBProjectFile) get(File);
|
||||
}
|
||||
public static Repository.Component.Component getComponent() {
|
||||
return (Repository.Component.Component) get(Component);
|
||||
}
|
||||
public static Repository.BugReport.BugReport getBugReport() {
|
||||
return (BugReport) get(BugReport);
|
||||
}
|
||||
public static db_project_info getRoot() {
|
||||
return (db_project_info) get(Root);
|
||||
}
|
||||
public static boolean HasRoot() {
|
||||
return get(Root) != null;
|
||||
}
|
||||
public static db_project_info getVersion() {
|
||||
return (db_project_info) get(Version);
|
||||
}
|
||||
public static Account getAccount() {
|
||||
return (Account) get(Account);
|
||||
}
|
||||
public static boolean HasSubscriber() {
|
||||
return get(Current.Subscriber) != null;
|
||||
}
|
||||
public static Repository.Subscribes.Subscriber getSubscriber() {
|
||||
return (Subscriber) get(Current.Subscriber);
|
||||
}
|
||||
public static Machine getMachine() {
|
||||
return (Machine) get(Current.Machine);
|
||||
}
|
||||
public static User getUser() {
|
||||
return (User) get(Current.User);
|
||||
}
|
||||
public static Compiler getCompiler() {
|
||||
return (Compiler) get(Current.Compiler);
|
||||
}
|
||||
public static CompilationTask getCompilationTask() {
|
||||
return (CompilationTask) get(Current.CompilationTask);
|
||||
}
|
||||
public static RunTask getRunTask() {
|
||||
return (RunTask) get(Current.RunTask);
|
||||
}
|
||||
public static RemoteFile getRemoteFile() {
|
||||
return (RemoteFile) get(Current.RemoteFile);
|
||||
}
|
||||
public static Makefile getMakefile() {
|
||||
return (Makefile) get(Current.Makefile);
|
||||
}
|
||||
public static Module getModule() {
|
||||
return (Module) get(Current.Module);
|
||||
}
|
||||
public static RunConfiguration getRunConfiguration() {
|
||||
return (RunConfiguration) get(Current.RunConfiguration);
|
||||
}
|
||||
public static Repository.Component.Sapfor.Sapfor getSapfor() {
|
||||
return (Repository.Component.Sapfor.Sapfor) get(Current.Sapfor);
|
||||
}
|
||||
public static boolean HasGroup() {
|
||||
return get(Current.Group) != null;
|
||||
}
|
||||
public static TestingSystem.Group.Group getGroup() {
|
||||
return (TestingSystem.Group.Group) get(Current.Group);
|
||||
}
|
||||
//--
|
||||
public static boolean HasConfiguration() {
|
||||
return get(Current.Configuration) != null;
|
||||
}
|
||||
public static TestingSystem.Configuration.Configuration getConfiguration() {
|
||||
return (Configuration) get(Current.Configuration);
|
||||
}
|
||||
public static SapforConfiguration getSapforConfiguration() {
|
||||
return (TestingSystem.Sapfor.SapforConfiguration.SapforConfiguration) get(Current.SapforConfiguration);
|
||||
}
|
||||
//--
|
||||
public static Test getTest() {
|
||||
return (TestingSystem.Test.Test) get(Current.Test);
|
||||
}
|
||||
public static boolean HasTest() {
|
||||
return get(Current.Test) != null;
|
||||
}
|
||||
public static boolean HasVersion() {
|
||||
return get(Current.Version) != null;
|
||||
}
|
||||
public static TestCompilationTask getTestCompilationTask() {
|
||||
return (TestingSystem.Tasks.TestCompilationTask) get(Current.TestCompilationTask);
|
||||
}
|
||||
public static boolean HasTestCompilationTask() {
|
||||
return get(Current.TestCompilationTask) != null;
|
||||
}
|
||||
public static boolean HasTestRunTask() {
|
||||
return get(Current.TestRunTask) != null;
|
||||
}
|
||||
public static TestRunTask getTestRunTask() {
|
||||
return (TestingSystem.Tasks.TestRunTask) get(Current.TestRunTask);
|
||||
}
|
||||
public static RemoteFile getComponentServerBackup() {
|
||||
return (RemoteFile) get(Current.ComponentServerBackup);
|
||||
}
|
||||
public static boolean HasComponentServerBackup() {
|
||||
return get(Current.ComponentServerBackup) != null;
|
||||
}
|
||||
//-
|
||||
public static boolean HasSapforTasksPackage() {
|
||||
return get(Current.SapforTasksPackage) != null;
|
||||
}
|
||||
public static SapforTasksPackage_2023 getSapforTasksPackage() {
|
||||
return (SapforTasksPackage_2023) get(Current.SapforTasksPackage);
|
||||
}
|
||||
//-
|
||||
public static DefaultMutableTreeNode getProjectNode() {
|
||||
return (DefaultMutableTreeNode) get(Current.ProjectNode);
|
||||
}
|
||||
public static DefaultMutableTreeNode getProjectCurrentParentNode() {
|
||||
DefaultMutableTreeNode node = Current.getProjectNode();
|
||||
//если в дереве еще никто не выделялся, берем корень.
|
||||
if (node == null)
|
||||
return Current.getProject().filesTreeRoot;
|
||||
return (node.getUserObject() instanceof DBProjectFile) ? (DefaultMutableTreeNode) node.getParent() : node;
|
||||
}
|
||||
public static File getSelectedDirectory() {
|
||||
return (File) get(Current.SelectedDirectory);
|
||||
}
|
||||
public static DBProjectFile getSelectedFile() {
|
||||
return (DBProjectFile) get(Current.SelectedFile);
|
||||
}
|
||||
//-
|
||||
public static boolean HasBugReport() {
|
||||
return get(Current.BugReport) != null;
|
||||
}
|
||||
public static PassForm getPassForm() {
|
||||
return (Visual_DVM_2021.Passes.UI.PassForm) get(Current.PassForm);
|
||||
}
|
||||
public static VisualiserTheme getTheme() {
|
||||
return (VisualiserTheme) get(Current.Theme);
|
||||
}
|
||||
//--------------------------------------------------------------------------------
|
||||
public static ParallelRegion getParallelRegion() {
|
||||
return (ParallelRegion) get(Current.ParallelRegion);
|
||||
}
|
||||
public static boolean HasParallelRegion() {
|
||||
return get(Current.ParallelRegion) != null;
|
||||
}
|
||||
public static boolean HasFunction() {
|
||||
return get(Current.Function) != null;
|
||||
}
|
||||
public static boolean HasSelectedFunction() {
|
||||
return get(Current.SelectedFunction) != null;
|
||||
}
|
||||
public static FuncInfo getFunction() {
|
||||
return (FuncInfo) get(Current.Function);
|
||||
}
|
||||
public static FuncInfo getSelectionFunction() {
|
||||
return (FuncInfo) get(Current.SelectedFunction);
|
||||
}
|
||||
public static boolean HasTasksPackage() {
|
||||
return get(Current.TasksPackage) != null;
|
||||
}
|
||||
public static TasksPackage getTasksPackage() {
|
||||
return (TasksPackage) get(Current.TasksPackage);
|
||||
}
|
||||
public static boolean HasScenario() {
|
||||
return get(Current.Scenario) != null;
|
||||
}
|
||||
public static db_project_info getPackageVersion() {
|
||||
return (db_project_info) get(Current.PackageVersion);
|
||||
}
|
||||
public static boolean HasPackageVersion() {
|
||||
return get(Current.PackageVersion) != null;
|
||||
}
|
||||
public static GlobalData.RemoteSapfor.RemoteSapfor getRemoteSapfor() {
|
||||
return (RemoteSapfor) get(RemoteSapfor);
|
||||
}
|
||||
public static boolean HasRemoteSapfor() {
|
||||
return get(Current.RemoteSapfor) != null;
|
||||
}
|
||||
public static boolean HasSapforConfiguration() {
|
||||
return get(Current.SapforConfiguration) != null;
|
||||
}
|
||||
public static boolean HasSapforTask() {
|
||||
return get(Current.SapforTask) != null;
|
||||
}
|
||||
public static SapforTask_2023 getSapforTask() {
|
||||
return (SapforTask_2023) get(Current.SapforTask);
|
||||
}
|
||||
public static ProjectData.ProjectView getProjectView() {
|
||||
return (ProjectData.ProjectView) get(ProjectView);
|
||||
}
|
||||
public static boolean Check(TextLog Log, Current... names) {
|
||||
for (Current name : names)
|
||||
if (get(name) == null)
|
||||
Log.Writeln_(name.getDescription() + " не выбран(а)");
|
||||
return Log.isEmpty();
|
||||
}
|
||||
public static void CreateAll() {
|
||||
for (Current c : values())
|
||||
objects.put(c, null);
|
||||
}
|
||||
//-----------------------------------------
|
||||
public static Object get(Current name) {
|
||||
return objects.get(name);
|
||||
}
|
||||
public static Object set(Current name, Object object) {
|
||||
objects.replace(name, object);
|
||||
return object;
|
||||
}
|
||||
//применять только для наследников iDBObject
|
||||
public static boolean CheckID(Current name, int id) {
|
||||
return (get(name) != null) && (((iDBObject) get(name)).id == id);
|
||||
}
|
||||
public static TestingSystem.Sapfor.SapforConfigurationCommand.SapforConfigurationCommand getSapforConfigurationCommand() {
|
||||
return (TestingSystem.Sapfor.SapforConfigurationCommand.SapforConfigurationCommand) get(Current.SapforConfigurationCommand);
|
||||
}
|
||||
public static boolean HasSapforProfile() {
|
||||
return get(Current.SapforProfile)!=null;
|
||||
}
|
||||
public static GlobalData.SapforProfile.SapforProfile getSapforProfile(){
|
||||
return (GlobalData.SapforProfile.SapforProfile) get(Current.SapforProfile);
|
||||
}
|
||||
//--------------------------------------------
|
||||
public String getDescription() {
|
||||
switch (this) {
|
||||
case SapforProfile:
|
||||
return "Профиль SAPFOR";
|
||||
case SapforProfileSetting:
|
||||
return "Настройка профиля SAPFOR";
|
||||
case SapforEtalonTaskResult:
|
||||
return "Задача SAPFOR(Эталон)";
|
||||
case SapforTaskResult:
|
||||
return "Задача SAPFOR";
|
||||
case ComponentServerBackup:
|
||||
return "Версия компонента для восстановления с сервера";
|
||||
case Subscriber:
|
||||
return "Адресат";
|
||||
case SapforTask:
|
||||
return "Задача SAPFOR";
|
||||
case SelectedFunction:
|
||||
return "Выбранный узел графа процедур";
|
||||
case SapforConfigurationCommand:
|
||||
return "Команда конфигурации тестирования SAPFOR";
|
||||
case SapforConfiguration:
|
||||
return "Конфигурация тестирования SAPFOR";
|
||||
case RemoteSapfor:
|
||||
return "SAPFOR";
|
||||
case PackageVersion:
|
||||
return "Версия пакетного режима";
|
||||
case SapforTasksPackage:
|
||||
return "Пакет задач SAPFOR";
|
||||
case TasksPackage:
|
||||
return "Пакет задач";
|
||||
case Credentials:
|
||||
return "Учётные данные";
|
||||
case Function:
|
||||
return "Функция";
|
||||
case TestRunTask:
|
||||
return "Задача на запуск теста";
|
||||
case TestCompilationTask:
|
||||
return "Задача на компиляцию теста";
|
||||
case DVMParameterValue:
|
||||
return "Параметр DVM системы";
|
||||
case ParallelRegion:
|
||||
return "Область распараллеливания";
|
||||
case Group:
|
||||
return "Группа тестов DVM";
|
||||
case Scenario:
|
||||
return "Сценарий";
|
||||
case ScenarioCommand:
|
||||
return "Команда сценария";
|
||||
case ProjectNode:
|
||||
return "текущий узел дерева проектов"; //служебка
|
||||
case Test:
|
||||
return "Тест";
|
||||
case Sapfor:
|
||||
return "SAPFOR";
|
||||
case Theme:
|
||||
return "Тема";
|
||||
case EnvironmentValue:
|
||||
return "Значение переменной окружения";
|
||||
case SelectedDirectory:
|
||||
return "Папка проекта";
|
||||
case SelectedFile:
|
||||
return "Файл проекта";
|
||||
case RunConfiguration:
|
||||
return "Конфигурация запуска";
|
||||
case RunTask:
|
||||
return "Задача на запуск";
|
||||
case CompilationTask:
|
||||
return "Задача на компиляцию";
|
||||
case Makefile:
|
||||
return "Мейкфайл";
|
||||
case Module:
|
||||
return "Языковой модуль мейкфайла";
|
||||
case RemoteFile:
|
||||
return "Удалённый файл";
|
||||
case Component:
|
||||
return "Компонент";
|
||||
case Project:
|
||||
return "Проект";
|
||||
case File:
|
||||
return "Файл";
|
||||
case Root:
|
||||
return "Корень дерева версий";
|
||||
case Version:
|
||||
return "Версия";
|
||||
case BugReport:
|
||||
return "Отчёт об ошибке";
|
||||
case Account:
|
||||
return "Аккаунт";
|
||||
case Machine:
|
||||
return "Машина";
|
||||
case User:
|
||||
return "Пользователь";
|
||||
case Compiler:
|
||||
return "Компилятор";
|
||||
case DialogWindow:
|
||||
return "Диалоговое окно";
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
//---
|
||||
public enum Mode {
|
||||
Undefined,
|
||||
Normal,
|
||||
Server,
|
||||
Testing,
|
||||
Package
|
||||
}
|
||||
}
|
||||
31
src/Common/Database/ColumnType.java
Normal file
31
src/Common/Database/ColumnType.java
Normal file
@@ -0,0 +1,31 @@
|
||||
package Common.Database;
|
||||
public enum ColumnType {
|
||||
UNDEFINED,
|
||||
INT,
|
||||
LONG,
|
||||
DOUBLE,
|
||||
STRING;
|
||||
public static ColumnType valueOf(Class<?> type) {
|
||||
ColumnType res = UNDEFINED;
|
||||
try {
|
||||
res = valueOf(type.getSimpleName().toUpperCase());
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
return res;
|
||||
}
|
||||
public String getSQLType() {
|
||||
String res = "";
|
||||
switch (this) {
|
||||
case INT:
|
||||
case LONG:
|
||||
res = "INTEGER";
|
||||
break;
|
||||
case DOUBLE:
|
||||
res = "REAL";
|
||||
break;
|
||||
case STRING:
|
||||
res = "VARCHAR";
|
||||
}
|
||||
return res;
|
||||
}
|
||||
}
|
||||
64
src/Common/Database/DBObject.java
Normal file
64
src/Common/Database/DBObject.java
Normal file
@@ -0,0 +1,64 @@
|
||||
package Common.Database;
|
||||
import Common.UI.Selectable;
|
||||
import Common.Utils.Index;
|
||||
import Common.Utils.Utils;
|
||||
import com.sun.org.glassfish.gmbal.Description;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Objects;
|
||||
public abstract class DBObject implements Selectable, Serializable {
|
||||
//<editor-fold desc="Selectable">
|
||||
@Description("IGNORE")
|
||||
private boolean selected = false;
|
||||
@Override
|
||||
public boolean isSelected() {
|
||||
return selected;
|
||||
}
|
||||
@Override
|
||||
public void select(boolean flag) {
|
||||
if (selected != flag) {
|
||||
selected = flag;
|
||||
Index counter = getSelectionCounter();
|
||||
if (Objects.nonNull(counter)) {
|
||||
if (selected) counter.Inc();
|
||||
else counter.Dec();
|
||||
}
|
||||
}
|
||||
}
|
||||
//</editor-fold>
|
||||
public Index getSelectionCounter() {
|
||||
return null;
|
||||
}
|
||||
public boolean isVisible() {
|
||||
return true;
|
||||
}
|
||||
public abstract Object getPK();
|
||||
public String getBDialogName() {
|
||||
return Utils.Brackets(getDialogName());
|
||||
}
|
||||
public String getDialogName() {
|
||||
return getPK().toString();
|
||||
}
|
||||
//статус. например завершенность багрепорта или состояние задачи на запуск. как правило обладает цветным шрифтом.
|
||||
//как объект будут называть по внешним ключам.
|
||||
public String getFKName() {
|
||||
return null;
|
||||
}
|
||||
public Object getEmptyFK() {
|
||||
return null;
|
||||
}
|
||||
@Override
|
||||
public String toString() {
|
||||
return getBDialogName();
|
||||
}
|
||||
//---
|
||||
public void SynchronizeFields(DBObject src){
|
||||
selected = src.selected;
|
||||
}
|
||||
//------
|
||||
public DBObject(){}
|
||||
public DBObject(DBObject src){
|
||||
this.SynchronizeFields(src);
|
||||
}
|
||||
//---------
|
||||
}
|
||||
34
src/Common/Database/DBTable.java
Normal file
34
src/Common/Database/DBTable.java
Normal file
@@ -0,0 +1,34 @@
|
||||
package Common.Database;
|
||||
import java.lang.reflect.Field;
|
||||
public abstract class DBTable<K, D extends DBObject> extends DataSet<K, D> {
|
||||
//-
|
||||
public DBTableColumn PK = null;
|
||||
private Database db = null; //база данных - владелец таблицы.
|
||||
public DBTable(Class<K> k_in, Class<D> d_in) {
|
||||
super(k_in, d_in);
|
||||
for (Field field : d.getFields()) {
|
||||
DBTableColumn column = new DBTableColumn(field);
|
||||
if ((!column.Ignore) && !columns.containsKey(column.Name)) {
|
||||
columns.put(column.Name, column);
|
||||
if (column.PrimaryKey) PK = column;
|
||||
}
|
||||
}
|
||||
}
|
||||
public Database getDb() {
|
||||
return db;
|
||||
}
|
||||
public void setDb(Database db_in) {
|
||||
db = db_in;
|
||||
}
|
||||
@Override
|
||||
public String getPKName() {
|
||||
return PK.Name;
|
||||
}
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder res = new StringBuilder(Name + "\n");
|
||||
for (DBTableColumn c : columns.values())
|
||||
res.append(c).append("\n");
|
||||
return res.toString();
|
||||
}
|
||||
}
|
||||
50
src/Common/Database/DBTableColumn.java
Normal file
50
src/Common/Database/DBTableColumn.java
Normal file
@@ -0,0 +1,50 @@
|
||||
package Common.Database;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.Vector;
|
||||
public class DBTableColumn {
|
||||
public String Name = "";
|
||||
public ColumnType type = ColumnType.UNDEFINED;
|
||||
public Vector<String> attributes = new Vector<String>();
|
||||
public boolean Ignore = false;
|
||||
public boolean PrimaryKey = false;
|
||||
public boolean AutoIncrement = false;
|
||||
public Object default_value = null;
|
||||
public DBTableColumn(Field field) {
|
||||
ExtractAttributes(field);
|
||||
PrimaryKey = attributes.contains("PRIMARY KEY");
|
||||
AutoIncrement = attributes.contains("AUTOINCREMENT");
|
||||
Name = field.getName();
|
||||
type = (field.getType().isEnum()) ? ColumnType.STRING : ColumnType.valueOf(field.getType());
|
||||
Ignore = ((Modifier.isStatic(field.getModifiers()) ||
|
||||
type.equals(ColumnType.UNDEFINED) ||
|
||||
attributes.contains("IGNORE")
|
||||
)
|
||||
);
|
||||
}
|
||||
public String QName() {
|
||||
return "\"" + Name + "\"";
|
||||
}
|
||||
public void ExtractAttributes(Field field) {
|
||||
attributes = new Vector<String>();
|
||||
Annotation[] annotations = field.getAnnotations();
|
||||
for (Annotation a : annotations) {
|
||||
String[] data = a.toString().split("value=");
|
||||
if (data.length > 1) {
|
||||
String[] attributes_ = data[1].split("[,\")]");
|
||||
for (String attribute : attributes_) {
|
||||
if (attribute.length() > 0)
|
||||
attributes.add(attribute);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public String toString() {
|
||||
String res = QName() + " " + type.getSQLType();
|
||||
if (attributes.size() > 0)
|
||||
res += " " + String.join(" ", attributes);
|
||||
return res;
|
||||
}
|
||||
}
|
||||
253
src/Common/Database/DataSet.java
Normal file
253
src/Common/Database/DataSet.java
Normal file
@@ -0,0 +1,253 @@
|
||||
package Common.Database;
|
||||
import Common.Current;
|
||||
import Common.UI.DataSetControlForm;
|
||||
import Common.UI.Menus_2023.DataMenuBar;
|
||||
import Common.UI.Tables.ColumnFilter;
|
||||
import Common.UI.UI;
|
||||
import Common.UI.Windows.Dialog.DBObjectDialog;
|
||||
import Common.UI.Windows.Dialog.DialogFields;
|
||||
import Common.Utils.TextLog;
|
||||
import Visual_DVM_2021.UI.Interface.FilterWindow;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.util.Comparator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Vector;
|
||||
import java.util.stream.Collectors;
|
||||
public class DataSet<K, D extends DBObject> extends DataSetAnchestor {
|
||||
//-
|
||||
public static LinkedHashMap<Class, Object> selections = new LinkedHashMap<>();
|
||||
//-
|
||||
public String Name;
|
||||
public Class<K> k; //класс первичного ключа.
|
||||
public Class<D> d; //класс объектов.
|
||||
public LinkedHashMap<K, D> Data = new LinkedHashMap<>(); //наполнение
|
||||
//-
|
||||
//<editor-fold desc="UI таблица">
|
||||
public DataSetControlForm ui_;
|
||||
protected FilterWindow f_ui;
|
||||
//</editor-fold>
|
||||
//-
|
||||
public LinkedHashMap<Integer, ColumnFilter> columnsFilters = new LinkedHashMap<>();
|
||||
public DataSet(Class<K> k_in, Class<D> d_in) {
|
||||
k = k_in;
|
||||
d = d_in;
|
||||
Name = d.getSimpleName();
|
||||
}
|
||||
public void mountUI(JPanel content_in) {
|
||||
UI.Clear(content_in);
|
||||
//-->
|
||||
ui_ = createUI();
|
||||
ui_.setContent(content_in);
|
||||
//-->
|
||||
if (UI.menuBars.containsKey(getClass())) {
|
||||
DataMenuBar bar = UI.menuBars.get(getClass());
|
||||
content_in.add(bar, BorderLayout.NORTH);
|
||||
setFilterUI(count -> UI.menuBars.get(getClass()).countLabel.setText(String.valueOf(count)));
|
||||
if (ui_.hasCheckBox())
|
||||
bar.createSelectionButtons(this);
|
||||
}
|
||||
content_in.add(ui_.getDataPanel(), BorderLayout.CENTER);
|
||||
}
|
||||
public DataSetControlForm getUi() {
|
||||
return ui_;
|
||||
}
|
||||
public void setFilterUI(FilterWindow ui_in) {
|
||||
f_ui = ui_in;
|
||||
}
|
||||
public void ShowUI() {
|
||||
if (ui_ != null) {
|
||||
ui_.Show();
|
||||
if (f_ui != null)
|
||||
f_ui.ShowMatchesCount(getRowCountUI());
|
||||
}
|
||||
}
|
||||
public void ShowUI(Object key) {
|
||||
if (ui_ != null) {
|
||||
ui_.Show(key);
|
||||
if (f_ui != null)
|
||||
f_ui.ShowMatchesCount(getRowCountUI());
|
||||
}
|
||||
}
|
||||
public void ClearUI() {
|
||||
if ((ui_ != null) && ui_.isShown()) {
|
||||
ui_.ClearSelection();
|
||||
ui_.Clear();
|
||||
if (f_ui != null)
|
||||
f_ui.ShowNoMatches();
|
||||
}
|
||||
}
|
||||
public void RefreshUI() {
|
||||
if (ui_ != null) ui_.Refresh();
|
||||
}
|
||||
public int getRowCountUI() {
|
||||
return ui_.getRowCount();
|
||||
}
|
||||
public void SetCurrentObjectUI(Object pk) {
|
||||
if (ui_ != null) {
|
||||
//todo возможно проверить, что текущий объект уже соответствует ключу, и если да, то ничего делать.
|
||||
ui_.ClearSelection(); //сброс текущего объекта и всего что с ним связано.
|
||||
ui_.Select(pk);
|
||||
}
|
||||
}
|
||||
//столбы/ потом переименовать обратно в getUIColumnNames.сейчас так для скорости переноса.
|
||||
public String[] getUIColumnNames() {
|
||||
return new String[]{};
|
||||
}
|
||||
protected DataSetControlForm createUI() {
|
||||
return null;
|
||||
}
|
||||
public boolean hasUI() {
|
||||
return ui_ != null;
|
||||
}
|
||||
public void CheckAll(boolean flag) {
|
||||
for (D object : Data.values()) {
|
||||
if (object.isVisible())
|
||||
object.Select(flag);
|
||||
}
|
||||
RefreshUI();
|
||||
}
|
||||
public D getFirstRecord() {
|
||||
return Data.values().stream().findFirst().orElse(null);
|
||||
}
|
||||
public Vector<D> getOrderedRecords(Comparator<D> comparator) {
|
||||
Vector<D> res = new Vector<>(Data.values());
|
||||
res.sort(comparator);
|
||||
return res;
|
||||
}
|
||||
@SuppressWarnings("unchecked")
|
||||
public DBObjectDialog<D, ? extends DialogFields> getDialog() {
|
||||
return null;
|
||||
}
|
||||
public boolean ShowAddObjectDialog(DBObject object) {
|
||||
return getDialog().ShowDialog(getSingleDescription() + ": добавление", object);
|
||||
}
|
||||
public boolean ShowEditObjectDialog(DBObject object) {
|
||||
DBObjectDialog dialog = getDialog();
|
||||
dialog.edit = true;
|
||||
dialog.SetEditLimits();
|
||||
return dialog.ShowDialog(getSingleDescription() + ": редактирование", object);
|
||||
}
|
||||
public boolean ViewObject(DBObject object) {
|
||||
DBObjectDialog dialog = getDialog();
|
||||
dialog.SetReadonly();
|
||||
dialog.ShowDialog(getSingleDescription() + ": просмотр", object);
|
||||
return false;
|
||||
}
|
||||
public boolean ShowDeleteObjectDialog(DBObject object) {
|
||||
return UI.Warning(getSingleDescription() + " " + object.getBDialogName() + " будет удален(а)");
|
||||
}
|
||||
public String QName() {
|
||||
return "\"" + Name + "\"";
|
||||
}
|
||||
public String getPKName() {
|
||||
return "";
|
||||
} //получить имя ключевого поля. нужно для таблиц.
|
||||
public String getPluralDescription() {
|
||||
return "";
|
||||
}
|
||||
public String getSingleDescription() {
|
||||
return "";
|
||||
}
|
||||
//времянки
|
||||
public Current CurrentName() {
|
||||
return Current.Undefined;
|
||||
}
|
||||
public boolean CheckCurrent(TextLog log) {
|
||||
return Current.Check(log, CurrentName());
|
||||
}
|
||||
public boolean hasCurrent() {
|
||||
return Current.get(CurrentName()) != null;
|
||||
}
|
||||
public void dropCurrent() {
|
||||
Current.set(CurrentName(), null);
|
||||
}
|
||||
public D getCurrent() {
|
||||
return (D) Current.get(CurrentName());
|
||||
}
|
||||
public void setCurrent(D o) {
|
||||
Current.set(CurrentName(), o);
|
||||
}
|
||||
//-
|
||||
public void put(Object key, D object) {
|
||||
Data.put((K) key, object);
|
||||
}
|
||||
public D get(Object key) {
|
||||
return Data.get(key);
|
||||
}
|
||||
public Object getFieldAt(D object, int columnIndex) {
|
||||
return null;
|
||||
}
|
||||
public void clear() {
|
||||
Data.clear();
|
||||
}
|
||||
public int size() {
|
||||
return Data.size();
|
||||
}
|
||||
public boolean containsKey(Object key) {
|
||||
return Data.containsKey(key);
|
||||
}
|
||||
//-
|
||||
public Vector<K> getVisibleKeys() {
|
||||
Comparator<D> comparator = getComparator();
|
||||
Vector<K> res = new Vector<>();
|
||||
if (comparator == null) {
|
||||
for (K key : Data.keySet())
|
||||
if (Data.get(key).isVisible())
|
||||
res.add(key);
|
||||
} else {
|
||||
Vector<D> raw = new Vector<>();
|
||||
for (D object : Data.values()) {
|
||||
if (object.isVisible())
|
||||
raw.add(object);
|
||||
}
|
||||
raw.sort(comparator);
|
||||
for (D object : raw)
|
||||
res.add((K) object.getPK());
|
||||
}
|
||||
return res;
|
||||
}
|
||||
protected Comparator<D> getComparator() {
|
||||
return null;
|
||||
}
|
||||
public int getCheckedCount() {
|
||||
return (int) Data.values().stream().filter(d -> d.isVisible() && d.isSelected()).count();
|
||||
}
|
||||
public Vector<D> getCheckedItems() {
|
||||
return Data.values().stream().filter(d -> d.isVisible() && d.isSelected()).collect(Collectors.toCollection(Vector::new));
|
||||
}
|
||||
public Vector<K> getCheckedKeys() {
|
||||
return Data.values().stream().filter(DBObject::isSelected).map(d -> (K) d.getPK()).collect(Collectors.toCollection(Vector::new));
|
||||
}
|
||||
//--
|
||||
public void SaveLastSelections() {
|
||||
if (hasUI()) {
|
||||
Object lastPk = null;
|
||||
if ((CurrentName() != Current.Undefined) && (getCurrent() != null))
|
||||
lastPk = getCurrent().getPK();
|
||||
if (!selections.containsKey(getClass()))
|
||||
selections.put(getClass(), lastPk);
|
||||
else selections.replace(getClass(), lastPk);
|
||||
}
|
||||
}
|
||||
public void RestoreLastSelections() {
|
||||
if (hasUI()) {
|
||||
Object lastPk = selections.get(getClass());
|
||||
// if (lastPk != null) UI.Info(this.getClass() + ":" + lastPk.toString());
|
||||
if ((CurrentName() != Current.Undefined) && (lastPk != null)) {
|
||||
// UI.Info(lastPk.toString());
|
||||
// System.out.println(ui);
|
||||
// UI.Info("+");
|
||||
ui_.Select(lastPk);
|
||||
}
|
||||
}
|
||||
}
|
||||
//---
|
||||
// применить значение фильтра к фильру объекта напирмер Message.filterValue = text;
|
||||
public void changeColumnFilterValue(int columnIndex, String text) {
|
||||
}
|
||||
public Object getColumnFilterValue(int columnIndex) {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
11
src/Common/Database/DataSetAnchestor.java
Normal file
11
src/Common/Database/DataSetAnchestor.java
Normal file
@@ -0,0 +1,11 @@
|
||||
package Common.Database;
|
||||
import java.util.LinkedHashMap;
|
||||
public abstract class DataSetAnchestor {
|
||||
//чтобы обмануть стирание типов во всех параметризованных полях. используется не во всех потомках.
|
||||
//ибо не все наборы данных относятся к базам.
|
||||
public LinkedHashMap<String, DBTableColumn> columns = new LinkedHashMap<>();
|
||||
//то же самое. на самом деле внешние ключи бывают только у таблиц бд
|
||||
public LinkedHashMap<Class<? extends DBObject>, FKBehaviour> getFKDependencies() {
|
||||
return new LinkedHashMap<>();
|
||||
}
|
||||
}
|
||||
274
src/Common/Database/Database.java
Normal file
274
src/Common/Database/Database.java
Normal file
@@ -0,0 +1,274 @@
|
||||
package Common.Database;
|
||||
import Common.Global;
|
||||
import Common.Utils.Utils;
|
||||
import Repository.RepositoryRefuseException;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Vector;
|
||||
//самый общий интерфейс базы данных, независимо от реализации.
|
||||
public abstract class Database {
|
||||
//------------------------------
|
||||
public LinkedHashMap<Class<? extends DBObject>, DBTable> tables = new LinkedHashMap<>(); //таблицы
|
||||
protected File file = null;
|
||||
public Database(File file_in) {
|
||||
file = file_in;
|
||||
}
|
||||
public File getFile() {
|
||||
return file;
|
||||
}
|
||||
public void setFile(File file_in) {
|
||||
file = file_in;
|
||||
}
|
||||
//<editor-fold desc="Общая часть">
|
||||
public void Connect() throws Exception {
|
||||
// UI.Print(DebugPrintLevel.Database, "соединение с базой данных " + file.getAbsolutePath());
|
||||
connect();
|
||||
}
|
||||
public void prepareTablesStatements() throws Exception {
|
||||
}
|
||||
public void Disconnect() throws Exception {
|
||||
// UI.Print(DebugPrintLevel.Database, "закрытие соединения с базой данных " + file.getAbsolutePath());
|
||||
disconnect();
|
||||
}
|
||||
public void BeginTransaction() throws Exception {
|
||||
// UI.Print(DebugPrintLevel.Database, "BEGIN TRANSACTION:");
|
||||
beginTransaction();
|
||||
}
|
||||
public void Commit() throws Exception {
|
||||
// UI.Print(DebugPrintLevel.Database, "COMMIT");
|
||||
commit();
|
||||
}
|
||||
public void CreateAllTables() throws Exception {
|
||||
BeginTransaction();
|
||||
initAllTables(); // все добавления новых таблиц - туть.
|
||||
for (DBTable table : tables.values()) {
|
||||
CreateTable(table);
|
||||
table.setDb(this);
|
||||
}
|
||||
Commit();
|
||||
}
|
||||
//схема как с проходами. в методе initAllTables добавляем все таблицы через уникальные конструкторы
|
||||
public void addTable(DBTable table) {
|
||||
tables.put(table.d, table);
|
||||
}
|
||||
public void Synchronize() throws Exception {
|
||||
BeginTransaction();
|
||||
for (DBTable table : tables.values())
|
||||
LoadAll(table);
|
||||
Init(); //перегружаемая часть синхронизации.
|
||||
Commit();
|
||||
}
|
||||
public void LoadAllTablesWithoutInit() throws Exception {
|
||||
BeginTransaction();
|
||||
for (DBTable table : tables.values())
|
||||
LoadAll(table);
|
||||
Commit();
|
||||
}
|
||||
public <K, D extends DBObject> void LoadAll(DBTable<K, D> table) throws Exception {
|
||||
table.Data.clear();
|
||||
loadAll(table);
|
||||
}
|
||||
public DBObject Insert(DBObject o) throws Exception {
|
||||
DBTable table = tables.get(o.getClass());
|
||||
insert(table, o);
|
||||
table.Data.put(o.getPK(), o);
|
||||
return o;
|
||||
}
|
||||
public DBObject InsertWithCheck(DBObject o) throws Exception {
|
||||
DBTable table = tables.get(o.getClass());
|
||||
if (!table.Data.containsKey(o.getPK())) {
|
||||
insert(table, o);
|
||||
table.Data.put(o.getPK(), o);
|
||||
} else
|
||||
throw new RepositoryRefuseException("Таблица " + Utils.Brackets(table.Name) + " уже содержит объект с ключом " + Utils.Brackets(o.getPK().toString()));
|
||||
return o;
|
||||
}
|
||||
public DBObject InsertWithCheck_(DBObject o) throws Exception {
|
||||
DBTable table = tables.get(o.getClass());
|
||||
if (!table.Data.containsKey(o.getPK())) {
|
||||
insert(table, o);
|
||||
table.Data.put(o.getPK(), o);
|
||||
return o;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
// не работает с автоинкрементом.
|
||||
public DBObject UpdateWithCheck(DBObject to_update) throws Exception {
|
||||
DBTable table = tables.get(to_update.getClass());
|
||||
if (table.Data.containsKey(to_update.getPK())) {
|
||||
DBObject o = (DBObject) table.Data.get(to_update.getPK());
|
||||
o.SynchronizeFields(to_update);
|
||||
update(table, o);
|
||||
return o;
|
||||
} else {
|
||||
insert(table, to_update);
|
||||
table.Data.put(to_update.getPK(), to_update);
|
||||
return to_update;
|
||||
}
|
||||
}
|
||||
public DBObject DeleteWithCheck(DBObject to_delete) throws Exception {
|
||||
DBTable table = tables.get(to_delete.getClass());
|
||||
if (table.Data.containsKey(to_delete.getPK())) {
|
||||
DBObject o = (DBObject) table.Data.get(to_delete.getPK());
|
||||
delete(table, o);
|
||||
table.Data.remove(o.getPK());
|
||||
return o;
|
||||
} else
|
||||
throw new RepositoryRefuseException("Таблица " + Utils.Brackets(table.Name) + " не содержит объект с ключом " + Utils.Brackets(to_delete.getPK().toString()));
|
||||
}
|
||||
// не работает с автоинкрементом.
|
||||
public DBObject getObjectCopyByPK(Class table_class, Object pk) throws Exception {
|
||||
DBTable table = tables.get(table_class);
|
||||
Object res_ = table_class.newInstance();
|
||||
DBObject res = (DBObject) res_;
|
||||
if (table.Data.containsKey(pk)) {
|
||||
DBObject original = (DBObject) table.Data.get(pk);
|
||||
res.SynchronizeFields(original);
|
||||
} else {
|
||||
table_class.getField(table.getPKName()).set(res, pk); //инче просто синхроним пк. и вставляем
|
||||
insert(table, res);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
public boolean checkObjectExistense(Class table_class, Object pk) throws Exception {
|
||||
DBTable table = tables.get(table_class);
|
||||
return table.containsKey(pk);
|
||||
}
|
||||
public Vector<Object> getObjectsCopies(Class table_class, Vector<Object> keys) {
|
||||
Vector<Object> res = new Vector<>();
|
||||
DBTable table = tables.get(table_class);
|
||||
for (Object key : keys)
|
||||
if (table.containsKey(key))
|
||||
res.add(table.Data.get(key));
|
||||
return res;
|
||||
}
|
||||
public void Delete(DBObject o) throws Exception {
|
||||
DBTable table = tables.get(o.getClass());
|
||||
delete(table, o);
|
||||
table.Data.remove(o.getPK());
|
||||
}
|
||||
public void DeleteAll(Class<? extends DBObject> c) throws Exception {
|
||||
DBTable table = tables.get(c);
|
||||
deleteAll(table);
|
||||
table.Data.clear();
|
||||
}
|
||||
//не вполне обычный случай. подразумевается что поле объекта изменено
|
||||
//этот же метод закрепляет изменение в бд
|
||||
//в дальнейшем возможно сделать новое значение поля 2 параметром метода?
|
||||
public void Update(DBObject o) throws Exception {
|
||||
DBTable table = tables.get(o.getClass());
|
||||
update(table, o);
|
||||
}
|
||||
public void ResetAI(Class<? extends DBObject> c) throws Exception {
|
||||
resetAI(tables.get(c));
|
||||
}
|
||||
//</editor-fold>
|
||||
//<editor-fold desc="работа с внешними ключами">
|
||||
public <O extends DBObject, F extends DBObject> Vector<DBObject> getVectorByFK(O owner, Class<F> fk_class) {
|
||||
Vector<DBObject> res = new Vector<>();
|
||||
try {
|
||||
for (Object o : tables.get(fk_class).Data.values()) {
|
||||
if (fk_class.getField(owner.getFKName()).get(o).equals(owner.getPK())) res.add((DBObject) o);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Global.Log.PrintException(e);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
public <F extends DBObject> void DeleteByFK(DBObject master, Class<F> fk_class) throws Exception {
|
||||
Vector<DBObject> to_delete = getVectorByFK(master, fk_class);
|
||||
BeginTransaction();
|
||||
for (DBObject object : to_delete)
|
||||
Delete(object);
|
||||
Commit();
|
||||
}
|
||||
//-----------
|
||||
public <F extends DBObject> void DropByFK(DBObject master, Class<F> fk_class) throws Exception {
|
||||
Vector<DBObject> to_drop = getVectorByFK(master, fk_class);
|
||||
BeginTransaction();
|
||||
for (DBObject object : to_drop) {
|
||||
fk_class.getField(master.getFKName()).set(object, master.getEmptyFK());
|
||||
Update(object);
|
||||
}
|
||||
Commit();
|
||||
}
|
||||
public <K, O extends DBObject, F extends DBObject> LinkedHashMap<K, F> getMapByFK(O owner, Class<F> fk_class, Class<K> key_class) {
|
||||
LinkedHashMap<K, F> res = new LinkedHashMap<>();
|
||||
try {
|
||||
for (Object o : tables.get(fk_class).Data.values()) {
|
||||
F f = (F) o;
|
||||
if (fk_class.getField(owner.getFKName()).get(f).equals(owner.getPK())) res.put((K) f.getPK(), f);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Global.Log.PrintException(e);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
public <O extends DBObject, F extends iDBObject> LinkedHashMap<Integer, F> getMapByFKi(O owner, Class<F> fk_class) {
|
||||
return getMapByFK(owner, fk_class, java.lang.Integer.class);
|
||||
}
|
||||
//-
|
||||
public <O extends DBObject, F extends DBObject> Vector<String> getVectorStringByFK(O owner, Class<F> fk_class) {
|
||||
Vector<String> res = new Vector<>();
|
||||
try {
|
||||
for (Object o : tables.get(fk_class).Data.values()) {
|
||||
if (fk_class.getField(owner.getFKName()).get(o).equals(owner.getPK())) res.add(o.toString());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Global.Log.PrintException(e);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
//безопасное получение объекта по первичному ключу.
|
||||
public <O extends DBObject> O getByPK(Class<O> class_in, Object pk, Object undefined_pk) {
|
||||
return ((!pk.equals(undefined_pk)) && tables.get(class_in).Data.containsKey(pk)) ?
|
||||
(O) (tables.get(class_in).Data.get(pk)) : null;
|
||||
}
|
||||
public <O extends iDBObject> O getById(Class<O> class_in, int pk) {
|
||||
return getByPK(class_in, pk, Utils.Nan);
|
||||
}
|
||||
public <G, O extends DBObject, F extends DBObject> LinkedHashMap<G, F> getByFKAndGroupBy(O owner, Class<F> fk_class, String group_field, Class<G> group_class) {
|
||||
LinkedHashMap<G, F> res = new LinkedHashMap<>();
|
||||
try {
|
||||
for (Object o : tables.get(fk_class).Data.values()) {
|
||||
F f = (F) o;
|
||||
if (fk_class.getField(owner.getFKName()).get(f).equals(owner.getPK()))
|
||||
res.put((G) (fk_class.getField(group_field).get(f)), f);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Global.Log.PrintException(e);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
//</editor-fold>
|
||||
//<editor-fold desc="Перегружаемая часть">
|
||||
//-
|
||||
protected abstract void connect() throws Exception;
|
||||
protected abstract void disconnect() throws Exception;
|
||||
//-
|
||||
protected abstract void beginTransaction() throws Exception;
|
||||
protected abstract void commit() throws Exception;
|
||||
//-
|
||||
protected abstract boolean TableExists(DBTable table) throws Exception;
|
||||
protected abstract void CreateTable(DBTable table) throws Exception;
|
||||
protected abstract <K, D extends DBObject> void loadAll(DBTable<K, D> table) throws Exception;
|
||||
protected abstract void initAllTables() throws Exception;
|
||||
//перегружаемая часть синхронизации
|
||||
public void Init() throws Exception {
|
||||
}
|
||||
protected abstract void insert(DBTable table, DBObject o) throws Exception;
|
||||
protected abstract void delete(DBTable table, DBObject o) throws Exception;
|
||||
protected abstract void deleteAll(DBTable table) throws Exception;
|
||||
protected abstract void update(DBTable table, DBObject o) throws Exception;
|
||||
protected abstract void resetAI(DBTable table) throws Exception;
|
||||
//-
|
||||
public void SaveLastSelections() {
|
||||
for (DataSet dataSet : tables.values())
|
||||
dataSet.SaveLastSelections();
|
||||
}
|
||||
public void RestoreLastSelections() {
|
||||
for (DataSet dataSet : tables.values())
|
||||
dataSet.RestoreLastSelections();
|
||||
}
|
||||
}
|
||||
9
src/Common/Database/FKBehaviour.java
Normal file
9
src/Common/Database/FKBehaviour.java
Normal file
@@ -0,0 +1,9 @@
|
||||
package Common.Database;
|
||||
public class FKBehaviour {
|
||||
public FKDataBehaviour data; //поведение данных внешнего ключа при удалении/модификации
|
||||
public FKCurrentObjectBehaviuor ui; //поведение интерфейсов таблиц внешнего ключа при показе текущего объекта.
|
||||
public FKBehaviour(FKDataBehaviour data_in, FKCurrentObjectBehaviuor ui_in) {
|
||||
data = data_in;
|
||||
ui = ui_in;
|
||||
}
|
||||
}
|
||||
5
src/Common/Database/FKCurrentObjectBehaviuor.java
Normal file
5
src/Common/Database/FKCurrentObjectBehaviuor.java
Normal file
@@ -0,0 +1,5 @@
|
||||
package Common.Database;
|
||||
public enum FKCurrentObjectBehaviuor {
|
||||
PASSIVE,
|
||||
ACTIVE
|
||||
}
|
||||
7
src/Common/Database/FKDataBehaviour.java
Normal file
7
src/Common/Database/FKDataBehaviour.java
Normal file
@@ -0,0 +1,7 @@
|
||||
package Common.Database;
|
||||
//поведение таблиц имеющих внешние ключи
|
||||
public enum FKDataBehaviour {
|
||||
NONE,
|
||||
DROP,
|
||||
DELETE
|
||||
}
|
||||
261
src/Common/Database/SQLITE/SQLiteDatabase.java
Normal file
261
src/Common/Database/SQLITE/SQLiteDatabase.java
Normal file
@@ -0,0 +1,261 @@
|
||||
package Common.Database.SQLITE;
|
||||
import Common.Database.DBObject;
|
||||
import Common.Database.DBTable;
|
||||
import Common.Database.DBTableColumn;
|
||||
import Common.Database.Database;
|
||||
import Common.UI.UI;
|
||||
import Common.Utils.Utils;
|
||||
import Visual_DVM_2021.Passes.PassException;
|
||||
import javafx.util.Pair;
|
||||
|
||||
import java.io.File;
|
||||
import java.sql.*;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Vector;
|
||||
|
||||
import static Common.Utils.Utils.requireNonNullElse;
|
||||
public abstract class SQLiteDatabase extends Database {
|
||||
protected Connection conn = null;
|
||||
protected Statement statement = null;
|
||||
protected ResultSet resSet = null;
|
||||
public LinkedHashMap<Class<? extends DBObject>, PreparedStatement> insertStatements = new LinkedHashMap<>();
|
||||
public LinkedHashMap<Class<? extends DBObject>, PreparedStatement> updateStatements = new LinkedHashMap<>();
|
||||
public LinkedHashMap<Class<? extends DBObject>, PreparedStatement> deleteStatements = new LinkedHashMap<>();
|
||||
//->>
|
||||
public SQLiteDatabase(File file_in) {
|
||||
super(file_in);
|
||||
}
|
||||
@Override
|
||||
protected void connect() throws Exception {
|
||||
Class.forName("org.sqlite.JDBC");
|
||||
for (int i = 0; i < 5; ++i) {
|
||||
try {
|
||||
conn = DriverManager.getConnection("jdbc:sqlite:" + file.getAbsolutePath());
|
||||
break;
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
conn = null;
|
||||
System.gc();
|
||||
Utils.sleep(2000);
|
||||
}
|
||||
}
|
||||
if (conn == null)
|
||||
throw new PassException("Внутренняя ошибка sqlite. Не удалось установить соединение за 5 попыток.");
|
||||
statement = conn.createStatement();
|
||||
}
|
||||
@Override
|
||||
protected void disconnect() throws Exception {
|
||||
if (conn != null) {
|
||||
conn.close();
|
||||
conn = null;
|
||||
}
|
||||
if (statement != null) {
|
||||
statement.close();
|
||||
statement = null;
|
||||
}
|
||||
if (resSet != null) {
|
||||
resSet.close();
|
||||
resSet = null;
|
||||
}
|
||||
for (PreparedStatement preparedStatement : insertStatements.values()) {
|
||||
if (preparedStatement != null)
|
||||
preparedStatement.close();
|
||||
}
|
||||
for (PreparedStatement preparedStatement : updateStatements.values()) {
|
||||
if (preparedStatement != null)
|
||||
preparedStatement.close();
|
||||
}
|
||||
for (PreparedStatement preparedStatement : deleteStatements.values()) {
|
||||
if (preparedStatement != null)
|
||||
preparedStatement.close();
|
||||
}
|
||||
insertStatements.clear();
|
||||
updateStatements.clear();
|
||||
deleteStatements.clear();
|
||||
//-->>
|
||||
System.gc();
|
||||
//->>
|
||||
}
|
||||
@Override
|
||||
protected void beginTransaction() throws Exception {
|
||||
conn.setAutoCommit(false);
|
||||
}
|
||||
@Override
|
||||
protected void commit() throws Exception {
|
||||
conn.commit();
|
||||
conn.setAutoCommit(true);
|
||||
}
|
||||
@Override
|
||||
protected boolean TableExists(DBTable table) throws Exception {
|
||||
int count = 0;
|
||||
resSet = statement.executeQuery("SELECT count(*) FROM 'sqlite_master' WHERE type=\"table\" AND name=" + table.QName());
|
||||
if (resSet.next())
|
||||
count = resSet.getInt(1);
|
||||
return count > 0;
|
||||
}
|
||||
@Override
|
||||
public void CreateTable(DBTable table) throws Exception {
|
||||
if (table.columns.size() > 0) {
|
||||
if (TableExists(table)) {
|
||||
Vector<String> existing_columns = new Vector<>();
|
||||
Vector<String> columns_to_create = new Vector<>();
|
||||
//предполагаем что первичный ключ и атрибуты не изменятся.
|
||||
//и что не будет столбов с одинаковыми именами но разными типами.
|
||||
resSet = statement.executeQuery("pragma table_info(" + table.QName() + ")");
|
||||
while (resSet.next())
|
||||
existing_columns.add(resSet.getString(2));
|
||||
//-
|
||||
for (String target_column : table.columns.keySet()) {
|
||||
if (!existing_columns.contains(target_column))
|
||||
columns_to_create.add(target_column);
|
||||
}
|
||||
for (String cn : columns_to_create)
|
||||
statement.execute("ALTER TABLE " + table.QName() + " ADD COLUMN " + table.columns.get(cn));
|
||||
} else {
|
||||
String cmd = "CREATE TABLE if not exists " + table.QName() + " ";
|
||||
Vector<String> columns_names = new Vector<>();
|
||||
for (DBTableColumn column : table.columns.values())
|
||||
columns_names.add(column.toString());
|
||||
cmd += Utils.RBrackets(String.join(",", columns_names));
|
||||
statement.execute(cmd);
|
||||
}
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void prepareTablesStatements() throws Exception {
|
||||
for (DBTable table : tables.values()) {
|
||||
//---
|
||||
Vector<String> column_names = new Vector<>();
|
||||
Vector<String> column_values = new Vector<>();
|
||||
for (DBTableColumn column : table.columns.values()) {
|
||||
if (!column.AutoIncrement) {
|
||||
column_names.add(column.QName());
|
||||
column_values.add("?");
|
||||
}
|
||||
}
|
||||
insertStatements.put(table.d, conn.prepareStatement(
|
||||
"INSERT OR REPLACE INTO " + table.QName() + " " +
|
||||
Utils.RBrackets(String.join(",", column_names)) + " " + "VALUES " +
|
||||
Utils.RBrackets(String.join(",", column_values))));
|
||||
//------------------------------------------------------------------------------->>
|
||||
Vector<String> new_values = new Vector();
|
||||
for (DBTableColumn column : table.columns.values()) {
|
||||
if (!column.AutoIncrement) {
|
||||
new_values.add(column.QName() + "=?");
|
||||
}
|
||||
}
|
||||
updateStatements.put(table.d, conn.prepareStatement(
|
||||
"UPDATE " + table.QName() + " " +
|
||||
"SET " + String.join(",", new_values) + " " +
|
||||
"WHERE (" + table.PK.QName() + "=?)"
|
||||
));
|
||||
//---------------------------------------------------------------------------------->>>
|
||||
deleteStatements.put(table.d, conn.prepareStatement("DELETE FROM " + table.QName() + " WHERE " + table.PK.QName() + " = ?"));
|
||||
}
|
||||
}
|
||||
@Override
|
||||
protected void delete(DBTable table, DBObject o) throws Exception {
|
||||
PreparedStatement ps = deleteStatements.get(table.d);
|
||||
ps.setObject(1, o.getPK());
|
||||
ps.executeUpdate();
|
||||
}
|
||||
protected <K, D extends DBObject> Pair<K, D> readRecord(DBTable<K, D> table) throws Exception {
|
||||
D o = table.d.newInstance();
|
||||
for (DBTableColumn column : table.columns.values()) {
|
||||
Object field_value = null;
|
||||
switch (column.type) {
|
||||
case DOUBLE:
|
||||
field_value = requireNonNullElse(resSet.getDouble(column.Name), 0);
|
||||
break;
|
||||
case UNDEFINED:
|
||||
break;
|
||||
case INT:
|
||||
field_value = requireNonNullElse(resSet.getInt(column.Name), 0);
|
||||
break;
|
||||
case LONG:
|
||||
field_value = requireNonNullElse(resSet.getLong(column.Name), 0);
|
||||
break;
|
||||
case STRING:
|
||||
if (table.d.getField(column.Name).getType().isEnum()) {
|
||||
Class enum_class = Class.forName(table.d.getField(column.Name).getType().getName());
|
||||
String string = resSet.getString(column.Name);
|
||||
Object[] enum_constants = enum_class.getEnumConstants();
|
||||
if (string != null) {
|
||||
try {
|
||||
field_value = Enum.valueOf(enum_class, string);
|
||||
} catch (Exception ignore) {
|
||||
System.out.println(Utils.Brackets(string) + "not found");
|
||||
field_value = enum_constants[0];
|
||||
System.out.println(field_value);
|
||||
}
|
||||
} else field_value = enum_constants[0];
|
||||
} else
|
||||
field_value = requireNonNullElse(resSet.getString(column.Name), "");
|
||||
break;
|
||||
}
|
||||
if (field_value != null) {
|
||||
table.d.getField(column.Name).set(o, field_value);
|
||||
} else
|
||||
throw new PassException("Ошибка при загрузке поля " + Utils.Brackets(column.Name) + " класса " + Utils.Brackets(table.d.getSimpleName()));
|
||||
}
|
||||
return new Pair<>((K) o.getPK(), o);
|
||||
}
|
||||
@Override
|
||||
protected <K, D extends DBObject> void loadAll(DBTable<K, D> table) throws Exception {
|
||||
resSet = statement.executeQuery("SELECT * FROM " + table.QName());
|
||||
while (resSet.next()) {
|
||||
Pair<K, D> record = readRecord(table);
|
||||
table.Data.put(record.getKey(), record.getValue());
|
||||
}
|
||||
}
|
||||
@Override
|
||||
protected void insert(DBTable table, DBObject o) throws Exception {
|
||||
PreparedStatement ps = insertStatements.get(table.d);
|
||||
if (ps == null)
|
||||
UI.Info("INSERT NULL");
|
||||
int i = 1;
|
||||
for (DBTableColumn column : table.columns.values()) {
|
||||
if (!column.AutoIncrement) {
|
||||
ps.setObject(i, o.getClass().getField(column.Name).get(o));
|
||||
++i;
|
||||
}
|
||||
}
|
||||
ps.execute();
|
||||
//-->
|
||||
for (DBTableColumn column : table.columns.values()) {
|
||||
if (column.AutoIncrement) {
|
||||
resSet = statement.executeQuery("SELECT MAX(" + column.QName() + ") AS LAST FROM " + table.QName());
|
||||
String maxId = resSet.getString("LAST");
|
||||
int intMaxId = Integer.parseInt(maxId);
|
||||
o.getClass().getField(column.Name).set(o, intMaxId);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@Override
|
||||
protected void update(DBTable table, DBObject o) throws Exception {
|
||||
PreparedStatement ps = updateStatements.get(table.d);
|
||||
if (ps == null)
|
||||
UI.Info("UPDATE NULL");
|
||||
int i = 1;
|
||||
for (DBTableColumn column : table.columns.values()) {
|
||||
if (!column.AutoIncrement) {
|
||||
ps.setObject(i, o.getClass().getField(column.Name).get(o));
|
||||
++i;
|
||||
}
|
||||
}
|
||||
ps.setObject(i, o.getPK());
|
||||
ps.executeUpdate();
|
||||
}
|
||||
@Override
|
||||
protected void deleteAll(DBTable table) throws Exception {
|
||||
statement.executeUpdate("DELETE FROM " + table.QName());
|
||||
}
|
||||
@Override
|
||||
protected void resetAI(DBTable table) throws Exception {
|
||||
statement.executeUpdate("UPDATE SQLITE_SEQUENCE SET SEQ = 0 WHERE NAME =" + table.QName());
|
||||
}
|
||||
//--
|
||||
//https://stackoverflow.com/questions/8558099/sqlite-query-with-byte-where-clause
|
||||
|
||||
}
|
||||
43
src/Common/Database/TableFilter.java
Normal file
43
src/Common/Database/TableFilter.java
Normal file
@@ -0,0 +1,43 @@
|
||||
package Common.Database;
|
||||
import Common.UI.Menus_2023.StableMenuItem;
|
||||
import Common.Utils.Utils;
|
||||
|
||||
import javax.swing.*;
|
||||
public class TableFilter<D extends DBObject> {
|
||||
DataSet table;
|
||||
public JMenuItem menuItem; //пункт меню фильтра. ( возможно потом сделать и кнопку)
|
||||
String description;
|
||||
boolean active = false; //включен ли фильтр
|
||||
public int count = 0;
|
||||
protected boolean validate(D object) {
|
||||
return true;
|
||||
}
|
||||
public boolean Validate(D object) {
|
||||
boolean valid;
|
||||
if (valid=validate(object))
|
||||
count++;
|
||||
return !active || valid;
|
||||
}
|
||||
static String getNotActiveIconPath() {
|
||||
return "/icons/NotPick.png";
|
||||
}
|
||||
static String getActiveIconPath() {
|
||||
return "/icons/Pick.png";
|
||||
}
|
||||
public TableFilter(DataSet table_in, String description_in) {
|
||||
table = table_in;
|
||||
menuItem = new StableMenuItem((description = description_in)+" (0)");
|
||||
menuItem.addActionListener(e -> {
|
||||
active = !active;
|
||||
Mark();
|
||||
table.ShowUI();
|
||||
});
|
||||
Mark();
|
||||
}
|
||||
public void Mark() {
|
||||
menuItem.setIcon(Utils.getIcon(active ? getActiveIconPath() : getNotActiveIconPath()));
|
||||
}
|
||||
public void ShowDescriptionAndCount() {
|
||||
menuItem.setText(description + " " + Utils.RBrackets(count));
|
||||
}
|
||||
}
|
||||
30
src/Common/Database/iDBObject.java
Normal file
30
src/Common/Database/iDBObject.java
Normal file
@@ -0,0 +1,30 @@
|
||||
package Common.Database;
|
||||
import Common.Utils.Utils;
|
||||
import com.sun.org.glassfish.gmbal.Description;
|
||||
//автоинкрементальный ключ
|
||||
public class iDBObject extends DBObject {
|
||||
@Description("PRIMARY KEY,AUTOINCREMENT")
|
||||
public int id;
|
||||
@Override
|
||||
public Object getPK() {
|
||||
return id;
|
||||
}
|
||||
@Override
|
||||
public String getFKName() {
|
||||
return getClass().getSimpleName().toLowerCase() + "_id";
|
||||
}
|
||||
@Override
|
||||
public Object getEmptyFK() {
|
||||
return Utils.Nan;
|
||||
}
|
||||
//---
|
||||
@Override
|
||||
public void SynchronizeFields(DBObject src) {
|
||||
super.SynchronizeFields(src);
|
||||
id = ((iDBObject)src).id;
|
||||
}
|
||||
public iDBObject(){}
|
||||
public iDBObject(iDBObject src){
|
||||
this.SynchronizeFields(src);
|
||||
}
|
||||
}
|
||||
6
src/Common/Database/iDBTable.java
Normal file
6
src/Common/Database/iDBTable.java
Normal file
@@ -0,0 +1,6 @@
|
||||
package Common.Database;
|
||||
public abstract class iDBTable<D extends iDBObject> extends DBTable<Integer, D> {
|
||||
public iDBTable(Class<D> d_in) {
|
||||
super(Integer.class, d_in);
|
||||
}
|
||||
}
|
||||
35
src/Common/Database/nDBObject.java
Normal file
35
src/Common/Database/nDBObject.java
Normal file
@@ -0,0 +1,35 @@
|
||||
package Common.Database;
|
||||
import Common.Utils.Utils;
|
||||
import com.sun.org.glassfish.gmbal.Description;
|
||||
public abstract class nDBObject extends DBObject {
|
||||
String getClassNameL() {
|
||||
return getClass().getSimpleName().toLowerCase();
|
||||
}
|
||||
@Description("PRIMARY KEY, UNIQUE")
|
||||
public String id = "";
|
||||
@Override
|
||||
public Object getPK() {
|
||||
return id;
|
||||
}
|
||||
@Override
|
||||
public String getFKName() {
|
||||
return getClassNameL() + "_id";
|
||||
}
|
||||
@Override
|
||||
public Object getEmptyFK() {
|
||||
return "";
|
||||
}
|
||||
public void genName() {
|
||||
id = Utils.getDateName(getClassNameL());
|
||||
}
|
||||
//-
|
||||
@Override
|
||||
public void SynchronizeFields(DBObject src) {
|
||||
super.SynchronizeFields(src);
|
||||
id = ((nDBObject)src).id;
|
||||
}
|
||||
public nDBObject(nDBObject src){
|
||||
this.SynchronizeFields(src);
|
||||
}
|
||||
public nDBObject(){}
|
||||
}
|
||||
32
src/Common/Database/rDBObject.java
Normal file
32
src/Common/Database/rDBObject.java
Normal file
@@ -0,0 +1,32 @@
|
||||
package Common.Database;
|
||||
import java.util.Date;
|
||||
//объект репозитория. ключ имя, и есть данные отправителя.
|
||||
public class rDBObject extends nDBObject {
|
||||
public String sender_name = "";
|
||||
public String sender_address = "";
|
||||
public String description = "";
|
||||
//-
|
||||
public long date = 0;
|
||||
public long change_date;
|
||||
public Date getDate() {
|
||||
return new Date(date);
|
||||
}
|
||||
public Date getChangeDate() {
|
||||
return new Date(change_date);
|
||||
}
|
||||
@Override
|
||||
public void SynchronizeFields(DBObject src) {
|
||||
super.SynchronizeFields(src);
|
||||
rDBObject r = (rDBObject) src;
|
||||
sender_name = r.sender_name;
|
||||
sender_address = r.sender_address;
|
||||
description = r.description;
|
||||
date = r.date;
|
||||
change_date = r.change_date;
|
||||
}
|
||||
public rDBObject(rDBObject src) {
|
||||
this.SynchronizeFields(src);
|
||||
}
|
||||
public rDBObject() {
|
||||
}
|
||||
}
|
||||
403
src/Common/Global.java
Normal file
403
src/Common/Global.java
Normal file
@@ -0,0 +1,403 @@
|
||||
package Common;
|
||||
import Common.Database.DataSet;
|
||||
import Common.UI.Menus_2023.ComponentsMenuBar.ComponentsMenuBar;
|
||||
import Common.UI.UI;
|
||||
import Common.Utils.Utils;
|
||||
import GlobalData.GlobalDatabase;
|
||||
import GlobalData.Settings.DBSetting;
|
||||
import GlobalData.Settings.SettingName;
|
||||
import ProjectData.ProjectView;
|
||||
import Repository.Component.*;
|
||||
import Repository.Component.PerformanceAnalyzer.PerformanceAnalyzer;
|
||||
import Repository.Component.Sapfor.MessagesServer;
|
||||
import Repository.Component.Sapfor.Sapfor_F;
|
||||
import Repository.Component.Sapfor.TransformationPermission;
|
||||
import Repository.Server.ComponentsServer;
|
||||
import TestingSystem.TestingServer;
|
||||
import Visual_DVM_2021.Passes.All.PerformSapforTasksPackage;
|
||||
import Visual_DVM_2021.Passes.PassCode_2021;
|
||||
import Visual_DVM_2021.Passes.Pass_2021;
|
||||
import Visual_DVM_2021.UI.Interface.Loggable;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.fife.ui.rsyntaxtextarea.AbstractTokenMakerFactory;
|
||||
import org.fife.ui.rsyntaxtextarea.TokenMakerFactory;
|
||||
|
||||
import java.io.File;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Vector;
|
||||
public class Global {
|
||||
//кронтаб и перезагрузка
|
||||
//https://snipp.ru/raznoe/crontab
|
||||
// /var/spool/cron/crontabs/testuser что менять
|
||||
//https://saribzhanov.ru/tehno/perezagruzka-ubuntu-po-cron/ //раз в сутки
|
||||
//testuser ALL=NOPASSWD:/sbin/reboot
|
||||
//0 2 2,15 * * reboot &>/var/log/reboot.log
|
||||
//https://unix.stackexchange.com/questions/117148/how-can-i-run-reboot-as-a-normal-user-without-needing-to-enter-a-password
|
||||
public static final String ServerAddress = "alex-freenas.ddns.net";
|
||||
public static final String MailAddress = "sapfor.tracker@internet.ru";
|
||||
// public static final String MailPassword = "3s4w9e5fs3c1a89AA"; основной пароль.
|
||||
public static final String MailPassword = "knKn2PpfrC348ZxHtMnT"; //пароль для сапфора как внешнего приложения.
|
||||
public static final String dateNaN = "NaN";
|
||||
//--------------------------------------------------
|
||||
//текущая папка системы. в отличие от шарпа никогда не должна меняться.
|
||||
public static final String components = "Components";
|
||||
public static final String data = "Data";
|
||||
public static final String Bugs = "Bugs";
|
||||
public static final String BackUps = "BackUps";
|
||||
public static final String DataBackUps = "DataBackUps";
|
||||
public static final String Temp = "Temp";
|
||||
public static final String Projects = "Projects";
|
||||
public static final String CompilationTasks = "CompilationTasks";
|
||||
public static final String RunTasks = "RunTasks";
|
||||
public static final String Sts = "Sts";
|
||||
public static final String Repo = "Repo";
|
||||
public static final String Tests = "Tests";
|
||||
public static final String Packages = "Packages";
|
||||
public static final String PerformanceAnalyzer = "PerformanceAnalyzer";
|
||||
public static GlobalProperties properties = new GlobalProperties();
|
||||
//</editor-fold>
|
||||
//------------------------------------------------------
|
||||
public static boolean enable_text_changed = false;
|
||||
//---
|
||||
public static boolean files_multiselection = false;
|
||||
public static boolean versions_multiselection = false;
|
||||
//---
|
||||
public static TransformationPermission transformationPermission = TransformationPermission.None;
|
||||
//??
|
||||
public static DataSet<ComponentType, Component> Components = null;
|
||||
public static MessagesServer messagesServer = null;
|
||||
//--------------------------------------------------
|
||||
public static GlobalDatabase db = null;
|
||||
public static String[] admins_mails = new String[]{
|
||||
"vmk-post@yandex.ru",
|
||||
"79854210702@ya.ru"
|
||||
};
|
||||
//-
|
||||
public static String Home;
|
||||
public static File ComponentsDirectory;
|
||||
public static File DataDirectory;
|
||||
public static File BugReportsDirectory;
|
||||
public static File BackUpsDirectory;
|
||||
public static File TempDirectory;
|
||||
public static File ProjectsDirectory;
|
||||
public static File CompilationTasksDirectory;
|
||||
public static File RunTasksDirectory;
|
||||
public static File StsDirectory;
|
||||
public static File RepoDirectory;
|
||||
public static File TestsDirectory;
|
||||
public static File PerformanceAnalyzerDirectory;
|
||||
public static File DataBackUpsDirectory;
|
||||
public static File PackagesDirectory;
|
||||
public static File SapforPackagesDirectory;
|
||||
//------------------------------------------------------------------
|
||||
public static Visualiser visualiser = null;
|
||||
public static Visualizer_2 visualizer_2 = null;
|
||||
public static PerformanceAnalyzer performanceAnalyzer = null;
|
||||
//------------------------------------------------------------------
|
||||
public static ComponentsServer componentsServer = new ComponentsServer();
|
||||
public static TestingServer testingServer = new TestingServer();
|
||||
//------------------------------------------------------------------
|
||||
public static boolean isWindows;
|
||||
public static int bad_state = 0;
|
||||
public static int need_update = 0;
|
||||
public static int need_publish = 0;
|
||||
//------------------------------------------------------------------------
|
||||
public static Loggable Log;
|
||||
public static void SynschronizeProperties() {
|
||||
//---- NEW -----
|
||||
try {
|
||||
File new_propertiesFile = Paths.get(Home, "properties").toFile();
|
||||
if (new_propertiesFile.exists()) {
|
||||
String packed = FileUtils.readFileToString(new_propertiesFile, Charset.defaultCharset());
|
||||
properties = Utils.gson.fromJson(packed, GlobalProperties.class);
|
||||
}
|
||||
//пусть всегда в него пишет. с учетом того, что новые настройки могут появиться.
|
||||
FileUtils.writeStringToFile(new_propertiesFile, Utils.jsonToPrettyFormat(Utils.gson.toJson(properties)));
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
public static void CheckVisualiserDirectories() {
|
||||
Utils.CheckDirectory(ComponentsDirectory = Paths.get(Home, components).toFile());
|
||||
Utils.CheckAndCleanDirectory(TempDirectory = Paths.get(Home, Temp).toFile());
|
||||
Utils.CheckDirectory(DataDirectory = Paths.get(Home, data).toFile());
|
||||
//-
|
||||
Utils.CheckDirectory(RepoDirectory = Paths.get(Home, Repo).toFile());
|
||||
Utils.CheckDirectory(BugReportsDirectory = Paths.get(Home, Bugs).toFile());
|
||||
Utils.CheckDirectory(BackUpsDirectory = Paths.get(Home, BackUps).toFile());
|
||||
Utils.CheckDirectory(ProjectsDirectory = Paths.get(Home, Projects).toFile());
|
||||
Utils.CheckDirectory(CompilationTasksDirectory = Paths.get(Home, CompilationTasks).toFile());
|
||||
Utils.CheckDirectory(RunTasksDirectory = Paths.get(Home, RunTasks).toFile());
|
||||
Utils.CheckDirectory(StsDirectory = Paths.get(Home, Sts).toFile());
|
||||
Utils.CheckDirectory(TestsDirectory = Paths.get(Home, Tests).toFile());
|
||||
Utils.CheckDirectory(PerformanceAnalyzerDirectory = Paths.get(Home, PerformanceAnalyzer).toFile());
|
||||
Utils.CheckDirectory(SapforPackagesDirectory = Paths.get(Home, "SapforTasksPackages").toFile());
|
||||
}
|
||||
public static void CheckServerDirectories() {
|
||||
Utils.CheckDirectory(ComponentsDirectory = Paths.get(Home, components).toFile());
|
||||
Utils.CheckAndCleanDirectory(TempDirectory = Paths.get(Home, Temp).toFile());
|
||||
Utils.CheckDirectory(DataDirectory = Paths.get(Home, data).toFile());
|
||||
//-
|
||||
Utils.CheckDirectory(BugReportsDirectory = Paths.get(Home, Bugs).toFile());
|
||||
Utils.CheckDirectory(DataBackUpsDirectory = Paths.get(Home, DataBackUps).toFile());
|
||||
}
|
||||
public static void CheckTestingSystemDirectories() {
|
||||
Utils.CheckDirectory(ComponentsDirectory = Paths.get(Home, components).toFile());
|
||||
Utils.CheckAndCleanDirectory(TempDirectory = Paths.get(Home, Temp).toFile());
|
||||
Utils.CheckDirectory(DataDirectory = Paths.get(Home, data).toFile());
|
||||
//-
|
||||
Utils.CheckDirectory(TestsDirectory = Paths.get(Home, Tests).toFile());
|
||||
Utils.CheckDirectory(RepoDirectory = Paths.get(Home, Repo).toFile());
|
||||
Utils.CheckDirectory(PackagesDirectory = Paths.get(Home, Packages).toFile());
|
||||
}
|
||||
public static void CreateLog() {
|
||||
Log = new Loggable() {
|
||||
@Override
|
||||
public String getLogHomePath() {
|
||||
return Paths.get(Home, "Components").toString();
|
||||
}
|
||||
@Override
|
||||
public String getLogName() {
|
||||
return "VisualDVM";
|
||||
}
|
||||
};
|
||||
Log.ClearLog();
|
||||
}
|
||||
//-
|
||||
public static void FinishApplication() {
|
||||
try {
|
||||
if (db != null) db.Disconnect();
|
||||
if (componentsServer.db != null)
|
||||
componentsServer.db.Disconnect();
|
||||
if (testingServer.db != null)
|
||||
testingServer.db.Disconnect();
|
||||
if (visualizer_2 != null)
|
||||
visualizer_2.Shutdown();
|
||||
if (messagesServer != null)
|
||||
messagesServer.Shutdown();
|
||||
if (performanceAnalyzer != null)
|
||||
performanceAnalyzer.Shutdown();
|
||||
} catch (Exception ex) {
|
||||
if (Log != null) {
|
||||
Log.PrintException(ex);
|
||||
} else {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
System.exit(0);
|
||||
}
|
||||
public static void ActivateDB() throws Exception {
|
||||
db = new GlobalDatabase();
|
||||
db.Connect();
|
||||
db.CreateAllTables();
|
||||
db.prepareTablesStatements();
|
||||
db.Synchronize();
|
||||
}
|
||||
public static void RefreshUpdatesStatus() {
|
||||
Components.RefreshUI();
|
||||
ValidateComponentsStates();
|
||||
if (UI.HasNewMainWindow())
|
||||
UI.getMainWindow().ShowUpdatesIcon();
|
||||
}
|
||||
public static boolean ValidateComponentsStates() {
|
||||
bad_state = need_update = need_publish = 0;
|
||||
for (Component component : Components.Data.values()) {
|
||||
if (component.isVisible()) {
|
||||
switch (component.getState()) {
|
||||
case Not_found:
|
||||
case Unknown_version:
|
||||
case Old_version:
|
||||
if (component.isNecessary())
|
||||
bad_state++;
|
||||
component.Select(true);
|
||||
break;
|
||||
case Needs_update:
|
||||
need_update++;
|
||||
component.Select(true);
|
||||
break;
|
||||
case Needs_publish:
|
||||
need_publish++;
|
||||
break;
|
||||
default:
|
||||
component.Select(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return (bad_state == 0);
|
||||
}
|
||||
public static DBSetting getSetting(SettingName settingName) throws Exception {
|
||||
switch (Current.mode) {
|
||||
case Normal:
|
||||
return db.settings.get(settingName);
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
public static void changeSetting(SettingName settingName, Object new_value) throws Exception {
|
||||
Pass_2021.passes.get(PassCode_2021.UpdateSetting).Do(settingName, new_value);
|
||||
}
|
||||
public static String packSapforSettings() {
|
||||
Vector<String> res_ = new Vector<>();
|
||||
Vector<SettingName> forbidden = new Vector<>();
|
||||
forbidden.add(SettingName.GCOVLimit);
|
||||
forbidden.add(SettingName.Precompilation);
|
||||
forbidden.add(SettingName.DVMConvertationOptions);
|
||||
forbidden.add(SettingName.SaveModifications);
|
||||
for (DBSetting setting : db.settings.getSettingsByOwner(ComponentType.SapforOptions)) {
|
||||
if (!forbidden.contains(setting.Name))
|
||||
res_.add(setting.Value);
|
||||
}
|
||||
return String.join("|", res_);
|
||||
}
|
||||
//--
|
||||
public static void NormalMode(int port) throws Exception {
|
||||
isWindows = System.getProperty("os.name").startsWith("Windows");
|
||||
CheckVisualiserDirectories();
|
||||
CreateLog();
|
||||
//-
|
||||
visualizer_2 = new Visualizer_2(port);
|
||||
visualizer_2.Connect();
|
||||
visualizer_2.refreshPid();
|
||||
//если делать раньше, то не удастся убить сервер.
|
||||
if (Utils.ContainsCyrillic(Global.Home)) {
|
||||
UI.Info("В пути к корневой папке " + Utils.DQuotes(Global.Home) + "\n" +
|
||||
"Найдены русские буквы.\n" +
|
||||
"Визуализатор завершает работу."); //
|
||||
FinishApplication();
|
||||
}
|
||||
messagesServer = new MessagesServer();
|
||||
messagesServer.Start();
|
||||
//создание списков служебных объектов
|
||||
Current.CreateAll();
|
||||
UI.CreateAll();
|
||||
Pass_2021.CreateAll();
|
||||
Utils.init();
|
||||
//единственное меню до остальных.
|
||||
UI.menuBars.put(ComponentsSet.class, new ComponentsMenuBar());
|
||||
Components = new ComponentsSet();
|
||||
Current.set(Current.ProjectView, ProjectView.Files);
|
||||
Components.put(ComponentType.Visualiser, visualiser = new Visualiser());
|
||||
Components.put(ComponentType.Sapfor_F, (Component) Current.set(Current.Sapfor, new Sapfor_F()));
|
||||
Components.put(ComponentType.Visualizer_2, visualizer_2);
|
||||
Components.put(ComponentType.PerformanceAnalyzer, performanceAnalyzer = new PerformanceAnalyzer());
|
||||
Components.put(ComponentType.Instruction, new Instruction());
|
||||
//-
|
||||
for (Component component : Components.Data.values())
|
||||
if (component.isVisible()) component.InitialVersionCheck();
|
||||
//-
|
||||
UI.CreateComponentsForm();
|
||||
AbstractTokenMakerFactory atmf = (AbstractTokenMakerFactory) TokenMakerFactory.getDefaultInstance();
|
||||
atmf.putMapping("text/FortranSPF", "Common.UI.Themes.FortranSPFTokenMaker");
|
||||
atmf.putMapping("text/FreeFortranSPF", "Common.UI.Themes.FreeFortranSPFTokenMaker");
|
||||
// FoldParserManager.get().addFoldParserMapping("text/FortranSPF", new FortranFolder()); блоки кода. todo
|
||||
//-------->>
|
||||
//-------->>
|
||||
if (properties.AutoUpdateSearch)
|
||||
Pass_2021.passes.get(PassCode_2021.GetComponentsActualVersions).Do();
|
||||
ValidateComponentsStates();
|
||||
if ((need_update > 0) || (bad_state > 0)) {
|
||||
boolean flag = true;
|
||||
do {
|
||||
UI.ShowComponentsWindow();
|
||||
if (flag = (!ValidateComponentsStates())) {
|
||||
if (!UI.Question("Найдено " + bad_state + " некорректных необходимых компонент.Работа визуализатора невозможна.\n" +
|
||||
"Вернуться к окну компонент"
|
||||
)) {
|
||||
UI.Info("Визуализатор завершает работу.");
|
||||
FinishApplication();
|
||||
}
|
||||
}
|
||||
} while (flag);
|
||||
}
|
||||
//---
|
||||
ActivateDB(); //тут current getAccount; роль по умолчанию всегда неизвестна.
|
||||
///--------------
|
||||
Pass_2021.passes.get(PassCode_2021.CheckAccount).Do();
|
||||
//---------------
|
||||
componentsServer.ActivateDB();
|
||||
testingServer.ActivateDB();
|
||||
//-- чисто чтобы создать таблицы. соединения на стороне клиента не предвидится.
|
||||
testingServer.SetCurrentAccountDB(Current.getAccount().email);
|
||||
//--->>>
|
||||
if (db.settings.get(SettingName.AutoBugReportsLoad).toBoolean())
|
||||
Pass_2021.passes.get(PassCode_2021.SynchronizeBugReports).Do();
|
||||
//--
|
||||
if (db.settings.get(SettingName.AutoTestsLoad).toBoolean())
|
||||
Pass_2021.passes.get(PassCode_2021.SynchronizeTests).Do();
|
||||
Pass_2021.CheckAllStats();
|
||||
Current.getSapfor().refreshPid(); //без сапфора сюда это все равно не дойдет.
|
||||
UI.CreateMenus();
|
||||
UI.CreateWindows();
|
||||
}
|
||||
public static void ServerMode() throws Exception {
|
||||
isWindows = false;
|
||||
CheckServerDirectories();
|
||||
CreateLog();
|
||||
componentsServer = new ComponentsServer();
|
||||
componentsServer.ActivateDB();
|
||||
componentsServer.Start();
|
||||
System.exit(0);
|
||||
}
|
||||
public static void TestingSystemMode() throws Exception {
|
||||
isWindows = false;
|
||||
CheckTestingSystemDirectories();
|
||||
CreateLog();
|
||||
testingServer = new TestingServer();
|
||||
testingServer.ActivateDB();
|
||||
testingServer.Start();
|
||||
System.exit(0);
|
||||
}
|
||||
public static void PackageMode() throws Exception {
|
||||
Log = new Loggable() {
|
||||
@Override
|
||||
public String getLogHomePath() {
|
||||
return Home;
|
||||
}
|
||||
@Override
|
||||
public String getLogName() {
|
||||
return "PackageMode";
|
||||
}
|
||||
};
|
||||
Log.ClearLog();
|
||||
//--
|
||||
Pass_2021 pass = new PerformSapforTasksPackage();
|
||||
pass.Do(Home);
|
||||
//--
|
||||
}
|
||||
//---
|
||||
public static void Init(String... args) {
|
||||
System.out.println("VisualSapfor.jar started..");
|
||||
Home = System.getProperty("user.dir"); //если Linux, дает без слеша в конце !!!
|
||||
System.out.println("home directory is" + Utils.Brackets(Home));
|
||||
//---
|
||||
SynschronizeProperties();
|
||||
Current.mode = properties.Mode;
|
||||
System.out.println("mode is " + Current.mode);
|
||||
try {
|
||||
switch (Current.mode) {
|
||||
case Normal:
|
||||
NormalMode(Integer.parseInt(args[1]));
|
||||
break;
|
||||
case Server:
|
||||
ServerMode();
|
||||
break;
|
||||
case Testing:
|
||||
TestingSystemMode();
|
||||
break;
|
||||
case Package:
|
||||
PackageMode();
|
||||
break;
|
||||
case Undefined:
|
||||
break;
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
System.out.println("VISUALISER FAILED");
|
||||
ex.printStackTrace();
|
||||
if (Global.Log != null)
|
||||
Global.Log.PrintException(ex);
|
||||
FinishApplication();
|
||||
}
|
||||
}
|
||||
}
|
||||
87
src/Common/GlobalProperties.java
Normal file
87
src/Common/GlobalProperties.java
Normal file
@@ -0,0 +1,87 @@
|
||||
package Common;
|
||||
import com.google.gson.annotations.Expose;
|
||||
|
||||
import java.io.File;
|
||||
import java.nio.file.Paths;
|
||||
public class GlobalProperties extends Properties {
|
||||
@Expose
|
||||
public Current.Mode Mode = Current.Mode.Normal;
|
||||
//---
|
||||
@Expose
|
||||
public int SocketTimeout = 5000;
|
||||
@Expose
|
||||
public boolean OldServer = false;
|
||||
//---
|
||||
@Expose
|
||||
public String SMTPHost = "smtp.mail.ru";
|
||||
@Expose
|
||||
public int SMTPPort = 465;
|
||||
@Expose
|
||||
public int MailSocketPort = 465;
|
||||
//---
|
||||
@Expose
|
||||
public String BackupWorkspace = "_sapfor_x64_backups";
|
||||
@Expose
|
||||
public int BackupHour = 5;
|
||||
@Expose
|
||||
public int BackupMinute = 0;
|
||||
@Expose
|
||||
public boolean EmailAdminsOnStart = false;
|
||||
//---
|
||||
@Expose
|
||||
public boolean AutoUpdateSearch = true;
|
||||
// настройки визуализатора. по крайней мере, флаги.
|
||||
@Expose
|
||||
public boolean ConfirmPassesStart = true;
|
||||
@Expose
|
||||
public boolean ShowPassesDone = true;
|
||||
@Expose
|
||||
public boolean FocusPassesResult = true;
|
||||
//-
|
||||
@Expose
|
||||
public String GlobalDBName = "db7.sqlite";
|
||||
@Expose
|
||||
public String ProjectDBName = "new_project_base.sqlite";
|
||||
@Expose
|
||||
public String BugReportsDBName = "bug_reports.sqlite";
|
||||
@Expose
|
||||
public String TestsDBName = "tests.sqlite";
|
||||
//-
|
||||
@Expose
|
||||
public int ComponentsWindowWidth = 650;
|
||||
@Expose
|
||||
public int ComponentsWindowHeight = 250;
|
||||
//-
|
||||
@Expose
|
||||
public String VisualiserPath = "";
|
||||
@Expose
|
||||
public String Sapfor_FPath = "";
|
||||
@Expose
|
||||
public String Visualizer_2Path = "";
|
||||
@Expose
|
||||
public String InstructionPath = "";
|
||||
@Expose
|
||||
public String PerformanceAnalyzerPath = "";
|
||||
@Expose
|
||||
public int ComponentsBackUpsCount=10;
|
||||
@Expose
|
||||
public long SapforTaskMaxId = 0; //вероятно, временно. когда перейдем на удаленную машину.
|
||||
//-
|
||||
@Override
|
||||
public String getFieldDescription(String fieldName) {
|
||||
switch (fieldName) {
|
||||
case "ShowPassesDone":
|
||||
return "Сообщать об успешном выполнении проходов";
|
||||
case "ConfirmPassesStart":
|
||||
return "Запрашивать подтверждения начала выполнения проходов";
|
||||
case "FocusPassesResult":
|
||||
return "Переходить на результирующую вкладку проходов по их завершении";
|
||||
default:
|
||||
return "?";
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public File getFile() {
|
||||
return Paths.get(System.getProperty("user.dir"),"properties").toFile();
|
||||
}
|
||||
}
|
||||
3
src/Common/PackageModeSupervisor.java
Normal file
3
src/Common/PackageModeSupervisor.java
Normal file
@@ -0,0 +1,3 @@
|
||||
package Common;
|
||||
public class PackageModeSupervisor {
|
||||
}
|
||||
50
src/Common/Properties.java
Normal file
50
src/Common/Properties.java
Normal file
@@ -0,0 +1,50 @@
|
||||
package Common;
|
||||
import Common.UI.Menus_2023.StableMenuItem;
|
||||
import Common.Utils.Utils;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.io.File;
|
||||
public abstract class Properties {
|
||||
public void addFlagMenuItem(JMenu menu, String fieldName) {
|
||||
JMenuItem menu_item = new StableMenuItem(getFieldDescription(fieldName),
|
||||
getFlag(fieldName) ? "/icons/Pick.png" : "/icons/NotPick.png");
|
||||
//-
|
||||
menu_item.addActionListener(e -> {
|
||||
switchFlag(fieldName);
|
||||
Update();
|
||||
menu_item.setIcon(Utils.getIcon(getFlag(fieldName) ? "/icons/Pick.png" : "/icons/NotPick.png"));
|
||||
});
|
||||
menu.add(menu_item);
|
||||
}
|
||||
public boolean getFlag(String fieldName) {
|
||||
boolean field = false;
|
||||
try {
|
||||
field = (boolean) GlobalProperties.class.getField(fieldName).get(this);
|
||||
//
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
return field;
|
||||
}
|
||||
public void switchFlag(String fieldName) {
|
||||
boolean field = false;
|
||||
try {
|
||||
field = (boolean) GlobalProperties.class.getField(fieldName).get(this);
|
||||
GlobalProperties.class.getField(fieldName).set(this, !field);
|
||||
//
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
public void Update() {
|
||||
try {
|
||||
FileUtils.write(getFile(), Utils.jsonToPrettyFormat(Utils.gson.toJson(this)));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
//--
|
||||
public abstract String getFieldDescription(String fieldName);
|
||||
public abstract File getFile();
|
||||
}
|
||||
9
src/Common/UI/ComboBox/StyledTextComboBox.java
Normal file
9
src/Common/UI/ComboBox/StyledTextComboBox.java
Normal file
@@ -0,0 +1,9 @@
|
||||
package Common.UI.ComboBox;
|
||||
import Common.UI.Menus.TextComboBoxMenu;
|
||||
|
||||
import javax.swing.*;
|
||||
public class StyledTextComboBox extends JComboBox<String> {
|
||||
public StyledTextComboBox() {
|
||||
setComponentPopupMenu(new TextComboBoxMenu(this));
|
||||
}
|
||||
}
|
||||
53
src/Common/UI/ControlForm.java
Normal file
53
src/Common/UI/ControlForm.java
Normal file
@@ -0,0 +1,53 @@
|
||||
package Common.UI;
|
||||
import Common.Global;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
//класс, представляющий собой прокручиваемую панель, на которой лежит нечто.
|
||||
public class ControlForm<C extends Component> {
|
||||
public C control = null;
|
||||
protected Class<C> control_class;
|
||||
protected JPanel content; //задник.
|
||||
public JScrollPane scroll = null;
|
||||
public ControlForm(Class<C> class_in) {
|
||||
control_class = class_in;
|
||||
setContent(new JPanel(new BorderLayout()));
|
||||
}
|
||||
//нужно будет вывестии сделать нормальные формы для деревьев а не ручное создание.
|
||||
public JPanel getContent() {
|
||||
return content;
|
||||
}
|
||||
public void setContent(JPanel content_in) {
|
||||
|
||||
content = content_in;
|
||||
}
|
||||
//-
|
||||
public void Show() {
|
||||
Clear();
|
||||
CreateControl();
|
||||
//------------------------
|
||||
scroll = new JScrollPane(control);
|
||||
scroll.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED);
|
||||
scroll.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
|
||||
}
|
||||
public void CreateControl() {
|
||||
try {
|
||||
control = control_class.newInstance();
|
||||
} catch (Exception e) {
|
||||
Global.Log.PrintException(e);
|
||||
}
|
||||
}
|
||||
public boolean isShown() {
|
||||
return control != null;
|
||||
}
|
||||
public void Clear() {
|
||||
control = null; //очищено.
|
||||
}
|
||||
public void Refresh() {
|
||||
if (control != null)
|
||||
refresh();
|
||||
}
|
||||
//-
|
||||
protected void refresh() {
|
||||
} //перерисовать контрол.
|
||||
}
|
||||
19
src/Common/UI/ControlWithCurrentForm.java
Normal file
19
src/Common/UI/ControlWithCurrentForm.java
Normal file
@@ -0,0 +1,19 @@
|
||||
package Common.UI;
|
||||
import Common.Current;
|
||||
|
||||
import java.awt.*;
|
||||
public class ControlWithCurrentForm<C extends Component> extends ControlForm<C> {
|
||||
public ControlWithCurrentForm(Class<C> class_in) {
|
||||
super(class_in);
|
||||
}
|
||||
//-
|
||||
public Current CurrentName() {
|
||||
return Current.Undefined;
|
||||
}
|
||||
public void ShowCurrentObject() throws Exception {
|
||||
}
|
||||
public void ShowNoCurrentObject() throws Exception {
|
||||
}
|
||||
public void MouseAction2() throws Exception {
|
||||
}
|
||||
}
|
||||
7
src/Common/UI/DataControl.java
Normal file
7
src/Common/UI/DataControl.java
Normal file
@@ -0,0 +1,7 @@
|
||||
package Common.UI;
|
||||
import Common.Database.DBObject;
|
||||
public interface DataControl {
|
||||
DBObject getRowObject(int rowIndex); //получить объект, сответствующий данной строке.
|
||||
void SelectRowByPK(Object pk);
|
||||
//выделить строку где лежит объект с данным первичным ключом.
|
||||
}
|
||||
13
src/Common/UI/DataControl_OLD.java
Normal file
13
src/Common/UI/DataControl_OLD.java
Normal file
@@ -0,0 +1,13 @@
|
||||
package Common.UI;
|
||||
import Common.Current;
|
||||
public interface DataControl_OLD {
|
||||
//todo скорее всего устареет.
|
||||
default Current getCurrent() {
|
||||
return Current.Undefined;
|
||||
}
|
||||
//-?
|
||||
default void ShowCurrentObject() throws Exception {
|
||||
}
|
||||
default void ShowNoCurrentObject() throws Exception {
|
||||
}
|
||||
}
|
||||
329
src/Common/UI/DataSetControlForm.java
Normal file
329
src/Common/UI/DataSetControlForm.java
Normal file
@@ -0,0 +1,329 @@
|
||||
package Common.UI;
|
||||
import Common.Current;
|
||||
import Common.Database.DBObject;
|
||||
import Common.Database.DBTable;
|
||||
import Common.Database.DataSet;
|
||||
import Common.Database.FKBehaviour;
|
||||
import Common.Global;
|
||||
import Common.UI.Menus.TableMenu;
|
||||
import Common.UI.Tables.ColumnInfo;
|
||||
import Common.UI.Tables.DataTable;
|
||||
import Common.UI.Tables.Grid.GridAnchestor;
|
||||
import Common.Utils.Utils;
|
||||
import GlobalData.Grid.Grid;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.table.TableColumn;
|
||||
import java.awt.*;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.util.Arrays;
|
||||
import java.util.Vector;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
import static Common.UI.Tables.TableEditors.EditorSelect;
|
||||
import static Common.UI.Tables.TableRenderers.RendererSelect;
|
||||
public class DataSetControlForm extends ControlWithCurrentForm<DataTable> {
|
||||
protected JPanel dataPanel;
|
||||
protected DataSet dataSource;
|
||||
public JPanel getDataPanel() {
|
||||
return dataPanel;
|
||||
}
|
||||
protected int current_row_i;
|
||||
protected boolean events_on = true;
|
||||
protected String colNamesAndSizes = "";
|
||||
protected Vector<ColumnInfo> columns = new Vector<>();
|
||||
public DataSetControlForm(DataSet dataSource_in) {
|
||||
this(dataSource_in, DataTable.class);
|
||||
}
|
||||
public DataSetControlForm(DataSet dataSource_in, Class tableClass) {
|
||||
super(tableClass);
|
||||
dataSource = dataSource_in;
|
||||
//---
|
||||
dataPanel = new JPanel(new BorderLayout());
|
||||
content.add(dataPanel, BorderLayout.CENTER);
|
||||
}
|
||||
@Override
|
||||
public void Show() {
|
||||
super.Show();
|
||||
dataPanel.add(scroll);
|
||||
dataPanel.updateUI();
|
||||
}
|
||||
@Override
|
||||
public void Clear() {
|
||||
super.Clear();
|
||||
UI.Clear(dataPanel);
|
||||
}
|
||||
public DataSet getDataSource() {
|
||||
return dataSource;
|
||||
}
|
||||
@Override
|
||||
public Current CurrentName() {
|
||||
return getDataSource().CurrentName();
|
||||
}
|
||||
public void SaveColumns() {
|
||||
if (Global.db != null) {
|
||||
try {
|
||||
if ((CurrentName() != Current.Undefined)) {
|
||||
Vector<String> widths = IntStream.range(0, columns.size()).mapToObj(i -> String.valueOf(control.getColumnModel().getColumn(i).getWidth())).collect(Collectors.toCollection(Vector::new));
|
||||
String packed = String.join("|", widths);
|
||||
Grid grid;
|
||||
if (Global.db.grids.containsKey(CurrentName())) {
|
||||
grid = Global.db.grids.get(CurrentName());
|
||||
} else {
|
||||
grid = new Grid(CurrentName());
|
||||
Global.db.Insert(grid);
|
||||
}
|
||||
grid.sizes = packed;
|
||||
Global.db.Update(grid);
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
public boolean hasCheckBox() {
|
||||
return false;
|
||||
}
|
||||
private Vector<String> getHeaders() {
|
||||
return columns.stream().map(ColumnInfo::getName).collect(Collectors.toCollection(Vector::new));
|
||||
}
|
||||
protected void CreateColumnsInfo() {
|
||||
columns.clear();
|
||||
columns.add(new ColumnInfo(getDataSource().getPKName()));
|
||||
if (hasCheckBox()) {
|
||||
columns.add(new ColumnInfo("", RendererSelect, EditorSelect));
|
||||
columns.get(1).setMinWidth(25);
|
||||
columns.get(1).setMaxWidth(25);
|
||||
}
|
||||
Arrays.stream(getDataSource().getUIColumnNames()).forEach(name -> columns.add(new ColumnInfo(name)));
|
||||
AdditionalInitColumns();
|
||||
}
|
||||
protected void AdditionalInitColumns() {
|
||||
//уточнение инфы по столбцам.
|
||||
}
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public void CreateControl() {
|
||||
CreateColumnsInfo();
|
||||
GridAnchestor table_data_model = new GridAnchestor(getHeaders(), dataSource.getVisibleKeys()) {
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public Object getValueAt(int rowIndex, int columnIndex) {
|
||||
Object key = data.get(rowIndex);
|
||||
if (columnIndex == 0)
|
||||
return key;
|
||||
DBObject object = getDataSource().get((key));
|
||||
if ((columnIndex == 1) && hasCheckBox())
|
||||
return object.isSelected();
|
||||
return getDataSource().getFieldAt(object, columnIndex);
|
||||
}
|
||||
@Override
|
||||
public boolean isCellEditable(int row, int col) {
|
||||
return columns.get(col).isEditable();
|
||||
}
|
||||
//------------------------------------------------------------------------------------
|
||||
@Override
|
||||
public void setValueAt(Object value, int row, int col) {
|
||||
fireTableCellUpdated(row, col);
|
||||
}
|
||||
};
|
||||
control = new DataTable(table_data_model) {
|
||||
@Override
|
||||
public TableMenu CreateMenu() {
|
||||
return new TableMenu(this);
|
||||
}
|
||||
//строго говоря эта штука нужна только для рендереров и едиторов клеток.
|
||||
@Override
|
||||
public DBObject getRowObject(int rowIndex) {
|
||||
//вот так делать НЕЛЬЗЯ. модель только для внутреннего пользования
|
||||
// Object key = table_data_model.data.get(rowIndex);
|
||||
//из таблицы можно пользоваться только getValueAt
|
||||
//иначе сортировка не будет работать.
|
||||
Object key = getValueAt(rowIndex, 0);
|
||||
return getDataSource().get(key);
|
||||
}
|
||||
//-----------------------------NEW-------------------------------------
|
||||
@Override
|
||||
public void CorrectColumnsSizes() {
|
||||
if ((Global.db != null) && CurrentName() != Current.Undefined && Global.db.grids.containsKey(CurrentName())) {
|
||||
//Undefined может оказаться в таблице, например если енум устарел. Поэтому надо проверять.
|
||||
if (!getColumnsProfile().equalsIgnoreCase(colNamesAndSizes)) {
|
||||
Grid grid = Global.db.grids.get(CurrentName());
|
||||
String[] data = grid.sizes.split("\\|");
|
||||
for (int i = 0; i < columns.size(); ++i) {
|
||||
if (i <= (data.length - 1)) {
|
||||
int width = Integer.parseInt(data[i]);
|
||||
getColumnModel().getColumn(i).setPreferredWidth(width);
|
||||
getColumnModel().getColumn(i).setWidth(width);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else
|
||||
super.CorrectColumnsSizes(); //обычный авторазмер.
|
||||
}
|
||||
public String getColumnsProfile() {
|
||||
String res = "";
|
||||
for (int i = 0; i < getColumnModel().getColumnCount(); i++) {
|
||||
if (i > 0) res += ",";
|
||||
TableColumn column = getColumnModel().getColumn(i);
|
||||
res += column.getHeaderValue();
|
||||
res += ":";
|
||||
res += column.getWidth();
|
||||
}
|
||||
return res;
|
||||
}
|
||||
@Override
|
||||
public void Init() {
|
||||
for (int i = 0; i < columns.size(); i++) {
|
||||
ColumnInfo columnInfo = columns.get(i);
|
||||
if (columnInfo.isVisible()) {
|
||||
if (columnInfo.hasRenderer())
|
||||
getColumnModel().getColumn(i).setCellRenderer(UI.TableRenderers.get(columnInfo.getRenderer()));
|
||||
if (columnInfo.hasEditor())
|
||||
getColumnModel().getColumn(i).setCellEditor(UI.TableEditors.get(columnInfo.getEditor()));
|
||||
if (columnInfo.hasMaxWidth())
|
||||
getColumnModel().getColumn((i)).setMaxWidth(columnInfo.getMaxWidth());
|
||||
if (columnInfo.hasMinWidth())
|
||||
getColumnModel().getColumn((i)).setMinWidth(columnInfo.getMinWidth());
|
||||
} else {
|
||||
getColumnModel().getColumn(i).setMinWidth(0);
|
||||
getColumnModel().getColumn(i).setMaxWidth(0);
|
||||
}
|
||||
}
|
||||
//обновление в БД при ручном изменении размера столбиков.--------->>
|
||||
getTableHeader().addMouseListener(new MouseAdapter() {
|
||||
public void mouseReleased(MouseEvent arg0) {
|
||||
System.out.println("Header mouse released");
|
||||
String new_colNamesAndSizes = getColumnsProfile();
|
||||
// check if changed, if yes, persist...
|
||||
if (!colNamesAndSizes.equals(new_colNamesAndSizes)) {
|
||||
colNamesAndSizes = new_colNamesAndSizes;
|
||||
SaveColumns();
|
||||
System.out.println("columns updated");
|
||||
}
|
||||
}
|
||||
});
|
||||
//------------------------->>
|
||||
}
|
||||
};
|
||||
if (CurrentName() != Current.Undefined) {
|
||||
current_row_i = Utils.Nan;
|
||||
ListSelectionModel selModel = control.getSelectionModel();
|
||||
selModel.addListSelectionListener(e -> {
|
||||
int row = control.getSelectedRow();
|
||||
if ((row >= 0)) {
|
||||
if (row != current_row_i) {
|
||||
current_row_i = row;
|
||||
// System.out.println("current row_i="+current_row_i);
|
||||
getDataSource().setCurrent(control.getRowObject(row));
|
||||
if (events_on) {
|
||||
try {
|
||||
ShowCurrentObject();
|
||||
} catch (Exception ex) {
|
||||
Global.Log.PrintException(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
current_row_i = Utils.Nan;
|
||||
// System.out.println("no current row_i="+current_row_i);
|
||||
getDataSource().dropCurrent();
|
||||
if (events_on) {
|
||||
try {
|
||||
ShowNoCurrentObject();
|
||||
} catch (Exception ex) {
|
||||
Global.Log.PrintException(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
//двойной клик мыши.------------------------------------------------------
|
||||
control.addMouseListener(new MouseAdapter() {
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent e) {
|
||||
if ((e.getClickCount() == 2) && (dataSource.getCurrent() != null)) {
|
||||
try {
|
||||
MouseAction2();
|
||||
} catch (Exception ex) {
|
||||
Global.Log.PrintException(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
//----------------------------------------------------------------------------
|
||||
//при переотображении таблицы скидываем текущий объект!!
|
||||
getDataSource().dropCurrent();
|
||||
try {
|
||||
ShowNoCurrentObject();
|
||||
} catch (Exception e) {
|
||||
Global.Log.PrintException(e);
|
||||
}
|
||||
}
|
||||
//---
|
||||
/*
|
||||
if (hasCheckBox()) {
|
||||
TableColumn column = control.getColumnModel().getColumn(1)
|
||||
column.setHeaderRenderer(new TableCellRenderer() {
|
||||
@Override
|
||||
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
|
||||
return null;
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
*/
|
||||
}
|
||||
@Override
|
||||
protected void refresh() {
|
||||
control.CorrectSizes();
|
||||
}
|
||||
public void Show(Object pk) {
|
||||
Show();
|
||||
Select(pk);
|
||||
}
|
||||
public void Select(Object pk) {
|
||||
if (isShown())
|
||||
control.SelectRowByPK(pk);
|
||||
}
|
||||
public void ClearSelection() {
|
||||
if (isShown())
|
||||
control.clearSelection(); //строка сбросится сама. благодаря сбросу события выбора
|
||||
}
|
||||
public int getRowCount() {
|
||||
return control.getRowCount();
|
||||
}
|
||||
@Override
|
||||
public void ShowCurrentObject() throws Exception {
|
||||
if (dataSource instanceof DBTable) {
|
||||
DBTable table = (DBTable) dataSource;
|
||||
for (Class dep : table.getFKDependencies().keySet()) {
|
||||
FKBehaviour behaviour = table.getFKDependencies().get(dep);
|
||||
switch (behaviour.ui) {
|
||||
case ACTIVE:
|
||||
table.getDb().tables.get(dep).ShowUI();
|
||||
break;
|
||||
case PASSIVE:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void ShowNoCurrentObject() throws Exception {
|
||||
if (dataSource instanceof DBTable) {
|
||||
DBTable table = (DBTable) dataSource;
|
||||
for (Class dep : table.getFKDependencies().keySet()) {
|
||||
FKBehaviour behaviour = table.getFKDependencies().get(dep);
|
||||
switch (behaviour.ui) {
|
||||
case ACTIVE:
|
||||
table.getDb().tables.get(dep).ClearUI();
|
||||
break;
|
||||
case PASSIVE:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
17
src/Common/UI/DebugPrintLevel.java
Normal file
17
src/Common/UI/DebugPrintLevel.java
Normal file
@@ -0,0 +1,17 @@
|
||||
package Common.UI;
|
||||
public enum DebugPrintLevel {
|
||||
Undefined,
|
||||
Passes,
|
||||
Project;
|
||||
public String getDescription() {
|
||||
return toString();
|
||||
}
|
||||
public boolean isEnabled() {
|
||||
switch (this) {
|
||||
case Passes:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
33
src/Common/UI/DragDrop/ExampleDrop.java
Normal file
33
src/Common/UI/DragDrop/ExampleDrop.java
Normal file
@@ -0,0 +1,33 @@
|
||||
package Common.UI.DragDrop;
|
||||
import javax.swing.*;
|
||||
/**
|
||||
* A simple example showing how to use {@link FileDrop}
|
||||
*
|
||||
* @author Robert Harder, rob@iharder.net
|
||||
*/
|
||||
public class ExampleDrop {
|
||||
/*
|
||||
/** Runs a sample program that shows dropped files */
|
||||
public static void kek(String[] args) {
|
||||
javax.swing.JFrame frame = new javax.swing.JFrame("FileDrop");
|
||||
//javax.swing.border.TitledBorder dragBorder = new javax.swing.border.TitledBorder( "Drop 'em" );
|
||||
final javax.swing.JTextArea text = new javax.swing.JTextArea();
|
||||
frame.getContentPane().add(
|
||||
new javax.swing.JScrollPane(text),
|
||||
java.awt.BorderLayout.CENTER);
|
||||
new FileDrop(System.out, text, /*dragBorder,*/ new FileDrop.Listener() {
|
||||
public void filesDropped(java.io.File[] files) {
|
||||
for (int i = 0; i < files.length; i++) {
|
||||
try {
|
||||
text.append(files[i].getCanonicalPath() + "\n");
|
||||
} // end try
|
||||
catch (java.io.IOException e) {
|
||||
}
|
||||
} // end for: through each dropped file
|
||||
} // end filesDropped
|
||||
}); // end FileDrop.Listener
|
||||
frame.setBounds(100, 100, 300, 400);
|
||||
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||
frame.setVisible(true);
|
||||
} // end main
|
||||
}
|
||||
792
src/Common/UI/DragDrop/FileDrop.java
Normal file
792
src/Common/UI/DragDrop/FileDrop.java
Normal file
@@ -0,0 +1,792 @@
|
||||
package Common.UI.DragDrop;
|
||||
import Common.Global;
|
||||
|
||||
import java.awt.datatransfer.DataFlavor;
|
||||
import java.io.*;
|
||||
/**
|
||||
* This class makes it easy to drag and drop files from the operating
|
||||
* system to a Java program. Any <tt>java.awt.Component</tt> can be
|
||||
* dropped onto, but only <tt>javax.swing.JComponent</tt>s will indicate
|
||||
* the drop event with a changed border.
|
||||
* <p/>
|
||||
* To use this class, construct a new <tt>FileDrop</tt> by passing
|
||||
* it the target component and a <tt>Listener</tt> to receive notification
|
||||
* when file(s) have been dropped. Here is an example:
|
||||
* <p/>
|
||||
* <code><pre>
|
||||
* JPanel myPanel = new JPanel();
|
||||
* new FileDrop( myPanel, new FileDrop.Listener()
|
||||
* { public void filesDropped( java.io.File[] files )
|
||||
* {
|
||||
* // handle file drop
|
||||
* ...
|
||||
* } // end filesDropped
|
||||
* }); // end FileDrop.Listener
|
||||
* </pre></code>
|
||||
* <p/>
|
||||
* You can specify the border that will appear when files are being dragged by
|
||||
* calling the constructor with a <tt>javax.swing.border.Border</tt>. Only
|
||||
* <tt>JComponent</tt>s will show any indication with a border.
|
||||
* <p/>
|
||||
* You can turn on some debugging features by passing a <tt>PrintStream</tt>
|
||||
* object (such as <tt>System.out</tt>) into the full constructor. A <tt>null</tt>
|
||||
* value will result in no extra debugging information being output.
|
||||
* <p/>
|
||||
*
|
||||
* <p>I'm releasing this code into the Public Domain. Enjoy.
|
||||
* </p>
|
||||
* <p><em>Original author: Robert Harder, rharder@usa.net</em></p>
|
||||
* <p>2007-09-12 Nathan Blomquist -- Linux (KDE/Gnome) support added.</p>
|
||||
*
|
||||
* @author Robert Harder
|
||||
* @author rharder@users.sf.net
|
||||
* @version 1.0.1
|
||||
*/
|
||||
public class FileDrop {
|
||||
// Default border color
|
||||
private static final java.awt.Color defaultBorderColor = new java.awt.Color(0f, 0f, 1f, 0.25f);
|
||||
// BEGIN 2007-09-12 Nathan Blomquist -- Linux (KDE/Gnome) support added.
|
||||
private static final String ZERO_CHAR_STRING = "" + (char) 0;
|
||||
/**
|
||||
* Discover if the running JVM is modern enough to have drag and drop.
|
||||
*/
|
||||
private static Boolean supportsDnD;
|
||||
private transient javax.swing.border.Border normalBorder;
|
||||
private transient java.awt.dnd.DropTargetListener dropListener;
|
||||
/**
|
||||
* Constructs a {@link FileDrop} with a default light-blue border
|
||||
* and, if <var>c</var> is a {@link java.awt.Container}, recursively
|
||||
* sets all elements contained within as drop targets, though only
|
||||
* the top level container will change borders.
|
||||
*
|
||||
* @param c Component on which files will be dropped.
|
||||
* @param listener Listens for <tt>filesDropped</tt>.
|
||||
* @since 1.0
|
||||
*/
|
||||
public FileDrop(
|
||||
final java.awt.Component c,
|
||||
final Listener listener) {
|
||||
this(null, // Logging stream
|
||||
c, // Drop target
|
||||
javax.swing.BorderFactory.createMatteBorder(2, 2, 2, 2, defaultBorderColor), // Drag border
|
||||
true, // Recursive
|
||||
listener);
|
||||
} // end constructor
|
||||
/**
|
||||
* Constructor with a default border and the option to recursively set drop targets.
|
||||
* If your component is a <tt>java.awt.Container</tt>, then each of its children
|
||||
* database.Objects.components will also listen for drops, though only the parent will change borders.
|
||||
*
|
||||
* @param c Component on which files will be dropped.
|
||||
* @param recursive Recursively set children as drop targets.
|
||||
* @param listener Listens for <tt>filesDropped</tt>.
|
||||
* @since 1.0
|
||||
*/
|
||||
public FileDrop(
|
||||
final java.awt.Component c,
|
||||
final boolean recursive,
|
||||
final Listener listener) {
|
||||
this(null, // Logging stream
|
||||
c, // Drop target
|
||||
javax.swing.BorderFactory.createMatteBorder(2, 2, 2, 2, defaultBorderColor), // Drag border
|
||||
recursive, // Recursive
|
||||
listener);
|
||||
} // end constructor
|
||||
/**
|
||||
* Constructor with a default border and debugging optionally turned on.
|
||||
* With Debugging turned on, more status messages will be displayed to
|
||||
* <tt>out</tt>. A common way to use this constructor is with
|
||||
* <tt>System.out</tt> or <tt>System.err</tt>. A <tt>null</tt> value for
|
||||
* the parameter <tt>out</tt> will result in no debugging output.
|
||||
*
|
||||
* @param out PrintStream to record debugging info or null for no debugging.
|
||||
* @param out
|
||||
* @param c Component on which files will be dropped.
|
||||
* @param listener Listens for <tt>filesDropped</tt>.
|
||||
* @since 1.0
|
||||
*/
|
||||
public FileDrop(
|
||||
final PrintStream out,
|
||||
final java.awt.Component c,
|
||||
final Listener listener) {
|
||||
this(out, // Logging stream
|
||||
c, // Drop target
|
||||
javax.swing.BorderFactory.createMatteBorder(2, 2, 2, 2, defaultBorderColor),
|
||||
false, // Recursive
|
||||
listener);
|
||||
} // end constructor
|
||||
/**
|
||||
* Constructor with a default border, debugging optionally turned on
|
||||
* and the option to recursively set drop targets.
|
||||
* If your component is a <tt>java.awt.Container</tt>, then each of its children
|
||||
* database.Objects.components will also listen for drops, though only the parent will change borders.
|
||||
* With Debugging turned on, more status messages will be displayed to
|
||||
* <tt>out</tt>. A common way to use this constructor is with
|
||||
* <tt>System.out</tt> or <tt>System.err</tt>. A <tt>null</tt> value for
|
||||
* the parameter <tt>out</tt> will result in no debugging output.
|
||||
*
|
||||
* @param out PrintStream to record debugging info or null for no debugging.
|
||||
* @param out
|
||||
* @param c Component on which files will be dropped.
|
||||
* @param recursive Recursively set children as drop targets.
|
||||
* @param listener Listens for <tt>filesDropped</tt>.
|
||||
* @since 1.0
|
||||
*/
|
||||
public FileDrop(
|
||||
final PrintStream out,
|
||||
final java.awt.Component c,
|
||||
final boolean recursive,
|
||||
final Listener listener) {
|
||||
this(out, // Logging stream
|
||||
c, // Drop target
|
||||
javax.swing.BorderFactory.createMatteBorder(2, 2, 2, 2, defaultBorderColor), // Drag border
|
||||
recursive, // Recursive
|
||||
listener);
|
||||
} // end constructor
|
||||
/**
|
||||
* Constructor with a specified border
|
||||
*
|
||||
* @param c Component on which files will be dropped.
|
||||
* @param dragBorder Border to use on <tt>JComponent</tt> when dragging occurs.
|
||||
* @param listener Listens for <tt>filesDropped</tt>.
|
||||
* @since 1.0
|
||||
*/
|
||||
public FileDrop(
|
||||
final java.awt.Component c,
|
||||
final javax.swing.border.Border dragBorder,
|
||||
final Listener listener) {
|
||||
this(
|
||||
null, // Logging stream
|
||||
c, // Drop target
|
||||
dragBorder, // Drag border
|
||||
false, // Recursive
|
||||
listener);
|
||||
} // end constructor
|
||||
/**
|
||||
* Constructor with a specified border and the option to recursively set drop targets.
|
||||
* If your component is a <tt>java.awt.Container</tt>, then each of its children
|
||||
* database.Objects.components will also listen for drops, though only the parent will change borders.
|
||||
*
|
||||
* @param c Component on which files will be dropped.
|
||||
* @param dragBorder Border to use on <tt>JComponent</tt> when dragging occurs.
|
||||
* @param recursive Recursively set children as drop targets.
|
||||
* @param listener Listens for <tt>filesDropped</tt>.
|
||||
* @since 1.0
|
||||
*/
|
||||
public FileDrop(
|
||||
final java.awt.Component c,
|
||||
final javax.swing.border.Border dragBorder,
|
||||
final boolean recursive,
|
||||
final Listener listener) {
|
||||
this(
|
||||
null,
|
||||
c,
|
||||
dragBorder,
|
||||
recursive,
|
||||
listener);
|
||||
} // end constructor
|
||||
/**
|
||||
* Constructor with a specified border and debugging optionally turned on.
|
||||
* With Debugging turned on, more status messages will be displayed to
|
||||
* <tt>out</tt>. A common way to use this constructor is with
|
||||
* <tt>System.out</tt> or <tt>System.err</tt>. A <tt>null</tt> value for
|
||||
* the parameter <tt>out</tt> will result in no debugging output.
|
||||
*
|
||||
* @param out PrintStream to record debugging info or null for no debugging.
|
||||
* @param c Component on which files will be dropped.
|
||||
* @param dragBorder Border to use on <tt>JComponent</tt> when dragging occurs.
|
||||
* @param listener Listens for <tt>filesDropped</tt>.
|
||||
* @since 1.0
|
||||
*/
|
||||
public FileDrop(
|
||||
final PrintStream out,
|
||||
final java.awt.Component c,
|
||||
final javax.swing.border.Border dragBorder,
|
||||
final Listener listener) {
|
||||
this(
|
||||
out, // Logging stream
|
||||
c, // Drop target
|
||||
dragBorder, // Drag border
|
||||
false, // Recursive
|
||||
listener);
|
||||
} // end constructor
|
||||
/**
|
||||
* Full constructor with a specified border and debugging optionally turned on.
|
||||
* With Debugging turned on, more status messages will be displayed to
|
||||
* <tt>out</tt>. A common way to use this constructor is with
|
||||
* <tt>System.out</tt> or <tt>System.err</tt>. A <tt>null</tt> value for
|
||||
* the parameter <tt>out</tt> will result in no debugging output.
|
||||
*
|
||||
* @param out PrintStream to record debugging info or null for no debugging.
|
||||
* @param c Component on which files will be dropped.
|
||||
* @param dragBorder Border to use on <tt>JComponent</tt> when dragging occurs.
|
||||
* @param recursive Recursively set children as drop targets.
|
||||
* @param listener Listens for <tt>filesDropped</tt>.
|
||||
* @since 1.0
|
||||
*/
|
||||
public FileDrop(
|
||||
final PrintStream out,
|
||||
final java.awt.Component c,
|
||||
final javax.swing.border.Border dragBorder,
|
||||
final boolean recursive,
|
||||
final Listener listener) {
|
||||
if (supportsDnD()) { // Make a drop listener
|
||||
dropListener = new java.awt.dnd.DropTargetListener() {
|
||||
public void dragEnter(java.awt.dnd.DropTargetDragEvent evt) {
|
||||
log(out, "FileDrop: dragEnter event.");
|
||||
// Is this an acceptable drag event?
|
||||
if (isDragOk(out, evt)) {
|
||||
// If it's a Swing component, set its border
|
||||
if (c instanceof javax.swing.JComponent) {
|
||||
javax.swing.JComponent jc = (javax.swing.JComponent) c;
|
||||
normalBorder = jc.getBorder();
|
||||
log(out, "FileDrop: normal border saved.");
|
||||
jc.setBorder(dragBorder);
|
||||
log(out, "FileDrop: drag border set.");
|
||||
} // end if: JComponent
|
||||
// Acknowledge that it's okay to enter
|
||||
//evt.acceptDrag( java.awt.dnd.DnDConstants.ACTION_COPY_OR_MOVE );
|
||||
evt.acceptDrag(java.awt.dnd.DnDConstants.ACTION_COPY);
|
||||
log(out, "FileDrop: event accepted.");
|
||||
} // end if: drag ok
|
||||
else { // Reject the drag event
|
||||
evt.rejectDrag();
|
||||
log(out, "FileDrop: event rejected.");
|
||||
} // end else: drag not ok
|
||||
} // end dragEnter
|
||||
public void dragOver(java.awt.dnd.DropTargetDragEvent evt) { // This is called continually as long as the mouse is
|
||||
// over the drag target.
|
||||
} // end dragOver
|
||||
public void drop(java.awt.dnd.DropTargetDropEvent evt) {
|
||||
log(out, "FileDrop: drop event.");
|
||||
try { // Get whatever was dropped
|
||||
java.awt.datatransfer.Transferable tr = evt.getTransferable();
|
||||
// Is it a file list?
|
||||
if (tr.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {
|
||||
// Say we'll take it.
|
||||
//evt.acceptDrop ( java.awt.dnd.DnDConstants.ACTION_COPY_OR_MOVE );
|
||||
evt.acceptDrop(java.awt.dnd.DnDConstants.ACTION_COPY);
|
||||
log(out, "FileDrop: file list accepted.");
|
||||
// Get a useful list
|
||||
java.util.List fileList = (java.util.List)
|
||||
tr.getTransferData(DataFlavor.javaFileListFlavor);
|
||||
java.util.Iterator iterator = fileList.iterator();
|
||||
// Convert list to array
|
||||
File[] filesTemp = new File[fileList.size()];
|
||||
fileList.toArray(filesTemp);
|
||||
final File[] files = filesTemp;
|
||||
// Alert listener to drop.
|
||||
if (listener != null)
|
||||
listener.filesDropped(files);
|
||||
// Mark that drop is completed.
|
||||
evt.getDropTargetContext().dropComplete(true);
|
||||
log(out, "FileDrop: drop complete.");
|
||||
} // end if: file list
|
||||
else // this section will check for a reader flavor.
|
||||
{
|
||||
// Thanks, Nathan!
|
||||
// BEGIN 2007-09-12 Nathan Blomquist -- Linux (KDE/Gnome) support added.
|
||||
DataFlavor[] flavors = tr.getTransferDataFlavors();
|
||||
boolean handled = false;
|
||||
for (int zz = 0; zz < flavors.length; zz++) {
|
||||
if (flavors[zz].isRepresentationClassReader()) {
|
||||
// Say we'll take it.
|
||||
//evt.acceptDrop ( java.awt.dnd.DnDConstants.ACTION_COPY_OR_MOVE );
|
||||
evt.acceptDrop(java.awt.dnd.DnDConstants.ACTION_COPY);
|
||||
log(out, "FileDrop: reader accepted.");
|
||||
Reader reader = flavors[zz].getReaderForText(tr);
|
||||
BufferedReader br = new BufferedReader(reader);
|
||||
if (listener != null)
|
||||
listener.filesDropped(createFileArray(br, out));
|
||||
// Mark that drop is completed.
|
||||
evt.getDropTargetContext().dropComplete(true);
|
||||
log(out, "FileDrop: drop complete.");
|
||||
handled = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!handled) {
|
||||
log(out, "FileDrop: not a file list or reader - abort.");
|
||||
evt.rejectDrop();
|
||||
}
|
||||
// END 2007-09-12 Nathan Blomquist -- Linux (KDE/Gnome) support added.
|
||||
} // end else: not a file list
|
||||
} // end try
|
||||
catch (IOException io) {
|
||||
log(out, "FileDrop: IOException - abort:");
|
||||
Global.Log.PrintException(io);
|
||||
evt.rejectDrop();
|
||||
} // end catch IOException
|
||||
catch (java.awt.datatransfer.UnsupportedFlavorException ufe) {
|
||||
log(out, "FileDrop: UnsupportedFlavorException - abort:");
|
||||
Global.Log.PrintException(ufe);
|
||||
evt.rejectDrop();
|
||||
} // end catch: UnsupportedFlavorException
|
||||
finally {
|
||||
// If it's a Swing component, reset its border
|
||||
if (c instanceof javax.swing.JComponent) {
|
||||
javax.swing.JComponent jc = (javax.swing.JComponent) c;
|
||||
jc.setBorder(normalBorder);
|
||||
log(out, "FileDrop: normal border restored.");
|
||||
} // end if: JComponent
|
||||
} // end finally
|
||||
} // end drop
|
||||
public void dragExit(java.awt.dnd.DropTargetEvent evt) {
|
||||
log(out, "FileDrop: dragExit event.");
|
||||
// If it's a Swing component, reset its border
|
||||
if (c instanceof javax.swing.JComponent) {
|
||||
javax.swing.JComponent jc = (javax.swing.JComponent) c;
|
||||
jc.setBorder(normalBorder);
|
||||
log(out, "FileDrop: normal border restored.");
|
||||
} // end if: JComponent
|
||||
} // end dragExit
|
||||
public void dropActionChanged(java.awt.dnd.DropTargetDragEvent evt) {
|
||||
log(out, "FileDrop: dropActionChanged event.");
|
||||
// Is this an acceptable drag event?
|
||||
if (isDragOk(out, evt)) { //evt.acceptDrag( java.awt.dnd.DnDConstants.ACTION_COPY_OR_MOVE );
|
||||
evt.acceptDrag(java.awt.dnd.DnDConstants.ACTION_COPY);
|
||||
log(out, "FileDrop: event accepted.");
|
||||
} // end if: drag ok
|
||||
else {
|
||||
evt.rejectDrag();
|
||||
log(out, "FileDrop: event rejected.");
|
||||
} // end else: drag not ok
|
||||
} // end dropActionChanged
|
||||
}; // end DropTargetListener
|
||||
// Make the component (and possibly children) drop targets
|
||||
makeDropTarget(out, c, recursive);
|
||||
} // end if: supports dnd
|
||||
else {
|
||||
log(out, "FileDrop: Drag and drop is not supported with this JVM");
|
||||
} // end else: does not support DnD
|
||||
} // end constructor
|
||||
private static boolean supportsDnD() { // Static Boolean
|
||||
if (supportsDnD == null) {
|
||||
boolean support = false;
|
||||
try {
|
||||
Class arbitraryDndClass = Class.forName("java.awt.dnd.DnDConstants");
|
||||
support = true;
|
||||
} // end try
|
||||
catch (Exception e) {
|
||||
support = false;
|
||||
} // end catch
|
||||
supportsDnD = new Boolean(support);
|
||||
} // end if: first time through
|
||||
return supportsDnD.booleanValue();
|
||||
} // end supportsDnD
|
||||
private static File[] createFileArray(BufferedReader bReader, PrintStream out) {
|
||||
try {
|
||||
java.util.List list = new java.util.ArrayList();
|
||||
String line = null;
|
||||
while ((line = bReader.readLine()) != null) {
|
||||
try {
|
||||
// kde seems to append a 0 char to the end of the reader
|
||||
if (ZERO_CHAR_STRING.equals(line)) continue;
|
||||
File file = new File(new java.net.URI(line));
|
||||
list.add(file);
|
||||
} catch (Exception ex) {
|
||||
log(out, "Error with " + line + ": " + ex.getMessage());
|
||||
}
|
||||
}
|
||||
return (File[]) list.toArray(new File[list.size()]);
|
||||
} catch (IOException ex) {
|
||||
log(out, "FileDrop: IOException");
|
||||
}
|
||||
return new File[0];
|
||||
}
|
||||
/**
|
||||
* Outputs <tt>message</tt> to <tt>out</tt> if it's not null.
|
||||
*/
|
||||
private static void log(PrintStream out, String message) { // Log message if requested
|
||||
// if (out != null)
|
||||
// UI.Print(DebugPrintLevel.DragDrop, message);
|
||||
} // end log
|
||||
/**
|
||||
* Removes the drag-and-drop hooks from the component and optionally
|
||||
* from the all children. You should call this if you add and remove
|
||||
* database.Objects.components after you've set up the drag-and-drop.
|
||||
* This will recursively unregister all database.Objects.components contained within
|
||||
* <var>c</var> if <var>c</var> is a {@link java.awt.Container}.
|
||||
*
|
||||
* @param c The component to unregister as a drop target
|
||||
* @since 1.0
|
||||
*/
|
||||
public static boolean remove(java.awt.Component c) {
|
||||
return remove(null, c, true);
|
||||
} // end remove
|
||||
/**
|
||||
* Removes the drag-and-drop hooks from the component and optionally
|
||||
* from the all children. You should call this if you add and remove
|
||||
* database.Objects.components after you've set up the drag-and-drop.
|
||||
*
|
||||
* @param out Optional {@link PrintStream} for logging drag and drop messages
|
||||
* @param c The component to unregister
|
||||
* @param recursive Recursively unregister database.Objects.components within a container
|
||||
* @since 1.0
|
||||
*/
|
||||
public static boolean remove(PrintStream out, java.awt.Component c, boolean recursive) { // Make sure we support dnd.
|
||||
if (supportsDnD()) {
|
||||
log(out, "FileDrop: Removing drag-and-drop hooks.");
|
||||
c.setDropTarget(null);
|
||||
if (recursive && (c instanceof java.awt.Container)) {
|
||||
java.awt.Component[] comps = ((java.awt.Container) c).getComponents();
|
||||
for (int i = 0; i < comps.length; i++)
|
||||
remove(out, comps[i], recursive);
|
||||
return true;
|
||||
} // end if: recursive
|
||||
else return false;
|
||||
} // end if: supports DnD
|
||||
else return false;
|
||||
} // end remove
|
||||
// END 2007-09-12 Nathan Blomquist -- Linux (KDE/Gnome) support added.
|
||||
private void makeDropTarget(final PrintStream out, final java.awt.Component c, boolean recursive) {
|
||||
// Make drop target
|
||||
final java.awt.dnd.DropTarget dt = new java.awt.dnd.DropTarget();
|
||||
try {
|
||||
dt.addDropTargetListener(dropListener);
|
||||
} // end try
|
||||
catch (java.util.TooManyListenersException e) {
|
||||
Global.Log.PrintException(e);
|
||||
log(out, "FileDrop: Drop will not work due to previous error. Do you have another listener attached?");
|
||||
} // end catch
|
||||
// Listen for hierarchy changes and remove the drop target when the parent gets cleared out.
|
||||
c.addHierarchyListener(new java.awt.event.HierarchyListener() {
|
||||
public void hierarchyChanged(java.awt.event.HierarchyEvent evt) {
|
||||
log(out, "FileDrop: Hierarchy changed.");
|
||||
java.awt.Component parent = c.getParent();
|
||||
if (parent == null) {
|
||||
c.setDropTarget(null);
|
||||
log(out, "FileDrop: Drop target cleared from component.");
|
||||
} // end if: null parent
|
||||
else {
|
||||
new java.awt.dnd.DropTarget(c, dropListener);
|
||||
log(out, "FileDrop: Drop target added to component.");
|
||||
} // end else: parent not null
|
||||
} // end hierarchyChanged
|
||||
}); // end hierarchy listener
|
||||
if (c.getParent() != null)
|
||||
new java.awt.dnd.DropTarget(c, dropListener);
|
||||
if (recursive && (c instanceof java.awt.Container)) {
|
||||
// Get the container
|
||||
java.awt.Container cont = (java.awt.Container) c;
|
||||
// Get it's database.Objects.components
|
||||
java.awt.Component[] comps = cont.getComponents();
|
||||
// Set it's database.Objects.components as listeners also
|
||||
for (int i = 0; i < comps.length; i++)
|
||||
makeDropTarget(out, comps[i], recursive);
|
||||
} // end if: recursively set database.Objects.components as listener
|
||||
} // end dropListener
|
||||
/**
|
||||
* Determine if the dragged data is a file list.
|
||||
*/
|
||||
private boolean isDragOk(final PrintStream out, final java.awt.dnd.DropTargetDragEvent evt) {
|
||||
boolean ok = false;
|
||||
// Get data flavors being dragged
|
||||
DataFlavor[] flavors = evt.getCurrentDataFlavors();
|
||||
// See if any of the flavors are a file list
|
||||
int i = 0;
|
||||
while (!ok && i < flavors.length) {
|
||||
// BEGIN 2007-09-12 Nathan Blomquist -- Linux (KDE/Gnome) support added.
|
||||
// Is the flavor a file list?
|
||||
final DataFlavor curFlavor = flavors[i];
|
||||
if (curFlavor.equals(DataFlavor.javaFileListFlavor) ||
|
||||
curFlavor.isRepresentationClassReader()) {
|
||||
ok = true;
|
||||
}
|
||||
// END 2007-09-12 Nathan Blomquist -- Linux (KDE/Gnome) support added.
|
||||
i++;
|
||||
} // end while: through flavors
|
||||
// If logging is enabled, show data flavors
|
||||
if (out != null) {
|
||||
if (flavors.length == 0)
|
||||
log(out, "FileDrop: no data flavors.");
|
||||
for (i = 0; i < flavors.length; i++)
|
||||
log(out, flavors[i].toString());
|
||||
} // end if: logging enabled
|
||||
return ok;
|
||||
} // end isDragOk
|
||||
|
||||
|
||||
|
||||
|
||||
/* ******** I N N E R I N T E R F A C E L I S T E N E R ******** */
|
||||
/**
|
||||
* Implement this inner interface to listen for when files are dropped. For example
|
||||
* your class declaration may begin like this:
|
||||
* <code><pre>
|
||||
* public class MyClass implements FileDrop.Listener
|
||||
* ...
|
||||
* public void filesDropped( java.io.File[] files )
|
||||
* {
|
||||
* ...
|
||||
* } // end filesDropped
|
||||
* ...
|
||||
* </pre></code>
|
||||
*
|
||||
* @since 1.1
|
||||
*/
|
||||
public interface Listener {
|
||||
/**
|
||||
* This method is called when files have been successfully dropped.
|
||||
*
|
||||
* @param files An array of <tt>File</tt>s that were dropped.
|
||||
* @since 1.0
|
||||
*/
|
||||
void filesDropped(File[] files);
|
||||
} // end inner-interface Listener
|
||||
|
||||
|
||||
/* ******** I N N E R C L A S S ******** */
|
||||
/**
|
||||
* This is the event that is passed to the
|
||||
* {@link FileDropListener#filesDropped filesDropped(...)} method in
|
||||
* your {@link FileDropListener} when files are dropped onto
|
||||
* a registered drop target.
|
||||
*
|
||||
* <p>I'm releasing this code into the Public Domain. Enjoy.</p>
|
||||
*
|
||||
* @author Robert Harder
|
||||
* @author rob@iharder.net
|
||||
* @version 1.2
|
||||
*/
|
||||
public static class Event extends java.util.EventObject {
|
||||
private final File[] files;
|
||||
/**
|
||||
* Constructs an {@link Event} with the array
|
||||
* of files that were dropped and the
|
||||
* {@link FileDrop} that initiated the event.
|
||||
*
|
||||
* @param files The array of files that were dropped
|
||||
* @source The event source
|
||||
* @since 1.1
|
||||
*/
|
||||
public Event(File[] files, Object source) {
|
||||
super(source);
|
||||
this.files = files;
|
||||
} // end constructor
|
||||
/**
|
||||
* Returns an array of files that were dropped on a
|
||||
* registered drop target.
|
||||
*
|
||||
* @return array of files that were dropped
|
||||
* @since 1.1
|
||||
*/
|
||||
public File[] getFiles() {
|
||||
return files;
|
||||
} // end getFiles
|
||||
} // end inner class Event
|
||||
|
||||
|
||||
|
||||
/* ******** I N N E R C L A S S ******** */
|
||||
/**
|
||||
* At last an easy way to encapsulate your custom objects for dragging and dropping
|
||||
* in your Java programs!
|
||||
* When you need to create a {@link java.awt.datatransfer.Transferable} object,
|
||||
* use this class to wrap your object.
|
||||
* For example:
|
||||
* <pre><code>
|
||||
* ...
|
||||
* MyCoolClass myObj = new MyCoolClass();
|
||||
* Transferable xfer = new TransferableObject( myObj );
|
||||
* ...
|
||||
* </code></pre>
|
||||
* Or if you need to know when the data was actually dropped, like when you're
|
||||
* moving data out of a list, say, you can use the {@link Fetcher}
|
||||
* inner class to return your object Just in Time.
|
||||
* For example:
|
||||
* <pre><code>
|
||||
* ...
|
||||
* final MyCoolClass myObj = new MyCoolClass();
|
||||
*
|
||||
* TransferableObject.Fetcher fetcher = new TransferableObject.Fetcher()
|
||||
* { public Object getObject(){ return myObj; }
|
||||
* }; // end fetcher
|
||||
*
|
||||
* Transferable xfer = new TransferableObject( fetcher );
|
||||
* ...
|
||||
* </code></pre>
|
||||
* <p>
|
||||
* The {@link DataFlavor} associated with
|
||||
* {@link TransferableObject} has the representation class
|
||||
* <tt>net.iharder.dnd.TransferableObject.class</tt> and MIME type
|
||||
* <tt>application/x-net.iharder.dnd.TransferableObject</tt>.
|
||||
* This data flavor is accessible via the static
|
||||
* {@link #DATA_FLAVOR} property.
|
||||
*
|
||||
*
|
||||
* <p>I'm releasing this code into the Public Domain. Enjoy.</p>
|
||||
*
|
||||
* @author Robert Harder
|
||||
* @author rob@iharder.net
|
||||
* @version 1.2
|
||||
*/
|
||||
public static class TransferableObject implements java.awt.datatransfer.Transferable {
|
||||
/**
|
||||
* The MIME type for {@link #DATA_FLAVOR} is
|
||||
* <tt>application/x-net.iharder.dnd.TransferableObject</tt>.
|
||||
*
|
||||
* @since 1.1
|
||||
*/
|
||||
public final static String MIME_TYPE = "application/x-net.iharder.dnd.TransferableObject";
|
||||
/**
|
||||
* The default {@link DataFlavor} for
|
||||
* {@link TransferableObject} has the representation class
|
||||
* <tt>net.iharder.dnd.TransferableObject.class</tt>
|
||||
* and the MIME type
|
||||
* <tt>application/x-net.iharder.dnd.TransferableObject</tt>.
|
||||
*
|
||||
* @since 1.1
|
||||
*/
|
||||
public final static DataFlavor DATA_FLAVOR =
|
||||
new DataFlavor(TransferableObject.class, MIME_TYPE);
|
||||
private Fetcher fetcher;
|
||||
private Object data;
|
||||
private DataFlavor customFlavor;
|
||||
/**
|
||||
* Creates a new {@link TransferableObject} that wraps <var>data</var>.
|
||||
* Along with the {@link #DATA_FLAVOR} associated with this class,
|
||||
* this creates a custom data flavor with a representation class
|
||||
* determined from <code>data.getClass()</code> and the MIME type
|
||||
* <tt>application/x-net.iharder.dnd.TransferableObject</tt>.
|
||||
*
|
||||
* @param data The data to transfer
|
||||
* @since 1.1
|
||||
*/
|
||||
public TransferableObject(Object data) {
|
||||
this.data = data;
|
||||
this.customFlavor = new DataFlavor(data.getClass(), MIME_TYPE);
|
||||
} // end constructor
|
||||
/**
|
||||
* Creates a new {@link TransferableObject} that will return the
|
||||
* object that is returned by <var>fetcher</var>.
|
||||
* No custom data flavor is set other than the default
|
||||
* {@link #DATA_FLAVOR}.
|
||||
*
|
||||
* @param fetcher The {@link Fetcher} that will return the data object
|
||||
* @see Fetcher
|
||||
* @since 1.1
|
||||
*/
|
||||
public TransferableObject(Fetcher fetcher) {
|
||||
this.fetcher = fetcher;
|
||||
} // end constructor
|
||||
/**
|
||||
* Creates a new {@link TransferableObject} that will return the
|
||||
* object that is returned by <var>fetcher</var>.
|
||||
* Along with the {@link #DATA_FLAVOR} associated with this class,
|
||||
* this creates a custom data flavor with a representation class <var>dataClass</var>
|
||||
* and the MIME type
|
||||
* <tt>application/x-net.iharder.dnd.TransferableObject</tt>.
|
||||
*
|
||||
* @param dataClass The {@link Class} to use in the custom data flavor
|
||||
* @param fetcher The {@link Fetcher} that will return the data object
|
||||
* @see Fetcher
|
||||
* @since 1.1
|
||||
*/
|
||||
public TransferableObject(Class dataClass, Fetcher fetcher) {
|
||||
this.fetcher = fetcher;
|
||||
this.customFlavor = new DataFlavor(dataClass, MIME_TYPE);
|
||||
} // end constructor
|
||||
/**
|
||||
* Returns the custom {@link DataFlavor} associated
|
||||
* with the encapsulated object or <tt>null</tt> if the {@link Fetcher}
|
||||
* constructor was used without passing a {@link Class}.
|
||||
*
|
||||
* @return The custom data flavor for the encapsulated object
|
||||
* @since 1.1
|
||||
*/
|
||||
public DataFlavor getCustomDataFlavor() {
|
||||
return customFlavor;
|
||||
} // end getCustomDataFlavor
|
||||
|
||||
|
||||
/* ******** T R A N S F E R A B L E M E T H O D S ******** */
|
||||
/**
|
||||
* Returns a two- or three-element array containing first
|
||||
* the custom data flavor, if one was created in the constructors,
|
||||
* second the default {@link #DATA_FLAVOR} associated with
|
||||
* {@link TransferableObject}, and third the
|
||||
* {@link DataFlavor.stringFlavor}.
|
||||
*
|
||||
* @return An array of supported data flavors
|
||||
* @since 1.1
|
||||
*/
|
||||
public DataFlavor[] getTransferDataFlavors() {
|
||||
if (customFlavor != null)
|
||||
return new DataFlavor[]
|
||||
{customFlavor,
|
||||
DATA_FLAVOR,
|
||||
DataFlavor.stringFlavor
|
||||
}; // end flavors array
|
||||
else
|
||||
return new DataFlavor[]
|
||||
{DATA_FLAVOR,
|
||||
DataFlavor.stringFlavor
|
||||
}; // end flavors array
|
||||
} // end getTransferDataFlavors
|
||||
/**
|
||||
* Returns the data encapsulated in this {@link TransferableObject}.
|
||||
* If the {@link Fetcher} constructor was used, then this is when
|
||||
* the {@link Fetcher#getObject getObject()} method will be called.
|
||||
* If the requested data flavor is not supported, then the
|
||||
* {@link Fetcher#getObject getObject()} method will not be called.
|
||||
*
|
||||
* @param flavor The data flavor for the data to return
|
||||
* @return The dropped data
|
||||
* @since 1.1
|
||||
*/
|
||||
public Object getTransferData(DataFlavor flavor)
|
||||
throws java.awt.datatransfer.UnsupportedFlavorException, IOException {
|
||||
// Native object
|
||||
if (flavor.equals(DATA_FLAVOR))
|
||||
return fetcher == null ? data : fetcher.getObject();
|
||||
// String
|
||||
if (flavor.equals(DataFlavor.stringFlavor))
|
||||
return fetcher == null ? data.toString() : fetcher.getObject().toString();
|
||||
// We can't do anything else
|
||||
throw new java.awt.datatransfer.UnsupportedFlavorException(flavor);
|
||||
} // end getTransferData
|
||||
/**
|
||||
* Returns <tt>true</tt> if <var>flavor</var> is one of the supported
|
||||
* flavors. Flavors are supported using the <code>equals(...)</code> method.
|
||||
*
|
||||
* @param flavor The data flavor to check
|
||||
* @return Whether or not the flavor is supported
|
||||
* @since 1.1
|
||||
*/
|
||||
public boolean isDataFlavorSupported(DataFlavor flavor) {
|
||||
// Native object
|
||||
if (flavor.equals(DATA_FLAVOR))
|
||||
return true;
|
||||
// String
|
||||
return flavor.equals(DataFlavor.stringFlavor);
|
||||
// We can't do anything else
|
||||
} // end isDataFlavorSupported
|
||||
|
||||
|
||||
/* ******** I N N E R I N T E R F A C E F E T C H E R ******** */
|
||||
/**
|
||||
* Instead of passing your data directly to the {@link TransferableObject}
|
||||
* constructor, you may want to know exactly when your data was received
|
||||
* in case you need to remove it from its source (or do anyting else to it).
|
||||
* When the {@link #getTransferData getTransferData(...)} method is called
|
||||
* on the {@link TransferableObject}, the {@link Fetcher}'s
|
||||
* {@link #getObject getObject()} method will be called.
|
||||
*
|
||||
* @author Robert Harder
|
||||
* @version 1.1
|
||||
* @copyright 2001
|
||||
* @since 1.1
|
||||
*/
|
||||
public interface Fetcher {
|
||||
/**
|
||||
* Return the object being encapsulated in the
|
||||
* {@link TransferableObject}.
|
||||
*
|
||||
* @return The dropped object
|
||||
* @since 1.1
|
||||
*/
|
||||
Object getObject();
|
||||
} // end inner interface Fetcher
|
||||
} // end class TransferableObject
|
||||
} // end class FileDrop
|
||||
154
src/Common/UI/Editor/BaseEditor.java
Normal file
154
src/Common/UI/Editor/BaseEditor.java
Normal file
@@ -0,0 +1,154 @@
|
||||
package Common.UI.Editor;
|
||||
import Common.Current;
|
||||
import Common.Global;
|
||||
import Common.UI.Menus.StyledPopupMenu;
|
||||
import Common.UI.Menus.TextEditorMenu;
|
||||
import Common.UI.Themes.ThemeElement;
|
||||
import Common.UI.UI;
|
||||
import Common.UI.Windows.Dialog.DialogFields;
|
||||
import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea;
|
||||
|
||||
import javax.swing.event.HyperlinkEvent;
|
||||
import javax.swing.event.HyperlinkListener;
|
||||
import java.awt.*;
|
||||
import java.awt.event.KeyAdapter;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.net.URI;
|
||||
public class BaseEditor extends RSyntaxTextArea implements ThemeElement, DialogFields {
|
||||
private final StyledPopupMenu menu;
|
||||
// protected int changesCount = 0;
|
||||
// protected int insertsCount = 0;
|
||||
// protected int removesCount = 0;
|
||||
// protected boolean ctrlZ = false;
|
||||
protected String startText = "";
|
||||
private boolean search_enabled = true;
|
||||
public BaseEditor() {
|
||||
setTabSize(6);
|
||||
setPaintTabLines(true);
|
||||
setCodeFoldingEnabled(true);
|
||||
addKeyListener(new KeyAdapter() {
|
||||
@Override
|
||||
public void keyPressed(KeyEvent e) {
|
||||
if (e.isControlDown()) {
|
||||
switch (e.getKeyCode()) {
|
||||
case KeyEvent.VK_ADD: //num lock +
|
||||
case KeyEvent.VK_EQUALS: //+
|
||||
FontUp();
|
||||
break;
|
||||
case KeyEvent.VK_SUBTRACT: //num lock -
|
||||
case KeyEvent.VK_MINUS: //-
|
||||
FontDown();
|
||||
break;
|
||||
case KeyEvent.VK_S:
|
||||
saveText();
|
||||
break;
|
||||
//todo переход в нужную строку по ctrl+g?
|
||||
case KeyEvent.VK_Z:
|
||||
if (getText().equals(startText)) {
|
||||
UI.Info("Начальная версия текста достигнута.");
|
||||
e.consume();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
setPopupMenu(menu = createMenu());
|
||||
applyTheme();
|
||||
//-
|
||||
this.setHyperlinksEnabled(true);
|
||||
HyperlinkListener listener = new HyperlinkListener() {
|
||||
@Override
|
||||
public void hyperlinkUpdate(HyperlinkEvent event) {
|
||||
if (event.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
|
||||
try {
|
||||
Desktop.getDesktop().browse(new URI(event.getURL().toString()));
|
||||
} catch (Exception ioe) {
|
||||
System.err.println("Error loading url from link: " + ioe);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
this.addHyperlinkListener(listener);
|
||||
}
|
||||
@Override
|
||||
public void setText(String t) {
|
||||
super.setText(t);
|
||||
startText = t;
|
||||
}
|
||||
public void setSearchEnabled(boolean f_in) {
|
||||
search_enabled = f_in;
|
||||
}
|
||||
protected StyledPopupMenu createMenu() {
|
||||
return new TextEditorMenu(this);
|
||||
}
|
||||
private void changeFont(int size) {
|
||||
if ((size > 1) && (size < 48)) {
|
||||
setFont(getFont().deriveFont((float) size));
|
||||
saveFont();
|
||||
}
|
||||
}
|
||||
protected void saveFont() {
|
||||
}
|
||||
protected void saveText() {
|
||||
}
|
||||
public void ClearSelection() {
|
||||
setSelectionStart(0);
|
||||
setSelectionEnd(0);
|
||||
}
|
||||
public void gotoLine(int LineNum) {
|
||||
gotoLine_(LineNum - 1);
|
||||
}
|
||||
//без вычитания.
|
||||
public void gotoLine_(int LineNum) {
|
||||
//requestFocus();
|
||||
try {
|
||||
//особеннсть контрола.
|
||||
//нельзя полностью скинуть текущую позицию. пэтому если надо
|
||||
//освежить 0 строку, передергиваем до последней.
|
||||
if (LineNum == 0)
|
||||
setCaretPosition(getLineStartOffset(getLineCount() - 1));
|
||||
ClearSelection();
|
||||
if (LineNum > 0) {
|
||||
setCaretPosition(getLineStartOffset(LineNum));
|
||||
setSelectionStart(getLineStartOffset(LineNum));
|
||||
setSelectionEnd(getLineStartOffset(LineNum));
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
Global.Log.Print("Не удалось перейти на строку " + LineNum);
|
||||
Global.Log.PrintException(ex);
|
||||
}
|
||||
}
|
||||
//------------------------------------------
|
||||
public void FontUp() {
|
||||
changeFont(getFont().getSize() + 1);
|
||||
}
|
||||
public void FontDown() {
|
||||
changeFont(getFont().getSize() - 1);
|
||||
}
|
||||
@Override
|
||||
public void applyTheme() {
|
||||
float font_size = (float) getFont().getSize();
|
||||
Current.getTheme().getEditorTheme().apply(this);
|
||||
setFont(getFont().deriveFont(font_size));
|
||||
menu.applyTheme();
|
||||
//меню связано с редактором. поэтому тема меняется только вместе с ним.
|
||||
}
|
||||
@Override
|
||||
public Component getContent() {
|
||||
return this;
|
||||
}
|
||||
public void ShowBegin() {
|
||||
setCaretPosition(0);
|
||||
}
|
||||
public boolean lineIsVisible(int lineNum) {
|
||||
boolean res = false;
|
||||
Rectangle rectangle = this.getVisibleRect();
|
||||
try {
|
||||
res = rectangle.contains(rectangle.x, yForLine(lineNum));
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
return res;
|
||||
}
|
||||
}
|
||||
30
src/Common/UI/Editor/CaretInfo.java
Normal file
30
src/Common/UI/Editor/CaretInfo.java
Normal file
@@ -0,0 +1,30 @@
|
||||
package Common.UI.Editor;
|
||||
import Common.Global;
|
||||
import ProjectData.Files.UI.Editor.SPFEditor;
|
||||
import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea;
|
||||
public class CaretInfo {
|
||||
public String current_line = ""; //полный текст текущей строки
|
||||
public String before = ""; //кусок строки перед кареткой
|
||||
public String after = ""; //кусок строки после каретки
|
||||
public String prefix_word = ""; //слово перед кареткой
|
||||
public String suffix_word = ""; //слово после каретки
|
||||
public CaretInfo(RSyntaxTextArea Body) {
|
||||
try {
|
||||
int start = Body.getLineStartOffset(Body.getCaretLineNumber());
|
||||
int before_length = Body.getCaretOffsetFromLineStart();
|
||||
int end = Body.getLineEndOffset(Body.getCaretLineNumber());
|
||||
int after_length = end - start - before_length;
|
||||
before = Body.getText(start, before_length).toUpperCase();
|
||||
after = Body.getText(start + before_length, after_length).toUpperCase();
|
||||
//нужно чтобы перевод строки не влезал
|
||||
after = after.replace("\n", "");
|
||||
current_line = (before + after);
|
||||
prefix_word = SPFEditor.getLastWord(before, ' ', ',', ':', '.', '(', ')');
|
||||
suffix_word = SPFEditor.getFirstWord(after, ' ', ',', ':', '.', '(', ')');
|
||||
} catch (Exception ex) {
|
||||
Global.Log.PrintException(ex);
|
||||
}
|
||||
}
|
||||
public CaretInfo() {
|
||||
}
|
||||
}
|
||||
8
src/Common/UI/Editor/Viewer.java
Normal file
8
src/Common/UI/Editor/Viewer.java
Normal file
@@ -0,0 +1,8 @@
|
||||
package Common.UI.Editor;
|
||||
public class Viewer extends BaseEditor {
|
||||
public Viewer() {
|
||||
setLineWrap(true);
|
||||
setWrapStyleWord(true);
|
||||
setEditable(false);
|
||||
}
|
||||
}
|
||||
11
src/Common/UI/EmptyDialogFields.form
Normal file
11
src/Common/UI/EmptyDialogFields.form
Normal file
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="Common.UI.EmptyDialogFields">
|
||||
<grid id="27dc6" binding="content" layout-manager="BorderLayout" hgap="0" vgap="0">
|
||||
<constraints>
|
||||
<xy x="20" y="20" width="500" height="400"/>
|
||||
</constraints>
|
||||
<properties/>
|
||||
<border type="none"/>
|
||||
<children/>
|
||||
</grid>
|
||||
</form>
|
||||
12
src/Common/UI/EmptyDialogFields.java
Normal file
12
src/Common/UI/EmptyDialogFields.java
Normal file
@@ -0,0 +1,12 @@
|
||||
package Common.UI;
|
||||
import Common.UI.Windows.Dialog.DialogFields;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
public class EmptyDialogFields implements DialogFields {
|
||||
private JPanel content;
|
||||
@Override
|
||||
public Component getContent() {
|
||||
return content;
|
||||
}
|
||||
}
|
||||
15
src/Common/UI/Label/ShortLabel.java
Normal file
15
src/Common/UI/Label/ShortLabel.java
Normal file
@@ -0,0 +1,15 @@
|
||||
package Common.UI.Label;
|
||||
import javax.swing.*;
|
||||
public class ShortLabel extends JLabel {
|
||||
int max = 0;
|
||||
public ShortLabel(int max_in) {
|
||||
max = max_in;
|
||||
}
|
||||
@Override
|
||||
public void setText(String text_in) {
|
||||
if ((max > 0) && (text_in.length() > max)) {
|
||||
super.setText(text_in.substring(0, max - 1) + "...");
|
||||
} else super.setText(text_in);
|
||||
setToolTipText(text_in);
|
||||
}
|
||||
}
|
||||
10
src/Common/UI/List/HyperlinksStyledList.java
Normal file
10
src/Common/UI/List/HyperlinksStyledList.java
Normal file
@@ -0,0 +1,10 @@
|
||||
package Common.UI.List;
|
||||
import Common.Current;
|
||||
import Common.UI.Themes.VisualiserFonts;
|
||||
public class HyperlinksStyledList extends StyledList {
|
||||
@Override
|
||||
public void applyTheme() {
|
||||
super.applyTheme();
|
||||
setFont(Current.getTheme().Fonts.get(VisualiserFonts.Hyperlink));
|
||||
}
|
||||
}
|
||||
17
src/Common/UI/List/StyledList.java
Normal file
17
src/Common/UI/List/StyledList.java
Normal file
@@ -0,0 +1,17 @@
|
||||
package Common.UI.List;
|
||||
import Common.Current;
|
||||
import Common.UI.Themes.ThemeElement;
|
||||
import Common.UI.Themes.VisualiserFonts;
|
||||
|
||||
import javax.swing.*;
|
||||
public class StyledList extends JList implements ThemeElement {
|
||||
public StyledList() {
|
||||
setFont(Current.getTheme().Fonts.get(VisualiserFonts.TreePlain));
|
||||
applyTheme();
|
||||
}
|
||||
@Override
|
||||
public void applyTheme() {
|
||||
setBackground(Current.getTheme().table_background);
|
||||
setForeground(Current.getTheme().foreground);
|
||||
}
|
||||
}
|
||||
30
src/Common/UI/Menus/AttachementsMenu.java
Normal file
30
src/Common/UI/Menus/AttachementsMenu.java
Normal file
@@ -0,0 +1,30 @@
|
||||
package Common.UI.Menus;
|
||||
import Common.Current;
|
||||
import Common.Global;
|
||||
import Visual_DVM_2021.Passes.PassCode_2021;
|
||||
import Visual_DVM_2021.Passes.Pass_2021;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
public class AttachementsMenu extends StyledPopupMenu {
|
||||
JMenuItem mscreenshot;
|
||||
JMenuItem mExplorer;
|
||||
public AttachementsMenu() {
|
||||
add(mscreenshot = Pass_2021.passes.get(PassCode_2021.MakeScreenShot).createMenuItem());
|
||||
addSeparator();
|
||||
mExplorer = new VisualiserMenuItem("Открыть вложения в проводнике...", "/icons/Explorer.png");
|
||||
mExplorer.addActionListener(
|
||||
new AbstractAction() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
try {
|
||||
Desktop.getDesktop().open(Current.getProject().getAttachmentsDirectory());
|
||||
} catch (Exception ex) {
|
||||
Global.Log.PrintException(ex);
|
||||
}
|
||||
}
|
||||
});
|
||||
add(mExplorer);
|
||||
}
|
||||
}
|
||||
24
src/Common/UI/Menus/FileStyleMenu.java
Normal file
24
src/Common/UI/Menus/FileStyleMenu.java
Normal file
@@ -0,0 +1,24 @@
|
||||
package Common.UI.Menus;
|
||||
import Common.Current;
|
||||
import ProjectData.Files.LanguageStyle;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
public class FileStyleMenu extends StyledPopupMenu {
|
||||
public FileStyleMenu() {
|
||||
for (LanguageStyle s : LanguageStyle.values()) {
|
||||
JMenuItem m = new VisualiserMenuItem(s.getDescription());
|
||||
m.addActionListener(
|
||||
new AbstractAction() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
if (Current.getFile().UpdateStyle(s)) {
|
||||
Current.getSapfor().ResetAllAnalyses();
|
||||
Current.getFile().form.ShowStyle();
|
||||
}
|
||||
}
|
||||
});
|
||||
add(m);
|
||||
}
|
||||
}
|
||||
}
|
||||
35
src/Common/UI/Menus/GraphMenu.java
Normal file
35
src/Common/UI/Menus/GraphMenu.java
Normal file
@@ -0,0 +1,35 @@
|
||||
package Common.UI.Menus;
|
||||
import Common.UI.Trees.StyledTree;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.MouseEvent;
|
||||
public class GraphMenu<T extends StyledTree> extends StyledPopupMenu {
|
||||
public T tree;
|
||||
public GraphMenu(T tree_in, String branches_name) {
|
||||
tree = tree_in;
|
||||
JMenuItem m = null;
|
||||
m = new VisualiserMenuItem("Свернуть все " + branches_name);
|
||||
m.addActionListener(new AbstractAction() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
tree.CollapseAll();
|
||||
}
|
||||
});
|
||||
add(m);
|
||||
m = new VisualiserMenuItem("Развернуть все " + branches_name);
|
||||
m.addActionListener(new AbstractAction() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
tree.ExpandAll();
|
||||
}
|
||||
});
|
||||
add(m);
|
||||
}
|
||||
public GraphMenu(T tree) {
|
||||
this(tree, tree.getBranchesName());
|
||||
}
|
||||
public void Show(MouseEvent mouseEvent) {
|
||||
show(tree, mouseEvent.getX(), mouseEvent.getY());
|
||||
}
|
||||
}
|
||||
342
src/Common/UI/Menus/MainEditorMenu.java
Normal file
342
src/Common/UI/Menus/MainEditorMenu.java
Normal file
@@ -0,0 +1,342 @@
|
||||
package Common.UI.Menus;
|
||||
import Common.Current;
|
||||
import Common.Global;
|
||||
import Common.UI.Editor.CaretInfo;
|
||||
import Common.Utils.Utils;
|
||||
import ProjectData.Files.DBProjectFile;
|
||||
import ProjectData.Files.UI.Editor.SPFEditor;
|
||||
import ProjectData.SapforData.Functions.FuncCall;
|
||||
import ProjectData.SapforData.Functions.FuncInfo;
|
||||
import ProjectData.SapforData.Functions.FunctionType;
|
||||
import ProjectData.SapforData.Loops.Loop;
|
||||
import Visual_DVM_2021.Passes.PassCode_2021;
|
||||
import Visual_DVM_2021.Passes.Pass_2021;
|
||||
import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
public class MainEditorMenu extends TextEditorMenu {
|
||||
FuncCall call = null;
|
||||
FuncInfo decl = null;
|
||||
Loop loop = null;
|
||||
DBProjectFile header = null;
|
||||
//------------------
|
||||
JMenuItem m_comment;
|
||||
JMenuItem m_uncomment;
|
||||
JMenuItem m_inline;
|
||||
JMenuItem m_add_lines_to_region;
|
||||
JMenuItem m_remove_lines_from_region;
|
||||
JMenuItem m_loop_union;
|
||||
JMenuItem m_undo;
|
||||
JMenuItem m_gotoFunction;
|
||||
JMenuItem m_gotoHeader;
|
||||
//-----------------
|
||||
public MainEditorMenu(RSyntaxTextArea editor_in) {
|
||||
super(editor_in);
|
||||
addSeparator();
|
||||
m_gotoHeader = new VisualiserMenuItem("Перейти к заголовочному файлу", "/icons/Transformations/SPF_InsertIncludesPass.png");
|
||||
m_gotoHeader.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
Pass_2021.passes.get(PassCode_2021.OpenCurrentFile).Do(header);
|
||||
}
|
||||
});
|
||||
add(m_gotoHeader);
|
||||
addSeparator();
|
||||
m_gotoFunction = new VisualiserMenuItem("Перейти к объявлению процедуры", "/icons/versions/currentVersion.png");
|
||||
m_gotoFunction.addActionListener(
|
||||
new AbstractAction() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
decl.Show(true);
|
||||
}
|
||||
});
|
||||
add(m_gotoFunction);
|
||||
m_inline = new VisualiserMenuItem("Подставить вызов процедуры", "/icons/Transformations/SPF_InlineProcedures.png");
|
||||
m_inline.addActionListener(
|
||||
new AbstractAction() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
Pass_2021.passes.get(PassCode_2021.SPF_InlineProcedure).Do(call);
|
||||
}
|
||||
});
|
||||
add(m_inline);
|
||||
addSeparator();
|
||||
m_loop_union = new VisualiserMenuItem("Объединить цикл со следующим", "/icons/Transformations/SPF_LoopUnion.png");
|
||||
m_loop_union.addActionListener(
|
||||
new AbstractAction() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
Pass_2021.passes.get(PassCode_2021.SPF_LoopUnionCurrent).Do();
|
||||
}
|
||||
});
|
||||
add(m_loop_union);
|
||||
m_add_lines_to_region = new VisualiserMenuItem("Добавить строки в область", "/icons/Menu/AddLines.png");
|
||||
m_add_lines_to_region.addActionListener(
|
||||
new AbstractAction() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
try {
|
||||
Pass_2021.passes.get(PassCode_2021.SPF_ChangeSpfIntervals).Do(
|
||||
((RSyntaxTextArea) editor).getLineOfOffset(editor.getSelectionStart()) + 1,
|
||||
((RSyntaxTextArea) editor).getLineOfOffset(editor.getSelectionEnd()) + 1,
|
||||
1
|
||||
);
|
||||
} catch (Exception ex) {
|
||||
Global.Log.PrintException(ex);
|
||||
}
|
||||
}
|
||||
});
|
||||
add(m_add_lines_to_region);
|
||||
m_remove_lines_from_region = new VisualiserMenuItem("Удалить строки из области", "/icons/Menu/RemoveLines.png");
|
||||
m_remove_lines_from_region.addActionListener(
|
||||
new AbstractAction() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
try {
|
||||
Pass_2021.passes.get(PassCode_2021.SPF_ChangeSpfIntervals).Do(
|
||||
((RSyntaxTextArea) editor).getLineOfOffset(editor.getSelectionStart()) + 1,
|
||||
((RSyntaxTextArea) editor).getLineOfOffset(editor.getSelectionEnd()) + 1,
|
||||
0
|
||||
);
|
||||
} catch (Exception ex) {
|
||||
Global.Log.PrintException(ex);
|
||||
}
|
||||
}
|
||||
});
|
||||
add(m_remove_lines_from_region);
|
||||
addSeparator();
|
||||
m_comment = new VisualiserMenuItem("Закомментировать блок", "/icons/Editor/Comment.png");
|
||||
m_comment.addActionListener(
|
||||
new AbstractAction() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
String new_ = "";
|
||||
String[] data = selectedText.split("\n");
|
||||
int i = 0;
|
||||
switch (Current.getFile().languageName) {
|
||||
case fortran:
|
||||
for (String line : data) {
|
||||
if (!line.startsWith("!")) {
|
||||
new_ += "!" + line;
|
||||
} else new_ += line;
|
||||
if (i < data.length - 1) new_ += "\n";
|
||||
++i;
|
||||
}
|
||||
break;
|
||||
case c:
|
||||
case cpp:
|
||||
for (String line : data) {
|
||||
if (!line.startsWith("//")) {
|
||||
new_ += "//" + line;
|
||||
} else new_ += line;
|
||||
if (i < data.length - 1) new_ += "\n";
|
||||
++i;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
new_ = selectedText;
|
||||
break;
|
||||
}
|
||||
editor.replaceSelection(new_);
|
||||
}
|
||||
});
|
||||
add(m_comment);
|
||||
m_uncomment = new VisualiserMenuItem("Раскомментировать блок", "/icons/Editor/Uncomment.png");
|
||||
m_uncomment.addActionListener(
|
||||
new AbstractAction() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
String new_ = "";
|
||||
String[] data = selectedText.split("\n");
|
||||
int i = 0;
|
||||
switch (Current.getFile().languageName) {
|
||||
case fortran:
|
||||
for (String line : data) {
|
||||
if (line.startsWith("!")) {
|
||||
new_ += line.substring(1);
|
||||
} else new_ += line;
|
||||
if (i < data.length - 1) new_ += "\n";
|
||||
++i;
|
||||
}
|
||||
break;
|
||||
case c:
|
||||
case cpp:
|
||||
for (String line : data) {
|
||||
if (line.startsWith("//")) {
|
||||
new_ += line.substring(2);
|
||||
} else new_ += line;
|
||||
if (i < data.length - 1) new_ += "\n";
|
||||
++i;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
new_ = selectedText;
|
||||
break;
|
||||
}
|
||||
//todo. возможно, изменить концепцию на выделенные строки?
|
||||
editor.replaceSelection(new_);
|
||||
}
|
||||
});
|
||||
add(m_uncomment);
|
||||
addSeparator();
|
||||
m_undo = new VisualiserMenuItem("Отменить последнюю модификацию", "/icons/Menu/Undo.png");
|
||||
m_undo.addActionListener(
|
||||
new AbstractAction() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
try {
|
||||
Current.getSapfor().UpdateProjectFiles(false);
|
||||
} catch (Exception ex) {
|
||||
Global.Log.PrintException(ex);
|
||||
}
|
||||
}
|
||||
});
|
||||
add(m_undo);
|
||||
}
|
||||
private void checkFunction() {
|
||||
call = null;
|
||||
decl = null;
|
||||
//--
|
||||
m_inline.setEnabled(false);
|
||||
m_gotoFunction.setEnabled(false);
|
||||
//--
|
||||
m_inline.setToolTipText("");
|
||||
m_gotoFunction.setToolTipText("");
|
||||
//--
|
||||
if (selectedText == null) {
|
||||
m_inline.setText("Невозможно подставить вызов процедуры. Не выделено имя процедуры.");
|
||||
m_gotoFunction.setText("Невозможно перейти к объявлению процедуры. Не выделено имя процедуры");
|
||||
return;
|
||||
}
|
||||
if (selectedText.contains("\n")) {
|
||||
m_inline.setText("Невозможно подставить вызов процедуры. Выделено несколько строк");
|
||||
m_gotoFunction.setText("Невозможно перейти к объявлению процедуры. Выделено несколько строк.");
|
||||
return;
|
||||
}
|
||||
if (!Utils.isFunctionName(selectedText)) {
|
||||
String tip = "Имя процедуры может содержать только английские буквы, цифры и подчеркивания, и не может начинаться с цифры.";
|
||||
//-
|
||||
m_inline.setText("Невозможно подставить вызов процедуры " + Utils.Brackets(selectedText) +
|
||||
" . Выделено некорректное имя.");
|
||||
m_gotoFunction.setText("Невозможно перейти к объявлению процедуры " + Utils.Brackets(selectedText) +
|
||||
" . Выделено некорректное имя.");
|
||||
//-
|
||||
m_inline.setToolTipText(tip);
|
||||
m_gotoFunction.setToolTipText(tip);
|
||||
return;
|
||||
}
|
||||
if (!Pass_2021.passes.get(PassCode_2021.SPF_GetGraphFunctions).isDone()) {
|
||||
m_inline.setText("Невозможно подставить вызов процедуры " + Utils.Brackets(selectedText) +
|
||||
" . Выполните проход \"Граф процедур \".");
|
||||
m_gotoFunction.setText("Невозможно перейти к объявлению процедуры " + Utils.Brackets(selectedText) +
|
||||
" . Выполните проход \"Граф процедур \"");
|
||||
return;
|
||||
}
|
||||
if (Current.getSapfor().isIntrinsic(selectedText)) {
|
||||
m_inline.setText("Невозможно подставить вызов процедуры " + Utils.Brackets(selectedText) +
|
||||
" . Процедура является стандартной.");
|
||||
m_gotoFunction.setText("Невозможно перейти к объявлению процедуры " + Utils.Brackets(selectedText) +
|
||||
" . Процедура является стандартной.");
|
||||
return;
|
||||
}
|
||||
call = Current.getFile().find_func_call(selectedText);
|
||||
if (call == null) {
|
||||
m_inline.setText("Невозможно подставить вызов процедуры " + Utils.Brackets(selectedText) +
|
||||
" . Вызов не найден в текущей строке.");
|
||||
m_gotoFunction.setText("Невозможно перейти к объявлению процедуры " + Utils.Brackets(selectedText) +
|
||||
" . Объявление процедуры уже находится в текущей строке.");
|
||||
return;
|
||||
}
|
||||
decl = Current.getProject().allFunctions.get(call.funcName);
|
||||
if (decl.type.equals(FunctionType.NotFound)) {
|
||||
m_inline.setText("Невозможно подставить вызов процедуры " + Utils.Brackets(selectedText) +
|
||||
" . Объявление процедуры не найдено в проекте.");
|
||||
m_gotoFunction.setText("Невозможно перейти к объявлению процедуры " + Utils.Brackets(selectedText) +
|
||||
" . Объявление процедуры не найдено в проекте.");
|
||||
return;
|
||||
}
|
||||
//---
|
||||
m_inline.setEnabled(true);
|
||||
m_gotoFunction.setEnabled(true);
|
||||
m_inline.setText("Подставить вызов процедуры " + Utils.Brackets(selectedText));
|
||||
m_gotoFunction.setText("Перейти к объявлению процедуры " + Utils.Brackets(selectedText));
|
||||
//--
|
||||
}
|
||||
private void checkHeader() {
|
||||
header = null;
|
||||
m_gotoHeader.setEnabled(false);
|
||||
//--
|
||||
CaretInfo caretInfo = ((SPFEditor) editor).getCaretInfo();
|
||||
if (caretInfo != null) {
|
||||
String header_ = Utils.extractHeaderName(caretInfo.current_line);
|
||||
if (header_ == null) {
|
||||
m_gotoHeader.setText("Невозможно перейти к заголовочному файлу. В текущей строке не найдено включений.");
|
||||
return;
|
||||
}
|
||||
if (!Pass_2021.passes.get(PassCode_2021.SPF_GetIncludeDependencies).isDone()) {
|
||||
m_gotoHeader.setText("Невозможно перейти к заголовочному файлу. Выполните проход \"Поиск зависимостей по включению\"");
|
||||
return;
|
||||
}
|
||||
if (!Current.getFile().relativeHeaders.containsKey(header_)) {
|
||||
m_gotoHeader.setText("Невозможно перейти к заголовочному файлу " + Utils.Brackets(header_) + " . Файл не найден среди включений текущего файла.");
|
||||
return;
|
||||
}
|
||||
header = Current.getFile().relativeHeaders.get(header_);
|
||||
m_gotoHeader.setText("Переход к заголовочному файлу " + Utils.Brackets(header_));
|
||||
m_gotoHeader.setEnabled(true);
|
||||
}
|
||||
}
|
||||
private void checkLoop() {
|
||||
loop = null;
|
||||
m_loop_union.setEnabled(false);
|
||||
if (!Pass_2021.passes.get(PassCode_2021.SPF_GetGraphLoops).isDone()) {
|
||||
m_loop_union.setText("Невозможно объединить цикл в текущей строке со следующим. " +
|
||||
"Выполните проход \"Граф циклов\"");
|
||||
return;
|
||||
}
|
||||
loop = Current.getFile().find_current_loop();
|
||||
if (loop == null) {
|
||||
m_loop_union.setText("Невозможно объединить цикл в текущей строке со следующим. Не найдено циклов в текущей строке.");
|
||||
return;
|
||||
}
|
||||
m_loop_union.setEnabled(true);
|
||||
m_loop_union.setText("Объединить цикл в строке " + Utils.Brackets(loop.line) + " со следующим");
|
||||
}
|
||||
@Override
|
||||
public void CheckElementsVisibility() {
|
||||
super.CheckElementsVisibility();
|
||||
m_strike.setVisible(false);
|
||||
m_unstrike.setVisible(false);
|
||||
checkFunction();
|
||||
checkHeader();
|
||||
checkLoop();
|
||||
if (selectedText == null) {
|
||||
m_comment.setEnabled(false);
|
||||
m_uncomment.setEnabled(false);
|
||||
m_add_lines_to_region.setEnabled(false);
|
||||
m_remove_lines_from_region.setEnabled(false);
|
||||
m_comment.setText("Невозможно закомментировать блок. Не выделено ни одной строки.");
|
||||
m_uncomment.setText("Невозможно раскомментировать блок. Не выделено ни одной строки.");
|
||||
m_add_lines_to_region.setText("Невозможно добавить строки в область. Не выделено ни одной строки.");
|
||||
m_remove_lines_from_region.setText("Невозможно удалить строки из области. Не выделено ни одной строки.");
|
||||
} else {
|
||||
m_comment.setEnabled(true);
|
||||
m_uncomment.setEnabled(true);
|
||||
m_add_lines_to_region.setEnabled(true);
|
||||
m_remove_lines_from_region.setEnabled(true);
|
||||
m_comment.setText("Закомментировать блок");
|
||||
m_uncomment.setText("Раскомментировать блок");
|
||||
m_add_lines_to_region.setText("Добавить строки в область");
|
||||
m_remove_lines_from_region.setText("Удалить строки из области");
|
||||
}
|
||||
if (Current.getSapfor().OldFiles.isEmpty()) {
|
||||
m_undo.setEnabled(false);
|
||||
m_undo.setText("Невозможно отменить последнюю модификацию. Модификации отсутствуют.");
|
||||
} else {
|
||||
m_undo.setEnabled(true);
|
||||
m_undo.setText("Отменить последнюю модификацию.");
|
||||
}
|
||||
}
|
||||
}
|
||||
18
src/Common/UI/Menus/PassesSubMenu.java
Normal file
18
src/Common/UI/Menus/PassesSubMenu.java
Normal file
@@ -0,0 +1,18 @@
|
||||
package Common.UI.Menus;
|
||||
import Common.Current;
|
||||
import Common.UI.Themes.VisualiserFonts;
|
||||
import Common.Utils.Utils;
|
||||
import Visual_DVM_2021.Passes.PassCode_2021;
|
||||
import Visual_DVM_2021.Passes.Pass_2021;
|
||||
|
||||
import javax.swing.*;
|
||||
public class PassesSubMenu extends JMenu {
|
||||
public PassesSubMenu(String title, String icon, PassCode_2021... passes) {
|
||||
super(title);
|
||||
setIcon(Utils.getIcon(icon));
|
||||
setFont(Current.getTheme().Fonts.get(VisualiserFonts.Menu));
|
||||
for (PassCode_2021 code : passes) {
|
||||
add(Pass_2021.passes.get(code).createMenuItem());
|
||||
}
|
||||
}
|
||||
}
|
||||
135
src/Common/UI/Menus/ProjectFilesMenu.java
Normal file
135
src/Common/UI/Menus/ProjectFilesMenu.java
Normal file
@@ -0,0 +1,135 @@
|
||||
package Common.UI.Menus;
|
||||
import Common.Current;
|
||||
import Common.Global;
|
||||
import Common.UI.Menus_2023.LanguagesSubmenu;
|
||||
import Common.UI.Menus_2023.StableMenuItem;
|
||||
import Common.UI.Menus_2023.StylesSubmenu;
|
||||
import Common.UI.Menus_2023.TypesSubmenu;
|
||||
import Common.UI.Trees.StyledTree;
|
||||
import Common.UI.UI;
|
||||
import Common.Utils.Utils;
|
||||
import ProjectData.Files.FileType;
|
||||
import ProjectData.Files.LanguageStyle;
|
||||
import ProjectData.LanguageName;
|
||||
import Visual_DVM_2021.Passes.PassCode_2021;
|
||||
import Visual_DVM_2021.Passes.Pass_2021;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
public class ProjectFilesMenu extends GraphMenu {
|
||||
VisualiserMenuItem m_select_all;
|
||||
VisualiserMenuItem m_unselect_all;
|
||||
VisualiserMenuItem m_multiselection;
|
||||
JMenu mLanguage;
|
||||
JMenu mStyle;
|
||||
JMenu mType;
|
||||
public ProjectFilesMenu(StyledTree tree) {
|
||||
super(tree, "подпапки");
|
||||
addSeparator();
|
||||
JMenuItem m = new VisualiserMenuItem("Открыть в проводнике...", "/icons/Explorer.png");
|
||||
m.addActionListener(
|
||||
new AbstractAction() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
try {
|
||||
Desktop.getDesktop().open(Current.getProject().Home);
|
||||
} catch (Exception ex) {
|
||||
Global.Log.PrintException(ex);
|
||||
}
|
||||
}
|
||||
});
|
||||
add(m);
|
||||
addSeparator();
|
||||
add(new PassesSubMenu("Добавить", "/icons/RedAdd.png",
|
||||
PassCode_2021.AddFile,
|
||||
PassCode_2021.CreateEmptyDirectory,
|
||||
PassCode_2021.ImportFiles));
|
||||
addSeparator();
|
||||
add(new PassesSubMenu("Переименовать", "/icons/Menu/Rename.png",
|
||||
PassCode_2021.RenameFile,
|
||||
PassCode_2021.RenameDirectory));
|
||||
add(new VisualiserMenuItem("Удалить текущий проект", "/icons/Delete.png") {
|
||||
{
|
||||
addActionListener(e -> {
|
||||
if (Current.HasProject()) {
|
||||
UI.getVersionsWindow().getVersionsForm().getTree().SelectNode(Current.getProject().node);
|
||||
Pass_2021.passes.get(PassCode_2021.DeleteVersion).Do();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
addSeparator();
|
||||
m_multiselection = new VisualiserMenuItem("Массовый режим работы с файлами");
|
||||
m_multiselection.setIcon(Utils.getIcon(Global.files_multiselection ? "/icons/Pick.png" : "/icons/NotPick.png"));
|
||||
m_multiselection.addActionListener(e -> {
|
||||
Global.files_multiselection = !Global.files_multiselection;
|
||||
m_multiselection.setIcon(Utils.getIcon(Global.files_multiselection ? "/icons/Pick.png" : "/icons/NotPick.png"));
|
||||
Current.getProject().SelectAllFiles(false);
|
||||
UI.getMainWindow().getProjectWindow().RefreshProjectFiles();
|
||||
|
||||
//-
|
||||
});
|
||||
add(m_multiselection);
|
||||
addSeparator();
|
||||
//-
|
||||
m_select_all = new StableMenuItem("Выбрать всё", "/icons/SelectAll.png");
|
||||
m_select_all.addActionListener(e -> {
|
||||
Current.getProject().SelectAllFiles(true);
|
||||
tree.updateUI();
|
||||
});
|
||||
add(m_select_all);
|
||||
m_unselect_all = new StableMenuItem("Отменить всё", "/icons/UnselectAll.png");
|
||||
m_unselect_all.addActionListener(e -> {
|
||||
Current.getProject().SelectAllFiles(false);
|
||||
tree.updateUI();
|
||||
});
|
||||
add(m_unselect_all);
|
||||
//--------------------------------------------------
|
||||
add(mLanguage = new LanguagesSubmenu(PassCode_2021.SetSelectedFilesLanguage.getDescription()) {
|
||||
@Override
|
||||
public void action(LanguageName languageName) {
|
||||
Pass_2021.passes.get(PassCode_2021.SetSelectedFilesLanguage).Do(languageName);
|
||||
}
|
||||
});
|
||||
add(mStyle = new StylesSubmenu(PassCode_2021.SetSelectedFilesStyle.getDescription()) {
|
||||
@Override
|
||||
public void action(LanguageStyle languageStyle) {
|
||||
Pass_2021.passes.get(PassCode_2021.SetSelectedFilesStyle).Do(languageStyle);
|
||||
}
|
||||
});
|
||||
add(mType = new TypesSubmenu(PassCode_2021.SetSelectedFilesType.getDescription()) {
|
||||
@Override
|
||||
public void action(FileType fileType) {
|
||||
Pass_2021.passes.get(PassCode_2021.SetSelectedFilesType).Do(fileType);
|
||||
}
|
||||
});
|
||||
//--------------------------------------------------
|
||||
add(Pass_2021.passes.get(PassCode_2021.ExcludeSelectedFiles).createMenuItem());
|
||||
add(Pass_2021.passes.get(PassCode_2021.IncludeSelectedFiles).createMenuItem());
|
||||
add(Pass_2021.passes.get(PassCode_2021.ExcludeFile).createMenuItem());
|
||||
add(Pass_2021.passes.get(PassCode_2021.IncludeFile).createMenuItem());
|
||||
add(Pass_2021.passes.get(PassCode_2021.DeleteFile).createMenuItem());
|
||||
add(Pass_2021.passes.get(PassCode_2021.DeleteDirectory).createMenuItem());
|
||||
add(Pass_2021.passes.get(PassCode_2021.DeleteSelectedFiles).createMenuItem());
|
||||
}
|
||||
@Override
|
||||
public void CheckElementsVisibility() {
|
||||
m_select_all.setVisible(Global.files_multiselection);
|
||||
m_unselect_all.setVisible(Global.files_multiselection);
|
||||
mLanguage.setVisible(Global.files_multiselection);
|
||||
mStyle.setVisible(Global.files_multiselection);
|
||||
mType.setVisible(Global.files_multiselection);
|
||||
//-
|
||||
Pass_2021.passes.get(PassCode_2021.ExcludeFile).setControlsVisible(!Global.files_multiselection);
|
||||
Pass_2021.passes.get(PassCode_2021.IncludeFile).setControlsVisible(!Global.files_multiselection);
|
||||
//-
|
||||
Pass_2021.passes.get(PassCode_2021.DeleteFile).setControlsVisible(!Global.files_multiselection);
|
||||
Pass_2021.passes.get(PassCode_2021.DeleteDirectory).setControlsVisible(!Global.files_multiselection);
|
||||
//--
|
||||
Pass_2021.passes.get(PassCode_2021.ExcludeSelectedFiles).setControlsVisible(Global.files_multiselection);
|
||||
Pass_2021.passes.get(PassCode_2021.IncludeSelectedFiles).setControlsVisible(Global.files_multiselection);
|
||||
Pass_2021.passes.get(PassCode_2021.DeleteSelectedFiles).setControlsVisible(Global.files_multiselection);
|
||||
}
|
||||
}
|
||||
|
||||
18
src/Common/UI/Menus/PropertiesSubmenu.java
Normal file
18
src/Common/UI/Menus/PropertiesSubmenu.java
Normal file
@@ -0,0 +1,18 @@
|
||||
package Common.UI.Menus;
|
||||
import Common.Current;
|
||||
import Common.Global;
|
||||
import Common.UI.Themes.VisualiserFonts;
|
||||
import Common.Utils.Utils;
|
||||
|
||||
import javax.swing.*;
|
||||
public class PropertiesSubmenu extends JMenu {
|
||||
public PropertiesSubmenu(String title, String icon, String... settings) {
|
||||
super(title);
|
||||
if (icon != null)
|
||||
setIcon(Utils.getIcon(icon));
|
||||
setFont(Current.getTheme().Fonts.get(VisualiserFonts.Menu));
|
||||
for (String name : settings) {
|
||||
Global.properties.addFlagMenuItem(this, name);
|
||||
}
|
||||
}
|
||||
}
|
||||
86
src/Common/UI/Menus/SelectionTreeMenu.java
Normal file
86
src/Common/UI/Menus/SelectionTreeMenu.java
Normal file
@@ -0,0 +1,86 @@
|
||||
package Common.UI.Menus;
|
||||
import Common.Current;
|
||||
import Common.UI.Menus_2023.StableMenuItem;
|
||||
import Common.UI.Selectable;
|
||||
import Common.UI.Trees.DataTree;
|
||||
import Common.UI.Trees.SelectableTree;
|
||||
import Common.Utils.Utils;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
public abstract class SelectionTreeMenu extends GraphMenu<DataTree> {
|
||||
VisualiserMenuItem m_select_for_current;
|
||||
VisualiserMenuItem m_unselect_for_current;
|
||||
VisualiserMenuItem m_select_all;
|
||||
VisualiserMenuItem m_unselect_all;
|
||||
public SelectionTreeMenu(SelectableTree tree_in) {
|
||||
super(tree_in, "");
|
||||
addSeparator();
|
||||
//-
|
||||
m_select_all = new StableMenuItem("Выбрать всё", "/icons/SelectAll.png");
|
||||
m_select_all.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
SelectAll(true);
|
||||
tree.updateUI();
|
||||
}
|
||||
});
|
||||
add(m_select_all);
|
||||
m_unselect_all = new StableMenuItem("Отменить всё", "/icons/UnselectAll.png");
|
||||
m_unselect_all.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
SelectAll(false);
|
||||
tree.updateUI();
|
||||
}
|
||||
});
|
||||
add(m_unselect_all);
|
||||
addSeparator();
|
||||
m_select_for_current = new VisualiserMenuItem("");
|
||||
m_select_for_current.addActionListener(new AbstractAction() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
Object o = Current.get(tree.getCurrent());
|
||||
if (o instanceof Selectable) {
|
||||
((Selectable) o).SelectAllChildren(true);
|
||||
}
|
||||
tree.updateUI();
|
||||
}
|
||||
});
|
||||
add(m_select_for_current);
|
||||
//--------
|
||||
m_unselect_for_current = new VisualiserMenuItem("");
|
||||
m_unselect_for_current.addActionListener(new AbstractAction() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
Object o = Current.get(tree.getCurrent());
|
||||
if (o instanceof Selectable) {
|
||||
((Selectable) o).SelectAllChildren(false);
|
||||
}
|
||||
tree.updateUI();
|
||||
}
|
||||
});
|
||||
//-------
|
||||
add(m_unselect_for_current);
|
||||
}
|
||||
public abstract Class getTargetClass(); //для кого позволяется выбирать всех потомков.
|
||||
public abstract void SelectAll(boolean select);
|
||||
@Override
|
||||
public void CheckElementsVisibility() {
|
||||
Object current = Current.get(tree.getCurrent());
|
||||
if ((current != null) && (current.getClass().equals(getTargetClass()))) {
|
||||
String name = ((Selectable) current).getSelectionText();
|
||||
m_select_for_current.setText("Выбрать всё для " +
|
||||
Utils.Brackets(name));
|
||||
m_unselect_for_current.setText("Отменить выбор всех для " +
|
||||
Utils.Brackets(name));
|
||||
//-
|
||||
m_select_for_current.setVisible(true);
|
||||
m_unselect_for_current.setVisible(true);
|
||||
} else {
|
||||
m_select_for_current.setVisible(false);
|
||||
m_unselect_for_current.setVisible(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
38
src/Common/UI/Menus/StyledPopupMenu.java
Normal file
38
src/Common/UI/Menus/StyledPopupMenu.java
Normal file
@@ -0,0 +1,38 @@
|
||||
package Common.UI.Menus;
|
||||
import Common.Current;
|
||||
import Common.UI.Themes.ThemeElement;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.event.PopupMenuEvent;
|
||||
import javax.swing.event.PopupMenuListener;
|
||||
public class StyledPopupMenu extends JPopupMenu implements ThemeElement {
|
||||
public StyledPopupMenu() {
|
||||
addPopupMenuListener(new PopupMenuListener() {
|
||||
@Override
|
||||
public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
|
||||
CheckElementsVisibility();
|
||||
}
|
||||
@Override
|
||||
public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
|
||||
}
|
||||
@Override
|
||||
public void popupMenuCanceled(PopupMenuEvent e) {
|
||||
}
|
||||
});
|
||||
}
|
||||
private void refreshTheme_r(MenuElement element) {
|
||||
element.getComponent().setBackground(Current.getTheme().background);
|
||||
element.getComponent().setForeground(Current.getTheme().foreground);
|
||||
for (MenuElement se : element.getSubElements())
|
||||
refreshTheme_r(se);
|
||||
}
|
||||
@Override
|
||||
public void applyTheme() {
|
||||
setBackground(Current.getTheme().background);
|
||||
setForeground(Current.getTheme().foreground);
|
||||
refreshTheme_r(this);
|
||||
}
|
||||
public void CheckElementsVisibility() {
|
||||
applyTheme();
|
||||
}
|
||||
}
|
||||
29
src/Common/UI/Menus/TableMenu.java
Normal file
29
src/Common/UI/Menus/TableMenu.java
Normal file
@@ -0,0 +1,29 @@
|
||||
package Common.UI.Menus;
|
||||
import Common.Utils.Utils;
|
||||
|
||||
import javax.swing.*;
|
||||
public class TableMenu extends StyledPopupMenu {
|
||||
int row = Utils.Nan;
|
||||
int column = Utils.Nan;
|
||||
Object target = null;
|
||||
//-
|
||||
JTable owner = null;
|
||||
VisualiserMenuItem mcopy;
|
||||
public TableMenu(JTable owner_in) {
|
||||
owner = owner_in;
|
||||
mcopy = new VisualiserMenuItem("Копировать текст текущей ячейки", "/icons/Editor/Copy.png");
|
||||
//если удалось нажать значит все условия выполнены
|
||||
mcopy.addActionListener(e -> Utils.CopyToClipboard(target.toString()));
|
||||
add(mcopy);
|
||||
}
|
||||
@Override
|
||||
public void CheckElementsVisibility() {
|
||||
row = owner.getSelectedRow();
|
||||
column = owner.getSelectedColumn();
|
||||
if ((row >= 0) && (column >= 0)) {
|
||||
target = owner.getValueAt(row, column);
|
||||
mcopy.setVisible(true);
|
||||
} else mcopy.setVisible(false);
|
||||
super.CheckElementsVisibility();
|
||||
}
|
||||
}
|
||||
28
src/Common/UI/Menus/TestsCompilationFilterMenu.java
Normal file
28
src/Common/UI/Menus/TestsCompilationFilterMenu.java
Normal file
@@ -0,0 +1,28 @@
|
||||
package Common.UI.Menus;
|
||||
import GlobalData.Tasks.TaskState;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.event.ActionListener;
|
||||
public class TestsCompilationFilterMenu extends StyledPopupMenu{
|
||||
public void CreateStateItem(TaskState state, ActionListener listener){
|
||||
JMenuItem m = new VisualiserMenuItem(state.getDescription());
|
||||
m.addActionListener(listener);
|
||||
add(m);
|
||||
}
|
||||
public TestsCompilationFilterMenu(){
|
||||
for (TaskState taskState: TaskState.values()){
|
||||
switch (taskState){
|
||||
case Queued:
|
||||
case FailedToQueue:
|
||||
case NoSuchTask:
|
||||
case AbortingByUser:
|
||||
break;
|
||||
case Waiting:
|
||||
CreateStateItem(taskState, e -> {
|
||||
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
42
src/Common/UI/Menus/TextComboBoxMenu.java
Normal file
42
src/Common/UI/Menus/TextComboBoxMenu.java
Normal file
@@ -0,0 +1,42 @@
|
||||
package Common.UI.Menus;
|
||||
import Common.UI.UI;
|
||||
import Common.Utils.Utils;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
public class TextComboBoxMenu extends StyledPopupMenu {
|
||||
protected JComboBox<String> box;
|
||||
protected String selectedText = null;
|
||||
//-------------------------------------------------
|
||||
JMenuItem m_copy;
|
||||
JMenuItem m_paste;
|
||||
//-------------------------------------------------
|
||||
public TextComboBoxMenu(JComboBox<String> box_in) {
|
||||
box = box_in;
|
||||
m_copy = new VisualiserMenuItem("Копировать", "/icons/Editor/Copy.png");
|
||||
m_copy.addActionListener(
|
||||
new AbstractAction() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
Utils.CopyToClipboard(box.getSelectedItem().toString());
|
||||
}
|
||||
});
|
||||
add(m_copy);
|
||||
m_paste = new VisualiserMenuItem("Вставить", "/icons/Editor/Paste.png");
|
||||
m_paste.addActionListener(
|
||||
new AbstractAction() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
UI.TrySelect(box, Utils.getFromClipboard());
|
||||
}
|
||||
});
|
||||
add(m_paste);
|
||||
}
|
||||
@Override
|
||||
public void CheckElementsVisibility() {
|
||||
boolean visible_ = box.getSelectedIndex() >= 0;
|
||||
m_paste.setVisible(visible_);
|
||||
m_copy.setVisible(visible_);
|
||||
super.CheckElementsVisibility();
|
||||
}
|
||||
}
|
||||
86
src/Common/UI/Menus/TextEditorMenu.java
Normal file
86
src/Common/UI/Menus/TextEditorMenu.java
Normal file
@@ -0,0 +1,86 @@
|
||||
package Common.UI.Menus;
|
||||
import Common.Utils.Utils;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.text.JTextComponent;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.util.Vector;
|
||||
public class TextEditorMenu extends StyledPopupMenu {
|
||||
protected JTextComponent editor;
|
||||
protected String selectedText = null;
|
||||
//-------------------------------------------------
|
||||
JMenuItem m_cut;
|
||||
JMenuItem m_copy;
|
||||
JMenuItem m_paste;
|
||||
protected JMenuItem m_strike;
|
||||
protected JMenuItem m_unstrike;
|
||||
//-------------------------------------------------
|
||||
public TextEditorMenu(JTextComponent editor_in) {
|
||||
editor = editor_in;
|
||||
m_cut = new VisualiserMenuItem("Вырезать", "/icons/Editor/Cut.png");
|
||||
m_cut.addActionListener(new AbstractAction() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
editor.cut();
|
||||
}
|
||||
});
|
||||
add(m_cut);
|
||||
m_copy = new VisualiserMenuItem("Копировать", "/icons/Editor/Copy.png");
|
||||
m_copy.addActionListener(
|
||||
new AbstractAction() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
editor.copy();
|
||||
}
|
||||
});
|
||||
add(m_copy);
|
||||
m_paste = new VisualiserMenuItem("Вставить", "/icons/Editor/Paste.png");
|
||||
m_paste.addActionListener(
|
||||
new AbstractAction() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
editor.paste();
|
||||
}
|
||||
});
|
||||
add(m_paste);
|
||||
//--
|
||||
m_strike = new VisualiserMenuItem("Вычеркнуть","/icons/Editor/Strikethrough.png");
|
||||
m_strike.addActionListener(
|
||||
new AbstractAction() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
String[] data = selectedText.split("\n");
|
||||
Vector<String> new_data = new Vector<>();
|
||||
for (String line: data){
|
||||
new_data.add(Utils.strikeThrough(line));
|
||||
}
|
||||
editor.replaceSelection(String.join("\n", new_data));
|
||||
}
|
||||
});
|
||||
add(m_strike);
|
||||
m_unstrike = new VisualiserMenuItem("Отменить вычёркивание","/icons/Editor/NoStrike.png");
|
||||
m_unstrike.addActionListener(
|
||||
new AbstractAction() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
String[] data = selectedText.split("\n");
|
||||
Vector<String> new_data = new Vector<>();
|
||||
for (String line: data){
|
||||
new_data.add(Utils.noStrikeThrough(line));
|
||||
}
|
||||
editor.replaceSelection(String.join("\n", new_data));
|
||||
}
|
||||
});
|
||||
add(m_unstrike);
|
||||
}
|
||||
@Override
|
||||
public void CheckElementsVisibility() {
|
||||
selectedText = editor.getSelectedText();
|
||||
m_cut.setVisible(editor.isEditable() && (selectedText != null));
|
||||
m_paste.setVisible(editor.isEditable());
|
||||
m_copy.setVisible(selectedText != null);
|
||||
m_strike.setVisible(editor.isEditable() && (selectedText != null));
|
||||
m_unstrike.setVisible(editor.isEditable() && (selectedText != null));
|
||||
super.CheckElementsVisibility();
|
||||
}
|
||||
}
|
||||
53
src/Common/UI/Menus/VersionsMenu.java
Normal file
53
src/Common/UI/Menus/VersionsMenu.java
Normal file
@@ -0,0 +1,53 @@
|
||||
package Common.UI.Menus;
|
||||
import Common.Current;
|
||||
import Common.Global;
|
||||
import Common.UI.Menus_2023.StableMenuItem;
|
||||
import Common.UI.Trees.DataTree;
|
||||
import Common.UI.UI;
|
||||
import Common.Utils.Utils;
|
||||
import Visual_DVM_2021.Passes.PassCode_2021;
|
||||
import Visual_DVM_2021.Passes.Pass_2021;
|
||||
public class VersionsMenu extends GraphMenu<DataTree> {
|
||||
VisualiserMenuItem m_select_all;
|
||||
VisualiserMenuItem m_unselect_all;
|
||||
VisualiserMenuItem m_multiselection;
|
||||
public VersionsMenu(DataTree tree) {
|
||||
super(tree, "подверсии");
|
||||
add(Pass_2021.passes.get(PassCode_2021.DeleteSubversions).createMenuItem());
|
||||
add(Pass_2021.passes.get(PassCode_2021.DeleteLonelyM).createMenuItem());
|
||||
addSeparator();
|
||||
m_multiselection = new VisualiserMenuItem("Массовый режим работы с версиями");
|
||||
m_multiselection.setIcon(Utils.getIcon(Global.versions_multiselection ? "/icons/Pick.png" : "/icons/NotPick.png"));
|
||||
m_multiselection.addActionListener(e -> {
|
||||
Global.versions_multiselection = !Global.versions_multiselection;
|
||||
m_multiselection.setIcon(Utils.getIcon(Global.versions_multiselection ? "/icons/Pick.png" : "/icons/NotPick.png"));
|
||||
Current.getRoot().SelectAllVersions(false);
|
||||
UI.getVersionsWindow().getVersionsForm().getTree().updateUI();
|
||||
});
|
||||
add(m_multiselection);
|
||||
addSeparator();
|
||||
add(Pass_2021.passes.get(PassCode_2021.DeleteVersion).createMenuItem());
|
||||
//-
|
||||
m_select_all = new StableMenuItem("Выбрать всё, кроме резервных копий","/icons/SelectAll.png");
|
||||
m_select_all.addActionListener(e -> {
|
||||
Current.getRoot().SelectAllVersions(true);
|
||||
tree.updateUI();
|
||||
});
|
||||
add(m_select_all);
|
||||
m_unselect_all = new StableMenuItem("Отменить всё","/icons/UnselectAll.png");
|
||||
m_unselect_all.addActionListener(e -> {
|
||||
Current.getRoot().SelectAllVersions(false);
|
||||
tree.updateUI();
|
||||
});
|
||||
add(m_unselect_all);
|
||||
add(Pass_2021.passes.get(PassCode_2021.DeleteSelectedVersions).createMenuItem());
|
||||
}
|
||||
@Override
|
||||
public void CheckElementsVisibility() {
|
||||
Pass_2021.passes.get(PassCode_2021.DeleteSelectedVersions).setControlsVisible(!Global.versions_multiselection);
|
||||
Pass_2021.passes.get(PassCode_2021.DeleteSelectedVersions).setControlsVisible(Global.versions_multiselection);
|
||||
Pass_2021.passes.get(PassCode_2021.DeleteVersion).setControlsVisible(!Global.versions_multiselection);
|
||||
m_select_all.setVisible(Global.versions_multiselection);
|
||||
m_unselect_all.setVisible(Global.versions_multiselection);
|
||||
}
|
||||
}
|
||||
21
src/Common/UI/Menus/VisualiserMenuItem.java
Normal file
21
src/Common/UI/Menus/VisualiserMenuItem.java
Normal file
@@ -0,0 +1,21 @@
|
||||
package Common.UI.Menus;
|
||||
import Common.Current;
|
||||
import Common.UI.Themes.VisualiserFonts;
|
||||
import Common.Utils.Utils;
|
||||
|
||||
import javax.swing.*;
|
||||
public class VisualiserMenuItem extends JMenuItem {
|
||||
public VisualiserMenuItem(String text) {
|
||||
super(text, null);
|
||||
setFont(Current.getTheme().Fonts.get(VisualiserFonts.Menu));
|
||||
}
|
||||
public VisualiserMenuItem(String text, String icon_path) {
|
||||
super(text);
|
||||
setFont(Current.getTheme().Fonts.get(VisualiserFonts.Menu));
|
||||
if (icon_path != null)
|
||||
setIcon(Utils.getIcon(icon_path));
|
||||
}
|
||||
public VisualiserMenuItem(){
|
||||
setFont(Current.getTheme().Fonts.get(VisualiserFonts.Menu));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package Common.UI.Menus_2023.BugReportsMenuBar;
|
||||
import Common.UI.Menus_2023.DataMenuBar;
|
||||
import Visual_DVM_2021.Passes.PassCode_2021;
|
||||
public class BugReportsMenuBar extends DataMenuBar {
|
||||
public BugReportsMenuBar() {
|
||||
super("отчёты об ошибках",
|
||||
PassCode_2021.SynchronizeBugReports,
|
||||
PassCode_2021.DownloadAllBugReportsArchives,
|
||||
PassCode_2021.AddBugReport,
|
||||
PassCode_2021.PublishBugReport,
|
||||
PassCode_2021.OpenBugReportTestProject,
|
||||
PassCode_2021.OpenBugReport,
|
||||
PassCode_2021.UpdateBugReportProgress,
|
||||
PassCode_2021.CloseBugReport,
|
||||
PassCode_2021.DeleteBugReport);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package Common.UI.Menus_2023.CompilersMenuBar;
|
||||
import Common.UI.Menus_2023.DataMenuBar;
|
||||
import Visual_DVM_2021.Passes.PassCode_2021;
|
||||
public class CompilersMenuBar extends DataMenuBar {
|
||||
public CompilersMenuBar() {
|
||||
super("компиляторы",
|
||||
PassCode_2021.AddCompiler,
|
||||
PassCode_2021.EditCompiler,
|
||||
PassCode_2021.DeleteCompiler,
|
||||
PassCode_2021.ShowCompilerVersion,
|
||||
PassCode_2021.ShowCompilerHelp);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package Common.UI.Menus_2023.ComponentsMenuBar;
|
||||
import Common.Current;
|
||||
import Common.UI.Menus_2023.DataMenuBar;
|
||||
import Common.UI.Menus_2023.VisualiserMenu;
|
||||
import Common.UI.Themes.VisualiserFonts;
|
||||
import Visual_DVM_2021.Passes.PassCode_2021;
|
||||
import Visual_DVM_2021.Passes.Pass_2021;
|
||||
public class ComponentsMenuBar extends DataMenuBar {
|
||||
public ComponentsMenuBar() {
|
||||
super("компоненты");
|
||||
addMenus(
|
||||
new VisualiserMenu(
|
||||
"Восстановление предыдущей версии компонента", "/icons/Resurrect.png") {
|
||||
{
|
||||
setFont(Current.getTheme().Fonts.get(VisualiserFonts.Menu));
|
||||
add(Pass_2021.passes.get(PassCode_2021.ResurrectComponent).createMenuItem());
|
||||
add(Pass_2021.passes.get(PassCode_2021.ResurrectComponentFromServer).createMenuItem());
|
||||
}
|
||||
}
|
||||
);
|
||||
addPasses(PassCode_2021.InstallComponentFromFolder,
|
||||
PassCode_2021.UpdateSelectedComponents,
|
||||
PassCode_2021.PublishComponent,
|
||||
PassCode_2021.ShowComponentChangesLog);
|
||||
Pass_2021.passes.get(PassCode_2021.PublishComponent).setControlsVisible(false);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package Common.UI.Menus_2023.ConfigurationsMenuBar;
|
||||
import Common.UI.Menus_2023.DataMenuBar;
|
||||
import Visual_DVM_2021.Passes.PassCode_2021;
|
||||
public class ConfigurationsMenuBar extends DataMenuBar {
|
||||
public ConfigurationsMenuBar() {
|
||||
super("конфигурации");
|
||||
/*
|
||||
add(new MenuBarButton() {
|
||||
{
|
||||
setText("Оповещение по email");
|
||||
setToolTipText("Оповещение о прогрессе выполнения пакета тестов");
|
||||
Mark();
|
||||
addActionListener(e -> {
|
||||
email = !email;
|
||||
Mark();
|
||||
});
|
||||
}
|
||||
public void Mark() {
|
||||
setIcon(Utils.getIcon(email ? "/icons/Pick.png" : "/icons/NotPick.png"));
|
||||
}
|
||||
|
||||
});
|
||||
*/
|
||||
addPasses(
|
||||
PassCode_2021.EditMachineKernels,
|
||||
PassCode_2021.StartTests,
|
||||
PassCode_2021.PublishConfiguration,
|
||||
PassCode_2021.CopyConfigurations,
|
||||
PassCode_2021.EditConfiguration,
|
||||
PassCode_2021.DeleteSelectedConfigurations
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package Common.UI.Menus_2023.DVMParametersMenuBar;
|
||||
import Common.UI.Menus_2023.DataMenuBar;
|
||||
import Visual_DVM_2021.Passes.PassCode_2021;
|
||||
public class DVMParametersMenuBar extends DataMenuBar {
|
||||
public DVMParametersMenuBar() {
|
||||
super("параметры",
|
||||
PassCode_2021.AddDVMParameter,
|
||||
PassCode_2021.EditDVMParameter,
|
||||
PassCode_2021.DeleteDVMParameter);
|
||||
}
|
||||
}
|
||||
54
src/Common/UI/Menus_2023/DataMenuBar.java
Normal file
54
src/Common/UI/Menus_2023/DataMenuBar.java
Normal file
@@ -0,0 +1,54 @@
|
||||
package Common.UI.Menus_2023;
|
||||
import Common.Database.DataSet;
|
||||
import Visual_DVM_2021.Passes.PassCode_2021;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.ActionListener;
|
||||
public class DataMenuBar extends VisualiserMenuBar {
|
||||
public JLabel countLabel = null;
|
||||
JButton selectAllButton = null;
|
||||
JButton unselectAllButton = null;
|
||||
//-
|
||||
public ActionListener selectAllListener = null;
|
||||
public ActionListener unselectAllListener = null;
|
||||
//-
|
||||
public DataMenuBar(String dataName, PassCode_2021... passes) {
|
||||
// Font font = Current.getTheme().Fonts.get(VisualiserFonts.TreeBoldItalic).deriveFont(12.0F);
|
||||
add(new JLabel(dataName + " "));
|
||||
add(countLabel = new JLabel("?"));
|
||||
addPasses(passes);
|
||||
}
|
||||
public void createSelectionButtons(DataSet dataSet) {
|
||||
java.awt.Dimension d = new Dimension(25, 25);
|
||||
if (selectAllButton == null) {
|
||||
add(selectAllButton = new MenuBarButton() {
|
||||
{
|
||||
setIcon("/icons/SelectAll.png");
|
||||
setToolTipText("Выбрать всё");
|
||||
setPreferredSize(d);
|
||||
setMinimumSize(d);
|
||||
setMaximumSize(d);
|
||||
}
|
||||
}, 0);
|
||||
}
|
||||
if (unselectAllButton == null) {
|
||||
add(unselectAllButton = new MenuBarButton() {
|
||||
{
|
||||
setIcon("/icons/UnselectAll.png");
|
||||
setToolTipText("Отменить всё");
|
||||
setPreferredSize(d);
|
||||
setMinimumSize(d);
|
||||
setMaximumSize(d);
|
||||
}
|
||||
}, 1);
|
||||
}
|
||||
if (selectAllListener != null) {
|
||||
selectAllButton.removeActionListener(selectAllListener); }
|
||||
selectAllButton.addActionListener(selectAllListener = e -> dataSet.CheckAll(true));
|
||||
if (unselectAllListener != null) {
|
||||
unselectAllButton.removeActionListener(unselectAllListener);
|
||||
}
|
||||
unselectAllButton.addActionListener(unselectAllListener = e -> dataSet.CheckAll(false));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package Common.UI.Menus_2023.EnvironmentValuesMenuBar;
|
||||
import Common.UI.Menus_2023.DataMenuBar;
|
||||
import Visual_DVM_2021.Passes.PassCode_2021;
|
||||
public class EnvironmentValuesMenuBar extends DataMenuBar {
|
||||
public EnvironmentValuesMenuBar() {
|
||||
super("переменные окружения", PassCode_2021.AddEnvironmentValue,
|
||||
PassCode_2021.EditEnvironmentValue,
|
||||
PassCode_2021.DeleteEnvironmentValue,
|
||||
PassCode_2021.PickCompilerEnvironments
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package Common.UI.Menus_2023.FastAccessMenuBar;
|
||||
import Common.Global;
|
||||
import Common.UI.Menus_2023.VisualiserMenuBar;
|
||||
import Common.UI.UI;
|
||||
import GlobalData.Settings.SettingName;
|
||||
import Visual_DVM_2021.Passes.PassCode_2021;
|
||||
import Visual_DVM_2021.Passes.Pass_2021;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.util.LinkedHashMap;
|
||||
public class FastAccessMenuBar extends VisualiserMenuBar {
|
||||
LinkedHashMap<PassCode_2021, JButton> passesButtons = new LinkedHashMap<>();
|
||||
public FastAccessMenuBar() {
|
||||
Refresh();
|
||||
}
|
||||
@Override
|
||||
public void setSizeLimits() {
|
||||
//если задавать PreffredSize 0, скролл НЕ РАБОТАЕТ. Магия!
|
||||
}
|
||||
public void showPass(Pass_2021 pass) {
|
||||
JButton button = null;
|
||||
if (passesButtons.containsKey(pass.code()))
|
||||
button = passesButtons.get((pass.code()));
|
||||
else {
|
||||
button = pass.createButton();
|
||||
passesButtons.put(pass.code(), button);
|
||||
}
|
||||
add(button);
|
||||
Dimension d = button.getPreferredSize();
|
||||
button.setPreferredSize(new Dimension(d.width, 30));
|
||||
revalidate();
|
||||
repaint();
|
||||
}
|
||||
public void Refresh() {
|
||||
UI.Clear(this);
|
||||
int i = 1;
|
||||
for (Pass_2021 pass : Pass_2021.FAPasses) {
|
||||
if (pass.stats.HasUsages()) {
|
||||
showPass(pass);
|
||||
++i;
|
||||
if (i > (Global.db.settings.get(SettingName.FastAccessPassesCount).toInt32())) break;
|
||||
}
|
||||
}
|
||||
}
|
||||
public void Drop(){
|
||||
UI.Clear(this);
|
||||
}
|
||||
}
|
||||
84
src/Common/UI/Menus_2023/FileMenuBar/FileMenuBar.java
Normal file
84
src/Common/UI/Menus_2023/FileMenuBar/FileMenuBar.java
Normal file
@@ -0,0 +1,84 @@
|
||||
package Common.UI.Menus_2023.FileMenuBar;
|
||||
import Common.UI.Menus_2023.MenuBarButton;
|
||||
import Common.UI.Menus_2023.VisualiserMenuBar;
|
||||
import Common.UI.UI;
|
||||
import ProjectData.Files.UI.Editor.SPFEditor;
|
||||
import Visual_DVM_2021.Passes.PassCode_2021;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
public class FileMenuBar extends VisualiserMenuBar {
|
||||
public JSpinner sToGo;
|
||||
JLabel LineCountLabel;
|
||||
public JLabel CurrentSymbolLabel;
|
||||
SPFEditor editor;
|
||||
FileSettingsMenu fileSettingsMenu;
|
||||
public FileMenuBar(SPFEditor editor_in) {
|
||||
editor = editor_in;
|
||||
add(new MenuBarButton() {
|
||||
{
|
||||
setToolTipText("Поиск(Ctrl+F)");
|
||||
setIcon("/icons/LastOpened.png");
|
||||
addActionListener(e -> UI.ShowSearchForm());
|
||||
}
|
||||
});
|
||||
addPasses(PassCode_2021.Save);
|
||||
add(new MenuBarButton() {
|
||||
{
|
||||
setToolTipText("Увеличить шрифт(Ctrl+'+')");
|
||||
setIcon("/icons/Editor/Font+.png");
|
||||
addActionListener(e -> editor.FontUp());
|
||||
}
|
||||
});
|
||||
add(new MenuBarButton() {
|
||||
{
|
||||
setToolTipText("Уменьшить шрифт(Ctrl+'-')");
|
||||
setIcon("/icons/Editor/Font-.png");
|
||||
addActionListener(e -> editor.FontDown());
|
||||
}
|
||||
});
|
||||
add(new MenuBarButton() {
|
||||
boolean isOn = false;
|
||||
{
|
||||
setToolTipText("Отображать спецсимволы");
|
||||
setIcon("/icons/Editor/ShowNoSigns.png");
|
||||
addActionListener(e-> {
|
||||
isOn = !isOn;
|
||||
if (isOn) {
|
||||
setIcon("/icons/Editor/ShowAllSigns.png");
|
||||
setToolTipText("Скрыть спецсимволы");
|
||||
editor.setWhitespaceVisible(true);
|
||||
editor.setEOLMarkersVisible(true);
|
||||
} else {
|
||||
setIcon("/icons/Editor/ShowNoSigns.png");
|
||||
setToolTipText("Отображать спецсимволы");
|
||||
editor.setWhitespaceVisible(false);
|
||||
editor.setEOLMarkersVisible(false);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
add(new JLabel(" Строка "));
|
||||
add(sToGo = new JSpinner());
|
||||
sToGo.setPreferredSize(new Dimension(60, 25));
|
||||
sToGo.setMaximumSize(new Dimension(60, 25));
|
||||
add(new JLabel(" из "));
|
||||
add(LineCountLabel = new JLabel("?"));
|
||||
add(new JLabel(" | "));
|
||||
add(new JLabel("Позиция "));
|
||||
add(CurrentSymbolLabel = new JLabel());
|
||||
add(new JSeparator());
|
||||
addMenus(fileSettingsMenu = new FileSettingsMenu());
|
||||
//--
|
||||
// addPasses(PassCode_2021.CloseCurrentFile);
|
||||
//-
|
||||
setPreferredSize(new Dimension(0, 30));
|
||||
}
|
||||
public void ShowLinesCount() {
|
||||
LineCountLabel.setText(String.valueOf(editor.getLineCount()));
|
||||
}
|
||||
//-
|
||||
public void ShowLanguage(){fileSettingsMenu.ShowLanguage();}
|
||||
public void ShowType(){fileSettingsMenu.ShowType();}
|
||||
public void ShowStyle(){fileSettingsMenu.ShowStyle();}
|
||||
}
|
||||
63
src/Common/UI/Menus_2023/FileMenuBar/FileSettingsMenu.java
Normal file
63
src/Common/UI/Menus_2023/FileMenuBar/FileSettingsMenu.java
Normal file
@@ -0,0 +1,63 @@
|
||||
package Common.UI.Menus_2023.FileMenuBar;
|
||||
import Common.Current;
|
||||
import Common.UI.Menus_2023.LanguagesSubmenu;
|
||||
import Common.UI.Menus_2023.StylesSubmenu;
|
||||
import Common.UI.Menus_2023.TypesSubmenu;
|
||||
import Common.UI.Menus_2023.VisualiserMenu;
|
||||
import Common.UI.UI;
|
||||
import ProjectData.Files.FileType;
|
||||
import ProjectData.Files.LanguageStyle;
|
||||
import ProjectData.LanguageName;
|
||||
|
||||
import javax.swing.*;
|
||||
public class FileSettingsMenu extends VisualiserMenu {
|
||||
JMenu mLanguage;
|
||||
JMenu mStyle;
|
||||
JMenu mType;
|
||||
public FileSettingsMenu() {
|
||||
super("Настройки файла", "/icons/Settings.png");
|
||||
add(mLanguage = new LanguagesSubmenu() {
|
||||
@Override
|
||||
public void action(LanguageName languageName) {
|
||||
if (Current.getFile().UpdateLanguage(languageName)) {
|
||||
Current.getSapfor().ResetAllAnalyses();
|
||||
Current.getFile().form.ShowLanguage();
|
||||
UI.getMainWindow().getProjectWindow().getFilesTreeForm().getTree().RefreshNode(Current.getFile().node);
|
||||
}
|
||||
}
|
||||
});
|
||||
ShowLanguage();
|
||||
//--
|
||||
add(mStyle = new StylesSubmenu() {
|
||||
@Override
|
||||
public void action(LanguageStyle languageStyle) {
|
||||
if (Current.getFile().UpdateStyle(languageStyle)) {
|
||||
Current.getSapfor().ResetAllAnalyses();
|
||||
Current.getFile().form.ShowStyle();
|
||||
}
|
||||
}
|
||||
});
|
||||
ShowStyle();
|
||||
//--
|
||||
add(mType = new TypesSubmenu() {
|
||||
@Override
|
||||
public void action(FileType fileType) {
|
||||
if (Current.getFile().UpdateType(fileType)) {
|
||||
Current.getSapfor().ResetAllAnalyses();
|
||||
UI.getMainWindow().getProjectWindow().getFilesTreeForm().getTree().RefreshNode(Current.getFile().node);
|
||||
Current.getFile().form.ShowType();
|
||||
}
|
||||
}
|
||||
});
|
||||
ShowType();
|
||||
}
|
||||
public void ShowLanguage() {
|
||||
mLanguage.setText("Язык: " + Current.getFile().languageName.getDescription());
|
||||
}
|
||||
public void ShowStyle() {
|
||||
mStyle.setText("Стиль: " + Current.getFile().style.getDescription());
|
||||
}
|
||||
public void ShowType() {
|
||||
mType.setText("Тип: " + Current.getFile().fileType.getDescription());
|
||||
}
|
||||
}
|
||||
42
src/Common/UI/Menus_2023/GroupsMenuBar/GroupsMenuBar.java
Normal file
42
src/Common/UI/Menus_2023/GroupsMenuBar/GroupsMenuBar.java
Normal file
@@ -0,0 +1,42 @@
|
||||
package Common.UI.Menus_2023.GroupsMenuBar;
|
||||
import Common.Global;
|
||||
import Common.UI.Menus_2023.DataMenuBar;
|
||||
import Common.UI.Menus_2023.MenuBarButton;
|
||||
import Common.Utils.Utils;
|
||||
import TestingSystem.Group.GroupInterface;
|
||||
import Visual_DVM_2021.Passes.PassCode_2021;
|
||||
|
||||
import javax.swing.*;
|
||||
public class GroupsMenuBar extends DataMenuBar {
|
||||
public GroupsMenuBar() {
|
||||
super("группы", PassCode_2021.SynchronizeTests, PassCode_2021.DownloadGroup, PassCode_2021.ConvertCorrectnessTests, PassCode_2021.PublishGroup, PassCode_2021.CopyGroups, PassCode_2021.EditGroup, PassCode_2021.DeleteSelectedGroups);
|
||||
add(new JSeparator());
|
||||
add(new MenuBarButton() {
|
||||
{
|
||||
setText("Свои");
|
||||
setToolTipText("Отображать только группы тестов авторства пользователя");
|
||||
Mark();
|
||||
addActionListener(e -> {
|
||||
GroupInterface.filterMyOnly = !GroupInterface.filterMyOnly;
|
||||
Mark();
|
||||
Global.testingServer.db.groups.ShowUI();
|
||||
});
|
||||
}
|
||||
public void Mark() {
|
||||
setIcon(Utils.getIcon(GroupInterface.filterMyOnly ? "/icons/Pick.png" : "/icons/NotPick.png"));
|
||||
}
|
||||
});
|
||||
}
|
||||
public void addFilters(JMenu typesFilterMenu, JMenu languagesFilterMenu) {
|
||||
filters = addMenus(typesFilterMenu, languagesFilterMenu);
|
||||
}
|
||||
JMenuBar filters= null;
|
||||
public void DropFilters() {
|
||||
if (filters != null) {
|
||||
remove(filters);
|
||||
filters = null;
|
||||
}
|
||||
revalidate();
|
||||
repaint();
|
||||
}
|
||||
}
|
||||
34
src/Common/UI/Menus_2023/LanguagesSubmenu.java
Normal file
34
src/Common/UI/Menus_2023/LanguagesSubmenu.java
Normal file
@@ -0,0 +1,34 @@
|
||||
package Common.UI.Menus_2023;
|
||||
import Common.Utils.Utils;
|
||||
import ProjectData.LanguageName;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
public abstract class LanguagesSubmenu extends VisualiserMenu {
|
||||
public LanguagesSubmenu() {
|
||||
this("Язык");
|
||||
}
|
||||
public LanguagesSubmenu(String text) {
|
||||
super(text, "/icons/Language.png", true);
|
||||
for (LanguageName languageName : LanguageName.values()) {
|
||||
if (languageName.equals(LanguageName.fortran) ||
|
||||
(languageName.equals(LanguageName.c) ||
|
||||
(languageName.equals(LanguageName.cpp)))) {
|
||||
|
||||
JMenuItem languageItem = new StableMenuItem(languageName.getDescription());
|
||||
String li = languageName.getIcon();
|
||||
if (!li.isEmpty())
|
||||
languageItem.setIcon(Utils.getIcon(li));
|
||||
languageItem.addActionListener(
|
||||
new AbstractAction() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
action(languageName);
|
||||
}
|
||||
});
|
||||
add(languageItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
public abstract void action(LanguageName languageName);
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package Common.UI.Menus_2023.MachinesMenuBar;
|
||||
import Common.UI.Menus_2023.DataMenuBar;
|
||||
import Visual_DVM_2021.Passes.PassCode_2021;
|
||||
public class MachinesMenuBar extends DataMenuBar {
|
||||
public MachinesMenuBar() {
|
||||
super("машины",
|
||||
PassCode_2021.AddMachine,
|
||||
PassCode_2021.EditMachine,
|
||||
PassCode_2021.DeleteMachine);
|
||||
}
|
||||
}
|
||||
14
src/Common/UI/Menus_2023/MainMenuBar/AnalysesMenu.java
Normal file
14
src/Common/UI/Menus_2023/MainMenuBar/AnalysesMenu.java
Normal file
@@ -0,0 +1,14 @@
|
||||
package Common.UI.Menus_2023.MainMenuBar;
|
||||
import Common.UI.Menus_2023.VisualiserMenu;
|
||||
import Repository.Component.Sapfor.Sapfor;
|
||||
import Visual_DVM_2021.Passes.PassCode_2021;
|
||||
import Visual_DVM_2021.Passes.Pass_2021;
|
||||
public class AnalysesMenu extends VisualiserMenu {
|
||||
public AnalysesMenu() {
|
||||
super("Анализаторы","/icons/Analyses.png" );
|
||||
for (PassCode_2021 code : Sapfor.getAnalysesCodes())
|
||||
add(Pass_2021.passes.get(code).createMenuItem());
|
||||
addSeparator();
|
||||
add(Pass_2021.passes.get(PassCode_2021.SPF_GetGCovInfo).createMenuItem());
|
||||
}
|
||||
}
|
||||
20
src/Common/UI/Menus_2023/MainMenuBar/GlobalCleaningMenu.java
Normal file
20
src/Common/UI/Menus_2023/MainMenuBar/GlobalCleaningMenu.java
Normal file
@@ -0,0 +1,20 @@
|
||||
package Common.UI.Menus_2023.MainMenuBar;
|
||||
import Common.UI.Menus_2023.VisualiserMenu;
|
||||
import Visual_DVM_2021.Passes.PassCode_2021;
|
||||
import Visual_DVM_2021.Passes.Pass_2021;
|
||||
public class GlobalCleaningMenu extends VisualiserMenu {
|
||||
public GlobalCleaningMenu() {
|
||||
super("Очистка", "/icons/Clean.png", false);
|
||||
add(Pass_2021.passes.get(PassCode_2021.DropLastProjects).createMenuItem());
|
||||
add(Pass_2021.passes.get(PassCode_2021.DropFastAccess).createMenuItem());
|
||||
addSeparator();
|
||||
add(Pass_2021.passes.get(PassCode_2021.DeleteDownloadedBugReports).createMenuItem());
|
||||
addSeparator();
|
||||
add(Pass_2021.passes.get(PassCode_2021.DropAnalyses).createMenuItem());
|
||||
add(Pass_2021.passes.get(PassCode_2021.CleanAnalyses).createMenuItem());
|
||||
add(Pass_2021.passes.get(PassCode_2021.DropSavedArrays).createMenuItem());
|
||||
add(Pass_2021.passes.get(PassCode_2021.DeleteDebugResults).createMenuItem());
|
||||
addSeparator();
|
||||
add(Pass_2021.passes.get(PassCode_2021.ResetCurrentProject).createMenuItem());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package Common.UI.Menus_2023.MainMenuBar;
|
||||
import Common.Global;
|
||||
import Common.UI.Menus.VisualiserMenuItem;
|
||||
import Common.UI.Menus_2023.VisualiserMenu;
|
||||
import GlobalData.DBLastProject.DBLastProject;
|
||||
import GlobalData.Settings.SettingName;
|
||||
import Visual_DVM_2021.Passes.PassCode_2021;
|
||||
import Visual_DVM_2021.Passes.Pass_2021;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.event.MenuEvent;
|
||||
import javax.swing.event.MenuListener;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.io.File;
|
||||
import java.util.Vector;
|
||||
public class LastOpenedProjectsMenu extends VisualiserMenu {
|
||||
public LastOpenedProjectsMenu() {
|
||||
super("Недавние проекты", "/icons/LastOpened.png");
|
||||
addMenuListener(new MenuListener() {
|
||||
@Override
|
||||
public void menuSelected(MenuEvent e) {
|
||||
removeAll();
|
||||
Vector<DBLastProject> projects = Global.db.lastProjects.getOrdered();
|
||||
int k = 1;
|
||||
for (DBLastProject p : projects) {
|
||||
if (new File(p.HomePath).exists() && p.lastOpened != 0) {
|
||||
VisualiserMenuItem i = new VisualiserMenuItem(p.HomePath);
|
||||
i.addActionListener(new AbstractAction() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
Pass_2021.passes.get(PassCode_2021.OpenCurrentProject).Do(new File(p.HomePath));
|
||||
}
|
||||
});
|
||||
add(i);
|
||||
++k;
|
||||
if (k > (Global.db.settings.get(SettingName.LastOpenedProjectsCount).toInt32())) break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void menuDeselected(MenuEvent e) {
|
||||
}
|
||||
@Override
|
||||
public void menuCanceled(MenuEvent e) {
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
87
src/Common/UI/Menus_2023/MainMenuBar/MainMenuBar.java
Normal file
87
src/Common/UI/Menus_2023/MainMenuBar/MainMenuBar.java
Normal file
@@ -0,0 +1,87 @@
|
||||
package Common.UI.Menus_2023.MainMenuBar;
|
||||
import Common.Global;
|
||||
import Common.UI.Menus_2023.MenuBarButton;
|
||||
import Common.UI.Menus_2023.VisualiserMenuBar;
|
||||
import Common.UI.UI;
|
||||
import Repository.Component.PerformanceAnalyzer.PerformanceAnalyzer;
|
||||
import Visual_DVM_2021.Passes.PassCode_2021;
|
||||
import Visual_DVM_2021.Passes.Pass_2021;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
public class MainMenuBar extends VisualiserMenuBar {
|
||||
JMenu analyses;
|
||||
JMenu transformations;
|
||||
MenuBarButton components;
|
||||
public MainMenuBar() {
|
||||
addMenus(new LastOpenedProjectsMenu());
|
||||
addPasses(PassCode_2021.OpenCurrentProject, PassCode_2021.CreateEmptyProject);
|
||||
addMenus(
|
||||
analyses = new AnalysesMenu(),
|
||||
transformations = new TransformationsMenu(),
|
||||
new GlobalCleaningMenu(),
|
||||
new VisualiserSettingsMenu()
|
||||
);
|
||||
add(components = new MenuBarButton() {
|
||||
{
|
||||
setToolTipText("Компоненты");
|
||||
setIcon("/icons/ComponentsActual.png");
|
||||
addActionListener(e -> {
|
||||
if (PerformanceAnalyzer.isActive) {
|
||||
UI.Info("Перед работой с компонентами закройте анализатор производительности!");
|
||||
} else {
|
||||
Pass_2021.passes.get(PassCode_2021.GetComponentsActualVersions).Do();
|
||||
Global.RefreshUpdatesStatus();
|
||||
UI.ShowComponentsWindow();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
add(new MenuBarButton() {
|
||||
{
|
||||
setIcon("/icons/Comparsion.png");
|
||||
setToolTipText("Анализатор статистик");
|
||||
addActionListener(e -> {
|
||||
Global.performanceAnalyzer.Start();
|
||||
});
|
||||
}
|
||||
});
|
||||
addPasses(PassCode_2021.ShowInstruction);
|
||||
//-
|
||||
setPreferredSize(new Dimension(0, 30));
|
||||
//---
|
||||
/*
|
||||
add(new MenuBarButton() {
|
||||
{
|
||||
setIcon("/icons/Apply.png");
|
||||
setToolTipText("Test");
|
||||
addActionListener(e -> {
|
||||
Current.getProject().hasSubdirectories();
|
||||
});
|
||||
}
|
||||
});
|
||||
*/
|
||||
//---
|
||||
ShowProject(false);
|
||||
}
|
||||
public void ShowUpdatesIcon() {
|
||||
components.setIcon(
|
||||
(Global.need_update > 0) || (Global.bad_state > 0)
|
||||
? "/icons/ComponentsNeedUpdate.gif"
|
||||
: (Global.need_publish > 0 ? "/icons/ComponentsNeedPublish_2023.gif" : "/icons/ComponentsActual.png"));
|
||||
}
|
||||
public void ShowProject(boolean flag) {
|
||||
analyses.setEnabled(flag);
|
||||
transformations.setEnabled(flag);
|
||||
Pass_2021[] cleaningPasses = new Pass_2021[]{
|
||||
Pass_2021.passes.get(PassCode_2021.DropAnalyses),
|
||||
Pass_2021.passes.get(PassCode_2021.DropSavedArrays),
|
||||
Pass_2021.passes.get(PassCode_2021.CleanAnalyses),
|
||||
Pass_2021.passes.get(PassCode_2021.DeleteDebugResults),
|
||||
Pass_2021.passes.get(PassCode_2021.ResetCurrentProject)
|
||||
};
|
||||
for (Pass_2021 pass: cleaningPasses){
|
||||
pass.setControlsEnabled(flag);
|
||||
}
|
||||
}
|
||||
}
|
||||
19
src/Common/UI/Menus_2023/MainMenuBar/MainWindow.java
Normal file
19
src/Common/UI/Menus_2023/MainMenuBar/MainWindow.java
Normal file
@@ -0,0 +1,19 @@
|
||||
package Common.UI.Menus_2023.MainMenuBar;
|
||||
import Visual_DVM_2021.UI.Interface.CallbackWindow;
|
||||
import Visual_DVM_2021.UI.Interface.ProjectWindow;
|
||||
import Visual_DVM_2021.UI.Interface.TestingWindow;
|
||||
public interface MainWindow {
|
||||
void Show();
|
||||
void ShowProject();
|
||||
void ShowNoProject();
|
||||
ProjectWindow getProjectWindow();
|
||||
CallbackWindow getCallbackWindow();
|
||||
//-
|
||||
void ShowUpdatesIcon();
|
||||
void FocusProject();
|
||||
void FocusCallback();
|
||||
void FocusTesting();
|
||||
TestingWindow getTestingWindow();
|
||||
void ShowTestingTab();
|
||||
void HideTestingTab();
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package Common.UI.Menus_2023.MainMenuBar;
|
||||
import Common.UI.Menus.PassesSubMenu;
|
||||
import Common.UI.Menus_2023.VisualiserMenu;
|
||||
import Repository.Component.Sapfor.Sapfor;
|
||||
import Visual_DVM_2021.Passes.PassCode_2021;
|
||||
import Visual_DVM_2021.Passes.Pass_2021;
|
||||
public class TransformationsMenu extends VisualiserMenu {
|
||||
public TransformationsMenu() {
|
||||
super("Преобразования", "/icons/Transformations.png");
|
||||
add(new PassesSubMenu("Циклы", "/icons/Menu/Loops.png",
|
||||
Sapfor.getLoopsTransformationsCodes()));
|
||||
addSeparator();
|
||||
add(new PassesSubMenu("Приватные переменные", "/icons/Menu/Privates.png",
|
||||
Sapfor.getPrivatesTransformationsCodes()));
|
||||
addSeparator();
|
||||
add(new PassesSubMenu("Процедуры", "/icons/Menu/Functions.png",
|
||||
Sapfor.getProceduresTransformationsCodes()));
|
||||
addSeparator();
|
||||
add(new PassesSubMenu("DVM директивы", "/icons/Menu/Dvm.png",
|
||||
Sapfor.getDVMTransformationsCodes()));
|
||||
addSeparator();
|
||||
add(new PassesSubMenu("Интервалы", "/icons/Menu/Intervals.png",
|
||||
Sapfor.getIntervalsTransformationsCodes()
|
||||
));
|
||||
addSeparator();
|
||||
add(new PassesSubMenu("Области распараллеливания", "/icons/Menu/Regions.png",
|
||||
Sapfor.getRegionsTransformationsCodes()
|
||||
));
|
||||
addSeparator();
|
||||
add(new PassesSubMenu("Предобработка проекта", "/icons/Menu/Preprocessing.png",
|
||||
Sapfor.getPreparationTransformationsCodes()
|
||||
)
|
||||
);
|
||||
add(Pass_2021.passes.get(PassCode_2021.SPF_SharedMemoryParallelization).createMenuItem());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package Common.UI.Menus_2023.MainMenuBar;
|
||||
import Common.Global;
|
||||
import Common.UI.Menus.PropertiesSubmenu;
|
||||
import Common.UI.Menus_2023.SettingsSubmenu;
|
||||
import Common.UI.Menus_2023.VisualiserMenu;
|
||||
import GlobalData.Settings.SettingName;
|
||||
public class VisualiserSettingsMenu extends VisualiserMenu {
|
||||
public VisualiserSettingsMenu() {
|
||||
super("Настройки визуализатора", "/icons/Settings.png");
|
||||
//-
|
||||
add(new PropertiesSubmenu("Подтверждения и уведомления", null,
|
||||
"ShowPassesDone",
|
||||
"ConfirmPassesStart",
|
||||
"FocusPassesResult"
|
||||
));
|
||||
add(new SettingsSubmenu("Компактность отображения", null,
|
||||
SettingName.SmallScreen,
|
||||
SettingName.ShowFullTabsNames,
|
||||
SettingName.ShowFullArraysDeclarations,
|
||||
SettingName.FastAccessPassesCount,
|
||||
SettingName.LastOpenedProjectsCount
|
||||
));
|
||||
if (Global.isWindows) {
|
||||
add(new SettingsSubmenu("Компиляция на локальной машине", null,
|
||||
SettingName.LocalMakePathWindows,
|
||||
SettingName.Kernels
|
||||
));
|
||||
} else {
|
||||
add(new SettingsSubmenu("Компиляция на локальной машине", null,
|
||||
SettingName.Kernels
|
||||
));
|
||||
}
|
||||
add(new SettingsSubmenu("Синхронизация", null,
|
||||
SettingName.AutoBugReportsLoad,
|
||||
SettingName.AutoTestsLoad
|
||||
));
|
||||
add(new SettingsSubmenu("Сравнение", null,
|
||||
SettingName.ExtensionsOn,
|
||||
SettingName.RegisterOn,
|
||||
SettingName.SpacesOn,
|
||||
SettingName.EmptyLinesOn,
|
||||
SettingName.FortranWrapsOn,
|
||||
SettingName.ComparsionDiffMergeOn
|
||||
));
|
||||
add(Global.db.settings.get(SettingName.Workspace).getMenuItem());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package Common.UI.Menus_2023.MakefilesMenuBar;
|
||||
import Common.UI.Menus_2023.DataMenuBar;
|
||||
import Visual_DVM_2021.Passes.PassCode_2021;
|
||||
public class MakefilesMenuBar extends DataMenuBar {
|
||||
public MakefilesMenuBar() {
|
||||
super("мейкфайлы",
|
||||
PassCode_2021.Compile,
|
||||
PassCode_2021.AddMakefile,
|
||||
PassCode_2021.EditMakefile,
|
||||
PassCode_2021.DeleteMakefile);
|
||||
addSeparator();
|
||||
addPasses(PassCode_2021.ShowMakefilePreview, PassCode_2021.EditProjectCompilationMaxtime);
|
||||
}
|
||||
}
|
||||
32
src/Common/UI/Menus_2023/MenuBarButton.java
Normal file
32
src/Common/UI/Menus_2023/MenuBarButton.java
Normal file
@@ -0,0 +1,32 @@
|
||||
package Common.UI.Menus_2023;
|
||||
import Common.Current;
|
||||
import Common.UI.Themes.VisualiserFonts;
|
||||
import Common.Utils.Utils;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
//https://java-online.ru/swing-jbutton.xhtml
|
||||
public class MenuBarButton extends JButton {
|
||||
public MenuBarButton() {
|
||||
super();
|
||||
setFont(Current.getTheme().Fonts.get(VisualiserFonts.Menu));
|
||||
//
|
||||
setBorderPainted(false);
|
||||
setContentAreaFilled(false);
|
||||
setOpaque(false);
|
||||
//setFocusPainted(false);
|
||||
//-
|
||||
setMinimumSize(new Dimension(38, 30)); //иначе сужаются вертикально.
|
||||
}
|
||||
@Override
|
||||
protected void paintComponent(Graphics g) {
|
||||
if (getModel().isPressed()) {
|
||||
g.setColor(new Color(163, 184, 204));
|
||||
g.fillRect(0, 0, getWidth(), getHeight());
|
||||
}
|
||||
super.paintComponent(g);
|
||||
}
|
||||
public void setIcon(String icon_path) {
|
||||
setIcon(Utils.getIcon(icon_path));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package Common.UI.Menus_2023.ModulesMenuBar;
|
||||
import Common.UI.Menus_2023.DataMenuBar;
|
||||
import Visual_DVM_2021.Passes.PassCode_2021;
|
||||
public class ModulesMenuBar extends DataMenuBar {
|
||||
public ModulesMenuBar() {
|
||||
super("языковые модули", PassCode_2021.EditModule);
|
||||
}
|
||||
}
|
||||
25
src/Common/UI/Menus_2023/PassButton.java
Normal file
25
src/Common/UI/Menus_2023/PassButton.java
Normal file
@@ -0,0 +1,25 @@
|
||||
package Common.UI.Menus_2023;
|
||||
import Visual_DVM_2021.Passes.Pass_2021;
|
||||
|
||||
import java.awt.*;
|
||||
public class PassButton extends MenuBarButton implements PassControl {
|
||||
public PassButton(Pass_2021 pass, boolean tab) {
|
||||
setText(pass.getButtonText());
|
||||
setToolTipText(pass.getDescription());
|
||||
if (pass.getIconPath() != null) {
|
||||
if (tab) {
|
||||
setIcon(pass.getTabIcon());
|
||||
setPreferredSize(new Dimension(18,18));
|
||||
setMaximumSize(new Dimension(18,18));
|
||||
setMinimumSize(new Dimension(18,18));
|
||||
}
|
||||
else
|
||||
setIcon(pass.getIconPath());
|
||||
}
|
||||
addActionListener(pass.getControlAction());
|
||||
pass.controls.add(this);
|
||||
}
|
||||
public PassButton(Pass_2021 pass) {
|
||||
this(pass, false);
|
||||
}
|
||||
}
|
||||
7
src/Common/UI/Menus_2023/PassControl.java
Normal file
7
src/Common/UI/Menus_2023/PassControl.java
Normal file
@@ -0,0 +1,7 @@
|
||||
package Common.UI.Menus_2023;
|
||||
public interface PassControl {
|
||||
void setIcon(String icon_path);
|
||||
void setEnabled(boolean flag);
|
||||
void setVisible(boolean flag);
|
||||
void setToolTipText(String text);
|
||||
}
|
||||
17
src/Common/UI/Menus_2023/PassMenuItem.java
Normal file
17
src/Common/UI/Menus_2023/PassMenuItem.java
Normal file
@@ -0,0 +1,17 @@
|
||||
package Common.UI.Menus_2023;
|
||||
import Common.UI.Menus.VisualiserMenuItem;
|
||||
import Common.Utils.Utils;
|
||||
import Visual_DVM_2021.Passes.Pass_2021;
|
||||
public class PassMenuItem extends VisualiserMenuItem implements PassControl {
|
||||
@Override
|
||||
public void setIcon(String icon_path) {
|
||||
setIcon(Utils.getIcon(icon_path));
|
||||
}
|
||||
public PassMenuItem(Pass_2021 pass) {
|
||||
setText(pass.getDescription());
|
||||
setToolTipText(pass.getDescription());
|
||||
if (pass.getIconPath() != null) setIcon(pass.getIconPath());
|
||||
addActionListener(pass.getControlAction());
|
||||
pass.controls.add(this);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package Common.UI.Menus_2023.ProjectMenuBar;
|
||||
import Common.UI.Menus_2023.VisualiserMenu;
|
||||
public class FilesOperationsMenu extends VisualiserMenu {
|
||||
public FilesOperationsMenu() {
|
||||
super("Массовые операции над файлами","/icons/MassFiles.png" );
|
||||
}
|
||||
}
|
||||
33
src/Common/UI/Menus_2023/ProjectMenuBar/ProjectMenuBar.java
Normal file
33
src/Common/UI/Menus_2023/ProjectMenuBar/ProjectMenuBar.java
Normal file
@@ -0,0 +1,33 @@
|
||||
package Common.UI.Menus_2023.ProjectMenuBar;
|
||||
import Common.UI.Menus_2023.MenuBarButton;
|
||||
import Common.UI.Menus_2023.VisualiserMenuBar;
|
||||
import Common.UI.UI;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
public class ProjectMenuBar extends VisualiserMenuBar {
|
||||
public ProjectViewMenu projectViewMenu;
|
||||
public ProjectMenuBar() {
|
||||
addMenus(projectViewMenu = new ProjectViewMenu());
|
||||
add(new JSeparator());
|
||||
addMenus(
|
||||
new ProjectSettingsMenu()
|
||||
);
|
||||
add(new MenuBarButton() {
|
||||
{
|
||||
setToolTipText("Профили");
|
||||
setIcon("/icons/Profiles.png");
|
||||
addActionListener(e -> {
|
||||
UI.ShowProfilesWindow();
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
public ProjectViewMenu getProjectViewMenu() {
|
||||
return projectViewMenu;
|
||||
}
|
||||
@Override
|
||||
public void setSizeLimits() {
|
||||
setPreferredSize(new Dimension(0, 32));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
package Common.UI.Menus_2023.ProjectMenuBar;
|
||||
import Common.Current;
|
||||
import Common.Global;
|
||||
import Common.UI.Menus_2023.LanguagesSubmenu;
|
||||
import Common.UI.Menus_2023.SettingsSubmenu;
|
||||
import Common.UI.Menus_2023.StylesSubmenu;
|
||||
import Common.UI.Menus_2023.VisualiserMenu;
|
||||
import GlobalData.Settings.SettingName;
|
||||
import ProjectData.Files.LanguageStyle;
|
||||
import ProjectData.LanguageName;
|
||||
|
||||
import javax.swing.*;
|
||||
public class ProjectSettingsMenu extends VisualiserMenu {
|
||||
JMenu mLanguage;
|
||||
JMenu mStyle;
|
||||
public ProjectSettingsMenu() {
|
||||
super("Настройки проекта", "/icons/Settings.png");
|
||||
add(mLanguage = new LanguagesSubmenu() {
|
||||
@Override
|
||||
public void action(LanguageName languageName) {
|
||||
if (Current.getProject().UpdateLanguage(languageName)) {
|
||||
Current.getSapfor().ResetAllAnalyses();
|
||||
ShowLanguage();
|
||||
}
|
||||
}
|
||||
});
|
||||
ShowLanguage();
|
||||
//--
|
||||
add(mStyle = new StylesSubmenu() {
|
||||
@Override
|
||||
public void action(LanguageStyle languageStyle) {
|
||||
if (Current.getProject().UpdateStyle(languageStyle))
|
||||
ShowStyle();
|
||||
}
|
||||
});
|
||||
ShowStyle();
|
||||
addSeparator();
|
||||
add(new SettingsSubmenu("Анализ", null,
|
||||
SettingName.Precompilation,
|
||||
SettingName.STATIC_SHADOW_ANALYSIS,
|
||||
SettingName.KEEP_DVM_DIRECTIVES,
|
||||
SettingName.IGNORE_IO_SAPFOR,
|
||||
SettingName.MPI_PROGRAM,
|
||||
SettingName.ANALYSIS_OPTIONS,
|
||||
SettingName.PARALLELIZE_FREE_LOOPS
|
||||
));
|
||||
addSeparator();
|
||||
add(new SettingsSubmenu("Построение системы интервалов", null,
|
||||
SettingName.KEEP_LOOPS_CLOSE_NESTING,
|
||||
SettingName.KEEP_GCOV
|
||||
));
|
||||
addSeparator();
|
||||
add(new SettingsSubmenu("Построение версий", null,
|
||||
SettingName.FREE_FORM,
|
||||
SettingName.KEEP_SPF_DIRECTIVES,
|
||||
SettingName.KEEP_SPF_DIRECTIVES_AMONG_TRANSFORMATIONS,
|
||||
SettingName.OUTPUT_UPPER,
|
||||
SettingName.MAX_SHADOW_WIDTH,
|
||||
SettingName.DVMConvertationOptions,
|
||||
SettingName.SaveModifications
|
||||
));
|
||||
addSeparator();
|
||||
add(Global.db.settings.get(SettingName.TRANSLATE_MESSAGES).getMenuItem());
|
||||
add(Global.db.settings.get(SettingName.DEBUG_PRINT_ON).getMenuItem());
|
||||
add(Global.db.settings.get(SettingName.GCOVLimit).getMenuItem());
|
||||
}
|
||||
public void ShowLanguage() {
|
||||
mLanguage.setText("Язык: " + Current.getProject().languageName.getDescription());
|
||||
}
|
||||
public void ShowStyle() {
|
||||
mStyle.setText("Стиль: " + Current.getProject().style.getDescription());
|
||||
}
|
||||
}
|
||||
34
src/Common/UI/Menus_2023/ProjectMenuBar/ProjectViewMenu.java
Normal file
34
src/Common/UI/Menus_2023/ProjectMenuBar/ProjectViewMenu.java
Normal file
@@ -0,0 +1,34 @@
|
||||
package Common.UI.Menus_2023.ProjectMenuBar;
|
||||
import Common.Current;
|
||||
import Common.UI.Menus_2023.VisualiserMenu;
|
||||
import Common.UI.Themes.VisualiserFonts;
|
||||
import Common.UI.UI;
|
||||
import Common.Utils.Utils;
|
||||
import ProjectData.ProjectView;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.util.LinkedHashMap;
|
||||
public class ProjectViewMenu extends VisualiserMenu {
|
||||
LinkedHashMap<ProjectView, JMenuItem> views;
|
||||
public ProjectViewMenu() {
|
||||
super("", "");
|
||||
views = new LinkedHashMap<>();
|
||||
for (ProjectView view : ProjectView.values()) {
|
||||
JMenuItem m = new JMenuItem(view.getDescription()) {
|
||||
{
|
||||
setIcon(Utils.getIcon(view.getIcon()));
|
||||
setFont(Current.getTheme().Fonts.get(VisualiserFonts.TreeItalic));
|
||||
addActionListener(e -> {
|
||||
Current.set(Current.ProjectView, view);
|
||||
UI.getMainWindow().getProjectWindow().ShowProjectView();
|
||||
});
|
||||
}
|
||||
};
|
||||
add(m);
|
||||
views.put(view, m);
|
||||
}
|
||||
}
|
||||
public void SelectView(ProjectView view){
|
||||
views.get(view).doClick();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package Common.UI.Menus_2023.RemoteSapforsMenuBar;
|
||||
import Common.UI.Menus_2023.DataMenuBar;
|
||||
import Visual_DVM_2021.Passes.PassCode_2021;
|
||||
public class RemoteSapforsMenuBar extends DataMenuBar {
|
||||
public RemoteSapforsMenuBar() {
|
||||
super("SAPFOR", PassCode_2021.InstallRemoteSapfor,
|
||||
PassCode_2021.AddSapfor,
|
||||
PassCode_2021.EditSapfor,
|
||||
PassCode_2021.DeleteSapfor);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package Common.UI.Menus_2023.RunConfigurationsMenuBar;
|
||||
import Common.UI.Menus_2023.DataMenuBar;
|
||||
import Visual_DVM_2021.Passes.PassCode_2021;
|
||||
|
||||
import javax.swing.*;
|
||||
public class RunConfigurationsMenuBar extends DataMenuBar {
|
||||
public RunConfigurationsMenuBar() {
|
||||
super("конфигурации запуска", PassCode_2021.Run,
|
||||
PassCode_2021.AddRunConfiguration, PassCode_2021.EditRunConfiguration, PassCode_2021.DeleteRunConfiguration);
|
||||
add(new JSeparator());
|
||||
addPasses(PassCode_2021.EditProjectRunMaxtime);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package Common.UI.Menus_2023.SapforConfigurationCommandsMenuBar;
|
||||
import Common.UI.Menus_2023.DataMenuBar;
|
||||
import Visual_DVM_2021.Passes.PassCode_2021;
|
||||
public class SapforConfigurationCommandsMenuBar extends DataMenuBar {
|
||||
public SapforConfigurationCommandsMenuBar() {
|
||||
super("команды",
|
||||
PassCode_2021.PublishSapforConfigurationCommand,
|
||||
PassCode_2021.EditSapforConfigurationCommand,
|
||||
PassCode_2021.DeleteSapforConfigurationCommand
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package Common.UI.Menus_2023.SapforConfigurationsMenuBar;
|
||||
import Common.UI.Menus_2023.DataMenuBar;
|
||||
import Visual_DVM_2021.Passes.PassCode_2021;
|
||||
public class SapforConfigurationsMenuBar extends DataMenuBar {
|
||||
public SapforConfigurationsMenuBar() {
|
||||
super("конфигурации", PassCode_2021.StartSapforTests,
|
||||
PassCode_2021.PublishSapforConfiguration,
|
||||
PassCode_2021.EditSapforConfiguration,
|
||||
PassCode_2021.DeleteSapforConfiguration
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package Common.UI.Menus_2023.SapforTasksMenuBar;
|
||||
import Common.UI.Menus_2023.DataMenuBar;
|
||||
import Visual_DVM_2021.Passes.PassCode_2021;
|
||||
public class SapforTasksMenuBar extends DataMenuBar {
|
||||
public SapforTasksMenuBar() {
|
||||
super("задачи", PassCode_2021.OpenSapforTest);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package Common.UI.Menus_2023.SapforTasksPackagesBar;
|
||||
import Common.UI.Menus_2023.DataMenuBar;
|
||||
import Visual_DVM_2021.Passes.PassCode_2021;
|
||||
public class SapforTasksPackagesBar extends DataMenuBar {
|
||||
public SapforTasksPackagesBar() {
|
||||
super("пакеты задач", PassCode_2021.DeleteSapforTasksPackage);
|
||||
}
|
||||
}
|
||||
19
src/Common/UI/Menus_2023/SettingsSubmenu.java
Normal file
19
src/Common/UI/Menus_2023/SettingsSubmenu.java
Normal file
@@ -0,0 +1,19 @@
|
||||
package Common.UI.Menus_2023;
|
||||
import Common.Current;
|
||||
import Common.Global;
|
||||
import Common.UI.Themes.VisualiserFonts;
|
||||
import Common.Utils.Utils;
|
||||
import GlobalData.Settings.SettingName;
|
||||
|
||||
import javax.swing.*;
|
||||
public class SettingsSubmenu extends JMenu {
|
||||
public SettingsSubmenu(String title, String icon, SettingName... settings) {
|
||||
super(title);
|
||||
if (icon != null)
|
||||
setIcon(Utils.getIcon(icon));
|
||||
setFont(Current.getTheme().Fonts.get(VisualiserFonts.Menu));
|
||||
for (SettingName c : settings) {
|
||||
add(Global.db.settings.get(c).getMenuItem());
|
||||
}
|
||||
}
|
||||
}
|
||||
41
src/Common/UI/Menus_2023/StableMenuItem.java
Normal file
41
src/Common/UI/Menus_2023/StableMenuItem.java
Normal file
@@ -0,0 +1,41 @@
|
||||
package Common.UI.Menus_2023;
|
||||
import Common.UI.Menus.VisualiserMenuItem;
|
||||
import Common.UI.UI;
|
||||
import Common.Utils.Utils;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.plaf.ComponentUI;
|
||||
import javax.swing.plaf.basic.BasicMenuItemUI;
|
||||
//неичезающий меню итем. нужен для настроек
|
||||
//https://translated.turbopages.org/proxy_u/en-ru.ru.64537f6c-6460c460-8e74a1ab-74722d776562/https/tips4java.wordpress.com/2010/09/12/keeping-menus-open/
|
||||
class StableItemUI extends BasicMenuItemUI {
|
||||
public static ComponentUI createUI(JComponent c) {
|
||||
return new StableItemUI();
|
||||
}
|
||||
@Override
|
||||
protected void doClick(MenuSelectionManager msm) {
|
||||
menuItem.doClick(0);
|
||||
if (UI.last_menu_path != null)
|
||||
MenuSelectionManager.defaultManager().setSelectedPath(UI.last_menu_path);
|
||||
}
|
||||
}
|
||||
public class StableMenuItem extends VisualiserMenuItem {
|
||||
{
|
||||
getModel().addChangeListener(e -> {
|
||||
if (getModel().isArmed() && isShowing())
|
||||
UI.last_menu_path = MenuSelectionManager.defaultManager().getSelectedPath();
|
||||
});
|
||||
}
|
||||
public StableMenuItem(String text) {
|
||||
super(text);
|
||||
setUI(new StableItemUI());
|
||||
}
|
||||
public StableMenuItem(String text, String icon_path) {
|
||||
super(text);
|
||||
setIcon(Utils.getIcon(icon_path));
|
||||
setUI(new StableItemUI());
|
||||
}
|
||||
public StableMenuItem() {
|
||||
setUI(new StableItemUI());
|
||||
}
|
||||
}
|
||||
16
src/Common/UI/Menus_2023/StablePassMenuItem.java
Normal file
16
src/Common/UI/Menus_2023/StablePassMenuItem.java
Normal file
@@ -0,0 +1,16 @@
|
||||
package Common.UI.Menus_2023;
|
||||
import Common.Utils.Utils;
|
||||
import Visual_DVM_2021.Passes.Pass_2021;
|
||||
public class StablePassMenuItem extends StableMenuItem implements PassControl {
|
||||
@Override
|
||||
public void setIcon(String icon_path) {
|
||||
setIcon(Utils.getIcon(icon_path));
|
||||
}
|
||||
public StablePassMenuItem(Pass_2021 pass) {
|
||||
setText(pass.getDescription());
|
||||
setToolTipText(pass.getDescription());
|
||||
if (pass.getIconPath() != null) setIcon(pass.getIconPath());
|
||||
addActionListener(pass.getControlAction());
|
||||
pass.controls.add(this);
|
||||
}
|
||||
}
|
||||
25
src/Common/UI/Menus_2023/StylesSubmenu.java
Normal file
25
src/Common/UI/Menus_2023/StylesSubmenu.java
Normal file
@@ -0,0 +1,25 @@
|
||||
package Common.UI.Menus_2023;
|
||||
import ProjectData.Files.LanguageStyle;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
public abstract class StylesSubmenu extends VisualiserMenu {
|
||||
public StylesSubmenu() {
|
||||
this("Стиль");
|
||||
}
|
||||
public StylesSubmenu(String text) {
|
||||
super(text, "/icons/Style.png", true);
|
||||
for (LanguageStyle languageStyle : LanguageStyle.values()) {
|
||||
JMenuItem m = new StableMenuItem(languageStyle.getDescription());
|
||||
m.addActionListener(
|
||||
new AbstractAction() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
action(languageStyle);
|
||||
}
|
||||
});
|
||||
add(m);
|
||||
}
|
||||
}
|
||||
public abstract void action(LanguageStyle languageStyle);
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package Common.UI.Menus_2023.SubscribersMenuBar;
|
||||
import Common.UI.Menus_2023.DataMenuBar;
|
||||
import Visual_DVM_2021.Passes.PassCode_2021;
|
||||
public class SubscribersMenuBar extends DataMenuBar {
|
||||
public SubscribersMenuBar() {
|
||||
super("Адресаты",
|
||||
PassCode_2021.SaveBugReportExecutor,
|
||||
PassCode_2021.SaveBugReportRecipients,
|
||||
PassCode_2021.AddSubscriber,
|
||||
PassCode_2021.EditSubscriber,
|
||||
PassCode_2021.DeleteSubscriber);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package Common.UI.Menus_2023.TasksPackagesMenuBar;
|
||||
import Common.Current;
|
||||
import Common.UI.Menus_2023.DataMenuBar;
|
||||
import Common.UI.Menus_2023.MenuBarButton;
|
||||
import Common.UI.Themes.VisualiserFonts;
|
||||
import Common.UI.UI;
|
||||
import Common.Utils.Utils;
|
||||
import TestingSystem.TestingServer;
|
||||
import Visual_DVM_2021.Passes.PassCode_2021;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
public class TasksPackagesMenuBar extends DataMenuBar {
|
||||
JButton autorefreshButton;
|
||||
JSpinner sCheckTime;
|
||||
public TasksPackagesMenuBar() {
|
||||
super("пакеты задач", PassCode_2021.SynchronizeTestsTasks, PassCode_2021.AbortSelectedPackages);
|
||||
add(autorefreshButton = new MenuBarButton() {
|
||||
{
|
||||
setText("проверка раз в");
|
||||
setToolTipText("автоматическое обновление состояния пакета задач");
|
||||
Mark();
|
||||
addActionListener(e -> {
|
||||
TestingServer.checkTasks = !TestingServer.checkTasks;
|
||||
TestingServer.switchTimer(TestingServer.checkTasks);
|
||||
Mark();
|
||||
});
|
||||
}
|
||||
public void Mark() {
|
||||
setIcon(Utils.getIcon(TestingServer.checkTasks ? "/icons/Pick.png" : "/icons/NotPick.png"));
|
||||
}
|
||||
});
|
||||
add(sCheckTime = new JSpinner());
|
||||
sCheckTime.setPreferredSize(new Dimension(60, 26));
|
||||
sCheckTime.setMaximumSize(new Dimension(60, 26));
|
||||
sCheckTime.setModel(new SpinnerNumberModel(TestingServer.checkIntervalSecond, 10, 3600, 1));
|
||||
UI.MakeSpinnerRapid(sCheckTime, e -> {
|
||||
TestingServer.checkIntervalSecond = (int) sCheckTime.getValue();
|
||||
if (TestingServer.checkTasks) TestingServer.ResetTimer();
|
||||
});
|
||||
add(new JLabel(" сек") {
|
||||
{
|
||||
setFont(Current.getTheme().Fonts.get(VisualiserFonts.TreeItalic));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void ShowAutorefresh() {
|
||||
autorefreshButton.setIcon(Utils.getIcon(TestingServer.checkTasks ? "/icons/Pick.png" : "/icons/NotPick.png"));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package Common.UI.Menus_2023.TestRunTasksMenuBar;
|
||||
import Common.UI.Menus_2023.DataMenuBar;
|
||||
import Visual_DVM_2021.Passes.PassCode_2021;
|
||||
|
||||
import javax.swing.*;
|
||||
public class TestRunTasksMenuBar extends DataMenuBar {
|
||||
JMenuBar filters= null;
|
||||
public void DropFilters() {
|
||||
if (filters != null) {
|
||||
remove(filters);
|
||||
filters = null;
|
||||
}
|
||||
revalidate();
|
||||
repaint();
|
||||
}
|
||||
public void addFilters(JMenu cFilterMenu, JMenu rFilterMenu) {
|
||||
filters= addMenus(cFilterMenu, rFilterMenu);
|
||||
}
|
||||
public TestRunTasksMenuBar() {
|
||||
super("задачи", PassCode_2021.DownloadTaskTest);
|
||||
}
|
||||
}
|
||||
12
src/Common/UI/Menus_2023/TestsMenuBar/TestsMenuBar.java
Normal file
12
src/Common/UI/Menus_2023/TestsMenuBar/TestsMenuBar.java
Normal file
@@ -0,0 +1,12 @@
|
||||
package Common.UI.Menus_2023.TestsMenuBar;
|
||||
import Common.UI.Menus_2023.DataMenuBar;
|
||||
import Visual_DVM_2021.Passes.PassCode_2021;
|
||||
public class TestsMenuBar extends DataMenuBar {
|
||||
public TestsMenuBar() {
|
||||
super("тесты",
|
||||
PassCode_2021.DownloadTest,
|
||||
PassCode_2021.PublishTest,
|
||||
PassCode_2021.EditTest,
|
||||
PassCode_2021.DeleteSelectedTests);
|
||||
}
|
||||
}
|
||||
26
src/Common/UI/Menus_2023/TypesSubmenu.java
Normal file
26
src/Common/UI/Menus_2023/TypesSubmenu.java
Normal file
@@ -0,0 +1,26 @@
|
||||
package Common.UI.Menus_2023;
|
||||
import ProjectData.Files.FileType;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
public abstract class TypesSubmenu extends VisualiserMenu {
|
||||
public TypesSubmenu() {
|
||||
this("Тип");
|
||||
}
|
||||
public TypesSubmenu(String text) {
|
||||
super(text, "/icons/type.png", true);
|
||||
for (FileType fileType : FileType.values()) {
|
||||
if (fileType != FileType.forbidden) {
|
||||
JMenuItem m = new StableMenuItem(fileType.getDescription());
|
||||
m.addActionListener(new AbstractAction() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
action(fileType);
|
||||
}
|
||||
});
|
||||
add(m);
|
||||
}
|
||||
}
|
||||
}
|
||||
public abstract void action(FileType fileType);
|
||||
}
|
||||
11
src/Common/UI/Menus_2023/UsersMenuBar/UsersMenuBar.java
Normal file
11
src/Common/UI/Menus_2023/UsersMenuBar/UsersMenuBar.java
Normal file
@@ -0,0 +1,11 @@
|
||||
package Common.UI.Menus_2023.UsersMenuBar;
|
||||
import Common.UI.Menus_2023.DataMenuBar;
|
||||
import Visual_DVM_2021.Passes.PassCode_2021;
|
||||
public class UsersMenuBar extends DataMenuBar {
|
||||
public UsersMenuBar() {
|
||||
super("пользователи", PassCode_2021.AddUser,
|
||||
PassCode_2021.EditUser,
|
||||
PassCode_2021.InitialiseUser,
|
||||
PassCode_2021.DeleteUser);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package Common.UI.Menus_2023.VariantsMenuBar;
|
||||
import Common.UI.Menus.VisualiserMenuItem;
|
||||
import Common.UI.Menus_2023.DataMenuBar;
|
||||
import Common.UI.Menus_2023.VisualiserMenu;
|
||||
import Visual_DVM_2021.Passes.PassCode_2021;
|
||||
import Visual_DVM_2021.Passes.Pass_2021;
|
||||
public class VariantsMenuBar extends DataMenuBar {
|
||||
public VariantsMenuBar() {
|
||||
super("варианты");
|
||||
addMenus(new VisualiserMenu("Отображение параллельных вариантов",
|
||||
"/icons/ShowPassword.png") {
|
||||
{
|
||||
add(new VisualiserMenuItem("Все варианты") {
|
||||
{
|
||||
addActionListener(e -> Pass_2021.passes.get(PassCode_2021.GenerateParallelVariants).Do(true));
|
||||
}
|
||||
});
|
||||
add(new VisualiserMenuItem("Минимальное покрытие вариантов") {
|
||||
{
|
||||
addActionListener(e -> Pass_2021.passes.get(PassCode_2021.GenerateParallelVariants).Do(false));
|
||||
}
|
||||
});
|
||||
}
|
||||
;
|
||||
});
|
||||
addPasses(PassCode_2021.PredictParallelVariants, PassCode_2021.CreateParallelVariants);
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user