/** * This file Copyright (c) 2005-2010 Aptana, Inc. This program is * dual-licensed under both the Aptana Public License and the GNU General * Public license. You may elect to use one or the other of these licenses. * * This program is distributed in the hope that it will be useful, but * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or * NONINFRINGEMENT. Redistribution, except as permitted by whichever of * the GPL or APL you select, is prohibited. * * 1. For the GPL license (GPL), you can redistribute and/or modify this * program under the terms of the GNU General Public License, * Version 3, as published by the Free Software Foundation. You should * have received a copy of the GNU General Public License, Version 3 along * with this program; if not, write to the Free Software Foundation, Inc., 51 * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Aptana provides a special exception to allow redistribution of this file * with certain other free and open source software ("FOSS") code and certain additional terms * pursuant to Section 7 of the GPL. You may view the exception and these * terms on the web at http://www.aptana.com/legal/gpl/. * * 2. For the Aptana Public License (APL), this program and the * accompanying materials are made available under the terms of the APL * v1.0 which accompanies this distribution, and is available at * http://www.aptana.com/legal/apl/. * * You may view the GPL, Aptana's exception and additional terms, and the * APL in the file titled license.html at the root of the corresponding * plugin containing this source file. * * Any modifications to this file must keep this entire header intact. */ package com.aptana.ide.syncing.ui.dialogs; import java.text.MessageFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IAdaptable; import org.eclipse.jface.action.Action; import org.eclipse.jface.action.IMenuManager; import org.eclipse.jface.action.MenuManager; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.dialogs.TitleAreaDialog; import org.eclipse.jface.layout.GridDataFactory; import org.eclipse.jface.layout.GridLayoutFactory; import org.eclipse.jface.viewers.ArrayContentProvider; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.LabelProvider; import org.eclipse.jface.viewers.ListViewer; import org.eclipse.jface.viewers.SelectionChangedEvent; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.jface.viewers.ViewerComparator; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.SashForm; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Group; import org.eclipse.swt.widgets.Shell; import com.aptana.ide.core.CoreStrings; import com.aptana.ide.core.StringUtils; import com.aptana.ide.core.io.IConnectionPoint; import com.aptana.ide.core.ui.CoreUIPlugin; import com.aptana.ide.core.ui.SWTUtils; import com.aptana.ide.syncing.core.DefaultSiteConnection; import com.aptana.ide.syncing.core.ISiteConnection; import com.aptana.ide.syncing.core.SiteConnection; import com.aptana.ide.syncing.core.SyncingPlugin; import com.aptana.ide.syncing.ui.internal.SiteConnectionPropertiesWidget; import com.aptana.ide.syncing.ui.internal.SyncUtils; import com.aptana.ide.ui.UIUtils; /** * @author Max Stepanov * */ public class SiteConnectionsEditorDialog extends TitleAreaDialog implements SiteConnectionPropertiesWidget.Client { private ISiteConnection initialSelection; private ListViewer sitesViewer; private Button addButton; private Button removeButton; private SiteConnectionPropertiesWidget sitePropertiesWidget; private List<ISiteConnection> sites = new ArrayList<ISiteConnection>(); /** * @param parentShell */ public SiteConnectionsEditorDialog(Shell parentShell) { super(parentShell); setShellStyle(getShellStyle() | SWT.RESIZE); setHelpAvailable(false); sites.add(DefaultSiteConnection.getInstance()); sites.addAll(Arrays.asList(SyncingPlugin.getSiteConnectionManager().getSiteConnections())); setSelection(DefaultSiteConnection.getInstance()); } public void setCreateNew(String name, IAdaptable source, IAdaptable destination) { IConnectionPoint sourceConnection = SyncUtils.findOrCreateConnectionPointFor(source); IConnectionPoint destinationConnection = SyncUtils.findOrCreateConnectionPointFor(destination); SiteConnection siteConnection = (SiteConnection) SyncingPlugin.getSiteConnectionManager().createSiteConnection(); siteConnection.setName(createUniqueSiteName(name)); siteConnection.setSource(sourceConnection); siteConnection.setDestination(destinationConnection); sites.add(siteConnection); if (sitesViewer != null) { sitesViewer.refresh(); } setSelection(siteConnection); } protected void configureShell(Shell newShell) { super.configureShell(newShell); newShell.setText(Messages.SiteConnectionsEditorDialog_DialogTitle); } protected Control createDialogArea(Composite parent) { Composite dialogArea = (Composite) super.createDialogArea(parent); setTitle(Messages.SiteConnectionsEditorDialog_Title); setMessage(Messages.SiteConnectionsEditorDialog_Message); Composite container = new Composite(dialogArea, SWT.NONE); container.setLayoutData(GridDataFactory.fillDefaults().grab(true, true).create()); container.setLayout(GridLayoutFactory.swtDefaults() .margins(convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_MARGIN), convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_MARGIN)) .spacing(convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_SPACING), convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_SPACING)) .create()); SashForm sashForm = new SashForm(container, SWT.HORIZONTAL); sashForm.setLayoutData(GridDataFactory.fillDefaults().hint(SWT.DEFAULT, 400).grab(true, true).create()); /* column 1 - the list of connections */ Group group = new Group(sashForm, SWT.NONE); group.setText(Messages.SiteConnectionsEditorDialog_LBL_ConnectionGroup); group.setLayoutData(GridDataFactory.fillDefaults().grab(true, true).create()); group.setLayout(GridLayoutFactory.swtDefaults().numColumns(2).create()); sitesViewer = new ListViewer(group, SWT.SINGLE | SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER); sitesViewer.getControl().setLayoutData(GridDataFactory.fillDefaults().grab(true, true).span(2, 1).create()); sitesViewer.setContentProvider(new ArrayContentProvider()); sitesViewer.setLabelProvider(new SitesLabelProvider()); sitesViewer.setComparator(new SitesSorter()); sitesViewer.setInput(sites); addButton = new Button(group, SWT.PUSH); addButton.setLayoutData(GridDataFactory.swtDefaults().create()); addButton.setImage(SWTUtils.getImage(CoreUIPlugin.getDefault(), "/icons/add.gif")); //$NON-NLS-1$ addButton.setToolTipText(StringUtils.ellipsify(CoreStrings.ADD)); removeButton = new Button(group, SWT.PUSH); removeButton.setLayoutData(GridDataFactory.swtDefaults().create()); removeButton.setImage(SWTUtils.getImage(CoreUIPlugin.getDefault(), "/icons/delete.gif")); //$NON-NLS-1$ removeButton.setToolTipText(CoreStrings.REMOVE); /* column 2 - the details of the selected connection */ Composite composite = new Composite(sashForm, SWT.NONE); composite.setLayout(GridLayoutFactory.fillDefaults().create()); sitePropertiesWidget = new SiteConnectionPropertiesWidget(composite, SWT.NONE, this); sitePropertiesWidget.setLayoutData(GridDataFactory.fillDefaults().grab(true, true).create()); sitePropertiesWidget.setSource(null); sashForm.setWeights(new int[] { 30, 70 }); /* -- */ sitesViewer.addSelectionChangedListener(new ISelectionChangedListener() { public void selectionChanged(SelectionChangedEvent event) { ISiteConnection selection = (ISiteConnection) ((IStructuredSelection) event.getSelection()).getFirstElement(); if (selection != sitePropertiesWidget.getSource()) { if (doSelectionChange()) { sitePropertiesWidget.setSource(selection); } else { sitesViewer.setSelection(new StructuredSelection(sitePropertiesWidget.getSource()), true); } } removeButton.setEnabled(!event.getSelection().isEmpty() && selection != DefaultSiteConnection.getInstance()); } }); MenuManager menuManager = new MenuManager(); createActions(menuManager); sitesViewer.getControl().setMenu(menuManager.createContextMenu(sitesViewer.getControl())); addButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { if (doSelectionChange()) { setCreateNew(Messages.SiteConnectionsEditorDialog_LBL_NewConnection, null, null); } else { sitesViewer.setSelection(new StructuredSelection(sitePropertiesWidget.getSource()), true); } } }); removeButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { if (!sitesViewer.getSelection().isEmpty()) { if (MessageDialog.openConfirm(getShell(), Messages.SiteConnectionsEditorDialog_DeleteConfirm_Title, Messages.SiteConnectionsEditorDialog_DeleteConfirm_Message)) { ISiteConnection selection = (ISiteConnection) ((IStructuredSelection) sitesViewer.getSelection()).getFirstElement(); int newSelectionIndex = sitesViewer.getList().getSelectionIndex() - 1; SyncingPlugin.getSiteConnectionManager().removeSiteConnection(selection); sites.remove(selection); sitePropertiesWidget.setSource(null); sitesViewer.refresh(); if (newSelectionIndex > -1 || newSelectionIndex < sitesViewer.getList().getItemCount()) { setSelection(newSelectionIndex == 0 ? DefaultSiteConnection.getInstance() : sites.get(newSelectionIndex - 1)); } } } } }); return dialogArea; } /* (non-Javadoc) * @see org.eclipse.jface.dialogs.TitleAreaDialog#createContents(org.eclipse.swt.widgets.Composite) */ @Override protected Control createContents(Composite parent) { try { return super.createContents(parent); } finally { if (initialSelection != null) { sitesViewer.setSelection(new StructuredSelection(initialSelection), true); } } } protected void createActions(IMenuManager menuManager) { menuManager.add(new Action(Messages.SiteConnectionsEditorDialog_LBL_Duplicate) { @Override public void run() { ISiteConnection siteConnection = (ISiteConnection) ((IStructuredSelection) sitesViewer.getSelection()).getFirstElement(); if (siteConnection != null && doSelectionChange()) { try { SiteConnection newSite = (SiteConnection) SyncingPlugin.getSiteConnectionManager().cloneSiteConnection(siteConnection); newSite.setName(StringUtils.format("Copy of {0}", siteConnection.getName())); //$NON-NLS-1$ sites.add(newSite); sitesViewer.refresh(); sitesViewer.setSelection(new StructuredSelection(newSite), true); } catch (CoreException e) { UIUtils.showErrorMessage(Messages.SiteConnectionsEditorDialog_ERR_Duplicate, e); } } } }); } protected void createButtonsForButtonBar(Composite parent) { createButton(parent, IDialogConstants.APPLY_ID, IDialogConstants.APPLY_LABEL, false); createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL, false); createButton(parent, IDialogConstants.CANCEL_ID, IDialogConstants.CANCEL_LABEL, false); } protected boolean doSelectionChange() { if (sitePropertiesWidget.isChanged()) { MessageDialog dlg = new MessageDialog(getShell(), Messages.SiteConnectionsEditorDialog_SaveConfirm_Title, null, StringUtils.format(Messages.SiteConnectionsEditorDialog_SaveConfirm_Message, sitePropertiesWidget.getSource().getName()), MessageDialog.QUESTION, new String[] { IDialogConstants.NO_LABEL, IDialogConstants.YES_LABEL, IDialogConstants.CANCEL_LABEL }, 1); switch (dlg.open()) { case 1: if (sitePropertiesWidget.applyChanges()) { break; } case 2: return false; } } return true; } /* (non-Javadoc) * @see org.eclipse.jface.dialogs.TitleAreaDialog#setErrorMessage(java.lang.String) */ @Override public void setErrorMessage(String newErrorMessage) { super.setErrorMessage(newErrorMessage); boolean hasError = (newErrorMessage != null); Button button = getButton(IDialogConstants.APPLY_ID); if (button != null) { button.setEnabled(!hasError); } button = getButton(IDialogConstants.OK_ID); if (button != null) { button.setEnabled(!hasError); } } protected void buttonPressed(int buttonId) { if (buttonId == IDialogConstants.APPLY_ID) { applyPressed(); } super.buttonPressed(buttonId); } protected void okPressed() { if (applyPressed()) { super.okPressed(); } } protected boolean applyPressed() { boolean applied = !sitePropertiesWidget.isChanged() || sitePropertiesWidget.applyChanges(); if (applied) { sitesViewer.refresh(); } ISiteConnection siteConnection = sitePropertiesWidget.getSource(); if (siteConnection != DefaultSiteConnection.getInstance()) { SyncingPlugin.getSiteConnectionManager().addSiteConnection(siteConnection); } SyncingPlugin.getSiteConnectionManager().siteConnectionChanged(siteConnection); return applied; } public void setSelection(ISiteConnection selection) { this.initialSelection = selection; if (sitesViewer != null) { sitesViewer.setSelection(new StructuredSelection(selection), true); } } private static String createUniqueSiteName(String baseName) { Pattern pattern = Pattern.compile("^(.*) (\\d+)$"); //$NON-NLS-1$ Matcher matcher = pattern.matcher(baseName); if (matcher.matches()) { baseName = matcher.group(1); } int lastIndex = Integer.MIN_VALUE; for (ISiteConnection i : SyncingPlugin.getSiteConnectionManager().getSiteConnections()) { String siteName = i.getName(); if (siteName.startsWith(baseName)) { if (siteName.equals(baseName) && lastIndex == Integer.MIN_VALUE) { lastIndex = 1; } matcher = pattern.matcher(siteName); if (matcher.matches()) { try { lastIndex = Math.max(lastIndex, Integer.parseInt(matcher.group(2))); } catch (NumberFormatException e) { } } } } if (lastIndex == Integer.MIN_VALUE) { return baseName; } return MessageFormat.format("{0} {1}", baseName, lastIndex + 1); //$NON-NLS-1$ } private class SitesLabelProvider extends LabelProvider { /* (non-Javadoc) * @see org.eclipse.jface.viewers.LabelProvider#getText(java.lang.Object) */ @Override public String getText(Object element) { if (element instanceof ISiteConnection) { return ((ISiteConnection) element).getName(); } return super.getText(element); } } private class SitesSorter extends ViewerComparator { /* (non-Javadoc) * @see org.eclipse.jface.viewers.ViewerComparator#category(java.lang.Object) */ @Override public int category(Object element) { if (element == DefaultSiteConnection.getInstance()) { return 0; } return 1; } } }