using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.IO;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Media.Effects;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Interop;
using BuzzGUI.Interfaces;
using BuzzGUI.Common;
using BuzzGUI.Common.InterfaceExtensions;
using System.ComponentModel;
using PropertyChanged;
namespace BuzzGUI.MachineView
{
///
/// Interaction logic for MachineView.xaml
///
///
[DoNotNotify]
public partial class MachineView : UserControl, INotifyPropertyChanged
{
IMachineGraph machineGraph;
public IMachineGraph MachineGraph
{
get { return machineGraph; }
set
{
if (machineGraph != null)
{
machineGraph.PropertyChanged -= new System.ComponentModel.PropertyChangedEventHandler(machineGraph_PropertyChanged);
machineGraph.MachineAdded -= new Action(machineGraph_MachineAdded);
machineGraph.MachineRemoved -= new Action(machineGraph_MachineRemoved);
machineGraph.ConnectionAdded -= new Action(machineGraph_ConnectionAdded);
machineGraph.ConnectionRemoved -= new Action(machineGraph_ConnectionRemoved);
ClearMachines();
}
machineGraph = value;
if (machineGraph != null)
{
machineGraph.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler(machineGraph_PropertyChanged);
machineGraph.MachineAdded += new Action(machineGraph_MachineAdded);
machineGraph.MachineRemoved += new Action(machineGraph_MachineRemoved);
machineGraph.ConnectionAdded += new Action(machineGraph_ConnectionAdded);
machineGraph.ConnectionRemoved += new Action(machineGraph_ConnectionRemoved);
AddAllMachines();
}
if (cpuMonitorWindow != null)
cpuMonitorWindow.MachineGraph = value;
if (hdRecorderWindow != null)
hdRecorderWindow.MachineGraph = value;
}
}
void machineGraph_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
}
void AddAllMachines()
{
machineCanvas.Children.Clear();
foreach (IMachine i in machineGraph.Machines)
machineGraph_MachineAdded(i);
foreach (IMachine i in machineGraph.Machines)
foreach (var mc in i.Inputs)
machineGraph_ConnectionAdded(mc);
PropertyChanged.Raise(this, "Machines");
PropertyChanged.Raise(this, "SelectedMachines");
}
void ClearMachines()
{
foreach (MachineControl mc in machineCanvas.Children)
mc.Release();
machineCanvas.Children.Clear();
PropertyChanged.Raise(this, "Machines");
PropertyChanged.Raise(this, "SelectedMachines");
}
void machineGraph_MachineAdded(IMachine m)
{
machineCanvas.Children.Add(new MachineControl(this) { Machine = m } );
PropertyChanged.Raise(this, "Machines");
PropertyChanged.Raise(this, "SelectedMachines");
}
void machineGraph_MachineRemoved(IMachine m)
{
var mc = GetMachineControl(m);
mc.Release();
machineCanvas.Children.Remove(mc);
PropertyChanged.Raise(this, "Machines");
PropertyChanged.Raise(this, "SelectedMachines");
}
void machineGraph_ConnectionAdded(IMachineConnection mc)
{
MachineControl src = GetMachineControl(mc.Source);
MachineControl dst = GetMachineControl(mc.Destination);
Connection c = new Connection(mc, this, src, dst, new Point(0, 0));
dst.inputs.Add(c);
src.outputs.Add(c);
if (dst.Machine.IsWireless)
src.UpdateWirelessOutputs();
}
void machineGraph_ConnectionRemoved(IMachineConnection mc)
{
MachineControl src = GetMachineControl(mc.Source);
MachineControl dst = GetMachineControl(mc.Destination);
var c = dst.inputs.First(x => x.MachineConnection == mc);
c.RemoveVisuals();
dst.inputs.Remove(c);
src.outputs.Remove(c);
if (dst.Machine.IsWireless)
src.UpdateWirelessOutputs();
}
public IEnumerable Machines { get { return machineCanvas.Children.Cast(); } }
public IEnumerable SelectedMachines { get { return Machines.Where(x => x.IsSelected); } }
public MachineControl GetMachineControl(IMachine m) { return Machines.FirstOrDefault(x => x.Machine == m); }
public IEnumerable Connections { get { return Machines.SelectMany(m => m.inputs); } }
public bool IsSoloActive { get { return Machines.Any(m => m.Machine.IsSoloed); } }
internal AmpControl ampControl;
public IBuzz Buzz { get; set; }
public static MachineViewSettings StaticSettings = new MachineViewSettings();
public MachineViewSettings Settings { get { return StaticSettings; } }
Zoomer zoomer;
public Zoomer Zoomer { get { return zoomer; } set { zoomer = value; PropertyChanged.Raise(this, "Zoomer"); } }
internal Point contextMenuPoint = new Point(-1, -1);
ListBoxItemDragSource machineListDragSource;
ListBoxItemDragSource templateListDragSource;
ListBoxItemDragSource mdbListDragSource;
public ParametersTab.ParametersTabVM ParametersTabVM { get; private set; }
public MDBTab.MDBTabVM MDBTabVM { get; private set; }
public MachineList MachineList { get; private set; }
void GeneralSettings_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
switch (e.PropertyName)
{
case "WPFIdealFontMetrics":
PropertyChanged.Raise(this, "TextFormattingMode");
break;
}
}
void Settings_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
switch (e.PropertyName)
{
case "ZoomMouseGesture":
zoomer.Ctrl = Settings.ZoomMouseGesture == ZoomMouseGestures.CtrlMouseWheel;
break;
case "ShowCurvedWires":
foreach (var c in Connections)
{
if (Settings.ShowCurvedWires)
{
c.PlugSnapping = 4;
c.CurvedWires = true;
}
else
{
c.PlugSnapping = 0;
c.CurvedWires = false;
}
c.Invalidate();
}
break;
case "ChannelOnWire":
foreach (var c in Connections)
c.Invalidate();
break;
case "DefaultZoomLevel":
Zoomer.Level = Settings.DefaultZoomLevel;
break;
}
}
SimpleCommand NewMachineCommand { get; set; }
SimpleCommand ReplaceMachineCommand { get; set; }
SimpleCommand InsertMachineCommand { get; set; }
public ICommand ImportSongCommand { get; private set; }
public ICommand UnmuteAllMachinesCommand { get; private set; }
public ICommand SettingsCommand { get; private set; }
public SimpleCommand SelectAllCommand { get; private set; }
public ICommand DeselectCommand { get; private set; }
public ICommand DeleteSelectedCommand { get; private set; }
public ICommand CutCommand { get; private set; }
public ICommand CopyCommand { get; private set; }
public ICommand PasteCommand { get; private set; }
public ICommand CreateTemplateCommand { get; private set; }
public ICommand TemplateListParentCommand { get; private set; }
void Commands()
{
NewMachineCommand = new SimpleCommand
{
CanExecuteDelegate = x => true,
ExecuteDelegate = id =>
{
var p = CommandCanvasPosition;
machineGraph.CreateMachine((int)id, (float)p.X, (float)p.Y);
}
};
ReplaceMachineCommand = new SimpleCommand
{
CanExecuteDelegate = x => true,
ExecuteDelegate = id =>
{
var p = CommandCanvasPosition;
if (SelectedMachines.Count() == 1)
machineGraph.ReplaceMachine(SelectedMachines.FirstOrDefault().Machine, (int)id, (float)p.X, (float)p.Y);
}
};
InsertMachineCommand = new SimpleCommand
{
CanExecuteDelegate = x => true,
ExecuteDelegate = id =>
{
var p1 = insertMachineConnection.Source.Position;
var p2 = insertMachineConnection.Destination.Position;
machineGraph.InsertMachine(insertMachineConnection, (int)id, 0.5f * (p1.Item1 + p2.Item1), 0.5f * (p1.Item2 + p2.Item2));
}
};
ImportSongCommand = new SimpleCommand
{
CanExecuteDelegate = x => true,
ExecuteDelegate = id =>
{
var p = CommandCanvasPosition;
machineGraph.ImportSong((float)p.X, (float)p.Y);
}
};
UnmuteAllMachinesCommand = new SimpleCommand
{
CanExecuteDelegate = x => true,
ExecuteDelegate = x => { foreach (var m in Machines) { m.Machine.IsMuted = false; m.Machine.IsSoloed = false; } }
};
SelectAllCommand = new SimpleCommand
{
CanExecuteDelegate = x => true,
ExecuteDelegate = x => { foreach (var m in Machines) m.IsSelected = true; }
};
DeselectCommand = new SimpleCommand
{
CanExecuteDelegate = x => SelectedMachines.Count() > 0,
ExecuteDelegate = x => { ClearSelection(); }
};
DeleteSelectedCommand = new SimpleCommand
{
CanExecuteDelegate = x => SelectedMachines.Count() > 0,
ExecuteDelegate = x => { DeleteMachines(SelectedMachines.Select(m => m.Machine)); }
};
SettingsCommand = new SimpleCommand
{
CanExecuteDelegate = x => true,
ExecuteDelegate = x =>
{
SettingsWindow.Show(this, "Machine View");
}
};
CutCommand = new SimpleCommand
{
CanExecuteDelegate = x => SelectedMachines.Count() > 0,
ExecuteDelegate = x =>
{
using (new ActionGroup(machineGraph))
{
CopySelectedMachines();
DeleteMachines(SelectedMachines.Select(m => m.Machine));
}
}
};
CopyCommand = new SimpleCommand
{
CanExecuteDelegate = x => SelectedMachines.Count() > 0,
ExecuteDelegate = x =>
{
CopySelectedMachines();
}
};
PasteCommand = new SimpleCommand
{
CanExecuteDelegate = x =>
{
var s = ClipboardEx.GetText();
return BuzzGUI.Common.Templates.Template.IsValidTemplateString(s) || BuzzGUI.Common.Presets.Preset.IsValidPresetString(s);
},
ExecuteDelegate = p =>
{
if (p is Point)
PasteMachines((Point)p);
else
PasteMachines(CommandCanvasPosition);
}
};
CreateTemplateCommand = new SimpleCommand
{
CanExecuteDelegate = x => SelectedMachines.Count() > 0,
ExecuteDelegate = x => { CreateTemplate(); }
};
TemplateListParentCommand = new SimpleCommand
{
CanExecuteDelegate = x => templateList != null && !templateList.IsAtRoot,
ExecuteDelegate = x => { templateList.SetDirectory(".."); }
};
this.InputBindings.Add(new InputBinding(SettingsCommand, new KeyGesture(Key.E, ModifierKeys.Control)));
this.InputBindings.Add(new InputBinding(SelectAllCommand, new KeyGesture(Key.A, ModifierKeys.Control)));
this.InputBindings.Add(new InputBinding(DeselectCommand, new KeyGesture(Key.D, ModifierKeys.Control)));
this.InputBindings.Add(new InputBinding(DeleteSelectedCommand, new KeyGesture(Key.Delete)));
this.InputBindings.Add(new InputBinding(UnmuteAllMachinesCommand, new KeyGesture(Key.U, ModifierKeys.Control)));
this.InputBindings.Add(new InputBinding(CutCommand, new KeyGesture(Key.X, ModifierKeys.Control)));
this.InputBindings.Add(new InputBinding(CopyCommand, new KeyGesture(Key.C, ModifierKeys.Control)));
this.InputBindings.Add(new InputBinding(PasteCommand, new KeyGesture(Key.V, ModifierKeys.Control)));
}
public MachineView(IBuzz buzz, ResourceDictionary rd)
{
Global.GeneralSettings.PropertyChanged += new PropertyChangedEventHandler(GeneralSettings_PropertyChanged);
Settings.PropertyChanged += Settings_PropertyChanged;
SettingsWindow.AddSettings("Machine View", Settings);
Buzz = buzz;
this.DataContext = this;
if (rd != null) this.Resources.MergedDictionaries.Add(rd);
Commands();
ParametersTabVM = new ParametersTab.ParametersTabVM(this);
MachineList = new MachineList(this);
MDBTabVM = new MDBTab.MDBTabVM(this);
InitializeComponent();
ampControl = new AmpControl(rd)
{
Visibility = Visibility.Hidden
};
ampCanvas.Children.Add(ampControl);
this.Loaded += new RoutedEventHandler(MachineView_Loaded);
viewGrid.SizeChanged += new SizeChangedEventHandler(MachineView_SizeChanged);
grid.GotFocus += new RoutedEventHandler(grid_GotFocus);
containerCanvas.DataContext = this;
containerCanvas.Style = FindResource("ContainerCanvasStyle") as Style;
this.TextInput += (sender, e) =>
{
if (e.Text.Length == 1 && ((e.Text[0] >= 'a' && e.Text[0] <= 'z') || (e.Text[0] >= 'A' && e.Text[0] <= 'Z') || (e.Text[0] >= '0' && e.Text[0] <= '9')))
{
if (!viewGrid.IsPointInside(Win32Mouse.GetPosition(viewGrid))) return;
var pos = machineCanvas.GetPositionAtPoint(Win32Mouse.GetPosition(machineCanvas));
var moc = MouseOverConnection;
var w = new QuickNewMachineWindow(this, e.Text[0])
{
Resources = this.Resources.MergedDictionaries[0]
};
new WindowInteropHelper(w).Owner = ((HwndSource)PresentationSource.FromVisual(this)).Handle;
if ((bool)w.ShowDialog() && w.SelectedItem != null)
{
if (moc != null && w.SelectedItem.Instrument.Type == InstrumentType.Effect)
{
machineGraph.InsertMachine(moc.MachineConnection,
w.SelectedItem.Instrument.MachineDLL.Name, w.SelectedItem.Instrument.Name,
0.5f * (moc.Source.Machine.Position.Item1 + moc.Destination.Machine.Position.Item1),
0.5f * (moc.Source.Machine.Position.Item2 + moc.Destination.Machine.Position.Item2));
}
else
{
CreateInstrument(w.SelectedItem.Instrument, (float)pos.X, (float)pos.Y);
}
}
}
};
machineListDragSource = new ListBoxItemDragSource(machineListBox);
mdbListDragSource = new ListBoxItemDragSource(mdbListBox);
machineListSearchTextBox.Search += (sender, e) => { MachineList.Filter = machineListSearchTextBox.Text; };
mdbListSearchTextBox.Search += (sender, e) => { MDBTabVM.Filter = mdbListSearchTextBox.Text; };
machineListSearchTextBox.PreviewKeyDown += (sender, e) =>
{
if (e.Key == Key.Down)
{
if (machineListBox.SelectedIndex == -1)
machineListBox.SelectedIndex = 0;
else
{
if (machineListBox.SelectedIndex < machineListBox.Items.Count - 1)
{
machineListBox.SelectedIndex++;
machineListBox.ScrollIntoView(machineListBox.SelectedItem);
}
}
}
else if (e.Key == Key.Up)
{
if (machineListBox.SelectedIndex != -1 && machineListBox.SelectedIndex > 0)
{
machineListBox.SelectedIndex--;
machineListBox.ScrollIntoView(machineListBox.SelectedItem);
}
}
else if (e.Key == Key.Return)
{
if (machineListBox.SelectedItem != null)
{
CreateInstrument((machineListBox.SelectedItem as MachineListItemVM).Instrument, 0, 0);
}
}
};
templateListDragSource = new ListBoxItemDragSource(templateListBox);
templateListSearchTextBox.Search += (sender, e) => { TemplateList.Filter = templateListSearchTextBox.Text; };
}
public void Release()
{
Global.GeneralSettings.PropertyChanged -= GeneralSettings_PropertyChanged;
Settings.PropertyChanged -= Settings_PropertyChanged;
ParametersTabVM.Release();
MDBTabVM.Release();
templateList.Release();
}
void grid_GotFocus(object sender, RoutedEventArgs e)
{
ClearSelection();
//machineGraph.Buzz.MIDIFocusMachine = null; // useless?
e.Handled = true;
}
void MachineView_Loaded(object l_sender, RoutedEventArgs l_e)
{
new Dragger
{
Element = this,
Gesture = new DragMouseGesture { Button = MouseButton.Middle },
AlternativeGesture = new DragMouseGesture { Button = MouseButton.Left, Modifiers = ModifierKeys.Shift },
DragCursor = Cursors.ScrollAll,
Drag = delta =>
{
sv.ScrollToHorizontalOffset(sv.HorizontalOffset - delta.X);
sv.ScrollToVerticalOffset(sv.VerticalOffset - delta.Y);
}
};
Zoomer = new Zoomer
{
Element = grid,
LevelCount = 8,
Ctrl = Settings.ZoomMouseGesture == ZoomMouseGestures.CtrlMouseWheel,
Reset = () =>
{
sv.ScrollToHorizontalOffset(machineCanvas.Width / 2 - sv.ViewportWidth / 2);
sv.ScrollToVerticalOffset(machineCanvas.Height / 2 - sv.ViewportHeight / 2);
},
Level = Settings.DefaultZoomLevel
};
List oldSelection = new List();
new Dragger
{
Element = viewGrid,
Gesture = new DragMouseGesture { Button = MouseButton.Left },
AlternativeGesture = new DragMouseGesture { Button = MouseButton.Left, Modifiers = ModifierKeys.Control },
Mode = DraggerMode.Absolute,
BeginDrag = (p, alt, cc) =>
{
if (!alt)
{
grid.Focus();
oldSelection = new List();
}
else
{
oldSelection = new List(SelectedMachines);
}
selectionLayer.BeginSelect(p);
foreach (var m in Machines) m.IsSelected = (m.GetBounds(viewGrid).Contains(p) || oldSelection.Contains(m));
},
Drag = p =>
{
Rect r = selectionLayer.UpdateSelect(p);
foreach (var m in Machines) m.IsSelected = (m.GetBounds(viewGrid).IntersectsWith(r) || oldSelection.Contains(m));
},
EndDrag = p =>
{
selectionLayer.EndSelect(p);
PropertyChanged.Raise(this, "SelectedMachines");
}
};
viewGrid.MouseLeftButtonDown += (sender, e) =>
{
if (e.ClickCount == 2)
{
Point p = e.GetPosition(this);
machineGraph.DoubleClick((int)p.X, (int)p.Y);
e.Handled = true;
}
};
mainGrid.ContextMenuOpening += (sender, e) =>
{
contextMenuPoint.X = e.CursorLeft;
contextMenuPoint.Y = e.CursorTop;
};
mainGrid.ContextMenuClosing += (sender, e) =>
{
contextMenuPoint = new Point(-1, -1);
};
grid.DragEnter += (sender, e) => { UpdateDragEffect(e); };
grid.DragOver += (sender, e) => { UpdateDragEffect(e); };
grid.Drop += (sender, e) =>
{
if (e.Data.GetDataPresent(typeof(MachineListItemVM)))
{
var mli = e.Data.GetData(typeof(MachineListItemVM)) as MachineListItemVM;
var p = machineCanvas.GetPositionAtPoint(e.GetPosition(machineCanvas));
CreateInstrument(mli.Instrument, (float)p.X, (float)p.Y);
e.Handled = true;
}
if (e.Data.GetDataPresent(typeof(MDBTab.MachineListItemVM)))
{
var mli = e.Data.GetData(typeof(MDBTab.MachineListItemVM)) as MDBTab.MachineListItemVM;
var p = machineCanvas.GetPositionAtPoint(e.GetPosition(machineCanvas));
CreateInstrument(mli.Instrument, (float)p.X, (float)p.Y);
e.Handled = true;
}
else if (e.Data.GetDataPresent(typeof(TemplateListItemVM)))
{
var tli = e.Data.GetData(typeof(TemplateListItemVM)) as TemplateListItemVM;
var p = machineCanvas.GetPositionAtPoint(e.GetPosition(machineCanvas));
PasteTemplate(tli.Path, p);
e.Handled = true;
}
else if (e.Data.GetDataPresent(DataFormats.FileDrop))
{
var filenames = (string[])e.Data.GetData(DataFormats.FileDrop);
PasteTemplate(filenames[0], CommandCanvasPosition);
}
};
mainGrid.ColumnDefinitions[1].Width = new GridLength(RegistryEx.Read("SidebarWidth", 300.0));
sidebar.SizeChanged += (sender, e) =>
{
if (e.WidthChanged)
RegistryEx.Write("SidebarWidth", mainGrid.ColumnDefinitions[1].Width);
};
loaded = true;
}
public void OnBuzzInitComplete()
{
// instrument list is now ready
MachineList.Update();
MDBTabVM.Update();
}
bool loaded = false;
void MachineView_SizeChanged(object sender, SizeChangedEventArgs e)
{
if (loaded)
UpdateCanvasSize(e.NewSize);
}
void UpdateCanvasSize(Size size)
{
size.Height = Math.Min(1000000, size.Height);
double w = Math.Max(0, size.Width - SystemParameters.VerticalScrollBarWidth);
double h = Math.Max(0, size.Height - SystemParameters.HorizontalScrollBarHeight);
machineCanvas.Width = Math.Max(0, w * machineCanvas.CanvasSize);
machineCanvas.Height = Math.Max(0, h * machineCanvas.CanvasSize);
double s = Math.Pow(2.0, Zoomer.Level / (double)Zoomer.LevelCount);
sv.ScrollToHorizontalOffset(machineCanvas.Width / 2 * s - w / 2);
sv.ScrollToVerticalOffset(machineCanvas.Height / 2 * s - h / 2);
containerCanvas.Width = machineCanvas.Width;
containerCanvas.Height = machineCanvas.Height;
}
void sv_ScrollChanged(object sender, ScrollChangedEventArgs e)
{
int ix = (int)sv.HorizontalOffset;
if (ix != sv.HorizontalOffset)
sv.ScrollToHorizontalOffset(ix);
else
sv.ScrollToHorizontalOffset(ix);
int iy = (int)sv.VerticalOffset;
if (iy != sv.VerticalOffset)
sv.ScrollToVerticalOffset(iy);
else
sv.ScrollToVerticalOffset(iy);
}
public void ClearSelection()
{
foreach (var m in Machines)
m.IsSelected = false;
PropertyChanged.Raise(this, "SelectedMachines");
}
public void SetSelection(MachineControl s, bool add)
{
foreach (var m in Machines)
m.IsSelected = m == s ? true : (add ? m.IsSelected : false);
PropertyChanged.Raise(this, "SelectedMachines");
}
public void SetSelection(IEnumerable s, bool add)
{
foreach (var m in Machines)
m.IsSelected = s.Contains(m.Machine) ? true : (add ? m.IsSelected : false);
PropertyChanged.Raise(this, "SelectedMachines");
}
public void BeginMoveSelectedMachines()
{
foreach (var m in Machines)
m.BeginDragPosition = MachineCanvas.GetPosition(m);
}
public void MoveSelectedMachines(Point delta)
{
foreach (var m in SelectedMachines)
machineCanvas.Drag(m, delta);
}
public void MoveSelectedMachines(IEnumerable deltas)
{
foreach (var x in SelectedMachines.Zip(deltas, (m, d) => new { m, d }))
machineCanvas.Drag(x.m, x.d);
}
public void EndMoveSelectedMachines()
{
List>> mm = new List>>();
foreach (var m in SelectedMachines)
{
Point p = MachineCanvas.GetPosition(m);
mm.Add(new Tuple>(m.Machine, new Tuple((float)p.X, (float)p.Y)));
}
machineGraph.MoveMachines(mm);
}
public void BringToTop(IEnumerable m)
{
foreach (var x in Machines.Where(x => m.Contains(x.Machine)))
x.BringToTop();
}
#region New Machine Menu
List BuildMachineIndexMenuItems(IMenuItem mie)
{
List l = new List();
foreach (var e in mie.Children)
{
var vm = new MenuItemVM() { Text = e.Text, Command = NewMachineCommand, CommandParameter = e.ID, IsEnabled = e.IsEnabled, IsSeparator = e.IsSeparator, IsLabel = e.IsLabel };
if (mie.Children.Count() > 0) vm.Children = BuildMachineIndexMenuItems(e);
l.Add(vm);
}
return l;
}
IList machineIndex;
public IList MachineIndex
{
get
{
if (machineIndex == null)
machineIndex = BuildMachineIndexMenuItems(machineGraph.Buzz.MachineIndex);
return machineIndex;
}
}
#endregion
#region Replace Machine Menu
List BuildReplaceMachineIndexMenuItems(IMenuItem mie)
{
List l = new List();
foreach (var e in mie.Children)
{
var vm = new MenuItemVM() { Text = e.Text, Command = ReplaceMachineCommand, CommandParameter = e.ID, IsEnabled = e.IsEnabled, IsSeparator = e.IsSeparator, IsLabel = e.IsLabel };
if (mie.Children.Count() > 0) vm.Children = BuildReplaceMachineIndexMenuItems(e);
l.Add(vm);
}
return l;
}
List replaceMachineIndex;
public List ReplaceMachineIndex
{
get
{
if (replaceMachineIndex == null)
replaceMachineIndex = BuildReplaceMachineIndexMenuItems(machineGraph.Buzz.MachineIndex);
return replaceMachineIndex;
}
}
#endregion
#region InsertMachineMenu
List BuildInsertMachineIndexMenuItems(IMenuItem mie)
{
List l = new List();
foreach (var e in mie.Children)
{
var vm = new MenuItemVM() { Text = e.Text, Command = InsertMachineCommand, CommandParameter = e.ID, IsEnabled = e.IsEnabled, IsSeparator = e.IsSeparator, IsLabel = e.IsLabel };
if (mie.Children.Count() > 0) vm.Children = BuildInsertMachineIndexMenuItems(e);
l.Add(vm);
}
return l;
}
List insertMachineIndex;
public List InsertMachineIndex
{
get
{
if (insertMachineIndex == null)
insertMachineIndex = BuildInsertMachineIndexMenuItems(machineGraph.Buzz.MachineIndex);
return insertMachineIndex;
}
}
ContextMenu insertMenu;
IMachineConnection insertMachineConnection;
public void InsertMachinePopup(IMachineConnection mc)
{
if (insertMenu == null)
{
insertMenu = new ContextMenu()
{
Resources = this.Resources.MergedDictionaries[0],
ItemContainerStyle = TryFindResource("ContextMenuItemStyle") as Style
};
TextOptions.SetTextFormattingMode(insertMenu, Global.GeneralSettings.WPFIdealFontMetrics ? TextFormattingMode.Ideal : TextFormattingMode.Display);
insertMenu.ItemsSource = InsertMachineIndex;
}
insertMachineConnection = mc;
insertMenu.IsOpen = true;
}
#endregion
public void LPToDP(ref float x, ref float y)
{
Point p = machineCanvas.TranslatePoint(machineCanvas.GetPointAtPosition(new Point(x, y)), this);
x = (float)p.X;
y = (float)p.Y;
}
public void DPToLP(ref float x, ref float y)
{
Point p = machineCanvas.GetPositionAtPoint(this.TranslatePoint(new Point(x, y), machineCanvas));
x = (float)p.X;
y = (float)p.Y;
}
void UpdateDragEffect(DragEventArgs e)
{
if (e.Data.GetDataPresent(typeof(MachineListItemVM)) || e.Data.GetDataPresent(typeof(MDBTab.MachineListItemVM)) || e.Data.GetDataPresent(typeof(TemplateListItemVM))) {
e.Effects = DragDropEffects.Copy;
}
else if (e.Data.GetDataPresent(DataFormats.FileDrop))
{
var filenames = (string[])e.Data.GetData(DataFormats.FileDrop);
// allow drop of single .xml files only
if (filenames.Length == 1 && System.IO.Path.GetExtension(filenames[0]).ToLower() == ".xml")
e.Effects = DragDropEffects.Copy;
else
e.Effects = DragDropEffects.None;
}
else
{
e.Effects = DragDropEffects.None;
}
e.Handled = true;
}
internal void DeleteMachines(IEnumerable machines)
{
if (machines.Count() == 1)
{
var m = machines.First();
if (m.DLL.Info.Type == MachineType.Effect && !m.IsControlMachine && m.Inputs.Count >= 1 || m.Outputs.Count >= 1)
{
using (new ActionGroup(machineGraph))
{
var oldinputs = m.Inputs.Select(x => new { Source = x.Source, Channel = x.SourceChannel, Amp = (double)x.Amp / 0x4000, Pan = x.Pan }).ToArray();
var oldoutputs = m.Outputs.Select(x => new { Destination = x.Destination, Channel = x.DestinationChannel, Amp = (double)x.Amp / 0x4000, Pan = x.Pan }).ToArray();
machineGraph.DeleteMachines(machines);
foreach (var oi in oldinputs)
{
foreach (var oo in oldoutputs)
{
if (machineGraph.CanConnectMachines(oi.Source, oo.Destination))
{
var amp = Math.Min(Math.Max((int)((oi.Amp * oo.Amp) * 0x4000), 0), 0xfffe);
var pan = Math.Min(Math.Max(oi.Pan + oo.Pan - 0x4000, 0), 0x8000);
machineGraph.ConnectMachines(oi.Source, oo.Destination, oi.Channel, oo.Channel, amp, pan);
}
}
}
}
}
else
{
machineGraph.DeleteMachines(machines);
}
}
else
{
machineGraph.DeleteMachines(machines);
}
}
internal void DisconnectMachine(IMachine m)
{
if (m.Inputs.Count == 0 && m.Outputs.Count == 0) return;
using (new ActionGroup(machineGraph))
{
var oldinputs = m.Inputs.Select(x => new { Source = x.Source, Channel = x.SourceChannel, Amp = (double)x.Amp / 0x4000, Pan = x.Pan }).ToArray();
var oldoutputs = m.Outputs.Select(x => new { Destination = x.Destination, Channel = x.DestinationChannel, Amp = (double)x.Amp / 0x4000, Pan = x.Pan }).ToArray();
var connections = m.Outputs.Concat(m.Inputs).ToArray();
foreach (var mc in connections)
m.Graph.DisconnectMachines(mc);
foreach (var oi in oldinputs)
{
foreach (var oo in oldoutputs)
{
var amp = Math.Min(Math.Max((int)((oi.Amp * oo.Amp) * 0x4000), 0), 0xfffe);
var pan = Math.Min(Math.Max(oi.Pan + oo.Pan - 0x4000, 0), 0x8000);
machineGraph.ConnectMachines(oi.Source, oo.Destination, oi.Channel, oo.Channel, amp, pan);
}
}
}
}
void CopySelectedMachines()
{
try
{
Mouse.OverrideCursor = Cursors.Wait;
var t = new BuzzGUI.Common.Templates.Template(SelectedMachines.Select(m => m.Machine), BuzzGUI.Common.Templates.TemplatePatternMode.PatternsAndSequences, BuzzGUI.Common.Templates.TemplateWavetableMode.NoWavetable);
var ms = new MemoryStream();
t.Save(ms);
ms.Position = 0;
var sr = new StreamReader(ms);
ClipboardEx.SetText(sr.ReadToEnd());
}
catch (Exception e)
{
System.Windows.MessageBox.Show(string.Format("Copy failed ({0})", e.Message));
}
finally
{
Mouse.OverrideCursor = null;
}
}
void PasteMachines(Point pos)
{
try
{
Mouse.OverrideCursor = Cursors.Wait;
var s = ClipboardEx.GetText();
if (BuzzGUI.Common.Templates.Template.IsValidTemplateString(s))
{
var t = BuzzGUI.Common.Templates.Template.LoadFromString(s);
var newmachines = t.Paste(machineGraph, pos);
SetSelection(newmachines, false);
BringToTop(newmachines);
}
else if (BuzzGUI.Common.Presets.Preset.IsValidPresetString(s))
{
var p = BuzzGUI.Common.Presets.Preset.FromString(s);
var instr = Buzz.Instruments.First(i => i.MachineDLL.Name == p.Machine && string.IsNullOrEmpty(i.Name));
var m = CreateInstrument(instr, (float)pos.X, (float)pos.Y);
p.Apply(m, true);
SetSelection(Enumerable.Repeat(m, 1), false);
BringToTop(Enumerable.Repeat(m, 1));
}
}
catch (Exception e)
{
System.Windows.MessageBox.Show(string.Format("Paste failed ({0})", e.Message));
}
finally
{
Mouse.OverrideCursor = null;
}
}
internal void CloneSelectedMachines(bool includepatandseq)
{
try
{
Mouse.OverrideCursor = Cursors.Wait;
var t = new BuzzGUI.Common.Templates.Template(SelectedMachines.Select(m => m.Machine),
includepatandseq ? BuzzGUI.Common.Templates.TemplatePatternMode.PatternsAndSequences : BuzzGUI.Common.Templates.TemplatePatternMode.NoPatterns,
BuzzGUI.Common.Templates.TemplateWavetableMode.NoWavetable);
var newmachines = t.Paste(machineGraph, new Point(double.NaN, double.NaN));
SetSelection(newmachines, false);
BringToTop(newmachines);
}
catch (Exception e)
{
System.Windows.MessageBox.Show(string.Format("Clone failed ({0})", e.Message));
}
finally
{
Mouse.OverrideCursor = null;
}
}
// NOTE: this is used to create both instruments and machines
IMachine CreateInstrument(IInstrument instrument, float x, float y)
{
using (new ActionGroup(machineGraph))
{
bool songwasempty = machineGraph.Machines.Count == 1;
machineGraph.CreateMachine(instrument.MachineDLL.Name, instrument.Name, null, null, null, null, -1, x, y);
var machine = machineGraph.Machines.Last();
if (machine.AllNonInputParameters().Any())
machine.CreatePattern("00", 16);
if (machine.DLL.Info.Type == MachineType.Generator)
{
// automatically connect generators to master if there are no effects
if (!machine.IsControlMachine && !machineGraph.Machines.Any(m => m.DLL.Info.Type == MachineType.Effect))
{
machineGraph.ConnectMachines(machine, machineGraph.Machines.First(m => m.Name == "Master"), 0, 0, 0x4000, 0x4000);
}
Buzz.Song.AddSequence(machine, Buzz.Song.Sequences.Count);
if (songwasempty)
{
Buzz.Song.Sequences.First(s => s.Machine == machine).SetEvent(0, new SequenceEvent(SequenceEventType.PlayPattern, machine.Patterns[0]));
}
}
return machine;
}
}
TemplateList templateList;
public TemplateList TemplateList
{
get
{
if (templateList == null)
templateList = new TemplateList(this);
return templateList;
}
}
internal void CreateTemplate()
{
var sm = SelectedMachines.Select(m => m.Machine);
CreateTemplateWindow w = new CreateTemplateWindow(sm, TemplateList.Items != null ? TemplateList.Items.Select(t => t.DisplayName) : new string[] { })
{
Resources = this.Resources.MergedDictionaries[0],
WindowStartupLocation = WindowStartupLocation.CenterOwner,
Style = TryFindResource("ThemeWindowStyle") as Style
};
new WindowInteropHelper(w).Owner = ((HwndSource)PresentationSource.FromVisual(this)).Handle;
if ((bool)w.ShowDialog())
{
var t = new BuzzGUI.Common.Templates.Template(sm, CreateTemplateWindow.PatternMode, CreateTemplateWindow.WavetableMode);
TemplateList.SaveTemplate(w.TemplateName, t, CreateTemplateWindow.WavetableMode == Common.Templates.TemplateWavetableMode.WaveFiles ? MachineGraph.Buzz.Song.Wavetable : null);
}
}
internal void PasteTemplate(string filename, Point pos, IMachine machineToReplace = null)
{
try
{
Mouse.OverrideCursor = Cursors.Wait;
if (machineToReplace != null)
{
if (MachineControl.CachedTemplate.Path != filename)
throw new Exception("wrong cached template");
using (new ActionGroup(machineGraph))
{
var t = MachineControl.CachedTemplate;
var connected = machineToReplace.Outputs.Select(mc => mc.Destination)
.Traverse(m => m.Outputs.Select(mc => mc.Destination));
DeleteMachines(connected);
DisconnectMachine(machineToReplace);
var newmachines = t.Paste(machineGraph, pos, machineToReplace).Concat(Enumerable.Repeat(machineToReplace, 1));
SetSelection(newmachines, false);
BringToTop(newmachines);
}
}
else
{
var t = BuzzGUI.Common.Templates.Template.Load(filename);
var newmachines = t.Paste(machineGraph, pos);
SetSelection(newmachines, false);
BringToTop(newmachines);
}
}
catch (Exception e)
{
System.Windows.MessageBox.Show(string.Format("PasteTemplate failed ({0})", e.Message));
}
finally
{
Mouse.OverrideCursor = null;
}
}
public void TemplateListPreviewKeyDown(object sender, KeyEventArgs e)
{
var tli = (sender as ListBoxItem).DataContext as TemplateListItemVM;
if (e.Key == Key.Delete && (Keyboard.Modifiers == ModifierKeys.None || Keyboard.Modifiers == ModifierKeys.Shift))
{
tli.Delete(Keyboard.Modifiers == ModifierKeys.Shift);
e.Handled = true;
}
else if (Keyboard.Modifiers == ModifierKeys.None)
{
if ((e.Key == Key.Return || e.Key == Key.Right) && tli.Type == TemplateListItemVM.Types.Directory)
{
templateList.SetDirectory(tli.Path);
templateListBox.SelectedIndex = 0;
e.Handled = true;
}
if (e.Key == Key.Back || e.Key == Key.Left)
{
templateList.SetDirectory("..");
templateListBox.SelectedIndex = 0;
e.Handled = true;
}
}
}
public void TemplateListMouseDoubleClick(object sender, MouseEventArgs e)
{
var tli = (sender as ListBoxItem).DataContext as TemplateListItemVM;
if (tli.Type == TemplateListItemVM.Types.Directory)
{
templateList.SetDirectory(tli.Path);
templateListBox.SelectedIndex = 0;
}
/*
if (e.Key == Key.Delete && (Keyboard.Modifiers == ModifierKeys.None || Keyboard.Modifiers == ModifierKeys.Shift))
{
tli.Delete(Keyboard.Modifiers == ModifierKeys.Shift);
e.Handled = true;
}
*/
}
internal Point CommandPoint
{
get
{
if (contextMenuPoint.X >= 0)
return contextMenuPoint;
else
return Win32Mouse.GetPosition(machineCanvas);
}
}
internal Point CommandCanvasPosition
{
get
{
if (contextMenuPoint.X >= 0)
return machineCanvas.GetPositionAtPoint(contextMenuPoint);
else
return machineCanvas.GetPositionAtPoint(Win32Mouse.GetPosition(machineCanvas));
}
}
internal void UpdateSolo()
{
PropertyChanged.Raise(this, "IsSoloActive");
}
#region CPUMonitor
static CPUMonitor.CPUMonitorWindow cpuMonitorWindow;
public bool IsCPUMonitorVisible
{
get { return cpuMonitorWindow != null && cpuMonitorWindow.IsVisible; }
set
{
if (value)
{
if (cpuMonitorWindow == null)
{
cpuMonitorWindow = new CPUMonitor.CPUMonitorWindow()
{
Resources = this.Resources.MergedDictionaries[0],
WindowStartupLocation = WindowStartupLocation.CenterOwner
};
new WindowInteropHelper(cpuMonitorWindow).Owner = ((HwndSource)PresentationSource.FromVisual(this)).Handle;
cpuMonitorWindow.Closed += cpuMonitorWindow_Closed;
cpuMonitorWindow.MachineGraph = machineGraph;
cpuMonitorWindow.Show();
}
}
else
{
if (cpuMonitorWindow != null)
{
cpuMonitorWindow.MachineGraph = null;
cpuMonitorWindow.Close();
}
}
}
}
void cpuMonitorWindow_Closed(object sender, EventArgs e)
{
cpuMonitorWindow.Closed -= cpuMonitorWindow_Closed;
cpuMonitorWindow = null;
Buzz.IsCPUMonitorWindowVisible = false;
}
#endregion
#region HDRecorder
static HDRecorder.HDRecorderWindow hdRecorderWindow;
public bool IsHardDiskRecorderVisible
{
get { return hdRecorderWindow != null && hdRecorderWindow.IsVisible; }
set
{
if (value)
{
if (hdRecorderWindow == null)
{
hdRecorderWindow = new HDRecorder.HDRecorderWindow()
{
Resources = this.Resources.MergedDictionaries[0],
WindowStartupLocation = WindowStartupLocation.CenterOwner
};
new WindowInteropHelper(hdRecorderWindow).Owner = ((HwndSource)PresentationSource.FromVisual(this)).Handle;
hdRecorderWindow.Closed += hdRecorderWindow_Closed;
hdRecorderWindow.MachineGraph = machineGraph;
hdRecorderWindow.Show();
}
}
else
{
if (hdRecorderWindow != null)
{
hdRecorderWindow.MachineGraph = null;
hdRecorderWindow.Close();
}
}
}
}
void hdRecorderWindow_Closed(object sender, EventArgs e)
{
hdRecorderWindow.Closed -= hdRecorderWindow_Closed;
hdRecorderWindow = null;
Buzz.IsHardDiskRecorderWindowVisible = false;
}
#endregion
void Hyperlink_Click(object sender, RoutedEventArgs e)
{
System.Diagnostics.Process.Start((sender as Hyperlink).NavigateUri.ToString());
}
Connection MouseOverConnection
{
get
{
var uie = Mouse.DirectlyOver as UIElement;
if (uie == null) return null;
Control ctrl = uie.GetAncestor();
if (ctrl == null) return null;
return Connections.FirstOrDefault(c => c.ConnectionControl == ctrl);
}
}
public TextFormattingMode TextFormattingMode { get { return Global.GeneralSettings.WPFIdealFontMetrics ? TextFormattingMode.Ideal : TextFormattingMode.Display; } }
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
#endregion
}
}