/*
* *****************************************************************************
* * Copyright (c) 2006-2012 XMind Ltd. and others. This file is a part of XMind
* 3. XMind releases 3 and above are dual-licensed under the Eclipse Public
* License (EPL), which is available at
* http://www.eclipse.org/legal/epl-v10.html and the GNU Lesser General Public
* License (LGPL), which is available at http://www.gnu.org/licenses/lgpl.html
* See http://www.xmind.net/license.html for details. Contributors: XMind Ltd. -
* initial API and implementation
*******************************************************************************/
package org.xmind.gef.ui.properties;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.core.runtime.Assert;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ControlEvent;
import org.eclipse.swt.events.ControlListener;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.GridData;
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.Label;
import org.eclipse.ui.forms.widgets.ScrolledForm;
import org.eclipse.ui.forms.widgets.Section;
import org.eclipse.ui.part.IPageSite;
import org.eclipse.ui.part.Page;
import org.xmind.gef.ui.editor.IGraphicalEditor;
import org.xmind.ui.forms.WidgetFactory;
public abstract class GraphicalPropertySheetPage extends Page
implements ISelectionChangedListener, IPropertyPartContainer {
protected static class SectionRec {
String id;
IPropertySectionPart section;
Section control;
boolean visible;
public SectionRec(String id, IPropertySectionPart section) {
this.id = id;
this.section = section;
}
}
private static final int DEFAULT_SECTION_WIDTH = 200;
private final IGraphicalEditor editor;
private List<SectionRec> sections = new ArrayList<SectionRec>();
private Composite composite;
private WidgetFactory widgetFactory;
private ScrolledForm form;
private Label titleBar;
private Control titleSeparator;
private String title;
public GraphicalPropertySheetPage(IGraphicalEditor editor) {
this.editor = editor;
}
public void init(IPageSite pageSite) {
super.init(pageSite);
for (SectionRec rec : sections) {
rec.section.init(this, getContributedEditor());
}
if (editor != null) {
editor.getSite().getSelectionProvider()
.addSelectionChangedListener(this);
final ISelection selection = editor.getSite().getSelectionProvider()
.getSelection();
if (selection != null && !selection.isEmpty()) {
Display.getCurrent().asyncExec(new Runnable() {
public void run() {
selectionChanged(new SelectionChangedEvent(
editor.getSite().getSelectionProvider(),
selection));
}
});
}
}
}
public IGraphicalEditor getContributedEditor() {
return editor;
}
protected void addSection(String id, IPropertySectionPart section) {
Assert.isNotNull(id);
Assert.isNotNull(section);
removeSection(id);
SectionRec rec = new SectionRec(id, section);
sections.add(rec);
section.init(this, editor);
if (form != null && !form.isDisposed()) {
createSectionControl(form.getBody(), rec);
}
}
protected void removeSection(String id) {
SectionRec rec = getRec(id);
if (rec == null)
return;
if (sections.remove(rec)) {
rec.section.dispose();
if (rec.control != null && !rec.control.isDisposed()) {
rec.control.dispose();
}
}
}
protected boolean hasSection(String id) {
return getRec(id) != null;
}
protected IPropertySectionPart getSection(String id) {
SectionRec rec = getRec(id);
return rec == null ? null : rec.section;
}
protected List<String> getSectionIds() {
ArrayList<String> list = new ArrayList<String>(sections.size());
for (SectionRec rec : sections) {
list.add(rec.id);
}
return list;
}
protected List<String> getVisibleSectionIds() {
ArrayList<String> list = new ArrayList<String>(sections.size());
for (SectionRec rec : sections) {
if (rec.visible)
list.add(rec.id);
}
return list;
}
protected boolean isSectionVisible(String id) {
SectionRec rec = getRec(id);
return rec != null && rec.visible;
}
protected void setSectionVisible(String id, boolean visible) {
SectionRec rec = getRec(id);
if (rec == null || rec.visible == visible)
return;
rec.visible = visible;
if (rec.control != null && !rec.control.isDisposed()) {
GridData gd = (GridData) rec.control.getLayoutData();
gd.exclude = !visible;
rec.control.setVisible(visible);
}
}
protected void reflow() {
if (form != null && !form.isDisposed()) {
form.reflow(true);
form.getParent().layout();
}
}
protected void moveSectionFirst(String id) {
SectionRec rec = getRec(id);
if (rec == null)
return;
moveSectionFirst(rec);
}
private void moveSectionFirst(SectionRec rec) {
if (rec.control != null && !rec.control.isDisposed()) {
rec.control.moveAbove(null);
rec.control.getParent().layout();
}
}
protected void moveSectionAfter(String id, String lastId) {
SectionRec rec = getRec(id);
if (rec == null)
return;
SectionRec lastRec = getRec(lastId);
if (lastRec == null) {
moveSectionFirst(rec);
} else {
if (rec.control != null && !rec.control.isDisposed()
&& lastRec.control != null
&& !lastRec.control.isDisposed()) {
rec.control.moveBelow(lastRec.control);
rec.control.getParent().layout();
}
}
}
private SectionRec getRec(String id) {
if (id == null)
return null;
for (SectionRec rec : sections) {
if (id.equals(rec.id))
return rec;
}
return null;
}
public void createControl(Composite parent) {
composite = new Composite(parent, SWT.NO_FOCUS);
GridLayout layout = new GridLayout(1, true);
layout.marginHeight = 0;
layout.marginWidth = 0;
layout.horizontalSpacing = 0;
layout.verticalSpacing = 0;
composite.setLayout(layout);
titleBar = new Label(composite, SWT.NONE);
titleBar.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
titleBar.setBackground(
composite.getDisplay().getSystemColor(SWT.COLOR_WHITE));
titleSeparator = new Label(composite, SWT.SEPARATOR | SWT.HORIZONTAL);
titleSeparator.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
this.widgetFactory = new WidgetFactory(composite.getDisplay());
form = widgetFactory.createScrolledForm(composite);
form.setLayoutData(new GridData(GridData.FILL_BOTH));
form.setMinWidth(DEFAULT_SECTION_WIDTH); // TODO this not working???
form.addDisposeListener(new DisposeListener() {
public void widgetDisposed(DisposeEvent e) {
if (widgetFactory != null) {
widgetFactory.dispose();
widgetFactory = null;
}
}
});
createSectionControls(form, form.getBody());
Composite internalComposite = new Composite(form.getBody(), SWT.NONE);
internalComposite.setBackground(form.getBody().getBackground());
internalComposite.setLayout(new GridLayout(1, false));
internalComposite
.setLayoutData(new GridData(SWT.FILL, SWT.BOTTOM, true, true));
createExtendSectionControls(widgetFactory, internalComposite);
form.reflow(true);
}
protected void createExtendSectionControls(WidgetFactory widgetFactory,
Composite parent) {
}
protected void createSectionControls(final ScrolledForm form,
final Composite formBody) {
GridLayout layout = new GridLayout(1, true);
formBody.setLayout(layout);
for (SectionRec rec : sections) {
createSectionControl(formBody, rec);
}
form.addControlListener(new ControlListener() {
public void controlResized(ControlEvent e) {
relayout(form, formBody);
}
public void controlMoved(ControlEvent e) {
}
});
}
private void relayout(ScrolledForm form, Composite formBody) {
Rectangle area = form.getClientArea();
GridLayout layout = (GridLayout) formBody.getLayout();
int newNumColumns = Math.max(1, area.width / DEFAULT_SECTION_WIDTH);
boolean change = newNumColumns != layout.numColumns
&& newNumColumns >= 0
&& newNumColumns <= formBody.getChildren().length;
if (change) {
layout.numColumns = newNumColumns;
formBody.layout();
}
}
private void createSectionControl(Composite parent, SectionRec rec) {
rec.control = widgetFactory.createSection(parent,
Section.TITLE_BAR | SWT.BORDER);
Composite client = widgetFactory.createComposite(rec.control,
SWT.NO_FOCUS | SWT.WRAP);
rec.control.setClient(client);
GridData data = new GridData(GridData.FILL_HORIZONTAL);
data.verticalAlignment = GridData.BEGINNING;
data.widthHint = DEFAULT_SECTION_WIDTH;
rec.control.setLayoutData(data);
rec.section.createControl(client);
rec.visible = true;
updateSectionTitle(rec);
}
public void updateSectionTitle(IPropertySectionPart section) {
SectionRec rec = findRecord(section);
if (rec != null) {
updateSectionTitle(rec);
}
}
private SectionRec findRecord(IPropertySectionPart section) {
for (SectionRec rec : sections) {
if (rec.section == section)
return rec;
}
return null;
}
private void updateSectionTitle(SectionRec rec) {
if (rec.control == null || rec.control.isDisposed())
return;
String title = rec.section.getTitle();
if (title == null) {
title = ""; //$NON-NLS-1$
}
rec.control.setText(title);
}
public Control getControl() {
return composite;
}
public void setFocus() {
if (sections.isEmpty()) {
if (form != null && !form.isDisposed())
form.setFocus();
else if (composite != null && !composite.isDisposed())
composite.setFocus();
} else {
sections.get(0).section.setFocus();
}
}
public void selectionChanged(SelectionChangedEvent event) {
ISelection selection = event.getSelection();
selectionChanged(selection);
if (composite != null && !composite.isDisposed())
composite.setRedraw(false);
setSelectionToSections(selection);
if (form != null && !form.isDisposed()) {
refresh();
}
if (composite != null && !composite.isDisposed())
composite.setRedraw(true);
}
protected abstract void selectionChanged(ISelection selection);
private void setSelectionToSections(ISelection selection) {
for (SectionRec rec : sections) {
if (rec.visible) {
rec.section.setSelection(selection);
updateSectionTitle(rec);
}
}
}
private void updateTitleBar() {
if (titleBar == null || titleBar.isDisposed())
return;
String title = getTitle();
titleBar.setText(title == null ? "" : title); //$NON-NLS-1$
setTitleVisible(title != null);
}
private void setTitleVisible(boolean visible) {
if (titleBar == null || titleBar.isDisposed())
return;
if (titleBar.getVisible() == visible)
return;
titleBar.setVisible(visible);
((GridData) titleBar.getLayoutData()).exclude = !visible;
titleSeparator.setVisible(visible);
((GridData) titleSeparator.getLayoutData()).exclude = !visible;
titleBar.getParent().layout();
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
if (title == this.title || (title != null && title.equals(this.title)))
return;
this.title = title;
updateTitleBar();
}
public IPageSite getContainerSite() {
return getSite();
}
public void refresh() {
for (SectionRec rec : sections) {
if (rec.visible) {
rec.section.refresh();
}
}
if (form != null && !form.isDisposed()) {
form.reflow(true);
}
}
public void dispose() {
if (editor != null) {
editor.getSite().getSelectionProvider()
.removeSelectionChangedListener(this);
}
for (SectionRec rec : sections) {
rec.section.dispose();
rec.visible = false;
rec.control = null;
}
if (composite != null) {
composite.dispose();
composite = null;
}
form = null;
title = null;
titleBar = null;
titleSeparator = null;
super.dispose();
}
}