Java tutorial
/* * JBoss, Home of Professional Open Source. * Copyright 2010, Red Hat, Inc., and individual contributors * as indicated by the @author tags. See the copyright.txt file in the * distribution for a full listing of individual contributors. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package org.jboss.as.console.client.shared.runtime.logviewer; import com.google.gwt.core.client.Scheduler; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; import com.google.gwt.event.logical.shared.AttachEvent; import com.google.gwt.event.logical.shared.ResizeEvent; import com.google.gwt.event.logical.shared.ResizeHandler; import com.google.gwt.event.shared.HandlerRegistration; import com.google.gwt.safehtml.shared.SafeHtmlUtils; import com.google.gwt.user.client.Window; import com.google.gwt.user.client.ui.*; import edu.ycp.cs.dh.acegwt.client.ace.AceEditor; import org.jboss.as.console.client.shared.runtime.logviewer.actions.ChangePageSize; import org.jboss.as.console.client.shared.runtime.logviewer.actions.FollowLogFile; import org.jboss.as.console.client.shared.runtime.logviewer.actions.NavigateInLogFile; import org.jboss.as.console.client.shared.runtime.logviewer.actions.UnFollowLogFile; import org.jboss.ballroom.client.widgets.tools.ToolButton; import org.jboss.ballroom.client.widgets.tools.ToolStrip; import org.jboss.gwt.circuit.Action; import org.jboss.gwt.circuit.Dispatcher; import static com.google.gwt.dom.client.Style.Unit.EM; import static com.google.gwt.dom.client.Style.Unit.PX; import static com.google.gwt.dom.client.Style.VerticalAlign.MIDDLE; import static org.jboss.as.console.client.shared.runtime.logviewer.Direction.*; import static org.jboss.as.console.client.shared.util.IdHelper.setId; /** * Shows a log file in a read-only ACE editor. * * @author Harald Pehl */ public class LogFilePanel extends Composite implements LogViewerId { private final static int HEADER_HEIGHT = 48; // no search + 35; private final static int TOOLS_HEIGHT = 32; private final static int MARGIN_BOTTOM = 50; private final Dispatcher circuit; private final String name; private final VerticalPanel panel; private final AceEditor editor; private final LogFileIndicator indicator; private final Label position; private final HandlerRegistration resizeHandler; private final CheckBox follow; private final ToolButton head; private final ToolButton prev; private final ToolButton next; private final ToolButton tail; private int visibleLines; public LogFilePanel(final Dispatcher circuit, final LogFile logFile) { this.circuit = circuit; this.name = logFile.getName(); panel = new VerticalPanel(); panel.setStyleName("rhs-content-panel"); panel.add(new HTML("<h3>" + logFile.getName() + "</h3>")); // No search box: The search works only inside the currently displayed lines not over the whole // log file. It's better to disable search than having a search which is ambiguous to the user. // panel.add(new SearchBox()); editor = new AceEditor(); editor.addAttachHandler(new AttachEvent.Handler() { @Override public void onAttachOrDetach(AttachEvent event) { if (event.isAttached()) { Scheduler.get().scheduleDeferred(new Scheduler.ScheduledCommand() { @Override public void execute() { editor.startEditor(); editor.setReadOnly(true); editor.setShowGutter(false); editor.setShowPrintMargin(false); editor.setModeByName("logfile"); editor.setThemeByName("logfile"); editor.setText(logFile.getContent()); editor.setVScrollBarVisible(false); } }); } } }); indicator = new LogFileIndicator(); HorizontalPanel editorPanel = new HorizontalPanel(); editorPanel.setStyleName("fill-layout-width"); editorPanel.add(editor); editorPanel.add(indicator); indicator.getElement().getParentElement().getStyle().setWidth(4, PX); indicator.getElement().getParentElement().getStyle().setPaddingLeft(4, PX); panel.add(editorPanel); follow = new CheckBox("Auto Refresh"); follow.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { if (follow.getValue()) { circuit.dispatch(new FollowLogFile()); } else { circuit.dispatch(new UnFollowLogFile()); } } }); setId(follow, BASE_ID, "auto_refresh"); position = new Label(); position.getElement().setAttribute("style", "padding-right:15px;padding-top:4px;"); setId(position, BASE_ID, "position"); head = new ToolButton("Head", new ClickHandler() { @Override public void onClick(ClickEvent event) { onNavigate(HEAD); } }); setId(head, BASE_ID, "head"); prev = new ToolButton("<i class=\"icon-angle-up\"></i>", new ClickHandler() { @Override public void onClick(ClickEvent event) { onNavigate(PREVIOUS); } }); setId(prev, BASE_ID, "prev"); next = new ToolButton("<i class=\"icon-angle-down\"></i>", new ClickHandler() { @Override public void onClick(ClickEvent event) { onNavigate(NEXT); } }); setId(next, BASE_ID, "next"); tail = new ToolButton("Tail", new ClickHandler() { @Override public void onClick(ClickEvent event) { onNavigate(TAIL); } }); setId(tail, BASE_ID, "tail"); ToolStrip navigationTools = new ToolStrip(); navigationTools.addToolWidget(follow); navigationTools.addToolWidgetRight(position); navigationTools.addToolButtonRight(head); navigationTools.addToolButtonRight(prev); navigationTools.addToolButtonRight(next); navigationTools.addToolButtonRight(tail); panel.add(navigationTools); resizeHandler = Window.addResizeHandler(new ResizeHandler() { @Override public void onResize(ResizeEvent event) { LogFilePanel.this.onResize(); } }); initWidget(panel); setStyleName("rhs-content-panel"); } public void refresh(LogFile logFile, Action action) { editor.setText(logFile.getContent()); indicator.refresh(logFile, action); position.setText("Pos. " + (int) Math.floor(indicator.getRatio()) + " %"); follow.setValue(logFile.isFollow()); if (logFile.getLines().size() < visibleLines) { head.setEnabled(false); prev.setEnabled(false); next.setEnabled(false); tail.setEnabled(false); } else { head.setEnabled(!logFile.isHead()); prev.setEnabled(!logFile.isHead()); next.setEnabled(!logFile.isTail()); tail.setEnabled(!logFile.isTail()); } } private void onNavigate(Direction direction) { if (direction == Direction.HEAD || direction == Direction.PREVIOUS) { circuit.dispatch(new UnFollowLogFile()); } circuit.dispatch(new NavigateInLogFile(direction)); } @Override protected void onUnload() { editor.destroy(); resizeHandler.removeHandler(); } public void onResize() { Scheduler.get().scheduleDeferred(new Scheduler.ScheduledCommand() { @Override public void execute() { int panelHeight = panel.getElement().getParentElement().getOffsetHeight(); int editorHeight = panelHeight - HEADER_HEIGHT - TOOLS_HEIGHT - MARGIN_BOTTOM; if (panelHeight > 0) { editor.setHeight(editorHeight + "px"); visibleLines = editorHeight / 16; circuit.dispatch(new ChangePageSize(visibleLines)); } } }); } public String getName() { return name; } /** * Simulates AceEditor's build in search box */ private class SearchBox extends Composite { public SearchBox() { // first part: setup the visible widgets final TextBox findTextBox = new TextBox(); findTextBox.addStyleName("ace_search_field"); findTextBox.getElement().setAttribute("placeholder", "Find"); setId(findTextBox, BASE_ID, "find_input"); ToolButton findButton = new ToolButton("Find", new ClickHandler() { @Override public void onClick(ClickEvent event) { editor.search(findTextBox.getValue()); } }); setId(findButton, BASE_ID, "find"); Button findPrev = new Button(SafeHtmlUtils.fromSafeConstant("<i class=\"icon-angle-left\"></i>")); findPrev.addStyleName("toolstrip-button"); findPrev.getElement().setAttribute("action", "findPrev"); // AceEditor action wiring setId(findPrev, BASE_ID, "prev_match"); Button findNext = new Button(SafeHtmlUtils.fromSafeConstant("<i class=\"icon-angle-right\"></i>")); findNext.addStyleName("toolstrip-button"); findNext.getElement().setAttribute("action", "findNext"); // AceEditor action wiring setId(findNext, BASE_ID, "next_match"); ToolStrip searchTools = new ToolStrip(); searchTools.addToolWidget(findTextBox); searchTools.addToolButton(findButton); searchTools.addToolWidget(findPrev); searchTools.addToolWidget(findNext); findTextBox.getElement().getStyle().setWidth(20, EM); findTextBox.getElement().getStyle().setMarginBottom(0, PX); findTextBox.getElement().getParentElement().getStyle().setVerticalAlign(MIDDLE); findButton.getElement().getParentElement().getStyle().setVerticalAlign(MIDDLE); findPrev.getElement().getParentElement().getStyle().setVerticalAlign(MIDDLE); findNext.getElement().getParentElement().getStyle().setVerticalAlign(MIDDLE); // next part: rebuild the original search box FlowPanel searchForm = div("ace_search_form", false); searchForm.add(searchTools); FlowPanel replaceForm = div("ace_replace_form", true); replaceForm.add(hiddenTextBox("ace_search_field")); replaceForm.add(hiddenButton("replaceAndFindNext", "ace_replacebtn")); replaceForm.add(hiddenButton("replaceAll", "ace_replacebtn")); FlowPanel searchOptions = div("ace_search_options", true); searchOptions.add(hiddenButton("toggleRegexpMode", "ace_button")); searchOptions.add(hiddenButton("toggleCaseSensitive", "ace_button")); searchOptions.add(hiddenButton("toggleWholeWords", "ace_button")); FlowPanel searchBox = div("ace_search_log_viewer", false); searchBox.add(hiddenButton("close", "ace_searchbtn_close")); searchBox.add(searchForm); searchBox.add(replaceForm); searchBox.add(searchOptions); initWidget(searchBox); } private FlowPanel div(String styleName, boolean hidden) { FlowPanel div = new FlowPanel(); div.setStyleName(styleName); if (hidden) { div.setVisible(false); } return div; } private Button hiddenButton(String action, String styleName) { Button button = new Button(); button.setStyleName(styleName); button.getElement().setAttribute("action", action); button.setVisible(false); return button; } private TextBox hiddenTextBox(String styleName) { TextBox textBox = new TextBox(); textBox.setStyleName(styleName); textBox.setVisible(false); return textBox; } } }