/******************************************************************************* * Copyright (c) 2014 Open Door Logistics (www.opendoorlogistics.com) * All rights reserved. This program and the accompanying materials * are made available under the terms of the GNU Lesser Public License v3 * which accompanies this distribution, and is available at http://www.gnu.org/licenses/lgpl.txt ******************************************************************************/ package com.opendoorlogistics.studio.panels; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Component; 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.JButton; import javax.swing.JEditorPane; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTable; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; import javax.swing.table.AbstractTableModel; import javax.swing.table.DefaultTableCellRenderer; import com.opendoorlogistics.codefromweb.PackTableColumn; import com.opendoorlogistics.core.formulae.Functions.FmConst; import com.opendoorlogistics.core.formulae.definitions.FunctionDefinition; import com.opendoorlogistics.core.formulae.definitions.FunctionDefinition.FunctionArgument; import com.opendoorlogistics.core.formulae.definitions.FunctionDefinition.FunctionType; import com.opendoorlogistics.core.formulae.definitions.FunctionDefinitionLibrary; import com.opendoorlogistics.core.scripts.execution.adapters.FunctionsBuilder; import com.opendoorlogistics.core.utils.strings.StandardisedStringSet; import com.opendoorlogistics.core.utils.strings.Strings; import com.opendoorlogistics.core.utils.ui.ShowPanel; import com.opendoorlogistics.studio.InitialiseStudio; import com.opendoorlogistics.studio.internalframes.ODLInternalFrame; final public class FunctionsListPanel extends JPanel { private final List<FunctionDefinition> allFunctions; private final List<FunctionDefinition> topLevel ; private final JTable table; private List<FunctionDefinition> current ; private final JButton upButton; private class DescriptionPane extends JEditorPane{ DescriptionPane(){ super("text/html",""); } void update(){ StringBuilder builder = new StringBuilder(); builder.append("<html><head></head><body>"); FunctionDefinition dfn = table.getSelectedRow()!=-1 ? current.get(table.getSelectedRow()):null; if(dfn!=null){ builder.append("<p>"+Strings.convertEnumToDisplayFriendly(dfn.getType().name())+ " <b>" + dfn.getName() + "</b>") ; if(Strings.isEmpty(dfn.getDescription())==false){ builder.append("<br>" + dfn.getDescription()) ; } builder.append("</p>"); if(dfn.nbArgs()>0){ builder.append("<p>"); for(int i = 0 ; i< dfn.nbArgs() ; i++){ if(i>0){ builder.append("<br>"); } FunctionArgument arg = dfn.getArg(i); builder.append("Argument " + Integer.toString(i+1) + " - <b>" + arg.getName() +"</b>"); if(Strings.isEmpty(arg.getDescription())==false){ builder.append(" - " + arg.getDescription()); } } builder.append("</p>"); } } // html+="<body bgcolor='#777779'><hr/><font size=50>This is Html content</font><hr/>"; builder.append("</body></html>"); setText(builder.toString()); } } private List<FunctionDefinition> filterForGroup( String group){ ArrayList<FunctionDefinition> ret = new ArrayList<FunctionDefinition>(); for(FunctionDefinition dfn : allFunctions){ if(Strings.equalsStd(group, dfn.getGroup())){ ret.add(dfn); } } return ret; } public FunctionsListPanel() { setLayout(new BorderLayout()); setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); FunctionDefinitionLibrary library =FunctionsBuilder.getAllDefinitions(); allFunctions = library.toList(); // Get the top level topLevel = new ArrayList<FunctionDefinition>(); StandardisedStringSet groups = new StandardisedStringSet(true); for(FunctionDefinition dfn : allFunctions){ if(dfn.getGroup()!=null){ // first time? String groupname = dfn.getGroup(); if(!groups.contains(groupname)){ groups.add(groupname); FunctionDefinition groupDfn = new FunctionDefinition(groupname); groupDfn.setDescription("Function group"); groupDfn.setGroup(groupname); topLevel.add(groupDfn); } }else{ // top level topLevel.add(dfn); } } current = topLevel; table = new JTable(createTableModel(current)); table.setDefaultRenderer(Object.class, new DefaultTableCellRenderer(){ @Override public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { Component ret = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); FunctionDefinition dfn = row < current.size() ? current.get(row):null; if(dfn == null || dfn.getGroup()==null || current!=topLevel){ ret.setForeground(Color.BLACK ); }else{ ret.setForeground(new Color(0, 0, 100)); } if(dfn!=null && dfn.getType() == FunctionType.CONSTANT){ FmConst fmconst =(FmConst) dfn.getFactory().createFunction(); if(fmconst.value()!=null && fmconst.value() instanceof Color){ ret.setBackground((Color)fmconst.value()); } }else{ ret.setBackground(row%2==0 ? Color.white : new Color(240,240,230)); } return ret; } }); DescriptionPane descriptionPane = new DescriptionPane(); descriptionPane.update(); table.getSelectionModel().addListSelectionListener(new ListSelectionListener() { @Override public void valueChanged(ListSelectionEvent e) { // should we go down? FunctionDefinition dfn = table.getSelectedRow()!=-1 ? current.get(table.getSelectedRow()):null; if(dfn!=null && current == topLevel && dfn.getGroup()!=null){ current = filterForGroup(dfn.getGroup()); table.setModel(createTableModel(current)); packTable(table); upButton.setEnabled(true); } descriptionPane.update(); } }); // create up button upButton = new JButton("Browse to top level"); upButton.setEnabled(false); upButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { if(current!=topLevel){ current = topLevel; table.setModel(createTableModel(current)); packTable(table); descriptionPane.update(); upButton.setEnabled(false); } } }); packTable(table); // have panel just for the description so we can add the button to the south of it JPanel southPanel = new JPanel(new BorderLayout()); southPanel.add(descriptionPane, BorderLayout.CENTER); southPanel.add(upButton, BorderLayout.SOUTH); add(new JLabel("The following functions are available in the calculated fields of a table adapter:"), BorderLayout.NORTH); add(new JScrollPane(table), BorderLayout.CENTER); add(southPanel, BorderLayout.SOUTH); } private void packTable(JTable table) { PackTableColumn.packAll(table, 4); table.getColumnModel().getColumn(0).setMinWidth(60); } @SuppressWarnings("serial") private AbstractTableModel createTableModel(final List<FunctionDefinition> fnclist) { return new AbstractTableModel() { @Override public Object getValueAt(int rowIndex, int columnIndex) { FunctionDefinition dfn = fnclist.get(rowIndex); switch (columnIndex) { case 0: return Strings.convertEnumToDisplayFriendly(dfn.getType().name()); case 1: if(fnclist !=topLevel || dfn.getGroup()==null){ return dfn.getSignature(dfn.getType()!=FunctionType.OPERATOR); } return dfn.getGroup(); case 2: return dfn.getDescription(); } return null; } @Override public int getRowCount() { return fnclist.size(); } @Override public int getColumnCount() { return 3; } @Override public String getColumnName(int column) { switch (column) { case 0: return "Type"; case 1: return "Function"; case 2: return "Description"; } return null; } }; } public static void main(String[] args) { InitialiseStudio.initialise(false); ShowPanel.showPanel(new FunctionsListPanel()); } public static ODLInternalFrame createFrame(){ ODLInternalFrame frame = new ODLInternalFrame("Functions list"); frame.setTitle("Available table adapter functions"); frame.add(new FunctionsListPanel()); return frame; } }