This is in preparation to support masking of Layers. We now distinguish
between the "display_bitmap" which will be the whole Layer with every
effect applied and the "content_bitmap" which contains the actual
unmodified pixels in the Layer.
This makes it consistent with `ImageViewer`, where `F` was unavailable
for use as a shortcut. A small change, but it's nice having the same
keyboard shortcuts where we can :^)
We often want to zoom and fit the content of the widget into the
visible frame (or some rect within the frame), and it makes sense to
move this functionality into the AbstractZoomPanWidget to minimize
the amount of coordinate math derived classes need to do.
This commit moves the code that implements this functionality from
`PixelPaint::ImageEditor` into `AbstractZoomPanWidget` so that we
can also use it for other applications (such as ImageViewer!)
pledge_domains() that takes only one String argument was specifically
added as a shortcut for pledging a single domain. So, it makes sense to
use singular here.
Now that the GML formatter is both perserving comments and also mostly
agrees to the existing GML style, it can be used to auto-format all the
GML files in the system. This commit does not only contain the scripts
for running the formatting on CI and the pre-commit hook, but also
initially formats all the existing GML files so that the hook is
successfull.
The ImageEditor tracks whether it was loaded from an image
(the alternative being a project file.) If it was loaded from an image
file we redirect save project actions to save as instead.
Now while dragging a new rectangular selection you can cancel it by
hitting Escape. Existing selections are cleared by Escape as well if the
RectangularSelectTool is active.
This change unfortunately cannot be atomically made without a single
commit changing everything.
Most of the important changes are in LibIPC/Connection.cpp,
LibIPC/ServerConnection.cpp and LibCore/LocalServer.cpp.
The notable changes are:
- IPCCompiler now generates the decode and decode_message functions such
that they take a Core::Stream::LocalSocket instead of the socket fd.
- IPC::Decoder now uses the receive_fd method of LocalSocket instead of
doing system calls directly on the fd.
- IPC::ConnectionBase and related classes now use the Stream API
functions.
- IPC::ServerConnection no longer constructs the socket itself; instead,
a convenience macro, IPC_CLIENT_CONNECTION, is used in place of
C_OBJECT and will generate a static try_create factory function for
the ServerConnection subclass. The subclass is now responsible for
passing the socket constructed in this function to its
ServerConnection base; the socket is passed as the first argument to
the constructor (as a NonnullOwnPtr<Core::Stream::LocalServer>) before
any other arguments.
- The functionality regarding taking over sockets from SystemServer has
been moved to LibIPC/SystemServerTakeover.cpp. The Core::LocalSocket
implementation of this functionality hasn't been deleted due to my
intention of removing this class in the near future and to reduce
noise on this (already quite noisy) PR.
Using a WeakPtr to keep a reference to the active layer caused it to
be destroyed when the last tab was closed, which made the
m_layer == layer check in set_layer() return early since it was
already null. Because of this the LayerPropertiesWidget was never
disabled.
After closing the last open ImageEditor, selecting a color would try to
dereference it causing a crash. Instead make set_image_editor() take a
pointer to it and set it to nullptr when closing the last tab like we
do with LayerListWidget and LayerPropertiesWidget.
Now, each new filter only has to describe how to actually change
the bitmaps, and the common logic of pulling out the bitmap from the
layer, and marking the action as done, etc is all handled in the
`Filter` base class.
This also makes it possible to apply filters to external bitmaps,
which are not embedded in a `Layer` (which we can use to preview
filters in the future!)
Previously, we would clear it if there was still an editor open. This
was not obvious because it was only visible when an inactive tab was
closed, since closing an active tab would trigger an editor change
which would re-fill the layers widget.
This allows us to request any specific editor to close itself. Earlier,
this could only be done for the currently active editor, so trying to
close inactive tabs would not work properly.
Previously the save logic was hardcoded to only work for the active
editor, so closing editors in the background would not properly
handle the unsaved changes. This patch brings us closer to be able
to fix that problem.
The rotate clockwise/rotate counterclockwise actions can be added to
CommonActions since they are repeated in FontEditor, ImageViewer and
PixelPaint. This keeps the shortcuts and icons consistent across
applications.
This is just a slight variation of `/res/icons/16x16/paste.png`, I've
removed the lines on the paper to make it look consistent with the
"New Image" icon, which is an empty piece of paper.
I think this is likely the more common operation and makes more sense
in the toolbar. It calls the 'save as' action internally anyway if there
is no associated file.
Now, when trying to close the application, there is a separate prompt
for each open tab with unsaved changes. Each tab is closed after it is
handled appropriately (assuming the user didn't Cancel), this makes it
so that the message box is always asking about the currently active tab,
allowing the user to see that the image contains.
If at any point the user presses "Cancel", all remaining tabs are kept
open.