From: joncruz Date: Sun, 8 Mar 2009 09:30:53 +0000 (+0000) Subject: Reworked internals of color and drag-n-drop. X-Git-Url: https://git.tokkee.org/?a=commitdiff_plain;h=7c65abbcc285edbc00c4c77408a9668e69b97b28;p=inkscape.git Reworked internals of color and drag-n-drop. --- diff --git a/src/gradient-drag.cpp b/src/gradient-drag.cpp index 6d8815938..4758d27bf 100644 --- a/src/gradient-drag.cpp +++ b/src/gradient-drag.cpp @@ -358,7 +358,7 @@ GrDrag::addStopNearPoint (SPItem *item, Geom::Point mouse_p, double tolerance) bool -GrDrag::dropColor(SPItem */*item*/, gchar *c, Geom::Point p) +GrDrag::dropColor(SPItem */*item*/, gchar const *c, Geom::Point p) { // first, see if we can drop onto one of the existing draggers for (GList *i = draggers; i != NULL; i = i->next) { // for all draggables of dragger diff --git a/src/gradient-drag.h b/src/gradient-drag.h index 974bba4de..a53acffe6 100644 --- a/src/gradient-drag.h +++ b/src/gradient-drag.h @@ -124,7 +124,7 @@ public: // FIXME: make more of this private! void selectByCoords(std::vector coords); void selectRect(Geom::Rect const &r); - bool dropColor(SPItem *item, gchar *c, Geom::Point p); + bool dropColor(SPItem *item, gchar const *c, Geom::Point p); SPStop *addStopNearPoint (SPItem *item, Geom::Point mouse_p, double tolerance); diff --git a/src/interface.cpp b/src/interface.cpp index e542a1944..8379cd0e2 100644 --- a/src/interface.cpp +++ b/src/interface.cpp @@ -61,6 +61,7 @@ #include "style.h" #include "event-context.h" #include "gradient-drag.h" +#include "widgets/eek-color-def.h" // Include Mac OS X menu synchronization on native OSX build #ifdef GDK_WINDOWING_QUARTZ @@ -77,8 +78,7 @@ typedef enum { IMAGE_DATA, APP_X_INKY_COLOR, APP_X_COLOR, - APP_X_NOCOLOR, - APP_X_XCOLOR + APP_OSWB_COLOR, } ui_drop_target_info; static GtkTargetEntry ui_drop_target_entries [] = { @@ -90,7 +90,7 @@ static GtkTargetEntry ui_drop_target_entries [] = { #if ENABLE_MAGIC_COLORS {(gchar *)"application/x-inkscape-color", 0, APP_X_INKY_COLOR}, #endif // ENABLE_MAGIC_COLORS - {(gchar *)"application/x-oswb-nocolor", 0, APP_X_NOCOLOR }, + {(gchar *)"application/x-oswb-color", 0, APP_OSWB_COLOR }, {(gchar *)"application/x-color", 0, APP_X_COLOR } }; @@ -1165,10 +1165,10 @@ sp_ui_drag_data_received(GtkWidget *widget, Geom::Point const button_doc(desktop->dt2doc(button_dt)); if ( data->length == 8 ) { - gchar c[64] = {0}; + gchar colorspec[64] = {0}; // Careful about endian issues. guint16* dataVals = (guint16*)data->data; - sp_svg_write_color( c, 64, + sp_svg_write_color( colorspec, sizeof(colorspec), SP_RGBA32_U_COMPOSE( 0x0ff & (dataVals[0] >> 8), 0x0ff & (dataVals[1] >> 8), @@ -1181,7 +1181,7 @@ sp_ui_drag_data_received(GtkWidget *widget, bool consumed = false; if (desktop->event_context && desktop->event_context->get_drag()) { - consumed = desktop->event_context->get_drag()->dropColor(item, c, button_dt); + consumed = desktop->event_context->get_drag()->dropColor(item, colorspec, button_dt); if (consumed) { sp_document_done( doc , SP_VERB_NONE, _("Drop color on gradient")); desktop->event_context->get_drag()->updateDraggers(); @@ -1224,7 +1224,7 @@ sp_ui_drag_data_received(GtkWidget *widget, } SPCSSAttr *css = sp_repr_css_attr_new(); - sp_repr_css_set_property( css, fillnotstroke ? "fill":"stroke", c ); + sp_repr_css_set_property( css, fillnotstroke ? "fill":"stroke", colorspec ); sp_desktop_apply_css_recursive( item, css, true ); item->updateRepr(); @@ -1236,66 +1236,85 @@ sp_ui_drag_data_received(GtkWidget *widget, } break; - case APP_X_NOCOLOR: - case APP_X_XCOLOR: + case APP_OSWB_COLOR: { - gchar* c = g_strdup("none"); // temp - int destX = 0; - int destY = 0; - gtk_widget_translate_coordinates( widget, &(desktop->canvas->widget), x, y, &destX, &destY ); - Geom::Point where( sp_canvas_window_to_world( desktop->canvas, Geom::Point( destX, destY ) ) ); - Geom::Point const button_dt(desktop->w2d(where)); - Geom::Point const button_doc(desktop->dt2doc(button_dt)); + bool worked = false; + Glib::ustring colorspec; + if ( data->format == 8 ) { + eek::ColorDef color; + worked = color.fromMIMEData("application/x-oswb-color", + reinterpret_cast(data->data), + data->length, + data->format); + if ( worked ) { + if ( color.getType() == eek::ColorDef::CLEAR ) { + colorspec = ""; // TODO check if this is sufficient + } else if ( color.getType() == eek::ColorDef::NONE ) { + colorspec = "none"; + } else { + gchar* tmp = g_strdup_printf("#%02x%02x%02x", color.getR(), color.getG(), color.getB()); + colorspec = tmp; + g_free(tmp); + } + } + } + if ( worked ) { + int destX = 0; + int destY = 0; + gtk_widget_translate_coordinates( widget, &(desktop->canvas->widget), x, y, &destX, &destY ); + Geom::Point where( sp_canvas_window_to_world( desktop->canvas, Geom::Point( destX, destY ) ) ); + Geom::Point const button_dt(desktop->w2d(where)); + Geom::Point const button_doc(desktop->dt2doc(button_dt)); - SPItem *item = desktop->item_at_point( where, true ); + SPItem *item = desktop->item_at_point( where, true ); - bool consumed = false; - if (desktop->event_context && desktop->event_context->get_drag()) { - consumed = desktop->event_context->get_drag()->dropColor(item, c, button_dt); - if (consumed) { - sp_document_done( doc , SP_VERB_NONE, _("Drop color on gradient")); - desktop->event_context->get_drag()->updateDraggers(); + bool consumed = false; + if (desktop->event_context && desktop->event_context->get_drag()) { + consumed = desktop->event_context->get_drag()->dropColor(item, colorspec.c_str(), button_dt); + if (consumed) { + sp_document_done( doc , SP_VERB_NONE, _("Drop color on gradient")); + desktop->event_context->get_drag()->updateDraggers(); + } } - } - if (!consumed && item) { - bool fillnotstroke = (drag_context->action != GDK_ACTION_MOVE); - if (fillnotstroke && - (SP_IS_SHAPE(item) || SP_IS_TEXT(item) || SP_IS_FLOWTEXT(item))) { - Path *livarot_path = Path_for_item(item, true, true); - livarot_path->ConvertWithBackData(0.04); - - boost::optional position = get_nearest_position_on_Path(livarot_path, button_doc); - if (position) { - Geom::Point nearest = get_point_on_Path(livarot_path, position->piece, position->t); - Geom::Point delta = nearest - button_doc; - Inkscape::Preferences *prefs = Inkscape::Preferences::get(); - delta = desktop->d2w(delta); - double stroke_tolerance = - ( !SP_OBJECT_STYLE(item)->stroke.isNone() ? - desktop->current_zoom() * - SP_OBJECT_STYLE (item)->stroke_width.computed * - to_2geom(sp_item_i2d_affine(item)).descrim() * 0.5 - : 0.0) - + prefs->getIntLimited("/options/dragtolerance/value", 0, 0, 100); - - if (Geom::L2 (delta) < stroke_tolerance) { - fillnotstroke = false; + if (!consumed && item) { + bool fillnotstroke = (drag_context->action != GDK_ACTION_MOVE); + if (fillnotstroke && + (SP_IS_SHAPE(item) || SP_IS_TEXT(item) || SP_IS_FLOWTEXT(item))) { + Path *livarot_path = Path_for_item(item, true, true); + livarot_path->ConvertWithBackData(0.04); + + boost::optional position = get_nearest_position_on_Path(livarot_path, button_doc); + if (position) { + Geom::Point nearest = get_point_on_Path(livarot_path, position->piece, position->t); + Geom::Point delta = nearest - button_doc; + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + delta = desktop->d2w(delta); + double stroke_tolerance = + ( !SP_OBJECT_STYLE(item)->stroke.isNone() ? + desktop->current_zoom() * + SP_OBJECT_STYLE (item)->stroke_width.computed * + to_2geom(sp_item_i2d_affine(item)).descrim() * 0.5 + : 0.0) + + prefs->getIntLimited("/options/dragtolerance/value", 0, 0, 100); + + if (Geom::L2 (delta) < stroke_tolerance) { + fillnotstroke = false; + } } + delete livarot_path; } - delete livarot_path; - } - SPCSSAttr *css = sp_repr_css_attr_new(); - sp_repr_css_set_property( css, fillnotstroke ? "fill":"stroke", c ); + SPCSSAttr *css = sp_repr_css_attr_new(); + sp_repr_css_set_property( css, fillnotstroke ? "fill":"stroke", colorspec.c_str() ); - sp_desktop_apply_css_recursive( item, css, true ); - item->updateRepr(); + sp_desktop_apply_css_recursive( item, css, true ); + item->updateRepr(); - sp_document_done( doc , SP_VERB_NONE, - _("Drop color")); + sp_document_done( doc , SP_VERB_NONE, + _("Drop color")); + } } - g_free(c); } break; diff --git a/src/ui/dialog/swatches.cpp b/src/ui/dialog/swatches.cpp index ecd54be39..f1d6c6816 100644 --- a/src/ui/dialog/swatches.cpp +++ b/src/ui/dialog/swatches.cpp @@ -100,24 +100,8 @@ public: static std::vector possible; - -typedef enum { - APP_X_INKY_COLOR_ID = 0, - APP_X_INKY_COLOR = 0, - APP_X_COLOR, - APP_X_NOCOLOR, - APP_X_XCOLOR, - TEXT_DATA -} colorFlavorType; - -std::map mimeToInt; -std::map intToMime; - -#if ENABLE_MAGIC_COLORS -// {"application/x-inkscape-color-id", GTK_TARGET_SAME_APP, APP_X_INKY_COLOR_ID}, -// {"application/x-inkscape-color", 0, APP_X_INKY_COLOR}, -#endif // ENABLE_MAGIC_COLORS - +static std::vector mimeStrings; +static std::map mimeToInt; void ColorItem::_dragGetColorData( GtkWidget */*widget*/, GdkDragContext */*drag_context*/, @@ -128,12 +112,10 @@ void ColorItem::_dragGetColorData( GtkWidget */*widget*/, { ColorItem* item = reinterpret_cast(user_data); std::string key; - if ( info == TEXT_DATA ) { - key = "text/plain"; - } else if ( (info == APP_X_NOCOLOR) || (info == APP_X_XCOLOR) ) { - key = "application/x-oswb-nocolor"; + if ( info < mimeStrings.size() ) { + key = mimeStrings[info]; } else { - key = "application/x-color"; + g_warning("ERROR: unknown value (%d)", info); } if ( !key.empty() ) { @@ -297,20 +279,6 @@ static void dieDieDie( GtkObject *obj, gpointer user_data ) g_message("die die die %p %p", obj, user_data ); } -//TODO: warning: deprecated conversion from string constant to ‘gchar*’ -// -//Turn out to be warnings that we should probably leave in place. The -// pointers/types used need to be read-only. So until we correct the using -// code, those warnings are actually desired. They say "Hey! Fix this". We -// definitely don't want to hide/ignore them. --JonCruz -static const GtkTargetEntry destColorTargets[] = { -#if ENABLE_MAGIC_COLORS -// {"application/x-inkscape-color-id", GTK_TARGET_SAME_APP, APP_X_INKY_COLOR_ID}, - {"application/x-inkscape-color", 0, APP_X_INKY_COLOR}, -#endif // ENABLE_MAGIC_COLORS - {"application/x-color", 0, APP_X_COLOR}, -}; - #include "color.h" // for SP_RGBA32_U_COMPOSE void ColorItem::_dropDataIn( GtkWidget */*widget*/, @@ -321,58 +289,6 @@ void ColorItem::_dropDataIn( GtkWidget */*widget*/, guint /*event_time*/, gpointer user_data) { -// g_message(" droppy droppy %d", info); - switch (info) { - case APP_X_INKY_COLOR: - { - if ( data->length >= 8 ) { - // Careful about endian issues. - guint16* dataVals = (guint16*)data->data; - if ( user_data ) { - ColorItem* item = reinterpret_cast(user_data); - if ( item->def.isEditable() ) { - // Shove on in the new value - item->def.setRGB( 0x0ff & (dataVals[0] >> 8), 0x0ff & (dataVals[1] >> 8), 0x0ff & (dataVals[2] >> 8) ); - } - } - } - break; - } - case APP_X_NOCOLOR: - case APP_X_XCOLOR: - { -// g_message("APP_X_NOCOLOR dropping through to x-color"); - } - case APP_X_COLOR: - { - if ( data->length == 8 ) { - // Careful about endian issues. - guint16* dataVals = (guint16*)data->data; -// { -// gchar c[64] = {0}; -// sp_svg_write_color( c, 64, -// SP_RGBA32_U_COMPOSE( -// 0x0ff & (dataVals[0] >> 8), -// 0x0ff & (dataVals[1] >> 8), -// 0x0ff & (dataVals[2] >> 8), -// 0xff // can't have transparency in the color itself -// //0x0ff & (data->data[3] >> 8), -// )); -// } - if ( user_data ) { - ColorItem* item = reinterpret_cast(user_data); - if ( item->def.isEditable() ) { - // Shove on in the new value - item->def.setRGB( 0x0ff & (dataVals[0] >> 8), 0x0ff & (dataVals[1] >> 8), 0x0ff & (dataVals[2] >> 8) ); - } - } - } - break; - } - default: - g_message("unknown drop type"); - } - } static bool bruteForce( SPDocument* document, Inkscape::XML::Node* node, Glib::ustring const& match, int r, int g, int b ) @@ -505,17 +421,6 @@ void ColorItem::_colorDefChanged(void* data) Gtk::Widget* ColorItem::getPreview(PreviewStyle style, ViewType view, ::PreviewSize size, guint ratio) { - if (mimeToInt.empty()) { - mimeToInt["application/x-inkscape-nocolor"] = APP_X_NOCOLOR; - intToMime[APP_X_NOCOLOR] = "application/x-inkscape-nocolor"; - - mimeToInt["application/x-color"] = APP_X_COLOR; - intToMime[APP_X_COLOR] = "application/x-color"; - - mimeToInt["text/plain"] = TEXT_DATA; - intToMime[TEXT_DATA] = "text/plain"; - } - Gtk::Widget* widget = 0; if ( style == PREVIEW_STYLE_BLURB) { Gtk::Label *lbl = new Gtk::Label(def.descr); @@ -607,6 +512,11 @@ Gtk::Widget* ColorItem::getPreview(PreviewStyle style, ViewType view, ::PreviewS for ( std::vector::iterator it = listing.begin(); it != listing.end(); ++it ) { curr->target = g_strdup(it->c_str()); curr->flags = 0; + if ( mimeToInt.find(*it) == mimeToInt.end() ){ + // these next lines are order-dependent: + mimeToInt[*it] = mimeStrings.size(); + mimeStrings.push_back(*it); + } curr->info = mimeToInt[curr->target]; curr++; } @@ -647,17 +557,17 @@ Gtk::Widget* ColorItem::getPreview(PreviewStyle style, ViewType view, ::PreviewS if ( def.isEditable() ) { - gtk_drag_dest_set( GTK_WIDGET(newBlot->gobj()), - GTK_DEST_DEFAULT_ALL, - destColorTargets, - G_N_ELEMENTS(destColorTargets), - GdkDragAction(GDK_ACTION_COPY | GDK_ACTION_MOVE) ); +// gtk_drag_dest_set( GTK_WIDGET(newBlot->gobj()), +// GTK_DEST_DEFAULT_ALL, +// destColorTargets, +// G_N_ELEMENTS(destColorTargets), +// GdkDragAction(GDK_ACTION_COPY | GDK_ACTION_MOVE) ); - g_signal_connect( G_OBJECT(newBlot->gobj()), - "drag-data-received", - G_CALLBACK(_dropDataIn), - this ); +// g_signal_connect( G_OBJECT(newBlot->gobj()), +// "drag-data-received", +// G_CALLBACK(_dropDataIn), +// this ); } g_signal_connect( G_OBJECT(newBlot->gobj()), diff --git a/src/widgets/eek-color-def.cpp b/src/widgets/eek-color-def.cpp index 8c8d240c6..fb0eeeb5e 100644 --- a/src/widgets/eek-color-def.cpp +++ b/src/widgets/eek-color-def.cpp @@ -44,6 +44,11 @@ #endif #include +#include +#include +#include +#include +#include #if !defined(_) #define _(s) gettext(s) @@ -54,6 +59,12 @@ namespace eek { +static std::string mimeTEXT("text/plain"); +static std::string mimeX_COLOR("application/x-color"); +static std::string mimeOSWB_COLOR("application/x-oswb-color"); + +static std::string doubleToStr(double d); + ColorDef::ColorDef() : descr(_("none")), type(NONE), @@ -131,23 +142,21 @@ public: std::vector ColorDef::getMIMETypes() { std::vector listing; - if ( getType() != eek::ColorDef::RGB ) { - listing.push_back("application/x-oswb-nocolor"); - } - listing.push_back("application/x-color"); - listing.push_back("text/plain"); + listing.push_back(mimeOSWB_COLOR); + listing.push_back(mimeX_COLOR); + listing.push_back(mimeTEXT); return listing; } void ColorDef::getMIMEData(std::string const & type, char*& dest, int& len, int& format) { - if ( type == "text/plain" ) { + if ( type == mimeTEXT ) { dest = new char[8]; snprintf( dest, 8, "#%02x%02x%02x", getR(), getG(), getB() ); dest[7] = 0; len = 8; format = 8; - } else if ( (type == "application/x-color") || (type == "application/x-oswb-nocolor") ) { + } else if ( type == mimeX_COLOR ) { uint16_t* tmp = new uint16_t[4]; tmp[0] = (getR() << 8) | getR(); tmp[1] = (getG() << 8) | getG(); @@ -156,6 +165,38 @@ void ColorDef::getMIMEData(std::string const & type, char*& dest, int& len, int& dest = reinterpret_cast(tmp); len = 8; format = 16; + } else if ( type == mimeOSWB_COLOR ) { + std::string tmp(""); + switch ( getType() ) { + case eek::ColorDef::NONE: + { + tmp += ""; + } + break; + case eek::ColorDef::CLEAR: + { + tmp += ""; + } + break; + default: + { + tmp += std::string(""; + tmp += ""; + tmp += ""; + } + } + tmp += ""; + len = tmp.size(); + dest = new char[len]; + // Note that this is not null-terminated: + memcpy(dest, tmp.c_str(), len); + format = 8; } else { // nothing dest = 0; @@ -163,6 +204,68 @@ void ColorDef::getMIMEData(std::string const & type, char*& dest, int& len, int& } } +bool ColorDef::fromMIMEData(std::string const & type, char const * data, int len, int /*format*/) +{ + bool worked = false; + bool changed = false; + if ( type == mimeTEXT ) { + } else if ( type == mimeX_COLOR ) { + } else if ( type == mimeOSWB_COLOR ) { + std::string xml(data, len); + if ( xml.find("") != std::string::npos ) { + if ( (this->type != eek::ColorDef::NONE) + || (this->r != 0) + || (this->g != 0) + || (this->b != 0) ) { + this->type = eek::ColorDef::NONE; + this->r = 0; + this->g = 0; + this->b = 0; + changed = true; + } + worked = true; + } else { + size_t pos = xml.find("", pos); + std::string srgb = xml.substr(pos, endPos); + this->type = eek::ColorDef::RGB; + size_t numPos = srgb.find("r="); + if (numPos != std::string::npos) { + char* endPtr = 0; + double dbl = strtod(srgb.c_str() + numPos + 3, &endPtr); + this->r = static_cast(255 * dbl); + } + numPos = srgb.find("g="); + if (numPos != std::string::npos) { + char* endPtr = 0; + double dbl = strtod(srgb.c_str() + numPos + 3, &endPtr); + this->g = static_cast(255 * dbl); + } + numPos = srgb.find("b="); + if (numPos != std::string::npos) { + char* endPtr = 0; + double dbl = strtod(srgb.c_str() + numPos + 3, &endPtr); + this->b = static_cast(255 * dbl); + } + changed = true; + worked = true; + } + } + } + if ( changed ) { + // beware of callbacks changing things + for ( std::vector::iterator it = _listeners.begin(); it != _listeners.end(); ++it ) + { + if ( (*it)->_cb ) + { + (*it)->_cb( (*it)->_data ); + } + } + } + return worked; +} + void ColorDef::setRGB( unsigned int r, unsigned int g, unsigned int b ) { if ( r != this->r || g != this->g || b != this->b ) { @@ -186,10 +289,16 @@ void ColorDef::addCallback( ColorCallback cb, void* data ) _listeners.push_back( new HookData(cb, data) ); } -void ColorDef::removeCallback( ColorCallback cb, void* data ) +void ColorDef::removeCallback( ColorCallback /*cb*/, void* /*data*/ ) +{ +} + +static std::string doubleToStr(double d) { - (void)cb; - (void)data; + // TODO ensure "." is used for decimal separator. + std::stringstream out; + out << d; + return out.str(); } } // namespace eek diff --git a/src/widgets/eek-color-def.h b/src/widgets/eek-color-def.h index 39d69d5d1..2f6117d54 100644 --- a/src/widgets/eek-color-def.h +++ b/src/widgets/eek-color-def.h @@ -66,6 +66,7 @@ public: std::vector getMIMETypes(); void getMIMEData(std::string const & type, char*& dest, int& len, int& format); + bool fromMIMEData(std::string const & type, char const * data, int len, int format); void setRGB( unsigned int r, unsigned int g, unsigned int b ); unsigned int getR() const { return r; }