diff --git a/App/RobobinApp/App.xaml.cs b/App/RobobinApp/App.xaml.cs index 5f31488a69d1bc868a8fcb9dee500c3ae7f9081c..848550bd7fd7b1e29ba1c9c3632fc7c8b1806032 100644 --- a/App/RobobinApp/App.xaml.cs +++ b/App/RobobinApp/App.xaml.cs @@ -19,7 +19,16 @@ public partial class App : Application MainPage = new AppShell(); } + protected override Window CreateWindow(IActivationState activationState) + { + var window = base.CreateWindow(activationState); + + window.MinimumWidth = 800; + window.MinimumHeight = 650; + + return window; + } private void ConfigureLogging() { var loggerFactory = LoggerFactory.Create(builder => diff --git a/App/RobobinApp/Models/Graph.cs b/App/RobobinApp/Models/Graph.cs index 414492e4d4560eca6f49d1c9faabb1d0c1cc8833..e8fa370cb33143056d2e88d8e2bf1bfab78a2673 100644 --- a/App/RobobinApp/Models/Graph.cs +++ b/App/RobobinApp/Models/Graph.cs @@ -22,11 +22,19 @@ namespace Robobin.Models public class Graph { + public string Name { get; set; } public List<Node> Nodes { get; set; } public (float magnitude, float angle)[,] AdjacencyMatrix { get; set; } - public Graph(List<Node> nodes, (float, float)[,] adjacencyMatrix) + public Graph(string name, List<Node> nodes, (float, float)[,] adjacencyMatrix) + { + Name = name; + Nodes = nodes; + AdjacencyMatrix = adjacencyMatrix; + } + public Graph( List<Node> nodes, (float, float)[,] adjacencyMatrix) { + Name = "Graph"; Nodes = nodes; AdjacencyMatrix = adjacencyMatrix; } diff --git a/App/RobobinApp/ViewModels/MainPageViewModel.cs b/App/RobobinApp/ViewModels/MainPageViewModel.cs index 2841d931211e0abd43ef23f1c5fb50879b5fae42..5d1041cbe089b20c4dcc5ce472862a08f1e8dea2 100644 --- a/App/RobobinApp/ViewModels/MainPageViewModel.cs +++ b/App/RobobinApp/ViewModels/MainPageViewModel.cs @@ -1,3 +1,4 @@ +using System.Collections.ObjectModel; using System.ComponentModel; using System.Runtime.CompilerServices; using System.Windows.Input; @@ -14,31 +15,120 @@ namespace RobobinApp.ViewModels { private bool _isBusy; private string _statusMessage; - public Graph Graph { get; private set; } + public ICommand ConnectToRobobinCommand { get; } + private Graph _selectedGraph; + public ObservableCollection<Graph> Graphs { get; } + public ICommand SelectGraphCommand { get; } + public Graph Graph + { + get => _selectedGraph; + set + { + _selectedGraph = value; + OnPropertyChanged(); + } + } + public ObservableCollection<string> GraphNames { get; } + public MainPageViewModel() { ConnectToRobobinCommand = new Command(async () => await OnConnectToRobobin()); + SelectGraphCommand = new Command<int>(OnSelectGraph); - // Create nodes with X and Y coordinates - var nodes = new List<Node> + var graphNodes1 = new List<Node> +{ + new Node("A", 50, 50), + new Node("B", 150, 50), + new Node("C", 250, 50), + new Node("Home", 350, 50), + new Node("E", 50, 150), + new Node("F", 150, 150), + new Node("G", 250, 150), + new Node("H", 350, 150), + new Node("I", 50, 250), + new Node("J", 150, 250), + new Node("K", 250, 250), + new Node("L", 350, 250), + new Node("M", 50, 350), + new Node("N", 150, 350), + new Node("O", 350, 350) +}; + + var graphMatrix1 = CalculatePolarConnections(graphNodes1, new bool[,] { - new Node("N1", 100, 100), // Example coordinates - new Node("N2", 200, 100), - new Node("N3", 150, 200), - }; + { false, true, false, false, true, false, false, false, false, false, false, false, false, false, false }, + { true, false, true, false, false, true, false, false, false, false, false, false, false, false, false }, + { false, true, false, true, false, false, true, false, false, false, false, false, false, false, false }, + { false, false, true, false, false, false, false, true, false, false, false, false, false, false, true }, + { true, false, false, false, false, true, false, false, true, false, false, false, false, false, false }, + { false, true, false, false, true, false, true, false, false, true, false, false, false, false, false }, + { false, false, true, false, false, true, false, true, false, false, true, false, false, false, false }, + { false, false, false, true, false, false, true, false, false, false, false, true, false, false, false }, + { false, false, false, false, true, false, false, false, false, true, false, false, true, false, false }, + { false, false, false, false, false, true, false, false, true, false, true, false, false, true, false }, + { false, false, false, false, false, false, true, false, false, true, false, true, false, false, false }, + { false, false, false, false, false, false, false, true, false, false, true, false, false, false, true }, + { false, false, false, false, false, false, false, false, true, false, false, false, false, true, false }, + { false, false, false, false, false, false, false, false, false, true, false, false, true, false, true }, + { false, false, false, true, false, false, false, false, false, false, false, true, false, true, false } + }); + + var graph1 = new Graph("Lab 1", graphNodes1, graphMatrix1); + + + + + - // Create an empty adjacency matrix for three nodes - var adjacencyMatrix = new (float, float)[,] + + + + var graph2Nodes = new List<Node> + { + new Node("Home", 50, 50), + new Node("B", 250, 50), + new Node("C", 150, 150), + new Node("D", 150, 300) + }; + var graph2Matrix = CalculatePolarConnections(graph2Nodes, new bool[,] + { + { false, true, true, false }, + { true, false, true, true }, + { true, true, false, true }, + { false, true, true, false } + }); + var graph2 = new Graph("Lab 2",graph2Nodes, graph2Matrix); + + var graph3Nodes = new List<Node> + { + new Node("X", 75, 75), + new Node("Home", 300, 75), + new Node("Z", 200, 250) + }; + var graph3Matrix = CalculatePolarConnections(graph3Nodes, new bool[,] { - { (0, 0), (100, 0), (111.80f, 63.44f) }, - { (100, 180), (0, 0), (111.80f, 116.57f) }, - { (111.80f, -116.56f), (111.80f, -63.43f), (0, 0) } - }; + { false, true, true }, + { true, false, true }, + { true, true, false } + }); + var graph3 = new Graph("Lab3", graph3Nodes, graph3Matrix); - // Create graph - Graph = new Graph(nodes, adjacencyMatrix); + + + // Add graphs to collection + Graphs = new ObservableCollection<Graph> { graph1, graph2, graph3 }; + GraphNames = new ObservableCollection<string>(Graphs.Select(g => g.Name)); // Create list of names + Graph = Graphs.First(); + } + + private void OnSelectGraph(int graphIndex) + { + if (graphIndex >= 0 && graphIndex < Graphs.Count) + { + Graph = Graphs[graphIndex]; + } } public static (float magnitude, float angle)[,] CalculatePolarConnections(List<Node> nodes, bool[,] connections) { diff --git a/App/RobobinApp/Views/CentreGraph.xaml.cs b/App/RobobinApp/Views/CentreGraph.xaml.cs index 53a9a02ccba7ad2358872d6179a71d044c51509e..6c2d591e611a6d0371a3db33c8e9b8fd0adc96be 100644 --- a/App/RobobinApp/Views/CentreGraph.xaml.cs +++ b/App/RobobinApp/Views/CentreGraph.xaml.cs @@ -8,7 +8,6 @@ namespace RobobinApp.Views { private Graph _graph; - // Method to set the graph data public void SetGraph(Graph graph) { _graph = graph; @@ -18,39 +17,67 @@ namespace RobobinApp.Views { if (_graph == null) return; - // Set the background color - canvas.FillColor = Colors.LightPink; + + canvas.FillColor = Color.FromHex("#2C2F33"); canvas.FillRectangle(dirtyRect); - // Draw nodes and edges - const float nodeRadius = 10; // Radius for nodes + + float minX = _graph.Nodes.Min(node => node.X); + float minY = _graph.Nodes.Min(node => node.Y); + float maxX = _graph.Nodes.Max(node => node.X); + float maxY = _graph.Nodes.Max(node => node.Y); + + float graphWidth = maxX - minX; + float graphHeight = maxY - minY; + + float scaleX = dirtyRect.Width / graphWidth; + float scaleY = dirtyRect.Height / graphHeight; + float scale = Math.Min(scaleX, scaleY) * 0.8f; + + float offsetX = dirtyRect.Center.X - ((minX + maxX) * 0.5f) * scale; + float offsetY = dirtyRect.Center.Y - ((minY + maxY) * 0.5f) * scale; + + + const float baseNodeRadius = 5; + float nodeRadius = baseNodeRadius * scale; foreach (var node in _graph.Nodes) { - // Draw the node - canvas.FillColor = Colors.Red; - canvas.FillCircle(node.X, node.Y, nodeRadius); - canvas.DrawString(node.Name, node.X + 12, node.Y - 5, HorizontalAlignment.Left); - - // Draw edges based on the adjacency matrix for (int j = 0; j < _graph.Nodes.Count; j++) { var (magnitude, angle) = _graph.AdjacencyMatrix[_graph.Nodes.IndexOf(node), j]; - // Only draw if there's a valid connection (magnitude > 0) if (magnitude > 0) { - // Calculate the target node's coordinates based on the angle and magnitude - float targetX = node.X + magnitude * MathF.Cos(MathF.PI * (angle / 180)); - float targetY = node.Y + magnitude * MathF.Sin(MathF.PI * (angle / 180)); - // Draw edge - canvas.StrokeColor = Colors.Black; + float targetX = (node.X + magnitude * MathF.Cos(MathF.PI * angle / 180)) * scale + offsetX; + float targetY = (node.Y + magnitude * MathF.Sin(MathF.PI * angle / 180)) * scale + offsetY; + + + canvas.StrokeColor = Colors.Grey; canvas.StrokeSize = 2; - canvas.DrawLine(node.X, node.Y, targetX, targetY); // Draw edge + canvas.DrawLine(node.X * scale + offsetX, node.Y * scale + offsetY, targetX, targetY); } } } + + // Draw nodes + foreach (var node in _graph.Nodes) + { + float scaledX = node.X * scale + offsetX; + float scaledY = node.Y * scale + offsetY; + canvas.FillColor = Colors.Red; + + if (node.Name == "Home") + { + canvas.FillColor = Colors.Green; + + } + canvas.FillCircle(scaledX, scaledY, nodeRadius); + canvas.FontColor = Colors.White; + canvas.DrawString(node.Name, scaledX + nodeRadius + 2, scaledY - nodeRadius, HorizontalAlignment.Left); + } } + } } diff --git a/App/RobobinApp/Views/MainPage.xaml b/App/RobobinApp/Views/MainPage.xaml index d771d9da3e384d72da8c10f3e6274f87981bfe14..bd416ccc45cac5ab19ebe2dcde447587167dd116 100644 --- a/App/RobobinApp/Views/MainPage.xaml +++ b/App/RobobinApp/Views/MainPage.xaml @@ -44,9 +44,8 @@ HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" Grid.Column="1" Grid.Row="0"> - <GraphicsView Drawable="{StaticResource drawable}" - HeightRequest="300" - WidthRequest="400" /> + <GraphicsView x:Name="GraphicsView" + Drawable="{StaticResource drawable}" /> </Frame> <VerticalStackLayout StyleClass="sideFrame" @@ -55,6 +54,12 @@ Grid.Column="2" Grid.Row="0"> <HorizontalStackLayout HorizontalOptions="Start" VerticalOptions="End"> <Button Text="Info" /> + <Picker Title="Select Graph" + ItemsSource="{Binding GraphNames}" + SelectedIndexChanged="OnGraphSelected" + HorizontalOptions="Center" /> + + </HorizontalStackLayout> <local:SideBox HeaderTitle="Mode:" /> <local:SideBox HeaderTitle="Admin:" /> diff --git a/App/RobobinApp/Views/MainPage.xaml.cs b/App/RobobinApp/Views/MainPage.xaml.cs index 6a20095e56467bdd3e44cbf774bbdba7fa4ec2d4..886ab3f3e07a93cf9f1a91c4bb0fb6602f4c30fa 100644 --- a/App/RobobinApp/Views/MainPage.xaml.cs +++ b/App/RobobinApp/Views/MainPage.xaml.cs @@ -1,6 +1,7 @@ using Microsoft.Maui.Controls; using RobobinApp.ViewModels; -using RobobinApp.Models; +using RobobinApp.Models; +using System.Diagnostics; namespace RobobinApp.Views { @@ -19,5 +20,24 @@ namespace RobobinApp.Views drawable.SetGraph(viewModel.Graph); } } + + private void OnGraphSelected(object sender, EventArgs e) + { + if (sender is Picker picker && BindingContext is MainPageViewModel viewModel) + { + // Update the selected graph + viewModel.SelectGraphCommand.Execute(picker.SelectedIndex); + + // Refresh the drawable with the new graph + var drawable = (GraphicsDrawable)Resources["drawable"]; + var newGraph = viewModel.Graphs.FirstOrDefault(g => g.Name == viewModel.Graph.Name); + drawable.SetGraph(newGraph); + + // Invalidate the GraphicsView to redraw the updated graph + GraphicsView.Invalidate(); + + Debug.WriteLine("New Graph picked and drawn"); + } + } } }