001: /*
002: *
003: * Copyright (c) 2007, Sun Microsystems, Inc.
004: *
005: * All rights reserved.
006: *
007: * Redistribution and use in source and binary forms, with or without
008: * modification, are permitted provided that the following conditions
009: * are met:
010: *
011: * * Redistributions of source code must retain the above copyright
012: * notice, this list of conditions and the following disclaimer.
013: * * Redistributions in binary form must reproduce the above copyright
014: * notice, this list of conditions and the following disclaimer in the
015: * documentation and/or other materials provided with the distribution.
016: * * Neither the name of Sun Microsystems nor the names of its contributors
017: * may be used to endorse or promote products derived from this software
018: * without specific prior written permission.
019: *
020: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
021: * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
022: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
023: * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
024: * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
025: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
026: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
027: * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
028: * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
029: * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
030: * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
031: */
032: package com.sun.svg.component;
033:
034: import org.w3c.dom.Document;
035: import org.w3c.dom.svg.SVGElement;
036: import org.w3c.dom.svg.SVGLocatableElement;
037: import org.w3c.dom.svg.SVGMatrix;
038: import org.w3c.dom.svg.SVGRect;
039: import org.w3c.dom.svg.SVGSVGElement;
040:
041: /**
042: * The SVGProgressBar class is a primitive component which can be attached to
043: * SVG markup which follows the expected structure for a progress bar.
044: *
045: * The expected structure for the progress bar is that there is a background
046: * element which defines the maximum size for the progress indicator and there
047: * is a progress indicator which should be scaled, along the horizontal axis,
048: * to reflect the progress value. The code also expects a text indicator to display
049: * the value as <progress>%.
050: *
051: * The code assumes that the progressBar background and the progress indicator
052: * have the same x=axis origin.
053: */
054: public class SVGProgressBar {
055: static final String PROGRESS_SUFFIX = "progress";
056: static final String BACKGROUND_SUFFIX = "bkg";
057: static final String TEXT_SUFFIX = "text";
058:
059: /**
060: * The progress bar progress indicator
061: */
062: protected SVGLocatableElement progress;
063:
064: /**
065: * The progress's initial transform.
066: */
067: protected SVGMatrix progressTxf;
068:
069: /**
070: * The progress indicator's bounding box.
071: */
072: protected SVGRect progressBBox;
073:
074: /**
075: * The min scale of the progress bar along the x-axis
076: */
077: protected float minScale;
078:
079: /**
080: * The max scale for the progress bar along the y-axis
081: */
082: protected float maxScale;
083:
084: /**
085: * The document's root svg element.
086: */
087: protected SVGSVGElement svg;
088:
089: /**
090: * The progress bar's text display.
091: */
092: protected SVGElement text;
093:
094: /**
095: * The prefix used for all the elements in the scroll bar component.
096: */
097: protected String idPrefix;
098:
099: /**
100: * The current progress bar position in the [0,1] range.
101: */
102: protected float pos;
103:
104: /**
105: * @param idPrefix - the progress bar group identifier.
106: */
107: public SVGProgressBar(final String idPrefix) {
108: if (idPrefix == null || "".equals(idPrefix)) {
109: throw new IllegalArgumentException(
110: "SVGProgressBar id prefix "
111: + "should not be null or empty");
112: }
113:
114: this .idPrefix = idPrefix;
115: }
116:
117: /**
118: * Hooks the input skin to this user interface component.
119: *
120: * @param doc - the new Document skin containing the associated progress
121: * bar elements.
122: */
123: public void hookSkin(final Document doc) {
124: svg = (SVGSVGElement) doc.getDocumentElement();
125: SVGLocatableElement bkg = (SVGLocatableElement) doc
126: .getElementById(idPrefix + "." + BACKGROUND_SUFFIX);
127:
128: if (bkg == null) {
129: throw new IllegalArgumentException(
130: "SVGProgressBar : element with id " + idPrefix
131: + "." + BACKGROUND_SUFFIX
132: + " does not exist in skin");
133: }
134:
135: progress = (SVGLocatableElement) doc.getElementById(idPrefix
136: + "." + PROGRESS_SUFFIX);
137:
138: if (progress == null) {
139: throw new IllegalArgumentException(
140: "SVGProgressBar : element with id " + idPrefix
141: + "." + PROGRESS_SUFFIX
142: + " does not exist is skin");
143: }
144: text = (SVGElement) doc.getElementById(idPrefix + "."
145: + TEXT_SUFFIX);
146:
147: SVGRect bkgBBox = bkg.getBBox();
148: progressBBox = progress.getBBox();
149:
150: progressTxf = progress.getMatrixTrait("transform");
151:
152: // Min scale is for 1%. Max scale is for 100%. Below 1%, the progress indicator is hidden.
153: float bkgBBoxWidth = bkgBBox.getWidth();
154: float progressBBoxWidth = progressBBox.getWidth();
155: if (bkgBBoxWidth <= 0) {
156: throw new IllegalArgumentException(
157: "The progress bar with id prefix " + idPrefix
158: + " has an invalid zero-width background");
159: }
160: if (progressBBoxWidth <= 0) {
161: throw new IllegalArgumentException(
162: "The progress bar with id prefix "
163: + idPrefix
164: + " has an invalid zero-width progress indicator");
165: }
166:
167: float defaultPos = progressBBoxWidth / bkgBBoxWidth;
168:
169: // For pos = 1, we need the progressBBox width to be the same width as the background.
170: maxScale = 1 / defaultPos;
171:
172: // For pos = 0.01, we need the progressBBox width to be 1% of the background's width.
173: minScale = 0.01f * maxScale;
174:
175: setProgress(pos);
176: }
177:
178: /**
179: * @param pos the desired thumb position in the [0, 1] interval. If the value is out of range, it
180: * is clipped to the valid range.
181: */
182: public void setProgress(float pos) {
183: if (pos < 0) {
184: pos = 0;
185: } else if (pos > 1) {
186: pos = 1;
187: }
188:
189: float xScale = minScale + pos * (maxScale - minScale);
190: SVGMatrix scale = svg.createSVGMatrixComponents(xScale, 0, 0,
191: 1, 0, 0);
192: SVGMatrix txf = svg.createSVGMatrixComponents(1, 0, 0, 1, 0, 0);
193: txf.mMultiply(progressTxf);
194: txf.mTranslate(progressBBox.getX(), progressBBox.getY());
195: txf.mMultiply(scale);
196: txf.mTranslate(-progressBBox.getX(), -progressBBox.getY());
197:
198: progress.setMatrixTrait("transform", txf);
199:
200: text.setTrait("#text", "" + (int) Math.ceil(pos * 100) + "%");
201: this.pos = pos;
202: }
203: }
|