1 // $Id: CellListCanvas.java,v 1.1 2000/05/18 22:00:53 tucker Exp $
2 // Hive. Copyright (c) 1998-1999, The Massachusetts Institute of Technology.
3 // All rights reserved. Distributed with no warranty, without even the
4 // implied warranty of merchantability or fitness for a particular purpose.
5 // For more details see COPYING.GPL, the GNU General Public License.
6
7 /**
8 ** Panel showing the cells being monitored and this information about them:
9 ** - uptime
10 ** - colored border legend
11 ** - name
12 ** - displaying icons or not (can be set)
13 **
14 **
15 ** NOTE: This currently does not display the uptimes of remote cells. This is due
16 ** to the fact that the CellListAgentImpl relies on a centralized "master" cell to
17 ** give it updates every so often (this is currently pinot-noir, which is out of date.
18 **
19 ** This also desperately needs to be made a little more efficient.
20 ** right now it gets a vector of celllistinfo objects every time some
21 ** happens -- it needs to be able to deal with more incremental
22 ** information to deal with the bandwidth better
23 **/
24 package net.hivecell.hive.agent.hiveui.iconicui;
25
26 import net.hivecell.hive;
27 import net.hivecell.hive.agent.hiveui.BaseGUIAgentImpl;
28 import net.hivecell.hive.agent.hiveui.BaseUIAgentImpl;
29 import net.hivecell.hive.cell.RemoteCell;
30 import net.hivecell.hive.cell.Cell;
31 import net.hivecell.hive.agent.cell.CellListAgentImpl;
32 import net.hivecell.hive.agent.cell.CellListInfo;
33 import net.hivecell.hive.support.Debug;
34 import net.hivecell.hive.support.CellAddress;
35 import net.hivecell.hive.support.CellConnectException;
36 import net.hivecell.hive.support.MalformedHiveURLException;
37
38 import net.hivecell.hive.support.BaseCanvas;
39
40 import java.awt;
41 import java.awt.event;
42 import java.util;
43
44
45 public class CellListCanvas
46 extends BaseCanvas
47 implements MouseListener, MouseMotionListener {
48
49 protected BaseGUIAgentImpl uiAgent;
50 protected Vector monitoredCells; // The names of all the cells we're monitoring in the order we began to monitor them.
51 protected Vector orderedCells; // All of the cells we know about, with the monitoredCells first, then the unmonitored ones.
52 protected Hashtable cellColors; // Cell name -> border color
53 protected Hashtable cellInfo; // Cell name -> CellListInfo
54 protected Hashtable cellRects; // Cell name -> rectangle in which their data is displayed.
55 protected Hashtable shortNames; // Cell name string -> short name
56
57 protected Dimension rectSize = new Dimension(100, 45); // Size of the bounding rectangle for the cell info
58 protected CellAddress selectedCell; // The cell that the mouse clicked on
59 protected Color unmonitoredCellColor; // The color of a cell that isn't being monitored, but that we know about.
60
61
62 public CellListCanvas( BaseGUIAgentImpl uiAgent ) {
63 super();
64 setSize(100, 300);
65
66 monitoredCells = new Vector();
67 orderedCells = new Vector();
68 cellColors = new Hashtable();
69 cellInfo = new Hashtable();
70 cellRects = new Hashtable();
71 shortNames = new Hashtable();
72
73 unmonitoredCellColor = Color.gray;
74
75 this.uiAgent = uiAgent;
76
77 (new Thread( new Runnable() {
78 public void run() {
79 while( true ) {
80 try {
81 Thread.sleep( 1000 );
82 } catch( InterruptedException error ) { }
83 render();
84 }
85 }
86 })).start();
87
88 addMouseListener(this);
89
90 setVisible(true);
91 }
92
93
94 /**
95 * Create a color that the UI will use to distinguish this
96 * cell from the others.
97 *
98 * @param remoteCellAddress the cell we need the color for
99 * @return the color for this cell
100 */
101 public Color addMonitoredCell( CellAddress cell ) {
102 Color col = null;
103
104 // if a new cell, create a new random color, pastelize it and use it
105 col = (Color)cellColors.get(cell);
106 if (col == null) {
107 col = createNewColor();
108 col = makePastel( col );
109 cellColors.put( cell, col );
110 }
111
112 if (!monitoredCells.contains(cell))
113 monitoredCells.addElement(cell);
114 if (cellRects.get(cell) == null)
115 cellRects.put( cell, new Rectangle(rectSize) );
116
117 rearrangeOrdered();
118 render(super.getGraphics());
119
120 return (col);
121 }
122
123
124 public void addUnmonitoredCell( CellAddress cell ) {
125 cellRects.put( cell, new Rectangle(rectSize) );
126 }
127
128 /**
129 * Remove a cell and its appropriate color from the database.
130 *
131 * @param cell the cell to remove for our database
132 */
133 public void stopMonitoringCell( CellAddress cell ) {
134 cellColors.remove( cell );
135 monitoredCells.removeElement( cell );
136 cellRects.remove( cell );
137 rearrangeOrdered();
138 }
139
140
141 /** Get the color of cell's border. */
142 public Color getColor( CellAddress cell ) { return ((Color)cellColors.get(cell)); }
143
144 public BaseGUIAgentImpl getUI() { return (uiAgent); }
145
146
147 /**
148 * A "magic" function -- i really don't know how to make colors
149 * pastel, but nelson said this might do it :)
150 *
151 * @param c the color we wish to "pastelize"
152 * @return the pastel version of the color we set it
153 */
154 private Color makePastel( Color c ) {
155
156 // uhm - maybe this makes the colors pastel? nelson said it
157 // would :)
158 float[] hsb = Color.RGBtoHSB( c.getRed(), c.getGreen(), c.getBlue(), null );
159 hsb[1] = (float)0.4;
160 hsb[2] = (float)0.95;
161 return Color.getHSBColor( hsb[0], hsb[1], hsb[2] );
162
163 }
164
165 /**
166 * Do nelson's idea of only having like seven colors, and then we
167 * cycle through it -- hopefully we are not looking at more than 7
168 * cells
169 */
170 private Color createNewColor() {
171
172 Color colors[] = { Color.red, Color.blue, Color.green, Color.white, Color.magenta, Color.black };
173
174 int nextColor = ( cellColors.size() % colors.length ) + 1;
175 return colors[ nextColor ];
176
177 }
178
179
180 private void rearrangeOrdered() {
181
182 orderedCells = new Vector(); // Start from scratch each time
183
184 // Go through the cells and arrange them in order:
185 // First are the ones we are monitoring, in the order we began monitoring them
186 Enumeration e = monitoredCells.elements();
187 while (e.hasMoreElements()) { orderedCells.addElement(e.nextElement()); }
188
189 // Next are the ones we know about, but aren't monitoring.
190 e = cellInfo.keys();
191 while (e.hasMoreElements()) {
192 CellAddress k = (CellAddress)e.nextElement();
193 if (!monitoredCells.contains(k))
194 orderedCells.addElement(k);
195 }
196
197 }
198
199 /** Called by the CellListAgentImpl in its update loop, */
200 public void newCellInfo(Vector v) { // V is a vector of CellListInfo types.
201
202 Enumeration e = v.elements();
203 while (e.hasMoreElements()) {
204 CellListInfo cli = (CellListInfo)e.nextElement();
205 if ( !cellInfo.containsKey(cli.getAddress()) ) {
206 cellInfo.put(cli.getAddress(), cli);
207 addUnmonitoredCell(cli.getAddress());
208 rearrangeOrdered();
209 }
210 }
211 render( getGraphics() );
212 }
213
214
215
216 // this method is a big hack to get the spacing right. Needs to be cleaned up later.
217 public void render(Graphics g) {
218 // printCOLS();
219 if (g == null) return;
220 Point pos = new Point(5, 15);
221
222 Color oldCol = g.getColor();
223 Color bg = getBackground();
224 g.setColor(bg);
225 g.fillRect(0, 0, this.getSize().width, this.getSize().height);
226
227
228 // Now, go through and render them all.
229 Enumeration e = orderedCells.elements();
230 while (e.hasMoreElements()) {
231 CellAddress cell = (CellAddress)e.nextElement();
232
233 ((Rectangle)cellRects.get(cell)).setLocation(pos.x - 5, pos.y - 15);
234
235
236 g.setColor( pickTextCol(bg) );
237
238 // Draw the name of the cell first
239 String name = stripName(cell.toString());
240 g.drawString(name, pos.x, pos.y);
241
242 pos.y += 5; // jump down 5
243 // If the agent is being monitored, draw a colored, raised box.
244 if (monitoredCells.contains(cell)) {
245 g.setColor((Color)cellColors.get(cell));
246 g.fill3DRect(pos.x, pos.y, 15, 15, true);
247 }
248 else {
249 g.setColor(unmonitoredCellColor);
250 g.fill3DRect(pos.x, pos.y, 15, 15, false);
251 }
252 // If not, draw a gray sunken one.
253
254 pos.x += 25; // Move 10 beyond edge of the rect
255 pos.y += 12; // Move down 12 pixels from the top edge of the rectangle
256 g.setColor( pickTextCol(bg) );
257 if (cellInfo.containsKey(cell)) {
258 CellListInfo tcli = (CellListInfo)cellInfo.get(cell);
259 String outString = (tcli.isUp() ? "up" : "down");
260 g.drawString( outString, pos.x, pos.y );
261 }
262
263 pos.y += 30;
264 pos.x = 5;
265 }
266
267 g.setColor(oldCol);
268 }
269
270
271 /**
272 ** This selects a text color that contrasts with bg, so that
273 ** text can be read on any color background.
274 **
275 ** @param bg The color to contrast against.
276 **/
277 private Color pickTextCol(Color bg) {
278 return ( new Color(255 - bg.getRed(), 255 - bg.getGreen(), 255 - bg.getBlue()) );
279 }
280
281
282 private String stripName(String raw) {
283
284 if (shortNames.containsKey(raw))
285 return ((String)shortNames.get(raw));
286
287 String ret;
288
289 // Strip of the "hive://"
290 ret = raw.substring(raw.lastIndexOf("/") + 1);
291
292 // Strip off the port number for now.
293 int pStart = ret.lastIndexOf(":");
294 String port = "";
295 if (pStart != -1) {
296 port = ret.substring( pStart ); // Capture the ':'
297 ret = ret.substring( 0, pStart );
298 }
299
300
301 // Get the domain from ret and this domain
302 String domain = ret.substring(ret.indexOf(".") + 1);
303 String myDomain = uiAgent.getCellAddress().toString();
304 // Strip the "hive://"
305 myDomain = myDomain.substring(myDomain.lastIndexOf("/") + 1);
306 // Strip the port
307 int endp = myDomain.lastIndexOf(":");
308 if (endp != -1)
309 myDomain = myDomain.substring(myDomain.indexOf(".") + 1, endp);
310 else myDomain = myDomain.substring(myDomain.indexOf(".") + 1);
311
312
313 // if they are in the same domain, don't show it.
314 if (myDomain.equals(domain)) {
315 int firstDot = ret.indexOf("."); // is this a FQDN?
316 if (firstDot > 0) // yes, strip out domainname
317 ret = ret.substring( 0, ret.indexOf(".") ) + port;
318 else // no, just use hostname
319 ret = ret + port;
320 } else
321 ret += port;
322
323 shortNames.put(raw, ret);
324 return (ret);
325 }
326
327
328 /** Mouse handling code */
329
330 // Mouse pressed - start a drag here. (This is where we should put in
331 // the click-an-agent-to-edit stuff)
332 public void mousePressed(MouseEvent event) {
333
334 // Figure out which mouse button it was from the meta/alt flags.
335 int mouseButton = -1;
336 selectedCell = null;
337
338 if (event.isAltDown()) {
339 mouseButton = 1;
340 } else if (event.isMetaDown()) {
341 mouseButton = 2;
342 } else {
343 mouseButton = 0;
344 }
345
346
347 // Figure out which icon was pressed.
348 Enumeration e = orderedCells.elements();
349 while (e.hasMoreElements()) {
350 CellAddress tCell = (CellAddress)e.nextElement();
351 if ( ((Rectangle)cellRects.get(tCell)).contains(event.getX(), event.getY()) ) {
352 selectedCell = tCell;
353 break;
354 }
355 }
356
357 if ( selectedCell == null ) { // Whoops, mouse missed.
358 Debug.notice("There's nothing at (" + event.getX() + ", " + event.getY() + ")");
359 return;
360
361 } else if ( selectedCell != null ) {
362
363 if (mouseButton == 0) {
364 } else if (mouseButton == 2) { // Handle Popup menu stuff.
365
366 String cellName = selectedCell.toString();
367 PopupMenu pm = new PopupMenu( cellName );
368
369 if( Global.windowsOS == true ) { // hack stupid Windows JDK bug in popups
370 pm.add(cellName);
371 pm.add("-");
372 }
373
374
375 for (int i = 0; i < uiAgent.defaultCellCmds.length; i++)
376 pm.add(uiAgent.defaultCellCmds[i]);
377
378 pm.addActionListener( new ActionListener() {
379 public void actionPerformed(ActionEvent ae) {
380 String command = ae.getActionCommand();/*
381
382 if (monitoredCells.contains(selectedCell)) {
383 addUnmonitoredCell(selectedCell); // Not being monitored, but still not gone.
384 rearrangeOrdered();
385 }
386 //else addMonitoredCell(selectedCell);
387 //rearrangeOrdered();
388
389 } else if (command.equals(BaseUIAgentImpl.changeShowCellAgentsCmd)) {
390
391 } else if (command.equals(BaseUIAgentImpl.killCellCmd)) {
392
393 }
394 */
395 uiAgent.invokeCellMenuCommand(selectedCell, command);
396 if (command.equals(BaseUIAgentImpl.changeMonitoringCellCmd))
397 rearrangeOrdered();
398
399 }
400 });
401
402 add(pm);
403 pm.show(this, event.getX(), event.getY());
404
405
406 } else if (mouseButton == 1) { // middle button
407 } else {
408 Debug.error("Unknown mouse button. What the hell is going on?"); // shouldn't reach here.
409 }
410 }
411
412 }
413
414
415 /** We don't care about these events */
416 public void mouseReleased(MouseEvent event) {}
417 public void mouseDragged(MouseEvent event) {}
418 public void mouseClicked(MouseEvent event) {}
419 public void mouseEntered(MouseEvent event) {}
420 public void mouseExited(MouseEvent event) {}
421 public void mouseMoved(MouseEvent event) {}
422
423 }