com.seaglasslookandfeel.SeaGlassContext Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of seaglasslookandfeel Show documentation
Show all versions of seaglasslookandfeel Show documentation
A Java cross-platform look and feel for JRE 1.8 and later.
This is developed from
Synth, and is based on forms seen in sea glass,
that is, bits of glass washed up on the shore by
the sea.
/*
* Copyright (c) 2009 Kathryn Huxtable and Kenneth Orr.
*
* This file is part of the SeaGlass Pluggable Look and Feel.
*
* 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.
*
* $Id: SeaGlassContext.java 1527 2010-06-09 18:22:31Z [email protected] $
*/
package com.seaglasslookandfeel;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.plaf.synth.Region;
import javax.swing.plaf.synth.SynthConstants;
import javax.swing.plaf.synth.SynthContext;
import javax.swing.plaf.synth.SynthPainter;
import javax.swing.plaf.synth.SynthStyle;
/**
* An immutable transient object containing contextual information about a
* Region
. A SeaGlassContext
should only be considered
* valid for the duration of the method it is passed to. In other words you
* should not cache a SeaGlassContext
that is passed to you and
* expect it to remain valid.
*
* Extends SynthContext by Scott Violet and reimplements most of its methods
* because too much is package local.
*
* @see javax.swing.plaf.synth.SynthContext
*/
public class SeaGlassContext extends SynthContext {
private static final SynthPainter EMPTY_PAINTER = new SynthPainter() {
};
/** This button *must* not have a UI or we end up throwing an NPE. */
private static final JButton FAKE_BUTTON = new JButton() {
public void updateUI() {
// Do nothing.
}
};
// Fake items are created because there's no public empty constructor for
// SynthContext and we need a way to determine when our own empty
// constructor was called. We pass these to SynthContext's constructor and
// then test for them later.
private static final JButton fakeComponent = FAKE_BUTTON;
private static Region fakeRegion = Region.BUTTON;
private static SynthStyle fakeStyle = new SeaGlassStyle(null, null);
// From SynthContext.
private static final Map contextMap;
static {
contextMap = new HashMap();
}
private JComponent component;
private Region region;
private SynthStyle style;
private int state;
/**
* Creates a new SeaGlassContext object.
*/
public SeaGlassContext() {
super(fakeComponent, fakeRegion, fakeStyle, 0);
}
/**
* Creates a SeaGlassContext with the specified values. This is meant for
* subclasses and custom UI implementors. You very rarely need to construct
* a SeaGlassContext, though some methods will take one.
*
* @param component JComponent
* @param region Identifies the portion of the JComponent
* @param style Style associated with the component
* @param state State of the component as defined in SynthConstants.
*/
public SeaGlassContext(JComponent component, Region region, SynthStyle style, int state) {
super(component, region, style, state);
if (component == fakeComponent) {
this.component = null;
this.region = null;
this.style = null;
return;
}
if (component == null || region == null || style == null) {
throw new NullPointerException("You must supply a non-null component, region and style");
}
reset(component, region, style, state);
}
/**
* The method used to get a context.
*
* @param type the class of the context.
* @param component the component.
* @param region the region.
* @param style the style.
* @param state the state.
*
* @return the newly constructed context, corresponding to the arguments.
*/
public static SeaGlassContext getContext(Class type, JComponent component, Region region, SynthStyle style, int state) {
SeaGlassContext context = null;
synchronized (contextMap) {
List instances = (List) contextMap.get(type);
if (instances != null) {
int size = instances.size();
if (size > 0) {
context = (SeaGlassContext) instances.remove(size - 1);
}
}
}
if (context == null) {
try {
context = (SeaGlassContext) type.newInstance();
} catch (IllegalAccessException iae) {
iae.printStackTrace();
} catch (InstantiationException ie) {
ie.printStackTrace();
}
}
context.reset(component, region, style, state);
return context;
}
/**
* Release a context for re-use.
*
* @param context the context to release.
*/
static void releaseContext(SeaGlassContext context) {
synchronized (contextMap) {
List instances = (List) contextMap.get(context.getClass());
if (instances == null) {
instances = new ArrayList(5);
contextMap.put(context.getClass(), instances);
}
instances.add(context);
}
}
/**
* Returns the hosting component containing the region.
*
* @return Hosting Component
*/
public JComponent getComponent() {
return component;
}
/**
* Returns the Region identifying this state.
*
* @return Region of the hosting component
*/
public Region getRegion() {
return region;
}
/**
* A convenience method for getRegion().isSubregion()
.
*
* @return {@code true} if the context represents a subregion, {@code false}
* otherwise.
*/
@SuppressWarnings("all")
public boolean isSubregion() {
return getRegion().isSubregion();
}
/**
* Sets the current style for the context.
*
* @param style the new style.
*/
@SuppressWarnings("all")
public void setStyle(SynthStyle style) {
this.style = style;
}
/**
* Returns the style associated with this Region.
*
* @return SynthStyle associated with the region.
*/
public SynthStyle getStyle() {
return style;
}
/**
* Sets the current state for a component/region.
*
* @param state the new state.
*/
@SuppressWarnings("all")
public void setComponentState(int state) {
this.state = state;
}
/**
* Returns the state of the widget, which is a bitmask of the values defined
* in SynthConstants
. A region will at least be in one of
* ENABLED
, MOUSE_OVER
, PRESSED
or
* DISABLED
.
*
* @see SynthConstants
*
* @return State of Component
*/
public int getComponentState() {
return state;
}
/**
* Resets the state of the Context.
*
* @param component the new component.
* @param region the new region.
* @param style the new style.
* @param state the new state.
*/
@SuppressWarnings("all")
public void reset(JComponent component, Region region, SynthStyle style, int state) {
this.component = component;
this.region = region;
this.style = style;
this.state = state;
}
/**
* Release a context for re-use after nulling the component and style.
*/
@SuppressWarnings("all")
public void dispose() {
this.component = null;
this.style = null;
releaseContext(this);
}
/**
* Convenience method to get the Painter from the current SynthStyle. This
* will NEVER return null.
*
* @return the painter for the style and context, otherwise the empty
* painter.
*/
@SuppressWarnings("all")
public SynthPainter getPainter() {
SynthPainter painter = getStyle().getPainter(this);
if (painter != null) {
return painter;
}
return EMPTY_PAINTER;
}
}