|
Line 1
Link Here
|
|
|
1 |
/***************************************************************************** |
| 2 |
* Copyright (c) 1997-2006, Intel Corporation. |
| 3 |
* All rights reserved. This program and the accompanying materials |
| 4 |
* are made available under the terms of the Eclipse Public License v1.0 |
| 5 |
* which accompanies this distribution, and is available at |
| 6 |
* http://www.eclipse.org/legal/epl-v10.html |
| 7 |
* |
| 8 |
* Contributors: |
| 9 |
* Intel Corporation - Initial API and implementation |
| 10 |
* Ruslan A. Scherbakov, Intel - Initial API and implementation |
| 11 |
* |
| 12 |
* $Id$ |
| 13 |
*****************************************************************************/ |
| 14 |
|
| 15 |
package org.eclipse.tptp.trace.jvmti.internal.client.widgets; |
| 16 |
|
| 17 |
import java.util.ArrayList; |
| 18 |
import java.util.Hashtable; |
| 19 |
import java.util.Iterator; |
| 20 |
import java.util.List; |
| 21 |
import java.util.Set; |
| 22 |
|
| 23 |
import org.eclipse.emf.common.util.EList; |
| 24 |
import org.eclipse.hyades.models.trace.TRCThread; |
| 25 |
import org.eclipse.hyades.models.trace.TRCThreadEvent; |
| 26 |
import org.eclipse.jface.viewers.ISelection; |
| 27 |
import org.eclipse.jface.viewers.IStructuredSelection; |
| 28 |
import org.eclipse.swt.SWT; |
| 29 |
import org.eclipse.swt.events.ControlEvent; |
| 30 |
import org.eclipse.swt.events.ControlListener; |
| 31 |
import org.eclipse.swt.events.FocusEvent; |
| 32 |
import org.eclipse.swt.events.FocusListener; |
| 33 |
import org.eclipse.swt.events.KeyEvent; |
| 34 |
import org.eclipse.swt.events.KeyListener; |
| 35 |
import org.eclipse.swt.events.MouseEvent; |
| 36 |
import org.eclipse.swt.events.MouseListener; |
| 37 |
import org.eclipse.swt.events.MouseMoveListener; |
| 38 |
import org.eclipse.swt.events.SelectionEvent; |
| 39 |
import org.eclipse.swt.events.SelectionListener; |
| 40 |
import org.eclipse.swt.graphics.GC; |
| 41 |
import org.eclipse.swt.graphics.Point; |
| 42 |
import org.eclipse.swt.graphics.Rectangle; |
| 43 |
import org.eclipse.swt.widgets.Composite; |
| 44 |
|
| 45 |
public class ThreadStatesCtrl extends TraceCtrl implements FocusListener, |
| 46 |
KeyListener, MouseMoveListener, MouseListener, ControlListener, |
| 47 |
SelectionListener { |
| 48 |
|
| 49 |
private ITimeDataProvider _timeProvider; |
| 50 |
boolean _isInFocus = false; |
| 51 |
private int _topItem = 0; |
| 52 |
private int _itemHeight = 18; |
| 53 |
private int _dragState = 0; |
| 54 |
private int _hitIdx = 0; |
| 55 |
private int _dragX0 = 0; |
| 56 |
private int _dragX = 0; |
| 57 |
private double _timeStep = 0.01; |
| 58 |
private double _time0bak; |
| 59 |
private double _time1bak; |
| 60 |
private ItemData _data = new ItemData(); |
| 61 |
private ArrayList _selectionListeners; |
| 62 |
|
| 63 |
public ThreadStatesCtrl(Composite parent, TraceColorScheme colors) { |
| 64 |
super(parent, colors, SWT.NO_BACKGROUND | SWT.H_SCROLL | SWT.V_SCROLL); |
| 65 |
addFocusListener(this); |
| 66 |
addMouseListener(this); |
| 67 |
addMouseMoveListener(this); |
| 68 |
addKeyListener(this); |
| 69 |
addControlListener(this); |
| 70 |
getVerticalBar().addSelectionListener(this); |
| 71 |
getHorizontalBar().addSelectionListener(this); |
| 72 |
} |
| 73 |
|
| 74 |
public void setTimeProvider(ITimeDataProvider timeProvider) { |
| 75 |
_timeProvider = timeProvider; |
| 76 |
adjustScrolls(); |
| 77 |
redraw(); |
| 78 |
} |
| 79 |
|
| 80 |
public void addSelectionListener(SelectionListener listener) { |
| 81 |
if (listener == null) |
| 82 |
SWT.error(SWT.ERROR_NULL_ARGUMENT); |
| 83 |
if (null == _selectionListeners) |
| 84 |
_selectionListeners = new ArrayList(); |
| 85 |
_selectionListeners.add(listener); |
| 86 |
} |
| 87 |
|
| 88 |
public void removeSelectionListener(SelectionListener listener) { |
| 89 |
if (null != _selectionListeners) |
| 90 |
_selectionListeners.remove(listener); |
| 91 |
} |
| 92 |
|
| 93 |
public void fireSelectionChanged() { |
| 94 |
if (null != _selectionListeners) { |
| 95 |
Iterator it = _selectionListeners.iterator(); |
| 96 |
while (it.hasNext()) { |
| 97 |
SelectionListener listener = (SelectionListener) it.next(); |
| 98 |
listener.widgetSelected(null); |
| 99 |
} |
| 100 |
} |
| 101 |
} |
| 102 |
|
| 103 |
public void fireDefaultSelection() { |
| 104 |
if (null != _selectionListeners) { |
| 105 |
Iterator it = _selectionListeners.iterator(); |
| 106 |
while (it.hasNext()) { |
| 107 |
SelectionListener listener = (SelectionListener) it.next(); |
| 108 |
listener.widgetDefaultSelected(null); |
| 109 |
} |
| 110 |
} |
| 111 |
} |
| 112 |
|
| 113 |
public void refreshData(Object threads[]) { |
| 114 |
_data.refreshData(threads); |
| 115 |
adjustScrolls(); |
| 116 |
redraw(); |
| 117 |
} |
| 118 |
|
| 119 |
public void adjustScrolls() { |
| 120 |
if (null == _timeProvider) { |
| 121 |
getVerticalBar().setValues(0, 1, 1, 1, 1, 1); |
| 122 |
getHorizontalBar().setValues(0, 1, 1, 1, 1, 1); |
| 123 |
return; |
| 124 |
} |
| 125 |
int page = countPerPage(); |
| 126 |
if (_topItem + page > _data._items.length) |
| 127 |
_topItem = _data._items.length - page; |
| 128 |
if (_topItem < 0) |
| 129 |
_topItem = 0; |
| 130 |
getVerticalBar().setValues(_topItem, 0, _data._items.length, page, 1, |
| 131 |
page); |
| 132 |
double time0 = _timeProvider.getTime0(); |
| 133 |
double time1 = _timeProvider.getTime1(); |
| 134 |
double timeMin = _timeProvider.getMinTime(); |
| 135 |
double timeMax = _timeProvider.getMaxTime(); |
| 136 |
int timePage = (int) ((time1 - time0) / _timeStep); |
| 137 |
int timePos = (int) (time0 / _timeStep); |
| 138 |
getHorizontalBar().setValues(timePos, (int) (timeMin / _timeStep), |
| 139 |
(int) (timeMax / _timeStep), timePage, 1, timePage); |
| 140 |
} |
| 141 |
|
| 142 |
boolean ensureVisibleItem(int idx, boolean redraw) { |
| 143 |
boolean changed = false; |
| 144 |
if (idx < 0 || idx >= _data._items.length) |
| 145 |
return changed; |
| 146 |
if (idx < _topItem) { |
| 147 |
_topItem = idx; |
| 148 |
getVerticalBar().setSelection(_topItem); |
| 149 |
if (redraw) |
| 150 |
redraw(); |
| 151 |
changed = true; |
| 152 |
} else { |
| 153 |
int page = countPerPage(); |
| 154 |
if (idx >= _topItem + page) { |
| 155 |
_topItem = idx - page + 1; |
| 156 |
getVerticalBar().setSelection(_topItem); |
| 157 |
if (redraw) |
| 158 |
redraw(); |
| 159 |
changed = true; |
| 160 |
} |
| 161 |
} |
| 162 |
return changed; |
| 163 |
} |
| 164 |
|
| 165 |
static TRCThreadEvent getFirstEvent(TRCThread thread) { |
| 166 |
EList list = thread.getThreadEvents(); |
| 167 |
TRCThreadEvent event = null; |
| 168 |
if (!list.isEmpty()) |
| 169 |
event = (TRCThreadEvent) list.get(0); |
| 170 |
return event; |
| 171 |
} |
| 172 |
|
| 173 |
static TRCThreadEvent findEvent(TRCThread thread, double time, int n) { |
| 174 |
EList list = thread.getThreadEvents(); |
| 175 |
Iterator it = list.iterator(); |
| 176 |
TRCThreadEvent event = null; |
| 177 |
TRCThreadEvent prevEvent = null; |
| 178 |
TRCThreadEvent nextEvent = null; |
| 179 |
if (it.hasNext()) { |
| 180 |
event = (TRCThreadEvent) it.next(); |
| 181 |
double currTime = event.getTime(); |
| 182 |
if (time < currTime) { |
| 183 |
if (1 != n) |
| 184 |
event = null; |
| 185 |
return event; |
| 186 |
} |
| 187 |
while (it.hasNext()) { |
| 188 |
nextEvent = (TRCThreadEvent) it.next(); |
| 189 |
double nextTime = nextEvent.getTime(); |
| 190 |
if (currTime <= time && time < nextTime) { |
| 191 |
if (1 == n) |
| 192 |
event = nextEvent; |
| 193 |
else if (-1 == n) |
| 194 |
event = prevEvent; |
| 195 |
return event; |
| 196 |
} |
| 197 |
prevEvent = event; |
| 198 |
event = nextEvent; |
| 199 |
} |
| 200 |
} |
| 201 |
if (1 == n) |
| 202 |
event = null; |
| 203 |
else if (-1 == n) |
| 204 |
event = prevEvent; |
| 205 |
return event; |
| 206 |
} |
| 207 |
|
| 208 |
static class Selection implements IStructuredSelection { |
| 209 |
|
| 210 |
List list = new ArrayList(); |
| 211 |
|
| 212 |
public Object getFirstElement() { |
| 213 |
if (!list.isEmpty()) |
| 214 |
return list.get(0); |
| 215 |
return null; |
| 216 |
} |
| 217 |
|
| 218 |
public Iterator iterator() { |
| 219 |
return list.iterator(); |
| 220 |
} |
| 221 |
|
| 222 |
public int size() { |
| 223 |
return list.size(); |
| 224 |
} |
| 225 |
|
| 226 |
public Object[] toArray() { |
| 227 |
return list.toArray(); |
| 228 |
} |
| 229 |
|
| 230 |
public List toList() { |
| 231 |
return list; |
| 232 |
} |
| 233 |
|
| 234 |
public boolean isEmpty() { |
| 235 |
return list.isEmpty(); |
| 236 |
} |
| 237 |
} |
| 238 |
|
| 239 |
public ISelection getSelection() { |
| 240 |
Selection sel = new Selection(); |
| 241 |
TRCThread thread = getSelectedThread(); |
| 242 |
if (null != thread && null != _timeProvider) { |
| 243 |
double selectedTime = _timeProvider.getSelectedTime(); |
| 244 |
TRCThreadEvent event = findEvent(thread, selectedTime, 0); |
| 245 |
if (null != event) |
| 246 |
sel.list.add(event); |
| 247 |
} |
| 248 |
return sel; |
| 249 |
} |
| 250 |
|
| 251 |
public void selectEvent(int n) { |
| 252 |
if (null == _timeProvider) |
| 253 |
return; |
| 254 |
TRCThread thread = getSelectedThread(); |
| 255 |
if (thread == _timeProvider) |
| 256 |
return; |
| 257 |
double selectedTime = _timeProvider.getSelectedTime(); |
| 258 |
double endTime = _timeProvider.getEndTime(); |
| 259 |
TRCThreadEvent nextEvent; |
| 260 |
if (-1 == n && selectedTime >= endTime) |
| 261 |
nextEvent = findEvent(thread, selectedTime, 0); |
| 262 |
else |
| 263 |
nextEvent = findEvent(thread, selectedTime, n); |
| 264 |
if (null != nextEvent) { |
| 265 |
_timeProvider.setSelectedTime(nextEvent.getTime(), true); |
| 266 |
fireSelectionChanged(); |
| 267 |
} |
| 268 |
else if (1 == n) { |
| 269 |
_timeProvider.setSelectedTime(endTime, true); |
| 270 |
fireSelectionChanged(); |
| 271 |
} |
| 272 |
} |
| 273 |
|
| 274 |
public void selectNextEvent() { |
| 275 |
selectEvent(1); |
| 276 |
} |
| 277 |
|
| 278 |
public void selectPrevEvent() { |
| 279 |
selectEvent(-1); |
| 280 |
} |
| 281 |
|
| 282 |
public TRCThread getSelectedThread() { |
| 283 |
TRCThread thread = null; |
| 284 |
int idx = getSelectedIndex(); |
| 285 |
if (idx >= 0 && _data._items[idx] instanceof ThreadItem) |
| 286 |
thread = ((ThreadItem) _data._items[idx])._thread; |
| 287 |
return thread; |
| 288 |
} |
| 289 |
|
| 290 |
public int getSelectedIndex() { |
| 291 |
int idx = -1; |
| 292 |
for (int i = 0; i < _data._items.length; i++) { |
| 293 |
Item item = (Item) _data._items[i]; |
| 294 |
if (item._selected) { |
| 295 |
idx = i; |
| 296 |
break; |
| 297 |
} |
| 298 |
} |
| 299 |
return idx; |
| 300 |
} |
| 301 |
|
| 302 |
boolean toggle(int idx) { |
| 303 |
boolean toggled = false; |
| 304 |
if (idx >= 0 && idx < _data._items.length) { |
| 305 |
Item item = (Item) _data._items[idx]; |
| 306 |
if (item._hasChildren) { |
| 307 |
item._expanded = !item._expanded; |
| 308 |
_data.updateItems(); |
| 309 |
adjustScrolls(); |
| 310 |
redraw(); |
| 311 |
toggled = true; |
| 312 |
} |
| 313 |
} |
| 314 |
return toggled; |
| 315 |
} |
| 316 |
|
| 317 |
int hitTest(int x, int y) { |
| 318 |
if (x < 0) |
| 319 |
return -1; |
| 320 |
if (y < 0) |
| 321 |
return -1; |
| 322 |
int hit = -1; |
| 323 |
int idx = y / _itemHeight; |
| 324 |
idx += _topItem; |
| 325 |
if (idx < _data._items.length) |
| 326 |
hit = idx; |
| 327 |
return hit; |
| 328 |
} |
| 329 |
|
| 330 |
double hitTimeTest(int x, int y) { |
| 331 |
if (null == _timeProvider) |
| 332 |
return -1; |
| 333 |
double hitTime = -1; |
| 334 |
Point size = getCtrlSize(); |
| 335 |
double time0 = _timeProvider.getTime0(); |
| 336 |
double time1 = _timeProvider.getTime1(); |
| 337 |
int left = _timeProvider.getNameSpace(); |
| 338 |
x -= left; |
| 339 |
if (x >= 0 && size.x >= left) { |
| 340 |
hitTime = time0 + (time1 - time0) * x / (size.x - left); |
| 341 |
} |
| 342 |
return hitTime; |
| 343 |
} |
| 344 |
|
| 345 |
void selectItem(int idx, boolean addSelection) { |
| 346 |
if (addSelection) { |
| 347 |
if (idx >= 0 && idx < _data._items.length) { |
| 348 |
Item item = (Item) _data._items[idx]; |
| 349 |
item._selected = true; |
| 350 |
} |
| 351 |
} else { |
| 352 |
for (int i = 0; i < _data._items.length; i++) { |
| 353 |
Item item = (Item) _data._items[i]; |
| 354 |
item._selected = i == idx; |
| 355 |
} |
| 356 |
} |
| 357 |
boolean changed = ensureVisibleItem(idx, true); |
| 358 |
if (!changed) |
| 359 |
redraw(); |
| 360 |
} |
| 361 |
|
| 362 |
public int countPerPage() { |
| 363 |
int height = getCtrlSize().y; |
| 364 |
int count = 0; |
| 365 |
if (height > 0) |
| 366 |
count = height / _itemHeight; |
| 367 |
return count; |
| 368 |
} |
| 369 |
|
| 370 |
public int getTopIndex() { |
| 371 |
int idx = -1; |
| 372 |
if (_data._items.length > 0) |
| 373 |
idx = 0; |
| 374 |
return idx; |
| 375 |
} |
| 376 |
|
| 377 |
public int getBottomIndex() { |
| 378 |
int idx = _data._items.length - 1; |
| 379 |
return idx; |
| 380 |
} |
| 381 |
|
| 382 |
Point getCtrlSize() { |
| 383 |
Point size = getSize(); |
| 384 |
size.x -= getVerticalBar().getSize().x; |
| 385 |
size.y -= getHorizontalBar().getSize().y; |
| 386 |
return size; |
| 387 |
} |
| 388 |
|
| 389 |
void getNameRect(Rectangle rect, Point size, int idx, int nameWidth) { |
| 390 |
idx -= _topItem; |
| 391 |
rect.x = 0; |
| 392 |
rect.y = idx * _itemHeight; |
| 393 |
rect.width = nameWidth; |
| 394 |
rect.height = _itemHeight; |
| 395 |
} |
| 396 |
|
| 397 |
void getStatesRect(Rectangle rect, Point size, int idx, int nameWidth) { |
| 398 |
idx -= _topItem; |
| 399 |
rect.x = nameWidth; |
| 400 |
rect.y = idx * _itemHeight; |
| 401 |
rect.width = size.x - rect.x; |
| 402 |
rect.height = _itemHeight; |
| 403 |
} |
| 404 |
|
| 405 |
void paint(Rectangle rect, GC gc) { |
| 406 |
Point size = getCtrlSize(); |
| 407 |
if (size.x < 2 || size.y < 2 || null == _timeProvider) |
| 408 |
return; |
| 409 |
double time0 = _timeProvider.getTime0(); |
| 410 |
double time1 = _timeProvider.getTime1(); |
| 411 |
double endTime = _timeProvider.getEndTime(); |
| 412 |
double selectedTime = _timeProvider.getSelectedTime(); |
| 413 |
int left = _timeProvider.getNameSpace(); |
| 414 |
// draw thread states |
| 415 |
Object[] items = _data._items; |
| 416 |
for (int i = _topItem; i < items.length; i++) { |
| 417 |
Item item = (Item) items[i]; |
| 418 |
getNameRect(_rect0, size, i, left); |
| 419 |
if (_rect0.y >= size.y) |
| 420 |
break; |
| 421 |
if (item instanceof GroupItem) { |
| 422 |
getStatesRect(_rect1, size, i, left); |
| 423 |
_rect0.width += _rect1.width; |
| 424 |
drawName(item, _rect0, gc); |
| 425 |
} else { |
| 426 |
drawName(item, _rect0, gc); |
| 427 |
getStatesRect(_rect0, size, i, left); |
| 428 |
drawItemData(item, _rect0, time0, time1, endTime, selectedTime, |
| 429 |
gc); |
| 430 |
} |
| 431 |
} |
| 432 |
// fill free canvas area |
| 433 |
_rect0.x = 0; |
| 434 |
_rect0.y += _rect0.height; |
| 435 |
_rect0.width = size.x; |
| 436 |
_rect0.height = size.y - _rect0.y; |
| 437 |
if (_rect0.y < size.y) { |
| 438 |
gc.setBackground(_colors.getColor(TraceColorScheme.BACKGROUND)); |
| 439 |
gc.fillRectangle(_rect0); |
| 440 |
} |
| 441 |
} |
| 442 |
|
| 443 |
void drawName(Item item, Rectangle rect, GC gc) { |
| 444 |
if (item instanceof GroupItem) { |
| 445 |
gc.setBackground(_colors |
| 446 |
.getBkColorGroup(item._selected, _isInFocus)); |
| 447 |
gc.fillRectangle(rect); |
| 448 |
if (item._selected && _isInFocus) { |
| 449 |
gc.setForeground(_colors.getBkColor(item._selected, _isInFocus, |
| 450 |
false)); |
| 451 |
gc.drawRectangle(rect.x, rect.y, rect.width - 2, |
| 452 |
rect.height - 2); |
| 453 |
} |
| 454 |
gc.setForeground(_colors.getBkColor(false, false, false)); |
| 455 |
gc.drawLine(rect.x, rect.y + rect.height - 1, rect.width - 1, |
| 456 |
rect.y + rect.height - 1); |
| 457 |
gc.setForeground(_colors |
| 458 |
.getFgColorGroup(item._selected, _isInFocus)); |
| 459 |
} else { |
| 460 |
gc.setBackground(_colors.getBkColor(item._selected, _isInFocus, |
| 461 |
true)); |
| 462 |
gc.setForeground(_colors.getFgColor(item._selected, _isInFocus)); |
| 463 |
gc.fillRectangle(rect); |
| 464 |
} |
| 465 |
Utils.init(_rect1, rect); |
| 466 |
_rect1.x += 4; |
| 467 |
_rect1.width -= 4; |
| 468 |
int textWidth = 0; |
| 469 |
// draw text |
| 470 |
if (_rect1.width > 0) |
| 471 |
textWidth = Utils.drawText(gc, item._name, _rect1, true) + 8; |
| 472 |
// draw middle line |
| 473 |
Utils.init(_rect1, rect); |
| 474 |
_rect1.x += textWidth; |
| 475 |
_rect1.width -= textWidth; |
| 476 |
gc.setForeground(_colors.getColor(TraceColorScheme.LIGHT_LINE)); |
| 477 |
if (_rect1.width > 0 && item instanceof ThreadItem) { |
| 478 |
int midy = _rect1.y + _rect1.height / 2; |
| 479 |
gc.drawLine(_rect1.x, midy, _rect1.x + _rect1.width, midy); |
| 480 |
} |
| 481 |
// gc.drawLine(_rect1.x + _rect1.width - 1, _rect1.y, _rect1.x + |
| 482 |
// _rect1.width - 1, _rect1.y + _rect1.height); |
| 483 |
} |
| 484 |
|
| 485 |
void drawItemData(Item item, Rectangle rect, double time0, double time1, |
| 486 |
double endTime, double selectedTime, GC gc) { |
| 487 |
if (rect.isEmpty()) |
| 488 |
return; |
| 489 |
if (time1 <= time0) { |
| 490 |
gc.setBackground(_colors.getBkColor(false, false, false)); |
| 491 |
gc.fillRectangle(rect); |
| 492 |
return; |
| 493 |
} |
| 494 |
|
| 495 |
Utils.init(_rect1, rect); |
| 496 |
boolean selected = item._selected; |
| 497 |
double K = (double) rect.width / (time1 - time0); |
| 498 |
|
| 499 |
if (item instanceof GroupItem) { |
| 500 |
gc.setBackground(_colors.getBkColorGroup(selected, _isInFocus)); |
| 501 |
gc.fillRectangle(rect); |
| 502 |
} else if (item instanceof ThreadItem) { |
| 503 |
TRCThread thread = ((ThreadItem) item)._thread; |
| 504 |
int x0 = rect.x; |
| 505 |
EList list = thread.getThreadEvents(); |
| 506 |
Iterator it = list.iterator(); |
| 507 |
TRCThreadEvent lastEvent = null; |
| 508 |
if (it.hasNext()) { |
| 509 |
TRCThreadEvent currEvent = (TRCThreadEvent) it.next(); |
| 510 |
TRCThreadEvent nextEvent = null; |
| 511 |
double currEventTime = currEvent.getTime(); |
| 512 |
double nextEventTime = currEventTime; |
| 513 |
x0 = rect.x + (int) ((currEventTime - time0) * K); |
| 514 |
int xEnd = rect.x + (int) ((time1 - time0) * K); |
| 515 |
int x1 = -1; |
| 516 |
|
| 517 |
// reduce rect |
| 518 |
_rect1.y += 3; |
| 519 |
_rect1.height -= 6; |
| 520 |
|
| 521 |
// fill space before first event |
| 522 |
if (x0 > rect.x) { |
| 523 |
_rect1.width = (x0 <= xEnd ? x0 : xEnd) - _rect1.x; |
| 524 |
gc.setBackground(_colors.getBkColor(selected, _isInFocus, |
| 525 |
false)); |
| 526 |
gc.fillRectangle(_rect1); |
| 527 |
// draw middle line |
| 528 |
gc.setForeground(_colors |
| 529 |
.getColor(TraceColorScheme.MID_LINE)); |
| 530 |
int midy = _rect1.y + _rect1.height / 2; |
| 531 |
gc.drawLine(_rect1.x, midy, _rect1.x + _rect1.width, midy); |
| 532 |
} |
| 533 |
|
| 534 |
// draw event states |
| 535 |
while (x0 <= xEnd && null != currEvent) { |
| 536 |
boolean stopped = false;//currEvent instanceof TRCThreadDeadEvent; |
| 537 |
if (it.hasNext()) { |
| 538 |
nextEvent = (TRCThreadEvent) it.next(); |
| 539 |
nextEventTime = nextEvent.getTime(); |
| 540 |
} else if (stopped) { |
| 541 |
nextEvent = null; |
| 542 |
nextEventTime = time1; |
| 543 |
} else { |
| 544 |
nextEvent = null; |
| 545 |
nextEventTime = endTime; |
| 546 |
} |
| 547 |
x1 = rect.x + (int) ((nextEventTime - time0) * K); |
| 548 |
if (x1 >= rect.x) { |
| 549 |
_rect1.x = x0 >= rect.x ? x0 : rect.x; |
| 550 |
_rect1.width = (x1 <= xEnd ? x1 : xEnd) - _rect1.x; |
| 551 |
boolean timeSelected = currEventTime <= selectedTime && selectedTime < nextEventTime; |
| 552 |
Utils.drawState(_colors, currEvent, _rect1, gc, selected, false, timeSelected); |
| 553 |
} |
| 554 |
lastEvent = currEvent; |
| 555 |
currEvent = nextEvent; |
| 556 |
currEventTime = nextEventTime; |
| 557 |
x0 = x1; |
| 558 |
} |
| 559 |
} |
| 560 |
|
| 561 |
// fill space after last event |
| 562 |
int xEnd = rect.x + rect.width; |
| 563 |
if (x0 < xEnd) { |
| 564 |
_rect1.x = x0 >= rect.x ? x0 : rect.x; |
| 565 |
_rect1.width = xEnd - _rect1.x; |
| 566 |
gc.setBackground(_colors.getBkColor(selected, _isInFocus, false)); |
| 567 |
gc.fillRectangle(_rect1); |
| 568 |
// draw middle line |
| 569 |
gc.setForeground(_colors.getColor(Utils.getEventColor(lastEvent))); |
| 570 |
int midy = _rect1.y + _rect1.height / 2; |
| 571 |
int lw = gc.getLineWidth(); |
| 572 |
gc.setLineWidth(2); |
| 573 |
gc.drawLine(_rect1.x, midy, _rect1.x + _rect1.width, midy); |
| 574 |
gc.setLineWidth(lw); |
| 575 |
} |
| 576 |
|
| 577 |
// draw focus ares |
| 578 |
Utils.init(_rect1, rect); |
| 579 |
gc.setForeground(_colors.getBkColor(false, false, false)); |
| 580 |
int y = _rect1.y; |
| 581 |
gc.drawLine(_rect1.x, y, _rect1.x + _rect1.width, y); |
| 582 |
y++; |
| 583 |
gc.drawLine(_rect1.x, y, _rect1.x + _rect1.width, y); |
| 584 |
y++; |
| 585 |
gc.drawLine(_rect1.x, y, _rect1.x + _rect1.width, y); |
| 586 |
y = _rect1.y + _rect1.height - 1; |
| 587 |
gc.drawLine(_rect1.x, y, _rect1.x + _rect1.width, y); |
| 588 |
y--; |
| 589 |
gc.drawLine(_rect1.x, y, _rect1.x + _rect1.width, y); |
| 590 |
y--; |
| 591 |
gc.drawLine(_rect1.x, y, _rect1.x + _rect1.width, y); |
| 592 |
// gc.setForeground(_colors.getBkColor(selected, _isInFocus, |
| 593 |
// false)); |
| 594 |
} |
| 595 |
|
| 596 |
// draw selected time |
| 597 |
int x = rect.x + (int) ((selectedTime - time0) * K); |
| 598 |
if (x >= rect.x && x < rect.x + rect.width) { |
| 599 |
gc.setForeground(_colors.getColor(TraceColorScheme.SELECTED_TIME)); |
| 600 |
gc.drawLine(x, rect.y, x, rect.y + rect.height); |
| 601 |
} |
| 602 |
} |
| 603 |
|
| 604 |
public void keyPressed(KeyEvent e) { |
| 605 |
int idx = -1; |
| 606 |
if (SWT.HOME == e.keyCode) { |
| 607 |
idx = getTopIndex(); |
| 608 |
} else if (SWT.END == e.keyCode) { |
| 609 |
idx = getBottomIndex(); |
| 610 |
} else if (SWT.ARROW_DOWN == e.keyCode) { |
| 611 |
idx = getSelectedIndex(); |
| 612 |
if (idx < 0) |
| 613 |
idx = 0; |
| 614 |
else if (idx < _data._items.length - 1) |
| 615 |
idx++; |
| 616 |
} else if (SWT.ARROW_UP == e.keyCode) { |
| 617 |
idx = getSelectedIndex(); |
| 618 |
if (idx < 0) |
| 619 |
idx = 0; |
| 620 |
else if (idx > 0) |
| 621 |
idx--; |
| 622 |
} else if (SWT.ARROW_LEFT == e.keyCode) { |
| 623 |
selectPrevEvent(); |
| 624 |
} else if (SWT.ARROW_RIGHT == e.keyCode) { |
| 625 |
selectNextEvent(); |
| 626 |
} else if (SWT.PAGE_DOWN == e.keyCode) { |
| 627 |
int page = countPerPage(); |
| 628 |
idx = getSelectedIndex(); |
| 629 |
if (idx < 0) |
| 630 |
idx = 0; |
| 631 |
idx += page; |
| 632 |
if (idx >= _data._items.length) |
| 633 |
idx = _data._items.length - 1; |
| 634 |
} else if (SWT.PAGE_UP == e.keyCode) { |
| 635 |
int page = countPerPage(); |
| 636 |
idx = getSelectedIndex(); |
| 637 |
if (idx < 0) |
| 638 |
idx = 0; |
| 639 |
idx -= page; |
| 640 |
if (idx < 0) |
| 641 |
idx = 0; |
| 642 |
} else if (SWT.CR == e.keyCode) { |
| 643 |
idx = getSelectedIndex(); |
| 644 |
if (idx >= 0) { |
| 645 |
if (_data._items[idx] instanceof ThreadItem) |
| 646 |
fireDefaultSelection(); |
| 647 |
else if (_data._items[idx] instanceof GroupItem) |
| 648 |
toggle(idx); |
| 649 |
} |
| 650 |
idx = -1; |
| 651 |
} |
| 652 |
if (idx >= 0) { |
| 653 |
selectItem(idx, false); |
| 654 |
fireSelectionChanged(); |
| 655 |
} |
| 656 |
} |
| 657 |
|
| 658 |
public void keyReleased(KeyEvent e) { |
| 659 |
} |
| 660 |
|
| 661 |
public void focusGained(FocusEvent e) { |
| 662 |
_isInFocus = true; |
| 663 |
redraw(); |
| 664 |
} |
| 665 |
|
| 666 |
public void focusLost(FocusEvent e) { |
| 667 |
_isInFocus = false; |
| 668 |
if (1 == _dragState) { |
| 669 |
setCapture(false); |
| 670 |
_dragState = 0; |
| 671 |
} |
| 672 |
redraw(); |
| 673 |
} |
| 674 |
|
| 675 |
public void mouseMove(MouseEvent e) { |
| 676 |
Point size = getCtrlSize(); |
| 677 |
if (1 == _dragState && null != _timeProvider) { |
| 678 |
int leftSpace = _timeProvider.getNameSpace(); |
| 679 |
int x = e.x - leftSpace; |
| 680 |
if (x > 0 && size.x > leftSpace && _dragX != x) { |
| 681 |
_dragX = x; |
| 682 |
double K = (double) (size.x - leftSpace) |
| 683 |
/ (_time1bak - _time0bak); |
| 684 |
double timeDelta = (_dragX - _dragX0) / K; |
| 685 |
double time1 = _time1bak - timeDelta; |
| 686 |
double maxTime = _timeProvider.getMaxTime(); |
| 687 |
if (time1 > maxTime) |
| 688 |
time1 = maxTime; |
| 689 |
double time0 = time1 - (_time1bak - _time0bak); |
| 690 |
if (time0 < 0) |
| 691 |
time0 = 0; |
| 692 |
_timeProvider.setStartFinishTime(time0, time1); |
| 693 |
} |
| 694 |
} |
| 695 |
} |
| 696 |
|
| 697 |
public void mouseDoubleClick(MouseEvent e) { |
| 698 |
if (1 == e.button) { |
| 699 |
int idx = hitTest(e.x, e.y); |
| 700 |
if (idx >= 0) { |
| 701 |
selectItem(idx, false); |
| 702 |
if (_data._items[idx] instanceof ThreadItem) { |
| 703 |
fireDefaultSelection(); |
| 704 |
} |
| 705 |
} |
| 706 |
} |
| 707 |
} |
| 708 |
|
| 709 |
public void mouseDown(MouseEvent e) { |
| 710 |
if (null == _timeProvider) |
| 711 |
return; |
| 712 |
if (1 == e.button) { |
| 713 |
int idx = hitTest(e.x, e.y); |
| 714 |
if (idx >= 0) { |
| 715 |
if (_data._items[idx] instanceof ThreadItem) { |
| 716 |
double hitTime = hitTimeTest(e.x, e.y); |
| 717 |
if (hitTime >= 0) { |
| 718 |
_timeProvider.setSelectedTime(hitTime, false); |
| 719 |
setCapture(true); |
| 720 |
_dragState = 1; |
| 721 |
_dragX = _dragX0 = e.x - _timeProvider.getNameSpace(); |
| 722 |
_time0bak = _timeProvider.getTime0(); |
| 723 |
_time1bak = _timeProvider.getTime1(); |
| 724 |
} |
| 725 |
} else if (_data._items[idx] instanceof GroupItem) { |
| 726 |
_hitIdx = idx; |
| 727 |
_dragState = 2; |
| 728 |
} |
| 729 |
selectItem(idx, false); |
| 730 |
fireSelectionChanged(); |
| 731 |
} |
| 732 |
} |
| 733 |
} |
| 734 |
|
| 735 |
public void mouseUp(MouseEvent e) { |
| 736 |
if (0 != _dragState) { |
| 737 |
setCapture(false); |
| 738 |
if (2 == _dragState) { |
| 739 |
if (hitTest(e.x, e.y) == _hitIdx) |
| 740 |
toggle(_hitIdx); |
| 741 |
} |
| 742 |
_dragState = 0; |
| 743 |
} |
| 744 |
} |
| 745 |
|
| 746 |
public void controlMoved(ControlEvent e) { |
| 747 |
} |
| 748 |
|
| 749 |
public void controlResized(ControlEvent e) { |
| 750 |
adjustScrolls(); |
| 751 |
} |
| 752 |
|
| 753 |
public void widgetDefaultSelected(SelectionEvent e) { |
| 754 |
} |
| 755 |
|
| 756 |
public void widgetSelected(SelectionEvent e) { |
| 757 |
if (e.widget == getVerticalBar()) { |
| 758 |
_topItem = getVerticalBar().getSelection(); |
| 759 |
if (_topItem < 0) |
| 760 |
_topItem = 0; |
| 761 |
redraw(); |
| 762 |
} else if (e.widget == getHorizontalBar() && null != _timeProvider) { |
| 763 |
int startTime = getHorizontalBar().getSelection(); |
| 764 |
double time0 = _timeProvider.getTime0(); |
| 765 |
double time1 = _timeProvider.getTime1(); |
| 766 |
double range = time1 - time0; |
| 767 |
// _timeRangeFixed = true; |
| 768 |
time0 = _timeStep * startTime; |
| 769 |
time1 = time0 + range; |
| 770 |
_timeProvider.setStartFinishTime(time0, time1); |
| 771 |
} |
| 772 |
} |
| 773 |
} |
| 774 |
|
| 775 |
class Item { |
| 776 |
public boolean _expanded; |
| 777 |
public boolean _selected; |
| 778 |
public boolean _hasChildren; |
| 779 |
public String _name; |
| 780 |
|
| 781 |
Item(String name) { |
| 782 |
_name = name; |
| 783 |
} |
| 784 |
|
| 785 |
public String toString() { |
| 786 |
return _name; |
| 787 |
} |
| 788 |
} |
| 789 |
|
| 790 |
class ThreadItem extends Item { |
| 791 |
public TRCThread _thread; |
| 792 |
|
| 793 |
ThreadItem(TRCThread thread) { |
| 794 |
super(thread.getName()); |
| 795 |
_thread = thread; |
| 796 |
} |
| 797 |
} |
| 798 |
|
| 799 |
class GroupItem extends Item { |
| 800 |
public ArrayList _threads; |
| 801 |
|
| 802 |
GroupItem(String name) { |
| 803 |
super(name); |
| 804 |
_threads = new ArrayList(); |
| 805 |
_hasChildren = true; |
| 806 |
} |
| 807 |
|
| 808 |
void add(Object thread) { |
| 809 |
_threads.add(thread); |
| 810 |
} |
| 811 |
} |
| 812 |
|
| 813 |
class ItemData { |
| 814 |
public Object[] _items = new Object[0]; |
| 815 |
private Object _threads[] = new Object[0]; |
| 816 |
private Hashtable _groupTable = new Hashtable(); |
| 817 |
private boolean _flatList; |
| 818 |
|
| 819 |
void clearGroups() { |
| 820 |
Set keys = _groupTable.keySet(); |
| 821 |
Iterator it = keys.iterator(); |
| 822 |
while (it.hasNext()) { |
| 823 |
String key = (String) it.next(); |
| 824 |
GroupItem group = (GroupItem) _groupTable.get(key); |
| 825 |
group._threads.clear(); |
| 826 |
} |
| 827 |
} |
| 828 |
|
| 829 |
void deleteEmptyGroups() { |
| 830 |
Set keys = _groupTable.keySet(); |
| 831 |
Iterator it = keys.iterator(); |
| 832 |
while (it.hasNext()) { |
| 833 |
String key = (String) it.next(); |
| 834 |
GroupItem group = (GroupItem) _groupTable.get(key); |
| 835 |
if (group._threads.size() == 0) |
| 836 |
_groupTable.remove(key); |
| 837 |
} |
| 838 |
} |
| 839 |
|
| 840 |
public void updateItems() { |
| 841 |
ArrayList itemList = new ArrayList(); |
| 842 |
Set keys = _groupTable.keySet(); |
| 843 |
Iterator it = keys.iterator(); |
| 844 |
while (it.hasNext()) { |
| 845 |
String key = (String) it.next(); |
| 846 |
GroupItem group = (GroupItem) _groupTable.get(key); |
| 847 |
if (!_flatList) |
| 848 |
itemList.add(group); |
| 849 |
if (_flatList || group._expanded) { |
| 850 |
Iterator it2 = group._threads.iterator(); |
| 851 |
while (it2.hasNext()) |
| 852 |
itemList.add(new ThreadItem((TRCThread) it2.next())); |
| 853 |
} |
| 854 |
} |
| 855 |
_items = itemList.toArray(); |
| 856 |
} |
| 857 |
|
| 858 |
public void refreshData(Object threads[]) { |
| 859 |
clearGroups(); |
| 860 |
_threads = threads; |
| 861 |
String undef = "<undefined>"; |
| 862 |
ArrayList groupList = new ArrayList(); |
| 863 |
for (int i = 0; i < _threads.length; i++) { |
| 864 |
TRCThread thread = (TRCThread) _threads[i]; |
| 865 |
String groupName = thread.getGroupName(); |
| 866 |
if (null == groupName) |
| 867 |
groupName = undef; |
| 868 |
GroupItem group = (GroupItem) _groupTable.get(groupName); |
| 869 |
if (null == group) { |
| 870 |
group = new GroupItem(groupName); |
| 871 |
group._expanded = !groupName.equalsIgnoreCase("system") |
| 872 |
&& !groupName.equalsIgnoreCase(undef); |
| 873 |
_groupTable.put(groupName, group); |
| 874 |
groupList.add(group); |
| 875 |
} |
| 876 |
group.add(thread); |
| 877 |
} |
| 878 |
deleteEmptyGroups(); |
| 879 |
updateItems(); |
| 880 |
} |
| 881 |
} |