Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.smallmind.swing.catalog.Catalog Maven / Gradle / Ivy
/*
* Copyright (c) 2007 through 2024 David Berkman
*
* This file is part of the SmallMind Code Project.
*
* The SmallMind Code Project is free software, you can redistribute
* it and/or modify it under either, at your discretion...
*
* 1) The terms of GNU Affero General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at
* your option) any later version.
*
* ...or...
*
* 2) The terms of the Apache License, Version 2.0.
*
* The SmallMind Code Project 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 or Apache License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* and the Apache License along with the SmallMind Code Project. If not, see
* or .
*
* Additional permission under the GNU Affero GPL version 3 section 7
* ------------------------------------------------------------------
* If you modify this Program, or any covered work, by linking or
* combining it with other code, such other code is not for that reason
* alone subject to any of the requirements of the GNU Affero GPL
* version 3.
*/
package org.smallmind.swing.catalog;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.awt.event.HierarchyBoundsListener;
import java.awt.event.HierarchyEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.util.ArrayList;
import java.util.LinkedList;
import javax.swing.JLayeredPane;
import javax.swing.JPanel;
import javax.swing.JViewport;
import javax.swing.Scrollable;
import javax.swing.SwingUtilities;
import org.smallmind.swing.MultiListSelectionEvent;
import org.smallmind.swing.MultiListSelectionListener;
import org.smallmind.swing.layout.ListLayout;
public class Catalog, D> extends JLayeredPane implements Scrollable, CatalogDataListener, HierarchyBoundsListener, ComponentListener, MouseListener, MouseMotionListener {
private final JPanel glassPanel;
private final JPanel catalogPanel;
private final CatalogModel model;
private final CatalogMultiListDataProvider multiListDataProvider;
private MultiListSelectionModel selectionModel;
private CatalogCellRenderer renderer;
private CatalogScrollModel scrollModel;
private Component lastTargetedComponent = null;
public Catalog (T key, CatalogModel model) {
super();
this.model = model;
setFocusable(true);
glassPanel = new JPanel();
glassPanel.setOpaque(false);
glassPanel.setSize(getSize());
catalogPanel = new JPanel(new ListLayout(0));
catalogPanel.setOpaque(true);
catalogPanel.setSize(getSize());
add(catalogPanel, 10);
add(glassPanel, 11);
multiListDataProvider = new CatalogMultiListDataProvider(key, this);
setSelectionModel(new DefaultMultiListSelectionModel());
model.addCatalogDataListener(this);
setCellRenderer(new DefaultCatalogCellRenderer());
setScrollModel(new DefaultCatalogScrollModel(this));
addHierarchyBoundsListener(this);
addComponentListener(this);
glassPanel.addMouseListener(this);
glassPanel.addMouseMotionListener(this);
}
public CatalogModel getModel () {
return model;
}
public synchronized CatalogCellRenderer getCellRenderer () {
return renderer;
}
public synchronized void setCellRenderer (CatalogCellRenderer renderer) {
this.renderer = renderer;
catalogPanel.removeAll();
for (int count = 0; count < model.getSize(); count++) {
catalogPanel.add(getRenderedComponent(count), count);
}
catalogPanel.invalidate();
}
public synchronized CatalogScrollModel getScrollModel () {
return scrollModel;
}
public synchronized void setScrollModel (CatalogScrollModel scrollModel) {
this.scrollModel = scrollModel;
}
public synchronized MultiListSelectionModel getSelectionModel () {
return selectionModel;
}
public synchronized void setSelectionModel (MultiListSelectionModel selectionModel) {
if (this.selectionModel != null) {
this.selectionModel.removeMultiListDataProvider(multiListDataProvider);
this.selectionModel.removeMultiListSelectionListener(multiListDataProvider);
}
if (selectionModel != null) {
this.selectionModel = selectionModel;
selectionModel.addMultiListDataProvider(multiListDataProvider);
selectionModel.addMultiListSelectionListener(multiListDataProvider);
reRenderAllComponents();
}
}
public synchronized MultiListSelectionModel.SelctionMode getSelectionMode () {
return selectionModel.getSelectionMode();
}
public synchronized void setSelectionMode (MultiListSelectionModel.SelctionMode selectionMode) {
selectionModel.setSelectionMode(selectionMode);
}
public synchronized void addMultiListSelectionListener (MultiListSelectionListener listener) {
selectionModel.addMultiListSelectionListener(listener);
}
public synchronized void removeMultiListSelectionListener (MultiListSelectionListener listener) {
selectionModel.removeMultiListSelectionListener(listener);
}
public synchronized void clearSelection () {
selectionModel.clearSelection();
}
public synchronized void addSelectionInterval (int startIndex, int endIndex) {
selectionModel.addSelectionInterval(new MultiListSelection(multiListDataProvider.getKey(), startIndex), new MultiListSelection(multiListDataProvider.getKey(), startIndex));
}
public synchronized MultiListSelection getAnchorSelectionIndex () {
return selectionModel.getAnchorSelection();
}
public synchronized MultiListSelection getLeadSelectionIndex () {
return selectionModel.getLeadSelection();
}
public synchronized MultiListSelection getMinSelectionIndex () {
return selectionModel.getMinSelection();
}
public synchronized MultiListSelection getMaxSelectionIndex () {
return selectionModel.getMaxSelection();
}
public synchronized int getSelectedIndex () {
return selectionModel.getSelectedIndex(multiListDataProvider.getKey());
}
public synchronized void setSelectedIndex (int index) {
selectionModel.setSelectionInterval(new MultiListSelection(multiListDataProvider.getKey(), index), new MultiListSelection(multiListDataProvider.getKey(), index));
}
public synchronized int[] getSelectedIndices () {
ArrayList indexList;
int[] indices;
indexList = new ArrayList();
for (int count = 0; count < catalogPanel.getComponentCount(); count++) {
if (selectionModel.isSelected(new MultiListSelection(multiListDataProvider.getKey(), count))) {
indexList.add(count);
}
}
indices = new int[indexList.size()];
for (int count = 0; count < indexList.size(); count++) {
indices[count] = indexList.get(count);
}
return indices;
}
public synchronized void setSelectedIndices (int[] indices) {
selectionModel.clearSelection();
for (int index : indices) {
selectionModel.addSelectionInterval(new MultiListSelection(multiListDataProvider.getKey(), index), new MultiListSelection(multiListDataProvider.getKey(), index));
}
}
public synchronized D getSelectedValue () {
int index;
if ((index = getSelectedIndex()) >= 0) {
return model.getElementAt(index);
}
return null;
}
public synchronized Object[] getSelectedValues () {
LinkedList valueList;
valueList = new LinkedList();
for (int count = 0; count < catalogPanel.getComponentCount(); count++) {
if (selectionModel.isSelected(new MultiListSelection(multiListDataProvider.getKey(), count))) {
valueList.add(model.getElementAt(count));
}
}
return valueList.toArray();
}
public synchronized boolean isSelectedIndex (int index) {
return selectionModel.isSelected(new MultiListSelection(multiListDataProvider.getKey(), index));
}
public synchronized boolean isSelectedValue (D element) {
return selectionModel.isSelected(new MultiListSelection(multiListDataProvider.getKey(), model.indexOf(element)));
}
public synchronized boolean isSelectionEmpty () {
return selectionModel.isSelectionEmpty();
}
public synchronized void removeSelectionInterval (int startIndex, int endIndex) {
selectionModel.removeSelectionInterval(new MultiListSelection(multiListDataProvider.getKey(), startIndex), new MultiListSelection(multiListDataProvider.getKey(), endIndex));
}
public synchronized void setSelectionInterval (int startIndex, int endIndex) {
selectionModel.setSelectionInterval(new MultiListSelection(multiListDataProvider.getKey(), startIndex), new MultiListSelection(multiListDataProvider.getKey(), endIndex));
}
private void reRenderAllComponents () {
for (int count = 0; count < catalogPanel.getComponentCount(); count++) {
reRenderComponent(count);
}
}
private void reRenderComponent (int index) {
getRenderedComponent(index).repaint();
}
public Component getRenderedComponent (int index) {
return renderer.getCatalogCellRendererComponent(this, model.getElementAt(index), index, isSelectedIndex(index), false);
}
public synchronized void itemAdded (CatalogDataEvent catalogDataEvent) {
Component component;
int index;
index = catalogDataEvent.getEndIndex();
component = getRenderedComponent(index);
catalogPanel.add(component, index);
adjustToContents();
for (int count = catalogDataEvent.getEndIndex() + 1; count < catalogPanel.getComponentCount(); count++) {
reRenderComponent(count);
}
selectionModel.insertIndexInterval(new MultiListSelection(multiListDataProvider.getKey(), index), 1, true);
}
public synchronized void intervalRemoved (CatalogDataEvent catalogDataEvent) {
for (int count = catalogDataEvent.getStartIndex(); count <= catalogDataEvent.getEndIndex(); count++) {
catalogPanel.remove(catalogDataEvent.getStartIndex());
}
adjustToContents();
for (int count = 0; count < catalogPanel.getComponentCount(); count++) {
reRenderComponent(count);
}
selectionModel.removeIndexInterval(new MultiListSelection(multiListDataProvider.getKey(), catalogDataEvent.getStartIndex()), new MultiListSelection(multiListDataProvider.getKey(), catalogDataEvent.getEndIndex()));
}
public synchronized void intervalChanged (CatalogDataEvent catalogDataEvent) {
for (int count = catalogDataEvent.getStartIndex(); count <= catalogDataEvent.getEndIndex(); count++) {
catalogPanel.remove(catalogDataEvent.getStartIndex());
}
for (int count = catalogDataEvent.getEndIndex(); count >= catalogDataEvent.getStartIndex(); count--) {
catalogPanel.add(getRenderedComponent(count), catalogDataEvent.getStartIndex());
}
adjustToContents();
for (int count = catalogDataEvent.getStartIndex(); count <= catalogDataEvent.getEndIndex(); count++) {
reRenderComponent(count);
}
}
private void adjustToContents () {
Rectangle bounds;
double preferredWidth;
double preferredHeight = 0;
if (getParent() != null) {
if (getParent() instanceof JViewport) {
preferredWidth = ((JViewport)getParent()).getViewSize().getWidth();
} else {
preferredWidth = getParent().getWidth();
}
for (int count = 0; count < catalogPanel.getComponentCount(); count++) {
preferredHeight += catalogPanel.getComponent(count).getPreferredSize().getHeight();
}
bounds = new Rectangle(new Point(0, 0), new Dimension((int)preferredWidth, (int)preferredHeight));
setPreferredSize(bounds.getSize());
catalogPanel.setBounds(bounds);
glassPanel.setBounds(bounds);
}
}
public synchronized void revalidate () {
adjustToContents();
super.revalidate();
}
public synchronized void repaint () {
reRenderAllComponents();
}
public synchronized int getIndexAtPoint (Point point) {
int height = 0;
for (int count = 0; count < catalogPanel.getComponentCount(); count++) {
height += catalogPanel.getComponent(count).getPreferredSize().getHeight();
if (point.getY() <= height) {
return count;
}
}
return -1;
}
public synchronized Rectangle getSquashedRectangleAtIndex (int index) {
int yPos = 0;
for (int count = 0; count < index; count++) {
yPos += catalogPanel.getComponent(count).getPreferredSize().getHeight();
}
return new Rectangle(0, yPos, 0, (int)catalogPanel.getComponent(index).getPreferredSize().getHeight());
}
public synchronized Dimension getPreferredScrollableViewportSize () {
return getPreferredSize();
}
public boolean getScrollableTracksViewportWidth () {
return true;
}
public boolean getScrollableTracksViewportHeight () {
return false;
}
public synchronized int getScrollableUnitIncrement (Rectangle visibleRect, int orientation, int direction) {
return scrollModel.getScrollableUnitIncrement(visibleRect, orientation, direction);
}
public synchronized int getScrollableBlockIncrement (Rectangle visibleRect, int orientation, int direction) {
return scrollModel.getScrollableBlockIncrement(visibleRect, orientation, direction);
}
public synchronized void valueChanged (MultiListSelectionEvent multiListSelectionEvent) {
for (int count = multiListSelectionEvent.getFirstIndex(); count <= multiListSelectionEvent.getLastIndex(); count++) {
if (count >= catalogPanel.getComponentCount()) {
break;
} else {
reRenderComponent(count);
}
}
}
public synchronized void ancestorResized (HierarchyEvent hierarchyEvent) {
adjustToContents();
}
public void ancestorMoved (HierarchyEvent hierarchyEvent) {
}
public synchronized void componentHidden (ComponentEvent componentEvnt) {
adjustToContents();
}
public void componentMoved (ComponentEvent componentEvnt) {
}
public synchronized void componentShown (ComponentEvent componentEvnt) {
adjustToContents();
}
public synchronized void componentResized (ComponentEvent componentEvnt) {
adjustToContents();
}
private void dispatchGlassMouseEvent (MouseEvent mouseEvent, boolean moved) {
Component targetComponent;
MouseEvent targetEvent;
Point mousePoint;
if ((targetComponent = SwingUtilities.getDeepestComponentAt(catalogPanel, mouseEvent.getX(), mouseEvent.getY())) != null) {
if (moved && (targetComponent != lastTargetedComponent)) {
if (lastTargetedComponent != null) {
mousePoint = SwingUtilities.convertPoint(glassPanel, mouseEvent.getPoint(), lastTargetedComponent);
lastTargetedComponent.dispatchEvent(new MouseEvent(lastTargetedComponent, MouseEvent.MOUSE_EXITED, mouseEvent.getWhen(), 0, (int)mousePoint.getX(), (int)mousePoint.getY(), mouseEvent.getClickCount(), mouseEvent.isPopupTrigger(), mouseEvent.getButton()));
}
mousePoint = SwingUtilities.convertPoint(glassPanel, mouseEvent.getPoint(), targetComponent);
targetComponent.dispatchEvent(new MouseEvent(targetComponent, MouseEvent.MOUSE_ENTERED, mouseEvent.getWhen(), 0, (int)mousePoint.getX(), (int)mousePoint.getY(), mouseEvent.getClickCount(), mouseEvent.isPopupTrigger(), mouseEvent.getButton()));
}
targetEvent = SwingUtilities.convertMouseEvent(glassPanel, mouseEvent, targetComponent);
targetComponent.dispatchEvent(targetEvent);
lastTargetedComponent = targetComponent;
}
}
private int getComponentIndex (Point point) {
Component cellComponent;
if ((cellComponent = catalogPanel.getComponentAt(point)) != null) {
for (int count = 0; count < catalogPanel.getComponentCount(); count++) {
if (catalogPanel.getComponent(count) == cellComponent) {
return count;
}
}
}
return -1;
}
public synchronized void mouseClicked (MouseEvent mouseEvent) {
dispatchGlassMouseEvent(mouseEvent, false);
}
public synchronized void mousePressed (MouseEvent mouseEvent) {
MultiListSelection anchorSelection;
int index;
if ((index = getComponentIndex(mouseEvent.getPoint())) >= 0) {
if (mouseEvent.isShiftDown()) {
if ((anchorSelection = selectionModel.getAnchorSelection()) == null) {
setSelectedIndex(index);
} else {
selectionModel.setSelectionInterval(anchorSelection, new MultiListSelection(multiListDataProvider.getKey(), index));
}
} else if (mouseEvent.isControlDown()) {
if (isSelectedIndex(index)) {
selectionModel.removeSelectionInterval(new MultiListSelection(multiListDataProvider.getKey(), index), new MultiListSelection(multiListDataProvider.getKey(), index));
} else {
selectionModel.addSelectionInterval(new MultiListSelection(multiListDataProvider.getKey(), index), new MultiListSelection(multiListDataProvider.getKey(), index));
}
} else {
setSelectedIndex(index);
}
requestFocusInWindow();
}
dispatchGlassMouseEvent(mouseEvent, false);
}
public synchronized void mouseReleased (MouseEvent mouseEvent) {
dispatchGlassMouseEvent(mouseEvent, false);
}
public synchronized void mouseEntered (MouseEvent mouseEvent) {
lastTargetedComponent = null;
}
public synchronized void mouseExited (MouseEvent mouseEvent) {
}
public synchronized void mouseDragged (MouseEvent mouseEvent) {
dispatchGlassMouseEvent(mouseEvent, true);
}
public synchronized void mouseMoved (MouseEvent mouseEvent) {
dispatchGlassMouseEvent(mouseEvent, true);
}
}