From a6f36fc60e32b5ba8bee4f43b7eddcb035570def Mon Sep 17 00:00:00 2001 From: boccioli_m Date: Thu, 8 Oct 2015 16:36:24 +0200 Subject: [PATCH] New feature: show custom panel (if its class is enabled as plugin) Working on Kollimators.java custom panel --- plugins/Kollimators.form | 8 +- plugins/Kollimators.java | 8 +- plugins/TestingList.form | 136 +++++++++++++++++------- plugins/TestingList.java | 219 +++++++++++++++++++++++++++++---------- plugins/icons/x-8px.png | Bin 0 -> 2899 bytes plugins/icons/x.png | Bin 0 -> 4513 bytes 6 files changed, 267 insertions(+), 104 deletions(-) create mode 100644 plugins/icons/x-8px.png create mode 100644 plugins/icons/x.png diff --git a/plugins/Kollimators.form b/plugins/Kollimators.form index c51d75f..7e4fe6b 100644 --- a/plugins/Kollimators.form +++ b/plugins/Kollimators.form @@ -17,7 +17,7 @@ - + @@ -66,14 +66,14 @@ - + - + @@ -100,7 +100,7 @@ - + diff --git a/plugins/Kollimators.java b/plugins/Kollimators.java index 7e309dd..9981c5f 100644 --- a/plugins/Kollimators.java +++ b/plugins/Kollimators.java @@ -88,7 +88,7 @@ public class Kollimators extends javax.swing.JPanel { layout.setHorizontalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() - .addContainerGap() + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) .addGroup(layout.createSequentialGroup() .addComponent(jLabel7) @@ -128,12 +128,12 @@ public class Kollimators extends javax.swing.JPanel { .addComponent(jTextField8, javax.swing.GroupLayout.PREFERRED_SIZE, 100, javax.swing.GroupLayout.PREFERRED_SIZE))) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addComponent(jButton1) - .addContainerGap(32, Short.MAX_VALUE)) + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() - .addContainerGap() + .addGap(0, 0, 0) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false) .addComponent(jButton1, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addGroup(layout.createSequentialGroup() @@ -156,7 +156,7 @@ public class Kollimators extends javax.swing.JPanel { .addComponent(jTextField7, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(jLabel8) .addComponent(jTextField8, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))) - .addContainerGap(16, Short.MAX_VALUE)) + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) ); }// //GEN-END:initComponents diff --git a/plugins/TestingList.form b/plugins/TestingList.form index 3a91eea..a14a9fd 100644 --- a/plugins/TestingList.form +++ b/plugins/TestingList.form @@ -48,6 +48,14 @@ + + + + + + + + @@ -180,43 +188,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -444,14 +415,99 @@ - + + + + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/TestingList.java b/plugins/TestingList.java index 1a3dfeb..f719cf6 100644 --- a/plugins/TestingList.java +++ b/plugins/TestingList.java @@ -295,9 +295,9 @@ public class TestingList extends Panel { */ private void initialise(){ initComponents(); - addCustomPanel(); initLogger(); buildTable(); + closeCustomPanel(); try { loadTests(); //if not administrator, then show only enabled tests @@ -313,32 +313,69 @@ public class TestingList extends Panel { } } + /** - * add custom panel if specified + * close the custom panel if present + */ + private void closeCustomPanel(){ + jPanelCustomFrame.removeAll(); + jPanelCustom.setVisible(false); + repaint(); + } + + /** + * load plugins available excluding the plugins used directly by TestingList + * @return list of plugins assumed to be custom panels */ - private void addCustomPanel(){ + private List getCustomPanels(){ Path pluginsPath = Paths.get(".", "home", "config", "plugins.properties"); + List stringBuffer =new ArrayList() ; try { File file = new File(pluginsPath.toString()); FileReader fileReader = new FileReader(file); BufferedReader bufferedReader = new BufferedReader(fileReader); - StringBuffer stringBuffer = new StringBuffer(); - String line; + String line, fileName; while ((line = bufferedReader.readLine()) != null) { - stringBuffer.append(line); - stringBuffer.append("\n"); + if(line.contains("=enabled")){ + fileName = line.replace(".java=enabled", ""); + fileName = (Paths.get(fileName)).getFileName().toString(); + if( !(fileName.contains("TestingListDetails") || + fileName.contains("TestingList") || + fileName.contains("NewTest"))){ + stringBuffer.add(fileName); + } + } } fileReader.close(); - System.out.println("Contents of file:"); - System.out.println(stringBuffer.toString()); + //System.out.println("Contents of file:"); + //System.out.println(stringBuffer.toString()); } catch (IOException e) { e.printStackTrace(); } + return stringBuffer; + } + + + /** + * add custom panel if specified. + * Custom panels are java classes. To add a new custom panel MyNewPanel: + * - create a panel and save it as MyNewPanel.java + * - add MyNewPanel.java file in the pshell plugins folder + * - on pshell, open Plugins and enable MyNewPanel.java + * - restart pshell + * To show the new panel, open the enu Advanced/Load Custom Panel + * + */ + private void loadCustomPanel(String sPanelClassName){ try { + closeCustomPanel(); //create a class to visualise the details panel - Class panelClass = getController().getClassByName("Kollimators"); + Class panelClass = getController().getClassByName(sPanelClassName); JPanel detailsPanel = (JPanel) panelClass.getConstructor(new Class[]{String.class}).newInstance(new Object[]{""}); - this.jPanelCustom.add(detailsPanel); + this.jPanelCustomFrame.add(detailsPanel); + repaint(); + revalidate(); + jPanelCustom.setVisible(true); } catch (ClassNotFoundException ex) { Logger.getLogger(TestingList.class.getName()).log(Level.SEVERE, null, ex); } catch (NoSuchMethodException ex) { @@ -413,6 +450,7 @@ public class TestingList extends Panel { jMenuAdvanced = new javax.swing.JMenu(); jMenuItemNewTest = new javax.swing.JMenuItem(); jMenuItemNewDevice = new javax.swing.JMenuItem(); + jMenuLoadCustomPanel = new javax.swing.JMenu(); jSeparator2 = new javax.swing.JPopupMenu.Separator(); jMenuItemEditScript = new javax.swing.JMenuItem(); jMenuItemOpenLog = new javax.swing.JMenuItem(); @@ -430,8 +468,6 @@ public class TestingList extends Panel { jSeparator4 = new javax.swing.JPopupMenu.Separator(); jCheckBoxMenuShowSelectedTests1 = new javax.swing.JCheckBoxMenuItem(); jMenuItemReload1 = new javax.swing.JMenuItem(); - jScrollPane2 = new javax.swing.JScrollPane(); - jTable1 = new javax.swing.JTable(); jPanel1 = new javax.swing.JPanel(); jPanelTopCommands = new javax.swing.JPanel(); jPanelButtons = new javax.swing.JPanel(); @@ -443,7 +479,11 @@ public class TestingList extends Panel { jCheckBoxEnableDisable = new javax.swing.JCheckBox(); jButtonMoveDown = new javax.swing.JButton(); jButtonMoveUp = new javax.swing.JButton(); + jScrollPane2 = new javax.swing.JScrollPane(); + jTable1 = new javax.swing.JTable(); jPanelCustom = new javax.swing.JPanel(); + jPanelCustomFrame = new javax.swing.JPanel(); + jButtonX = new javax.swing.JButton(); jCheckBoxMenuShowSelectedTests.setSelected(true); jCheckBoxMenuShowSelectedTests.setText("Show enabled tests only"); @@ -480,6 +520,18 @@ public class TestingList extends Panel { } }); jMenuAdvanced.add(jMenuItemNewDevice); + + jMenuLoadCustomPanel.setText("Load Custom Panel"); + jMenuLoadCustomPanel.addMenuListener(new javax.swing.event.MenuListener() { + public void menuCanceled(javax.swing.event.MenuEvent evt) { + } + public void menuDeselected(javax.swing.event.MenuEvent evt) { + } + public void menuSelected(javax.swing.event.MenuEvent evt) { + jMenuLoadCustomPanelMenuSelected(evt); + } + }); + jMenuAdvanced.add(jMenuLoadCustomPanel); jMenuAdvanced.add(jSeparator2); jMenuItemEditScript.setText("Edit selected test"); @@ -574,48 +626,6 @@ public class TestingList extends Panel { setLayout(new java.awt.BorderLayout()); - jTable1.setAutoCreateRowSorter(true); - jTable1.setFont(new java.awt.Font("Tahoma", 0, 15)); // NOI18N - jTable1.setModel(new javax.swing.table.DefaultTableModel( - new Object [][] { - - }, - new String [] { - "Enable", "Start", "Time", "Device Name", "Device Description", "Test Suite", "Test Name", "Test Peth", "Test Parameters", "Test Description", "Test Help", "Last Test Result", "Status", "" - } - ) { - Class[] types = new Class [] { - java.lang.Boolean.class, java.lang.Object.class, java.lang.Object.class, java.lang.Object.class, java.lang.Object.class, java.lang.Object.class, java.lang.Object.class, java.lang.Object.class, java.lang.Object.class, java.lang.Object.class, java.lang.Object.class, java.lang.Object.class, java.lang.Object.class, javax.swing.Icon.class - }; - boolean[] canEdit = new boolean [] { - true, true, false, false, false, false, false, false, false, false, false, false, false, false - }; - - public Class getColumnClass(int columnIndex) { - return types [columnIndex]; - } - - public boolean isCellEditable(int rowIndex, int columnIndex) { - return canEdit [columnIndex]; - } - }); - jTable1.getTableHeader().setReorderingAllowed(false); - jTable1.setDragEnabled(true); - jTable1.setRowHeight(22); - jTable1.addMouseListener(new java.awt.event.MouseAdapter() { - public void mouseClicked(java.awt.event.MouseEvent evt) { - jTable1MouseClicked(evt); - } - }); - jTable1.addKeyListener(new java.awt.event.KeyAdapter() { - public void keyReleased(java.awt.event.KeyEvent evt) { - jTable1KeyReleased(evt); - } - }); - jScrollPane2.setViewportView(jTable1); - - add(jScrollPane2, java.awt.BorderLayout.CENTER); - jPanel1.setMinimumSize(new java.awt.Dimension(100, 200)); jPanel1.setPreferredSize(new java.awt.Dimension(110, 110)); jPanel1.setLayout(new java.awt.BorderLayout()); @@ -717,7 +727,80 @@ public class TestingList extends Panel { jPanel1.add(jPanelTopCommands, java.awt.BorderLayout.CENTER); add(jPanel1, java.awt.BorderLayout.NORTH); - add(jPanelCustom, java.awt.BorderLayout.PAGE_END); + + jTable1.setAutoCreateRowSorter(true); + jTable1.setFont(new java.awt.Font("Tahoma", 0, 15)); // NOI18N + jTable1.setModel(new javax.swing.table.DefaultTableModel( + new Object [][] { + + }, + new String [] { + "Enable", "Start", "Time", "Device Name", "Device Description", "Test Suite", "Test Name", "Test Peth", "Test Parameters", "Test Description", "Test Help", "Last Test Result", "Status", "" + } + ) { + Class[] types = new Class [] { + java.lang.Boolean.class, java.lang.Object.class, java.lang.Object.class, java.lang.Object.class, java.lang.Object.class, java.lang.Object.class, java.lang.Object.class, java.lang.Object.class, java.lang.Object.class, java.lang.Object.class, java.lang.Object.class, java.lang.Object.class, java.lang.Object.class, javax.swing.Icon.class + }; + boolean[] canEdit = new boolean [] { + true, true, false, false, false, false, false, false, false, false, false, false, false, false + }; + + public Class getColumnClass(int columnIndex) { + return types [columnIndex]; + } + + public boolean isCellEditable(int rowIndex, int columnIndex) { + return canEdit [columnIndex]; + } + }); + jTable1.getTableHeader().setReorderingAllowed(false); + jTable1.setDragEnabled(true); + jTable1.setRowHeight(22); + jTable1.addMouseListener(new java.awt.event.MouseAdapter() { + public void mouseClicked(java.awt.event.MouseEvent evt) { + jTable1MouseClicked(evt); + } + }); + jTable1.addKeyListener(new java.awt.event.KeyAdapter() { + public void keyReleased(java.awt.event.KeyEvent evt) { + jTable1KeyReleased(evt); + } + }); + jScrollPane2.setViewportView(jTable1); + + add(jScrollPane2, java.awt.BorderLayout.CENTER); + + jPanelCustom.setPreferredSize(new java.awt.Dimension(400, 100)); + + jButtonX.setFont(new java.awt.Font("Tahoma", 0, 8)); // NOI18N + jButtonX.setIcon(new javax.swing.ImageIcon(getClass().getResource("/icons/x-8px.png"))); // NOI18N + jButtonX.setToolTipText("Close this custom panel"); + jButtonX.setPreferredSize(new java.awt.Dimension(8, 8)); + jButtonX.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + jButtonXActionPerformed(evt); + } + }); + + javax.swing.GroupLayout jPanelCustomLayout = new javax.swing.GroupLayout(jPanelCustom); + jPanelCustom.setLayout(jPanelCustomLayout); + jPanelCustomLayout.setHorizontalGroup( + jPanelCustomLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jPanelCustomFrame, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanelCustomLayout.createSequentialGroup() + .addGap(0, 382, Short.MAX_VALUE) + .addComponent(jButtonX, javax.swing.GroupLayout.PREFERRED_SIZE, 18, javax.swing.GroupLayout.PREFERRED_SIZE)) + ); + jPanelCustomLayout.setVerticalGroup( + jPanelCustomLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanelCustomLayout.createSequentialGroup() + .addComponent(jButtonX, javax.swing.GroupLayout.DEFAULT_SIZE, 17, Short.MAX_VALUE) + .addGap(0, 0, 0) + .addComponent(jPanelCustomFrame, javax.swing.GroupLayout.PREFERRED_SIZE, 80, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(253, 253, 253)) + ); + + add(jPanelCustom, java.awt.BorderLayout.SOUTH); }// //GEN-END:initComponents private void jButtonRunActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButtonRunActionPerformed @@ -985,6 +1068,27 @@ public class TestingList extends Panel { jButtonRunActionPerformed( evt); }//GEN-LAST:event_jMenuItemRunSingleTestActionPerformed + private void jMenuLoadCustomPanelMenuSelected(javax.swing.event.MenuEvent evt) {//GEN-FIRST:event_jMenuLoadCustomPanelMenuSelected + // TODO add your handling code here: + List menuList = getCustomPanels(); + jMenuLoadCustomPanel.removeAll(); + for(int u = 0; u < menuList.size(); u++){ + + JMenuItem menuItem = new JMenuItem(menuList.get(u)); + menuItem.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + loadCustomPanel(((JMenuItem)evt.getSource()).getText()); + } + }); + jMenuLoadCustomPanel.add(menuItem); + } + }//GEN-LAST:event_jMenuLoadCustomPanelMenuSelected + + private void jButtonXActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButtonXActionPerformed + // TODO add your handling code here: + closeCustomPanel(); + }//GEN-LAST:event_jButtonXActionPerformed + // // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JButton jButtonMoveDown; @@ -993,6 +1097,7 @@ public class TestingList extends Panel { private javax.swing.JButton jButtonOptions; private javax.swing.JButton jButtonRun; private javax.swing.JButton jButtonSave; + private javax.swing.JButton jButtonX; private javax.swing.JCheckBox jCheckBoxEnableDisable; private javax.swing.JCheckBoxMenuItem jCheckBoxMenuShowSelectedTests; private javax.swing.JCheckBoxMenuItem jCheckBoxMenuShowSelectedTests1; @@ -1009,10 +1114,12 @@ public class TestingList extends Panel { private javax.swing.JMenuItem jMenuItemSelectNone; private javax.swing.JMenuItem jMenuItemSelectSelection; private javax.swing.JMenuItem jMenuItemShowDetails; + private javax.swing.JMenu jMenuLoadCustomPanel; private javax.swing.JMenu jMenuSelect; private javax.swing.JPanel jPanel1; private javax.swing.JPanel jPanelButtons; private javax.swing.JPanel jPanelCustom; + private javax.swing.JPanel jPanelCustomFrame; private javax.swing.JPanel jPanelSelection; private javax.swing.JPanel jPanelTopCommands; private javax.swing.JPopupMenu jPopupMenuConfigs; diff --git a/plugins/icons/x-8px.png b/plugins/icons/x-8px.png new file mode 100644 index 0000000000000000000000000000000000000000..ba065ed4fbcfe1d9abc8cd3909dd2d8b1caf9f1f GIT binary patch literal 2899 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 literal 0 HcmV?d00001 diff --git a/plugins/icons/x.png b/plugins/icons/x.png new file mode 100644 index 0000000000000000000000000000000000000000..97b71b78f060da03869e5459a8a84e04a3056a19 GIT binary patch literal 4513 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 literal 0 HcmV?d00001