/*******************************************************************************
* Copyright (c) 2011, 2012 Anton Gorenkov
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Anton Gorenkov - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.testsrunner.internal.ui.view;
import org.eclipse.cdt.testsrunner.internal.TestsRunnerPlugin;
import org.eclipse.cdt.testsrunner.internal.model.TestingSessionsManager;
import org.eclipse.cdt.testsrunner.internal.ui.view.actions.HistoryDropDownAction;
import org.eclipse.cdt.testsrunner.internal.ui.view.actions.RerunAction;
import org.eclipse.cdt.testsrunner.internal.ui.view.actions.ScrollLockAction;
import org.eclipse.cdt.testsrunner.internal.ui.view.actions.ShowFailedOnlyAction;
import org.eclipse.cdt.testsrunner.internal.ui.view.actions.ShowFileNameOnlyAction;
import org.eclipse.cdt.testsrunner.internal.ui.view.actions.ShowNextFailureAction;
import org.eclipse.cdt.testsrunner.internal.ui.view.actions.ShowPreviousFailureAction;
import org.eclipse.cdt.testsrunner.internal.ui.view.actions.ShowTestsInHierarchyAction;
import org.eclipse.cdt.testsrunner.internal.ui.view.actions.ShowTimeAction;
import org.eclipse.cdt.testsrunner.internal.ui.view.actions.StopAction;
import org.eclipse.cdt.testsrunner.internal.ui.view.actions.ToggleOrientationAction;
import org.eclipse.cdt.testsrunner.model.ITestingSession;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.swt.dnd.Clipboard;
import org.eclipse.swt.events.ControlEvent;
import org.eclipse.swt.events.ControlListener;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.IActionBars;
import org.eclipse.ui.IMemento;
import org.eclipse.ui.IViewSite;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.actions.ActionFactory;
import org.eclipse.ui.part.ViewPart;
/**
* Represents a view part showing the testing results (count statistics,
* red/green bar, tests hierarchy and test messages).
*/
public class ResultsView extends ViewPart {
/**
* Represents view orientation
*
* @note <code>Auto</code> state may be not acceptable for some methods (see
* their comments for details).
*/
public enum Orientation {
Horizontal,
Vertical,
Auto,
}
/** View parent. */
private Composite parent;
/** Child widget: statistics viewer. */
private ProgressCountPanel progressCountPanel;
/** Tests hierarchy and message viewer. */
private ResultsPanel resultsPanel;
/** User interface updater instance. */
private UIUpdater uiUpdater;
/** The reference to the testing sessions manager instance. */
private TestingSessionsManager sessionsManager;
/** Shows whether the results view was disposed. */
private boolean isDisposed = false;
// Toolbar & view menu actions
private Action nextAction;
private Action previousAction;
private Action rerunAction;
private Action stopAction;
private ToggleOrientationAction[] toggleOrientationActions;
private Action historyAction;
private Action showFailedOnly;
private Action showTestsInHierarchyAction;
private Action showTimeAction;
private Action scrollLockAction;
private Action showFileNameOnlyAction;
/**
* The current orientation preference (Horizontal, Vertical, Auto).
*/
private Orientation orientation = Orientation.Auto;
/**
* The current view orientation (Horizontal or Vertical).
*/
private Orientation currentOrientation;
/**
* Previously saved state. It is used to store the same state if the view
* was not opened.
*/
private IMemento memento;
// Persistence tags
static final String TAG_ORIENTATION = "orientation"; //$NON-NLS-1$
static final String TAG_SHOW_FAILED_ONLY = "showFailedOnly"; //$NON-NLS-1$
static final String TAG_SHOW_TESTS_IN_HIERARCHY = "showTestsInHierarchy"; //$NON-NLS-1$
static final String TAG_SHOW_TIME = "showTime"; //$NON-NLS-1$
static final String TAG_SCROLL_LOCK = "scrollLock"; //$NON-NLS-1$
static final String TAG_SHOW_FILE_NAME_ONLY_ACTION = "showFileNameOnly"; //$NON-NLS-1$
static final String TAG_HISTORY_SIZE = "history_size"; //$NON-NLS-1$
@Override
public void createPartControl(Composite parent) {
sessionsManager = TestsRunnerPlugin.getDefault().getTestingSessionsManager();
IWorkbench workbench = TestsRunnerPlugin.getDefault().getWorkbench();
Clipboard clipboard = new Clipboard(parent.getDisplay());
this.parent = parent;
GridLayout gridLayout = new GridLayout();
gridLayout.marginWidth = 0;
gridLayout.marginHeight = 0;
parent.setLayout(gridLayout);
currentOrientation = getActualOrientation();
progressCountPanel = new ProgressCountPanel(parent, currentOrientation);
resultsPanel = new ResultsPanel(parent, sessionsManager, workbench, getViewSite(), clipboard);
uiUpdater = new UIUpdater(this, resultsPanel.getTestsHierarchyViewer(), progressCountPanel, sessionsManager);
configureActionsBars();
parent.addControlListener(new ControlListener() {
@Override
public void controlMoved(ControlEvent e) {
}
@Override
public void controlResized(ControlEvent e) {
computeOrientation();
}
});
restoreState(memento);
uiUpdater.reapplyActiveSession();
}
@Override
public void setFocus() {
resultsPanel.getTestsHierarchyViewer().getTreeViewer().getControl().setFocus();
}
/**
* Configures the view tool bar and menu.
*/
private void configureActionsBars() {
IActionBars actionBars = getViewSite().getActionBars();
// Create common action
toggleOrientationActions = new ToggleOrientationAction[] {
new ToggleOrientationAction(this, Orientation.Vertical),
new ToggleOrientationAction(this, Orientation.Horizontal),
new ToggleOrientationAction(this, Orientation.Auto),
};
nextAction = new ShowNextFailureAction(resultsPanel.getTestsHierarchyViewer());
nextAction.setEnabled(false);
actionBars.setGlobalActionHandler(ActionFactory.NEXT.getId(), nextAction);
previousAction = new ShowPreviousFailureAction(resultsPanel.getTestsHierarchyViewer());
previousAction.setEnabled(false);
actionBars.setGlobalActionHandler(ActionFactory.PREVIOUS.getId(), previousAction);
showFailedOnly = new ShowFailedOnlyAction(resultsPanel);
showTestsInHierarchyAction = new ShowTestsInHierarchyAction(resultsPanel.getTestsHierarchyViewer());
showTimeAction = new ShowTimeAction(resultsPanel.getTestsHierarchyViewer());
scrollLockAction = new ScrollLockAction(uiUpdater);
showFileNameOnlyAction = new ShowFileNameOnlyAction(resultsPanel.getMessagesViewer());
rerunAction = new RerunAction(sessionsManager);
rerunAction.setEnabled(false);
stopAction = new StopAction(sessionsManager);
stopAction.setEnabled(false);
historyAction = new HistoryDropDownAction(sessionsManager, parent.getShell());
// Configure toolbar
IToolBarManager toolBar = actionBars.getToolBarManager();
toolBar.add(nextAction);
toolBar.add(previousAction);
toolBar.add(showFailedOnly);
toolBar.add(scrollLockAction);
toolBar.add(new Separator());
toolBar.add(rerunAction);
toolBar.add(stopAction);
toolBar.add(historyAction);
// Configure view menu
IMenuManager viewMenu = actionBars.getMenuManager();
viewMenu.add(showTestsInHierarchyAction);
viewMenu.add(showTimeAction);
viewMenu.add(new Separator());
MenuManager layoutSubMenu = new MenuManager(UIViewMessages.ResultsView_layout_menu_text);
for (int i = 0; i < toggleOrientationActions.length; ++i) {
layoutSubMenu.add(toggleOrientationActions[i]);
}
viewMenu.add(layoutSubMenu);
viewMenu.add(new Separator());
viewMenu.add(showFailedOnly);
viewMenu.add(showFileNameOnlyAction);
}
@Override
public void dispose() {
isDisposed = true;
if (uiUpdater != null) {
uiUpdater.dispose();
}
}
/**
* Changes the view orientation
*
* @param orientation new view orientation (Horizontal, Vertical, Auto)
*/
public void setOrientation(Orientation orientation) {
this.orientation = orientation;
computeOrientation();
}
/**
* Checks whether actual orientation is changed and changes orientation of
* the child widgets.
*/
private void computeOrientation() {
Orientation newActualOrientation = getActualOrientation();
if (newActualOrientation != currentOrientation) {
currentOrientation = newActualOrientation;
progressCountPanel.setPanelOrientation(currentOrientation);
resultsPanel.setPanelOrientation(currentOrientation);
for (int i = 0; i < toggleOrientationActions.length; ++i) {
toggleOrientationActions[i].setChecked(orientation == toggleOrientationActions[i].getOrientation());
}
parent.layout();
}
}
/**
* Recalculates actual view orientation depending on the specified by user
* orientation value and current view size.
*
* @param orientation by user specified orientation
* @return actual orientation
*/
private Orientation getActualOrientation() {
switch (orientation) {
case Horizontal:
case Vertical:
return orientation;
case Auto:
Point size = parent.getSize();
return (size.x > size.y) ? Orientation.Horizontal : Orientation.Vertical;
}
return null;
}
/**
* Updates view actions state from the active session.
*/
public void updateActionsFromSession() {
ITestingSession session = sessionsManager.getActiveSession();
boolean hasErrors = session != null && session.hasErrors();
previousAction.setEnabled(hasErrors);
nextAction.setEnabled(hasErrors);
rerunAction.setEnabled(session != null && session.isFinished());
stopAction.setEnabled(session != null && !session.isFinished());
}
/**
* Changes the view caption.
*
* @param message new view caption
*/
public void setCaption(String message) {
setContentDescription(message);
}
@Override
public void init(IViewSite site, IMemento memento) throws PartInitException {
super.init(site, memento);
this.memento = memento;
}
/**
* Restores the value of the checkable action.
*
* @param memento previously saved state to restore the action value from
* @param key tag name that is used to restore the value
* @param action action to restore
*/
private void restoreActionChecked(IMemento memento, String key, Action action) {
Boolean checked = memento.getBoolean(key);
if (checked != null) {
action.setChecked(checked);
action.run();
}
}
/**
* Restores the state of the view.
*
* @param memento previously saved state
*/
private void restoreState(IMemento memento) {
if (memento != null) {
Integer orientationIndex = memento.getInteger(TAG_ORIENTATION);
if (orientationIndex != null) {
setOrientation(Orientation.values()[orientationIndex]);
}
resultsPanel.restoreState(memento);
restoreActionChecked(memento, TAG_SHOW_FAILED_ONLY, showFailedOnly);
restoreActionChecked(memento, TAG_SHOW_TESTS_IN_HIERARCHY, showTestsInHierarchyAction);
restoreActionChecked(memento, TAG_SHOW_TIME, showTimeAction);
restoreActionChecked(memento, TAG_SCROLL_LOCK, scrollLockAction);
restoreActionChecked(memento, TAG_SHOW_FILE_NAME_ONLY_ACTION, showFileNameOnlyAction);
Integer historySize = memento.getInteger(TAG_HISTORY_SIZE);
if (historySize != null) {
sessionsManager.setHistorySizeLimit(historySize);
}
}
}
@Override
public void saveState(IMemento memento) {
//Keep the old state;
if (parent == null) {
if (this.memento != null) {
memento.putMemento(this.memento);
}
return;
}
memento.putInteger(TAG_ORIENTATION, orientation.ordinal());
resultsPanel.saveState(memento);
memento.putBoolean(TAG_SHOW_FAILED_ONLY, showFailedOnly.isChecked());
memento.putBoolean(TAG_SHOW_TESTS_IN_HIERARCHY, showTestsInHierarchyAction.isChecked());
memento.putBoolean(TAG_SHOW_TIME, showTimeAction.isChecked());
memento.putBoolean(TAG_SCROLL_LOCK, scrollLockAction.isChecked());
memento.putBoolean(TAG_SHOW_FILE_NAME_ONLY_ACTION, showFileNameOnlyAction.isChecked());
memento.putInteger(TAG_HISTORY_SIZE, sessionsManager.getHistorySizeLimit());
}
/**
* Returns whether the view was disposed.
*
* @return true if the view was disposed
*/
public boolean isDisposed() {
return isDisposed;
}
}