123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588 |
- /* GCSx
- ** DIALOG.H
- **
- ** Dialog boxes, and basic dialog elements
- */
- /*****************************************************************************
- ** Copyright (C) 2003-2006 Janson
- **
- ** This program is free software; you can redistribute it and/or modify
- ** it under the terms of the GNU General Public License as published by
- ** the Free Software Foundation; either version 2 of the License, or
- ** (at your option) any later version.
- **
- ** This program is distributed in the hope that it will be useful,
- ** but WITHOUT ANY WARRANTY; without even the implied warranty of
- ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- ** GNU General Public License for more details.
- **
- ** You should have received a copy of the GNU General Public License
- ** along with this program; if not, write to the Free Software
- ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
- *****************************************************************************/
- #ifndef __GCSx_DIALOG_H_
- #define __GCSx_DIALOG_H_
- // A dialog Window collects widget Windows and is itself the client area
- // of a FrameWindow.
- class Widget;
- class Dialog : public WindowCollection, public Window {
- protected:
- std::string title;
- int lastButtonId;
- int open;
- int openModal;
- int nextTabId;
- class FrameWindow* myFrame;
- int autoApply; // If widgets apply on every setting change
- int noAutoClose; // Prevent ESC key and Enter key
- int inSiblingModify; // Are we in the middle of siblingModified()?
- int hasTitlebar;
- int isToolPanel;
-
- // For arrangeRow() and makePretty()
- int lastWidgetArranged;
- int nextWidgetY;
-
- // Apply/save settings
- // Don't call this directly- use doAction()
- void applySettings();
- // Load settings
- // Called from runModal and runWindowed
- void loadSettings();
-
- // Dialog sizing constants
- enum {
- // Separation between elements
- GUI_DIALOG_SEPHEIGHT = 5,
- GUI_DIALOG_SEPWIDTH = 2, // Used by arrangeRow() only
- // Separation before button row
- GUI_DIALOG_BUTTONSEPHEIGHT = 10,
- // Separation between multiple checks or radios
- GUI_DIALOG_CHECKSEPHEIGHT = 0, // Used by makePretty() only
- // Separation between two columns
- GUI_DIALOG_GUTTERWIDTH = 5, // Used by makePretty() only
- // Margins on edges- normal dialog
- GUI_DIALOG_TOPMARGIN = 5,
- GUI_DIALOG_BOTTOMMARGIN = 5,
- GUI_DIALOG_LEFTMARGIN = 5,
- GUI_DIALOG_RIGHTMARGIN = 5,
- // Margins on edges- tool panel dialog
- GUI_PANEL_TOPMARGIN = 2,
- GUI_PANEL_BOTTOMMARGIN = 2,
- GUI_PANEL_LEFTMARGIN = 3,
- GUI_PANEL_RIGHTMARGIN = 1,
- // Max number of columns/rows we support
- GUI_DIALOG_NUMCOL = 10, // Used by makePretty() only
- GUI_DIALOG_NUMROW = 20, // Used by makePretty() only
- };
- // Opens this dialog, but without assigning it as a child window anywhere
- void runAsPanel();
- public:
- enum ButtonAction {
- // "DEFAULT" means "whatever the button is set to do" and should only be used
- // as a return value for verifyEntry(), not as an actual button action
- BUTTON_DEFAULT,
- BUTTON_NOTHING,
- BUTTON_OK,
- BUTTON_APPLY,
- BUTTON_CANCEL,
- BUTTON_LASTACT = BUTTON_CANCEL,
- };
- enum DialogAction {
- DIALOGACTION_CHECK,
- DIALOGACTION_UNCHECK,
- DIALOGACTION_RADIO,
- DIALOGACTION_TEXTCHANGE,
- };
-
- Dialog(const std::string& dTitle, int dAutoApply = 0, int dHasTitlebar = 1, int toolPanel = 0);
- virtual ~Dialog();
- void setTitle(const std::string& newTitle);
- #ifndef NDEBUG
- const char* debugDump() const;
- #endif
-
- virtual int event(int hasFocus, const SDL_Event* event);
- void display(SDL_Surface* destSurface, Rect& toDisplay, const Rect& clipArea, int xOffset, int yOffset);
- void resolutionChange(int fromW, int fromH, int fromBpp, int toW, int toH, int toBpp);
- const char* tooltip(int xPos, int yPos) const;
- WindowType windowType() const;
- WindowSort windowSort() const;
- CommandSupport supportsCommand(int code) const;
-
- // For outside code to find widgets to edit properties, etc.
- // If it finds a container widget, it returns the inner widget
- // which = 1 for second widget, etc. May not be in original order added!
- Widget* findWidget(int id, int which = 0);
-
- // By default, dialogs do NOT want to be deleted, most are settings dialogs
- // you set up once and bring back over and over
- virtual int wantsToBeDeleted() const;
-
- // Handles calling verifyEntry(0), etc.
- // You shouldn't call this directly, it's used by frame windows only
- int attemptClose();
-
- // Validates that all current entry is OK and/or runs custom code for a
- // button, return an action. buttonId of 0 for closing
- // the dialog via [X]. The default code for this merely runs entryValid() on
- // all widgets if buttonType is OK or APPLY.
- virtual ButtonAction verifyEntry(int buttonId, ButtonAction buttonType);
-
- // Remove all widgets; allows you to readd widgets
- // Must be closed when called!
- void clearWidgets();
- // Add a widget to this dialog; if fails, widget is not owned by us
- // If successful, we will handle deleting widget unless it's not set as wantsToBeDeleted()
- // Typically called by widget from addTo()
- void addWidget(Widget* newWidget);
-
- // Rearrange size of dialog and all new widgets automatically
- // Call this after each chunk or when all done
- // If you wish to arrange as a table, increase maxColumns
- // Puts static text in column 1 right-aligned, all other widgets in columns 2 onwards
- // If you simply want all widgets to flow into all columns, set pureFlow to true
- // If you want all static text right-aligned, set staticRight to true
- // (this only matters for pureFlow mode)
- // ALWAYS centers a final row of buttons, in all circumstances
- void makePretty(int maxColumns = 2, int vertCenter = 1, int pureFlow = 0, int staticRight = 0);
- // All widgets added since last call to this are arranged in a single row
- // Call this after each row
- void arrangeRow(int vertCenter = 1, int leftColumnSize = -1, int staticRight = 0);
-
- // Creates a FrameWindow, run this dialog, return the button code pressed
- // Returns 0 if ESC/[X] and no CANCEL button
- int runModal(int xPos = -1, int yPos = -1);
-
- // Creates a FrameWindow, add dialog to desktop, return with dialog still open
- void runWindowed(int xPos = -1, int yPos = -1);
-
- // Actually handles an action- call with a constant other than DEFAULT
- // Returns true if this window was closed, possibly deleted
- int doAction(ButtonAction buttonType);
- // First control- used on dialog init
- virtual void firstControl();
- // Next and previous control, optionally limited to controls with a given ID
- // Can do next from a control other than current if desired
- // Returns true if control was switched.
- int nextControl(int id = -1, const Widget* from = NULL);
- int prevControl(int id = -1);
-
- // Select first button with given action; returns true if found
- int buttonControl(ButtonAction action);
- void currentFocusDoAction();
-
- // Select control based on hotkey AND ACTIVATE; returns true if found
- int hotkeyControl(char keypress);
-
- // Called whenever a child is modified, propogates to all other controls
- // (via siblingModified())
- // If this causes another widget to modify, it will NOT propogate
- // A button press doesn't call this
- // focus or other purely-visual or cursor changes don't call this
- // load() shouldn't call this
- virtual void childModified(Window* modified);
- };
- class Widget : public Window {
- protected:
- std::string label;
- int underline;
- int disabled;
- int haveFocus;
- int tabId;
- char shortcut;
- const char* tip;
-
- // Internal ID, internal use includes grouping radio buttons and pass to
- // verifyEntry and afterChange in Dialog class. Internal ID should be >= 0
- int id;
-
- // (where we store the setting when the dialog closes)
- void* setting;
-
- // sets label, underline
- void setLabel(const std::string& newLabel);
-
- public:
- Widget(int wId, const std::string& wLabel, void* wSetting);
- virtual ~Widget();
- // (mostly a shortcut)
- Dialog* myParent();
- void setToolTip(const char* wTip);
- virtual const char* tooltip(int xPos, int yPos) const;
- // Return true if entry is valid to close
- // False if entry is invalid and should be selected and modified (can pop up an error)
- virtual int entryValid() const;
-
- // Used by findWidget to make sure it's returning the actual widget
- // and not a container widget like WidgetScroll
- virtual Widget* returnSelf();
-
- // Changes setting storage (doesn't affect current value if open!)
- void changeStorage(void* newSetting);
-
- // Add to a dialog; if fails, widget is not owned by dialog
- // If successful, dialog will handle deleting widget unless it's not set as wantsToBeDeleted()
- virtual void addTo(Dialog* dialog);
-
- // Set or query tab id
- virtual int stateTabId() const;
- virtual int stateTabId(int wTabId);
- // Selected- perform action
- virtual void doAction();
- // Tabbed to- perform action
- virtual void tabAction();
-
- #ifndef NDEBUG
- const char* debugDump() const;
- #endif
-
- virtual void disable();
- virtual void enable();
- // Widgets DO want to be deleted if the dialog is
- int wantsToBeDeleted() const;
- // If disabled, refuse all
- virtual int refuseAll() const;
- // Loads setting into our "current" storage
- // Also preps anything else necessary before displaying a dialog, such as
- // setting graphical states back to normal
- virtual void load() = 0;
-
- // Stores our current storage into setting
- virtual void apply() = 0;
- // Called whenever another widget is modified
- // Call AFTER the modification is complete!
- // If this causes us to modify, that won't be propogated
- // Default action is to do nothing
- // A button press doesn't call this
- virtual void siblingModified(Widget* modified);
-
- WindowType windowType() const;
- virtual int getId() const;
- virtual char getShortcut() const;
- };
- class WButton : public Widget {
- protected:
- Dialog::ButtonAction action;
- int command;
- int pressed;
- int spacePressed;
- int hover;
- // Where the icon comes from, if there is one
- int isIcon;
- SDL_Surface* icon;
- int iconX;
- int iconY;
- int iconW;
- int iconH;
-
- enum {
- // Margins on edges (includes bevel)
- GUI_BUTTON_TOPMARGIN = 6,
- GUI_BUTTON_BOTTOMMARGIN = 6,
- GUI_BUTTON_LEFTMARGIN = 12,
- GUI_BUTTON_RIGHTMARGIN = 12,
- // Margin from edge to focus box
- GUI_BUTTON_VFOCUSMARGIN = 4,
- GUI_BUTTON_HFOCUSMARGIN = 5,
- // Margins on edges (includes bevel)
- GUI_ICON_MARGIN = 6,
- // Margin to focus rectangle
- GUI_ICON_FOCUSMARGIN = 4,
- };
-
- // Constructor for radio/checkbox
- WButton(int bId, const std::string& bLabel, void* bSetting);
- WButton(int bId, SDL_Surface* iIconSurface, int iX, int iY, int iW, int iH, void* bSetting);
-
- // Icon display
- void constructIcon(SDL_Surface* iIconSurface, int iX, int iY, int iW, int iH);
- void iconDisplay(SDL_Surface* destSurface, int atX, int atY, int pressed);
- public:
- // Buttons do not have a place to store the setting, but instead
- // return a value or perform some other operation; action is a
- // BUTTON constant from Dialog::ButtonAction; command is sent as
- // a message; Buttons with an icon don't currently display a label.
- WButton(int bId, const std::string& bLabel, Dialog::ButtonAction bAction = Dialog::BUTTON_NOTHING, int bCommand = NO_COMMAND);
- WButton(int bId, SDL_Surface* iIconSurface, int iX, int iY, int iW, int iH, Dialog::ButtonAction bAction = Dialog::BUTTON_NOTHING, int bCommand = NO_COMMAND);
- void changeIcon(int iX, int iY);
- // (this won't rearrange any elements)
- virtual void changeText(const std::string& newLabel);
-
- int event(int hasFocus, const SDL_Event* event);
- virtual void load();
- virtual void apply();
- virtual void display(SDL_Surface* destSurface, Rect& toDisplay, const Rect& clipArea, int xOffset, int yOffset);
-
- // All button presses go through this function
- virtual void doAction();
- Dialog::ButtonAction getAction() const;
- };
- class WCheckBox : public WButton {
- protected:
- // A checkbox is a bit set to on or off in a single location
- // Only the noted bit should be affected.
- int value;
- int currentStatus;
- int isRadio;
-
- // Other controls enabled or disabled based on button status
- // (control id -> enable or disable)
- std::map<int, int> affectControls;
- enum {
- GUI_CHECKBOX_TOPMARGIN = 1,
- GUI_CHECKBOX_BOTTOMMARGIN = 3,
- GUI_CHECKBOX_LEFTMARGIN = 1,
- GUI_CHECKBOX_RIGHTMARGIN = 4,
-
- // margin before/after checkbox
- GUI_CHECKBOX_PRECHECK = 3,
- GUI_CHECKBOX_POSTCHECK = 7,
- };
- static int checkboxSize;
- static int checkboxX;
- static int checkboxY;
- static int checkboxXText;
- public:
- WCheckBox(int cId, const std::string& cLabel, int* cSetting, int cValue);
- WCheckBox(int cId, SDL_Surface* iIconSurface, int iX, int iY, int iW, int iH, int* cSetting, int cValue);
-
- // enable = enable control if checked; otherwise disable if checked
- // doesn't take effect until modified or dialog loaded
- void affectControl(int cId, int enable);
- void changeText(const std::string& newLabel);
- virtual void load();
- virtual void apply();
- void display(SDL_Surface* destSurface, Rect& toDisplay, const Rect& clipArea, int xOffset, int yOffset);
-
- // We can query or set the value of the checkbox with this
- // (returns true/false not gaurunteed to be 1/0)
- // ALL places checkbox is checked or modified go through this function
- virtual int state(int checked = -1, int fromLoad = 0);
- virtual void doAction();
- int getValue() const { return value; }
- };
- // Similar to a checkbox, but only one value can be set at once;
- // the location is set to exactly the value- no bit operations are done
- // Values must be zero or positive! A value that doesn't match any, will have
- // NO button selected when the dialog opens, and will not change it if none of
- // them end up selected.
- // Setting one radio button unsets all other radio buttons with the same id.
- class WRadioButton : public WCheckBox {
- public:
- WRadioButton(int rId, const std::string& rLabel, int* rSetting, int rValue);
- WRadioButton(int rId, SDL_Surface* iIconSurface, int iX, int iY, int iW, int iH, int* rSetting, int rValue);
-
- void load();
- void apply();
-
- // We can query or set the value of the radio button with this
- // If we set it, it will unset any other set buttons with the same id.
- // ALL places radio is checked or modified go through this function
- virtual int state(int value = -1, int fromLoad = 0);
- void doAction();
- };
- class WTextBox : public Widget {
- protected:
- enum UndoType {
- UNDO_NONE = 0,
- UNDO_TYPING,
- UNDO_DELETE,
- UNDO_OTHER,
- };
-
- int maxSize;
- std::string currentValue;
- std::string undoValue;
- int undoPoint;
- UndoType undoType;
-
- // Insertion point data- points to the character it is before
- int insertPoint;
- int insertPointX;
-
- // Selection begin OR end will ALWAYS match insertpoint UNLESS
- // there is no selection, in which case both are set to ZERO
- int selectionBegin;
- int selectionEnd;
-
- // Not gaurunteed to be valid if no selection
- int selectionBeginX;
- int selectionEndX;
-
- // How far left we have scrolled the text; 0 if text fully fits into textbox
- // Never a positive value
- int scrollPointX;
-
- // The x/y offset to start display text at normally, accounting for all
- // margins and padding
- int textX;
- int textY;
-
- // Insertion point
- int insertY;
- int insertHeight;
- int insertBlink;
- Uint32 insertBlinkMs;
-
- // Characters that make up "words"
- static const std::string wordChars;
- enum {
- GUI_TEXTBOX_INSERTPOINTWIDTH = 2,
- GUI_TEXTBOX_BORDERTHICKNESS = 2,
- // This is the max (visible) size for a textbox by default
- GUI_TEXTBOX_MAXSIZE = 20,
- // Margin is blank space inside textbox border
- GUI_TEXTBOX_INNERMARGIN = 0,
- // Padding is added to edges of text within textbox, but only shows when
- // fully scrolled to that end of the text
- GUI_TEXTBOX_LEFTPAD = 3,
- GUI_TEXTBOX_RIGHTPAD = 3,
- // Preferred number of pixels to show in excess on each side when scrolling
- GUI_TEXTBOX_SCROLLAHEAD = 10,
- // MS to wait between blinks
- DELAY_CURSOR_BLINK = 500,
- };
-
- // Sets dirty and resets cursor blink
- void setDirtyAndBlink();
-
- // Saves an undo point
- void saveUndo(UndoType type);
- public:
- // Text boxes do not have prompts
- // Zero max size = no limit
- WTextBox(int tId, std::string* tSetting, int tMaxSize, int tDisplayLength = -1);
- virtual ~WTextBox();
-
- virtual int event(int hasFocus, const SDL_Event* event);
- virtual void load();
- virtual void apply();
- void display(SDL_Surface* destSurface, Rect& toDisplay, const Rect& clipArea, int xOffset, int yOffset);
- void tabAction();
- CommandSupport supportsCommand(int code) const;
- // We can query or set the current text with this; setting text
- // resets selection, insertion, and scroll points; setting text may
- // return different text if the text set was not valid
- const std::string& state() const;
- const std::string& state(const std::string& newValue);
-
- // Returns the insertion position, given a pixel X offset; X offset
- // does not need to be within the actual display boundaries (IE you can drag
- // past the edges)
- int insertWhere(int x) const;
-
- // Handle special keystrokes
- void keyBackspace();
- void keyDelete();
-
- // Query or set the insertion point, which also clears selection and
- // scrolls if needed to view; if drag is true, this drags the current
- // insertion point to the given position, modifying the selection as well
- int insertionState(int newPos = -1, int drag = 0);
- // Selects entire text, scrolls to end
- void selectAll();
-
- // Undo
- void undo();
-
- // Inserts text at the insertion point, overwriting any selection
- // No text = clear selection
- // Resets selection and adjusts insertion and scroll points
- void pasteText(const std::string& text);
-
- // Copies current selection to buffer
- // Copies "" if no selection
- void copyText(std::string& buffer) const;
- // Validates a change to textbox before it occurs, returns true if change
- // is OK; making changes to new text or cursor position is OK; this is only
- // called if text changes, not just if cursor position does; you can assume
- // new cursor position is right after the added text or where the deleted
- // text was. Default version allows all changes. Isn't called just on cursor
- // move or load().
- virtual int allowChange(const std::string& oldValue, std::string* newValue,
- int oldCursorPos, int* newCursorPos) const;
- };
- class WNumberBox : public WTextBox {
- protected:
- int min;
- int max;
- public:
- WNumberBox(int tId, int* tSetting, int tMin, int tMax);
- ~WNumberBox();
-
- int allowChange(const std::string& oldValue, std::string* newValue,
- int oldCursorPos, int* newCursorPos) const;
- int event(int hasFocus, const SDL_Event* event);
- void load();
- void apply();
- int entryValid() const;
- int state() const;
- int state(int newValue);
- };
- class WStatic : public Widget {
- public:
- enum {
- REFUSE_STATIC = 2,
- };
- // Static text does not have a place to store any setting
- WStatic(int sId, const std::string& sLabel);
- void changeText(const std::string& newLabel);
- // Refuse all!
- // If not disabled, returns WStatic::REFUSE_STATIC to clarify
- int refuseAll() const;
-
- int event(int hasFocus, const SDL_Event* event);
- void load();
- void apply();
- void display(SDL_Surface* destSurface, Rect& toDisplay, const Rect& clipArea, int xOffset, int yOffset);
- };
- #endif
|