package com.ramussoft.gui.qualifier.table; import java.awt.BorderLayout; import java.awt.event.ActionEvent; import java.awt.event.KeyEvent; import java.awt.print.PrinterException; import java.io.OutputStream; import java.util.ArrayList; import java.util.Arrays; import java.util.Comparator; import java.util.List; import javax.swing.AbstractAction; import javax.swing.Action; import javax.swing.ImageIcon; import javax.swing.JComponent; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.KeyStroke; import javax.swing.event.TreeSelectionEvent; import javax.swing.event.TreeSelectionListener; import javax.swing.tree.TreePath; import com.ramussoft.common.AccessRules; import com.ramussoft.common.Attribute; import com.ramussoft.common.DeleteStatusList; import com.ramussoft.common.Element; import com.ramussoft.common.Engine; import com.ramussoft.common.Qualifier; import com.ramussoft.common.event.AttributeAdapter; import com.ramussoft.common.event.AttributeEvent; import com.ramussoft.common.event.AttributeListener; import com.ramussoft.common.event.QualifierAdapter; import com.ramussoft.common.event.QualifierEvent; import com.ramussoft.common.event.QualifierListener; import com.ramussoft.common.journal.Journaled; import com.ramussoft.core.attribute.simple.IconPersistent; import com.ramussoft.database.common.Row; import com.ramussoft.database.common.RowSet; import com.ramussoft.gui.StandardFilePlugin; import com.ramussoft.gui.attribute.icon.IconFactory; import com.ramussoft.gui.attribute.icon.IconPreviewPanel; import com.ramussoft.gui.common.AbstractView; import com.ramussoft.gui.common.BaseDialog; import com.ramussoft.gui.common.GUIFramework; import com.ramussoft.gui.common.GlobalResourcesManager; import com.ramussoft.gui.common.TabView; import com.ramussoft.gui.common.UniqueView; import com.ramussoft.gui.common.event.ActionListener; import com.ramussoft.gui.common.prefrence.Options; import com.ramussoft.gui.common.print.HTMLPrintable; import com.ramussoft.gui.qualifier.Commands; import com.ramussoft.gui.qualifier.QualifierSelectComponent; public abstract class AbstractTableView extends AbstractView implements Commands { protected CreateElementAction createElementAction = new CreateElementAction(); protected DeleteElementAction deleteElementAction = new DeleteElementAction(); protected CollapseAction collapseAction = new CollapseAction(); protected ExpandAction expandAction = new ExpandAction(); protected CreateChildElementAction createChildElementAction = new CreateChildElementAction(); protected SetElementIconAction setElementIconAction = new SetElementIconAction(); protected SortByName sortByName = new SortByName(); protected SelectUnconnected selectUnconnected = new SelectUnconnected(); protected JoinElements joinElements = new JoinElements(); private SetElementQualifierAction setElementQualifierAction = new SetElementQualifierAction(); protected Engine engine; protected Qualifier qualifier; protected AccessRules accessRules; private RowSet rowSet; protected RowTreeTable table; protected RowTreeTableComponent component; private JPanel panel = new JPanel(new BorderLayout()); private QualifierListener qualifierListener = new QualifierAdapter() { @Override public void qualifierUpdated(QualifierEvent event) { if (event.getNewQualifier().equals(qualifier)) { AbstractTableView.this .qualifierUpdated(event.getNewQualifier()); IconFactory.clearQualifierIconsBuffer(event.getEngine()); component.repaint(); } } }; private AttributeListener attributeListener = new AttributeAdapter() { @Override public void attributeUpdated(AttributeEvent event) { for (Attribute attribute : rowSet.getAttributes()) { if (attribute.equals(event.getAttribute())) { attribute.setName(event.getNewValue().toString()); fullRefresh(); } } } }; private ActionListener fullRefreshListener = new ActionListener() { @Override public void onAction(com.ramussoft.gui.common.event.ActionEvent event) { fullRefresh(); } }; public void fullRefresh() { Qualifier q = engine.getQualifier(qualifier.getId()); if (q == null) close(); else { qualifier = q; componentRefresh(); } } protected void componentRefresh() { try { component.getRowSet().close(); } catch (Exception e) { e.printStackTrace(); } createComponent(); } public AbstractTableView(GUIFramework framework, Engine engine, AccessRules accessor, Qualifier qualifier) { super(framework); this.engine = engine; this.qualifier = qualifier; this.accessRules = accessor; framework.addActionListener(FULL_REFRESH, fullRefreshListener); engine.addQualifierListener(qualifierListener); engine.addAttributeListener(attributeListener); } public void close() { framework.removeActionListener(FULL_REFRESH, fullRefreshListener); try { engine.removeQualifierListener(qualifierListener); } catch (Exception e) { e.printStackTrace(); } try { engine.removeAttributeListener(attributeListener); } catch (Exception e) { e.printStackTrace(); } component.getModel().close(); } @Override public JComponent createComponent() { createInnerComponent(); return panel; } protected void createInnerComponent() { panel.removeAll(); Attribute[] attributes = getAttributes(); RootCreater rootCreater = getRootCreater(); component = new RowTreeTableComponent(engine, qualifier, accessRules, rootCreater, attributes, framework); rowSet = component.getRowSet(); table = component.getTable(); table.getTreeSelectionModel().addTreeSelectionListener( new TreeSelectionListener() { @Override public void valueChanged(TreeSelectionEvent e) { refreshActions(); } }); refreshActions(); panel.add(component, BorderLayout.CENTER); panel.revalidate(); panel.repaint(); } protected void refreshActions() { boolean canCreateElement = accessRules.canCreateElement(qualifier .getId()); createElementAction.setEnabled(canCreateElement); sortByName .setEnabled(accessRules.canUpdateQualifier(qualifier.getId())); if (table.getTreeSelectionModel().getSelectionPath() == null) { deleteElementAction.setEnabled(false); createChildElementAction.setEnabled(false); joinElements.setEnabled(false); setElementIconAction.setEnabled(false); } else { boolean e = true; boolean i = true; TreePath[] paths = table.getTreeSelectionModel() .getSelectionPaths(); long[] ids = new long[paths.length]; boolean first = true; for (int j = 0; j < ids.length; j++) { Row row = ((TreeTableNode) paths[j].getLastPathComponent()) .getRow(); if (row == null) { e = false; i = false; break; } if (row.getChildCount() > 0) { e = false; break; } ids[j] = row.getElementId(); if (first) { first = false; if (!accessRules.canUpdateAttribute(row.getElement() .getQualifierId(), row.getRowSet().getHAttribute() .getId())) { i = false; } } } if (e) { if (!accessRules.canDeleteElements(ids)) { e = false; } } deleteElementAction.setEnabled(e); setElementQualifierAction.setEnabled(e); joinElements.setEnabled(e); createChildElementAction.setEnabled(canCreateElement); setElementIconAction.setEnabled(i); } } protected Attribute[] getAttributes() { Attribute[] attributes = qualifier.getAttributes().toArray( new Attribute[qualifier.getAttributes().size()]); return attributes; } protected RootCreater getRootCreater() { return new RowRootCreater(); } @Override public Action[] getActions() { return new Action[]{createElementAction, setElementIconAction, sortByName, selectUnconnected, joinElements, setElementQualifierAction, /* * createChildElementAction, */ deleteElementAction, null, expandAction, collapseAction}; } protected class CreateElementAction extends AbstractAction { public CreateElementAction() { this.putValue(ACTION_COMMAND_KEY, "CreateElement"); this.putValue( SMALL_ICON, new ImageIcon(getClass().getResource( "/com/ramussoft/gui/table/add.png"))); this.putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_ADD, KeyEvent.CTRL_MASK)); } /** * */ private static final long serialVersionUID = -5284012805486357491L; @Override public void actionPerformed(ActionEvent e) { if (beforeRowCreate()) { createRow(); } } } public Row createRow() { Row root = rowSet.getRoot(); TreePath path = table.getTreeSelectionModel().getSelectionPath(); if (path != null) { TreeTableNode node = (TreeTableNode) path.getLastPathComponent(); if (node.getRow() != null) { if (node.getRow().getParent() != null) root = node.getRow().getParent(); } } return rowSet.createRow(root); } protected class CreateChildElementAction extends AbstractAction { public CreateChildElementAction() { this.putValue(ACTION_COMMAND_KEY, "CreateChildElement"); this.putValue( SMALL_ICON, new ImageIcon(getClass().getResource( "/com/ramussoft/gui/table/add-child.png"))); } /** * */ private static final long serialVersionUID = -5284012805486357491L; @Override public void actionPerformed(ActionEvent e) { Row root = rowSet.getRoot(); TreePath path = table.getTreeSelectionModel().getSelectionPath(); if (path != null) { TreeTableNode node = (TreeTableNode) path .getLastPathComponent(); if (node.getRow() != null) { root = node.getRow(); } } rowSet.createRow(root); } } protected class SetElementIconAction extends AbstractAction { /** * */ private static final long serialVersionUID = -8380866817844775216L; public SetElementIconAction() { this.putValue(ACTION_COMMAND_KEY, "SetElementIcon"); this.putValue( SMALL_ICON, new ImageIcon(getClass().getResource( "/com/ramussoft/gui/set-icon.png"))); this.putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_I, KeyEvent.CTRL_MASK)); } @Override public void actionPerformed(ActionEvent e) { TreePath[] paths = table.getTreeSelectionModel() .getSelectionPaths(); if (paths.length == 0) { System.err .println("Trying to set element icon, but no elements are selected"); return; } IconPersistent p = null; IconPreviewPanel panel = new IconPreviewPanel( IconFactory.getIconsDirectory()); p = panel.select(framework.getMainFrame()); if (p != null) { component.getRowSet().startUserTransaction(); for (TreePath path : paths) { Row row = ((TreeTableNode) path.getLastPathComponent()) .getRow(); if (row != null) { IconFactory.setIcon(engine, p, row); } } component.getRowSet().commitUserTransaction(); } } } ; /** * @return Selected (not chacked row) */ public Row getSelectedRow() { TreeTableNode node = table.getSelectedNode(); if (node == null) return null; return node.getRow(); } protected class SortByName extends AbstractAction { /** * */ private static final long serialVersionUID = -8699279349736829371L; public SortByName() { this.putValue(ACTION_COMMAND_KEY, "Action.SortByName"); this.putValue( SMALL_ICON, new ImageIcon(getClass().getResource( "/com/ramussoft/gui/table/sort-incr.png"))); } @Override public void actionPerformed(ActionEvent e) { component.getRowSet().startUserTransaction(); component.getRowSet().sortByName(); component.getRowSet().commitUserTransaction(); fullRefresh(); } } ; protected class SelectUnconnected extends AbstractAction { /** * */ private static final long serialVersionUID = -1173048315785554892L; public SelectUnconnected() { this.putValue(ACTION_COMMAND_KEY, "Action.SelectUnconnected"); this.putValue( SMALL_ICON, new ImageIcon(getClass().getResource( "/com/ramussoft/gui/table/select-unconnected.png"))); } @Override public void actionPerformed(ActionEvent e) { table.expandAll(); table.clearSelection(); for (int i = 0; i < table.getRowCount(); i++) { TreePath path = table.getPathForRow(i); Row row = ((TreeTableNode) path.getLastPathComponent()) .getRow(); long[] elementIds = new long[1]; if ((row != null) && (row.getChildCount() == 0)) { elementIds[0] = row.getElementId(); if ((accessRules.canDeleteElements(elementIds)) && (accessRules.getElementsDeleteStatusList( elementIds).size() == 0)) table.getTreeSelectionModel().addSelectionPath(path); } } table.requestFocus(); } } ; protected class JoinElements extends AbstractAction { /** * */ private static final long serialVersionUID = 7511253862730487588L; public JoinElements() { putValue(ACTION_COMMAND_KEY, "Action.JoinElements"); this.putValue( SMALL_ICON, new ImageIcon(getClass().getResource( "/com/ramussoft/gui/table/join-elements.png"))); } @Override public void actionPerformed(ActionEvent e) { TreePath[] paths = table.getTreeSelectionModel() .getSelectionPaths(); List<Row> list = SelectableTableView .showRowSelectDialog(component, framework, engine, accessRules, qualifier, SelectType.RADIO); if ((list != null) && (list.size() == 1)) { Element element = list.get(0).getElement(); ArrayList<Element> elements = new ArrayList<Element>( paths.length); for (TreePath path : paths) { Row row = ((TreeTableNode) path.getLastPathComponent()) .getRow(); if (row != null) if (!element.equals(row.getElement())) { elements.add(row.getElement()); } } component.getRowSet().startUserTransaction(); engine.replaceElements( elements.toArray(new Element[elements.size()]), element); component.getRowSet().commitUserTransaction(); } } } ; protected class DeleteElementAction extends AbstractAction { public DeleteElementAction() { this.putValue(ACTION_COMMAND_KEY, "DeleteElement"); this.putValue( SMALL_ICON, new ImageIcon(getClass().getResource( "/com/ramussoft/gui/table/delete.png"))); // this.putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke( // KeyEvent.VK_DELETE, 0)); } /** * */ private static final long serialVersionUID = -5284012805486357491L; @Override public void actionPerformed(ActionEvent e) { TreePath[] paths = table.getTreeSelectionModel() .getSelectionPaths(); if (paths.length == 0) { System.err .println("Trying to delete element, but no elements are selected"); return; } long[] elementIds = new long[paths.length]; for (int i = 0; i < elementIds.length; i++) { Row row = ((TreeTableNode) paths[i].getLastPathComponent()) .getRow(); if (row == null) { System.err .println("Trying to delete node, which conatain no row"); return; } elementIds[i] = row.getElementId(); } DeleteStatusList list = accessRules .getElementsDeleteStatusList(elementIds); if (list.size() > 0) { if (!StatusMessageFormat.deleteElements(list, null, framework)) return; } else { if (JOptionPane .showConfirmDialog( component, GlobalResourcesManager .getString("DeleteActiveElementsDialog.Warning"), GlobalResourcesManager .getString("ConfirmMessage.Title"), JOptionPane.YES_NO_OPTION) != JOptionPane.YES_OPTION) return; } component.getRowSet().startUserTransaction(); for (long elementId : elementIds) engine.deleteElement(elementId); component.getRowSet().commitUserTransaction(); } } protected class CollapseAction extends AbstractAction { /** * */ private static final long serialVersionUID = -2888510142746145088L; public CollapseAction() { this.putValue(ACTION_COMMAND_KEY, "CollapseAll"); this.putValue( SMALL_ICON, new ImageIcon(getClass().getResource( "/com/ramussoft/gui/table/collapse.png"))); this.putValue( ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_C, KeyEvent.CTRL_MASK | KeyEvent.SHIFT_MASK)); } @Override public void actionPerformed(ActionEvent e) { table.collapseAll(); } } protected class ExpandAction extends AbstractAction { /** * */ private static final long serialVersionUID = -1143583852789406865L; public ExpandAction() { this.putValue(ACTION_COMMAND_KEY, "ExpandAll"); this.putValue( SMALL_ICON, new ImageIcon(getClass().getResource( "/com/ramussoft/gui/table/expand.png"))); this.putValue( ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_E, KeyEvent.CTRL_MASK | KeyEvent.SHIFT_MASK)); } @Override public void actionPerformed(ActionEvent e) { table.expandAll(); } } public Qualifier getQualifier() { return qualifier; } protected boolean beforeRowCreate() { return true; } public RowTreeTableComponent getComponent() { return component; } private Attribute[] getSortedAttributes(List<Attribute> list) { Attribute[] res = list.toArray(new Attribute[list.size()]); Arrays.sort(res, new Comparator<Attribute>() { @Override public int compare(Attribute o1, Attribute o2) { if (o1.getId() < o2.getId()) return -1; if (o1.getId() > o2.getId()) return 1; return 0; } }); return res; } public void qualifierUpdated(Qualifier newQualifier) { Attribute[] oldAs = getSortedAttributes(qualifier.getAttributes()); Attribute[] newAs = getSortedAttributes(newQualifier.getAttributes()); if ((!Arrays.equals(oldAs, newAs)) || (qualifier.getAttributeForName() != newQualifier .getAttributeForName())) { qualifier = newQualifier; fullRefresh(); } } protected class SetElementQualifierAction extends AbstractAction { /** * */ private static final long serialVersionUID = -5168999627602603222L; public SetElementQualifierAction() { putValue(ACTION_COMMAND_KEY, "Action.SetElementQualifier"); this.putValue( SMALL_ICON, new ImageIcon( getClass() .getResource( "/com/ramussoft/gui/table/set-element-qualifier.png"))); setEnabled(false); } @Override public void actionPerformed(ActionEvent e) { final QualifierSelectComponent component = new QualifierSelectComponent( engine, true, false); BaseDialog bd = new BaseDialog(framework.getMainFrame(), true) { /** * */ private static final long serialVersionUID = -8463457256203708106L; @Override protected void onOk() { List<Qualifier> list = component.getSelected(); if (list.size() <= 0) { JOptionPane.showMessageDialog(framework.getMainFrame(), GlobalResourcesManager.getString("CheckQualifierFirst")); return; } if (!list.get(0).equals(getQualifier())) if (list.size() > 0) { TreePath[] paths = table.getTreeSelectionModel() .getSelectionPaths(); if (paths.length == 0) { System.err .println("Trying to set element's qualifier, but no elements are selected"); return; } List<Row> rows = new ArrayList<Row>(paths.length); for (int i = 0; i < paths.length; i++) { Row row = ((TreeTableNode) paths[i] .getLastPathComponent()).getRow(); if (row != null) { rows.add(row); } } ((Journaled) engine).startUserTransaction(); for (Row row : rows) { rowSet.setRowQualifier(row, list.get(0)); } ((Journaled) engine).commitUserTransaction(); } super.onOk(); } }; bd.setMainPane(component); bd.setTitle(GlobalResourcesManager .getString("Action.SetElementQualifier")); bd.pack(); bd.setLocationRelativeTo(null); Options.loadOptions(bd); bd.setVisible(true); Options.saveOptions(bd); } } ; @Override public String[] getGlobalActions() { return new String[]{StandardFilePlugin.ACTION_PRINT, StandardFilePlugin.ACTION_PAGE_SETUP, StandardFilePlugin.ACTION_PRINT_PREVIEW}; } @Override public void onAction(com.ramussoft.gui.common.event.ActionEvent event) { if (event.getKey().equals(StandardFilePlugin.ACTION_PAGE_SETUP)) new HTMLPrintable().pageSetup(framework); else if (event.getKey().equals(StandardFilePlugin.ACTION_PRINT)) { HTMLPrintable printable = new HTMLPrintable(); init(printable); try { printable.print(framework); } catch (PrinterException e) { JOptionPane.showMessageDialog(framework.getMainFrame(), e.getLocalizedMessage()); e.printStackTrace(); } } else if (event.getKey().equals( StandardFilePlugin.ACTION_PRINT_PREVIEW)) { HTMLPrintable printable = new HTMLPrintable(); init(printable); framework.printPreview(printable); } } private void init(HTMLPrintable printable) { try { String title; if (this instanceof UniqueView) { title = getString(((UniqueView) this).getId()); } else if (this instanceof TabView) { title = ((TabView) this).getTitle(); } else { title = getQualifier().getName(); } OutputStream os = printable.getOutputStream(); String top = "<html>\n<head>\n<title>" + title + "</title>\n</head>\n\n<body>\n"; os.write(top.getBytes()); os.write(table.getBodyText(title).getBytes()); os.write("</body>\n</html>\n".getBytes()); os.close(); } catch (Exception e) { e.printStackTrace(); } } public Action getExpandAction() { return expandAction; } public Action getCollapseAction() { return collapseAction; } public Action getSortByNameAction() { return sortByName; } public Action getCreateElementAction() { return createElementAction; } public DeleteElementAction getDeleteElementAction() { return deleteElementAction; } }