23#include <glibmm/fileutils.h>
24#include <glibmm/i18n.h>
25#include <glibmm/main.h>
26#include <gtkmm/button.h>
27#include <gtkmm/checkbutton.h>
28#include <gtkmm/flowbox.h>
29#include <gtkmm/grid.h>
30#include <gtkmm/image.h>
31#include <gtkmm/label.h>
32#include <gtkmm/menubutton.h>
33#include <gtkmm/picture.h>
34#include <gtkmm/spinbutton.h>
35#include <gtkmm/togglebutton.h>
36#include <gtkmm/window.h>
49#define noTIMING_INFO 1;
62 width *= device_scale;
69 cairo_set_line_width(ctx, 1.0 * device_scale);
72 cairo_surface_set_device_scale(
surface, device_scale, device_scale);
83 return value ? value :
"";
88 return strtod(val.c_str(),
nullptr);
92 Glib::ObjectBase{
"MarkerComboBox"},
95 _combo_id(
std::move(id)),
105 _scale_with_stroke(
get_widget<
Gtk::CheckButton>(_builder,
"scale-with-stroke")),
106 _menu_btn(
get_widget<
Gtk::MenuButton>(_builder,
"menu-btn")),
111 _orient_auto_rev(
get_widget<
Gtk::ToggleButton>(_builder,
"orient-auto-rev")),
112 _orient_auto(
get_widget<
Gtk::ToggleButton>(_builder,
"orient-auto")),
113 _orient_angle(
get_widget<
Gtk::ToggleButton>(_builder,
"orient-angle")),
115 _current_img(
get_widget<
Gtk::Image>(_builder,
"current-img")),
122 auto device_scale = get_scale_factor();
142 image->set_visible(
true);
143 auto const box = Gtk::make_managed<Gtk::FlowBoxChild>();
144 box->set_child(*
image);
145 if (
item->separator) {
146 image->set_sensitive(
false);
147 image->set_focusable(
false);
148 image->set_size_request(-1, 10);
149 box->set_sensitive(
false);
150 box->set_focusable(
false);
151 box->add_css_class(
"marker-separator");
154 box->add_css_class(
"marker-item-box");
157 box->set_size_request(
item->width,
item->height);
160 box->set_focusable(
false);
168 _marker_list.signal_selected_children_changed().connect([=](){
175 _marker_list.signal_child_activated().connect([=](Gtk::FlowBoxChild* box){
179 auto set_orient = [=](
bool enable_angle,
const char* value) {
184 _orient_auto_rev.signal_toggled().connect([=](){ set_orient(
false,
"auto-start-reverse"); });
185 _orient_auto.signal_toggled().connect([=]() { set_orient(
false,
"auto"); });
189 _angle_btn.signal_value_changed().connect([=]() {
194 auto set_scale = [=](
bool changeWidth) {
221 auto idle_set_scale = [=](
bool changeWidth) {
225 _idle = Glib::signal_idle().connect([=](){
227 if (marker == orig_marker) {
228 set_scale(changeWidth);
243 _scale_x.signal_value_changed().connect([=]() { idle_set_scale(
true); });
244 _scale_y.signal_value_changed().connect([=]() { idle_set_scale(
false); });
251 auto set_offset = [=](){
255 _offset_x.signal_value_changed().connect([=]() { set_offset(); });
256 _offset_y.signal_value_changed().connect([=]() { set_offset(); });
275 auto units =
get_attrib(marker,
"markerUnits");
277 auto aspect =
get_attrib(marker,
"preserveAspectRatio");
286 _angle_btn.set_value(strtod(orient.c_str(),
nullptr));
287 if (orient ==
"auto-start-reverse") {
291 else if (orient ==
"auto") {
313 Cairo::RefPtr<Cairo::Surface>
surface;
324 drawing.
setRoot(
_sandbox->getRoot()->invoke_show(drawing, visionkey, SP_ITEM_SHOW_DISPLAY));
326 auto alloc =
_preview.get_allocation();
335 _sandbox->getRoot()->invoke_hide(visionkey);
340 std::ostringstream ost;
341 ost <<
"<small>" << label.raw() <<
"</small>";
359 if (!document)
return nullptr;
362 if (!defs)
return nullptr;
365 if (is<SPMarker>(&
child)) {
366 auto marker = cast<SPMarker>(&
child);
367 auto id = marker->getId();
368 if (
id && marker_id ==
id) {
385 bool selected =
false;
388 if (
auto box =
dynamic_cast<Gtk::FlowBoxChild*
>(&widget)) {
390 if (*marker == *item) {
391 _marker_list.select_child(*box);
407 if (marker !=
nullptr) {
413 Glib::RefPtr<MarkerItem> marker_item;
427 auto empty = Glib::RefPtr<MarkerItem>();
429 if (sel.size() == 1) {
491 item->history =
false;
492 item->separator =
true;
494 item->
label = filler ?
"filler" :
"Separator";
497 auto device_scale = get_scale_factor();
499 item->pix = separator;
517 if (markers_doc ==
nullptr) {
538 auto sp_marker = cast<SPMarker>(marker);
548 auto id = marker ? marker->
getId() :
nullptr;
570 return std::string();
576 bool stockid =
item->stock;
578 std::string markurn = stockid ?
"urn:inkscape:marker:" +
item->
id :
item->
id;
579 auto mark = cast<SPMarker>(
get_stock_item(markurn.c_str(), stockid));
585 std::ostringstream ost;
586 ost <<
"url(#" <<
id <<
")";
590 mark->getRepr()->setAttribute(
"inkscape:collect",
"always");
634 for (
int i = 0; i < fillup; ++i) {
637 for (
int i = 0; i <
max; ++i) {
659 std::vector<SPMarker *> ml;
660 if (source ==
nullptr)
return ml;
668 if (is<SPMarker>(&
child)) {
669 auto marker = cast<SPMarker>(&
child);
670 ml.push_back(marker);
697 drawing.
setRoot(
_sandbox->getRoot()->invoke_show(drawing, visionkey, SP_ITEM_SHOW_DISPLAY));
703 item->history =
true;
704 item->separator =
false;
717 for (
auto i:marker_list) {
726 item->source = source;
732 item->stock = !history;
733 item->history = history;
745 _sandbox->getRoot()->invoke_hide(visionkey);
749auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(current_time - old_time);
750g_warning(
"%s render time for %d markers: %d ms", combo_id, (
int)marker_list.size(),
static_cast<int>(elapsed.count()));
759Cairo::RefPtr<Cairo::Surface>
763 std::optional<guint32> checkerboard_color;
768 int device_scale = get_scale_factor();
769 auto const fg = get_color();
771 drawing, checkerboard_color, no_clip,
scale, device_scale);
777 if (
auto wnd =
dynamic_cast<Gtk::Window*
>(this->get_root())) {
780 gint32(0xff * color.get_red()) << 24 |
781 gint32(0xff * color.get_green()) << 16 |
782 gint32(0xff * color.get_blue()) << 8 |
786 auto const color = get_color();
788 gint32(0xff * color.get_red()) << 24 |
789 gint32(0xff * color.get_green()) << 16 |
790 gint32(0xff * color.get_blue()) << 8 |
Bin: widget that can hold one child, useful as a base class of custom widgets.
Cairo::RefPtr< Cairo::ImageSurface > surface
Two-dimensional point with integer coordinates.
void setRoot(DrawingItem *root)
Interface for refcounted XML nodes.
virtual char const * attribute(char const *key) const =0
Get the string representation of a node's attribute.
Cairo::RefPtr< Cairo::ImageSurface > render_surface(double scale)
Typed SVG document implementation.
SPDefs * getDefs()
Return the main defs object for the document.
static SPDocument * createNewDoc(char const *filename, bool keepalive, bool make_new=false, SPDocument *parent=nullptr)
Fetches document from filename, or creates new, if NULL; public document appears in document list.
static unsigned int display_key_new(unsigned numkeys)
Allocates unique integer keys.
SPObject is an abstract base class of all of the document nodes at the SVG document level.
char const * label() const
Gets the author-visible label property for the object or a default if no label is defined.
char const * getId() const
Returns the objects current ID string.
Inkscape::XML::Node * getRepr()
Returns the XML representation of tree.
char const * getAttribute(char const *name) const
sigc::connection connectModified(sigc::slot< void(SPObject *, unsigned int)> slot)
Connects to the modification notification signal.
bool checkerboard(gint x, gint y, guint size)
struct _cairo_surface cairo_surface_t
std::unique_ptr< Magick::Image > image
static constexpr int ITEM_HEIGHT
static constexpr int ITEM_WIDTH
Combobox for selecting dash patterns - implementation.
MultiDegree< n > max(MultiDegree< n > const &p, MultiDegree< n > const &q)
Returns the maximal degree appearing in the two arguments for each variables.
std::string get_path_string(Domain domain, Type type, char const *filename, char const *extra)
std::string get_filename(Type type, char const *filename, bool localized, bool silent)
bool file_test(char const *utf8name, GFileTest test)
Button
helper to stop accidents on int vs gtkmm3's weak=typed enums, & looks nicer!
static void set_sensitive(Gtk::SearchEntry2 &entry, bool const sensitive)
W & get_widget(const Glib::RefPtr< Gtk::Builder > &builder, const char *id)
Gtk::Widget * for_each_child(Gtk::Widget &widget, Func &&func, bool const plus_self=false, bool const recurse=false, int const level=0)
Call Func with a reference to each child of parent, until it returns _break.
W & get_derived_widget(const Glib::RefPtr< Gtk::Builder > &builder, const char *id, Args &&... args)
Glib::RefPtr< Gtk::Builder > create_builder(const char *filename)
std::unique_ptr< SPDocument > ink_markers_preview_doc(const Glib::ustring &group_id)
Returns a new document containing default start, mid, and end markers.
Cairo::RefPtr< Cairo::Surface > create_marker_image(const Glib::ustring &group_id, SPDocument *_sandbox, Gdk::RGBA marker_color, Geom::IntPoint pixel_size, const char *mname, SPDocument *source, Inkscape::Drawing &drawing, std::optional< guint32 > checkerboard, bool no_clip, double scale, int device_scale)
Creates a copy of the marker named mname, determines its visible and renderable area in the bounding ...
time_t now()
parse current time from SOURCE_DATE_EPOCH environment variable
void cairo_line_to(cairo_t *cr, Geom::Point p1)
void cairo_move_to(cairo_t *cr, Geom::Point p1)
Inkscape::IO::Resource - simple resource API.
void sp_marker_set_orient(SPMarker *marker, const char *value)
void sp_marker_scale_with_stroke(SPMarker *marker, bool scale_with_stroke)
void sp_validate_marker(SPMarker *sp_marker, SPDocument *doc)
void sp_marker_set_offset(SPMarker *marker, double dx, double dy)
void sp_marker_set_uniform_scale(SPMarker *marker, bool uniform)
void sp_marker_set_size(SPMarker *marker, double sx, double sy)
void sp_marker_flip_horizontally(SPMarker *marker)
SPRoot: SVG <svg> implementation.
SPObject * get_stock_item(gchar const *urn, bool stock, SPDocument *stock_doc)
TODO: insert short description here.
void cairo_set_source_rgba(cairo_t *cr, colour c)
Glib::RefPtr< Gdk::Texture > to_texture(Cairo::RefPtr< Cairo::Surface > const &surface)
Convert an image surface in ARGB32 format to a texture.
Gdk::RGBA get_color_with_class(Gtk::Widget &widget, Glib::ustring const &css_class)