123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350 |
- #include "pch.h"
- #include "trekctrls.h"
- #include "trekmdl.h"
- #include "badwords.h"
- //////////////////////////////////////////////////////////////////////////////
- //
- // ChatListItem
- //
- //////////////////////////////////////////////////////////////////////////////
- class ChatListItem : public ListItem
- {
- private:
- long m_lData;
- ChatInfo* m_pchatInfo;
- TVector<ZString> m_vMsgLines;
- WinPoint m_ptLineSize;
-
- public:
- ChatListItem(ChatInfo* pchatInfo, const WinPoint& ptLineSize) :
- m_lData((long)pchatInfo),
- m_pchatInfo(pchatInfo),
- m_ptLineSize(ptLineSize)
- {
- ZString strMsg = CensorBadWords (m_pchatInfo->GetMessage());
- IEngineFont* pfont = pchatInfo->IsFromLeader() ? TrekResources::SmallBoldFont() : TrekResources::SmallFont();
- int nStrLenLeft = strMsg.GetLength();
- int nStrLenLine;
- while ((nStrLenLine = pfont->GetMaxTextLength(strMsg, ptLineSize.X(), true))
- < nStrLenLeft)
- {
- int nStrLenWordBreak = nStrLenLine;
- while (nStrLenWordBreak > 2 && strMsg[nStrLenWordBreak] != ' ' && strMsg[nStrLenWordBreak-1] != ' ')
- nStrLenWordBreak--;
- if (nStrLenWordBreak != 2)
- nStrLenLine = nStrLenWordBreak;
-
- if (nStrLenLine <= 2)
- {
- // put a blank line without the character
- nStrLenLine = 3;
- m_vMsgLines.PushEnd("");
- }
- else
- {
- m_vMsgLines.PushEnd(strMsg.Left(nStrLenLine));
- }
- strMsg = " " + strMsg.RightOf(nStrLenLine);
- nStrLenLeft -= nStrLenLine - 2;
- ZAssert(strMsg.GetLength() == nStrLenLeft);
- }
- m_vMsgLines.PushEnd(strMsg);
- }
- ~ChatListItem()
- {
- // debugf("~ChatListItem\n");
- }
- short GetItemHeight()
- {
- return m_vMsgLines.GetCount();
- }
- long GetItemData()
- {
- return m_lData;
- };
- bool Update()
- {
- return true;
- }
- void SetSortOrder(long lSortOrder)
- {
- }
-
- bool SetFilter(long lFilter)
- {
- return true;
- }
- void DrawItem(Surface* pSurface, const WinRect& rect, bool fSelected, int iFirstSlot)
- {
- IEngineFont* pfont = m_pchatInfo->IsFromLeader() ? TrekResources::SmallBoldFont() : TrekResources::SmallFont();
- WinPoint pt(rect.Min() + WinPoint(3,3));
- for (
- int i = iFirstSlot;
- i < m_vMsgLines.GetCount() && pt.Y() < rect.YMax();
- i++
- ) {
- pSurface->DrawString(pfont, m_pchatInfo->GetColor(), pt, m_vMsgLines[i]);
- pt += WinPoint(0, m_ptLineSize.Y());
- }
- }
- };
- //////////////////////////////////////////////////////////////////////////////
- //
- // ChatListPaneImpl
- //
- //////////////////////////////////////////////////////////////////////////////
- class ChatListPaneImpl : public ChatListPane,
- public EventTargetContainer<ChatListPaneImpl>,
- public TrekClientEventSink,
- public IKeyboardInput
- {
- private:
- TRef<ListPaneOld> m_pListPane;
- WinPoint m_ptItemSize;
- TList<ChatTarget> m_listChannels;
- TRef<IKeyboardInput> m_keyboardDelegate;
- TRef<IEventTarget> m_targetAutoscrollOn;
- bool m_bAutoscroll;
- bool m_bPlayerChatsOnly;
- bool m_bIgnoreScrollingEvents;
- public:
- ChatListPaneImpl(const WinPoint& ptSize):
- m_ptItemSize(ptSize.X(), 12), m_bAutoscroll(true), m_bIgnoreScrollingEvents(false)
- {
- m_bPlayerChatsOnly = true;
- m_pListPane = ListPaneOld::Create(ptSize, 12, true, NULL),
- InsertAtBottom(m_pListPane);
- AddEventTarget(OnListSelect, m_pListPane->GetEventSource());
- AddEventTarget(OnScroll, m_pListPane->GetScrollEvent());
- UpdateContents();
- m_keyboardDelegate = IKeyboardInput::CreateDelegate(this);
- GetWindow()->AddKeyboardInputFilter(m_keyboardDelegate);
- }
- ~ChatListPaneImpl()
- {
- GetWindow()->RemoveKeyboardInputFilter(m_keyboardDelegate);
- if (m_targetAutoscrollOn)
- m_targetAutoscrollOn->Disconnect();
- }
- void AutoscrollOff()
- {
- m_bAutoscroll = false;
- // set/reset a timer to turn it back on after 10 seconds
- if (m_targetAutoscrollOn)
- m_targetAutoscrollOn->Disconnect();
- m_targetAutoscrollOn =
- new TEventTarget<ChatListPaneImpl>(this, OnAutoscrollTimeout, GetWindow(), 10);
- }
- void AutoscrollOn()
- {
- m_bAutoscroll = true;
- if (m_targetAutoscrollOn)
- m_targetAutoscrollOn->Disconnect();
- }
- bool OnAutoscrollTimeout()
- {
- m_pListPane->ScrollBottom();
- AutoscrollOn();
- return false;
- }
- bool OnListSelect(int nSel)
- {
- return true;
- }
- void OnClearChat()
- {
- m_pListPane->RemoveAll();
- }
- void OnChatMessageChange()
- {
- // save some info about the current state of the chat list
- int countOld = m_pListPane->GetCountItems();
- int posOld = m_pListPane->GetScrollPosition();
- UpdateContents();
- // if the number of items did not change, assume we were just doing
- // something like marking a player as dead so keep the current scroll
- // position.
- if (countOld == m_pListPane->GetCountItems())
- m_pListPane->SetScrollPosition(posOld);
- }
- bool ChatIsNonCriticalMessage(ChatInfo * pchatinfo)
- {
- return !pchatinfo->IsFromPlayer()
- && !pchatinfo->IsFromObjectModel()
- && pchatinfo->GetChatTarget() != CHAT_INDIVIDUAL_NOFILTER
- && m_bPlayerChatsOnly;
- }
- void OnDeleteChatMessage(ChatInfo* pchatInfo)
- {
- m_bIgnoreScrollingEvents = true;
- m_pListPane->RemoveItemByData((long)pchatInfo);
- m_bIgnoreScrollingEvents = false;
- }
- void OnNewChatMessage()
- {
- ChatInfo * pchatinfo = &(trekClient.m_chatList.last()->data());
- if (ChatIsNonCriticalMessage(pchatinfo))
- {
- trekClient.PostText(false, CensorBadWords (pchatinfo->GetMessage()));
- }
- else
- {
- AddChatItem(pchatinfo);
- }
- }
- void PageUp()
- {
- m_pListPane->ScrollPageUp();
- AutoscrollOff();
- }
- void PageDown()
- {
- m_pListPane->ScrollPageDown();
-
- // if we are at the bottom of the list, turn auto-scroll back on
- if (m_pListPane->IsItemVisibleByIdx(m_pListPane->GetCountItems() - 1))
- AutoscrollOn();
- else
- AutoscrollOff();
- }
- bool OnScroll()
- {
- if (!m_bIgnoreScrollingEvents)
- {
- // if we are at the bottom of the list, turn auto-scroll back on
- if (m_pListPane->IsItemVisibleByIdx(m_pListPane->GetCountItems() - 1))
- AutoscrollOn();
- else
- AutoscrollOff();
- }
- return true;
- }
- void UpdateContents()
- {
- m_pListPane->RemoveAll();
- for (ChatLink* link = trekClient.m_chatList.first(); link; link = link->next())
- {
- AddChatItem(&(link->data()));
- }
- m_pListPane->ScrollBottom();
- AutoscrollOn();
- }
- bool ChatPassesFilter(ChatInfo* pchatInfo)
- {
- if (ChatIsNonCriticalMessage(pchatInfo))
- {
- return false;
- }
- if (m_listChannels.IsEmpty())
- {
- return true;
- }
- else
- {
- TList<ChatTarget>::Iterator iter(m_listChannels);
-
- while (!iter.End())
- {
- if (iter.Value() == pchatInfo->GetChatTarget())
- return true;
- iter.Next();
- }
- }
- return false;
- }
- void AddChatItem(ChatInfo* pchatInfo)
- {
- if (ChatPassesFilter(pchatInfo))
- {
- m_bIgnoreScrollingEvents = true;
- int idx = m_pListPane->AppendItem(new ChatListItem(pchatInfo, m_ptItemSize));
-
- if (m_bAutoscroll)
- {
- m_pListPane->SetSelItemByIdx(idx);
- m_pListPane->ScrollBottom();
- }
- m_bIgnoreScrollingEvents = false;
- }
- }
- void AddChannel(ChatTarget channel)
- {
- m_listChannels.PushEnd(channel);
- UpdateContents();
- }
- void RemoveChannel(ChatTarget channel)
- {
- m_listChannels.Remove(channel);
- UpdateContents();
- }
- void ResetChannels()
- {
- m_listChannels.SetEmpty();
- UpdateContents();
- }
- void UpdateLayout()
- {
- DefaultUpdateLayout();
- }
- };
- TRef<IObject> ChatListPaneFactory::Apply(ObjectStack& stack)
- {
- TRef<PointValue> ppointSize; CastTo(ppointSize, stack.Pop());
- return (Pane*)new ChatListPaneImpl(
- WinPoint(
- (int)ppointSize->GetValue().X(),
- (int)ppointSize->GetValue().Y()
- )
- );
- }
|