/* * Copyright (c) 2010, Michael Grossmann * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of the jo-widgets.org nor the * names of its contributors may be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * DAMAGE. */ package org.jowidgets.impl.widgets.composed; import org.jowidgets.api.color.Colors; import org.jowidgets.api.controller.IPaintEvent; import org.jowidgets.api.graphics.IGraphicContext; import org.jowidgets.api.graphics.IPaintListener; import org.jowidgets.api.model.levelmeter.ILevelListener; import org.jowidgets.api.model.levelmeter.ILevelMeterModel; import org.jowidgets.api.widgets.ICanvas; import org.jowidgets.api.widgets.IComposite; import org.jowidgets.api.widgets.ILevelMeter; import org.jowidgets.api.widgets.descriptor.setup.ILevelMeterSetup; import org.jowidgets.common.color.IColorConstant; import org.jowidgets.tools.layout.MigLayoutFactory; import org.jowidgets.tools.widgets.blueprint.BPF; import org.jowidgets.tools.widgets.invoker.ColorSettingsInvoker; import org.jowidgets.tools.widgets.invoker.VisibiliySettingsInvoker; import org.jowidgets.tools.widgets.wrapper.ControlWrapper; public final class LevelMeterImpl extends ControlWrapper implements ILevelMeter { private static final String UPPER_SCALE_LETTERING = "0db"; private static final String LOWER_SCALE_LETTERING = "-" + Character.toString('\u221E'); private static final int GAP_BETWEEN_SCALE_TEXT_AND_SCALE_LINE = 2; private static final int LENGTH_OF_LONGER_SCALE_LINE = 7; private static final int LENGTH_OF_SMALLER_SCALE_LINE = 3; private static final int GAP_BETWEEN_SCALE_AND_BAR = 7; private final ILevelMeterModel model; private final ILevelListener levelListener; private final ILevelMeterSetup setup; private final ICanvas canvas; private double lastLevel; public LevelMeterImpl(final IComposite composite, final ILevelMeterSetup setup) { super(composite); this.model = setup.getModel(); this.setup = setup; this.lastLevel = -1; VisibiliySettingsInvoker.setVisibility(setup, this); ColorSettingsInvoker.setColors(setup, this); composite.setLayout(MigLayoutFactory.growingInnerCellLayout()); canvas = composite.add(BPF.canvas(), MigLayoutFactory.GROWING_CELL_CONSTRAINTS); this.levelListener = new ILevelListener() { @Override public void levelChanged(final double oldValue, final double newValue) { if (lastLevel == -1 || lastLevel != newValue) { canvas.redraw(); lastLevel = newValue; } } }; model.addLevelListener(levelListener); canvas.addPaintListener(new IPaintListener() { @Override public void paint(final IPaintEvent paintEvent) { final IGraphicContext gc = paintEvent.getGraphicContext(); paintCanvas(gc); } }); } @Override public ILevelMeterModel getModel() { return model; } @Override public void dispose() { model.removesLevelListener(levelListener); super.dispose(); } private void paintCanvas(final IGraphicContext gc) { final int gapSize = setup.getGapSize(); final int boxHeight = setup.getBoxHeight(); final int canvasHeight = gc.getBounds().getHeight(); final int canvasWidth = gc.getBounds().getWidth(); final int baseline = canvasHeight; //clear canvas gc.clearRectangle(0, 0, canvasWidth, canvasHeight); gc.setForegroundColor(setup.getBackgroundColor()); gc.fillRectangle(0, 0, canvasWidth, canvasHeight); //calculate box data depending on canvas height final int numberOfBoxes = calculateNumberOfBoxes(canvasHeight, boxHeight, gapSize); final int numberOfActiveBoxes = (int) Math.round(numberOfBoxes * model.getLevel()); final int numberOfLowPeakBoxes = (int) Math.round(numberOfBoxes * setup.getHighPeakThreshold()); final int numberOfHighPeakBoxes = (int) Math.round(numberOfBoxes * setup.getClipPeakThreshold()); int letteringWidth = 0; //draw scale of configured to do so if (setup.isLetteringVisible()) { gc.setForegroundColor(Colors.BLACK); final int heightOfOneScaleSector = canvasHeight / 10; final int lengthOfLongestScaleLettering = gc.getTextWidth(UPPER_SCALE_LETTERING); letteringWidth = lengthOfLongestScaleLettering + GAP_BETWEEN_SCALE_TEXT_AND_SCALE_LINE + LENGTH_OF_LONGER_SCALE_LINE + GAP_BETWEEN_SCALE_AND_BAR; for (int i = 0; i < 11; i++) { if (i == 0 || i == 5 || i == 10) { gc.setLineWidth(2); gc.drawLine(lengthOfLongestScaleLettering + GAP_BETWEEN_SCALE_TEXT_AND_SCALE_LINE, baseline - 1 - (i * heightOfOneScaleSector), lengthOfLongestScaleLettering + GAP_BETWEEN_SCALE_TEXT_AND_SCALE_LINE + LENGTH_OF_LONGER_SCALE_LINE, baseline - 1 - (i * heightOfOneScaleSector)); } else { gc.setLineWidth(1); gc.drawLine(lengthOfLongestScaleLettering + GAP_BETWEEN_SCALE_TEXT_AND_SCALE_LINE + 2, baseline - 1 - (i * heightOfOneScaleSector), lengthOfLongestScaleLettering + GAP_BETWEEN_SCALE_TEXT_AND_SCALE_LINE + 2 + LENGTH_OF_SMALLER_SCALE_LINE, baseline - 1 - (i * heightOfOneScaleSector)); } if (i == 0) { final int fontHeight = gc.getFontMetrics().getHeight(); gc.drawText(LOWER_SCALE_LETTERING, 0, baseline - fontHeight - 2 - (i * heightOfOneScaleSector)); } if (i == 10) { final int fontHeight = gc.getFontMetrics().getHeight(); gc.drawText(UPPER_SCALE_LETTERING, 0, baseline - fontHeight / 2 - 2 - (i * heightOfOneScaleSector)); } } } IColorConstant boxColor = setup.getLowPeakColor(); //draw boxes for (int i = 0; i < numberOfBoxes; i++) { if (i + 1 > numberOfLowPeakBoxes) { boxColor = setup.getHighPeakColor(); } if (i + 1 > numberOfHighPeakBoxes) { boxColor = setup.getClipPeakColor(); } if (i + 1 > numberOfActiveBoxes) { boxColor = setup.getNoPeakColor(); } final int y = baseline - i * (gapSize + boxHeight) - boxHeight - gapSize; gc.setForegroundColor(boxColor); gc.fillRectangle(letteringWidth + gapSize, y, canvasWidth - 2 * gapSize, boxHeight); } } private int calculateNumberOfBoxes(final int canvasHeight, final int boxHeight, final int gapSize) { int result = canvasHeight / (boxHeight + gapSize); if (result * boxHeight + ((result + 1) * gapSize) > canvasHeight) { result--; } return result; } @Override public void setToolTipText(final String toolTip) { canvas.setToolTipText(toolTip); } }