blob: 05602dd5529f7d0e24a0c45ad77d741dc01ee401 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2006, 2010 Soyatec (http://www.soyatec.com) 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:
* Soyatec - initial API and implementation
*******************************************************************************/
package org.eclipse.xwt.tools.ui.designer.layouts.pages;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.xwt.IConstants;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.gef.EditPart;
import org.eclipse.gef.commands.Command;
import org.eclipse.gef.commands.CommandStack;
import org.eclipse.gef.commands.CompoundCommand;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Group;
import org.eclipse.xwt.tools.ui.designer.commands.AddNewChildCommand;
import org.eclipse.xwt.tools.ui.designer.commands.ApplyAttributeSettingCommand;
import org.eclipse.xwt.tools.ui.designer.commands.DeleteCommand;
import org.eclipse.xwt.tools.ui.designer.core.editor.EditDomain;
import org.eclipse.xwt.tools.ui.designer.layouts.control.CheckBoxFieldEditor;
import org.eclipse.xwt.tools.ui.designer.layouts.control.FieldEditor;
import org.eclipse.xwt.tools.ui.designer.layouts.control.FieldEditorEvent;
import org.eclipse.xwt.tools.ui.designer.layouts.control.FieldEditorListener;
import org.eclipse.xwt.tools.ui.designer.layouts.control.RadioGroupFieldEditor;
import org.eclipse.xwt.tools.ui.designer.layouts.control.SpinnerFieldEditor;
import org.eclipse.xwt.tools.ui.designer.loader.XWTProxy;
import org.eclipse.xwt.tools.ui.designer.model.RefreshAdapter;
import org.eclipse.xwt.tools.ui.xaml.XamlAttribute;
import org.eclipse.xwt.tools.ui.xaml.XamlElement;
import org.eclipse.xwt.tools.ui.xaml.XamlNode;
/**
* @author jliu (jin.liu@soyatec.com)
*/
public abstract class AssistantPage implements IAssistantPage, FieldEditorListener {
private EditPart editPart;
private Control control;
private List<FieldEditor> editors = new ArrayList<FieldEditor>();
private XamlAttribute assistParentAttr;
private XamlElement assistModel;
private Map<FieldEditor, List<RefreshAdapter>> editor2refresher;
public void setEditPart(EditPart editPart) {
if (editPart != null && editPart != this.editPart) {
this.editPart = editPart;
}
refresh();
}
public EditPart getEditPart() {
return editPart;
}
public XamlNode getModel() {
if (editPart == null) {
return null;
}
return (XamlNode) editPart.getModel();
}
/*
* (non-Javadoc)
*
* @see org.eclipse.xwt.tools.ui.designer.layouts.pages.IAssistantPage#getControl(org.eclipse.swt.widgets.Composite)
*/
public Control getControl(Composite parent) {
if (control == null || control.isDisposed()) {
control = createControl(parent);
control.setData(this);
}
return control;
}
protected void execute(Command command) {
if (editPart == null || command == null || !command.canExecute()) {
return;
}
EditDomain editDomain = EditDomain.getEditDomain(editPart);
if (editDomain == null) {
return;
}
CommandStack commandStack = editDomain.getCommandStack();
if (commandStack == null) {
return;
}
commandStack.execute(command);
}
protected RadioGroupFieldEditor createRadio(Composite parent, String groupName, String fieldName, String[][] labelsAndValues) {
RadioGroupFieldEditor editor = new RadioGroupFieldEditor(fieldName, labelsAndValues, parent, groupName);
addEditor(editor);
return editor;
}
protected CheckBoxFieldEditor createCheckBox(Composite parent, String fieldName, String labelText) {
CheckBoxFieldEditor editor = new CheckBoxFieldEditor(fieldName, labelText, parent);
addEditor(editor);
return editor;
}
protected SpinnerFieldEditor createSpinner(Composite parent, String fieldName, String labelText) {
SpinnerFieldEditor editor = new SpinnerFieldEditor(fieldName, labelText, parent);
addEditor(editor);
return editor;
}
protected void addEditor(final FieldEditor editor) {
editor.addListener(this);
editors.add(editor);
setUpRefresher(editor);
}
protected void setUpRefresher(final FieldEditor editor) {
XamlNode model = getAssistModel();
if (model != null) {
String fieldName = editor.getFieldName();
RefreshAdapter refresher = new RefreshAdapter(model, fieldName) {
protected void performRefresh(Notification msg) {
Display display = editor.getEditor().getDisplay();
if (Display.getCurrent() == display) {
editor.apply(getAssistant());
}
else {
display.asyncExec(new Runnable() {
public void run() {
editor.apply(getAssistant());
}
});
}
}
};
getRefreshers(editor).add(refresher);
}
}
protected Group createGroup(Composite composite, String groupName, int numColumns) {
Group group = new Group(composite, SWT.NONE);
group.setText(groupName);
group.setLayout(new GridLayout(numColumns, false));
adapt(group);
return group;
}
protected Composite createComposite(Composite parent) {
Composite composite = new Composite(parent, SWT.NONE);
adapt(composite);
return composite;
}
protected void adapt(Control control) {
control.setBackground(control.getDisplay().getSystemColor(SWT.COLOR_WHITE));
}
/*
* (non-Javadoc)
*
* @see org.eclipse.xwt.tools.ui.designer.layouts.control.FieldEditor.FieldEditorListener#handleEvent(java.lang.String, java.lang.String, java.lang.String)
*/
public final void handleEvent(FieldEditorEvent event) {
FieldEditor editor = event.editor;
List<RefreshAdapter> refreshers = getRefreshers(editor);
for (RefreshAdapter refresher : refreshers) {
refresher.setRefreshRequired(false);
}
Command command = computeCommand(event);
if (command != null && command.canExecute()) {
execute(command);
}
for (RefreshAdapter refresher : refreshers) {
refresher.setRefreshRequired(true);
}
}
protected List<RefreshAdapter> getRefreshers(FieldEditor editor) {
if (editor == null) {
return Collections.emptyList();
}
if (editor2refresher == null) {
editor2refresher = new HashMap<FieldEditor, List<RefreshAdapter>>();
}
List<RefreshAdapter> result = editor2refresher.get(editor);
if (result == null) {
result = new ArrayList<RefreshAdapter>();
editor2refresher.put(editor, result);
}
return result;
}
protected Command computeCommand(FieldEditorEvent event) {
return createCommand(event.field, event.newVlaue);
}
protected Command createCommand(String attrName, String attrValue) {
CompoundCommand command = new CompoundCommand();
XamlElement assistModel = getAssistModel();
if (assistModel == null) {
return null;
}
XamlAttribute assistParent = getAssistParent();
if (assistModel.eContainer() == null) {
command.add(new AddNewChildCommand(assistParent, assistModel));
}
if (assistParent.eContainer() == null) {
command.add(new AddNewChildCommand(getModel(), assistParent));
}
command.add(new ApplyAttributeSettingCommand(assistModel, attrName, IConstants.XWT_NAMESPACE, attrValue));
return command.unwrap();
}
private XamlElement getAssistModel() {
if (assistModel == null && editPart != null) {
assistModel = createAssistModel(getModel());
}
return assistModel;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.xwt.tools.ui.designer.layouts.pages.IAssistantPage#refresh()
*/
public void refresh() {
// Clear cache models, so we can use latest ones when refreshing.
this.assistModel = null;
this.assistParentAttr = null;
apply(getAssistant());
}
protected Object getAssistant() {
XamlElement assistModel = getAssistModel();
if (assistModel == null) {
return null;
}
return XWTProxy.createValue(assistModel);
}
/*
* (non-Javadoc)
*
* @see org.eclipse.xwt.tools.ui.designer.layouts.pages.IAssistantPage#performDefault()
*/
public void performDefault() {
XamlElement assistModel = getAssistModel();
if (assistModel != null) {
execute(new DeleteCommand(assistModel.getAttributes()));
}
}
protected XamlAttribute getAssistParent() {
if (assistParentAttr == null) {
assistParentAttr = createAssistParent(getModel());
}
return assistParentAttr;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.xwt.tools.ui.designer.layouts.pages.IAssistantPage#dispose()
*/
public void dispose() {
if (control != null) {
control.dispose();
}
editPart = null;
assistParentAttr = null;
assistModel = null;
for (FieldEditor editor : editors) {
List<RefreshAdapter> list = editor2refresher.get(editor);
for (RefreshAdapter refresher : list) {
refresher.dispose();
}
}
editor2refresher.clear();
editors.clear();
}
protected void apply(Object assistant) {
for (FieldEditor fEditor : editors) {
setUpRefresher(fEditor);
fEditor.apply(assistant);
}
}
protected abstract XamlElement createAssistModel(XamlNode parent);
protected abstract XamlAttribute createAssistParent(XamlNode parent);
protected abstract Control createControl(Composite parent);
}