Commit graph

42 commits

Author SHA1 Message Date
Andreas Kling
b513a787fb GTextEditor: set_text() should clear any existing spans 2019-10-26 20:21:12 +02:00
Andreas Kling
bc2026d26d LibGUI: Make GTextEditor::Span have a range instead of two positions
A GTextRange is really just two GTextPositions (start and end) anyway.
This way we can say nice things like "if (range.contains(position))"
2019-10-26 15:33:19 +02:00
Andreas Kling
4fa8acf6ea GTextEditor: The Home key should jump to the first non-space character
Press Home twice to get to column 0. This feels way more natural.
2019-10-26 14:02:39 +02:00
Andreas Kling
532001f4c1 GTextEditor: Arrow keys should only modify selection when Shift is held 2019-10-26 14:01:53 +02:00
Andreas Kling
59107a7cfe GTextEditor: Allow setting a custom font for each span 2019-10-26 00:13:07 +02:00
Andreas Kling
0d53d74d5f GTextEditor: Add a "span" mechanism for having custom-style text ranges
It's now possible to give GTextEditor a vector of Span objects.
Spans currently tell the editor which color to use for each character
in the span. This can be used to implement syntax highlighting :^)
2019-10-25 21:07:02 +02:00
Andreas Kling
0a0dfeee8b LibGUI: Make GTextEditor::set_cursor() public
Also clamp the cursor value to the possible range instead of asserting
when trying to set a cursor past the end of the document.
2019-10-21 19:01:27 +02:00
Andreas Kling
caf1b37e75 GTextEditor: Unbreak right-aligned single-line text boxes
This makes the Calculator app look right once again! :^)
2019-09-16 20:57:32 +02:00
Andreas Kling
b41b5433f4 LibGUI: Add Undo/Redo to GCommonActions 2019-09-14 22:23:49 +02:00
Andreas Kling
e83390387c LibGUI: Simplify GCommonActions a bit
Use the same callback signature as GAction so we can just forward it
to GAction instead of chaining callbacks.
2019-09-14 22:10:44 +02:00
Andreas Kling
11f2e7cd5c GMenu: Update apps now that you can create a nameless GMenu
We had many context menus with names, simply because you were forced
to give them names.
2019-09-13 22:14:07 +02:00
Andreas Kling
6ab498edf7 GTextEditor: Paint line numbers with TopRight text alignment
This makes sure they line up with the first visual line for wrapped
lines that span multiple visual lines.
2019-09-06 19:24:16 +02:00
rhin123
1adec6d54b TextEditor: Removed unnecessary use of for_each
Didn't notice that m_visual_rect existed :P
2019-09-06 07:17:57 +02:00
rhin123
5594f19624 TextEditor: Added GCommonActions 2019-09-05 09:40:54 +02:00
Andreas Kling
77a58119e7 GTextEditor: Hide the horizontal scrollbar when line-wrapping is on 2019-09-01 20:34:50 +02:00
Andreas Kling
906582d8df GTextEditor: Fix wrong width calculations with line-wrapping enabled
There were various little mistakes in the width calculations used by
the line-wrapping layout code.

With this patch, we should no longer see the horizontal scrollbar get
enabled with line-wrapping enabled. I will hide the scrollbar in a
separate patch.
2019-09-01 20:04:25 +02:00
Andreas Kling
74ca299b4b GTextEditor: Make visual lines stop after their last character
Instead of letting each visual line run to the end of the editor when
wrapping lines, stop each visual line where it runs ouf characters.

Fixes #493.
2019-09-01 17:30:23 +02:00
Rhin
3e6a0a0533 TextEditor: Stopped disappearing text at end of document (#505)
text_position_at() was returning -1 if the position wasn't in
the bounds of a visual line. Now if the position is past the last
line, we simply return the last line index instead of -1.

Fixes #502.
2019-09-01 12:34:14 +02:00
Andreas Kling
3e2e086011 LibGUI: Add a way for GWidget subclasses to learn that the font changed
Use this in GTextEditor to update the vertical scrolling step size so
we always scroll one-line-at-a-time.
2019-09-01 12:26:35 +02:00
Rhin
d3ebd8897f GTextEditor: Set content size based on the visual line rects (#500)
When we update our content size, the width & height is now calculated
from the visual line rect size. Also now after we recompute all visual
lines, if the total height is different, we re-update the content size.
2019-08-29 06:26:24 +02:00
Andreas Kling
50ef2216fa GTextEditor: Optimize write_to_file() with ftruncate()
Compute the final file size and ftruncate() the destination file to the
right size immediately instead of incrementally appending to it.

This kind of optimization belongs in the kernel, but until we have it
there, this makes saving text files a whole lot faster. :^)
2019-08-28 19:32:45 +02:00
Andreas Kling
fcf85d8fef GTextEditor: Always call did_change() after deleting with backspace
This is needed for the on_change callback to fire.
2019-08-27 20:16:52 +02:00
Andrew Weller
ed0553fe10 GTextEditor: Fixed bug on KeyCode::Key_Right pressed.
Pressing right did nothing when the very last characters of the buffer
were selected.

The expected action would be for the cursor to move to the end of the
buffer.

This patch fixes that.
2019-08-27 07:17:22 +02:00
Andrew Weller
b50ffaf7e1 GTextEditor: Fixed bug in find_prev
Find_prev returned invalid when the contents of the file were equal to
the contents of the search box.

This is due to the checker walking on an empty character at the end of
a line.
2019-08-27 07:17:22 +02:00
Andreas Kling
a6be213287 GTextEditor: Add add_custom_context_menu_action()
This allows embedders to add their own custom GAction set to a text
editor's context menu.
2019-08-25 21:33:08 +02:00
Andreas Kling
fa20dcafb5 GTextEditor: Simplify computation of visual selection start/end
Add Line::visual_line_containing(int column) to easily convert a column
number into a visual line index.
2019-08-25 14:04:46 +02:00
Andreas Kling
5aac652b4b GTextEditor: Relayout when the line-wrapping setting is changed 2019-08-25 12:23:14 +02:00
Andreas Kling
3ca1c72c77 GTextEditor: Unbreak selection painting in the new line-wrapping world
To expand a bit on how the line-wrapping works, each physical line of
text is broken up into multiple visual lines. This is recomputed when
the document changes, or when the widget is resized.

Each GTextEditor::Line keeps track of the visual breaking points, and
also their visual rect in content coordinates. This allows us to do
painting and hit testing reasonably efficiently for now.

This code needs some cleanup, but it's finally in a working state, so
here it goes. :^)
2019-08-25 11:24:23 +02:00
Andreas Kling
7b5bcec562 GTextEditor: Fix computing content x/rect values with line wrapping
This makes the cursor actually get painted on the right visual line
when in line-wrapping mode.
2019-08-25 11:24:23 +02:00
Andreas Kling
2e31b6627e GTextEditor: Take horizontal padding into account for line visual rects 2019-08-25 11:24:23 +02:00
Andreas Kling
9752e683f6 GTextEditor: Start working on a line-wrapping feature
This is not finished, but since the feature is controlled by a runtime
flag, the broken implementation should not affect users of this widget
too much (in theory :^).)
2019-08-25 11:24:23 +02:00
Andreas Kling
23b70d5c59 GTextEditor: Clean up some of the rect computations
Moving some rect computations to separate functions to make it easier
to reuse them.
2019-08-25 07:17:09 +02:00
Andrew Weller
e75e33eb46 TextEditor: Replaced 'Find' button with 'Prev' and 'Next' buttons. 2019-08-24 21:57:42 +02:00
Andreas Kling
748b38d80f GTextEditor: Fix obvious bug in find()
We forgot to rewind the search cursor after a partial match, which
would make us fail to find "xxy" in "xxxxy".
2019-08-23 13:54:25 +02:00
Andreas Kling
0c72371ad9 GTextEditor: Implement a simple text search API
- GTextRange find(const StringView& needle, const GTextPosition& start)

This function searches for the needle in the haystack (the full text)
and returns a GTextRange for the closest match after "start".
If the needle is not found, it returns an invalid GTextRange.
If no "start" position is provided, the search begins at the head of
the text document. :^)
2019-08-21 21:23:17 +02:00
Andreas Kling
5670a3e064 GTextEditor: Run clang-format on GTextEditor.cpp 2019-08-21 20:20:07 +02:00
Andreas Kling
9e5c5627d5 GTextEditor: Give Line objects a back-reference to the GTextEditor
This will allow us to do more complicated things in Line without having
to pass the editor around all the time.
2019-08-21 19:32:39 +02:00
Andreas Kling
b98c77229d TextEditor: Let's have line numbers starting at 1.
Thanks to Dan for pointing this out on IRC:

<danboid> I see TextEditor still numbers its lines from 0. You're too much of a programmer sometimes kling! :)
<  kling> that might be the most extreme form of "programmer design" I've seen in serenity
2019-07-27 21:20:38 +02:00
Andreas Kling
2196f17c10 LibGUI: Convert Vector<OwnPtr> to NonnullOwnPtrVector.
This is turning out really nice so far. :^)
2019-07-24 09:13:06 +02:00
Andreas Kling
c110cf193d Kernel: Have the open() syscall take an explicit path length parameter.
Instead of computing the path length inside the syscall handler, let the
caller do that work. This allows us to implement to new variants of open()
and creat(), called open_with_path_length() and creat_with_path_length().
These are suitable for use with e.g StringView.
2019-07-08 20:01:49 +02:00
Andreas Kling
0e75aba7c3 StringView: Rename characters() to characters_without_null_termination().
This should make you think twice before trying to use the const char* from
a StringView as if it's a null-terminated string.
2019-07-08 15:38:44 +02:00
Andreas Kling
04b9dc2d30 Libraries: Create top level directory for libraries.
Things were getting a little crowded in the project root, so this patch
moves the Lib*/ directories into Libraries/.
2019-07-04 16:16:50 +02:00
Renamed from LibGUI/GTextEditor.cpp (Browse further)