/**************************************************************************
* $Id: Display.java,v 1.1.1.1 2000/03/29 22:58:14 kkeys Exp $
*
* File: Display.java Name: Display
* Classes: Display,Hover_Check
* Class: Display
* Goal: Create a extended panel which will allow for display
* and editing of nodes and lines. It will also displays messages
* to the user throught a status bar which will appear on the
* bottom of the display.
*
* Mode: effects how Display handles events and what message
* is displayed in the status bar
* ADD_NODE: will add nodes on mouse down events
* ADD_LINK: will start a line on mouse down and finish it
* on mouse up
* SELECT: will the nearest object that is with in it size
* PROPERT: Not current implemented
* REMOVE: will remove the nearest object
* FORMAT: set when all events are to be ignored
* ROOT_SELECT: Not current implemented
* Should allow the user to select a parent and all
* nodes which are its children
* MOVE: changed where the screen is current focused on mouse
* down events
* ZOOM: will zoom with centers the points mouse down event is occured
*
* and links. It will also allow a GUI for thier
* creation, manipulation, and destruction
*
* Class: Hover_Check
* Goal: To have a class which checks the x, y ever so often and
* checks to see if the is a object near it and tells display to
* print it. This means that it must be a thread.
*
* Written: Bradley Huffaker (12/17/97)
* Modified: Jaeyeon Jung (2/20/97)
* To make it display World Map
*
* For:Cooperative Association for Internet Data Analysis
***************************************************************************
***************************************************************************
By accessing this software, DISPLAY, you are duly informed of and
agree to be bound by the conditions described below in this notice:
This software product, DISPLAY, is developed by Bradley Huffaker, and
Jaeyeon Jung copyrighted(C) 1998 by the University of California,
San Diego (UCSD), with all rights reserved. UCSD administers the NLANR
Cache grants, NCR-9796082 and NCR-9616602, under which most of this code
was developed.
There is no charge for DISPLAY software. You can redistribute it and/or
modify it under the terms of the GNU General Public License, v. 2 dated
June 1991 which is incorporated by reference herein. DISPLAY is
distributed WITHOUT ANY WARRANTY, IMPLIED OR EXPRESS, OF
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE or that the use of
it will not infringe on any third party's intellectual property
rights.
You should have received a copy of the GNU GPL along with the DISPLAY
program. Copies can also be obtained from
http://www.gnu.org/copyleft/gpl.html or by writing to
University of California, San Diego
SDSC/CAIDA/NLANR
9500 Gilman Dr., MS-0505
La Jolla, CA 92093 - 0505 USA
Or contact INFO@NLANR.NET
**************************************************************************/
package bhuffake.plankton;
import bhuffake.image.WorldProducer;
import bhuffake.image.WorldProducerInterface;
import java.net.*;
import java.awt.image.FilteredImageSource;
import java.io.*;
import bhuffake.tools.Strings;
import bhuffake.tools.StatusBar;
import java.awt.*;
import java.util.Date;
import java.lang.Math;
import java.awt.Dimension;
public class Display extends Panel implements WorldProducerInterface, Runnable
{
// Used to display the current status and other messages
protected StatusBar statusBar;
// Flag for when to redraw the whole image or use the old copy
protected boolean full_image_changed;
// Flag for when to redraw the left image or use the old copy
protected boolean left_image_changed;
// Flag for when to redraw the right image or use the old copy
protected boolean right_image_changed;
// Flag to indicate redrawing the whole map when size is changed
protected boolean size_changed;
// Flag to indicate redrawing the whole image when mouse is down
// at MOVE mode
protected boolean mouse_down = false;
// Drop redraw request when it is in the middle of drawing for SPEED
protected boolean is_drawing = false;
// Used to hold the offscreen image
protected Image full_offscreen;
protected int full_offscreen_height = 0;
protected int full_offscreen_width = 0;
// Used for displaying both image
protected Image left_offscreen;
protected int left_offscreen_height= 0;
protected int left_offscreen_width = 0;
protected Image right_offscreen;
protected int right_offscreen_height = 0;
protected int right_offscreen_width = 0;
protected Image both_screen;
protected int both_screen_height = 0;
protected int both_screen_width = 0;
// The Rectangle that contains all nodes
protected int node_height = 0;
protected int node_width = 0;
// The net size of panel where node will be placed
protected int width, height;
// Map stuff - jjung
protected double top_lat, top_lon;
protected double bot_lat, bot_lon;
protected double source_top_lat, source_top_lon;
protected double source_bot_lat, source_bot_lon;
protected Image image;
protected Image source_image;
protected Image default_image;
protected boolean showMap = false;
protected boolean viewGeo = false;
protected boolean setMap = false;
protected boolean stepBystep = false;
WorldProducer worldProducer;
protected int current_step;
final double MAX_ZOOM = .003;
double scaler;
// List of nodes and links
// List of selected nodes and links
protected DList dlist;
protected DList selected;
protected DList ordered;
// This handles mouse motion stuff
protected DisplayObject mouse_down_selected = null;
protected boolean mouse_dragged = false;
// The date of the file
protected Date date = null;
static final public int FULL = 0;
static final public int RIGHT = 1;
static final public int LEFT = 2;
// Holds the mode that the display is current in
protected int mode;
static final public int ADD_NODE = 0;
static final public int ADD_LINK = 1;
static final public int SELECT = 2;
static final public int ROOT_SELECT = 3;
static final public int SELECT_TREE = 4;
static final public int PROPERT = 5;
static final public int REMOVE = 6;
static final public int FORMAT = 7;
static final public int ANIMATE = 9;
static final public int ZOOM = 10;
static final public int STEP_BY_STEP = 11;
static final public int MOVE = 12;
static final public String ADD_NODE_STR = "Add Node";
static final public String ADD_LINK_STR = "Add Link";
static final public String SELECT_STR = "Select Object";
static final public String ROOT_SELECT_STR = "Select Root";
static final public String SELECT_TREE_STR = "Select Tree";
static final public String PROPERT_STR = "Properties";
static final public String REMOVE_STR = "Remove Object";
static final public String FORMAT_STR = "Formating Nodes";
static final public String ANIMATE_STR = "Animating";
static final public String ZOOM_STR = "Zoom";
static final public String STEP_BY_STEP_STR = "Step by Step";
static final public String MOVE_STR = "Move";
// Holds the current resolution of the objects
protected int res;
static final public int LOW = 0;
static final public int HIGH = 1;
static final public String LOW_STRING = "Low Res";
static final public String HIGH_STRING = "High Res";
// Old x and Old y are used in a mouse drag to find the change
// and move all the selected objects by that change
int old_x, old_y;
// Used in the handleEvent to tell if the user is hovering over
// a object rather just scanning to it.
int MIN_MOUSE_HOVER = 10;
// This is used by the addlink methods to add a link between
// two nodes
Node addlink_node;
Link addlink_link;
// Color by HTTP or DOMAIN
static final public int COLOR_HTTP = 0;
static final public int COLOR_DOMAIN = 1;
protected boolean viewBoth = false;
// This allows for mouse motion
int x_shift = 0;
int y_shift = 0;
// This limits the number to times it checks for closeness
Check_Hover check_hover;
// Keeps track of the number of files are current being used.
int num_files = 1;
int current_fileIndex =0;
// ------- Animation Stuff -----------------------------
// A array of images one for each file. Which it then flips throw
// for the animation.
Image[] slids;
// The controlling thread
Thread myThread;
// The sleep time
long sleep_length= 1000;
// the number of times to go throught the slid show;
int slid_times = 1;
// The animator class
DisplayInterface animator;
// Color stuff
ColorMaskFrame colorMaskFrame;
public Display()
{
setBackground(Color.white);
statusBar = new StatusBar();
printMessage("");
dlist = new DList();
selected = new DList();
check_hover = new Check_Hover(this);
check_hover.start();
setViewBoth(false);
width = size().width;
height = size().height - statusBar.getHeight();
full_image_changed = true;
}
public Display(Image image, double top_lat_input, double top_lon_input, double bot_lat_input, double bot_lon_input)
{
this();
source_image = image;
source_top_lat = top_lat_input;
source_top_lon = top_lon_input;
source_bot_lat = bot_lat_input;
source_bot_lon = bot_lon_input;
}
/********************************************************
* Purpose: To set up the shift created by the scroll bars
* Currently not implement because Plankton can't seem
* to get the scoll bars to work
*
*********************************************************/
public void Shift_X(float shift) {}
public void Shift_Y(float shift) {}
/********************************************************
* Purpose: To set the current mode and display it in the
* status bar.
*********************************************************/
public void setMode(int mode_type)
{
mode = mode_type;
switch (mode)
{
case ADD_NODE: statusBar.setString(ADD_NODE_STR,0);
break;
case ADD_LINK: statusBar.setString(ADD_LINK_STR,0);
break;
case SELECT: statusBar.setString(SELECT_STR,0);
break;
case ROOT_SELECT:
statusBar.setString(ROOT_SELECT_STR,0);
break;
case SELECT_TREE:
statusBar.setString(SELECT_TREE_STR,0);
break;
case PROPERT: statusBar.setString(PROPERT_STR,0);
break;
case REMOVE: statusBar.setString(REMOVE_STR,0);
break;
case FORMAT:
statusBar.setString(FORMAT_STR,0);
break;
case ANIMATE: statusBar.setString(ANIMATE_STR,0);
break;
case ZOOM: statusBar.setString(ZOOM_STR,0);
break;
case STEP_BY_STEP: statusBar.setString(STEP_BY_STEP_STR,0);
break;
case MOVE: statusBar.setString(MOVE_STR,0);
break;
default:
mode = MOVE;
statusBar.setString(MOVE_STR,0);
}
repaintStatusBar();
}
/********************************************************
* Purpose: To get the current mode
*********************************************************/
public int getMode() { return mode; }
/********************************************************
* Purpose: To set the current resolution.
*********************************************************/
public void setRes(int res_type)
{
setResNoPaint(res_type);
repaintNodes();
}
/********************************************************
* Purpose: To set the current resolution.
*********************************************************/
public void setResNoPaint(int res_type)
{
res = res_type;
boolean little_on = false;
if (res == LOW)
{
statusBar.setString(LOW_STRING,1);
little_on = true;
}
else
{
statusBar.setString(HIGH_STRING,1);
little_on = false;
}
if (dlist == null)
return;
DList mylist = dlist.DList();
mylist.reset();
while(!mylist.end())
mylist.next().setLittle(little_on);
repaintStatusBar();
}
/********************************************************
* Purpose: resize of the box
*********************************************************/
public void mapSizeChange()
{
if(image == null)
return;
if (worldProducer == null )
{
worldProducer = new WorldProducer(source_image,
top_lon, top_lat, bot_lon, bot_lat,
width, height);
worldProducer.setParent(this);
}
else
worldProducer.setSize(width,height);
image = createImage(worldProducer);
full_image_changed = true;
right_image_changed = true;
size_changed = true;
}
/********************************************************
* Purpose: Allow for other Classes to print things in the
* Status bar.
*********************************************************/
public void printMessage(String message)
{
statusBar.setString(message,2);
repaintStatusBar();
}
/********************************************************
* Purpose: Gets the current string in the status Bar
*********************************************************/
public String getMessage()
{
return(statusBar.getString(2));
}
/********************************************************
* Purpose: Sets the current display list (ie the list of
* nodes and lines)
*********************************************************/
public void setList(DList list)
{
setListNoPaint(list);
repaintNodes();
}
/********************************************************
* Purpose: Sets the current display list (ie the list of
* nodes and lines) with out redrawing the image
* used when loading.
*********************************************************/
public void setListNoPaint(DList list)
{
dlist = list;
if (colorMaskFrame != null)
colorMaskFrame.setList(dlist);
selected.clear();
full_image_changed = true;
left_image_changed = true;
right_image_changed = true;
}
/********************************************************
* Purpose:Sets the date for the current list
*********************************************************/
public void setDate(Date date_input)
{
date = date_input;
}
public void setMap()
{
top_lat = source_top_lat;
top_lon = source_top_lon;
bot_lat = source_bot_lat;
bot_lon = source_bot_lon;
// bhuffake To remove the possible of crash caused
// by lack of image.
if (source_image != null)
{
worldProducer = new WorldProducer(source_image,
top_lon, top_lat,bot_lon, bot_lat,
width,height);
worldProducer.setParent(this);
image = createImage(worldProducer);
default_image = image;
size_changed = false;
setMap = true;
}
}
public void showAllNames() { showNames(true); }
public void showRootNames() { showNames(false); }
protected void showNames(boolean showAll)
{
DList mylist = dlist.DList();
mylist.reset();
while (!mylist.end())
{
DisplayObject object = mylist.next();
if (object instanceof Node)
{
if (showAll || ((Node)object).isRoot())
((Node)object).showName();
else
((Node)object).hideName();
}
}
repaintNodes();
}
public void hideNames()
{
DList mylist = dlist.DList();
mylist.reset();
while (!mylist.end())
{
DisplayObject object = mylist.next();
if (object instanceof Node)
((Node)object).hideName();
}
repaintNodes();
}
public void setShowMap(boolean flag)
{
showMap = flag;
}
public boolean isShowMap()
{
return showMap;
}
public void setViewGeo(boolean flag)
{
viewGeo = flag;
}
public boolean isViewGeo()
{
return viewGeo;
}
public void setViewBoth(boolean flag)
{
if(viewBoth && !flag)
width = size().width;
if(!viewBoth && flag)
width = size().width / 2;
size_changed = true;
viewBoth = flag;
}
public boolean isViewBoth()
{
return viewBoth;
}
public void setMap(boolean flag)
{
setMap = flag;
}
public boolean isSetMap()
{
return setMap;
}
public void RootORGeo()
{
DList mylist = dlist.DList();
mylist.reset();
while (!mylist.end())
{
DisplayObject object = mylist.next();
object.onMap(isViewGeo());
if (object instanceof Node )
{
Node node = (Node)object;
if (isViewGeo())
{
node.setToGeoXYNoFlag();
}
else
{
// This made it so that the objects
// could not be moved. But is required
// To make this zoom. Needs to be
// fixed.
// Braldey Huffaker
node.setToRootXYNoFlag();
}
}
}
}
public void forcedDraw()
{
is_drawing = false;
}
/********************************************************
* Purpose:
*********************************************************/
public DList getList()
{
return dlist;
}
/********************************************************
* Purpose:
*********************************************************/
public DList getOrderedList()
{
return ordered;
}
public void setOrderedList(DList list)
{
ordered = list;
}
/********************************************************
* Purpose:To select which fileIndex to use
*********************************************************/
public void setFileIndex(int fileIndex)
{
setFileIndexNoPaint(fileIndex);
if (colorMaskFrame != null && colorMaskFrame.inUse())
colorMaskFrame.Color();
else
repaintNodes();
}
/********************************************************
* Purpose:To select which fileIndex to use
*********************************************************/
public void setFileIndexNoPaint(int fileIndex)
{
current_fileIndex = fileIndex;
DList mylist = dlist.DList();
mylist.reset();
while(!mylist.end())
{
DisplayObject object = mylist.next();
object.setFileIndex(fileIndex);
}
}
/********************************************************
* Purpose:To set the number of files current in use
*********************************************************/
public void setNumFiles(int numFiles)
{
num_files = numFiles;
}
/********************************************************
* Purpose:To get the number of files the list has
*********************************************************/
public int getNumFiles() { return num_files; }
/********************************************************
* Purpose:
*********************************************************/
public void deselectAll()
{
while (!selected.empty())
selected.pop().setSelect(false);
while (!nearest_objects.empty())
nearest_objects.pop().setHighlight(false);
repaintNodes();
}
/********************************************************
* Purpose:To take in a string find all nodes that contain
* that string in their name
*********************************************************/
public void selectByName(String string)
{
printMessage("Searching ...");
char[] array = string.toCharArray();
// Remove white space at the front
int start = 0;
while (start < array.length-1 && (array[start] == ' '
|| array[start] == '\t'))
start++;
// Remove white space at the end and check to see
// if it is a ip address
int end = start;
while (end < array.length && array[end] != ' '
&& array[end] != '\t')
end++;
string = new String(array,start,end-start);
while (!selected.empty())
selected.pop().setSelect(false);
DList mylist = dlist.DList();
mylist.reset();
boolean found = false;
int num_found = 0;
while(!mylist.end())
{
DisplayObject object = mylist.next();
if (object instanceof Node)
{
Node node = (Node) object;
if (node.getName().indexOf(string) >= 0)
{
found = true;
node.setRoot(true);
//node.setSelect(true);
//selected.push(node);
num_found++;
}
else
node.setRoot(false);
}
}
if (!found)
printMessage("Unable to find any nodes");
else
printMessage("Nodes matched:"+ num_found);
repaintNodes();
}
public void lineSize(int size_input)
{
int min = size_input;
DList mylist = dlist.DList();
mylist.reset();
while (!mylist.end())
{
DisplayObject object = mylist.next();
if (object instanceof Link)
{
int old = object.getSize();
if (old + size_input <= 0)
{
if(old -1 < (-1*min))
min = 1 - old;
}
}
}
mylist.reset();
while (!mylist.end())
{
DisplayObject object = mylist.next();
if (object instanceof Link)
{
int old = object.getSize();
object.setSize(min+old);
}
}
if (min != size_input)
printMessage("Link size can't be smaller than 0 ");
else
printMessage("");
repaintNodes();
}
public void nodeSize(int size_input)
{
int min = size_input;
DList mylist = dlist.DList();
mylist.reset();
while (!mylist.end())
{
DisplayObject object = mylist.next();
if (object instanceof Node)
{
int old = object.getSize();
if (old + size_input <= 0)
{
if(old -1 < (-1*min))
min = 1 - old;
}
}
}
mylist.reset();
while (!mylist.end())
{
DisplayObject object = mylist.next();
if (object instanceof Node)
{
int old = object.getSize();
object.setSize(min+old);
}
}
if (min != size_input)
printMessage("Node size can't be smaller than 0 ");
else
printMessage("");
repaintNodes();
}
public void rotate(double degree_input)
{
double radian = (degree_input/180) * Math.PI;
double theta;
double x,y;
int[] root_xy;
int[] center_xy = centerRootXY();
double r;
DList mylist = dlist.DList();
mylist.reset();
while (!mylist.end())
{
DisplayObject object = mylist.next();
if (object instanceof Node)
{
root_xy = ((Node)object).getRootXY();
r = Math.sqrt
(Math.pow((double)
(root_xy[0]-center_xy[0]), (double)2)+
Math.pow((double)
(root_xy[1]-center_xy[1]), (double)2));
double delta_x = (double)(root_xy[0]-
center_xy[0]);
double delta_y = (double)(root_xy[1]-
center_xy[1]);
if(delta_x==0)
{
if(delta_y > 0)
theta = Math.PI/2;
else
theta = 3*Math.PI/2;
}
else
{
theta = Math.atan(delta_y/delta_x);
if(delta_x > 0)
theta = 2*Math.PI+theta;
else
theta = Math.PI+theta;
}
x = r * Math.cos(theta+radian) + center_xy[0];
y = r * Math.sin(theta+radian) + center_xy[1];
((Node)object).setRootXY((int)x,(int)y);
}
}
if(isViewBoth())
repaintLeftNodes();
else
repaintNodes();
}
/********************************************************
* Purpose:To scale all the nodes xy by some scaler
*********************************************************/
public void scale(double scaler_input)
{
scaler = scaler_input;
printMessage("Click the point you are in terested");
/*
if (isViewGeo())
{
scaler = 1/scaler_input;
printMessage("Click the point you are in terested");
}
else
{
scaler = scaler_input;
printMessage("Click the point you are in terested");
//printMessage("Zooming ... Please wait");
//zoomNoMap(scaler_input);
//printMessage("");
//recenter();
//repaintNodes();
}
*/
}
public void zoom(double scaler_input)
{
double lon = (top_lon + bot_lon)/2;
double lat = (top_lat + bot_lat)/2;
zoom(lon,lat,scaler_input);
}
public void zoom(double t_lon, double t_lat, double b_lon, double b_lat)
{
while(t_lon >= b_lon)
b_lon += 360;
double lon = (t_lon + b_lon)/2;
double lat = (t_lat + b_lat)/2;
double scaler = (b_lon - t_lon)/(bot_lon - top_lon);
zoom(lon,lat,scaler);
}
public void zoom(int x, int y, double scaler_input)
{
double latlong[] = FromMap(x,y);
if (isViewGeo())
zoom(latlong[1],latlong[0],scaler_input);
else
{
printMessage("Zooming ... Please wait");
zoomNoMap(scaler_input);
recenter();
}
}
public void zoom(double m_lon, double m_lat, double scaler_input)
{
double lat_size, lon_size;
if (top_lat < bot_lat)
lat_size = (bot_lat - top_lat) * scaler_input;
else
lat_size = (top_lat - bot_lat) * scaler_input;
if (top_lon < bot_lon)
lon_size = (bot_lon - top_lon) * scaler_input;
else
lon_size = (top_lon - bot_lon) * scaler_input;
if (lon_size/360 < MAX_ZOOM)
return;
if (lat_size >180)
{
lon_size = lon_size* 180/lat_size;
lat_size = 180;
}
if (lon_size >360)
{
lat_size = lat_size* 360/lon_size;
lon_size = 360;
}
double t_lat = m_lat + lat_size/2;
double t_lon = m_lon - lon_size/2;
double b_lat = m_lat - lat_size/2;
double b_lon = m_lon + lon_size/2;
while (t_lon < -180)
{
t_lon += 360;
b_lon += 360;
}
while (t_lon > 180)
{
t_lon -= 360;
b_lon -= 360;
}
while (t_lat > 90)
{
b_lat -= t_lat -90;
t_lat = 90;
}
while (b_lat < -90)
{
t_lat -= b_lat +90;
b_lat = -90;
}
top_lon = t_lon;
top_lat = t_lat;
bot_lon = b_lon;
bot_lat = b_lat;
if(isShowMap()|| isViewBoth())
{
printMessage("Loading Image, Please wait....");
if (worldProducer != null)
worldProducer.abort();
worldProducer.setBox(top_lon,top_lat,bot_lon,bot_lat);
image = createImage(worldProducer);
if(size_changed)
mapSizeChange();
}
ChangeGeoXY();
}
public void ChangeGeoXY()
{
DList mylist = dlist.DList();
mylist.reset();
while (!mylist.end())
{
DisplayObject object = mylist.next();
if (object instanceof Node)
{
double lat = object.getLatitude();
double lon = object.getLongitude();
int[] xy = ToMap(lat,lon);
((Node)object).setGeoXY(xy[0],xy[1]);
}
}
}
public void ChangeRootXY()
{
int[] minmax = MinMaxRootXY();
int min_x = minmax[0];
int min_y = minmax[1];
int max_x = minmax[2];
int max_y = minmax[3];
if (max_x*max_y*width*height !=0)
{
node_width = width + 10;
node_height = height + 10;
if (max_x > width || max_y > height)
{
if((double)max_x/width > (double)max_y/height)
zoomNoMap((double)width/max_x);
else
zoomNoMap((double)height/max_y);
}
else
{
if((double)width/max_x > (double)height/max_y)
zoomNoMap((double)height/max_y);
else
zoomNoMap((double)width/max_x);
}
}
recenter();
}
protected int[] MinMaxRootXY ()
{
DList mylist = dlist.DList();
mylist.reset();
int min_x = 10;
int min_y = 20;
int max_x = 0;
int max_y = 0;
int[] minmax = new int[4];
while(!mylist.end())
{
DisplayObject object = mylist.next();
if (object instanceof Node)
{
int[] xy = ((Node)object).getRootXY();
if (xy[0] < min_x)
min_x = xy[0];
if (xy[0] > max_x)
max_x = xy[0];
if (xy[1] < min_y)
min_y = xy[1];
if (xy[1] > max_y)
max_y = xy[1];
}
}
if (min_x != 10 || min_y != 20)
{
mylist.reset();
min_x = 10 - min_x;
min_y = 20 - min_y;
while(!mylist.end())
{
DisplayObject object = mylist.next();
if (object instanceof Node)
((Node)object).changeRootXY(min_x,min_y);
}
max_x += min_x;
max_y += min_y;
}
minmax[0] = min_x;
minmax[1] = min_y;
minmax[2] = max_x;
minmax[3] = max_y;
return minmax;
}
public void zoomNoMap(double scaler_input)
{
DList mylist = dlist.DList();
mylist.reset();
while (!mylist.end())
{
DisplayObject object = mylist.next();
if (object instanceof Node)
((Node)object).scaleRootXY(scaler_input);
}
}
public int[] ToMap(double lat, double lon)
{
int[] xy = new int[2];
double boundary = (top_lon + bot_lon)/2 - 180;
while (lon < boundary )
lon += 360.0;
xy[0] = (int) (
((lon - top_lon) * width) / (bot_lon - top_lon));
xy[1] = (int) (
((top_lat - lat) * height) / (top_lat - bot_lat));
return xy;
}
public double[] FromMap(int x, int y)
{
double[] node_lat_lon = new double[2];
node_lat_lon[0] = top_lat - ((double) y * (top_lat - bot_lat) /
(double) height);
node_lat_lon[1] = top_lon + ((double) x * (bot_lon - top_lon) /
(double) width);
return node_lat_lon;
}
/********************************************************
* Purpose:To display all objects step by step
*********************************************************/
public void stepBystepNoPaint(boolean flag)
{
stepBystep = flag;
}
public void stepBystep(boolean flag)
{
stepBystep = flag;
repaintNodes();
}
public void stepBystep(int current_step_input)
{
stepBystep = true;
current_step = current_step_input;
repaintNodes();
}
public boolean isStepByStep()
{
return stepBystep;
}
/********************************************************
* Purpose:To color all objects by there top level domain
*********************************************************/
public void colorByMask(int http_domain)
{
if (colorMaskFrame != null)
colorMaskFrame.hide();
switch (http_domain) {
case COLOR_HTTP:
colorMaskFrame = new ColorMaskFrame(this,dlist,
num_files,current_fileIndex,
http_domain, "Mask/Color by HTTP Request");
break;
case COLOR_DOMAIN:
colorMaskFrame = new ColorMaskFrame(this,dlist,
num_files,current_fileIndex, http_domain,
"Mask/Color by Top Level Domain Name");
break;
}
colorMaskFrame.inUse(true);
colorMaskFrame.toFront();
colorMaskFrame.show();
colorMaskFrame.Color();
}
/*******************************************************
* Purpose: To color by defualt colors
*******************************************************/
public void colorByDefault()
{
DList mylist = dlist.DList();
mylist.reset();
while(!mylist.end())
mylist.next().setToDefaultColor();
printMessage("Colored by Default");
repaintNodes();
}
/*********************************************************
* Purpose:To paint out the current date of the network
**********************************************************/
public void paintDate()
{
String string = "none given";
if (date != null)
{
string = "Network date: "
+date.getDate()+"/";
switch (date.getMonth())
{
case 1: string = string + "JAN"; break;
case 2: string = string + "FEB"; break;
case 3: string = string + "MAR"; break;
case 4: string = string + "APR"; break;
case 5: string = string + "MAY"; break;
case 6: string = string + "JUN"; break;
case 7: string = string + "JUL"; break;
case 8: string = string + "AGU"; break;
case 9: string = string + "SEP"; break;
case 10: string = string + "OCT"; break;
case 11: string = string + "NOV"; break;
case 12: string = string + "DEC"; break;
}
string = string + "/" + (date.getYear() + 1900);
}
printMessage("Network date: "+string);
}
/********************************************************
* Purpose:
*********************************************************/
public void Clear()
{
dlist.clear();
colorByDefault();
printMessage("Network Cleared");
}
/********************************************************
* Purpose:
*********************************************************/
public void paint(Graphics g)
{
Dimension dim = size();
FontMetrics fm = getFontMetrics(getFont());
statusBar.draw(g,dim,fm);
paintNodes(g, dim);
}
/********************************************************
* Purpose:
*********************************************************/
public void repaintStatusBar()
{
Font font = getFont();
// This checks to see if the font has been initialized
if (font != null)
{
Graphics g = getGraphics();
Dimension dim = size();
FontMetrics fm = getFontMetrics(font);
statusBar.draw(g,dim,fm);
}
}
/********************************************************
* Purpose:
*********************************************************/
public void repaintNodes()
{
full_image_changed = true;
left_image_changed = true;
right_image_changed = true;
paintNodes(getGraphics(), size());
}
public void repaintLeftNodes()
{
left_image_changed = true;
paintNodes(getGraphics(), size());
}
public void repaintRightNodes()
{
right_image_changed = true;
paintNodes(getGraphics(), size());
}
/********************************************************
* Purpose: ruturn the dimension for nodes and links
(with extracting the area for statusBar)
*********************************************************/
public Dimension displaySize()
{
return new Dimension(width,height);
}
protected void paintNodes(Graphics g, Dimension dim)
{
Image half_screen = null;
int x_shift_paint = x_shift;
int y_shift_paint = y_shift;
if (is_drawing){
printMessage("Please wait, it is busy drawing images now....");
return;
}
is_drawing = true;
printMessage("Drawing images....");
if ((isViewBoth() && (width != dim.width/2 ||
height != dim.height - statusBar.getHeight())) ||
(!isViewBoth() && (width != dim.width ||
height != dim.height - statusBar.getHeight())))
{
size_changed = true;
full_image_changed = true;
left_image_changed = true;
right_image_changed = true;
if (isViewBoth())
width = dim.width/2;
else
width = dim.width;
height = dim.height - statusBar.getHeight();
if(isShowMap() || isViewBoth())
mapSizeChange();
ChangeGeoXY();
ChangeRootXY();
}
// Redraw the offscreen image (ie that complete image)
// if you have to
if(!isViewBoth() && full_image_changed)
{
CheckRootNodeSize();
redrawOffscreen(FULL);
}
if (isViewBoth() &&left_image_changed)
{
setShowMap(false);
setViewGeo(false);
CheckRootNodeSize();
redrawOffscreen(LEFT);
}
if (isViewBoth() &&right_image_changed)
{
setShowMap(true);
setViewGeo(true);
redrawOffscreen(RIGHT);
}
int statusBarheight = statusBar.getHeight();
int clip_height = dim.height - statusBarheight;
// Redraw from the original image onto the clipped image
g.clipRect(0,0,dim.width,clip_height);
g.setColor(getBackground());
if(!isViewBoth())
{
if (isViewGeo())
{
x_shift_paint = 0;
y_shift_paint = 0;
}
g.drawImage(full_offscreen,x_shift_paint,y_shift_paint,this);
// Not to fill background with bizarre color
g.setColor(getBackground());
if (x_shift_paint > 0)
g.fillRect(0,0,x_shift_paint,clip_height);
if (dim.width > full_offscreen_width + x_shift_paint)
{
int erase_x = full_offscreen_width + x_shift_paint;
int erase_width = dim.width - erase_x;
g.fillRect(erase_x,0,erase_width,clip_height);
}
if (clip_height > full_offscreen_height + y_shift_paint)
{
int erase_y = full_offscreen_height + y_shift_paint;
int erase_height = clip_height - erase_y;
g.fillRect(0,erase_y,width,erase_height);
}
}
else
{
//to draw the offscreen image on only half of the screen
//at the expense of speed
//otherwise, it produce weird images sometimes
if(half_screen == null)
half_screen = createImage(width,height);
Graphics half_graphics = half_screen.getGraphics();
half_graphics.clipRect(0,0,width,height);
half_graphics.setColor(getBackground());
half_graphics.fillRect(0,0,width,height);
half_graphics.drawImage(left_offscreen,x_shift_paint,y_shift_paint,this);
g.drawImage(half_screen,0,0,this);
//g.drawImage(left_offscreen,x_shift_paint,y_shift_paint,this);
// Not to fill background with bizarre color
g.setColor(getBackground());
if (x_shift_paint > 0)
g.fillRect(0,0,x_shift_paint,clip_height);
if (width > left_offscreen_width + x_shift_paint)
{
int erase_x = left_offscreen_width + x_shift_paint;
int erase_width = width - erase_x;
g.fillRect(erase_x,0,erase_width,clip_height);
}
if (clip_height > left_offscreen_height + y_shift_paint)
{
int erase_y = left_offscreen_height + y_shift_paint;
int erase_height = clip_height - erase_y;
g.fillRect(0,erase_y,width,erase_height);
}
half_screen.flush();
half_graphics.setColor(getBackground());
half_graphics.fillRect(0,0,width,height);
half_graphics.drawImage(right_offscreen,0,0,this);
g.drawImage(half_screen,width,0,this);
//g.drawImage(right_offscreen,dim.width/2,0,this);
}
// The following four ifs take care of the times when the image
// of the network is shifted off the screen. leaving blank space.
if (y_shift_paint > 0)
g.fillRect(0,0,width,y_shift_paint);
if (statusBarheight <= 0)
{
g.clipRect(0,0,dim.width,dim.height);
FontMetrics fm = getFontMetrics(getFont());
statusBar.draw(g,dim,fm);
}
printMessage("");
is_drawing = false;
}
protected void drawStepByStep(Graphics g)
{
DList ordered_mylist;
ordered_mylist = ordered.DList();
int rank = -1;
int count = ordered_mylist.count();
//when reverse order is needed
//int index = count;
int index = 0;
Node[] nodes = new Node[count];
DList links = new DList();
DList node_list = new DList();
ordered_mylist.reset();
while(!ordered_mylist.end())
{
DisplayObject object = ordered_mylist.next();
if(object instanceof Node)
{
Node node = (Node)object;
if(object.exists())
nodes[index++] = node;
//when reverse order is needed
// nodes[--index] = node;
}
}
DList mylist = dlist.DList();
mylist.reset();
while(!mylist.end())
mylist.next().hide();
int node_rank = 0;
for(int i = 0; i < index; i ++)
{
node_rank = nodes[i].getRank();
if(node_rank > current_step) {
if(current_step > 0)
printMessage ("Current level: " +current_step);
else if (current_step == 0)
printMessage ("Click [Next] to start");
break;
}
if(rank != node_rank && i > 0 )
{
links.reset();
while(!links.empty())
{
DisplayObject object = links.pop();
if(object.exists()) {
object.show();
//System.err.println(((Link)object).getString());
object.draw(g,displaySize(),getLatLon());
}
//(links.pop()).draw(g,displaySize(),getLatLon());
}
node_list.reset();
while(!node_list.end())
{
DisplayObject object = node_list.next();
if(object.exists()) {
object.show();
object.draw(g,displaySize(),getLatLon());
}
//(node_list.next()).draw(g,displaySize(),getLatLon());
}
}
else
{
DList node_link = nodes[i].getLink();
node_link.reset();
while(!node_link.end())
links.enqueue(node_link.next());
}
nodes[i].show();
nodes[i].draw(g,displaySize(),getLatLon());
node_list.enqueue(nodes[i]);
rank = node_rank;
}
if (node_rank <= current_step)
printMessage ("The end of hierarchy");
//stepBystepNoPaint(false);
full_image_changed = true;
left_image_changed = true;
right_image_changed = true;
}
protected void redrawOffscreen(int which_screen)
{
Image offscreen = null;
int offscreen_width = 0;
int offscreen_height = 0;
boolean image_changed = false;
switch (which_screen)
{
case FULL:
offscreen = full_offscreen;
offscreen_width = full_offscreen_width;
offscreen_height = full_offscreen_height;
image_changed = full_image_changed;
break;
case LEFT:
offscreen = left_offscreen;
offscreen_width = left_offscreen_width;
offscreen_height = left_offscreen_height;
image_changed = left_image_changed;
break;
case RIGHT:
offscreen = right_offscreen;
offscreen_width = right_offscreen_width;
offscreen_height = right_offscreen_height;
image_changed = right_image_changed;
break;
}
if (node_width < width)
node_width = width;
if (node_height < height)
node_height = height;
if (offscreen == null
|| node_width > offscreen_width
|| node_height > offscreen_height)
{
image_changed = true;
if (node_width > offscreen_width)
offscreen_width = node_width;
if (node_height > offscreen_height)
offscreen_height = node_height;
if (offscreen != null)
offscreen.flush();
offscreen = createImage(offscreen_width
,offscreen_height);
}
if(!image_changed)
return;
Graphics g = offscreen.getGraphics();
FontMetrics fm = getFontMetrics(getFont());
// Need to clear the slate clear
g.setColor(getBackground());
g.fillRect(0,0,offscreen_width,offscreen_height);
if (image != null && isShowMap())
g.drawImage(image,0,0,this);
if (which_screen == LEFT)
setViewGeo(false);
else if (which_screen == RIGHT)
setViewGeo(true);
RootORGeo();
DList mylist;
if(!this.isStepByStep())
{
mylist = dlist.DList();
mylist.reset();
while(!mylist.end())
{
DisplayObject object = mylist.next();
object.draw(g,displaySize(),getLatLon());
}
}
else
drawStepByStep(g);
switch (which_screen)
{
case FULL:
full_offscreen = offscreen;
full_offscreen_width = offscreen_width;
full_offscreen_height = offscreen_height;
full_image_changed = false;
break;
case LEFT:
left_offscreen = offscreen;
left_offscreen_width = offscreen_width;
left_offscreen_height = offscreen_height;
left_image_changed = false;
break;
case RIGHT:
right_offscreen = offscreen;
right_offscreen_width = offscreen_width;
right_offscreen_height = offscreen_height;
right_image_changed = false;
break;
}
}
/***********************************************************
* Purpose: to find out if any of the nodes will be draw outside
* of the offscreen image. If so it finds where the
* new bondray should be.
************************************************************/
protected void CheckRootNodeSize()
{
int[] minmax = MinMaxRootXY();
int min_x = minmax[0];
int min_y = minmax[1];
int max_x = minmax[2];
int max_y = minmax[3];
if (max_x > node_width - 10 || max_y > node_height - 10)
{
node_width = max_x + 10;
node_height = max_y + 10;
}
}
/********************************************************
* Purpose:
*********************************************************/
public void recenter()
{
// It doesn't make sense when nodes are formatted with geo
if (isViewGeo())
return;
CheckRootNodeSize();
/*
boolean set = false;
int xy[] = null;
int num_nodes = 0;
int center_x = 0;
int center_y = 0;
DList mylist = dlist.DList();
mylist.reset();
while(!mylist.end())
{
DisplayObject object = mylist.next();
if (object instanceof Node)
{
num_nodes++;
if (set)
{
xy = ((Node)object).getRootXY();
center_x += xy[0];
center_y += xy[1];
}
else
{
xy = ((Node)object).getRootXY();
center_x = xy[0];
center_y = xy[1];
set = true;
}
}
}
if (num_nodes > 0)
*/
int[] center_xy = centerRootXY();
int center_x = center_xy[0];
int center_y = center_xy[1];
if (center_x >= 0 && center_y >= 0)
{
Dimension dim = displaySize();
x_shift = dim.width/2 - center_x;
y_shift = dim.height/2- center_y;
//x_shift = dim.width/2 - (center_x/num_nodes);
//y_shift = dim.height/2- (center_y/num_nodes);
}
}
public int[] centerRootXY()
{
boolean set = false;
int xy[] = null;
int num_nodes = 0;
int center_xy[] = new int[2];
int center_x = 0;
int center_y = 0;
DList mylist = dlist.DList();
mylist.reset();
while(!mylist.end())
{
DisplayObject object = mylist.next();
if (object instanceof Node)
{
num_nodes++;
if (set)
{
xy = ((Node)object).getRootXY();
center_x += xy[0];
center_y += xy[1];
}
else
{
xy = ((Node)object).getRootXY();
center_x = xy[0];
center_y = xy[1];
set = true;
}
}
}
if (num_nodes > 0)
{
center_xy[0] = center_x/num_nodes;
center_xy[1] = center_y/num_nodes;
return center_xy;
}
center_xy[0] = -1;
center_xy[1] = -1;
return center_xy;
}
/********************************************************
* Purpose:To handle the mouse events
*********************************************************/
Date last_move_date = new Date();
public boolean handleEvent(Event event)
{
// Shifts the give x,y by the shift
int x_shift_handle_event = x_shift;
int y_shift_handle_event = y_shift;
boolean event_at_right = false;
if (isViewBoth() && event.x > width)
{
event.x = event.x - width;
x_shift_handle_event = 0;
y_shift_handle_event = 0;
event_at_right = true;
}
else if (!isViewBoth() && isViewGeo())
{
x_shift_handle_event = 0;
y_shift_handle_event = 0;
event_at_right = true;
}
else
event_at_right = false;
event.x -= x_shift_handle_event;
event.y -= y_shift_handle_event;
if (mode == FORMAT || mode == ANIMATE)
return super.handleEvent(event);
switch(event.id)
{
case Event.ACTION_EVENT:
if (event.target == colorMaskFrame)
{
if (colorMaskFrame.isHide())
colorMaskFrame.inUse(false);
repaintNodes();
}
break;
case Event.MOUSE_MOVE:
//if (mode != ZOOM && mode != STEP_BY_STEP ) {
if (mode != ZOOM ) {
check_hover.set(event.x,event.y,event_at_right);
}
break;
case Event.MOUSE_DOWN:
old_x = event.x;
old_y = event.y;
if (mode == ADD_NODE)
AddNode(event.x, event.y);
else if (mode == ADD_LINK)
AddLink(event.x,event.y);
else if (mode == SELECT || mode == SELECT_TREE)
DownSelect(event.x,event.y);
else if (mode == PROPERT)
Propert(event.x,event.y);
else if (mode == REMOVE)
Remove(event.x,event.y);
else if (mode == ROOT_SELECT)
RootSelect(event.x,event.y);
else if (mode == ZOOM) {
if(isViewBoth())
{
if(event_at_right)
setViewGeo(true);
else
setViewGeo(false);
}
if(isViewGeo() && scaler !=0)
scaler = 1/scaler;
zoom(event.x,event.y,scaler);
if (isViewBoth())
{
if(event_at_right)
repaintRightNodes();
else
repaintLeftNodes();
}
else
repaintNodes();
printMessage("");
setMode(MOVE);
}
else {
mouse_down = true;
check_hover.set();
}
break;
case Event.MOUSE_DRAG:
mouse_dragged = true;
if (mode == ADD_LINK)
AddLink_Drag(event.x,event.y);
else if (mode == SELECT
|| mode == ADD_NODE
|| mode == SELECT_TREE)
ChangeXY(event.x, event.y);
else if (mode != ZOOM || mode == MOVE)
{
if(isViewBoth())
{
if(event_at_right)
setViewGeo(true);
else
setViewGeo(false);
}
Move(event.x,event.y);
}
break;
case Event.MOUSE_UP:
if (mode == ADD_LINK)
AddLink_Up(event.x,event.y);
else if (mode == SELECT || mode == SELECT_TREE)
UpSelect(event.x,event.y);
break;
}
return super.handleEvent(event);
}
/**************************************************
* Purpose: To display the objects information
*
* nearest_object: is used to reduce needless redrawing
* of the information
***************************************************/
DList nearest_objects = new DList();
public void GetString(int x, int y)
{
if (x > size().width || y > size().height)
return;
DList objects = nearObjects(x,y);
String answer = new String();
boolean equal = true;
objects.reset();
while (!objects.end() && equal)
{
if(!nearest_objects.exists(objects.next()))
equal = false;
}
if (equal && !mouse_down)
return;
nearest_objects.reset();
while (!nearest_objects.end())
{
DisplayObject old = nearest_objects.next();
if (old.isHighlighted()) {
//remove
old.setHighlight(false);
nearest_objects.drop(old);
}
}
if (objects.empty())
printMessage(null);
else {
objects.reset();
while(!objects.end()) {
DisplayObject object = objects.next();
if (answer.length() == 0)
answer = object.getString();
else
answer = answer + " : " + object.getString();
//remove
if(mouse_down)
object.setHighlight(true);
}
//remove
if(mouse_down)
{
repaintNodes();
mouse_down = false;
}
printMessage(answer);
}
nearest_objects = objects;
}
/********************************************************
* Purpose:
*********************************************************/
int counter = 0;
public void AddNode(int x, int y)
{
DisplayObject object = near(x,y);
// Don't allow nodes to be added on top of each other
// If some does attempt to do so. Toggle the node
// to Selected = !Selected
if (object instanceof Node)
{
if (object.isSelected())
{
object.setSelect(false);
selected.drop(object);
}
else
{
object.setSelect(true);
selected.add(object);
}
repaintNodes();
return;
}
Node node = new Node("Node "+ counter++,x,y);
node.setSelect(true);
dlist.add(node);
selected.add(node);
printMessage(node.getString());
repaintNodes();
}
/********************************************************
* Purpose:
*********************************************************/
public void AddLink(int x, int y)
{
DisplayObject object = near(x,y);
if (object instanceof Node)
{
addlink_node = new Node("AddLink Node",x,y);
addlink_link = new Link((Node)object,addlink_node,Link.ONE);
dlist.add(addlink_link);
}
else
{
addlink_node = null;
addlink_link = null;
}
full_image_changed = true;
repaintNodes();
}
/********************************************************
* Purpose:
*********************************************************/
public void AddLink_Drag(int x, int y)
{
if (addlink_node != null && addlink_link != null)
addlink_node.setXY(x,y);
full_image_changed = true;
repaintNodes();
}
/********************************************************
* Purpose:
*********************************************************/
public void AddLink_Up(int x, int y)
{
DisplayObject object = near(x,y);
if (addlink_link != null && object instanceof Node
&& addlink_link.getParent() != object)
addlink_link.setChild((Node)object);
else
dlist.drop(addlink_link);
addlink_link = null;
addlink_node = null;
full_image_changed = true;
repaintNodes();
}
/********************************************************
* Purpose:
*********************************************************/
public void DownSelect(int x, int y)
{
mouse_down_selected = near(x,y);
mouse_dragged = false;
}
/********************************************************
* Purpose:
*********************************************************/
public void UpSelect(int x, int y)
{
if (mouse_dragged)
return;
int near_distance = -1;
int distance;
DisplayObject object = mouse_down_selected;
if (object instanceof Node)
{
if (mode == SELECT)
{
if (object.isSelected())
{
object.setSelect(false);
selected.drop(object);
}
else
{
object.setSelect(true);
selected.enqueue(object);
}
}
else
((Node)object).selectTree(!object.isSelected()
,selected);
// Makes sure the the current state of the object
// is correct
full_image_changed = true;
repaintNodes();
}
if (object != null)
printMessage(object.getString());
}
/********************************************************
* Purpose:
*********************************************************/
public void Propert(int x, int y) {}
/********************************************************
* Purpose:
*********************************************************/
public void Remove(int x,int y)
{
DisplayObject object = near(x,y);
if (object != null)
{
selected.drop(object);
dlist.drop(object);
DisplayObject[] objects = object.remove();
for (int index=0; index < objects.length; index++)
{
object = objects[index];
object.remove();
dlist.drop(object);
selected.drop(object);
}
full_image_changed = true;
repaintNodes();
}
}
/********************************************************
* Purpose:
*********************************************************/
public void RootSelect(int x, int y)
{
DisplayObject object = near(x,y);
if (object instanceof Node)
{
((Node)object).swapRoot();
repaintNodes();
}
}
/********************************************************
* Purpose:
*********************************************************/
public void ChangeXY(int x, int y)
{
int delta_x = x - old_x;
old_x = x;
int delta_y = y - old_y;
old_y = y;
selected.reset();
if (mouse_down_selected != null
&& !mouse_down_selected.isSelected())
{
full_image_changed = true;
left_image_changed = true;
if (mouse_down_selected instanceof Node)
((Node)mouse_down_selected)
.changeRootXY(delta_x, delta_y);
else
mouse_down_selected
.changeXY(delta_x, delta_y);
}
else
{
while (!selected.end())
{
DisplayObject object = selected.next();
if (!object.isSelected())
selected.drop(object);
else if (object instanceof Node)
{
full_image_changed = true;
left_image_changed = true;
((Node)object)
.changeRootXY(delta_x, delta_y);
}
}
}
if (!isViewBoth() && full_image_changed)
repaintNodes();
if (isViewBoth() && left_image_changed)
repaintLeftNodes();
}
/********************************************************
* Purpose:
*********************************************************/
public void Move(int x, int y)
{
int delta_x = x - old_x;
int delta_y = y - old_y;
if(isViewGeo())
{
double[] old_latlon = FromMap(old_x,old_y);
double[] latlon = FromMap(x,y);
double delta_lon = latlon[1] - old_latlon[1];
double delta_lat = latlon[0] - old_latlon[0];
zoom (top_lon-delta_lon,top_lat-delta_lat,bot_lon-delta_lon,bot_lat-delta_lat);
if(isViewBoth())
repaintRightNodes();
else
repaintNodes();
}
else
{
x_shift += delta_x;
y_shift += delta_y;
//paintNodes(getGraphics(),size());
//if(isViewBoth())
// repaintLeftNodes();
//else
// repaintNodes();
repaint();
}
printMessage("");
old_x = x - delta_x;
old_y = y - delta_y;
}
/********************************************************
* Purpose:
*********************************************************/
protected DisplayObject near(int x, int y)
{
double near_distance = -1;
double distance;
DisplayObject near_object = null;
dlist.reset();
while(!dlist.end())
{
DisplayObject object = dlist.next();
distance = object.near(x,y);
if (near_distance < 0 && distance > 0)
{
near_distance = distance;
near_object = object;
}
else if (distance > 0 && (
(near_object instanceof Link && object instanceof Node)
|| distance < near_distance))
{
near_distance = distance;
near_object = object;
}
}
return near_object;
}
protected DList nearObjects(int x, int y)
{
double near_distance = -1;
double distance;
DList near_objects = new DList();
DisplayObject near_object = null;
dlist.reset();
while(!dlist.end())
{
DisplayObject object = dlist.next();
distance = object.near(x,y);
if (near_distance < 0 && distance > 0)
{
near_distance = distance;
near_objects.enqueue(object);
near_object = object;
}
else if (distance > 0 && (
(near_object instanceof Link && object instanceof Node)
|| distance <= near_distance))
{
near_distance = distance;
near_objects.enqueue(object);
near_object = object;
}
}
near_objects.reset();
while(!near_objects.end())
{
DisplayObject object = near_objects.next();
distance = object.near(x,y);
if (distance > near_distance || (near_object instanceof
Node && object instanceof Link))
near_objects.drop(object);
}
return near_objects;
}
/********************************************************
* Purpose:To allow for the Display to sleep
*********************************************************/
public void setAnimator(DisplayInterface animator_input)
{
animator = animator_input;
}
/********************************************************
* Purpose:To allow for the Display to sleep
*********************************************************/
public void setThread(Thread thread)
{
myThread = thread;
}
/********************************************************
* Purpose:Sets the amout of time that it would sleep.
*********************************************************/
public void setSleep(long sleep)
{
sleep_length = sleep;
}
/********************************************************
* Purpose:Sets the number of times it should loop
*********************************************************/
public void setTimes(int time)
{
slid_times = time;
}
/********************************************************
* Purpose: To get boundary lat/longs -jjung
*********************************************************/
public double[] getLatLon()
{
double[] lat_lon = new double[4];
lat_lon[0] = top_lat;
lat_lon[1] = top_lon;
lat_lon[2] = bot_lat;
lat_lon[3] = bot_lon;
return lat_lon;
}
public void setLatLon(double t_lat, double t_lon, double b_lat,
double b_lon)
{
source_top_lat = top_lat = t_lat;
source_top_lon = top_lon = t_lon;
source_bot_lat = bot_lat = b_lat;
source_bot_lon = bot_lon = b_lon;
}
/********************************************************
* Purpose:To create a group of images that will be presented
* in a side show.
*********************************************************/
public void run()
{
int current_mode = mode;
setMode(ANIMATE);
slids = new Image[num_files];
current_fileIndex = 0;
int times = 0;
while(times < slid_times)
{
animator.setFileIndex(current_fileIndex);
if (slids[current_fileIndex] == null)
{
full_offscreen = null;
setFileIndex(current_fileIndex);
slids[current_fileIndex] = full_offscreen;
}
else
{
full_offscreen = slids[current_fileIndex];
repaint();
}
try {
myThread.sleep(sleep_length);
} catch (InterruptedException exc) {
System.err.println ("Display.run():"
+ exc.toString());
}
current_fileIndex = (current_fileIndex+1)
%num_files;
if (current_fileIndex == 0)
times++;
}
setMode(current_mode);
}
}
class Check_Hover extends Thread
{
protected final int WAIT = 10;
protected boolean set = false;
protected int x,y;
protected Display display;
protected boolean hover_set_at_right = false;
public Check_Hover(Display display_input)
{
display = display_input;
}
public void run()
{
try
{
while(true)
{
if (set)
{
if(display.isViewBoth())
{
if(hover_set_at_right)
display.setViewGeo(true);
else
display.setViewGeo(false);
display.RootORGeo();
}
display.GetString(x,y);
}
set = false;
sleep(WAIT);
}
} catch (InterruptedException e) {
System.err.println("Hover_check.run():" + e.toString());
}
}
synchronized public void set()
{
set = true;
}
synchronized public void set(int x_input,int y_input,boolean event_at_right)
{
x = x_input;
y = y_input;
set = true;
if (event_at_right)
hover_set_at_right = true;
else
hover_set_at_right = false;
}
}
"They are called 'sampans,'" Doctor Bronson explained, "and are made entirety of wood. Of late years the Japanese sometimes use copper or iron nails for fastenings; but formerly you found them without a particle of metal about them." "And I am afraid I betrayed the fact," Bruce admitted. "I might have thought of some other way of accounting for my presence here. Still, that rather piratical-looking young man seemed to think you had done right. What's this about some man picked up in the garden?" CHAPTER LII. THE CAGE IS OPENED. Third. Combination machines can only be employed with success when one attendant performs all the operations, and when the change from one to another requires but little adjustment and re-arrangement. When their train approached ours they looked out of the windows, or opened the doors, and waved and greeted and shouted at the top of their voices. me in the cab, he told me that for three days they gave you up. of mind is gone for ever--but anyway, I never cared much for just Two legs waved over the last cockpit place. She waited, too, made silent by sudden realization of how futile anything that she might say would be. "I am glad to see you again," she faltered; "it is four years since Black River and the cloud-burst." She was angry at her own stupidity and want of resource, and her tone was more casual than she meant it to be. The result of this division shook the last resistance of Walpole. When the motion which had been rejected on the 18th of December—for copies of the correspondence with the King of Prussia—was again put, he made no opposition, and it[79] passed without a division. He made, however, one more attempt to carry his measures. In the disputed election of Chippenham he stood his ground against the petition, and was defeated by a majority of one. It was now clear to himself that he must give way. His relatives and friends assured him that to defer longer was only to court more decided discomfiture. On the 31st of January, he, therefore, prepared to depart for his seat at Houghton, and the next morning he demanded of the king, in a private audience, leave to retire. George, on this occasion, evinced a degree of feeling that did him honour. When the old Minister who had served him through so long a course of years knelt to kiss hands, the king embraced him, shed tears, and begged that he would often come to see him. On the 9th of February Sir Robert was created Earl of Orford, and on the 11th he made a formal resignation of all his places. "I'll chance it," said Alf desperately, reaching for the cup of coffee. "I'm sure it'll be better for me to eat something." "They d?an't care, nuther—it's only me." "Wipe the blood off his face." There was silence, in which a coal fell. She still stood with her arms outstretched; he knew that she was calling him—as no woman had ever called him—with all that of herself which was in his heart, part of his own being. HoME免费一1一级做爰片在线观看
ENTER NUMBET 0018esunda.com.cn
www.mtconnect.org.cn
www.sexk2lir.com.cn
www.jjw1107.com.cn
www.xqvi.com.cn
dgyexin.com.cn
hiisoo.com.cn
daiy12.com.cn
ldl.org.cn
qhdf.com.cn