public override void LoadConfig(XmlElement element) { base.LoadConfig(element); foreach (var itemElementAsXmlNode in element.ChildNodes) { // TODO: I hope this never fails. Maybe check ahead of time? XmlElement itemElement = (XmlElement)itemElementAsXmlNode; PieItem subItem = null; // Fill with default values // The rest of the values will be filled in after calling LoadConfig() on this. switch (itemElement.Name) { case PieFolderItem.TYPE_NAME: // (except we need to fill with prevFolder now) subItem = new PieFolderItem(false, null, false, null, this); break; case FileItem.TYPE_NAME: subItem = new FileItem(false, null, false, null, null, null, FileItemType.File); break; default: // This should NEVER happen. // TODO: Add error message if it does? break; } // This should NEVER be null afterwards. subItem.LoadConfig(itemElement); Items.Add(subItem); } }
// This is a bit more complicated. // We have to account for all the stuff that hovering over/pressing/etc... on an item does. private void CreateDisplayInfo(PieItem pieItem, int number, int totalItems) { ItemDisplayInfo itemInfo = new ItemDisplayInfo(); // The PieItem itemInfo.Item = pieItem; // The Button control to be used in the main window. // Here, we set the non-user-configurable options. itemInfo.ItemButton = new Button(); itemInfo.ItemButton.HorizontalAlignment = HorizontalAlignment.Center; itemInfo.ItemButton.VerticalAlignment = VerticalAlignment.Center; itemInfo.ItemButton.Background = System.Windows.Media.Brushes.Transparent; itemInfo.ItemButton.BorderBrush = System.Windows.Media.Brushes.Transparent; // Currently just a blank image, will actually be set to something later on. var itemImage = new System.Windows.Controls.Image(); itemInfo.ItemButton.Content = itemImage; // The Label control to be used in the main window. itemInfo.ItemLabel = new Label(); itemInfo.ItemLabel.HorizontalAlignment = HorizontalAlignment.Center; itemInfo.ItemLabel.VerticalAlignment = VerticalAlignment.Center; // This fixes the flashing button issue if the mouse is on top of both the button and the label. itemInfo.ItemLabel.IsHitTestVisible = false; // Invisible by default. Will activate only on mouse hover on button. itemInfo.ItemLabel.Visibility = Visibility.Hidden; UpdateItemAppearance(itemInfo, number, totalItems); itemInfo.ItemButton.MouseEnter += (s, e) => { itemInfo.ItemLabel.Visibility = Visibility.Visible; }; itemInfo.ItemButton.MouseLeave += (s, e) => { itemInfo.ItemLabel.Visibility = Visibility.Hidden; }; // Handle custom clicking and dragging in these next three functions. // MouseDown just means the mouse has been pressed down on the button. // Dragging means the mouse has moved past the given threshold while MouseDown and we started visually dragging. itemInfo.ItemButton.PreviewMouseLeftButtonDown += (s, e) => { itemInfo.MouseDown = true; itemInfo.InitialMousePosition = Mouse.GetPosition(mainGrid); }; itemInfo.ItemButton.PreviewMouseLeftButtonUp += (s, e) => { if (itemInfo.Dragging) { RefreshFolder(); Config.SaveItems(RootFolder); } else { itemInfo.Item.LeftClick(this); } itemInfo.MouseDown = false; itemInfo.Dragging = false; itemInfo.ItemButton.RenderTransform = Transform.Identity; itemInfo.ItemLabel.RenderTransform = Transform.Identity; }; itemInfo.ItemButton.PreviewMouseMove += (s, e) => { if (!itemInfo.MouseDown) { return; } var currentMousePoint = Mouse.GetPosition(mainGrid); if (itemInfo.Dragging) { // TODO: Constantly creating a bunch of new objects here feels inefficient. var offset = new TranslateTransform(currentMousePoint.X - itemInfo.InitialMousePosition.X, currentMousePoint.Y - itemInfo.InitialMousePosition.Y); itemInfo.ItemButton.RenderTransform = offset; itemInfo.ItemLabel.RenderTransform = offset; // TODO: Handle item swapping here. System.Windows.Point centerPoint = new System.Windows.Point(mainGrid.Width / 2, mainGrid.Height / 2); double angle = Math.Atan2(currentMousePoint.Y - centerPoint.Y, currentMousePoint.X - centerPoint.X); // Make between $0$ and $2\pi$ if (angle < 0) { angle += 2 * Math.PI; } // itemInfo.ItemLabel.Content = angle.ToString(); // You're gonna need to draw a picture for this. // Sorry ahead of time. int oldPosition = CurrentFolder.Items.IndexOf(itemInfo.Item); int halfSpaces = (int)(2 * angle / (2 * Math.PI / CurrentFolder.Items.Count)); int newPosition; // Probably will never get strict inequality, but safety for roundoff nonsense. if (halfSpaces <= 0 || halfSpaces >= 2 * CurrentFolder.Items.Count - 1) { newPosition = 0; } else { newPosition = (halfSpaces + 1) / 2; } //itemInfo.ItemLabel.Content = oldPosition.ToString(); // Swap oldPosition and newPosition if (newPosition != oldPosition) { if (oldPosition < newPosition) { CurrentFolder.Items.Insert(newPosition + 1, itemInfo.Item); CurrentFolder.Items.RemoveAt(oldPosition); } else // newPosition < oldPosition { CurrentFolder.Items.Insert(newPosition, itemInfo.Item); CurrentFolder.Items.RemoveAt(oldPosition + 1); } // TODO: The behaviour when "swapping" the last and first items might not be // exactly what the user expects. Investigate making this more intuitive? RefreshFolder(); // Start dragging the new Button that was generated during RefreshFolder(). // Here's a cheap way to pull this off. Just replace the new one with the old one. int newInfoIndex = ItemDisplayInfos.FindIndex((s) => { return(s.Item == itemInfo.Item); }); mainGrid.Children.Remove(ItemDisplayInfos[newInfoIndex].ItemButton); mainGrid.Children.Remove(ItemDisplayInfos[newInfoIndex].ItemLabel); ItemDisplayInfos[newInfoIndex] = itemInfo; mainGrid.Children.Add(itemInfo.ItemButton); mainGrid.Children.Add(itemInfo.ItemLabel); } } else { if (System.Windows.Point.Subtract(currentMousePoint, itemInfo.InitialMousePosition).Length >= Config.PieItemDragSensitivity) // TODO: Implement custom tolerances { itemInfo.Dragging = true; } } }; // Create the context menu MenuItem settingsMenuItem = new MenuItem(); settingsMenuItem.Header = "Item settings"; settingsMenuItem.Click += (s, e) => { PieItemSettingsWindow pieItemSettingsWindow = new PieItemSettingsWindow(pieItem, CurrentFolder); pieItemSettingsWindow.ShowDialog(); // Replace the old pieItem with the new one if (pieItemSettingsWindow.Saved) { int i = CurrentFolder.Items.IndexOf(pieItem); // You know, I feel like this should never happen if (i == -1) { return; } CurrentFolder.Items[i] = pieItemSettingsWindow.NewPieItem; RefreshFolder(); Config.SaveItems(RootFolder); } }; MenuItem removeMenuItem = new MenuItem(); removeMenuItem.Header = "Remove"; removeMenuItem.Click += (s, e) => { CurrentFolder.Items.Remove(pieItem); RefreshFolder(); Config.SaveItems(RootFolder); }; itemInfo.ItemButton.ContextMenu = new ContextMenu(); itemInfo.ItemButton.ContextMenu.Items.Add(settingsMenuItem); itemInfo.ItemButton.ContextMenu.Items.Add(removeMenuItem); //TODO: Figure out transparency of background/border on hover. ItemDisplayInfos.Add(itemInfo); }
/* * containingFolder is the folder that contains this PieItem. */ public PieItemSettingsWindow(PieItem item, PieFolderItem containingFolder) : this() { OldPieItem = item; NewPieItem = item; // TODO: Feels mildly clunky. Rewrite? ContainingFolder = containingFolder; Saved = false; if (item.IsCustomName) { textBoxName.Text = (item.Name == null) ? "" : item.Name; checkBoxName.IsChecked = true; checkBoxName_Checked(null, null); } else { checkBoxName.IsChecked = false; checkBoxName_Unchecked(null, null); } if (item.IsCustomIcon) { textBoxIcon.Text = (item.Icon.ImagePath == null) ? "" : item.Icon.ImagePath; checkBoxIcon.IsChecked = true; checkBoxIcon_Checked(null, null); } else { checkBoxIcon.IsChecked = false; checkBoxIcon_Unchecked(null, null); } // Type-specific configuration. if (item is PieFolderItem) { radioButtonPieFolder.IsChecked = true; radioButtonPieFolder_Checked(null, null); } else if (item is FileItem) { switch (((FileItem)item).Type) { case FileItemType.File: radioButtonFile.IsChecked = true; radioButtonFile_Checked(null, null); break; case FileItemType.Folder: radioButtonFolder.IsChecked = true; radioButtonFolder_Checked(null, null); break; case FileItemType.Other: radioButtonOther.IsChecked = true; radioButtonOther_Checked(null, null); break; } textBoxTarget.Text = (((FileItem)item).FilePath == null) ? "" : ((FileItem)item).FilePath; textBoxArguments.Text = (((FileItem)item).Arguments == null) ? "" : ((FileItem)item).Arguments; } }