/*
uiml.net: a Uiml .NET renderer (http://research.edm.uhasselt.be/kris/research/uiml.net)
Copyright (C) 2005 Kris Luyten (kris.luyten@uhasselt.be)
Expertise Centre for Digital Media (http://www.edm.uhasselt.be)
Hasselt University
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public License
as published by the Free Software Foundation; either version 2.1
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
namespace Uiml {
using System;
using System.Xml;
using System.Collections;
using Uiml.LayoutManagement;
public class UimlDocument : IUimlElement, IUimlComponent, ICloneable {
private Interface m_interface;
private ArrayList m_peers;
private Head m_head;
private bool m_hasLayout;
private ConstraintSystem m_solver = null;
///
///Reads a UIML document in memory specified in fName
///
public UimlDocument(String fName)
{
try
{
XmlDocument doc = new XmlDocument();
doc.Load(fName);
Load(doc);
}
catch(Exception e)
{
Console.WriteLine("Error loading {0} ({1})", fName, e);
}
}
public UimlDocument(XmlNode uimlTopNode)
{
Load(uimlTopNode);
}
///
///private parameterless constructor for cloning
///
private UimlDocument()
{
}
private void Load(XmlNode uimlTopNode)
{
m_peers = new ArrayList();
Process(uimlTopNode);
m_interface.AttachPeers(m_peers);
}
public void Process(XmlNode n)
{
if(n.Name == Head.IAM)
m_head = new Head(n);
if(n.Name == Peer.IAM)
AddPeer(new Peer(n));
else if(n.Name == Interface.IAM)
m_interface = new Interface(n);
else if(n.Name == Template.IAM)
TemplateRepository.Instance.Register(new Template(n));
else if(n.HasChildNodes)
{
XmlNodeList xnl = n.ChildNodes;
for(int i=0; i
/// Searches for a specific vocabulary to map the classes on
///
public Peer SearchPeers(string pattern)
{
IEnumerator enumPeers = Peers;
while(enumPeers.MoveNext())
{
if(((Peer)enumPeers.Current).Provides(pattern))
return ((Peer)enumPeers.Current);
}
throw new VocabularyUnavailableException(pattern);
}
///
///For now, only a single vocabulary peer will be taken into account
///
public String Vocabulary
{
get
{
IEnumerator enumPeers = Peers;
while(enumPeers.MoveNext())
{
return ((Peer)enumPeers.Current).GetVocabulary().Identifier;
}
return "";
}
}
public void Connect(Object o)
{
//TODO: support multiple structures
// connect to the top part
((Structure)UInterface.UStructure[0]).Top.Connect(o, this);
ExternalObjects.Instance.Add(o.GetType().ToString(),o);
// connect to the rules
if(UInterface.UBehavior != null)
{
IEnumerator er = ((Behavior)UInterface.UBehavior[0]).Rules;
while(er.MoveNext())
{
((Executing.Rule)er.Current).Connect(o);
}
}
}
public void Disconnect(Object o)
{
((Structure)UInterface.UStructure[0]).Top.Disconnect(o, this);
ExternalObjects.Instance.Remove(o);
if(UInterface.UBehavior != null)
{
IEnumerator er = ((Behavior)UInterface.UBehavior[0]).Rules;
while(er.MoveNext())
{
((Executing.Rule)er.Current).Disconnect(o);
}
}
}
public void Connect(Object o, String identifier)
{
//TODO: support multiple structures
Console.WriteLine(UInterface.UStructure);
Console.WriteLine(UInterface.UStructure[0]);
Part p = ((Structure)UInterface.UStructure[0]).SearchPart(identifier);
if (p != null)
p.Connect(o, this);
}
/**
* Search the part of the interface that matches identifier.
**/
public Part SearchPart(String searchfor)
{
//TODO: support multiple structures
Structure t = (Structure)UInterface.UStructure[0];
Part p = (Part)t.SearchPart(searchfor);
return p;
//return ((Structure)UInterface.UStructure[0]).SearchPart(searchfor);
}
public void SolveLayoutProperties(Uiml.Rendering.IRenderer r)
{
try
{
LayoutPropertyRepository.Instance.InitializeProperties(this, r);
ArrayList layouts = new ArrayList();
// process layouts
Part top = ((Structure) UInterface.UStructure[0]).Top;
top.GetLayouts(ref layouts);
foreach (Layout l in layouts)
l.SolveLayoutProperties();
m_hasLayout = layouts.Count > 0;
if (HasLayout)
{
// create constraint system
m_solver = new ConstraintSystem(layouts);
m_solver.Solve();
}
}
catch(IndexOutOfRangeException ioore)
{
Console.WriteLine("No layout specified, continuing anyway....");
}
}
public void ResolveLayoutProperties(Uiml.Rendering.IRenderer r)
{
if (HasSolver)
{
Solver.Resolve();
}
}
public ArrayList Children
{
get
{
ArrayList al = new ArrayList();
al.Add(UHead);
al.Add(UInterface);
al.Add(m_peers);
return al;
}
}
public string PartTree()
{
return ((Structure) UInterface.UStructure[0]).PartTree();
}
//ICloneable methods:
public object Clone()
{
UimlDocument iamclone = new UimlDocument();
if (UHead == null)
iamclone.UHead = null;
else
iamclone.UHead = (Head)UHead.Clone();
iamclone.UInterface = (Interface)UInterface.Clone();
return iamclone;
}
// IUimlComponent methods:
//public ArrayList Children { get ; } //This method already exist to return a "complete" UIML document in an ArrayList
public void Add(string pattern, IUimlComponent component) { /* do nothing */ }
public void Remove(IUimlComponent component) { /* do nothing */ }
public UimlComposite Composite
{
get { return null; }
}
public Hashtable CompChildren
{
get {return null; }
}
public ConstraintSystem Solver
{
get { return m_solver; }
}
public bool HasSolver
{
get { return Solver != null; }
}
public bool HasLayout
{
get { return m_hasLayout; }
}
public const string PEER = "peers";
public const string UIML = "uiml";
public const string INTERFACE = "interface";
public const string STRUCTURE = "structure";
public const string STYLE = "style";
public const string PROPERTY = "property";
public const string CONSTANT = "constant";
}
}