org.pushingpixels.flamingo.api.common.AbstractFileViewPanel Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of flamengo Show documentation
Show all versions of flamengo Show documentation
Flamingo Swing component suite
The newest version!
/*
* Copyright (c) 2005-2010 Flamingo Kirill Grouchnikov. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* o Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* o Neither the name of Flamingo Kirill Grouchnikov nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.pushingpixels.flamingo.api.common;
import java.awt.Dimension;
import java.io.InputStream;
import java.util.*;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
import org.pushingpixels.flamingo.api.common.icon.EmptyResizableIcon;
import org.pushingpixels.flamingo.api.common.icon.ResizableIcon;
/**
* Panel that hosts file-related command buttons with progress indication and
* cancellation capabilities.
*
* @author Kirill Grouchnikov
* @param
* Type tag.
*/
public abstract class AbstractFileViewPanel extends JCommandButtonPanel {
/**
* Maps from file name to the buttons.
*/
protected Map buttonMap;
/**
* Progress listener to report back on loaded images.
*/
protected ProgressListener progressListener;
/**
* Contains the buttons with completely loaded images.
*/
protected Set loadedSet;
/**
* The main worker that loads the images off EDT.
*/
private SwingWorker mainWorker;
/**
* Information on the specific file. Depending on the actual type of the
* file repository, the property map will have different keys.
*
* @author Kirill Grouchnikov
*/
public static class Leaf {
/**
* Leaf name.
*/
protected String leafName;
/**
* Stream with the contents of the leaf file.
*/
protected InputStream leafStream;
/**
* Leaf property map.
*/
protected Map leafProps;
/**
* Creates a new leaf.
*
* @param leafName
* Leaf name.
* @param leafStream
* Stream with the contents of the leaf file.
*/
public Leaf(String leafName, InputStream leafStream) {
this.leafName = leafName;
this.leafStream = leafStream;
this.leafProps = new HashMap();
}
/**
* Returns the leaf name.
*
* @return Leaf name.
*/
public String getLeafName() {
return leafName;
}
/**
* Returns the stream with the contents of the leaf file.
*
* @return Stream with the contents of the leaf file.
*/
public InputStream getLeafStream() {
return leafStream;
}
/**
* Returns the leaf property with the specified name.
*
* @param propName
* Property name.
* @return Leaf property with the specified name.
*/
public Object getLeafProp(String propName) {
return this.leafProps.get(propName);
}
/**
* Sets the leaf property with the specified name.
*
* @param propName
* Property name.
* @param propValue
* Property value.
*/
public void setLeafProp(String propName, Object propValue) {
this.leafProps.put(propName, propValue);
}
/**
* Returns the map of all the properties of this leaf.
*
* @return Unmodifiable view of the map of all the properties of this
* leaf.
*/
public Map getLeafProps() {
return Collections.unmodifiableMap(this.leafProps);
}
}
/**
* Creates a new panel.
*
* @param startingDimension
* Initial dimension for icons.
* @param progressListener
* Progress listener to report back on loaded icons.
*/
public AbstractFileViewPanel(int startingDimension,
ProgressListener progressListener) {
super(startingDimension);
this.buttonMap = new HashMap();
this.progressListener = progressListener;
this.loadedSet = new HashSet();
this.setToShowGroupLabels(false);
}
/**
* Creates a new panel.
*
* @param startingState
* Initial state for icons.
* @param progressListener
* Progress listener to report back on loaded icons.
*/
public AbstractFileViewPanel(CommandButtonDisplayState startingState,
ProgressListener progressListener) {
super(startingState);
this.buttonMap = new HashMap();
this.progressListener = progressListener;
this.loadedSet = new HashSet();
this.setToShowGroupLabels(false);
}
/**
* Sets the current entries to show. The current contents of the panel are
* discarded. For each matching entry determined by the
* {@link #toShowFile(StringValuePair)} call, a new {@link JCommandButton}
* hosting an the matching implementation of {@link ResizableIcon} is added
* to the panel.
*
* @param leafs
* Information on the entries to show in the panel.
*/
public void setFolder(final java.util.List> leafs) {
this.removeAllGroups();
this.addButtonGroup("");
this.buttonMap.clear();
int fileCount = 0;
final Map newButtons = new HashMap();
for (StringValuePair leaf : leafs) {
String name = leaf.getKey();
if (!toShowFile(leaf))
continue;
int initialSize = currDimension;
if (initialSize < 0)
initialSize = currState.getPreferredIconSize();
JCommandButton button = new JCommandButton(name,
new EmptyResizableIcon(initialSize));
button.setHorizontalAlignment(SwingUtilities.LEFT);
button.setDisplayState(this.currState);
if (this.currState == CommandButtonDisplayState.FIT_TO_ICON)
button.updateCustomDimension(currDimension);
this.addButtonToLastGroup(button);
newButtons.put(name, button);
buttonMap.put(name, button);
fileCount++;
}
this.doLayout();
this.repaint();
final int totalCount = fileCount;
this.mainWorker = new SwingWorker() {
@Override
protected Void doInBackground() throws Exception {
if ((totalCount > 0) && (progressListener != null)) {
progressListener.onProgress(new ProgressEvent(
AbstractFileViewPanel.this, 0, totalCount, 0));
}
for (final StringValuePair leafPair : leafs) {
if (isCancelled())
break;
final String name = leafPair.getKey();
if (!toShowFile(leafPair))
continue;
InputStream stream = getLeafContent(leafPair.getValue());
Leaf leaf = new Leaf(name, stream);
leaf.setLeafProp("source", leafPair.getValue());
for (Map.Entry propEntry : leafPair
.getProps().entrySet()) {
leaf.setLeafProp(propEntry.getKey(), propEntry
.getValue());
}
publish(leaf);
}
return null;
}
@Override
protected void process(List leaves) {
for (final Leaf leaf : leaves) {
final String name = leaf.getLeafName();
InputStream stream = leaf.getLeafStream();
Dimension dim = new Dimension(currDimension, currDimension);
final ResizableIcon icon = getResizableIcon(leaf, stream,
currState, dim);
if (icon == null)
continue;
final JCommandButton commandButton = newButtons.get(name);
commandButton.setIcon(icon);
if (icon instanceof AsynchronousLoading) {
((AsynchronousLoading) icon)
.addAsynchronousLoadListener(new AsynchronousLoadListener() {
public void completed(boolean success) {
synchronized (AbstractFileViewPanel.this) {
if (loadedSet
.contains(commandButton))
return;
loadedSet.add(commandButton);
// loadedCount++;
if (progressListener != null) {
progressListener
.onProgress(new ProgressEvent(
AbstractFileViewPanel.this,
0, totalCount,
loadedSet
.size()));
if (loadedSet.size() == totalCount) {
progressListener
.onProgress(new ProgressEvent(
AbstractFileViewPanel.this,
0,
totalCount,
totalCount));
}
}
}
}
});
}
configureCommandButton(leaf, commandButton, icon);
commandButton.setDisplayState(currState);
if (currState == CommandButtonDisplayState.FIT_TO_ICON)
commandButton.updateCustomDimension(currDimension);
}
}
};
mainWorker.execute();
}
/**
* Returns the number of loaded icons.
*
* @return The number of loaded icons.
*/
public int getLoadedIconCount() {
return this.loadedSet.size();
}
/**
* Cancels the pending processing.
*/
public void cancelMainWorker() {
if (this.mainWorker == null)
return;
if (this.mainWorker.isDone() || this.mainWorker.isCancelled())
return;
this.mainWorker.cancel(false);
}
/**
* Returns the button map.
*
* @return Unmodifiable view on the button map.
*/
public Map getButtonMap() {
return Collections.unmodifiableMap(buttonMap);
}
/**
* Returns indication whether the specified file should be shown on this
* panel.
*
* @param pair
* Information on the file.
* @return true
if the specified file should be shown on this
* panel, false
otherwise.
*/
protected abstract boolean toShowFile(StringValuePair pair);
/**
* Returns the icon for the specified parameters.
*
* @param leaf
* Information on the file.
* @param stream
* Input stream with the file contents.
* @param state
* Icon state.
* @param dimension
* Icon dimension.
* @return File icon.
*/
protected abstract ResizableIcon getResizableIcon(Leaf leaf,
InputStream stream, CommandButtonDisplayState state,
Dimension dimension);
/**
* Configures the specified command button. Can be used to wire additional
* behavior, such as tooltips or action listeners if the specific view panel
* implementation requires it.
*
* @param leaf
* Information on the file "behind" the button.
* @param button
* Button to configure.
* @param icon
* Button icon.
*/
protected abstract void configureCommandButton(Leaf leaf,
JCommandButton button, ResizableIcon icon);
/**
* Returns the input stream with the file contents.
*
* @param leaf
* Leaf (file behind a command button on this panel).
* @return Input stream with the file contents.
*/
protected abstract InputStream getLeafContent(T leaf);
}