diff options
Diffstat (limited to 'gerrit-gwtexpui/src/main/java/com/google/gwtexpui/clippy/client/CopyableLabel.java')
-rw-r--r-- | gerrit-gwtexpui/src/main/java/com/google/gwtexpui/clippy/client/CopyableLabel.java | 230 |
1 files changed, 230 insertions, 0 deletions
diff --git a/gerrit-gwtexpui/src/main/java/com/google/gwtexpui/clippy/client/CopyableLabel.java b/gerrit-gwtexpui/src/main/java/com/google/gwtexpui/clippy/client/CopyableLabel.java new file mode 100644 index 0000000000..273318be51 --- /dev/null +++ b/gerrit-gwtexpui/src/main/java/com/google/gwtexpui/clippy/client/CopyableLabel.java @@ -0,0 +1,230 @@ +// Copyright (C) 2009 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0 +// +// 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.google.gwtexpui.clippy.client; + +import com.google.gwt.core.client.GWT; +import com.google.gwt.core.client.Scheduler; +import com.google.gwt.event.dom.client.BlurEvent; +import com.google.gwt.event.dom.client.BlurHandler; +import com.google.gwt.event.dom.client.ClickEvent; +import com.google.gwt.event.dom.client.ClickHandler; +import com.google.gwt.event.dom.client.KeyPressEvent; +import com.google.gwt.event.dom.client.KeyPressHandler; +import com.google.gwt.http.client.URL; +import com.google.gwt.user.client.Command; +import com.google.gwt.user.client.DOM; +import com.google.gwt.user.client.Element; +import com.google.gwt.user.client.ui.Composite; +import com.google.gwt.user.client.ui.FlowPanel; +import com.google.gwt.user.client.ui.HasText; +import com.google.gwt.user.client.ui.InlineLabel; +import com.google.gwt.user.client.ui.Label; +import com.google.gwt.user.client.ui.TextBox; +import com.google.gwtexpui.safehtml.client.SafeHtml; +import com.google.gwtexpui.safehtml.client.SafeHtmlBuilder; +import com.google.gwtexpui.user.client.UserAgent; + +/** + * Label which permits the user to easily copy the complete content. + * <p> + * If the Flash plugin is available a "movie" is embedded that provides + * one-click copying of the content onto the system clipboard. The label (if + * visible) can also be clicked, switching from a label to an input box, + * allowing the user to copy the text with a keyboard shortcut. + */ +public class CopyableLabel extends Composite implements HasText { + private static final int SWF_WIDTH = 110; + private static final int SWF_HEIGHT = 14; + private static String swfUrl; + private static boolean flashEnabled = true; + + static { + ClippyResources.I.css().ensureInjected(); + } + + public static boolean isFlashEnabled() { + return flashEnabled; + } + + public static void setFlashEnabled(final boolean on) { + flashEnabled = on; + } + + private static String swfUrl() { + if (swfUrl == null) { + swfUrl = GWT.getModuleBaseURL() + "gwtexpui_clippy1.cache.swf"; + } + return swfUrl; + } + + private final FlowPanel content; + private String text; + private int visibleLen; + private Label textLabel; + private TextBox textBox; + private Element swf; + + /** + * Create a new label + * + * @param str initial content + */ + public CopyableLabel(final String str) { + this(str, true); + } + + /** + * Create a new label + * + * @param str initial content + * @param showLabel if true, the content is shown, if false it is hidden from + * view and only the copy icon is displayed. + */ + public CopyableLabel(final String str, final boolean showLabel) { + content = new FlowPanel(); + initWidget(content); + + text = str; + visibleLen = text.length(); + + if (showLabel) { + textLabel = new InlineLabel(getText()); + textLabel.setStyleName(ClippyResources.I.css().label()); + textLabel.addClickHandler(new ClickHandler() { + @Override + public void onClick(final ClickEvent event) { + showTextBox(); + } + }); + content.add(textLabel); + } + embedMovie(); + } + + /** + * Change the text which is displayed in the clickable label. + * + * @param text the new preview text, should be shorter than the original text + * which would be copied to the clipboard. + */ + public void setPreviewText(final String text) { + if (textLabel != null) { + textLabel.setText(text); + visibleLen = text.length(); + } + } + + private void embedMovie() { + if (flashEnabled && UserAgent.hasFlash) { + final String flashVars = "text=" + URL.encodeQueryString(getText()); + final SafeHtmlBuilder h = new SafeHtmlBuilder(); + + h.openElement("div"); + h.setStyleName(ClippyResources.I.css().control()); + + h.openElement("object"); + h.setWidth(SWF_WIDTH); + h.setHeight(SWF_HEIGHT); + h.setAttribute("classid", "clsid:d27cdb6e-ae6d-11cf-96b8-444553540000"); + h.paramElement("movie", swfUrl()); + h.paramElement("FlashVars", flashVars); + + h.openElement("embed"); + h.setWidth(SWF_WIDTH); + h.setHeight(SWF_HEIGHT); + h.setAttribute("wmode", "transparent"); + h.setAttribute("type", "application/x-shockwave-flash"); + h.setAttribute("src", swfUrl()); + h.setAttribute("FlashVars", flashVars); + h.closeSelf(); + + h.closeElement("object"); + h.closeElement("div"); + + if (swf != null) { + DOM.removeChild(getElement(), swf); + } + DOM.appendChild(getElement(), swf = SafeHtml.parse(h)); + } + } + + public String getText() { + return text; + } + + public void setText(final String newText) { + text = newText; + visibleLen = newText.length(); + + if (textLabel != null) { + textLabel.setText(getText()); + } + if (textBox != null) { + textBox.setText(getText()); + textBox.selectAll(); + } + embedMovie(); + } + + private void showTextBox() { + if (textBox == null) { + textBox = new TextBox(); + textBox.setText(getText()); + textBox.setVisibleLength(visibleLen); + textBox.addKeyPressHandler(new KeyPressHandler() { + @Override + public void onKeyPress(final KeyPressEvent event) { + if (event.isControlKeyDown() || event.isMetaKeyDown()) { + switch (event.getCharCode()) { + case 'c': + case 'x': + Scheduler.get().scheduleDeferred(new Command() { + public void execute() { + hideTextBox(); + } + }); + break; + } + } + } + }); + textBox.addBlurHandler(new BlurHandler() { + @Override + public void onBlur(final BlurEvent event) { + hideTextBox(); + } + }); + content.insert(textBox, 1); + } + + textLabel.setVisible(false); + textBox.setVisible(true); + Scheduler.get().scheduleDeferred(new Command() { + @Override + public void execute() { + textBox.selectAll(); + textBox.setFocus(true); + } + }); + } + + private void hideTextBox() { + if (textBox != null) { + textBox.removeFromParent(); + textBox = null; + } + textLabel.setVisible(true); + } +} |