Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDarin Wright2007-08-20 19:05:10 +0000
committerDarin Wright2007-08-20 19:05:10 +0000
commit915e49c30214e6279a4a9fb91a7c70f963c6a256 (patch)
tree0b6e7d5436cb5e72cd0d8147a28bad158d02d329 /org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/elements
parent38f0eda6752aff71557ebcd7677d8e2bb3e0a66f (diff)
downloadeclipse.platform.debug-915e49c30214e6279a4a9fb91a7c70f963c6a256.tar.gz
eclipse.platform.debug-915e49c30214e6279a4a9fb91a7c70f963c6a256.tar.xz
eclipse.platform.debug-915e49c30214e6279a4a9fb91a7c70f963c6a256.zip
Bug 176627 - [Registers view] Switching stack frames: Unnecessary scrolling to top and group closing
Diffstat (limited to 'org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/elements')
-rw-r--r--org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/elements/adapters/RegisterGroupProxy.java516
-rw-r--r--org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/elements/adapters/StackFrameViewerInputProvider.java39
2 files changed, 555 insertions, 0 deletions
diff --git a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/elements/adapters/RegisterGroupProxy.java b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/elements/adapters/RegisterGroupProxy.java
new file mode 100644
index 000000000..fc5dc7724
--- /dev/null
+++ b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/elements/adapters/RegisterGroupProxy.java
@@ -0,0 +1,516 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and others.
+ * 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.debug.internal.ui.elements.adapters;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.core.runtime.PlatformObject;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.debug.core.DebugException;
+import org.eclipse.debug.core.model.IRegisterGroup;
+import org.eclipse.debug.core.model.IStackFrame;
+import org.eclipse.debug.internal.core.commands.Request;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenCountUpdate;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenUpdate;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IColumnPresentation;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IColumnPresentationFactory;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementCompareRequest;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementContentProvider;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementMementoProvider;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementMementoRequest;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IHasChildrenUpdate;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelProxy;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelProxyFactory;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IViewerUpdate;
+import org.eclipse.debug.internal.ui.views.launch.DebugElementAdapterFactory;
+import org.eclipse.jface.viewers.TreePath;
+import org.eclipse.ui.IMemento;
+
+/**
+ * Used as input to the registers view for a stack frame. Insulates register groups
+ * that do not change across stack frame selection to avoid register groups collapsing
+ * while stepping between frames.
+ * <p>
+ * The standard debug model {@link IStackFrame} uses an
+ * {@link org.eclipse.debug.internal.ui.viewers.model.provisional.IViewerInputProvider} to
+ * create a register group proxy for the register view's input.
+ * </p>
+ * <p>
+ * This class delegates to the underlying stack frame for the following adapters. This way,
+ * if a standard model provides custom adapters they are still used to present custom content
+ * in the view and provide stable register groups while stepping.
+ * <ul>
+ * <li>{@link IModelProxyFactory}</li>
+ * <li>{@link IColumnPresentationFactory}</li>
+ * <li>{@link IElementContentProvider}</li>
+ * <li>{@link IElementMementoProvider}</li>
+ * </ul>
+ * </p>
+ * @since 3.4
+ */
+public class RegisterGroupProxy implements IModelProxyFactory, IColumnPresentationFactory, IElementContentProvider, IElementMementoProvider {
+
+ private IRegisterGroup[] fGroups;
+ private IStackFrame fFrame;
+
+ private static final String HASH_CODE = "HASH_CODE"; //$NON-NLS-1$
+
+ /**
+ * Local implementation of a viewer update request. This class delegates to the underlying frame
+ * for viewer requests. The requests have to be wrapped such that the request's element provided
+ * for existing clients is the underlying frame, rather than the register group proxy (as existing
+ * models do not know or need to know about the proxy).
+ */
+ private class Update extends Request implements IViewerUpdate {
+ private IViewerUpdate fViewerUpdate;
+
+ Update(IViewerUpdate update) {
+ fViewerUpdate = update;
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.internal.ui.viewers.model.provisional.IViewerUpdate#getElement()
+ */
+ public Object getElement() {
+ return fFrame;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.internal.ui.viewers.model.provisional.IViewerUpdate#getElementPath()
+ */
+ public TreePath getElementPath() {
+ return TreePath.EMPTY;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.internal.ui.viewers.model.provisional.IViewerUpdate#getPresentationContext()
+ */
+ public IPresentationContext getPresentationContext() {
+ return fViewerUpdate.getPresentationContext();
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.internal.core.commands.Request#done()
+ */
+ public void done() {
+ fViewerUpdate.setStatus(getStatus());
+ fViewerUpdate.done();
+ }
+ }
+
+ private class CountUpdate extends Update implements IChildrenCountUpdate {
+
+ private IChildrenCountUpdate fUpdate;
+
+ CountUpdate(IChildrenCountUpdate delegate) {
+ super(delegate);
+ fUpdate = delegate;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenCountUpdate#setChildCount(int)
+ */
+ public void setChildCount(int numChildren) {
+ fUpdate.setChildCount(numChildren);
+ }
+
+ }
+
+ private class HasUpdate extends Update implements IHasChildrenUpdate {
+
+ private IHasChildrenUpdate fUpdate;
+
+ HasUpdate(IHasChildrenUpdate delegate) {
+ super(delegate);
+ fUpdate = delegate;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.internal.ui.viewers.model.provisional.IHasChildrenUpdate#setHasChilren(boolean)
+ */
+ public void setHasChilren(boolean hasChildren) {
+ fUpdate.setHasChilren(hasChildren);
+ }
+
+ }
+
+ private class ChildrenUpdate extends Update implements IChildrenUpdate {
+
+ private IChildrenUpdate fUpdate;
+
+ ChildrenUpdate(IChildrenUpdate delegate) {
+ super(delegate);
+ fUpdate = delegate;
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenUpdate#getLength()
+ */
+ public int getLength() {
+ return fUpdate.getLength();
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenUpdate#getOffset()
+ */
+ public int getOffset() {
+ return fUpdate.getOffset();
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenUpdate#setChild(java.lang.Object, int)
+ */
+ public void setChild(Object child, int offset) {
+ fUpdate.setChild(child, offset);
+ }
+
+ }
+
+ /**
+ * The memento request has to override {@link #getElement()} to provide the element
+ * that a memento is requested for (which could be any element in the view, not just
+ * the root stack frame).
+ */
+ private class MementoRequest extends Update implements IElementMementoRequest {
+
+ private IElementMementoRequest fUpdate;
+ MementoRequest(IElementMementoRequest request) {
+ super(request);
+ fUpdate = request;
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.internal.ui.viewers.model.provisional.IElementMementoRequest#getMemento()
+ */
+ public IMemento getMemento() {
+ return fUpdate.getMemento();
+ }
+ public Object getElement() {
+ return fUpdate.getElement();
+ }
+ public TreePath getElementPath() {
+ return fUpdate.getElementPath();
+ }
+
+ }
+
+ private class ElementCompare extends MementoRequest implements IElementCompareRequest {
+
+ private IElementCompareRequest fRequest;
+ ElementCompare(IElementCompareRequest request) {
+ super(request);
+ fRequest = request;
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.internal.ui.viewers.model.provisional.IElementCompareRequest#setEqual(boolean)
+ */
+ public void setEqual(boolean equal) {
+ fRequest.setEqual(equal);
+ }
+
+ }
+
+ /**
+ * Creates a new register group proxy for the given stack frame.
+ *
+ * @param frame stack frame
+ * @throws DebugException exception if unable to retrieve register groups
+ */
+ public RegisterGroupProxy(IStackFrame frame) throws DebugException {
+ fFrame = frame;
+ init(frame);
+ }
+
+ /* (non-Javadoc)
+ *
+ * A register group proxy is equal to other stack frames that have the same
+ * register groups.
+ *
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ public boolean equals(Object obj) {
+ if (obj instanceof RegisterGroupProxy) {
+ return Arrays.equals(fGroups, ((RegisterGroupProxy)obj).fGroups);
+ }
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#hashCode()
+ */
+ public int hashCode() {
+ int code = getClass().hashCode();
+ for (int i = 0; i < fGroups.length; i++) {
+ code+=fGroups[i].hashCode();
+ }
+ return code;
+ }
+
+ /**
+ * Initializes the register groups for this stack frame.
+ *
+ * @param frame stack frame
+ */
+ private void init(IStackFrame frame) throws DebugException {
+ fGroups = frame.getRegisterGroups();
+ }
+
+ /**
+ * Returns cached register groups for this stack frame.
+ *
+ * @return register groups
+ */
+ protected IRegisterGroup[] getRegisterGroups() {
+ return fGroups;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.internal.ui.viewers.model.provisional.IModelProxyFactory#createModelProxy(java.lang.Object, org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext)
+ */
+ public IModelProxy createModelProxy(Object element, IPresentationContext context) {
+ IModelProxyFactory factory = getModelProxyFactoryAdapter(fFrame);
+ if (factory != null) {
+ return factory.createModelProxy(fFrame, context);
+ }
+ return null;
+ }
+
+ /**
+ * Returns the model proxy factory for the given element or
+ * <code>null</code> if none.
+ *
+ * @param element
+ * element to retrieve adapter for
+ * @return model proxy factory adapter or <code>null</code>
+ */
+ protected IModelProxyFactory getModelProxyFactoryAdapter(Object element) {
+ IModelProxyFactory adapter = null;
+ if (element instanceof IModelProxyFactory) {
+ adapter = (IModelProxyFactory) element;
+ } else if (element instanceof IAdaptable) {
+ IAdaptable adaptable = (IAdaptable) element;
+ adapter = (IModelProxyFactory) adaptable.getAdapter(IModelProxyFactory.class);
+ if (adapter == null && !(element instanceof PlatformObject)) {
+ // for objects that don't properly subclass PlatformObject to inherit default
+ // adapters, just delegate to the adapter factory
+ adapter = (IModelProxyFactory) new DebugElementAdapterFactory().getAdapter(element, IModelProxyFactory.class);
+ }
+ }
+ return adapter;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.internal.ui.viewers.model.provisional.IColumnPresentationFactory#createColumnPresentation(org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext, java.lang.Object)
+ */
+ public IColumnPresentation createColumnPresentation(IPresentationContext context, Object element) {
+ IColumnPresentationFactory factory = getColumnPresenetationFactoryAdapter(fFrame);
+ if (factory != null) {
+ return factory.createColumnPresentation(context, fFrame);
+ }
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.internal.ui.viewers.model.provisional.IColumnPresentationFactory#getColumnPresentationId(org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext, java.lang.Object)
+ */
+ public String getColumnPresentationId(IPresentationContext context, Object element) {
+ IColumnPresentationFactory factory = getColumnPresenetationFactoryAdapter(fFrame);
+ if (factory != null) {
+ return factory.getColumnPresentationId(context, fFrame);
+ }
+ return null;
+ }
+
+ /**
+ * Returns the column presentation factory for the given element or <code>null</code>.
+ *
+ * @param input
+ * @return column presentation factory of <code>null</code>
+ */
+ protected IColumnPresentationFactory getColumnPresenetationFactoryAdapter(Object input) {
+ IColumnPresentationFactory adapter = null;
+ if (input instanceof IColumnPresentationFactory) {
+ adapter = (IColumnPresentationFactory) input;
+ } else if (input instanceof IAdaptable) {
+ IAdaptable adaptable = (IAdaptable) input;
+ adapter = (IColumnPresentationFactory) adaptable.getAdapter(IColumnPresentationFactory.class);
+ if (adapter == null && !(input instanceof PlatformObject)) {
+ // for objects that don't properly subclass PlatformObject to inherit default
+ // adapters, just delegate to the adapter factory
+ adapter = (IColumnPresentationFactory) new DebugElementAdapterFactory().getAdapter(input, IColumnPresentationFactory.class);
+ }
+ }
+ return adapter;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.internal.ui.viewers.model.provisional.IElementContentProvider#update(org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenCountUpdate[])
+ */
+ public void update(IChildrenCountUpdate[] updates) {
+ IElementContentProvider provider = getContentAdapter(fFrame);
+ if (provider != null) {
+ IChildrenCountUpdate[] others = new IChildrenCountUpdate[updates.length];
+ for (int i = 0; i < updates.length; i++) {
+ others[i] = new CountUpdate(updates[i]);
+ }
+ provider.update(others);
+ } else {
+ cancelUpdates(updates);
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.internal.ui.viewers.model.provisional.IElementContentProvider#update(org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenUpdate[])
+ */
+ public void update(IChildrenUpdate[] updates) {
+ IElementContentProvider provider = getContentAdapter(fFrame);
+ if (provider != null) {
+ IChildrenUpdate[] others = new IChildrenUpdate[updates.length];
+ for (int i = 0; i < updates.length; i++) {
+ others[i] = new ChildrenUpdate(updates[i]);
+ }
+ provider.update(others);
+ } else {
+ cancelUpdates(updates);
+ }
+
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.internal.ui.viewers.model.provisional.IElementContentProvider#update(org.eclipse.debug.internal.ui.viewers.model.provisional.IHasChildrenUpdate[])
+ */
+ public void update(IHasChildrenUpdate[] updates) {
+ IElementContentProvider provider = getContentAdapter(fFrame);
+ if (provider != null) {
+ IHasChildrenUpdate[] others = new IHasChildrenUpdate[updates.length];
+ for (int i = 0; i < updates.length; i++) {
+ others[i] = new HasUpdate(updates[i]);
+ }
+ provider.update(others);
+ } else {
+ cancelUpdates(updates);
+ }
+ }
+
+ /**
+ * Cancels a collection of update requests.
+ *
+ * @param updates updates to cancel
+ */
+ private void cancelUpdates(IViewerUpdate[] updates) {
+ for (int i = 0; i < updates.length; i++) {
+ updates[i].setStatus(Status.CANCEL_STATUS);
+ updates[i].done();
+ }
+ }
+
+ /**
+ * Returns the content adapter for the given element or
+ * <code>null</code> if none.
+ *
+ * @param element
+ * element to retrieve adapter for
+ * @return content adapter or <code>null</code>
+ */
+ protected IElementContentProvider getContentAdapter(Object element) {
+ IElementContentProvider adapter = null;
+ if (element instanceof IElementContentProvider) {
+ adapter = (IElementContentProvider) element;
+ } else if (element instanceof IAdaptable) {
+ IAdaptable adaptable = (IAdaptable) element;
+ adapter = (IElementContentProvider) adaptable.getAdapter(IElementContentProvider.class);
+ if (adapter == null && !(element instanceof PlatformObject)) {
+ // for objects that don't properly subclass PlatformObject to inherit default
+ // adapters, just delegate to the adapter factory
+ adapter = (IElementContentProvider) new DebugElementAdapterFactory().getAdapter(element, IElementContentProvider.class);
+ }
+ }
+ return adapter;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.internal.ui.viewers.model.provisional.IElementMementoProvider#compareElements(org.eclipse.debug.internal.ui.viewers.model.provisional.IElementCompareRequest[])
+ */
+ public void compareElements(IElementCompareRequest[] requests) {
+ IElementMementoProvider provider = getViewerStateAdapter(fFrame);
+ if (provider != null) {
+ List others = new ArrayList(requests.length);
+ for (int i = 0; i < requests.length; i++) {
+ IElementCompareRequest request = requests[i];
+ if (request.getElement().equals(this)) {
+ Integer integer = request.getMemento().getInteger(HASH_CODE);
+ if (integer != null) {
+ request.setEqual(integer.intValue() == hashCode());
+ } else {
+ request.setEqual(false);
+ }
+ request.done();
+ } else {
+ others.add(new ElementCompare(request));
+ }
+ }
+ if (!others.isEmpty()) {
+ provider.compareElements((IElementCompareRequest[]) others.toArray(new IElementCompareRequest[others.size()]));
+ }
+ } else {
+ cancelUpdates(requests);
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.internal.ui.viewers.model.provisional.IElementMementoProvider#encodeElements(org.eclipse.debug.internal.ui.viewers.model.provisional.IElementMementoRequest[])
+ */
+ public void encodeElements(IElementMementoRequest[] requests) {
+ IElementMementoProvider provider = getViewerStateAdapter(fFrame);
+ if (provider != null) {
+ List others = new ArrayList(requests.length);
+ for (int i = 0; i < requests.length; i++) {
+ IElementMementoRequest request = requests[i];
+ if (request.getElement().equals(this)) {
+ request.getMemento().putInteger(HASH_CODE, this.hashCode());
+ request.done();
+ } else {
+ others.add(new MementoRequest(request));
+ }
+ }
+ if (!others.isEmpty()) {
+ provider.encodeElements((IElementMementoRequest[]) others.toArray(new IElementMementoRequest[others.size()]));
+ }
+ } else {
+ cancelUpdates(requests);
+ }
+ }
+
+ /**
+ * Returns the viewer state adapter for the given element or
+ * <code>null</code> if none.
+ *
+ * @param element
+ * element to retrieve adapter for
+ * @return viewer state adapter or <code>null</code>
+ */
+ protected IElementMementoProvider getViewerStateAdapter(Object element) {
+ IElementMementoProvider adapter = null;
+ if (element instanceof IElementMementoProvider) {
+ adapter = (IElementMementoProvider) element;
+ } else if (element instanceof IAdaptable) {
+ IAdaptable adaptable = (IAdaptable) element;
+ adapter = (IElementMementoProvider) adaptable.getAdapter(IElementMementoProvider.class);
+ if (adapter == null && !(element instanceof PlatformObject)) {
+ // for objects that don't properly subclass PlatformObject to inherit default
+ // adapters, just delegate to the adapter factory
+ adapter = (IElementMementoProvider) new DebugElementAdapterFactory().getAdapter(element, IElementMementoProvider.class);
+ }
+ }
+ return adapter;
+ }
+}
diff --git a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/elements/adapters/StackFrameViewerInputProvider.java b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/elements/adapters/StackFrameViewerInputProvider.java
new file mode 100644
index 000000000..ecd1418d8
--- /dev/null
+++ b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/elements/adapters/StackFrameViewerInputProvider.java
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and others.
+ * 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.debug.internal.ui.elements.adapters;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.debug.core.model.IStackFrame;
+import org.eclipse.debug.internal.ui.model.elements.ViewerInputProvider;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IViewerUpdate;
+import org.eclipse.debug.ui.IDebugUIConstants;
+
+/**
+ * @since 3.4
+ */
+public class StackFrameViewerInputProvider extends ViewerInputProvider {
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.internal.ui.model.elements.ViewerInputProvider#getViewerInput(java.lang.Object, org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext, org.eclipse.debug.internal.ui.viewers.model.provisional.IViewerUpdate)
+ */
+ protected Object getViewerInput(Object source, IPresentationContext context, IViewerUpdate update) throws CoreException {
+ return new RegisterGroupProxy((IStackFrame) source);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.internal.ui.model.elements.ViewerInputProvider#supportsContextId(java.lang.String)
+ */
+ protected boolean supportsContextId(String id) {
+ return IDebugUIConstants.ID_REGISTER_VIEW.equals(id);
+ }
+
+}

Back to the top