Loading...
Logo
Processing Forum
EDIT: code added as a reply in this thread.


Entities are the way Twitter calls links, medias embedded, users screen names and hashtags. Those should be displayed in a different color and be clickable linking to proper pages.




When you got a tweet (aka status) you get those like this:

Text:         a string containing all the tweet text, including entities text.

Hashtag entities: an array containing the first and one after last indexes of the hashtag in the above string.
                          also, you have the text (only hash text) accessible by hashtag object.
                     this is the JSON:
                   "hashtags":[{"indices":[32,36],"text":"lol"}] //

URL entities: Similar to hashtags, but also containing both, expanded and shorted URL text in the object.
                       "urls":[{"indices":[32,52], "url":"http:\/\/t.co\/IOwBrTZR",             "display_url":"youtube.com\/watch?v=oHg5SJ\u2026",             "expanded_url":"http:\/\/www.youtube.com\/watch?v=oHg5SJYRHA0"}]

Mentions entities: Are the users mentioned in tweet, they must be linked to users pages. They came like this;
                              "user_mentions" : [ { "name" : "Twitter API" , "indices" : [ 4 , 15 ] ,                   "screen_name" : "twitterapi" , "id" : 6253282 , "id_str" : "6253282" } ] 

The media stuff is similar, but i'm not concerned with them now,  I'll leave it out for now.


So I need to display this, changing colors and linking accordingly. I started by hashtags, and i managed to split the text string in the pieces that are not hashtags, like:

"this is a #test to display tweets. #hashtag. ok." 

became:

piece 1: this is a 

piece 2:  to display tweets. 

piece 3:  . ok. 

Remember that those can came in any order and amount in a tweet.
Than i started thinking that this may not be the best approach. If i repeat this for the other entities i'll end with a lot of pieces to assemble back together... Looks messy. And  I thought to use text(x, y, width, height) but to use that I need all the text in the same string... and won't be able to change colors, right? I'll have to handle line brakes manually?
Than i thought, i may convert the text to a char array and work only with the indexes of entities. I could use textWidth(text preceding the hashtag) to create a bounding box for linking, but any way I'll have to make several calls to text() to change colors... (edit) Maybe an array of words would be best...

Is any of those the way to go?

thanks

EDIT: I'm asking about handling the string, coloring, linking and spacing it to display. I got the JSON reading stuff and bounding box linking working already. actually twitter4j has those working for me ;-)
I can provide a text file with some JSONs from twitter and the code for reading them if some one wants. 



I don't have the code here, but i'll post it latter. I leave the code, but the code doesn't leaves me...





Replies(5)

Might I suggest that you read or re-read the forum guidelines, please?
About choosing the proper thread section...
Well I asked my self if that would be the proper choice but, as my question isn't related to any specific library, though i'm using some, I thought that should be in programming questions. What I'm looking help for involves only text(), String manipulation and fill(). I mean any one could help me with this issues. Anyway if this is the wrong choice, please move it ;-)
 I'll check the guidelines again.

And what about the question it self? No thoughts? :-)
OK, I have actually not moved the topic because I wasn't sure myself... (about is that about the Twitter library or only a display problem).
Per my policy, generic questions without code to see should go to General Discussion. Programming questions is more about questions on real code, to fix or improve.
Showing a simple test sketch with some pseudo-tweet to display could help...

But, basically, if I understood the core of your problem, yes, you have to split the text and display it segment per segment, with proper fill() and such on each part. Not an easy task indeed, but Processing is a rather low-level API, where you have to do high level stuff yourself... or delegate it to some library.
Thanks. I'll get you some code as soon as i get home. :) I might have waited, but i can't take this out of my mind... It is already started.
:) 
This code will need the twitter4j library onky foe reading status NO KEY needed. I'm working in a version without the JSON.
This is the file with the jasons to be read:

.txt will open in a browser page to copy and paste

.txt.zip will download


file with 40 tweets in  JSON

the code, the part of splitting the strings is just outputting to console so far. But there are stuff displayed in canvas already. Press n for next tweet and p for previous.


first tab:
Copy code
  1. import processing.opengl.*;
  2. import twitter4j.Status;
  3. import twitter4j.TwitterException;
  4. import twitter4j.json.DataObjectFactory;
  5. String[] rawData;
  6. int i = 0;

  7. int id = 0;
  8. ArrayList <TweetDisplayer> displayer = new ArrayList<TweetDisplayer>();



  9. void setup()
  10. {
  11.   size (700, 500, OPENGL);
  12.   background(0);
  13.   smooth();

  14.   ConfigurationBuilder cb = new ConfigurationBuilder();
  15.   cb.setDebugEnabled(true);
  16.   cb.setJSONStoreEnabled(true);
  17.   rawData = loadStrings("saved3.txt");


  18.   try {
  19.     for (int i = 0; i < rawData.length; i++)
  20.     {
  21.       if (rawData[i].startsWith("{"))
  22.       {
  23.         Status status = DataObjectFactory.createStatus(rawData[i]);
  24.         displayer.add(new TweetDisplayer(status));
  25.       }
  26.     }
  27.   } 
  28.   catch (TwitterException te) {
  29.     te.printStackTrace();
  30.     System.exit(-1);
  31.   }
  32. }

  33. void draw()  
  34. {
  35.   displayer.get(i).display();
  36. }

  37. void mousePressed()
  38. {
  39.   //println("id = " + id + " x = " + mouseX + " y = " + mouseY); 
  40.   //id++;
  41. }


  42. void keyPressed()
  43. {
  44.   if (key == 'n')
  45.   {
  46.     if (i < displayer.size()-1)
  47.     {
  48.       i++;
  49.       displayer.get(i).debug();
  50.       println("\n");
  51.     }
  52.   }

  53.   if (key == 'p')
  54.   {
  55.     if (i > 0)
  56.     {
  57.       i--;
  58.         displayer.get(i).debug();
  59.         println("\n");
  60.     }
  61.   }
  62. };


displayTweet tab :


Copy code
  1. class TweetDisplayer
  2. {
  3.   float x = 100;          // I'll remove this hard numbers later
  4.   float y = 100;
  5.   float sizeX = 200;
  6.   float sizeY = 124;
  7.   float border = 8;

  8.   PFont font = createFont("GilSans", 32);
  9.   Status status;

  10.   String profImageUrl;
  11.   PImage profImage ;

  12.   String userTwitter;

  13.   String scrName;
  14.   CompleteText name;         /// completText has mouse test and linked url
  15.   CompleteText screenName;
  16.   String twText;
  17.   HashtagEntity[] htEnt;
  18.   int hashtagCount;
  19.   ArrayList<String> pieces = new ArrayList<String>();



  20.   TweetDisplayer(Status _status)
  21.   {
  22.     status = _status;
  23.     try {
  24.       User user = status.getUser();       /// several items are getted from user use object
  25.       
  26.       //avatar
  27.       profImageUrl = user.getProfileImageURL().toString();
  28.       profImage = loadImage(profImageUrl, "png");
  29.       
  30.       //names
  31.       scrName = user.getScreenName();
  32.       userTwitter = "https://twitter.com/" + scrName;
  33.       name = new CompleteText(user.getName(), 168, 133, font, 16, userTwitter);
  34.       screenName = new CompleteText("@"+scrName, 168, 151, font, 14, userTwitter);
  35.       
  36.       //text 
  37.       twText = status.getText();
  38.       
  39.       
  40.       // Entities
  41.       htEnt = status.getHashtagEntities();
  42.       hashtagCount = (htEnt == null)?  0:htEnt.length;
  43.       println(hashtagCount);
  44.       init();     
  45.     }
  46.     catch (Exception e) {
  47.       e.printStackTrace();
  48.       System.out.println("algo errado: " + e.getMessage());
  49.       System.exit(-1);
  50.     }
  51.   }

  52.   void init()
  53.   {
  54.       StringBuilder sb = new StringBuilder(twText);
  55.     if (hashtagCount > 0)                           // there is hashtags!
  56.     {   
  57.       int index;
  58.       // if starts with add the rest and process
  59.       // may not be in crescent order...
  60.       for (int i = 0; i < hashtagCount; i++)
  61.       {
  62.         if (htEnt[i].getStart() == 0)               // starts with a hashtag?
  63.         {
  64.           pieces.add(sb.substring(htEnt[i].getEnd()));
  65.           println("*******" + sb.toString());
  66.         }
  67.       }
  68.         /// else...
  69.        for (int i = 0; i < hashtagCount; i++)
  70.       {
  71.           int initial = (i == 0)? 0:htEnt[i-1].getEnd();
  72.           println(initial +  "    " + htEnt[i].getStart() );
  73.           
  74.           //check to see if next piece is a hashtag
  75.           if( initial != htEnt[i].getStart() - 1) 
  76.           {
  77.           pieces.add(sb.substring(initial, htEnt[i].getStart()));
  78.           }
  79.       }
  80.       
  81.       if(htEnt[hashtagCount-1].getEnd() != sb.toString().length()) pieces.add(sb.substring(htEnt[hashtagCount-1].getEnd()));
  82.       

  83.     }
  84.   }
  85.  
  86.  
  87.   
  88.   void debug()
  89.   {
  90.      for (int i = 0; i < pieces.size(); i++)
  91.       {
  92.           println(i + 1 + "º pedaço " + pieces.get(i));
  93.       }
  94.   }
  95.   
  96.  
  97.  
  98.  
  99.   
  100.   void display()
  101.   {
  102.     fill(57);
  103.     rect(x, y, x + sizeX, y + sizeY);
  104.     fill(255);
  105.     noStroke();
  106.     //name
  107.     name.display();
  108.     screenName.display();
  109.     // avatar
  110.     noTint();
  111.     image(profImage, x + border, y + border, profImage.width, profImage.height);
  112.     //text
  113.     fill(250,255,255);
  114.     text(twText, 110, 167, 280, 120); // this is here, but gonna be replaced..
  115.   }
  116. }// end of class



  117. // linked text with mouse detect
  118. class CompleteText {

  119.   String linkedText;
  120.   String linkTo;
  121.   float completeWidth;
  122.   float completeHeight;
  123.   float x;
  124.   float y;
  125.   PFont font;
  126.   float fontSize;
  127.   color baseColor = color(180);
  128.   color altColor  = color(255);


  129.   CompleteText() {
  130.   }/// default

  131.     CompleteText(String _linkedText, float _x, float _y, PFont _font, int _fontSize, String _linkTo)
  132.   {
  133.     linkedText = _linkedText;
  134.     linkTo = _linkTo;
  135.     font = _font;
  136.     fontSize = _fontSize;
  137.     textFont(font, _fontSize);
  138.     completeWidth = textWidth(linkedText);
  139.     completeHeight = textAscent()+textDescent();
  140.     x = _x;
  141.     y = _y;
  142.   }

  143.   void display()
  144.   {

  145.     //rect(x, y - textAscent(), completeWidth, completeHeight);
  146.     noStroke();
  147.     color c = isOver()? altColor:baseColor;
  148.     fill(c);
  149.     textFont(font, fontSize);
  150.     text(linkedText, x, y);
  151.     if (isClicked()) link(linkTo);
  152.   }

  153.   boolean isOver()
  154.   {
  155.     float upperY = y - textAscent();
  156.     float lowerY = y + textDescent();
  157.     float rightX  = x + completeWidth;
  158.     if (mouseY < lowerY && mouseY > upperY && mouseX > x && mouseX < rightX)
  159.     {
  160.       return true;
  161.     }
  162.     else
  163.     {
  164.       return false;
  165.     }
  166.   }

  167.   boolean isClicked()
  168.   {
  169.     return (isOver() && mousePressed);
  170.   }
  171. }