package org.limewire.mojito.visual;
import java.awt.BasicStroke;
import java.awt.Component;
import java.awt.Graphics2D;
import java.awt.Stroke;
import java.math.BigDecimal;
import java.net.SocketAddress;
import org.limewire.mojito.KUID;
import org.limewire.mojito.io.MessageDispatcher.MessageDispatcherEvent.EventType;
import org.limewire.mojito.messages.DHTMessage.OpCode;
/**<p>
* Draws graphical representations of the DHT. <code>Painter</code> creates
* different dash patterns depending on the DHT message type.
* </p><p>
* You need to implement:
* <ul>
* <li> {@link #paint(Component, Graphics2D)}: <code>paint</code> uses a
* {@link Graphics2D} object to draw.</li>
* <li>
* <code>handle(EventType, KUID, SocketAddress, OpCode, boolean)</code>:
* takes care of messages sent or received, the socket
* address and the DHT message code. <code>handle</code>
* can accumulate the information and later <code>paint</code> that information.</li>
* <li>
* {@link #clear()}: removes the accumulated information in which
* <code>handle</code> stores.</li>
* </ul>
*/
public abstract class Painter {
private static final int SCALE = 10;
public static final BigDecimal MAX_ID = new BigDecimal(KUID.MAXIMUM.toBigInteger(), SCALE);
public static final Stroke DEFAULT_STROKE = new BasicStroke(1.0f);
public static final Stroke TWO_PIXEL_STROKE = new BasicStroke(2.0f);
public abstract void paint(Component c, Graphics2D g);
public abstract void handle(EventType type, KUID nodeId, SocketAddress dst, OpCode opcode, boolean request);
public abstract void clear();
public static Stroke getStrokeForOpCode(OpCode opcode) {
float dash_phase = (float)Math.random() * 10f;
switch(opcode) {
case PING_REQUEST:
case PING_RESPONSE:
return new BasicStroke(1.0f, BasicStroke.CAP_ROUND,
BasicStroke.JOIN_ROUND, 10.0f,
new float[]{ 2f, 2f }, dash_phase);
case FIND_NODE_REQUEST:
case FIND_NODE_RESPONSE:
return new BasicStroke(1.0f, BasicStroke.CAP_ROUND,
BasicStroke.JOIN_ROUND, 10.0f,
new float[]{ 1f, 5f, 5f }, dash_phase);
case FIND_VALUE_REQUEST:
case FIND_VALUE_RESPONSE:
return new BasicStroke(1.0f, BasicStroke.CAP_ROUND,
BasicStroke.JOIN_ROUND, 10.0f,
new float[]{ 5f, 5f }, dash_phase);
case STORE_REQUEST:
case STORE_RESPONSE:
return new BasicStroke(1.0f, BasicStroke.CAP_ROUND,
BasicStroke.JOIN_ROUND, 10.0f,
new float[]{ 5f, 3f }, dash_phase);
default:
return DEFAULT_STROKE;
}
}
public static double position(KUID nodeId, double scale) {
return position(new BigDecimal(nodeId.toBigInteger(), SCALE), scale);
}
public static double position(BigDecimal nodeId, double scale) {
return nodeId.divide(MAX_ID, BigDecimal.ROUND_HALF_UP).multiply(BigDecimal.valueOf(scale)).doubleValue();
}
}