Java tutorial
/* * Copyright 2008 Google Inc. * * 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.bcdlog.client.edition; import com.bcdlog.client.Client; import com.bcdlog.client.resources.Strings; import com.bcdlog.client.resources.images.edition.Images; import com.bcdlog.client.ui.ClearBothDiv; import com.bcdlog.client.ui.MessageBox; import com.bcdlog.client.ui.PromptClickHandler; import com.bcdlog.client.ui.Trigger; import com.bcdlog.client.ui.TriggerPushButton; import com.bcdlog.client.ui.WindowPanel; import com.bcdlog.client.util.GWTUtils; import com.bcdlog.shared.resources.FrameworkMessages; import com.google.gwt.core.client.GWT; import com.google.gwt.core.client.JsArrayString; import com.google.gwt.event.dom.client.ChangeEvent; import com.google.gwt.event.dom.client.ChangeHandler; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; import com.google.gwt.event.dom.client.KeyUpEvent; import com.google.gwt.event.dom.client.KeyUpHandler; import com.google.gwt.resources.client.ImageResource; import com.google.gwt.user.client.ui.FlowPanel; import com.google.gwt.user.client.ui.Image; import com.google.gwt.user.client.ui.ListBox; import com.google.gwt.user.client.ui.PushButton; import com.google.gwt.user.client.ui.RichTextArea; import com.google.gwt.user.client.ui.ToggleButton; import com.google.gwt.user.client.ui.Widget; /** * A sample toolbar for use with {@link RichTextArea}. It provides a simple UI * for all rich text formatting, dynamically displayed only for the available * functionality. */ public class RichTextToolbar extends FlowPanel { /** * We use an inner EventHandler class to avoid exposing event methods on the * RichTextToolbar itself. */ private class EventHandler implements ClickHandler, ChangeHandler, KeyUpHandler { public void onChange(ChangeEvent event) { Widget sender = (Widget) event.getSource(); if (sender == fontStyles) { setFontStyle(fontStyles.getValue(fontStyles.getSelectedIndex())); fontStyles.setSelectedIndex(0); } else if (sender == fonts) { formatter.setFontName(fonts.getValue(fonts.getSelectedIndex())); fonts.setSelectedIndex(0); } else if (sender == fontSizes) { formatter.setFontSize(fontSizesConstants[fontSizes.getSelectedIndex() - 1]); fontSizes.setSelectedIndex(0); } } public void onClick(ClickEvent event) { Widget sender = (Widget) event.getSource(); if (sender == bold) { formatter.toggleBold(); } else if (sender == italic) { formatter.toggleItalic(); } else if (sender == underline) { formatter.toggleUnderline(); } else if (sender == subscript) { formatter.toggleSubscript(); } else if (sender == superscript) { formatter.toggleSuperscript(); } else if (sender == strikethrough) { formatter.toggleStrikethrough(); } else if (sender == indent) { formatter.rightIndent(); } else if (sender == outdent) { formatter.leftIndent(); } else if (sender == justifyLeft) { formatter.setJustification(RichTextArea.Justification.LEFT); } else if (sender == justifyCenter) { formatter.setJustification(RichTextArea.Justification.CENTER); } else if (sender == justifyRight) { formatter.setJustification(RichTextArea.Justification.RIGHT); } else if (sender == insertSpecialCharacter) { specialCharactersManager.selectCharacter(insertSpecialCharacter); } else if (sender == insertImage) { PromptClickHandler okClickHandler = new PromptClickHandler() { public void onClick(ClickEvent event) { formatter.insertImage(getTextBox().getValue()); } }; MessageBox.prompt(client, strings.enterImageURL(), okClickHandler, (Trigger) sender, "http://"); } else if (sender == createLink) { PromptClickHandler okClickHandler = new PromptClickHandler() { public void onClick(ClickEvent event) { formatter.createLink(getTextBox().getValue()); } }; MessageBox.prompt(client, strings.enterLinkURL(), okClickHandler, (Trigger) sender, getHrefFromSelection()); } else if (sender == removeLink) { formatter.removeLink(); } else if (sender == hr) { formatter.insertHorizontalRule(); } else if (sender == ol) { formatter.insertOrderedList(); } else if (sender == ul) { formatter.insertUnorderedList(); } else if (sender == removeFormat) { formatter.removeFormat(); } else if (sender == backColors) { showColorPicker(sender); } else if (sender == foreColors) { showColorPicker(sender); } else if (sender == richTextArea) { // We use the RichTextArea's onKeyUp event to update the toolbar // status. // This will catch any cases where the user moves the cursur // using the // keyboard, or uses one of the browser's built-in keyboard // shortcuts. updateStatus(); } } public void onKeyUp(KeyUpEvent event) { Widget sender = (Widget) event.getSource(); if (sender == richTextArea) { // We use the RichTextArea's onKeyUp event to update the toolbar // status. // This will catch any cases where the user moves the cursur // using the // keyboard, or uses one of the browser's built-in keyboard // shortcuts. updateStatus(); } } } private static final RichTextArea.FontSize[] fontSizesConstants = new RichTextArea.FontSize[] { RichTextArea.FontSize.XX_SMALL, RichTextArea.FontSize.X_SMALL, RichTextArea.FontSize.SMALL, RichTextArea.FontSize.MEDIUM, RichTextArea.FontSize.LARGE, RichTextArea.FontSize.X_LARGE, RichTextArea.FontSize.XX_LARGE }; private final Images images = (Images) GWT.create(Images.class); private final Strings strings = (Strings) GWT.create(Strings.class); private final EventHandler handler = new EventHandler(); private final RichTextArea richTextArea; private final RichTextArea.Formatter formatter; private final FlowPanel outer = new FlowPanel(); private final FlowPanel buttonsPanel = new FlowPanel(); private ToggleButton bold; private ToggleButton italic; private ToggleButton underline; private ToggleButton subscript; private ToggleButton superscript; private ToggleButton strikethrough; private PushButton indent; private PushButton outdent; private PushButton justifyLeft; private PushButton justifyCenter; private PushButton justifyRight; private PushButton hr; private PushButton ol; private PushButton ul; private PushButton insertImage; private PushButton insertSpecialCharacter; private TriggerPushButton createLink; private PushButton removeLink; private PushButton removeFormat; private PushButton backColors; private PushButton foreColors; private ListBox fonts; private ListBox fontSizes; private ListBox fontStyles; private final Client client; private final WindowPanel backgroundColorChooser; private final WindowPanel foregroundColorChooser; private final RichMessageArea richMessageArea; private final SpecialCharactersManager specialCharactersManager; private int scrollTop; private int scrollLeft; /** * Creates a new toolbar that drives the given rich text area. * * @param richTextArea the rich text area to be controlled */ public RichTextToolbar(final RichMessageArea richMessageArea, final Client client) { this.client = client; this.richMessageArea = richMessageArea; this.richTextArea = (RichTextArea) richMessageArea.getTextArea(); this.formatter = richTextArea.getFormatter(); specialCharactersManager = new SpecialCharactersManager(client, formatter); outer.add(buttonsPanel); outer.add(richTextArea); add(outer); createFullScreenButton(); buttonsPanel.add(createHtmlEdit()); buttonsPanel.add(bold = createToggleButton(images.bold(), strings.bold())); buttonsPanel.add(italic = createToggleButton(images.italic(), strings.italic())); buttonsPanel.add(underline = createToggleButton(images.underline(), strings.underline())); buttonsPanel.add(subscript = createToggleButton(images.subscript(), strings.subscript())); buttonsPanel.add(superscript = createToggleButton(images.superscript(), strings.superscript())); buttonsPanel.add(justifyLeft = createPushButton(images.justifyLeft(), strings.justifyLeft())); buttonsPanel.add(justifyCenter = createPushButton(images.justifyCenter(), strings.justifyCenter())); buttonsPanel.add(justifyRight = createPushButton(images.justifyRight(), strings.justifyRight())); buttonsPanel.add(strikethrough = createToggleButton(images.strikeThrough(), strings.strikeThrough())); buttonsPanel.add(hr = createPushButton(images.hr(), strings.hr())); buttonsPanel.add(ol = createPushButton(images.ol(), strings.ol())); buttonsPanel.add(ul = createPushButton(images.ul(), strings.ul())); buttonsPanel.add(outdent = createPushButton(images.outdent(), strings.outdent())); buttonsPanel.add(indent = createPushButton(images.indent(), strings.indent())); buttonsPanel.add(insertImage = createPushButton(images.insertImage(), strings.insertImage())); buttonsPanel.add(insertSpecialCharacter = createPushButton(images.insertSpecialCharacter(), client.getFrameworkMessages().insertSpecialCharacter())); buttonsPanel.add(createLink = createPushButton(images.createLink(), strings.createLink())); buttonsPanel.add(removeLink = createPushButton(images.removeLink(), strings.removeLink())); buttonsPanel.add(backColors = createPushButton(images.backColors(), strings.background())); backgroundColorChooser = new ColorChooser(client, formatter, strings.background(), ColorChooser.Kind.BACKGROUND); buttonsPanel.add(foreColors = createPushButton(images.foreColors(), strings.foreground())); foregroundColorChooser = new ColorChooser(client, formatter, strings.foreground(), ColorChooser.Kind.FOREGROUND); buttonsPanel.add(removeFormat = createPushButton(images.removeFormat(), strings.removeFormat())); buttonsPanel.add(createFullScreenButton()); buttonsPanel.add(fontStyles = createFontStylesList()); buttonsPanel.add(fonts = createFontList()); buttonsPanel.add(fontSizes = createFontSizes()); // We only use these handlers for updating status, so don't hook them up // unless at least basic editing is supported. richTextArea.addKeyUpHandler(handler); richTextArea.addClickHandler(handler); addStyleName(FrameworkMessages.FWK_PREFIX + "EditorToolbar"); buttonsPanel.add(new ClearBothDiv()); } /** * Add given style to selected text * @param style */ public void setFontStyle(String style) { // Remove parent header ? addTagAroundSelectedText(style); } /** * Add given tag around selected text * @param tag * @return */ private void addTagAroundSelectedText(String tag) { formatter.insertHTML(tag + getSelectedText() + tag.replaceFirst("<", "</")); } /** * Get first occurence of selected text * @return */ private String getSelectedText() { JsArrayString tx = GWTUtils.getSelection(richTextArea.getElement()); return tx.get(0); } /** * Have url around selected text * <a href="http://my.url.com">selectedText</a> * @return */ public String getHrefFromSelection() { return GWTUtils.getHrefFromText(richTextArea.getElement(), getSelectedText()); } /** * Have url around selected image * <img src="http://my.url.com" ... * @return */ public String getSrcFromSelection() { return GWTUtils.getSrcFromText(richTextArea.getElement(), getSelectedText()); } private ToggleButton createFullScreenButton() { final ToggleButton fullScreen = new ToggleButton(new Image(images.fullScreen())); fullScreen.addStyleName(FrameworkMessages.FWK_PREFIX + "fullscreenBtn"); fullScreen.addClickHandler(new ClickHandler() { // To restore originale size public void onClick(ClickEvent event) { if (richMessageArea.getPanel().getStyleName() .contains(FrameworkMessages.FWK_PREFIX + "fullscreen")) { richMessageArea.getPanel().removeStyleName(FrameworkMessages.FWK_PREFIX + "fullscreen"); richMessageArea.restore(); fullScreen.setTitle(client.getFrameworkMessages().fullSreenOn()); } else { // richMessageArea.saveSize(); richMessageArea.enlarge(); fullScreen.setTitle(client.getFrameworkMessages().fullSreenOff()); richMessageArea.getPanel().addStyleName(FrameworkMessages.FWK_PREFIX + "fullscreen"); } } }); fullScreen.setTitle(client.getFrameworkMessages().fullSreenOn()); return fullScreen; } private Widget createHtmlEdit() { final ToggleButton htmlEdit = new ToggleButton(new Image(images.html())); htmlEdit.addClickHandler(new ClickHandler() { public void onClick(ClickEvent event) { ToggleButton editorEdit = new ToggleButton(new Image(images.html())); editorEdit.addClickHandler(new ClickHandler() { public void onClick(ClickEvent event) { richMessageArea.switchToEditor(); htmlEdit.setDown(false); GWTUtils.setScrollTop(richTextArea.getElement(), scrollTop); GWTUtils.setScrollLeft(richTextArea.getElement(), scrollLeft); } }); editorEdit.setDown(true); editorEdit.setTitle(client.getFrameworkMessages().htmlEditOff()); scrollTop = GWTUtils.getScrollTop(richTextArea.getElement()); scrollLeft = GWTUtils.getScrollLeft(richTextArea.getElement()); richMessageArea.switchToHtml(editorEdit, createFullScreenButton()); } }); htmlEdit.setTitle(client.getFrameworkMessages().htmlEditOn()); return htmlEdit; } public void showColorPicker(Widget sender) { if (sender == backColors) { backgroundColorChooser.showAtPreviousPositionOrRelative(sender); } else if (sender == foreColors) { foregroundColorChooser.showAtPreviousPositionOrRelative(sender); } } private ListBox createFontStylesList() { ListBox lb = new ListBox(); lb.addChangeHandler(handler); lb.setVisibleItemCount(1); lb.addItem(strings.fontStyle(), ""); lb.addItem("Paragraph", "<p>"); lb.addItem("Address", "<address>"); lb.addItem("Preformatted", "<pre>"); lb.addItem("Blockquote", "<blockquote>"); lb.addItem("Header 1", "<h1>"); lb.addItem("Header 2", "<h2>"); lb.addItem("Header 3", "<h3>"); lb.addItem("Header 4", "<h4>"); lb.addItem("Header 5", "<h5>"); lb.addItem("Header 6", "<h6>"); return lb; } private ListBox createFontList() { ListBox lb = new ListBox(); lb.addChangeHandler(handler); lb.setVisibleItemCount(1); lb.addItem(strings.font(), ""); lb.addItem("Arial", "Arial"); lb.addItem("Arial Black", "Arial Black"); lb.addItem("Comic Sans MS", "Comic Sans MS"); lb.addItem("Courier New", "Courier New"); lb.addItem("Georgia", "Georgia"); lb.addItem("Impact", "Impact"); lb.addItem("Times New Roman", "Times New Roman"); lb.addItem("Trebuchet MS", "Trebuchet MS"); lb.addItem("Verdana", "Verdana"); return lb; } private ListBox createFontSizes() { ListBox lb = new ListBox(); lb.addChangeHandler(handler); lb.setVisibleItemCount(1); lb.addItem(strings.size()); lb.addItem(strings.xxsmall()); lb.addItem(strings.xsmall()); lb.addItem(strings.small()); lb.addItem(strings.medium()); lb.addItem(strings.large()); lb.addItem(strings.xlarge()); lb.addItem(strings.xxlarge()); return lb; } private TriggerPushButton createPushButton(ImageResource img, String tip) { TriggerPushButton pb = new TriggerPushButton(new Image(img)); pb.addClickHandler(handler); pb.setTitle(tip); return pb; } private ToggleButton createToggleButton(ImageResource img, String tip) { ToggleButton tb = new ToggleButton(new Image(img)); tb.addClickHandler(handler); tb.setTitle(tip); return tb; } /** * Updates the status of all the stateful buttons. */ private void updateStatus() { bold.setDown(formatter.isBold()); italic.setDown(formatter.isItalic()); underline.setDown(formatter.isUnderlined()); subscript.setDown(formatter.isSubscript()); superscript.setDown(formatter.isSuperscript()); strikethrough.setDown(formatter.isStrikethrough()); } }