Bug 409065 - [variables] Enable "Show Logical Structure" by default

Change-Id: I733eadd388c3dcfdc34f7b6a58a705a28eb92c7e
diff --git a/org.eclipse.debug.ui/icons/full/ovr16/var_cntnt_prvdr_ov.png b/org.eclipse.debug.ui/icons/full/ovr16/var_cntnt_prvdr_ov.png
new file mode 100644
index 0000000..d2e8a8c
--- /dev/null
+++ b/org.eclipse.debug.ui/icons/full/ovr16/var_cntnt_prvdr_ov.png
Binary files differ
diff --git a/org.eclipse.debug.ui/icons/full/ovr16/var_cntnt_prvdr_ov@2x.png b/org.eclipse.debug.ui/icons/full/ovr16/var_cntnt_prvdr_ov@2x.png
new file mode 100644
index 0000000..9c15cfe
--- /dev/null
+++ b/org.eclipse.debug.ui/icons/full/ovr16/var_cntnt_prvdr_ov@2x.png
Binary files differ
diff --git a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/DebugPluginImages.java b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/DebugPluginImages.java
index 0c1ddaf..3f70b31 100644
--- a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/DebugPluginImages.java
+++ b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/DebugPluginImages.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- *  Copyright (c) 2000, 2014 IBM Corporation and others.
+ *  Copyright (c) 2000, 2017 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
@@ -236,6 +236,7 @@
 		declareRegistryImage(IDebugUIConstants.IMG_OVR_ERROR, OVR + "error.png"); //$NON-NLS-1$
 		declareRegistryImage(IInternalDebugUIConstants.IMG_OVR_TRANSPARENT, OVR + "transparent.png"); //$NON-NLS-1$
 		declareRegistryImage(IDebugUIConstants.IMG_OVR_SKIP_BREAKPOINT, OVR + "skip_breakpoint_ov.png"); //$NON-NLS-1$
+		declareRegistryImage(IInternalDebugUIConstants.IMG_OVR_SHOW_LOGICAL_STRUCTURE, OVR + "var_cntnt_prvdr_ov.png"); //$NON-NLS-1$
 
 		//source location
 		declareRegistryImage(IInternalDebugUIConstants.IMG_SRC_LOOKUP_MENU, ELCL + "edtsrclkup_co.png"); //$NON-NLS-1$
diff --git a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/IInternalDebugUIConstants.java b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/IInternalDebugUIConstants.java
index 3ed20ea..3243591 100644
--- a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/IInternalDebugUIConstants.java
+++ b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/IInternalDebugUIConstants.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2016 IBM Corporation and others.
+ * Copyright (c) 2000, 2017 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
@@ -193,6 +193,11 @@
      */
     public static final String IMG_OVR_TRANSPARENT = "IMG_OVR_TRANSPARENT";  //$NON-NLS-1$
 
+	/**
+	 * Logical Structure overlay image identifier.
+	 */
+	public static final String IMG_OVR_SHOW_LOGICAL_STRUCTURE = "IMG_OVR_SHOW_LOGICAL_STRUCTURE"; //$NON-NLS-1$
+
     /**
      * Editor Id for the "Source Not Found" editor
      */
diff --git a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/views/variables/AvailableLogicalStructuresAction.java b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/views/variables/AvailableLogicalStructuresAction.java
index f3aaae0..602eba9 100644
--- a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/views/variables/AvailableLogicalStructuresAction.java
+++ b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/views/variables/AvailableLogicalStructuresAction.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * Copyright (c) 2000, 2017 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
@@ -16,14 +16,18 @@
 import org.eclipse.debug.core.model.IExpression;
 import org.eclipse.debug.core.model.IValue;
 import org.eclipse.debug.core.model.IVariable;
+import org.eclipse.debug.internal.ui.DebugPluginImages;
 import org.eclipse.debug.internal.ui.IDebugHelpContextIds;
+import org.eclipse.debug.internal.ui.IInternalDebugUIConstants;
 import org.eclipse.jface.action.Action;
 import org.eclipse.jface.action.ActionContributionItem;
 import org.eclipse.jface.action.IMenuCreator;
 import org.eclipse.jface.viewers.ISelection;
 import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.swt.SWT;
 import org.eclipse.swt.widgets.Control;
 import org.eclipse.swt.widgets.Menu;
+import org.eclipse.swt.widgets.MenuItem;
 import org.eclipse.ui.PlatformUI;
 
 /**
@@ -41,6 +45,7 @@
 		setView(view);
 		setToolTipText(VariablesViewMessages.AvailableLogicalStructuresAction_0);
 		setText(VariablesViewMessages.AvailableLogicalStructuresAction_1);
+		setImageDescriptor(DebugPluginImages.getImageDescriptor(IInternalDebugUIConstants.IMG_ELCL_SHOW_LOGICAL_STRUCTURE));
 		PlatformUI.getWorkbench().getHelpSystem().setHelp(this, IDebugHelpContextIds.VARIABLES_SELECT_LOGICAL_STRUCTURE);
 		setEnabled(false);
 		setMenuCreator(this);
@@ -104,7 +109,7 @@
 			for (int i = 0; i < types.length; i++) {
                 ILogicalStructureType type= types[i];
 				Action action = new SelectLogicalStructureAction(getView(), type, getValue(), types);
-                action.setChecked(enabledType == type);
+				action.setChecked((enabledType == type) && getView().isShowLogicalStructure());
                 StringBuffer label= new StringBuffer();
                 //add the numerical accelerator
                 if (i < 9) {
@@ -113,10 +118,19 @@
                     label.append(' ');
                 }
                 label.append(action.getText());
-                action.setText(label.toString());
+				if (enabledType == type) {
+					action.setText(label.toString() + " " + VariablesViewMessages.AvailableLogicalStructuresAction_2); //$NON-NLS-1$
+				} else {
+					action.setText(label.toString());
+				}
 				addActionToMenu(fMenu, action);
 			}
 		}
+
+		new MenuItem(fMenu, SWT.SEPARATOR);
+		EditVariableLogicalStructureAction editVariableLogicalStructureAction = new EditVariableLogicalStructureAction(getView());
+		editVariableLogicalStructureAction.setText(VariablesViewMessages.AvailableLogicalStructuresAction_3);
+		addActionToMenu(fMenu, editVariableLogicalStructureAction);
 		return fMenu;
 	}
 
@@ -126,36 +140,33 @@
 	public void init() {
 		setValue(null);
 		setTypes(null);
-		if (getView().isShowLogicalStructure()) {
-			ISelection s = getView().getViewer().getSelection();
-			if (s instanceof IStructuredSelection) {
-				IStructuredSelection selection = (IStructuredSelection) s;
-				if (selection.size() == 1) {
-					Object obj = selection.getFirstElement();
-					IValue value = null;
-					if (obj instanceof IVariable) {
-						IVariable var = (IVariable) obj;
-						try {
-							value = var.getValue();
-						} catch (DebugException e) {
-						}
-					} else if (obj instanceof IExpression) {
-						IExpression expression = (IExpression)obj;
-						value = expression.getValue();
+		ISelection s = getView().getViewer().getSelection();
+		if (s instanceof IStructuredSelection) {
+			IStructuredSelection selection = (IStructuredSelection) s;
+			if (selection.size() == 1) {
+				Object obj = selection.getFirstElement();
+				IValue value = null;
+				if (obj instanceof IVariable) {
+					IVariable var = (IVariable) obj;
+					try {
+						value = var.getValue();
+					} catch (DebugException e) {
 					}
-					if (value != null) {
-						ILogicalStructureType[] types = DebugPlugin.getLogicalStructureTypes(value);
-						if (types.length > 0) {
-							setTypes(types);
-							setValue(value);
-							setEnabled(true);
-							return;
-						}
+				} else if (obj instanceof IExpression) {
+					IExpression expression = (IExpression) obj;
+					value = expression.getValue();
+				}
+				if (value != null) {
+					ILogicalStructureType[] types = DebugPlugin.getLogicalStructureTypes(value);
+					if (types.length > 0) {
+						setTypes(types);
+						setValue(value);
+						setEnabled(true);
+						return;
 					}
 				}
 			}
 		}
-		setEnabled(false);
 	}
 
 	protected ILogicalStructureType[] getTypes() {
diff --git a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/views/variables/EditVariableLogicalStructureAction.java b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/views/variables/EditVariableLogicalStructureAction.java
new file mode 100644
index 0000000..13fc017
--- /dev/null
+++ b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/views/variables/EditVariableLogicalStructureAction.java
@@ -0,0 +1,103 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2017 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 implementation
+ *******************************************************************************/
+package org.eclipse.debug.internal.ui.views.variables;
+
+import org.eclipse.debug.core.DebugException;
+import org.eclipse.debug.core.DebugPlugin;
+import org.eclipse.debug.core.ILogicalStructureType;
+import org.eclipse.debug.core.model.IValue;
+import org.eclipse.debug.core.model.IVariable;
+import org.eclipse.debug.internal.ui.DebugUIPlugin;
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.ui.IWorkbenchPart;
+import org.eclipse.ui.dialogs.PreferencesUtil;
+
+/**
+ * Action which prompts the user to edit the logical structure that
+ * is currently active on the given object.
+ */
+public class EditVariableLogicalStructureAction extends Action {
+
+    /**
+     * The editable structure for the currently selected variable or
+     * <code>null</code> if none.
+     */
+	private ILogicalStructureType fStructure = null;
+	private VariablesView fView = null;
+
+	public EditVariableLogicalStructureAction(VariablesView view) {
+		super();
+		fView = view;
+		ISelection selection = view.getViewer().getSelection();
+		if (selection != null) {
+			init(selection);
+		}
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * @see
+	 * org.eclipse.ui.IObjectActionDelegate#setActivePart(org.eclipse.jface.
+	 * action.IAction, org.eclipse.ui.IWorkbenchPart)
+	 */
+	public void setActivePart(IAction action, IWorkbenchPart targetPart) {
+    }
+
+    /**
+     * Prompt the user to edit the logical structure associated with the currently
+     * selected variable.
+     */
+	@Override
+	public void run() {
+		PreferencesUtil.createPreferenceDialogOn(DebugUIPlugin.getShell(), "org.eclipse.jdt.debug.ui.JavaLogicalStructuresPreferencePage", //$NON-NLS-1$
+				new String[] { "org.eclipse.jdt.debug.ui.JavaDetailFormattersPreferencePage", //$NON-NLS-1$
+						"org.eclipse.jdt.debug.ui.JavaLogicalStructuresPreferencePage", //$NON-NLS-1$
+						"org.eclipse.jdt.debug.ui.heapWalking", //$NON-NLS-1$
+						"org.eclipse.jdt.debug.ui.JavaPrimitivesPreferencePage" }, (fStructure != null) //$NON-NLS-1$
+								? fStructure.getId() + fStructure.getDescription() + fStructure.hashCode()
+								: null).open();
+    }
+
+	private void init(ISelection selection) {
+        fStructure= null;
+        Object element = ((IStructuredSelection) selection).getFirstElement();
+        if (element instanceof IVariable) {
+            try {
+                IValue value= ((IVariable) element).getValue();
+                ILogicalStructureType type= getLogicalStructure(value);
+				fStructure = type;
+            } catch (DebugException e) {
+				DebugUIPlugin.log(e.getStatus());
+            }
+        }
+		setEnabled(fView.isShowLogicalStructure());
+    }
+
+    /**
+     * Returns the logical structure currently associated with the given
+     * value or <code>null</code> if none.
+     * @param value the value
+     * @return the logical structure currently associated with the given
+     *  value or <code>null</code> if none.
+     */
+	private ILogicalStructureType getLogicalStructure(IValue value) {
+        // This code is based on VariablesViewContentProvider#getLogicalValue(IValue)
+        ILogicalStructureType type = null;
+        ILogicalStructureType[] types = DebugPlugin.getLogicalStructureTypes(value);
+        if (types.length > 0) {
+            type= DebugPlugin.getDefaultStructureType(types);
+        }
+        return type;
+    }
+}
diff --git a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/views/variables/SelectLogicalStructureAction.java b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/views/variables/SelectLogicalStructureAction.java
index a33395d..6870e23 100644
--- a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/views/variables/SelectLogicalStructureAction.java
+++ b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/views/variables/SelectLogicalStructureAction.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * Copyright (c) 2000, 2017 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
@@ -60,9 +60,12 @@
                 // Checking this action sets the type to fType, unchecking it sets the type
                 // to null ("none selected")
                 ILogicalStructureType type= null;
+				IAction action = getView().getAction("ToggleContentProviders"); //$NON-NLS-1$
                 if (isChecked()) {
                     type= fType;
+					action.setChecked(true);
                 }
+				action.run();
                 DebugPlugin.setDefaultStructureType(fAvailableTypes, type);
 				getView().getViewer().refresh();
 			}
diff --git a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/views/variables/ToggleLogicalStructureAction.java b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/views/variables/ToggleLogicalStructureAction.java
index 2ddd2e8..504a1fd 100644
--- a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/views/variables/ToggleLogicalStructureAction.java
+++ b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/views/variables/ToggleLogicalStructureAction.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2006 IBM Corporation and others.
+ * Copyright (c) 2000, 2017 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
@@ -28,6 +28,7 @@
 public class ToggleLogicalStructureAction extends Action {
 
 	private VariablesView fView;
+	public static String ID = DebugUIPlugin.getUniqueIdentifier() + ".ToggleObjectBrowsersAction"; //$NON-NLS-1$
 
 	public ToggleLogicalStructureAction(VariablesView view) {
 		super(null, IAction.AS_CHECK_BOX);
@@ -36,7 +37,8 @@
 		setHoverImageDescriptor(DebugPluginImages.getImageDescriptor(IInternalDebugUIConstants.IMG_LCL_SHOW_LOGICAL_STRUCTURE));
 		setDisabledImageDescriptor(DebugPluginImages.getImageDescriptor(IInternalDebugUIConstants.IMG_DLCL_SHOW_LOGICAL_STRUCTURE));
 		setImageDescriptor(DebugPluginImages.getImageDescriptor(IInternalDebugUIConstants.IMG_ELCL_SHOW_LOGICAL_STRUCTURE));
-		setId(DebugUIPlugin.getUniqueIdentifier() + ".ToggleObjectBrowsersAction"); //$NON-NLS-1$
+		setId(ID);
+		view.storeDefaultPreference(this, Boolean.TRUE);
 		PlatformUI.getWorkbench().getHelpSystem().setHelp(this, IDebugHelpContextIds.VARIABLES_CONTENT_PROVIDERS_ACTION);
 	}
 
diff --git a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/views/variables/VariablesView.java b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/views/variables/VariablesView.java
index ad267f2..506f5fa 100644
--- a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/views/variables/VariablesView.java
+++ b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/views/variables/VariablesView.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- *  Copyright (c) 2000, 2016 IBM Corporation and others.
+ *  Copyright (c) 2000, 2017 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
@@ -73,6 +73,7 @@
 import org.eclipse.debug.ui.contexts.DebugContextEvent;
 import org.eclipse.debug.ui.contexts.IDebugContextListener;
 import org.eclipse.debug.ui.contexts.IDebugContextService;
+import org.eclipse.jface.action.Action;
 import org.eclipse.jface.action.IAction;
 import org.eclipse.jface.action.IMenuListener;
 import org.eclipse.jface.action.IMenuManager;
@@ -1607,4 +1608,20 @@
 	public int promptToSaveOnClose() {
 		return ISaveablePart2.YES;
 	}
+
+	/**
+	 * Stores the default value for the generated String that can be used as a
+	 * key into a preference store based on the specified action.
+	 *
+	 * @param action the action to store a default value
+	 * @param value the default value for action
+	 *
+	 */
+	void storeDefaultPreference(Action action, Object value) {
+		if (value instanceof Boolean) {
+			getPreferenceStore().setDefault(generatePreferenceKey(action), (Boolean)value);
+		} else if (value instanceof String) {
+			getPreferenceStore().setDefault(generatePreferenceKey(action), (String) value);
+		}
+	}
 }
diff --git a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/views/variables/VariablesViewMessages.java b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/views/variables/VariablesViewMessages.java
index 3929a89..62289a1 100644
--- a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/views/variables/VariablesViewMessages.java
+++ b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/views/variables/VariablesViewMessages.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- *  Copyright (c) 2000, 2009 IBM Corporation and others.
+ *  Copyright (c) 2000, 2017 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
@@ -26,6 +26,8 @@
 
 	public static String AvailableLogicalStructuresAction_0;
 	public static String AvailableLogicalStructuresAction_1;
+	public static String AvailableLogicalStructuresAction_2;
+	public static String AvailableLogicalStructuresAction_3;
 
 	static {
 		// load message values from bundle file
diff --git a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/views/variables/VariablesViewMessages.properties b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/views/variables/VariablesViewMessages.properties
index 162fe53..5a136bb 100644
--- a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/views/variables/VariablesViewMessages.properties
+++ b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/views/variables/VariablesViewMessages.properties
@@ -1,5 +1,5 @@
 ###############################################################################
-# Copyright (c) 2000, 2010 IBM Corporation and others.
+# Copyright (c) 2000, 2017 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
@@ -17,7 +17,9 @@
 ExpressionView_4=Expressions View &Only
 
 AvailableLogicalStructuresAction_0=Select From Available Logical Structures
-AvailableLogicalStructuresAction_1=&Show Structure As
+AvailableLogicalStructuresAction_1=&Show Logical Structure
+AvailableLogicalStructuresAction_2=(Last used)
+AvailableLogicalStructuresAction_3=&Edit Logical Structure...
 DetailPaneMaxLengthDialog_0=Configure Details Pane
 DetailPaneMaxLengthDialog_1=&Maximum characters to display in details pane (0 = unlimited):
 DetailPaneMaxLengthDialog_2=Integer must be non-negative