#pragma once #include "Array.h" #include "Critical.h" #include "ReferenceCounter.h" #include "Text.h" #include "Thread.h" namespace Framework { class ConsoleHandler; enum class Color { BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE, LIGHT_BLACK, LIGHT_RED, LIGHT_GREEN, LIGHT_YELLOW, LIGHT_BLUE, LIGHT_MAGENTA, LIGHT_CYAN, LIGHT_WHITE, }; /** * simple console command interface used for autocompletion and execution of * commands */ class ConsoleCommand : public ReferenceCounter { private: Text name; public: /** * creates a new command * * \param name the name of the command. if the user types this name into * the console at the beginning, the command will be executed */ DLLEXPORT ConsoleCommand(Text name); DLLEXPORT virtual ~ConsoleCommand(); /** * the name of the command * * \return the name */ DLLEXPORT const Text& getName() const; /** * calculates autocomplete posibilities when the user presses the tab * key and wants to use this command * * \param args the current arguments that would be passed to the command * if it was executed * \param appendToLast true if the last argument is not finished * \param possibilities the array to which the * possibilities should be added */ virtual void addAutocompletePossibilities(const RCArray& args, bool appendToLast, RCArray& possibilities) const = 0; /** * executes the command * * \param args the arguments that the user has passed to the command * \return true if the command was executed successfully */ virtual bool execute(RCArray& args) const = 0; }; /** * repesents console content that is sticky, meaning it stays in the console * even if other messages are printed or commands are executed */ class StickyConsoleContent : public virtual ReferenceCounter { private: int length; char* content; Color* color; Color* backgroundColor; ConsoleHandler* zConsoleHandler; public: DLLEXPORT StickyConsoleContent(); DLLEXPORT ~StickyConsoleContent(); /** * the current length of the command. * * \return the length in characters including possible newlines */ DLLEXPORT int getLength() const; /** * sets the current content of the command. all previous colors will be * removed. does not free any memory of the given arguments. * * \param length the new length in characters * \param content the new content */ DLLEXPORT void setContent(int length, const char* content); /** * sets the current content of the command. all previous colors will be * removed. does not free any memory of the given arguments. * * \param length the new length in characters * \param content the new content * \param color the font color of the content */ DLLEXPORT void setContent(int length, const char* content, Color color); /** * sets the current content of the command. all previous colors will be * removed. does not free any memory of the given arguments. * * \param length the new length in characters * \param content the new content * \param color the font color of the content * \param backgroundColor the background color of the content */ DLLEXPORT void setContent(int length, const char* content, Color color, Color backgroundColor); /** * sets the current content of the command. all previous colors will be * removed. does not free any memory of the given arguments. * * \param length the new length in characters * \param content the new content * \param color array of font colors for each character */ DLLEXPORT void setContent( int length, const char* content, Color* color); /** * sets the current content of the command. all previous colors will be * removed. does not free any memory of the given arguments. * * \param length the new length in characters * \param content the new content * \param color array of font colors for each character * \param backgroundColor array of background colors for each character */ DLLEXPORT void setContent(int length, const char* content, Color* color, Color* backgroundColor); /** * replaces a part of the current content. the colors of the current * start position will be used for the new content. does not free any * memory of the given arguments. * * \param start the start position of the replacement * \param length the length of the content that should be replaced * \param newLength the length of the new content that should be * inserted instead of the old content * \param newContent the new content */ DLLEXPORT void repaceContent( int start, int length, int newLength, const char* newContent); /** * replaces a part of the current content. the backgound color of the * current start position will be used for the new content. does not * free any memory of the given arguments. * * \param start the start position of the replacement * \param length the length of the content that should be replaced * \param newLength the length of the new content that should be * inserted instead of the old content * \param newContent the new content * \param color the font color of the new content */ DLLEXPORT void repaceContent(int start, int length, int newLength, const char* newContent, Color color); /** * replaces a part of the current content. does not * free any memory of the given arguments. * * \param start the start position of the replacement * \param length the length of the content that should be replaced * \param newLength the length of the new content that should be * inserted instead of the old content * \param newContent the new content * \param color the font color of the new content * \param backgroundColor the background color of the new content */ DLLEXPORT void repaceContent(int start, int length, int newLength, const char* newContent, Color color, Color backgroundColor); /** * replaces a part of the current content. the backgound color of the * current start position will be used for the new content. does not * free any memory of the given arguments. * * \param start the start position of the replacement * \param length the length of the content that should be replaced * \param newLength the length of the new content that should be * inserted instead of the old content * \param newContent the new content * \param color array the font colorc of the new content for each * character */ DLLEXPORT void repaceContent(int start, int length, int newLength, const char* newContent, Color* color); /** * replaces a part of the current content. does not * free any memory of the given arguments. * * \param start the start position of the replacement * \param length the length of the content that should be replaced * \param newLength the length of the new content that should be * inserted instead of the old content * \param newContent the new content * \param color array the font colorc of the new content for each * character * \param backgroundColor the background color of the new content for * each character */ DLLEXPORT void repaceContent(int start, int length, int newLength, const char* newContent, Color* color, Color* backgroundColor); /** * triggers reprinting of all sticky console content. */ DLLEXPORT void triggerUpdate(); /** * true if the content is a input line where the user can type in * * \param true if the user can edit this content */ DLLEXPORT virtual bool isInput(); public: /** * prints the content to the console * * \return number of lines printed */ DLLEXPORT virtual int print() const; /** * sets the console handler instance where this content will be printed * to. This will automatically be done if the content is added to a * consolehandler. * * \param zConsoleHandler the handler instance without increasing the * reference counter */ DLLEXPORT void setConsoleHandlerZ(ConsoleHandler* zConsoleHandler); protected: /** * called before all sticky console content is reprinted when isInput * is true. restoreCursorPos() must be called after this */ DLLEXPORT virtual void setCursorToBeginning(); /** * reprints all input from the user so that the user can edit the * content again. can only be called after setCursorToBeginning was * called */ DLLEXPORT virtual void restoreCursorPos(); ConsoleHandler* zConsoleHandlerRef() const; public: friend ConsoleHandler; }; /** * displays a progress bar in the console. */ class ConsoleProgressBar : public StickyConsoleContent { private: int progress; int maxProgress; int maxWidth; public: DLLEXPORT ConsoleProgressBar(); /** * sets the max used with of the progress bar in charachters including * the percentage number. * * \param maxWidth the width in characters */ DLLEXPORT void setMaxWidth(int maxWidth); /** * sets the current progress. * * \param progress the progress */ DLLEXPORT void setProgress(int progress); /** * sets the max progress steps needed to reach 100% progress. * * \param maxProgress max progress */ DLLEXPORT void setMaxProgress(int maxProgress); /** * the current progress. * * \return the progress */ DLLEXPORT int getProgress() const; protected: /** * prints the progress bar to the console. * * \return number of lines printed */ DLLEXPORT virtual int print() const override; }; class ConsoleListView; /** * a command input line where the user can type in commands. the user can * type the tab key for autocompletion. * ConsoleListView is used for displaying the autocompletion possibilities. */ class InputLine : public StickyConsoleContent, private Thread { private: int cursorPos; RCArray commands; Critical cs; protected: Framework::Text input; ConsoleListView* suggestions; public: DLLEXPORT InputLine(); DLLEXPORT ~InputLine(); /** * ads a command to the list of possible commands used for * autocompletion and execution. * * \param command the command to add */ DLLEXPORT void addPossibleCommand(ConsoleCommand* command); /** * returns true because the user can edit the content of this line. * * \return true */ DLLEXPORT virtual bool isInput() override; protected: /** * called before all sticky console content is reprinted when isInput * is true. restoreCursorPos() must be called after this */ DLLEXPORT virtual void setCursorToBeginning(); /** * prints the input line to the console. restoreCursorPos must be called * later * * \return number of lines printed */ DLLEXPORT virtual int print() const override; /** * reprints all input from the user so that the user can edit the * content again. can only be called after setCursorToBeginning was * called */ DLLEXPORT virtual void restoreCursorPos() override; /** * writes the next autocomplete step to input or displays a list of * possibilities in suggestions. * */ DLLEXPORT void applyAutocompletion(); /** * executes a given command. * * \param command the command * \return true if the command was executed successfully */ DLLEXPORT bool executeCommand(Text command); /** * splits a given command into its name and arguments. * * \param command the command to split * \param split the array with the name and arguments * \param lastFinished true if the last argument is finished (folowed by * a witespace or ending character) * \return true if the command was split successfully */ DLLEXPORT bool parseCommand( Text command, RCArray& split, bool& lastFinished); private: DLLEXPORT void thread() override; friend ConsoleHandler; }; /** * prints a list of words to the console. the list will be printed ordered * by ascii value. it can be organized in multiple columns. */ class ConsoleListView : public StickyConsoleContent { private: int maxColumns; RCArray items; int maxVisibleLines; int lineOffset; public: DLLEXPORT ConsoleListView(); /** * the number of columns used to display the complete list of words. * * \return the number of columns */ DLLEXPORT int getUsedColumns() const; /** * the number of lines needed to display the complete list of words. * * \return the number of lines */ DLLEXPORT int getNeededLines() const; /** * specifies the maximum amount of lines visible. * * \param maxVisibleLines the amount of lines */ DLLEXPORT void setMaxVisibleLines(int maxVisibleLines); /** * specifies the offset of the first line that should be printed. * * \param lineOffset the index of the first line that is printed */ DLLEXPORT void setLineOffset(int lineOffset); /** * specifies the maximum amount of columns used to display the list of * words. * * \param maxColumns the amount of columns */ DLLEXPORT void setMaxColumns(int maxColumns); /** * adds a word to the list of words. * * \param item the word to add */ DLLEXPORT void addItem(Text item); /** * removes all words from the list. */ DLLEXPORT void clear(); /** * the items in the list view. * * \return items */ DLLEXPORT const RCArray& getItems() const; protected: /** * prints the list of words to the console. * * \return number of lines printed */ DLLEXPORT virtual int print() const override; }; enum class ConsoleContentPosition { /** * before all other sticky console content. */ Top, /** * after all pther sticky console content. */ Bottom, }; class ConsoleHandler : public ReferenceCounter { private: StickyConsoleContent** lines; int* lineCounts; int contentCount; Critical cs; #ifdef WIN32 HANDLE hConsole; #endif public: DLLEXPORT ConsoleHandler(); DLLEXPORT ~ConsoleHandler(); /** * adds a sticky console content to the console at a specified position. * * \param content the new content * \param pos the position of the new content */ DLLEXPORT void addContent( StickyConsoleContent* content, ConsoleContentPosition pos); /** * removes a sticky console content from the list of displayed sticky * console content. * * \param zContent the content to remove without increasing the * reference counter */ DLLEXPORT void removeContent(StickyConsoleContent* zContent); /** * the current with of the console window in characters. * * \return the with in characters */ DLLEXPORT int getWidth() const; /** * the current height of the console window in characters. * * \return the height in characters */ DLLEXPORT int getHeight() const; /** * removes all sticky console content from the list of displayed sticky * console content. */ DLLEXPORT void clear(); /** * reprints all sticky console content that is currently displayed. */ DLLEXPORT void print(); /** * prints something to the console at the position of the first sticky * console content and reprints all sticky console content below the * newly printed content. * * \param str the string to print */ DLLEXPORT void print(Text str); public: friend InputLine; }; } // namespace Framework