/*******************************************************************************
* Copyright (c) 2008-2011 Chair for Applied Software Engineering,
* Technische Universitaet Muenchen.
* 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:
******************************************************************************/
package org.eclipse.emf.emfstore.client.ui.dialogs;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.Platform;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.emfstore.client.model.ProjectSpace;
import org.eclipse.emf.emfstore.client.ui.Activator;
import org.eclipse.emf.emfstore.client.ui.views.changes.TabbedChangesComposite;
import org.eclipse.emf.emfstore.server.model.versioning.ChangePackage;
import org.eclipse.emf.emfstore.server.model.versioning.LogMessage;
import org.eclipse.emf.emfstore.server.model.versioning.operations.AbstractOperation;
import org.eclipse.jface.dialogs.TitleAreaDialog;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.KeyListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
/**
* This class shows a ChangesTreeComposite and a Text control to enter commit message.
*
* @author Hodaie
* @author Shterev
*/
public class CommitDialog extends TitleAreaDialog implements KeyListener {
private Text txtLogMsg;
private String logMsg = "";
private ChangePackage changes;
private EList<String> oldLogMessages;
private ProjectSpace activeProjectSpace;
private HashMap<String, CommitDialogTray> trays;
/**
* Constructor.
*
* @param parentShell shell
* @param changes the {@link ChangePackage} to be displayed
* @param activeProjectSpace ProjectSpace that will be committed
*/
public CommitDialog(Shell parentShell, ChangePackage changes, ProjectSpace activeProjectSpace) {
super(parentShell);
this.setShellStyle(this.getShellStyle() | SWT.RESIZE);
this.changes = changes;
this.activeProjectSpace = activeProjectSpace;
trays = new HashMap<String, CommitDialogTray>();
IConfigurationElement[] config = Platform.getExtensionRegistry().getConfigurationElementsFor(
"org.eclipse.emf.emfstore.client.ui.commitdialog.tray");
for (IConfigurationElement c : config) {
try {
CommitDialogTray tray = (CommitDialogTray) c.createExecutableExtension("class");
String name = c.getAttribute("name");
tray.init(this);
trays.put(name, tray);
} catch (CoreException e) {
}
}
}
/**
* @return the change package
*/
public ChangePackage getChangePackage() {
return changes;
}
/**
* @return the active project space
*/
public ProjectSpace getActiveProjectSpace() {
return activeProjectSpace;
}
/**
* {@inheritDoc}
*/
@Override
protected Control createDialogArea(Composite parent) {
oldLogMessages = activeProjectSpace.getOldLogMessages();
Composite contents = new Composite(parent, SWT.NONE);
contents.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
contents.setLayout(new GridLayout(2, false));
setTitle("Commit your local changes to the server");
setMessage("Don't forget the commit message!");
setTitleImage(Activator.getImageDescriptor("icons/dontForget.png").createImage());
// Log message
Label lblLogMsg = new Label(contents, SWT.NONE);
lblLogMsg.setLayoutData(new GridData(SWT.BEGINNING, SWT.CENTER, false, false, 2, 1));
lblLogMsg.setText("Log message:");
txtLogMsg = new Text(contents, SWT.MULTI | SWT.LEAD | SWT.BORDER);
GridDataFactory.fillDefaults().grab(true, false).span(2, 1).align(SWT.FILL, SWT.TOP).hint(1, 75)
.applyTo(txtLogMsg);
String logMsg = "";
LogMessage logMessage = changes.getLogMessage();
if (logMessage != null && logMessage.getMessage() != null) {
logMsg = logMessage.getMessage();
} else if (oldLogMessages != null && oldLogMessages.size() > 0) {
logMsg = oldLogMessages.get(oldLogMessages.size() - 1);
}
txtLogMsg.setText(logMsg);
txtLogMsg.selectAll();
// to implement a shortcut for submitting the commit
txtLogMsg.addKeyListener(this);
// previous log messages
Label oldLabel = new Label(contents, SWT.NONE);
oldLabel.setText("Previous messages:");
final Combo oldMsg = new Combo(contents, SWT.READ_ONLY);
GridDataFactory.fillDefaults().align(SWT.FILL, SWT.TOP).grab(true, false).applyTo(oldMsg);
ArrayList<String> oldLogMessagesCopy = new ArrayList<String>();
oldLogMessagesCopy.addAll(oldLogMessages);
Collections.reverse(oldLogMessagesCopy);
oldMsg.setItems(oldLogMessagesCopy.toArray(new String[0]));
oldMsg.addSelectionListener(new SelectionListener() {
public void widgetDefaultSelected(SelectionEvent e) {
// nothing to do here
}
public void widgetSelected(SelectionEvent e) {
txtLogMsg.setText(oldMsg.getItem(oldMsg.getSelectionIndex()));
}
});
// ChangesTree
ArrayList<ChangePackage> changePackages = new ArrayList<ChangePackage>();
changePackages.add(changes);
TabbedChangesComposite changesComposite = new TabbedChangesComposite(contents, SWT.BORDER, changePackages,
getActiveProjectSpace().getProject());
changesComposite.setShowRootNodes(false);
changesComposite.setReverseNodes(false);
changesComposite.setInput(changePackages);
GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL).grab(true, true).span(2, 1).applyTo(changesComposite);
return contents;
}
/**
* {@inheritDoc}
*/
@Override
protected void configureShell(Shell newShell) {
super.configureShell(newShell);
newShell.setText("Commit");
Rectangle area = newShell.getShell().getParent().getClientArea();
int width = area.width * 2 / 3;
int height = area.height * 2 / 3;
newShell.setBounds((area.width - width) / 2, (area.height - height) / 2, width, height);
newShell.addDisposeListener(new DisposeListener() {
public void widgetDisposed(DisposeEvent e) {
for (CommitDialogTray tray : trays.values()) {
tray.dispose();
}
}
});
}
/**
* {@inheritDoc}
*/
@Override
protected void okPressed() {
logMsg = txtLogMsg.getText();
// suppress duplicates
if (!oldLogMessages.contains(logMsg)) {
oldLogMessages.add(logMsg);
}
// remove older messages
if (oldLogMessages.size() > 10) {
// the list can only grow one element at a time,
// so only one element should be deleted
oldLogMessages.remove(0);
}
for (CommitDialogTray t : trays.values()) {
t.okPressed();
}
super.okPressed();
}
/**
* @return the log message that has been set by the user.
*/
public String getLogText() {
return logMsg.equals("") ? "<Empty log message>" : logMsg;
}
/**
* handles the pressing of Ctrl+ENTER: OKpressed() is called. {@inheritDoc}
*
* @see org.eclipse.swt.events.KeyListener#keyPressed(org.eclipse.swt.events.KeyEvent)
*/
public void keyPressed(KeyEvent e) {
if (e.keyCode == SWT.CR && (e.stateMask & SWT.MOD1) != 0) {
this.okPressed();
}
}
/**
* does nothing. {@inheritDoc}
*
* @see org.eclipse.swt.events.KeyListener#keyReleased(org.eclipse.swt.events.KeyEvent)
*/
public void keyReleased(KeyEvent e) {
// nothing to do
}
/**
* {@inheritDoc}
*
* @see org.eclipse.jface.dialogs.Dialog#createButtonsForButtonBar(org.eclipse.swt.widgets.Composite)
*/
@Override
protected void createButtonsForButtonBar(Composite parent) {
// final String notifyUsers = "Notify users";
IConfigurationElement[] config = Platform.getExtensionRegistry().getConfigurationElementsFor(
"org.eclipse.emf.emfstore.client.ui.commitdialog.tray");
for (IConfigurationElement c : config) {
final String name = c.getAttribute("name");
final CommitDialogTray tray = trays.get(name);
if (tray != null) {
final Button notificationsButton = createButton(parent, 2138, name + " >>", false);
notificationsButton.addSelectionListener(new SelectionAdapter() {
private boolean isOpen;
@Override
public void widgetSelected(SelectionEvent e) {
if (!isOpen) {
openTray(tray);
notificationsButton.setText(name + " <<");
Rectangle bounds = getShell().getBounds();
bounds.x -= 100;
getShell().setBounds(bounds);
} else {
closeTray();
notificationsButton.setText(name + " >>");
Rectangle bounds = getShell().getBounds();
bounds.x += 100;
getShell().setBounds(bounds);
}
isOpen = !isOpen;
}
});
}
}
super.createButtonsForButtonBar(parent);
}
/**
* @return the operations.
*/
public List<AbstractOperation> getOperations() {
return changes.getOperations();
}
}