Permalink
Browse files

2008-05-13 Mike Kestner <mkestner@novell.com>

	* libsteticui/Application.cs: refactor to split out isolated backend
	and inprocess backend cases.  Dispose additions.  Destroy handling for
	the public accessors.
	* libsteticui/ApplicationBackendController.cs: use IsolatedApplication.
	* libsteticui/PluggableWidget.cs: IsolatedApplication handling and
	dispose rework.
	* libsteticui/Project.cs: ditto.
	* stetic/Stetic.cs: use new ApplicationFactory.

svn path=/trunk/stetic/; revision=103105
  • Loading branch information...
1 parent e3639c0 commit 6bed5d019446f5a623fa0d3bc7200a56e48c92bc @mkestner mkestner committed May 13, 2008
Showing with 269 additions and 204 deletions.
  1. +11 −0 ChangeLog
  2. +222 −175 libsteticui/Application.cs
  3. +2 −2 libsteticui/ApplicationBackendController.cs
  4. +18 −19 libsteticui/PluggableWidget.cs
  5. +14 −6 libsteticui/Project.cs
  6. +2 −2 stetic/Stetic.cs
View
11 ChangeLog
@@ -1,5 +1,16 @@
2008-05-13 Mike Kestner <mkestner@novell.com>
+ * libsteticui/Application.cs: refactor to split out isolated backend
+ and inprocess backend cases. Dispose additions. Destroy handling for
+ the public accessors.
+ * libsteticui/ApplicationBackendController.cs: use IsolatedApplication.
+ * libsteticui/PluggableWidget.cs: IsolatedApplication handling and
+ dispose rework.
+ * libsteticui/Project.cs: ditto.
+ * stetic/Stetic.cs: use new ApplicationFactory.
+
+2008-05-13 Mike Kestner <mkestner@novell.com>
+
* libsteticui/AssemblyResolver.cs: update to JBs latest Linker version.
* libsteticui/CecilWidgetLibrary.cs: use new cache API.
* libsteticui/LibraryCache.cs: rewritten to use instances,
View
397 libsteticui/Application.cs
@@ -25,16 +25,172 @@ public enum IsolationMode
public delegate string AssemblyResolverCallback (string assemblyName);
- public class Application: MarshalByRefObject, IDisposable
- {
- ApplicationBackend backend;
- bool externalBackend;
+ public static class ApplicationFactory {
+
+ public static Application CreateApplication (IsolationMode mode)
+ {
+ switch (mode) {
+ case IsolationMode.None:
+ return new LocalApplication ();
+ case IsolationMode.ProcessTcp:
+ case IsolationMode.ProcessUnix:
+ return new IsolatedApplication (mode);
+ default:
+ throw new ArgumentException ("mode");
+ }
+ }
+ }
+
+ internal class IsolatedApplication : Application {
+
string channelId;
ApplicationBackendController backendController;
+
+ string RegisterRemotingChannel (IsolationMode mode)
+ {
+ string remotingChannel;
+ if (mode == IsolationMode.ProcessTcp) {
+ remotingChannel = "tcp";
+ IChannel ch = ChannelServices.GetChannel ("tcp");
+ if (ch == null) {
+ ChannelServices.RegisterChannel (new TcpChannel (0));
+ }
+ } else {
+ remotingChannel = "unix";
+ IChannel ch = ChannelServices.GetChannel ("unix");
+ if (ch == null) {
+ string unixRemotingFile = Path.GetTempFileName ();
+ ChannelServices.RegisterChannel (new UnixChannel (unixRemotingFile));
+ }
+ }
+ return remotingChannel;
+ }
+
+ public IsolatedApplication (IsolationMode mode)
+ {
+ if (mode == IsolationMode.None)
+ throw new ArgumentException ("mode");
+ channelId = RegisterRemotingChannel (mode);
+ backendController = new ApplicationBackendController (this, channelId);
+ backendController.StartBackend ();
+ OnBackendChanged (false);
+ }
+
+ public override void Dispose ()
+ {
+ base.Dispose ();
+ backendController.StopBackend (true);
+ }
+
+ public event BackendChangingHandler BackendChanging;
+ public event BackendChangedHandler BackendChanged;
+
+ void OnNewBackendStarted (object ob, EventArgs args)
+ {
+ OnBackendChanging ();
+ ApplicationBackendController oldBackend = backendController;
+ backendController = (ApplicationBackendController) ob;
+ OnBackendChanged (true);
+ oldBackend.StopBackend (false);
+ }
+
+ void OnBackendStopped (object ob, EventArgs args)
+ {
+ // The backend process crashed, try to restart it
+ Backend = null;
+ backendController = new ApplicationBackendController (this, channelId);
+ backendController.StartBackend ();
+ OnBackendChanged (true);
+ }
+ void OnBackendChanged (bool notify)
+ {
+ ApplicationBackend oldBackend = Backend;
+
+ Backend = backendController.Backend;
+ backendController.Stopped += OnBackendStopped;
+ UpdateWidgetLibraries (false, false);
+ ClearCollections ();
+ if (notify && BackendChanged != null)
+ BackendChanged (oldBackend);
+
+ Backend.ActiveProject = ActiveProject != null ? ActiveProject.ProjectBackend : null;
+ }
+
+ void OnBackendChanging ()
+ {
+ Backend.GlobalWidgetLibraries = widgetLibraries;
+ if (BackendChanging != null)
+ BackendChanging ();
+ }
+
+ internal override void RestartBackend ()
+ {
+ // The backend process needs to be restarted.
+ // This is done in background.
+
+ ThreadPool.QueueUserWorkItem (delegate {
+ try {
+ // Start the new backend
+ ApplicationBackendController newController = new ApplicationBackendController (this, channelId);
+ newController.StartBackend ();
+ Gtk.Application.Invoke (newController, EventArgs.Empty, OnNewBackendStarted);
+ } catch {
+ // FIXME: show an error message
+ }
+ });
+ }
+
+ internal override ComponentType CreateComponentType (string typeName)
+ {
+ string desc = null, className = null, category = null, targetGtkVersion = null, library = null;
+ Gdk.Pixbuf px = null;
+
+ byte[] icon;
+
+ if (Backend.GetClassDescriptorInfo (typeName, out desc, out className, out category, out targetGtkVersion, out library, out icon) && icon != null)
+ px = new Gdk.Pixbuf (icon);
+
+ if (px == null)
+ px = ComponentType.Unknown.Icon;
+
+ if (desc == null)
+ desc = typeName;
+
+ return new ComponentType (this, typeName, desc, className, category, targetGtkVersion, library, px);
+ }
+ }
+
+ internal class LocalApplication : Application {
+
+ public LocalApplication ()
+ {
+ Backend = new ApplicationBackend (this);
+ }
+
+ public override void Dispose ()
+ {
+ base.Dispose ();
+ Backend.Dispose ();
+ }
+
+ internal override ComponentType CreateComponentType (string typeName)
+ {
+ ClassDescriptor cls = Registry.LookupClassByName (typeName);
+ if (cls == null)
+ return null;
+
+ return new ComponentType (this, typeName, cls.Label, cls.WrappedTypeName, cls.Category, cls.TargetGtkVersion, cls.Library.Name, cls.Icon);
+ }
+ }
+
+ public abstract class Application : MarshalByRefObject, IDisposable {
+
+ ApplicationBackend backend;
+
Hashtable components = new Hashtable ();
Hashtable types = new Hashtable ();
- ArrayList widgetLibraries = new ArrayList ();
+ internal ArrayList widgetLibraries = new ArrayList ();
ArrayList projects = new ArrayList ();
Project activeProject;
Designer activeDesigner;
@@ -48,32 +204,14 @@ public class Application: MarshalByRefObject, IDisposable
static Hashtable libraryCheckCache;
- internal event BackendChangingHandler BackendChanging;
- internal event BackendChangedHandler BackendChanged;
- internal event EventHandler Disposing;
-
- public Application (IsolationMode mode)
- {
- if (mode == IsolationMode.None) {
- backend = new ApplicationBackend (this);
- externalBackend = false;
- } else {
- externalBackend = true;
- channelId = RegisterRemotingChannel (mode);
- backendController = new ApplicationBackendController (this, channelId);
- backendController.StartBackend ();
- OnBackendChanged (false);
- }
- }
-
public AssemblyResolverCallback WidgetLibraryResolver {
get { return Backend.WidgetLibraryResolver; }
set { Backend.WidgetLibraryResolver = value; }
}
public bool ShowNonContainerWarning {
- get { return backend.ShowNonContainerWarning; }
- set { backend.ShowNonContainerWarning = value; }
+ get { return Backend.ShowNonContainerWarning; }
+ set { Backend.ShowNonContainerWarning = value; }
}
// Loads the libraries registered in the projects or in the application.
@@ -84,67 +222,12 @@ public void UpdateWidgetLibraries (bool forceUnload)
UpdateWidgetLibraries (true, forceUnload);
}
- internal void UpdateWidgetLibraries (bool allowBackendRestart, bool forceUnload)
+ internal virtual void RestartBackend ()
{
- // Collect libraries from the project and from the application
-
- ArrayList assemblies = new ArrayList ();
- assemblies.AddRange (widgetLibraries);
-
- ArrayList projectBackends = new ArrayList ();
- foreach (Project p in projects)
- if (p.IsBackendLoaded)
- projectBackends.Add (p.ProjectBackend);
-
- if (!Backend.UpdateLibraries (assemblies, projectBackends, allowBackendRestart, forceUnload))
- {
- // The backend process needs to be restarted.
- // This is done in background.
-
- ThreadPool.QueueUserWorkItem (delegate {
- try {
- // Start the new backend
- ApplicationBackendController newController = new ApplicationBackendController (this, channelId);
- newController.StartBackend ();
- Gtk.Application.Invoke (newController, EventArgs.Empty, OnNewBackendStarted);
- } catch {
- // FIXME: show an error message
- }
- });
- }
}
-
- void OnNewBackendStarted (object ob, EventArgs args)
- {
- // The new backend is running, just do the switch
-
- OnBackendChanging ();
-
- ApplicationBackendController oldBackend = backendController;
- backendController = (ApplicationBackendController) ob;
-
- OnBackendChanged (true);
- // The old backend can now be safely stopped
- oldBackend.StopBackend (false);
- }
-
- void OnBackendStopped (object ob, EventArgs args)
+ protected void ClearCollections ()
{
- // The backend process crashed, try to restart it
- backend = null;
- backendController = new ApplicationBackendController (this, channelId);
- backendController.StartBackend ();
- OnBackendChanged (true);
- }
-
- void OnBackendChanged (bool notify)
- {
- ApplicationBackend oldBackend = backend;
-
- backend = backendController.Backend;
- backendController.Stopped += OnBackendStopped;
- UpdateWidgetLibraries (false, false);
lock (types) {
types.Clear ();
}
@@ -161,38 +244,22 @@ void OnBackendChanged (bool notify)
foreach (Component c in comps) {
c.Dispose ();
}
-
- if (notify && BackendChanged != null)
- BackendChanged (oldBackend);
-
- backend.ActiveProject = activeProject != null ? activeProject.ProjectBackend : null;
}
-
- void OnBackendChanging ()
- {
- backend.GlobalWidgetLibraries = widgetLibraries;
- if (BackendChanging != null)
- BackendChanging ();
- }
-
- internal string RegisterRemotingChannel (IsolationMode mode)
+
+ internal void UpdateWidgetLibraries (bool allowBackendRestart, bool forceUnload)
{
- string remotingChannel;
- if (mode == IsolationMode.ProcessTcp) {
- remotingChannel = "tcp";
- IChannel ch = ChannelServices.GetChannel ("tcp");
- if (ch == null) {
- ChannelServices.RegisterChannel (new TcpChannel (0));
- }
- } else {
- remotingChannel = "unix";
- IChannel ch = ChannelServices.GetChannel ("unix");
- if (ch == null) {
- string unixRemotingFile = Path.GetTempFileName ();
- ChannelServices.RegisterChannel (new UnixChannel (unixRemotingFile));
- }
- }
- return remotingChannel;
+ // Collect libraries from the project and from the application
+
+ ArrayList assemblies = new ArrayList ();
+ assemblies.AddRange (widgetLibraries);
+
+ ArrayList projectBackends = new ArrayList ();
+ foreach (Project p in projects)
+ if (p.IsBackendLoaded)
+ projectBackends.Add (p.ProjectBackend);
+
+ if (!Backend.UpdateLibraries (assemblies, projectBackends, allowBackendRestart, forceUnload))
+ RestartBackend ();
}
public virtual void Dispose ()
@@ -201,46 +268,54 @@ public virtual void Dispose ()
return;
disposed = true;
- if (Disposing != null)
- Disposing (this, EventArgs.Empty);
- if (externalBackend) {
- backendController.StopBackend (true);
- } else {
- backend.Dispose ();
- }
+ ClearCollections ();
+ ArrayList copy = (ArrayList) projects.Clone ();
+ foreach (Project p in copy)
+ p.Dispose ();
+ if (propertiesWidget != null)
+ propertiesWidget.Dispose ();
+ if (paletteWidget != null)
+ paletteWidget.Dispose ();
+ if (projectWidget != null)
+ projectWidget.Dispose ();
+ if (signalsWidget != null)
+ signalsWidget.Dispose ();
+ widgetLibraries.Clear ();
System.Runtime.Remoting.RemotingServices.Disconnect (this);
}
- internal bool Disposed {
- get { return disposed; }
- }
-
public override object InitializeLifetimeService ()
{
// Will be disconnected when calling Dispose
return null;
}
- internal ApplicationBackend Backend {
- get {
- if (disposed)
- throw new InvalidOperationException ("Application has been disposed");
- return backend;
- }
+ internal ApplicationBackend Backend {
+ get { return backend; }
+ set { backend = value; }
+ }
+
+ void ProjectDisposed (object sender, EventArgs args)
+ {
+ projects.Remove (sender as Project);
+ if (!disposed)
+ UpdateWidgetLibraries (false, false);
}
public Project LoadProject (string path)
{
Project p = new Project (this);
p.Load (path);
projects.Add (p);
+ p.Disposed += ProjectDisposed;
return p;
}
public Project CreateProject ()
{
Project p = new Project (this);
projects.Add (p);
+ p.Disposed += ProjectDisposed;
return p;
}
@@ -256,15 +331,15 @@ public void AddWidgetLibrary (string assemblyPath)
{
if (!widgetLibraries.Contains (assemblyPath)) {
widgetLibraries.Add (assemblyPath);
- Backend.GlobalWidgetLibraries = widgetLibraries;
+ Backend.GlobalWidgetLibraries = widgetLibraries;
UpdateWidgetLibraries (false, false);
}
}
public void RemoveWidgetLibrary (string assemblyPath)
{
widgetLibraries.Remove (assemblyPath);
- Backend.GlobalWidgetLibraries = widgetLibraries;
+ Backend.GlobalWidgetLibraries = widgetLibraries;
UpdateWidgetLibraries (false, false);
}
@@ -277,7 +352,7 @@ public bool IsWidgetLibrary (string assemblyRef)
{
ImportContext ic = new ImportContext ();
ic.App = this.Backend;
- return Application.InternalIsWidgetLibrary (ic, assemblyRef);
+ return InternalIsWidgetLibrary (ic, assemblyRef);
}
internal static bool InternalIsWidgetLibrary (ImportContext ic, string assemblyRef)
@@ -305,11 +380,6 @@ internal static bool InternalIsWidgetLibrary (ImportContext ic, string assemblyR
return data.IsLibrary;
}
- internal void DisposeProject (Project p)
- {
- projects.Remove (p);
- }
-
public CodeGenerationResult GenerateProjectCode (string file, string namespaceName, CodeDomProvider provider, GenerationOptions options, params Project[] projects)
{
ArrayList files = new ArrayList ();
@@ -361,10 +431,6 @@ public CodeGenerationResult GenerateProjectCode (GenerationOptions options, para
}
}
- internal bool UseExternalBackend {
- get { return externalBackend; }
- }
-
internal Project ActiveProject {
get { return activeProject; }
set {
@@ -383,32 +449,40 @@ internal void SetActiveDesignSession (Project p, WidgetEditSession session)
public WidgetPropertyTree PropertiesWidget {
get {
- if (propertiesWidget == null)
+ if (propertiesWidget == null) {
propertiesWidget = new WidgetPropertyTree (this);
+ propertiesWidget.Destroyed += delegate { propertiesWidget = null; };
+ }
return propertiesWidget;
}
}
public Palette PaletteWidget {
get {
- if (paletteWidget == null)
+ if (paletteWidget == null) {
paletteWidget = new Palette (this);
+ paletteWidget.Destroyed += delegate { paletteWidget = null; };
+ }
return paletteWidget;
}
}
public WidgetTree WidgetTreeWidget {
get {
- if (projectWidget == null)
+ if (projectWidget == null) {
projectWidget = new WidgetTree (this);
+ projectWidget.Destroyed += delegate { projectWidget = null; };
+ }
return projectWidget;
}
}
public SignalsEditor SignalsWidget {
get {
- if (signalsWidget == null)
+ if (signalsWidget == null) {
signalsWidget = new SignalsEditor (this);
+ signalsWidget.Destroyed += delegate { signalsWidget = null; };
+ }
return signalsWidget;
}
}
@@ -436,6 +510,8 @@ internal void NotifyLibraryUnloaded (string name)
}
}
+ internal abstract ComponentType CreateComponentType (string typeName);
+
internal ComponentType GetComponentType (string typeName)
{
lock (types) {
@@ -448,36 +524,7 @@ internal ComponentType GetComponentType (string typeName)
return t;
}
- string desc = null, className = null, category = null, targetGtkVersion = null, library = null;
- Gdk.Pixbuf px = null;
-
- if (externalBackend) {
- byte[] icon;
-
- if (Backend.GetClassDescriptorInfo (typeName, out desc, out className, out category, out targetGtkVersion, out library, out icon)) {
- if (icon != null)
- px = new Gdk.Pixbuf (icon);
- }
-
- if (px == null) {
- px = ComponentType.Unknown.Icon;
- }
-
- if (desc == null)
- desc = typeName;
- } else {
- ClassDescriptor cls = Registry.LookupClassByName (typeName);
- if (cls != null) {
- desc = cls.Label;
- className = cls.WrappedTypeName;
- category = cls.Category;
- targetGtkVersion = cls.TargetGtkVersion;
- px = cls.Icon;
- library = cls.Library.Name;
- }
- }
-
- t = new ComponentType (this, typeName, desc, className, category, targetGtkVersion, library, px);
+ t = CreateComponentType (typeName);
types [typeName] = t;
return t;
}
View
4 libsteticui/ApplicationBackendController.cs
@@ -15,13 +15,13 @@ internal class ApplicationBackendController: MarshalByRefObject
bool stopping;
ApplicationBackend backend;
string channelId;
- Application app;
+ IsolatedApplication app;
ManualResetEvent runningEvent = new ManualResetEvent (false);
public event EventHandler Stopped;
- public ApplicationBackendController (Application app, string channelId)
+ public ApplicationBackendController (IsolatedApplication app, string channelId)
{
this.app = app;
this.channelId = channelId;
View
37 libsteticui/PluggableWidget.cs
@@ -20,9 +20,9 @@ public PluggableWidget (Application app)
Add (book);
this.app = app;
- if (app.UseExternalBackend) {
- app.BackendChanged += OnBackendChanged;
- app.BackendChanging += OnBackendChanging;
+ if (app is IsolatedApplication) {
+ (app as IsolatedApplication).BackendChanged += OnBackendChanged;
+ (app as IsolatedApplication).BackendChanging += OnBackendChanging;
}
}
@@ -50,9 +50,9 @@ protected void ResetCustomWidget ()
protected override void OnRealized ()
{
base.OnRealized ();
- if (!initialized && !app.Disposed) {
+ if (!initialized) {
initialized = true;
- if (app.UseExternalBackend)
+ if (app is IsolatedApplication)
ConnectPlug ();
else {
Gtk.Widget w = OnCreateWidget ();
@@ -64,7 +64,7 @@ protected override void OnRealized ()
protected override void OnUnrealized ()
{
- if (!app.Disposed && app.UseExternalBackend && initialized) {
+ if (app is IsolatedApplication && initialized) {
OnDestroyPlug (socket.Id);
initialized = false;
}
@@ -93,10 +93,10 @@ protected void PrepareUpdateWidget ()
protected void UpdateWidget ()
{
- if (!initialized || app.Disposed)
+ if (!initialized)
return;
- if (!app.UseExternalBackend) {
+ if (app is LocalApplication) {
Gtk.Widget w = OnCreateWidget ();
if (w.Parent != book) {
book.AppendPage (w, null);
@@ -119,25 +119,24 @@ protected void UpdateWidget ()
public override void Dispose ()
{
- if (app.UseExternalBackend) {
- app.BackendChanged -= OnBackendChanged;
- app.BackendChanging -= OnBackendChanging;
+ if (app is IsolatedApplication) {
+ IsolatedApplication iapp = app as IsolatedApplication;
+ iapp.BackendChanged -= OnBackendChanged;
+ iapp.BackendChanging -= OnBackendChanging;
}
base.Dispose ();
}
internal virtual void OnBackendChanged (ApplicationBackend oldBackend)
{
- if (!initialized || app.Disposed)
+ if (!initialized)
return;
- if (app.UseExternalBackend) {
- Gtk.Widget w = book.GetNthPage (0);
- book.RemovePage (0);
- w.Destroy ();
- socket.Dispose ();
- ConnectPlug ();
- }
+ Gtk.Widget w = book.GetNthPage (0);
+ book.RemovePage (0);
+ w.Destroy ();
+ socket.Dispose ();
+ ConnectPlug ();
}
internal virtual void OnBackendChanging ()
View
20 libsteticui/Project.cs
@@ -54,8 +54,11 @@ internal Project (Application app, ProjectBackend backend)
backend.SetFrontend (this);
}
- app.BackendChanging += OnBackendChanging;
- app.BackendChanged += OnBackendChanged;
+ if (app is IsolatedApplication) {
+ IsolatedApplication iapp = app as IsolatedApplication;
+ iapp.BackendChanging += OnBackendChanging;
+ iapp.BackendChanged += OnBackendChanged;
+ }
}
internal ProjectBackend ProjectBackend {
@@ -80,20 +83,25 @@ internal Project (Application app, ProjectBackend backend)
get { return app; }
}
+ internal event EventHandler Disposed;
+
public void Dispose ()
{
- app.BackendChanging -= OnBackendChanging;
- app.BackendChanged -= OnBackendChanged;
+ if (app is IsolatedApplication) {
+ IsolatedApplication iapp = app as IsolatedApplication;
+ iapp.BackendChanging -= OnBackendChanging;
+ iapp.BackendChanged -= OnBackendChanged;
+ }
if (tmpProjectFile != null && File.Exists (tmpProjectFile)) {
File.Delete (tmpProjectFile);
tmpProjectFile = null;
}
if (backend != null)
backend.Dispose ();
- app.DisposeProject (this);
+ if (Disposed != null)
+ Disposed (this, EventArgs.Empty);
System.Runtime.Remoting.RemotingServices.Disconnect (this);
- app.UpdateWidgetLibraries (false, false);
}
public override object InitializeLifetimeService ()
View
4 stetic/Stetic.cs
@@ -84,7 +84,7 @@ public static int Main (string[] args)
int ret;
if (args.Length - n > 2 && ((args [n] == "--generate" || args [n] == "-g"))) {
- SteticApp = new Stetic.Application (IsolationMode.None);
+ SteticApp = Stetic.ApplicationFactory.CreateApplication (IsolationMode.None);
GenerationOptions ops = new GenerationOptions ();
ops.UsePartialClasses = usePartial;
ops.GenerateEmptyBuildMethod = genEmpty;
@@ -93,7 +93,7 @@ public static int Main (string[] args)
ret = GenerateCode (args [n+1], args, n+2, ops);
}
else {
- SteticApp = new Stetic.Application (mode);
+ SteticApp = Stetic.ApplicationFactory.CreateApplication (mode);
SteticApp.AllowInProcLibraries = false;
ret = RunApp (args, n);
}

0 comments on commit 6bed5d0

Please sign in to comment.