// Copyright 2011 Palantir Technologies
//
// 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 com.palantir.ptoss.cinch.example.simple;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.lang.reflect.InvocationTargetException;
import javax.swing.DefaultBoundedRangeModel;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.UIManager;
import javax.swing.plaf.metal.MetalSliderUI;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.palantir.ptoss.cinch.core.Bindings;
import com.palantir.ptoss.cinch.core.DefaultBindableModel;
import com.palantir.ptoss.cinch.example.Examples;
import com.palantir.ptoss.cinch.swing.Bound;
import com.palantir.ptoss.cinch.swing.BoundExtent;
/**
* An illustration of using the {@link BoundExtent} annotation to tie the extent of one control to
* another. In this example, the top slider in the UI sets the extent for the bottom slider.
* @see JSlider#setExtent(int)
* @see BoundExtent
*/
public class BoundExtentsExample {
static final Logger log = LoggerFactory.getLogger(BoundExtentsExample.class);
public static class Model extends DefaultBindableModel {
private int sliderExtent;
public int getSliderExtent() {
return sliderExtent;
}
public void setSliderExtent(int sliderPosition) {
this.sliderExtent = sliderPosition;
log.debug("Slider Extent set: " + sliderPosition);
update();
}
}
@SuppressWarnings("unused")
private final Model model = new Model();
private final JPanel panel = new JPanel();
@BoundExtent(to = "sliderExtent")
private final JSlider slider = new JSlider(new DefaultBoundedRangeModel(0, 0, 0, 100));
@Bound(to = "sliderExtent")
private final JSlider controlSlider = new JSlider(new DefaultBoundedRangeModel(0, 0, 0, 100));
@Bound(to = "sliderExtent")
private final JLabel extent = new JLabel();
private final Bindings bindings = Bindings.standard();
public BoundExtentsExample() {
initializeInterface();
bindings.bind(this);
}
private JPanel buildTextPanel() {
JPanel panel = new JPanel(new BorderLayout());
panel.add(extent, BorderLayout.CENTER);
panel.add(new JLabel("Extent: "), BorderLayout.WEST);
return panel;
}
private void styleSlider(JSlider slider) {
slider.setMajorTickSpacing(10);
slider.setMinorTickSpacing(1);
slider.setPaintLabels(true);
slider.setPaintTicks(true);
slider.setPaintTrack(true);
slider.setSnapToTicks(true);
}
private void addExtentsHighlight(JSlider slider) {
slider.setUI(new ExtentHighlightingSliderUI(slider));
}
private void initializeInterface() {
panel.setLayout(new BorderLayout());
styleSlider(slider);
addExtentsHighlight(slider);
panel.add(slider, BorderLayout.CENTER);
styleSlider(controlSlider);
panel.add(controlSlider, BorderLayout.NORTH);
panel.add(buildTextPanel(), BorderLayout.SOUTH);
JFrame frame = new JFrame(getClass().getSimpleName());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocation(100, 100);
frame.setSize(400, 200);
frame.setContentPane(panel);
frame.setVisible(true);
}
public static void main(String[] args) throws InterruptedException, InvocationTargetException {
Examples.initializeLogging();
// set to Metal LaF
try {
UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName());
EventQueue.invokeAndWait(new Runnable() {
public void run() {
new BoundExtentsExample();
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
static class ExtentHighlightingSliderUI extends MetalSliderUI {
final JSlider slider;
Color originalLabelColor = null;
static final Color RED = Color.RED;
public ExtentHighlightingSliderUI(JSlider slider) {
this.slider = slider;
}
public void setOriginalLabelColor(Color originalLabelColor) {
if (originalLabelColor == null || !RED.equals(originalLabelColor)) {
this.originalLabelColor = originalLabelColor;
}
}
@Override
protected void paintHorizontalLabel(Graphics g, int value, Component label) {
final int extentLowerBound = slider.getMaximum() - slider.getExtent();
setOriginalLabelColor(label.getForeground());
if (value > extentLowerBound) {
label.setForeground(Color.RED);
} else {
label.setForeground(originalLabelColor);
}
super.paintHorizontalLabel(g, value, label);
}
@Override
protected void paintMinorTickForHorizSlider(Graphics g, Rectangle tickBounds, int x) {
super.paintMinorTickForHorizSlider(g, tickBounds, x);
Color original = g.getColor();
if (valueForXPosition(x) > slider.getMaximum() - slider.getExtent()) {
g.setColor(Color.RED);
}
g.drawLine(x, TICK_BUFFER, x, TICK_BUFFER + (tickLength / 2));
g.setColor(original);
}
@Override
protected void paintMajorTickForHorizSlider(Graphics g, Rectangle tickBounds, int x) {
super.paintMajorTickForHorizSlider(g, tickBounds, x);
Color original = g.getColor();
if (valueForXPosition(x) > slider.getMaximum() - slider.getExtent()) {
g.setColor(Color.RED);
}
g.drawLine(x, TICK_BUFFER, x, TICK_BUFFER + (tickLength - 1));
g.setColor(original);
}
}
}