From a2b53fde559830138c46d674112c5a1a1dcf1f3b Mon Sep 17 00:00:00 2001 From: "Josiah (Gaming32) Glosson" Date: Sun, 18 Jul 2021 13:09:44 -0500 Subject: [PATCH 01/40] Have draggable nodes (demo) --- shuffle_editor_test.py | 151 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 151 insertions(+) create mode 100644 shuffle_editor_test.py diff --git a/shuffle_editor_test.py b/shuffle_editor_test.py new file mode 100644 index 00000000..2b03642a --- /dev/null +++ b/shuffle_editor_test.py @@ -0,0 +1,151 @@ +from typing import Optional +import pygame +import pygame.display +import pygame.draw +import pygame.event +import pygame.font +import pygame.time +from pygame import * +from pygame.locals import * + + +class Editor: + nodes: list['Node'] + connections: list['Connection'] + selected: Optional['Node'] + + def __init__(self, shuffles: list[str]) -> None: + self.nodes = [Node('', self, -Node.WIDTH, 15)] + self.nodes.extend(Node(shuffle, self) for shuffle in shuffles) + self.connections = [] + self.selected = None + + def draw(self, surface: Surface): + for connection in self.connections: + connection.draw(surface) + for node in self.nodes: + node.draw(surface) + + def drag(self, rel: Vector2): + if self.selected is not None: + self.selected.drag(rel) + + def select(self, pos: Vector2): + for node in reversed(self.nodes): + if node.in_area(pos): + self.selected = node + return + self.selected = None + + def delete(self): + if self.selected is not None: + self.selected.delete() + + +class Node: + WIDTH = 250 + HEIGHT = 50 + + shuffle: str + x: int + y: int + editor: Editor + pre_connection: Optional['Connection'] + post_connection: Optional['Connection'] + + def __init__(self, shuffle: str, editor: Editor, x: int = 0, y: int = 0) -> None: + self.shuffle = shuffle + self.editor = editor + self.x = x + self.y = y + self.pre_connection = None + self.post_connection = None + + def draw(self, surface: Surface): + border = (128, 128, 255) if self.editor.selected is self else (0, 0, 0) + pygame.draw.circle(surface, border, (self.x, self.y + Node.HEIGHT / 2), 10) + pygame.draw.circle(surface, border, (self.x + Node.WIDTH, self.y + Node.HEIGHT / 2), 10) + pygame.draw.rect(surface, (255, 255, 255), (self.x, self.y, Node.WIDTH, Node.HEIGHT)) + pygame.draw.rect(surface, border, (self.x, self.y, Node.WIDTH, Node.HEIGHT), 2) + text_r = font.render(self.shuffle, True, (0, 0, 0)) + rect = text_r.get_rect() + surface.blit( + text_r, + rect.move(self.x, self.y) + .move(Node.WIDTH / 2, Node.HEIGHT / 2) + .move(-rect.width / 2, -rect.height / 2) + ) + self._hovered = False + + def drag(self, rel: Vector2): + self.x += rel.x + self.y += rel.y + + def in_area(self, pos: Vector2): + return Rect(self.x, self.y, Node.WIDTH, Node.HEIGHT).collidepoint(pos) + + def delete(self): + if self == self.editor.selected: + self.editor.selected = None + self.editor.nodes.remove(self) + if self.pre_connection is not None and self.post_connection is not None: + self.pre_connection.to = self.post_connection.to + if self.post_connection is not None and self.pre_connection is not None: + self.post_connection.from_ = self.pre_connection.from_ + + def __eq__(self, o: object) -> bool: + if isinstance(o, Node): + return ( + self.editor is o.editor + and self.shuffle == o.shuffle + and self.x == o.x + and self.y == o.y + and self.pre_connection is o.pre_connection + and self.post_connection is o.post_connection + ) + return False + + +class Connection: + from_: Optional[Node] + to: Optional[Node] + + def __init__(self, from_: Node = None, to: Node = None) -> None: + self.from_ = from_ + self.to = to + + def draw(self, surface: Surface): + pass + + +pygame.init() +screen = pygame.display.set_mode((1280, 720), RESIZABLE) +font = pygame.font.SysFont('ariel', 24) + +editor = Editor(['Linear', 'Randomly', 'Backwards', 'Slight Shuffle', 'No Shuffle']) + + +clock = pygame.time.Clock() +running = True +while running: + delta = clock.tick(60) / 1000 + for event in pygame.event.get(): + if event.type == QUIT: + running = False + elif event.type == MOUSEMOTION: + if event.buttons[0]: + editor.drag(Vector2(event.rel)) + elif event.type == MOUSEBUTTONDOWN: + if event.button == 1: + editor.select(Vector2(event.pos)) + elif event.type == KEYDOWN: + if event.key == K_DELETE: + editor.delete() + + screen.fill((128, 128, 128)) + + dims = screen.get_size() + + editor.draw(screen) + + pygame.display.update() From 4f0b1aad7229cc1406be85eec1b10daac9dcc2aa Mon Sep 17 00:00:00 2001 From: "Josiah (Gaming32) Glosson" Date: Sun, 18 Jul 2021 14:17:52 -0500 Subject: [PATCH 02/40] Finish demo editor editing (serialization still to come) --- shuffle_editor_test.py | 86 ++++++++++++++++++++++++++++++++++++------ 1 file changed, 74 insertions(+), 12 deletions(-) diff --git a/shuffle_editor_test.py b/shuffle_editor_test.py index 2b03642a..db27e732 100644 --- a/shuffle_editor_test.py +++ b/shuffle_editor_test.py @@ -1,4 +1,5 @@ -from typing import Optional +from typing import Optional, Union + import pygame import pygame.display import pygame.draw @@ -13,12 +14,16 @@ class Editor: nodes: list['Node'] connections: list['Connection'] selected: Optional['Node'] + dragging: Optional['Connection'] + drag_candidate: Optional['Node'] def __init__(self, shuffles: list[str]) -> None: self.nodes = [Node('', self, -Node.WIDTH, 15)] self.nodes.extend(Node(shuffle, self) for shuffle in shuffles) self.connections = [] self.selected = None + self.dragging = None + self.drag_candidate = None def draw(self, surface: Surface): for connection in self.connections: @@ -29,14 +34,41 @@ def draw(self, surface: Surface): def drag(self, rel: Vector2): if self.selected is not None: self.selected.drag(rel) + elif self.dragging is not None: + self.dragging.current_drag_pos += rel + pos = self.dragging.current_drag_pos + for node in reversed(self.nodes): + if node.in_area(pos): + self.drag_candidate = node + break + else: + self.drag_candidate = None def select(self, pos: Vector2): for node in reversed(self.nodes): if node.in_area(pos): self.selected = node return + elif node.in_start_drag(pos): + new_connection = Connection(node, pos) + self.connections.append(new_connection) + self.dragging = new_connection + self.selected = None + return self.selected = None + def end_connection(self): + if self.dragging is None: + return + if self.drag_candidate is not None: + self.dragging.finish_dragging(self.drag_candidate) + else: + self.connections.remove(self.dragging) + self.dragging = None + self.drag_candidate = None + self.dragging = None + self.drag_candidate = None + def delete(self): if self.selected is not None: self.selected.delete() @@ -62,11 +94,12 @@ def __init__(self, shuffle: str, editor: Editor, x: int = 0, y: int = 0) -> None self.post_connection = None def draw(self, surface: Surface): - border = (128, 128, 255) if self.editor.selected is self else (0, 0, 0) - pygame.draw.circle(surface, border, (self.x, self.y + Node.HEIGHT / 2), 10) - pygame.draw.circle(surface, border, (self.x + Node.WIDTH, self.y + Node.HEIGHT / 2), 10) + border_color = (128, 128, 255) if self.editor.selected is self else (0, 0, 0) + left_color = (128, 128, 255) if self is self.editor.drag_candidate else border_color + pygame.draw.circle(surface, left_color, (self.x, self.y + Node.HEIGHT / 2), 10) + pygame.draw.circle(surface, border_color, (self.x + Node.WIDTH, self.y + Node.HEIGHT / 2), 10) pygame.draw.rect(surface, (255, 255, 255), (self.x, self.y, Node.WIDTH, Node.HEIGHT)) - pygame.draw.rect(surface, border, (self.x, self.y, Node.WIDTH, Node.HEIGHT), 2) + pygame.draw.rect(surface, border_color, (self.x, self.y, Node.WIDTH, Node.HEIGHT), 2) text_r = font.render(self.shuffle, True, (0, 0, 0)) rect = text_r.get_rect() surface.blit( @@ -84,13 +117,16 @@ def drag(self, rel: Vector2): def in_area(self, pos: Vector2): return Rect(self.x, self.y, Node.WIDTH, Node.HEIGHT).collidepoint(pos) + def in_start_drag(self, pos: Vector2): + return Rect(self.x + Node.WIDTH, self.y + Node.HEIGHT / 2 - 10, 10, 20).collidepoint(pos) + def delete(self): if self == self.editor.selected: self.editor.selected = None self.editor.nodes.remove(self) - if self.pre_connection is not None and self.post_connection is not None: + if self.pre_connection is not None: self.pre_connection.to = self.post_connection.to - if self.post_connection is not None and self.pre_connection is not None: + if self.post_connection is not None: self.post_connection.from_ = self.pre_connection.from_ def __eq__(self, o: object) -> bool: @@ -105,17 +141,38 @@ def __eq__(self, o: object) -> bool: ) return False + def get_pos(self) -> Vector2: + return Vector2(self.x, self.y) + class Connection: - from_: Optional[Node] + from_: Node to: Optional[Node] + current_drag_pos: Vector2 - def __init__(self, from_: Node = None, to: Node = None) -> None: + def __init__(self, from_: Node, to: Union[Node, Vector2]) -> None: self.from_ = from_ - self.to = to + if isinstance(to, Node): + self.to = to + self.current_drag_pos = Vector2() + else: + self.to = None + self.current_drag_pos = to def draw(self, surface: Surface): - pass + from_pos = self.from_.get_pos() + (Node.WIDTH + 10, Node.HEIGHT / 2) + end_pos: Vector2 = Vector2(self.current_drag_pos) if self.to is None else (self.to.get_pos() + (0, Node.HEIGHT / 2)) + end_pos -= (10, 0) + mid_start = from_pos + (15, 0) + mid_end = end_pos - (15, 0) + pygame.draw.line(surface, (0, 0, 0), from_pos, mid_start, 5) + pygame.draw.line(surface, (0, 0, 0), mid_start, mid_end, 5) + pygame.draw.line(surface, (0, 0, 0), mid_end, end_pos, 5) + if self.to is None: + pygame.draw.circle(surface, (0, 0, 0), end_pos + (10, 0), 10) + + def finish_dragging(self, other: Node): + self.to = other pygame.init() @@ -125,6 +182,8 @@ def draw(self, surface: Surface): editor = Editor(['Linear', 'Randomly', 'Backwards', 'Slight Shuffle', 'No Shuffle']) +# editor.connections.append(Connection(editor.nodes[-1], Vector2())) + clock = pygame.time.Clock() running = True while running: @@ -138,13 +197,16 @@ def draw(self, surface: Surface): elif event.type == MOUSEBUTTONDOWN: if event.button == 1: editor.select(Vector2(event.pos)) + elif event.type == MOUSEBUTTONUP: + if event.button == 1: + editor.end_connection() elif event.type == KEYDOWN: if event.key == K_DELETE: editor.delete() screen.fill((128, 128, 128)) - dims = screen.get_size() + # editor.connections[-1].current_drag_pos.update(pygame.mouse.get_pos()) editor.draw(screen) From 647fd8e45623341ca0d6ffc414684b5f224ce744 Mon Sep 17 00:00:00 2001 From: "Josiah (Gaming32) Glosson" Date: Sun, 18 Jul 2021 16:52:58 -0500 Subject: [PATCH 03/40] Implement demo in Java --- shuffle_editor_test.py | 25 ++++-- src/frames/ShuffleEditor.java | 86 ++++++++++++++++++ src/prompts/ShufflePrompt.java | 71 +++++++++------ src/utils/ShuffleGraph.java | 111 ++++++++++++++++++++++++ src/utils/shuffle_utils/AWTUtils.java | 33 +++++++ src/utils/shuffle_utils/Connection.java | 66 ++++++++++++++ src/utils/shuffle_utils/Node.java | 90 +++++++++++++++++++ 7 files changed, 447 insertions(+), 35 deletions(-) create mode 100644 src/frames/ShuffleEditor.java create mode 100644 src/utils/ShuffleGraph.java create mode 100644 src/utils/shuffle_utils/AWTUtils.java create mode 100644 src/utils/shuffle_utils/Connection.java create mode 100644 src/utils/shuffle_utils/Node.java diff --git a/shuffle_editor_test.py b/shuffle_editor_test.py index db27e732..2b430ac8 100644 --- a/shuffle_editor_test.py +++ b/shuffle_editor_test.py @@ -35,8 +35,8 @@ def drag(self, rel: Vector2): if self.selected is not None: self.selected.drag(rel) elif self.dragging is not None: - self.dragging.current_drag_pos += rel pos = self.dragging.current_drag_pos + pos += rel for node in reversed(self.nodes): if node.in_area(pos): self.drag_candidate = node @@ -51,8 +51,14 @@ def select(self, pos: Vector2): return elif node.in_start_drag(pos): new_connection = Connection(node, pos) + removed = 0 + for (i, conn) in enumerate(self.connections.copy()): + if conn.from_ == node: + del self.connections[i - removed] + removed += 1 self.connections.append(new_connection) self.dragging = new_connection + node.post_connection = new_connection self.selected = None return self.selected = None @@ -64,8 +70,6 @@ def end_connection(self): self.dragging.finish_dragging(self.drag_candidate) else: self.connections.remove(self.dragging) - self.dragging = None - self.drag_candidate = None self.dragging = None self.drag_candidate = None @@ -94,7 +98,7 @@ def __init__(self, shuffle: str, editor: Editor, x: int = 0, y: int = 0) -> None self.post_connection = None def draw(self, surface: Surface): - border_color = (128, 128, 255) if self.editor.selected is self else (0, 0, 0) + border_color = (128, 128, 255) if self is self.editor.selected else (0, 0, 0) left_color = (128, 128, 255) if self is self.editor.drag_candidate else border_color pygame.draw.circle(surface, left_color, (self.x, self.y + Node.HEIGHT / 2), 10) pygame.draw.circle(surface, border_color, (self.x + Node.WIDTH, self.y + Node.HEIGHT / 2), 10) @@ -108,7 +112,6 @@ def draw(self, surface: Surface): .move(Node.WIDTH / 2, Node.HEIGHT / 2) .move(-rect.width / 2, -rect.height / 2) ) - self._hovered = False def drag(self, rel: Vector2): self.x += rel.x @@ -173,6 +176,14 @@ def draw(self, surface: Surface): def finish_dragging(self, other: Node): self.to = other + other.pre_connection = self + removed = 0 + for (i, conn) in enumerate(other.editor.connections.copy()): + if conn == self: + continue + if conn.to == other: + del other.editor.connections[i - removed] + removed += 1 pygame.init() @@ -182,8 +193,6 @@ def finish_dragging(self, other: Node): editor = Editor(['Linear', 'Randomly', 'Backwards', 'Slight Shuffle', 'No Shuffle']) -# editor.connections.append(Connection(editor.nodes[-1], Vector2())) - clock = pygame.time.Clock() running = True while running: @@ -206,8 +215,6 @@ def finish_dragging(self, other: Node): screen.fill((128, 128, 128)) - # editor.connections[-1].current_drag_pos.update(pygame.mouse.get_pos()) - editor.draw(screen) pygame.display.update() diff --git a/src/frames/ShuffleEditor.java b/src/frames/ShuffleEditor.java new file mode 100644 index 00000000..4def27f4 --- /dev/null +++ b/src/frames/ShuffleEditor.java @@ -0,0 +1,86 @@ +package frames; + +import java.awt.Color; +import java.awt.Font; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.RenderingHints; +import java.awt.Point; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.event.KeyEvent; +import java.awt.event.KeyListener; + +import javax.swing.JPanel; +import javax.swing.SwingUtilities; + +import utils.ShuffleGraph; +import utils.Shuffles; + +public class ShuffleEditor extends JPanel implements KeyListener { + int prevX, prevY; + ShuffleGraph graph; + + public ShuffleEditor() { + this.graph = new ShuffleGraph(new Shuffles[] {Shuffles.RANDOM, Shuffles.REVERSE, Shuffles.ALMOST, Shuffles.ALREADY}); + MouseHandler handler = new MouseHandler(); + addMouseListener(handler); + addMouseMotionListener(handler); + addKeyListener(this); + } + + @Override + protected void paintComponent(Graphics g) { + Graphics2D g2d = (Graphics2D)g; + g.setFont(new Font("ariel", Font.PLAIN, 24)); + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + g.setColor(new Color(128, 128, 128)); + g.fillRect(0, 0, getWidth(), getHeight()); + graph.draw(g2d); + } + + @Override + public void keyTyped(KeyEvent e) {} + + @Override + public void keyPressed(KeyEvent e) { + if (e.getKeyCode() == KeyEvent.VK_DELETE) { + graph.deleteNode(); + repaint(); + } + } + + @Override + public void keyReleased(KeyEvent e) {} + + protected class MouseHandler extends MouseAdapter { + @Override + public void mousePressed(MouseEvent e) { + requestFocus(); // Java doesn't handle this for us? + if (SwingUtilities.isLeftMouseButton(e)) { + graph.select(e.getPoint()); + prevX = e.getX(); + prevY = e.getY(); + repaint(); + } + } + + @Override + public void mouseReleased(MouseEvent e) { + if (SwingUtilities.isLeftMouseButton(e)) { + graph.endConnection(); + repaint(); + } + } + + @Override + public void mouseDragged(MouseEvent e) { + if (SwingUtilities.isLeftMouseButton(e)) { + graph.drag(new Point(e.getX() - prevX, e.getY() - prevY)); + prevX = e.getX(); + prevY = e.getY(); + repaint(); + } + } + } +} diff --git a/src/prompts/ShufflePrompt.java b/src/prompts/ShufflePrompt.java index bb6e013b..d726ecd3 100644 --- a/src/prompts/ShufflePrompt.java +++ b/src/prompts/ShufflePrompt.java @@ -8,6 +8,7 @@ import javax.swing.JOptionPane; import frames.AppFrame; +import frames.ShuffleEditor; import frames.UtilFrame; import main.ArrayManager; import panes.JErrorPane; @@ -106,6 +107,7 @@ public void reposition() { // //GEN-BEGIN:initComponents private void initComponents() { + this.shuffleEditor1 = new ShuffleEditor(); this.jLabel1 = new javax.swing.JLabel(); this.jScrollPane1 = new javax.swing.JScrollPane(); this.jList1 = new javax.swing.JList(); @@ -154,41 +156,57 @@ public void valueChanged(javax.swing.event.ListSelectionEvent evt) { .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER) .addGroup(layout.createSequentialGroup() .addGap(20, 20, 20) - .addComponent(this.jLabel1) - .addGap(5, 5, 5)) - .addGroup(layout.createSequentialGroup() - .addComponent(this.jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 175, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addComponent(this.shuffleEditor1, javax.swing.GroupLayout.PREFERRED_SIZE, 700, javax.swing.GroupLayout.PREFERRED_SIZE)) .addGap(20, 20, 20)) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) - .addGap(475, 475, 475) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER) - .addGroup(layout.createSequentialGroup() - .addGap(20, 20, 20) - .addComponent(this.jLabel2) - .addGap(5, 5, 5)) - .addGroup(layout.createSequentialGroup() - .addComponent(this.jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, 175, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addGap(20, 20, 20))) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() .addContainerGap() - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(this.jLabel1)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, true) - .addComponent(this.jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 175, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addGap(20, 20, 20)) - .addGroup(layout.createSequentialGroup() - .addContainerGap() - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(this.jLabel2)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, true) - .addComponent(this.jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, 175, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addComponent(this.shuffleEditor1, javax.swing.GroupLayout.PREFERRED_SIZE, 450, javax.swing.GroupLayout.PREFERRED_SIZE)) .addGap(20, 20, 20)) ); + // layout.setHorizontalGroup( + // layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + // .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER) + // .addGroup(layout.createSequentialGroup() + // .addGap(20, 20, 20) + // .addComponent(this.jLabel1) + // .addGap(5, 5, 5)) + // .addGroup(layout.createSequentialGroup() + // .addComponent(this.jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 175, javax.swing.GroupLayout.PREFERRED_SIZE)) + // .addGap(20, 20, 20)) + // .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) + // .addGap(475, 475, 475) + // .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER) + // .addGroup(layout.createSequentialGroup() + // .addGap(20, 20, 20) + // .addComponent(this.jLabel2) + // .addGap(5, 5, 5)) + // .addGroup(layout.createSequentialGroup() + // .addComponent(this.jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, 175, javax.swing.GroupLayout.PREFERRED_SIZE)) + // .addGap(20, 20, 20))) + // ); + // layout.setVerticalGroup( + // layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + // .addGroup(layout.createSequentialGroup() + // .addContainerGap() + // .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + // .addComponent(this.jLabel1)) + // .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + // .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, true) + // .addComponent(this.jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 175, javax.swing.GroupLayout.PREFERRED_SIZE)) + // .addGap(20, 20, 20)) + // .addGroup(layout.createSequentialGroup() + // .addContainerGap() + // .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + // .addComponent(this.jLabel2)) + // .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + // .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, true) + // .addComponent(this.jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, 175, javax.swing.GroupLayout.PREFERRED_SIZE)) + // .addGap(20, 20, 20)) + // ); pack(); }// //GEN-END:initComponents @@ -214,6 +232,7 @@ private void jList2ValueChanged(javax.swing.event.ListSelectionEvent evt) throws }//GEN-LAST:event_jList1ValueChanged // Variables declaration - do not modify//GEN-BEGIN:variables + private frames.ShuffleEditor shuffleEditor1; private javax.swing.JLabel jLabel1; @SuppressWarnings("rawtypes") private javax.swing.JList jList1; diff --git a/src/utils/ShuffleGraph.java b/src/utils/ShuffleGraph.java new file mode 100644 index 00000000..fb220923 --- /dev/null +++ b/src/utils/ShuffleGraph.java @@ -0,0 +1,111 @@ +package utils; + +import java.awt.Graphics2D; +import java.awt.Point; +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +import utils.shuffle_utils.Connection; +import utils.shuffle_utils.Node; + +public class ShuffleGraph { + public List nodes; + public List connections; + public Node selected; + public Connection dragging; + public Node dragCandidate; + + public ShuffleGraph() { + this(new Shuffles[] {}); + } + + public ShuffleGraph(Shuffles[] shuffles) { + this.nodes = new ArrayList<>(); + this.nodes.add(new Node(null, this, -Node.WIDTH, 15)); + for (Shuffles shuffle : shuffles) { + this.nodes.add(new Node(shuffle, this)); + } + this.connections = new ArrayList<>(); + this.selected = null; + this.dragging = null; + this.dragCandidate = null; + } + + public void draw(Graphics2D g) { + for (Connection connection : this.connections) { + connection.draw(g); + } + for (Node node : this.nodes) { + node.draw(g); + } + } + + public void drag(Point rel) { + if (this.selected != null) { + this.selected.drag(rel); + } else if (this.dragging != null) { + Point pos = this.dragging.currentDragPos; + pos.translate(rel.x, rel.y); + boolean foundCandidate = false; + ListIterator it = this.nodes.listIterator(this.nodes.size()); + while (it.hasPrevious()) { + Node node = it.previous(); + if (node.inArea(pos)) { + this.dragCandidate = node; + foundCandidate = true; + break; + } + } + if (!foundCandidate) { + this.dragCandidate = null; + } + } + } + + public void select(Point pos) { + ListIterator it = this.nodes.listIterator(this.nodes.size()); + while (it.hasPrevious()) { + Node node = it.previous(); + if (node.inArea(pos)) { + this.selected = node; + return; + } else if (node.inStartDrag(pos)) { + Connection newConnection = new Connection(node, pos); + int removed = 0; + for (int i = 0; i < this.connections.size(); i++) { + Connection conn = this.connections.get(i - removed); + if (conn.from == node) { + this.connections.remove(i - removed); + removed++; + } + } + this.connections.add(newConnection); + this.dragging = newConnection; + node.postConnection = newConnection; + this.selected = null; + return; + } + } + this.selected = null; + } + + public void endConnection() { + if (this.dragging == null) { + return; + } + if (this.dragCandidate != null) { + this.dragging.finishDragging(this.dragCandidate); + } else { + this.connections.remove(this.dragging); + } + this.dragging = null; + this.dragCandidate = null; + } + + public void deleteNode() { + if (this.selected != null) { + this.selected.delete(); + } + } +} diff --git a/src/utils/shuffle_utils/AWTUtils.java b/src/utils/shuffle_utils/AWTUtils.java new file mode 100644 index 00000000..d94cff2f --- /dev/null +++ b/src/utils/shuffle_utils/AWTUtils.java @@ -0,0 +1,33 @@ +package utils.shuffle_utils; + +import java.awt.BasicStroke; +import java.awt.Graphics2D; +import java.awt.Stroke; +import java.awt.font.FontRenderContext; +import java.awt.font.GlyphVector; +import java.awt.geom.Rectangle2D; + +public class AWTUtils { + public static void drawCircle(Graphics2D g, int x, int y, int r) { + x = x - r; + y = y - r; + g.fillOval(x, y, r * 2, r * 2); + } + + public static void drawBorderRect(Graphics2D g, int x, int y, int width, int height, int thickness) { + Stroke oldStroke = g.getStroke(); + g.setStroke(new BasicStroke(thickness)); + g.drawRect(x, y, width, height); + g.setStroke(oldStroke); + } + + public static Rectangle2D getStringBounds(Graphics2D g, String str, float x, float y) { + FontRenderContext frc = g.getFontRenderContext(); + GlyphVector gv = g.getFont().createGlyphVector(frc, str); + return gv.getPixelBounds(null, x, y); + } + + public static Rectangle2D getStringBounds(Graphics2D g, String str) { + return getStringBounds(g, str, 0, 0); + } +} diff --git a/src/utils/shuffle_utils/Connection.java b/src/utils/shuffle_utils/Connection.java new file mode 100644 index 00000000..98cc795b --- /dev/null +++ b/src/utils/shuffle_utils/Connection.java @@ -0,0 +1,66 @@ +package utils.shuffle_utils; + +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.Stroke; +import java.awt.Point; +import java.util.List; + +public class Connection { + public Node from, to; + public Point currentDragPos; + + public Connection(Node from, Node to) { + this.from = from; + this.to = to; + this.currentDragPos = new Point(); + } + + public Connection(Node from, Point to) { + this.from = from; + this.to = null; + this.currentDragPos = to; + } + + public void draw(Graphics2D g) { + Point fromPos = this.from.getPos(); + fromPos = new Point(fromPos.x + Node.WIDTH + 10, fromPos.y + Node.HEIGHT / 2); + Point endPos; + if (this.to == null) { + endPos = new Point(this.currentDragPos.x - 10, this.currentDragPos.y); + } else { + Point toPos = this.to.getPos(); + endPos = new Point(toPos.x, toPos.y + Node.HEIGHT / 2); + } + Point midStart = new Point(fromPos.x + 15, fromPos.y); + Point midEnd = new Point(endPos.x - 15, endPos.y); + Stroke oldStroke = g.getStroke(); + g.setStroke(new BasicStroke(5)); + g.setColor(Color.BLACK); + g.drawLine(fromPos.x, fromPos.y, midStart.x, midStart.y); + g.drawLine(midStart.x, midStart.y, midEnd.x, midEnd.y); + g.drawLine(midEnd.x, midEnd.y, endPos.x, endPos.y); + g.setStroke(oldStroke); + if (this.to == null) { + AWTUtils.drawCircle(g, endPos.x + 10, endPos.y, 10); + } + } + + public void finishDragging(Node other) { + this.to = other; + other.preConnection = this; + int removed = 0; + List connections = other.graph.connections; + for (int i = 0; i < connections.size(); i++) { + Connection conn = connections.get(i - removed); + if (conn == this) { + continue; + } + if (conn.to == other) { + connections.remove(i - removed); + removed++; + } + } + } +} diff --git a/src/utils/shuffle_utils/Node.java b/src/utils/shuffle_utils/Node.java new file mode 100644 index 00000000..46fe86de --- /dev/null +++ b/src/utils/shuffle_utils/Node.java @@ -0,0 +1,90 @@ +package utils.shuffle_utils; + +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.Point; +import java.awt.geom.Rectangle2D; + +import utils.ShuffleGraph; +import utils.Shuffles; + +public class Node { + public static final int WIDTH = 250; + public static final int HEIGHT = 50; + + public Shuffles shuffle; + public int x, y; + public ShuffleGraph graph; + public Connection preConnection, postConnection; + + public Node(Shuffles shuffle, ShuffleGraph graph, int x, int y) { + this.shuffle = shuffle; + this.graph = graph; + this.x = x; + this.y = y; + this.preConnection = null; + this.postConnection = null; + } + + public Node(Shuffles shuffle, ShuffleGraph graph) { + this(shuffle, graph, 0, 0); + } + + protected String getShuffleName() { + if (this.shuffle == null) { + return ""; + } + return this.shuffle.getName(); + } + + public void draw(Graphics2D g) { + Color borderColor = this.graph.selected == this ? new Color(128, 128, 255) : new Color(0, 0, 0); + Color leftColor = this.graph.dragCandidate == this ? new Color(128, 128, 255) : borderColor; + g.setColor(leftColor); + AWTUtils.drawCircle(g, x, y + HEIGHT / 2, 10); + g.setColor(borderColor); + AWTUtils.drawCircle(g, x + WIDTH, y + HEIGHT / 2, 10); + g.setColor(Color.WHITE); + g.fillRect(x, y, WIDTH, HEIGHT); + g.setColor(borderColor); + AWTUtils.drawBorderRect(g, x, y, WIDTH, HEIGHT, 2); + g.setColor(Color.BLACK); + String text = getShuffleName(); + Rectangle2D rect = AWTUtils.getStringBounds(g, text); + g.drawString( + text, + (int)(x + WIDTH / 2 - rect.getWidth() / 2), + (int)(y + HEIGHT / 2 + rect.getHeight() / 2) + ); + } + + public void drag(Point rel) { + this.x += rel.getX(); + this.y += rel.getY(); + } + + public boolean inArea(Point pos) { + return (new Rectangle2D.Double(x, y, WIDTH, HEIGHT)).contains(pos); + } + + public boolean inStartDrag(Point pos) { + return (new Rectangle2D.Double(x + WIDTH, y + HEIGHT / 2 - 10, 10, 20)).contains(pos); + } + + public void delete() { + if (this == this.graph.selected) { + this.graph.selected = null; + } + this.graph.nodes.remove(this); + if (this.preConnection != null) { + this.preConnection.to = this.postConnection.to; + } + if (this.postConnection != null) { + this.postConnection.from = this.preConnection.from; + } + } + + public Point getPos() { + return new Point(this.x, this.y); + } +} From 43b263eac0633dced8ac75f1122bb0f402ae23dd Mon Sep 17 00:00:00 2001 From: "Josiah (Gaming32) Glosson" Date: Thu, 22 Jul 2021 18:37:23 -0500 Subject: [PATCH 04/40] Implement the Collection interface, fix bugs, and add support for distributions --- src/frames/ShuffleEditor.java | 10 +- src/utils/Distributions.java | 1 - src/utils/ShuffleGraph.java | 220 ++++++++++++++++++++++- src/utils/shuffle_utils/Node.java | 50 +++++- src/utils/shuffle_utils/ShuffleInfo.java | 95 ++++++++++ 5 files changed, 362 insertions(+), 14 deletions(-) create mode 100644 src/utils/shuffle_utils/ShuffleInfo.java diff --git a/src/frames/ShuffleEditor.java b/src/frames/ShuffleEditor.java index 4def27f4..9b829fa1 100644 --- a/src/frames/ShuffleEditor.java +++ b/src/frames/ShuffleEditor.java @@ -10,19 +10,27 @@ import java.awt.event.MouseEvent; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; +import java.util.Arrays; import javax.swing.JPanel; import javax.swing.SwingUtilities; import utils.ShuffleGraph; import utils.Shuffles; +import utils.shuffle_utils.ShuffleInfo; public class ShuffleEditor extends JPanel implements KeyListener { int prevX, prevY; ShuffleGraph graph; public ShuffleEditor() { - this.graph = new ShuffleGraph(new Shuffles[] {Shuffles.RANDOM, Shuffles.REVERSE, Shuffles.ALMOST, Shuffles.ALREADY}); + this.graph = new ShuffleGraph( + ShuffleInfo.fromShuffleIterable( + Arrays.stream( + new Shuffles[] {Shuffles.RANDOM, Shuffles.REVERSE, Shuffles.ALMOST, Shuffles.ALREADY} + )::iterator + ) + ); MouseHandler handler = new MouseHandler(); addMouseListener(handler); addMouseMotionListener(handler); diff --git a/src/utils/Distributions.java b/src/utils/Distributions.java index 78c15aca..dd26c35b 100644 --- a/src/utils/Distributions.java +++ b/src/utils/Distributions.java @@ -2,7 +2,6 @@ import java.io.File; import java.io.FileNotFoundException; -import java.util.Arrays; import java.util.Random; import java.util.Scanner; diff --git a/src/utils/ShuffleGraph.java b/src/utils/ShuffleGraph.java index fb220923..db98ed38 100644 --- a/src/utils/ShuffleGraph.java +++ b/src/utils/ShuffleGraph.java @@ -3,13 +3,17 @@ import java.awt.Graphics2D; import java.awt.Point; import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; import java.util.List; import java.util.ListIterator; +import java.util.NoSuchElementException; import utils.shuffle_utils.Connection; import utils.shuffle_utils.Node; +import utils.shuffle_utils.ShuffleInfo; -public class ShuffleGraph { +public class ShuffleGraph implements Collection { public List nodes; public List connections; public Node selected; @@ -17,13 +21,13 @@ public class ShuffleGraph { public Node dragCandidate; public ShuffleGraph() { - this(new Shuffles[] {}); + this(new ShuffleInfo[0]); } - public ShuffleGraph(Shuffles[] shuffles) { + public ShuffleGraph(ShuffleInfo[] shuffles) { this.nodes = new ArrayList<>(); this.nodes.add(new Node(null, this, -Node.WIDTH, 15)); - for (Shuffles shuffle : shuffles) { + for (ShuffleInfo shuffle : shuffles) { this.nodes.add(new Node(shuffle, this)); } this.connections = new ArrayList<>(); @@ -32,6 +36,22 @@ public ShuffleGraph(Shuffles[] shuffles) { this.dragCandidate = null; } + public static ShuffleGraph single(ShuffleInfo shuffle) { + return new ShuffleGraph(new ShuffleInfo[] {shuffle}); + } + + public static ShuffleGraph single(Shuffles shuffle) { + return new ShuffleGraph(new ShuffleInfo[] {new ShuffleInfo(shuffle)}); + } + + public static ShuffleGraph single(Distributions distribution) { + return new ShuffleGraph(new ShuffleInfo[] {new ShuffleInfo(distribution)}); + } + + public void addDisconnected(ShuffleInfo shuffle) { + this.nodes.add(new Node(shuffle, this)); + } + public void draw(Graphics2D g) { for (Connection connection : this.connections) { connection.draw(g); @@ -108,4 +128,196 @@ public void deleteNode() { this.selected.delete(); } } + + + // Collection code + public int size() { + int size = 0; + Node node = this.nodes.get(0); + while (node != null) { + size++; + Connection connect = node.postConnection; + if (connect == null) { + break; + } + node = connect.to; + } + return size - 1; + } + + public void clear() { + this.nodes.subList(1, this.nodes.size()).clear(); + this.nodes.get(0).postConnection = null; + } + + public Node findLast() { + Node node = this.nodes.get(0); + while (node != null) { + Connection connect = node.postConnection; + if (connect == null) { + break; + } + node = connect.to; + } + return node; + } + + public boolean add(ShuffleInfo shuffle) { + add(shuffle, findLast()); + return true; + } + + public boolean addAll(Collection c) { + Node after = findLast(); + for (ShuffleInfo shuffle : c) { + after = add(shuffle, after); + } + return true; + } + + Node add(ShuffleInfo shuffle, Node after) { + Node newNode = new Node(shuffle, this, after.x + Node.WIDTH + 15, after.y); + if (after.postConnection == null) { + after.postConnection = new Connection(after, newNode); + } else { + after.postConnection.to = newNode; + } + return newNode; + } + + Node find(Object o) { + if (o == null) { + return null; + } + Node node = this.nodes.get(0); + while (node != null) { + Connection connect = node.postConnection; + if (connect == null) { + break; + } + node = connect.to; + if (node.equals(o)) { + return node; + } + } + return null; + } + + public boolean contains(Object o) { + return find(o) != null; + } + + public boolean containsAll(Collection c) { + for (Object o : c) { + if (!contains(o)) { + return false; + } + } + return true; + } + + public boolean isEmpty() { + return iterator().hasNext(); + } + + public boolean remove(Object o) { + Node found = find(o); + if (found == null) { + return false; + } + found.delete(); + return true; + } + + public boolean removeAll(Collection c) { + boolean affected = false; + for (Object o : c) { + affected = remove(o) || affected; + } + return affected; + } + + public boolean retainAll(Collection c) { + throw new UnsupportedOperationException(); + } + + public Object[] toArray() { + List result = new ArrayList<>(); + for (ShuffleInfo shuffle : this) { + result.add(shuffle); + } + return result.toArray(); + } + + @SuppressWarnings("unchecked") + public T[] toArray(T[] a) { + Class type = a.getClass().getComponentType(); + if (type == ShuffleInfo.class || type == Object.class) { + int mySize = size(); + if (mySize > a.length) { + return (T[])toArray(); + } + ShuffleInfo[] result = (ShuffleInfo[])a; + int i = 0; + Node node = this.nodes.get(0); + while (node != null) { + Connection connect = node.postConnection; + if (connect == null) { + break; + } + node = connect.to; + result[i++] = node.getValue(); + } + if (i < a.length - 1) { + a[i] = null; + } + return a; + } else if (type == Node.class) { + return this.nodes.toArray(a); + } else { + throw new ArrayStoreException(); + } + } + + public Iterator iterator() { + return new GraphIterator(this); + } + + protected class GraphIterator implements Iterator { + Node currentNode, nextNode; + + GraphIterator(ShuffleGraph graph) { + this.currentNode = graph.nodes.get(0); + this.nextNode = findNext(); + } + + Node findNext() { + Connection connect = this.currentNode.postConnection; + if (connect != null) { + Node next = connect.to; + if (next != null) { + return next; + } + } + return null; + } + + public boolean hasNext() { + return this.nextNode != null; + } + + public ShuffleInfo next() { + if (this.nextNode == null) { + throw new NoSuchElementException(); + } + this.currentNode = this.nextNode; + this.nextNode = findNext(); + return this.currentNode.getValue(); + } + + public void remove() { + this.nextNode.delete(); + this.nextNode = findNext(); + } + } } diff --git a/src/utils/shuffle_utils/Node.java b/src/utils/shuffle_utils/Node.java index 46fe86de..4affef5a 100644 --- a/src/utils/shuffle_utils/Node.java +++ b/src/utils/shuffle_utils/Node.java @@ -6,18 +6,17 @@ import java.awt.geom.Rectangle2D; import utils.ShuffleGraph; -import utils.Shuffles; public class Node { public static final int WIDTH = 250; public static final int HEIGHT = 50; - public Shuffles shuffle; + public ShuffleInfo shuffle; public int x, y; public ShuffleGraph graph; public Connection preConnection, postConnection; - public Node(Shuffles shuffle, ShuffleGraph graph, int x, int y) { + public Node(ShuffleInfo shuffle, ShuffleGraph graph, int x, int y) { this.shuffle = shuffle; this.graph = graph; this.x = x; @@ -26,10 +25,27 @@ public Node(Shuffles shuffle, ShuffleGraph graph, int x, int y) { this.postConnection = null; } - public Node(Shuffles shuffle, ShuffleGraph graph) { + public Node(ShuffleInfo shuffle, ShuffleGraph graph) { this(shuffle, graph, 0, 0); } + public boolean equals(Object o) { + if (o == null) { + return false; + } + if (o instanceof Node) { + Node other = (Node)o; + return this.x == other.x + && this.y == other.y + && this.graph == other.graph + && this.shuffle.equals(other.shuffle); + } else if (o instanceof ShuffleInfo) { + return this.shuffle.equals(o); + } else { + return false; + } + } + protected String getShuffleName() { if (this.shuffle == null) { return ""; @@ -64,11 +80,11 @@ public void drag(Point rel) { } public boolean inArea(Point pos) { - return (new Rectangle2D.Double(x, y, WIDTH, HEIGHT)).contains(pos); + return (new Rectangle2D.Double(x - 25, y, WIDTH + 15, HEIGHT)).contains(pos); } public boolean inStartDrag(Point pos) { - return (new Rectangle2D.Double(x + WIDTH, y + HEIGHT / 2 - 10, 10, 20)).contains(pos); + return (new Rectangle2D.Double(x + WIDTH - 15, y + HEIGHT / 2 - 10, 30, 20)).contains(pos); } public void delete() { @@ -77,14 +93,32 @@ public void delete() { } this.graph.nodes.remove(this); if (this.preConnection != null) { - this.preConnection.to = this.postConnection.to; + if (this.postConnection == null) { + this.graph.connections.remove(this.preConnection); + if (this.preConnection.from != null) { + this.preConnection.from.postConnection = null; + } + } else { + this.preConnection.to = this.postConnection.to; + } } if (this.postConnection != null) { - this.postConnection.from = this.preConnection.from; + if (this.preConnection == null) { + this.graph.connections.remove(this.postConnection); + if (this.postConnection.to != null) { + this.postConnection.to.preConnection = null; + } + } else { + this.postConnection.from = this.preConnection.from; + } } } public Point getPos() { return new Point(this.x, this.y); } + + public ShuffleInfo getValue() { + return this.shuffle; + } } diff --git a/src/utils/shuffle_utils/ShuffleInfo.java b/src/utils/shuffle_utils/ShuffleInfo.java new file mode 100644 index 00000000..5ef55d17 --- /dev/null +++ b/src/utils/shuffle_utils/ShuffleInfo.java @@ -0,0 +1,95 @@ +package utils.shuffle_utils; + +import java.util.ArrayList; +import java.util.List; + +import main.ArrayVisualizer; +import utils.Delays; +import utils.Distributions; +import utils.Highlights; +import utils.Shuffles; +import utils.Writes; + +final public class ShuffleInfo { + final boolean isDistribution; + final Distributions distribution; + final Shuffles shuffle; + + public ShuffleInfo(Distributions distribution) { + this.isDistribution = true; + this.distribution = distribution; + this.shuffle = null; + } + + public ShuffleInfo(Shuffles shuffle) { + this.isDistribution = false; + this.distribution = null; + this.shuffle = shuffle; + } + + public static ShuffleInfo[] fromDistributionIterable(Iterable iterable) { + List result = new ArrayList<>(); + iterable.forEach(dist -> result.add(new ShuffleInfo(dist))); + return result.toArray(new ShuffleInfo[0]); + } + + public static ShuffleInfo[] fromShuffleIterable(Iterable iterable) { + List result = new ArrayList<>(); + iterable.forEach(shuff -> result.add(new ShuffleInfo(shuff))); + return result.toArray(new ShuffleInfo[0]); + } + + public boolean isDistribution() { + return this.isDistribution; + } + + public Distributions getDistribution() { + return this.distribution; + } + + public Shuffles getShuffle() { + return this.shuffle; + } + + public boolean equals(Object o) { + if (o == null || !(o instanceof ShuffleInfo)) { + return false; + } + ShuffleInfo other = (ShuffleInfo)o; + if (this.isDistribution != other.isDistribution) { + return false; + } + if (isDistribution) { + return this.distribution == other.distribution; + } else { + return this.shuffle == other.shuffle; + } + } + + public String getName() { + if (this.isDistribution) { + return this.distribution.getName(); + } + return this.shuffle.getName(); + } + + public void shuffle(int[] array, ArrayVisualizer arrayVisualizer) { + if (this.isDistribution) { + Writes Writes = arrayVisualizer.getWrites(); + int currentLen = arrayVisualizer.getCurrentLength(); + double sleep = arrayVisualizer.shuffleEnabled() ? 1 : 0; + int[] copy = new int[currentLen]; + int[] tmp = new int[currentLen]; + Writes.arraycopy(array, 0, copy, 0, currentLen, sleep, true, true); + this.distribution.initializeArray(tmp, arrayVisualizer); + for (int i = 0; i < currentLen; i++) { + Writes.write(array, i, copy[tmp[i]], sleep, true, false); + } + } else { + Delays Delays = arrayVisualizer.getDelays(); + Highlights Highlights = arrayVisualizer.getHighlights(); + Writes Writes = arrayVisualizer.getWrites(); + this.shuffle.shuffleArray(array, arrayVisualizer, Delays, Highlights, Writes); + } + } +} From 712a1b6d6c26789a0697ba59174217ef74260aab Mon Sep 17 00:00:00 2001 From: "Josiah (Gaming32) Glosson" Date: Thu, 22 Jul 2021 19:36:31 -0500 Subject: [PATCH 05/40] Make it actually work --- src/frames/ShuffleEditor.java | 18 +++---- src/main/ArrayManager.java | 52 ++++++++++--------- src/prompts/ShufflePrompt.java | 5 +- src/threads/RunExchangeSorts.java | 4 +- src/threads/RunHybridSorts.java | 6 +-- src/threads/RunInsertionSorts.java | 4 +- src/threads/RunQuickSorts.java | 2 +- src/utils/ShuffleGraph.java | 28 ++++++++-- .../{shuffle_utils => }/ShuffleInfo.java | 32 ++++++------ src/utils/shuffle_utils/Node.java | 1 + 10 files changed, 89 insertions(+), 63 deletions(-) rename src/utils/{shuffle_utils => }/ShuffleInfo.java (79%) diff --git a/src/frames/ShuffleEditor.java b/src/frames/ShuffleEditor.java index 9b829fa1..cb021e41 100644 --- a/src/frames/ShuffleEditor.java +++ b/src/frames/ShuffleEditor.java @@ -16,21 +16,21 @@ import javax.swing.SwingUtilities; import utils.ShuffleGraph; +import utils.ShuffleInfo; import utils.Shuffles; -import utils.shuffle_utils.ShuffleInfo; public class ShuffleEditor extends JPanel implements KeyListener { int prevX, prevY; - ShuffleGraph graph; + public ShuffleGraph graph; public ShuffleEditor() { - this.graph = new ShuffleGraph( - ShuffleInfo.fromShuffleIterable( - Arrays.stream( - new Shuffles[] {Shuffles.RANDOM, Shuffles.REVERSE, Shuffles.ALMOST, Shuffles.ALREADY} - )::iterator - ) - ); + // this.graph = new ShuffleGraph( + // ShuffleInfo.fromShuffleIterable( + // Arrays.stream( + // new Shuffles[] {Shuffles.RANDOM, Shuffles.REVERSE, Shuffles.ALMOST, Shuffles.ALREADY} + // )::iterator + // ) + // ); MouseHandler handler = new MouseHandler(); addMouseListener(handler); addMouseMotionListener(handler); diff --git a/src/main/ArrayManager.java b/src/main/ArrayManager.java index f0107d54..8440e0ab 100644 --- a/src/main/ArrayManager.java +++ b/src/main/ArrayManager.java @@ -1,17 +1,14 @@ package main; import java.util.Arrays; -import java.util.Comparator; -import java.util.Hashtable; -import java.util.Random; -import java.util.function.IntConsumer; import panes.JErrorPane; import utils.Delays; import utils.Highlights; +import utils.ShuffleGraph; +import utils.ShuffleInfo; import utils.Shuffles; import utils.Distributions; -import utils.Statistics; import utils.Writes; /* @@ -54,17 +51,17 @@ final public class ArrayManager { private ArrayVisualizer ArrayVisualizer; private Delays Delays; private Highlights Highlights; - private Shuffles Shuffles; - private Distributions Distributions; + private ShuffleGraph shuffle; + private Distributions distribution; private Writes Writes; public ArrayManager(ArrayVisualizer arrayVisualizer) { this.ArrayVisualizer = arrayVisualizer; - this.Shuffles = utils.Shuffles.RANDOM; - this.Distributions = utils.Distributions.LINEAR; - this.shuffleTypes = utils.Shuffles.values(); - this.distributionTypes = utils.Distributions.values(); + this.shuffle = ShuffleGraph.single(Shuffles.RANDOM); + this.distribution = Distributions.LINEAR; + this.shuffleTypes = Shuffles.values(); + this.distributionTypes = Distributions.values(); hadDistributionAllocationError = false; @@ -108,7 +105,7 @@ public void initializeArray(int[] array) { hadDistributionAllocationError = true; temp = array; } - Distributions.initializeArray(temp, this.ArrayVisualizer); + distribution.initializeArray(temp, this.ArrayVisualizer); double uniqueFactor = (double)currentLen/ArrayVisualizer.getUniqueItems(); for(int i = 0; i < currentLen; i++) @@ -124,11 +121,14 @@ public String[] getShuffleIDs() { public Shuffles[] getShuffles() { return this.shuffleTypes; } - public Shuffles getShuffle() { - return this.Shuffles; + public ShuffleGraph getShuffle() { + return this.shuffle; } - public void setShuffle(Shuffles choice) { - this.Shuffles = choice; + public void setShuffle(ShuffleGraph graph) { + this.shuffle = graph; + } + public void setShuffleSingle(Shuffles shuffle) { + this.setShuffle(ShuffleGraph.single(shuffle)); } public String[] getDistributionIDs() { @@ -138,15 +138,19 @@ public Distributions[] getDistributions() { return this.distributionTypes; } public Distributions getDistribution() { - return this.Distributions; + return this.distribution; } public void setDistribution(Distributions choice) { - this.Distributions = choice; - this.Distributions.selectDistribution(ArrayVisualizer.getArray(), ArrayVisualizer); + this.distribution = choice; + this.distribution.selectDistribution(ArrayVisualizer.getArray(), ArrayVisualizer); if (!ArrayVisualizer.isActive()) this.initializeArray(ArrayVisualizer.getArray()); } + public boolean containsShuffle(Shuffles shuffle) { + return this.shuffle.contains(new ShuffleInfo(shuffle)); + } + public void shuffleArray(int[] array, int currentLen, ArrayVisualizer ArrayVisualizer) { this.initializeArray(array); @@ -160,11 +164,11 @@ public void shuffleArray(int[] array, int currentLen, ArrayVisualizer ArrayVisua Delays.setSleepRatio(sleepRatio); } - Shuffles tempShuffle = this.Shuffles; - if(Distributions == Distributions.RANDOM || Distributions == Distributions.EQUAL) - this.Shuffles = Shuffles.ALREADY; - Shuffles.shuffleArray(array, this.ArrayVisualizer, Delays, Highlights, Writes); - this.Shuffles = tempShuffle; + ShuffleGraph tempShuffle = this.shuffle; + if(distribution == Distributions.RANDOM || distribution == Distributions.EQUAL) + this.shuffle = ShuffleGraph.single(Shuffles.ALREADY); + shuffle.shuffleArray(array, this.ArrayVisualizer); + this.shuffle = tempShuffle; Delays.setSleepRatio(speed); diff --git a/src/prompts/ShufflePrompt.java b/src/prompts/ShufflePrompt.java index d726ecd3..31d0e48a 100644 --- a/src/prompts/ShufflePrompt.java +++ b/src/prompts/ShufflePrompt.java @@ -81,11 +81,12 @@ public ShufflePrompt(ArrayManager ArrayManager, JFrame frame, UtilFrame utilFram } jList2.setListData(ArrayManager.getShuffleIDs()); for(int i = 0; i < ArrayManager.getShuffles().length; i++) { - if(ArrayManager.getShuffle().equals(ArrayManager.getShuffles()[i])) { + if(ArrayManager.containsShuffle(ArrayManager.getShuffles()[i])) { jList2.setSelectedIndex(i); break; } } + this.shuffleEditor1.graph = ArrayManager.getShuffle(); initializing = false; reposition(); @@ -228,7 +229,7 @@ private void jList2ValueChanged(javax.swing.event.ListSelectionEvent evt) throws int selection = jList2.getSelectedIndex(); Shuffles[] shuffles = ArrayManager.getShuffles(); if (selection >= 0 && selection < shuffles.length) - ArrayManager.setShuffle(shuffles[selection]); + ArrayManager.setShuffleSingle(shuffles[selection]); }//GEN-LAST:event_jList1ValueChanged // Variables declaration - do not modify//GEN-BEGIN:variables diff --git a/src/threads/RunExchangeSorts.java b/src/threads/RunExchangeSorts.java index c26e9df2..c1b6dfb4 100644 --- a/src/threads/RunExchangeSorts.java +++ b/src/threads/RunExchangeSorts.java @@ -177,7 +177,7 @@ protected synchronized void executeSortList(int[] array) throws Exception { RunExchangeSorts.this.runIndividualSort(CircleSortIterative, 0, array, 1024, 1, false); RunExchangeSorts.this.runIndividualSort(CircleMergeSort, 0, array, 1024, 0.75, false); RunExchangeSorts.this.runIndividualSort(PseudoHeapSort, 0, array, 1024, 1.5, false); - RunExchangeSorts.this.runIndividualSort(LLQuickSort, 0, array, 2048, arrayManager.getShuffle() == Shuffles.RANDOM ? 1.5 : 5, false); + RunExchangeSorts.this.runIndividualSort(LLQuickSort, 0, array, 2048, arrayManager.containsShuffle(Shuffles.RANDOM) ? 1.5 : 5, false); RunExchangeSorts.this.runIndividualSort(LLQuickSortMiddlePivot, 0, array, 2048, 1.5, false); RunExchangeSorts.this.runIndividualSort(LRQuickSort, 0, array, 2048, 1, false); RunExchangeSorts.this.runIndividualSort(LRQuickSortParallel, 0, array, 2048, 1, false); @@ -185,7 +185,7 @@ protected synchronized void executeSortList(int[] array) throws Exception { RunExchangeSorts.this.runIndividualSort(StacklessQuickSort, 0, array, 2048, 1, false); RunExchangeSorts.this.runIndividualSort(IterativeQuickSort, 0, array, 2048, 1, false); // RunExchangeSorts.this.runIndividualSort(MeanQuickSort, 0, array, 2048, 1, false); - RunExchangeSorts.this.runIndividualSort(StableQuickSort, 0, array, 2048, arrayManager.getShuffle() == Shuffles.RANDOM ? 1 : 6.5, false); + RunExchangeSorts.this.runIndividualSort(StableQuickSort, 0, array, 2048, arrayManager.containsShuffle(Shuffles.RANDOM) ? 1 : 6.5, false); RunExchangeSorts.this.runIndividualSort(StableQuickSortMiddlePivot, 0, array, 2048, 1, false); RunExchangeSorts.this.runIndividualSort(ooPQuickSort, 0, array, 2048, 1, false); RunExchangeSorts.this.runIndividualSort(StableQuickSortParallel, 0, array, 2048, 1, false); diff --git a/src/threads/RunHybridSorts.java b/src/threads/RunHybridSorts.java index 08190a90..a74d593f 100644 --- a/src/threads/RunHybridSorts.java +++ b/src/threads/RunHybridSorts.java @@ -153,10 +153,10 @@ protected synchronized void executeSortList(int[] array) throws Exception { RunHybridSorts.this.runIndividualSort(QuickSPSort, 0, array, 512, 0.4, false); RunHybridSorts.this.runIndividualSort(BinaryMergeSort, 0, array, 2048, 1, false); RunHybridSorts.this.runIndividualSort(MergeInsertionSort, 0, array, 2048, 1.75, false); - RunHybridSorts.this.runIndividualSort(SwapMergeSort, 0, array, 2048, arrayManager.getShuffle() == Shuffles.RANDOM ? 1.65 : 6.5, false); + RunHybridSorts.this.runIndividualSort(SwapMergeSort, 0, array, 2048, arrayManager.containsShuffle(Shuffles.RANDOM) ? 1.65 : 6.5, false); RunHybridSorts.this.runIndividualSort(BaseNMergeSort, 4, array, 2048, 1, false); - RunHybridSorts.this.runIndividualSort(WeaveMergeSort, 0, array, 2048, arrayManager.getShuffle() == Shuffles.RANDOM ? 1.65 : 6.5, false); - RunHybridSorts.this.runIndividualSort(ImprovedWeaveMergeSort, 0, array, 2048, arrayManager.getShuffle() == Shuffles.RANDOM ? 1.65 : 6.5, false); + RunHybridSorts.this.runIndividualSort(WeaveMergeSort, 0, array, 2048, arrayManager.containsShuffle(Shuffles.RANDOM) ? 1.65 : 6.5, false); + RunHybridSorts.this.runIndividualSort(ImprovedWeaveMergeSort, 0, array, 2048, arrayManager.containsShuffle(Shuffles.RANDOM) ? 1.65 : 6.5, false); RunHybridSorts.this.runIndividualSort(TimSort, 0, array, 2048, 1, false); RunHybridSorts.this.runIndividualSort(CocktailMergeSort, 0, array, 2048, 1, false); RunHybridSorts.this.runIndividualSort(BubbleMergeSort, 0, array, 2048, 1, false); diff --git a/src/threads/RunInsertionSorts.java b/src/threads/RunInsertionSorts.java index aa5ae2e1..5bec4a3b 100644 --- a/src/threads/RunInsertionSorts.java +++ b/src/threads/RunInsertionSorts.java @@ -109,8 +109,8 @@ protected synchronized void executeSortList(int[] array) throws Exception { RunInsertionSorts.this.runIndividualSort(LibrarySort, 0, array, 2048, 1, false); RunInsertionSorts.this.runIndividualSort(ClassicLibrarySort, 0, array, 2048, 1, false); RunInsertionSorts.this.runIndividualSort(PatienceSort, 0, array, 2048, 1, false); - RunInsertionSorts.this.runIndividualSort(ClassicTreeSort, 0, array, 2048, arrayManager.getShuffle() == Shuffles.RANDOM ? 1 : 5, false); - RunInsertionSorts.this.runIndividualSort(TreeSort, 0, array, 2048, arrayManager.getShuffle() == Shuffles.RANDOM ? 1 : 5, false); + RunInsertionSorts.this.runIndividualSort(ClassicTreeSort, 0, array, 2048, arrayManager.containsShuffle(Shuffles.RANDOM) ? 1 : 5, false); + RunInsertionSorts.this.runIndividualSort(TreeSort, 0, array, 2048, arrayManager.containsShuffle(Shuffles.RANDOM) ? 1 : 5, false); RunInsertionSorts.this.runIndividualSort(ShuffledTreeSort, 0, array, 2048, 1, false); RunInsertionSorts.this.runIndividualSort(AATreeSort, 0, array, 2048, 1, false); RunInsertionSorts.this.runIndividualSort(AVLTreeSort, 0, array, 2048, 1, false); diff --git a/src/threads/RunQuickSorts.java b/src/threads/RunQuickSorts.java index 8016d70b..4613ccc5 100644 --- a/src/threads/RunQuickSorts.java +++ b/src/threads/RunQuickSorts.java @@ -45,7 +45,7 @@ public RunQuickSorts(ArrayVisualizer arrayVisualizer) { @Override protected synchronized void executeSortList(int[] array) throws Exception { - RunQuickSorts.this.runIndividualSort(CubeRootQuickSort, 0, array, 2048, arrayManager.getShuffle() == Shuffles.RANDOM ? 1 : 6.5, false); + RunQuickSorts.this.runIndividualSort(CubeRootQuickSort, 0, array, 2048, arrayManager.containsShuffle(Shuffles.RANDOM) ? 1 : 6.5, false); } @Override diff --git a/src/utils/ShuffleGraph.java b/src/utils/ShuffleGraph.java index db98ed38..517f2123 100644 --- a/src/utils/ShuffleGraph.java +++ b/src/utils/ShuffleGraph.java @@ -9,9 +9,9 @@ import java.util.ListIterator; import java.util.NoSuchElementException; +import main.ArrayVisualizer; import utils.shuffle_utils.Connection; import utils.shuffle_utils.Node; -import utils.shuffle_utils.ShuffleInfo; public class ShuffleGraph implements Collection { public List nodes; @@ -37,15 +37,23 @@ public ShuffleGraph(ShuffleInfo[] shuffles) { } public static ShuffleGraph single(ShuffleInfo shuffle) { - return new ShuffleGraph(new ShuffleInfo[] {shuffle}); + ShuffleGraph graph = new ShuffleGraph(); + graph.add(shuffle); + return graph; } public static ShuffleGraph single(Shuffles shuffle) { - return new ShuffleGraph(new ShuffleInfo[] {new ShuffleInfo(shuffle)}); + return single(new ShuffleInfo(shuffle)); } public static ShuffleGraph single(Distributions distribution) { - return new ShuffleGraph(new ShuffleInfo[] {new ShuffleInfo(distribution)}); + return single(new ShuffleInfo(distribution)); + } + + public void shuffleArray(int[] array, ArrayVisualizer arrayVisualizer) { + for (ShuffleInfo shuffle : this) { + shuffle.shuffle(array, arrayVisualizer); + } } public void addDisconnected(ShuffleInfo shuffle) { @@ -151,15 +159,19 @@ public void clear() { } public Node findLast() { + Node previous = null; Node node = this.nodes.get(0); while (node != null) { Connection connect = node.postConnection; if (connect == null) { + previous = node; + node = null; break; } + previous = node; node = connect.to; } - return node; + return previous; } public boolean add(ShuffleInfo shuffle) { @@ -179,9 +191,12 @@ Node add(ShuffleInfo shuffle, Node after) { Node newNode = new Node(shuffle, this, after.x + Node.WIDTH + 15, after.y); if (after.postConnection == null) { after.postConnection = new Connection(after, newNode); + this.connections.add(after.postConnection); } else { after.postConnection.to = newNode; } + newNode.preConnection = after.postConnection; + this.nodes.add(newNode); return newNode; } @@ -196,6 +211,9 @@ Node find(Object o) { break; } node = connect.to; + if (node == null) { + break; + } if (node.equals(o)) { return node; } diff --git a/src/utils/shuffle_utils/ShuffleInfo.java b/src/utils/ShuffleInfo.java similarity index 79% rename from src/utils/shuffle_utils/ShuffleInfo.java rename to src/utils/ShuffleInfo.java index 5ef55d17..37a71b0e 100644 --- a/src/utils/shuffle_utils/ShuffleInfo.java +++ b/src/utils/ShuffleInfo.java @@ -1,14 +1,9 @@ -package utils.shuffle_utils; +package utils; import java.util.ArrayList; import java.util.List; import main.ArrayVisualizer; -import utils.Delays; -import utils.Distributions; -import utils.Highlights; -import utils.Shuffles; -import utils.Writes; final public class ShuffleInfo { final boolean isDistribution; @@ -52,18 +47,25 @@ public Shuffles getShuffle() { } public boolean equals(Object o) { - if (o == null || !(o instanceof ShuffleInfo)) { + if (o == null) { return false; } - ShuffleInfo other = (ShuffleInfo)o; - if (this.isDistribution != other.isDistribution) { - return false; - } - if (isDistribution) { - return this.distribution == other.distribution; - } else { - return this.shuffle == other.shuffle; + if (o instanceof ShuffleInfo) { + ShuffleInfo other = (ShuffleInfo)o; + if (this.isDistribution != other.isDistribution) { + return false; + } + if (isDistribution) { + return this.distribution == other.distribution; + } else { + return this.shuffle == other.shuffle; + } + } else if (o instanceof Shuffles) { + return !this.isDistribution && this.shuffle == o; + } else if (o instanceof Distributions) { + return this.isDistribution && this.distribution == o; } + return false; } public String getName() { diff --git a/src/utils/shuffle_utils/Node.java b/src/utils/shuffle_utils/Node.java index 4affef5a..54d7ad8d 100644 --- a/src/utils/shuffle_utils/Node.java +++ b/src/utils/shuffle_utils/Node.java @@ -6,6 +6,7 @@ import java.awt.geom.Rectangle2D; import utils.ShuffleGraph; +import utils.ShuffleInfo; public class Node { public static final int WIDTH = 250; From aef921b9c137ae1d11dc8d5375bb3f81958db656 Mon Sep 17 00:00:00 2001 From: "Josiah (Gaming32) Glosson" Date: Thu, 22 Jul 2021 20:06:08 -0500 Subject: [PATCH 06/40] Add button (took a lot of effort lol) --- src/dialogs/ShuffleDialog.java | 238 ++++++++++++++++++ .../ShufflePanel.java} | 8 +- src/prompts/ShufflePrompt.java | 97 +++---- 3 files changed, 293 insertions(+), 50 deletions(-) create mode 100644 src/dialogs/ShuffleDialog.java rename src/{frames/ShuffleEditor.java => panels/ShufflePanel.java} (93%) diff --git a/src/dialogs/ShuffleDialog.java b/src/dialogs/ShuffleDialog.java new file mode 100644 index 00000000..b7b0537a --- /dev/null +++ b/src/dialogs/ShuffleDialog.java @@ -0,0 +1,238 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package dialogs; + +import java.awt.Dialog; + +import javax.swing.JFrame; + +import frames.AppFrame; +import frames.UtilFrame; +import main.ArrayManager; +import panels.ShufflePanel; +import panes.JErrorPane; +import utils.Distributions; +import utils.ShuffleInfo; +import utils.Shuffles; +import panels.ShufflePanel; + +/* + * +MIT License + +Copyright (c) 2019 w0rthy +Copyright (c) 2021 ArrayV 4.0 Team + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + * + */ + +/** + * + * @author S630690 + */ +final public class ShuffleDialog extends javax.swing.JDialog implements AppFrame { + + /** + * + */ + private static final long serialVersionUID = 1L; + + private ArrayManager ArrayManager; + private JFrame Frame; + private UtilFrame UtilFrame; + + private boolean initializing; + + /** + * Creates new form SortPrompt + */ + public ShuffleDialog(ArrayManager ArrayManager, JFrame frame, UtilFrame utilFrame) { + super(frame, "ArrayV Advanced Shuffle Editor", true); + + this.ArrayManager = ArrayManager; + this.Frame = frame; + this.UtilFrame = utilFrame; + + initComponents(); + + initializing = true; + this.shuffleEditor.graph = ArrayManager.getShuffle(); + initializing = false; + + reposition(); + setVisible(true); + } + + @Override + public void reposition() { + setLocation(Frame.getX()+(Frame.getWidth()-getWidth())/2,Frame.getY()+(Frame.getHeight()-getHeight())/2); + } + + + /** + * This method is called from within the constructor to initialize the form. + * WARNING: Do NOT modify this code. The content of this method is always + * regenerated by the Form Editor. + */ + @SuppressWarnings({ "rawtypes" }) + // //GEN-BEGIN:initComponents + private void initComponents() { + + this.shuffleEditor = new ShufflePanel(); + + this.jLabel1 = new javax.swing.JLabel(); + this.jScrollPane1 = new javax.swing.JScrollPane(); + this.jList1 = new javax.swing.JList(); + + this.jLabel2 = new javax.swing.JLabel(); + this.jScrollPane2 = new javax.swing.JScrollPane(); + this.jList2 = new javax.swing.JList(); + + setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE); + + jLabel1.setText("What shape do you want the array to have?"); + jLabel2.setText("How do you want the array to be shuffled?"); + + jScrollPane1.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); + jScrollPane2.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); + + jScrollPane1.setViewportView(this.jList1); + jScrollPane2.setViewportView(this.jList2); + + jList1.addListSelectionListener(new javax.swing.event.ListSelectionListener() { + @Override + public void valueChanged(javax.swing.event.ListSelectionEvent evt) { + try { + jList1ValueChanged(evt); + } catch (Exception e) { + JErrorPane.invokeErrorMessage(e); + } + } + }); + + jList2.addListSelectionListener(new javax.swing.event.ListSelectionListener() { + @Override + public void valueChanged(javax.swing.event.ListSelectionEvent evt) { + try { + jList2ValueChanged(evt); + } catch (Exception e) { + JErrorPane.invokeErrorMessage(e); + } + } + }); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); + getContentPane().setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER) + .addGroup(layout.createSequentialGroup() + .addGap(20, 20, 20) + .addComponent(this.shuffleEditor)) + .addGap(20, 20, 20)) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addContainerGap() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, true) + .addComponent(this.shuffleEditor)) + .addGap(20, 20, 20)) + ); + // layout.setHorizontalGroup( + // layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + // .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER) + // .addGroup(layout.createSequentialGroup() + // .addGap(20, 20, 20) + // .addComponent(this.jLabel1) + // .addGap(5, 5, 5)) + // .addGroup(layout.createSequentialGroup() + // .addComponent(this.jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 175, javax.swing.GroupLayout.PREFERRED_SIZE)) + // .addGap(20, 20, 20)) + // .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) + // .addGap(475, 475, 475) + // .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER) + // .addGroup(layout.createSequentialGroup() + // .addGap(20, 20, 20) + // .addComponent(this.jLabel2) + // .addGap(5, 5, 5)) + // .addGroup(layout.createSequentialGroup() + // .addComponent(this.jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, 175, javax.swing.GroupLayout.PREFERRED_SIZE)) + // .addGap(20, 20, 20))) + // ); + // layout.setVerticalGroup( + // layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + // .addGroup(layout.createSequentialGroup() + // .addContainerGap() + // .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + // .addComponent(this.jLabel1)) + // .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + // .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, true) + // .addComponent(this.jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 175, javax.swing.GroupLayout.PREFERRED_SIZE)) + // .addGap(20, 20, 20)) + // .addGroup(layout.createSequentialGroup() + // .addContainerGap() + // .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + // .addComponent(this.jLabel2)) + // .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + // .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, true) + // .addComponent(this.jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, 175, javax.swing.GroupLayout.PREFERRED_SIZE)) + // .addGap(20, 20, 20)) + // ); + + pack(); + }// //GEN-END:initComponents + + private void jList1ValueChanged(javax.swing.event.ListSelectionEvent evt) throws Exception {//GEN-FIRST:event_jList1ValueChanged + // TODO add your handling code here: + if (initializing) + return; + int selection = jList1.getSelectedIndex(); + Distributions[] distributions = ArrayManager.getDistributions(); + if (selection >= 0 && selection < distributions.length) + shuffleEditor.graph.addDisconnected(new ShuffleInfo(distributions[selection])); + }//GEN-LAST:event_jList1ValueChanged + + private void jList2ValueChanged(javax.swing.event.ListSelectionEvent evt) throws Exception {//GEN-FIRST:event_jList1ValueChanged + // TODO add your handling code here: + if (initializing) + return; + int selection = jList2.getSelectedIndex(); + Shuffles[] shuffles = ArrayManager.getShuffles(); + if (selection >= 0 && selection < shuffles.length) + shuffleEditor.graph.addDisconnected(new ShuffleInfo(shuffles[selection])); + }//GEN-LAST:event_jList1ValueChanged + + // Variables declaration - do not modify//GEN-BEGIN:variables + private ShufflePanel shuffleEditor; + + private javax.swing.JLabel jLabel1; + @SuppressWarnings("rawtypes") + private javax.swing.JList jList1; + private javax.swing.JScrollPane jScrollPane1; + + private javax.swing.JLabel jLabel2; + @SuppressWarnings("rawtypes") + private javax.swing.JList jList2; + private javax.swing.JScrollPane jScrollPane2; + // End of variables declaration//GEN-END:variables +} \ No newline at end of file diff --git a/src/frames/ShuffleEditor.java b/src/panels/ShufflePanel.java similarity index 93% rename from src/frames/ShuffleEditor.java rename to src/panels/ShufflePanel.java index cb021e41..5eac9926 100644 --- a/src/frames/ShuffleEditor.java +++ b/src/panels/ShufflePanel.java @@ -1,6 +1,7 @@ -package frames; +package panels; import java.awt.Color; +import java.awt.Dimension; import java.awt.Font; import java.awt.Graphics; import java.awt.Graphics2D; @@ -19,11 +20,11 @@ import utils.ShuffleInfo; import utils.Shuffles; -public class ShuffleEditor extends JPanel implements KeyListener { +public class ShufflePanel extends JPanel implements KeyListener { int prevX, prevY; public ShuffleGraph graph; - public ShuffleEditor() { + public ShufflePanel() { // this.graph = new ShuffleGraph( // ShuffleInfo.fromShuffleIterable( // Arrays.stream( @@ -31,6 +32,7 @@ public ShuffleEditor() { // )::iterator // ) // ); + setPreferredSize(new Dimension(700, 450)); MouseHandler handler = new MouseHandler(); addMouseListener(handler); addMouseMotionListener(handler); diff --git a/src/prompts/ShufflePrompt.java b/src/prompts/ShufflePrompt.java index 31d0e48a..06c675c3 100644 --- a/src/prompts/ShufflePrompt.java +++ b/src/prompts/ShufflePrompt.java @@ -5,12 +5,12 @@ package prompts; import javax.swing.JFrame; -import javax.swing.JOptionPane; +import dialogs.ShuffleDialog; import frames.AppFrame; -import frames.ShuffleEditor; import frames.UtilFrame; import main.ArrayManager; +import panels.ShufflePanel; import panes.JErrorPane; import utils.Distributions; import utils.Shuffles; @@ -20,6 +20,7 @@ MIT License Copyright (c) 2019 w0rthy +Copyright (c) 2021 ArrayV 4.0 Team Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -86,7 +87,7 @@ public ShufflePrompt(ArrayManager ArrayManager, JFrame frame, UtilFrame utilFram break; } } - this.shuffleEditor1.graph = ArrayManager.getShuffle(); + // this.shuffleEditor1.graph = ArrayManager.getShuffle(); initializing = false; reposition(); @@ -108,7 +109,8 @@ public void reposition() { // //GEN-BEGIN:initComponents private void initComponents() { - this.shuffleEditor1 = new ShuffleEditor(); + this.jButton1 = new javax.swing.JButton(); + this.jLabel1 = new javax.swing.JLabel(); this.jScrollPane1 = new javax.swing.JScrollPane(); this.jList1 = new javax.swing.JList(); @@ -119,6 +121,14 @@ private void initComponents() { setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE); + jButton1.setText("Open Advanced Editor"); + jButton1.addActionListener(new java.awt.event.ActionListener() { + @Override + public void actionPerformed(java.awt.event.ActionEvent evt) { + jButton1ActionPerformed(); + } + }); + jLabel1.setText("What shape do you want the array to have?"); jLabel2.setText("How do you want the array to be shuffled?"); @@ -157,61 +167,53 @@ public void valueChanged(javax.swing.event.ListSelectionEvent evt) { .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER) .addGroup(layout.createSequentialGroup() .addGap(20, 20, 20) - .addComponent(this.shuffleEditor1, javax.swing.GroupLayout.PREFERRED_SIZE, 700, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addComponent(this.jLabel1) + .addGap(5, 5, 5)) + .addGroup(layout.createSequentialGroup() + .addComponent(this.jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 175, javax.swing.GroupLayout.PREFERRED_SIZE)) .addGap(20, 20, 20)) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) + .addGap(475, 475, 475) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER) + .addGroup(layout.createSequentialGroup() + .addGap(20, 20, 20) + .addComponent(this.jLabel2) + .addGap(5, 5, 5)) + .addGroup(layout.createSequentialGroup() + .addComponent(this.jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, 175, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGap(20, 20, 20)) + .addGroup(javax.swing.GroupLayout.Alignment.CENTER, layout.createSequentialGroup() + .addComponent(this.jButton1))) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() .addContainerGap() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(this.jLabel1)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, true) - .addComponent(this.shuffleEditor1, javax.swing.GroupLayout.PREFERRED_SIZE, 450, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addComponent(this.jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 175, javax.swing.GroupLayout.PREFERRED_SIZE)) .addGap(20, 20, 20)) + .addGroup(layout.createSequentialGroup() + .addContainerGap() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(this.jLabel2)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, true) + .addComponent(this.jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, 175, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGap(10, 10, 10) + .addComponent(this.jButton1) + .addGap(15, 15, 15)) ); - // layout.setHorizontalGroup( - // layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - // .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER) - // .addGroup(layout.createSequentialGroup() - // .addGap(20, 20, 20) - // .addComponent(this.jLabel1) - // .addGap(5, 5, 5)) - // .addGroup(layout.createSequentialGroup() - // .addComponent(this.jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 175, javax.swing.GroupLayout.PREFERRED_SIZE)) - // .addGap(20, 20, 20)) - // .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) - // .addGap(475, 475, 475) - // .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER) - // .addGroup(layout.createSequentialGroup() - // .addGap(20, 20, 20) - // .addComponent(this.jLabel2) - // .addGap(5, 5, 5)) - // .addGroup(layout.createSequentialGroup() - // .addComponent(this.jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, 175, javax.swing.GroupLayout.PREFERRED_SIZE)) - // .addGap(20, 20, 20))) - // ); - // layout.setVerticalGroup( - // layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - // .addGroup(layout.createSequentialGroup() - // .addContainerGap() - // .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - // .addComponent(this.jLabel1)) - // .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - // .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, true) - // .addComponent(this.jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 175, javax.swing.GroupLayout.PREFERRED_SIZE)) - // .addGap(20, 20, 20)) - // .addGroup(layout.createSequentialGroup() - // .addContainerGap() - // .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - // .addComponent(this.jLabel2)) - // .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - // .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, true) - // .addComponent(this.jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, 175, javax.swing.GroupLayout.PREFERRED_SIZE)) - // .addGap(20, 20, 20)) - // ); pack(); }// //GEN-END:initComponents + private void jButton1ActionPerformed() {//GEN-FIRST:event_jList1ValueChanged + ShuffleDialog editor = new ShuffleDialog(ArrayManager, this, UtilFrame); + }//GEN-LAST:event_jList1ValueChanged + private void jList1ValueChanged(javax.swing.event.ListSelectionEvent evt) throws Exception {//GEN-FIRST:event_jList1ValueChanged // TODO add your handling code here: if (initializing) @@ -233,7 +235,8 @@ private void jList2ValueChanged(javax.swing.event.ListSelectionEvent evt) throws }//GEN-LAST:event_jList1ValueChanged // Variables declaration - do not modify//GEN-BEGIN:variables - private frames.ShuffleEditor shuffleEditor1; + private javax.swing.JButton jButton1; + private javax.swing.JLabel jLabel1; @SuppressWarnings("rawtypes") private javax.swing.JList jList1; From 170f763f06c4a0ee5bbed158e6b30bd203d510fb Mon Sep 17 00:00:00 2001 From: "Josiah (Gaming32) Glosson" Date: Sat, 24 Jul 2021 07:18:52 -0500 Subject: [PATCH 07/40] It's alive! --- src/dialogs/ShuffleDialog.java | 70 ++++++++++++++++++++-------------- src/utils/ShuffleGraph.java | 4 ++ 2 files changed, 45 insertions(+), 29 deletions(-) diff --git a/src/dialogs/ShuffleDialog.java b/src/dialogs/ShuffleDialog.java index b7b0537a..8be1902b 100644 --- a/src/dialogs/ShuffleDialog.java +++ b/src/dialogs/ShuffleDialog.java @@ -4,8 +4,10 @@ */ package dialogs; +import java.awt.Dimension; import java.awt.Dialog; +import javax.swing.GroupLayout; import javax.swing.JFrame; import frames.AppFrame; @@ -60,11 +62,12 @@ final public class ShuffleDialog extends javax.swing.JDialog implements AppFrame private JFrame Frame; private UtilFrame UtilFrame; - private boolean initializing; + private boolean bypassEvents; /** * Creates new form SortPrompt */ + @SuppressWarnings("unchecked") public ShuffleDialog(ArrayManager ArrayManager, JFrame frame, UtilFrame utilFrame) { super(frame, "ArrayV Advanced Shuffle Editor", true); @@ -74,9 +77,11 @@ public ShuffleDialog(ArrayManager ArrayManager, JFrame frame, UtilFrame utilFram initComponents(); - initializing = true; + bypassEvents = true; this.shuffleEditor.graph = ArrayManager.getShuffle(); - initializing = false; + jList1.setListData(ArrayManager.getDistributionIDs()); + jList2.setListData(ArrayManager.getShuffleIDs()); + bypassEvents = false; reposition(); setVisible(true); @@ -84,7 +89,6 @@ public ShuffleDialog(ArrayManager ArrayManager, JFrame frame, UtilFrame utilFram @Override public void reposition() { - setLocation(Frame.getX()+(Frame.getWidth()-getWidth())/2,Frame.getY()+(Frame.getHeight()-getHeight())/2); } @@ -99,19 +103,14 @@ private void initComponents() { this.shuffleEditor = new ShufflePanel(); - this.jLabel1 = new javax.swing.JLabel(); this.jScrollPane1 = new javax.swing.JScrollPane(); this.jList1 = new javax.swing.JList(); - this.jLabel2 = new javax.swing.JLabel(); this.jScrollPane2 = new javax.swing.JScrollPane(); this.jList2 = new javax.swing.JList(); setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE); - jLabel1.setText("What shape do you want the array to have?"); - jLabel2.setText("How do you want the array to be shuffled?"); - jScrollPane1.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); jScrollPane2.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); @@ -143,21 +142,28 @@ public void valueChanged(javax.swing.event.ListSelectionEvent evt) { javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); getContentPane().setLayout(layout); layout.setHorizontalGroup( - layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER) - .addGroup(layout.createSequentialGroup() - .addGap(20, 20, 20) - .addComponent(this.shuffleEditor)) - .addGap(20, 20, 20)) - ); - layout.setVerticalGroup( - layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + layout.createParallelGroup(GroupLayout.Alignment.CENTER) .addGroup(layout.createSequentialGroup() - .addContainerGap() - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, true) - .addComponent(this.shuffleEditor)) - .addGap(20, 20, 20)) - ); + .addGap(10, 10, 10) + .addComponent(this.shuffleEditor) + .addGap(10, 10, 10)) + .addGroup(layout.createSequentialGroup() + .addGap(75, 75, 75) + .addComponent(this.jScrollPane1, 175, 175, 175) + .addGap(75, 75, 75) + .addComponent(this.jScrollPane2, 175, 175, 175) + .addGap(75, 75, 75)) + ); + layout.setVerticalGroup( + layout.createSequentialGroup() + .addGap(10, 10, 10) + .addComponent(this.shuffleEditor) + .addGap(10, 10, 10) + .addGroup(layout.createParallelGroup(GroupLayout.Alignment.CENTER) + .addComponent(this.jScrollPane1, 175, 175, 175) + .addComponent(this.jScrollPane2, 175, 175, 175)) + .addGap(10, 10, 10) + ); // layout.setHorizontalGroup( // layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) // .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER) @@ -204,33 +210,39 @@ public void valueChanged(javax.swing.event.ListSelectionEvent evt) { private void jList1ValueChanged(javax.swing.event.ListSelectionEvent evt) throws Exception {//GEN-FIRST:event_jList1ValueChanged // TODO add your handling code here: - if (initializing) + if (bypassEvents) return; int selection = jList1.getSelectedIndex(); Distributions[] distributions = ArrayManager.getDistributions(); if (selection >= 0 && selection < distributions.length) - shuffleEditor.graph.addDisconnected(new ShuffleInfo(distributions[selection])); + shuffleEditor.graph.addDisconnected(new ShuffleInfo(distributions[selection]), 250, 250); + shuffleEditor.repaint(); + bypassEvents = true; + jList1.clearSelection(); + bypassEvents = false; }//GEN-LAST:event_jList1ValueChanged private void jList2ValueChanged(javax.swing.event.ListSelectionEvent evt) throws Exception {//GEN-FIRST:event_jList1ValueChanged // TODO add your handling code here: - if (initializing) + if (bypassEvents) return; int selection = jList2.getSelectedIndex(); Shuffles[] shuffles = ArrayManager.getShuffles(); if (selection >= 0 && selection < shuffles.length) - shuffleEditor.graph.addDisconnected(new ShuffleInfo(shuffles[selection])); + shuffleEditor.graph.addDisconnected(new ShuffleInfo(shuffles[selection]), 250, 250); + shuffleEditor.repaint(); + bypassEvents = true; + jList2.clearSelection(); + bypassEvents = false; }//GEN-LAST:event_jList1ValueChanged // Variables declaration - do not modify//GEN-BEGIN:variables private ShufflePanel shuffleEditor; - private javax.swing.JLabel jLabel1; @SuppressWarnings("rawtypes") private javax.swing.JList jList1; private javax.swing.JScrollPane jScrollPane1; - private javax.swing.JLabel jLabel2; @SuppressWarnings("rawtypes") private javax.swing.JList jList2; private javax.swing.JScrollPane jScrollPane2; diff --git a/src/utils/ShuffleGraph.java b/src/utils/ShuffleGraph.java index 517f2123..e810ba18 100644 --- a/src/utils/ShuffleGraph.java +++ b/src/utils/ShuffleGraph.java @@ -60,6 +60,10 @@ public void addDisconnected(ShuffleInfo shuffle) { this.nodes.add(new Node(shuffle, this)); } + public void addDisconnected(ShuffleInfo shuffle, int x, int y) { + this.nodes.add(new Node(shuffle, this, x, y)); + } + public void draw(Graphics2D g) { for (Connection connection : this.connections) { connection.draw(g); From e00ec6455f7c56d4eaf7bb8c8969742f3a8f129c Mon Sep 17 00:00:00 2001 From: "Josiah (Gaming32) Glosson" Date: Sat, 24 Jul 2021 11:41:20 -0500 Subject: [PATCH 08/40] Import/export feature --- Noisily sorted.txt | 4 + backwards slightly random.txt | 4 + src/dialogs/CustomImageDialog.java | 18 +- src/dialogs/ExportShuffleDialog.java | 12 ++ src/dialogs/ImportShuffleDialog.java | 12 ++ src/dialogs/ImportSortDialog.java | 8 +- src/dialogs/LoadCustomDistributionDialog.java | 6 +- src/dialogs/RunScriptDialog.java | 6 +- src/dialogs/SaveArrayDialog.java | 8 +- src/dialogs/ShuffleDialog.java | 134 ++++++++----- src/dialogs/SoundbankDialog.java | 14 +- src/utils/shuffle_utils/GraphReader.java | 178 ++++++++++++++++++ src/utils/shuffle_utils/GraphWriter.java | 67 +++++++ 13 files changed, 397 insertions(+), 74 deletions(-) create mode 100644 Noisily sorted.txt create mode 100644 backwards slightly random.txt create mode 100644 src/dialogs/ExportShuffleDialog.java create mode 100644 src/dialogs/ImportShuffleDialog.java create mode 100644 src/utils/shuffle_utils/GraphReader.java create mode 100644 src/utils/shuffle_utils/GraphWriter.java diff --git a/Noisily sorted.txt b/Noisily sorted.txt new file mode 100644 index 00000000..bba9d73c --- /dev/null +++ b/Noisily sorted.txt @@ -0,0 +1,4 @@ +N true RANDOM 56 71 0 1 +N false SORTED 363 125 1 -1 +C 0 1 +C 1 2 diff --git a/backwards slightly random.txt b/backwards slightly random.txt new file mode 100644 index 00000000..a1ca0b00 --- /dev/null +++ b/backwards slightly random.txt @@ -0,0 +1,4 @@ +N false REVERSE 25 15 0 1 +N false ALMOST 275 15 1 -1 +C 0 1 +C 1 2 diff --git a/src/dialogs/CustomImageDialog.java b/src/dialogs/CustomImageDialog.java index e937a34f..7e461438 100644 --- a/src/dialogs/CustomImageDialog.java +++ b/src/dialogs/CustomImageDialog.java @@ -14,16 +14,16 @@ public CustomImageDialog() { FileNameExtensionFilter webmpImages = new FileNameExtensionFilter("WEBMP Images", "wbmp"); this.removeAllFilesOption(); - this.fileDialog.addChoosableFileFilter(allImages); - this.fileDialog.addChoosableFileFilter(jpegImages); - this.fileDialog.addChoosableFileFilter(pngImages); - this.fileDialog.addChoosableFileFilter(gifImages); - this.fileDialog.addChoosableFileFilter(bmpImages); - this.fileDialog.addChoosableFileFilter(webmpImages); + fileDialog.addChoosableFileFilter(allImages); + fileDialog.addChoosableFileFilter(jpegImages); + fileDialog.addChoosableFileFilter(pngImages); + fileDialog.addChoosableFileFilter(gifImages); + fileDialog.addChoosableFileFilter(bmpImages); + fileDialog.addChoosableFileFilter(webmpImages); - this.fileDialog.setDialogTitle("Choose an image..."); + fileDialog.setDialogTitle("Choose an image..."); - this.fileDialog.showDialog(null, "Select"); - this.file = this.fileDialog.getSelectedFile(); + fileDialog.showDialog(null, "Select"); + this.file = fileDialog.getSelectedFile(); } } \ No newline at end of file diff --git a/src/dialogs/ExportShuffleDialog.java b/src/dialogs/ExportShuffleDialog.java new file mode 100644 index 00000000..e70ca657 --- /dev/null +++ b/src/dialogs/ExportShuffleDialog.java @@ -0,0 +1,12 @@ +package dialogs; + +final public class ExportShuffleDialog extends FileDialog { + public ExportShuffleDialog() { + super(); + + fileDialog.setDialogTitle("Choose where to export the current shuffle graph..."); + + fileDialog.showSaveDialog(null); + this.file = fileDialog.getSelectedFile(); + } +} \ No newline at end of file diff --git a/src/dialogs/ImportShuffleDialog.java b/src/dialogs/ImportShuffleDialog.java new file mode 100644 index 00000000..f1d2ae2a --- /dev/null +++ b/src/dialogs/ImportShuffleDialog.java @@ -0,0 +1,12 @@ +package dialogs; + +final public class ImportShuffleDialog extends FileDialog { + public ImportShuffleDialog() { + super(); + + fileDialog.setDialogTitle("Choose where to import the current shuffle graph from..."); + + fileDialog.showOpenDialog(null); + this.file = fileDialog.getSelectedFile(); + } +} \ No newline at end of file diff --git a/src/dialogs/ImportSortDialog.java b/src/dialogs/ImportSortDialog.java index b2e0e941..9587b28a 100644 --- a/src/dialogs/ImportSortDialog.java +++ b/src/dialogs/ImportSortDialog.java @@ -8,11 +8,11 @@ public ImportSortDialog() { FileNameExtensionFilter javaFiles = new FileNameExtensionFilter("Java Source Files (.java)", "java"); this.removeAllFilesOption(); - this.fileDialog.addChoosableFileFilter(javaFiles); + fileDialog.addChoosableFileFilter(javaFiles); - this.fileDialog.setDialogTitle("Choose a sort file to import..."); + fileDialog.setDialogTitle("Choose a sort file to import..."); - this.fileDialog.showDialog(null, "Select"); - this.file = this.fileDialog.getSelectedFile(); + fileDialog.showOpenDialog(null); + this.file = fileDialog.getSelectedFile(); } } \ No newline at end of file diff --git a/src/dialogs/LoadCustomDistributionDialog.java b/src/dialogs/LoadCustomDistributionDialog.java index 47c7d24b..23c0e1e1 100644 --- a/src/dialogs/LoadCustomDistributionDialog.java +++ b/src/dialogs/LoadCustomDistributionDialog.java @@ -4,9 +4,9 @@ final public class LoadCustomDistributionDialog extends FileDialog { public LoadCustomDistributionDialog() { super(); - this.fileDialog.setDialogTitle("Choose a distribution file..."); + fileDialog.setDialogTitle("Choose a distribution file..."); - this.fileDialog.showDialog(null, "Select"); - this.file = this.fileDialog.getSelectedFile(); + fileDialog.showDialog(null, "Select"); + this.file = fileDialog.getSelectedFile(); } } \ No newline at end of file diff --git a/src/dialogs/RunScriptDialog.java b/src/dialogs/RunScriptDialog.java index 72e648b2..19dce4bc 100644 --- a/src/dialogs/RunScriptDialog.java +++ b/src/dialogs/RunScriptDialog.java @@ -4,9 +4,9 @@ final public class RunScriptDialog extends FileDialog { public RunScriptDialog() { super(); - this.fileDialog.setDialogTitle("Choose a script file..."); + fileDialog.setDialogTitle("Choose a script file..."); - this.fileDialog.showDialog(null, "Select"); - this.file = this.fileDialog.getSelectedFile(); + fileDialog.showDialog(null, "Select"); + this.file = fileDialog.getSelectedFile(); } } \ No newline at end of file diff --git a/src/dialogs/SaveArrayDialog.java b/src/dialogs/SaveArrayDialog.java index 38ba1860..01430984 100644 --- a/src/dialogs/SaveArrayDialog.java +++ b/src/dialogs/SaveArrayDialog.java @@ -1,14 +1,12 @@ package dialogs; -import javax.swing.filechooser.FileNameExtensionFilter; - final public class SaveArrayDialog extends FileDialog { public SaveArrayDialog() { super(); - this.fileDialog.setDialogTitle("Choose where to save the contents of the main array..."); + fileDialog.setDialogTitle("Choose where to save the contents of the main array..."); - this.fileDialog.showSaveDialog(null); - this.file = this.fileDialog.getSelectedFile(); + fileDialog.showSaveDialog(null); + this.file = fileDialog.getSelectedFile(); } } \ No newline at end of file diff --git a/src/dialogs/ShuffleDialog.java b/src/dialogs/ShuffleDialog.java index 8be1902b..84724f60 100644 --- a/src/dialogs/ShuffleDialog.java +++ b/src/dialogs/ShuffleDialog.java @@ -5,10 +5,12 @@ package dialogs; import java.awt.Dimension; +import java.io.IOException; import java.awt.Dialog; import javax.swing.GroupLayout; import javax.swing.JFrame; +import javax.swing.JOptionPane; import frames.AppFrame; import frames.UtilFrame; @@ -16,8 +18,12 @@ import panels.ShufflePanel; import panes.JErrorPane; import utils.Distributions; +import utils.ShuffleGraph; import utils.ShuffleInfo; import utils.Shuffles; +import utils.shuffle_utils.GraphReader; +import utils.shuffle_utils.GraphWriter; +import utils.shuffle_utils.GraphReader.MalformedGraphFileException; import panels.ShufflePanel; /* @@ -85,6 +91,7 @@ public ShuffleDialog(ArrayManager ArrayManager, JFrame frame, UtilFrame utilFram reposition(); setVisible(true); + setAlwaysOnTop(false); } @Override @@ -103,6 +110,9 @@ private void initComponents() { this.shuffleEditor = new ShufflePanel(); + this.jButton1 = new javax.swing.JButton(); + this.jButton2 = new javax.swing.JButton(); + this.jScrollPane1 = new javax.swing.JScrollPane(); this.jList1 = new javax.swing.JList(); @@ -111,11 +121,27 @@ private void initComponents() { setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE); - jScrollPane1.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); - jScrollPane2.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); + jButton1.setText("Import..."); + jButton1.addActionListener(new java.awt.event.ActionListener() { + @Override + public void actionPerformed(java.awt.event.ActionEvent evt) { + jButton1ActionPerformed(); + } + }); + + jButton2.setText("Export..."); + jButton2.addActionListener(new java.awt.event.ActionListener() { + @Override + public void actionPerformed(java.awt.event.ActionEvent evt) { + jButton2ActionPerformed(); + } + }); + jScrollPane1.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); jScrollPane1.setViewportView(this.jList1); + jScrollPane2.setViewportView(this.jList2); + jScrollPane2.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); jList1.addListSelectionListener(new javax.swing.event.ListSelectionListener() { @Override @@ -153,6 +179,12 @@ public void valueChanged(javax.swing.event.ListSelectionEvent evt) { .addGap(75, 75, 75) .addComponent(this.jScrollPane2, 175, 175, 175) .addGap(75, 75, 75)) + .addGroup(layout.createSequentialGroup() + .addGap(150, 150, 150) + .addComponent(this.jButton1) + .addGap(20, 20, 20) + .addComponent(this.jButton2) + .addGap(150, 150, 150)) ); layout.setVerticalGroup( layout.createSequentialGroup() @@ -163,51 +195,64 @@ public void valueChanged(javax.swing.event.ListSelectionEvent evt) { .addComponent(this.jScrollPane1, 175, 175, 175) .addComponent(this.jScrollPane2, 175, 175, 175)) .addGap(10, 10, 10) + .addGroup(layout.createParallelGroup(GroupLayout.Alignment.CENTER) + .addComponent(this.jButton1) + .addComponent(this.jButton2)) + .addGap(10, 10, 10) ); - // layout.setHorizontalGroup( - // layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - // .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER) - // .addGroup(layout.createSequentialGroup() - // .addGap(20, 20, 20) - // .addComponent(this.jLabel1) - // .addGap(5, 5, 5)) - // .addGroup(layout.createSequentialGroup() - // .addComponent(this.jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 175, javax.swing.GroupLayout.PREFERRED_SIZE)) - // .addGap(20, 20, 20)) - // .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) - // .addGap(475, 475, 475) - // .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER) - // .addGroup(layout.createSequentialGroup() - // .addGap(20, 20, 20) - // .addComponent(this.jLabel2) - // .addGap(5, 5, 5)) - // .addGroup(layout.createSequentialGroup() - // .addComponent(this.jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, 175, javax.swing.GroupLayout.PREFERRED_SIZE)) - // .addGap(20, 20, 20))) - // ); - // layout.setVerticalGroup( - // layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - // .addGroup(layout.createSequentialGroup() - // .addContainerGap() - // .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - // .addComponent(this.jLabel1)) - // .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - // .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, true) - // .addComponent(this.jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 175, javax.swing.GroupLayout.PREFERRED_SIZE)) - // .addGap(20, 20, 20)) - // .addGroup(layout.createSequentialGroup() - // .addContainerGap() - // .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - // .addComponent(this.jLabel2)) - // .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - // .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, true) - // .addComponent(this.jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, 175, javax.swing.GroupLayout.PREFERRED_SIZE)) - // .addGap(20, 20, 20)) - // ); - pack(); }// //GEN-END:initComponents + private void jButton1ActionPerformed() {//GEN-FIRST:event_jButton1ActionPerformed + FileDialog fileDialog = new ImportShuffleDialog(); + ShuffleGraph newShuffle; + try { + newShuffle = new GraphReader().read(fileDialog.file); + } catch (IOException e) { + e.printStackTrace(); + JErrorPane.invokeCustomErrorMessage("IO Error: " + e.getMessage()); + return; + } catch (MalformedGraphFileException e) { + e.printStackTrace(); + JErrorPane.invokeCustomErrorMessage("Error Parsing File: " + e.getMessage()); + return; + } catch (IllegalArgumentException e) { + e.printStackTrace(); + String message = e.getMessage(); + if (message.startsWith("No enum constant utils.")) { + message = message.substring("No enum constant utils.".length()); + if (message.startsWith("Shuffles.")) { + message = message.substring("Shuffles.".length()); + JErrorPane.invokeCustomErrorMessage("No shuffle with the ID \"" + message + "\""); + return; + } else if (message.startsWith("Distributions.")) { + message = message.substring("Distributions.".length()); + JErrorPane.invokeCustomErrorMessage("No distribution with the ID \"" + message + "\""); + return; + } + } + JErrorPane.invokeErrorMessage(e, "Import Advanced Shuffle");; + return; + } + ArrayManager.setShuffle(newShuffle); + this.shuffleEditor.graph = newShuffle; + this.shuffleEditor.repaint(); + }//GEN-LAST:event_jButton1ActionPerformed + + private void jButton2ActionPerformed() {//GEN-FIRST:event_jButton1ActionPerformed + FileDialog fileDialog = new ExportShuffleDialog(); + try { + new GraphWriter(shuffleEditor.graph).write(fileDialog.file); + } catch (IOException e) { + e.printStackTrace(); + JErrorPane.invokeCustomErrorMessage("IO Error: " + e.getMessage()); + return; + } + JOptionPane.showMessageDialog(null, + "Successfully exported current shuffle to file \"" + fileDialog.file.getAbsolutePath() + "\"", + "Advanced Shuffle Editor", JOptionPane.INFORMATION_MESSAGE); + }//GEN-LAST:event_jButton1ActionPerformed + private void jList1ValueChanged(javax.swing.event.ListSelectionEvent evt) throws Exception {//GEN-FIRST:event_jList1ValueChanged // TODO add your handling code here: if (bypassEvents) @@ -239,6 +284,9 @@ private void jList2ValueChanged(javax.swing.event.ListSelectionEvent evt) throws // Variables declaration - do not modify//GEN-BEGIN:variables private ShufflePanel shuffleEditor; + private javax.swing.JButton jButton1; + private javax.swing.JButton jButton2; + @SuppressWarnings("rawtypes") private javax.swing.JList jList1; private javax.swing.JScrollPane jScrollPane1; diff --git a/src/dialogs/SoundbankDialog.java b/src/dialogs/SoundbankDialog.java index 7d7da77b..58196aad 100644 --- a/src/dialogs/SoundbankDialog.java +++ b/src/dialogs/SoundbankDialog.java @@ -12,14 +12,14 @@ public SoundbankDialog() { FileNameExtensionFilter generalMIDI = new FileNameExtensionFilter("General MIDI (.gm)", "gm"); this.removeAllFilesOption(); - this.fileDialog.addChoosableFileFilter(allSoundbanks); - this.fileDialog.addChoosableFileFilter(soundfonts); - this.fileDialog.addChoosableFileFilter(downloadableSounds); - this.fileDialog.addChoosableFileFilter(generalMIDI); + fileDialog.addChoosableFileFilter(allSoundbanks); + fileDialog.addChoosableFileFilter(soundfonts); + fileDialog.addChoosableFileFilter(downloadableSounds); + fileDialog.addChoosableFileFilter(generalMIDI); - this.fileDialog.setDialogTitle("Choose a MIDI soundbank..."); + fileDialog.setDialogTitle("Choose a MIDI soundbank..."); - this.fileDialog.showDialog(null, "Select"); - this.file = this.fileDialog.getSelectedFile(); + fileDialog.showDialog(null, "Select"); + this.file = fileDialog.getSelectedFile(); } } \ No newline at end of file diff --git a/src/utils/shuffle_utils/GraphReader.java b/src/utils/shuffle_utils/GraphReader.java new file mode 100644 index 00000000..a9925433 --- /dev/null +++ b/src/utils/shuffle_utils/GraphReader.java @@ -0,0 +1,178 @@ +package utils.shuffle_utils; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.Scanner; + +import utils.Distributions; +import utils.ShuffleGraph; +import utils.ShuffleInfo; +import utils.Shuffles; + +public final class GraphReader { + public final class MalformedGraphFileException extends Exception { + // public int line, column; + + public MalformedGraphFileException() { + super(); + // this.line = 0; + // this.column = 0; + } + + // public MalformedGraphFileException(int line, int column) { + // super(); + // this.line = line; + // this.column = column; + // } + + public MalformedGraphFileException(String message) { + super(message); + // this.line = 0; + // this.column = 0; + } + + // public MalformedGraphFileException(String message, int line, int column) { + // super(message); + // this.line = line; + // this.column = column; + // } + } + + private final class PartialElement { + int left, right; + + public PartialElement(int left, int right) { + this.left = left; + this.right = right; + } + } + + Scanner scanner; + ShuffleGraph result; + List partialNodes; + + public GraphReader() { + result = null; + } + + public ShuffleGraph getResult() { + return result; + } + + public ShuffleGraph read(String fileName) throws IOException, MalformedGraphFileException { + scanner = new Scanner(fileName); + try { + read(); + } finally { + scanner.close(); + } + return result; + } + + public ShuffleGraph read(File file) throws IOException, MalformedGraphFileException { + scanner = new Scanner(file); + try { + read(); + } finally { + scanner.close(); + } + return result; + } + + public ShuffleGraph read(Scanner scanner) throws IOException, MalformedGraphFileException { + this.scanner = scanner; + try { + read(); + } finally { + scanner.close(); + } + return result; + } + + private void read() throws IOException, MalformedGraphFileException { + result = new ShuffleGraph(); + partialNodes = new ArrayList<>(); + + while (scanner.hasNext()) { + String identifier = scanner.next().toUpperCase(); + switch (identifier) { + case "N": + readNode(); + break; + case "C": + readConnection(); + break; + default: + throw new MalformedGraphFileException("Invalid element type \"" + identifier + "\""); + } + } + + for (int i = 1; i < result.nodes.size(); i++) { + Node node = result.nodes.get(i); + PartialElement partial = partialNodes.get(i - 1); + node.preConnection = partial.left == -1 ? null : result.connections.get(partial.left); + node.postConnection = partial.right == -1 ? null : result.connections.get(partial.right); + } + + partialNodes = null; + } + + private void readNode() throws MalformedGraphFileException { + if (!scanner.hasNextBoolean()) { + throw new MalformedGraphFileException("Expected isDistribution in node declaration"); + } + boolean isDistribution = scanner.nextBoolean(); + if (!scanner.hasNext()) { + throw new MalformedGraphFileException("Unexpected EOF during node parsing"); + } + String name = scanner.next(); + ShuffleInfo shuffleInfo; + if (isDistribution) { + Distributions distribution = Distributions.valueOf(name); + shuffleInfo = new ShuffleInfo(distribution); + } else { + Shuffles shuffle = Shuffles.valueOf(name); + shuffleInfo = new ShuffleInfo(shuffle); + } + if (!scanner.hasNextInt()) { + throw new MalformedGraphFileException("Expected X coordinate in node declaration"); + } + int x = scanner.nextInt(); + if (!scanner.hasNextInt()) { + throw new MalformedGraphFileException("Expected Y coordinate in node declaration"); + } + int y = scanner.nextInt(); + if (!scanner.hasNextInt()) { + throw new MalformedGraphFileException("Expected preConnection ID in node declaration"); + } + int preConnectionID = scanner.nextInt(); + if (!scanner.hasNextInt()) { + throw new MalformedGraphFileException("Expected postConnection ID in node declaration"); + } + int postConnectionID = scanner.nextInt(); + + result.nodes.add(new Node(shuffleInfo, result, x, y)); + partialNodes.add(new PartialElement(preConnectionID, postConnectionID)); + } + + private void readConnection() throws MalformedGraphFileException { + if (!scanner.hasNextInt()) { + throw new MalformedGraphFileException("Expected fromNode ID in connection declaration"); + } + int fromNodeID = scanner.nextInt(); + if (!scanner.hasNextInt()) { + throw new MalformedGraphFileException("Expected toNode ID in connection declaration"); + } + int toNodeID = scanner.nextInt(); + + Node fromNode = fromNodeID == -1 ? null : result.nodes.get(fromNodeID); + Node toNode = toNodeID == -1 ? null : result.nodes.get(toNodeID); + Connection connection = new Connection(fromNode, toNode); + result.connections.add(connection); + if (fromNodeID == 0) { + fromNode.postConnection = connection; + } + } +} diff --git a/src/utils/shuffle_utils/GraphWriter.java b/src/utils/shuffle_utils/GraphWriter.java new file mode 100644 index 00000000..a65f88b6 --- /dev/null +++ b/src/utils/shuffle_utils/GraphWriter.java @@ -0,0 +1,67 @@ +package utils.shuffle_utils; + +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +import utils.ShuffleGraph; + +public final class GraphWriter { + ShuffleGraph graph; + + public GraphWriter(ShuffleGraph graph) { + this.graph = graph; + } + + public void write(String fileName) throws IOException { + FileWriter writer = new FileWriter(fileName); + write(writer); + } + + public void write(File file) throws IOException { + FileWriter writer = new FileWriter(file); + write(writer); + } + + public void write(FileWriter writer) throws IOException { + Map nodeMap = new HashMap<>(); + Map connectionMap = new HashMap<>(); + for (int i = 0; i < graph.nodes.size(); i++) { + Node node = graph.nodes.get(i); + nodeMap.put(node, i); + } + nodeMap.put(null, -1); + for (int i = 0; i < graph.connections.size(); i++) { + Connection conn = graph.connections.get(i); + connectionMap.put(conn, i); + } + connectionMap.put(null, -1); + + for (int i = 1; i < graph.nodes.size(); i++) { + Node node = graph.nodes.get(i); + writer.write("N "); + if (node.getValue().isDistribution()) { + writer.write("true "); + writer.write(node.getValue().getDistribution().name() + " "); + } else { + writer.write("false "); + writer.write(node.getValue().getShuffle().name() + " "); + } + writer.write(node.x + " "); + writer.write(node.y + " "); + writer.write(connectionMap.get(node.preConnection) + " "); + writer.write(connectionMap.get(node.postConnection) + "\n"); + } + + for (int i = 0; i < graph.connections.size(); i++) { + Connection conn = graph.connections.get(i); + writer.write("C "); + writer.write(nodeMap.get(conn.from) + " "); + writer.write(nodeMap.get(conn.to) + "\n"); + } + + writer.close(); + } +} From 7697ef1fb01e0f0bd8e8b71f50d538fa415b5b3a Mon Sep 17 00:00:00 2001 From: "Josiah (Gaming32) Glosson" Date: Sat, 24 Jul 2021 12:00:00 -0500 Subject: [PATCH 09/40] Improve errors --- src/dialogs/ShuffleDialog.java | 17 -------- src/utils/shuffle_utils/GraphReader.java | 55 +++++++++++++++++++----- 2 files changed, 45 insertions(+), 27 deletions(-) diff --git a/src/dialogs/ShuffleDialog.java b/src/dialogs/ShuffleDialog.java index 84724f60..0393a1e0 100644 --- a/src/dialogs/ShuffleDialog.java +++ b/src/dialogs/ShuffleDialog.java @@ -216,23 +216,6 @@ private void jButton1ActionPerformed() {//GEN-FIRST:event_jButton1ActionPerforme e.printStackTrace(); JErrorPane.invokeCustomErrorMessage("Error Parsing File: " + e.getMessage()); return; - } catch (IllegalArgumentException e) { - e.printStackTrace(); - String message = e.getMessage(); - if (message.startsWith("No enum constant utils.")) { - message = message.substring("No enum constant utils.".length()); - if (message.startsWith("Shuffles.")) { - message = message.substring("Shuffles.".length()); - JErrorPane.invokeCustomErrorMessage("No shuffle with the ID \"" + message + "\""); - return; - } else if (message.startsWith("Distributions.")) { - message = message.substring("Distributions.".length()); - JErrorPane.invokeCustomErrorMessage("No distribution with the ID \"" + message + "\""); - return; - } - } - JErrorPane.invokeErrorMessage(e, "Import Advanced Shuffle");; - return; } ArrayManager.setShuffle(newShuffle); this.shuffleEditor.graph = newShuffle; diff --git a/src/utils/shuffle_utils/GraphReader.java b/src/utils/shuffle_utils/GraphReader.java index a9925433..d48b62ab 100644 --- a/src/utils/shuffle_utils/GraphReader.java +++ b/src/utils/shuffle_utils/GraphReader.java @@ -112,8 +112,16 @@ private void read() throws IOException, MalformedGraphFileException { for (int i = 1; i < result.nodes.size(); i++) { Node node = result.nodes.get(i); PartialElement partial = partialNodes.get(i - 1); - node.preConnection = partial.left == -1 ? null : result.connections.get(partial.left); - node.postConnection = partial.right == -1 ? null : result.connections.get(partial.right); + try { + node.preConnection = partial.left == -1 ? null : result.connections.get(partial.left); + node.postConnection = partial.right == -1 ? null : result.connections.get(partial.right); + } catch (IndexOutOfBoundsException e) { + String message = e.getMessage(); + int id = Integer.parseInt(message.split(" ", 3)[1]); + MalformedGraphFileException newError = new MalformedGraphFileException("No connection with the ID " + id); + newError.initCause(e); + throw newError; + } } partialNodes = null; @@ -129,12 +137,30 @@ private void readNode() throws MalformedGraphFileException { } String name = scanner.next(); ShuffleInfo shuffleInfo; - if (isDistribution) { - Distributions distribution = Distributions.valueOf(name); - shuffleInfo = new ShuffleInfo(distribution); - } else { - Shuffles shuffle = Shuffles.valueOf(name); - shuffleInfo = new ShuffleInfo(shuffle); + try { + if (isDistribution) { + Distributions distribution = Distributions.valueOf(name); + shuffleInfo = new ShuffleInfo(distribution); + } else { + Shuffles shuffle = Shuffles.valueOf(name); + shuffleInfo = new ShuffleInfo(shuffle); + } + } catch (IllegalArgumentException e) { + String message = e.getMessage(); + if (message.startsWith("No enum constant utils.")) { + message = message.substring("No enum constant utils.".length()); + if (message.startsWith("Shuffles.")) { + message = "No shuffle with the ID \"" + message.substring("Shuffles.".length()) + "\""; + } else if (message.startsWith("Distributions.")) { + message = "No distribution with the ID \"" + message.substring("Distributions.".length()) + "\""; + } else { + throw e; + } + MalformedGraphFileException newError = new MalformedGraphFileException(message); + newError.initCause(e); + throw newError; + } + throw e; } if (!scanner.hasNextInt()) { throw new MalformedGraphFileException("Expected X coordinate in node declaration"); @@ -167,8 +193,17 @@ private void readConnection() throws MalformedGraphFileException { } int toNodeID = scanner.nextInt(); - Node fromNode = fromNodeID == -1 ? null : result.nodes.get(fromNodeID); - Node toNode = toNodeID == -1 ? null : result.nodes.get(toNodeID); + Node fromNode = null, toNode = null; + try { + fromNode = fromNodeID == -1 ? null : result.nodes.get(fromNodeID); + toNode = toNodeID == -1 ? null : result.nodes.get(toNodeID); + } catch (IndexOutOfBoundsException e) { + String message = e.getMessage(); + int id = Integer.parseInt(message.split(" ", 3)[1]); + MalformedGraphFileException newError = new MalformedGraphFileException("No node with the ID " + id); + newError.initCause(e); + throw newError; + } Connection connection = new Connection(fromNode, toNode); result.connections.add(connection); if (fromNodeID == 0) { From 418e1addb8cc377661f8f40efa877c0323114819 Mon Sep 17 00:00:00 2001 From: "Josiah (Gaming32) Glosson" Date: Sat, 24 Jul 2021 15:53:31 -0500 Subject: [PATCH 10/40] Fix distribution shuffling --- src/utils/ShuffleInfo.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/ShuffleInfo.java b/src/utils/ShuffleInfo.java index 37a71b0e..7b8a4aff 100644 --- a/src/utils/ShuffleInfo.java +++ b/src/utils/ShuffleInfo.java @@ -85,7 +85,7 @@ public void shuffle(int[] array, ArrayVisualizer arrayVisualizer) { Writes.arraycopy(array, 0, copy, 0, currentLen, sleep, true, true); this.distribution.initializeArray(tmp, arrayVisualizer); for (int i = 0; i < currentLen; i++) { - Writes.write(array, i, copy[tmp[i]], sleep, true, false); + Writes.write(array, i, tmp[copy[i]], sleep, true, false); } } else { Delays Delays = arrayVisualizer.getDelays(); From 74cd7ebd83ecffdcd23d6d48379753f746a42c40 Mon Sep 17 00:00:00 2001 From: "Josiah (Gaming32) Glosson" Date: Mon, 26 Jul 2021 13:40:33 -0500 Subject: [PATCH 11/40] Add some labels --- src/dialogs/ShuffleDialog.java | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/src/dialogs/ShuffleDialog.java b/src/dialogs/ShuffleDialog.java index 0393a1e0..340b4424 100644 --- a/src/dialogs/ShuffleDialog.java +++ b/src/dialogs/ShuffleDialog.java @@ -4,9 +4,7 @@ */ package dialogs; -import java.awt.Dimension; import java.io.IOException; -import java.awt.Dialog; import javax.swing.GroupLayout; import javax.swing.JFrame; @@ -24,7 +22,6 @@ import utils.shuffle_utils.GraphReader; import utils.shuffle_utils.GraphWriter; import utils.shuffle_utils.GraphReader.MalformedGraphFileException; -import panels.ShufflePanel; /* * @@ -89,9 +86,9 @@ public ShuffleDialog(ArrayManager ArrayManager, JFrame frame, UtilFrame utilFram jList2.setListData(ArrayManager.getShuffleIDs()); bypassEvents = false; + setAlwaysOnTop(false); reposition(); setVisible(true); - setAlwaysOnTop(false); } @Override @@ -115,9 +112,11 @@ private void initComponents() { this.jScrollPane1 = new javax.swing.JScrollPane(); this.jList1 = new javax.swing.JList(); + this.jLabel1 = new javax.swing.JLabel(); this.jScrollPane2 = new javax.swing.JScrollPane(); this.jList2 = new javax.swing.JList(); + this.jLabel2 = new javax.swing.JLabel(); setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE); @@ -154,6 +153,8 @@ public void valueChanged(javax.swing.event.ListSelectionEvent evt) { } }); + jLabel1.setText("Distribution Change"); + jList2.addListSelectionListener(new javax.swing.event.ListSelectionListener() { @Override public void valueChanged(javax.swing.event.ListSelectionEvent evt) { @@ -165,6 +166,8 @@ public void valueChanged(javax.swing.event.ListSelectionEvent evt) { } }); + jLabel2.setText("Shuffle"); + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); getContentPane().setLayout(layout); layout.setHorizontalGroup( @@ -175,9 +178,13 @@ public void valueChanged(javax.swing.event.ListSelectionEvent evt) { .addGap(10, 10, 10)) .addGroup(layout.createSequentialGroup() .addGap(75, 75, 75) - .addComponent(this.jScrollPane1, 175, 175, 175) + .addGroup(layout.createParallelGroup(GroupLayout.Alignment.CENTER) + .addComponent(this.jLabel1) + .addComponent(this.jScrollPane1, 175, 175, 175)) .addGap(75, 75, 75) - .addComponent(this.jScrollPane2, 175, 175, 175) + .addGroup(layout.createParallelGroup(GroupLayout.Alignment.CENTER) + .addComponent(this.jLabel2) + .addComponent(this.jScrollPane2, 175, 175, 175)) .addGap(75, 75, 75)) .addGroup(layout.createSequentialGroup() .addGap(150, 150, 150) @@ -192,8 +199,12 @@ public void valueChanged(javax.swing.event.ListSelectionEvent evt) { .addComponent(this.shuffleEditor) .addGap(10, 10, 10) .addGroup(layout.createParallelGroup(GroupLayout.Alignment.CENTER) - .addComponent(this.jScrollPane1, 175, 175, 175) - .addComponent(this.jScrollPane2, 175, 175, 175)) + .addGroup(layout.createSequentialGroup() + .addComponent(this.jLabel1) + .addComponent(this.jScrollPane1, 175, 175, 175)) + .addGroup(layout.createSequentialGroup() + .addComponent(this.jLabel2) + .addComponent(this.jScrollPane2, 175, 175, 175))) .addGap(10, 10, 10) .addGroup(layout.createParallelGroup(GroupLayout.Alignment.CENTER) .addComponent(this.jButton1) @@ -273,9 +284,11 @@ private void jList2ValueChanged(javax.swing.event.ListSelectionEvent evt) throws @SuppressWarnings("rawtypes") private javax.swing.JList jList1; private javax.swing.JScrollPane jScrollPane1; + private javax.swing.JLabel jLabel1; @SuppressWarnings("rawtypes") private javax.swing.JList jList2; private javax.swing.JScrollPane jScrollPane2; + private javax.swing.JLabel jLabel2; // End of variables declaration//GEN-END:variables } \ No newline at end of file From f4abca3aa035d32238ccab7f36d5a881cf13d3af Mon Sep 17 00:00:00 2001 From: "Josiah (Gaming32) Glosson" Date: Mon, 26 Jul 2021 14:46:17 -0500 Subject: [PATCH 12/40] Add warped distributions --- Noisily sorted.txt | 3 +- src/dialogs/ShuffleDialog.java | 49 +++++++++++++++++++++++- src/utils/ShuffleInfo.java | 37 ++++++++++++++---- src/utils/shuffle_utils/GraphReader.java | 32 +++++++++++++++- src/utils/shuffle_utils/GraphWriter.java | 5 +++ 5 files changed, 116 insertions(+), 10 deletions(-) diff --git a/Noisily sorted.txt b/Noisily sorted.txt index bba9d73c..00d2e2be 100644 --- a/Noisily sorted.txt +++ b/Noisily sorted.txt @@ -1,4 +1,5 @@ -N true RANDOM 56 71 0 1 +1 +N true RANDOM true 56 71 0 1 N false SORTED 363 125 1 -1 C 0 1 C 1 2 diff --git a/src/dialogs/ShuffleDialog.java b/src/dialogs/ShuffleDialog.java index 340b4424..0361f47c 100644 --- a/src/dialogs/ShuffleDialog.java +++ b/src/dialogs/ShuffleDialog.java @@ -83,6 +83,7 @@ public ShuffleDialog(ArrayManager ArrayManager, JFrame frame, UtilFrame utilFram bypassEvents = true; this.shuffleEditor.graph = ArrayManager.getShuffle(); jList1.setListData(ArrayManager.getDistributionIDs()); + jList3.setListData(ArrayManager.getDistributionIDs()); jList2.setListData(ArrayManager.getShuffleIDs()); bypassEvents = false; @@ -114,6 +115,10 @@ private void initComponents() { this.jList1 = new javax.swing.JList(); this.jLabel1 = new javax.swing.JLabel(); + this.jScrollPane3 = new javax.swing.JScrollPane(); + this.jList3 = new javax.swing.JList(); + this.jLabel3 = new javax.swing.JLabel(); + this.jScrollPane2 = new javax.swing.JScrollPane(); this.jList2 = new javax.swing.JList(); this.jLabel2 = new javax.swing.JLabel(); @@ -138,6 +143,9 @@ public void actionPerformed(java.awt.event.ActionEvent evt) { jScrollPane1.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); jScrollPane1.setViewportView(this.jList1); + + jScrollPane3.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); + jScrollPane3.setViewportView(this.jList3); jScrollPane2.setViewportView(this.jList2); jScrollPane2.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); @@ -155,6 +163,19 @@ public void valueChanged(javax.swing.event.ListSelectionEvent evt) { jLabel1.setText("Distribution Change"); + jList3.addListSelectionListener(new javax.swing.event.ListSelectionListener() { + @Override + public void valueChanged(javax.swing.event.ListSelectionEvent evt) { + try { + jList3ValueChanged(evt); + } catch (Exception e) { + JErrorPane.invokeErrorMessage(e); + } + } + }); + + jLabel3.setText("Distribution Warp"); + jList2.addListSelectionListener(new javax.swing.event.ListSelectionListener() { @Override public void valueChanged(javax.swing.event.ListSelectionEvent evt) { @@ -182,6 +203,10 @@ public void valueChanged(javax.swing.event.ListSelectionEvent evt) { .addComponent(this.jLabel1) .addComponent(this.jScrollPane1, 175, 175, 175)) .addGap(75, 75, 75) + .addGroup(layout.createParallelGroup(GroupLayout.Alignment.CENTER) + .addComponent(this.jLabel3) + .addComponent(this.jScrollPane3, 175, 175, 175)) + .addGap(75, 75, 75) .addGroup(layout.createParallelGroup(GroupLayout.Alignment.CENTER) .addComponent(this.jLabel2) .addComponent(this.jScrollPane2, 175, 175, 175)) @@ -202,6 +227,9 @@ public void valueChanged(javax.swing.event.ListSelectionEvent evt) { .addGroup(layout.createSequentialGroup() .addComponent(this.jLabel1) .addComponent(this.jScrollPane1, 175, 175, 175)) + .addGroup(layout.createSequentialGroup() + .addComponent(this.jLabel3) + .addComponent(this.jScrollPane3, 175, 175, 175)) .addGroup(layout.createSequentialGroup() .addComponent(this.jLabel2) .addComponent(this.jScrollPane2, 175, 175, 175))) @@ -254,13 +282,27 @@ private void jList1ValueChanged(javax.swing.event.ListSelectionEvent evt) throws int selection = jList1.getSelectedIndex(); Distributions[] distributions = ArrayManager.getDistributions(); if (selection >= 0 && selection < distributions.length) - shuffleEditor.graph.addDisconnected(new ShuffleInfo(distributions[selection]), 250, 250); + shuffleEditor.graph.addDisconnected(new ShuffleInfo(distributions[selection], false), 250, 250); shuffleEditor.repaint(); bypassEvents = true; jList1.clearSelection(); bypassEvents = false; }//GEN-LAST:event_jList1ValueChanged + private void jList3ValueChanged(javax.swing.event.ListSelectionEvent evt) throws Exception {//GEN-FIRST:event_jList1ValueChanged + // TODO add your handling code here: + if (bypassEvents) + return; + int selection = jList3.getSelectedIndex(); + Distributions[] distributions = ArrayManager.getDistributions(); + if (selection >= 0 && selection < distributions.length) + shuffleEditor.graph.addDisconnected(new ShuffleInfo(distributions[selection], true), 250, 250); + shuffleEditor.repaint(); + bypassEvents = true; + jList3.clearSelection(); + bypassEvents = false; + }//GEN-LAST:event_jList1ValueChanged + private void jList2ValueChanged(javax.swing.event.ListSelectionEvent evt) throws Exception {//GEN-FIRST:event_jList1ValueChanged // TODO add your handling code here: if (bypassEvents) @@ -286,6 +328,11 @@ private void jList2ValueChanged(javax.swing.event.ListSelectionEvent evt) throws private javax.swing.JScrollPane jScrollPane1; private javax.swing.JLabel jLabel1; + @SuppressWarnings("rawtypes") + private javax.swing.JList jList3; + private javax.swing.JScrollPane jScrollPane3; + private javax.swing.JLabel jLabel3; + @SuppressWarnings("rawtypes") private javax.swing.JList jList2; private javax.swing.JScrollPane jScrollPane2; diff --git a/src/utils/ShuffleInfo.java b/src/utils/ShuffleInfo.java index 37a71b0e..1bcd7acd 100644 --- a/src/utils/ShuffleInfo.java +++ b/src/utils/ShuffleInfo.java @@ -9,25 +9,36 @@ final public class ShuffleInfo { final boolean isDistribution; final Distributions distribution; final Shuffles shuffle; + final boolean warpDistribution; - public ShuffleInfo(Distributions distribution) { + public ShuffleInfo(Distributions distribution, boolean warpDistribution) { this.isDistribution = true; this.distribution = distribution; this.shuffle = null; + this.warpDistribution = warpDistribution; + } + + public ShuffleInfo(Distributions distribution) { + this(distribution, false); } public ShuffleInfo(Shuffles shuffle) { this.isDistribution = false; this.distribution = null; this.shuffle = shuffle; + this.warpDistribution = false; } - public static ShuffleInfo[] fromDistributionIterable(Iterable iterable) { + public static ShuffleInfo[] fromDistributionIterable(Iterable iterable, boolean warped) { List result = new ArrayList<>(); - iterable.forEach(dist -> result.add(new ShuffleInfo(dist))); + iterable.forEach(dist -> result.add(new ShuffleInfo(dist, warped))); return result.toArray(new ShuffleInfo[0]); } + public static ShuffleInfo[] fromDistributionIterable(Iterable iterable) { + return fromDistributionIterable(iterable, false); + } + public static ShuffleInfo[] fromShuffleIterable(Iterable iterable) { List result = new ArrayList<>(); iterable.forEach(shuff -> result.add(new ShuffleInfo(shuff))); @@ -41,11 +52,15 @@ public boolean isDistribution() { public Distributions getDistribution() { return this.distribution; } - + public Shuffles getShuffle() { return this.shuffle; } + public boolean isDistributionWarped() { + return this.warpDistribution; + } + public boolean equals(Object o) { if (o == null) { return false; @@ -56,7 +71,7 @@ public boolean equals(Object o) { return false; } if (isDistribution) { - return this.distribution == other.distribution; + return this.distribution == other.distribution && this.warpDistribution == other.warpDistribution; } else { return this.shuffle == other.shuffle; } @@ -70,6 +85,8 @@ public boolean equals(Object o) { public String getName() { if (this.isDistribution) { + if (warpDistribution) + return "Warped " + this.distribution.getName(); return this.distribution.getName(); } return this.shuffle.getName(); @@ -84,8 +101,14 @@ public void shuffle(int[] array, ArrayVisualizer arrayVisualizer) { int[] tmp = new int[currentLen]; Writes.arraycopy(array, 0, copy, 0, currentLen, sleep, true, true); this.distribution.initializeArray(tmp, arrayVisualizer); - for (int i = 0; i < currentLen; i++) { - Writes.write(array, i, copy[tmp[i]], sleep, true, false); + if (warpDistribution) { + for (int i = 0; i < currentLen; i++) { + Writes.write(array, i, copy[tmp[i]], sleep, true, false); + } + } else { + for (int i = 0; i < currentLen; i++) { + Writes.write(array, i, tmp[copy[i]], sleep, true, false); + } } } else { Delays Delays = arrayVisualizer.getDelays(); diff --git a/src/utils/shuffle_utils/GraphReader.java b/src/utils/shuffle_utils/GraphReader.java index d48b62ab..5f831007 100644 --- a/src/utils/shuffle_utils/GraphReader.java +++ b/src/utils/shuffle_utils/GraphReader.java @@ -3,8 +3,13 @@ import java.io.File; import java.io.IOException; import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; import java.util.List; import java.util.Scanner; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; import utils.Distributions; import utils.ShuffleGraph; @@ -49,12 +54,23 @@ public PartialElement(int left, int right) { } } + public final static int[] COMPATIBLE_VERSIONS = {0, 1}; + static Set compatibleVersionsSet; + Scanner scanner; ShuffleGraph result; List partialNodes; + int version; public GraphReader() { result = null; + if (compatibleVersionsSet == null) { + compatibleVersionsSet = new HashSet<>( + Arrays.stream(COMPATIBLE_VERSIONS) + .boxed() + .collect(Collectors.toList()) + ); + } } public ShuffleGraph getResult() { @@ -92,6 +108,13 @@ public ShuffleGraph read(Scanner scanner) throws IOException, MalformedGraphFile } private void read() throws IOException, MalformedGraphFileException { + version = scanner.hasNextInt() ? scanner.nextInt() : 0; + if (!compatibleVersionsSet.contains(version)) { + throw new MalformedGraphFileException("Unsupported version for reading: " + version + " (Supported versions: " + + Arrays.stream(COMPATIBLE_VERSIONS) + .mapToObj(String::valueOf) + .collect(Collectors.joining(", ", "{", "}")) + ")"); + } result = new ShuffleGraph(); partialNodes = new ArrayList<>(); @@ -139,8 +162,15 @@ private void readNode() throws MalformedGraphFileException { ShuffleInfo shuffleInfo; try { if (isDistribution) { + boolean isDistributionWarped = false; + if (version > 0) { + if (!scanner.hasNextBoolean()) { + throw new MalformedGraphFileException("Expected isDistributionWarped in node declaration"); + } + isDistributionWarped = scanner.nextBoolean(); + } Distributions distribution = Distributions.valueOf(name); - shuffleInfo = new ShuffleInfo(distribution); + shuffleInfo = new ShuffleInfo(distribution, isDistributionWarped); } else { Shuffles shuffle = Shuffles.valueOf(name); shuffleInfo = new ShuffleInfo(shuffle); diff --git a/src/utils/shuffle_utils/GraphWriter.java b/src/utils/shuffle_utils/GraphWriter.java index a65f88b6..5e11d710 100644 --- a/src/utils/shuffle_utils/GraphWriter.java +++ b/src/utils/shuffle_utils/GraphWriter.java @@ -9,6 +9,8 @@ import utils.ShuffleGraph; public final class GraphWriter { + final public static int VERSION = 1; + ShuffleGraph graph; public GraphWriter(ShuffleGraph graph) { @@ -39,12 +41,15 @@ public void write(FileWriter writer) throws IOException { } connectionMap.put(null, -1); + writer.write(VERSION + "\n"); + for (int i = 1; i < graph.nodes.size(); i++) { Node node = graph.nodes.get(i); writer.write("N "); if (node.getValue().isDistribution()) { writer.write("true "); writer.write(node.getValue().getDistribution().name() + " "); + writer.write(node.getValue().isDistributionWarped() + " "); } else { writer.write("false "); writer.write(node.getValue().getShuffle().name() + " "); From b9f03fc09178fe28c9c1efbcf6382eb10d7be8e9 Mon Sep 17 00:00:00 2001 From: "Josiah (Gaming32) Glosson" Date: Tue, 27 Jul 2021 14:55:36 -0500 Subject: [PATCH 13/40] Reimplement and deprecate old method --- src/main/ArrayManager.java | 17 +++++++++++++++++ src/main/ArrayVisualizer.java | 2 -- src/panels/ShufflePanel.java | 10 ---------- src/utils/ShuffleGraph.java | 4 ++++ 4 files changed, 21 insertions(+), 12 deletions(-) diff --git a/src/main/ArrayManager.java b/src/main/ArrayManager.java index 8440e0ab..bb03071e 100644 --- a/src/main/ArrayManager.java +++ b/src/main/ArrayManager.java @@ -124,12 +124,29 @@ public Shuffles[] getShuffles() { public ShuffleGraph getShuffle() { return this.shuffle; } + + /** + * @deprecated This method is deprecatated. Please use {@link #setShuffleSingle(Shuffles)} or {@link #setShuffle(ShuffleGraph)} instead. + * @see #setShuffleSingle(Shuffles) + * @see #setShuffle(ShuffleGraph) + */ + public void setShuffle(Shuffles choice) { + this.setShuffleSingle(choice); + } + public void setShuffle(ShuffleGraph graph) { this.shuffle = graph; } + public void setShuffleSingle(Shuffles shuffle) { this.setShuffle(ShuffleGraph.single(shuffle)); } + public void setShuffleSingle(Distributions distribution) { + this.setShuffle(ShuffleGraph.single(distribution)); + } + public void setShuffleSingle(Distributions distribution, boolean warped) { + this.setShuffle(ShuffleGraph.single(distribution, warped)); + } public String[] getDistributionIDs() { return this.distributionIDs; diff --git a/src/main/ArrayVisualizer.java b/src/main/ArrayVisualizer.java index fcad3640..891fb9f1 100644 --- a/src/main/ArrayVisualizer.java +++ b/src/main/ArrayVisualizer.java @@ -22,8 +22,6 @@ import java.awt.event.KeyListener; import java.awt.event.WindowEvent; import java.io.File; -import java.io.FileWriter; -import java.io.IOException; import java.math.RoundingMode; import java.text.DecimalFormat; import java.text.DecimalFormatSymbols; diff --git a/src/panels/ShufflePanel.java b/src/panels/ShufflePanel.java index 5eac9926..fe70dc2b 100644 --- a/src/panels/ShufflePanel.java +++ b/src/panels/ShufflePanel.java @@ -11,27 +11,17 @@ import java.awt.event.MouseEvent; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; -import java.util.Arrays; import javax.swing.JPanel; import javax.swing.SwingUtilities; import utils.ShuffleGraph; -import utils.ShuffleInfo; -import utils.Shuffles; public class ShufflePanel extends JPanel implements KeyListener { int prevX, prevY; public ShuffleGraph graph; public ShufflePanel() { - // this.graph = new ShuffleGraph( - // ShuffleInfo.fromShuffleIterable( - // Arrays.stream( - // new Shuffles[] {Shuffles.RANDOM, Shuffles.REVERSE, Shuffles.ALMOST, Shuffles.ALREADY} - // )::iterator - // ) - // ); setPreferredSize(new Dimension(700, 450)); MouseHandler handler = new MouseHandler(); addMouseListener(handler); diff --git a/src/utils/ShuffleGraph.java b/src/utils/ShuffleGraph.java index e810ba18..8c2a3ec7 100644 --- a/src/utils/ShuffleGraph.java +++ b/src/utils/ShuffleGraph.java @@ -50,6 +50,10 @@ public static ShuffleGraph single(Distributions distribution) { return single(new ShuffleInfo(distribution)); } + public static ShuffleGraph single(Distributions distribution, boolean warped) { + return single(new ShuffleInfo(distribution, warped)); + } + public void shuffleArray(int[] array, ArrayVisualizer arrayVisualizer) { for (ShuffleInfo shuffle : this) { shuffle.shuffle(array, arrayVisualizer); From 0353c34a9af51428324bcb6fe1efdbbb4354b1de Mon Sep 17 00:00:00 2001 From: "Josiah (Gaming32) Glosson" Date: Tue, 27 Jul 2021 15:15:45 -0500 Subject: [PATCH 14/40] GUI improvements --- src/dialogs/ShuffleDialog.java | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/dialogs/ShuffleDialog.java b/src/dialogs/ShuffleDialog.java index 0361f47c..bc70bdc3 100644 --- a/src/dialogs/ShuffleDialog.java +++ b/src/dialogs/ShuffleDialog.java @@ -4,6 +4,7 @@ */ package dialogs; +import java.awt.Dimension; import java.io.IOException; import javax.swing.GroupLayout; @@ -87,6 +88,7 @@ public ShuffleDialog(ArrayManager ArrayManager, JFrame frame, UtilFrame utilFram jList2.setListData(ArrayManager.getShuffleIDs()); bypassEvents = false; + setMinimumSize(new Dimension(580, 300)); setAlwaysOnTop(false); reposition(); setVisible(true); @@ -96,7 +98,6 @@ public ShuffleDialog(ArrayManager ArrayManager, JFrame frame, UtilFrame utilFram public void reposition() { } - /** * This method is called from within the constructor to initialize the form. * WARNING: Do NOT modify this code. The content of this method is always @@ -198,19 +199,19 @@ public void valueChanged(javax.swing.event.ListSelectionEvent evt) { .addComponent(this.shuffleEditor) .addGap(10, 10, 10)) .addGroup(layout.createSequentialGroup() - .addGap(75, 75, 75) + .addGap(10, 75, 75) .addGroup(layout.createParallelGroup(GroupLayout.Alignment.CENTER) .addComponent(this.jLabel1) .addComponent(this.jScrollPane1, 175, 175, 175)) - .addGap(75, 75, 75) + .addGap(10, 75, 75) .addGroup(layout.createParallelGroup(GroupLayout.Alignment.CENTER) .addComponent(this.jLabel3) .addComponent(this.jScrollPane3, 175, 175, 175)) - .addGap(75, 75, 75) + .addGap(10, 75, 75) .addGroup(layout.createParallelGroup(GroupLayout.Alignment.CENTER) .addComponent(this.jLabel2) .addComponent(this.jScrollPane2, 175, 175, 175)) - .addGap(75, 75, 75)) + .addGap(10, 75, 75)) .addGroup(layout.createSequentialGroup() .addGap(150, 150, 150) .addComponent(this.jButton1) From bc05cb33a90e12ec8180f6ca7e0585f789359046 Mon Sep 17 00:00:00 2001 From: "Josiah (Gaming32) Glosson" Date: Tue, 27 Jul 2021 15:16:03 -0500 Subject: [PATCH 15/40] Add dragging limit for nodes --- src/utils/shuffle_utils/Node.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/utils/shuffle_utils/Node.java b/src/utils/shuffle_utils/Node.java index 54d7ad8d..ad22a9b5 100644 --- a/src/utils/shuffle_utils/Node.java +++ b/src/utils/shuffle_utils/Node.java @@ -77,6 +77,9 @@ public void draw(Graphics2D g) { public void drag(Point rel) { this.x += rel.getX(); + if (this.x < -WIDTH / 2) { + this.x = -WIDTH / 2; + } this.y += rel.getY(); } From 3e00fb7bc3de05d6166c485cbdf94020ed126091 Mon Sep 17 00:00:00 2001 From: "Josiah (Gaming32) Glosson" Date: Tue, 27 Jul 2021 15:50:49 -0500 Subject: [PATCH 16/40] Add panning using middle click --- src/panels/ShufflePanel.java | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/src/panels/ShufflePanel.java b/src/panels/ShufflePanel.java index fe70dc2b..bc490c02 100644 --- a/src/panels/ShufflePanel.java +++ b/src/panels/ShufflePanel.java @@ -18,7 +18,8 @@ import utils.ShuffleGraph; public class ShufflePanel extends JPanel implements KeyListener { - int prevX, prevY; + int camX = 0, camY = 0; + int prevX = 0, prevY = 0; public ShuffleGraph graph; public ShufflePanel() { @@ -36,6 +37,7 @@ protected void paintComponent(Graphics g) { g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g.setColor(new Color(128, 128, 128)); g.fillRect(0, 0, getWidth(), getHeight()); + g.translate(camX, camY); graph.draw(g2d); } @@ -57,10 +59,11 @@ protected class MouseHandler extends MouseAdapter { @Override public void mousePressed(MouseEvent e) { requestFocus(); // Java doesn't handle this for us? + prevX = e.getX(); + prevY = e.getY(); if (SwingUtilities.isLeftMouseButton(e)) { - graph.select(e.getPoint()); - prevX = e.getX(); - prevY = e.getY(); + Point grab = new Point(e.getX() - camX, e.getY() - camY); + graph.select(grab); repaint(); } } @@ -75,12 +78,19 @@ public void mouseReleased(MouseEvent e) { @Override public void mouseDragged(MouseEvent e) { - if (SwingUtilities.isLeftMouseButton(e)) { + if (SwingUtilities.isMiddleMouseButton(e)) { + camX += e.getX() - prevX; + camY += e.getY() - prevY; + if (camX > 0) { + camX = 0; + } + repaint(); + } else if (SwingUtilities.isLeftMouseButton(e)) { graph.drag(new Point(e.getX() - prevX, e.getY() - prevY)); - prevX = e.getX(); - prevY = e.getY(); repaint(); } + prevX = e.getX(); + prevY = e.getY(); } } } From 383202885bc042434844a65e4f70732e8104e26d Mon Sep 17 00:00:00 2001 From: "Josiah (Gaming32) Glosson" Date: Tue, 27 Jul 2021 16:03:13 -0500 Subject: [PATCH 17/40] Revamp scrambled tail/head --- src/utils/Shuffles.java | 34 +++++++++++++++++++++++++--------- 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/src/utils/Shuffles.java b/src/utils/Shuffles.java index 7ed8a549..e2e8c4a2 100644 --- a/src/utils/Shuffles.java +++ b/src/utils/Shuffles.java @@ -140,11 +140,19 @@ public String getName() { public void shuffleArray(int[] array, ArrayVisualizer ArrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { int currentLen = ArrayVisualizer.getCurrentLength(); boolean delay = ArrayVisualizer.shuffleEnabled(); - int len = Math.max(1, currentLen/7); - - this.shuffle(array, 0, currentLen, delay ? 0.5 : 0, Writes); - Highlights.clearMark(2); - this.sort(array, 0, currentLen-len, delay ? 0.5 : 0, Writes); + + Random random = new Random(); + int[] aux = new int[currentLen]; + int i = 0, j = 0, k = 0; + while (i < currentLen) { + Highlights.markArray(2, i); + if (random.nextDouble() < 1/7d) + Writes.write(aux, k++, array[i++], delay ? 1 : 0, false, true); + else + Writes.write(array, j++, array[i++], delay ? 1 : 0, true, false); + } + Writes.arraycopy(aux, 0, array, j, k, delay ? 1 : 0, true, false); + shuffle(array, j, currentLen, delay ? 2 : 0, Writes); } }, SHUFFLED_HEAD { @@ -155,11 +163,19 @@ public String getName() { public void shuffleArray(int[] array, ArrayVisualizer ArrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { int currentLen = ArrayVisualizer.getCurrentLength(); boolean delay = ArrayVisualizer.shuffleEnabled(); - int len = Math.max(1, currentLen/7); - this.shuffle(array, 0, currentLen, delay ? 0.5 : 0, Writes); - Highlights.clearMark(2); - this.sort(array, len, currentLen, delay ? 0.5 : 0, Writes); + Random random = new Random(); + int[] aux = new int[currentLen]; + int i = currentLen - 1, j = currentLen - 1, k = 0; + while (i >= 0) { + Highlights.markArray(2, i); + if (random.nextDouble() < 1/7d) + Writes.write(aux, k++, array[i--], delay ? 1 : 0, false, true); + else + Writes.write(array, j--, array[i--], delay ? 1 : 0, true, false); + } + Writes.reversearraycopy(aux, 0, array, 0, k, delay ? 1 : 0, true, false); + shuffle(array, 0, j, delay ? 2 : 0, Writes); } }, MOVED_ELEMENT { From acb0175cb49ec7edbbfc1d6ff4917577e049798c Mon Sep 17 00:00:00 2001 From: "Josiah (Gaming32) Glosson" Date: Tue, 27 Jul 2021 16:17:22 -0500 Subject: [PATCH 18/40] Remove some redundant shuffles --- src/utils/Shuffles.java | 72 ++++------------------------------------- 1 file changed, 6 insertions(+), 66 deletions(-) diff --git a/src/utils/Shuffles.java b/src/utils/Shuffles.java index e2e8c4a2..020229b0 100644 --- a/src/utils/Shuffles.java +++ b/src/utils/Shuffles.java @@ -106,18 +106,6 @@ public void shuffleArray(int[] array, ArrayVisualizer ArrayVisualizer, Delays De this.sort(array, 0, currentLen, delay ? 1 : 0, Writes); } }, - REV_SORTED { - public String getName() { - return "Reverse Sorted"; - } - @Override - public void shuffleArray(int[] array, ArrayVisualizer ArrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { - int currentLen = ArrayVisualizer.getCurrentLength(); - boolean delay = ArrayVisualizer.shuffleEnabled(); - this.sort(array, 0, currentLen, delay ? 1 : 0, Writes); - Writes.reversal(array, 0, currentLen-1, delay ? 1 : 0, true, false); - } - }, NAIVE { public String getName() { return "Naive Randomly"; @@ -317,52 +305,6 @@ public void shuffleArray(int[] array, ArrayVisualizer ArrayVisualizer, Delays De Writes.write(array, i, temp[i], delay ? 1 : 0, true, false); } }, - REV_FINAL_MERGE { - public String getName() { - return "Reversed Final Merge"; - } - @Override - public void shuffleArray(int[] array, ArrayVisualizer ArrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { - int currentLen = ArrayVisualizer.getCurrentLength(); - boolean delay = ArrayVisualizer.shuffleEnabled(); - int count = 2; - - int k = 0; - int[] temp = new int[currentLen]; - - for(int j = 0; j < count; j++) - for(int i = j; i < currentLen; i+=count) - Writes.write(temp, k++, array[i], 0, false, true); - - for(int i = 0; i < currentLen; i++) - Writes.write(array, i, temp[i], delay ? 1 : 0, true, false); - - Writes.reversal(array, 0, currentLen-1, delay ? 1 : 0, true, false); - } - }, - REV_SAWTOOTH { - public String getName() { - return "Reversed Sawtooth"; - } - @Override - public void shuffleArray(int[] array, ArrayVisualizer ArrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { - int currentLen = ArrayVisualizer.getCurrentLength(); - boolean delay = ArrayVisualizer.shuffleEnabled(); - int count = 4; - - int k = 0; - int[] temp = new int[currentLen]; - - for(int j = 0; j < count; j++) - for(int i = j; i < currentLen; i+=count) - Writes.write(temp, k++, array[i], 0, false, true); - - for(int i = 0; i < currentLen; i++) - Writes.write(array, i, temp[i], delay ? 1 : 0, true, false); - - Writes.reversal(array, 0, currentLen-1, delay ? 1 : 0, true, false); - } - }, ORGAN { public String getName() { return "Pipe Organ"; @@ -654,30 +596,28 @@ public void shuffleArray(int[] array, ArrayVisualizer ArrayVisualizer, Delays De heapSort.makeHeap(array, 0, currentLen, delay ? 1 : 0); } }, - REV_SMOOTH { + SMOOTH { public String getName() { - return "Reversed Smoothified"; + return "Smoothified"; } @Override public void shuffleArray(int[] array, ArrayVisualizer ArrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { int currentLen = ArrayVisualizer.getCurrentLength(); boolean delay = ArrayVisualizer.shuffleEnabled(); - - Writes.reversal(array, 0, currentLen-1, delay ? 1 : 0, true, false); + SmoothSort smoothSort = new SmoothSort(ArrayVisualizer); smoothSort.smoothHeapify(array, currentLen); } }, - REV_POPLAR { + POPLAR { public String getName() { - return "Reversed Poplarified"; + return "Poplarified"; } @Override public void shuffleArray(int[] array, ArrayVisualizer ArrayVisualizer, Delays Delays, Highlights Highlights, Writes Writes) { int currentLen = ArrayVisualizer.getCurrentLength(); boolean delay = ArrayVisualizer.shuffleEnabled(); - - Writes.reversal(array, 0, currentLen-1, delay ? 1 : 0, true, false); + PoplarHeapSort poplarHeapSort = new PoplarHeapSort(ArrayVisualizer); poplarHeapSort.poplarHeapify(array, 0, currentLen); } From 202fa4dd1dc55dd8e2a3f9960de61094a188f066 Mon Sep 17 00:00:00 2001 From: "Josiah (Gaming32) Glosson" Date: Wed, 28 Jul 2021 16:20:14 -0500 Subject: [PATCH 19/40] Fix infinite shuffle loops --- src/utils/ShuffleGraph.java | 2 ++ src/utils/shuffle_utils/Connection.java | 10 ++++++++++ src/utils/shuffle_utils/Node.java | 8 ++------ 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/src/utils/ShuffleGraph.java b/src/utils/ShuffleGraph.java index 8c2a3ec7..dcafaffd 100644 --- a/src/utils/ShuffleGraph.java +++ b/src/utils/ShuffleGraph.java @@ -112,6 +112,7 @@ public void select(Point pos) { for (int i = 0; i < this.connections.size(); i++) { Connection conn = this.connections.get(i - removed); if (conn.from == node) { + conn.remove(); this.connections.remove(i - removed); removed++; } @@ -133,6 +134,7 @@ public void endConnection() { if (this.dragCandidate != null) { this.dragging.finishDragging(this.dragCandidate); } else { + this.dragging.remove(); this.connections.remove(this.dragging); } this.dragging = null; diff --git a/src/utils/shuffle_utils/Connection.java b/src/utils/shuffle_utils/Connection.java index 98cc795b..d3d396f3 100644 --- a/src/utils/shuffle_utils/Connection.java +++ b/src/utils/shuffle_utils/Connection.java @@ -47,6 +47,15 @@ public void draw(Graphics2D g) { } } + public void remove() { + if (this.from != null) { + this.from.postConnection = null; + } + if (this.to != null) { + this.to.preConnection = null; + } + } + public void finishDragging(Node other) { this.to = other; other.preConnection = this; @@ -58,6 +67,7 @@ public void finishDragging(Node other) { continue; } if (conn.to == other) { + conn.remove(); connections.remove(i - removed); removed++; } diff --git a/src/utils/shuffle_utils/Node.java b/src/utils/shuffle_utils/Node.java index ad22a9b5..2bb3e2d3 100644 --- a/src/utils/shuffle_utils/Node.java +++ b/src/utils/shuffle_utils/Node.java @@ -98,20 +98,16 @@ public void delete() { this.graph.nodes.remove(this); if (this.preConnection != null) { if (this.postConnection == null) { + this.preConnection.remove(); this.graph.connections.remove(this.preConnection); - if (this.preConnection.from != null) { - this.preConnection.from.postConnection = null; - } } else { this.preConnection.to = this.postConnection.to; } } if (this.postConnection != null) { if (this.preConnection == null) { + this.postConnection.remove(); this.graph.connections.remove(this.postConnection); - if (this.postConnection.to != null) { - this.postConnection.to.preConnection = null; - } } else { this.postConnection.from = this.preConnection.from; } From 80acaebabdfcd083e321f62a44f9a5c018e8bf0e Mon Sep 17 00:00:00 2001 From: "Josiah (Gaming32) Glosson" Date: Wed, 28 Jul 2021 16:36:28 -0500 Subject: [PATCH 20/40] Improve the Choose Shuffle dialog --- src/prompts/ShufflePrompt.java | 31 ++++++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/src/prompts/ShufflePrompt.java b/src/prompts/ShufflePrompt.java index 06c675c3..ae1386c3 100644 --- a/src/prompts/ShufflePrompt.java +++ b/src/prompts/ShufflePrompt.java @@ -4,6 +4,9 @@ */ package prompts; +import java.util.Arrays; + +import javax.swing.DefaultListModel; import javax.swing.JFrame; import dialogs.ShuffleDialog; @@ -57,6 +60,7 @@ final public class ShufflePrompt extends javax.swing.JFrame implements AppFrame private JFrame Frame; private UtilFrame UtilFrame; + private DefaultListModel shuffleModel; private boolean initializing; /** @@ -80,14 +84,20 @@ public ShufflePrompt(ArrayManager ArrayManager, JFrame frame, UtilFrame utilFram break; } } - jList2.setListData(ArrayManager.getShuffleIDs()); - for(int i = 0; i < ArrayManager.getShuffles().length; i++) { - if(ArrayManager.containsShuffle(ArrayManager.getShuffles()[i])) { - jList2.setSelectedIndex(i); - break; + shuffleModel = new DefaultListModel<>(); + jList2.setModel(shuffleModel); + Arrays.stream(ArrayManager.getShuffleIDs()).forEach(shuffleModel::addElement); + if (ArrayManager.getShuffle().size() > 1) { + shuffleModel.add(0, "Advanced"); + jList2.setSelectedIndex(0); + } else { + for(int i = 0; i < ArrayManager.getShuffles().length; i++) { + if(ArrayManager.containsShuffle(ArrayManager.getShuffles()[i])) { + jList2.setSelectedIndex(i); + break; + } } } - // this.shuffleEditor1.graph = ArrayManager.getShuffle(); initializing = false; reposition(); @@ -211,7 +221,9 @@ public void valueChanged(javax.swing.event.ListSelectionEvent evt) { }// //GEN-END:initComponents private void jButton1ActionPerformed() {//GEN-FIRST:event_jList1ValueChanged - ShuffleDialog editor = new ShuffleDialog(ArrayManager, this, UtilFrame); + UtilFrame.jButton6ResetText(); + dispose(); + new ShuffleDialog(ArrayManager, this, UtilFrame); }//GEN-LAST:event_jList1ValueChanged private void jList1ValueChanged(javax.swing.event.ListSelectionEvent evt) throws Exception {//GEN-FIRST:event_jList1ValueChanged @@ -229,6 +241,11 @@ private void jList2ValueChanged(javax.swing.event.ListSelectionEvent evt) throws if (initializing) return; int selection = jList2.getSelectedIndex(); + if (shuffleModel.getElementAt(0).equals("Advanced")) { + if (selection == 0) return; + shuffleModel.remove(0); + selection--; + } Shuffles[] shuffles = ArrayManager.getShuffles(); if (selection >= 0 && selection < shuffles.length) ArrayManager.setShuffleSingle(shuffles[selection]); From fcec38644e7539ee4e35a0d787aa3c199aef7b9c Mon Sep 17 00:00:00 2001 From: "Josiah (Gaming32) Glosson" Date: Wed, 28 Jul 2021 16:46:02 -0500 Subject: [PATCH 21/40] Fix bug(s) --- src/utils/ShuffleGraph.java | 7 +++++-- src/utils/shuffle_utils/Connection.java | 2 +- src/utils/shuffle_utils/Node.java | 4 ++-- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/utils/ShuffleGraph.java b/src/utils/ShuffleGraph.java index dcafaffd..5866a66b 100644 --- a/src/utils/ShuffleGraph.java +++ b/src/utils/ShuffleGraph.java @@ -112,8 +112,8 @@ public void select(Point pos) { for (int i = 0; i < this.connections.size(); i++) { Connection conn = this.connections.get(i - removed); if (conn.from == node) { - conn.remove(); this.connections.remove(i - removed); + conn.remove(); removed++; } } @@ -134,8 +134,8 @@ public void endConnection() { if (this.dragCandidate != null) { this.dragging.finishDragging(this.dragCandidate); } else { - this.dragging.remove(); this.connections.remove(this.dragging); + this.dragging.remove(); } this.dragging = null; this.dragCandidate = null; @@ -203,6 +203,9 @@ Node add(ShuffleInfo shuffle, Node after) { after.postConnection = new Connection(after, newNode); this.connections.add(after.postConnection); } else { + if (after.postConnection.to != null) { + after.postConnection.to.preConnection = null; + } after.postConnection.to = newNode; } newNode.preConnection = after.postConnection; diff --git a/src/utils/shuffle_utils/Connection.java b/src/utils/shuffle_utils/Connection.java index d3d396f3..0cb7fb63 100644 --- a/src/utils/shuffle_utils/Connection.java +++ b/src/utils/shuffle_utils/Connection.java @@ -67,8 +67,8 @@ public void finishDragging(Node other) { continue; } if (conn.to == other) { - conn.remove(); connections.remove(i - removed); + conn.remove(); removed++; } } diff --git a/src/utils/shuffle_utils/Node.java b/src/utils/shuffle_utils/Node.java index 2bb3e2d3..98128296 100644 --- a/src/utils/shuffle_utils/Node.java +++ b/src/utils/shuffle_utils/Node.java @@ -98,16 +98,16 @@ public void delete() { this.graph.nodes.remove(this); if (this.preConnection != null) { if (this.postConnection == null) { - this.preConnection.remove(); this.graph.connections.remove(this.preConnection); + this.preConnection.remove(); } else { this.preConnection.to = this.postConnection.to; } } if (this.postConnection != null) { if (this.preConnection == null) { - this.postConnection.remove(); this.graph.connections.remove(this.postConnection); + this.postConnection.remove(); } else { this.postConnection.from = this.preConnection.from; } From 76a49913c4a3559476ff2effe0d5eb2e399b1763 Mon Sep 17 00:00:00 2001 From: "Josiah (Gaming32) Glosson" Date: Thu, 29 Jul 2021 12:18:55 -0500 Subject: [PATCH 22/40] Shrink text when necessary --- src/utils/ShuffleGraph.java | 19 +++++++++++++++++++ src/utils/shuffle_utils/Node.java | 1 + 2 files changed, 20 insertions(+) diff --git a/src/utils/ShuffleGraph.java b/src/utils/ShuffleGraph.java index 5866a66b..8be11d79 100644 --- a/src/utils/ShuffleGraph.java +++ b/src/utils/ShuffleGraph.java @@ -4,9 +4,11 @@ import java.awt.Point; import java.util.ArrayList; import java.util.Collection; +import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.ListIterator; +import java.util.Map; import java.util.NoSuchElementException; import main.ArrayVisualizer; @@ -20,6 +22,9 @@ public class ShuffleGraph implements Collection { public Connection dragging; public Node dragCandidate; + final static int DEFAULT_TEXT_SIZE = 24; + Map textSizes = new HashMap<>(); + public ShuffleGraph() { this(new ShuffleInfo[0]); } @@ -147,6 +152,20 @@ public void deleteNode() { } } + public void calcTextSize(String text, int fit, Graphics2D g) { + if (textSizes.containsKey(text)) { + g.setFont(g.getFont().deriveFont((float)textSizes.get(text))); + return; + } + int size = DEFAULT_TEXT_SIZE; + g.setFont(g.getFont().deriveFont((float)size)); + while (g.getFontMetrics().stringWidth(text) >= fit) { + size--; + g.setFont(g.getFont().deriveFont((float)size)); + } + textSizes.put(text, size); + } + // Collection code public int size() { diff --git a/src/utils/shuffle_utils/Node.java b/src/utils/shuffle_utils/Node.java index 98128296..61c3aca5 100644 --- a/src/utils/shuffle_utils/Node.java +++ b/src/utils/shuffle_utils/Node.java @@ -67,6 +67,7 @@ public void draw(Graphics2D g) { AWTUtils.drawBorderRect(g, x, y, WIDTH, HEIGHT, 2); g.setColor(Color.BLACK); String text = getShuffleName(); + graph.calcTextSize(text, WIDTH, g); Rectangle2D rect = AWTUtils.getStringBounds(g, text); g.drawString( text, From 08187dcedb9057ab192e6f5e83bafd473c78c65b Mon Sep 17 00:00:00 2001 From: "Josiah (Gaming32) Glosson" Date: Mon, 2 Aug 2021 10:47:58 -0500 Subject: [PATCH 23/40] Add base distribution selector --- src/dialogs/ShuffleDialog.java | 134 +++++++++++++++++++++++---------- 1 file changed, 93 insertions(+), 41 deletions(-) diff --git a/src/dialogs/ShuffleDialog.java b/src/dialogs/ShuffleDialog.java index bc70bdc3..c8f26843 100644 --- a/src/dialogs/ShuffleDialog.java +++ b/src/dialogs/ShuffleDialog.java @@ -83,12 +83,19 @@ public ShuffleDialog(ArrayManager ArrayManager, JFrame frame, UtilFrame utilFram bypassEvents = true; this.shuffleEditor.graph = ArrayManager.getShuffle(); + jList4.setListData(ArrayManager.getDistributionIDs()); + for(int i = 0; i < ArrayManager.getDistributions().length; i++) { + if(ArrayManager.getDistribution().equals(ArrayManager.getDistributions()[i])) { + jList4.setSelectedIndex(i); + break; + } + } jList1.setListData(ArrayManager.getDistributionIDs()); jList3.setListData(ArrayManager.getDistributionIDs()); jList2.setListData(ArrayManager.getShuffleIDs()); bypassEvents = false; - setMinimumSize(new Dimension(580, 300)); + setMinimumSize(new Dimension(765, 300)); setAlwaysOnTop(false); reposition(); setVisible(true); @@ -112,6 +119,10 @@ private void initComponents() { this.jButton1 = new javax.swing.JButton(); this.jButton2 = new javax.swing.JButton(); + this.jScrollPane4 = new javax.swing.JScrollPane(); + this.jList4 = new javax.swing.JList(); + this.jLabel4 = new javax.swing.JLabel(); + this.jScrollPane1 = new javax.swing.JScrollPane(); this.jList1 = new javax.swing.JList(); this.jLabel1 = new javax.swing.JLabel(); @@ -142,6 +153,9 @@ public void actionPerformed(java.awt.event.ActionEvent evt) { } }); + jScrollPane4.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); + jScrollPane4.setViewportView(this.jList4); + jScrollPane1.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); jScrollPane1.setViewportView(this.jList1); @@ -151,6 +165,19 @@ public void actionPerformed(java.awt.event.ActionEvent evt) { jScrollPane2.setViewportView(this.jList2); jScrollPane2.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); + jList4.addListSelectionListener(new javax.swing.event.ListSelectionListener() { + @Override + public void valueChanged(javax.swing.event.ListSelectionEvent evt) { + try { + jList4ValueChanged(evt); + } catch (Exception e) { + JErrorPane.invokeErrorMessage(e); + } + } + }); + + jLabel4.setText("Base Distribution"); + jList1.addListSelectionListener(new javax.swing.event.ListSelectionListener() { @Override public void valueChanged(javax.swing.event.ListSelectionEvent evt) { @@ -193,52 +220,62 @@ public void valueChanged(javax.swing.event.ListSelectionEvent evt) { javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); getContentPane().setLayout(layout); layout.setHorizontalGroup( - layout.createParallelGroup(GroupLayout.Alignment.CENTER) - .addGroup(layout.createSequentialGroup() - .addGap(10, 10, 10) - .addComponent(this.shuffleEditor) - .addGap(10, 10, 10)) - .addGroup(layout.createSequentialGroup() - .addGap(10, 75, 75) - .addGroup(layout.createParallelGroup(GroupLayout.Alignment.CENTER) - .addComponent(this.jLabel1) - .addComponent(this.jScrollPane1, 175, 175, 175)) - .addGap(10, 75, 75) - .addGroup(layout.createParallelGroup(GroupLayout.Alignment.CENTER) - .addComponent(this.jLabel3) - .addComponent(this.jScrollPane3, 175, 175, 175)) - .addGap(10, 75, 75) - .addGroup(layout.createParallelGroup(GroupLayout.Alignment.CENTER) - .addComponent(this.jLabel2) - .addComponent(this.jScrollPane2, 175, 175, 175)) - .addGap(10, 75, 75)) - .addGroup(layout.createSequentialGroup() - .addGap(150, 150, 150) - .addComponent(this.jButton1) - .addGap(20, 20, 20) - .addComponent(this.jButton2) - .addGap(150, 150, 150)) - ); - layout.setVerticalGroup( layout.createSequentialGroup() .addGap(10, 10, 10) - .addComponent(this.shuffleEditor) - .addGap(10, 10, 10) + .addGroup(layout.createParallelGroup(GroupLayout.Alignment.CENTER) + .addComponent(this.jLabel4) + .addComponent(this.jScrollPane4, 175, 175, 175)) .addGroup(layout.createParallelGroup(GroupLayout.Alignment.CENTER) .addGroup(layout.createSequentialGroup() - .addComponent(this.jLabel1) - .addComponent(this.jScrollPane1, 175, 175, 175)) + .addGap(10, 10, 10) + .addComponent(this.shuffleEditor) + .addGap(10, 10, 10)) .addGroup(layout.createSequentialGroup() - .addComponent(this.jLabel3) - .addComponent(this.jScrollPane3, 175, 175, 175)) + .addGap(10, 75, 75) + .addGroup(layout.createParallelGroup(GroupLayout.Alignment.CENTER) + .addComponent(this.jLabel1) + .addComponent(this.jScrollPane1, 175, 175, 175)) + .addGap(10, 75, 75) + .addGroup(layout.createParallelGroup(GroupLayout.Alignment.CENTER) + .addComponent(this.jLabel3) + .addComponent(this.jScrollPane3, 175, 175, 175)) + .addGap(10, 75, 75) + .addGroup(layout.createParallelGroup(GroupLayout.Alignment.CENTER) + .addComponent(this.jLabel2) + .addComponent(this.jScrollPane2, 175, 175, 175)) + .addGap(10, 75, 75)) .addGroup(layout.createSequentialGroup() - .addComponent(this.jLabel2) - .addComponent(this.jScrollPane2, 175, 175, 175))) - .addGap(10, 10, 10) - .addGroup(layout.createParallelGroup(GroupLayout.Alignment.CENTER) - .addComponent(this.jButton1) - .addComponent(this.jButton2)) - .addGap(10, 10, 10) + .addGap(150, 150, 150) + .addComponent(this.jButton1) + .addGap(20, 20, 20) + .addComponent(this.jButton2) + .addGap(150, 150, 150))) + ); + layout.setVerticalGroup( + layout.createParallelGroup(GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addGap(10, 30, 30) + .addComponent(this.jLabel4) + .addComponent(this.jScrollPane4, 175, 175, 175)) + .addGroup(layout.createSequentialGroup() + .addGap(10, 10, 10) + .addComponent(this.shuffleEditor) + .addGap(10, 10, 10) + .addGroup(layout.createParallelGroup(GroupLayout.Alignment.CENTER) + .addGroup(layout.createSequentialGroup() + .addComponent(this.jLabel1) + .addComponent(this.jScrollPane1, 175, 175, 175)) + .addGroup(layout.createSequentialGroup() + .addComponent(this.jLabel3) + .addComponent(this.jScrollPane3, 175, 175, 175)) + .addGroup(layout.createSequentialGroup() + .addComponent(this.jLabel2) + .addComponent(this.jScrollPane2, 175, 175, 175))) + .addGap(10, 10, 10) + .addGroup(layout.createParallelGroup(GroupLayout.Alignment.CENTER) + .addComponent(this.jButton1) + .addComponent(this.jButton2)) + .addGap(10, 10, 10)) ); pack(); }// //GEN-END:initComponents @@ -276,6 +313,16 @@ private void jButton2ActionPerformed() {//GEN-FIRST:event_jButton1ActionPerforme "Advanced Shuffle Editor", JOptionPane.INFORMATION_MESSAGE); }//GEN-LAST:event_jButton1ActionPerformed + private void jList4ValueChanged(javax.swing.event.ListSelectionEvent evt) throws Exception {//GEN-FIRST:event_jList1ValueChanged + // TODO add your handling code here: + if (bypassEvents) + return; + int selection = jList4.getSelectedIndex(); + Distributions[] distributions = ArrayManager.getDistributions(); + if (selection >= 0 && selection < distributions.length) + ArrayManager.setDistribution(distributions[selection]); + }//GEN-LAST:event_jList1ValueChanged + private void jList1ValueChanged(javax.swing.event.ListSelectionEvent evt) throws Exception {//GEN-FIRST:event_jList1ValueChanged // TODO add your handling code here: if (bypassEvents) @@ -324,6 +371,11 @@ private void jList2ValueChanged(javax.swing.event.ListSelectionEvent evt) throws private javax.swing.JButton jButton1; private javax.swing.JButton jButton2; + @SuppressWarnings("rawtypes") + private javax.swing.JList jList4; + private javax.swing.JScrollPane jScrollPane4; + private javax.swing.JLabel jLabel4; + @SuppressWarnings("rawtypes") private javax.swing.JList jList1; private javax.swing.JScrollPane jScrollPane1; From 52ffda56c43e57c8c6438bd85322a81a3f498cf0 Mon Sep 17 00:00:00 2001 From: "Josiah (Gaming32) Glosson" Date: Mon, 2 Aug 2021 10:55:23 -0500 Subject: [PATCH 24/40] Change heading --- src/main/ArrayVisualizer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/ArrayVisualizer.java b/src/main/ArrayVisualizer.java index 891fb9f1..e8c55783 100644 --- a/src/main/ArrayVisualizer.java +++ b/src/main/ArrayVisualizer.java @@ -1214,7 +1214,7 @@ private void drawWindows() { this.window.setLocation(0, 0); this.window.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); - this.window.setTitle("w0rthy's Array Visualizer - " + (this.ComparisonSorts.length + this.DistributionSorts.length) + " Sorts, 15 Visual Styles, and " + (Distributions.values().length * Shuffles.values().length) + " Inputs to Sort"); + this.window.setTitle("w0rthy's Array Visualizer - " + (this.ComparisonSorts.length + this.DistributionSorts.length) + " Sorts, 15 Visual Styles, and Infinite Inputs to Sort"); this.window.setBackground(Color.BLACK); this.window.setIgnoreRepaint(true); From 8c2edf3c94397cb500bff8dad52f7c498deb686c Mon Sep 17 00:00:00 2001 From: "Josiah (Gaming32) Glosson" Date: Wed, 4 Aug 2021 13:07:47 -0500 Subject: [PATCH 25/40] Delete shuffle_editor_test.py --- shuffle_editor_test.py | 220 ----------------------------------------- 1 file changed, 220 deletions(-) delete mode 100644 shuffle_editor_test.py diff --git a/shuffle_editor_test.py b/shuffle_editor_test.py deleted file mode 100644 index 2b430ac8..00000000 --- a/shuffle_editor_test.py +++ /dev/null @@ -1,220 +0,0 @@ -from typing import Optional, Union - -import pygame -import pygame.display -import pygame.draw -import pygame.event -import pygame.font -import pygame.time -from pygame import * -from pygame.locals import * - - -class Editor: - nodes: list['Node'] - connections: list['Connection'] - selected: Optional['Node'] - dragging: Optional['Connection'] - drag_candidate: Optional['Node'] - - def __init__(self, shuffles: list[str]) -> None: - self.nodes = [Node('', self, -Node.WIDTH, 15)] - self.nodes.extend(Node(shuffle, self) for shuffle in shuffles) - self.connections = [] - self.selected = None - self.dragging = None - self.drag_candidate = None - - def draw(self, surface: Surface): - for connection in self.connections: - connection.draw(surface) - for node in self.nodes: - node.draw(surface) - - def drag(self, rel: Vector2): - if self.selected is not None: - self.selected.drag(rel) - elif self.dragging is not None: - pos = self.dragging.current_drag_pos - pos += rel - for node in reversed(self.nodes): - if node.in_area(pos): - self.drag_candidate = node - break - else: - self.drag_candidate = None - - def select(self, pos: Vector2): - for node in reversed(self.nodes): - if node.in_area(pos): - self.selected = node - return - elif node.in_start_drag(pos): - new_connection = Connection(node, pos) - removed = 0 - for (i, conn) in enumerate(self.connections.copy()): - if conn.from_ == node: - del self.connections[i - removed] - removed += 1 - self.connections.append(new_connection) - self.dragging = new_connection - node.post_connection = new_connection - self.selected = None - return - self.selected = None - - def end_connection(self): - if self.dragging is None: - return - if self.drag_candidate is not None: - self.dragging.finish_dragging(self.drag_candidate) - else: - self.connections.remove(self.dragging) - self.dragging = None - self.drag_candidate = None - - def delete(self): - if self.selected is not None: - self.selected.delete() - - -class Node: - WIDTH = 250 - HEIGHT = 50 - - shuffle: str - x: int - y: int - editor: Editor - pre_connection: Optional['Connection'] - post_connection: Optional['Connection'] - - def __init__(self, shuffle: str, editor: Editor, x: int = 0, y: int = 0) -> None: - self.shuffle = shuffle - self.editor = editor - self.x = x - self.y = y - self.pre_connection = None - self.post_connection = None - - def draw(self, surface: Surface): - border_color = (128, 128, 255) if self is self.editor.selected else (0, 0, 0) - left_color = (128, 128, 255) if self is self.editor.drag_candidate else border_color - pygame.draw.circle(surface, left_color, (self.x, self.y + Node.HEIGHT / 2), 10) - pygame.draw.circle(surface, border_color, (self.x + Node.WIDTH, self.y + Node.HEIGHT / 2), 10) - pygame.draw.rect(surface, (255, 255, 255), (self.x, self.y, Node.WIDTH, Node.HEIGHT)) - pygame.draw.rect(surface, border_color, (self.x, self.y, Node.WIDTH, Node.HEIGHT), 2) - text_r = font.render(self.shuffle, True, (0, 0, 0)) - rect = text_r.get_rect() - surface.blit( - text_r, - rect.move(self.x, self.y) - .move(Node.WIDTH / 2, Node.HEIGHT / 2) - .move(-rect.width / 2, -rect.height / 2) - ) - - def drag(self, rel: Vector2): - self.x += rel.x - self.y += rel.y - - def in_area(self, pos: Vector2): - return Rect(self.x, self.y, Node.WIDTH, Node.HEIGHT).collidepoint(pos) - - def in_start_drag(self, pos: Vector2): - return Rect(self.x + Node.WIDTH, self.y + Node.HEIGHT / 2 - 10, 10, 20).collidepoint(pos) - - def delete(self): - if self == self.editor.selected: - self.editor.selected = None - self.editor.nodes.remove(self) - if self.pre_connection is not None: - self.pre_connection.to = self.post_connection.to - if self.post_connection is not None: - self.post_connection.from_ = self.pre_connection.from_ - - def __eq__(self, o: object) -> bool: - if isinstance(o, Node): - return ( - self.editor is o.editor - and self.shuffle == o.shuffle - and self.x == o.x - and self.y == o.y - and self.pre_connection is o.pre_connection - and self.post_connection is o.post_connection - ) - return False - - def get_pos(self) -> Vector2: - return Vector2(self.x, self.y) - - -class Connection: - from_: Node - to: Optional[Node] - current_drag_pos: Vector2 - - def __init__(self, from_: Node, to: Union[Node, Vector2]) -> None: - self.from_ = from_ - if isinstance(to, Node): - self.to = to - self.current_drag_pos = Vector2() - else: - self.to = None - self.current_drag_pos = to - - def draw(self, surface: Surface): - from_pos = self.from_.get_pos() + (Node.WIDTH + 10, Node.HEIGHT / 2) - end_pos: Vector2 = Vector2(self.current_drag_pos) if self.to is None else (self.to.get_pos() + (0, Node.HEIGHT / 2)) - end_pos -= (10, 0) - mid_start = from_pos + (15, 0) - mid_end = end_pos - (15, 0) - pygame.draw.line(surface, (0, 0, 0), from_pos, mid_start, 5) - pygame.draw.line(surface, (0, 0, 0), mid_start, mid_end, 5) - pygame.draw.line(surface, (0, 0, 0), mid_end, end_pos, 5) - if self.to is None: - pygame.draw.circle(surface, (0, 0, 0), end_pos + (10, 0), 10) - - def finish_dragging(self, other: Node): - self.to = other - other.pre_connection = self - removed = 0 - for (i, conn) in enumerate(other.editor.connections.copy()): - if conn == self: - continue - if conn.to == other: - del other.editor.connections[i - removed] - removed += 1 - - -pygame.init() -screen = pygame.display.set_mode((1280, 720), RESIZABLE) -font = pygame.font.SysFont('ariel', 24) - -editor = Editor(['Linear', 'Randomly', 'Backwards', 'Slight Shuffle', 'No Shuffle']) - - -clock = pygame.time.Clock() -running = True -while running: - delta = clock.tick(60) / 1000 - for event in pygame.event.get(): - if event.type == QUIT: - running = False - elif event.type == MOUSEMOTION: - if event.buttons[0]: - editor.drag(Vector2(event.rel)) - elif event.type == MOUSEBUTTONDOWN: - if event.button == 1: - editor.select(Vector2(event.pos)) - elif event.type == MOUSEBUTTONUP: - if event.button == 1: - editor.end_connection() - elif event.type == KEYDOWN: - if event.key == K_DELETE: - editor.delete() - - screen.fill((128, 128, 128)) - - editor.draw(screen) - - pygame.display.update() From 9905de5d3fabd8399cfb353669bd29b95e6eb01b Mon Sep 17 00:00:00 2001 From: "Josiah (Gaming32) Glosson" Date: Wed, 4 Aug 2021 13:09:20 -0500 Subject: [PATCH 26/40] Update CustomImageDialog.java --- src/dialogs/CustomImageDialog.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dialogs/CustomImageDialog.java b/src/dialogs/CustomImageDialog.java index 7e461438..ef4b812f 100644 --- a/src/dialogs/CustomImageDialog.java +++ b/src/dialogs/CustomImageDialog.java @@ -23,7 +23,7 @@ public CustomImageDialog() { fileDialog.setDialogTitle("Choose an image..."); - fileDialog.showDialog(null, "Select"); + fileDialog.showOpenDialog(null); this.file = fileDialog.getSelectedFile(); } } \ No newline at end of file From c2ae11a1a8c0a5de54ce4360bc528916d83a7e31 Mon Sep 17 00:00:00 2001 From: "Josiah (Gaming32) Glosson" Date: Wed, 4 Aug 2021 13:12:18 -0500 Subject: [PATCH 27/40] Update ArrayManager.java --- src/main/ArrayManager.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/main/ArrayManager.java b/src/main/ArrayManager.java index bb03071e..2f4e1c58 100644 --- a/src/main/ArrayManager.java +++ b/src/main/ArrayManager.java @@ -181,11 +181,7 @@ public void shuffleArray(int[] array, int currentLen, ArrayVisualizer ArrayVisua Delays.setSleepRatio(sleepRatio); } - ShuffleGraph tempShuffle = this.shuffle; - if(distribution == Distributions.RANDOM || distribution == Distributions.EQUAL) - this.shuffle = ShuffleGraph.single(Shuffles.ALREADY); shuffle.shuffleArray(array, this.ArrayVisualizer); - this.shuffle = tempShuffle; Delays.setSleepRatio(speed); From 09f9d08884b9baf7005b97bc7176c2209b95a783 Mon Sep 17 00:00:00 2001 From: "Josiah (Gaming32) Glosson" Date: Thu, 5 Aug 2021 10:44:57 -0500 Subject: [PATCH 28/40] Offset added nodes --- src/dialogs/ShuffleDialog.java | 12 +++++++++--- src/utils/ShuffleGraph.java | 11 +++++++++++ 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/src/dialogs/ShuffleDialog.java b/src/dialogs/ShuffleDialog.java index c8f26843..5c7fde66 100644 --- a/src/dialogs/ShuffleDialog.java +++ b/src/dialogs/ShuffleDialog.java @@ -5,6 +5,7 @@ package dialogs; import java.awt.Dimension; +import java.awt.Point; import java.io.IOException; import javax.swing.GroupLayout; @@ -313,6 +314,11 @@ private void jButton2ActionPerformed() {//GEN-FIRST:event_jButton1ActionPerforme "Advanced Shuffle Editor", JOptionPane.INFORMATION_MESSAGE); }//GEN-LAST:event_jButton1ActionPerformed + private void addToGraph(ShuffleInfo shuffle) { + Point safePos = shuffleEditor.graph.findSafeCoordinate(100, 100, 20, 20); + shuffleEditor.graph.addDisconnected(shuffle, safePos.x, safePos.y); + } + private void jList4ValueChanged(javax.swing.event.ListSelectionEvent evt) throws Exception {//GEN-FIRST:event_jList1ValueChanged // TODO add your handling code here: if (bypassEvents) @@ -330,7 +336,7 @@ private void jList1ValueChanged(javax.swing.event.ListSelectionEvent evt) throws int selection = jList1.getSelectedIndex(); Distributions[] distributions = ArrayManager.getDistributions(); if (selection >= 0 && selection < distributions.length) - shuffleEditor.graph.addDisconnected(new ShuffleInfo(distributions[selection], false), 250, 250); + addToGraph(new ShuffleInfo(distributions[selection], false)); shuffleEditor.repaint(); bypassEvents = true; jList1.clearSelection(); @@ -344,7 +350,7 @@ private void jList3ValueChanged(javax.swing.event.ListSelectionEvent evt) throws int selection = jList3.getSelectedIndex(); Distributions[] distributions = ArrayManager.getDistributions(); if (selection >= 0 && selection < distributions.length) - shuffleEditor.graph.addDisconnected(new ShuffleInfo(distributions[selection], true), 250, 250); + addToGraph(new ShuffleInfo(distributions[selection], true)); shuffleEditor.repaint(); bypassEvents = true; jList3.clearSelection(); @@ -358,7 +364,7 @@ private void jList2ValueChanged(javax.swing.event.ListSelectionEvent evt) throws int selection = jList2.getSelectedIndex(); Shuffles[] shuffles = ArrayManager.getShuffles(); if (selection >= 0 && selection < shuffles.length) - shuffleEditor.graph.addDisconnected(new ShuffleInfo(shuffles[selection]), 250, 250); + addToGraph(new ShuffleInfo(shuffles[selection])); shuffleEditor.repaint(); bypassEvents = true; jList2.clearSelection(); diff --git a/src/utils/ShuffleGraph.java b/src/utils/ShuffleGraph.java index 8be11d79..7cccd877 100644 --- a/src/utils/ShuffleGraph.java +++ b/src/utils/ShuffleGraph.java @@ -5,11 +5,13 @@ import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; +import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.ListIterator; import java.util.Map; import java.util.NoSuchElementException; +import java.util.Set; import main.ArrayVisualizer; import utils.shuffle_utils.Connection; @@ -73,6 +75,15 @@ public void addDisconnected(ShuffleInfo shuffle, int x, int y) { this.nodes.add(new Node(shuffle, this, x, y)); } + public Point findSafeCoordinate(int baseX, int baseY, int offsetX, int offsetY) { + Point p = new Point(baseX, baseY); + while (this.nodes.stream().anyMatch(node -> node.x == p.x && node.y == p.y)) { + p.x += offsetX; + p.y += offsetY; + } + return p; + } + public void draw(Graphics2D g) { for (Connection connection : this.connections) { connection.draw(g); From 7eb5a7bfc3abdf45c69eb9438ed845b068d4c00c Mon Sep 17 00:00:00 2001 From: "Josiah (Gaming32) Glosson" Date: Thu, 5 Aug 2021 11:02:58 -0500 Subject: [PATCH 29/40] Add a button to clear disconnected nodes --- src/dialogs/ShuffleDialog.java | 24 ++++++++++++++--- src/utils/ShuffleGraph.java | 49 +++++++++++++++++++++++++++++++--- 2 files changed, 67 insertions(+), 6 deletions(-) diff --git a/src/dialogs/ShuffleDialog.java b/src/dialogs/ShuffleDialog.java index 5c7fde66..fc2bcc5d 100644 --- a/src/dialogs/ShuffleDialog.java +++ b/src/dialogs/ShuffleDialog.java @@ -96,7 +96,7 @@ public ShuffleDialog(ArrayManager ArrayManager, JFrame frame, UtilFrame utilFram jList2.setListData(ArrayManager.getShuffleIDs()); bypassEvents = false; - setMinimumSize(new Dimension(765, 300)); + setMinimumSize(new Dimension(765, 310)); setAlwaysOnTop(false); reposition(); setVisible(true); @@ -119,6 +119,7 @@ private void initComponents() { this.jButton1 = new javax.swing.JButton(); this.jButton2 = new javax.swing.JButton(); + this.jButton3 = new javax.swing.JButton(); this.jScrollPane4 = new javax.swing.JScrollPane(); this.jList4 = new javax.swing.JList(); @@ -153,6 +154,14 @@ public void actionPerformed(java.awt.event.ActionEvent evt) { jButton2ActionPerformed(); } }); + + jButton3.setText("Clear Disconnected Nodes"); + jButton3.addActionListener(new java.awt.event.ActionListener() { + @Override + public void actionPerformed(java.awt.event.ActionEvent evt) { + jButton3ActionPerformed(); + } + }); jScrollPane4.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); jScrollPane4.setViewportView(this.jList4); @@ -225,7 +234,8 @@ public void valueChanged(javax.swing.event.ListSelectionEvent evt) { .addGap(10, 10, 10) .addGroup(layout.createParallelGroup(GroupLayout.Alignment.CENTER) .addComponent(this.jLabel4) - .addComponent(this.jScrollPane4, 175, 175, 175)) + .addComponent(this.jScrollPane4, 175, 175, 175) + .addComponent(this.jButton3)) .addGroup(layout.createParallelGroup(GroupLayout.Alignment.CENTER) .addGroup(layout.createSequentialGroup() .addGap(10, 10, 10) @@ -257,7 +267,9 @@ public void valueChanged(javax.swing.event.ListSelectionEvent evt) { .addGroup(layout.createSequentialGroup() .addGap(10, 30, 30) .addComponent(this.jLabel4) - .addComponent(this.jScrollPane4, 175, 175, 175)) + .addComponent(this.jScrollPane4, 175, 175, 175) + .addGap(20, 20, 20) + .addComponent(this.jButton3)) .addGroup(layout.createSequentialGroup() .addGap(10, 10, 10) .addComponent(this.shuffleEditor) @@ -314,6 +326,11 @@ private void jButton2ActionPerformed() {//GEN-FIRST:event_jButton1ActionPerforme "Advanced Shuffle Editor", JOptionPane.INFORMATION_MESSAGE); }//GEN-LAST:event_jButton1ActionPerformed + private void jButton3ActionPerformed() {//GEN-FIRST:event_jButton1ActionPerformed + shuffleEditor.graph.removeAllDisconnected(); + shuffleEditor.repaint(); + }//GEN-LAST:event_jButton1ActionPerformed + private void addToGraph(ShuffleInfo shuffle) { Point safePos = shuffleEditor.graph.findSafeCoordinate(100, 100, 20, 20); shuffleEditor.graph.addDisconnected(shuffle, safePos.x, safePos.y); @@ -376,6 +393,7 @@ private void jList2ValueChanged(javax.swing.event.ListSelectionEvent evt) throws private javax.swing.JButton jButton1; private javax.swing.JButton jButton2; + private javax.swing.JButton jButton3; @SuppressWarnings("rawtypes") private javax.swing.JList jList4; diff --git a/src/utils/ShuffleGraph.java b/src/utils/ShuffleGraph.java index 7cccd877..56907b7d 100644 --- a/src/utils/ShuffleGraph.java +++ b/src/utils/ShuffleGraph.java @@ -84,6 +84,29 @@ public Point findSafeCoordinate(int baseX, int baseY, int offsetX, int offsetY) return p; } + public int removeAllDisconnected() { + Set toKeep = new HashSet<>(); + toKeep.add(this.nodes.get(0)); + for (Node connected : connectedNodesIterable()) { + toKeep.add(connected); + } + int removed = this.nodes.size() - toKeep.size(); + this.nodes.retainAll(toKeep); + return removed; + } + + public Iterator iterateConnectedNodes() { + return new NodeIterator(this); + } + + public Iterable connectedNodesIterable() { + return new Iterable() { + public Iterator iterator() { + return ShuffleGraph.this.iterateConnectedNodes(); + } + }; + } + public void draw(Graphics2D g) { for (Connection connection : this.connections) { connection.draw(g); @@ -345,9 +368,29 @@ public Iterator iterator() { } protected class GraphIterator implements Iterator { - Node currentNode, nextNode; + NodeIterator it; GraphIterator(ShuffleGraph graph) { + this.it = new NodeIterator(graph); + } + + public boolean hasNext() { + return this.it.hasNext(); + } + + public ShuffleInfo next() { + return this.it.next().getValue(); + } + + public void remove() { + this.it.remove();; + } + } + + protected class NodeIterator implements Iterator { + Node currentNode, nextNode; + + NodeIterator(ShuffleGraph graph) { this.currentNode = graph.nodes.get(0); this.nextNode = findNext(); } @@ -367,13 +410,13 @@ public boolean hasNext() { return this.nextNode != null; } - public ShuffleInfo next() { + public Node next() { if (this.nextNode == null) { throw new NoSuchElementException(); } this.currentNode = this.nextNode; this.nextNode = findNext(); - return this.currentNode.getValue(); + return this.currentNode; } public void remove() { From c69d7e057ce5a5eb3b6693b7127b3f16be0dde14 Mon Sep 17 00:00:00 2001 From: "Josiah (Gaming32) Glosson" Date: Fri, 6 Aug 2021 06:42:09 -0500 Subject: [PATCH 30/40] Added sleep ratio and made coordinates optional in shuffle files --- Noisily sorted.txt | 6 +- src/main/ArrayManager.java | 1 + src/utils/ShuffleGraph.java | 2 + src/utils/shuffle_utils/GraphReader.java | 76 +++++++++++++++--------- 4 files changed, 53 insertions(+), 32 deletions(-) diff --git a/Noisily sorted.txt b/Noisily sorted.txt index 00d2e2be..b7ae4d0a 100644 --- a/Noisily sorted.txt +++ b/Noisily sorted.txt @@ -1,5 +1,5 @@ -1 -N true RANDOM true 56 71 0 1 -N false SORTED 363 125 1 -1 +2 2 +N true RANDOM true 0 1 +N false SORTED 1 -1 C 0 1 C 1 2 diff --git a/src/main/ArrayManager.java b/src/main/ArrayManager.java index 2f4e1c58..0bc00946 100644 --- a/src/main/ArrayManager.java +++ b/src/main/ArrayManager.java @@ -178,6 +178,7 @@ public void shuffleArray(int[] array, int currentLen, ArrayVisualizer ArrayVisua if(ArrayVisualizer.isActive()) { double sleepRatio = ArrayVisualizer.getCurrentLength()/1024d; + sleepRatio *= shuffle.sleepRatio; Delays.setSleepRatio(sleepRatio); } diff --git a/src/utils/ShuffleGraph.java b/src/utils/ShuffleGraph.java index 56907b7d..00c86007 100644 --- a/src/utils/ShuffleGraph.java +++ b/src/utils/ShuffleGraph.java @@ -23,6 +23,7 @@ public class ShuffleGraph implements Collection { public Node selected; public Connection dragging; public Node dragCandidate; + public double sleepRatio; final static int DEFAULT_TEXT_SIZE = 24; Map textSizes = new HashMap<>(); @@ -41,6 +42,7 @@ public ShuffleGraph(ShuffleInfo[] shuffles) { this.selected = null; this.dragging = null; this.dragCandidate = null; + this.sleepRatio = 1; } public static ShuffleGraph single(ShuffleInfo shuffle) { diff --git a/src/utils/shuffle_utils/GraphReader.java b/src/utils/shuffle_utils/GraphReader.java index 5f831007..e9452b37 100644 --- a/src/utils/shuffle_utils/GraphReader.java +++ b/src/utils/shuffle_utils/GraphReader.java @@ -1,5 +1,6 @@ package utils.shuffle_utils; +import java.awt.Point; import java.io.File; import java.io.IOException; import java.util.ArrayList; @@ -9,7 +10,6 @@ import java.util.Scanner; import java.util.Set; import java.util.stream.Collectors; -import java.util.stream.Stream; import utils.Distributions; import utils.ShuffleGraph; @@ -18,31 +18,13 @@ public final class GraphReader { public final class MalformedGraphFileException extends Exception { - // public int line, column; - public MalformedGraphFileException() { super(); - // this.line = 0; - // this.column = 0; } - // public MalformedGraphFileException(int line, int column) { - // super(); - // this.line = line; - // this.column = column; - // } - public MalformedGraphFileException(String message) { super(message); - // this.line = 0; - // this.column = 0; } - - // public MalformedGraphFileException(String message, int line, int column) { - // super(message); - // this.line = line; - // this.column = column; - // } } private final class PartialElement { @@ -54,7 +36,7 @@ public PartialElement(int left, int right) { } } - public final static int[] COMPATIBLE_VERSIONS = {0, 1}; + public final static int[] COMPATIBLE_VERSIONS = {0, 1, 2}; static Set compatibleVersionsSet; Scanner scanner; @@ -118,6 +100,10 @@ private void read() throws IOException, MalformedGraphFileException { result = new ShuffleGraph(); partialNodes = new ArrayList<>(); + if (version >= 2 && scanner.hasNextDouble()) { + result.sleepRatio = scanner.nextDouble(); + } + while (scanner.hasNext()) { String identifier = scanner.next().toUpperCase(); switch (identifier) { @@ -147,6 +133,23 @@ private void read() throws IOException, MalformedGraphFileException { } } + if (version >= 2) { + for (int i = 1; i < result.nodes.size(); i++) { + Node node = result.nodes.get(i); + if (node.x == Integer.MIN_VALUE) { // coordinates not specified + if (node.preConnection == null || node.preConnection.from == null) { + Point safePos = result.findSafeCoordinate(100, 100, 20, 20); + node.x = safePos.x; + node.y = safePos.y; + } else { + Node previous = node.preConnection.from; + node.x = previous.x + Node.WIDTH + 15; + node.y = previous.y; + } + } + } + } + partialNodes = null; } @@ -192,22 +195,37 @@ private void readNode() throws MalformedGraphFileException { } throw e; } - if (!scanner.hasNextInt()) { + if (!scanner.hasNextInt()) { // x throw new MalformedGraphFileException("Expected X coordinate in node declaration"); } int x = scanner.nextInt(); - if (!scanner.hasNextInt()) { + if (!scanner.hasNextInt()) { // y throw new MalformedGraphFileException("Expected Y coordinate in node declaration"); } int y = scanner.nextInt(); - if (!scanner.hasNextInt()) { - throw new MalformedGraphFileException("Expected preConnection ID in node declaration"); - } - int preConnectionID = scanner.nextInt(); - if (!scanner.hasNextInt()) { - throw new MalformedGraphFileException("Expected postConnection ID in node declaration"); + int preConnectionID, postConnectionID; + if (version < 2) { + if (!scanner.hasNextInt()) { // preConnectionID + throw new MalformedGraphFileException("Expected preConnection ID in node declaration"); + } + preConnectionID = scanner.nextInt(); + if (!scanner.hasNextInt()) { // postConnectionID + throw new MalformedGraphFileException("Expected postConnection ID in node declaration"); + } + postConnectionID = scanner.nextInt(); + } else { + if (!scanner.hasNextInt()) { + preConnectionID = x; + postConnectionID = y; + x = Integer.MIN_VALUE; + } else { + preConnectionID = scanner.nextInt(); + if (!scanner.hasNextInt()) { // postConnectionID + throw new MalformedGraphFileException("Expected postConnection ID in node declaration"); + } + postConnectionID = scanner.nextInt(); + } } - int postConnectionID = scanner.nextInt(); result.nodes.add(new Node(shuffleInfo, result, x, y)); partialNodes.add(new PartialElement(preConnectionID, postConnectionID)); From 7abe505519f7932d6ad909e0e9b8765ceabb6d98 Mon Sep 17 00:00:00 2001 From: "Josiah (Gaming32) Glosson" Date: Fri, 6 Aug 2021 11:49:47 -0500 Subject: [PATCH 31/40] Add GUI --- src/dialogs/ShuffleDialog.java | 52 +++++++++++++++++++++++- src/utils/shuffle_utils/GraphWriter.java | 8 +++- 2 files changed, 56 insertions(+), 4 deletions(-) diff --git a/src/dialogs/ShuffleDialog.java b/src/dialogs/ShuffleDialog.java index fc2bcc5d..4a85e27c 100644 --- a/src/dialogs/ShuffleDialog.java +++ b/src/dialogs/ShuffleDialog.java @@ -4,6 +4,7 @@ */ package dialogs; +import java.awt.Color; import java.awt.Dimension; import java.awt.Point; import java.io.IOException; @@ -11,6 +12,8 @@ import javax.swing.GroupLayout; import javax.swing.JFrame; import javax.swing.JOptionPane; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; import frames.AppFrame; import frames.UtilFrame; @@ -84,6 +87,7 @@ public ShuffleDialog(ArrayManager ArrayManager, JFrame frame, UtilFrame utilFram bypassEvents = true; this.shuffleEditor.graph = ArrayManager.getShuffle(); + jTextField1.setText(Double.toString(shuffleEditor.graph.sleepRatio)); jList4.setListData(ArrayManager.getDistributionIDs()); for(int i = 0; i < ArrayManager.getDistributions().length; i++) { if(ArrayManager.getDistribution().equals(ArrayManager.getDistributions()[i])) { @@ -121,6 +125,9 @@ private void initComponents() { this.jButton2 = new javax.swing.JButton(); this.jButton3 = new javax.swing.JButton(); + this.jTextField1 = new javax.swing.JTextField(10); + this.jLabel5 = new javax.swing.JLabel(); + this.jScrollPane4 = new javax.swing.JScrollPane(); this.jList4 = new javax.swing.JList(); this.jLabel4 = new javax.swing.JLabel(); @@ -163,6 +170,23 @@ public void actionPerformed(java.awt.event.ActionEvent evt) { } }); + jLabel5.setText("Sleep Ratio"); + + jTextField1.getDocument().addDocumentListener(new DocumentListener() { + @Override + public void insertUpdate(DocumentEvent e) { + jTextField1TextChanged(e); + } + @Override + public void removeUpdate(DocumentEvent e) { + jTextField1TextChanged(e); + } + @Override + public void changedUpdate(DocumentEvent e) { + jTextField1TextChanged(e); + } + }); + jScrollPane4.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); jScrollPane4.setViewportView(this.jList4); @@ -235,7 +259,9 @@ public void valueChanged(javax.swing.event.ListSelectionEvent evt) { .addGroup(layout.createParallelGroup(GroupLayout.Alignment.CENTER) .addComponent(this.jLabel4) .addComponent(this.jScrollPane4, 175, 175, 175) - .addComponent(this.jButton3)) + .addComponent(this.jButton3) + .addComponent(this.jLabel5) + .addComponent(this.jTextField1)) .addGroup(layout.createParallelGroup(GroupLayout.Alignment.CENTER) .addGroup(layout.createSequentialGroup() .addGap(10, 10, 10) @@ -269,7 +295,10 @@ public void valueChanged(javax.swing.event.ListSelectionEvent evt) { .addComponent(this.jLabel4) .addComponent(this.jScrollPane4, 175, 175, 175) .addGap(20, 20, 20) - .addComponent(this.jButton3)) + .addComponent(this.jButton3) + .addGap(20, 20, 20) + .addComponent(this.jLabel5) + .addComponent(this.jTextField1, 20, 20, 20)) .addGroup(layout.createSequentialGroup() .addGap(10, 10, 10) .addComponent(this.shuffleEditor) @@ -308,6 +337,8 @@ private void jButton1ActionPerformed() {//GEN-FIRST:event_jButton1ActionPerforme return; } ArrayManager.setShuffle(newShuffle); + jTextField1.setForeground(Color.BLACK); + jTextField1.setText(Double.toString(newShuffle.sleepRatio)); this.shuffleEditor.graph = newShuffle; this.shuffleEditor.repaint(); }//GEN-LAST:event_jButton1ActionPerformed @@ -331,6 +362,20 @@ private void jButton3ActionPerformed() {//GEN-FIRST:event_jButton1ActionPerforme shuffleEditor.repaint(); }//GEN-LAST:event_jButton1ActionPerformed + private void jTextField1TextChanged(DocumentEvent e) {//GEN-FIRST:event_jList1ValueChanged + String text = jTextField1.getText(); + if (text.length() == 0) return; + double sleepRatio; + try { + sleepRatio = Double.parseDouble(text); + } catch (NumberFormatException ex) { + jTextField1.setForeground(new Color(204, 0, 0)); + return; + } + jTextField1.setForeground(Color.BLACK); + shuffleEditor.graph.sleepRatio = sleepRatio; + }//GEN-LAST:event_jList1ValueChanged + private void addToGraph(ShuffleInfo shuffle) { Point safePos = shuffleEditor.graph.findSafeCoordinate(100, 100, 20, 20); shuffleEditor.graph.addDisconnected(shuffle, safePos.x, safePos.y); @@ -395,6 +440,9 @@ private void jList2ValueChanged(javax.swing.event.ListSelectionEvent evt) throws private javax.swing.JButton jButton2; private javax.swing.JButton jButton3; + private javax.swing.JTextField jTextField1; + private javax.swing.JLabel jLabel5; + @SuppressWarnings("rawtypes") private javax.swing.JList jList4; private javax.swing.JScrollPane jScrollPane4; diff --git a/src/utils/shuffle_utils/GraphWriter.java b/src/utils/shuffle_utils/GraphWriter.java index 5e11d710..e15de432 100644 --- a/src/utils/shuffle_utils/GraphWriter.java +++ b/src/utils/shuffle_utils/GraphWriter.java @@ -9,7 +9,7 @@ import utils.ShuffleGraph; public final class GraphWriter { - final public static int VERSION = 1; + public static final int VERSION = 2; ShuffleGraph graph; @@ -41,8 +41,11 @@ public void write(FileWriter writer) throws IOException { } connectionMap.put(null, -1); - writer.write(VERSION + "\n"); + // Metadata + writer.write(VERSION + " "); + writer.write(graph.sleepRatio + "\n"); + // Nodes for (int i = 1; i < graph.nodes.size(); i++) { Node node = graph.nodes.get(i); writer.write("N "); @@ -60,6 +63,7 @@ public void write(FileWriter writer) throws IOException { writer.write(connectionMap.get(node.postConnection) + "\n"); } + // Connections for (int i = 0; i < graph.connections.size(); i++) { Connection conn = graph.connections.get(i); writer.write("C "); From d7da291c3d7cf87df1f7447394009d868a5f6630 Mon Sep 17 00:00:00 2001 From: "Josiah (Gaming32) Glosson" Date: Fri, 6 Aug 2021 11:54:53 -0500 Subject: [PATCH 32/40] Rename Node and Connection classes --- src/utils/ShuffleGraph.java | 96 +++++++++---------- src/utils/shuffle_utils/GraphReader.java | 14 +-- src/utils/shuffle_utils/GraphWriter.java | 12 +-- ...Connection.java => ShuffleConnection.java} | 18 ++-- .../{Node.java => ShuffleNode.java} | 12 +-- 5 files changed, 76 insertions(+), 76 deletions(-) rename src/utils/shuffle_utils/{Connection.java => ShuffleConnection.java} (76%) rename src/utils/shuffle_utils/{Node.java => ShuffleNode.java} (91%) diff --git a/src/utils/ShuffleGraph.java b/src/utils/ShuffleGraph.java index 00c86007..31ea3633 100644 --- a/src/utils/ShuffleGraph.java +++ b/src/utils/ShuffleGraph.java @@ -14,15 +14,15 @@ import java.util.Set; import main.ArrayVisualizer; -import utils.shuffle_utils.Connection; -import utils.shuffle_utils.Node; +import utils.shuffle_utils.ShuffleConnection; +import utils.shuffle_utils.ShuffleNode; public class ShuffleGraph implements Collection { - public List nodes; - public List connections; - public Node selected; - public Connection dragging; - public Node dragCandidate; + public List nodes; + public List connections; + public ShuffleNode selected; + public ShuffleConnection dragging; + public ShuffleNode dragCandidate; public double sleepRatio; final static int DEFAULT_TEXT_SIZE = 24; @@ -34,9 +34,9 @@ public ShuffleGraph() { public ShuffleGraph(ShuffleInfo[] shuffles) { this.nodes = new ArrayList<>(); - this.nodes.add(new Node(null, this, -Node.WIDTH, 15)); + this.nodes.add(new ShuffleNode(null, this, -ShuffleNode.WIDTH, 15)); for (ShuffleInfo shuffle : shuffles) { - this.nodes.add(new Node(shuffle, this)); + this.nodes.add(new ShuffleNode(shuffle, this)); } this.connections = new ArrayList<>(); this.selected = null; @@ -70,11 +70,11 @@ public void shuffleArray(int[] array, ArrayVisualizer arrayVisualizer) { } public void addDisconnected(ShuffleInfo shuffle) { - this.nodes.add(new Node(shuffle, this)); + this.nodes.add(new ShuffleNode(shuffle, this)); } public void addDisconnected(ShuffleInfo shuffle, int x, int y) { - this.nodes.add(new Node(shuffle, this, x, y)); + this.nodes.add(new ShuffleNode(shuffle, this, x, y)); } public Point findSafeCoordinate(int baseX, int baseY, int offsetX, int offsetY) { @@ -87,9 +87,9 @@ public Point findSafeCoordinate(int baseX, int baseY, int offsetX, int offsetY) } public int removeAllDisconnected() { - Set toKeep = new HashSet<>(); + Set toKeep = new HashSet<>(); toKeep.add(this.nodes.get(0)); - for (Node connected : connectedNodesIterable()) { + for (ShuffleNode connected : connectedNodesIterable()) { toKeep.add(connected); } int removed = this.nodes.size() - toKeep.size(); @@ -97,23 +97,23 @@ public int removeAllDisconnected() { return removed; } - public Iterator iterateConnectedNodes() { + public Iterator iterateConnectedNodes() { return new NodeIterator(this); } - public Iterable connectedNodesIterable() { - return new Iterable() { - public Iterator iterator() { + public Iterable connectedNodesIterable() { + return new Iterable() { + public Iterator iterator() { return ShuffleGraph.this.iterateConnectedNodes(); } }; } public void draw(Graphics2D g) { - for (Connection connection : this.connections) { + for (ShuffleConnection connection : this.connections) { connection.draw(g); } - for (Node node : this.nodes) { + for (ShuffleNode node : this.nodes) { node.draw(g); } } @@ -125,9 +125,9 @@ public void drag(Point rel) { Point pos = this.dragging.currentDragPos; pos.translate(rel.x, rel.y); boolean foundCandidate = false; - ListIterator it = this.nodes.listIterator(this.nodes.size()); + ListIterator it = this.nodes.listIterator(this.nodes.size()); while (it.hasPrevious()) { - Node node = it.previous(); + ShuffleNode node = it.previous(); if (node.inArea(pos)) { this.dragCandidate = node; foundCandidate = true; @@ -141,17 +141,17 @@ public void drag(Point rel) { } public void select(Point pos) { - ListIterator it = this.nodes.listIterator(this.nodes.size()); + ListIterator it = this.nodes.listIterator(this.nodes.size()); while (it.hasPrevious()) { - Node node = it.previous(); + ShuffleNode node = it.previous(); if (node.inArea(pos)) { this.selected = node; return; } else if (node.inStartDrag(pos)) { - Connection newConnection = new Connection(node, pos); + ShuffleConnection newConnection = new ShuffleConnection(node, pos); int removed = 0; for (int i = 0; i < this.connections.size(); i++) { - Connection conn = this.connections.get(i - removed); + ShuffleConnection conn = this.connections.get(i - removed); if (conn.from == node) { this.connections.remove(i - removed); conn.remove(); @@ -206,10 +206,10 @@ public void calcTextSize(String text, int fit, Graphics2D g) { // Collection code public int size() { int size = 0; - Node node = this.nodes.get(0); + ShuffleNode node = this.nodes.get(0); while (node != null) { size++; - Connection connect = node.postConnection; + ShuffleConnection connect = node.postConnection; if (connect == null) { break; } @@ -223,11 +223,11 @@ public void clear() { this.nodes.get(0).postConnection = null; } - public Node findLast() { - Node previous = null; - Node node = this.nodes.get(0); + public ShuffleNode findLast() { + ShuffleNode previous = null; + ShuffleNode node = this.nodes.get(0); while (node != null) { - Connection connect = node.postConnection; + ShuffleConnection connect = node.postConnection; if (connect == null) { previous = node; node = null; @@ -245,17 +245,17 @@ public boolean add(ShuffleInfo shuffle) { } public boolean addAll(Collection c) { - Node after = findLast(); + ShuffleNode after = findLast(); for (ShuffleInfo shuffle : c) { after = add(shuffle, after); } return true; } - Node add(ShuffleInfo shuffle, Node after) { - Node newNode = new Node(shuffle, this, after.x + Node.WIDTH + 15, after.y); + ShuffleNode add(ShuffleInfo shuffle, ShuffleNode after) { + ShuffleNode newNode = new ShuffleNode(shuffle, this, after.x + ShuffleNode.WIDTH + 15, after.y); if (after.postConnection == null) { - after.postConnection = new Connection(after, newNode); + after.postConnection = new ShuffleConnection(after, newNode); this.connections.add(after.postConnection); } else { if (after.postConnection.to != null) { @@ -268,13 +268,13 @@ Node add(ShuffleInfo shuffle, Node after) { return newNode; } - Node find(Object o) { + ShuffleNode find(Object o) { if (o == null) { return null; } - Node node = this.nodes.get(0); + ShuffleNode node = this.nodes.get(0); while (node != null) { - Connection connect = node.postConnection; + ShuffleConnection connect = node.postConnection; if (connect == null) { break; } @@ -307,7 +307,7 @@ public boolean isEmpty() { } public boolean remove(Object o) { - Node found = find(o); + ShuffleNode found = find(o); if (found == null) { return false; } @@ -345,9 +345,9 @@ public T[] toArray(T[] a) { } ShuffleInfo[] result = (ShuffleInfo[])a; int i = 0; - Node node = this.nodes.get(0); + ShuffleNode node = this.nodes.get(0); while (node != null) { - Connection connect = node.postConnection; + ShuffleConnection connect = node.postConnection; if (connect == null) { break; } @@ -358,7 +358,7 @@ public T[] toArray(T[] a) { a[i] = null; } return a; - } else if (type == Node.class) { + } else if (type == ShuffleNode.class) { return this.nodes.toArray(a); } else { throw new ArrayStoreException(); @@ -389,18 +389,18 @@ public void remove() { } } - protected class NodeIterator implements Iterator { - Node currentNode, nextNode; + protected class NodeIterator implements Iterator { + ShuffleNode currentNode, nextNode; NodeIterator(ShuffleGraph graph) { this.currentNode = graph.nodes.get(0); this.nextNode = findNext(); } - Node findNext() { - Connection connect = this.currentNode.postConnection; + ShuffleNode findNext() { + ShuffleConnection connect = this.currentNode.postConnection; if (connect != null) { - Node next = connect.to; + ShuffleNode next = connect.to; if (next != null) { return next; } @@ -412,7 +412,7 @@ public boolean hasNext() { return this.nextNode != null; } - public Node next() { + public ShuffleNode next() { if (this.nextNode == null) { throw new NoSuchElementException(); } diff --git a/src/utils/shuffle_utils/GraphReader.java b/src/utils/shuffle_utils/GraphReader.java index e9452b37..ed0706fd 100644 --- a/src/utils/shuffle_utils/GraphReader.java +++ b/src/utils/shuffle_utils/GraphReader.java @@ -119,7 +119,7 @@ private void read() throws IOException, MalformedGraphFileException { } for (int i = 1; i < result.nodes.size(); i++) { - Node node = result.nodes.get(i); + ShuffleNode node = result.nodes.get(i); PartialElement partial = partialNodes.get(i - 1); try { node.preConnection = partial.left == -1 ? null : result.connections.get(partial.left); @@ -135,15 +135,15 @@ private void read() throws IOException, MalformedGraphFileException { if (version >= 2) { for (int i = 1; i < result.nodes.size(); i++) { - Node node = result.nodes.get(i); + ShuffleNode node = result.nodes.get(i); if (node.x == Integer.MIN_VALUE) { // coordinates not specified if (node.preConnection == null || node.preConnection.from == null) { Point safePos = result.findSafeCoordinate(100, 100, 20, 20); node.x = safePos.x; node.y = safePos.y; } else { - Node previous = node.preConnection.from; - node.x = previous.x + Node.WIDTH + 15; + ShuffleNode previous = node.preConnection.from; + node.x = previous.x + ShuffleNode.WIDTH + 15; node.y = previous.y; } } @@ -227,7 +227,7 @@ private void readNode() throws MalformedGraphFileException { } } - result.nodes.add(new Node(shuffleInfo, result, x, y)); + result.nodes.add(new ShuffleNode(shuffleInfo, result, x, y)); partialNodes.add(new PartialElement(preConnectionID, postConnectionID)); } @@ -241,7 +241,7 @@ private void readConnection() throws MalformedGraphFileException { } int toNodeID = scanner.nextInt(); - Node fromNode = null, toNode = null; + ShuffleNode fromNode = null, toNode = null; try { fromNode = fromNodeID == -1 ? null : result.nodes.get(fromNodeID); toNode = toNodeID == -1 ? null : result.nodes.get(toNodeID); @@ -252,7 +252,7 @@ private void readConnection() throws MalformedGraphFileException { newError.initCause(e); throw newError; } - Connection connection = new Connection(fromNode, toNode); + ShuffleConnection connection = new ShuffleConnection(fromNode, toNode); result.connections.add(connection); if (fromNodeID == 0) { fromNode.postConnection = connection; diff --git a/src/utils/shuffle_utils/GraphWriter.java b/src/utils/shuffle_utils/GraphWriter.java index e15de432..b034e1ca 100644 --- a/src/utils/shuffle_utils/GraphWriter.java +++ b/src/utils/shuffle_utils/GraphWriter.java @@ -28,15 +28,15 @@ public void write(File file) throws IOException { } public void write(FileWriter writer) throws IOException { - Map nodeMap = new HashMap<>(); - Map connectionMap = new HashMap<>(); + Map nodeMap = new HashMap<>(); + Map connectionMap = new HashMap<>(); for (int i = 0; i < graph.nodes.size(); i++) { - Node node = graph.nodes.get(i); + ShuffleNode node = graph.nodes.get(i); nodeMap.put(node, i); } nodeMap.put(null, -1); for (int i = 0; i < graph.connections.size(); i++) { - Connection conn = graph.connections.get(i); + ShuffleConnection conn = graph.connections.get(i); connectionMap.put(conn, i); } connectionMap.put(null, -1); @@ -47,7 +47,7 @@ public void write(FileWriter writer) throws IOException { // Nodes for (int i = 1; i < graph.nodes.size(); i++) { - Node node = graph.nodes.get(i); + ShuffleNode node = graph.nodes.get(i); writer.write("N "); if (node.getValue().isDistribution()) { writer.write("true "); @@ -65,7 +65,7 @@ public void write(FileWriter writer) throws IOException { // Connections for (int i = 0; i < graph.connections.size(); i++) { - Connection conn = graph.connections.get(i); + ShuffleConnection conn = graph.connections.get(i); writer.write("C "); writer.write(nodeMap.get(conn.from) + " "); writer.write(nodeMap.get(conn.to) + "\n"); diff --git a/src/utils/shuffle_utils/Connection.java b/src/utils/shuffle_utils/ShuffleConnection.java similarity index 76% rename from src/utils/shuffle_utils/Connection.java rename to src/utils/shuffle_utils/ShuffleConnection.java index 0cb7fb63..f8c6d15b 100644 --- a/src/utils/shuffle_utils/Connection.java +++ b/src/utils/shuffle_utils/ShuffleConnection.java @@ -7,17 +7,17 @@ import java.awt.Point; import java.util.List; -public class Connection { - public Node from, to; +public class ShuffleConnection { + public ShuffleNode from, to; public Point currentDragPos; - public Connection(Node from, Node to) { + public ShuffleConnection(ShuffleNode from, ShuffleNode to) { this.from = from; this.to = to; this.currentDragPos = new Point(); } - public Connection(Node from, Point to) { + public ShuffleConnection(ShuffleNode from, Point to) { this.from = from; this.to = null; this.currentDragPos = to; @@ -25,13 +25,13 @@ public Connection(Node from, Point to) { public void draw(Graphics2D g) { Point fromPos = this.from.getPos(); - fromPos = new Point(fromPos.x + Node.WIDTH + 10, fromPos.y + Node.HEIGHT / 2); + fromPos = new Point(fromPos.x + ShuffleNode.WIDTH + 10, fromPos.y + ShuffleNode.HEIGHT / 2); Point endPos; if (this.to == null) { endPos = new Point(this.currentDragPos.x - 10, this.currentDragPos.y); } else { Point toPos = this.to.getPos(); - endPos = new Point(toPos.x, toPos.y + Node.HEIGHT / 2); + endPos = new Point(toPos.x, toPos.y + ShuffleNode.HEIGHT / 2); } Point midStart = new Point(fromPos.x + 15, fromPos.y); Point midEnd = new Point(endPos.x - 15, endPos.y); @@ -56,13 +56,13 @@ public void remove() { } } - public void finishDragging(Node other) { + public void finishDragging(ShuffleNode other) { this.to = other; other.preConnection = this; int removed = 0; - List connections = other.graph.connections; + List connections = other.graph.connections; for (int i = 0; i < connections.size(); i++) { - Connection conn = connections.get(i - removed); + ShuffleConnection conn = connections.get(i - removed); if (conn == this) { continue; } diff --git a/src/utils/shuffle_utils/Node.java b/src/utils/shuffle_utils/ShuffleNode.java similarity index 91% rename from src/utils/shuffle_utils/Node.java rename to src/utils/shuffle_utils/ShuffleNode.java index 61c3aca5..3eb1c75c 100644 --- a/src/utils/shuffle_utils/Node.java +++ b/src/utils/shuffle_utils/ShuffleNode.java @@ -8,16 +8,16 @@ import utils.ShuffleGraph; import utils.ShuffleInfo; -public class Node { +public class ShuffleNode { public static final int WIDTH = 250; public static final int HEIGHT = 50; public ShuffleInfo shuffle; public int x, y; public ShuffleGraph graph; - public Connection preConnection, postConnection; + public ShuffleConnection preConnection, postConnection; - public Node(ShuffleInfo shuffle, ShuffleGraph graph, int x, int y) { + public ShuffleNode(ShuffleInfo shuffle, ShuffleGraph graph, int x, int y) { this.shuffle = shuffle; this.graph = graph; this.x = x; @@ -26,7 +26,7 @@ public Node(ShuffleInfo shuffle, ShuffleGraph graph, int x, int y) { this.postConnection = null; } - public Node(ShuffleInfo shuffle, ShuffleGraph graph) { + public ShuffleNode(ShuffleInfo shuffle, ShuffleGraph graph) { this(shuffle, graph, 0, 0); } @@ -34,8 +34,8 @@ public boolean equals(Object o) { if (o == null) { return false; } - if (o instanceof Node) { - Node other = (Node)o; + if (o instanceof ShuffleNode) { + ShuffleNode other = (ShuffleNode)o; return this.x == other.x && this.y == other.y && this.graph == other.graph From 095143de8d7a3d41cf5acac6fd1c4df40ba37180 Mon Sep 17 00:00:00 2001 From: "Josiah (Gaming32) Glosson" Date: Fri, 6 Aug 2021 11:58:24 -0500 Subject: [PATCH 33/40] Update ShufflePrompt.java --- src/prompts/ShufflePrompt.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/prompts/ShufflePrompt.java b/src/prompts/ShufflePrompt.java index ae1386c3..09a7b0bd 100644 --- a/src/prompts/ShufflePrompt.java +++ b/src/prompts/ShufflePrompt.java @@ -13,7 +13,6 @@ import frames.AppFrame; import frames.UtilFrame; import main.ArrayManager; -import panels.ShufflePanel; import panes.JErrorPane; import utils.Distributions; import utils.Shuffles; @@ -97,6 +96,10 @@ public ShufflePrompt(ArrayManager ArrayManager, JFrame frame, UtilFrame utilFram break; } } + if (jList2.getSelectedIndex() == -1) { + shuffleModel.add(0, "Advanced"); + jList2.setSelectedIndex(0); + } } initializing = false; From 0ebba958477e7b9ed860b31d699afe0eff3b3326 Mon Sep 17 00:00:00 2001 From: "Josiah (Gaming32) Glosson" Date: Fri, 6 Aug 2021 12:26:55 -0500 Subject: [PATCH 34/40] Ignore CUSTOM distribution --- src/dialogs/ShuffleDialog.java | 40 +++++++++++++++++++++++++--------- 1 file changed, 30 insertions(+), 10 deletions(-) diff --git a/src/dialogs/ShuffleDialog.java b/src/dialogs/ShuffleDialog.java index 4a85e27c..202d014a 100644 --- a/src/dialogs/ShuffleDialog.java +++ b/src/dialogs/ShuffleDialog.java @@ -8,6 +8,9 @@ import java.awt.Dimension; import java.awt.Point; import java.io.IOException; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; import javax.swing.GroupLayout; import javax.swing.JFrame; @@ -69,6 +72,8 @@ final public class ShuffleDialog extends javax.swing.JDialog implements AppFrame private ArrayManager ArrayManager; private JFrame Frame; private UtilFrame UtilFrame; + List distributions; + List distributionNames; private boolean bypassEvents; @@ -95,8 +100,17 @@ public ShuffleDialog(ArrayManager ArrayManager, JFrame frame, UtilFrame utilFram break; } } - jList1.setListData(ArrayManager.getDistributionIDs()); - jList3.setListData(ArrayManager.getDistributionIDs()); + + distributions = Arrays.stream(ArrayManager.getDistributions()) + .filter(dist -> dist.getName() != "Custom") + .collect(Collectors.toList()); + distributionNames = distributions.stream() + .map(Distributions::getName) + .collect(Collectors.toList()); + Object[] distributionNamesArray = distributionNames.toArray(); + jList1.setListData(distributionNamesArray); + jList3.setListData(distributionNamesArray); + jList2.setListData(ArrayManager.getShuffleIDs()); bypassEvents = false; @@ -395,10 +409,13 @@ private void jList1ValueChanged(javax.swing.event.ListSelectionEvent evt) throws // TODO add your handling code here: if (bypassEvents) return; - int selection = jList1.getSelectedIndex(); - Distributions[] distributions = ArrayManager.getDistributions(); - if (selection >= 0 && selection < distributions.length) - addToGraph(new ShuffleInfo(distributions[selection], false)); + String selection = (String)jList1.getSelectedValue(); + Distributions distribution = distributions.stream() + .filter(d -> d.getName().equals(selection)) + .findFirst() + .orElse(null); + if (distribution != null) + addToGraph(new ShuffleInfo(distribution, false)); shuffleEditor.repaint(); bypassEvents = true; jList1.clearSelection(); @@ -409,10 +426,13 @@ private void jList3ValueChanged(javax.swing.event.ListSelectionEvent evt) throws // TODO add your handling code here: if (bypassEvents) return; - int selection = jList3.getSelectedIndex(); - Distributions[] distributions = ArrayManager.getDistributions(); - if (selection >= 0 && selection < distributions.length) - addToGraph(new ShuffleInfo(distributions[selection], true)); + String selection = (String)jList3.getSelectedValue(); + Distributions distribution = distributions.stream() + .filter(d -> d.getName().equals(selection)) + .findFirst() + .orElse(null); + if (distribution != null) + addToGraph(new ShuffleInfo(distribution, true)); shuffleEditor.repaint(); bypassEvents = true; jList3.clearSelection(); From 22eaa5e468822ac5b301f859340408997dfb69ee Mon Sep 17 00:00:00 2001 From: "Josiah (Gaming32) Glosson" Date: Fri, 6 Aug 2021 12:36:26 -0500 Subject: [PATCH 35/40] Update ShuffleDialog.java --- src/dialogs/ShuffleDialog.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dialogs/ShuffleDialog.java b/src/dialogs/ShuffleDialog.java index 202d014a..2623529e 100644 --- a/src/dialogs/ShuffleDialog.java +++ b/src/dialogs/ShuffleDialog.java @@ -237,7 +237,7 @@ public void valueChanged(javax.swing.event.ListSelectionEvent evt) { } }); - jLabel1.setText("Distribution Change"); + jLabel1.setText("Distribution Stretch"); jList3.addListSelectionListener(new javax.swing.event.ListSelectionListener() { @Override From 215430f86e2ac1f403e0c1daaf7db1aa062165db Mon Sep 17 00:00:00 2001 From: "Josiah (Gaming32) Glosson" Date: Sat, 7 Aug 2021 15:55:30 -0500 Subject: [PATCH 36/40] Update Noisily sorted.txt --- Noisily sorted.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Noisily sorted.txt b/Noisily sorted.txt index b7ae4d0a..15f723e9 100644 --- a/Noisily sorted.txt +++ b/Noisily sorted.txt @@ -1,4 +1,4 @@ -2 2 +2 2.0 N true RANDOM true 0 1 N false SORTED 1 -1 C 0 1 From f83b9a7034d128d0f98cdda7046cf4ba903c0071 Mon Sep 17 00:00:00 2001 From: "Josiah (Gaming32) Glosson" Date: Mon, 9 Aug 2021 10:53:04 -0500 Subject: [PATCH 37/40] Rename findSafeCoordinate to findSafeCoordinates --- src/dialogs/ShuffleDialog.java | 2 +- src/utils/ShuffleGraph.java | 2 +- src/utils/shuffle_utils/GraphReader.java | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/dialogs/ShuffleDialog.java b/src/dialogs/ShuffleDialog.java index 2623529e..16f3c346 100644 --- a/src/dialogs/ShuffleDialog.java +++ b/src/dialogs/ShuffleDialog.java @@ -391,7 +391,7 @@ private void jTextField1TextChanged(DocumentEvent e) {//GEN-FIRST:event_jList1Va }//GEN-LAST:event_jList1ValueChanged private void addToGraph(ShuffleInfo shuffle) { - Point safePos = shuffleEditor.graph.findSafeCoordinate(100, 100, 20, 20); + Point safePos = shuffleEditor.graph.findSafeCoordinates(100, 100, 20, 20); shuffleEditor.graph.addDisconnected(shuffle, safePos.x, safePos.y); } diff --git a/src/utils/ShuffleGraph.java b/src/utils/ShuffleGraph.java index 31ea3633..4059b0a5 100644 --- a/src/utils/ShuffleGraph.java +++ b/src/utils/ShuffleGraph.java @@ -77,7 +77,7 @@ public void addDisconnected(ShuffleInfo shuffle, int x, int y) { this.nodes.add(new ShuffleNode(shuffle, this, x, y)); } - public Point findSafeCoordinate(int baseX, int baseY, int offsetX, int offsetY) { + public Point findSafeCoordinates(int baseX, int baseY, int offsetX, int offsetY) { Point p = new Point(baseX, baseY); while (this.nodes.stream().anyMatch(node -> node.x == p.x && node.y == p.y)) { p.x += offsetX; diff --git a/src/utils/shuffle_utils/GraphReader.java b/src/utils/shuffle_utils/GraphReader.java index ed0706fd..7ec18683 100644 --- a/src/utils/shuffle_utils/GraphReader.java +++ b/src/utils/shuffle_utils/GraphReader.java @@ -138,7 +138,7 @@ private void read() throws IOException, MalformedGraphFileException { ShuffleNode node = result.nodes.get(i); if (node.x == Integer.MIN_VALUE) { // coordinates not specified if (node.preConnection == null || node.preConnection.from == null) { - Point safePos = result.findSafeCoordinate(100, 100, 20, 20); + Point safePos = result.findSafeCoordinates(100, 100, 20, 20); node.x = safePos.x; node.y = safePos.y; } else { From bd42a95423639148c3683c65cc85b0885489603f Mon Sep 17 00:00:00 2001 From: "Josiah (Gaming32) Glosson" Date: Mon, 9 Aug 2021 11:07:46 -0500 Subject: [PATCH 38/40] Add delays per sub-shuffle --- src/dialogs/ShuffleDialog.java | 33 ++++++++++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/src/dialogs/ShuffleDialog.java b/src/dialogs/ShuffleDialog.java index 16f3c346..56195fbf 100644 --- a/src/dialogs/ShuffleDialog.java +++ b/src/dialogs/ShuffleDialog.java @@ -7,6 +7,8 @@ import java.awt.Color; import java.awt.Dimension; import java.awt.Point; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; import java.io.IOException; import java.util.Arrays; import java.util.List; @@ -114,6 +116,15 @@ public ShuffleDialog(ArrayManager ArrayManager, JFrame frame, UtilFrame utilFram jList2.setListData(ArrayManager.getShuffleIDs()); bypassEvents = false; + addWindowListener(new WindowAdapter() { + @Override + public void windowClosed(WindowEvent e) { + if (jCheckBox1.isSelected()) { + shuffleEditor.graph.sleepRatio *= shuffleEditor.graph.size(); + } + } + }); + setMinimumSize(new Dimension(765, 310)); setAlwaysOnTop(false); reposition(); @@ -139,8 +150,9 @@ private void initComponents() { this.jButton2 = new javax.swing.JButton(); this.jButton3 = new javax.swing.JButton(); - this.jTextField1 = new javax.swing.JTextField(10); + this.jTextField1 = new javax.swing.JTextField(); this.jLabel5 = new javax.swing.JLabel(); + this.jCheckBox1 = new javax.swing.JCheckBox(); this.jScrollPane4 = new javax.swing.JScrollPane(); this.jList4 = new javax.swing.JList(); @@ -201,6 +213,9 @@ public void changedUpdate(DocumentEvent e) { } }); + jCheckBox1.setText("Time per sub-shuffle"); + jCheckBox1.setSelected(false); + jScrollPane4.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); jScrollPane4.setViewportView(this.jList4); @@ -275,7 +290,8 @@ public void valueChanged(javax.swing.event.ListSelectionEvent evt) { .addComponent(this.jScrollPane4, 175, 175, 175) .addComponent(this.jButton3) .addComponent(this.jLabel5) - .addComponent(this.jTextField1)) + .addComponent(this.jTextField1) + .addComponent(this.jCheckBox1)) .addGroup(layout.createParallelGroup(GroupLayout.Alignment.CENTER) .addGroup(layout.createSequentialGroup() .addGap(10, 10, 10) @@ -312,7 +328,8 @@ public void valueChanged(javax.swing.event.ListSelectionEvent evt) { .addComponent(this.jButton3) .addGap(20, 20, 20) .addComponent(this.jLabel5) - .addComponent(this.jTextField1, 20, 20, 20)) + .addComponent(this.jTextField1, 20, 20, 20) + .addComponent(this.jCheckBox1)) .addGroup(layout.createSequentialGroup() .addGap(10, 10, 10) .addComponent(this.shuffleEditor) @@ -351,6 +368,9 @@ private void jButton1ActionPerformed() {//GEN-FIRST:event_jButton1ActionPerforme return; } ArrayManager.setShuffle(newShuffle); + if (jCheckBox1.isSelected()) { + shuffleEditor.graph.sleepRatio /= shuffleEditor.graph.size(); + } jTextField1.setForeground(Color.BLACK); jTextField1.setText(Double.toString(newShuffle.sleepRatio)); this.shuffleEditor.graph = newShuffle; @@ -359,13 +379,19 @@ private void jButton1ActionPerformed() {//GEN-FIRST:event_jButton1ActionPerforme private void jButton2ActionPerformed() {//GEN-FIRST:event_jButton1ActionPerformed FileDialog fileDialog = new ExportShuffleDialog(); + double oldSleepRatio = shuffleEditor.graph.sleepRatio; + if (jCheckBox1.isSelected()) { + shuffleEditor.graph.sleepRatio *= shuffleEditor.graph.size(); + } try { new GraphWriter(shuffleEditor.graph).write(fileDialog.file); } catch (IOException e) { + shuffleEditor.graph.sleepRatio = oldSleepRatio; e.printStackTrace(); JErrorPane.invokeCustomErrorMessage("IO Error: " + e.getMessage()); return; } + shuffleEditor.graph.sleepRatio = oldSleepRatio; JOptionPane.showMessageDialog(null, "Successfully exported current shuffle to file \"" + fileDialog.file.getAbsolutePath() + "\"", "Advanced Shuffle Editor", JOptionPane.INFORMATION_MESSAGE); @@ -462,6 +488,7 @@ private void jList2ValueChanged(javax.swing.event.ListSelectionEvent evt) throws private javax.swing.JTextField jTextField1; private javax.swing.JLabel jLabel5; + private javax.swing.JCheckBox jCheckBox1; @SuppressWarnings("rawtypes") private javax.swing.JList jList4; From 6d00b59f0ca510e4bb01f8282bdffd253708bcf0 Mon Sep 17 00:00:00 2001 From: "Josiah (Gaming32) Glosson" Date: Mon, 9 Aug 2021 11:09:35 -0500 Subject: [PATCH 39/40] Remove an unnecessary field --- src/dialogs/ShuffleDialog.java | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/dialogs/ShuffleDialog.java b/src/dialogs/ShuffleDialog.java index 56195fbf..1de35a90 100644 --- a/src/dialogs/ShuffleDialog.java +++ b/src/dialogs/ShuffleDialog.java @@ -75,7 +75,6 @@ final public class ShuffleDialog extends javax.swing.JDialog implements AppFrame private JFrame Frame; private UtilFrame UtilFrame; List distributions; - List distributionNames; private boolean bypassEvents; @@ -106,12 +105,12 @@ public ShuffleDialog(ArrayManager ArrayManager, JFrame frame, UtilFrame utilFram distributions = Arrays.stream(ArrayManager.getDistributions()) .filter(dist -> dist.getName() != "Custom") .collect(Collectors.toList()); - distributionNames = distributions.stream() - .map(Distributions::getName) - .collect(Collectors.toList()); - Object[] distributionNamesArray = distributionNames.toArray(); - jList1.setListData(distributionNamesArray); - jList3.setListData(distributionNamesArray); + Object[] distributionNames = distributions.stream() + .map(Distributions::getName) + .collect(Collectors.toList()) + .toArray(); + jList1.setListData(distributionNames); + jList3.setListData(distributionNames); jList2.setListData(ArrayManager.getShuffleIDs()); bypassEvents = false; From 5a26192ce578fc936b1d655eb8956caaa74b54eb Mon Sep 17 00:00:00 2001 From: "Josiah (Gaming32) Glosson" Date: Mon, 9 Aug 2021 11:16:33 -0500 Subject: [PATCH 40/40] Persist the per-shuffle delay checkbox --- src/dialogs/ShuffleDialog.java | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/dialogs/ShuffleDialog.java b/src/dialogs/ShuffleDialog.java index 1de35a90..01c21e41 100644 --- a/src/dialogs/ShuffleDialog.java +++ b/src/dialogs/ShuffleDialog.java @@ -74,8 +74,9 @@ final public class ShuffleDialog extends javax.swing.JDialog implements AppFrame private ArrayManager ArrayManager; private JFrame Frame; private UtilFrame UtilFrame; - List distributions; - + private List distributions; + private static boolean perShuffleDelay = false; + private boolean bypassEvents; /** @@ -93,7 +94,6 @@ public ShuffleDialog(ArrayManager ArrayManager, JFrame frame, UtilFrame utilFram bypassEvents = true; this.shuffleEditor.graph = ArrayManager.getShuffle(); - jTextField1.setText(Double.toString(shuffleEditor.graph.sleepRatio)); jList4.setListData(ArrayManager.getDistributionIDs()); for(int i = 0; i < ArrayManager.getDistributions().length; i++) { if(ArrayManager.getDistribution().equals(ArrayManager.getDistributions()[i])) { @@ -113,12 +113,19 @@ public ShuffleDialog(ArrayManager ArrayManager, JFrame frame, UtilFrame utilFram jList3.setListData(distributionNames); jList2.setListData(ArrayManager.getShuffleIDs()); + + jTextField1.setText(Double.toString( + perShuffleDelay ? + shuffleEditor.graph.sleepRatio / shuffleEditor.graph.size() : + shuffleEditor.graph.sleepRatio + )); + jCheckBox1.setSelected(perShuffleDelay); bypassEvents = false; addWindowListener(new WindowAdapter() { @Override public void windowClosed(WindowEvent e) { - if (jCheckBox1.isSelected()) { + if (perShuffleDelay = jCheckBox1.isSelected()) { shuffleEditor.graph.sleepRatio *= shuffleEditor.graph.size(); } } @@ -213,7 +220,6 @@ public void changedUpdate(DocumentEvent e) { }); jCheckBox1.setText("Time per sub-shuffle"); - jCheckBox1.setSelected(false); jScrollPane4.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); jScrollPane4.setViewportView(this.jList4);