diff options
author | Jean Michel-Lemieux | 2003-09-10 19:24:01 +0000 |
---|---|---|
committer | Jean Michel-Lemieux | 2003-09-10 19:24:01 +0000 |
commit | f86bcedb2d5348338f237c7ba8b0cd77e4eeb8c7 (patch) | |
tree | e461b89842179de336eaa381827400afbfdc1948 /bundles/org.eclipse.team.ui | |
parent | ba7e4312188694331aed1085e3a91433f5467361 (diff) | |
download | eclipse.platform.team-f86bcedb2d5348338f237c7ba8b0cd77e4eeb8c7.tar.gz eclipse.platform.team-f86bcedb2d5348338f237c7ba8b0cd77e4eeb8c7.tar.xz eclipse.platform.team-f86bcedb2d5348338f237c7ba8b0cd77e4eeb8c7.zip |
*** empty log message ***
Diffstat (limited to 'bundles/org.eclipse.team.ui')
14 files changed, 573 insertions, 83 deletions
diff --git a/bundles/org.eclipse.team.ui/icons/full/ovr/confchg_ov.gif b/bundles/org.eclipse.team.ui/icons/full/ovr/confchg_ov.gif Binary files differnew file mode 100644 index 000000000..020fc5438 --- /dev/null +++ b/bundles/org.eclipse.team.ui/icons/full/ovr/confchg_ov.gif diff --git a/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/TeamUIPlugin.java b/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/TeamUIPlugin.java index 9f18abc07..1ff8f2e97 100644 --- a/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/TeamUIPlugin.java +++ b/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/TeamUIPlugin.java @@ -296,6 +296,7 @@ public class TeamUIPlugin extends AbstractUIPlugin implements IPropertyChangeLis // View decoration overlays createImageDescriptor(ISharedImages.IMG_DIRTY_OVR, baseURL); + createImageDescriptor(ISharedImages.IMG_CONFLICT_OVR, baseURL); createImageDescriptor(ISharedImages.IMG_CHECKEDIN_OVR, baseURL); createImageDescriptor(ISharedImages.IMG_CHECKEDOUT_OVR, baseURL); createImageDescriptor(ISharedImages.IMG_SYNC_VIEW, baseURL); diff --git a/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/messages.properties b/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/messages.properties index 5018560c6..a5ac03c51 100644 --- a/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/messages.properties +++ b/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/messages.properties @@ -96,11 +96,9 @@ SyncView.errorSaving=Error while saving modified resources SyncView.cantSaveError=Can't save changes: {0} SyncView.dirtyIndicatorInTitle=*{0} +LiveSyncView.titleTooltip=Working Set: {0} LiveSyncView.title=Synchronize -LiveSyncView.titleTooltip={0}\nWorking Set: {1}\n -LiveSyncView.titleChangeNumbers=mode matched {0} of {1} changes: {2} hidden by working set -LiveSyncView.titleChangeNumbersNoWorkingSet=mode matched {0} of {1} changes -LiveSyncView.titleWithSubscriber={0} ({1}) - {2} +LiveSyncView.titleSubscriber=Synchronize - {0} SubscriberEventHandler.jobName=Updating synchronization state SubscriberEventHandler.errors=Errors have occured while calculating the synchronization state. The Synchronize View may be out-of-date. Refresh the view or fix the errors and re-run the Synchronize command. @@ -403,6 +401,12 @@ SynchronizeView.12=One item selected SynchronizeView.13=\ items selected SynchronizeView.14=Error opening perspective SynchronizeView.16=Error opening view + +StatisticsPanel.outgoing=Outgoing +StatisticsPanel.incoming=Incoming +StatisticsPanel.conflicting=Conflicting +StatisticsPanel.changeNumbers={0}/{1} + SyncViewerPreferencePage.6=Synchronize view preferences SyncViewerPreferencePage.7=Team Synchronize View settings: SyncViewerPreferencePage.8=Display diff --git a/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/sync/sets/SyncInfoStatistics.java b/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/sync/sets/SyncInfoStatistics.java index 2b9e16ce4..5e08f13ea 100644 --- a/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/sync/sets/SyncInfoStatistics.java +++ b/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/sync/sets/SyncInfoStatistics.java @@ -76,8 +76,8 @@ public class SyncInfoStatistics { long count = 0; while (it.hasNext()) { Integer key = (Integer) it.next(); - if((key.intValue() & mask) != 0) { - count += ((Integer)stats.get(key)).intValue(); + if((key.intValue() & mask) == kind) { + count += ((Long)stats.get(key)).intValue(); } } return count; diff --git a/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/sync/sets/SyncSet.java b/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/sync/sets/SyncSet.java index 11a62161c..9dc897185 100644 --- a/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/sync/sets/SyncSet.java +++ b/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/sync/sets/SyncSet.java @@ -106,7 +106,11 @@ public class SyncSet { private void internalAddSyncInfo(SyncInfo info) { IResource local = info.getLocal(); IPath path = local.getFullPath(); - if(resources.put(path, info) == null) { + SyncInfo oldSyncInfo = (SyncInfo)resources.put(path, info); + if(oldSyncInfo == null) { + statistics.add(info); + } else { + statistics.remove(oldSyncInfo); statistics.add(info); } } diff --git a/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/sync/views/StatisticsCounterBar.java b/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/sync/views/StatisticsCounterBar.java new file mode 100644 index 000000000..ca42c58b2 --- /dev/null +++ b/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/sync/views/StatisticsCounterBar.java @@ -0,0 +1,240 @@ +/******************************************************************************* + * Copyright (c) 2000, 2003 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.team.internal.ui.sync.views; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.ControlAdapter; +import org.eclipse.swt.events.ControlEvent; +import org.eclipse.swt.events.MouseAdapter; +import org.eclipse.swt.events.MouseEvent; +import org.eclipse.swt.events.MouseMoveListener; +import org.eclipse.swt.events.PaintEvent; +import org.eclipse.swt.events.PaintListener; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.Cursor; +import org.eclipse.swt.graphics.GC; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.graphics.Rectangle; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.widgets.Canvas; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.team.core.subscribers.SyncInfo; + +/** + * A progress bar with a red/green indication for success or failure. + */ +public class StatisticsCounterBar extends Canvas { + private static final int DEFAULT_WIDTH = 160; + private static final int DEFAULT_HEIGHT = 20; + + private int outgoingCount = 0; + private int incomingCount = 0; + private int conflicCount = 0; + + private int totalCount = 0; + + private int fColorBarWidth = 0; + + private Color outgoingColor; + private Color incomingColor; + private Color conflictColor; + + private int activeMode = SyncInfo.IN_SYNC; + + private final Cursor counterBarCursor = new Cursor(getDisplay(), SWT.CURSOR_HAND); + + public StatisticsCounterBar(Composite parent, int cSpan) { + super(parent, SWT.NONE); + + addControlListener(new ControlAdapter() { + public void controlResized(ControlEvent e) { + redraw(); + } + }); + addPaintListener(new PaintListener() { + public void paintControl(PaintEvent e) { + paint(e); + } + }); + + addMouseMoveListener( + new MouseMoveListener() { + private Cursor fLastCursor; + public void mouseMove(MouseEvent e) { + Cursor cursor= null; + int mode = handlemouseInCounterBar(e.x, e.y); + if (mode != SyncInfo.IN_SYNC) + cursor= counterBarCursor; + if (fLastCursor != cursor) { + setCursor(cursor); + fLastCursor= cursor; + } + } + } + ); + + addMouseListener( + new MouseAdapter() { + public void mouseDown(MouseEvent e) { + int mode = handlemouseInCounterBar(e.x, e.y); + if(mode != activeMode) { + activeMode = mode; + redraw(); + } + } + } + ); + + Display display= parent.getDisplay(); + conflictColor = new Color(display, 204, 51, 51); + incomingColor = new Color(display, 51, 102, 204); + outgoingColor = new Color(display, 102, 102, 102); + + GridData data = new GridData(GridData.FILL_HORIZONTAL | GridData.GRAB_HORIZONTAL | GridData.HORIZONTAL_ALIGN_FILL); + data.horizontalSpan = cSpan; + setLayoutData(data); + } + + protected int handlemouseInCounterBar(int x, int y) { + int nextX = 1; + int sizeX = 0; + if(conflicCount > 0) { + sizeX = scale(conflicCount); + if(x >= nextX && x <= sizeX) return SyncInfo.CONFLICTING; + nextX = (sizeX - 1); + } + if(incomingCount > 0) { + sizeX = scale(incomingCount) + nextX; + if(x >= nextX && x <= sizeX) return SyncInfo.INCOMING; + nextX = (sizeX - 1); + } + if(outgoingCount > 0) { + sizeX = scale(outgoingCount) + nextX; + if(x >= nextX && x <= sizeX) return SyncInfo.OUTGOING; + } + return SyncInfo.IN_SYNC; + } + + public void reset() { + conflicCount = 0; + incomingCount = 0; + outgoingCount = 0; + fColorBarWidth = 0; + redraw(); + } + + private void paintStep(int startX, int endX, int direction) { + GC gc = new GC(this); + setStatusColor(gc, direction); + Rectangle rect= getClientArea(); + startX= Math.max(1, startX); + gc.fillRectangle(startX, 1, endX, rect.height-2); + gc.dispose(); + } + + public void dispose() { + super.dispose(); + conflictColor.dispose(); + outgoingColor.dispose(); + incomingColor.dispose(); + } + + private void setStatusColor(GC gc, int direction) { + switch(direction) { + case SyncInfo.OUTGOING: + gc.setBackground(outgoingColor); break; + case SyncInfo.INCOMING: + gc.setBackground(incomingColor); break; + case SyncInfo.CONFLICTING: + gc.setBackground(conflictColor); break; + } + } + + private int scale(int value) { + if (totalCount > 0) { + Rectangle r= getClientArea(); + if (r.width != 0) + return Math.max(0, value*(r.width-2)/totalCount); + } + return value; + } + + private void drawBevelRect(GC gc, int x, int y, int w, int h, Color topleft, Color bottomright) { + gc.setForeground(topleft); + gc.drawLine(x, y, x+w-1, y); + gc.drawLine(x, y, x, y+h-1); + + gc.setForeground(bottomright); + gc.drawLine(x+w, y, x+w, y+h); + gc.drawLine(x, y+h, x+w, y+h); + } + + private void paint(PaintEvent event) { + GC gc = event.gc; + Display disp= getDisplay(); + + Rectangle rect= getClientArea(); + gc.fillRectangle(rect); + drawBevelRect(gc, rect.x, rect.y, rect.width-1, rect.height-1, + disp.getSystemColor(SWT.COLOR_WIDGET_NORMAL_SHADOW), + disp.getSystemColor(SWT.COLOR_WIDGET_HIGHLIGHT_SHADOW)); + + int nextX = 1; + int sizeX = 0; + if(conflicCount > 0) { + sizeX = scale(conflicCount); + paintStep(nextX, sizeX, SyncInfo.CONFLICTING); + if(activeMode == SyncInfo.CONFLICTING) { + drawBorder(gc, rect, nextX, sizeX); + } + nextX = (sizeX - 1); + } + if(incomingCount > 0) { + sizeX = scale(incomingCount) + nextX; + paintStep(nextX, sizeX, SyncInfo.INCOMING); + if(activeMode == SyncInfo.INCOMING) { + drawBorder(gc, rect, nextX, sizeX); + } + nextX = (sizeX - 1); + } + if(outgoingCount > 0) { + sizeX = scale(outgoingCount) + nextX; + paintStep(nextX, sizeX, SyncInfo.OUTGOING); + if(activeMode == SyncInfo.OUTGOING) { + drawBorder(gc, rect, nextX, sizeX); + } + } + } + + private void drawBorder(GC gc, Rectangle rect, int nextX, int sizeX) { + int lineWidth = 3; + gc.setLineWidth(lineWidth); + gc.setForeground(getDisplay().getSystemColor(SWT.COLOR_YELLOW)); + gc.drawRectangle(nextX, 0, (sizeX - lineWidth) + 1, rect.height - lineWidth); + } + + public Point computeSize(int wHint, int hHint, boolean changed) { + checkWidget(); + Point size= new Point(DEFAULT_WIDTH, DEFAULT_HEIGHT); + if (wHint != SWT.DEFAULT) size.x= wHint; + if (hHint != SWT.DEFAULT) size.y= hHint; + return size; + } + + public void update(int conflicts, int outgoing, int incoming) { + totalCount = conflicts + outgoing + incoming; + conflicCount = conflicts; + incomingCount = incoming; + outgoingCount = outgoing; + redraw(); + } +} diff --git a/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/sync/views/StatisticsPanel.java b/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/sync/views/StatisticsPanel.java new file mode 100644 index 000000000..815413113 --- /dev/null +++ b/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/sync/views/StatisticsPanel.java @@ -0,0 +1,145 @@ +/*************.****************************************************************** + * Copyright (c) 2000, 2003 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.team.internal.ui.sync.views; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.ControlAdapter; +import org.eclipse.swt.events.ControlEvent; +import org.eclipse.swt.events.DisposeEvent; +import org.eclipse.swt.events.DisposeListener; +import org.eclipse.swt.events.PaintEvent; +import org.eclipse.swt.events.PaintListener; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Label; +import org.eclipse.team.core.subscribers.SyncInfo; +import org.eclipse.team.internal.ui.Policy; +import org.eclipse.team.internal.ui.TeamUIPlugin; +import org.eclipse.team.internal.ui.sync.sets.SyncInfoStatistics; +import org.eclipse.team.ui.ISharedImages; + +/** + * Composite that displays statistics relating to Synchronization information. + * + * @since 3.0 + */ +public class StatisticsPanel extends Composite { + + private ViewStatusInformation stats; + + private Label nOutgoing; + private Label nIncoming; + private Label nConflicting; + + private final Image iOutgoing = TeamUIPlugin.getImageDescriptor(ISharedImages.IMG_DLG_SYNC_OUTGOING).createImage(); + private final Image iIncoming = TeamUIPlugin.getImageDescriptor(ISharedImages.IMG_DLG_SYNC_INCOMING).createImage(); + private final Image iConflicting = TeamUIPlugin.getImageDescriptor(ISharedImages.IMG_DLG_SYNC_CONFLICTING).createImage(); + + private boolean showDirectionText = true; + + public StatisticsPanel(Composite parent) { + super(parent, SWT.WRAP); + + GridLayout gridLayout= new GridLayout(); + gridLayout.numColumns= 9; + gridLayout.makeColumnsEqualWidth= false; + gridLayout.marginWidth= 3; + gridLayout.marginHeight= 0; + setLayout(gridLayout); + + nConflicting = createLabel(Policy.bind("StatisticsPanel.conflicting"), iConflicting, "0/0"); //$NON-NLS-1$ //$NON-NLS-2$ + nIncoming = createLabel(Policy.bind("StatisticsPanel.incoming"), iIncoming, "0/0"); //$NON-NLS-1$ //$NON-NLS-2$ + nOutgoing = createLabel(Policy.bind("StatisticsPanel.outgoing"), iOutgoing, "0/0"); //$NON-NLS-1$ //$NON-NLS-2$ + + addDisposeListener(new DisposeListener() { + public void widgetDisposed(DisposeEvent e) { + disposeIcons(); + } + }); + + addControlListener(new ControlAdapter() { + public void controlResized(ControlEvent e) { + } + }); + addPaintListener(new PaintListener() { + public void paintControl(PaintEvent e) { + paint(e); + } + }); + + setLayoutData(new GridData(GridData.GRAB_HORIZONTAL | GridData.HORIZONTAL_ALIGN_FILL)); + } + + protected void disposeIcons() { + iOutgoing.dispose(); + iIncoming.dispose(); + iConflicting.dispose(); + } + + private Label createLabel(String name, Image image, String init) { + Label label= new Label(this, SWT.NONE); + if (image != null) { + image.setBackground(label.getBackground()); + label.setImage(image); + } + label.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING)); + + label= new Label(this, SWT.NONE); + label.setText(name); + label.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING)); + + Label value= new Label(this, SWT.NONE); + value.setText(init); + + value.setBackground(getDisplay().getSystemColor(SWT.COLOR_WIDGET_BACKGROUND)); + value.setLayoutData(new GridData(GridData.FILL_HORIZONTAL | GridData.HORIZONTAL_ALIGN_BEGINNING)); + return value; + } + + private void paint(PaintEvent e) { + } + + public void update(ViewStatusInformation stats) { + this.stats = stats; + updateStats(); + } + + private void updateStats() { + if(stats != null) { + + SyncInfoStatistics workspaceSetStats = stats.getSubscriberInput().getSubscriberSyncSet().getStatistics(); + SyncInfoStatistics workingSetSetStats = stats.getSubscriberInput().getWorkingSetSyncSet().getStatistics(); + + int workspaceConflicting = (int)workspaceSetStats.countFor(SyncInfo.CONFLICTING, SyncInfo.DIRECTION_MASK); + int workspaceOutgoing = (int)workspaceSetStats.countFor(SyncInfo.OUTGOING, SyncInfo.DIRECTION_MASK); + int workspaceIncoming = (int)workspaceSetStats.countFor(SyncInfo.INCOMING, SyncInfo.DIRECTION_MASK); + int workingSetConflicting = (int)workingSetSetStats.countFor(SyncInfo.CONFLICTING, SyncInfo.DIRECTION_MASK); + int workingSetOutgoing = (int)workingSetSetStats.countFor(SyncInfo.OUTGOING, SyncInfo.DIRECTION_MASK); + int workingSetIncoming = (int)workingSetSetStats.countFor(SyncInfo.INCOMING, SyncInfo.DIRECTION_MASK); + + nConflicting.setText(Policy.bind("StatisticsPanel.changeNumbers", new Integer(workingSetConflicting).toString(), new Integer(workspaceConflicting).toString())); //$NON-NLS-1$ + nIncoming.setText(Policy.bind("StatisticsPanel.changeNumbers", new Integer(workingSetIncoming).toString(), new Integer(workspaceIncoming).toString())); //$NON-NLS-1$ + nOutgoing.setText(Policy.bind("StatisticsPanel.changeNumbers", new Integer(workingSetOutgoing).toString(), new Integer(workspaceOutgoing).toString())); //$NON-NLS-1$ + + redraw(); + } + } + + /* (non-Javadoc) + * @see org.eclipse.swt.widgets.Widget#dispose() + */ + public void dispose() { + super.dispose(); + disposeIcons(); + } +}
\ No newline at end of file diff --git a/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/sync/views/SyncSetContentProvider.java b/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/sync/views/SyncSetContentProvider.java index ddea777a8..0d1c9ad09 100644 --- a/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/sync/views/SyncSetContentProvider.java +++ b/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/sync/views/SyncSetContentProvider.java @@ -10,10 +10,12 @@ *******************************************************************************/ package org.eclipse.team.internal.ui.sync.views; +import java.util.ArrayList; +import java.util.List; + import org.eclipse.core.resources.IContainer; import org.eclipse.core.resources.IResource; import org.eclipse.jface.viewers.IStructuredContentProvider; -import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.StructuredViewer; import org.eclipse.jface.viewers.Viewer; import org.eclipse.swt.widgets.Control; @@ -129,8 +131,10 @@ public abstract class SyncSetContentProvider implements IStructuredContentProvid protected void handleResourceChanges(SyncSetChangedEvent event) { // Refresh the viewer for each changed resource SyncInfo[] infos = event.getChangedResources(); - for (int i = 0; i < infos.length; i++) { - ((StructuredViewer) viewer).refresh(getModelObject(infos[i].getLocal()), true); + for (int i = 0; i < infos.length; i++) { + IResource local = infos[i].getLocal(); + ((StructuredViewer) viewer).refresh(getModelObject(local), true); + updateParentLabels(local); } } @@ -146,6 +150,7 @@ public abstract class SyncSetContentProvider implements IStructuredContentProvid for (int i = 0; i < removed.length; i++) { IResource resource = removed[i]; ((StructuredViewer) viewer).refresh(getModelObject(resource)); + updateParentLabels(resource); } } @@ -161,12 +166,7 @@ public abstract class SyncSetContentProvider implements IStructuredContentProvid for (int i = 0; i < added.length; i++) { IResource resource = added[i]; ((StructuredViewer) viewer).refresh(getModelObject(resource.getParent())); - } - IStructuredSelection selection = (IStructuredSelection)viewer.getSelection(); - if(selection.size() == 0) { - if(viewer instanceof INavigableControl) { - ((INavigableControl)viewer).gotoDifference(INavigableControl.NEXT); - } + updateParentLabels(resource); } } @@ -268,4 +268,22 @@ public abstract class SyncSetContentProvider implements IStructuredContentProvid } return result; } -} + + /** + * Forces the viewer to update the labels for parents of this element. This + * can be useful when parents labels include information about their children + * that needs updating when a child changes. + */ + protected void updateParentLabels(IResource resource) { + List parents = new ArrayList(3); + IResource parent = resource.getParent(); + while(parent.getType() != IResource.ROOT) { + parents.add(getModelObject(parent)); + parent = parent.getParent(); + } + getViewer().update( + (SynchronizeViewNode[])parents.toArray(new SynchronizeViewNode[parents.size()]), + null + ); + } +}
\ No newline at end of file diff --git a/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/sync/views/SyncSetTreeContentProvider.java b/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/sync/views/SyncSetTreeContentProvider.java index 15278c5cd..e7b94e6c3 100644 --- a/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/sync/views/SyncSetTreeContentProvider.java +++ b/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/sync/views/SyncSetTreeContentProvider.java @@ -15,7 +15,8 @@ import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.jface.viewers.AbstractTreeViewer; import org.eclipse.jface.viewers.ITreeContentProvider; -import org.eclipse.team.internal.ui.sync.sets.*; +import org.eclipse.team.internal.ui.sync.sets.SubscriberInput; +import org.eclipse.team.internal.ui.sync.sets.SyncSetChangedEvent; /** * This class provides the contents for a AbstractTreeViewer using a SyncSet as the model @@ -83,7 +84,8 @@ public class SyncSetTreeContentProvider extends SyncSetContentProvider implement parent = getModelParent(resource); } Object element = getModelObject(resource); - tree.add(parent, element); + tree.add(parent, element); + updateParentLabels(resource); } } else { super.handleResourceAdditions(event); @@ -101,6 +103,7 @@ public class SyncSetTreeContentProvider extends SyncSetContentProvider implement Object[] modelRoots = new Object[roots.length]; for (int i = 0; i < modelRoots.length; i++) { modelRoots[i] = getModelObject(roots[i]); + updateParentLabels(roots[i]); } tree.remove(modelRoots); } else { diff --git a/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/sync/views/SyncViewerLabelProvider.java b/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/sync/views/SyncViewerLabelProvider.java index 546c3c61e..564fc63a3 100644 --- a/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/sync/views/SyncViewerLabelProvider.java +++ b/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/sync/views/SyncViewerLabelProvider.java @@ -1,16 +1,26 @@ package org.eclipse.team.internal.ui.sync.views; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + import org.eclipse.compare.CompareConfiguration; import org.eclipse.core.resources.IResource; +import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.jface.viewers.DecoratingLabelProvider; import org.eclipse.jface.viewers.ILabelProvider; import org.eclipse.jface.viewers.ITableLabelProvider; import org.eclipse.jface.viewers.LabelProvider; import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.graphics.Point; import org.eclipse.team.core.subscribers.SyncInfo; import org.eclipse.team.core.sync.IRemoteSyncElement; +import org.eclipse.team.internal.ui.OverlayIcon; import org.eclipse.team.internal.ui.TeamUIPlugin; import org.eclipse.team.internal.ui.actions.TeamAction; +import org.eclipse.team.internal.ui.sync.sets.SubscriberInput; +import org.eclipse.team.internal.ui.sync.sets.SyncInfoStatistics; +import org.eclipse.team.internal.ui.sync.sets.SyncSet; import org.eclipse.team.ui.ISharedImages; import org.eclipse.ui.internal.WorkbenchPlugin; import org.eclipse.ui.model.WorkbenchLabelProvider; @@ -26,14 +36,14 @@ public class SyncViewerLabelProvider extends LabelProvider implements ITableLabe private Image compressedFolderImage; + // cache for folder images that have been overlayed with conflict icon + private Map fgImageCache; + // Keep track of the compare and workbench image providers // so they can be properly disposed CompareConfiguration compareConfig = new CompareConfiguration(); WorkbenchLabelProvider workbenchLabelProvider = new WorkbenchLabelProvider(); - /** - * @return - */ public Image getCompressedFolderImage() { if (compressedFolderImage == null) { compressedFolderImage = TeamUIPlugin.getImageDescriptor(ISharedImages.IMG_COMPRESSED_FOLDER).createImage(); @@ -62,32 +72,79 @@ public class SyncViewerLabelProvider extends LabelProvider implements ITableLabe } public String getText(Object element) { - if (element instanceof CompressedFolder) { - IResource resource = getResource(element); - return resource.getProjectRelativePath().toString(); - } + String name; IResource resource = getResource(element); - return workbenchLabelProvider.getText(resource); + if (element instanceof CompressedFolder) { + name = resource.getProjectRelativePath().toString(); + } else { + name = workbenchLabelProvider.getText(resource); + } + return name; } + /** + * An image is decorated by at most 3 different plugins. + * 1. ask the workbench for the default icon for the resource + * 2. ask the compare plugin for the sync kind overlay + * 3. overlay the conflicting image on folders/projects containing conflicts + */ public Image getImage(Object element) { + Image decoratedImage = null; + IResource resource = getResource(element); + if (element instanceof CompressedFolder) { - return compareConfig.getImage(getCompressedFolderImage(), 0); + decoratedImage = compareConfig.getImage(getCompressedFolderImage(), IRemoteSyncElement.IN_SYNC); + } else { + int kind = getSyncKind(element); + switch (kind & IRemoteSyncElement.DIRECTION_MASK) { + case IRemoteSyncElement.OUTGOING: + kind = (kind &~ IRemoteSyncElement.OUTGOING) | IRemoteSyncElement.INCOMING; + break; + case IRemoteSyncElement.INCOMING: + kind = (kind &~ IRemoteSyncElement.INCOMING) | IRemoteSyncElement.OUTGOING; + break; + } + Image image = workbenchLabelProvider.getImage(resource); + decoratedImage = compareConfig.getImage(image, kind); } - IResource resource = getResource(element); - int kind = getSyncKind(element); - switch (kind & IRemoteSyncElement.DIRECTION_MASK) { - case IRemoteSyncElement.OUTGOING: - kind = (kind &~ IRemoteSyncElement.OUTGOING) | IRemoteSyncElement.INCOMING; - break; - case IRemoteSyncElement.INCOMING: - kind = (kind &~ IRemoteSyncElement.INCOMING) | IRemoteSyncElement.OUTGOING; - break; - } - Image image = workbenchLabelProvider.getImage(resource); - return compareConfig.getImage(image, kind); + + return propagateConflicts(decoratedImage, element, resource); } + private Image propagateConflicts(Image base, Object element, IResource resource) { + if(element instanceof SynchronizeViewNode && resource.getType() != IResource.FILE) { + // if the folder is already conflicting then don't bother propagating the conflict + if((getSyncKind(element) & SyncInfo.DIRECTION_MASK) != SyncInfo.CONFLICTING) { + SubscriberInput input = ((SynchronizeViewNode)element).getSubscriberInput(); + SyncSet set = new SyncSet(); + SyncInfo[] infos = input.getWorkingSetSyncSet().getOutOfSyncDescendants(resource); + for (int i = 0; i < infos.length; i++) { + set.add(infos[i]); + } + SyncInfoStatistics stats = set.getStatistics(); + long count = stats.countFor(SyncInfo.CONFLICTING, SyncInfo.DIRECTION_MASK); + if(count > 0) { + ImageDescriptor overlay = new OverlayIcon( + base, + new ImageDescriptor[] { TeamUIPlugin.getImageDescriptor(ISharedImages.IMG_CONFLICT_OVR)}, + new int[] {OverlayIcon.BOTTOM_LEFT}, + new Point(base.getBounds().width, base.getBounds().height)); + + if(fgImageCache == null) { + fgImageCache = new HashMap(10); + } + Image conflictDecoratedImage = (Image) fgImageCache.get(overlay); + if (conflictDecoratedImage == null) { + conflictDecoratedImage = overlay.createImage(); + fgImageCache.put(overlay, conflictDecoratedImage); + } + return conflictDecoratedImage; + } + } + } + return base; + } + /* (non-Javadoc) * @see org.eclipse.jface.viewers.IBaseLabelProvider#dispose() */ @@ -95,8 +152,16 @@ public class SyncViewerLabelProvider extends LabelProvider implements ITableLabe super.dispose(); workbenchLabelProvider.dispose(); compareConfig.dispose(); - if (compressedFolderImage != null) + if (compressedFolderImage != null) { compressedFolderImage.dispose(); + } + if(fgImageCache != null) { + Iterator it = fgImageCache.values().iterator(); + while (it.hasNext()) { + Image element = (Image) it.next(); + element.dispose(); + } + } } /* (non-Javadoc) diff --git a/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/sync/views/SynchronizeView.java b/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/sync/views/SynchronizeView.java index cac599459..4f2c39eec 100644 --- a/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/sync/views/SynchronizeView.java +++ b/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/sync/views/SynchronizeView.java @@ -47,6 +47,7 @@ import org.eclipse.swt.events.KeyListener; import org.eclipse.swt.events.SelectionListener; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Display; @@ -114,6 +115,7 @@ public class SynchronizeView extends ViewPart implements ITeamResourceChangeList // Parent composite of this view. It is remembered so that we can dispose of its children when // the viewer type is switched. private Composite composite = null; + private StatisticsPanel statsPanel; private IMemento memento; // Viewer type constants @@ -125,9 +127,6 @@ public class SynchronizeView extends ViewPart implements ITeamResourceChangeList // Remembering the current input and the previous. private SubscriberInput input = null; - // Stats about the current subscriber. This is used for status line and/or title updating - private ViewStatusInformation statusInformation; - // A set of common actions. They are hooked to the active SubscriberInput and must // be reset when the input changes. private SyncViewerActions actions; @@ -156,7 +155,13 @@ public class SynchronizeView extends ViewPart implements ITeamResourceChangeList /* (non-Javadoc) * @see org.eclipse.ui.IWorkbenchPart#createPartControl(org.eclipse.swt.widgets.Composite) */ - public void createPartControl(Composite parent) { + public void createPartControl(Composite parent) { + GridLayout gridLayout= new GridLayout(); + gridLayout.makeColumnsEqualWidth= false; + gridLayout.marginWidth= 0; + gridLayout.marginHeight = 0; + parent.setLayout(gridLayout); + createViewer(parent); this.composite = parent; @@ -178,7 +183,8 @@ public class SynchronizeView extends ViewPart implements ITeamResourceChangeList TeamUIPlugin.disposeOnShutdown(refreshingImg); setViewImage(initialImg); - updateTitle(); + updateStatusPanel(); + updateTooltip(); initializeJobListener(); actions.setContext(null); @@ -222,9 +228,10 @@ public class SynchronizeView extends ViewPart implements ITeamResourceChangeList RefreshSubscriberInputJob refreshJob = TeamUIPlugin.getPlugin().getRefreshJob(); refreshJob.setSubscriberInput(input); + updateStatusPanel(); + setTitle(Policy.bind("LiveSyncView.titleSubscriber", input.getSubscriber().getName())); //$NON-NLS-1$ } - }); - updateTitle(); + }); } private void disconnectSubscriberInput() { @@ -254,6 +261,7 @@ public class SynchronizeView extends ViewPart implements ITeamResourceChangeList viewer.setSelection(oldSelection, true); } fireSafePropertyChange(PROP_VIEWTYPE); + updateStatusPanel(); } } /** @@ -343,6 +351,7 @@ public class SynchronizeView extends ViewPart implements ITeamResourceChangeList Label label = new Label(parent, SWT.WRAP); label.setText(Policy.bind("SynchronizeView.noSubscribersMessage")); //$NON-NLS-1$ } else { + statsPanel = new StatisticsPanel(parent); switch(currentViewType) { case TREE_VIEW: createTreeViewerPartControl(parent); @@ -359,9 +368,11 @@ public class SynchronizeView extends ViewPart implements ITeamResourceChangeList } protected void createTreeViewerPartControl(Composite parent) { + GridData data = new GridData(GridData.FILL_BOTH); viewer = new SyncTreeViewer(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL); viewer.setLabelProvider(SyncViewerLabelProvider.getDecoratingLabelProvider()); viewer.setSorter(new SyncViewerSorter(ResourceSorter.NAME)); + ((TreeViewer)viewer).getTree().setLayoutData(data); } protected void createTableViewerPartControl(Composite parent) { @@ -470,46 +481,33 @@ public class SynchronizeView extends ViewPart implements ITeamResourceChangeList initializeSubscriberInput(newInput); } } - /* - * Synchronize - (showing N of M changes) - {Subscriber name} - */ - protected void updateTitle() { + + protected void updateStatusPanel() { Display.getDefault().asyncExec(new Runnable() { public void run() { SubscriberInput input = getInput(); - if(input != null) { - ViewStatusInformation newStatus = new ViewStatusInformation(input); - if(statusInformation == null || ! statusInformation.equals(newStatus)) { - statusInformation = newStatus; - - TeamSubscriber subscriber = input.getSubscriber(); - String changesText; - if(input.getWorkingSet() != null) { - changesText = Policy.bind("LiveSyncView.titleChangeNumbers", //$NON-NLS-1$ - new Long(statusInformation.getNumShowing()).toString(), - new Long(statusInformation.getNumInWorkingSet()).toString(), - new Long(statusInformation.getNumInWorkspace() - statusInformation.getNumInWorkingSet()).toString()); - } else { - changesText = Policy.bind("LiveSyncView.titleChangeNumbersNoWorkingSet", //$NON-NLS-1$ - new Long(statusInformation.getNumShowing()).toString(), - new Long(statusInformation.getNumInWorkingSet()).toString()); - } - String title = Policy.bind("LiveSyncView.titleWithSubscriber", new String[] {Policy.bind("LiveSyncView.title"), changesText, subscriber.getName()}); //$NON-NLS-1$ //$NON-NLS-2$ - setTitle(title); - StringBuffer b = new StringBuffer(title + "\n"); //$NON-NLS-1$ - b.append(input.getSubscriberSyncSet().getStatistics().toString()); - setTitleToolTip(b.toString()); + if(input != null && statsPanel != null) { + statsPanel.update(new ViewStatusInformation(input)); + } + } + }); + } + + protected void updateTooltip() { + Display.getDefault().asyncExec(new Runnable() { + public void run() { + SubscriberInput input = getInput(); + if(input != null) { + if(input.getWorkingSet() != null) { + String tooltip = Policy.bind("LiveSyncView.titleTooltip", input.getWorkingSet().getName()); //$NON-NLS-1$ + setTitleToolTip(tooltip); + } else { + setTitleToolTip(""); //$NON-NLS-1$ } - } else { - setTitle(Policy.bind("LiveSyncView.title")); //$NON-NLS-1$ - setTitleToolTip(""); //$NON-NLS-1$ } - } + } }); } - - - /** * Passing the focus request to the viewer's control. */ @@ -632,6 +630,7 @@ public class SynchronizeView extends ViewPart implements ITeamResourceChangeList context.setInput(null); actions.setContext(context); viewer.setInput(null); + setTitle(Policy.bind("LiveSyncView.titleSubscriber")); //$NON-NLS-1$ } }); } @@ -757,7 +756,7 @@ public class SynchronizeView extends ViewPart implements ITeamResourceChangeList * Update the title when either the subscriber or filter sync set changes. */ public void syncSetChanged(SyncSetChangedEvent event) { - updateTitle(); + updateStatusPanel(); // remove opened compare editors if file was removed from sync view and update if changed IResource[] resources =event.getRemovedResources(); @@ -844,7 +843,7 @@ public class SynchronizeView extends ViewPart implements ITeamResourceChangeList public void workingSetChanged(IWorkingSet set) { input.setWorkingSet(set); - updateTitle(); + updateTooltip(); } /** * Updates the filter applied to the active subscriber input and ensures that selection and expansions diff --git a/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/sync/views/SynchronizeViewNode.java b/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/sync/views/SynchronizeViewNode.java index d91150d33..5269efc77 100644 --- a/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/sync/views/SynchronizeViewNode.java +++ b/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/sync/views/SynchronizeViewNode.java @@ -45,6 +45,10 @@ public class SynchronizeViewNode implements IAdaptable, IActionFilter, ISynchron return input.getFilteredSyncSet(); } + public SubscriberInput getSubscriberInput() { + return input; + } + /* (non-Javadoc) * @see org.eclipse.team.ui.sync.ISynchronizeViewNode#getTeamSubscriber() */ diff --git a/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/sync/views/ViewStatusInformation.java b/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/sync/views/ViewStatusInformation.java index e09f6d150..02e6603c6 100644 --- a/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/sync/views/ViewStatusInformation.java +++ b/bundles/org.eclipse.team.ui/src/org/eclipse/team/internal/ui/sync/views/ViewStatusInformation.java @@ -20,9 +20,11 @@ class ViewStatusInformation { private long numShowing = 0; private long numInWorkingSet = 0; private long numInWorkspace = 0; + private SubscriberInput input; ViewStatusInformation(SubscriberInput input) { this.subscriberName = input.getSubscriber().getName(); + this.input = input; IWorkingSet set = input.getWorkingSet(); if(set != null) { this.workingSetName = set.getName(); @@ -54,6 +56,10 @@ class ViewStatusInformation { return workingSetName; } + public SubscriberInput getSubscriberInput() { + return input; + } + public boolean equals(Object other) { if(other == this) return true; if(other instanceof ViewStatusInformation) { diff --git a/bundles/org.eclipse.team.ui/src/org/eclipse/team/ui/ISharedImages.java b/bundles/org.eclipse.team.ui/src/org/eclipse/team/ui/ISharedImages.java index 8838e6016..097f7a723 100644 --- a/bundles/org.eclipse.team.ui/src/org/eclipse/team/ui/ISharedImages.java +++ b/bundles/org.eclipse.team.ui/src/org/eclipse/team/ui/ISharedImages.java @@ -23,6 +23,7 @@ public interface ISharedImages { public final String IMG_DIRTY_OVR = "ovr/dirty_ov.gif"; //$NON-NLS-1$ public final String IMG_CHECKEDIN_OVR = "ovr/version_controlled.gif"; //$NON-NLS-1$ public final String IMG_CHECKEDOUT_OVR = "ovr/checkedout_ov.gif"; //$NON-NLS-1$ + public final String IMG_CONFLICT_OVR = "ovr/confchg_ov.gif"; //$NON-NLS-1$ public final String IMG_COLLAPSE_ALL = "clcl16/collapseall.gif"; //$NON-NLS-1$ public final String IMG_COLLAPSE_ALL_ENABLED = "elcl16/collapseall.gif"; //$NON-NLS-1$ |