using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Configuration;
using System.Diagnostics;
using System.Drawing;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Forms;
using System.Windows.Input;
using System.Windows.Interop;
using DelftTools.Controls.Swf;
using DelftTools.Shell.Core;
using DelftTools.Shell.Gui;
using DelftTools.Shell.Gui.Forms;
using DelftTools.Utils;
using DelftTools.Utils.Aop;
using DelftTools.Utils.Collections;
using DelftTools.Utils.Collections.Extensions;
using DelftTools.Utils.Interop;
using DelftTools.Utils.Reflection;
using DeltaShell.Core;
using DeltaShell.Gui.Forms.OptionsDialog;
using DeltaShell.Gui.Properties;
using Fluent;
using log4net;
using Microsoft.Win32;
using Xceed.Wpf.AvalonDock;
using Xceed.Wpf.AvalonDock.Controls;
using Xceed.Wpf.AvalonDock.Layout;
using Xceed.Wpf.AvalonDock.Layout.Serialization;
using Xceed.Wpf.AvalonDock.Themes;
using Application = System.Windows.Forms.Application;
using Button = Fluent.Button;
using Cursors = System.Windows.Input.Cursors;
using IWin32Window = System.Windows.Forms.IWin32Window;
using MessageBox = DelftTools.Controls.Swf.MessageBox;
namespace DeltaShell.Gui.Forms.MainWindow
{
///
/// Main windows of Delta Shell
///
public partial class MainWindow : IMainWindow, IDisposable, IWin32Window, ISynchronizeInvoke
{
private static readonly ILog log = LogManager.GetLogger(typeof(MainWindow));
private static Form synchronizationForm;
///
/// Remember last active contextual tab per view.
///
private readonly IDictionary lastActiveContextTabNamePerViewType = new Dictionary();
private bool resetDefaultLayout;
private MessageWindow.MessageWindow messageWindow;
private PropertyGridView.PropertyGridView propertyGrid;
private WindowInteropHelper windowInteropHelper;
private IEnumerable ribbonCommandHandlers;
///
/// This is used when user selects non-contextual tab explicitly. Then we won't activate contextual tab on the next view activation.
///
private bool activateContextualTab;
///
/// Used when contextual tab was activated and we switch back to view which does not support contextual tabs.
///
private string lastNonContextualTab;
public MainWindow()
{
InitializeComponent();
windowInteropHelper = new WindowInteropHelper(this);
ModalHelper.MainWindow = this;
InitializeInvokeRequired();
App.RunDeltaShell(this);
log.Info(Properties.Resources.MainWindow_MainWindow_Main_window_created_);
}
public MainWindow(DeltaShellGui gui)
{
DeltaShellApplication.SetLanguageAndRegionalSettions(Settings.Default);
Gui = gui;
InitializeComponent();
windowInteropHelper = new WindowInteropHelper(this);
ModalHelper.MainWindow = this;
InitializeInvokeRequired();
log.Info(Properties.Resources.MainWindow_MainWindow_Main_window_created_);
}
public DeltaShellGui Gui { get; set; }
public bool IsWindowDisposed { get; private set; }
public bool Enabled
{
get
{
return IsEnabled;
}
set
{
IsEnabled = value;
NativeWin32.EnableWindow(new HandleRef(this, windowInteropHelper.Handle), value); // prevents resize etc
}
}
public DockingManager DockingManager
{
get
{
return dockingManager;
}
}
public IMessageWindow MessageWindow
{
get
{
return messageWindow;
}
}
public bool Visible
{
get
{
return IsVisible;
}
set
{
if (value)
{
if (IsVisible)
{
return;
}
Show();
}
else
{
if (!IsVisible)
{
return;
}
Hide();
}
}
}
public string StatusBarMessage
{
get
{
return StatusMessageTextBlock.Text;
}
set
{
StatusMessageTextBlock.Text = value;
}
}
public IProjectExplorer ProjectExplorer
{
get
{
return Gui.ToolWindowViews.OfType().FirstOrDefault();
}
}
public IPropertyGrid PropertyGrid
{
get
{
return propertyGrid;
}
}
public bool InvokeRequired
{
get
{
return !Dispatcher.CheckAccess();
}
}
public IntPtr Handle
{
get
{
return windowInteropHelper.Handle;
}
}
public void SubscribeToGui()
{
if (Gui != null)
{
Gui.ToolWindowViews.CollectionChanged += ToolWindowViews_CollectionChanged;
Gui.DocumentViews.ActiveViewChanged += DocumentViewsOnActiveViewChanged;
Gui.DocumentViews.ActiveViewChanging += DocumentViewsOnActiveViewChanging;
}
}
public void UnsubscribeFromGui()
{
if (Gui != null)
{
Gui.ToolWindowViews.CollectionChanged -= ToolWindowViews_CollectionChanged;
Gui.DocumentViews.ActiveViewChanged -= DocumentViewsOnActiveViewChanged;
Gui.DocumentViews.ActiveViewChanging -= DocumentViewsOnActiveViewChanging;
}
}
public void RestoreLayout()
{
if (Assembly.GetEntryAssembly() == null) // API, not a real exe
{
return; // make sure we don't mess layout
}
OnLoadLayout("normal");
RestoreWindowAppearance();
}
public void SaveLayout()
{
if (Settings.Default.autosaveWindowLayout)
{
SaveWindowAppearance();
OnSaveLayout("normal");
}
}
public void InitializeToolWindows()
{
InitMessagesWindowOrActivate();
InitPropertiesWindowAndActivate();
}
public void SuspendLayout() {}
public void ResumeLayout() {}
public void InitPropertiesWindowAndActivate()
{
if ((propertyGrid == null) || (propertyGrid.IsDisposed))
{
propertyGrid = new PropertyGridView.PropertyGridView(Gui);
}
propertyGrid.Text = Properties.Resources.Properties;
propertyGrid.Data = propertyGrid.GetObjectProperties(Gui.Selection);
Gui.ToolWindowViews.Add(propertyGrid, ViewLocation.Right | ViewLocation.Bottom);
Gui.ToolWindowViews.ActiveView = null;
Gui.ToolWindowViews.ActiveView = Gui.MainWindow.PropertyGrid;
}
public void ShowStartPage(bool checkUseSettings = true)
{
if (!checkUseSettings || Convert.ToBoolean(Gui.Application.UserSettings["showStartPage"], CultureInfo.InvariantCulture))
{
log.Info(Properties.Resources.MainWindow_ShowStartPage_Adding_welcome_page____);
OpenStartPage();
}
}
public void ClearDocumentTabs()
{
foreach (var contentToClose in dockingManager.Layout.Descendents().OfType().Where(d => (d.Parent is LayoutDocumentPane || d.Parent is LayoutDocumentFloatingWindow)).ToArray())
{
if (!contentToClose.CanClose)
{
continue;
}
if (contentToClose is LayoutDocument)
{
CloseContent(contentToClose as LayoutDocument);
}
else if (contentToClose is LayoutAnchorable)
{
CloseContent(contentToClose as LayoutAnchorable);
}
}
foreach (var child in LayoutDocumentPaneGroup.Children.OfType())
{
child.Children.Clear();
}
while (LayoutDocumentPaneGroup.Children.Count != 1)
{
LayoutDocumentPaneGroup.Children.RemoveAt(0);
}
}
public void Dispose()
{
Close();
Close();
if (IsWindowDisposed)
{
return;
}
// TODO: add dispose code
IsWindowDisposed = true;
if (Equals(InvokeRequiredInfo.SynchronizeObject, this))
{
InvokeRequiredInfo.SynchronizeObject = null;
}
if (dockingManager.AutoHideWindow != null)
{
var m = typeof(LayoutAutoHideWindowControl).GetField("_manager", BindingFlags.Instance | BindingFlags.NonPublic);
m.SetValue(dockingManager.AutoHideWindow, null);
dockingManager.AutoHideWindow.Dispose();
}
Content = null;
if (Ribbon != null)
{
foreach (var tab in Ribbon.Tabs)
{
foreach (var group in tab.Groups)
{
group.Items.Clear();
}
tab.Groups.Clear();
}
Ribbon.Tabs.Clear();
Ribbon = null;
}
dockingManager = null;
if (propertyGrid != null)
{
propertyGrid.Dispose();
propertyGrid = null;
}
if (messageWindow != null)
{
messageWindow.OnError -= MessageWindowOnError;
messageWindow.Dispose();
messageWindow = null;
}
// I pulled this code from some internet sources combined with the reflector to remove a well-known leak
var handlers = typeof(SystemEvents).GetField("_handlers", BindingFlags.Static | BindingFlags.NonPublic)
.GetValue(null);
var upcHandler = typeof(SystemEvents).GetField("OnUserPreferenceChangedEvent", BindingFlags.NonPublic | BindingFlags.Static).GetValue(null);
var eventLockObject = typeof(SystemEvents).GetField("eventLockObject", BindingFlags.NonPublic | BindingFlags.Static).GetValue(null);
lock (eventLockObject)
{
var upcHandlerList = (IList) ((IDictionary) handlers)[upcHandler];
for (int i = upcHandlerList.Count - 1; i >= 0; i--)
{
var target = (Delegate) upcHandlerList[i].GetType().GetField("_delegate", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(upcHandlerList[i]);
upcHandlerList.RemoveAt(i);
}
}
ribbonCommandHandlers = null;
windowInteropHelper = null;
Gui = null;
// Dispatcher.InvokeShutdown();
//System.Windows.Threading.Dispatcher.CurrentDispatcher.InvokeShutdown();
}
public void ValidateItems()
{
if (Gui == null)
{
return;
}
ValidateMainWindowRibbonItems();
if (ribbonCommandHandlers == null)
{
return;
}
// activate all context-specific groups (ValidateItems implementations should activate them)
foreach (var tabGroup in Ribbon.ContextualGroups)
{
var showGroup = false;
foreach (var tabItem in tabGroup.Items)
{
var tabItemVisible = ribbonCommandHandlers.Any(h => h.IsContextualTabVisible(tabGroup.Name, tabItem.Name));
tabItem.Visibility = tabItemVisible ? Visibility.Visible : Visibility.Collapsed;
if (tabItemVisible && !showGroup)
{
showGroup = true;
}
}
tabGroup.Visibility = showGroup ? Visibility.Visible : Visibility.Collapsed;
}
foreach (var ribbonCommandHandler in ribbonCommandHandlers)
{
ribbonCommandHandler.ValidateItems();
}
foreach (var ribbonGroupBox in Ribbon.Tabs.SelectMany(tab => tab.Groups))
{
// Colapse all groups without visible items
ribbonGroupBox.Visibility = ribbonGroupBox.Items.OfType().All(e => e.Visibility == Visibility.Collapsed || e is Separator)
? Visibility.Collapsed
: Visibility.Visible;
}
}
public void SetWaitCursorOn()
{
Mouse.OverrideCursor = Cursors.Wait;
}
public void SetWaitCursorOff()
{
Mouse.OverrideCursor = null;
}
public IAsyncResult BeginInvoke(Delegate method, object[] args)
{
Dispatcher.BeginInvoke(method, args);
return null;
}
public object EndInvoke(IAsyncResult result)
{
throw new NotImplementedException();
}
public object Invoke(Delegate method, object[] args)
{
return Dispatcher.Invoke(method, args);
}
private void ToolWindowViews_CollectionChanged(object sender, NotifyCollectionChangingEventArgs e)
{
if (e.Action != NotifyCollectionChangeAction.Remove)
{
return;
}
if (e.Item == propertyGrid)
{
propertyGrid = null;
}
if (e.Item == MessageWindow)
{
messageWindow = null;
}
}
private void DocumentViewsOnActiveViewChanging(object sender, ActiveViewChangeEventArgs e)
{
if (Ribbon.SelectedTabItem != null && !Ribbon.SelectedTabItem.IsContextual)
{
lastNonContextualTab = Ribbon.SelectedTabItem.Header.ToString();
}
// remember active contextual tab per view type, when view is activated back - activate contextual item
if (Ribbon.SelectedTabItem != null && e.OldView != null)
{
if (Ribbon.SelectedTabItem.IsContextual)
{
lastActiveContextTabNamePerViewType[e.OldView.GetType()] = Ribbon.SelectedTabItem.Header.ToString();
activateContextualTab = true;
}
else
{
// user has clicked on non-contextual tab before switching active view
if (lastActiveContextTabNamePerViewType.ContainsKey(e.OldView.GetType()))
{
activateContextualTab = false;
}
}
}
else
{
activateContextualTab = true;
}
}
private void DocumentViewsOnActiveViewChanged(object sender, ActiveViewChangeEventArgs e)
{
// activate contextual tab which was active for this view type
if (activateContextualTab && Ribbon.SelectedTabItem != null && e.View != null &&
Ribbon.Tabs.Any(t => t.IsContextual && t.Visibility == Visibility.Visible))
{
string lastActiveTabForActiveView;
if (lastActiveContextTabNamePerViewType.TryGetValue(e.View.GetType(), out lastActiveTabForActiveView))
{
var tab = Ribbon.Tabs.First(t => t.Header.ToString() == lastActiveTabForActiveView);
if (tab.IsVisible)
{
Ribbon.SelectedTabItem = tab;
}
}
else // activate first contextual group tab
{
var tab = Ribbon.Tabs.FirstOrDefault(t => t.IsContextual && t.Visibility == Visibility.Visible);
Ribbon.SelectedTabItem = tab;
}
}
else if (!string.IsNullOrEmpty(lastNonContextualTab)) // reactivate last non-contextual tab
{
var tab = Ribbon.Tabs.First(t => t.Header.ToString() == lastNonContextualTab);
Ribbon.SelectedTabItem = tab;
}
}
private void InitializeInvokeRequired()
{
if (Assembly.GetEntryAssembly() != null) // HACK: when assembly is non-empty - we run from real exe (not test)
{
if (InvokeRequiredInfo.SynchronizeObject == null)
{
InvokeRequiredInfo.SynchronizeObject = this;
InvokeRequiredInfo.WaitMethod = Application.DoEvents;
}
return; // uses MainWindow
}
// use static form for synchronization
if (synchronizationForm == null)
{
synchronizationForm = new Form
{
ShowInTaskbar = false, WindowState = FormWindowState.Minimized
};
var handle = synchronizationForm.Handle; //force get handle
synchronizationForm.Show();
}
if (InvokeRequiredInfo.SynchronizeObject == null)
{
InvokeRequiredInfo.SynchronizeObject = synchronizationForm;
InvokeRequiredInfo.WaitMethod = Application.DoEvents;
}
}
private void AddRecentlyOpenedProjectsToFileMenu()
{
var mruList = Settings.Default["mruList"] as StringCollection;
foreach (var recent in mruList)
{
AddNewMruItem(recent, false);
}
}
private void AddNewMruItem(string path, bool putOnTop = true)
{
var newItem = new TabItem
{
Header = path
};
newItem.MouseDoubleClick += (sender, args) =>
{
try
{
Gui.CommandHandler.TryOpenExistingWTIProject(path);
RecentProjectsTabControl.Items.Remove(newItem);
RecentProjectsTabControl.Items.Insert(1, newItem);
}
catch (Exception)
{
//remove item from the list if it cannot be retrieved from file
RecentProjectsTabControl.Items.Remove(newItem);
log.WarnFormat("{0} {1}", Properties.Resources.MainWindow_AddNewMruItem_Can_t_open_project, path);
}
finally
{
CommitMruToSettings();
ValidateItems();
Menu.IsOpen = false;
}
};
if (RecentProjectsTabControl.Items.OfType().Any(i => Equals(i.Header, path)))
{
return;
}
if (putOnTop)
{
RecentProjectsTabControl.Items.Insert(1, newItem);
}
else
{
RecentProjectsTabControl.Items.Add(newItem);
}
}
private void CommitMruToSettings()
{
var mruList = (StringCollection) Settings.Default["mruList"];
mruList.Clear();
foreach (TabItem item in RecentProjectsTabControl.Items)
{
if (item is SeparatorTabItem) //header
{
continue;
}
mruList.Add(item.Header.ToString());
}
}
private void OnLayoutRootPropertyChanged(object sender, PropertyChangedEventArgs e) {}
private void ValidateMainWindowRibbonItems()
{
if (Gui.ToolWindowViews != null)
{
ButtonShowMessages.IsChecked = Gui.ToolWindowViews.Contains(MessageWindow);
ButtonShowProperties.IsChecked = Gui.ToolWindowViews.Contains(PropertyGrid);
}
var appHasProject = (Gui.Application.Project != null);
var isActivityRunning = Gui.Application.IsActivityRunning();
// filemenu items dependent on existence of project and if processes are running
ButtonMenuFileNewProject.IsEnabled = !isActivityRunning;
ButtonMenuFileOpenProject.IsEnabled = !isActivityRunning;
ButtonMenuFileSaveProject.IsEnabled = appHasProject && !isActivityRunning;
ButtonMenuFileSaveProjectAs.IsEnabled = appHasProject && !isActivityRunning;
ButtonMenuFileCloseProject.IsEnabled = appHasProject && !isActivityRunning;
}
private void InitMessagesWindowOrActivate()
{
if (messageWindow == null || messageWindow.IsDisposed)
{
if (messageWindow != null && messageWindow.IsDisposed)
{
messageWindow.OnError -= MessageWindowOnError;
}
messageWindow = new MessageWindow.MessageWindow
{
Text = Properties.Resources.Messages
};
messageWindow.OnError += MessageWindowOnError;
}
if (Gui == null || Gui.ToolWindowViews == null)
{
return;
}
if (Gui.ToolWindowViews.Contains(messageWindow))
{
Gui.ToolWindowViews.ActiveView = messageWindow;
return;
}
Gui.ToolWindowViews.Add(messageWindow, ViewLocation.Bottom);
messageWindow.Visible = true; //doesn't always work (eg, remains false)
}
[InvokeRequired]
private void MessageWindowOnError(object sender, EventArgs e)
{
// activates messageWindow when error occurs
InitMessagesWindowOrActivate();
}
private void OnFileSaveClicked(object sender, RoutedEventArgs e)
{
MessageBox.Show("Not implemented yet.");
return;
// Original code:
//var saveProject = Gui.CommandHandler.SaveProject();
//OnAfterProjectSaveOrOpen(saveProject);
}
private void OnFileSaveAsClicked(object sender, RoutedEventArgs e)
{
MessageBox.Show("Not implemented yet.");
return;
// Original code:
//var saveProject = Gui.CommandHandler.SaveProjectAs();
//OnAfterProjectSaveOrOpen(saveProject);
}
private void OnAfterProjectSaveOrOpen(bool actionSuccesful)
{
if (actionSuccesful)
{
AddNewMruItem(Gui.Application.ProjectFilePath);
CommitMruToSettings();
}
ValidateItems();
}
private void OnFileOpenClicked(object sender, RoutedEventArgs e)
{
MessageBox.Show("Not implemented yet.");
return;
// Original code:
//var succesful = Gui.CommandHandler.TryOpenExistingWTIProject();
//OnAfterProjectSaveOrOpen(succesful);
}
private void OnFileCloseClicked(object sender, RoutedEventArgs e)
{
Gui.CommandHandler.TryCloseWTIProject();
ValidateItems();
}
private void OnFileNewClicked(object sender, RoutedEventArgs e)
{
Gui.CommandHandler.TryCreateNewWTIProject();
ValidateItems();
}
private void OnFileExitClicked(object sender, RoutedEventArgs e)
{
Gui.Exit();
}
private string GetLayoutFilePath(string perspective)
{
string localUserSettingsDirectory = Gui.Application.GetUserSettingsDirectoryPath();
string layoutFileName = GetLayoutFileName(perspective);
return Path.Combine(localUserSettingsDirectory, layoutFileName);
}
private static string GetLayoutFileName(string perspective)
{
return "WindowLayout_" + perspective + ".xml";
}
private void OnLoadLayout(string perspective)
{
string layoutFilePath = GetLayoutFilePath(perspective);
if (!File.Exists(layoutFilePath))
{
// try to load the default file directly from the current directory
string layoutFileName = GetLayoutFileName(perspective);
UriBuilder uri = new UriBuilder(Assembly.GetExecutingAssembly().CodeBase);
string path = Uri.UnescapeDataString(uri.Path);
string assemblyDir = Path.GetDirectoryName(path);
layoutFilePath = Path.Combine(assemblyDir, layoutFileName);
if (!File.Exists(layoutFilePath))
{
return;
}
}
var layoutSerializer = new XmlLayoutSerializer(dockingManager);
//Here I've implemented the LayoutSerializationCallback just to show
// a way to feed layout desarialization with content loaded at runtime
//Actually I could in this case let AvalonDock to attach the contents
//from current layout using the content ids
//LayoutSerializationCallback should anyway be handled to attach contents
//not currently loaded
layoutSerializer.LayoutSerializationCallback += (s, e) =>
{
var c = e.Content;
/*
if (e.Model.ContentId == FileStatsViewModel.ToolContentId)
e.Content = Workspace.This.FileStats;
else if (!string.IsNullOrWhiteSpace(e.Model.ContentId) &&
File.Exists(e.Model.ContentId))
e.Content = Workspace.This.Open(e.Model.ContentId);
*/
};
try
{
layoutSerializer.Deserialize(layoutFilePath);
}
catch (InvalidOperationException)
{
// the xml was not valid. Too bad.
log.Warn(Properties.Resources.MainWindow_OnLoadLayout_Could_not_load_the_requested_dock_layout__The_settings_are_invalid_and_will_be_reset_to_the_default_state_);
return;
}
// load ribbon state
var ribbonSettingsPath = layoutFilePath + ".ribbon";
if (!File.Exists(ribbonSettingsPath))
{
return;
}
try
{
var settings = File.ReadAllText(ribbonSettingsPath).Split('|');
if (settings.Length != 2)
{
return;
}
var ribbonStateSettings = settings[0].Split(',');
Ribbon.IsMinimized = bool.Parse(ribbonStateSettings[0]);
Ribbon.ShowQuickAccessToolBarAboveRibbon = bool.Parse(ribbonStateSettings[1]);
// disabled LoadState because the ribbon elements are not correctly detected during Ribbon.LoadState,
// resulting in disappearing quickaccess items
//Ribbon.LoadState(ribbonStream);
}
catch (Exception)
{
log.Warn(Properties.Resources.MainWindow_OnLoadLayout_Could_not_restore_the_ribbon_state__The_settings_are_invalid_and_will_be_reset_to_the_default_state_);
}
}
private void OnSaveLayout(string perspective)
{
string layoutFilePath = GetLayoutFilePath(perspective);
var ribbonLayoutFilePath = layoutFilePath + ".ribbon";
if (resetDefaultLayout)
{
if (File.Exists(layoutFilePath))
{
File.Delete(layoutFilePath);
}
if (File.Exists(ribbonLayoutFilePath))
{
File.Delete(ribbonLayoutFilePath);
}
return; // Do not save when resetting
}
var layoutSerializer = new XmlLayoutSerializer(dockingManager);
layoutSerializer.Serialize(layoutFilePath);
var ribbonStream = new FileStream(ribbonLayoutFilePath, FileMode.Create);
Ribbon.SaveState(ribbonStream);
}
private void RestoreWindowAppearance()
{
WindowStartupLocation = WindowStartupLocation.Manual;
var x = Settings.Default.MainWindow_X;
var y = Settings.Default.MainWindow_Y;
var width = Settings.Default.MainWindow_Width;
var height = Settings.Default.MainWindow_Height;
var rec = new Rectangle(x, y, width, height);
if (!IsVisibleOnAnyScreen(rec))
{
width = Screen.PrimaryScreen.Bounds.Width - 200;
height = Screen.PrimaryScreen.Bounds.Height - 200;
}
var fs = Settings.Default.MainWindow_FullScreen;
Width = width;
Height = height;
if (fs)
{
WindowState = WindowState.Maximized;
}
}
private bool IsVisibleOnAnyScreen(Rectangle rect)
{
foreach (Screen screen in Screen.AllScreens)
{
if (screen.WorkingArea.IntersectsWith(rect))
{
return true;
}
}
return false;
}
private void SaveWindowAppearance()
{
if (WindowState == WindowState.Maximized)
{
Settings.Default.MainWindow_FullScreen = true;
}
else
{
Settings.Default.MainWindow_Width = (int) Width;
Settings.Default.MainWindow_Height = (int) Height;
Settings.Default.MainWindow_FullScreen = false;
}
Settings.Default.Save();
}
private void MainWindow_OnLoaded(object sender, RoutedEventArgs e)
{
AddRecentlyOpenedProjectsToFileMenu();
SetColorTheme((string) Gui.Application.UserSettings["colorTheme"]);
FileManualButton.IsEnabled = File.Exists(ConfigurationManager.AppSettings["manualFileName"]);
// Enable as soon as relevant/implemented
AboutButton.IsEnabled = false;
LicenseButton.IsEnabled = false;
FeedbackButton.IsEnabled = false;
UpdateMainWindowRibbonElements();
UpdateRibbonExtensions();
ValidateItems();
}
private void UpdateMainWindowRibbonElements()
{
resetUIButton.ToolTip = new ScreenTip
{
Title = Properties.Resources.MainWindow_UpdateMainWindowRibbonElements_Reset_layout__restart_,
Text = Properties.Resources.MainWindow_UpdateMainWindowRibbonElements_When_this_option_is_turned_on__the_default_layout_will_be_used_when_restarting_DeltaShell_,
MaxWidth = 250
};
}
private void UpdateRibbonExtensions()
{
// get all ribbon controls
ribbonCommandHandlers = Gui.Plugins.Where(p => p.RibbonCommandHandler != null).OrderBy(p => p.Name).Select(p => p.RibbonCommandHandler).ToArray();
foreach (var ribbonExtension in ribbonCommandHandlers)
{
var ribbonControl = (Ribbon) ribbonExtension.GetRibbonControl();
// fill contextual groups from plugins
foreach (var group in ribbonControl.ContextualGroups)
{
if (Ribbon.ContextualGroups.Any(g => g.Name == group.Name))
{
continue;
}
Ribbon.ContextualGroups.Add(group);
}
// fill tabs from plugins
foreach (var tab in ribbonControl.Tabs)
{
var existingTab = Ribbon.Tabs.FirstOrDefault(t => t.Header.Equals(tab.Header));
if (existingTab == null) // add new tab
{
Ribbon.Tabs.Add(tab);
existingTab = tab;
}
else
{
if (!string.IsNullOrEmpty(tab.ReduceOrder))
{
existingTab.ReduceOrder += "," + tab.ReduceOrder; // Naive implementation; Can cause duplicates to occur
}
foreach (var group in tab.Groups)
{
var existingGroup = existingTab.Groups.FirstOrDefault(g => g.Header.Equals(group.Header));
if (existingGroup == null) // add new group
{
var newGroup = new RibbonGroupBox
{
Header = group.Header,
Name = group.Name // Ensure ReduceOrder is working properly
};
// Set KeyTip for keyboard navigation:
var keys = KeyTip.GetKeys(group);
if (!string.IsNullOrEmpty(keys))
{
KeyTip.SetKeys(newGroup, keys);
}
existingTab.Groups.Add(newGroup);
existingGroup = newGroup;
}
// Set group icon if not yet set:
if (existingGroup.Icon == null && group.Icon != null)
{
existingGroup.Icon = group.Icon;
}
foreach (var item in group.Items.Cast