void FSFloaterNearbyChat::onOpen(const LLSD& key )
{
	FSFloaterIMContainer* floater_container = FSFloaterIMContainer::getInstance();
	if (floater_container)
	{
		if (gSavedSettings.getBOOL("ChatHistoryTornOff"))
		{
			// first set the tear-off host to this floater
			setHost(floater_container);
			// clear the tear-off host right after, the "last host used" will still stick
			setHost(NULL);
			// reparent the floater to the main view
			gFloaterView->addChild(this);
		}
		else
		{
			floater_container->addFloater(this, FALSE);
		}
	}

	// We override this to put nearbychat in the IM floater. -AO
	if(isChatMultiTab() && ! isVisible(this))
	{
		// only show the floater container if we are actually attached -Zi
		if (floater_container && !gSavedSettings.getBOOL("ChatHistoryTornOff"))
		{
			// make sure to show our parent floater, too
			floater_container->setVisible(TRUE);
			floater_container->showFloater(this, LLTabContainer::START);
		}
		setVisible(TRUE);
	}

	LLFloater::onOpen(key);
}
void FSFloaterNearbyChat::setVisible(BOOL visible)
{
	if (visible)
	{
		removeScreenChat();
	}
	LLFloater::setVisible(visible);
	
	// <Ansariel> Support for chat console
	static LLCachedControl<bool> chatHistoryTornOff(gSavedSettings, "ChatHistoryTornOff");
	if (FSUseNearbyChatConsole)
	{
		FSFloaterIMContainer* floater_container = FSFloaterIMContainer::getInstance();
		if (floater_container && !chatHistoryTornOff && !floater_container->getVisible())
		{
			// In case the nearby chat is docked into the IM floater and the
			// IM floater is invisible, always show the console.
			gConsole->setVisible(TRUE);
		}
		else
		{
			// In case the nearby chat is undocked OR docked and the IM floater
			// is visible, show console only if nearby chat is not visible.
			gConsole->setVisible(!getVisible());
		}
	}
	// </Ansariel> Support for chat console

	BOOL is_minimized = visible && isChatMultiTab()
		? FSFloaterIMContainer::getInstance()->isMinimized()
		: !visible;

	if (!is_minimized && mChatHistory && mInputEditor)
	{
		//only if floater was construced and initialized from xml
		FSFloaterIMContainer* im_container = FSFloaterIMContainer::getInstance();
		
		//prevent stealing focus when opening a background IM tab (EXT-5387, checking focus for EXT-6781)
		// If this is docked, is the selected tab, and the im container has focus, put focus in the input ctrl -KC
		bool is_active = im_container->getActiveFloater() == this && im_container->hasFocus();
		if (!isChatMultiTab() || is_active || hasFocus())
		{
			mInputEditor->setFocus(TRUE);
		}
	}
}
void LLIMFloater::setVisible(BOOL visible)
{
	LLNotificationsUI::LLScreenChannel* channel = static_cast<LLNotificationsUI::LLScreenChannel*>
		(LLNotificationsUI::LLChannelManager::getInstance()->
											findChannelByID(LLUUID(gSavedSettings.getString("NotificationChannelUUID"))));
	LLTransientDockableFloater::setVisible(visible);

	// update notification channel state
	if(channel)
	{
		channel->updateShowToastsState();
		channel->redrawToasts();
	}

	BOOL is_minimized = visible && isChatMultiTab()
		? LLIMFloaterContainer::getInstance()->isMinimized()
		: !visible;

	if (!is_minimized && mChatHistory && mInputEditor)
	{
		//only if floater was construced and initialized from xml
		updateMessages();
		//prevent stealing focus when opening a background IM tab (EXT-5387, checking focus for EXT-6781)
		if (!isChatMultiTab() || hasFocus())
		{
			mInputEditor->setFocus(TRUE);
		}
	}

	if(!visible)
	{
		LLIMChiclet* chiclet = LLChicletBar::getInstance()->getChicletPanel()->findChiclet<LLIMChiclet>(mSessionID);
		if(chiclet)
		{
			chiclet->setToggleState(false);
		}
	}
}
void LLIMFloater::onIMChicletCreated( const LLUUID& session_id )
{

	if (isChatMultiTab())
	{
		LLIMFloaterContainer* im_box = LLIMFloaterContainer::getInstance();
		if (!im_box) return;

		if (LLIMFloater::findInstance(session_id)) return;

		LLIMFloater* new_tab = LLIMFloater::getInstance(session_id);

		im_box->addFloater(new_tab, FALSE, LLTabContainer::END);
	}

}
void FSFloaterNearbyChat::openFloater(const LLSD& key)
{
	// We override this to put nearbychat in the IM floater. -AO
	if (isChatMultiTab())
	{
		// <FS:Ansariel> [FS communication UI]
		//LLIMFloaterContainer* floater_container = LLIMFloaterContainer::getInstance();
		FSFloaterIMContainer* floater_container = FSFloaterIMContainer::getInstance();
		// </FS:Ansariel> [FS communication UI]
		// only show the floater container if we are actually attached -Zi
		if (floater_container && !gSavedSettings.getBOOL("ChatHistoryTornOff"))
		{
			floater_container->showFloater(this, LLTabContainer::START);
		}
		setVisible(TRUE);
		LLFloater::openFloater(key);
	}
}
void LLIMFloater::setDocked(bool docked, bool pop_on_undock)
{
	// update notification channel state
	LLNotificationsUI::LLScreenChannel* channel = static_cast<LLNotificationsUI::LLScreenChannel*>
		(LLNotificationsUI::LLChannelManager::getInstance()->
											findChannelByID(LLUUID(gSavedSettings.getString("NotificationChannelUUID"))));
	
	if(!isChatMultiTab())
	{
		LLTransientDockableFloater::setDocked(docked, pop_on_undock);
	}

	// update notification channel state
	if(channel)
	{
		channel->updateShowToastsState();
		channel->redrawToasts();
	}
}
BOOL LLIMFloater::getVisible()
{
	if(isChatMultiTab())
	{
		LLIMFloaterContainer* im_container = LLIMFloaterContainer::getInstance();
		
		// Treat inactive floater as invisible.
		bool is_active = im_container->getActiveFloater() == this;
	
		//torn off floater is always inactive
		if (!is_active && getHost() != im_container)
		{
			return LLTransientDockableFloater::getVisible();
		}

		// getVisible() returns TRUE when Tabbed IM window is minimized.
		return is_active && !im_container->isMinimized() && im_container->getVisible();
	}
	else
	{
		return LLTransientDockableFloater::getVisible();
	}
}
//static
bool LLIMFloater::toggle(const LLUUID& session_id)
{
	if(!isChatMultiTab())
	{
		LLIMFloater* floater = LLFloaterReg::findTypedInstance<LLIMFloater>("impanel", session_id);
		if (floater && floater->getVisible() && floater->hasFocus())
		{
			// clicking on chiclet to close floater just hides it to maintain existing
			// scroll/text entry state
			floater->setVisible(false);
			return false;
		}
		else if(floater && (!floater->isDocked() || floater->getVisible() && !floater->hasFocus()))
		{
			floater->setVisible(TRUE);
			floater->setFocus(TRUE);
			return true;
		}
	}

	// ensure the list of messages is updated when floater is made visible
	show(session_id);
	return true;
}
//static
LLIMFloater* LLIMFloater::show(const LLUUID& session_id)
{
	closeHiddenIMToasts();

	if (!gIMMgr->hasSession(session_id)) return NULL;

	if(!isChatMultiTab())
	{
		//hide all
		LLFloaterReg::const_instance_list_t& inst_list = LLFloaterReg::getFloaterList("impanel");
		for (LLFloaterReg::const_instance_list_t::const_iterator iter = inst_list.begin();
			 iter != inst_list.end(); ++iter)
		{
			LLIMFloater* floater = dynamic_cast<LLIMFloater*>(*iter);
			if (floater && floater->isDocked())
			{
				floater->setVisible(false);
			}
		}
	}

	bool exist = findInstance(session_id);

	LLIMFloater* floater = getInstance(session_id);
	if (!floater) return NULL;

	if(isChatMultiTab())
	{
		LLIMFloaterContainer* floater_container = LLIMFloaterContainer::getInstance();

		// do not add existed floaters to avoid adding torn off instances
		if (!exist)
		{
			//		LLTabContainer::eInsertionPoint i_pt = user_initiated ? LLTabContainer::RIGHT_OF_CURRENT : LLTabContainer::END;
			// TODO: mantipov: use LLTabContainer::RIGHT_OF_CURRENT if it exists
			LLTabContainer::eInsertionPoint i_pt = LLTabContainer::END;
			
			if (floater_container)
			{
				floater_container->addFloater(floater, TRUE, i_pt);
			}
		}

		floater->openFloater(floater->getKey());
	}
	else
	{
		// Docking may move chat window, hide it before moving, or user will see how window "jumps"
		floater->setVisible(false);

		if (floater->getDockControl() == NULL)
		{
			LLChiclet* chiclet =
					LLChicletBar::getInstance()->getChicletPanel()->findChiclet<LLChiclet>(
							session_id);
			if (chiclet == NULL)
			{
				llerror("Dock chiclet for LLIMFloater doesn't exists", 0);
			}
			else
			{
				LLChicletBar::getInstance()->getChicletPanel()->scrollToChiclet(chiclet);
			}

			floater->setDockControl(new LLDockControl(chiclet, floater, floater->getDockTongue(),
					LLDockControl::BOTTOM));
		}

		// window is positioned, now we can show it.
	}
	floater->setVisible(TRUE);

	return floater;
}
//virtual
BOOL LLIMFloater::postBuild()
{
	const LLUUID& other_party_id = LLIMModel::getInstance()->getOtherParticipantID(mSessionID);
	if (other_party_id.notNull())
	{
		mOtherParticipantUUID = other_party_id;
	}

	mControlPanel->setSessionId(mSessionID);
	mControlPanel->getParent()->setVisible(gSavedSettings.getBOOL("IMShowControlPanel"));

	LLButton* slide_left = getChild<LLButton>("slide_left_btn");
	slide_left->setVisible(mControlPanel->getParent()->getVisible());
	slide_left->setClickedCallback(boost::bind(&LLIMFloater::onSlide, this));

	LLButton* slide_right = getChild<LLButton>("slide_right_btn");
	slide_right->setVisible(!mControlPanel->getParent()->getVisible());
	slide_right->setClickedCallback(boost::bind(&LLIMFloater::onSlide, this));

	mInputEditor = getChild<LLLineEditor>("chat_editor");
	mInputEditor->setMaxTextLength(1023);
	// enable line history support for instant message bar
	mInputEditor->setEnableLineHistory(TRUE);
	// *TODO Establish LineEditor with autoreplace callback
	mInputEditor->setAutoreplaceCallback(boost::bind(&LLAutoReplace::autoreplaceCallback, LLAutoReplace::getInstance(), _1, _2));

	LLFontGL* font = LLViewerChat::getChatFont();
	mInputEditor->setFont(font);	
	
	mInputEditor->setFocusReceivedCallback( boost::bind(onInputEditorFocusReceived, _1, this) );
	mInputEditor->setFocusLostCallback( boost::bind(onInputEditorFocusLost, _1, this) );
	mInputEditor->setKeystrokeCallback( onInputEditorKeystroke, this );
	mInputEditor->setCommitOnFocusLost( FALSE );
	mInputEditor->setRevertOnEsc( FALSE );
	mInputEditor->setReplaceNewlinesWithSpaces( FALSE );
	mInputEditor->setPassDelete( TRUE );

	childSetCommitCallback("chat_editor", onSendMsg, this);
	
	mChatHistory = getChild<LLChatHistory>("chat_history");

	setDocked(true);

	mTypingStart = LLTrans::getString("IM_typing_start_string");

	// Disable input editor if session cannot accept text
	LLIMModel::LLIMSession* im_session =
		LLIMModel::instance().findIMSession(mSessionID);
	if( im_session && !im_session->mTextIMPossible )
	{
		mInputEditor->setEnabled(FALSE);
		mInputEditor->setLabel(LLTrans::getString("IM_unavailable_text_label"));
	}

	if ( im_session && im_session->isP2PSessionType())
	{
		// look up display name for window title
		LLAvatarNameCache::get(im_session->mOtherParticipantID,
							   boost::bind(&LLIMFloater::onAvatarNameCache,
										   this, _1, _2));
	}
	else
	{
		std::string session_name(LLIMModel::instance().getName(mSessionID));
		updateSessionName(session_name, session_name);
	}
	
	//*TODO if session is not initialized yet, add some sort of a warning message like "starting session...blablabla"
	//see LLFloaterIMPanel for how it is done (IB)

	if(isChatMultiTab())
	{
		return LLFloater::postBuild();
	}
	else
	{
		return LLDockableFloater::postBuild();
	}
}
// static
void LLIMFloater::initIMFloater()
{
	// This is called on viewer start up
	// init chat window type before user changed it in preferences
	isChatMultiTab();
}
示例#12
0
void FSFloaterNearbyChat::addMessage(const LLChat& chat,bool archive,const LLSD &args)
{
	LLChat& tmp_chat = const_cast<LLChat&>(chat);
	bool use_plain_text_chat_history = gSavedSettings.getBOOL("PlainTextChatHistory");
	bool show_timestamps_nearby_chat = gSavedSettings.getBOOL("FSShowTimestampsNearbyChat");
	// [FIRE-1641 : SJ]: Option to hide timestamps in nearby chat - add Timestamp when show_timestamps_nearby_chat is TRUE
	if (show_timestamps_nearby_chat)
	{
		if (tmp_chat.mTimeStr.empty())
		{
			tmp_chat.mTimeStr = appendTime();
		}
	}

	// <FS:Ansariel> Optional muted chat history
	tmp_chat.mFromName = chat.mFromName;
	LLSD chat_args = args;
	chat_args["use_plain_text_chat_history"] = use_plain_text_chat_history;
	chat_args["show_time"] = show_timestamps_nearby_chat;
	chat_args["is_local"] = true;
	mChatHistoryMuted->appendMessage(chat, chat_args);
	// </FS:Ansariel> Optional muted chat history
	if (!chat.mMuted)
	{
		// <FS:Ansariel> Optional muted chat history
		//tmp_chat.mFromName = chat.mFromName;
		//LLSD chat_args = args;
		//chat_args["use_plain_text_chat_history"] = use_plain_text_chat_history;
		//chat_args["show_timestamps_nearby_chat"] = show_timestamps_nearby_chat;
		// <(FS:Ansariel> Optional muted chat history
		mChatHistory->appendMessage(chat, chat_args);
	}

	if (archive)
	{
		mMessageArchive.push_back(chat);
		if (mMessageArchive.size() > 200)
		{
			mMessageArchive.erase(mMessageArchive.begin());
		}
	}

	// <FS:Ansariel> Optional muted chat history
	//if (args["do_not_log"].asBoolean()) 
	if (args["do_not_log"].asBoolean() || chat.mMuted) 
	// </FS:Ansariel> Optional muted chat history
	{
		return;
	}
	
	// AO: IF tab mode active, flash our tab
	if (isChatMultiTab())
	{
		LLMultiFloater* hostp = getHost();
        // KC: Don't flash tab on system messages
		if (!isInVisibleChain() && hostp
        && (chat.mSourceType == CHAT_SOURCE_AGENT || chat.mSourceType == CHAT_SOURCE_OBJECT))
		{
			hostp->setFloaterFlashing(this, TRUE);
		}
	}

	if (gSavedPerAccountSettings.getBOOL("LogNearbyChat"))
	{
		std::string from_name = chat.mFromName;

		if (chat.mSourceType == CHAT_SOURCE_AGENT)
		{
			// if the chat is coming from an agent, log the complete name
			LLAvatarName av_name;
			LLAvatarNameCache::get(chat.mFromID, &av_name);

			if (!av_name.isDisplayNameDefault())
			{
				from_name = av_name.getCompleteName();
			}

			// Ansariel: Handle IMs in nearby chat
			// FS:LO FIRE-5230 - Chat Console Improvement: Replacing the "IM" in front of group chat messages with the actual group name
			if (gSavedSettings.getBOOL("FSShowIMInChatHistory"))
			{
				if (chat.mChatType == CHAT_TYPE_IM_GROUP && !chat.mFromNameGroup.empty())
				{
					from_name = "IM: " + chat.mFromNameGroup + from_name;
				}
				else if (chat.mChatType == CHAT_TYPE_IM)
				{
					from_name = "IM: " + from_name;
				}

				// <FS:LO> hack to prevent chat logs from containing lines like "TIMESTANMP IM:: friend is on/offline" (aka the double ":" )
				if (from_name == "IM:")
				{
					from_name = "IM";
				}
				// </FS:LO>
			}
			// FS:LO FIRE-5230 - Chat Console Improvement: Replacing the "IM" in front of group chat messages with the actual group name
		}
		// <FS:LO> Make logging IMs to the chat history file toggleable again
		if (!(chat.mChatType == CHAT_TYPE_IM || chat.mChatType == CHAT_TYPE_IM_GROUP) ||
			(chat.mChatType == CHAT_TYPE_IM && chat.mSourceType == CHAT_SOURCE_OBJECT) ||
			gSavedSettings.getBOOL("FSLogIMInChatHistory"))
		{
			LLLogChat::saveHistory("chat", from_name, chat.mFromID, chat.mText);
		}
	}
}