<commit_before>﻿using Choosability.FixerBreaker;
using Choosability.FixerBreaker.KnowledgeEngine;
using Graphs;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using Choosability;
using GraphicsLayer;
using System.Windows.Browser;
using GraphsCore;
using BitLevelGeneration;
using Choosability.Polynomials;
using SLPropertyGrid.MultiObject;
using System.IO.IsolatedStorage;

namespace WebGraphs
{
    public partial class MainPage : UserControl
    {
        public MainPage()
        {
            InitializeComponent();

            _mainMenu.NewClicked += NewTab;
            _mainMenu.CloseClicked += CloseSelectedTab;
            _mainMenu.CloseAllClicked += CloseAllTabs;
            _mainMenu.TogglePropertiesClicked += () => _propertiesContainer.Visibility = _propertiesContainer.Visibility == System.Windows.Visibility.Collapsed ? System.Windows.Visibility.Visible : System.Windows.Visibility.Collapsed;
            _mainMenu.UndoClicked += Undo;
            _mainMenu.RedoClicked += Redo;
            _mainMenu.CutClicked += Cut;
            _mainMenu.CopyClicked += Copy;
            _mainMenu.PasteClicked += Paste;
            _mainMenu.ZoomInClicked += ZoomIn;
            _mainMenu.ZoomOutClicked += ZoomOut;
            _mainMenu.ZoomFitClicked += ZoomFit;
            _mainMenu.LabelWithDegreesClicked += LabelWithDegrees;
            _mainMenu.LabelWithInDegreesClicked += LabelWithInDegrees;
            _mainMenu.LabelWithOutDegreesClicked += LabelWithOutDegrees;
            _mainMenu.ClearAllLabelsClicked += ClearLabels;
            _mainMenu.CountEulerianSubgraphs += CountEulerianSubgraphs;
            _mainMenu.CheckD1AT += CheckD1AT;
            _mainMenu.FindATNumber += FindATNumber;
            _mainMenu.FindStrongComponents += FindStrongComponents;
            _mainMenu.CheckD1Paintable += CheckD1Paintable;
            _mainMenu.Check2FoldD1Paintable += Check2FoldD1Paintable;
            _mainMenu.FindPaintNumber += FindPaintNumber;
            _mainMenu.ExportTeX += ExportTeX;
            _mainMenu.AnalyzeFixerBreaker += AnalyzeFixerBreaker;
            _mainMenu.DoMozhan += DoMozhan;
            _mainMenu.DoWebLink += ExportWebLink;
            _mainMenu.DoLightWebLink += ExportLightWebLink;
            _mainMenu.CheckfAT += CheckfAT;
            _mainMenu.CheckfATUsingFormula += CheckfATUsingFormula;
            _mainMenu.CheckfPaintable += CheckfPaintable;
            _mainMenu.LabelWithDegreeSymbol += LabelWithDegreeSymbol;
            _mainMenu.LabelWithDegreeSymbolMinusOne += LabelWithDegreeSymbolMinusOne;
            _mainMenu.DoGraph6 += DoGraph6;
            _mainMenu.DoEdgeWeights += DoEdgeWeights;
            _mainMenu.DoAdjacencyMatrix += DoAdjacencyMatrix;
            _mainMenu.ComputeCoefficient += ComputeCoefficient;
            _mainMenu.GenerateRandomOrientation += GenerateRandomOrientation;
            _mainMenu.GenerateBalancedOrientation += GenerateBalancedOrientation;
            _mainMenu.DoSpringsLayout += DoSpringsLayout;
            _mainMenu.CheckfChoosable += CheckfChoosable;
            _mainMenu.OnInstructions += OnInstructions;
            _mainMenu.OnAbout += OnAbout;
            _mainMenu.LabelWithOutDegreesPlusOneClicked += LabelWithOutDegreesPlusOne;
            _mainMenu.ComputeSignSum += ComputeSignSum;
            _mainMenu.ClearOrientation += ClearOrientation;
            _mainMenu.AnalyzeOnlyNearColorings += AnalyzeOnlyNearColorings;
            _mainMenu.AnalyzeOnlyNearColoringsForSelectedEdge += AnalyzeOnlyNearColoringsForSelectedEdge;
            _mainMenu.CheckFGPaintable += CheckFGPaintable;
            
            _propertyGrid.SomethingChanged += _propertyGrid_SomethingChanged;

            DoAutoLoad();
        }

        void DoAutoLoad()
        {
            try
            {
                var c = HtmlPage.Window.Invoke("GetURLParameter", "c") as string;
                if (!string.IsNullOrEmpty(c))
                {
                    AddTab(CompactSerializer.Deserialize(c), FindUnusedName());
                    return;
                }
            }
            catch { }

            try
            {
                var jib = HtmlPage.Window.Invoke("GetURLParameter", "jib") as string;
                if (!string.IsNullOrEmpty(jib))
                {
                    var json = Utility.Decompress(jib);
                    AddTab(Graphs.Graph.Deserialize(json), FindUnusedName());
                    return;
                }
            }
            catch { }
            try
            {
                HtmlPage.Window.Invoke("GetAutoLoad", (Action<string>)(json =>
                {
                    if (!string.IsNullOrEmpty(json))
                    {
                        AddTab(Graphs.Graph.Deserialize(json), FindUnusedName());
                        return;
                    }
                }));
            }
            catch { }

            try
            {
                var graph6 = HtmlPage.Window.Invoke("GetURLParameter", "graph6") as string;
                if (!string.IsNullOrEmpty(graph6))
                {
                    var gg = GraphsCore.GraphIO.GraphFromGraph6(graph6);
                    gg.Name = graph6;
                    AddTab(gg, graph6);
                    return;
                }
            }
            catch { }

            try
            {
                var ew = HtmlPage.Window.Invoke("GetURLParameter", "ew") as string;
                if (!string.IsNullOrEmpty(ew))
                {
                    AddTab(GraphsCore.GraphIO.GraphFromEdgeWeightString(ew), FindUnusedName());
                    return;
                }
            }
            catch { }

            if (!LoadFromLocalStorage())
                NewTab();
        }

        bool LoadFromLocalStorage()
        {
            var loadedSomething = false;
            foreach (var name in Storage.GetFileNames())
            {
                var g = Storage.Load(name);
                AddTab(g, name);
                loadedSomething = true;
            }

            return loadedSomething;
        }

        void _propertyGrid_SomethingChanged()
        {
            var tabCanvas = SelectedTabCanvas;
            if (tabCanvas != null)
                tabCanvas.Invalidate();
        }

        #region tab stuff
        void NewTab()
        {
            AddTab(null, FindUnusedName());
        }

        void AddTab(Graphs.Graph g, string name)
        {
            var item = new TabItem();
            item.Header = name;
            _tabControl.Items.Add(item);

            var canvas = new Canvas();
            item.Content = canvas;
            canvas.HorizontalAlignment = System.Windows.HorizontalAlignment.Stretch;
            canvas.VerticalAlignment = System.Windows.VerticalAlignment.Stretch;
            var tabCanvas = new TabCanvas(canvas, new GraphCanvas(g), _propertyGrid, item);
            tabCanvas.Title = name;
            item.Tag = tabCanvas;

            _tabControl.SelectedItem = item;
        }

        string FindUnusedName()
        {
            var root = "scratch ";
            var next = 1;
            foreach (TabItem ti in _tabControl.Items)
            {
                var headerText = ti.Header as string;

                if (headerText.StartsWith(root))
                {
                    int i;
                    if (int.TryParse(headerText.Replace(root, ""), out i))
                        next = Math.Max(next, i + 1);
                }
            }

            return root + next;
        }

        protected override void OnMouseLeftButtonUp(MouseButtonEventArgs e)
        {
            base.OnMouseLeftButtonUp(e);
        }

        TabCanvas GetTabCanvas(TabItem ti)
        {
            if (ti == null)
                return null;

            return (TabCanvas)ti.Tag;
        }

        TabCanvas SelectedTabCanvas { get { return GetTabCanvas(_tabControl.SelectedItem as TabItem); } }

        void CloseSelectedTab()
        {
            var selected = _tabControl.SelectedItem as TabItem;
            if (selected == null)
                return;

            var tc = (TabCanvas)selected.Tag;
            Storage.Delete(tc.Title);
            _tabControl.Items.Remove(selected);
        }

        void CloseAllTabs()
        {
            foreach (TabItem item in _tabControl.Items)
            {
                var tc = (TabCanvas)item.Tag;
                Storage.Delete(tc.Title);
            }
            _tabControl.Items.Clear();
        }

        void FocusSelectedTab()
        {
            var item = _tabControl.SelectedItem as TabItem;
            if (item == null)
                return;

            item.Focus();
        }
                
        #endregion

        protected override void OnMouseWheel(MouseWheelEventArgs e)
        {
            var tabCanvas = SelectedTabCanvas;
            if (tabCanvas == null)
                return;

            var p = e.GetPosition(tabCanvas.Canvas);
            tabCanvas.Operations.DoZoom(e.Delta / 120, new GraphicsLayer.Box((double)p.X / tabCanvas.Canvas.ActualWidth, (double)p.Y / tabCanvas.Canvas.ActualHeight));

            base.OnMouseWheel(e);
        }
        void ToolStripButtonClicked(object sender, MouseButtonEventArgs e)
        {
            var item = sender as Image;
            switch (((BitmapImage)item.Source).UriSource.OriginalString.Replace("/images/", ""))
            {
                case "new.png":
                    NewTab();
                    break;
                case "open.png":
                    break;
                case "delete.png":
                    DeleteSelected();
                    break;
                case "complement.png":
                    ComplementSelected();
                    break;
                case "compress-hi.png":
                    ContractSelected();
                    break;
                case "copy.png":
                    Copy();
                    break;
                case "cut.png":
                    Cut();
                    break;
                case "paste.png":
                    Paste();
                    break;
                case "undo.png":
                    Undo();
                    break;
                case "redo.png":
                    Redo();
                    break;
                case "squared.png":
                    TakeSquare();
                    break;
                case "line graph.png":
                    TakeLineGraph();
                    break;
                case "clear.png":
                    ClearLabels();
                    break;
                case "zoom fit.png":
                    ZoomFit();
                    break;
            }
        }

        protected override void OnKeyDown(KeyEventArgs e)
        {
            base.OnKeyDown(e);

            switch (e.Key)
            {
                case Key.A:
                    break;
                case Key.Add:
                    break;
                case Key.Alt:
                    break;
                case Key.B:
                    break;
                case Key.Back:
                    break;
                case Key.C:
                    if (Keyboard.Modifiers == ModifierKeys.Control)
                        Copy();
                    break;
                case Key.CapsLock:
                    break;
                case Key.Ctrl:
                    break;
                case Key.D:
                    break;
                case Key.D0:
                    break;
                case Key.D1:
                    break;
                case Key.D2:
                    break;
                case Key.D3:
                    break;
                case Key.D4:
                    break;
                case Key.D5:
                    break;
                case Key.D6:
                    break;
                case Key.D7:
                    break;
                case Key.D8:
                    break;
                case Key.D9:
                    break;
                case Key.Decimal:
                    break;
                case Key.Delete:
                    break;
                case Key.Divide:
                    break;
                case Key.Down:
                    break;
                case Key.E:
                    break;
                case Key.End:
                    break;
                case Key.Enter:
                    break;
                case Key.Escape:
                    break;
                case Key.F:
                    if (Keyboard.Modifiers == ModifierKeys.Control)
                        ZoomFit();
                    break;
                case Key.F1:
                    break;
                case Key.F10:
                    break;
                case Key.F11:
                    break;
                case Key.F12:
                    break;
                case Key.F2:
                    break;
                case Key.F3:
                    break;
                case Key.F4:
                    break;
                case Key.F5:
                    break;
                case Key.F6:
                    break;
                case Key.F7:
                    break;
                case Key.F8:
                    break;
                case Key.F9:
                    break;
                case Key.G:
                    break;
                case Key.H:
                    break;
                case Key.Home:
                    break;
                case Key.I:
                    break;
                case Key.Insert:
                    break;
                case Key.J:
                    break;
                case Key.K:
                    break;
                case Key.L:
                    break;
                case Key.Left:
                    break;
                case Key.M:
                    break;
                case Key.Multiply:
                    break;
                case Key.N:
                    if (Keyboard.Modifiers == ModifierKeys.Control)
                        NewTab();
                    break;
                case Key.None:
                    break;
                case Key.NumPad0:
                    break;
                case Key.NumPad1:
                    break;
                case Key.NumPad2:
                    break;
                case Key.NumPad3:
                    break;
                case Key.NumPad4:
                    break;
                case Key.NumPad5:
                    break;
                case Key.NumPad6:
                    break;
                case Key.NumPad7:
                    break;
                case Key.NumPad8:
                    break;
                case Key.NumPad9:
                    break;
                case Key.O:
                    break;
                case Key.P:
                    break;
                case Key.PageDown:
                    break;
                case Key.PageUp:
                    break;
                case Key.Q:
                    break;
                case Key.R:
                    break;
                case Key.Right:
                    break;
                case Key.S:
                    break;
                case Key.Shift:
                    break;
                case Key.Space:
                    break;
                case Key.Subtract:
                    break;
                case Key.T:
                    break;
                case Key.Tab:
                    break;
                case Key.U:
                    break;
                case Key.Unknown:
                    break;
                case Key.Up:
                    break;
                case Key.V:
                    if (Keyboard.Modifiers == ModifierKeys.Control)
                        Paste();
                    break;
                case Key.W:
                    break;
                case Key.X:
                    if (Keyboard.Modifiers == ModifierKeys.Control)
                        Cut();
                    break;
                case Key.Y:
                    if (Keyboard.Modifiers == ModifierKeys.Control)
                        Redo();
                    break;
                case Key.Z:
                    if (Keyboard.Modifiers == ModifierKeys.Control)
                        Undo();
                    break;
                default:
                    break;
            }
        }

        #region menu actions
        void OnAbout()
        {
            MessageBox.Show("web graphs\n\n\nlandon made", "about", MessageBoxButton.OK);
        }
        void OnInstructions()
        {
            MessageBox.Show(@"* Double left click to add vertex.
  * Hold down left mouse button and draw a curve, surround some
vertices, it will select them.
  * You can left click on selected vertices and drag them around.
  * With vertices selected, double left click on any vertex and it
will join the selected to that vertex.
  * If you draw the curve across some edges it will select them.
  * Hold ctrl key to select symmetric difference.
  * Mouse wheel zooms in and out.
  * You can delete anything when you have it selected by hitting the
trash can button.
  * The toolbar buttons have tool tips.
  * To use the f-choosability algorithms, put the list sizes as the vertex labels.
  * In the vertex labels you can use numbers, but also things like `d-1' to get degree minus one.
  * There are some helpers under the `Label' menu item.
  * You can paste in graphs in graph6 format.", "instructions", MessageBoxButton.OK);
        }
        void DeleteSelected()
        {
            var tabCanvas = SelectedTabCanvas;
            if (tabCanvas == null)
                return;

            tabCanvas.Operations.DoDelete();

            FocusSelectedTab();
        }
        void ComplementSelected()
        {
            var tabCanvas = SelectedTabCanvas;
            if (tabCanvas == null)
                return;

            tabCanvas.Operations.DoComplement();

            FocusSelectedTab();
        }
        void ContractSelected()
        {
            var tabCanvas = SelectedTabCanvas;
            if (tabCanvas == null)
                return;

            tabCanvas.Operations.DoContractSelectedSubgraph();

            FocusSelectedTab();
        }
        void ZoomFit()
        {
            var tabCanvas = SelectedTabCanvas;
            if (tabCanvas == null)
                return;

            tabCanvas.Operations.DoZoomFit();

            FocusSelectedTab();
        }
        void ZoomIn()
        {
            var tabCanvas = SelectedTabCanvas;
            if (tabCanvas == null)
                return;

            tabCanvas.Operations.DoZoom(1, new GraphicsLayer.Box(0.5, 0.5));

            FocusSelectedTab();
        }
        void ZoomOut()
        {
            var tabCanvas = SelectedTabCanvas;
            if (tabCanvas == null)
                return;

            tabCanvas.Operations.DoZoom(-1, new GraphicsLayer.Box(0.5, 0.5));

            FocusSelectedTab();
        }
        void Cut()
        {
            var tabCanvas = SelectedTabCanvas;
            if (tabCanvas == null)
                return;

            tabCanvas.Operations.DoCut();

            FocusSelectedTab();
        }
        void Copy()
        {
            var tabCanvas = SelectedTabCanvas;
            if (tabCanvas == null)
                return;

            tabCanvas.Operations.DoCopy();

            FocusSelectedTab();
        }
        void Paste()
        {
            var tabCanvas = SelectedTabCanvas;
            if (tabCanvas == null)
                return;

            tabCanvas.Operations.DoPaste();

            FocusSelectedTab();
        }
        void Undo()
        {
            var tabCanvas = SelectedTabCanvas;
            if (tabCanvas == null)
                return;

            tabCanvas.Operations.DoUndo();

            FocusSelectedTab();
        }
        void Redo()
        {
            var tabCanvas = SelectedTabCanvas;
            if (tabCanvas == null)
                return;

            tabCanvas.Operations.DoRedo();

            FocusSelectedTab();
        }
        void TakeSquare()
        {
            var tabCanvas = SelectedTabCanvas;
            if (tabCanvas == null)
                return;

            var g = tabCanvas.Operations.DoSquare();
            AddTab(g, string.Format("({0})^2", tabCanvas.Title));

            FocusSelectedTab();
        }
        void TakeLineGraph()
        {
            var tabCanvas = SelectedTabCanvas;
            if (tabCanvas == null)
                return;

            var g = tabCanvas.Operations.DoLineGraph();
            AddTab(g, string.Format("L({0})", tabCanvas.Title));

            FocusSelectedTab();
        }
        void LabelWithDegrees()
        {
            var tabCanvas = SelectedTabCanvas;
            if (tabCanvas == null)
                return;

            tabCanvas.Operations.DoDegreeLabeling();

            FocusSelectedTab();
        }
        void LabelWithInDegrees()
        {
            var tabCanvas = SelectedTabCanvas;
            if (tabCanvas == null)
                return;

            tabCanvas.Operations.DoInDegreeLabeling();

            FocusSelectedTab();
        }
        void LabelWithOutDegrees()
        {
            var tabCanvas = SelectedTabCanvas;
            if (tabCanvas == null)
                return;

            tabCanvas.Operations.DoOutDegreeLabeling();

            FocusSelectedTab();
        }
        void LabelWithOutDegreesPlusOne()
        {
            var tabCanvas = SelectedTabCanvas;
            if (tabCanvas == null)
                return;

            tabCanvas.Operations.DoOutDegreePlusOneLabeling();

            FocusSelectedTab();
        }
        void LabelWithDegreeSymbol()
        {
            var tabCanvas = SelectedTabCanvas;
            if (tabCanvas == null)
                return;

            tabCanvas.Operations.DoClearLabels("d", AlgorithmBlob.Create(SelectedTabCanvas).SelectedVertices);
        }
        void LabelWithDegreeSymbolMinusOne()
        {
            var tabCanvas = SelectedTabCanvas;
            if (tabCanvas == null)
                return;

            tabCanvas.Operations.DoClearLabels("d-1", AlgorithmBlob.Create(SelectedTabCanvas).SelectedVertices);
        }

        void ClearLabels()
        {
            var tabCanvas = SelectedTabCanvas;
            if (tabCanvas == null)
                return;

            tabCanvas.Operations.DoClearLabels("", AlgorithmBlob.Create(SelectedTabCanvas).SelectedVertices);

            FocusSelectedTab();
        }
        void ExportTeX()
        {
            var tabCanvas = SelectedTabCanvas;
            if (tabCanvas == null)
                return;

            var tikz = TeXConverter.ToTikz(tabCanvas.Operations.Graph);
            if (!string.IsNullOrEmpty(tikz))
            {
                ShowText(tikz);
            }
        }

        async void ExportWebLink()
        {
            var tabCanvas = SelectedTabCanvas;
            if (tabCanvas == null)
                return;

            var g = HttpUtility.UrlEncode(CompactSerializer.Serialize(tabCanvas.Operations.Graph));
            var url = @"https://dl.dropboxusercontent.com/u/8609833/Web/WebGraphs/WebGraphsTestPage.html?c=" + g;

            try
            {
                var address = new System.Uri("http://tinyurl.com/api-create.php?url=" + url);
                var client = new System.Net.WebClient();
                url = await AsyncPlatformExtensions.DownloadStringTaskAsync(client, address);

            }
            catch { }

            if (!string.IsNullOrEmpty(url))
                ShowText(url);
        }

        async void ExportLightWebLink()
        {
            var tabCanvas = SelectedTabCanvas;
            if (tabCanvas == null)<commit_msg>Changed back to JSON for weblinks.<commit_after>﻿using Choosability.FixerBreaker;
using Choosability.FixerBreaker.KnowledgeEngine;
using Graphs;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using Choosability;
using GraphicsLayer;
using System.Windows.Browser;
using GraphsCore;
using BitLevelGeneration;
using Choosability.Polynomials;
using SLPropertyGrid.MultiObject;
using System.IO.IsolatedStorage;

namespace WebGraphs
{
    public partial class MainPage : UserControl
    {
        public MainPage()
        {
            InitializeComponent();

            _mainMenu.NewClicked += NewTab;
            _mainMenu.CloseClicked += CloseSelectedTab;
            _mainMenu.CloseAllClicked += CloseAllTabs;
            _mainMenu.TogglePropertiesClicked += () => _propertiesContainer.Visibility = _propertiesContainer.Visibility == System.Windows.Visibility.Collapsed ? System.Windows.Visibility.Visible : System.Windows.Visibility.Collapsed;
            _mainMenu.UndoClicked += Undo;
            _mainMenu.RedoClicked += Redo;
            _mainMenu.CutClicked += Cut;
            _mainMenu.CopyClicked += Copy;
            _mainMenu.PasteClicked += Paste;
            _mainMenu.ZoomInClicked += ZoomIn;
            _mainMenu.ZoomOutClicked += ZoomOut;
            _mainMenu.ZoomFitClicked += ZoomFit;
            _mainMenu.LabelWithDegreesClicked += LabelWithDegrees;
            _mainMenu.LabelWithInDegreesClicked += LabelWithInDegrees;
            _mainMenu.LabelWithOutDegreesClicked += LabelWithOutDegrees;
            _mainMenu.ClearAllLabelsClicked += ClearLabels;
            _mainMenu.CountEulerianSubgraphs += CountEulerianSubgraphs;
            _mainMenu.CheckD1AT += CheckD1AT;
            _mainMenu.FindATNumber += FindATNumber;
            _mainMenu.FindStrongComponents += FindStrongComponents;
            _mainMenu.CheckD1Paintable += CheckD1Paintable;
            _mainMenu.Check2FoldD1Paintable += Check2FoldD1Paintable;
            _mainMenu.FindPaintNumber += FindPaintNumber;
            _mainMenu.ExportTeX += ExportTeX;
            _mainMenu.AnalyzeFixerBreaker += AnalyzeFixerBreaker;
            _mainMenu.DoMozhan += DoMozhan;
            _mainMenu.DoWebLink += ExportWebLink;
            _mainMenu.DoLightWebLink += ExportLightWebLink;
            _mainMenu.CheckfAT += CheckfAT;
            _mainMenu.CheckfATUsingFormula += CheckfATUsingFormula;
            _mainMenu.CheckfPaintable += CheckfPaintable;
            _mainMenu.LabelWithDegreeSymbol += LabelWithDegreeSymbol;
            _mainMenu.LabelWithDegreeSymbolMinusOne += LabelWithDegreeSymbolMinusOne;
            _mainMenu.DoGraph6 += DoGraph6;
            _mainMenu.DoEdgeWeights += DoEdgeWeights;
            _mainMenu.DoAdjacencyMatrix += DoAdjacencyMatrix;
            _mainMenu.ComputeCoefficient += ComputeCoefficient;
            _mainMenu.GenerateRandomOrientation += GenerateRandomOrientation;
            _mainMenu.GenerateBalancedOrientation += GenerateBalancedOrientation;
            _mainMenu.DoSpringsLayout += DoSpringsLayout;
            _mainMenu.CheckfChoosable += CheckfChoosable;
            _mainMenu.OnInstructions += OnInstructions;
            _mainMenu.OnAbout += OnAbout;
            _mainMenu.LabelWithOutDegreesPlusOneClicked += LabelWithOutDegreesPlusOne;
            _mainMenu.ComputeSignSum += ComputeSignSum;
            _mainMenu.ClearOrientation += ClearOrientation;
            _mainMenu.AnalyzeOnlyNearColorings += AnalyzeOnlyNearColorings;
            _mainMenu.AnalyzeOnlyNearColoringsForSelectedEdge += AnalyzeOnlyNearColoringsForSelectedEdge;
            _mainMenu.CheckFGPaintable += CheckFGPaintable;
            
            _propertyGrid.SomethingChanged += _propertyGrid_SomethingChanged;

            DoAutoLoad();
        }

        void DoAutoLoad()
        {
            try
            {
                var c = HtmlPage.Window.Invoke("GetURLParameter", "c") as string;
                if (!string.IsNullOrEmpty(c))
                {
                    AddTab(CompactSerializer.Deserialize(c), FindUnusedName());
                    return;
                }
            }
            catch { }

            try
            {
                var jib = HtmlPage.Window.Invoke("GetURLParameter", "jib") as string;
                if (!string.IsNullOrEmpty(jib))
                {
                    var json = Utility.Decompress(jib);
                    AddTab(Graphs.Graph.Deserialize(json), FindUnusedName());
                    return;
                }
            }
            catch { }
            try
            {
                HtmlPage.Window.Invoke("GetAutoLoad", (Action<string>)(json =>
                {
                    if (!string.IsNullOrEmpty(json))
                    {
                        AddTab(Graphs.Graph.Deserialize(json), FindUnusedName());
                        return;
                    }
                }));
            }
            catch { }

            try
            {
                var graph6 = HtmlPage.Window.Invoke("GetURLParameter", "graph6") as string;
                if (!string.IsNullOrEmpty(graph6))
                {
                    var gg = GraphsCore.GraphIO.GraphFromGraph6(graph6);
                    gg.Name = graph6;
                    AddTab(gg, graph6);
                    return;
                }
            }
            catch { }

            try
            {
                var ew = HtmlPage.Window.Invoke("GetURLParameter", "ew") as string;
                if (!string.IsNullOrEmpty(ew))
                {
                    AddTab(GraphsCore.GraphIO.GraphFromEdgeWeightString(ew), FindUnusedName());
                    return;
                }
            }
            catch { }

            if (!LoadFromLocalStorage())
                NewTab();
        }

        bool LoadFromLocalStorage()
        {
            var loadedSomething = false;
            foreach (var name in Storage.GetFileNames())
            {
                var g = Storage.Load(name);
                AddTab(g, name);
                loadedSomething = true;
            }

            return loadedSomething;
        }

        void _propertyGrid_SomethingChanged()
        {
            var tabCanvas = SelectedTabCanvas;
            if (tabCanvas != null)
                tabCanvas.Invalidate();
        }

        #region tab stuff
        void NewTab()
        {
            AddTab(null, FindUnusedName());
        }

        void AddTab(Graphs.Graph g, string name)
        {
            var item = new TabItem();
            item.Header = name;
            _tabControl.Items.Add(item);

            var canvas = new Canvas();
            item.Content = canvas;
            canvas.HorizontalAlignment = System.Windows.HorizontalAlignment.Stretch;
            canvas.VerticalAlignment = System.Windows.VerticalAlignment.Stretch;
            var tabCanvas = new TabCanvas(canvas, new GraphCanvas(g), _propertyGrid, item);
            tabCanvas.Title = name;
            item.Tag = tabCanvas;

            _tabControl.SelectedItem = item;
        }

        string FindUnusedName()
        {
            var root = "scratch ";
            var next = 1;
            foreach (TabItem ti in _tabControl.Items)
            {
                var headerText = ti.Header as string;

                if (headerText.StartsWith(root))
                {
                    int i;
                    if (int.TryParse(headerText.Replace(root, ""), out i))
                        next = Math.Max(next, i + 1);
                }
            }

            return root + next;
        }

        protected override void OnMouseLeftButtonUp(MouseButtonEventArgs e)
        {
            base.OnMouseLeftButtonUp(e);
        }

        TabCanvas GetTabCanvas(TabItem ti)
        {
            if (ti == null)
                return null;

            return (TabCanvas)ti.Tag;
        }

        TabCanvas SelectedTabCanvas { get { return GetTabCanvas(_tabControl.SelectedItem as TabItem); } }

        void CloseSelectedTab()
        {
            var selected = _tabControl.SelectedItem as TabItem;
            if (selected == null)
                return;

            var tc = (TabCanvas)selected.Tag;
            Storage.Delete(tc.Title);
            _tabControl.Items.Remove(selected);
        }

        void CloseAllTabs()
        {
            foreach (TabItem item in _tabControl.Items)
            {
                var tc = (TabCanvas)item.Tag;
                Storage.Delete(tc.Title);
            }
            _tabControl.Items.Clear();
        }

        void FocusSelectedTab()
        {
            var item = _tabControl.SelectedItem as TabItem;
            if (item == null)
                return;

            item.Focus();
        }
                
        #endregion

        protected override void OnMouseWheel(MouseWheelEventArgs e)
        {
            var tabCanvas = SelectedTabCanvas;
            if (tabCanvas == null)
                return;

            var p = e.GetPosition(tabCanvas.Canvas);
            tabCanvas.Operations.DoZoom(e.Delta / 120, new GraphicsLayer.Box((double)p.X / tabCanvas.Canvas.ActualWidth, (double)p.Y / tabCanvas.Canvas.ActualHeight));

            base.OnMouseWheel(e);
        }
        void ToolStripButtonClicked(object sender, MouseButtonEventArgs e)
        {
            var item = sender as Image;
            switch (((BitmapImage)item.Source).UriSource.OriginalString.Replace("/images/", ""))
            {
                case "new.png":
                    NewTab();
                    break;
                case "open.png":
                    break;
                case "delete.png":
                    DeleteSelected();
                    break;
                case "complement.png":
                    ComplementSelected();
                    break;
                case "compress-hi.png":
                    ContractSelected();
                    break;
                case "copy.png":
                    Copy();
                    break;
                case "cut.png":
                    Cut();
                    break;
                case "paste.png":
                    Paste();
                    break;
                case "undo.png":
                    Undo();
                    break;
                case "redo.png":
                    Redo();
                    break;
                case "squared.png":
                    TakeSquare();
                    break;
                case "line graph.png":
                    TakeLineGraph();
                    break;
                case "clear.png":
                    ClearLabels();
                    break;
                case "zoom fit.png":
                    ZoomFit();
                    break;
            }
        }

        protected override void OnKeyDown(KeyEventArgs e)
        {
            base.OnKeyDown(e);

            switch (e.Key)
            {
                case Key.A:
                    break;
                case Key.Add:
                    break;
                case Key.Alt:
                    break;
                case Key.B:
                    break;
                case Key.Back:
                    break;
                case Key.C:
                    if (Keyboard.Modifiers == ModifierKeys.Control)
                        Copy();
                    break;
                case Key.CapsLock:
                    break;
                case Key.Ctrl:
                    break;
                case Key.D:
                    break;
                case Key.D0:
                    break;
                case Key.D1:
                    break;
                case Key.D2:
                    break;
                case Key.D3:
                    break;
                case Key.D4:
                    break;
                case Key.D5:
                    break;
                case Key.D6:
                    break;
                case Key.D7:
                    break;
                case Key.D8:
                    break;
                case Key.D9:
                    break;
                case Key.Decimal:
                    break;
                case Key.Delete:
                    break;
                case Key.Divide:
                    break;
                case Key.Down:
                    break;
                case Key.E:
                    break;
                case Key.End:
                    break;
                case Key.Enter:
                    break;
                case Key.Escape:
                    break;
                case Key.F:
                    if (Keyboard.Modifiers == ModifierKeys.Control)
                        ZoomFit();
                    break;
                case Key.F1:
                    break;
                case Key.F10:
                    break;
                case Key.F11:
                    break;
                case Key.F12:
                    break;
                case Key.F2:
                    break;
                case Key.F3:
                    break;
                case Key.F4:
                    break;
                case Key.F5:
                    break;
                case Key.F6:
                    break;
                case Key.F7:
                    break;
                case Key.F8:
                    break;
                case Key.F9:
                    break;
                case Key.G:
                    break;
                case Key.H:
                    break;
                case Key.Home:
                    break;
                case Key.I:
                    break;
                case Key.Insert:
                    break;
                case Key.J:
                    break;
                case Key.K:
                    break;
                case Key.L:
                    break;
                case Key.Left:
                    break;
                case Key.M:
                    break;
                case Key.Multiply:
                    break;
                case Key.N:
                    if (Keyboard.Modifiers == ModifierKeys.Control)
                        NewTab();
                    break;
                case Key.None:
                    break;
                case Key.NumPad0:
                    break;
                case Key.NumPad1:
                    break;
                case Key.NumPad2:
                    break;
                case Key.NumPad3:
                    break;
                case Key.NumPad4:
                    break;
                case Key.NumPad5:
                    break;
                case Key.NumPad6:
                    break;
                case Key.NumPad7:
                    break;
                case Key.NumPad8:
                    break;
                case Key.NumPad9:
                    break;
                case Key.O:
                    break;
                case Key.P:
                    break;
                case Key.PageDown:
                    break;
                case Key.PageUp:
                    break;
                case Key.Q:
                    break;
                case Key.R:
                    break;
                case Key.Right:
                    break;
                case Key.S:
                    break;
                case Key.Shift:
                    break;
                case Key.Space:
                    break;
                case Key.Subtract:
                    break;
                case Key.T:
                    break;
                case Key.Tab:
                    break;
                case Key.U:
                    break;
                case Key.Unknown:
                    break;
                case Key.Up:
                    break;
                case Key.V:
                    if (Keyboard.Modifiers == ModifierKeys.Control)
                        Paste();
                    break;
                case Key.W:
                    break;
                case Key.X:
                    if (Keyboard.Modifiers == ModifierKeys.Control)
                        Cut();
                    break;
                case Key.Y:
                    if (Keyboard.Modifiers == ModifierKeys.Control)
                        Redo();
                    break;
                case Key.Z:
                    if (Keyboard.Modifiers == ModifierKeys.Control)
                        Undo();
                    break;
                default:
                    break;
            }
        }

        #region menu actions
        void OnAbout()
        {
            MessageBox.Show("web graphs\n\n\nlandon made", "about", MessageBoxButton.OK);
        }
        void OnInstructions()
        {
            MessageBox.Show(@"* Double left click to add vertex.
  * Hold down left mouse button and draw a curve, surround some
vertices, it will select them.
  * You can left click on selected vertices and drag them around.
  * With vertices selected, double left click on any vertex and it
will join the selected to that vertex.
  * If you draw the curve across some edges it will select them.
  * Hold ctrl key to select symmetric difference.
  * Mouse wheel zooms in and out.
  * You can delete anything when you have it selected by hitting the
trash can button.
  * The toolbar buttons have tool tips.
  * To use the f-choosability algorithms, put the list sizes as the vertex labels.
  * In the vertex labels you can use numbers, but also things like `d-1' to get degree minus one.
  * There are some helpers under the `Label' menu item.
  * You can paste in graphs in graph6 format.", "instructions", MessageBoxButton.OK);
        }
        void DeleteSelected()
        {
            var tabCanvas = SelectedTabCanvas;
            if (tabCanvas == null)
                return;

            tabCanvas.Operations.DoDelete();

            FocusSelectedTab();
        }
        void ComplementSelected()
        {
            var tabCanvas = SelectedTabCanvas;
            if (tabCanvas == null)
                return;

            tabCanvas.Operations.DoComplement();

            FocusSelectedTab();
        }
        void ContractSelected()
        {
            var tabCanvas = SelectedTabCanvas;
            if (tabCanvas == null)
                return;

            tabCanvas.Operations.DoContractSelectedSubgraph();

            FocusSelectedTab();
        }
        void ZoomFit()
        {
            var tabCanvas = SelectedTabCanvas;
            if (tabCanvas == null)
                return;

            tabCanvas.Operations.DoZoomFit();

            FocusSelectedTab();
        }
        void ZoomIn()
        {
            var tabCanvas = SelectedTabCanvas;
            if (tabCanvas == null)
                return;

            tabCanvas.Operations.DoZoom(1, new GraphicsLayer.Box(0.5, 0.5));

            FocusSelectedTab();
        }
        void ZoomOut()
        {
            var tabCanvas = SelectedTabCanvas;
            if (tabCanvas == null)
                return;

            tabCanvas.Operations.DoZoom(-1, new GraphicsLayer.Box(0.5, 0.5));

            FocusSelectedTab();
        }
        void Cut()
        {
            var tabCanvas = SelectedTabCanvas;
            if (tabCanvas == null)
                return;

            tabCanvas.Operations.DoCut();

            FocusSelectedTab();
        }
        void Copy()
        {
            var tabCanvas = SelectedTabCanvas;
            if (tabCanvas == null)
                return;

            tabCanvas.Operations.DoCopy();

            FocusSelectedTab();
        }
        void Paste()
        {
            var tabCanvas = SelectedTabCanvas;
            if (tabCanvas == null)
                return;

            tabCanvas.Operations.DoPaste();

            FocusSelectedTab();
        }
        void Undo()
        {
            var tabCanvas = SelectedTabCanvas;
            if (tabCanvas == null)
                return;

            tabCanvas.Operations.DoUndo();

            FocusSelectedTab();
        }
        void Redo()
        {
            var tabCanvas = SelectedTabCanvas;
            if (tabCanvas == null)
                return;

            tabCanvas.Operations.DoRedo();

            FocusSelectedTab();
        }
        void TakeSquare()
        {
            var tabCanvas = SelectedTabCanvas;
            if (tabCanvas == null)
                return;

            var g = tabCanvas.Operations.DoSquare();
            AddTab(g, string.Format("({0})^2", tabCanvas.Title));

            FocusSelectedTab();
        }
        void TakeLineGraph()
        {
            var tabCanvas = SelectedTabCanvas;
            if (tabCanvas == null)
                return;

            var g = tabCanvas.Operations.DoLineGraph();
            AddTab(g, string.Format("L({0})", tabCanvas.Title));

            FocusSelectedTab();
        }
        void LabelWithDegrees()
        {
            var tabCanvas = SelectedTabCanvas;
            if (tabCanvas == null)
                return;

            tabCanvas.Operations.DoDegreeLabeling();

            FocusSelectedTab();
        }
        void LabelWithInDegrees()
        {
            var tabCanvas = SelectedTabCanvas;
            if (tabCanvas == null)
                return;

            tabCanvas.Operations.DoInDegreeLabeling();

            FocusSelectedTab();
        }
        void LabelWithOutDegrees()
        {
            var tabCanvas = SelectedTabCanvas;
            if (tabCanvas == null)
                return;

            tabCanvas.Operations.DoOutDegreeLabeling();

            FocusSelectedTab();
        }
        void LabelWithOutDegreesPlusOne()
        {
            var tabCanvas = SelectedTabCanvas;
            if (tabCanvas == null)
                return;

            tabCanvas.Operations.DoOutDegreePlusOneLabeling();

            FocusSelectedTab();
        }
        void LabelWithDegreeSymbol()
        {
            var tabCanvas = SelectedTabCanvas;
            if (tabCanvas == null)
                return;

            tabCanvas.Operations.DoClearLabels("d", AlgorithmBlob.Create(SelectedTabCanvas).SelectedVertices);
        }
        void LabelWithDegreeSymbolMinusOne()
        {
            var tabCanvas = SelectedTabCanvas;
            if (tabCanvas == null)
                return;

            tabCanvas.Operations.DoClearLabels("d-1", AlgorithmBlob.Create(SelectedTabCanvas).SelectedVertices);
        }

        void ClearLabels()
        {
            var tabCanvas = SelectedTabCanvas;
            if (tabCanvas == null)
                return;

            tabCanvas.Operations.DoClearLabels("", AlgorithmBlob.Create(SelectedTabCanvas).SelectedVertices);

            FocusSelectedTab();
        }
        void ExportTeX()
        {
            var tabCanvas = SelectedTabCanvas;
            if (tabCanvas == null)
                return;

            var tikz = TeXConverter.ToTikz(tabCanvas.Operations.Graph);
            if (!string.IsNullOrEmpty(tikz))
            {
                ShowText(tikz);
            }
        }

        async void ExportWebLink()
        {
            var tabCanvas = SelectedTabCanvas;
            if (tabCanvas == null)
                return;

            var json = tabCanvas.Operations.Graph.Serialize();
            var g = HttpUtility.UrlEncode(Utility.Compress(json));

            var url = @"https://dl.dropboxusercontent.com/u/8609833/Web/WebGraphs/WebGraphsTestPage.html?jib=" + g;

            try
            {
                var address = new System.Uri("http://tinyurl.com/api-create.php?url=" + url);
                var client = new System.Net.WebClient();
                url = await AsyncPlatformExtensions.DownloadStringTaskAsync(client, address);

            }
            catch { }

            if (!string.IsNullOrEmpty(url))
                ShowText(url);
        }

        async void ExportLightWebLink()
        {
            var tabCanvas = SelectedTabCanvas;
            if (tabCanvas == null)
{'fraction_non_alphanumeric': 0.07777047024005261, 'fraction_numerical': 0.003288391976323578, 'mean_word_length': 1.152488387524884, 'pattern_counts': {'":': 28, '<': 5, '<?xml version=': 0, '>': 9, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1824583', 'n_tokens_mistral': 12398, 'n_tokens_neox': 11472, 'n_words': 2497}