Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- package ru.nolesh.libgdx.extension;
- import java.io.DataInputStream;
- import java.io.IOException;
- import java.io.InputStream;
- import java.net.HttpURLConnection;
- import java.net.MalformedURLException;
- import java.net.URL;
- import java.util.ArrayList;
- import java.util.HashMap;
- import java.util.List;
- import java.util.Map;
- import com.badlogic.gdx.Gdx;
- import com.badlogic.gdx.graphics.Color;
- import com.badlogic.gdx.graphics.Pixmap;
- import com.badlogic.gdx.graphics.Texture;
- import com.badlogic.gdx.graphics.g2d.BitmapFont;
- import com.badlogic.gdx.graphics.g2d.BitmapFont.TextBounds;
- import com.badlogic.gdx.graphics.g2d.SpriteBatch;
- import com.badlogic.gdx.scenes.scene2d.InputEvent;
- import com.badlogic.gdx.scenes.scene2d.InputListener;
- import com.badlogic.gdx.scenes.scene2d.ui.List.ListStyle;
- import com.badlogic.gdx.scenes.scene2d.ui.ScrollPane;
- import com.badlogic.gdx.scenes.scene2d.ui.Widget;
- import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener.ChangeEvent;
- import com.badlogic.gdx.scenes.scene2d.utils.Drawable;
- import com.badlogic.gdx.utils.GdxRuntimeException;
- import com.badlogic.gdx.utils.Pools;
- /**
- * Extended list with headers. It allows to load images from URL in lazy mode.
- * @author Nolesh
- */
- public class MyLazyImageList2 extends ScrollPane{
- public static final String SEPARATOR = "/*~*/";
- private static final String SEPARATOR_TEMPLATE = "/\\*~\\*/";
- private static final int MAX_THREAD_AMOUNT = 2;
- private volatile static int threadAmount;
- private MyRawList rawList;
- private boolean isEnabled;
- private String emptyLabel;
- private Texture placeholder;
- private String headers[];
- private Drawable headersBackground;
- private Color headersColor;
- /**
- * Constructor
- * @param items To create items use MyLazyImageListItem.formItems(names, urls)
- * @param style
- * @param listStyle
- * @param placeholder It must not be empty!
- */
- public MyLazyImageList2(MyLazyImageListItem[] items, ScrollPaneStyle style,
- ListStyle listStyle, Texture placeholder){
- super(null, style);
- isEnabled = true;
- rawList = new MyRawList(items, listStyle, this);
- setWidget(rawList);
- setWidth(rawList.getPrefWidth());
- setHeight(rawList.getPrefHeight());
- setScrollingDisabled(true, false);
- emptyLabel = "There are no any items";
- if(placeholder==null)
- throw new IllegalArgumentException("Placeholder must not be empty!");
- this.placeholder=placeholder;
- threadAmount=0;
- }
- public boolean isEnabled() {
- return isEnabled;
- }
- public void setEnabled(boolean isEnabled) {
- this.isEnabled = isEnabled;
- }
- public void setItems(MyLazyImageListItem[] items){
- rawList.setItems(items);
- }
- public void setSelectedIndex(int index){
- rawList.setSelectedIndex(index);
- }
- public int getSelectedIndex(){
- if(isEnabled) return rawList.getSelectedIndex();
- else return -1;
- }
- public String getEmptyLabel() {
- return emptyLabel;
- }
- public void setEmptyLabel(String emptyLabel) {
- this.emptyLabel = emptyLabel;
- }
- public String[] getHeaders() {
- return headers;
- }
- /**
- * Sets the headers
- * @param headers String of headers (Use SEPARATOR to concatenate headers to each other)
- * @param background - Must be not null!
- */
- public void setHeaders(String headers, Drawable background) {
- if(background==null) throw new IllegalArgumentException("Background must be not null!");
- this.headers = headers.split(SEPARATOR_TEMPLATE);
- headersBackground = background;
- }
- public Color getHeadersColor() {
- return headersColor;
- }
- public void setHeadersColor(Color headersColor) {
- this.headersColor = headersColor;
- }
- /******************** RAW LIST ************************/
- public class MyRawList extends Widget{
- private MyLazyImageList2 myLazyImageList;
- private ListStyle style;
- private MyLazyImageListItem[] items;
- private int selectedIndex;
- private float prefWidth, prefHeight;
- private float itemHeight;
- private float textOffsetX, textOffsetY;
- private float coefH;
- private float coefW;
- private volatile Map<String, Pixmap> neccessaryCache;
- private Map<String, Texture> cache;
- private volatile List<String> beingDownloaded = new ArrayList<String>();
- private volatile List<String> downloaded = new ArrayList<String>();
- private List<String> tempDownloaded = new ArrayList<String>();
- private List<String[]> elements = new ArrayList<String[]>();
- private int imageWidth = 35, imageHeight = 26;
- public MyRawList (MyLazyImageListItem[] items, ListStyle style, MyLazyImageList2 myLazyImageList) {
- coefH = (float)Gdx.graphics.getHeight()/320;
- coefW = (float)Gdx.graphics.getWidth()/480;
- setStyle(style);
- setItems(items);
- setWidth(getPrefWidth());
- setHeight(getPrefHeight());
- this.myLazyImageList=myLazyImageList;
- neccessaryCache = new HashMap<String, Pixmap>();
- cache = new HashMap<String, Texture>();
- addListener(new InputListener() {
- public boolean touchDown (InputEvent event, float x, float y, int pointer, int button) {
- if(!isEnabled) return false;
- if (pointer == 0 && button != 0) return false;
- MyRawList.this.touchDown(y);
- return true;
- }
- });
- }
- protected synchronized Map<String, Pixmap> getCache(){
- return neccessaryCache;
- }
- protected Texture getTexture(URL url){
- String urlStr = url.toString();
- if(downloaded.contains(urlStr)&&!beingDownloaded.contains(urlStr)){
- if(getCache().containsKey(urlStr)){
- Pixmap pixmap = getCache().remove(urlStr);
- cache.put(urlStr, new Texture(pixmap));
- }
- if(cache.get(urlStr)!=null) return cache.get(urlStr);
- }
- asyncDownloadTextureFromURL(url);
- return placeholder;
- }
- protected void clearPixmapCache(int from, int to) {
- tempDownloaded.clear();
- for(int i = from; i<=to; i++){
- if(!tempDownloaded.contains(items[i].url.toString())&&downloaded.contains(items[i].url.toString())){
- tempDownloaded.add(items[i].url.toString());
- }
- }
- downloaded.removeAll(tempDownloaded);
- for(String key : downloaded){
- if(cache.containsKey(key)){
- cache.remove(key).dispose();
- }
- }
- downloaded.clear();
- downloaded.addAll(tempDownloaded);
- }
- protected void asyncDownloadTextureFromURL(final URL url) {
- final String urlStr = url.toString();
- if(beingDownloaded.contains(urlStr)) return;
- if(threadAmount>=MAX_THREAD_AMOUNT) return;
- threadAmount++;
- new Thread(new Runnable() {
- @Override
- public void run() {
- beingDownloaded.add(urlStr);
- Gdx.app.log("MyLazyImageList", "Start downloading: "+urlStr);
- Pixmap pixmap = syncDownloadPixmapFromURL(url);
- if(pixmap==null){
- beingDownloaded.remove(urlStr);
- threadAmount--;
- return;
- }
- if(pixmap!=null)
- getCache().put(urlStr, pixmap);
- Gdx.app.log("MyLazyImageList", "Stop downloading: "+urlStr);
- if(!downloaded.contains(urlStr))
- downloaded.add(urlStr);
- beingDownloaded.remove(urlStr);
- threadAmount--;
- }
- }).start();
- }
- private Pixmap syncDownloadPixmapFromURL(URL url) {
- try {
- /*Properties systemProperties = System.getProperties();
- systemProperties.setProperty("http.proxyHost","proxy");
- systemProperties.setProperty("http.proxyPort","3128");
- Authenticator authenticator = new Authenticator() {
- public PasswordAuthentication getPasswordAuthentication() {
- return (new PasswordAuthentication("nik",
- "AresII".toCharArray()));
- }
- };
- Authenticator.setDefault(authenticator);*/
- HttpURLConnection conn= (HttpURLConnection)url.openConnection();
- conn.setDoInput(true);
- conn.connect();
- int length = conn.getContentLength();
- if(length<=0) return null;
- InputStream is = conn.getInputStream();
- DataInputStream dis = new DataInputStream(is);
- byte[] data = new byte[length];
- dis.readFully(data);
- Pixmap pixmap = new Pixmap(data, 0, data.length);
- pixmap = ImagePow2.isPow2(pixmap)?pixmap:ImagePow2.getPow2Pixmap(pixmap);
- return pixmap;
- } catch (MalformedURLException e) {
- e.printStackTrace();
- } catch (IOException e) {
- e.printStackTrace();
- }
- return null;
- }
- void touchDown (float y) {
- int oldIndex = selectedIndex;
- selectedIndex = (int)((getHeight() - y) / itemHeight);
- selectedIndex = Math.max(0, selectedIndex);
- selectedIndex = Math.min(items.length - 1, selectedIndex);
- ChangeEvent changeEvent = Pools.obtain(ChangeEvent.class);
- if (fire(changeEvent)) selectedIndex = oldIndex;
- Pools.free(changeEvent);
- }
- public void setStyle (ListStyle style) {
- if (style == null) throw new IllegalArgumentException("style cannot be null.");
- this.style = style;
- if (items != null)
- setItems(items);
- else
- invalidateHierarchy();
- }
- /** Returns the list's style. Modifying the returned style may not have an effect until {@link #setStyle(ListStyle)} is called. */
- public ListStyle getStyle () {
- return style;
- }
- int startIndex = 0;
- int lastVisibleIndex = 0;
- @Override
- public void draw (SpriteBatch batch, float parentAlpha) {
- BitmapFont font = style.font;
- Drawable selectedDrawable = style.selection;
- Color fontColorSelected = style.fontColorSelected;
- Color fontColorUnselected = style.fontColorUnselected;
- float x = getX();
- float y = getY();
- Color color = getColor();
- parentAlpha*=getColor().a;
- batch.setColor(color.r, color.g, color.b, color.a * parentAlpha);
- font.setColor(fontColorUnselected.r, fontColorUnselected.g, fontColorUnselected.b, fontColorUnselected.a * parentAlpha);
- float itemY = getHeight();
- //Makes offset for headers
- if(headers!=null && !headers.equals("")){
- itemY -= itemHeight/3 + (textOffsetY/3)*coefH - font.getBounds(headers[0]).height/2;
- }
- if(items==null||elements.isEmpty()){
- float centerX = myLazyImageList.getWidth()/2;
- float centerY = myLazyImageList.getHeight()/2;
- font.draw(batch, emptyLabel, centerX - font.getBounds(emptyLabel).width/2,
- centerY+font.getBounds(emptyLabel).height/2);
- return;
- }
- boolean isSetLastVisibleIndex = true;
- for (int i = 0; i < items.length; i++) {
- boolean isDrawn = true;
- if(getHeight()-itemY<myLazyImageList.getScrollY()-itemHeight){
- startIndex=i;
- isDrawn=false;
- }
- if(getHeight()-itemY>myLazyImageList.getScrollY()+myLazyImageList.getHeight()){
- if(isSetLastVisibleIndex) lastVisibleIndex=i;
- isSetLastVisibleIndex = false;
- isDrawn=false;
- }
- if(isDrawn){
- if (selectedIndex == i && selectedIndex!=-1) {
- //if(isEnabled){
- selectedDrawable.draw(batch, x, y + itemY - itemHeight, getWidth(), itemHeight);
- font.setColor(fontColorSelected.r, fontColorSelected.g,
- fontColorSelected.b, fontColorSelected.a * parentAlpha);
- }
- else{
- //if(isEnabled){
- font.setColor(fontColorUnselected.r, fontColorUnselected.g, fontColorUnselected.b,
- fontColorUnselected.a * parentAlpha);
- }
- float equalPartWidth = getWidth()/(elements.get(i).length+1);
- for(int j=0; j<elements.get(i).length; j++){
- String shortName = cutName(font, elements.get(i)[j], (int)(equalPartWidth));
- if(shortName.equals(elements.get(i)[j]))
- font.draw(batch, elements.get(i)[j]
- , x + textOffsetX +equalPartWidth*(j)+(equalPartWidth-font.getBounds(elements.get(i)[j]).width)/2,
- y + itemY - textOffsetY*coefH - font.getBounds(items[i].name).height/2);
- else
- font.draw(batch, shortName
- , x + textOffsetX + equalPartWidth*(j),
- y + itemY - textOffsetY*coefH - font.getBounds(items[i].name).height/2);
- }
- Texture tempTexture = getTexture(items[i].url);
- if(tempTexture!=null)
- batch.draw(tempTexture, x + textOffsetX +equalPartWidth*(elements.get(i).length)+(equalPartWidth-imageWidth)/2,
- y + itemY-textOffsetY*coefH/2-imageHeight , imageWidth, imageHeight);
- }
- itemY -= itemHeight;
- }
- //Drawing headers
- if(headers!=null && !headers.equals("")){
- float height = font.getBounds(headers[0]).height + 6*coefH;
- headersBackground.draw(batch, 0, myLazyImageList.getHeight()-height, myLazyImageList.getWidth(), height);
- float equalPartWidthForHeader = getWidth()/headers.length;
- font.setColor(headersColor==null?fontColorSelected:headersColor);
- for(int k=0; k<headers.length; k++){
- font.draw(batch, headers[k], x+ textOffsetX + equalPartWidthForHeader*(k)
- + (equalPartWidthForHeader-font.getBounds(headers[k]).width)/2,
- myLazyImageList.getHeight()-3*coefH);
- }
- }
- clearPixmapCache(startIndex, lastVisibleIndex);
- }
- private String cutName(BitmapFont font, String name, int width){
- if(font.getBounds(name).width<=width) return name;
- String tempName = name;
- while(true){
- if(font.getBounds(tempName+"...").width>width){
- if(tempName.length()<3) break;
- tempName=tempName.substring(0, tempName.length()-2);
- }
- else break;
- }
- return tempName+"...";
- }
- /** @return The index of the currently selected item. The top item has an index of 0. */
- public int getSelectedIndex () {
- return selectedIndex;
- }
- public void setSelectedIndex (int index) {
- if(index==-1) { selectedIndex = -1; return; }
- if(items==null) throw new GdxRuntimeException("There are no any items!");
- if (index < -1 || index >= items.length)
- throw new GdxRuntimeException("index must be >= -1 and < " + items.length + ": " + index);
- selectedIndex = index;
- }
- /** @return The text of the currently selected item or null if the list is empty. */
- public MyLazyImageListItem getSelection () {
- if(items==null) return null;
- if (items.length == 0) return null;
- return items[selectedIndex];
- }
- /** @return The index of the item that was selected, or -1. */
- public int setSelection (String item) {
- selectedIndex = -1;
- if(items==null) return -1;
- for (int i = 0, n = items.length; i < n; i++) {
- if (items[i].equals(item)) {
- selectedIndex = i;
- break;
- }
- }
- return selectedIndex;
- }
- public void setItems (MyLazyImageListItem[] objects) {
- elements.clear();
- if(objects == null){
- items = null;
- return;
- }
- //if (objects == null) throw new IllegalArgumentException("items cannot be null.");
- if (!(objects instanceof MyLazyImageListItem[])) {
- throw new IllegalArgumentException("Items must be instance of MyLazyImageListItem");
- }
- items = objects;
- selectedIndex = 0;
- final BitmapFont font = style.font;
- final Drawable selectedDrawable = style.selection;
- itemHeight = font.getCapHeight() - font.getDescent() * 2;
- itemHeight += selectedDrawable.getTopHeight() + selectedDrawable.getBottomHeight();
- itemHeight*=coefH;
- prefWidth += selectedDrawable.getLeftWidth() + selectedDrawable.getRightWidth();
- textOffsetX = selectedDrawable.getLeftWidth()*coefW;
- textOffsetY = selectedDrawable.getTopHeight() - font.getDescent();
- prefWidth = 0;
- for (int i = 0; i < items.length; i++) {
- TextBounds bounds = font.getBounds(items[i].name);
- prefWidth = Math.max(bounds.width, prefWidth);
- //cutName(font, items[i].showName, (int)(getWidth()-imageWidth-textOffsetX*2-5));
- }
- prefHeight = items.length * itemHeight;
- imageWidth*=coefW;
- imageHeight*=coefH;
- for(int i=0; i<objects.length; i++){
- String[] names = objects[i].name.split(SEPARATOR_TEMPLATE);
- elements.add(names);
- }
- invalidateHierarchy();
- }
- public MyLazyImageListItem[] getItems () {
- return items;
- }
- public float getPrefWidth () {
- return prefWidth;
- }
- public float getPrefHeight () {
- return prefHeight;
- }
- }
- /************************ LIST ITEM ************************/
- public static class MyLazyImageListItem{
- public String name;
- public URL url;
- public MyLazyImageListItem(String name, URL url){
- this.name = name;
- this.url=url;
- }
- /**
- * Forms array of items (size of texts must be equal to size of urls)
- * @param texts If you want to have several columns, you should split them by SEPARATOR
- * @param urls URLs of the images which has to be downloaded
- * @return
- */
- public static MyLazyImageListItem[] formItems(String[] texts, URL[] urls) {
- if(texts.length!=urls.length) return null;
- //throw new Exception("Amount of text variables must be equals to amount of textures variable!");
- MyLazyImageListItem[] listItems = new MyLazyImageListItem[texts.length];
- for (int i=0; i<texts.length; i++) {
- listItems[i] = new MyLazyImageListItem(texts[i], urls[i]);
- }
- return listItems;
- }
- }
- public static class ImagePow2 {
- static int pow2[] = {2,4,8,16,32,64,128,256,512,1024,2048,4096,8192};
- public static boolean isPow2(Pixmap pixmap){
- boolean isWidthPow2 = false, isHeightPow2 = false;
- for(int i=0; i<pow2.length; i++){
- if(pow2[i]==pixmap.getWidth()) isWidthPow2=true;
- if(pow2[i]==pixmap.getHeight()) isHeightPow2=true;
- }
- return isWidthPow2&&isHeightPow2;
- }
- private static int getPow2(int value){
- int diff = value;
- int tmp = value;
- int minVal = value;
- for(int i=0; i<pow2.length; i++){
- diff = Math.abs(value - pow2[i]);
- if(tmp>diff){
- tmp=diff;
- minVal = pow2[i];
- }
- }
- return minVal;
- }
- public static Pixmap getPow2Pixmap(Pixmap pixmap){
- int width = getPow2(pixmap.getWidth());
- int height = getPow2(pixmap.getHeight());
- Pixmap updatedPixmap = new Pixmap(width, height, pixmap.getFormat());
- updatedPixmap.drawPixmap(pixmap, 0, 0, pixmap.getWidth(), pixmap.getHeight(),
- 0, 0, width, height);
- return updatedPixmap;
- }
- }
- }
- /**TO USE**/
- /*
- MyLazyImageList2 myLazyListTop100 = new MyLazyImageList2(null, scrollPaneStyle, listStyle,
- new Texture(Gdx.files.internal("skins/unknown_flag.png")));
- myLazyListTop100.setEnabled(false);
- String splitter = MyLazyImageList2.SEPARATOR;
- myLazyListTop100.setHeaders("#"+splitter+"Nickname"+splitter+"Location"+splitter+"Score"+splitter+"flag",
- dialogStyle.stageBackground);
- myLazyListTop100.setHeadersColor(new Color(0, 1, 1, 1));
- MyLazyImageListItem[] items = MyLazyImageListItem.formItems(names, urls);
- myLazyListTop100.setItems(items);
- myLazyListTop100.setSelectedIndex(player_position-1);
- stage.addActor(myLazyListTop100);
- */
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement