org.netbeans.api.visual.widget.ResourceTable Maven / Gradle / Ivy
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.netbeans.api.visual.widget;
import java.awt.Color;
import java.awt.Font;
import java.awt.Paint;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeListenerProxy;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
/**
* The ResourceTable is used to manage a widgets resource. A ResourceTable
* can have a parent ResourceTable. The values in the child resource table will
* override the values in a parent resource table.
*
* @author treyspiva
*/
public class ResourceTable
{
public static final String PARENT_RESOURCE_TABLE = "ParentResourceTable";
// private PropertyChangeSupport propertySupport = null;
private ArrayList < WeakReference > listeners =
new ArrayList < WeakReference >();
private HashMap < String, ArrayList < WeakReference >> propertyListeners =
new HashMap < String, ArrayList < WeakReference >>();
// private HashMap < String, Paint > paintProperties
// = new HashMap();
//
// private HashMap < String, Color > colorProperties
// = new HashMap();
//
// private HashMap < String, Font > fontProperties
// = new HashMap();
private HashMap < String, Object > properties =
new HashMap < String, Object >();
private ArrayList < WeakReference < ResourceTable > > childrenTables =
new ArrayList>();
private ResourceTable parentTable = null;
/**
* Create a new resource table that has a parent.
*
* @param parent the parent resource table.
*/
public ResourceTable(ResourceTable parent)
{
this();
this.parentTable = parent;
if(this.parentTable != null)
{
this.parentTable.addChild(this);
}
}
/**
* Create a new resource table.
*/
public ResourceTable()
{
// propertySupport = new PropertyChangeSupport(this);
}
///////////////////////////////////////////////////////////////////////////
// Data Management
public void setParentTable(ResourceTable parent)
{
ResourceTable oldTable = this.parentTable;
this.parentTable = parent;
firePropertyChange(PARENT_RESOURCE_TABLE, oldTable, parent);
}
public ResourceTable getParentTable()
{
return parentTable;
}
/**
* Add a child resource table. The child resource table will be notified
* when items in the resource table are changes.
*
* @param childTable the child table.
*/
private void addChild(ResourceTable childTable)
{
childrenTables.add(new WeakReference < ResourceTable >(childTable));
}
/**
* Remove a resource table from the children list.
*
* @param childTable the child resource table.
*/
private void removeChild(ResourceTable childTable)
{
childrenTables.remove(childTable);
}
/**
* Removes the parent resource table.
*/
public void removeParent()
{
parentTable.removeChild(this);
parentTable = null;
}
/**
* Clears the entire resource table. Events will be sent to the listners.
*/
public void clear()
{
for(Map.Entry entry : properties.entrySet())
{
firePropertyChange(entry.getKey(), entry.getValue(), null);
}
properties.clear();
// for(Map.Entry entry : colorProperties.entrySet())
// {
// firePropertyChange(entry.getKey(), entry.getValue(), null);
// }
// colorProperties.clear();
//
// for(Map.Entry entry : paintProperties.entrySet())
// {
// firePropertyChange(entry.getKey(), entry.getValue(), null);
// }
// paintProperties.clear();
//
// for(Map.Entry entry : fontProperties.entrySet())
// {
// firePropertyChange(entry.getKey(), entry.getValue(), null);
// }
// fontProperties.clear();
}
///////////////////////////////////////////////////////////////////////////
// Resource Management methods
public Object getProperty(String name)
{
Object retVal = properties.get(name);
if((retVal == null) && (parentTable != null))
{
retVal = parentTable.getProperty(name);
}
return retVal;
}
/**
* Add a resource property. If a property with the same name already
* exist, it will be overridden by the new property value. If the new
* value is null, the property will be removed from the table.
*
* @param name the name of the property.
* @param value the property value.
*/
public void addProperty(String name, Object value)
{
Object oldValue = properties.remove(name);
if(value != null)
{
properties.put(name, value);
}
firePropertyChange(name, oldValue, value);
}
// /**
// * Retreives a color resource value.
// *
// * @param name the resource name.
// * @return The color property or null if the property does not exist.
// */
// public Color getColor(String name)
// {
// Color retVal = colorProperties.get(name);
//
// if((retVal == null) && (parentTable != null))
// {
// retVal = parentTable.getColor(name);
// }
//
// return retVal;
// }
//
// /**
// * Add a color resource property. If a property with the same name already
// * exist, it will be overridden by the new property value. If the new
// * value is null, the property will be removed from the table.
// *
// * @param name the name of the property.
// * @param value the property value.
// */
// public void addColor(String name, Color value)
// {
// Color oldValue = colorProperties.remove(name);
//
// if(value != null)
// {
// colorProperties.put(name, value);
// }
//
// firePropertyChange(name, oldValue, value);
// }
//
// /**
// * Retreives a color resource value.
// *
// * @param name the resource name.
// * @return The color property or null if the property does not exist.
// */
// public Font getFont(String name)
// {
// Font retVal = fontProperties.get(name);
//
// if((retVal == null) && (parentTable != null))
// {
// retVal = parentTable.getFont(name);
// }
//
// return retVal;
// }
//
// /**
// * Add a color resource property. If a property with the same name already
// * exist, it will be overridden by the new property value. If the new
// * value is null, the property will be removed from the table.
// *
// * @param name the name of the property.
// * @param value the property value.
// */
// public void addFont(String name, Font value)
// {
// Font oldValue = fontProperties.remove(name);
//
// if(value != null)
// {
// fontProperties.put(name, value);
// }
//
// firePropertyChange(name, oldValue, value);
// }
//
// /**
// * Retreives a paint resource value.
// *
// * @param name the resource name.
// * @return The paint property or null if the property does not exist.
// */
// public Paint getPaint(String name)
// {
// Paint retVal = paintProperties.get(name);
//
// if((retVal == null) && (parentTable != null))
// {
// retVal = parentTable.getPaint(name);
// }
//
// return retVal;
// }
//
// /**
// * Add a paint resource property. If a property with the same name already
// * exist, it will be overridden by the new property value. If the new
// * value is null, the property will be removed from the table.
// *
// * @param name the name of the property.
// * @param value the property value.
// */
// public void addPaint(String name, Paint value)
// {
// Paint oldValue = paintProperties.remove(name);
//
// if(value != null)
// {
// paintProperties.put(name, value);
// }
//
// firePropertyChange(name, oldValue, value);
// }
//
// public Set getLocalColorPropertyNames()
// {
// return (Set)Collections.unmodifiableSet(colorProperties.keySet());
// }
//
// public Set getLocalPaintPropertyNames()
// {
// return (Set)Collections.unmodifiableSet(paintProperties.keySet());
// }
//
// public Set getLocalFontPropertyNames()
// {
// return (Set)Collections.unmodifiableSet(fontProperties.keySet());
// }
public Set getLocalPropertyNames() {
return Collections.unmodifiableSet(properties.keySet());
}
////////////////////////////////////////////////////////////////////////////
// Listener Management
/**
* Add a PropertyChangeListener to the listener list. The listener is
* registered for all properties. The same listener object may be added
* more than once, and will be called as many times as it is added. If
* listener is null, no exception is thrown and no action is taken.
*
* @param listener The PropertyChangeListener to be added
*/
public void addPropertyChangeListener(PropertyChangeListener listener)
{
if (listener instanceof PropertyChangeListenerProxy)
{
PropertyChangeListenerProxy proxy = (PropertyChangeListenerProxy) listener;
addPropertyChangeListener(proxy.getPropertyName(),
proxy.getListener());
}
else
{
listeners.add(new WeakReference<>(listener));
}
}
/**
* Add a PropertyChangeListener for a specific property. The listener will
* be invoked only when a call on firePropertyChange names that specific
* property. The same listener object may be added more than once. For each
* property, the listener will be invoked the number of times it was added
* for that property. If propertyName or listener is null, no exception is
* thrown and no action is taken.
*
* @param propertyName The name of the property to listen on.
* @param listener The PropertyChangeListener to be added.
*/
public void addPropertyChangeListener(String propertyName,
PropertyChangeListener listener)
{
ArrayList < WeakReference > propListeners = propertyListeners.get(propertyName);
if(propListeners == null)
{
propListeners = new ArrayList < WeakReference >();
propertyListeners.put(propertyName, propListeners);
}
propListeners.add(new WeakReference < PropertyChangeListener>(listener));
}
/**
* Remove a PropertyChangeListener from the listener list. This removes a
* PropertyChangeListener that was registered for all properties. If
* listener was added more than once to the same event source, it will be
* notified one less time after being removed. If listener is null, or was
* never added, no exception is thrown and no action is taken.
*
* @param listener The PropertyChangeListener to be rem ove
*/
public void removePropertyChangeListener(PropertyChangeListener listener)
{
for(int index = listeners.size() - 1; index >= 0; index--)
{
WeakReference ref = listeners.get(index);
PropertyChangeListener refListener = ref.get();
if(refListener != null)
{
if(refListener.equals(listener) == true)
{
listeners.remove(index);
}
}
else
{
listeners.remove(index);
}
}
}
/**
* Remove a PropertyChangeListener for a specific property. If listener was
* added more than once to the same event source for the specified property,
* it will be notified one less time after being removed. If propertyName
* is null, no exception is thrown and no action is taken. If listener is
* null, or was never added for the specified property, no exception is
* thrown and no action is taken.
*
* @param propertyName The name of the property that was listened on.
* @param listener The PropertyChangeListener to be removed.
*/
public void removePropertyChangeListener(String propertyName,
PropertyChangeListener listener)
{
ArrayList < WeakReference > propListeners = propertyListeners.get(propertyName);
if(propListeners != null)
{
for(int index = propListeners.size() - 1; index >= 0; index--)
{
WeakReference ref = propListeners.get(index);
PropertyChangeListener refListener = ref.get();
if(refListener != null)
{
if(refListener.equals(listener) == true)
{
propListeners.remove(index);
}
}
else
{
propListeners.remove(index);
}
}
}
}
/**
* Fires a propety change to all registered listeners. The event will also
* be sent to all child resource tables as well.
*
* @param name
* @param oldValue
* @param newValue
*/
private void firePropertyChange(String name, Object oldValue, Object newValue)
{
PropertyChangeEvent event = new PropertyChangeEvent(this, name, oldValue, newValue);
firePropertyChange(name, event);
}
private void firePropertyChange(String name, PropertyChangeEvent event)
{
fireEventAndCleanList(listeners, event);
ArrayList> propListeners = propertyListeners.get(name);
if (propListeners != null)
{
fireEventAndCleanList(propListeners, event);
}
for(int index = childrenTables.size() - 1; index >= 0; index--)
{
WeakReference < ResourceTable > childRef = childrenTables.get(index);
if(childRef.get() != null)
{
childRef.get().notifyPropertyChanged(name, event);
}
else
{
childrenTables.remove(index);
}
}
}
private void fireParentChangedChange(ResourceTable oldTable, ResourceTable newTable)
{
PropertyChangeEvent event = new PropertyChangeEvent(this, PARENT_RESOURCE_TABLE, oldTable, newTable);
fireEventAndCleanList(listeners, event);
// Since the parent table changed, the listeners property value may have also changed.
for(String key : propertyListeners.keySet())
{
// If this table does not contain the key, then the parent specified
// the value. Therefore notify that the reource changed.
if(properties.containsKey(key) == false)
{
Object oldResource = oldTable.getProperty(key);
Object newResource = getProperty(key);
if(oldResource.equals(newResource) == false)
{
firePropertyChange(key, oldResource, newResource);
}
}
}
for(int index = childrenTables.size() - 1; index >= 0; index--)
{
WeakReference < ResourceTable > childRef = childrenTables.get(index);
if(childRef.get() != null)
{
childRef.get().notifyPropertyChanged(PARENT_RESOURCE_TABLE, event);
}
else
{
childrenTables.remove(index);
}
}
}
private void fireEventAndCleanList(ArrayList > refListeners,
PropertyChangeEvent event)
{
for(int index = refListeners.size() - 1; index >= 0; index--)
{
WeakReference ref = refListeners.get(index);
PropertyChangeListener refListener = ref.get();
if(refListener != null)
{
refListener.propertyChange(event);
}
else
{
refListeners.remove(index);
}
}
}
/**
* Notifies that resource table that a property has been changes. This is
* usally sent by a parent resource table. If the resource is being
* overridden by the child resource table a property change event will not
* be sent to the child resource table, since the overriden value did not
* change.
*
* @param name the name of the property.
* @param event the event to send if the property is not overridden.
*/
private void notifyPropertyChanged(String name, PropertyChangeEvent event)
{
if(PARENT_RESOURCE_TABLE.equals(name) == true)
{
// There is nothing for me to do. If this table overrides the
// property, Do not notify listeners of the change. If this table
// does not override a property, then the parent that changed will
// notify via the property event. Therefore nothing to do.
}
else if(properties.containsKey(name) == false)
{
firePropertyChange(name, event);
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy