Age | Commit message (Collapse) | Author |
|
|
|
This would undo all commands at once instead of one at a time.
|
|
When clicking empty space (beneath any used lines) in the TextEditor,
the cursor would jump to the start of the last line, rather than the
correct column, or the end of the line where appropriate. This was
because in the for_each_visual_line callback would return
IterationDecision::Continue if the clicked point wasn't in the line's
rect. Thus the callback would continue on each iteration and at the
end, would set the cursor to the default column of 0. To fix this I
added a bool to the callback's signature which tells the callback if
the for_each_visual_line method is on the last visual line. The
callback now does not return IterationDecision:Continue if
for_each_visual_line method is on the last line and the correct column
is then calculated with the line passed.
|
|
This work is already done (and more correctly) by the parent class
(AbstractView) if we just let it take care of the event instead.
Fixes the root cause of #4096.
|
|
This moves file extension to icon mappings from compile time macros to an
INI config file (/etc/FileIconProvider.ini), so file icons can easily be
customized and extended :^)
I also switched the format from a static file extension (".foo") to
glob-like patterns ("*.foo", using StringUtils::matches()), which allows
us to assign icons to specific exactly matching file names, like many
IDEs do - e.g. "CMakeLists.txt" or ".prettierrc".
|
|
By using Gfx::Bitmap::is_path_a_supported_image_format() we can
automatically provide the image icon for all supported image formats,
without keeping a second list of image file extensions.
|
|
This adds the following:
- cplusplus: .cxx, .cc, .c++
- header: .hpp, .hxx, .hh, .h++
- javascript: .mjs
|
|
Bitmap::is_path_a_supported_image_format() and Bitmap::load_from_file()
now check the file extension with CaseSensitivity::CaseInsensitive.
This fixes a couple of inconsistencies, for example would
FileSystemModel::icon_for() recognize image files uppercase extensions
but couldn't create thumbnails for them (any attempt to create a bitmap
from such files would fail).
|
|
When calculating the vertical distance between icons, we should take
into account the value of the vertical scrollbar.
Fixes #4040
|
|
This is making me question the usefulness of application-global
shortcuts, but for now let's just prevent them from triggering while
you're looking at a modal message box..
|
|
This makes most operations thread safe, especially so that they
can safely be used in the Kernel. This includes obtaining a strong
reference from a weak reference, which now requires an explicit
call to WeakPtr::strong_ref(). Another major change is that
Weakable::make_weak_ref() may require the explicit target type.
Previously we used reinterpret_cast in WeakPtr, assuming that it
can be properly converted. But WeakPtr does not necessarily have
the knowledge to be able to do this. Instead, we now ask the class
itself to deliver a WeakPtr to the type that we want.
Also, WeakLink is no longer specific to a target type. The reason
for this is that we want to be able to safely convert e.g. WeakPtr<T>
to WeakPtr<U>, and before this we just reinterpret_cast the internal
WeakLink<T> to WeakLink<U>, which is a bold assumption that it would
actually produce the correct code. Instead, WeakLink now operates
on just a raw pointer and we only make those constructors/operators
available if we can verify that it can be safely cast.
In order to guarantee thread safety, we now use the least significant
bit in the pointer for locking purposes. This also means that only
properly aligned pointers can be used.
|
|
Set the max height of the text_rect to be the height difference
between two icons. Calculate the number of text lines that can be
displayed in this height, and display only that many.
|
|
|
|
|
|
...instead of maybe bitmap + a single mime type and its corresponding data.
This allows drag&drop operations to hold multiple different kinds of
data, and the views/applications to choose between those.
For instance, Spreadsheet can keep the structure of the dragged cells,
and still provide text-only data to be passed to different unrelated editors.
|
|
The current implementation is lying, it returns negative values if the
inner rect has a zero width or height but also a scrollbar - which
doesn't mean there's a "negative size" available though; it's still "no
size available", i.e. 0.
|
|
Add a clip rect for the rubber band painter of widget_inner_rect
This ensures the rubber band is not drawn over the scrollbars.
Fixes #3926
|
|
After moving the cursor to the home position, clear the
selection.
Fixes #3925.
|
|
shift-selecting simply toggles all indices in the range between the
cursor and the index that is being 'selected'.
|
|
If the user tries to drag an item with a null drag data type from an
AbstractView, return from the mouse event early.
|
|
Views would previously require that an item be selected before it could
be dragged. This patch makes us consider initiating a drag immediately
after the view has been selected, without requiring a mouseup event in
between.
|
|
|
|
This is sad (since it would be nice to preserve the cursor+selection)
but until we implement persistent model indexes, this at least prevents
us from keeping a stale cursor index.
|
|
Not sure why I put this into LibGUI in the first place.
|
|
The calls to set_cursor() already take care of scrolling the new cursor
into view if needed.
|
|
This returns true if the widget has focus, or if one of its descendant
widgets does. Use this in StackWidget and TabWidget.
This also fixes HackStudio crashing on startup in StackWidget, due to
running before the window has a focused widget.
|
|
When setting a new active widget, transfer focus if it's anywhere in
the old active widget's tree, not just at the immediate child.
|
|
When computing the chain of focusable widgets in a window, only include
each widget once (to avoid loops) and resolve focus proxies immediately
instead of lazily. This prevents the focus from getting stuck when
cycling backwards and hitting a proxy that points forward.
|
|
When opening a new window, we'll now try to find a suitable widget for
initial focus by picking the first available mouse-focusable one.
Whenever you press the tab key in a window with no focused widget,
we'll attempt to find a keyboard-focusable widget and give it focus.
This should make all applications keyboard-interactive immediately
without having to manually place focus with the mouse.
|
|
|
|
If a button is orphaned, there are no siblings anyway, so there's no
need to try to update them.
|
|
If there are no tab buttons or tab children, don't participate in the
focus chain.
|
|
This one is a bit sketchy. While a window is inactive, none of its
widgets are considered focused (Widget::is_focused() will return false)
but this caused programmatic changes of the active widget in a tab
or stack widget to fail focus propagation from old child to new child.
Work around this by checking against Window::focused_widget() directly
instead of asking Widget::is_focused().
|
|
This transparently transfers focus to the active widget whenever the
stack widget is focused.
|
|
You can now focus a TabWidget by tabbing (with the keyboard!) to it.
Once focused, you can switch the active tab by pressing the left/right
keyboard keys.
|
|
This matches the behavior of GUI::StackWidget.
|
|
Every widget now has a GUI::FocusPolicy that determines how it can
receive focus:
- NoFocus: The widget is not focusable (default)
- TabFocus: The widget can be focused using the tab key.
- ClickFocus: The widget can be focused by clicking on it.
- StrongFocus: Both of the above.
For widgets that have a focus proxy, getting/setting the focus policy
will affect the proxy instead.
|
|
|
|
Some of the indexes generated during cursor movement were using column
instead of model_column(), which caused inconsistent display of items
under the cursor.
|
|
If an AbstractView receives focus without a valid cursor index, we now
ask it to move its cursor to the home position. This way, the user can
actually start moving the cursor after tabbing to a view.
|
|
This was preventing views from relinquishing focus via the keyboard.
Fixes #3862.
|
|
At least pass them up to GUI::Widget so they can be handled there.
|
|
This patch adds a simple filter that makes button and menu item icons
have that "'90s disabled" look when disabled. It's pretty awesome.
|
|
TreeView was still partly sticking to the pre-cursor way of using the
first index in the selection as the implied cursor. This patch fixes
all of the TreeView code to operate on the cursor instead.
This makes trees behave much more intuitively when alternating between
mouse and keyboard interaction.
|
|
Instead of filling the whole row with selection color, only fill behind
the text. This gives a snugger, more focused appearance.
For embedders that want the entire row to get filled with the selection
color when selected, they can opt in to the old behavior by calling
TreeView::set_should_fill_selected_rows(). This is used by Profiler.
|
|
|
|
|
|
|
|
This makes the cursor actually visible to the user, and looks rather
neat if I may say so. :^)
|
|
Move the wrapping logic to get_item_rects(). This makes mouse events
able to hit the wrapped labels, and various other little things stop
glitching out as well.
Also, instead of having a per-line width when wrapping icon names,
make the text rect wide enough to fit every line.
|