aboutsummaryrefslogtreecommitdiff
path: root/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/LintTooltipManager.java
diff options
context:
space:
mode:
Diffstat (limited to 'eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/LintTooltipManager.java')
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/LintTooltipManager.java181
1 files changed, 181 insertions, 0 deletions
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/LintTooltipManager.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/LintTooltipManager.java
new file mode 100644
index 000000000..f71935889
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/LintTooltipManager.java
@@ -0,0 +1,181 @@
+/*
+ * Copyright (C) 2012 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 static com.android.ide.eclipse.adt.internal.editors.layout.gle2.LintOverlay.ICON_SIZE;
+
+import com.android.annotations.Nullable;
+import com.android.ide.eclipse.adt.internal.editors.layout.LayoutEditorDelegate;
+import com.android.ide.eclipse.adt.internal.editors.layout.uimodel.UiViewElementNode;
+import com.android.ide.eclipse.adt.internal.preferences.AdtPrefs;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Shell;
+import org.w3c.dom.Node;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+/** Tooltip in the layout editor showing lint errors under the cursor */
+class LintTooltipManager implements Listener {
+ private final LayoutCanvas mCanvas;
+ private Shell mTip = null;
+ private List<UiViewElementNode> mShowingNodes;
+
+ /**
+ * Sets up a custom tooltip when hovering over tree items. It currently displays the error
+ * message for the lint warning associated with each node, if any (and only if the hover
+ * is over the icon portion).
+ */
+ LintTooltipManager(LayoutCanvas canvas) {
+ mCanvas = canvas;
+ }
+
+ void register() {
+ mCanvas.addListener(SWT.Dispose, this);
+ mCanvas.addListener(SWT.KeyDown, this);
+ mCanvas.addListener(SWT.MouseMove, this);
+ mCanvas.addListener(SWT.MouseHover, this);
+ }
+
+ void unregister() {
+ if (!mCanvas.isDisposed()) {
+ mCanvas.removeListener(SWT.Dispose, this);
+ mCanvas.removeListener(SWT.KeyDown, this);
+ mCanvas.removeListener(SWT.MouseMove, this);
+ mCanvas.removeListener(SWT.MouseHover, this);
+ }
+ }
+
+ @Override
+ public void handleEvent(Event event) {
+ switch(event.type) {
+ case SWT.MouseMove:
+ // See if we're still overlapping this or *other* errors; if so, keep the
+ // tip up (or update it).
+ if (mShowingNodes != null) {
+ List<UiViewElementNode> nodes = computeNodes(event);
+ if (nodes != null && !nodes.isEmpty()) {
+ if (nodes.equals(mShowingNodes)) {
+ return;
+ } else {
+ show(nodes);
+ }
+ break;
+ }
+ }
+
+ // If not, fall through and hide the tooltip
+
+ //$FALL-THROUGH$
+ case SWT.Dispose:
+ case SWT.FocusOut:
+ case SWT.KeyDown:
+ case SWT.MouseExit:
+ case SWT.MouseDown:
+ hide();
+ break;
+ case SWT.MouseHover:
+ hide();
+ show(event);
+ break;
+ }
+ }
+
+ void hide() {
+ if (mTip != null) {
+ mTip.dispose();
+ mTip = null;
+ }
+ mShowingNodes = null;
+ }
+
+ private void show(Event event) {
+ List<UiViewElementNode> nodes = computeNodes(event);
+ if (nodes != null && !nodes.isEmpty()) {
+ show(nodes);
+ }
+ }
+
+ /** Show a tooltip listing the lint errors for the given nodes */
+ private void show(List<UiViewElementNode> nodes) {
+ hide();
+
+ if (!AdtPrefs.getPrefs().isLintOnSave()) {
+ return;
+ }
+
+ mTip = new LintTooltip(mCanvas, nodes);
+ Rectangle rect = mCanvas.getBounds();
+ Point size = mTip.computeSize(SWT.DEFAULT, SWT.DEFAULT);
+ Point pos = mCanvas.toDisplay(rect.x, rect.y + rect.height);
+ if (size.x > rect.width) {
+ size = mTip.computeSize(rect.width, SWT.DEFAULT);
+ }
+ mTip.setBounds(pos.x, pos.y, size.x, size.y);
+
+ mShowingNodes = nodes;
+ mTip.setVisible(true);
+ }
+
+ /**
+ * Compute the list of nodes which have lint warnings near the given mouse
+ * coordinates
+ *
+ * @param event the mouse cursor event
+ * @return a list of nodes, possibly empty
+ */
+ @Nullable
+ private List<UiViewElementNode> computeNodes(Event event) {
+ LayoutPoint p = ControlPoint.create(mCanvas, event.x, event.y).toLayout();
+ LayoutEditorDelegate delegate = mCanvas.getEditorDelegate();
+ ViewHierarchy viewHierarchy = mCanvas.getViewHierarchy();
+ CanvasTransform mHScale = mCanvas.getHorizontalTransform();
+ CanvasTransform mVScale = mCanvas.getVerticalTransform();
+
+ int layoutIconSize = mHScale.inverseScale(ICON_SIZE);
+ int slop = mVScale.inverseScale(10); // extra space around icon where tip triggers
+
+ Collection<Node> xmlNodes = delegate.getLintNodes();
+ if (xmlNodes == null) {
+ return null;
+ }
+ List<UiViewElementNode> nodes = new ArrayList<UiViewElementNode>();
+ for (Node xmlNode : xmlNodes) {
+ CanvasViewInfo v = viewHierarchy.findViewInfoFor(xmlNode);
+ if (v != null) {
+ Rectangle b = v.getAbsRect();
+ int x2 = b.x + b.width;
+ int y2 = b.y + b.height;
+ if (p.x < x2 - layoutIconSize - slop
+ || p.x > x2 + slop
+ || p.y < y2 - layoutIconSize - slop
+ || p.y > y2 + slop) {
+ continue;
+ }
+
+ nodes.add(v.getUiViewNode());
+ }
+ }
+
+ return nodes;
+ }
+}