1 17 package org.eclipse.emf.common.ui.viewer; 18 19 20 import java.util.Iterator ; 21 import java.util.LinkedList ; 22 23 import org.eclipse.jface.viewers.TableTreeViewer; 24 import org.eclipse.swt.SWT; 25 import org.eclipse.swt.custom.TableTree; 26 import org.eclipse.swt.custom.TableTreeItem; 27 import org.eclipse.swt.events.PaintEvent; 28 import org.eclipse.swt.events.PaintListener; 29 import org.eclipse.swt.graphics.GC; 30 import org.eclipse.swt.graphics.Image; 31 import org.eclipse.swt.graphics.Point; 32 import org.eclipse.swt.graphics.Rectangle; 33 import org.eclipse.swt.widgets.Composite; 34 import org.eclipse.swt.widgets.Control; 35 import org.eclipse.swt.widgets.Display; 36 import org.eclipse.swt.widgets.Item; 37 import org.eclipse.swt.widgets.Table; 38 import org.eclipse.swt.widgets.TableItem; 39 import org.eclipse.swt.widgets.Widget; 40 41 42 45 public class ExtendedTableTreeViewer extends TableTreeViewer 46 { 47 public static final String ITEM_ID = "TableTreeItemID"; 48 49 public ExtendedTableTreeViewer(TableTree tableTree) 50 { 51 super(tableTree); 52 } 53 54 public ExtendedTableTreeViewer(Composite parent) 55 { 56 super(parent); 57 } 58 59 public ExtendedTableTreeViewer(Composite parent, int style) 60 { 61 super(parent, style); 62 } 63 64 protected Item newItem(Widget parent, int flags, int index) 65 { 66 TableTreeItem item = 67 index >= 0 ? 68 parent instanceof TableTreeItem ? 69 new ExtendedTableTreeItem((TableTreeItem) parent, flags, index) : 70 new ExtendedTableTreeItem((TableTree) parent, flags, index) : 71 parent instanceof TableTreeItem ? 72 new ExtendedTableTreeItem((TableTreeItem) parent, flags) : 73 new ExtendedTableTreeItem((TableTree) parent, flags); 74 75 return item; 76 } 77 78 protected Point interactorSize = new Point(12, 12); 86 protected boolean interactorFound = false; 87 88 protected void hookControl(Control control) 89 { 90 super.hookControl(control); 91 92 105 getTableTree().getTable().addPaintListener 106 (new PaintListener() 107 { 108 protected boolean isStarted; 109 protected TableTreeItem firstTableTreeItem; 110 protected TableTreeItem lastTableTreeItem; 111 protected LinkedList chain; 112 protected int scrollX; 113 114 120 protected Rectangle fixForGC(Rectangle bounds) 121 { 122 if (isGTK() && bounds != null) 123 { 124 bounds.x -= 2; 125 bounds.y -= getTableTree().getTable().getHeaderHeight(); 126 } 127 return bounds; 128 } 129 130 public void paintControl(PaintEvent event) 131 { 132 135 Table table = (Table)event.getSource(); 136 TableItem[] items = table.getItems(); 137 138 firstTableTreeItem = null; 139 lastTableTreeItem = null; 140 141 for (int i = table.getTopIndex(); i < items.length; i++) 142 { 143 TableItem tableItem = items[i]; 144 ExtendedTableTreeItem tableTreeItem = (ExtendedTableTreeItem)tableItem.getData(ITEM_ID); 145 if (!tableTreeItem.isDisposed()) 146 { 147 if (firstTableTreeItem == null) 148 { 149 firstTableTreeItem = tableTreeItem; 150 } 151 lastTableTreeItem = tableTreeItem; 152 153 if (!interactorFound) 154 { 155 Rectangle bounds = tableItem.getImageBounds(0); 156 if (bounds.width != 0) 157 { 158 interactorFound = true; 159 interactorSize = new Point(bounds.width, bounds.height); 160 } 161 } 162 163 Rectangle itemBounds = tableTreeItem.getBounds(0); 164 if (itemBounds != null) 165 { 166 Image image = tableTreeItem.getFirstImage(); 167 if (image != null) 168 { 169 if (!isGTK()) 174 { 175 Display display = tableItem.getDisplay(); 178 event.gc.setBackground( 179 display.getSystemColor(SWT.COLOR_LIST_BACKGROUND)); 180 181 Rectangle bounds = tableTreeItem.getImageBounds(tableItem, 0); 182 bounds.x += bounds.width; 183 bounds.y = itemBounds.y; 184 bounds.width = imagePaddingWidth - 1; 185 bounds.height = itemBounds.height; 186 event.gc.fillRectangle(fixForGC(bounds)); 187 } 188 189 Rectangle sourceBounds = image.getBounds(); 192 Rectangle targetBounds = 193 fixForGC(tableTreeItem.getFirstImageBounds(tableItem)); 194 195 event.gc.drawImage(image, sourceBounds.x, sourceBounds.y, sourceBounds.width, sourceBounds.height, targetBounds.x, targetBounds.y, targetBounds.width, targetBounds.height); 196 } 197 198 fixForGC(itemBounds); 202 if (itemBounds.y + itemBounds.height > event.y + event.height) 203 { 204 205 break; 206 } 207 } 208 } 209 } 210 211 if (firstTableTreeItem != null && isIndenting()) 214 { 215 isStarted = false; 216 chain = new LinkedList (); 217 event.gc.setForeground(table.getDisplay().getSystemColor(SWT.COLOR_WIDGET_NORMAL_SHADOW)); 218 scrollX = items[0].getBounds(0).x; 219 paintLines(event.gc, getTableTree().getItems()); 220 } 221 } 222 223 private boolean indenting = false; 224 private boolean indentingTested = false; 225 226 231 protected boolean isIndenting() 232 { 233 if (!indentingTested) 234 { 235 TableItem[] items = getTableTree().getTable().getItems(); 236 if (items.length > 1) 237 { 238 int x = items[0].getBounds(0).x; 239 for (int i = 1, len = items.length; i < len; i++) 240 { 241 if (items[i].getBounds(0).x != x) 242 { 243 indenting = true; 244 } 245 246 TableTreeItem item = (TableTreeItem)items[i].getData(ITEM_ID); 247 if (item.getParentItem() != null) 248 { 249 indentingTested = true; 250 break; 251 } 252 } 253 } 254 } 255 return indenting; 256 } 257 258 protected boolean paintLines(GC gc, TableTreeItem [] tableTreeItems) 259 { 260 int offset = interactorSize.x; 261 int indent = Math.min(6, (offset - 8) / 2); 262 263 if (tableTreeItems != null) 264 { 265 for (int i = 0; i < tableTreeItems.length; ++i) 266 { 267 TableTreeItem tableTreeItem = tableTreeItems[i]; 268 if (!isStarted && tableTreeItem == firstTableTreeItem) 269 { 270 isStarted = true; 271 } 272 if (isStarted) 273 { 274 Rectangle bounds = tableTreeItem.getBounds(0); 275 int x = 1 + scrollX; 276 277 for (Iterator j = chain.iterator(); j.hasNext(); ) 278 { 279 TableTreeItem ancestor = (TableTreeItem)j.next(); 280 if (ancestor != null) 281 { 282 gc.drawLine(x + offset/2, bounds.y, x + offset/2, bounds.y + bounds.height); 283 } 284 x += offset; 285 } 286 287 if (i + 1 == tableTreeItems.length) 288 { 289 if (i != 0 || !chain.isEmpty()) 290 { 291 gc.drawLine 292 (x + offset/2, bounds.y, 293 x + offset/2, bounds.y + (tableTreeItem.getItemCount() > 0 ? indent - 1 : bounds.height/2)); 294 } 295 } 296 else 297 { 298 if (tableTreeItem.getItemCount() > 0) 299 { 300 gc.drawLine 301 (x + offset/2, bounds.y, x + offset/2, bounds.y + indent - 1); 302 gc.drawLine 303 (x + offset/2, bounds.y + bounds.height - indent + 2, x + offset/2, bounds.y + bounds.height); 304 } 305 else 306 { 307 gc.drawLine(x + offset/2, bounds.y, x + offset/2, bounds.y + bounds.height); 308 } 309 } 310 311 gc.drawLine 312 (x + (tableTreeItem.getItemCount() > 0 ? offset - indent + 1 : offset/2), bounds.y + (bounds.height + 1)/2, 313 x + offset + 2, bounds.y + (bounds.height + 1)/2); 314 315 } 316 if (tableTreeItem.getExpanded()) 317 { 318 chain.addLast(i + 1 == tableTreeItems.length ? null : tableTreeItem); 319 if (!paintLines(gc, tableTreeItem.getItems())) 320 { 321 return false; 322 } 323 chain.removeLast(); 324 } 325 if (isStarted && tableTreeItem == lastTableTreeItem) 326 { 327 return false; 328 } 329 } 330 } 331 332 return true; 333 } 334 }); 335 } 336 337 protected String imagePadding; 338 protected int imagePaddingWidth; 339 340 protected void createImagePadding(int width) 341 { 342 GC gc = new GC(getTableTree().getTable()); 343 imagePadding = " "; 344 while ((imagePaddingWidth = gc.stringExtent(imagePadding).x) < width + 6) 345 { 346 imagePadding += " "; 347 } 348 gc.dispose(); 349 350 TableItem [] tableItems = getTableTree().getTable().getItems(); 351 for (int i = 0; i < tableItems.length; ++i) 352 { 353 TableTreeItem tableTreeItem = (TableTreeItem)tableItems[i].getData(ITEM_ID); 354 tableTreeItem.setText(0, tableTreeItem.getText(0)); 355 } 356 } 357 358 362 protected static boolean isGTK() 363 { 364 return "gtk".equals(SWT.getPlatform()); 365 } 366 367 374 public static Rectangle getImageBounds(TableItem tableItem, int column) 375 { 376 Object item = tableItem.getData(ITEM_ID); 377 return item instanceof ExtendedTableTreeItem ? 378 ((ExtendedTableTreeItem)item).getImageBounds(tableItem, column) : 379 tableItem.getImageBounds(column); 380 } 381 382 386 protected static Rectangle center(Rectangle bounds, int maxHeight) 387 { 388 if (bounds.height < maxHeight) 389 { 390 bounds.y += (maxHeight - bounds.height) / 2; 391 } 392 return bounds; 393 } 394 395 399 protected static Rectangle scale(Rectangle bounds, int maxHeight) 400 { 401 if (bounds.height > maxHeight) 402 { 403 float sf = (float)bounds.width / (float)bounds.height; 404 bounds.width = Math.round(sf * maxHeight); 405 bounds.height = maxHeight; 406 } 407 return bounds; 408 } 409 410 public class ExtendedTableTreeItem extends TableTreeItem 411 { 412 protected Image firstImage; 413 414 public ExtendedTableTreeItem(TableTree parent, int style) 415 { 416 super(parent, style); 417 } 418 419 public ExtendedTableTreeItem(TableTree parent, int style, int index) 420 { 421 super(parent, style, index); 422 } 423 424 public ExtendedTableTreeItem(TableTreeItem parent, int style) 425 { 426 super(parent, style); 427 } 428 429 public ExtendedTableTreeItem(TableTreeItem parent, int style, int index) 430 { 431 super(parent, style, index); 432 } 433 434 public void setText(int index, String text) 435 { 436 if (index == 0 && imagePadding != null) 438 { 439 if (text != null && text.indexOf(imagePadding) == 0) 440 { 441 super.setText(0, text); 442 } 443 else 444 { 445 super.setText(0, imagePadding + text); 446 } 447 } 448 else 449 { 450 super.setText(index, text); 451 } 452 } 453 454 public String getText(int index) 455 { 456 String result = super.getText(index); 457 if (index == 0 && result != null && imagePadding != null && result.indexOf(imagePadding) == 0) 458 { 459 result = result.substring(imagePadding.length()); 460 } 461 462 return result; 463 } 464 465 public void setImage(int index, Image image) 466 { 467 if (index == 0) 468 { 469 firstImage = image; 470 if (image != null && imagePadding == null) 471 { 472 createImagePadding(image.getBounds().width); 473 } 474 } 475 else 476 { 477 super.setImage(index, image); 478 } 479 } 480 481 485 public Image getFirstImage() 486 { 487 return firstImage; 488 } 489 490 public int getImagePaddingWidth() 491 { 492 return imagePaddingWidth; 493 } 494 495 500 public Rectangle getImageBounds(int column) 501 { 502 return getImageBounds(getTableItem(), column); 503 } 504 505 510 private Rectangle getImageBounds(TableItem tableItem, int column) 511 { 512 if (isGTK()) 513 { 514 Rectangle result = tableItem.getBounds(column); 515 int itemHeight = result.height; 516 517 if (column == 0) 518 { 519 result.width = interactorSize.x; 520 result.height = interactorSize.y; 521 } 522 else 523 { 524 Image image = tableItem.getImage(column); 525 if (image == null) 526 { 527 result.width = 0; 528 result.height = 0; 529 } 530 else 531 { 532 Rectangle imageBounds = image.getBounds(); 533 result.width = imageBounds.width; 534 result.height = imageBounds.height; 535 } 536 } 537 center(result, itemHeight); 538 result.x += 3; 539 540 return result; 541 } 542 543 return tableItem.getImageBounds(column); 544 } 545 546 550 public Rectangle getFirstImageBounds() 551 { 552 return getFirstImageBounds(getTableItem()); 553 } 554 555 560 private Rectangle getFirstImageBounds(TableItem tableItem) 561 { 562 Rectangle result = new Rectangle(0, 0, 0, 0); 563 564 if (tableItem != null) 565 { 566 Rectangle itemBounds = tableItem.getBounds(0); 567 Rectangle interactorBounds = getImageBounds(tableItem, 0); 568 569 result.x = interactorBounds.x + interactorBounds.width + 5; 570 result.y = itemBounds.y; 571 572 if (firstImage != null) 573 { 574 Rectangle imageBounds = firstImage.getBounds(); 575 result.width = imageBounds.width; 576 result.height = imageBounds.height; 577 } 578 579 scale(result, itemBounds.height); 580 center(result, itemBounds.height); 581 } 582 583 return result; 584 } 585 586 589 protected TableItem getTableItem() 590 { 591 TableItem[] items = getTableTree().getTable().getItems(); 592 for (int i = 0; i < items.length; i++) 593 { 594 if (items[i].getData(ITEM_ID) == this) return items[i]; 595 } 596 return null; 597 } 598 } 599 } 600 | Popular Tags |