diff --git a/src/main/java/eu/omp/irap/vespa/epntapclient/EpnTapMainApp.java b/src/main/java/eu/omp/irap/vespa/epntapclient/EpnTapMainApp.java index cd9931e..a1d05fe 100644 --- a/src/main/java/eu/omp/irap/vespa/epntapclient/EpnTapMainApp.java +++ b/src/main/java/eu/omp/irap/vespa/epntapclient/EpnTapMainApp.java @@ -23,8 +23,8 @@ import javax.swing.SwingUtilities; import com.google.gson.Gson; -import eu.omp.irap.vespa.epntapclient.gui.EpnTapMainView; -import eu.omp.irap.vespa.epntapclient.gui.GUIController; +import eu.omp.irap.vespa.epntapclient.gui.mainPanel.MainPanelView; +import eu.omp.irap.vespa.epntapclient.gui.mainPanel.MainPanelController; /** * Simple class to have a main function to launch the EPNTap client. @@ -55,12 +55,12 @@ public class EpnTapMainApp { return; } - GUIController guiCtrl = new GUIController(); + MainPanelController guiCtrl = new MainPanelController(); guiCtrl.readServices(); SwingUtilities.invokeLater(EpnTapMainApp.run(guiCtrl.getView(), "EPN-TAP client")); } - private static Runnable run(final EpnTapMainView voTableView, final String title) { + private static Runnable run(final MainPanelView voTableView, final String title) { return new Runnable() { @Override diff --git a/src/main/java/eu/omp/irap/vespa/epntapclient/gui/EpnTapMainView.java b/src/main/java/eu/omp/irap/vespa/epntapclient/gui/EpnTapMainView.java deleted file mode 100644 index aa94ba1..0000000 --- a/src/main/java/eu/omp/irap/vespa/epntapclient/gui/EpnTapMainView.java +++ /dev/null @@ -1,130 +0,0 @@ -/* - * This file is a part of EpnTAPClient. - * This program aims to provide EPN-TAP support for software clients, like CASSIS spectrum analyzer. - * See draft specifications: https://voparis-confluence.obspm.fr/pages/viewpage.action?pageId=559861 - * Copyright (C) 2016 Institut de Recherche en Astrophysique et Planétologie. - * - * This program is free software: you can - * redistribute it and/or modify it under the terms of the GNU General Public License as published - * by the Free Software Foundation, either version 3 of the License, or (at your option) any later - * version. This program is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR - * PURPOSE. See the GNU General Public License for more details. You should have received a copy of - * the GNU General Public License along with this program. If not, see - * . - */ - -package eu.omp.irap.vespa.epntapclient.gui; - -import java.awt.BorderLayout; -import java.awt.Dimension; - -import javax.swing.JOptionPane; -import javax.swing.JPanel; -import javax.swing.JSplitPane; - -import eu.omp.irap.vespa.epntapclient.gui.panels.RequestPanel; -import eu.omp.irap.vespa.epntapclient.gui.panels.ResultsPanel; -import eu.omp.irap.vespa.epntapclient.gui.panels.ServicesPanel; - -/** - * The main view of the application, which manage all the other views. - * - * @author N. Jourdane - */ -public class EpnTapMainView extends JPanel { - - /** The serial version UID. */ - private static final long serialVersionUID = 1L; - - /** The JPanel where the VOTable results is displayed. */ - private ResultsPanel resultsPanel; - - /** The JPanel where the list of services is displayed. */ - private ServicesPanel servicesPanel; - - /** The JPanel where the user build the query. */ - private RequestPanel requestPanel; - - - /** - * The main view constructor, which create all the panels. - * - * @param voTableServicesView The view to put in the services panel, built by ServicesController - * @param voTableResultsView The view to put in the results panel, built by ResultsController. - */ - - public EpnTapMainView(ViewListener viewListener) { - servicesPanel = new ServicesPanel(viewListener); - resultsPanel = new ResultsPanel(viewListener); - requestPanel = new RequestPanel(viewListener); - buildMainView(); - } - - /** - * Build and fill the GUI. - */ - private void buildMainView() { - setLayout(new BorderLayout()); - - JSplitPane northPanel = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, servicesPanel, - requestPanel); - JSplitPane mainPanel = new JSplitPane(JSplitPane.VERTICAL_SPLIT, northPanel, resultsPanel); - - add(mainPanel, BorderLayout.CENTER); - - setSizes(); - } - - private void setSizes() { - servicesPanel.setPreferredSize( - new Dimension(GUIDim.LEFT_PANEL_WIDTH, GUIDim.TOP_PANEL_HEIGHT)); - servicesPanel.setMinimumSize( - new Dimension(GUIDim.LEFT_PANEL_MIN_WIDTH, GUIDim.TOP_PANEL_MIN_HEIGHT)); - - requestPanel.setPreferredSize( - new Dimension(GUIDim.RIGHT_PANEL_WIDTH, GUIDim.TOP_PANEL_HEIGHT)); - requestPanel.setMinimumSize( - new Dimension(GUIDim.RIGHT_PANEL_MIN_WIDTH, GUIDim.TOP_PANEL_MIN_HEIGHT)); - - resultsPanel.setPreferredSize( - new Dimension(GUIDim.LEFT_PANEL_MIN_WIDTH + GUIDim.RIGHT_PANEL_MIN_WIDTH, - GUIDim.BOTTOM_PANEL_HEIGHT)); - resultsPanel.setMinimumSize( - new Dimension(GUIDim.LEFT_PANEL_MIN_WIDTH + GUIDim.RIGHT_PANEL_MIN_WIDTH, - GUIDim.BOTTOM_PANEL_MIN_HEIGHT)); - } - - /** - * @return The JPanel where the VOTable result is displayed. - */ - public ResultsPanel getResultsPanel() { - return resultsPanel; - } - - /** - * @return The JPanel containing the GUI elements to build the query. - */ - public RequestPanel getRequestPanel() { - return requestPanel; - } - - /** - * @return The JPanel where the list of services is displayed. - */ - public ServicesPanel getServicesPanel() { - return servicesPanel; - } - - /** - * Display an error message. Usually used each time an error happens. - * - * @param title The title of the error. - * @param message The message of the error. - */ - public void displayError(String title, String message) { - JOptionPane.showMessageDialog(this, message, title, - JOptionPane.ERROR_MESSAGE); - } - -} diff --git a/src/main/java/eu/omp/irap/vespa/epntapclient/gui/GUIController.java b/src/main/java/eu/omp/irap/vespa/epntapclient/gui/GUIController.java deleted file mode 100644 index 976d276..0000000 --- a/src/main/java/eu/omp/irap/vespa/epntapclient/gui/GUIController.java +++ /dev/null @@ -1,145 +0,0 @@ -/* - * This file is a part of EpnTAPClient. - * This program aims to provide EPN-TAP support for software clients, like CASSIS spectrum analyzer. - * See draft specifications: https://voparis-confluence.obspm.fr/pages/viewpage.action?pageId=559861 - * Copyright (C) 2016 Institut de Recherche en Astrophysique et Planétologie. - * - * This program is free software: you can - * redistribute it and/or modify it under the terms of the GNU General Public License as published - * by the Free Software Foundation, either version 3 of the License, or (at your option) any later - * version. This program is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR - * PURPOSE. See the GNU General Public License for more details. You should have received a copy of - * the GNU General Public License along with this program. If not, see - * . - */ - -package eu.omp.irap.vespa.epntapclient.gui; - -import java.io.File; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.util.logging.Level; -import java.util.logging.Logger; - -import javax.swing.JOptionPane; - -import eu.omp.irap.vespa.epntapclient.EpnTapController; -import eu.omp.irap.vespa.epntapclient.service.Queries; -import eu.omp.irap.vespa.votable.controller.CantGetVOTableException; - -/** - * @author N. Jourdane - */ -public class GUIController extends EpnTapController implements ViewListener { - - /** The logger for the class GUIController. */ - private static final Logger logger = Logger.getLogger(GUIController.class.getName()); - - private EpnTapMainView mainView; - - private String voTablePath; - - /** The name of the table selected by the user on the table list panel. */ - private String selectedTableName; - - /** The URL of the service corresponding to the selected table. */ - private String selectedTableServiceURL; - - - public GUIController() { - super(); - mainView = new EpnTapMainView(this); - } - - @Override - public void readServices() { - try { - servicesCtrl.readTable(); - } catch (CantGetVOTableException e) { - displayError("Can not get services.", e); - } - mainView.getServicesPanel().fillTable(servicesCtrl.getVOTableData()); - } - - public EpnTapMainView getView() { - return mainView; - } - - /** Update the row selected by the user on the Services Panel. */ - @Override - public void onServiceSelected(int selectedServiceRow) { - String url = mainView.getServicesPanel().getServiceURL(selectedServiceRow); - String tableName = mainView.getServicesPanel().getTableName(selectedServiceRow); - updateService(url, tableName); - } - - /** Send the specified query on selectedTableServiceURL */ - @Override - public void onSendButtonClicked(String query) { - GUIController.logger.info("Sending query: " + query + " on " + selectedTableServiceURL); - try { - voTablePath = sendQuery(query, selectedTableServiceURL); - } catch (CantGetVOTableException e) { - displayError("Can not send the query.", e); - GUIController.logger.log(Level.WARNING, "Can not send query.", e); - } - - mainView.getResultsPanel().fillTable(resultsCtrl.getVOTableData()); - } - - @Override - public void displayError(String message, Exception e) { - logger.log(Level.SEVERE, message, e); - JOptionPane.showMessageDialog(mainView, e.getMessage(), message, JOptionPane.ERROR_MESSAGE); - } - - /** Copy the VOTable to a specified location. */ - @Override - public void onDownloadButtonClicked(File outputFile) { - try { - Files.copy(Paths.get(voTablePath), Paths.get(outputFile.getAbsolutePath())); - } catch (IOException e) { - // TODO create exception - mainView.displayError("Can not save the file.", - "Check that you can write on the specified directory."); - GUIController.logger.log(Level.WARNING, "Can not save the file.", e); - } - } - - /** Update a query parameter in the parameter list. */ - @Override - public void onParameterChanged(String paramName, Object paramValue) { - updateParameter(paramName, paramValue); - updateQueryArea(); - GUIController.logger.info("uploaded " + paramName + ": " + paramValue); - } - - /** Remove a query parameter from the parameters list. */ - @Override - public void onParameterRemoved(String paramName) { - removeParameter(paramName); - updateQueryArea(); - GUIController.logger.info("removed " + paramName); - } - - /** - * Update the query area with a working ADQL query, based on the parameters list. - */ - private void updateQueryArea() { - String query = Queries.getQuery(selectedTableName, paramValues, 10); - mainView.getRequestPanel().updateQueryArea(query); - } - - public void updateService(String serviceURL, String tableName) { - if (!tableName.equals(selectedTableName)) { - selectedTableServiceURL = serviceURL; - selectedTableName = tableName; - updateQueryArea(); - GUIController.logger.info("Selected table: " + selectedTableName + " - service: " - + selectedTableServiceURL); - } - } - -} diff --git a/src/main/java/eu/omp/irap/vespa/epntapclient/gui/GUIDim.java b/src/main/java/eu/omp/irap/vespa/epntapclient/gui/GUIDim.java deleted file mode 100644 index 4823552..0000000 --- a/src/main/java/eu/omp/irap/vespa/epntapclient/gui/GUIDim.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * This file is a part of EpnTAPClient. - * This program aims to provide EPN-TAP support for software clients, like CASSIS spectrum analyzer. - * See draft specifications: https://voparis-confluence.obspm.fr/pages/viewpage.action?pageId=559861 - * Copyright (C) 2016 Institut de Recherche en Astrophysique et Planétologie. - * - * This program is free software: you can - * redistribute it and/or modify it under the terms of the GNU General Public License as published - * by the Free Software Foundation, either version 3 of the License, or (at your option) any later - * version. This program is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR - * PURPOSE. See the GNU General Public License for more details. You should have received a copy of - * the GNU General Public License along with this program. If not, see - * . - */ - -package eu.omp.irap.vespa.epntapclient.gui; - -/** - * A simple class containing GUI panel and elements dimensions. - * - * @author N. Jourdane - */ -public class GUIDim { - - /** The width of the left panel (services view). */ - public static final int LEFT_PANEL_WIDTH = 550; - - /** The minimum width of the left panel (services view). */ - public static final int LEFT_PANEL_MIN_WIDTH = 300; - - /** The width of the right panel (request view). */ - public static final int RIGHT_PANEL_WIDTH = 450; - - /** The minimum width of the right panel (request view). */ - public static final int RIGHT_PANEL_MIN_WIDTH = 220; - - /** The height of the top panel (request view and services view). */ - public static final int TOP_PANEL_HEIGHT = 400; - - /** The minimum height of the top panel (request view and services view). */ - public static final int TOP_PANEL_MIN_HEIGHT = 100; - - /** The height of the bottom panel (result view). */ - public static final int BOTTOM_PANEL_HEIGHT = 150; - - /** The minimum height of the bottom panel (result view). */ - public static final int BOTTOM_PANEL_MIN_HEIGHT = 100; - - - /** Private constructor to hide the implicit public one. */ - private GUIDim() { - } -} diff --git a/src/main/java/eu/omp/irap/vespa/epntapclient/gui/ParamField.java b/src/main/java/eu/omp/irap/vespa/epntapclient/gui/ParamField.java deleted file mode 100644 index 58cd18b..0000000 --- a/src/main/java/eu/omp/irap/vespa/epntapclient/gui/ParamField.java +++ /dev/null @@ -1,663 +0,0 @@ -/* - * This file is a part of EpnTAPClient. - * This program aims to provide EPN-TAP support for software clients, like CASSIS spectrum analyzer. - * See draft specifications: https://voparis-confluence.obspm.fr/pages/viewpage.action?pageId=559861 - * Copyright (C) 2016 Institut de Recherche en Astrophysique et Planétologie. - * - * This program is free software: you can - * redistribute it and/or modify it under the terms of the GNU General Public License as published - * by the Free Software Foundation, either version 3 of the License, or (at your option) any later - * version. This program is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR - * PURPOSE. See the GNU General Public License for more details. You should have received a copy of - * the GNU General Public License along with this program. If not, see - * . - */ - -package eu.omp.irap.vespa.epntapclient.gui; - -import java.awt.Color; -import java.awt.Dimension; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.text.DateFormat; -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.List; -import java.util.Locale; -import java.util.logging.Level; -import java.util.logging.Logger; - -import javax.swing.BoxLayout; -import javax.swing.JComboBox; -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.JTextField; -import javax.swing.SwingUtilities; -import javax.swing.event.DocumentEvent; -import javax.swing.event.DocumentListener; - -import eu.omp.irap.vespa.epntapclient.EpnTapGet; -import eu.omp.irap.vespa.votable.utils.CantSendQueryException; - -/** - * A field used to set a service parameter to build the query (in the parameter panel). ParamField - * is an abstract method and all type of parameter field should extend it. See - * https://voparis-confluence.obspm.fr/display/VES/4+-+EPN-TAP+queries to get all parameters - * details. - * - * @author N. Jourdane - */ -public abstract class ParamField extends JPanel { - - /** The serial version UID. */ - private static final long serialVersionUID = 1L; - - /** The logger for the class ParamField. */ - protected static final Logger logger = Logger.getLogger(ParamField.class.getName()); - - /** The minimum width of the field. */ - private static final int MIN_FIELD_WIDTH = 30; - - /** The preferred field height. */ - private static final int FIELD_HEIGHT = 20; - - /** The maximum width of the field. */ - private static final int MAX_FIELD_WIDTH = 400; - - /** The preferred label width. */ - private static final int LABEL_WIDTH = 140; - - /** The date format used in the DateRange field */ - private static final String DATE_FORMAT = "dd/MM/yyyy"; - - /** The regex used to validate the Date fields */ - private static final String DATE_REGEX = "(^(((0[1-9]|1[0-9]|2[0-8])[\\/](0[1-9]|1[012]))|((29|30|31)[\\/](0[13578]|1[02]))|((29|30)[\\/](0[4,6,9]|11)))[\\/](19|[2-9][0-9])\\d\\d$)|(^29[\\/]02[\\/](19|[2-9][0-9])(00|04|08|12|16|20|24|28|32|36|40|44|48|52|56|60|64|68|72|76|80|84|88|92|96)$)"; - - /** The suffix used in REG-TAP parameters names, indicating that it's a beginning of a range. */ - private static final String MIN_SUFFIX = "min"; - - /** The suffix used in REG-TAP parameters names, indicating that it is a end of a range. */ - private static final String MAX_SUFFIX = "max"; - - /** The main view of the application. */ - protected ViewListener viewListener; - - /** The parameter name of the field */ - protected String paramName; - - - /** - * Method constructor for the parameter field abstract class, which do all common action for all - * type of field, such as displaying the name of the parameter. - * - * @param mainView The main view of the application. - * @param paramName The name of the parameter. - */ - public ParamField(ViewListener viewListener, String paramName) { - super(); - - this.viewListener = viewListener; - this.paramName = paramName; - - buildParamField(); - } - - private void buildParamField() { - setLayout(new BoxLayout(this, BoxLayout.X_AXIS)); - - setMaximumSize(new Dimension(ParamField.MAX_FIELD_WIDTH, ParamField.FIELD_HEIGHT)); - - String strLabel = paramName.replaceAll("_", " ").trim(); - JLabel label = new JLabel(strLabel.substring(0, 1).toUpperCase() + strLabel.substring(1)); - label.setPreferredSize(new Dimension(ParamField.LABEL_WIDTH, ParamField.FIELD_HEIGHT)); - - this.add(label); - } - - - /** - * The string field is used for parameter with a `String` class. It is a simple JTextField with - * no verification. The parameter is sent to the controller each time it is modified. - * - * @author N. Jourdane - */ - public static class StringField extends ParamField implements TextFieldListener { - - /** The serial version UID. */ - private static final long serialVersionUID = 1L; - - /** The JTextField used to put the parameter value. */ - JTextField field; - - - /** - * Method constructor for the string field. - * - * @param mainView The main view of the application. - * @param paramName The name of the parameter. - */ - public StringField(ViewListener viewListener, String paramName) { - super(viewListener, paramName); - field = new JTextField(); - ParamField.addChangeListener(this, field); - this.add(field); - } - - /** - * This method is called each time the field is modified. - */ - @Override - public void update(JTextField textField) { - if (textField.getText().isEmpty()) { - viewListener.onParameterChanged(paramName, null); - } else { - viewListener.onParameterChanged(paramName, textField.getText()); - } - } - } - - /** - * The float field is used for parameter with a `Float` class. It is a JTextField which checks - * if the content is a valid float. If the parameter is valid or if it is empty, then the float - * value is sent to the controller. - * - * @author N. Jourdane - */ - public static class FloatField extends ParamField implements TextFieldListener { - - /** The serial version UID. */ - private static final long serialVersionUID = 1L; - - /** The JTextField used to put the parameter value. */ - JTextField field; - - - /** - * Method constructor - * - * @param mainView The main view of the application. - * @param paramName The name of the parameter. - */ - public FloatField(ViewListener viewListener, String paramName) { - super(viewListener, paramName); - field = new JTextField(); - ParamField.addChangeListener(this, field); - this.add(field); - } - - /** - * This method is called each time the field is modified. - */ - @Override - public void update(JTextField textField) { - if (textField.getText().isEmpty()) { - textField.setBackground(Color.WHITE); - viewListener.onParameterRemoved(paramName); - } else { - try { - float value = Float.parseFloat(textField.getText()); - viewListener.onParameterChanged(paramName, value); - textField.setBackground(Color.WHITE); - } catch (@SuppressWarnings("unused") NumberFormatException e) { - textField.setBackground(Color.PINK); - } - } - } - } - - /** - * The date range field is used for couples of parameter with both a `Date` type (actually only - * `time_min` and `time_max` parameters is concerned for now). These are JTextFields which check - * if the content is a valid date, according to DATE_FORMAT. If the parameter is valid or if it - * is empty, then the dates value are sent to the controller, in Julian Day format. - * - * @author N. Jourdane - */ - public static class DateRangeField extends ParamField implements TextFieldListener { - - /** The serial version UID. */ - private static final long serialVersionUID = 1L; - - /** The JTextField used to put the parameter minimum value of the range. */ - JTextField fieldMin; - - /** The JTextField used to put the parameter maximum value of the range. */ - JTextField fieldMax; - - - /** - * Method constructor - * - * @param mainView The main view of the application. - * @param paramName The name of the parameter. - */ - public DateRangeField(ViewListener viewListener, String paramName) { - super(viewListener, paramName); - this.add(new JLabel("min ")); - fieldMin = new JTextField(); - fieldMin.setName(ParamField.MIN_SUFFIX); - fieldMin.setPreferredSize( - new Dimension(ParamField.MIN_FIELD_WIDTH, ParamField.FIELD_HEIGHT)); - ParamField.addChangeListener(this, fieldMin); - this.add(fieldMin); - - this.add(new JLabel("max ")); - fieldMax = new JTextField(); - fieldMax.setName(ParamField.MAX_SUFFIX); - fieldMax.setPreferredSize( - new Dimension(ParamField.MIN_FIELD_WIDTH, ParamField.FIELD_HEIGHT)); - ParamField.addChangeListener(this, fieldMin); - this.add(fieldMax); - } - - /** - * This method is called each time the field is modified. - */ - @Override - public void update(JTextField field) { - DateFormat df = new SimpleDateFormat(ParamField.DATE_FORMAT, Locale.ENGLISH); - if (field.getText().isEmpty()) { - field.setBackground(Color.WHITE); - viewListener.onParameterRemoved(paramName + field.getName()); - } else if (field.getText().matches(ParamField.DATE_REGEX)) { - try { - long date = df.parse(field.getText()).getTime(); - date = Math.round(date / 86400000.0 + 2440587.5); // to JD - viewListener.onParameterChanged(paramName + field.getName(), - date); - field.setBackground(Color.WHITE); - } catch (@SuppressWarnings("unused") ParseException e) { - field.setBackground(Color.PINK); - } - // TODO: check if date min < date max - } else { - field.setBackground(Color.PINK); - } - } - } - - /** - * The float range field is used for couples of parameter with both a `Float` class. These are - * JTextFields which check if the content is a valid float. If the parameter is valid or if it - * is empty, then the float value are sent to the controller. - * - * @author N. Jourdane - */ - public static class FloatRangeField extends ParamField implements TextFieldListener { - - /** The serial version UID. */ - private static final long serialVersionUID = 1L; - - /** The JTextField used to put the parameter minimum value of the range. */ - JTextField fieldMin; - - /** The JTextField used to put the parameter maximum value of the range. */ - JTextField fieldMax; - - - /** - * Method constructor - * - * @param mainView The main view of the application. - * @param paramName The name of the parameter. - */ - public FloatRangeField(ViewListener viewListener, String paramName) { - super(viewListener, paramName); - fieldMin = new JTextField(); - fieldMin.setName(ParamField.MIN_SUFFIX); - ParamField.addChangeListener(this, fieldMin); - this.add(fieldMin); - - fieldMax = new JTextField(); - fieldMax.setName(ParamField.MAX_SUFFIX); - ParamField.addChangeListener(this, fieldMax); - this.add(fieldMax); - } - - /** - * This method is called each time the field is modified. - */ - @Override - public void update(JTextField field) { - if (field.getText().isEmpty()) { - field.setBackground(Color.WHITE); - viewListener.onParameterRemoved(paramName + field.getName()); - } else { - try { - viewListener.onParameterChanged(paramName + field.getName(), - Float.parseFloat(field.getText())); - field.setBackground(Color.WHITE); - } catch (@SuppressWarnings("unused") NumberFormatException e) { - field.setBackground(Color.PINK); - } - } - } - } - - /** - * The target name field is used only for the `target_name` parameter. It is a ComboBox which is - * automatically filled with actual target names which begins by the entered characters, by - * asking to an online resolver (RESOLVER_URL). The parameter is sent to the controller each - * time it is updated, so it is possible to enter a parameter that the resolver do not know. - * - * @author N. Jourdane - */ - public static class TargetNameField extends ParamField implements TextFieldListener { - - /** The serial version UID. */ - private static final long serialVersionUID = 1L; - - /** The comboBox to enter the target_name and display target name propositions. */ - JComboBox comboBox; - - /** The JTextField related to the ComboBox, allowing to listen for text content update. */ - JTextField field; - - /** - * The content of the last entered value. It is used to avoid recursions, because each time - * an update event is detected, the resolver is called and the ComboBox is filled with new - * values, which trigger a new event. - */ - String lastContent; - - /** - * This method is called each time the field is modified. A Runnable is used it is - * impossible to modify the comboBox from a DocumentEvent. - */ - Runnable updateComboBox = new Runnable() { - - @Override - public void run() { - String content = field.getText(); - if (!content.equals(lastContent)) { - if (content.length() >= 2) { - lastContent = content; - comboBox.removeAllItems(); - try { - for (String s : EpnTapGet.getTargetNames(content)) { - comboBox.addItem(s); - } - } catch (CantSendQueryException e) { - ParamField.logger.log(Level.WARNING, - "Can't get table names for the resolver", e); - } - comboBox.getEditor().setItem(content); - comboBox.showPopup(); - } - if (content.isEmpty()) { - viewListener.onParameterRemoved(paramName); - } else { - viewListener.onParameterChanged(paramName, content); - } - } - } - }; - - - /** - * Method constructor - * - * @param mainView The main view of the application. - * @param paramName The name of the parameter. - */ - public TargetNameField(ViewListener viewListener, String paramName) { - super(viewListener, paramName); - comboBox = new JComboBox<>(); - comboBox.setPreferredSize( - new Dimension(ParamField.MIN_FIELD_WIDTH, ParamField.FIELD_HEIGHT)); - - comboBox.setEditable(true); - field = (JTextField) comboBox.getEditor().getEditorComponent(); - ParamField.addChangeListener(this, field); - this.add(comboBox); - } - - /** - * This method is called each time the field is modified. - */ - @Override - public void update(JTextField textField) { - SwingUtilities.invokeLater(updateComboBox); - } - } - - /** - * The data product type field is used only for the `dataproduct_type` parameter. It is a - * ComboBox filled with a list of static data product types (see - * https://voparis-confluence.obspm.fr/display/VES/4+-+EPN-TAP+queries#id-4-EPN-TAPqueries- - * __RefHeading__35_312326667_Toc3037660444.2.4DataProductType). The parameter is sent to the - * controller each time it is updated. - * - * @author N. Jourdane - */ - public static class DataProductTypeField extends ParamField { - - /** The serial version UID. */ - private static final long serialVersionUID = 1L; - - /** The comboBox used to select the data product type. */ - JComboBox comboBox; - - - /** - * An enumeration of all available data product types. Each values comes with an id because - * EPN-TAP table can possibly be filled with the id instead of the name, so the query have - * to ask for both of them. - * - * @author N. Jourdane - */ - @SuppressWarnings("javadoc") - enum DataProductType { - // @noformat - ALL("All", "all"), IM("Image", "im"), SP("Spectrum", "sp"), - DS("Dynamic spectrum", "ds"), SC("Spectral cube", "sc"), PR("Profile", "pr"), - VO("Volume", "vo"), MO("Movie", "mo"), CU("Cube", "cu"), - TS("Time series", "ts"), CA("Catalog", "ca"), SV("Spatial vector", "sv"); - // @format - - /** The full name of the data product type, such as `Dynamic spectrum`. */ - private String name = ""; - - /** The id of the data product type, such as `ds`. */ - private String id = ""; - - - /** - * Method constructor for the enumeration. - * - * @param name The full name of the data product type, such as `Dynamic spectrum`. - * @param id The id of the data product type, such as `ds`. - */ - DataProductType(String name, String id) { - this.name = name; - this.id = id; - } - - /** - * @return A list of two strings, containing the name (formated for the query) and the - * id, used in the query. A list is used instead of a array because the getQuery - * function ( @see Queries) needs to know the parameter type. - */ - public List query() { - List item = new ArrayList<>(); - item.add(name.replace(" ", "-").toLowerCase()); - item.add(id); - return item; - } - - @Override - public String toString() { - return name; - } - } - - - /** - * Method constructor - * - * @param mainView The main view of the application. - * @param paramName The name of the parameter. - */ - public DataProductTypeField(ViewListener viewListener, String paramName) { - super(viewListener, paramName); - comboBox = new JComboBox<>(DataProductType.values()); - comboBox.setSelectedItem(DataProductType.ALL); - comboBox.setPreferredSize( - new Dimension(ParamField.MIN_FIELD_WIDTH, ParamField.FIELD_HEIGHT)); - comboBox.addActionListener(new ActionListener() { - - @Override - public void actionPerformed(ActionEvent e) { - update(); - } - }); - this.add(comboBox); - } - - /** - * This method is called each time the field is modified. - */ - void update() { - DataProductType item = (DataProductType) comboBox.getSelectedItem(); - if (DataProductType.ALL.equals(item)) { - viewListener.onParameterRemoved(paramName); - } else { - viewListener.onParameterChanged(paramName, item.query()); - } - } - } - - /** - * The target class field is used only for the `target_class` parameter. It is a ComboBox filled - * with a list of static target classes (see - * https://voparis-confluence.obspm.fr/display/VES/4+-+EPN-TAP+queries#id-4-EPN-TAPqueries- - * __RefHeading__39_312326667_Toc3037660464.2.6TargetClass). The parameter is sent to the - * controller each time it is updated. - * - * @author N. Jourdane - */ - public static class TargetClassField extends ParamField { - - /** The serial version UID. */ - private static final long serialVersionUID = 1L; - - /** The comboBox used to select the target class. */ - JComboBox comboBox; - - - /** - * An enumeration of all available target classes. - * - * @author N. Jourdane - */ - @SuppressWarnings("javadoc") - enum TargetClass { - // @noformat - ALL("All"), COMET("Comet"), EXOPLANET("Exoplanet"), RING("Ring"), - SAMPLE("Sample"), SKY("Sky"), SPACECRAFT("Spacecraft"), SPACEJUNK("Spacejunk"), - STAR("Star"), INTERPLANETARY_MEDIUM("Interplanetary medium"); - // @format - - /** The name of the target class. */ - String name; - - - /** - * Method constructor for the enumeration. - * - * @param name The name of the target class. - */ - TargetClass(String name) { - this.name = name; - } - - /** - * @return The name formated for the query. - */ - String query() { - return name.replace(" ", "_").toLowerCase(); - } - } - - - /** - * Method constructor - * - * @param mainView The main view of the application. - * @param paramName The name of the parameter. - */ - public TargetClassField(ViewListener viewListener, String paramName) { - super(viewListener, paramName); - comboBox = new JComboBox<>(TargetClass.values()); - comboBox.setPreferredSize( - new Dimension(ParamField.MIN_FIELD_WIDTH, ParamField.FIELD_HEIGHT)); - comboBox.addActionListener(new ActionListener() { - - @Override - public void actionPerformed(ActionEvent e) { - update(); - } - }); - this.add(comboBox); - } - - /** - * This method is called each time the field is modified. - */ - void update() { - TargetClass value = (TargetClass) comboBox.getSelectedItem(); - if (TargetClass.ALL.equals(value)) { - viewListener.onParameterRemoved(paramName); - } else { - viewListener.onParameterChanged(paramName, value.query()); - } - } - } - - /** - * The listener of text field, it aims to provide a simple way to listen a text field without to - * override removeUpdate(DocumentEvent de), insertUpdate(DocumentEvent de) and - * changedUpdate(DocumentEvent de) on each field to listen. - * - * @author N. Jourdane - */ - interface TextFieldListener { - - /** - * When the content of the JTextField is updated. - * - * @param field The JTextField. Is useful for classes containing several text fields, such - * as DateRangeField, to know which one triggered the event. - */ - void update(JTextField field); - } - - - /** - * To add the listener. @see TextFieldListener - * - * @param changeListener The listener of text fields. - * @param field The field to listen. - */ - static void addChangeListener(final TextFieldListener changeListener, final JTextField field) { - field.getDocument().addDocumentListener(new DocumentListener() { - - @Override - public void removeUpdate(DocumentEvent de) { - changeListener.update(field); - } - - @Override - public void insertUpdate(DocumentEvent de) { - changeListener.update(field); - } - - @Override - public void changedUpdate(DocumentEvent de) { - changeListener.update(field); - } - }); - } -} \ No newline at end of file diff --git a/src/main/java/eu/omp/irap/vespa/epntapclient/gui/ViewListener.java b/src/main/java/eu/omp/irap/vespa/epntapclient/gui/ViewListener.java deleted file mode 100644 index c4775c8..0000000 --- a/src/main/java/eu/omp/irap/vespa/epntapclient/gui/ViewListener.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * This file is a part of EpnTAPClient. - * This program aims to provide EPN-TAP support for software clients, like CASSIS spectrum analyzer. - * See draft specifications: https://voparis-confluence.obspm.fr/pages/viewpage.action?pageId=559861 - * Copyright (C) 2016 Institut de Recherche en Astrophysique et Planétologie. - * - * This program is free software: you can - * redistribute it and/or modify it under the terms of the GNU General Public License as published - * by the Free Software Foundation, either version 3 of the License, or (at your option) any later - * version. This program is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR - * PURPOSE. See the GNU General Public License for more details. You should have received a copy of - * the GNU General Public License along with this program. If not, see - * . - */ - -package eu.omp.irap.vespa.epntapclient.gui; - -import java.io.File; - -/** - * The interface for the main view listener, which listen for GUI events in the view, implemented by - * the controller. - * - * @author N. Jourdane - */ -public interface ViewListener { - - /** - * When a service is selected on the service panel. - * - * @param selectedService The row number selected in the service panel. - */ - void onServiceSelected(int selectedService); - - /** - * When the `Send query` button is clicked. - * - * @param query The query to send. - */ - void onSendButtonClicked(String query); - - /** - * When the `Download VOTable` button is clicked. - * - * @param outputFile The file to copy the VOTable. - */ - void onDownloadButtonClicked(File outputFile); - - /** - * When a parameter is removed on the parameter panel. - * - * @param paramName The name of the parameter as described in REG-TAP specifications. - * @param paramValue The value of the parameter to update. - */ - void onParameterChanged(String paramName, Object paramValue); - - /** - * When a parameter is updated to a valid value on the parameter panel. - * - * @param paramName The name of the parameter as described in REG-TAP specifications. - */ - void onParameterRemoved(String paramName); -} diff --git a/src/main/java/eu/omp/irap/vespa/epntapclient/gui/mainPanel/GUIDim.java b/src/main/java/eu/omp/irap/vespa/epntapclient/gui/mainPanel/GUIDim.java new file mode 100644 index 0000000..137fa1c --- /dev/null +++ b/src/main/java/eu/omp/irap/vespa/epntapclient/gui/mainPanel/GUIDim.java @@ -0,0 +1,54 @@ +/* + * This file is a part of EpnTAPClient. + * This program aims to provide EPN-TAP support for software clients, like CASSIS spectrum analyzer. + * See draft specifications: https://voparis-confluence.obspm.fr/pages/viewpage.action?pageId=559861 + * Copyright (C) 2016 Institut de Recherche en Astrophysique et Planétologie. + * + * This program is free software: you can + * redistribute it and/or modify it under the terms of the GNU General Public License as published + * by the Free Software Foundation, either version 3 of the License, or (at your option) any later + * version. This program is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. You should have received a copy of + * the GNU General Public License along with this program. If not, see + * . + */ + +package eu.omp.irap.vespa.epntapclient.gui.mainPanel; + +/** + * A simple class containing GUI panel and elements dimensions. + * + * @author N. Jourdane + */ +public class GUIDim { + + /** The width of the left panel (services view). */ + public static final int LEFT_PANEL_WIDTH = 550; + + /** The minimum width of the left panel (services view). */ + public static final int LEFT_PANEL_MIN_WIDTH = 300; + + /** The width of the right panel (request view). */ + public static final int RIGHT_PANEL_WIDTH = 450; + + /** The minimum width of the right panel (request view). */ + public static final int RIGHT_PANEL_MIN_WIDTH = 220; + + /** The height of the top panel (request view and services view). */ + public static final int TOP_PANEL_HEIGHT = 400; + + /** The minimum height of the top panel (request view and services view). */ + public static final int TOP_PANEL_MIN_HEIGHT = 100; + + /** The height of the bottom panel (result view). */ + public static final int BOTTOM_PANEL_HEIGHT = 150; + + /** The minimum height of the bottom panel (result view). */ + public static final int BOTTOM_PANEL_MIN_HEIGHT = 100; + + + /** Private constructor to hide the implicit public one. */ + private GUIDim() { + } +} diff --git a/src/main/java/eu/omp/irap/vespa/epntapclient/gui/mainPanel/MainPanelController.java b/src/main/java/eu/omp/irap/vespa/epntapclient/gui/mainPanel/MainPanelController.java new file mode 100644 index 0000000..93a6eaf --- /dev/null +++ b/src/main/java/eu/omp/irap/vespa/epntapclient/gui/mainPanel/MainPanelController.java @@ -0,0 +1,145 @@ +/* + * This file is a part of EpnTAPClient. + * This program aims to provide EPN-TAP support for software clients, like CASSIS spectrum analyzer. + * See draft specifications: https://voparis-confluence.obspm.fr/pages/viewpage.action?pageId=559861 + * Copyright (C) 2016 Institut de Recherche en Astrophysique et Planétologie. + * + * This program is free software: you can + * redistribute it and/or modify it under the terms of the GNU General Public License as published + * by the Free Software Foundation, either version 3 of the License, or (at your option) any later + * version. This program is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. You should have received a copy of + * the GNU General Public License along with this program. If not, see + * . + */ + +package eu.omp.irap.vespa.epntapclient.gui.mainPanel; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.logging.Level; +import java.util.logging.Logger; + +import javax.swing.JOptionPane; + +import eu.omp.irap.vespa.epntapclient.EpnTapController; +import eu.omp.irap.vespa.epntapclient.service.Queries; +import eu.omp.irap.vespa.votable.controller.CantGetVOTableException; + +/** + * @author N. Jourdane + */ +public class MainPanelController extends EpnTapController implements ViewListener { + + /** The logger for the class GUIController. */ + private static final Logger logger = Logger.getLogger(MainPanelController.class.getName()); + + private MainPanelView mainView; + + private String voTablePath; + + /** The name of the table selected by the user on the table list panel. */ + private String selectedTableName; + + /** The URL of the service corresponding to the selected table. */ + private String selectedTableServiceURL; + + + public MainPanelController() { + super(); + mainView = new MainPanelView(this); + } + + @Override + public void readServices() { + try { + servicesCtrl.readTable(); + } catch (CantGetVOTableException e) { + displayError("Can not get services.", e); + } + mainView.getServicesPanel().fillTable(servicesCtrl.getVOTableData()); + } + + public MainPanelView getView() { + return mainView; + } + + /** Update the row selected by the user on the Services Panel. */ + @Override + public void onServiceSelected(int selectedServiceRow) { + String url = mainView.getServicesPanel().getServiceURL(selectedServiceRow); + String tableName = mainView.getServicesPanel().getTableName(selectedServiceRow); + updateService(url, tableName); + } + + /** Send the specified query on selectedTableServiceURL */ + @Override + public void onSendButtonClicked(String query) { + MainPanelController.logger.info("Sending query: " + query + " on " + selectedTableServiceURL); + try { + voTablePath = sendQuery(query, selectedTableServiceURL); + } catch (CantGetVOTableException e) { + displayError("Can not send the query.", e); + MainPanelController.logger.log(Level.WARNING, "Can not send query.", e); + } + + mainView.getResultsPanel().fillTable(resultsCtrl.getVOTableData()); + } + + @Override + public void displayError(String message, Exception e) { + logger.log(Level.SEVERE, message, e); + JOptionPane.showMessageDialog(mainView, e.getMessage(), message, JOptionPane.ERROR_MESSAGE); + } + + /** Copy the VOTable to a specified location. */ + @Override + public void onDownloadButtonClicked(File outputFile) { + try { + Files.copy(Paths.get(voTablePath), Paths.get(outputFile.getAbsolutePath())); + } catch (IOException e) { + // TODO create exception + mainView.displayError("Can not save the file.", + "Check that you can write on the specified directory."); + MainPanelController.logger.log(Level.WARNING, "Can not save the file.", e); + } + } + + /** Update a query parameter in the parameter list. */ + @Override + public void onParameterChanged(String paramName, Object paramValue) { + updateParameter(paramName, paramValue); + updateQueryArea(); + MainPanelController.logger.info("uploaded " + paramName + ": " + paramValue); + } + + /** Remove a query parameter from the parameters list. */ + @Override + public void onParameterRemoved(String paramName) { + removeParameter(paramName); + updateQueryArea(); + MainPanelController.logger.info("removed " + paramName); + } + + /** + * Update the query area with a working ADQL query, based on the parameters list. + */ + private void updateQueryArea() { + String query = Queries.getQuery(selectedTableName, paramValues, 10); + mainView.getRequestPanel().updateQueryArea(query); + } + + public void updateService(String serviceURL, String tableName) { + if (!tableName.equals(selectedTableName)) { + selectedTableServiceURL = serviceURL; + selectedTableName = tableName; + updateQueryArea(); + MainPanelController.logger.info("Selected table: " + selectedTableName + " - service: " + + selectedTableServiceURL); + } + } + +} diff --git a/src/main/java/eu/omp/irap/vespa/epntapclient/gui/mainPanel/MainPanelView.java b/src/main/java/eu/omp/irap/vespa/epntapclient/gui/mainPanel/MainPanelView.java new file mode 100644 index 0000000..ecd8ff6 --- /dev/null +++ b/src/main/java/eu/omp/irap/vespa/epntapclient/gui/mainPanel/MainPanelView.java @@ -0,0 +1,131 @@ +/* + * This file is a part of EpnTAPClient. + * This program aims to provide EPN-TAP support for software clients, like CASSIS spectrum analyzer. + * See draft specifications: https://voparis-confluence.obspm.fr/pages/viewpage.action?pageId=559861 + * Copyright (C) 2016 Institut de Recherche en Astrophysique et Planétologie. + * + * This program is free software: you can + * redistribute it and/or modify it under the terms of the GNU General Public License as published + * by the Free Software Foundation, either version 3 of the License, or (at your option) any later + * version. This program is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. You should have received a copy of + * the GNU General Public License along with this program. If not, see + * . + */ + +package eu.omp.irap.vespa.epntapclient.gui.mainPanel; + +import java.awt.BorderLayout; +import java.awt.Dimension; + +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JSplitPane; + +import eu.omp.irap.vespa.epntapclient.gui.requestpanel.RequestPanelView; +import eu.omp.irap.vespa.epntapclient.gui.resultpanel.ResultPanelView; +import eu.omp.irap.vespa.epntapclient.gui.servicespanel.ServicesPanelView; + +/** + * The main view of the application, which manage all the other views. + * + * @author N. Jourdane + */ +public class MainPanelView extends JPanel { + + /** The serial version UID. */ + private static final long serialVersionUID = 1L; + + /** The JPanel where the VOTable results is displayed. */ + private ResultPanelView resultsPanel; + + /** The JPanel where the list of services is displayed. */ + private ServicesPanelView servicesPanel; + + /** The JPanel where the user build the query. */ + private RequestPanelView requestPanel; + + + /** + * The main view constructor, which create all the panels. + * + * @param voTableServicesView The view to put in the services panel, built by ServicesController + * @param voTableResultsView The view to put in the results panel, built by ResultsController. + */ + + public MainPanelView(ViewListener viewListener) { + servicesPanel = new ServicesPanelView(viewListener); + resultsPanel = new ResultPanelView(viewListener); + requestPanel = new RequestPanelView(viewListener); + buildMainView(); + } + + /** + * Build and fill the GUI. + */ + private void buildMainView() { + setLayout(new BorderLayout()); + + JSplitPane northPanel = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, servicesPanel, + requestPanel); + JSplitPane mainPanel = new JSplitPane(JSplitPane.VERTICAL_SPLIT, northPanel, resultsPanel); + + add(mainPanel, BorderLayout.CENTER); + + revalidate(); + setSizes(); + } + + private void setSizes() { + servicesPanel.setPreferredSize( + new Dimension(GUIDim.LEFT_PANEL_WIDTH, GUIDim.TOP_PANEL_HEIGHT)); + servicesPanel.setMinimumSize( + new Dimension(GUIDim.LEFT_PANEL_MIN_WIDTH, GUIDim.TOP_PANEL_MIN_HEIGHT)); + + requestPanel.setPreferredSize( + new Dimension(GUIDim.RIGHT_PANEL_WIDTH, GUIDim.TOP_PANEL_HEIGHT)); + requestPanel.setMinimumSize( + new Dimension(GUIDim.RIGHT_PANEL_MIN_WIDTH, GUIDim.TOP_PANEL_MIN_HEIGHT)); + + resultsPanel.setPreferredSize( + new Dimension(GUIDim.LEFT_PANEL_MIN_WIDTH + GUIDim.RIGHT_PANEL_MIN_WIDTH, + GUIDim.BOTTOM_PANEL_HEIGHT)); + resultsPanel.setMinimumSize( + new Dimension(GUIDim.LEFT_PANEL_MIN_WIDTH + GUIDim.RIGHT_PANEL_MIN_WIDTH, + GUIDim.BOTTOM_PANEL_MIN_HEIGHT)); + } + + /** + * @return The JPanel where the VOTable result is displayed. + */ + public ResultPanelView getResultsPanel() { + return resultsPanel; + } + + /** + * @return The JPanel containing the GUI elements to build the query. + */ + public RequestPanelView getRequestPanel() { + return requestPanel; + } + + /** + * @return The JPanel where the list of services is displayed. + */ + public ServicesPanelView getServicesPanel() { + return servicesPanel; + } + + /** + * Display an error message. Usually used each time an error happens. + * + * @param title The title of the error. + * @param message The message of the error. + */ + public void displayError(String title, String message) { + JOptionPane.showMessageDialog(this, message, title, + JOptionPane.ERROR_MESSAGE); + } + +} diff --git a/src/main/java/eu/omp/irap/vespa/epntapclient/gui/mainPanel/ViewListener.java b/src/main/java/eu/omp/irap/vespa/epntapclient/gui/mainPanel/ViewListener.java new file mode 100644 index 0000000..6222ca2 --- /dev/null +++ b/src/main/java/eu/omp/irap/vespa/epntapclient/gui/mainPanel/ViewListener.java @@ -0,0 +1,64 @@ +/* + * This file is a part of EpnTAPClient. + * This program aims to provide EPN-TAP support for software clients, like CASSIS spectrum analyzer. + * See draft specifications: https://voparis-confluence.obspm.fr/pages/viewpage.action?pageId=559861 + * Copyright (C) 2016 Institut de Recherche en Astrophysique et Planétologie. + * + * This program is free software: you can + * redistribute it and/or modify it under the terms of the GNU General Public License as published + * by the Free Software Foundation, either version 3 of the License, or (at your option) any later + * version. This program is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. You should have received a copy of + * the GNU General Public License along with this program. If not, see + * . + */ + +package eu.omp.irap.vespa.epntapclient.gui.mainPanel; + +import java.io.File; + +/** + * The interface for the main view listener, which listen for GUI events in the view, implemented by + * the controller. + * + * @author N. Jourdane + */ +public interface ViewListener { + + /** + * When a service is selected on the service panel. + * + * @param selectedService The row number selected in the service panel. + */ + void onServiceSelected(int selectedService); + + /** + * When the `Send query` button is clicked. + * + * @param query The query to send. + */ + void onSendButtonClicked(String query); + + /** + * When the `Download VOTable` button is clicked. + * + * @param outputFile The file to copy the VOTable. + */ + void onDownloadButtonClicked(File outputFile); + + /** + * When a parameter is removed on the parameter panel. + * + * @param paramName The name of the parameter as described in REG-TAP specifications. + * @param paramValue The value of the parameter to update. + */ + void onParameterChanged(String paramName, Object paramValue); + + /** + * When a parameter is updated to a valid value on the parameter panel. + * + * @param paramName The name of the parameter as described in REG-TAP specifications. + */ + void onParameterRemoved(String paramName); +} diff --git a/src/main/java/eu/omp/irap/vespa/epntapclient/gui/panels/RequestPanel.java b/src/main/java/eu/omp/irap/vespa/epntapclient/gui/panels/RequestPanel.java deleted file mode 100644 index 73ccbc6..0000000 --- a/src/main/java/eu/omp/irap/vespa/epntapclient/gui/panels/RequestPanel.java +++ /dev/null @@ -1,150 +0,0 @@ -/* - * This file is a part of EpnTAPClient. - * This program aims to provide EPN-TAP support for software clients, like CASSIS spectrum analyzer. - * See draft specifications: https://voparis-confluence.obspm.fr/pages/viewpage.action?pageId=559861 - * Copyright (C) 2016 Institut de Recherche en Astrophysique et Planétologie. - * - * This program is free software: you can - * redistribute it and/or modify it under the terms of the GNU General Public License as published - * by the Free Software Foundation, either version 3 of the License, or (at your option) any later - * version. This program is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR - * PURPOSE. See the GNU General Public License for more details. You should have received a copy of - * the GNU General Public License along with this program. If not, see - * . - */ - -package eu.omp.irap.vespa.epntapclient.gui.panels; - -import java.awt.BorderLayout; -import java.awt.Dimension; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.util.ArrayList; -import java.util.List; - -import javax.swing.BorderFactory; -import javax.swing.BoxLayout; -import javax.swing.JButton; -import javax.swing.JPanel; -import javax.swing.JTextArea; - -import eu.omp.irap.vespa.epntapclient.gui.ParamField; -import eu.omp.irap.vespa.epntapclient.gui.ParamField.DataProductTypeField; -import eu.omp.irap.vespa.epntapclient.gui.ParamField.DateRangeField; -import eu.omp.irap.vespa.epntapclient.gui.ParamField.FloatRangeField; -import eu.omp.irap.vespa.epntapclient.gui.ParamField.TargetNameField; -import eu.omp.irap.vespa.epntapclient.gui.ViewListener; - -/** - * The view of the panel where the user builds the query. - * - * @author N. Jourdane - */ -public class RequestPanel extends JPanel { - - /** The serial version UID. */ - private static final long serialVersionUID = 1L; - - /** The main view of the application. */ - protected ViewListener viewListener; - - /** The text area where the user write the query. */ - protected JTextArea queryArea; - - /** - * The parameters fields for the request. - */ - private List paramFields; - - /** The height of the buttons panel. */ - private static final int BUTTON_PANEL_HEIGHT = 20; - - - /** - * Method constructor - * - * @param mainView The EPN-TAP main view. - */ - public RequestPanel(ViewListener viewListener) { - this.viewListener = viewListener; - buildRequestPanel(); - } - - private void buildRequestPanel() { - setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); - - this.add(buildParamPanel(), this); - this.add(buildQueryPanel(), this); - this.add(buildButtonPanel(), this); - } - - /** - * Build a JPanel containing graphical elements to build the query user-friendly. - * - * @return The JPanel. - */ - private JPanel buildParamPanel() { - paramFields = new ArrayList<>(); - paramFields.add(new TargetNameField(viewListener, "target_name")); - paramFields.add(new DateRangeField(viewListener, "time_")); - paramFields.add(new FloatRangeField(viewListener, "spectral_range_")); - paramFields.add(new DataProductTypeField(viewListener, "dataproduct_type")); - JPanel paramPanel = new JPanel(); - paramPanel.setLayout(new BoxLayout(paramPanel, BoxLayout.Y_AXIS)); - paramPanel.setBorder(BorderFactory.createTitledBorder("Query parameters")); - - for (ParamField field : paramFields) { - paramPanel.add(field); - } - - return paramPanel; - } - - /** - * Build a JPanel containing a text-area where the query is displayed. - * - * @return The JPanel. - */ - private JPanel buildQueryPanel() { - JPanel queryPanel = new JPanel(); - queryPanel.setBorder(BorderFactory.createTitledBorder("Query for the selected service(s)")); - queryArea = new JTextArea(""); - queryArea.setToolTipText("The query sent to the service(s)."); - queryArea.setLineWrap(true); - queryPanel.setLayout(new BorderLayout()); - queryPanel.add(queryArea, BorderLayout.CENTER); - - return queryPanel; - } - - /** - * Update the query JTextArea. - * - * @param query The string literal to put in the text-area, which will override the old content. - */ - public void updateQueryArea(String query) { - queryArea.setText(query); - } - - /** - * Build a JPanel containing the button(s), particularly the `Send` button. - * - * @return The JPanel . - */ - private JPanel buildButtonPanel() { - JPanel buttonPanel = new JPanel(); - JButton btnSend = new JButton("Send query"); - btnSend.addActionListener(new ActionListener() { - - @Override - public void actionPerformed(ActionEvent e) { - viewListener.onSendButtonClicked(queryArea.getText()); - } - }); - buttonPanel.add(btnSend); - buttonPanel.setMaximumSize(new Dimension(1000, RequestPanel.BUTTON_PANEL_HEIGHT)); - - return buttonPanel; - } -} diff --git a/src/main/java/eu/omp/irap/vespa/epntapclient/gui/panels/ResultsPanel.java b/src/main/java/eu/omp/irap/vespa/epntapclient/gui/panels/ResultsPanel.java deleted file mode 100644 index 2ae20a3..0000000 --- a/src/main/java/eu/omp/irap/vespa/epntapclient/gui/panels/ResultsPanel.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * This file is a part of EpnTAPClient. - * This program aims to provide EPN-TAP support for software clients, like CASSIS spectrum analyzer. - * See draft specifications: https://voparis-confluence.obspm.fr/pages/viewpage.action?pageId=559861 - * Copyright (C) 2016 Institut de Recherche en Astrophysique et Planétologie. - * - * This program is free software: you can - * redistribute it and/or modify it under the terms of the GNU General Public License as published - * by the Free Software Foundation, either version 3 of the License, or (at your option) any later - * version. This program is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR - * PURPOSE. See the GNU General Public License for more details. You should have received a copy of - * the GNU General Public License along with this program. If not, see - * . - */ - -package eu.omp.irap.vespa.epntapclient.gui.panels; - -import java.awt.BorderLayout; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; - -import javax.swing.JButton; -import javax.swing.JFileChooser; -import javax.swing.JLabel; -import javax.swing.JPanel; - -import eu.omp.irap.vespa.epntapclient.gui.ViewListener; -import eu.omp.irap.vespa.votable.view.VOTableView; - -/** - * @author N. Jourdane - */ -public class ResultsPanel extends VOTableView { - - /** The serial version UID. */ - private static final long serialVersionUID = 1L; - - ViewListener viewListener; - - /** A label to display several informations (aka. status bar). */ - private JLabel infoLabel; - - private JButton fileButton; - - - /** - * Method constructor which customize the result panel, but don't build it from scratch since - * VOTableView is already created by ResultController. - * - * @param mainView The main view of the application. - * @param voTableView The generic view of the VOTable panel. - */ - public ResultsPanel(ViewListener viewListener) { - super(); - this.viewListener = viewListener; - buildResultPanel(); - } - - public void buildResultPanel() { - add(buildBottomBar(), BorderLayout.SOUTH); - } - - private JPanel buildBottomBar() { - JPanel statusBar = new JPanel(); - statusBar.setLayout(new BorderLayout()); - statusBar.add(getInfoLabel()); - statusBar.add(getFileButton(), BorderLayout.EAST); - - return statusBar; - } - - public JLabel getInfoLabel() { - return infoLabel == null ? new JLabel() : infoLabel; - } - - /** - * @param infoText The text to display in the status-bar, which will override the old one. - */ - public void setInfoText(String infoText) { - infoLabel.setText(infoText); - } - - public JButton getFileButton() { - if (fileButton == null) { - fileButton = new JButton("Get File"); - fileButton.addActionListener(new ActionListener() { - - @Override - public void actionPerformed(ActionEvent e) { - final JFileChooser fc = new JFileChooser(); - fc.showOpenDialog(ResultsPanel.this); - viewListener.onDownloadButtonClicked(fc.getSelectedFile()); - } - }); - } - return fileButton; - } - -} diff --git a/src/main/java/eu/omp/irap/vespa/epntapclient/gui/panels/ServicesPanel.java b/src/main/java/eu/omp/irap/vespa/epntapclient/gui/panels/ServicesPanel.java deleted file mode 100644 index 7b12483..0000000 --- a/src/main/java/eu/omp/irap/vespa/epntapclient/gui/panels/ServicesPanel.java +++ /dev/null @@ -1,130 +0,0 @@ -/* - * This file is a part of EpnTAPClient. - * This program aims to provide EPN-TAP support for software clients, like CASSIS spectrum analyzer. - * See draft specifications: https://voparis-confluence.obspm.fr/pages/viewpage.action?pageId=559861 - * Copyright (C) 2016 Institut de Recherche en Astrophysique et Planétologie. - * - * This program is free software: you can - * redistribute it and/or modify it under the terms of the GNU General Public License as published - * by the Free Software Foundation, either version 3 of the License, or (at your option) any later - * version. This program is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR - * PURPOSE. See the GNU General Public License for more details. You should have received a copy of - * the GNU General Public License along with this program. If not, see - * . - */ - -package eu.omp.irap.vespa.epntapclient.gui.panels; - -import java.awt.BorderLayout; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; - -import javax.swing.JButton; -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.JTextField; -import javax.swing.event.ListSelectionEvent; -import javax.swing.event.ListSelectionListener; - -import eu.omp.irap.vespa.epntapclient.gui.ViewListener; -import eu.omp.irap.vespa.votable.view.VOTableView; - -/** - * @author N. Jourdane - */ -public class ServicesPanel extends VOTableView { - - /** The serial version UID. */ - private static final long serialVersionUID = 1L; - - private ViewListener viewListener; - - private JButton serviceButton; - - private JTextField serviceUrlTextField; - - private JTextField tableNameTextField; - - - /** - * Method constructor which customize the services panel, but don't build it from scratch since - * VOTableView is already created by ServicesController. Add also the JTable listener. - * - * @param mainView The main view of the application. - * @param voTableView The generic view of the VOTable panel. - */ - public ServicesPanel(final ViewListener viewListener) { - super(); - this.viewListener = viewListener; - buildServicesPanel(); - } - - private void buildServicesPanel() { - getTable().getSelectionModel().addListSelectionListener(new ListSelectionListener() { - - @Override - public void valueChanged(ListSelectionEvent evt) { - viewListener.onServiceSelected(getTable().getSelectedRow()); - } - }); - - add(buildAddServicePanel(), BorderLayout.SOUTH); - } - - private JPanel buildAddServicePanel() { - JPanel addServicePanel = new JPanel(); - addServicePanel.add(new JLabel("Service URL")); - addServicePanel.add(getServiceUrlTextField()); - addServicePanel.add(new JLabel("Table name")); - addServicePanel.add(getTableNameTextField()); - addServicePanel.add(getServiceButton()); - - return addServicePanel; - } - - private JTextField getTableNameTextField() { - return tableNameTextField == null ? new JTextField(10) : tableNameTextField; - } - - private JTextField getServiceUrlTextField() { - return serviceUrlTextField == null ? new JTextField(10) : serviceUrlTextField; - } - - private JButton getServiceButton() { - if (serviceButton == null) { - serviceButton = new JButton("Set service"); - - serviceButton.addActionListener(new ActionListener() { - - @Override - public void actionPerformed(ActionEvent e) { - viewListener.onServiceSelected(-1); - } - }); - } - return serviceButton; - } - - /** - * @param row The row index in the JTable element. - * @return The URL of the service corresponding to the row. - */ - public String getServiceURL(int row) { - if (row == -1) { - return serviceUrlTextField.getText(); - } - return (String) getValueAt(5, row); - } - - /** - * @param row The row index in the JTable element. - * @return The table name of the service corresponding to the row. - */ - public String getTableName(int row) { - if (row == -1) { - return tableNameTextField.getText(); - } - return (String) getValueAt(2, row); - } -} diff --git a/src/main/java/eu/omp/irap/vespa/epntapclient/gui/requestpanel/ParamField.java b/src/main/java/eu/omp/irap/vespa/epntapclient/gui/requestpanel/ParamField.java new file mode 100644 index 0000000..a3c6e58 --- /dev/null +++ b/src/main/java/eu/omp/irap/vespa/epntapclient/gui/requestpanel/ParamField.java @@ -0,0 +1,664 @@ +/* + * This file is a part of EpnTAPClient. + * This program aims to provide EPN-TAP support for software clients, like CASSIS spectrum analyzer. + * See draft specifications: https://voparis-confluence.obspm.fr/pages/viewpage.action?pageId=559861 + * Copyright (C) 2016 Institut de Recherche en Astrophysique et Planétologie. + * + * This program is free software: you can + * redistribute it and/or modify it under the terms of the GNU General Public License as published + * by the Free Software Foundation, either version 3 of the License, or (at your option) any later + * version. This program is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. You should have received a copy of + * the GNU General Public License along with this program. If not, see + * . + */ + +package eu.omp.irap.vespa.epntapclient.gui.requestpanel; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.text.DateFormat; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; +import java.util.logging.Level; +import java.util.logging.Logger; + +import javax.swing.BoxLayout; +import javax.swing.JComboBox; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JTextField; +import javax.swing.SwingUtilities; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; + +import eu.omp.irap.vespa.epntapclient.EpnTapGet; +import eu.omp.irap.vespa.epntapclient.gui.mainPanel.ViewListener; +import eu.omp.irap.vespa.votable.utils.CantSendQueryException; + +/** + * A field used to set a service parameter to build the query (in the parameter panel). ParamField + * is an abstract method and all type of parameter field should extend it. See + * https://voparis-confluence.obspm.fr/display/VES/4+-+EPN-TAP+queries to get all parameters + * details. + * + * @author N. Jourdane + */ +public abstract class ParamField extends JPanel { + + /** The serial version UID. */ + private static final long serialVersionUID = 1L; + + /** The logger for the class ParamField. */ + protected static final Logger logger = Logger.getLogger(ParamField.class.getName()); + + /** The minimum width of the field. */ + private static final int MIN_FIELD_WIDTH = 30; + + /** The preferred field height. */ + private static final int FIELD_HEIGHT = 20; + + /** The maximum width of the field. */ + private static final int MAX_FIELD_WIDTH = 400; + + /** The preferred label width. */ + private static final int LABEL_WIDTH = 140; + + /** The date format used in the DateRange field */ + private static final String DATE_FORMAT = "dd/MM/yyyy"; + + /** The regex used to validate the Date fields */ + private static final String DATE_REGEX = "(^(((0[1-9]|1[0-9]|2[0-8])[\\/](0[1-9]|1[012]))|((29|30|31)[\\/](0[13578]|1[02]))|((29|30)[\\/](0[4,6,9]|11)))[\\/](19|[2-9][0-9])\\d\\d$)|(^29[\\/]02[\\/](19|[2-9][0-9])(00|04|08|12|16|20|24|28|32|36|40|44|48|52|56|60|64|68|72|76|80|84|88|92|96)$)"; + + /** The suffix used in REG-TAP parameters names, indicating that it's a beginning of a range. */ + private static final String MIN_SUFFIX = "min"; + + /** The suffix used in REG-TAP parameters names, indicating that it is a end of a range. */ + private static final String MAX_SUFFIX = "max"; + + /** The main view of the application. */ + protected ViewListener viewListener; + + /** The parameter name of the field */ + protected String paramName; + + + /** + * Method constructor for the parameter field abstract class, which do all common action for all + * type of field, such as displaying the name of the parameter. + * + * @param mainView The main view of the application. + * @param paramName The name of the parameter. + */ + public ParamField(ViewListener viewListener, String paramName) { + super(); + + this.viewListener = viewListener; + this.paramName = paramName; + + buildParamField(); + } + + private void buildParamField() { + setLayout(new BoxLayout(this, BoxLayout.X_AXIS)); + + setMaximumSize(new Dimension(ParamField.MAX_FIELD_WIDTH, ParamField.FIELD_HEIGHT)); + + String strLabel = paramName.replaceAll("_", " ").trim(); + JLabel label = new JLabel(strLabel.substring(0, 1).toUpperCase() + strLabel.substring(1)); + label.setPreferredSize(new Dimension(ParamField.LABEL_WIDTH, ParamField.FIELD_HEIGHT)); + + this.add(label); + } + + + /** + * The string field is used for parameter with a `String` class. It is a simple JTextField with + * no verification. The parameter is sent to the controller each time it is modified. + * + * @author N. Jourdane + */ + public static class StringField extends ParamField implements TextFieldListener { + + /** The serial version UID. */ + private static final long serialVersionUID = 1L; + + /** The JTextField used to put the parameter value. */ + JTextField field; + + + /** + * Method constructor for the string field. + * + * @param mainView The main view of the application. + * @param paramName The name of the parameter. + */ + public StringField(ViewListener viewListener, String paramName) { + super(viewListener, paramName); + field = new JTextField(); + ParamField.addChangeListener(this, field); + this.add(field); + } + + /** + * This method is called each time the field is modified. + */ + @Override + public void update(JTextField textField) { + if (textField.getText().isEmpty()) { + viewListener.onParameterChanged(paramName, null); + } else { + viewListener.onParameterChanged(paramName, textField.getText()); + } + } + } + + /** + * The float field is used for parameter with a `Float` class. It is a JTextField which checks + * if the content is a valid float. If the parameter is valid or if it is empty, then the float + * value is sent to the controller. + * + * @author N. Jourdane + */ + public static class FloatField extends ParamField implements TextFieldListener { + + /** The serial version UID. */ + private static final long serialVersionUID = 1L; + + /** The JTextField used to put the parameter value. */ + JTextField field; + + + /** + * Method constructor + * + * @param mainView The main view of the application. + * @param paramName The name of the parameter. + */ + public FloatField(ViewListener viewListener, String paramName) { + super(viewListener, paramName); + field = new JTextField(); + ParamField.addChangeListener(this, field); + this.add(field); + } + + /** + * This method is called each time the field is modified. + */ + @Override + public void update(JTextField textField) { + if (textField.getText().isEmpty()) { + textField.setBackground(Color.WHITE); + viewListener.onParameterRemoved(paramName); + } else { + try { + float value = Float.parseFloat(textField.getText()); + viewListener.onParameterChanged(paramName, value); + textField.setBackground(Color.WHITE); + } catch (@SuppressWarnings("unused") NumberFormatException e) { + textField.setBackground(Color.PINK); + } + } + } + } + + /** + * The date range field is used for couples of parameter with both a `Date` type (actually only + * `time_min` and `time_max` parameters is concerned for now). These are JTextFields which check + * if the content is a valid date, according to DATE_FORMAT. If the parameter is valid or if it + * is empty, then the dates value are sent to the controller, in Julian Day format. + * + * @author N. Jourdane + */ + public static class DateRangeField extends ParamField implements TextFieldListener { + + /** The serial version UID. */ + private static final long serialVersionUID = 1L; + + /** The JTextField used to put the parameter minimum value of the range. */ + JTextField fieldMin; + + /** The JTextField used to put the parameter maximum value of the range. */ + JTextField fieldMax; + + + /** + * Method constructor + * + * @param mainView The main view of the application. + * @param paramName The name of the parameter. + */ + public DateRangeField(ViewListener viewListener, String paramName) { + super(viewListener, paramName); + this.add(new JLabel("min ")); + fieldMin = new JTextField(); + fieldMin.setName(ParamField.MIN_SUFFIX); + fieldMin.setPreferredSize( + new Dimension(ParamField.MIN_FIELD_WIDTH, ParamField.FIELD_HEIGHT)); + ParamField.addChangeListener(this, fieldMin); + this.add(fieldMin); + + this.add(new JLabel("max ")); + fieldMax = new JTextField(); + fieldMax.setName(ParamField.MAX_SUFFIX); + fieldMax.setPreferredSize( + new Dimension(ParamField.MIN_FIELD_WIDTH, ParamField.FIELD_HEIGHT)); + ParamField.addChangeListener(this, fieldMin); + this.add(fieldMax); + } + + /** + * This method is called each time the field is modified. + */ + @Override + public void update(JTextField field) { + DateFormat df = new SimpleDateFormat(ParamField.DATE_FORMAT, Locale.ENGLISH); + if (field.getText().isEmpty()) { + field.setBackground(Color.WHITE); + viewListener.onParameterRemoved(paramName + field.getName()); + } else if (field.getText().matches(ParamField.DATE_REGEX)) { + try { + long date = df.parse(field.getText()).getTime(); + date = Math.round(date / 86400000.0 + 2440587.5); // to JD + viewListener.onParameterChanged(paramName + field.getName(), + date); + field.setBackground(Color.WHITE); + } catch (@SuppressWarnings("unused") ParseException e) { + field.setBackground(Color.PINK); + } + // TODO: check if date min < date max + } else { + field.setBackground(Color.PINK); + } + } + } + + /** + * The float range field is used for couples of parameter with both a `Float` class. These are + * JTextFields which check if the content is a valid float. If the parameter is valid or if it + * is empty, then the float value are sent to the controller. + * + * @author N. Jourdane + */ + public static class FloatRangeField extends ParamField implements TextFieldListener { + + /** The serial version UID. */ + private static final long serialVersionUID = 1L; + + /** The JTextField used to put the parameter minimum value of the range. */ + JTextField fieldMin; + + /** The JTextField used to put the parameter maximum value of the range. */ + JTextField fieldMax; + + + /** + * Method constructor + * + * @param mainView The main view of the application. + * @param paramName The name of the parameter. + */ + public FloatRangeField(ViewListener viewListener, String paramName) { + super(viewListener, paramName); + fieldMin = new JTextField(); + fieldMin.setName(ParamField.MIN_SUFFIX); + ParamField.addChangeListener(this, fieldMin); + this.add(fieldMin); + + fieldMax = new JTextField(); + fieldMax.setName(ParamField.MAX_SUFFIX); + ParamField.addChangeListener(this, fieldMax); + this.add(fieldMax); + } + + /** + * This method is called each time the field is modified. + */ + @Override + public void update(JTextField field) { + if (field.getText().isEmpty()) { + field.setBackground(Color.WHITE); + viewListener.onParameterRemoved(paramName + field.getName()); + } else { + try { + viewListener.onParameterChanged(paramName + field.getName(), + Float.parseFloat(field.getText())); + field.setBackground(Color.WHITE); + } catch (@SuppressWarnings("unused") NumberFormatException e) { + field.setBackground(Color.PINK); + } + } + } + } + + /** + * The target name field is used only for the `target_name` parameter. It is a ComboBox which is + * automatically filled with actual target names which begins by the entered characters, by + * asking to an online resolver (RESOLVER_URL). The parameter is sent to the controller each + * time it is updated, so it is possible to enter a parameter that the resolver do not know. + * + * @author N. Jourdane + */ + public static class TargetNameField extends ParamField implements TextFieldListener { + + /** The serial version UID. */ + private static final long serialVersionUID = 1L; + + /** The comboBox to enter the target_name and display target name propositions. */ + JComboBox comboBox; + + /** The JTextField related to the ComboBox, allowing to listen for text content update. */ + JTextField field; + + /** + * The content of the last entered value. It is used to avoid recursions, because each time + * an update event is detected, the resolver is called and the ComboBox is filled with new + * values, which trigger a new event. + */ + String lastContent; + + /** + * This method is called each time the field is modified. A Runnable is used it is + * impossible to modify the comboBox from a DocumentEvent. + */ + Runnable updateComboBox = new Runnable() { + + @Override + public void run() { + String content = field.getText(); + if (!content.equals(lastContent)) { + if (content.length() >= 2) { + lastContent = content; + comboBox.removeAllItems(); + try { + for (String s : EpnTapGet.getTargetNames(content)) { + comboBox.addItem(s); + } + } catch (CantSendQueryException e) { + ParamField.logger.log(Level.WARNING, + "Can't get table names for the resolver", e); + } + comboBox.getEditor().setItem(content); + comboBox.showPopup(); + } + if (content.isEmpty()) { + viewListener.onParameterRemoved(paramName); + } else { + viewListener.onParameterChanged(paramName, content); + } + } + } + }; + + + /** + * Method constructor + * + * @param mainView The main view of the application. + * @param paramName The name of the parameter. + */ + public TargetNameField(ViewListener viewListener, String paramName) { + super(viewListener, paramName); + comboBox = new JComboBox<>(); + comboBox.setPreferredSize( + new Dimension(ParamField.MIN_FIELD_WIDTH, ParamField.FIELD_HEIGHT)); + + comboBox.setEditable(true); + field = (JTextField) comboBox.getEditor().getEditorComponent(); + ParamField.addChangeListener(this, field); + this.add(comboBox); + } + + /** + * This method is called each time the field is modified. + */ + @Override + public void update(JTextField textField) { + SwingUtilities.invokeLater(updateComboBox); + } + } + + /** + * The data product type field is used only for the `dataproduct_type` parameter. It is a + * ComboBox filled with a list of static data product types (see + * https://voparis-confluence.obspm.fr/display/VES/4+-+EPN-TAP+queries#id-4-EPN-TAPqueries- + * __RefHeading__35_312326667_Toc3037660444.2.4DataProductType). The parameter is sent to the + * controller each time it is updated. + * + * @author N. Jourdane + */ + public static class DataProductTypeField extends ParamField { + + /** The serial version UID. */ + private static final long serialVersionUID = 1L; + + /** The comboBox used to select the data product type. */ + JComboBox comboBox; + + + /** + * An enumeration of all available data product types. Each values comes with an id because + * EPN-TAP table can possibly be filled with the id instead of the name, so the query have + * to ask for both of them. + * + * @author N. Jourdane + */ + @SuppressWarnings("javadoc") + enum DataProductType { + // @noformat + ALL("All", "all"), IM("Image", "im"), SP("Spectrum", "sp"), + DS("Dynamic spectrum", "ds"), SC("Spectral cube", "sc"), PR("Profile", "pr"), + VO("Volume", "vo"), MO("Movie", "mo"), CU("Cube", "cu"), + TS("Time series", "ts"), CA("Catalog", "ca"), SV("Spatial vector", "sv"); + // @format + + /** The full name of the data product type, such as `Dynamic spectrum`. */ + private String name = ""; + + /** The id of the data product type, such as `ds`. */ + private String id = ""; + + + /** + * Method constructor for the enumeration. + * + * @param name The full name of the data product type, such as `Dynamic spectrum`. + * @param id The id of the data product type, such as `ds`. + */ + DataProductType(String name, String id) { + this.name = name; + this.id = id; + } + + /** + * @return A list of two strings, containing the name (formated for the query) and the + * id, used in the query. A list is used instead of a array because the getQuery + * function ( @see Queries) needs to know the parameter type. + */ + public List query() { + List item = new ArrayList<>(); + item.add(name.replace(" ", "-").toLowerCase()); + item.add(id); + return item; + } + + @Override + public String toString() { + return name; + } + } + + + /** + * Method constructor + * + * @param mainView The main view of the application. + * @param paramName The name of the parameter. + */ + public DataProductTypeField(ViewListener viewListener, String paramName) { + super(viewListener, paramName); + comboBox = new JComboBox<>(DataProductType.values()); + comboBox.setSelectedItem(DataProductType.ALL); + comboBox.setPreferredSize( + new Dimension(ParamField.MIN_FIELD_WIDTH, ParamField.FIELD_HEIGHT)); + comboBox.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + update(); + } + }); + this.add(comboBox); + } + + /** + * This method is called each time the field is modified. + */ + void update() { + DataProductType item = (DataProductType) comboBox.getSelectedItem(); + if (DataProductType.ALL.equals(item)) { + viewListener.onParameterRemoved(paramName); + } else { + viewListener.onParameterChanged(paramName, item.query()); + } + } + } + + /** + * The target class field is used only for the `target_class` parameter. It is a ComboBox filled + * with a list of static target classes (see + * https://voparis-confluence.obspm.fr/display/VES/4+-+EPN-TAP+queries#id-4-EPN-TAPqueries- + * __RefHeading__39_312326667_Toc3037660464.2.6TargetClass). The parameter is sent to the + * controller each time it is updated. + * + * @author N. Jourdane + */ + public static class TargetClassField extends ParamField { + + /** The serial version UID. */ + private static final long serialVersionUID = 1L; + + /** The comboBox used to select the target class. */ + JComboBox comboBox; + + + /** + * An enumeration of all available target classes. + * + * @author N. Jourdane + */ + @SuppressWarnings("javadoc") + enum TargetClass { + // @noformat + ALL("All"), COMET("Comet"), EXOPLANET("Exoplanet"), RING("Ring"), + SAMPLE("Sample"), SKY("Sky"), SPACECRAFT("Spacecraft"), SPACEJUNK("Spacejunk"), + STAR("Star"), INTERPLANETARY_MEDIUM("Interplanetary medium"); + // @format + + /** The name of the target class. */ + String name; + + + /** + * Method constructor for the enumeration. + * + * @param name The name of the target class. + */ + TargetClass(String name) { + this.name = name; + } + + /** + * @return The name formated for the query. + */ + String query() { + return name.replace(" ", "_").toLowerCase(); + } + } + + + /** + * Method constructor + * + * @param mainView The main view of the application. + * @param paramName The name of the parameter. + */ + public TargetClassField(ViewListener viewListener, String paramName) { + super(viewListener, paramName); + comboBox = new JComboBox<>(TargetClass.values()); + comboBox.setPreferredSize( + new Dimension(ParamField.MIN_FIELD_WIDTH, ParamField.FIELD_HEIGHT)); + comboBox.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + update(); + } + }); + this.add(comboBox); + } + + /** + * This method is called each time the field is modified. + */ + void update() { + TargetClass value = (TargetClass) comboBox.getSelectedItem(); + if (TargetClass.ALL.equals(value)) { + viewListener.onParameterRemoved(paramName); + } else { + viewListener.onParameterChanged(paramName, value.query()); + } + } + } + + /** + * The listener of text field, it aims to provide a simple way to listen a text field without to + * override removeUpdate(DocumentEvent de), insertUpdate(DocumentEvent de) and + * changedUpdate(DocumentEvent de) on each field to listen. + * + * @author N. Jourdane + */ + interface TextFieldListener { + + /** + * When the content of the JTextField is updated. + * + * @param field The JTextField. Is useful for classes containing several text fields, such + * as DateRangeField, to know which one triggered the event. + */ + void update(JTextField field); + } + + + /** + * To add the listener. @see TextFieldListener + * + * @param changeListener The listener of text fields. + * @param field The field to listen. + */ + static void addChangeListener(final TextFieldListener changeListener, final JTextField field) { + field.getDocument().addDocumentListener(new DocumentListener() { + + @Override + public void removeUpdate(DocumentEvent de) { + changeListener.update(field); + } + + @Override + public void insertUpdate(DocumentEvent de) { + changeListener.update(field); + } + + @Override + public void changedUpdate(DocumentEvent de) { + changeListener.update(field); + } + }); + } +} \ No newline at end of file diff --git a/src/main/java/eu/omp/irap/vespa/epntapclient/gui/requestpanel/RequestPanelCtrl.java b/src/main/java/eu/omp/irap/vespa/epntapclient/gui/requestpanel/RequestPanelCtrl.java new file mode 100644 index 0000000..05ad91b --- /dev/null +++ b/src/main/java/eu/omp/irap/vespa/epntapclient/gui/requestpanel/RequestPanelCtrl.java @@ -0,0 +1,28 @@ +/* + * This file is a part of EpnTAPClient. + * This program aims to provide EPN-TAP support for software clients, like CASSIS spectrum analyzer. + * See draft specifications: https://voparis-confluence.obspm.fr/pages/viewpage.action?pageId=559861 + * Copyright (C) 2016 Institut de Recherche en Astrophysique et Planétologie. + * + * This program is free software: you can + * redistribute it and/or modify it under the terms of the GNU General Public License as published + * by the Free Software Foundation, either version 3 of the License, or (at your option) any later + * version. This program is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. You should have received a copy of + * the GNU General Public License along with this program. If not, see + * . + */ + +package eu.omp.irap.vespa.epntapclient.gui.requestpanel; + +import java.util.logging.Logger; + +/** + * @author N. Jourdane + */ +public class RequestPanelCtrl { + + /** The logger for the class RequestPanelCtrl. */ + private static final Logger logger = Logger.getLogger(RequestPanelCtrl.class.getName()); +} diff --git a/src/main/java/eu/omp/irap/vespa/epntapclient/gui/requestpanel/RequestPanelView.java b/src/main/java/eu/omp/irap/vespa/epntapclient/gui/requestpanel/RequestPanelView.java new file mode 100644 index 0000000..43f937e --- /dev/null +++ b/src/main/java/eu/omp/irap/vespa/epntapclient/gui/requestpanel/RequestPanelView.java @@ -0,0 +1,149 @@ +/* + * This file is a part of EpnTAPClient. + * This program aims to provide EPN-TAP support for software clients, like CASSIS spectrum analyzer. + * See draft specifications: https://voparis-confluence.obspm.fr/pages/viewpage.action?pageId=559861 + * Copyright (C) 2016 Institut de Recherche en Astrophysique et Planétologie. + * + * This program is free software: you can + * redistribute it and/or modify it under the terms of the GNU General Public License as published + * by the Free Software Foundation, either version 3 of the License, or (at your option) any later + * version. This program is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. You should have received a copy of + * the GNU General Public License along with this program. If not, see + * . + */ + +package eu.omp.irap.vespa.epntapclient.gui.requestpanel; + +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.ArrayList; +import java.util.List; + +import javax.swing.BorderFactory; +import javax.swing.BoxLayout; +import javax.swing.JButton; +import javax.swing.JPanel; +import javax.swing.JTextArea; + +import eu.omp.irap.vespa.epntapclient.gui.mainPanel.ViewListener; +import eu.omp.irap.vespa.epntapclient.gui.requestpanel.ParamField.DataProductTypeField; +import eu.omp.irap.vespa.epntapclient.gui.requestpanel.ParamField.DateRangeField; +import eu.omp.irap.vespa.epntapclient.gui.requestpanel.ParamField.FloatRangeField; +import eu.omp.irap.vespa.epntapclient.gui.requestpanel.ParamField.TargetNameField; + +/** + * The view of the panel where the user builds the query. + * + * @author N. Jourdane + */ +public class RequestPanelView extends JPanel { + + /** The serial version UID. */ + private static final long serialVersionUID = 1L; + + /** The main view of the application. */ + protected ViewListener viewListener; + + /** The text area where the user write the query. */ + protected JTextArea queryArea; + + /** + * The parameters fields for the request. + */ + private List paramFields; + + /** The height of the buttons panel. */ + private static final int BUTTON_PANEL_HEIGHT = 20; + + + /** + * Method constructor + * + * @param mainView The EPN-TAP main view. + */ + public RequestPanelView(ViewListener viewListener) { + this.viewListener = viewListener; + buildRequestPanel(); + } + + private void buildRequestPanel() { + setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); + + this.add(buildParamPanel(), this); + this.add(buildQueryPanel(), this); + this.add(buildButtonPanel(), this); + } + + /** + * Build a JPanel containing graphical elements to build the query user-friendly. + * + * @return The JPanel. + */ + private JPanel buildParamPanel() { + paramFields = new ArrayList<>(); + paramFields.add(new TargetNameField(viewListener, "target_name")); + paramFields.add(new DateRangeField(viewListener, "time_")); + paramFields.add(new FloatRangeField(viewListener, "spectral_range_")); + paramFields.add(new DataProductTypeField(viewListener, "dataproduct_type")); + JPanel paramPanel = new JPanel(); + paramPanel.setLayout(new BoxLayout(paramPanel, BoxLayout.Y_AXIS)); + paramPanel.setBorder(BorderFactory.createTitledBorder("Query parameters")); + + for (ParamField field : paramFields) { + paramPanel.add(field); + } + + return paramPanel; + } + + /** + * Build a JPanel containing a text-area where the query is displayed. + * + * @return The JPanel. + */ + private JPanel buildQueryPanel() { + JPanel queryPanel = new JPanel(); + queryPanel.setBorder(BorderFactory.createTitledBorder("Query for the selected service(s)")); + queryArea = new JTextArea(""); + queryArea.setToolTipText("The query sent to the service(s)."); + queryArea.setLineWrap(true); + queryPanel.setLayout(new BorderLayout()); + queryPanel.add(queryArea, BorderLayout.CENTER); + + return queryPanel; + } + + /** + * Update the query JTextArea. + * + * @param query The string literal to put in the text-area, which will override the old content. + */ + public void updateQueryArea(String query) { + queryArea.setText(query); + } + + /** + * Build a JPanel containing the button(s), particularly the `Send` button. + * + * @return The JPanel . + */ + private JPanel buildButtonPanel() { + JPanel buttonPanel = new JPanel(); + JButton btnSend = new JButton("Send query"); + btnSend.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + viewListener.onSendButtonClicked(queryArea.getText()); + } + }); + buttonPanel.add(btnSend); + buttonPanel.setMaximumSize(new Dimension(1000, RequestPanelView.BUTTON_PANEL_HEIGHT)); + + return buttonPanel; + } +} diff --git a/src/main/java/eu/omp/irap/vespa/epntapclient/gui/resultpanel/ResultPanelCtrl.java b/src/main/java/eu/omp/irap/vespa/epntapclient/gui/resultpanel/ResultPanelCtrl.java new file mode 100644 index 0000000..86c2e0d --- /dev/null +++ b/src/main/java/eu/omp/irap/vespa/epntapclient/gui/resultpanel/ResultPanelCtrl.java @@ -0,0 +1,28 @@ +/* + * This file is a part of EpnTAPClient. + * This program aims to provide EPN-TAP support for software clients, like CASSIS spectrum analyzer. + * See draft specifications: https://voparis-confluence.obspm.fr/pages/viewpage.action?pageId=559861 + * Copyright (C) 2016 Institut de Recherche en Astrophysique et Planétologie. + * + * This program is free software: you can + * redistribute it and/or modify it under the terms of the GNU General Public License as published + * by the Free Software Foundation, either version 3 of the License, or (at your option) any later + * version. This program is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. You should have received a copy of + * the GNU General Public License along with this program. If not, see + * . + */ + +package eu.omp.irap.vespa.epntapclient.gui.resultpanel; + +import java.util.logging.Logger; + +/** + * @author N. Jourdane + */ +public class ResultPanelCtrl { + + /** The logger for the class ResultPanelCtrl. */ + private static final Logger logger = Logger.getLogger(ResultPanelCtrl.class.getName()); +} diff --git a/src/main/java/eu/omp/irap/vespa/epntapclient/gui/resultpanel/ResultPanelView.java b/src/main/java/eu/omp/irap/vespa/epntapclient/gui/resultpanel/ResultPanelView.java new file mode 100644 index 0000000..c9e1ab9 --- /dev/null +++ b/src/main/java/eu/omp/irap/vespa/epntapclient/gui/resultpanel/ResultPanelView.java @@ -0,0 +1,100 @@ +/* + * This file is a part of EpnTAPClient. + * This program aims to provide EPN-TAP support for software clients, like CASSIS spectrum analyzer. + * See draft specifications: https://voparis-confluence.obspm.fr/pages/viewpage.action?pageId=559861 + * Copyright (C) 2016 Institut de Recherche en Astrophysique et Planétologie. + * + * This program is free software: you can + * redistribute it and/or modify it under the terms of the GNU General Public License as published + * by the Free Software Foundation, either version 3 of the License, or (at your option) any later + * version. This program is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. You should have received a copy of + * the GNU General Public License along with this program. If not, see + * . + */ + +package eu.omp.irap.vespa.epntapclient.gui.resultpanel; + +import java.awt.BorderLayout; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +import javax.swing.JButton; +import javax.swing.JFileChooser; +import javax.swing.JLabel; +import javax.swing.JPanel; + +import eu.omp.irap.vespa.epntapclient.gui.mainPanel.ViewListener; +import eu.omp.irap.vespa.votable.view.VOTableView; + +/** + * @author N. Jourdane + */ +public class ResultPanelView extends VOTableView { + + /** The serial version UID. */ + private static final long serialVersionUID = 1L; + + ViewListener viewListener; + + /** A label to display several informations (aka. status bar). */ + private JLabel infoLabel; + + private JButton fileButton; + + + /** + * Method constructor which customize the result panel, but don't build it from scratch since + * VOTableView is already created by ResultController. + * + * @param mainView The main view of the application. + * @param voTableView The generic view of the VOTable panel. + */ + public ResultPanelView(ViewListener viewListener) { + super(); + this.viewListener = viewListener; + buildResultPanel(); + } + + public void buildResultPanel() { + add(buildBottomBar(), BorderLayout.SOUTH); + } + + private JPanel buildBottomBar() { + JPanel statusBar = new JPanel(); + statusBar.setLayout(new BorderLayout()); + statusBar.add(getInfoLabel()); + statusBar.add(getFileButton(), BorderLayout.EAST); + + return statusBar; + } + + public JLabel getInfoLabel() { + return infoLabel == null ? new JLabel() : infoLabel; + } + + /** + * @param infoText The text to display in the status-bar, which will override the old one. + */ + public void setInfoText(String infoText) { + infoLabel.setText(infoText); + } + + public JButton getFileButton() { + if (fileButton == null) { + fileButton = new JButton("Get File"); + fileButton.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + final JFileChooser fc = new JFileChooser(); + fc.showOpenDialog(ResultPanelView.this); + viewListener.onDownloadButtonClicked(fc.getSelectedFile()); + } + }); + } + return fileButton; + } + +} diff --git a/src/main/java/eu/omp/irap/vespa/epntapclient/gui/servicespanel/ServicesPanelCtrl.java b/src/main/java/eu/omp/irap/vespa/epntapclient/gui/servicespanel/ServicesPanelCtrl.java new file mode 100644 index 0000000..586edc8 --- /dev/null +++ b/src/main/java/eu/omp/irap/vespa/epntapclient/gui/servicespanel/ServicesPanelCtrl.java @@ -0,0 +1,28 @@ +/* + * This file is a part of EpnTAPClient. + * This program aims to provide EPN-TAP support for software clients, like CASSIS spectrum analyzer. + * See draft specifications: https://voparis-confluence.obspm.fr/pages/viewpage.action?pageId=559861 + * Copyright (C) 2016 Institut de Recherche en Astrophysique et Planétologie. + * + * This program is free software: you can + * redistribute it and/or modify it under the terms of the GNU General Public License as published + * by the Free Software Foundation, either version 3 of the License, or (at your option) any later + * version. This program is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. You should have received a copy of + * the GNU General Public License along with this program. If not, see + * . + */ + +package eu.omp.irap.vespa.epntapclient.gui.servicespanel; + +import java.util.logging.Logger; + +/** + * @author N. Jourdane + */ +public class ServicesPanelCtrl { + + /** The logger for the class ServicesPanelCtrl. */ + private static final Logger logger = Logger.getLogger(ServicesPanelCtrl.class.getName()); +} diff --git a/src/main/java/eu/omp/irap/vespa/epntapclient/gui/servicespanel/ServicesPanelView.java b/src/main/java/eu/omp/irap/vespa/epntapclient/gui/servicespanel/ServicesPanelView.java new file mode 100644 index 0000000..10b0cdf --- /dev/null +++ b/src/main/java/eu/omp/irap/vespa/epntapclient/gui/servicespanel/ServicesPanelView.java @@ -0,0 +1,130 @@ +/* + * This file is a part of EpnTAPClient. + * This program aims to provide EPN-TAP support for software clients, like CASSIS spectrum analyzer. + * See draft specifications: https://voparis-confluence.obspm.fr/pages/viewpage.action?pageId=559861 + * Copyright (C) 2016 Institut de Recherche en Astrophysique et Planétologie. + * + * This program is free software: you can + * redistribute it and/or modify it under the terms of the GNU General Public License as published + * by the Free Software Foundation, either version 3 of the License, or (at your option) any later + * version. This program is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. You should have received a copy of + * the GNU General Public License along with this program. If not, see + * . + */ + +package eu.omp.irap.vespa.epntapclient.gui.servicespanel; + +import java.awt.BorderLayout; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +import javax.swing.JButton; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JTextField; +import javax.swing.event.ListSelectionEvent; +import javax.swing.event.ListSelectionListener; + +import eu.omp.irap.vespa.epntapclient.gui.mainPanel.ViewListener; +import eu.omp.irap.vespa.votable.view.VOTableView; + +/** + * @author N. Jourdane + */ +public class ServicesPanelView extends VOTableView { + + /** The serial version UID. */ + private static final long serialVersionUID = 1L; + + private ViewListener viewListener; + + private JButton serviceButton; + + private JTextField serviceUrlTextField; + + private JTextField tableNameTextField; + + + /** + * Method constructor which customize the services panel, but don't build it from scratch since + * VOTableView is already created by ServicesController. Add also the JTable listener. + * + * @param mainView The main view of the application. + * @param voTableView The generic view of the VOTable panel. + */ + public ServicesPanelView(final ViewListener viewListener) { + super(); + this.viewListener = viewListener; + buildServicesPanel(); + } + + private void buildServicesPanel() { + getTable().getSelectionModel().addListSelectionListener(new ListSelectionListener() { + + @Override + public void valueChanged(ListSelectionEvent evt) { + viewListener.onServiceSelected(getTable().getSelectedRow()); + } + }); + + add(buildAddServicePanel(), BorderLayout.SOUTH); + } + + private JPanel buildAddServicePanel() { + JPanel addServicePanel = new JPanel(); + addServicePanel.add(new JLabel("Service URL")); + addServicePanel.add(getServiceUrlTextField()); + addServicePanel.add(new JLabel("Table name")); + addServicePanel.add(getTableNameTextField()); + addServicePanel.add(getServiceButton()); + + return addServicePanel; + } + + private JTextField getTableNameTextField() { + return tableNameTextField == null ? new JTextField(10) : tableNameTextField; + } + + private JTextField getServiceUrlTextField() { + return serviceUrlTextField == null ? new JTextField(10) : serviceUrlTextField; + } + + private JButton getServiceButton() { + if (serviceButton == null) { + serviceButton = new JButton("Set service"); + + serviceButton.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + viewListener.onServiceSelected(-1); + } + }); + } + return serviceButton; + } + + /** + * @param row The row index in the JTable element. + * @return The URL of the service corresponding to the row. + */ + public String getServiceURL(int row) { + if (row == -1) { + return serviceUrlTextField.getText(); + } + return (String) getValueAt(5, row); + } + + /** + * @param row The row index in the JTable element. + * @return The table name of the service corresponding to the row. + */ + public String getTableName(int row) { + if (row == -1) { + return tableNameTextField.getText(); + } + return (String) getValueAt(2, row); + } +} -- libgit2 0.21.2