/*******************************************************************************
* Copyright (C) 2003-2004, 2013, Guillaume Brocker
*
* 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:
* Guillaume Brocker - Initial API and implementation
*
******************************************************************************/
package eclox.ui.editor.advanced;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.resource.FontRegistry;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.forms.IDetailsPage;
import org.eclipse.ui.forms.IFormPart;
import org.eclipse.ui.forms.IManagedForm;
import org.eclipse.ui.forms.events.HyperlinkEvent;
import org.eclipse.ui.forms.events.IHyperlinkListener;
import org.eclipse.ui.forms.widgets.FormText;
import org.eclipse.ui.forms.widgets.FormToolkit;
import org.eclipse.ui.forms.widgets.Section;
import eclox.core.doxyfiles.Doxyfile;
import eclox.core.doxyfiles.Setting;
import eclox.ui.Plugin;
import eclox.ui.editor.editors.SettingEditor;
/**
* Implements the generic details node page.
*
* @author gbrocker
*/
public class DetailsPage implements IDetailsPage {
/** symbolic name for emphasis font */
private static final String EMPHASIS = "em";
/** the static setting editor class register */
private static EditorClassRegister editorClassRegister = new EditorClassRegister();
/** the setting editor instance */
private SettingEditor editor;
/** the section that contains all our controls */
private Section section;
/** he editor content container widget */
private Composite editorContainer;
/** the control containing all controls of the section */
private Composite sectionContent;
/** the managed form the page is attached to */
protected IManagedForm managedForm;
/** the current selection */
private NavigableSelection selection = new NavigableSelection();
/** the control displaying the setting's note text */
private FormText noteLabel;
/** the font registry used for note text formatting */
private FontRegistry fontRegistry;
/**
* Defines the listeners that will managed activation of hyper-links in the
* setting's note.
*/
private class MyHyperlinkListener implements IHyperlinkListener {
private DetailsPage owner;
/**
* Constructor
*
* @param owner the owner of the instance
*/
MyHyperlinkListener( DetailsPage owner ) {
this.owner = owner;
}
/**
* @see org.eclipse.ui.forms.events.IHyperlinkListener#linkActivated(org.eclipse.ui.forms.events.HyperlinkEvent)
*/
public void linkActivated(HyperlinkEvent e) {
// Pre-condition
assert editor != null;
Doxyfile doxyfile = editor.getInput().getOwner();
Setting setting = doxyfile.getSetting( e.getHref().toString() );
if( setting != null ) {
managedForm.fireSelectionChanged( owner, selection.select(setting) );
}
}
/**
* @see org.eclipse.ui.forms.events.IHyperlinkListener#linkEntered(org.eclipse.ui.forms.events.HyperlinkEvent)
*/
public void linkEntered(HyperlinkEvent e) {}
/**
* @see org.eclipse.ui.forms.events.IHyperlinkListener#linkExited(org.eclipse.ui.forms.events.HyperlinkEvent)
*/
public void linkExited(HyperlinkEvent e) {}
}
/**
* @see org.eclipse.ui.forms.IDetailsPage#createContents(org.eclipse.swt.widgets.Composite)
*/
public void createContents(Composite parent) {
FormToolkit toolkit = this.managedForm.getToolkit();
fontRegistry = new FontRegistry(parent.getDisplay());
// Initializes the parent control.
parent.setLayout(new FillLayout());
// Creates the section
this.section = toolkit.createSection(parent, Section.TITLE_BAR);
this.section.marginHeight = 5;
this.section.marginWidth = 10;
// Createst the section content and its layout
this.sectionContent = toolkit.createComposite(section);
this.section.setClient(this.sectionContent);
GridLayout layout = new GridLayout(1, true);
layout.marginWidth = 0;
layout.marginHeight = 0;
this.sectionContent.setLayout(layout);
// Creates the editor content.
this.editorContainer = managedForm.getToolkit().createComposite(sectionContent);
this.editorContainer.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
// Creates controls displaying the setting note.
this.noteLabel = this.managedForm.getToolkit().createFormText( sectionContent, false );
this.noteLabel.setLayoutData( new GridData(GridData.FILL_HORIZONTAL) );
this.noteLabel.setFont( EMPHASIS, fontRegistry.getItalic("") );
this.noteLabel.addHyperlinkListener( new MyHyperlinkListener(this) );
}
/**
* @see org.eclipse.ui.forms.IFormPart#commit(boolean)
*/
public void commit(boolean onSave) {
if( editor != null ) {
editor.commit();
}
}
/**
* @see org.eclipse.ui.forms.IFormPart#dispose()
*/
public void dispose() {}
/**
* @see org.eclipse.ui.forms.IFormPart#initialize(org.eclipse.ui.forms.IManagedForm)
*/
public void initialize(IManagedForm form) {
this.managedForm = form;
}
/**
* @see org.eclipse.ui.forms.IFormPart#isDirty()
*/
public boolean isDirty() {
return editor != null ? editor.isDirty() : false;
}
/**
* @see org.eclipse.ui.forms.IFormPart#isStale()
*/
public boolean isStale() {
return editor != null ? editor.isStale() : false;
}
/**
* @see org.eclipse.ui.forms.IFormPart#refresh()
*/
public void refresh() {
if( editor != null ) {
editor.refresh();
}
}
/**
* @see org.eclipse.ui.forms.IFormPart#setFocus()
*/
public void setFocus() {
// Pre-condition
assert this.editor != null;
this.editor.setFocus();
}
/**
* @see org.eclipse.ui.forms.IFormPart#setFormInput(java.lang.Object)
*/
public boolean setFormInput(Object input) {
return false;
}
/**
* @see org.eclipse.ui.forms.IPartSelectionListener#selectionChanged(org.eclipse.ui.forms.IFormPart, org.eclipse.jface.viewers.ISelection)
*/
public void selectionChanged(IFormPart part, ISelection newSelection) {
// Pre-condition
assert (newSelection instanceof NavigableSelection);
// Retreieves the node that is provided by the selection.
/*if( part != this )*/ {
selection = (NavigableSelection) newSelection;
Object object = selection.getFirstElement();
Setting setting = (object instanceof Setting) ? (Setting) object : null;
String text = setting.getProperty(Setting.TEXT);
// Checks that the setting has a text property.
if( text == null ) {
Plugin.log(setting.getIdentifier() + ": missing TEXT property.");
text = new String(setting.getIdentifier());
}
// Updates the form controls.
this.selectNote(setting);
this.selectEditor(setting);
this.section.setText( text );
this.section.layout(true, true);
}
}
/**
* Disposes the current editor.
*/
private void disposeEditor() {
if(editor != null) {
editor.dispose();
editor = null;
}
}
/**
* Selects the editor for the specified setting.
*
* @param input the setting that is the new input
*/
private void selectEditor(Setting input) {
try {
// Retrieves the editor class for the input.
Class<?> editorClass = editorClassRegister.find(input);
// Perhaps should we remove the current editor.
if(editor != null && editor.getClass() != editorClass) {
disposeEditor();
}
// Perhaps, we should create a new editor instance.
if(editor == null) {
editor = (SettingEditor) editorClass.newInstance();
editor.createContent(editorContainer, managedForm.getToolkit());
editorContainer.setLayoutData( new GridData(editor.grabVerticalSpace() ? GridData.FILL_BOTH : GridData.FILL_HORIZONTAL) );
}
// Assigns the input to the editor.
editor.setInput(input);
editor.refresh();
}
catch(Throwable throwable) {
MessageDialog.openError(this.managedForm.getForm().getShell(), "Unexpected Error", throwable.toString());
}
}
/**
* Updates the UI controls for the specified node.
*
* @param setting a setting instance to use to refresh the UI controls.
*/
private void selectNote(Setting setting) {
// Retrieves the setting's note text.
String text = setting.getProperty( Setting.NOTE );
// If there is none, build a default one.
if(text == null) {
text = "Not available.";
}
// Else do some parsing and replacements for layout and style.
else {
Doxyfile doxyfile = setting.getOwner();
text = text.startsWith("<p>") ? text : "<p>"+text+"</p>";
Matcher matcher = Pattern.compile("([A-Z_]{2,}|Warning:|Note:|@[a-z]+)").matcher(text);
StringBuffer buffer = new StringBuffer();
while( matcher.find() ) {
String match = matcher.group(1);
if( match.equals("YES") || match.equals("NO") ) {
matcher.appendReplacement( buffer, "<span font=\""+EMPHASIS+"\">"+match+"</span>");
}
else if( match.equals("Note:") || match.equals("Warning:") ) {
matcher.appendReplacement( buffer, "<b>"+match+"</b>");
}
else if( match.startsWith("@") ) {
matcher.appendReplacement( buffer, "<span font=\""+EMPHASIS+"\">"+match+"</span>");
}
else {
Setting matchSetting = doxyfile.getSetting(match);
if( matchSetting != null ) {
String settingText = matchSetting.getProperty(Setting.TEXT);
if( matchSetting == setting ) {
matcher.appendReplacement( buffer, "<span font=\""+EMPHASIS+"\">"+settingText+"</span>");
}
else {
matcher.appendReplacement( buffer, "<a href=\""+matchSetting.getIdentifier()+"\">"+settingText+"</a>");
}
}
}
}
matcher.appendTail( buffer );
text = buffer.toString();
}
// Finally, assignes the text to the user interface control.
this.noteLabel.setText("<form>"+text+"</form>", true, false);
}
}