diff --git a/src/ui/clipboard.cpp b/src/ui/clipboard.cpp
index 081fbba64c100f9b0900d9a47abf89cd17b1b199..7e41006bec7832908135b1423526b39a18d97e12 100644 (file)
--- a/src/ui/clipboard.cpp
+++ b/src/ui/clipboard.cpp
Inkscape::XML::Node *_clipnode; ///< The node that holds extra information
Inkscape::XML::Document *_doc; ///< Reference to the clipboard's Inkscape::XML::Document
+ // we need a way to copy plain text AND remember its style;
+ // the standard _clipnode is only available in an SVG tree, hence this special storage
+ SPCSSAttr *_text_style; ///< Style copied along with plain text fragment
+
Glib::RefPtr<Gtk::Clipboard> _clipboard; ///< Handle to the system wide clipboard - for convenience
std::list<Glib::ustring> _preferred_targets; ///< List of supported clipboard targets
};
_root(NULL),
_clipnode(NULL),
_doc(NULL),
+ _text_style(NULL),
_clipboard( Gtk::Clipboard::get() )
{
// push supported clipboard targets, in order of preference
if (desktop->event_context->get_drag()) {
GrDrag *drag = desktop->event_context->get_drag();
if (drag->hasSelection()) {
- _setClipboardColor(drag->getColor());
+ guint32 col = drag->getColor();
+
+ // set the color as clipboard content (text in RRGGBBAA format)
+ _setClipboardColor(col);
+
+ // create a style with this color on fill and opacity in master opacity, so it can be
+ // pasted on other stops or objects
+ if (_text_style) {
+ sp_repr_css_attr_unref(_text_style);
+ _text_style = NULL;
+ }
+ _text_style = sp_repr_css_attr_new();
+ // print and set properties
+ gchar color_str[16];
+ g_snprintf(color_str, 16, "#%06x", col >> 8);
+ sp_repr_css_set_property(_text_style, "fill", color_str);
+ float opacity = SP_RGBA32_A_F(col);
+ if (opacity > 1.0) opacity = 1.0; // safeguard
+ Inkscape::CSSOStringStream opcss;
+ opcss << opacity;
+ sp_repr_css_set_property(_text_style, "opacity", opcss.str().data());
+
_discardInternalClipboard();
return;
}
}
// Special case for when the text tool is active - if some text is selected, copy plain text,
- // not the object that holds it
+ // not the object that holds it; also copy the style at cursor into
if (tools_isactive(desktop, TOOLS_TEXT)) {
+ _discardInternalClipboard();
Glib::ustring selected_text = sp_text_get_selected_text(desktop->event_context);
if (!selected_text.empty()) {
_clipboard->set_text(selected_text);
- _discardInternalClipboard();
- return;
}
+ if (_text_style) {
+ sp_repr_css_attr_unref(_text_style);
+ _text_style = NULL;
+ }
+ _text_style = sp_text_get_style_at_cursor(desktop->event_context);
+ return;
}
if (selection->isEmpty()) { // check whether something is selected
return NULL;
Inkscape::XML::Node *ch = sp_repr_children(root);
- while (ch != NULL &&
+ while (ch != NULL &&
strcmp(ch->name(), "svg:g") &&
strcmp(ch->name(), "svg:path") &&
strcmp(ch->name(), "svg:use") &&
SPDocument *tempdoc = _retrieveClipboard("image/x-inkscape-svg");
if ( tempdoc == NULL ) {
- _userWarn(desktop, _("No style on the clipboard."));
- return false;
+ // no document, but we can try _text_style
+ if (_text_style) {
+ sp_desktop_set_style(desktop, _text_style);
+ return true;
+ } else {
+ _userWarn(desktop, _("No style on the clipboard."));
+ return false;
+ }
}
Inkscape::XML::Node
Inkscape::XML::Node *obj_copy = _copyNode(obj, target_xmldoc, target_parent);
pasted_objects = g_slist_prepend(pasted_objects, (gpointer) obj_copy);
}
-
+
// Change the selection to the freshly pasted objects
Inkscape::Selection *selection = sp_desktop_selection(desktop);
selection->setReprList(pasted_objects);
-
+
// invers apply parent transform
Geom::Matrix doc2parent = sp_item_i2doc_affine(SP_ITEM(desktop->currentLayer())).inverse();
- sp_selection_apply_affine(selection, doc2parent);
-
+ sp_selection_apply_affine(selection, desktop->dt2doc() * doc2parent * desktop->doc2dt(), true, false);
+
// Update (among other things) all curves in paths, for bounds() to work
sp_document_ensure_up_to_date(target_document);
if (clipnode) {
Geom::Point min, max;
sp_repr_get_point(clipnode, "min", &min);
- sp_repr_get_point(clipnode, "max", &max);
+ sp_repr_get_point(clipnode, "max", &max);
pos_original = Geom::Point(min[Geom::X], max[Geom::Y]);
}
Geom::Point offset = pos_original - sel_bbox->corner(3);
-
+
if (!in_place) {
SnapManager &m = desktop->namedview->snap_manager;
m.setup(desktop, false); // Don't display the snapindicator
-
+
// get offset from mouse pointer to bbox center, snap to grid if enabled
Geom::Point mouse_offset = desktop->point() - sel_bbox->midpoint();
offset = m.multipleOfGridPitch(mouse_offset - offset) + offset;
sp_selection_move_relative(selection, offset);
}
-
+
g_slist_free(pasted_objects);
}
Inkscape::XML::Document *target_xmldoc = sp_document_repr_doc(target_document);
prevent_id_clashes(clipdoc, target_document);
-
+
for (Inkscape::XML::Node *def = defs->firstChild() ; def ; def = def->next()) {
_copyNode(def, target_xmldoc, target_defs);
}
_clipnode = _doc->createElement("inkscape:clipboard");
_root->appendChild(_clipnode);
Inkscape::GC::release(_clipnode);
+
+ // once we create a SVG document, style will be stored in it, so flush _text_style
+ if (_text_style) {
+ sp_repr_css_attr_unref(_text_style);
+ _text_style = NULL;
+ }
}
}
format = EnumClipboardFormats(format);
}
CloseClipboard();
-
+
if (format == CF_ENHMETAFILE)
return CLIPBOARD_WIN32_EMF_TARGET;
if (format == CF_DIB || format == CF_BITMAP)
return CLIPBOARD_GDK_PIXBUF_TARGET;
}
-
+
if (IsClipboardFormatAvailable(CF_ENHMETAFILE))
return CLIPBOARD_WIN32_EMF_TARGET;
#endif