/** * Copyright (C) 2013 Arman Gal * * 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 org.clevermore.monitor.client.widgets; import org.clevermore.monitor.client.AbstractRefreshRequest; import org.clevermore.monitor.client.AbstractRefreshResponse; import org.clevermore.monitor.client.BasicMonitoringRefreshServiceAsync; import com.allen_sauer.gwt.log.client.Log; import com.google.gwt.core.client.Scheduler; import com.google.gwt.core.client.Scheduler.RepeatingCommand; import com.google.gwt.dom.client.Style; import com.google.gwt.dom.client.Style.Cursor; import com.google.gwt.dom.client.Style.Float; import com.google.gwt.dom.client.Style.Unit; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; import com.google.gwt.event.dom.client.MouseOverEvent; import com.google.gwt.event.dom.client.MouseOverHandler; import com.google.gwt.user.client.Timer; import com.google.gwt.user.client.Window; import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.gwt.user.client.ui.Composite; import com.google.gwt.user.client.ui.FlowPanel; import com.google.gwt.user.client.ui.HTML; import com.google.gwt.user.client.ui.Image; import com.google.gwt.user.client.ui.Widget; /** * Abstract composite that every monitoring widget should extend.<br> * Main features is provides:<br> * - Giving correct CSS structure to the destination widget.<br> * - Managing the refresh mechanism.<br> * - * * @author Arman Gal * @param <RQ> * @param <RS> * @param <SR> */ public abstract class AbstractMonitoringWidget<RQ extends AbstractRefreshRequest, RS extends AbstractRefreshResponse, SR extends BasicMonitoringRefreshServiceAsync<RQ, RS>> extends Composite { private SR service; private FlowPanel mainPanel = new FlowPanel(); private FlowPanel header = new FlowPanel(); private FlowPanel dataPanel = new FlowPanel(); /** * default title widget */ private HTML lable = new HTML(); /** * the custom title widget */ private Widget title; /** * refresh progress indicator, it's up to developer to decide if to use it. */ private ProgressLabel refProg = new ProgressLabel(); /** * widget name */ private String name; /** * indicates if to send refresh command. */ private boolean refresh = false; public void forceRefresh() { try { if (isRefresh()) { refProg.progress(); service.refresh(createRefreshRequest(), new AsyncCallback<RS>() { public void onSuccess(RS result) { refresh(result); }; @Override public void onFailure(Throwable caught) { Log.error("Refresh server call failed:" + caught.getMessage(), caught); } }); } } catch (Exception e) { Log.error("Refresh failed:" + e.getMessage(), e); } Log.debug("Reschedule widget refresh" + this.getClass().getName() + " :" + isRefresh()); } private RepeatingCommand refreshCommand = new RepeatingCommand() { @Override public boolean execute() { forceRefresh(); return true; } }; /** * have to be implemented by any widget in order to create correct request to server * * @return - RefreshRequest */ public abstract RQ createRefreshRequest(); /** * Any monitoring widget should implement this one in order to receive fresh data from server and update * the UI. * * @param refershResponse - response received from server */ public abstract void refresh(RS refershResponse); /** * Any monitoring widget should implement this one in order to update the UI or do whatever... * * @param t */ public abstract void refreshFailed(Throwable t); /** * an option to zoom the widget to full screen size */ private ClickHandler zoom = new ClickHandler() { @Override public void onClick(ClickEvent event) { String styles = mainPanel.getStyleName(); if (styles.contains("fullSize")) { mainPanel.removeStyleName("fullSize"); } else { mainPanel.addStyleName("fullSize"); } } }; private MouseOverHandler handCursor = new MouseOverHandler() { @Override public void onMouseOver(MouseOverEvent event) { ((Widget) event.getSource()).getElement().getStyle().setCursor(Cursor.POINTER); } }; public SR getService() { return service; } @Override protected void onAttach() { super.onAttach(); Timer t = new Timer() { @Override public void run() { Log.debug("Monitoring widget attached:" + name); try { Style style = getElement().getStyle(); int absoluteLeft = getAbsoluteLeft(); if (absoluteLeft < Window.getClientWidth() / 2) { style.setFloat(Float.LEFT); Log.debug("Monitoring widget:" + name + " floating to left:" + absoluteLeft); } else { style.setWidth(50, Unit.PCT); style.setFloat(Float.RIGHT); Log.debug("Monitoring widget:" + name + " floating to right:" + absoluteLeft); } } catch (Exception e) { Log.error(e.getMessage(), e); } } }; t.schedule(1000); } /** * @param name - the name of the widget * @param refreshDelay - referesh rate in ms. */ public AbstractMonitoringWidget(final String name, final int refreshDelay, SR service) { this.name = name; this.service = service; header.setStyleName("header"); Image img = new Image(); img.setUrl("img/header-icon.png"); img.addClickHandler(zoom); img.addMouseOverHandler(handCursor); header.add(img); lable.setText(name); lable.setStyleName("lable"); header.add(lable); mainPanel.add(header); mainPanel.add(dataPanel); dataPanel.setStyleName("data"); initWidget(mainPanel); setStyleName("monitoringWidget"); if (refreshDelay > 0) { // first time do the request faster then the original one Scheduler.get().scheduleFixedDelay(new RepeatingCommand() { @Override public boolean execute() { forceRefresh(); Scheduler.get().scheduleFixedDelay(refreshCommand, refreshDelay); return false; } }, 1); } setRefresh(true); } public FlowPanel getDataPanel() { return dataPanel; } public void updateTitle(String title) { this.lable.setText(title); } public void setTitleWidget(Widget title) { lable.removeFromParent(); header.add(title); this.title = title; } public Widget getTitleWidget() { return this.title; } public boolean isRefresh() { return refresh; } public void setRefresh(boolean refresh) { Log.debug(refresh ? "Enabling " : "Disabling " + name + " widget refresh mechinism."); this.refresh = refresh; } public ProgressLabel getRefProg() { return refProg; } }