/* * JaamSim Discrete Event Simulation * Copyright (C) 2013 Ausenco Engineering Canada 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.jaamsim.Graphics; import java.util.ArrayList; import com.jaamsim.DisplayModels.TextModel; import com.jaamsim.StringProviders.StringProvInput; import com.jaamsim.input.BooleanInput; import com.jaamsim.input.ColourInput; import com.jaamsim.input.EntityInput; import com.jaamsim.input.Input; import com.jaamsim.input.InputAgent; import com.jaamsim.input.IntegerInput; import com.jaamsim.input.Keyword; import com.jaamsim.input.StringChoiceInput; import com.jaamsim.input.StringInput; import com.jaamsim.input.StringListInput; import com.jaamsim.input.UnitTypeInput; import com.jaamsim.input.Vec3dInput; import com.jaamsim.units.DimensionlessUnit; import com.jaamsim.units.Unit; /** * OverylayText displays written text as a 2D overlay on a View window. * @author Harry King * */ public class OverlayText extends OverlayEntity { @Keyword(description = "The height of the font as displayed in the view window. Unit is in pixels.", exampleList = {"15"}) private final IntegerInput textHeight; @Keyword(description = "The fixed and variable text to be displayed. If spaces are included, " + "enclose the text in single quotes. If variable text is to be " + "displayed using the DataSource keyword, include the appropriate Java " + "format in the text, such as %s, %.6f, %.6g.", exampleList = {"'Present speed = %.3f m/s'", "'Present State = %s'"}) protected final StringInput formatText; @Keyword(description = "The unit type for the numerical value to be displayed as " + "variable text. Set to DimensionlessUnit if the variable text is " + "non-numeric, such as the state of a Server.", exampleList = {"DistanceUnit", "DimensionlessUnit"}) protected final UnitTypeInput unitType; @Keyword(description = "The unit in which to express an expression that returns a numeric " + "value.", exampleList = {"m/s"}) protected final EntityInput<Unit> unit; @Keyword(description = "An expression that returns the variable text to be displayed. " + "The expression can return a number that will be formated as text, " + "or it can return text directly, such as the state of a Server. " + "An object that returns a number, such as a TimeSeries, can also " + "be entered.", exampleList = {"[Queue1].AverageQueueTime", "[Server1].State", "'[Queue1].QueueLength + [Queue2].QueueLength'", "TimeSeries1"}) protected final StringProvInput dataSource; @Keyword(description = "The text to display if there is any failure while formatting the " + "variable text or while evaluating the expression.", exampleList = {"'Input Error'"}) protected final StringInput failText; @Keyword(description = "The font to be used for the text.", exampleList = { "Arial" }) private final StringChoiceInput fontName; @Keyword(description = "The font styles to be applied to the text, e.g. Bold, Italic. ", exampleList = { "Bold" }) private final StringListInput fontStyle; @Keyword(description = "The colour of the text, specified by a colour keyword or RGB values.", exampleList = { "red", "skyblue", "135 206 235" }) private final ColourInput fontColor; @Keyword(description = "If TRUE, then a drop shadow appears for the text.", exampleList = { "TRUE" }) private final BooleanInput dropShadow; @Keyword(description = "The colour for the drop shadow, specified by a colour keyword or " + "RGB values.", exampleList = { "red", "skyblue", "135 206 235" }) private final ColourInput dropShadowColor; @Keyword(description = "The { x, y, z } coordinates of the drop shadow's offset, expressed " + "as a decimal fraction of the text height.", exampleList = { "0.1 -0.1 0.001" }) private final Vec3dInput dropShadowOffset; private String renderText; { textHeight = new IntegerInput("TextHeight", "Key Inputs", 15); textHeight.setValidRange(0, 1000); this.addInput(textHeight); formatText = new StringInput("Format", "Key Inputs", ""); this.addInput(formatText); unitType = new UnitTypeInput("UnitType", "Key Inputs", DimensionlessUnit.class); this.addInput(unitType); unit = new EntityInput<>(Unit.class, "Unit", "Key Inputs", null); unit.setSubClass(null); this.addInput(unit); dataSource = new StringProvInput("DataSource", "Key Inputs", null); dataSource.setUnitType(DimensionlessUnit.class); dataSource.setEntity(this); this.addInput(dataSource); this.addSynonym(dataSource, "OutputName"); failText = new StringInput("FailText", "Key Inputs", "Input Error"); this.addInput(failText); fontName = new StringChoiceInput("FontName", "Font", -1); fontName.setChoices(TextModel.validFontNames); fontName.setDefaultText("TextModel"); this.addInput(fontName); fontColor = new ColourInput("FontColour", "Font", ColourInput.BLACK); fontColor.setDefaultText("TextModel"); this.addInput(fontColor); this.addSynonym(fontColor, "FontColor"); fontStyle = new StringListInput("FontStyle", "Font", new ArrayList<String>(0)); fontStyle.setValidOptions(TextModel.validStyles); fontStyle.setCaseSensitive(false); fontStyle.setDefaultText("TextModel"); this.addInput(fontStyle); dropShadow = new BooleanInput("DropShadow", "Font", false); dropShadow.setDefaultText("TextModel"); this.addInput(dropShadow); dropShadowColor = new ColourInput("DropShadowColour", "Font", ColourInput.BLACK); dropShadowColor.setDefaultText("TextModel"); this.addInput(dropShadowColor); this.addSynonym(dropShadowColor, "DropShadowColor"); dropShadowOffset = new Vec3dInput("DropShadowOffset", "Font", null); dropShadowOffset.setDefaultText("TextModel"); this.addInput(dropShadowOffset); } public OverlayText() {} @Override public void updateForInput(Input<?> in) { super.updateForInput(in); if (in == unitType) { Class<? extends Unit> ut = unitType.getUnitType(); dataSource.setUnitType(ut); unit.setSubClass(ut); return; } } @Override public void setInputsForDragAndDrop() { super.setInputsForDragAndDrop(); // Set the displayed text to the entity's name InputAgent.applyArgs(this, "Format", this.getName()); } public String getRenderText(double simTime) { // Only static text is to be displayed if( dataSource.getValue() == null ) return formatText.getValue(); // Dynamic text is to be displayed try { double siFactor = 1.0d; if (unit.getValue() != null) siFactor = unit.getValue().getConversionFactorToSI(); return dataSource.getValue().getNextString(simTime, formatText.getValue(), siFactor); } catch (Throwable e) { return failText.getValue(); } } @Override public void updateGraphics(double simTime) { super.updateGraphics(simTime); // This text is cached because reflection is used to get it, so who knows how long it will take String newRenderText = getRenderText(simTime); if (newRenderText.equals(renderText)) { // Nothing important has changed return; } // The text has been updated renderText = newRenderText; } public String getCachedText() { return renderText; } public int getTextHeight() { return textHeight.getValue(); } public StringChoiceInput getFontNameInput() { return fontName; } public StringListInput getFontStyleInput() { return fontStyle; } public ColourInput getFontColorInput() { return fontColor; } public BooleanInput getDropShadowInput() { return dropShadow; } public ColourInput getDropShadowColorInput() { return dropShadowColor; } public Vec3dInput getDropShadowOffsetInput() { return dropShadowOffset; } }