index 1bc3e68821b6927bb94cf80741e6aa8277eae80b..1f708e3de3534c1c84f8387ecc391d7da91c0f2b 100644 (file)
#include "sp-gradient.h"
#include "sp-gradient-vector.h"
#include "swatches.h"
+#include "style.h"
#include "widgets/gradient-vector.h"
#include "widgets/eek-preview.h"
+#include "display/nr-plain-stuff.h"
+#include "sp-gradient-reference.h"
+
+//#define USE_DOCUMENT_PALETTE 1
namespace Inkscape {
namespace UI {
namespace Dialogs {
+#define VBLOCK 16
+
+void _loadPaletteFile( gchar const *filename );
+
+/**
+ * The color swatch you see on screen as a clickable box.
+ */
+class ColorItem : public Inkscape::UI::Previewable
+{
+ friend void _loadPaletteFile( gchar const *filename );
+public:
+ ColorItem( ege::PaintDef::ColorType type );
+ ColorItem( unsigned int r, unsigned int g, unsigned int b,
+ Glib::ustring& name );
+ virtual ~ColorItem();
+ ColorItem(ColorItem const &other);
+ virtual ColorItem &operator=(ColorItem const &other);
+ virtual Gtk::Widget* getPreview(PreviewStyle style,
+ ViewType view,
+ ::PreviewSize size,
+ guint ratio);
+ void buttonClicked(bool secondary = false);
+
+ void setState( bool fill, bool stroke );
+ bool isFill() { return _isFill; }
+ bool isStroke() { return _isStroke; }
+
+ ege::PaintDef def;
+ void* ptr;
+
+private:
+ static void _dropDataIn( GtkWidget *widget,
+ GdkDragContext *drag_context,
+ gint x, gint y,
+ GtkSelectionData *data,
+ guint info,
+ guint event_time,
+ gpointer user_data);
+
+ static void _dragGetColorData( GtkWidget *widget,
+ GdkDragContext *drag_context,
+ GtkSelectionData *data,
+ guint info,
+ guint time,
+ gpointer user_data);
+
+ static void _wireMagicColors( void* p );
+ static void _colorDefChanged(void* data);
+
+ void _linkTint( ColorItem& other, int percent );
+ void _linkTone( ColorItem& other, int percent, int grayLevel );
+
+ Gtk::Tooltips tips;
+ std::vector<Gtk::Widget*> _previews;
+
+ bool _isFill;
+ bool _isStroke;
+ bool _isLive;
+ bool _linkIsTone;
+ int _linkPercent;
+ int _linkGray;
+ ColorItem* _linkSrc;
+ std::vector<ColorItem*> _listeners;
+};
+
+
ColorItem::ColorItem(ege::PaintDef::ColorType type) :
def(type),
ptr(0),
+ _isFill(false),
+ _isStroke(false),
_isLive(false),
_linkIsTone(false),
_linkPercent(0),
ColorItem::ColorItem( unsigned int r, unsigned int g, unsigned int b, Glib::ustring& name ) :
def( r, g, b, name ),
ptr(0),
+ _isFill(false),
+ _isStroke(false),
_isLive(false),
_linkIsTone(false),
_linkPercent(0),
return *this;
}
+void ColorItem::setState( bool fill, bool stroke )
+{
+ if ( (_isFill != fill) || (_isStroke != stroke) ) {
+ _isFill = fill;
+ _isStroke = stroke;
+
+ for ( std::vector<Gtk::Widget*>::iterator it = _previews.begin(); it != _previews.end(); ++it ) {
+ Gtk::Widget* widget = *it;
+ if ( IS_EEK_PREVIEW(widget->gobj()) ) {
+ EekPreview * preview = EEK_PREVIEW(widget->gobj());
+
+ int val = eek_preview_get_linked( preview );
+ val &= ~(PREVIEW_FILL | PREVIEW_STROKE);
+ if ( _isFill ) {
+ val |= PREVIEW_FILL;
+ }
+ if ( _isStroke ) {
+ val |= PREVIEW_STROKE;
+ }
+ eek_preview_set_linked( preview, static_cast<LinkType>(val) );
+ }
+ }
+ }
+}
+
class JustForNow
{
static std::vector<std::string> mimeStrings;
static std::map<std::string, guint> mimeToInt;
+static std::map<ColorItem*, guchar*> previewMap;
+static std::map<ColorItem*, SPGradient*> gradMap; // very temporary workaround.
+
void ColorItem::_dragGetColorData( GtkWidget */*widget*/,
GdkDragContext */*drag_context*/,
GtkSelectionData *data,
using Inkscape::IO::Resource::get_path;
using Inkscape::IO::Resource::ICONS;
using Inkscape::IO::Resource::SYSTEM;
+ int width = 32;
+ int height = 24;
if (item->def.getType() != ege::PaintDef::RGB){
GError *error = NULL;
@@ -158,18 +263,35 @@ static void dragBegin( GtkWidget */*widget*/, GdkDragContext* dc, gpointer data
&bytesRead,
&bytesWritten,
&error);
- GdkPixbuf* pixbuf = gdk_pixbuf_new_from_file_at_scale(localFilename, 32, 24, FALSE, &error);
+ GdkPixbuf* pixbuf = gdk_pixbuf_new_from_file_at_scale(localFilename, width, height, FALSE, &error);
g_free(localFilename);
gtk_drag_set_icon_pixbuf( dc, pixbuf, 0, 0 );
- return;
- }
+ } else {
+ GdkPixbuf* pixbuf = 0;
+ if ( gradMap.find(item) == gradMap.end() ){
+ Glib::RefPtr<Gdk::Pixbuf> thumb = Gdk::Pixbuf::create( Gdk::COLORSPACE_RGB, false, 8, width, height );
+ guint32 fillWith = (0xff000000 & (item->def.getR() << 24))
+ | (0x00ff0000 & (item->def.getG() << 16))
+ | (0x0000ff00 & (item->def.getB() << 8));
+ thumb->fill( fillWith );
+ pixbuf = thumb->gobj();
+ } else {
+ SPGradient* grad = gradMap[item];
+
+ guchar* px = g_new( guchar, 3 * height * width );
+ nr_render_checkerboard_rgb( px, width, height, 3 * width, 0, 0 );
- Glib::RefPtr<Gdk::Pixbuf> thumb = Gdk::Pixbuf::create( Gdk::COLORSPACE_RGB, false, 8, 32, 24 );
- guint32 fillWith = (0xff000000 & (item->def.getR() << 24))
- | (0x00ff0000 & (item->def.getG() << 16))
- | (0x0000ff00 & (item->def.getB() << 8));
- thumb->fill( fillWith );
- gtk_drag_set_icon_pixbuf( dc, thumb->gobj(), 0, 0 );
+ sp_gradient_render_vector_block_rgb( grad,
+ px, width, height, 3 * width,
+ 0, width, TRUE );
+
+ pixbuf = gdk_pixbuf_new_from_data( px, GDK_COLORSPACE_RGB, FALSE, 8,
+ width, height, width * 3,
+ 0, // add delete function
+ 0 );
+ }
+ gtk_drag_set_icon_pixbuf( dc, pixbuf, 0, 0 );
+ }
}
}
@@ -244,6 +366,7 @@ static void redirSecondaryClick( GtkMenuItem *menuitem, gpointer /*user_data*/ )
}
}
+#if USE_DOCUMENT_PALETTE
static void editGradientImpl( SPGradient* gr )
{
if ( gr ) {
}
}
}
+#endif // USE_DOCUMENT_PALETTE
static gboolean handleButtonPress( GtkWidget* /*widget*/, GdkEventButton* event, gpointer user_data)
{
@@ -331,6 +455,7 @@ static gboolean handleButtonPress( GtkWidget* /*widget*/, GdkEventButton* event,
user_data);
gtk_menu_shell_append(GTK_MENU_SHELL(popupMenu), child);
+#if USE_DOCUMENT_PALETTE
child = gtk_separator_menu_item_new();
gtk_menu_shell_append(GTK_MENU_SHELL(popupMenu), child);
popupExtras.push_back(child);
@@ -349,7 +474,6 @@ static gboolean handleButtonPress( GtkWidget* /*widget*/, GdkEventButton* event,
gtk_widget_set_sensitive( child, FALSE );
child = gtk_menu_item_new_with_label(_("Edit..."));
- gtk_menu_shell_append(GTK_MENU_SHELL(popupMenu), child);
g_signal_connect( G_OBJECT(child),
"activate",
G_CALLBACK(editGradient),
@@ -365,6 +489,7 @@ static gboolean handleButtonPress( GtkWidget* /*widget*/, GdkEventButton* event,
gtk_menu_shell_append(GTK_MENU_SHELL(popupMenu), child);
//popupExtras.push_back(child);
gtk_widget_set_sensitive( child, FALSE );
+#endif // USE_DOCUMENT_PALETTE
gtk_widget_show_all(popupMenu);
}
@@ -550,7 +675,20 @@ Gtk::Widget* ColorItem::getPreview(PreviewStyle style, ViewType view, ::PreviewS
EekPreview * preview = EEK_PREVIEW(eekWidget);
Gtk::Widget* newBlot = Glib::wrap(eekWidget);
- eek_preview_set_color( preview, (def.getR() << 8) | def.getR(), (def.getG() << 8) | def.getG(), (def.getB() << 8) | def.getB());
+ if ( previewMap.find(this) == previewMap.end() ){
+ eek_preview_set_color( preview, (def.getR() << 8) | def.getR(),
+ (def.getG() << 8) | def.getG(),
+ (def.getB() << 8) | def.getB());
+ } else {
+ guchar* px = previewMap[this];
+ int width = 128;
+ int height = 16;
+ GdkPixbuf* pixbuf = gdk_pixbuf_new_from_data( px, GDK_COLORSPACE_RGB, FALSE, 8,
+ width, height, width * 3,
+ 0, // add delete function
+ 0 );
+ eek_preview_set_pixbuf( preview, pixbuf );
+ }
if ( def.getType() != ege::PaintDef::RGB ) {
using Inkscape::IO::Resource::get_path;
using Inkscape::IO::Resource::ICONS;
break;
}
case ege::PaintDef::RGB: {
- gchar c[64];
- guint32 rgba = (def.getR() << 24) | (def.getG() << 16) | (def.getB() << 8) | 0xff;
- sp_svg_write_color(c, sizeof(c), rgba);
-
- sp_repr_css_set_property( css, attrName, c );
+ Glib::ustring colorspec;
+ if ( gradMap.find(this) == gradMap.end() ){
+ gchar c[64];
+ guint32 rgba = (def.getR() << 24) | (def.getG() << 16) | (def.getB() << 8) | 0xff;
+ sp_svg_write_color(c, sizeof(c), rgba);
+ colorspec = c;
+ } else {
+ SPGradient* grad = gradMap[this];
+ colorspec = "url(#";
+ colorspec += grad->id;
+ colorspec += ")";
+ }
+ sp_repr_css_set_property( css, attrName, colorspec.c_str() );
descr = secondary? _("Set stroke color from swatch") : _("Set fill color from swatch");
break;
}
_clear->ptr = this;
_remove = new ColorItem( ege::PaintDef::NONE );
_remove->ptr = this;
+#if USE_DOCUMENT_PALETTE
{
JustForNow *docPalette = new JustForNow();
_ptr = docPalette;
}
+#endif // USE_DOCUMENT_PALETTE
loadEmUp();
if ( !possible.empty() ) {
JustForNow* first = 0;
{
_documentConnection.disconnect();
_resourceConnection.disconnect();
+ _selChanged.disconnect();
+ _setModified.disconnect();
+ _subselChanged.disconnect();
if ( _clear ) {
delete _clear;
if ( desktop != _currentDesktop ) {
if ( _currentDesktop ) {
_documentConnection.disconnect();
+ _selChanged.disconnect();
+ _setModified.disconnect();
+ _subselChanged.disconnect();
}
_currentDesktop = desktop;
if ( desktop ) {
- sigc::bound_mem_functor1<void, Inkscape::UI::Dialogs::SwatchesPanel, SPDocument*> first = sigc::mem_fun(*this, &SwatchesPanel::_setDocument);
+ _currentDesktop->selection->connectChanged(
+ sigc::hide(sigc::mem_fun(*this, &SwatchesPanel::_updateFromSelection)));
- sigc::slot<void, SPDocument*> base2 = first;
+ _currentDesktop->selection->connectModified(
+ sigc::hide(sigc::hide(sigc::mem_fun(*this, &SwatchesPanel::_updateFromSelection))));
+
+ _currentDesktop->connectToolSubselectionChanged(
+ sigc::hide(sigc::mem_fun(*this, &SwatchesPanel::_updateFromSelection)));
+ sigc::bound_mem_functor1<void, Inkscape::UI::Dialogs::SwatchesPanel, SPDocument*> first = sigc::mem_fun(*this, &SwatchesPanel::_setDocument);
+ sigc::slot<void, SPDocument*> base2 = first;
sigc::slot<void,SPDesktop*, SPDocument*> slot2 = sigc::hide<0>( base2 );
_documentConnection = desktop->connectDocumentReplaced( slot2 );
}
}
+#if USE_DOCUMENT_PALETTE
if ( _ptr ) {
JustForNow *docPalette = reinterpret_cast<JustForNow *>(_ptr);
// TODO delete pointed to objects
sp_gradient_ensure_vector( grad );
SPGradientStop first = grad->vector.stops[0];
SPColor color = first.color;
- guint32 together = color.toRGBA32(0);
-
- Glib::ustring name( grad->id );
- unsigned int r = SP_RGBA32_R_U(together);
- unsigned int g = SP_RGBA32_G_U(together);
- unsigned int b = SP_RGBA32_B_U(together);
- ColorItem* item = new ColorItem( r, g, b, name );
- item->ptr = this;
- docPalette->_colors.push_back(item);
+ guint32 together = color.toRGBA32(first.opacity);
+
+ // At the moment we can't trust the count of 1 vs 2 stops.
+ SPGradientStop second = (*it)->vector.stops[1];
+ SPColor color2 = second.color;
+ guint32 together2 = color2.toRGBA32(second.opacity);
+
+ if ( (grad->vector.stops.size() <= 2) && (together == together2) ) {
+ // Treat as solid-color
+ Glib::ustring name( grad->id );
+ unsigned int r = SP_RGBA32_R_U(together);
+ unsigned int g = SP_RGBA32_G_U(together);
+ unsigned int b = SP_RGBA32_B_U(together);
+ ColorItem* item = new ColorItem( r, g, b, name );
+ item->ptr = this;
+ docPalette->_colors.push_back(item);
+ gradMap[item] = grad;
+ } else {
+ // Treat as gradient
+ Glib::ustring name( grad->id );
+ unsigned int r = SP_RGBA32_R_U(together);
+ unsigned int g = SP_RGBA32_G_U(together);
+ unsigned int b = SP_RGBA32_B_U(together);
+ ColorItem* item = new ColorItem( r, g, b, name );
+ item->ptr = this;
+ docPalette->_colors.push_back(item);
+
+ gint width = 128;
+ gint height = VBLOCK;
+ guchar* px = g_new( guchar, 3 * height * width );
+ nr_render_checkerboard_rgb( px, width, VBLOCK, 3 * width, 0, 0 );
+
+ sp_gradient_render_vector_block_rgb( grad,
+ px, width, height, 3 * width,
+ 0, width, TRUE );
+
+ previewMap[item] = px;
+ gradMap[item] = grad;
+ }
}
}
}
_rebuild();
}
}
+#endif // USE_DOCUMENT_PALETTE
+}
+
+void SwatchesPanel::_updateFromSelection()
+{
+#if USE_DOCUMENT_PALETTE
+ if ( _ptr ) {
+ JustForNow *docPalette = reinterpret_cast<JustForNow *>(_ptr);
+
+ Glib::ustring fillId;
+ Glib::ustring strokeId;
+
+ SPStyle *tmpStyle = sp_style_new( sp_desktop_document(_currentDesktop) );
+ int result = sp_desktop_query_style( _currentDesktop, tmpStyle, QUERY_STYLE_PROPERTY_FILL );
+ switch (result) {
+ case QUERY_STYLE_SINGLE:
+ case QUERY_STYLE_MULTIPLE_AVERAGED:
+ case QUERY_STYLE_MULTIPLE_SAME:
+ {
+ if (tmpStyle->fill.set && tmpStyle->fill.isPaintserver()) {
+ SPPaintServer* server = tmpStyle->getFillPaintServer();
+ if ( SP_IS_GRADIENT(server) ) {
+ SPGradient* target = 0;
+ SPGradient* grad = SP_GRADIENT(server);
+ if (grad->repr->attribute("osb:paint")) {
+ target = grad;
+ } else if ( grad->ref ) {
+ SPGradient *tmp = grad->ref->getObject();
+ if ( tmp && tmp->repr->attribute("osb:paint") ) {
+ target = tmp;
+ }
+ }
+ if ( target ) {
+ gchar const* id = target->repr->attribute("id");
+ if ( id ) {
+ fillId = id;
+ }
+ }
+ }
+ }
+ break;
+ }
+ }
+
+ result = sp_desktop_query_style( _currentDesktop, tmpStyle, QUERY_STYLE_PROPERTY_STROKE );
+ switch (result) {
+ case QUERY_STYLE_SINGLE:
+ case QUERY_STYLE_MULTIPLE_AVERAGED:
+ case QUERY_STYLE_MULTIPLE_SAME:
+ {
+ if (tmpStyle->stroke.set && tmpStyle->stroke.isPaintserver()) {
+ SPPaintServer* server = tmpStyle->getStrokePaintServer();
+ if ( SP_IS_GRADIENT(server) ) {
+ SPGradient* target = 0;
+ SPGradient* grad = SP_GRADIENT(server);
+ if (grad->repr->attribute("osb:paint")) {
+ target = grad;
+ } else if ( grad->ref ) {
+ SPGradient *tmp = grad->ref->getObject();
+ if ( tmp && tmp->repr->attribute("osb:paint") ) {
+ target = tmp;
+ }
+ }
+ if ( target ) {
+ gchar const* id = target->repr->attribute("id");
+ if ( id ) {
+ strokeId = id;
+ }
+ }
+ }
+ }
+ break;
+ }
+ }
+ sp_style_unref(tmpStyle);
+
+ for ( std::vector<ColorItem*>::iterator it = docPalette->_colors.begin(); it != docPalette->_colors.end(); ++it ) {
+ ColorItem* item = *it;
+ bool isFill = (fillId == item->def.descr);
+ bool isStroke = (strokeId == item->def.descr);
+ item->setState( isFill, isStroke );
+ }
+ }
+#endif // USE_DOCUMENT_PALETTE
}
void SwatchesPanel::_handleAction( int setId, int itemId )