
org.pushingpixels.lafwidget.contrib.blogofbug.swing.components.JCarosel Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of laf-widget Show documentation
Show all versions of laf-widget Show documentation
Laf-Widget provides support for common "feel" widgets in look-and-feel libraries
The newest version!
/*
* JCarosel.java
*
* Created on November 22, 2006, 7:27 PM
*
* Copyright 2006-2007 Nigel Hughes
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at http://www.apache.org/
* licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language
* governing permissions and limitations under the License.
*/
package org.pushingpixels.lafwidget.contrib.blogofbug.swing.components;
import java.awt.*;
import java.awt.event.*;
import org.pushingpixels.lafwidget.contrib.blogofbug.swing.SwingBugUtilities;
import org.pushingpixels.lafwidget.contrib.blogofbug.swing.layout.CaroselLayout;
import org.pushingpixels.lafwidget.contrib.blogofbug.utility.ImageUtilities;
/**
* A carousel component which lays out components around a carousel, moving each
* to the front as it is clicked on. Double clicking will fire the action
* associated with the compnent if it has one, or give it the focus if it does
* not.
*
* Note this will be changed to only allow RichComponents in the future.
*
* @author bug
*/
public class JCarosel extends GradientPanel implements MouseListener,
MouseWheelListener {
/**
* Set to true if the performance should be measured. Debugging purposes
* only
*/
private static final boolean MEASURE_PERFORMANCE = true;
/**
* The property that is set when a new component comes to the front. To use
* it add a property change listener for it, useful for keeping animations
* synchronized.
*/
public static final String FRONT_COMPONENT_CHANGE = "frontComponentChanged";
/**
* The layout being used for the carousel
*/
protected CaroselLayout layout;
/**
* The last component the wheel selected. Used to ensure we don't move too
* far around why they are wheeling and they turn back on themselves
* creating a nasty oscilation in the animation (everything works fine, it's
* just not purty)
*/
protected Component lastWheeledTo = null;
/**
* The prefered width of the components in the container, everything will be
* scaled to this width for neutral scaling (1.0)
*/
protected int DEFAULT_CONTENT_WIDTH = 64;
/**
* Delay in milliseconds from the first click to the start of the spin, this
* gives implementors using a double click anywhere to fire an event a
* chance for their users to get the double click message before the
* component spins around.
*/
protected int spinStartDelay = 200;
/**
* Creates a new instance of JCarosel
*/
public JCarosel() {
layout = new CaroselLayout(this);
this.setLayout(layout);
this.addMouseWheelListener(this);
setContentWidth(DEFAULT_CONTENT_WIDTH);
}
/**
* Creates a new Carousel specifying the prefered width up front
*
* @param contentWidth
* The prefered width of component at neutral scale (3 or 9
* o'clock)
*/
public JCarosel(int contentWidth) {
this();
setContentWidth(contentWidth);
}
/**
* Sets the prefered width of the components inside the carousel, this is
* the neutral width that will change as the component is scaled, but at 9
* and 6 o'clock where the scale is one they will be this width.
*
* @param contentWidth
* The prefered width.
*/
public void setContentWidth(int contentWidth) {
layout.setNeutralContentWidth(contentWidth);
}
/**
* If set to true the carousel will fade out components as they move away
* from the front of the carousel (6 o'clock)
*
* @param useDepthBased
* True to fade components as they move to the back, false to not
* do it
*/
public void setDepthBasedAlpha(boolean useDepthBased) {
layout.setDepthBasedAlpha(useDepthBased);
}
/**
* Specifies which type of CarouselLayout to be used to lay the component
* out around the carousel Any looping layout can be used. Mobius strip
* layout anyone?
*
* @param layout
* The carousel layout to use
*/
public void setLayout(CaroselLayout layout) {
this.layout = layout;
super.setLayout(layout);
}
/**
* Adds a component to the carousel
*
* @param component
* The component to add to the carousel
* @return The component
*/
public Component add(Component component) {
add("", component);
component.setForeground(Color.WHITE);
component.setBackground(Color.BLACK);
bringToFront(getComponent(0));
validate();
return component;
}
/**
* Adds an image to the carousel
*
* @param image
* The image to add
* @param text
* The text label
* @return The component created, normally a reflected image label
*/
public Component add(Image image, String text) {
ReflectedImageLabel component = new ReflectedImageLabel(image, text);
component.addMouseListener(this);
return add(component);
}
/**
* Removes the component from the carousel
*
* @param component
* The component to remove
*/
public void remove(Component component) {
super.remove(component);
if (getComponentCount() > 0) {
bringToFront(getComponent(0));
}
invalidate();
validate();
}
/**
* The image to add and it's width and height
*
* @param imageURL
* The URL
* @param width
* The desired rendering width
* @param height
* The desired rendering height
* @return The component created
* @deprecated This function will be removed, use add(String imageURL)
* instead.
*/
public Component add(String imageURL, int width, int height) {
ReflectedImageLabel component = new ReflectedImageLabel(imageURL,
width, height);
component.addMouseListener(this);
return add(component);
}
/**
* Add the image, and it's label to the carousel
*
* @param imageURL
* The image URL
* @param text
* The text label
* @param width
* The width
* @param height
* The height
* @return The component created to hold the image
* @deprecated This function will be removed, use setNeutralWidth() on
* JCarousel instead.
*/
public Component add(String imageURL, String text, int width, int height) {
ReflectedImageLabel component = new ReflectedImageLabel(imageURL, text,
width, height);
component.addMouseListener(this);
return add(component);
}
/**
* Brings the specified component to the front of the carousel
*
* @param component
* The component to bring to the front
*/
public void bringToFront(Component component) {
firePropertyChange(FRONT_COMPONENT_CHANGE, getComponent(0), component);
layout.setFrontMostComponent(component);
}
/**
* Which component is at the front
*
* @return The component at the front (by default 6 o'clock)
*/
public Component getFrontmost() {
return getComponent(0);
}
/**
* Bring the "clicked" component to the front. Delays by 200ms to allow for
* a double click
*
* @param mouseEvent
* Brings the component clicked on by the mouse to the front
*/
public void mouseClicked(final MouseEvent mouseEvent) {
if (mouseEvent.getClickCount() == 1) {
SwingBugUtilities.invokeAfter(new Runnable() {
public void run() {
bringToFront((Component) mouseEvent.getSource());
}
}, spinStartDelay);
}
}
/**
* Sets the delay between clicking on a component in the carousel, and the
* spin starting to move that component to the front. The longer it is, the
* easier it is to double click on a non-front component
*
* @param spinStartDelay
*/
public void setSpinStartDelay(int spinStartDelay) {
this.spinStartDelay = spinStartDelay;
}
/**
* Returns the spin start delay
*
* @return The delay in ms between the click and the spin
*/
public int getSpinStartDelay() {
return spinStartDelay;
}
/**
* Inserts a component at the specified index
*
* @param i
* The index
* @param comp
* The component
*/
public void insertComponentAt(int i, Component comp) {
add(comp);
layout.moveComponentTo(i, comp);
}
/**
* Inserts a new object at a specific location
*
* @param i
* The position on the carousel
* @param imageURL
* The URL of the image
* @param width
* The width of the image
* @param height
* The height of the image
* @return The component created to show the image (usually a
* ReflectedImageLabel but this may change)
*/
public Component insertAt(int i, String imageURL, int width, int height) {
Component comp = add(imageURL, width, height);
layout.moveComponentTo(i, comp);
return comp;
}
/**
* Inserts a new object at a specific location
*
* @param i
* The position on the carousel
* @param imageURL
* The URL of the image
* @param text
* The text label
* @param width
* The prefered width of the image
* @param height
* The prefered height of the image
* @return The component created to represent the image, currently reflected
* image label but may change
*/
public Component insertAt(int i, String imageURL, String text, int width,
int height) {
Component comp = add(imageURL, text, width, height);
layout.moveComponentTo(i, comp);
return comp;
}
/**
* Moves everything to their final positions
*
*/
public void finalizeLayoutImmediately() {
layout.layoutContainer(this);
layout.finalizeLayoutImmediately();
repaint();
}
/**
* Not interested
*
* @param mouseEvent
* Ignored
*/
public void mousePressed(MouseEvent mouseEvent) {
}
/**
* Not interested
*
* @param mouseEvent
* Ignored
*/
public void mouseReleased(MouseEvent mouseEvent) {
}
/**
* Not interested
*
* @param mouseEvent
* Ignored
*/
public void mouseEntered(MouseEvent mouseEvent) {
}
/**
* Not interested
*
* @param mouseEvent
* Ignored
*/
public void mouseExited(MouseEvent mouseEvent) {
}
/**
* When event received will spin the carousel to select the next object.
* Because the wheel can be spun quicker than the carousel animates it keeps
* track of the target (so the user may have selected something three
* components away, althought the animation has not yet finished moving past
* the first comopnent)
*
* @param mouseWheelEvent
* The event object
*/
public void mouseWheelMoved(MouseWheelEvent mouseWheelEvent) {
if (mouseWheelEvent.getScrollType() == MouseWheelEvent.WHEEL_UNIT_SCROLL) {
int amount = mouseWheelEvent.getWheelRotation();
if (lastWheeledTo == null) {
lastWheeledTo = getFrontmost();
}
int lastPosition = layout.getComponentIndex(lastWheeledTo);
int frontMostPosition = layout.getComponentIndex(getComponent(0));
// Don't over spin
if (Math.abs(lastPosition - frontMostPosition) > layout
.getComponentCount() / 4) {
return;
}
if (amount > 0) {
lastWheeledTo = layout.getPreviousComponent(lastWheeledTo);
} else {
lastWheeledTo = layout.getNextComponent(lastWheeledTo);
}
bringToFront(lastWheeledTo);
}
}
/**
* Adds a new image to the carousel
*
* @param imageURL
* The image
* @return The component created
*/
public Component add(String imageURL) {
ReflectedImageLabel component = new ReflectedImageLabel(imageURL);
component.addMouseListener(this);
return add(component);
}
/**
* Adds a new image to the carousel
*
* @param imageURL
* The image
* @param textLabel
* The label
* @return The component created
*/
public Component add(String imageURL, String textLabel) {
ReflectedImageLabel component = new ReflectedImageLabel(ImageUtilities
.loadCompatibleImage(imageURL), textLabel);
component.addMouseListener(this);
return add(component);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy