/*
* Copyright (C) 2006-2007 Eskil Bylund
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
using System;
using System.Text;
using System.Threading;
using System.Reflection;
using Gtk;
using Mono.Unix;
using Notifications;
using DCSharp.Backend.Connections;
using DCSharp.Backend.Managers;
using DCSharp.Backend.Objects;
using DCSharp.Logging;
using DCSharp.Settings;
using DCSharp.Xml;
using DCSharp.Xml.FileList;
namespace DCSharp.GUI{
public static class GUI
{
private static Thread mainThread;
private static InterfaceSettings settings;
private static string settingsFile;
private static Notification notification;
// Windows
private static HubWindow hubWindow;
private static PreferencesWindow preferencesWindow;
// Pages
private static SearchPage searchPage;
private static DownloadPage downloadPage;
private static UploadPage uploadPage;
private static Page currentPage;
#region Properties
public static MainWindow MainWindow
{
get { return mainWindow; }
}
private static MainWindow mainWindow;
#endregion
#region Methods
public static void Init()
{
mainThread = Thread.CurrentThread;
// Init the runtime
LogManager.Handlers += LogManager.DefaultHandler;
Runtime.Init();
// Locale
string localeDir = Environment.GetEnvironmentVariable("DCSHARP_LOCALE");
if (localeDir == null)
{
localeDir = "./locale";
}
// Init
Catalog.Init("dcsharp", localeDir);
IconManager.Init();
settingsFile = Runtime.GetDataFile("InterfaceSettings.xml");
settings = InterfaceSettings.Load(settingsFile);
Glade.XML.CustomHandler = new Glade.XMLCustomWidgetHandler(CustomWidgetHandler);
#if GNOME
Gnome.Vfs.Vfs.Initialize();
AboutDialog.SetUrlHook(OpenUrl);
#endif
// Notifications
notification = new Notification();
notification.Summary = Catalog.GetString("Download complete");
notification.Category = "transfer.complete";
notification.AddHint("desktop-entry", "dcsharp");
// Main mindow
mainWindow = new MainWindow(Runtime.ConnectionManager,
Runtime.FavoriteHubManager);
RestoreWindowSettings();
mainWindow.ToolbarVisible = settings.ToolbarVisible;
mainWindow.Window.Destroyed += delegate
{
Application.Quit();
};
mainWindow.Show();
// Events
mainWindow.PageManager.CurrentPageChanged += OnCurrentPageChanged;
mainWindow.PageManager.PageRemoved += OnPageRemoved;
mainWindow.Window.ConfigureEvent += OnWindowConfigureEvent;
mainWindow.Window.WindowStateEvent += OnWindowStateEvent;
// Runtime Events
AppDomain.CurrentDomain.UnhandledException += OnUnhandledException;
Runtime.HubManager.HubAdded += OnHubAdded;
Runtime.HubManager.HubRemoved += OnHubRemoved;
Runtime.ConnectionManager.ConnectionAdded += OnConnectionAdded;
Runtime.ConnectionManager.ConnectionRemoved += OnConnectionRemoved;
Runtime.DownloadManager.DownloadAdded += OnDownloadAdded;
Runtime.DownloadManager.DownloadRemoved += OnDownloadRemoved;
Runtime.ConnectionCreated += OnConnectionCreated;
Runtime.Error += OnRuntimeError;
Runtime.Listener.ReceivedFileListing += OnReceivedFileListing;
// Connect
Runtime.ConnectToFavoriteHubs();
}
public static void Run()
{
try
{
Application.Run();
}
finally
{
Runtime.Shutdown();
SaveSettings();
}
}
public static void InvokeAndWait(EventHandler handler)
{
if (Thread.CurrentThread == mainThread)
{
handler(null, null);
}
else
{
AutoResetEvent autoEvent = new AutoResetEvent(false);
Application.Invoke(delegate
{
handler(null, null);
autoEvent.Set();
});
autoEvent.WaitOne();
}
}
#region Pages
public static void ShowHub(HubConnection hub, bool present)
{
if (hub == null)
{
throw new ArgumentNullException("hub");
}
HubPage hubPage = mainWindow.PageManager.Find<HubPage>(delegate(HubPage page)
{
return page.Hub.Equals(hub);
});
if (hubPage == null)
{
hubPage = new HubPage(hub);
// Restore settings
HubSettings hubSettings = settings.GetHubSettings(hub.Hostname);
if (hubSettings.PanePosition > 0)
{
hubPage.PanePosition = hubSettings.PanePosition;
}
if (hubSettings.VisibleColumns != 0)
{
hubPage.VisibleColumns = hubSettings.VisibleColumns;
}
}
else
{
hubPage.Hub = hub;
}
ShowPage(hubPage, present);
}
public static void ShowSearch(bool present)
{
if (searchPage == null)
{
searchPage = new SearchPage(Runtime.SearchManager);
searchPage.SetSearchEnabled(Runtime.HubManager.Count > 0);
if (settings.SearchColumns != 0)
{
searchPage.VisibleColumns = settings.SearchColumns;
}
}
ShowPage(searchPage, present);
searchPage.FocusSearchEntry();
}
public static void ShowDownloads(bool present)
{
if (downloadPage == null)
{
downloadPage = new DownloadPage(Runtime.ConnectionManager,
Runtime.DownloadManager);
if (settings.DownloadColumns != 0)
{
downloadPage.VisibleColumns = settings.DownloadColumns;
}
downloadPage.DirectoryTreeVisible = settings.DownloadPageDirectoryTreeVisible;
downloadPage.SourcesVisible = settings.DownloadPageSourcesVisible;
downloadPage.PanePosition = settings.DownloadPagePanePosition;
}
ShowPage(downloadPage, present);
}
public static void ShowUploads(bool present)
{
if (uploadPage == null)
{
uploadPage = new UploadPage(Runtime.ConnectionManager);
if (settings.UploadColumns != 0)
{
uploadPage.VisibleColumns = settings.UploadColumns;
}
}
ShowPage(uploadPage, present);
}
public static ChatPage ShowChat(LocalIdentity localIdentity,
Identity remoteIdentity, bool present)
{
if (localIdentity == null)
{
throw new ArgumentNullException("localIdentity");
}
if (remoteIdentity == null)
{
throw new ArgumentNullException("remoteIdentity");
}
ChatPage chatPage = mainWindow.PageManager.Find<ChatPage>(
delegate(ChatPage page)
{
return page.RemoteIdentity.User == remoteIdentity.User;
});
if (chatPage == null)
{
chatPage = new ChatPage(localIdentity, remoteIdentity);
}
ShowPage(chatPage, present);
return chatPage;
}
public static void ShowFileList(FileListing list, Identity identity,
DownloadFileInfo fileListDownload, string pathToSelect)
{
if (identity == null)
{
throw new ArgumentNullException("user");
}
FileListingPage filePage = mainWindow.PageManager.Find<FileListingPage>(
delegate(FileListingPage page)
{
return page.User.User == identity.User;
});
if (filePage == null)
{
filePage = new FileListingPage(list, identity, fileListDownload,
pathToSelect);
}
else
{
filePage.FileListing = list;
filePage.FileListDownload = fileListDownload;
if (pathToSelect != null)
{
filePage.SelectPath(pathToSelect);
}
}
ShowPage(filePage, true);
}
private static void ShowPage(Page page, bool present)
{
if (!mainWindow.PageManager.Contains(page))
{
mainWindow.PageManager.Add(page);
}
if (present)
{
mainWindow.PageManager.Present(page);
}
}
private static void OnCurrentPageChanged(object obj, PageEventArgs args)
{
// Update the position of the new message separator.
HubPage hubPage = currentPage as HubPage;
if (hubPage != null)
{
hubPage.UpdateNewMessageSeparator();
hubPage.ShowSeparatorOnMessage = true;
}
hubPage = args.Page as HubPage;
if (hubPage != null)
{
hubPage.ShowSeparatorOnMessage = false;
}
currentPage = args.Page;
}
private static void OnPageRemoved(object obj, PageEventArgs args)
{
Page page = args.Page;
if (page != searchPage && page != downloadPage && page != uploadPage)
{
HubPage hubPage = page as HubPage;
if (hubPage != null && hubPage.Hub != null)
{
// Save settings
HubSettings hubSettings = settings.GetHubSettings(hubPage.Hub.Hostname);
hubSettings.PanePosition = hubPage.PanePosition;
hubSettings.VisibleColumns = hubPage.VisibleColumns;
hubPage.Hub.Disconnect();
}
// Destroy the page in an idle handler so that any calls to
// Application.Invoke have been handled.
GLib.Idle.Add(delegate
{
page.Destroy();
return false;
});
}
else if (page == searchPage)
{
searchPage.StopSearch();
}
}
#endregion
#region Windows
public static void EditHubs()
{
if (hubWindow == null)
{
hubWindow = new HubWindow(Runtime.HubManager,
Runtime.FavoriteHubManager, mainWindow.Window);
hubWindow.Window.SkipTaskbarHint = true;
hubWindow.Window.Destroyed += delegate
{
hubWindow = null;
};
}
hubWindow.Show();
}
public static void EditPreferences()
{
if (preferencesWindow == null)
{
preferencesWindow = new PreferencesWindow(Runtime.Settings,
Runtime.ConnectionSettings, Runtime.ShareManager, mainWindow.Window);
preferencesWindow.Window.Destroyed += delegate
{
preferencesWindow = null;
};
}
preferencesWindow.Show();
}
private static void RestoreWindowSettings()
{
int x = settings.WindowX;
int y = settings.WindowY;
int width = settings.WindowWidth;
int height = settings.WindowHeight;
if (width != 0 && height != 0)
{
mainWindow.Window.Resize(width, height);
}
if (x != 0 && y != 0)
{
mainWindow.Window.Move(x, y);
}
if (settings.WindowMaximized)
{
mainWindow.Window.Maximize();
}
}
private static void SaveWindowSettings()
{
int x, y, width, height;
mainWindow.Window.GetPosition(out x, out y);
mainWindow.Window.GetSize(out width, out height);
settings.WindowX = x;
settings.WindowY = y;
settings.WindowWidth = width;
settings.WindowHeight = height;
}
[GLib.ConnectBefore]
private static void OnWindowConfigureEvent(object obj, ConfigureEventArgs args)
{
Window window = (Window)obj;
if ((window.GdkWindow.State & Gdk.WindowState.Maximized) != 0)
{
return;
}
SaveWindowSettings();
}
private static void OnWindowStateEvent(object obj, WindowStateEventArgs args)
{
if ((args.Event.NewWindowState & Gdk.WindowState.Withdrawn) == 0)
{
settings.WindowMaximized =
(args.Event.NewWindowState & Gdk.WindowState.Maximized) != 0;
}
}
#endregion
private static void SaveSettings()
{
settings.ToolbarVisible = mainWindow.ToolbarVisible;
if (searchPage != null)
{
settings.SearchColumns = searchPage.VisibleColumns;
}
if (downloadPage != null)
{
settings.DownloadColumns = downloadPage.VisibleColumns;
settings.DownloadPageDirectoryTreeVisible = downloadPage.DirectoryTreeVisible;
settings.DownloadPageSourcesVisible = downloadPage.SourcesVisible;
settings.DownloadPagePanePosition = downloadPage.PanePosition;
}
if (uploadPage != null)
{
settings.UploadColumns = uploadPage.VisibleColumns;
}
settings.Save(settingsFile);
}
#if GNOME
private static void OpenUrl(Gtk.AboutDialog about, string url)
{
Util.OpenUrl(url);
}
#endif
private static Widget CustomWidgetHandler(Glade.XML xml,
string funcName, string name, string string1, string string2,
int int1, int int2)
{
switch (funcName)
{
case "ChatView":
return new ChatView();
case "HistoryEntry":
return new HistoryEntry();
case "SearchEntry":
return new SearchEntry();
case "SearchFileTypeComboBox":
return new SearchFileTypeComboBox();
case "SearchResultView":
return new SearchResultView();
case "UserView":
return new UserView(null);
default:
return null;
}
}
#region Runtime event handlers
private static void OnHubAdded(object obj, ConnectionEventArgs args)
{
HubConnection hub = (HubConnection)args.Connection;
InvokeAndWait(delegate
{
ShowHub(hub, false);
// Enable searching
if (searchPage != null)
{
searchPage.SetSearchEnabled(true);
}
});
hub.PrivateMessage += OnPrivateMessage;
}
private static void OnHubRemoved(object obj, ConnectionEventArgs args)
{
HubConnection hub = (HubConnection)args.Connection;
hub.PrivateMessage -= OnPrivateMessage;
Application.Invoke(delegate
{
// Disable searching
if (searchPage != null && Runtime.HubManager.Count == 0)
{
searchPage.SetSearchEnabled(false);
}
});
}
private static void OnPrivateMessage(object obj, MessageEventArgs args)
{
Application.Invoke(delegate
{
HubConnection hub = (HubConnection)obj;
Identity remoteIdentity = args.From == hub.LocalIdentity ?
args.To : args.From;
ChatPage chatPage = ShowChat(hub.LocalIdentity, remoteIdentity, false);
chatPage.DisplayMessage(args.From.User, args.Message);
});
}
private static void OnConnectionAdded(object obj, ConnectionEventArgs args)
{
UserConnection connection = (UserConnection)args.Connection;
connection.TransferStarted += OnTransferStarted;
}
private static void OnConnectionRemoved(object obj, ConnectionEventArgs args)
{
UserConnection connection = (UserConnection)args.Connection;
connection.TransferStarted -= OnTransferStarted;
}
private static void OnTransferStarted(object obj, TransferEventArgs args)
{
if (args.Transfer is UploadFileInfo)
{
InvokeAndWait(delegate
{
ShowUploads(false);
});
}
}
private static void OnDownloadAdded(object obj, DownloadEventArgs args)
{
if (!args.Download.IsFileList)
{
Application.Invoke(delegate
{
ShowDownloads(false);
});
}
}
private static void OnDownloadRemoved(object obj, DownloadEventArgs args)
{
DownloadFileInfo download = args.Download;
if (download.IsFileList || download.Size == 0 ||
download.Position != download.Size)
{
return;
}
Application.Invoke(delegate
{
notification.Body = GLib.Markup.EscapeText(download.Name);
notification.IconName = Util.GetIconName(download.Name);
// Actions
notification.ClearActions();
notification.AddAction("default", String.Empty, delegate
{
ShowDownloads(true);
mainWindow.Show();
});
#if GNOME
notification.AddAction("open", Catalog.GetString("Open"), delegate
{
Util.OpenFile(System.IO.Path.Combine(download.Target, download.Name));
});
notification.AddAction("browse", Catalog.GetString("Open Folder"), delegate
{
Util.OpenFile(download.Target);
});
#endif
notification.Show();
});
}
private static void OnReceivedFileListing(FileListing list, Identity identity)
{
Application.Invoke(delegate
{
FileListingPage filePage = mainWindow.PageManager.Find<FileListingPage>(
delegate(FileListingPage page)
{
return page.User.User == identity.User;
});
if (filePage != null)
{
filePage.FileListing = list;
}
});
}
private static void OnConnectionCreated(object obj, ConnectionEventArgs args)
{
HubConnection hub = args.Connection as HubConnection;
if (hub != null)
{
InvokeAndWait(delegate
{
ShowHub(hub, false);
});
}
}
private static void OnRuntimeError(object obj, RuntimeErrorEventArgs args)
{
InvokeAndWait(delegate
{
OnRuntimeError(args.Error);
});
}
private static void OnRuntimeError(RuntimeError error)
{
string primary;
string secondary = null;
Window parent = mainWindow.Window;
switch (error)
{
case RuntimeError.ServerStart:
primary = Catalog.GetString("Could not listen to port {0}");
primary = String.Format(primary, Runtime.ConnectionSettings.Port);
secondary = Catalog.GetString("Please select another port in the preferences window.");
EditPreferences();
parent = preferencesWindow.Window;
break;
default:
primary = Catalog.GetString("An error occured");
break;
}
MessageDialog dialog = new MessageDialog(primary, secondary,
null, MessageType.Error, parent);
dialog.AddButton(Stock.Ok, ResponseType.Ok);
dialog.Run();
dialog.Destroy();
}
private static void OnUnhandledException(object obj,
UnhandledExceptionEventArgs args)
{
Exception e = (Exception)args.ExceptionObject;
// Exception details
StringBuilder details = new StringBuilder();
details.Append(Catalog.GetString("An unhandled exception occured:")
+ "\n\n");
details.Append(e.ToString() + "\n\n");
details.Append(String.Format ("Version: {0}",
DCSharp.Extras.Util.AppVersion) + "\n");
details.Append(String.Format ("Runtime Version: {0}",
Environment.Version.ToString ()) + "\n");
details.Append("Assemblies:" + "\n");
foreach (Assembly a in AppDomain.CurrentDomain.GetAssemblies ())
{
AssemblyName name = a.GetName();
details.Append ("\t" + name.Name + " (" +
name.Version.ToString() + ")\n");
}
// Info
string primary = Catalog.GetString("An unhandled exception occured");
string secondary = Catalog.GetString("Please report this to the developers. Visit {0} for more information.");
secondary = String.Format(secondary, DCSharp.Extras.Util.Website);
Console.Error.WriteLine(primary);
Console.Error.WriteLine(secondary);
Console.Error.WriteLine(e);
InvokeAndWait(delegate
{
// Create dialog
Window parent = mainWindow.Window;
MessageDialog dialog = new MessageDialog(primary, secondary,
details.ToString(), MessageType.Error, parent);
dialog.AddButton(Stock.Ok, ResponseType.Ok);
if (parent != null && parent.Visible)
{
dialog.Dialog.SkipPagerHint = true;
dialog.Dialog.SkipTaskbarHint = true;
}
dialog.Run();
dialog.Destroy();
Application.Quit();
});
}
#endregion
#endregion
}
}
|