<Window x:Class="WpfApplication1.Window1" Name="winBoltCircle" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:WpfApplication1" Title="Bolt Hole Pattern" Height="800" Width="800"> <Window.Resources> <local:FormattingConverter x:Key="formatter" /> </Window.Resources> <Grid Margin="5,5,5,5"> <Grid.RowDefinitions> <RowDefinition Height="50"/> <RowDefinition Height="100"/> <RowDefinition /> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="250" /> <ColumnDefinition /> <ColumnDefinition /> </Grid.ColumnDefinitions> <ListView x:Name="CoordinateGrid" Grid.Row="2" Grid.Column="0" MouseDoubleClick="CoordinateGrid_MouseDoubleClick"> <ListView.ItemContainerStyle> <Style TargetType="ListViewItem"> <Setter Property="HorizontalContentAlignment" Value="Stretch" /> </Style> </ListView.ItemContainerStyle> <ListView.View> <GridView > <GridViewColumn Header="Number" DisplayMemberBinding="{Binding Path=HoleNumber}" /> <GridViewColumn Header="X Coord" Width="65"> <GridViewColumn.CellTemplate> <DataTemplate> <TextBlock Text="{Binding AbsX, Converter={StaticResource formatter}, ConverterParameter='\{0:f4\}'}" HorizontalAlignment="Right" /> </DataTemplate> </GridViewColumn.CellTemplate> </GridViewColumn> <GridViewColumn Header="Y Coord" Width="65" > <GridViewColumn.CellTemplate> <DataTemplate> <TextBlock Text="{Binding AbsY, Converter={StaticResource formatter}, ConverterParameter='\{0:f4\}'}" HorizontalAlignment="Right" /> </DataTemplate> </GridViewColumn.CellTemplate> </GridViewColumn> <GridViewColumn Header="Angle" Width="65"> <GridViewColumn.CellTemplate> <DataTemplate> <TextBlock Text="{Binding Angle, Converter={StaticResource formatter}, ConverterParameter='\{0:f2\}'}" HorizontalAlignment="Right" /> </DataTemplate> </GridViewColumn.CellTemplate> </GridViewColumn> </GridView> </ListView.View> </ListView> <StackPanel Grid.Row="2" Grid.Column="1" Grid.ColumnSpan="2" > <TextBlock Margin="10,0,0,0" Text="Double-Click a row in the grid to toggle hole visibility." /> <Canvas Margin="10,10,10,10" Name="canvas1" Background="CadetBlue" Width="500" Height="500" /> </StackPanel> <StackPanel Grid.Row="1" Grid.Column="0"> <StackPanel Orientation="Horizontal" > <TextBlock Text="Bolt Cir Dia. " Width="75" /> <TextBox Name="txtBoltCirDia" Text="{Binding Path=BoltCirDia, ElementName=winBoltCircle}" PreviewGotKeyboardFocus="TextBox_PreviewGotKeyboardFocus" Height="25" Width="100" /> </StackPanel> <StackPanel Orientation="Horizontal" > <TextBlock Text="No. of Holes: " Width="75" /> <TextBox Name="txtHoleCount" Text="{Binding Path=HoleCount, ElementName=winBoltCircle}" PreviewGotKeyboardFocus="TextBox_PreviewGotKeyboardFocus" Height="25" Width="100" /> <Button Name="btnHoleCountDecrease" Click="btnHoleCountDecrease_Click" Margin="5,0,0,0" Width="25">-</Button> <Button Name="btnHoleCountIncrease" Click="btnHoleCountIncrease_Click" Margin="5,0,0,0" Width="25">+</Button> </StackPanel> <StackPanel Orientation="Horizontal"> <TextBlock Text="Start Angle: " Width="75"/> <TextBox Name="txtStartAngle" Text="{Binding Path=StartAngle, ElementName=winBoltCircle}" PreviewGotKeyboardFocus="TextBox_PreviewGotKeyboardFocus" Height="25" Width="100" /> <Button Name="btnStartAngleDecrease" Click="btnStartAngleDecrease_Click" Margin="5,0,0,0" Width="25">-</Button> <Button Name="btnStartAngleIncrease" Click="btnStartAngleIncrease_Click" Margin="5,0,0,0" Width="25">+</Button> </StackPanel> </StackPanel> <StackPanel Grid.Column="2" Grid.Row="1" > <Button Name="btnDraw" Height="36" VerticalAlignment="Top" Click="btnDraw_Click">ReDraw</Button> <StackPanel Orientation="Horizontal" Grid.Column="2" Grid.Row="1" Margin="0,10,0,0"> <TextBlock Text="Hole Size" VerticalAlignment="Center" Margin="0,0,10,0"/> <Button Name="btnHoleSizeDecrease" Click="btnHoleSizeDecrease_Click" Margin="5,0,0,0" Width="25">-</Button> <Button Name="btnHoleSizeIncrease" Click="btnHoleSizeIncrease_Click" Margin="5,0,0,0" Width="25">+</Button> </StackPanel> </StackPanel> </Grid> </Window>Code behind:
using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; using System.Text; 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.Navigation; using System.Windows.Shapes; using System.ComponentModel; namespace WpfApplication1 { /// <summary> /// Interaction logic for Window1.xaml /// </summary> public partial class Window1 : Window, INotifyPropertyChanged { private int _HoleCount; private double _BoltCirDia; private double _StartAngle; private double _AngularSpacing; private ObservableCollection<Hole> HoleList {get; set;} // Canvas sketch related fields public double SketchBoltCirRad; public double SketchX0 {get; set; } public double SketchY0 { get; set; } public event PropertyChangedEventHandler PropertyChanged; private void NotifyPropertyChanged(String info) { if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(info)); } } public double BoltCirDia { get { return _BoltCirDia; } set { _BoltCirDia = value; NotifyPropertyChanged("BoltCirDia"); RepaintScreen(); } } public double StartAngle { get { return _StartAngle; } set { _StartAngle = value; NotifyPropertyChanged("StartAngle"); RepaintScreen(); } } public double AngularSpacing { get { return _AngularSpacing; } set { _AngularSpacing = value; } } public int HoleCount { get { return _HoleCount; } set { if (value >= 0) { _HoleCount = value; } else { _HoleCount = 0; } if (value > 0) { _AngularSpacing = 360.0 / _HoleCount; } else { _AngularSpacing = 0; } NotifyPropertyChanged("HoleCount"); RedrawScreen(); } } //-- Constructor -------------------------------------------- public Window1() { InitializeComponent(); HoleList = new ObservableCollection<Hole>(); SketchX0 = canvas1.Width / 2; SketchY0 = canvas1.Height / 2; SketchBoltCirRad = canvas1.Width / 2 * .7; CoordinateGrid.ItemsSource = HoleList; // Point the ListView to the HoleList collection //-- Set some default values for the UI BoltCirDia = 12.0; HoleCount = 6; StartAngle = 0; } public void CreateHoleList() { HoleList.Clear(); if (HoleCount>0) { int x; double CurrentAngle = StartAngle; for (x = 1; x <= HoleCount; x++) { Hole NewHole = new Hole(); NewHole.HoleNumber = x; NewHole.HoleEntity.Stroke = Brushes.Black; //-- Set BCR and Angle, and let the Hole calculate the absolute coords of each hole NewHole.BoltCirRad = this.BoltCirDia/2.0; NewHole.Angle = CurrentAngle; //--Setup HoleLabel (position happens in UpdateHoles()--------- NewHole.HoleLabel.Text=x.ToString(); NewHole.HoleLabel.TextAlignment = TextAlignment.Center; NewHole.HoleLabel.Foreground = Brushes.White; NewHole.HoleLabel.FontSize = 12; HoleList.Add(NewHole); CurrentAngle = StartAngle+x*AngularSpacing; // Increment the angle for the next Hole } } } public void DrawGridLines() { int LineSpacing = 20; double LineWidth = 0.5; Brush LineColor = Brushes.Gray; //-- Horizontal Grid Lines (work from Center to Left, then Center to Right) for (double x = 0; x <= canvas1.Width / 2; x += LineSpacing) { for (int y = -1; y <= 1; y += 2) { Line VerticalGraphLine = new Line(); VerticalGraphLine.X1 = SketchX0 + x * y; VerticalGraphLine.Y1 = 0; VerticalGraphLine.X2 = VerticalGraphLine.X1; VerticalGraphLine.Y2 = canvas1.Height; VerticalGraphLine.Stroke = LineColor; VerticalGraphLine.StrokeThickness = LineWidth; canvas1.Children.Add(VerticalGraphLine); } } //-- Vertical Grid Lines (work from Center Up, then Center down) for (double x = 0; x <= canvas1.Height / 2; x += LineSpacing) { for (int y = -1; y <= 1; y += 2) { Line HorizontalGraphLine = new Line(); HorizontalGraphLine.X1 = 0; HorizontalGraphLine.Y1 = SketchY0 + x * y; HorizontalGraphLine.X2 = canvas1.Height; HorizontalGraphLine.Y2 = HorizontalGraphLine.Y1; HorizontalGraphLine.Stroke = LineColor; HorizontalGraphLine.StrokeThickness = LineWidth; canvas1.Children.Add(HorizontalGraphLine); } } } public void DrawBoltCir() { Ellipse BoltCirEntity = new Ellipse(); BoltCirEntity.Width = SketchBoltCirRad * 2; BoltCirEntity.Height = SketchBoltCirRad * 2; BoltCirEntity.Stroke = Brushes.Black; BoltCirEntity.Margin = new Thickness(SketchX0 - SketchBoltCirRad, SketchY0 - SketchBoltCirRad, 0, 0); Line HorizontalCL = new Line(); HorizontalCL.X1 = 10; HorizontalCL.Y1 = SketchY0; HorizontalCL.X2 = canvas1.Width-10; HorizontalCL.Y2 = SketchY0; HorizontalCL.Stroke = Brushes.Black; HorizontalCL.StrokeThickness = 1; Line VerticalCL = new Line(); VerticalCL.X1 = SketchX0; VerticalCL.Y1 = 10; VerticalCL.X2 = SketchX0; VerticalCL.Y2 = canvas1.Height-10; VerticalCL.Stroke = Brushes.Black; VerticalCL.StrokeThickness = 1; //-- Add objects to Canvas canvas1.Children.Add(BoltCirEntity); canvas1.Children.Add(HorizontalCL); canvas1.Children.Add(VerticalCL); } public void DrawHoles() { // This methods adds the HoleEntity and HoleLabel to the canvas // The method UpdateHoles() must be used to set the sketch positions for these objects // Canvas clearing should be handled outside this method as needed. foreach (Hole Hole in HoleList) { canvas1.Children.Add(Hole.HoleEntity); canvas1.Children.Add(Hole.HoleLabel); } } private void UpdateHoles() { foreach (Hole HoleEnt in HoleList) { //-- Update absolute coord points on the Hole by setting its properties ----- //-- The Hole object will calculate the absolute X and Y in its poperty setters HoleEnt.BoltCirRad = this.BoltCirDia/2; HoleEnt.Angle=(HoleEnt.HoleNumber-1)*AngularSpacing+StartAngle; //--Update the Hole sketch data for the Canvas layout ---- HoleEnt.HoleEntity.Width = HoleEnt.HoleDia; HoleEnt.HoleEntity.Height = HoleEnt.HoleDia; HoleEnt.CanvasX = SketchX0 + SketchBoltCirRad * Math.Cos(dtr(HoleEnt.Angle)) - HoleEnt.HoleDia / 2; HoleEnt.CanvasY = SketchY0 - SketchBoltCirRad * Math.Sin(dtr(HoleEnt.Angle)) - HoleEnt.HoleDia / 2; HoleEnt.HoleEntity.Margin = new Thickness(HoleEnt.CanvasX, HoleEnt.CanvasY, 0, 0); //---Update the HoleLabel sketch coords for the Canvas ----- double TextCLR = (SketchBoltCirRad - HoleEnt.HoleDia / 2 - HoleEnt.HoleLabel.FontSize); double HoleLabelX = (SketchX0+TextCLR * Math.Cos(dtr(HoleEnt.Angle))-HoleEnt.HoleLabel.FontSize/2); double HoleLabelY = (SketchY0-TextCLR * Math.Sin(dtr(HoleEnt.Angle))-HoleEnt.HoleLabel.FontSize*.6); HoleEnt.HoleLabel.Margin = new Thickness(HoleLabelX, HoleLabelY,0,0); } } public class Hole:INotifyPropertyChanged { public Ellipse HoleEntity = new Ellipse(); public TextBlock HoleLabel = new TextBlock(); public static double _HoleDia = 20; public int HoleNumber { get; set; } public double CanvasX { get; set; } public double CanvasY { get; set; } public double HoleLabelX { get; set; } public double HoleLabelY { get; set; } public string AbsXDisplay{ get; set; } public string AbsYDisplay { get; set; } private bool _Visible; private double _AbsX; private double _AbsY; private double _Angle; private double _BoltCirRad; public event PropertyChangedEventHandler PropertyChanged; public Hole() { HoleEntity.Width = _HoleDia; HoleEntity.Height = _HoleDia; Visible = true; } private void NotifyPropertyChanged(String info) { if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(info)); } } public bool Visible { get { return _Visible; } set { _Visible = value; HoleEntity.Visibility = value ? Visibility.Visible : Visibility.Hidden; NotifyPropertyChanged("Visible"); } } public double AbsX { get { return _AbsX; } set { _AbsX = value; AbsXDisplay = String.Format("{0:f4}", value); NotifyPropertyChanged("AbsX"); } } public double AbsY { get { return _AbsY; } set { _AbsY = value; AbsYDisplay = String.Format("{0:f4}", value); NotifyPropertyChanged("AbsY"); } } public double HoleDia { get { return _HoleDia;} set { _HoleDia = value; NotifyPropertyChanged("HoleDia"); } } public double BoltCirRad { get{return _BoltCirRad;} set { _BoltCirRad = value; AbsX = (this.BoltCirRad * Math.Cos(dtr(this.Angle))); AbsY = (this.BoltCirRad * Math.Sin(dtr(this.Angle))); } } public double Angle { get{return _Angle;} set { _Angle = value; AbsX = (this.BoltCirRad * Math.Cos(dtr(this.Angle))); AbsY = (this.BoltCirRad * Math.Sin(dtr(this.Angle))); NotifyPropertyChanged("Angle"); } } } public static double dtr(double degrees) { double radians = (Math.PI / 180) * degrees; return (radians); } private void ChangeHoleCount(int ChangeAmount) { if(HoleCount+ChangeAmount>=0) { HoleCount+=ChangeAmount; } } private void ChangeStartAngle(int ChangeAmount) { StartAngle+=ChangeAmount; } private void ChangeHoleSketchSize(int ChangeAmount) { if (Hole._HoleDia + ChangeAmount > 0) { Hole._HoleDia += ChangeAmount; } UpdateHoles(); //RepaintScreen(); } private void ToggleHoleVisiblity(Hole SelectedHole) { SelectedHole.Visible = (SelectedHole.Visible) ? false : true; RepaintScreen(); } private void RedrawScreen() { canvas1.Children.Clear(); CreateHoleList(); // Recreate the Hole list collection, which re-calcs the absolute coordinates and angle of each hole DrawGridLines(); DrawBoltCir(); DrawHoles(); UpdateHoles(); // Recalculate the abs and canvas coords on the HoleList. Will update grid and update on the canvas } private void RepaintScreen() { UpdateHoles(); // Recalculate the abs and canvas coords on the HoleList so we can draw the holes on the canvas } private void TextBox_PreviewGotKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e) { ((TextBox)sender).SelectAll(); } private void btnDraw_Click(object sender, RoutedEventArgs e) { RedrawScreen(); } private void btnHoleCountIncrease_Click(object sender, RoutedEventArgs e) { ChangeHoleCount(1); } private void btnHoleCountDecrease_Click(object sender, RoutedEventArgs e) { ChangeHoleCount(-1); } private void btnStartAngleIncrease_Click(object sender, RoutedEventArgs e) { ChangeStartAngle(1); } private void btnStartAngleDecrease_Click(object sender, RoutedEventArgs e) { ChangeStartAngle(-1); } private void btnStartAngleIncrease_MouseDown(object sender, MouseButtonEventArgs e) { ChangeStartAngle(1); } private void btnStartAngleDecrease_MouseDown(object sender, MouseButtonEventArgs e) { ChangeStartAngle(-1); } private void btnHoleSizeDecrease_Click(object sender, RoutedEventArgs e) { ChangeHoleSketchSize(-1); } private void btnHoleSizeIncrease_Click(object sender, RoutedEventArgs e) { ChangeHoleSketchSize(1); } private void CoordinateGrid_MouseDoubleClick(object sender, MouseButtonEventArgs e) { var lvRef=(ListView)sender; Hole SelectedHole = (Hole)lvRef.SelectedItem; ToggleHoleVisiblity(SelectedHole); } } [ValueConversion(typeof(object), typeof(string))] public class FormattingConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { string formatString = parameter as string; if (formatString != null) { return string.Format(culture, formatString, value); } else { return value.ToString(); } } public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { // we don't intend this to ever be called return null; } } }>>MMORPG? (help me out here (sorry, I'm not a gamer, and I guess it is related to that))