summaryrefslogtreecommitdiff
path: root/src/gui/widgets
AgeCommit message (Collapse)AuthorFilesLines
2025-05-09Fixed tooltip visibility logic for shortcut and inventory windowsfix-item-tooltip-visibilityThorbjørn Lindeijer3-25/+39
* When hovering an empty box in the shortcut window, the tooltip of a previously hovered non-empty box would stay visible. * When hovering to the right of a row of inventory items, the tooltip for the left-most item on the next row would be displayed. Also added some padding to shift the text and item icon a little in the shortcut window when using the Jewelry theme.
2025-04-28GUI: Use theme icons for offline/online player indicatorsThorbjørn Lindeijer2-34/+24
Instead of loading images directly, which is less flexible. In Jewelry theme, these icons are embedded in the window.png image.
2025-04-26GUI: Added support for explicit outline color per palette entryThorbjørn Lindeijer6-41/+116
This enables customized outlines for each text color as well as adding outlines for specific palettes, as done by the Jewelry theme. Merged PARTY_CHAT_TAB and PARTY_SOCIAL_TAB into just PARTY_TAB since we should probably be using the same color there anyway. Split off WHISPER_TAB as separate color from WHISPER.
2025-04-25GUI: Added support for multiple color palettes to ThemeThorbjørn Lindeijer19-226/+161
Each Skin can point to a different palette, which can be used to tweak text colors where necessary. For now there is no generic solution for this, instead a number of locations have been adjusted to take the palette into account: * ChatWindow sets its palette on the BrowserBox used in its tabs. * Popup sets its palette on child widgets when they are added (covering BrowserBox, Label and TextBox). * ItemPopup now uses its palette when looking up colors. The BrowserBox now retrieves its numbered text colors from the theme. Also added OLDCHAT, AWAYCHAT and GLOBAL theme colors, with ##g, ##o and ##a to choose these colors respectively. Fixed ImageRect move constructor. TextPreview class was cleaned up from unused functionality. Being name colors are no longer different between the name shown on the being and the name shown in the SpeechDialog.
2025-04-25Introduced theme dropdown in interface setupThorbjørn Lindeijer3-20/+13
* Added Theme dropdown to Interface setup * Added CARET theme color * Fixed issue with logging errors in `check` function in `theme.cpp` * Fixed XML::Children::Iterator to iterate only element nodes * Changed default theme to "jewelry" Changing the theme (or font size) shows a dialog that points out a restart is required to apply these changes. This is necessary at the moment because many things, like default or minimum window sizes, are only calculated once.
2025-04-25GUI: Added support for hiding the scroll area buttonsThorbjørn Lindeijer2-9/+138
And made the Jewelry theme hide those buttons.
2025-04-25GUI: Added support for fixed-size scrollarea markersThorbjørn Lindeijer2-7/+338
Due to getVerticalMarkerDimension and getHorizontalMarkerDimension not being virtual, this unfortunately required copying a lot of code from Guichan to make sure it calls our versions of these functions. Also addressed a small issue where gcn::ScrollArea::checkPolicies was not taking the frame size of the content into account.
2025-04-25Jewelry: Fixed sticky button positionThorbjørn Lindeijer1-18/+18
Used "spacing" to store the additional space between the sticky button and the edge of the window (or the close button). Adjusted Popup and ToolWindow skins by one pixel to make the sticky button align the same way as for the Window skin.
2025-04-25GUI: Allow theme to skin item slots and equipment boxesThorbjørn Lindeijer8-57/+60
* Added EquipmentBox and ItemSlot skin types. * Allowed rectangles drawn by the theme to be not filled. * Added width/height attributes to skin element since we needed a way to specify the size of the item slots and equipment boxes.
2025-04-25GUI: Allow customizing the SkinType used by a WindowThorbjørn Lindeijer2-9/+23
Now different windows can use different skin types. This also introduces a new ToolWindow skin type, which is generally a window without title bar nor close button. Customized windows are: * Chat -> Popup skin * MiniMap -> Popup skin * ShortcutWindow (items and emotes) -> ToolWindow skin Even though the MiniMap now appears as a Popup, it does have a title, so appropriate attributes have been added to this skin type.
2025-04-02Use a consistent naming style for enum class valuesThorbjørn Lindeijer2-10/+10
Sometimes I've used CamelCase and sometimes SNAKE_CASE for these values. Since "enum class" values are always prefixed with the enum name, which uses CamelCase, I find it more fitting to use it for the values as well. Also fixes compilation on Windows where 'ERROR' was conflicting with a define.
2025-04-02General code cleanupsThorbjørn Lindeijer2-36/+18
* Removed some unused includes and forward declarations. * Use std::unique_ptr to automate cleanup. * Use TextRenderer::renderText in BrowserBox to avoid code duplication. * Removed unused STATE_NORMAL from StateFlags. * Small layout fix in ServerDialog. * Reduced rewrapping delay in BrowserBox to 33ms and disabled it entirely when there are no more than 1000 lines to rewrap. The rewrapping is usually fast enough.
2025-04-02Fixed minimum width of the Social windowThorbjørn Lindeijer2-2/+17
Needs to allow space for all three buttons, especially since they are no longer clipped to the window.
2025-04-01GUI: Made CheckBox, RadioButton and Slider more customizableThorbjørn Lindeijer5-49/+63
Added handling of padding and text format and added new "spacing" skin variable which is used for the space between the label and the control in case of CheckBox and RadioButton. Small tweaks to UI layout in various places.
2025-03-31GUI: Support customizing widget text format through themeThorbjørn Lindeijer6-39/+138
The following widgets now support setting the font, text color, outline color and shadow color through the theme: * Button * Tab * Window (title) * ProgressBar The text format can be specified differently per skin state.
2025-03-31GUI: De-hardcode the window title offsetsThorbjørn Lindeijer2-9/+14
2025-03-31GUI: Apply clipping only where necessaryThorbjørn Lindeijer5-31/+40
Clipping has been disabled globally by taking it out of Graphics::pushClipArea. Now its name is a little confusing, but it can't just be changed since it is part of Guichan. Widgets that do need to clip their children use the new Graphics::pushClipRect, which pushes a clipping rectangle without affecting the local coordinates. These are: * ScrollArea * TextField * TabbedArea (scrolling tabs) * MiniMap While it might count as a small optimization, I'm actually disabling clipping because it is not always desired. For example it gets in the way of rendering the complete ResizeGrip in the Jewelry theme because that's a child widget.
2025-03-24Expanded GUI theming capabilitiesThorbjørn Lindeijer26-288/+433
* Moved previously hardcoded values for frame size, padding and title bar height to the Skin. * Added support for rendering colored rectangles (used for scroll bar background). * Scroll bar width is now determined by its skin. * Added separate skins for horizontal and vertical scroll bars and horizontal and vertical scroll markers and added a skin for the shortcut box. * Added support for hovered state on window close button.
2025-03-24Define the GUI theme in XMLThorbjørn Lindeijer14-164/+181
Now all images used by the various UI widgets are defined in a `theme.xml`, removing hardcoded requirements on the size of images, borders and sub-images and their locations. The `colors.xml` file was merged into this new file as well. The `<img>` element defines either a plain image, or a 9-scale that is automatically rendered at the size of the widget when any of the `left`, `right`, `top` or `bottom` attributes are given. The `x`, `y`, `width` and `height` attributes determine the sub-rectangle within the image referenced by `src`. `x` and `y` default to 0 and `width` and `height` default to the imge size. The `<state>` element defines in which state its images are used by setting its `selected`, `disabled`, `hovered` or `focused` attributes to either `true` or `false`. Only the first matching state is rendered. The `Text` and `SpeechBubble` classes now use the same skin to draw the bubble, as well as using a newly introduced `BUBBLE_TEXT` color from the theme palette.
2025-03-17Have ImageRect automatically initialize and clean upThorbjørn Lindeijer2-4/+0
2025-03-14Moved widget drawing code into ThemeThorbjørn Lindeijer29-1244/+172
This is cleaner overall since now each widget type no longer needs to keep track of its own instances and updating of the GUI alpha. It also introduces a single point from where the GUI theme support can be enhanced. Theme is no longer a singleton, though for now there is a single instance owned by the Gui singleton. Widgets adjusted to delegate their painting to the Theme: * Button * Tab * TextField * CheckBox * RadioButton * Slider * DropDown * ProgressBar * ScrollArea * ResizeGrip * PlayerBox (by subclassing ScrollArea) The Window and Popup widgets already use the theme through the Skin class. They can actually use a different skin per instance, though this feature is only used by the SpeechBubble.
2025-03-11Implemented replacement of key names in NPC dialogThorbjørn Lindeijer2-0/+42
Now when NPCs text includes "###MoveUp;", it will get replaced by "Up", or whatever key is currently bound to that action. For compatibility reasons the key name can optionally have a "key" prefix, for example "###keyMoveUp;". Closes #73
2025-03-07Reuse gcn::ScrollArea::drawThorbjørn Lindeijer2-27/+7
Code appeared duplicated just because we don't draw the background, but this could be done by overriding drawBackground instead.
2025-03-07Introduced spriteOffsetY setting to replace half tile hackThorbjørn Lindeijer1-3/+2
For historical reasons, sprites get a 16 pixel offset by default, which is used to position them correctly on their tile. When pixel-based movement was added, actors are now positioned on the middle of a tile and the built-in offset was removed. Servers that use sprites that do not rely on this offset can now set the spriteOffsetY option to 0.
2025-02-28Fixed unresponsive UI when switching server/char with Away dialog openThorbjørn Lindeijer2-7/+8
The UI became unresponsive as a result of not actually deleting the OkDialog. The dialog is now managed by the AwayListener, which now schedules Away dialog for deletion when necessary, using a DeathListener to clear the reference to the dialog. The WindowContainer now uses an std::set instead of std::list to keep track of widgets scheduled for deletion, to avoid crashing when a widget is scheduled for deletion multiple times.
2025-02-26Plugged a few more memory leaksThorbjørn Lindeijer4-20/+9
* DebugWindow and SkillDialog were not deleting their tabs nor their tab widgets. * TabbedArea was not deleting its arrow buttons. * Button was deleting its TextPopup on deletion of the last Button instance, which was wrong because it was also being deleted by the WindowContainer. Also removed some misplaced event forwarding to the TextPopup. TabbedArea is tricky because it does not automatically delete added tabs or their widgets. Tab instances are only deleted when they were added by name. Issues found by Valgrind memory analyzer.
2025-02-26Use ResourceRef for all resource typesThorbjørn Lindeijer29-169/+124
All ResourceManager functions that load resources now return respective ResourceRef values, which helps to make sure resources are properly cleaned up. The Sound class was cleaned up and now also allows SoundEffect resources to be unloaded. The Animation class now keeps its ImageSet loaded only as long as necessary. Previously, SimpleAnimation and ParticleEmitter would keep the ImageSet loaded indefinitely by never decreasing its reference count. Reduced duplicated animation loading code between SimpleAnimation and ParticleEmitter.
2025-02-21Removed ImageSpriteThorbjørn Lindeijer1-2/+0
The only use of ImageSprite was for FloorItem instances, which now just draw the item icon in FloorItem::draw. This leaves only one Sprite subclass, AnimatedSprite, which means we can remove the entire virtual Sprite interface.
2025-02-21Replaced ImageSprite in Emote by plain ImageThorbjørn Lindeijer1-5/+12
Emotes just need an image to be represented in the UI, so we don't need to use ImageSprite.
2025-02-17Further ResourceManager and PhysFS cleanupsThorbjørn Lindeijer2-16/+31
* Wrapped remaining PhysFS API calls and set PHYSFS_DEPRECATED to suppress deprecation warnings for PHYSFS_getUserDir, since no alternative is available for now. * Removed support for decompressing .gz files, since it has been unused for years and doesn't seem useful when updates are anyway served in an archive. * Use SDL_LoadFile and SDL_LoadFile_RW convenience functions (raises minimum SDL version to 2.0.10). * Removed ResourceManager::copyFile, since it was unused and will likely stay unused. * Removed ResourceManager::loadTextFile. Instead, split up the string in BrowserBox::addRows without making additional copies.
2025-01-21Replaced include guards with #pragma onceThorbjørn Lindeijer46-186/+46
Thanks to https://github.com/cgmb/guardonce and a follow-up replace to remove duplicated newlines at end of file: find src -type f -name '*.h' -exec \ sed --in-place -e :a -e '/^\n*$/{$d;N;};/\n$/ba' {} \; Source: https://unix.stackexchange.com/questions/81685/how-to-remove-multiple-newlines-at-eof Fixes compile on macOS, which appears to have been due to the EVENT_H include guard.
2025-01-21Fixed ConfigOptionChanged eventsThorbjørn Lindeijer1-1/+1
With the statically typed config we no longer get an event for each changed config value. Where relevant, this is now done through `setConfigValue`. The `Event` now uses a `std::any`, which for `ConfigOptionChanged` events is set to the changed `Config` member. This allows for a type-safe check on which config value was changed.
2025-01-20Made client config statically typedThorbjørn Lindeijer21-86/+73
This makes accessing the config values much faster, since it no longer needs to do a lookup nor string conversion, which means we could remove some needless copying of the values. Overall it makes it easier to find out where settings are used and it puts the defaults along with the declaration. Options with default values are no longer saved to the config file. This does not include unrecognized options, which are kept around to provide some compatibility with older clients. While most basic options have kept the same name, more complicated settings like window geometry, shortcuts, outfits, etc. now have their own XML elements. Older clients will ignore these and erase them when saving the configuration.
2024-10-29Optimise PlayerRelationsManager::clearThorbjørn Lindeijer1-5/+4
Previous implementation was O(n^2), doing lots of work (saving file and updating UI) for each removed player.
2024-10-26Fixed FPS limit being enabled by defaultThorbjørn Lindeijer2-2/+2
There were some inconsistencies between the values set up in `Client::initConfiguration` and those in `getConfigDefaults`. These duplicates have now been removed. For some of these settings the code getting the values had to be adjusted to use getBoolValue, to actually rely on the provided default instead of one provided as a parameter.
2024-10-18Added small grabbable margin to Shortcuts windowThorbjørn Lindeijer3-43/+19
The Shortcuts window could no longer be moved since adding support for resizing windows at the top edge. Now there is again a bit of space where the window can be grabbed. Included some related cleanups.
2024-10-18General code cleanupsThorbjørn Lindeijer1-3/+2
2024-10-08Do a single logic update each frameThorbjørn Lindeijer1-1/+1
The logic update now uses Time::deltaTimeMs() where needed to make it framerate-independent. This means there will no longer be multiple logic calls per frame (as was usually the case with logic ticking at 100 fps whereas the game would generally run at 60 fps). At the same time, the game can be more precise at higher framerates and should now run smoother at 144 Hz, for example. Previously the game would sometimes skip logic ticks at that rate. This change affects: * Updating of animations * Being movement speed * More moving of manual time variables to Timer Notoriously, the particle system still does 100 ticks/second.
2024-10-08Added convenient and efficient Timer classThorbjørn Lindeijer2-5/+7
The Timer is efficient because it does not depend on incrementing a counter to keep track of time, nor does it call SDL_GetTicks every time its state is checked (this happens once per frame instead). Along with global functions Time::absoluteTimeMs() and Time::deltaTimeMs(), this replaces previous globals tick_time, cur_time and get_elapsed_time(). For now, there is still a fixed 100 times per second logic call rate, but the new Time::deltaTimeMs() function should allow getting rid of this.
2024-09-28Removed getter/setter cruft from ItemInfoThorbjørn Lindeijer3-7/+7
Made the class and the code in general more readable by removing all the needless getters and setters.
2024-09-02Added a hand mouse cursor, used when hovering linksThorbjørn Lindeijer2-11/+16
InputEvent::mIsConsumed is used to tell the Window it should not change the mouse cursor as well. This change also adds a closed hand mouse cursor, though this is unused for now (might be useful when dragging stuff around). The new cursors are by meway.
2024-08-31Display "Mana" as part of the version in Setup windowThorbjørn Lindeijer1-1/+1
This was already done in the log, when responding to the --version parameter and for the label on the Desktop widget, but not in the Setup window. Now it is consistently part of the FULL_VERSION define.
2024-08-31BrowserBox: Make sure to start each line with the default colorThorbjørn Lindeijer1-1/+4
This was already the case for each newly added line, but when the entire layout was redone previous selected colors would spill over to the next line.
2024-08-31Some margin and indentation tweaks in news and NPC dialogsThorbjørn Lindeijer3-39/+37
* Apply indentation after wrapping only in NPC dialogs and chat window, since we don't want this in the updater window / news. * Added some margin around the text in the updater window and NPC dialogs, using gcn::Widget::setFrameSize. * Cosmetic changes to BrowserBox implementation.
2024-08-28Fixed handling of consecutive text formatting markersThorbjørn Lindeijer1-11/+7
If a text contained for example "##3##B", expected behavior was to switch to blue color and bold font. Instead, due to there being no actual text in between the markers, the layouting code was aborting prematurely here: if (mMode == AUTO_WRAP && partWidth == 0) break; As far as I could judge, this check is actually not necessary anyway, but I've kept it for now since the wrapping code looks so problematic. Instead, a while loop now makes sure we process all consecutive formatting markers. Closes #75
2024-08-15Fixed resize border width on bottom and right sidesThorbjørn Lindeijer1-4/+4
2024-08-04Small code simplification in Button::initThorbjørn Lindeijer1-10/+7
2024-08-04Reuse Window::ensureOnScreenThorbjørn Lindeijer1-17/+7
Less code duplication.
2024-06-25Added online player list to Social windowDavid Athay2-19/+8
The online list refreshes every 18 seconds, which matches ManaVerse behavior. It's not ideal, but to improve this would mean diving into TMWA. The client version was bumped to 8 to get a SMSG_ONLINE_LIST reply. Further changes needed related to the client version are tracked by #71. This also changes the TabbedArea to take into account the frame size for its tab widgets, to make sure those frames are not clipped by the TabbedArea widget (as happened in the Social window). The horizontal scroll bar is now disabled in all social tabs, with the vertical one appearing only when necessary. Closes #61
2024-06-25Fixed spaces getting added to chat every 50 charactersThorbjørn Lindeijer2-25/+2
This reverts part of 087babc2525ddb89e5b31f240a08739d9a3029a9. It's unclear to me why big words should be split (chat window force-wraps when necessary anyway) and it's causing issues by adding spaces in the middle of links, for example.