1 /******************************************************************************* 2 * Copyright (c) 2000, 2018 IBM Corporation and others. 3 * 4 * This program and the accompanying materials 5 * are made available under the terms of the Eclipse Public License 2.0 6 * which accompanies this distribution, and is available at 7 * https://www.eclipse.org/legal/epl-2.0/ 8 * 9 * SPDX-License-Identifier: EPL-2.0 10 * 11 * Contributors: 12 * IBM Corporation - initial API and implementation 13 *******************************************************************************/ 14 package org.eclipse.team.internal.ccvs.ui; 15 16 import java.lang.reflect.InvocationTargetException; 17 import java.util.ArrayList; 18 import java.util.List; 19 20 import org.eclipse.core.resources.IProject; 21 import org.eclipse.core.runtime.IAdaptable; 22 import org.eclipse.core.runtime.IProgressMonitor; 23 import org.eclipse.jface.dialogs.*; 24 import org.eclipse.jface.dialogs.Dialog; 25 import org.eclipse.jface.util.PropertyChangeEvent; 26 import org.eclipse.jface.viewers.IStructuredSelection; 27 import org.eclipse.jface.viewers.TableViewer; 28 import org.eclipse.osgi.util.NLS; 29 import org.eclipse.swt.SWT; 30 import org.eclipse.swt.events.SelectionAdapter; 31 import org.eclipse.swt.events.SelectionEvent; 32 import org.eclipse.swt.layout.GridData; 33 import org.eclipse.swt.layout.GridLayout; 34 import org.eclipse.swt.widgets.*; 35 import org.eclipse.team.core.RepositoryProvider; 36 import org.eclipse.team.core.TeamException; 37 import org.eclipse.team.internal.ccvs.core.*; 38 import org.eclipse.team.internal.ccvs.core.resources.CVSWorkspaceRoot; 39 import org.eclipse.team.internal.ccvs.core.syncinfo.FolderSyncInfo; 40 import org.eclipse.team.internal.ccvs.ui.repo.RepositoryComparator; 41 import org.eclipse.ui.PlatformUI; 42 import org.eclipse.ui.model.WorkbenchContentProvider; 43 import org.eclipse.ui.model.WorkbenchLabelProvider; 44 45 public class CVSProjectPropertiesPage extends CVSPropertiesPage { 46 IProject project; 47 ICVSRepositoryLocation oldLocation; 48 ICVSRepositoryLocation newLocation = null; 49 50 private static final int TABLE_HEIGHT_HINT = 150; 51 52 // Widgets 53 Text methodText; 54 Text userText; 55 Text hostText; 56 Text pathText; 57 Text moduleText; 58 Text portText; 59 Text tagText; 60 private Button fetchButton; 61 private Button watchEditButton; 62 63 IUserInfo info; 64 CVSTeamProvider provider; 65 private boolean fetch; 66 private boolean watchEdit; 67 isCompatible(ICVSRepositoryLocation location, ICVSRepositoryLocation oldLocation)68 public static boolean isCompatible(ICVSRepositoryLocation location, 69 ICVSRepositoryLocation oldLocation) { 70 return CVSRepositoryLocationMatcher.isCompatible(location, oldLocation, 71 false); 72 } 73 74 private class RepositorySelectionDialog extends Dialog { 75 ICVSRepositoryLocation[] allLocations; 76 ICVSRepositoryLocation[] compatibleLocations; 77 ICVSRepositoryLocation selectedLocation; 78 79 TableViewer viewer; 80 Button okButton; 81 boolean showCompatible = true; 82 RepositorySelectionDialog(Shell shell, ICVSRepositoryLocation oldLocation)83 public RepositorySelectionDialog(Shell shell, ICVSRepositoryLocation oldLocation) { 84 super(shell); 85 initialize(oldLocation); 86 } initialize(ICVSRepositoryLocation oldLocation)87 private void initialize(ICVSRepositoryLocation oldLocation) { 88 allLocations = CVSUIPlugin.getPlugin().getRepositoryManager().getKnownRepositoryLocations(); 89 List locations = new ArrayList(); 90 for (ICVSRepositoryLocation location : allLocations) { 91 if (isCompatible(location, oldLocation)) { 92 locations.add(location); 93 } 94 } 95 compatibleLocations = (ICVSRepositoryLocation[]) locations.toArray(new ICVSRepositoryLocation[locations.size()]); 96 } 97 @Override createButtonsForButtonBar(Composite parent)98 protected void createButtonsForButtonBar(Composite parent) { 99 // create OK and Cancel buttons by default 100 okButton = createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL, true); 101 okButton.setEnabled(false); 102 createButton(parent, IDialogConstants.CANCEL_ID, IDialogConstants.CANCEL_LABEL, false); 103 } 104 @Override createDialogArea(Composite parent)105 protected Control createDialogArea(Composite parent) { 106 parent.getShell().setText(CVSUIMessages.CVSProjectPropertiesPage_Select_a_Repository_1); 107 Composite composite = (Composite) super.createDialogArea(parent); 108 109 createLabel(composite, CVSUIMessages.CVSProjectPropertiesPage_Select_a_CVS_repository_location_to_share_the_project_with__2, 1); 110 Table table = new Table(composite, SWT.SINGLE | SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL); 111 GridData data = new GridData(GridData.FILL_HORIZONTAL); 112 data.heightHint = TABLE_HEIGHT_HINT; 113 table.setLayoutData(data); 114 viewer = new TableViewer(table); 115 viewer.setLabelProvider(new WorkbenchLabelProvider()); 116 viewer.setComparator(new RepositoryComparator()); 117 viewer.setContentProvider(new WorkbenchContentProvider() { 118 @Override 119 public Object[] getElements(Object inputElement) { 120 if (showCompatible) { 121 return compatibleLocations; 122 } else { 123 return allLocations; 124 } 125 } 126 }); 127 viewer.addSelectionChangedListener(event -> { 128 IStructuredSelection selection = event.getStructuredSelection(); 129 if (selection.isEmpty()) { 130 selectedLocation = null; 131 okButton.setEnabled(false); 132 } else { 133 selectedLocation = (ICVSRepositoryLocation)selection.getFirstElement(); 134 okButton.setEnabled(true); 135 } 136 }); 137 viewer.addDoubleClickListener(event -> okPressed()); 138 viewer.setInput(compatibleLocations); 139 140 final Button compatibleButton = createCheckBox(composite, CVSUIMessages.CVSProjectPropertiesPage_31); 141 compatibleButton.setSelection(showCompatible); 142 compatibleButton.addSelectionListener(new SelectionAdapter() { 143 @Override 144 public void widgetSelected(SelectionEvent e) { 145 showCompatible = compatibleButton.getSelection(); 146 viewer.refresh(); 147 } 148 }); 149 150 Dialog.applyDialogFont(parent); 151 152 return composite; 153 } 154 @Override cancelPressed()155 protected void cancelPressed() { 156 selectedLocation = null; 157 super.cancelPressed(); 158 } getLocation()159 public ICVSRepositoryLocation getLocation() { 160 return selectedLocation; 161 } 162 } 163 164 @Override createContents(Composite parent)165 protected Control createContents(Composite parent) { 166 initialize(); 167 168 Composite composite = new Composite(parent, SWT.NULL); 169 composite.setLayoutData(new GridData(GridData.FILL_BOTH)); 170 GridLayout layout = new GridLayout(); 171 layout.numColumns = 2; 172 composite.setLayout(layout); 173 174 Label label = createLabel(composite, CVSUIMessages.CVSProjectPropertiesPage_connectionType, 1); 175 methodText= createReadOnlyText(composite, ""); //$NON-NLS-1$ 176 177 label = createLabel(composite, CVSUIMessages.CVSProjectPropertiesPage_user, 1); 178 userText= createReadOnlyText(composite, ""); //$NON-NLS-1$ 179 180 label = createLabel(composite, CVSUIMessages.CVSRepositoryLocationPropertySource_host, 1); 181 hostText= createReadOnlyText(composite, ""); //$NON-NLS-1$ 182 183 label = createLabel(composite, CVSUIMessages.CVSPropertiesPage_port, 1); 184 portText= createReadOnlyText(composite, ""); //$NON-NLS-1$ 185 186 label = createLabel(composite, CVSUIMessages.CVSRepositoryLocationPropertySource_root, 1); 187 pathText= createReadOnlyText(composite, ""); //$NON-NLS-1$ 188 189 label = createLabel(composite, CVSUIMessages.CVSPropertiesPage_module, 1); 190 moduleText= createReadOnlyText(composite, ""); //$NON-NLS-1$ 191 192 label = createLabel(composite, CVSUIMessages.CVSPropertiesPage_tag, 1); 193 tagText= createReadOnlyText(composite, ""); //$NON-NLS-1$ 194 195 createLabel(composite, "", 1); //$NON-NLS-1$ 196 197 // Should absent directories be fetched on update 198 fetchButton = createCheckBox(composite, CVSUIMessages.CVSProjectPropertiesPage_fetchAbsentDirectoriesOnUpdate); 199 fetchButton.addListener(SWT.Selection, event -> fetch = fetchButton.getSelection()); 200 201 // Should the project be configured for watch/edit 202 watchEditButton = createCheckBox(composite, CVSUIMessages.CVSProjectPropertiesPage_configureForWatchEdit); 203 watchEditButton.addListener(SWT.Selection, event -> watchEdit = watchEditButton.getSelection()); 204 205 createLabel(composite, "", 1); //$NON-NLS-1$ 206 createLabel(composite, "", 1); //$NON-NLS-1$ 207 createLabel(composite, "", 1); //$NON-NLS-1$ 208 createLabel(composite, "", 1); //$NON-NLS-1$ 209 210 label = new Label(composite, SWT.WRAP); 211 label.setText(CVSUIMessages.CVSProjectPropertiesPage_You_can_change_the_sharing_of_this_project_to_another_repository_location__However__this_is_only_possible_if_the_new_location_is___compatible____on_the_same_host_with_the_same_repository_path___1); 212 GridData data = new GridData(GridData.FILL_HORIZONTAL); 213 data.widthHint = 200; 214 data.horizontalSpan = 2; 215 label.setLayoutData(data); 216 217 Button changeButton = new Button(composite, SWT.PUSH); 218 changeButton.setText(CVSUIMessages.CVSProjectPropertiesPage_Change_Sharing_5); 219 changeButton.addListener(SWT.Selection, e -> { 220 RepositorySelectionDialog dialog = new RepositorySelectionDialog(getShell(), oldLocation); 221 dialog.open(); 222 ICVSRepositoryLocation location = dialog.getLocation(); 223 if (location == null) return; 224 newLocation = location; 225 initializeValues(newLocation); 226 }); 227 228 initializeValues(oldLocation); 229 PlatformUI.getWorkbench().getHelpSystem().setHelp(getControl(), IHelpContextIds.PROJECT_PROPERTY_PAGE); 230 Dialog.applyDialogFont(parent); 231 return composite; 232 } 233 /** 234 * Utility method that creates a label instance 235 * and sets the default layout data. 236 * 237 * @param parent the parent for the new label 238 * @param text the text for the new label 239 * @return the new label 240 */ 241 @Override createLabel(Composite parent, String text, int span)242 protected Label createLabel(Composite parent, String text, int span) { 243 Label label = new Label(parent, SWT.LEFT); 244 label.setText(text); 245 GridData data = new GridData(); 246 data.horizontalSpan = span; 247 data.horizontalAlignment = GridData.FILL; 248 label.setLayoutData(data); 249 return label; 250 } 251 252 /** 253 * Creates a new checkbox instance and sets the default layout data. 254 * 255 * @param group the composite in which to create the checkbox 256 * @param label the string to set into the checkbox 257 * @return the new checkbox 258 */ createCheckBox(Composite group, String label)259 protected Button createCheckBox(Composite group, String label) { 260 Button button = new Button(group, SWT.CHECK | SWT.LEFT); 261 button.setText(label); 262 GridData data = new GridData(); 263 data.horizontalSpan = 2; 264 button.setLayoutData(data); 265 return button; 266 } 267 /** 268 * Initializes the page 269 */ initialize()270 private void initialize() { 271 // Get the project that is the source of this property page 272 project = null; 273 IAdaptable element = getElement(); 274 if (element instanceof IProject) { 275 project = (IProject)element; 276 } else { 277 Object adapter = element.getAdapter(IProject.class); 278 if (adapter instanceof IProject) { 279 project = (IProject)adapter; 280 } 281 } 282 // Do some pre-checks to ensure we're in a good state 283 provider = (CVSTeamProvider)RepositoryProvider.getProvider(project, CVSProviderPlugin.getTypeId()); 284 if (provider == null) return; 285 CVSWorkspaceRoot cvsRoot = provider.getCVSWorkspaceRoot(); 286 try { 287 oldLocation = cvsRoot.getRemoteLocation(); 288 fetch = provider.getFetchAbsentDirectories(); 289 watchEdit = provider.isWatchEditEnabled(); 290 } catch (TeamException e) { 291 handle(e); 292 } 293 } 294 /** 295 * Set the initial values of the widgets 296 */ initializeValues(ICVSRepositoryLocation location)297 private void initializeValues(ICVSRepositoryLocation location) { 298 if (provider == null) return; 299 CVSWorkspaceRoot cvsRoot = provider.getCVSWorkspaceRoot(); 300 ICVSFolder folder = cvsRoot.getLocalRoot(); 301 302 try { 303 if (!folder.isCVSFolder()) return; 304 methodText.setText(location.getMethod().getName()); 305 info = location.getUserInfo(true); 306 userText.setText(info.getUsername()); 307 hostText.setText(location.getHost()); 308 int port = location.getPort(); 309 if (port == ICVSRepositoryLocation.USE_DEFAULT_PORT) { 310 portText.setText(CVSUIMessages.CVSPropertiesPage_defaultPort); 311 } else { 312 portText.setText("" + port); //$NON-NLS-1$ 313 } 314 pathText.setText(location.getRootDirectory()); 315 FolderSyncInfo syncInfo = folder.getFolderSyncInfo(); 316 if (syncInfo == null) return; 317 String label = syncInfo.getRepository(); 318 if (label.equals(FolderSyncInfo.VIRTUAL_DIRECTORY)) { 319 label = NLS.bind(CVSUIMessages.CVSPropertiesPage_virtualModule, new String[] { label }); 320 } 321 moduleText.setText(label); 322 fetchButton.setSelection(fetch); 323 watchEditButton.setSelection(watchEdit); 324 } catch (TeamException e) { 325 handle(e); 326 } 327 328 initializeTag(); 329 } 330 initializeTag()331 private void initializeTag() { 332 provider = (CVSTeamProvider)RepositoryProvider.getProvider(project, CVSProviderPlugin.getTypeId()); 333 if (provider == null) return; 334 try { 335 ICVSFolder local = CVSWorkspaceRoot.getCVSFolderFor(project); 336 CVSTag tag = local.getFolderSyncInfo().getTag(); 337 338 tagText.setText(getTagLabel(tag)); 339 340 } catch (TeamException e) { 341 handle(e); 342 } 343 } 344 @Override performOk()345 public boolean performOk() { 346 final boolean[] changeReadOnly = { false }; 347 try { 348 if (fetch != provider.getFetchAbsentDirectories()) 349 provider.setFetchAbsentDirectories(fetch); 350 if (watchEdit != provider.isWatchEditEnabled()) { 351 provider.setWatchEditEnabled(watchEdit); 352 changeReadOnly[0] = true; 353 } 354 } catch (CVSException e) { 355 handle(e); 356 } 357 if (newLocation == null && !changeReadOnly[0]) { 358 return true; 359 } 360 try { 361 if (newLocation != null && !isCompatible(newLocation, oldLocation)) { 362 if (!MessageDialog.openQuestion(getShell(), CVSUIMessages.CVSProjectPropertiesPage_32, CVSUIMessages.CVSProjectPropertiesPage_33)) { // 363 return false; 364 } 365 } 366 new ProgressMonitorDialog(getShell()).run(true, true, monitor -> { 367 try { 368 monitor.beginTask(CVSUIMessages.CVSProjectPropertiesPage_progressTaskName, 369 ((newLocation == null)?0:100) + (changeReadOnly[0]?100:0)); 370 if (newLocation != null) 371 provider.setRemoteRoot(newLocation, Policy.subMonitorFor(monitor, 100)); 372 if (changeReadOnly[0]) 373 setReadOnly(watchEdit, Policy.infiniteSubMonitorFor(monitor, 100)); 374 } catch (TeamException e) { 375 throw new InvocationTargetException(e); 376 } 377 }); 378 newLocation = null; 379 if (changeReadOnly[0]) { 380 CVSUIPlugin.broadcastPropertyChange(new PropertyChangeEvent(this, CVSUIPlugin.P_DECORATORS_CHANGED, null, null)); 381 } 382 } catch (InvocationTargetException e) { 383 handle(e); 384 } catch (InterruptedException e) { 385 return false; 386 } 387 388 return true; 389 } 390 /** 391 * @param watchEdit 392 */ setReadOnly(final boolean watchEdit, final IProgressMonitor monitor)393 protected void setReadOnly(final boolean watchEdit, final IProgressMonitor monitor) throws CVSException { 394 monitor.beginTask(null, 512); 395 String taskName = watchEdit? 396 CVSUIMessages.CVSProjectPropertiesPage_setReadOnly: 397 CVSUIMessages.CVSProjectPropertiesPage_clearReadOnly; 398 monitor.subTask(taskName); 399 ICVSFolder root = CVSWorkspaceRoot.getCVSFolderFor(project); 400 root.accept(new ICVSResourceVisitor() { 401 @Override 402 public void visitFile(ICVSFile file) throws CVSException { 403 // only change managed, unmodified files 404 if (file.isManaged() && !file.isModified(null)) 405 file.setReadOnly(watchEdit); 406 monitor.worked(1); 407 } 408 409 @Override 410 public void visitFolder(ICVSFolder folder) throws CVSException { 411 folder.acceptChildren(this); 412 } 413 }); 414 monitor.done(); 415 } 416 /** 417 * Shows the given errors to the user. 418 */ handle(Throwable t)419 protected void handle(Throwable t) { 420 CVSUIPlugin.openError(getShell(), null, null, t); 421 } 422 } 423 424