/*******************************************************************************
* ALMA - Atacama Large Millimeter Array
* Copyright (c) COSYLAB - Control System Laboratory, 2011
* (in the framework of the ALMA collaboration).
* All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*******************************************************************************/
package com.cosylab.cdb.browser;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.table.*;
/**
* This class is responsible for initialising and placing all Components inside the GUI.
*
* @author Hernan Raffi
* @version 2.0
*
*/
public class Browser extends JFrame implements ActionListener
{
/**
* The instance of the Browser class used during execution.
*/
private static Browser instance = null;
/**
* The IOR (Input Output reference) string which represents the
* DAL access parameters.
*/
private static String strIOR = null;
/**
* The message text area (Bottom of the GUI)
*/
private JTextArea messageTextArea;
/**
* JSlit Pane used to separete the CDB tree and the tabbed Pane window.
*/
private JSplitPane splitPane;
/**
* The location where the separation occurs.
*/
private final int dividerLocation = 240;
/**
* Text Field that shows the selected tree path. Located on top of the Browsers GUI.
*/
private JTextField currentLocation;
/**
* Button used to Save Changes to an XML record (located on top of the tabbed pane).
*/
private final JButton saveChanges = new JButton(" Save Changes to XML record ");
/**
* Button used to reset an XML record (located on top of the tabbed pane).
*/
private final JButton resetData = new JButton(" Reset Data ");
/**
* Button used to refresh the CDB tree (located on top of the CDB tree).
*/
private JButton refreshTree = new JButton(" Refrest CDB Tree ");
private final String titleCol1 = "ATTRIBUTE NAME";
private final String titleCol2 = "ATTRIBUTE VALUE";
/**
* Constructor of the Browser class.
*/
Browser(){
super("Configuration Database Browser");
if(buttonsEnabled()){
setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
}
addWindowListener(new WindowAdapter(){
public void windowClosing(WindowEvent e){
if( buttonsEnabled()){
String msg1 = "Warning: Node has been modified.";
String msg2 = "Please save or reset changes before closing the Browser.";
CDBDialog dialog1 = new CDBDialog(Browser.getInstance(), msg1,msg2);
}
else{
System.exit(0);
}
}
public void windowClosed(WindowEvent ev) {
return;
}
});
}
/**
* Only one instance of the Browser class can be created at any time
* during program execution.
* @return always the same instance of the Browser class.
*/
public static Browser getInstance(){
if(instance == null){
instance = new Browser();
}
return instance;
}
/**
* Sets up the Graphical User Interface (GUI) of the Browser.
* The GUI is divided into three sections: left side, where the CDB Tree will be visible;
* right side for the output (tabbed pane) and the bottom for the message text area.
* CDB tree (left) and the tabbed panes (right) are separeted by a JSplitPane object.
* On top of the GUI there is a location bar (shows the current selected path in th tree).
*/
public void createGUI(){
// 'top panel' that will contain all other panels and components.
JPanel topPanel = new JPanel(new BorderLayout());
topPanel.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
this.getContentPane().add(topPanel, BorderLayout.CENTER);
// Create a message text area (bottom of the GUI).
messageTextArea = new JTextArea(10,20);
messageTextArea.setEditable(false);
topPanel.add(new JScrollPane(messageTextArea), BorderLayout.SOUTH);
// JSplitPane to divide the CDBTree with the tabbedPane.
splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, true);
// Set up right component (area for the tabbed pane).
saveChanges.setEnabled(false);
resetData.setEnabled(false);
JTextArea outputArea = new JTextArea();
outputArea.setBackground(Color.LIGHT_GRAY);
outputArea.setEditable(false);
setRightComp(outputArea, false);
// Set up left Component (CDB Tree)
setLeftComp();
// add splitPane to top Panel
topPanel.add(splitPane, BorderLayout.CENTER);
// The location bar and the 'refresh button'
JPanel north = new JPanel(new GridLayout(1,2));
north.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
refreshTree.addActionListener(this);
JLabel locationLabel = new JLabel("CURRENT LOCATION: ", JLabel.RIGHT);
currentLocation = new JTextField(40);
currentLocation.setBackground(Color.WHITE);
currentLocation.setEditable(false);
JPanel n = new JPanel(new GridLayout(1,2));
n.add(refreshTree);
n.add(locationLabel);
north.add(n);
north.add(currentLocation);
topPanel.add(north, BorderLayout.NORTH);
}
/**
* Create the tabbed pane with two tabs (Table View and XML View).
*
* @param nodeHashMap
* data of the entry (null is possible).
* @param xml
* XML record of the node (null is possible).
*/
public void createTabbedPane(LinkedHashMap attributes, String XML) {
JTabbedPane newTabbedPane = new JTabbedPane();
// create table tab
// if(attributes != null){
String titles[] = { titleCol1, titleCol2 };
Object data[][] = CDBLogic.getData(attributes);
if (data != null) {
JTable newTable = new CDBTable(data, titles);
TableModel newTableModel = new CDBTableModel(data, titles);
newTable.setModel(newTableModel);
newTable.setBackground(Color.LIGHT_GRAY);
newTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
CDBLogic.tableModels.put(CDBLogic.getKey(), (CDBTableModel) newTableModel);
CDBLogic.tables.put(CDBLogic.getKey(), (CDBTable) newTable);
newTabbedPane.addTab(" Table View ", new JScrollPane(newTable));
CDBLogic.selectedTable = (CDBTable) newTable;
CDBLogic.selectedTableModel = (CDBTableModel) newTableModel;
// }
} else {
CDBLogic.selectedTable = null;
CDBLogic.selectedTableModel = null;
CDBLogic.tableModels.put(CDBLogic.getKey(), null);
CDBLogic.tables.put(CDBLogic.getKey(), null);
newTabbedPane.addTab(" Table View ", null);
newTabbedPane.setEnabledAt(CDBLogic.tableIndex, false);
}
// create XML tab
if (XML != null) {
JTextArea XMLArea = new JTextArea(XML);
CDBLogic.addListener(XMLArea);
XMLArea.setEditable(true);
XMLArea.setBackground(Color.LIGHT_GRAY);
XMLArea.setLineWrap(true);
XMLArea.setWrapStyleWord(true);
CDBLogic.xmls.put(CDBLogic.getKey(), (JTextArea) XMLArea);
newTabbedPane.addTab(" XML View ", (JTextArea) XMLArea);
if (!newTabbedPane.isEnabledAt(CDBLogic.tableIndex)) {
newTabbedPane.setSelectedIndex(CDBLogic.xmlIndex);
}
CDBLogic.selectedXMLArea = (JTextArea) XMLArea;
} else {
CDBLogic.xmls.put(CDBLogic.getKey(), null);
newTabbedPane.addTab(" XML View ", null);
newTabbedPane.setEnabledAt(CDBLogic.xmlIndex, false);
CDBLogic.selectedXMLArea = null;
}
CDBLogic.selectedTabbedPane = (JTabbedPane) newTabbedPane;
CDBLogic.tabbedPanes.put(CDBLogic.getKey(), (JTabbedPane) newTabbedPane);
setRightComp(newTabbedPane, true);
}
/**
* Sets the right component either a tabbed Pane or an empty text area.
* @param component the component that is added to the right side of the GUI.
* @param showButtons true only if component is instance of JTabbedPane.
*/
public void setRightComp(JComponent component, boolean showButtons){
JPanel panel = new JPanel(new BorderLayout());
panel.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
panel.add(component, BorderLayout.CENTER);
if(showButtons){
JPanel buttonPanel = new JPanel(new GridLayout(1,2));
saveChanges.setEnabled(false);
resetData.setEnabled(false);
saveChanges.addActionListener(this);
resetData.addActionListener(this);
buttonPanel.add(saveChanges);
buttonPanel.add(resetData);
panel.add(buttonPanel, BorderLayout.NORTH);
}
splitPane.setRightComponent(new JScrollPane(panel));
splitPane.setDividerLocation(dividerLocation);
}
/**
* Sets the cdb Tree in the left side of the GUI.
*/
public void setLeftComp(){
JTree cdbTree = CDBLogic.setUpCDBTree(strIOR);
splitPane.setLeftComponent(new JScrollPane(cdbTree));
splitPane.setDividerLocation(dividerLocation);
}
/**
* Adds some text to the message area at the buttom of the GUI.
* @param message the text to be added.
* @param newLine dispalay message in the next (new) line.
*/
public void display(String message, boolean newLine){
if(newLine){
messageTextArea.append("\n" + message);
}
else
messageTextArea.append(" " + message);
}
/**
* Updates the location text field.
* @param newLoc the new selected location.
*/
public void setPath(String newLoc){
currentLocation.setText(" " + newLoc);
}
/**
* Returns the path of the current selected tree node.
* @return String current selected tree path.
*/
public String getPath(){
return currentLocation.getText();
}
/**
* Enables/Disables both buttons: saveChanges & resetData
* @param enable enable or disable both buttons.
*/
public void enableButtons(boolean enable){
if(enable){
saveChanges.setEnabled(true);
resetData.setEnabled(true);
}
else{
saveChanges.setEnabled(false);
resetData.setEnabled(false);
}
}
/**
* Checks if the buttons (on top pf the tabbed pane) are enabled.
* @reurn true if buttons are enabled; false otherwise.
*/
public boolean buttonsEnabled(){
if(saveChanges.isEnabled() && resetData.isEnabled()){
return true;
}else
return false;
}
/**
* Invoked when an action occurs (User presses the button).
* @param e A semantic event which indicates that a component-defined action occured.
*/
public void actionPerformed(ActionEvent e) {
if(e.getSource() == refreshTree){
if(buttonsEnabled()){
String msg1 = "WARNING: Not able to refresh CDB Tree.";
String msg2 = "Please save or reset changes made to node "+ getPath() +".";
CDBDialog d = new CDBDialog(this,msg1,msg2);
return;
}
messageTextArea.setText("\nRefreshing CDB Tree... ");
CDBLogic.clearHashMaps();
setPath("");
JTextArea empty = new JTextArea();
empty.setBackground(Color.LIGHT_GRAY);
empty.setEditable(false);
setRightComp(empty, false);
setLeftComp();
display("done.", false);
}
if(e.getSource() == resetData){
if(CDBLogic.isXMLTabSelected()){ //XML string has been edited
CDBLogic.resetXMLString();
}
else{ // Table has been edited
CDBLogic.selectedTable.editCellAt(0,0);
CDBLogic.resetTable();
}
}
if(e.getSource() == saveChanges){
if(CDBLogic.isXMLTabSelected()){
CDBLogic.saveXMLString(false);
}
else{
CDBLogic.selectedTable.editCellAt(0,0);
CDBLogic.saveTable();
}
}
}
/**
* The main method.
* @param args the IOR (Input Output reference) which represents the DAL access parameters.
*/
public static void main(String []args){
for(int i = 0; i < args.length; i ++){
if(args[i].equals("-d")){
if(i < args.length -1){
strIOR = args[++i];
}
}
}
instance = getInstance();
instance.setJMenuBar(new CDBMenu());
instance.createGUI();
instance.setBounds(50,50,850,650);
instance.setVisible(true);
}
}