Commit graph

78 commits

Author SHA1 Message Date
Andreas Kling
94ca55cefd Meta: Add license header to source files
As suggested by Joshua, this commit adds the 2-clause BSD license as a
comment block to the top of every source file.

For the first pass, I've just added myself for simplicity. I encourage
everyone to add themselves as copyright holders of any file they've
added or modified in some significant way. If I've added myself in
error somewhere, feel free to replace it with the appropriate copyright
holder instead.

Going forward, all new source files should include a license header.
2020-01-18 09:45:54 +01:00
Andreas Kling
aaaf04f393 LibGUI: Relayout GTextEditor on font change
Fixes #941.
2019-12-29 23:03:41 +01:00
Andreas Kling
aae54bdbde LibDraw: Add ColorRole::BaseText (to be painted on ColorRole::Base) 2019-12-24 22:01:32 +01:00
Andreas Kling
a79bac428b LibGUI+LibDraw: Add "Palette" concept for scoped color theming
GApplication now has a palette. This palette contains all the system
theme colors by default, and is inherited by a new top-level GWidget.
New child widgets inherit their parents palette.

It is possible to override the GApplication palette, and the palette
of any GWidget.

The Palette object contains a bunch of colors, each corresponding to
a ColorRole. Each role has a convenience getter as well.

Each GWidget now has a background_role() and foreground_role(), which
are then looked up in their current palette when painting. This means
that you no longer alter the background color of a widget by setting
it directly, rather you alter either its background role, or the
widget's palette.
2019-12-24 21:27:16 +01:00
Andreas Kling
b6eba388e3 LibDraw: Add Selection and SelectionText system theme colors 2019-12-24 12:13:49 +01:00
Andreas Kling
b25600a7ef LibGUI: Respect more theme colors in GTextEditor 2019-12-24 02:38:18 +01:00
Andreas Kling
7301db4f9a GTextEditor: Fix broken rendering of selection on wrapped lines
This logic broke when converting String::length() to return size_t.
2019-12-17 21:15:10 +01:00
Andreas Kling
fd5eb79d19 LibGUI: Make GMenu inherit from CObject
This is primarily to make it possible to pass a GMenu* where a CObject*
is expected.
2019-12-09 21:05:44 +01:00
Andreas Kling
6f4c380d95 AK: Use size_t for the length of strings
Using int was a mistake. This patch changes String, StringImpl,
StringView and StringBuilder to use size_t instead of int for lengths.
Obviously a lot of code needs to change as a result of this.
2019-12-09 17:51:21 +01:00
Sasan Hezarkhani
51262e7e2d GTextEditor: Clear current selection, if any, on set_document() 2019-12-03 12:51:27 +01:00
Sasan Hezarkhani
5c2ef01f7b LibGUI: Expose a function to clear GTextEditor selection 2019-12-03 12:51:27 +01:00
Andreas Kling
d27e5a77e7 GTextEditor: Don't assert is_readonly() in did_change()
This callback will be invoked when calling set_text() to set the
initial contents of a GTextEditor, and that's okay.
2019-11-30 19:11:31 +01:00
Andreas Kling
6f70238a32 GTextEditor: Fire the on_change hook on GTextDocument change 2019-11-30 18:55:07 +01:00
Andreas Kling
32be9941f4 GTextEditor: Implement Shift+Delete using RemoveTextCommand 2019-11-30 17:19:35 +01:00
Andreas Kling
990042c8ec GTextEditor: Implement the Delete key using RemoveTextCommand 2019-11-30 16:58:07 +01:00
Andreas Kling
00a91bb02c LibGUI: Consolidate and simplify commands used for insertion/removal
This patch adds InsertTextCommand and RemoveTextCommand.
These two commands are used to ... insert and remove text :^)

The bulk of the logic is moved into GTextDocument, and we now use the
command's redo() virtual to perform the action. Or in other words, when
you type into the text editor, we create an InsertTextCommand, push it
onto the undo stack, and call redo() on it immediately. That's how the
text gets inserted.

This makes it quite easy to implement more commands, as there is no
distinction between a redo() and the initial application.
2019-11-30 16:54:05 +01:00
Andreas Kling
ee8773c586 LibGUI: Move the undo stack from GTextEditor to GTextDocument
Since the same document can be edited by multiple editors, we need to
keep the undo stack with the document for coherency.
2019-11-30 13:05:17 +01:00
Andreas Kling
fc14bdd442 LibGUI: Don't recompute line-wrapping over and over during set_text()
This makes the TextEditor start up fast for large files again.
2019-11-23 17:41:14 +01:00
Andreas Kling
c8e02e60a6 HackStudio+LibGUI: Implement matching curly brace highlighting
This works for C++ syntax highlighted text documents by caching the C++
token type in a new "arbitrary data" member of GTextDocumentSpan.

When the cursor is placed immediately before a '{' or immediately after
a '}', we highlight both of these brace buddies by changing their
corresponding spans to have a different background color.

..and spans can also now have a custom background color. :^)
2019-11-18 19:10:06 +01:00
Andreas Kling
57f7009b9e GTextEditor: Allow GTextDocumentSpans to be "skippable"
Setting the is_skippable flag on a GTextDocumentSpan will now cause the
cursor to skip over that span when moving with Ctrl+Left/Right.
2019-11-15 21:03:15 +01:00
Andreas Kling
27a30fdc2a GTextEditor: Allow moving the cursor span-wise with Ctrl+Left/Right
This allows you to move token by token when using HackStudio to edit
a C++ file.

Fixes #767.
2019-11-15 21:02:24 +01:00
ctfloyd
a3520bfdfd GTextEditor: Alt+Shift+S alphabetically sorts selected lines 2019-11-15 21:01:12 +01:00
Andreas Kling
ca538b6cee LibGUI: Add a simple GWidget class registry/factory
You can now register a GWidget subclass with REGISTER_GWIDGET(class)
and it will be available for factory construction through the new
GWidgetClassRegistration interface.

To obtain a GWidgetClassRegistration for a given class name, you call
GWidgetClassRegistration::find(class_name). You can also iterate over
all the registered classes using GWCR::for_each(callback).

This will be very useful for implementing a proper GUI designer, and
also in the future for things like script bindings.

NOTE: All of the registrations are done in GWidget.cpp at the moment
since I ran into trouble with the fricken linker pruning the global
constructors this mechanism relies on. :^)
2019-11-10 12:57:37 +01:00
Rhin
503fe37eaa TextEditor: Enable/disable undo & redo buttons based on availability (#740) 2019-11-09 08:50:39 +01:00
Andreas Kling
fa77a57257 GTextEditor: Allow moving the selected line(s) up/down in bulk
You can now press Ctrl+Shift+Up/Down in a GTextEditor and the currently
selected line(s) will all move together one step up/down.

If there is no selection, we move the line with the cursor on it. :^)
2019-11-08 20:14:42 +01:00
Andreas Kling
c16b1a515e GTextEditor: Add a way to flush any pending on_change notifications
Since on_change handlers can alter the text document we're working on,
we have to make sure they've been run before we try looking at spans.
This fixes some flakiness when a paint happened before HackStudio had
a chance to re-highlight some C++ while editing it.

The design where clients of GTextEditor perform syntax highlighting in
the "arbitrary code execution" on_change callback is not very good.
We should find a way to move highlighting closer to the editor.
2019-11-08 19:51:10 +01:00
rhin123
96c1e36ed3 TextEditor: Added redo functionality & proper stack manipulation
Added redo functionality & added m_undo_stack_index that moves back &
forth on the stack depending on the undo's & redo's.
2019-11-07 22:29:59 +01:00
Andreas Kling
f5c2ae1192 GTextEditor: Move the cursor to column 0 after deleting a whole line 2019-11-04 12:36:10 +01:00
rhin123
9e608885d1 TextEditor: Added undo functionality
Created a stack where a vector of undo actions are stored.
2019-11-03 20:21:14 +01:00
Andreas Kling
b8bf998b61 LibGUI: Move text search functions from GTextEditor to GTextDocument
Also add a find_all() that retuns a Vector<GTextRange> and simply does
a find_next() loop, returning all the matching ranges.
2019-11-01 21:31:06 +01:00
Andreas Kling
bddba567b3 LibGUI: Add GTextDocument::text_in_range(GTextRange)
This function returns a String containing the text in a given range.
GTextEditor::selected_text() is now just a wrapper around this.
2019-10-30 20:28:44 +01:00
Andreas Kling
9b13a3905b LibGUI: Support multiple GTextEditors editing the same GTextDocument
With this patch, you can now assign the same GTextDocument to multiple
GTextEditor widgets via GTextEditor::set_document().

The editors have independent cursors and selection, but all changes
are shared, and immediately propagate to all editors.

This is very unoptimized and will do lots of unnecessary invalidation,
especially line re-wrapping and repainting over and over again.
2019-10-27 19:36:59 +01:00
Andreas Kling
f96c683543 LibGUI: Move visual line metadata from GTextDocument to GTextEditor
This patch decouples GTextDocument and GTextDocumentLine from the line
wrapping functionality of GTextEditor.

This should basically make it possible to have multiple GTextEditors
editing the same GTextDocument. Of course, that will require a bit more
work since there's no paint invalidation yet.
2019-10-27 18:00:07 +01:00
Andreas Kling
f1c6193d6d LibGUI: Move GTextDocument out of GTextEditor
The idea here is to decouple the document from the editor widget so you
could have multiple editors being views onto the same document.

This doesn't work yet, since the document and editor are coupled in
various ways still (including a per-line back-pointer to the editor.)
2019-10-27 16:44:16 +01:00
Andreas Kling
db5178fb8f GTextEditor: Double-clicking on a span should select the span
This makes double-clicking on a C++ token in HackStudio select the
whole token, which is pretty nice. It's not perfect in all cases,
but a lot nicer than just expanding until we hit whitespace. :^)
2019-10-27 11:18:19 +01:00
Andreas Kling
8fa466e496 GTextEditor: Backspace over soft tabs
This makes the backspace erase backwards until the next soft tab stop.
We currently always use 4 as the soft tab width, but I suppose we could
make it configurable at some point. :^)
2019-10-27 10:42:48 +01:00
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