18#include <gdkmm/cursor.h>
19#include <gdkmm/general.h>
20#include <gtkmm/drawingarea.h>
21#include <gtkmm/eventcontrollerkey.h>
22#include <gtkmm/eventcontrollermotion.h>
23#include <gtkmm/gestureclick.h>
24#include <gtkmm/window.h>
25#include <sigc++/functors/mem_fun.h>
52 Glib::ObjectBase{
"GradientWithStops"},
62 set_name(
"GradientEdit");
66 auto const click = Gtk::GestureClick::create();
70 add_controller(click);
72 auto const motion = Gtk::EventControllerMotion::create();
74 add_controller(motion);
76 auto const key = Gtk::EventControllerKey::create();
96 set_sensitive(gradient !=
nullptr);
125 if (
auto wnd =
dynamic_cast<Gtk::Window*
>(this->get_root())) {
147 auto pos = [&](
double offset) {
return round(layout.
x + layout.
width * CLAMP(
offset, 0, 1)); };
157 left = round((left + prev) / 2);
162 if (
index + 1 < v.size()) {
167 right = round((right + next) / 2);
183 const auto half_stop = round((stop_width + 1) / 2);
184 const auto x = half_stop;
185 const double width = get_width() - stop_width;
186 const double height = get_height();
204 for (
size_t i = 0; i < v.size(); ++i) {
206 if (x >= pos.left && x <= pos.right && y >= pos.top && y <= pos.bottom) {
207 return static_cast<int>(i);
219 auto index =
static_cast<size_t>(maybe_index);
223 if (
index < v.size()) {
228 std::vector<double> offsets;
229 offsets.reserve(v.size());
231 offsets.push_back(s.offset);
233 std::sort(offsets.begin(), offsets.end());
237 max = offsets[
index + 1];
239 else if (
index + 1 == v.size()) {
240 min = offsets[
index - 1];
244 min = offsets[
index - 1];
245 max = offsets[
index + 1];
258 if (!(
direction == Gtk::DirectionType::TAB_FORWARD ||
direction == Gtk::DirectionType::TAB_BACKWARD)) {
262 auto const backward =
direction == Gtk::DirectionType::TAB_BACKWARD;
263 auto const n_stops =
_stops.size();
268 if (!(new_stop >= 0 && new_stop < n_stops)) {
296 case GDK_KEY_KP_Left:
301 case GDK_KEY_KP_Right:
305 case GDK_KEY_BackSpace:
338 if (limits.min_offset < limits.max_offset) {
349 }
else if (n_press == 2) {
352 if (
index >= 0)
return;
355 if (layout.width > 0 && x > layout.x && x < layout.x + layout.width) {
356 auto const position = (x - layout.x) / layout.width;
372 if (layout.width > 0) {
374 if (limits.min_offset < limits.max_offset) {
375 auto new_offset = CLAMP(limits.offset + offset_shift, limits.min_offset, limits.max_offset);
376 if (new_offset != limits.offset) {
391 if (layout.width > 0) {
392 auto delta =
dx / layout.width;
394 if (limits.min_offset < limits.max_offset) {
395 auto new_offset = CLAMP(
_stop_offset +
delta, limits.min_offset, limits.max_offset);
404Glib::RefPtr<Gdk::Cursor>
const *
427 if (cursor !=
nullptr) {
439 const double scale = get_scale_factor();
442 if (layout.width <= 0)
return;
452 cr->begin_new_path();
454 auto const fg = get_color();
464 for (
size_t i = 0; i <
_stops.size(); ++i) {
465 const auto& stop =
_stops[i];
472 const auto is_selected =
_focused_stop ==
static_cast<int>(i);
479 g_warning(
"Rendering gradient stop failed.");
486 if (is_selected && tip) {
491 Gdk::Cairo::set_source_pixbuf(cr, tip, round(pos.tip *
scale - tip->get_width() / 2),
499 cr->rectangle(pos.left, layout.y, pos.right - pos.left, layout.height);
504 Gdk::Cairo::set_source_pixbuf(cr, pix, round(pos.tip *
scale - pix->get_width() / 2),
Cairo integration helpers.
double get_width_px() const
double get_height_px() const
size_t set_style(const Glib::ustring &selector, const char *name, const Glib::ustring &value)
Glib::RefPtr< Gdk::Pixbuf > render(double scale)
SPObject is an abstract base class of all of the document nodes at the SVG document level.
sigc::connection connectRelease(sigc::slot< void(SPObject *)> slot)
Connects to the release request signal.
sigc::connection connectModified(sigc::slot< void(SPObject *, unsigned int)> slot)
Connects to the modification notification signal.
SPStop * getNextStop()
Virtual write: write object attributes to repr.
Inkscape::Colors::Color getColor() const
Utilities to more easily use Gtk::EventController & subclasses like Gesture.
Utility functions to convert ascii representations to numbers.
static constexpr int GRADIENT_IMAGE_HEIGHT
Gradient image widget with stop handles.
std::string get_filename(Type type, char const *filename, bool localized, bool silent)
bool has_flag(Gdk::ModifierType const state, Gdk::ModifierType const flags)
Helper to query if ModifierType state contains one or more of given flag(s).
static Geom::Point direction(Geom::Point const &first, Geom::Point const &second)
Computes an unit vector of the direction from first to second control point.
std::string format_number(double val, unsigned int precision=3)
void draw_gradient(const Cairo::RefPtr< Cairo::Context > &cr, SPGradient *gradient, int x, int width)
Renders a preview of a gradient into the passed context.
static cairo_user_data_key_t key
Inkscape::IO::Resource - simple resource API.
TODO: insert short description here.
Gdk::RGBA get_color_with_class(Gtk::Widget &widget, Glib::ustring const &css_class)
Glib::ustring gdk_to_css_color(const Gdk::RGBA &color)
These GUI related color conversions allow us to convert from SVG xml attributes to Gdk colors,...