#region Disclaimer / License
// Copyright (C) 2011, Jackie Ng
// http://trac.osgeo.org/mapguide/wiki/maestro, jumpinjackie@gmail.com
//
// This library 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 library 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 library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
//
#endregion
using System;
using System.Collections.Generic;
using System.Text;
using OSGeo.MapGuide.MaestroAPI.Services;
using Maestro.Editors.Common;
using System.ComponentModel;
using System.IO;
using OSGeo.MapGuide.MaestroAPI.Resource;
using Maestro.Editors.Generic;
using OSGeo.MapGuide.MaestroAPI;
using OSGeo.MapGuide.MaestroAPI.Schema;
namespace Maestro.Editors
{
///
/// A base class for providing editor services for a given resource being edited
///
public abstract class ResourceEditorServiceBase : IEditorService
{
///
/// The server connection
///
protected IServerConnection _conn;
///
/// The resource being edited
///
protected IResource _editCopy;
///
/// Initializes a new instance of the class.
///
/// The resource ID.
/// The conn.
///
/// The editor service does not do live edits of the resource you pass in to this constructor
///
/// When an editor is modifying a resource, it is not modifying the resource you specify here. It is instead modifying a
/// session-based copy of the resource that is created internally by the editor service. On a save action (a call to
/// ), the session-based copy is copied back into the resource
/// id you specified, overwriting its contents and data files.
///
/// This provides an extra level of safety against unintentional edits, as such edits will only apply to the session-copy, only
/// being committed back to the resource id you specified on an explicit save action.
///
protected ResourceEditorServiceBase(string resourceID, IServerConnection conn)
{
this.IsNew = ResourceIdentifier.IsSessionBased(resourceID);
this.ResourceID = resourceID;
_conn = conn;
this.PreviewLocale = "en"; //NOXLATE
}
///
/// Gets the locale to use for previewing
///
public virtual string PreviewLocale
{
get;
set;
}
///
/// Raised when the edited resource has changed
///
public event EventHandler DirtyStateChanged;
///
/// Edits the expression.
///
/// The current expr.
/// The class def.
/// Name of the provider.
/// The feature source id.
/// If true, FDO stylization functions are also included in the function list
///
public string EditExpression(string currentExpr, ClassDefinition classDef, string providerName, string featureSourceId, bool attachStylizationFunctions)
{
var ed = FdoExpressionEditorFactory.Create(); new ExpressionEditor();
var caps = this.FeatureService.GetProviderCapabilities(providerName);
ed.Initialize(this.FeatureService, caps, classDef, featureSourceId, attachStylizationFunctions);
ed.Expression = currentExpr;
if (ed.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
return ed.Expression;
}
return null;
}
///
/// Initiates the editing process. The resource to be edited is copied to the session repository and
/// a deserialized version is returned from this copy. Subsequent calls will return the same reference
/// to this resource object.
///
///
/// A deserialized version of a session-copy of the resource to be edited
///
public IResource GetEditedResource()
{
if (_editCopy == null)
{
string copy = _conn.GenerateSessionResourceId(ResourceIdentifier.GetResourceType(this.ResourceID));
_conn.ResourceService.CopyResource(this.ResourceID, copy, true);
_editCopy = _conn.ResourceService.GetResource(copy);
_editCopy.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler(OnResourcePropertyChanged);
}
return _editCopy;
}
///
/// Called when [resource property changed].
///
/// The sender.
/// The instance containing the event data.
protected void OnResourcePropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
MarkDirty();
}
///
/// Called when [dirty state changed].
///
protected void OnDirtyStateChanged()
{
var handler = this.DirtyStateChanged;
if (handler != null)
handler(this, EventArgs.Empty);
}
///
/// Indicates whether the edited resource has unsaved changes
///
public bool IsDirty
{
get;
private set;
}
///
/// Forces the edited resource to be marked as dirty
///
public void MarkDirty()
{
this.IsDirty = true;
OnDirtyStateChanged();
}
///
/// Indicates whether the edited resource is a new resource
///
public bool IsNew
{
get;
private set;
}
///
/// Opens the specified URL
///
///
public abstract void OpenUrl(string url);
///
/// Gets the resource ID of the resource, whose session-copy is being edited
///
public string ResourceID { get; private set; }
///
/// Invokes a prompt to select a resource of any type
///
///
public string SelectAnyResource()
{
var picker = new ResourcePicker(_conn.ResourceService, ResourcePickerMode.OpenResource);
if (picker.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
return picker.ResourceID;
}
return string.Empty;
}
///
/// Invokes a prompt to select a resource of the specified type
///
///
///
public string SelectResource(OSGeo.MapGuide.MaestroAPI.ResourceTypes resType)
{
var picker = new ResourcePicker(_conn.ResourceService, resType, ResourcePickerMode.OpenResource);
if (picker.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
return picker.ResourceID;
}
return string.Empty;
}
///
/// Invokes a prompt to select a folder
///
///
public string SelectFolder()
{
var picker = new ResourcePicker(_conn.ResourceService, ResourcePickerMode.OpenFolder);
if (picker.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
return picker.ResourceID;
}
return string.Empty;
}
///
/// Invokes a prompt to select a file from an unmanaged alias
///
///
///
///
public abstract string SelectUnmanagedData(string startPath, System.Collections.Specialized.NameValueCollection fileTypes);
///
/// Saves the edited resource. The session copy, which holds the current changes is copied back
/// to the original resource ID.
///
public void Save()
{
if (!OnBeforeSave())
{
_conn.ResourceService.CopyResource(this.EditedResourceID, this.ResourceID, true);
this.IsDirty = false;
OnDirtyStateChanged();
OnSaved();
}
}
///
/// Saves the edited resource under a different resource ID. The session copy, which holds the current changes is copied back
/// to the specified resource ID
///
///
public void SaveAs(string resourceID)
{
if (ResourceIdentifier.IsSessionBased(resourceID))
throw new ArgumentException(Strings.NotSessionBasedId); //LOCALIZE
if (!OnBeforeSave())
{
//_conn.ResourceService.SaveResourceAs(_editCopy, resourceID);
_conn.ResourceService.CopyResource(_editCopy.ResourceID, resourceID, true);
this.ResourceID = resourceID;
this.IsNew = false;
this.IsDirty = false;
OnDirtyStateChanged();
OnSaved();
}
}
///
/// Indicates whether an upgrade for this resource is available
///
public bool IsUpgradeAvailable
{
get
{
if (_editCopy == null)
return false;
return _conn.Capabilities.GetMaxSupportedResourceVersion(_editCopy.ResourceType) > _editCopy.ResourceVersion;
}
}
///
/// Gets the resource ID of the actively edited resource
///
public string EditedResourceID
{
get { return _editCopy.ResourceID; }
}
///
/// Registers a custom notifier
///
///
public void RegisterCustomNotifier(INotifyResourceChanged irc)
{
irc.ResourceChanged += (sender, e) =>
{
this.IsDirty = true;
OnDirtyStateChanged();
};
}
///
/// Updates the session copy's resource content
///
///
public void UpdateResourceContent(string xml)
{
try
{
using (var ms = new MemoryStream(Encoding.UTF8.GetBytes(xml)))
{
_conn.ResourceService.SetResourceXmlData(this.EditedResourceID, ms);
}
}
catch (Exception ex)
{
XmlContentErrorDialog.CheckAndHandle(ex, xml, false);
}
}
///
/// Called when [before save].
///
///
private bool OnBeforeSave()
{
var e = new CancelEventArgs();
var handler = this.BeforeSave;
if (handler != null)
handler(this, e);
return e.Cancel;
}
///
/// Raised before a save operation commences
///
public event System.ComponentModel.CancelEventHandler BeforeSave;
///
/// Gets the associated feature service
///
public IFeatureService FeatureService
{
get { return _conn.FeatureService; }
}
///
/// Gets the associated resource service
///
public IResourceService ResourceService
{
get { return _conn.ResourceService; }
}
///
/// Invokes a prompt to select the coordinate system
///
///
public string GetCoordinateSystem()
{
var dlg = new CoordinateSystemPicker(_conn.CoordinateSystemCatalog);
if (dlg.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
return dlg.SelectedCoordSys.WKT;
}
return string.Empty;
}
///
/// Gets the associated drawing service
///
public IDrawingService DrawingService
{
get { return (IDrawingService)_conn.GetService((int)ServiceType.Drawing); }
}
///
/// Forces the the event. Normally the databinding
/// system should auto-flag dirty state, only call this if you don't utilise this
/// databinding system.
///
public void HasChanged()
{
this.IsDirty = true;
OnDirtyStateChanged();
}
///
/// Gets the session id
///
public string SessionID
{
get { return _conn.SessionID; }
}
///
/// Indicates if a specified custom command is supported and can be created
///
///
///
public bool SupportsCommand(OSGeo.MapGuide.MaestroAPI.Commands.CommandType cmdType)
{
return Array.IndexOf(_conn.Capabilities.SupportedCommands, (int)cmdType) >= 0;
}
///
/// Create a custom command
///
///
///
public OSGeo.MapGuide.MaestroAPI.Commands.ICommand CreateCommand(OSGeo.MapGuide.MaestroAPI.Commands.CommandType cmdType)
{
return _conn.CreateCommand((int)cmdType);
}
///
/// Raises a request to refresh the Site Explorer
///
public abstract void RequestRefresh();
///
/// Raises a request to refresh the Site Explorer at the specified folder id
///
///
public abstract void RequestRefresh(string folderId);
///
/// Called when [saved].
///
protected void OnSaved()
{
var handler = this.Saved;
if (handler != null)
handler(this, EventArgs.Empty);
}
///
/// Raised when the edited resource is saved
///
public event EventHandler Saved;
///
/// Synchronises changes in the in-memory resource back to the session repository. This is usually called
/// before validation of the edited resource begins.
///
public void SyncSessionCopy()
{
string xml = ResourceTypeRegistry.SerializeAsString(_editCopy);
try
{
using (var ms = new MemoryStream(Encoding.UTF8.GetBytes(xml)))
{
this.ResourceService.SetResourceXmlData(_editCopy.ResourceID, ms);
}
}
catch (Exception ex)
{
XmlContentErrorDialog.CheckAndHandle(ex, xml, false);
}
}
///
/// Gets the MapGuide Server version
///
public Version SiteVersion
{
get { return _conn.SiteVersion; }
}
///
/// Opens the specified resource
///
///
public abstract void OpenResource(string resourceId);
///
/// Gets the suggested save folder for a "save as" operation
///
public string SuggestedSaveFolder
{
get;
set;
}
///
/// Gets the value of a custom connection property
///
///
///
public object GetCustomProperty(string name)
{
return _conn.GetCustomProperty(name);
}
///
/// Gets the service of the specified type
///
///
///
public IService GetService(int serviceType)
{
return _conn.GetService(serviceType);
}
///
/// Gets the supported services
///
public int[] SupportedServiceTypes
{
get { return _conn.Capabilities.SupportedServices; }
}
///
/// Runs the specified process with the given arguments
///
///
///
public abstract void RunProcess(string processName, params string[] args);
///
/// Performs processing before a resource preview is generated
///
public void PrePreviewProcess()
{
SyncSessionCopy();
var handler = this.BeforePreview;
if (handler != null)
handler(this, EventArgs.Empty);
}
///
/// Raised when processing is required before a preview is generated
///
public event EventHandler BeforePreview;
}
}