/******************************************************************************* * Copyright (c) 2012-present Jakub Kováč, Jozef Brandýs, Katarína Kotrlová, * Pavol Lukča, Ladislav Pápay, Viktor Tomkovič, Tatiana Tóthová * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. ******************************************************************************/ package algvis.ds.dictionaries.skiplist; import java.awt.Color; import java.util.Hashtable; import algvis.core.DataStructure; import algvis.core.Node; import algvis.core.NodeColor; import algvis.core.history.HashtableStoreSupport; import algvis.core.visual.ZDepth; import algvis.ui.view.View; public class SkipNode extends Node { private SkipNode left = null; private SkipNode right = null; private SkipNode up = null; private SkipNode down = null; public SkipNode(DataStructure D, int key, int x, int y) { super(D, key, x, y, ZDepth.ACTIONNODE); } public SkipNode(DataStructure D, int key, int zDepth) { super(D, key, zDepth); } public void linkleft(SkipNode v) { setLeft(v); v.setRight(this); } public void linkright(SkipNode v) { setRight(v); v.setLeft(this); } public void linkup(SkipNode v) { setUp(v); v.setDown(this); } public void linkdown(SkipNode v) { setDown(v); v.setUp(this); } public void isolate() { setLeft(setRight(setUp(setDown(null)))); } @Override public void drawBg(View v) { v.setColor(getBgColor()); v.fillSqr(x, y, Node.RADIUS); v.setColor(Color.BLACK); // fgcolor); v.drawSqr(x, y, Node.RADIUS); if (marked) { v.drawSqr(x, y, Node.RADIUS + 2); } } public void drawSkipList(View V) { if (getLeft() == null && getDown() != null) { V.setColor(Color.black); V.drawLine(x, y, getDown().x, getDown().y); getDown().drawSkipList(V); } if (getRight() != null) { V.setColor(Color.black); V.drawArrow(x, y, getRight().x - Node.RADIUS, getRight().y); getRight().drawSkipList(V); } draw(V); } public void moveSkipList() { if (getLeft() == null && getDown() != null) { getDown().moveSkipList(); } if (getRight() != null) { getRight().moveSkipList(); } move(); } public void _reposition() { if (D.x2 < this.tox) { D.x2 = this.tox; } if (D.y2 < this.toy) { D.y2 = this.toy; } if (getLeft() == null) { if (getUp() == null) { goToRoot(); } else { goTo(getUp().tox, getUp().toy + DataStructure.minsepy); } if (getDown() != null) { getDown()._reposition(); } } else { if (getDown() == null) { goNextTo(getLeft()); } else { goTo(getDown().tox, getLeft().toy); } } if (getRight() != null) { getRight()._reposition(); } } // we assume this is a bottom node private void colorColumn(NodeColor color) { SkipNode w = this; while (w != null) { w.setColor(color); w = w.getUp(); // stand up } } // color all the columns to the right of this one (inclusive) public void colorAfter(NodeColor color) { SkipNode w = this; while (w.getDown() != null) { w = w.getDown(); } while (w != null) { w.colorColumn(color); w = w.getRight(); } } // color all the columns to the left of this one (NON-inclusive) public void colorBefore(NodeColor color) { SkipNode w = this; while (w.getDown() != null) { w = w.getDown(); } w = w.getLeft(); while (w != null) { w.colorColumn(color); w = w.getLeft(); } } public SkipNode find(int x, int y) { if (inside(x, y)) { return this; } if (getLeft() == null && getDown() != null) { final SkipNode tmp = getDown().find(x, y); if (tmp != null) { return tmp; } } if (getRight() != null) { return getRight().find(x, y); } return null; } SkipNode getLeft() { return left; } void setLeft(SkipNode left) { this.left = left; } public SkipNode getRight() { return right; } SkipNode setRight(SkipNode right) { return this.right = right; } public SkipNode getUp() { return up; } public SkipNode setUp(SkipNode up) { return this.up = up; } public SkipNode getDown() { return down; } public SkipNode setDown(SkipNode down) { return this.down = down; } @Override public void storeState(Hashtable<Object, Object> state) { super.storeState(state); HashtableStoreSupport.store(state, hash + "down", down); HashtableStoreSupport.store(state, hash + "left", left); HashtableStoreSupport.store(state, hash + "right", right); HashtableStoreSupport.store(state, hash + "up", up); if (right != null) { right.storeState(state); } if (down != null) { down.storeState(state); } } @Override public void restoreState(Hashtable<?, ?> state) { super.restoreState(state); final Object down = state.get(hash + "down"); if (down != null) { this.down = (SkipNode) HashtableStoreSupport.restore(down); } final Object left = state.get(hash + "left"); if (left != null) { this.left = (SkipNode) HashtableStoreSupport.restore(left); } final Object right = state.get(hash + "right"); if (right != null) { this.right = (SkipNode) HashtableStoreSupport.restore(right); } final Object up = state.get(hash + "up"); if (up != null) { this.up = (SkipNode) HashtableStoreSupport.restore(up); } if (this.right != null) { this.right.restoreState(state); } if (this.down != null) { this.down.restoreState(state); } } }