/* * Copyright 2014-2015 Cel Skeggs. * * This file is part of the CCRE, the Common Chicken Runtime Engine. * * The CCRE 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 3 of the License, or (at your option) any * later version. * * The CCRE 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 the CCRE. If not, see <http://www.gnu.org/licenses/>. */ package ccre.supercanvas.components.channels; import java.awt.Color; import java.awt.FontMetrics; import java.awt.Graphics2D; import ccre.channel.CancelOutput; import ccre.channel.EventInput; import ccre.channel.EventOutput; import ccre.rconf.RConf.Entry; import ccre.supercanvas.BaseChannelComponent; import ccre.supercanvas.Rendering; import ccre.supercanvas.SuperCanvasPanel; /** * A component allowing display of events. * * @author skeggsc */ public class EventDisplayComponent extends BaseChannelComponent<EventDisplayComponent.View> implements EventOutput { static enum View { FLASHING_LIGHT, TIME_COUNTER, TEXTUAL } private static final long serialVersionUID = 7298197110274322991L; private transient long countStart; private boolean subscribed; private final EventInput inp; private transient CancelOutput unsubscribe; /** * Create a new EventDisplayComponent with a EventInput to read from. * * @param cx the X coordinate. * @param cy the Y coordinate. * @param name the name of the input. * @param inp the EventInput to read from. */ public EventDisplayComponent(int cx, int cy, String name, EventInput inp) { super(cx, cy, name); this.inp = inp; } /** * Create a new EventDisplayComponent. * * @param cx the X coordinate. * @param cy the Y coordinate. * @param name the name of the input. */ public EventDisplayComponent(int cx, int cy, String name) { this(cx, cy, name, null); } @Override public void channelRender(Graphics2D g, int screenWidth, int screenHeight, FontMetrics fontMetrics, int mouseX, int mouseY) { long count = (System.currentTimeMillis() - countStart); switch (activeView) { case FLASHING_LIGHT: int rad = Math.min(halfWidth / 3, halfHeight / 3); int trad = Math.round(rad * (1 - Math.min(1, Math.max(count / 500.0f, 0)))); g.setColor(Color.BLACK); g.fillOval(centerX - rad, centerY - rad, rad * 2, rad * 2); g.setColor(Rendering.blend(Color.GREEN, Color.BLACK, count / 500.0f)); g.fillOval(centerX - trad, centerY - trad, trad * 2, trad * 2); g.setColor(Color.BLACK); g.drawOval(centerX - rad, centerY - rad, rad * 2, rad * 2); break; case TIME_COUNTER: g.setFont(Rendering.labels); g.setColor(Color.BLACK); String text = countStart == 0 ? "NEVER" : String.format("%2.1fs", count / 1000.0); g.drawString(text, centerX - g.getFontMetrics().stringWidth(text) / 2, centerY + g.getFontMetrics().getAscent() / 2); break; case TEXTUAL: g.setFont(Rendering.labels); g.setColor(Color.BLACK); text = count < 500 ? "YES" : "NO"; g.drawString(text, centerX - g.getFontMetrics().stringWidth(text) / 2, centerY + g.getFontMetrics().getAscent() / 2); break; } } @Override public boolean onInteract(int x, int y) { return false; } @Override protected void onChangePanel(SuperCanvasPanel panel) { boolean hasPanel = panel != null; if (inp != null && hasPanel != subscribed) { if (unsubscribe != null) { unsubscribe.cancel(); unsubscribe = null; } if (hasPanel) { unsubscribe = inp.send(this); } subscribed = hasPanel; } } @Override public void event() { countStart = System.currentTimeMillis(); } @Override protected void setDefaultView() { activeView = View.FLASHING_LIGHT; } @Override public Entry[] queryRConf() throws InterruptedException { return rconfBase(); } @Override public boolean signalRConf(int field, byte[] data) throws InterruptedException { return rconfBase(field, data) == BASE_VALID; } }