This patch removes size policies and preferred sizes, and replaces them
with min-size and max-size for each widget.
Box layout now works in 3 passes:
1) Set all items (widgets/spacers) to their min-size
2) Distribute remaining space evenly, respecting max-size
3) Place widgets one after the other, adding spacing in between
I've also added convenience helpers for setting a fixed size (which is
the same as setting min-size and max-size to the same value.)
This significantly reduces the verbosity of widget layout and makes GML
a bit more pleasant to write, too. :^)
Calling the file MainWindow.gml (and subsequently using MainWindowGML.h
for the generated file's name) suggests that's possible for every
application, but having a second one anywhere results in the following
CMake error:
add_custom_target cannot create target "generate_MainWindowGML.h"
because another target with the same name already exists. The
existing target is a custom target created in source directory [...]
It's now also more consistent with the other applications already using
GML, namely "BrowserWindow.gml" and "FileManagerWindow.gml".
This patch replaces the UI-from-JSON mechanism with a more
human-friendly DSL.
The current implementation simply converts the GML into a JSON object
that can be consumed by GUI::Widget::load_from_json(). The parser is
not very helpful if you make a mistake.
The language offers a very simple way to instantiate any registered
Core::Object class by simply saying @ClassName
@GUI::Label {
text: "Hello friends!"
tooltip: ":^)"
}
Layouts are Core::Objects and can be assigned to the "layout" property:
@GUI::Widget {
layout: @GUI::VerticalBoxLayout {
spacing: 2
margins: [8, 8, 8, 8]
}
}
And finally, child objects are simply nested within their parent:
@GUI::Widget {
layout: @GUI::HorizontalBoxLayout {
}
@GUI::Button {
text: "OK"
}
@GUI::Button {
text: "Cancel"
}
}
This feels a *lot* more pleasant to write than the JSON we had. The fact
that no new code was being written with the JSON mechanism was pretty
telling, so let's approach this with developer convenience in mind. :^)
The qualified name of a font is "<Family> <Size> <Weight>". You can
get the QN of a Font via the Font::qualified_name() API, and you can
get any system font by QN from the GUI::FontDatabase. :^)
This is our first client of the new JSON GUI declaration thingy.
The skeleton of the TextEditor app GUI is now declared separately from
the C++ logic, and we use the Core::Object::name() of widgets to locate
them once they have been instantiated by the GUI builder.
The move constructor of a lambda just copies it anyway.
Even if the first move() left an 'empty' closure behind, then
'm_editor->on_cursor_change' would only be able to see an empty
closure, which is certainly not what was intended.
So far, clicking on a link from the Markdown/HTML preview Web::PageView did
nothing - now we pass that link to Desktop::Launcher, which will then
open it in Browser, FileManager, another TextEditor instance etc.
Since the vast majority of message boxes should be modal, require
the parent window to be passed in, which can be nullptr for the
rare case that they don't. By it being the first argument, the
default arguments also don't need to be explicitly stated in most
cases, and it encourages passing in a parent window handle.
Fix up several message boxes that should have been modal.
This patch adds a PreviewMode enum with the following values:
- None
- Markdown
- HTML
This makes it a bit more logical to implement exclusive behavior.
During app teardown, the Application object may be destroyed before
something else, and so having Application::the() return a reference was
obscuring the truth about its lifetime.
This patch makes the API more honest by returning a pointer. While
this makes call sites look a bit more sketchy, do note that the global
Application pointer only becomes null during app teardown.
Attempting to open a non-existent file from the command line should not
fail, it should just open a new text document with that name. Note that
the file is not created until you actually save it.
And move canonicalized_path() to a static method on LexicalPath.
This is to make it clear that FileSystemPath/canonicalized_path() only
perform *lexical* canonicalization.
This works by hooking into the change notifications from the TextEditor
widget and parsing the document content as markdown, and generating an
HTML document from it which is displayed using LibWeb.
This will make it a bit easier to write man pages! :^)
This patch adds GUI::Action::create_checkable() helpers that work just
like the existing create() helpers, but the actions become checkable(!)
Clients are no longer required to manage the checked state of their
actions manually, but instead they will be checked/unchecked as needed
by GUI::Action itself before the activation hook is fired.
This allows us to construct menus in a more natural way:
auto& file_menu = menubar->add_menu("File");
file_menu.add_action(...);
Instead of the old way:
auto file_menu = GUI::Menu::construct();
file_menu->add_action(...);
menubar->add_menu(file_menu);