1 /**********************************************************************
2 * Copyright (c) 2005, 2013 IBM Corporation, Ericsson
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
9 * IBM - Initial API and implementation
10 * Bernd Hufmann - Updated for TMF
11 **********************************************************************/
13 package org
.eclipse
.tracecompass
.tmf
.ui
.views
.uml2sd
;
15 import java
.text
.MessageFormat
;
16 import java
.util
.ArrayList
;
17 import java
.util
.List
;
18 import java
.util
.Timer
;
19 import java
.util
.TimerTask
;
21 import org
.eclipse
.jface
.contexts
.IContextIds
;
22 import org
.eclipse
.jface
.util
.IPropertyChangeListener
;
23 import org
.eclipse
.jface
.util
.PropertyChangeEvent
;
24 import org
.eclipse
.jface
.viewers
.ISelectionProvider
;
25 import org
.eclipse
.jface
.viewers
.StructuredSelection
;
26 import org
.eclipse
.swt
.SWT
;
27 import org
.eclipse
.swt
.accessibility
.ACC
;
28 import org
.eclipse
.swt
.accessibility
.Accessible
;
29 import org
.eclipse
.swt
.accessibility
.AccessibleAdapter
;
30 import org
.eclipse
.swt
.accessibility
.AccessibleControlAdapter
;
31 import org
.eclipse
.swt
.accessibility
.AccessibleControlEvent
;
32 import org
.eclipse
.swt
.accessibility
.AccessibleEvent
;
33 import org
.eclipse
.swt
.events
.DisposeEvent
;
34 import org
.eclipse
.swt
.events
.DisposeListener
;
35 import org
.eclipse
.swt
.events
.FocusEvent
;
36 import org
.eclipse
.swt
.events
.FocusListener
;
37 import org
.eclipse
.swt
.events
.KeyEvent
;
38 import org
.eclipse
.swt
.events
.MouseEvent
;
39 import org
.eclipse
.swt
.events
.SelectionEvent
;
40 import org
.eclipse
.swt
.events
.SelectionListener
;
41 import org
.eclipse
.swt
.events
.TraverseEvent
;
42 import org
.eclipse
.swt
.events
.TraverseListener
;
43 import org
.eclipse
.swt
.graphics
.GC
;
44 import org
.eclipse
.swt
.graphics
.Image
;
45 import org
.eclipse
.swt
.graphics
.ImageData
;
46 import org
.eclipse
.swt
.graphics
.Rectangle
;
47 import org
.eclipse
.swt
.printing
.Printer
;
48 import org
.eclipse
.swt
.printing
.PrinterData
;
49 import org
.eclipse
.swt
.widgets
.Canvas
;
50 import org
.eclipse
.swt
.widgets
.Caret
;
51 import org
.eclipse
.swt
.widgets
.Composite
;
52 import org
.eclipse
.swt
.widgets
.Control
;
53 import org
.eclipse
.swt
.widgets
.Display
;
54 import org
.eclipse
.swt
.widgets
.Event
;
55 import org
.eclipse
.swt
.widgets
.Listener
;
56 import org
.eclipse
.swt
.widgets
.MenuItem
;
57 import org
.eclipse
.tracecompass
.internal
.tmf
.ui
.Activator
;
58 import org
.eclipse
.tracecompass
.internal
.tmf
.ui
.ITmfImageConstants
;
59 import org
.eclipse
.tracecompass
.tmf
.core
.timestamp
.ITmfTimestamp
;
60 import org
.eclipse
.tracecompass
.tmf
.ui
.views
.uml2sd
.core
.BaseMessage
;
61 import org
.eclipse
.tracecompass
.tmf
.ui
.views
.uml2sd
.core
.BasicExecutionOccurrence
;
62 import org
.eclipse
.tracecompass
.tmf
.ui
.views
.uml2sd
.core
.Frame
;
63 import org
.eclipse
.tracecompass
.tmf
.ui
.views
.uml2sd
.core
.GraphNode
;
64 import org
.eclipse
.tracecompass
.tmf
.ui
.views
.uml2sd
.core
.ITimeRange
;
65 import org
.eclipse
.tracecompass
.tmf
.ui
.views
.uml2sd
.core
.Lifeline
;
66 import org
.eclipse
.tracecompass
.tmf
.ui
.views
.uml2sd
.core
.Metrics
;
67 import org
.eclipse
.tracecompass
.tmf
.ui
.views
.uml2sd
.dialogs
.SDPrintDialog
;
68 import org
.eclipse
.tracecompass
.tmf
.ui
.views
.uml2sd
.dialogs
.SDPrintDialogUI
;
69 import org
.eclipse
.tracecompass
.tmf
.ui
.views
.uml2sd
.drawings
.IColor
;
70 import org
.eclipse
.tracecompass
.tmf
.ui
.views
.uml2sd
.handlers
.provider
.ISDCollapseProvider
;
71 import org
.eclipse
.tracecompass
.tmf
.ui
.views
.uml2sd
.load
.LoadersManager
;
72 import org
.eclipse
.tracecompass
.tmf
.ui
.views
.uml2sd
.preferences
.ISDPreferences
;
73 import org
.eclipse
.tracecompass
.tmf
.ui
.views
.uml2sd
.preferences
.SDViewPref
;
74 import org
.eclipse
.tracecompass
.tmf
.ui
.views
.uml2sd
.util
.Messages
;
75 import org
.eclipse
.ui
.contexts
.IContextService
;
76 import org
.eclipse
.ui
.part
.ViewPart
;
80 * This class implements sequence diagram widget used in the sequence diagram view.
86 public class SDWidget
extends ScrollView
implements SelectionListener
,
87 IPropertyChangeListener
, DisposeListener
, ITimeCompressionListener
{
89 // ------------------------------------------------------------------------
91 // ------------------------------------------------------------------------
94 * The frame to display in the sequence diagram widget.
98 * The overview image to display.
100 private Image fOverView
= null;
102 * The zoom in menu item.
104 private MenuItem fZoomIn
= null;
106 * The zoom out menu item.
108 private MenuItem fZoomOut
= null;
110 * The sequence diagram selection provider.
112 private SDWidgetSelectionProvider fSelProvider
= null;
114 * The current zoom value.
116 private float fZoomValue
= 1;
118 * The current zoomInMode (true for zoom in).
120 private boolean fZoomInMode
= false;
122 * The current zoomOutMode (true for zoom out).
124 private boolean fZoomOutMode
= false;
126 * The current list of selected graph nodes.
128 private List
<GraphNode
> fSelectedNodeList
= null;
130 * Flag whether ctrl button is selected or not.
132 private boolean fCtrlSelection
= false;
134 * A reference to the view site.
136 private ViewPart fSite
= null;
138 * The current graph node (the last selected one).
140 private GraphNode fCurrentGraphNode
= null;
142 * The first graph node in list (multiple selection).
144 private GraphNode fListStart
= null;
146 * The previous graph node (multiple selection).
148 private List
<GraphNode
> fPrevList
= null;
150 * The time compression bar.
152 private TimeCompressionBar fTimeBar
= null;
154 * The current diagram tool tip.
156 private DiagramToolTip fToolTip
= null;
158 * The accessible object reference of view control.
160 private Accessible fAccessible
= null;
162 * The current node for the tooltip to display.
164 private GraphNode fToolTipNode
;
166 * The life line to drag and drop.
168 private Lifeline fDragAndDrop
= null;
170 * The number of focused widgets.
172 private int fFocusedWidget
= -1;
176 private float fPrinterZoom
= 0;
178 * Y coordinate for printer.
180 private int fPrinterY
= 0;
182 * X coordinate for printer.
184 private int fPrinterX
= 0;
186 * Flag whether drag and drop is enabled or not.
188 private boolean fIsDragAndDrop
= false;
190 * The x coordinate for drag.
192 private int fDragX
= 0;
194 * The y coordinate for drag.
196 private int fDragY
= 0;
200 private boolean fReorderMode
= false;
202 * The collapse caret image.
204 private Image fCollapaseCaretImg
= null;
206 * The arrow up caret image.
208 private Image fArrowUpCaretImg
= null;
210 * The current caret image.
212 private Image fCurrentCaretImage
= null;
214 * A sequence diagramm collapse provider (for collapsing graph nodes)
216 private ISDCollapseProvider fCollapseProvider
= null;
218 * The insertion caret.
220 private Caret fInsertionCartet
= null;
222 * The reorder list when in reorder mode.
224 private List
<Lifeline
[]> fReorderList
= null;
226 * Flag to specify whether in printing mode or not.
228 private boolean fIsPrinting
= false;
230 * A printer reference.
232 private Printer fPrinter
= null;
234 * Flag whether shift was selected or not.
236 private boolean fShiftSelection
= false;
238 * The scroll tooltip.
240 private DiagramToolTip fScrollToolTip
= null;
242 * Timer for auto_scroll feature
244 private AutoScroll fLocalAutoScroll
= null;
246 * TimerTask for auto_scroll feature !=null when auto scroll is running
248 private Timer fLocalAutoScrollTimer
= null;
250 // ------------------------------------------------------------------------
252 // ------------------------------------------------------------------------
254 * Constructor for SDWidget.
255 * @param c The parent composite
258 public SDWidget(Composite c
, int s
) {
259 super(c
, s
| SWT
.NO_BACKGROUND
, true);
260 setOverviewEnabled(true);
261 fSelectedNodeList
= new ArrayList
<>();
262 fSelProvider
= new SDWidgetSelectionProvider();
263 SDViewPref
.getInstance().addPropertyChangeListener(this);
264 fToolTip
= new DiagramToolTip(getViewControl());
265 super.addDisposeListener(this);
267 fScrollToolTip
= new DiagramToolTip(c
);
268 getVerticalBar().addListener(SWT
.MouseUp
, new Listener() {
271 public void handleEvent(Event event
) {
272 fScrollToolTip
.hideToolTip();
276 fAccessible
= getViewControl().getAccessible();
278 fAccessible
.addAccessibleListener(new AccessibleAdapter() {
280 public void getName(AccessibleEvent e
) {
282 if (e
.childID
== 0) {
283 if (fToolTipNode
!= null) {
284 if (fToolTipNode
instanceof Lifeline
) {
285 Lifeline lifeline
= (Lifeline
) fToolTipNode
;
286 e
.result
= lifeline
.getToolTipText();
288 e
.result
= fToolTipNode
.getName() + getPostfixForTooltip(true);
292 if (getFocusNode() != null) {
293 if (getFocusNode() instanceof Lifeline
) {
294 e
.result
= MessageFormat
.format(Messages
.SequenceDiagram_LifelineNode
, new Object
[] { String
.valueOf(getFocusNode().getName()) });
296 if (getFocusNode() instanceof BaseMessage
) {
297 BaseMessage mes
= (BaseMessage
) getFocusNode();
298 if ((mes
.getStartLifeline() != null) && (mes
.getEndLifeline() != null)) {
299 e
.result
= MessageFormat
.format(
300 Messages
.SequenceDiagram_MessageNode
,
301 new Object
[] { String
.valueOf(mes
.getName()), String
.valueOf(mes
.getStartLifeline().getName()), Integer
.valueOf(mes
.getStartOccurrence()), String
.valueOf(mes
.getEndLifeline().getName()),
302 Integer
.valueOf(mes
.getEndOccurrence()) });
303 } else if ((mes
.getStartLifeline() == null) && (mes
.getEndLifeline() != null)) {
304 e
.result
= MessageFormat
.format(Messages
.SequenceDiagram_FoundMessageNode
, new Object
[] { String
.valueOf(mes
.getName()), String
.valueOf(mes
.getEndLifeline().getName()), Integer
.valueOf(mes
.getEndOccurrence()) });
305 } else if ((mes
.getStartLifeline() != null) && (mes
.getEndLifeline() == null)) {
306 e
.result
= MessageFormat
.format(Messages
.SequenceDiagram_LostMessageNode
, new Object
[] { String
.valueOf(mes
.getName()), String
.valueOf(mes
.getStartLifeline().getName()), Integer
.valueOf(mes
.getStartOccurrence()) });
308 } else if (getFocusNode() instanceof BasicExecutionOccurrence
) {
309 BasicExecutionOccurrence exec
= (BasicExecutionOccurrence
) getFocusNode();
310 e
.result
= MessageFormat
.format(Messages
.SequenceDiagram_ExecutionOccurrenceWithParams
,
311 new Object
[] { String
.valueOf(exec
.getName()), String
.valueOf(exec
.getLifeline().getName()), Integer
.valueOf(exec
.getStartOccurrence()), Integer
.valueOf(exec
.getEndOccurrence()) });
319 fAccessible
.addAccessibleControlListener(new AccessibleControlAdapter() {
321 public void getFocus(AccessibleControlEvent e
) {
322 if (fFocusedWidget
== -1) {
323 e
.childID
= ACC
.CHILDID_SELF
;
325 e
.childID
= fFocusedWidget
;
330 public void getRole(AccessibleControlEvent e
) {
332 case ACC
.CHILDID_SELF
:
333 e
.detail
= ACC
.ROLE_CLIENT_AREA
;
336 e
.detail
= ACC
.ROLE_TOOLTIP
;
339 e
.detail
= ACC
.ROLE_LABEL
;
347 public void getState(AccessibleControlEvent e
) {
348 e
.detail
= ACC
.STATE_FOCUSABLE
;
349 if (e
.childID
== ACC
.CHILDID_SELF
) {
350 e
.detail
|= ACC
.STATE_FOCUSED
;
352 e
.detail
|= ACC
.STATE_SELECTABLE
;
353 if (e
.childID
== fFocusedWidget
) {
354 e
.detail
|= ACC
.STATE_FOCUSED
| ACC
.STATE_SELECTED
| ACC
.STATE_CHECKED
;
360 fInsertionCartet
= new Caret((Canvas
) getViewControl(), SWT
.NONE
);
361 fInsertionCartet
.setVisible(false);
363 fCollapaseCaretImg
= Activator
.getDefault().getImageFromPath(ITmfImageConstants
.IMG_UI_ARROW_COLLAPSE_OBJ
);
364 fArrowUpCaretImg
= Activator
.getDefault().getImageFromPath(ITmfImageConstants
.IMG_UI_ARROW_UP_OBJ
);
366 fReorderList
= new ArrayList
<>();
367 getViewControl().addTraverseListener(new LocalTraverseListener());
369 addTraverseListener(new LocalTraverseListener());
371 getViewControl().addFocusListener(new FocusListener() {
374 public void focusGained(FocusEvent e
) {
375 SDViewPref
.getInstance().setNoFocusSelection(false);
376 fCtrlSelection
= false;
377 fShiftSelection
= false;
382 public void focusLost(FocusEvent e
) {
383 SDViewPref
.getInstance().setNoFocusSelection(true);
389 // ------------------------------------------------------------------------
391 // ------------------------------------------------------------------------
394 * Sets the time compression bar.
396 * @param bar The time compression bar to set
398 public void setTimeBar(TimeCompressionBar bar
) {
401 fTimeBar
.addTimeCompressionListener(this);
406 * Resize the contents to insure the frame fit into the view
408 * @param frame the frame which will be drawn in the view
410 public void resizeContents(Frame frame
) {
411 int width
= Math
.round((frame
.getWidth() + 2 * Metrics
.FRAME_H_MARGIN
) * fZoomValue
);
412 int height
= Math
.round((frame
.getHeight() + 2 * Metrics
.FRAME_V_MARGIN
) * fZoomValue
);
413 resizeContents(width
, height
);
417 * The frame to render (the sequence diagram)
419 * @param theFrame the frame to display
420 * @param resetPosition boolean
422 public void setFrame(Frame theFrame
, boolean resetPosition
) {
423 fReorderList
.clear();
424 fSelectedNodeList
.clear();
425 fSelProvider
.setSelection(new StructuredSelection());
428 setContentsPos(0, 0);
429 resizeContents(fFrame
);
432 // prepare the old overview to be reused
433 if (fOverView
!= null) {
437 resizeContents(fFrame
);
441 * Returns the current Frame (the sequence diagram container)
445 public Frame
getFrame() {
450 * Returns the selection provider for the current sequence diagram
452 * @return the selection provider
454 public ISelectionProvider
getSelectionProvider() {
459 * Returns a list of selected graph nodes.
461 * @return a list of selected graph nodes.
463 public List
<GraphNode
> getSelection() {
464 return fSelectedNodeList
;
468 * Adds a graph node to the selected nodes list.
470 * @param node A graph node
472 public void addSelection(GraphNode node
) {
476 fSelectedNodeList
.add(node
);
477 node
.setSelected(true);
478 fCurrentGraphNode
= node
;
479 StructuredSelection selection
= new StructuredSelection(fSelectedNodeList
);
480 fSelProvider
.setSelection(selection
);
484 * Adds a list of node to the selected nodes list.
486 * @param list of graph nodes
488 public void addSelection(List
<GraphNode
> list
) {
489 for (int i
= 0; i
< list
.size(); i
++) {
490 if (!fSelectedNodeList
.contains(list
.get(i
))) {
491 fSelectedNodeList
.add(list
.get(i
));
492 list
.get(i
).setSelected(true);
495 StructuredSelection selection
= new StructuredSelection(fSelectedNodeList
);
496 fSelProvider
.setSelection(selection
);
500 * Removes a node from the selected nodes list.
502 * @param node to remove
504 public void removeSelection(GraphNode node
) {
505 fSelectedNodeList
.remove(node
);
506 node
.setSelected(false);
507 node
.setFocused(false);
508 StructuredSelection selection
= new StructuredSelection(fSelectedNodeList
);
509 fSelProvider
.setSelection(selection
);
513 * Removes a list of graph nodes from the selected nodes list.
515 * @param list of nodes to remove.
517 public void removeSelection(List
<GraphNode
> list
) {
518 fSelectedNodeList
.removeAll(list
);
519 for (int i
= 0; i
< list
.size(); i
++) {
520 list
.get(i
).setSelected(false);
521 list
.get(i
).setFocused(false);
523 StructuredSelection selection
= new StructuredSelection(fSelectedNodeList
);
524 fSelProvider
.setSelection(selection
);
528 * Clear the list of GraphNodes which must be drawn selected.
530 public void clearSelection() {
531 for (int i
= 0; i
< fSelectedNodeList
.size(); i
++) {
532 fSelectedNodeList
.get(i
).setSelected(false);
533 fSelectedNodeList
.get(i
).setFocused(false);
535 fCurrentGraphNode
= null;
536 fSelectedNodeList
.clear();
537 fSelProvider
.setSelection(new StructuredSelection());
543 * @param viewSite The view part to set
545 public void setSite(ViewPart viewSite
) {
547 fSite
.getSite().setSelectionProvider(fSelProvider
);
548 Object serviceObject
= fSite
.getSite().getWorkbenchWindow().getService(IContextService
.class);
549 IContextService service
= (IContextService
) serviceObject
;
550 service
.activateContext("org.eclipse.linuxtools.tmf.ui.view.uml2sd.context"); //$NON-NLS-1$
551 service
.activateContext(IContextIds
.CONTEXT_ID_WINDOW
);
555 * Returns the GraphNode overView the mouse if any
557 * @return the current graph node
559 public GraphNode
getMouseOverNode() {
560 return fCurrentGraphNode
;
564 * Sets the zoom in mode.
567 * The mode value to set.
569 public void setZoomInMode(boolean value
) {
571 setZoomOutMode(false);
577 * Sets the zoom out mode.
580 * The mode value to set.
582 public void setZoomOutMode(boolean value
) {
584 setZoomInMode(false);
586 fZoomOutMode
= value
;
590 * Sets the current zoom value.
593 * The current zoom value
596 public void setZoomValue(float zoomValue
) {
597 fZoomValue
= zoomValue
;
601 * Moves the Sequence diagram to ensure the given node is visible and draw it selected
603 * @param node the GraphNode to move to
605 public void moveTo(GraphNode node
) {
615 * Moves the Sequence diagram to ensure the given node is visible
617 * @param node the GraphNode to move to
619 public void ensureVisible(GraphNode node
) {
623 int x
= Math
.round(node
.getX() * fZoomValue
);
624 int y
= Math
.round(node
.getY() * fZoomValue
);
625 int width
= Math
.round(node
.getWidth() * fZoomValue
);
626 int height
= Math
.round(node
.getHeight() * fZoomValue
);
627 if ((node
instanceof BaseMessage
) && (height
== 0)) {
628 int header
= Metrics
.LIFELINE_HEARDER_TEXT_V_MARGIN
* 2 + Metrics
.getLifelineHeaderFontHeigth();
629 height
= -Math
.round((Metrics
.getMessagesSpacing() + header
) * fZoomValue
);
630 y
= y
+ Math
.round(Metrics
.SYNC_INTERNAL_MESSAGE_HEIGHT
* fZoomValue
);
632 if (node
instanceof BasicExecutionOccurrence
) {
636 if (node
instanceof Lifeline
) {
638 height
= getVisibleHeight();
640 ensureVisible(x
, y
, width
, height
, SWT
.CENTER
, true);
645 * Returns the current zoom factor.
646 * @return the current zoom factor.
648 public float getZoomFactor() {
653 * Returns teh printer reference.
655 * @return the printer reference
657 public Printer
getPrinter() {
662 * Returns whether the widget is used for printing or not.
664 * @return whether the widget is used for printing or not
666 public boolean isPrinting() {
671 * Returns the current graph node.
673 * @return the current graph node
676 public GraphNode
getCurrentGraphNode() {
677 return fCurrentGraphNode
;
681 * Returns the current zoom value.
683 * @return the current zoom value
686 public float getZoomValue() {
691 * Gets the zoom in mode.
693 * @return the mode value to set.
696 public boolean getZoomInMode() {
702 * Gets the zoom out mode.
704 * @return the mode value to set.
707 public boolean getZoomOutMode() {
712 * Returns if ctrl selection
713 * @return true if ctrl selection else false
716 public boolean isCtrlSelection() {
717 return fCtrlSelection
;
721 * Returns if shift selection
722 * @return true if shift Selection else false
725 public boolean isShiftSelection() {
726 return fCtrlSelection
;
730 * Gets the overview image.
732 * @param rect Rectangle to include overview.
733 * @return the overview image
735 public Image
getOverview(Rectangle rect
) {
736 float oldzoom
= fZoomValue
;
737 if ((fOverView
!= null) && ((rect
.width
!= fOverView
.getBounds().width
) || (rect
.height
!= fOverView
.getBounds().height
))) {
741 if (fOverView
== null) {
742 int backX
= getContentsX();
743 int backY
= getContentsY();
744 setContentsPos(0, 0);
745 fOverView
= new Image(getDisplay(), rect
.width
, rect
.height
);
746 GC gcim
= new GC(fOverView
);
747 NGC context
= new NGC(this, gcim
);
748 context
.setBackground(SDViewPref
.getInstance().getBackGroundColor(ISDPreferences
.PREF_FRAME
));
749 fFrame
.draw(context
);
750 setContentsPos(backX
, backY
);
754 fZoomValue
= oldzoom
;
759 * Resets the zoom factor.
761 public void resetZoomFactor() {
762 int currentX
= Math
.round(getContentsX() / fZoomValue
);
763 int currentY
= Math
.round(getContentsY() / fZoomValue
);
765 if (fTimeBar
!= null && !fTimeBar
.isDisposed()) {
766 fTimeBar
.setZoom(fZoomValue
);
770 setContentsPos(currentX
, currentY
);
774 * Enable or disable the lifeline reodering using Drag and Drop
776 * @param mode - true to enable false otherwise
778 public void setReorderMode(boolean mode
) {
783 * Return the lifelines reorder sequence (using Drag and Drop) if the the reorder mode is turn on. Each ArryList
784 * element is of type Lifeline[2] with Lifeline[0] inserted before Lifeline[1] in the diagram
786 * @return - the re-odered sequence
788 public List
<Lifeline
[]> getLifelineReoderList() {
793 * Sets the focus on given graph node (current node).
796 * The graph node to focus on.
798 public void setFocus(GraphNode node
) {
802 if (fCurrentGraphNode
!= null) {
803 fCurrentGraphNode
.setFocused(false);
805 fCurrentGraphNode
= node
;
806 node
.setFocused(true);
812 * Returns the graph node focused on.
814 * @return the current graph node
816 public GraphNode
getFocusNode() {
817 return fCurrentGraphNode
;
821 * Method to traverse right.
823 public void traverseRight() {
824 Object selectedNode
= getFocusNode();
825 if (selectedNode
== null) {
828 GraphNode node
= null;
829 if ((selectedNode
instanceof BaseMessage
) && (((BaseMessage
) selectedNode
).getEndLifeline() != null)) {
830 node
= fFrame
.getCalledMessage((BaseMessage
) selectedNode
);
832 if (selectedNode
instanceof BasicExecutionOccurrence
) {
833 selectedNode
= ((BasicExecutionOccurrence
) selectedNode
).getLifeline();
835 if ((node
== null) && (selectedNode
instanceof Lifeline
)) {
836 for (int i
= 0; i
< fFrame
.lifeLinesCount(); i
++) {
837 if ((selectedNode
== fFrame
.getLifeline(i
)) && (i
< fFrame
.lifeLinesCount() - 1)) {
838 node
= fFrame
.getLifeline(i
+ 1);
850 * Method to traverse left.
852 public void traverseLeft() {
853 Object selectedNode
= getFocusNode();
854 GraphNode node
= null;
855 if ((selectedNode
instanceof BaseMessage
) && (((BaseMessage
) selectedNode
).getStartLifeline() != null)) {
856 node
= fFrame
.getCallerMessage((BaseMessage
) selectedNode
);
858 if (selectedNode
instanceof BasicExecutionOccurrence
) {
859 selectedNode
= ((BasicExecutionOccurrence
) selectedNode
).getLifeline();
862 if ((selectedNode
instanceof BaseMessage
) && (((BaseMessage
) selectedNode
).getEndLifeline() != null)) {
863 selectedNode
= ((BaseMessage
) selectedNode
).getEndLifeline();
865 for (int i
= 0; i
< fFrame
.lifeLinesCount(); i
++) {
866 if ((selectedNode
== fFrame
.getLifeline(i
)) && (i
> 0)) {
867 node
= fFrame
.getLifeline(i
- 1);
871 if ((fFrame
.lifeLinesCount() > 0) && (node
== null)) {
872 node
= fFrame
.getLifeline(0);
882 * Method to traverse up.
884 public void traverseUp() {
885 Object selectedNode
= getFocusNode();
886 if (selectedNode
== null) {
889 GraphNode node
= null;
890 if (selectedNode
instanceof BaseMessage
) {
891 node
= fFrame
.getPrevLifelineMessage(((BaseMessage
) selectedNode
).getStartLifeline(), (BaseMessage
) selectedNode
);
892 } else if (selectedNode
instanceof Lifeline
) {
893 node
= fFrame
.getPrevLifelineMessage((Lifeline
) selectedNode
, null);
894 if (!(node
instanceof Lifeline
)) {
897 } else if (selectedNode
instanceof BasicExecutionOccurrence
) {
898 node
= fFrame
.getPrevExecOccurrence((BasicExecutionOccurrence
) selectedNode
);
900 node
= ((BasicExecutionOccurrence
) selectedNode
).getLifeline();
903 if ((node
== null) && (selectedNode
instanceof BaseMessage
) && (((BaseMessage
) selectedNode
).getStartLifeline() != null)) {
904 node
= ((BaseMessage
) selectedNode
).getStartLifeline();
914 * Method to traverse down.
916 public void traverseDown() {
917 Object selectedNode
= getFocusNode();
918 if (selectedNode
== null) {
922 if (selectedNode
instanceof BaseMessage
) {
923 node
= fFrame
.getNextLifelineMessage(((BaseMessage
) selectedNode
).getStartLifeline(), (BaseMessage
) selectedNode
);
924 } else if (selectedNode
instanceof Lifeline
) {
925 node
= fFrame
.getFirstExecution((Lifeline
) selectedNode
);
926 } else if (selectedNode
instanceof BasicExecutionOccurrence
) {
927 node
= fFrame
.getNextExecOccurrence((BasicExecutionOccurrence
) selectedNode
);
939 * Method to traverse home.
941 public void traverseHome() {
942 Object selectedNode
= getFocusNode();
943 if (selectedNode
== null) {
946 GraphNode node
= null;
948 if (selectedNode
instanceof BaseMessage
) {
949 if (((BaseMessage
) selectedNode
).getStartLifeline() != null) {
950 node
= fFrame
.getNextLifelineMessage(((BaseMessage
) selectedNode
).getStartLifeline(), null);
952 node
= fFrame
.getNextLifelineMessage(((BaseMessage
) selectedNode
).getEndLifeline(), null);
954 } else if (selectedNode
instanceof Lifeline
) {
955 node
= fFrame
.getNextLifelineMessage((Lifeline
) selectedNode
, null);
956 } else if (selectedNode
instanceof BasicExecutionOccurrence
) {
957 node
= fFrame
.getFirstExecution(((BasicExecutionOccurrence
) selectedNode
).getLifeline());
959 if (fFrame
.lifeLinesCount() > 0) {
960 Lifeline lifeline
= fFrame
.getLifeline(0);
961 node
= fFrame
.getNextLifelineMessage(lifeline
, null);
972 * Method to traverse to the end.
974 public void traverseEnd() {
975 Object selectedNode
= getFocusNode();
976 if (selectedNode
== null) {
980 if (selectedNode
instanceof BaseMessage
) {
981 node
= fFrame
.getPrevLifelineMessage(((BaseMessage
) selectedNode
).getStartLifeline(), null);
982 } else if (selectedNode
instanceof Lifeline
) {
983 node
= fFrame
.getPrevLifelineMessage((Lifeline
) selectedNode
, null);
984 } else if (selectedNode
instanceof BasicExecutionOccurrence
) {
985 node
= fFrame
.getLastExecOccurrence(((BasicExecutionOccurrence
) selectedNode
).getLifeline());
987 if (fFrame
.lifeLinesCount() > 0) {
988 Lifeline lifeline
= fFrame
.getLifeline(0);
989 node
= fFrame
.getPrevLifelineMessage(lifeline
, null);
1002 * Method to print UI.
1004 * @param sdPrintDialog the sequence diagram printer dialog.
1006 public void printUI(SDPrintDialogUI sdPrintDialog
) {
1007 PrinterData data
= sdPrintDialog
.getPrinterData();
1009 if ((data
== null) || (fFrame
== null)) {
1013 fPrinter
= new Printer(data
);
1015 String jobName
= MessageFormat
.format(Messages
.SequenceDiagram_plus
, new Object
[] { String
.valueOf(fSite
.getContentDescription()), String
.valueOf(fFrame
.getName()) });
1016 fPrinter
.startJob(jobName
);
1018 GC gc
= new GC(fPrinter
);
1020 float lastZoom
= fZoomValue
;
1022 Rectangle area
= getClientArea();
1026 NGC context
= new NGC(this, gcim
);
1028 // Set the metrics to use for lifeline text and message text
1029 // using the Graphical Context
1030 Metrics
.setLifelineFontHeight(context
.getFontHeight(SDViewPref
.getInstance().getFont(ISDPreferences
.PREF_LIFELINE
)));
1031 Metrics
.setLifelineFontWidth(context
.getFontWidth(SDViewPref
.getInstance().getFont(ISDPreferences
.PREF_LIFELINE
)));
1032 Metrics
.setLifelineWidth(SDViewPref
.getInstance().getLifelineWidth());
1033 Metrics
.setFrameFontHeight(context
.getFontHeight(SDViewPref
.getInstance().getFont(ISDPreferences
.PREF_FRAME_NAME
)));
1034 Metrics
.setLifelineHeaderFontHeight(context
.getFontHeight(SDViewPref
.getInstance().getFont(ISDPreferences
.PREF_LIFELINE_HEADER
)));
1036 int syncMessFontH
= context
.getFontHeight(SDViewPref
.getInstance().getFont(ISDPreferences
.PREF_SYNC_MESS
));
1037 int syncMessRetFontH
= context
.getFontHeight(SDViewPref
.getInstance().getFont(ISDPreferences
.PREF_SYNC_MESS_RET
));
1038 int asyncMessFontH
= context
.getFontHeight(SDViewPref
.getInstance().getFont(ISDPreferences
.PREF_ASYNC_MESS
));
1039 int asyncMessRetFontH
= context
.getFontHeight(SDViewPref
.getInstance().getFont(ISDPreferences
.PREF_ASYNC_MESS_RET
));
1041 int messageFontHeight
= 0;
1042 if (syncMessFontH
> syncMessRetFontH
) {
1043 messageFontHeight
= syncMessFontH
;
1045 messageFontHeight
= syncMessRetFontH
;
1047 if (messageFontHeight
< asyncMessFontH
) {
1048 messageFontHeight
= asyncMessFontH
;
1050 if (messageFontHeight
< asyncMessRetFontH
) {
1051 messageFontHeight
= asyncMessRetFontH
;
1053 Metrics
.setMessageFontHeight(messageFontHeight
);
1054 context
.setFont(SDViewPref
.getInstance().getFont(ISDPreferences
.PREF_LIFELINE
));
1056 int width
= Math
.round((fFrame
.getWidth() + 2 * Metrics
.FRAME_H_MARGIN
) * fZoomValue
);
1057 int height
= Math
.round((fFrame
.getHeight() + 2 * Metrics
.FRAME_V_MARGIN
) * fZoomValue
);
1058 if (width
< area
.width
) {
1061 if (height
< area
.height
) {
1062 height
= area
.height
;
1064 resizeContents(width
, height
);
1066 context
.setBackground(SDViewPref
.getInstance().getBackGroundColor(ISDPreferences
.PREF_FRAME
));
1067 context
.fillRectangle(0, 0, getContentsWidth(), Metrics
.FRAME_V_MARGIN
);
1068 context
.fillRectangle(0, 0, fFrame
.getX(), getContentsHeight());
1069 context
.fillRectangle(fFrame
.getX() + fFrame
.getWidth() + 1, 0, getContentsWidth() - (fFrame
.getX() + fFrame
.getWidth() + 1), getContentsHeight());
1070 context
.fillRectangle(0, fFrame
.getY() + fFrame
.getHeight() + 1, getContentsWidth(), getContentsHeight() - (fFrame
.getY() + fFrame
.getHeight() + 1));
1071 gcim
.setLineWidth(1);
1073 fPrinter
.startPage();
1074 fZoomValue
= lastZoom
;
1076 int restoreX
= getContentsX();
1077 int restoreY
= getContentsY();
1079 float zh
= sdPrintDialog
.getStepY() * sdPrintDialog
.getZoomFactor();
1080 float zw
= sdPrintDialog
.getStepX() * sdPrintDialog
.getZoomFactor();
1082 float zoomValueH
= fPrinter
.getClientArea().height
/ zh
;
1083 float zoomValueW
= fPrinter
.getClientArea().width
/ zw
;
1084 if (zoomValueH
> zoomValueW
) {
1085 fPrinterZoom
= zoomValueH
;
1087 fPrinterZoom
= zoomValueW
;
1090 if (sdPrintDialog
.printSelection()) {
1091 int[] pagesList
= sdPrintDialog
.getPageList();
1093 for (int pageIndex
= 0; pageIndex
< pagesList
.length
; pageIndex
++) {
1094 printPage(pagesList
[pageIndex
], sdPrintDialog
, context
);
1096 } else if (sdPrintDialog
.printAll()) {
1097 for (int pageIndex
= 1; pageIndex
<= sdPrintDialog
.maxNumOfPages(); pageIndex
++) {
1098 printPage(pageIndex
, sdPrintDialog
, context
);
1100 } else if (sdPrintDialog
.printCurrent()) {
1101 printPage(getContentsX(), getContentsY(), sdPrintDialog
, context
, 1);
1102 } else if (sdPrintDialog
.printRange()) {
1103 for (int pageIndex
= sdPrintDialog
.getFrom(); pageIndex
<= sdPrintDialog
.maxNumOfPages() && pageIndex
<= sdPrintDialog
.getTo(); pageIndex
++) {
1104 printPage(pageIndex
, sdPrintDialog
, context
);
1109 fIsPrinting
= false;
1114 fZoomValue
= lastZoom
;
1116 setContentsPos(restoreX
, restoreY
);
1122 public void print() {
1123 SDPrintDialog sdPrinter
= new SDPrintDialog(this.getShell(), this);
1125 if (sdPrinter
.open() != 0) {
1128 } catch (Exception e
) {
1129 Activator
.getDefault().logError("Error creating image", e
); //$NON-NLS-1$
1132 printUI(sdPrinter
.getDialogUI());
1136 * Method to print a page.
1138 * @param pageNum The page number
1139 * @param pd The sequence diagram print dialog
1140 * @param context The graphical context
1142 public void printPage(int pageNum
, SDPrintDialogUI pd
, NGC context
) {
1143 int j
= pageNum
/ pd
.getNbRow();
1144 int i
= pageNum
% pd
.getNbRow();
1154 i
= (int) (i
* pd
.getStepX());
1155 j
= (int) (j
* pd
.getStepY());
1157 printPage(i
, j
, pd
, context
, pageNum
);
1163 * Method to print page ranges.
1170 * The sequence diagram print dialog
1172 * The graphical context
1176 public void printPage(int i
, int j
, SDPrintDialogUI pd
, NGC context
, int pageNum
) {
1177 fIsPrinting
= false;
1178 int pageNumFontZoom
= fPrinter
.getClientArea().height
/ getVisibleHeight();
1181 setContentsPos(i
, j
);
1184 float lastZoom
= fZoomValue
;
1185 fZoomValue
= fPrinterZoom
* lastZoom
;
1187 fFrame
.draw(context
);
1189 fZoomValue
= pageNumFontZoom
;
1190 context
.setFont(SDViewPref
.getInstance().getFont(ISDPreferences
.PREF_LIFELINE
));
1191 String currentPageNum
= String
.valueOf(pageNum
);
1192 int ii
= context
.textExtent(currentPageNum
);
1193 int jj
= context
.getCurrentFontHeight();
1194 fZoomValue
= fPrinterZoom
* lastZoom
;
1195 context
.drawText(currentPageNum
, Math
.round(fPrinterX
+ getVisibleWidth() / fPrinterZoom
- ii
/ fPrinterZoom
), Math
.round(fPrinterY
+ getVisibleHeight() / fPrinterZoom
- jj
/ fPrinterZoom
), false);
1196 fIsPrinting
= false;
1197 fZoomValue
= lastZoom
;
1201 * Sets the collapse provider.
1203 * @param provider The collapse provider to set
1205 protected void setCollapseProvider(ISDCollapseProvider provider
) {
1206 fCollapseProvider
= provider
;
1211 * Checks for focus of children.
1213 * @param children Control to check
1214 * @return true if child is on focus else false
1216 protected boolean checkFocusOnChilds(Control children
) {
1217 if (children
instanceof Composite
) {
1218 Control
[] child
= ((Composite
) children
).getChildren();
1219 for (int i
= 0; i
< child
.length
; i
++) {
1220 if (child
[i
].isFocusControl()) {
1223 checkFocusOnChilds(child
[i
]);
1230 * A post action for a tooltip (before displaying).
1232 * @param accessible true if accessible else false
1233 * @return the tooltip text.
1235 protected String
getPostfixForTooltip(boolean accessible
) {
1236 StringBuffer postfix
= new StringBuffer();
1237 // Determine if the tooltip must show the time difference between the current mouse position and
1238 // the last selected graphNode
1239 if ((fCurrentGraphNode
!= null) &&
1240 (fCurrentGraphNode
instanceof ITimeRange
) &&
1241 (fToolTipNode
instanceof ITimeRange
) &&
1242 (fCurrentGraphNode
!= fToolTipNode
) &&
1243 ((ITimeRange
) fToolTipNode
).hasTimeInfo() &&
1244 ((ITimeRange
) fCurrentGraphNode
).hasTimeInfo()) {
1245 postfix
.append(" -> "); //$NON-NLS-1$
1246 postfix
.append(fCurrentGraphNode
.getName());
1247 postfix
.append("\n"); //$NON-NLS-1$
1248 postfix
.append(Messages
.SequenceDiagram_Delta
);
1249 postfix
.append(" "); //$NON-NLS-1$
1251 //double delta = ((ITimeRange)toolTipNode).getLastTime()-((ITimeRange)currentGraphNode).getLastTime();
1252 ITmfTimestamp firstTime
= ((ITimeRange
) fCurrentGraphNode
).getEndTime();
1253 ITmfTimestamp lastTime
= ((ITimeRange
) fToolTipNode
).getEndTime();
1254 ITmfTimestamp delta
= lastTime
.getDelta(firstTime
);
1255 postfix
.append(delta
.toString());
1258 if ((fToolTipNode
instanceof ITimeRange
) && ((ITimeRange
) fToolTipNode
).hasTimeInfo()) {
1259 postfix
.append("\n"); //$NON-NLS-1$
1260 ITmfTimestamp firstTime
= ((ITimeRange
) fToolTipNode
).getStartTime();
1261 ITmfTimestamp lastTime
= ((ITimeRange
) fToolTipNode
).getEndTime();
1263 if (firstTime
!= null) {
1264 if (lastTime
!= null && firstTime
.compareTo(lastTime
, true) != 0) {
1265 postfix
.append("start: "); //$NON-NLS-1$
1266 postfix
.append(firstTime
.toString());
1267 postfix
.append("\n"); //$NON-NLS-1$
1268 postfix
.append("end: "); //$NON-NLS-1$
1269 postfix
.append(lastTime
.toString());
1270 postfix
.append("\n"); //$NON-NLS-1$
1272 postfix
.append(firstTime
.toString());
1275 else if (lastTime
!= null) {
1276 postfix
.append(lastTime
.toString());
1280 return postfix
.toString();
1284 * Sets a new focused widget.
1286 * @param newFocusShape A new focus shape.
1288 protected void setFocus(int newFocusShape
) {
1289 fFocusedWidget
= newFocusShape
;
1290 if (fFocusedWidget
== -1) {
1291 getViewControl().getAccessible().setFocus(ACC
.CHILDID_SELF
);
1293 getViewControl().getAccessible().setFocus(fFocusedWidget
);
1298 * Highlight the given GraphNode<br>
1299 * The GraphNode is then displayed using the system default selection color
1301 * @param node the GraphNode to highlight
1303 protected void performSelection(GraphNode node
) {
1304 if ((fCtrlSelection
) || (fShiftSelection
)) {
1306 if (fSelectedNodeList
.contains(node
)) {
1307 removeSelection(node
);
1323 * Returns a draw buffer image.
1325 * @return a Image containing the draw buffer.
1327 protected Image
getDrawBuffer() {
1330 Rectangle area
= getClientArea();
1331 Image dbuffer
= new Image(getDisplay(), area
.width
, area
.height
);
1332 GC gcim
= new GC(dbuffer
);
1333 NGC context
= new NGC(this, gcim
);
1335 // Set the metrics to use for lifeline text and message text
1336 // using the Graphical Context
1337 Metrics
.setLifelineFontHeight(context
.getFontHeight(SDViewPref
.getInstance().getFont(ISDPreferences
.PREF_LIFELINE
)));
1338 Metrics
.setLifelineFontWidth(context
.getFontWidth(SDViewPref
.getInstance().getFont(ISDPreferences
.PREF_LIFELINE
)));
1339 Metrics
.setLifelineWidth(SDViewPref
.getInstance().getLifelineWidth());
1340 Metrics
.setFrameFontHeight(context
.getFontHeight(SDViewPref
.getInstance().getFont(ISDPreferences
.PREF_FRAME_NAME
)));
1341 Metrics
.setLifelineHeaderFontHeight(context
.getFontHeight(SDViewPref
.getInstance().getFont(ISDPreferences
.PREF_LIFELINE_HEADER
)));
1343 int syncMessFontH
= context
.getFontHeight(SDViewPref
.getInstance().getFont(ISDPreferences
.PREF_SYNC_MESS
));
1344 int syncMessRetFontH
= context
.getFontHeight(SDViewPref
.getInstance().getFont(ISDPreferences
.PREF_SYNC_MESS_RET
));
1345 int asyncMessFontH
= context
.getFontHeight(SDViewPref
.getInstance().getFont(ISDPreferences
.PREF_ASYNC_MESS
));
1346 int asyncMessRetFontH
= context
.getFontHeight(SDViewPref
.getInstance().getFont(ISDPreferences
.PREF_ASYNC_MESS_RET
));
1348 int messageFontHeight
= 0;
1349 if (syncMessFontH
> syncMessRetFontH
) {
1350 messageFontHeight
= syncMessFontH
;
1352 messageFontHeight
= syncMessRetFontH
;
1354 if (messageFontHeight
< asyncMessFontH
) {
1355 messageFontHeight
= asyncMessFontH
;
1357 if (messageFontHeight
< asyncMessRetFontH
) {
1358 messageFontHeight
= asyncMessRetFontH
;
1360 Metrics
.setMessageFontHeight(messageFontHeight
);
1361 context
.setFont(SDViewPref
.getInstance().getFont(ISDPreferences
.PREF_LIFELINE
));
1363 int width
= (int) ((fFrame
.getWidth() + 2 * Metrics
.FRAME_H_MARGIN
) * fZoomValue
);
1364 int height
= (int) ((fFrame
.getHeight() + 2 * Metrics
.FRAME_V_MARGIN
) * fZoomValue
);
1366 resizeContents(width
, height
);
1368 context
.setBackground(SDViewPref
.getInstance().getBackGroundColor(ISDPreferences
.PREF_FRAME
));
1369 context
.fillRectangle(0, 0, getContentsWidth(), Metrics
.FRAME_V_MARGIN
);
1370 context
.fillRectangle(0, 0, fFrame
.getX(), getContentsHeight());
1371 context
.fillRectangle(fFrame
.getX() + fFrame
.getWidth() + 1, 0, getContentsWidth() - (fFrame
.getX() + fFrame
.getWidth() + 1), getContentsHeight());
1372 context
.fillRectangle(0, fFrame
.getY() + fFrame
.getHeight() + 1, getContentsWidth(), getContentsHeight() - (fFrame
.getY() + fFrame
.getHeight() + 1));
1373 gcim
.setLineWidth(1);
1375 fFrame
.draw(context
);
1376 if (fDragAndDrop
!= null) {
1377 Lifeline node
= fDragAndDrop
;
1378 boolean isSelected
= fDragAndDrop
.isSelected();
1379 boolean hasFocus
= fDragAndDrop
.hasFocus();
1380 node
.setSelected(false);
1381 node
.setFocused(false);
1382 node
.draw(context
, fDragX
, fDragY
);
1383 node
.setSelected(isSelected
);
1384 node
.setFocused(hasFocus
);
1392 protected void keyPressedEvent(KeyEvent event
) {
1393 if (!(isFocusControl() || getViewControl().isFocusControl())) {
1394 Control
[] child
= getParent().getChildren();
1395 for (int i
= 0; i
< child
.length
; i
++) {
1396 if ((child
[i
].isFocusControl())&& (!(child
[i
] instanceof ScrollView
))) {
1397 getViewControl().setFocus();
1404 if (event
.keyCode
== SWT
.CTRL
) {
1405 fCtrlSelection
= true;
1407 if (event
.keyCode
== SWT
.SHIFT
) {
1408 fShiftSelection
= true;
1409 fPrevList
= new ArrayList
<>();
1410 fPrevList
.addAll(getSelection());
1413 GraphNode prevNode
= getFocusNode();
1415 if (event
.keyCode
== SWT
.ARROW_RIGHT
) {
1419 if (event
.keyCode
== SWT
.ARROW_LEFT
) {
1423 if (event
.keyCode
== SWT
.ARROW_DOWN
) {
1427 if (event
.keyCode
== SWT
.ARROW_UP
) {
1431 if (event
.keyCode
== SWT
.HOME
) {
1435 if (event
.keyCode
== SWT
.END
) {
1439 if ((!fShiftSelection
) && (!fCtrlSelection
)) {
1440 fListStart
= fCurrentGraphNode
;
1443 if (event
.character
== ' ') {
1444 performSelection(fCurrentGraphNode
);
1445 if (!fShiftSelection
) {
1446 fListStart
= fCurrentGraphNode
;
1450 if ((fShiftSelection
) && (prevNode
!= getFocusNode())) {
1452 addSelection(fPrevList
);
1453 addSelection(fFrame
.getNodeList(fListStart
, getFocusNode()));
1454 if (getFocusNode() instanceof Lifeline
) {
1455 ensureVisible(getFocusNode().getX(), getFocusNode().getY(), getFocusNode().getWidth(), getFocusNode().getHeight(), SWT
.CENTER
| SWT
.VERTICAL
, true);
1457 ensureVisible(getFocusNode());
1459 } else if ((!fCtrlSelection
) && (!fShiftSelection
)) {
1462 if (getFocusNode() != null) {
1463 addSelection(getFocusNode());
1465 if (getFocusNode() instanceof Lifeline
) {
1466 ensureVisible(getFocusNode().getX(), getFocusNode().getY(), getFocusNode().getWidth(), getFocusNode().getHeight(), SWT
.CENTER
| SWT
.VERTICAL
, true);
1468 ensureVisible(getFocusNode());
1473 if (fCurrentGraphNode
!= null) {
1474 fCurrentGraphNode
.setFocused(true);
1478 if ((event
.character
== ' ') && ((fZoomInMode
) || (fZoomOutMode
))) {
1479 int cx
= Math
.round((getContentsX() + getVisibleWidth() / 2) / fZoomValue
);
1480 int cy
= Math
.round((getContentsY() + getVisibleHeight() / 2) / fZoomValue
);
1482 if (fZoomValue
< 64) {
1483 fZoomValue
= fZoomValue
* (float) 1.25;
1486 fZoomValue
= fZoomValue
/ (float) 1.25;
1488 int x
= Math
.round(cx
* fZoomValue
- getVisibleWidth() / (float) 2);
1489 int y
= Math
.round(cy
* fZoomValue
- getVisibleHeight() / (float) 2);
1490 setContentsPos(x
, y
);
1491 if (fTimeBar
!= null) {
1492 fTimeBar
.setZoom(fZoomValue
);
1494 // redraw also resize the scrollView content
1500 protected void keyReleasedEvent(KeyEvent event
) {
1502 if (event
.keyCode
== SWT
.CTRL
) {
1503 fCtrlSelection
= false;
1505 if (event
.keyCode
== SWT
.SHIFT
) {
1506 fShiftSelection
= false;
1508 super.keyReleasedEvent(event
);
1513 public boolean isFocusControl() {
1514 Control
[] child
= getChildren();
1515 for (int i
= 0; i
< child
.length
; i
++) {
1516 if (child
[i
].isFocusControl()) {
1519 checkFocusOnChilds(child
[i
]);
1525 public boolean setContentsPos(int x
, int y
) {
1535 if (fFrame
== null) {
1538 if (localX
+ getVisibleWidth() > getContentsWidth()) {
1539 localX
= getContentsWidth() - getVisibleWidth();
1541 if (localY
+ getVisibleHeight() > getContentsHeight()) {
1542 localY
= getContentsHeight() - getVisibleHeight();
1544 int x1
= Math
.round(localX
/ fZoomValue
);
1545 int y2
= Math
.round(localY
/ fZoomValue
);
1546 int width
= Math
.round(getVisibleWidth() / fZoomValue
);
1547 int height
= Math
.round(getVisibleHeight() / fZoomValue
);
1548 fFrame
.updateIndex(x1
, y2
, width
, height
);
1550 if (fInsertionCartet
!= null && fInsertionCartet
.isVisible()) {
1551 fInsertionCartet
.setVisible(false);
1554 return super.setContentsPos(localX
, localY
);
1558 protected void contentsMouseHover(MouseEvent event
) {
1559 GraphNode graphNode
= null;
1560 if (fFrame
!= null) {
1561 int x
= Math
.round(event
.x
/ fZoomValue
);
1562 int y
= Math
.round(event
.y
/ fZoomValue
);
1563 graphNode
= fFrame
.getNodeAt(x
, y
);
1564 if ((graphNode
!= null) && (SDViewPref
.getInstance().tooltipEnabled())) {
1565 fToolTipNode
= graphNode
;
1566 String postfix
= getPostfixForTooltip(true);
1567 if (graphNode
instanceof Lifeline
) {
1568 Lifeline lifeline
= (Lifeline
) graphNode
;
1569 fToolTip
.showToolTip(lifeline
.getToolTipText() + postfix
);
1572 fToolTip
.showToolTip(graphNode
.getName() + postfix
);
1576 fToolTip
.hideToolTip();
1582 protected void contentsMouseMoveEvent(MouseEvent e
) {
1583 fScrollToolTip
.hideToolTip();
1584 fToolTip
.hideToolTip();
1585 if (!(isFocusControl() || getViewControl().isFocusControl())) {
1586 Control
[] child
= getParent().getChildren();
1587 for (int i
= 0; i
< child
.length
; i
++) {
1588 if ((child
[i
].isFocusControl()) && (!(child
[i
] instanceof ScrollView
))) {
1589 getViewControl().setFocus();
1596 if (((e
.stateMask
& SWT
.BUTTON_MASK
) != 0) && ((fDragAndDrop
!= null) || fIsDragAndDrop
) && (fReorderMode
|| fCollapseProvider
!= null)) {
1597 fIsDragAndDrop
= false;
1598 if (fCurrentGraphNode
instanceof Lifeline
) {
1599 fDragAndDrop
= (Lifeline
) fCurrentGraphNode
;
1601 if (fDragAndDrop
!= null) {
1604 if (e
.x
> getContentsX() + getVisibleWidth()) {
1605 dx
= e
.x
- (getContentsX() + getVisibleWidth());
1606 } else if (e
.x
< getContentsX()) {
1607 dx
= -getContentsX() + e
.x
;
1609 if (e
.y
> getContentsY() + getVisibleHeight()) {
1610 dy
= e
.y
- (getContentsY() + getVisibleHeight());
1611 } else if (e
.y
< getContentsY()) {
1612 dy
= -getContentsY() + e
.y
;
1616 if (dx
!= 0 || dy
!= 0) {
1617 if (fLocalAutoScroll
== null) {
1618 if (fLocalAutoScrollTimer
== null) {
1619 fLocalAutoScrollTimer
= new Timer(true);
1621 fLocalAutoScroll
= new AutoScroll(this, dx
, dy
);
1622 fLocalAutoScrollTimer
.schedule(fLocalAutoScroll
, 0, 75);
1624 fLocalAutoScroll
.fDeltaX
= dx
;
1625 fLocalAutoScroll
.fDeltaY
= dy
;
1627 } else if (fLocalAutoScroll
!= null) {
1628 fLocalAutoScroll
.cancel();
1629 fLocalAutoScroll
= null;
1631 fDragX
= Math
.round(e
.x
/ fZoomValue
);
1632 fDragY
= Math
.round(e
.y
/ fZoomValue
);
1634 Lifeline node
= fFrame
.getCloserLifeline(fDragX
);
1635 if ((node
!= null) && (node
!= fDragAndDrop
)) {
1638 int height
= Metrics
.getLifelineHeaderFontHeigth() + 2 * Metrics
.LIFELINE_HEARDER_TEXT_V_MARGIN
;
1639 int hMargin
= Metrics
.LIFELINE_VT_MAGIN
/ 4;
1640 int x
= node
.getX();
1641 int width
= node
.getWidth();
1642 if (fFrame
.getVisibleAreaY() < node
.getY() + node
.getHeight() - height
- hMargin
) {
1643 y
= contentsToViewY(Math
.round((node
.getY() + node
.getHeight()) * fZoomValue
));
1645 y
= Math
.round(height
* fZoomValue
);
1648 if (fFrame
.getVisibleAreaY() < contentsToViewY(node
.getY() - hMargin
)) {
1649 y1
= contentsToViewY(Math
.round((node
.getY() - hMargin
) * fZoomValue
));
1651 y1
= Math
.round(height
* fZoomValue
);
1654 int rx
= Math
.round(x
* fZoomValue
);
1656 fInsertionCartet
.setVisible(true);
1657 if ((fInsertionCartet
.getImage() != null) && (!fInsertionCartet
.getImage().isDisposed())) {
1658 fInsertionCartet
.getImage().dispose();
1660 if (rx
<= e
.x
&& Math
.round(rx
+ (width
* fZoomValue
)) >= e
.x
) {
1661 if (fCollapseProvider
!= null) {
1662 ImageData data
= fCollapaseCaretImg
.getImageData();
1663 data
= data
.scaledTo(Math
.round(fCollapaseCaretImg
.getBounds().width
* fZoomValue
), Math
.round(fCollapaseCaretImg
.getBounds().height
* fZoomValue
));
1664 fCurrentCaretImage
= new Image(Display
.getCurrent(), data
);
1665 fInsertionCartet
.setImage(fCurrentCaretImage
);
1666 fInsertionCartet
.setLocation(contentsToViewX(rx
+ Math
.round((width
/ (float) 2) * fZoomValue
)) - fCurrentCaretImage
.getBounds().width
/ 2, y
);
1668 } else if (fReorderMode
) {
1670 if (node
.getIndex() > 1 && fFrame
.getLifeline(node
.getIndex() - 2) == fDragAndDrop
) {
1673 ImageData data
= fArrowUpCaretImg
.getImageData();
1674 data
= data
.scaledTo(Math
.round(fArrowUpCaretImg
.getBounds().width
* fZoomValue
), Math
.round(fArrowUpCaretImg
.getBounds().height
* fZoomValue
));
1675 fCurrentCaretImage
= new Image(Display
.getCurrent(), data
);
1676 fInsertionCartet
.setImage(fCurrentCaretImage
);
1677 fInsertionCartet
.setLocation(contentsToViewX(Math
.round((x
- Metrics
.LIFELINE_SPACING
/ 2) * fZoomValue
)) - fCurrentCaretImage
.getBounds().width
/ 2, y1
);
1679 if (node
.getIndex() < fFrame
.lifeLinesCount() && fFrame
.getLifeline(node
.getIndex()) == fDragAndDrop
) {
1682 ImageData data
= fArrowUpCaretImg
.getImageData();
1683 data
= data
.scaledTo(Math
.round(fArrowUpCaretImg
.getBounds().width
* fZoomValue
), Math
.round(fArrowUpCaretImg
.getBounds().height
* fZoomValue
));
1684 fCurrentCaretImage
= new Image(Display
.getCurrent(), data
);
1685 fInsertionCartet
.setImage(fCurrentCaretImage
);
1686 fInsertionCartet
.setLocation(contentsToViewX(Math
.round((x
+ width
+ Metrics
.LIFELINE_SPACING
/ 2) * fZoomValue
)) - fCurrentCaretImage
.getBounds().width
/ 2 + 1, y1
);
1690 fInsertionCartet
.setVisible(false);
1694 super.contentsMouseMoveEvent(e
);
1699 protected void contentsMouseUpEvent(MouseEvent event
) {
1700 // Just in case the diagram highlight a time compression region
1701 // this region need to be released when clicking everywhere
1702 fInsertionCartet
.setVisible(false);
1703 if (fDragAndDrop
!= null) {
1704 if ((fOverView
!= null) && (!fOverView
.isDisposed())) {
1705 fOverView
.dispose();
1708 Lifeline node
= fFrame
.getCloserLifeline(fDragX
);
1710 int rx
= Math
.round(node
.getX() * fZoomValue
);
1711 if (rx
<= event
.x
&& Math
.round(rx
+ (node
.getWidth() * fZoomValue
)) >= event
.x
) {
1712 if ((fCollapseProvider
!= null) && (fDragAndDrop
!= node
)) {
1713 fCollapseProvider
.collapseTwoLifelines(fDragAndDrop
, node
);
1715 } else if (rx
< event
.x
) {
1716 fFrame
.insertLifelineAfter(fDragAndDrop
, node
);
1717 if (node
.getIndex() < fFrame
.lifeLinesCount()) {
1718 Lifeline temp
[] = { fDragAndDrop
, fFrame
.getLifeline(node
.getIndex()) };
1719 fReorderList
.add(temp
);
1721 Lifeline temp
[] = { fDragAndDrop
, null };
1722 fReorderList
.add(temp
);
1725 fFrame
.insertLifelineBefore(fDragAndDrop
, node
);
1726 Lifeline temp
[] = { fDragAndDrop
, node
};
1727 fReorderList
.add(temp
);
1731 fDragAndDrop
= null;
1733 if (fFrame
== null) {
1736 fFrame
.resetTimeCompression();
1738 // reset auto scroll if it's engaged
1739 if (fLocalAutoScroll
!= null) {
1740 fLocalAutoScroll
.cancel();
1741 fLocalAutoScroll
= null;
1743 super.contentsMouseUpEvent(event
);
1747 protected void contentsMouseDownEvent(MouseEvent event
) {
1748 if (fCurrentGraphNode
!= null) {
1749 fCurrentGraphNode
.setFocused(false);
1752 // Just in case the diagram highlight a time compression region
1753 // this region need to be released when clicking everywhere
1754 if (fFrame
== null) {
1758 fFrame
.resetTimeCompression();
1760 if ((event
.stateMask
& SWT
.CTRL
) != 0) {
1761 fCtrlSelection
= true;
1763 fCtrlSelection
= false;
1766 if (((fZoomInMode
) || (fZoomOutMode
)) && (event
.button
== 1)) {
1767 int cx
= Math
.round(event
.x
/ fZoomValue
);
1768 int cy
= Math
.round(event
.y
/ fZoomValue
);
1770 if (fZoomValue
< 64) {
1771 fZoomValue
= fZoomValue
* (float) 1.25;
1774 fZoomValue
= fZoomValue
/ (float) 1.25;
1776 int x
= Math
.round(cx
* fZoomValue
- getVisibleWidth() / (float) 2);
1777 int y
= Math
.round(cy
* fZoomValue
- getVisibleHeight() / (float) 2);
1778 setContentsPos(x
, y
);
1779 if (fTimeBar
!= null) {
1780 fTimeBar
.setZoom(fZoomValue
);
1782 // redraw also resize the scrollView content
1785 GraphNode node
= null;
1786 int x
= Math
.round(event
.x
/ fZoomValue
);
1787 int y
= Math
.round(event
.y
/ fZoomValue
);
1788 node
= fFrame
.getNodeAt(x
, y
);
1790 if ((event
.button
== 1) || ((node
!= null) && !node
.isSelected())) {
1791 if (!fShiftSelection
) {
1794 if (fShiftSelection
) {
1796 addSelection(fFrame
.getNodeList(fListStart
, node
));
1798 performSelection(node
);
1800 fCurrentGraphNode
= node
;
1802 node
.setFocused(true);
1807 if (fDragAndDrop
== null) {
1808 super.contentsMouseDownEvent(event
);
1810 fIsDragAndDrop
= (event
.button
== 1);
1815 * TimerTask for auto scroll feature.
1817 protected static class AutoScroll
extends TimerTask
{
1827 * Field sequence diagram reference.
1829 public SDWidget fSdWidget
;
1832 * Constructor for AutoScroll.
1833 * @param sv sequence diagram widget reference
1837 public AutoScroll(SDWidget sv
, int dx
, int dy
) {
1845 Display display
= Display
.getDefault();
1846 if ((display
== null) || (display
.isDisposed())) {
1849 display
.asyncExec(new Runnable() {
1852 if (fSdWidget
.isDisposed()) {
1855 fSdWidget
.fDragX
+= fDeltaX
;
1856 fSdWidget
.fDragY
+= fDeltaY
;
1857 fSdWidget
.scrollBy(fDeltaX
, fDeltaY
);
1864 protected void drawContents(GC gc
, int clipx
, int clipy
, int clipw
, int cliph
) {
1865 if (fFrame
== null) {
1866 gc
.setBackground(getDisplay().getSystemColor(SWT
.COLOR_WHITE
));
1867 gc
.fillRectangle(0, 0, getVisibleWidth(), getVisibleHeight());
1871 SDViewPref
.getInstance();
1873 Rectangle area
= getClientArea();
1874 Image dbuffer
= getDrawBuffer();
1875 int height
= Math
.round((fFrame
.getHeight() + 2 * Metrics
.FRAME_V_MARGIN
) * fZoomValue
);
1878 gc
.drawImage(dbuffer
, 0, 0, area
.width
, area
.height
, 0, 0, area
.width
, area
.height
);
1879 } catch (Exception e
) {
1880 Activator
.getDefault().logError("Error drawin content", e
); //$NON-NLS-1$
1883 setHScrollBarIncrement(Math
.round(SDViewPref
.getInstance().getLifelineWidth() / (float) 2 * fZoomValue
));
1884 setVScrollBarIncrement(Math
.round(Metrics
.getMessagesSpacing() * fZoomValue
));
1885 if ((fTimeBar
!= null) && (fFrame
.hasTimeInfo())) {
1886 fTimeBar
.resizeContents(9, height
+ getHorizontalBarHeight());
1887 fTimeBar
.setContentsPos(getContentsX(), getContentsY());
1891 float xRatio
= getContentsWidth() / (float) getVisibleWidth();
1892 float yRatio
= getContentsHeight() / (float) getVisibleHeight();
1893 if (yRatio
> xRatio
) {
1894 setOverviewSize((int) (getVisibleHeight() * 0.75));
1896 setOverviewSize((int) (getVisibleWidth() * 0.75));
1901 public void widgetDefaultSelected(SelectionEvent event
) {
1905 public void widgetSelected(SelectionEvent event
) {
1906 if (event
.widget
== fZoomIn
) {
1907 fZoomValue
= fZoomValue
* 2;
1908 } else if (event
.widget
== fZoomOut
) {
1909 fZoomValue
= fZoomValue
/ 2;
1915 * Called when property changed occurs in the preference page. "PREFOK" is
1916 * fired when the user press the ok or apply button
1919 public void propertyChange(PropertyChangeEvent e
) {
1920 if (fFrame
!= null && !isDisposed()) {
1921 fFrame
.resetTimeCompression();
1923 if (e
.getProperty().equals("PREFOK")) //$NON-NLS-1$
1925 // Prepare the overview to be reused for the new
1926 // settings (especially the colors)
1927 if (fOverView
!= null) {
1928 fOverView
.dispose();
1936 public void widgetDisposed(DisposeEvent e
) {
1937 if (fOverView
!= null) {
1938 fOverView
.dispose();
1940 super.removeDisposeListener(this);
1941 if ((fCurrentCaretImage
!= null) && (!fCurrentCaretImage
.isDisposed())) {
1942 fCurrentCaretImage
.dispose();
1944 if ((fArrowUpCaretImg
!= null) && (!fArrowUpCaretImg
.isDisposed())) {
1945 fArrowUpCaretImg
.dispose();
1947 if ((fCollapaseCaretImg
!= null) && (!fCollapaseCaretImg
.isDisposed())) {
1948 fCollapaseCaretImg
.dispose();
1950 SDViewPref
.getInstance().removePropertyChangeListener(this);
1951 LoadersManager lm
= LoadersManager
.getInstance();
1952 if (fSite
instanceof SDView
) {
1953 ((SDView
) fSite
).resetProviders();
1955 lm
.resetLoader(((SDView
) fSite
).getViewSite().getId());
1961 protected void drawOverview(GC gc
, Rectangle r
) {
1962 float oldzoom
= fZoomValue
;
1963 if (getContentsWidth() > getContentsHeight()) {
1964 fZoomValue
= (float) r
.width
/ (float) getContentsWidth() * oldzoom
;
1966 fZoomValue
= (float) r
.height
/ (float) getContentsHeight() * oldzoom
;
1968 if ((fOverView
!= null) && ((r
.width
!= fOverView
.getBounds().width
) || (r
.height
!= fOverView
.getBounds().height
))) {
1969 fOverView
.dispose();
1972 if (fOverView
== null) {
1973 int backX
= getContentsX();
1974 int backY
= getContentsY();
1975 setContentsPos(0, 0);
1976 fOverView
= new Image(getDisplay(), r
.width
, r
.height
);
1977 GC gcim
= new GC(fOverView
);
1978 NGC context
= new NGC(this, gcim
);
1979 context
.setBackground(SDViewPref
.getInstance().getBackGroundColor(ISDPreferences
.PREF_FRAME
));
1980 fFrame
.draw(context
);
1981 setContentsPos(backX
, backY
);
1985 if ((fOverView
!= null) && (r
.width
== fOverView
.getBounds().width
) && (r
.height
== fOverView
.getBounds().height
)) {
1986 gc
.drawImage(fOverView
, 0, 0, r
.width
, r
.height
, 0, 0, r
.width
, r
.height
);
1989 fZoomValue
= oldzoom
;
1991 super.drawOverview(gc
, r
);
1995 public void deltaSelected(Lifeline lifeline
, int startEvent
, int nbEvent
, IColor color
) {
1996 fFrame
.highlightTimeCompression(lifeline
, startEvent
, nbEvent
, color
);
1997 ensureVisible(lifeline
);
1998 int y1
= lifeline
.getY() + lifeline
.getHeight() + (Metrics
.getMessageFontHeigth() + Metrics
.getMessagesSpacing()) * startEvent
;
1999 int y2
= lifeline
.getY() + lifeline
.getHeight() + (Metrics
.getMessageFontHeigth() + Metrics
.getMessagesSpacing()) * (startEvent
+ nbEvent
);
2000 ensureVisible(lifeline
.getX(), y1
- (Metrics
.getLifelineHeaderFontHeigth() + +2 * Metrics
.LIFELINE_HEARDER_TEXT_V_MARGIN
), lifeline
.getWidth(), y2
- y1
+ 3, SWT
.CENTER
| SWT
.VERTICAL
, true);
2006 public int getVisibleWidth() {
2008 return fPrinter
.getClientArea().width
;
2010 return super.getVisibleWidth();
2014 public int getVisibleHeight() {
2016 return fPrinter
.getClientArea().height
;
2018 return super.getVisibleHeight();
2022 public int contentsToViewX(int x
) {
2024 int v
= Math
.round(fPrinterX
* fPrinterZoom
);
2027 return x
- getContentsX();
2031 public int contentsToViewY(int y
) {
2033 int v
= Math
.round(fPrinterY
* fPrinterZoom
);
2036 return y
- getContentsY();
2040 public int getContentsX() {
2042 return Math
.round(fPrinterX
* fPrinterZoom
);
2044 return super.getContentsX();
2048 public int getContentsY() {
2050 return Math
.round(fPrinterY
* fPrinterZoom
);
2052 return super.getContentsY();
2056 * Traverse Listener implementation.
2058 protected static class LocalTraverseListener
implements TraverseListener
{
2060 public void keyTraversed(TraverseEvent e
) {
2061 if ((e
.detail
== SWT
.TRAVERSE_TAB_NEXT
) || (e
.detail
== SWT
.TRAVERSE_TAB_PREVIOUS
)) {