/**
   * Constructor.
   *
   * @param inSettings the system settings
   * @param inSupportGroup the support domain group
   */
  public SupportStreamHelpPanel(
      final SystemSettings inSettings, final DomainGroupModelView inSupportGroup) {
    Label headerLabel = new Label("Support Stream");
    headerPanel.add(headerLabel);
    headerPanel.addStyleName(StaticResourceBundle.INSTANCE.coreCss().header());
    contentPanel.add(descriptionPanel);
    add(headerPanel);
    add(contentPanel);

    logoPanel.add(
        new AvatarWidget(
            inSupportGroup.getId(), inSupportGroup.getAvatarId(), EntityType.GROUP, Size.Normal));
    logoPanel.addStyleName(StaticResourceBundle.INSTANCE.coreCss().supportGroupLogoPanel());

    contentPanel.addStyleName(StaticResourceBundle.INSTANCE.coreCss().contentPanel());
    contentPanel.add(logoPanel);
    descriptionPanel.add(new Label(inSupportGroup.getDescription()));

    Hyperlink gotoStreamLink =
        new Hyperlink(
            "Go to Stream",
            Session.getInstance()
                .generateUrl(
                    new CreateUrlRequest(
                        Page.GROUPS, inSettings.getSupportStreamGroupShortName())));
    descriptionPanel.add(gotoStreamLink);
    gotoStreamLink.addStyleName(
        StaticResourceBundle.INSTANCE.coreCss().goToSupportGroupStreamLink());

    contentPanel.add(descriptionPanel);
    descriptionPanel.addStyleName(
        StaticResourceBundle.INSTANCE.coreCss().supportGroupDescriptionPanel());
  }
  /**
   * Default constructor.
   *
   * @param inEntity the entity.
   * @param inEntityId id of the entity to upload the banner for.
   */
  public BannerUploadStrategy(final T inEntity, final Long inEntityId) {
    // TODO:Once the profile pages are entirely split from the domain models, refactor this to use
    // DTO's correctly.
    entity = inEntity;
    entityId = inEntityId;

    if (entity.getClass() == Organization.class
        || entity.getClass() == OrganizationModelView.class) {
      entityType = EntityType.ORGANIZATION;
      deleteAction = OrganizationBannerModel.getInstance();
    } else if (entity.getClass() == DomainGroup.class
        || entity.getClass() == DomainGroupModelView.class) {
      entityType = EntityType.GROUP;
      deleteAction = GroupBannerModel.getInstance();
    }

    Session.getInstance()
        .getEventBus()
        .addObservers(
            new Observer<BaseDataResponseEvent<Bannerable>>() {
              public void update(final BaseDataResponseEvent<Bannerable> arg1) {
                Session.getInstance()
                    .getEventBus()
                    .notifyObservers(
                        new ClearUploadedImageEvent(
                            entityType, ImageType.BANNER, arg1.getResponse()));
              }
            },
            DeleteGroupBannerResponseEvent.class,
            DeleteOrganizationBannerResponseEvent.class);
  }
 /** Determine if message text changed and handle appropriately. */
 private void checkMessageTextChanged() {
   String newText = message.getText();
   if (!newText.equals(messageText)) {
     messageText = newText;
     Session.getInstance().getEventBus().notifyObservers(MessageTextAreaChangedEvent.getEvent());
   }
 }
Example #4
0
  /**
   * Constructor.
   *
   * @param entityType Type of entity the avatar belongs to.
   * @param entityUniqueId Short name / account id of entity the avatar belongs to.
   * @param avatar Avatar image widget.
   */
  public AvatarLinkPanel(
      final EntityType entityType, final String entityUniqueId, final AvatarWidget avatar) {
    Panel main = new FlowPanel();
    main.addStyleName(StaticResourceBundle.INSTANCE.coreCss().avatar());
    initWidget(main);

    Page page;
    switch (entityType) {
      case PERSON:
        page = Page.PEOPLE;
        break;
      case GROUP:
        page = Page.GROUPS;
        break;
      default:
        // this should never happen
        return;
    }
    HashMap<String, String> params = new HashMap<String, String>();
    params.put("tab", "Stream");

    String linkUrl =
        Session.getInstance().generateUrl(new CreateUrlRequest(page, entityUniqueId, params));

    Hyperlink link = new InlineHyperlink("", linkUrl);
    main.add(link);
    link.getElement().appendChild(avatar.getElement());
  }
 /**
  * Sends event on successful response.
  *
  * @param inMembershipCriteria Requested criterion.
  * @param found If any query results found.
  */
 private void sendSuccessEvent(
     final MembershipCriteriaDTO inMembershipCriteria, final boolean found) {
   final EventBus eventBus = Session.getInstance().getEventBus();
   if (found) {
     eventBus.notifyObservers(new MembershipCriteriaAddedEvent(inMembershipCriteria, true));
   } else {
     eventBus.notifyObservers(new MembershipCriteriaVerificationNoUsersEvent());
   }
 }
  /**
   * Get the people from the server, convert them to JSON, and feed them back to the handler.
   *
   * @param ntids the ntids.
   * @param callbackIndex the callback index.
   */
  public static void bulkGetPeople(final String[] ntids, final int callbackIndex) {
    Session.getInstance()
        .getEventBus()
        .addObserver(
            GotBulkEntityResponseEvent.class,
            new Observer<GotBulkEntityResponseEvent>() {
              public void update(final GotBulkEntityResponseEvent arg1) {
                List<String> ntidList = Arrays.asList(ntids);
                JsArray<JavaScriptObject> personJSONArray =
                    (JsArray<JavaScriptObject>) JavaScriptObject.createArray();
                int count = 0;

                if (ntidList.size() == arg1.getResponse().size()) {
                  boolean notCorrectResponse = false;
                  for (Serializable person : arg1.getResponse()) {
                    PersonModelView personMV = (PersonModelView) person;
                    if (ntidList.contains(personMV.getAccountId())) {
                      AvatarUrlGenerator urlGen = new AvatarUrlGenerator(EntityType.PERSON);
                      String imageUrl =
                          urlGen.getSmallAvatarUrl(personMV.getId(), personMV.getAvatarId());

                      JsArrayString personJSON = (JsArrayString) JavaScriptObject.createObject();
                      personJSON.set(0, personMV.getAccountId());
                      personJSON.set(1, personMV.getDisplayName());
                      personJSON.set(2, imageUrl);

                      personJSONArray.set(count, personJSON);
                      count++;
                    } else {
                      notCorrectResponse = true;
                      break;
                    }
                  }
                  if (!notCorrectResponse) {
                    callGotBulkPeopleCallback(personJSONArray, callbackIndex);
                  }
                }
              }
            });

    ArrayList<StreamEntityDTO> entities = new ArrayList<StreamEntityDTO>();

    for (int i = 0; i < ntids.length; i++) {
      StreamEntityDTO dto = new StreamEntityDTO();
      dto.setUniqueIdentifier(ntids[i]);
      dto.setType(EntityType.PERSON);
      entities.add(dto);
    }

    if (ntids.length == 0) {
      JsArray<JavaScriptObject> personJSONArray =
          (JsArray<JavaScriptObject>) JavaScriptObject.createArray();
      callGotBulkPeopleCallback(personJSONArray, callbackIndex);
    } else {
      BulkEntityModel.getInstance().fetch(entities, false);
    }
  }
  /**
   * Creates a page given a page and view.
   *
   * @param page the page.
   * @param views the views.
   * @return the page widget.
   */
  public Widget createPage(final Page page, final List<String> views) {
    RootPanel.get().setStyleName("");

    String view = "";
    if (views.size() > 0) {
      view = views.get(0);
    }

    switch (page) {
      case ACTION:
        return new ActionExecutorPanel(Session.getInstance().getActionProcessor(), view);
      case SEARCH:
        return new SearchContent();
      case SETTINGS:
        return new SettingsContent(Session.getInstance().getActionProcessor());
      case AUTHORIZE:
        return new OAuthAuthorizeContent(Session.getInstance().getActionProcessor(), view);
      case GALLERY:
        return new GalleryContent();
      case ACTIVITY:
        return new StreamContent();
      case PEOPLE:
        return new PersonalProfilePanel(view);
      case PERSONAL_SETTINGS:
        return new PersonalProfileSettingsPanel();
      case GROUPS:
        return new GroupProfilePanel(view);
      case GROUP_SETTINGS:
        return new GroupProfileSettingsPanel(view);
      case NEW_GROUP:
        return new CreateGroupPanel(view);
      case ORGANIZATIONS:
        return new OrganizationProfilePanel(view);
      case ORG_SETTINGS:
        return new OrganizationProfileSettingsPanel(view);
      case HELP:
        return new HelpContent();
      case METRICS:
        return new MetricsSummaryContent();
      default:
        return new StartPageContent();
    }
  }
  /** Init the data. */
  public void init() {
    Session.getInstance()
        .getTimer()
        .addTimerJob(
            "getNotificationCountTimerJob",
            POLL_TIME_MINUTES,
            NotificationCountModel.getInstance(),
            null,
            true);

    NotificationCountModel.getInstance().fetch(null, true);
  }
 /** Record page view metrics. */
 private void recordPageViewMetrics() {
   Session.getInstance()
       .getEventBus()
       .addObserver(
           SwitchedHistoryViewEvent.class,
           new Observer<SwitchedHistoryViewEvent>() {
             public void update(final SwitchedHistoryViewEvent event) {
               UsageMetricDTO umd = new UsageMetricDTO(true, false);
               umd.setMetricDetails(event.getPage().toString());
               UsageMetricModel.getInstance().insert(umd);
             }
           });
 }
  /**
   * Gets called from JSNI with the shindig results and wraps them into Java objects.
   *
   * @param metadata the shindig metadata.
   */
  public static void gotGadgetMetaData(final JavaScriptObject metadata) {
    List<GadgetMetaDataDTO> gadgetMetaDataList = new LinkedList<GadgetMetaDataDTO>();
    for (GeneralGadgetDefinition gadgetDef : gadgetDefs) {
      gadgetMetaDataList.add(new GadgetMetaDataDTO(gadgetDef));
    }

    for (int i = 0; i < getGadgetCount(metadata); i++) {
      if (isGadgetValid(metadata, i)) {
        String url = getGadgetUrl(metadata, i);
        int j = 0;
        for (j = 0; j < gadgetDefs.size(); j++) {
          if (gadgetDefs.get(j).getUrl().equals(url)) {
            break;
          }
        }
        GadgetMetaDataDTO gMetaData = new GadgetMetaDataDTO(gadgetDefs.get(j));
        gMetaData.setTitle(getGadgetTitle(metadata, i));
        gMetaData.setTitleUrl(getGadgetTitleUrl(metadata, i));
        gMetaData.setDescription(getGadgetDescription(metadata, i));
        gMetaData.setAuthor(getGadgetAuthor(metadata, i));
        gMetaData.setAuthorEmail(getGadgetAuthorEmail(metadata, i));
        gMetaData.setThumbnail(getGadgetThumbnail(metadata, i));
        gMetaData.setScreenshot(getGadgetScreenshot(metadata, i));
        gMetaData.setString(getGadgetString(metadata, i));

        List<UserPrefDTO> userPrefs = new ArrayList<UserPrefDTO>();
        String[] keys = getUserPrefsKeys(metadata, i);
        for (int k = 0; k < keys.length; k++) {
          UserPrefDTO userPref = new UserPrefDTO();
          userPref.setDisplayName(getUserPrefDisplayName(metadata, i, keys[k]));
          userPref.setDataType(getUserPrefType(metadata, i, keys[k]).toUpperCase());
          userPrefs.add(userPref);
        }
        gMetaData.setUserPrefs(userPrefs);

        gadgetMetaDataList.remove(j);
        gadgetMetaDataList.add(j, gMetaData);
      }
    }

    // DEPRECATED: Use event bus.
    if (onGotGadgetMetaData != null) {
      onGotGadgetMetaData.onGotGadgetMetaData(gadgetMetaDataList);
    }
    Session.getInstance()
        .getEventBus()
        .notifyObservers(new GotGadgetMetaDataEvent(gadgetMetaDataList));
  }
 /**
  * init *MUST* be called after all the tabs are added. This can not be done in the constructor
  * because it looks into the history to see which tab to select. This obviously can't be done
  * until we have all the tabs.
  */
 public void init() {
   Session.getInstance()
       .getEventBus()
       .addObserver(
           UpdatedHistoryParametersEvent.class,
           new Observer<UpdatedHistoryParametersEvent>() {
             public void update(final UpdatedHistoryParametersEvent event) {
               if (null != event.getParameters().get(key)) {
                 switchToTab(event.getParameters().get(key));
               } else if (null != firstTab) {
                 switchToTab(firstTab);
               }
             }
           },
           true);
 }
 /** Record stream view metrics. */
 private void recordStreamViewMetrics() {
   // TODO: This is listening to the stream response event as the request stream event is called
   // twice on activity page for some reason (profile pages work correctly). Somewhere
   // this is filtered down to only one call to the server to get the stream, so response
   // event works fine for metrics, but should track down why request it double-firing.
   Session.getInstance()
       .getEventBus()
       .addObserver(
           GotStreamResponseEvent.class,
           new Observer<GotStreamResponseEvent>() {
             public void update(final GotStreamResponseEvent event) {
               UsageMetricDTO umd = new UsageMetricDTO(false, true);
               umd.setMetricDetails(event.getJsonRequest());
               UsageMetricModel.getInstance().insert(umd);
             }
           });
 }
  /**
   * Gets fired off when the avatar id is changed.
   *
   * @param inAvatarId - the avatar id.
   * @param inDisplayDelete - flag telling to display or hide the delete button.
   * @param inDisplayEdit - flag telling to display or hide the edit button
   */
  public void onAvatarIdChanged(
      final String inAvatarId, final boolean inDisplayDelete, final boolean inDisplayEdit) {
    Session.getInstance().getCurrentPerson().setAvatarId(inAvatarId);

    avatarId = inAvatarId;
    Widget avatar = widget.createImage(strategy, avatarId);
    avatarContainer.clear();
    avatarContainer.add(avatar);

    if (editButton != null) {
      editButton.setVisible(inDisplayEdit);
    }

    if (deleteButton != null) {
      deleteButton.setVisible(inDisplayDelete);
    }
  }
  /** Shows the ToS modal. */
  private void displayToS() {

    Session.getInstance()
        .getEventBus()
        .addObserver(
            GotSystemSettingsResponseEvent.class,
            new Observer<GotSystemSettingsResponseEvent>() {
              public void update(final GotSystemSettingsResponseEvent event) {
                if (displayTOS) {
                  Dialog.showCentered(
                      new TermsOfServiceDialogContent(
                          new TermsOfServiceDTO(event.getResponse().getTermsOfService()), false));
                }
              }
            });

    SystemSettingsModel.getInstance().fetch(null, true);
  }
  /**
   * Get the header composite.
   *
   * @param viewer the user.
   * @return the header composite.
   */
  HeaderComposite getHeaderComposite(final PersonModelView viewer) {
    panel.add(footerPanel);
    header.render(viewer);

    Session.getInstance()
        .getEventBus()
        .addObserver(
            GotSystemSettingsResponseEvent.class,
            new Observer<GotSystemSettingsResponseEvent>() {
              public void update(final GotSystemSettingsResponseEvent event) {
                final SystemSettings settings = event.getResponse();
                header.setSiteLabelTemplate(settings.getHeaderTemplate(), settings.getSiteLabel());
                footerPanel.setSiteLabelTemplate(
                    settings.getFooterTemplate(), settings.getSiteLabel());
              }
            });

    SystemSettingsModel.getInstance().fetch(null, true);

    return header;
  }
  /** {@inheritDoc} */
  public void fetch(
      final MembershipCriteriaVerificationRequest inRequest,
      final boolean inUseClientCacheIfAvailable) {
    final EventBus eventBus = Session.getInstance().getEventBus();
    final String criterion = inRequest.getMembershipCriteria().getCriteria();

    if (inRequest.isGroup()) {
      super.callReadAction(
          "groupLookup",
          new GroupLookupRequest(criterion),
          new OnSuccessCommand<Boolean>() {
            public void onSuccess(final Boolean wasFound) {
              sendSuccessEvent(inRequest.getMembershipCriteria(), wasFound);
            }
          },
          new OnFailureCommand() {
            public void onFailure(final Throwable inEx) {
              eventBus.notifyObservers(new MembershipCriteriaVerificationFailureEvent());
            }
          },
          inUseClientCacheIfAvailable);
    } else {
      super.callReadAction(
          "personLookupOrg",
          new PersonLookupRequest(criterion, MAX_RESULTS),
          new OnSuccessCommand<ArrayList<PersonModelView>>() {
            public void onSuccess(final ArrayList<PersonModelView> people) {
              sendSuccessEvent(inRequest.getMembershipCriteria(), !people.isEmpty());
            }
          },
          new OnFailureCommand() {
            public void onFailure(final Throwable inEx) {
              eventBus.notifyObservers(new MembershipCriteriaVerificationFailureEvent());
            }
          },
          inUseClientCacheIfAvailable);
    }
  }
  /** Constructor. */
  public NotificationCountWidget() {
    addStyleName(StaticResourceBundle.INSTANCE.coreCss().notifCount());
    setTitle("View Notifications");

    addClickHandler(
        new ClickHandler() {
          public void onClick(final ClickEvent inEvent) {
            showDialog();
          }
        });

    Session.getInstance()
        .getEventBus()
        .addObserver(
            NotificationCountsAvailableEvent.class,
            new Observer<NotificationCountsAvailableEvent>() {
              public void update(final NotificationCountsAvailableEvent ev) {
                int total = ev.getNormalCount() + ev.getHighPriorityCount();
                setText(Integer.toString(total));
                if (total > 0) {
                  if (ev.getHighPriorityCount() > 0) {
                    addStyleName(StaticResourceBundle.INSTANCE.coreCss().notifCountHighPriority());
                    removeStyleName(
                        StaticResourceBundle.INSTANCE.coreCss().notifCountNormalPriority());
                  } else {
                    addStyleName(
                        StaticResourceBundle.INSTANCE.coreCss().notifCountNormalPriority());
                    removeStyleName(
                        StaticResourceBundle.INSTANCE.coreCss().notifCountHighPriority());
                  }
                } else {
                  removeStyleName(
                      StaticResourceBundle.INSTANCE.coreCss().notifCountNormalPriority());
                  removeStyleName(StaticResourceBundle.INSTANCE.coreCss().notifCountHighPriority());
                }
              }
            });
  }
  /** Posts the message. */
  public void postMessage() {
    StreamScope scope = postToPanel.getPostScope();
    if (scope == null) {
      ErrorPostingMessageToNullScopeEvent error = new ErrorPostingMessageToNullScopeEvent();
      error.setErrorMsg("The stream name you entered could not be found");
      Session.getInstance().getEventBus().notifyObservers(error);
      return;
    }

    EntityType recipientType = DomainConversionUtility.convertToEntityType(scope.getScopeType());
    if (EntityType.NOTSET.equals(recipientType)) {
      recipientType = EntityType.GROUP;
    }

    ActivityDTOPopulatorStrategy objectStrat =
        attachment != null ? attachment.getPopulator() : new NotePopulator();
    ActivityDTO activity =
        activityPopulator.getActivityDTO(
            messageText, recipientType, scope.getUniqueKey(), new PostPopulator(), objectStrat);
    PostActivityRequest postRequest = new PostActivityRequest(activity);

    ActivityModel.getInstance().insert(postRequest);
  }
  /** Activate the control. */
  public void activate() {
    this.clear();
    this.setVisible(true);
    Widget avatar =
        new AvatarWidget(
            Session.getInstance().getCurrentPerson().getId(),
            Session.getInstance().getCurrentPerson().getAvatarId(),
            EntityType.PERSON,
            Size.VerySmall,
            Background.White);
    avatar.addStyleName("avatar");
    this.add(avatar);

    FlowPanel body = new FlowPanel();
    body.addStyleName("body");

    commentBox = new TextArea();
    body.add(commentBox);
    commentBox.setFocus(true);

    countDown = new Label(Integer.toString(MAXLENGTH));
    countDown.addStyleName("characters-remaining");
    body.add(countDown);

    post = new Hyperlink("post", History.getToken());
    post.addStyleName("post-button");
    post.addStyleName("inactive");

    final Label warning = new Label();
    warning.addStyleName("warning hidden");
    body.add(warning);

    Session.getInstance()
        .getEventBus()
        .addObserver(
            GotSystemSettingsResponseEvent.class,
            new Observer<GotSystemSettingsResponseEvent>() {
              public void update(final GotSystemSettingsResponseEvent event) {
                String text = event.getResponse().getContentWarningText();
                if (text != null && !text.isEmpty()) {
                  warning.removeStyleName("hidden");
                  warning.setText(text);
                }
              }
            });

    SystemSettingsModel.getInstance().fetch(null, true);

    post.addClickHandler(
        new ClickHandler() {
          public void onClick(final ClickEvent event) {
            fullCollapse = false;
            if (!inactive) {
              unActivate();
              CommentDTO comment = new CommentDTO();
              comment.setBody(commentBox.getText());
              comment.setActivityId(messageId);
              Session.getInstance()
                  .getActionProcessor()
                  .makeRequest(
                      new ActionRequestImpl<CommentDTO>("postActivityCommentAction", comment),
                      new AsyncCallback<CommentDTO>() {
                        /* implement the async call back methods */
                        public void onFailure(final Throwable caught) {}

                        public void onSuccess(final CommentDTO result) {
                          Session.getInstance()
                              .getEventBus()
                              .notifyObservers(new CommentAddedEvent(result, messageId));
                        }
                      });
            }
          }
        });
    body.add(post);

    this.add(body);
    commentBox.setFocus(true);
    nativeSetFocus(commentBox.getElement());

    commentBox.addBlurHandler(
        new BlurHandler() {
          public void onBlur(final BlurEvent arg0) {
            TimerFactory timerFactory = new TimerFactory();
            timerFactory.runTimer(
                BLUR_DELAY,
                new TimerHandler() {
                  public void run() {
                    if (commentBox.getText().length() == 0) {
                      unActivate();
                    }
                  }
                });
          }
        });

    commentBox.addKeyPressHandler(
        new KeyPressHandler() {
          public void onKeyPress(final KeyPressEvent event) {
            if (event.getCharCode() == KeyCodes.KEY_ESCAPE) {
              unActivate();
            }
          }
        });

    commentBox.addKeyUpHandler(
        new KeyUpHandler() {
          public void onKeyUp(final KeyUpEvent event) {
            onCommentChanges();
          }
        });

    commentBox.addChangeHandler(
        new ChangeHandler() {
          public void onChange(final ChangeEvent event) {
            onCommentChanges();
          }
        });
  }
/** Post box. */
public class PostBoxComposite extends Composite {
  /** Max auto-complete hashtags to show. */
  private static final int MAX_HASH_TAG_AUTOCOMPLETE_ENTRIES = 10;

  /** Hide delay after blur on post box. */
  private static final Integer BLUR_DELAY = 500;

  /** Max chars for post. */
  private static final Integer POST_MAX = 250;

  /** Post box default height. */
  private static final int POST_BOX_DEFAULT_HEIGHT = 250;

  /** Padding for hashtag dropdown. */
  private static final int HASH_TAG_DROP_DOWN_PADDING = 14;

  /** Binder for building UI. */
  private static LocalUiBinder binder = GWT.create(LocalUiBinder.class);

  /** Binder for building UI. */
  interface LocalUiBinder extends UiBinder<Widget, PostBoxComposite> {}

  /** Post box CssResource style. */
  interface PostBoxStyle extends CssResource {
    /**
     * Visible post box style.
     *
     * @return Visible post box style.
     */
    String visiblePostBox();

    /**
     * Post char count over limit.
     *
     * @return Post char count over limit.
     */
    String postCharCountOverLimit();

    /**
     * Post button inactive.
     *
     * @return post button inactive.
     */
    String postButtonInactive();

    /**
     * Active hashtag style.
     *
     * @return Active hashtag style.
     */
    String activeHashTag();
  }

  /** Post box CssResource style. */
  @UiField PostBoxStyle style;

  /** UI element for poster avatar. */
  @UiField HTMLPanel posterAvatar;

  /** UI element for post panel. */
  @UiField HTMLPanel postPanel;

  /** UI element for post box. */
  @UiField ExtendedTextArea postBox;

  /** UI element for post options. */
  @UiField DivElement postOptions;

  /** UI element for post button. */
  @UiField PushButton postButton;

  /** UI element for post char count. */
  @UiField DivElement postCharCount;

  /** UI element for add link composite. */
  @UiField AddLinkComposite addLinkComposite;

  /** Hash Tags. */
  @UiField FlowPanel hashTags;

  /** The content warning. */
  @UiField Label contentWarning;

  /** The content warning container. */
  @UiField DivElement contentWarningContainer;

  /** Currently active item. */
  private Integer activeItemIndex = null;

  /** Timer factory. */
  private final TimerFactory timerFactory = new TimerFactory();

  /** Current stream to post to. */
  private StreamScope currentStream =
      new StreamScope(ScopeType.PERSON, Session.getInstance().getCurrentPerson().getAccountId());

  /** Avatar Renderer. */
  private final AvatarRenderer avatarRenderer = new AvatarRenderer();

  /** Activity Populator. */
  private final ActivityDTOPopulator activityPopulator = new ActivityDTOPopulator();

  /** Attachment. */
  private Attachment attachment = null;

  /** All hash tags. */
  private ArrayList<String> allHashTags;

  /** Default constructor. */
  public PostBoxComposite() {
    initWidget(binder.createAndBindUi(this));
    buildPage();
  }

  /** Build page. */
  private void buildPage() {
    posterAvatar.add(
        avatarRenderer.render(
            Session.getInstance().getCurrentPerson().getEntityId(),
            Session.getInstance().getCurrentPerson().getAvatarId(),
            EntityType.PERSON,
            Size.Small));
    postCharCount.setInnerText(POST_MAX.toString());
    checkPostBox();
    postBox.setLabel("Post to your stream...");
    postBox.reset();

    addEvents();

    postBox.addKeyUpHandler(
        new KeyUpHandler() {
          public void onKeyUp(final KeyUpEvent event) {
            checkPostBox();
          }
        });

    postBox.addFocusHandler(
        new FocusHandler() {
          public void onFocus(final FocusEvent event) {
            postOptions.addClassName(style.visiblePostBox());
          }
        });

    postBox.addBlurHandler(
        new BlurHandler() {
          public void onBlur(final BlurEvent event) {

            timerFactory.runTimer(
                BLUR_DELAY,
                new TimerHandler() {
                  public void run() {
                    if (postBox.getText().trim().length() == 0
                        && !addLinkComposite.inAddMode()
                        && attachment == null) {
                      postOptions.removeClassName(style.visiblePostBox());
                      postBox.getElement().getStyle().clearHeight();
                      postBox.reset();
                    }
                  }
                });
          }
        });

    setupPostButtonClickHandler();

    postBox.addKeyDownHandler(
        new KeyDownHandler() {
          public void onKeyDown(final KeyDownEvent event) {
            if ((event.getNativeKeyCode() == KeyCodes.KEY_TAB
                    || event.getNativeKeyCode() == KeyCodes.KEY_ENTER)
                && !event.isAnyModifierKeyDown()
                && activeItemIndex != null) {
              hashTags
                  .getWidget(activeItemIndex)
                  .getElement()
                  .dispatchEvent(
                      Document.get().createClickEvent(1, 0, 0, 0, 0, false, false, false, false));
              event.preventDefault();
              event.stopPropagation();
              // clearSearch();

            } else if (event.getNativeKeyCode() == KeyCodes.KEY_DOWN && activeItemIndex != null) {
              if (activeItemIndex + 1 < hashTags.getWidgetCount()) {
                selectItem((Label) hashTags.getWidget(activeItemIndex + 1));
              }
              event.preventDefault();
              event.stopPropagation();
            } else if (event.getNativeKeyCode() == KeyCodes.KEY_UP && activeItemIndex != null) {
              if (activeItemIndex - 1 >= 0) {
                selectItem((Label) hashTags.getWidget(activeItemIndex - 1));
              }
              event.preventDefault();
              event.stopPropagation();
            } else if (event.getNativeKeyCode() == KeyCodes.KEY_ENTER && event.isControlKeyDown()) {
              postButton
                  .getElement()
                  .dispatchEvent(
                      Document.get().createClickEvent(1, 0, 0, 0, 0, false, false, false, false));
              event.preventDefault();
              event.stopPropagation();
            }
          }
        });

    postBox.addKeyUpHandler(
        new KeyUpHandler() {
          public void onKeyUp(final KeyUpEvent event) {
            int tagsAdded = 0;

            String postText = postBox.getText();
            if (!postText.endsWith(" ")) {
              String[] words = postText.split("\\s");
              if (words.length >= 1) {
                final String lastWord = words[words.length - 1];
                if (lastWord.startsWith("#")) {
                  boolean activeItemSet = false;
                  Label firstItem = null;

                  for (String hashTag : allHashTags) {
                    if (hashTag.startsWith(lastWord)) {
                      // get list ready on first tag added
                      if (tagsAdded == 0) {
                        hashTags.clear();

                        String boxHeight =
                            postBox.getElement().getStyle().getHeight().replace("px", "");
                        if (boxHeight.isEmpty()) {
                          boxHeight = "44";
                        }
                        hashTags
                            .getElement()
                            .getStyle()
                            .setTop(
                                Integer.parseInt(boxHeight) + HASH_TAG_DROP_DOWN_PADDING, Unit.PX);
                        hashTags.setVisible(true);
                      }

                      final String hashTagFinal = hashTag;
                      final Label tagLbl = new Label(hashTagFinal);
                      tagLbl.addClickHandler(
                          new ClickHandler() {
                            public void onClick(final ClickEvent event) {
                              String postText = postBox.getText();
                              postText =
                                  postText.substring(0, postText.length() - lastWord.length())
                                      + hashTagFinal
                                      + " ";
                              postBox.setText(postText);
                              hashTags.setVisible(false);
                              hashTags.clear();
                              activeItemIndex = null;
                            }
                          });
                      tagLbl.addMouseOverHandler(
                          new MouseOverHandler() {
                            public void onMouseOver(final MouseOverEvent arg0) {
                              selectItem(tagLbl);
                            }
                          });
                      hashTags.add(tagLbl);

                      if (firstItem == null) {
                        firstItem = tagLbl;
                      }

                      if (activeItemIndex != null
                          && activeItemIndex.equals(hashTags.getWidgetCount() - 1)) {
                        activeItemIndex = null;
                        activeItemSet = true;
                        selectItem(tagLbl);
                      }

                      tagsAdded++;
                      if (tagsAdded >= MAX_HASH_TAG_AUTOCOMPLETE_ENTRIES) {
                        break;
                      }
                    }
                  }

                  if (!activeItemSet && firstItem != null) {
                    activeItemIndex = null;
                    selectItem(firstItem);
                  }
                }
              }
            }

            if (tagsAdded == 0) {
              hashTags.setVisible(false);
              activeItemIndex = null;
            }
          }
        });

    AllPopularHashTagsModel.getInstance().fetch(null, true);
    SystemSettingsModel.getInstance().fetch(null, true);

    hashTags.setVisible(false);
  }

  /** Add events. */
  private void addEvents() {
    EventBus.getInstance()
        .addObserver(
            MessageStreamAppendEvent.class,
            new Observer<MessageStreamAppendEvent>() {
              public void update(final MessageStreamAppendEvent event) {
                attachment = null;
                addLinkComposite.close();
                postBox.setText("");
                postBox.reset();
                postBox.getElement().getStyle().clearHeight();
                postOptions.removeClassName(style.visiblePostBox());
                checkPostBox();
              }
            });

    EventBus.getInstance()
        .addObserver(
            PostableStreamScopeChangeEvent.class,
            new Observer<PostableStreamScopeChangeEvent>() {
              public void update(final PostableStreamScopeChangeEvent stream) {
                currentStream = stream.getResponse();
                if (currentStream != null && !"".equals(currentStream.getDisplayName())) {
                  if (currentStream.getScopeType().equals(ScopeType.PERSON)) {
                    if (currentStream.getDisplayName().endsWith("s")) {
                      postBox.setLabel("Post to " + currentStream.getDisplayName() + "' stream...");
                    } else {
                      postBox.setLabel(
                          "Post to " + currentStream.getDisplayName() + "'s stream...");
                    }
                  } else {
                    postBox.setLabel(
                        "Post to the " + currentStream.getDisplayName() + " stream...");
                  }
                } else {
                  postBox.setLabel("Post to your stream...");
                }

                postPanel.setVisible(stream.getResponse().getScopeType() != null);
              }
            });

    EventBus.getInstance()
        .addObserver(
            MessageAttachmentChangedEvent.class,
            new Observer<MessageAttachmentChangedEvent>() {
              public void update(final MessageAttachmentChangedEvent evt) {
                attachment = evt.getAttachment();
              }
            });

    EventBus.getInstance()
        .addObserver(
            GotSystemSettingsResponseEvent.class,
            new Observer<GotSystemSettingsResponseEvent>() {
              public void update(final GotSystemSettingsResponseEvent event) {
                String warning = event.getResponse().getContentWarningText();
                if (warning != null && !warning.isEmpty()) {
                  contentWarning.setText(warning);
                } else {
                  contentWarning.setVisible(false);
                  contentWarningContainer.getStyle().setDisplay(Display.NONE);
                }
              }
            });

    Session.getInstance()
        .getEventBus()
        .addObserver(
            GotAllPopularHashTagsResponseEvent.class,
            new Observer<GotAllPopularHashTagsResponseEvent>() {
              public void update(final GotAllPopularHashTagsResponseEvent event) {
                allHashTags = new ArrayList<String>(event.getResponse());
              }
            });
  }

  /** Check the post box. */
  private void checkPostBox() {
    postCharCount.setInnerText(Integer.toString(POST_MAX - postBox.getText().length()));

    if (POST_MAX - postBox.getText().length() < 0) {
      postCharCount.addClassName(style.postCharCountOverLimit());
    } else {
      postCharCount.removeClassName(style.postCharCountOverLimit());
    }

    if ((postBox.getText().length() > 0 && POST_MAX - postBox.getText().length() >= 0)
        || attachment != null) {
      postButton.removeStyleName(style.postButtonInactive());
    } else {
      postButton.addStyleName(style.postButtonInactive());
    }
  }

  /**
   * Select an item.
   *
   * @param item the item.
   */
  private void selectItem(final Label item) {
    if (activeItemIndex != null) {
      hashTags.getWidget(activeItemIndex).removeStyleName(style.activeHashTag());
    }
    item.addStyleName(style.activeHashTag());
    activeItemIndex = hashTags.getWidgetIndex(item);
  }

  /**
   * Setup the post button click handler - to prevent the checkstyle error of too-long method name.
   */
  private void setupPostButtonClickHandler() {
    postButton.addClickHandler(
        new ClickHandler() {
          /**
           * Handle the button click.
           *
           * @param inEvent the click event
           */
          public void onClick(final ClickEvent inEvent) {
            if (!postButton.getStyleName().contains(style.postButtonInactive())) {
              ActivityDTOPopulatorStrategy objectStrat =
                  attachment != null ? attachment.getPopulator() : new NotePopulator();

              ActivityDTO activity =
                  activityPopulator.getActivityDTO(
                      postBox.getText(),
                      DomainConversionUtility.convertToEntityType(currentStream.getScopeType()),
                      currentStream.getUniqueKey(),
                      new PostPopulator(),
                      objectStrat);
              PostActivityRequest postRequest = new PostActivityRequest(activity);

              ActivityModel.getInstance().insert(postRequest);

              postButton.addStyleName(style.postButtonInactive());
            }
          }
        });
  }
}
  /** Add events. */
  private void addEvents() {
    EventBus.getInstance()
        .addObserver(
            MessageStreamAppendEvent.class,
            new Observer<MessageStreamAppendEvent>() {
              public void update(final MessageStreamAppendEvent event) {
                attachment = null;
                addLinkComposite.close();
                postBox.setText("");
                postBox.reset();
                postBox.getElement().getStyle().clearHeight();
                postOptions.removeClassName(style.visiblePostBox());
                checkPostBox();
              }
            });

    EventBus.getInstance()
        .addObserver(
            PostableStreamScopeChangeEvent.class,
            new Observer<PostableStreamScopeChangeEvent>() {
              public void update(final PostableStreamScopeChangeEvent stream) {
                currentStream = stream.getResponse();
                if (currentStream != null && !"".equals(currentStream.getDisplayName())) {
                  if (currentStream.getScopeType().equals(ScopeType.PERSON)) {
                    if (currentStream.getDisplayName().endsWith("s")) {
                      postBox.setLabel("Post to " + currentStream.getDisplayName() + "' stream...");
                    } else {
                      postBox.setLabel(
                          "Post to " + currentStream.getDisplayName() + "'s stream...");
                    }
                  } else {
                    postBox.setLabel(
                        "Post to the " + currentStream.getDisplayName() + " stream...");
                  }
                } else {
                  postBox.setLabel("Post to your stream...");
                }

                postPanel.setVisible(stream.getResponse().getScopeType() != null);
              }
            });

    EventBus.getInstance()
        .addObserver(
            MessageAttachmentChangedEvent.class,
            new Observer<MessageAttachmentChangedEvent>() {
              public void update(final MessageAttachmentChangedEvent evt) {
                attachment = evt.getAttachment();
              }
            });

    EventBus.getInstance()
        .addObserver(
            GotSystemSettingsResponseEvent.class,
            new Observer<GotSystemSettingsResponseEvent>() {
              public void update(final GotSystemSettingsResponseEvent event) {
                String warning = event.getResponse().getContentWarningText();
                if (warning != null && !warning.isEmpty()) {
                  contentWarning.setText(warning);
                } else {
                  contentWarning.setVisible(false);
                  contentWarningContainer.getStyle().setDisplay(Display.NONE);
                }
              }
            });

    Session.getInstance()
        .getEventBus()
        .addObserver(
            GotAllPopularHashTagsResponseEvent.class,
            new Observer<GotAllPopularHashTagsResponseEvent>() {
              public void update(final GotAllPopularHashTagsResponseEvent event) {
                allHashTags = new ArrayList<String>(event.getResponse());
              }
            });
  }
  /** Build page. */
  private void buildPage() {
    posterAvatar.add(
        avatarRenderer.render(
            Session.getInstance().getCurrentPerson().getEntityId(),
            Session.getInstance().getCurrentPerson().getAvatarId(),
            EntityType.PERSON,
            Size.Small));
    postCharCount.setInnerText(POST_MAX.toString());
    checkPostBox();
    postBox.setLabel("Post to your stream...");
    postBox.reset();

    addEvents();

    postBox.addKeyUpHandler(
        new KeyUpHandler() {
          public void onKeyUp(final KeyUpEvent event) {
            checkPostBox();
          }
        });

    postBox.addFocusHandler(
        new FocusHandler() {
          public void onFocus(final FocusEvent event) {
            postOptions.addClassName(style.visiblePostBox());
          }
        });

    postBox.addBlurHandler(
        new BlurHandler() {
          public void onBlur(final BlurEvent event) {

            timerFactory.runTimer(
                BLUR_DELAY,
                new TimerHandler() {
                  public void run() {
                    if (postBox.getText().trim().length() == 0
                        && !addLinkComposite.inAddMode()
                        && attachment == null) {
                      postOptions.removeClassName(style.visiblePostBox());
                      postBox.getElement().getStyle().clearHeight();
                      postBox.reset();
                    }
                  }
                });
          }
        });

    setupPostButtonClickHandler();

    postBox.addKeyDownHandler(
        new KeyDownHandler() {
          public void onKeyDown(final KeyDownEvent event) {
            if ((event.getNativeKeyCode() == KeyCodes.KEY_TAB
                    || event.getNativeKeyCode() == KeyCodes.KEY_ENTER)
                && !event.isAnyModifierKeyDown()
                && activeItemIndex != null) {
              hashTags
                  .getWidget(activeItemIndex)
                  .getElement()
                  .dispatchEvent(
                      Document.get().createClickEvent(1, 0, 0, 0, 0, false, false, false, false));
              event.preventDefault();
              event.stopPropagation();
              // clearSearch();

            } else if (event.getNativeKeyCode() == KeyCodes.KEY_DOWN && activeItemIndex != null) {
              if (activeItemIndex + 1 < hashTags.getWidgetCount()) {
                selectItem((Label) hashTags.getWidget(activeItemIndex + 1));
              }
              event.preventDefault();
              event.stopPropagation();
            } else if (event.getNativeKeyCode() == KeyCodes.KEY_UP && activeItemIndex != null) {
              if (activeItemIndex - 1 >= 0) {
                selectItem((Label) hashTags.getWidget(activeItemIndex - 1));
              }
              event.preventDefault();
              event.stopPropagation();
            } else if (event.getNativeKeyCode() == KeyCodes.KEY_ENTER && event.isControlKeyDown()) {
              postButton
                  .getElement()
                  .dispatchEvent(
                      Document.get().createClickEvent(1, 0, 0, 0, 0, false, false, false, false));
              event.preventDefault();
              event.stopPropagation();
            }
          }
        });

    postBox.addKeyUpHandler(
        new KeyUpHandler() {
          public void onKeyUp(final KeyUpEvent event) {
            int tagsAdded = 0;

            String postText = postBox.getText();
            if (!postText.endsWith(" ")) {
              String[] words = postText.split("\\s");
              if (words.length >= 1) {
                final String lastWord = words[words.length - 1];
                if (lastWord.startsWith("#")) {
                  boolean activeItemSet = false;
                  Label firstItem = null;

                  for (String hashTag : allHashTags) {
                    if (hashTag.startsWith(lastWord)) {
                      // get list ready on first tag added
                      if (tagsAdded == 0) {
                        hashTags.clear();

                        String boxHeight =
                            postBox.getElement().getStyle().getHeight().replace("px", "");
                        if (boxHeight.isEmpty()) {
                          boxHeight = "44";
                        }
                        hashTags
                            .getElement()
                            .getStyle()
                            .setTop(
                                Integer.parseInt(boxHeight) + HASH_TAG_DROP_DOWN_PADDING, Unit.PX);
                        hashTags.setVisible(true);
                      }

                      final String hashTagFinal = hashTag;
                      final Label tagLbl = new Label(hashTagFinal);
                      tagLbl.addClickHandler(
                          new ClickHandler() {
                            public void onClick(final ClickEvent event) {
                              String postText = postBox.getText();
                              postText =
                                  postText.substring(0, postText.length() - lastWord.length())
                                      + hashTagFinal
                                      + " ";
                              postBox.setText(postText);
                              hashTags.setVisible(false);
                              hashTags.clear();
                              activeItemIndex = null;
                            }
                          });
                      tagLbl.addMouseOverHandler(
                          new MouseOverHandler() {
                            public void onMouseOver(final MouseOverEvent arg0) {
                              selectItem(tagLbl);
                            }
                          });
                      hashTags.add(tagLbl);

                      if (firstItem == null) {
                        firstItem = tagLbl;
                      }

                      if (activeItemIndex != null
                          && activeItemIndex.equals(hashTags.getWidgetCount() - 1)) {
                        activeItemIndex = null;
                        activeItemSet = true;
                        selectItem(tagLbl);
                      }

                      tagsAdded++;
                      if (tagsAdded >= MAX_HASH_TAG_AUTOCOMPLETE_ENTRIES) {
                        break;
                      }
                    }
                  }

                  if (!activeItemSet && firstItem != null) {
                    activeItemIndex = null;
                    selectItem(firstItem);
                  }
                }
              }
            }

            if (tagsAdded == 0) {
              hashTags.setVisible(false);
              activeItemIndex = null;
            }
          }
        });

    AllPopularHashTagsModel.getInstance().fetch(null, true);
    SystemSettingsModel.getInstance().fetch(null, true);

    hashTags.setVisible(false);
  }
/** Entry point classes define <code>onModuleLoad()</code>. */
public class ApplicationEntryPoint implements EntryPoint {
  /** Relative URL of page to redirect to for users without access. */
  private static final String ACCESS_DENIED_PAGE = "/requestaccess.html";

  /** Mandatory ID for the HTML body element to identify that the full app should be created. */
  private static final String FULL_APP_ELEMENT_ID = "full-app-rootpanel";

  /** Idle timeout in seconds. */
  private static final int APP_IDLE_TIMEOUT = 5 * 60;

  /** Display TOS. */
  private boolean displayTOS = true;

  /** The action processor. */
  private ActionProcessor processor;

  /** The root panel. */
  private RootPanel rootPanel;

  /** The master page. */
  private MasterComposite master;

  /** The jsni facade. */
  private final WidgetJSNIFacade jSNIFacade = new WidgetJSNIFacadeImpl();

  /** The session. */
  private final Session session = Session.getInstance();

  /** Employee lookup modal. */
  private static EmployeeLookupContent dialogContent;

  /** Shows the login. */
  private void showLogin() {
    Dialog.showCentered(new LoginDialogContent());
  }

  /** Method that gets called during load of the EntryPoint. */
  public void onModuleLoad() {
    // The entry point will be invoked when just a Eureka Connect widget is desired, so do nothing
    // if the
    // appropriate full-app element is not found
    rootPanel = RootPanel.get(FULL_APP_ELEMENT_ID);
    if (rootPanel == null) {
      return;
    }

    ActionRPCServiceAsync service = (ActionRPCServiceAsync) GWT.create(ActionRPCService.class);
    processor = new ActionProcessorImpl(service);

    ((ServiceDefTarget) service).setServiceEntryPoint("/gwt_rpc");

    StaticResourceBundle.INSTANCE.coreCss().ensureInjected();
    StaticResourceBundle.INSTANCE.yuiCss().ensureInjected();

    session.setActionProcessor(processor);
    session.setEventBus(EventBus.getInstance());
    session.setPeriodicEventManager(
        new PeriodicEventManager(APP_IDLE_TIMEOUT, new TimerFactory(), processor));

    master = new MasterComposite();

    EventBus.getInstance()
        .addObserver(
            FormLoginCompleteEvent.class,
            new Observer<FormLoginCompleteEvent>() {
              public void update(final FormLoginCompleteEvent event) {
                Window.Location.reload();
              }
            });

    EventBus.getInstance()
        .addObserver(
            TermsOfServiceAcceptedEvent.class,
            new Observer<TermsOfServiceAcceptedEvent>() {
              public void update(final TermsOfServiceAcceptedEvent event) {
                displayTOS = false;
                loadPerson();
              }
            });

    setUpGwtFunctions();

    processor.makeRequest(
        new ActionRequestImpl<PersonModelView>("noOperation", null),
        new AsyncCallback<Serializable>() {
          public void onFailure(final Throwable caught) {
            if (caught.getMessage().contains("NO_CREDENTIALS")) {
              showLogin();
            } else if (caught.getMessage().contains("LOGIN_DISABLED")) {
              Window.Location.assign(ACCESS_DENIED_PAGE);
            } else {
              Dialog.showCentered(
                  new MessageDialogContent("Unable to Establish Connection", "Please Refresh."));
            }
          }

          public void onSuccess(final Serializable sessionId) {
            ActionProcessorImpl.setCurrentSessionId((String) sessionId);

            loadPerson();
          }
        });
  }

  /** Load the person. */
  private void loadPerson() {
    // this must be the first action called so that the session is handled correctly
    processor.makeRequest(
        new ActionRequestImpl<PersonModelView>("getPersonModelView", null),
        new AsyncCallback<PersonModelView>() {
          /* implement the async call back methods */
          public void onFailure(final Throwable caught) {
            rootPanel.add(master);

            if (caught instanceof SessionException) {
              Dialog.showCentered(
                  new MessageDialogContent("Unable to Establish Session", "Please Refresh."));
            } else {
              Dialog.showCentered(
                  new MessageDialogContent("Unable to Establish Connection", "Please Refresh."));
            }
          }

          public void onSuccess(final PersonModelView resultMV) {
            // If user needs to accept ToS, short circuit here.
            if (!resultMV.getTosAcceptance()) {
              displayToS();
              return;
            }

            session.setAuthenticationType(resultMV.getAuthenticationType());
            session.setCurrentPerson(resultMV);
            session.setCurrentPersonRoles(resultMV.getRoles());
            jSNIFacade.setViewer(resultMV.getOpenSocialId(), resultMV.getAccountId());
            jSNIFacade.setOwner(resultMV.getOpenSocialId());
            processor.setQueueRequests(true);

            // create the StartTabs model before the event bus is buffered, so it's event wiring
            // stays
            // intact for the life of the app
            StartTabsModel.getInstance();

            recordStreamViewMetrics();
            recordPageViewMetrics();

            session.setHistoryHandler(new HistoryHandler());
            Session.getInstance().getEventBus().bufferObservers();
            History.fireCurrentHistoryState();

            processor.setQueueRequests(true);
            master.renderHeaderAndFooter();
            processor.fireQueuedRequests();
            processor.setQueueRequests(false);

            session.getPeriodicEventManager().start();
            rootPanel.add(master);
            Window.Location.replace("/#" + Page.ACTIVITY.toString());
          }
        });
  }

  /** Shows the ToS modal. */
  private void displayToS() {

    Session.getInstance()
        .getEventBus()
        .addObserver(
            GotSystemSettingsResponseEvent.class,
            new Observer<GotSystemSettingsResponseEvent>() {
              public void update(final GotSystemSettingsResponseEvent event) {
                if (displayTOS) {
                  Dialog.showCentered(
                      new TermsOfServiceDialogContent(
                          new TermsOfServiceDTO(event.getResponse().getTermsOfService()), false));
                }
              }
            });

    SystemSettingsModel.getInstance().fetch(null, true);
  }

  /** Record stream view metrics. */
  private void recordStreamViewMetrics() {
    // TODO: This is listening to the stream response event as the request stream event is called
    // twice on activity page for some reason (profile pages work correctly). Somewhere
    // this is filtered down to only one call to the server to get the stream, so response
    // event works fine for metrics, but should track down why request it double-firing.
    Session.getInstance()
        .getEventBus()
        .addObserver(
            GotStreamResponseEvent.class,
            new Observer<GotStreamResponseEvent>() {
              public void update(final GotStreamResponseEvent event) {
                UsageMetricDTO umd = new UsageMetricDTO(false, true);
                umd.setMetricDetails(event.getJsonRequest());
                UsageMetricModel.getInstance().insert(umd);
              }
            });
  }

  /** Record page view metrics. */
  private void recordPageViewMetrics() {
    Session.getInstance()
        .getEventBus()
        .addObserver(
            SwitchedHistoryViewEvent.class,
            new Observer<SwitchedHistoryViewEvent>() {
              public void update(final SwitchedHistoryViewEvent event) {
                UsageMetricDTO umd = new UsageMetricDTO(true, false);
                umd.setMetricDetails(event.getPage().toString());
                UsageMetricModel.getInstance().insert(umd);
              }
            });
  }

  /**
   * Fires off a gadget change state event.
   *
   * @param id the gadget id
   * @param view the view to set.
   * @param params the optional parameters.
   */
  public static void changeGadgetState(final int id, final String view, final String params) {
    GadgetStateChangeEvent event =
        new GadgetStateChangeEvent(new Long(id), "gadgetId", view, params);
    EventBus.getInstance().notifyObservers(event);
  }

  /**
   * Fires of the UpdateGadgetPrefsEvent when called from the gadget container.
   *
   * @param inId - id of the gadget being updated.
   * @param inPrefs - updated preferences for the gadget.
   */
  public static void updateGadgetPrefs(final int inId, final String inPrefs) {
    UpdateGadgetPrefsEvent event = new UpdateGadgetPrefsEvent(new Long(inId), inPrefs);
    EventBus.getInstance().notifyObservers(event);
  }

  /**
   * Get the save command object.
   *
   * @return the save command
   */
  private static Command getEmployeeSelectedCommand() {
    return new Command() {
      public void execute() {
        PersonModelView result = dialogContent.getPerson();
        AvatarUrlGenerator urlGen = new AvatarUrlGenerator(EntityType.PERSON);
        String imageUrl = urlGen.getSmallAvatarUrl(result.getId(), result.getAvatarId());

        callEmployeeSelectedHandler(result.getAccountId(), result.getDisplayName(), imageUrl);
      }
    };
  }

  /** Launch the employee lookup modal. */
  public static void launchEmployeeLookup() {
    dialogContent = new EmployeeLookupContent(getEmployeeSelectedCommand());
    Dialog.showCentered(dialogContent);
  }

  /**
   * Call the handler when the employee lookup is done.
   *
   * @param ntid the ntid.
   * @param displayName the display name.
   * @param avatarUrl the avatarurl.
   */
  private static native void callEmployeeSelectedHandler(
      final String ntid, final String displayName, final String avatarUrl)
      /*-{
             $wnd.empLookupCallback(ntid, displayName, avatarUrl);
      }-*/ ;

  /**
   * Get the people from the server, convert them to JSON, and feed them back to the handler.
   *
   * @param ntids the ntids.
   * @param callbackIndex the callback index.
   */
  public static void bulkGetPeople(final String[] ntids, final int callbackIndex) {
    Session.getInstance()
        .getEventBus()
        .addObserver(
            GotBulkEntityResponseEvent.class,
            new Observer<GotBulkEntityResponseEvent>() {
              public void update(final GotBulkEntityResponseEvent arg1) {
                List<String> ntidList = Arrays.asList(ntids);
                JsArray<JavaScriptObject> personJSONArray =
                    (JsArray<JavaScriptObject>) JavaScriptObject.createArray();
                int count = 0;

                if (ntidList.size() == arg1.getResponse().size()) {
                  boolean notCorrectResponse = false;
                  for (Serializable person : arg1.getResponse()) {
                    PersonModelView personMV = (PersonModelView) person;
                    if (ntidList.contains(personMV.getAccountId())) {
                      AvatarUrlGenerator urlGen = new AvatarUrlGenerator(EntityType.PERSON);
                      String imageUrl =
                          urlGen.getSmallAvatarUrl(personMV.getId(), personMV.getAvatarId());

                      JsArrayString personJSON = (JsArrayString) JavaScriptObject.createObject();
                      personJSON.set(0, personMV.getAccountId());
                      personJSON.set(1, personMV.getDisplayName());
                      personJSON.set(2, imageUrl);

                      personJSONArray.set(count, personJSON);
                      count++;
                    } else {
                      notCorrectResponse = true;
                      break;
                    }
                  }
                  if (!notCorrectResponse) {
                    callGotBulkPeopleCallback(personJSONArray, callbackIndex);
                  }
                }
              }
            });

    ArrayList<StreamEntityDTO> entities = new ArrayList<StreamEntityDTO>();

    for (int i = 0; i < ntids.length; i++) {
      StreamEntityDTO dto = new StreamEntityDTO();
      dto.setUniqueIdentifier(ntids[i]);
      dto.setType(EntityType.PERSON);
      entities.add(dto);
    }

    if (ntids.length == 0) {
      JsArray<JavaScriptObject> personJSONArray =
          (JsArray<JavaScriptObject>) JavaScriptObject.createArray();
      callGotBulkPeopleCallback(personJSONArray, callbackIndex);
    } else {
      BulkEntityModel.getInstance().fetch(entities, false);
    }
  }

  /**
   * Call the handler with the JSON data.
   *
   * @param data the data.
   * @param callbackIndex the callback index.
   */
  private static native void callGotBulkPeopleCallback(final JsArray data, final int callbackIndex)
      /*-{
             $wnd.bulkGetPeopleCallback[callbackIndex](data);
      }-*/ ;

  /**
   * Returns an additional property value given a key.
   *
   * @param key the key.
   * @return the value.
   */
  public static String getAddtionalProperty(final String key) {
    return Session.getInstance().getCurrentPerson().getAdditionalProperties().get(key);
  }

  /**
   * This method exposes the GWT History.newItem method to javascript. This is so gadgets can have
   * access to the browsers history token without triggering a refresh in IE. Amazingly, this
   * function wouldn't even need to exist if it weren't for IE. Yay for inter-browser support!
   */
  private static native void setUpGwtFunctions()/*-{
        $wnd.gwt_newHistoryItem = function(token) {
                @com.google.gwt.user.client.History::newItem(Ljava/lang/String;)(token);
        }

        $wnd.gwt_getAdditionalProperty = function(key) {
                return @org.eurekastreams.web.client.ui.pages.master.ApplicationEntryPoint::getAddtionalProperty(Ljava/lang/String;)(key);
        }

        $wnd.gwt_bulkGetPeople = function(ntids, handler) {
                if ($wnd.bulkGetPeopleCallback == null)
                {
                    $wnd.bulkGetPeopleCallback = [];
                }
                $wnd.bulkGetPeopleCallback.push(handler);
                @org.eurekastreams.web.client.ui.pages.master.ApplicationEntryPoint::bulkGetPeople([Ljava/lang/String;I)(ntids, $wnd.bulkGetPeopleCallback.length-1);
        }

        $wnd.gwt_launchEmpLookup = function(handler) {
                $wnd.empLookupCallback = handler;
                @org.eurekastreams.web.client.ui.pages.master.ApplicationEntryPoint::launchEmployeeLookup()();
        }

        $wnd.gwt_changeGadgetState = function(id, view, params) {
                @org.eurekastreams.web.client.ui.pages.master.ApplicationEntryPoint::changeGadgetState(ILjava/lang/String;Ljava/lang/String;)(id, view, params);
        }

        $wnd.gwt_updateGadgetPrefs = function(id, prefs) {
                @org.eurekastreams.web.client.ui.pages.master.ApplicationEntryPoint::updateGadgetPrefs(ILjava/lang/String;)(id, prefs);
        }

        $wnd.gwt_triggerShowNotificationEvent = function(notification) {
                var notificationEvent = @org.eurekastreams.web.client.events.ShowNotificationEvent::getInstance(Ljava/lang/String;)(notification);

                var s = @org.eurekastreams.web.client.ui.Session::getInstance()();
                var eb = [email protected]::getEventBus()();
                [email protected]::notifyObservers(Ljava/lang/Object;)(notificationEvent);
        }


        $wnd.jQuery('body').ready(function() {
                $wnd.jQuery('body').mousemove(function(e) {
                   $wnd.mouseXpos = e.pageX;
                   $wnd.mouseYpos = e.pageY;
                });
        });
    }-*/ ;

  /**
   * Get the user agent (for detecting IE7).
   *
   * @return the user agent.
   */
  public static native String getUserAgent()/*-{
        return navigator.userAgent.toLowerCase();
    }-*/ ;
}
  /**
   * Default constructor.
   *
   * @param json the id of the default view.
   */
  public StreamListFormElement(final JSONObject json) {
    scopes =
        new StreamScopeFormElement(
            "scopes",
            new LinkedList<StreamScope>(),
            "",
            "Enter the name of an employee or group.",
            false,
            true,
            "/resources/autocomplete/entities/",
            MAX_NAME,
            MAX_ITEMS);

    this.addStyleName(StaticResourceBundle.INSTANCE.coreCss().streamLists());
    label.addStyleName(StaticResourceBundle.INSTANCE.coreCss().formLabel());
    this.add(label);

    this.add(streamOptions);

    streamOptions.addItem("Everyone", "");
    streamOptions.addItem("Following", StreamJsonRequestFactory.FOLLOWED_BY_KEY);
    streamOptions.addItem("Saved", StreamJsonRequestFactory.SAVED_KEY);
    streamOptions.addItem("Groups I've Joined", StreamJsonRequestFactory.JOINED_GROUPS_KEY);
    streamOptions.addItem("Posted To", StreamJsonRequestFactory.RECIPIENT_KEY);
    streamOptions.addItem("Authored By", StreamJsonRequestFactory.AUTHOR_KEY);
    streamOptions.addItem("Liked By", StreamJsonRequestFactory.LIKER_KEY);

    streamOptions.addChangeHandler(
        new ChangeHandler() {
          public void onChange(final ChangeEvent event) {
            scopes.setVisible(hasStreamScopes(getSelected()));
          }
        });

    if (json == null) {
      streamOptions.setSelectedIndex(0);
      scopes.setVisible(false);
    } else {
      if (json.containsKey(StreamJsonRequestFactory.RECIPIENT_KEY)) {
        setSelectedByValue(StreamJsonRequestFactory.RECIPIENT_KEY);
      } else if (json.containsKey(StreamJsonRequestFactory.SAVED_KEY)) {
        setSelectedByValue(StreamJsonRequestFactory.SAVED_KEY);
      } else if (json.containsKey(StreamJsonRequestFactory.PARENT_ORG_KEY)) {
        setSelectedByValue(StreamJsonRequestFactory.PARENT_ORG_KEY);
      } else if (json.containsKey(StreamJsonRequestFactory.FOLLOWED_BY_KEY)) {
        setSelectedByValue(StreamJsonRequestFactory.FOLLOWED_BY_KEY);
      } else if (json.containsKey(StreamJsonRequestFactory.AUTHOR_KEY)) {
        setSelectedByValue(StreamJsonRequestFactory.AUTHOR_KEY);
      } else if (json.containsKey(StreamJsonRequestFactory.LIKER_KEY)) {
        setSelectedByValue(StreamJsonRequestFactory.LIKER_KEY);
      } else if (json.containsKey(StreamJsonRequestFactory.JOINED_GROUPS_KEY)) {
        setSelectedByValue(StreamJsonRequestFactory.JOINED_GROUPS_KEY);
      } else {
        setSelectedByValue("");
      }

      if (hasStreamScopes(getSelected())) {
        Session.getInstance()
            .getEventBus()
            .addObserver(
                GotBulkEntityResponseEvent.class,
                new Observer<GotBulkEntityResponseEvent>() {
                  public void update(final GotBulkEntityResponseEvent event) {
                    JSONArray recipientArray = json.get(getSelected()).isArray();

                    for (int i = 0; i < recipientArray.size(); i++) {
                      JSONObject recipient = (JSONObject) recipientArray.get(i);
                      String uniqueId =
                          recipient
                              .get(StreamJsonRequestFactory.ENTITY_UNIQUE_ID_KEY)
                              .isString()
                              .stringValue();
                      String displayName =
                          getEntityDisplayName(
                              EntityType.valueOf(
                                  recipient
                                      .get(StreamJsonRequestFactory.ENTITY_TYPE_KEY)
                                      .isString()
                                      .stringValue()),
                              uniqueId,
                              event.getResponse());

                      ScopeType scopeType =
                          ScopeType.valueOf(
                              recipient
                                  .get(StreamJsonRequestFactory.ENTITY_TYPE_KEY)
                                  .isString()
                                  .stringValue());

                      StreamScope scope = new StreamScope(scopeType, uniqueId);
                      scope.setDisplayName(displayName);

                      Session.getInstance()
                          .getEventBus()
                          .notifyObservers(new StreamScopeAddedEvent(scope));
                    }

                    Session.getInstance()
                        .getEventBus()
                        .removeObserver(GotBulkEntityResponseEvent.class, this);
                  }
                });

        ArrayList<StreamEntityDTO> entities = new ArrayList<StreamEntityDTO>();

        JSONArray recipientArray = json.get(getSelected()).isArray();
        for (int i = 0; i < recipientArray.size(); i++) {
          JSONObject recipient = (JSONObject) recipientArray.get(i);
          StreamEntityDTO entity = new StreamEntityDTO();
          entity.setType(
              EntityType.valueOf(
                  recipient
                      .get(StreamJsonRequestFactory.ENTITY_TYPE_KEY)
                      .isString()
                      .stringValue()));
          entity.setUniqueIdentifier(
              recipient
                  .get(StreamJsonRequestFactory.ENTITY_UNIQUE_ID_KEY)
                  .isString()
                  .stringValue());
          entities.add(entity);
        }
        BulkEntityModel.getInstance().fetch(entities, false);
      }
    }

    this.add(scopes);
  }
  /**
   * Builds the UI.
   *
   * @param inScope the scope.
   */
  private void setupWidgets(final StreamScope inScope) {
    this.getElement().setAttribute("id", "post-to-stream");
    this.addStyleName(StaticResourceBundle.INSTANCE.coreCss().small());

    charsRemaining = new Label();
    postButton = new Hyperlink("", History.getToken());
    postButton.getElement().setAttribute("tabindex", "2");
    message = new PostToStreamTextboxPanel();
    message.setText(postBoxDefaultText);
    message.setVisible(false); // Hide until post ready event.

    this.addStyleName(StaticResourceBundle.INSTANCE.coreCss().postToStream());
    errorMsg.addStyleName(StaticResourceBundle.INSTANCE.coreCss().formErrorBox());
    errorMsg.setVisible(false);
    this.add(errorMsg);

    FlowPanel postInfoContainer = new FlowPanel();
    postInfoContainer.addStyleName(StaticResourceBundle.INSTANCE.coreCss().postInfoContainer());

    postButton.addStyleName(StaticResourceBundle.INSTANCE.coreCss().postButton());
    postInfoContainer.add(postButton);

    charsRemaining.addStyleName(StaticResourceBundle.INSTANCE.coreCss().charactersRemaining());
    postInfoContainer.add(charsRemaining);

    AvatarWidget avatar =
        new AvatarWidget(
            Session.getInstance().getCurrentPerson(), EntityType.PERSON, Size.VerySmall);
    avatar.addStyleName(StaticResourceBundle.INSTANCE.coreCss().postEntryAvatar());

    Panel entryPanel = new FlowPanel();
    entryPanel.addStyleName(StaticResourceBundle.INSTANCE.coreCss().postEntryPanel());
    entryPanel.add(avatar);
    entryPanel.add(postInfoContainer);
    entryPanel.add(message);
    SimplePanel breakPanel = new SimplePanel();
    breakPanel.addStyleName(StaticResourceBundle.INSTANCE.coreCss().breakClass());
    entryPanel.add(breakPanel);
    add(entryPanel);

    // below text area: links and post to on one line, then content warning below

    expandedPanel.addStyleName(StaticResourceBundle.INSTANCE.coreCss().postExpandedPanel());

    postToPanel = new PostToPanel(inScope);
    expandedPanel.add(postToPanel);
    links = new AddLinkComposite();
    expandedPanel.add(links);

    contentWarning = new FlowPanel();
    contentWarningContainer.addStyleName(StaticResourceBundle.INSTANCE.coreCss().contentWarning());
    contentWarningContainer.add(new SimplePanel());
    contentWarningContainer.add(contentWarning);
    expandedPanel.add(contentWarningContainer);

    add(expandedPanel);

    setVisible(false);

    setVisible(Session.getInstance().getCurrentPerson() != null);
  }
  /** Wires up events. */
  private void setupEvents() {
    // user clicked in message text box
    message.addFocusHandler(
        new FocusHandler() {
          public void onFocus(final FocusEvent inEvent) {
            if ((" " + getStyleName() + " ")
                .contains(StaticResourceBundle.INSTANCE.coreCss().small())) {
              removeStyleName(StaticResourceBundle.INSTANCE.coreCss().small());
              onExpand();
            }
          }
        });

    message.addValueChangedHandler(
        new ValueChangeHandler<String>() {
          public void onValueChange(final ValueChangeEvent<String> newValue) {
            checkMessageTextChanged();
          }
        });

    // user typed in message text box
    message.addKeystrokeHandler(
        new KeyUpHandler() {
          public void onKeyUp(final KeyUpEvent ev) {
            if (ev.getNativeKeyCode() == KeyCodes.KEY_ENTER
                && ev.isControlKeyDown()
                && message.getText().length() > 0) {
              checkMessageTextChanged();
              handlePostMessage();
            } else {
              checkMessageTextChanged();
            }
          }
        });

    // user clicked on post button
    postButton.addClickHandler(
        new ClickHandler() {
          public void onClick(final ClickEvent ev) {
            checkMessageTextChanged();
            handlePostMessage();
          }
        });

    final EventBus eventBus = Session.getInstance().getEventBus();
    eventBus.addObserver(
        MessageStreamAppendEvent.class,
        new Observer<MessageStreamAppendEvent>() {
          public void update(final MessageStreamAppendEvent event) {
            errorMsg.setVisible(false);
            addStyleName(StaticResourceBundle.INSTANCE.coreCss().small());
            messageText = "";
            message.setText(postBoxDefaultText);
            onRemainingCharactersChanged();
            links.close();
          }
        });

    eventBus.addObserver(
        GotSystemSettingsResponseEvent.class,
        new Observer<GotSystemSettingsResponseEvent>() {
          public void update(final GotSystemSettingsResponseEvent event) {
            String warning = event.getResponse().getContentWarningText();
            if (warning != null && !warning.isEmpty()) {
              contentWarning.getElement().setInnerHTML(warning);
            } else {
              contentWarning.setVisible(false);
            }
            message.setVisible(true);
          }
        });

    eventBus.addObserver(
        MessageTextAreaChangedEvent.getEvent(),
        new Observer<MessageTextAreaChangedEvent>() {
          public void update(final MessageTextAreaChangedEvent arg1) {
            // the value changed - make sure we're not stuck in the disabled, non-editable mode
            if ((" " + getStyleName() + " ")
                .contains(StaticResourceBundle.INSTANCE.coreCss().small())) {
              removeStyleName(StaticResourceBundle.INSTANCE.coreCss().small());
            }
            onRemainingCharactersChanged();
          }
        });

    eventBus.addObserver(
        MessageAttachmentChangedEvent.class,
        new Observer<MessageAttachmentChangedEvent>() {
          public void update(final MessageAttachmentChangedEvent evt) {
            errorMsg.setVisible(false);
            attachment = evt.getAttachment();
            if (attachment == null && messageText.isEmpty()) {
              hidePostButton();
            } else {
              showPostButton();
            }
          }
        });

    eventBus.addObserver(
        new ErrorPostingMessageToNullScopeEvent(),
        new Observer<ErrorPostingMessageToNullScopeEvent>() {
          public void update(final ErrorPostingMessageToNullScopeEvent event) {
            errorMsg.setText(event.getErrorMsg());
            errorMsg.setVisible(true);
            showPostButton();
          }
        });
  }
  /** Default constructor. */
  public MasterComposite() {
    actionProcessor = Session.getInstance().getActionProcessor();

    evtMgr = Session.getInstance().getPeriodicEventManager();

    panel =
        new FlowPanel() {
          @Override
          public void onBrowserEvent(final Event ev) {
            super.onBrowserEvent(ev);
            evtMgr.userActivityDetected();
          }
        };
    panel.sinkEvents(Event.KEYEVENTS | Event.FOCUSEVENTS | Event.MOUSEEVENTS & ~Event.ONMOUSEMOVE);
    panel.addStyleName(StaticResourceBundle.INSTANCE.coreCss().main());

    headerPanel.addStyleName(StaticResourceBundle.INSTANCE.coreCss().headerContainer());

    notifier.addStyleName(StaticResourceBundle.INSTANCE.coreCss().masterNotifier());
    panel.add(notifier);

    mainContents.addStyleName(StaticResourceBundle.INSTANCE.coreCss().mainContents());
    mainContents.add(headerPanel);

    mainContents.add(contentPanel);
    contentPanel.addStyleName(StaticResourceBundle.INSTANCE.coreCss().content());
    panel.add(mainContents);

    initWidget(panel);

    Session.getInstance()
        .getEventBus()
        .addObserver(
            GetTutorialVideoResponseEvent.class,
            new Observer<GetTutorialVideoResponseEvent>() {
              public void update(final GetTutorialVideoResponseEvent event) {
                HashSet<TutorialVideoDTO> tutVids = event.getResponse();
                PersonModelView currentPerson = Session.getInstance().getCurrentPerson();

                for (TutorialVideoDTO vid : tutVids) {
                  if (vid.getPage() == currentPage) {
                    if (currentPage == Page.PEOPLE
                        && !(currentViews.contains(currentPerson.getAccountId()))) {
                      // if you are on the person profile tab but it's not you then don't show this
                      // dialog.
                      break;
                    }
                    if (!(currentPerson.getOptOutVideos().contains(vid.getEntityId()))) {
                      final Integer videoWidth =
                          vid.getVideoWidth() != null
                              ? vid.getVideoWidth()
                              : OptOutableVideoDialogContent.DEFAULT_VIDEO_WIDTH;

                      OptOutableVideoDialogContent dialogContent =
                          new OptOutableVideoDialogContent(vid);
                      Dialog dialog =
                          new Dialog(dialogContent) {
                            {
                              getPopupPanel().setModal(true);
                            }

                            @Override
                            public void center() {
                              getPopupPanel()
                                  .setWidth(
                                      videoWidth
                                          + OptOutableVideoDialogContent.CONTENT_WIDTH
                                          + OptOutableVideoDialogContent.MARGIN_OFFSET
                                          + "px");
                              super.center();
                              getPopupPanel()
                                  .setPopupPosition(
                                      getPopupPanel().getAbsoluteLeft(),
                                      OptOutableVideoDialogContent.DIALOG_HEIGHT_OFFSET);
                            }
                          };
                      dialog.show();
                    }
                    break;
                  }
                }
              }
            });

    Session.getInstance()
        .getEventBus()
        .addObserver(
            SwitchedHistoryViewEvent.class,
            new Observer<SwitchedHistoryViewEvent>() {
              public void update(final SwitchedHistoryViewEvent event) {
                mainContents.remove(banner);
                notifier.setVisible(false);
                contentPanel.clear();
                factory.createPage(event.getPage(), event.getViews(), contentPanel);
                currentPage = event.getPage();
                currentViews = event.getViews();
                pageHasBeenLoaded = true;
                TutorialVideoModel.getInstance().fetch(null, true);
              }
            });

    Session.getInstance()
        .getEventBus()
        .addObserver(
            SetBannerEvent.class,
            new Observer<SetBannerEvent>() {
              public void update(final SetBannerEvent event) {
                mainContents.insert(banner, 1);

                // Banner exists and should override the banner the theme is supplying. (i.e.
                // profile page.)
                if (event.getBannerableEntity() != null) {
                  AvatarUrlGenerator urlGen = new AvatarUrlGenerator(null);
                  new WidgetJSNIFacadeImpl()
                      .setBanner(urlGen.getBannerUrl(event.getBannerableEntity().getBannerId()));
                }
                // Start page, the bannerable entity is null, just clear out the banner value
                // to let the theme take over again.
                else {
                  new WidgetJSNIFacadeImpl().clearBanner(false);
                }
              }
            });
  }
  /** Render header and footer. */
  public void renderHeaderAndFooter() {
    PersonModelView person = Session.getInstance().getCurrentPerson();

    headerPanel.clear();
    headerPanel.add(getHeaderComposite(person));
  }
  /**
   * Create an avatar upload form element.
   *
   * @param label the label of the element.
   * @param desc the description.
   * @param servletPath the path to hit to upload the image
   * @param inProcessor the processor.
   * @param inStrategy the strategy.
   */
  public AvatarUploadFormElement(
      final String label,
      final String desc,
      final String servletPath,
      final ActionProcessor inProcessor,
      final ImageUploadStrategy inStrategy) {
    description = desc;
    strategy = inStrategy;
    Boolean resizeable = strategy.isResizable();

    errorBox = new FlowPanel();
    errorBox.addStyleName(StaticResourceBundle.INSTANCE.coreCss().formErrorBox());
    errorBox.add(
        new Label(
            "There was an error uploading your image. Please be sure "
                + "that your photo is under 4MB and is a PNG, JPG, or GIF."));

    errorBox.setVisible(false);

    this.addStyleName(StaticResourceBundle.INSTANCE.coreCss().formAvatarUpload());
    this.addStyleName(StaticResourceBundle.INSTANCE.coreCss().formElement());

    processor = inProcessor;
    // AvatarEntity Entity = inEntity;

    uploadForm.setAction(servletPath);

    uploadForm.setEncoding(FormPanel.ENCODING_MULTIPART);
    uploadForm.setMethod(FormPanel.METHOD_POST);

    Label photoLabel = new Label(label);
    photoLabel.addStyleName(StaticResourceBundle.INSTANCE.coreCss().formLabel());
    panel.add(photoLabel);

    FlowPanel avatarModificationPanel = new FlowPanel();
    avatarModificationPanel.addStyleName(
        StaticResourceBundle.INSTANCE.coreCss().avatarModificationPanel());

    avatarContainer.addStyleName(StaticResourceBundle.INSTANCE.coreCss().avatarContainer());
    avatarModificationPanel.add(avatarContainer);

    FlowPanel photoButtonPanel = new FlowPanel();
    photoButtonPanel.addStyleName(StaticResourceBundle.INSTANCE.coreCss().formPhotoButtonPanel());

    if (resizeable) {
      editButton = new Anchor("Resize");
      editButton.addStyleName(StaticResourceBundle.INSTANCE.coreCss().formResizeButton());
      editButton.addStyleName(StaticResourceBundle.INSTANCE.coreCss().formButton());
      photoButtonPanel.add(editButton);
    }

    deleteButton = new Anchor("Delete");
    deleteButton.addStyleName(StaticResourceBundle.INSTANCE.coreCss().formDeleteButton());
    deleteButton.addStyleName(StaticResourceBundle.INSTANCE.coreCss().formButton());
    photoButtonPanel.add(deleteButton);

    avatarModificationPanel.add(photoButtonPanel);
    panel.add(avatarModificationPanel);

    FlowPanel uploadPanel = new FlowPanel();
    uploadPanel.addStyleName(StaticResourceBundle.INSTANCE.coreCss().formUploadPanel());
    uploadPanel.add(errorBox);

    // Wrapping the FileUpload because otherwise IE7 shifts it way
    // to the right. I couldn't figure out why,
    // but for whatever reason, this works.
    FlowPanel fileUploadWrapper = new FlowPanel();
    FileUpload upload = new FileUpload();
    upload.setName("imageUploadFormElement");
    upload.addStyleName(StaticResourceBundle.INSTANCE.coreCss().formAvatarUpload());
    fileUploadWrapper.add(upload);
    uploadPanel.add(fileUploadWrapper);

    uploadPanel.add(new Label(description));
    Anchor submitButton = new Anchor("");
    submitButton.addStyleName(StaticResourceBundle.INSTANCE.coreCss().formUploadButton());
    submitButton.addStyleName(StaticResourceBundle.INSTANCE.coreCss().formButton());

    uploadPanel.add(submitButton);

    hiddenImage = new Image();
    hiddenImage.addStyleName(StaticResourceBundle.INSTANCE.coreCss().avatarHiddenOriginal());
    uploadPanel.add(hiddenImage);

    panel.add(uploadPanel);

    submitButton.addClickHandler(
        new ClickHandler() {
          public void onClick(final ClickEvent event) {
            uploadForm.submit();
          }
        });

    uploadForm.setWidget(panel);
    this.add(uploadForm);

    uploadForm.addSubmitCompleteHandler(
        new SubmitCompleteHandler() {
          public void onSubmitComplete(final SubmitCompleteEvent ev) {
            String result = ev.getResults().replaceAll("\\<.*?\\>", "");
            final boolean fail = "fail".equals(result);
            errorBox.setVisible(fail);
            if (!fail) {
              String[] results = result.split(",");
              if (results.length >= 4) {
                strategy.setX(Integer.parseInt(results[1]));
                strategy.setY(Integer.parseInt(results[2]));
                strategy.setCropSize(Integer.parseInt(results[3]));
              }
              onAvatarIdChanged(results[0], strategy.getEntityType() == EntityType.PERSON);
            }
          }
        });

    if (editButton != null) {
      editButton.addClickHandler(
          new ClickHandler() {
            public void onClick(final ClickEvent inArg0) {
              // Since the size of the image is required before we can correctly show the
              // resize dialog, this method determines the avatar url and sets image url.
              // The load event of that image being loaded will kick off the resize modal.
              AvatarUrlGenerator urlGenerator = new AvatarUrlGenerator(EntityType.PERSON);
              hiddenImage.setUrl(urlGenerator.getOriginalAvatarUrl(avatarId));
            }
          });
      hiddenImage.addLoadHandler(
          new LoadHandler() {
            public void onLoad(final LoadEvent inEvent) {
              imageCropDialog =
                  new ImageCropContent(
                      strategy,
                      processor,
                      avatarId,
                      new Command() {
                        public void execute() {
                          onAvatarIdChanged(
                              strategy.getImageId(), strategy.getEntityType() == EntityType.PERSON);
                        }
                      },
                      hiddenImage.getWidth() + "px",
                      hiddenImage.getHeight() + "px");

              Dialog dialog = new Dialog(imageCropDialog);
              dialog.showCentered();
            }
          });
    }

    if (strategy.getImageType().equals(ImageType.BANNER)) {
      onAvatarIdChanged(
          strategy.getImageId(),
          strategy.getId().equals(strategy.getImageEntityId()),
          true,
          strategy.getEntityType() == EntityType.PERSON);
    } else {
      onAvatarIdChanged(strategy.getImageId(), strategy.getEntityType() == EntityType.PERSON);
    }

    deleteButton.addClickHandler(
        new ClickHandler() {
          @SuppressWarnings("unchecked")
          public void onClick(final ClickEvent event) {
            if (new WidgetJSNIFacadeImpl()
                .confirm("Are you sure you want to delete your current photo?")) {
              strategy.getDeleteAction().delete(strategy.getDeleteParam());
            }
          }
        });

    Session.getInstance()
        .getEventBus()
        .addObserver(
            ClearUploadedImageEvent.class,
            new Observer<ClearUploadedImageEvent>() {
              public void update(final ClearUploadedImageEvent event) {
                if (event.getImageType().equals(strategy.getImageType())
                    && event.getEntityType().equals(strategy.getEntityType())) {
                  if (event.getImageType().equals(ImageType.BANNER)) {
                    onAvatarIdChanged(
                        event.getEntity().getBannerId(),
                        strategy.getId().equals(event.getEntity().getBannerEntityId()),
                        true,
                        strategy.getEntityType() == EntityType.PERSON);
                  } else {
                    onAvatarIdChanged(null, strategy.getEntityType() == EntityType.PERSON);
                  }
                }
              }
            });
  }
  /** Activate the control. */
  public void activate() {
    clear();
    this.setVisible(true);
    Widget avatar =
        new AvatarWidget(
            Session.getInstance().getCurrentPerson().getAvatarId(),
            EntityType.PERSON,
            Size.VerySmall);
    avatar.addStyleName(StaticResourceBundle.INSTANCE.coreCss().avatar());
    this.add(avatar);

    FlowPanel body = new FlowPanel();
    body.addStyleName(StaticResourceBundle.INSTANCE.coreCss().body());

    SimplePanel boxWrapper = new SimplePanel();
    boxWrapper.addStyleName(StaticResourceBundle.INSTANCE.coreCss().boxWrapper());
    commentBox = new ExtendedTextArea(true);
    boxWrapper.add(commentBox);
    body.add(boxWrapper);
    commentBox.setFocus(true);

    countDown = new Label(Integer.toString(MAXLENGTH));
    countDown.addStyleName(StaticResourceBundle.INSTANCE.coreCss().charactersRemaining());
    body.add(countDown);

    post = new PushButton("post");
    post.addStyleName(StaticResourceBundle.INSTANCE.coreCss().postButton());
    post.addStyleName(StaticResourceBundle.INSTANCE.coreCss().inactive());
    body.add(post);

    final Label warning = new Label();
    warning.addStyleName(StaticResourceBundle.INSTANCE.coreCss().warning());
    warning.addStyleName(StaticResourceBundle.INSTANCE.coreCss().hidden());
    body.add(warning);

    Session.getInstance()
        .getEventBus()
        .addObserver(
            GotSystemSettingsResponseEvent.class,
            new Observer<GotSystemSettingsResponseEvent>() {
              public void update(final GotSystemSettingsResponseEvent event) {
                String text = event.getResponse().getContentWarningText();
                if (text != null && !text.isEmpty()) {
                  warning.removeStyleName(StaticResourceBundle.INSTANCE.coreCss().hidden());
                  warning.setText(text);
                }
              }
            });

    SystemSettingsModel.getInstance().fetch(null, true);

    post.addClickHandler(
        new ClickHandler() {
          public void onClick(final ClickEvent event) {
            fullCollapse = false;
            if (!inactive) {
              unActivate();
              CommentDTO comment = new CommentDTO();
              comment.setBody(commentBox.getText());
              comment.setActivityId(messageId);
              Session.getInstance()
                  .getActionProcessor()
                  .makeRequest(
                      "postActivityCommentAction",
                      comment,
                      new AsyncCallback<CommentDTO>() {
                        /* implement the async call back methods */
                        public void onFailure(final Throwable caught) {}

                        public void onSuccess(final CommentDTO result) {
                          ActivityModel.getInstance().clearCache();
                          Session.getInstance()
                              .getEventBus()
                              .notifyObservers(new CommentAddedEvent(result, messageId));
                        }
                      });
            }
          }
        });

    this.add(body);
    commentBox.setFocus(true);
    nativeSetFocus(commentBox.getElement());

    commentBox.addBlurHandler(
        new BlurHandler() {
          public void onBlur(final BlurEvent arg0) {
            TimerFactory timerFactory = new TimerFactory();
            timerFactory.runTimer(
                BLUR_DELAY,
                new TimerHandler() {
                  public void run() {
                    if (commentBox.getText().length() == 0) {
                      unActivate();
                    }
                  }
                });
          }
        });

    commentBox.addKeyDownHandler(
        new KeyDownHandler() {
          public void onKeyDown(final KeyDownEvent event) {
            if (event.getNativeKeyCode() == KeyCodes.KEY_ESCAPE) {
              unActivate();
            } else if (event.getNativeKeyCode() == KeyCodes.KEY_ENTER && event.isControlKeyDown()) {
              post.getElement()
                  .dispatchEvent(
                      Document.get().createClickEvent(1, 0, 0, 0, 0, false, false, false, false));
              event.preventDefault();
              event.stopPropagation();
            }
          }
        });

    commentBox.addKeyUpHandler(
        new KeyUpHandler() {
          public void onKeyUp(final KeyUpEvent event) {
            onCommentChanges();
          }
        });

    commentBox.addValueChangeHandler(
        new ValueChangeHandler<String>() {
          public void onValueChange(final ValueChangeEvent<String> inArg0) {
            onCommentChanges();
          }
        });

    commentBox.addChangeHandler(
        new ChangeHandler() {
          public void onChange(final ChangeEvent event) {
            onCommentChanges();
          }
        });
  }