/*******************************************************************************
* 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.trie;
import java.awt.Color;
import java.util.Hashtable;
import algvis.core.DataStructure;
import algvis.core.Node;
import algvis.core.NodeColor;
import algvis.core.TreeNode;
import algvis.core.history.HashtableStoreSupport;
import algvis.core.visual.ZDepth;
import algvis.ui.Fonts;
import algvis.ui.view.View;
public class TrieNode extends TreeNode {
public char ch;
protected final int radius = 2;
private static final int ordinaryNode = -7;
private boolean greyPair = false;
protected TrieNode(DataStructure D, int key, int x, int y) {
super(D, key, x, y);
ch = '?';
}
protected TrieNode(DataStructure D, int key, char ch) {
super(D, key, ZDepth.NODE);
this.ch = ch;
}
protected TrieNode(DataStructure D, int key) {
super(D, key, ZDepth.NODE);
ch = '?';
}
protected TrieNode(DataStructure D, char ch, int x, int y) {
super(D, ordinaryNode, x, y);
this.ch = ch;
}
protected TrieNode(DataStructure D, char ch) {
super(D, ordinaryNode, ZDepth.NODE);
this.ch = ch;
}
public TrieNode(DataStructure D) {
super(D, ordinaryNode, ZDepth.NODE);
ch = '?';
}
@Override
public TrieNode getParent() {
return (TrieNode) super.getParent();
}
@Override
public TrieNode getChild() {
return (TrieNode) super.getChild();
}
@Override
public TrieNode getRight() {
return (TrieNode) super.getRight();
}
void unsetGrey() {
TrieNode w = getChild();
while (w != null) {
w.unsetGrey();
w = w.getRight();
}
greyPair = false;
}
void drawGrey(View v) {
TrieNode w = getChild();
while (w != null) {
w.drawGrey(v);
w = w.getRight();
}
if (greyPair && getParent() != null) {
v.drawWideLine(x, y, getParent().x, getParent().y, 10.0f);
}
}
@Override
public void drawEdges(View v) {
if (state != INVISIBLE) {
if (thread) {
v.setColor(Color.red);
if (getChild() != null) {
v.drawFancyArc(x, y, getChild().x, getChild().y);
}
v.setColor(Color.black);
} else {
TreeNode w = getChild();
while (w != null) {
v.setColor(Color.DARK_GRAY);
v.drawFancyArc(x, y, w.x, w.y);
w.drawEdges(v);
w = w.getRight();
v.setColor(Color.black);
}
}
}
}
@Override
protected void drawBg(View v) {
v.setColor(Color.DARK_GRAY);
v.fillCircle(x, y, radius);
if (marked) {
v.setColor(Color.BLACK);
v.fillCircle(x, y, radius + 1);
}
}
@Override
public void draw(View v) {
if (state == Node.INVISIBLE || getKey() == NULL) {
return;
}
drawBg(v);
// drawKey(v);
drawLabel(v);
drawArrow(v);
drawArc(v);
}
public void drawLabel(View v) {
final TrieNode u = getParent();
if (u != null) {
int midx, midy, w, h;
if (ch == '$') {
midx = x - ((x - u.x) / 15);
midy = y - ((y - u.y) / 5 * 2) - 1;
w = 4;
h = 5;
v.setColor(NodeColor.DARKER.bgColor);
v.fillRoundRectangle(midx, midy, w, h, 4, 8);
v.setColor(NodeColor.DARKER.fgColor);
v.drawRoundRectangle(midx, midy, w, h, 4, 8);
// if (marked) {
// v.drawRoundRectangle(midx, midy, w + 2, h + 2, 5, 9);
// }
v.setColor(Color.BLACK);
v.drawString("" + ch, midx, midy - 1, Fonts.TYPEWRITER);
} else {
midx = x - ((x - u.x) / 15);
midy = y - ((y - u.y) / 5 * 2) - 1;
w = 6;
h = 7;
v.setColor(getBgColor());
v.fillRoundRectangle(midx, midy, w, h, 6, 10);
v.setColor(Color.BLACK);
v.drawRoundRectangle(midx, midy, w, h, 6, 10);
v.setColor(getFgColor());
v.drawString("" + ch, midx, midy - 1, Fonts.TYPEWRITER);
}
}
}
@Override
public void drawVertices(View v) {
TreeNode w = getChild();
while (w != null) {
w.drawVertices(v);
w = w.getRight();
}
draw(v);
}
public void clearExtraColor() {
TrieNode w = getChild();
while (w != null) {
w.clearExtraColor();
w = w.getRight();
}
setColor(NodeColor.NORMAL);
}
protected char getLabel() {
return ch;
}
public TrieNode getChildWithCH(char ch) {
TrieNode v = this.getChild();
if (v != null) {
while (v != null) {
if (ch == v.ch) {
return v;
}
v = v.getRight();
}
}
return null;
}
@Override
public void drawTree(View v) {
drawGrey(v);
super.drawTree(v);
}
/**
*
* @param ch
* A character which will be inserted in lexicographical order
* @return A node with proper label
*/
TrieNode addRight(char ch, int x, int y) {
if (getLabel() > ch) {
final TrieNode u = new TrieNode(D, ch);
u.setParent(getParent());
u.setRight(this);
getParent().setChild(u);
return u;
} else if (getLabel() == ch) {
return this;
} else {
final TrieNode v = getRight();
if ((v == null)) {
final TrieNode u = new TrieNode(D, ch);
u.setParent(getParent());
setRight(u);
return u;
} else {
if (v.getLabel() > ch) {
final TrieNode u = new TrieNode(D, ch);
u.setRight(getRight());
u.setParent(getParent());
setRight(u);
return u;
} else if (v.getLabel() < ch) {
return v.addRight(ch, x, y);
} else {
// if (c == 0)
return v;
}
}
}
}
/**
*
* @param ch
* A character which will be appended to this node
* @return A node appended
*/
public TrieNode addChild(char ch, int x, int y) {
final TrieNode v = getChild();
if (v == null) {
final TrieNode u = new TrieNode(D, ch, x, y);
setChild(u);
u.setParent(this);
return u;
} else {
return v.addRight(ch, x, y);
}
}
@Override
public String toString() {
return "" + ch;
}
@Override
public void storeState(Hashtable<Object, Object> state) {
super.storeState(state);
HashtableStoreSupport.store(state, hash + "ch", ch);
}
@Override
public void restoreState(Hashtable<?, ?> state) {
super.restoreState(state);
final Object ch = state.get(hash + "ch");
if (ch != null) {
this.ch = (Character) HashtableStoreSupport.restore(ch);
}
}
}