///
/// Copyright © 2003-2008 JetBrains s.r.o.
/// You may distribute under the terms of the GNU General Public License, as published by the Free Software Foundation, version 2 (see License.txt in the repository root folder).
///
using System;
using JetBrains.Omea.OpenAPI;
using System.Reflection;
using System.Xml;
using JetBrains.Omea.Base;
using System.Collections;
using System.IO;
using System.Drawing;
namespace JetBrains.Omea
{
/**
* IResourceIconProvider implementation based on an XML configuration
* section.
*/
internal class ConfigurableIconProvider: IResourceIconProvider, IOverlayIconProvider
{
private class ResourceIconCondition
{
private enum CondType { HasProp, PropValue, HasInLink };
private CondType _type;
private string _propName;
private string _propValue;
internal ResourceIconCondition( XmlNode node )
{
if ( node.Name == "prop" )
{
_type = CondType.PropValue;
}
else if ( node.Name == "hasprop" )
{
_type = CondType.HasProp;
}
else if ( node.Name == "hasinlink" )
{
_type = CondType.HasInLink;
}
else
{
throw new Exception( "Invalid icon condition " + node.Name );
}
_propName = XmlTools.GetRequiredAttribute( node, "name" );
if ( _type == CondType.PropValue )
{
_propValue = XmlTools.GetRequiredAttribute( node, "value" );
}
}
internal bool MatchResource( IResource res )
{
switch( _type )
{
case CondType.PropValue: return res.GetPropText( _propName ) == _propValue;
case CondType.HasProp: return res.HasProp( _propName );
case CondType.HasInLink: return res.GetLinksTo( null, _propName ).Count > 0;
default: return false;
}
}
}
private class ResourceIconInstance
{
internal string _name;
internal bool _isDefault;
internal ArrayList _conditions = new ArrayList();
internal ResourceIconInstance( XmlNode node )
{
_name = XmlTools.GetRequiredAttribute( node, "name" );
if ( XmlTools.GetIntAttribute( node, "default", 0 ) == 1 )
{
_isDefault = true;
}
foreach( XmlNode condNode in node.ChildNodes )
{
_conditions.Add( new ResourceIconCondition( condNode ) );
}
}
internal bool MatchResource( IResource res )
{
for( int i=0; i<_conditions.Count; i++ )
{
ResourceIconCondition cond = (ResourceIconCondition) _conditions [i];
if ( !cond.MatchResource( res ) )
return false;
}
return true;
}
}
private class ResourceTypeIconConfiguration
{
internal string _resType;
private ArrayList _condIconInstances = new ArrayList();
private ArrayList _overlayIconInstances = new ArrayList();
private ResourceIconInstance _uncondIconInstance;
private ResourceIconInstance _defaultIconInstance;
internal ResourceTypeIconConfiguration( XmlNode node )
{
_resType = XmlTools.GetRequiredAttribute( node, "type" );
foreach( XmlNode iconNode in node.SelectNodes( "icon" ) )
{
ResourceIconInstance iconInstance = new ResourceIconInstance( iconNode );
AddIconInstance( iconInstance );
}
foreach( XmlNode overlayNode in node.SelectNodes( "overlay" ) )
{
ResourceIconInstance iconInstance = new ResourceIconInstance( overlayNode );
_overlayIconInstances.Add( iconInstance );
}
}
internal void AddIconInstance( ResourceIconInstance iconInstance )
{
if ( iconInstance._conditions.Count == 0 )
{
if ( _uncondIconInstance != null )
{
throw new Exception( "There can be only one icon with no conditions for a resource type" );
}
_uncondIconInstance = iconInstance;
}
else
{
_condIconInstances.Add( iconInstance );
}
if ( iconInstance._isDefault )
{
if ( _defaultIconInstance != null )
{
throw new Exception( "There can be only one default icon for a resource type" );
}
_defaultIconInstance = iconInstance;
}
}
internal string GetResourceIconName( IResource res )
{
for( int i=0; i<_condIconInstances.Count; i++ )
{
ResourceIconInstance instance = (ResourceIconInstance) _condIconInstances [i];
if ( instance.MatchResource( res ) )
{
return instance._name;
}
}
if ( _uncondIconInstance != null )
{
return _uncondIconInstance._name;
}
return null;
}
internal string GetDefaultIconName()
{
if ( _defaultIconInstance != null )
{
return _defaultIconInstance._name;
}
if ( _uncondIconInstance != null )
{
return _uncondIconInstance._name;
}
return null;
}
internal string[] GetOverlayIconNames( IResource res )
{
ArrayList result = null;
for( int i=0; i<_overlayIconInstances.Count; i++ )
{
ResourceIconInstance instance = (ResourceIconInstance) _overlayIconInstances [i];
if ( instance.MatchResource( res ) )
{
if ( result == null )
{
result = new ArrayList();
}
result.Add( instance._name );
}
}
if ( result != null )
{
return (string[]) result.ToArray( typeof (string) );
}
return null;
}
}
private Assembly _pluginAssembly;
private string _defaultNamespace;
private Hashtable _resourceTypeMap = new Hashtable(); // resource type (string) -> ResourceTypeIconConfiguration
private Hashtable _iconMap = new Hashtable(); // icon name -> icon
public ConfigurableIconProvider( Assembly pluginAssembly, XmlNode node )
{
_pluginAssembly = pluginAssembly;
XmlAttribute attrNS = node.Attributes ["namespace"];
_defaultNamespace = (attrNS == null) ? "" : attrNS.Value;
foreach( XmlNode typeNode in node.SelectNodes( "icons" ) )
{
ResourceTypeIconConfiguration cfg = new ResourceTypeIconConfiguration( typeNode );
_resourceTypeMap [cfg._resType] = cfg;
}
// shortcut for resource types which have only one icon
foreach( XmlNode iconNode in node.SelectNodes( "icon" ) )
{
ResourceTypeIconConfiguration cfg = new ResourceTypeIconConfiguration( iconNode );
ResourceIconInstance instance = new ResourceIconInstance( iconNode );
cfg.AddIconInstance( instance );
_resourceTypeMap [cfg._resType] = cfg;
}
}
public Icon GetResourceIcon( IResource res )
{
ResourceTypeIconConfiguration cfg = (ResourceTypeIconConfiguration) _resourceTypeMap [res.Type];
if ( cfg == null )
return null;
string iconName = cfg.GetResourceIconName( res );
return LoadIconIfNew( iconName );
}
public Icon GetDefaultIcon( string resType )
{
ResourceTypeIconConfiguration cfg = (ResourceTypeIconConfiguration) _resourceTypeMap [resType];
if ( cfg == null )
return null;
string iconName = cfg.GetDefaultIconName();
return LoadIconIfNew( iconName );
}
public Icon[] GetOverlayIcons( IResource res )
{
ResourceTypeIconConfiguration cfg = (ResourceTypeIconConfiguration) _resourceTypeMap [res.Type];
if ( cfg == null )
return null;
string[] overlayIconNames = cfg.GetOverlayIconNames( res );
if ( overlayIconNames == null || overlayIconNames.Length == 0 )
{
return null;
}
Icon[] overlayIcons = new Icon [overlayIconNames.Length];
for( int i=0; i