/******************************************************************************
* Copyright (c) 2005, 2006 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 de.tud.cs.st.vespucci.vespucci_model.diagram.sheet;
import java.util.ArrayList;
import java.util.Iterator;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.gmf.runtime.common.core.command.ICommand;
import org.eclipse.gmf.runtime.common.core.util.StringStatics;
import org.eclipse.gmf.runtime.common.ui.util.StatusLineUtil;
import org.eclipse.gmf.runtime.diagram.ui.properties.sections.AbstractModelerPropertySection;
import org.eclipse.gmf.runtime.diagram.ui.properties.views.TextChangeHelper;
import org.eclipse.jdt.ui.PreferenceConstants;
import org.eclipse.jface.preference.PreferenceConverter;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.ScrolledComposite;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.layout.FormAttachment;
import org.eclipse.swt.layout.FormData;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.editors.text.EditorsUI;
import org.eclipse.ui.texteditor.AbstractTextEditor;
import org.eclipse.ui.views.properties.tabbed.TabbedPropertySheetPage;
/**
* A Changed Copy of AbstractBasicTextPropertySection (org.eclipse.gmf.runtime.diagram
* .ui.properties.sections.AbstractBasicTextPropertySection)
*
*
*
* Original version by:
*
* @author natalia balaba
*
* Changed by:
* @author Malte Viering
* @author Benjamin Lück
* @author Dominic Scheurer
* @author Alexander Weitzmann
* @author Theo Kischka
*/
public abstract class SimpleChangedAbstractBasicTextPropertySection extends AbstractModelerPropertySection {
private static final int DESCRIPTION_TAB_HEIGHT_SHIFT = 25;
private static final int DESCRIPTION_TAB_WIDTH_SHIFT = 32;
// styled text widget to display and set value of the property
private StyledText textWidget;
// parent parent ... parent composite for the size of the textfield
private Composite scrolledParent;
private Composite sectionComposite;
private final int startHeight = 15;
Listener resizeLinstener = new Listener() {
@Override
public void handleEvent(final Event e) {
updateHeight();
scrolledParent.getVerticalBar().setVisible(false);
scrolledParent.getHorizontalBar().setVisible(false);
}
};
/**
* A helper to listen for events that indicate that a text field has been changed.
*/
private final TextChangeHelper listener = new TextChangeHelper() {
private boolean textModified = false;
/**
* Pattern to be used to match strings in query including the single quotes
*/
private static final String STRING_PATTERN = "'.+?'";
/**
* @see org.eclipse.swt.widgets.Listener#handleEvent(org.eclipse.swt.widgets.Event)
*/
@Override
public void handleEvent(final Event event) {
switch (event.type) {
case SWT.KeyDown:
textModified = true;
if (event.character == SWT.CR) {
getPropertyValueString();
}
break;
case SWT.FocusOut:
textChanged((Control) event.widget);
break;
case SWT.FocusIn:
textChanged((Control) event.widget);
break;
case SWT.MouseDown:
break;
default:
break;
}
}
@Override
public void startListeningTo(final Control control) {
control.addListener(SWT.FocusOut, this);
control.addListener(SWT.Modify, this);
control.addListener(SWT.FocusIn, this);
control.addListener(SWT.MouseDown, this);
}
@Override
public void textChanged(final Control control) {
if (textModified) {
// clear error message
final IWorkbenchPart part = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().getActivePart();
StatusLineUtil.outputErrorMessage(part, StringStatics.BLANK);
setPropertyValue(control);
textModified = false;
}
}
};
/**
* @return - the default implementation returns contents of the text widget as a new value for
* the property. Subclasses can
* could be override.
*/
protected final Object computeNewPropertyValue() {
return getTextWidget().getText();
}
/*
* (non-Javadoc)
* @see org.eclipse.ui.views.properties.tabbed.ISection#createControls(org.eclipse
* .swt.widgets.Composite,
* org.eclipse.ui.views.properties.tabbed.TabbedPropertySheetPage)
*/
@Override
public final void createControls(final Composite parent, final TabbedPropertySheetPage aTabbedPropertySheetPage) {
doCreateControls(parent, aTabbedPropertySheetPage);
}
/**
* Instantiate a text widget
*
* @param parent
* - parent composite
* @return - a text widget to display and edit the property
*/
protected final StyledText createTextWidget(final Composite parent) {
getSectionComposite().getSize();
final StyledText st = new StyledText(parent, SWT.MULTI | SWT.V_SCROLL | SWT.H_SCROLL);
final Font userFont = JFaceResources.getFont(PreferenceConstants.EDITOR_TEXT_FONT);
st.setFont(userFont);
final FormData data = new FormData();
data.left = new FormAttachment(0, 0);
data.right = new FormAttachment(100, 0);
data.top = new FormAttachment(0, 0);
data.height = startHeight;
st.setLayoutData(data);
st.setBackground(EditorsUI.getSharedTextColors().getColor(
PreferenceConverter.getColor(EditorsUI.getPreferenceStore(), AbstractTextEditor.PREFERENCE_COLOR_BACKGROUND)));
if (isReadOnly()) {
st.setEditable(false);
}
return st;
}
/*
* (non-Javadoc)
* @see org.eclipse.ui.views.properties.tabbed.ISection#dispose()
*/
@Override
public final void dispose() {
stopTextWidgetEventListener();
super.dispose();
}
/**
* Creates the GUI <code>Control</code> for this text property section
*
* @param parent
* parent <code>Composite</code>
* @param aTabbedPropertySheetPage
* <code>TabbedPropertySheetPage</code>
* @see org.eclipse.gmf.runtime.common.ui.properties.ISection#createControls(org.eclipse.swt.widgets.Composite,
* org.eclipse.gmf.runtime.common.ui.properties.TabbedPropertySheetPage)
*/
public final void doCreateControls(final Composite parent, final TabbedPropertySheetPage aTabbedPropertySheetPage) {
super.createControls(parent, aTabbedPropertySheetPage);
sectionComposite = getWidgetFactory().createFlatFormComposite(parent);
textWidget = createTextWidget(sectionComposite);
scrolledParent = parent;
while (true) {
// TODO: There must be a nicer way for redraw the text widget then
// to say the first scrolledcomposite .layout()
// the scrolledParent should be "main" composite for the query tab
if (scrolledParent instanceof ScrolledComposite) {
break;
}
if (scrolledParent.getParent() == null) {
break;
}
scrolledParent = scrolledParent.getParent();
}
scrolledParent.addListener(SWT.Resize, resizeLinstener);
updateHeight();
startTextWidgetEventListener();
}
private int getHeight() {
return scrolledParent.getSize().y - DESCRIPTION_TAB_HEIGHT_SHIFT;
}
/**
* @return Returns the listener.
*/
protected final TextChangeHelper getListener() {
return listener;
}
/**
* @return - title of the command which will be executed to set the property
*/
protected abstract String getPropertyChangeCommandName();
/**
* @return - name of the property to place in the label widget
*/
protected abstract String getPropertyNameLabel();
/**
* returns as an array the property name
*
* @return - array of strings where each describes a property name one per property. The strings
* will be used to calculate
* common indent from the left
*/
protected final String[] getPropertyNameStringsArray() {
return new String[] { getPropertyNameLabel() };
}
/**
* @return - string representation of the property value
*/
protected abstract String getPropertyValueString();
/**
* @return Returns the sectionComposite.
*/
public final Composite getSectionComposite() {
return sectionComposite;
}
/**
* @return Returns the textWidget.
*/
protected final StyledText getTextWidget() {
return textWidget;
}
private int getWidth() {
return scrolledParent.getSize().x - DESCRIPTION_TAB_WIDTH_SHIFT;
}
/*
* (non-Javadoc)
* @see org.eclipse.ui.views.properties.tabbed.ISection#refresh()
*/
@Override
public final void refresh() {
getListener().startNonUserChange();
try {
executeAsReadAction(new Runnable() {
@Override
public void run() {
refreshUI();
}
});
} finally {
getListener().finishNonUserChange();
}
}
/**
* Refresh UI body - refresh will surround this with read action block
*/
protected final void refreshUI() {
if (textWidget != null) {
textWidget.setText(getPropertyValueString());
}
}
/**
* User pressed Enter key after editing text field - update the model
*
* @param control
* <code>Control</code>
*/
protected final synchronized void setPropertyValue(final Control control) {
final Object value = computeNewPropertyValue();
final ArrayList<ICommand> commands = new ArrayList<ICommand>();
for (final Iterator<?> it = getEObjectList().iterator(); it.hasNext();) {
final EObject next = (EObject) it.next();
commands.add(createCommand(getPropertyChangeCommandName(), next, new Runnable() {
@Override
public void run() {
setPropertyValue(next, value);
}
}));
}
executeAsCompositeCommand(getPropertyChangeCommandName(), commands);
refresh();
}
/**
* Set property value for the given object
*
* @param object
* - owner of the property
* @param value
* - new value
*/
protected abstract void setPropertyValue(EObject object, Object value);
public final void setScrolledParent(final Composite scrolledParent) {
this.scrolledParent = scrolledParent;
}
/**
* Start listening to the text widget events
*/
protected final void startTextWidgetEventListener() {
if (!isReadOnly()) {
getListener().startListeningTo(getTextWidget());
getListener().startListeningForEnter(getTextWidget());
}
}
/**
* Stop listening to text widget events
*/
protected final void stopTextWidgetEventListener() {
if (!isReadOnly()) {
getListener().stopListeningTo(getTextWidget());
}
}
/**
* calculates the new size of the widget and updates it
*/
private void updateHeight() {
if (getTextWidget() != null && !getTextWidget().isDisposed()) {
getTextWidget().setVisible(false);
scrolledParent.setVisible(false);
final FormData data = new FormData();
data.left = new FormAttachment(0, 0);
data.right = new FormAttachment(100, 0);
data.top = new FormAttachment(0, 0);
data.height = getHeight();
data.width = getWidth();
getTextWidget().setLayoutData(data);
final int HEIGHTS_SCROLLLINE = 30;
Composite com = getSectionComposite();
// TODO: there must be a nice way to update the heights and widths
// of the textwidget and its parents
while (true) {
if (com instanceof ScrolledComposite) {
break;
}
if (com.getParent() == null) {
break;
}
com.setSize(getWidth(), getHeight() + HEIGHTS_SCROLLLINE);
com = com.getParent();
}
com.layout();
getTextWidget().setVisible(true);
scrolledParent.setVisible(true);
}
}
}