2013-08-26 12:42:32 +02:00
|
|
|
|
/* Copyright (c) Citrix Systems Inc.
|
|
|
|
|
* All rights reserved.
|
|
|
|
|
*
|
|
|
|
|
* Redistribution and use in source and binary forms,
|
|
|
|
|
* with or without modification, are permitted provided
|
|
|
|
|
* that the following conditions are met:
|
|
|
|
|
*
|
|
|
|
|
* * Redistributions of source code must retain the above
|
|
|
|
|
* copyright notice, this list of conditions and the
|
|
|
|
|
* following disclaimer.
|
|
|
|
|
* * Redistributions in binary form must reproduce the above
|
|
|
|
|
* copyright notice, this list of conditions and the
|
|
|
|
|
* following disclaimer in the documentation and/or other
|
|
|
|
|
* materials provided with the distribution.
|
|
|
|
|
*
|
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
|
|
|
|
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
|
|
|
|
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
|
|
|
|
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
|
|
|
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
|
|
|
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
|
|
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
|
|
|
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
|
|
|
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
|
|
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
|
|
|
|
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
|
|
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
|
|
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
|
|
|
* SUCH DAMAGE.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.ComponentModel;
|
|
|
|
|
using System.Linq;
|
|
|
|
|
using System.Text;
|
|
|
|
|
using System.Windows.Forms;
|
|
|
|
|
|
2013-08-30 14:35:32 +02:00
|
|
|
|
using XenAdmin.Alerts;
|
2013-08-26 12:42:32 +02:00
|
|
|
|
using XenAdmin.Commands;
|
|
|
|
|
using XenAdmin.XenSearch;
|
|
|
|
|
using XenAPI;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
namespace XenAdmin.Controls.MainWindowControls
|
|
|
|
|
{
|
|
|
|
|
public partial class NavigationPane : UserControl
|
|
|
|
|
{
|
2013-08-26 14:08:23 +02:00
|
|
|
|
public enum NavigationMode
|
|
|
|
|
{
|
|
|
|
|
Infrastructure, Objects, Tags, Folders, CustomFields, vApps,
|
|
|
|
|
SavedSearch, Notifications
|
|
|
|
|
}
|
2013-08-26 12:42:32 +02:00
|
|
|
|
|
|
|
|
|
private NavigationMode currentMode;
|
2013-11-19 16:42:47 +01:00
|
|
|
|
private NotificationsSubMode lastNotificationsMode = NotificationsSubMode.Alerts;
|
2013-08-26 12:42:32 +02:00
|
|
|
|
|
|
|
|
|
#region Events
|
|
|
|
|
|
2013-08-30 14:35:32 +02:00
|
|
|
|
[Browsable(true)]
|
|
|
|
|
public event Action<NavigationMode> NavigationModeChanged;
|
|
|
|
|
|
2013-08-30 16:19:59 +02:00
|
|
|
|
[Browsable(true)]
|
2013-11-07 11:00:53 +01:00
|
|
|
|
public event Action<NotificationsSubModeItem> NotificationsSubModeChanged;
|
2013-08-30 16:19:59 +02:00
|
|
|
|
|
2013-08-26 12:42:32 +02:00
|
|
|
|
[Browsable(true)]
|
|
|
|
|
public event Action TreeViewSelectionChanged;
|
|
|
|
|
|
|
|
|
|
[Browsable(true)]
|
|
|
|
|
public event Action TreeNodeBeforeSelected;
|
|
|
|
|
|
|
|
|
|
[Browsable(true)]
|
|
|
|
|
public event Action TreeNodeClicked;
|
|
|
|
|
|
|
|
|
|
[Browsable(true)]
|
|
|
|
|
public event Action TreeNodeRightClicked;
|
|
|
|
|
|
|
|
|
|
[Browsable(true)]
|
|
|
|
|
public event Action TreeViewRefreshed;
|
|
|
|
|
|
|
|
|
|
[Browsable(true)]
|
|
|
|
|
public event Action TreeViewRefreshSuspended;
|
|
|
|
|
|
|
|
|
|
[Browsable(true)]
|
|
|
|
|
public event Action TreeViewRefreshResumed;
|
|
|
|
|
|
2013-11-12 13:44:19 +01:00
|
|
|
|
internal event Action<string> DragDropCommandActivated;
|
|
|
|
|
|
2013-08-26 12:42:32 +02:00
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
public NavigationPane()
|
|
|
|
|
{
|
|
|
|
|
InitializeComponent();
|
|
|
|
|
|
2013-11-12 13:44:19 +01:00
|
|
|
|
navigationView.DragDropCommandActivated += navigationView_DragDropCommandActivated;
|
|
|
|
|
|
2013-08-26 12:42:32 +02:00
|
|
|
|
AddNavigationItemPair(buttonInfraBig, buttonInfraSmall);
|
|
|
|
|
AddNavigationItemPair(buttonObjectsBig, buttonObjectsSmall);
|
2013-08-26 14:08:23 +02:00
|
|
|
|
AddNavigationItemPair(buttonOrganizationBig, buttonOrganizationSmall);
|
2013-08-26 12:42:32 +02:00
|
|
|
|
AddNavigationItemPair(buttonSearchesBig, buttonSearchesSmall);
|
|
|
|
|
AddNavigationItemPair(buttonNotifyBig, buttonNotifySmall);
|
|
|
|
|
|
|
|
|
|
buttonInfraBig.SetTag(NavigationMode.Infrastructure);
|
|
|
|
|
buttonObjectsBig.SetTag(NavigationMode.Objects);
|
|
|
|
|
buttonNotifyBig.SetTag(NavigationMode.Notifications);
|
|
|
|
|
|
2013-08-26 14:08:23 +02:00
|
|
|
|
PopulateOrganizationDropDown();
|
|
|
|
|
|
2013-08-26 12:42:32 +02:00
|
|
|
|
Search.SearchesChanged += PopulateSearchDropDown;
|
|
|
|
|
PopulateSearchDropDown();
|
|
|
|
|
|
|
|
|
|
buttonInfraBig.Checked = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected override void OnResize(EventArgs e)
|
|
|
|
|
{
|
2014-07-08 13:54:03 +02:00
|
|
|
|
int panel2Height = splitContainer1.Panel2.Height;
|
|
|
|
|
|
2013-08-26 12:42:32 +02:00
|
|
|
|
base.OnResize(e);
|
2014-06-13 13:19:08 +02:00
|
|
|
|
|
2013-08-26 12:42:32 +02:00
|
|
|
|
splitContainer1.Panel1MinSize = splitContainer1.ClientSize.Height - toolStripBig.MaximumSize.Height - splitContainer1.SplitterWidth;
|
2014-06-13 13:19:08 +02:00
|
|
|
|
|
2014-07-08 13:54:03 +02:00
|
|
|
|
// Recalculate splitter distance so that Panel2.Height is preserved
|
|
|
|
|
splitContainer1.SplitterDistance = splitContainer1.ClientSize.Height - panel2Height - splitContainer1.SplitterWidth;
|
2013-08-26 12:42:32 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#region Accessors
|
|
|
|
|
|
|
|
|
|
private Search m_search;
|
|
|
|
|
public Search Search
|
|
|
|
|
{
|
|
|
|
|
get
|
|
|
|
|
{
|
|
|
|
|
switch (currentMode)
|
|
|
|
|
{
|
|
|
|
|
case NavigationMode.Notifications:
|
|
|
|
|
case NavigationMode.Infrastructure:
|
|
|
|
|
return TreeSearch.DefaultTreeSearch ?? TreeSearch.SearchFor(null);
|
|
|
|
|
case NavigationMode.Objects:
|
|
|
|
|
return Search.SearchForAllTypes();
|
2013-08-26 14:08:23 +02:00
|
|
|
|
case NavigationMode.Tags:
|
|
|
|
|
return Search.SearchForTags();
|
|
|
|
|
case NavigationMode.Folders:
|
2013-08-28 15:44:46 +02:00
|
|
|
|
return Search.SearchForFolders();
|
2013-08-26 14:08:23 +02:00
|
|
|
|
case NavigationMode.CustomFields:
|
|
|
|
|
return Search.SearchForCustomFields();
|
|
|
|
|
case NavigationMode.vApps:
|
|
|
|
|
return Search.SearchForVapps();
|
2013-08-26 12:42:32 +02:00
|
|
|
|
default:
|
|
|
|
|
return m_search;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public bool InSearchMode
|
|
|
|
|
{
|
|
|
|
|
set { navigationView.InSearchMode = value; }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
internal SelectionBroadcaster SelectionManager
|
|
|
|
|
{
|
|
|
|
|
get { return navigationView.SelectionManager; }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
2013-11-19 16:42:47 +01:00
|
|
|
|
public void UpdateNotificationsButton(NotificationsSubMode mode, int entries)
|
2013-08-30 14:35:32 +02:00
|
|
|
|
{
|
2013-11-19 16:42:47 +01:00
|
|
|
|
notificationsView.UpdateEntries(mode, entries);
|
2013-11-26 12:36:45 +01:00
|
|
|
|
buttonNotifyBig.UnreadEntries = buttonNotifySmall.UnreadEntries = notificationsView.GetTotalEntries();
|
2013-08-30 14:35:32 +02:00
|
|
|
|
}
|
|
|
|
|
|
2013-08-26 12:42:32 +02:00
|
|
|
|
public void XenConnectionCollectionChanged(CollectionChangeEventArgs e)
|
|
|
|
|
{
|
|
|
|
|
navigationView.XenConnectionCollectionChanged(e);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public bool SelectObject(IXenObject o)
|
|
|
|
|
{
|
|
|
|
|
return navigationView.SelectObject(o, false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void EditSelectedNode()
|
|
|
|
|
{
|
|
|
|
|
navigationView.EditSelectedNode();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public bool TryToSelectNewNode(Predicate<object> tagMatch, bool selectNode, bool expandNode, bool ensureNodeVisible)
|
|
|
|
|
{
|
|
|
|
|
return navigationView.TryToSelectNewNode(tagMatch, selectNode, expandNode, ensureNodeVisible);
|
|
|
|
|
}
|
|
|
|
|
|
2013-09-12 00:12:08 +02:00
|
|
|
|
public void UpdateSearch()
|
|
|
|
|
{
|
|
|
|
|
navigationView.CurrentSearch = Search;
|
|
|
|
|
}
|
|
|
|
|
|
2013-08-26 12:42:32 +02:00
|
|
|
|
public void RequestRefreshTreeView()
|
|
|
|
|
{
|
|
|
|
|
navigationView.RequestRefreshTreeView();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void FocusTreeView()
|
|
|
|
|
{
|
|
|
|
|
navigationView.FocusTreeView();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void SaveAndRestoreTreeViewFocus(MethodInvoker f)
|
|
|
|
|
{
|
|
|
|
|
navigationView.MajorChange(() => navigationView.SaveAndRestoreTreeViewFocus(f));
|
|
|
|
|
}
|
|
|
|
|
|
2013-11-18 15:31:00 +01:00
|
|
|
|
public void SwitchToInfrastructureMode()
|
|
|
|
|
{
|
|
|
|
|
if (!buttonInfraBig.Checked)
|
|
|
|
|
buttonInfraBig.Checked = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void SwitchToNotificationsView(NotificationsSubMode subMode)
|
2013-09-12 00:12:08 +02:00
|
|
|
|
{
|
|
|
|
|
//check the button if switching has been requested programmatically
|
|
|
|
|
if (!buttonNotifyBig.Checked)
|
|
|
|
|
buttonNotifyBig.Checked = true;
|
|
|
|
|
|
2013-11-18 15:31:00 +01:00
|
|
|
|
//show the notificationsView first and then hide the navigationView
|
|
|
|
|
//to avoid instantaneous appearance of empty panels
|
2013-09-12 00:12:08 +02:00
|
|
|
|
notificationsView.Visible = true;
|
|
|
|
|
notificationsView.SelectNotificationsSubMode(subMode);
|
|
|
|
|
navigationView.Visible = false;
|
|
|
|
|
}
|
|
|
|
|
|
2013-08-26 12:42:32 +02:00
|
|
|
|
#region Private Methods
|
|
|
|
|
|
|
|
|
|
private void AddNavigationItemPair(INavigationItem bigButton, INavigationItem smallButton)
|
|
|
|
|
{
|
|
|
|
|
bigButton.PairedItem = smallButton;
|
|
|
|
|
smallButton.PairedItem = bigButton;
|
|
|
|
|
bigButton.NavigationViewChanged += NavigationViewChanged;
|
|
|
|
|
smallButton.NavigationViewChanged += NavigationViewChanged;
|
|
|
|
|
}
|
|
|
|
|
|
2013-08-26 14:08:23 +02:00
|
|
|
|
private void PopulateOrganizationDropDown()
|
|
|
|
|
{
|
|
|
|
|
toolStripMenuItemFields.Tag = NavigationMode.CustomFields;
|
|
|
|
|
toolStripMenuItemFolders.Tag = NavigationMode.Folders;
|
|
|
|
|
toolStripMenuItemTags.Tag = NavigationMode.Tags;
|
|
|
|
|
toolStripMenuItemVapps.Tag = NavigationMode.vApps;
|
|
|
|
|
|
|
|
|
|
var items = from ToolStripItem item in buttonOrganizationBig.DropDownItems select item;
|
|
|
|
|
buttonOrganizationBig.SetItemList(items.ToArray());
|
|
|
|
|
}
|
|
|
|
|
|
2013-08-26 12:42:32 +02:00
|
|
|
|
private void PopulateSearchDropDown()
|
|
|
|
|
{
|
|
|
|
|
Search[] searches = Search.Searches;
|
|
|
|
|
Array.Sort(searches);
|
|
|
|
|
|
|
|
|
|
var itemList = new List<ToolStripMenuItem>();
|
|
|
|
|
|
|
|
|
|
foreach (Search search in searches)
|
|
|
|
|
{
|
|
|
|
|
var item = new ToolStripMenuItem
|
|
|
|
|
{
|
|
|
|
|
Text = search.Name.EscapeAmpersands(),
|
|
|
|
|
Tag = search,
|
|
|
|
|
Image = search.DefaultSearch
|
|
|
|
|
? Properties.Resources._000_defaultSpyglass_h32bit_16
|
|
|
|
|
: Properties.Resources._000_Search_h32bit_16,
|
|
|
|
|
|
|
|
|
|
};
|
|
|
|
|
itemList.Add(item);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
buttonSearchesBig.SetItemList(itemList.ToArray());
|
|
|
|
|
}
|
|
|
|
|
|
2013-09-12 00:12:08 +02:00
|
|
|
|
private void OnNavigationModeChanged()
|
2013-08-26 12:42:32 +02:00
|
|
|
|
{
|
2013-08-30 14:35:32 +02:00
|
|
|
|
if (currentMode == NavigationMode.Notifications)
|
|
|
|
|
{
|
2013-11-19 16:42:47 +01:00
|
|
|
|
//restore the last selected view
|
|
|
|
|
SwitchToNotificationsView(lastNotificationsMode);
|
2013-08-30 14:35:32 +02:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2013-11-18 15:31:00 +01:00
|
|
|
|
//show the navigationView first and then hide the notificationsView
|
|
|
|
|
//to avoid instantaneous appearance of empty panels
|
2013-08-30 14:35:32 +02:00
|
|
|
|
navigationView.Visible = true;
|
2013-11-18 15:31:00 +01:00
|
|
|
|
notificationsView.Visible = false;
|
2013-08-30 14:35:32 +02:00
|
|
|
|
|
|
|
|
|
navigationView.CurrentSearch = Search;
|
|
|
|
|
navigationView.NavigationMode = currentMode;
|
|
|
|
|
navigationView.ResetSeachBox();
|
|
|
|
|
navigationView.RequestRefreshTreeView();
|
|
|
|
|
navigationView.FocusTreeView();
|
2013-11-18 15:31:00 +01:00
|
|
|
|
|
|
|
|
|
if (navigationView.SelectionManager.Selection.Count < 1)
|
|
|
|
|
navigationView.SelectObject(null, false);
|
2013-08-30 14:35:32 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (NavigationModeChanged != null)
|
|
|
|
|
NavigationModeChanged(currentMode);
|
2013-08-26 12:42:32 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
#region Control Event Handlers
|
|
|
|
|
|
2013-11-12 13:44:19 +01:00
|
|
|
|
private void navigationView_DragDropCommandActivated(string cmdText)
|
|
|
|
|
{
|
|
|
|
|
if (DragDropCommandActivated != null)
|
|
|
|
|
DragDropCommandActivated(cmdText);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2013-08-26 12:42:32 +02:00
|
|
|
|
private void navigationView_TreeViewSelectionChanged()
|
|
|
|
|
{
|
|
|
|
|
if (TreeViewSelectionChanged != null)
|
|
|
|
|
TreeViewSelectionChanged();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void navigationView_TreeNodeBeforeSelected()
|
|
|
|
|
{
|
|
|
|
|
if (TreeNodeBeforeSelected != null)
|
|
|
|
|
TreeNodeBeforeSelected();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void navigationView_TreeNodeClicked()
|
|
|
|
|
{
|
|
|
|
|
if (TreeNodeClicked != null)
|
|
|
|
|
TreeNodeClicked();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void navigationView_TreeNodeRightClicked()
|
|
|
|
|
{
|
|
|
|
|
if (TreeNodeRightClicked != null)
|
|
|
|
|
TreeNodeRightClicked();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void navigationView_TreeViewRefreshed()
|
|
|
|
|
{
|
|
|
|
|
if (TreeViewRefreshed != null)
|
|
|
|
|
TreeViewRefreshed();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void navigationView_TreeViewRefreshResumed()
|
|
|
|
|
{
|
|
|
|
|
if (TreeViewRefreshResumed != null)
|
|
|
|
|
TreeViewRefreshResumed();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void navigationView_TreeViewRefreshSuspended()
|
|
|
|
|
{
|
|
|
|
|
if (TreeViewRefreshSuspended != null)
|
|
|
|
|
TreeViewRefreshSuspended();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private void NavigationViewChanged(object obj)
|
|
|
|
|
{
|
|
|
|
|
var search = obj as Search;
|
|
|
|
|
|
|
|
|
|
if (search == null)
|
|
|
|
|
{
|
|
|
|
|
currentMode = (NavigationMode)obj;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
m_search = search;
|
|
|
|
|
currentMode = NavigationMode.SavedSearch;
|
|
|
|
|
}
|
|
|
|
|
|
2013-09-12 00:12:08 +02:00
|
|
|
|
OnNavigationModeChanged();
|
2013-08-26 12:42:32 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void toolStripBig_LayoutCompleted(object sender, EventArgs e)
|
|
|
|
|
{
|
|
|
|
|
foreach (ToolStripItem item in toolStripBig.Items)
|
|
|
|
|
{
|
|
|
|
|
var navItem = item as INavigationItem;
|
|
|
|
|
if (navItem == null)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
var pairedItem = navItem.PairedItem as ToolStripItem;
|
|
|
|
|
if (pairedItem == null)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
pairedItem.Visible = (item.Placement == ToolStripItemPlacement.None);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-11-07 11:00:53 +01:00
|
|
|
|
private void notificationsView_NotificationsSubModeChanged(NotificationsSubModeItem subModeItem)
|
2013-08-30 16:19:59 +02:00
|
|
|
|
{
|
2013-11-19 16:42:47 +01:00
|
|
|
|
lastNotificationsMode = subModeItem.SubMode;
|
|
|
|
|
|
2013-08-30 16:19:59 +02:00
|
|
|
|
if (NotificationsSubModeChanged != null)
|
2013-11-07 11:00:53 +01:00
|
|
|
|
NotificationsSubModeChanged(subModeItem);
|
2013-08-30 16:19:59 +02:00
|
|
|
|
}
|
|
|
|
|
|
2013-08-26 12:42:32 +02:00
|
|
|
|
#endregion
|
|
|
|
|
}
|
|
|
|
|
}
|