/*
* Copyright (C) 2010 The Android Open Source Project
*
* Licensed under the Eclipse Public License, Version 1.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.eclipse.org/org/documents/epl-v10.php
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.ide.eclipse.adt.internal.editors.layout.gle2;
import org.eclipse.jface.action.IStatusLineManager;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.graphics.Region;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
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.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeItem;
import org.eclipse.ui.IActionBars;
import org.eclipse.ui.views.properties.IPropertySheetEntry;
import org.eclipse.ui.views.properties.PropertySheetEntry;
/**
* A customized property sheet page for the graphical layout editor v2.
* <p/>
* Currently it just provides a custom tooltip to display attributes javadocs.
* <p/>
* The property sheet is linked to the current site's selection service.
* <p/>
* Note: this is an exact copy of GLE1's UiPropertySheetPage implementation.
* The idea is that eventually GLE1 will go away and we'll upgrade this to be
* a more robust property editor (it currently lacks on so many levels, it's not
* even worth listing the flaws.)
*
* @since GLE2
*/
public class PropertySheetPage extends org.eclipse.ui.views.properties.PropertySheetPage {
public PropertySheetPage() {
super();
}
@Override
public void createControl(Composite parent) {
super.createControl(parent);
setupTooltip();
// Override parent class' "set status message" behavior. The parent will set
// the status message to the property's "getDescription()" field. That field
// may contain newlines, which means the text gets cut off. We want to instead
// show ALL the text, fit on a single line, and since we don't get to subclass
// the viewer we will just replace the status message with our own, which works
// since our mouse listener is registered later so runs later.
final Tree tree = (Tree) getControl();
tree.addMouseListener(new MouseAdapter() {
@Override
public void mouseDown(MouseEvent event) {
Point pt = new Point(event.x, event.y);
TreeItem item = tree.getItem(pt);
if (item != null) {
Object object = item.getData();
if (object instanceof IPropertySheetEntry) {
IPropertySheetEntry entry = (IPropertySheetEntry) object;
String help = entry.getDescription();
if (help != null) {
// Strip out newlines to make this a single line entry
help = help.replace('\n', ' ');
// Remove repeated spaces in case there were trailing spaces
help = help.replaceAll(" ", " "); //$NON-NLS-1$ //$NON-NLS-2$
IActionBars actionBars = getSite().getActionBars();
IStatusLineManager status = actionBars.getStatusLineManager();
status.setMessage(help);
}
}
}
}
});
// Fix the selection background. In Eclipse 3.5 and 3.6, the selection color
// is white, painted on top of a white or light blue background (table striping),
// which is practically unreadable. This is fixed in 3.7M3, but we need a workaround
// for earlier releases. The following code performs custom painting of this region,
// and is based on the snippet "draw a custom gradient selection for tree" (snippet 226)
// from http://www.eclipse.org/swt/snippets/ .
tree.addListener(SWT.EraseItem, new Listener() {
public void handleEvent(Event event) {
if ((event.detail & SWT.SELECTED) != 0) {
GC gc = event.gc;
Rectangle area = tree.getClientArea();
int columnCount = tree.getColumnCount();
if (event.index == columnCount - 1 || columnCount == 0) {
int width = area.x + area.width - event.x;
if (width > 0) {
Region region = new Region();
gc.getClipping(region);
region.add(event.x, event.y, width, event.height);
gc.setClipping(region);
region.dispose();
}
}
gc.setAdvanced(true);
if (gc.getAdvanced()) {
gc.setAlpha(127);
}
Rectangle rect = event.getBounds();
Color foreground = gc.getForeground();
Color background = gc.getBackground();
Display display = tree.getDisplay();
gc.setForeground(display.getSystemColor(SWT.COLOR_LIST_SELECTION));
gc.setBackground(display.getSystemColor(SWT.COLOR_LIST_BACKGROUND));
gc.fillGradientRectangle(0, rect.y, 500, rect.height, false);
gc.setForeground(foreground);
gc.setBackground(background);
event.detail &= ~SWT.SELECTED;
}
}
});
}
/**
* Sets up a custom tooltip when hovering over tree items.
* <p/>
* The tooltip will display the element's javadoc, if any, or the item's getText otherwise.
*/
private void setupTooltip() {
final Tree tree = (Tree) getControl();
/*
* Reference:
* http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.swt.snippets/src/org/eclipse/swt/snippets/Snippet125.java?view=markup
*/
final Listener listener = new Listener() {
Shell tip = null;
Label label = null;
public void handleEvent(Event event) {
switch(event.type) {
case SWT.Dispose:
case SWT.KeyDown:
case SWT.MouseExit:
case SWT.MouseDown:
case SWT.MouseMove:
if (tip != null) {
tip.dispose();
tip = null;
label = null;
}
break;
case SWT.MouseHover:
if (tip != null) {
tip.dispose();
tip = null;
label = null;
}
String tooltip = null;
TreeItem item = tree.getItem(new Point(event.x, event.y));
if (item != null) {
Object data = item.getData();
if (data instanceof PropertySheetEntry) {
tooltip = ((PropertySheetEntry) data).getDescription();
}
if (tooltip == null) {
tooltip = item.getText();
} else {
tooltip = item.getText() + ":\r" + tooltip;
}
if (tooltip != null) {
Shell shell = tree.getShell();
Display display = tree.getDisplay();
tip = new Shell(shell, SWT.ON_TOP | SWT.NO_FOCUS | SWT.TOOL);
tip.setBackground(display .getSystemColor(SWT.COLOR_INFO_BACKGROUND));
FillLayout layout = new FillLayout();
layout.marginWidth = 2;
tip.setLayout(layout);
label = new Label(tip, SWT.NONE);
label.setForeground(display.getSystemColor(SWT.COLOR_INFO_FOREGROUND));
label.setBackground(display.getSystemColor(SWT.COLOR_INFO_BACKGROUND));
label.setData("_TABLEITEM", item);
label.setText(tooltip);
label.addListener(SWT.MouseExit, this);
label.addListener(SWT.MouseDown, this);
Point size = tip.computeSize(SWT.DEFAULT, SWT.DEFAULT);
Rectangle rect = item.getBounds(0);
// Display the tooltip on the same line as the property,
// but offset to the right of wherever the mouse cursor was,
// such that it does not obscure the list of properties.
Point pt = tree.toDisplay(event.x + 15, rect.y);
tip.setBounds(pt.x, pt.y, size.x, size.y);
tip.setVisible(true);
}
}
}
}
};
tree.addListener(SWT.Dispose, listener);
tree.addListener(SWT.KeyDown, listener);
tree.addListener(SWT.MouseMove, listener);
tree.addListener(SWT.MouseHover, listener);
}
}