First of all, this component is a clone version of Ivan Novakov's Simple horizontal text scrolling with Ext Core 3 (marquee replacement) in GXT. Thank you Mr. Novakov.
OK. It's a simple implementation. When the viewport is building, please add a Marquee instance into RootPanel. And when you need to show some news, just use: marquee.show(String[] news), then the marquee will queue these news, and rolling them one by one. After rolling all news, the marquee will automatically hide itself. The code is as below:
Code:
import java.util.LinkedList;
import java.util.Queue;
import com.extjs.gxt.ui.client.core.El;
import com.extjs.gxt.ui.client.widget.BoxComponent;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.Timer;
public class Marquee extends BoxComponent
{
private static Marquee instance = null;
private Queue<String> newsQue = new LinkedList<String>();
private El layerEl;
private El textEl;
private int wndWidth = -1;
private int step = 5;
private int interval = 50;
private Timer timer = null;
public static synchronized Marquee getInstance()
{ // JavaScript is a single-threaded language, so multi-threaded performance is ignored
if (instance == null) {
Marquee marquee = new Marquee();
instance = marquee;
}
return instance;
}
private Marquee()
{
baseStyle = "x-marquee";
setMonitorWindowResize(true);
}
@Override
protected void onWindowResize(int width, int height) {
wndWidth = width;
}
@Override
public void show()
{
if ((timer != null) || newsQue.isEmpty()) {
return;
}
super.show();
}
@Override
protected void onShow()
{
super.onShow();
if (rendered) {
layerEl.show();
timer = new Timer() {
private int x = 9999;
private int txtWidth = -1;
@Override
public void run()
{
if (x > wndWidth) {
if (!resetTextEl()) {
timer.cancel();
timer = null;
layerEl.hide();
return;
}
txtWidth = textEl.getWidth();
x = -txtWidth;
}
int left = wndWidth - (x += step) - txtWidth;
textEl.setX(left == -1 ? -2 : left); // -1 == Style.DEFAULT keeps X unchanged
}
};
timer.scheduleRepeating(interval);
}
}
public void show(String news)
{
newsQue.add(news);
show();
}
public void show(String[] news)
{
for (String s : news) {
show(s);
}
}
private boolean resetTextEl()
{
String news = newsQue.poll();
textEl.update((news == null) ? " " : news);
textEl.setX(layerEl.getRight(false));
return news != null;
}
@Override
protected void onRender(Element target, int index)
{
layerEl = new El(DOM.createDiv());
layerEl.hide();
setElement(layerEl.dom, target, index);
textEl = new El(DOM.createSpan());
textEl.addStyleName("x-marquee-text");
getElement().appendChild(textEl.dom);
super.onRender(target, index);
disableTextSelection(true);
wndWidth = target.getClientWidth();
}
}
And these css should be write into gxt-all, I used the @import "gxt-marquee.css";
Code:
.x-marquee {
position: fixed;
bottom: 0px;
left: 0px;
right: 0px;
padding: 0px;
width: 100%;
height: 25px;
background-color: #000;
text-align: left;
filter:alpha(opacity=50);
opacity: 0.5;
-moz-opacity:0.5;
}
.x-marquee-text {
position: absolute;
vertical-align: baseline;
font-size: 15px;
font-weight: bold;
color: #DFD;
white-space: nowrap;
margin: 5px;
font-family: "Trebuchet MS", "Lucida Sans Unicode", "Arial", "sans-serif";
}
Marquee1.jpg