X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=src%2Ftext-context.cpp;h=c10e0d1a0f70846cb68d9f405f0795da0a3b2fa4;hb=8cd8b6ee0c2bd47add62310866479d49a2070057;hp=2a804dfbdd2cde68d74e061e399a20ca36676ab9;hpb=3da8c9f095f6e1d434809a58940f93585c58ebf3;p=inkscape.git diff --git a/src/text-context.cpp b/src/text-context.cpp index 2a804dfbd..c10e0d1a0 100644 --- a/src/text-context.cpp +++ b/src/text-context.cpp @@ -35,7 +35,6 @@ #include "desktop.h" #include "desktop-style.h" #include "desktop-handles.h" -#include "desktop-affine.h" #include "message-stack.h" #include "message-context.h" #include "pixmaps/cursor-text.xpm" @@ -44,12 +43,13 @@ #include "object-edit.h" #include "xml/repr.h" #include "xml/node-event-vector.h" -#include "prefs-utils.h" +#include "preferences.h" #include "rubberband.h" #include "sp-metrics.h" #include "context-fns.h" #include "verbs.h" - +#include "shape-editor.h" +#include "selection-chemistry.h" #include "text-editing.h" #include "text-context.h" @@ -131,13 +131,10 @@ sp_text_context_init(SPTextContext *tc) event_context->tolerance = 0; event_context->within_tolerance = false; - event_context->shape_repr = NULL; - event_context->shape_knot_holder = NULL; - tc->imc = NULL; tc->text = NULL; - tc->pdoc = NR::Point(0, 0); + tc->pdoc = Geom::Point(0, 0); new (&tc->text_sel_start) Inkscape::Text::Layout::iterator(); new (&tc->text_sel_end) Inkscape::Text::Layout::iterator(); new (&tc->text_selection_quads) std::vector(); @@ -171,6 +168,10 @@ sp_text_context_dispose(GObject *obj) tc->style_set_connection.~connection(); tc->sel_changed_connection.~connection(); tc->sel_modified_connection.~connection(); + + delete ec->shape_editor; + ec->shape_editor = NULL; + tc->text_sel_end.~iterator(); tc->text_sel_start.~iterator(); tc->text_selection_quads.~vector(); @@ -183,31 +184,21 @@ sp_text_context_dispose(GObject *obj) } Inkscape::Rubberband::get(ec->desktop)->stop(); - - if (ec->shape_knot_holder) { - delete ec->shape_knot_holder; - ec->shape_knot_holder = NULL; - } - if (ec->shape_repr) { // remove old listener - sp_repr_remove_listener_by_data(ec->shape_repr, ec); - Inkscape::GC::release(ec->shape_repr); - ec->shape_repr = 0; - } } -static Inkscape::XML::NodeEventVector ec_shape_repr_events = { - NULL, /* child_added */ - NULL, /* child_removed */ - ec_shape_event_attr_changed, - NULL, /* content_changed */ - NULL /* order_changed */ -}; - static void sp_text_context_setup(SPEventContext *ec) { SPTextContext *tc = SP_TEXT_CONTEXT(ec); SPDesktop *desktop = ec->desktop; + GtkSettings* settings = gtk_settings_get_default(); + gint timeout = 0; + g_object_get( settings, "gtk-cursor-blink-time", &timeout, NULL ); + if (timeout < 0) { + timeout = 200; + } else { + timeout /= 2; + } tc->cursor = sp_canvas_item_new(sp_desktop_controls(desktop), SP_TYPE_CTRLLINE, NULL); sp_ctrlline_set_coords(SP_CTRLLINE(tc->cursor), 100, 0, 100, 100); @@ -215,16 +206,16 @@ sp_text_context_setup(SPEventContext *ec) sp_canvas_item_hide(tc->cursor); tc->indicator = sp_canvas_item_new(sp_desktop_controls(desktop), SP_TYPE_CTRLRECT, NULL); - SP_CTRLRECT(tc->indicator)->setRectangle(NR::Rect(NR::Point(0, 0), NR::Point(100, 100))); + SP_CTRLRECT(tc->indicator)->setRectangle(Geom::Rect(Geom::Point(0, 0), Geom::Point(100, 100))); SP_CTRLRECT(tc->indicator)->setColor(0x0000ff7f, false, 0); sp_canvas_item_hide(tc->indicator); tc->frame = sp_canvas_item_new(sp_desktop_controls(desktop), SP_TYPE_CTRLRECT, NULL); - SP_CTRLRECT(tc->frame)->setRectangle(NR::Rect(NR::Point(0, 0), NR::Point(100, 100))); + SP_CTRLRECT(tc->frame)->setRectangle(Geom::Rect(Geom::Point(0, 0), Geom::Point(100, 100))); SP_CTRLRECT(tc->frame)->setColor(0x0000ff7f, false, 0); sp_canvas_item_hide(tc->frame); - tc->timeout = gtk_timeout_add(200, (GtkFunction) sp_text_context_timeout, ec); + tc->timeout = gtk_timeout_add(timeout, (GtkFunction) sp_text_context_timeout, ec); tc->imc = gtk_im_multicontext_new(); if (tc->imc) { @@ -251,15 +242,11 @@ sp_text_context_setup(SPEventContext *ec) if (((SPEventContextClass *) parent_class)->setup) ((SPEventContextClass *) parent_class)->setup(ec); + ec->shape_editor = new ShapeEditor(ec->desktop); + SPItem *item = sp_desktop_selection(ec->desktop)->singleItem(); if (item && SP_IS_FLOWTEXT (item) && SP_FLOWTEXT(item)->has_internal_frame()) { - ec->shape_knot_holder = sp_item_knot_holder(item, ec->desktop); - Inkscape::XML::Node *shape_repr = SP_OBJECT_REPR(SP_FLOWTEXT(item)->get_frame(NULL)); - if (shape_repr) { - ec->shape_repr = shape_repr; - Inkscape::GC::anchor(shape_repr); - sp_repr_add_listener(shape_repr, &ec_shape_repr_events, ec); - } + ec->shape_editor->set_item(item, SH_KNOTHOLDER); } tc->sel_changed_connection = sp_desktop_selection(desktop)->connectChanged( @@ -277,10 +264,11 @@ sp_text_context_setup(SPEventContext *ec) sp_text_context_selection_changed(sp_desktop_selection(desktop), tc); - if (prefs_get_int_attribute("tools.text", "selcue", 0) != 0) { + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + if (prefs->getBool("/tools/text/selcue")) { ec->enableSelectionCue(); } - if (prefs_get_int_attribute("tools.text", "gradientdrag", 0) != 0) { + if (prefs->getBool("/tools/text/gradientdrag")) { ec->enableGrDrag(); } } @@ -352,12 +340,12 @@ sp_text_context_item_handler(SPEventContext *event_context, SPItem *item, GdkEve case GDK_BUTTON_PRESS: if (event->button.button == 1 && !event_context->space_panning) { // find out clicked item, disregarding groups - item_ungrouped = desktop->item_at_point(NR::Point(event->button.x, event->button.y), TRUE); + item_ungrouped = desktop->item_at_point(Geom::Point(event->button.x, event->button.y), TRUE); if (SP_IS_TEXT(item_ungrouped) || SP_IS_FLOWTEXT(item_ungrouped)) { sp_desktop_selection(desktop)->set(item_ungrouped); if (tc->text) { // find out click point in document coordinates - NR::Point p = desktop->w2d(NR::Point(event->button.x, event->button.y)); + Geom::Point p = desktop->w2d(Geom::Point(event->button.x, event->button.y)); // set the cursor closest to that point tc->text_sel_start = tc->text_sel_end = sp_te_get_position_by_coords(tc->text, p); // update display @@ -397,6 +385,7 @@ sp_text_context_item_handler(SPEventContext *event_context, SPItem *item, GdkEve case GDK_BUTTON_RELEASE: if (event->button.button == 1 && tc->dragging && !event_context->space_panning) { tc->dragging = 0; + sp_event_context_discard_delayed_snap_event(event_context); ret = TRUE; } break; @@ -405,7 +394,7 @@ sp_text_context_item_handler(SPEventContext *event_context, SPItem *item, GdkEve Inkscape::Text::Layout const *layout = te_get_layout(tc->text); if (!layout) break; // find out click point in document coordinates - NR::Point p = desktop->w2d(NR::Point(event->button.x, event->button.y)); + Geom::Point p = desktop->w2d(Geom::Point(event->button.x, event->button.y)); // set the cursor closest to that point Inkscape::Text::Layout::iterator new_end = sp_te_get_position_by_coords(tc->text, p); if (tc->dragging == 2) { @@ -434,13 +423,20 @@ sp_text_context_item_handler(SPEventContext *event_context, SPItem *item, GdkEve break; } // find out item under mouse, disregarding groups - item_ungrouped = desktop->item_at_point(NR::Point(event->button.x, event->button.y), TRUE); + item_ungrouped = desktop->item_at_point(Geom::Point(event->button.x, event->button.y), TRUE); if (SP_IS_TEXT(item_ungrouped) || SP_IS_FLOWTEXT(item_ungrouped)) { - sp_canvas_item_show(tc->indicator); - boost::optional ibbox = sp_item_bbox_desktop(item_ungrouped); + + Inkscape::Text::Layout const *layout = te_get_layout(item_ungrouped); + if (layout->inputTruncated()) { + SP_CTRLRECT(tc->indicator)->setColor(0xff0000ff, false, 0); + } else { + SP_CTRLRECT(tc->indicator)->setColor(0x0000ff7f, false, 0); + } + Geom::OptRect ibbox = sp_item_bbox_desktop(item_ungrouped); if (ibbox) { SP_CTRLRECT(tc->indicator)->setRectangle(*ibbox); } + sp_canvas_item_show(tc->indicator); event_context->cursor_shape = cursor_text_insert_xpm; event_context->hot_x = 7; @@ -482,10 +478,10 @@ sp_text_context_setup_text(SPTextContext *tc) rtext->setAttribute("xml:space", "preserve"); // we preserve spaces in the text objects we create /* Set style */ - sp_desktop_apply_style_tool(SP_EVENT_CONTEXT_DESKTOP(ec), rtext, "tools.text", true); + sp_desktop_apply_style_tool(SP_EVENT_CONTEXT_DESKTOP(ec), rtext, "/tools/text", true); - sp_repr_set_svg_double(rtext, "x", tc->pdoc[NR::X]); - sp_repr_set_svg_double(rtext, "y", tc->pdoc[NR::Y]); + sp_repr_set_svg_double(rtext, "x", tc->pdoc[Geom::X]); + sp_repr_set_svg_double(rtext, "y", tc->pdoc[Geom::Y]); /* Create */ Inkscape::XML::Node *rtspan = xml_doc->createElement("svg:tspan"); @@ -502,7 +498,8 @@ sp_text_context_setup_text(SPTextContext *tc) /* yes, it's immediate .. why does it matter? */ sp_desktop_selection(ec->desktop)->set(text_item); Inkscape::GC::release(rtext); - text_item->transform = SP_ITEM(ec->desktop->currentRoot())->getRelativeTransform(ec->desktop->currentLayer()); + text_item->transform = sp_item_i2doc_affine(SP_ITEM(ec->desktop->currentLayer())).inverse(); + text_item->updateRepr(); sp_document_done(sp_desktop_document(ec->desktop), SP_VERB_CONTEXT_TEXT, _("Create text")); @@ -596,7 +593,8 @@ sp_text_context_root_handler(SPEventContext *const event_context, GdkEvent *cons sp_text_context_validate_cursor_iterators(tc); - event_context->tolerance = prefs_get_int_attribute_limited("options.dragtolerance", "value", 0, 0, 100); + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + event_context->tolerance = prefs->getIntLimited("/options/dragtolerance/value", 0, 0, 100); switch (event->type) { case GDK_BUTTON_PRESS: @@ -611,8 +609,15 @@ sp_text_context_root_handler(SPEventContext *const event_context, GdkEvent *cons event_context->yp = (gint) event->button.y; event_context->within_tolerance = true; - NR::Point const button_pt(event->button.x, event->button.y); - tc->p0 = desktop->w2d(button_pt); + Geom::Point const button_pt(event->button.x, event->button.y); + Geom::Point button_dt(desktop->w2d(button_pt)); + + SnapManager &m = desktop->namedview->snap_manager; + m.setup(desktop); + m.freeSnapReturnByRef(button_dt, Inkscape::SNAPSOURCE_NODE_HANDLE); + m.unSetup(); + + tc->p0 = button_dt; Inkscape::Rubberband::get(desktop)->start(desktop, tc->p0); sp_canvas_item_grab(SP_CANVAS_ITEM(desktop->acetate), GDK_KEY_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_BUTTON_PRESS_MASK | GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK, @@ -646,23 +651,44 @@ sp_text_context_root_handler(SPEventContext *const event_context, GdkEvent *cons // motion notify coordinates as given (no snapping back to origin) event_context->within_tolerance = false; - NR::Point const motion_pt(event->motion.x, event->motion.y); - NR::Point const p = desktop->w2d(motion_pt); + Geom::Point const motion_pt(event->motion.x, event->motion.y); + Geom::Point p = desktop->w2d(motion_pt); + + SnapManager &m = desktop->namedview->snap_manager; + m.setup(desktop); + m.freeSnapReturnByRef(p, Inkscape::SNAPSOURCE_NODE_HANDLE); + m.unSetup(); Inkscape::Rubberband::get(desktop)->move(p); gobble_motion_events(GDK_BUTTON1_MASK); // status text - GString *xs = SP_PX_TO_METRIC_STRING(fabs((p - tc->p0)[NR::X]), desktop->namedview->getDefaultMetric()); - GString *ys = SP_PX_TO_METRIC_STRING(fabs((p - tc->p0)[NR::Y]), desktop->namedview->getDefaultMetric()); + GString *xs = SP_PX_TO_METRIC_STRING(fabs((p - tc->p0)[Geom::X]), desktop->namedview->getDefaultMetric()); + GString *ys = SP_PX_TO_METRIC_STRING(fabs((p - tc->p0)[Geom::Y]), desktop->namedview->getDefaultMetric()); event_context->_message_context->setF(Inkscape::IMMEDIATE_MESSAGE, _("Flowed text frame: %s × %s"), xs->str, ys->str); g_string_free(xs, FALSE); g_string_free(ys, FALSE); + } else if (!sp_event_context_knot_mouseover(event_context)) { + SnapManager &m = desktop->namedview->snap_manager; + m.setup(desktop); + + Geom::Point const motion_w(event->motion.x, event->motion.y); + Geom::Point motion_dt(desktop->w2d(motion_w)); + m.preSnap(Inkscape::SnapCandidatePoint(motion_dt, Inkscape::SNAPSOURCE_NODE_HANDLE)); + m.unSetup(); } break; case GDK_BUTTON_RELEASE: if (event->button.button == 1 && !event_context->space_panning) { + sp_event_context_discard_delayed_snap_event(event_context); + + Geom::Point p1 = desktop->w2d(Geom::Point(event->button.x, event->button.y)); + + SnapManager &m = desktop->namedview->snap_manager; + m.setup(desktop); + m.freeSnapReturnByRef(p1, Inkscape::SNAPSOURCE_NODE_HANDLE); + m.unSetup(); if (tc->grabbed) { sp_canvas_item_ungrab(tc->grabbed, GDK_CURRENT_TIME); @@ -674,9 +700,7 @@ sp_text_context_root_handler(SPEventContext *const event_context, GdkEvent *cons if (tc->creating && event_context->within_tolerance) { /* Button 1, set X & Y & new item */ sp_desktop_selection(desktop)->clear(); - NR::Point dtp = desktop->w2d(NR::Point(event->button.x, event->button.y)); - tc->pdoc = sp_desktop_dt2root_xy_point(desktop, dtp); - + tc->pdoc = desktop->dt2doc(p1); tc->show = TRUE; tc->phase = 1; tc->nascent_object = 1; // new object was just created @@ -684,21 +708,19 @@ sp_text_context_root_handler(SPEventContext *const event_context, GdkEvent *cons /* Cursor */ sp_canvas_item_show(tc->cursor); // Cursor height is defined by the new text object's font size; it needs to be set - // articifically here, for the text object does not exist yet: + // artificially here, for the text object does not exist yet: double cursor_height = sp_desktop_get_font_size_tool(desktop); - sp_ctrlline_set_coords(SP_CTRLLINE(tc->cursor), dtp, dtp + NR::Point(0, cursor_height)); + sp_ctrlline_set_coords(SP_CTRLLINE(tc->cursor), p1, p1 + Geom::Point(0, cursor_height)); event_context->_message_context->set(Inkscape::NORMAL_MESSAGE, _("Type text; Enter to start new line.")); // FIXME:: this is a copy of a string from _update_cursor below, do not desync event_context->within_tolerance = false; } else if (tc->creating) { - NR::Point const button_pt(event->button.x, event->button.y); - NR::Point p1 = desktop->w2d(button_pt); double cursor_height = sp_desktop_get_font_size_tool(desktop); - if (fabs(p1[NR::Y] - tc->p0[NR::Y]) > cursor_height) { + if (fabs(p1[Geom::Y] - tc->p0[Geom::Y]) > cursor_height) { // otherwise even one line won't fit; most probably a slip of hand (even if bigger than tolerance) SPItem *ft = create_flowtext_with_internal_frame (desktop, tc->p0, p1); /* Set style */ - sp_desktop_apply_style_tool(desktop, SP_OBJECT_REPR(ft), "tools.text", true); + sp_desktop_apply_style_tool(desktop, SP_OBJECT_REPR(ft), "/tools/text", true); sp_desktop_selection(desktop)->set(ft); desktop->messageStack()->flash(Inkscape::NORMAL_MESSAGE, _("Flowed text is created.")); sp_document_done(sp_desktop_document(desktop), SP_VERB_CONTEXT_TEXT, @@ -815,8 +837,8 @@ sp_text_context_root_handler(SPEventContext *const event_context, GdkEvent *cons int screenlines = 1; if (tc->text) { double spacing = sp_te_get_average_linespacing(tc->text); - NR::Rect const d = desktop->get_display_area(); - screenlines = (int) floor(fabs(d.min()[NR::Y] - d.max()[NR::Y])/spacing) - 1; + Geom::Rect const d = desktop->get_display_area(); + screenlines = (int) floor(fabs(d.min()[Geom::Y] - d.max()[Geom::Y])/spacing) - 1; if (screenlines <= 0) screenlines = 1; } @@ -890,10 +912,10 @@ sp_text_context_root_handler(SPEventContext *const event_context, GdkEvent *cons if (MOD__CTRL_ONLY && tc->text) { SPStyle const *style = sp_te_style_at_position(tc->text, std::min(tc->text_sel_start, tc->text_sel_end)); SPCSSAttr *css = sp_repr_css_attr_new(); - if (style->font_style.computed == SP_CSS_FONT_STYLE_NORMAL) - sp_repr_css_set_property(css, "font-style", "italic"); - else + if (style->font_style.computed != SP_CSS_FONT_STYLE_NORMAL) sp_repr_css_set_property(css, "font-style", "normal"); + else + sp_repr_css_set_property(css, "font-style", "italic"); sp_te_apply_style(tc->text, tc->text_sel_start, tc->text_sel_end, css); sp_repr_css_attr_unref(css); sp_document_done(sp_desktop_document(desktop), SP_VERB_CONTEXT_TEXT, @@ -1012,15 +1034,15 @@ sp_text_context_root_handler(SPEventContext *const event_context, GdkEvent *cons gint mul = 1 + gobble_key_events( get_group0_keyval(&event->key), 0); // with any mask if (MOD__SHIFT) - sp_te_adjust_kerning_screen(tc->text, tc->text_sel_start, tc->text_sel_end, desktop, NR::Point(mul*-10, 0)); + sp_te_adjust_kerning_screen(tc->text, tc->text_sel_start, tc->text_sel_end, desktop, Geom::Point(mul*-10, 0)); else - sp_te_adjust_kerning_screen(tc->text, tc->text_sel_start, tc->text_sel_end, desktop, NR::Point(mul*-1, 0)); + sp_te_adjust_kerning_screen(tc->text, tc->text_sel_start, tc->text_sel_end, desktop, Geom::Point(mul*-1, 0)); sp_text_context_update_cursor(tc); sp_text_context_update_text_selection(tc); sp_document_maybe_done(sp_desktop_document(desktop), "kern:left", SP_VERB_CONTEXT_TEXT, _("Kern to the left")); } else { - if (MOD__CTRL) + if (MOD__CTRL) tc->text_sel_end.cursorLeftWithControl(); else tc->text_sel_end.cursorLeft(); @@ -1037,9 +1059,9 @@ sp_text_context_root_handler(SPEventContext *const event_context, GdkEvent *cons gint mul = 1 + gobble_key_events( get_group0_keyval(&event->key), 0); // with any mask if (MOD__SHIFT) - sp_te_adjust_kerning_screen(tc->text, tc->text_sel_start, tc->text_sel_end, desktop, NR::Point(mul*10, 0)); + sp_te_adjust_kerning_screen(tc->text, tc->text_sel_start, tc->text_sel_end, desktop, Geom::Point(mul*10, 0)); else - sp_te_adjust_kerning_screen(tc->text, tc->text_sel_start, tc->text_sel_end, desktop, NR::Point(mul*1, 0)); + sp_te_adjust_kerning_screen(tc->text, tc->text_sel_start, tc->text_sel_end, desktop, Geom::Point(mul*1, 0)); sp_text_context_update_cursor(tc); sp_text_context_update_text_selection(tc); sp_document_maybe_done(sp_desktop_document(desktop), "kern:right", SP_VERB_CONTEXT_TEXT, @@ -1062,9 +1084,9 @@ sp_text_context_root_handler(SPEventContext *const event_context, GdkEvent *cons gint mul = 1 + gobble_key_events( get_group0_keyval(&event->key), 0); // with any mask if (MOD__SHIFT) - sp_te_adjust_kerning_screen(tc->text, tc->text_sel_start, tc->text_sel_end, desktop, NR::Point(0, mul*-10)); + sp_te_adjust_kerning_screen(tc->text, tc->text_sel_start, tc->text_sel_end, desktop, Geom::Point(0, mul*-10)); else - sp_te_adjust_kerning_screen(tc->text, tc->text_sel_start, tc->text_sel_end, desktop, NR::Point(0, mul*-1)); + sp_te_adjust_kerning_screen(tc->text, tc->text_sel_start, tc->text_sel_end, desktop, Geom::Point(0, mul*-1)); sp_text_context_update_cursor(tc); sp_text_context_update_text_selection(tc); sp_document_maybe_done(sp_desktop_document(desktop), "kern:up", SP_VERB_CONTEXT_TEXT, @@ -1088,9 +1110,9 @@ sp_text_context_root_handler(SPEventContext *const event_context, GdkEvent *cons gint mul = 1 + gobble_key_events( get_group0_keyval(&event->key), 0); // with any mask if (MOD__SHIFT) - sp_te_adjust_kerning_screen(tc->text, tc->text_sel_start, tc->text_sel_end, desktop, NR::Point(0, mul*10)); + sp_te_adjust_kerning_screen(tc->text, tc->text_sel_start, tc->text_sel_end, desktop, Geom::Point(0, mul*10)); else - sp_te_adjust_kerning_screen(tc->text, tc->text_sel_start, tc->text_sel_end, desktop, NR::Point(0, mul*1)); + sp_te_adjust_kerning_screen(tc->text, tc->text_sel_start, tc->text_sel_end, desktop, Geom::Point(0, mul*1)); sp_text_context_update_cursor(tc); sp_text_context_update_text_selection(tc); sp_document_maybe_done(sp_desktop_document(desktop), "kern:down", SP_VERB_CONTEXT_TEXT, @@ -1285,6 +1307,9 @@ sp_text_context_root_handler(SPEventContext *const event_context, GdkEvent *cons } Inkscape::Rubberband::get(desktop)->stop(); } + } else if ((group0_keyval == GDK_x || group0_keyval == GDK_X) && MOD__ALT_ONLY) { + desktop->setToolboxFocusTo ("altx-text"); + return TRUE; } } break; @@ -1323,7 +1348,7 @@ sp_text_paste_inline(SPEventContext *ec) Glib::RefPtr refClipboard = Gtk::Clipboard::get(); Glib::ustring const clip_text = refClipboard->wait_for_text(); - + if (!clip_text.empty()) { // Fix for 244940 // The XML standard defines the following as valid characters @@ -1351,7 +1376,7 @@ sp_text_paste_inline(SPEventContext *ec) itr = text.erase(itr); } } - + if (!tc->text) { // create text if none (i.e. if nascent_object) sp_text_context_setup_text(tc); tc->nascent_object = 0; // we don't need it anymore, having created a real @@ -1396,6 +1421,21 @@ sp_text_get_selected_text(SPEventContext const *ec) return sp_te_get_string_multiline(tc->text, tc->text_sel_start, tc->text_sel_end); } +SPCSSAttr * +sp_text_get_style_at_cursor(SPEventContext const *ec) +{ + if (!SP_IS_TEXT_CONTEXT(ec)) + return NULL; + SPTextContext const *tc = SP_TEXT_CONTEXT(ec); + if (tc->text == NULL) + return NULL; + + SPObject const *obj = sp_te_object_at_position(tc->text, tc->text_sel_end); + if (obj) + return take_style_from_item((SPItem *) obj); + return NULL; +} + /** Deletes the currently selected characters. Returns false if there is no text selection currently. @@ -1438,26 +1478,10 @@ sp_text_context_selection_changed(Inkscape::Selection *selection, SPTextContext SPEventContext *ec = SP_EVENT_CONTEXT(tc); - if (ec->shape_knot_holder) { // destroy knotholder - delete ec->shape_knot_holder; - ec->shape_knot_holder = NULL; - } - - if (ec->shape_repr) { // remove old listener - sp_repr_remove_listener_by_data(ec->shape_repr, ec); - Inkscape::GC::release(ec->shape_repr); - ec->shape_repr = 0; - } - + ec->shape_editor->unset_item(SH_KNOTHOLDER); SPItem *item = selection->singleItem(); if (item && SP_IS_FLOWTEXT (item) && SP_FLOWTEXT(item)->has_internal_frame()) { - ec->shape_knot_holder = sp_item_knot_holder(item, ec->desktop); - Inkscape::XML::Node *shape_repr = SP_OBJECT_REPR(SP_FLOWTEXT(item)->get_frame(NULL)); - if (shape_repr) { - ec->shape_repr = shape_repr; - Inkscape::GC::anchor(shape_repr); - sp_repr_add_listener(shape_repr, &ec_shape_repr_events, ec); - } + ec->shape_editor->set_item(item, SH_KNOTHOLDER); } if (tc->text && (item != tc->text)) { @@ -1576,7 +1600,7 @@ sp_text_context_update_cursor(SPTextContext *tc, bool scroll_to_see) // scroll to show cursor if (scroll_to_see) { Geom::Point const center = SP_EVENT_CONTEXT(tc)->desktop->get_display_area().midpoint(); - if (NR::L2(d0 - center) > NR::L2(d1 - center)) + if (Geom::L2(d0 - center) > Geom::L2(d1 - center)) // unlike mouse moves, here we must scroll all the way at first shot, so we override the autoscrollspeed SP_EVENT_CONTEXT(tc)->desktop->scroll_to_point(d0, 1.0); else @@ -1595,18 +1619,32 @@ sp_text_context_update_cursor(SPTextContext *tc, bool scroll_to_see) tc->show = TRUE; tc->phase = 1; + Inkscape::Text::Layout const *layout = te_get_layout(tc->text); + int const nChars = layout->iteratorToCharIndex(layout->end()); + char const *trunc = ""; + bool truncated = false; + if (layout->inputTruncated()) { + truncated = true; + trunc = _(" [truncated]"); + } if (SP_IS_FLOWTEXT(tc->text)) { SPItem *frame = SP_FLOWTEXT(tc->text)->get_frame (NULL); // first frame only if (frame) { + if (truncated) { + SP_CTRLRECT(tc->frame)->setColor(0xff0000ff, false, 0); + } else { + SP_CTRLRECT(tc->frame)->setColor(0x0000ff7f, false, 0); + } sp_canvas_item_show(tc->frame); - boost::optional frame_bbox = sp_item_bbox_desktop(frame); + Geom::OptRect frame_bbox = sp_item_bbox_desktop(frame); if (frame_bbox) { SP_CTRLRECT(tc->frame)->setRectangle(*frame_bbox); } } - SP_EVENT_CONTEXT(tc)->_message_context->set(Inkscape::NORMAL_MESSAGE, _("Type flowed text; Enter to start new paragraph.")); + + SP_EVENT_CONTEXT(tc)->_message_context->setF(Inkscape::NORMAL_MESSAGE, _("Type or edit flowed text (%d characters%s); Enter to start new paragraph."), nChars, trunc); } else { - SP_EVENT_CONTEXT(tc)->_message_context->set(Inkscape::NORMAL_MESSAGE, _("Type text; Enter to start new line.")); + SP_EVENT_CONTEXT(tc)->_message_context->setF(Inkscape::NORMAL_MESSAGE, _("Type or edit text (%d characters%s); Enter to start new line."), nChars, trunc); } } else { @@ -1655,12 +1693,13 @@ static gint sp_text_context_timeout(SPTextContext *tc) { if (tc->show) { + sp_canvas_item_show(tc->cursor); if (tc->phase) { tc->phase = 0; - sp_canvas_item_hide(tc->cursor); + sp_ctrlline_set_rgba32(SP_CTRLLINE(tc->cursor), 0x000000ff); } else { tc->phase = 1; - sp_canvas_item_show(tc->cursor); + sp_ctrlline_set_rgba32(SP_CTRLLINE(tc->cursor), 0xffffffff); } } @@ -1726,6 +1765,29 @@ sptc_commit(GtkIMContext */*imc*/, gchar *string, SPTextContext *tc) _("Type text")); } +void +sp_text_context_place_cursor (SPTextContext *tc, SPObject *text, Inkscape::Text::Layout::iterator where) +{ + SP_EVENT_CONTEXT_DESKTOP (tc)->selection->set (text); + tc->text_sel_start = tc->text_sel_end = where; + sp_text_context_update_cursor(tc); + sp_text_context_update_text_selection(tc); +} + +void +sp_text_context_place_cursor_at (SPTextContext *tc, SPObject *text, Geom::Point const p) +{ + SP_EVENT_CONTEXT_DESKTOP (tc)->selection->set (text); + sp_text_context_place_cursor (tc, text, sp_te_get_position_by_coords(tc->text, p)); +} + +Inkscape::Text::Layout::iterator *sp_text_context_get_cursor_position(SPTextContext *tc, SPObject *text) +{ + if (text != tc->text) + return NULL; + return &(tc->text_sel_end); +} + /* Local Variables: