From e3c25fc6cbfe412bbbeec2529f79e084a3ddae37 Mon Sep 17 00:00:00 2001 From: lr279911 Date: Wed, 7 Aug 2024 08:52:25 +0200 Subject: [PATCH 1/6] HIM for opi to bob files --- .../builder/model/AdvancedConverter.java | 247 +++++++- .../builder/model/AdvancedConverterApp.java | 28 + .../builder/model/BrowserConverter.java | 562 ++++++++++++++++++ .../display/builder/model/Converter.java | 219 ++++--- .../builder/model/ConverterMenuEntry.java | 40 ++ .../org.phoebus.framework.spi.AppDescriptor | 1 + .../services/org.phoebus.ui.spi.MenuEntry | 1 + .../main/resources/icons/arrow_refresh.png | Bin 0 -> 685 bytes .../model/src/main/resources/icons/help.png | Bin 0 -> 786 bytes docs/source/convertor.rst | 19 + 10 files changed, 995 insertions(+), 122 deletions(-) create mode 100644 app/display/model/src/main/java/org/csstudio/display/builder/model/AdvancedConverterApp.java create mode 100644 app/display/model/src/main/java/org/csstudio/display/builder/model/BrowserConverter.java create mode 100644 app/display/model/src/main/java/org/csstudio/display/builder/model/ConverterMenuEntry.java create mode 100644 app/display/model/src/main/resources/META-INF/services/org.phoebus.framework.spi.AppDescriptor create mode 100644 app/display/model/src/main/resources/META-INF/services/org.phoebus.ui.spi.MenuEntry create mode 100644 app/display/model/src/main/resources/icons/arrow_refresh.png create mode 100644 app/display/model/src/main/resources/icons/help.png diff --git a/app/display/model/src/main/java/org/csstudio/display/builder/model/AdvancedConverter.java b/app/display/model/src/main/java/org/csstudio/display/builder/model/AdvancedConverter.java index ae9a1839ea..20c6fc2bd8 100644 --- a/app/display/model/src/main/java/org/csstudio/display/builder/model/AdvancedConverter.java +++ b/app/display/model/src/main/java/org/csstudio/display/builder/model/AdvancedConverter.java @@ -14,24 +14,94 @@ import java.nio.file.Path; import java.util.ArrayList; import java.util.List; - - +import java.util.logging.Level; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import static org.csstudio.display.builder.model.ModelPlugin.logger; /** * Extension of Converter class to manage opi folder and several features * assumed in opi2bob_recursive_converter.python script - * + * * @author Katy SAINTIN */ public class AdvancedConverter extends Converter { + + // Singleton design pattern + private static AdvancedConverter instance = null; + + // different state of the conversion process + protected enum ConvertType { + FILELIST, NEWFILE, SUCCESS, ERROR + }; + + private IConverterListener listener = null; + + public static AdvancedConverter getInstance() { + if (instance == null) { + instance = new AdvancedConverter(); + } + + return instance; + } + + protected class ConverterEvent { + + private String[] fileList = null; + private ConvertType type = null; + private File file = null; + private String message = null; + + protected String getMessage() { + return message; + } + + private void setMessage(String errorMessage) { + this.message = errorMessage; + } + + protected File getFile() { + return file; + } + + private void setFile(File file) { + this.file = file; + } + + protected ConvertType getType() { + return type; + } + + private void setType(ConvertType type) { + this.type = type; + } + + protected String[] getFileList() { + return fileList; + } + + private void setFileList(String[] fileList) { + this.fileList = fileList; + } + + } + + protected interface IConverterListener { + public void convertEvent(ConverterEvent event); // tracking events + } + + protected void setConverterListener(IConverterListener listener) { + this.listener = listener; + } + /** * Generate argument for the original Converter - * + * * @param args * @return */ - public static String[] generateRecursiveArguments(String[] args) { + public String[] generateRecursiveArguments(String[] args) { List converterArguments = new ArrayList<>(); if (args != null && args.length > 0) { String firstArg = args[0]; @@ -58,9 +128,10 @@ public static String[] generateRecursiveArguments(String[] args) { } // Assume a folder for a recursive management + File file = null; for (String fileName : args) { if (!fileName.startsWith("-o")) { - File file = new File(fileName); + file = new File(fileName); if (file.exists()) { if (file.isDirectory()) { List listOpiFiles = listOpiFiles(file.getAbsolutePath()); @@ -82,7 +153,7 @@ public static String[] generateRecursiveArguments(String[] args) { /** * This method generate the tree structure hosts bob script and pictures ... */ - private static void populateTreeStructure(File rootOutputFolder, File outputFolder, File opiRootFolder) { + private void populateTreeStructure(File rootOutputFolder, File outputFolder, File opiRootFolder) { if (outputFolder != null && opiRootFolder != null) { // Create the tree structure in root folder then copy all files except opi file @@ -117,8 +188,6 @@ private static void populateTreeStructure(File rootOutputFolder, File outputFold Path copyPath = copyFile.toPath(); Files.copy(tmpPath, copyPath); - - } else if (!rootOutputFolder.getAbsolutePath().equals(outputFolder.getAbsolutePath())) { // Move the corresponding generated bob file in the sub folder // Find the corresponding bob file @@ -139,36 +208,149 @@ private static void populateTreeStructure(File rootOutputFolder, File outputFold } catch (IOException e) { String errMessage = "Error to move or copy " + tmpFile.getAbsolutePath(); errMessage = errMessage + " " + e.getMessage(); - System.err.println(errMessage); - // e.printStackTrace(); + logger.log(Level.WARNING, errMessage, e); + notifyConvertEvent(ConvertType.ERROR, errMessage + " may already exist in the output folder"); + e.printStackTrace(); } } } } } + /** + * Tracking information about the currant converting file and get access to the + * case newFile + */ + protected void traceProgression(File infile, File outfile) { + super.traceProgression(infile, outfile); + notifyConvertEvent(ConvertType.NEWFILE, infile); + } + + /** + * This method manage the different state of the conversion process and update + * the JDialog display + * + * @param type + * @param value + */ + private void notifyConvertEvent(ConvertType type, Object value) { + if (listener != null) { + ConverterEvent event = new ConverterEvent(); + event.setType(type); + boolean setValue = false; + switch (type) { + case FILELIST: // before conversion + if (value instanceof String[]) { + // get an array with every opi file to convert + setValue = true; + event.setFileList((String[]) value); + } + break; + case NEWFILE: // every new file to convert + if (value instanceof File) { + setValue = true; + event.setFile((File) value); + } + break; + case SUCCESS: + case ERROR: + default: + break; + } + + if (!setValue) { + event.setMessage(String.valueOf(value)); + } + listener.convertEvent(event); + } + } + /** * Fix error conversion that Converter not manage */ - private static void updateScriptsAndBobFiles(File outputFolderFile) { + private void updateScriptsAndBobFiles(File outputFolderFile) { // Changing import in script System.out.println("Update import in scripts"); List scriptList = listScriptFiles(outputFolderFile.getAbsolutePath()); List bobList = listBobFiles(outputFolderFile.getAbsolutePath()); - scriptList.addAll(bobList); File tmpFile = null; + scriptList.addAll(bobList); Path tmpPath; for (String file : scriptList) { + try { if (!isScriptFile(file) || file.contains(PHOEBUS)) tmpFile = new File(file); - tmpPath = tmpFile.toPath(); - + tmpPath = tmpFile.toPath(); + // Change import css to phoebus in embedded script String contains = Files.readString(tmpPath, Charset.defaultCharset()); String newContains = contains.replaceAll(IMPORT_CSS, IMPORT_PHOEBUS); + // add name of the file in phoebus + String name = "" + tmpFile.getName().substring(0, tmpFile.getName().length() - 4) + "\n"; + + if (isBobFile(tmpFile.getName())) { + // regex used to find the place where the name should be (between the display + // tag and background_color) + String research = ""; + Pattern formula = Pattern.compile(research, Pattern.DOTALL); + Matcher match = formula.matcher(newContains); + match.find(); + String oldName = match.group(1); + // if the place found before does not contain the name tag we create a name + // based on it file name + if (!oldName.contains("")) { + Pattern bckgrnd = Pattern.compile(""); + Matcher index = bckgrnd.matcher(newContains); + List result = new ArrayList<>(); + while (index.find()) { + result.add(index.start()); + } + for (int i = 0; i < newContains.length(); i++) { + if (i == result.get(0) - 1) { + newContains = newContains.substring(0, i - 1) + name + newContains.substring(i); + } + } + } + + // convert & to && + // regex used to find the place where the boolean expression should be (between + // the ) + String search = "]*>"; + Pattern pattern = Pattern.compile(search); + Matcher matcher = pattern.matcher(newContains); + StringBuffer next = new StringBuffer(); + while (matcher.find()) { + String hit = matcher.group(); + if (!hit.contains("&&")) { + String modifAnd = hit.replace("&", "&&"); + matcher.appendReplacement(next, Matcher.quoteReplacement(modifAnd)); + } + + } + matcher.appendTail(next); + newContains = next.toString(); + + // convert | to || + Pattern pattern2 = Pattern.compile(search); + Matcher matcher2 = pattern2.matcher(newContains); + StringBuffer next2 = new StringBuffer(); + while (matcher2.find()) { + String hit = matcher2.group(); + if (!hit.contains("||")) { + String modifOr = hit.replace("|", "||"); + matcher2.appendReplacement(next2, Matcher.quoteReplacement(modifOr)); + } + + } + matcher2.appendTail(next2); + newContains = next2.toString(); + } + // Replace embedded opi by bob + newContains = newContains.replaceAll(OPI, BOB); // prevent replaceAll problem for opi becoming .bob in + // the bob file newContains = newContains.replaceAll(OPI_EXTENSION, BOB_EXTENSION); newContains = newContains.replaceAll(OPI_EXTENSION.toUpperCase(), BOB_EXTENSION.toUpperCase()); @@ -183,21 +365,19 @@ private static void updateScriptsAndBobFiles(File outputFolderFile) { // Write new contains Files.writeString(tmpPath, newContains, Charset.defaultCharset()); } catch (Exception e) { + e.printStackTrace(); String errMessage = "Error update " + file; errMessage = errMessage + " " + e.getMessage(); - System.err.println(errMessage); + //System.err.println(errMessage); + logger.log(Level.WARNING, errMessage, e); + notifyConvertEvent(ConvertType.ERROR, errMessage); } } } - /** - * Call Converter main class with full arguments list all the opi file - * - * @param i - */ - public static void main(String[] args) { - + @Override + protected void launchConversion(String[] args) { if (args.length == 0 || args[0].startsWith("-h")) { System.out.println( "Usage: -main org.csstudio.display.builder.model.AdvancedConverter [-help] [-output /path/to/folder] "); @@ -213,7 +393,6 @@ public static void main(String[] args) { // Parse arguments in order to generate a full arguments with all opi file String[] generateArguments = generateRecursiveArguments(args); - // Find opi root folder the shorter path parent folder File opiRootFolder = null; File outputFolderFile = null; @@ -226,7 +405,8 @@ public static void main(String[] args) { } catch (Exception e) { String errMessage = "Error on Output folder " + outputFolderFile.getAbsolutePath() + " creation"; errMessage = errMessage + " " + e.getMessage(); - System.err.println(errMessage); + logger.log(Level.WARNING, errMessage, e); + notifyConvertEvent(ConvertType.ERROR, errMessage); // e.printStackTrace(); } } @@ -248,19 +428,30 @@ public static void main(String[] args) { } } // Call main super class - Converter.main(generateArguments); - System.out.println("Conversion done"); + notifyConvertEvent(ConvertType.FILELIST, generateArguments); + super.launchConversion(generateArguments); + System.out.println("Conversion done"); // All the bob are generated in the output folder // Generate the same tree structure from opi project // Copy and move scripts and pictures in the generated output folder System.out.println("populate output tree structure"); populateTreeStructure(outputFolderFile, outputFolderFile, opiRootFolder); - + // Pre processing modifications // Replace import in embedded scripts and scripts file System.out.println("pre processing modifications"); updateScriptsAndBobFiles(outputFolderFile); + notifyConvertEvent(ConvertType.SUCCESS, "Process is finished"); + + } + /** + * Call Converter main class with full arguments list all the opi file + * + * @param i + */ + public static void main(String[] args) { + AdvancedConverter.getInstance().launchConversion(args); } } diff --git a/app/display/model/src/main/java/org/csstudio/display/builder/model/AdvancedConverterApp.java b/app/display/model/src/main/java/org/csstudio/display/builder/model/AdvancedConverterApp.java new file mode 100644 index 0000000000..a48498cf73 --- /dev/null +++ b/app/display/model/src/main/java/org/csstudio/display/builder/model/AdvancedConverterApp.java @@ -0,0 +1,28 @@ + +package org.csstudio.display.builder.model; + +import java.util.logging.Logger; + +import org.phoebus.framework.spi.AppDescriptor; +import org.phoebus.framework.spi.AppInstance; + +@SuppressWarnings("nls") +public class AdvancedConverterApp implements AppDescriptor +{ + public static final Logger logger = Logger.getLogger(AdvancedConverterApp.class.getPackageName()); + public static final String NAME = "advancedConverter"; + public static final String DisplayName = "OPI Converter"; + + + @Override + public String getName() { + return NAME; + } + + @Override + public AppInstance create() { + BrowserConverter.displayBrowserConverter(); + return null; + } +} + diff --git a/app/display/model/src/main/java/org/csstudio/display/builder/model/BrowserConverter.java b/app/display/model/src/main/java/org/csstudio/display/builder/model/BrowserConverter.java new file mode 100644 index 0000000000..158226a842 --- /dev/null +++ b/app/display/model/src/main/java/org/csstudio/display/builder/model/BrowserConverter.java @@ -0,0 +1,562 @@ +package org.csstudio.display.builder.model; + +import static javax.swing.JOptionPane.YES_NO_OPTION; +import static javax.swing.JOptionPane.YES_OPTION; +import static javax.swing.JOptionPane.showConfirmDialog; + +import java.awt.Color; +import java.awt.Cursor; +import java.awt.Dimension; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.io.File; +import java.io.IOException; +import java.net.URL; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +import javax.swing.Icon; +import javax.swing.ImageIcon; +import javax.swing.JButton; +import javax.swing.JDialog; +import javax.swing.JFileChooser; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JProgressBar; +import javax.swing.JScrollPane; +import javax.swing.JTextArea; +import javax.swing.JTextField; +import javax.swing.SwingUtilities; + +import org.csstudio.display.builder.model.AdvancedConverter.ConvertType; +import org.csstudio.display.builder.model.AdvancedConverter.ConverterEvent; +import org.csstudio.display.builder.model.AdvancedConverter.IConverterListener; + +public class BrowserConverter extends JFrame implements IConverterListener { + + private static final long serialVersionUID = 1L; + + private static final String TITLE_WINDOW = "BOB Converter"; + private static final String OVERRIDING_MSG = "Are you sure to override these files :"; + private static final String LABEL_NAME_OUTPUT = "Output"; + private static final String LABEL_NAME_INPUT = "Input"; + private static final String ICON_HELP = "/icons/help.png"; + private static final String SELECT_NULL = "Select Paths"; + private static final String SELECT_A_FOLDER_OUTPUT = "select a folder who will receive the conversion"; + private static final String SELECT_FOLDER_INPUT = "select a folder or a file to convert"; + private static final Color VERY_DARK_GREEN = new Color(0,102,0); + public static final Color VERY_DARK_RED = new Color(153,0,0); + + + + private static BrowserConverter instance = null; + private int progress = 0; + private String[] fileList = null; + private static File output; + private static File input; + private int returnvalue; + private static String[] args; + private ArrayList over; + + // Message JDialog + + private static JDialog dlg; + private static JLabel progressMsg; + + // HMI + private JFileChooser fileChooserInput; + private JFileChooser fileChooserOutput; + private JTextField txtFieldInput; + private JTextField txtFieldOutput; + + // process bar + private JProgressBar b; + + // input/output list + private static ArrayList outputFolderList; + private static ArrayList inputFolderList; + + // error JDialog + private static JDialog errDlg; + private static JTextArea errorArea; + private static JScrollPane scroll; + + private BrowserConverter() { + over = new ArrayList<>(); + inputFolderList = new ArrayList<>(); + outputFolderList = new ArrayList<>(); + + errorArea = new JTextArea(); + + // Set Listener to converter + AdvancedConverter.getInstance().setConverterListener(this); + + // creation of the HMI + createHIM(); + + } + + /** + * + * This method create the HIM + */ + public void createHIM() { + JPanel window = new JPanel(); + setTitle(TITLE_WINDOW); + setSize(410, 142); + setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE); + txtFieldInput = new JTextField(17); + JButton inputBut = new JButton("Browse"); + inputBut.setPreferredSize(new Dimension(80, 30)); + txtFieldOutput = new JTextField(17); + JButton outputBut = new JButton("Browse"); + outputBut.setPreferredSize(new Dimension(80, 30)); + JButton runBut = new JButton("Run"); + runBut.setPreferredSize(new Dimension(400, 30)); + URL resource = BrowserConverter.class.getResource(ICON_HELP); + Icon help = new ImageIcon(resource); + JLabel helpLabelInput = new JLabel(help); + JLabel helpLabelOutput = new JLabel(help); + helpLabelInput.setPreferredSize(new Dimension(25, 25)); + helpLabelOutput.setPreferredSize(new Dimension(25, 25)); + txtFieldInput.setEditable(false); + txtFieldOutput.setEditable(false); + JLabel inLabel = new JLabel(LABEL_NAME_INPUT); + helpLabelInput.setToolTipText(SELECT_FOLDER_INPUT); + inLabel.setToolTipText(SELECT_FOLDER_INPUT); + JLabel outLabel = new JLabel(LABEL_NAME_OUTPUT); + outLabel.setToolTipText(SELECT_A_FOLDER_OUTPUT); + helpLabelOutput.setToolTipText(SELECT_A_FOLDER_OUTPUT); + inLabel.setPreferredSize(new Dimension(55, 15)); + outLabel.setPreferredSize(new Dimension(55, 15)); + + // filtre1 = new JCheckBox("resize OPI"); + // filtre2 = new JCheckBox("Filter 2"); + // filtre3 = new JCheckBox("Filer 3"); + // filtre4 = new JCheckBox("Filter 4"); + + window.add(inLabel); + window.add(helpLabelInput); + window.add(txtFieldInput); + window.add(inputBut); + window.add(outLabel); + window.add(helpLabelOutput); + window.add(txtFieldOutput); + window.add(outputBut); + /* + * window.add(filtre1); window.add(filtre2); window.add(filtre3); + * window.add(filtre4); + */ + window.add(runBut); + + add(window); + setResizable(false); + + // open input selection if inputBut pressed + inputBut.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + try { + selectInput(); + } catch (IOException ex) { + throw new RuntimeException(ex); + } + + } + }); + + // open output selection if outputBut pressed + outputBut.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + try { + selectOutput(); + } catch (IOException ex) { + throw new RuntimeException(ex); + } + + } + }); + + // Run button to start conversion + runBut.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + reset(); + if (input != null && output != null) { + try { + if (JOptionPane.showConfirmDialog(instance, + "Are you sure to convert " + input + " into " + output, "Confirm", + YES_NO_OPTION) == YES_OPTION) { + override(input, output); + convert(); + } else { + return; + } + } catch (IOException ex) { + throw new RuntimeException(ex); + } + } else if (input != null && output == null) { + output = input; + try { + if (JOptionPane.showConfirmDialog(instance, + "Are you sure to convert " + input + " into " + output, "Confirm", + YES_NO_OPTION) == YES_OPTION) { + convert(); + } else { + return; + } + } catch (IOException ex) { + throw new RuntimeException(ex); + } + } else if (input == null && output == null) { + JOptionPane.showMessageDialog(null, SELECT_NULL); + } else if (input == output) { + + try { + if (JOptionPane.showConfirmDialog(instance, + "Are you sure to convert " + input + " into " + output, "Confirm", + YES_NO_OPTION) == YES_OPTION) { + convert(); + } + } catch (IOException ex) { + throw new RuntimeException(ex); + } + } else if (input.listFiles() == null) { + try { + if (JOptionPane.showConfirmDialog(null, "Are you sure to convert " + input + " into " + output, + "Confirm", YES_NO_OPTION) == YES_OPTION) { + convert(); + } + } catch (IOException e1) { + e1.printStackTrace(); + } + } + } + + }); + } + + /** + * + * This method open the input file or folder selection + */ + private void selectInput() throws IOException { + if (fileChooserInput == null) { + fileChooserInput = new JFileChooser(); + fileChooserInput.setDialogTitle(LABEL_NAME_INPUT); + fileChooserInput.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES); + } + returnvalue = fileChooserInput.showOpenDialog(instance); + if (returnvalue == JFileChooser.APPROVE_OPTION) { + input = fileChooserInput.getSelectedFile(); + txtFieldInput.setText(input.getAbsolutePath()); + } + } + + /** + * + * This method open the output folder selection + */ + private void selectOutput() throws IOException { + if (fileChooserOutput == null) { + fileChooserOutput = new JFileChooser(); + fileChooserOutput.setDialogTitle(LABEL_NAME_OUTPUT); + fileChooserOutput.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); + } + int returnvalue = fileChooserOutput.showOpenDialog(instance); + if (returnvalue == JFileChooser.APPROVE_OPTION) { + output = fileChooserOutput.getSelectedFile(); + txtFieldOutput.setText(output.getAbsolutePath()); + } + } + + /** + * return every opi files in the input folder + * + * @param input + * @return inputFolderList + */ + protected ArrayList getInputFile(File input) { + + if (input.listFiles() != null) { + for (final File fileEntry : Objects.requireNonNull(input.listFiles())) { + if (fileEntry.isDirectory()) { + getInputFile(fileEntry); + } else { + if (AdvancedConverter.getInstance().isOpiFile(fileEntry.getName())) { + System.out.println("input " + fileEntry.getName()); + inputFolderList.add(fileEntry); + + } + } + } + } + return inputFolderList; + + } + + /** + * return an ArrayList with every bob files in the output folder + * + * @param output + * @return outputFolderList + */ + protected ArrayList getOutputFile(File output) { + if (output.listFiles() != null) { + for (final File fileExit : Objects.requireNonNull(output.listFiles())) { + if (fileExit.isDirectory()) { + getOutputFile(fileExit); + } else { + if (AdvancedConverter.getInstance().isBobFile(fileExit.getName())) { + System.out.println("output " + fileExit.getName()); + outputFolderList.add(fileExit); + + } + } + } + } + return outputFolderList; + + } + + /** + * This method seek for similar files in the input and output folder + * + * @param input + * @param output + * @throws IOException + * + * + */ + public void override(File input, File output) throws IOException { + // research all same files in the input and output + ArrayList folder1 = getInputFile(input); + ArrayList folder2 = getOutputFile(output); + + for (int i = 0; i < folder1.size(); i++) { + for (int j = 0; j < folder2.size(); j++) { + if (folder2.get(j).getName().substring(0, folder2.get(j).getName().length() - 4) + .equals(folder1.get(i).getName().substring(0, folder1.get(i).getName().length() - 4))) { + over.add(folder2.get(j)); + } + } + } + + } + + /** + * This method delete bob files in the output folder who already exist in the + * input folder and are present in the output folder then convert the input + * folder + * + * @throws IOException + * + * + */ + public void convert() throws IOException { + // delete all duplicate file to the output + if (!over.isEmpty()) { + if (showConfirmDialog(null, OVERRIDING_MSG + " \n" + over, "Conflict", YES_NO_OPTION) == YES_OPTION) { + + List pathList = new ArrayList(); + for(File file : over) { + pathList.add(file.toPath()); + } + + for (Path path : pathList) { + Files.delete(path); + } + +// for (int i = 0; i < over.size(); i++) { +// // System.out.println("im deleting " + over.get(i).toPath()); +// Files.delete(over.get(i).toPath()); +// } + } else { + return; + } + } + // convert every files from the input + displayProgress("Processing..."); + conversion(); + } + + /** + * This method display messages during the conversion + * + * @param msgDisplay + * + * + */ + private void displayProgress(String msgDisplay) { + + // Create an instance of jdialog + if (dlg == null) { + dlg = new JDialog(dlg, "converting"); + dlg.setAlwaysOnTop(true); + dlg.setSize(250, 150); + + progressMsg = new JLabel("init message"); + b = new JProgressBar(0, 100); + dlg.add(progressMsg); + b.setBounds(35, 40, 165, 30); + progressMsg.setBounds(40, 25, 200, 15); + b.setValue(0); + dlg.setLayout(null); + b.setStringPainted(true); + dlg.add(b); + + } + + Thread displayThread = new Thread() { + + public void run() { + dlg.setLocationRelativeTo(instance); + dlg.setVisible(true); + progressMsg.setText(msgDisplay); + dlg.setCursor(new Cursor(Cursor.WAIT_CURSOR)); + + }; + }; + + // Call thread run method + SwingUtilities.invokeLater(displayThread); + } + + /** + * Thread conversion + * + * This method execute the conversion and update the message displayed + */ + private void conversion() { + Thread t = new Thread() { + public void run() { + args = new String[] { "-output ", output.getAbsolutePath(), input.getAbsolutePath() }; + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + } + AdvancedConverter.getInstance().launchConversion(args); + displayProgress("Process finish"); + try { + Thread.sleep(1500); + } catch (InterruptedException e) { + } + dlg.setVisible(false); + } + }; + t.start(); + } + + @Override + public void convertEvent(ConverterEvent event) { + ConvertType type = event.getType(); + System.out.println("convertEvent" + event.getType()); + System.out.println("File" + event.getFile()); + + switch (type) { + case FILELIST: + fileList = event.getFileList(); + break; + case NEWFILE: + incrementProgress(); + // TODO + displayProgress("Convert " + event.getFile().getName()); + progressMsg.setForeground(Color.BLACK); + break; + + case ERROR: + displayError(event.getMessage()); + displayProgress("Error script"); + progressMsg.setForeground(VERY_DARK_RED); + break; + + case SUCCESS: + displayProgress(event.getMessage()); + progressMsg.setForeground(VERY_DARK_GREEN); + default: + break; + } + + } + + /** + * this method fill the progress bar + * + * @param val(advancement + * value) + */ + private void incrementProgress() { + int percentage = 0; + int nbFile = fileList != null ? fileList.length : 0; + progress++; + System.out.println("progress " + progress); + if (nbFile == 0) { + percentage = (progress * 100) / 1; + } else { + percentage = (progress * 100) / (nbFile-2); + } + b.setValue(percentage); + + } + + /** + * display error + * + * @param msgError + */ + private void displayError(String msgError) { + if (errDlg == null) { + errDlg = new JDialog(errDlg, "Conversion error"); + errDlg.setAlwaysOnTop(true); + errDlg.setSize(550, 150); + errorArea.setEditable(false); + scroll = new JScrollPane(errorArea); + } + errorArea.append(msgError + "\n"); + errDlg.add(scroll); + errDlg.setLocationRelativeTo(null); + errDlg.setVisible(true); + + // JOptionPane.showMessageDialog( null,msgError, + // "Error",JOptionPane.WARNING_MESSAGE); + } + + /** + * reset variable of progression and of overriding after conversion + */ + private void reset() { + progress = 0; + fileList = null; + inputFolderList.clear(); + outputFolderList.clear(); + errorArea.setText(""); + over.clear(); + if(progressMsg != null || b!=null) { + progressMsg.setForeground(Color.BLACK); + b.setValue(0); + + } + + } + + public static void displayBrowserConverter() { + if (instance == null) { + instance = new BrowserConverter(); + } + instance.setVisible(true); + instance.setLocationRelativeTo(null); + instance.toFront(); + } + + // Local test + /* + * public static void main(String[] args){ try { new BrowserConvertor(); } catch + * (IOException e) { throw new RuntimeException(e); } + * + * } + */ + +} diff --git a/app/display/model/src/main/java/org/csstudio/display/builder/model/Converter.java b/app/display/model/src/main/java/org/csstudio/display/builder/model/Converter.java index e28065b8da..bb02b7ad9e 100644 --- a/app/display/model/src/main/java/org/csstudio/display/builder/model/Converter.java +++ b/app/display/model/src/main/java/org/csstudio/display/builder/model/Converter.java @@ -19,25 +19,30 @@ import org.csstudio.display.builder.model.persist.ModelReader; import org.csstudio.display.builder.model.persist.ModelWriter; -/** 'Main' for converting *.opi or older *.bob files into the current format - * @author Kay Kasemir +/** + * 'Main' for converting *.opi or older *.bob files into the current format + * + * @author Kay Kasemir */ @SuppressWarnings("nls") -public class Converter -{ - /** @param infile Input file (*.opi, older *.bob) - * @param outfile Output file (*.bob to write) - * @throws Exception on error - */ +public class Converter { + /** + * @param infile + * Input file (*.opi, older *.bob) + * @param outfile + * Output file (*.bob to write) + * @throws Exception + * on error + */ /** * * @return all opi files contained in a given folder */ - - public static final String OUTPUT_ARG = "-output"; public static final String OPI_EXTENSION = ".opi"; public static final String BOB_EXTENSION = ".bob"; + public static final String OPI = "opi"; + public static final String BOB = "bob"; public static final String PYTHON_EXTENSION = ".python"; public static final String PY_EXTENSION = ".py"; public static final String JAVASCRIPT_EXTENSION = ".javascript"; @@ -45,8 +50,14 @@ public class Converter public static final String IMPORT_CSS = "org.csstudio.opibuilder"; public static final String IMPORT_PHOEBUS = "org.csstudio.display.builder.runtime.script"; public static final String PHOEBUS = "phoebus_"; - - public static List listOpiFiles(String folder) { + + /** + * + * @param folder + * @return all opi files contained in a given folder + */ + + public List listOpiFiles(String folder) { List extensionsList = new ArrayList(); extensionsList.add(OPI_EXTENSION); return listFiles(folder, extensionsList); @@ -56,7 +67,7 @@ public static List listOpiFiles(String folder) { * * @return all bob files contained in a given folder */ - public static List listBobFiles(String folder) { + public List listBobFiles(String folder) { List extensionsList = new ArrayList(); extensionsList.add(BOB_EXTENSION); return listFiles(folder, extensionsList); @@ -66,7 +77,7 @@ public static List listBobFiles(String folder) { * * @return all script files contained in a given folder */ - public static List listScriptFiles(String folder) { + public List listScriptFiles(String folder) { List extensionsList = new ArrayList(); extensionsList.add(PYTHON_EXTENSION); extensionsList.add(PY_EXTENSION); @@ -81,7 +92,7 @@ public static List listScriptFiles(String folder) { * @param fileName * @return true if the file is a script file */ - public static boolean isScriptFile(String fileName) { + public boolean isScriptFile(String fileName) { List extensionsList = new ArrayList(); extensionsList.add(PYTHON_EXTENSION); extensionsList.add(PY_EXTENSION); @@ -96,7 +107,7 @@ public static boolean isScriptFile(String fileName) { * @param fileName * @return true if the file is a opi file */ - public static boolean isOpiFile(String fileName) { + public boolean isOpiFile(String fileName) { List extensionsList = new ArrayList(); extensionsList.add(OPI_EXTENSION); return matchExtensions(fileName, extensionsList); @@ -108,7 +119,7 @@ public static boolean isOpiFile(String fileName) { * @param fileName * @return true if the file is a bob file */ - public static boolean isBobFile(String fileName) { + public boolean isBobFile(String fileName) { List extensionsList = new ArrayList(); extensionsList.add(BOB_EXTENSION); return matchExtensions(fileName, extensionsList); @@ -137,7 +148,7 @@ public static boolean matchExtensions(String fileName, List extensionsLi * * @return all files contained in a given folder and match with given extension */ - public static List listFiles(String folder, List searchExtension) { + public List listFiles(String folder, List searchExtension) { List searchFiles = new ArrayList(); File folderFile = new File(folder); if (folderFile.exists() && folderFile.isDirectory()) { @@ -158,80 +169,100 @@ public static List listFiles(String folder, List searchExtension return searchFiles; } - - - private static void convert(final File infile, final File outfile) throws Exception - { - System.out.println("Converting: " + infile + " => " + outfile); - - final ModelReader reader = new ModelReader(new FileInputStream(infile)); - DisplayModel model = reader.readModel(); - ModelWriter writer = new ModelWriter(new FileOutputStream(outfile)); - writer.writeModel(model); - writer.close(); - } - - /** @param infile Input file (*.opi, older *.bob) - * @param output_dir Folder where to create output.bob, null to use folder of input file - * @throws Exception on error - */ - private static void convert(final String input, final File output_dir) throws Exception - { - final File infile = new File(input); - if (! infile.canRead()) - throw new Exception("Cannot read " + infile); - File outfile; - - if (isOpiFile(input)) - outfile = new File(input.substring(0, input.length()-4) + ".bob"); - else - outfile = new File(input); - if (output_dir != null) - outfile = new File(output_dir, outfile.getName()); - if (outfile.canRead()) - throw new Exception("Output file " + outfile + " exists"); - - convert(infile, outfile); - } - - /** @param args Command line arguments */ - public static void main(final String[] args) - { - if (args.length == 0 || args[0].startsWith("-h")) - { - System.out.println("Usage: -main org.csstudio.display.builder.model.Converter [-help] [-output /path/to/folder] "); - System.out.println(); - System.out.println("Converts BOY *.opi files to Display Builder *.bob format"); - System.out.println(); - System.out.println("-output /path/to/folder - Folder into which converted files are written"); - System.out.println(" - One or more files to convert"); - return; - } - final List files = new ArrayList<>(List.of(args)); - final File output_dir; - if (files.get(0).startsWith("-o")) - { - if (files.size() < 2) - { - System.err.println("Missing folder for -output /path/to/folder"); - return; - } - output_dir = new File(files.get(1)); - files.remove(0); - files.remove(0); - } - else - output_dir = null; - for (String file : files) - { - try - { - convert(file, output_dir); - } - catch (Exception ex) - { - logger.log(Level.WARNING, "Cannot convert " + file, ex); - } - } - } + private void convert(final File infile, final File outfile) throws Exception { + traceProgression(infile, outfile); // displaying current file and it output location + try (FileOutputStream outStream = new FileOutputStream(outfile); + ModelWriter writer = new ModelWriter(outStream);) + { + final ModelReader reader = new ModelReader(new FileInputStream(infile)); + DisplayModel model = reader.readModel(); + writer.writeModel(model); + writer.close(); + } catch (Exception e) { + throw e; + } + } + + /** + * displaying 2 files + * + * @param infile + * @param outfile + */ + protected void traceProgression(File infile, final File outfile) { + System.out.println("Converting: " + infile + " => " + outfile); + + } + + /** + * @param infile + * Input file (*.opi, older *.bob) + * @param output_dir + * Folder where to create output.bob, null to use folder + * of input file + * @throws Exception + * on error + */ + private void convert(final String input, final File output_dir) throws Exception { + final File infile = new File(input); + if (!infile.canRead()) + throw new Exception("Cannot read " + infile); + File outfile; + + if (isOpiFile(input)) + outfile = new File(input.substring(0, input.length() - 4) + ".bob"); + else + outfile = new File(input); + if (output_dir != null) + outfile = new File(output_dir, outfile.getName()); + if (outfile.canRead()) + throw new Exception("Output file " + outfile + " exists"); + + convert(infile, outfile); + } + + protected void launchConversion(final String[] args) { + if (args.length == 0 || args[0].startsWith("-h")) { + System.out.println( + "Usage: -main org.csstudio.display.builder.model.Converter [-help] [-output /path/to/folder] "); + System.out.println(); + System.out.println("Converts BOY *.opi files to Display Builder *.bob format"); + System.out.println(); + System.out.println("-output /path/to/folder - Folder into which converted files are written"); + System.out.println(" - One or more files to convert"); + return; + } + final List files = new ArrayList<>(List.of(args)); + final File output_dir; + if (files.get(0).startsWith("-o")) { + if (files.size() < 2) { + System.err.println("Missing folder for -output /path/to/folder"); + return; + } + output_dir = new File(files.get(1)); + files.remove(0); + files.remove(0); + } else + output_dir = null; + for (String file : files) { + try { + convert(file, output_dir); + } catch (Exception ex) { + ex.printStackTrace(); + System.err.println("Cannot convert " + file); + logger.log(Level.WARNING, "Cannot convert " + file, ex); + } + } + } + + /** + * @param args + * Command line arguments + */ + public static void main(final String[] args) { + + Converter converter = new Converter(); + converter.launchConversion(args); + } + } diff --git a/app/display/model/src/main/java/org/csstudio/display/builder/model/ConverterMenuEntry.java b/app/display/model/src/main/java/org/csstudio/display/builder/model/ConverterMenuEntry.java new file mode 100644 index 0000000000..32ca441b49 --- /dev/null +++ b/app/display/model/src/main/java/org/csstudio/display/builder/model/ConverterMenuEntry.java @@ -0,0 +1,40 @@ +package org.csstudio.display.builder.model; + +import org.phoebus.framework.workbench.ApplicationService; +import org.phoebus.ui.javafx.ImageCache; +import org.phoebus.ui.spi.MenuEntry; + +import javafx.scene.image.Image; + + +@SuppressWarnings("nls") +public class ConverterMenuEntry implements MenuEntry { + + + @Override + public Void call() throws Exception { + ApplicationService.createInstance(AdvancedConverterApp.NAME); + return null; + } + + @Override + public String getMenuPath() { + // TODO Auto-generated method stub + return "Utility"; + } + + @Override + public String getName() { + // TODO Auto-generated method stub + return AdvancedConverterApp.DisplayName; + } + + public Image getIcon() + { + return ImageCache.getImage(AdvancedConverterApp.class, "/icons/arrow_refresh.png"); + } + + + + +} diff --git a/app/display/model/src/main/resources/META-INF/services/org.phoebus.framework.spi.AppDescriptor b/app/display/model/src/main/resources/META-INF/services/org.phoebus.framework.spi.AppDescriptor new file mode 100644 index 0000000000..9fa0ea9947 --- /dev/null +++ b/app/display/model/src/main/resources/META-INF/services/org.phoebus.framework.spi.AppDescriptor @@ -0,0 +1 @@ +org.csstudio.display.builder.model.AdvancedConverterApp \ No newline at end of file diff --git a/app/display/model/src/main/resources/META-INF/services/org.phoebus.ui.spi.MenuEntry b/app/display/model/src/main/resources/META-INF/services/org.phoebus.ui.spi.MenuEntry new file mode 100644 index 0000000000..3850d8481b --- /dev/null +++ b/app/display/model/src/main/resources/META-INF/services/org.phoebus.ui.spi.MenuEntry @@ -0,0 +1 @@ +org.csstudio.display.builder.model.ConverterMenuEntry \ No newline at end of file diff --git a/app/display/model/src/main/resources/icons/arrow_refresh.png b/app/display/model/src/main/resources/icons/arrow_refresh.png new file mode 100644 index 0000000000000000000000000000000000000000..0de26566d4102eec080253c2d08985ec58b14838 GIT binary patch literal 685 zcmV;e0#f~nP)`!iy8(2_#ButL^3%VaH2WCpD^U)OZxp@C)2#hU)y+@T%ZNzJigNk%37 zz-WYJwT%teVfiEI+B*@v4ey@58(ld4VY_&5-ox`e@AKg+0U-I`y79bmuw_~y6+4rZ zBG5EdFDS+@M0OSE`>d7SUDOzKZ&h*4eB1iX7tOd9RiYtW2mQ--bUahxr1`i{RG@dM zL#}_X=DDO1{;UI$pFu=dLYT_=5d8WC-sLfjr7UO-HKMAwa=!>)kEhvuwre zuW3yF@ZxFCkI*+ad|5kOX%5zu8IQjhan)UqgSrFGA_0nQFn@Z08DSEUToCSz4Z1ls z&fDbq$T&7|6iq$_uDI$@q1_kQ@dfqk*0>{SDL6V)94@)ete)j++*>bIc9sj}Y;R1o z#OpH+Yt-^4wfv{nern^iVag8$XgYMs^AIOw1Qr{*Wn)N-{9ma}x2(<~`9Go1=*>YR!KZvrBS zCd!u}@M0og%Ev@_;Z?Kk>Wwv=%h_57zmt2<_1msz_niYE=YRNPpd%02TK9oK1z z>ooPno}v^sikz_|1XHFx_L%~;ljh7i(jiay5F0x*+(9aXXFCl?AdQj5XlQ65%sEv+ ztfe?|YcjPN*@yYtE~ImQh{l|#A6Z8iu>pf43Rj52CzU_dMQm|S2xR62YjQOn+z8WH zaK=!}ggOZi{4pB7SQ=xC0n|vXP_Bkx_a)FeNd}w8U97BNbSWxa^QW-li9BZ#M1!_xE*?wzt^GcoeoL*JGLSe_+l-JT2#2tz!z&^ z_s5anq&^nBklIMwRvcoP3%qs%%Ea?1c{_*V*Xj&~uLu-2Dp1fUN4<0zMo$EH>*U83 zm_9;Vt%-bE{_J_!If!1y=c+`QVZ>0_BPy z+%^pgnv`f8H)Z%0&Tp8&u*MCIC4igNW5MeWM_DHpDNi)Zxz|9XboOnitwFq$ETN=X zj-tkCJnz**Y4k#6_Ty^B=hWo~L!47r`HoP=x&3T1)JLr2t2+#fH OPI converter*, it will generate a pop up window. In this pop up, you can choose a input file or folder with the Browse button in the input section. In a similar way, you can choose or not a output folder. +To run the conversion you need to press the run button. + +If the output is empty, the conversion will be done in the input folder. + +Right before the conversion, you might have an overriding message window. It appear when you already converted a file in the output folder. + +If you select **YES**, it will **delete** all bob files present in the output folder and process the conversion normaly and convert evey opi files. + +If you select **NO**, you return in the browsing section. + +During the conversion, you can follow the conversion process with the progress bar. When the conversion is done, you return in the browsing section and can close the window with the "x" button or rerun a conversion. + + + From 9909637ca8508d40a7d6bd592b64279187cfb059 Mon Sep 17 00:00:00 2001 From: lr279911 Date: Wed, 7 Aug 2024 11:04:23 +0200 Subject: [PATCH 2/6] Adding a Phoebus App for AdvancedConverter #3049 --- .../builder/model/BrowserConverter.java | 29 +++++++++---------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/app/display/model/src/main/java/org/csstudio/display/builder/model/BrowserConverter.java b/app/display/model/src/main/java/org/csstudio/display/builder/model/BrowserConverter.java index 158226a842..72e2f5d96b 100644 --- a/app/display/model/src/main/java/org/csstudio/display/builder/model/BrowserConverter.java +++ b/app/display/model/src/main/java/org/csstudio/display/builder/model/BrowserConverter.java @@ -49,10 +49,8 @@ public class BrowserConverter extends JFrame implements IConverterListener { private static final String SELECT_NULL = "Select Paths"; private static final String SELECT_A_FOLDER_OUTPUT = "select a folder who will receive the conversion"; private static final String SELECT_FOLDER_INPUT = "select a folder or a file to convert"; - private static final Color VERY_DARK_GREEN = new Color(0,102,0); - public static final Color VERY_DARK_RED = new Color(153,0,0); - - + private static final Color VERY_DARK_GREEN = new Color(0, 102, 0); + private static final Color VERY_DARK_RED = new Color(153, 0, 0); private static BrowserConverter instance = null; private int progress = 0; @@ -360,20 +358,20 @@ public void convert() throws IOException { // delete all duplicate file to the output if (!over.isEmpty()) { if (showConfirmDialog(null, OVERRIDING_MSG + " \n" + over, "Conflict", YES_NO_OPTION) == YES_OPTION) { - + List pathList = new ArrayList(); - for(File file : over) { + for (File file : over) { pathList.add(file.toPath()); } - + for (Path path : pathList) { Files.delete(path); } - -// for (int i = 0; i < over.size(); i++) { -// // System.out.println("im deleting " + over.get(i).toPath()); -// Files.delete(over.get(i).toPath()); -// } + + // for (int i = 0; i < over.size(); i++) { + // // System.out.println("im deleting " + over.get(i).toPath()); + // Files.delete(over.get(i).toPath()); + // } } else { return; } @@ -462,7 +460,6 @@ public void convertEvent(ConverterEvent event) { break; case NEWFILE: incrementProgress(); - // TODO displayProgress("Convert " + event.getFile().getName()); progressMsg.setForeground(Color.BLACK); break; @@ -472,7 +469,7 @@ public void convertEvent(ConverterEvent event) { displayProgress("Error script"); progressMsg.setForeground(VERY_DARK_RED); break; - + case SUCCESS: displayProgress(event.getMessage()); progressMsg.setForeground(VERY_DARK_GREEN); @@ -496,7 +493,7 @@ private void incrementProgress() { if (nbFile == 0) { percentage = (progress * 100) / 1; } else { - percentage = (progress * 100) / (nbFile-2); + percentage = (progress * 100) / (nbFile - 2); } b.setValue(percentage); @@ -534,7 +531,7 @@ private void reset() { outputFolderList.clear(); errorArea.setText(""); over.clear(); - if(progressMsg != null || b!=null) { + if (progressMsg != null || b != null) { progressMsg.setForeground(Color.BLACK); b.setValue(0); From c863024959a3006202961186f58cf63f7b3bcc70 Mon Sep 17 00:00:00 2001 From: lr279911 Date: Wed, 7 Aug 2024 15:18:27 +0200 Subject: [PATCH 3/6] Optimize for loop --- .../display/builder/model/persist/ModelReader.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/app/display/model/src/main/java/org/csstudio/display/builder/model/persist/ModelReader.java b/app/display/model/src/main/java/org/csstudio/display/builder/model/persist/ModelReader.java index 7676e40c28..ecb35ab100 100644 --- a/app/display/model/src/main/java/org/csstudio/display/builder/model/persist/ModelReader.java +++ b/app/display/model/src/main/java/org/csstudio/display/builder/model/persist/ModelReader.java @@ -221,13 +221,16 @@ private List readWidgetsAllowingRetry(final Element parent_xml) final List widgets = new ArrayList<>(); final String source = xml_file == null ? "line" : xml_file; widget_errors_during_parse = 0; - for (final Element widget_xml : XMLUtil.getChildElements(parent_xml, XMLTags.WIDGET)) + Iterable childElements = XMLUtil.getChildElements(parent_xml, XMLTags.WIDGET); + for (final Element widget_xml : childElements) { boolean added = false; try { - widgets.add(readWidget(widget_xml)); + //Assign widget for debugging mode + Widget widget = readWidget(widget_xml); + widgets.add(widget); added = true; } catch (ParseAgainException ex) From aaf1d8bd21d1c6e9a08d0d2734c68b852bb43658 Mon Sep 17 00:00:00 2001 From: ks167484 Date: Thu, 8 Aug 2024 23:57:04 +0200 Subject: [PATCH 4/6] Fix Unit Test on AdvancedConverter --- .../display/builder/model/AdvancedConverterTest.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/display/model/src/test/java/org/csstudio/display/builder/model/AdvancedConverterTest.java b/app/display/model/src/test/java/org/csstudio/display/builder/model/AdvancedConverterTest.java index 91f6122e4c..31449b5c46 100644 --- a/app/display/model/src/test/java/org/csstudio/display/builder/model/AdvancedConverterTest.java +++ b/app/display/model/src/test/java/org/csstudio/display/builder/model/AdvancedConverterTest.java @@ -20,7 +20,7 @@ public void listOpiFilesTest() { String tmpOpiFolder = "src/test/resources/opiFiles"; File file = new File(tmpOpiFolder); - List listOpiFiles = AdvancedConverter.listOpiFiles(file.getAbsolutePath()); + List listOpiFiles = AdvancedConverter.getInstance().listOpiFiles(file.getAbsolutePath()); assertTrue(listOpiFiles.size() == 4); for (String opiFile : listOpiFiles) { @@ -33,11 +33,11 @@ public void listScriptFilesTest() { String tmpOpiFolder = "src/test/resources/opiFiles"; File file = new File(tmpOpiFolder); - List listScriptFiles = AdvancedConverter.listScriptFiles(file.getAbsolutePath()); + List listScriptFiles = AdvancedConverter.getInstance().listScriptFiles(file.getAbsolutePath()); assertTrue(listScriptFiles.size() == 4); for (String scriptFile : listScriptFiles) { - assertTrue(AdvancedConverter.isScriptFile(scriptFile)); + assertTrue(AdvancedConverter.getInstance().isScriptFile(scriptFile)); } } @@ -48,7 +48,7 @@ public void generateRecursiveArgumentsTest() { String tmpOpiFolder = "src/test/resources/opiFiles"; File file = new File(tmpOpiFolder); String[] arg = new String[] { file.getAbsolutePath() }; - String[] generateArguments = AdvancedConverter.generateRecursiveArguments(arg); + String[] generateArguments = AdvancedConverter.getInstance().generateRecursiveArguments(arg); // System.out.println(Arrays.toString(generateArguments)); // System.out.println(generateArguments.length); assertTrue(generateArguments.length == 6); From d3d155d4486921618505bb18fdaadbdc991d9e62 Mon Sep 17 00:00:00 2001 From: ks167484 Date: Fri, 9 Aug 2024 03:33:39 +0200 Subject: [PATCH 5/6] Use only one constant for extension --- .../csstudio/display/builder/model/AdvancedConverter.java | 6 +++--- .../org/csstudio/display/builder/model/Converter.java | 8 +++----- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/app/display/model/src/main/java/org/csstudio/display/builder/model/AdvancedConverter.java b/app/display/model/src/main/java/org/csstudio/display/builder/model/AdvancedConverter.java index 20c6fc2bd8..5946fe0e30 100644 --- a/app/display/model/src/main/java/org/csstudio/display/builder/model/AdvancedConverter.java +++ b/app/display/model/src/main/java/org/csstudio/display/builder/model/AdvancedConverter.java @@ -349,10 +349,10 @@ private void updateScriptsAndBobFiles(File outputFolderFile) { } // Replace embedded opi by bob - newContains = newContains.replaceAll(OPI, BOB); // prevent replaceAll problem for opi becoming .bob in + newContains = newContains.replaceAll(OPI_EXTENSION, BOB_EXTENSION); // prevent replaceAll problem for opi becoming .bob in // the bob file - newContains = newContains.replaceAll(OPI_EXTENSION, BOB_EXTENSION); - newContains = newContains.replaceAll(OPI_EXTENSION.toUpperCase(), BOB_EXTENSION.toUpperCase()); + newContains = newContains.replaceAll("." + OPI_EXTENSION, "." + BOB_EXTENSION); + newContains = newContains.replaceAll("." + OPI_EXTENSION.toUpperCase(), "." + BOB_EXTENSION.toUpperCase()); // Replace name of script for phoebus => phoebus_scritfile.py for (String scriptFile : scriptList) { diff --git a/app/display/model/src/main/java/org/csstudio/display/builder/model/Converter.java b/app/display/model/src/main/java/org/csstudio/display/builder/model/Converter.java index bb02b7ad9e..496e09f35b 100644 --- a/app/display/model/src/main/java/org/csstudio/display/builder/model/Converter.java +++ b/app/display/model/src/main/java/org/csstudio/display/builder/model/Converter.java @@ -39,10 +39,8 @@ public class Converter { * @return all opi files contained in a given folder */ public static final String OUTPUT_ARG = "-output"; - public static final String OPI_EXTENSION = ".opi"; - public static final String BOB_EXTENSION = ".bob"; - public static final String OPI = "opi"; - public static final String BOB = "bob"; + public static final String OPI_EXTENSION = "opi"; + public static final String BOB_EXTENSION = "bob"; public static final String PYTHON_EXTENSION = ".python"; public static final String PY_EXTENSION = ".py"; public static final String JAVASCRIPT_EXTENSION = ".javascript"; @@ -135,7 +133,7 @@ public static boolean matchExtensions(String fileName, List extensionsLi boolean match = false; if (fileName != null && extensionsList != null && !extensionsList.isEmpty()) { for (String ext : extensionsList) { - if (fileName.toLowerCase().endsWith(ext)) { + if (fileName.toLowerCase().endsWith("." + ext)) { match = true; break; } From e4a4c4fe066ae78057bf17b44ea8f4c4d675c51b Mon Sep 17 00:00:00 2001 From: lr279911 Date: Wed, 28 Aug 2024 16:03:55 +0200 Subject: [PATCH 6/6] adding the possibility to copy all pvs from a view in the widget info dialog --- .../representation/javafx/Messages.java | 2 + .../javafx/WidgetInfoDialog.java | 89 ++++++++++++++++--- .../representation/javafx/messages.properties | 2 + .../javafx/messages_fr.properties | 4 + 4 files changed, 85 insertions(+), 12 deletions(-) diff --git a/app/display/representation-javafx/src/main/java/org/csstudio/display/builder/representation/javafx/Messages.java b/app/display/representation-javafx/src/main/java/org/csstudio/display/builder/representation/javafx/Messages.java index 9a5413095b..9f0b610d55 100644 --- a/app/display/representation-javafx/src/main/java/org/csstudio/display/builder/representation/javafx/Messages.java +++ b/app/display/representation-javafx/src/main/java/org/csstudio/display/builder/representation/javafx/Messages.java @@ -50,6 +50,8 @@ public class Messages ConvertToEmbeddedJavaScript, ConvertToEmbeddedPython, ConvertToScriptFile, + CopyWidgetInfo, + CopyButton, Edit, ExportWidgetInfo, ExportFailed, diff --git a/app/display/representation-javafx/src/main/java/org/csstudio/display/builder/representation/javafx/WidgetInfoDialog.java b/app/display/representation-javafx/src/main/java/org/csstudio/display/builder/representation/javafx/WidgetInfoDialog.java index 5adf641745..c53ebbe438 100644 --- a/app/display/representation-javafx/src/main/java/org/csstudio/display/builder/representation/javafx/WidgetInfoDialog.java +++ b/app/display/representation-javafx/src/main/java/org/csstudio/display/builder/representation/javafx/WidgetInfoDialog.java @@ -20,12 +20,20 @@ import java.util.logging.Logger; import java.util.stream.Collectors; +import javafx.geometry.Pos; +import javafx.scene.layout.FlowPane; import javafx.event.EventHandler; -import javafx.scene.control.ContextMenu; -import javafx.scene.control.MenuItem; -import javafx.scene.control.SelectionMode; +import javafx.geometry.Insets; +import javafx.scene.Group; +import javafx.scene.Scene; +import javafx.scene.control.*; import javafx.scene.control.cell.PropertyValueFactory; import javafx.scene.input.ContextMenuEvent; +import javafx.scene.layout.TilePane; +import javafx.stage.Stage; +import javafx.scene.input.Clipboard; +import javafx.scene.input.ClipboardContent; + import org.csstudio.display.builder.model.DisplayModel; import org.csstudio.display.builder.model.Widget; import org.csstudio.display.builder.model.WidgetDescriptor; @@ -34,6 +42,7 @@ import org.csstudio.display.builder.model.util.DisplayWidgetStats; import org.csstudio.display.builder.model.util.VTypeUtil; import org.csstudio.display.builder.representation.javafx.widgets.JFXBaseRepresentation; +import org.epics.pva.data.PVAValue; import org.epics.vtype.Alarm; import org.epics.vtype.AlarmSeverity; import org.epics.vtype.VNumberArray; @@ -55,17 +64,8 @@ import javafx.collections.ObservableList; import javafx.event.ActionEvent; import javafx.scene.Node; -import javafx.scene.control.Alert; import javafx.scene.control.Alert.AlertType; -import javafx.scene.control.Button; import javafx.scene.control.ButtonBar.ButtonData; -import javafx.scene.control.ButtonType; -import javafx.scene.control.Dialog; -import javafx.scene.control.Label; -import javafx.scene.control.Tab; -import javafx.scene.control.TabPane; -import javafx.scene.control.TableColumn; -import javafx.scene.control.TableView; import javafx.scene.image.Image; import javafx.scene.image.ImageView; import javafx.scene.layout.HBox; @@ -189,13 +189,18 @@ public WidgetInfoDialog(final Widget widget, final Collection pv tabs.getSelectionModel().select(1); final ButtonType export = new ButtonType(Messages.ExportWidgetInfo, ButtonData.LEFT); + final ButtonType copy = new ButtonType(Messages.CopyWidgetInfo, ButtonData.LEFT); + getDialogPane().setContent(tabs); getDialogPane().getButtonTypes().addAll(export, ButtonType.CLOSE); + getDialogPane().getButtonTypes().addAll(copy); setResizable(true); tabs.setMinWidth(800); Button exportButton = (Button)getDialogPane().lookupButton(export); + Button copyButton = (Button)getDialogPane().lookupButton(copy); + exportButton.addEventFilter( ActionEvent.ACTION, event -> { @@ -210,10 +215,70 @@ public WidgetInfoDialog(final Widget widget, final Collection pv event.consume(); } ); + copyButton.addEventFilter( + ActionEvent.ACTION, + event -> { + pvListDisplay(); + event.consume(); + } + ); setResultConverter(button -> true); } + + private void pvListDisplay(){ + FlowPane layout = new FlowPane(); + layout.setVgap(10); + layout.setHgap(20); + layout.setAlignment(Pos.TOP_CENTER); + Stage stage = new Stage(); + TextArea area = new TextArea(); + TilePane container = new TilePane(); + Button copyPv = new Button(Messages.CopyButton); + Button ok = new Button("OK"); + area.setPadding(new Insets(10, 10, 10, 10)); + area.setPrefSize(250,450); + stage.setResizable(false); + //stage.setMaxHeight(530); + //stage.setMaxWidth(270); + + layout.getChildren().add(area); + layout.getChildren().add(copyPv); + layout.getChildren().add(ok); + + Scene scene = new Scene(layout, 250, 500); + stage.setAlwaysOnTop(true); + stage.setTitle("PV List"); + stage.setScene(scene); + stage.show(); + + + pvs.stream().sorted(Comparator.comparing(pv -> pv.getName())).forEach(pv -> { + if(!area.getText().contains(pv.getName())) + area.setText(area.getText()+pv.getName()+"\n"); + }); + + EventHandler copying = new EventHandler() { + public void handle(ActionEvent e) + { + final Clipboard clipboard = Clipboard.getSystemClipboard(); + final ClipboardContent content = new ClipboardContent(); + content.putString(area.getText()); + clipboard.setContent(content); + } + }; + EventHandler cancel = new EventHandler() { + public void handle(ActionEvent e) + { + stage.close(); + } + }; + + copyPv.setOnAction(copying); + ok.setOnAction(cancel); + } + /** * Writes the table content of each tab to file. * diff --git a/app/display/representation-javafx/src/main/resources/org/csstudio/display/builder/representation/javafx/messages.properties b/app/display/representation-javafx/src/main/resources/org/csstudio/display/builder/representation/javafx/messages.properties index 29d8692889..d0a178c137 100644 --- a/app/display/representation-javafx/src/main/resources/org/csstudio/display/builder/representation/javafx/messages.properties +++ b/app/display/representation-javafx/src/main/resources/org/csstudio/display/builder/representation/javafx/messages.properties @@ -44,6 +44,8 @@ Copy=Copy Duplicate=Duplicate Edit=Edit\u2026 ExportWidgetInfo=Export to file +CopyWidgetInfo=Display Pv list +CopyButton =Copy to Clipboard ExportDone=Exported Widget Info to file {0}. ExportFailed=Export failed. FileTypeAll=All Files (*.*) diff --git a/app/display/representation-javafx/src/main/resources/org/csstudio/display/builder/representation/javafx/messages_fr.properties b/app/display/representation-javafx/src/main/resources/org/csstudio/display/builder/representation/javafx/messages_fr.properties index 5ca24bb967..26c1c15dd2 100644 --- a/app/display/representation-javafx/src/main/resources/org/csstudio/display/builder/representation/javafx/messages_fr.properties +++ b/app/display/representation-javafx/src/main/resources/org/csstudio/display/builder/representation/javafx/messages_fr.properties @@ -48,6 +48,10 @@ Copy=Copier Duplicate=Dupliquer Edit=Modifier\u2026 ExportWidgetInfo=Exporter vers un fichier +CopyWidgetInfo=Afficher liste des Pv +CopyButton =Copier dans le press-papier + + ExportDone=Informations sur le widget exportées dans le fichier {0}. ExportFailed=Échec de l'exportation. FileTypeAll=Tous les fichiers (*.*)