// FIXME: Keyboard and general mouse movement events!! public override bool KeyPressed(CircuitEditor editor, Gdk.EventKey eventKey) { bool consumed = false; var modifiers = eventKey.State & Accelerator.DefaultModMask; if (modifiers == Gdk.ModifierType.None) { // No modifiers are pressed if (eventKey.Key == Gdk.Key.Up) { CompOrientation = Circuit.Orientation.North; consumed = true; } if (eventKey.Key == Gdk.Key.Down) { CompOrientation = Circuit.Orientation.South; consumed = true; } if (eventKey.Key == Gdk.Key.Left) { CompOrientation = Circuit.Orientation.West; consumed = true; } if (eventKey.Key == Gdk.Key.Right) { CompOrientation = Circuit.Orientation.East; consumed = true; } } if (consumed) { editor.DrawingArea.QueueDraw(); } return(consumed); }
static Gtk.Toolbar CreateToolbar(CircuitEditor editor) { Gtk.Toolbar toolbar = new Gtk.Toolbar(); SelectTool selectTool = new SelectTool(editor, toolbar); WireTool wireTool = new WireTool(editor, toolbar); // FIXME: Make this be selected with a callback or something //editor.CurrentTool = selectTool; ComponentTool constantTool = new ComponentTool(ComponentType.Constant, "Constant", editor, toolbar); ComponentTool bufferTool = new ComponentTool(ComponentType.Buffer, "Buffer gate", editor, toolbar); ComponentTool notTool = new ComponentTool(ComponentType.Not, "Not gate", editor, toolbar); ComponentTool andTool = new ComponentTool(ComponentType.And, "And gate", editor, toolbar); ComponentTool orTool = new ComponentTool(ComponentType.Or, "Or gate", editor, toolbar); ComponentTool xorTool = new ComponentTool(ComponentType.Xor, "Xor gate", editor, toolbar); SeparatorToolItem sep = new SeparatorToolItem(); int index = 0; toolbar.Insert(selectTool, index++); toolbar.Insert(wireTool, index++); toolbar.Insert(sep, index++); toolbar.Insert(constantTool, index++); toolbar.Insert(bufferTool, index++); toolbar.Insert(notTool, index++); toolbar.Insert(andTool, index++); toolbar.Insert(orTool, index++); toolbar.Insert(xorTool, index++); return(toolbar); }
public SelectTool( CircuitEditor circuitEditor, Gtk.Toolbar toolbar ) : base(Util.Icon.Selector(), "Select", circuitEditor, toolbar) { }
public void ClearSelection(CircuitEditor editor) { SelectedWires.Clear(); SelectedGates.Clear(); editor.DrawingArea.QueueDraw(); }
public BasicTool(Image image, string name, CircuitEditor circuitEditor) : base(image, name) { CircuitEditor = circuitEditor; Clicked += BasicTool_Clicked; }
public override void GestureEnd(CircuitEditor editor, Vector2d endOffset) { // FIXME: Do l-shaped wire addition var diff = editor.RoundDistToGrid(endOffset); if (Math.Abs(diff.X) > Math.Abs(diff.Y)) { // FIXME: We shouldn't rely on the constructor to flip negative diffs // because we are going to remove that so we should do it ourselves here. // Here we are drawing a horizontal line CurrentWire = new Wire(DragStartPos, diff.X, Circuit.Direction.Horizontal); } else { //This should be a vertical line CurrentWire = new Wire(DragStartPos, diff.Y, Circuit.Direction.Vertical); } DraggingWire = false; if (CurrentWire.Length != 0) { // Here we should figure out if we are modifying an existing wire. // Because adding wires handles merging wires that go in the same // direction, we only want to detect the case where we are shrinking // a wire. This is easy, because we only need to check that we grabbed // one end of the wire and the the other end is inside the wire we want // to shrink. Wire?modifying = null; bool movingEnd = false; foreach (var bWire in editor.Scene.Wires.WiresList) { if (CurrentWire.Direction != bWire.Direction) { continue; } // We do 'IsPointInsideWire' because we don't want to detect the case // where we are dragging a wire left from a junction to create a new wire. // What would happen if we used 'IsPointOnWire' is that the start pos would // be equal and at the same time 'CurrentWire.Pos' would be on the wire, // making us think that we want to edit the wire while we don't want to. if (DragStartPos == bWire.Pos && bWire.IsPointInsideWire(CurrentWire.EndPos)) { modifying = bWire; movingEnd = false; } else if (DragStartPos == bWire.EndPos && bWire.IsPointInsideWire(CurrentWire.Pos)) { modifying = bWire; movingEnd = true; } else if (CurrentWire == bWire) { // If they are the same wire we want to remove the bWire modifying = bWire; } } // If there there more than one endpoint at the start position // We don't want to modify a wire, we want to create a new one // If there was only one point we check that we actually want to // modify that wire (ie modifying is not null). if (modifying is Wire modify) { // Here we are modifying an existing wire. // So we should figure out how the wire should be modified. // If the wire is deleted we need to check for places where we should merge // other connecting wires. The creation of the remove transaction should // probably be created in a Wires.CreateRemoveWireTransaction(...). Wire modifiedWire = modify; if (movingEnd == false) { // Here we are moving the start poistion of the wire. diff = CurrentWire.EndPos - modify.Pos; modifiedWire.Pos = CurrentWire.EndPos; modifiedWire.Length -= diff.ManhattanDistance; } else { // Here we only need to change the length of the wire. diff = modify.EndPos - CurrentWire.Pos; modifiedWire.Length -= diff.ManhattanDistance; } if (modifiedWire.Length > 0) { // FIMXE: Figure out if there are any edge-cases when modifying wires like this. // One of the cases is where the modified wire should split another already // existing wire. WireTransaction?modifyTransaction = editor.Scene.Wires.CreateModifyWireTransaction(modify, modifiedWire); if (modifyTransaction != null) { editor.Scene.PushTransaction(modifyTransaction); //Console.WriteLine($"Modified existing wire! ({modify}) -> ({modifiedWire})\n{modifyTransaction}\n"); } } else { // Here we should remove the wire completely var deleteTransaction = editor.Scene.Wires.CreateRemoveWireTransaction(modify); editor.Scene.PushTransaction(deleteTransaction); //Console.WriteLine($"Deleted wire! ({modify})\n{deleteTransaction}\n"); } } else { var transaction = editor.Scene.Wires.CreateAddWireTransaction(CurrentWire); if (transaction != null) { editor.Scene.PushTransaction(transaction); //Console.WriteLine($"End wire!\n{transaction}\n"); } else { //Console.WriteLine($"No wire created!\n"); } } } else { //Console.WriteLine($"Zero length wire!\n\n"); } editor.DrawingArea.QueueDraw(); }
public abstract void GestureStart(CircuitEditor editor, Vector2d dragStartPos);
public abstract void GestureEnd(CircuitEditor editor, Vector2d endOffset);
// VERY IMPORTANT!!!!!!!!!!!! // After the call to Application.Init() NullReferenceExceptions // will no longer be thrown. This is an active bug in GtkSharp // and can be tracked here https://github.com/GtkSharp/GtkSharp/issues/155 // Hopefully this can be fixed sooner rather than later... static void Main() { Backend = Logic.Init(); CultureInfo.CurrentCulture = CultureInfo.InvariantCulture; Value a = new Value(0b00_00_00_00_01_01_01_01_10_10_10_10_11_11_11_11, 16); Value b = new Value(0b00_01_10_11_00_01_10_11_00_01_10_11_00_01_10_11, 16); Console.WriteLine($"Resolve: {Value.Resolve(a, b)}"); Console.WriteLine($"And: {Value.And(a, b)}"); Console.WriteLine($"Or: {Value.Or(a, b)}"); Console.WriteLine($"Not: {Value.Not(a)}"); Application.Init(); GLib.ExceptionManager.UnhandledException += ExceptionManager_UnhandledException; Window wnd = new Window("Logik"); wnd.Resize(1600, 800); Notebook nbook = new Notebook(); var circuitEditor = new CircuitEditor(); nbook.AppendPage(circuitEditor.DrawingArea, new Label("Circuit editor")); nbook.AppendPage(new Label("TODO: Package editor"), new Label("Package editor")); Notebook sideBar = new Notebook(); var components = new ComponentView(new List <ComponentFolder> { new ComponentFolder("Test folder 1", new List <Component.Component>() { new Component.Component("Test comp 1", "x-office-document"), new Component.Component("Test comp 2", "x-office-document"), new Component.Component("Test comp 3", "x-office-document"), }), new ComponentFolder("Test folder 2", new List <Component.Component>() { new Component.Component("Another test comp 1", "x-office-document"), new Component.Component("Another test comp 2", "x-office-document"), new Component.Component("Another test comp 3", "x-office-document"), }), }); sideBar.AppendPage(components.TreeView, new Label("Components")); var hierarchy = new HierarchyView(new HierarchyComponent("Top comp", "x-office-document", new List <HierarchyComponent>() { new HierarchyComponent("Test Comp 1", "x-office-document", new List <HierarchyComponent>() { new HierarchyComponent("Test Nested Comp 1", "x-office-document", new List <HierarchyComponent>()), }), new HierarchyComponent("Test Comp 2", "x-office-document", new List <HierarchyComponent>() { new HierarchyComponent("Test Nested Comp 1", "x-office-document", new List <HierarchyComponent>()), new HierarchyComponent("Test Nested Comp 2", "x-office-document", new List <HierarchyComponent>()), }), new HierarchyComponent("Test Comp 3", "x-office-document", new List <HierarchyComponent>()), })); sideBar.AppendPage(hierarchy.TreeView, new Label("Hierarchy")); HPaned hPaned = new HPaned(); hPaned.Pack1(sideBar, false, false); hPaned.Pack2(nbook, true, false); //Add the label to the form VBox box = new VBox(false, 0); box.PackStart(CreateMenuBar(wnd), false, false, 0); box.PackStart(CreateToolbar(circuitEditor), false, false, 0); box.PackEnd(hPaned, true, true, 0); box.Expand = true; wnd.Add(box); wnd.Destroyed += Wnd_Destroyed; wnd.ShowAll(); Application.Run(); }
public SelectTool(CircuitEditor circuitEditor) : base(Icon.Selector(), "Select", circuitEditor) { }
public override void GestureUpdate(CircuitEditor editor, Vector2d offset) { SelectionSize = editor.RoundDistToGrid(offset); editor.DrawingArea.QueueDraw(); }
public override void GestureEnd(CircuitEditor editor, Vector2d endOffset) { SelectionSize = editor.RoundDistToGrid(endOffset); Selecting = false; // Make sure we don't have a negitive size if (SelectionSize.X < 0) { SelectionSize.X = -SelectionSize.X; SelectionStart.X -= SelectionSize.X; } if (SelectionSize.Y < 0) { SelectionSize.Y = -SelectionSize.Y; SelectionStart.Y -= SelectionSize.Y; } if (Poking) { Poking = false; LogikUI.Simulation.ReleaseComponent(SelectedGates[0].ID); } // FIXME: Do the selecting var wires = editor.Scene.Wires; // If the size is zero we want to check if we clicked a wire or gate if (SelectionSize == Vector2i.Zero) { ClearSelection(editor); bool foundGate = false; var pos = editor.FromGridToWorld(SelectionStart); foreach (var instance in editor.Scene.Gates.Instances) { Rect r = editor.Scene.Gates.GetBounds(instance); r = r.Rotate(instance.Position * CircuitEditor.DotSpacing, instance.Orientation); if (r.Contains(pos)) { SelectedGates.Add(instance); break; } } if (foundGate == false) { foreach (var wire in wires.WiresList) { if (wire.IsPointOnWire(SelectionStart)) { SelectedWires.Add(wire); foundGate = true; break; } } } } else { ClearSelection(editor); // Here we should loop through all wires and see if they are contained in the area Recti selectionRect = new Recti(SelectionStart, SelectionSize); foreach (var wire in wires.WiresList) { if (selectionRect.Contains(wire.Pos) && selectionRect.Contains(wire.EndPos)) { SelectedWires.Add(wire); Console.WriteLine($"Selected wire: {wire}"); } } Rect worldRect = editor.FromGridToWorld(selectionRect); foreach (var instance in editor.Scene.Gates.Instances) { Rect r = editor.Scene.Gates.GetBounds(instance); r = r.Rotate(instance.Position * CircuitEditor.DotSpacing, instance.Orientation); if (worldRect.Contains(r)) { SelectedGates.Add(instance); } } } editor.DrawingArea.QueueDraw(); }
public override void DeSelect(CircuitEditor editor) { }
public WireTool(CircuitEditor circuitEditor) : base(Icon.Wire(), "Wire", circuitEditor) { }
// Use this for initialization void Start() { Application.targetFrameRate = -1; QualitySettings.vSyncCount = 0; circuitEditor = new CircuitEditor(notGateTex, bufferGateTex, wireTex, emptyTex, outputPlane); }
public override void GestureUpdate(CircuitEditor editor, Vector2d offset) { SelectionSize = editor.RoundDistToGrid(offset); //Console.WriteLine($"Size: {SelectionSize}"); editor.DrawingArea.QueueDraw(); }
public virtual bool KeyPressed(CircuitEditor editor, EventKey eventKey) => false;
static MenuBar CreateMenuBar(Window parent, CircuitEditor editor) { MenuItem open = new MenuItem("Open..."); open.Activated += (object?sender, EventArgs e) => { FileChooserDialog fcd = new FileChooserDialog("Open Project", parent, FileChooserAction.Open, Stock.Open, ResponseType.Ok, Stock.Cancel, ResponseType.Cancel); fcd.SelectMultiple = false; AddFilters(fcd); if (fcd.Run() == (int)ResponseType.Ok) { try { FileManager.Load(fcd.Filename); Console.WriteLine($"Successfully read and parsed project file { fcd.Filename }."); Console.WriteLine($"- wires: { FileManager.Wires }"); Console.WriteLine($"- components: { FileManager.Components }"); Console.WriteLine($"- labels: { FileManager.Labels }"); var lables = new TextLabels(FileManager.Labels.ToArray()); var gates = new Gates(); gates.Instances = FileManager.Components; var wires = new Wires(gates, FileManager.Wires.ToArray()); editor.Scene = new Scene(wires, gates, lables); } catch (Exception err) { // FIXME: Do something if parse fails? Output.WriteError($"Failed to read and parse project file { fcd.Filename }.", err); } } fcd.Dispose(); }; MenuItem saveAs = new MenuItem("Save As..."); saveAs.Activated += (object?sender, EventArgs e) => { FileChooserDialog fcd = new FileChooserDialog("Save Project", parent, FileChooserAction.Save, Stock.Save, ResponseType.Ok, Stock.Cancel, ResponseType.Cancel); AddFilters(fcd); if (fcd.Run() == (int)ResponseType.Ok) { try { FileManager.Labels = new List <TextLabel>(editor.Scene.Labels.Labels); FileManager.Wires = editor.Scene.Wires.WiresList; FileManager.Components = editor.Scene.Gates.Instances; FileManager.Save(fcd.Filename); Console.WriteLine($"Successfully saved and parsed project file { fcd.Filename }."); Console.WriteLine($"- wires: { FileManager.Wires }"); Console.WriteLine($"- components: { FileManager.Components }"); Console.WriteLine($"- labels: { FileManager.Labels }"); } catch (Exception err) { // FIXME: Do something if parse fails? Output.WriteError($"Failed to write and parse project file { fcd.Filename }.", err); } } fcd.Dispose(); }; MenuItem save = new MenuItem("Save..."); save.Activated += (object?sender, EventArgs e) => { if (FileManager.IsNew) { saveAs.Activate(); } else { FileManager.Save(); } }; Menu fileMenu = new Menu(); fileMenu.Append(open); fileMenu.Append(save); fileMenu.Append(saveAs); MenuItem file = new MenuItem("File"); file.AddEvents((int)Gdk.EventMask.AllEventsMask); file.Submenu = fileMenu; // FIXME: Hook up callbacks // FIXME: On windows (and Mac) there should be no delay // on the ability to close the menu when you've opened it. // Atm there is a delay after opening the menu and when // you can close it... MenuBar bar = new MenuBar(); bar.Append(file); return(bar); }
public abstract void DeSelect(CircuitEditor editor);
public virtual void DeSelect(CircuitEditor editor) { }
public override void GestureUpdate(CircuitEditor editor, Vector2d offset) { VisualPosition = StartPosition + editor.RoundDistToGrid(offset); editor.DrawingArea.QueueDraw(); }
public virtual void MouseMoved(CircuitEditor editor, Vector2d mousePos) { }
public override void DeSelect(CircuitEditor editor) { PlacingComponent = false; editor.DrawingArea.QueueDraw(); }
public abstract void GestureUpdate(CircuitEditor editor, Vector2d offset);
public WireTool( CircuitEditor circuitEditor, Gtk.Toolbar toolbar ) : base(Icon.Wire(), "Wire", circuitEditor, toolbar) { }
public abstract void Draw(CircuitEditor editor, Cairo.Context cr);
public ComponentTool(T exampleInstance, CircuitEditor circuitEditor) : base(Icon.AndGate(), exampleInstance.Name, circuitEditor) { BaseComponent = exampleInstance; }