/*
* Freeplane - mind map editor
* Copyright (C) 2008 Dimitry Polivaev
*
* This file author is Dimitry Polivaev
*
* 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 2 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 <http://www.gnu.org/licenses/>.
*/
package org.freeplane.view.swing.map.attribute;
import java.awt.Color;
import java.awt.EventQueue;
import javax.swing.JComponent;
import javax.swing.JScrollPane;
import javax.swing.UIManager;
import javax.swing.event.AncestorEvent;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.ListSelectionListener;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableModel;
import org.freeplane.core.util.LogUtils;
import org.freeplane.features.attribute.AttributeRegistry;
import org.freeplane.features.attribute.AttributeTableLayoutModel;
import org.freeplane.features.attribute.NodeAttributeTableModel;
import org.freeplane.features.map.NodeModel;
import org.freeplane.view.swing.map.MapView;
import org.freeplane.view.swing.map.NodeView;
/**
* This class represents a single Node of a MindMap (in analogy to
* TreeCellRenderer).
*/
public class AttributeView implements ChangeListener, TableModelListener {
private static final Color HEADER_BACKGROUND = UIManager.getColor("TableHeader.background");
static private AttributePopupMenu tablePopupMenu;
private AttributeTable attributeTable;
private JScrollPane attributeViewScrollPane;
private AttributeTableModelDecoratorAdapter currentAttributeTableModel;
private ExtendedAttributeTableModelDecorator extendedAttributeTableModel = null;
final private NodeView nodeView;
final private ReducedAttributeTableModelDecorator reducedAttributeTableModel;
private JTableHeader tableHeader;
private ListSelectionListener tableSelectionListener;
public AttributeView(final NodeView nodeView, final boolean addToNodeView) {
super();
this.nodeView = nodeView;
if(addToNodeView){
reducedAttributeTableModel = new ReducedAttributeTableModelDecorator(this);
currentAttributeTableModel = reducedAttributeTableModel;
}
else{
reducedAttributeTableModel = null;
currentAttributeTableModel = extendedAttributeTableModel = new ExtendedAttributeTableModelDecorator(this);
}
setViewType(getAttributeRegistry().getAttributeViewType());
addListeners();
}
private void addListeners() {
getAttributeRegistry().addChangeListener(this);
addTableListeners();
}
private void addTableListeners() {
if (!getMapView().getModeController().canEdit()) {
return;
}
if (attributeTable != null) {
if (AttributeView.tablePopupMenu == null) {
AttributeView.tablePopupMenu = new AttributePopupMenu();
}
getAttributes().getLayout().addColumnWidthChangeListener(attributeTable);
attributeTable.addMouseListener(AttributeView.tablePopupMenu);
tableHeader.addMouseListener(AttributeView.tablePopupMenu);
if (tableSelectionListener != null) {
attributeTable.getSelectionModel().addListSelectionListener(tableSelectionListener);
attributeTable.getColumnModel().getSelectionModel().addListSelectionListener(tableSelectionListener);
}
}
else {
getAttributes().addTableModelListener(this);
}
}
/*
* (non-Javadoc)
* @seejavax.swing.event.AncestorListener#ancestorMoved(javax.swing.event.
* AncestorEvent)
*/
public void ancestorMoved(final AncestorEvent event) {
}
/**
*/
public boolean areAttributesVisible() {
final String viewType = getViewType();
return viewType != AttributeTableLayoutModel.HIDE_ALL
&& (currentAttributeTableModel.areAttributesVisible() || viewType != getAttributeRegistry()
.getAttributeViewType());
}
AttributeRegistry getAttributeRegistry() {
return AttributeRegistry.getRegistry(getNode().getMap());
}
public NodeAttributeTableModel getAttributes() {
return NodeAttributeTableModel.getModel(getNode());
}
public TableModel getCurrentAttributeTableModel() {
return currentAttributeTableModel;
}
/**
* @return Returns the extendedAttributeTableModel.
*/
private ExtendedAttributeTableModelDecorator getExtendedAttributeTableModel() {
if (extendedAttributeTableModel == null) {
extendedAttributeTableModel = new ExtendedAttributeTableModelDecorator(this);
}
return extendedAttributeTableModel;
}
/**
*/
public MapView getMapView() {
return getNodeView().getMap();
}
/**
*/
NodeModel getNode() {
return getNodeView().getModel();
}
/**
*/
public NodeView getNodeView() {
return nodeView;
}
public String getViewType() {
return currentAttributeTableModel == reducedAttributeTableModel ? getAttributeRegistry().getAttributeViewType()
: AttributeTableLayoutModel.SHOW_ALL;
}
boolean isPopupShown() {
return attributeTable != null && AttributeView.tablePopupMenu != null
&& (AttributeView.tablePopupMenu.getTable() == attributeTable);
}
static private int VIEWER_POSITION = 3;
private void provideAttributeTable() {
if (attributeTable == null) {
getAttributes().removeTableModelListener(this);
attributeTable = new AttributeTable(this);
tableHeader = attributeTable.getTableHeader();
tableHeader.setBackground(AttributeView.HEADER_BACKGROUND);
addTableListeners();
attributeViewScrollPane = new AttributeViewScrollPane(attributeTable);
attributeViewScrollPane.setAlignmentX(AttributeViewScrollPane.LEFT_ALIGNMENT);
if(addToNodeView()){
getNodeView().addContent(attributeViewScrollPane, VIEWER_POSITION);
}
setViewType(getAttributeRegistry().getAttributeViewType());
}
}
boolean addToNodeView() {
return reducedAttributeTableModel != null;
}
private void removeListeners() {
getAttributeRegistry().removeChangeListener(this);
if (!getMapView().getModeController().canEdit()) {
return;
}
if (attributeTable != null) {
getAttributes().getLayout().removeColumnWidthChangeListener(attributeTable);
attributeTable.getParent().remove(attributeTable);
attributeTable.getModel().removeTableModelListener(attributeTable);
attributeTable.removeMouseListener(AttributeView.tablePopupMenu);
tableHeader.removeMouseListener(AttributeView.tablePopupMenu);
AttributeView.tablePopupMenu = null;
}
else {
getAttributes().removeTableModelListener(this);
}
}
private void setViewType(final String viewType) {
JTableHeader currentColumnHeaderView = null;
if (viewType == AttributeTableLayoutModel.SHOW_ALL || ! addToNodeView()) {
currentAttributeTableModel = getExtendedAttributeTableModel();
currentColumnHeaderView = tableHeader;
}
else {
currentAttributeTableModel = reducedAttributeTableModel;
}
if (attributeTable != null) {
attributeTable.setModel(currentAttributeTableModel);
attributeTable.setTableHeader(currentColumnHeaderView);
attributeViewScrollPane.setColumnHeaderView(currentColumnHeaderView);
attributeViewScrollPane.invalidate();
}
}
public void startEditing() {
provideAttributeTable();
if (currentAttributeTableModel == reducedAttributeTableModel) {
getExtendedAttributeTableModel();
setViewType(AttributeTableLayoutModel.SHOW_ALL);
}
EventQueue.invokeLater(new Runnable() {
public void run() {
startEditingTable();
}
});
}
private void startEditingTable() {
attributeTable.requestFocusInWindow();
if (currentAttributeTableModel.getRowCount() == 0) {
attributeTable.insertRow(0);
}
else {
attributeTable.changeSelection(0, 0, false, false);
}
}
public void stateChanged(final ChangeEvent event) {
setViewType(getAttributeRegistry().getAttributeViewType());
if(addToNodeView()){
reducedAttributeTableModel.stateChanged(null);
}
if(attributeTable != null)
attributeTable.revalidate();
}
public void stopEditing() {
if (attributeTable.isEditing()) {
attributeTable.getCellEditor().stopCellEditing();
}
final String registryAttributeViewType = getAttributeRegistry().getAttributeViewType();
if (registryAttributeViewType != getViewType()) {
setViewType(registryAttributeViewType);
}
getNodeView().requestFocusInWindow();
}
public void syncronizeAttributeView() {
if (attributeTable == null && currentAttributeTableModel.areAttributesVisible()) {
provideAttributeTable();
}
}
public void tableChanged(final TableModelEvent e) {
final NodeModel node = getNode();
getMapView().getModeController().getMapController().nodeChanged(node);
}
/**
*/
public void update() {
if (attributeTable != null && attributeTable.isVisible()) {
attributeTable.updateAttributeTable();
}
}
/*
* (non-Javadoc)
* @see
* javax.swing.event.AncestorListener#ancestorRemoved(javax.swing.event.
* AncestorEvent)
*/
public void viewRemoved() {
removeListeners();
if (addToNodeView()) {
reducedAttributeTableModel.viewRemoved(nodeView);
}
if (extendedAttributeTableModel != null) {
extendedAttributeTableModel.viewRemoved(nodeView);
}
if (attributeTable != null) {
attributeTable.viewRemoved(nodeView);
attributeTable = null;
}
}
public JComponent getContainer() {
if(attributeViewScrollPane == null){
provideAttributeTable();
}
return attributeViewScrollPane;
}
public void addRow() {
attributeTable.insertRow(attributeTable.getRowCount());
}
public void setOptimalColumnWidths() {
//DOCEAR: race conditions
try {
attributeTable.setOptimalColumnWidths();
}
catch(Exception e) {
LogUtils.warn("race conditions: setOptimalColumnWidth: " + e.getMessage());
}
}
public AttributeTable getAttributeTable() {
return attributeTable;
}
public void addTableSelectionListener(ListSelectionListener listSelectionListener) {
// we have to cache the listener to enable lazy construction of the AttributeTable
tableSelectionListener = listSelectionListener;
}
}