Search code examples
icefaces

Dynamic styling with IceFaces: how can I change the color of the outputText at the time of rendering?


I'm new to ICEFaces and I have to maintain someone else's code. I'm working on a web chat where the user can send and receive messages. I would like the messages to have different colors depending on whether they were sent by the user or by someone else.

I currently have the following code in my xhtml file:

<h:dataTable id="history" value="#{chatBean.messages}" var="message" border="0" align="left" style="width: 100%" >
    <h:column width="590" height="25" align="left" valign="bottom" >
        <h:outputText value="#{message}" styleClass="#{chatBean.messageColor}" />
    </h:column>
</h:dataTable>

This shows all messages sent and received, but all with the same color, even though the messageColor property of the chat bean changes: I did an experiment and appended the result of getMessageColor() at the end of each message and it does change, but the text is still rendered in the same color.

The CSS has the following classes (among others):

.class1
{
  color:#818181;
  width: 100%; 
  font-size: 15px; 
  font-family: Arial, Helvetica, sans-serif; 
  font-weight: bold;    
}

.class2
{
  color:#00657c;
  width: 100%; 
  font-size: 15px; 
  font-family: Arial, Helvetica, sans-serif; 
  font-weight: bold;
} 

Here's the code for the ChatBean class:

@ManagedBean(name = "chatBean")
@SessionScoped
public class ChatBean implements Serializable {
  private static final long serialVersionUID = -12636320254821872L;
  private static final String PUSH_GROUP = "chatPage";
  private PortableRenderer renderer;
  private String message;
  private String lastMessageSent = "";
  private Date lastMessageTime = new Date();
  private String isDown = "false";
  private List<String> messages = new ArrayList<String>();
  private String buttonDisabled = "true";
  private String buttonCancelDisabled = "true";
  private String pollDisabled = "false";
  private String id = "";
  private ChatClient chat;
  private Timer timer = new Timer();
  private String messageColor;

  public class ChatThread extends Thread implements Serializable {
      private static final long serialVersionUID = -7636532554421738019L;
      private Map<String, String> data;
      private String mail;
      public ChatThread(final Map<String, String> data, final String mail) {
          this.data = data;
          this.mail = mail;
      }
      @Override
      public void run() {
          chat = new ChatClient(new ChatClient.Event() {
              @Override
              public void handle(String msg) {
                  if(msg != null && msg.length() > 0)
                      pushMessage(msg);
              }
              @Override
              public void agentConnected(String msg) {
                  buttonDisabled = "false";
                  buttonCancelDisabled = "false";
                  pushMessage(msg);
              }
              @Override
              public void agentDisconnected(String msg) {
                  buttonDisabled = "true";
                  pushMessage(msg);
                  try {
                      timer.cancel();
                  } catch (Exception e) {
                      e.printStackTrace();
                  }
              }
          });

          chat.login(mail, data);
          chat.join(mail, data.get("partner"), data.get("business"));
          timer.scheduleAtFixedRate(new RefreshTimerTask(), 0, 1000);
      }
  }
  public class RefreshTimerTask extends TimerTask implements Serializable {
      private static final long serialVersionUID = 1852678537009150141L;
      public void run() {
          chat.refresh();
      }
  }

  public ChatBean() {
      if(getSession() != null) {
          id = getSession().getId();
          PushRenderer.addCurrentSession(PUSH_GROUP + id);
          renderer = PushRenderer.getPortableRenderer();
          setMessageColor("class1");
          Log.getLogger().debug("New chat bean.");
          if(getData().containsKey("login_chat")) {
              ChatThread chat = new ChatThread(getData(), getSessionAttribute(GenesysSingleton.getInstance().getConfigApp().getDisplayName(), "<mail>"));
              chat.start();
          }
      }
  }

  private void pushMessage(String msg) {
      if(msg != null && !msg.isEmpty()) {
          ChatBean.this.isDown = "true";
          messages.add(msg);//Acá se puede acceder a textColor.
          try {
              PushRenderer.render(PUSH_GROUP + id);
          } catch (Exception e) {
              renderer.render(PUSH_GROUP + id);
          }
          setMessageColor("class1");
      }
  }
  private String getSessionAttribute(String key, String ref) {
      Object value = getSession().getAttribute(key);
      return value != null ? value.toString() : ref;
  }

  private Map<String, String> getData() {
      Map<String, String> data = new HashMap<String, String>();
      HttpSession session = getSession();
      @SuppressWarnings("rawtypes")
      Enumeration enums = session.getAttributeNames();
      while(enums.hasMoreElements()) {
          String key = enums.nextElement().toString();
          if(!"com.sun.faces.application.view.activeViewMaps".equals(key)
              && !"com.sun.faces.renderkit.ServerSideStateHelper.LogicalViewMap".equals(key)
              && !"javax.faces.request.charset".equals(key))
              data.put(key, session.getAttribute(key).toString());
      }
      return data;
  }

  public void sendMessage(ActionEvent event) {
      sendMessage();
  }

  protected synchronized void sendMessage() {
      if (message != null && !message.trim().isEmpty()){
          Date now = new Date();
          //No permito mandar el mismo mensaje 2 veces seguidas en un intervalo menor a un segundo.
          message = message.trim();
          if (message.equals(lastMessageSent)&&(now.getTime()<(1000+lastMessageTime.getTime()))){
              message = null;
          }
          else{
              setMessageColor("class2");
              lastMessageSent = message;
              message = null;
              lastMessageTime = new Date();
              chat.refresh(lastMessageSent);
          }
      }
  }

  public String disconnect() {
      pollDisabled = "true";
      return "login";
  }

  public void sendClose(ActionEvent event) {
  }

  public void receiveMessage() {
  }

  @PreDestroy
  public void destroy() {
      buttonDisabled = "true";
      try {

          //pushMessage(SISTEMA_3);
      } catch (Exception e) {
          e.printStackTrace();
      }
      try {
          Thread.sleep(1000);
      } catch (InterruptedException e) {
          e.printStackTrace();
      };
      System.out.println(id + "- ssssssss");
      try {
          timer.cancel();
      } catch (Exception e) {
      }
      chat.logout();
      chat.close();
  }

  private HttpSession getSession() {
      return (HttpSession) getContext().getSession(false);
  }
  private ExternalContext getContext() {
      return getFacesContext().getExternalContext();
  }
  private FacesContext getFacesContext() {
      return FacesContext.getCurrentInstance();
  }

  public String getMessage() {
      return message;
  }

  public void setMessage(String message) {
      this.message = message;
  }

  public String getButtonDisabled() {
      return buttonDisabled;
  }

  public void setButtonDisabled(String buttonDisabled) {
      this.buttonDisabled = buttonDisabled;
  }

  public List<String> getMessages() {
      try {
          JavascriptContext.addJavascriptCall(getFacesContext(), "document.getElementById('scrollDataTable').scrollIntoView();");
      } catch (Exception e) {
          e.printStackTrace();
      }
      return messages;
  }

  public void setMessages(List<String> messages) {
      this.messages = messages;
  }

  public String getPollDisabled() {
      return pollDisabled;
  }

  public void setPollDisabled(String pollDisabled) {
      this.pollDisabled = pollDisabled;
  }

  public String getButtonCancelDisabled() {
      return buttonCancelDisabled;
  }

  public void setButtonCancelDisabled(String buttonCancelDisabled) {
      this.buttonCancelDisabled = buttonCancelDisabled;
  }

  public String getIsDown() {
      return isDown;
  }

  public void setIsDown(String isDown) {
      this.isDown = isDown;
  }

  public String getMessageColor() {
      return messageColor;
  }

  public void setMessageColor(String textColor) {
      this.messageColor = textColor;
  }

}

All help will be appreciated. Thank you in advance.


Solution

  • OK, I have found a better solution.

    I created a TextModel class:

    import java.io.Serializable;
    
    
    
    public class TextModel implements Serializable {
    
        private static final long serialVersionUID = -8470475291191399871L;
    
        private String text;
    
        private String clase;
    
    
    
        public TextModel() {
    
        }
    
    
    
        public TextModel(String text, String clase) {
    
            this.text = text;
    
            this.clase = clase;
    
        }
    
    
    
        public String getText() {
    
            return text;
    
        }
    
    
    
        public void setText(String text) {
    
            this.text = text;
    
        }
    
    
    
        public String getClase() {
    
            return clase;
    
        }
    
    
    
        public void setClase(String clase) {
    
            this.clase = clase;
    
        }
    
    
    
        public String toString() {
    
            return text;
    
        }
    
    }
    

    Then I changed messages in ChatBean from List to List, and changed the following functions in ChatBean.java:

    private void pushMessage(String msg) {
        if(msg != null && !msg.isEmpty()) {
            ChatBean.this.isDown = "true";
            messages.add(new TextModel(msg,clase));
            try {
                PushRenderer.render(PUSH_GROUP + id);
            } catch (Exception e) {
                renderer.render(PUSH_GROUP + id);
            }
            clase = "class1";
        }
    }
    protected synchronized void sendMessage() {
        if (message != null && !message.trim().isEmpty()){
            Date now = new Date();
            message = message.trim();
            if (message.equals(lastMessageSent)&&(now.getTime()<(1000+lastMessageTime.getTime()))){
                message = null;
            }
            else{
                clase = "class2";
                lastMessageSent = message;
                message = null;
                lastMessageTime = new Date();
                chat.refresh(lastMessageSent);
            }
        }
    }
    

    Where clase is either "class1" or "class2" (could be neater, but it works for now, I can always make it neater later).

    Finally, on chat.xhtml, I changed the outputtext tag to:

    <h:outputText value="#{message.text}" styleClass="#{message.clase}" />
    

    That's it. No more messy JavaScript patches.

    The trick was making the class a property of the message itself rather than the ChatBean.

    I hope this helps someone else in the future.