/**
* This file Copyright (c) 2005-2008 Aptana, Inc. This program is
* dual-licensed under both the Aptana Public License and the GNU General
* Public license. You may elect to use one or the other of these licenses.
*
* This program is distributed in the hope that it will be useful, but
* AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
* NONINFRINGEMENT. Redistribution, except as permitted by whichever of
* the GPL or APL you select, is prohibited.
*
* 1. For the GPL license (GPL), you can redistribute and/or modify this
* program under the terms of the GNU General Public License,
* Version 3, as published by the Free Software Foundation. You should
* have received a copy of the GNU General Public License, Version 3 along
* with this program; if not, write to the Free Software Foundation, Inc., 51
* Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Aptana provides a special exception to allow redistribution of this file
* with certain other free and open source software ("FOSS") code and certain additional terms
* pursuant to Section 7 of the GPL. You may view the exception and these
* terms on the web at http://www.aptana.com/legal/gpl/.
*
* 2. For the Aptana Public License (APL), this program and the
* accompanying materials are made available under the terms of the APL
* v1.0 which accompanies this distribution, and is available at
* http://www.aptana.com/legal/apl/.
*
* You may view the GPL, Aptana's exception and additional terms, and the
* APL in the file titled license.html at the root of the corresponding
* plugin containing this source file.
*
* Any modifications to this file must keep this entire header intact.
*/
package com.aptana.ide.debug.internal.ui.preferences;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.jface.layout.GridLayoutFactory;
import org.eclipse.jface.preference.PreferencePage;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.text.Document;
import org.eclipse.jface.text.source.SourceViewer;
import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.CheckStateChangedEvent;
import org.eclipse.jface.viewers.CheckboxTableViewer;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.ICheckStateListener;
import org.eclipse.jface.viewers.IDoubleClickListener;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.window.Window;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.KeyAdapter;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Table;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchPreferencePage;
import org.eclipse.ui.PlatformUI;
import com.aptana.ide.core.StringUtils;
import com.aptana.ide.debug.core.DetailFormatter;
import com.aptana.ide.debug.core.JSDetailFormattersManager;
import com.aptana.ide.debug.internal.ui.IDebugHelpContextIds;
import com.aptana.ide.debug.internal.ui.IDebugUIConstants;
import com.aptana.ide.debug.internal.ui.dialogs.DetailFormatterDialog;
import com.aptana.ide.debug.ui.DebugUiPlugin;
/**
* @author Max Stepanov
*/
public class JSDetailFormattersPreferencePage extends PreferencePage implements IWorkbenchPreferencePage
{
private Label listLabel;
private Button addFormatterButton;
private Button removeFormatterButton;
private Button editFormatterButton;
private Button inlineButton;
private Button inlineAllButton;
private CheckboxTableViewer listViewer;
private SourceViewer sourceViewer;
private List<String> types;
private Set<DetailFormatter> formatters;
/**
* JSDetailFormattersPreferencePage
*/
public JSDetailFormattersPreferencePage()
{
super();
setTitle(Messages.JSDetailFormattersPreferencePage_DetailFormatters);
setPreferenceStore(DebugUiPlugin.getDefault().getPreferenceStore());
setDescription(Messages.JSDetailFormattersPreferencePage_OverrideDefault);
}
protected Control createContents(Composite parent)
{
initializeDialogUnits(parent);
Composite composite = new Composite(parent, SWT.NONE);
composite.setLayout(GridLayoutFactory.swtDefaults().numColumns(2).margins(0, 0).create());
GridDataFactory.fillDefaults().applyTo(composite);
composite.setFont(parent.getFont());
createFormattersList(composite);
createOptions(composite);
Dialog.applyDialogFont(composite);
noDefaultAndApplyButton();
PlatformUI.getWorkbench().getHelpSystem().setHelp(getControl(),
IDebugHelpContextIds.JS_DETAIL_FORMATTER_PREFERENCE_PAGE);
return composite;
}
public void init(IWorkbench workbench)
{
}
private void createOptions(Composite parent)
{
Group group = new Group(parent, SWT.NONE);
group.setText(Messages.JSDetailFormattersPreferencePage_ShowVariableDetails);
GridDataFactory.fillDefaults().span(2, 1).applyTo(group);
group.setLayout(new GridLayout());
String preference = getPreferenceStore().getString(IDebugUIConstants.PREF_SHOW_DETAILS);
inlineButton = new Button(group, SWT.RADIO);
inlineButton.setText(Messages.JSDetailFormattersPreferencePage_AsLabelForVariablesWithDetailFormatters);
inlineButton.setSelection(preference.equals(IDebugUIConstants.INLINE_FORMATTERS));
inlineAllButton = new Button(group, SWT.RADIO);
inlineAllButton.setText(Messages.JSDetailFormattersPreferencePage_AsLabelForAllVariables);
inlineAllButton.setSelection(preference.equals(IDebugUIConstants.INLINE_ALL));
Button detailPane = new Button(group, SWT.RADIO);
detailPane.setText(Messages.JSDetailFormattersPreferencePage_InDetailPaneOnly);
detailPane.setSelection(preference.equals(IDebugUIConstants.DETAIL_PANE) || preference.length() == 0);
}
private Control createFormattersList(Composite parent)
{
Font font = parent.getFont();
listLabel = new Label(parent, SWT.NONE);
listLabel.setText(Messages.JSDetailFormattersPreferencePage_TypesWithDetailFormatters);
GridDataFactory.swtDefaults().span(2, 1).applyTo(listLabel);
listLabel.setFont(font);
listViewer = CheckboxTableViewer.newCheckList(parent, SWT.CHECK | SWT.FULL_SELECTION | SWT.MULTI | SWT.BORDER);
Table table = (Table) listViewer.getControl();
GridDataFactory.fillDefaults().grab(true, true)
.hint(convertWidthInCharsToPixels(10), SWT.DEFAULT).applyTo(table);
table.setFont(font);
listViewer.setContentProvider(new ArrayContentProvider());
listViewer.setLabelProvider(new LabelProvider()
{
public String getText(Object element)
{
if (element instanceof DetailFormatter)
{
return ((DetailFormatter) element).getTypeName();
}
return null;
}
});
// button container
Composite composite = new Composite(parent, SWT.NONE);
GridDataFactory.fillDefaults().grab(false, true).applyTo(composite);
composite.setLayout(GridLayoutFactory.fillDefaults().create());
// Add button
addFormatterButton = new Button(composite, SWT.PUSH);
addFormatterButton.setText(StringUtils.ellipsify(Messages.JSDetailFormattersPreferencePage_Add));
addFormatterButton.setToolTipText(Messages.JSDetailFormattersPreferencePage_AllowToCreateNewDetailFormatter);
setButtonLayoutData(addFormatterButton);
addFormatterButton.setFont(font);
// Edit button
editFormatterButton = new Button(composite, SWT.PUSH);
editFormatterButton.setText(StringUtils.ellipsify(Messages.JSDetailFormattersPreferencePage_Edit));
editFormatterButton.setToolTipText(Messages.JSDetailFormattersPreferencePage_EditSelectedDetailFormatter);
setButtonLayoutData(editFormatterButton);
editFormatterButton.setFont(font);
// Remove button
removeFormatterButton = new Button(composite, SWT.PUSH);
removeFormatterButton.setText(Messages.JSDetailFormattersPreferencePage_Remove);
removeFormatterButton.setToolTipText(Messages.JSDetailFormattersPreferencePage_RemoveAllSelectedDetailFormatters);
setButtonLayoutData(removeFormatterButton);
removeFormatterButton.setFont(font);
Label label = new Label(parent, SWT.NONE);
label.setText(Messages.JSDetailFormattersPreferencePage_DetailFormatterCodeSnippetDefinedForSelectedType);
GridDataFactory.fillDefaults().grab(true, false).span(2, 1).applyTo(label);
label.setFont(font);
sourceViewer = new SourceViewer(parent, null, SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL);
sourceViewer.getTextWidget().setBackground(getShell().getDisplay().getSystemColor(SWT.COLOR_WIDGET_BACKGROUND));
sourceViewer.getTextWidget().setFont(JFaceResources.getTextFont());
GridDataFactory.fillDefaults().grab(true, true).span(2, 1).applyTo(sourceViewer.getControl());
// listeners
listViewer.addSelectionChangedListener(new ISelectionChangedListener()
{
public void selectionChanged(SelectionChangedEvent event)
{
updatePage((IStructuredSelection) event.getSelection());
}
});
listViewer.addDoubleClickListener(new IDoubleClickListener()
{
public void doubleClick(DoubleClickEvent event)
{
if (!event.getSelection().isEmpty())
{
editType();
}
}
});
listViewer.addCheckStateListener(new ICheckStateListener()
{
public void checkStateChanged(CheckStateChangedEvent event)
{
((DetailFormatter) event.getElement()).setEnabled(event.getChecked());
}
});
table.addKeyListener(new KeyAdapter()
{
public void keyPressed(KeyEvent event)
{
if (event.character == SWT.DEL && event.stateMask == 0)
{
removeTypes();
}
}
});
addFormatterButton.addListener(SWT.Selection, new Listener()
{
public void handleEvent(Event e)
{
addType();
}
});
editFormatterButton.addListener(SWT.Selection, new Listener()
{
public void handleEvent(Event e)
{
editType();
}
});
removeFormatterButton.addListener(SWT.Selection, new Listener()
{
public void handleEvent(Event e)
{
removeTypes();
}
});
editFormatterButton.setEnabled(false);
removeFormatterButton.setEnabled(false);
sourceViewer.setEditable(false);
sourceViewer.setDocument(new Document());
loadDetailFormatters();
listViewer.setInput(formatters);
updateViewerCheckboxes();
return parent;
}
private void updatePage(IStructuredSelection selection)
{
removeFormatterButton.setEnabled(!selection.isEmpty());
editFormatterButton.setEnabled(selection.size() == 1);
sourceViewer.getDocument().set(selection.size() == 1
? ((DetailFormatter) selection.getFirstElement()).getSnippet()
: StringUtils.EMPTY);
}
private void addType()
{
DetailFormatter detailFormatfer = new DetailFormatter(StringUtils.EMPTY, StringUtils.EMPTY, true);
DetailFormatterDialog dlg = new DetailFormatterDialog(getShell(), detailFormatfer, types, false);
if (dlg.open() == Window.OK)
{
addDetailFormatter(detailFormatfer);
}
}
private void removeTypes()
{
Object[] list = formatters.toArray();
IStructuredSelection selection = (IStructuredSelection) listViewer.getSelection();
Object first = selection.getFirstElement();
int index = -1;
for (int i = 0; i < list.length; i++)
{
if (list[i].equals(first))
{
index = i;
break;
}
}
removeDetailFormatters(selection.toArray());
list = formatters.toArray();
if (index > list.length - 1)
{
index = list.length - 1;
}
if (index >= 0)
{
listViewer.setSelection(new StructuredSelection(list[index]));
}
}
private void editType()
{
IStructuredSelection selection = (IStructuredSelection) listViewer.getSelection();
DetailFormatterDialog dlg = new DetailFormatterDialog(getShell(), (DetailFormatter) (selection).getFirstElement(), null, true, true);
if (dlg.open() == Window.OK)
{
listViewer.refresh();
updateViewerCheckboxes();
updatePage(selection);
}
}
public boolean performOk()
{
JSDetailFormattersManager.getDefault().setDetailFormatters(formatters);
String value = IDebugUIConstants.DETAIL_PANE;
if (inlineAllButton.getSelection())
{
value = IDebugUIConstants.INLINE_ALL;
}
else if (inlineButton.getSelection())
{
value = IDebugUIConstants.INLINE_FORMATTERS;
}
getPreferenceStore().setValue(IDebugUIConstants.PREF_SHOW_DETAILS, value);
DebugUiPlugin.getDefault().savePluginPreferences();
return true;
}
private void updateViewerCheckboxes()
{
DetailFormatter[] checkedElementsTmp = new DetailFormatter[formatters.size()];
int i = 0;
for (Iterator iter = formatters.iterator(); iter.hasNext();)
{
DetailFormatter detailFormatter = (DetailFormatter) iter.next();
if (detailFormatter.isEnabled())
{
checkedElementsTmp[i++] = detailFormatter;
}
}
DetailFormatter[] checkedElements = new DetailFormatter[i];
System.arraycopy(checkedElementsTmp, 0, checkedElements, 0, i);
listViewer.setAllChecked(false);
listViewer.setCheckedElements(checkedElements);
}
private void addDetailFormatter(DetailFormatter detailFormatter)
{
formatters.add(detailFormatter);
types.add(detailFormatter.getTypeName());
listViewer.refresh();
updateViewerCheckboxes();
IStructuredSelection selection = new StructuredSelection(detailFormatter);
listViewer.setSelection(selection);
updatePage(selection);
}
private void removeDetailFormatters(Object[] detailFormatters)
{
for (int i = 0; i < detailFormatters.length; ++i)
{
formatters.remove(detailFormatters[i]);
types.remove(((DetailFormatter) detailFormatters[i]).getTypeName());
}
listViewer.refresh();
listViewer.setSelection(StructuredSelection.EMPTY);
updatePage(StructuredSelection.EMPTY);
}
private void loadDetailFormatters()
{
formatters = new TreeSet<DetailFormatter>();
Collection detailFormatters = JSDetailFormattersManager.getDefault().getDetailFormatters();
types = new ArrayList<String>(detailFormatters.size());
for (Iterator i = detailFormatters.iterator(); i.hasNext();)
{
DetailFormatter detailFormatter = (DetailFormatter) i.next();
formatters.add(detailFormatter);
types.add(detailFormatter.getTypeName());
}
}
}