001/*
002 * This file is part of McIDAS-V
003 *
004 * Copyright 2007-2024
005 * Space Science and Engineering Center (SSEC)
006 * University of Wisconsin - Madison
007 * 1225 W. Dayton Street, Madison, WI 53706, USA
008 * https://www.ssec.wisc.edu/mcidas/
009 * 
010 * All Rights Reserved
011 * 
012 * McIDAS-V is built on Unidata's IDV and SSEC's VisAD libraries, and
013 * some McIDAS-V source code is based on IDV and VisAD source code.  
014 * 
015 * McIDAS-V is free software; you can redistribute it and/or modify
016 * it under the terms of the GNU Lesser Public License as published by
017 * the Free Software Foundation; either version 3 of the License, or
018 * (at your option) any later version.
019 * 
020 * McIDAS-V is distributed in the hope that it will be useful,
021 * but WITHOUT ANY WARRANTY; without even the implied warranty of
022 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
023 * GNU Lesser Public License for more details.
024 * 
025 * You should have received a copy of the GNU Lesser Public License
026 * along with this program.  If not, see https://www.gnu.org/licenses/.
027 */
028
029package edu.wisc.ssec.mcidasv.chooser;
030
031import static javax.swing.GroupLayout.Alignment.BASELINE;
032import static javax.swing.GroupLayout.Alignment.LEADING;
033import static javax.swing.GroupLayout.Alignment.TRAILING;
034import static javax.swing.LayoutStyle.ComponentPlacement.RELATED;
035import static javax.swing.LayoutStyle.ComponentPlacement.UNRELATED;
036
037import java.awt.BorderLayout;
038import java.awt.FlowLayout;
039import java.awt.event.ActionEvent;
040import java.awt.event.ActionListener;
041import java.awt.event.KeyEvent;
042import java.awt.event.KeyListener;
043import java.io.File;
044import java.lang.reflect.Method;
045import java.util.ArrayList;
046import java.util.Hashtable;
047import java.util.List;
048import java.util.Map;
049
050import javax.swing.BorderFactory;
051import javax.swing.Box;
052import javax.swing.BoxLayout;
053import javax.swing.GroupLayout;
054import javax.swing.JButton;
055import javax.swing.JComboBox;
056import javax.swing.JComponent;
057import javax.swing.JLabel;
058import javax.swing.JOptionPane;
059import javax.swing.JPanel;
060import javax.swing.JRadioButton;
061import javax.swing.JTextField;
062import javax.swing.plaf.FileChooserUI;
063
064import org.slf4j.Logger;
065import org.slf4j.LoggerFactory;
066import org.w3c.dom.Element;
067
068import ucar.unidata.idv.chooser.IdvChooser;
069import ucar.unidata.idv.chooser.IdvChooserManager;
070import ucar.unidata.util.GuiUtils;
071import ucar.unidata.util.PreferenceList;
072import ucar.unidata.xml.XmlObjectStore;
073
074import edu.wisc.ssec.mcidasv.Constants;
075import edu.wisc.ssec.mcidasv.chooser.adde.AddeChooser;
076import edu.wisc.ssec.mcidasv.util.McVGuiUtils;
077import edu.wisc.ssec.mcidasv.util.McVGuiUtils.Width;
078
079/**
080 * Polar Orbit Track Chooser
081 * Allows user to load TLE files for display in McIDAS-V via three methods:
082 * Remote: ADDE or URL
083 * Local: file
084 *
085 * @author Gail Dengel and Tommy Jasmin
086 */
087
088public class PolarOrbitTrackChooser extends AddeChooser implements Constants {
089
090    private static final long serialVersionUID = 1L;
091
092    private static final Logger logger = LoggerFactory.getLogger(PolarOrbitTrackChooser.class);
093
094    // chooser for local files
095    TLEFileChooser tlefc = null;
096
097    /** Connect button--we need to be able to disable this. */
098    JButton connectButton = McVGuiUtils.makeImageTextButton(ICON_CONNECT_SMALL, "Connect");
099
100    /** Manage button. */
101    JButton manageButton =
102        McVGuiUtils.makeImageButton("/edu/wisc/ssec/mcidasv/resources/icons/toolbar/preferences-system22.png",
103            this, "doManager", null, "Manage servers");
104
105    private JComboBox serverSelector;
106    private JRadioButton localBtn;
107    private JRadioButton addeBtn;
108    private JRadioButton urlBtn;
109    private JLabel descLabel;
110    List<JComponent> addeList = new ArrayList<JComponent>();
111
112    /** Manages the pull down list of URLs. */
113    private PreferenceList prefList;
114
115    /** List of URLs. */
116    private JComboBox box;
117    private JTextField boxEditor;
118
119    private boolean propsOk = false;
120
121    /** Text type. */
122    private static final String TLE_TYPE = "text";
123
124    /** Property ID used to get the list or URLs. */
125    public static final String PREF_URLLIST = "idv.urllist";
126
127    /** Property ID used to determine the last {@literal "source"}. */
128    public static final String PROP_LAST_SOURCE = "mcidasv.chooser.tle.lastsource";
129
130    /** Property value that represents the {@literal "local"} button. */
131    public static final String FILE_SOURCE = "FILE";
132
133    /** Property value that represents the {@literal "ADDE"} button. */
134    public static final String ADDE_SOURCE = "ADDE";
135
136    /** Property value that represents the {@literal "URL"} button. */
137    public static final String URL_SOURCE = "URL";
138
139    // Provide a default URL
140    private static final String DEFAULT_URL = "https://celestrak.com/NORAD/elements/weather.txt";
141
142    /**
143     * Property for the tle server name key.
144     * @see #getServer()
145     */
146    public static String TLE_SERVER_NAME_KEY = "tle_server";
147    public static String URL_NAME_KEY = "url_name";
148    public static String LOCAL_FILE_KEY = "file_object";
149
150    /**
151     * Property for the TLE group name key.
152     * @see #getGroup()
153     */
154    public static String TLE_GROUP_NAME_KEY = "tle_group";
155
156    /** Property for the TLE user ID. */
157    public static String TLE_USER_ID_KEY = "tle_user";
158
159    /** Property for the TLE project number. */
160    public static String TLE_PROJECT_NUMBER_KEY = "tle_proj";
161
162    /** TLE data source identifier. */
163    public static final String TLE_DATA_SOURCE_ID = "TLE";
164
165    /** TLE display type. */
166    public static final String TLE_DISPLAY_TYPE = "tledisplay";
167
168    /** TLE data source type. */
169    public static final String TLE_DATA_TYPE = "TEXT";
170
171    /**
172     * Construct an ADDE image selection widget
173     *
174     * @param mgr The chooser manager
175     * @param root The chooser.xml node
176     */
177
178    public PolarOrbitTrackChooser(IdvChooserManager mgr, Element root) {
179        super(mgr, root);
180        serverSelector = getServerSelector();
181        showServers();
182    }
183    
184    /**
185     * Return the data source ID.
186     *
187     * @return {@link #TLE_DATA_SOURCE_ID}
188     */
189
190    @Override protected String getDataSourceId() {
191        return TLE_DATA_SOURCE_ID;
192    }
193
194    /**
195     * Make the UI for this selector.
196     *
197     * @return The gui
198     */
199
200    @Override public JComponent doMakeContents() {
201        logger.debug("doMakeContents() in...");
202        JPanel outerPanel = new JPanel();
203        JPanel addePanel = new JPanel();
204        addePanel = (JPanel)makeAddePanel();
205
206        // retrieve our last visited directory
207        String path = (String)getIdv().getStateManager().getPreference(IdvChooser.PREF_DEFAULTDIR + getId());
208        String file = (String)getIdv().getStateManager().getPreference(IdvChooser.PREF_DEFAULTDIR + getId() + ".file");
209        tlefc = new TLEFileChooser(this, path, file);
210
211        JButton helpButton = McVGuiUtils.makeImageButton(ICON_HELP, "Show help");
212        helpButton.setActionCommand(GuiUtils.CMD_HELP);
213        helpButton.addActionListener(this);
214
215        JButton refreshButton = McVGuiUtils.makeImageButton(ICON_REFRESH, "Refresh");
216        refreshButton.setActionCommand(GuiUtils.CMD_UPDATE);
217        refreshButton.addActionListener(this);
218
219        McVGuiUtils.setComponentWidth(loadButton, Width.DOUBLE);
220        
221        outerPanel.setLayout(new BorderLayout());
222        JPanel choicePanel = new JPanel(new BorderLayout());
223        JPanel controlPanel = new JPanel(new FlowLayout(FlowLayout.TRAILING));
224        
225        // load the local and remote choices in a Box in center panel
226        JPanel centerPanel = new JPanel();
227        centerPanel.setLayout(new BoxLayout(centerPanel, BoxLayout.PAGE_AXIS));
228        JPanel localPanel = new JPanel(new BorderLayout());
229        
230        // create border like the remote panel (titled) but include the
231        // gap that remote panel creates with various GroupLayout effects
232        localPanel.setBorder(BorderFactory.createCompoundBorder(
233            BorderFactory.createTitledBorder("Local"),
234            BorderFactory.createEmptyBorder(GAP_RELATED, GAP_RELATED, GAP_RELATED, GAP_RELATED)));
235        
236        JPanel remotePanel = new JPanel();
237        remotePanel.setBorder(BorderFactory.createTitledBorder("Remote"));
238        
239        // populate the local access panel
240        localPanel.add(localBtn, BorderLayout.NORTH);
241        localPanel.add(tlefc, BorderLayout.CENTER);
242        
243        // populate the remote access panel
244        remotePanel.add(addePanel);
245        
246        centerPanel.add(localPanel);
247        centerPanel.add(remotePanel);
248        choicePanel.add(centerPanel, BorderLayout.CENTER);
249        
250        outerPanel.add(choicePanel, BorderLayout.CENTER);
251        
252        // populate and add the control panel
253        controlPanel.add(helpButton);
254        controlPanel.add(Box.createHorizontalStrut(5));
255        controlPanel.add(refreshButton);
256        controlPanel.add(Box.createHorizontalStrut(5));
257        controlPanel.add(cancelButton);
258        controlPanel.add(Box.createHorizontalStrut(5));
259        controlPanel.add(loadButton);
260        outerPanel.add(controlPanel, BorderLayout.PAGE_END);
261
262        final XmlObjectStore store = getIdv().getStore();
263        String lastSource = store.get(PROP_LAST_SOURCE, FILE_SOURCE);
264        if (FILE_SOURCE.equals(lastSource)) {
265            localBtn.setSelected(true);
266            for (ActionListener a: localBtn.getActionListeners()) {
267                a.actionPerformed(new ActionEvent(this, ActionEvent.ACTION_PERFORMED, null) {
268                    // nothing to do in here
269                });
270            }
271        } else if (ADDE_SOURCE.equals(lastSource)) {
272            addeBtn.setSelected(true);
273            for (ActionListener a: addeBtn.getActionListeners()) {
274                a.actionPerformed(new ActionEvent(this, ActionEvent.ACTION_PERFORMED, null) {
275                    // nothing to do in here
276                });
277            }
278        } else if (URL_SOURCE.equals(lastSource)) {
279            urlBtn.setSelected(true);
280            for (ActionListener a: urlBtn.getActionListeners()) {
281                a.actionPerformed(new ActionEvent(this, ActionEvent.ACTION_PERFORMED, null) {
282                    // nothing to do in here
283                });
284            }
285        } else {
286            logger.trace("should not be able to arrive here; defaulting to file. (lastSource={})", lastSource);
287            localBtn.setSelected(true);
288        }
289
290        if (localBtn.isSelected()) {
291            File tmp = new File(path + File.separatorChar + file);
292            try {
293                FileChooserUI fcUi = tlefc.getUI();
294                tlefc.setSelectedFile(tmp);
295                Class<? extends FileChooserUI> fcClass = fcUi.getClass();
296                Method setFileName = fcClass.getMethod("setFileName", String.class);
297                setFileName.invoke(fcUi, tmp.getName());
298            } catch (Exception e) {
299                logger.warn("Could not dynamically invoke setFileName", e);
300            }
301        }
302        return outerPanel;
303    }
304    
305    /**
306     * Used by the local file chooser to make sure we are in Local Mode
307     * (the radio button is selected).  Helps to retain cleaner state.
308     *
309     * @return true if Local File Mode radio button is selected
310     */
311
312    public boolean localMode() {
313        if (localBtn.isSelected()) {
314            return true;
315        } else {
316            return false;
317        }
318    }
319
320    private JComponent makeAddePanel() {
321        JPanel outerPanel = new JPanel();
322
323        localBtn = new JRadioButton("File", false);
324        addeBtn = new JRadioButton("ADDE", true);
325        urlBtn = new JRadioButton("URL", false);
326        GuiUtils.buttonGroup(localBtn, addeBtn, urlBtn);
327
328        final XmlObjectStore store = getIdv().getStore();
329
330        localBtn.addActionListener(new ActionListener() {
331            public void actionPerformed(ActionEvent e) {
332                enableLoadFromFile(false);
333                // enable the file chooser
334                if (tlefc != null) {
335                    tlefc.setEnabled(true);
336                    tlefc.handleFileChanged();
337                }
338
339                // disable everything else? Just following pattern below
340                for (int i = 0; i < 5; i++) {
341                    JComponent comp = addeList.get(i);
342                    comp.setEnabled(false);
343                    enableDescriptors(false);
344                }
345                for (int i = 5; i < 7; i++) {
346                    JComponent comp = addeList.get(i);
347                    comp.setEnabled(false);
348                }
349                store.put(PROP_LAST_SOURCE, FILE_SOURCE);
350                store.save();
351            }
352        });
353        
354        // TJJ Nov 2013, I need to figure out what these 
355        // hardcoded component ids are!
356        addeBtn.addActionListener(new ActionListener() {
357            public void actionPerformed(ActionEvent e) {
358                // disable the file chooser
359                if (tlefc != null) {
360                    tlefc.setEnabled(false);
361                }
362                enableLoadFromAdde(true);
363                for (int i = 0; i < 5; i++) {
364                    JComponent comp = addeList.get(i);
365                    comp.setEnabled(true);
366                    enableDescriptors(true);
367                }
368                for (int i = 5; i < 7; i++) {
369                    JComponent comp = addeList.get(i);
370                    comp.setEnabled(false);
371                }
372                store.put(PROP_LAST_SOURCE, ADDE_SOURCE);
373                store.save();
374            }
375        });
376
377        final JLabel urlLabel = new JLabel("URL:");
378        // TJJ Nov 2013, I need to figure out what these 
379        // hardcoded component ids are!
380        urlBtn.addActionListener(new ActionListener() {
381            public void actionPerformed(ActionEvent e) {
382                // disable the file chooser
383                if (tlefc != null) {
384                    tlefc.setEnabled(false);
385                }
386                for (int i = 5; i < 7; i++) {
387                    JComponent comp = addeList.get(i);
388                    comp.setEnabled(true);
389                }
390                enableLoadFromUrl(true);
391                for (int i = 0; i < 5; i++) {
392                    JComponent comp = addeList.get(i);
393                    comp.setEnabled(false);
394                    enableDescriptors(false);
395                }
396                urlLabel.setEnabled(true);
397                box.setEnabled(true);
398                store.put(PROP_LAST_SOURCE, URL_SOURCE);
399                store.save();
400            }
401        });
402        JLabel serverLabel = new JLabel("Server:");
403
404        descLabel = new JLabel("Descriptor:");
405        descLabel.setEnabled(false);
406        descriptorComboBox.setEnabled(false);
407
408        clearOnChange(serverSelector);
409        McVGuiUtils.setComponentWidth(serverSelector, Width.DOUBLE);
410
411        JLabel groupLabel = McVGuiUtils.makeLabelRight("Dataset:");
412
413        groupSelector.setEditable(isGroupEditable());
414        clearOnChange(groupSelector);
415        McVGuiUtils.setComponentWidth(groupSelector, Width.DOUBLE);
416
417        McVGuiUtils.setComponentWidth(connectButton, Width.DOUBLE);
418        connectButton.setActionCommand(CMD_CONNECT);
419        connectButton.addActionListener(this);
420
421        prefList = getPreferenceList(PREF_URLLIST);
422        box = prefList.createComboBox(CMD_LOAD, this);
423        boxEditor = (JTextField) box.getEditor().getEditorComponent();
424        if (boxEditor.getText().isEmpty()) {
425            boxEditor.setText(DEFAULT_URL);
426            box.setSelectedItem(DEFAULT_URL);
427        }
428        boxEditor.addKeyListener(new KeyListener() {
429            public void keyPressed(KeyEvent e) {}
430            public void keyReleased(KeyEvent e) {}
431            public void keyTyped(KeyEvent e) {}
432        });
433        urlLabel.setEnabled(false);
434        box.setEnabled(false);
435
436        GroupLayout layout = new GroupLayout(outerPanel);
437        outerPanel.setLayout(layout);
438        layout.setHorizontalGroup(
439            layout.createParallelGroup(LEADING)
440            .addGroup(TRAILING, layout.createSequentialGroup()
441                .addGroup(layout.createParallelGroup(TRAILING)
442                        .addGroup(LEADING, layout.createSequentialGroup()
443                        .addGroup(layout.createParallelGroup(LEADING)
444                        .addComponent(addeBtn)
445                        .addGroup(layout.createSequentialGroup()
446                            .addComponent(serverLabel)
447                            .addGap(GAP_RELATED)
448                            .addComponent(serverSelector)
449                            .addGap(GAP_RELATED)
450                            .addComponent(manageButton)
451                            .addGap(GAP_RELATED)
452                            .addComponent(groupLabel)
453                            .addGap(GAP_RELATED)
454                            .addComponent(groupSelector)
455                            .addGap(GAP_RELATED)
456                            .addComponent(publicButton)
457                            .addPreferredGap(RELATED, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
458                            .addComponent(connectButton))
459                        .addGroup(layout.createSequentialGroup()
460                            .addComponent(descLabel)
461                            .addGap(GAP_RELATED)
462                            .addComponent(descriptorComboBox))
463                            .addGap(GAP_RELATED)
464                        .addComponent(urlBtn)
465                        .addGroup(layout.createSequentialGroup()
466                            .addComponent(urlLabel)
467                            .addGap(GAP_RELATED)
468                            .addComponent(box))))))
469        );
470
471        layout.setVerticalGroup(
472            layout.createParallelGroup(LEADING)
473            .addGroup(layout.createSequentialGroup()
474                .addComponent(addeBtn)
475                .addGroup(layout.createParallelGroup(BASELINE)
476                    .addComponent(serverLabel)
477                    .addComponent(serverSelector)
478                    .addComponent(manageButton)
479                    .addComponent(groupLabel)
480                    .addComponent(groupSelector)
481                    .addComponent(publicButton)
482                    .addComponent(connectButton))
483                .addPreferredGap(RELATED)
484                .addGroup(layout.createParallelGroup(BASELINE)
485                    .addComponent(descLabel)
486                    .addComponent(descriptorComboBox))
487                .addPreferredGap(UNRELATED)
488                .addComponent(urlBtn)
489                .addGroup(layout.createParallelGroup(BASELINE)
490                    .addComponent(urlLabel)
491                    .addComponent(box)))
492        );
493
494        addeList.add(serverLabel);
495        addeList.add(serverSelector);
496        addeList.add(groupLabel);
497        addeList.add(groupSelector);
498        addeList.add(connectButton);
499        McVGuiUtils.setComponentWidth(descriptorComboBox, Width.DOUBLEDOUBLE);
500        addeList.add(urlLabel);
501        addeList.add(box);
502
503        return outerPanel;
504    }
505
506    public void enableLoadFromFile(boolean val) {
507        loadButton.setEnabled(val);
508        if (tlefc != null && tlefc.getSelectedFile() != null) {
509            setHaveData(val);
510        }
511    }
512
513    public void enableLoadFromAdde(boolean val) {
514        if (val && descriptorComboBox.isEnabled() && getSelectedDescriptor() != null) {
515            loadButton.setEnabled(val);
516        } else {
517            loadButton.setEnabled(val);
518        }
519    }
520
521    public void enableLoadFromUrl(boolean val) {
522        loadButton.setEnabled(val);
523        String url = (String) box.getSelectedItem();
524        if (val && url != null && !url.isEmpty()) {
525            setHaveData(true);
526        } else {
527            setHaveData(val);
528        }
529    }
530
531    public void enableFileLoad(boolean val) {
532        loadButton.setEnabled(val);
533    }
534
535    private void enableDescriptors(boolean val) {
536        if (val) {
537            boolean connected;
538            if (getState() == STATE_CONNECTED) {
539                connected = true;
540            } else {
541                connected = false;
542            }
543            if (connected) {
544                descLabel.setEnabled(true);
545                descriptorComboBox.setEnabled(true);
546            } else {
547                descLabel.setEnabled(false);
548                descriptorComboBox.setEnabled(false);
549            }
550        } else {
551            descLabel.setEnabled(false);
552            descriptorComboBox.setEnabled(false);
553        }
554    }
555
556    @Override protected boolean getGoodToGo() {
557        final XmlObjectStore store = getIdv().getStore();
558        String lastSource = store.get(PROP_LAST_SOURCE, FILE_SOURCE);
559        boolean goodToGo = false;
560        if (URL_SOURCE.equals(lastSource)) {
561            goodToGo = true;
562        }
563        return goodToGo;
564    }
565
566    /**
567     * Update labels, enable widgets, etc.
568     */
569
570    @Override protected void updateStatus() {
571        super.updateStatus();
572        enableWidgets();
573        if ((addeBtn != null) && addeBtn.isSelected()) {
574            enableLoadFromAdde(true);
575        }
576    }
577
578    /**
579     * Get the data type ID.
580     *
581     * @return {@link #TLE_DATA_TYPE}
582     */
583
584    @Override public String getDataType() {
585        return TLE_DATA_TYPE;
586    }
587
588    /**
589     * Get the adde server group type to use.
590     *
591     * @return {@link #TLE_TYPE}
592     */
593
594    @Override protected String getGroupType() {
595        return TLE_TYPE;
596    }
597
598    /**
599     * User said go, we go. 
600     * Create the TLE DataSource
601     */
602
603    @Override public void doLoadInThread() {
604        prefList.saveState(box);
605        String dsName = TLE_DATA_SOURCE_ID;
606        if (tlefc.getSelectedFile() != null) {
607            dsName = tlefc.getSelectedFile().getName();
608        }
609        Hashtable<String, Object> ht = new Hashtable<String, Object>();
610        getDataSourceProperties(ht);
611        if (propsOk) {
612            makeDataSource(dsName, TLE_DATA_SOURCE_ID, ht);
613            saveServerState();
614        }
615    }
616
617    /**
618     * Get the DataSource properties
619     * 
620     * @param ht Hashtable of properties
621     */
622
623    @Override protected void getDataSourceProperties(Hashtable ht) {
624
625        // Local data
626        if (localBtn.isSelected()) {
627            if (tlefc.getSelectedFile() != null) {
628                // local file, set a new key...
629                ht.put(LOCAL_FILE_KEY, tlefc.getSelectedFile());
630                propsOk = true;
631            } else {
632                JOptionPane.showMessageDialog(this, "No file selected.");
633                propsOk = false;
634            }
635        }
636
637        // Remote data, ADDE
638        if (addeBtn.isSelected()) {
639            if (getState() == STATE_CONNECTED) {
640                super.getDataSourceProperties(ht);
641                ht.put(DATASET_NAME_KEY, getDatasetName());
642                String server = getServer();
643                ht.put(TLE_SERVER_NAME_KEY, server);
644                String group = getGroup();
645                ht.put(TLE_GROUP_NAME_KEY, group);
646                Map<String, String> acct = getAccounting(server, group);
647                String user = acct.get("user");
648                String proj = acct.get("proj");
649                ht.put(TLE_USER_ID_KEY, user);
650                ht.put(TLE_PROJECT_NUMBER_KEY, proj);
651                propsOk = true;
652            } else {
653                JOptionPane.showMessageDialog(this, "No ADDE server connection.");
654                propsOk = false;
655            }
656        }
657
658        // Remote or Local, URL
659        if (urlBtn.isSelected()) {
660            String s = (String) box.getSelectedItem();
661            if ((s != null) && !s.isEmpty()) {
662                // TJJ Nov 2018
663                // Until we can update Java 8 distributed with McV, Celestrak cert authority
664                // isn't recognized, so revert to HTTP whenever HTTPS is used
665                s = s.replaceAll("(?i)https", "http");
666                ht.put(URL_NAME_KEY, s);
667                propsOk = true;
668            } else {
669                JOptionPane.showMessageDialog(this, "Please provide a valid URL.");
670                propsOk = false;
671            }
672        }
673    }
674
675    /* (non-Javadoc)
676     * @see edu.wisc.ssec.mcidasv.chooser.adde.AddeChooser#showGroups()
677     */
678
679    @Override
680    public void showGroups() {
681        super.showGroups();
682    }
683
684    private String getDatasetName() {
685        String dsName = (String) descriptorComboBox.getSelectedItem();
686        // strip out description part
687        dsName = dsName.substring(0, dsName.indexOf(" "));
688        return dsName;
689    }
690
691    @Override public void handleConnectFromThread() {
692        super.handleConnectFromThread();
693        enableDescriptors(true);
694    }
695
696    /**
697     * Get the default display type.
698     *
699     * @return {@link #TLE_DISPLAY_TYPE}
700     */
701
702    @Override protected String getDefaultDisplayType() {
703        return TLE_DISPLAY_TYPE;
704    }
705
706}