diff options
Diffstat (limited to 'propertysheet/src/org/eclipse/wb/internal/core/model/property/table')
8 files changed, 0 insertions, 2399 deletions
diff --git a/propertysheet/src/org/eclipse/wb/internal/core/model/property/table/HtmlTooltipHelper.java b/propertysheet/src/org/eclipse/wb/internal/core/model/property/table/HtmlTooltipHelper.java deleted file mode 100644 index 5e05549..0000000 --- a/propertysheet/src/org/eclipse/wb/internal/core/model/property/table/HtmlTooltipHelper.java +++ /dev/null @@ -1,332 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2011 Google, Inc. - * 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: - * Google, Inc. - initial API and implementation - *******************************************************************************/ -package org.eclipse.wb.internal.core.model.property.table; - -import com.google.common.base.Charsets; -import com.google.common.base.Joiner; - -import org.eclipse.swt.SWT; -import org.eclipse.swt.browser.Browser; -import org.eclipse.swt.browser.LocationAdapter; -import org.eclipse.swt.browser.LocationEvent; -import org.eclipse.swt.browser.ProgressAdapter; -import org.eclipse.swt.browser.ProgressEvent; -import org.eclipse.swt.graphics.Color; -import org.eclipse.swt.graphics.Point; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Control; -import org.eclipse.swt.widgets.Event; -import org.eclipse.swt.widgets.Label; -import org.eclipse.swt.widgets.Listener; -import org.eclipse.swt.widgets.Shell; -import org.eclipse.ui.PlatformUI; -import org.eclipse.ui.browser.IWebBrowser; -import org.eclipse.ui.browser.IWorkbenchBrowserSupport; -import org.eclipse.wb.draw2d.IColorConstants; -import org.eclipse.wb.internal.core.DesignerPlugin; -import org.eclipse.wb.internal.core.EnvironmentUtils; -import org.eclipse.wb.internal.core.utils.reflect.ReflectionUtils; -import org.eclipse.wb.internal.core.utils.ui.GridDataFactory; -import org.eclipse.wb.internal.core.utils.ui.PixelConverter; - -import java.io.StringReader; -import java.net.URL; -import java.text.MessageFormat; - -/** - * Helper for displaying HTML tooltips. - * - * @author scheglov_ke - * @coverage core.model.property.table - */ -public final class HtmlTooltipHelper { - public static Control createTooltipControl(Composite parent, String header, String details) { - return createTooltipControl(parent, header, details, 0); - } - - public static Control createTooltipControl(Composite parent, - String header, - String details, - int heightLimit) { - // prepare Control - Control control; - try { - String html = "<table cellspacing=2 cellpadding=0 border=0 margins=0 id=_wbp_tooltip_body>"; - if (header != null) { - html += "<tr align=center><td><b>" + header + "</b></td></tr>"; - } - html += "<tr><td align=justify>" + details + "</td></tr>"; - html += "</table>"; - control = createTooltipControl_Browser(parent, html, heightLimit); - } catch (Throwable e) { - control = createTooltipControl_Label(parent, details); - } - // set listeners - { - Listener listener = new Listener() { - @Override - public void handleEvent(Event event) { - Control tooltipControl = (Control) event.widget; - hideTooltip(tooltipControl); - } - }; - control.addListener(SWT.MouseExit, listener); - } - // done - return control; - } - - /** - * Creates {@link Browser} for displaying tooltip. - */ - private static Control createTooltipControl_Browser(Composite parent, - String html, - final int heightLimitChars) { - // prepare styles - String styles; - try { - styles = DesignerPlugin.readFile(PropertyTable.class.getResourceAsStream("Tooltip.css"), - Charsets.US_ASCII); - if (styles == null) { - styles = ""; - } - } catch (Throwable e) { - styles = ""; - } - // prepare HTML with styles and tags - String wrappedHtml; - { - String bodyAttributes = - MessageFormat.format( - "text=''{0}'' bgcolor=''{1}''", - getColorWebString(IColorConstants.tooltipForeground), - getColorWebString(IColorConstants.tooltipBackground)); - String closeElement = - EnvironmentUtils.IS_LINUX - ? " <a href='' style='position:absolute;right:1em;' id=_wbp_close>Close</a>" - : ""; - wrappedHtml = - /*CodeUtils.*/getSource( - "<html>", - " <style CHARSET='ISO-8859-1' TYPE='text/css'>", - styles, - " </style>", - " <body " + bodyAttributes + ">", - closeElement, - html, - " </body>", - "</html>"); - } - // prepare Browser - final Browser browser = new Browser(parent, SWT.NONE); - browser.setText(wrappedHtml); - // open URLs in new window - browser.addLocationListener(new LocationAdapter() { - @Override - public void changing(LocationEvent event) { - event.doit = false; - hideTooltip((Browser) event.widget); - if (!"about:blank".equals(event.location)) { - try { - IWorkbenchBrowserSupport support = PlatformUI.getWorkbench().getBrowserSupport(); - IWebBrowser browserSupport = support.createBrowser("wbp.browser"); - browserSupport.openURL(new URL(event.location)); - } catch (Throwable e) { - DesignerPlugin.log(e); - } - } - } - }); - // set size - { - int textLength = getTextLength(html); - // horizontal hint - int hintH = 50; - if (textLength < 100) { - hintH = 40; - } - // vertical hint - int hintV = textLength / hintH + 3; - hintV = Math.min(hintV, 8); - // do set - GridDataFactory.create(browser).hintC(hintH, hintV); - } - // tweak size after rendering HTML - browser.addProgressListener(new ProgressAdapter() { - @Override - public void completed(ProgressEvent event) { - browser.removeProgressListener(this); - tweakBrowserSize(browser, heightLimitChars); - browser.getShell().setVisible(true); - } - }); - // done - return browser; - } - - private static void tweakBrowserSize(Browser browser, int heightLimitChars) { - GridDataFactory.create(browser).grab().fill(); - // limit height - if (heightLimitChars != 0) { - PixelConverter pixelConverter = new PixelConverter(browser); - int maxHeight = pixelConverter.convertHeightInCharsToPixels(heightLimitChars); - expandShellToShowFullPage_Height(browser, maxHeight); - } - // if no limit, then show all, so make as tall as required - if (heightLimitChars == 0) { - expandShellToShowFullPage_Height(browser, Integer.MAX_VALUE); - } - } - - private static void expandShellToShowFullPage_Height(Browser browser, int maxHeight) { - try { - Shell shell = browser.getShell(); - // calculate required - int contentHeight; - { - getContentOffsetHeight(browser); - contentHeight = getContentScrollHeight(browser); - } - // apply height - int useHeight = Math.min(contentHeight + ((EnvironmentUtils.IS_LINUX) ? 2 : 10), maxHeight); - shell.setSize(shell.getSize().x, useHeight); - // trim height to content - { - int offsetHeight = getBodyOffsetHeight(browser); - int scrollHeight = getBodyScrollHeight(browser); - int delta = scrollHeight - offsetHeight; - if (delta != 0 && delta < 10) { - Point size = shell.getSize(); - shell.setSize(size.x, size.y + delta + 1); - } - } - // trim width to content - { - int offsetWidth = getContentOffsetWidth(browser); - { - Point size = shell.getSize(); - shell.setSize(offsetWidth + ((EnvironmentUtils.IS_MAC) ? 6 : 10), size.y); - } - } - // hide 'Close' if too narrow - if (EnvironmentUtils.IS_LINUX) { - if (shell.getSize().y < 30) { - hideCloseElement(browser); - } - } - } catch (Throwable e) { - } - } - - private static int getContentOffsetWidth(Browser browser) throws Exception { - return evaluateScriptInt( - browser, - "return document.getElementById('_wbp_tooltip_body').offsetWidth;"); - } - - private static int getContentOffsetHeight(Browser browser) throws Exception { - return evaluateScriptInt( - browser, - "return document.getElementById('_wbp_tooltip_body').offsetHeight;"); - } - - private static int getContentScrollHeight(Browser browser) throws Exception { - return evaluateScriptInt( - browser, - "return document.getElementById('_wbp_tooltip_body').scrollHeight;"); - } - - private static int getBodyOffsetHeight(Browser browser) throws Exception { - return evaluateScriptInt(browser, "return document.body.offsetHeight;"); - } - - private static int getBodyScrollHeight(Browser browser) throws Exception { - return evaluateScriptInt(browser, "return document.body.scrollHeight;"); - } - - private static int evaluateScriptInt(Browser browser, String script) throws Exception { - Object o = ReflectionUtils.invokeMethod(browser, "evaluate(java.lang.String)", script); - return ((Number) o).intValue(); - } - - private static void hideCloseElement(Browser browser) throws Exception { - String script = "document.getElementById('_wbp_close').style.display = 'none'"; - ReflectionUtils.invokeMethod(browser, "evaluate(java.lang.String)", script); - } - - /** - * @return the length of text in given HTML. Uses internal class, so may fail, in this case - * returns length on HTML. - */ - private static int getTextLength(String html) { - StringReader htmlStringReader = new StringReader(html); - try { - ClassLoader classLoader = PropertyTable.class.getClassLoader(); - Class<?> readerClass = - classLoader.loadClass("org.eclipse.jface.internal.text.html.HTML2TextReader"); - Object reader = readerClass.getConstructors()[0].newInstance(htmlStringReader, null); - String text = (String) ReflectionUtils.invokeMethod(reader, "getString()"); - return text.length(); - } catch (Throwable e) { - return html.length(); - } - } - - /** - * Returns a string representation of {@link Color} suitable for web pages. - * - * @param color - * the {@link Color} instance, not <code>null</code>. - * @return a string representation of {@link Color} suitable for web pages. - */ - private static String getColorWebString(final Color color) { - String colorString = "#" + Integer.toHexString(color.getRed()); - colorString += Integer.toHexString(color.getGreen()); - colorString += Integer.toHexString(color.getBlue()); - return colorString; - } - - /** - * Creates {@link Label} if {@link Browser} can not be used. - */ - private static Control createTooltipControl_Label(Composite parent, String html) { - // prepare Label - final Label label = new Label(parent, SWT.WRAP); - label.setText(html); - // set size - int requiredWidth = label.computeSize(SWT.DEFAULT, SWT.DEFAULT).x; - GridDataFactory.create(label).hintHC(50).hintHMin(requiredWidth); - // copy colors - label.setForeground(parent.getForeground()); - label.setBackground(parent.getBackground()); - // done - parent.getDisplay().asyncExec(new Runnable() { - @Override - public void run() { - Shell shell = label.getShell(); - shell.setVisible(true); - } - }); - return label; - } - - private static void hideTooltip(Control tooltip) { - tooltip.getShell().dispose(); - } - - // Copied from CodeUtils.java: CodeUtils.getSource() - /** - * @return the source as single {@link String}, lines joined using "\n". - */ - public static String getSource(String... lines) { - return Joiner.on('\n').join(lines); - } -} diff --git a/propertysheet/src/org/eclipse/wb/internal/core/model/property/table/IPropertyExceptionHandler.java b/propertysheet/src/org/eclipse/wb/internal/core/model/property/table/IPropertyExceptionHandler.java deleted file mode 100644 index 879f699..0000000 --- a/propertysheet/src/org/eclipse/wb/internal/core/model/property/table/IPropertyExceptionHandler.java +++ /dev/null @@ -1,25 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2011 Google, Inc. - * 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: - * Google, Inc. - initial API and implementation - *******************************************************************************/ -package org.eclipse.wb.internal.core.model.property.table; - -import org.eclipse.wb.internal.core.model.property.Property; -import org.eclipse.wb.internal.core.model.property.editor.PropertyEditor; - -/** - * Handler for any {@link Exception} that happens in {@link PropertyTable}, i.e. exceptions during - * {@link Property} modifications using {@link PropertyEditor}'s. - * - * @author scheglov_ke - * @coverage core.model.property.table - */ -public interface IPropertyExceptionHandler { - void handle(Throwable e); -} diff --git a/propertysheet/src/org/eclipse/wb/internal/core/model/property/table/IPropertyTooltipSite.java b/propertysheet/src/org/eclipse/wb/internal/core/model/property/table/IPropertyTooltipSite.java deleted file mode 100644 index e2fee14..0000000 --- a/propertysheet/src/org/eclipse/wb/internal/core/model/property/table/IPropertyTooltipSite.java +++ /dev/null @@ -1,30 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2011 Google, Inc. - * 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: - * Google, Inc. - initial API and implementation - *******************************************************************************/ -package org.eclipse.wb.internal.core.model.property.table; - -/** - * Interface that allows control of {@link PropertyTooltipProvider} interact with - * {@link PropertyTableTooltipHelper}. - * - * @author scheglov_ke - * @coverage core.model.property.table - */ -public interface IPropertyTooltipSite { - /** - * @return the {@link PropertyTable} of this site. - */ - PropertyTable getTable(); - - /** - * Hides current tooltip. - */ - void hideTooltip(); -} diff --git a/propertysheet/src/org/eclipse/wb/internal/core/model/property/table/PropertyTable.java b/propertysheet/src/org/eclipse/wb/internal/core/model/property/table/PropertyTable.java deleted file mode 100644 index 7a49cb3..0000000 --- a/propertysheet/src/org/eclipse/wb/internal/core/model/property/table/PropertyTable.java +++ /dev/null @@ -1,1602 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2011 Google, Inc. - * 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: - * Google, Inc. - initial API and implementation - *******************************************************************************/ -package org.eclipse.wb.internal.core.model.property.table; - -import com.google.common.collect.Lists; -import com.google.common.collect.Sets; - -import org.eclipse.jface.viewers.ISelection; -import org.eclipse.jface.viewers.ISelectionChangedListener; -import org.eclipse.jface.viewers.ISelectionProvider; -import org.eclipse.jface.viewers.SelectionChangedEvent; -import org.eclipse.jface.viewers.StructuredSelection; -import org.eclipse.swt.SWT; -import org.eclipse.swt.events.KeyAdapter; -import org.eclipse.swt.events.KeyEvent; -import org.eclipse.swt.events.MouseAdapter; -import org.eclipse.swt.events.MouseEvent; -import org.eclipse.swt.events.MouseMoveListener; -import org.eclipse.swt.graphics.Color; -import org.eclipse.swt.graphics.Font; -import org.eclipse.swt.graphics.GC; -import org.eclipse.swt.graphics.Image; -import org.eclipse.swt.graphics.Point; -import org.eclipse.swt.graphics.Rectangle; -import org.eclipse.swt.widgets.Canvas; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Event; -import org.eclipse.swt.widgets.Listener; -import org.eclipse.swt.widgets.ScrollBar; -import org.eclipse.wb.draw2d.IColorConstants; -import org.eclipse.wb.draw2d.ICursorConstants; -import org.eclipse.wb.internal.core.DesignerPlugin; -import org.eclipse.wb.internal.core.model.property.Property; -import org.eclipse.wb.internal.core.model.property.category.PropertyCategory; -import org.eclipse.wb.internal.core.model.property.category.PropertyCategoryProvider; -import org.eclipse.wb.internal.core.model.property.category.PropertyCategoryProviders; -import org.eclipse.wb.internal.core.model.property.editor.PropertyEditor; -import org.eclipse.wb.internal.core.model.property.editor.complex.IComplexPropertyEditor; -import org.eclipse.wb.internal.core.model.property.editor.presentation.PropertyEditorPresentation; -import org.eclipse.wb.internal.core.utils.check.Assert; -import org.eclipse.wb.internal.core.utils.ui.DrawUtils; - -import java.util.Collection; -import java.util.List; -import java.util.Set; - -/** - * Control that can display {@link Property}'s and edit them using {@link PropertyEditor}'s. - * - * @author scheglov_ke - * @author lobas_av - * @coverage core.model.property.table - */ -public class PropertyTable extends Canvas implements ISelectionProvider { - //////////////////////////////////////////////////////////////////////////// - // - // Colors - // - //////////////////////////////////////////////////////////////////////////// - private static final Color COLOR_BACKGROUND = IColorConstants.listBackground; - private static final Color COLOR_NO_PROPERTIES = IColorConstants.gray; - private static final Color COLOR_LINE = IColorConstants.lightGray; - private static final Color COLOR_COMPLEX_LINE = DrawUtils.getShiftedColor( - IColorConstants.lightGray, - -32); - private static final Color COLOR_PROPERTY_BG = DrawUtils.getShiftedColor(COLOR_BACKGROUND, -12); - private static final Color COLOR_PROPERTY_BG_MODIFIED = COLOR_BACKGROUND; - private static final Color COLOR_PROPERTY_FG_TITLE = IColorConstants.listForeground; - private static final Color COLOR_PROPERTY_FG_VALUE = - DrawUtils.isDarkColor(IColorConstants.listBackground) - ? IColorConstants.lightBlue - : IColorConstants.darkBlue; - private static final Color COLOR_PROPERTY_BG_SELECTED = IColorConstants.listSelection; - private static final Color COLOR_PROPERTY_FG_SELECTED = IColorConstants.listSelectionText; - private static final Color COLOR_PROPERTY_FG_ADVANCED = IColorConstants.gray; - // BEGIN ADT MODIFICATIONS - public static final Color COLOR_PROPERTY_FG_DEFAULT = IColorConstants.darkGray; - // END ADT MODIFICATIONS - //////////////////////////////////////////////////////////////////////////// - // - // Sizes - // - //////////////////////////////////////////////////////////////////////////// - private static final int MIN_COLUMN_WIDTH = 75; - private static final int MARGIN_LEFT = 2; - private static final int MARGIN_RIGHT = 1; - private static final int STATE_IMAGE_MARGIN_RIGHT = 4; - //////////////////////////////////////////////////////////////////////////// - // - // Images - // - //////////////////////////////////////////////////////////////////////////// - private static final Image m_plusImage = DesignerPlugin.getImage("properties/plus.gif"); - private static final Image m_minusImage = DesignerPlugin.getImage("properties/minus.gif"); - private static int m_stateWidth = 9; - //////////////////////////////////////////////////////////////////////////// - // - // Instance fields - // - //////////////////////////////////////////////////////////////////////////// - private final PropertyTableTooltipHelper m_tooltipHelper; - private boolean m_showAdvancedProperties; - private Property[] m_rawProperties; - private List<PropertyInfo> m_properties; - private final Set<String> m_expandedIds = Sets.newTreeSet(); - // BEGIN ADT MODIFICATIONS - // Add support for "expand by default" : If you specify ids to be collapsed by - // default, then any *other* ids will be expanded by default. - private Set<String> m_collapsedIds = null; - - /** - * Sets a set of ids that should be collapsed by default. Everything else - * will be expanded by default. If this method is not called, ids are - * collapsed by default instead. - * - * @param names set of ids to be collapsed - */ - public void setDefaultCollapsedNames(Collection<String> names) { - m_collapsedIds = Sets.newTreeSet(); - for (String name : names) { - m_collapsedIds.add("|" + name); // See PropertyInfo constructor for id syntax - } - } - // END ADT MODIFICATIONS - - private Image m_bufferedImage; - private int m_rowHeight; - private int m_selection; - private int m_page; - private int m_splitter = -1; - - //////////////////////////////////////////////////////////////////////////// - // - // Constructor - // - //////////////////////////////////////////////////////////////////////////// - public PropertyTable(Composite parent, int style) { - super(parent, style | SWT.V_SCROLL | SWT.NO_BACKGROUND | SWT.NO_REDRAW_RESIZE); - hookControlEvents(); - // calculate sizes - { - GC gc = new GC(this); - try { - m_rowHeight = 1 + gc.getFontMetrics().getHeight() + 1; - } finally { - gc.dispose(); - } - } - // install tooltip helper - m_tooltipHelper = new PropertyTableTooltipHelper(this); - } - - //////////////////////////////////////////////////////////////////////////// - // - // Events - // - //////////////////////////////////////////////////////////////////////////// - /** - * Adds listeners for events. - */ - private void hookControlEvents() { - addListener(SWT.Dispose, new Listener() { - @Override - public void handleEvent(Event event) { - disposeBufferedImage(); - } - }); - addListener(SWT.Resize, new Listener() { - @Override - public void handleEvent(Event event) { - handleResize(); - } - }); - addListener(SWT.Paint, new Listener() { - @Override - public void handleEvent(Event event) { - handlePaint(event.gc, event.x, event.y, event.width, event.height); - } - }); - getVerticalBar().addListener(SWT.Selection, new Listener() { - @Override - public void handleEvent(Event event) { - handleVerticalScrolling(); - } - }); - addMouseListener(new MouseAdapter() { - @Override - public void mouseDown(MouseEvent event) { - forceFocus(); - handleMouseDown(event); - } - - @Override - public void mouseUp(MouseEvent event) { - handleMouseUp(event); - } - - @Override - public void mouseDoubleClick(MouseEvent event) { - handleMouseDoubleClick(event); - } - }); - addMouseMoveListener(new MouseMoveListener() { - @Override - public void mouseMove(MouseEvent event) { - handleMouseMove(event); - } - }); - // keyboard - addKeyListener(new KeyAdapter() { - @Override - public void keyPressed(KeyEvent e) { - handleKeyDown(e); - } - }); - } - - //////////////////////////////////////////////////////////////////////////// - // - // Events: dispose, resize, scroll - // - //////////////////////////////////////////////////////////////////////////// - /** - * Disposes image used for double buffered painting. - */ - private void disposeBufferedImage() { - if (m_bufferedImage != null) { - m_bufferedImage.dispose(); - m_bufferedImage = null; - } - } - - /** - * Handles {@link SWT#Resize} event. - */ - private void handleResize() { - disposeBufferedImage(); - configureScrolling(); - // splitter - { - // set default value for splitter - if (m_splitter <= MIN_COLUMN_WIDTH) { - m_splitter = Math.max((int) (getClientArea().width * 0.4), MIN_COLUMN_WIDTH); - } - configureSplitter(); - } - } - - /** - * Handles {@link SWT#Selection} event for vertical {@link ScrollBar}. - */ - private void handleVerticalScrolling() { - ScrollBar verticalBar = getVerticalBar(); - if (verticalBar.getEnabled()) { - // update selection - m_selection = verticalBar.getSelection(); - // redraw (but not include vertical bar to avoid flashing) - { - Rectangle clientArea = getClientArea(); - redraw(clientArea.x, clientArea.y, clientArea.width, clientArea.height, false); - } - } - } - - //////////////////////////////////////////////////////////////////////////// - // - // Keyboard - // - //////////////////////////////////////////////////////////////////////////// - /** - * Handles {@link SWT#KeyDown} event. - */ - private void handleKeyDown(KeyEvent e) { - if (m_activePropertyInfo != null) { - try { - Property property = m_activePropertyInfo.getProperty(); - // expand/collapse - if (m_activePropertyInfo.isComplex()) { - if (!m_activePropertyInfo.isExpanded() - && (e.character == '+' || e.keyCode == SWT.ARROW_RIGHT)) { - m_activePropertyInfo.expand(); - configureScrolling(); - return; - } - if (m_activePropertyInfo.isExpanded() - && (e.character == '-' || e.keyCode == SWT.ARROW_LEFT)) { - m_activePropertyInfo.collapse(); - configureScrolling(); - return; - } - } - // navigation - if (navigate(e)) { - return; - } - // editor activation - if (e.character == ' ' || e.character == SWT.CR) { - activateEditor(property, null); - return; - } - // DEL - if (e.keyCode == SWT.DEL) { - e.doit = false; - property.setValue(Property.UNKNOWN_VALUE); - return; - } - // send to editor - property.getEditor().keyDown(this, property, e); - } catch (Throwable ex) { - DesignerPlugin.log(ex); - } - } - } - - /** - * @return <code>true</code> if given {@link KeyEvent} was navigation event, so new - * {@link PropertyInfo} was selected. - */ - public boolean navigate(KeyEvent e) { - int index = m_properties.indexOf(m_activePropertyInfo); - Rectangle clientArea = getClientArea(); - // - int newIndex = index; - if (e.keyCode == SWT.HOME) { - newIndex = 0; - } else if (e.keyCode == SWT.END) { - newIndex = m_properties.size() - 1; - } else if (e.keyCode == SWT.PAGE_UP) { - newIndex = Math.max(index - m_page + 1, 0); - } else if (e.keyCode == SWT.PAGE_DOWN) { - newIndex = Math.min(index + m_page - 1, m_properties.size() - 1); - } else if (e.keyCode == SWT.ARROW_UP) { - newIndex = Math.max(index - 1, 0); - } else if (e.keyCode == SWT.ARROW_DOWN) { - newIndex = Math.min(index + 1, m_properties.size() - 1); - } - // activate new property - if (newIndex != index && newIndex < m_properties.size()) { - setActivePropertyInfo(m_properties.get(newIndex)); - // check for scrolling - int y = m_rowHeight * (newIndex - m_selection); - if (y < 0) { - m_selection = newIndex; - configureScrolling(); - } else if (y + m_rowHeight > clientArea.height) { - m_selection = newIndex - m_page + 1; - configureScrolling(); - } - // repaint - redraw(); - return true; - } - // no navigation change - return false; - } - - //////////////////////////////////////////////////////////////////////////// - // - // Events: mouse - // - //////////////////////////////////////////////////////////////////////////// - private boolean m_splitterResizing; - /** - * We do expand/collapse on to events: click on state sign and on double click. But when we double - * click on state sign, we will have <em>two</em> events, so we should ignore double click. - */ - private long m_lastExpandCollapseTime; - - /** - * Handles {@link SWT#MouseDown} event. - */ - private void handleMouseDown(MouseEvent event) { - m_splitterResizing = event.button == 1 && m_properties != null && isLocationSplitter(event.x); - // click in property - if (!m_splitterResizing && m_properties != null) { - int propertyIndex = getPropertyIndex(event.y); - if (propertyIndex >= m_properties.size()) { - return; - } - // prepare property - setActivePropertyInfo(m_properties.get(propertyIndex)); - Property property = m_activePropertyInfo.getProperty(); - // de-activate current editor - deactivateEditor(true); - redraw(); - // activate editor - if (isLocationValue(event.x)) { - activateEditor(property, getValueRelativeLocation(event.x, event.y)); - } - } - } - - /** - * Handles {@link SWT#MouseUp} event. - */ - private void handleMouseUp(MouseEvent event) { - if (event.button == 1) { - // resize splitter - if (m_splitterResizing) { - m_splitterResizing = false; - return; - } - // if out of bounds, then ignore - if (!getClientArea().contains(event.x, event.y)) { - return; - } - // update - if (m_properties != null) { - int index = getPropertyIndex(event.y); - if (index < m_properties.size()) { - PropertyInfo propertyInfo = m_properties.get(index); - // check for expand/collapse - if (isLocationState(propertyInfo, event.x)) { - try { - m_lastExpandCollapseTime = System.currentTimeMillis(); - propertyInfo.flip(); - configureScrolling(); - } catch (Throwable e) { - DesignerPlugin.log(e); - } - } - } - } - } - } - - /** - * Handles {@link SWT#MouseDoubleClick} event. - */ - private void handleMouseDoubleClick(MouseEvent event) { - if (System.currentTimeMillis() - m_lastExpandCollapseTime > getDisplay().getDoubleClickTime()) { - try { - if (m_activePropertyInfo != null) { - if (m_activePropertyInfo.isComplex()) { - m_activePropertyInfo.flip(); - configureScrolling(); - } else { - Property property = m_activePropertyInfo.getProperty(); - property.getEditor().doubleClick(property, getValueRelativeLocation(event.x, event.y)); - } - } - } catch (Throwable e) { - handleException(e); - } - } - } - - /** - * Handles {@link SWT#MouseMove} event. - */ - private void handleMouseMove(MouseEvent event) { - int x = event.x; - // resize splitter - if (m_splitterResizing) { - m_splitter = x; - configureSplitter(); - redraw(); - return; - } - // if out of bounds, then ignore - if (!getClientArea().contains(event.x, event.y)) { - return; - } - // update - if (m_properties != null) { - // update cursor - if (isLocationSplitter(x)) { - setCursor(ICursorConstants.SIZEWE); - } else { - setCursor(null); - } - // update tooltip helper - updateTooltip(event); - } else { - updateTooltipNoProperty(); - } - } - - /** - * Updates {@link PropertyTableTooltipHelper}. - */ - private void updateTooltip(MouseEvent event) { - int x = event.x; - int propertyIndex = getPropertyIndex(event.y); - // - if (propertyIndex < m_properties.size()) { - PropertyInfo propertyInfo = m_properties.get(propertyIndex); - Property property = propertyInfo.getProperty(); - int y = (propertyIndex - m_selection) * m_rowHeight; - // check for title - { - int titleX = getTitleTextX(propertyInfo); - int titleRight = m_splitter - 2; - if (titleX <= x && x < titleRight) { - m_tooltipHelper.update(property, true, false, titleX, titleRight, y, m_rowHeight); - return; - } - } - // check for value - { - int valueX = m_splitter + 3; - if (x > valueX) { - m_tooltipHelper.update( - property, - false, - true, - valueX, - getClientArea().width, - y, - m_rowHeight); - } - } - } else { - updateTooltipNoProperty(); - } - } - - private void updateTooltipNoProperty() { - m_tooltipHelper.update(null, false, false, 0, 0, 0, 0); - } - - //////////////////////////////////////////////////////////////////////////// - // - // Editor - // - //////////////////////////////////////////////////////////////////////////// - private PropertyInfo m_activePropertyInfo; - private String m_activePropertyId; - private PropertyEditor m_activeEditor; - - /** - * Tries to activate editor for {@link PropertyInfo} under cursor. - * - * @param location - * the mouse location, if editor is activated using mouse click, or <code>null</code> if - * it is activated using keyboard. - */ - public void activateEditor(Property property, Point location) { - try { - // de-activate old editor - deactivateEditor(true); - // activate editor - PropertyEditor editor = property.getEditor(); - try { - if (editor.activate(this, property, location)) { - m_activeEditor = editor; - } - } catch (Throwable e) { - handleException(e); - } - // set bounds - setActiveEditorBounds(); - } catch (Throwable e) { - DesignerPlugin.log(e); - } - } - - /** - * Deactivates current {@link PropertyEditor}. - */ - public void deactivateEditor(boolean save) { - if (m_activeEditor != null) { - PropertyEditor activeEditor = m_activeEditor; - m_activeEditor = null; - if (m_activePropertyInfo != null && m_activePropertyInfo.m_property != null) { - activeEditor.deactivate(this, m_activePropertyInfo.m_property, save); - } - } - } - - /** - * Sets correct bounds for active editor, for example we need update bounds after scrolling. - */ - private void setActiveEditorBounds() { - if (m_activeEditor != null) { - int index = m_properties.indexOf(m_activePropertyInfo); - if (index == -1) { - // it is possible that active property was hidden because its parent was collapsed - deactivateEditor(true); - } else { - // prepare bounds for editor - Rectangle bounds; - { - Rectangle clientArea = getClientArea(); - int x = m_splitter + 1; - int width = clientArea.width - x - MARGIN_RIGHT; - int y = m_rowHeight * (index - m_selection) + 1; - int height = m_rowHeight - 1; - bounds = new Rectangle(x, y, width, height); - } - // update bounds using presentation - { - PropertyEditorPresentation presentation = m_activeEditor.getPresentation(); - if (presentation != null) { - int presentationWidth = - presentation.show( - this, - m_activePropertyInfo.m_property, - bounds.x, - bounds.y, - bounds.width, - bounds.height); - bounds.width -= presentationWidth; - } - } - // set editor bounds - m_activeEditor.setBounds(bounds); - } - } - } - - //////////////////////////////////////////////////////////////////////////// - // - // Exceptions - // - //////////////////////////////////////////////////////////////////////////// - private IPropertyExceptionHandler m_exceptionHandler; - - /** - * Sets {@link IPropertyExceptionHandler} for handling all exceptions. - */ - public void setExceptionHandler(IPropertyExceptionHandler exceptionHandler) { - m_exceptionHandler = exceptionHandler; - } - - /** - * Handles given {@link Throwable}.<br> - * Right now it just logs it, but in future we can open some dialog here. - */ - public void handleException(Throwable e) { - m_exceptionHandler.handle(e); - } - - //////////////////////////////////////////////////////////////////////////// - // - // Scrolling - // - //////////////////////////////////////////////////////////////////////////// - /** - * Configures vertical {@link ScrollBar}. - */ - private void configureScrolling() { - ScrollBar verticalBar = getVerticalBar(); - if (m_properties == null) { - verticalBar.setEnabled(false); - } else { - m_page = getClientArea().height / m_rowHeight; - m_selection = Math.max(0, Math.min(m_properties.size() - m_page, m_selection)); - verticalBar.setValues(m_selection, 0, m_properties.size(), m_page, 1, m_page); - // enable/disable scrolling - if (m_properties.size() <= m_page) { - verticalBar.setEnabled(false); - } else { - verticalBar.setEnabled(true); - } - } - // redraw, we reconfigure scrolling only if list of properties was changed, so we should redraw - redraw(); - } - - //////////////////////////////////////////////////////////////////////////// - // - // Location/size utils - // - //////////////////////////////////////////////////////////////////////////// - /** - * @return the <code>X</code> position for first pixel of {@link PropertyInfo} title (location of - * state image). - */ - private int getTitleX(PropertyInfo propertyInfo) { - return MARGIN_LEFT + getLevelIndent() * propertyInfo.getLevel(); - } - - /** - * @return the <code>X</code> position for first pixel of {@link PropertyInfo} title text. - */ - private int getTitleTextX(PropertyInfo propertyInfo) { - return getTitleX(propertyInfo) + getLevelIndent(); - } - - /** - * @return the indentation for single level. - */ - private int getLevelIndent() { - return m_stateWidth + STATE_IMAGE_MARGIN_RIGHT; - } - - /** - * Checks horizontal splitter value to boundary values. - */ - private void configureSplitter() { - Rectangle clientArea = getClientArea(); - // check title width - if (m_splitter < MIN_COLUMN_WIDTH) { - m_splitter = MIN_COLUMN_WIDTH; - } - // check value width - if (clientArea.width - m_splitter < MIN_COLUMN_WIDTH) { - m_splitter = clientArea.width - MIN_COLUMN_WIDTH; - } - } - - /** - * @return the index in {@link #m_properties} corresponding given <code>y</code> location. - */ - private int getPropertyIndex(int y) { - return m_selection + y / m_rowHeight; - } - - /** - * @return <code>true</code> if given <code>x</code> coordinate is on state (plus/minus) image. - */ - private boolean isLocationState(PropertyInfo propertyInfo, int x) { - int levelX = getTitleX(propertyInfo); - return propertyInfo.isComplex() && levelX <= x && x <= levelX + m_stateWidth; - } - - /** - * Returns <code>true</code> if <code>x</code> coordinate is on splitter. - */ - private boolean isLocationSplitter(int x) { - return Math.abs(m_splitter - x) < 2; - } - - /** - * @return <code>true</code> if given <code>x</code> is on value part of property. - */ - private boolean isLocationValue(int x) { - return x > m_splitter + 2; - } - - /** - * @param x - * the {@link PropertyTable} relative coordinate. - * @param y - * the {@link PropertyTable} relative coordinate. - * - * @return the location relative to the value part of property. - */ - private Point getValueRelativeLocation(int x, int y) { - return new Point(x - (m_splitter + 2), y - m_rowHeight * getPropertyIndex(y)); - } - - //////////////////////////////////////////////////////////////////////////// - // - // Access - // - //////////////////////////////////////////////////////////////////////////// - /** - * Shows or hides {@link Property}-s with {@link PropertyCategory#ADVANCED}. - */ - public void setShowAdvancedProperties(boolean showAdvancedProperties) { - m_showAdvancedProperties = showAdvancedProperties; - setInput0(); - } - - /** - * Sets the array of {@link Property}'s to display/edit. - */ - public void setInput(Property[] properties) { - m_rawProperties = properties; - setInput0(); - } - - private void setInput0() { - // send "hide" to all PropertyEditorPresentation's - if (m_properties != null) { - for (PropertyInfo propertyInfo : m_properties) { - Property property = propertyInfo.getProperty(); - // hide presentation - { - PropertyEditorPresentation presentation = property.getEditor().getPresentation(); - if (presentation != null) { - presentation.hide(this, property); - } - } - } - } - // set new properties - if (m_rawProperties == null || m_rawProperties.length == 0) { - deactivateEditor(false); - m_properties = Lists.newArrayList(); - } else { - try { - // add PropertyInfo for each Property - m_properties = Lists.newArrayList(); - for (Property property : m_rawProperties) { - if (rawProperties_shouldShow(property)) { - PropertyInfo propertyInfo = new PropertyInfo(property); - m_properties.add(propertyInfo); - } - } - // expand properties using history - while (true) { - boolean expanded = false; - List<PropertyInfo> currentProperties = Lists.newArrayList(m_properties); - for (PropertyInfo propertyInfo : currentProperties) { - expanded |= propertyInfo.expandFromHistory(); - } - // stop - if (!expanded) { - break; - } - } - } catch (Throwable e) { - DesignerPlugin.log(e); - } - } - // update active property - if (m_activePropertyId != null) { - PropertyInfo newActivePropertyInfo = null; - // try to find corresponding PropertyInfo - if (m_properties != null) { - for (PropertyInfo propertyInfo : m_properties) { - if (propertyInfo.m_id.equals(m_activePropertyId)) { - newActivePropertyInfo = propertyInfo; - break; - } - } - } - // set new PropertyInfo - setActivePropertyInfo(newActivePropertyInfo); - } - // update scroll bar - configureScrolling(); - } - - /** - * @return <code>true</code> if given {@link Property} should be displayed. - */ - private boolean rawProperties_shouldShow(Property property) throws Exception { - PropertyCategory category = getCategory(property); - // filter out hidden properties - if (category.isHidden()) { - return false; - } - // filter out advanced properties - if (category.isAdvanced()) { - if (!m_showAdvancedProperties && !property.isModified()) { - return false; - } - } - if (category.isAdvancedReally()) { - return m_showAdvancedProperties; - } - // OK - return true; - } - - /** - * Activates given {@link Property}. - */ - public void setActiveProperty(Property property) { - for (PropertyInfo propertyInfo : m_properties) { - if (propertyInfo.m_property == property) { - setActivePropertyInfo(propertyInfo); - break; - } - } - } - - //////////////////////////////////////////////////////////////////////////// - // - // Access: only for testing - // - //////////////////////////////////////////////////////////////////////////// - /** - * @return the count of properties in "expanded" list. - */ - public int forTests_getPropertiesCount() { - return m_properties.size(); - } - - /** - * @return the {@link Property} from "expanded" list. - */ - public Property forTests_getProperty(int index) { - return m_properties.get(index).getProperty(); - } - - /** - * Expands the {@link PropertyInfo} with given index. - */ - public void forTests_expand(int index) throws Exception { - m_properties.get(index).expand(); - } - - /** - * @return the position of splitter. - */ - public int forTests_getSplitter() { - return m_splitter; - } - - /** - * @return the location of state image (plus/minus) for given {@link Property}. - */ - public Point forTests_getStateLocation(Property property) { - PropertyInfo propertyInfo = getPropertyInfo(property); - if (propertyInfo != null) { - int index = m_properties.indexOf(propertyInfo); - int x = getTitleX(propertyInfo); - int y = m_rowHeight * (index - m_selection) + 1; - return new Point(x, y); - } - return null; - } - - /** - * @return the location of state image (plus/minus) for given {@link Property}. - */ - public Point forTests_getValueLocation(Property property) { - PropertyInfo propertyInfo = getPropertyInfo(property); - if (propertyInfo != null) { - int index = m_properties.indexOf(propertyInfo); - int x = m_splitter + 5; - int y = m_rowHeight * (index - m_selection) + 1; - return new Point(x, y); - } - return null; - } - - /** - * @return the active {@link PropertyEditor}. - */ - public PropertyEditor forTests_getActiveEditor() { - return m_activeEditor; - } - - /** - * @return the {@link PropertyCategory} that is used by this {@link PropertyTable} to display. - */ - public PropertyCategory forTests_getCategory(Property property) { - return getCategory(property); - } - - /** - * @return the {@link PropertyInfo}for given {@link Property}. - */ - private PropertyInfo getPropertyInfo(Property property) { - for (PropertyInfo propertyInfo : m_properties) { - if (propertyInfo.getProperty() == property) { - return propertyInfo; - } - } - return null; - } - - //////////////////////////////////////////////////////////////////////////// - // - // ISelectionProvider - // - //////////////////////////////////////////////////////////////////////////// - private final List<ISelectionChangedListener> m_selectionListeners = Lists.newArrayList(); - - @Override -public void addSelectionChangedListener(ISelectionChangedListener listener) { - if (!m_selectionListeners.contains(listener)) { - m_selectionListeners.add(listener); - } - } - - @Override -public void removeSelectionChangedListener(ISelectionChangedListener listener) { - m_selectionListeners.add(listener); - } - - @Override -public ISelection getSelection() { - if (m_activePropertyInfo != null) { - return new StructuredSelection(m_activePropertyInfo.getProperty()); - } else { - return StructuredSelection.EMPTY; - } - } - - @Override - public void setSelection(ISelection selection) { - throw new UnsupportedOperationException(); - } - - /** - * Sets the new active {@link PropertyInfo} and sends event to {@link ISelectionChangedListener} - * 's. - */ - private void setActivePropertyInfo(PropertyInfo activePropertyInfo) { - m_activePropertyInfo = activePropertyInfo; - // update m_activePropertyId only when really select property, - // not just remove selection because there are no corresponding property for old active - // so, later for some other component, if we don't select other property, old active will be selected - if (m_activePropertyInfo != null) { - m_activePropertyId = m_activePropertyInfo.m_id; - } - // make sure that active property is visible - if (m_activePropertyInfo != null) { - int row = m_properties.indexOf(m_activePropertyInfo); - if (m_selection <= row && row < m_selection + m_page) { - } else { - m_selection = row; - configureScrolling(); - } - } - // send events - SelectionChangedEvent selectionEvent = new SelectionChangedEvent(this, getSelection()); - for (ISelectionChangedListener listener : m_selectionListeners) { - listener.selectionChanged(selectionEvent); - } - // re-draw - redraw(); - } - - //////////////////////////////////////////////////////////////////////////// - // - // Painting - // - //////////////////////////////////////////////////////////////////////////// - private boolean m_painting; - private Font m_baseFont; - private Font m_boldFont; - private Font m_italicFont; - - /** - * Handles {@link SWT#Paint} event. - */ - private void handlePaint(GC gc, int x, int y, int width, int height) { - // sometimes we disable Eclipse Shell to prevent user actions, but we do this for short time - if (!isEnabled()) { - return; - } - // prevent recursion - if (m_painting) { - return; - } - m_painting = true; - // - try { - setActiveEditorBounds(); - // prepare buffered image - if (m_bufferedImage == null || m_bufferedImage.isDisposed()) { - Point size = getSize(); - m_bufferedImage = new Image(DesignerPlugin.getStandardDisplay(), size.x, size.y); - } - // prepare buffered GC - GC bufferedGC = null; - try { - // perform some drawing - { - bufferedGC = new GC(m_bufferedImage); - bufferedGC.setClipping(x, y, width, height); - bufferedGC.setBackground(gc.getBackground()); - bufferedGC.setForeground(gc.getForeground()); - bufferedGC.setFont(gc.getFont()); - bufferedGC.setLineStyle(gc.getLineStyle()); - bufferedGC.setLineWidth(gc.getLineWidth()); - } - // fill client area - { - Rectangle clientArea = getClientArea(); - bufferedGC.setBackground(COLOR_BACKGROUND); - bufferedGC.fillRectangle(clientArea); - } - // draw content - if (m_properties == null || m_properties.size() == 0) { - drawEmptyContent(bufferedGC); - } else { - drawContent(bufferedGC); - } - } finally { - // flush image - if (bufferedGC != null) { - bufferedGC.dispose(); - } - } - gc.drawImage(m_bufferedImage, 0, 0); - } finally { - m_painting = false; - } - } - - /** - * Draws content when there are no properties. - */ - private void drawEmptyContent(GC gc) { - Rectangle area = getClientArea(); - // draw message - gc.setForeground(COLOR_NO_PROPERTIES); - DrawUtils.drawStringCHCV( - gc, - "<No properties>", - 0, - 0, - area.width, - area.height); - } - - /** - * Draws all {@link PropertyInfo}'s, separators, etc. - */ - private void drawContent(GC gc) { - Rectangle clientArea = getClientArea(); - // prepare fonts - m_baseFont = gc.getFont(); - m_boldFont = DrawUtils.getBoldFont(m_baseFont); - m_italicFont = DrawUtils.getItalicFont(m_baseFont); - // show presentations - int[] presentationsWidth = showPresentations(clientArea); - // draw properties - { - int y = clientArea.y - m_rowHeight * m_selection; - for (int i = 0; i < m_properties.size(); i++) { - // skip, if not visible yet - if (y + m_rowHeight < 0) { - y += m_rowHeight; - continue; - } - // stop, if already invisible - if (y > clientArea.height) { - break; - } - // draw single property - { - PropertyInfo propertyInfo = m_properties.get(i); - drawProperty(gc, propertyInfo, y + 1, m_rowHeight - 1, clientArea.width - - presentationsWidth[i]); - y += m_rowHeight; - } - // draw row separator - gc.setForeground(COLOR_LINE); - gc.drawLine(0, y, clientArea.width, y); - } - } - // draw expand line - drawExpandLines(gc, clientArea); - // draw rectangle around table - gc.setForeground(COLOR_LINE); - gc.drawRectangle(0, 0, clientArea.width - 1, clientArea.height - 1); - // draw splitter - gc.setForeground(COLOR_LINE); - gc.drawLine(m_splitter, 0, m_splitter, clientArea.height); - // dispose font - m_boldFont.dispose(); - m_italicFont.dispose(); - } - - /** - * Shows {@link PropertyEditorPresentation}'s for all {@link Property}'s, i.e. updates also their - * bounds. So, some {@link PropertyEditorPresentation}'s become invisible because they are moved - * above or below visible client area. - * - * @return the array of width for each {@link PropertyEditorPresentation}'s, consumed on the - * right. - */ - private int[] showPresentations(Rectangle clientArea) { - int[] presentationsWidth = new int[m_properties.size()]; - // prepare value rectangle - int x = m_splitter + 4; - int w = clientArea.width - x - MARGIN_RIGHT; - // show presentation's for all properties - int y = clientArea.y - m_rowHeight * m_selection; - for (int i = 0; i < m_properties.size(); i++) { - PropertyInfo propertyInfo = m_properties.get(i); - Property property = propertyInfo.getProperty(); - PropertyEditorPresentation presentation = property.getEditor().getPresentation(); - if (presentation != null) { - presentationsWidth[i] = presentation.show(this, property, x, y + 1, w, m_rowHeight - 1); - } - y += m_rowHeight; - } - return presentationsWidth; - } - - /** - * Draws lines from expanded complex property to its last sub-property. - */ - private void drawExpandLines(GC gc, Rectangle clientArea) { - int height = m_rowHeight - 1; - int xOffset = m_plusImage.getBounds().width / 2; - int yOffset = (height - m_plusImage.getBounds().width) / 2; - // - int y = clientArea.y - m_selection * m_rowHeight; - gc.setForeground(COLOR_COMPLEX_LINE); - for (int i = 0; i < m_properties.size(); i++) { - PropertyInfo propertyInfo = m_properties.get(i); - // - if (propertyInfo.isExpanded()) { - int index = m_properties.indexOf(propertyInfo); - // prepare index of last sub-property - int index2 = index; - for (; index2 < m_properties.size(); index2++) { - PropertyInfo nextPropertyInfo = m_properties.get(index2); - if (nextPropertyInfo != propertyInfo - && nextPropertyInfo.getLevel() <= propertyInfo.getLevel()) { - break; - } - } - index2--; - // draw line if there are children - if (index2 > index) { - int x = getTitleX(propertyInfo) + xOffset; - int y1 = y + height - yOffset; - int y2 = y + m_rowHeight * (index2 - index) + m_rowHeight / 2; - gc.drawLine(x, y1, x, y2); - gc.drawLine(x, y2, x + m_rowHeight / 3, y2); - } - } - // - y += m_rowHeight; - } - } - - /** - * Draws single {@link PropertyInfo} in specified rectangle. - */ - private void drawProperty(GC gc, PropertyInfo propertyInfo, int y, int height, int width) { - // remember colors - Color oldBackground = gc.getBackground(); - Color oldForeground = gc.getForeground(); - // draw property - try { - Property property = propertyInfo.getProperty(); - boolean isActiveProperty = - m_activePropertyInfo != null && m_activePropertyInfo.getProperty() == property; - // set background - boolean modified = property.isModified(); - { - if (isActiveProperty) { - gc.setBackground(COLOR_PROPERTY_BG_SELECTED); - } else { - if (modified) { - gc.setBackground(COLOR_PROPERTY_BG_MODIFIED); - } else { - gc.setBackground(COLOR_PROPERTY_BG); - } - } - gc.fillRectangle(0, y, width, height); - } - // draw state image - if (propertyInfo.isShowComplex()) { - Image stateImage = propertyInfo.isExpanded() ? m_minusImage : m_plusImage; - DrawUtils.drawImageCV(gc, stateImage, getTitleX(propertyInfo), y, height); - } - // draw title - { - // configure GC - { - gc.setForeground(COLOR_PROPERTY_FG_TITLE); - // check category - if (getCategory(property).isAdvanced()) { - gc.setForeground(COLOR_PROPERTY_FG_ADVANCED); - gc.setFont(m_italicFont); - } else if (getCategory(property).isPreferred() || getCategory(property).isSystem()) { - gc.setFont(m_boldFont); - } - // check for active - if (isActiveProperty) { - gc.setForeground(COLOR_PROPERTY_FG_SELECTED); - } - } - // paint title - int x = getTitleTextX(propertyInfo); - DrawUtils.drawStringCV(gc, property.getTitle(), x, y, m_splitter - x, height); - } - // draw value - { - // configure GC - gc.setFont(m_baseFont); - if (!isActiveProperty) { - gc.setForeground(COLOR_PROPERTY_FG_VALUE); - } - // prepare value rectangle - int x = m_splitter + 4; - int w = width - x - MARGIN_RIGHT; - // paint value - - // BEGIN ADT MODIFICATIONS - if (!modified) { - gc.setForeground(COLOR_PROPERTY_FG_DEFAULT); - } - // END ADT MODIFICATIONS - - property.getEditor().paint(property, gc, x, y, w, height); - } - } catch (Throwable e) { - DesignerPlugin.log(e); - } finally { - // restore colors - gc.setBackground(oldBackground); - gc.setForeground(oldForeground); - } - } - - //////////////////////////////////////////////////////////////////////////// - // - // PropertyCategory - // - //////////////////////////////////////////////////////////////////////////// - private PropertyCategoryProvider m_propertyCategoryProvider = - PropertyCategoryProviders.fromProperty(); - - /** - * Sets the {@link PropertyCategoryProvider} that can be used to tweak usual - * {@link PropertyCategory}. - */ - public void setPropertyCategoryProvider(PropertyCategoryProvider propertyCategoryProvider) { - m_propertyCategoryProvider = propertyCategoryProvider; - } - - /** - * @return the {@link PropertyCategory} that is used by this {@link PropertyTable} to display. - */ - private PropertyCategory getCategory(Property property) { - return m_propertyCategoryProvider.getCategory(property); - } - - //////////////////////////////////////////////////////////////////////////// - // - // PropertyInfo - // - //////////////////////////////////////////////////////////////////////////// - /** - * Class with information about single {@link Property}. - * - * @author scheglov_ke - */ - private final class PropertyInfo { - private final String m_id; - private final int m_level; - private final Property m_property; - private final boolean m_stateComplex; - private boolean m_stateExpanded; - private List<PropertyInfo> m_children; - - //////////////////////////////////////////////////////////////////////////// - // - // Constructor - // - //////////////////////////////////////////////////////////////////////////// - public PropertyInfo(Property property) { - this(property, "", 0); - } - - private PropertyInfo(Property property, String idPrefix, int level) { - // BEGIN ADT MODIFICATIONS - //m_id = idPrefix + "|" + property.getTitle(); - m_id = idPrefix + "|" + property.getName(); - // END ADT MODIFICATIONS - m_level = level; - m_property = property; - m_stateComplex = property.getEditor() instanceof IComplexPropertyEditor; - } - - //////////////////////////////////////////////////////////////////////////// - // - // State - // - //////////////////////////////////////////////////////////////////////////// - /** - * @return <code>true</code> if this property is complex. - */ - public boolean isComplex() { - return m_stateComplex; - } - - public boolean isShowComplex() throws Exception { - if (m_stateComplex) { - prepareChildren(); - return m_children != null && !m_children.isEmpty(); - } - return false; - } - - /** - * @return <code>true</code> if this complex property is expanded. - */ - public boolean isExpanded() { - return m_stateExpanded; - } - - //////////////////////////////////////////////////////////////////////////// - // - // Access - // - //////////////////////////////////////////////////////////////////////////// - /** - * @return the level of this property, i.e. on which level of complex property it is located. - */ - public int getLevel() { - return m_level; - } - - /** - * @return the {@link Property}. - */ - public Property getProperty() { - return m_property; - } - - /** - * Flips collapsed/expanded state and adds/removes sub-properties. - */ - public void flip() throws Exception { - Assert.isTrue(m_stateComplex); - if (m_stateExpanded) { - collapse(); - } else { - expand(); - } - } - - /** - * Expands this property. - */ - public void expand() throws Exception { - Assert.isTrue(m_stateComplex); - Assert.isTrue(!m_stateExpanded); - // - m_stateExpanded = true; - m_expandedIds.add(m_id); - // BEGIN ADT MODIFICATIONS - if (m_collapsedIds != null) { - m_collapsedIds.remove(m_id); - } - // END ADT MODIFICATIONS - prepareChildren(); - // - int index = m_properties.indexOf(this); - addChildren(index + 1); - } - - /** - * Collapses this property. - */ - public void collapse() throws Exception { - Assert.isTrue(m_stateComplex); - Assert.isTrue(m_stateExpanded); - // - m_stateExpanded = false; - m_expandedIds.remove(m_id); - // BEGIN ADT MODIFICATIONS - if (m_collapsedIds != null) { - m_collapsedIds.add(m_id); - } - // END ADT MODIFICATIONS - prepareChildren(); - // - int index = m_properties.indexOf(this); - removeChildren(index + 1); - } - - //////////////////////////////////////////////////////////////////////////// - // - // Internal - // - //////////////////////////////////////////////////////////////////////////// - /** - * Adds children properties. - * - * @return the index for new properties to add. - */ - private int addChildren(int index) throws Exception { - prepareChildren(); - for (PropertyInfo child : m_children) { - // skip if should not display raw Property - if (!rawProperties_shouldShow(child.m_property)) { - continue; - } - // add child - m_properties.add(index++, child); - // add children of current child - if (child.isExpanded()) { - index = child.addChildren(index); - } - } - return index; - } - - /** - * Removes children properties. - */ - private void removeChildren(int index) throws Exception { - prepareChildren(); - for (PropertyInfo child : m_children) { - // skip if should not display raw Property - if (!rawProperties_shouldShow(child.m_property)) { - continue; - } - // hide presentation - { - PropertyEditorPresentation presentation = - child.getProperty().getEditor().getPresentation(); - if (presentation != null) { - presentation.hide(PropertyTable.this, child.getProperty()); - } - } - // remove child - m_properties.remove(index); - // remove children of current child - if (child.isExpanded()) { - child.removeChildren(index); - } - } - } - - /** - * Prepares children {@link PropertyInfo}'s, for sub-properties. - */ - private void prepareChildren() throws Exception { - if (m_children == null) { - m_children = Lists.newArrayList(); - for (Property subProperty : getSubProperties()) { - PropertyInfo subPropertyInfo = createSubPropertyInfo(subProperty); - m_children.add(subPropertyInfo); - } - } - } - - private PropertyInfo createSubPropertyInfo(Property subProperty) { - return new PropertyInfo(subProperty, m_id, m_level + 1); - } - - private Property[] getSubProperties() throws Exception { - IComplexPropertyEditor complexEditor = (IComplexPropertyEditor) m_property.getEditor(); - List<Property> subProperties = Lists.newArrayList(); - for (Property subProperty : complexEditor.getProperties(m_property)) { - if (getCategory(subProperty).isHidden() && !subProperty.isModified()) { - // skip hidden properties - continue; - } - subProperties.add(subProperty); - } - return subProperties.toArray(new Property[subProperties.size()]); - } - - //////////////////////////////////////////////////////////////////////////// - // - // Persistent expanding support - // - //////////////////////////////////////////////////////////////////////////// - /** - * @return <code>true</code> if this {@link PropertyInfo} was expanded from history. - */ - public boolean expandFromHistory() throws Exception { - if (isComplex() && !isExpanded() && m_expandedIds.contains(m_id)) { - expand(); - return true; - } - // BEGIN ADT MODIFICATIONS - if (m_collapsedIds != null && isComplex() && !isExpanded() - && !m_collapsedIds.contains(m_id)) { - expand(); - return true; - } - // END ADT MODIFICATIONS - return false; - } - } - - // BEGIN ADT MODIFICATIONS - /** Collapse all top-level properties */ - public void collapseAll() { - try { - m_lastExpandCollapseTime = System.currentTimeMillis(); - if (m_collapsedIds != null) { - m_collapsedIds.addAll(m_expandedIds); - } - m_expandedIds.clear(); - setInput(m_rawProperties); - redraw(); - } catch (Throwable e) { - DesignerPlugin.log(e); - } - } - - /** Expand all top-level properties */ - public void expandAll() { - try { - m_lastExpandCollapseTime = System.currentTimeMillis(); - if (m_collapsedIds != null) { - m_collapsedIds.clear(); - } - m_expandedIds.clear(); - for (PropertyInfo info : m_properties) { - if (info.m_stateComplex) { - m_expandedIds.add(info.m_id); - } - } - setInput(m_rawProperties); - redraw(); - } catch (Throwable e) { - DesignerPlugin.log(e); - } - } - // END ADT MODIFICATIONS -}
\ No newline at end of file diff --git a/propertysheet/src/org/eclipse/wb/internal/core/model/property/table/PropertyTableTooltipHelper.java b/propertysheet/src/org/eclipse/wb/internal/core/model/property/table/PropertyTableTooltipHelper.java deleted file mode 100644 index 16b9d8f..0000000 --- a/propertysheet/src/org/eclipse/wb/internal/core/model/property/table/PropertyTableTooltipHelper.java +++ /dev/null @@ -1,191 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2011 Google, Inc. - * 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: - * Google, Inc. - initial API and implementation - *******************************************************************************/ -package org.eclipse.wb.internal.core.model.property.table; - -import org.eclipse.swt.SWT; -import org.eclipse.swt.graphics.Point; -import org.eclipse.swt.widgets.Control; -import org.eclipse.swt.widgets.Display; -import org.eclipse.swt.widgets.Event; -import org.eclipse.swt.widgets.Listener; -import org.eclipse.swt.widgets.Shell; -import org.eclipse.wb.internal.core.EnvironmentUtils; -import org.eclipse.wb.internal.core.model.property.Property; -import org.eclipse.wb.internal.core.utils.ui.GridLayoutFactory; - -/** - * Helper class for displaying tooltips. - * - * @author scheglov_ke - * @coverage core.model.property.table - */ -class PropertyTableTooltipHelper implements IPropertyTooltipSite { - private final PropertyTable m_table; - private Shell m_tooltip; - - //////////////////////////////////////////////////////////////////////////// - // - // Constructor - // - //////////////////////////////////////////////////////////////////////////// - public PropertyTableTooltipHelper(PropertyTable table) { - m_table = table; - m_table.addListener(SWT.MouseHover, new Listener() { - @Override - public void handleEvent(Event event) { - if (event.stateMask == 0) { - showTooltip(); - } - } - }); - m_table.addListener(SWT.MouseExit, new Listener() { - @Override - public void handleEvent(Event event) { - // check, may be cursor is now on tooltip, so ignore this MouseExit - { - Control control = Display.getCurrent().getCursorControl(); - while (control != null) { - if (control == m_tooltip) { - return; - } - control = control.getParent(); - } - } - // no, we should hide tooltip - hideTooltip(); - } - }); - } - - //////////////////////////////////////////////////////////////////////////// - // - // Access - // - //////////////////////////////////////////////////////////////////////////// - private Property m_property; - private boolean m_onTitle; - private boolean m_onValue; - private int m_beginX; - private int m_endX; - private int m_y; - private int m_rowHeight; - - /** - * {@link PropertyTable} call this method to inform that cursor location was changed. - */ - public void update(Property property, - boolean onTitle, - boolean onValue, - int beginX, - int endX, - int y, - int rowHeight) { - m_property = property; - m_onTitle = onTitle; - m_onValue = onValue; - m_beginX = beginX; - m_endX = endX; - m_y = y; - m_rowHeight = rowHeight; - } - - //////////////////////////////////////////////////////////////////////////// - // - // IPropertyTooltipSite - // - //////////////////////////////////////////////////////////////////////////// - @Override -public PropertyTable getTable() { - return m_table; - } - - @Override -public void hideTooltip() { - if (m_tooltip != null && !m_tooltip.isDisposed()) { - m_tooltip.dispose(); - } - m_tooltip = null; - } - - //////////////////////////////////////////////////////////////////////////// - // - // Showing tooltip - // - //////////////////////////////////////////////////////////////////////////// - private void showTooltip() { - hideTooltip(); - // check for property - if (m_property == null) { - return; - } - // - if (m_onTitle) { - showTooltip(m_property.getAdapter(PropertyTooltipProvider.class), m_beginX, m_endX); - } - if (m_onValue) { - showTooltip(m_property.getEditor().getAdapter(PropertyTooltipProvider.class), - m_beginX, m_endX); - } - } - - private void showTooltip(PropertyTooltipProvider provider, int startX, int endX) { - if (provider == null) { - return; - } - // create Shell - { - m_tooltip = new Shell(m_table.getShell(), SWT.NO_FOCUS | SWT.ON_TOP | SWT.TOOL | SWT.SINGLE); - configureColors(m_tooltip); - GridLayoutFactory.create(m_tooltip).noMargins(); - } - // prepare control - Control control = provider.createTooltipControl(m_property, m_tooltip, endX - startX, this); - if (control == null) { - hideTooltip(); - return; - } - // show Shell - { - // prepare tooltip location - Point tooltipLocation; - if (provider.getTooltipPosition() == PropertyTooltipProvider.ON) { - tooltipLocation = m_table.toDisplay(new Point(startX, m_y)); - } else { - tooltipLocation = m_table.toDisplay(new Point(startX, m_y + m_rowHeight)); - } - // set location/size and open - m_tooltip.setLocation(tooltipLocation.x, tooltipLocation.y); - // for non-windows systems the tooltip may have invalid tooltip bounds - // because some widget's API functions may fail if tooltip content is not visible - // ex., on MacOSX tree widget's items has zero bounds since they are not yet visible. - // the workaround is to preset tooltip size to big values before any computeSize called. - if (!EnvironmentUtils.IS_WINDOWS) { - m_tooltip.setSize(1000, 1000); - } - m_tooltip.setSize(m_tooltip.computeSize(SWT.DEFAULT, SWT.DEFAULT)); - provider.show(m_tooltip); - } - } - - //////////////////////////////////////////////////////////////////////////// - // - // Utils - // - //////////////////////////////////////////////////////////////////////////// - /** - * Sets given {@link Control} correct background/foreground for tooltips. - */ - private void configureColors(Control control) { - Display display = Display.getCurrent(); - control.setForeground(display.getSystemColor(SWT.COLOR_INFO_FOREGROUND)); - control.setBackground(display.getSystemColor(SWT.COLOR_INFO_BACKGROUND)); - } -} diff --git a/propertysheet/src/org/eclipse/wb/internal/core/model/property/table/PropertyTooltipProvider.java b/propertysheet/src/org/eclipse/wb/internal/core/model/property/table/PropertyTooltipProvider.java deleted file mode 100644 index 1c3d4fe..0000000 --- a/propertysheet/src/org/eclipse/wb/internal/core/model/property/table/PropertyTooltipProvider.java +++ /dev/null @@ -1,117 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2011 Google, Inc. - * 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: - * Google, Inc. - initial API and implementation - *******************************************************************************/ -package org.eclipse.wb.internal.core.model.property.table; - -import org.eclipse.wb.internal.core.model.property.Property; - -import org.eclipse.swt.SWT; -import org.eclipse.swt.graphics.Point; -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.swt.widgets.Shell; - -/** - * Provider for tooltip controls. - * - * @author scheglov_ke - * @coverage core.model.property.table - */ -public abstract class PropertyTooltipProvider { - /** - * Show tooltip directly on property row. - */ - public static final int ON = 0; - /** - * Show tooltip below property row. - */ - public static final int BELOW = 1; - - //////////////////////////////////////////////////////////////////////////// - // - // PropertyTooltipProvider - // - //////////////////////////////////////////////////////////////////////////// - /** - * Create tooltip control. - */ - public abstract Control createTooltipControl(Property property, - Composite parent, - int availableWidth, - IPropertyTooltipSite site); - - /** - * Shows tooltip {@link Shell}. - */ - public void show(Shell shell) { - shell.setVisible(true); - } - - /** - * Returns position for tooltip control. Usually we should show directly on same row, because we - * use tooltip to show just longer (full) text of property. But for "class" property we show - * hierarchy, so it is better show it below and allow user see also property row. - */ - public int getTooltipPosition() { - return ON; - } - - //////////////////////////////////////////////////////////////////////////// - // - // Tooltip listener - // - //////////////////////////////////////////////////////////////////////////// - /** - * {@link Listener} that hides tooltip on mouse exit or click. - */ - protected static final class HideListener implements Listener { - private final IPropertyTooltipSite m_site; - - //////////////////////////////////////////////////////////////////////////// - // - // Constructor - // - //////////////////////////////////////////////////////////////////////////// - public HideListener(IPropertyTooltipSite site) { - m_site = site; - } - - //////////////////////////////////////////////////////////////////////////// - // - // Listener - // - //////////////////////////////////////////////////////////////////////////// - public void handleEvent(Event event) { - Control tooltipControl = (Control) event.widget; - switch (event.type) { - case SWT.MouseDown : { - PropertyTable table = m_site.getTable(); - // convert location from tooltip to table - Point p = new Point(event.x, event.y); - p = tooltipControl.toDisplay(p); - p = table.toControl(p); - // send MouseDown to table - Event newEvent = new Event(); - newEvent.x = p.x; - newEvent.y = p.y; - table.notifyListeners(SWT.MouseDown, newEvent); - // hide tooltip - m_site.hideTooltip(); - break; - } - case SWT.MouseExit : - m_site.hideTooltip(); - break; - } - } - } -} diff --git a/propertysheet/src/org/eclipse/wb/internal/core/model/property/table/PropertyTooltipTextProvider.java b/propertysheet/src/org/eclipse/wb/internal/core/model/property/table/PropertyTooltipTextProvider.java deleted file mode 100644 index b2e9b69..0000000 --- a/propertysheet/src/org/eclipse/wb/internal/core/model/property/table/PropertyTooltipTextProvider.java +++ /dev/null @@ -1,67 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2011 Google, Inc. - * 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: - * Google, Inc. - initial API and implementation - *******************************************************************************/ -package org.eclipse.wb.internal.core.model.property.table; - -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Control; -import org.eclipse.swt.widgets.Shell; -import org.eclipse.wb.internal.core.model.property.Property; - -/** - * Implementation of {@link PropertyTooltipProvider} for text. - * - * @author scheglov_ke - * @coverage core.model.property.table - */ -public abstract class PropertyTooltipTextProvider extends PropertyTooltipProvider { - //////////////////////////////////////////////////////////////////////////// - // - // PropertyTooltipProvider - // - //////////////////////////////////////////////////////////////////////////// - @Override - public Control createTooltipControl(Property property, - Composite parent, - int availableWidth, - IPropertyTooltipSite site) { - // prepare header and content - String header = null; - String content = null; - try { - // BEGIN ADT MODIFICATIONS - // was: header = property.getTitle(); - header = property.getName(); - // END ADT MODIFICATIONS - content = getText(property); - } catch (Throwable e) { - } - if (header == null || content == null) { - return null; - } - // create tooltip Control - return HtmlTooltipHelper.createTooltipControl(parent, header, content, 8); - } - - @Override - public void show(Shell shell) { - // do nothing, Shell will be displayed when Browser will complete rendering - } - - //////////////////////////////////////////////////////////////////////////// - // - // Text - // - //////////////////////////////////////////////////////////////////////////// - /** - * @return the text to show as tooltip. - */ - protected abstract String getText(Property property) throws Exception; -} diff --git a/propertysheet/src/org/eclipse/wb/internal/core/model/property/table/Tooltip.css b/propertysheet/src/org/eclipse/wb/internal/core/model/property/table/Tooltip.css deleted file mode 100644 index 2ba2a02..0000000 --- a/propertysheet/src/org/eclipse/wb/internal/core/model/property/table/Tooltip.css +++ /dev/null @@ -1,35 +0,0 @@ -/* Font definitions */ -html { font-family: 'Segoe UI','Verdana','Helvetica',sans-serif; font-size: 9pt; font-style: normal; font-weight: normal; } -body, h1, h2, h3, h4, h5, h6, p, table, td, caption, th, ul, ol, dl, li, dd, dt { font-size: 1em; } -pre { font-family: monospace; } - -/* Margins */ -body { overflow: auto; margin-top: 0px; margin-bottom: 0px; margin-left: 0.3em; margin-right: 0.3em; } -div { margin: 0px; } -h1 { margin-top: 0.3em; margin-bottom: 0.04em; } -h2 { margin-top: 2em; margin-bottom: 0.25em; } -h3 { margin-top: 1.7em; margin-bottom: 0.25em; } -h4 { margin-top: 2em; margin-bottom: 0.3em; } -h5 { margin-top: 0px; margin-bottom: 0px; } -p { margin-top: 0em; margin-bottom: 0em; } -pre { margin-left: 0.6em; } -ul { margin-top: 0px; margin-bottom: 1em; } -li { margin-top: 0px; margin-bottom: 0px; } -li p { margin-top: 0px; margin-bottom: 0px; } -ol { margin-top: 0px; margin-bottom: 1em; } -dl { margin-top: 0px; margin-bottom: 1em; } -dt { margin-top: 0px; margin-bottom: 0px; font-weight: bold; } -dd { margin-top: 0px; margin-bottom: 0px; } - -/* Styles and colors */ -a:link { color: #0000FF; } -a:hover { color: #000080; } -a:visited { text-decoration: underline; } -a.header:link { text-decoration: none; color: InfoText } -a.header:visited { text-decoration: none; color: InfoText } -a.header:hover { text-decoration: underline; color: #000080; } -h4 { font-style: italic; } -strong { font-weight: bold; } -em { font-style: italic; } -var { font-style: italic; } -th { font-weight: bold; } |