Skip to content

Week 10 recap GSoC 2025 - Reposition Toolbar on Initial Selection

Monday, 11 August 2025  |  Ross Rosales (rossr)

Intro

Last week, I added canvas limitations to keep the Selection Action Bar within a user's view. This week, I focused on positioning the toolbar so it renders directly underneath the initial selection instead of a hard coded value on the canvas. This change improves the user experience by reducing mouse travel and making the toolbar feel more intentional and intuitive to use.

Side note: This week I also added 2 buttons: 'Fill with Color' and 'Crop to Selection'.

Obstacles to Implementation

The first step to render the Selection Action Bar under the selection was to find the selection's coordinates.

Mapping Coordinates

The difficulty and learning opportunity I found during this process was understanding the difference between the image space and the canvas space. To keep it simple, selections live in the image space and the Selection Action Bar lives in the canvas space. Due to zooming in and out, different resolutions, and resizing, coordinates in the image space are not always equal to the canvas space. So to translate/map the coordinates of the selection to match where the toolbar should render, we can use KisCoordinatesConverter to translate these coordinates from image space to canvas space.

// get current selection
KisSelectionSP selection = d->m_viewManager->selection();

// get coordinates of current selection
QRectF selectionBounds = selection->selectedRect();
int selectionBottom = selectionBounds.bottom();
QPointF selectionCenter = selectionBounds.center();
QPointF bottomCenter(selectionCenter.x(), selectionBottom);

// translate the selection coordinates to the canvas widget space
QPointF widgetBottomCenter = converter->imageToWidget(bottomCenter);

// adjust/center/space how the toolbar renders under the selection
widgetBottomCenter.setX(widgetBottomCenter.x() - (d->actionBarWidth / 2)); 
widgetBottomCenter.setY(widgetBottomCenter.y() + d->bufferSpace);

// update the relative position of the toolbar
d->dragRectPosition = widgetBottomCenter.toPoint();

Conclusion

With these improvements, the UI now feels user friendly and intentional. For the next (and final) 2 weeks of GSoC, I plan to organize my documentation to build out a technical page on Krita's official documentation website and to refactor some code for better maintainability.

Contact

To anyone reading this, please feel free to reach out to me. I'm always open to suggestions and thoughts on how to improve as a developer and as a person. Email: ross.erosales@gmail.com Matrix: @rossr:matrix.org