From c72b841304a2a24ac0af1b44c6c6c7aff0953860 Mon Sep 17 00:00:00 2001 From: Maurycy Zarzycki Date: Wed, 25 Nov 2020 00:10:10 +0100 Subject: [PATCH] Command list now displays line number and vertical lines delimiting if blocks + displaying a lot of commands now works faster because indenting now happens once instead once for each command --- DROD/CharacterDialogWidget.cpp | 267 ++++++++++++++++++--------------- DROD/CharacterDialogWidget.h | 11 +- DROD/DROD.2019.vcxproj | 2 + DROD/DROD.2019.vcxproj.filters | 6 + FrontEndLib/ListBoxWidget.cpp | 162 +++++++++++++------- FrontEndLib/ListBoxWidget.h | 4 + drod/CommandListBoxWidget.cpp | 108 +++++++++++++ drod/CommandListBoxWidget.h | 45 ++++++ 8 files changed, 428 insertions(+), 177 deletions(-) create mode 100644 drod/CommandListBoxWidget.cpp create mode 100644 drod/CommandListBoxWidget.h diff --git a/DROD/CharacterDialogWidget.cpp b/DROD/CharacterDialogWidget.cpp index 1940526d..96ec1431 100644 --- a/DROD/CharacterDialogWidget.cpp +++ b/DROD/CharacterDialogWidget.cpp @@ -26,6 +26,7 @@ * ***** END LICENSE BLOCK ***** */ #include "CharacterDialogWidget.h" +#include "CommandListBoxWidget.h" #include "DrodBitmapManager.h" #include "DrodFontManager.h" #include "EditRoomScreen.h" @@ -189,6 +190,9 @@ const UINT LIST_LINE_HEIGHT = 22; const SURFACECOLOR PaleRed = {255, 192, 192}; std::map CCharacterDialogWidget::speechLengthCache; +const UINT CCharacterDialogWidget::INDENT_PREFIX_SIZE = 8; +const UINT CCharacterDialogWidget::INDENT_TAB_SIZE = 3; +const UINT CCharacterDialogWidget::INDENT_IF_CONDITION_SIZE = 5; #define NOT_FOUND (UINT(-1)) @@ -493,8 +497,8 @@ CCharacterDialogWidget::CCharacterDialogWidget( AddWidget(new CLabelWidget(0L, X_COMMANDSLABEL, Y_COMMANDSLABEL, CX_COMMANDSLABEL, CY_COMMANDSLABEL, F_Small, g_pTheDB->GetMessageText(MID_Commands))); - this->pCommandsListBox = new CListBoxWidget(TAG_COMMANDSLISTBOX, X_COMMANDS, Y_COMMANDS, - CX_COMMANDS, CY_COMMANDS, false, true, true); + this->pCommandsListBox = new CCommandListBoxWidget(TAG_COMMANDSLISTBOX, X_COMMANDS, Y_COMMANDS, + CX_COMMANDS, CY_COMMANDS); AddWidget(this->pCommandsListBox); //Appearance (character/tile graphic). @@ -2462,7 +2466,7 @@ void CCharacterDialogWidget::OnKeyDown( line!=selectedLines.end(); ++line) { if (*line < pCommands->size()) - wstrCommandsText += toText(*pCommands, (*pCommands)[*line]); + wstrCommandsText += toText(*pCommands, (*pCommands)[*line], *line); } if (!wstrCommandsText.empty()) g_pTheSound->PlaySoundEffect(SEID_POTION); @@ -3228,8 +3232,6 @@ const { WSTRING wstr; - wstr += GetPrettyPrinting(commands, pCommand, 6, 3); //indent the If conditions considerably - //Call language-specific version of method. switch (Language::GetLanguage()) { @@ -4066,158 +4068,176 @@ WSTRING CCharacterDialogWidget::GetDataName(const UINT dwID) const } //***************************************************************************** -WSTRING CCharacterDialogWidget::GetPrettyPrinting( -//Add indenting to clarify the code flow. -// -//Params: - const COMMANDPTR_VECTOR& commands, - CCharacterCommand* pCommand, - const UINT ifIndent, const UINT tabSize) -const +UINT CCharacterDialogWidget::ExtractCommandIndent(const UINT wCommandIndex) const +//Extracts command's indent size from the command listbox text { - ASSERT(pCommand); + WSTRING wstr = this->pCommandsListBox->GetTextAtLine(wCommandIndex); - WSTRING wstr; + UINT i = 0; + for (; i < wstr.size(); ++i) + { + if (!iswspace(wstr.at(i))) + break; + } - //Determine indentation for command. - if (pCommand->command == CCharacterCommand::CC_Label) //labels always have indent 0 - return wstr; + return i; +} + +//***************************************************************************** +void CCharacterDialogWidget::PrettyPrintCommands(const COMMANDPTR_VECTOR &commands) +{ + WSTRING wstr; - UINT wNestDepth = 0, wIndent = 2; //insert past labels + UINT wNestDepth = 0, wIndent = INDENT_PREFIX_SIZE; //insert past labels - bool bIfCondition = false; + UINT index = 0; + bool bLastWasIfCondition = false; for (COMMANDPTR_VECTOR::const_iterator command = commands.begin(); - (*command) != pCommand && command != commands.end(); ++command) + command != commands.end(); ++command, ++index) { - bIfCondition = false; - switch ((*command)->command) + wstr.clear(); + CCharacterCommand *pCommand = *command; + bool bIsIfCondition = false; + bool bUndoOneDepth = false; + bool bIsLabel = false; + switch (pCommand->command) { case CCharacterCommand::CC_If: - bIfCondition = true; + bIsIfCondition = true; ++wNestDepth; //indent inside of if block - break; + bUndoOneDepth = true; + break; case CCharacterCommand::CC_IfElseIf: - bIfCondition = true; - break; + bIsIfCondition = true; + break; case CCharacterCommand::CC_IfEnd: if (wNestDepth) --wNestDepth; else wstr += wszExclamation; //superfluous IfEnd - break; + break; default: break; } - } - - //Unnest If block markers. - switch (pCommand->command) - { - case CCharacterCommand::CC_IfEnd: - case CCharacterCommand::CC_IfElse: - case CCharacterCommand::CC_IfElseIf: - if (wNestDepth) - --wNestDepth; - else - wstr += wszExclamation; //superfluous IfEnd - //no break - case CCharacterCommand::CC_Disappear: - case CCharacterCommand::CC_MoveTo: - case CCharacterCommand::CC_MoveRel: - case CCharacterCommand::CC_EndScript: - case CCharacterCommand::CC_EndScriptOnExit: - case CCharacterCommand::CC_FlushSpeech: - case CCharacterCommand::CC_GoSub: - case CCharacterCommand::CC_GoTo: - case CCharacterCommand::CC_If: - case CCharacterCommand::CC_Imperative: - case CCharacterCommand::CC_Behavior: - case CCharacterCommand::CC_Label: - case CCharacterCommand::CC_LevelEntrance: - case CCharacterCommand::CC_SetMusic: - case CCharacterCommand::CC_Speech: - case CCharacterCommand::CC_TurnIntoMonster: - case CCharacterCommand::CC_PlayerEquipsWeapon: - case CCharacterCommand::CC_SetPlayerStealth: - case CCharacterCommand::CC_SetWaterTraversal: - case CCharacterCommand::CC_StartGlobalScript: - case CCharacterCommand::CC_AnswerOption: - case CCharacterCommand::CC_AmbientSound: - case CCharacterCommand::CC_AmbientSoundAt: - case CCharacterCommand::CC_PlayVideo: - case CCharacterCommand::CC_WorldMapSelect: - case CCharacterCommand::CC_WorldMapMusic: - case CCharacterCommand::CC_WorldMapIcon: - case CCharacterCommand::CC_WorldMapImage: - case CCharacterCommand::CC_ChallengeCompleted: - case CCharacterCommand::CC_Return: - if (bIfCondition) - wstr += wszQuestionMark; //questionable If condition - break; - case CCharacterCommand::CC_ImageOverlay: - if (bIfCondition) - wstr += wszQuestionMark; //questionable If condition - if (pCommand->label.empty()) { - wstr += wszExclamation; - } else { - vector temp; - if (!CImageOverlay::parse(pCommand->label, temp)) + //Unnest If block markers. + switch (pCommand->command) + { + case CCharacterCommand::CC_IfElse: + case CCharacterCommand::CC_IfElseIf: + if (wNestDepth) + bUndoOneDepth = true; + else + wstr += wszExclamation; //superfluous IfEnd + //no break + case CCharacterCommand::CC_IfEnd: + case CCharacterCommand::CC_Disappear: + case CCharacterCommand::CC_MoveTo: + case CCharacterCommand::CC_MoveRel: + case CCharacterCommand::CC_EndScript: + case CCharacterCommand::CC_EndScriptOnExit: + case CCharacterCommand::CC_FlushSpeech: + case CCharacterCommand::CC_GoSub: + case CCharacterCommand::CC_GoTo: + case CCharacterCommand::CC_If: + case CCharacterCommand::CC_Imperative: + case CCharacterCommand::CC_Behavior: + case CCharacterCommand::CC_LevelEntrance: + case CCharacterCommand::CC_SetMusic: + case CCharacterCommand::CC_Speech: + case CCharacterCommand::CC_TurnIntoMonster: + case CCharacterCommand::CC_PlayerEquipsWeapon: + case CCharacterCommand::CC_SetPlayerStealth: + case CCharacterCommand::CC_SetWaterTraversal: + case CCharacterCommand::CC_StartGlobalScript: + case CCharacterCommand::CC_AnswerOption: + case CCharacterCommand::CC_AmbientSound: + case CCharacterCommand::CC_AmbientSoundAt: + case CCharacterCommand::CC_PlayVideo: + case CCharacterCommand::CC_WorldMapSelect: + case CCharacterCommand::CC_WorldMapMusic: + case CCharacterCommand::CC_WorldMapIcon: + case CCharacterCommand::CC_WorldMapImage: + case CCharacterCommand::CC_ChallengeCompleted: + case CCharacterCommand::CC_Return: + if (bLastWasIfCondition) + wstr += wszQuestionMark; //questionable If condition + break; + case CCharacterCommand::CC_Label: + bIsLabel = true; + if (bLastWasIfCondition) + wstr += wszQuestionMark; //questionable If condition + break; + case CCharacterCommand::CC_ImageOverlay: + if (bLastWasIfCondition) + wstr += wszQuestionMark; //questionable If condition + if (pCommand->label.empty()) { wstr += wszExclamation; - } - break; + } + else { + vector temp; + if (!CImageOverlay::parse(pCommand->label, temp)) + wstr += wszExclamation; + } + break; - case CCharacterCommand::CC_VarSet: - if (bIfCondition) - wstr += wszQuestionMark; //questionable If condition - //no break - case CCharacterCommand::CC_WaitForVar: - { - //Verify integrity of hold var refs. - switch (pCommand->y) + case CCharacterCommand::CC_VarSet: + if (bLastWasIfCondition) + wstr += wszQuestionMark; //questionable If condition + //no break + case CCharacterCommand::CC_WaitForVar: { + //Verify integrity of hold var refs. + switch (pCommand->y) + { case ScriptVars::AppendText: case ScriptVars::AssignText: - break; + break; default: if (!pCommand->label.empty()) //an expression is used as an operand { - CEditRoomScreen *pEditRoomScreen = DYN_CAST(CEditRoomScreen*, CScreen*, - g_pTheSM->GetScreen(SCR_EditRoom)); + CEditRoomScreen *pEditRoomScreen = DYN_CAST(CEditRoomScreen *, CScreen *, + g_pTheSM->GetScreen(SCR_EditRoom)); ASSERT(pEditRoomScreen); ASSERT(pEditRoomScreen->pHold); - UINT index=0; + UINT index = 0; if (!CCharacter::IsValidExpression(pCommand->label.c_str(), index, pEditRoomScreen->pHold)) wstr += wszAsterisk; //expression is not valid } - break; + break; + } } + break; + + //Deprecated commands. + case CCharacterCommand::CC_GotoIf: + case CCharacterCommand::CC_WaitForHalph: + case CCharacterCommand::CC_WaitForNotHalph: + case CCharacterCommand::CC_WaitForMonster: + case CCharacterCommand::CC_WaitForNotMonster: + case CCharacterCommand::CC_WaitForCharacter: + case CCharacterCommand::CC_WaitForNotCharacter: + wstr += wszAsterisk; + break; + default: break; } - break; - //Deprecated commands. - case CCharacterCommand::CC_GotoIf: - case CCharacterCommand::CC_WaitForHalph: - case CCharacterCommand::CC_WaitForNotHalph: - case CCharacterCommand::CC_WaitForMonster: - case CCharacterCommand::CC_WaitForNotMonster: - case CCharacterCommand::CC_WaitForCharacter: - case CCharacterCommand::CC_WaitForNotCharacter: - wstr += wszAsterisk; - break; - default: break; - } + UINT wFinalIndent = wNestDepth * INDENT_TAB_SIZE; + if (bIsLabel) + wFinalIndent = 0; - if (bIfCondition) - { - wIndent += ifIndent; - if (bIfCondition) - if (wNestDepth) //...but don't include If indentation in the code block - --wNestDepth; - } + else if (bLastWasIfCondition) + wFinalIndent += INDENT_IF_CONDITION_SIZE; - wstr.insert(wstr.end(), wIndent + wNestDepth*tabSize, W_t(' ')); + else if (bUndoOneDepth) + wFinalIndent -= INDENT_TAB_SIZE; - return wstr; + wstr.insert(wstr.begin(), bIsLabel ? wIndent - 2 : wIndent, W_t(' ')); + wstr.insert(wstr.end(), wFinalIndent, W_t(' ')); + wstr += this->pCommandsListBox->GetTextAtLine(index); + this->pCommandsListBox->SetItemTextAtLine(index, wstr.c_str()); + + bLastWasIfCondition = bIsIfCondition; + } } //***************************************************************************** @@ -4731,6 +4751,9 @@ void CCharacterDialogWidget::PopulateCommandDescriptions( GetCommandDesc(commands, pCommand).c_str()); SetCommandColor(pCommandList, insertedIndex, pCommand->command); } + + PrettyPrintCommands(commands); + if (commands.size()) pCommandList->SelectLine(0); } @@ -7747,7 +7770,8 @@ WSTRING CCharacterDialogWidget::toText( // //Params: const COMMANDPTR_VECTOR& commands, - CCharacterCommand* pCommand) //Command to parse + CCharacterCommand* pCommand, //Command to parse + const UINT wCommandIndex) //Index of the command { #define concatNum(n) wstr += _itoW(n,temp,10) #define concatNumWithComma(n) concatNum(n); wstr += wszComma; @@ -7761,7 +7785,8 @@ WSTRING CCharacterDialogWidget::toText( if (wstrCommandName.empty()) return wstr; - wstr += GetPrettyPrinting(commands, pCommand, 6, 3); + UINT indent = ExtractCommandIndent(wCommandIndex); + wstr.insert(wstr.end(), indent - INDENT_PREFIX_SIZE + 2, W_t(' ')); wstr += wstrCommandName; wstr += wszSpace; diff --git a/DROD/CharacterDialogWidget.h b/DROD/CharacterDialogWidget.h index 4058466f..152a9e05 100644 --- a/DROD/CharacterDialogWidget.h +++ b/DROD/CharacterDialogWidget.h @@ -79,6 +79,10 @@ friend class CRenameDialogWidget; bool RenameCharacter(); bool RenameVar(); + static const UINT INDENT_PREFIX_SIZE; + static const UINT INDENT_TAB_SIZE; + static const UINT INDENT_IF_CONDITION_SIZE; + private: void AddCharacterDialog(); void AddCommandDialog(); @@ -108,9 +112,8 @@ friend class CRenameDialogWidget; const WCHAR* pText) const; HoldCharacter* GetCustomCharacter(); WSTRING GetDataName(const UINT dwID) const; - WSTRING GetPrettyPrinting(const COMMANDPTR_VECTOR& commands, - CCharacterCommand* pCommand, - const UINT ifIndent, const UINT tabSize) const; + UINT ExtractCommandIndent(const UINT wCommandIndex) const; + void PrettyPrintCommands(const COMMANDPTR_VECTOR &commands); WSTRING GetEntranceName(CEditRoomScreen *pEditRoomScreen, UINT entranceID) const; void AppendGotoDestination(WSTRING& wstr, const COMMANDPTR_VECTOR& commands, const CCharacterCommand& pCommand) const; @@ -168,7 +171,7 @@ friend class CRenameDialogWidget; //For text editing of script commands. CCharacterCommand* fromText(WSTRING text); - WSTRING toText(const COMMANDPTR_VECTOR& commands, CCharacterCommand* pCommand); + WSTRING toText(const COMMANDPTR_VECTOR& commands, CCharacterCommand* pCommand, const UINT wCommandIndex); CListBoxWidget *pGraphicListBox, *pPlayerGraphicListBox, *pAddCommandGraphicListBox; COptionButtonWidget *pIsVisibleButton; diff --git a/DROD/DROD.2019.vcxproj b/DROD/DROD.2019.vcxproj index a1f39248..ba7f321b 100644 --- a/DROD/DROD.2019.vcxproj +++ b/DROD/DROD.2019.vcxproj @@ -622,6 +622,7 @@ + @@ -709,6 +710,7 @@ + diff --git a/DROD/DROD.2019.vcxproj.filters b/DROD/DROD.2019.vcxproj.filters index 0513020e..016ce07c 100644 --- a/DROD/DROD.2019.vcxproj.filters +++ b/DROD/DROD.2019.vcxproj.filters @@ -256,6 +256,9 @@ General + + Widgets + @@ -525,6 +528,9 @@ General + + Widgets + diff --git a/FrontEndLib/ListBoxWidget.cpp b/FrontEndLib/ListBoxWidget.cpp index dffdc8d2..c101f107 100644 --- a/FrontEndLib/ListBoxWidget.cpp +++ b/FrontEndLib/ListBoxWidget.cpp @@ -38,6 +38,17 @@ using namespace std; WSTRING CListBoxWidget::wstrFilterWord; + +#ifdef RUSSIAN_BUILD +const int TEXT_DRAW_Y_OFFSET = -1; //Because this particular font is a tiny bit too far down. +#else +const int TEXT_DRAW_Y_OFFSET = -5; //Because this particular font is always too far down. +#endif + +const UINT ITEM_LEFT_PADDING = 2; + + + // //Public methods. // @@ -893,14 +904,6 @@ void CListBoxWidget::Paint( //this widget can't be offset. ASSERT(!IsScrollOffset()); - static const UINT CX_ITEM_INDENT = 2; - -#ifdef RUSSIAN_BUILD - static const int DY_TEXT = -1; //Because this particular font is a tiny bit too far down. -#else - static const int DY_TEXT = -5; //Because this particular font is always too far down. -#endif - //Draw inset area where text appears. SDL_Surface *pDestSurface = GetDestSurface(); DrawInset(this->x, this->y, this->w, this->h, this->images[0], @@ -917,64 +920,34 @@ void CListBoxWidget::Paint( //Draw item text. const UINT wStopLineNo = this->wTopLineNo + this->wDisplayLineCount; - const int xDraw = this->x + CX_INSET_BORDER + CX_ITEM_INDENT; - int yDraw = this->ItemsRect.y = this->y + CY_INSET_BORDER; - const UINT cxDraw = this->w - (CX_INSET_BORDER * 2) - CX_ITEM_INDENT - - (bDrawScrollBar * CX_UP); for (UINT wLineNo = this->wTopLineNo; wLineNo < wStopLineNo && iListItem != items.end(); ++wLineNo, ++iListItem) { - ASSERT(yDraw < static_cast(this->y + this->h - CY_INSET_BORDER)); + Paint_Line(wLineNo, wLineNo - this->wTopLineNo, **iListItem); + } - //If this is selected item, draw solid rect underneath. - SDL_Rect ItemRect = MAKE_SDL_RECT(xDraw - CX_ITEM_INDENT, yDraw, - cxDraw + CX_ITEM_INDENT, CY_LBOX_ITEM); - if (this->selectedLines.has(wLineNo)) - { - const SURFACECOLOR BackColor = - GetSurfaceColor(pDestSurface, 190, 181, 165); - DrawFilledRect(ItemRect, BackColor, pDestSurface); - } + this->ItemsRect.y = this->y + CY_INSET_BORDER; - //Draw text for one item. - const UINT eDrawFont = this->selectedLines.has(wLineNo) ? - FONTLIB::F_SelectedListBoxItem : FONTLIB::F_ListBoxItem; - SDL_Color origColor = g_pTheFM->GetFontColor(eDrawFont); - if ((*iListItem)->bGrayed) //whether text is shown grayed out - { - g_pTheFM->SetFontColor(eDrawFont, Gray); - } else { - g_pTheFM->SetFontColor(eDrawFont, (*iListItem)->color); - } - //Draw selected line text. - g_pTheFM->DrawTextXY(eDrawFont, (*iListItem)->text.c_str(), pDestSurface, - xDraw, yDraw + DY_TEXT, cxDraw, (int)CY_LBOX_ITEM - DY_TEXT); - g_pTheFM->SetFontColor(eDrawFont, origColor); - - //Draw focus box (cursor). - const bool bCursorOnLine = wLineNo == this->wCursorLine; - if (bCursorOnLine && IsSelected()) - { - const SURFACECOLOR FocusColor = - GetSurfaceColor(pDestSurface, RGB_FOCUS); - DrawRect(ItemRect,FocusColor,pDestSurface); - } - yDraw += CY_LBOX_ITEM; - } + if (this->wstrActiveFilter.size() > 0) + { + int drawX, drawY; + UINT drawWidth, drawHeight; + GetLineDrawCoords(0, drawX, drawY, drawWidth, drawHeight); + + drawX = this->x + 10; + drawY = this->y + TEXT_DRAW_Y_OFFSET + this->h - CY_LBOX_ITEM - 1; - if (this->wstrActiveFilter.size() > 0) { const SURFACECOLOR FilterSeparatorColor = GetSurfaceColor(GetDestSurface(), 102, 102, 102); - const UINT wTextY = this->y + DY_TEXT + this->h - CY_LBOX_ITEM - 1; WSTRING message = this->wstrFilterWord; message += wszColon; message += wszSpace; message += this->wstrActiveFilter; - DrawRow(this->x, wTextY + 3, cxDraw, FilterSeparatorColor, pDestSurface); + DrawRow(this->x, drawY + 3, drawWidth, FilterSeparatorColor, pDestSurface); g_pTheFM->DrawTextXY(FONTLIB::F_ListBoxItem, message.c_str(), pDestSurface, - this->x + 10, wTextY, - cxDraw - 20, (int)CY_LBOX_ITEM - DY_TEXT); + drawX, drawY, + drawWidth - 20, (int)CY_LBOX_ITEM - TEXT_DRAW_Y_OFFSET); } @@ -983,6 +956,65 @@ void CListBoxWidget::Paint( if (bUpdateRect) UpdateRect(); } +//****************************************************************************** +void CListBoxWidget::Paint_Line( + const UINT wListItemNumber, + const UINT wDrawLineNumber, + const LBOX_ITEM &listItem) +{ + SDL_Surface *pDestSurface = GetDestSurface(); + + bool bIsSelected = this->selectedLines.has(wListItemNumber); + + int drawX, drawY; + UINT drawWidth, drawHeight; + GetLineDrawCoords(wDrawLineNumber, drawX, drawY, drawWidth, drawHeight); + + ASSERT(drawY < static_cast(this->y + this->h - CY_INSET_BORDER)); + + //If this is selected item, draw solid rect underneath. + if (bIsSelected) + { + SDL_Rect ItemRect = MAKE_SDL_RECT( + drawX - ITEM_LEFT_PADDING, drawY, + drawWidth + ITEM_LEFT_PADDING, drawHeight + ); + + const SURFACECOLOR BackColor = GetSurfaceColor(pDestSurface, 190, 181, 165); + DrawFilledRect(ItemRect, BackColor, pDestSurface); + } + + const UINT eDrawFont = bIsSelected + ? FONTLIB::F_SelectedListBoxItem + : FONTLIB::F_ListBoxItem; + SDL_Color origColor = g_pTheFM->GetFontColor(eDrawFont); + + //whether text is shown grayed out + if (listItem.bGrayed) + g_pTheFM->SetFontColor(eDrawFont, Gray); + else + g_pTheFM->SetFontColor(eDrawFont, listItem.color); + + //Draw selected line text. + g_pTheFM->DrawTextXY(eDrawFont, listItem.text.c_str(), pDestSurface, + drawX, drawY + TEXT_DRAW_Y_OFFSET, drawWidth, (int)drawHeight - TEXT_DRAW_Y_OFFSET); + g_pTheFM->SetFontColor(eDrawFont, origColor); + + //Draw focus box (cursor). + const bool bCursorOnLine = (wListItemNumber == this->wCursorLine); + if (bCursorOnLine && IsSelected()) + { + SDL_Rect ItemRect = MAKE_SDL_RECT( + drawX - ITEM_LEFT_PADDING, drawY, + drawWidth + ITEM_LEFT_PADDING, drawHeight + ); + + const SURFACECOLOR FocusColor = + GetSurfaceColor(pDestSurface, RGB_FOCUS); + DrawRect(ItemRect, FocusColor, pDestSurface); + } +} + //****************************************************************************** void CListBoxWidget::SetItemColor(const UINT dwKey, const SDL_Color& color) { @@ -1026,6 +1058,18 @@ void CListBoxWidget::SetItemText(const UINT dwKey, const WCHAR *pwczSetText) } } +//****************************************************************************** +void CListBoxWidget::SetItemTextAtLine(const UINT index, const WCHAR *pwczSetText) +//Updates the text description of the item at the specific line. +{ + ASSERT(pwczSetText); + + if (index >= this->filteredItems.size()) + return; + + this->filteredItems[index]->text = pwczSetText; +} + //****************************************************************************** void CListBoxWidget::SetRearrangeable(const UINT dwKey, bool val) { @@ -1251,6 +1295,17 @@ void CListBoxWidget::UpdateFilter(WSTRING wstrFilter) } +//****************************************************************************** +void CListBoxWidget::GetLineDrawCoords(const UINT wLineNumber, int &drawX, int &drawY, UINT &drawWidth, UINT &drawHeight) +{ + const bool bDrawScrollBar = (this->filteredItems.size() > this->wDisplayLineCount); + + drawX = this->x + CX_INSET_BORDER + ITEM_LEFT_PADDING; + drawY = this->y + CY_INSET_BORDER + wLineNumber * CY_LBOX_ITEM; + drawWidth = this->w - (CX_INSET_BORDER * 2) - ITEM_LEFT_PADDING - (bDrawScrollBar * CX_UP); + drawHeight = CY_LBOX_ITEM; +} + //****************************************************************************** void CListBoxWidget::HandleMouseDown( //Handles a mouse down event. @@ -1346,6 +1401,9 @@ void CListBoxWidget::HandleDrag( } else { this->wCursorLine = this->wDraggingLineNo; } + + UpdateFilter(WSTRING()); + RequestPaint(); } //****************************************************************************** diff --git a/FrontEndLib/ListBoxWidget.h b/FrontEndLib/ListBoxWidget.h index d186a789..632a6df6 100644 --- a/FrontEndLib/ListBoxWidget.h +++ b/FrontEndLib/ListBoxWidget.h @@ -125,6 +125,7 @@ class CListBoxWidget : public CScrollableWidget void SetItemColor(const UINT dwKey, const SDL_Color& color); void SetItemColorAtLine(const UINT index, const SDL_Color& color); void SetItemText(const UINT dwKey, const WCHAR *pwczSetText); + void SetItemTextAtLine(const UINT index, const WCHAR *pwczSetText); void SetRearrangeable(bool val) { this->bRearrangable = val; } void SetRearrangeable(const UINT dwKey, bool val); void SetSelectedItemText(const WCHAR *pwczSetText); @@ -150,6 +151,9 @@ class CListBoxWidget : public CScrollableWidget virtual void ScrollUpOneLine(const UINT wLines=1); virtual void ScrollUpOnePage(); + void GetLineDrawCoords(const UINT wLineNumber, int &drawX, int &drawY, UINT &drawWidth, UINT &drawHeight); + virtual void Paint_Line(const UINT wListItemNumber, const UINT wDrawLineNumber, const LBOX_ITEM &listItem); + vector Items; UINT wTopLineNo; //of view area UINT wDisplayLineCount; //lines in view area diff --git a/drod/CommandListBoxWidget.cpp b/drod/CommandListBoxWidget.cpp new file mode 100644 index 00000000..3b22cfe6 --- /dev/null +++ b/drod/CommandListBoxWidget.cpp @@ -0,0 +1,108 @@ +// $Id$ + +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Deadly Rooms of Death. + * + * The Initial Developer of the Original Code is + * Caravel Software. + * Portions created by the Initial Developer are Copyright (C) 2002, 2005 + * Caravel Software. All Rights Reserved. + * + * Contributor(s): Mike Rimer (mrimer) + * + * ***** END LICENSE BLOCK ***** */ + +#include "CommandListBoxWidget.h" +#include "DrodFontManager.h" + +// +//Public methods. +// + +//****************************************************************************** +CCommandListBoxWidget::CCommandListBoxWidget( + //Constructor. + // + //Params: + const UINT dwSetTagNo, //(in) Required params for CWidget + const int nSetX, const int nSetY, // constructor. + const UINT wSetW, const UINT wSetH) + : CListBoxWidget(dwSetTagNo, nSetX, nSetY, wSetW, wSetH, false, true, true) +{} + +UINT CountIndent(const WSTRING &wstr) { + UINT count = 0; + for (UINT i = 0; i < wstr.size(); ++i) + { + if (wstr.at(i) == wszSpace[0]) + count++; + else + break; + } + + return count; +} + +//****************************************************************************** +void CCommandListBoxWidget::Paint_Line(const UINT wListItemNumber, const UINT wDrawLineNumber, const LBOX_ITEM &listItem) +{ + CListBoxWidget::Paint_Line(wListItemNumber, wDrawLineNumber, listItem); + + int drawX, drawY; + UINT drawWidth, drawHeight; + GetLineDrawCoords(wDrawLineNumber, drawX, drawY, drawWidth, drawHeight); + + const UINT indent = CountIndent(listItem.text); + static const UINT LINE_LEFT_PADDING = 5; + static const UINT INDENT_WIDTH = 3; + static const UINT SPACE_WIDTH = g_pTheDFM->GetSpaceWidth(FONTLIB::F_ListBoxItem); + static const SURFACECOLOR LINE_COLOR = { 170, 170, 170 }; + + SDL_Surface *pDestSurface = GetDestSurface(); + + for (UINT i = 8; i < indent; i += 3) + { + // Hack to avoid drawing line in the if's condition which is indented like this: + // If ... <- Default indent is 8 + // Wait for clean room <- If conditions have indent of 5 + // Speech "",Normal,Self,0,. <- If body has indent of 3 + // If End + if (i + 5 == indent) + break; + + DrawCol(drawX + i * SPACE_WIDTH + LINE_LEFT_PADDING, drawY, drawHeight, LINE_COLOR, pDestSurface); + } + + { // Draw line number + static const UINT LINE_NUMBER_FONT = FONTLIB::F_Small; + static const UINT LINE_NUMBER_WIDTH = 35; + static const SDL_Color LINE_NUMBER_COLOR = { 120, 120, 120, 0 }; + + WCHAR buffer[12]; + WSTRING wstrLineNumber; + wstrLineNumber += _itoW(wListItemNumber, buffer, 10, 12); + + SDL_Color oldColor = g_pTheFM->GetFontColor(LINE_NUMBER_FONT); + UINT wTextWidth; + g_pTheFM->SetFontColor(LINE_NUMBER_FONT, LINE_NUMBER_COLOR); + g_pTheFM->GetTextWidth(LINE_NUMBER_FONT, wstrLineNumber.c_str(), wTextWidth); + g_pTheFM->DrawTextXY( + LINE_NUMBER_FONT, wstrLineNumber.c_str(), pDestSurface, + drawX + LINE_NUMBER_WIDTH - wTextWidth, drawY - 5, + wTextWidth, CY_LBOX_ITEM + ); + g_pTheFM->SetFontColor(LINE_NUMBER_FONT, oldColor); + } +} diff --git a/drod/CommandListBoxWidget.h b/drod/CommandListBoxWidget.h new file mode 100644 index 00000000..60bfe902 --- /dev/null +++ b/drod/CommandListBoxWidget.h @@ -0,0 +1,45 @@ +// $Id$ + +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Deadly Rooms of Death. + * + * The Initial Developer of the Original Code is + * Caravel Software. + * Portions created by the Initial Developer are Copyright (C) 2002, 2005 + * Caravel Software. All Rights Reserved. + * + * Contributor(s): Mike Rimer (mrimer) + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef _COMMANDLISTBOXWIDGET_H +#define _COMMANDLISTBOXWIDGET_H + + +#include + +//****************************************************************************** +class CCommandListBoxWidget : public CListBoxWidget +{ +public: + CCommandListBoxWidget(const UINT dwSetTagNo, const int nSetX, const int nSetY, + const UINT wSetW, const UINT wSetH); + virtual ~CCommandListBoxWidget() { Clear(); } + +protected: + virtual void Paint_Line(const UINT wListItemNumber, const UINT wDrawLineNumber, const LBOX_ITEM &listItem); +}; + +#endif //#ifndef _COMMANDLISTBOXWIDGET_H