Icon Delegates
Objective
You want to author an IconDelegate to display icon for a Windchill object type.
Background
The purpose of object icons is to allow the user to readily distinguish between different Windchill business objects in the Windchill UI. Its possible to associate an icon with a Modeled type while modeling the class. This icon will be used when an object of this type is displayed. In case of subtypes, the Type and Attribute Management utility allows the user to associate an icon to be used to represent this subtype in the UI. If the icon specified is an invalid or blank, the icon of the parent type is used. This behavior is accomplished using IconDelegates.
However, there are cases where the icons are determined dynamically by other factors, such as attributes on the object. The following table shows the OOTB IconDelegates available for some Windchill Types.
Windchill Type
|
IconDelegate
|
wt.part.WTPart
|
com.ptc.windchill.enterprise.part.comm ands.delegate.WTPartIconDelegate
|
wt.epm.EPMDocument
|
wt.epm.identity.EPMDocumentIconDelegate
|
wt.doc.WTDocument
|
wt.doc.DocumentIconDelegate
|
If the user needs different icons on types (other than the OOTB) or for his own modeled/subtypes, he needs to author custom IconDelegates for the respective type.
Scope/Applicability/Assumptions
User is not supposed to author custom IconDelegates for types for which OOTB IconDelegates exists.
Intended Outcome
User able to view the icons defined by his IconDelegate for the respective Windchill type objects.
Solution
Author custom IconDelegate for Windchill type to specify your icon.
Prerequisite knowledge
To achieve this objective, you need to have an understanding of the following:
• Java
• Windchill Type Identifiers
Solution Elements
Element
|
Type
|
Description
|
<custom_IconDelegate>. java
|
java
|
Your IcondDelegate
Run time Location:
<Windchill>\codebase\*
|
Your xconf file
|
xconf
|
Register your IconDelegate
Run time Location:
<Windchill>\codebase\*
|
Procedure – Authoring Custom IconDelegate
Windchill UI deals with objects either in Persistable form or in TypeInstance form and hence IconDelegates should be able to handle both the forms. The attributes that participate in determining the icon is easily available if you have the object in Persistable form. If the object is in a TypeInstance form and the attributes are not available, then the TypeInstance has to be inflated to get the attributes, which can degrade the performance. If its in a TypeInstance object, the icon and tool tip for the icon are available as an SCA attribute, which is defined in <Windchill>/codebase/LogicalAttributes.xml
<Class name="wt.fc.Persistable">
-------
<Property>
<LogicalForm>objectIcon</LogicalForm>
<ExternalForm>SCA|objectIcon</ExternalForm>
</Property>
<Property>
<!-- This attribute is populated by the SCA|objectIcon
function -->
<LogicalForm>objectTooltip</LogicalForm>
<ExternalForm>NPA|objectTooltip</ExternalForm>
</Property>
Authoring the custom IconDelegate
1. You can extend either wt.fc.IconDelegate or an existing subclass of wt.fc.IconDelegate.
2. There are few API’s that you need to over-ride, where you have to put your icon determining logic.
a. These two API’s returns an IconSelector object, which holds the information of the icon for the specific Windchill object.
API Signature
|
Description
|
public IconSelector getStandardIconSelector() throws WTException, IllegalAccessException, InvocationTargetException;
|
Get the standard selector for the icon
|
public IconSelector getOpenIconSelector() throws WTException, IllegalAccessException, InvocationTargetException;
|
Get a selector for when the object is opened (for example when a folder is opened)
|
b. This API returns the localized tooltip value that need to be shown for the icon.
API Signature
|
Description
|
public String getToolTip()
|
The tooltip to be shown with the icon.
|
c. This API is needed to handle TypeInstances. In the method, you have to check whether the available TypeInstance has all the minimum required attribute values to determine icon and tool tip. If not there is a need to inflate the TypeInstance.
API Signature
|
Description
|
protected Boolean inflateRequired()
|
Inflate Required, if TypeInstance doesn't have required attributes to calculate the icon/tool tip.
|
@Override
protected boolean inflateRequired() {
boolean need = super.inflateRequired();
TypeInstance ti = getTypeInstanceObject();
if(ti != null && !need){
//check you necessary attributes in TypeInstance
// to determine to inflate it or not.
}
}
return need;
}
d. This API is needed to handle TypeInstances. In the method, you have to add all the attributes that drive icon/tool tip determination. This will make sure that they are properly populated when you invoke getStandardIconSelector() or getOpenIconSelector().
API Signature
|
Description
|
protected void initAttributes(Set<AttributeTypeIdentifier> attributes)
|
Update <AttributeTypeIdentifier> with attributes that drive-determining icon/tool tip.
|
@Override
protected void initAttributes(Set<AttributeTypeIdentifier>
attributes) {
super.initAttributes(attributes);
//add your attributes here
}
3. IconDelegate defines a static helper method to create AttributeTypeIdentifier and TypeIdentifier objects that your subclass can use. e.g.
AttributeTypeIdentifier NAME_ATI = getIdentifier("name",
"wt.part.WTPart");
TypeIdentifier WTPART_TI = getIdentifier("wt.part.WTPart",
null);
4. The getObject() API will convert the current TypeInstance to a Persistable, if not available. Hence its usage should be avoided in favor of getObject(false).
Coding Pattern
Many of the IconDelegate subclasses now use an internal "params" object to encapsulate whether or not they are working with a Persistable or a TypeInstance. The params object has simple properties that the icon resolution logic can use, regardless of whether the properties were populated from a Persistable or TypeInstance.
AttributeTypeIdentifier PERSONAL_CABINET_ATI =
getIdentifier("personalCabinet", "wt.folder.Cabinet");
TypeIdentifier CABINET_TID = getIdentifier("wt.folder.Cabinet",
null);
protected void initAttributes(Set<AttributeTypeIdentifier>
attributes) {
super.initAttributes(attributes);
attributes.add(PERSONAL_CABINET_ATI);
}
private static class ObjectParams {
Cabinet cabinet = null;
TypeInstance ti = null;
ObjectParams(Cabinet cabinet){
if(cabinet != null)
this.cabinet = cabinet;
}
ObjectParams(TypeInstance ti){
if(ti != null)
this.ti = ti;
}
void reSetObject(Cabinet cabinet){
if(cabinet != null)
this.cabinet = cabinet;
}
boolean isPersonalCabinet(){
if(cabinet != null){
return (cabinet.isPersonalCabinet());
}else{
return (Boolean)ti.get(PERSONAL_CABINET_ATI);
}
}
}
protected boolean inflateRequired() {
boolean need = false;
TypeInstance ti = getTypeInstanceObject();
if(ti != null){
need = super.inflateRequired();
if(!need){
if(ti.get(PERSONAL_CABINET_ATI) == null){ // should contain
PERSONAL_CABINET_ATI
need = true;
}
}
}
return need;
}
private ObjectParams getObjectParams(){
ObjectParams object_params = null;
WTObject obj = super.getObject(false);
TypeInstance ti = getTypeInstanceObject();
if (obj != null && obj instanceof Cabinet) {//Object is available
object_params = new ObjectParams((Cabinet)obj);
} else if(ti != null) {//TypeInstance is available
if(inflateRequired()){
obj = super.getObject(true);
if (obj != null && obj instanceof Cabinet) {
object_params = new ObjectParams((Cabinet)obj);
}else{
object_params = null;
}
} else {
object_params = new ObjectParams(ti);
}
}
return object_params;
}
public IconSelector getStandardIconSelector()
throws WTException, IllegalAccessException,
InvocationTargetException {
IconSelector icon = null;
ObjectParams object_params = getObjectParams();
if(object_params != null){
boolean is_personal_cabinet =
object_params.isPersonalCabinet();
if(is_personal_cabinet)
icon = new IconSelector(PERSONAL_ICON);
else
icon = new IconSelector(SHARED_ICON);
}
if (icon == null)
icon = super.getStandardIconSelector();
return icon;
}
Registering the custom IconDelegate
You need to register your custom IconDelegate in an xconf file and propagate into the <Windchill>/codebase/service.properties file via xconfmanager.
<Service context="default" name="wt.fc.IconDelegate">
<Option cardinality="duplicate" requestor="<your_type>"
serviceClass="<your_IconDelegate>"/>
</Service>